diff --git a/src/lime/tools/ConfigData.hx b/src/lime/tools/ConfigData.hx index d869814206..79683495af 100644 --- a/src/lime/tools/ConfigData.hx +++ b/src/lime/tools/ConfigData.hx @@ -9,7 +9,12 @@ import haxe.xml.Fast as Access; abstract ConfigData(Dynamic) to Dynamic from Dynamic { - private static inline var ARRAY:String = "___array"; + private static inline var ARRAY:String = "config:array_"; + + /** + If set, `parse()` will add child nodes to this array instead of parsing them. + **/ + @:noCompletion public var xmlChildren(get, set):Array; public function new() { @@ -75,7 +80,7 @@ abstract ConfigData(Dynamic) to Dynamic from Dynamic if (current != null) { - array = Reflect.field(current, field + ARRAY); + array = Reflect.field(current, ARRAY + field); if (array == null && Reflect.hasField(current, field)) { @@ -170,7 +175,7 @@ abstract ConfigData(Dynamic) to Dynamic from Dynamic return defaultValue; } - public function getKeyValueArray(id:String, defaultValues:Dynamic = null):Array<{ key:Dynamic, value:Dynamic }> + public function getKeyValueArray(id:String, defaultValues:Dynamic = null):Array<{ key:String, value:Dynamic }> { var values = {}; if (defaultValues != null) @@ -181,7 +186,7 @@ abstract ConfigData(Dynamic) to Dynamic from Dynamic var data = get(id); for (key in Reflect.fields(data)) { - if (!StringTools.endsWith (key, ARRAY)) + if (!StringTools.startsWith(key, "config:")) { Reflect.setField(values, key, Reflect.field(data, key)); } @@ -216,72 +221,63 @@ abstract ConfigData(Dynamic) to Dynamic from Dynamic { for (field in Reflect.fields(source)) { - if (StringTools.endsWith(field, ARRAY)) + if (StringTools.startsWith(field, ARRAY)) { continue; } - var doCopy = true; - var exists = Reflect.hasField(destination, field); - var typeDest = null; + var valueSource = Reflect.field(source, field); + var valueDest = Reflect.field(destination, field); + var typeSource = Type.typeof(valueSource).getName(); + var typeDest = Type.typeof(valueDest).getName(); - if (exists) + // if trying to copy a non object over an object, don't + if (typeSource != "TObject" && typeDest == "TObject") { - var valueSource = Reflect.field(source, field); - var valueDest = Reflect.field(destination, field); - var typeSource = Type.typeof(valueSource).getName(); - typeDest = Type.typeof(valueDest).getName(); + continue; + } - // if trying to copy a non object over an object, don't - if (typeSource != "TObject" && typeDest == "TObject") + if (valueSource != valueDest && valueDest != null && typeSource != "TObject" && !#if (haxe_ver >= 4.2) Std.isOfType #else Std.is #end(valueSource, Array)) + { + if (!Reflect.hasField(destination, ARRAY + field)) { - doCopy = false; - - // if (Log.verbose) { - // - // Log.println (field + " not merged by preference"); - // - // } + Reflect.setField(destination, ARRAY + field, [ObjectTools.deepCopy(Reflect.field(destination, field))]); } - if (doCopy && Reflect.field(source, field) != Reflect.field(destination, field) && typeSource != "TObject") - { - if (!Reflect.hasField(destination, field + ARRAY)) - { - Reflect.setField(destination, field + ARRAY, [ObjectTools.deepCopy(Reflect.field(destination, field))]); - } - - var array:Array = Reflect.field(destination, field + ARRAY); - - if (Reflect.hasField(source, field + ARRAY)) - { - array = array.concat(Reflect.field(source, field + ARRAY)); - Reflect.setField(destination, field + ARRAY, array); - } - else - { - array.push(Reflect.field(source, field)); - } + var array:Array = Reflect.field(destination, ARRAY + field); - Reflect.setField(destination, field, Reflect.field(source, field)); - doCopy = false; + if (Reflect.hasField(source, ARRAY + field)) + { + array = array.concat(Reflect.field(source, ARRAY + field)); + Reflect.setField(destination, ARRAY + field, array); + } + else + { + array.push(Reflect.field(source, field)); } + + Reflect.setField(destination, field, Reflect.field(source, field)); + continue; } - if (doCopy) + if (typeDest == "TObject") + { + mergeValues(valueSource, valueDest); + } + else if (typeDest == "TClass" && #if (haxe_ver >= 4.2) Std.isOfType #else Std.is #end (valueSource, Array) && #if (haxe_ver >= 4.2) Std.isOfType #else Std.is #end(valueDest, Array)) { - if (typeDest == "TObject") + for (item in (cast valueSource:Array)) { - mergeValues(Reflect.field(source, field), Reflect.field(destination, field)); + (cast valueDest:Array).push(item); } - else - { - Reflect.setField(destination, field, Reflect.field(source, field)); + } + else + { + Reflect.setField(destination, field, Reflect.field(source, field)); - if (Reflect.hasField(source, field + ARRAY)) - { - Reflect.setField(destination, field + ARRAY, Reflect.field(source, field + ARRAY)); - } + if (Reflect.hasField(source, ARRAY + field)) + { + Reflect.setField(destination, ARRAY + field, Reflect.field(source, ARRAY + field)); } } } @@ -302,6 +298,10 @@ abstract ConfigData(Dynamic) to Dynamic from Dynamic { bucketType = elem.att.type; } + else if (elem.x.exists("config:type")) + { + bucketType = elem.x.get("config:type"); + } if (bucketType != "") { @@ -318,7 +318,7 @@ abstract ConfigData(Dynamic) to Dynamic from Dynamic { for (attrName in elem.x.attributes()) { - if (attrName != "type") + if (attrName != "type" && attrName != "config:type") { var attrValue = elem.x.get(attrName); if (substitute != null) attrValue = substitute(attrValue); @@ -327,64 +327,77 @@ abstract ConfigData(Dynamic) to Dynamic from Dynamic } } - private function parseChildren(elem:Access, bucket:Dynamic, depth:Int = 0, substitute:String->String = null):Void + private function parseChildren(elem:Access, bucket:ConfigData, depth:Int = 0, substitute:String->String = null):Void { + if (bucket.xmlChildren != null) + { + var children:Array = bucket.xmlChildren; + for (child in elem.elements) + { + children.push(child.x.toString()); + } + + return; + } + for (child in elem.elements) { - if (child.name != "config") + if (child.name == "config") { - // log("config data > child : " + child.name); + continue; + } - var d = depth + 1; + // log("config data > child : " + child.name); - var hasChildren = child.x.elements().hasNext(); - var hasAttributes = child.x.attributes().hasNext(); + var d = depth + 1; - if (Reflect.hasField(bucket, child.name)) - { - var array:Array = Reflect.field(bucket, child.name + ARRAY); - if (array == null) - { - array = [ObjectTools.deepCopy(Reflect.field(bucket, child.name))]; - Reflect.setField(bucket, child.name + ARRAY, array); - } + var hasChildren = child.x.elements().hasNext(); + var hasAttributes = child.x.attributes().hasNext(); - var arrayBucket = {}; - array.push(arrayBucket); + if (Reflect.hasField(bucket, child.name)) + { + var array:Array = Reflect.field(bucket, ARRAY + child.name); + if (array == null) + { + array = [ObjectTools.deepCopy(Reflect.field(bucket, child.name))]; + Reflect.setField(bucket, ARRAY + child.name, array); + } - if (hasAttributes) - { - parseAttributes(child, arrayBucket, substitute); - } + var arrayBucket = {}; + array.push(arrayBucket); - if (hasChildren) - { - parseChildren(child, arrayBucket, d, substitute); - } + if (hasAttributes) + { + parseAttributes(child, arrayBucket, substitute); + } - if (!hasChildren && !hasAttributes) - { - parseValue(child, arrayBucket, substitute); - } + if (hasChildren) + { + parseChildren(child, arrayBucket, d, substitute); } if (!hasChildren && !hasAttributes) { - parseValue(child, bucket, substitute); + parseValue(child, arrayBucket, substitute); } - else - { - var childBucket = addBucket(child.name, bucket); + } - if (hasAttributes) - { - parseAttributes(child, childBucket, substitute); - } + if (!hasChildren && !hasAttributes) + { + parseValue(child, bucket, substitute); + } + else + { + var childBucket = addBucket(child.name, bucket); - if (hasChildren) - { - parseChildren(child, childBucket, d, substitute); - } + if (hasAttributes) + { + parseAttributes(child, childBucket, substitute); + } + + if (hasChildren) + { + parseChildren(child, childBucket, d, substitute); } } } @@ -426,12 +439,12 @@ abstract ConfigData(Dynamic) to Dynamic from Dynamic if (Reflect.hasField(current, field)) { - var array:Array = Reflect.field(current, field + ARRAY); + var array:Array = Reflect.field(current, ARRAY + field); if (array == null) { array = [ObjectTools.deepCopy(Reflect.field(current, field))]; - Reflect.setField(current, field + ARRAY, array); + Reflect.setField(current, ARRAY + field, array); } if (!unique || array.indexOf(value) == -1) @@ -495,11 +508,11 @@ abstract ConfigData(Dynamic) to Dynamic from Dynamic { if (typeSource != "TObject") { - var array:Array = Reflect.field(bucket, node + ARRAY); + var array:Array = Reflect.field(bucket, ARRAY + node); if (array == null) { array = [ObjectTools.deepCopy(Reflect.field(bucket, node))]; - Reflect.setField(bucket, node + ARRAY, array); + Reflect.setField(bucket, ARRAY + node, array); } array.push(value); @@ -513,4 +526,15 @@ abstract ConfigData(Dynamic) to Dynamic from Dynamic Reflect.setField(bucket, node, value); } } + + // Getters & Setters + + private inline function get_xmlChildren():Array { + return Reflect.field(this, "config:xml_children"); + } + + private inline function set_xmlChildren(value:Array):Array { + Reflect.setField(this, "config:xml_children", value); + return value; + } } diff --git a/src/lime/tools/HXProject.hx b/src/lime/tools/HXProject.hx index 357cea03ef..b2e4561df8 100644 --- a/src/lime/tools/HXProject.hx +++ b/src/lime/tools/HXProject.hx @@ -208,6 +208,11 @@ class HXProject extends Script splashScreens = new Array(); targetHandlers = new Map(); + config.set("android", { manifest:{}, application:{}, activity:{} }); + config.get("android.manifest").xmlChildren = []; + config.get("android.application").xmlChildren = []; + config.get("android.activity").xmlChildren = []; + initializeDefines(); } diff --git a/templates/android/template/app/src/main/AndroidManifest.xml b/templates/android/template/app/src/main/AndroidManifest.xml index aeac9518c8..ed3640a1f5 100644 --- a/templates/android/template/app/src/main/AndroidManifest.xml +++ b/templates/android/template/app/src/main/AndroidManifest.xml @@ -1,11 +1,13 @@ - + ::foreach ANDROID_PERMISSIONS:: ::end:: + ::foreach ANDROID_MANIFEST_CHILDREN::::__current__:: + ::end:: @@ -14,6 +16,8 @@ ::elseif (WIN_ORIENTATION=="landscape"):: ::end:: + ::foreach ANDROID_APPLICATION_CHILDREN::::__current__:: + ::end:: @@ -35,6 +39,9 @@ ::end:: + ::foreach ANDROID_ACTIVITY_CHILDREN::::__current__:: + ::end:: + diff --git a/tools/platforms/AndroidPlatform.hx b/tools/platforms/AndroidPlatform.hx index 4d4caaaf12..4e9311fde0 100644 --- a/tools/platforms/AndroidPlatform.hx +++ b/tools/platforms/AndroidPlatform.hx @@ -463,7 +463,6 @@ class AndroidPlatform extends PlatformTarget context.CPP_DIR = targetDirectory + "/obj"; context.OUTPUT_DIR = targetDirectory; - context.ANDROID_INSTALL_LOCATION = project.config.getString("android.install-location", "auto"); context.ANDROID_MINIMUM_SDK_VERSION = project.config.getInt("android.minimum-sdk-version", 21); context.ANDROID_TARGET_SDK_VERSION = project.config.getInt("android.target-sdk-version", 30); context.ANDROID_EXTENSIONS = project.config.getArrayString("android.extension"); @@ -478,6 +477,12 @@ class AndroidPlatform extends PlatformTarget context.ANDROID_USE_ANDROIDX = project.config.getString("android.useAndroidX", "true"); context.ANDROID_ENABLE_JETIFIER = project.config.getString("android.enableJetifier", "false"); + context.ANDROID_MANIFEST = project.config.getKeyValueArray("android.manifest", { + "android:versionCode": project.meta.buildNumber, + "android:versionName": project.meta.version, + "android:installLocation": project.config.getString("android.install-location", "auto") + }); + context.ANDROID_MANIFEST_CHILDREN = project.config.get("android.manifest").xmlChildren; context.ANDROID_APPLICATION = project.config.getKeyValueArray("android.application", { "android:label": project.meta.title, "android:allowBackup": "true", @@ -485,6 +490,7 @@ class AndroidPlatform extends PlatformTarget "android:hardwareAccelerated": "true", "android:allowNativeHeapPointerTagging": context.ANDROID_TARGET_SDK_VERSION >= 30 ? "false" : null }); + context.ANDROID_APPLICATION_CHILDREN = project.config.get("android.application").xmlChildren; context.ANDROID_ACTIVITY = project.config.getKeyValueArray("android.activity", { "android:name": "MainActivity", "android:exported": "true", @@ -495,6 +501,7 @@ class AndroidPlatform extends PlatformTarget .join("|"), "android:screenOrientation": project.window.orientation == PORTRAIT ? "sensorPortrait" : (project.window.orientation == LANDSCAPE ? "sensorLandscape" : null) }); + context.ANDROID_ACTIVITY_CHILDREN = project.config.get("android.activity").xmlChildren; context.ANDROID_ACCEPT_FILE_INTENT = project.config.getArrayString("android.accept-file-intent", []); if (!project.environment.exists("ANDROID_SDK") || !project.environment.exists("ANDROID_NDK_ROOT"))