Enable material paint for fence slab and ceiling nodes
This commit is contained in:
@@ -2,13 +2,16 @@ import {
|
|||||||
type AnyNode,
|
type AnyNode,
|
||||||
type AnyNodeId,
|
type AnyNodeId,
|
||||||
type BuildingNode,
|
type BuildingNode,
|
||||||
|
type CeilingNode,
|
||||||
emitter,
|
emitter,
|
||||||
|
type FenceNode,
|
||||||
type ItemNode,
|
type ItemNode,
|
||||||
type NodeEvent,
|
type NodeEvent,
|
||||||
type RoofEvent,
|
type RoofEvent,
|
||||||
type RoofNode,
|
type RoofNode,
|
||||||
type RoofSegmentEvent,
|
type RoofSegmentEvent,
|
||||||
resolveLevelId,
|
resolveLevelId,
|
||||||
|
type SlabNode,
|
||||||
type StairEvent,
|
type StairEvent,
|
||||||
type StairNode,
|
type StairNode,
|
||||||
type StairSegmentEvent,
|
type StairSegmentEvent,
|
||||||
@@ -25,6 +28,7 @@ import { useCallback, useEffect, useRef } from 'react'
|
|||||||
import { type BufferGeometry, Color, type Material, type Mesh, type Object3D } from 'three'
|
import { type BufferGeometry, Color, type Material, type Mesh, type Object3D } from 'three'
|
||||||
import {
|
import {
|
||||||
buildRoofSurfaceMaterialPatch,
|
buildRoofSurfaceMaterialPatch,
|
||||||
|
buildSingleSurfaceMaterialPatch,
|
||||||
buildStairSurfaceMaterialPatch,
|
buildStairSurfaceMaterialPatch,
|
||||||
buildWallSurfaceMaterialPatch,
|
buildWallSurfaceMaterialPatch,
|
||||||
hasActivePaintMaterial,
|
hasActivePaintMaterial,
|
||||||
@@ -609,7 +613,30 @@ export const SelectionManager = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const disabledNodeTypes = ['fence', 'item', 'slab', 'ceiling', 'window', 'door', 'zone']
|
if (node.type === 'fence' || node.type === 'slab' || node.type === 'ceiling') {
|
||||||
|
const target = node.type
|
||||||
|
const compatible =
|
||||||
|
isActivePaintMaterialCompatible(activePaintMaterial, target) &&
|
||||||
|
hasActivePaintMaterial(activePaintMaterial)
|
||||||
|
|
||||||
|
return {
|
||||||
|
apply: compatible
|
||||||
|
? () => {
|
||||||
|
useScene
|
||||||
|
.getState()
|
||||||
|
.updateNode(
|
||||||
|
node.id as AnyNodeId,
|
||||||
|
buildSingleSurfaceMaterialPatch<FenceNode | SlabNode | CeilingNode>(
|
||||||
|
activePaintMaterial.material,
|
||||||
|
activePaintMaterial.materialPreset,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const disabledNodeTypes = ['item', 'window', 'door', 'zone']
|
||||||
if (disabledNodeTypes.includes(node.type)) {
|
if (disabledNodeTypes.includes(node.type)) {
|
||||||
return {
|
return {
|
||||||
apply: null,
|
apply: null,
|
||||||
@@ -776,6 +803,14 @@ export const SelectionManager = () => {
|
|||||||
nextMaterialTargetHandled = true
|
nextMaterialTargetHandled = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
(node.type === 'fence' || node.type === 'slab' || node.type === 'ceiling') &&
|
||||||
|
nodeToSelect.type === node.type
|
||||||
|
) {
|
||||||
|
setSelectedMaterialTargetForNode(nodeToSelect, 'surface')
|
||||||
|
nextMaterialTargetHandled = true
|
||||||
|
}
|
||||||
|
|
||||||
if (!nextMaterialTargetHandled && useEditor.getState().selectedMaterialTarget) {
|
if (!nextMaterialTargetHandled && useEditor.getState().selectedMaterialTarget) {
|
||||||
useEditor.getState().setSelectedMaterialTarget(null)
|
useEditor.getState().setSelectedMaterialTarget(null)
|
||||||
}
|
}
|
||||||
@@ -1092,6 +1127,9 @@ const SelectionStateSync = () => {
|
|||||||
if (
|
if (
|
||||||
!selectedNode ||
|
!selectedNode ||
|
||||||
(selectedNode.type !== 'wall' &&
|
(selectedNode.type !== 'wall' &&
|
||||||
|
selectedNode.type !== 'fence' &&
|
||||||
|
selectedNode.type !== 'slab' &&
|
||||||
|
selectedNode.type !== 'ceiling' &&
|
||||||
selectedNode.type !== 'stair' &&
|
selectedNode.type !== 'stair' &&
|
||||||
selectedNode.type !== 'roof')
|
selectedNode.type !== 'roof')
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
type CeilingNode,
|
||||||
|
type FenceNode,
|
||||||
getCatalogMaterialById,
|
getCatalogMaterialById,
|
||||||
getEffectiveRoofSurfaceMaterial,
|
getEffectiveRoofSurfaceMaterial,
|
||||||
getEffectiveStairSurfaceMaterial,
|
getEffectiveStairSurfaceMaterial,
|
||||||
@@ -10,13 +12,19 @@ import {
|
|||||||
type MaterialTarget,
|
type MaterialTarget,
|
||||||
type RoofNode,
|
type RoofNode,
|
||||||
type RoofSurfaceMaterialRole,
|
type RoofSurfaceMaterialRole,
|
||||||
|
type SlabNode,
|
||||||
type StairNode,
|
type StairNode,
|
||||||
type StairSurfaceMaterialRole,
|
type StairSurfaceMaterialRole,
|
||||||
type WallNode,
|
type WallNode,
|
||||||
type WallSurfaceSide,
|
type WallSurfaceSide,
|
||||||
} from '@pascal-app/core'
|
} from '@pascal-app/core'
|
||||||
|
|
||||||
export type PaintableMaterialTarget = Extract<MaterialTarget, 'wall' | 'roof' | 'stair'>
|
export type PaintableMaterialTarget = Extract<
|
||||||
|
MaterialTarget,
|
||||||
|
'wall' | 'roof' | 'stair' | 'fence' | 'slab' | 'ceiling'
|
||||||
|
>
|
||||||
|
|
||||||
|
export type SingleSurfaceMaterialRole = 'surface'
|
||||||
|
|
||||||
export type ActivePaintMaterial = {
|
export type ActivePaintMaterial = {
|
||||||
material?: MaterialSchema
|
material?: MaterialSchema
|
||||||
@@ -135,12 +143,26 @@ export function buildStairSurfaceMaterialPatch(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function buildSingleSurfaceMaterialPatch<TNode extends FenceNode | SlabNode | CeilingNode>(
|
||||||
|
material: MaterialSchema | undefined,
|
||||||
|
materialPreset: string | undefined,
|
||||||
|
): Partial<TNode> {
|
||||||
|
return {
|
||||||
|
material,
|
||||||
|
materialPreset,
|
||||||
|
} as Partial<TNode>
|
||||||
|
}
|
||||||
|
|
||||||
export function resolveActivePaintMaterialFromSelection(params: {
|
export function resolveActivePaintMaterialFromSelection(params: {
|
||||||
nodes: Record<string, any>
|
nodes: Record<string, any>
|
||||||
selectedId: string | null
|
selectedId: string | null
|
||||||
selectedMaterialTarget: {
|
selectedMaterialTarget: {
|
||||||
nodeId: string
|
nodeId: string
|
||||||
role: WallSurfaceSide | StairSurfaceMaterialRole | RoofSurfaceMaterialRole
|
role:
|
||||||
|
| WallSurfaceSide
|
||||||
|
| StairSurfaceMaterialRole
|
||||||
|
| RoofSurfaceMaterialRole
|
||||||
|
| SingleSurfaceMaterialRole
|
||||||
} | null
|
} | null
|
||||||
}): ActivePaintMaterial | null {
|
}): ActivePaintMaterial | null {
|
||||||
const { nodes, selectedId, selectedMaterialTarget } = params
|
const { nodes, selectedId, selectedMaterialTarget } = params
|
||||||
@@ -208,6 +230,26 @@ export function resolveActivePaintMaterialFromSelection(params: {
|
|||||||
: null
|
: null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
(selectedNode.type === 'fence' ||
|
||||||
|
selectedNode.type === 'slab' ||
|
||||||
|
selectedNode.type === 'ceiling') &&
|
||||||
|
selectedMaterialTarget.role === 'surface'
|
||||||
|
) {
|
||||||
|
const target = selectedNode.type
|
||||||
|
return hasActivePaintMaterial({
|
||||||
|
material: selectedNode.material,
|
||||||
|
materialPreset: selectedNode.materialPreset,
|
||||||
|
sourceTarget: target,
|
||||||
|
})
|
||||||
|
? {
|
||||||
|
material: selectedNode.material,
|
||||||
|
materialPreset: selectedNode.materialPreset,
|
||||||
|
sourceTarget: target,
|
||||||
|
}
|
||||||
|
: null
|
||||||
|
}
|
||||||
|
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -233,5 +275,17 @@ export function resolvePaintTargetFromSelection(params: {
|
|||||||
return 'stair'
|
return 'stair'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (selectedNode.type === 'fence') {
|
||||||
|
return 'fence'
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectedNode.type === 'slab') {
|
||||||
|
return 'slab'
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectedNode.type === 'ceiling') {
|
||||||
|
return 'ceiling'
|
||||||
|
}
|
||||||
|
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import {
|
|||||||
type PaintableMaterialTarget,
|
type PaintableMaterialTarget,
|
||||||
resolveActivePaintMaterialFromSelection,
|
resolveActivePaintMaterialFromSelection,
|
||||||
resolvePaintTargetFromSelection,
|
resolvePaintTargetFromSelection,
|
||||||
|
type SingleSurfaceMaterialRole,
|
||||||
} from '../lib/material-paint'
|
} from '../lib/material-paint'
|
||||||
|
|
||||||
const DEFAULT_ACTIVE_SIDEBAR_PANEL = 'site'
|
const DEFAULT_ACTIVE_SIDEBAR_PANEL = 'site'
|
||||||
@@ -94,6 +95,7 @@ export type MaterialTargetRole =
|
|||||||
| WallSurfaceSide
|
| WallSurfaceSide
|
||||||
| StairSurfaceMaterialRole
|
| StairSurfaceMaterialRole
|
||||||
| RoofSurfaceMaterialRole
|
| RoofSurfaceMaterialRole
|
||||||
|
| SingleSurfaceMaterialRole
|
||||||
|
|
||||||
export type SelectedMaterialTarget = {
|
export type SelectedMaterialTarget = {
|
||||||
nodeId: AnyNodeId
|
nodeId: AnyNodeId
|
||||||
|
|||||||
Reference in New Issue
Block a user