From a7e01f08b987fa8648e5fd2866e1c3b94a939062 Mon Sep 17 00:00:00 2001 From: Victor Giers Date: Wed, 15 Apr 2026 01:29:05 +0200 Subject: [PATCH] Add teleport and visibility effects to project sequences --- src/app/App.tsx | 98 +++++++++++++++++++++++++++++++++ src/app/ProjectSchedulePane.tsx | 41 +++++++++++++- 2 files changed, 138 insertions(+), 1 deletion(-) diff --git a/src/app/App.tsx b/src/app/App.tsx index 9e6a8036..451286ec 100644 --- a/src/app/App.tsx +++ b/src/app/App.tsx @@ -4552,6 +4552,43 @@ export function App({ store, initialStatusMessage }: AppProps) { ); }; + const handleAddProjectSequenceTeleportStep = ( + sequenceId: string, + targetEntityId: string + ) => { + updateProjectSequence( + sequenceId, + "Add project sequence teleport effect", + "Added teleport effect.", + (sequence) => { + sequence.effects.push({ + stepClass: "impulse", + type: "teleportPlayer", + targetEntityId + }); + } + ); + }; + + const handleAddProjectSequenceVisibilityStep = ( + sequenceId: string, + targetBrushId: string + ) => { + updateProjectSequence( + sequenceId, + "Add project sequence visibility effect", + "Added visibility effect.", + (sequence) => { + sequence.effects.push({ + stepClass: "impulse", + type: "toggleVisibility", + targetBrushId, + visible: undefined + }); + } + ); + }; + const handleDeleteProjectSequenceStep = ( sequenceId: string, stepIndex: number @@ -4765,6 +4802,67 @@ export function App({ store, initialStatusMessage }: AppProps) { ); }; + const updateProjectSequenceTeleportStepTarget = ( + sequenceId: string, + stepIndex: number, + targetEntityId: string + ) => { + updateProjectSequenceStep( + sequenceId, + stepIndex, + "Set project sequence teleport target", + "Updated teleport target.", + (step) => { + if (step.type !== "teleportPlayer") { + throw new Error("Only teleport effects expose a teleport target."); + } + + step.targetEntityId = targetEntityId; + } + ); + }; + + const updateProjectSequenceVisibilityStepTarget = ( + sequenceId: string, + stepIndex: number, + targetBrushId: string + ) => { + updateProjectSequenceStep( + sequenceId, + stepIndex, + "Set project sequence visibility target", + "Updated visibility target.", + (step) => { + if (step.type !== "toggleVisibility") { + throw new Error("Only visibility effects expose a whitebox solid target."); + } + + step.targetBrushId = targetBrushId; + } + ); + }; + + const updateProjectSequenceVisibilityStepMode = ( + sequenceId: string, + stepIndex: number, + mode: "toggle" | "show" | "hide" + ) => { + updateProjectSequenceStep( + sequenceId, + stepIndex, + "Set project sequence visibility mode", + "Updated visibility mode.", + (step) => { + if (step.type !== "toggleVisibility") { + throw new Error("Only visibility effects expose a visibility mode."); + } + + step.visible = + mode === "toggle" ? undefined : mode === "show"; + } + ); + }; + const updateWorldTimeOfDaySettings = ( label: string, diff --git a/src/app/ProjectSchedulePane.tsx b/src/app/ProjectSchedulePane.tsx index 7c45c539..0a4b58c1 100644 --- a/src/app/ProjectSchedulePane.tsx +++ b/src/app/ProjectSchedulePane.tsx @@ -34,6 +34,14 @@ interface ProjectSequencerPaneProps { mode: "timeline" | "sequence"; onSetMode(mode: "timeline" | "sequence"): void; targetOptions: ProjectScheduleTargetOption[]; + teleportTargetOptions: Array<{ + entityId: string; + label: string; + }>; + visibilityTargetOptions: Array<{ + brushId: string; + label: string; + }>; scheduler: ProjectScheduler; sequences: ProjectSequenceLibrary; dialogues: ProjectDialogueLibrary; @@ -74,6 +82,8 @@ interface ProjectSequencerPaneProps { onAddHeldControlStep(sequenceId: string, targetKey: string): void; onAddImpulseControlStep(sequenceId: string, targetKey: string): void; onAddDialogueStep(sequenceId: string, dialogueId: string): void; + onAddTeleportStep(sequenceId: string, targetEntityId: string): void; + onAddVisibilityStep(sequenceId: string, targetBrushId: string): void; onDeleteStep(sequenceId: string, stepIndex: number): void; onSetControlStepTarget( sequenceId: string, @@ -110,6 +120,21 @@ interface ProjectSequencerPaneProps { stepIndex: number, dialogueId: string ): void; + onSetTeleportStepTarget( + sequenceId: string, + stepIndex: number, + targetEntityId: string + ): void; + onSetVisibilityStepTarget( + sequenceId: string, + stepIndex: number, + targetBrushId: string + ): void; + onSetVisibilityStepMode( + sequenceId: string, + stepIndex: number, + mode: "toggle" | "show" | "hide" + ): void; } function handleCommitOnEnter( @@ -283,6 +308,8 @@ export function ProjectSequencerPane({ mode, onSetMode, targetOptions, + teleportTargetOptions, + visibilityTargetOptions, scheduler, sequences, dialogues, @@ -317,6 +344,8 @@ export function ProjectSequencerPane({ onAddHeldControlStep, onAddImpulseControlStep, onAddDialogueStep, + onAddTeleportStep, + onAddVisibilityStep, onDeleteStep, onSetControlStepTarget, onSetControlStepEffectOption, @@ -324,7 +353,10 @@ export function ProjectSequencerPane({ onSetControlStepColorValue, onSetControlStepAnimationClip, onSetControlStepAnimationLoop, - onSetDialogueStepDialogueId + onSetDialogueStepDialogueId, + onSetTeleportStepTarget, + onSetVisibilityStepTarget, + onSetVisibilityStepMode }: ProjectSequencerPaneProps) { const selectedRoutine = selectedRoutineId === null ? null : scheduler.routines[selectedRoutineId] ?? null; @@ -442,6 +474,8 @@ export function ProjectSequencerPane({ sequences={sequences} dialogues={dialogues} targetOptions={targetOptions} + teleportTargetOptions={teleportTargetOptions} + visibilityTargetOptions={visibilityTargetOptions} selectedSequenceId={selectedSequenceId} onSelectSequence={onSelectSequence} onAddSequence={onAddSequence} @@ -450,6 +484,8 @@ export function ProjectSequencerPane({ onAddHeldControlStep={onAddHeldControlStep} onAddImpulseControlStep={onAddImpulseControlStep} onAddDialogueStep={onAddDialogueStep} + onAddTeleportStep={onAddTeleportStep} + onAddVisibilityStep={onAddVisibilityStep} onDeleteStep={onDeleteStep} onSetControlStepTarget={onSetControlStepTarget} onSetControlStepEffectOption={onSetControlStepEffectOption} @@ -458,6 +494,9 @@ export function ProjectSequencerPane({ onSetControlStepAnimationClip={onSetControlStepAnimationClip} onSetControlStepAnimationLoop={onSetControlStepAnimationLoop} onSetDialogueStepDialogueId={onSetDialogueStepDialogueId} + onSetTeleportStepTarget={onSetTeleportStepTarget} + onSetVisibilityStepTarget={onSetVisibilityStepTarget} + onSetVisibilityStepMode={onSetVisibilityStepMode} /> ) : (