feat: add playable flight and office screen sharing
This commit is contained in:
@@ -76,6 +76,10 @@ export interface SceneActor {
|
||||
switchActor(kind: ActorKind, identity?: ActorIdentity, mode?: ActorMode): ActorControllerSnapshot;
|
||||
/** Rebuild the visible skin for a new serializable identity, preserving motion and kind. */
|
||||
setIdentity(identity: ActorIdentity): ActorControllerSnapshot;
|
||||
/** Attach a caller-owned live/static face texture. False when the current actor is not humanoid. */
|
||||
attachFaceTexture(texture: THREE.Texture): boolean;
|
||||
/** Detach and release the adapter's reference without disposing the caller texture. */
|
||||
clearFaceTexture(): void;
|
||||
dispose(): void;
|
||||
}
|
||||
|
||||
@@ -137,6 +141,23 @@ function disposeRig(actor: RiggedActor): void {
|
||||
else disposeCrow(actor.rig);
|
||||
}
|
||||
|
||||
const DEFAULT_FACE_COLOR = 0x18242b;
|
||||
|
||||
function faceMaterial(rig: HumanoidRig): THREE.MeshBasicMaterial {
|
||||
const material = rig.face.material;
|
||||
if (!(material instanceof THREE.MeshBasicMaterial)) {
|
||||
throw new Error("scene actor: humanoid face must use one MeshBasicMaterial");
|
||||
}
|
||||
return material;
|
||||
}
|
||||
|
||||
function applyFaceTexture(rig: HumanoidRig, texture: THREE.Texture | null): void {
|
||||
const material = faceMaterial(rig);
|
||||
material.map = texture;
|
||||
material.color.set(texture ? 0xffffff : DEFAULT_FACE_COLOR);
|
||||
material.needsUpdate = true;
|
||||
}
|
||||
|
||||
function positive(value: number, name: string): number {
|
||||
if (!(value > 0) || !Number.isFinite(value)) throw new RangeError(`${name} must be finite and positive`);
|
||||
return value;
|
||||
@@ -177,6 +198,7 @@ export function createSceneActor(options: SceneActorOptions): SceneActor {
|
||||
root.add(actor.rig.root);
|
||||
let enabled = options.active ?? false;
|
||||
let desired: ActorActionSnapshot = { ...NEUTRAL_ACTOR_ACTIONS };
|
||||
let faceTexture: THREE.Texture | null = null;
|
||||
let disposed = false;
|
||||
|
||||
function sync(): void {
|
||||
@@ -218,6 +240,11 @@ export function createSceneActor(options: SceneActorOptions): SceneActor {
|
||||
const previous = actor;
|
||||
actor = buildActor(kind, controller.state().identity);
|
||||
root.add(actor.rig.root);
|
||||
if (actor.kind === "humanoid" && faceTexture) applyFaceTexture(actor.rig, faceTexture);
|
||||
if (previous.kind === "humanoid") applyFaceTexture(previous.rig, null);
|
||||
// A face is a humanoid-only, potentially sensitive live reference. Do not
|
||||
// retain it invisibly while the player is represented as an animal.
|
||||
if (actor.kind !== "humanoid") faceTexture = null;
|
||||
disposeRig(previous);
|
||||
sync();
|
||||
}
|
||||
@@ -299,10 +326,25 @@ export function createSceneActor(options: SceneActorOptions): SceneActor {
|
||||
replaceActor(controller.state().kind);
|
||||
return controller.snapshot();
|
||||
},
|
||||
attachFaceTexture(texture) {
|
||||
if (disposed || actor.kind !== "humanoid") return false;
|
||||
if (!texture || texture.isTexture !== true) {
|
||||
throw new RangeError("scene actor: face texture must be a Three.js Texture");
|
||||
}
|
||||
faceTexture = texture;
|
||||
applyFaceTexture(actor.rig, texture);
|
||||
return true;
|
||||
},
|
||||
clearFaceTexture() {
|
||||
faceTexture = null;
|
||||
if (!disposed && actor.kind === "humanoid") applyFaceTexture(actor.rig, null);
|
||||
},
|
||||
dispose() {
|
||||
if (disposed) return;
|
||||
disposed = true;
|
||||
root.removeFromParent();
|
||||
if (actor.kind === "humanoid") applyFaceTexture(actor.rig, null);
|
||||
faceTexture = null;
|
||||
disposeRig(actor);
|
||||
},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user