58 lines
2.0 KiB
TypeScript
58 lines
2.0 KiB
TypeScript
'use client'
|
|
|
|
import { type AnyNode, type AnyNodeId, useScene } from '@pascal-app/core'
|
|
import { triggerSFX } from '@pascal-app/editor'
|
|
import { useViewer } from '@pascal-app/viewer'
|
|
import { useMemo } from 'react'
|
|
import { FLOWER_PRESETS, FLOWER_SEED_POOL } from './flower-presets'
|
|
import FlowerPreview from './flower-preview'
|
|
import { FlowerNode } from './flower-schema'
|
|
import { usePlacement } from './placement'
|
|
import { useTreesStore } from './store'
|
|
|
|
/** The flowers placement tool — mirrors the trees tool, reading the flower
|
|
* brush from the shared store. Petal colour is baked from the preset at
|
|
* placement, then editable per-flower in the inspector. */
|
|
export default function FlowerTool() {
|
|
const activeLevelId = useViewer((s) => s.selection.levelId)
|
|
const preset = useTreesStore((s) => s.flowerPreset)
|
|
const height = useTreesStore((s) => s.flowerHeight)
|
|
|
|
const previewNode = useMemo(
|
|
() =>
|
|
FlowerNode.parse({
|
|
preset,
|
|
height,
|
|
petalColor: FLOWER_PRESETS[preset].petalColor,
|
|
seed: 1,
|
|
position: [0, 0, 0],
|
|
rotation: [0, 0, 0],
|
|
}),
|
|
[preset, height],
|
|
)
|
|
|
|
const { cursorRef, cursorVisible } = usePlacement(activeLevelId, (position) => {
|
|
if (!activeLevelId) return
|
|
const s = useTreesStore.getState()
|
|
const flower = FlowerNode.parse({
|
|
preset: s.flowerPreset,
|
|
height: s.flowerHeight,
|
|
petalColor: FLOWER_PRESETS[s.flowerPreset].petalColor,
|
|
seed: FLOWER_SEED_POOL[Math.floor(Math.random() * FLOWER_SEED_POOL.length)] ?? 1,
|
|
position,
|
|
rotation: [0, (Math.floor(Math.random() * 8) * Math.PI) / 4, 0],
|
|
})
|
|
useScene.getState().createNode(flower as unknown as AnyNode, activeLevelId as AnyNodeId)
|
|
useViewer.getState().setSelection({ selectedIds: [flower.id as AnyNodeId] })
|
|
triggerSFX('sfx:item-place')
|
|
})
|
|
|
|
if (!activeLevelId) return null
|
|
|
|
return (
|
|
<group ref={cursorRef} visible={cursorVisible}>
|
|
<FlowerPreview node={previewNode} />
|
|
</group>
|
|
)
|
|
}
|