Nudging behavior on number props can now be customized

This commit is contained in:
Aria Minaei 2021-08-22 12:58:38 +02:00
parent 74724d7ec1
commit 36017c6a73
7 changed files with 81 additions and 14 deletions

View file

@ -13,7 +13,7 @@ const editorSheetObjectConfig = types.compound({
showAxes: types.boolean(true, {label: 'Axes'}),
showGrid: types.boolean(true, {label: 'Grid'}),
showOverlayIcons: types.boolean(false, {label: 'Overlay Icons'}),
resolution: types.number(1440, {
resolution: types.number(500, {
label: 'Resolution',
range: [0, 1000],
}),

View file

@ -18,21 +18,25 @@ export type TransformControlsMode = 'translate' | 'rotate' | 'scale'
export type TransformControlsSpace = 'world' | 'local'
export type ViewportShading = 'wireframe' | 'flat' | 'solid' | 'rendered'
const positionComp = types.number(1, {nudgeMultiplier: 0.1})
const rotationComp = types.number(1, {nudgeMultiplier: 0.02})
const scaleComp = types.number(1, {nudgeMultiplier: 0.1})
export const baseSheetObjectType = types.compound({
position: types.compound({
x: types.number(0),
y: types.number(0),
z: types.number(0),
x: positionComp,
y: positionComp,
z: positionComp,
}),
rotation: types.compound({
x: types.number(0),
y: types.number(0),
z: types.number(0),
x: rotationComp,
y: rotationComp,
z: rotationComp,
}),
scale: types.compound({
x: types.number(1),
y: types.number(1),
z: types.number(1),
x: scaleComp,
y: scaleComp,
z: scaleComp,
}),
})

View file

@ -13,11 +13,40 @@ export interface PropTypeConfig_Number extends IBasePropType<number> {
type: 'number'
default: number
range?: [min: number, max: number]
nudgeFn: NumberNudgeFn
nudgeMultiplier: number
}
export type NumberNudgeFn = (p: {
deltaX: number
deltaFraction: number
magnitude: number
config: PropTypeConfig_Number
}) => number
const defaultNumberNudgeFn: NumberNudgeFn = ({
config,
deltaX,
deltaFraction,
magnitude,
}) => {
const {range} = config
if (range) {
return (
deltaFraction * (range[1] - range[0]) * magnitude * config.nudgeMultiplier
)
}
return deltaX * magnitude * config.nudgeMultiplier
}
export const number = (
defaultValue: number,
opts?: Pick<PropTypeConfig_Number, 'range'> & PropTypeConfigExtras,
opts?: {
nudgeFn?: PropTypeConfig_Number['nudgeFn']
range?: PropTypeConfig_Number['range']
nudgeMultiplier?: number
} & PropTypeConfigExtras,
): PropTypeConfig_Number => {
return {
type: 'number',
@ -26,6 +55,9 @@ export const number = (
[s]: 'TheatrePropType',
...(opts ? opts : {}),
label: opts?.label,
nudgeFn: opts?.nudgeFn ?? defaultNumberNudgeFn,
nudgeMultiplier:
typeof opts?.nudgeMultiplier === 'number' ? opts.nudgeMultiplier : 1,
}
}

View file

@ -1,7 +1,7 @@
import type {PropTypeConfig_Number} from '@theatre/core/propTypes'
import type SheetObject from '@theatre/core/sheetObjects/SheetObject'
import BasicNumberInput from '@theatre/studio/uiComponents/form/BasicNumberInput'
import React from 'react'
import React, {useCallback} from 'react'
import {useEditingToolsForPrimitiveProp} from './utils/useEditingToolsForPrimitiveProp'
import {SingleRowPropEditor} from './utils/SingleRowPropEditor'
@ -12,6 +12,13 @@ const NumberPropEditor: React.FC<{
}> = ({propConfig, pointerToProp, obj}) => {
const stuff = useEditingToolsForPrimitiveProp<number>(pointerToProp, obj)
const nudge = useCallback(
(params: {deltaX: number; deltaFraction: number; magnitude: number}) => {
return propConfig.nudgeFn({...params, config: propConfig})
},
[propConfig],
)
return (
<SingleRowPropEditor {...{stuff, propConfig, pointerToProp}}>
<BasicNumberInput
@ -20,6 +27,7 @@ const NumberPropEditor: React.FC<{
discardTemporaryValue={stuff.discardTemporaryValue}
permenantlySetValue={stuff.permenantlySetValue}
range={propConfig.range}
nudge={nudge}
/>
</SingleRowPropEditor>
)

View file

@ -4,6 +4,7 @@ import styled from 'styled-components'
import type {SequenceEditorPanelLayout} from '@theatre/studio/panels/SequenceEditorPanel/layout/layout'
import {usePrism, useVal} from '@theatre/dataverse-react'
import getStudio from '@theatre/studio/getStudio'
import type {BasicNumberInputNudgeFn} from '@theatre/studio/uiComponents/form/BasicNumberInput'
import BasicNumberInput from '@theatre/studio/uiComponents/form/BasicNumberInput'
import type {CommitOrDiscard} from '@theatre/studio/StudioStore/StudioStore'
import {propNameText} from '@theatre/studio/panels/DetailPanel/propEditors/utils/SingleRowPropEditor'
@ -23,6 +24,8 @@ const Label = styled.div`
white-space: nowrap;
`
const nudge: BasicNumberInputNudgeFn = ({deltaX}) => deltaX * 0.25
const LengthEditorPopover: React.FC<{
layoutP: Pointer<SequenceEditorPanelLayout>
/**
@ -87,6 +90,7 @@ const LengthEditorPopover: React.FC<{
isValid={greaterThanZero}
inputRef={inputRef}
onBlur={onRequestClose}
nudge={nudge}
/>
</Container>
)

View file

@ -73,6 +73,7 @@ const FillIndicator = styled.div`
background-color: #2d5561;
z-index: -1;
border-radius: 2px;
pointer-events: none;
${Container}.dragging &, ${Container}.noFocus:hover & {
background-color: #338198;
@ -103,6 +104,12 @@ type IState = IState_NoFocus | IState_EditingViaKeyboard | IState_Dragging
const alwaysValid = (v: number) => true
export type BasicNumberInputNudgeFn = (params: {
deltaX: number
deltaFraction: number
magnitude: number
}) => number
const BasicNumberInput: React.FC<{
value: number
temporarilySetValue: (v: number) => void
@ -117,6 +124,7 @@ const BasicNumberInput: React.FC<{
* before this, so use this for UI purposes such as closing a popover.
*/
onBlur?: () => void
nudge: BasicNumberInputNudgeFn
}> = (propsA) => {
const [stateA, setState] = useState<IState>({mode: 'noFocus'})
const isValid = propsA.isValid ?? alwaysValid
@ -207,8 +215,11 @@ const BasicNumberInput: React.FC<{
})
}
let inputWidth: number
const transitionToDraggingMode = () => {
const curValue = refs.current.props.value
inputWidth = inputRef.current?.getBoundingClientRect().width!
setState({
mode: 'dragging',
@ -238,9 +249,16 @@ const BasicNumberInput: React.FC<{
}
}
const onDrag = (dx: number, _dy: number) => {
const onDrag = (deltaX: number, _dy: number) => {
const curState = refs.current.state as IState_Dragging
const newValue = curState.valueBeforeDragging + dx
const newValue =
curState.valueBeforeDragging +
propsA.nudge({
deltaX,
deltaFraction: deltaX / inputWidth,
magnitude: 1,
})
setState({
...curState,

View file

@ -23,6 +23,7 @@ const Container = styled.ul`
min-width: ${minWidth}px;
z-index: 10000;
background: ${transparentize(0.2, '#111')};
backdrop-filter: blur(2px);
color: white;
list-style-type: none;
padding: 2px 0;