diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1b6c28343..4436dc809 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -70,6 +70,7 @@ are doing mtv adjustments during precollision.
### Fixed
+- Fixed issue where `ex.Scene.onPreLoad(loader: ex.DefaultLoader)` would lock up the engine if there was an empty loader
- Fixed issue where `ex.Scene` scoped input events would preserve state and get stuck causing issues when switching back to the original scene.
- Fixed issue where not all physical keys from the spec were present in `ex.Keys` including the reported `ex.Keys.Tab`
- Fixed invalid graphics types around `ex.Graphic.tint`
diff --git a/sandbox/tests/loader-lockup/index.html b/sandbox/tests/loader-lockup/index.html
new file mode 100644
index 000000000..2db12e026
--- /dev/null
+++ b/sandbox/tests/loader-lockup/index.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+ Loader Lockup
+
+
+
+
+
+
diff --git a/sandbox/tests/loader-lockup/index.ts b/sandbox/tests/loader-lockup/index.ts
new file mode 100644
index 000000000..355e874c5
--- /dev/null
+++ b/sandbox/tests/loader-lockup/index.ts
@@ -0,0 +1,33 @@
+class SceneX extends ex.Scene {
+ override backgroundColor = ex.Color.DarkGray;
+ override onInitialize() {
+ this.input.pointers.on('down', () => {
+ console.warn('should change scenes');
+ this.engine.goToScene('SceneY');
+ });
+ }
+}
+
+class SceneY extends ex.Scene {
+ override backgroundColor = ex.Color.Viridian;
+ // issue still occurs if onPreLoad is not defined or
+ // if we call super.onPreLoad(loader)
+ override onPreLoad(loader: ex.DefaultLoader) {
+ // un-commenting this call fixes the issue.
+ // loader.addResource({
+ // data: {},
+ // isLoaded: () => true,
+ // load: () => Promise.resolve(),
+ // });
+ }
+}
+
+var gameLoaderLockup = new ex.Engine({
+ scenes: {
+ SceneX,
+ SceneY: { scene: SceneY, loader: ex.Loader }
+ }
+});
+
+gameLoaderLockup.start();
+gameLoaderLockup.goToScene('SceneX');
diff --git a/src/engine/Director/DefaultLoader.ts b/src/engine/Director/DefaultLoader.ts
index 97caff13d..29fd503b2 100644
--- a/src/engine/Director/DefaultLoader.ts
+++ b/src/engine/Director/DefaultLoader.ts
@@ -186,6 +186,10 @@ export class DefaultLoader implements Loadable[]> {
private _loadingFuture = new Future();
public areResourcesLoaded() {
+ if (this._resources.length === 0) {
+ // special case no resources mean loaded;
+ return Promise.resolve();
+ }
return this._loadingFuture.promise;
}
diff --git a/src/spec/DefaultLoaderSpec.ts b/src/spec/DefaultLoaderSpec.ts
index 66b7335c5..d5d875e6c 100644
--- a/src/spec/DefaultLoaderSpec.ts
+++ b/src/spec/DefaultLoaderSpec.ts
@@ -25,6 +25,12 @@ describe('A DefaultLoader', () => {
expect(sut).toBeDefined();
});
+ it('is loaded when no resources', async () => {
+ const loader = new ex.DefaultLoader();
+ expect(loader.isLoaded()).toBe(true);
+ await expectAsync(loader.areResourcesLoaded()).toBeResolved();
+ });
+
it('can be constructed with non-defaults', () => {
const sut = new ex.DefaultLoader({
loadables: [new ex.ImageSource('./some/image.png')]