From 8ad051429b5fa189f1fc729280072ac760370f8c Mon Sep 17 00:00:00 2001 From: Dr Tracy Gardner Date: Mon, 15 Jul 2024 16:38:41 +0000 Subject: [PATCH] Added animation switching. --- dev-dist/sw.js | 2 +- main.js | 138 ++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 137 insertions(+), 3 deletions(-) diff --git a/dev-dist/sw.js b/dev-dist/sw.js index 10e8622..6a861dc 100644 --- a/dev-dist/sw.js +++ b/dev-dist/sw.js @@ -82,7 +82,7 @@ define(['./workbox-07658ed7'], (function (workbox) { 'use strict'; "revision": "3ca0b8505b4bec776b69afdba2768812" }, { "url": "index.html", - "revision": "0.huiv818ldb" + "revision": "0.a9s4d27p4i8" }], {}); workbox.cleanupOutdatedCaches(); workbox.registerRoute(new workbox.NavigationRoute(workbox.createHandlerBoundToURL("index.html"), { diff --git a/main.js b/main.js index 821d2a6..961e6ff 100644 --- a/main.js +++ b/main.js @@ -454,6 +454,10 @@ const toolbox = { kind: "block", type: "clear_effects", }, + { + kind: "block", + type: "switch_animation", + }, ], }, { @@ -1457,7 +1461,7 @@ Blockly.Blocks["load_model"] = { changeEvent.type === Blockly.Events.BLOCK_CREATE && changeEvent.ids.includes(this.id) ) { - var variable = this.workspace.getVariable(nextVariableName); + let variable = this.workspace.getVariable(nextVariableName); if (!variable) { variable = this.workspace.createVariable( nextVariableName, @@ -1806,6 +1810,49 @@ Blockly.Blocks["say"] = { }, }; +Blockly.Blocks["switch_animation"] = { + init: function () { + this.appendDummyInput() + .appendField("switch animation of") + .appendField(new Blockly.FieldVariable("mesh"), "MODEL") + .appendField("to") + .appendField( + new Blockly.FieldDropdown(this.getAnimationNames()), + "ANIMATION_NAME", + ); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setColour(160); + this.setTooltip( + "Changes the animation of the specified model to the given animation.", + ); + this.setHelpUrl(""); + }, + + getAnimationNames: function () { + return [ + ["Idle", "Idle"], + ["Walk", "Walk"], + ["Run", "Run"], + ["Wave", "Wave"], + ["Yes", "Yes"], + ["No", "No"], + ["Duck", "Duck"], + ["Fall", "Fall"], + ["HitReact", "HitReact"], + ["Idle_Attack", "Idle_Attack"], + ["Idle_Hold", "Idle_Hold"], + ["Jump", "Jump"], + ["Jump_Idle", "Jump_Idle"], + ["Jump_Land", "Jump_Land"], + ["Punch", "Punch"], + ["Run_Attack", "Run_Attack"], + ["Run_Hold", "Run_Hold"], + ["Walk_Hold", "Walk_Hold"], + ]; + }, +}; + Blockly.Blocks["move_by_vector"] = { init: function () { this.jsonInit({ @@ -2859,7 +2906,7 @@ function loadModelIntoScene(modelName, modelId, scale, x, y, z) { boxBody.setLinearDamping(0); bb.physics = boxBody; - console.log("Configured", modelId); + //console.log("Configured", modelId); }, null, function (error) { @@ -3359,6 +3406,93 @@ javascriptGenerator.forBlock["clear_effects"] = function (block) { });\n`; }; +javascriptGenerator.forBlock["switch_animation"] = function (block) { + const modelName = javascriptGenerator.nameDB_.getName( + block.getFieldValue("MODEL"), + Blockly.Names.NameType.VARIABLE, + ); + const animationName = block.getFieldValue("ANIMATION_NAME"); + + // Wrap the logic in an asynchronous IIFE + return ` +(async function() { + const maxAttempts = 100; + let attempts = 0; + + const findModelAndSwitchAnimation = async () => { + const model = scene.getMeshByName(${modelName}); + if (model) { + window.switchToAnimation(scene, model, '${animationName}'); + } else if (attempts < maxAttempts) { + attempts++; + await new Promise(resolve => setTimeout(resolve, 500)); // Wait 500ms before retrying + findModelAndSwitchAnimation(); + } else { + console.error('Model ' + ${modelName} + ' not found after ' + maxAttempts + ' attempts.'); + } + }; + + await findModelAndSwitchAnimation(); +})(); + `; +}; + +function switchToAnimation(scene, mesh, animationName, loop = true) { + const newAnimationName = animationName; + + //console.log(`Switching ${mesh.name} to animation ${newAnimationName}`); + + //const mesh = scene.getMeshByName(meshName); + if (!mesh) { + console.error(`Mesh ${mesh.name} not found.`); + return null; + } + + let targetAnimationGroup = scene.animationGroups.find( + (group) => + group.name === newAnimationName && + animationGroupTargetsDescendant(group, mesh), + ); + + if (!targetAnimationGroup) { + console.error(`Animation "${newAnimationName}" not found.`); + return null; + } + + if (!mesh.animationGroups) { + mesh.animationGroups = []; + stopAnimationsTargetingMesh(scene, mesh); + //console.log(`Stopping all animations on mesh`); + } + + if ( + mesh.animationGroups[0] && + mesh.animationGroups[0].name !== newAnimationName + ) { + stopAnimationsTargetingMesh(scene, mesh); + + //console.log(`Stopping animation ${mesh.animationGroups[0].name}`); + mesh.animationGroups[0].stop(); + mesh.animationGroups = []; + } + + if (!mesh.animationGroups[0]) { + //console.log(`Starting animation ${newAnimationName}`); + mesh.animationGroups[0] = targetAnimationGroup; + mesh.animationGroups[0].start( + loop, + 1.0, + targetAnimationGroup.from, + targetAnimationGroup.to, + false, + ); + } + + return targetAnimationGroup; +} + +window.switchToAnimation = switchToAnimation; + javascriptGenerator.forBlock["move_forward"] = function (block) { const modelName = javascriptGenerator.nameDB_.getName( block.getFieldValue("MODEL"),