feat(289): Labeled markers (#362)

This commit is contained in:
Colin Duffy 2023-01-23 13:59:23 -08:00 committed by GitHub
parent 1fb69126fd
commit 4b4fe858f9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 137 additions and 3 deletions

View file

@ -19,13 +19,16 @@ import type {UseDragOpts} from '@theatre/studio/uiComponents/useDrag'
import type {CommitOrDiscard} from '@theatre/studio/StudioStore/StudioStore' import type {CommitOrDiscard} from '@theatre/studio/StudioStore/StudioStore'
import type {StudioHistoricStateSequenceEditorMarker} from '@theatre/studio/store/types' import type {StudioHistoricStateSequenceEditorMarker} from '@theatre/studio/store/types'
import {zIndexes} from '@theatre/studio/panels/SequenceEditorPanel/SequenceEditorPanel' import {zIndexes} from '@theatre/studio/panels/SequenceEditorPanel/SequenceEditorPanel'
import DopeSnap from './DopeSnap' import DopeSnap from '@theatre/studio/panels/SequenceEditorPanel/RightOverlay/DopeSnap'
import {absoluteDims} from '@theatre/studio/utils/absoluteDims' import {absoluteDims} from '@theatre/studio/utils/absoluteDims'
import {DopeSnapHitZoneUI} from './DopeSnapHitZoneUI' import {DopeSnapHitZoneUI} from '@theatre/studio/panels/SequenceEditorPanel/RightOverlay/DopeSnapHitZoneUI'
import { import {
snapToAll, snapToAll,
snapToNone, snapToNone,
} from '@theatre/studio/panels/SequenceEditorPanel/DopeSheet/Right/KeyframeSnapTarget' } from '@theatre/studio/panels/SequenceEditorPanel/DopeSheet/Right/KeyframeSnapTarget'
import usePopover from '@theatre/studio/uiComponents/Popover/usePopover'
import BasicPopover from '@theatre/studio/uiComponents/Popover/BasicPopover'
import MarkerEditorPopover from './MarkerEditorPopover'
const MARKER_SIZE_W_PX = 12 const MARKER_SIZE_W_PX = 12
const MARKER_SIZE_H_PX = 12 const MARKER_SIZE_H_PX = 12
@ -164,11 +167,32 @@ const MarkerDotVisible: React.VFC<IMarkerDotVisibleProps> = ({
marker, marker,
}) })
const {
node: popoverNode,
toggle: togglePopover,
close: closePopover,
} = usePopover({debugName: 'MarkerPopover'}, () => {
return (
<BasicPopover>
<MarkerEditorPopover
marker={marker}
layoutP={layoutP}
onRequestClose={closePopover}
/>
</BasicPopover>
)
})
return ( return (
<> <>
{contextMenu} {contextMenu}
{popoverNode}
<HitZone <HitZone
title={marker.label ? `Marker: ${marker.label}` : 'Marker'}
ref={markRef} ref={markRef}
onClick={(e) => {
togglePopover(e, markRef.current!)
}}
{...DopeSnapHitZoneUI.reactProps({ {...DopeSnapHitZoneUI.reactProps({
isDragging, isDragging,
position: marker.position, position: marker.position,

View file

@ -0,0 +1,99 @@
import type {Pointer} from '@theatre/dataverse'
import React, {useLayoutEffect, useMemo, useRef} from 'react'
import styled from 'styled-components'
import type {SequenceEditorPanelLayout} from '@theatre/studio/panels/SequenceEditorPanel/layout/layout'
import {useVal} from '@theatre/react'
import getStudio from '@theatre/studio/getStudio'
import type {BasicNumberInputNudgeFn} from '@theatre/studio/uiComponents/form/BasicNumberInput'
import type {CommitOrDiscard} from '@theatre/studio/StudioStore/StudioStore'
import {propNameTextCSS} from '@theatre/studio/propEditors/utils/propNameTextCSS'
import type {StudioHistoricStateSequenceEditorMarker} from '@theatre/studio/store/types/historic'
import BasicStringInput from '@theatre/studio/uiComponents/form/BasicStringInput'
const Container = styled.div`
display: flex;
gap: 8px;
/* padding: 4px 8px; */
height: 28px;
align-items: center;
`
const Label = styled.div`
${propNameTextCSS};
white-space: nowrap;
`
const nudge: BasicNumberInputNudgeFn = ({deltaX}) => deltaX * 0.25
const MarkerEditorPopover: React.FC<{
layoutP: Pointer<SequenceEditorPanelLayout>
marker: StudioHistoricStateSequenceEditorMarker
/**
* Called when user hits enter/escape
*/
onRequestClose: (reason: string) => void
}> = ({layoutP, marker}) => {
const sheet = useVal(layoutP.sheet)
const fns = useMemo(() => {
let tempTransaction: CommitOrDiscard | undefined
return {
temporarilySetValue(newLabel: string): void {
if (tempTransaction) {
tempTransaction.discard()
tempTransaction = undefined
}
tempTransaction = getStudio()!.tempTransaction(({stateEditors}) => {
stateEditors.studio.historic.projects.stateByProjectId.stateBySheetId.sequenceEditor.updateMarker(
{
sheetAddress: sheet.address,
markerId: marker.id,
label: newLabel,
},
)
})
},
discardTemporaryValue(): void {
if (tempTransaction) {
tempTransaction.discard()
tempTransaction = undefined
}
},
permanentlySetValue(newLabel: string): void {
if (tempTransaction) {
tempTransaction.discard()
tempTransaction = undefined
}
getStudio()!.transaction(({stateEditors}) => {
stateEditors.studio.historic.projects.stateByProjectId.stateBySheetId.sequenceEditor.updateMarker(
{
sheetAddress: sheet.address,
markerId: marker.id,
label: newLabel,
},
)
})
},
}
}, [layoutP, sheet])
const inputRef = useRef<HTMLInputElement>(null)
useLayoutEffect(() => {
inputRef.current!.focus()
}, [])
return (
<Container>
{/* <Label>Marker</Label> */}
<BasicStringInput
value={marker.label ?? ''}
{...fns}
isValid={() => true}
inputRef={inputRef}
/>
</Container>
)
}
export default MarkerEditorPopover

View file

@ -11,7 +11,7 @@ import HorizontalScrollbar from './HorizontalScrollbar'
import Playhead from './Playhead' import Playhead from './Playhead'
import TopStrip from './TopStrip' import TopStrip from './TopStrip'
import FocusRangeCurtains from '@theatre/studio/panels/SequenceEditorPanel/DopeSheet/Right/FocusRangeCurtains' import FocusRangeCurtains from '@theatre/studio/panels/SequenceEditorPanel/DopeSheet/Right/FocusRangeCurtains'
import Markers from './Markers' import Markers from './Markers/Markers'
const Container = styled.div` const Container = styled.div`
position: absolute; position: absolute;

View file

@ -338,6 +338,16 @@ namespace stateEditors {
pointableSetUtil.remove(currentMarkerSet, options.markerId), pointableSetUtil.remove(currentMarkerSet, options.markerId),
) )
} }
export function updateMarker(options: {
sheetAddress: SheetAddress
markerId: SequenceMarkerId
label: string
}) {
const currentMarkerSet = _ensureMarkers(options.sheetAddress)
const marker = currentMarkerSet.byId[options.markerId]
if (marker !== undefined) marker.label = options.label
}
} }
} }
} }

View file

@ -78,6 +78,7 @@ export type PaneInstanceDescriptor = {
*/ */
export type StudioHistoricStateSequenceEditorMarker = { export type StudioHistoricStateSequenceEditorMarker = {
id: SequenceMarkerId id: SequenceMarkerId
label?: string
/** /**
* The position this marker takes in the sequence. * The position this marker takes in the sequence.
* *