@needle-tools/engine 4.7.0 → 4.7.2-alpha
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +3782 -3778
- package/LICENSE.md +10 -10
- package/README.md +64 -64
- package/components.needle.json +1 -1
- package/dist/generateMeshBVH.worker-Cdfpaq5W.js +25 -0
- package/dist/gltf-progressive-YjtQYFa9.js +1052 -0
- package/dist/gltf-progressive-yOP1mp5W.min.js +8 -0
- package/dist/gltf-progressive-zdhlW609.umd.cjs +8 -0
- package/dist/{needle-engine.bundle-BFsiOavn.min.js → needle-engine.bundle-BhDF-YSv.min.js} +107 -107
- package/dist/{needle-engine.bundle-BxOXkBoQ.umd.cjs → needle-engine.bundle-D2myV4E4.umd.cjs} +114 -114
- package/dist/{needle-engine.bundle-BodidWhS.js → needle-engine.bundle-gp00DTS4.js} +2932 -2920
- package/dist/needle-engine.d.ts +129 -130
- package/dist/needle-engine.js +4 -4
- package/dist/needle-engine.min.js +1 -1
- package/dist/needle-engine.umd.cjs +1 -1
- package/dist/{postprocessing-CjW23fio.umd.cjs → postprocessing-8AQTeZsr.umd.cjs} +2 -2
- package/dist/{postprocessing-xYQWCHFu.min.js → postprocessing-BDScN9yu.min.js} +2 -2
- package/dist/{postprocessing-DYLNOL3W.js → postprocessing-BkxN_08g.js} +3 -3
- package/dist/{three-DuDKwKB8.min.js → three-Boa-jOq-.min.js} +33 -33
- package/dist/{three-DrqIzZTH.js → three-Bz6X1mrw.js} +4198 -4198
- package/dist/{three-B_hneGZr.umd.cjs → three-DMrv-4ar.umd.cjs} +4 -4
- package/dist/{three-examples-X3OadjXB.umd.cjs → three-examples-C7ryg8vN.umd.cjs} +3 -3
- package/dist/{three-examples-DaDLBuy6.min.js → three-examples-DuVhxqft.min.js} +14 -14
- package/dist/{three-examples-B50TT3Iu.js → three-examples-GggCDHv0.js} +5 -5
- package/dist/{three-mesh-ui-CxuWt7m-.js → three-mesh-ui-CLNOfsWn.js} +1 -1
- package/dist/{three-mesh-ui-B3p3gyUz.min.js → three-mesh-ui-CY6Izc7C.min.js} +1 -1
- package/dist/{three-mesh-ui-CQiIQIlA.umd.cjs → three-mesh-ui-CwlN0FUC.umd.cjs} +1 -1
- package/dist/{vendor-BmYIgaS1.js → vendor-BSD1RQIh.js} +3 -3
- package/dist/{vendor-Cavtu3CP.umd.cjs → vendor-DHr4aqIZ.umd.cjs} +3 -3
- package/dist/{vendor-BlSxe9JJ.min.js → vendor-zxXa3Dmr.min.js} +3 -3
- package/lib/asap/needle-asap.d.ts +1 -1
- package/lib/asap/needle-asap.js +95 -95
- package/lib/asap/sessiongranted.d.ts +3 -3
- package/lib/asap/sessiongranted.js +65 -65
- package/lib/asap/utils.d.ts +1 -1
- package/lib/asap/utils.js +3 -3
- package/lib/engine/analytics/index.d.ts +6 -6
- package/lib/engine/analytics/index.js +12 -12
- package/lib/engine/analytics/lcp.d.ts +3 -3
- package/lib/engine/analytics/lcp.js +34 -34
- package/lib/engine/api.d.ts +82 -82
- package/lib/engine/api.js +81 -81
- package/lib/engine/assets/index.d.ts +11 -11
- package/lib/engine/assets/index.js +47 -47
- package/lib/engine/assets/static.d.ts +1 -1
- package/lib/engine/assets/static.js +4 -4
- package/lib/engine/codegen/register_types.d.ts +1 -1
- package/lib/engine/codegen/register_types.js +300 -300
- package/lib/engine/debug/debug.d.ts +15 -15
- package/lib/engine/debug/debug.js +44 -44
- package/lib/engine/debug/debug_console.d.ts +2 -2
- package/lib/engine/debug/debug_console.js +307 -307
- package/lib/engine/debug/debug_overlay.d.ts +22 -22
- package/lib/engine/debug/debug_overlay.js +316 -316
- package/lib/engine/debug/debug_spatial_console.d.ts +2 -2
- package/lib/engine/debug/debug_spatial_console.js +390 -390
- package/lib/engine/debug/index.d.ts +2 -2
- package/lib/engine/debug/index.js +2 -2
- package/lib/engine/engine_addressables.d.ts +164 -166
- package/lib/engine/engine_addressables.js +601 -608
- package/lib/engine/engine_addressables.js.map +1 -1
- package/lib/engine/engine_animation.d.ts +43 -43
- package/lib/engine/engine_animation.js +133 -133
- package/lib/engine/engine_application.d.ts +45 -45
- package/lib/engine/engine_application.js +104 -104
- package/lib/engine/engine_assetdatabase.d.ts +25 -25
- package/lib/engine/engine_assetdatabase.js +346 -346
- package/lib/engine/engine_audio.d.ts +4 -4
- package/lib/engine/engine_audio.js +23 -23
- package/lib/engine/engine_camera.d.ts +13 -13
- package/lib/engine/engine_camera.js +30 -30
- package/lib/engine/engine_components.d.ts +110 -110
- package/lib/engine/engine_components.js +374 -374
- package/lib/engine/engine_components_internal.d.ts +9 -9
- package/lib/engine/engine_components_internal.js +36 -36
- package/lib/engine/engine_constants.d.ts +10 -10
- package/lib/engine/engine_constants.js +41 -41
- package/lib/engine/engine_context.d.ts +475 -475
- package/lib/engine/engine_context.js +1673 -1673
- package/lib/engine/engine_context_registry.d.ts +71 -71
- package/lib/engine/engine_context_registry.js +117 -117
- package/lib/engine/engine_coroutine.d.ts +35 -35
- package/lib/engine/engine_coroutine.js +52 -52
- package/lib/engine/engine_create_objects.d.ts +119 -119
- package/lib/engine/engine_create_objects.js +320 -320
- package/lib/engine/engine_default_parameters.d.ts +2 -2
- package/lib/engine/engine_default_parameters.js +3 -3
- package/lib/engine/engine_editor-sync.d.ts +21 -21
- package/lib/engine/engine_editor-sync.js +4 -4
- package/lib/engine/engine_fileloader.d.ts +2 -2
- package/lib/engine/engine_fileloader.js +8 -8
- package/lib/engine/engine_gameobject.d.ts +68 -68
- package/lib/engine/engine_gameobject.js +619 -619
- package/lib/engine/engine_generic_utils.d.ts +1 -1
- package/lib/engine/engine_generic_utils.js +13 -13
- package/lib/engine/engine_gizmos.d.ts +149 -149
- package/lib/engine/engine_gizmos.js +530 -530
- package/lib/engine/engine_gltf.d.ts +12 -12
- package/lib/engine/engine_gltf.js +15 -15
- package/lib/engine/engine_gltf_builtin_components.d.ts +11 -11
- package/lib/engine/engine_gltf_builtin_components.js +341 -341
- package/lib/engine/engine_hot_reload.d.ts +8 -8
- package/lib/engine/engine_hot_reload.js +197 -197
- package/lib/engine/engine_input.d.ts +362 -362
- package/lib/engine/engine_input.js +1294 -1294
- package/lib/engine/engine_input_utils.d.ts +2 -2
- package/lib/engine/engine_input_utils.js +22 -22
- package/lib/engine/engine_instancing.d.ts +19 -19
- package/lib/engine/engine_instancing.js +39 -39
- package/lib/engine/engine_license.d.ts +11 -11
- package/lib/engine/engine_license.js +369 -369
- package/lib/engine/engine_lifecycle_api.d.ts +83 -83
- package/lib/engine/engine_lifecycle_api.js +106 -106
- package/lib/engine/engine_lifecycle_functions_internal.d.ts +32 -32
- package/lib/engine/engine_lifecycle_functions_internal.js +146 -146
- package/lib/engine/engine_lightdata.d.ts +23 -23
- package/lib/engine/engine_lightdata.js +101 -91
- package/lib/engine/engine_lightdata.js.map +1 -1
- package/lib/engine/engine_loaders.callbacks.d.ts +97 -97
- package/lib/engine/engine_loaders.callbacks.js +86 -86
- package/lib/engine/engine_loaders.d.ts +48 -48
- package/lib/engine/engine_loaders.gltf.d.ts +13 -13
- package/lib/engine/engine_loaders.gltf.js +62 -62
- package/lib/engine/engine_loaders.js +337 -337
- package/lib/engine/engine_lods.d.ts +35 -31
- package/lib/engine/engine_lods.js +160 -146
- package/lib/engine/engine_lods.js.map +1 -1
- package/lib/engine/engine_mainloop_utils.d.ts +32 -32
- package/lib/engine/engine_mainloop_utils.js +466 -466
- package/lib/engine/engine_math.d.ts +114 -114
- package/lib/engine/engine_math.js +247 -247
- package/lib/engine/engine_modules.d.ts +36 -36
- package/lib/engine/engine_modules.js +85 -85
- package/lib/engine/engine_networking.d.ts +260 -260
- package/lib/engine/engine_networking.js +764 -764
- package/lib/engine/engine_networking_auto.d.ts +24 -24
- package/lib/engine/engine_networking_auto.js +310 -310
- package/lib/engine/engine_networking_blob.d.ts +48 -48
- package/lib/engine/engine_networking_blob.js +228 -228
- package/lib/engine/engine_networking_files.d.ts +35 -35
- package/lib/engine/engine_networking_files.js +172 -172
- package/lib/engine/engine_networking_files_default_components.d.ts +6 -6
- package/lib/engine/engine_networking_files_default_components.js +42 -42
- package/lib/engine/engine_networking_instantiate.d.ts +100 -100
- package/lib/engine/engine_networking_instantiate.js +345 -345
- package/lib/engine/engine_networking_peer.d.ts +15 -15
- package/lib/engine/engine_networking_peer.js +132 -132
- package/lib/engine/engine_networking_streams.d.ts +123 -123
- package/lib/engine/engine_networking_streams.js +645 -645
- package/lib/engine/engine_networking_types.d.ts +22 -22
- package/lib/engine/engine_networking_types.js +7 -7
- package/lib/engine/engine_networking_utils.d.ts +2 -2
- package/lib/engine/engine_networking_utils.js +20 -20
- package/lib/engine/engine_networking_websocket.d.ts +1 -1
- package/lib/engine/engine_networking_websocket.js +2 -2
- package/lib/engine/engine_patcher.d.ts +10 -10
- package/lib/engine/engine_patcher.js +142 -142
- package/lib/engine/engine_physics.d.ts +152 -152
- package/lib/engine/engine_physics.js +645 -645
- package/lib/engine/engine_physics.types.d.ts +40 -40
- package/lib/engine/engine_physics.types.js +33 -33
- package/lib/engine/engine_physics_rapier.d.ts +147 -147
- package/lib/engine/engine_physics_rapier.js +1433 -1433
- package/lib/engine/engine_playerview.d.ts +26 -26
- package/lib/engine/engine_playerview.js +64 -64
- package/lib/engine/engine_scenelighting.d.ts +71 -71
- package/lib/engine/engine_scenelighting.js +226 -226
- package/lib/engine/engine_serialization.d.ts +3 -3
- package/lib/engine/engine_serialization.js +3 -3
- package/lib/engine/engine_serialization_builtin_serializer.d.ts +72 -72
- package/lib/engine/engine_serialization_builtin_serializer.js +403 -403
- package/lib/engine/engine_serialization_core.d.ts +94 -94
- package/lib/engine/engine_serialization_core.js +607 -607
- package/lib/engine/engine_serialization_decorator.d.ts +23 -23
- package/lib/engine/engine_serialization_decorator.js +66 -66
- package/lib/engine/engine_setup.d.ts +1 -1
- package/lib/engine/engine_setup.js +2 -2
- package/lib/engine/engine_shaders.d.ts +53 -53
- package/lib/engine/engine_shaders.js +252 -252
- package/lib/engine/engine_shims.d.ts +4 -4
- package/lib/engine/engine_shims.js +24 -24
- package/lib/engine/engine_test_utils.d.ts +39 -39
- package/lib/engine/engine_test_utils.js +83 -83
- package/lib/engine/engine_texture.d.ts +28 -28
- package/lib/engine/engine_texture.js +64 -64
- package/lib/engine/engine_three_utils.d.ts +204 -204
- package/lib/engine/engine_three_utils.js +788 -788
- package/lib/engine/engine_time.d.ts +51 -51
- package/lib/engine/engine_time.js +82 -82
- package/lib/engine/engine_time_utils.d.ts +88 -88
- package/lib/engine/engine_time_utils.js +215 -215
- package/lib/engine/engine_tonemapping.d.ts +6 -6
- package/lib/engine/engine_tonemapping.js +197 -197
- package/lib/engine/engine_types.d.ts +578 -578
- package/lib/engine/engine_types.js +95 -95
- package/lib/engine/engine_typestore.d.ts +28 -28
- package/lib/engine/engine_typestore.js +55 -55
- package/lib/engine/engine_util_decorator.d.ts +13 -13
- package/lib/engine/engine_util_decorator.js +116 -116
- package/lib/engine/engine_utils.d.ts +248 -248
- package/lib/engine/engine_utils.js +1012 -1012
- package/lib/engine/engine_utils_format.d.ts +24 -24
- package/lib/engine/engine_utils_format.js +239 -239
- package/lib/engine/engine_utils_screenshot.d.ts +159 -159
- package/lib/engine/engine_utils_screenshot.js +522 -522
- package/lib/engine/engine_utils_screenshot.xr.d.ts +5 -5
- package/lib/engine/engine_utils_screenshot.xr.js +90 -90
- package/lib/engine/engine_xr.d.ts +1 -1
- package/lib/engine/engine_xr.js +1 -1
- package/lib/engine/export/gltf/Writers.d.ts +19 -19
- package/lib/engine/export/gltf/Writers.js +24 -24
- package/lib/engine/export/gltf/index.d.ts +11 -11
- package/lib/engine/export/gltf/index.js +123 -123
- package/lib/engine/export/index.d.ts +2 -2
- package/lib/engine/export/index.js +2 -2
- package/lib/engine/export/state.d.ts +7 -7
- package/lib/engine/export/state.js +17 -17
- package/lib/engine/export/utils.d.ts +2 -2
- package/lib/engine/export/utils.js +7 -7
- package/lib/engine/extensions/EXT_texture_exr.d.ts +8 -8
- package/lib/engine/extensions/EXT_texture_exr.js +32 -32
- package/lib/engine/extensions/NEEDLE_animator_controller_model.d.ts +122 -122
- package/lib/engine/extensions/NEEDLE_animator_controller_model.js +95 -95
- package/lib/engine/extensions/NEEDLE_components.d.ts +35 -35
- package/lib/engine/extensions/NEEDLE_components.js +220 -220
- package/lib/engine/extensions/NEEDLE_gameobject_data.d.ts +10 -10
- package/lib/engine/extensions/NEEDLE_gameobject_data.js +57 -57
- package/lib/engine/extensions/NEEDLE_lighting_settings.d.ts +37 -37
- package/lib/engine/extensions/NEEDLE_lighting_settings.js +157 -157
- package/lib/engine/extensions/NEEDLE_lightmaps.d.ts +18 -18
- package/lib/engine/extensions/NEEDLE_lightmaps.js +99 -99
- package/lib/engine/extensions/NEEDLE_persistent_assets.d.ts +11 -11
- package/lib/engine/extensions/NEEDLE_persistent_assets.js +63 -63
- package/lib/engine/extensions/NEEDLE_progressive.d.ts +1 -1
- package/lib/engine/extensions/NEEDLE_progressive.js +1 -1
- package/lib/engine/extensions/NEEDLE_render_objects.d.ts +13 -13
- package/lib/engine/extensions/NEEDLE_render_objects.js +159 -159
- package/lib/engine/extensions/NEEDLE_techniques_webgl.d.ts +38 -38
- package/lib/engine/extensions/NEEDLE_techniques_webgl.js +564 -564
- package/lib/engine/extensions/extension_resolver.d.ts +4 -4
- package/lib/engine/extensions/extension_resolver.js +1 -1
- package/lib/engine/extensions/extension_utils.d.ts +12 -12
- package/lib/engine/extensions/extension_utils.js +152 -152
- package/lib/engine/extensions/extensions.d.ts +32 -32
- package/lib/engine/extensions/extensions.js +107 -107
- package/lib/engine/extensions/index.d.ts +6 -6
- package/lib/engine/extensions/index.js +6 -6
- package/lib/engine/extensions/usage_tracker.d.ts +13 -13
- package/lib/engine/extensions/usage_tracker.js +65 -65
- package/lib/engine/js-extensions/Camera.d.ts +1 -1
- package/lib/engine/js-extensions/Camera.js +39 -39
- package/lib/engine/js-extensions/ExtensionUtils.d.ts +9 -9
- package/lib/engine/js-extensions/ExtensionUtils.js +67 -67
- package/lib/engine/js-extensions/Layers.d.ts +6 -6
- package/lib/engine/js-extensions/Layers.js +22 -22
- package/lib/engine/js-extensions/Object3D.d.ts +120 -120
- package/lib/engine/js-extensions/Object3D.js +136 -136
- package/lib/engine/js-extensions/RGBAColor.d.ts +23 -23
- package/lib/engine/js-extensions/RGBAColor.js +111 -111
- package/lib/engine/js-extensions/Vector.d.ts +3 -3
- package/lib/engine/js-extensions/Vector.js +13 -13
- package/lib/engine/js-extensions/index.d.ts +5 -5
- package/lib/engine/js-extensions/index.js +5 -5
- package/lib/engine/physics/workers/mesh-bvh/GenerateMeshBVHWorker.d.ts +4 -4
- package/lib/engine/physics/workers/mesh-bvh/GenerateMeshBVHWorker.js +79 -79
- package/lib/engine/shaders/shaderData.d.ts +55 -55
- package/lib/engine/shaders/shaderData.js +58 -58
- package/lib/engine/tests/test_utils.d.ts +2 -2
- package/lib/engine/tests/test_utils.js +53 -53
- package/lib/engine/webcomponents/WebXRButtons.d.ts +56 -56
- package/lib/engine/webcomponents/WebXRButtons.js +230 -230
- package/lib/engine/webcomponents/api.d.ts +5 -5
- package/lib/engine/webcomponents/api.js +4 -4
- package/lib/engine/webcomponents/buttons.d.ts +51 -51
- package/lib/engine/webcomponents/buttons.js +264 -264
- package/lib/engine/webcomponents/fonts.d.ts +9 -9
- package/lib/engine/webcomponents/fonts.js +32 -32
- package/lib/engine/webcomponents/icons.d.ts +9 -9
- package/lib/engine/webcomponents/icons.js +52 -52
- package/lib/engine/webcomponents/index.d.ts +1 -1
- package/lib/engine/webcomponents/index.js +1 -1
- package/lib/engine/webcomponents/logo-element.d.ts +10 -10
- package/lib/engine/webcomponents/logo-element.js +67 -67
- package/lib/engine/webcomponents/needle menu/needle-menu-spatial.d.ts +37 -37
- package/lib/engine/webcomponents/needle menu/needle-menu-spatial.js +513 -513
- package/lib/engine/webcomponents/needle menu/needle-menu.d.ts +155 -155
- package/lib/engine/webcomponents/needle menu/needle-menu.js +1029 -1029
- package/lib/engine/webcomponents/needle-button.d.ts +34 -34
- package/lib/engine/webcomponents/needle-button.js +161 -161
- package/lib/engine/webcomponents/needle-engine.ar-overlay.d.ts +21 -21
- package/lib/engine/webcomponents/needle-engine.ar-overlay.js +166 -166
- package/lib/engine/webcomponents/needle-engine.attributes.d.ts +69 -69
- package/lib/engine/webcomponents/needle-engine.attributes.js +1 -1
- package/lib/engine/webcomponents/needle-engine.d.ts +116 -116
- package/lib/engine/webcomponents/needle-engine.extras.d.ts +6 -6
- package/lib/engine/webcomponents/needle-engine.extras.js +13 -13
- package/lib/engine/webcomponents/needle-engine.js +821 -821
- package/lib/engine/webcomponents/needle-engine.loading.d.ts +44 -44
- package/lib/engine/webcomponents/needle-engine.loading.js +341 -341
- package/lib/engine/xr/NeedleXRController.d.ts +313 -313
- package/lib/engine/xr/NeedleXRController.js +1007 -1007
- package/lib/engine/xr/NeedleXRSession.d.ts +340 -340
- package/lib/engine/xr/NeedleXRSession.js +1463 -1463
- package/lib/engine/xr/NeedleXRSync.d.ts +22 -22
- package/lib/engine/xr/NeedleXRSync.js +188 -188
- package/lib/engine/xr/SceneTransition.d.ts +18 -18
- package/lib/engine/xr/SceneTransition.js +69 -69
- package/lib/engine/xr/TempXRContext.d.ts +34 -34
- package/lib/engine/xr/TempXRContext.js +187 -187
- package/lib/engine/xr/XRRig.d.ts +7 -7
- package/lib/engine/xr/XRRig.js +1 -1
- package/lib/engine/xr/api.d.ts +6 -6
- package/lib/engine/xr/api.js +6 -6
- package/lib/engine/xr/events.d.ts +66 -66
- package/lib/engine/xr/events.js +93 -93
- package/lib/engine/xr/internal.d.ts +12 -12
- package/lib/engine/xr/internal.js +25 -25
- package/lib/engine/xr/usdz.d.ts +12 -12
- package/lib/engine/xr/usdz.js +29 -29
- package/lib/engine/xr/utils.d.ts +11 -11
- package/lib/engine/xr/utils.js +34 -34
- package/lib/engine-components/AlignmentConstraint.d.ts +10 -10
- package/lib/engine-components/AlignmentConstraint.js +39 -39
- package/lib/engine-components/Animation.d.ts +156 -156
- package/lib/engine-components/Animation.js +508 -508
- package/lib/engine-components/AnimationCurve.d.ts +40 -40
- package/lib/engine-components/AnimationCurve.js +159 -159
- package/lib/engine-components/AnimationUtils.d.ts +8 -8
- package/lib/engine-components/AnimationUtils.js +27 -27
- package/lib/engine-components/AnimationUtilsAutoplay.d.ts +1 -1
- package/lib/engine-components/AnimationUtilsAutoplay.js +39 -39
- package/lib/engine-components/Animator.d.ts +217 -217
- package/lib/engine-components/Animator.js +354 -354
- package/lib/engine-components/AnimatorController.d.ts +227 -227
- package/lib/engine-components/AnimatorController.js +1152 -1152
- package/lib/engine-components/AudioListener.d.ts +33 -33
- package/lib/engine-components/AudioListener.js +86 -86
- package/lib/engine-components/AudioSource.d.ts +217 -217
- package/lib/engine-components/AudioSource.js +635 -635
- package/lib/engine-components/AvatarLoader.d.ts +80 -80
- package/lib/engine-components/AvatarLoader.js +231 -231
- package/lib/engine-components/AxesHelper.d.ts +32 -32
- package/lib/engine-components/AxesHelper.js +67 -67
- package/lib/engine-components/BasicIKConstraint.d.ts +9 -9
- package/lib/engine-components/BasicIKConstraint.js +43 -43
- package/lib/engine-components/BoxCollider.d.ts +2 -2
- package/lib/engine-components/BoxCollider.js +2 -2
- package/lib/engine-components/BoxHelperComponent.d.ts +47 -47
- package/lib/engine-components/BoxHelperComponent.js +102 -102
- package/lib/engine-components/Camera.d.ts +231 -231
- package/lib/engine-components/Camera.js +700 -700
- package/lib/engine-components/CameraUtils.d.ts +1 -1
- package/lib/engine-components/CameraUtils.js +123 -123
- package/lib/engine-components/CharacterController.d.ts +55 -55
- package/lib/engine-components/CharacterController.js +236 -236
- package/lib/engine-components/Collider.d.ts +188 -188
- package/lib/engine-components/Collider.js +369 -369
- package/lib/engine-components/Component.d.ts +792 -792
- package/lib/engine-components/Component.js +920 -920
- package/lib/engine-components/ContactShadows.d.ts +94 -94
- package/lib/engine-components/ContactShadows.js +453 -453
- package/lib/engine-components/DeleteBox.d.ts +19 -19
- package/lib/engine-components/DeleteBox.js +58 -58
- package/lib/engine-components/DeviceFlag.d.ts +16 -16
- package/lib/engine-components/DeviceFlag.js +47 -47
- package/lib/engine-components/DragControls.d.ts +170 -170
- package/lib/engine-components/DragControls.js +1421 -1421
- package/lib/engine-components/DropListener.d.ts +215 -215
- package/lib/engine-components/DropListener.js +642 -642
- package/lib/engine-components/Duplicatable.d.ts +35 -35
- package/lib/engine-components/Duplicatable.js +202 -202
- package/lib/engine-components/EventList.d.ts +54 -54
- package/lib/engine-components/EventList.js +232 -232
- package/lib/engine-components/EventTrigger.d.ts +33 -33
- package/lib/engine-components/EventTrigger.js +75 -75
- package/lib/engine-components/EventType.d.ts +22 -22
- package/lib/engine-components/EventType.js +23 -23
- package/lib/engine-components/Fog.d.ts +22 -22
- package/lib/engine-components/Fog.js +61 -61
- package/lib/engine-components/Gizmos.d.ts +17 -17
- package/lib/engine-components/Gizmos.js +64 -64
- package/lib/engine-components/GridHelper.d.ts +20 -20
- package/lib/engine-components/GridHelper.js +54 -54
- package/lib/engine-components/GroundProjection.d.ts +67 -67
- package/lib/engine-components/GroundProjection.js +343 -343
- package/lib/engine-components/Interactable.d.ts +12 -12
- package/lib/engine-components/Interactable.js +12 -12
- package/lib/engine-components/Joints.d.ts +19 -19
- package/lib/engine-components/Joints.js +51 -51
- package/lib/engine-components/LODGroup.d.ts +35 -35
- package/lib/engine-components/LODGroup.js +152 -152
- package/lib/engine-components/Light.d.ts +180 -180
- package/lib/engine-components/Light.js +535 -535
- package/lib/engine-components/LookAtConstraint.d.ts +19 -19
- package/lib/engine-components/LookAtConstraint.js +35 -35
- package/lib/engine-components/NeedleMenu.d.ts +50 -50
- package/lib/engine-components/NeedleMenu.js +92 -92
- package/lib/engine-components/NestedGltf.d.ts +25 -25
- package/lib/engine-components/NestedGltf.js +88 -88
- package/lib/engine-components/Networking.d.ts +54 -54
- package/lib/engine-components/Networking.js +112 -112
- package/lib/engine-components/OffsetConstraint.d.ts +14 -14
- package/lib/engine-components/OffsetConstraint.js +65 -65
- package/lib/engine-components/OrbitControls.d.ts +268 -268
- package/lib/engine-components/OrbitControls.js +1015 -1015
- package/lib/engine-components/PlayerColor.d.ts +19 -19
- package/lib/engine-components/PlayerColor.js +94 -94
- package/lib/engine-components/ReflectionProbe.d.ts +28 -28
- package/lib/engine-components/ReflectionProbe.js +204 -204
- package/lib/engine-components/Renderer.d.ts +153 -153
- package/lib/engine-components/Renderer.js +834 -834
- package/lib/engine-components/RendererInstancing.d.ts +140 -140
- package/lib/engine-components/RendererInstancing.js +744 -744
- package/lib/engine-components/RendererInstancing.js.map +1 -1
- package/lib/engine-components/RendererLightmap.d.ts +24 -24
- package/lib/engine-components/RendererLightmap.js +182 -182
- package/lib/engine-components/RigidBody.d.ts +155 -155
- package/lib/engine-components/RigidBody.js +517 -517
- package/lib/engine-components/SceneSwitcher.d.ts +263 -263
- package/lib/engine-components/SceneSwitcher.js +971 -971
- package/lib/engine-components/ScreenCapture.d.ts +144 -144
- package/lib/engine-components/ScreenCapture.js +547 -547
- package/lib/engine-components/ShadowCatcher.d.ts +33 -33
- package/lib/engine-components/ShadowCatcher.js +166 -166
- package/lib/engine-components/Skybox.d.ts +88 -88
- package/lib/engine-components/Skybox.js +469 -469
- package/lib/engine-components/SmoothFollow.d.ts +34 -34
- package/lib/engine-components/SmoothFollow.js +82 -82
- package/lib/engine-components/SpatialTrigger.d.ts +102 -102
- package/lib/engine-components/SpatialTrigger.js +225 -225
- package/lib/engine-components/SpectatorCamera.d.ts +111 -111
- package/lib/engine-components/SpectatorCamera.js +715 -715
- package/lib/engine-components/SphereCollider.d.ts +2 -2
- package/lib/engine-components/SphereCollider.js +2 -2
- package/lib/engine-components/SpriteRenderer.d.ts +132 -132
- package/lib/engine-components/SpriteRenderer.js +472 -472
- package/lib/engine-components/SyncedCamera.d.ts +41 -41
- package/lib/engine-components/SyncedCamera.js +199 -199
- package/lib/engine-components/SyncedRoom.d.ts +106 -106
- package/lib/engine-components/SyncedRoom.js +371 -371
- package/lib/engine-components/SyncedTransform.d.ts +94 -94
- package/lib/engine-components/SyncedTransform.js +331 -331
- package/lib/engine-components/TestRunner.d.ts +16 -16
- package/lib/engine-components/TestRunner.js +102 -102
- package/lib/engine-components/TransformGizmo.d.ts +75 -75
- package/lib/engine-components/TransformGizmo.js +209 -209
- package/lib/engine-components/VideoPlayer.d.ts +184 -184
- package/lib/engine-components/VideoPlayer.js +978 -978
- package/lib/engine-components/Voip.d.ts +67 -67
- package/lib/engine-components/Voip.js +360 -360
- package/lib/engine-components/api.d.ts +51 -51
- package/lib/engine-components/api.js +50 -50
- package/lib/engine-components/avatar/AvatarBlink_Simple.d.ts +11 -11
- package/lib/engine-components/avatar/AvatarBlink_Simple.js +76 -76
- package/lib/engine-components/avatar/AvatarEyeLook_Rotation.d.ts +14 -14
- package/lib/engine-components/avatar/AvatarEyeLook_Rotation.js +68 -68
- package/lib/engine-components/avatar/Avatar_Brain_LookAt.d.ts +29 -29
- package/lib/engine-components/avatar/Avatar_Brain_LookAt.js +121 -121
- package/lib/engine-components/avatar/Avatar_MouthShapes.d.ts +15 -15
- package/lib/engine-components/avatar/Avatar_MouthShapes.js +79 -79
- package/lib/engine-components/avatar/Avatar_MustacheShake.d.ts +9 -9
- package/lib/engine-components/avatar/Avatar_MustacheShake.js +29 -29
- package/lib/engine-components/codegen/components.d.ts +216 -216
- package/lib/engine-components/codegen/components.js +218 -218
- package/lib/engine-components/debug/LogStats.d.ts +5 -5
- package/lib/engine-components/debug/LogStats.js +18 -18
- package/lib/engine-components/export/gltf/GltfExport.d.ts +30 -30
- package/lib/engine-components/export/gltf/GltfExport.js +246 -246
- package/lib/engine-components/export/gltf/index.d.ts +1 -1
- package/lib/engine-components/export/gltf/index.js +1 -1
- package/lib/engine-components/export/index.d.ts +1 -1
- package/lib/engine-components/export/index.js +1 -1
- package/lib/engine-components/export/usdz/Extension.d.ts +22 -22
- package/lib/engine-components/export/usdz/Extension.js +1 -1
- package/lib/engine-components/export/usdz/ThreeUSDZExporter.d.ts +162 -162
- package/lib/engine-components/export/usdz/ThreeUSDZExporter.js +1789 -1789
- package/lib/engine-components/export/usdz/USDZExporter.d.ts +130 -130
- package/lib/engine-components/export/usdz/USDZExporter.js +663 -663
- package/lib/engine-components/export/usdz/extensions/Animation.d.ts +106 -106
- package/lib/engine-components/export/usdz/extensions/Animation.js +1071 -1071
- package/lib/engine-components/export/usdz/extensions/DocumentExtension.d.ts +5 -5
- package/lib/engine-components/export/usdz/extensions/DocumentExtension.js +6 -6
- package/lib/engine-components/export/usdz/extensions/NodeMaterialConverter.d.ts +10 -10
- package/lib/engine-components/export/usdz/extensions/NodeMaterialConverter.js +451 -451
- package/lib/engine-components/export/usdz/extensions/USDZText.d.ts +54 -54
- package/lib/engine-components/export/usdz/extensions/USDZText.js +203 -203
- package/lib/engine-components/export/usdz/extensions/USDZUI.d.ts +8 -8
- package/lib/engine-components/export/usdz/extensions/USDZUI.js +158 -158
- package/lib/engine-components/export/usdz/extensions/behavior/Actions.d.ts +30 -30
- package/lib/engine-components/export/usdz/extensions/behavior/Actions.js +88 -88
- package/lib/engine-components/export/usdz/extensions/behavior/AudioExtension.d.ts +10 -10
- package/lib/engine-components/export/usdz/extensions/behavior/AudioExtension.js +86 -86
- package/lib/engine-components/export/usdz/extensions/behavior/Behaviour.d.ts +28 -28
- package/lib/engine-components/export/usdz/extensions/behavior/Behaviour.js +290 -290
- package/lib/engine-components/export/usdz/extensions/behavior/BehaviourComponents.d.ts +190 -190
- package/lib/engine-components/export/usdz/extensions/behavior/BehaviourComponents.js +1060 -1060
- package/lib/engine-components/export/usdz/extensions/behavior/BehavioursBuilder.d.ts +135 -135
- package/lib/engine-components/export/usdz/extensions/behavior/BehavioursBuilder.js +548 -548
- package/lib/engine-components/export/usdz/extensions/behavior/PhysicsExtension.d.ts +7 -7
- package/lib/engine-components/export/usdz/extensions/behavior/PhysicsExtension.js +115 -115
- package/lib/engine-components/export/usdz/index.d.ts +3 -3
- package/lib/engine-components/export/usdz/index.js +2 -2
- package/lib/engine-components/export/usdz/utils/animationutils.d.ts +7 -7
- package/lib/engine-components/export/usdz/utils/animationutils.js +163 -163
- package/lib/engine-components/export/usdz/utils/quicklook.d.ts +2 -2
- package/lib/engine-components/export/usdz/utils/quicklook.js +43 -43
- package/lib/engine-components/particlesystem/ParticleSystem.d.ts +177 -177
- package/lib/engine-components/particlesystem/ParticleSystem.js +1176 -1176
- package/lib/engine-components/particlesystem/ParticleSystemModules.d.ts +526 -526
- package/lib/engine-components/particlesystem/ParticleSystemModules.js +1930 -1930
- package/lib/engine-components/particlesystem/ParticleSystemSubEmitter.d.ts +25 -25
- package/lib/engine-components/particlesystem/ParticleSystemSubEmitter.js +87 -87
- package/lib/engine-components/particlesystem/api.d.ts +2 -2
- package/lib/engine-components/particlesystem/api.js +2 -2
- package/lib/engine-components/postprocessing/Effects/Antialiasing.d.ts +17 -17
- package/lib/engine-components/postprocessing/Effects/Antialiasing.js +59 -59
- package/lib/engine-components/postprocessing/Effects/BloomEffect.d.ts +46 -46
- package/lib/engine-components/postprocessing/Effects/BloomEffect.js +113 -113
- package/lib/engine-components/postprocessing/Effects/ChromaticAberration.d.ts +11 -11
- package/lib/engine-components/postprocessing/Effects/ChromaticAberration.js +39 -39
- package/lib/engine-components/postprocessing/Effects/ColorAdjustments.d.ts +23 -23
- package/lib/engine-components/postprocessing/Effects/ColorAdjustments.js +111 -111
- package/lib/engine-components/postprocessing/Effects/DepthOfField.d.ts +25 -25
- package/lib/engine-components/postprocessing/Effects/DepthOfField.js +104 -104
- package/lib/engine-components/postprocessing/Effects/EffectWrapper.d.ts +12 -12
- package/lib/engine-components/postprocessing/Effects/EffectWrapper.js +18 -18
- package/lib/engine-components/postprocessing/Effects/Pixelation.d.ts +11 -11
- package/lib/engine-components/postprocessing/Effects/Pixelation.js +32 -32
- package/lib/engine-components/postprocessing/Effects/ScreenspaceAmbientOcclusion.d.ts +18 -18
- package/lib/engine-components/postprocessing/Effects/ScreenspaceAmbientOcclusion.js +91 -91
- package/lib/engine-components/postprocessing/Effects/ScreenspaceAmbientOcclusionN8.d.ts +70 -70
- package/lib/engine-components/postprocessing/Effects/ScreenspaceAmbientOcclusionN8.js +176 -176
- package/lib/engine-components/postprocessing/Effects/Sharpening.d.ts +18 -18
- package/lib/engine-components/postprocessing/Effects/Sharpening.js +127 -127
- package/lib/engine-components/postprocessing/Effects/TiltShiftEffect.d.ts +17 -17
- package/lib/engine-components/postprocessing/Effects/TiltShiftEffect.js +70 -70
- package/lib/engine-components/postprocessing/Effects/Tonemapping.d.ts +19 -19
- package/lib/engine-components/postprocessing/Effects/Tonemapping.js +94 -94
- package/lib/engine-components/postprocessing/Effects/Tonemapping.utils.d.ts +13 -13
- package/lib/engine-components/postprocessing/Effects/Tonemapping.utils.js +51 -51
- package/lib/engine-components/postprocessing/Effects/Vignette.d.ts +15 -15
- package/lib/engine-components/postprocessing/Effects/Vignette.js +60 -60
- package/lib/engine-components/postprocessing/PostProcessingEffect.d.ts +90 -90
- package/lib/engine-components/postprocessing/PostProcessingEffect.js +168 -168
- package/lib/engine-components/postprocessing/PostProcessingHandler.d.ts +42 -42
- package/lib/engine-components/postprocessing/PostProcessingHandler.js +494 -494
- package/lib/engine-components/postprocessing/Volume.d.ts +90 -90
- package/lib/engine-components/postprocessing/Volume.js +385 -385
- package/lib/engine-components/postprocessing/VolumeParameter.d.ts +26 -26
- package/lib/engine-components/postprocessing/VolumeParameter.js +136 -136
- package/lib/engine-components/postprocessing/VolumeProfile.d.ts +15 -15
- package/lib/engine-components/postprocessing/VolumeProfile.js +60 -60
- package/lib/engine-components/postprocessing/index.d.ts +6 -6
- package/lib/engine-components/postprocessing/index.js +6 -6
- package/lib/engine-components/postprocessing/utils.d.ts +55 -55
- package/lib/engine-components/postprocessing/utils.js +119 -119
- package/lib/engine-components/timeline/PlayableDirector.d.ts +163 -163
- package/lib/engine-components/timeline/PlayableDirector.js +686 -686
- package/lib/engine-components/timeline/SignalAsset.d.ts +24 -24
- package/lib/engine-components/timeline/SignalAsset.js +130 -130
- package/lib/engine-components/timeline/TimelineModels.d.ts +89 -89
- package/lib/engine-components/timeline/TimelineModels.js +22 -22
- package/lib/engine-components/timeline/TimelineTracks.d.ts +110 -110
- package/lib/engine-components/timeline/TimelineTracks.js +879 -879
- package/lib/engine-components/timeline/index.d.ts +4 -4
- package/lib/engine-components/timeline/index.js +3 -3
- package/lib/engine-components/ui/BaseUIComponent.d.ts +48 -48
- package/lib/engine-components/ui/BaseUIComponent.js +170 -170
- package/lib/engine-components/ui/Button.d.ts +64 -64
- package/lib/engine-components/ui/Button.js +315 -315
- package/lib/engine-components/ui/Canvas.d.ts +74 -74
- package/lib/engine-components/ui/Canvas.js +407 -407
- package/lib/engine-components/ui/CanvasGroup.d.ts +19 -19
- package/lib/engine-components/ui/CanvasGroup.js +58 -58
- package/lib/engine-components/ui/EventSystem.d.ts +125 -125
- package/lib/engine-components/ui/EventSystem.js +765 -765
- package/lib/engine-components/ui/Graphic.d.ts +55 -55
- package/lib/engine-components/ui/Graphic.js +255 -255
- package/lib/engine-components/ui/Image.d.ts +35 -35
- package/lib/engine-components/ui/Image.js +116 -116
- package/lib/engine-components/ui/InputField.d.ts +42 -42
- package/lib/engine-components/ui/InputField.js +268 -268
- package/lib/engine-components/ui/Interfaces.d.ts +38 -38
- package/lib/engine-components/ui/Interfaces.js +12 -12
- package/lib/engine-components/ui/Layout.d.ts +84 -84
- package/lib/engine-components/ui/Layout.js +330 -330
- package/lib/engine-components/ui/Outline.d.ts +7 -7
- package/lib/engine-components/ui/Outline.js +20 -20
- package/lib/engine-components/ui/PointerEvents.d.ts +115 -115
- package/lib/engine-components/ui/PointerEvents.js +145 -145
- package/lib/engine-components/ui/RaycastUtils.d.ts +11 -11
- package/lib/engine-components/ui/RaycastUtils.js +67 -67
- package/lib/engine-components/ui/Raycaster.d.ts +30 -30
- package/lib/engine-components/ui/Raycaster.js +95 -95
- package/lib/engine-components/ui/RectTransform.d.ts +61 -61
- package/lib/engine-components/ui/RectTransform.js +356 -356
- package/lib/engine-components/ui/SpatialHtml.d.ts +8 -8
- package/lib/engine-components/ui/SpatialHtml.js +79 -79
- package/lib/engine-components/ui/Symbols.d.ts +1 -1
- package/lib/engine-components/ui/Symbols.js +1 -1
- package/lib/engine-components/ui/Text.d.ts +78 -78
- package/lib/engine-components/ui/Text.js +539 -539
- package/lib/engine-components/ui/Utils.d.ts +24 -24
- package/lib/engine-components/ui/Utils.js +90 -90
- package/lib/engine-components/ui/index.d.ts +1 -1
- package/lib/engine-components/ui/index.js +1 -1
- package/lib/engine-components/utils/EnvironmentScene.d.ts +5 -5
- package/lib/engine-components/utils/EnvironmentScene.js +205 -205
- package/lib/engine-components/utils/LookAt.d.ts +31 -31
- package/lib/engine-components/utils/LookAt.js +82 -82
- package/lib/engine-components/utils/OpenURL.d.ts +42 -42
- package/lib/engine-components/utils/OpenURL.js +119 -119
- package/lib/engine-components/webxr/Avatar.d.ts +25 -25
- package/lib/engine-components/webxr/Avatar.js +255 -255
- package/lib/engine-components/webxr/TeleportTarget.d.ts +7 -7
- package/lib/engine-components/webxr/TeleportTarget.js +7 -7
- package/lib/engine-components/webxr/WebARCameraBackground.d.ts +30 -30
- package/lib/engine-components/webxr/WebARCameraBackground.js +155 -155
- package/lib/engine-components/webxr/WebARSessionRoot.d.ts +98 -98
- package/lib/engine-components/webxr/WebARSessionRoot.js +770 -770
- package/lib/engine-components/webxr/WebXR.d.ts +232 -232
- package/lib/engine-components/webxr/WebXR.js +561 -561
- package/lib/engine-components/webxr/WebXRAvatar.d.ts +27 -27
- package/lib/engine-components/webxr/WebXRAvatar.js +44 -44
- package/lib/engine-components/webxr/WebXRImageTracking.d.ts +86 -86
- package/lib/engine-components/webxr/WebXRImageTracking.js +471 -471
- package/lib/engine-components/webxr/WebXRPlaneTracking.d.ts +92 -92
- package/lib/engine-components/webxr/WebXRPlaneTracking.js +500 -500
- package/lib/engine-components/webxr/WebXRRig.d.ts +32 -32
- package/lib/engine-components/webxr/WebXRRig.js +72 -72
- package/lib/engine-components/webxr/XRFlag.d.ts +38 -38
- package/lib/engine-components/webxr/XRFlag.js +139 -139
- package/lib/engine-components/webxr/controllers/XRControllerFollow.d.ts +47 -47
- package/lib/engine-components/webxr/controllers/XRControllerFollow.js +120 -120
- package/lib/engine-components/webxr/controllers/XRControllerModel.d.ts +43 -43
- package/lib/engine-components/webxr/controllers/XRControllerModel.js +352 -352
- package/lib/engine-components/webxr/controllers/XRControllerMovement.d.ts +78 -78
- package/lib/engine-components/webxr/controllers/XRControllerMovement.js +506 -506
- package/lib/engine-components/webxr/index.d.ts +3 -3
- package/lib/engine-components/webxr/index.js +3 -3
- package/lib/engine-components/webxr/types.d.ts +3 -3
- package/lib/engine-components/webxr/types.js +1 -1
- package/lib/engine-components-experimental/Presentation.d.ts +6 -6
- package/lib/engine-components-experimental/Presentation.js +9 -9
- package/lib/engine-components-experimental/api.d.ts +4 -4
- package/lib/engine-components-experimental/api.js +4 -4
- package/lib/engine-components-experimental/networking/PlayerSync.d.ts +156 -156
- package/lib/engine-components-experimental/networking/PlayerSync.js +377 -377
- package/lib/engine-schemes/api.d.ts +12 -12
- package/lib/engine-schemes/api.js +12 -12
- package/lib/engine-schemes/schemes.d.ts +7 -7
- package/lib/engine-schemes/schemes.js +19 -19
- package/lib/engine-schemes/synced-camera-model.d.ts +25 -25
- package/lib/engine-schemes/synced-camera-model.js +67 -67
- package/lib/engine-schemes/synced-transform-model.d.ts +31 -31
- package/lib/engine-schemes/synced-transform-model.js +66 -66
- package/lib/engine-schemes/transform.d.ts +12 -12
- package/lib/engine-schemes/transform.js +39 -39
- package/lib/engine-schemes/vec2.d.ts +10 -10
- package/lib/engine-schemes/vec2.js +25 -25
- package/lib/engine-schemes/vec3.d.ts +11 -11
- package/lib/engine-schemes/vec3.js +29 -29
- package/lib/engine-schemes/vec4.d.ts +12 -12
- package/lib/engine-schemes/vec4.js +33 -33
- package/lib/engine-schemes/vr-user-state-buffer.d.ts +37 -37
- package/lib/engine-schemes/vr-user-state-buffer.js +110 -110
- package/lib/include/three/EXT_mesh_gpu_instancing_exporter.d.ts +6 -6
- package/lib/include/three/EXT_mesh_gpu_instancing_exporter.js +45 -45
- package/lib/needle-engine.d.ts +7 -7
- package/lib/needle-engine.js +64 -64
- package/package.json +2 -2
- package/plugins/common/buildinfo.js +64 -64
- package/plugins/common/cloud.js +1 -1
- package/plugins/common/config.cjs +31 -31
- package/plugins/common/config.js +35 -35
- package/plugins/common/files.js +31 -31
- package/plugins/common/generator.js +10 -10
- package/plugins/common/license.js +452 -452
- package/plugins/common/logger.js +327 -320
- package/plugins/common/npm.js +15 -15
- package/plugins/common/timers.js +7 -7
- package/plugins/common/version.js +37 -37
- package/plugins/gltf-packer.mjs +1 -1
- package/plugins/next/alias.cjs +39 -39
- package/plugins/next/license.cjs +24 -24
- package/plugins/next/meshbvhworker.cjs +18 -18
- package/plugins/next/next.js +141 -141
- package/plugins/types/index.d.ts +2 -2
- package/plugins/types/license.d.ts +24 -24
- package/plugins/types/needleConfig.d.ts +27 -27
- package/plugins/types/next.d.ts +2 -2
- package/plugins/types/userconfig.d.ts +124 -124
- package/plugins/types/vite.d.ts +13 -13
- package/plugins/types/webmanifest.d.ts +32 -32
- package/plugins/vite/alias.js +189 -189
- package/plugins/vite/asap.js +251 -251
- package/plugins/vite/build-pipeline.js +371 -371
- package/plugins/vite/build.js +19 -19
- package/plugins/vite/buildinfo.js +41 -41
- package/plugins/vite/config.js +106 -106
- package/plugins/vite/copyfiles.js +138 -138
- package/plugins/vite/defines.js +70 -70
- package/plugins/vite/dependencies.js +232 -232
- package/plugins/vite/dependency-watcher.js +237 -237
- package/plugins/vite/drop-client.js +76 -76
- package/plugins/vite/drop.js +87 -87
- package/plugins/vite/editor-connection.js +124 -124
- package/plugins/vite/facebook-instant-games.js +102 -102
- package/plugins/vite/gzip.js +5 -5
- package/plugins/vite/imports-logger.js +143 -143
- package/plugins/vite/index.js +147 -147
- package/plugins/vite/license.js +56 -56
- package/plugins/vite/local-files.js +440 -440
- package/plugins/vite/logger.client.js +272 -262
- package/plugins/vite/logger.js +100 -100
- package/plugins/vite/materialx.js +31 -31
- package/plugins/vite/meta.js +163 -163
- package/plugins/vite/npm.js +7 -7
- package/plugins/vite/peer.js +29 -29
- package/plugins/vite/poster-client.js +73 -73
- package/plugins/vite/poster.js +79 -79
- package/plugins/vite/pwa.js +604 -604
- package/plugins/vite/reload-client.js +15 -15
- package/plugins/vite/reload.js +351 -351
- package/plugins/vite/server.js +66 -66
- package/plugins/vite/transform-codegen.js +55 -55
- package/plugins/vite/transform.js +32 -32
- package/plugins/vite/vite-4.4-hack.js +31 -31
- package/src/asap/needle-asap.ts +111 -111
- package/src/asap/sessiongranted.ts +75 -75
- package/src/asap/utils.ts +4 -4
- package/src/engine/analytics/index.ts +10 -10
- package/src/engine/analytics/lcp.ts +35 -35
- package/src/engine/api.ts +82 -82
- package/src/engine/assets/index.ts +59 -59
- package/src/engine/assets/static.js +5 -5
- package/src/engine/codegen/register_types.ts +300 -300
- package/src/engine/debug/debug.ts +51 -51
- package/src/engine/debug/debug_console.ts +333 -333
- package/src/engine/debug/debug_overlay.ts +332 -332
- package/src/engine/debug/debug_spatial_console.ts +429 -429
- package/src/engine/debug/index.ts +1 -1
- package/src/engine/engine_addressables.ts +671 -680
- package/src/engine/engine_animation.ts +145 -145
- package/src/engine/engine_application.ts +113 -113
- package/src/engine/engine_assetdatabase.ts +389 -389
- package/src/engine/engine_audio.ts +24 -24
- package/src/engine/engine_camera.ts +39 -39
- package/src/engine/engine_components.ts +366 -366
- package/src/engine/engine_components_internal.ts +40 -40
- package/src/engine/engine_constants.ts +52 -52
- package/src/engine/engine_context.ts +1824 -1824
- package/src/engine/engine_context_registry.ts +129 -129
- package/src/engine/engine_coroutine.ts +54 -54
- package/src/engine/engine_create_objects.ts +411 -411
- package/src/engine/engine_default_parameters.ts +3 -3
- package/src/engine/engine_editor-sync.ts +28 -28
- package/src/engine/engine_fileloader.js +9 -9
- package/src/engine/engine_gameobject.ts +712 -712
- package/src/engine/engine_generic_utils.js +13 -13
- package/src/engine/engine_gizmos.ts +577 -577
- package/src/engine/engine_gltf.ts +29 -29
- package/src/engine/engine_gltf_builtin_components.ts +403 -403
- package/src/engine/engine_hot_reload.ts +210 -210
- package/src/engine/engine_input.ts +1500 -1500
- package/src/engine/engine_input_utils.ts +23 -23
- package/src/engine/engine_instancing.ts +45 -45
- package/src/engine/engine_license.ts +386 -386
- package/src/engine/engine_lifecycle_api.ts +113 -113
- package/src/engine/engine_lifecycle_functions_internal.ts +193 -193
- package/src/engine/engine_lightdata.ts +125 -117
- package/src/engine/engine_loaders.callbacks.ts +136 -136
- package/src/engine/engine_loaders.gltf.ts +82 -82
- package/src/engine/engine_loaders.ts +378 -378
- package/src/engine/engine_lods.ts +186 -168
- package/src/engine/engine_mainloop_utils.ts +472 -472
- package/src/engine/engine_math.ts +282 -282
- package/src/engine/engine_modules.ts +83 -83
- package/src/engine/engine_networking.ts +862 -862
- package/src/engine/engine_networking_auto.ts +352 -352
- package/src/engine/engine_networking_blob.ts +275 -275
- package/src/engine/engine_networking_files.ts +217 -217
- package/src/engine/engine_networking_files_default_components.ts +58 -58
- package/src/engine/engine_networking_instantiate.ts +419 -419
- package/src/engine/engine_networking_peer.ts +159 -159
- package/src/engine/engine_networking_streams.ts +713 -713
- package/src/engine/engine_networking_types.ts +24 -24
- package/src/engine/engine_networking_utils.ts +23 -23
- package/src/engine/engine_networking_websocket.ts +2 -2
- package/src/engine/engine_patcher.ts +199 -199
- package/src/engine/engine_physics.ts +783 -783
- package/src/engine/engine_physics.types.ts +46 -46
- package/src/engine/engine_physics_rapier.ts +1577 -1577
- package/src/engine/engine_playerview.ts +80 -80
- package/src/engine/engine_scenelighting.ts +294 -294
- package/src/engine/engine_serialization.ts +2 -2
- package/src/engine/engine_serialization_builtin_serializer.ts +473 -473
- package/src/engine/engine_serialization_core.ts +720 -720
- package/src/engine/engine_serialization_decorator.ts +80 -80
- package/src/engine/engine_setup.ts +1 -1
- package/src/engine/engine_shaders.ts +267 -267
- package/src/engine/engine_shims.ts +32 -32
- package/src/engine/engine_test_utils.ts +109 -109
- package/src/engine/engine_texture.ts +82 -82
- package/src/engine/engine_three_utils.ts +928 -928
- package/src/engine/engine_time.ts +94 -94
- package/src/engine/engine_time_utils.ts +237 -237
- package/src/engine/engine_tonemapping.ts +208 -208
- package/src/engine/engine_types.ts +730 -730
- package/src/engine/engine_typestore.ts +63 -63
- package/src/engine/engine_util_decorator.ts +136 -136
- package/src/engine/engine_utils.ts +1115 -1115
- package/src/engine/engine_utils_format.ts +273 -273
- package/src/engine/engine_utils_screenshot.ts +708 -708
- package/src/engine/engine_utils_screenshot.xr.ts +103 -103
- package/src/engine/export/gltf/Writers.ts +34 -34
- package/src/engine/export/gltf/index.ts +158 -158
- package/src/engine/export/index.ts +2 -2
- package/src/engine/export/state.ts +19 -19
- package/src/engine/export/utils.ts +9 -9
- package/src/engine/extensions/EXT_texture_exr.ts +50 -50
- package/src/engine/extensions/NEEDLE_animator_controller_model.ts +195 -195
- package/src/engine/extensions/NEEDLE_components.ts +268 -268
- package/src/engine/extensions/NEEDLE_gameobject_data.ts +81 -81
- package/src/engine/extensions/NEEDLE_lighting_settings.ts +185 -185
- package/src/engine/extensions/NEEDLE_lightmaps.ts +119 -119
- package/src/engine/extensions/NEEDLE_persistent_assets.ts +76 -76
- package/src/engine/extensions/NEEDLE_render_objects.ts +209 -209
- package/src/engine/extensions/NEEDLE_techniques_webgl.ts +640 -640
- package/src/engine/extensions/extension_resolver.ts +4 -4
- package/src/engine/extensions/extension_utils.ts +166 -166
- package/src/engine/extensions/extensions.ts +140 -140
- package/src/engine/extensions/index.ts +5 -5
- package/src/engine/extensions/usage_tracker.ts +100 -100
- package/src/engine/js-extensions/Camera.ts +37 -37
- package/src/engine/js-extensions/ExtensionUtils.ts +85 -85
- package/src/engine/js-extensions/Layers.ts +23 -23
- package/src/engine/js-extensions/Object3D.ts +296 -296
- package/src/engine/js-extensions/RGBAColor.ts +126 -126
- package/src/engine/js-extensions/Vector.ts +18 -18
- package/src/engine/js-extensions/index.ts +4 -4
- package/src/engine/physics/workers/mesh-bvh/GenerateMeshBVHWorker.js +125 -125
- package/src/engine/shaders/shaderData.ts +67 -67
- package/src/engine/tests/test_utils.ts +63 -63
- package/src/engine/webcomponents/WebXRButtons.ts +260 -260
- package/src/engine/webcomponents/api.ts +6 -6
- package/src/engine/webcomponents/buttons.ts +292 -292
- package/src/engine/webcomponents/fonts.ts +41 -41
- package/src/engine/webcomponents/icons.ts +57 -57
- package/src/engine/webcomponents/index.ts +1 -1
- package/src/engine/webcomponents/logo-element.ts +78 -78
- package/src/engine/webcomponents/needle menu/needle-menu-spatial.ts +573 -573
- package/src/engine/webcomponents/needle menu/needle-menu.ts +1118 -1118
- package/src/engine/webcomponents/needle-button.ts +181 -181
- package/src/engine/webcomponents/needle-engine.ar-overlay.ts +186 -186
- package/src/engine/webcomponents/needle-engine.attributes.ts +82 -82
- package/src/engine/webcomponents/needle-engine.extras.ts +16 -16
- package/src/engine/webcomponents/needle-engine.loading.ts +373 -373
- package/src/engine/webcomponents/needle-engine.ts +860 -860
- package/src/engine/xr/NeedleXRController.ts +1125 -1125
- package/src/engine/xr/NeedleXRSession.ts +1624 -1624
- package/src/engine/xr/NeedleXRSync.ts +220 -220
- package/src/engine/xr/SceneTransition.ts +78 -78
- package/src/engine/xr/TempXRContext.ts +216 -216
- package/src/engine/xr/XRRig.ts +9 -9
- package/src/engine/xr/api.ts +5 -5
- package/src/engine/xr/events.ts +102 -102
- package/src/engine/xr/internal.ts +34 -34
- package/src/engine/xr/usdz.ts +30 -30
- package/src/engine/xr/utils.ts +39 -39
- package/src/engine-components/AlignmentConstraint.ts +36 -36
- package/src/engine-components/Animation.ts +557 -557
- package/src/engine-components/AnimationCurve.ts +150 -150
- package/src/engine-components/AnimationUtils.ts +28 -28
- package/src/engine-components/AnimationUtilsAutoplay.ts +43 -43
- package/src/engine-components/Animator.ts +397 -397
- package/src/engine-components/AnimatorController.ts +1293 -1293
- package/src/engine-components/AudioListener.ts +92 -92
- package/src/engine-components/AudioSource.ts +644 -644
- package/src/engine-components/AvatarLoader.ts +263 -263
- package/src/engine-components/AxesHelper.ts +59 -59
- package/src/engine-components/BasicIKConstraint.ts +54 -54
- package/src/engine-components/BoxCollider.ts +1 -1
- package/src/engine-components/BoxHelperComponent.ts +114 -114
- package/src/engine-components/Camera.ts +719 -719
- package/src/engine-components/CameraUtils.ts +138 -138
- package/src/engine-components/CharacterController.ts +253 -253
- package/src/engine-components/Collider.ts +374 -374
- package/src/engine-components/Component.ts +1297 -1297
- package/src/engine-components/ContactShadows.ts +506 -506
- package/src/engine-components/DeleteBox.ts +62 -62
- package/src/engine-components/DeviceFlag.ts +46 -46
- package/src/engine-components/DragControls.ts +1623 -1623
- package/src/engine-components/DropListener.ts +713 -713
- package/src/engine-components/Duplicatable.ts +198 -198
- package/src/engine-components/EventList.ts +266 -266
- package/src/engine-components/EventTrigger.ts +74 -74
- package/src/engine-components/EventType.ts +22 -22
- package/src/engine-components/Fog.ts +60 -60
- package/src/engine-components/Gizmos.ts +56 -56
- package/src/engine-components/GridHelper.ts +48 -48
- package/src/engine-components/GroundProjection.ts +356 -356
- package/src/engine-components/Interactable.ts +14 -14
- package/src/engine-components/Joints.ts +52 -52
- package/src/engine-components/LODGroup.ts +153 -153
- package/src/engine-components/Light.ts +558 -558
- package/src/engine-components/LookAtConstraint.ts +25 -25
- package/src/engine-components/NeedleMenu.ts +84 -84
- package/src/engine-components/NestedGltf.ts +86 -86
- package/src/engine-components/Networking.ts +114 -114
- package/src/engine-components/OffsetConstraint.ts +60 -60
- package/src/engine-components/OrbitControls.ts +1074 -1074
- package/src/engine-components/PlayerColor.ts +103 -103
- package/src/engine-components/ReflectionProbe.ts +220 -220
- package/src/engine-components/Renderer.ts +903 -903
- package/src/engine-components/RendererInstancing.ts +855 -855
- package/src/engine-components/RendererLightmap.ts +198 -198
- package/src/engine-components/RigidBody.ts +526 -526
- package/src/engine-components/SceneSwitcher.ts +1030 -1030
- package/src/engine-components/ScreenCapture.ts +592 -592
- package/src/engine-components/ShadowCatcher.ts +172 -172
- package/src/engine-components/Skybox.ts +475 -475
- package/src/engine-components/SmoothFollow.ts +76 -76
- package/src/engine-components/SpatialTrigger.ts +229 -229
- package/src/engine-components/SpectatorCamera.ts +787 -787
- package/src/engine-components/SphereCollider.ts +1 -1
- package/src/engine-components/SpriteRenderer.ts +468 -468
- package/src/engine-components/SyncedCamera.ts +220 -220
- package/src/engine-components/SyncedRoom.ts +380 -380
- package/src/engine-components/SyncedTransform.ts +383 -383
- package/src/engine-components/TestRunner.ts +118 -118
- package/src/engine-components/TransformGizmo.ts +219 -219
- package/src/engine-components/VideoPlayer.ts +1025 -1025
- package/src/engine-components/Voip.ts +363 -363
- package/src/engine-components/api.ts +60 -60
- package/src/engine-components/avatar/AvatarBlink_Simple.ts +69 -69
- package/src/engine-components/avatar/AvatarEyeLook_Rotation.ts +63 -63
- package/src/engine-components/avatar/Avatar_Brain_LookAt.ts +139 -139
- package/src/engine-components/avatar/Avatar_MouthShapes.ts +83 -83
- package/src/engine-components/avatar/Avatar_MustacheShake.ts +31 -31
- package/src/engine-components/codegen/components.ts +217 -217
- package/src/engine-components/debug/LogStats.ts +21 -21
- package/src/engine-components/export/gltf/GltfExport.ts +265 -265
- package/src/engine-components/export/usdz/Extension.ts +24 -24
- package/src/engine-components/export/usdz/ThreeUSDZExporter.ts +2426 -2426
- package/src/engine-components/export/usdz/USDZExporter.ts +705 -705
- package/src/engine-components/export/usdz/extensions/Animation.ts +1204 -1204
- package/src/engine-components/export/usdz/extensions/DocumentExtension.ts +9 -9
- package/src/engine-components/export/usdz/extensions/NodeMaterialConverter.ts +532 -532
- package/src/engine-components/export/usdz/extensions/USDZText.ts +240 -240
- package/src/engine-components/export/usdz/extensions/USDZUI.ts +189 -189
- package/src/engine-components/export/usdz/extensions/behavior/Actions.ts +99 -99
- package/src/engine-components/export/usdz/extensions/behavior/AudioExtension.ts +102 -102
- package/src/engine-components/export/usdz/extensions/behavior/Behaviour.ts +320 -320
- package/src/engine-components/export/usdz/extensions/behavior/BehaviourComponents.ts +1225 -1225
- package/src/engine-components/export/usdz/extensions/behavior/BehavioursBuilder.ts +646 -646
- package/src/engine-components/export/usdz/extensions/behavior/PhysicsExtension.ts +132 -132
- package/src/engine-components/export/usdz/index.ts +2 -2
- package/src/engine-components/export/usdz/utils/animationutils.ts +191 -191
- package/src/engine-components/export/usdz/utils/quicklook.ts +50 -50
- package/src/engine-components/particlesystem/ParticleSystem.ts +1287 -1287
- package/src/engine-components/particlesystem/ParticleSystemModules.ts +1765 -1765
- package/src/engine-components/particlesystem/ParticleSystemSubEmitter.ts +111 -111
- package/src/engine-components/particlesystem/api.ts +1 -1
- package/src/engine-components/postprocessing/Effects/Antialiasing.ts +64 -64
- package/src/engine-components/postprocessing/Effects/BloomEffect.ts +116 -116
- package/src/engine-components/postprocessing/Effects/ChromaticAberration.ts +37 -37
- package/src/engine-components/postprocessing/Effects/ColorAdjustments.ts +106 -106
- package/src/engine-components/postprocessing/Effects/DepthOfField.ts +103 -103
- package/src/engine-components/postprocessing/Effects/EffectWrapper.ts +25 -25
- package/src/engine-components/postprocessing/Effects/Pixelation.ts +32 -32
- package/src/engine-components/postprocessing/Effects/ScreenspaceAmbientOcclusion.ts +90 -90
- package/src/engine-components/postprocessing/Effects/ScreenspaceAmbientOcclusionN8.ts +192 -192
- package/src/engine-components/postprocessing/Effects/Sharpening.ts +143 -143
- package/src/engine-components/postprocessing/Effects/TiltShiftEffect.ts +61 -61
- package/src/engine-components/postprocessing/Effects/Tonemapping.ts +103 -103
- package/src/engine-components/postprocessing/Effects/Tonemapping.utils.ts +60 -60
- package/src/engine-components/postprocessing/Effects/Vignette.ts +59 -59
- package/src/engine-components/postprocessing/PostProcessingEffect.ts +192 -192
- package/src/engine-components/postprocessing/PostProcessingHandler.ts +572 -572
- package/src/engine-components/postprocessing/Volume.ts +426 -426
- package/src/engine-components/postprocessing/VolumeParameter.ts +158 -158
- package/src/engine-components/postprocessing/VolumeProfile.ts +61 -61
- package/src/engine-components/postprocessing/index.ts +5 -5
- package/src/engine-components/postprocessing/utils.ts +154 -154
- package/src/engine-components/timeline/PlayableDirector.ts +722 -722
- package/src/engine-components/timeline/SignalAsset.ts +144 -144
- package/src/engine-components/timeline/TimelineModels.ts +92 -92
- package/src/engine-components/timeline/TimelineTracks.ts +967 -967
- package/src/engine-components/timeline/index.ts +3 -3
- package/src/engine-components/ui/BaseUIComponent.ts +203 -203
- package/src/engine-components/ui/Button.ts +307 -307
- package/src/engine-components/ui/Canvas.ts +419 -419
- package/src/engine-components/ui/CanvasGroup.ts +54 -54
- package/src/engine-components/ui/EventSystem.ts +854 -854
- package/src/engine-components/ui/Graphic.ts +275 -275
- package/src/engine-components/ui/Image.ts +112 -112
- package/src/engine-components/ui/InputField.ts +321 -321
- package/src/engine-components/ui/Interfaces.ts +57 -57
- package/src/engine-components/ui/Layout.ts +334 -334
- package/src/engine-components/ui/Outline.ts +13 -13
- package/src/engine-components/ui/PointerEvents.ts +206 -206
- package/src/engine-components/ui/RaycastUtils.ts +69 -69
- package/src/engine-components/ui/Raycaster.ts +102 -102
- package/src/engine-components/ui/RectTransform.ts +375 -375
- package/src/engine-components/ui/SpatialHtml.ts +79 -79
- package/src/engine-components/ui/Symbols.ts +1 -1
- package/src/engine-components/ui/Text.ts +578 -578
- package/src/engine-components/ui/Utils.ts +113 -113
- package/src/engine-components/utils/EnvironmentScene.ts +245 -245
- package/src/engine-components/utils/LookAt.ts +88 -88
- package/src/engine-components/utils/OpenURL.ts +114 -114
- package/src/engine-components/webxr/Avatar.ts +265 -265
- package/src/engine-components/webxr/TeleportTarget.ts +9 -9
- package/src/engine-components/webxr/WebARCameraBackground.ts +175 -175
- package/src/engine-components/webxr/WebARSessionRoot.ts +880 -880
- package/src/engine-components/webxr/WebXR.ts +585 -585
- package/src/engine-components/webxr/WebXRAvatar.ts +66 -66
- package/src/engine-components/webxr/WebXRImageTracking.ts +519 -519
- package/src/engine-components/webxr/WebXRPlaneTracking.ts +570 -570
- package/src/engine-components/webxr/WebXRRig.ts +77 -77
- package/src/engine-components/webxr/XRFlag.ts +147 -147
- package/src/engine-components/webxr/controllers/XRControllerFollow.ts +118 -118
- package/src/engine-components/webxr/controllers/XRControllerModel.ts +373 -373
- package/src/engine-components/webxr/controllers/XRControllerMovement.ts +550 -550
- package/src/engine-components/webxr/index.ts +2 -2
- package/src/engine-components/webxr/types.ts +3 -3
- package/src/engine-components-experimental/Presentation.ts +12 -12
- package/src/engine-components-experimental/api.ts +4 -4
- package/src/engine-components-experimental/networking/PlayerSync.ts +401 -401
- package/src/engine-schemes/COMPILE_SCHEMES.bat +3 -3
- package/src/engine-schemes/COMPILE_TS.bat +11 -11
- package/src/engine-schemes/README.md +1 -1
- package/src/engine-schemes/api.ts +12 -12
- package/src/engine-schemes/dist/api.js +17 -0
- package/src/engine-schemes/dist/api.js.meta +7 -0
- package/src/engine-schemes/dist/schemes.js +25 -0
- package/src/engine-schemes/dist/schemes.js.meta +7 -0
- package/src/engine-schemes/dist/synced-camera-model.js +74 -0
- package/src/engine-schemes/dist/synced-camera-model.js.meta +7 -0
- package/src/engine-schemes/dist/synced-transform-model.js +73 -0
- package/src/engine-schemes/dist/synced-transform-model.js.meta +7 -0
- package/src/engine-schemes/dist/transform.js +46 -0
- package/src/engine-schemes/dist/transform.js.meta +7 -0
- package/src/engine-schemes/dist/vec2.js +32 -0
- package/src/engine-schemes/dist/vec2.js.meta +7 -0
- package/src/engine-schemes/dist/vec3.js +36 -0
- package/src/engine-schemes/dist/vec3.js.meta +7 -0
- package/src/engine-schemes/dist/vec4.js +40 -0
- package/src/engine-schemes/dist/vec4.js.meta +7 -0
- package/src/engine-schemes/dist/vr-user-state-buffer.js +110 -0
- package/src/engine-schemes/dist/vr-user-state-buffer.js.meta +7 -0
- package/src/engine-schemes/schemes.ts +28 -28
- package/src/engine-schemes/synced-camera-model.ts +92 -92
- package/src/engine-schemes/synced-transform-model.ts +90 -90
- package/src/engine-schemes/syncedCamera.fbs +10 -10
- package/src/engine-schemes/transform.ts +50 -50
- package/src/engine-schemes/transforms.fbs +25 -25
- package/src/engine-schemes/vec.fbs +19 -19
- package/src/engine-schemes/vec2.ts +33 -33
- package/src/engine-schemes/vec3.ts +38 -38
- package/src/engine-schemes/vec4.ts +43 -43
- package/src/engine-schemes/vr-user-state-buffer.ts +145 -145
- package/src/engine-schemes/vrUserStateBuffer.fbs +17 -17
- package/src/include/draco/draco_decoder.js +34 -34
- package/src/include/ktx2/basis_transcoder.js +21 -21
- package/src/include/needle/arial-msdf.json +1471 -1471
- package/src/include/three/DragControls.js +231 -231
- package/src/include/three/EXT_mesh_gpu_instancing_exporter.js +66 -66
- package/src/needle-engine.ts +70 -70
- package/dist/generateMeshBVH.worker-BaNp_Xtp.js +0 -25
- package/dist/gltf-progressive-Bl4okF1b.min.js +0 -8
- package/dist/gltf-progressive-DSpdn0QT.js +0 -1054
- package/dist/gltf-progressive-P8b8a0qY.umd.cjs +0 -8
|
@@ -1,1153 +1,1153 @@
|
|
|
1
|
-
import { AnimationClip, AnimationMixer, AxesHelper, Euler, LoopOnce, Quaternion, Vector3 } from "three";
|
|
2
|
-
import { isDevEnvironment } from "../engine/debug/index.js";
|
|
3
|
-
import { Mathf } from "../engine/engine_math.js";
|
|
4
|
-
import { InstantiateIdProvider } from "../engine/engine_networking_instantiate.js";
|
|
5
|
-
import { assign, TypeSerializer } from "../engine/engine_serialization_core.js";
|
|
6
|
-
import { isAnimationAction } from "../engine/engine_three_utils.js";
|
|
7
|
-
import { TypeStore } from "../engine/engine_typestore.js";
|
|
8
|
-
import { deepClone, getParam } from "../engine/engine_utils.js";
|
|
9
|
-
import { AnimatorConditionMode, AnimatorControllerParameterType, AnimatorStateInfo, createMotion } from "../engine/extensions/NEEDLE_animator_controller_model.js";
|
|
10
|
-
const debug = getParam("debuganimatorcontroller");
|
|
11
|
-
const debugRootMotion = getParam("debugrootmotion");
|
|
12
|
-
/**
|
|
13
|
-
* Generates a hash code for a string
|
|
14
|
-
* @param str - The string to hash
|
|
15
|
-
* @returns A numeric hash value
|
|
16
|
-
*/
|
|
17
|
-
function stringToHash(str) {
|
|
18
|
-
let hash = 0;
|
|
19
|
-
for (let i = 0; i < str.length; i++) {
|
|
20
|
-
const char = str.charCodeAt(i);
|
|
21
|
-
hash = ((hash << 5) - hash) + char;
|
|
22
|
-
hash = hash & hash;
|
|
23
|
-
}
|
|
24
|
-
return hash;
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* Controls the playback of animations using a state machine architecture.
|
|
28
|
-
*
|
|
29
|
-
* The AnimatorController manages animation states, transitions between states,
|
|
30
|
-
* and parameters that affect those transitions. It is used by the {@link Animator}
|
|
31
|
-
* component to control animation behavior on 3D models.
|
|
32
|
-
*
|
|
33
|
-
* Use the static method {@link AnimatorController.createFromClips} to create
|
|
34
|
-
* an animator controller from a set of animation clips.
|
|
35
|
-
*/
|
|
36
|
-
export class AnimatorController {
|
|
37
|
-
/**
|
|
38
|
-
* Creates an AnimatorController from a set of animation clips.
|
|
39
|
-
* Each clip becomes a state in the controller's state machine.
|
|
40
|
-
*
|
|
41
|
-
* @param clips - The animation clips to use for creating states
|
|
42
|
-
* @param options - Configuration options for the controller including looping behavior and transitions
|
|
43
|
-
* @returns A new AnimatorController instance
|
|
44
|
-
*/
|
|
45
|
-
static createFromClips(clips, options = { looping: false, autoTransition: true, transitionDuration: 0 }) {
|
|
46
|
-
const states = [];
|
|
47
|
-
for (let i = 0; i < clips.length; i++) {
|
|
48
|
-
const clip = clips[i];
|
|
49
|
-
const transitions = [];
|
|
50
|
-
if (options.autoTransition !== false) {
|
|
51
|
-
const dur = options.transitionDuration ?? 0;
|
|
52
|
-
const normalizedDuration = dur / clip.duration;
|
|
53
|
-
// automatically transition to self by default
|
|
54
|
-
let nextState = i;
|
|
55
|
-
if (options.autoTransition === undefined || options.autoTransition === true) {
|
|
56
|
-
nextState = (i + 1) % clips.length;
|
|
57
|
-
}
|
|
58
|
-
transitions.push({
|
|
59
|
-
exitTime: 1 - normalizedDuration,
|
|
60
|
-
offset: 0,
|
|
61
|
-
duration: dur,
|
|
62
|
-
hasExitTime: true,
|
|
63
|
-
destinationState: nextState,
|
|
64
|
-
conditions: [],
|
|
65
|
-
});
|
|
66
|
-
}
|
|
67
|
-
const state = {
|
|
68
|
-
name: clip.name,
|
|
69
|
-
hash: i,
|
|
70
|
-
motion: {
|
|
71
|
-
name: clip.name,
|
|
72
|
-
clip: clip,
|
|
73
|
-
isLooping: options?.looping ?? false,
|
|
74
|
-
},
|
|
75
|
-
transitions: transitions,
|
|
76
|
-
behaviours: []
|
|
77
|
-
};
|
|
78
|
-
states.push(state);
|
|
79
|
-
}
|
|
80
|
-
const model = {
|
|
81
|
-
name: "AnimatorController",
|
|
82
|
-
guid: new InstantiateIdProvider(Date.now()).generateUUID(),
|
|
83
|
-
parameters: [],
|
|
84
|
-
layers: [{
|
|
85
|
-
name: "Base Layer",
|
|
86
|
-
stateMachine: {
|
|
87
|
-
defaultState: 0,
|
|
88
|
-
states: states
|
|
89
|
-
}
|
|
90
|
-
}]
|
|
91
|
-
};
|
|
92
|
-
const controller = new AnimatorController(model);
|
|
93
|
-
return controller;
|
|
94
|
-
}
|
|
95
|
-
/**
|
|
96
|
-
* Plays an animation state by name or hash.
|
|
97
|
-
*
|
|
98
|
-
* @param name - The name or hash identifier of the state to play
|
|
99
|
-
* @param layerIndex - The layer index (defaults to 0)
|
|
100
|
-
* @param normalizedTime - The normalized time to start the animation from (0-1)
|
|
101
|
-
* @param durationInSec - Transition duration in seconds
|
|
102
|
-
*/
|
|
103
|
-
play(name, layerIndex = -1, normalizedTime = Number.NEGATIVE_INFINITY, durationInSec = 0) {
|
|
104
|
-
if (layerIndex < 0)
|
|
105
|
-
layerIndex = 0;
|
|
106
|
-
else if (layerIndex >= this.model.layers.length) {
|
|
107
|
-
console.warn("invalid layer");
|
|
108
|
-
return;
|
|
109
|
-
}
|
|
110
|
-
const layer = this.model.layers[layerIndex];
|
|
111
|
-
const sm = layer.stateMachine;
|
|
112
|
-
for (const state of sm.states) {
|
|
113
|
-
if (state.name === name || state.hash === name) {
|
|
114
|
-
if (debug)
|
|
115
|
-
console.log("transition to ", state);
|
|
116
|
-
this.transitionTo(state, durationInSec, normalizedTime);
|
|
117
|
-
return;
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
console.warn("Could not find " + name + " to play");
|
|
121
|
-
}
|
|
122
|
-
/**
|
|
123
|
-
* Resets the controller to its initial state.
|
|
124
|
-
*/
|
|
125
|
-
reset() {
|
|
126
|
-
this.setStartTransition();
|
|
127
|
-
}
|
|
128
|
-
/**
|
|
129
|
-
* Sets a boolean parameter value by name or hash.
|
|
130
|
-
*
|
|
131
|
-
* @param name - The name or hash identifier of the parameter
|
|
132
|
-
* @param value - The boolean value to set
|
|
133
|
-
*/
|
|
134
|
-
setBool(name, value) {
|
|
135
|
-
const key = typeof name === "string" ? "name" : "hash";
|
|
136
|
-
return this.model?.parameters?.filter(p => p[key] === name).forEach(p => p.value = value);
|
|
137
|
-
}
|
|
138
|
-
/**
|
|
139
|
-
* Gets a boolean parameter value by name or hash.
|
|
140
|
-
*
|
|
141
|
-
* @param name - The name or hash identifier of the parameter
|
|
142
|
-
* @returns The boolean value of the parameter, or false if not found
|
|
143
|
-
*/
|
|
144
|
-
getBool(name) {
|
|
145
|
-
const key = typeof name === "string" ? "name" : "hash";
|
|
146
|
-
return this.model?.parameters?.find(p => p[key] === name)?.value ?? false;
|
|
147
|
-
}
|
|
148
|
-
/**
|
|
149
|
-
* Sets a float parameter value by name or hash.
|
|
150
|
-
*
|
|
151
|
-
* @param name - The name or hash identifier of the parameter
|
|
152
|
-
* @param val - The float value to set
|
|
153
|
-
* @returns True if the parameter was found and set, false otherwise
|
|
154
|
-
*/
|
|
155
|
-
setFloat(name, val) {
|
|
156
|
-
const key = typeof name === "string" ? "name" : "hash";
|
|
157
|
-
const filtered = this.model?.parameters?.filter(p => p[key] === name);
|
|
158
|
-
filtered.forEach(p => p.value = val);
|
|
159
|
-
return filtered?.length > 0;
|
|
160
|
-
}
|
|
161
|
-
/**
|
|
162
|
-
* Gets a float parameter value by name or hash.
|
|
163
|
-
*
|
|
164
|
-
* @param name - The name or hash identifier of the parameter
|
|
165
|
-
* @returns The float value of the parameter, or 0 if not found
|
|
166
|
-
*/
|
|
167
|
-
getFloat(name) {
|
|
168
|
-
const key = typeof name === "string" ? "name" : "hash";
|
|
169
|
-
return this.model?.parameters?.find(p => p[key] === name)?.value ?? 0;
|
|
170
|
-
}
|
|
171
|
-
/**
|
|
172
|
-
* Sets an integer parameter value by name or hash.
|
|
173
|
-
*
|
|
174
|
-
* @param name - The name or hash identifier of the parameter
|
|
175
|
-
* @param val - The integer value to set
|
|
176
|
-
*/
|
|
177
|
-
setInteger(name, val) {
|
|
178
|
-
const key = typeof name === "string" ? "name" : "hash";
|
|
179
|
-
return this.model?.parameters?.filter(p => p[key] === name).forEach(p => p.value = val);
|
|
180
|
-
}
|
|
181
|
-
/**
|
|
182
|
-
* Gets an integer parameter value by name or hash.
|
|
183
|
-
*
|
|
184
|
-
* @param name - The name or hash identifier of the parameter
|
|
185
|
-
* @returns The integer value of the parameter, or 0 if not found
|
|
186
|
-
*/
|
|
187
|
-
getInteger(name) {
|
|
188
|
-
const key = typeof name === "string" ? "name" : "hash";
|
|
189
|
-
return this.model?.parameters?.find(p => p[key] === name)?.value ?? 0;
|
|
190
|
-
}
|
|
191
|
-
/**
|
|
192
|
-
* Sets a trigger parameter to active (true).
|
|
193
|
-
* Trigger parameters are automatically reset after they are consumed by a transition.
|
|
194
|
-
*
|
|
195
|
-
* @param name - The name or hash identifier of the trigger parameter
|
|
196
|
-
*/
|
|
197
|
-
setTrigger(name) {
|
|
198
|
-
if (debug)
|
|
199
|
-
console.log("SET TRIGGER", name);
|
|
200
|
-
const key = typeof name === "string" ? "name" : "hash";
|
|
201
|
-
return this.model?.parameters?.filter(p => p[key] === name).forEach(p => p.value = true);
|
|
202
|
-
}
|
|
203
|
-
/**
|
|
204
|
-
* Resets a trigger parameter to inactive (false).
|
|
205
|
-
*
|
|
206
|
-
* @param name - The name or hash identifier of the trigger parameter
|
|
207
|
-
*/
|
|
208
|
-
resetTrigger(name) {
|
|
209
|
-
const key = typeof name === "string" ? "name" : "hash";
|
|
210
|
-
return this.model?.parameters?.filter(p => p[key] === name).forEach(p => p.value = false);
|
|
211
|
-
}
|
|
212
|
-
/**
|
|
213
|
-
* Gets the current state of a trigger parameter.
|
|
214
|
-
*
|
|
215
|
-
* @param name - The name or hash identifier of the trigger parameter
|
|
216
|
-
* @returns The boolean state of the trigger, or false if not found
|
|
217
|
-
*/
|
|
218
|
-
getTrigger(name) {
|
|
219
|
-
const key = typeof name === "string" ? "name" : "hash";
|
|
220
|
-
return this.model?.parameters?.find(p => p[key] === name)?.value ?? false;
|
|
221
|
-
}
|
|
222
|
-
/**
|
|
223
|
-
* Checks if the controller is currently in a transition between states.
|
|
224
|
-
*
|
|
225
|
-
* @returns True if a transition is in progress, false otherwise
|
|
226
|
-
*/
|
|
227
|
-
isInTransition() {
|
|
228
|
-
return this._activeStates.length > 1;
|
|
229
|
-
}
|
|
230
|
-
/** Set the speed of the animator controller. Larger values will make the animation play faster. */
|
|
231
|
-
setSpeed(speed) {
|
|
232
|
-
this._speed = speed;
|
|
233
|
-
}
|
|
234
|
-
_speed = 1;
|
|
235
|
-
/**
|
|
236
|
-
* Finds an animation state by name or hash.
|
|
237
|
-
* @deprecated Use findState instead
|
|
238
|
-
*
|
|
239
|
-
* @param name - The name or hash identifier of the state to find
|
|
240
|
-
* @returns The found state or null if not found
|
|
241
|
-
*/
|
|
242
|
-
FindState(name) { return this.findState(name); }
|
|
243
|
-
/**
|
|
244
|
-
* Finds an animation state by name or hash.
|
|
245
|
-
*
|
|
246
|
-
* @param name - The name or hash identifier of the state to find
|
|
247
|
-
* @returns The found state or null if not found
|
|
248
|
-
*/
|
|
249
|
-
findState(name) {
|
|
250
|
-
if (!name)
|
|
251
|
-
return null;
|
|
252
|
-
if (Array.isArray(this.model.layers)) {
|
|
253
|
-
for (const layer of this.model.layers) {
|
|
254
|
-
for (const state of layer.stateMachine.states) {
|
|
255
|
-
if (state.name === name || state.hash == name)
|
|
256
|
-
return state;
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
return null;
|
|
261
|
-
}
|
|
262
|
-
/**
|
|
263
|
-
* Gets information about the current playing animation state.
|
|
264
|
-
*
|
|
265
|
-
* @returns An AnimatorStateInfo object with data about the current state, or null if no state is active
|
|
266
|
-
*/
|
|
267
|
-
getCurrentStateInfo() {
|
|
268
|
-
if (!this._activeState)
|
|
269
|
-
return null;
|
|
270
|
-
const action = this._activeState.motion.action;
|
|
271
|
-
if (!action)
|
|
272
|
-
return null;
|
|
273
|
-
const dur = this._activeState.motion.clip.duration;
|
|
274
|
-
const normalizedTime = dur <= 0 ? 0 : Math.abs(action.time / dur);
|
|
275
|
-
return new AnimatorStateInfo(this._activeState, normalizedTime, dur, this._speed);
|
|
276
|
-
}
|
|
277
|
-
/**
|
|
278
|
-
* Gets the animation action currently playing.
|
|
279
|
-
*
|
|
280
|
-
* @returns The current animation action, or null if no action is playing
|
|
281
|
-
*/
|
|
282
|
-
get currentAction() {
|
|
283
|
-
if (!this._activeState)
|
|
284
|
-
return null;
|
|
285
|
-
const action = this._activeState.motion.action;
|
|
286
|
-
if (!action)
|
|
287
|
-
return null;
|
|
288
|
-
return action;
|
|
289
|
-
}
|
|
290
|
-
/**
|
|
291
|
-
* The normalized time (0-1) to start playing the first state at.
|
|
292
|
-
* This affects the initial state when the animator is first enabled.
|
|
293
|
-
*/
|
|
294
|
-
normalizedStartOffset = 0;
|
|
295
|
-
/**
|
|
296
|
-
* The Animator component this controller is bound to.
|
|
297
|
-
*/
|
|
298
|
-
animator;
|
|
299
|
-
/**
|
|
300
|
-
* The data model describing the animation states and transitions.
|
|
301
|
-
*/
|
|
302
|
-
model;
|
|
303
|
-
/**
|
|
304
|
-
* Gets the engine context from the bound animator.
|
|
305
|
-
*/
|
|
306
|
-
get context() { return this.animator?.context; }
|
|
307
|
-
/**
|
|
308
|
-
* Gets the animation mixer used by this controller.
|
|
309
|
-
*/
|
|
310
|
-
get mixer() {
|
|
311
|
-
return this._mixer;
|
|
312
|
-
}
|
|
313
|
-
/**
|
|
314
|
-
* Cleans up resources used by this controller.
|
|
315
|
-
* Stops all animations and unregisters the mixer from the animation system.
|
|
316
|
-
*/
|
|
317
|
-
dispose() {
|
|
318
|
-
this._mixer.stopAllAction();
|
|
319
|
-
if (this.animator) {
|
|
320
|
-
this._mixer.uncacheRoot(this.animator.gameObject);
|
|
321
|
-
for (const action of this._activeStates) {
|
|
322
|
-
if (action.motion.clip)
|
|
323
|
-
this.mixer.uncacheAction(action.motion.clip, this.animator.gameObject);
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
this.context?.animations.unregisterAnimationMixer(this._mixer);
|
|
327
|
-
}
|
|
328
|
-
// applyRootMotion(obj: Object3D) {
|
|
329
|
-
// // this.internalApplyRootMotion(obj);
|
|
330
|
-
// }
|
|
331
|
-
/**
|
|
332
|
-
* Binds this controller to an animator component.
|
|
333
|
-
* Creates a new animation mixer and sets up animation actions.
|
|
334
|
-
*
|
|
335
|
-
* @param animator - The animator to bind this controller to
|
|
336
|
-
*/
|
|
337
|
-
bind(animator) {
|
|
338
|
-
if (!animator)
|
|
339
|
-
console.error("AnimatorController.bind: animator is null");
|
|
340
|
-
else if (this.animator !== animator) {
|
|
341
|
-
if (this._mixer) {
|
|
342
|
-
this._mixer.stopAllAction();
|
|
343
|
-
this.context?.animations.unregisterAnimationMixer(this._mixer);
|
|
344
|
-
}
|
|
345
|
-
this.animator = animator;
|
|
346
|
-
this._mixer = new AnimationMixer(this.animator.gameObject);
|
|
347
|
-
this.context?.animations.registerAnimationMixer(this._mixer);
|
|
348
|
-
this.createActions(this.animator);
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
/**
|
|
352
|
-
* Creates a deep copy of this controller.
|
|
353
|
-
* Clones the model data but does not copy runtime state.
|
|
354
|
-
*
|
|
355
|
-
* @returns A new AnimatorController instance with the same configuration
|
|
356
|
-
*/
|
|
357
|
-
clone() {
|
|
358
|
-
if (typeof this.model === "string") {
|
|
359
|
-
console.warn("AnimatorController has not been resolved, can not create model from string", this.model);
|
|
360
|
-
return null;
|
|
361
|
-
}
|
|
362
|
-
if (debug)
|
|
363
|
-
console.warn("AnimatorController clone()", this.model);
|
|
364
|
-
// clone runtime controller but dont clone clip or action
|
|
365
|
-
const clonedModel = deepClone(this.model, (_owner, _key, _value) => {
|
|
366
|
-
if (_value === null || _value === undefined)
|
|
367
|
-
return true;
|
|
368
|
-
// dont clone three Objects
|
|
369
|
-
if (_value.type === "Object3D" || _value.isObject3D === true)
|
|
370
|
-
return false;
|
|
371
|
-
// dont clone AnimationAction
|
|
372
|
-
if (isAnimationAction(_value)) { //.constructor.name === "AnimationAction") {
|
|
373
|
-
// console.log(_value);
|
|
374
|
-
return false;
|
|
375
|
-
}
|
|
376
|
-
// dont clone AnimationClip
|
|
377
|
-
if (_value["tracks"] !== undefined)
|
|
378
|
-
return false;
|
|
379
|
-
// when assigned __concreteInstance during serialization
|
|
380
|
-
if (_value instanceof AnimatorController)
|
|
381
|
-
return false;
|
|
382
|
-
return true;
|
|
383
|
-
});
|
|
384
|
-
console.assert(clonedModel !== this.model);
|
|
385
|
-
const controller = new AnimatorController(clonedModel);
|
|
386
|
-
return controller;
|
|
387
|
-
}
|
|
388
|
-
/**
|
|
389
|
-
* Updates the controller's state machine and animations.
|
|
390
|
-
* Called each frame by the animator component.
|
|
391
|
-
*
|
|
392
|
-
* @param weight - The weight to apply to the animations (for blending)
|
|
393
|
-
*/
|
|
394
|
-
update(weight) {
|
|
395
|
-
if (!this.animator)
|
|
396
|
-
return;
|
|
397
|
-
this.evaluateTransitions();
|
|
398
|
-
this.updateActiveStates(weight);
|
|
399
|
-
// We want to update the animation mixer even if there is no active state (e.g. in cases where an empty animator controller is assigned and the timeline runs)
|
|
400
|
-
// if (!this._activeState) return;
|
|
401
|
-
const dt = this.animator.context.time.deltaTime;
|
|
402
|
-
if (this.animator.applyRootMotion) {
|
|
403
|
-
this.rootMotionHandler?.onBeforeUpdate(weight);
|
|
404
|
-
}
|
|
405
|
-
this._mixer.update(dt);
|
|
406
|
-
if (this.animator.applyRootMotion) {
|
|
407
|
-
this.rootMotionHandler?.onAfterUpdate(weight);
|
|
408
|
-
}
|
|
409
|
-
}
|
|
410
|
-
_mixer;
|
|
411
|
-
_activeState;
|
|
412
|
-
/**
|
|
413
|
-
* Gets the currently active animation state.
|
|
414
|
-
*
|
|
415
|
-
* @returns The active state or undefined if no state is active
|
|
416
|
-
*/
|
|
417
|
-
get activeState() { return this._activeState; }
|
|
418
|
-
constructor(model) {
|
|
419
|
-
this.model = model;
|
|
420
|
-
if (debug)
|
|
421
|
-
console.log(this);
|
|
422
|
-
}
|
|
423
|
-
_activeStates = [];
|
|
424
|
-
updateActiveStates(weight) {
|
|
425
|
-
for (let i = 0; i < this._activeStates.length; i++) {
|
|
426
|
-
const state = this._activeStates[i];
|
|
427
|
-
const motion = state.motion;
|
|
428
|
-
if (!motion.action) {
|
|
429
|
-
this._activeStates.splice(i, 1);
|
|
430
|
-
i--;
|
|
431
|
-
}
|
|
432
|
-
else {
|
|
433
|
-
const action = motion.action;
|
|
434
|
-
action.weight = weight;
|
|
435
|
-
// console.log(action.getClip().name, action.getEffectiveWeight(), action.isScheduled());
|
|
436
|
-
if ((action.getEffectiveWeight() <= 0 && !action.isRunning())) {
|
|
437
|
-
if (debug)
|
|
438
|
-
console.debug("REMOVE", state.name, action.getEffectiveWeight(), action.isRunning(), action.isScheduled());
|
|
439
|
-
this._activeStates.splice(i, 1);
|
|
440
|
-
i--;
|
|
441
|
-
}
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
}
|
|
445
|
-
setStartTransition() {
|
|
446
|
-
if (this.model.layers.length > 1 && (debug || isDevEnvironment())) {
|
|
447
|
-
console.warn("Multiple layers are not supported yet " + this.animator?.name);
|
|
448
|
-
}
|
|
449
|
-
for (const layer of this.model.layers) {
|
|
450
|
-
const sm = layer.stateMachine;
|
|
451
|
-
if (sm.defaultState === undefined) {
|
|
452
|
-
if (debug)
|
|
453
|
-
console.warn("AnimatorController default state is undefined, will assign state 0 as default", layer);
|
|
454
|
-
sm.defaultState = 0;
|
|
455
|
-
}
|
|
456
|
-
const start = sm.states[sm.defaultState];
|
|
457
|
-
this.transitionTo(start, 0, this.normalizedStartOffset);
|
|
458
|
-
break;
|
|
459
|
-
}
|
|
460
|
-
}
|
|
461
|
-
evaluateTransitions() {
|
|
462
|
-
let didEnterStateThisFrame = false;
|
|
463
|
-
if (!this._activeState) {
|
|
464
|
-
this.setStartTransition();
|
|
465
|
-
if (!this._activeState)
|
|
466
|
-
return;
|
|
467
|
-
didEnterStateThisFrame = true;
|
|
468
|
-
}
|
|
469
|
-
const state = this._activeState;
|
|
470
|
-
const action = state.motion.action;
|
|
471
|
-
let index = 0;
|
|
472
|
-
for (const transition of state.transitions) {
|
|
473
|
-
++index;
|
|
474
|
-
// transition without exit time and without condition that transition to itself are ignored
|
|
475
|
-
if (!transition.hasExitTime && transition.conditions.length <= 0) {
|
|
476
|
-
// if (this._activeState && this.getState(transition.destinationState, currentLayer)?.hash === this._activeState.hash)
|
|
477
|
-
continue;
|
|
478
|
-
}
|
|
479
|
-
let allConditionsAreMet = true;
|
|
480
|
-
for (const cond of transition.conditions) {
|
|
481
|
-
if (!this.evaluateCondition(cond)) {
|
|
482
|
-
allConditionsAreMet = false;
|
|
483
|
-
break;
|
|
484
|
-
}
|
|
485
|
-
}
|
|
486
|
-
if (!allConditionsAreMet)
|
|
487
|
-
continue;
|
|
488
|
-
if (debug && allConditionsAreMet) {
|
|
489
|
-
// console.log("All conditions are met", transition);
|
|
490
|
-
}
|
|
491
|
-
if (action) {
|
|
492
|
-
const dur = state.motion.clip.duration;
|
|
493
|
-
const normalizedTime = dur <= 0 ? 1 : Math.abs(action.time / dur);
|
|
494
|
-
let exitTime = transition.exitTime;
|
|
495
|
-
// When the animation is playing backwards we need to check exit time inverted
|
|
496
|
-
if (action.timeScale < 0) {
|
|
497
|
-
exitTime = 1 - exitTime;
|
|
498
|
-
}
|
|
499
|
-
let makeTransition = false;
|
|
500
|
-
if (transition.hasExitTime) {
|
|
501
|
-
if (action.timeScale > 0)
|
|
502
|
-
makeTransition = normalizedTime >= transition.exitTime;
|
|
503
|
-
// When the animation is playing backwards we need to check exit time inverted
|
|
504
|
-
else if (action.timeScale < 0)
|
|
505
|
-
makeTransition = 1 - normalizedTime >= transition.exitTime;
|
|
506
|
-
}
|
|
507
|
-
else {
|
|
508
|
-
makeTransition = true;
|
|
509
|
-
}
|
|
510
|
-
if (makeTransition) {
|
|
511
|
-
// disable triggers for this transition
|
|
512
|
-
for (const cond of transition.conditions) {
|
|
513
|
-
const param = this.model.parameters.find(p => p.name === cond.parameter);
|
|
514
|
-
if (param?.type === AnimatorControllerParameterType.Trigger && param.value) {
|
|
515
|
-
param.value = false;
|
|
516
|
-
}
|
|
517
|
-
}
|
|
518
|
-
// if (transition.hasExitTime && transition.exitTime >= .9999)
|
|
519
|
-
action.clampWhenFinished = true;
|
|
520
|
-
// else action.clampWhenFinished = false;
|
|
521
|
-
if (debug) {
|
|
522
|
-
const targetState = this.getState(transition.destinationState, 0);
|
|
523
|
-
console.log(`Transition to ${transition.destinationState} / ${targetState?.name}`, transition, "\nTimescale: " + action.timeScale, "\nNormalized time: " + normalizedTime.toFixed(3), "\nExit Time: " + exitTime, transition.hasExitTime);
|
|
524
|
-
// console.log(action.time, transition.exitTime);
|
|
525
|
-
}
|
|
526
|
-
this.transitionTo(transition.destinationState, transition.duration, transition.offset);
|
|
527
|
-
// use the first transition that matches all conditions and make the transition as soon as in range
|
|
528
|
-
return;
|
|
529
|
-
}
|
|
530
|
-
}
|
|
531
|
-
else {
|
|
532
|
-
this.transitionTo(transition.destinationState, transition.duration, transition.offset);
|
|
533
|
-
return;
|
|
534
|
-
}
|
|
535
|
-
// if none of the transitions can be made continue searching for another transition meeting the conditions
|
|
536
|
-
}
|
|
537
|
-
// action.time += this.context.time.deltaTime
|
|
538
|
-
// console.log(action?.time, action?.getEffectiveWeight())
|
|
539
|
-
// update timescale
|
|
540
|
-
if (action) {
|
|
541
|
-
this.setTimescale(action, state);
|
|
542
|
-
}
|
|
543
|
-
let didTriggerLooping = false;
|
|
544
|
-
if (state.motion.isLooping && action) {
|
|
545
|
-
// we dont use the three loop state here because it prevents the transition check above
|
|
546
|
-
// it is easier if we re-trigger loop here.
|
|
547
|
-
// We also can easily add the cycle offset settings from unity later
|
|
548
|
-
if (action.time >= action.getClip().duration) {
|
|
549
|
-
didTriggerLooping = true;
|
|
550
|
-
action.reset();
|
|
551
|
-
action.time = 0;
|
|
552
|
-
action.play();
|
|
553
|
-
}
|
|
554
|
-
else if (action.time <= 0 && action.timeScale < 0) {
|
|
555
|
-
didTriggerLooping = true;
|
|
556
|
-
action.reset();
|
|
557
|
-
action.time = action.getClip().duration;
|
|
558
|
-
action.play();
|
|
559
|
-
}
|
|
560
|
-
}
|
|
561
|
-
// call update state behaviours:
|
|
562
|
-
if (!didTriggerLooping && state && !didEnterStateThisFrame && action && this.animator) {
|
|
563
|
-
if (state.behaviours) {
|
|
564
|
-
const duration = action?.getClip().duration;
|
|
565
|
-
const normalizedTime = action.time / duration;
|
|
566
|
-
const info = new AnimatorStateInfo(this._activeState, normalizedTime, duration, this._speed);
|
|
567
|
-
for (const beh of state.behaviours) {
|
|
568
|
-
if (beh.instance) {
|
|
569
|
-
beh.instance.onStateUpdate?.call(beh.instance, this.animator, info, 0);
|
|
570
|
-
}
|
|
571
|
-
}
|
|
572
|
-
}
|
|
573
|
-
}
|
|
574
|
-
}
|
|
575
|
-
setTimescale(action, state) {
|
|
576
|
-
let speedFactor = state.speed ?? 1;
|
|
577
|
-
if (state.speedParameter)
|
|
578
|
-
speedFactor *= this.getFloat(state.speedParameter);
|
|
579
|
-
if (speedFactor !== undefined) {
|
|
580
|
-
action.timeScale = speedFactor * this._speed;
|
|
581
|
-
}
|
|
582
|
-
}
|
|
583
|
-
getState(state, layerIndex) {
|
|
584
|
-
if (typeof state === "number") {
|
|
585
|
-
if (state == -1) {
|
|
586
|
-
state = this.model.layers[layerIndex].stateMachine.defaultState; // exit state -> entry state
|
|
587
|
-
if (state === undefined) {
|
|
588
|
-
if (debug)
|
|
589
|
-
console.warn("AnimatorController default state is undefined: ", this.model, "Layer: " + layerIndex);
|
|
590
|
-
state = 0;
|
|
591
|
-
}
|
|
592
|
-
}
|
|
593
|
-
state = this.model.layers[layerIndex].stateMachine.states[state];
|
|
594
|
-
}
|
|
595
|
-
return state;
|
|
596
|
-
}
|
|
597
|
-
/**
|
|
598
|
-
* These actions have been active previously but not faded out because we entered a state that has no real animation - no duration. In which case we hold the previously active actions until they are faded out.
|
|
599
|
-
*/
|
|
600
|
-
_heldActions = [];
|
|
601
|
-
releaseHeldActions(duration) {
|
|
602
|
-
for (const prev of this._heldActions) {
|
|
603
|
-
prev.fadeOut(duration);
|
|
604
|
-
}
|
|
605
|
-
this._heldActions.length = 0;
|
|
606
|
-
}
|
|
607
|
-
transitionTo(state, durationInSec, offsetNormalized) {
|
|
608
|
-
if (!this.animator)
|
|
609
|
-
return;
|
|
610
|
-
const layerIndex = 0;
|
|
611
|
-
state = this.getState(state, layerIndex);
|
|
612
|
-
if (!state?.motion || !state.motion.clip || !(state.motion.clip instanceof AnimationClip)) {
|
|
613
|
-
// if(debug) console.warn("State has no clip or motion", state);
|
|
614
|
-
return;
|
|
615
|
-
}
|
|
616
|
-
const isSelf = this._activeState === state;
|
|
617
|
-
if (isSelf) {
|
|
618
|
-
const motion = state.motion;
|
|
619
|
-
if (!motion.action_loopback && motion.clip) {
|
|
620
|
-
// uncache action immediately resets the applied animation which breaks the root motion
|
|
621
|
-
// this happens if we have a transition to self and the clip is not cached yet
|
|
622
|
-
const previousMatrix = this.rootMotionHandler ? this.animator.gameObject.matrix.clone() : null;
|
|
623
|
-
this._mixer.uncacheAction(motion.clip, this.animator.gameObject);
|
|
624
|
-
if (previousMatrix)
|
|
625
|
-
previousMatrix.decompose(this.animator.gameObject.position, this.animator.gameObject.quaternion, this.animator.gameObject.scale);
|
|
626
|
-
motion.action_loopback = this.createAction(motion.clip);
|
|
627
|
-
}
|
|
628
|
-
}
|
|
629
|
-
// call exit state behaviours
|
|
630
|
-
if (this._activeState?.behaviours && this._activeState.motion.action) {
|
|
631
|
-
const duration = this._activeState?.motion.clip.duration;
|
|
632
|
-
const normalizedTime = this._activeState.motion.action.time / duration;
|
|
633
|
-
const info = new AnimatorStateInfo(this._activeState, normalizedTime, duration, this._speed);
|
|
634
|
-
for (const beh of this._activeState.behaviours) {
|
|
635
|
-
beh.instance?.onStateExit?.call(beh.instance, this.animator, info, layerIndex);
|
|
636
|
-
}
|
|
637
|
-
}
|
|
638
|
-
const prevAction = this._activeState?.motion.action;
|
|
639
|
-
if (isSelf) {
|
|
640
|
-
state.motion.action = state.motion.action_loopback;
|
|
641
|
-
state.motion.action_loopback = prevAction;
|
|
642
|
-
}
|
|
643
|
-
const prev = this._activeState;
|
|
644
|
-
this._activeState = state;
|
|
645
|
-
const action = state.motion?.action;
|
|
646
|
-
const clip = state.motion.clip;
|
|
647
|
-
if (clip?.duration <= 0 && clip.tracks.length <= 0) {
|
|
648
|
-
// if the new state doesn't have a valid clip / no tracks we don't fadeout the previous action and instead hold the previous action.
|
|
649
|
-
if (prevAction) {
|
|
650
|
-
this._heldActions.push(prevAction);
|
|
651
|
-
}
|
|
652
|
-
}
|
|
653
|
-
else if (prevAction) {
|
|
654
|
-
prevAction.fadeOut(durationInSec);
|
|
655
|
-
this.releaseHeldActions(durationInSec);
|
|
656
|
-
}
|
|
657
|
-
if (action) {
|
|
658
|
-
offsetNormalized = Math.max(0, Math.min(1, offsetNormalized));
|
|
659
|
-
if (state.cycleOffsetParameter) {
|
|
660
|
-
let val = this.getFloat(state.cycleOffsetParameter);
|
|
661
|
-
if (typeof val === "number") {
|
|
662
|
-
if (val < 0)
|
|
663
|
-
val += 1;
|
|
664
|
-
offsetNormalized += val;
|
|
665
|
-
offsetNormalized %= 1;
|
|
666
|
-
}
|
|
667
|
-
else if (debug)
|
|
668
|
-
console.warn("AnimatorController cycle offset parameter is not a number", state.cycleOffsetParameter);
|
|
669
|
-
}
|
|
670
|
-
else if (typeof state.cycleOffset === "number") {
|
|
671
|
-
offsetNormalized += state.cycleOffset;
|
|
672
|
-
offsetNormalized %= 1;
|
|
673
|
-
}
|
|
674
|
-
if (action.isRunning())
|
|
675
|
-
action.stop();
|
|
676
|
-
action.reset();
|
|
677
|
-
action.enabled = true;
|
|
678
|
-
this.setTimescale(action, state);
|
|
679
|
-
const duration = state.motion.clip.duration;
|
|
680
|
-
// if we are looping to the same state we don't want to offset the current start time
|
|
681
|
-
action.time = isSelf ? 0 : offsetNormalized * duration;
|
|
682
|
-
if (action.timeScale < 0)
|
|
683
|
-
action.time = duration - action.time;
|
|
684
|
-
action.clampWhenFinished = true;
|
|
685
|
-
action.setLoop(LoopOnce, 0);
|
|
686
|
-
if (durationInSec > 0)
|
|
687
|
-
action.fadeIn(durationInSec);
|
|
688
|
-
else
|
|
689
|
-
action.weight = 1;
|
|
690
|
-
action.play();
|
|
691
|
-
if (this.rootMotionHandler) {
|
|
692
|
-
this.rootMotionHandler.onStart(action);
|
|
693
|
-
}
|
|
694
|
-
if (!this._activeStates.includes(state))
|
|
695
|
-
this._activeStates.push(state);
|
|
696
|
-
// call enter state behaviours
|
|
697
|
-
if (this._activeState.behaviours) {
|
|
698
|
-
const info = new AnimatorStateInfo(state, offsetNormalized, duration, this._speed);
|
|
699
|
-
for (const beh of this._activeState.behaviours) {
|
|
700
|
-
beh.instance?.onStateEnter?.call(beh.instance, this.animator, info, layerIndex);
|
|
701
|
-
}
|
|
702
|
-
}
|
|
703
|
-
}
|
|
704
|
-
else if (debug) {
|
|
705
|
-
if (!state["__warned_no_motion"]) {
|
|
706
|
-
state["__warned_no_motion"] = true;
|
|
707
|
-
console.warn("No action", state.motion, this);
|
|
708
|
-
}
|
|
709
|
-
}
|
|
710
|
-
if (debug)
|
|
711
|
-
console.log("TRANSITION FROM " + prev?.name + " TO " + state.name, durationInSec, prevAction, action, action?.getEffectiveTimeScale(), action?.getEffectiveWeight(), action?.isRunning(), action?.isScheduled(), action?.paused);
|
|
712
|
-
}
|
|
713
|
-
createAction(clip) {
|
|
714
|
-
// uncache clip causes issues when multiple states use the same clip
|
|
715
|
-
// this._mixer.uncacheClip(clip);
|
|
716
|
-
// instead only uncache the action when one already exists to make sure
|
|
717
|
-
// we get unique actions per state
|
|
718
|
-
const existing = this._mixer.existingAction(clip);
|
|
719
|
-
if (existing)
|
|
720
|
-
this._mixer.uncacheAction(clip, this.animator?.gameObject);
|
|
721
|
-
if (this.animator?.applyRootMotion) {
|
|
722
|
-
if (!this.rootMotionHandler) {
|
|
723
|
-
this.rootMotionHandler = new RootMotionHandler(this);
|
|
724
|
-
}
|
|
725
|
-
// TODO: find root bone properly
|
|
726
|
-
const root = this.animator.gameObject;
|
|
727
|
-
return this.rootMotionHandler.createClip(this._mixer, root, clip);
|
|
728
|
-
}
|
|
729
|
-
else {
|
|
730
|
-
const action = this._mixer.clipAction(clip);
|
|
731
|
-
return action;
|
|
732
|
-
}
|
|
733
|
-
}
|
|
734
|
-
evaluateCondition(cond) {
|
|
735
|
-
const param = this.model.parameters.find(p => p.name === cond.parameter);
|
|
736
|
-
if (!param)
|
|
737
|
-
return false;
|
|
738
|
-
// console.log(param.name, param.value);
|
|
739
|
-
switch (cond.mode) {
|
|
740
|
-
case AnimatorConditionMode.If:
|
|
741
|
-
return param.value === true;
|
|
742
|
-
case AnimatorConditionMode.IfNot:
|
|
743
|
-
return param.value === false;
|
|
744
|
-
case AnimatorConditionMode.Greater:
|
|
745
|
-
return param.value > cond.threshold;
|
|
746
|
-
case AnimatorConditionMode.Less:
|
|
747
|
-
return param.value < cond.threshold;
|
|
748
|
-
case AnimatorConditionMode.Equals:
|
|
749
|
-
return param.value === cond.threshold;
|
|
750
|
-
case AnimatorConditionMode.NotEqual:
|
|
751
|
-
return param.value !== cond.threshold;
|
|
752
|
-
}
|
|
753
|
-
return false;
|
|
754
|
-
}
|
|
755
|
-
createActions(_animator) {
|
|
756
|
-
if (debug)
|
|
757
|
-
console.log("AnimatorController createActions", this.model);
|
|
758
|
-
for (const layer of this.model.layers) {
|
|
759
|
-
const sm = layer.stateMachine;
|
|
760
|
-
for (let index = 0; index < sm.states.length; index++) {
|
|
761
|
-
const state = sm.states[index];
|
|
762
|
-
// ensure we have a transitions array
|
|
763
|
-
if (!state.transitions) {
|
|
764
|
-
state.transitions = [];
|
|
765
|
-
}
|
|
766
|
-
for (const t of state.transitions) {
|
|
767
|
-
// can happen if conditions are empty in blender - the exporter seems to skip empty arrays
|
|
768
|
-
if (!t.conditions)
|
|
769
|
-
t.conditions = [];
|
|
770
|
-
}
|
|
771
|
-
// ensure we have a motion even if none was exported
|
|
772
|
-
if (!state.motion) {
|
|
773
|
-
if (debug)
|
|
774
|
-
console.warn("No motion", state);
|
|
775
|
-
state.motion = createMotion(state.name);
|
|
776
|
-
// console.warn("Missing motion", "AnimatorController: " + this.model.name, state);
|
|
777
|
-
// sm.states.splice(index, 1);
|
|
778
|
-
// index -= 1;
|
|
779
|
-
// continue;
|
|
780
|
-
}
|
|
781
|
-
// the clips array contains which animator has which animationclip
|
|
782
|
-
if (this.animator && state.motion.clips) {
|
|
783
|
-
// TODO: we have to compare by name because on instantiate we clone objects but not the node object
|
|
784
|
-
const mapping = state.motion.clips?.find(e => e.node.name === this.animator?.gameObject?.name);
|
|
785
|
-
if (!mapping) {
|
|
786
|
-
if (debug || isDevEnvironment()) {
|
|
787
|
-
console.warn("Could not find clip for animator \"" + this.animator?.gameObject?.name + "\"", state.motion.clips.map(c => c.node.name));
|
|
788
|
-
}
|
|
789
|
-
}
|
|
790
|
-
else
|
|
791
|
-
state.motion.clip = mapping.clip;
|
|
792
|
-
}
|
|
793
|
-
// ensure we have a clip to blend to
|
|
794
|
-
if (!state.motion.clip) {
|
|
795
|
-
if (debug)
|
|
796
|
-
console.warn("No clip assigned to state", state);
|
|
797
|
-
const clip = new AnimationClip(undefined, undefined, []);
|
|
798
|
-
state.motion.clip = clip;
|
|
799
|
-
}
|
|
800
|
-
if (state.motion?.clip) {
|
|
801
|
-
const clip = state.motion.clip;
|
|
802
|
-
if (clip instanceof AnimationClip) {
|
|
803
|
-
const action = this.createAction(clip);
|
|
804
|
-
state.motion.action = action;
|
|
805
|
-
}
|
|
806
|
-
else {
|
|
807
|
-
if (debug || isDevEnvironment())
|
|
808
|
-
console.warn("No valid animationclip assigned", state);
|
|
809
|
-
}
|
|
810
|
-
}
|
|
811
|
-
// create state machine behaviours
|
|
812
|
-
if (state.behaviours && Array.isArray(state.behaviours)) {
|
|
813
|
-
for (const behaviour of state.behaviours) {
|
|
814
|
-
if (!behaviour?.typeName)
|
|
815
|
-
continue;
|
|
816
|
-
const type = TypeStore.get(behaviour.typeName);
|
|
817
|
-
if (type) {
|
|
818
|
-
const instance = new type();
|
|
819
|
-
if (instance.isStateMachineBehaviour) {
|
|
820
|
-
instance._context = this.context ?? undefined;
|
|
821
|
-
assign(instance, behaviour.properties);
|
|
822
|
-
behaviour.instance = instance;
|
|
823
|
-
}
|
|
824
|
-
if (debug)
|
|
825
|
-
console.log("Created animator controller behaviour", state.name, behaviour.typeName, behaviour.properties, instance);
|
|
826
|
-
}
|
|
827
|
-
else {
|
|
828
|
-
if (debug || isDevEnvironment())
|
|
829
|
-
console.warn("Could not find AnimatorBehaviour type: " + behaviour.typeName);
|
|
830
|
-
}
|
|
831
|
-
}
|
|
832
|
-
}
|
|
833
|
-
}
|
|
834
|
-
}
|
|
835
|
-
}
|
|
836
|
-
/**
|
|
837
|
-
* Yields all animation actions managed by this controller.
|
|
838
|
-
* Iterates through all states in all layers and returns their actions.
|
|
839
|
-
*/
|
|
840
|
-
*enumerateActions() {
|
|
841
|
-
if (!this.model.layers)
|
|
842
|
-
return;
|
|
843
|
-
for (const layer of this.model.layers) {
|
|
844
|
-
const sm = layer.stateMachine;
|
|
845
|
-
for (let index = 0; index < sm.states.length; index++) {
|
|
846
|
-
const state = sm.states[index];
|
|
847
|
-
if (state?.motion) {
|
|
848
|
-
if (state.motion.action)
|
|
849
|
-
yield state.motion.action;
|
|
850
|
-
if (state.motion.action_loopback)
|
|
851
|
-
yield state.motion.action_loopback;
|
|
852
|
-
}
|
|
853
|
-
}
|
|
854
|
-
}
|
|
855
|
-
}
|
|
856
|
-
// https://docs.unity3d.com/Manual/RootMotion.html
|
|
857
|
-
rootMotionHandler;
|
|
858
|
-
}
|
|
859
|
-
/**
|
|
860
|
-
* Wraps a KeyframeTrack to allow custom evaluation of animation values.
|
|
861
|
-
* Used internally to modify animation behavior without changing the original data.
|
|
862
|
-
*/
|
|
863
|
-
class TrackEvaluationWrapper {
|
|
864
|
-
track;
|
|
865
|
-
createdInterpolant;
|
|
866
|
-
originalEvaluate;
|
|
867
|
-
customEvaluate;
|
|
868
|
-
constructor(track, evaluate) {
|
|
869
|
-
this.track = track;
|
|
870
|
-
const t = track;
|
|
871
|
-
const createOriginalInterpolator = t.createInterpolant.bind(track);
|
|
872
|
-
t.createInterpolant = () => {
|
|
873
|
-
t.createInterpolant = createOriginalInterpolator;
|
|
874
|
-
this.createdInterpolant = createOriginalInterpolator();
|
|
875
|
-
this.originalEvaluate = this.createdInterpolant.evaluate.bind(this.createdInterpolant);
|
|
876
|
-
this.customEvaluate = time => {
|
|
877
|
-
if (!this.originalEvaluate)
|
|
878
|
-
return;
|
|
879
|
-
const res = this.originalEvaluate(time);
|
|
880
|
-
return evaluate(time, res);
|
|
881
|
-
};
|
|
882
|
-
this.createdInterpolant.evaluate = this.customEvaluate;
|
|
883
|
-
return this.createdInterpolant;
|
|
884
|
-
};
|
|
885
|
-
}
|
|
886
|
-
;
|
|
887
|
-
dispose() {
|
|
888
|
-
if (this.createdInterpolant && this.originalEvaluate) {
|
|
889
|
-
this.createdInterpolant.evaluate = this.originalEvaluate;
|
|
890
|
-
}
|
|
891
|
-
this.track = undefined;
|
|
892
|
-
this.createdInterpolant = null;
|
|
893
|
-
this.originalEvaluate = undefined;
|
|
894
|
-
this.customEvaluate = undefined;
|
|
895
|
-
}
|
|
896
|
-
}
|
|
897
|
-
/**
|
|
898
|
-
* Handles root motion extraction from animation tracks.
|
|
899
|
-
* Captures movement from animations and applies it to the root object.
|
|
900
|
-
*/
|
|
901
|
-
class RootMotionAction {
|
|
902
|
-
static lastObjPosition = {};
|
|
903
|
-
static lastObjRotation = {};
|
|
904
|
-
// we remove the first keyframe rotation from the space rotation when updating
|
|
905
|
-
static firstKeyframeRotation = {};
|
|
906
|
-
// this is used to rotate the space on clip end / start (so the transform direction is correct)
|
|
907
|
-
static spaceRotation = {};
|
|
908
|
-
static effectiveSpaceRotation = {};
|
|
909
|
-
static clipOffsetRotation = {};
|
|
910
|
-
set action(val) {
|
|
911
|
-
this._action = val;
|
|
912
|
-
}
|
|
913
|
-
get action() {
|
|
914
|
-
return this._action;
|
|
915
|
-
}
|
|
916
|
-
get cacheId() {
|
|
917
|
-
return this.root.uuid;
|
|
918
|
-
}
|
|
919
|
-
_action;
|
|
920
|
-
root;
|
|
921
|
-
clip;
|
|
922
|
-
positionWrapper = null;
|
|
923
|
-
rotationWrapper = null;
|
|
924
|
-
context;
|
|
925
|
-
positionChange = new Vector3();
|
|
926
|
-
rotationChange = new Quaternion();
|
|
927
|
-
constructor(context, root, clip, positionTrack, rotationTrack) {
|
|
928
|
-
// console.log(this, positionTrack, rotationTrack);
|
|
929
|
-
this.context = context;
|
|
930
|
-
this.root = root;
|
|
931
|
-
this.clip = clip;
|
|
932
|
-
if (!RootMotionAction.firstKeyframeRotation[this.cacheId])
|
|
933
|
-
RootMotionAction.firstKeyframeRotation[this.cacheId] = new Quaternion();
|
|
934
|
-
if (rotationTrack) {
|
|
935
|
-
const values = rotationTrack.values;
|
|
936
|
-
RootMotionAction.firstKeyframeRotation[this.cacheId]
|
|
937
|
-
.set(values[0], values[1], values[2], values[3]);
|
|
938
|
-
}
|
|
939
|
-
if (!RootMotionAction.spaceRotation[this.cacheId])
|
|
940
|
-
RootMotionAction.spaceRotation[this.cacheId] = new Quaternion();
|
|
941
|
-
if (!RootMotionAction.effectiveSpaceRotation[this.cacheId])
|
|
942
|
-
RootMotionAction.effectiveSpaceRotation[this.cacheId] = new Quaternion();
|
|
943
|
-
RootMotionAction.clipOffsetRotation[this.cacheId] = new Quaternion();
|
|
944
|
-
if (rotationTrack) {
|
|
945
|
-
RootMotionAction.clipOffsetRotation[this.cacheId]
|
|
946
|
-
.set(rotationTrack.values[0], rotationTrack.values[1], rotationTrack.values[2], rotationTrack.values[3])
|
|
947
|
-
.invert();
|
|
948
|
-
}
|
|
949
|
-
this.handlePosition(clip, positionTrack);
|
|
950
|
-
this.handleRotation(clip, rotationTrack);
|
|
951
|
-
}
|
|
952
|
-
onStart(action) {
|
|
953
|
-
if (action.getClip() !== this.clip)
|
|
954
|
-
return;
|
|
955
|
-
if (!RootMotionAction.lastObjRotation[this.cacheId]) {
|
|
956
|
-
RootMotionAction.lastObjRotation[this.cacheId] = this.root.quaternion.clone();
|
|
957
|
-
}
|
|
958
|
-
const lastRotation = RootMotionAction.lastObjRotation[this.cacheId];
|
|
959
|
-
// const firstKeyframe = RootMotionAction.firstKeyframeRotation[this.this.cacheId];
|
|
960
|
-
// lastRotation.invert().premultiply(firstKeyframe).invert();
|
|
961
|
-
RootMotionAction.spaceRotation[this.cacheId].copy(lastRotation);
|
|
962
|
-
if (debugRootMotion) {
|
|
963
|
-
const euler = new Euler().setFromQuaternion(lastRotation);
|
|
964
|
-
console.log("START", this.clip.name, Mathf.toDegrees(euler.y), this.root.position.z);
|
|
965
|
-
}
|
|
966
|
-
}
|
|
967
|
-
getClipRotationOffset() {
|
|
968
|
-
return RootMotionAction.clipOffsetRotation[this.cacheId];
|
|
969
|
-
}
|
|
970
|
-
_prevTime = 0;
|
|
971
|
-
handlePosition(_clip, track) {
|
|
972
|
-
if (track) {
|
|
973
|
-
const root = this.root;
|
|
974
|
-
if (debugRootMotion)
|
|
975
|
-
root.add(new AxesHelper());
|
|
976
|
-
if (!RootMotionAction.lastObjPosition[this.cacheId])
|
|
977
|
-
RootMotionAction.lastObjPosition[this.cacheId] = this.root.position.clone();
|
|
978
|
-
const valuesDiff = new Vector3();
|
|
979
|
-
const valuesPrev = new Vector3();
|
|
980
|
-
// const rotation = new Quaternion();
|
|
981
|
-
this.positionWrapper = new TrackEvaluationWrapper(track, (time, value) => {
|
|
982
|
-
const weight = this.action.getEffectiveWeight();
|
|
983
|
-
// reset for testing
|
|
984
|
-
if (debugRootMotion) {
|
|
985
|
-
if (root.position.length() > 8)
|
|
986
|
-
root.position.set(0, root.position.y, 0);
|
|
987
|
-
}
|
|
988
|
-
if (time > this._prevTime) {
|
|
989
|
-
valuesDiff.set(value[0], value[1], value[2]);
|
|
990
|
-
valuesDiff.sub(valuesPrev);
|
|
991
|
-
valuesDiff.multiplyScalar(weight);
|
|
992
|
-
valuesDiff.applyQuaternion(this.getClipRotationOffset());
|
|
993
|
-
// RootMotionAction.effectiveSpaceRotation[id].slerp(RootMotionAction.spaceRotation[id], weight);
|
|
994
|
-
valuesDiff.applyQuaternion(root.quaternion);
|
|
995
|
-
this.positionChange.copy(valuesDiff);
|
|
996
|
-
// this.root.position.add(valuesDiff);
|
|
997
|
-
}
|
|
998
|
-
valuesPrev.fromArray(value);
|
|
999
|
-
this._prevTime = time;
|
|
1000
|
-
value[0] = 0;
|
|
1001
|
-
value[1] = 0;
|
|
1002
|
-
value[2] = 0;
|
|
1003
|
-
return value;
|
|
1004
|
-
});
|
|
1005
|
-
}
|
|
1006
|
-
}
|
|
1007
|
-
static identityQuaternion = new Quaternion();
|
|
1008
|
-
handleRotation(clip, track) {
|
|
1009
|
-
if (track) {
|
|
1010
|
-
if (debugRootMotion) {
|
|
1011
|
-
const arr = track.values;
|
|
1012
|
-
const firstKeyframe = new Euler().setFromQuaternion(new Quaternion(arr[0], arr[1], arr[2], arr[3]));
|
|
1013
|
-
console.log(clip.name, track.name, "FIRST ROTATION IN TRACK", Mathf.toDegrees(firstKeyframe.y));
|
|
1014
|
-
const i = track.values.length - 4;
|
|
1015
|
-
const lastKeyframe = new Quaternion().set(arr[i], arr[i + 1], arr[i + 2], arr[i + 3]);
|
|
1016
|
-
const euler = new Euler().setFromQuaternion(lastKeyframe);
|
|
1017
|
-
console.log(clip.name, track.name, "LAST ROTATION IN TRACK", Mathf.toDegrees(euler.y));
|
|
1018
|
-
}
|
|
1019
|
-
// if (!RootMotionAction.lastObjRotation[root.uuid]) RootMotionAction.lastObjRotation[root.uuid] = new Quaternion();
|
|
1020
|
-
// const temp = new Quaternion();
|
|
1021
|
-
let prevTime = 0;
|
|
1022
|
-
const valuesPrev = new Quaternion();
|
|
1023
|
-
const valuesDiff = new Quaternion();
|
|
1024
|
-
// const summedRot = new Quaternion();
|
|
1025
|
-
this.rotationWrapper = new TrackEvaluationWrapper(track, (time, value) => {
|
|
1026
|
-
// root.quaternion.copy(RootMotionAction.lastObjRotation[root.uuid]);
|
|
1027
|
-
if (time > prevTime) {
|
|
1028
|
-
valuesDiff.set(value[0], value[1], value[2], value[3]);
|
|
1029
|
-
valuesPrev.invert();
|
|
1030
|
-
valuesDiff.multiply(valuesPrev);
|
|
1031
|
-
// if(weight < .99) valuesDiff.slerp(RootMotionAction.identityQuaternion, 1 - weight);
|
|
1032
|
-
this.rotationChange.copy(valuesDiff);
|
|
1033
|
-
// root.quaternion.multiply(valuesDiff);
|
|
1034
|
-
}
|
|
1035
|
-
// else
|
|
1036
|
-
// root.quaternion.multiply(this.getClipRotationOffset());
|
|
1037
|
-
// RootMotionAction.lastObjRotation[root.uuid].copy(root.quaternion);
|
|
1038
|
-
valuesPrev.fromArray(value);
|
|
1039
|
-
prevTime = time;
|
|
1040
|
-
value[0] = 0;
|
|
1041
|
-
value[1] = 0;
|
|
1042
|
-
value[2] = 0;
|
|
1043
|
-
value[3] = 1;
|
|
1044
|
-
return value;
|
|
1045
|
-
});
|
|
1046
|
-
}
|
|
1047
|
-
}
|
|
1048
|
-
// private lastPos: Vector3 = new Vector3();
|
|
1049
|
-
onBeforeUpdate(_weight) {
|
|
1050
|
-
this.positionChange.set(0, 0, 0);
|
|
1051
|
-
this.rotationChange.set(0, 0, 0, 1);
|
|
1052
|
-
}
|
|
1053
|
-
onAfterUpdate(weight) {
|
|
1054
|
-
if (!this.action)
|
|
1055
|
-
return false;
|
|
1056
|
-
weight *= this.action.getEffectiveWeight();
|
|
1057
|
-
if (weight <= 0)
|
|
1058
|
-
return false;
|
|
1059
|
-
this.positionChange.multiplyScalar(weight);
|
|
1060
|
-
this.rotationChange.slerp(RootMotionAction.identityQuaternion, 1 - weight);
|
|
1061
|
-
return true;
|
|
1062
|
-
}
|
|
1063
|
-
}
|
|
1064
|
-
/**
|
|
1065
|
-
* Manages root motion for a character.
|
|
1066
|
-
* Extracts motion from animation tracks and applies it to the character's transform.
|
|
1067
|
-
*/
|
|
1068
|
-
class RootMotionHandler {
|
|
1069
|
-
controller;
|
|
1070
|
-
handler = [];
|
|
1071
|
-
root;
|
|
1072
|
-
basePosition = new Vector3();
|
|
1073
|
-
baseQuaternion = new Quaternion();
|
|
1074
|
-
baseRotation = new Euler();
|
|
1075
|
-
constructor(controller) {
|
|
1076
|
-
this.controller = controller;
|
|
1077
|
-
}
|
|
1078
|
-
createClip(mixer, root, clip) {
|
|
1079
|
-
this.root = root;
|
|
1080
|
-
let rootName = "";
|
|
1081
|
-
if (root && "name" in root) {
|
|
1082
|
-
rootName = root.name;
|
|
1083
|
-
}
|
|
1084
|
-
const positionTrack = this.findRootTrack(clip, ".position");
|
|
1085
|
-
const rotationTrack = this.findRootTrack(clip, ".quaternion");
|
|
1086
|
-
const handler = new RootMotionAction(this.controller.context, root, clip, positionTrack, rotationTrack);
|
|
1087
|
-
this.handler.push(handler);
|
|
1088
|
-
// it is important we do this after the handler is created
|
|
1089
|
-
// otherwise we can not hook into threejs interpolators
|
|
1090
|
-
const action = mixer.clipAction(clip);
|
|
1091
|
-
handler.action = action;
|
|
1092
|
-
return action;
|
|
1093
|
-
}
|
|
1094
|
-
onStart(action) {
|
|
1095
|
-
for (const handler of this.handler) {
|
|
1096
|
-
handler.onStart(action);
|
|
1097
|
-
}
|
|
1098
|
-
}
|
|
1099
|
-
onBeforeUpdate(weight) {
|
|
1100
|
-
// capture the position of the object
|
|
1101
|
-
this.basePosition.copy(this.root.position);
|
|
1102
|
-
this.baseQuaternion.copy(this.root.quaternion);
|
|
1103
|
-
for (const hand of this.handler)
|
|
1104
|
-
hand.onBeforeUpdate(weight);
|
|
1105
|
-
}
|
|
1106
|
-
summedPosition = new Vector3();
|
|
1107
|
-
summedRotation = new Quaternion();
|
|
1108
|
-
onAfterUpdate(weight) {
|
|
1109
|
-
if (weight <= 0)
|
|
1110
|
-
return;
|
|
1111
|
-
// TODO: blend weight properly with root motion (when using timeline blending with animator)
|
|
1112
|
-
// apply the accumulated changes
|
|
1113
|
-
this.root.position.copy(this.basePosition);
|
|
1114
|
-
this.root.quaternion.copy(this.baseQuaternion);
|
|
1115
|
-
this.summedPosition.set(0, 0, 0);
|
|
1116
|
-
this.summedRotation.set(0, 0, 0, 1);
|
|
1117
|
-
for (const entry of this.handler) {
|
|
1118
|
-
if (entry.onAfterUpdate(weight)) {
|
|
1119
|
-
this.summedPosition.add(entry.positionChange);
|
|
1120
|
-
this.summedRotation.multiply(entry.rotationChange);
|
|
1121
|
-
}
|
|
1122
|
-
}
|
|
1123
|
-
this.root.position.add(this.summedPosition);
|
|
1124
|
-
this.root.quaternion.multiply(this.summedRotation);
|
|
1125
|
-
// RootMotionAction.lastObjRotation[this.root.uuid].copy(this.root.quaternion);
|
|
1126
|
-
}
|
|
1127
|
-
findRootTrack(clip, name) {
|
|
1128
|
-
const tracks = clip.tracks;
|
|
1129
|
-
if (!tracks)
|
|
1130
|
-
return null;
|
|
1131
|
-
for (const track of tracks) {
|
|
1132
|
-
if (track.name.endsWith(name)) {
|
|
1133
|
-
return track;
|
|
1134
|
-
}
|
|
1135
|
-
}
|
|
1136
|
-
return null;
|
|
1137
|
-
}
|
|
1138
|
-
}
|
|
1139
|
-
/**
|
|
1140
|
-
* Serialization handler for AnimatorController instances.
|
|
1141
|
-
* Handles conversion between serialized data and runtime objects.
|
|
1142
|
-
*/
|
|
1143
|
-
class AnimatorControllerSerializator extends TypeSerializer {
|
|
1144
|
-
onSerialize(_, _context) {
|
|
1145
|
-
}
|
|
1146
|
-
onDeserialize(data, context) {
|
|
1147
|
-
if (context.type === AnimatorController && data?.__type === "AnimatorController")
|
|
1148
|
-
return new AnimatorController(data);
|
|
1149
|
-
return undefined;
|
|
1150
|
-
}
|
|
1151
|
-
}
|
|
1152
|
-
new AnimatorControllerSerializator(AnimatorController);
|
|
1
|
+
import { AnimationClip, AnimationMixer, AxesHelper, Euler, LoopOnce, Quaternion, Vector3 } from "three";
|
|
2
|
+
import { isDevEnvironment } from "../engine/debug/index.js";
|
|
3
|
+
import { Mathf } from "../engine/engine_math.js";
|
|
4
|
+
import { InstantiateIdProvider } from "../engine/engine_networking_instantiate.js";
|
|
5
|
+
import { assign, TypeSerializer } from "../engine/engine_serialization_core.js";
|
|
6
|
+
import { isAnimationAction } from "../engine/engine_three_utils.js";
|
|
7
|
+
import { TypeStore } from "../engine/engine_typestore.js";
|
|
8
|
+
import { deepClone, getParam } from "../engine/engine_utils.js";
|
|
9
|
+
import { AnimatorConditionMode, AnimatorControllerParameterType, AnimatorStateInfo, createMotion } from "../engine/extensions/NEEDLE_animator_controller_model.js";
|
|
10
|
+
const debug = getParam("debuganimatorcontroller");
|
|
11
|
+
const debugRootMotion = getParam("debugrootmotion");
|
|
12
|
+
/**
|
|
13
|
+
* Generates a hash code for a string
|
|
14
|
+
* @param str - The string to hash
|
|
15
|
+
* @returns A numeric hash value
|
|
16
|
+
*/
|
|
17
|
+
function stringToHash(str) {
|
|
18
|
+
let hash = 0;
|
|
19
|
+
for (let i = 0; i < str.length; i++) {
|
|
20
|
+
const char = str.charCodeAt(i);
|
|
21
|
+
hash = ((hash << 5) - hash) + char;
|
|
22
|
+
hash = hash & hash;
|
|
23
|
+
}
|
|
24
|
+
return hash;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Controls the playback of animations using a state machine architecture.
|
|
28
|
+
*
|
|
29
|
+
* The AnimatorController manages animation states, transitions between states,
|
|
30
|
+
* and parameters that affect those transitions. It is used by the {@link Animator}
|
|
31
|
+
* component to control animation behavior on 3D models.
|
|
32
|
+
*
|
|
33
|
+
* Use the static method {@link AnimatorController.createFromClips} to create
|
|
34
|
+
* an animator controller from a set of animation clips.
|
|
35
|
+
*/
|
|
36
|
+
export class AnimatorController {
|
|
37
|
+
/**
|
|
38
|
+
* Creates an AnimatorController from a set of animation clips.
|
|
39
|
+
* Each clip becomes a state in the controller's state machine.
|
|
40
|
+
*
|
|
41
|
+
* @param clips - The animation clips to use for creating states
|
|
42
|
+
* @param options - Configuration options for the controller including looping behavior and transitions
|
|
43
|
+
* @returns A new AnimatorController instance
|
|
44
|
+
*/
|
|
45
|
+
static createFromClips(clips, options = { looping: false, autoTransition: true, transitionDuration: 0 }) {
|
|
46
|
+
const states = [];
|
|
47
|
+
for (let i = 0; i < clips.length; i++) {
|
|
48
|
+
const clip = clips[i];
|
|
49
|
+
const transitions = [];
|
|
50
|
+
if (options.autoTransition !== false) {
|
|
51
|
+
const dur = options.transitionDuration ?? 0;
|
|
52
|
+
const normalizedDuration = dur / clip.duration;
|
|
53
|
+
// automatically transition to self by default
|
|
54
|
+
let nextState = i;
|
|
55
|
+
if (options.autoTransition === undefined || options.autoTransition === true) {
|
|
56
|
+
nextState = (i + 1) % clips.length;
|
|
57
|
+
}
|
|
58
|
+
transitions.push({
|
|
59
|
+
exitTime: 1 - normalizedDuration,
|
|
60
|
+
offset: 0,
|
|
61
|
+
duration: dur,
|
|
62
|
+
hasExitTime: true,
|
|
63
|
+
destinationState: nextState,
|
|
64
|
+
conditions: [],
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
const state = {
|
|
68
|
+
name: clip.name,
|
|
69
|
+
hash: i,
|
|
70
|
+
motion: {
|
|
71
|
+
name: clip.name,
|
|
72
|
+
clip: clip,
|
|
73
|
+
isLooping: options?.looping ?? false,
|
|
74
|
+
},
|
|
75
|
+
transitions: transitions,
|
|
76
|
+
behaviours: []
|
|
77
|
+
};
|
|
78
|
+
states.push(state);
|
|
79
|
+
}
|
|
80
|
+
const model = {
|
|
81
|
+
name: "AnimatorController",
|
|
82
|
+
guid: new InstantiateIdProvider(Date.now()).generateUUID(),
|
|
83
|
+
parameters: [],
|
|
84
|
+
layers: [{
|
|
85
|
+
name: "Base Layer",
|
|
86
|
+
stateMachine: {
|
|
87
|
+
defaultState: 0,
|
|
88
|
+
states: states
|
|
89
|
+
}
|
|
90
|
+
}]
|
|
91
|
+
};
|
|
92
|
+
const controller = new AnimatorController(model);
|
|
93
|
+
return controller;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Plays an animation state by name or hash.
|
|
97
|
+
*
|
|
98
|
+
* @param name - The name or hash identifier of the state to play
|
|
99
|
+
* @param layerIndex - The layer index (defaults to 0)
|
|
100
|
+
* @param normalizedTime - The normalized time to start the animation from (0-1)
|
|
101
|
+
* @param durationInSec - Transition duration in seconds
|
|
102
|
+
*/
|
|
103
|
+
play(name, layerIndex = -1, normalizedTime = Number.NEGATIVE_INFINITY, durationInSec = 0) {
|
|
104
|
+
if (layerIndex < 0)
|
|
105
|
+
layerIndex = 0;
|
|
106
|
+
else if (layerIndex >= this.model.layers.length) {
|
|
107
|
+
console.warn("invalid layer");
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
const layer = this.model.layers[layerIndex];
|
|
111
|
+
const sm = layer.stateMachine;
|
|
112
|
+
for (const state of sm.states) {
|
|
113
|
+
if (state.name === name || state.hash === name) {
|
|
114
|
+
if (debug)
|
|
115
|
+
console.log("transition to ", state);
|
|
116
|
+
this.transitionTo(state, durationInSec, normalizedTime);
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
console.warn("Could not find " + name + " to play");
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Resets the controller to its initial state.
|
|
124
|
+
*/
|
|
125
|
+
reset() {
|
|
126
|
+
this.setStartTransition();
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Sets a boolean parameter value by name or hash.
|
|
130
|
+
*
|
|
131
|
+
* @param name - The name or hash identifier of the parameter
|
|
132
|
+
* @param value - The boolean value to set
|
|
133
|
+
*/
|
|
134
|
+
setBool(name, value) {
|
|
135
|
+
const key = typeof name === "string" ? "name" : "hash";
|
|
136
|
+
return this.model?.parameters?.filter(p => p[key] === name).forEach(p => p.value = value);
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Gets a boolean parameter value by name or hash.
|
|
140
|
+
*
|
|
141
|
+
* @param name - The name or hash identifier of the parameter
|
|
142
|
+
* @returns The boolean value of the parameter, or false if not found
|
|
143
|
+
*/
|
|
144
|
+
getBool(name) {
|
|
145
|
+
const key = typeof name === "string" ? "name" : "hash";
|
|
146
|
+
return this.model?.parameters?.find(p => p[key] === name)?.value ?? false;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Sets a float parameter value by name or hash.
|
|
150
|
+
*
|
|
151
|
+
* @param name - The name or hash identifier of the parameter
|
|
152
|
+
* @param val - The float value to set
|
|
153
|
+
* @returns True if the parameter was found and set, false otherwise
|
|
154
|
+
*/
|
|
155
|
+
setFloat(name, val) {
|
|
156
|
+
const key = typeof name === "string" ? "name" : "hash";
|
|
157
|
+
const filtered = this.model?.parameters?.filter(p => p[key] === name);
|
|
158
|
+
filtered.forEach(p => p.value = val);
|
|
159
|
+
return filtered?.length > 0;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Gets a float parameter value by name or hash.
|
|
163
|
+
*
|
|
164
|
+
* @param name - The name or hash identifier of the parameter
|
|
165
|
+
* @returns The float value of the parameter, or 0 if not found
|
|
166
|
+
*/
|
|
167
|
+
getFloat(name) {
|
|
168
|
+
const key = typeof name === "string" ? "name" : "hash";
|
|
169
|
+
return this.model?.parameters?.find(p => p[key] === name)?.value ?? 0;
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Sets an integer parameter value by name or hash.
|
|
173
|
+
*
|
|
174
|
+
* @param name - The name or hash identifier of the parameter
|
|
175
|
+
* @param val - The integer value to set
|
|
176
|
+
*/
|
|
177
|
+
setInteger(name, val) {
|
|
178
|
+
const key = typeof name === "string" ? "name" : "hash";
|
|
179
|
+
return this.model?.parameters?.filter(p => p[key] === name).forEach(p => p.value = val);
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Gets an integer parameter value by name or hash.
|
|
183
|
+
*
|
|
184
|
+
* @param name - The name or hash identifier of the parameter
|
|
185
|
+
* @returns The integer value of the parameter, or 0 if not found
|
|
186
|
+
*/
|
|
187
|
+
getInteger(name) {
|
|
188
|
+
const key = typeof name === "string" ? "name" : "hash";
|
|
189
|
+
return this.model?.parameters?.find(p => p[key] === name)?.value ?? 0;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Sets a trigger parameter to active (true).
|
|
193
|
+
* Trigger parameters are automatically reset after they are consumed by a transition.
|
|
194
|
+
*
|
|
195
|
+
* @param name - The name or hash identifier of the trigger parameter
|
|
196
|
+
*/
|
|
197
|
+
setTrigger(name) {
|
|
198
|
+
if (debug)
|
|
199
|
+
console.log("SET TRIGGER", name);
|
|
200
|
+
const key = typeof name === "string" ? "name" : "hash";
|
|
201
|
+
return this.model?.parameters?.filter(p => p[key] === name).forEach(p => p.value = true);
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Resets a trigger parameter to inactive (false).
|
|
205
|
+
*
|
|
206
|
+
* @param name - The name or hash identifier of the trigger parameter
|
|
207
|
+
*/
|
|
208
|
+
resetTrigger(name) {
|
|
209
|
+
const key = typeof name === "string" ? "name" : "hash";
|
|
210
|
+
return this.model?.parameters?.filter(p => p[key] === name).forEach(p => p.value = false);
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Gets the current state of a trigger parameter.
|
|
214
|
+
*
|
|
215
|
+
* @param name - The name or hash identifier of the trigger parameter
|
|
216
|
+
* @returns The boolean state of the trigger, or false if not found
|
|
217
|
+
*/
|
|
218
|
+
getTrigger(name) {
|
|
219
|
+
const key = typeof name === "string" ? "name" : "hash";
|
|
220
|
+
return this.model?.parameters?.find(p => p[key] === name)?.value ?? false;
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Checks if the controller is currently in a transition between states.
|
|
224
|
+
*
|
|
225
|
+
* @returns True if a transition is in progress, false otherwise
|
|
226
|
+
*/
|
|
227
|
+
isInTransition() {
|
|
228
|
+
return this._activeStates.length > 1;
|
|
229
|
+
}
|
|
230
|
+
/** Set the speed of the animator controller. Larger values will make the animation play faster. */
|
|
231
|
+
setSpeed(speed) {
|
|
232
|
+
this._speed = speed;
|
|
233
|
+
}
|
|
234
|
+
_speed = 1;
|
|
235
|
+
/**
|
|
236
|
+
* Finds an animation state by name or hash.
|
|
237
|
+
* @deprecated Use findState instead
|
|
238
|
+
*
|
|
239
|
+
* @param name - The name or hash identifier of the state to find
|
|
240
|
+
* @returns The found state or null if not found
|
|
241
|
+
*/
|
|
242
|
+
FindState(name) { return this.findState(name); }
|
|
243
|
+
/**
|
|
244
|
+
* Finds an animation state by name or hash.
|
|
245
|
+
*
|
|
246
|
+
* @param name - The name or hash identifier of the state to find
|
|
247
|
+
* @returns The found state or null if not found
|
|
248
|
+
*/
|
|
249
|
+
findState(name) {
|
|
250
|
+
if (!name)
|
|
251
|
+
return null;
|
|
252
|
+
if (Array.isArray(this.model.layers)) {
|
|
253
|
+
for (const layer of this.model.layers) {
|
|
254
|
+
for (const state of layer.stateMachine.states) {
|
|
255
|
+
if (state.name === name || state.hash == name)
|
|
256
|
+
return state;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
return null;
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Gets information about the current playing animation state.
|
|
264
|
+
*
|
|
265
|
+
* @returns An AnimatorStateInfo object with data about the current state, or null if no state is active
|
|
266
|
+
*/
|
|
267
|
+
getCurrentStateInfo() {
|
|
268
|
+
if (!this._activeState)
|
|
269
|
+
return null;
|
|
270
|
+
const action = this._activeState.motion.action;
|
|
271
|
+
if (!action)
|
|
272
|
+
return null;
|
|
273
|
+
const dur = this._activeState.motion.clip.duration;
|
|
274
|
+
const normalizedTime = dur <= 0 ? 0 : Math.abs(action.time / dur);
|
|
275
|
+
return new AnimatorStateInfo(this._activeState, normalizedTime, dur, this._speed);
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Gets the animation action currently playing.
|
|
279
|
+
*
|
|
280
|
+
* @returns The current animation action, or null if no action is playing
|
|
281
|
+
*/
|
|
282
|
+
get currentAction() {
|
|
283
|
+
if (!this._activeState)
|
|
284
|
+
return null;
|
|
285
|
+
const action = this._activeState.motion.action;
|
|
286
|
+
if (!action)
|
|
287
|
+
return null;
|
|
288
|
+
return action;
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* The normalized time (0-1) to start playing the first state at.
|
|
292
|
+
* This affects the initial state when the animator is first enabled.
|
|
293
|
+
*/
|
|
294
|
+
normalizedStartOffset = 0;
|
|
295
|
+
/**
|
|
296
|
+
* The Animator component this controller is bound to.
|
|
297
|
+
*/
|
|
298
|
+
animator;
|
|
299
|
+
/**
|
|
300
|
+
* The data model describing the animation states and transitions.
|
|
301
|
+
*/
|
|
302
|
+
model;
|
|
303
|
+
/**
|
|
304
|
+
* Gets the engine context from the bound animator.
|
|
305
|
+
*/
|
|
306
|
+
get context() { return this.animator?.context; }
|
|
307
|
+
/**
|
|
308
|
+
* Gets the animation mixer used by this controller.
|
|
309
|
+
*/
|
|
310
|
+
get mixer() {
|
|
311
|
+
return this._mixer;
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Cleans up resources used by this controller.
|
|
315
|
+
* Stops all animations and unregisters the mixer from the animation system.
|
|
316
|
+
*/
|
|
317
|
+
dispose() {
|
|
318
|
+
this._mixer.stopAllAction();
|
|
319
|
+
if (this.animator) {
|
|
320
|
+
this._mixer.uncacheRoot(this.animator.gameObject);
|
|
321
|
+
for (const action of this._activeStates) {
|
|
322
|
+
if (action.motion.clip)
|
|
323
|
+
this.mixer.uncacheAction(action.motion.clip, this.animator.gameObject);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
this.context?.animations.unregisterAnimationMixer(this._mixer);
|
|
327
|
+
}
|
|
328
|
+
// applyRootMotion(obj: Object3D) {
|
|
329
|
+
// // this.internalApplyRootMotion(obj);
|
|
330
|
+
// }
|
|
331
|
+
/**
|
|
332
|
+
* Binds this controller to an animator component.
|
|
333
|
+
* Creates a new animation mixer and sets up animation actions.
|
|
334
|
+
*
|
|
335
|
+
* @param animator - The animator to bind this controller to
|
|
336
|
+
*/
|
|
337
|
+
bind(animator) {
|
|
338
|
+
if (!animator)
|
|
339
|
+
console.error("AnimatorController.bind: animator is null");
|
|
340
|
+
else if (this.animator !== animator) {
|
|
341
|
+
if (this._mixer) {
|
|
342
|
+
this._mixer.stopAllAction();
|
|
343
|
+
this.context?.animations.unregisterAnimationMixer(this._mixer);
|
|
344
|
+
}
|
|
345
|
+
this.animator = animator;
|
|
346
|
+
this._mixer = new AnimationMixer(this.animator.gameObject);
|
|
347
|
+
this.context?.animations.registerAnimationMixer(this._mixer);
|
|
348
|
+
this.createActions(this.animator);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
/**
|
|
352
|
+
* Creates a deep copy of this controller.
|
|
353
|
+
* Clones the model data but does not copy runtime state.
|
|
354
|
+
*
|
|
355
|
+
* @returns A new AnimatorController instance with the same configuration
|
|
356
|
+
*/
|
|
357
|
+
clone() {
|
|
358
|
+
if (typeof this.model === "string") {
|
|
359
|
+
console.warn("AnimatorController has not been resolved, can not create model from string", this.model);
|
|
360
|
+
return null;
|
|
361
|
+
}
|
|
362
|
+
if (debug)
|
|
363
|
+
console.warn("AnimatorController clone()", this.model);
|
|
364
|
+
// clone runtime controller but dont clone clip or action
|
|
365
|
+
const clonedModel = deepClone(this.model, (_owner, _key, _value) => {
|
|
366
|
+
if (_value === null || _value === undefined)
|
|
367
|
+
return true;
|
|
368
|
+
// dont clone three Objects
|
|
369
|
+
if (_value.type === "Object3D" || _value.isObject3D === true)
|
|
370
|
+
return false;
|
|
371
|
+
// dont clone AnimationAction
|
|
372
|
+
if (isAnimationAction(_value)) { //.constructor.name === "AnimationAction") {
|
|
373
|
+
// console.log(_value);
|
|
374
|
+
return false;
|
|
375
|
+
}
|
|
376
|
+
// dont clone AnimationClip
|
|
377
|
+
if (_value["tracks"] !== undefined)
|
|
378
|
+
return false;
|
|
379
|
+
// when assigned __concreteInstance during serialization
|
|
380
|
+
if (_value instanceof AnimatorController)
|
|
381
|
+
return false;
|
|
382
|
+
return true;
|
|
383
|
+
});
|
|
384
|
+
console.assert(clonedModel !== this.model);
|
|
385
|
+
const controller = new AnimatorController(clonedModel);
|
|
386
|
+
return controller;
|
|
387
|
+
}
|
|
388
|
+
/**
|
|
389
|
+
* Updates the controller's state machine and animations.
|
|
390
|
+
* Called each frame by the animator component.
|
|
391
|
+
*
|
|
392
|
+
* @param weight - The weight to apply to the animations (for blending)
|
|
393
|
+
*/
|
|
394
|
+
update(weight) {
|
|
395
|
+
if (!this.animator)
|
|
396
|
+
return;
|
|
397
|
+
this.evaluateTransitions();
|
|
398
|
+
this.updateActiveStates(weight);
|
|
399
|
+
// We want to update the animation mixer even if there is no active state (e.g. in cases where an empty animator controller is assigned and the timeline runs)
|
|
400
|
+
// if (!this._activeState) return;
|
|
401
|
+
const dt = this.animator.context.time.deltaTime;
|
|
402
|
+
if (this.animator.applyRootMotion) {
|
|
403
|
+
this.rootMotionHandler?.onBeforeUpdate(weight);
|
|
404
|
+
}
|
|
405
|
+
this._mixer.update(dt);
|
|
406
|
+
if (this.animator.applyRootMotion) {
|
|
407
|
+
this.rootMotionHandler?.onAfterUpdate(weight);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
_mixer;
|
|
411
|
+
_activeState;
|
|
412
|
+
/**
|
|
413
|
+
* Gets the currently active animation state.
|
|
414
|
+
*
|
|
415
|
+
* @returns The active state or undefined if no state is active
|
|
416
|
+
*/
|
|
417
|
+
get activeState() { return this._activeState; }
|
|
418
|
+
constructor(model) {
|
|
419
|
+
this.model = model;
|
|
420
|
+
if (debug)
|
|
421
|
+
console.log(this);
|
|
422
|
+
}
|
|
423
|
+
_activeStates = [];
|
|
424
|
+
updateActiveStates(weight) {
|
|
425
|
+
for (let i = 0; i < this._activeStates.length; i++) {
|
|
426
|
+
const state = this._activeStates[i];
|
|
427
|
+
const motion = state.motion;
|
|
428
|
+
if (!motion.action) {
|
|
429
|
+
this._activeStates.splice(i, 1);
|
|
430
|
+
i--;
|
|
431
|
+
}
|
|
432
|
+
else {
|
|
433
|
+
const action = motion.action;
|
|
434
|
+
action.weight = weight;
|
|
435
|
+
// console.log(action.getClip().name, action.getEffectiveWeight(), action.isScheduled());
|
|
436
|
+
if ((action.getEffectiveWeight() <= 0 && !action.isRunning())) {
|
|
437
|
+
if (debug)
|
|
438
|
+
console.debug("REMOVE", state.name, action.getEffectiveWeight(), action.isRunning(), action.isScheduled());
|
|
439
|
+
this._activeStates.splice(i, 1);
|
|
440
|
+
i--;
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
setStartTransition() {
|
|
446
|
+
if (this.model.layers.length > 1 && (debug || isDevEnvironment())) {
|
|
447
|
+
console.warn("Multiple layers are not supported yet " + this.animator?.name);
|
|
448
|
+
}
|
|
449
|
+
for (const layer of this.model.layers) {
|
|
450
|
+
const sm = layer.stateMachine;
|
|
451
|
+
if (sm.defaultState === undefined) {
|
|
452
|
+
if (debug)
|
|
453
|
+
console.warn("AnimatorController default state is undefined, will assign state 0 as default", layer);
|
|
454
|
+
sm.defaultState = 0;
|
|
455
|
+
}
|
|
456
|
+
const start = sm.states[sm.defaultState];
|
|
457
|
+
this.transitionTo(start, 0, this.normalizedStartOffset);
|
|
458
|
+
break;
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
evaluateTransitions() {
|
|
462
|
+
let didEnterStateThisFrame = false;
|
|
463
|
+
if (!this._activeState) {
|
|
464
|
+
this.setStartTransition();
|
|
465
|
+
if (!this._activeState)
|
|
466
|
+
return;
|
|
467
|
+
didEnterStateThisFrame = true;
|
|
468
|
+
}
|
|
469
|
+
const state = this._activeState;
|
|
470
|
+
const action = state.motion.action;
|
|
471
|
+
let index = 0;
|
|
472
|
+
for (const transition of state.transitions) {
|
|
473
|
+
++index;
|
|
474
|
+
// transition without exit time and without condition that transition to itself are ignored
|
|
475
|
+
if (!transition.hasExitTime && transition.conditions.length <= 0) {
|
|
476
|
+
// if (this._activeState && this.getState(transition.destinationState, currentLayer)?.hash === this._activeState.hash)
|
|
477
|
+
continue;
|
|
478
|
+
}
|
|
479
|
+
let allConditionsAreMet = true;
|
|
480
|
+
for (const cond of transition.conditions) {
|
|
481
|
+
if (!this.evaluateCondition(cond)) {
|
|
482
|
+
allConditionsAreMet = false;
|
|
483
|
+
break;
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
if (!allConditionsAreMet)
|
|
487
|
+
continue;
|
|
488
|
+
if (debug && allConditionsAreMet) {
|
|
489
|
+
// console.log("All conditions are met", transition);
|
|
490
|
+
}
|
|
491
|
+
if (action) {
|
|
492
|
+
const dur = state.motion.clip.duration;
|
|
493
|
+
const normalizedTime = dur <= 0 ? 1 : Math.abs(action.time / dur);
|
|
494
|
+
let exitTime = transition.exitTime;
|
|
495
|
+
// When the animation is playing backwards we need to check exit time inverted
|
|
496
|
+
if (action.timeScale < 0) {
|
|
497
|
+
exitTime = 1 - exitTime;
|
|
498
|
+
}
|
|
499
|
+
let makeTransition = false;
|
|
500
|
+
if (transition.hasExitTime) {
|
|
501
|
+
if (action.timeScale > 0)
|
|
502
|
+
makeTransition = normalizedTime >= transition.exitTime;
|
|
503
|
+
// When the animation is playing backwards we need to check exit time inverted
|
|
504
|
+
else if (action.timeScale < 0)
|
|
505
|
+
makeTransition = 1 - normalizedTime >= transition.exitTime;
|
|
506
|
+
}
|
|
507
|
+
else {
|
|
508
|
+
makeTransition = true;
|
|
509
|
+
}
|
|
510
|
+
if (makeTransition) {
|
|
511
|
+
// disable triggers for this transition
|
|
512
|
+
for (const cond of transition.conditions) {
|
|
513
|
+
const param = this.model.parameters.find(p => p.name === cond.parameter);
|
|
514
|
+
if (param?.type === AnimatorControllerParameterType.Trigger && param.value) {
|
|
515
|
+
param.value = false;
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
// if (transition.hasExitTime && transition.exitTime >= .9999)
|
|
519
|
+
action.clampWhenFinished = true;
|
|
520
|
+
// else action.clampWhenFinished = false;
|
|
521
|
+
if (debug) {
|
|
522
|
+
const targetState = this.getState(transition.destinationState, 0);
|
|
523
|
+
console.log(`Transition to ${transition.destinationState} / ${targetState?.name}`, transition, "\nTimescale: " + action.timeScale, "\nNormalized time: " + normalizedTime.toFixed(3), "\nExit Time: " + exitTime, transition.hasExitTime);
|
|
524
|
+
// console.log(action.time, transition.exitTime);
|
|
525
|
+
}
|
|
526
|
+
this.transitionTo(transition.destinationState, transition.duration, transition.offset);
|
|
527
|
+
// use the first transition that matches all conditions and make the transition as soon as in range
|
|
528
|
+
return;
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
else {
|
|
532
|
+
this.transitionTo(transition.destinationState, transition.duration, transition.offset);
|
|
533
|
+
return;
|
|
534
|
+
}
|
|
535
|
+
// if none of the transitions can be made continue searching for another transition meeting the conditions
|
|
536
|
+
}
|
|
537
|
+
// action.time += this.context.time.deltaTime
|
|
538
|
+
// console.log(action?.time, action?.getEffectiveWeight())
|
|
539
|
+
// update timescale
|
|
540
|
+
if (action) {
|
|
541
|
+
this.setTimescale(action, state);
|
|
542
|
+
}
|
|
543
|
+
let didTriggerLooping = false;
|
|
544
|
+
if (state.motion.isLooping && action) {
|
|
545
|
+
// we dont use the three loop state here because it prevents the transition check above
|
|
546
|
+
// it is easier if we re-trigger loop here.
|
|
547
|
+
// We also can easily add the cycle offset settings from unity later
|
|
548
|
+
if (action.time >= action.getClip().duration) {
|
|
549
|
+
didTriggerLooping = true;
|
|
550
|
+
action.reset();
|
|
551
|
+
action.time = 0;
|
|
552
|
+
action.play();
|
|
553
|
+
}
|
|
554
|
+
else if (action.time <= 0 && action.timeScale < 0) {
|
|
555
|
+
didTriggerLooping = true;
|
|
556
|
+
action.reset();
|
|
557
|
+
action.time = action.getClip().duration;
|
|
558
|
+
action.play();
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
// call update state behaviours:
|
|
562
|
+
if (!didTriggerLooping && state && !didEnterStateThisFrame && action && this.animator) {
|
|
563
|
+
if (state.behaviours) {
|
|
564
|
+
const duration = action?.getClip().duration;
|
|
565
|
+
const normalizedTime = action.time / duration;
|
|
566
|
+
const info = new AnimatorStateInfo(this._activeState, normalizedTime, duration, this._speed);
|
|
567
|
+
for (const beh of state.behaviours) {
|
|
568
|
+
if (beh.instance) {
|
|
569
|
+
beh.instance.onStateUpdate?.call(beh.instance, this.animator, info, 0);
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
setTimescale(action, state) {
|
|
576
|
+
let speedFactor = state.speed ?? 1;
|
|
577
|
+
if (state.speedParameter)
|
|
578
|
+
speedFactor *= this.getFloat(state.speedParameter);
|
|
579
|
+
if (speedFactor !== undefined) {
|
|
580
|
+
action.timeScale = speedFactor * this._speed;
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
getState(state, layerIndex) {
|
|
584
|
+
if (typeof state === "number") {
|
|
585
|
+
if (state == -1) {
|
|
586
|
+
state = this.model.layers[layerIndex].stateMachine.defaultState; // exit state -> entry state
|
|
587
|
+
if (state === undefined) {
|
|
588
|
+
if (debug)
|
|
589
|
+
console.warn("AnimatorController default state is undefined: ", this.model, "Layer: " + layerIndex);
|
|
590
|
+
state = 0;
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
state = this.model.layers[layerIndex].stateMachine.states[state];
|
|
594
|
+
}
|
|
595
|
+
return state;
|
|
596
|
+
}
|
|
597
|
+
/**
|
|
598
|
+
* These actions have been active previously but not faded out because we entered a state that has no real animation - no duration. In which case we hold the previously active actions until they are faded out.
|
|
599
|
+
*/
|
|
600
|
+
_heldActions = [];
|
|
601
|
+
releaseHeldActions(duration) {
|
|
602
|
+
for (const prev of this._heldActions) {
|
|
603
|
+
prev.fadeOut(duration);
|
|
604
|
+
}
|
|
605
|
+
this._heldActions.length = 0;
|
|
606
|
+
}
|
|
607
|
+
transitionTo(state, durationInSec, offsetNormalized) {
|
|
608
|
+
if (!this.animator)
|
|
609
|
+
return;
|
|
610
|
+
const layerIndex = 0;
|
|
611
|
+
state = this.getState(state, layerIndex);
|
|
612
|
+
if (!state?.motion || !state.motion.clip || !(state.motion.clip instanceof AnimationClip)) {
|
|
613
|
+
// if(debug) console.warn("State has no clip or motion", state);
|
|
614
|
+
return;
|
|
615
|
+
}
|
|
616
|
+
const isSelf = this._activeState === state;
|
|
617
|
+
if (isSelf) {
|
|
618
|
+
const motion = state.motion;
|
|
619
|
+
if (!motion.action_loopback && motion.clip) {
|
|
620
|
+
// uncache action immediately resets the applied animation which breaks the root motion
|
|
621
|
+
// this happens if we have a transition to self and the clip is not cached yet
|
|
622
|
+
const previousMatrix = this.rootMotionHandler ? this.animator.gameObject.matrix.clone() : null;
|
|
623
|
+
this._mixer.uncacheAction(motion.clip, this.animator.gameObject);
|
|
624
|
+
if (previousMatrix)
|
|
625
|
+
previousMatrix.decompose(this.animator.gameObject.position, this.animator.gameObject.quaternion, this.animator.gameObject.scale);
|
|
626
|
+
motion.action_loopback = this.createAction(motion.clip);
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
// call exit state behaviours
|
|
630
|
+
if (this._activeState?.behaviours && this._activeState.motion.action) {
|
|
631
|
+
const duration = this._activeState?.motion.clip.duration;
|
|
632
|
+
const normalizedTime = this._activeState.motion.action.time / duration;
|
|
633
|
+
const info = new AnimatorStateInfo(this._activeState, normalizedTime, duration, this._speed);
|
|
634
|
+
for (const beh of this._activeState.behaviours) {
|
|
635
|
+
beh.instance?.onStateExit?.call(beh.instance, this.animator, info, layerIndex);
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
const prevAction = this._activeState?.motion.action;
|
|
639
|
+
if (isSelf) {
|
|
640
|
+
state.motion.action = state.motion.action_loopback;
|
|
641
|
+
state.motion.action_loopback = prevAction;
|
|
642
|
+
}
|
|
643
|
+
const prev = this._activeState;
|
|
644
|
+
this._activeState = state;
|
|
645
|
+
const action = state.motion?.action;
|
|
646
|
+
const clip = state.motion.clip;
|
|
647
|
+
if (clip?.duration <= 0 && clip.tracks.length <= 0) {
|
|
648
|
+
// if the new state doesn't have a valid clip / no tracks we don't fadeout the previous action and instead hold the previous action.
|
|
649
|
+
if (prevAction) {
|
|
650
|
+
this._heldActions.push(prevAction);
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
else if (prevAction) {
|
|
654
|
+
prevAction.fadeOut(durationInSec);
|
|
655
|
+
this.releaseHeldActions(durationInSec);
|
|
656
|
+
}
|
|
657
|
+
if (action) {
|
|
658
|
+
offsetNormalized = Math.max(0, Math.min(1, offsetNormalized));
|
|
659
|
+
if (state.cycleOffsetParameter) {
|
|
660
|
+
let val = this.getFloat(state.cycleOffsetParameter);
|
|
661
|
+
if (typeof val === "number") {
|
|
662
|
+
if (val < 0)
|
|
663
|
+
val += 1;
|
|
664
|
+
offsetNormalized += val;
|
|
665
|
+
offsetNormalized %= 1;
|
|
666
|
+
}
|
|
667
|
+
else if (debug)
|
|
668
|
+
console.warn("AnimatorController cycle offset parameter is not a number", state.cycleOffsetParameter);
|
|
669
|
+
}
|
|
670
|
+
else if (typeof state.cycleOffset === "number") {
|
|
671
|
+
offsetNormalized += state.cycleOffset;
|
|
672
|
+
offsetNormalized %= 1;
|
|
673
|
+
}
|
|
674
|
+
if (action.isRunning())
|
|
675
|
+
action.stop();
|
|
676
|
+
action.reset();
|
|
677
|
+
action.enabled = true;
|
|
678
|
+
this.setTimescale(action, state);
|
|
679
|
+
const duration = state.motion.clip.duration;
|
|
680
|
+
// if we are looping to the same state we don't want to offset the current start time
|
|
681
|
+
action.time = isSelf ? 0 : offsetNormalized * duration;
|
|
682
|
+
if (action.timeScale < 0)
|
|
683
|
+
action.time = duration - action.time;
|
|
684
|
+
action.clampWhenFinished = true;
|
|
685
|
+
action.setLoop(LoopOnce, 0);
|
|
686
|
+
if (durationInSec > 0)
|
|
687
|
+
action.fadeIn(durationInSec);
|
|
688
|
+
else
|
|
689
|
+
action.weight = 1;
|
|
690
|
+
action.play();
|
|
691
|
+
if (this.rootMotionHandler) {
|
|
692
|
+
this.rootMotionHandler.onStart(action);
|
|
693
|
+
}
|
|
694
|
+
if (!this._activeStates.includes(state))
|
|
695
|
+
this._activeStates.push(state);
|
|
696
|
+
// call enter state behaviours
|
|
697
|
+
if (this._activeState.behaviours) {
|
|
698
|
+
const info = new AnimatorStateInfo(state, offsetNormalized, duration, this._speed);
|
|
699
|
+
for (const beh of this._activeState.behaviours) {
|
|
700
|
+
beh.instance?.onStateEnter?.call(beh.instance, this.animator, info, layerIndex);
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
else if (debug) {
|
|
705
|
+
if (!state["__warned_no_motion"]) {
|
|
706
|
+
state["__warned_no_motion"] = true;
|
|
707
|
+
console.warn("No action", state.motion, this);
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
if (debug)
|
|
711
|
+
console.log("TRANSITION FROM " + prev?.name + " TO " + state.name, durationInSec, prevAction, action, action?.getEffectiveTimeScale(), action?.getEffectiveWeight(), action?.isRunning(), action?.isScheduled(), action?.paused);
|
|
712
|
+
}
|
|
713
|
+
createAction(clip) {
|
|
714
|
+
// uncache clip causes issues when multiple states use the same clip
|
|
715
|
+
// this._mixer.uncacheClip(clip);
|
|
716
|
+
// instead only uncache the action when one already exists to make sure
|
|
717
|
+
// we get unique actions per state
|
|
718
|
+
const existing = this._mixer.existingAction(clip);
|
|
719
|
+
if (existing)
|
|
720
|
+
this._mixer.uncacheAction(clip, this.animator?.gameObject);
|
|
721
|
+
if (this.animator?.applyRootMotion) {
|
|
722
|
+
if (!this.rootMotionHandler) {
|
|
723
|
+
this.rootMotionHandler = new RootMotionHandler(this);
|
|
724
|
+
}
|
|
725
|
+
// TODO: find root bone properly
|
|
726
|
+
const root = this.animator.gameObject;
|
|
727
|
+
return this.rootMotionHandler.createClip(this._mixer, root, clip);
|
|
728
|
+
}
|
|
729
|
+
else {
|
|
730
|
+
const action = this._mixer.clipAction(clip);
|
|
731
|
+
return action;
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
evaluateCondition(cond) {
|
|
735
|
+
const param = this.model.parameters.find(p => p.name === cond.parameter);
|
|
736
|
+
if (!param)
|
|
737
|
+
return false;
|
|
738
|
+
// console.log(param.name, param.value);
|
|
739
|
+
switch (cond.mode) {
|
|
740
|
+
case AnimatorConditionMode.If:
|
|
741
|
+
return param.value === true;
|
|
742
|
+
case AnimatorConditionMode.IfNot:
|
|
743
|
+
return param.value === false;
|
|
744
|
+
case AnimatorConditionMode.Greater:
|
|
745
|
+
return param.value > cond.threshold;
|
|
746
|
+
case AnimatorConditionMode.Less:
|
|
747
|
+
return param.value < cond.threshold;
|
|
748
|
+
case AnimatorConditionMode.Equals:
|
|
749
|
+
return param.value === cond.threshold;
|
|
750
|
+
case AnimatorConditionMode.NotEqual:
|
|
751
|
+
return param.value !== cond.threshold;
|
|
752
|
+
}
|
|
753
|
+
return false;
|
|
754
|
+
}
|
|
755
|
+
createActions(_animator) {
|
|
756
|
+
if (debug)
|
|
757
|
+
console.log("AnimatorController createActions", this.model);
|
|
758
|
+
for (const layer of this.model.layers) {
|
|
759
|
+
const sm = layer.stateMachine;
|
|
760
|
+
for (let index = 0; index < sm.states.length; index++) {
|
|
761
|
+
const state = sm.states[index];
|
|
762
|
+
// ensure we have a transitions array
|
|
763
|
+
if (!state.transitions) {
|
|
764
|
+
state.transitions = [];
|
|
765
|
+
}
|
|
766
|
+
for (const t of state.transitions) {
|
|
767
|
+
// can happen if conditions are empty in blender - the exporter seems to skip empty arrays
|
|
768
|
+
if (!t.conditions)
|
|
769
|
+
t.conditions = [];
|
|
770
|
+
}
|
|
771
|
+
// ensure we have a motion even if none was exported
|
|
772
|
+
if (!state.motion) {
|
|
773
|
+
if (debug)
|
|
774
|
+
console.warn("No motion", state);
|
|
775
|
+
state.motion = createMotion(state.name);
|
|
776
|
+
// console.warn("Missing motion", "AnimatorController: " + this.model.name, state);
|
|
777
|
+
// sm.states.splice(index, 1);
|
|
778
|
+
// index -= 1;
|
|
779
|
+
// continue;
|
|
780
|
+
}
|
|
781
|
+
// the clips array contains which animator has which animationclip
|
|
782
|
+
if (this.animator && state.motion.clips) {
|
|
783
|
+
// TODO: we have to compare by name because on instantiate we clone objects but not the node object
|
|
784
|
+
const mapping = state.motion.clips?.find(e => e.node.name === this.animator?.gameObject?.name);
|
|
785
|
+
if (!mapping) {
|
|
786
|
+
if (debug || isDevEnvironment()) {
|
|
787
|
+
console.warn("Could not find clip for animator \"" + this.animator?.gameObject?.name + "\"", state.motion.clips.map(c => c.node.name));
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
else
|
|
791
|
+
state.motion.clip = mapping.clip;
|
|
792
|
+
}
|
|
793
|
+
// ensure we have a clip to blend to
|
|
794
|
+
if (!state.motion.clip) {
|
|
795
|
+
if (debug)
|
|
796
|
+
console.warn("No clip assigned to state", state);
|
|
797
|
+
const clip = new AnimationClip(undefined, undefined, []);
|
|
798
|
+
state.motion.clip = clip;
|
|
799
|
+
}
|
|
800
|
+
if (state.motion?.clip) {
|
|
801
|
+
const clip = state.motion.clip;
|
|
802
|
+
if (clip instanceof AnimationClip) {
|
|
803
|
+
const action = this.createAction(clip);
|
|
804
|
+
state.motion.action = action;
|
|
805
|
+
}
|
|
806
|
+
else {
|
|
807
|
+
if (debug || isDevEnvironment())
|
|
808
|
+
console.warn("No valid animationclip assigned", state);
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
// create state machine behaviours
|
|
812
|
+
if (state.behaviours && Array.isArray(state.behaviours)) {
|
|
813
|
+
for (const behaviour of state.behaviours) {
|
|
814
|
+
if (!behaviour?.typeName)
|
|
815
|
+
continue;
|
|
816
|
+
const type = TypeStore.get(behaviour.typeName);
|
|
817
|
+
if (type) {
|
|
818
|
+
const instance = new type();
|
|
819
|
+
if (instance.isStateMachineBehaviour) {
|
|
820
|
+
instance._context = this.context ?? undefined;
|
|
821
|
+
assign(instance, behaviour.properties);
|
|
822
|
+
behaviour.instance = instance;
|
|
823
|
+
}
|
|
824
|
+
if (debug)
|
|
825
|
+
console.log("Created animator controller behaviour", state.name, behaviour.typeName, behaviour.properties, instance);
|
|
826
|
+
}
|
|
827
|
+
else {
|
|
828
|
+
if (debug || isDevEnvironment())
|
|
829
|
+
console.warn("Could not find AnimatorBehaviour type: " + behaviour.typeName);
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
/**
|
|
837
|
+
* Yields all animation actions managed by this controller.
|
|
838
|
+
* Iterates through all states in all layers and returns their actions.
|
|
839
|
+
*/
|
|
840
|
+
*enumerateActions() {
|
|
841
|
+
if (!this.model.layers)
|
|
842
|
+
return;
|
|
843
|
+
for (const layer of this.model.layers) {
|
|
844
|
+
const sm = layer.stateMachine;
|
|
845
|
+
for (let index = 0; index < sm.states.length; index++) {
|
|
846
|
+
const state = sm.states[index];
|
|
847
|
+
if (state?.motion) {
|
|
848
|
+
if (state.motion.action)
|
|
849
|
+
yield state.motion.action;
|
|
850
|
+
if (state.motion.action_loopback)
|
|
851
|
+
yield state.motion.action_loopback;
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
// https://docs.unity3d.com/Manual/RootMotion.html
|
|
857
|
+
rootMotionHandler;
|
|
858
|
+
}
|
|
859
|
+
/**
|
|
860
|
+
* Wraps a KeyframeTrack to allow custom evaluation of animation values.
|
|
861
|
+
* Used internally to modify animation behavior without changing the original data.
|
|
862
|
+
*/
|
|
863
|
+
class TrackEvaluationWrapper {
|
|
864
|
+
track;
|
|
865
|
+
createdInterpolant;
|
|
866
|
+
originalEvaluate;
|
|
867
|
+
customEvaluate;
|
|
868
|
+
constructor(track, evaluate) {
|
|
869
|
+
this.track = track;
|
|
870
|
+
const t = track;
|
|
871
|
+
const createOriginalInterpolator = t.createInterpolant.bind(track);
|
|
872
|
+
t.createInterpolant = () => {
|
|
873
|
+
t.createInterpolant = createOriginalInterpolator;
|
|
874
|
+
this.createdInterpolant = createOriginalInterpolator();
|
|
875
|
+
this.originalEvaluate = this.createdInterpolant.evaluate.bind(this.createdInterpolant);
|
|
876
|
+
this.customEvaluate = time => {
|
|
877
|
+
if (!this.originalEvaluate)
|
|
878
|
+
return;
|
|
879
|
+
const res = this.originalEvaluate(time);
|
|
880
|
+
return evaluate(time, res);
|
|
881
|
+
};
|
|
882
|
+
this.createdInterpolant.evaluate = this.customEvaluate;
|
|
883
|
+
return this.createdInterpolant;
|
|
884
|
+
};
|
|
885
|
+
}
|
|
886
|
+
;
|
|
887
|
+
dispose() {
|
|
888
|
+
if (this.createdInterpolant && this.originalEvaluate) {
|
|
889
|
+
this.createdInterpolant.evaluate = this.originalEvaluate;
|
|
890
|
+
}
|
|
891
|
+
this.track = undefined;
|
|
892
|
+
this.createdInterpolant = null;
|
|
893
|
+
this.originalEvaluate = undefined;
|
|
894
|
+
this.customEvaluate = undefined;
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
/**
|
|
898
|
+
* Handles root motion extraction from animation tracks.
|
|
899
|
+
* Captures movement from animations and applies it to the root object.
|
|
900
|
+
*/
|
|
901
|
+
class RootMotionAction {
|
|
902
|
+
static lastObjPosition = {};
|
|
903
|
+
static lastObjRotation = {};
|
|
904
|
+
// we remove the first keyframe rotation from the space rotation when updating
|
|
905
|
+
static firstKeyframeRotation = {};
|
|
906
|
+
// this is used to rotate the space on clip end / start (so the transform direction is correct)
|
|
907
|
+
static spaceRotation = {};
|
|
908
|
+
static effectiveSpaceRotation = {};
|
|
909
|
+
static clipOffsetRotation = {};
|
|
910
|
+
set action(val) {
|
|
911
|
+
this._action = val;
|
|
912
|
+
}
|
|
913
|
+
get action() {
|
|
914
|
+
return this._action;
|
|
915
|
+
}
|
|
916
|
+
get cacheId() {
|
|
917
|
+
return this.root.uuid;
|
|
918
|
+
}
|
|
919
|
+
_action;
|
|
920
|
+
root;
|
|
921
|
+
clip;
|
|
922
|
+
positionWrapper = null;
|
|
923
|
+
rotationWrapper = null;
|
|
924
|
+
context;
|
|
925
|
+
positionChange = new Vector3();
|
|
926
|
+
rotationChange = new Quaternion();
|
|
927
|
+
constructor(context, root, clip, positionTrack, rotationTrack) {
|
|
928
|
+
// console.log(this, positionTrack, rotationTrack);
|
|
929
|
+
this.context = context;
|
|
930
|
+
this.root = root;
|
|
931
|
+
this.clip = clip;
|
|
932
|
+
if (!RootMotionAction.firstKeyframeRotation[this.cacheId])
|
|
933
|
+
RootMotionAction.firstKeyframeRotation[this.cacheId] = new Quaternion();
|
|
934
|
+
if (rotationTrack) {
|
|
935
|
+
const values = rotationTrack.values;
|
|
936
|
+
RootMotionAction.firstKeyframeRotation[this.cacheId]
|
|
937
|
+
.set(values[0], values[1], values[2], values[3]);
|
|
938
|
+
}
|
|
939
|
+
if (!RootMotionAction.spaceRotation[this.cacheId])
|
|
940
|
+
RootMotionAction.spaceRotation[this.cacheId] = new Quaternion();
|
|
941
|
+
if (!RootMotionAction.effectiveSpaceRotation[this.cacheId])
|
|
942
|
+
RootMotionAction.effectiveSpaceRotation[this.cacheId] = new Quaternion();
|
|
943
|
+
RootMotionAction.clipOffsetRotation[this.cacheId] = new Quaternion();
|
|
944
|
+
if (rotationTrack) {
|
|
945
|
+
RootMotionAction.clipOffsetRotation[this.cacheId]
|
|
946
|
+
.set(rotationTrack.values[0], rotationTrack.values[1], rotationTrack.values[2], rotationTrack.values[3])
|
|
947
|
+
.invert();
|
|
948
|
+
}
|
|
949
|
+
this.handlePosition(clip, positionTrack);
|
|
950
|
+
this.handleRotation(clip, rotationTrack);
|
|
951
|
+
}
|
|
952
|
+
onStart(action) {
|
|
953
|
+
if (action.getClip() !== this.clip)
|
|
954
|
+
return;
|
|
955
|
+
if (!RootMotionAction.lastObjRotation[this.cacheId]) {
|
|
956
|
+
RootMotionAction.lastObjRotation[this.cacheId] = this.root.quaternion.clone();
|
|
957
|
+
}
|
|
958
|
+
const lastRotation = RootMotionAction.lastObjRotation[this.cacheId];
|
|
959
|
+
// const firstKeyframe = RootMotionAction.firstKeyframeRotation[this.this.cacheId];
|
|
960
|
+
// lastRotation.invert().premultiply(firstKeyframe).invert();
|
|
961
|
+
RootMotionAction.spaceRotation[this.cacheId].copy(lastRotation);
|
|
962
|
+
if (debugRootMotion) {
|
|
963
|
+
const euler = new Euler().setFromQuaternion(lastRotation);
|
|
964
|
+
console.log("START", this.clip.name, Mathf.toDegrees(euler.y), this.root.position.z);
|
|
965
|
+
}
|
|
966
|
+
}
|
|
967
|
+
getClipRotationOffset() {
|
|
968
|
+
return RootMotionAction.clipOffsetRotation[this.cacheId];
|
|
969
|
+
}
|
|
970
|
+
_prevTime = 0;
|
|
971
|
+
handlePosition(_clip, track) {
|
|
972
|
+
if (track) {
|
|
973
|
+
const root = this.root;
|
|
974
|
+
if (debugRootMotion)
|
|
975
|
+
root.add(new AxesHelper());
|
|
976
|
+
if (!RootMotionAction.lastObjPosition[this.cacheId])
|
|
977
|
+
RootMotionAction.lastObjPosition[this.cacheId] = this.root.position.clone();
|
|
978
|
+
const valuesDiff = new Vector3();
|
|
979
|
+
const valuesPrev = new Vector3();
|
|
980
|
+
// const rotation = new Quaternion();
|
|
981
|
+
this.positionWrapper = new TrackEvaluationWrapper(track, (time, value) => {
|
|
982
|
+
const weight = this.action.getEffectiveWeight();
|
|
983
|
+
// reset for testing
|
|
984
|
+
if (debugRootMotion) {
|
|
985
|
+
if (root.position.length() > 8)
|
|
986
|
+
root.position.set(0, root.position.y, 0);
|
|
987
|
+
}
|
|
988
|
+
if (time > this._prevTime) {
|
|
989
|
+
valuesDiff.set(value[0], value[1], value[2]);
|
|
990
|
+
valuesDiff.sub(valuesPrev);
|
|
991
|
+
valuesDiff.multiplyScalar(weight);
|
|
992
|
+
valuesDiff.applyQuaternion(this.getClipRotationOffset());
|
|
993
|
+
// RootMotionAction.effectiveSpaceRotation[id].slerp(RootMotionAction.spaceRotation[id], weight);
|
|
994
|
+
valuesDiff.applyQuaternion(root.quaternion);
|
|
995
|
+
this.positionChange.copy(valuesDiff);
|
|
996
|
+
// this.root.position.add(valuesDiff);
|
|
997
|
+
}
|
|
998
|
+
valuesPrev.fromArray(value);
|
|
999
|
+
this._prevTime = time;
|
|
1000
|
+
value[0] = 0;
|
|
1001
|
+
value[1] = 0;
|
|
1002
|
+
value[2] = 0;
|
|
1003
|
+
return value;
|
|
1004
|
+
});
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
1007
|
+
static identityQuaternion = new Quaternion();
|
|
1008
|
+
handleRotation(clip, track) {
|
|
1009
|
+
if (track) {
|
|
1010
|
+
if (debugRootMotion) {
|
|
1011
|
+
const arr = track.values;
|
|
1012
|
+
const firstKeyframe = new Euler().setFromQuaternion(new Quaternion(arr[0], arr[1], arr[2], arr[3]));
|
|
1013
|
+
console.log(clip.name, track.name, "FIRST ROTATION IN TRACK", Mathf.toDegrees(firstKeyframe.y));
|
|
1014
|
+
const i = track.values.length - 4;
|
|
1015
|
+
const lastKeyframe = new Quaternion().set(arr[i], arr[i + 1], arr[i + 2], arr[i + 3]);
|
|
1016
|
+
const euler = new Euler().setFromQuaternion(lastKeyframe);
|
|
1017
|
+
console.log(clip.name, track.name, "LAST ROTATION IN TRACK", Mathf.toDegrees(euler.y));
|
|
1018
|
+
}
|
|
1019
|
+
// if (!RootMotionAction.lastObjRotation[root.uuid]) RootMotionAction.lastObjRotation[root.uuid] = new Quaternion();
|
|
1020
|
+
// const temp = new Quaternion();
|
|
1021
|
+
let prevTime = 0;
|
|
1022
|
+
const valuesPrev = new Quaternion();
|
|
1023
|
+
const valuesDiff = new Quaternion();
|
|
1024
|
+
// const summedRot = new Quaternion();
|
|
1025
|
+
this.rotationWrapper = new TrackEvaluationWrapper(track, (time, value) => {
|
|
1026
|
+
// root.quaternion.copy(RootMotionAction.lastObjRotation[root.uuid]);
|
|
1027
|
+
if (time > prevTime) {
|
|
1028
|
+
valuesDiff.set(value[0], value[1], value[2], value[3]);
|
|
1029
|
+
valuesPrev.invert();
|
|
1030
|
+
valuesDiff.multiply(valuesPrev);
|
|
1031
|
+
// if(weight < .99) valuesDiff.slerp(RootMotionAction.identityQuaternion, 1 - weight);
|
|
1032
|
+
this.rotationChange.copy(valuesDiff);
|
|
1033
|
+
// root.quaternion.multiply(valuesDiff);
|
|
1034
|
+
}
|
|
1035
|
+
// else
|
|
1036
|
+
// root.quaternion.multiply(this.getClipRotationOffset());
|
|
1037
|
+
// RootMotionAction.lastObjRotation[root.uuid].copy(root.quaternion);
|
|
1038
|
+
valuesPrev.fromArray(value);
|
|
1039
|
+
prevTime = time;
|
|
1040
|
+
value[0] = 0;
|
|
1041
|
+
value[1] = 0;
|
|
1042
|
+
value[2] = 0;
|
|
1043
|
+
value[3] = 1;
|
|
1044
|
+
return value;
|
|
1045
|
+
});
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
// private lastPos: Vector3 = new Vector3();
|
|
1049
|
+
onBeforeUpdate(_weight) {
|
|
1050
|
+
this.positionChange.set(0, 0, 0);
|
|
1051
|
+
this.rotationChange.set(0, 0, 0, 1);
|
|
1052
|
+
}
|
|
1053
|
+
onAfterUpdate(weight) {
|
|
1054
|
+
if (!this.action)
|
|
1055
|
+
return false;
|
|
1056
|
+
weight *= this.action.getEffectiveWeight();
|
|
1057
|
+
if (weight <= 0)
|
|
1058
|
+
return false;
|
|
1059
|
+
this.positionChange.multiplyScalar(weight);
|
|
1060
|
+
this.rotationChange.slerp(RootMotionAction.identityQuaternion, 1 - weight);
|
|
1061
|
+
return true;
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
1064
|
+
/**
|
|
1065
|
+
* Manages root motion for a character.
|
|
1066
|
+
* Extracts motion from animation tracks and applies it to the character's transform.
|
|
1067
|
+
*/
|
|
1068
|
+
class RootMotionHandler {
|
|
1069
|
+
controller;
|
|
1070
|
+
handler = [];
|
|
1071
|
+
root;
|
|
1072
|
+
basePosition = new Vector3();
|
|
1073
|
+
baseQuaternion = new Quaternion();
|
|
1074
|
+
baseRotation = new Euler();
|
|
1075
|
+
constructor(controller) {
|
|
1076
|
+
this.controller = controller;
|
|
1077
|
+
}
|
|
1078
|
+
createClip(mixer, root, clip) {
|
|
1079
|
+
this.root = root;
|
|
1080
|
+
let rootName = "";
|
|
1081
|
+
if (root && "name" in root) {
|
|
1082
|
+
rootName = root.name;
|
|
1083
|
+
}
|
|
1084
|
+
const positionTrack = this.findRootTrack(clip, ".position");
|
|
1085
|
+
const rotationTrack = this.findRootTrack(clip, ".quaternion");
|
|
1086
|
+
const handler = new RootMotionAction(this.controller.context, root, clip, positionTrack, rotationTrack);
|
|
1087
|
+
this.handler.push(handler);
|
|
1088
|
+
// it is important we do this after the handler is created
|
|
1089
|
+
// otherwise we can not hook into threejs interpolators
|
|
1090
|
+
const action = mixer.clipAction(clip);
|
|
1091
|
+
handler.action = action;
|
|
1092
|
+
return action;
|
|
1093
|
+
}
|
|
1094
|
+
onStart(action) {
|
|
1095
|
+
for (const handler of this.handler) {
|
|
1096
|
+
handler.onStart(action);
|
|
1097
|
+
}
|
|
1098
|
+
}
|
|
1099
|
+
onBeforeUpdate(weight) {
|
|
1100
|
+
// capture the position of the object
|
|
1101
|
+
this.basePosition.copy(this.root.position);
|
|
1102
|
+
this.baseQuaternion.copy(this.root.quaternion);
|
|
1103
|
+
for (const hand of this.handler)
|
|
1104
|
+
hand.onBeforeUpdate(weight);
|
|
1105
|
+
}
|
|
1106
|
+
summedPosition = new Vector3();
|
|
1107
|
+
summedRotation = new Quaternion();
|
|
1108
|
+
onAfterUpdate(weight) {
|
|
1109
|
+
if (weight <= 0)
|
|
1110
|
+
return;
|
|
1111
|
+
// TODO: blend weight properly with root motion (when using timeline blending with animator)
|
|
1112
|
+
// apply the accumulated changes
|
|
1113
|
+
this.root.position.copy(this.basePosition);
|
|
1114
|
+
this.root.quaternion.copy(this.baseQuaternion);
|
|
1115
|
+
this.summedPosition.set(0, 0, 0);
|
|
1116
|
+
this.summedRotation.set(0, 0, 0, 1);
|
|
1117
|
+
for (const entry of this.handler) {
|
|
1118
|
+
if (entry.onAfterUpdate(weight)) {
|
|
1119
|
+
this.summedPosition.add(entry.positionChange);
|
|
1120
|
+
this.summedRotation.multiply(entry.rotationChange);
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
1123
|
+
this.root.position.add(this.summedPosition);
|
|
1124
|
+
this.root.quaternion.multiply(this.summedRotation);
|
|
1125
|
+
// RootMotionAction.lastObjRotation[this.root.uuid].copy(this.root.quaternion);
|
|
1126
|
+
}
|
|
1127
|
+
findRootTrack(clip, name) {
|
|
1128
|
+
const tracks = clip.tracks;
|
|
1129
|
+
if (!tracks)
|
|
1130
|
+
return null;
|
|
1131
|
+
for (const track of tracks) {
|
|
1132
|
+
if (track.name.endsWith(name)) {
|
|
1133
|
+
return track;
|
|
1134
|
+
}
|
|
1135
|
+
}
|
|
1136
|
+
return null;
|
|
1137
|
+
}
|
|
1138
|
+
}
|
|
1139
|
+
/**
|
|
1140
|
+
* Serialization handler for AnimatorController instances.
|
|
1141
|
+
* Handles conversion between serialized data and runtime objects.
|
|
1142
|
+
*/
|
|
1143
|
+
class AnimatorControllerSerializator extends TypeSerializer {
|
|
1144
|
+
onSerialize(_, _context) {
|
|
1145
|
+
}
|
|
1146
|
+
onDeserialize(data, context) {
|
|
1147
|
+
if (context.type === AnimatorController && data?.__type === "AnimatorController")
|
|
1148
|
+
return new AnimatorController(data);
|
|
1149
|
+
return undefined;
|
|
1150
|
+
}
|
|
1151
|
+
}
|
|
1152
|
+
new AnimatorControllerSerializator(AnimatorController);
|
|
1153
1153
|
//# sourceMappingURL=AnimatorController.js.map
|