diff --git a/_layouts/default.html b/_layouts/default.html index 1094359..3d9d6b9 100644 --- a/_layouts/default.html +++ b/_layouts/default.html @@ -569,10 +569,13 @@

Asset Manager

this.loadingUITextColor = loadingUITextColor || "white"; } CustomLoadingScreen.prototype.displayLoadingUI = function () { + if (document.getElementById("customLoadingScreen")) { + return; + } var loadingDiv = document.createElement("div"); loadingDiv.id = "customLoadingScreen"; const canvasContainer = document.querySelector('.canvas-container'); - if (canvasContainer) { + if (canvasContainer) { loadingDiv.style.position = "absolute"; loadingDiv.style.top = "0"; loadingDiv.style.left = "0"; @@ -1356,6 +1359,14 @@

Asset Manager

kind: 'block', type: 'apply_impulse', }, + { + kind: 'block', + type: 'set_linear_velocity', + }, + { + kind: 'block', + type: 'set_angular_velocity', + }, { kind: 'block', type: 'set_physics_impostor', @@ -1371,7 +1382,11 @@

Asset Manager

{ kind: 'block', type: 'get_joystick_force', - } + }, + { + kind: 'block', + type: 'clear_collision_cache', + } ] }, { @@ -2909,6 +2924,10 @@

Asset Manager

} } + clearCollisionCache() { + this.processedCollisions.clear(); + } + onCollision(target1, target2, callback) { const impostor1 = this._getPhysicsImpostor(target1); @@ -3081,6 +3100,20 @@

Asset Manager

} } + setLinearVelocity(target, x, y, z) { + const mesh = this._getMesh(target); + if (mesh && mesh.physicsImpostor) { + mesh.physicsImpostor.setLinearVelocity(new BABYLON.Vector3(x, y, z)); + } + } + + setAngularVelocity(target, x, y, z) { + const mesh = this._getMesh(target); + if (mesh && mesh.physicsImpostor) { + mesh.physicsImpostor.setAngularVelocity(new BABYLON.Vector3(x, y, z)); + } + } + getPosX(target) { const mesh = this._getMesh(target); return mesh ? mesh.position.x : 0; @@ -5313,6 +5346,36 @@

Asset Manager

colour: 120, tooltip: 'To be used inside an onCollision callback' }, + { + type: 'set_linear_velocity', + message0: 'Set linear velocity of %1 to x: %2 y: %3 z: %4', + args0: [ + { type: 'input_value', name: 'OBJECT' }, + { type: 'input_value', name: 'X', check: 'Number' }, + { type: 'input_value', name: 'Y', check: 'Number' }, + { type: 'input_value', name: 'Z', check: 'Number' }, + ], + "inputsInline": true, + previousStatement: null, + nextStatement: null, + colour: 120, + tooltip: 'Sets the linear velocity of the specified object', + }, + { + type: 'set_angular_velocity', + message0: 'Set angular velocity of %1 to x: %2 y: %3 z: %4', + args0: [ + { type: 'input_value', name: 'OBJECT' }, + { type: 'input_value', name: 'X', check: 'Number' }, + { type: 'input_value', name: 'Y', check: 'Number' }, + { type: 'input_value', name: 'Z', check: 'Number' }, + ], + "inputsInline": true, + previousStatement: null, + nextStatement: null, + colour: 120, + tooltip: 'Sets the angular velocity of the specified object', + }, { type: 'set_gravity', message0: 'Set scene gravity to x: %1 y: %2 z: %3', @@ -5623,6 +5686,15 @@

Asset Manager

"hasCollidedObjectVar": true } }, + { + "type": "clear_collision_cache", + "message0": "clear collision cache", + "previousStatement": null, + "nextStatement": null, + "colour": "#5BA55B", + "tooltip": "Clears the history of processed collisions, allowing them to trigger again.", + "helpUrl": "" + }, { "type": "destroy_object", "message0": "destroy object %1", @@ -6470,6 +6542,10 @@

Asset Manager

return `sceneManager.onCollision(${obj1}, ${obj2}, ${callback});\n`; }; + javascript.javascriptGenerator.forBlock['clear_collision_cache'] = function (block, generator) { + return 'sceneManager.clearCollisionCache();\n'; + }; + javascript.javascriptGenerator.forBlock['destroy_object'] = function (block, generator) { const objectName = generator.valueToCode(block, 'OBJECT', generator.ORDER_ATOMIC) || 'null'; return `sceneManager.destroyObject(${objectName});\n`; @@ -6845,6 +6921,22 @@

Asset Manager

return `sceneManager.applyImpulse(${target}, ${fx}, ${fy}, ${fz}, ${px}, ${py}, ${pz});\n`; }; + javascript.javascriptGenerator.forBlock['set_linear_velocity'] = function (block, generator) { + const target = generator.valueToCode(block, 'OBJECT', generator.ORDER_ATOMIC) || 'null'; + const x = generator.valueToCode(block, 'X', generator.ORDER_ATOMIC) || 0; + const y = generator.valueToCode(block, 'Y', generator.ORDER_ATOMIC) || 0; + const z = generator.valueToCode(block, 'Z', generator.ORDER_ATOMIC) || 0; + return `sceneManager.setLinearVelocity(${target}, ${x}, ${y}, ${z});\n`; + }; + + javascript.javascriptGenerator.forBlock['set_angular_velocity'] = function (block, generator) { + const target = generator.valueToCode(block, 'OBJECT', generator.ORDER_ATOMIC) || 'null'; + const x = generator.valueToCode(block, 'X', generator.ORDER_ATOMIC) || 0; + const y = generator.valueToCode(block, 'Y', generator.ORDER_ATOMIC) || 0; + const z = generator.valueToCode(block, 'Z', generator.ORDER_ATOMIC) || 0; + return `sceneManager.setAngularVelocity(${target}, ${x}, ${y}, ${z});\n`; + }; + javascript.javascriptGenerator.forBlock['get_object_pos'] = function (block, generator) { const axis = block.getFieldValue('AXIS'); const target = generator.valueToCode(block, 'OBJECT', generator.ORDER_ATOMIC) || 'null'; diff --git a/tests/loading_screen.spec.js b/tests/loading_screen.spec.js new file mode 100644 index 0000000..7675825 --- /dev/null +++ b/tests/loading_screen.spec.js @@ -0,0 +1,34 @@ +const { test, expect } = require('@playwright/test'); + +test.describe('Loading Screen Bug Fix', () => { + test.beforeEach(async ({ page }) => { + await page.goto('/'); + // Handle the hero overlay + const startButton = page.locator('#start-button'); + if (await startButton.isVisible()) { + await startButton.click(); + } + }); + + test('Multiple calls to show loading screen should not stack elements', async ({ page }) => { + // Inject and execute code to show loading screen multiple times + const testCode = ` + var loadingScreen = new CustomLoadingScreen('Testing...', 'black', 'white'); + sceneManager.engine.loadingScreen = loadingScreen; + sceneManager.engine.displayLoadingUI(); + sceneManager.engine.displayLoadingUI(); + sceneManager.engine.displayLoadingUI(); + `; + + await page.evaluate((code) => { + window.doRun(code); + }, testCode); + + // Check number of elements with id "customLoadingScreen" + const count = await page.evaluate(() => { + return document.querySelectorAll('#customLoadingScreen').length; + }); + + expect(count).toBe(1); + }); +});