Make default and static overrides distinguishable
Right now it's easy for the user to distinguish between a sequenced prop and non-sequenced props. However, among the non-sequenced ones, it's not possible to distinguish between those that have a static override, and those that don't. The goal of this commit is to make it easy to distinguish between the two.
This commit is contained in:
parent
5c135a3cb9
commit
6f8e91ed5f
5 changed files with 85 additions and 79 deletions
|
@ -18,6 +18,7 @@ import type {
|
|||
$FixMe,
|
||||
$IntentionalAny,
|
||||
SerializableMap,
|
||||
SerializablePrimitive,
|
||||
SerializableValue,
|
||||
} from '@theatre/shared/utils/types'
|
||||
import type {Prism, Pointer} from '@theatre/dataverse'
|
||||
|
@ -31,6 +32,7 @@ import {
|
|||
isPropConfSequencable,
|
||||
} from '@theatre/shared/propTypes/utils'
|
||||
import getOrderingOfPropTypeConfig from './getOrderingOfPropTypeConfig'
|
||||
import type {SheetState_Historic} from '@theatre/core/projects/store/types/SheetState_Historic'
|
||||
|
||||
/**
|
||||
* Given an object like: `{transform: {type: 'absolute', position: {x: 0}}}`,
|
||||
|
@ -64,6 +66,10 @@ export default class SheetObjectTemplate {
|
|||
readonly _temp_actions_atom: Atom<SheetObjectActionsConfig>
|
||||
readonly _cache = new SimpleCache()
|
||||
readonly project: Project
|
||||
readonly pointerToSheetState: Pointer<SheetState_Historic | undefined>
|
||||
readonly pointerToStaticOverrides: Pointer<
|
||||
SerializableMap<SerializablePrimitive> | undefined
|
||||
>
|
||||
|
||||
get staticConfig() {
|
||||
return this._config.get()
|
||||
|
@ -92,6 +98,14 @@ export default class SheetObjectTemplate {
|
|||
this._config = new Atom(config)
|
||||
this._temp_actions_atom = new Atom(_temp_actions)
|
||||
this.project = sheetTemplate.project
|
||||
|
||||
this.pointerToSheetState =
|
||||
this.sheetTemplate.project.pointers.historic.sheetsById[
|
||||
this.address.sheetId
|
||||
]
|
||||
|
||||
this.pointerToStaticOverrides =
|
||||
this.pointerToSheetState.staticOverrides.byObject[this.address.objectKey]
|
||||
}
|
||||
|
||||
createInstance(
|
||||
|
@ -132,17 +146,7 @@ export default class SheetObjectTemplate {
|
|||
getStaticValues(): Prism<SerializableMap> {
|
||||
return this._cache.get('getStaticValues', () =>
|
||||
prism(() => {
|
||||
const pointerToSheetState =
|
||||
this.sheetTemplate.project.pointers.historic.sheetsById[
|
||||
this.address.sheetId
|
||||
]
|
||||
|
||||
const json =
|
||||
val(
|
||||
pointerToSheetState.staticOverrides.byObject[
|
||||
this.address.objectKey
|
||||
],
|
||||
) ?? {}
|
||||
const json = val(this.pointerToStaticOverrides) ?? {}
|
||||
|
||||
const config = val(this.configPointer)
|
||||
const deserialized = config.deserializeAndSanitize(json) || {}
|
||||
|
|
|
@ -7,6 +7,7 @@ import type {
|
|||
} from '@theatre/core/propTypes'
|
||||
import type {PathToProp} from '@theatre/shared/utils/addresses'
|
||||
import type {$IntentionalAny} from '@theatre/shared/utils/types'
|
||||
import memoizeFn from '@theatre/shared/utils/memoizeFn'
|
||||
|
||||
/**
|
||||
* Either compound or enum properties can be considered "composite"
|
||||
|
@ -70,53 +71,32 @@ export function isPropConfSequencable(
|
|||
return !isPropConfigComposite(conf) // now all non-compounds are sequencable
|
||||
}
|
||||
|
||||
const compoundPropSequenceabilityCache = new WeakMap<
|
||||
PropTypeConfig_Compound<{}> | PropTypeConfig_Enum,
|
||||
boolean
|
||||
>()
|
||||
|
||||
/**
|
||||
* See {@link compoundHasSimpleDescendantsImpl}
|
||||
*/
|
||||
export function compoundHasSimpleDescendants(
|
||||
conf: PropTypeConfig_Compound<{}> | PropTypeConfig_Enum,
|
||||
): boolean {
|
||||
if (!compoundPropSequenceabilityCache.has(conf)) {
|
||||
compoundPropSequenceabilityCache.set(
|
||||
conf,
|
||||
compoundHasSimpleDescendantsImpl(conf),
|
||||
)
|
||||
}
|
||||
|
||||
return compoundPropSequenceabilityCache.get(conf)!
|
||||
}
|
||||
|
||||
/**
|
||||
* This basically checks of the compound prop has at least one simple prop in its descendants.
|
||||
* In other words, if the compound props has no subs, or its subs are only compounds that eventually
|
||||
* don't have simple subs, this will return false.
|
||||
*/
|
||||
function compoundHasSimpleDescendantsImpl(
|
||||
conf: PropTypeConfig_Compound<{}> | PropTypeConfig_Enum,
|
||||
): boolean {
|
||||
if (conf.type === 'enum') {
|
||||
throw new Error(`Not implemented yet for enums`)
|
||||
}
|
||||
export const compoundHasSimpleDescendants = memoizeFn(
|
||||
(conf: PropTypeConfig_Compound<{}> | PropTypeConfig_Enum): boolean => {
|
||||
if (conf.type === 'enum') {
|
||||
throw new Error(`Not implemented yet for enums`)
|
||||
}
|
||||
|
||||
for (const key in conf.props) {
|
||||
const subConf = conf.props[
|
||||
key as $IntentionalAny as keyof typeof conf.props
|
||||
] as PropTypeConfig
|
||||
if (isPropConfigComposite(subConf)) {
|
||||
if (compoundHasSimpleDescendants(subConf)) {
|
||||
for (const key in conf.props) {
|
||||
const subConf = conf.props[
|
||||
key as $IntentionalAny as keyof typeof conf.props
|
||||
] as PropTypeConfig
|
||||
if (isPropConfigComposite(subConf)) {
|
||||
if (compoundHasSimpleDescendants(subConf)) {
|
||||
return true
|
||||
}
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
return false
|
||||
},
|
||||
)
|
||||
|
||||
/**
|
||||
* Iterates recursively over the simple props of a compound prop. Returns a generator.
|
||||
|
|
|
@ -2,9 +2,9 @@ import {transparentize} from 'polished'
|
|||
import React from 'react'
|
||||
import styled from 'styled-components'
|
||||
|
||||
export const theme = {
|
||||
const theme = {
|
||||
defaultState: {
|
||||
color: transparentize(0.85, `#C4C4C4`),
|
||||
color: transparentize(0.95, `#C4C4C4`),
|
||||
},
|
||||
withStaticOverride: {
|
||||
color: transparentize(0.85, `#C4C4C4`),
|
||||
|
@ -28,24 +28,31 @@ const Rect = styled.rect`
|
|||
fill: currentColor;
|
||||
`
|
||||
|
||||
const Icon = () => (
|
||||
<svg
|
||||
width="5"
|
||||
height="5"
|
||||
viewBox="0 0 5 5"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<Rect width="5" height="5" />
|
||||
</svg>
|
||||
)
|
||||
const DefaultIcon = styled.div`
|
||||
width: 5px;
|
||||
height: 5px;
|
||||
border-radius: 1px;
|
||||
/* border: 1px solid currentColor; */
|
||||
background-color: currentColor;
|
||||
`
|
||||
|
||||
const FilledIcon = styled.div`
|
||||
width: 5px;
|
||||
height: 5px;
|
||||
background-color: currentColor;
|
||||
border-radius: 1px;
|
||||
`
|
||||
|
||||
const DefaultOrStaticValueIndicator: React.FC<{hasStaticOverride: boolean}> = (
|
||||
props,
|
||||
) => {
|
||||
return (
|
||||
<Container hasStaticOverride={props.hasStaticOverride}>
|
||||
<Icon />
|
||||
{props.hasStaticOverride ? (
|
||||
<FilledIcon title="The default value is overridden" />
|
||||
) : (
|
||||
<DefaultIcon title="This is the default value for this prop" />
|
||||
)}
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -54,6 +54,13 @@ export function useEditingToolsForCompoundProp<T extends SerializablePrimitive>(
|
|||
obj: SheetObject,
|
||||
propConfig: PropTypeConfig_Compound<{}>,
|
||||
): Stuff {
|
||||
const pathToProp = getPointerParts(pointerToProp).path
|
||||
|
||||
const pointerToStaticOverrides = pointerDeep(
|
||||
obj.template.pointerToStaticOverrides,
|
||||
pathToProp,
|
||||
)
|
||||
|
||||
return usePrism((): Stuff => {
|
||||
// if the compound has no simple descendants, then there isn't much the user can do with it
|
||||
if (!compoundHasSimpleDescendants(propConfig)) {
|
||||
|
@ -67,8 +74,6 @@ export function useEditingToolsForCompoundProp<T extends SerializablePrimitive>(
|
|||
}
|
||||
}
|
||||
|
||||
const pathToProp = getPointerParts(pointerToProp).path
|
||||
|
||||
/**
|
||||
* TODO This implementation is wrong because {@link stateEditors.studio.ephemeral.projects.stateByProjectId.stateBySheetId.stateByObjectKey.propsBeingScrubbed.flag}
|
||||
* does not prune empty objects
|
||||
|
@ -96,6 +101,11 @@ export function useEditingToolsForCompoundProp<T extends SerializablePrimitive>(
|
|||
obj.template.getMapOfValidSequenceTracks_forStudio(),
|
||||
)
|
||||
|
||||
const staticOverrides = getDeep(
|
||||
val(obj.template.getStaticValues()),
|
||||
pathToProp,
|
||||
)
|
||||
|
||||
const possibleSequenceTrackIds = getDeep(
|
||||
validSequencedTracks,
|
||||
pathToProp,
|
||||
|
@ -106,9 +116,8 @@ export function useEditingToolsForCompoundProp<T extends SerializablePrimitive>(
|
|||
Object.keys(possibleSequenceTrackIds).length !== 0 // check if object is empty or undefined
|
||||
const listOfDescendantTrackIds: SequenceTrackId[] = []
|
||||
|
||||
let hasOneOrMoreStatics = true
|
||||
let hasOneOrMoreStatics = staticOverrides !== undefined
|
||||
if (hasOneOrMoreSequencedTracks) {
|
||||
hasOneOrMoreStatics = false
|
||||
for (const descendant of iteratePropType(propConfig, [])) {
|
||||
if (isPropConfigComposite(descendant.conf)) continue
|
||||
const sequencedTrackIdBelongingToDescendant = getDeep(
|
||||
|
@ -214,7 +223,9 @@ export function useEditingToolsForCompoundProp<T extends SerializablePrimitive>(
|
|||
...common,
|
||||
type: 'AllStatic',
|
||||
controlIndicators: (
|
||||
<DefaultOrStaticValueIndicator hasStaticOverride={false} />
|
||||
<DefaultOrStaticValueIndicator
|
||||
hasStaticOverride={hasOneOrMoreStatics}
|
||||
/>
|
||||
),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -272,14 +272,20 @@ function createPrism<T extends SerializablePrimitive>(
|
|||
}
|
||||
}
|
||||
|
||||
contextMenuItems.push({
|
||||
label: 'Reset to default',
|
||||
callback: () => {
|
||||
getStudio()!.transaction(({unset: unset}) => {
|
||||
unset(pointerToProp)
|
||||
})
|
||||
},
|
||||
})
|
||||
const allStaticOverrides = val(obj.template.getStaticValues())
|
||||
|
||||
const staticOverride = getDeep(allStaticOverrides, pathToProp)
|
||||
|
||||
if (typeof staticOverride !== 'undefined') {
|
||||
contextMenuItems.push({
|
||||
label: 'Reset to default',
|
||||
callback: () => {
|
||||
getStudio()!.transaction(({unset: unset}) => {
|
||||
unset(pointerToProp)
|
||||
})
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
if (isSequencable) {
|
||||
contextMenuItems.push({
|
||||
|
@ -297,9 +303,7 @@ function createPrism<T extends SerializablePrimitive>(
|
|||
})
|
||||
}
|
||||
|
||||
const statics = val(obj.template.getStaticValues())
|
||||
|
||||
if (typeof getDeep(statics, pathToProp) !== 'undefined') {
|
||||
if (typeof staticOverride !== 'undefined') {
|
||||
const ret: EditingToolsStatic<T> = {
|
||||
...common,
|
||||
type: 'Static',
|
||||
|
|
Loading…
Reference in a new issue