79 lines
2.6 KiB
TypeScript
79 lines
2.6 KiB
TypeScript
import { type NodeDefinition, ZoneNode as ZoneNodeSchema } from '@pascal-app/core'
|
|
import { buildZoneFloorplan } from './floorplan'
|
|
import {
|
|
zoneAddVertexAffordance,
|
|
zoneMoveEdgeAffordance,
|
|
zoneMoveVertexAffordance,
|
|
} from './floorplan-affordances'
|
|
import { zoneFloorplanMoveTarget } from './floorplan-move'
|
|
import { zoneParametrics } from './parametrics'
|
|
import { ZoneNode } from './schema'
|
|
|
|
/**
|
|
* Zone — Stage A. Custom-behavior escape hatch: zone uses TSL shader
|
|
* materials + `<Html>` portals + per-frame uniform poking, so it
|
|
* lives via `def.renderer` + `def.system` (no `def.geometry` possible
|
|
* because zone isn't really a mesh).
|
|
*/
|
|
export const zoneDefinition: NodeDefinition<typeof ZoneNode> = {
|
|
kind: 'zone',
|
|
snapProfile: 'structural',
|
|
schemaVersion: 1,
|
|
schema: ZoneNode,
|
|
category: 'site',
|
|
|
|
defaults: () => {
|
|
const stub = ZoneNodeSchema.parse({ id: 'zone_default' as never, type: 'zone' })
|
|
const { id: _id, type: _type, ...rest } = stub
|
|
return rest
|
|
},
|
|
|
|
capabilities: {
|
|
selectable: { hitVolume: 'bbox' },
|
|
duplicable: true,
|
|
deletable: true,
|
|
// Zones describe regions of a site — they don't translate as
|
|
// reusable presets independent of their site context.
|
|
presettable: false,
|
|
},
|
|
|
|
parametrics: zoneParametrics,
|
|
// No dirty consumer rebuilds this kind — see NodeDefinition.dirtyTracking.
|
|
dirtyTracking: false,
|
|
|
|
renderer: {
|
|
kind: 'parametric',
|
|
module: () => import('./renderer'),
|
|
},
|
|
system: {
|
|
module: () => import('./system'),
|
|
priority: 4,
|
|
},
|
|
floorplan: buildZoneFloorplan,
|
|
// 2D body move — centroid-pivot polygon mover (same as slab / ceiling).
|
|
// Without this, zone fell through to the overlay's generic free-translate
|
|
// path, which committed a `position` field zone has no schema for, so the
|
|
// polygon never actually moved on drop.
|
|
floorplanMoveTarget: zoneFloorplanMoveTarget,
|
|
// Polygon editor when selected — same three operations slabs / ceilings
|
|
// expose. The shared factories key off `node.polygon`, optional
|
|
// `node.holes` (absent on zones). See `floorplan-affordances.ts`.
|
|
floorplanAffordances: {
|
|
'move-vertex': zoneMoveVertexAffordance,
|
|
'add-vertex': zoneAddVertexAffordance,
|
|
'move-edge': zoneMoveEdgeAffordance,
|
|
},
|
|
|
|
presentation: {
|
|
label: 'Zone',
|
|
description: 'A polygonal site zone (lawn, water, paving) with a TSL gradient material.',
|
|
icon: { kind: 'url', src: '/icons/zone.webp' },
|
|
paletteSection: 'site',
|
|
paletteOrder: 20,
|
|
},
|
|
|
|
mcp: {
|
|
description: 'A polygon-bounded site zone with a typed surface (grass / water / paving / ...).',
|
|
},
|
|
}
|