Perf: first-pass at reducing number of re-renders in <NextPrevKeyframeCursors>
This commit is contained in:
parent
f82c9d1155
commit
b37ccb1e4e
1 changed files with 163 additions and 146 deletions
|
@ -185,157 +185,25 @@ export function useEditingToolsForCompoundProp<T extends SerializablePrimitive>(
|
|||
}
|
||||
|
||||
if (hasOneOrMoreSequencedTracks) {
|
||||
const sequenceTrackId = possibleSequenceTrackIds
|
||||
const nearbyKeyframeControls = prism.sub(
|
||||
'lcr',
|
||||
(): NearbyKeyframesControls => {
|
||||
const sequencePosition = val(
|
||||
obj.sheet.getSequence().positionDerivation,
|
||||
)
|
||||
|
||||
/*
|
||||
2/10 perf concern:
|
||||
When displaying a hierarchy like {props: {transform: {position: {x, y, z}}}},
|
||||
we'd be recalculating this variable for both `position` and `transform`. While
|
||||
we _could_ be re-using the calculation of `transform` in `position`, I think
|
||||
it's unlikely that this optimization would matter.
|
||||
*/
|
||||
const nearbyKeyframesInEachTrack = listOfDescendantTrackIds
|
||||
.map((trackId) => ({
|
||||
trackId,
|
||||
track: val(
|
||||
obj.template.project.pointers.historic.sheetsById[
|
||||
obj.address.sheetId
|
||||
].sequence.tracksByObject[obj.address.objectKey].trackData[
|
||||
trackId
|
||||
],
|
||||
),
|
||||
}))
|
||||
.filter(({track}) => !!track)
|
||||
.map((s) => ({
|
||||
...s,
|
||||
nearbies: getNearbyKeyframesOfTrack(
|
||||
obj,
|
||||
{id: s.trackId, data: s.track!},
|
||||
sequencePosition,
|
||||
),
|
||||
}))
|
||||
|
||||
const hasCur = nearbyKeyframesInEachTrack.find(
|
||||
({nearbies}) => !!nearbies.cur,
|
||||
)
|
||||
const allCur = nearbyKeyframesInEachTrack.every(
|
||||
({nearbies}) => !!nearbies.cur,
|
||||
)
|
||||
|
||||
const closestPrev = nearbyKeyframesInEachTrack.reduce<
|
||||
undefined | KeyframeWithTrack
|
||||
>((acc, s) => {
|
||||
if (s.nearbies.prev) {
|
||||
if (
|
||||
acc === undefined ||
|
||||
s.nearbies.prev.kf.position > acc.kf.position
|
||||
) {
|
||||
return s.nearbies.prev
|
||||
} else {
|
||||
return acc
|
||||
}
|
||||
} else {
|
||||
return acc
|
||||
}
|
||||
}, undefined)
|
||||
|
||||
const closestNext = nearbyKeyframesInEachTrack.reduce<
|
||||
undefined | KeyframeWithTrack
|
||||
>((acc, s) => {
|
||||
if (s.nearbies.next) {
|
||||
if (
|
||||
acc === undefined ||
|
||||
s.nearbies.next.kf.position < acc.kf.position
|
||||
) {
|
||||
return s.nearbies.next
|
||||
} else {
|
||||
return acc
|
||||
}
|
||||
} else {
|
||||
return acc
|
||||
}
|
||||
}, undefined)
|
||||
|
||||
const toggle = () => {
|
||||
if (allCur) {
|
||||
getStudio().transaction((api) => {
|
||||
api.unset(pointerToProp)
|
||||
})
|
||||
} else if (hasCur) {
|
||||
getStudio().transaction((api) => {
|
||||
api.set(pointerToProp, val(pointerToProp))
|
||||
})
|
||||
} else {
|
||||
getStudio().transaction((api) => {
|
||||
api.set(pointerToProp, val(pointerToProp))
|
||||
})
|
||||
}
|
||||
}
|
||||
return {
|
||||
cur: hasCur
|
||||
? {
|
||||
type: 'on',
|
||||
itemKey:
|
||||
createStudioSheetItemKey.forCompoundPropAggregateKeyframe(
|
||||
obj,
|
||||
pathToProp,
|
||||
sequencePosition,
|
||||
),
|
||||
toggle,
|
||||
}
|
||||
: {
|
||||
toggle,
|
||||
type: 'off',
|
||||
},
|
||||
prev:
|
||||
closestPrev !== undefined
|
||||
? {
|
||||
position: closestPrev.kf.position,
|
||||
itemKey:
|
||||
createStudioSheetItemKey.forCompoundPropAggregateKeyframe(
|
||||
obj,
|
||||
pathToProp,
|
||||
closestPrev.kf.position,
|
||||
),
|
||||
jump: () => {
|
||||
obj.sheet.getSequence().position = closestPrev.kf.position
|
||||
},
|
||||
}
|
||||
: undefined,
|
||||
next:
|
||||
closestNext !== undefined
|
||||
? {
|
||||
position: closestNext.kf.position,
|
||||
itemKey:
|
||||
createStudioSheetItemKey.forCompoundPropAggregateKeyframe(
|
||||
obj,
|
||||
pathToProp,
|
||||
closestNext.kf.position,
|
||||
),
|
||||
jump: () => {
|
||||
obj.sheet.getSequence().position = closestNext.kf.position
|
||||
},
|
||||
}
|
||||
: undefined,
|
||||
}
|
||||
},
|
||||
[sequenceTrackId],
|
||||
)
|
||||
|
||||
const nextPrevKeyframeCursors = (
|
||||
<NextPrevKeyframeCursors {...nearbyKeyframeControls} />
|
||||
const controlIndicators = prism.memo(
|
||||
`controlIndicators`,
|
||||
() => (
|
||||
<ControlIndicators
|
||||
{...{
|
||||
pointerToProp,
|
||||
obj,
|
||||
possibleSequenceTrackIds,
|
||||
listOfDescendantTrackIds,
|
||||
}}
|
||||
/>
|
||||
),
|
||||
[possibleSequenceTrackIds, listOfDescendantTrackIds],
|
||||
)
|
||||
|
||||
const ret: HasSequences = {
|
||||
...common,
|
||||
type: 'HasSequences',
|
||||
controlIndicators: nextPrevKeyframeCursors,
|
||||
controlIndicators,
|
||||
}
|
||||
|
||||
return ret
|
||||
|
@ -350,3 +218,152 @@ export function useEditingToolsForCompoundProp<T extends SerializablePrimitive>(
|
|||
}
|
||||
}, [])
|
||||
}
|
||||
|
||||
function ControlIndicators({
|
||||
pointerToProp,
|
||||
obj,
|
||||
possibleSequenceTrackIds,
|
||||
listOfDescendantTrackIds,
|
||||
}: {
|
||||
pointerToProp: Pointer<{}>
|
||||
obj: SheetObject
|
||||
possibleSequenceTrackIds: IPropPathToTrackIdTree
|
||||
listOfDescendantTrackIds: SequenceTrackId[]
|
||||
}) {
|
||||
return usePrism(() => {
|
||||
const pathToProp = getPointerParts(pointerToProp).path
|
||||
|
||||
const sequencePosition = val(obj.sheet.getSequence().positionDerivation)
|
||||
|
||||
/*
|
||||
2/10 perf concern:
|
||||
When displaying a hierarchy like {props: {transform: {position: {x, y, z}}}},
|
||||
we'd be recalculating this variable for both `position` and `transform`. While
|
||||
we _could_ be re-using the calculation of `transform` in `position`, I think
|
||||
it's unlikely that this optimization would matter.
|
||||
*/
|
||||
const nearbyKeyframesInEachTrack = listOfDescendantTrackIds
|
||||
.map((trackId) => ({
|
||||
trackId,
|
||||
track: val(
|
||||
obj.template.project.pointers.historic.sheetsById[obj.address.sheetId]
|
||||
.sequence.tracksByObject[obj.address.objectKey].trackData[trackId],
|
||||
),
|
||||
}))
|
||||
.filter(({track}) => !!track)
|
||||
.map((s) => ({
|
||||
...s,
|
||||
nearbies: getNearbyKeyframesOfTrack(
|
||||
obj,
|
||||
{id: s.trackId, data: s.track!},
|
||||
sequencePosition,
|
||||
),
|
||||
}))
|
||||
|
||||
const hasCur = nearbyKeyframesInEachTrack.find(
|
||||
({nearbies}) => !!nearbies.cur,
|
||||
)
|
||||
const allCur = nearbyKeyframesInEachTrack.every(
|
||||
({nearbies}) => !!nearbies.cur,
|
||||
)
|
||||
|
||||
const closestPrev = nearbyKeyframesInEachTrack.reduce<
|
||||
undefined | KeyframeWithTrack
|
||||
>((acc, s) => {
|
||||
if (s.nearbies.prev) {
|
||||
if (
|
||||
acc === undefined ||
|
||||
s.nearbies.prev.kf.position > acc.kf.position
|
||||
) {
|
||||
return s.nearbies.prev
|
||||
} else {
|
||||
return acc
|
||||
}
|
||||
} else {
|
||||
return acc
|
||||
}
|
||||
}, undefined)
|
||||
|
||||
const closestNext = nearbyKeyframesInEachTrack.reduce<
|
||||
undefined | KeyframeWithTrack
|
||||
>((acc, s) => {
|
||||
if (s.nearbies.next) {
|
||||
if (
|
||||
acc === undefined ||
|
||||
s.nearbies.next.kf.position < acc.kf.position
|
||||
) {
|
||||
return s.nearbies.next
|
||||
} else {
|
||||
return acc
|
||||
}
|
||||
} else {
|
||||
return acc
|
||||
}
|
||||
}, undefined)
|
||||
|
||||
const toggle = () => {
|
||||
if (allCur) {
|
||||
getStudio().transaction((api) => {
|
||||
api.unset(pointerToProp)
|
||||
})
|
||||
} else if (hasCur) {
|
||||
getStudio().transaction((api) => {
|
||||
api.set(pointerToProp, val(pointerToProp))
|
||||
})
|
||||
} else {
|
||||
getStudio().transaction((api) => {
|
||||
api.set(pointerToProp, val(pointerToProp))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const pr: NearbyKeyframesControls = {
|
||||
cur: hasCur
|
||||
? {
|
||||
type: 'on',
|
||||
itemKey: createStudioSheetItemKey.forCompoundPropAggregateKeyframe(
|
||||
obj,
|
||||
pathToProp,
|
||||
sequencePosition,
|
||||
),
|
||||
toggle,
|
||||
}
|
||||
: {
|
||||
toggle,
|
||||
type: 'off',
|
||||
},
|
||||
prev:
|
||||
closestPrev !== undefined
|
||||
? {
|
||||
position: closestPrev.kf.position,
|
||||
itemKey:
|
||||
createStudioSheetItemKey.forCompoundPropAggregateKeyframe(
|
||||
obj,
|
||||
pathToProp,
|
||||
closestPrev.kf.position,
|
||||
),
|
||||
jump: () => {
|
||||
obj.sheet.getSequence().position = closestPrev.kf.position
|
||||
},
|
||||
}
|
||||
: undefined,
|
||||
next:
|
||||
closestNext !== undefined
|
||||
? {
|
||||
position: closestNext.kf.position,
|
||||
itemKey:
|
||||
createStudioSheetItemKey.forCompoundPropAggregateKeyframe(
|
||||
obj,
|
||||
pathToProp,
|
||||
closestNext.kf.position,
|
||||
),
|
||||
jump: () => {
|
||||
obj.sheet.getSequence().position = closestNext.kf.position
|
||||
},
|
||||
}
|
||||
: undefined,
|
||||
}
|
||||
|
||||
return <NextPrevKeyframeCursors {...pr} />
|
||||
}, [pointerToProp, obj, possibleSequenceTrackIds, listOfDescendantTrackIds])
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue