Make it possible to move the playhead to an exact position (#92)

This commit is contained in:
Fulop 2022-03-03 09:54:54 +01:00 committed by GitHub
parent fb7467862b
commit 3f2a9032f1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 138 additions and 24 deletions

View file

@ -16,6 +16,9 @@ import {
useLockFrameStampPosition,
} from '@theatre/studio/panels/SequenceEditorPanel/FrameStampPositionProvider'
import {pointerEventsAutoInNormalMode} from '@theatre/studio/css'
import usePopover from '@theatre/studio/uiComponents/Popover/usePopover'
import BasicPopover from '@theatre/studio/uiComponents/Popover/BasicPopover'
import PlayheadPositionPopover from './PlayheadPositionPopover'
const Container = styled.div<{isVisible: boolean}>`
--thumbColor: #00e0ff;
@ -150,6 +153,20 @@ const Playhead: React.FC<{layoutP: Pointer<SequenceEditorPanelLayout>}> = ({
}) => {
const [thumbRef, thumbNode] = useRefAndState<HTMLElement | null>(null)
const [popoverNode, openPopover, closePopover, isPopoverOpen] = usePopover(
{},
() => {
return (
<BasicPopover>
<PlayheadPositionPopover
layoutP={layoutP}
onRequestClose={closePopover}
/>
</BasicPopover>
)
},
)
const gestureHandlers = useMemo((): Parameters<typeof useDrag>[1] => {
const setIsSeeking = val(layoutP.seeker.setIsSeeking)
@ -215,6 +232,8 @@ const Playhead: React.FC<{layoutP: Pointer<SequenceEditorPanelLayout>}> = ({
posInClippedSpace <= val(layoutP.clippedSpace.width)
return (
<>
{popoverNode}
<Container
isVisible={isVisible}
style={{transform: `translate3d(${posInClippedSpace}px, 0, 0)`}}
@ -224,6 +243,9 @@ const Playhead: React.FC<{layoutP: Pointer<SequenceEditorPanelLayout>}> = ({
<Thumb
ref={thumbRef as $IntentionalAny}
data-pos={posInUnitSpace.toFixed(3)}
onClick={(e) => {
openPopover(e, thumbNode!)
}}
>
<RoomToClick room={8} />
<Squinch />
@ -239,8 +261,9 @@ const Playhead: React.FC<{layoutP: Pointer<SequenceEditorPanelLayout>}> = ({
className={isSeeking ? 'seeking' : ''}
/>
</Container>
</>
)
}, [layoutP])
}, [layoutP, thumbRef, popoverNode])
}
export default Playhead

View file

@ -0,0 +1,91 @@
import styled from 'styled-components'
import type {SequenceEditorPanelLayout} from '@theatre/studio/panels/SequenceEditorPanel/layout/layout'
import {usePrism} from '@theatre/react'
import type {BasicNumberInputNudgeFn} from '@theatre/studio/uiComponents/form/BasicNumberInput'
import BasicNumberInput from '@theatre/studio/uiComponents/form/BasicNumberInput'
import {propNameText} from '@theatre/studio/panels/DetailPanel/propEditors/utils/SingleRowPropEditor'
import {useLayoutEffect, useMemo, useRef} from 'react'
import React from 'react'
import {val} from '@theatre/dataverse'
import type {Pointer} from '@theatre/dataverse'
import clamp from 'lodash-es/clamp'
const greaterThanZero = (v: number) => isFinite(v) && v > 0
const Container = styled.div`
display: flex;
gap: 8px;
padding: 4px 8px;
height: 28px;
align-items: center;
`
const Label = styled.div`
${propNameText};
white-space: nowrap;
`
const nudge: BasicNumberInputNudgeFn = ({deltaX}) => deltaX * 0.25
const PlayheadPositionPopover: React.FC<{
layoutP: Pointer<SequenceEditorPanelLayout>
/**
* Called when user hits enter/escape
*/
onRequestClose: () => void
}> = ({layoutP, onRequestClose}) => {
const sheet = val(layoutP.sheet)
const sequence = sheet.getSequence()
const fns = useMemo(() => {
let tempPosition: number | undefined
const originalPosition = sequence.position
return {
temporarilySetValue(newPosition: number): void {
if (tempPosition) {
tempPosition = undefined
}
tempPosition = clamp(newPosition, 0, sequence.length)
sequence.position = tempPosition
},
discardTemporaryValue(): void {
if (tempPosition) {
tempPosition = undefined
sequence.position = originalPosition
}
},
permenantlySetValue(newPosition: number): void {
if (tempPosition) {
tempPosition = undefined
}
sequence.position = clamp(newPosition, 0, sequence.length)
},
}
}, [layoutP, sequence])
const inputRef = useRef<HTMLInputElement>(null)
useLayoutEffect(() => {
inputRef.current!.focus()
}, [])
return usePrism(() => {
const sequence = sheet.getSequence()
return (
<Container>
<Label>Playhead position</Label>
<BasicNumberInput
value={sequence.position}
{...fns}
isValid={greaterThanZero}
inputRef={inputRef}
onBlur={onRequestClose}
nudge={nudge}
/>
</Container>
)
}, [sheet, fns, inputRef])
}
export default PlayheadPositionPopover