diff --git a/standalone-openfl-app/.gitignore b/standalone-openfl-app/.gitignore
index 204f95a3..46313fc4 100644
--- a/standalone-openfl-app/.gitignore
+++ b/standalone-openfl-app/.gitignore
@@ -1,2 +1,9 @@
+**/bin/*
+**/Export/*
+**/lime-repo/**/*
+**/openfl-repo/**/*
+
bin
-Export
\ No newline at end of file
+Export
+lime-repo
+openfl-repo
\ No newline at end of file
diff --git a/standalone-openfl-app/CORE_PRINCIPLES_IMPORTANT!.md b/standalone-openfl-app/CORE_PRINCIPLES_IMPORTANT!.md
index 3c236549..5d43579b 100644
--- a/standalone-openfl-app/CORE_PRINCIPLES_IMPORTANT!.md
+++ b/standalone-openfl-app/CORE_PRINCIPLES_IMPORTANT!.md
@@ -2,4 +2,22 @@
- Make the code work with the .hxml based workflow
- don't use compiletime `#if lime` or `#if openfl` as this relies on the openfl and lime build system. We don't use their buildsystems but try to do the same thing they do for the hxcpp based targets. (Native Windows/ Linux compilation)
- Adhere to the spec outlined in OpenFL_Build_Chain_Asset_System_Deep_dive.md and IMPORTANT_INSTRUCTIONS.md
-
\ No newline at end of file
+ - There is sample code in the Export/haxe directory. We want our own src/ManifestResources.hx to mirror the implementation in Export/haxe/ManifestResources.hx
+ - Mirror preload logic from the Export/haxe directory into our own files.
+ - We also want to preload our assets using a similar approach using the ManifestResource and doing related initialization in ApplicationMain.hx
+
+# Implementation details:
+
+ - macros/AssetMacro.hx
+ - Implement a @:assets decorator that allows specifying assets with the same parameters that openfl/lime use in project.xml
+ - These assets will be defined in Assets.hx
+ - Generate an asset manifest `default.json` in a folder `manifest` in the hxcpp output directory (the same path the built binary gets put into) (get the path for this from the haxe compiler at build time) as defined with the `-cpp` flag in build.hxml
+ - Copy assets into the hxcpp output directory similarly to how lime and openfl do this
+ - Assets.hx
+ - as stated previously, the @:asset decorator will be used here to specify assets for the compiler to copy to the build output directory at compile time
+ - Main.hx
+ - This is the entrypoint for game specific code, no need to touch this yet.
+ - ApplicationMain.hx
+ - This is the actual entrypoint of the application. This sets up the lime/openfl application, window and stage. Also this is responsible for preloading assets.
+ - ManifestResources.hx
+ - This will be left the same as the sample in Export/haxe/ManifestResources.hx
diff --git a/standalone-openfl-app/IMPORTANT_INSTRUCTIONS.md b/standalone-openfl-app/IMPORTANT_INSTRUCTIONS.md
index 6dcb57f8..2038a922 100644
--- a/standalone-openfl-app/IMPORTANT_INSTRUCTIONS.md
+++ b/standalone-openfl-app/IMPORTANT_INSTRUCTIONS.md
@@ -19,4 +19,19 @@ We already know that it makes some calls to lime under the hood which has a simi
The current project is built to create an openfl app using the hxml build system and bypass lime's/ openfl's build system entirely.
-We are currently working on asset bundling, this is proving to be a difficult task. Please document how openfl does this in a file called BUILD_CHAIN_DOCUMENTATION_OPENFL.md
\ No newline at end of file
+We are currently working on asset bundling, this is proving to be a difficult task. Please document how openfl does this in a file called OpenFL_Build_Chain_Asset_System_Deep_Dive.md
+
+## What we need:
+- `src/Assets.hx`
+ - define asset paths in a similar way to how openfl does this in the project.xml file. This will be done using a custom meta tag `@:Assets`
+ - We will have a macro in `src/macros/AssetMacro.hx` to process these meta tags, build a manifest, and copy the assets into the `--cpp` output directory specified in `build.hxml`
+- `src/macros/AssetMacro.hx`
+ - Process `@:Assets` metatags defined in `src/Assets.hx`
+ - Build manifest in a `manifest` subdirectory the `--cpp` output directory specified in `build.hxml`
+ - copy the assets into the `assets` subdirectory in the `--cpp` output directory
+- `src/ManifestResources.hx`
+ - initialize the Asset Libraries from the manifest files
+- `src/ApplicationMain.hx`
+ - Initialize `src/ManifestResources.hx`
+ - bootstrap the openfl application
+ - add `src/Main.hx` to the application
\ No newline at end of file
diff --git a/standalone-openfl-app/LIME_PROJECT_FORMAT.md b/standalone-openfl-app/LIME_PROJECT_FORMAT.md
new file mode 100644
index 00000000..a2c86949
--- /dev/null
+++ b/standalone-openfl-app/LIME_PROJECT_FORMAT.md
@@ -0,0 +1,734 @@
+---
+title: XML Format
+---
+
+## Overview
+
+Usually a simple project file is all you need to build projects using Lime or OpenFL, but it can be extended based on your needs. Here is a reference of what you can do.
+
+### XML Schema
+
+If you are using an XSD aware XML editor you can use the following declaration to enable XML validation and type hinting/auto completion.
+
+```xml
+
+
+
+```
+
+### Conditionals
+
+First, every node in the project file format supports `if` and `unless` attributes. These are conditional values to help you customize your build process, based upon a number of values. Here are some of the default values:
+
+- mobile, desktop or web
+- ios, android, windows, mac, linux or html5
+- cpp, neko, flash or js
+
+You can [``](#set) or [``](#define) values for conditional logic:
+
+```xml
+
+
+
+
+
+```
+
+Both also support a `value` attribute, which can be retrieved later using the `${}` syntax.
+
+```xml
+
+
+
+
+```
+
+You can also check values that were defined on the command line:
+
+```sh
+lime test flash -Dblue
+```
+
+```xml
+
+```
+
+If you need to have multiple values in a conditional, spaces imply an "and" and vertical bars imply an "or", like this:
+
+```xml
+
+```
+
+If a value isn't found, either because it was never set or because of [``](#unset)/[``](#undefine), it will be treated as `false`.
+
+### Build info
+
+The `${}` syntax can get information about the build. You can use this data in a condition, print it, or pass it along to Haxe:
+
+```xml
+
+
+
+```
+
+### Duplicates
+
+You can include more than one copy of each tag, so do not worry about putting it all in one place. All of the values you define will be used. If you define the same value more than once, the last definition will be used.
+
+```xml
+
+
+```
+
+### include.xml
+
+If you create a haxelib, you can add _include.xml_ to the top-level directory. The build tools will automatically add the contents of the file to the user's project. You can use this to add binary dependencies, additional classpaths, etc.
+
+## XML Tag Glossary
+
+### app
+
+The `` tag sets values important to building your project, including the entry point (main class), the output file directory, or if you want to customize the executable filename or define a custom preloader for a web platform:
+
+```xml
+
+
+```
+
+You can retrieve this information later:
+
+```xml
+
+```
+
+### architecture
+
+Use `` tags to set or exclude target-specific architectures. Depending on the target, values can include `arm64`, `armv7`, `armv7s`, `armv6`, `armv5`, `x86`, and `x64`.
+
+By default, the only architecture built for Android will be `armv7`. For example, if you want to enable `armv6` and disable `armv7` you would set the `` tag to:
+
+```xml
+
+```
+
+### assets
+
+Use asset nodes to add resources to your project, available using `lime.Assets`.
+
+The path attribute can point to either a file or a directory. These files will be copied (or embedded) in your final project, and can be accessed using the `lime.Assets` class.
+
+For example, if you include the following node in your project file:
+
+```xml
+
+```
+
+You can access it in your application like this:
+
+```haxe
+var bitmapData = Assets.getBitmapData ("images/MyImage.png");
+```
+
+The target path will mirror the source path by default, but you also can include a rename attribute, if you wish to use a different target path. The `lime.Assets` class will use the _target_ path by default, so using the rename attribute will alter the names you use to reference your files.
+
+If you would prefer to set the ID for your asset file yourself, use an "id" attribute. This only applies to asset nodes which point to a file, not a directory path.
+
+When pointing to a directory, you can use the include or exclude attributes to specify patterns for including files automatically. Wildcards are supported. To include all the files under the directory, for example, use an include value of "*". You can separate multiple patterns using "\|" characters.
+
+You can nest assets nodes inside of each other. If you specify a directory in the top assets node, its path will be appended to the paths you specify in subsequent nodes.
+
+The type for each file will be determined automatically, based on each file extension, but you can use the type attribute to set it for the file or directory yourself. If you are nesting a node inside of another assets node, you can also use the name of the type as the name of your node.
+
+These are the current types:
+
+- binary
+- font
+- image
+- music
+- sound
+- template
+- text
+
+Some targets can only support playing one music file at a time. You should use "music" for files which are designed to play as background music, and "sound" for all other audio. "binary" and "text" are generic types which are available as a ByteArray or String in your application. Most targets can use them interchangeably.
+
+If an asset is specified as "template", it will not be copied/embedded as an ordinary asset, but instead will be copied to the root directory of your project, so you can replace any of the template HX, HXML or platform-specific files for the target.
+
+```xml
+
+
+
+
+
+
+
+
+
+```
+
+### certificate
+
+Use `` tags to add a keystore for release signing on certain platforms.
+
+If you do not include the password attribute, you will be prompted for your certificate password at the command-line.
+
+For Android, the alias will be set to the file name of your certificate by default, without the extension. If the alias name is different, you can use the alias attribute.
+
+If you have set the password attribute, the alias_password attribute will default to the same value. Otherwise you can add an alias-password attribute to specify a different value.
+
+```xml
+
+```
+
+iOS does not use a certificate `path` and `password`, but instead uses a `team-id` attribute matching the ID provided in the Apple Developer portal for your team:
+
+```xml
+
+```
+
+You can retrieve this information later:
+
+```xml
+
+```
+
+### classpath
+
+Same as [``](#source).
+
+### compilerflag
+
+Same as [``](#haxeflag).
+
+### config
+
+Use `` tags to set platform-specific values. See [config options](config) for the full list.
+
+```xml
+
+
+
+
+
+```
+
+You can retrieve this information later:
+
+```xml
+
+
+```
+
+### define
+
+Use `` tags to set variables for conditional logic. See the [Conditionals](#conditionals) section above, and see [``](#undefine) to remove a defined value.
+
+```xml
+
+
+```
+
+These values will be available in Haxe and in [templates](#template). For templates, use the syntax `::DEFINE_CUSTOM_VALUE::`. Hyphens are converted to underscores in both cases.
+
+### dependency
+
+Use `` tags to specify native frameworks or references that are required to compile your project, as well as additional libraries you need copied.
+
+When targeting [iOS](../../advanced-setup/ios/), it may be used to add a native framework.
+
+```xml
+
+```
+
+When targeting [Android](../../advanced-setup/android/), it may be used to add a native library.
+
+```xml
+
+```
+
+When targeting [Adobe AIR](../../advanced-setup/air/), it may be used to add a native extension.
+
+```xml
+
+```
+
+### echo
+
+Prints a specified message to the console.
+
+```xml
+
+```
+
+The `` element is often combined with `if` or `unless`.
+
+```xml
+
+```
+
+Or it may be added inside a `` element:
+
+```xml
+
+
+
+```
+
+### error
+
+Logs an error with `lime.utils.Log.error()` which by default throws `value` message and stops compilation (if `lime.utils.Log.throwErrors` is set to `true`).
+
+The `` element is often combined with `if` or `unless`.
+
+```xml
+
+
+
+```
+
+### haxedef
+
+Use `` tags to add Haxe defines (similar to using a [``](#haxeflag) with "-D"):
+
+```xml
+
+```
+
+### haxeflag
+
+Use `` tags to add additional [Haxe compiler arguments](https://haxe.org/manual/compiler-usage.html):
+
+```xml
+
+```
+
+### haxelib
+
+Use `` tags to include [Haxe libraries](https://lib.haxe.org):
+
+```xml
+
+```
+
+You can specify a version or path, if you prefer:
+
+```xml
+
+
+```
+
+By default, an error will be thrown if the requested library isn't installed. You can set `optional` to continue without the library instead.
+
+```xml
+
+```
+
+If you have multiple Haxelib repository folders, you can select one using the `repository` attribute. The folder you select must include a copy of Lime (and OpenFL, if applicable).
+
+```xml
+
+```
+
+### icon
+
+Use `` nodes to add icon files to your project. When the command-line tools request icons for a target platform, it will either use an exact size match you have provided, or it will attempt to find the closest match possible and resize. If you include an SVG vector icon, it should prefer this file over resizing bitmap files.
+
+```xml
+
+
+
+```
+
+### include
+
+Use `` tags to add the tags found in another project file, or to find an _include.xml_ file in the target directory:
+
+```xml
+
+
+```
+
+### java
+
+Use `` tags to add Java classes to the project when targeting Android:
+
+```xml
+
+```
+
+### language
+
+Adds a language to the list of supported languages (by default the list is empty).
+
+```xml
+
+```
+
+### launchImage
+
+Sets the path to launch image of the app (image which will be shown at application start up)
+
+```xml
+
+```
+
+### launchStoryboard
+
+Sets the launch screen storyboard (useful only for iOS development).
+
+```xml
+
+```
+
+or
+
+```xml
+
+```
+
+You can also use `template` for this purpose.
+
+#### The default template
+
+The launch storyboard feature uses Haxe templates and your _project.xml_ configuration to generate an Xcode storyboard file. Lime includes one default storyboard template `splash.storyboard`, which can be configured with the following options.
+
+```xml
+
+
+
+
+
+
+```
+
+`template` is the specific storyboard template you’re using, chosen from the templates available at `templates/ios/storyboards`.
+
+`assetsPath` is the path from your openfl/lime project root to where your launch storyboard images are saved.
+
+`bg` is a hexadecimal formatted color to use as the background, in case you’re not using a full-screen content mode.
+
+`contentMode` determines how the image scales to fit the screen.
+
+- `center` is unscaled
+- `scaleAspectFill` scales to fill the entire screen, with original aspect ratio
+- `scaleAspectFit` scales to fit inside the screen (letterbox), with original aspect ratio
+- `scaleToFill` stretches the image to fill the screen
+
+There are three optional attributes, (`portrait`, `landscape` and `ipad`) which you can choose from based on the target devices and orientation of your game. (The above example includes just ipad and portrait.)
+
+- `ipad` determines the image to use for iPads.
+- `portrait` determines the image to use for iPods and iPhones in portrait orientation.
+- `landscape` determines the image to use for iPods and iPhones in landscape orientation.
+
+Finally, you have the `imageset` child elements. For each imageset, lime looks for `{name}.png`, `{name}@2x.png`, and `{name}@3x.png` in the specified `assetsPath`, copying any of those that exist into an Xcode imageset. Most iPhones these days require the @2x or @3x image, while iPads require @2x.
+
+#### About templates and custom storyboard
+
+`template`, `assetsPath`, and the `imageset` elements are standard parts of the configuration. All the other attributes listed above are available based on the chosen default template, `splash.storyboard`.
+
+If the default template doesn’t meet your needs, you have two options, but both require you to open your exported iOS project in Xcode and create your own storyboard.
+
+1. Take the storyboard you built in Xcode and put it into your project. In this case, you would use the name or path attribute instead of template, and you would have no template-specific attributes to set, but you would still need to provide the appropriate imagesets.
+
+ ```xml
+
+
+
+ ```
+
+2. Using the default template as an example, take the storyboard you built in Xcode and add it to your lime templates. You would use it in the same manner as the default template, but use any attributes you specified instead.
+
+### library
+
+All assets go into the "default" library, but by adding `` tags it is possible to modify the default library and also define additional libraries and load/unload them as needed.
+
+To disable preloading on the default library:
+
+```xml
+
+```
+
+To load assets at runtime:
+
+```haxe
+Assets.loadLibrary ("default").onComplete (function (library) {
+
+ var bitmapData = Assets.getBitmapData ("default:image.png");
+ // or
+ var bitmapData = Assets.getBitmapData ("image.png");
+ // "default:" prefix is implied, if no library prefix is included
+});
+```
+
+#### Using Additional Asset Libraries
+
+You can easily add assets to libraries other than the "default" library. These are not preloaded by default, unless you add:
+
+```xml
+
+```
+
+Then to have certain assets allocated to the above library:
+
+```xml
+
+```
+
+Be sure to specify the correct library when retrieving the assets in your code. See the above example for using the library prefix.
+
+You can also use `Assets.unloadLibrary` when you are doing using those resources.
+
+### log
+
+Logs an error (see [``](#error)), warning or info message.
+
+Examples:
+
+```xml
+
+
+
+
+
+```
+
+The `` element is often combined with `if` or `unless`.
+
+```xml
+
+```
+
+```xml
+
+```
+
+Or it may be added inside a `` element:
+
+```xml
+
+
+
+```
+
+### meta
+
+Use `` tags to add information about your application, which usually will not affect how the application runs, but how it is identified to the target operating system or on an application store:
+
+```xml
+
+```
+
+You can retrieve this information later:
+
+```xml
+
+```
+
+### module
+
+More to come.
+
+### ndll
+
+You can use `` tags to include native libraries. These are usually located under an "ndll" directory, with additional directories based upon the target platform. Usually an `` tag will be included as a part of an extension, and is rare to be used directly:
+
+```xml
+
+```
+
+### output
+
+**Deprecated!** Use the [``](#app) element instead.
+
+Can be used for setting app file name, app path and app swf-version:
+
+```xml
+
+
+
+```
+
+### path
+
+Use `` tags to add directories to your system's PATH environment variable.
+
+```xml
+
+```
+
+### postbuild
+
+Lets you set post-build commands such as Haxe code (interpeted by the Haxe interpreter), a run file command, or a console command.
+
+```xml
+
+
+
+
+```
+
+### prebuild
+
+Lets you set pre-build commands such as Haxe code (interpeted by the Haxe interpreter), a run file command, or a console command:
+
+```xml
+
+
+
+
+```
+
+### preloader
+
+**Deprecated!** Use [``](#app) instead.
+
+```xml
+
+```
+
+### sample
+
+In a library that targets Lime, makes a sample available using the `lime create` command.
+
+```xml
+
+```
+
+Then you can use:
+
+```sh
+lime create flixel:Arcade
+```
+
+### section
+
+The `` tag is used to group other tags together. This is usually most valuable when combined with "if" and/or "unless" logic:
+
+```xml
+
+
+
+```
+
+### set
+
+Use `` tags to set variables for conditional logic. See the [Conditionals](#conditionals) section above, and see [``](#unset) to remove a set value.
+
+```xml
+
+
+```
+
+These values will be available in [templates](#template) using the syntax `::SET_CUSTOM_VALUE::`. (Hyphens are converted to underscores.)
+
+### setenv
+
+Use `` tags to set environment variables. See the [Conditionals](#conditionals) section above.
+
+```xml
+
+```
+
+### source
+
+Use `` tags to add Haxe class paths:
+
+```xml
+
+```
+
+If you are using `@:file`, `@:bitmap`, `@:sound` or `@:file` tags in your project, be sure that the asset files are available within your Haxe source paths.
+
+### splashscreen
+
+Same as [``](#launchimage).
+
+### ssl
+
+Not implemented
+
+### swf
+
+See [``](#library).
+
+### target
+
+Lets you redefine the build process for a specific target by running a custom haxelib command. This might be useful if you want to use your own library for building your project, i.e. you know what you're doing and you know how the Lime build system works.
+
+```xml
+
+```
+
+### template
+
+Use `` tags to add paths which can override the templates used by the command-line tools.
+
+You can add a full template path like this:
+
+```xml
+
+```
+
+Otherwise, you can override a single file like this:
+
+```xml
+
+```
+
+### templatepath
+
+See [``](#template).
+
+```xml
+
+```
+
+### undefine
+
+Unsets a previously defined flag. See entry for [``](#define).
+
+```xml
+
+```
+
+### unset
+
+Unsets a previously set value. See entry for [``](#set).
+
+```xml
+
+
+```
+
+### window
+
+You can use `` tags to control how an application will be initialized. This includes the screen resolution and background color, as well as other options, such as whether hardware should be allowed or display mode flags.
+
+By default, mobile platforms use a window width and height of 0, which is a special value that uses the resolution of the current display. This is available on desktop platforms, but usually it is recommended to enable the `fullscreen` flag instead, and to set the `width` and `height` values to a good windowed resolution. There is a special `fps="0"` value for HTML5, which is default, which uses "requestAnimationFrame" instead of forcing a frame rate.
+
+```xml
+
+
+
+
+```
+
+The `orientation` value expects either "portrait" or "landscape" ... the default is "auto" which allows the operating system to decide which orientation to use.
+
+You can retrieve this information later:
+
+```xml
+
+```
diff --git a/standalone-openfl-app/Makefile b/standalone-openfl-app/Makefile
new file mode 100644
index 00000000..e2130bc0
--- /dev/null
+++ b/standalone-openfl-app/Makefile
@@ -0,0 +1,24 @@
+# Makefile for standalone OpenFL application
+
+# Default target
+.PHONY: all
+all: build
+
+# Build the application
+.PHONY: build
+build:
+ haxe build.hxml
+
+# Run the compiled application
+.PHONY: run
+run:
+ bash -c "cd bin/cpp && ./ApplicationMain"
+
+# Build and run the application
+.PHONY: test
+test: build run
+
+# Clean build artifacts
+.PHONY: clean
+clean:
+ rm -rf bin/cpp
diff --git a/standalone-openfl-app/assets/data/config.json b/standalone-openfl-app/assets/data/config.json
new file mode 100644
index 00000000..544b7b4d
--- /dev/null
+++ b/standalone-openfl-app/assets/data/config.json
@@ -0,0 +1,3 @@
+{
+
+}
\ No newline at end of file
diff --git a/standalone-openfl-app/assets/images/logo.png b/standalone-openfl-app/assets/images/logo.png
new file mode 100644
index 00000000..1a410954
Binary files /dev/null and b/standalone-openfl-app/assets/images/logo.png differ
diff --git a/standalone-openfl-app/build.hxml b/standalone-openfl-app/build.hxml
index 6c456b64..c3d7fabe 100644
--- a/standalone-openfl-app/build.hxml
+++ b/standalone-openfl-app/build.hxml
@@ -1,51 +1,28 @@
--cp src
--lib lime
+-main ApplicationMain
+
-lib openfl
--D lime-default
--D openfl-legacy
--D native
--D lime-cffi
--D lime-native
--D tools
-
-# Run asset macro to build the manifest
---macro macros.AssetMacro.buildAssets()
-
-# Entry point
--main ApplicationMain
-
-# C++ target - adjust as needed
--cpp bin/cpp
-
-# Debug mode
--debug
-
--lib hxcpp
+-lib lime
-lib actuate
--lib hxp
--cp assets
--D openfl=8.9.5
--D lime=7.9.0
--D app_file=src/Main.hx
--D meta.buildNumber="1.0.0"
--D meta.company="YourCompanyName"
--D meta.title="YourApplicationTitle"
--D meta.packageName="com.yourcompany.yourapp"
--D meta.version="1.0.0"
--D WIN_WIDTH=800
--D WIN_HEIGHT=600
--D allowHighDPI=true
--D alwaysOnTop=false
--D borderless=false
--D fullscreen=false
--D hidden=false
--D resizable=true
--D fps=60
--D background=0xFFFFFF
--D antialiasing=true
--D hardware=true
--D vsync=true
--D depthBuffer=true
--D stencilBuffer=false
--D parameters="{}"
\ No newline at end of file
+-cp src
+-D lime-harfbuzz
+-D lime-openal
+-D lime-threads
+-D tools=8.2.2
+-D lime-cairo
+-D lime-opengl
+# -D no-compilation
+-D native
+-D lime-curl
+-D lime-native
+-D lime-vorbis
+-D openfl-native
+-D lime-cffi
+-D linux
+-D desktop
+--remap flash:openfl
+-cpp bin/cpp
+--macro keep("Main")
+--macro keep("Assets")
+--macro keep("AssetMacro")
+# --macro macros.MacroLoader.run()
\ No newline at end of file
diff --git a/standalone-openfl-app/manifest/default.json b/standalone-openfl-app/manifest/default.json
deleted file mode 100644
index 1cda77d0..00000000
--- a/standalone-openfl-app/manifest/default.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "name": "default",
- "libraryType": null,
- "rootPath": ".",
- "assets": [
- {
- "path": "assets/data/img/placeholder.txt",
- "id": "data/img/placeholder.txt",
- "type": "text"
- }
- ],
- "version": 2,
- "libraryArgs": []
-}
\ No newline at end of file
diff --git a/standalone-openfl-app/src/ApplicationMain.hx b/standalone-openfl-app/src/ApplicationMain.hx
index 2fdf4c84..cd9f06cd 100644
--- a/standalone-openfl-app/src/ApplicationMain.hx
+++ b/standalone-openfl-app/src/ApplicationMain.hx
@@ -1,136 +1,331 @@
package;
-import openfl.Lib;
-import lime.utils.AssetType;
-import lime.tools.Asset;
-import lime.ui.WindowAttributes;
-import openfl.system.System;
-import openfl.display.Application;
-import openfl.display.Stage;
-import openfl.events.Event;
-import openfl.events.FullScreenEvent;
+#if macro
+import haxe.macro.Compiler;
+import haxe.macro.Context;
+import haxe.macro.Expr;
+#end
+
@:access(lime.app.Application)
@:access(lime.system.System)
@:access(openfl.display.Stage)
@:access(openfl.events.UncaughtErrorEvents)
-class ApplicationMain {
- public static function main() {
- lime.system.System.__registerEntryPoint("src/DocumentClass.hx", create);
+@:dox(hide)
+class ApplicationMain
+{
+ #if !macro
+ public static function main()
+ {
+ lime.system.System.__registerEntryPoint("MinimalApplication", create);
+
+ #if (js && html5)
+ #if (munit || (utest && openfl_enable_utest_legacy_mode))
+ lime.system.System.embed("MinimalApplication", null, 800, 600);
+ #end
+ #else
create(null);
+ #end
}
- // public static function create(config):Void {
- // try {
- // trace("Creating minimal application");
- // var app = new Application();
-
- // // Initialize assets via macro-generated code
- // Assets.initializeAssets();
- // trace("Assets initialized");
-
- // // Minimal metadata
- // app.meta["name"] = "Debug Application";
-
- // // Simple window
- // var attributes:WindowAttributes = {
- // height: 600,
- // width: 800,
- // title: "Debug Window"
- // };
-
- // app.createWindow(attributes);
-
- // // Skip preloader, just call start directly
- // start(app.window.stage);
-
- // var result = app.exec();
- // lime.system.System.exit(result);
- // } catch (e:Dynamic) {
- // trace("Error: " + e);
- // }
- // }
-
public static function create(config):Void
{
- var app = new Application();
- app.meta["build"] = "1.0.0"; // Replace with actual build number
- app.meta["company"] = "Your Company"; // Replace with your company name
- app.meta["file"] = "src/Main.hx"; // Path to your main application file
- app.meta["name"] = "Your Application"; // Replace with your application title
- app.meta["packageName"] = "com.yourcompany.yourapp"; // Replace with your package name
- app.meta["version"] = "1.0.0"; // Replace with your application version
- // var asset = new Asset();
- // asset.sourcePath = "src/assets"; // Path to your assets
- // asset.targetPath = "assets"; // Target path for assets
- // asset.type = AssetType.IMAGE; // Type of asset
- if (config.hxtelemetry != null)
- {
- app.meta["hxtelemetry-allocations"] = config.hxtelemetry.allocations;
- app.meta["hxtelemetry-host"] = config.hxtelemetry.host;
- }
- var attributes:WindowAttributes = {
- allowHighDPI: true, // Set to true or false as needed
- alwaysOnTop: false, // Set to true or false as needed
- borderless: false, // Set to true or false as needed
- frameRate: 60, // Set your desired frame rate
- height: 600, // Set your desired window height
- hidden: false, // Set to true or false as needed
- maximized: false, // Set to true or false as needed
- minimized: false, // Set to true or false as needed
- resizable: true, // Set to true or false as needed
- title: "Your Application", // Replace with your application title
- width: 800, // Set your desired window width
- x: 100, // Set your desired x position
- y: 100 // Set your desired y position
- };
- app.createWindow(attributes);
- var preloader = getPreloader();
- app.preloader.onProgress.add(function(loaded, total)
- {
- @:privateAccess preloader.update(loaded, total);
- });
- app.preloader.onComplete.add(function()
- {
- @:privateAccess preloader.start();
- });
- preloader.onComplete.add(start.bind(app.window.stage));
- app.preloader.load();
- var result = app.exec();
- lime.system.System.exit(result);
+ var app = new openfl.display.Application();
+
+ #if !disable_preloader_assets
+ ManifestResources.init(config);
+ #end
+
+ app.meta["build"] = "48";
+ app.meta["company"] = "Company Name";
+ app.meta["file"] = "MinimalApplication";
+ app.meta["name"] = "MinimalApplication";
+ app.meta["packageName"] = "com.sample.minimalapplication";
+ app.meta["version"] = "1.0.0";
+
+
+
+ #if !flash
+
+ var attributes:lime.ui.WindowAttributes = {
+ allowHighDPI: false,
+ alwaysOnTop: false,
+ borderless: false,
+ // display: 0,
+ element: null,
+ frameRate: 30,
+ #if !web fullscreen: false, #end
+ height: 600,
+ hidden: #if munit true #else false #end,
+ maximized: false,
+ minimized: false,
+ parameters: {},
+ resizable: true,
+ title: "MinimalApplication",
+ width: 800,
+ x: null,
+ y: null,
+ };
+
+ attributes.context = {
+ antialiasing: 0,
+ background: 16777215,
+ colorDepth: 32,
+ depth: true,
+ hardware: true,
+ stencil: true,
+ type: null,
+ vsync: false
+ };
+
+ if (app.window == null)
+ {
+ if (config != null)
+ {
+ for (field in Reflect.fields(config))
+ {
+ if (Reflect.hasField(attributes, field))
+ {
+ Reflect.setField(attributes, field, Reflect.field(config, field));
+ }
+ else if (Reflect.hasField(attributes.context, field))
+ {
+ Reflect.setField(attributes.context, field, Reflect.field(config, field));
+ }
+ }
+ }
+
+ #if sys
+ lime.system.System.__parseArguments(attributes);
+ #end
+ }
+
+ app.createWindow(attributes);
+
+ #elseif air
+ app.window.title = "MinimalApplication";
+ #else
+ app.window.context.attributes.background = 16777215;
+ app.window.frameRate = 30;
+ #end
+
+ var preloader = getPreloader();
+ app.preloader.onProgress.add (function(loaded, total)
+ {
+ @:privateAccess preloader.update(loaded, total);
+ });
+ app.preloader.onComplete.add(function()
+ {
+ @:privateAccess preloader.start();
+ });
+
+ preloader.onComplete.add(start.bind((cast app.window:openfl.display.Window).stage));
+
+ #if !disable_preloader_assets
+ for (library in ManifestResources.preloadLibraries)
+ {
+ app.preloader.addLibrary(library);
+ }
+
+ for (name in ManifestResources.preloadLibraryNames)
+ {
+ app.preloader.addLibraryName(name);
+ }
+ #end
+
+ app.preloader.load();
+
+ var result = app.exec();
+
+ #if (sys && !ios && !nodejs && !emscripten)
+ lime.system.System.exit(result);
+ #end
}
- public static function start(stage:Stage):Void {
- if (stage.__uncaughtErrorEvents.__enabled) {
- try {
- // Instantiate and add DocumentClass
- var documentClass = new DocumentClass();
- Lib.current.addChild(documentClass);
-
+ public static function start(stage:openfl.display.Stage):Void
+ {
+ #if flash
+ ApplicationMain.getEntryPoint();
+ #else
+ if (stage.__uncaughtErrorEvents.__enabled)
+ {
+ try
+ {
+ ApplicationMain.getEntryPoint();
- // Then dispatch events
- stage.dispatchEvent(new Event(Event.RESIZE, false, false));
- if (stage.window.fullscreen) {
- stage.dispatchEvent(new FullScreenEvent(FullScreenEvent.FULL_SCREEN, false, false, true, true));
+ stage.dispatchEvent(new openfl.events.Event(openfl.events.Event.RESIZE, false, false));
+
+ if (stage.window.fullscreen)
+ {
+ stage.dispatchEvent(new openfl.events.FullScreenEvent(openfl.events.FullScreenEvent.FULL_SCREEN, false, false, true, true));
}
- } catch (e:Dynamic) {
- stage.__handleError(e);
}
- } else {
- // Instantiate and add DocumentClass
- var documentClass = new DocumentClass();
- Lib.current.addChild(documentClass);
-
-
- // Then dispatch events
- stage.dispatchEvent(new Event(Event.RESIZE, false, false));
- if (stage.window.fullscreen) {
- stage.dispatchEvent(new FullScreenEvent(FullScreenEvent.FULL_SCREEN, false, false, true, true));
+ catch (e:Dynamic)
+ {
+ #if !display
+ stage.__handleError(e);
+ #end
}
}
+ else
+ {
+ ApplicationMain.getEntryPoint();
+
+ stage.dispatchEvent(new openfl.events.Event(openfl.events.Event.RESIZE, false, false));
+
+ if (stage.window.fullscreen)
+ {
+ stage.dispatchEvent(new openfl.events.FullScreenEvent(openfl.events.FullScreenEvent.FULL_SCREEN, false, false, true, true));
+ }
+ }
+ #end
+ }
+ #end
+
+ macro public static function getEntryPoint()
+ {
+ var hasMain = false;
+
+ switch (Context.follow(Context.getType("Main")))
+ {
+ case TInst(t, params):
+
+ var type = t.get();
+ for (method in type.statics.get())
+ {
+ if (method.name == "main")
+ {
+ hasMain = true;
+ break;
+ }
+ }
+
+ if (hasMain)
+ {
+ return Context.parse("@:privateAccess Main.main()", Context.currentPos());
+ }
+ else if (type.constructor != null)
+ {
+ return macro
+ {
+ var current = stage.getChildAt (0);
+
+ if (current == null || !(current is openfl.display.DisplayObjectContainer))
+ {
+ current = new openfl.display.MovieClip();
+ stage.addChild(current);
+ }
+
+ new DocumentClass(cast current);
+ };
+ }
+ else
+ {
+ Context.fatalError("Main class \"Main\" has neither a static main nor a constructor.", Context.currentPos());
+ }
+
+ default:
+
+ Context.fatalError("Main class \"Main\" isn't a class.", Context.currentPos());
+ }
+
+ return null;
}
- public static function getPreloader() {
- return new openfl.display.Preloader();
+ macro public static function getPreloader()
+ {
+
+ return macro
+ {
+ new openfl.display.Preloader(new openfl.display.Preloader.DefaultPreloader());
+ };
+
+ }
+
+ #if !macro
+ @:noCompletion @:dox(hide) public static function __init__()
+ {
+ var init = lime.app.Application;
+
+ #if neko
+ // Copy from https://github.com/HaxeFoundation/haxe/blob/development/std/neko/_std/Sys.hx#L164
+ // since Sys.programPath () isn't available in __init__
+ var sys_program_path = {
+ var m = neko.vm.Module.local().name;
+ try
+ {
+ sys.FileSystem.fullPath(m);
+ }
+ catch (e:Dynamic)
+ {
+ // maybe the neko module name was supplied without .n extension...
+ if (!StringTools.endsWith(m, ".n"))
+ {
+ try
+ {
+ sys.FileSystem.fullPath(m + ".n");
+ }
+ catch (e:Dynamic)
+ {
+ m;
+ }
+ }
+ else
+ {
+ m;
+ }
+ }
+ };
+
+ var loader = new neko.vm.Loader(untyped $loader);
+ loader.addPath(haxe.io.Path.directory(#if (haxe_ver >= 3.3) sys_program_path #else Sys.executablePath() #end));
+ loader.addPath("./");
+ loader.addPath("@executable_path/");
+ #end
+ }
+ #end
+}
+
+#if !macro
+@:build(DocumentClass.build())
+@:keep @:dox(hide) class DocumentClass extends Main {}
+#else
+class DocumentClass
+{
+ macro public static function build():Array
+ {
+ var classType = Context.getLocalClass().get();
+ var searchTypes = classType;
+
+ while (searchTypes != null)
+ {
+ if (searchTypes.module == "openfl.display.DisplayObject" || searchTypes.module == "flash.display.DisplayObject")
+ {
+ var fields = Context.getBuildFields();
+
+ var method = macro
+ {
+ current.addChild(this);
+ super();
+ dispatchEvent(new openfl.events.Event(openfl.events.Event.ADDED_TO_STAGE, false, false));
+ }
+
+ fields.push({ name: "new", access: [ APublic ], kind: FFun({ args: [ { name: "current", opt: false, type: macro :openfl.display.DisplayObjectContainer, value: null } ], expr: method, params: [], ret: macro :Void }), pos: Context.currentPos() });
+
+ return fields;
+ }
+
+ if (searchTypes.superClass != null)
+ {
+ searchTypes = searchTypes.superClass.t.get();
+ }
+ else
+ {
+ searchTypes = null;
+ }
+ }
+
+ return null;
}
}
+#end
diff --git a/standalone-openfl-app/src/Assets.hx b/standalone-openfl-app/src/Assets.hx
index 70025a70..97ded63a 100644
--- a/standalone-openfl-app/src/Assets.hx
+++ b/standalone-openfl-app/src/Assets.hx
@@ -1,8 +1,29 @@
package;
-class Assets{
-
+/**
+ * Asset definition class using meta tags instead of project.xml
+ * The AssetMacro will process these declarations at compile time
+ */
+@:keep
+@:build(macros.AssetMacro.build()) // Fix: use fully qualified path with package name
+class Assets {
+ // Define image assets
+ @:Assets("assets/images/", "images")
+ public static var images:String;
-
-
+ // Define sound assets
+ @:Assets("assets/sounds/", "sounds")
+ public static var sounds:String;
+
+ // Define font assets
+ @:Assets("assets/fonts/", "fonts")
+ public static var fonts:String;
+
+ // Define data assets
+ @:Assets("assets/data/", "data")
+ public static var data:String;
+
+ // You can also define individual files if needed
+ @:Assets("assets/images/logo.png", "images", "logo.png")
+ public static var logo:String;
}
\ No newline at end of file
diff --git a/standalone-openfl-app/src/DocumentClass.hx b/standalone-openfl-app/src/DocumentClass.hx
deleted file mode 100644
index 715835f9..00000000
--- a/standalone-openfl-app/src/DocumentClass.hx
+++ /dev/null
@@ -1,19 +0,0 @@
-package;
-
-import openfl.events.EventDispatcher;
-import openfl.display.Sprite;
-import openfl.events.Event;
-import openfl.display.DisplayObjectContainer;
-import openfl.events.MouseEvent;
-
-class DocumentClass extends Sprite
-{
- public function new()
- {
- super();
- dispatchEvent(new openfl.events.Event(openfl.events.Event.ADDED_TO_STAGE, false, false));
- graphics.beginFill(0xFFF00F, 1);
- graphics.drawRect(0, 0, 800, 600);
- graphics.endFill();
- }
-}
\ No newline at end of file
diff --git a/standalone-openfl-app/src/Main.hx b/standalone-openfl-app/src/Main.hx
index 4e58b05a..79356a69 100644
--- a/standalone-openfl-app/src/Main.hx
+++ b/standalone-openfl-app/src/Main.hx
@@ -1,20 +1,22 @@
package;
-import openfl.utils.AssetType;
import openfl.display.Sprite;
-import openfl.Assets;
+import openfl.Lib;
+import sys.FileSystem;
+import Assets;
class Main extends Sprite {
public function new() {
super();
-
+
+ Lib.current.addChild(this);
+
// Draw background to verify app is running
graphics.beginFill(0x3498db, 1);
graphics.drawRect(0, 0, 800, 600);
graphics.endFill();
- var testAsset = Assets.getText("assets/data/img/placeholder.txt");
- trace(testAsset);
-
+ var testAsset = openfl.Assets.getText("img/placeholder.txt");
+ trace("Successfully loaded asset: " + testAsset);
}
}
diff --git a/standalone-openfl-app/src/ManifestResources.hx b/standalone-openfl-app/src/ManifestResources.hx
index 25d37b90..04eee418 100644
--- a/standalone-openfl-app/src/ManifestResources.hx
+++ b/standalone-openfl-app/src/ManifestResources.hx
@@ -1,118 +1,40 @@
package;
-import haxe.io.Bytes;
import haxe.io.Path;
-import lime.utils.AssetBundle;
import lime.utils.AssetLibrary;
import lime.utils.AssetManifest;
-import lime.utils.Assets;
-
-#if sys
+import lime.utils.Assets as LimeAssets;
import sys.FileSystem;
-#end
-#if disable_preloader_assets
-@:dox(hide) class ManifestResources {
- public static var preloadLibraries:Array;
- public static var preloadLibraryNames:Array;
- public static var rootPath:String;
-
- public static function init (config:Dynamic):Void {
- preloadLibraries = new Array ();
- preloadLibraryNames = new Array ();
- }
-}
-#else
@:access(lime.utils.Assets)
+@:keep class ManifestResources {
+ public static var preloadLibraries:Array = [];
+ public static var preloadLibraryNames:Array = [];
+ public static var rootPath:String;
+ public static function init(config:Dynamic):Void {
+ rootPath = "";
-@:keep @:dox(hide) class ManifestResources {
+ #if sys
+ var manifestPath = Path.join(["manifest", "data.json"]);
+ if (!FileSystem.exists(manifestPath)) {
+ trace("Manifest file not found: " + manifestPath);
+ return;
+ }
+ #end
-
- public static var preloadLibraries:Array;
- public static var preloadLibraryNames:Array;
- public static var rootPath:String;
-
-
- public static function init (config:Dynamic):Void {
-
- preloadLibraries = new Array ();
- preloadLibraryNames = new Array ();
-
- rootPath = null;
-
- if (config != null && Reflect.hasField (config, "rootPath")) {
-
- rootPath = Reflect.field (config, "rootPath");
-
- if(!StringTools.endsWith (rootPath, "/")) {
-
- rootPath += "/";
-
- }
-
- }
-
- if (rootPath == null) {
-
- #if (ios || tvos || webassembly)
- rootPath = "assets/";
- #elseif android
- rootPath = "";
- #elseif (console || sys)
- rootPath = lime.system.System.applicationDirectory;
- #else
- rootPath = "./";
- #end
-
- }
-
- #if (openfl && !flash && !display)
-
- #end
-
- var data, manifest, library, bundle;
-
- Assets.libraryPaths["default"] = rootPath + "manifest/default.json";
-
-
- library = Assets.getLibrary ("default");
- if (library != null) preloadLibraries.push (library);
- else preloadLibraryNames.push ("default");
-
-
- }
-
-
-}
-
-#if !display
-#if flash
-
-@:keep @:bind @:noCompletion #if display private #end class __ASSET__assets_data_img_placeholder_txt extends null { }
-@:keep @:bind @:noCompletion #if display private #end class __ASSET__manifest_default_json extends null { }
-
-
-#elseif (desktop || cpp)
-
-
-
-
-#else
-
-
-
-#end
-
-#if (openfl && !flash)
-
-#if html5
-
-#else
-
-#end
-
-#end
-#end
-
-#end
\ No newline at end of file
+ try {
+ var manifest = AssetManifest.fromFile(manifestPath);
+ if (manifest != null) {
+ var library = AssetLibrary.fromManifest(manifest);
+ if (library != null) {
+ preloadLibraries.push(library);
+ preloadLibraryNames.push("default");
+ LimeAssets.registerLibrary("default", library);
+ }
+ }
+ } catch (e:Dynamic) {
+ trace("Error loading asset manifest: " + e);
+ }
+ }
+}
\ No newline at end of file
diff --git a/standalone-openfl-app/src/macros/AssetMacro.hx b/standalone-openfl-app/src/macros/AssetMacro.hx
index ebed5820..3814f111 100644
--- a/standalone-openfl-app/src/macros/AssetMacro.hx
+++ b/standalone-openfl-app/src/macros/AssetMacro.hx
@@ -1,9 +1,238 @@
package macros;
-class AssetMacro{
-
- public static function buildAssets(){
+import haxe.macro.Context;
+import haxe.macro.Expr;
+import haxe.macro.Type;
+import sys.FileSystem;
+import sys.io.File;
+import haxe.Json;
+using StringTools;
+/**
+ * Macro for processing @:Assets meta tags and building asset manifests
+ */
+@:keep
+class AssetMacro {
+ // Track all assets processed
+ private static var assetMap:Map> = new Map();
+
+ /**
+ * Entry point for the macro - called during compilation
+ */
+ public static function build():Array {
+ #if macro
+ Sys.println("AssetMacro.build() called - macro is running");
+ Context.warning("AssetMacro is running", Context.currentPos());
+ #end
+
+ // Get current build context
+ var fields = Context.getBuildFields();
+ var localClass = Context.getLocalClass().get();
+
+ #if macro
+ Sys.println("Processing class: " + localClass.name);
+ #end
+
+ // Get the output directory from build.hxml
+ var outputDir = getOutputDir();
+ var manifestDir = outputDir + "/manifest";
+ var assetsOutputDir = outputDir + "/assets";
+
+ // Create directories if they don't exist
+ createDirectory(manifestDir);
+ createDirectory(assetsOutputDir);
+
+ // Process asset fields
+ for (field in fields) {
+ processField(field, assetsOutputDir);
+ }
+
+ // Build the manifest files
+ buildManifests(manifestDir);
+
+ return fields;
+ }
+
+ /**
+ * Process a field for @:Assets meta
+ */
+ private static function processField(field:Field, assetsOutputDir:String) {
+ // Look for our custom meta
+ var assetsMeta = findAssetsMeta(field.meta);
+ if (assetsMeta == null) return;
+
+ var params = assetsMeta.params;
+ if (params.length < 2) {
+ Context.error("@:Assets meta requires at least 2 parameters: source path and library name", assetsMeta.pos);
+ return;
+ }
+
+ // Extract parameters
+ var sourcePath = extractString(params[0]);
+ var libraryName = extractString(params[1]);
+ var targetPath = params.length > 2 ? extractString(params[2]) : null;
+
+ // Process directory or single file
+ if (FileSystem.exists(sourcePath)) {
+ if (FileSystem.isDirectory(sourcePath)) {
+ processDirectory(sourcePath, libraryName, assetsOutputDir);
+ } else {
+ processSingleFile(sourcePath, libraryName, targetPath, assetsOutputDir);
+ }
+ } else {
+ Context.warning('Asset source not found: ${sourcePath}', field.pos);
+ }
+ }
+
+ /**
+ * Process a directory of assets
+ */
+ private static function processDirectory(sourcePath:String, libraryName:String, assetsOutputDir:String) {
+ if (!sourcePath.endsWith("/")) sourcePath += "/";
+ var targetDir = assetsOutputDir + "/" + libraryName + "/";
+ createDirectory(targetDir);
+
+ function scanDir(path:String, relPath:String = "") {
+ if (!FileSystem.exists(path)) return;
+
+ for (entry in FileSystem.readDirectory(path)) {
+ var fullPath = path + entry;
+ var relAssetPath = relPath + entry;
+
+ if (FileSystem.isDirectory(fullPath)) {
+ var newRelPath = relPath + entry + "/";
+ var newTargetDir = targetDir + newRelPath;
+ createDirectory(newTargetDir);
+ scanDir(fullPath + "/", newRelPath);
+ } else {
+ // Copy file and register in asset map
+ var targetPath = targetDir + relAssetPath;
+ try {
+ File.copy(fullPath, targetPath);
+
+ // Register asset
+ if (!assetMap.exists(libraryName)) {
+ assetMap.set(libraryName, []);
+ }
+
+ assetMap.get(libraryName).push({
+ id: relAssetPath,
+ path: relAssetPath,
+ size: FileSystem.stat(fullPath).size,
+ type: getAssetType(fullPath)
+ });
+ } catch (e) {
+ Context.warning('Failed to copy asset: ${fullPath} -> ${targetPath}. Error: ${e}', Context.currentPos());
+ }
+ }
+ }
+ }
+
+ scanDir(sourcePath);
+ }
+
+ /**
+ * Process a single file asset
+ */
+ private static function processSingleFile(sourcePath:String, libraryName:String, targetPath:String, assetsOutputDir:String) {
+ var targetDir = assetsOutputDir + "/" + libraryName + "/";
+ createDirectory(targetDir);
+
+ var fileName = targetPath != null ? targetPath : sourcePath.split("/").pop();
+ var destPath = targetDir + fileName;
+
+ try {
+ File.copy(sourcePath, destPath);
+
+ // Register asset
+ if (!assetMap.exists(libraryName)) {
+ assetMap.set(libraryName, []);
+ }
+
+ assetMap.get(libraryName).push({
+ id: fileName,
+ path: fileName,
+ size: FileSystem.stat(sourcePath).size,
+ type: getAssetType(sourcePath)
+ });
+ } catch (e) {
+ Context.warning('Failed to copy asset: ${sourcePath} -> ${destPath}. Error: ${e}', Context.currentPos());
+ }
+ }
+
+ /**
+ * Build manifest JSON files for each library
+ */
+ private static function buildManifests(manifestDir:String) {
+ for (library in assetMap.keys()) {
+ var assets = assetMap.get(library);
+ var manifest = {
+ name: library,
+ assets: assets,
+ rootPath: "../assets/" + library + "/"
+ };
+
+ var manifestPath = manifestDir + "/" + library + ".json";
+ try {
+ var content = Json.stringify(manifest, null, " ");
+ File.saveContent(manifestPath, content);
+ Context.info('Built manifest: ${manifestPath} with ${assets.length} assets', Context.currentPos());
+ } catch (e) {
+ Context.warning('Failed to write manifest: ${manifestPath}. Error: ${e}', Context.currentPos());
+ }
+ }
+ }
+
+ // Helper functions
+
+ private static function getOutputDir():String {
+ // Try to parse the --cpp argument from the build.hxml
+ var args = Sys.args();
+ for (i in 0...args.length) {
+ if (args[i] == "--cpp" && i < args.length - 1) {
+ return args[i + 1];
+ }
+ }
+ return "bin/cpp"; // Default output directory
+ }
+
+ private static function createDirectory(path:String) {
+ if (!FileSystem.exists(path)) {
+ try {
+ FileSystem.createDirectory(path);
+ } catch (e) {
+ Context.warning('Failed to create directory: ${path}. Error: ${e}', Context.currentPos());
+ }
+ }
+ }
+
+ private static function findAssetsMeta(metaAccess:Array):MetadataEntry {
+ if (metaAccess == null) return null;
+
+ for (meta in metaAccess) {
+ if (meta.name == ":Assets" || meta.name == "Assets") {
+ return meta;
+ }
+ }
+ return null;
+ }
+
+ private static function extractString(expr:Expr):String {
+ switch (expr.expr) {
+ case EConst(CString(s)): return s;
+ default: Context.error("Expected string literal", expr.pos);
+ }
+ return null;
+ }
+
+ private static function getAssetType(path:String):String {
+ var ext = path.split(".").pop().toLowerCase();
+ return (switch (ext) {
+ case "jpg", "jpeg", "png", "gif", "bmp": "image";
+ case "mp3", "ogg", "wav": "sound";
+ case "ttf", "otf": "font";
+ case "json", "xml", "txt": "text";
+ default: "binary";
+ }).toUpperCase();
}
-
}
\ No newline at end of file