diff --git a/src/app/ProjectSchedulePane.tsx b/src/app/ProjectSchedulePane.tsx index be8c591d..4b26f759 100644 --- a/src/app/ProjectSchedulePane.tsx +++ b/src/app/ProjectSchedulePane.tsx @@ -943,13 +943,15 @@ export function ProjectSequencerPane({ onChange={(event) => onSetRoutineSequenceId( selectedRoutine.id, - event.currentTarget.value === "" - ? null - : event.currentTarget.value + event.currentTarget.value ) } > - This Placement (inline effects) + {selectedRoutine.sequenceId === null ? ( + + Select Sequence + + ) : null} {compatibleHeldSequences.map((sequence) => ( {sequence.title} @@ -958,83 +960,44 @@ export function ProjectSequencerPane({ - { - onSelectSequence(selectedRoutine.sequenceId ?? selectedSequenceId); - onSetMode("sequence"); - }} - > - Edit Sequences - + {selectedRoutine.sequenceId === null ? ( + onCreateRoutineSequence(selectedRoutine.id)} + > + Create Attached Sequence + + ) : ( + { + onSelectSequence( + selectedRoutine.sequenceId ?? selectedSequenceId + ); + onSetMode("sequence"); + }} + > + Edit Sequence + + )} - {selectedRoutine.sequenceId !== null ? ( + {selectedAttachedSequence !== null ? ( - This placement resolves held effects from the selected - sequence. Inline effects stay preserved as fallback, but are - not edited while a sequence is attached. + This placement resolves held effects from{" "} + {selectedAttachedSequence.title}. + Edit animation, path, presence, lighting, or other held + engine effects in the Sequence Editor. ) : null} - {selectedRoutine.sequenceId === null && - compatibleHeldSequences.length === 0 ? ( + {selectedRoutine.sequenceId === null ? ( {selectedRoutine.target.kind === "global" - ? "No compatible impulse sequence is authored yet for this project event lane. Use Sequence Editor to author one-shot effects like scene transitions, dialogue starts, or teleports." - : "No compatible sequence with held effects is authored for this target yet. Use Sequence Editor to author effects, or keep this placement on its own inline effects."} + ? "Project event placements run attached sequences only. Create a sequence with impulse effects like scene transitions, dialogue starts, or teleports." + : "This placement has no attached sequence yet. Create one, then author presence, animation, path, lighting, sound, or other engine effects inside the Sequence Editor."} ) : null} - {selectedRoutine.sequenceId === null && - selectedRoutine.target.kind === "actor" ? ( - <> - - Presence - - onSetActorRoutinePresence( - selectedRoutine.id, - event.currentTarget.value !== "hidden" - ) - } - > - Present - Hidden - - - > - ) : selectedRoutine.target.kind === "global" ? ( - - Project event placements run attached sequences only. Add or - pick a sequence with impulse effects like scene transitions, - dialogue starts, teleports, or other one-shot engine events. - - ) : selectedRoutine.sequenceId === null ? ( - - Effect - - onSetRoutineEffectOption( - selectedRoutine.id, - event.currentTarget.value as ProjectScheduleEffectOptionId - ) - } - > - {selectedEffectOptions.map((effectOption) => ( - - {effectOption.label} - - ))} - - - ) : null} - {selectedRoutine.sequenceId === null && - selectedRoutine.target.kind === "actor" ? ( - <> - - Animation - - Clip - - onSetActorRoutineAnimationClip( - selectedRoutine.id, - event.currentTarget.value === "" - ? null - : event.currentTarget.value - ) - } - > - None - {(selectedTargetOption.defaults.actorAnimationClipNames ?? []).map( - (clipName) => ( - - {clipName} - - ) - )} - - - - - onSetActorRoutineAnimationLoop( - selectedRoutine.id, - event.currentTarget.checked - ) - } - /> - Loop - - {(selectedTargetOption.defaults.actorAnimationClipNames ?? []) - .length === 0 ? ( - - Animation clips are available only when this actor has one - uniquely bound NPC model with imported clips. - - ) : null} - - - - Path - - Path - - onSetActorRoutinePath( - selectedRoutine.id, - event.currentTarget.value === "" - ? null - : event.currentTarget.value - ) - } - > - None - {(selectedTargetOption.defaults.actorPathOptions ?? []).map( - (pathOption) => ( - - {pathOption.label} - - ) - )} - - - - Speed - - onSetActorRoutinePathSpeed( - selectedRoutine.id, - Number(event.currentTarget.value) - ) - } - onKeyDown={(event) => - handleCommitOnEnter(event, () => - onSetActorRoutinePathSpeed( - selectedRoutine.id, - Number(event.currentTarget.value) - ) - ) - } - /> - - - - onSetActorRoutinePathLoop( - selectedRoutine.id, - event.currentTarget.checked - ) - } - /> - Loop - - {(selectedTargetOption.defaults.actorPathOptions ?? []).length === - 0 ? ( - - Paths are available only when this actor has one uniquely - bound NPC usage in a scene with enabled authored paths. - - ) : null} - - > - ) : selectedRoutine.target.kind === "global" ? null : selectedRoutine.sequenceId === null ? ( - <> - {selectedEffectOptions.find( - (effectOption) => effectOption.id === selectedEffectOptionId - )?.valueKind === "number" ? ( - - Value - - - {selectedEffectOptions.find( - (effectOption) => - effectOption.id === selectedEffectOptionId - )?.valueLabel ?? "Value"} - - - effectOption.id === selectedEffectOptionId - )?.min ?? 0 - } - step={ - selectedEffectOptions.find( - (effectOption) => - effectOption.id === selectedEffectOptionId - )?.step ?? 0.1 - } - defaultValue={getRoutineNumericValue(selectedRoutine) ?? 0} - onBlur={(event) => - onSetRoutineNumericValue( - selectedRoutine.id, - Number(event.currentTarget.value) - ) - } - onKeyDown={(event) => - handleCommitOnEnter(event, () => - onSetRoutineNumericValue( - selectedRoutine.id, - Number(event.currentTarget.value) - ) - ) - } - /> - - - ) : null} - - {selectedEffectOptions.find( - (effectOption) => effectOption.id === selectedEffectOptionId - )?.valueKind === "color" ? ( - - Value - - - {selectedEffectOptions.find( - (effectOption) => - effectOption.id === selectedEffectOptionId - )?.valueLabel ?? "Color"} - - - onSetRoutineColorValue( - selectedRoutine.id, - event.currentTarget.value - ) - } - /> - - - ) : null} - - {selectedEffectOptions.find( - (effectOption) => effectOption.id === selectedEffectOptionId - )?.valueKind === "animation" ? ( - - Animation - - Clip - - onSetRoutineAnimationClip( - selectedRoutine.id, - event.currentTarget.value - ) - } - > - {(selectedTargetOption.defaults.animationClipNames ?? []).map( - (clipName) => ( - - {clipName} - - ) - )} - - - - - onSetRoutineAnimationLoop( - selectedRoutine.id, - event.currentTarget.checked - ) - } - /> - Loop - - - ) : null} - > - ) : null} - Details