diff --git a/theatre/studio/src/TheatreStudio.ts b/theatre/studio/src/TheatreStudio.ts index 813cf9a..f769279 100644 --- a/theatre/studio/src/TheatreStudio.ts +++ b/theatre/studio/src/TheatreStudio.ts @@ -1,26 +1,13 @@ -import get from 'lodash-es/get' import type {IProject, IRafDriver, ISheet, ISheetObject} from '@theatre/core' import type {Prism, Pointer} from '@theatre/dataverse' -import {getPointerParts, prism, val} from '@theatre/dataverse' +import {prism} from '@theatre/dataverse' import SimpleCache from '@theatre/shared/utils/SimpleCache' -import { - getPropConfigByPath, - isPropConfigComposite, - iteratePropType, -} from '@theatre/shared/propTypes/utils' -import type {PropTypeConfig} from '@theatre/core/propTypes' -import type {PathToProp} from '@theatre/shared/src/utils/addresses' -import type {KeyframeId, SequenceTrackId} from '@theatre/shared/utils/ids' -import pointerDeep from '@theatre/shared/utils/pointerDeep' -import forEachPropDeep from '@theatre/shared/utils/forEachDeep' -import getDeep from '@theatre/shared/utils/getDeep' -import type {$FixMe, $IntentionalAny, VoidFn} from '@theatre/shared/utils/types' +import type {$IntentionalAny, VoidFn} from '@theatre/shared/utils/types' import type {IScrub} from '@theatre/studio/Scrub' import type {Studio} from '@theatre/studio/Studio' import { isSheetObjectPublicAPI, isSheetPublicAPI, - isSheetObject, } from '@theatre/shared/instanceTypes' import {getOutlineSelection} from './selectors' import type SheetObject from '@theatre/core/sheetObjects/SheetObject' @@ -91,18 +78,6 @@ export interface ITransactionAPI { * Makes Theatre forget about this sheet. */ __experimental_forgetSheet(sheet: TheatreSheet): void - - __experimental_sequenceProp(pointer: Pointer): void - __experimental_staticProp(pointer: Pointer): void - __experimental_deleteKeyframes( - pointer: Pointer, - from: number, - to: number, - ): void - __experimental_addKeyframes(pointer: Pointer, keyframes: []): void - // transaction - // - //__experimental_setSequenceDuration(pointer: Pointer, duration: number): void } /** * @@ -487,14 +462,6 @@ export interface IStudio { __experimental_createContentOfSaveFileTyped( projectId: string, ): __UNSTABLE_Project_OnDiskState - - __experimental_setPropAsSequenced(prop: Pointer): void - __experimental_setPropAsStatic(prop: Pointer): void - __experimental_isPropSequenced(prop: Pointer): boolean - - // __experimental - // - //__experimental_setSequenceDuration(prop: Pointer, duration: number): boolean } } @@ -540,97 +507,6 @@ export default class TheatreStudio implements IStudio { ): __UNSTABLE_Project_OnDiskState { return getStudio().createContentOfSaveFile(projectId) as $IntentionalAny }, - // WARNING: for some reason this is not immediately applied - // but needs a timeout.. urgh - __experimental_setPropAsSequenced(prop: Pointer): void { - const {path, root} = getPointerParts(prop) - if (!isSheetObject(root)) { - throw new Error( - 'Argument prop must be a pointer to a SheetObject property', - ) - } - - const propAddress = {...root.address, pathToProp: path} - const propConfig = getPropConfigByPath(root.template.staticConfig, path) - if (typeof propConfig !== 'undefined') - getStudio()!.transaction(({stateEditors}) => { - stateEditors.coreByProject.historic.sheetsById.sequence.setPrimitivePropAsSequenced( - propAddress, - propConfig, - ) - console.log('inner setPropAsSequenced', performance.now()) - }) - }, - __experimental_setPropAsStatic(prop: Pointer): void { - const {path, root} = getPointerParts(prop) - if (!isSheetObject(root)) { - throw new Error( - 'Argument prop must be a pointer to a SheetObject property', - ) - } - - const propAddress = {...root.address, pathToProp: path} - const propConfig = getPropConfigByPath(root.template.staticConfig, path) - if (typeof propConfig !== 'undefined') { - for (const {path: subPath, conf} of iteratePropType(propConfig, [])) { - if (isPropConfigComposite(conf)) continue - getStudio()!.transaction(({stateEditors}) => { - const pointerToSub = pointerDeep(prop, subPath) - - stateEditors.coreByProject.historic.sheetsById.sequence.setPrimitivePropAsStatic( - { - ...propAddress, - value: root.getValueByPointer(pointerToSub as $IntentionalAny), - }, - ) - }) - } - } - }, - __experimental_isPropSequenced(prop: Pointer): boolean { - const {path, root} = getPointerParts(prop) - if (!isSheetObject(root)) { - throw new Error( - 'Argument prop must be a pointer to a SheetObject property', - ) - } - - const propAddress = {...root.address, pathToProp: path} - const propConfig = getPropConfigByPath(root.template.staticConfig, path) - const validTracks = root.template - .getArrayOfValidSequenceTracks() - .getValue() - tf: for (let t = 0; t < validTracks.length; t++) { - const otherPath = validTracks[t].pathToProp - if (otherPath.length === path.length) { - for (let p = 0; p < path.length; p++) { - if (path[p] !== otherPath[p]) { - continue tf - } - } - return true - } - } - return false - }, - // __experimental - // - //__experimental_setSequenceDuration(prop: Pointer, duration: number): boolean { - //const {path, root} = getPointerParts(prop) - //if (!isSheet(root)) { - //throw new Error( - //'Argument prop must be a pointer to a Sheet property', - //) - //} - - //getStudio()!.transaction(({stateEditors}) => { - //stateEditors.coreByProject.historic.sheetsById.sequence.setLength({ - //...root.address, - //length: duration, - //}) - //}) - //return false - //}, } /** @@ -676,250 +552,11 @@ export default class TheatreStudio implements IStudio { ) } - const __experimental_sequenceProp = (prop: Pointer) => { - const {path, root} = getPointerParts(prop) - - // NOT IMPLEMENTED FULLY - // only works for simple props. not something like color - if (!isSheetObject(root)) { - throw new Error( - 'Argument prop must be a pointer to a SheetObject property', - ) - } - - const propAddress = {...root.address, pathToProp: path} - const propConfig = getPropConfigByPath(root.template.staticConfig, path) - - if (propConfig === undefined) { - throw new Error('propConfig is undefined. so, yeah.') - } - console.log({propConfig, propAddress}) - stateEditors.coreByProject.historic.sheetsById.sequence.setPrimitivePropAsSequenced( - propAddress, - propConfig, - ) - } - const __experimental_staticProp = (prop: Pointer) => { - const {path, root} = getPointerParts(prop) - - // NOT IMPLEMENTED FULLY - // only works for simple props. not something like color - if (!isSheetObject(root)) { - throw new Error( - 'Argument prop must be a pointer to a SheetObject property', - ) - } - - const propAddress = {...root.address, pathToProp: path} - const propConfig = getPropConfigByPath(root.template.staticConfig, path) - - if (propConfig === undefined) { - throw new Error('propConfig is undefined. so, yeah.') - } - - for (const {path: subPath, conf} of iteratePropType(propConfig, [])) { - if (isPropConfigComposite(conf)) continue - const pointerToSub = pointerDeep(prop, subPath) - - stateEditors.coreByProject.historic.sheetsById.sequence.setPrimitivePropAsStatic( - { - ...propAddress, - value: root.getValueByPointer(pointerToSub as $IntentionalAny), - }, - ) - } - } - - const __experimental_deleteKeyframes = ( - prop: Pointer, - from: number = 0, - to: number = 0, - ) => { - const {root, path} = getPointerParts(prop as Pointer<$FixMe>) - if (isSheetObject(root)) { - const sequenceTracksTree = root.template - .getMapOfValidSequenceTracks_forStudio() - .getValue() - - const defaultValue = getDeep( - root.template.getDefaultValues().getValue(), - path, - ) - - const propConfig = getPropConfigByPath( - root.template.staticConfig, - path, - ) as PropTypeConfig - - const unsetStaticOrKeyframeProp = (value: T, path: PathToProp) => { - const propAddress = {...root.address, pathToProp: path} - - const trackId = get(sequenceTracksTree, path) as $FixMe as - | SequenceTrackId - | undefined - - const sequence = root.sheet.getSequence() - const trackP = val( - sequence._project.pointers.historic.sheetsById[ - sequence._sheet.address.sheetId - ].sequence.tracksByObject[root.address.objectKey], - ) - if (!trackP) { - throw new Error('whatever, man') - } - const {trackData, trackIdByPropPath} = trackP - //const objectAddress = encodePathToProp(path) - //const id = trackIdByPropPath[objectAddress] - - if ( - typeof trackId === 'string' && - typeof trackData !== 'undefined' - ) { - const track = trackData[trackId] - if (!track) { - throw new Error('whatever, man') - } - - const keyframeIds: KeyframeId[] = [] - if (to > from) { - track.keyframes.forEach((kf) => { - if (kf.position >= from && kf.position <= to) { - } else { - keyframeIds.push(kf.id) - } - }) - } - const objectKey = propAddress.objectKey - stateEditors.coreByProject.historic.sheetsById.sequence.keepKeyframes( - { - ...root.address, - objectKey, - trackId, - keyframeIds, - }, - ) - } else if (propConfig !== undefined) { - stateEditors.coreByProject.historic.sheetsById.staticOverrides.byObject.unsetValueOfPrimitiveProp( - propAddress, - ) - } - } - - if (propConfig.type === 'compound') { - forEachPropDeep( - defaultValue, - (v, pathToProp) => { - unsetStaticOrKeyframeProp(v, pathToProp) - }, - getPointerParts(prop).path, - ) - } else { - unsetStaticOrKeyframeProp(defaultValue, path) - } - } else { - throw new Error( - 'Only setting props of SheetObject-s is supported in a transaction so far', - ) - } - } - - const __experimental_addKeyframes = ( - prop: Pointer, - keyframes: [], - ) => { - const {root, path} = getPointerParts(prop as Pointer<$FixMe>) - if (isSheetObject(root)) { - let sequenceTracksTree = root.template - .getMapOfValidSequenceTracks_forStudio() - .getValue() - - const defaultValue = getDeep( - root.template.getDefaultValues().getValue(), - path, - ) - - const propConfig = getPropConfigByPath( - root.template.staticConfig, - path, - ) as PropTypeConfig - console.log(path, propConfig) - - const addStaticOrKeyframeProp = (value: T, path: PathToProp) => { - const propAddress = {...root.address, pathToProp: path} - - let trackId = get(sequenceTracksTree, path) as $FixMe as - | SequenceTrackId - | undefined - - if (typeof trackId !== 'string' && propConfig !== undefined) { - throw Error('can only add keyframes to sequenced prop') - } - - if (typeof trackId === 'string') { - const objectKey = propAddress.objectKey - stateEditors.coreByProject.historic.sheetsById.sequence.addKeyframes( - { - ...root.address, - objectKey, - trackId, - keyframes, - }, - ) - console.log({ - a: {...root.address}, - objectKey, - trackId, - keyframes, - }) - } else if (propConfig !== undefined) { - throw Error('hmmm') - } - } - - if (propConfig.type === 'compound') { - forEachPropDeep( - defaultValue, - (v, pathToProp) => { - console.log('comp compoumnD') - addStaticOrKeyframeProp(v, pathToProp) - }, - getPointerParts(prop).path, - ) - } else { - console.log('singlerer', {defaultValue, path}) - addStaticOrKeyframeProp(defaultValue, path) - } - } else { - throw new Error( - 'Only setting props of SheetObject-s is supported in a transaction so far', - ) - } - } - - // transaction - // - //const __experimental_setSequenceDuration = (prop: Pointer, duration: number) => { - //const {root, path} = getPointerParts(prop as Pointer<$FixMe>) - //if (isSheet(root)) { - //stateEditors.coreByProject.historic.sheetsById.sequence.setLength({ - //...root.address, - //length: duration, - //}) - //} - //} - return fn({ set, unset, __experimental_forgetObject, __experimental_forgetSheet, - __experimental_sequenceProp, - __experimental_staticProp, - __experimental_deleteKeyframes, - __experimental_addKeyframes, - // transaction - // - //__experimental_setSequenceDuration, }) }) } diff --git a/theatre/studio/src/panels/SequenceEditorPanel/GraphEditor/BasicKeyframedTrack/BasicKeyframedTrack.tsx b/theatre/studio/src/panels/SequenceEditorPanel/GraphEditor/BasicKeyframedTrack/BasicKeyframedTrack.tsx index d3cbc9c..e62b64f 100644 --- a/theatre/studio/src/panels/SequenceEditorPanel/GraphEditor/BasicKeyframedTrack/BasicKeyframedTrack.tsx +++ b/theatre/studio/src/panels/SequenceEditorPanel/GraphEditor/BasicKeyframedTrack/BasicKeyframedTrack.tsx @@ -66,7 +66,7 @@ const BasicKeyframedTrack: React.VFC<{ const extremumSpace: ExtremumSpace = useMemo(() => { const extremums = - propConfig.type === 'number' || propConfig.type === 'boolean' + propConfig.type === 'number' ? calculateScalarExtremums(trackData.keyframes, propConfig) : calculateNonScalarExtremums(trackData.keyframes) @@ -109,7 +109,7 @@ const BasicKeyframedTrack: React.VFC<{ layoutP={layoutP} sheetObject={sheetObject} trackId={trackId} - isScalar={propConfig.type === 'number' || propConfig.type === 'boolean'} + isScalar={propConfig.type === 'number'} key={kf.id} extremumSpace={cachedExtremumSpace.current} color={color} @@ -146,16 +146,12 @@ function calculateScalarExtremums( } keyframes.forEach((cur, i) => { - const cv = typeof cur.value === 'boolean' ? (cur.value ? 1 : 0) : cur.value - const curVal = valueInProp(cv, propConfig) as number - + const curVal = valueInProp(cur.value, propConfig) as number check(curVal) if (!cur.connectedRight) return const next = keyframes[i + 1] if (!next) return - const nv = - typeof next.value === 'boolean' ? (next.value ? 1 : 0) : next.value - const diff = (typeof nv === 'number' ? nv : 1) - curVal + const diff = (typeof next.value === 'number' ? next.value : 1) - curVal check(curVal + cur.handles[3] * diff) check(curVal + next.handles[1] * diff) }) diff --git a/theatre/studio/src/propEditors/useEditingToolsForSimpleProp.tsx b/theatre/studio/src/propEditors/useEditingToolsForSimpleProp.tsx index f9ed55c..93fdeea 100644 --- a/theatre/studio/src/propEditors/useEditingToolsForSimpleProp.tsx +++ b/theatre/studio/src/propEditors/useEditingToolsForSimpleProp.tsx @@ -293,6 +293,7 @@ function createPrism( callback: () => { getStudio()!.transaction(({stateEditors}) => { const propAddress = {...obj.address, pathToProp} + stateEditors.coreByProject.historic.sheetsById.sequence.setPrimitivePropAsSequenced( propAddress, propConfig, diff --git a/theatre/studio/src/store/stateEditors.ts b/theatre/studio/src/store/stateEditors.ts index da730b3..0aee371 100644 --- a/theatre/studio/src/store/stateEditors.ts +++ b/theatre/studio/src/store/stateEditors.ts @@ -772,63 +772,6 @@ namespace stateEditors { stateEditors.coreByProject.historic.sheetsById.staticOverrides.byObject.setValueOfCompoundProp( p, ) - const toVT = { - sequenced: false, - panelID: p.objectKey, - prop: p.pathToProp, - origin: 'stateEditors.ts', - } - const event = new CustomEvent('sequenceEvent', { - bubbles: false, - detail: toVT, - }) - window.dispatchEvent(event) - } - - export function setCompoundPropAsSequenced( - p: WithoutSheetInstance, - ) { - const tracks = _ensureTracksOfObject(p) - - for (const encodedPropPath of Object.keys( - tracks.trackIdByPropPath, - )) { - const propPath = JSON.parse(encodedPropPath) - const isSubOfTargetPath = p.pathToProp.every( - (key, i) => propPath[i] === key, - ) - if (isSubOfTargetPath) { - const possibleTrackId = - tracks.trackIdByPropPath[encodedPropPath] - if (typeof possibleTrackId === 'string') return - - const trackId = generateSequenceTrackId() - - const track: BasicKeyframedTrack = { - type: 'BasicKeyframedTrack', - __debugName: `${p.objectKey}:${encodedPropPath}`, - keyframes: [], - } - - tracks.trackData[trackId] = track - tracks.trackIdByPropPath[encodedPropPath] = trackId - } - } - - //stateEditors.coreByProject.historic.sheetsById.staticOverrides.byObject.setValueOfCompoundProp( - //p, - //) - const toVT = { - sequenced: false, - panelID: p.objectKey, - prop: p.pathToProp, - origin: 'stateEditors.ts', - } - const event = new CustomEvent('sequenceEvent', { - bubbles: false, - detail: toVT, - }) - window.dispatchEvent(event) } function _getTrack( @@ -1036,72 +979,6 @@ namespace stateEditors { } } - export function addKeyframes( - p: WithoutSheetInstance & { - trackId: SequenceTrackId - keyframes: { - position: number - handles?: [number, number, number, number] - value: T - type?: KeyframeType - }[] - }, - override: boolean = true, - ) { - const track = _getTrack(p) - if (!track) return - if (p.keyframes.length < 1) - throw new Error( - 'holy shit, you are trying to add non-existing keyframes', - ) - //const {keyframes} = track - if (!override) - throw new Error('whoopsie, not overriding is not implemented') - - // is it necessary to be so stupid here? - const oldKeyframes = track.keyframes - track.keyframes = [] - oldKeyframes.forEach((kf) => { - if (p.keyframes[0].position > kf.position) { - track.keyframes.push(kf) - } - }) - p.keyframes.forEach((pkf) => { - track.keyframes.push({ - id: generateKeyframeId(), - position: pkf.position, - connectedRight: true, - handles: pkf.handles || [0.5, 1, 0.5, 0], - type: pkf.type || 'bezier', - value: pkf.value, - }) - }) - oldKeyframes.forEach((kf) => { - if (p.keyframes[p.keyframes.length - 1].position < kf.position) { - track.keyframes.push(kf) - } - }) - } - - export function keepKeyframes( - p: WithoutSheetInstance & { - trackId: SequenceTrackId - keyframeIds: KeyframeId[] - }, - ) { - const track = _getTrack(p) - if (!track) return - - // is it necessary to be so stupid here? - const keyframes = track.keyframes - track.keyframes = [] - keyframes.forEach((kf) => { - if (p.keyframeIds.indexOf(kf.id) >= 0) { - track.keyframes.push(kf) - } - }) - } - export function deleteKeyframes( p: WithoutSheetInstance & { trackId: SequenceTrackId @@ -1110,6 +987,7 @@ namespace stateEditors { ) { const track = _getTrack(p) if (!track) return + track.keyframes = track.keyframes.filter( (kf) => p.keyframeIds.indexOf(kf.id) === -1, )