floorplan/zone: name label inside polygon + polygon editor on select
`buildZoneFloorplan` now emits a centered name label at the polygon's area-weighted centroid (Shoelace formula, with bbox-center fallback for degenerate rings). Label uses the legacy `FloorplanZoneLabel` styling: `fontSize: 0.2`, white fill, zone-color stroke, `paintOrder: 'stroke'` for the "outlined text" look that stays legible above any fill. When the zone is selected the builder also emits the polygon editor — edge-handle per edge, midpoint-handle per midpoint, endpoint-handle per vertex — driven by the shared `createPolygonVertexAffordance` / `createPolygonAddVertexAffordance` / `createPolygonMoveEdgeAffordance` factories slabs and ceilings already use. Zones have no `holes` field so the factory's optional `holeIndex` stays undefined and the operations target `node.polygon` directly. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
3419cf8587
commit
0dee7747d2
@@ -0,0 +1,66 @@
|
||||
import { type NodeDefinition, ZoneNode as ZoneNodeSchema } from '@pascal-app/core'
|
||||
import {
|
||||
zoneAddVertexAffordance,
|
||||
zoneMoveEdgeAffordance,
|
||||
zoneMoveVertexAffordance,
|
||||
} from './floorplan-affordances'
|
||||
import { buildZoneFloorplan } from './floorplan'
|
||||
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',
|
||||
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,
|
||||
},
|
||||
|
||||
parametrics: zoneParametrics,
|
||||
|
||||
renderer: {
|
||||
kind: 'parametric',
|
||||
module: () => import('./renderer'),
|
||||
},
|
||||
system: {
|
||||
module: () => import('./system'),
|
||||
priority: 4,
|
||||
},
|
||||
floorplan: buildZoneFloorplan,
|
||||
// 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.png' },
|
||||
paletteSection: 'site',
|
||||
paletteOrder: 20,
|
||||
},
|
||||
|
||||
mcp: {
|
||||
description: 'A polygon-bounded site zone with a typed surface (grass / water / paving / ...).',
|
||||
},
|
||||
}
|
||||
Reference in New Issue
Block a user