diff --git a/theatre/studio/src/panels/DetailPanel/propEditors/BooleanPropEditor.tsx b/theatre/studio/src/panels/DetailPanel/propEditors/BooleanPropEditor.tsx index 88d8d3d..53cf76a 100644 --- a/theatre/studio/src/panels/DetailPanel/propEditors/BooleanPropEditor.tsx +++ b/theatre/studio/src/panels/DetailPanel/propEditors/BooleanPropEditor.tsx @@ -15,7 +15,11 @@ const BooleanPropEditor: React.FC<{ pointerToProp: SheetObject['propsP'] obj: SheetObject }> = ({propConfig, pointerToProp, obj}) => { - const stuff = useEditingToolsForPrimitiveProp(pointerToProp, obj) + const stuff = useEditingToolsForPrimitiveProp( + pointerToProp, + obj, + propConfig, + ) const onChange = useCallback( (el: React.ChangeEvent) => { diff --git a/theatre/studio/src/panels/DetailPanel/propEditors/NumberPropEditor.tsx b/theatre/studio/src/panels/DetailPanel/propEditors/NumberPropEditor.tsx index 370c079..07f4c24 100644 --- a/theatre/studio/src/panels/DetailPanel/propEditors/NumberPropEditor.tsx +++ b/theatre/studio/src/panels/DetailPanel/propEditors/NumberPropEditor.tsx @@ -10,7 +10,11 @@ const NumberPropEditor: React.FC<{ pointerToProp: SheetObject['propsP'] obj: SheetObject }> = ({propConfig, pointerToProp, obj}) => { - const stuff = useEditingToolsForPrimitiveProp(pointerToProp, obj) + const stuff = useEditingToolsForPrimitiveProp( + pointerToProp, + obj, + propConfig, + ) const nudge = useCallback( (params: {deltaX: number; deltaFraction: number; magnitude: number}) => { diff --git a/theatre/studio/src/panels/DetailPanel/propEditors/StringLiteralPropEditor.tsx b/theatre/studio/src/panels/DetailPanel/propEditors/StringLiteralPropEditor.tsx index 214d79a..0dc7074 100644 --- a/theatre/studio/src/panels/DetailPanel/propEditors/StringLiteralPropEditor.tsx +++ b/theatre/studio/src/panels/DetailPanel/propEditors/StringLiteralPropEditor.tsx @@ -12,7 +12,11 @@ const StringLiteralPropEditor: React.FC<{ pointerToProp: SheetObject['propsP'] obj: SheetObject }> = ({propConfig, pointerToProp, obj}) => { - const stuff = useEditingToolsForPrimitiveProp(pointerToProp, obj) + const stuff = useEditingToolsForPrimitiveProp( + pointerToProp, + obj, + propConfig, + ) const onChange = useCallback( (val: string) => { diff --git a/theatre/studio/src/panels/DetailPanel/propEditors/utils/useEditingToolsForPrimitiveProp.tsx b/theatre/studio/src/panels/DetailPanel/propEditors/utils/useEditingToolsForPrimitiveProp.tsx index a7eaea1..a20eb77 100644 --- a/theatre/studio/src/panels/DetailPanel/propEditors/utils/useEditingToolsForPrimitiveProp.tsx +++ b/theatre/studio/src/panels/DetailPanel/propEditors/utils/useEditingToolsForPrimitiveProp.tsx @@ -12,6 +12,7 @@ import last from 'lodash-es/last' import React from 'react' import DefaultOrStaticValueIndicator from './DefaultValueIndicator' import NextPrevKeyframeCursors from './NextPrevKeyframeCursors' +import type {PropTypeConfig} from '@theatre/core/propTypes' interface CommonStuff { value: T @@ -44,7 +45,11 @@ type Stuff = Default | Static | Sequenced export function useEditingToolsForPrimitiveProp< T extends SerializablePrimitive, ->(pointerToProp: SheetObject['propsP'], obj: SheetObject): Stuff { +>( + pointerToProp: SheetObject['propsP'], + obj: SheetObject, + propConfig: PropTypeConfig, +): Stuff { return usePrism(() => { const pathToProp = getPointerParts(pointerToProp).path @@ -114,114 +119,118 @@ export function useEditingToolsForPrimitiveProp< controlIndicators: <>, } - const validSequencedTracks = val( - obj.template.getMapOfValidSequenceTracks_forStudio(), - ) - const possibleSequenceTrackId = getDeep(validSequencedTracks, pathToProp) + const isSequencable = isPropConfSequencable(propConfig) - const isSequenced = typeof possibleSequenceTrackId === 'string' + if (isSequencable) { + const validSequencedTracks = val( + obj.template.getMapOfValidSequenceTracks_forStudio(), + ) + const possibleSequenceTrackId = getDeep(validSequencedTracks, pathToProp) - if (isSequenced) { - contextMenuItems.push({ - label: 'Make static', - callback: () => { - getStudio()!.transaction(({stateEditors}) => { - const propAddress = {...obj.address, pathToProp} - stateEditors.coreByProject.historic.sheetsById.sequence.setPrimitivePropAsStatic( - { - ...propAddress, - value: obj.getValueByPointer(pointerToProp) as T, - }, + const isSequenced = typeof possibleSequenceTrackId === 'string' + + if (isSequenced) { + contextMenuItems.push({ + label: 'Make static', + callback: () => { + getStudio()!.transaction(({stateEditors}) => { + const propAddress = {...obj.address, pathToProp} + stateEditors.coreByProject.historic.sheetsById.sequence.setPrimitivePropAsStatic( + { + ...propAddress, + value: obj.getValueByPointer(pointerToProp) as T, + }, + ) + }) + }, + }) + + const sequenceTrcackId = possibleSequenceTrackId as $FixMe as string + const nearbyKeyframes = prism.sub( + 'lcr', + (): NearbyKeyframes => { + const track = val( + obj.template.project.pointers.historic.sheetsById[ + obj.address.sheetId + ].sequence.tracksByObject[obj.address.objectKey].trackData[ + sequenceTrcackId + ], ) - }) - }, - }) + if (!track || track.keyframes.length === 0) return {} - const sequenceTrcackId = possibleSequenceTrackId as $FixMe as string - const nearbyKeyframes = prism.sub( - 'lcr', - (): NearbyKeyframes => { - const track = val( - obj.template.project.pointers.historic.sheetsById[ - obj.address.sheetId - ].sequence.tracksByObject[obj.address.objectKey].trackData[ - sequenceTrcackId - ], - ) - if (!track || track.keyframes.length === 0) return {} + const pos = val(obj.sheet.getSequence().positionDerivation) - const pos = val(obj.sheet.getSequence().positionDerivation) + const i = track.keyframes.findIndex((kf) => kf.position >= pos) - const i = track.keyframes.findIndex((kf) => kf.position >= pos) + if (i === -1) + return { + prev: last(track.keyframes), + } - if (i === -1) - return { - prev: last(track.keyframes), - } - - const k = track.keyframes[i]! - if (k.position === pos) { - return { - prev: i > 0 ? track.keyframes[i - 1] : undefined, - cur: k, - next: - i === track.keyframes.length - 1 - ? undefined - : track.keyframes[i + 1], - } - } else { - return { - next: k, - prev: i > 0 ? track.keyframes[i - 1] : undefined, - } - } - }, - [sequenceTrcackId], - ) - - let shade: Shade - - if (common.beingScrubbed) { - shade = 'Sequenced_OnKeyframe_BeingScrubbed' - } else { - if (nearbyKeyframes.cur) { - shade = 'Sequenced_OnKeyframe' - } else if (nearbyKeyframes.prev?.connectedRight === true) { - shade = 'Sequenced_BeingInterpolated' - } else { - shade = 'Sequened_NotBeingInterpolated' - } - } - - const nextPrevKeyframeCursors = ( - { - obj.sheet.getSequence().position = position - }} - toggleKeyframeOnCurrentPosition={() => { - if (nearbyKeyframes.cur) { - getStudio()!.transaction((api) => { - api.unset(pointerToProp) - }) + const k = track.keyframes[i]! + if (k.position === pos) { + return { + prev: i > 0 ? track.keyframes[i - 1] : undefined, + cur: k, + next: + i === track.keyframes.length - 1 + ? undefined + : track.keyframes[i + 1], + } } else { - getStudio()!.transaction((api) => { - api.set(pointerToProp, common.value) - }) + return { + next: k, + prev: i > 0 ? track.keyframes[i - 1] : undefined, + } } - }} - /> - ) + }, + [sequenceTrcackId], + ) - const ret: Sequenced = { - ...common, - type: 'Sequenced', - shade, - nearbyKeyframes, - controlIndicators: nextPrevKeyframeCursors, + let shade: Shade + + if (common.beingScrubbed) { + shade = 'Sequenced_OnKeyframe_BeingScrubbed' + } else { + if (nearbyKeyframes.cur) { + shade = 'Sequenced_OnKeyframe' + } else if (nearbyKeyframes.prev?.connectedRight === true) { + shade = 'Sequenced_BeingInterpolated' + } else { + shade = 'Sequened_NotBeingInterpolated' + } + } + + const nextPrevKeyframeCursors = ( + { + obj.sheet.getSequence().position = position + }} + toggleKeyframeOnCurrentPosition={() => { + if (nearbyKeyframes.cur) { + getStudio()!.transaction((api) => { + api.unset(pointerToProp) + }) + } else { + getStudio()!.transaction((api) => { + api.set(pointerToProp, common.value) + }) + } + }} + /> + ) + + const ret: Sequenced = { + ...common, + type: 'Sequenced', + shade, + nearbyKeyframes, + controlIndicators: nextPrevKeyframeCursors, + } + + return ret } - - return ret } contextMenuItems.push({ @@ -233,17 +242,19 @@ export function useEditingToolsForPrimitiveProp< }, }) - contextMenuItems.push({ - label: 'Sequence', - callback: () => { - getStudio()!.transaction(({stateEditors}) => { - const propAddress = {...obj.address, pathToProp} - stateEditors.coreByProject.historic.sheetsById.sequence.setPrimitivePropAsSequenced( - propAddress, - ) - }) - }, - }) + if (isSequencable) { + contextMenuItems.push({ + label: 'Sequence', + callback: () => { + getStudio()!.transaction(({stateEditors}) => { + const propAddress = {...obj.address, pathToProp} + stateEditors.coreByProject.historic.sheetsById.sequence.setPrimitivePropAsSequenced( + propAddress, + ) + }) + }, + }) + } const statics = val(obj.template.getStaticValues()) @@ -296,3 +307,7 @@ type Shade = | 'Sequenced_OnKeyframe_BeingScrubbed' | 'Sequenced_BeingInterpolated' | 'Sequened_NotBeingInterpolated' + +function isPropConfSequencable(conf: PropTypeConfig): boolean { + return conf.type === 'number' +} diff --git a/theatre/studio/src/panels/SequenceEditorPanel/DopeSheet/Left/PrimitivePropRow.tsx b/theatre/studio/src/panels/SequenceEditorPanel/DopeSheet/Left/PrimitivePropRow.tsx index 7e01856..23601f4 100644 --- a/theatre/studio/src/panels/SequenceEditorPanel/DopeSheet/Left/PrimitivePropRow.tsx +++ b/theatre/studio/src/panels/SequenceEditorPanel/DopeSheet/Left/PrimitivePropRow.tsx @@ -90,6 +90,7 @@ const PrimitivePropRow: React.FC<{ const {controlIndicators} = useEditingToolsForPrimitiveProp( pointerToProp, obj, + leaf.propConf, ) const possibleColor = usePrism(() => { diff --git a/theatre/studio/src/panels/SequenceEditorPanel/layout/tree.ts b/theatre/studio/src/panels/SequenceEditorPanel/layout/tree.ts index 76ced1e..2bdad10 100644 --- a/theatre/studio/src/panels/SequenceEditorPanel/layout/tree.ts +++ b/theatre/studio/src/panels/SequenceEditorPanel/layout/tree.ts @@ -54,6 +54,7 @@ export type SequenceEditorTree_PrimitiveProp = sheetObject: SheetObject pathToProp: PathToProp trackId: SequenceTrackId + propConf: PropTypeConfig_AllPrimitives } export type SequenceEditorTree_AllRowTypes = @@ -250,7 +251,7 @@ export const calculateSequenceEditorTree = ( sheetObject: SheetObject, trackId: SequenceTrackId, pathToProp: PathToProp, - conf: PropTypeConfig_AllPrimitives, + propConf: PropTypeConfig_AllPrimitives, arrayOfChildren: Array< SequenceEditorTree_PrimitiveProp | SequenceEditorTree_PropWithChildren >, @@ -258,6 +259,7 @@ export const calculateSequenceEditorTree = ( ) { const row: SequenceEditorTree_PrimitiveProp = { type: 'primitiveProp', + propConf: propConf, depth: level, sheetObject: sheetObject, pathToProp,