Files
editor/packages/editor/src/lib/window-interaction.ts
T

87 lines
2.2 KiB
TypeScript

import {
type AnyNodeId,
useInteractive,
useScene,
type WindowInteractiveState,
} from '@pascal-app/core'
export const WINDOW_TOGGLE_ANIMATION_MS = 520
type WindowOpenAnimationOptions = {
persist?: boolean
}
export function isOperableWindowType(windowType: string | undefined) {
return (
windowType === 'sliding' ||
windowType === 'casement' ||
windowType === 'awning' ||
windowType === 'hopper' ||
windowType === 'single-hung' ||
windowType === 'double-hung' ||
windowType === 'louvered'
)
}
function getDisplayedWindowValue(windowId: AnyNodeId, nodeValue: number | undefined) {
const interactive = useInteractive.getState()
const runtimeValue = interactive.windows[windowId]?.operationState
if (runtimeValue !== undefined) return runtimeValue
const queuedValue = interactive.windowAnimations[windowId]?.from
if (queuedValue !== undefined) return queuedValue
return nodeValue ?? 0
}
function startWindowOpenAnimation(
windowId: AnyNodeId,
field: keyof WindowInteractiveState,
from: number,
to: number,
options?: WindowOpenAnimationOptions,
) {
useInteractive.getState().startWindowAnimation(windowId, {
field,
from,
to,
startedAt: null,
durationMs: WINDOW_TOGGLE_ANIMATION_MS,
persist: options?.persist ?? true,
})
}
export function toggleWindowOpenState(windowId: AnyNodeId, options?: WindowOpenAnimationOptions) {
const node = useScene.getState().nodes[windowId]
if (
node?.type !== 'window' ||
node.openingKind === 'opening' ||
!isOperableWindowType(node.windowType)
) {
return
}
const currentOpenAmount = getDisplayedWindowValue(windowId, node.operationState)
startWindowOpenAnimation(
windowId,
'operationState',
currentOpenAmount,
currentOpenAmount >= 0.5 ? 0 : 1,
options,
)
}
export function closeWindowOpenState(windowId: AnyNodeId, options?: WindowOpenAnimationOptions) {
const node = useScene.getState().nodes[windowId]
if (
node?.type !== 'window' ||
node.openingKind === 'opening' ||
!isOperableWindowType(node.windowType)
) {
return
}
const currentOpenAmount = getDisplayedWindowValue(windowId, node.operationState)
startWindowOpenAnimation(windowId, 'operationState', currentOpenAmount, 0, options)
}