From 0e58775532fefb1d8281076a9314c4e84e96ddb8 Mon Sep 17 00:00:00 2001 From: "Enzo Persillet (Tutez)" Date: Wed, 1 Apr 2026 21:44:38 +0200 Subject: [PATCH 1/2] Include generated animate classes in the build --- scripts/Tools.hx | 123 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 107 insertions(+), 16 deletions(-) diff --git a/scripts/Tools.hx b/scripts/Tools.hx index 9a3d0fb..36a6caa 100644 --- a/scripts/Tools.hx +++ b/scripts/Tools.hx @@ -55,6 +55,67 @@ class Tools private static var targetDirectory:String; private static var targetFlags:Map; + private static function readGeneratedClassesFile(path:String):Array + { + if (path == null || !FileSystem.exists(path)) + { + return null; + } + + var generatedClasses = []; + for (line in File.getContent(path).split("\n")) + { + var className = StringTools.trim(line); + if (className != "" && !StringTools.startsWith(className, "#")) + { + generatedClasses.push(className); + } + } + + return generatedClasses; + } + + private static function writeGeneratedClassesCache(path:String, generatedClasses:Array):Void + { + if (path == null) + { + return; + } + + File.saveContent(path, generatedClasses.join("\n")); + } + + private static function deleteGeneratedClassFiles(targetPath:String, classNames:Array):Void + { + if (targetPath == null || classNames == null) + { + return; + } + + for (className in classNames) + { + if (className == null || className == "") + { + continue; + } + + var classPath = Path.combine(targetPath, className.split(".").join("/") + ".hx"); + + if (FileSystem.exists(classPath)) + { + FileSystem.deleteFile(classPath); + } + } + } + + private static function pushUniqueHaxeflag(output:HXProject, value:String):Void + { + if (value != null && output.haxeflags.indexOf(value) == -1) + { + output.haxeflags.push(value); + } + } + #if neko public static function __init__() { @@ -996,7 +1057,7 @@ class Tools for (className in generatedClasses) { - output.haxeflags.push(className); + pushUniqueHaxeflag(output, className); } } @@ -1018,11 +1079,14 @@ class Tools var cacheAvailable = false; var cacheDirectory = null; var cacheFile = null; + var generatedClassesFile = null; + var cachedGeneratedClasses:Array = null; if (targetDirectory != null) { cacheDirectory = targetDirectory + "/obj/libraries"; cacheFile = cacheDirectory + "/" + library.name + ".zip"; + generatedClassesFile = cacheDirectory + "/" + library.name + ".classes.txt"; if (FileSystem.exists(cacheFile)) { @@ -1036,6 +1100,16 @@ class Tools } } + if (cacheAvailable && library.generate != false) + { + cachedGeneratedClasses = readGeneratedClassesFile(generatedClassesFile); + + if (cachedGeneratedClasses == null) + { + cacheAvailable = false; + } + } + if (!cacheAvailable) { if (cacheDirectory != null) @@ -1056,6 +1130,7 @@ class Tools if (library.generate != false) { var targetPath:String; + var previousGeneratedClasses = readGeneratedClassesFile(generatedClassesFile); if (project.target == IOS) { @@ -1067,26 +1142,42 @@ class Tools } var generatedClasses = exporter.generateClasses(targetPath, output.assets, library.prefix); + var generatedLookup = new Map(); + + for (className in generatedClasses) + { + generatedLookup.set(className, true); + } + + if (previousGeneratedClasses != null) + { + var removedGeneratedClasses = []; - // for (className in generatedClasses) - // { - // output.haxeflags.push(className); - // } + for (className in previousGeneratedClasses) + { + if (!generatedLookup.exists(className)) + { + removedGeneratedClasses.push(className); + } + } - // if (cacheDirectory != null) - // { - // File.saveContent(cacheDirectory + "/classNames.txt", generatedClasses.join("\n")); - // } + deleteGeneratedClassFiles(targetPath, removedGeneratedClasses); + } + + for (className in generatedClasses) + { + pushUniqueHaxeflag(output, className); + } + + writeGeneratedClassesCache(generatedClassesFile, generatedClasses); } } - else + else if (library.generate != false && cachedGeneratedClasses != null) { - // var generatedClasses = File.getContent(cacheDirectory + "/classNames.txt").split("\n"); - - // for (className in generatedClasses) - // { - // output.haxeflags.push(className); - // } + for (className in cachedGeneratedClasses) + { + pushUniqueHaxeflag(output, className); + } } var asset = new Asset(cacheFile, "lib/" + library.name + ".zip", AssetType.BUNDLE); From d8d2cb495c8a457bd048d358d9f7773512485528 Mon Sep 17 00:00:00 2001 From: "Enzo Persillet (Tutez)" Date: Wed, 1 Apr 2026 21:45:29 +0200 Subject: [PATCH 2/2] Resolve generated symbol types against the runtime library --- .../exporters/animate/AnimateBitmapSymbol.hx | 50 ++++++- .../exporters/animate/AnimateButtonSymbol.hx | 17 ++- .../animate/AnimateGeneratedTypeContext.hx | 137 ++++++++++++++++++ .../exporters/animate/AnimateSpriteSymbol.hx | 13 +- templates/animate/BitmapData.mtt | 7 +- templates/animate/MovieClip.mtt | 16 +- templates/animate/SimpleButton.mtt | 16 +- 7 files changed, 238 insertions(+), 18 deletions(-) create mode 100644 src/swf/exporters/animate/AnimateGeneratedTypeContext.hx diff --git a/src/swf/exporters/animate/AnimateBitmapSymbol.hx b/src/swf/exporters/animate/AnimateBitmapSymbol.hx index 3b5e06e..af6f444 100644 --- a/src/swf/exporters/animate/AnimateBitmapSymbol.hx +++ b/src/swf/exporters/animate/AnimateBitmapSymbol.hx @@ -1,5 +1,6 @@ package swf.exporters.animate; +import swf.utils.SymbolUtils; import openfl.display.Bitmap; import openfl.display.BitmapData; import openfl.display.PixelSnapping; @@ -14,6 +15,9 @@ class AnimateBitmapSymbol extends AnimateSymbol public var path:String; public var smooth:Null; + private var resolvedSymbolType:Class; + private var resolvedSymbolTypeReady = false; + public function new() { super(); @@ -22,9 +26,53 @@ class AnimateBitmapSymbol extends AnimateSymbol private override function __createObject(library:AnimateLibrary):Bitmap { #if lime - return new Bitmap(BitmapData.fromImage(library.getImage(path)), PixelSnapping.AUTO, smooth != false); + return new Bitmap(__createBitmapData(library), PixelSnapping.AUTO, smooth != false); #else return null; #end } + + private function __createBitmapData(library:AnimateLibrary):BitmapData + { + var symbolType = __resolveSymbolType(); + + if (symbolType != null) + { + AnimateGeneratedTypeContext.setBitmap(library, this); + + try + { + var bitmapData:BitmapData = cast Type.createInstance(symbolType, []); + AnimateGeneratedTypeContext.clearBitmapIfMatches(library, this); + if (bitmapData != null) + { + return bitmapData; + } + } + catch (e:Dynamic) + { + AnimateGeneratedTypeContext.clearBitmap(); + throw e; + } + } + + return BitmapData.fromImage(library.getImage(path)); + } + + private function __resolveSymbolType():Class + { + if (className == null) + { + return null; + } + + if (resolvedSymbolTypeReady) + { + return resolvedSymbolType; + } + + resolvedSymbolType = Type.resolveClass(SymbolUtils.formatClassName(className)); + resolvedSymbolTypeReady = true; + return resolvedSymbolType; + } } diff --git a/src/swf/exporters/animate/AnimateButtonSymbol.hx b/src/swf/exporters/animate/AnimateButtonSymbol.hx index 602939e..94f9376 100644 --- a/src/swf/exporters/animate/AnimateButtonSymbol.hx +++ b/src/swf/exporters/animate/AnimateButtonSymbol.hx @@ -65,11 +65,18 @@ class AnimateButtonSymbol extends AnimateSymbol if (symbolType != null) { - simpleButton = Type.createInstance(symbolType, []); - } - else - { - // Log.warn ("Could not resolve class \"" + symbol.className + "\""); + AnimateGeneratedTypeContext.setButton(library, this); + + try + { + simpleButton = Type.createInstance(symbolType, []); + AnimateGeneratedTypeContext.clearButtonIfMatches(library, this); + } + catch (e:Dynamic) + { + AnimateGeneratedTypeContext.clearButton(); + throw e; + } } } diff --git a/src/swf/exporters/animate/AnimateGeneratedTypeContext.hx b/src/swf/exporters/animate/AnimateGeneratedTypeContext.hx new file mode 100644 index 0000000..18db2f8 --- /dev/null +++ b/src/swf/exporters/animate/AnimateGeneratedTypeContext.hx @@ -0,0 +1,137 @@ +package swf.exporters.animate; + +class AnimateGeneratedTypeContext +{ + public static var currentBitmapLibrary(default, null):AnimateLibrary; + public static var currentBitmapSymbol(default, null):AnimateBitmapSymbol; + public static var currentButtonLibrary(default, null):AnimateLibrary; + public static var currentButtonSymbol(default, null):AnimateButtonSymbol; + public static var currentLibrary(default, null):AnimateLibrary; + public static var currentSpriteSymbol(default, null):AnimateSpriteSymbol; + + public static function setBitmap(library:AnimateLibrary, symbol:AnimateBitmapSymbol):Void + { + currentBitmapLibrary = library; + currentBitmapSymbol = symbol; + } + + public static function clearBitmap():Void + { + currentBitmapLibrary = null; + currentBitmapSymbol = null; + } + + public static function clearBitmapIfMatches(library:AnimateLibrary, symbol:AnimateBitmapSymbol):Void + { + if (currentBitmapLibrary == library && currentBitmapSymbol == symbol) + { + clearBitmap(); + } + } + + public static function consumeBitmap():AnimateGeneratedBitmapContext + { + if (currentBitmapLibrary == null || currentBitmapSymbol == null) + { + return null; + } + + var context:AnimateGeneratedBitmapContext = { + library: currentBitmapLibrary, + symbol: currentBitmapSymbol + }; + + clearBitmap(); + return context; + } + + public static function setButton(library:AnimateLibrary, symbol:AnimateButtonSymbol):Void + { + currentButtonLibrary = library; + currentButtonSymbol = symbol; + } + + public static function clearButton():Void + { + currentButtonLibrary = null; + currentButtonSymbol = null; + } + + public static function clearButtonIfMatches(library:AnimateLibrary, symbol:AnimateButtonSymbol):Void + { + if (currentButtonLibrary == library && currentButtonSymbol == symbol) + { + clearButton(); + } + } + + public static function consumeButton():AnimateGeneratedButtonContext + { + if (currentButtonLibrary == null || currentButtonSymbol == null) + { + return null; + } + + var context:AnimateGeneratedButtonContext = { + library: currentButtonLibrary, + symbol: currentButtonSymbol + }; + + clearButton(); + return context; + } + + public static function setSprite(library:AnimateLibrary, symbol:AnimateSpriteSymbol):Void + { + currentLibrary = library; + currentSpriteSymbol = symbol; + } + + public static function clearSprite():Void + { + currentLibrary = null; + currentSpriteSymbol = null; + } + + public static function clearSpriteIfMatches(library:AnimateLibrary, symbol:AnimateSpriteSymbol):Void + { + if (currentLibrary == library && currentSpriteSymbol == symbol) + { + clearSprite(); + } + } + + public static function consumeSprite():AnimateGeneratedSpriteContext + { + if (currentLibrary == null || currentSpriteSymbol == null) + { + return null; + } + + var context:AnimateGeneratedSpriteContext = { + library: currentLibrary, + symbol: currentSpriteSymbol + }; + + clearSprite(); + return context; + } +} + +typedef AnimateGeneratedBitmapContext = +{ + var library:AnimateLibrary; + var symbol:AnimateBitmapSymbol; +} + +typedef AnimateGeneratedButtonContext = +{ + var library:AnimateLibrary; + var symbol:AnimateButtonSymbol; +} + +typedef AnimateGeneratedSpriteContext = +{ + var library:AnimateLibrary; + var symbol:AnimateSpriteSymbol; +} diff --git a/src/swf/exporters/animate/AnimateSpriteSymbol.hx b/src/swf/exporters/animate/AnimateSpriteSymbol.hx index 1a6bf2f..d23f342 100644 --- a/src/swf/exporters/animate/AnimateSpriteSymbol.hx +++ b/src/swf/exporters/animate/AnimateSpriteSymbol.hx @@ -90,7 +90,18 @@ class AnimateSpriteSymbol extends AnimateSymbol if (symbolType != null) { - sprite = Type.createInstance(symbolType, []); + AnimateGeneratedTypeContext.setSprite(library, this); + + try + { + sprite = Type.createInstance(symbolType, []); + AnimateGeneratedTypeContext.clearSpriteIfMatches(library, this); + } + catch (e:Dynamic) + { + AnimateGeneratedTypeContext.clearSprite(); + throw e; + } } else { diff --git a/templates/animate/BitmapData.mtt b/templates/animate/BitmapData.mtt index fbe3416..bdc8a82 100644 --- a/templates/animate/BitmapData.mtt +++ b/templates/animate/BitmapData.mtt @@ -8,9 +8,10 @@ class ::CLASS_NAME:: extends openfl.display.BitmapData { super(0, 0, true, 0); - var library = swf.exporters.animate.AnimateLibrary.get("::UUID::"); - var symbol:swf.exporters.animate.AnimateBitmapSymbol = cast library.symbols.get(::SYMBOL_ID::); + var context = swf.exporters.animate.AnimateGeneratedTypeContext.consumeBitmap(); + var library = context != null ? context.library : swf.exporters.animate.AnimateLibrary.get("::UUID::"); + var symbol:swf.exporters.animate.AnimateBitmapSymbol = context != null ? context.symbol : cast library.symbols.get(::SYMBOL_ID::); var image = library.getImage(symbol.path); __fromImage(image); } -} \ No newline at end of file +} diff --git a/templates/animate/MovieClip.mtt b/templates/animate/MovieClip.mtt index 5aeb90c..70e1320 100644 --- a/templates/animate/MovieClip.mtt +++ b/templates/animate/MovieClip.mtt @@ -9,10 +9,18 @@ class ::CLASS_NAME:: extends ::if BASE_CLASS_NAME::::BASE_CLASS_NAME::::else::#i public function new() { - var library = swf.exporters.animate.AnimateLibrary.get("::UUID::"); - var symbol = library.symbols.get(::SYMBOL_ID::); - symbol.__init(library); + var context = swf.exporters.animate.AnimateGeneratedTypeContext.consumeSprite(); + if (context != null) + { + context.symbol.__init(context.library); + } + else + { + var library = swf.exporters.animate.AnimateLibrary.get("::UUID::"); + var symbol = library.symbols.get(::SYMBOL_ID::); + symbol.__init(library); + } super(); } -} \ No newline at end of file +} diff --git a/templates/animate/SimpleButton.mtt b/templates/animate/SimpleButton.mtt index 95fec87..c70da6a 100644 --- a/templates/animate/SimpleButton.mtt +++ b/templates/animate/SimpleButton.mtt @@ -6,10 +6,18 @@ class ::CLASS_NAME:: extends ::if BASE_CLASS_NAME::::BASE_CLASS_NAME::::else::#i { public function new() { - var library = swf.exporters.animate.AnimateLibrary.get("::UUID::"); - var symbol = library.symbols.get(::SYMBOL_ID::); - symbol.__init(library); + var context = swf.exporters.animate.AnimateGeneratedTypeContext.consumeButton(); + if (context != null) + { + context.symbol.__init(context.library); + } + else + { + var library = swf.exporters.animate.AnimateLibrary.get("::UUID::"); + var symbol = library.symbols.get(::SYMBOL_ID::); + symbol.__init(library); + } super(); } -} \ No newline at end of file +}