@hology/core 0.0.220 → 0.0.222

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.
@@ -1,6 +1,11 @@
1
1
  import { ActorComponent } from '../component.js';
2
- import { PerspectiveCamera } from 'three';
2
+ import { Vector3, PerspectiveCamera } from 'three';
3
3
  import { DecimalInput, RestrictedRotationInput } from '../../input/index.js';
4
+ export type TemporaryThirdPersonCameraControlOptions = {
5
+ blendInDuration?: number;
6
+ blendOutDuration?: number;
7
+ fieldOfView?: number;
8
+ };
4
9
  /**
5
10
  * A camera that is behind the actor.
6
11
  * It can also spring back and forward to avoid clipping into other elements
@@ -40,9 +45,32 @@ export declare class ThirdPersonCameraComponent extends ActorComponent {
40
45
  private prevFixedBehind;
41
46
  private blendDurationLeft;
42
47
  private pointerEventsRegistered;
48
+ private temporaryControlActive;
49
+ private temporaryControlWeight;
50
+ private temporaryControlTargetWeight;
51
+ private temporaryControlBlendInDuration;
52
+ private temporaryControlBlendOutDuration;
53
+ private temporaryControlPositionEnabled;
54
+ private temporaryControlBaseFieldOfView;
55
+ private temporaryControlFieldOfView;
56
+ private readonly temporaryControlPosition;
57
+ private readonly temporaryControlLookAt;
43
58
  onInit(): Promise<void>;
44
59
  activate(): void;
45
60
  deactivate(): void;
61
+ /**
62
+ * Temporarily takes over the final camera pose while the normal third-person pose
63
+ * continues to update underneath it. Call this as the desired pose moves, then call
64
+ * clearTemporaryControl() to blend back to normal gameplay camera control.
65
+ */
66
+ setTemporaryControl(position: Vector3, lookAt: Vector3, options?: TemporaryThirdPersonCameraControlOptions): void;
67
+ /**
68
+ * Temporarily pans the camera toward a target without changing the position
69
+ * produced by normal third-person camera control.
70
+ */
71
+ setTemporaryLookAt(lookAt: Vector3, options?: TemporaryThirdPersonCameraControlOptions): void;
72
+ private activateTemporaryControl;
73
+ clearTemporaryControl(blendOutDuration?: number): void;
46
74
  private registerPointerEvents;
47
75
  private unregisterPointerEvents;
48
76
  onLateUpdate(deltaTime: number): void;
@@ -61,6 +89,8 @@ export declare class ThirdPersonCameraComponent extends ActorComponent {
61
89
  private checkForCollision;
62
90
  private getLookAtPosition;
63
91
  private updateCameraPosition;
92
+ private applyTemporaryControl;
93
+ private getTemporaryControlPosition;
64
94
  private prevLookAt;
65
95
  private smoothedLookAt;
66
96
  private previousTargetLookAt;
@@ -1,4 +1,4 @@
1
- import{__decorate as t,__metadata as e}from"tslib";import{ActorComponent as o,Component as i}from"../component.js";import{Vector3 as s,MathUtils as n,PerspectiveCamera as h,Object3D as r}from"three";import{ViewController as a}from"../../services/render.js";import{DecimalInput as c,RestrictedRotationInput as d}from"../../input/index.js";import{PhysicsSystem as m}from"../../services/physics/physics-system.js";import{Parameter as p}from"../../../shader/parameter.js";import{World as l}from"../../services/world.js";import{inject as u}from"../../inject.js";import{ease as f}from"@hology/nebula";const v=void 0!==window&&/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);let k=class extends o{constructor(){super(),this.viewController=u(a),this.physicsSystem=u(m),this.aspect=this.viewController.htmlElement.clientWidth/this.viewController.htmlElement.clientHeight,this.near=.5,this.far=500,this.viewAngle=v?30:45,this.collision=!0,this.collisionSphereRadius=.25,this.smoothCamera=!1,this.smoothSpeed=10,this.teleportSnapDistance=5,this.camera=new h(this.viewAngle,this.aspect,this.near,this.far),this.distance=9,this.minDistance=1.5,this.maxDistance=this.distance,this.height=3,this.offsetX=-1,this.offsetY=2,this.offsetZ=1.5,this.autoActivate=!0,this.bounceBackSpeed=3,this.restrictedDistance=Math.max(this.distance,this.maxDistance),this.rotationInput=new d(-Math.PI/4,Math.PI/2-.7),this.zoomInput=new c(1,0,1),this.offset=new s,this.lookAtOffset=new s(this.offsetX,0,this.offsetZ),this.fixedBehind=!0,this.world=u(l),this.activated=!1,this.isMouseLocked=!1,this.prevFixedBehind=!1,this.blendDurationLeft=0,this.pointerEventsRegistered=!1,this.canvas=null,this.pointerLockInactivatedAt=null,this.onMouseDown=t=>{this.isMouseLocked||"mouse"!==t.pointerType||this.hideCursor()},this.onKeyDown=t=>{"Escape"===t.key&&this.showCursor()},this.onPointerLockChange=()=>{this.isMouseLocked=null!=document.pointerLockElement||null!=document.mozPointerLockElement,this.element.style.cursor=this.isMouseLocked?"none":"default",this.isMouseLocked||(this.pointerLockInactivatedAt=performance.now())},this.prevLookAt=new s,this.smoothedLookAt=new s,this.previousTargetLookAt=new s,this.hasSmoothedLookAt=!1,this.smoothedRotX=0,this.smoothedRotY=0,this.smoothZoom=0}async onInit(){this.prevFixedBehind=this.fixedBehind,this.world.scene.add(this.camera),this.rotationInput.rotation.copy(this.actor.rotation),this.smoothedRotX=this.rotationInput.rotation.x,this.smoothedRotY=this.rotationInput.rotation.y,this.restrictedDistance=Math.max(this.distance,this.maxDistance),this.lookAtOffset.set(this.offsetX,0,this.offsetZ),this.smoothZoom=this.zoomInput.value,this.autoActivate&&this.activate(),this.disposed.subscribe(()=>{this.unregisterPointerEvents()})}activate(){this.activated=!0,this.hasSmoothedLookAt=!1,this.viewController.setCamera(this.camera),this.isMouseLocked=null!=document.pointerLockElement||null!=document.mozPointerLockElement,this.registerPointerEvents()}deactivate(){this.activated=!1,this.isMouseLocked=!1,this.unregisterPointerEvents()}registerPointerEvents(){if(this.pointerEventsRegistered||null==document.body.requestPointerLock)return;const t=this.element;t.addEventListener("pointerdown",this.onMouseDown),t.addEventListener("keydown",this.onKeyDown),document.addEventListener("pointerlockchange",this.onPointerLockChange,!1),this.pointerEventsRegistered=!0}unregisterPointerEvents(){if(!this.pointerEventsRegistered)return;const t=this.element;t.removeEventListener("pointerdown",this.onMouseDown),t.removeEventListener("keydown",this.onKeyDown),document.removeEventListener("pointerlockchange",this.onPointerLockChange,!1),this.pointerEventsRegistered=!1}onLateUpdate(t){this.activated&&this.setFromRotation(t)}get element(){return this.viewController.htmlElement}hideCursor({ignoreRecentUnlock:t=!1}={}){!t&&null!=this.pointerLockInactivatedAt&&performance.now()-this.pointerLockInactivatedAt<1600||(null==this.canvas&&(this.canvas=this.element.getElementsByTagName("canvas")[0]),this.canvas&&this.canvas.requestPointerLock&&this.requestPointerLock())}requestPointerLock(){try{const t=this.canvas.requestPointerLock({unadjustedMovement:!0});t?.catch(()=>this.onPointerLockChange())}catch{this.onPointerLockChange()}}showCursor(){this.pointerLockInactivatedAt=performance.now(),this.element.style.cursor="default",null==document.pointerLockElement&&null==document.mozPointerLockElement||window.document.exitPointerLock(),this.isMouseLocked=!1}setFromRotation(t){this.lookAtOffset.set(this.offsetX,0,this.offsetZ),this.fixedBehind!==this.prevFixedBehind?(this.blendDurationLeft=1,this.prevFixedBehind=this.fixedBehind):this.blendDurationLeft>0&&(this.blendDurationLeft-=t),this.collision&&this.checkForCollision(t);let e=this.zoomInput.value,o=this.rotationInput.rotation.x,i=this.rotationInput.rotation.y;if(this.smoothCamera){const s=1-Math.exp(-this.smoothSpeed*t*2);this.smoothedRotX=n.lerp(this.smoothedRotX,o,s),this.smoothedRotY=n.lerp(this.smoothedRotY,i,s),o=this.smoothedRotX,i=this.smoothedRotY,this.smoothZoom=n.lerp(this.smoothZoom,e,.4*s),e=this.smoothZoom}else this.smoothedRotX=o,this.smoothedRotY=i;const s=n.clamp(Math.min(this.restrictedDistance,this.distance),Math.min(this.minDistance,this.restrictedDistance),Math.max(this.distance*e,this.minDistance)),h=Math.cos(o)*s,r=this.fixedBehind?0:i;this.offset.x=Math.sin(-r)*h,this.offset.y=Math.sin(o)*s+this.offsetY,this.offset.z=Math.cos(-r)*-h,this.fixedBehind&&this.offset.add(this.lookAtOffset),this.updateCameraPosition(t)}checkForCollision(t){const e=this.getLookAtPosition(),o=this.camera.getWorldPosition(w),i=A.subVectors(o,e),s=i.length();if(s<.001)return;i.divideScalar(s);const h=this.physicsSystem.sphereCast(e,this.collisionSphereRadius,i,this.distance,void 0,{excludeActor:this.actor,excludeTriggers:!0,collisionFilter:-2});if(h.hasHit){const e=Math.max(this.minDistance,h.distance-.05);e<this.restrictedDistance?this.restrictedDistance=e:this.restrictedDistance=n.lerp(this.restrictedDistance,e,n.clamp(this.bounceBackSpeed*t,0,1))}else this.restrictedDistance=n.lerp(this.restrictedDistance,this.distance,n.clamp(this.bounceBackSpeed*t,0,1))}getLookAtPosition(){const t=y;return t.set(0,0,0),t.y=this.height,this.fixedBehind&&t.add(this.lookAtOffset),t.applyMatrix4(this.actor.object.matrixWorld),t}updateCameraPosition(t){this.actor.object.updateWorldMatrix(!0,!1),this.fixedBehind?(L.position.set(this.offset.x,this.offset.y,this.offset.z),L.rotation.set(0,0,0),L.scale.set(1,1,1),L.applyMatrix4(this.actor.object.matrix)):L.position.copy(this.actor.position).add(this.offset);const e=f.easeInOutCubic(1-this.blendDurationLeft);if(this.blendDurationLeft>0){const t=this.getLookAtPosition();this.prevLookAt.lerp(t,e),this.camera.lookAt(this.prevLookAt),this.camera.position.lerp(L.position,e),this.smoothedLookAt.copy(this.prevLookAt),this.previousTargetLookAt.copy(t),this.hasSmoothedLookAt=!0}else{const e=this.getLookAtPosition();if(this.smoothCamera){const o=1-Math.exp(-this.smoothSpeed*t),i=Math.max(0,this.teleportSnapDistance);!this.hasSmoothedLookAt||this.previousTargetLookAt.distanceToSquared(e)>i*i?this.smoothedLookAt.copy(e):this.smoothedLookAt.lerp(e,o)}else this.smoothedLookAt.copy(e);this.previousTargetLookAt.copy(e),this.hasSmoothedLookAt=!0,g.subVectors(L.position,e),this.camera.position.copy(this.smoothedLookAt).add(g),this.camera.lookAt(this.smoothedLookAt),this.prevLookAt.copy(this.smoothedLookAt)}}};t([p(),e("design:type",Number)],k.prototype,"near",void 0),t([p(),e("design:type",Number)],k.prototype,"far",void 0),t([p(),e("design:type",Number)],k.prototype,"viewAngle",void 0),t([p(),e("design:type",Boolean)],k.prototype,"collision",void 0),t([p(),e("design:type",Number)],k.prototype,"collisionSphereRadius",void 0),t([p(),e("design:type",Boolean)],k.prototype,"smoothCamera",void 0),t([p(),e("design:type",Number)],k.prototype,"smoothSpeed",void 0),t([p(),e("design:type",Number)],k.prototype,"teleportSnapDistance",void 0),k=t([i(),e("design:paramtypes",[])],k);export{k as ThirdPersonCameraComponent};const L=new r,y=new s,g=new s,A=new s,w=(new s,new s);export class ThirdPartyCameraComponent extends k{}/*
1
+ import{__decorate as t,__metadata as o}from"tslib";import{ActorComponent as e,Component as i}from"../component.js";import{Vector3 as s,MathUtils as r,PerspectiveCamera as n,Object3D as h}from"three";import{ViewController as a}from"../../services/render.js";import{DecimalInput as l,RestrictedRotationInput as c}from"../../input/index.js";import{PhysicsSystem as m}from"../../services/physics/physics-system.js";import{Parameter as p}from"../../../shader/parameter.js";import{World as d}from"../../services/world.js";import{inject as u}from"../../inject.js";import{ease as y}from"@hology/nebula";const f=void 0!==window&&/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);let v=class extends e{constructor(){super(),this.viewController=u(a),this.physicsSystem=u(m),this.aspect=this.viewController.htmlElement.clientWidth/this.viewController.htmlElement.clientHeight,this.near=.5,this.far=500,this.viewAngle=f?30:45,this.collision=!0,this.collisionSphereRadius=.25,this.smoothCamera=!1,this.smoothSpeed=10,this.teleportSnapDistance=5,this.camera=new n(this.viewAngle,this.aspect,this.near,this.far),this.distance=9,this.minDistance=1.5,this.maxDistance=this.distance,this.height=3,this.offsetX=-1,this.offsetY=2,this.offsetZ=1.5,this.autoActivate=!0,this.bounceBackSpeed=3,this.restrictedDistance=Math.max(this.distance,this.maxDistance),this.rotationInput=new c(-Math.PI/4,Math.PI/2-.7),this.zoomInput=new l(1,0,1),this.offset=new s,this.lookAtOffset=new s(this.offsetX,0,this.offsetZ),this.fixedBehind=!0,this.world=u(d),this.activated=!1,this.isMouseLocked=!1,this.prevFixedBehind=!1,this.blendDurationLeft=0,this.pointerEventsRegistered=!1,this.temporaryControlActive=!1,this.temporaryControlWeight=0,this.temporaryControlTargetWeight=0,this.temporaryControlBlendInDuration=.5,this.temporaryControlBlendOutDuration=.5,this.temporaryControlPositionEnabled=!1,this.temporaryControlBaseFieldOfView=this.camera.fov,this.temporaryControlFieldOfView=null,this.temporaryControlPosition=new s,this.temporaryControlLookAt=new s,this.canvas=null,this.pointerLockInactivatedAt=null,this.onMouseDown=t=>{this.isMouseLocked||"mouse"!==t.pointerType||this.hideCursor()},this.onKeyDown=t=>{"Escape"===t.key&&this.showCursor()},this.onPointerLockChange=()=>{this.isMouseLocked=null!=document.pointerLockElement||null!=document.mozPointerLockElement,this.element.style.cursor=this.isMouseLocked?"none":"default",this.isMouseLocked||(this.pointerLockInactivatedAt=performance.now())},this.prevLookAt=new s,this.smoothedLookAt=new s,this.previousTargetLookAt=new s,this.hasSmoothedLookAt=!1,this.smoothedRotX=0,this.smoothedRotY=0,this.smoothZoom=0}async onInit(){this.prevFixedBehind=this.fixedBehind,this.world.scene.add(this.camera),this.rotationInput.rotation.copy(this.actor.rotation),this.smoothedRotX=this.rotationInput.rotation.x,this.smoothedRotY=this.rotationInput.rotation.y,this.restrictedDistance=Math.max(this.distance,this.maxDistance),this.lookAtOffset.set(this.offsetX,0,this.offsetZ),this.smoothZoom=this.zoomInput.value,this.autoActivate&&this.activate(),this.disposed.subscribe(()=>{this.unregisterPointerEvents()})}activate(){this.activated=!0,this.hasSmoothedLookAt=!1,this.viewController.setCamera(this.camera),this.isMouseLocked=null!=document.pointerLockElement||null!=document.mozPointerLockElement,this.registerPointerEvents()}deactivate(){this.activated=!1,this.isMouseLocked=!1,this.unregisterPointerEvents()}setTemporaryControl(t,o,e={}){this.temporaryControlPosition.copy(t),this.temporaryControlLookAt.copy(o),this.temporaryControlPositionEnabled=!0,this.activateTemporaryControl(e)}setTemporaryLookAt(t,o={}){this.temporaryControlLookAt.copy(t),this.temporaryControlPositionEnabled=!1,this.activateTemporaryControl(o)}activateTemporaryControl(t){this.temporaryControlActive||(this.temporaryControlBaseFieldOfView=this.camera.fov),this.temporaryControlFieldOfView=null==t.fieldOfView?null:r.clamp(t.fieldOfView,1,179),null!=t.blendInDuration&&(this.temporaryControlBlendInDuration=Math.max(0,t.blendInDuration)),null!=t.blendOutDuration&&(this.temporaryControlBlendOutDuration=Math.max(0,t.blendOutDuration)),this.temporaryControlActive=!0,this.temporaryControlTargetWeight=1}clearTemporaryControl(t){this.temporaryControlActive&&(null!=t&&(this.temporaryControlBlendOutDuration=Math.max(0,t)),this.temporaryControlTargetWeight=0)}registerPointerEvents(){if(this.pointerEventsRegistered||null==document.body.requestPointerLock)return;const t=this.element;t.addEventListener("pointerdown",this.onMouseDown),t.addEventListener("keydown",this.onKeyDown),document.addEventListener("pointerlockchange",this.onPointerLockChange,!1),this.pointerEventsRegistered=!0}unregisterPointerEvents(){if(!this.pointerEventsRegistered)return;const t=this.element;t.removeEventListener("pointerdown",this.onMouseDown),t.removeEventListener("keydown",this.onKeyDown),document.removeEventListener("pointerlockchange",this.onPointerLockChange,!1),this.pointerEventsRegistered=!1}onLateUpdate(t){this.activated&&this.setFromRotation(t)}get element(){return this.viewController.htmlElement}hideCursor({ignoreRecentUnlock:t=!1}={}){!t&&null!=this.pointerLockInactivatedAt&&performance.now()-this.pointerLockInactivatedAt<1600||(null==this.canvas&&(this.canvas=this.element.getElementsByTagName("canvas")[0]),this.canvas&&this.canvas.requestPointerLock&&this.requestPointerLock())}requestPointerLock(){try{const t=this.canvas.requestPointerLock({unadjustedMovement:!0});t?.catch(()=>this.onPointerLockChange())}catch{this.onPointerLockChange()}}showCursor(){this.pointerLockInactivatedAt=performance.now(),this.element.style.cursor="default",null==document.pointerLockElement&&null==document.mozPointerLockElement||window.document.exitPointerLock(),this.isMouseLocked=!1}setFromRotation(t){this.lookAtOffset.set(this.offsetX,0,this.offsetZ),this.fixedBehind!==this.prevFixedBehind?(this.blendDurationLeft=1,this.prevFixedBehind=this.fixedBehind):this.blendDurationLeft>0&&(this.blendDurationLeft-=t),this.collision&&this.checkForCollision(t);let o=this.zoomInput.value,e=this.rotationInput.rotation.x,i=this.rotationInput.rotation.y;if(this.smoothCamera){const s=1-Math.exp(-this.smoothSpeed*t*2);this.smoothedRotX=r.lerp(this.smoothedRotX,e,s),this.smoothedRotY=r.lerp(this.smoothedRotY,i,s),e=this.smoothedRotX,i=this.smoothedRotY,this.smoothZoom=r.lerp(this.smoothZoom,o,.4*s),o=this.smoothZoom}else this.smoothedRotX=e,this.smoothedRotY=i;const s=r.clamp(Math.min(this.restrictedDistance,this.distance),Math.min(this.minDistance,this.restrictedDistance),Math.max(this.distance*o,this.minDistance)),n=Math.cos(e)*s,h=this.fixedBehind?0:i;this.offset.x=Math.sin(-h)*n,this.offset.y=Math.sin(e)*s+this.offsetY,this.offset.z=Math.cos(-h)*-n,this.fixedBehind&&this.offset.add(this.lookAtOffset),this.updateCameraPosition(t)}checkForCollision(t){const o=this.getLookAtPosition(),e=this.camera.getWorldPosition(A),i=L.subVectors(e,o),s=i.length();if(s<.001)return;i.divideScalar(s);const n=this.physicsSystem.sphereCast(o,this.collisionSphereRadius,i,this.distance,void 0,{excludeActor:this.actor,excludeTriggers:!0,collisionFilter:-2});if(n.hasHit){const o=Math.max(this.minDistance,n.distance-.05);o<this.restrictedDistance?this.restrictedDistance=o:this.restrictedDistance=r.lerp(this.restrictedDistance,o,r.clamp(this.bounceBackSpeed*t,0,1))}else this.restrictedDistance=r.lerp(this.restrictedDistance,this.distance,r.clamp(this.bounceBackSpeed*t,0,1))}getLookAtPosition(){const t=k;return t.set(0,0,0),t.y=this.height,this.fixedBehind&&t.add(this.lookAtOffset),t.applyMatrix4(this.actor.object.matrixWorld),t}updateCameraPosition(t){this.actor.object.updateWorldMatrix(!0,!1),this.fixedBehind?(C.position.set(this.offset.x,this.offset.y,this.offset.z),C.rotation.set(0,0,0),C.scale.set(1,1,1),C.applyMatrix4(this.actor.object.matrix)):C.position.copy(this.actor.position).add(this.offset);const o=y.easeInOutCubic(1-this.blendDurationLeft);if(this.blendDurationLeft>0){const t=this.getLookAtPosition();this.prevLookAt.lerp(t,o),this.camera.lookAt(this.prevLookAt),this.camera.position.lerp(C.position,o),this.smoothedLookAt.copy(this.prevLookAt),this.previousTargetLookAt.copy(t),this.hasSmoothedLookAt=!0}else{const o=this.getLookAtPosition();if(this.smoothCamera){const e=1-Math.exp(-this.smoothSpeed*t),i=Math.max(0,this.teleportSnapDistance);!this.hasSmoothedLookAt||this.previousTargetLookAt.distanceToSquared(o)>i*i?this.smoothedLookAt.copy(o):this.smoothedLookAt.lerp(o,e)}else this.smoothedLookAt.copy(o);this.previousTargetLookAt.copy(o),this.hasSmoothedLookAt=!0,g.subVectors(C.position,o),this.camera.position.copy(this.smoothedLookAt).add(g),this.camera.lookAt(this.smoothedLookAt),this.prevLookAt.copy(this.smoothedLookAt)}this.applyTemporaryControl(t)}applyTemporaryControl(t){if(!this.temporaryControlActive)return;this.temporaryControlTargetWeight>this.temporaryControlWeight?this.temporaryControlWeight=0===this.temporaryControlBlendInDuration?1:Math.min(1,this.temporaryControlWeight+t/this.temporaryControlBlendInDuration):this.temporaryControlTargetWeight<this.temporaryControlWeight&&(this.temporaryControlWeight=0===this.temporaryControlBlendOutDuration?0:Math.max(0,this.temporaryControlWeight-t/this.temporaryControlBlendOutDuration));const o=y.easeInOutCubic(this.temporaryControlWeight);this.temporaryControlPositionEnabled&&this.camera.position.lerp(this.getTemporaryControlPosition(),o),D.position.copy(this.camera.position),D.up.copy(this.camera.up),D.lookAt(this.temporaryControlLookAt),this.camera.quaternion.slerp(D.quaternion,o);const e=this.temporaryControlFieldOfView??this.temporaryControlBaseFieldOfView,i=r.lerp(this.temporaryControlBaseFieldOfView,e,o);this.camera.fov!==i&&(this.camera.fov=i,this.camera.updateProjectionMatrix()),0===this.temporaryControlTargetWeight&&0===this.temporaryControlWeight&&(this.temporaryControlActive=!1)}getTemporaryControlPosition(){if(!this.collision)return this.temporaryControlPosition;w.subVectors(this.temporaryControlPosition,this.temporaryControlLookAt);const t=w.length();if(t<.001)return this.temporaryControlPosition;w.divideScalar(t);const o=this.physicsSystem.sphereCast(this.temporaryControlLookAt,this.collisionSphereRadius,w,t,void 0,{excludeActor:this.actor,excludeTriggers:!0,collisionFilter:-2});return!o.hasHit||o.distance>=t?this.temporaryControlPosition:x.copy(this.temporaryControlLookAt).addScaledVector(w,Math.max(0,o.distance-.05))}};t([p(),o("design:type",Number)],v.prototype,"near",void 0),t([p(),o("design:type",Number)],v.prototype,"far",void 0),t([p(),o("design:type",Number)],v.prototype,"viewAngle",void 0),t([p(),o("design:type",Boolean)],v.prototype,"collision",void 0),t([p(),o("design:type",Number)],v.prototype,"collisionSphereRadius",void 0),t([p(),o("design:type",Boolean)],v.prototype,"smoothCamera",void 0),t([p(),o("design:type",Number)],v.prototype,"smoothSpeed",void 0),t([p(),o("design:type",Number)],v.prototype,"teleportSnapDistance",void 0),v=t([i(),o("design:paramtypes",[])],v);export{v as ThirdPersonCameraComponent};const C=new h,k=new s,g=new s,L=new s,A=(new s,new s),w=new s,x=new s,D=new n;export class ThirdPartyCameraComponent extends v{}/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -1,7 +1,7 @@
1
1
  export { CameraActor } from './builtin/camera-actor.js';
2
2
  export { CameraComponent } from './camera/camera-component.js';
3
3
  export { FirstPersonCameraComponent } from './camera/first-person-camera-component.js';
4
- export { ThirdPersonCameraComponent, ThirdPartyCameraComponent } from './camera/third-person-camera-component.js';
4
+ export { ThirdPersonCameraComponent, ThirdPartyCameraComponent, type TemporaryThirdPersonCameraControlOptions } from './camera/third-person-camera-component.js';
5
5
  export { SpawnPoint } from './builtin/spawn-point.js';
6
6
  export { TriggerVolume, TriggerVolumeComponent } from './builtin/trigger-volume.js';
7
7
  export { PositionalAudioActor, PositionalAudioComponent } from './builtin/positional-audio-actor.js';
@@ -19,7 +19,14 @@ export declare class InputService {
19
19
  private lastActiveDevice;
20
20
  readonly onDeviceChanged: Subject<InputDevice>;
21
21
  private prevGamepadButtonStates;
22
+ private suppressedGamepadButtons;
22
23
  getLastActiveDevice(): InputDevice;
24
+ /**
25
+ * Ignores button transitions for any gamepad buttons currently held down
26
+ * until each button is released. This is useful when dismissing modal UI
27
+ * whose confirm button is also bound to a gameplay action.
28
+ */
29
+ suppressHeldGamepadButtonsUntilRelease(): void;
23
30
  private setLastActiveDevice;
24
31
  private onKeyDown;
25
32
  /**
@@ -1,4 +1,4 @@
1
- import{__decorate as e}from"tslib";import{Service as t}from"typedi";import{inject as s}from"../inject.js";import{ViewController as i}from"../services/render.js";import{MathUtils as n}from"three";import{Subject as o}from"rxjs";let a=class{constructor(){this.view=s(i),this.inputs=new Map,this.deltaCallbacks=new Map,this.toggleCallbacks=new Map,this.keybinds=new Map,this.mousebinds=new Map,this.touchmoveBinds=new Map,this.wheelbinds=new Map,this.gamepadButtonBinds=new Map,this.gamepadAxisBinds=new Map,this.lastActiveDevice="kbm",this.onDeviceChanged=new o,this.prevGamepadButtonStates=new Map,this.onKeyDown=e=>{this.setLastActiveDevice("kbm"),this.view.paused||this.keybinds.forEach((t,s)=>{for(const i of t)if(i.test(e))if(this.inputs.has(s))this.inputs.get(s)(!0);else if(this.toggleCallbacks.has(s)){this.toggleCallbacks.get(s)(!0);this.activeToggleCallbacks.findIndex(e=>e.keybind===i&&e.toggle===this.toggleCallbacks.get(s))<0&&this.activeToggleCallbacks.push({keybind:i,toggle:this.toggleCallbacks.get(s)})}else console.warn("No input callback for registered for key bind "+i.display())})},this.activeToggleCallbacks=[],this.onKeyUp=e=>{this.setLastActiveDevice("kbm"),this.keybinds.forEach((t,s)=>{for(const i of t)if(i.test(e))if(this.inputs.has(s))this.inputs.get(s)(!1);else if(this.toggleCallbacks.has(s)){this.toggleCallbacks.get(s)(!1);const e=this.activeToggleCallbacks.findIndex(e=>e.keybind===i&&e.toggle===this.toggleCallbacks.get(s));e>=0&&this.activeToggleCallbacks.splice(e,1);for(const e of this.activeToggleCallbacks)e.toggle(!0)}else console.warn("No input callback for registered for key bind "+i.display())})},this.onMouseMove=e=>{if((Math.abs(e.movementX)>1||Math.abs(e.movementY)>1)&&this.setLastActiveDevice("kbm"),this.view.paused)return;if(!(null!=document.pointerLockElement||null!=document.mozPointerLockElement))return;const t=n.clamp(e.movementX,-50,50),s=n.clamp(e.movementY,-50,50);Math.abs(t)>200||Math.abs(s)>200||this.mousebinds.forEach((e,i)=>{const n=this.inputs.get(i)??this.deltaCallbacks.get(i);if(null!=n)switch(e.axis){case"x":n(t*e.multiplier);break;case"y":n(s*e.multiplier)}else console.warn("No input callback for registered for mouse bind "+e.axis)})},this.onTouchStart=e=>{if(this.setLastActiveDevice("kbm"),!this.view.paused){for(let t=0;t<=e.touches.length;t++){const s=e.touches[t];if(s?.target instanceof HTMLCanvasElement)return void(this.prevTouchEvent=s)}e.preventDefault()}},this.onTouchMove=e=>{if(this.view.paused)return;if(null==this.prevTouchEvent)return;let t=null;for(let s=0;s<=e.touches.length;s++){const i=e.touches[s];if(i&&i.target instanceof HTMLCanvasElement&&i.identifier===this.prevTouchEvent.identifier){t=i;break}}null!=t&&(this.touchmoveBinds.forEach((e,s)=>{const i=this.inputs.get(s)??this.deltaCallbacks.get(s);if(null!=i)switch(e.axis){case"x":i((t.clientX-this.prevTouchEvent.clientX)*e.multiplier);break;case"y":i((t.clientY-this.prevTouchEvent.clientY)*e.multiplier)}else console.warn("No input callback for registered for mouse bind "+e.axis)}),this.prevTouchEvent=t,e.preventDefault())},this.onTouchEnd=e=>{this.prevTouchEvent=null,e.preventDefault()},this.onWheel=e=>{this.setLastActiveDevice("kbm"),this.view.paused||this.wheelbinds.forEach((t,s)=>{const i=this.inputs.get(s)??this.deltaCallbacks.get(s);null!=i?i(e.deltaY*t.multiplier):console.warn("No input callback for registered for wheel bind")})}}getLastActiveDevice(){return this.lastActiveDevice}setLastActiveDevice(e){this.lastActiveDevice!==e&&(this.lastActiveDevice=e,this.onDeviceChanged.next(e))}start(){document.addEventListener("keydown",this.onKeyDown),document.addEventListener("mousedown",this.onKeyDown),document.addEventListener("mouseup",this.onKeyUp),document.addEventListener("keyup",this.onKeyUp),document.addEventListener("mousemove",this.onMouseMove),this.view.htmlElement.addEventListener("touchstart",this.onTouchStart,{passive:!1}),this.view.htmlElement.addEventListener("touchmove",this.onTouchMove,{passive:!1}),this.view.htmlElement.addEventListener("touchend",this.onTouchEnd,{passive:!1}),document.addEventListener("wheel",this.onWheel)}stop(){document.removeEventListener("keydown",this.onKeyDown),document.removeEventListener("mousedown",this.onKeyDown),document.removeEventListener("mouseup",this.onKeyUp),document.removeEventListener("keyup",this.onKeyUp),document.removeEventListener("mousemove",this.onMouseMove),this.view.htmlElement.removeEventListener("touchstart",this.onTouchStart),this.view.htmlElement.removeEventListener("touchmove",this.onTouchMove),this.view.htmlElement.removeEventListener("touchend",this.onTouchEnd),document.removeEventListener("wheel",this.onWheel)}update(e){if(this.view.paused)return;const t=navigator.getGamepads();for(let e=0;e<t.length;e++){const s=t[e];if(!s||"standard"!==s.mapping)continue;let i=this.prevGamepadButtonStates.get(e);null==i&&(i=new Array(s.buttons.length).fill(!1),this.prevGamepadButtonStates.set(e,i)),this.gamepadButtonBinds.forEach((e,t)=>{for(const n of e){const e=n.button,o=s.buttons[e];if(!o)continue;const a=o.pressed,h=o.value,l=i[e];if(a!==l){this.setLastActiveDevice("gamepad");const e=this.toggleCallbacks.get(t);e&&e(a)}const c=this.inputs.get(t)??this.deltaCallbacks.get(t);c&&(h>0||a||l&&0===h)&&"gamepad"===this.lastActiveDevice&&c(h)}});for(let e=0;e<s.buttons.length;e++)i[e]=s.buttons[e].pressed;this.gamepadAxisBinds.forEach((e,t)=>{for(const i of e){let e=s.axes[i.axis];if(e=Math.abs(e)<i.deadzone?0:(e-Math.sign(e)*i.deadzone)/(1-i.deadzone),0!==e&&this.setLastActiveDevice("gamepad"),"gamepad"!==this.lastActiveDevice)break;e*=i.multiplier;const n=this.inputs.get(t)??this.deltaCallbacks.get(t);n&&n(e)}})}}bind(e,t){this.inputs.set(e,t)}bindToggle(e,t){this.toggleCallbacks.set(e,t)}bindDelta(e,t){this.deltaCallbacks.set(e,t)}unbind(e){this.inputs.delete(e),this.toggleCallbacks.delete(e),this.deltaCallbacks.delete(e)}setKeybind(e,t){this.keybinds.has(e)||this.keybinds.set(e,[]),this.keybinds.get(e).push(t)}setMousebind(e,t){this.mousebinds.set(e,t)}setTouchMoveBind(e,t){this.touchmoveBinds.set(e,t)}setWheelbind(e,t){this.wheelbinds.set(e,t)}setGamepadButtonBind(e,t){this.gamepadButtonBinds.has(e)||this.gamepadButtonBinds.set(e,[]),this.gamepadButtonBinds.get(e).push(t)}setGamepadAxisBind(e,t){this.gamepadAxisBinds.has(e)||this.gamepadAxisBinds.set(e,[]),this.gamepadAxisBinds.get(e).push(t)}removeKeybind(e){this.keybinds.delete(e)}removeMousebind(e){this.mousebinds.delete(e)}removeWheelbind(e){this.wheelbinds.delete(e)}removeGamepadButtonBind(e){this.gamepadButtonBinds.delete(e)}removeGamepadAxisBind(e){this.gamepadAxisBinds.delete(e)}vibrate(e,t=1,s=1){const i=navigator.getGamepads();for(const n of i)n&&n.vibrationActuator&&n.vibrationActuator.playEffect("dual-rumble",{startDelay:0,duration:e,weakMagnitude:s,strongMagnitude:t})}};a=e([t()],a);export{a as InputService};/*
1
+ import{__decorate as e}from"tslib";import{Service as t}from"typedi";import{inject as s}from"../inject.js";import{ViewController as i}from"../services/render.js";import{MathUtils as n}from"three";import{Subject as o}from"rxjs";let a=class{constructor(){this.view=s(i),this.inputs=new Map,this.deltaCallbacks=new Map,this.toggleCallbacks=new Map,this.keybinds=new Map,this.mousebinds=new Map,this.touchmoveBinds=new Map,this.wheelbinds=new Map,this.gamepadButtonBinds=new Map,this.gamepadAxisBinds=new Map,this.lastActiveDevice="kbm",this.onDeviceChanged=new o,this.prevGamepadButtonStates=new Map,this.suppressedGamepadButtons=new Map,this.onKeyDown=e=>{this.setLastActiveDevice("kbm"),this.view.paused||this.keybinds.forEach((t,s)=>{for(const i of t)if(i.test(e))if(this.inputs.has(s))this.inputs.get(s)(!0);else if(this.toggleCallbacks.has(s)){this.toggleCallbacks.get(s)(!0);this.activeToggleCallbacks.findIndex(e=>e.keybind===i&&e.toggle===this.toggleCallbacks.get(s))<0&&this.activeToggleCallbacks.push({keybind:i,toggle:this.toggleCallbacks.get(s)})}else console.warn("No input callback for registered for key bind "+i.display())})},this.activeToggleCallbacks=[],this.onKeyUp=e=>{this.setLastActiveDevice("kbm"),this.keybinds.forEach((t,s)=>{for(const i of t)if(i.test(e))if(this.inputs.has(s))this.inputs.get(s)(!1);else if(this.toggleCallbacks.has(s)){this.toggleCallbacks.get(s)(!1);const e=this.activeToggleCallbacks.findIndex(e=>e.keybind===i&&e.toggle===this.toggleCallbacks.get(s));e>=0&&this.activeToggleCallbacks.splice(e,1);for(const e of this.activeToggleCallbacks)e.toggle(!0)}else console.warn("No input callback for registered for key bind "+i.display())})},this.onMouseMove=e=>{if((Math.abs(e.movementX)>1||Math.abs(e.movementY)>1)&&this.setLastActiveDevice("kbm"),this.view.paused)return;if(!(null!=document.pointerLockElement||null!=document.mozPointerLockElement))return;const t=n.clamp(e.movementX,-50,50),s=n.clamp(e.movementY,-50,50);Math.abs(t)>200||Math.abs(s)>200||this.mousebinds.forEach((e,i)=>{const n=this.inputs.get(i)??this.deltaCallbacks.get(i);if(null!=n)switch(e.axis){case"x":n(t*e.multiplier);break;case"y":n(s*e.multiplier)}else console.warn("No input callback for registered for mouse bind "+e.axis)})},this.onTouchStart=e=>{if(this.setLastActiveDevice("kbm"),!this.view.paused){for(let t=0;t<=e.touches.length;t++){const s=e.touches[t];if(s?.target instanceof HTMLCanvasElement)return void(this.prevTouchEvent=s)}e.preventDefault()}},this.onTouchMove=e=>{if(this.view.paused)return;if(null==this.prevTouchEvent)return;let t=null;for(let s=0;s<=e.touches.length;s++){const i=e.touches[s];if(i&&i.target instanceof HTMLCanvasElement&&i.identifier===this.prevTouchEvent.identifier){t=i;break}}null!=t&&(this.touchmoveBinds.forEach((e,s)=>{const i=this.inputs.get(s)??this.deltaCallbacks.get(s);if(null!=i)switch(e.axis){case"x":i((t.clientX-this.prevTouchEvent.clientX)*e.multiplier);break;case"y":i((t.clientY-this.prevTouchEvent.clientY)*e.multiplier)}else console.warn("No input callback for registered for mouse bind "+e.axis)}),this.prevTouchEvent=t,e.preventDefault())},this.onTouchEnd=e=>{this.prevTouchEvent=null,e.preventDefault()},this.onWheel=e=>{this.setLastActiveDevice("kbm"),this.view.paused||this.wheelbinds.forEach((t,s)=>{const i=this.inputs.get(s)??this.deltaCallbacks.get(s);null!=i?i(e.deltaY*t.multiplier):console.warn("No input callback for registered for wheel bind")})}}getLastActiveDevice(){return this.lastActiveDevice}suppressHeldGamepadButtonsUntilRelease(){const e=navigator.getGamepads();for(let t=0;t<e.length;t++){const s=e[t];if(!s||"standard"!==s.mapping)continue;let i=this.suppressedGamepadButtons.get(t);null==i&&(i=new Array(s.buttons.length).fill(!1),this.suppressedGamepadButtons.set(t,i));for(let e=0;e<s.buttons.length;e++)s.buttons[e].pressed&&(i[e]=!0)}}setLastActiveDevice(e){this.lastActiveDevice!==e&&(this.lastActiveDevice=e,this.onDeviceChanged.next(e))}start(){document.addEventListener("keydown",this.onKeyDown),document.addEventListener("mousedown",this.onKeyDown),document.addEventListener("mouseup",this.onKeyUp),document.addEventListener("keyup",this.onKeyUp),document.addEventListener("mousemove",this.onMouseMove),this.view.htmlElement.addEventListener("touchstart",this.onTouchStart,{passive:!1}),this.view.htmlElement.addEventListener("touchmove",this.onTouchMove,{passive:!1}),this.view.htmlElement.addEventListener("touchend",this.onTouchEnd,{passive:!1}),document.addEventListener("wheel",this.onWheel)}stop(){document.removeEventListener("keydown",this.onKeyDown),document.removeEventListener("mousedown",this.onKeyDown),document.removeEventListener("mouseup",this.onKeyUp),document.removeEventListener("keyup",this.onKeyUp),document.removeEventListener("mousemove",this.onMouseMove),this.view.htmlElement.removeEventListener("touchstart",this.onTouchStart),this.view.htmlElement.removeEventListener("touchmove",this.onTouchMove),this.view.htmlElement.removeEventListener("touchend",this.onTouchEnd),document.removeEventListener("wheel",this.onWheel)}update(e){if(this.view.paused)return;const t=navigator.getGamepads();for(let e=0;e<t.length;e++){const s=t[e];if(!s||"standard"!==s.mapping)continue;let i=this.prevGamepadButtonStates.get(e);null==i&&(i=new Array(s.buttons.length).fill(!1),this.prevGamepadButtonStates.set(e,i));let n=this.suppressedGamepadButtons.get(e);null==n&&(n=new Array(s.buttons.length).fill(!1),this.suppressedGamepadButtons.set(e,n)),this.gamepadButtonBinds.forEach((e,t)=>{for(const o of e){const e=o.button,a=s.buttons[e];if(!a)continue;const l=a.pressed,h=a.value,d=i[e];if(n[e]){l||(n[e]=!1);continue}if(l!==d){this.setLastActiveDevice("gamepad");const e=this.toggleCallbacks.get(t);e&&e(l)}const c=this.inputs.get(t)??this.deltaCallbacks.get(t);c&&(h>0||l||d&&0===h)&&"gamepad"===this.lastActiveDevice&&c(h)}});for(let e=0;e<s.buttons.length;e++)i[e]=s.buttons[e].pressed;this.gamepadAxisBinds.forEach((e,t)=>{for(const i of e){let e=s.axes[i.axis];if(e=Math.abs(e)<i.deadzone?0:(e-Math.sign(e)*i.deadzone)/(1-i.deadzone),0!==e&&this.setLastActiveDevice("gamepad"),"gamepad"!==this.lastActiveDevice)break;e*=i.multiplier;const n=this.inputs.get(t)??this.deltaCallbacks.get(t);n&&n(e)}})}}bind(e,t){this.inputs.set(e,t)}bindToggle(e,t){this.toggleCallbacks.set(e,t)}bindDelta(e,t){this.deltaCallbacks.set(e,t)}unbind(e){this.inputs.delete(e),this.toggleCallbacks.delete(e),this.deltaCallbacks.delete(e)}setKeybind(e,t){this.keybinds.has(e)||this.keybinds.set(e,[]),this.keybinds.get(e).push(t)}setMousebind(e,t){this.mousebinds.set(e,t)}setTouchMoveBind(e,t){this.touchmoveBinds.set(e,t)}setWheelbind(e,t){this.wheelbinds.set(e,t)}setGamepadButtonBind(e,t){this.gamepadButtonBinds.has(e)||this.gamepadButtonBinds.set(e,[]),this.gamepadButtonBinds.get(e).push(t)}setGamepadAxisBind(e,t){this.gamepadAxisBinds.has(e)||this.gamepadAxisBinds.set(e,[]),this.gamepadAxisBinds.get(e).push(t)}removeKeybind(e){this.keybinds.delete(e)}removeMousebind(e){this.mousebinds.delete(e)}removeWheelbind(e){this.wheelbinds.delete(e)}removeGamepadButtonBind(e){this.gamepadButtonBinds.delete(e)}removeGamepadAxisBind(e){this.gamepadAxisBinds.delete(e)}vibrate(e,t=1,s=1){const i=navigator.getGamepads();for(const n of i)n&&n.vibrationActuator&&n.vibrationActuator.playEffect("dual-rumble",{startDelay:0,duration:e,weakMagnitude:s,strongMagnitude:t})}};a=e([t()],a);export{a as InputService};/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -59,6 +59,8 @@ export declare class AssetLoader {
59
59
  getSequenceByName(name: string): Promise<Sequence>;
60
60
  getDataAssetById<T = unknown>(id: AssetId, type?: Type<T>): Promise<DataAssetRef<T> | null>;
61
61
  getDataAssetByName<T = unknown>(name: string, type?: Type<T>): Promise<DataAssetRef<T> | null>;
62
+ private getDataAssetsByDefinition;
63
+ getDataAssetsByType<T>(type: Type<T>): Promise<T[]>;
62
64
  getShaderGraphByAssetId(id: AssetId): Promise<ShaderGraphDocument>;
63
65
  prepareShaderGraphParameters(graph: ShaderGraphDocument, params?: Record<string, any>): Promise<Record<string, unknown>>;
64
66
  getMaterialByAssetId(id: AssetId): Promise<Material>;
@@ -1,4 +1,4 @@
1
- import{__decorate as e,__metadata as t}from"tslib";import{AudioLoader as s,LoadingManager as a,TextureLoader as r}from"three";import{FBXLoader as i,GLTFLoader as n,MTLLoader as o,OBJLoader as h,TGALoader as d}from"three-stdlib";import{KTX2Loader as c}from"three/examples/jsm/Addons.js";import{Service as l}from"typedi";import{AssetResourceLoader as u}from"../../scene/asset-resource-loader.js";import{applyMaterial as w}from"../../scene/materializer";import{materialFromAsset as g,materializeDataAssetRef as f,prepareShaderGraphParameters as m}from"../../scene/materializer.js";import{Prefab as y}from"../../scene/objects/prefab.js";import{pathJoin as A}from"../../utils/files.js";import{Sequence as p}from"../../effects/sequence/sequence-data.js";import{resolveAnimationClipAssetForTarget as b}from"../animation/retarget.js";let v=class{constructor(e,t,l){this.assetResourceLoader=e,this.assetService=t,this.shaders=l,this.baseUrl="",this.urlSuffix="",this.loadingManager=new a,this.glbLoader=new n(this.loadingManager),this.fbxLoader=new i(this.loadingManager),this.objLoader=new h(this.loadingManager),this.mtlLoader=new o(this.loadingManager),this.tgaLoader=new d(this.loadingManager),this.ktx2Loader=new c(this.loadingManager),this.textureLoader=new r(this.loadingManager),this.audioLoader=new s(this.loadingManager),this.animationVariantIds=new Map,this.assetResourceLoader.materialProvider=e=>this.getMaterialByAssetId(e),this.assetResourceLoader.animationRigProvider=async e=>(await this.assetService.getAsset(e))?.animationRig}resolvePath(e){return A(this.baseUrl,e)+this.urlSuffix}getAudioAtPath(e){const t=this.resolvePath(e);return this.audioLoader.loadAsync(t)}async getAudioByAssetId(e){const t=await this.assetService.getAsset(e);if(null==t)throw new Error(`No audio could be found with asset id ${e}`);return this.assetResourceLoader.getAudio(t)}async getAudioByAssetName(e){const t=await this.assetService.getAsset(e);if(null==t)throw new Error(`No audio could be found with asset name ${e}`);return this.assetResourceLoader.getAudio(t)}async getModelAtPath(e){const t=this.resolvePath(e);switch(e.split(".").pop().toLowerCase()){case"glb":case"gltf":return(await this.glbLoader.loadAsync(t)).scene;case"fbx":return this.fbxLoader.loadAsync(t);case"obj":return this.objLoader.loadAsync(t);default:throw new Error(`File suffix is not supperted in file ${e}`)}}async getGltfAtPath(e){const t=this.resolvePath(e);return this.glbLoader.loadAsync(t)}async getModelByAssetName(e){const t=(await this.assetService.getAssets()).find(t=>t.name===e);if(null==t)throw new Error(`No model could be found with asset name ${e}`);return this.assetResourceLoader.getMesh(t,{applyMaterials:!0,materialResolver:e=>this.getMaterialByAssetId(e)})}async getModelByAssetId(e){const t=await this.assetService.getAsset(e);if(null==t)throw new Error(`No model could be found with asset id ${e}`);return this.assetResourceLoader.getMesh(t,{applyMaterials:!0,materialResolver:e=>this.getMaterialByAssetId(e)})}async getAnimationClipByAssetId(e){const t=await this.assetService.getAsset(e);if(null==t)throw new Error(`No animation clip could be found with asset id ${e}`);return this.assetResourceLoader.getAnimationClip(t)}async getAnimationClipForTargetByAssetId(e,t){const s=await this.assetService.getAsset(e);if(null==s)throw new Error(`No animation clip could be found with asset id ${e}`);let a=s;if(null!=t&&s.anim?.rigId!==t){const r=`${e}|${t}`,i=this.animationVariantIds.get(r);null!=i?a=await this.assetService.getAsset(i):(a=b(s,await this.assetService.getAssets(),t),this.animationVariantIds.set(r,a.id))}return this.assetResourceLoader.getAnimationClip(a)}async getAnimationClipByAssetName(e){const t=(await this.assetService.getAssets()).find(t=>t.name===e);if(null==t)throw new Error(`No animation clip could be found with asset name ${e}`);return this.assetResourceLoader.getAnimationClip(t)}async applyMaterials(e,t){for(const s of e.materialAssignments??[])await w(t,s,async e=>this.getMaterialByAssetId(e))}async getTextureByAssetName(e){const t=(await this.assetService.getAssets()).find(t=>t.name===e);if(null==t)throw new Error(`No texture could be found with asset name ${e}`);return this.assetResourceLoader.getTexture(t)}async getTextureByAssetId(e){const t=await this.assetService.getAsset(e);if(null==t)throw new Error(`No texture could be found with asset id ${e}`);return this.assetResourceLoader.getTexture(t)}async getSequenceById(e){const t=await this.assetService.getAsset(e);if(null==t)throw new Error(`No sequence could be found with asset id ${e}`);if(null==t.sequence)throw new Error(`Missing sequence data in asset ${e}`);return new p(t.sequence)}async getSequenceByName(e){const t=(await this.assetService.getAssets()).find(t=>t.name===e);if(null==t)throw new Error(`No sequence could be found with asset name ${e}`);if(null==t.sequence)throw new Error(`Missing sequence data in asset ${e}`);return new p(t.sequence)}async getDataAssetById(e,t){const s=await f(e,this.assetService,this.assetResourceLoader,void 0,void 0,this.shaders);if(null!=t&&null!=s&&!(s.value instanceof t))throw new Error(`Invalid type. Expecting asset with id ${e} to be of type ${t.name} but got:`+s.value);return s}async getDataAssetByName(e,t){const s=(await this.assetService.getAssets()).find(t=>t.name===e);if(null==s)throw new Error(`No data asset could be found with name ${e}`);return this.getDataAssetById(s.id,t)}async getShaderGraphByAssetId(e){const t=await this.assetService.getAsset(e);if(null==t)throw new Error(`No shader graph could be found with asset id ${e}`);if("shaderGraph"!==t.type||null==t.shaderGraph)throw new Error(`Missing shader graph data in asset ${e}`);return t.shaderGraph}async prepareShaderGraphParameters(e,t={}){return m(t,e,this.assetService,this.assetResourceLoader,void 0,this.shaders)}async getMaterialByAssetId(e){const t=await this.assetService.getAsset(e);if(null==t)throw new Error(`No material could be found with asset id ${e}`);return g(t,null,this.assetService,this.assetResourceLoader,this.shaders,!1)}async getAsset(e){return this.assetService.getAsset(e)}async getPrefabByName(e){const t=(await this.assetService.getAssets()).find(t=>t.name===e);if("prefab"!==t.type)throw`Asset with name ${e} is not a prefab`;return new y(t)}async getPrefabById(e){const t=await this.getAsset(e);if("prefab"!==t.type)throw`Asset with name ${name} is not a prefab`;return new y(t)}clearCache(e){this.animationVariantIds.clear(),this.assetResourceLoader.clearCache(e)}clearCacheById(e){this.animationVariantIds.clear(),this.assetResourceLoader.clearCacheById(e)}};v=e([l(),t("design:paramtypes",[u,Function,Array])],v);export{v as AssetLoader};/*
1
+ import{__decorate as e,__metadata as t}from"tslib";import{AudioLoader as s,LoadingManager as a,TextureLoader as r}from"three";import{FBXLoader as i,GLTFLoader as n,MTLLoader as o,OBJLoader as h,TGALoader as d}from"three-stdlib";import{KTX2Loader as c}from"three/examples/jsm/Addons.js";import{Service as l}from"typedi";import{AssetResourceLoader as u}from"../../scene/asset-resource-loader.js";import{applyMaterial as g}from"../../scene/materializer";import{materialFromAsset as w,materializeDataAssetRef as f,prepareShaderGraphParameters as m}from"../../scene/materializer.js";import{Prefab as y}from"../../scene/objects/prefab.js";import{pathJoin as A}from"../../utils/files.js";import{Sequence as p}from"../../effects/sequence/sequence-data.js";import{resolveAnimationClipAssetForTarget as b}from"../animation/retarget.js";import{getDataAssetDefinitionId as v}from"@hology/core/shader/parameter";let L=class{constructor(e,t,l){this.assetResourceLoader=e,this.assetService=t,this.shaders=l,this.baseUrl="",this.urlSuffix="",this.loadingManager=new a,this.glbLoader=new n(this.loadingManager),this.fbxLoader=new i(this.loadingManager),this.objLoader=new h(this.loadingManager),this.mtlLoader=new o(this.loadingManager),this.tgaLoader=new d(this.loadingManager),this.ktx2Loader=new c(this.loadingManager),this.textureLoader=new r(this.loadingManager),this.audioLoader=new s(this.loadingManager),this.animationVariantIds=new Map,this.assetResourceLoader.materialProvider=e=>this.getMaterialByAssetId(e),this.assetResourceLoader.animationRigProvider=async e=>(await this.assetService.getAsset(e))?.animationRig}resolvePath(e){return A(this.baseUrl,e)+this.urlSuffix}getAudioAtPath(e){const t=this.resolvePath(e);return this.audioLoader.loadAsync(t)}async getAudioByAssetId(e){const t=await this.assetService.getAsset(e);if(null==t)throw new Error(`No audio could be found with asset id ${e}`);return this.assetResourceLoader.getAudio(t)}async getAudioByAssetName(e){const t=await this.assetService.getAsset(e);if(null==t)throw new Error(`No audio could be found with asset name ${e}`);return this.assetResourceLoader.getAudio(t)}async getModelAtPath(e){const t=this.resolvePath(e);switch(e.split(".").pop().toLowerCase()){case"glb":case"gltf":return(await this.glbLoader.loadAsync(t)).scene;case"fbx":return this.fbxLoader.loadAsync(t);case"obj":return this.objLoader.loadAsync(t);default:throw new Error(`File suffix is not supperted in file ${e}`)}}async getGltfAtPath(e){const t=this.resolvePath(e);return this.glbLoader.loadAsync(t)}async getModelByAssetName(e){const t=(await this.assetService.getAssets()).find(t=>t.name===e);if(null==t)throw new Error(`No model could be found with asset name ${e}`);return this.assetResourceLoader.getMesh(t,{applyMaterials:!0,materialResolver:e=>this.getMaterialByAssetId(e)})}async getModelByAssetId(e){const t=await this.assetService.getAsset(e);if(null==t)throw new Error(`No model could be found with asset id ${e}`);return this.assetResourceLoader.getMesh(t,{applyMaterials:!0,materialResolver:e=>this.getMaterialByAssetId(e)})}async getAnimationClipByAssetId(e){const t=await this.assetService.getAsset(e);if(null==t)throw new Error(`No animation clip could be found with asset id ${e}`);return this.assetResourceLoader.getAnimationClip(t)}async getAnimationClipForTargetByAssetId(e,t){const s=await this.assetService.getAsset(e);if(null==s)throw new Error(`No animation clip could be found with asset id ${e}`);let a=s;if(null!=t&&s.anim?.rigId!==t){const r=`${e}|${t}`,i=this.animationVariantIds.get(r);null!=i?a=await this.assetService.getAsset(i):(a=b(s,await this.assetService.getAssets(),t),this.animationVariantIds.set(r,a.id))}return this.assetResourceLoader.getAnimationClip(a)}async getAnimationClipByAssetName(e){const t=(await this.assetService.getAssets()).find(t=>t.name===e);if(null==t)throw new Error(`No animation clip could be found with asset name ${e}`);return this.assetResourceLoader.getAnimationClip(t)}async applyMaterials(e,t){for(const s of e.materialAssignments??[])await g(t,s,async e=>this.getMaterialByAssetId(e))}async getTextureByAssetName(e){const t=(await this.assetService.getAssets()).find(t=>t.name===e);if(null==t)throw new Error(`No texture could be found with asset name ${e}`);return this.assetResourceLoader.getTexture(t)}async getTextureByAssetId(e){const t=await this.assetService.getAsset(e);if(null==t)throw new Error(`No texture could be found with asset id ${e}`);return this.assetResourceLoader.getTexture(t)}async getSequenceById(e){const t=await this.assetService.getAsset(e);if(null==t)throw new Error(`No sequence could be found with asset id ${e}`);if(null==t.sequence)throw new Error(`Missing sequence data in asset ${e}`);return new p(t.sequence)}async getSequenceByName(e){const t=(await this.assetService.getAssets()).find(t=>t.name===e);if(null==t)throw new Error(`No sequence could be found with asset name ${e}`);if(null==t.sequence)throw new Error(`Missing sequence data in asset ${e}`);return new p(t.sequence)}async getDataAssetById(e,t){const s=await f(e,this.assetService,this.assetResourceLoader,void 0,void 0,this.shaders);if(null!=t&&null!=s&&!(s.value instanceof t))throw new Error(`Invalid type. Expecting asset with id ${e} to be of type ${t.name} but got:`+s.value);return s}async getDataAssetByName(e,t){const s=(await this.assetService.getAssets()).find(t=>t.name===e);if(null==s)throw new Error(`No data asset could be found with name ${e}`);return this.getDataAssetById(s.id,t)}async getDataAssetsByDefinition(e,t){const s=(await this.assetService.getAssets()).filter(t=>t.dataAsset?.definition===e);if(0===s.length)throw new Error(`No data assets could be found with definition ${e}`);return Promise.all(s.map(e=>this.getDataAssetById(e.id,t).then(e=>e?.value)))}async getDataAssetsByType(e){const t=v(e);return this.getDataAssetsByDefinition(t,e)}async getShaderGraphByAssetId(e){const t=await this.assetService.getAsset(e);if(null==t)throw new Error(`No shader graph could be found with asset id ${e}`);if("shaderGraph"!==t.type||null==t.shaderGraph)throw new Error(`Missing shader graph data in asset ${e}`);return t.shaderGraph}async prepareShaderGraphParameters(e,t={}){return m(t,e,this.assetService,this.assetResourceLoader,void 0,this.shaders)}async getMaterialByAssetId(e){const t=await this.assetService.getAsset(e);if(null==t)throw new Error(`No material could be found with asset id ${e}`);return w(t,null,this.assetService,this.assetResourceLoader,this.shaders,!1)}async getAsset(e){return this.assetService.getAsset(e)}async getPrefabByName(e){const t=(await this.assetService.getAssets()).find(t=>t.name===e);if("prefab"!==t.type)throw`Asset with name ${e} is not a prefab`;return new y(t)}async getPrefabById(e){const t=await this.getAsset(e);if("prefab"!==t.type)throw`Asset with name ${name} is not a prefab`;return new y(t)}clearCache(e){this.animationVariantIds.clear(),this.assetResourceLoader.clearCache(e)}clearCacheById(e){this.animationVariantIds.clear(),this.assetResourceLoader.clearCacheById(e)}};L=e([l(),t("design:paramtypes",[u,Function,Array])],L);export{L as AssetLoader};/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -385,6 +385,8 @@ export declare class SceneMaterializer {
385
385
  detailTier: DetailTier;
386
386
  constructor(scene: Scene, dataProvider: SceneDataProvider, assetsService: AssetsProvider, assetManagerService: AssetResourceLoader, renderingView: RenderingView, shaders: ShaderImpl[], actorTypes: ActorImpl[], actorProvider: ActorProvider, componentTypes?: ClassImpl<ActorComponent>[]);
387
387
  private refreshMaterialTextures;
388
+ private materialUsesTexture;
389
+ private replaceMaterialTextureReferences;
388
390
  private getAsset;
389
391
  private refreshMaterial;
390
392
  private vfxAssetUsesShaderGraph;