package; import haxe.io.Path; import openfl.utils.AssetLibrary; import openfl.utils.AssetManifest; import openfl.utils.AssetType; import openfl.events.Event; import openfl.events.EventDispatcher; import sys.FileSystem; import sys.io.File; import haxe.crypto.Base64; /** * Custom asset management system that initializes OpenFL's asset system. * This supplements OpenFL's built-in asset handling. */ class Assets { // Track initialization state public static var isLoaded:Bool = false; // Event dispatcher for asset loading events private static var dispatcher:EventDispatcher = new EventDispatcher(); // Potential manifest locations private static var manifestPaths = [ "manifest/default.json", "bin/cpp/manifest/default.json", "../manifest/default.json" ]; // Event types public static inline var ASSET_LOADED:String = "assetLoaded"; public static inline var ASSET_ERROR:String = "assetError"; /** * Initialize the asset system */ public static function initializeAssets():Void { if (isLoaded) return; // Don't load twice trace("Initializing asset system..."); // First, try to initialize embedded assets if the macro created them try { if (Reflect.hasField(macros.AssetMacro, "initEmbeddedAssets")) { trace("Initializing embedded assets..."); Reflect.callMethod(macros.AssetMacro, Reflect.field(macros.AssetMacro, "initEmbeddedAssets"), []); isLoaded = true; } } catch (e:Dynamic) { trace("No embedded assets available: " + e); } // Then try to load from manifest files loadFromManifest(); if (isLoaded) { trace("Asset system initialized successfully."); // Log available assets trace("Available assets:"); for (assetPath in openfl.Assets.list()) { var type = getAssetTypeString(assetPath); trace(" - " + assetPath + " (Type: " + type + ")"); } } else { trace("WARNING: Asset system could not be fully initialized."); } } /** * Try to load assets from an external manifest file */ private static function loadFromManifest():Void { trace("Checking for asset manifest files..."); for (path in manifestPaths) { if (FileSystem.exists(path)) { try { trace("Loading asset manifest from: " + path); var content = File.getContent(path); var jsonStartPos = 0; while (jsonStartPos < content.length && content.charAt(jsonStartPos) != '{') { jsonStartPos++; } if (jsonStartPos > 0) { content = content.substr(jsonStartPos); } if (content == null || content.length == 0 || content.charAt(0) != '{') { trace("Invalid JSON content in manifest file"); continue; } var manifestData = haxe.Json.parse(content); var manifest = new AssetManifest(); manifest.name = manifestData.name; manifest.assets = manifestData.assets; manifest.rootPath = manifestData.rootPath != null ? manifestData.rootPath : Path.directory(path); manifest.version = manifestData.version; manifest.libraryType = manifestData.libraryType; manifest.libraryArgs = manifestData.libraryArgs; if (manifest.assets != null && manifest.assets.length > 0) { trace("Parsed manifest with " + manifest.assets.length + " assets"); var library = AssetLibrary.fromManifest(manifest); if (library != null) { var libraryName = manifest.name != null ? manifest.name : "default"; if (openfl.Assets.hasLibrary(libraryName)) { openfl.Assets.unloadLibrary(libraryName); } openfl.Assets.registerLibrary(libraryName, library); trace("Registered asset library: " + libraryName); isLoaded = true; dispatcher.dispatchEvent(new Event(ASSET_LOADED)); return; } else { trace("ERROR: Failed to create library from manifest"); } } else { trace("ERROR: No assets found in manifest"); } } catch (e:Dynamic) { trace("Error loading manifest from " + path + ": " + e); } } else { trace("Manifest not found at: " + path); } } dispatcher.dispatchEvent(new Event(ASSET_ERROR)); } /** * Add event listener for asset events */ public static function addEventListener(type:String, listener:Dynamic->Void, useCapture:Bool = false, priority:Int = 0, useWeakReference:Bool = false):Void { dispatcher.addEventListener(type, listener, useCapture, priority, useWeakReference); } /** * Remove event listener */ public static function removeEventListener(type:String, listener:Dynamic->Void, useCapture:Bool = false):Void { dispatcher.removeEventListener(type, listener, useCapture); } /** * Force reload the asset system */ public static function reload():Void { var libraryNames = openfl.Assets.list().map(function(id) { var parts = id.split(":"); return parts.length > 1 ? parts[0] : "default"; }).filter(function(name) { return name != null && name != ""; }); var uniqueNames = new Map(); for (name in libraryNames) { uniqueNames.set(name, true); } for (name in uniqueNames.keys()) { if (openfl.Assets.hasLibrary(name)) { try { openfl.Assets.unloadLibrary(name); } catch (e:Dynamic) { trace("Error unloading library " + name + ": " + e); } } } isLoaded = false; initializeAssets(); } /** * Helper function to determine asset types by extension */ private static function getAssetTypeString(id:String):String { try { if (!openfl.Assets.exists(id)) return "unknown"; var extension = Path.extension(id).toLowerCase(); return switch(extension) { case "jpg", "jpeg", "png", "gif", "bmp": "image"; case "mp3", "ogg", "wav": "sound"; case "ttf", "otf": "font"; case "txt", "json", "xml", "csv", "tsv": "text"; default: "binary"; } } catch (e:Dynamic) { return "unknown"; } } /** * Debug the manifest and asset system status */ public static function debugManifest():String { var result = "Asset System Status:\n"; result += "Initialized: " + isLoaded + "\n\n"; var hasManifest = false; for (path in manifestPaths) { if (FileSystem.exists(path)) { hasManifest = true; try { var content = File.getContent(path); var jsonStartPos = 0; while (jsonStartPos < content.length && content.charAt(jsonStartPos) != '{') { jsonStartPos++; } if (jsonStartPos > 0) { content = content.substr(jsonStartPos); } result += "Manifest: " + path + "\n"; result += "Size: " + content.length + " bytes\n"; if (content.length > 200) { result += "Content: " + content.substr(0, 200) + "...\n"; } else { result += "Content: " + content + "\n"; } var assetCount = "unknown"; try { var jsonData = haxe.Json.parse(content); if (jsonData != null && jsonData.assets != null) { assetCount = Std.string(jsonData.assets.length); } } catch (e:Dynamic) { assetCount = "Error: " + e; } result += "Assets: " + assetCount + "\n"; } catch (e:Dynamic) { result += "Error reading manifest " + path + ": " + e + "\n"; } } } if (!hasManifest) { result += "No manifest files found.\n"; } var libraryNames = []; try { for (asset in openfl.Assets.list()) { var libName = ""; var colonIndex = asset.indexOf(":"); if (colonIndex > -1) { libName = asset.substring(0, colonIndex); } else { libName = "default"; } if (libraryNames.indexOf(libName) == -1) { libraryNames.push(libName); } } } catch (e:Dynamic) { result += "Error getting libraries: " + e + "\n"; } result += "\nLibraries: " + libraryNames.join(", ") + "\n"; result += "Asset count: " + openfl.Assets.list().length; return result; } }