diff --git a/src/Main.hx b/src/Main.hx index 00be103b..88303fa9 100644 --- a/src/Main.hx +++ b/src/Main.hx @@ -56,8 +56,8 @@ class Main extends hxd.App { }); #end + Settings.init(); ResourceLoader.init(s2d, () -> { - Settings.init(); AudioManager.init(); AudioManager.playShell(); marbleGame = new MarbleGame(s2d, s3d); diff --git a/src/MarbleWorld.hx b/src/MarbleWorld.hx index 4044e642..c972e19f 100644 --- a/src/MarbleWorld.hx +++ b/src/MarbleWorld.hx @@ -82,6 +82,7 @@ import src.Marble; import src.Resource; import src.ProfilerUI; import src.ResourceLoaderWorker; +import haxe.io.Path; class MarbleWorld extends Scheduler { public var collisionWorld:CollisionWorld; @@ -234,16 +235,16 @@ class MarbleWorld extends Scheduler { public function postInit() { // Add the sky at the last so that cubemap reflections work - this.scene.addChild(this.sky); - - this._ready = true; - this.playGui.init(this.scene2d); - var musicFileName = 'data/sound/music/' + this.mission.missionInfo.music; - AudioManager.playMusic(ResourceLoader.getResource(musicFileName, ResourceLoader.getAudio, this.soundResources), this.mission.missionInfo.music); - MarbleGame.canvas.clearContent(); - this.endPad.generateCollider(); - this.playGui.formatGemCounter(this.gemCount, this.totalGems); - start(); + this.playGui.init(this.scene2d, () -> { + this.scene.addChild(this.sky); + this._ready = true; + var musicFileName = 'data/sound/music/' + this.mission.missionInfo.music; + AudioManager.playMusic(ResourceLoader.getResource(musicFileName, ResourceLoader.getAudio, this.soundResources), this.mission.missionInfo.music); + MarbleGame.canvas.clearContent(); + this.endPad.generateCollider(); + this.playGui.formatGemCounter(this.gemCount, this.totalGems); + start(); + }); } public function initScene(onFinish:Void->Void) { @@ -331,8 +332,14 @@ class MarbleWorld extends Scheduler { "sound/set.wav", "sound/go.wav", "sound/alarm.wav", - "sound/alarm_timeout.wav" + "sound/alarm_timeout.wav", + "shapes/images/glow_bounce.dts", + "shapes/images/glow_bounce.png", + "shapes/images/helicopter.dts", + "shapes/images/helicopter.jpg" ]; + marblefiles.push(StringTools.replace(Settings.optionsSettings.marbleModel, "data/", "")); + marblefiles.push("shapes/balls/" + Settings.optionsSettings.marbleSkin + ".marble.png"); for (file in marblefiles) { worker.loadFile(file); } @@ -917,25 +924,89 @@ class MarbleWorld extends Scheduler { } public function addDtsObject(obj:DtsObject, onFinish:Void->Void) { - obj.idInLevel = this.dtsObjects.length; // Set the id of the thing - this.dtsObjects.push(obj); - if (obj is ForceObject) { - this.forceObjects.push(cast obj); - } - obj.init(cast this, () -> { - obj.update(this.timeState); - if (obj.useInstancing) { - this.instanceManager.addObject(obj); - } else - this.scene.addChild(obj); - for (collider in obj.colliders) { - if (collider != null) - this.collisionWorld.addEntity(collider); - } - if (obj.isBoundingBoxCollideable) - this.collisionWorld.addEntity(obj.boundingCollider); + function parseIfl(path:String, onFinish:Array->Void) { + ResourceLoader.load(path).entry.load(() -> { + var text = ResourceLoader.fileSystem.get(path).getText(); + var lines = text.split('\n'); + var keyframes = []; + for (line in lines) { + line = StringTools.trim(line); + if (line.substr(0, 2) == "//") + continue; + if (line == "") + continue; - onFinish(); + var parts = line.split(' '); + var count = parts.length > 1 ? Std.parseInt(parts[1]) : 1; + + for (i in 0...count) { + keyframes.push(parts[0]); + } + } + + onFinish(keyframes); + }); + } + + ResourceLoader.load(obj.dtsPath).entry.load(() -> { + var dtsFile = ResourceLoader.loadDts(obj.dtsPath); + var directoryPath = haxe.io.Path.directory(obj.dtsPath); + var texToLoad = []; + for (i in 0...dtsFile.resource.matNames.length) { + var matName = obj.matNameOverride.exists(dtsFile.resource.matNames[i]) ? obj.matNameOverride.get(dtsFile.resource.matNames[i]) : dtsFile.resource.matNames[i]; + var fullNames = ResourceLoader.getFullNamesOf(directoryPath + '/' + matName).filter(x -> haxe.io.Path.extension(x) != "dts"); + var fullName = fullNames.length > 0 ? fullNames[0] : null; + if (fullName != null) { + texToLoad.push(fullName); + } + } + + var worker = new ResourceLoaderWorker(() -> { + obj.idInLevel = this.dtsObjects.length; // Set the id of the thing + this.dtsObjects.push(obj); + if (obj is ForceObject) { + this.forceObjects.push(cast obj); + } + obj.init(cast this, () -> { + obj.update(this.timeState); + if (obj.useInstancing) { + this.instanceManager.addObject(obj); + } else + this.scene.addChild(obj); + for (collider in obj.colliders) { + if (collider != null) + this.collisionWorld.addEntity(collider); + } + if (obj.isBoundingBoxCollideable) + this.collisionWorld.addEntity(obj.boundingCollider); + + onFinish(); + }); + }); + + for (texPath in texToLoad) { + if (haxe.io.Path.extension(texPath) == "ifl") { + worker.addTask(fwd -> { + parseIfl(texPath, keyframes -> { + var innerWorker = new ResourceLoaderWorker(() -> { + fwd(); + }); + var loadedkf = []; + for (kf in keyframes) { + if (!loadedkf.contains(kf)) { + innerWorker.loadFile(directoryPath + '/' + kf); + loadedkf.push(kf); + } + } + innerWorker.run(); + }); + }); + } else { + worker.loadFile(texPath); + } + } + + worker.run(); }); } @@ -1077,6 +1148,8 @@ class MarbleWorld extends Scheduler { } } + var postInited = false; + function asyncLoadResources() { if (this.resourceLoadFuncs.length != 0) { if (lock) @@ -1101,8 +1174,10 @@ class MarbleWorld extends Scheduler { } else { if (this._resourcesLoaded < _loadingLength) return; - if (!_ready) + if (!_ready && !postInited) { + postInited = true; postInit(); + } } } diff --git a/src/ResourceLoader.hx b/src/ResourceLoader.hx index 2b57bb17..d8c93565 100644 --- a/src/ResourceLoader.hx +++ b/src/ResourceLoader.hx @@ -18,6 +18,7 @@ import hxd.res.Loader; import src.Resource; import src.ResourceLoaderWorker; import fs.TorqueFileSystem; +import src.Settings; class ResourceLoader { #if (hl && !android) @@ -191,33 +192,36 @@ class ResourceLoader { } static function preloadShapes(onFinish:Void->Void) { - var toloadfiles = []; - var toloaddirs = []; - var filestats = fileSystem.dir("shapes"); - for (file in filestats) { - if (file.isDirectory) { - toloaddirs.push(file); - } else { - toloadfiles.push(file); - } - } - while (toloaddirs.length > 0) { - var nextdir = toloaddirs.pop(); - for (file in fileSystem.dir(nextdir.path.substring(2))) { - if (file.isDirectory) { - toloaddirs.push(file); - } else { - toloadfiles.push(file); - } - } - } - var teleportPad = fileSystem.get("interiors_mbp/teleportpad.dts"); - var teleportTexture = fileSystem.get("interiors_mbp/repairbay.jpg"); - toloadfiles.push(teleportPad); // Because its not in the shapes folder like wtf - toloadfiles.push(teleportTexture); + var toloadfiles = [ + StringTools.replace(Settings.optionsSettings.marbleModel, "data/", ""), + "shapes/balls/" + Settings.optionsSettings.marbleSkin + ".marble.png" + ]; + // var toloaddirs = []; + // var filestats = fileSystem.dir("shapes"); + // for (file in filestats) { + // if (file.isDirectory) { + // toloaddirs.push(file); + // } else { + // toloadfiles.push(file); + // } + // } + // while (toloaddirs.length > 0) { + // var nextdir = toloaddirs.pop(); + // for (file in fileSystem.dir(nextdir.path.substring(2))) { + // if (file.isDirectory) { + // toloaddirs.push(file); + // } else { + // toloadfiles.push(file); + // } + // } + // } + // var teleportPad = fileSystem.get("interiors_mbp/teleportpad.dts"); + // var teleportTexture = fileSystem.get("interiors_mbp/repairbay.jpg"); + // toloadfiles.push(teleportPad); // Because its not in the shapes folder like wtf + // toloadfiles.push(teleportTexture); var worker = new ResourceLoaderWorker(onFinish); for (file in toloadfiles) { - worker.addTaskParallel((fwd) -> file.load(fwd)); + worker.loadFile(file); } worker.run(); } @@ -244,6 +248,9 @@ class ResourceLoader { if (!StringTools.startsWith(path, "data/")) path = "data/" + path; #end + #if (js || android) + path = StringTools.replace(path, "data/", ""); + #end return ResourceLoader.loader.load(path); } diff --git a/src/Settings.hx b/src/Settings.hx index bf6cde5d..f39be520 100644 --- a/src/Settings.hx +++ b/src/Settings.hx @@ -288,11 +288,13 @@ class Settings { levelStatistics.set(key, value); } } + #if js if (optionsSettings.marbleIndex == null) { optionsSettings.marbleIndex = 0; optionsSettings.marbleSkin = "base"; optionsSettings.marbleModel = "data/shapes/balls/ball-superball.dts"; } + #end highscoreName = json.highscoreName; } else { save(); diff --git a/src/gui/MarbleSelectGui.hx b/src/gui/MarbleSelectGui.hx index 822ef21a..b7aceab4 100644 --- a/src/gui/MarbleSelectGui.hx +++ b/src/gui/MarbleSelectGui.hx @@ -10,6 +10,7 @@ import h3d.Vector; import src.ResourceLoader; import src.DtsObject; import src.Settings; +import src.ResourceLoaderWorker; class MarbleSelectGui extends GuiImage { public function new() { @@ -94,7 +95,8 @@ class MarbleSelectGui extends GuiImage { } this.addChild(selectBtn); - var marbleShow = buildObjectShow(marbleData[curSelection].dts, new Vector(171, 97), new Vector(150, 150), 2.6, 0); + var marbleShow = buildObjectShow(marbleData[curSelection].dts, new Vector(171, 97), new Vector(150, 150), 2.6, 0, + ["base.marble" => marbleData[curSelection].skin + ".marble"]); marbleShow.horizSizing = Center; marbleShow.vertSizing = Bottom; marbleShow.visible = true; @@ -144,14 +146,36 @@ class MarbleSelectGui extends GuiImage { dtsObj.showSequences = false; dtsObj.useInstancing = false; dtsObj.matNameOverride.set("base.marble", marble.skin + ".marble"); - dtsObj.init(null, () -> {}); // The lambda is not gonna run async anyway - for (mat in dtsObj.materials) { - mat.mainPass.enableLights = false; - mat.mainPass.culling = None; - if (mat.blendMode != Alpha && mat.blendMode != Add) - mat.mainPass.addShader(new AlphaChannel()); - } - marbleShow.changeObject(dtsObj); + + ResourceLoader.load(dtsObj.dtsPath).entry.load(() -> { + var dtsFile = ResourceLoader.loadDts(dtsObj.dtsPath); + var directoryPath = haxe.io.Path.directory(dtsObj.dtsPath); + var texToLoad = []; + for (i in 0...dtsFile.resource.matNames.length) { + var matName = dtsObj.matNameOverride.exists(dtsFile.resource.matNames[i]) ? dtsObj.matNameOverride.get(dtsFile.resource.matNames[i]) : dtsFile.resource.matNames[i]; + var fullNames = ResourceLoader.getFullNamesOf(directoryPath + '/' + matName).filter(x -> haxe.io.Path.extension(x) != "dts"); + var fullName = fullNames.length > 0 ? fullNames[0] : null; + if (fullName != null) { + texToLoad.push(fullName); + } + } + + var worker = new ResourceLoaderWorker(() -> { + dtsObj.init(null, () -> {}); // The lambda is not gonna run async anyway + for (mat in dtsObj.materials) { + mat.mainPass.enableLights = false; + mat.mainPass.culling = None; + if (mat.blendMode != Alpha && mat.blendMode != Add) + mat.mainPass.addShader(new AlphaChannel()); + } + marbleShow.changeObject(dtsObj); + }); + + for (texPath in texToLoad) { + worker.loadFile(texPath); + } + worker.run(); + }); } var nextBtn = new GuiButton(loadButtonImages("data/ui/marbleSelect/next")); diff --git a/src/gui/PlayGui.hx b/src/gui/PlayGui.hx index 73f6b40c..2480032d 100644 --- a/src/gui/PlayGui.hx +++ b/src/gui/PlayGui.hx @@ -97,7 +97,7 @@ class PlayGui { } } - public function init(scene2d:h2d.Scene) { + public function init(scene2d:h2d.Scene, onFinish:Void->Void) { this.scene2d = scene2d; this._init = true; @@ -138,7 +138,9 @@ class PlayGui { powerupBox = new GuiImage(ResourceLoader.getResource('data/ui/game/powerup.png', ResourceLoader.getImage, this.imageResources).toTile()); initTimer(); - initGemCounter(); + initGemCounter(() -> { + onFinish(); + }); initCenterText(); initPowerupBox(); initTexts(); @@ -254,7 +256,7 @@ class PlayGui { } } - public function initGemCounter() { + public function initGemCounter(onFinish:Void->Void) { gemCountNumbers[0].position = new Vector(30, 0); gemCountNumbers[0].extent = new Vector(43, 55); @@ -301,21 +303,24 @@ class PlayGui { // gemImageObject.matNameOverride.set("base.gem", "base.gem."); gemImageObject.ambientSpinFactor /= -2; // ["base.gem"] = color + ".gem"; - gemImageObject.init(null, () -> { - for (mat in gemImageObject.materials) { - mat.mainPass.enableLights = false; + ResourceLoader.load("shapes/items/" + gemColor + ".gem.png").entry.load(() -> { + gemImageObject.init(null, () -> { + for (mat in gemImageObject.materials) { + mat.mainPass.enableLights = false; - // Huge hacks - if (mat.blendMode != Add) { - var alphaShader = new h3d.shader.AlphaChannel(); - mat.mainPass.addShader(alphaShader); + // Huge hacks + if (mat.blendMode != Add) { + var alphaShader = new h3d.shader.AlphaChannel(); + mat.mainPass.addShader(alphaShader); + } } - } - gemImageScene.addChild(gemImageObject); - var gemImageCenter = gemImageObject.getBounds().getCenter(); + gemImageScene.addChild(gemImageObject); + var gemImageCenter = gemImageObject.getBounds().getCenter(); - gemImageScene.camera.pos = new Vector(0, 3, gemImageCenter.z); - gemImageScene.camera.target = new Vector(gemImageCenter.x, gemImageCenter.y, gemImageCenter.z); + gemImageScene.camera.pos = new Vector(0, 3, gemImageCenter.z); + gemImageScene.camera.target = new Vector(gemImageCenter.x, gemImageCenter.y, gemImageCenter.z); + onFinish(); + }); }); } diff --git a/src/shapes/EndPad.hx b/src/shapes/EndPad.hx index 9383741e..62b0d660 100644 --- a/src/shapes/EndPad.hx +++ b/src/shapes/EndPad.hx @@ -32,7 +32,6 @@ class EndPad extends DtsObject { public function new() { super(); this.dtsPath = "data/shapes/pads/endarea.dts"; - this.useInstancing = false; this.isCollideable = true; this.identifier = "EndPad"; } diff --git a/src/shapes/Gem.hx b/src/shapes/Gem.hx index ef246612..1df630a6 100644 --- a/src/shapes/Gem.hx +++ b/src/shapes/Gem.hx @@ -6,10 +6,13 @@ import mis.MissionElement.MissionElementItem; import src.TimeState; import src.DtsObject; import src.ResourceLoaderWorker; +import src.ResourceLoader; class Gem extends DtsObject { public var pickedUp:Bool; + var gemColor:String; + public function new(element:MissionElementItem) { super(); dtsPath = "data/shapes/items/gem.dts"; @@ -25,6 +28,7 @@ class Gem extends DtsObject { color = GEM_COLORS[Math.floor(Math.random() * GEM_COLORS.length)]; this.identifier = "Gem" + color; this.matNameOverride.set('base.gem', color + ".gem"); + gemColor = color + ".gem"; } public override function init(level:MarbleWorld, onFinish:Void->Void) { diff --git a/src/shapes/StartPad.hx b/src/shapes/StartPad.hx index dd2009da..53bfa029 100644 --- a/src/shapes/StartPad.hx +++ b/src/shapes/StartPad.hx @@ -6,7 +6,6 @@ class StartPad extends DtsObject { public function new() { super(); dtsPath = "data/shapes/pads/startarea.dts"; - useInstancing = false; isCollideable = true; identifier = "StartPad"; }