@needle-tools/engine 3.28.6-beta → 3.28.7-beta.1
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 +2259 -2253
- package/LICENSE.md +10 -10
- package/README.md +52 -52
- package/dist/needle-engine.js +7 -10
- package/dist/needle-engine.light.js +7 -10
- package/dist/needle-engine.light.min.js +7 -10
- package/dist/needle-engine.light.umd.cjs +7 -10
- package/dist/needle-engine.min.js +7 -10
- package/dist/needle-engine.umd.cjs +7 -10
- package/lib/engine/api.d.ts +52 -52
- package/lib/engine/api.js +51 -51
- package/lib/engine/assets/index.d.ts +1 -1
- package/lib/engine/assets/index.js +4 -4
- package/lib/engine/codegen/register_types.d.ts +1 -1
- package/lib/engine/codegen/register_types.js +439 -439
- package/lib/engine/debug/debug.d.ts +12 -12
- package/lib/engine/debug/debug.js +26 -26
- package/lib/engine/debug/debug_console.d.ts +2 -2
- package/lib/engine/debug/debug_console.js +204 -204
- package/lib/engine/debug/debug_overlay.d.ts +10 -10
- package/lib/engine/debug/debug_overlay.js +277 -277
- package/lib/engine/debug/index.d.ts +1 -1
- package/lib/engine/debug/index.js +1 -1
- package/lib/engine/engine_addressables.d.ts +75 -75
- package/lib/engine/engine_addressables.js +441 -441
- package/lib/engine/engine_application.d.ts +19 -19
- package/lib/engine/engine_application.js +45 -45
- package/lib/engine/engine_assetdatabase.d.ts +25 -25
- package/lib/engine/engine_assetdatabase.js +341 -341
- package/lib/engine/engine_camera.d.ts +6 -6
- package/lib/engine/engine_camera.js +23 -23
- package/lib/engine/engine_components.d.ts +17 -17
- package/lib/engine/engine_components.js +273 -273
- package/lib/engine/engine_components_internal.d.ts +11 -11
- package/lib/engine/engine_components_internal.js +41 -41
- package/lib/engine/engine_constants.d.ts +5 -5
- package/lib/engine/engine_constants.js +32 -32
- package/lib/engine/engine_context.d.ts +269 -269
- package/lib/engine/engine_context.js +1242 -1242
- package/lib/engine/engine_context_registry.d.ts +50 -50
- package/lib/engine/engine_context_registry.js +89 -89
- package/lib/engine/engine_coroutine.d.ts +4 -4
- package/lib/engine/engine_coroutine.js +21 -21
- package/lib/engine/engine_create_objects.d.ts +13 -13
- package/lib/engine/engine_create_objects.js +33 -33
- 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 +17 -17
- package/lib/engine/engine_editor-sync.js +7 -7
- package/lib/engine/engine_element.d.ts +55 -55
- package/lib/engine/engine_element.js +559 -559
- package/lib/engine/engine_element_attributes.d.ts +49 -49
- package/lib/engine/engine_element_attributes.js +1 -1
- package/lib/engine/engine_element_extras.d.ts +6 -6
- package/lib/engine/engine_element_extras.js +13 -13
- package/lib/engine/engine_element_loading.d.ts +40 -40
- package/lib/engine/engine_element_loading.js +312 -312
- package/lib/engine/engine_element_overlay.d.ts +19 -19
- package/lib/engine/engine_element_overlay.js +143 -143
- package/lib/engine/engine_fileloader.d.ts +3 -3
- package/lib/engine/engine_fileloader.js +7 -7
- package/lib/engine/engine_gameobject.d.ts +39 -39
- package/lib/engine/engine_gameobject.js +559 -559
- 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 +26 -26
- package/lib/engine/engine_gizmos.js +282 -282
- package/lib/engine/engine_gltf.d.ts +13 -13
- package/lib/engine/engine_gltf.js +15 -15
- package/lib/engine/engine_gltf_builtin_components.d.ts +7 -7
- package/lib/engine/engine_gltf_builtin_components.js +298 -298
- package/lib/engine/engine_hot_reload.d.ts +5 -5
- package/lib/engine/engine_hot_reload.js +182 -182
- package/lib/engine/engine_input.d.ts +129 -129
- package/lib/engine/engine_input.js +799 -799
- 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 +16 -16
- package/lib/engine/engine_instancing.js +36 -36
- package/lib/engine/engine_license.d.ts +4 -4
- package/lib/engine/engine_license.js +398 -398
- package/lib/engine/engine_lifecycle_api.d.ts +14 -14
- package/lib/engine/engine_lifecycle_api.js +24 -24
- package/lib/engine/engine_lifecycle_functions_internal.d.ts +6 -6
- package/lib/engine/engine_lifecycle_functions_internal.js +28 -28
- package/lib/engine/engine_lightdata.d.ts +23 -23
- package/lib/engine/engine_lightdata.js +86 -86
- package/lib/engine/engine_loaders.d.ts +7 -7
- package/lib/engine/engine_loaders.js +69 -69
- package/lib/engine/engine_mainloop_utils.d.ts +13 -13
- package/lib/engine/engine_mainloop_utils.js +426 -426
- package/lib/engine/engine_math.d.ts +43 -43
- package/lib/engine/engine_math.js +147 -147
- package/lib/engine/engine_networking.d.ts +176 -176
- package/lib/engine/engine_networking.js +649 -649
- package/lib/engine/engine_networking_auto.d.ts +24 -24
- package/lib/engine/engine_networking_auto.js +324 -324
- package/lib/engine/engine_networking_files.d.ts +23 -23
- package/lib/engine/engine_networking_files.js +176 -176
- package/lib/engine/engine_networking_files_default_components.d.ts +3 -3
- package/lib/engine/engine_networking_files_default_components.js +39 -39
- package/lib/engine/engine_networking_instantiate.d.ts +39 -39
- package/lib/engine/engine_networking_instantiate.js +302 -302
- 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 +90 -90
- package/lib/engine/engine_networking_streams.js +428 -428
- package/lib/engine/engine_networking_types.d.ts +14 -14
- 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_patcher.d.ts +10 -10
- package/lib/engine/engine_patcher.js +142 -142
- package/lib/engine/engine_physics.d.ts +115 -115
- package/lib/engine/engine_physics.js +228 -228
- package/lib/engine/engine_physics.types.d.ts +37 -37
- package/lib/engine/engine_physics.types.js +33 -33
- package/lib/engine/engine_physics_rapier.d.ts +112 -112
- package/lib/engine/engine_physics_rapier.js +1266 -1266
- package/lib/engine/engine_playerview.d.ts +26 -26
- package/lib/engine/engine_playerview.js +64 -64
- package/lib/engine/engine_scenelighting.d.ts +74 -74
- package/lib/engine/engine_scenelighting.js +285 -285
- package/lib/engine/engine_scenetools.d.ts +35 -35
- package/lib/engine/engine_scenetools.js +212 -212
- package/lib/engine/engine_serialization.d.ts +4 -4
- package/lib/engine/engine_serialization.js +4 -4
- package/lib/engine/engine_serialization_builtin_serializer.d.ts +62 -62
- package/lib/engine/engine_serialization_builtin_serializer.js +369 -369
- package/lib/engine/engine_serialization_core.d.ts +84 -84
- package/lib/engine/engine_serialization_core.js +576 -576
- package/lib/engine/engine_serialization_decorator.d.ts +15 -15
- package/lib/engine/engine_serialization_decorator.js +54 -54
- package/lib/engine/engine_setup.d.ts +1 -1
- package/lib/engine/engine_setup.js +2 -2
- package/lib/engine/engine_shaders.d.ts +31 -31
- package/lib/engine/engine_shaders.js +229 -229
- package/lib/engine/engine_shims.d.ts +3 -3
- package/lib/engine/engine_shims.js +22 -22
- package/lib/engine/engine_texture.d.ts +20 -20
- package/lib/engine/engine_texture.js +57 -57
- package/lib/engine/engine_three_utils.d.ts +51 -51
- package/lib/engine/engine_three_utils.js +342 -342
- package/lib/engine/engine_time.d.ts +19 -19
- package/lib/engine/engine_time.js +47 -47
- package/lib/engine/engine_types.d.ts +358 -358
- package/lib/engine/engine_types.js +72 -72
- package/lib/engine/engine_typestore.d.ts +16 -16
- package/lib/engine/engine_typestore.js +35 -35
- package/lib/engine/engine_util_decorator.d.ts +12 -12
- package/lib/engine/engine_util_decorator.js +115 -115
- package/lib/engine/engine_utils.d.ts +104 -104
- package/lib/engine/engine_utils.js +518 -518
- package/lib/engine/engine_utils_screenshot.d.ts +10 -10
- package/lib/engine/engine_utils_screenshot.js +70 -70
- package/lib/engine/engine_web_api.d.ts +12 -12
- package/lib/engine/engine_web_api.js +112 -112
- 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 +116 -116
- package/lib/engine/extensions/NEEDLE_animator_controller_model.js +91 -91
- package/lib/engine/extensions/NEEDLE_components.d.ts +33 -33
- package/lib/engine/extensions/NEEDLE_components.js +206 -206
- 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 +38 -38
- package/lib/engine/extensions/NEEDLE_lighting_settings.js +183 -183
- package/lib/engine/extensions/NEEDLE_lightmaps.d.ts +18 -18
- package/lib/engine/extensions/NEEDLE_lightmaps.js +108 -108
- 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 +41 -41
- package/lib/engine/extensions/NEEDLE_progressive.js +366 -366
- 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 +39 -39
- package/lib/engine/extensions/NEEDLE_techniques_webgl.js +544 -544
- 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 +2 -2
- package/lib/engine/extensions/extension_utils.js +140 -140
- package/lib/engine/extensions/extensions.d.ts +21 -21
- package/lib/engine/extensions/extensions.js +94 -94
- package/lib/engine/extensions/index.d.ts +5 -5
- package/lib/engine/extensions/index.js +5 -5
- package/lib/engine/extensions/usage_tracker.d.ts +13 -13
- package/lib/engine/extensions/usage_tracker.js +61 -61
- package/lib/engine/js-extensions/Camera.d.ts +1 -1
- package/lib/engine/js-extensions/Camera.js +36 -36
- package/lib/engine/js-extensions/Layers.d.ts +3 -3
- package/lib/engine/js-extensions/Layers.js +19 -19
- package/lib/engine/js-extensions/index.d.ts +2 -2
- package/lib/engine/js-extensions/index.js +2 -2
- 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-components/AlignmentConstraint.d.ts +10 -10
- package/lib/engine-components/AlignmentConstraint.js +39 -39
- package/lib/engine-components/Animation.d.ts +53 -53
- package/lib/engine-components/Animation.js +333 -333
- package/lib/engine-components/AnimationCurve.d.ts +16 -16
- package/lib/engine-components/AnimationCurve.js +97 -97
- package/lib/engine-components/AnimationUtils.d.ts +8 -8
- package/lib/engine-components/AnimationUtils.js +110 -110
- package/lib/engine-components/Animator.d.ts +81 -81
- package/lib/engine-components/Animator.js +229 -229
- package/lib/engine-components/AnimatorController.d.ts +57 -57
- package/lib/engine-components/AnimatorController.js +887 -887
- package/lib/engine-components/AudioListener.d.ts +7 -7
- package/lib/engine-components/AudioListener.js +30 -30
- package/lib/engine-components/AudioSource.d.ts +61 -61
- package/lib/engine-components/AudioSource.js +422 -422
- package/lib/engine-components/AvatarLoader.d.ts +19 -19
- package/lib/engine-components/AvatarLoader.js +173 -173
- package/lib/engine-components/AxesHelper.d.ts +9 -9
- package/lib/engine-components/AxesHelper.js +44 -44
- package/lib/engine-components/BasicIKConstraint.d.ts +9 -9
- package/lib/engine-components/BasicIKConstraint.js +43 -43
- package/lib/engine-components/BoxHelperComponent.d.ts +16 -16
- package/lib/engine-components/BoxHelperComponent.js +89 -89
- package/lib/engine-components/Camera.d.ts +70 -70
- package/lib/engine-components/Camera.js +450 -450
- package/lib/engine-components/CameraUtils.d.ts +1 -1
- package/lib/engine-components/CameraUtils.js +77 -77
- package/lib/engine-components/CharacterController.d.ts +46 -46
- package/lib/engine-components/CharacterController.js +227 -227
- package/lib/engine-components/Collider.d.ts +46 -46
- package/lib/engine-components/Collider.js +153 -153
- package/lib/engine-components/Component.d.ts +228 -228
- package/lib/engine-components/Component.js +541 -541
- package/lib/engine-components/ContactShadows.d.ts +23 -23
- package/lib/engine-components/ContactShadows.js +233 -233
- package/lib/engine-components/DeleteBox.d.ts +9 -9
- package/lib/engine-components/DeleteBox.js +30 -30
- package/lib/engine-components/DeviceFlag.d.ts +12 -12
- package/lib/engine-components/DeviceFlag.js +43 -43
- package/lib/engine-components/DragControls.d.ts +51 -51
- package/lib/engine-components/DragControls.js +516 -516
- package/lib/engine-components/DropListener.d.ts +15 -15
- package/lib/engine-components/DropListener.js +120 -120
- package/lib/engine-components/Duplicatable.d.ts +16 -16
- package/lib/engine-components/Duplicatable.js +150 -150
- package/lib/engine-components/EventList.d.ts +28 -28
- package/lib/engine-components/EventList.js +105 -105
- package/lib/engine-components/EventTrigger.d.ts +12 -12
- package/lib/engine-components/EventTrigger.js +50 -50
- package/lib/engine-components/EventType.d.ts +19 -19
- package/lib/engine-components/EventType.js +71 -71
- package/lib/engine-components/FlyControls.d.ts +7 -7
- package/lib/engine-components/FlyControls.js +25 -25
- package/lib/engine-components/Fog.d.ts +20 -20
- package/lib/engine-components/Fog.js +60 -60
- package/lib/engine-components/Gizmos.d.ts +12 -12
- package/lib/engine-components/Gizmos.js +60 -60
- package/lib/engine-components/GridHelper.d.ts +12 -12
- package/lib/engine-components/GridHelper.js +47 -47
- package/lib/engine-components/GroundProjection.d.ts +21 -21
- package/lib/engine-components/GroundProjection.js +97 -97
- package/lib/engine-components/Interactable.d.ts +10 -10
- package/lib/engine-components/Interactable.js +11 -11
- package/lib/engine-components/Joints.d.ts +19 -19
- package/lib/engine-components/Joints.js +51 -51
- package/lib/engine-components/LODGroup.d.ts +30 -30
- package/lib/engine-components/LODGroup.js +145 -145
- package/lib/engine-components/Light.d.ts +75 -75
- package/lib/engine-components/Light.js +475 -475
- package/lib/engine-components/LookAtConstraint.d.ts +7 -7
- package/lib/engine-components/LookAtConstraint.js +17 -17
- package/lib/engine-components/NestedGltf.d.ts +11 -11
- package/lib/engine-components/NestedGltf.js +74 -74
- package/lib/engine-components/Networking.d.ts +11 -11
- package/lib/engine-components/Networking.js +70 -70
- package/lib/engine-components/OffsetConstraint.d.ts +14 -14
- package/lib/engine-components/OffsetConstraint.js +65 -65
- package/lib/engine-components/OrbitControls.d.ts +111 -111
- package/lib/engine-components/OrbitControls.js +646 -646
- package/lib/engine-components/ParticleSystem.d.ts +145 -145
- package/lib/engine-components/ParticleSystem.js +1077 -1077
- package/lib/engine-components/ParticleSystemModules.d.ts +489 -489
- package/lib/engine-components/ParticleSystemModules.js +1667 -1667
- package/lib/engine-components/ParticleSystemSubEmitter.d.ts +25 -25
- package/lib/engine-components/ParticleSystemSubEmitter.js +86 -86
- package/lib/engine-components/PlayerColor.d.ts +13 -13
- package/lib/engine-components/PlayerColor.js +83 -83
- package/lib/engine-components/ReflectionProbe.d.ts +22 -22
- package/lib/engine-components/ReflectionProbe.js +181 -181
- package/lib/engine-components/Renderer.d.ts +112 -112
- package/lib/engine-components/Renderer.js +1029 -1029
- package/lib/engine-components/RendererLightmap.d.ts +19 -19
- package/lib/engine-components/RendererLightmap.js +127 -127
- package/lib/engine-components/RigidBody.d.ts +120 -120
- package/lib/engine-components/RigidBody.js +452 -452
- package/lib/engine-components/SceneSwitcher.d.ts +72 -72
- package/lib/engine-components/SceneSwitcher.js +583 -583
- package/lib/engine-components/ScreenCapture.d.ts +64 -64
- package/lib/engine-components/ScreenCapture.js +405 -405
- package/lib/engine-components/ShadowCatcher.d.ts +18 -18
- package/lib/engine-components/ShadowCatcher.js +144 -144
- package/lib/engine-components/Skybox.d.ts +23 -23
- package/lib/engine-components/Skybox.js +287 -287
- package/lib/engine-components/SmoothFollow.d.ts +14 -14
- package/lib/engine-components/SmoothFollow.js +63 -63
- package/lib/engine-components/SpatialTrigger.d.ts +27 -27
- package/lib/engine-components/SpatialTrigger.js +144 -144
- package/lib/engine-components/SpectatorCamera.d.ts +45 -45
- package/lib/engine-components/SpectatorCamera.js +593 -593
- package/lib/engine-components/SpriteRenderer.d.ts +48 -48
- package/lib/engine-components/SpriteRenderer.js +257 -257
- package/lib/engine-components/SyncedCamera.d.ts +27 -27
- package/lib/engine-components/SyncedCamera.js +187 -187
- package/lib/engine-components/SyncedRoom.d.ts +24 -24
- package/lib/engine-components/SyncedRoom.js +162 -162
- package/lib/engine-components/SyncedTransform.d.ts +35 -35
- package/lib/engine-components/SyncedTransform.js +265 -265
- package/lib/engine-components/TestRunner.d.ts +13 -13
- package/lib/engine-components/TestRunner.js +99 -99
- package/lib/engine-components/TransformGizmo.d.ts +16 -16
- package/lib/engine-components/TransformGizmo.js +148 -148
- package/lib/engine-components/VideoPlayer.d.ts +86 -86
- package/lib/engine-components/VideoPlayer.js +792 -792
- package/lib/engine-components/Voip.d.ts +29 -29
- package/lib/engine-components/Voip.js +203 -203
- package/lib/engine-components/XRFlag.d.ts +33 -33
- package/lib/engine-components/XRFlag.js +128 -128
- package/lib/engine-components/api.d.ts +15 -15
- package/lib/engine-components/api.js +15 -15
- package/lib/engine-components/avatar/AvatarBlink_Simple.d.ts +10 -10
- package/lib/engine-components/avatar/AvatarBlink_Simple.js +75 -75
- package/lib/engine-components/avatar/AvatarEyeLook_Rotation.d.ts +13 -13
- package/lib/engine-components/avatar/AvatarEyeLook_Rotation.js +74 -74
- package/lib/engine-components/avatar/Avatar_Brain_LookAt.d.ts +27 -27
- package/lib/engine-components/avatar/Avatar_Brain_LookAt.js +119 -119
- package/lib/engine-components/avatar/Avatar_MouthShapes.d.ts +13 -13
- package/lib/engine-components/avatar/Avatar_MouthShapes.js +78 -78
- package/lib/engine-components/avatar/Avatar_MustacheShake.d.ts +8 -8
- package/lib/engine-components/avatar/Avatar_MustacheShake.js +28 -28
- package/lib/engine-components/codegen/components.d.ts +216 -216
- package/lib/engine-components/codegen/components.js +217 -217
- 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 +25 -25
- package/lib/engine-components/export/gltf/GltfExport.js +215 -215
- 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 +10 -10
- package/lib/engine-components/export/usdz/Extension.js +1 -1
- package/lib/engine-components/export/usdz/ThreeUSDZExporter.d.ts +114 -114
- package/lib/engine-components/export/usdz/ThreeUSDZExporter.js +1211 -1211
- package/lib/engine-components/export/usdz/USDZExporter.d.ts +59 -59
- package/lib/engine-components/export/usdz/USDZExporter.js +450 -450
- package/lib/engine-components/export/usdz/extensions/Animation.d.ts +69 -69
- package/lib/engine-components/export/usdz/extensions/Animation.js +650 -650
- 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/USDZText.d.ts +55 -55
- package/lib/engine-components/export/usdz/extensions/USDZText.js +246 -246
- package/lib/engine-components/export/usdz/extensions/USDZUI.d.ts +8 -8
- package/lib/engine-components/export/usdz/extensions/USDZUI.js +100 -100
- 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 +9 -9
- package/lib/engine-components/export/usdz/extensions/behavior/AudioExtension.js +52 -52
- package/lib/engine-components/export/usdz/extensions/behavior/Behaviour.d.ts +22 -22
- package/lib/engine-components/export/usdz/extensions/behavior/Behaviour.js +134 -134
- package/lib/engine-components/export/usdz/extensions/behavior/BehaviourComponents.d.ts +126 -126
- package/lib/engine-components/export/usdz/extensions/behavior/BehaviourComponents.js +824 -824
- package/lib/engine-components/export/usdz/extensions/behavior/BehavioursBuilder.d.ts +133 -133
- package/lib/engine-components/export/usdz/extensions/behavior/BehavioursBuilder.js +464 -464
- 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 +3 -3
- package/lib/engine-components/export/usdz/utils/animationutils.js +85 -85
- package/lib/engine-components/export/usdz/utils/quicklook.d.ts +2 -2
- package/lib/engine-components/export/usdz/utils/quicklook.js +35 -35
- package/lib/engine-components/export/usdz/utils/timeutils.d.ts +1 -1
- package/lib/engine-components/export/usdz/utils/timeutils.js +14 -14
- package/lib/engine-components/js-extensions/ExtensionUtils.d.ts +6 -6
- package/lib/engine-components/js-extensions/ExtensionUtils.js +65 -65
- package/lib/engine-components/js-extensions/Object3D.d.ts +2 -2
- package/lib/engine-components/js-extensions/Object3D.js +140 -140
- package/lib/engine-components/js-extensions/RGBAColor.d.ts +14 -14
- package/lib/engine-components/js-extensions/RGBAColor.js +49 -49
- package/lib/engine-components/js-extensions/index.d.ts +3 -3
- package/lib/engine-components/js-extensions/index.js +3 -3
- package/lib/engine-components/postprocessing/Effects/Antialiasing.d.ts +13 -13
- package/lib/engine-components/postprocessing/Effects/Antialiasing.js +45 -45
- package/lib/engine-components/postprocessing/Effects/Bloom.d.ts +12 -12
- package/lib/engine-components/postprocessing/Effects/Bloom.js +77 -77
- package/lib/engine-components/postprocessing/Effects/ChromaticAberration.d.ts +8 -8
- package/lib/engine-components/postprocessing/Effects/ChromaticAberration.js +38 -38
- package/lib/engine-components/postprocessing/Effects/ColorAdjustments.d.ts +12 -12
- package/lib/engine-components/postprocessing/Effects/ColorAdjustments.js +81 -81
- package/lib/engine-components/postprocessing/Effects/DepthOfField.d.ts +21 -21
- package/lib/engine-components/postprocessing/Effects/DepthOfField.js +97 -97
- package/lib/engine-components/postprocessing/Effects/Pixelation.d.ts +7 -7
- package/lib/engine-components/postprocessing/Effects/Pixelation.js +28 -28
- package/lib/engine-components/postprocessing/Effects/ScreenspaceAmbientOcclusion.d.ts +13 -13
- package/lib/engine-components/postprocessing/Effects/ScreenspaceAmbientOcclusion.js +86 -86
- package/lib/engine-components/postprocessing/Effects/ScreenspaceAmbientOcclusionN8.d.ts +24 -24
- package/lib/engine-components/postprocessing/Effects/ScreenspaceAmbientOcclusionN8.js +94 -94
- package/lib/engine-components/postprocessing/Effects/TiltShiftEffect.d.ts +13 -13
- package/lib/engine-components/postprocessing/Effects/TiltShiftEffect.js +62 -62
- package/lib/engine-components/postprocessing/Effects/Tonemapping.d.ts +16 -16
- package/lib/engine-components/postprocessing/Effects/Tonemapping.js +51 -51
- package/lib/engine-components/postprocessing/Effects/Vignette.d.ts +11 -11
- package/lib/engine-components/postprocessing/Effects/Vignette.js +56 -56
- package/lib/engine-components/postprocessing/PostProcessingEffect.d.ts +33 -33
- package/lib/engine-components/postprocessing/PostProcessingEffect.js +126 -126
- package/lib/engine-components/postprocessing/PostProcessingHandler.d.ts +22 -22
- package/lib/engine-components/postprocessing/PostProcessingHandler.js +201 -201
- package/lib/engine-components/postprocessing/Volume.d.ts +25 -25
- package/lib/engine-components/postprocessing/Volume.js +193 -193
- package/lib/engine-components/postprocessing/VolumeParameter.d.ts +22 -22
- package/lib/engine-components/postprocessing/VolumeParameter.js +80 -80
- package/lib/engine-components/postprocessing/VolumeProfile.d.ts +7 -7
- package/lib/engine-components/postprocessing/VolumeProfile.js +41 -41
- package/lib/engine-components/postprocessing/index.d.ts +4 -4
- package/lib/engine-components/postprocessing/index.js +4 -4
- package/lib/engine-components/timeline/PlayableDirector.d.ts +107 -107
- package/lib/engine-components/timeline/PlayableDirector.js +624 -624
- package/lib/engine-components/timeline/SignalAsset.d.ts +18 -18
- package/lib/engine-components/timeline/SignalAsset.js +124 -124
- package/lib/engine-components/timeline/TimelineModels.d.ts +88 -88
- package/lib/engine-components/timeline/TimelineModels.js +22 -22
- package/lib/engine-components/timeline/TimelineTracks.d.ts +90 -90
- package/lib/engine-components/timeline/TimelineTracks.js +825 -825
- 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 +31 -31
- package/lib/engine-components/ui/BaseUIComponent.js +161 -161
- package/lib/engine-components/ui/Button.d.ts +56 -56
- package/lib/engine-components/ui/Button.js +282 -282
- package/lib/engine-components/ui/Canvas.d.ts +67 -67
- package/lib/engine-components/ui/Canvas.js +382 -382
- package/lib/engine-components/ui/CanvasGroup.d.ts +15 -15
- package/lib/engine-components/ui/CanvasGroup.js +53 -53
- package/lib/engine-components/ui/EventSystem.d.ts +102 -102
- package/lib/engine-components/ui/EventSystem.js +641 -641
- package/lib/engine-components/ui/Graphic.d.ts +45 -45
- package/lib/engine-components/ui/Graphic.js +236 -236
- package/lib/engine-components/ui/Image.d.ts +27 -27
- package/lib/engine-components/ui/Image.js +107 -107
- package/lib/engine-components/ui/InputField.d.ts +34 -34
- package/lib/engine-components/ui/InputField.js +234 -234
- 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 +72 -72
- package/lib/engine-components/ui/Layout.js +318 -318
- 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 +64 -64
- package/lib/engine-components/ui/PointerEvents.js +68 -68
- 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 +18 -18
- package/lib/engine-components/ui/Raycaster.js +69 -69
- package/lib/engine-components/ui/RectTransform.d.ts +61 -61
- package/lib/engine-components/ui/RectTransform.js +343 -343
- package/lib/engine-components/ui/SpatialHtml.d.ts +6 -6
- package/lib/engine-components/ui/SpatialHtml.js +57 -57
- package/lib/engine-components/ui/Text.d.ts +74 -74
- package/lib/engine-components/ui/Text.js +534 -534
- package/lib/engine-components/ui/Utils.d.ts +23 -23
- 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/LookAt.d.ts +13 -13
- package/lib/engine-components/utils/LookAt.js +59 -59
- package/lib/engine-components/utils/OpenURL.d.ts +21 -21
- package/lib/engine-components/utils/OpenURL.js +124 -124
- package/lib/engine-components/webxr/WebARCameraBackground.d.ts +19 -19
- package/lib/engine-components/webxr/WebARCameraBackground.js +193 -193
- package/lib/engine-components/webxr/WebARSessionRoot.d.ts +38 -38
- package/lib/engine-components/webxr/WebARSessionRoot.js +407 -407
- package/lib/engine-components/webxr/WebXR.d.ts +110 -110
- package/lib/engine-components/webxr/WebXR.js +672 -672
- package/lib/engine-components/webxr/WebXRAvatar.d.ts +61 -61
- package/lib/engine-components/webxr/WebXRAvatar.js +289 -289
- package/lib/engine-components/webxr/WebXRController.d.ts +154 -154
- package/lib/engine-components/webxr/WebXRController.js +1028 -1028
- package/lib/engine-components/webxr/WebXRGrabRendering.d.ts +42 -42
- package/lib/engine-components/webxr/WebXRGrabRendering.js +137 -137
- package/lib/engine-components/webxr/WebXRImageTracking.d.ts +49 -49
- package/lib/engine-components/webxr/WebXRImageTracking.js +336 -336
- package/lib/engine-components/webxr/WebXRPlaneTracking.d.ts +49 -49
- package/lib/engine-components/webxr/WebXRPlaneTracking.js +372 -372
- package/lib/engine-components/webxr/WebXRRig.d.ts +4 -4
- package/lib/engine-components/webxr/WebXRRig.js +19 -19
- package/lib/engine-components/webxr/WebXRSync.d.ts +54 -54
- package/lib/engine-components/webxr/WebXRSync.js +410 -410
- package/lib/engine-components/webxr/index.d.ts +4 -4
- package/lib/engine-components/webxr/index.js +4 -4
- 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 +1 -1
- package/lib/engine-components-experimental/api.js +1 -1
- package/lib/engine-components-experimental/networking/PlayerSync.d.ts +50 -50
- package/lib/engine-components-experimental/networking/PlayerSync.js +200 -200
- package/lib/engine-schemes/api.d.ts +1 -1
- package/lib/engine-schemes/api.js +1 -1
- 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/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 +36 -36
- package/lib/engine-schemes/vr-user-state-buffer.js +103 -103
- package/lib/include/three/ARButton.d.ts +3 -3
- package/lib/include/three/ARButton.js +151 -151
- 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/include/three/VRButton.d.ts +5 -5
- package/lib/include/three/VRButton.js +118 -118
- package/lib/needle-engine.d.ts +6 -6
- package/lib/needle-engine.js +49 -49
- package/package.json +1 -1
- package/plugins/common/config.cjs +14 -14
- package/plugins/common/config.js +19 -19
- package/plugins/common/generator.js +10 -10
- package/plugins/common/license.cjs +30 -30
- package/plugins/common/version.js +11 -11
- package/plugins/next/license.cjs +4 -4
- package/plugins/next/next.js +70 -70
- package/plugins/types/index.d.ts +1 -1
- package/plugins/types/needleConfig.d.ts +21 -21
- package/plugins/types/userconfig.d.ts +42 -42
- package/plugins/vite/alias.js +70 -70
- package/plugins/vite/build.js +19 -19
- package/plugins/vite/config.js +73 -73
- package/plugins/vite/copyfiles.js +134 -134
- package/plugins/vite/defines.js +45 -45
- package/plugins/vite/dependency-watcher.js +224 -224
- package/plugins/vite/drop-client.js +76 -76
- package/plugins/vite/drop.js +82 -82
- package/plugins/vite/editor-connection.js +121 -121
- package/plugins/vite/facebook-instant-games.js +99 -99
- package/plugins/vite/gzip.js +5 -5
- package/plugins/vite/imports-logger.js +143 -143
- package/plugins/vite/index.js +81 -81
- package/plugins/vite/license.js +42 -42
- package/plugins/vite/meta.js +149 -149
- package/plugins/vite/peer.js +31 -31
- package/plugins/vite/poster-client.js +59 -59
- package/plugins/vite/poster.js +73 -73
- package/plugins/vite/reload-client.js +15 -15
- package/plugins/vite/reload.js +363 -363
- package/plugins/vite/transform-codegen.js +55 -55
- package/plugins/vite/vite-4.4-hack.js +31 -31
- package/src/engine/api.ts +54 -54
- package/src/engine/assets/index.ts +4 -4
- package/src/engine/codegen/register_types.ts +441 -441
- package/src/engine/debug/debug.ts +29 -29
- package/src/engine/debug/debug_console.ts +213 -213
- package/src/engine/debug/debug_overlay.ts +283 -283
- package/src/engine/engine.ts +13 -13
- package/src/engine/engine_addressables.ts +494 -494
- package/src/engine/engine_application.ts +53 -53
- package/src/engine/engine_assetdatabase.ts +383 -383
- package/src/engine/engine_camera.ts +32 -32
- package/src/engine/engine_components.ts +266 -266
- package/src/engine/engine_components_internal.ts +42 -42
- package/src/engine/engine_constants.ts +42 -42
- package/src/engine/engine_context.ts +1386 -1386
- package/src/engine/engine_context_registry.ts +103 -103
- package/src/engine/engine_coroutine.ts +24 -24
- package/src/engine/engine_create_objects.ts +39 -39
- package/src/engine/engine_default_parameters.ts +3 -3
- package/src/engine/engine_editor-sync.ts +29 -29
- package/src/engine/engine_element.ts +592 -592
- package/src/engine/engine_element_attributes.ts +61 -61
- package/src/engine/engine_element_extras.ts +16 -16
- package/src/engine/engine_element_loading.ts +341 -341
- package/src/engine/engine_element_overlay.ts +160 -160
- package/src/engine/engine_fileloader.js +8 -8
- package/src/engine/engine_gameobject.ts +621 -621
- package/src/engine/engine_generic_utils.js +13 -13
- package/src/engine/engine_gizmos.ts +321 -321
- package/src/engine/engine_gltf.ts +30 -30
- package/src/engine/engine_gltf_builtin_components.ts +350 -350
- package/src/engine/engine_hot_reload.ts +196 -196
- package/src/engine/engine_input.ts +879 -879
- package/src/engine/engine_input_utils.ts +23 -23
- package/src/engine/engine_instancing.ts +42 -42
- package/src/engine/engine_license.ts +413 -413
- package/src/engine/engine_lifecycle_api.ts +29 -29
- package/src/engine/engine_lifecycle_functions_internal.ts +36 -36
- package/src/engine/engine_lightdata.ts +113 -113
- package/src/engine/engine_loaders.ts +77 -77
- package/src/engine/engine_mainloop_utils.ts +431 -431
- package/src/engine/engine_math.ts +174 -174
- package/src/engine/engine_networking.ts +742 -742
- package/src/engine/engine_networking_auto.ts +373 -373
- package/src/engine/engine_networking_files.ts +206 -206
- package/src/engine/engine_networking_files_default_components.ts +54 -54
- package/src/engine/engine_networking_instantiate.ts +362 -362
- package/src/engine/engine_networking_peer.ts +158 -158
- package/src/engine/engine_networking_streams.ts +489 -489
- package/src/engine/engine_networking_types.ts +18 -18
- 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 +287 -287
- package/src/engine/engine_physics.types.ts +43 -43
- package/src/engine/engine_physics_rapier.ts +1385 -1385
- package/src/engine/engine_playerview.ts +79 -79
- package/src/engine/engine_scenelighting.ts +313 -313
- package/src/engine/engine_scenetools.ts +242 -242
- package/src/engine/engine_serialization.ts +6 -6
- package/src/engine/engine_serialization_builtin_serializer.ts +415 -415
- package/src/engine/engine_serialization_core.ts +680 -680
- package/src/engine/engine_serialization_decorator.ts +68 -68
- package/src/engine/engine_setup.ts +1 -1
- package/src/engine/engine_shaders.ts +242 -242
- package/src/engine/engine_shims.ts +28 -28
- package/src/engine/engine_texture.ts +70 -70
- package/src/engine/engine_three_utils.ts +382 -382
- package/src/engine/engine_time.ts +55 -55
- package/src/engine/engine_types.ts +489 -489
- package/src/engine/engine_typestore.ts +41 -41
- package/src/engine/engine_util_decorator.ts +134 -134
- package/src/engine/engine_utils.ts +605 -605
- package/src/engine/engine_utils_screenshot.ts +84 -84
- package/src/engine/engine_web_api.ts +119 -119
- package/src/engine/extensions/EXT_texture_exr.ts +49 -49
- package/src/engine/extensions/NEEDLE_animator_controller_model.ts +193 -193
- package/src/engine/extensions/NEEDLE_components.ts +250 -250
- package/src/engine/extensions/NEEDLE_gameobject_data.ts +82 -82
- package/src/engine/extensions/NEEDLE_lighting_settings.ts +210 -210
- package/src/engine/extensions/NEEDLE_lightmaps.ts +130 -130
- package/src/engine/extensions/NEEDLE_persistent_assets.ts +75 -75
- package/src/engine/extensions/NEEDLE_progressive.ts +412 -412
- package/src/engine/extensions/NEEDLE_render_objects.ts +209 -209
- package/src/engine/extensions/NEEDLE_techniques_webgl.ts +618 -618
- package/src/engine/extensions/extension_resolver.ts +4 -4
- package/src/engine/extensions/extension_utils.ts +149 -149
- package/src/engine/extensions/extensions.ts +118 -118
- package/src/engine/extensions/index.ts +4 -4
- package/src/engine/extensions/usage_tracker.ts +95 -95
- package/src/engine/js-extensions/Camera.ts +34 -34
- package/src/engine/js-extensions/Layers.ts +19 -19
- package/src/engine/js-extensions/index.ts +1 -1
- package/src/engine/shaders/shaderData.ts +67 -67
- package/src/engine/tests/test_utils.ts +63 -63
- package/src/engine-components/AlignmentConstraint.ts +35 -35
- package/src/engine-components/Animation.ts +345 -345
- package/src/engine-components/AnimationCurve.ts +83 -83
- package/src/engine-components/AnimationUtils.ts +117 -117
- package/src/engine-components/Animator.ts +243 -243
- package/src/engine-components/AnimatorController.ts +1020 -1020
- package/src/engine-components/AudioListener.ts +32 -32
- package/src/engine-components/AudioSource.ts +419 -419
- package/src/engine-components/AvatarLoader.ts +204 -204
- package/src/engine-components/AxesHelper.ts +33 -33
- package/src/engine-components/BasicIKConstraint.ts +53 -53
- package/src/engine-components/BoxCollider.ts +1 -1
- package/src/engine-components/BoxHelperComponent.ts +100 -100
- package/src/engine-components/Camera.ts +454 -454
- package/src/engine-components/CameraUtils.ts +89 -89
- package/src/engine-components/CharacterController.ts +243 -243
- package/src/engine-components/Collider.ts +160 -160
- package/src/engine-components/Component.ts +670 -670
- package/src/engine-components/ContactShadows.ts +265 -265
- package/src/engine-components/DeleteBox.ts +35 -35
- package/src/engine-components/DeviceFlag.ts +42 -42
- package/src/engine-components/DragControls.ts +574 -574
- package/src/engine-components/DropListener.ts +112 -112
- package/src/engine-components/Duplicatable.ts +146 -146
- package/src/engine-components/EventList.ts +125 -125
- package/src/engine-components/EventTrigger.ts +47 -47
- package/src/engine-components/EventType.ts +87 -87
- package/src/engine-components/FlyControls.ts +31 -31
- package/src/engine-components/Fog.ts +59 -59
- package/src/engine-components/Gizmos.ts +52 -52
- package/src/engine-components/GridHelper.ts +40 -40
- package/src/engine-components/GroundProjection.ts +97 -97
- package/src/engine-components/Interactable.ts +18 -18
- package/src/engine-components/Joints.ts +51 -51
- package/src/engine-components/LODGroup.ts +145 -145
- package/src/engine-components/Light.ts +493 -493
- package/src/engine-components/LookAtConstraint.ts +11 -11
- package/src/engine-components/NestedGltf.ts +70 -70
- package/src/engine-components/Networking.ts +72 -72
- package/src/engine-components/OffsetConstraint.ts +59 -59
- package/src/engine-components/OrbitControls.ts +653 -653
- package/src/engine-components/ParticleSystem.ts +1192 -1192
- package/src/engine-components/ParticleSystemModules.ts +1481 -1481
- package/src/engine-components/ParticleSystemSubEmitter.ts +110 -110
- package/src/engine-components/PlayerColor.ts +93 -93
- package/src/engine-components/ReflectionProbe.ts +192 -192
- package/src/engine-components/Renderer.ts +1125 -1125
- package/src/engine-components/RendererLightmap.ts +145 -145
- package/src/engine-components/RigidBody.ts +453 -453
- package/src/engine-components/SceneSwitcher.ts +594 -594
- package/src/engine-components/ScreenCapture.ts +437 -437
- package/src/engine-components/ShadowCatcher.ts +149 -149
- package/src/engine-components/Skybox.ts +281 -281
- package/src/engine-components/SmoothFollow.ts +57 -57
- package/src/engine-components/SpatialTrigger.ts +142 -142
- package/src/engine-components/SpectatorCamera.ts +675 -675
- package/src/engine-components/SphereCollider.ts +1 -1
- package/src/engine-components/SpriteRenderer.ts +244 -244
- package/src/engine-components/SyncedCamera.ts +208 -208
- package/src/engine-components/SyncedRoom.ts +166 -166
- package/src/engine-components/SyncedTransform.ts +336 -336
- package/src/engine-components/TestRunner.ts +114 -114
- package/src/engine-components/TransformGizmo.ts +157 -157
- package/src/engine-components/VideoPlayer.ts +831 -831
- package/src/engine-components/Voip.ts +214 -214
- package/src/engine-components/XRFlag.ts +138 -138
- package/src/engine-components/api.ts +22 -22
- package/src/engine-components/avatar/AvatarBlink_Simple.ts +67 -67
- package/src/engine-components/avatar/AvatarEyeLook_Rotation.ts +68 -68
- package/src/engine-components/avatar/Avatar_Brain_LookAt.ts +136 -136
- package/src/engine-components/avatar/Avatar_MouthShapes.ts +81 -81
- package/src/engine-components/avatar/Avatar_MustacheShake.ts +28 -28
- package/src/engine-components/codegen/components.ts +216 -216
- package/src/engine-components/debug/LogStats.ts +21 -21
- package/src/engine-components/export/gltf/GltfExport.ts +231 -231
- package/src/engine-components/export/usdz/Extension.ts +11 -11
- package/src/engine-components/export/usdz/ThreeUSDZExporter.ts +1773 -1773
- package/src/engine-components/export/usdz/USDZExporter.ts +477 -477
- package/src/engine-components/export/usdz/extensions/Animation.ts +774 -774
- package/src/engine-components/export/usdz/extensions/DocumentExtension.ts +9 -9
- package/src/engine-components/export/usdz/extensions/USDZText.ts +287 -287
- package/src/engine-components/export/usdz/extensions/USDZUI.ts +119 -119
- package/src/engine-components/export/usdz/extensions/behavior/Actions.ts +98 -98
- package/src/engine-components/export/usdz/extensions/behavior/AudioExtension.ts +67 -67
- package/src/engine-components/export/usdz/extensions/behavior/Behaviour.ts +202 -202
- package/src/engine-components/export/usdz/extensions/behavior/BehaviourComponents.ts +963 -963
- package/src/engine-components/export/usdz/extensions/behavior/BehavioursBuilder.ts +517 -517
- package/src/engine-components/export/usdz/index.ts +2 -2
- package/src/engine-components/export/usdz/utils/animationutils.ts +100 -100
- package/src/engine-components/export/usdz/utils/quicklook.ts +42 -42
- package/src/engine-components/export/usdz/utils/timeutils.ts +19 -19
- package/src/engine-components/js-extensions/ExtensionUtils.ts +81 -81
- package/src/engine-components/js-extensions/Object3D.ts +181 -181
- package/src/engine-components/js-extensions/RGBAColor.ts +54 -54
- package/src/engine-components/js-extensions/Vector.ts +16 -16
- package/src/engine-components/js-extensions/index.ts +2 -2
- package/src/engine-components/postprocessing/Effects/Antialiasing.ts +51 -51
- package/src/engine-components/postprocessing/Effects/Bloom.ts +76 -76
- package/src/engine-components/postprocessing/Effects/ChromaticAberration.ts +35 -35
- package/src/engine-components/postprocessing/Effects/ColorAdjustments.ts +96 -96
- package/src/engine-components/postprocessing/Effects/DepthOfField.ts +93 -93
- package/src/engine-components/postprocessing/Effects/Pixelation.ts +26 -26
- package/src/engine-components/postprocessing/Effects/ScreenspaceAmbientOcclusion.ts +84 -84
- package/src/engine-components/postprocessing/Effects/ScreenspaceAmbientOcclusionN8.ts +98 -98
- package/src/engine-components/postprocessing/Effects/TiltShiftEffect.ts +55 -55
- package/src/engine-components/postprocessing/Effects/Tonemapping.ts +54 -54
- package/src/engine-components/postprocessing/Effects/Vignette.ts +54 -54
- package/src/engine-components/postprocessing/PostProcessingEffect.ts +148 -148
- package/src/engine-components/postprocessing/PostProcessingHandler.ts +232 -232
- package/src/engine-components/postprocessing/Volume.ts +216 -216
- package/src/engine-components/postprocessing/VolumeParameter.ts +92 -92
- package/src/engine-components/postprocessing/VolumeProfile.ts +40 -40
- package/src/engine-components/postprocessing/index.ts +3 -3
- package/src/engine-components/timeline/PlayableDirector.ts +666 -666
- package/src/engine-components/timeline/SignalAsset.ts +138 -138
- package/src/engine-components/timeline/TimelineModels.ts +93 -93
- package/src/engine-components/timeline/TimelineTracks.ts +906 -906
- package/src/engine-components/timeline/index.ts +3 -3
- package/src/engine-components/ui/BaseUIComponent.ts +195 -195
- package/src/engine-components/ui/Button.ts +283 -283
- package/src/engine-components/ui/Canvas.ts +390 -390
- package/src/engine-components/ui/CanvasGroup.ts +49 -49
- package/src/engine-components/ui/EventSystem.ts +736 -736
- package/src/engine-components/ui/Graphic.ts +255 -255
- package/src/engine-components/ui/Image.ts +102 -102
- package/src/engine-components/ui/InputField.ts +290 -290
- package/src/engine-components/ui/Interfaces.ts +57 -57
- package/src/engine-components/ui/Layout.ts +322 -322
- package/src/engine-components/ui/Outline.ts +12 -12
- package/src/engine-components/ui/PointerEvents.ts +118 -118
- package/src/engine-components/ui/RaycastUtils.ts +68 -68
- package/src/engine-components/ui/Raycaster.ts +73 -73
- package/src/engine-components/ui/RectTransform.ts +364 -364
- package/src/engine-components/ui/SpatialHtml.ts +63 -63
- package/src/engine-components/ui/Text.ts +572 -572
- package/src/engine-components/ui/Utils.ts +110 -110
- package/src/engine-components/utils/LookAt.ts +65 -65
- package/src/engine-components/utils/OpenURL.ts +118 -118
- package/src/engine-components/webxr/WebARCameraBackground.ts +224 -224
- package/src/engine-components/webxr/WebARSessionRoot.ts +446 -446
- package/src/engine-components/webxr/WebXR.ts +761 -761
- package/src/engine-components/webxr/WebXRAvatar.ts +356 -356
- package/src/engine-components/webxr/WebXRController.ts +1168 -1168
- package/src/engine-components/webxr/WebXRGrabRendering.ts +150 -150
- package/src/engine-components/webxr/WebXRImageTracking.ts +371 -371
- package/src/engine-components/webxr/WebXRPlaneTracking.ts +429 -429
- package/src/engine-components/webxr/WebXRRig.ts +21 -21
- package/src/engine-components/webxr/WebXRSync.ts +463 -463
- package/src/engine-components/webxr/index.ts +3 -3
- package/src/engine-components-experimental/Presentation.ts +12 -12
- package/src/engine-components-experimental/networking/PlayerSync.ts +217 -217
- package/src/engine-schemes/COMPILE_SCHEMES.bat +3 -3
- package/src/engine-schemes/COMPILE_TS.bat +11 -11
- package/src/engine-schemes/schemes.ts +27 -27
- 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 +138 -138
- package/src/engine-schemes/vrUserStateBuffer.fbs +16 -16
- package/src/include/draco/draco_decoder.js +34 -34
- package/src/include/draco/draco_wasm_wrapper.js +117 -117
- package/src/include/ktx2/basis_transcoder.js +21 -21
- package/src/include/needle/arial-msdf.json +1471 -1471
- package/src/include/three/ARButton.js +231 -231
- package/src/include/three/DragControls.js +231 -231
- package/src/include/three/EXT_mesh_gpu_instancing_exporter.js +66 -66
- package/src/include/three/VRButton.js +194 -194
- package/src/needle-engine.ts +55 -55
- package/src/engine/dist/api.js +0 -73
- package/src/engine/dist/api.js.meta +0 -7
- package/src/engine/dist/engine_networking_streams.js +0 -474
- package/src/engine/dist/engine_networking_streams.js.meta +0 -7
- package/src/engine-schemes/dist/api.js +0 -17
- package/src/engine-schemes/dist/api.js.meta +0 -7
- package/src/engine-schemes/dist/schemes.js +0 -25
- package/src/engine-schemes/dist/schemes.js.meta +0 -7
- package/src/engine-schemes/dist/synced-camera-model.js +0 -74
- package/src/engine-schemes/dist/synced-camera-model.js.meta +0 -7
- package/src/engine-schemes/dist/synced-transform-model.js +0 -73
- package/src/engine-schemes/dist/synced-transform-model.js.meta +0 -7
- package/src/engine-schemes/dist/transform.js +0 -46
- package/src/engine-schemes/dist/transform.js.meta +0 -7
- package/src/engine-schemes/dist/vec2.js +0 -32
- package/src/engine-schemes/dist/vec2.js.meta +0 -7
- package/src/engine-schemes/dist/vec3.js +0 -36
- package/src/engine-schemes/dist/vec3.js.meta +0 -7
- package/src/engine-schemes/dist/vec4.js +0 -40
- package/src/engine-schemes/dist/vec4.js.meta +0 -7
- package/src/engine-schemes/dist/vr-user-state-buffer.js +0 -110
- package/src/engine-schemes/dist/vr-user-state-buffer.js.meta +0 -7
- package/src/engine-schemes/flatc.exe +0 -0
|
@@ -1,888 +1,888 @@
|
|
|
1
|
-
import { AnimatorConditionMode, AnimatorControllerParameterType, AnimatorStateInfo, createMotion } from "../engine/extensions/NEEDLE_animator_controller_model.js";
|
|
2
|
-
import { AnimationClip, AnimationMixer, AxesHelper, Euler, LoopOnce, Quaternion, Vector3 } from "three";
|
|
3
|
-
import { deepClone, getParam } from "../engine/engine_utils.js";
|
|
4
|
-
import { TypeStore } from "../engine/engine_typestore.js";
|
|
5
|
-
import { TypeSerializer, assign } from "../engine/engine_serialization_core.js";
|
|
6
|
-
import { Mathf } from "../engine/engine_math.js";
|
|
7
|
-
import { isAnimationAction } from "../engine/engine_three_utils.js";
|
|
8
|
-
import { isDevEnvironment } from "../engine/debug/index.js";
|
|
9
|
-
import { InstantiateIdProvider } from "../engine/engine_networking_instantiate.js";
|
|
10
|
-
const debug = getParam("debuganimatorcontroller");
|
|
11
|
-
const debugRootMotion = getParam("debugrootmotion");
|
|
12
|
-
function stringToHash(str) {
|
|
13
|
-
let hash = 0;
|
|
14
|
-
for (let i = 0; i < str.length; i++) {
|
|
15
|
-
const char = str.charCodeAt(i);
|
|
16
|
-
hash = ((hash << 5) - hash) + char;
|
|
17
|
-
hash = hash & hash;
|
|
18
|
-
}
|
|
19
|
-
return hash;
|
|
20
|
-
}
|
|
21
|
-
export class AnimatorController {
|
|
22
|
-
/** Create an animatorcontroller with clips assigned */
|
|
23
|
-
static createFromClips(clips, options = { looping: false, autoTransition: true, transitionDuration: 0 }) {
|
|
24
|
-
const states = [];
|
|
25
|
-
for (let i = 0; i < clips.length; i++) {
|
|
26
|
-
const clip = clips[i];
|
|
27
|
-
const transitions = [];
|
|
28
|
-
if (options.autoTransition !== false) {
|
|
29
|
-
const dur = options.transitionDuration ?? 0;
|
|
30
|
-
const normalizedDuration = dur / clip.duration;
|
|
31
|
-
// automatically transition to self by default
|
|
32
|
-
let nextState = i;
|
|
33
|
-
if (options.autoTransition === undefined || options.autoTransition === true) {
|
|
34
|
-
nextState = (i + 1) % clips.length;
|
|
35
|
-
}
|
|
36
|
-
transitions.push({
|
|
37
|
-
exitTime: 1 - normalizedDuration,
|
|
38
|
-
offset: 0,
|
|
39
|
-
duration: dur,
|
|
40
|
-
hasExitTime: true,
|
|
41
|
-
destinationState: nextState,
|
|
42
|
-
conditions: [],
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
const state = {
|
|
46
|
-
name: clip.name,
|
|
47
|
-
hash: i,
|
|
48
|
-
motion: {
|
|
49
|
-
name: clip.name,
|
|
50
|
-
clip: clip,
|
|
51
|
-
isLooping: options?.looping ?? false,
|
|
52
|
-
},
|
|
53
|
-
transitions: transitions,
|
|
54
|
-
behaviours: []
|
|
55
|
-
};
|
|
56
|
-
states.push(state);
|
|
57
|
-
}
|
|
58
|
-
const model = {
|
|
59
|
-
name: "AnimatorController",
|
|
60
|
-
guid: new InstantiateIdProvider(Date.now()).generateUUID(),
|
|
61
|
-
parameters: [],
|
|
62
|
-
layers: [{
|
|
63
|
-
name: "Base Layer",
|
|
64
|
-
stateMachine: {
|
|
65
|
-
defaultState: 0,
|
|
66
|
-
states: states
|
|
67
|
-
}
|
|
68
|
-
}]
|
|
69
|
-
};
|
|
70
|
-
const controller = new AnimatorController(model);
|
|
71
|
-
return controller;
|
|
72
|
-
}
|
|
73
|
-
play(name, layerIndex = -1, normalizedTime = Number.NEGATIVE_INFINITY, durationInSec = 0) {
|
|
74
|
-
if (layerIndex < 0)
|
|
75
|
-
layerIndex = 0;
|
|
76
|
-
else if (layerIndex >= this.model.layers.length) {
|
|
77
|
-
console.warn("invalid layer");
|
|
78
|
-
return;
|
|
79
|
-
}
|
|
80
|
-
const layer = this.model.layers[layerIndex];
|
|
81
|
-
const sm = layer.stateMachine;
|
|
82
|
-
for (const state of sm.states) {
|
|
83
|
-
if (state.name === name || state.hash === name) {
|
|
84
|
-
if (debug)
|
|
85
|
-
console.log("transition to ", state);
|
|
86
|
-
this.transitionTo(state, durationInSec, normalizedTime);
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
console.warn("Could not find " + name + " to play");
|
|
91
|
-
}
|
|
92
|
-
reset() {
|
|
93
|
-
this.setStartTransition();
|
|
94
|
-
}
|
|
95
|
-
setBool(name, value) {
|
|
96
|
-
const key = typeof name === "string" ? "name" : "hash";
|
|
97
|
-
return this.model?.parameters?.filter(p => p[key] === name).forEach(p => p.value = value);
|
|
98
|
-
}
|
|
99
|
-
getBool(name) {
|
|
100
|
-
const key = typeof name === "string" ? "name" : "hash";
|
|
101
|
-
return this.model?.parameters?.find(p => p[key] === name)?.value ?? false;
|
|
102
|
-
}
|
|
103
|
-
setFloat(name, val) {
|
|
104
|
-
const key = typeof name === "string" ? "name" : "hash";
|
|
105
|
-
const filtered = this.model?.parameters?.filter(p => p[key] === name);
|
|
106
|
-
filtered.forEach(p => p.value = val);
|
|
107
|
-
return filtered?.length > 0;
|
|
108
|
-
}
|
|
109
|
-
getFloat(name) {
|
|
110
|
-
const key = typeof name === "string" ? "name" : "hash";
|
|
111
|
-
return this.model?.parameters?.find(p => p[key] === name)?.value ?? 0;
|
|
112
|
-
}
|
|
113
|
-
setInteger(name, val) {
|
|
114
|
-
const key = typeof name === "string" ? "name" : "hash";
|
|
115
|
-
return this.model?.parameters?.filter(p => p[key] === name).forEach(p => p.value = val);
|
|
116
|
-
}
|
|
117
|
-
getInteger(name) {
|
|
118
|
-
const key = typeof name === "string" ? "name" : "hash";
|
|
119
|
-
return this.model?.parameters?.find(p => p[key] === name)?.value ?? 0;
|
|
120
|
-
}
|
|
121
|
-
setTrigger(name) {
|
|
122
|
-
if (debug)
|
|
123
|
-
console.log("SET TRIGGER", name);
|
|
124
|
-
const key = typeof name === "string" ? "name" : "hash";
|
|
125
|
-
return this.model?.parameters?.filter(p => p[key] === name).forEach(p => p.value = true);
|
|
126
|
-
}
|
|
127
|
-
resetTrigger(name) {
|
|
128
|
-
const key = typeof name === "string" ? "name" : "hash";
|
|
129
|
-
return this.model?.parameters?.filter(p => p[key] === name).forEach(p => p.value = false);
|
|
130
|
-
}
|
|
131
|
-
getTrigger(name) {
|
|
132
|
-
const key = typeof name === "string" ? "name" : "hash";
|
|
133
|
-
return this.model?.parameters?.find(p => p[key] === name)?.value ?? false;
|
|
134
|
-
}
|
|
135
|
-
isInTransition() {
|
|
136
|
-
return this._activeStates.length > 1;
|
|
137
|
-
}
|
|
138
|
-
setSpeed(speed) {
|
|
139
|
-
this._speed = speed;
|
|
140
|
-
}
|
|
141
|
-
/**@deprecated use findState */
|
|
142
|
-
FindState(name) { return this.findState(name); }
|
|
143
|
-
findState(name) {
|
|
144
|
-
if (!name)
|
|
145
|
-
return null;
|
|
146
|
-
if (Array.isArray(this.model.layers)) {
|
|
147
|
-
for (const layer of this.model.layers) {
|
|
148
|
-
for (const state of layer.stateMachine.states) {
|
|
149
|
-
if (state.name === name || state.hash == name)
|
|
150
|
-
return state;
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
return null;
|
|
155
|
-
}
|
|
156
|
-
normalizedStartOffset = 0;
|
|
157
|
-
_speed = 1;
|
|
158
|
-
animator;
|
|
159
|
-
model;
|
|
160
|
-
get context() { return this.animator?.context; }
|
|
161
|
-
get mixer() {
|
|
162
|
-
return this._mixer;
|
|
163
|
-
}
|
|
164
|
-
// applyRootMotion(obj: Object3D) {
|
|
165
|
-
// // this.internalApplyRootMotion(obj);
|
|
166
|
-
// }
|
|
167
|
-
bind(animator) {
|
|
168
|
-
if (!animator)
|
|
169
|
-
console.error("AnimatorController.bind: animator is null");
|
|
170
|
-
else if (this.animator !== animator) {
|
|
171
|
-
this.animator = animator;
|
|
172
|
-
this._mixer = new AnimationMixer(this.animator.gameObject);
|
|
173
|
-
this.createActions(this.animator);
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
clone() {
|
|
177
|
-
if (typeof this.model === "string") {
|
|
178
|
-
console.warn("AnimatorController has not been resolved, can not create model from string", this.model);
|
|
179
|
-
return null;
|
|
180
|
-
}
|
|
181
|
-
// clone runtime controller but dont clone clip or action
|
|
182
|
-
const clonedModel = deepClone(this.model, (_owner, _key, _value) => {
|
|
183
|
-
if (_value === null || _value === undefined)
|
|
184
|
-
return true;
|
|
185
|
-
// dont clone three Objects
|
|
186
|
-
if (_value.type === "Object3D" || _value.isObject3D === true)
|
|
187
|
-
return false;
|
|
188
|
-
// dont clone AnimationAction
|
|
189
|
-
if (isAnimationAction(_value)) { //.constructor.name === "AnimationAction") {
|
|
190
|
-
// console.log(_value);
|
|
191
|
-
return false;
|
|
192
|
-
}
|
|
193
|
-
// dont clone AnimationClip
|
|
194
|
-
if (_value["tracks"] !== undefined)
|
|
195
|
-
return false;
|
|
196
|
-
return true;
|
|
197
|
-
});
|
|
198
|
-
console.assert(clonedModel !== this.model);
|
|
199
|
-
const controller = new AnimatorController(clonedModel);
|
|
200
|
-
return controller;
|
|
201
|
-
}
|
|
202
|
-
update(weight) {
|
|
203
|
-
if (!this.animator)
|
|
204
|
-
return;
|
|
205
|
-
this.evaluateTransitions();
|
|
206
|
-
this.updateActiveStates(weight);
|
|
207
|
-
// 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)
|
|
208
|
-
// if (!this._activeState) return;
|
|
209
|
-
const dt = this.animator.context.time.deltaTime;
|
|
210
|
-
if (this.animator.applyRootMotion) {
|
|
211
|
-
this.rootMotionHandler?.onBeforeUpdate(weight);
|
|
212
|
-
}
|
|
213
|
-
this._mixer.update(dt);
|
|
214
|
-
if (this.animator.applyRootMotion) {
|
|
215
|
-
this.rootMotionHandler?.onAfterUpdate(weight);
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
_mixer;
|
|
219
|
-
_activeState;
|
|
220
|
-
get activeState() { return this._activeState; }
|
|
221
|
-
constructor(model) {
|
|
222
|
-
this.model = model;
|
|
223
|
-
if (debug)
|
|
224
|
-
console.log(this);
|
|
225
|
-
}
|
|
226
|
-
_activeStates = [];
|
|
227
|
-
updateActiveStates(weight) {
|
|
228
|
-
for (let i = 0; i < this._activeStates.length; i++) {
|
|
229
|
-
const state = this._activeStates[i];
|
|
230
|
-
const motion = state.motion;
|
|
231
|
-
if (!motion.action) {
|
|
232
|
-
this._activeStates.splice(i, 1);
|
|
233
|
-
i--;
|
|
234
|
-
}
|
|
235
|
-
else {
|
|
236
|
-
const action = motion.action;
|
|
237
|
-
action.weight = weight;
|
|
238
|
-
// console.log(action.getClip().name, action.getEffectiveWeight(), action.isScheduled());
|
|
239
|
-
if ((action.getEffectiveWeight() <= 0 && !action.isRunning())) {
|
|
240
|
-
if (debug)
|
|
241
|
-
console.debug("REMOVE", state.name, action.getEffectiveWeight(), action.isRunning(), action.isScheduled());
|
|
242
|
-
this._activeStates.splice(i, 1);
|
|
243
|
-
i--;
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
setStartTransition() {
|
|
249
|
-
for (const layer of this.model.layers) {
|
|
250
|
-
const sm = layer.stateMachine;
|
|
251
|
-
if (sm.defaultState === undefined) {
|
|
252
|
-
if (debug)
|
|
253
|
-
console.warn("AnimatorController default state is undefined, will assign state 0 as default", layer);
|
|
254
|
-
sm.defaultState = 0;
|
|
255
|
-
}
|
|
256
|
-
const start = sm.states[sm.defaultState];
|
|
257
|
-
this.transitionTo(start, 0, this.normalizedStartOffset);
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
evaluateTransitions() {
|
|
261
|
-
let didEnterStateThisFrame = false;
|
|
262
|
-
if (!this._activeState) {
|
|
263
|
-
this.setStartTransition();
|
|
264
|
-
if (!this._activeState)
|
|
265
|
-
return;
|
|
266
|
-
didEnterStateThisFrame = true;
|
|
267
|
-
}
|
|
268
|
-
const state = this._activeState;
|
|
269
|
-
const action = state.motion.action;
|
|
270
|
-
let index = 0;
|
|
271
|
-
for (const transition of state.transitions) {
|
|
272
|
-
++index;
|
|
273
|
-
// transition without exit time and without condition that transition to itself are ignored
|
|
274
|
-
if (!transition.hasExitTime && transition.conditions.length <= 0) {
|
|
275
|
-
// if (this._activeState && this.getState(transition.destinationState, currentLayer)?.hash === this._activeState.hash)
|
|
276
|
-
continue;
|
|
277
|
-
}
|
|
278
|
-
let allConditionsAreMet = true;
|
|
279
|
-
for (const cond of transition.conditions) {
|
|
280
|
-
if (!this.evaluateCondition(cond)) {
|
|
281
|
-
allConditionsAreMet = false;
|
|
282
|
-
break;
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
if (!allConditionsAreMet)
|
|
286
|
-
continue;
|
|
287
|
-
if (debug && allConditionsAreMet) {
|
|
288
|
-
// console.log("All conditions are met", transition);
|
|
289
|
-
}
|
|
290
|
-
if (action) {
|
|
291
|
-
const dur = state.motion.clip.duration;
|
|
292
|
-
const normalizedTime = dur <= 0 ? 1 : Math.abs(action.time / dur);
|
|
293
|
-
let makeTransition = false;
|
|
294
|
-
if (transition.hasExitTime) {
|
|
295
|
-
if (action.timeScale > 0)
|
|
296
|
-
makeTransition = normalizedTime >= transition.exitTime;
|
|
297
|
-
// When the animation is playing backwards we need to check exit time inverted
|
|
298
|
-
else if (action.timeScale < 0)
|
|
299
|
-
makeTransition = 1 - normalizedTime >= transition.exitTime;
|
|
300
|
-
}
|
|
301
|
-
else {
|
|
302
|
-
makeTransition = true;
|
|
303
|
-
}
|
|
304
|
-
if (makeTransition) {
|
|
305
|
-
// disable triggers for this transition
|
|
306
|
-
for (const cond of transition.conditions) {
|
|
307
|
-
const param = this.model.parameters.find(p => p.name === cond.parameter);
|
|
308
|
-
if (param?.type === AnimatorControllerParameterType.Trigger && param.value) {
|
|
309
|
-
param.value = false;
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
// if (transition.hasExitTime && transition.exitTime >= .9999)
|
|
313
|
-
action.clampWhenFinished = true;
|
|
314
|
-
// else action.clampWhenFinished = false;
|
|
315
|
-
if (debug) {
|
|
316
|
-
console.log("transition to " + transition.destinationState, transition, normalizedTime, transition.exitTime, transition.hasExitTime);
|
|
317
|
-
// console.log(action.time, transition.exitTime);
|
|
318
|
-
}
|
|
319
|
-
this.transitionTo(transition.destinationState, transition.duration, transition.offset);
|
|
320
|
-
// use the first transition that matches all conditions and make the transition as soon as in range
|
|
321
|
-
return;
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
else {
|
|
325
|
-
this.transitionTo(transition.destinationState, transition.duration, transition.offset);
|
|
326
|
-
return;
|
|
327
|
-
}
|
|
328
|
-
// if none of the transitions can be made continue searching for another transition meeting the conditions
|
|
329
|
-
}
|
|
330
|
-
// action.time += this.context.time.deltaTime
|
|
331
|
-
// console.log(action?.time, action?.getEffectiveWeight())
|
|
332
|
-
// update timescale
|
|
333
|
-
if (action) {
|
|
334
|
-
let speedFactor = state.speed ?? 1;
|
|
335
|
-
if (state.speedParameter)
|
|
336
|
-
speedFactor *= this.getFloat(state.speedParameter);
|
|
337
|
-
if (speedFactor !== undefined) {
|
|
338
|
-
action.timeScale = speedFactor * this._speed;
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
let didTriggerLooping = false;
|
|
342
|
-
if (state.motion.isLooping && action) {
|
|
343
|
-
// we dont use the three loop state here because it prevents the transition check above
|
|
344
|
-
// it is easier if we re-trigger loop here.
|
|
345
|
-
// We also can easily add the cycle offset settings from unity later
|
|
346
|
-
if (action.time >= action.getClip().duration) {
|
|
347
|
-
didTriggerLooping = true;
|
|
348
|
-
action.reset();
|
|
349
|
-
action.time = 0;
|
|
350
|
-
action.play();
|
|
351
|
-
}
|
|
352
|
-
else if (action.time <= 0 && action.timeScale < 0) {
|
|
353
|
-
didTriggerLooping = true;
|
|
354
|
-
action.reset();
|
|
355
|
-
action.time = action.getClip().duration;
|
|
356
|
-
action.play();
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
|
-
// call update state behaviours:
|
|
360
|
-
if (!didTriggerLooping && state && !didEnterStateThisFrame && action && this.animator) {
|
|
361
|
-
if (state.behaviours) {
|
|
362
|
-
const duration = action?.getClip().duration;
|
|
363
|
-
const normalizedTime = action.time / duration;
|
|
364
|
-
const info = new AnimatorStateInfo(this._activeState, normalizedTime, duration, this._speed);
|
|
365
|
-
for (const beh of state.behaviours) {
|
|
366
|
-
if (beh.instance) {
|
|
367
|
-
beh.instance.onStateUpdate?.call(beh.instance, this.animator, info, 0);
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
getState(state, layerIndex) {
|
|
374
|
-
if (typeof state === "number") {
|
|
375
|
-
if (state == -1) {
|
|
376
|
-
state = this.model.layers[layerIndex].stateMachine.defaultState; // exit state -> entry state
|
|
377
|
-
if (state === undefined) {
|
|
378
|
-
if (debug)
|
|
379
|
-
console.warn("AnimatorController default state is undefined: ", this.model, "Layer: " + layerIndex);
|
|
380
|
-
state = 0;
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
state = this.model.layers[layerIndex].stateMachine.states[state];
|
|
384
|
-
}
|
|
385
|
-
return state;
|
|
386
|
-
}
|
|
387
|
-
transitionTo(state, durationInSec, offsetNormalized) {
|
|
388
|
-
if (!this.animator)
|
|
389
|
-
return;
|
|
390
|
-
const layerIndex = 0;
|
|
391
|
-
state = this.getState(state, layerIndex);
|
|
392
|
-
if (!state?.motion || !state.motion.clip || !(state.motion.clip instanceof AnimationClip)) {
|
|
393
|
-
// if(debug) console.warn("State has no clip or motion", state);
|
|
394
|
-
return;
|
|
395
|
-
}
|
|
396
|
-
const isSelf = this._activeState === state;
|
|
397
|
-
if (isSelf) {
|
|
398
|
-
const motion = state.motion;
|
|
399
|
-
if (!motion.action_loopback && motion.clip) {
|
|
400
|
-
// uncache action immediately resets the applied animation which breaks the root motion
|
|
401
|
-
// this happens if we have a transition to self and the clip is not cached yet
|
|
402
|
-
const previousMatrix = this.rootMotionHandler ? this.animator.gameObject.matrix.clone() : null;
|
|
403
|
-
this._mixer.uncacheAction(motion.clip, this.animator.gameObject);
|
|
404
|
-
if (previousMatrix)
|
|
405
|
-
previousMatrix.decompose(this.animator.gameObject.position, this.animator.gameObject.quaternion, this.animator.gameObject.scale);
|
|
406
|
-
motion.action_loopback = this.createAction(motion.clip);
|
|
407
|
-
}
|
|
408
|
-
}
|
|
409
|
-
// call exit state behaviours
|
|
410
|
-
if (this._activeState?.behaviours && this._activeState.motion.action) {
|
|
411
|
-
const duration = this._activeState?.motion.clip.duration;
|
|
412
|
-
const normalizedTime = this._activeState.motion.action.time / duration;
|
|
413
|
-
const info = new AnimatorStateInfo(this._activeState, normalizedTime, duration, this._speed);
|
|
414
|
-
for (const beh of this._activeState.behaviours) {
|
|
415
|
-
beh.instance?.onStateExit?.call(beh.instance, this.animator, info, layerIndex);
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
const prevAction = this._activeState?.motion.action;
|
|
419
|
-
if (prevAction) {
|
|
420
|
-
prevAction.fadeOut(durationInSec);
|
|
421
|
-
}
|
|
422
|
-
if (isSelf) {
|
|
423
|
-
state.motion.action = state.motion.action_loopback;
|
|
424
|
-
state.motion.action_loopback = prevAction;
|
|
425
|
-
}
|
|
426
|
-
const prev = this._activeState;
|
|
427
|
-
this._activeState = state;
|
|
428
|
-
const action = state.motion?.action;
|
|
429
|
-
if (action) {
|
|
430
|
-
offsetNormalized = Math.max(0, Math.min(1, offsetNormalized));
|
|
431
|
-
if (state.cycleOffsetParameter) {
|
|
432
|
-
let val = this.getFloat(state.cycleOffsetParameter);
|
|
433
|
-
if (typeof val === "number") {
|
|
434
|
-
if (val < 0)
|
|
435
|
-
val += 1;
|
|
436
|
-
offsetNormalized += val;
|
|
437
|
-
offsetNormalized %= 1;
|
|
438
|
-
}
|
|
439
|
-
else if (debug)
|
|
440
|
-
console.warn("AnimatorController cycle offset parameter is not a number", state.cycleOffsetParameter);
|
|
441
|
-
}
|
|
442
|
-
else if (typeof state.cycleOffset === "number") {
|
|
443
|
-
offsetNormalized += state.cycleOffset;
|
|
444
|
-
offsetNormalized %= 1;
|
|
445
|
-
}
|
|
446
|
-
if (action.isRunning())
|
|
447
|
-
action.stop();
|
|
448
|
-
action.reset();
|
|
449
|
-
action.enabled = true;
|
|
450
|
-
const duration = state.motion.clip.duration;
|
|
451
|
-
// if we are looping to the same state we don't want to offset the current start time
|
|
452
|
-
action.time = isSelf ? 0 : offsetNormalized * duration;
|
|
453
|
-
if (action.timeScale < 0)
|
|
454
|
-
action.time = duration - action.time;
|
|
455
|
-
action.clampWhenFinished = true;
|
|
456
|
-
action.setLoop(LoopOnce, 0);
|
|
457
|
-
if (durationInSec > 0)
|
|
458
|
-
action.fadeIn(durationInSec);
|
|
459
|
-
else
|
|
460
|
-
action.weight = 1;
|
|
461
|
-
action.play();
|
|
462
|
-
if (this.rootMotionHandler) {
|
|
463
|
-
this.rootMotionHandler.onStart(action);
|
|
464
|
-
}
|
|
465
|
-
if (!this._activeStates.includes(state))
|
|
466
|
-
this._activeStates.push(state);
|
|
467
|
-
// call enter state behaviours
|
|
468
|
-
if (this._activeState.behaviours) {
|
|
469
|
-
const info = new AnimatorStateInfo(state, offsetNormalized, duration, this._speed);
|
|
470
|
-
for (const beh of this._activeState.behaviours) {
|
|
471
|
-
beh.instance?.onStateEnter?.call(beh.instance, this.animator, info, layerIndex);
|
|
472
|
-
}
|
|
473
|
-
}
|
|
474
|
-
}
|
|
475
|
-
else if (debug) {
|
|
476
|
-
if (!state["__warned_no_motion"]) {
|
|
477
|
-
state["__warned_no_motion"] = true;
|
|
478
|
-
console.warn("No action", state.motion, this);
|
|
479
|
-
}
|
|
480
|
-
}
|
|
481
|
-
if (debug)
|
|
482
|
-
console.log("TRANSITION FROM " + prev?.name + " TO " + state.name, durationInSec, prevAction, action, action?.getEffectiveTimeScale(), action?.getEffectiveWeight(), action?.isRunning(), action?.isScheduled(), action?.paused);
|
|
483
|
-
}
|
|
484
|
-
createAction(clip) {
|
|
485
|
-
// uncache clip causes issues when multiple states use the same clip
|
|
486
|
-
// this._mixer.uncacheClip(clip);
|
|
487
|
-
// instead only uncache the action when one already exists to make sure
|
|
488
|
-
// we get unique actions per state
|
|
489
|
-
const existing = this._mixer.existingAction(clip);
|
|
490
|
-
if (existing)
|
|
491
|
-
this._mixer.uncacheAction(clip, this.animator?.gameObject);
|
|
492
|
-
if (this.animator?.applyRootMotion) {
|
|
493
|
-
if (!this.rootMotionHandler) {
|
|
494
|
-
this.rootMotionHandler = new RootMotionHandler(this);
|
|
495
|
-
}
|
|
496
|
-
// TODO: find root bone properly
|
|
497
|
-
const root = this.animator.gameObject;
|
|
498
|
-
return this.rootMotionHandler.createClip(this._mixer, root, clip);
|
|
499
|
-
}
|
|
500
|
-
else {
|
|
501
|
-
const action = this._mixer.clipAction(clip);
|
|
502
|
-
return action;
|
|
503
|
-
}
|
|
504
|
-
}
|
|
505
|
-
evaluateCondition(cond) {
|
|
506
|
-
const param = this.model.parameters.find(p => p.name === cond.parameter);
|
|
507
|
-
if (!param)
|
|
508
|
-
return false;
|
|
509
|
-
// console.log(param.name, param.value);
|
|
510
|
-
switch (cond.mode) {
|
|
511
|
-
case AnimatorConditionMode.If:
|
|
512
|
-
return param.value === true;
|
|
513
|
-
case AnimatorConditionMode.IfNot:
|
|
514
|
-
return param.value === false;
|
|
515
|
-
case AnimatorConditionMode.Greater:
|
|
516
|
-
return param.value > cond.threshold;
|
|
517
|
-
case AnimatorConditionMode.Less:
|
|
518
|
-
return param.value < cond.threshold;
|
|
519
|
-
case AnimatorConditionMode.Equals:
|
|
520
|
-
return param.value === cond.threshold;
|
|
521
|
-
case AnimatorConditionMode.NotEqual:
|
|
522
|
-
return param.value !== cond.threshold;
|
|
523
|
-
}
|
|
524
|
-
return false;
|
|
525
|
-
}
|
|
526
|
-
createActions(_animator) {
|
|
527
|
-
// console.trace(this.model, _animator);
|
|
528
|
-
for (const layer of this.model.layers) {
|
|
529
|
-
const sm = layer.stateMachine;
|
|
530
|
-
for (let index = 0; index < sm.states.length; index++) {
|
|
531
|
-
const state = sm.states[index];
|
|
532
|
-
// ensure we have a transitions array
|
|
533
|
-
if (!state.transitions) {
|
|
534
|
-
state.transitions = [];
|
|
535
|
-
}
|
|
536
|
-
for (const t of state.transitions) {
|
|
537
|
-
// can happen if conditions are empty in blender - the exporter seems to skip empty arrays
|
|
538
|
-
if (!t.conditions)
|
|
539
|
-
t.conditions = [];
|
|
540
|
-
}
|
|
541
|
-
// ensure we have a motion even if none was exported
|
|
542
|
-
if (!state.motion) {
|
|
543
|
-
state.motion = createMotion(state.name);
|
|
544
|
-
// console.warn("Missing motion", "AnimatorController: " + this.model.name, state);
|
|
545
|
-
// sm.states.splice(index, 1);
|
|
546
|
-
// index -= 1;
|
|
547
|
-
// continue;
|
|
548
|
-
}
|
|
549
|
-
// the clips array contains which animator has which animationclip
|
|
550
|
-
if (this.animator && state.motion.clips) {
|
|
551
|
-
// TODO: we have to compare by name because on instantiate we clone objects but not the node object
|
|
552
|
-
const mapping = state.motion.clips?.find(e => e.node.name === this.animator?.gameObject?.name);
|
|
553
|
-
// console.log(state.name, mapping?.clip);
|
|
554
|
-
state.motion.clip = mapping?.clip;
|
|
555
|
-
}
|
|
556
|
-
// ensure we have a clip to blend to
|
|
557
|
-
if (!state.motion.clip) {
|
|
558
|
-
const clip = new AnimationClip(undefined, undefined, []);
|
|
559
|
-
state.motion.clip = clip;
|
|
560
|
-
}
|
|
561
|
-
if (state.motion?.clip) {
|
|
562
|
-
const clip = state.motion.clip;
|
|
563
|
-
if (clip instanceof AnimationClip) {
|
|
564
|
-
const action = this.createAction(clip);
|
|
565
|
-
state.motion.action = action;
|
|
566
|
-
}
|
|
567
|
-
else {
|
|
568
|
-
if (debug || isDevEnvironment())
|
|
569
|
-
console.warn("No valid animationclip assigned", state);
|
|
570
|
-
}
|
|
571
|
-
}
|
|
572
|
-
// create state machine behaviours
|
|
573
|
-
if (state.behaviours && Array.isArray(state.behaviours)) {
|
|
574
|
-
for (const behaviour of state.behaviours) {
|
|
575
|
-
if (!behaviour?.typeName)
|
|
576
|
-
continue;
|
|
577
|
-
const type = TypeStore.get(behaviour.typeName);
|
|
578
|
-
const instance = new type();
|
|
579
|
-
if (instance.isStateMachineBehaviour) {
|
|
580
|
-
instance._context = this.context ?? undefined;
|
|
581
|
-
assign(instance, behaviour.properties);
|
|
582
|
-
behaviour.instance = instance;
|
|
583
|
-
}
|
|
584
|
-
if (debug)
|
|
585
|
-
console.log("Created animator controller behaviour", state.name, behaviour.typeName, behaviour.properties, instance);
|
|
586
|
-
}
|
|
587
|
-
}
|
|
588
|
-
}
|
|
589
|
-
}
|
|
590
|
-
}
|
|
591
|
-
*enumerateActions() {
|
|
592
|
-
if (!this.model.layers)
|
|
593
|
-
return;
|
|
594
|
-
for (const layer of this.model.layers) {
|
|
595
|
-
const sm = layer.stateMachine;
|
|
596
|
-
for (let index = 0; index < sm.states.length; index++) {
|
|
597
|
-
const state = sm.states[index];
|
|
598
|
-
if (state?.motion) {
|
|
599
|
-
if (state.motion.action)
|
|
600
|
-
yield state.motion.action;
|
|
601
|
-
if (state.motion.action_loopback)
|
|
602
|
-
yield state.motion.action_loopback;
|
|
603
|
-
}
|
|
604
|
-
}
|
|
605
|
-
}
|
|
606
|
-
}
|
|
607
|
-
// https://docs.unity3d.com/Manual/RootMotion.html
|
|
608
|
-
rootMotionHandler;
|
|
609
|
-
}
|
|
610
|
-
class TrackEvaluationWrapper {
|
|
611
|
-
track;
|
|
612
|
-
createdInterpolant;
|
|
613
|
-
originalEvaluate;
|
|
614
|
-
customEvaluate;
|
|
615
|
-
constructor(track, evaluate) {
|
|
616
|
-
this.track = track;
|
|
617
|
-
const t = track;
|
|
618
|
-
const createOriginalInterpolator = t.createInterpolant.bind(track);
|
|
619
|
-
t.createInterpolant = () => {
|
|
620
|
-
t.createInterpolant = createOriginalInterpolator;
|
|
621
|
-
this.createdInterpolant = createOriginalInterpolator();
|
|
622
|
-
this.originalEvaluate = this.createdInterpolant.evaluate.bind(this.createdInterpolant);
|
|
623
|
-
this.customEvaluate = time => {
|
|
624
|
-
if (!this.originalEvaluate)
|
|
625
|
-
return;
|
|
626
|
-
const res = this.originalEvaluate(time);
|
|
627
|
-
return evaluate(time, res);
|
|
628
|
-
};
|
|
629
|
-
this.createdInterpolant.evaluate = this.customEvaluate;
|
|
630
|
-
return this.createdInterpolant;
|
|
631
|
-
};
|
|
632
|
-
}
|
|
633
|
-
;
|
|
634
|
-
dispose() {
|
|
635
|
-
if (this.createdInterpolant && this.originalEvaluate) {
|
|
636
|
-
this.createdInterpolant.evaluate = this.originalEvaluate;
|
|
637
|
-
}
|
|
638
|
-
this.track = undefined;
|
|
639
|
-
this.createdInterpolant = null;
|
|
640
|
-
this.originalEvaluate = undefined;
|
|
641
|
-
this.customEvaluate = undefined;
|
|
642
|
-
}
|
|
643
|
-
}
|
|
644
|
-
class RootMotionAction {
|
|
645
|
-
static lastObjPosition = {};
|
|
646
|
-
static lastObjRotation = {};
|
|
647
|
-
// we remove the first keyframe rotation from the space rotation when updating
|
|
648
|
-
static firstKeyframeRotation = {};
|
|
649
|
-
// this is used to rotate the space on clip end / start (so the transform direction is correct)
|
|
650
|
-
static spaceRotation = {};
|
|
651
|
-
static effectiveSpaceRotation = {};
|
|
652
|
-
static clipOffsetRotation = {};
|
|
653
|
-
set action(val) {
|
|
654
|
-
this._action = val;
|
|
655
|
-
}
|
|
656
|
-
get action() {
|
|
657
|
-
return this._action;
|
|
658
|
-
}
|
|
659
|
-
get cacheId() {
|
|
660
|
-
return this.root.uuid;
|
|
661
|
-
}
|
|
662
|
-
_action;
|
|
663
|
-
root;
|
|
664
|
-
clip;
|
|
665
|
-
positionWrapper = null;
|
|
666
|
-
rotationWrapper = null;
|
|
667
|
-
context;
|
|
668
|
-
positionChange = new Vector3();
|
|
669
|
-
rotationChange = new Quaternion();
|
|
670
|
-
constructor(context, root, clip, positionTrack, rotationTrack) {
|
|
671
|
-
// console.log(this, positionTrack, rotationTrack);
|
|
672
|
-
this.context = context;
|
|
673
|
-
this.root = root;
|
|
674
|
-
this.clip = clip;
|
|
675
|
-
if (!RootMotionAction.firstKeyframeRotation[this.cacheId])
|
|
676
|
-
RootMotionAction.firstKeyframeRotation[this.cacheId] = new Quaternion();
|
|
677
|
-
if (rotationTrack) {
|
|
678
|
-
const values = rotationTrack.values;
|
|
679
|
-
RootMotionAction.firstKeyframeRotation[this.cacheId]
|
|
680
|
-
.set(values[0], values[1], values[2], values[3]);
|
|
681
|
-
}
|
|
682
|
-
if (!RootMotionAction.spaceRotation[this.cacheId])
|
|
683
|
-
RootMotionAction.spaceRotation[this.cacheId] = new Quaternion();
|
|
684
|
-
if (!RootMotionAction.effectiveSpaceRotation[this.cacheId])
|
|
685
|
-
RootMotionAction.effectiveSpaceRotation[this.cacheId] = new Quaternion();
|
|
686
|
-
RootMotionAction.clipOffsetRotation[this.cacheId] = new Quaternion();
|
|
687
|
-
if (rotationTrack) {
|
|
688
|
-
RootMotionAction.clipOffsetRotation[this.cacheId]
|
|
689
|
-
.set(rotationTrack.values[0], rotationTrack.values[1], rotationTrack.values[2], rotationTrack.values[3])
|
|
690
|
-
.invert();
|
|
691
|
-
}
|
|
692
|
-
this.handlePosition(clip, positionTrack);
|
|
693
|
-
this.handleRotation(clip, rotationTrack);
|
|
694
|
-
}
|
|
695
|
-
onStart(action) {
|
|
696
|
-
if (action.getClip() !== this.clip)
|
|
697
|
-
return;
|
|
698
|
-
if (!RootMotionAction.lastObjRotation[this.cacheId]) {
|
|
699
|
-
RootMotionAction.lastObjRotation[this.cacheId] = this.root.quaternion.clone();
|
|
700
|
-
}
|
|
701
|
-
const lastRotation = RootMotionAction.lastObjRotation[this.cacheId];
|
|
702
|
-
// const firstKeyframe = RootMotionAction.firstKeyframeRotation[this.this.cacheId];
|
|
703
|
-
// lastRotation.invert().premultiply(firstKeyframe).invert();
|
|
704
|
-
RootMotionAction.spaceRotation[this.cacheId].copy(lastRotation);
|
|
705
|
-
if (debugRootMotion) {
|
|
706
|
-
const euler = new Euler().setFromQuaternion(lastRotation);
|
|
707
|
-
console.log("START", this.clip.name, Mathf.toDegrees(euler.y), this.root.position.z);
|
|
708
|
-
}
|
|
709
|
-
}
|
|
710
|
-
getClipRotationOffset() {
|
|
711
|
-
return RootMotionAction.clipOffsetRotation[this.cacheId];
|
|
712
|
-
}
|
|
713
|
-
_prevTime = 0;
|
|
714
|
-
handlePosition(_clip, track) {
|
|
715
|
-
if (track) {
|
|
716
|
-
const root = this.root;
|
|
717
|
-
if (debugRootMotion)
|
|
718
|
-
root.add(new AxesHelper());
|
|
719
|
-
if (!RootMotionAction.lastObjPosition[this.cacheId])
|
|
720
|
-
RootMotionAction.lastObjPosition[this.cacheId] = this.root.position.clone();
|
|
721
|
-
const valuesDiff = new Vector3();
|
|
722
|
-
const valuesPrev = new Vector3();
|
|
723
|
-
// const rotation = new Quaternion();
|
|
724
|
-
this.positionWrapper = new TrackEvaluationWrapper(track, (time, value) => {
|
|
725
|
-
const weight = this.action.getEffectiveWeight();
|
|
726
|
-
// reset for testing
|
|
727
|
-
if (debugRootMotion) {
|
|
728
|
-
if (root.position.length() > 8)
|
|
729
|
-
root.position.set(0, root.position.y, 0);
|
|
730
|
-
}
|
|
731
|
-
if (time > this._prevTime) {
|
|
732
|
-
valuesDiff.set(value[0], value[1], value[2]);
|
|
733
|
-
valuesDiff.sub(valuesPrev);
|
|
734
|
-
valuesDiff.multiplyScalar(weight);
|
|
735
|
-
valuesDiff.applyQuaternion(this.getClipRotationOffset());
|
|
736
|
-
// RootMotionAction.effectiveSpaceRotation[id].slerp(RootMotionAction.spaceRotation[id], weight);
|
|
737
|
-
valuesDiff.applyQuaternion(root.quaternion);
|
|
738
|
-
this.positionChange.copy(valuesDiff);
|
|
739
|
-
// this.root.position.add(valuesDiff);
|
|
740
|
-
}
|
|
741
|
-
valuesPrev.fromArray(value);
|
|
742
|
-
this._prevTime = time;
|
|
743
|
-
value[0] = 0;
|
|
744
|
-
value[1] = 0;
|
|
745
|
-
value[2] = 0;
|
|
746
|
-
return value;
|
|
747
|
-
});
|
|
748
|
-
}
|
|
749
|
-
}
|
|
750
|
-
static identityQuaternion = new Quaternion();
|
|
751
|
-
handleRotation(clip, track) {
|
|
752
|
-
if (track) {
|
|
753
|
-
if (debugRootMotion) {
|
|
754
|
-
const arr = track.values;
|
|
755
|
-
const firstKeyframe = new Euler().setFromQuaternion(new Quaternion(arr[0], arr[1], arr[2], arr[3]));
|
|
756
|
-
console.log(clip.name, track.name, "FIRST ROTATION IN TRACK", Mathf.toDegrees(firstKeyframe.y));
|
|
757
|
-
const i = track.values.length - 4;
|
|
758
|
-
const lastKeyframe = new Quaternion().set(arr[i], arr[i + 1], arr[i + 2], arr[i + 3]);
|
|
759
|
-
const euler = new Euler().setFromQuaternion(lastKeyframe);
|
|
760
|
-
console.log(clip.name, track.name, "LAST ROTATION IN TRACK", Mathf.toDegrees(euler.y));
|
|
761
|
-
}
|
|
762
|
-
// if (!RootMotionAction.lastObjRotation[root.uuid]) RootMotionAction.lastObjRotation[root.uuid] = new Quaternion();
|
|
763
|
-
// const temp = new Quaternion();
|
|
764
|
-
let prevTime = 0;
|
|
765
|
-
const valuesPrev = new Quaternion();
|
|
766
|
-
const valuesDiff = new Quaternion();
|
|
767
|
-
// const summedRot = new Quaternion();
|
|
768
|
-
this.rotationWrapper = new TrackEvaluationWrapper(track, (time, value) => {
|
|
769
|
-
// root.quaternion.copy(RootMotionAction.lastObjRotation[root.uuid]);
|
|
770
|
-
if (time > prevTime) {
|
|
771
|
-
valuesDiff.set(value[0], value[1], value[2], value[3]);
|
|
772
|
-
valuesPrev.invert();
|
|
773
|
-
valuesDiff.multiply(valuesPrev);
|
|
774
|
-
// if(weight < .99) valuesDiff.slerp(RootMotionAction.identityQuaternion, 1 - weight);
|
|
775
|
-
this.rotationChange.copy(valuesDiff);
|
|
776
|
-
// root.quaternion.multiply(valuesDiff);
|
|
777
|
-
}
|
|
778
|
-
// else
|
|
779
|
-
// root.quaternion.multiply(this.getClipRotationOffset());
|
|
780
|
-
// RootMotionAction.lastObjRotation[root.uuid].copy(root.quaternion);
|
|
781
|
-
valuesPrev.fromArray(value);
|
|
782
|
-
prevTime = time;
|
|
783
|
-
value[0] = 0;
|
|
784
|
-
value[1] = 0;
|
|
785
|
-
value[2] = 0;
|
|
786
|
-
value[3] = 1;
|
|
787
|
-
return value;
|
|
788
|
-
});
|
|
789
|
-
}
|
|
790
|
-
}
|
|
791
|
-
// private lastPos: Vector3 = new Vector3();
|
|
792
|
-
onBeforeUpdate(_weight) {
|
|
793
|
-
this.positionChange.set(0, 0, 0);
|
|
794
|
-
this.rotationChange.set(0, 0, 0, 1);
|
|
795
|
-
}
|
|
796
|
-
onAfterUpdate(weight) {
|
|
797
|
-
if (!this.action)
|
|
798
|
-
return false;
|
|
799
|
-
weight *= this.action.getEffectiveWeight();
|
|
800
|
-
if (weight <= 0)
|
|
801
|
-
return false;
|
|
802
|
-
this.positionChange.multiplyScalar(weight);
|
|
803
|
-
this.rotationChange.slerp(RootMotionAction.identityQuaternion, 1 - weight);
|
|
804
|
-
return true;
|
|
805
|
-
}
|
|
806
|
-
}
|
|
807
|
-
class RootMotionHandler {
|
|
808
|
-
controller;
|
|
809
|
-
handler = [];
|
|
810
|
-
root;
|
|
811
|
-
basePosition = new Vector3();
|
|
812
|
-
baseQuaternion = new Quaternion();
|
|
813
|
-
baseRotation = new Euler();
|
|
814
|
-
constructor(controller) {
|
|
815
|
-
this.controller = controller;
|
|
816
|
-
}
|
|
817
|
-
createClip(mixer, root, clip) {
|
|
818
|
-
this.root = root;
|
|
819
|
-
let rootName = "";
|
|
820
|
-
if (root && "name" in root) {
|
|
821
|
-
rootName = root.name;
|
|
822
|
-
}
|
|
823
|
-
const positionTrack = this.findRootTrack(clip, ".position");
|
|
824
|
-
const rotationTrack = this.findRootTrack(clip, ".quaternion");
|
|
825
|
-
const handler = new RootMotionAction(this.controller.context, root, clip, positionTrack, rotationTrack);
|
|
826
|
-
this.handler.push(handler);
|
|
827
|
-
// it is important we do this after the handler is created
|
|
828
|
-
// otherwise we can not hook into threejs interpolators
|
|
829
|
-
const action = mixer.clipAction(clip);
|
|
830
|
-
handler.action = action;
|
|
831
|
-
return action;
|
|
832
|
-
}
|
|
833
|
-
onStart(action) {
|
|
834
|
-
for (const handler of this.handler) {
|
|
835
|
-
handler.onStart(action);
|
|
836
|
-
}
|
|
837
|
-
}
|
|
838
|
-
onBeforeUpdate(weight) {
|
|
839
|
-
// capture the position of the object
|
|
840
|
-
this.basePosition.copy(this.root.position);
|
|
841
|
-
this.baseQuaternion.copy(this.root.quaternion);
|
|
842
|
-
for (const hand of this.handler)
|
|
843
|
-
hand.onBeforeUpdate(weight);
|
|
844
|
-
}
|
|
845
|
-
summedPosition = new Vector3();
|
|
846
|
-
summedRotation = new Quaternion();
|
|
847
|
-
onAfterUpdate(weight) {
|
|
848
|
-
if (weight <= 0)
|
|
849
|
-
return;
|
|
850
|
-
// TODO: blend weight properly with root motion (when using timeline blending with animator)
|
|
851
|
-
// apply the accumulated changes
|
|
852
|
-
this.root.position.copy(this.basePosition);
|
|
853
|
-
this.root.quaternion.copy(this.baseQuaternion);
|
|
854
|
-
this.summedPosition.set(0, 0, 0);
|
|
855
|
-
this.summedRotation.set(0, 0, 0, 1);
|
|
856
|
-
for (const entry of this.handler) {
|
|
857
|
-
if (entry.onAfterUpdate(weight)) {
|
|
858
|
-
this.summedPosition.add(entry.positionChange);
|
|
859
|
-
this.summedRotation.multiply(entry.rotationChange);
|
|
860
|
-
}
|
|
861
|
-
}
|
|
862
|
-
this.root.position.add(this.summedPosition);
|
|
863
|
-
this.root.quaternion.multiply(this.summedRotation);
|
|
864
|
-
// RootMotionAction.lastObjRotation[this.root.uuid].copy(this.root.quaternion);
|
|
865
|
-
}
|
|
866
|
-
findRootTrack(clip, name) {
|
|
867
|
-
const tracks = clip.tracks;
|
|
868
|
-
if (!tracks)
|
|
869
|
-
return null;
|
|
870
|
-
for (const track of tracks) {
|
|
871
|
-
if (track.name.endsWith(name)) {
|
|
872
|
-
return track;
|
|
873
|
-
}
|
|
874
|
-
}
|
|
875
|
-
return null;
|
|
876
|
-
}
|
|
877
|
-
}
|
|
878
|
-
class AnimatorControllerSerializator extends TypeSerializer {
|
|
879
|
-
onSerialize(_, _context) {
|
|
880
|
-
}
|
|
881
|
-
onDeserialize(data, context) {
|
|
882
|
-
if (context.type === AnimatorController && data?.__type === "AnimatorController")
|
|
883
|
-
return new AnimatorController(data);
|
|
884
|
-
return undefined;
|
|
885
|
-
}
|
|
886
|
-
}
|
|
887
|
-
new AnimatorControllerSerializator(AnimatorController);
|
|
1
|
+
import { AnimatorConditionMode, AnimatorControllerParameterType, AnimatorStateInfo, createMotion } from "../engine/extensions/NEEDLE_animator_controller_model.js";
|
|
2
|
+
import { AnimationClip, AnimationMixer, AxesHelper, Euler, LoopOnce, Quaternion, Vector3 } from "three";
|
|
3
|
+
import { deepClone, getParam } from "../engine/engine_utils.js";
|
|
4
|
+
import { TypeStore } from "../engine/engine_typestore.js";
|
|
5
|
+
import { TypeSerializer, assign } from "../engine/engine_serialization_core.js";
|
|
6
|
+
import { Mathf } from "../engine/engine_math.js";
|
|
7
|
+
import { isAnimationAction } from "../engine/engine_three_utils.js";
|
|
8
|
+
import { isDevEnvironment } from "../engine/debug/index.js";
|
|
9
|
+
import { InstantiateIdProvider } from "../engine/engine_networking_instantiate.js";
|
|
10
|
+
const debug = getParam("debuganimatorcontroller");
|
|
11
|
+
const debugRootMotion = getParam("debugrootmotion");
|
|
12
|
+
function stringToHash(str) {
|
|
13
|
+
let hash = 0;
|
|
14
|
+
for (let i = 0; i < str.length; i++) {
|
|
15
|
+
const char = str.charCodeAt(i);
|
|
16
|
+
hash = ((hash << 5) - hash) + char;
|
|
17
|
+
hash = hash & hash;
|
|
18
|
+
}
|
|
19
|
+
return hash;
|
|
20
|
+
}
|
|
21
|
+
export class AnimatorController {
|
|
22
|
+
/** Create an animatorcontroller with clips assigned */
|
|
23
|
+
static createFromClips(clips, options = { looping: false, autoTransition: true, transitionDuration: 0 }) {
|
|
24
|
+
const states = [];
|
|
25
|
+
for (let i = 0; i < clips.length; i++) {
|
|
26
|
+
const clip = clips[i];
|
|
27
|
+
const transitions = [];
|
|
28
|
+
if (options.autoTransition !== false) {
|
|
29
|
+
const dur = options.transitionDuration ?? 0;
|
|
30
|
+
const normalizedDuration = dur / clip.duration;
|
|
31
|
+
// automatically transition to self by default
|
|
32
|
+
let nextState = i;
|
|
33
|
+
if (options.autoTransition === undefined || options.autoTransition === true) {
|
|
34
|
+
nextState = (i + 1) % clips.length;
|
|
35
|
+
}
|
|
36
|
+
transitions.push({
|
|
37
|
+
exitTime: 1 - normalizedDuration,
|
|
38
|
+
offset: 0,
|
|
39
|
+
duration: dur,
|
|
40
|
+
hasExitTime: true,
|
|
41
|
+
destinationState: nextState,
|
|
42
|
+
conditions: [],
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
const state = {
|
|
46
|
+
name: clip.name,
|
|
47
|
+
hash: i,
|
|
48
|
+
motion: {
|
|
49
|
+
name: clip.name,
|
|
50
|
+
clip: clip,
|
|
51
|
+
isLooping: options?.looping ?? false,
|
|
52
|
+
},
|
|
53
|
+
transitions: transitions,
|
|
54
|
+
behaviours: []
|
|
55
|
+
};
|
|
56
|
+
states.push(state);
|
|
57
|
+
}
|
|
58
|
+
const model = {
|
|
59
|
+
name: "AnimatorController",
|
|
60
|
+
guid: new InstantiateIdProvider(Date.now()).generateUUID(),
|
|
61
|
+
parameters: [],
|
|
62
|
+
layers: [{
|
|
63
|
+
name: "Base Layer",
|
|
64
|
+
stateMachine: {
|
|
65
|
+
defaultState: 0,
|
|
66
|
+
states: states
|
|
67
|
+
}
|
|
68
|
+
}]
|
|
69
|
+
};
|
|
70
|
+
const controller = new AnimatorController(model);
|
|
71
|
+
return controller;
|
|
72
|
+
}
|
|
73
|
+
play(name, layerIndex = -1, normalizedTime = Number.NEGATIVE_INFINITY, durationInSec = 0) {
|
|
74
|
+
if (layerIndex < 0)
|
|
75
|
+
layerIndex = 0;
|
|
76
|
+
else if (layerIndex >= this.model.layers.length) {
|
|
77
|
+
console.warn("invalid layer");
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
const layer = this.model.layers[layerIndex];
|
|
81
|
+
const sm = layer.stateMachine;
|
|
82
|
+
for (const state of sm.states) {
|
|
83
|
+
if (state.name === name || state.hash === name) {
|
|
84
|
+
if (debug)
|
|
85
|
+
console.log("transition to ", state);
|
|
86
|
+
this.transitionTo(state, durationInSec, normalizedTime);
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
console.warn("Could not find " + name + " to play");
|
|
91
|
+
}
|
|
92
|
+
reset() {
|
|
93
|
+
this.setStartTransition();
|
|
94
|
+
}
|
|
95
|
+
setBool(name, value) {
|
|
96
|
+
const key = typeof name === "string" ? "name" : "hash";
|
|
97
|
+
return this.model?.parameters?.filter(p => p[key] === name).forEach(p => p.value = value);
|
|
98
|
+
}
|
|
99
|
+
getBool(name) {
|
|
100
|
+
const key = typeof name === "string" ? "name" : "hash";
|
|
101
|
+
return this.model?.parameters?.find(p => p[key] === name)?.value ?? false;
|
|
102
|
+
}
|
|
103
|
+
setFloat(name, val) {
|
|
104
|
+
const key = typeof name === "string" ? "name" : "hash";
|
|
105
|
+
const filtered = this.model?.parameters?.filter(p => p[key] === name);
|
|
106
|
+
filtered.forEach(p => p.value = val);
|
|
107
|
+
return filtered?.length > 0;
|
|
108
|
+
}
|
|
109
|
+
getFloat(name) {
|
|
110
|
+
const key = typeof name === "string" ? "name" : "hash";
|
|
111
|
+
return this.model?.parameters?.find(p => p[key] === name)?.value ?? 0;
|
|
112
|
+
}
|
|
113
|
+
setInteger(name, val) {
|
|
114
|
+
const key = typeof name === "string" ? "name" : "hash";
|
|
115
|
+
return this.model?.parameters?.filter(p => p[key] === name).forEach(p => p.value = val);
|
|
116
|
+
}
|
|
117
|
+
getInteger(name) {
|
|
118
|
+
const key = typeof name === "string" ? "name" : "hash";
|
|
119
|
+
return this.model?.parameters?.find(p => p[key] === name)?.value ?? 0;
|
|
120
|
+
}
|
|
121
|
+
setTrigger(name) {
|
|
122
|
+
if (debug)
|
|
123
|
+
console.log("SET TRIGGER", name);
|
|
124
|
+
const key = typeof name === "string" ? "name" : "hash";
|
|
125
|
+
return this.model?.parameters?.filter(p => p[key] === name).forEach(p => p.value = true);
|
|
126
|
+
}
|
|
127
|
+
resetTrigger(name) {
|
|
128
|
+
const key = typeof name === "string" ? "name" : "hash";
|
|
129
|
+
return this.model?.parameters?.filter(p => p[key] === name).forEach(p => p.value = false);
|
|
130
|
+
}
|
|
131
|
+
getTrigger(name) {
|
|
132
|
+
const key = typeof name === "string" ? "name" : "hash";
|
|
133
|
+
return this.model?.parameters?.find(p => p[key] === name)?.value ?? false;
|
|
134
|
+
}
|
|
135
|
+
isInTransition() {
|
|
136
|
+
return this._activeStates.length > 1;
|
|
137
|
+
}
|
|
138
|
+
setSpeed(speed) {
|
|
139
|
+
this._speed = speed;
|
|
140
|
+
}
|
|
141
|
+
/**@deprecated use findState */
|
|
142
|
+
FindState(name) { return this.findState(name); }
|
|
143
|
+
findState(name) {
|
|
144
|
+
if (!name)
|
|
145
|
+
return null;
|
|
146
|
+
if (Array.isArray(this.model.layers)) {
|
|
147
|
+
for (const layer of this.model.layers) {
|
|
148
|
+
for (const state of layer.stateMachine.states) {
|
|
149
|
+
if (state.name === name || state.hash == name)
|
|
150
|
+
return state;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
156
|
+
normalizedStartOffset = 0;
|
|
157
|
+
_speed = 1;
|
|
158
|
+
animator;
|
|
159
|
+
model;
|
|
160
|
+
get context() { return this.animator?.context; }
|
|
161
|
+
get mixer() {
|
|
162
|
+
return this._mixer;
|
|
163
|
+
}
|
|
164
|
+
// applyRootMotion(obj: Object3D) {
|
|
165
|
+
// // this.internalApplyRootMotion(obj);
|
|
166
|
+
// }
|
|
167
|
+
bind(animator) {
|
|
168
|
+
if (!animator)
|
|
169
|
+
console.error("AnimatorController.bind: animator is null");
|
|
170
|
+
else if (this.animator !== animator) {
|
|
171
|
+
this.animator = animator;
|
|
172
|
+
this._mixer = new AnimationMixer(this.animator.gameObject);
|
|
173
|
+
this.createActions(this.animator);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
clone() {
|
|
177
|
+
if (typeof this.model === "string") {
|
|
178
|
+
console.warn("AnimatorController has not been resolved, can not create model from string", this.model);
|
|
179
|
+
return null;
|
|
180
|
+
}
|
|
181
|
+
// clone runtime controller but dont clone clip or action
|
|
182
|
+
const clonedModel = deepClone(this.model, (_owner, _key, _value) => {
|
|
183
|
+
if (_value === null || _value === undefined)
|
|
184
|
+
return true;
|
|
185
|
+
// dont clone three Objects
|
|
186
|
+
if (_value.type === "Object3D" || _value.isObject3D === true)
|
|
187
|
+
return false;
|
|
188
|
+
// dont clone AnimationAction
|
|
189
|
+
if (isAnimationAction(_value)) { //.constructor.name === "AnimationAction") {
|
|
190
|
+
// console.log(_value);
|
|
191
|
+
return false;
|
|
192
|
+
}
|
|
193
|
+
// dont clone AnimationClip
|
|
194
|
+
if (_value["tracks"] !== undefined)
|
|
195
|
+
return false;
|
|
196
|
+
return true;
|
|
197
|
+
});
|
|
198
|
+
console.assert(clonedModel !== this.model);
|
|
199
|
+
const controller = new AnimatorController(clonedModel);
|
|
200
|
+
return controller;
|
|
201
|
+
}
|
|
202
|
+
update(weight) {
|
|
203
|
+
if (!this.animator)
|
|
204
|
+
return;
|
|
205
|
+
this.evaluateTransitions();
|
|
206
|
+
this.updateActiveStates(weight);
|
|
207
|
+
// 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)
|
|
208
|
+
// if (!this._activeState) return;
|
|
209
|
+
const dt = this.animator.context.time.deltaTime;
|
|
210
|
+
if (this.animator.applyRootMotion) {
|
|
211
|
+
this.rootMotionHandler?.onBeforeUpdate(weight);
|
|
212
|
+
}
|
|
213
|
+
this._mixer.update(dt);
|
|
214
|
+
if (this.animator.applyRootMotion) {
|
|
215
|
+
this.rootMotionHandler?.onAfterUpdate(weight);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
_mixer;
|
|
219
|
+
_activeState;
|
|
220
|
+
get activeState() { return this._activeState; }
|
|
221
|
+
constructor(model) {
|
|
222
|
+
this.model = model;
|
|
223
|
+
if (debug)
|
|
224
|
+
console.log(this);
|
|
225
|
+
}
|
|
226
|
+
_activeStates = [];
|
|
227
|
+
updateActiveStates(weight) {
|
|
228
|
+
for (let i = 0; i < this._activeStates.length; i++) {
|
|
229
|
+
const state = this._activeStates[i];
|
|
230
|
+
const motion = state.motion;
|
|
231
|
+
if (!motion.action) {
|
|
232
|
+
this._activeStates.splice(i, 1);
|
|
233
|
+
i--;
|
|
234
|
+
}
|
|
235
|
+
else {
|
|
236
|
+
const action = motion.action;
|
|
237
|
+
action.weight = weight;
|
|
238
|
+
// console.log(action.getClip().name, action.getEffectiveWeight(), action.isScheduled());
|
|
239
|
+
if ((action.getEffectiveWeight() <= 0 && !action.isRunning())) {
|
|
240
|
+
if (debug)
|
|
241
|
+
console.debug("REMOVE", state.name, action.getEffectiveWeight(), action.isRunning(), action.isScheduled());
|
|
242
|
+
this._activeStates.splice(i, 1);
|
|
243
|
+
i--;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
setStartTransition() {
|
|
249
|
+
for (const layer of this.model.layers) {
|
|
250
|
+
const sm = layer.stateMachine;
|
|
251
|
+
if (sm.defaultState === undefined) {
|
|
252
|
+
if (debug)
|
|
253
|
+
console.warn("AnimatorController default state is undefined, will assign state 0 as default", layer);
|
|
254
|
+
sm.defaultState = 0;
|
|
255
|
+
}
|
|
256
|
+
const start = sm.states[sm.defaultState];
|
|
257
|
+
this.transitionTo(start, 0, this.normalizedStartOffset);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
evaluateTransitions() {
|
|
261
|
+
let didEnterStateThisFrame = false;
|
|
262
|
+
if (!this._activeState) {
|
|
263
|
+
this.setStartTransition();
|
|
264
|
+
if (!this._activeState)
|
|
265
|
+
return;
|
|
266
|
+
didEnterStateThisFrame = true;
|
|
267
|
+
}
|
|
268
|
+
const state = this._activeState;
|
|
269
|
+
const action = state.motion.action;
|
|
270
|
+
let index = 0;
|
|
271
|
+
for (const transition of state.transitions) {
|
|
272
|
+
++index;
|
|
273
|
+
// transition without exit time and without condition that transition to itself are ignored
|
|
274
|
+
if (!transition.hasExitTime && transition.conditions.length <= 0) {
|
|
275
|
+
// if (this._activeState && this.getState(transition.destinationState, currentLayer)?.hash === this._activeState.hash)
|
|
276
|
+
continue;
|
|
277
|
+
}
|
|
278
|
+
let allConditionsAreMet = true;
|
|
279
|
+
for (const cond of transition.conditions) {
|
|
280
|
+
if (!this.evaluateCondition(cond)) {
|
|
281
|
+
allConditionsAreMet = false;
|
|
282
|
+
break;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
if (!allConditionsAreMet)
|
|
286
|
+
continue;
|
|
287
|
+
if (debug && allConditionsAreMet) {
|
|
288
|
+
// console.log("All conditions are met", transition);
|
|
289
|
+
}
|
|
290
|
+
if (action) {
|
|
291
|
+
const dur = state.motion.clip.duration;
|
|
292
|
+
const normalizedTime = dur <= 0 ? 1 : Math.abs(action.time / dur);
|
|
293
|
+
let makeTransition = false;
|
|
294
|
+
if (transition.hasExitTime) {
|
|
295
|
+
if (action.timeScale > 0)
|
|
296
|
+
makeTransition = normalizedTime >= transition.exitTime;
|
|
297
|
+
// When the animation is playing backwards we need to check exit time inverted
|
|
298
|
+
else if (action.timeScale < 0)
|
|
299
|
+
makeTransition = 1 - normalizedTime >= transition.exitTime;
|
|
300
|
+
}
|
|
301
|
+
else {
|
|
302
|
+
makeTransition = true;
|
|
303
|
+
}
|
|
304
|
+
if (makeTransition) {
|
|
305
|
+
// disable triggers for this transition
|
|
306
|
+
for (const cond of transition.conditions) {
|
|
307
|
+
const param = this.model.parameters.find(p => p.name === cond.parameter);
|
|
308
|
+
if (param?.type === AnimatorControllerParameterType.Trigger && param.value) {
|
|
309
|
+
param.value = false;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
// if (transition.hasExitTime && transition.exitTime >= .9999)
|
|
313
|
+
action.clampWhenFinished = true;
|
|
314
|
+
// else action.clampWhenFinished = false;
|
|
315
|
+
if (debug) {
|
|
316
|
+
console.log("transition to " + transition.destinationState, transition, normalizedTime, transition.exitTime, transition.hasExitTime);
|
|
317
|
+
// console.log(action.time, transition.exitTime);
|
|
318
|
+
}
|
|
319
|
+
this.transitionTo(transition.destinationState, transition.duration, transition.offset);
|
|
320
|
+
// use the first transition that matches all conditions and make the transition as soon as in range
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
else {
|
|
325
|
+
this.transitionTo(transition.destinationState, transition.duration, transition.offset);
|
|
326
|
+
return;
|
|
327
|
+
}
|
|
328
|
+
// if none of the transitions can be made continue searching for another transition meeting the conditions
|
|
329
|
+
}
|
|
330
|
+
// action.time += this.context.time.deltaTime
|
|
331
|
+
// console.log(action?.time, action?.getEffectiveWeight())
|
|
332
|
+
// update timescale
|
|
333
|
+
if (action) {
|
|
334
|
+
let speedFactor = state.speed ?? 1;
|
|
335
|
+
if (state.speedParameter)
|
|
336
|
+
speedFactor *= this.getFloat(state.speedParameter);
|
|
337
|
+
if (speedFactor !== undefined) {
|
|
338
|
+
action.timeScale = speedFactor * this._speed;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
let didTriggerLooping = false;
|
|
342
|
+
if (state.motion.isLooping && action) {
|
|
343
|
+
// we dont use the three loop state here because it prevents the transition check above
|
|
344
|
+
// it is easier if we re-trigger loop here.
|
|
345
|
+
// We also can easily add the cycle offset settings from unity later
|
|
346
|
+
if (action.time >= action.getClip().duration) {
|
|
347
|
+
didTriggerLooping = true;
|
|
348
|
+
action.reset();
|
|
349
|
+
action.time = 0;
|
|
350
|
+
action.play();
|
|
351
|
+
}
|
|
352
|
+
else if (action.time <= 0 && action.timeScale < 0) {
|
|
353
|
+
didTriggerLooping = true;
|
|
354
|
+
action.reset();
|
|
355
|
+
action.time = action.getClip().duration;
|
|
356
|
+
action.play();
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
// call update state behaviours:
|
|
360
|
+
if (!didTriggerLooping && state && !didEnterStateThisFrame && action && this.animator) {
|
|
361
|
+
if (state.behaviours) {
|
|
362
|
+
const duration = action?.getClip().duration;
|
|
363
|
+
const normalizedTime = action.time / duration;
|
|
364
|
+
const info = new AnimatorStateInfo(this._activeState, normalizedTime, duration, this._speed);
|
|
365
|
+
for (const beh of state.behaviours) {
|
|
366
|
+
if (beh.instance) {
|
|
367
|
+
beh.instance.onStateUpdate?.call(beh.instance, this.animator, info, 0);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
getState(state, layerIndex) {
|
|
374
|
+
if (typeof state === "number") {
|
|
375
|
+
if (state == -1) {
|
|
376
|
+
state = this.model.layers[layerIndex].stateMachine.defaultState; // exit state -> entry state
|
|
377
|
+
if (state === undefined) {
|
|
378
|
+
if (debug)
|
|
379
|
+
console.warn("AnimatorController default state is undefined: ", this.model, "Layer: " + layerIndex);
|
|
380
|
+
state = 0;
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
state = this.model.layers[layerIndex].stateMachine.states[state];
|
|
384
|
+
}
|
|
385
|
+
return state;
|
|
386
|
+
}
|
|
387
|
+
transitionTo(state, durationInSec, offsetNormalized) {
|
|
388
|
+
if (!this.animator)
|
|
389
|
+
return;
|
|
390
|
+
const layerIndex = 0;
|
|
391
|
+
state = this.getState(state, layerIndex);
|
|
392
|
+
if (!state?.motion || !state.motion.clip || !(state.motion.clip instanceof AnimationClip)) {
|
|
393
|
+
// if(debug) console.warn("State has no clip or motion", state);
|
|
394
|
+
return;
|
|
395
|
+
}
|
|
396
|
+
const isSelf = this._activeState === state;
|
|
397
|
+
if (isSelf) {
|
|
398
|
+
const motion = state.motion;
|
|
399
|
+
if (!motion.action_loopback && motion.clip) {
|
|
400
|
+
// uncache action immediately resets the applied animation which breaks the root motion
|
|
401
|
+
// this happens if we have a transition to self and the clip is not cached yet
|
|
402
|
+
const previousMatrix = this.rootMotionHandler ? this.animator.gameObject.matrix.clone() : null;
|
|
403
|
+
this._mixer.uncacheAction(motion.clip, this.animator.gameObject);
|
|
404
|
+
if (previousMatrix)
|
|
405
|
+
previousMatrix.decompose(this.animator.gameObject.position, this.animator.gameObject.quaternion, this.animator.gameObject.scale);
|
|
406
|
+
motion.action_loopback = this.createAction(motion.clip);
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
// call exit state behaviours
|
|
410
|
+
if (this._activeState?.behaviours && this._activeState.motion.action) {
|
|
411
|
+
const duration = this._activeState?.motion.clip.duration;
|
|
412
|
+
const normalizedTime = this._activeState.motion.action.time / duration;
|
|
413
|
+
const info = new AnimatorStateInfo(this._activeState, normalizedTime, duration, this._speed);
|
|
414
|
+
for (const beh of this._activeState.behaviours) {
|
|
415
|
+
beh.instance?.onStateExit?.call(beh.instance, this.animator, info, layerIndex);
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
const prevAction = this._activeState?.motion.action;
|
|
419
|
+
if (prevAction) {
|
|
420
|
+
prevAction.fadeOut(durationInSec);
|
|
421
|
+
}
|
|
422
|
+
if (isSelf) {
|
|
423
|
+
state.motion.action = state.motion.action_loopback;
|
|
424
|
+
state.motion.action_loopback = prevAction;
|
|
425
|
+
}
|
|
426
|
+
const prev = this._activeState;
|
|
427
|
+
this._activeState = state;
|
|
428
|
+
const action = state.motion?.action;
|
|
429
|
+
if (action) {
|
|
430
|
+
offsetNormalized = Math.max(0, Math.min(1, offsetNormalized));
|
|
431
|
+
if (state.cycleOffsetParameter) {
|
|
432
|
+
let val = this.getFloat(state.cycleOffsetParameter);
|
|
433
|
+
if (typeof val === "number") {
|
|
434
|
+
if (val < 0)
|
|
435
|
+
val += 1;
|
|
436
|
+
offsetNormalized += val;
|
|
437
|
+
offsetNormalized %= 1;
|
|
438
|
+
}
|
|
439
|
+
else if (debug)
|
|
440
|
+
console.warn("AnimatorController cycle offset parameter is not a number", state.cycleOffsetParameter);
|
|
441
|
+
}
|
|
442
|
+
else if (typeof state.cycleOffset === "number") {
|
|
443
|
+
offsetNormalized += state.cycleOffset;
|
|
444
|
+
offsetNormalized %= 1;
|
|
445
|
+
}
|
|
446
|
+
if (action.isRunning())
|
|
447
|
+
action.stop();
|
|
448
|
+
action.reset();
|
|
449
|
+
action.enabled = true;
|
|
450
|
+
const duration = state.motion.clip.duration;
|
|
451
|
+
// if we are looping to the same state we don't want to offset the current start time
|
|
452
|
+
action.time = isSelf ? 0 : offsetNormalized * duration;
|
|
453
|
+
if (action.timeScale < 0)
|
|
454
|
+
action.time = duration - action.time;
|
|
455
|
+
action.clampWhenFinished = true;
|
|
456
|
+
action.setLoop(LoopOnce, 0);
|
|
457
|
+
if (durationInSec > 0)
|
|
458
|
+
action.fadeIn(durationInSec);
|
|
459
|
+
else
|
|
460
|
+
action.weight = 1;
|
|
461
|
+
action.play();
|
|
462
|
+
if (this.rootMotionHandler) {
|
|
463
|
+
this.rootMotionHandler.onStart(action);
|
|
464
|
+
}
|
|
465
|
+
if (!this._activeStates.includes(state))
|
|
466
|
+
this._activeStates.push(state);
|
|
467
|
+
// call enter state behaviours
|
|
468
|
+
if (this._activeState.behaviours) {
|
|
469
|
+
const info = new AnimatorStateInfo(state, offsetNormalized, duration, this._speed);
|
|
470
|
+
for (const beh of this._activeState.behaviours) {
|
|
471
|
+
beh.instance?.onStateEnter?.call(beh.instance, this.animator, info, layerIndex);
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
else if (debug) {
|
|
476
|
+
if (!state["__warned_no_motion"]) {
|
|
477
|
+
state["__warned_no_motion"] = true;
|
|
478
|
+
console.warn("No action", state.motion, this);
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
if (debug)
|
|
482
|
+
console.log("TRANSITION FROM " + prev?.name + " TO " + state.name, durationInSec, prevAction, action, action?.getEffectiveTimeScale(), action?.getEffectiveWeight(), action?.isRunning(), action?.isScheduled(), action?.paused);
|
|
483
|
+
}
|
|
484
|
+
createAction(clip) {
|
|
485
|
+
// uncache clip causes issues when multiple states use the same clip
|
|
486
|
+
// this._mixer.uncacheClip(clip);
|
|
487
|
+
// instead only uncache the action when one already exists to make sure
|
|
488
|
+
// we get unique actions per state
|
|
489
|
+
const existing = this._mixer.existingAction(clip);
|
|
490
|
+
if (existing)
|
|
491
|
+
this._mixer.uncacheAction(clip, this.animator?.gameObject);
|
|
492
|
+
if (this.animator?.applyRootMotion) {
|
|
493
|
+
if (!this.rootMotionHandler) {
|
|
494
|
+
this.rootMotionHandler = new RootMotionHandler(this);
|
|
495
|
+
}
|
|
496
|
+
// TODO: find root bone properly
|
|
497
|
+
const root = this.animator.gameObject;
|
|
498
|
+
return this.rootMotionHandler.createClip(this._mixer, root, clip);
|
|
499
|
+
}
|
|
500
|
+
else {
|
|
501
|
+
const action = this._mixer.clipAction(clip);
|
|
502
|
+
return action;
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
evaluateCondition(cond) {
|
|
506
|
+
const param = this.model.parameters.find(p => p.name === cond.parameter);
|
|
507
|
+
if (!param)
|
|
508
|
+
return false;
|
|
509
|
+
// console.log(param.name, param.value);
|
|
510
|
+
switch (cond.mode) {
|
|
511
|
+
case AnimatorConditionMode.If:
|
|
512
|
+
return param.value === true;
|
|
513
|
+
case AnimatorConditionMode.IfNot:
|
|
514
|
+
return param.value === false;
|
|
515
|
+
case AnimatorConditionMode.Greater:
|
|
516
|
+
return param.value > cond.threshold;
|
|
517
|
+
case AnimatorConditionMode.Less:
|
|
518
|
+
return param.value < cond.threshold;
|
|
519
|
+
case AnimatorConditionMode.Equals:
|
|
520
|
+
return param.value === cond.threshold;
|
|
521
|
+
case AnimatorConditionMode.NotEqual:
|
|
522
|
+
return param.value !== cond.threshold;
|
|
523
|
+
}
|
|
524
|
+
return false;
|
|
525
|
+
}
|
|
526
|
+
createActions(_animator) {
|
|
527
|
+
// console.trace(this.model, _animator);
|
|
528
|
+
for (const layer of this.model.layers) {
|
|
529
|
+
const sm = layer.stateMachine;
|
|
530
|
+
for (let index = 0; index < sm.states.length; index++) {
|
|
531
|
+
const state = sm.states[index];
|
|
532
|
+
// ensure we have a transitions array
|
|
533
|
+
if (!state.transitions) {
|
|
534
|
+
state.transitions = [];
|
|
535
|
+
}
|
|
536
|
+
for (const t of state.transitions) {
|
|
537
|
+
// can happen if conditions are empty in blender - the exporter seems to skip empty arrays
|
|
538
|
+
if (!t.conditions)
|
|
539
|
+
t.conditions = [];
|
|
540
|
+
}
|
|
541
|
+
// ensure we have a motion even if none was exported
|
|
542
|
+
if (!state.motion) {
|
|
543
|
+
state.motion = createMotion(state.name);
|
|
544
|
+
// console.warn("Missing motion", "AnimatorController: " + this.model.name, state);
|
|
545
|
+
// sm.states.splice(index, 1);
|
|
546
|
+
// index -= 1;
|
|
547
|
+
// continue;
|
|
548
|
+
}
|
|
549
|
+
// the clips array contains which animator has which animationclip
|
|
550
|
+
if (this.animator && state.motion.clips) {
|
|
551
|
+
// TODO: we have to compare by name because on instantiate we clone objects but not the node object
|
|
552
|
+
const mapping = state.motion.clips?.find(e => e.node.name === this.animator?.gameObject?.name);
|
|
553
|
+
// console.log(state.name, mapping?.clip);
|
|
554
|
+
state.motion.clip = mapping?.clip;
|
|
555
|
+
}
|
|
556
|
+
// ensure we have a clip to blend to
|
|
557
|
+
if (!state.motion.clip) {
|
|
558
|
+
const clip = new AnimationClip(undefined, undefined, []);
|
|
559
|
+
state.motion.clip = clip;
|
|
560
|
+
}
|
|
561
|
+
if (state.motion?.clip) {
|
|
562
|
+
const clip = state.motion.clip;
|
|
563
|
+
if (clip instanceof AnimationClip) {
|
|
564
|
+
const action = this.createAction(clip);
|
|
565
|
+
state.motion.action = action;
|
|
566
|
+
}
|
|
567
|
+
else {
|
|
568
|
+
if (debug || isDevEnvironment())
|
|
569
|
+
console.warn("No valid animationclip assigned", state);
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
// create state machine behaviours
|
|
573
|
+
if (state.behaviours && Array.isArray(state.behaviours)) {
|
|
574
|
+
for (const behaviour of state.behaviours) {
|
|
575
|
+
if (!behaviour?.typeName)
|
|
576
|
+
continue;
|
|
577
|
+
const type = TypeStore.get(behaviour.typeName);
|
|
578
|
+
const instance = new type();
|
|
579
|
+
if (instance.isStateMachineBehaviour) {
|
|
580
|
+
instance._context = this.context ?? undefined;
|
|
581
|
+
assign(instance, behaviour.properties);
|
|
582
|
+
behaviour.instance = instance;
|
|
583
|
+
}
|
|
584
|
+
if (debug)
|
|
585
|
+
console.log("Created animator controller behaviour", state.name, behaviour.typeName, behaviour.properties, instance);
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
*enumerateActions() {
|
|
592
|
+
if (!this.model.layers)
|
|
593
|
+
return;
|
|
594
|
+
for (const layer of this.model.layers) {
|
|
595
|
+
const sm = layer.stateMachine;
|
|
596
|
+
for (let index = 0; index < sm.states.length; index++) {
|
|
597
|
+
const state = sm.states[index];
|
|
598
|
+
if (state?.motion) {
|
|
599
|
+
if (state.motion.action)
|
|
600
|
+
yield state.motion.action;
|
|
601
|
+
if (state.motion.action_loopback)
|
|
602
|
+
yield state.motion.action_loopback;
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
// https://docs.unity3d.com/Manual/RootMotion.html
|
|
608
|
+
rootMotionHandler;
|
|
609
|
+
}
|
|
610
|
+
class TrackEvaluationWrapper {
|
|
611
|
+
track;
|
|
612
|
+
createdInterpolant;
|
|
613
|
+
originalEvaluate;
|
|
614
|
+
customEvaluate;
|
|
615
|
+
constructor(track, evaluate) {
|
|
616
|
+
this.track = track;
|
|
617
|
+
const t = track;
|
|
618
|
+
const createOriginalInterpolator = t.createInterpolant.bind(track);
|
|
619
|
+
t.createInterpolant = () => {
|
|
620
|
+
t.createInterpolant = createOriginalInterpolator;
|
|
621
|
+
this.createdInterpolant = createOriginalInterpolator();
|
|
622
|
+
this.originalEvaluate = this.createdInterpolant.evaluate.bind(this.createdInterpolant);
|
|
623
|
+
this.customEvaluate = time => {
|
|
624
|
+
if (!this.originalEvaluate)
|
|
625
|
+
return;
|
|
626
|
+
const res = this.originalEvaluate(time);
|
|
627
|
+
return evaluate(time, res);
|
|
628
|
+
};
|
|
629
|
+
this.createdInterpolant.evaluate = this.customEvaluate;
|
|
630
|
+
return this.createdInterpolant;
|
|
631
|
+
};
|
|
632
|
+
}
|
|
633
|
+
;
|
|
634
|
+
dispose() {
|
|
635
|
+
if (this.createdInterpolant && this.originalEvaluate) {
|
|
636
|
+
this.createdInterpolant.evaluate = this.originalEvaluate;
|
|
637
|
+
}
|
|
638
|
+
this.track = undefined;
|
|
639
|
+
this.createdInterpolant = null;
|
|
640
|
+
this.originalEvaluate = undefined;
|
|
641
|
+
this.customEvaluate = undefined;
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
class RootMotionAction {
|
|
645
|
+
static lastObjPosition = {};
|
|
646
|
+
static lastObjRotation = {};
|
|
647
|
+
// we remove the first keyframe rotation from the space rotation when updating
|
|
648
|
+
static firstKeyframeRotation = {};
|
|
649
|
+
// this is used to rotate the space on clip end / start (so the transform direction is correct)
|
|
650
|
+
static spaceRotation = {};
|
|
651
|
+
static effectiveSpaceRotation = {};
|
|
652
|
+
static clipOffsetRotation = {};
|
|
653
|
+
set action(val) {
|
|
654
|
+
this._action = val;
|
|
655
|
+
}
|
|
656
|
+
get action() {
|
|
657
|
+
return this._action;
|
|
658
|
+
}
|
|
659
|
+
get cacheId() {
|
|
660
|
+
return this.root.uuid;
|
|
661
|
+
}
|
|
662
|
+
_action;
|
|
663
|
+
root;
|
|
664
|
+
clip;
|
|
665
|
+
positionWrapper = null;
|
|
666
|
+
rotationWrapper = null;
|
|
667
|
+
context;
|
|
668
|
+
positionChange = new Vector3();
|
|
669
|
+
rotationChange = new Quaternion();
|
|
670
|
+
constructor(context, root, clip, positionTrack, rotationTrack) {
|
|
671
|
+
// console.log(this, positionTrack, rotationTrack);
|
|
672
|
+
this.context = context;
|
|
673
|
+
this.root = root;
|
|
674
|
+
this.clip = clip;
|
|
675
|
+
if (!RootMotionAction.firstKeyframeRotation[this.cacheId])
|
|
676
|
+
RootMotionAction.firstKeyframeRotation[this.cacheId] = new Quaternion();
|
|
677
|
+
if (rotationTrack) {
|
|
678
|
+
const values = rotationTrack.values;
|
|
679
|
+
RootMotionAction.firstKeyframeRotation[this.cacheId]
|
|
680
|
+
.set(values[0], values[1], values[2], values[3]);
|
|
681
|
+
}
|
|
682
|
+
if (!RootMotionAction.spaceRotation[this.cacheId])
|
|
683
|
+
RootMotionAction.spaceRotation[this.cacheId] = new Quaternion();
|
|
684
|
+
if (!RootMotionAction.effectiveSpaceRotation[this.cacheId])
|
|
685
|
+
RootMotionAction.effectiveSpaceRotation[this.cacheId] = new Quaternion();
|
|
686
|
+
RootMotionAction.clipOffsetRotation[this.cacheId] = new Quaternion();
|
|
687
|
+
if (rotationTrack) {
|
|
688
|
+
RootMotionAction.clipOffsetRotation[this.cacheId]
|
|
689
|
+
.set(rotationTrack.values[0], rotationTrack.values[1], rotationTrack.values[2], rotationTrack.values[3])
|
|
690
|
+
.invert();
|
|
691
|
+
}
|
|
692
|
+
this.handlePosition(clip, positionTrack);
|
|
693
|
+
this.handleRotation(clip, rotationTrack);
|
|
694
|
+
}
|
|
695
|
+
onStart(action) {
|
|
696
|
+
if (action.getClip() !== this.clip)
|
|
697
|
+
return;
|
|
698
|
+
if (!RootMotionAction.lastObjRotation[this.cacheId]) {
|
|
699
|
+
RootMotionAction.lastObjRotation[this.cacheId] = this.root.quaternion.clone();
|
|
700
|
+
}
|
|
701
|
+
const lastRotation = RootMotionAction.lastObjRotation[this.cacheId];
|
|
702
|
+
// const firstKeyframe = RootMotionAction.firstKeyframeRotation[this.this.cacheId];
|
|
703
|
+
// lastRotation.invert().premultiply(firstKeyframe).invert();
|
|
704
|
+
RootMotionAction.spaceRotation[this.cacheId].copy(lastRotation);
|
|
705
|
+
if (debugRootMotion) {
|
|
706
|
+
const euler = new Euler().setFromQuaternion(lastRotation);
|
|
707
|
+
console.log("START", this.clip.name, Mathf.toDegrees(euler.y), this.root.position.z);
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
getClipRotationOffset() {
|
|
711
|
+
return RootMotionAction.clipOffsetRotation[this.cacheId];
|
|
712
|
+
}
|
|
713
|
+
_prevTime = 0;
|
|
714
|
+
handlePosition(_clip, track) {
|
|
715
|
+
if (track) {
|
|
716
|
+
const root = this.root;
|
|
717
|
+
if (debugRootMotion)
|
|
718
|
+
root.add(new AxesHelper());
|
|
719
|
+
if (!RootMotionAction.lastObjPosition[this.cacheId])
|
|
720
|
+
RootMotionAction.lastObjPosition[this.cacheId] = this.root.position.clone();
|
|
721
|
+
const valuesDiff = new Vector3();
|
|
722
|
+
const valuesPrev = new Vector3();
|
|
723
|
+
// const rotation = new Quaternion();
|
|
724
|
+
this.positionWrapper = new TrackEvaluationWrapper(track, (time, value) => {
|
|
725
|
+
const weight = this.action.getEffectiveWeight();
|
|
726
|
+
// reset for testing
|
|
727
|
+
if (debugRootMotion) {
|
|
728
|
+
if (root.position.length() > 8)
|
|
729
|
+
root.position.set(0, root.position.y, 0);
|
|
730
|
+
}
|
|
731
|
+
if (time > this._prevTime) {
|
|
732
|
+
valuesDiff.set(value[0], value[1], value[2]);
|
|
733
|
+
valuesDiff.sub(valuesPrev);
|
|
734
|
+
valuesDiff.multiplyScalar(weight);
|
|
735
|
+
valuesDiff.applyQuaternion(this.getClipRotationOffset());
|
|
736
|
+
// RootMotionAction.effectiveSpaceRotation[id].slerp(RootMotionAction.spaceRotation[id], weight);
|
|
737
|
+
valuesDiff.applyQuaternion(root.quaternion);
|
|
738
|
+
this.positionChange.copy(valuesDiff);
|
|
739
|
+
// this.root.position.add(valuesDiff);
|
|
740
|
+
}
|
|
741
|
+
valuesPrev.fromArray(value);
|
|
742
|
+
this._prevTime = time;
|
|
743
|
+
value[0] = 0;
|
|
744
|
+
value[1] = 0;
|
|
745
|
+
value[2] = 0;
|
|
746
|
+
return value;
|
|
747
|
+
});
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
static identityQuaternion = new Quaternion();
|
|
751
|
+
handleRotation(clip, track) {
|
|
752
|
+
if (track) {
|
|
753
|
+
if (debugRootMotion) {
|
|
754
|
+
const arr = track.values;
|
|
755
|
+
const firstKeyframe = new Euler().setFromQuaternion(new Quaternion(arr[0], arr[1], arr[2], arr[3]));
|
|
756
|
+
console.log(clip.name, track.name, "FIRST ROTATION IN TRACK", Mathf.toDegrees(firstKeyframe.y));
|
|
757
|
+
const i = track.values.length - 4;
|
|
758
|
+
const lastKeyframe = new Quaternion().set(arr[i], arr[i + 1], arr[i + 2], arr[i + 3]);
|
|
759
|
+
const euler = new Euler().setFromQuaternion(lastKeyframe);
|
|
760
|
+
console.log(clip.name, track.name, "LAST ROTATION IN TRACK", Mathf.toDegrees(euler.y));
|
|
761
|
+
}
|
|
762
|
+
// if (!RootMotionAction.lastObjRotation[root.uuid]) RootMotionAction.lastObjRotation[root.uuid] = new Quaternion();
|
|
763
|
+
// const temp = new Quaternion();
|
|
764
|
+
let prevTime = 0;
|
|
765
|
+
const valuesPrev = new Quaternion();
|
|
766
|
+
const valuesDiff = new Quaternion();
|
|
767
|
+
// const summedRot = new Quaternion();
|
|
768
|
+
this.rotationWrapper = new TrackEvaluationWrapper(track, (time, value) => {
|
|
769
|
+
// root.quaternion.copy(RootMotionAction.lastObjRotation[root.uuid]);
|
|
770
|
+
if (time > prevTime) {
|
|
771
|
+
valuesDiff.set(value[0], value[1], value[2], value[3]);
|
|
772
|
+
valuesPrev.invert();
|
|
773
|
+
valuesDiff.multiply(valuesPrev);
|
|
774
|
+
// if(weight < .99) valuesDiff.slerp(RootMotionAction.identityQuaternion, 1 - weight);
|
|
775
|
+
this.rotationChange.copy(valuesDiff);
|
|
776
|
+
// root.quaternion.multiply(valuesDiff);
|
|
777
|
+
}
|
|
778
|
+
// else
|
|
779
|
+
// root.quaternion.multiply(this.getClipRotationOffset());
|
|
780
|
+
// RootMotionAction.lastObjRotation[root.uuid].copy(root.quaternion);
|
|
781
|
+
valuesPrev.fromArray(value);
|
|
782
|
+
prevTime = time;
|
|
783
|
+
value[0] = 0;
|
|
784
|
+
value[1] = 0;
|
|
785
|
+
value[2] = 0;
|
|
786
|
+
value[3] = 1;
|
|
787
|
+
return value;
|
|
788
|
+
});
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
// private lastPos: Vector3 = new Vector3();
|
|
792
|
+
onBeforeUpdate(_weight) {
|
|
793
|
+
this.positionChange.set(0, 0, 0);
|
|
794
|
+
this.rotationChange.set(0, 0, 0, 1);
|
|
795
|
+
}
|
|
796
|
+
onAfterUpdate(weight) {
|
|
797
|
+
if (!this.action)
|
|
798
|
+
return false;
|
|
799
|
+
weight *= this.action.getEffectiveWeight();
|
|
800
|
+
if (weight <= 0)
|
|
801
|
+
return false;
|
|
802
|
+
this.positionChange.multiplyScalar(weight);
|
|
803
|
+
this.rotationChange.slerp(RootMotionAction.identityQuaternion, 1 - weight);
|
|
804
|
+
return true;
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
class RootMotionHandler {
|
|
808
|
+
controller;
|
|
809
|
+
handler = [];
|
|
810
|
+
root;
|
|
811
|
+
basePosition = new Vector3();
|
|
812
|
+
baseQuaternion = new Quaternion();
|
|
813
|
+
baseRotation = new Euler();
|
|
814
|
+
constructor(controller) {
|
|
815
|
+
this.controller = controller;
|
|
816
|
+
}
|
|
817
|
+
createClip(mixer, root, clip) {
|
|
818
|
+
this.root = root;
|
|
819
|
+
let rootName = "";
|
|
820
|
+
if (root && "name" in root) {
|
|
821
|
+
rootName = root.name;
|
|
822
|
+
}
|
|
823
|
+
const positionTrack = this.findRootTrack(clip, ".position");
|
|
824
|
+
const rotationTrack = this.findRootTrack(clip, ".quaternion");
|
|
825
|
+
const handler = new RootMotionAction(this.controller.context, root, clip, positionTrack, rotationTrack);
|
|
826
|
+
this.handler.push(handler);
|
|
827
|
+
// it is important we do this after the handler is created
|
|
828
|
+
// otherwise we can not hook into threejs interpolators
|
|
829
|
+
const action = mixer.clipAction(clip);
|
|
830
|
+
handler.action = action;
|
|
831
|
+
return action;
|
|
832
|
+
}
|
|
833
|
+
onStart(action) {
|
|
834
|
+
for (const handler of this.handler) {
|
|
835
|
+
handler.onStart(action);
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
onBeforeUpdate(weight) {
|
|
839
|
+
// capture the position of the object
|
|
840
|
+
this.basePosition.copy(this.root.position);
|
|
841
|
+
this.baseQuaternion.copy(this.root.quaternion);
|
|
842
|
+
for (const hand of this.handler)
|
|
843
|
+
hand.onBeforeUpdate(weight);
|
|
844
|
+
}
|
|
845
|
+
summedPosition = new Vector3();
|
|
846
|
+
summedRotation = new Quaternion();
|
|
847
|
+
onAfterUpdate(weight) {
|
|
848
|
+
if (weight <= 0)
|
|
849
|
+
return;
|
|
850
|
+
// TODO: blend weight properly with root motion (when using timeline blending with animator)
|
|
851
|
+
// apply the accumulated changes
|
|
852
|
+
this.root.position.copy(this.basePosition);
|
|
853
|
+
this.root.quaternion.copy(this.baseQuaternion);
|
|
854
|
+
this.summedPosition.set(0, 0, 0);
|
|
855
|
+
this.summedRotation.set(0, 0, 0, 1);
|
|
856
|
+
for (const entry of this.handler) {
|
|
857
|
+
if (entry.onAfterUpdate(weight)) {
|
|
858
|
+
this.summedPosition.add(entry.positionChange);
|
|
859
|
+
this.summedRotation.multiply(entry.rotationChange);
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
this.root.position.add(this.summedPosition);
|
|
863
|
+
this.root.quaternion.multiply(this.summedRotation);
|
|
864
|
+
// RootMotionAction.lastObjRotation[this.root.uuid].copy(this.root.quaternion);
|
|
865
|
+
}
|
|
866
|
+
findRootTrack(clip, name) {
|
|
867
|
+
const tracks = clip.tracks;
|
|
868
|
+
if (!tracks)
|
|
869
|
+
return null;
|
|
870
|
+
for (const track of tracks) {
|
|
871
|
+
if (track.name.endsWith(name)) {
|
|
872
|
+
return track;
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
return null;
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
class AnimatorControllerSerializator extends TypeSerializer {
|
|
879
|
+
onSerialize(_, _context) {
|
|
880
|
+
}
|
|
881
|
+
onDeserialize(data, context) {
|
|
882
|
+
if (context.type === AnimatorController && data?.__type === "AnimatorController")
|
|
883
|
+
return new AnimatorController(data);
|
|
884
|
+
return undefined;
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
new AnimatorControllerSerializator(AnimatorController);
|
|
888
888
|
//# sourceMappingURL=AnimatorController.js.map
|