async shape resource loading

This commit is contained in:
RandomityGuy 2022-11-29 23:11:35 +05:30
parent f79a633322
commit 92d59ec1b6
9 changed files with 197 additions and 82 deletions

View file

@ -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);

View file

@ -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<String>->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();
}
}
}

View file

@ -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);
}

View file

@ -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();

View file

@ -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"));

View file

@ -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();
});
});
}

View file

@ -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";
}

View file

@ -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) {

View file

@ -6,7 +6,6 @@ class StartPad extends DtsObject {
public function new() {
super();
dtsPath = "data/shapes/pads/startarea.dts";
useInstancing = false;
isCollideable = true;
identifier = "StartPad";
}