WIP
This commit is contained in:
24
hGameTest/Makefile
Normal file
24
hGameTest/Makefile
Normal file
@@ -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
|
||||
@@ -17,7 +17,8 @@ class Project extends HXProject {
|
||||
// App settings
|
||||
app.main = "Main";
|
||||
app.file = "hgame";
|
||||
app.path = "bin";
|
||||
app.path = "bin/openfl-build-chain";
|
||||
app.preloader = "HGamePreloader";
|
||||
|
||||
|
||||
// Window config
|
||||
@@ -52,6 +53,8 @@ class Project extends HXProject {
|
||||
haxeflags.push("--macro keep('Main')");
|
||||
haxeflags.push("-dce full");
|
||||
|
||||
// target = Platform.LINUX;
|
||||
target = Platform.LINUX;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
3
hGameTest/assets/data/config.json
Normal file
3
hGameTest/assets/data/config.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
|
||||
}
|
||||
1
hGameTest/assets/data/img/placeholder.txt
Normal file
1
hGameTest/assets/data/img/placeholder.txt
Normal file
@@ -0,0 +1 @@
|
||||
This file is intentionally left blank.
|
||||
18
hGameTest/assets/data/textures.json
Normal file
18
hGameTest/assets/data/textures.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"dataScheme":"textureList",
|
||||
"version":1,
|
||||
"textureData": {
|
||||
"spriteSheets":[{
|
||||
"sheetName":"testSheet",
|
||||
"path":"sheets/sheet.png",
|
||||
"sheetDataPath":"sheets/sheet.json",
|
||||
"explicitDimensions":true,
|
||||
"tileDimensions":{"width":16,"height":16}
|
||||
}],
|
||||
"sprites":
|
||||
[{
|
||||
"spriteName":"player",
|
||||
"path":"individual/character.png"
|
||||
}]
|
||||
}
|
||||
}
|
||||
BIN
hGameTest/assets/fonts/Terminus.ttf
Normal file
BIN
hGameTest/assets/fonts/Terminus.ttf
Normal file
Binary file not shown.
BIN
hGameTest/assets/images/logo.png
Normal file
BIN
hGameTest/assets/images/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 547 B |
@@ -1,9 +1,31 @@
|
||||
-lib actuate
|
||||
-lib lime
|
||||
-main ApplicationMain
|
||||
|
||||
-lib openfl
|
||||
-lib hxp
|
||||
-lib lime
|
||||
-lib actuate
|
||||
-lib hxcpp-debug-server
|
||||
|
||||
--main ApplicationMain
|
||||
-cp src
|
||||
|
||||
--cpp bin/cpp
|
||||
-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
|
||||
-D debug
|
||||
--remap flash:openfl
|
||||
-cpp bin/cpp
|
||||
--macro keep("Main")
|
||||
--macro keep("Assets")
|
||||
--macro keep("AssetMacro")
|
||||
--macro addGlobalMetadata('', '@:build(engine.macros.ConVarDecorators.build())')
|
||||
# --macro macros.MacroLoader.run()
|
||||
@@ -1,26 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2025 ${company}
|
||||
* Author: ${author}
|
||||
* License: ${license}
|
||||
*/
|
||||
// TODO: kanker
|
||||
package;
|
||||
|
||||
import openfl.events.Event;
|
||||
#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)
|
||||
@:dox(hide)
|
||||
|
||||
class ApplicationMain
|
||||
{
|
||||
/**
|
||||
* [Description]
|
||||
*
|
||||
*/
|
||||
#if !macro
|
||||
public static function main()
|
||||
{
|
||||
lime.system.System.__registerEntryPoint("::APP_FILE::", create);
|
||||
lime.system.System.__registerEntryPoint("MinimalApplication", create);
|
||||
|
||||
#if (js && html5)
|
||||
#if (munit || (utest && openfl_enable_utest_legacy_mode))
|
||||
lime.system.System.embed("::APP_FILE::", null, ::WIN_WIDTH::, ::WIN_HEIGHT::);
|
||||
lime.system.System.embed("MinimalApplication", null, 800, 600);
|
||||
#end
|
||||
#else
|
||||
create(null);
|
||||
@@ -35,49 +48,48 @@ class ApplicationMain
|
||||
ManifestResources.init(config);
|
||||
#end
|
||||
|
||||
app.meta["build"] = "::meta.buildNumber::";
|
||||
app.meta["company"] = "::meta.company::";
|
||||
app.meta["file"] = "::APP_FILE::";
|
||||
app.meta["name"] = "::meta.title::";
|
||||
app.meta["packageName"] = "::meta.packageName::";
|
||||
app.meta["version"] = "::meta.version::";
|
||||
|
||||
|
||||
::if (config.hxtelemetry != null)::#if hxtelemetry
|
||||
app.meta["hxtelemetry-allocations"] = "::config.hxtelemetry.allocations::";
|
||||
app.meta["hxtelemetry-host"] = "::config.hxtelemetry.host::";
|
||||
#end::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
|
||||
::foreach windows::
|
||||
|
||||
var attributes:lime.ui.WindowAttributes = {
|
||||
allowHighDPI: ::allowHighDPI::,
|
||||
alwaysOnTop: ::alwaysOnTop::,
|
||||
borderless: ::borderless::,
|
||||
// display: ::display::,
|
||||
allowHighDPI: false,
|
||||
alwaysOnTop: false,
|
||||
borderless: false,
|
||||
// display: 0,
|
||||
element: null,
|
||||
frameRate: ::fps::,
|
||||
#if !web fullscreen: ::fullscreen::, #end
|
||||
height: ::height::,
|
||||
hidden: #if munit true #else ::hidden:: #end,
|
||||
maximized: ::maximized::,
|
||||
minimized: ::minimized::,
|
||||
parameters: ::parameters::,
|
||||
resizable: ::resizable::,
|
||||
title: "::title::",
|
||||
width: ::width::,
|
||||
x: ::x::,
|
||||
y: ::y::,
|
||||
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: ::antialiasing::,
|
||||
background: ::background::,
|
||||
colorDepth: ::colorDepth::,
|
||||
depth: ::depthBuffer::,
|
||||
hardware: ::hardware::,
|
||||
stencil: ::stencilBuffer::,
|
||||
antialiasing: 0,
|
||||
background: 16777215,
|
||||
colorDepth: 32,
|
||||
depth: true,
|
||||
hardware: true,
|
||||
stencil: true,
|
||||
type: null,
|
||||
vsync: ::vsync::
|
||||
vsync: false
|
||||
};
|
||||
|
||||
if (app.window == null)
|
||||
@@ -103,13 +115,14 @@ class ApplicationMain
|
||||
}
|
||||
|
||||
app.createWindow(attributes);
|
||||
::end::
|
||||
|
||||
#elseif air
|
||||
app.window.title = "::meta.title::";
|
||||
app.window.title = "MinimalApplication";
|
||||
#else
|
||||
app.window.context.attributes.background = ::WIN_BACKGROUND::;
|
||||
app.window.frameRate = ::WIN_FPS::;
|
||||
app.window.context.attributes.background = 16777215;
|
||||
app.window.frameRate = 30;
|
||||
#end
|
||||
|
||||
|
||||
var preloader = getPreloader();
|
||||
app.preloader.onProgress.add (function(loaded, total)
|
||||
@@ -120,7 +133,6 @@ class ApplicationMain
|
||||
{
|
||||
@:privateAccess preloader.start();
|
||||
});
|
||||
|
||||
preloader.onComplete.add(start.bind((cast app.window:openfl.display.Window).stage));
|
||||
|
||||
#if !disable_preloader_assets
|
||||
@@ -188,7 +200,7 @@ class ApplicationMain
|
||||
{
|
||||
var hasMain = false;
|
||||
|
||||
switch (Context.follow(Context.getType("::APP_MAIN::")))
|
||||
switch (Context.follow(Context.getType("Main")))
|
||||
{
|
||||
case TInst(t, params):
|
||||
|
||||
@@ -204,7 +216,7 @@ class ApplicationMain
|
||||
|
||||
if (hasMain)
|
||||
{
|
||||
return Context.parse("@:privateAccess ::APP_MAIN::.main()", Context.currentPos());
|
||||
return Context.parse("@:privateAccess Main.main()", Context.currentPos());
|
||||
}
|
||||
else if (type.constructor != null)
|
||||
{
|
||||
@@ -223,12 +235,12 @@ class ApplicationMain
|
||||
}
|
||||
else
|
||||
{
|
||||
Context.fatalError("Main class \"::APP_MAIN::\" has neither a static main nor a constructor.", Context.currentPos());
|
||||
Context.fatalError("Main class \"Main\" has neither a static main nor a constructor.", Context.currentPos());
|
||||
}
|
||||
|
||||
default:
|
||||
|
||||
Context.fatalError("Main class \"::APP_MAIN::\" isn't a class.", Context.currentPos());
|
||||
Context.fatalError("Main class \"Main\" isn't a class.", Context.currentPos());
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -236,8 +248,8 @@ class ApplicationMain
|
||||
|
||||
macro public static function getPreloader()
|
||||
{
|
||||
::if (PRELOADER_NAME != "")::
|
||||
var type = Context.getType("::PRELOADER_NAME::");
|
||||
|
||||
var type = Context.getType("HGamePreloader");
|
||||
|
||||
switch (type)
|
||||
{
|
||||
@@ -251,7 +263,7 @@ class ApplicationMain
|
||||
{
|
||||
return macro
|
||||
{
|
||||
new ::PRELOADER_NAME::();
|
||||
new HGamePreloader();
|
||||
};
|
||||
}
|
||||
|
||||
@@ -270,16 +282,12 @@ class ApplicationMain
|
||||
|
||||
return macro
|
||||
{
|
||||
new openfl.display.Preloader(new ::PRELOADER_NAME::());
|
||||
new openfl.display.Preloader(new HGamePreloader());
|
||||
}
|
||||
::else::
|
||||
return macro
|
||||
{
|
||||
new openfl.display.Preloader(new openfl.display.Preloader.DefaultPreloader());
|
||||
};
|
||||
::end::
|
||||
|
||||
}
|
||||
|
||||
|
||||
#if !macro
|
||||
@:noCompletion @:dox(hide) public static function __init__()
|
||||
{
|
||||
@@ -326,7 +334,7 @@ class ApplicationMain
|
||||
|
||||
#if !macro
|
||||
@:build(DocumentClass.build())
|
||||
@:keep @:dox(hide) class DocumentClass extends ::APP_MAIN:: {}
|
||||
@:keep @:dox(hide) class DocumentClass extends Main {}
|
||||
#else
|
||||
class DocumentClass
|
||||
{
|
||||
|
||||
29
hGameTest/src/Assets.hx
Normal file
29
hGameTest/src/Assets.hx
Normal file
@@ -0,0 +1,29 @@
|
||||
package;
|
||||
|
||||
/**
|
||||
* Asset definition class using meta tags instead of project.xml
|
||||
* The AssetMacro will process these declarations at compile time
|
||||
*/
|
||||
@:build(macros.AssetMacro.build()) // Fix: use fully qualified path with package name
|
||||
@:keep
|
||||
class Assets {
|
||||
// Define image assets
|
||||
@:Assets("assets/images/", "images")
|
||||
private static var images:String;
|
||||
|
||||
// Define sound assets
|
||||
@:Assets("assets/sounds/", "sounds")
|
||||
private static var sounds:String;
|
||||
|
||||
// Define font assets
|
||||
@:Assets("assets/fonts/", "fonts")
|
||||
private static var fonts:String;
|
||||
|
||||
// Define data assets
|
||||
@:Assets("assets/data/", "data")
|
||||
private 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;
|
||||
}
|
||||
200
hGameTest/src/HGamePreloader.hx
Normal file
200
hGameTest/src/HGamePreloader.hx
Normal file
@@ -0,0 +1,200 @@
|
||||
package;
|
||||
|
||||
import openfl.events.ProgressEvent;
|
||||
import openfl.Lib;
|
||||
import haxe.Timer;
|
||||
import openfl.events.KeyboardEvent;
|
||||
import openfl.text.TextField;
|
||||
import openfl.display.Preloader;
|
||||
import openfl.events.Event;
|
||||
import openfl.display.Sprite;
|
||||
|
||||
@:keep @:noCompletion #if display private #end class __ASSET__fonts_terminus_ttf extends lime.text.Font {
|
||||
public function new() {
|
||||
__fontPath = ManifestResources.rootPath + "fonts/Terminus.ttf";
|
||||
name = "Terminus (TTF)";
|
||||
super();
|
||||
}
|
||||
}
|
||||
|
||||
class HGamePreloader extends Sprite {
|
||||
public static var preloadScreen:HGamePreloader;
|
||||
|
||||
private var textField:TextField;
|
||||
|
||||
public function new() {
|
||||
super();
|
||||
|
||||
init();
|
||||
initUI();
|
||||
|
||||
// openfl.Lib.current.addChild(preloadScreen);
|
||||
trace("Preloader initialized");
|
||||
textField.text = "Preloader ...";
|
||||
|
||||
this.addEventListener(Event.COMPLETE, onComplete);
|
||||
this.addEventListener(ProgressEvent.PROGRESS, (e:ProgressEvent) -> {
|
||||
trace(e.bytesLoaded + "/" + e.bytesTotal);
|
||||
onUpdate(cast e.bytesLoaded, cast e.bytesTotal);
|
||||
});
|
||||
Lib.current.stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
|
||||
Lib.current.stage.addEventListener(KeyboardEvent.KEY_UP, onDismiss);
|
||||
}
|
||||
|
||||
public function onComplete(event:Event) {
|
||||
event.preventDefault();
|
||||
trace("Preloader complete");
|
||||
}
|
||||
|
||||
public function pltrace(msg:String) {
|
||||
trace(msg);
|
||||
if (textField != null) {
|
||||
textField.text += "\n" + msg;
|
||||
}
|
||||
}
|
||||
|
||||
public var initialized:Bool = false;
|
||||
|
||||
public function init() {
|
||||
// Preload assets
|
||||
trace("Preloading assets...");
|
||||
registerFonts();
|
||||
// Add your asset loading logic here
|
||||
// For example, you can load images, sounds, etc.
|
||||
// You can use openfl.Assets.loadBitmapData() or openfl.Assets.loadSound() to load assets
|
||||
// and then add them to the preloadScreen or do any other processing you need.
|
||||
|
||||
// Require clicking to start the game
|
||||
// Add an event listener to the stage to check for input
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
public function onUpdate(loaded:Int, total:Int) {
|
||||
trace("Preloader update: " + loaded + "/" + total);
|
||||
// Update the preloader screen
|
||||
// You can update the progress bar or any other UI elements here
|
||||
// For example, you can use textField.text to show loading progress
|
||||
// textField.text = "Loading... " + Math.round(progress * 100) + "%";
|
||||
if (textField != null) {
|
||||
textField.text = "Loading... " + Math.round(loaded / total * 100) + "%";
|
||||
}
|
||||
// You can also update the preloader screen's graphics or animations here
|
||||
// For example, you can change the color or size of the preloader screen
|
||||
|
||||
preloadScreen.graphics.clear();
|
||||
preloadScreen.graphics.beginFill(Math.random() * 0xFFFFFF);
|
||||
preloadScreen.graphics.drawRect(0, 0, 800, 600);
|
||||
preloadScreen.graphics.endFill();
|
||||
}
|
||||
|
||||
public function registerFonts() {
|
||||
@:privateAccess
|
||||
var fontLibrary = openfl.utils.Assets.getLibrary("fonts");
|
||||
if (fontLibrary == null) {
|
||||
trace("Font library not found");
|
||||
return;
|
||||
}
|
||||
var fontAssets:Array<Dynamic> = fontLibrary.list('FONT');
|
||||
if (fontAssets == null) {
|
||||
trace("Font assets not found");
|
||||
return;
|
||||
}
|
||||
for (fontAsset in fontAssets) {
|
||||
trace('fontAsset: ${fontAsset}');
|
||||
var font = fontLibrary.getFont(fontAsset);
|
||||
if (font == null) {
|
||||
trace("Font not found: " + fontAsset);
|
||||
continue;
|
||||
}
|
||||
trace(@:privateAccess font.__fontPath);
|
||||
|
||||
openfl.text.Font.registerFont(font);
|
||||
|
||||
trace("Font registered: " + fontAsset);
|
||||
}
|
||||
}
|
||||
|
||||
public function onDismiss(event:KeyboardEvent) {
|
||||
trace("Preloader dismissed");
|
||||
|
||||
if (preloadScreen == null || openfl.Lib.current == null)
|
||||
return;
|
||||
|
||||
if (event.keyCode != openfl.ui.Keyboard.ENTER)
|
||||
return this.removeEventListener(KeyboardEvent.KEY_UP, onDismiss);
|
||||
|
||||
openfl.Lib.current.removeChild(preloadScreen);
|
||||
// var app = ApplicationMain.app;
|
||||
dispatchEvent(new Event(Event.UNLOAD));
|
||||
}
|
||||
|
||||
public function initUI() {
|
||||
// Initialize the UI elements
|
||||
trace("Initializing UI...");
|
||||
// You can add your UI initialization logic here
|
||||
// For example, you can create buttons, sliders, etc.
|
||||
// and add them to the preloadScreen or any other container
|
||||
preloadScreen = this;
|
||||
preloadScreen.graphics.beginFill(0x000000);
|
||||
preloadScreen.graphics.drawRect(0, 0, 800, 600);
|
||||
preloadScreen.graphics.endFill();
|
||||
preloadScreen.x = 0;
|
||||
preloadScreen.y = 0;
|
||||
preloadScreen.alpha = 0.5;
|
||||
preloadScreen.scaleX = 1;
|
||||
preloadScreen.scaleY = 1;
|
||||
preloadScreen.mouseEnabled = false;
|
||||
preloadScreen.mouseChildren = false;
|
||||
preloadScreen.name = "preloadScreen";
|
||||
preloadScreen.visible = true;
|
||||
preloadScreen.cacheAsBitmap = true;
|
||||
preloadScreen.filters = [];
|
||||
preloadScreen.transform.colorTransform = new openfl.geom.ColorTransform(1, 1, 1, 1, 0, 0, 0, 0);
|
||||
preloadScreen.transform.matrix = new openfl.geom.Matrix(1, 0, 0, 1, 0, 0);
|
||||
preloadScreen.transform.matrix3D = new openfl.geom.Matrix3D();
|
||||
|
||||
textField = new openfl.text.TextField();
|
||||
textField.x = 10;
|
||||
textField.y = 10;
|
||||
textField.width = 780;
|
||||
textField.height = 580;
|
||||
textField.multiline = true;
|
||||
textField.wordWrap = true;
|
||||
textField.selectable = false;
|
||||
textField.autoSize = openfl.text.TextFieldAutoSize.LEFT;
|
||||
textField.defaultTextFormat = new openfl.text.TextFormat("Arial", 12, 0xFFFFFF);
|
||||
textField.embedFonts = true;
|
||||
textField.antiAliasType = openfl.text.AntiAliasType.ADVANCED;
|
||||
textField.background = true;
|
||||
textField.backgroundColor = 0x000000;
|
||||
textField.border = true;
|
||||
textField.borderColor = 0xFFFFFF;
|
||||
textField.textColor = 0xFFFFFF;
|
||||
textField.text = "Loading...";
|
||||
textField.alpha = 1;
|
||||
textField.scaleX = 1;
|
||||
textField.scaleY = 1;
|
||||
textField.mouseEnabled = false;
|
||||
textField.name = "textField";
|
||||
textField.visible = true;
|
||||
textField.cacheAsBitmap = true;
|
||||
textField.filters = [];
|
||||
textField.transform.colorTransform = new openfl.geom.ColorTransform(1, 1, 1, 1, 0, 0, 0, 0);
|
||||
textField.transform.matrix = new openfl.geom.Matrix(1, 0, 0, 1, 0, 0);
|
||||
textField.transform.matrix3D = new openfl.geom.Matrix3D();
|
||||
preloadScreen.addChild(textField);
|
||||
}
|
||||
|
||||
public function onKeyDown(event:KeyboardEvent) {
|
||||
trace("Key pressed: " + event.keyCode);
|
||||
|
||||
if (!initialized)
|
||||
return;
|
||||
|
||||
if (event.keyCode == openfl.ui.Keyboard.ENTER) {
|
||||
// Start the game
|
||||
trace("Starting game...");
|
||||
openfl.Lib.current.stage.removeChild(preloadScreen);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,8 @@
|
||||
import openfl.display.Window;
|
||||
import assets.Scanner;
|
||||
import game.video.Mode;
|
||||
import openfl.events.KeyboardEvent;
|
||||
import openfl.display.Sprite;
|
||||
import openfl.display.Stage;
|
||||
import openfl.events.Event;
|
||||
import game.Input;
|
||||
import game.Game;
|
||||
import game.video.Mode;
|
||||
|
||||
class Main extends Sprite {
|
||||
public function new () {
|
||||
@@ -24,26 +19,13 @@ class Main extends Sprite {
|
||||
stage.addEventListener(KeyboardEvent.KEY_UP,Input.onKeyIsUp);
|
||||
stage.addEventListener(Event.RESIZE,onResize);
|
||||
game.onInit();
|
||||
//Mode.setVideoMode(1280, 960);
|
||||
|
||||
|
||||
}
|
||||
private function onResize (event:Event):Void {
|
||||
|
||||
//Here we can do shit with window scaling
|
||||
//stage.stageWidth;
|
||||
//stage.stageHeight;
|
||||
}
|
||||
|
||||
// static function main () {
|
||||
// // Bootstrap the OpenFL project
|
||||
// var application = new lime.app.Application();
|
||||
// application.createWindow({
|
||||
// hidden: false,
|
||||
// x: 0,
|
||||
// y: 0,
|
||||
// width: 800,
|
||||
// height: 600,
|
||||
// title: "DSTEngine Window"
|
||||
// });
|
||||
// }
|
||||
|
||||
}
|
||||
61
hGameTest/src/ManifestResources.hx
Normal file
61
hGameTest/src/ManifestResources.hx
Normal file
@@ -0,0 +1,61 @@
|
||||
package;
|
||||
|
||||
#if sys
|
||||
import haxe.io.Path;
|
||||
import openfl.utils.AssetLibrary;
|
||||
import openfl.utils.AssetManifest;
|
||||
import openfl.utils.Assets as LimeAssets;
|
||||
import sys.FileSystem;
|
||||
|
||||
@:access(lime.utils.Assets)
|
||||
@:keep class ManifestResources {
|
||||
public static var preloadLibraries:Array<AssetLibrary> = [];
|
||||
public static var preloadLibraryNames:Array<String> = [];
|
||||
public static var rootPath:String;
|
||||
|
||||
public static function init(config:Dynamic):Void {
|
||||
loadManifests();
|
||||
}
|
||||
public static function loadManifests() {
|
||||
rootPath = "";
|
||||
|
||||
var manifestDirPath = Path.join(["./manifest"]);
|
||||
|
||||
var manifestFiles = FileSystem.readDirectory(manifestDirPath);
|
||||
|
||||
for (manifestFile in manifestFiles) {
|
||||
var manifestPath = Path.join([manifestDirPath, manifestFile]);
|
||||
|
||||
if (!StringTools.endsWith(manifestFile, ".json")){
|
||||
trace('${manifestFile} is not a json file, skipping...');
|
||||
continue;
|
||||
}
|
||||
|
||||
loadManifest(manifestPath, manifestFile.split(".json")[0]);
|
||||
}
|
||||
}
|
||||
|
||||
public static function loadManifest(manifestPath, manifestName) {
|
||||
if (!FileSystem.exists(manifestPath)) {
|
||||
trace("Manifest file not found: " + manifestPath);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
var manifest = AssetManifest.fromFile(manifestPath);
|
||||
if (manifest != null) {
|
||||
var library = AssetLibrary.fromManifest(manifest);
|
||||
if (library != null) {
|
||||
trace("Library: `"+library+"`");
|
||||
trace("manifestName: `"+manifestName+"`");
|
||||
preloadLibraries.push(library);
|
||||
preloadLibraryNames.push(manifestName);
|
||||
// LimeAssets.registerLibrary(manifestName, library);
|
||||
openfl.utils.Assets.registerLibrary(manifestName, library);
|
||||
}
|
||||
}
|
||||
} catch (e:Dynamic) {
|
||||
trace("Error loading asset manifest: " + e);
|
||||
}
|
||||
}
|
||||
}
|
||||
#end
|
||||
@@ -10,8 +10,16 @@ class TextFormats{
|
||||
public var cInputFmt:TextFormat;
|
||||
public var cOutputFmt:TextFormat;
|
||||
public function new(){
|
||||
var font = Assets.getFont("fonts/Terminus.ttf");
|
||||
cInputFmt = new TextFormat(Assets.getFont("fonts/Terminus.ttf").fontName, 24, 0xffffff);
|
||||
cOutputFmt = new TextFormat(Assets.getFont("fonts/Terminus.ttf").fontName, 24, 0xffffff);
|
||||
trace('font: ${font}');
|
||||
trace('fontName: ${font.fontName}');
|
||||
trace('fontStyle: ${font.fontStyle}');
|
||||
trace('fontType: ${font.fontType}');
|
||||
trace('fontGlyphs: ${font.getGlyphs()}');
|
||||
trace(cInputFmt.font);
|
||||
trace(cOutputFmt.font);
|
||||
}
|
||||
public static function getFormats():TextFormats
|
||||
{
|
||||
|
||||
269
hGameTest/src/macros/AssetMacro.hx
Normal file
269
hGameTest/src/macros/AssetMacro.hx
Normal file
@@ -0,0 +1,269 @@
|
||||
package macros;
|
||||
|
||||
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<String, Array<{id:String, path:String, size:Int, type:String}>> = new Map();
|
||||
|
||||
/**
|
||||
* Entry point for the macro - called during compilation
|
||||
*/
|
||||
public static function build():Array<Field> {
|
||||
#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) {
|
||||
// Create an array to hold all assets for the default manifest
|
||||
var allAssets = [];
|
||||
|
||||
// First, process individual library manifests
|
||||
for (library in assetMap.keys()) {
|
||||
var assets = assetMap.get(library);
|
||||
var manifest = {
|
||||
name: library,
|
||||
assets: assets,
|
||||
rootPath: "../assets/" + library + "/"
|
||||
};
|
||||
|
||||
// Add assets to combined collection with library prefix
|
||||
for (asset in assets) {
|
||||
allAssets.push({
|
||||
id: library + "/" + asset.id,
|
||||
path: library + "/" + asset.path,
|
||||
size: asset.size,
|
||||
type: asset.type
|
||||
});
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
// Create the default manifest with all assets
|
||||
var defaultManifest = {
|
||||
name: "default",
|
||||
assets: allAssets,
|
||||
rootPath: "../assets/"
|
||||
};
|
||||
|
||||
// Save the default manifest
|
||||
var defaultManifestPath = manifestDir + "/default.json";
|
||||
try {
|
||||
var content = Json.stringify(defaultManifest, null, " ");
|
||||
File.saveContent(defaultManifestPath, content);
|
||||
Context.info('Built default manifest: ${defaultManifestPath} with ${allAssets.length} assets', Context.currentPos());
|
||||
} catch (e) {
|
||||
Context.warning('Failed to write default manifest: ${defaultManifestPath}. 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>):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();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user