Disallowed sequencing on non-numeric props

* This is temporary until we find a good UX for sequencing discrete values
This commit is contained in:
Aria Minaei 2021-09-06 11:42:09 +02:00
parent f6cf3711f4
commit b5e994f597
6 changed files with 143 additions and 113 deletions

View file

@ -15,7 +15,11 @@ const BooleanPropEditor: React.FC<{
pointerToProp: SheetObject['propsP'] pointerToProp: SheetObject['propsP']
obj: SheetObject obj: SheetObject
}> = ({propConfig, pointerToProp, obj}) => { }> = ({propConfig, pointerToProp, obj}) => {
const stuff = useEditingToolsForPrimitiveProp<boolean>(pointerToProp, obj) const stuff = useEditingToolsForPrimitiveProp<boolean>(
pointerToProp,
obj,
propConfig,
)
const onChange = useCallback( const onChange = useCallback(
(el: React.ChangeEvent<HTMLInputElement>) => { (el: React.ChangeEvent<HTMLInputElement>) => {

View file

@ -10,7 +10,11 @@ const NumberPropEditor: React.FC<{
pointerToProp: SheetObject['propsP'] pointerToProp: SheetObject['propsP']
obj: SheetObject obj: SheetObject
}> = ({propConfig, pointerToProp, obj}) => { }> = ({propConfig, pointerToProp, obj}) => {
const stuff = useEditingToolsForPrimitiveProp<number>(pointerToProp, obj) const stuff = useEditingToolsForPrimitiveProp<number>(
pointerToProp,
obj,
propConfig,
)
const nudge = useCallback( const nudge = useCallback(
(params: {deltaX: number; deltaFraction: number; magnitude: number}) => { (params: {deltaX: number; deltaFraction: number; magnitude: number}) => {

View file

@ -12,7 +12,11 @@ const StringLiteralPropEditor: React.FC<{
pointerToProp: SheetObject['propsP'] pointerToProp: SheetObject['propsP']
obj: SheetObject obj: SheetObject
}> = ({propConfig, pointerToProp, obj}) => { }> = ({propConfig, pointerToProp, obj}) => {
const stuff = useEditingToolsForPrimitiveProp<string>(pointerToProp, obj) const stuff = useEditingToolsForPrimitiveProp<string>(
pointerToProp,
obj,
propConfig,
)
const onChange = useCallback( const onChange = useCallback(
(val: string) => { (val: string) => {

View file

@ -12,6 +12,7 @@ import last from 'lodash-es/last'
import React from 'react' import React from 'react'
import DefaultOrStaticValueIndicator from './DefaultValueIndicator' import DefaultOrStaticValueIndicator from './DefaultValueIndicator'
import NextPrevKeyframeCursors from './NextPrevKeyframeCursors' import NextPrevKeyframeCursors from './NextPrevKeyframeCursors'
import type {PropTypeConfig} from '@theatre/core/propTypes'
interface CommonStuff<T> { interface CommonStuff<T> {
value: T value: T
@ -44,7 +45,11 @@ type Stuff<T> = Default<T> | Static<T> | Sequenced<T>
export function useEditingToolsForPrimitiveProp< export function useEditingToolsForPrimitiveProp<
T extends SerializablePrimitive, T extends SerializablePrimitive,
>(pointerToProp: SheetObject['propsP'], obj: SheetObject): Stuff<T> { >(
pointerToProp: SheetObject['propsP'],
obj: SheetObject,
propConfig: PropTypeConfig,
): Stuff<T> {
return usePrism(() => { return usePrism(() => {
const pathToProp = getPointerParts(pointerToProp).path const pathToProp = getPointerParts(pointerToProp).path
@ -114,114 +119,118 @@ export function useEditingToolsForPrimitiveProp<
controlIndicators: <></>, controlIndicators: <></>,
} }
const validSequencedTracks = val( const isSequencable = isPropConfSequencable(propConfig)
obj.template.getMapOfValidSequenceTracks_forStudio(),
)
const possibleSequenceTrackId = getDeep(validSequencedTracks, pathToProp)
const isSequenced = typeof possibleSequenceTrackId === 'string' if (isSequencable) {
const validSequencedTracks = val(
obj.template.getMapOfValidSequenceTracks_forStudio(),
)
const possibleSequenceTrackId = getDeep(validSequencedTracks, pathToProp)
if (isSequenced) { const isSequenced = typeof possibleSequenceTrackId === 'string'
contextMenuItems.push({
label: 'Make static', if (isSequenced) {
callback: () => { contextMenuItems.push({
getStudio()!.transaction(({stateEditors}) => { label: 'Make static',
const propAddress = {...obj.address, pathToProp} callback: () => {
stateEditors.coreByProject.historic.sheetsById.sequence.setPrimitivePropAsStatic( getStudio()!.transaction(({stateEditors}) => {
{ const propAddress = {...obj.address, pathToProp}
...propAddress, stateEditors.coreByProject.historic.sheetsById.sequence.setPrimitivePropAsStatic(
value: obj.getValueByPointer(pointerToProp) as T, {
}, ...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 pos = val(obj.sheet.getSequence().positionDerivation)
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 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) const k = track.keyframes[i]!
return { if (k.position === pos) {
prev: last(track.keyframes), return {
} prev: i > 0 ? track.keyframes[i - 1] : undefined,
cur: k,
const k = track.keyframes[i]! next:
if (k.position === pos) { i === track.keyframes.length - 1
return { ? undefined
prev: i > 0 ? track.keyframes[i - 1] : undefined, : track.keyframes[i + 1],
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 = (
<NextPrevKeyframeCursors
{...nearbyKeyframes}
jumpToPosition={(position) => {
obj.sheet.getSequence().position = position
}}
toggleKeyframeOnCurrentPosition={() => {
if (nearbyKeyframes.cur) {
getStudio()!.transaction((api) => {
api.unset(pointerToProp)
})
} else { } else {
getStudio()!.transaction((api) => { return {
api.set(pointerToProp, common.value) next: k,
}) prev: i > 0 ? track.keyframes[i - 1] : undefined,
}
} }
}} },
/> [sequenceTrcackId],
) )
const ret: Sequenced<T> = { let shade: Shade
...common,
type: 'Sequenced', if (common.beingScrubbed) {
shade, shade = 'Sequenced_OnKeyframe_BeingScrubbed'
nearbyKeyframes, } else {
controlIndicators: nextPrevKeyframeCursors, if (nearbyKeyframes.cur) {
shade = 'Sequenced_OnKeyframe'
} else if (nearbyKeyframes.prev?.connectedRight === true) {
shade = 'Sequenced_BeingInterpolated'
} else {
shade = 'Sequened_NotBeingInterpolated'
}
}
const nextPrevKeyframeCursors = (
<NextPrevKeyframeCursors
{...nearbyKeyframes}
jumpToPosition={(position) => {
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<T> = {
...common,
type: 'Sequenced',
shade,
nearbyKeyframes,
controlIndicators: nextPrevKeyframeCursors,
}
return ret
} }
return ret
} }
contextMenuItems.push({ contextMenuItems.push({
@ -233,17 +242,19 @@ export function useEditingToolsForPrimitiveProp<
}, },
}) })
contextMenuItems.push({ if (isSequencable) {
label: 'Sequence', contextMenuItems.push({
callback: () => { label: 'Sequence',
getStudio()!.transaction(({stateEditors}) => { callback: () => {
const propAddress = {...obj.address, pathToProp} getStudio()!.transaction(({stateEditors}) => {
stateEditors.coreByProject.historic.sheetsById.sequence.setPrimitivePropAsSequenced( const propAddress = {...obj.address, pathToProp}
propAddress, stateEditors.coreByProject.historic.sheetsById.sequence.setPrimitivePropAsSequenced(
) propAddress,
}) )
}, })
}) },
})
}
const statics = val(obj.template.getStaticValues()) const statics = val(obj.template.getStaticValues())
@ -296,3 +307,7 @@ type Shade =
| 'Sequenced_OnKeyframe_BeingScrubbed' | 'Sequenced_OnKeyframe_BeingScrubbed'
| 'Sequenced_BeingInterpolated' | 'Sequenced_BeingInterpolated'
| 'Sequened_NotBeingInterpolated' | 'Sequened_NotBeingInterpolated'
function isPropConfSequencable(conf: PropTypeConfig): boolean {
return conf.type === 'number'
}

View file

@ -90,6 +90,7 @@ const PrimitivePropRow: React.FC<{
const {controlIndicators} = useEditingToolsForPrimitiveProp( const {controlIndicators} = useEditingToolsForPrimitiveProp(
pointerToProp, pointerToProp,
obj, obj,
leaf.propConf,
) )
const possibleColor = usePrism(() => { const possibleColor = usePrism(() => {

View file

@ -54,6 +54,7 @@ export type SequenceEditorTree_PrimitiveProp =
sheetObject: SheetObject sheetObject: SheetObject
pathToProp: PathToProp pathToProp: PathToProp
trackId: SequenceTrackId trackId: SequenceTrackId
propConf: PropTypeConfig_AllPrimitives
} }
export type SequenceEditorTree_AllRowTypes = export type SequenceEditorTree_AllRowTypes =
@ -250,7 +251,7 @@ export const calculateSequenceEditorTree = (
sheetObject: SheetObject, sheetObject: SheetObject,
trackId: SequenceTrackId, trackId: SequenceTrackId,
pathToProp: PathToProp, pathToProp: PathToProp,
conf: PropTypeConfig_AllPrimitives, propConf: PropTypeConfig_AllPrimitives,
arrayOfChildren: Array< arrayOfChildren: Array<
SequenceEditorTree_PrimitiveProp | SequenceEditorTree_PropWithChildren SequenceEditorTree_PrimitiveProp | SequenceEditorTree_PropWithChildren
>, >,
@ -258,6 +259,7 @@ export const calculateSequenceEditorTree = (
) { ) {
const row: SequenceEditorTree_PrimitiveProp = { const row: SequenceEditorTree_PrimitiveProp = {
type: 'primitiveProp', type: 'primitiveProp',
propConf: propConf,
depth: level, depth: level,
sheetObject: sheetObject, sheetObject: sheetObject,
pathToProp, pathToProp,