Cleaner API for useFrameStampPosition()
This commit is contained in:
parent
0a3c699180
commit
74b6f93872
5 changed files with 56 additions and 38 deletions
|
@ -9,14 +9,11 @@ import useDrag from '@theatre/studio/uiComponents/useDrag'
|
||||||
import useRefAndState from '@theatre/studio/utils/useRefAndState'
|
import useRefAndState from '@theatre/studio/utils/useRefAndState'
|
||||||
import {val} from '@theatre/dataverse'
|
import {val} from '@theatre/dataverse'
|
||||||
import {lighten} from 'polished'
|
import {lighten} from 'polished'
|
||||||
import React, {useMemo, useRef} from 'react'
|
import React, {useMemo, useRef, useState} from 'react'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
import type KeyframeEditor from './KeyframeEditor'
|
import type KeyframeEditor from './KeyframeEditor'
|
||||||
import type {FrameStampPositionLock} from '@theatre/studio/panels/SequenceEditorPanel/FrameStampPositionProvider'
|
import {useLockFrameStampPosition} from '@theatre/studio/panels/SequenceEditorPanel/FrameStampPositionProvider'
|
||||||
import {
|
import {attributeNameThatLocksFramestamp} from '@theatre/studio/panels/SequenceEditorPanel/FrameStampPositionProvider'
|
||||||
attributeNameThatLocksFramestamp,
|
|
||||||
useFrameStampPosition,
|
|
||||||
} from '@theatre/studio/panels/SequenceEditorPanel/FrameStampPositionProvider'
|
|
||||||
|
|
||||||
export const dotSize = 6
|
export const dotSize = 6
|
||||||
const hitZoneSize = 12
|
const hitZoneSize = 12
|
||||||
|
@ -112,7 +109,8 @@ function useKeyframeContextMenu(node: HTMLDivElement | null, props: IProps) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function useDragKeyframe(node: HTMLDivElement | null, props: IProps) {
|
function useDragKeyframe(node: HTMLDivElement | null, props: IProps) {
|
||||||
const {getLock} = useFrameStampPosition()
|
const [isDragging, setIsDragging] = useState(false)
|
||||||
|
useLockFrameStampPosition(isDragging, props.keyframe.position)
|
||||||
|
|
||||||
const propsRef = useRef(props)
|
const propsRef = useRef(props)
|
||||||
propsRef.current = props
|
propsRef.current = props
|
||||||
|
@ -121,7 +119,6 @@ function useDragKeyframe(node: HTMLDivElement | null, props: IProps) {
|
||||||
let toUnitSpace: SequenceEditorPanelLayout['scaledSpace']['toUnitSpace']
|
let toUnitSpace: SequenceEditorPanelLayout['scaledSpace']['toUnitSpace']
|
||||||
let tempTransaction: CommitOrDiscard | undefined
|
let tempTransaction: CommitOrDiscard | undefined
|
||||||
let propsAtStartOfDrag: IProps
|
let propsAtStartOfDrag: IProps
|
||||||
let frameStampPositionLock: FrameStampPositionLock
|
|
||||||
|
|
||||||
let selectionDragHandlers:
|
let selectionDragHandlers:
|
||||||
| ReturnType<DopeSheetSelection['getDragHandlers']>
|
| ReturnType<DopeSheetSelection['getDragHandlers']>
|
||||||
|
@ -130,6 +127,7 @@ function useDragKeyframe(node: HTMLDivElement | null, props: IProps) {
|
||||||
return {
|
return {
|
||||||
lockCursorTo: 'ew-resize',
|
lockCursorTo: 'ew-resize',
|
||||||
onDragStart(event) {
|
onDragStart(event) {
|
||||||
|
setIsDragging(true)
|
||||||
if (propsRef.current.selection) {
|
if (propsRef.current.selection) {
|
||||||
const {selection, leaf} = propsRef.current
|
const {selection, leaf} = propsRef.current
|
||||||
const {sheetObject} = leaf
|
const {sheetObject} = leaf
|
||||||
|
@ -145,9 +143,6 @@ function useDragKeyframe(node: HTMLDivElement | null, props: IProps) {
|
||||||
|
|
||||||
propsAtStartOfDrag = propsRef.current
|
propsAtStartOfDrag = propsRef.current
|
||||||
toUnitSpace = val(propsAtStartOfDrag.layoutP.scaledSpace.toUnitSpace)
|
toUnitSpace = val(propsAtStartOfDrag.layoutP.scaledSpace.toUnitSpace)
|
||||||
|
|
||||||
frameStampPositionLock = getLock()
|
|
||||||
frameStampPositionLock.set(propsAtStartOfDrag.keyframe.position)
|
|
||||||
},
|
},
|
||||||
onDrag(dx, dy, event) {
|
onDrag(dx, dy, event) {
|
||||||
if (selectionDragHandlers) {
|
if (selectionDragHandlers) {
|
||||||
|
@ -155,9 +150,6 @@ function useDragKeyframe(node: HTMLDivElement | null, props: IProps) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const delta = toUnitSpace(dx)
|
const delta = toUnitSpace(dx)
|
||||||
const original =
|
|
||||||
propsAtStartOfDrag.trackData.keyframes[propsAtStartOfDrag.index]
|
|
||||||
frameStampPositionLock.set(original.position + delta)
|
|
||||||
|
|
||||||
if (tempTransaction) {
|
if (tempTransaction) {
|
||||||
tempTransaction.discard()
|
tempTransaction.discard()
|
||||||
|
@ -177,7 +169,7 @@ function useDragKeyframe(node: HTMLDivElement | null, props: IProps) {
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
onDragEnd(dragHappened) {
|
onDragEnd(dragHappened) {
|
||||||
frameStampPositionLock.unlock()
|
setIsDragging(false)
|
||||||
|
|
||||||
if (selectionDragHandlers) {
|
if (selectionDragHandlers) {
|
||||||
selectionDragHandlers.onDragEnd?.(dragHappened)
|
selectionDragHandlers.onDragEnd?.(dragHappened)
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
import {usePrism} from '@theatre/dataverse-react'
|
import {usePrism} from '@theatre/dataverse-react'
|
||||||
import type {Pointer} from '@theatre/dataverse'
|
import type {Pointer} from '@theatre/dataverse'
|
||||||
import {Box} from '@theatre/dataverse'
|
|
||||||
import {val} from '@theatre/dataverse'
|
import {val} from '@theatre/dataverse'
|
||||||
import React, {useMemo, useRef} from 'react'
|
import React, {useMemo, useRef, useState} from 'react'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
import type {SequenceEditorPanelLayout} from '@theatre/studio/panels/SequenceEditorPanel/layout/layout'
|
import type {SequenceEditorPanelLayout} from '@theatre/studio/panels/SequenceEditorPanel/layout/layout'
|
||||||
import {zIndexes} from '@theatre/studio/panels/SequenceEditorPanel/SequenceEditorPanel'
|
import {zIndexes} from '@theatre/studio/panels/SequenceEditorPanel/SequenceEditorPanel'
|
||||||
|
@ -13,7 +12,10 @@ import useDrag from '@theatre/studio/uiComponents/useDrag'
|
||||||
import getStudio from '@theatre/studio/getStudio'
|
import getStudio from '@theatre/studio/getStudio'
|
||||||
import type Sheet from '@theatre/core/sheets/Sheet'
|
import type Sheet from '@theatre/core/sheets/Sheet'
|
||||||
import usePopover from '@theatre/studio/uiComponents/Popover/usePopover'
|
import usePopover from '@theatre/studio/uiComponents/Popover/usePopover'
|
||||||
import {attributeNameThatLocksFramestamp} from '@theatre/studio/panels/SequenceEditorPanel/FrameStampPositionProvider'
|
import {
|
||||||
|
attributeNameThatLocksFramestamp,
|
||||||
|
useLockFrameStampPosition,
|
||||||
|
} from '@theatre/studio/panels/SequenceEditorPanel/FrameStampPositionProvider'
|
||||||
|
|
||||||
const coverWidth = 1000
|
const coverWidth = 1000
|
||||||
|
|
||||||
|
@ -159,7 +161,9 @@ const LengthIndicator: React.FC<IProps> = ({layoutP}) => {
|
||||||
function useDragBulge(node: HTMLDivElement | null, props: IProps) {
|
function useDragBulge(node: HTMLDivElement | null, props: IProps) {
|
||||||
const propsRef = useRef(props)
|
const propsRef = useRef(props)
|
||||||
propsRef.current = props
|
propsRef.current = props
|
||||||
const isDragging = useMemo(() => new Box(false), [])
|
const [isDragging, setIsDragging] = useState(false)
|
||||||
|
|
||||||
|
useLockFrameStampPosition(isDragging, -1)
|
||||||
|
|
||||||
const gestureHandlers = useMemo<Parameters<typeof useDrag>[1]>(() => {
|
const gestureHandlers = useMemo<Parameters<typeof useDrag>[1]>(() => {
|
||||||
let toUnitSpace: SequenceEditorPanelLayout['scaledSpace']['toUnitSpace']
|
let toUnitSpace: SequenceEditorPanelLayout['scaledSpace']['toUnitSpace']
|
||||||
|
@ -171,12 +175,12 @@ function useDragBulge(node: HTMLDivElement | null, props: IProps) {
|
||||||
return {
|
return {
|
||||||
lockCursorTo: 'ew-resize',
|
lockCursorTo: 'ew-resize',
|
||||||
onDragStart(event) {
|
onDragStart(event) {
|
||||||
|
setIsDragging(true)
|
||||||
propsAtStartOfDrag = propsRef.current
|
propsAtStartOfDrag = propsRef.current
|
||||||
sheet = val(propsRef.current.layoutP.sheet)
|
sheet = val(propsRef.current.layoutP.sheet)
|
||||||
initialLength = sheet.getSequence().length
|
initialLength = sheet.getSequence().length
|
||||||
|
|
||||||
toUnitSpace = val(propsAtStartOfDrag.layoutP.scaledSpace.toUnitSpace)
|
toUnitSpace = val(propsAtStartOfDrag.layoutP.scaledSpace.toUnitSpace)
|
||||||
isDragging.set(true)
|
|
||||||
},
|
},
|
||||||
onDrag(dx, dy, event) {
|
onDrag(dx, dy, event) {
|
||||||
const delta = toUnitSpace(dx)
|
const delta = toUnitSpace(dx)
|
||||||
|
@ -192,7 +196,7 @@ function useDragBulge(node: HTMLDivElement | null, props: IProps) {
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
onDragEnd(dragHappened) {
|
onDragEnd(dragHappened) {
|
||||||
isDragging.set(false)
|
setIsDragging(false)
|
||||||
if (dragHappened) {
|
if (dragHappened) {
|
||||||
if (tempTransaction) {
|
if (tempTransaction) {
|
||||||
tempTransaction.commit()
|
tempTransaction.commit()
|
||||||
|
@ -209,7 +213,7 @@ function useDragBulge(node: HTMLDivElement | null, props: IProps) {
|
||||||
|
|
||||||
useDrag(node, gestureHandlers)
|
useDrag(node, gestureHandlers)
|
||||||
|
|
||||||
return [isDragging.derivation]
|
return [isDragging]
|
||||||
}
|
}
|
||||||
|
|
||||||
export default LengthIndicator
|
export default LengthIndicator
|
||||||
|
|
|
@ -3,10 +3,17 @@ import {Atom, prism, val} from '@theatre/dataverse'
|
||||||
import mousePositionD from '@theatre/studio/utils/mousePositionD'
|
import mousePositionD from '@theatre/studio/utils/mousePositionD'
|
||||||
import type {$IntentionalAny} from '@theatre/shared/utils/types'
|
import type {$IntentionalAny} from '@theatre/shared/utils/types'
|
||||||
import {inRange, last} from 'lodash-es'
|
import {inRange, last} from 'lodash-es'
|
||||||
import React, {createContext, useCallback, useContext, useMemo} from 'react'
|
import React, {
|
||||||
|
createContext,
|
||||||
|
useCallback,
|
||||||
|
useContext,
|
||||||
|
useLayoutEffect,
|
||||||
|
useMemo,
|
||||||
|
useRef,
|
||||||
|
} from 'react'
|
||||||
import type {SequenceEditorPanelLayout} from './layout/layout'
|
import type {SequenceEditorPanelLayout} from './layout/layout'
|
||||||
|
|
||||||
export type FrameStampPositionLock = {
|
type FrameStampPositionLock = {
|
||||||
unlock: () => void
|
unlock: () => void
|
||||||
set: (pointerPositonInUnitSpace: number) => void
|
set: (pointerPositonInUnitSpace: number) => void
|
||||||
}
|
}
|
||||||
|
@ -93,7 +100,27 @@ const FrameStampPositionProvider: React.FC<{
|
||||||
return <context.Provider value={value}>{children}</context.Provider>
|
return <context.Provider value={value}>{children}</context.Provider>
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useFrameStampPosition = () => useContext(context)
|
export const useFrameStampPositionD = () => useContext(context).currentD
|
||||||
|
|
||||||
|
export const useLockFrameStampPosition = (shouldLock: boolean, val: number) => {
|
||||||
|
const {getLock} = useContext(context)
|
||||||
|
const lockRef = useRef<undefined | ReturnType<typeof getLock>>()
|
||||||
|
|
||||||
|
useLayoutEffect(() => {
|
||||||
|
if (!shouldLock) return
|
||||||
|
lockRef.current = getLock()
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
lockRef.current!.unlock()
|
||||||
|
}
|
||||||
|
}, [shouldLock])
|
||||||
|
|
||||||
|
useLayoutEffect(() => {
|
||||||
|
if (shouldLock) {
|
||||||
|
lockRef.current!.set(val)
|
||||||
|
}
|
||||||
|
}, [val])
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This attribute is used so that when the cursor hovers over a keyframe,
|
* This attribute is used so that when the cursor hovers over a keyframe,
|
||||||
|
@ -129,8 +156,6 @@ const pointerPositionInUnitSpace = (
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (mousePos.composedPath())
|
|
||||||
|
|
||||||
const {clientX, clientY} = mousePos
|
const {clientX, clientY} = mousePos
|
||||||
|
|
||||||
const {screenX: x, screenY: y, width: rightWidth, height} = rightDims
|
const {screenX: x, screenY: y, width: rightWidth, height} = rightDims
|
||||||
|
|
|
@ -6,13 +6,12 @@ import useDrag from '@theatre/studio/uiComponents/useDrag'
|
||||||
import useRefAndState from '@theatre/studio/utils/useRefAndState'
|
import useRefAndState from '@theatre/studio/utils/useRefAndState'
|
||||||
import type {VoidFn} from '@theatre/shared/utils/types'
|
import type {VoidFn} from '@theatre/shared/utils/types'
|
||||||
import {val} from '@theatre/dataverse'
|
import {val} from '@theatre/dataverse'
|
||||||
import React, {useMemo, useRef} from 'react'
|
import React, {useMemo, useRef, useState} from 'react'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
import type KeyframeEditor from './KeyframeEditor'
|
import type KeyframeEditor from './KeyframeEditor'
|
||||||
import type {Keyframe} from '@theatre/core/projects/store/types/SheetState_Historic'
|
import type {Keyframe} from '@theatre/core/projects/store/types/SheetState_Historic'
|
||||||
import type {FrameStampPositionLock} from '@theatre/studio/panels/SequenceEditorPanel/FrameStampPositionProvider'
|
import {useLockFrameStampPosition} from '@theatre/studio/panels/SequenceEditorPanel/FrameStampPositionProvider'
|
||||||
import {attributeNameThatLocksFramestamp} from '@theatre/studio/panels/SequenceEditorPanel/FrameStampPositionProvider'
|
import {attributeNameThatLocksFramestamp} from '@theatre/studio/panels/SequenceEditorPanel/FrameStampPositionProvider'
|
||||||
import {useFrameStampPosition} from '@theatre/studio/panels/SequenceEditorPanel/FrameStampPositionProvider'
|
|
||||||
|
|
||||||
export const dotSize = 6
|
export const dotSize = 6
|
||||||
|
|
||||||
|
@ -80,7 +79,8 @@ const Dot: React.FC<IProps> = (props) => {
|
||||||
export default Dot
|
export default Dot
|
||||||
|
|
||||||
function useDragKeyframe(node: SVGCircleElement | null, _props: IProps): void {
|
function useDragKeyframe(node: SVGCircleElement | null, _props: IProps): void {
|
||||||
const {getLock} = useFrameStampPosition()
|
const [isDragging, setIsDragging] = useState(false)
|
||||||
|
useLockFrameStampPosition(isDragging, _props.keyframe.position)
|
||||||
const propsRef = useRef(_props)
|
const propsRef = useRef(_props)
|
||||||
propsRef.current = _props
|
propsRef.current = _props
|
||||||
|
|
||||||
|
@ -92,11 +92,11 @@ function useDragKeyframe(node: SVGCircleElement | null, _props: IProps): void {
|
||||||
let verticalToExtremumSpace: SequenceEditorPanelLayout['graphEditorVerticalSpace']['toExtremumSpace']
|
let verticalToExtremumSpace: SequenceEditorPanelLayout['graphEditorVerticalSpace']['toExtremumSpace']
|
||||||
let unlockExtremums: VoidFn | undefined
|
let unlockExtremums: VoidFn | undefined
|
||||||
let keepSpeeds = false
|
let keepSpeeds = false
|
||||||
let frameStampPositionLock: FrameStampPositionLock
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
lockCursorTo: 'move',
|
lockCursorTo: 'move',
|
||||||
onDragStart(event) {
|
onDragStart(event) {
|
||||||
|
setIsDragging(true)
|
||||||
keepSpeeds = !!event.altKey
|
keepSpeeds = !!event.altKey
|
||||||
|
|
||||||
propsAtStartOfDrag = propsRef.current
|
propsAtStartOfDrag = propsRef.current
|
||||||
|
@ -106,8 +106,6 @@ function useDragKeyframe(node: SVGCircleElement | null, _props: IProps): void {
|
||||||
propsAtStartOfDrag.layoutP.graphEditorVerticalSpace.toExtremumSpace,
|
propsAtStartOfDrag.layoutP.graphEditorVerticalSpace.toExtremumSpace,
|
||||||
)
|
)
|
||||||
unlockExtremums = propsAtStartOfDrag.extremumSpace.lock()
|
unlockExtremums = propsAtStartOfDrag.extremumSpace.lock()
|
||||||
frameStampPositionLock = getLock()
|
|
||||||
frameStampPositionLock.set(propsAtStartOfDrag.keyframe.position)
|
|
||||||
},
|
},
|
||||||
onDrag(dx, dy) {
|
onDrag(dx, dy) {
|
||||||
const original =
|
const original =
|
||||||
|
@ -128,7 +126,6 @@ function useDragKeyframe(node: SVGCircleElement | null, _props: IProps): void {
|
||||||
value: original.value + dYInValueSpace,
|
value: original.value + dYInValueSpace,
|
||||||
handles: [...original.handles],
|
handles: [...original.handles],
|
||||||
}
|
}
|
||||||
frameStampPositionLock.set(cur.position)
|
|
||||||
updatedKeyframes.push(cur)
|
updatedKeyframes.push(cur)
|
||||||
|
|
||||||
if (keepSpeeds) {
|
if (keepSpeeds) {
|
||||||
|
@ -189,7 +186,7 @@ function useDragKeyframe(node: SVGCircleElement | null, _props: IProps): void {
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
onDragEnd(dragHappened) {
|
onDragEnd(dragHappened) {
|
||||||
frameStampPositionLock.unlock()
|
setIsDragging(false)
|
||||||
if (unlockExtremums) {
|
if (unlockExtremums) {
|
||||||
const unlock = unlockExtremums
|
const unlock = unlockExtremums
|
||||||
unlockExtremums = undefined
|
unlockExtremums = undefined
|
||||||
|
|
|
@ -7,7 +7,7 @@ import styled from 'styled-components'
|
||||||
import {stampsGridTheme} from '@theatre/studio/panels/SequenceEditorPanel/FrameGrid/StampsGrid'
|
import {stampsGridTheme} from '@theatre/studio/panels/SequenceEditorPanel/FrameGrid/StampsGrid'
|
||||||
import {zIndexes} from '@theatre/studio/panels/SequenceEditorPanel/SequenceEditorPanel'
|
import {zIndexes} from '@theatre/studio/panels/SequenceEditorPanel/SequenceEditorPanel'
|
||||||
import {topStripTheme} from './TopStrip'
|
import {topStripTheme} from './TopStrip'
|
||||||
import {useFrameStampPosition} from '@theatre/studio/panels/SequenceEditorPanel/FrameStampPositionProvider'
|
import {useFrameStampPositionD} from '@theatre/studio/panels/SequenceEditorPanel/FrameStampPositionProvider'
|
||||||
|
|
||||||
const Label = styled.div`
|
const Label = styled.div`
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
@ -36,7 +36,7 @@ const Line = styled.div`
|
||||||
const FrameStamp: React.FC<{
|
const FrameStamp: React.FC<{
|
||||||
layoutP: Pointer<SequenceEditorPanelLayout>
|
layoutP: Pointer<SequenceEditorPanelLayout>
|
||||||
}> = React.memo(({layoutP}) => {
|
}> = React.memo(({layoutP}) => {
|
||||||
const posInUnitSpace = useVal(useFrameStampPosition().currentD)
|
const posInUnitSpace = useVal(useFrameStampPositionD())
|
||||||
const unitSpaceToClippedSpace = useVal(layoutP.clippedSpace.fromUnitSpace)
|
const unitSpaceToClippedSpace = useVal(layoutP.clippedSpace.fromUnitSpace)
|
||||||
const {sequence, formatter, clippedSpaceWidth} = usePrism(() => {
|
const {sequence, formatter, clippedSpaceWidth} = usePrism(() => {
|
||||||
const sequence = val(layoutP.sheet).getSequence()
|
const sequence = val(layoutP.sheet).getSequence()
|
||||||
|
|
Loading…
Reference in a new issue