Merge branch 'develop' into DeprecatedGradleFeatures
This commit is contained in:
31
CHANGELOG.md
31
CHANGELOG.md
@@ -1,3 +1,34 @@
|
||||
8.0.0 (08/30/2022)
|
||||
------------------
|
||||
|
||||
* Updated HashLink to version 1.12
|
||||
* Updated Android minimum SDK version to 21
|
||||
* Updated Electron template to version 18
|
||||
* Updated HTML5 to high DPI by default
|
||||
* Added `--template` command line option to Lime tools
|
||||
* Added `--appstore` and `--adhoc` command line options for AIR on iOS to Lime tools (to match iOS native)
|
||||
* Added `-air-simulator` command line option for AIR to Lime tools (avoids packaging full AIR app)
|
||||
* Added `<config:air profile="value"/>` to optionally support custom AIR profiles in simulator
|
||||
* Added `setTextInputRect` to `Window` to specify a rectangle that has focus for text input
|
||||
* Added `JNISafety` to improve JNI communication on Android
|
||||
* Added `manageCookies` to `HTTPRequest` to support cookies on native platforms (only session for now)
|
||||
* Added `pitch` property to `AudioSource`
|
||||
* Added `-Delectron` flag to Electron builds so that it's possible to use `#if electron`
|
||||
* Added icon priorities to allow a library to provide a default icon that the user can override
|
||||
* Improved HashLink _.app_ file generation on macOS
|
||||
* Improved performance of `HTTPRequest` on native platforms with better buffer management
|
||||
* Improved support for Android 12 (SDK 31) and newer
|
||||
* Improved output file size if no assets are defined (sets `disable_preloader_assets` define)
|
||||
* Improved stage sizing on Electron (defaults to `0` for fluid width/height, same as regular browsers)
|
||||
* Fixed garbage collector crash issue on iOS 12
|
||||
* Fixed iOS build that failed because of missing _Metal.framework_ dependency
|
||||
* Fixed switching between light and dark modes on Android destroying the Lime activity
|
||||
* Fixed `getCurrentTime` on `AudioSource` for streaming sounds on native platforms
|
||||
* Fixed wrong types on `NativeMenuItem` Flash externs
|
||||
* Fixed set clipboard when `null` is passed (now changes to an empty string automatically)
|
||||
* Fixed warnings for deprecated "devicemotion" events on Firefox
|
||||
* Fixed incompatibility with "genes" Haxelib to allow generating JS Modules
|
||||
|
||||
7.9.0 (03/10/2021)
|
||||
------------------
|
||||
|
||||
|
||||
@@ -43,11 +43,11 @@ First install the latest version of [Haxe](http://www.haxe.org/download).
|
||||
Development Builds
|
||||
==================
|
||||
|
||||
When there are changes, Lime is built nightly. Builds are available for download [here](https://github.com/openfl/lime/actions?query=branch%3Adevelop).
|
||||
When there are changes, Lime is built nightly. Builds are available for download [here](https://github.com/openfl/lime/actions?query=branch%3Adevelop+is%3Asuccess).
|
||||
|
||||
To install a development build, use the "haxelib local" command:
|
||||
|
||||
haxelib local filename.zip
|
||||
haxelib local lime-haxelib.zip
|
||||
|
||||
|
||||
Building from Source
|
||||
|
||||
6
assets/docs-theme/resources/extra-styles.css
Normal file
6
assets/docs-theme/resources/extra-styles.css
Normal file
@@ -0,0 +1,6 @@
|
||||
body .navbar .brand:first-of-type {
|
||||
background: url(./images/logo.png) center left no-repeat;
|
||||
background-size: 32px 32px;
|
||||
padding-left: 40px;
|
||||
margin: 0.5em 0;
|
||||
}
|
||||
@@ -6,6 +6,22 @@ function readCookie(name) {
|
||||
return localStorage.getItem(name);
|
||||
}
|
||||
|
||||
function isDarkTheme() {
|
||||
return document.querySelector("html").classList.contains("dark-theme");
|
||||
}
|
||||
|
||||
function toggleTheme() {
|
||||
const htmlTag = document.querySelector("html");
|
||||
let isDark = isDarkTheme();
|
||||
if (isDark) {
|
||||
htmlTag.classList.remove("dark-theme");
|
||||
} else {
|
||||
htmlTag.classList.add("dark-theme");
|
||||
}
|
||||
isDark = isDarkTheme();
|
||||
localStorage.theme = isDark ? "dark" : "light";
|
||||
}
|
||||
|
||||
function toggleInherited(el) {
|
||||
var toggle = $(el).closest(".toggle");
|
||||
toggle.toggleClass("toggle-on");
|
||||
@@ -131,7 +147,7 @@ $(document).ready(function(){
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
|
||||
$("#select-platform").selectpicker().on("change", function(e){
|
||||
var value = $(":selected", this).val();
|
||||
setPlatform(value);
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
<style>
|
||||
::raw "
|
||||
a, code .type {
|
||||
a,
|
||||
code a,
|
||||
code .type,
|
||||
.dark-theme a,
|
||||
.dark-theme code a,
|
||||
.dark-theme code .type {
|
||||
color: #6fac17;
|
||||
}
|
||||
.navbar .brand {
|
||||
@@ -11,7 +16,12 @@ a, code .type {
|
||||
.navbar .brand img {
|
||||
max-width: 75px;
|
||||
}
|
||||
.nav-list>.active>a.treeLink, .nav-list>.active>a.treeLink:hover, .nav-list>.active>a.treeLink:focus {
|
||||
.nav-list>.active>a.treeLink,
|
||||
.nav-list>.active>a.treeLink:hover,
|
||||
.nav-list>.active>a.treeLink:focus,
|
||||
.dark-theme .nav-list>.active>a.treeLink,
|
||||
.dark-theme .nav-list>.active>a.treeLink:hover,
|
||||
.dark-theme .nav-list>.active>a.treeLink:focus {
|
||||
background: #6fac17;
|
||||
color: #ffffff;
|
||||
text-shadow: 0 0 0 transparent;
|
||||
@@ -45,6 +55,7 @@ a, code .type {
|
||||
<div class="container">
|
||||
<a ::cond api.isDefined("logo"):: ::attr href if(api.isDefined("website")) api.getValue("website") else api.config.rootPath:: class="brand"><img alt="" ::attr src api.getValue("logo"):: /></a>
|
||||
<a ::attr href api.config.rootPath:: class="brand" style="color:$$getHexValue(::textColor::)">::if api.config.pageTitle!=null::::api.config.pageTitle::::else::Lime API Documentation::end::</a>
|
||||
<a href="#" id="theme-toggle" style="color:$$getHexValue(::textColor::)" onclick="toggleTheme()" title="Toggle Dark Mode"><i class="fa fa-moon-o"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -11,13 +11,54 @@ import java.lang.Float;
|
||||
import java.lang.Double;
|
||||
|
||||
/**
|
||||
An object that was originally created by Haxe code. You can call its
|
||||
functions using `callX("functionName")`, where X is the number of arguments.
|
||||
A placeholder for an object created in Haxe. You can call the object's
|
||||
functions using `callN("functionName")`, where N is the number of arguments.
|
||||
|
||||
Caution: the Haxe function will run on the thread you called it from. In many
|
||||
cases, this will be the UI thread, which is _not_ the same as Haxe's main
|
||||
thread. To avoid unpredictable thread-related errors, consider using a
|
||||
`lime.system.ForegroundWorker` as your `HaxeObject`.
|
||||
Caution: the Haxe function will run on whichever thread you call it from.
|
||||
Java code typically runs on the UI thread, not Haxe's main thread, which can
|
||||
easily cause thread-related errors. This cannot be easily remedied using Java
|
||||
code, but is fixable in Haxe using `lime.system.JNI.JNISafety`.
|
||||
|
||||
Sample usage:
|
||||
|
||||
```haxe
|
||||
// MyHaxeObject.hx
|
||||
import lime.system.JNI;
|
||||
|
||||
class MyHaxeObject implements JNISafety
|
||||
{
|
||||
@:runOnMainThread
|
||||
public function onActivityResult(requestCode:Int, resultCode:Int):Void
|
||||
{
|
||||
// Insert code to process the result. This code will safely run on the
|
||||
// main Haxe thread.
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```java
|
||||
// MyJavaTool.java
|
||||
import android.content.Intent;
|
||||
import org.haxe.extension.Extension;
|
||||
import org.haxe.lime.HaxeObject;
|
||||
|
||||
public class MyJavaTool extends Extension
|
||||
{
|
||||
private static var haxeObject:HaxeObject;
|
||||
|
||||
public static function registerHaxeObject(object:HaxeObject)
|
||||
{
|
||||
haxeObject = object;
|
||||
}
|
||||
|
||||
// onActivityResult() always runs on the Android UI thread.
|
||||
@Override public boolean onActivityResult(int requestCode, int resultCode, Intent data)
|
||||
{
|
||||
haxeObject.call2(requestCode, resultCode);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
```
|
||||
**/
|
||||
public class HaxeObject
|
||||
{
|
||||
|
||||
@@ -70,10 +70,7 @@ class Build extends Script
|
||||
"https://github.com/openfl/lime/tree/develop/src/",
|
||||
"-D",
|
||||
"website",
|
||||
"http://lime.software",
|
||||
"-D",
|
||||
"logo",
|
||||
"/images/logo.png",
|
||||
"https://lime.openfl.org",
|
||||
"-D",
|
||||
"textColor",
|
||||
"0x777777",
|
||||
|
||||
@@ -13,4 +13,4 @@ hxml/android.hxml
|
||||
hxml/html5.hxml
|
||||
--next
|
||||
|
||||
-cmd haxelib run dox -i xml -in lime --title "Lime API Reference" -D website "http://lime.software" -D source-path "https://github.com/openfl/lime/tree/develop/src/" -D logo "/images/logo.png" -D textColor 0x777777 -theme ../assets/docs-theme --toplevel-package lime
|
||||
-cmd haxelib run dox -i xml -in lime --title "Lime API Reference" -D website "https://lime.openfl.org" -D source-path "https://github.com/openfl/lime/tree/develop/src/" -D textColor 0x777777 -theme ../assets/docs-theme --toplevel-package lime
|
||||
@@ -6,8 +6,8 @@ package flash.display;
|
||||
var data:Dynamic;
|
||||
var enabled:Bool;
|
||||
var isSeparator(default, never):Bool;
|
||||
var keyEquivalent:flash.ui.Keyboard;
|
||||
var keyEquivalentModifiers:Array<flash.ui.Keyboard>;
|
||||
var keyEquivalent:String;
|
||||
var keyEquivalentModifiers:Array<UInt>;
|
||||
var label:String;
|
||||
var menu(default, never):NativeMenu;
|
||||
var mnemonicIndex:Int;
|
||||
|
||||
@@ -5,7 +5,11 @@
|
||||
"tags": [],
|
||||
"description": "A foundational Haxe framework for cross-platform development",
|
||||
"version": "8.0.0",
|
||||
"releasenote": "",
|
||||
"contributors": [ "singmajesty" ],
|
||||
"releasenote": "Update HashLink, iOS and Android build fixes, and ongoing improvements",
|
||||
"contributors": [
|
||||
"singmajesty",
|
||||
"bowlerhat",
|
||||
"Dimensionscape"
|
||||
],
|
||||
"classPath": "src"
|
||||
}
|
||||
@@ -81,7 +81,7 @@ namespace lime {
|
||||
|
||||
static int VorbisFile_BufferClose (VorbisFile_Buffer* src) {
|
||||
|
||||
free (src);
|
||||
delete src;
|
||||
return 0;
|
||||
|
||||
}
|
||||
@@ -154,8 +154,8 @@ namespace lime {
|
||||
|
||||
if (ov_open_callbacks (buffer, vorbisFile, NULL, 0, VORBIS_FILE_BUFFER_CALLBACKS) != 0) {
|
||||
|
||||
free (buffer);
|
||||
free (vorbisFile);
|
||||
delete buffer;
|
||||
delete vorbisFile;
|
||||
return 0;
|
||||
|
||||
}
|
||||
@@ -178,7 +178,7 @@ namespace lime {
|
||||
|
||||
if (ov_open_callbacks (file, vorbisFile, NULL, 0, VORBIS_FILE_FILE_CALLBACKS) != 0) {
|
||||
|
||||
free (vorbisFile);
|
||||
delete vorbisFile;
|
||||
lime::fclose (file);
|
||||
return 0;
|
||||
|
||||
|
||||
@@ -349,7 +349,6 @@ class NativeHTTPRequest
|
||||
|
||||
future.onComplete(function(bytes)
|
||||
{
|
||||
bytes = buildBuffer();
|
||||
if (bytes == null)
|
||||
{
|
||||
promise.complete(null);
|
||||
@@ -362,7 +361,7 @@ class NativeHTTPRequest
|
||||
|
||||
return promise.future;
|
||||
}
|
||||
|
||||
|
||||
private function buildBuffer() {
|
||||
bytes = buffer.getBytes();
|
||||
return bytes;
|
||||
@@ -394,8 +393,9 @@ class NativeHTTPRequest
|
||||
}
|
||||
|
||||
private function curl_onWrite(curl:CURL, output:Bytes):Int
|
||||
{
|
||||
buffer.add(output);
|
||||
{
|
||||
buffer.addBytes(output, 0, output.length);
|
||||
|
||||
return output.length;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,210 +0,0 @@
|
||||
package lime.system;
|
||||
|
||||
import haxe.macro.Context;
|
||||
import haxe.macro.Expr;
|
||||
import haxe.macro.Type;
|
||||
#if target.threaded
|
||||
import sys.thread.Thread;
|
||||
#elseif cpp
|
||||
import cpp.vm.Thread;
|
||||
#elseif neko
|
||||
import neko.vm.Thread;
|
||||
#end
|
||||
|
||||
/**
|
||||
An object whose instance functions always run on the main thread. If called
|
||||
from any other thread, they'll switch to the main thread before proceeding.
|
||||
This is important for Android apps that use JNI, as most times a Java class
|
||||
calls a Haxe function, it does so on the UI thread.
|
||||
|
||||
Usage:
|
||||
|
||||
```haxe
|
||||
class MyClass extends ForegroundWorker
|
||||
{
|
||||
public function foregroundFunction():Void
|
||||
{
|
||||
// Code here is guaranteed to run on Haxe's main thread.
|
||||
}
|
||||
|
||||
@:anyThread public function anyThreadFunction():Void
|
||||
{
|
||||
// Code here will run on whichever thread calls the function, thanks
|
||||
// to `@:anyThread`.
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@see `ForegroundWorkerBuilder` for details and more options.
|
||||
**/
|
||||
#if (target.threaded || cpp || neko)
|
||||
@:autoBuild(lime.system.ForegroundWorkerBuilder.modifyInstanceFunctions())
|
||||
#end
|
||||
// Yes, this could also be an interface, but that opens up edge cases. Better to
|
||||
// leave those for advanced users who use `ForegroundWorkerBuilder`.
|
||||
class ForegroundWorker
|
||||
{
|
||||
#if (target.threaded || cpp || neko)
|
||||
private static var mainThread:Thread = Thread.current();
|
||||
#end
|
||||
|
||||
/**
|
||||
@return Whether the calling function is being run on the main thread.
|
||||
**/
|
||||
public static inline function onMainThread():Bool
|
||||
{
|
||||
#if (target.threaded || cpp || neko)
|
||||
return Thread.current() == mainThread;
|
||||
#else
|
||||
return true;
|
||||
#end
|
||||
}
|
||||
}
|
||||
|
||||
class ForegroundWorkerBuilder
|
||||
{
|
||||
/**
|
||||
A build macro that iterates through a class's instance functions
|
||||
(excluding those marked `@:anyThread`) and inserts code to ensure these
|
||||
functions run only on the main thread.
|
||||
|
||||
Caution: build macros never directly modify superclasses. To make a
|
||||
superclass's functions run on the main thread, either annotate that
|
||||
class with its own `@:build` metadata or override all of its functions.
|
||||
|
||||
Usage:
|
||||
|
||||
```haxe
|
||||
@:build(lime.system.ForegroundWorker.ForegroundWorkerBuilder.modifyInstanceFunctions())
|
||||
class MyClass
|
||||
{
|
||||
public var array0:Array<String> = [];
|
||||
private var array1:Array<String> = [];
|
||||
|
||||
public function copyItems():Void
|
||||
{
|
||||
//Thread safety code will be inserted automatically. You can
|
||||
//write thread-unsafe code as normal.
|
||||
for (i in 0...array0.length)
|
||||
if (this.array0[i] != null)
|
||||
this.array1.push(this.array0[i]);
|
||||
}
|
||||
}
|
||||
```
|
||||
**/
|
||||
public static macro function modifyInstanceFunctions():Array<Field>
|
||||
{
|
||||
var fields:Array<Field> = Context.getBuildFields();
|
||||
|
||||
for (field in fields)
|
||||
{
|
||||
if (field.access.indexOf(AStatic) >= 0)
|
||||
continue;
|
||||
|
||||
modifyField(field);
|
||||
}
|
||||
|
||||
return fields;
|
||||
}
|
||||
|
||||
/**
|
||||
A build macro that iterates through a class's static functions
|
||||
(excluding those marked `@:anyThread`) and inserts code to ensure these
|
||||
functions run only on the main thread.
|
||||
|
||||
Usage:
|
||||
|
||||
```haxe
|
||||
@:build(lime.system.ForegroundWorker.ForegroundWorkerBuilder.modifyStaticFunctions())
|
||||
class MyClass
|
||||
{
|
||||
private static var eventCount:Map<String, Int> = new Map();
|
||||
public static function countEvent(event:String):Void
|
||||
{
|
||||
//Thread safety code will be inserted automatically. You can
|
||||
//write thread-unsafe code as normal.
|
||||
if (eventCount.exists(event))
|
||||
eventCount[event]++;
|
||||
else
|
||||
eventCount[event] = 1;
|
||||
}
|
||||
}
|
||||
```
|
||||
**/
|
||||
public static macro function modifyStaticFunctions():Array<Field>
|
||||
{
|
||||
var fields:Array<Field> = Context.getBuildFields();
|
||||
|
||||
for (field in fields)
|
||||
{
|
||||
if (field.access.indexOf(AStatic) < 0)
|
||||
continue;
|
||||
|
||||
modifyField(field);
|
||||
}
|
||||
|
||||
return fields;
|
||||
}
|
||||
|
||||
#if macro
|
||||
private static function modifyField(field:Field):Void
|
||||
{
|
||||
if (field.name == "new")
|
||||
return;
|
||||
|
||||
if (field.meta != null)
|
||||
{
|
||||
for (meta in field.meta)
|
||||
{
|
||||
if (meta.name == ":anyThread")
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
switch (field.kind)
|
||||
{
|
||||
case FFun(f):
|
||||
field.access.remove(AInline);
|
||||
|
||||
var qualifiedIdent:Array<String>;
|
||||
if (field.access.indexOf(AStatic) >= 0)
|
||||
{
|
||||
if (Context.getLocalClass() == null)
|
||||
throw "ForegroundWorkerBuilder is only designed to work on classes.";
|
||||
|
||||
var localClass:ClassType = Context.getLocalClass().get();
|
||||
qualifiedIdent = localClass.pack.copy();
|
||||
if (localClass.module != localClass.name)
|
||||
qualifiedIdent.push(localClass.module);
|
||||
qualifiedIdent.push(localClass.name);
|
||||
}
|
||||
else
|
||||
{
|
||||
qualifiedIdent = [];
|
||||
}
|
||||
qualifiedIdent.push(field.name);
|
||||
|
||||
var args:Array<Expr> = [for (arg in f.args) macro $i{arg.name}];
|
||||
|
||||
var exprs:Array<Expr>;
|
||||
switch (f.expr.expr)
|
||||
{
|
||||
case EBlock(e):
|
||||
exprs = e;
|
||||
default:
|
||||
exprs = [f.expr];
|
||||
f.expr = { pos: field.pos, expr: EBlock(exprs) };
|
||||
}
|
||||
|
||||
exprs.unshift(macro
|
||||
if (!lime.system.ForegroundWorker.onMainThread())
|
||||
{
|
||||
haxe.MainLoop.runInMainThread($p{qualifiedIdent}.bind($a{args}));
|
||||
return;
|
||||
}
|
||||
);
|
||||
default:
|
||||
}
|
||||
}
|
||||
#end
|
||||
}
|
||||
@@ -1,7 +1,22 @@
|
||||
package lime.system;
|
||||
|
||||
#if (!lime_doc_gen || android)
|
||||
#if macro
|
||||
import haxe.macro.Context;
|
||||
import haxe.macro.Expr;
|
||||
import haxe.macro.Type;
|
||||
#else
|
||||
import lime._internal.backend.native.NativeCFFI;
|
||||
#end
|
||||
#if !lime_doc_gen
|
||||
#if target.threaded
|
||||
import sys.thread.Thread;
|
||||
#elseif cpp
|
||||
import cpp.vm.Thread;
|
||||
#elseif neko
|
||||
import neko.vm.Thread;
|
||||
#end
|
||||
#end
|
||||
|
||||
/**
|
||||
The Java Native Interface (JNI) allows C++ code to call Java functions, and
|
||||
@@ -19,7 +34,7 @@ import lime._internal.backend.native.NativeCFFI;
|
||||
Note that most Java code runs on a different thread than Haxe, meaning that
|
||||
you can get thread-related errors in both directions. Java functions can
|
||||
use `Extension.callbackHandler.post()` to switch to the UI thread, while
|
||||
Haxe code can avoid the problem using `lime.system.ForegroundWorker`.
|
||||
Haxe code can avoid the problem using `lime.system.JNI.JNISafety`.
|
||||
**/
|
||||
#if !lime_debug
|
||||
@:fileXml('tags="haxe,release"')
|
||||
@@ -325,4 +340,126 @@ class JNIMethod
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Most times a Java class calls a Haxe function, it does so on the UI thread,
|
||||
which can lead to thread-related errors. These errors can be avoided by
|
||||
switching back to the main thread before executing any code.
|
||||
|
||||
Usage:
|
||||
|
||||
```haxe
|
||||
class MyClass implements JNISafety
|
||||
{
|
||||
@:runOnMainThread
|
||||
public function callbackFunction(data:Dynamic):Void
|
||||
{
|
||||
// Code here is guaranteed to run on Haxe's main thread. It's safe
|
||||
// to call `callbackFunction` via JNI.
|
||||
}
|
||||
|
||||
public function notACallbackFunction():Void
|
||||
{
|
||||
// Code here will run on whichever thread calls the function. It may
|
||||
// not be safe to call `notACallbackFunction` via JNI.
|
||||
}
|
||||
}
|
||||
```
|
||||
**/
|
||||
// Haxe 3 can't parse "target.threaded" inside parentheses.
|
||||
#if !doc_gen
|
||||
#if target.threaded
|
||||
@:autoBuild(lime.system.JNI.JNISafetyTools.build())
|
||||
#elseif (cpp || neko)
|
||||
@:autoBuild(lime.system.JNI.JNISafetyTools.build())
|
||||
#end
|
||||
#end
|
||||
interface JNISafety {}
|
||||
|
||||
#if !doc_gen
|
||||
class JNISafetyTools
|
||||
{
|
||||
#if target.threaded
|
||||
private static var mainThread:Thread = Thread.current();
|
||||
#elseif (cpp || neko)
|
||||
private static var mainThread:Thread = Thread.current();
|
||||
#end
|
||||
|
||||
/**
|
||||
@return Whether the calling function is being run on the main thread.
|
||||
**/
|
||||
public static inline function onMainThread():Bool
|
||||
{
|
||||
#if target.threaded
|
||||
return Thread.current() == mainThread;
|
||||
#elseif (cpp || neko)
|
||||
return Thread.current() == mainThread;
|
||||
#else
|
||||
return true;
|
||||
#end
|
||||
}
|
||||
|
||||
public static macro function build():Array<Field>
|
||||
{
|
||||
var fields:Array<Field> = Context.getBuildFields();
|
||||
|
||||
#if macro
|
||||
for (field in fields)
|
||||
{
|
||||
// Don't modify constructors.
|
||||
if (field.name == "new")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Don't modify functions lacking `@:runOnMainThread`.
|
||||
if (field.meta == null || !Lambda.exists(field.meta,
|
||||
function(meta) return meta.name == ":runOnMainThread"))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (field.kind)
|
||||
{
|
||||
case FFun(f):
|
||||
// The function needs to call itself and can't be inline.
|
||||
field.access.remove(AInline);
|
||||
|
||||
// Make sure there's no return value.
|
||||
switch (f.ret)
|
||||
{
|
||||
case macro:Void:
|
||||
// Good to go.
|
||||
case null:
|
||||
f.ret = macro:Void;
|
||||
default:
|
||||
Context.error("Expected return type Void, got "
|
||||
+ new haxe.macro.Printer().printComplexType(f.ret) + ".", field.pos);
|
||||
}
|
||||
|
||||
var args:Array<Expr> = [];
|
||||
for (arg in f.args)
|
||||
{
|
||||
args.push(macro $i{arg.name});
|
||||
|
||||
// Account for an unlikely edge case.
|
||||
if (arg.name == field.name)
|
||||
Context.error('${field.name}() should not take an argument named ${field.name}.', field.pos);
|
||||
}
|
||||
|
||||
// Check the thread before running the function.
|
||||
f.expr = macro
|
||||
if (!lime.system.JNI.JNISafetyTools.onMainThread())
|
||||
haxe.MainLoop.runInMainThread($i{field.name}.bind($a{args}))
|
||||
else
|
||||
${f.expr};
|
||||
default:
|
||||
}
|
||||
}
|
||||
#end
|
||||
|
||||
return fields;
|
||||
}
|
||||
}
|
||||
#end
|
||||
#end
|
||||
|
||||
@@ -286,7 +286,12 @@ class AIRHelper
|
||||
var extDirs:Array<String> = getExtDirs(project);
|
||||
|
||||
var profile:String;
|
||||
if (targetPlatform == ANDROID)
|
||||
|
||||
if (project.config.exists("air.profile"))
|
||||
{
|
||||
profile = project.config.getString("air.profile");
|
||||
}
|
||||
else if (targetPlatform == ANDROID)
|
||||
{
|
||||
profile = "mobileDevice";
|
||||
}
|
||||
|
||||
@@ -298,9 +298,11 @@ class IconHelper
|
||||
for (icon in icons)
|
||||
{
|
||||
var iconDifference = icon.width - width + icon.height - height;
|
||||
if (Path.extension(icon.path) == "svg")
|
||||
|
||||
// If size is unspecified, accept it as an almost-perfect match
|
||||
if (icon.width == 0 && icon.height == 0)
|
||||
{
|
||||
iconDifference = 0;
|
||||
iconDifference = 1;
|
||||
}
|
||||
|
||||
if (iconDifference < 0 && !acceptSmaller)
|
||||
|
||||
@@ -112,7 +112,10 @@ class FileDialog
|
||||
var path = null;
|
||||
#if hl
|
||||
var bytes = NativeCFFI.lime_file_dialog_open_file(title, filter, defaultPath);
|
||||
path = @:privateAccess String.fromUTF8(cast bytes);
|
||||
if (bytes != null)
|
||||
{
|
||||
path = @:privateAccess String.fromUTF8(cast bytes);
|
||||
}
|
||||
#else
|
||||
path = NativeCFFI.lime_file_dialog_open_file(title, filter, defaultPath);
|
||||
#end
|
||||
@@ -149,7 +152,10 @@ class FileDialog
|
||||
var path = null;
|
||||
#if hl
|
||||
var bytes = NativeCFFI.lime_file_dialog_open_directory(title, filter, defaultPath);
|
||||
path = @:privateAccess String.fromUTF8(cast bytes);
|
||||
if (bytes != null)
|
||||
{
|
||||
path = @:privateAccess String.fromUTF8(cast bytes);
|
||||
}
|
||||
#else
|
||||
path = NativeCFFI.lime_file_dialog_open_directory(title, filter, defaultPath);
|
||||
#end
|
||||
@@ -164,7 +170,10 @@ class FileDialog
|
||||
var path = null;
|
||||
#if hl
|
||||
var bytes = NativeCFFI.lime_file_dialog_save_file(title, filter, defaultPath);
|
||||
if (bytes != null) path = @:privateAccess String.fromUTF8(cast bytes);
|
||||
if (bytes != null)
|
||||
{
|
||||
path = @:privateAccess String.fromUTF8(cast bytes);
|
||||
}
|
||||
#else
|
||||
path = NativeCFFI.lime_file_dialog_save_file(title, filter, defaultPath);
|
||||
#end
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package lime.utils;
|
||||
|
||||
import haxe.ds.ObjectMap;
|
||||
import haxe.io.Bytes;
|
||||
import haxe.io.Path;
|
||||
import haxe.macro.Compiler;
|
||||
@@ -35,18 +36,14 @@ class Preloader #if flash extends Sprite #end
|
||||
public var onProgress = new Event<Int->Int->Void>();
|
||||
|
||||
@:noCompletion private var bytesLoaded:Int;
|
||||
#if !disable_preloader_assets
|
||||
@:noCompletion private var bytesLoadedCache = new Map<AssetLibrary, Int>();
|
||||
#end
|
||||
@:noCompletion private var bytesLoadedCache = new ObjectMap<#if !disable_preloader_assets AssetLibrary #else Dynamic #end, Int>();
|
||||
@:noCompletion private var bytesLoadedCache2 = new Map<String, Int>();
|
||||
@:noCompletion private var bytesTotal:Int;
|
||||
@:noCompletion private var bytesTotalCache = new Map<String, Int>();
|
||||
@:noCompletion private var initLibraryNames:Bool;
|
||||
#if !disable_preloader_assets
|
||||
@:noCompletion private var libraries:Array<AssetLibrary>;
|
||||
@:noCompletion private var libraries:Array<#if !disable_preloader_assets AssetLibrary #else Dynamic #end>;
|
||||
@:noCompletion private var libraryNames:Array<String>;
|
||||
@:noCompletion private var loadedLibraries:Int;
|
||||
#end
|
||||
@:noCompletion private var loadedStage:Bool;
|
||||
@:noCompletion private var preloadComplete:Bool;
|
||||
@:noCompletion private var preloadStarted:Bool;
|
||||
@@ -63,10 +60,8 @@ class Preloader #if flash extends Sprite #end
|
||||
bytesLoaded = 0;
|
||||
bytesTotal = 0;
|
||||
|
||||
#if !disable_preloader_assets
|
||||
libraries = new Array<AssetLibrary>();
|
||||
libraries = new Array<#if !disable_preloader_assets AssetLibrary #else Dynamic #end>();
|
||||
libraryNames = new Array<String>();
|
||||
#end
|
||||
|
||||
onProgress.add(update);
|
||||
|
||||
@@ -111,8 +106,7 @@ class Preloader #if flash extends Sprite #end
|
||||
#end
|
||||
}
|
||||
|
||||
#if !disable_preloader_assets
|
||||
public function addLibrary(library:AssetLibrary):Void
|
||||
public function addLibrary(library:#if !disable_preloader_assets AssetLibrary #else Dynamic #end):Void
|
||||
{
|
||||
libraries.push(library);
|
||||
}
|
||||
@@ -124,21 +118,17 @@ class Preloader #if flash extends Sprite #end
|
||||
libraryNames.push(name);
|
||||
}
|
||||
}
|
||||
#end
|
||||
|
||||
public function load():Void
|
||||
{
|
||||
#if !disable_preloader_assets
|
||||
for (library in libraries)
|
||||
{
|
||||
bytesTotal += library.bytesTotal;
|
||||
}
|
||||
|
||||
loadedLibraries = -1;
|
||||
#end
|
||||
preloadStarted = false;
|
||||
|
||||
#if !disable_preloader_assets
|
||||
for (library in libraries)
|
||||
{
|
||||
Log.verbose("Preloading asset library");
|
||||
@@ -170,7 +160,7 @@ class Preloader #if flash extends Sprite #end
|
||||
}
|
||||
else
|
||||
{
|
||||
bytesLoaded += library.bytesTotal - bytesLoadedCache.get(library);
|
||||
bytesLoaded += Std.int(library.bytesTotal) - bytesLoadedCache.get(library);
|
||||
}
|
||||
|
||||
loadedAssetLibrary();
|
||||
@@ -189,12 +179,10 @@ class Preloader #if flash extends Sprite #end
|
||||
}
|
||||
|
||||
loadedLibraries++;
|
||||
#end
|
||||
preloadStarted = true;
|
||||
updateProgress();
|
||||
}
|
||||
|
||||
#if !disable_preloader_assets
|
||||
@:noCompletion private function loadedAssetLibrary(name:String = null):Void
|
||||
{
|
||||
loadedLibraries++;
|
||||
@@ -215,7 +203,6 @@ class Preloader #if flash extends Sprite #end
|
||||
|
||||
updateProgress();
|
||||
}
|
||||
#end
|
||||
|
||||
@:noCompletion private function start():Void
|
||||
{
|
||||
@@ -309,8 +296,8 @@ class Preloader #if flash extends Sprite #end
|
||||
}
|
||||
#end
|
||||
|
||||
if (!simulateProgress #if flash && loadedStage #end#if !disable_preloader_assets
|
||||
&& loadedLibraries == (libraries.length + libraryNames.length) #end)
|
||||
if (!simulateProgress #if flash && loadedStage #end
|
||||
&& loadedLibraries == (libraries.length + libraryNames.length))
|
||||
{
|
||||
if (!preloadComplete)
|
||||
{
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<meta-data android:name="SDL_ENV.SDL_IOS_ORIENTATIONS" android:value= "LandscapeLeft LandscapeRight" />
|
||||
::end::
|
||||
|
||||
<activity android:name="MainActivity" android:launchMode="singleTask" android:label="::APP_TITLE::" android:configChanges="keyboardHidden|orientation|screenSize|screenLayout"::if (WIN_ORIENTATION=="portrait"):: android:screenOrientation="sensorPortrait"::end::::if (WIN_ORIENTATION=="landscape"):: android:screenOrientation="sensorLandscape"::end:: android:exported="true">
|
||||
<activity android:name="MainActivity" android:exported="true" android:launchMode="singleTask" android:label="::APP_TITLE::" android:configChanges="keyboardHidden|orientation|screenSize|screenLayout|uiMode"::if (WIN_ORIENTATION=="portrait"):: android:screenOrientation="sensorPortrait"::end::::if (WIN_ORIENTATION=="landscape"):: android:screenOrientation="sensorLandscape"::end::>
|
||||
|
||||
<intent-filter>
|
||||
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#if !disable_preloader_assets
|
||||
package;
|
||||
|
||||
|
||||
import haxe.io.Bytes;
|
||||
import lime.utils.AssetBundle;
|
||||
import lime.utils.AssetLibrary;
|
||||
@@ -12,6 +10,18 @@ import lime.utils.Assets;
|
||||
import sys.FileSystem;
|
||||
#end
|
||||
|
||||
#if disable_preloader_assets
|
||||
@:dox(hide) class ManifestResources {
|
||||
public static var preloadLibraries:Array<Dynamic>;
|
||||
public static var preloadLibraryNames:Array<String>;
|
||||
public static var rootPath:String;
|
||||
|
||||
public static function init (config:Dynamic):Void {
|
||||
preloadLibraries = new Array ();
|
||||
preloadLibraryNames = new Array ();
|
||||
}
|
||||
}
|
||||
#else
|
||||
@:access(lime.utils.Assets)
|
||||
|
||||
|
||||
|
||||
4
templates/hl/mac-launch.sh
Normal file
4
templates/hl/mac-launch.sh
Normal file
@@ -0,0 +1,4 @@
|
||||
#!/usr/bin/env sh
|
||||
# HashLink needs a specific working directory to find hlboot.dat and libraries
|
||||
cd "$(dirname "$0")"
|
||||
exec ./hl
|
||||
@@ -207,6 +207,20 @@ class MacPlatform extends PlatformTarget
|
||||
if (noOutput) return;
|
||||
|
||||
HashlinkHelper.copyHashlink(project, targetDirectory, executableDirectory, executablePath, is64);
|
||||
|
||||
// HashLink looks for hlboot.dat and libraries in the current
|
||||
// working directory, so the .app file won't work properly if it
|
||||
// tries to run the HashLink executable directly.
|
||||
// when the .app file is launched, we can tell it to run a shell
|
||||
// script instead of the HashLink executable. the shell script will
|
||||
// adjusts the working directory before running the HL executable.
|
||||
|
||||
// unlike other platforms, we want to use the original "hl" name
|
||||
var hlExecutablePath = Path.combine(executableDirectory, "hl");
|
||||
System.renameFile(executablePath, hlExecutablePath);
|
||||
System.runCommand("", "chmod", ["755", hlExecutablePath]);
|
||||
// then we can use the executable name for the shell script
|
||||
System.copyFileTemplate(project.templatePaths, 'hl/mac-launch.sh', executablePath);
|
||||
}
|
||||
else if (targetType == "java")
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user