@pascal-app/core 0.3.1 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/dist/index.d.ts +1 -0
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +1 -0
  4. package/dist/schema/index.d.ts +2 -1
  5. package/dist/schema/index.d.ts.map +1 -1
  6. package/dist/schema/index.js +3 -1
  7. package/dist/schema/material.d.ts +62 -0
  8. package/dist/schema/material.d.ts.map +1 -0
  9. package/dist/schema/material.js +130 -0
  10. package/dist/schema/nodes/ceiling.d.ts +31 -0
  11. package/dist/schema/nodes/ceiling.d.ts.map +1 -1
  12. package/dist/schema/nodes/ceiling.js +2 -2
  13. package/dist/schema/nodes/door.d.ts +33 -2
  14. package/dist/schema/nodes/door.d.ts.map +1 -1
  15. package/dist/schema/nodes/door.js +2 -0
  16. package/dist/schema/nodes/roof-segment.d.ts +31 -0
  17. package/dist/schema/nodes/roof-segment.d.ts.map +1 -1
  18. package/dist/schema/nodes/roof-segment.js +2 -1
  19. package/dist/schema/nodes/roof.d.ts +31 -0
  20. package/dist/schema/nodes/roof.d.ts.map +1 -1
  21. package/dist/schema/nodes/roof.js +2 -1
  22. package/dist/schema/nodes/slab.d.ts +31 -0
  23. package/dist/schema/nodes/slab.d.ts.map +1 -1
  24. package/dist/schema/nodes/slab.js +2 -2
  25. package/dist/schema/nodes/wall.d.ts +31 -0
  26. package/dist/schema/nodes/wall.d.ts.map +1 -1
  27. package/dist/schema/nodes/wall.js +2 -1
  28. package/dist/schema/nodes/window.d.ts +31 -0
  29. package/dist/schema/nodes/window.d.ts.map +1 -1
  30. package/dist/schema/nodes/window.js +2 -1
  31. package/dist/schema/types.d.ts +218 -1
  32. package/dist/schema/types.d.ts.map +1 -1
  33. package/dist/store/actions/node-actions.d.ts.map +1 -1
  34. package/dist/store/actions/node-actions.js +9 -3
  35. package/dist/store/use-scene.d.ts.map +1 -1
  36. package/dist/store/use-scene.js +1 -0
  37. package/dist/utils/clone-scene-graph.d.ts +18 -0
  38. package/dist/utils/clone-scene-graph.d.ts.map +1 -0
  39. package/dist/utils/clone-scene-graph.js +96 -0
  40. package/package.json +2 -2
package/dist/index.d.ts CHANGED
@@ -18,5 +18,6 @@ export { DEFAULT_WALL_HEIGHT, DEFAULT_WALL_THICKNESS, getWallPlanFootprint, getW
18
18
  export { calculateLevelMiters, type Point2D, pointToKey, type WallMiterData, } from './systems/wall/wall-mitering';
19
19
  export { WallSystem } from './systems/wall/wall-system';
20
20
  export { WindowSystem } from './systems/window/window-system';
21
+ export { cloneSceneGraph } from './utils/clone-scene-graph';
21
22
  export { isObject } from './utils/types';
22
23
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,YAAY,EACV,aAAa,EACb,kBAAkB,EAClB,YAAY,EACZ,SAAS,EACT,WAAW,EACX,SAAS,EACT,SAAS,EACT,UAAU,EACV,SAAS,EACT,SAAS,EACT,gBAAgB,EAChB,SAAS,EACT,SAAS,EACT,SAAS,EACT,WAAW,EACX,SAAS,GACV,MAAM,cAAc,CAAA;AAErB,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAErD,OAAO,EACL,aAAa,EACb,WAAW,GACZ,MAAM,uCAAuC,CAAA;AAC9C,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,2CAA2C,CAAA;AAC9F,OAAO,EACL,mBAAmB,EACnB,cAAc,GACf,MAAM,wCAAwC,CAAA;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,wCAAwC,CAAA;AAExE,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAE7D,OAAO,EACL,oBAAoB,EACpB,sBAAsB,EACtB,KAAK,KAAK,EACV,iBAAiB,GAClB,MAAM,uBAAuB,CAAA;AAE9B,cAAc,UAAU,CAAA;AACxB,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,oBAAoB,EACzB,cAAc,GACf,MAAM,yBAAyB,CAAA;AAChC,OAAO,EAAE,iBAAiB,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAE1E,OAAO,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAA;AAChE,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAA;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAA;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAA;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAA;AACvD,OAAO,EACL,mBAAmB,EACnB,sBAAsB,EACtB,oBAAoB,EACpB,gBAAgB,GACjB,MAAM,+BAA+B,CAAA;AACtC,OAAO,EACL,oBAAoB,EACpB,KAAK,OAAO,EACZ,UAAU,EACV,KAAK,aAAa,GACnB,MAAM,8BAA8B,CAAA;AACrC,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAA;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAA;AAC7D,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,YAAY,EACV,aAAa,EACb,kBAAkB,EAClB,YAAY,EACZ,SAAS,EACT,WAAW,EACX,SAAS,EACT,SAAS,EACT,UAAU,EACV,SAAS,EACT,SAAS,EACT,gBAAgB,EAChB,SAAS,EACT,SAAS,EACT,SAAS,EACT,WAAW,EACX,SAAS,GACV,MAAM,cAAc,CAAA;AAErB,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAErD,OAAO,EACL,aAAa,EACb,WAAW,GACZ,MAAM,uCAAuC,CAAA;AAC9C,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,2CAA2C,CAAA;AAC9F,OAAO,EACL,mBAAmB,EACnB,cAAc,GACf,MAAM,wCAAwC,CAAA;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,wCAAwC,CAAA;AAExE,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAE7D,OAAO,EACL,oBAAoB,EACpB,sBAAsB,EACtB,KAAK,KAAK,EACV,iBAAiB,GAClB,MAAM,uBAAuB,CAAA;AAE9B,cAAc,UAAU,CAAA;AACxB,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,oBAAoB,EACzB,cAAc,GACf,MAAM,yBAAyB,CAAA;AAChC,OAAO,EAAE,iBAAiB,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAE1E,OAAO,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAA;AAChE,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAA;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAA;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAA;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAA;AACvD,OAAO,EACL,mBAAmB,EACnB,sBAAsB,EACtB,oBAAoB,EACpB,gBAAgB,GACjB,MAAM,+BAA+B,CAAA;AACtC,OAAO,EACL,oBAAoB,EACpB,KAAK,OAAO,EACZ,UAAU,EACV,KAAK,aAAa,GACnB,MAAM,8BAA8B,CAAA;AACrC,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAA;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAA;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAA;AAC3D,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA"}
package/dist/index.js CHANGED
@@ -24,4 +24,5 @@ export { DEFAULT_WALL_HEIGHT, DEFAULT_WALL_THICKNESS, getWallPlanFootprint, getW
24
24
  export { calculateLevelMiters, pointToKey, } from './systems/wall/wall-mitering';
25
25
  export { WallSystem } from './systems/wall/wall-system';
26
26
  export { WindowSystem } from './systems/window/window-system';
27
+ export { cloneSceneGraph } from './utils/clone-scene-graph';
27
28
  export { isObject } from './utils/types';
@@ -1,6 +1,7 @@
1
- export { BaseNode, generateId, Material, nodeType, objectId } from './base';
1
+ export { BaseNode, generateId, nodeType, objectId } from './base';
2
2
  export { CameraSchema } from './camera';
3
3
  export { type Collection, type CollectionId, generateCollectionId } from './collections';
4
+ export { DEFAULT_MATERIALS, MaterialPreset, MaterialProperties, MaterialSchema, resolveMaterial, } from './material';
4
5
  export { BuildingNode } from './nodes/building';
5
6
  export { CeilingNode } from './nodes/ceiling';
6
7
  export { DoorNode, DoorSegment } from './nodes/door';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/schema/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAA;AAE3E,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AAEvC,OAAO,EAAE,KAAK,UAAU,EAAE,KAAK,YAAY,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAA;AACxF,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAC7C,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AACzC,YAAY,EACV,eAAe,EACf,KAAK,EACL,UAAU,EACV,OAAO,EACP,MAAM,EACN,WAAW,EACX,WAAW,EACX,aAAa,EACb,kBAAkB,EAClB,aAAa,GACd,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAC5D,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AACvC,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AAChE,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAEvC,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AACvC,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AACvC,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAErD,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/schema/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAA;AAEjE,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AAEvC,OAAO,EAAE,KAAK,UAAU,EAAE,KAAK,YAAY,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAA;AAExF,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,kBAAkB,EAClB,cAAc,EACd,eAAe,GAChB,MAAM,YAAY,CAAA;AACnB,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAC7C,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AACzC,YAAY,EACV,eAAe,EACf,KAAK,EACL,UAAU,EACV,OAAO,EACP,MAAM,EACN,WAAW,EACX,WAAW,EACX,aAAa,EACb,kBAAkB,EAClB,aAAa,GACd,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAC5D,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AACvC,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AAChE,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAEvC,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AACvC,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AACvC,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAErD,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA"}
@@ -1,9 +1,11 @@
1
1
  // Base
2
- export { BaseNode, generateId, Material, nodeType, objectId } from './base';
2
+ export { BaseNode, generateId, nodeType, objectId } from './base';
3
3
  // Camera
4
4
  export { CameraSchema } from './camera';
5
5
  // Collections
6
6
  export { generateCollectionId } from './collections';
7
+ // Material
8
+ export { DEFAULT_MATERIALS, MaterialPreset, MaterialProperties, MaterialSchema, resolveMaterial, } from './material';
7
9
  export { BuildingNode } from './nodes/building';
8
10
  export { CeilingNode } from './nodes/ceiling';
9
11
  export { DoorNode, DoorSegment } from './nodes/door';
@@ -0,0 +1,62 @@
1
+ import { z } from 'zod';
2
+ export declare const MaterialPreset: z.ZodEnum<{
3
+ custom: "custom";
4
+ white: "white";
5
+ brick: "brick";
6
+ concrete: "concrete";
7
+ wood: "wood";
8
+ glass: "glass";
9
+ metal: "metal";
10
+ plaster: "plaster";
11
+ tile: "tile";
12
+ marble: "marble";
13
+ }>;
14
+ export type MaterialPreset = z.infer<typeof MaterialPreset>;
15
+ export declare const MaterialProperties: z.ZodObject<{
16
+ color: z.ZodDefault<z.ZodString>;
17
+ roughness: z.ZodDefault<z.ZodNumber>;
18
+ metalness: z.ZodDefault<z.ZodNumber>;
19
+ opacity: z.ZodDefault<z.ZodNumber>;
20
+ transparent: z.ZodDefault<z.ZodBoolean>;
21
+ side: z.ZodDefault<z.ZodEnum<{
22
+ front: "front";
23
+ back: "back";
24
+ double: "double";
25
+ }>>;
26
+ }, z.core.$strip>;
27
+ export type MaterialProperties = z.infer<typeof MaterialProperties>;
28
+ export declare const MaterialSchema: z.ZodObject<{
29
+ preset: z.ZodOptional<z.ZodEnum<{
30
+ custom: "custom";
31
+ white: "white";
32
+ brick: "brick";
33
+ concrete: "concrete";
34
+ wood: "wood";
35
+ glass: "glass";
36
+ metal: "metal";
37
+ plaster: "plaster";
38
+ tile: "tile";
39
+ marble: "marble";
40
+ }>>;
41
+ properties: z.ZodOptional<z.ZodObject<{
42
+ color: z.ZodDefault<z.ZodString>;
43
+ roughness: z.ZodDefault<z.ZodNumber>;
44
+ metalness: z.ZodDefault<z.ZodNumber>;
45
+ opacity: z.ZodDefault<z.ZodNumber>;
46
+ transparent: z.ZodDefault<z.ZodBoolean>;
47
+ side: z.ZodDefault<z.ZodEnum<{
48
+ front: "front";
49
+ back: "back";
50
+ double: "double";
51
+ }>>;
52
+ }, z.core.$strip>>;
53
+ texture: z.ZodOptional<z.ZodObject<{
54
+ url: z.ZodString;
55
+ repeat: z.ZodOptional<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>>;
56
+ scale: z.ZodOptional<z.ZodNumber>;
57
+ }, z.core.$strip>>;
58
+ }, z.core.$strip>;
59
+ export type MaterialSchema = z.infer<typeof MaterialSchema>;
60
+ export declare const DEFAULT_MATERIALS: Record<MaterialPreset, MaterialProperties>;
61
+ export declare function resolveMaterial(material?: MaterialSchema): MaterialProperties;
62
+ //# sourceMappingURL=material.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"material.d.ts","sourceRoot":"","sources":["../../src/schema/material.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,eAAO,MAAM,cAAc;;;;;;;;;;;EAWzB,CAAA;AACF,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAA;AAE3D,eAAO,MAAM,kBAAkB;;;;;;;;;;;iBAO7B,CAAA;AACF,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAA;AAEnE,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAUzB,CAAA;AACF,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAA;AAE3D,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,cAAc,EAAE,kBAAkB,CAiFxE,CAAA;AAED,wBAAgB,eAAe,CAAC,QAAQ,CAAC,EAAE,cAAc,GAAG,kBAAkB,CAiB7E"}
@@ -0,0 +1,130 @@
1
+ import { z } from 'zod';
2
+ export const MaterialPreset = z.enum([
3
+ 'white',
4
+ 'brick',
5
+ 'concrete',
6
+ 'wood',
7
+ 'glass',
8
+ 'metal',
9
+ 'plaster',
10
+ 'tile',
11
+ 'marble',
12
+ 'custom',
13
+ ]);
14
+ export const MaterialProperties = z.object({
15
+ color: z.string().default('#ffffff'),
16
+ roughness: z.number().min(0).max(1).default(0.5),
17
+ metalness: z.number().min(0).max(1).default(0),
18
+ opacity: z.number().min(0).max(1).default(1),
19
+ transparent: z.boolean().default(false),
20
+ side: z.enum(['front', 'back', 'double']).default('front'),
21
+ });
22
+ export const MaterialSchema = z.object({
23
+ preset: MaterialPreset.optional(),
24
+ properties: MaterialProperties.optional(),
25
+ texture: z
26
+ .object({
27
+ url: z.string(),
28
+ repeat: z.tuple([z.number(), z.number()]).optional(),
29
+ scale: z.number().optional(),
30
+ })
31
+ .optional(),
32
+ });
33
+ export const DEFAULT_MATERIALS = {
34
+ white: {
35
+ color: '#ffffff',
36
+ roughness: 0.9,
37
+ metalness: 0,
38
+ opacity: 1,
39
+ transparent: false,
40
+ side: 'front',
41
+ },
42
+ brick: {
43
+ color: '#8b4513',
44
+ roughness: 0.85,
45
+ metalness: 0,
46
+ opacity: 1,
47
+ transparent: false,
48
+ side: 'front',
49
+ },
50
+ concrete: {
51
+ color: '#808080',
52
+ roughness: 0.8,
53
+ metalness: 0,
54
+ opacity: 1,
55
+ transparent: false,
56
+ side: 'front',
57
+ },
58
+ wood: {
59
+ color: '#deb887',
60
+ roughness: 0.7,
61
+ metalness: 0,
62
+ opacity: 1,
63
+ transparent: false,
64
+ side: 'front',
65
+ },
66
+ glass: {
67
+ color: '#87ceeb',
68
+ roughness: 0.1,
69
+ metalness: 0.1,
70
+ opacity: 0.3,
71
+ transparent: true,
72
+ side: 'double',
73
+ },
74
+ metal: {
75
+ color: '#c0c0c0',
76
+ roughness: 0.3,
77
+ metalness: 0.9,
78
+ opacity: 1,
79
+ transparent: false,
80
+ side: 'front',
81
+ },
82
+ plaster: {
83
+ color: '#f5f5dc',
84
+ roughness: 0.95,
85
+ metalness: 0,
86
+ opacity: 1,
87
+ transparent: false,
88
+ side: 'front',
89
+ },
90
+ tile: {
91
+ color: '#d3d3d3',
92
+ roughness: 0.4,
93
+ metalness: 0.1,
94
+ opacity: 1,
95
+ transparent: false,
96
+ side: 'front',
97
+ },
98
+ marble: {
99
+ color: '#fafafa',
100
+ roughness: 0.2,
101
+ metalness: 0.1,
102
+ opacity: 1,
103
+ transparent: false,
104
+ side: 'front',
105
+ },
106
+ custom: {
107
+ color: '#ffffff',
108
+ roughness: 0.5,
109
+ metalness: 0,
110
+ opacity: 1,
111
+ transparent: false,
112
+ side: 'front',
113
+ },
114
+ };
115
+ export function resolveMaterial(material) {
116
+ if (!material) {
117
+ return DEFAULT_MATERIALS.white;
118
+ }
119
+ if (material.preset && material.preset !== 'custom') {
120
+ const presetProps = DEFAULT_MATERIALS[material.preset];
121
+ return {
122
+ ...presetProps,
123
+ ...material.properties,
124
+ };
125
+ }
126
+ return {
127
+ ...DEFAULT_MATERIALS.custom,
128
+ ...material.properties,
129
+ };
130
+ }
@@ -18,6 +18,37 @@ export declare const CeilingNode: z.ZodObject<{
18
18
  id: z.ZodDefault<z.ZodTemplateLiteral<`ceiling_${string}`>>;
19
19
  type: z.ZodDefault<z.ZodLiteral<"ceiling">>;
20
20
  children: z.ZodDefault<z.ZodArray<z.ZodDefault<z.ZodTemplateLiteral<`item_${string}`>>>>;
21
+ material: z.ZodOptional<z.ZodObject<{
22
+ preset: z.ZodOptional<z.ZodEnum<{
23
+ custom: "custom";
24
+ white: "white";
25
+ brick: "brick";
26
+ concrete: "concrete";
27
+ wood: "wood";
28
+ glass: "glass";
29
+ metal: "metal";
30
+ plaster: "plaster";
31
+ tile: "tile";
32
+ marble: "marble";
33
+ }>>;
34
+ properties: z.ZodOptional<z.ZodObject<{
35
+ color: z.ZodDefault<z.ZodString>;
36
+ roughness: z.ZodDefault<z.ZodNumber>;
37
+ metalness: z.ZodDefault<z.ZodNumber>;
38
+ opacity: z.ZodDefault<z.ZodNumber>;
39
+ transparent: z.ZodDefault<z.ZodBoolean>;
40
+ side: z.ZodDefault<z.ZodEnum<{
41
+ front: "front";
42
+ back: "back";
43
+ double: "double";
44
+ }>>;
45
+ }, z.core.$strip>>;
46
+ texture: z.ZodOptional<z.ZodObject<{
47
+ url: z.ZodString;
48
+ repeat: z.ZodOptional<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>>;
49
+ scale: z.ZodOptional<z.ZodNumber>;
50
+ }, z.core.$strip>>;
51
+ }, z.core.$strip>>;
21
52
  polygon: z.ZodArray<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>>;
22
53
  holes: z.ZodDefault<z.ZodArray<z.ZodArray<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>>>>;
23
54
  height: z.ZodDefault<z.ZodNumber>;
@@ -1 +1 @@
1
- {"version":3,"file":"ceiling.d.ts","sourceRoot":"","sources":["../../../src/schema/nodes/ceiling.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAIvB,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;iBAevB,CAAA;AAED,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAA"}
1
+ {"version":3,"file":"ceiling.d.ts","sourceRoot":"","sources":["../../../src/schema/nodes/ceiling.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAKvB,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAcvB,CAAA;AAED,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAA"}
@@ -1,13 +1,13 @@
1
1
  import dedent from 'dedent';
2
2
  import { z } from 'zod';
3
3
  import { BaseNode, nodeType, objectId } from '../base';
4
+ import { MaterialSchema } from '../material';
4
5
  import { ItemNode } from './item';
5
6
  export const CeilingNode = BaseNode.extend({
6
7
  id: objectId('ceiling'),
7
8
  type: nodeType('ceiling'),
8
9
  children: z.array(ItemNode.shape.id).default([]),
9
- // Specific props
10
- // Polygon boundary - array of [x, z] coordinates defining the ceiling
10
+ material: MaterialSchema.optional(),
11
11
  polygon: z.array(z.tuple([z.number(), z.number()])),
12
12
  holes: z.array(z.array(z.tuple([z.number(), z.number()]))).default([]),
13
13
  height: z.number().default(2.5), // Height in meters
@@ -1,8 +1,8 @@
1
1
  import { z } from 'zod';
2
2
  export declare const DoorSegment: z.ZodObject<{
3
3
  type: z.ZodEnum<{
4
- panel: "panel";
5
4
  glass: "glass";
5
+ panel: "panel";
6
6
  empty: "empty";
7
7
  }>;
8
8
  heightRatio: z.ZodNumber;
@@ -30,6 +30,37 @@ export declare const DoorNode: z.ZodObject<{
30
30
  metadata: z.ZodDefault<z.ZodOptional<z.ZodJSONSchema>>;
31
31
  id: z.ZodDefault<z.ZodTemplateLiteral<`door_${string}`>>;
32
32
  type: z.ZodDefault<z.ZodLiteral<"door">>;
33
+ material: z.ZodOptional<z.ZodObject<{
34
+ preset: z.ZodOptional<z.ZodEnum<{
35
+ custom: "custom";
36
+ white: "white";
37
+ brick: "brick";
38
+ concrete: "concrete";
39
+ wood: "wood";
40
+ glass: "glass";
41
+ metal: "metal";
42
+ plaster: "plaster";
43
+ tile: "tile";
44
+ marble: "marble";
45
+ }>>;
46
+ properties: z.ZodOptional<z.ZodObject<{
47
+ color: z.ZodDefault<z.ZodString>;
48
+ roughness: z.ZodDefault<z.ZodNumber>;
49
+ metalness: z.ZodDefault<z.ZodNumber>;
50
+ opacity: z.ZodDefault<z.ZodNumber>;
51
+ transparent: z.ZodDefault<z.ZodBoolean>;
52
+ side: z.ZodDefault<z.ZodEnum<{
53
+ front: "front";
54
+ back: "back";
55
+ double: "double";
56
+ }>>;
57
+ }, z.core.$strip>>;
58
+ texture: z.ZodOptional<z.ZodObject<{
59
+ url: z.ZodString;
60
+ repeat: z.ZodOptional<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>>;
61
+ scale: z.ZodOptional<z.ZodNumber>;
62
+ }, z.core.$strip>>;
63
+ }, z.core.$strip>>;
33
64
  position: z.ZodDefault<z.ZodTuple<[z.ZodNumber, z.ZodNumber, z.ZodNumber], null>>;
34
65
  rotation: z.ZodDefault<z.ZodTuple<[z.ZodNumber, z.ZodNumber, z.ZodNumber], null>>;
35
66
  side: z.ZodOptional<z.ZodEnum<{
@@ -53,8 +84,8 @@ export declare const DoorNode: z.ZodObject<{
53
84
  }>>;
54
85
  segments: z.ZodDefault<z.ZodArray<z.ZodObject<{
55
86
  type: z.ZodEnum<{
56
- panel: "panel";
57
87
  glass: "glass";
88
+ panel: "panel";
58
89
  empty: "empty";
59
90
  }>;
60
91
  heightRatio: z.ZodNumber;
@@ -1 +1 @@
1
- {"version":3,"file":"door.d.ts","sourceRoot":"","sources":["../../../src/schema/nodes/door.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAGvB,eAAO,MAAM,WAAW;;;;;;;;;;;iBAWtB,CAAA;AAEF,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAA;AAErD,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA6DnB,CAAA;AAEF,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,QAAQ,CAAC,CAAA"}
1
+ {"version":3,"file":"door.d.ts","sourceRoot":"","sources":["../../../src/schema/nodes/door.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAIvB,eAAO,MAAM,WAAW;;;;;;;;;;;iBAWtB,CAAA;AAEF,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAA;AAErD,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA8DnB,CAAA;AAEF,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,QAAQ,CAAC,CAAA"}
@@ -1,6 +1,7 @@
1
1
  import dedent from 'dedent';
2
2
  import { z } from 'zod';
3
3
  import { BaseNode, nodeType, objectId } from '../base';
4
+ import { MaterialSchema } from '../material';
4
5
  export const DoorSegment = z.object({
5
6
  type: z.enum(['panel', 'glass', 'empty']),
6
7
  heightRatio: z.number(),
@@ -14,6 +15,7 @@ export const DoorSegment = z.object({
14
15
  export const DoorNode = BaseNode.extend({
15
16
  id: objectId('door'),
16
17
  type: nodeType('door'),
18
+ material: MaterialSchema.optional(),
17
19
  position: z.tuple([z.number(), z.number(), z.number()]).default([0, 0, 0]),
18
20
  rotation: z.tuple([z.number(), z.number(), z.number()]).default([0, 0, 0]),
19
21
  side: z.enum(['front', 'back']).optional(),
@@ -27,6 +27,37 @@ export declare const RoofSegmentNode: z.ZodObject<{
27
27
  metadata: z.ZodDefault<z.ZodOptional<z.ZodJSONSchema>>;
28
28
  id: z.ZodDefault<z.ZodTemplateLiteral<`rseg_${string}`>>;
29
29
  type: z.ZodDefault<z.ZodLiteral<"roof-segment">>;
30
+ material: z.ZodOptional<z.ZodObject<{
31
+ preset: z.ZodOptional<z.ZodEnum<{
32
+ custom: "custom";
33
+ white: "white";
34
+ brick: "brick";
35
+ concrete: "concrete";
36
+ wood: "wood";
37
+ glass: "glass";
38
+ metal: "metal";
39
+ plaster: "plaster";
40
+ tile: "tile";
41
+ marble: "marble";
42
+ }>>;
43
+ properties: z.ZodOptional<z.ZodObject<{
44
+ color: z.ZodDefault<z.ZodString>;
45
+ roughness: z.ZodDefault<z.ZodNumber>;
46
+ metalness: z.ZodDefault<z.ZodNumber>;
47
+ opacity: z.ZodDefault<z.ZodNumber>;
48
+ transparent: z.ZodDefault<z.ZodBoolean>;
49
+ side: z.ZodDefault<z.ZodEnum<{
50
+ front: "front";
51
+ back: "back";
52
+ double: "double";
53
+ }>>;
54
+ }, z.core.$strip>>;
55
+ texture: z.ZodOptional<z.ZodObject<{
56
+ url: z.ZodString;
57
+ repeat: z.ZodOptional<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>>;
58
+ scale: z.ZodOptional<z.ZodNumber>;
59
+ }, z.core.$strip>>;
60
+ }, z.core.$strip>>;
30
61
  position: z.ZodDefault<z.ZodTuple<[z.ZodNumber, z.ZodNumber, z.ZodNumber], null>>;
31
62
  rotation: z.ZodDefault<z.ZodNumber>;
32
63
  roofType: z.ZodDefault<z.ZodEnum<{
@@ -1 +1 @@
1
- {"version":3,"file":"roof-segment.d.ts","sourceRoot":"","sources":["../../../src/schema/nodes/roof-segment.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAGvB,eAAO,MAAM,QAAQ;;;;;;;;EAA0E,CAAA;AAE/F,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,QAAQ,CAAC,CAAA;AAE/C,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAiC3B,CAAA;AAED,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAA"}
1
+ {"version":3,"file":"roof-segment.d.ts","sourceRoot":"","sources":["../../../src/schema/nodes/roof-segment.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAIvB,eAAO,MAAM,QAAQ;;;;;;;;EAA0E,CAAA;AAE/F,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,QAAQ,CAAC,CAAA;AAE/C,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAiC3B,CAAA;AAED,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAA"}
@@ -1,11 +1,12 @@
1
1
  import dedent from 'dedent';
2
2
  import { z } from 'zod';
3
3
  import { BaseNode, nodeType, objectId } from '../base';
4
+ import { MaterialSchema } from '../material';
4
5
  export const RoofType = z.enum(['hip', 'gable', 'shed', 'gambrel', 'dutch', 'mansard', 'flat']);
5
6
  export const RoofSegmentNode = BaseNode.extend({
6
7
  id: objectId('rseg'),
7
8
  type: nodeType('roof-segment'),
8
- // Position relative to parent roof group
9
+ material: MaterialSchema.optional(),
9
10
  position: z.tuple([z.number(), z.number(), z.number()]).default([0, 0, 0]),
10
11
  // Rotation around Y axis in radians
11
12
  rotation: z.number().default(0),
@@ -17,6 +17,37 @@ export declare const RoofNode: z.ZodObject<{
17
17
  metadata: z.ZodDefault<z.ZodOptional<z.ZodJSONSchema>>;
18
18
  id: z.ZodDefault<z.ZodTemplateLiteral<`roof_${string}`>>;
19
19
  type: z.ZodDefault<z.ZodLiteral<"roof">>;
20
+ material: z.ZodOptional<z.ZodObject<{
21
+ preset: z.ZodOptional<z.ZodEnum<{
22
+ custom: "custom";
23
+ white: "white";
24
+ brick: "brick";
25
+ concrete: "concrete";
26
+ wood: "wood";
27
+ glass: "glass";
28
+ metal: "metal";
29
+ plaster: "plaster";
30
+ tile: "tile";
31
+ marble: "marble";
32
+ }>>;
33
+ properties: z.ZodOptional<z.ZodObject<{
34
+ color: z.ZodDefault<z.ZodString>;
35
+ roughness: z.ZodDefault<z.ZodNumber>;
36
+ metalness: z.ZodDefault<z.ZodNumber>;
37
+ opacity: z.ZodDefault<z.ZodNumber>;
38
+ transparent: z.ZodDefault<z.ZodBoolean>;
39
+ side: z.ZodDefault<z.ZodEnum<{
40
+ front: "front";
41
+ back: "back";
42
+ double: "double";
43
+ }>>;
44
+ }, z.core.$strip>>;
45
+ texture: z.ZodOptional<z.ZodObject<{
46
+ url: z.ZodString;
47
+ repeat: z.ZodOptional<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>>;
48
+ scale: z.ZodOptional<z.ZodNumber>;
49
+ }, z.core.$strip>>;
50
+ }, z.core.$strip>>;
20
51
  position: z.ZodDefault<z.ZodTuple<[z.ZodNumber, z.ZodNumber, z.ZodNumber], null>>;
21
52
  rotation: z.ZodDefault<z.ZodNumber>;
22
53
  children: z.ZodDefault<z.ZodArray<z.ZodDefault<z.ZodTemplateLiteral<`rseg_${string}`>>>>;
@@ -1 +1 @@
1
- {"version":3,"file":"roof.d.ts","sourceRoot":"","sources":["../../../src/schema/nodes/roof.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAIvB,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;iBAkBpB,CAAA;AAED,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,QAAQ,CAAC,CAAA"}
1
+ {"version":3,"file":"roof.d.ts","sourceRoot":"","sources":["../../../src/schema/nodes/roof.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAKvB,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAkBpB,CAAA;AAED,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,QAAQ,CAAC,CAAA"}
@@ -1,11 +1,12 @@
1
1
  import dedent from 'dedent';
2
2
  import { z } from 'zod';
3
3
  import { BaseNode, nodeType, objectId } from '../base';
4
+ import { MaterialSchema } from '../material';
4
5
  import { RoofSegmentNode } from './roof-segment';
5
6
  export const RoofNode = BaseNode.extend({
6
7
  id: objectId('roof'),
7
8
  type: nodeType('roof'),
8
- // Position of the roof group center
9
+ material: MaterialSchema.optional(),
9
10
  position: z.tuple([z.number(), z.number(), z.number()]).default([0, 0, 0]),
10
11
  // Rotation around Y axis in radians
11
12
  rotation: z.number().default(0),
@@ -17,6 +17,37 @@ export declare const SlabNode: z.ZodObject<{
17
17
  metadata: z.ZodDefault<z.ZodOptional<z.ZodJSONSchema>>;
18
18
  id: z.ZodDefault<z.ZodTemplateLiteral<`slab_${string}`>>;
19
19
  type: z.ZodDefault<z.ZodLiteral<"slab">>;
20
+ material: z.ZodOptional<z.ZodObject<{
21
+ preset: z.ZodOptional<z.ZodEnum<{
22
+ custom: "custom";
23
+ white: "white";
24
+ brick: "brick";
25
+ concrete: "concrete";
26
+ wood: "wood";
27
+ glass: "glass";
28
+ metal: "metal";
29
+ plaster: "plaster";
30
+ tile: "tile";
31
+ marble: "marble";
32
+ }>>;
33
+ properties: z.ZodOptional<z.ZodObject<{
34
+ color: z.ZodDefault<z.ZodString>;
35
+ roughness: z.ZodDefault<z.ZodNumber>;
36
+ metalness: z.ZodDefault<z.ZodNumber>;
37
+ opacity: z.ZodDefault<z.ZodNumber>;
38
+ transparent: z.ZodDefault<z.ZodBoolean>;
39
+ side: z.ZodDefault<z.ZodEnum<{
40
+ front: "front";
41
+ back: "back";
42
+ double: "double";
43
+ }>>;
44
+ }, z.core.$strip>>;
45
+ texture: z.ZodOptional<z.ZodObject<{
46
+ url: z.ZodString;
47
+ repeat: z.ZodOptional<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>>;
48
+ scale: z.ZodOptional<z.ZodNumber>;
49
+ }, z.core.$strip>>;
50
+ }, z.core.$strip>>;
20
51
  polygon: z.ZodArray<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>>;
21
52
  holes: z.ZodDefault<z.ZodArray<z.ZodArray<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>>>>;
22
53
  elevation: z.ZodDefault<z.ZodNumber>;
@@ -1 +1 @@
1
- {"version":3,"file":"slab.d.ts","sourceRoot":"","sources":["../../../src/schema/nodes/slab.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAGvB,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;iBAcpB,CAAA;AAED,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,QAAQ,CAAC,CAAA"}
1
+ {"version":3,"file":"slab.d.ts","sourceRoot":"","sources":["../../../src/schema/nodes/slab.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAIvB,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAapB,CAAA;AAED,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,QAAQ,CAAC,CAAA"}
@@ -1,11 +1,11 @@
1
1
  import dedent from 'dedent';
2
2
  import { z } from 'zod';
3
3
  import { BaseNode, nodeType, objectId } from '../base';
4
+ import { MaterialSchema } from '../material';
4
5
  export const SlabNode = BaseNode.extend({
5
6
  id: objectId('slab'),
6
7
  type: nodeType('slab'),
7
- // Specific props
8
- // Polygon boundary - array of [x, z] coordinates defining the slab
8
+ material: MaterialSchema.optional(),
9
9
  polygon: z.array(z.tuple([z.number(), z.number()])),
10
10
  holes: z.array(z.array(z.tuple([z.number(), z.number()]))).default([]),
11
11
  elevation: z.number().default(0.05), // Elevation in meters
@@ -18,6 +18,37 @@ export declare const WallNode: z.ZodObject<{
18
18
  id: z.ZodDefault<z.ZodTemplateLiteral<`wall_${string}`>>;
19
19
  type: z.ZodDefault<z.ZodLiteral<"wall">>;
20
20
  children: z.ZodDefault<z.ZodArray<z.ZodDefault<z.ZodTemplateLiteral<`item_${string}`>>>>;
21
+ material: z.ZodOptional<z.ZodObject<{
22
+ preset: z.ZodOptional<z.ZodEnum<{
23
+ custom: "custom";
24
+ white: "white";
25
+ brick: "brick";
26
+ concrete: "concrete";
27
+ wood: "wood";
28
+ glass: "glass";
29
+ metal: "metal";
30
+ plaster: "plaster";
31
+ tile: "tile";
32
+ marble: "marble";
33
+ }>>;
34
+ properties: z.ZodOptional<z.ZodObject<{
35
+ color: z.ZodDefault<z.ZodString>;
36
+ roughness: z.ZodDefault<z.ZodNumber>;
37
+ metalness: z.ZodDefault<z.ZodNumber>;
38
+ opacity: z.ZodDefault<z.ZodNumber>;
39
+ transparent: z.ZodDefault<z.ZodBoolean>;
40
+ side: z.ZodDefault<z.ZodEnum<{
41
+ front: "front";
42
+ back: "back";
43
+ double: "double";
44
+ }>>;
45
+ }, z.core.$strip>>;
46
+ texture: z.ZodOptional<z.ZodObject<{
47
+ url: z.ZodString;
48
+ repeat: z.ZodOptional<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>>;
49
+ scale: z.ZodOptional<z.ZodNumber>;
50
+ }, z.core.$strip>>;
51
+ }, z.core.$strip>>;
21
52
  thickness: z.ZodOptional<z.ZodNumber>;
22
53
  height: z.ZodOptional<z.ZodNumber>;
23
54
  start: z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>;
@@ -1 +1 @@
1
- {"version":3,"file":"wall.d.ts","sourceRoot":"","sources":["../../../src/schema/nodes/wall.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAOvB,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAwBpB,CAAA;AACD,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,QAAQ,CAAC,CAAA"}
1
+ {"version":3,"file":"wall.d.ts","sourceRoot":"","sources":["../../../src/schema/nodes/wall.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAQvB,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAwBpB,CAAA;AACD,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,QAAQ,CAAC,CAAA"}
@@ -1,6 +1,7 @@
1
1
  import dedent from 'dedent';
2
2
  import { z } from 'zod';
3
3
  import { BaseNode, nodeType, objectId } from '../base';
4
+ import { MaterialSchema } from '../material';
4
5
  import { ItemNode } from './item';
5
6
  // import { DoorNode } from "./door";
6
7
  // import { ItemNode } from "./item";
@@ -9,7 +10,7 @@ export const WallNode = BaseNode.extend({
9
10
  id: objectId('wall'),
10
11
  type: nodeType('wall'),
11
12
  children: z.array(ItemNode.shape.id).default([]),
12
- // Specific props
13
+ material: MaterialSchema.optional(),
13
14
  thickness: z.number().optional(),
14
15
  height: z.number().optional(),
15
16
  // e.g., start/end points for path
@@ -17,6 +17,37 @@ export declare const WindowNode: z.ZodObject<{
17
17
  metadata: z.ZodDefault<z.ZodOptional<z.ZodJSONSchema>>;
18
18
  id: z.ZodDefault<z.ZodTemplateLiteral<`window_${string}`>>;
19
19
  type: z.ZodDefault<z.ZodLiteral<"window">>;
20
+ material: z.ZodOptional<z.ZodObject<{
21
+ preset: z.ZodOptional<z.ZodEnum<{
22
+ custom: "custom";
23
+ white: "white";
24
+ brick: "brick";
25
+ concrete: "concrete";
26
+ wood: "wood";
27
+ glass: "glass";
28
+ metal: "metal";
29
+ plaster: "plaster";
30
+ tile: "tile";
31
+ marble: "marble";
32
+ }>>;
33
+ properties: z.ZodOptional<z.ZodObject<{
34
+ color: z.ZodDefault<z.ZodString>;
35
+ roughness: z.ZodDefault<z.ZodNumber>;
36
+ metalness: z.ZodDefault<z.ZodNumber>;
37
+ opacity: z.ZodDefault<z.ZodNumber>;
38
+ transparent: z.ZodDefault<z.ZodBoolean>;
39
+ side: z.ZodDefault<z.ZodEnum<{
40
+ front: "front";
41
+ back: "back";
42
+ double: "double";
43
+ }>>;
44
+ }, z.core.$strip>>;
45
+ texture: z.ZodOptional<z.ZodObject<{
46
+ url: z.ZodString;
47
+ repeat: z.ZodOptional<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>>;
48
+ scale: z.ZodOptional<z.ZodNumber>;
49
+ }, z.core.$strip>>;
50
+ }, z.core.$strip>>;
20
51
  position: z.ZodDefault<z.ZodTuple<[z.ZodNumber, z.ZodNumber, z.ZodNumber], null>>;
21
52
  rotation: z.ZodDefault<z.ZodTuple<[z.ZodNumber, z.ZodNumber, z.ZodNumber], null>>;
22
53
  side: z.ZodOptional<z.ZodEnum<{
@@ -1 +1 @@
1
- {"version":3,"file":"window.d.ts","sourceRoot":"","sources":["../../../src/schema/nodes/window.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAGvB,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAwCrB,CAAA;AAEF,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,CAAA"}
1
+ {"version":3,"file":"window.d.ts","sourceRoot":"","sources":["../../../src/schema/nodes/window.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAIvB,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAwCrB,CAAA;AAEF,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,CAAA"}
@@ -1,10 +1,11 @@
1
1
  import dedent from 'dedent';
2
2
  import { z } from 'zod';
3
3
  import { BaseNode, nodeType, objectId } from '../base';
4
+ import { MaterialSchema } from '../material';
4
5
  export const WindowNode = BaseNode.extend({
5
6
  id: objectId('window'),
6
7
  type: nodeType('window'),
7
- // Position in wall-local coordinate system (center of window)
8
+ material: MaterialSchema.optional(),
8
9
  position: z.tuple([z.number(), z.number(), z.number()]).default([0, 0, 0]),
9
10
  rotation: z.tuple([z.number(), z.number(), z.number()]).default([0, 0, 0]),
10
11
  side: z.enum(['front', 'back']).optional(),
@@ -196,6 +196,37 @@ export declare const AnyNode: z.ZodDiscriminatedUnion<[z.ZodObject<{
196
196
  id: z.ZodDefault<z.ZodTemplateLiteral<`wall_${string}`>>;
197
197
  type: z.ZodDefault<z.ZodLiteral<"wall">>;
198
198
  children: z.ZodDefault<z.ZodArray<z.ZodDefault<z.ZodTemplateLiteral<`item_${string}`>>>>;
199
+ material: z.ZodOptional<z.ZodObject<{
200
+ preset: z.ZodOptional<z.ZodEnum<{
201
+ custom: "custom";
202
+ white: "white";
203
+ brick: "brick";
204
+ concrete: "concrete";
205
+ wood: "wood";
206
+ glass: "glass";
207
+ metal: "metal";
208
+ plaster: "plaster";
209
+ tile: "tile";
210
+ marble: "marble";
211
+ }>>;
212
+ properties: z.ZodOptional<z.ZodObject<{
213
+ color: z.ZodDefault<z.ZodString>;
214
+ roughness: z.ZodDefault<z.ZodNumber>;
215
+ metalness: z.ZodDefault<z.ZodNumber>;
216
+ opacity: z.ZodDefault<z.ZodNumber>;
217
+ transparent: z.ZodDefault<z.ZodBoolean>;
218
+ side: z.ZodDefault<z.ZodEnum<{
219
+ front: "front";
220
+ back: "back";
221
+ double: "double";
222
+ }>>;
223
+ }, z.core.$strip>>;
224
+ texture: z.ZodOptional<z.ZodObject<{
225
+ url: z.ZodString;
226
+ repeat: z.ZodOptional<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>>;
227
+ scale: z.ZodOptional<z.ZodNumber>;
228
+ }, z.core.$strip>>;
229
+ }, z.core.$strip>>;
199
230
  thickness: z.ZodOptional<z.ZodNumber>;
200
231
  height: z.ZodOptional<z.ZodNumber>;
201
232
  start: z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>;
@@ -341,6 +372,37 @@ export declare const AnyNode: z.ZodDiscriminatedUnion<[z.ZodObject<{
341
372
  metadata: z.ZodDefault<z.ZodOptional<z.ZodJSONSchema>>;
342
373
  id: z.ZodDefault<z.ZodTemplateLiteral<`slab_${string}`>>;
343
374
  type: z.ZodDefault<z.ZodLiteral<"slab">>;
375
+ material: z.ZodOptional<z.ZodObject<{
376
+ preset: z.ZodOptional<z.ZodEnum<{
377
+ custom: "custom";
378
+ white: "white";
379
+ brick: "brick";
380
+ concrete: "concrete";
381
+ wood: "wood";
382
+ glass: "glass";
383
+ metal: "metal";
384
+ plaster: "plaster";
385
+ tile: "tile";
386
+ marble: "marble";
387
+ }>>;
388
+ properties: z.ZodOptional<z.ZodObject<{
389
+ color: z.ZodDefault<z.ZodString>;
390
+ roughness: z.ZodDefault<z.ZodNumber>;
391
+ metalness: z.ZodDefault<z.ZodNumber>;
392
+ opacity: z.ZodDefault<z.ZodNumber>;
393
+ transparent: z.ZodDefault<z.ZodBoolean>;
394
+ side: z.ZodDefault<z.ZodEnum<{
395
+ front: "front";
396
+ back: "back";
397
+ double: "double";
398
+ }>>;
399
+ }, z.core.$strip>>;
400
+ texture: z.ZodOptional<z.ZodObject<{
401
+ url: z.ZodString;
402
+ repeat: z.ZodOptional<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>>;
403
+ scale: z.ZodOptional<z.ZodNumber>;
404
+ }, z.core.$strip>>;
405
+ }, z.core.$strip>>;
344
406
  polygon: z.ZodArray<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>>;
345
407
  holes: z.ZodDefault<z.ZodArray<z.ZodArray<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>>>>;
346
408
  elevation: z.ZodDefault<z.ZodNumber>;
@@ -363,6 +425,37 @@ export declare const AnyNode: z.ZodDiscriminatedUnion<[z.ZodObject<{
363
425
  id: z.ZodDefault<z.ZodTemplateLiteral<`ceiling_${string}`>>;
364
426
  type: z.ZodDefault<z.ZodLiteral<"ceiling">>;
365
427
  children: z.ZodDefault<z.ZodArray<z.ZodDefault<z.ZodTemplateLiteral<`item_${string}`>>>>;
428
+ material: z.ZodOptional<z.ZodObject<{
429
+ preset: z.ZodOptional<z.ZodEnum<{
430
+ custom: "custom";
431
+ white: "white";
432
+ brick: "brick";
433
+ concrete: "concrete";
434
+ wood: "wood";
435
+ glass: "glass";
436
+ metal: "metal";
437
+ plaster: "plaster";
438
+ tile: "tile";
439
+ marble: "marble";
440
+ }>>;
441
+ properties: z.ZodOptional<z.ZodObject<{
442
+ color: z.ZodDefault<z.ZodString>;
443
+ roughness: z.ZodDefault<z.ZodNumber>;
444
+ metalness: z.ZodDefault<z.ZodNumber>;
445
+ opacity: z.ZodDefault<z.ZodNumber>;
446
+ transparent: z.ZodDefault<z.ZodBoolean>;
447
+ side: z.ZodDefault<z.ZodEnum<{
448
+ front: "front";
449
+ back: "back";
450
+ double: "double";
451
+ }>>;
452
+ }, z.core.$strip>>;
453
+ texture: z.ZodOptional<z.ZodObject<{
454
+ url: z.ZodString;
455
+ repeat: z.ZodOptional<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>>;
456
+ scale: z.ZodOptional<z.ZodNumber>;
457
+ }, z.core.$strip>>;
458
+ }, z.core.$strip>>;
366
459
  polygon: z.ZodArray<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>>;
367
460
  holes: z.ZodDefault<z.ZodArray<z.ZodArray<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>>>>;
368
461
  height: z.ZodDefault<z.ZodNumber>;
@@ -384,6 +477,37 @@ export declare const AnyNode: z.ZodDiscriminatedUnion<[z.ZodObject<{
384
477
  metadata: z.ZodDefault<z.ZodOptional<z.ZodJSONSchema>>;
385
478
  id: z.ZodDefault<z.ZodTemplateLiteral<`roof_${string}`>>;
386
479
  type: z.ZodDefault<z.ZodLiteral<"roof">>;
480
+ material: z.ZodOptional<z.ZodObject<{
481
+ preset: z.ZodOptional<z.ZodEnum<{
482
+ custom: "custom";
483
+ white: "white";
484
+ brick: "brick";
485
+ concrete: "concrete";
486
+ wood: "wood";
487
+ glass: "glass";
488
+ metal: "metal";
489
+ plaster: "plaster";
490
+ tile: "tile";
491
+ marble: "marble";
492
+ }>>;
493
+ properties: z.ZodOptional<z.ZodObject<{
494
+ color: z.ZodDefault<z.ZodString>;
495
+ roughness: z.ZodDefault<z.ZodNumber>;
496
+ metalness: z.ZodDefault<z.ZodNumber>;
497
+ opacity: z.ZodDefault<z.ZodNumber>;
498
+ transparent: z.ZodDefault<z.ZodBoolean>;
499
+ side: z.ZodDefault<z.ZodEnum<{
500
+ front: "front";
501
+ back: "back";
502
+ double: "double";
503
+ }>>;
504
+ }, z.core.$strip>>;
505
+ texture: z.ZodOptional<z.ZodObject<{
506
+ url: z.ZodString;
507
+ repeat: z.ZodOptional<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>>;
508
+ scale: z.ZodOptional<z.ZodNumber>;
509
+ }, z.core.$strip>>;
510
+ }, z.core.$strip>>;
387
511
  position: z.ZodDefault<z.ZodTuple<[z.ZodNumber, z.ZodNumber, z.ZodNumber], null>>;
388
512
  rotation: z.ZodDefault<z.ZodNumber>;
389
513
  children: z.ZodDefault<z.ZodArray<z.ZodDefault<z.ZodTemplateLiteral<`rseg_${string}`>>>>;
@@ -405,6 +529,37 @@ export declare const AnyNode: z.ZodDiscriminatedUnion<[z.ZodObject<{
405
529
  metadata: z.ZodDefault<z.ZodOptional<z.ZodJSONSchema>>;
406
530
  id: z.ZodDefault<z.ZodTemplateLiteral<`rseg_${string}`>>;
407
531
  type: z.ZodDefault<z.ZodLiteral<"roof-segment">>;
532
+ material: z.ZodOptional<z.ZodObject<{
533
+ preset: z.ZodOptional<z.ZodEnum<{
534
+ custom: "custom";
535
+ white: "white";
536
+ brick: "brick";
537
+ concrete: "concrete";
538
+ wood: "wood";
539
+ glass: "glass";
540
+ metal: "metal";
541
+ plaster: "plaster";
542
+ tile: "tile";
543
+ marble: "marble";
544
+ }>>;
545
+ properties: z.ZodOptional<z.ZodObject<{
546
+ color: z.ZodDefault<z.ZodString>;
547
+ roughness: z.ZodDefault<z.ZodNumber>;
548
+ metalness: z.ZodDefault<z.ZodNumber>;
549
+ opacity: z.ZodDefault<z.ZodNumber>;
550
+ transparent: z.ZodDefault<z.ZodBoolean>;
551
+ side: z.ZodDefault<z.ZodEnum<{
552
+ front: "front";
553
+ back: "back";
554
+ double: "double";
555
+ }>>;
556
+ }, z.core.$strip>>;
557
+ texture: z.ZodOptional<z.ZodObject<{
558
+ url: z.ZodString;
559
+ repeat: z.ZodOptional<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>>;
560
+ scale: z.ZodOptional<z.ZodNumber>;
561
+ }, z.core.$strip>>;
562
+ }, z.core.$strip>>;
408
563
  position: z.ZodDefault<z.ZodTuple<[z.ZodNumber, z.ZodNumber, z.ZodNumber], null>>;
409
564
  rotation: z.ZodDefault<z.ZodNumber>;
410
565
  roofType: z.ZodDefault<z.ZodEnum<{
@@ -488,6 +643,37 @@ export declare const AnyNode: z.ZodDiscriminatedUnion<[z.ZodObject<{
488
643
  metadata: z.ZodDefault<z.ZodOptional<z.ZodJSONSchema>>;
489
644
  id: z.ZodDefault<z.ZodTemplateLiteral<`window_${string}`>>;
490
645
  type: z.ZodDefault<z.ZodLiteral<"window">>;
646
+ material: z.ZodOptional<z.ZodObject<{
647
+ preset: z.ZodOptional<z.ZodEnum<{
648
+ custom: "custom";
649
+ white: "white";
650
+ brick: "brick";
651
+ concrete: "concrete";
652
+ wood: "wood";
653
+ glass: "glass";
654
+ metal: "metal";
655
+ plaster: "plaster";
656
+ tile: "tile";
657
+ marble: "marble";
658
+ }>>;
659
+ properties: z.ZodOptional<z.ZodObject<{
660
+ color: z.ZodDefault<z.ZodString>;
661
+ roughness: z.ZodDefault<z.ZodNumber>;
662
+ metalness: z.ZodDefault<z.ZodNumber>;
663
+ opacity: z.ZodDefault<z.ZodNumber>;
664
+ transparent: z.ZodDefault<z.ZodBoolean>;
665
+ side: z.ZodDefault<z.ZodEnum<{
666
+ front: "front";
667
+ back: "back";
668
+ double: "double";
669
+ }>>;
670
+ }, z.core.$strip>>;
671
+ texture: z.ZodOptional<z.ZodObject<{
672
+ url: z.ZodString;
673
+ repeat: z.ZodOptional<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>>;
674
+ scale: z.ZodOptional<z.ZodNumber>;
675
+ }, z.core.$strip>>;
676
+ }, z.core.$strip>>;
491
677
  position: z.ZodDefault<z.ZodTuple<[z.ZodNumber, z.ZodNumber, z.ZodNumber], null>>;
492
678
  rotation: z.ZodDefault<z.ZodTuple<[z.ZodNumber, z.ZodNumber, z.ZodNumber], null>>;
493
679
  side: z.ZodOptional<z.ZodEnum<{
@@ -524,6 +710,37 @@ export declare const AnyNode: z.ZodDiscriminatedUnion<[z.ZodObject<{
524
710
  metadata: z.ZodDefault<z.ZodOptional<z.ZodJSONSchema>>;
525
711
  id: z.ZodDefault<z.ZodTemplateLiteral<`door_${string}`>>;
526
712
  type: z.ZodDefault<z.ZodLiteral<"door">>;
713
+ material: z.ZodOptional<z.ZodObject<{
714
+ preset: z.ZodOptional<z.ZodEnum<{
715
+ custom: "custom";
716
+ white: "white";
717
+ brick: "brick";
718
+ concrete: "concrete";
719
+ wood: "wood";
720
+ glass: "glass";
721
+ metal: "metal";
722
+ plaster: "plaster";
723
+ tile: "tile";
724
+ marble: "marble";
725
+ }>>;
726
+ properties: z.ZodOptional<z.ZodObject<{
727
+ color: z.ZodDefault<z.ZodString>;
728
+ roughness: z.ZodDefault<z.ZodNumber>;
729
+ metalness: z.ZodDefault<z.ZodNumber>;
730
+ opacity: z.ZodDefault<z.ZodNumber>;
731
+ transparent: z.ZodDefault<z.ZodBoolean>;
732
+ side: z.ZodDefault<z.ZodEnum<{
733
+ front: "front";
734
+ back: "back";
735
+ double: "double";
736
+ }>>;
737
+ }, z.core.$strip>>;
738
+ texture: z.ZodOptional<z.ZodObject<{
739
+ url: z.ZodString;
740
+ repeat: z.ZodOptional<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>>;
741
+ scale: z.ZodOptional<z.ZodNumber>;
742
+ }, z.core.$strip>>;
743
+ }, z.core.$strip>>;
527
744
  position: z.ZodDefault<z.ZodTuple<[z.ZodNumber, z.ZodNumber, z.ZodNumber], null>>;
528
745
  rotation: z.ZodDefault<z.ZodTuple<[z.ZodNumber, z.ZodNumber, z.ZodNumber], null>>;
529
746
  side: z.ZodOptional<z.ZodEnum<{
@@ -547,8 +764,8 @@ export declare const AnyNode: z.ZodDiscriminatedUnion<[z.ZodObject<{
547
764
  }>>;
548
765
  segments: z.ZodDefault<z.ZodArray<z.ZodObject<{
549
766
  type: z.ZodEnum<{
550
- panel: "panel";
551
767
  glass: "glass";
768
+ panel: "panel";
552
769
  empty: "empty";
553
770
  }>;
554
771
  heightRatio: z.ZodNumber;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/schema/types.ts"],"names":[],"mappings":"AAAA,OAAO,CAAC,MAAM,KAAK,CAAA;AAgBnB,eAAO,MAAM,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2BAelB,CAAA;AAEF,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,OAAO,CAAC,CAAA;AAC7C,MAAM,MAAM,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;AACzC,MAAM,MAAM,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/schema/types.ts"],"names":[],"mappings":"AAAA,OAAO,CAAC,MAAM,KAAK,CAAA;AAgBnB,eAAO,MAAM,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2BAelB,CAAA;AAEF,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,OAAO,CAAC,CAAA;AAC7C,MAAM,MAAM,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;AACzC,MAAM,MAAM,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"node-actions.d.ts","sourceRoot":"","sources":["../../../src/store/actions/node-actions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAEtD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAQ9C,eAAO,MAAM,iBAAiB,GAC5B,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,OAAO,CAAC,UAAU,CAAC,KAAK,IAAI,EAC7D,KAAK,MAAM,UAAU,EACrB,KAAK;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,SAAS,CAAA;CAAE,EAAE,SA2C/C,CAAA;AAED,eAAO,MAAM,iBAAiB,GAC5B,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,OAAO,CAAC,UAAU,CAAC,KAAK,IAAI,EAC7D,KAAK,MAAM,UAAU,EACrB,SAAS;IAAE,EAAE,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,CAAA;CAAE,EAAE,SAgErD,CAAA;AAED,eAAO,MAAM,iBAAiB,GAC5B,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,OAAO,CAAC,UAAU,CAAC,KAAK,IAAI,EAC7D,KAAK,MAAM,UAAU,EACrB,KAAK,SAAS,EAAE,SA4EjB,CAAA"}
1
+ {"version":3,"file":"node-actions.d.ts","sourceRoot":"","sources":["../../../src/store/actions/node-actions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAEtD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAQ9C,eAAO,MAAM,iBAAiB,GAC5B,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,OAAO,CAAC,UAAU,CAAC,KAAK,IAAI,EAC7D,KAAK,MAAM,UAAU,EACrB,KAAK;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,SAAS,CAAA;CAAE,EAAE,SA2C/C,CAAA;AAED,eAAO,MAAM,iBAAiB,GAC5B,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,OAAO,CAAC,UAAU,CAAC,KAAK,IAAI,EAC7D,KAAK,MAAM,UAAU,EACrB,SAAS;IAAE,EAAE,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,CAAA;CAAE,EAAE,SAsErD,CAAA;AAED,eAAO,MAAM,iBAAiB,GAC5B,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,OAAO,CAAC,UAAU,CAAC,KAAK,IAAI,EAC7D,KAAK,MAAM,UAAU,EACrB,KAAK,SAAS,EAAE,SA4EjB,CAAA"}
@@ -78,10 +78,16 @@ export const updateNodesAction = (set, get, updates) => {
78
78
  return { nodes: nextNodes };
79
79
  });
80
80
  // Collect all IDs that need to be marked dirty
81
- updates.forEach((u) => idsToMarkDirty.add(u.id));
82
- parentsToUpdate.forEach((pId) => idsToMarkDirty.add(pId));
81
+ for (const u of updates) {
82
+ idsToMarkDirty.add(u.id);
83
+ }
84
+ for (const pId of parentsToUpdate) {
85
+ idsToMarkDirty.add(pId);
86
+ }
83
87
  // Add to pending updates set
84
- idsToMarkDirty.forEach((id) => pendingUpdates.add(id));
88
+ for (const id of idsToMarkDirty) {
89
+ pendingUpdates.add(id);
90
+ }
85
91
  // Cancel any pending RAF and schedule a new one
86
92
  if (pendingRafId !== null) {
87
93
  cancelAnimationFrame(pendingRafId);
@@ -1 +1 @@
1
- {"version":3,"file":"use-scene.d.ts","sourceRoot":"","sources":["../../src/store/use-scene.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAA;AAE1C,OAAO,EAAU,KAAK,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,SAAS,CAAA;AAEnE,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAA;AAIrE,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AA8CzD,MAAM,MAAM,UAAU,GAAG;IAEvB,KAAK,EAAE,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,CAAA;IAGjC,WAAW,EAAE,SAAS,EAAE,CAAA;IAGxB,UAAU,EAAE,GAAG,CAAC,SAAS,CAAC,CAAA;IAG1B,WAAW,EAAE,MAAM,CAAC,YAAY,EAAE,UAAU,CAAC,CAAA;IAG7C,SAAS,EAAE,MAAM,IAAI,CAAA;IACrB,UAAU,EAAE,MAAM,IAAI,CAAA;IACtB,WAAW,EAAE,MAAM,IAAI,CAAA;IACvB,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,EAAE,WAAW,EAAE,SAAS,EAAE,KAAK,IAAI,CAAA;IAE/E,SAAS,EAAE,CAAC,EAAE,EAAE,SAAS,KAAK,IAAI,CAAA;IAClC,UAAU,EAAE,CAAC,EAAE,EAAE,SAAS,KAAK,IAAI,CAAA;IAEnC,UAAU,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,SAAS,KAAK,IAAI,CAAA;IACzD,WAAW,EAAE,CAAC,GAAG,EAAE;QAAE,IAAI,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,EAAE,SAAS,CAAA;KAAE,EAAE,KAAK,IAAI,CAAA;IAErE,UAAU,EAAE,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,KAAK,IAAI,CAAA;IAC3D,WAAW,EAAE,CAAC,OAAO,EAAE;QAAE,EAAE,EAAE,SAAS,CAAC;QAAC,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,CAAA;KAAE,EAAE,KAAK,IAAI,CAAA;IAE3E,UAAU,EAAE,CAAC,EAAE,EAAE,SAAS,KAAK,IAAI,CAAA;IACnC,WAAW,EAAE,CAAC,GAAG,EAAE,SAAS,EAAE,KAAK,IAAI,CAAA;IAGvC,gBAAgB,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS,EAAE,KAAK,YAAY,CAAA;IACvE,gBAAgB,EAAE,CAAC,EAAE,EAAE,YAAY,KAAK,IAAI,CAAA;IAC5C,gBAAgB,EAAE,CAAC,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC,KAAK,IAAI,CAAA;IACnF,eAAe,EAAE,CAAC,EAAE,EAAE,YAAY,EAAE,MAAM,EAAE,SAAS,KAAK,IAAI,CAAA;IAC9D,oBAAoB,EAAE,CAAC,EAAE,EAAE,YAAY,EAAE,MAAM,EAAE,SAAS,KAAK,IAAI,CAAA;CACpE,CAAA;AAID,KAAK,aAAa,GAAG,aAAa,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,GAAG;IACzD,QAAQ,EAAE,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,UAAU,EAAE,OAAO,GAAG,aAAa,GAAG,aAAa,CAAC,CAAC,CAAC,CAAA;CAC7F,CAAA;AAED,QAAA,MAAM,QAAQ,EAAE,aA0Mf,CAAA;AAED,eAAe,QAAQ,CAAA;AAOvB;;;GAGG;AACH,wBAAgB,qBAAqB,SAIpC;AAED,wBAAgB,iBAAiB,SAGhC"}
1
+ {"version":3,"file":"use-scene.d.ts","sourceRoot":"","sources":["../../src/store/use-scene.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAA;AAE1C,OAAO,EAAU,KAAK,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,SAAS,CAAA;AAEnE,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAA;AAIrE,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AA8CzD,MAAM,MAAM,UAAU,GAAG;IAEvB,KAAK,EAAE,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,CAAA;IAGjC,WAAW,EAAE,SAAS,EAAE,CAAA;IAGxB,UAAU,EAAE,GAAG,CAAC,SAAS,CAAC,CAAA;IAG1B,WAAW,EAAE,MAAM,CAAC,YAAY,EAAE,UAAU,CAAC,CAAA;IAG7C,SAAS,EAAE,MAAM,IAAI,CAAA;IACrB,UAAU,EAAE,MAAM,IAAI,CAAA;IACtB,WAAW,EAAE,MAAM,IAAI,CAAA;IACvB,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,EAAE,WAAW,EAAE,SAAS,EAAE,KAAK,IAAI,CAAA;IAE/E,SAAS,EAAE,CAAC,EAAE,EAAE,SAAS,KAAK,IAAI,CAAA;IAClC,UAAU,EAAE,CAAC,EAAE,EAAE,SAAS,KAAK,IAAI,CAAA;IAEnC,UAAU,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,SAAS,KAAK,IAAI,CAAA;IACzD,WAAW,EAAE,CAAC,GAAG,EAAE;QAAE,IAAI,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,EAAE,SAAS,CAAA;KAAE,EAAE,KAAK,IAAI,CAAA;IAErE,UAAU,EAAE,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,KAAK,IAAI,CAAA;IAC3D,WAAW,EAAE,CAAC,OAAO,EAAE;QAAE,EAAE,EAAE,SAAS,CAAC;QAAC,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,CAAA;KAAE,EAAE,KAAK,IAAI,CAAA;IAE3E,UAAU,EAAE,CAAC,EAAE,EAAE,SAAS,KAAK,IAAI,CAAA;IACnC,WAAW,EAAE,CAAC,GAAG,EAAE,SAAS,EAAE,KAAK,IAAI,CAAA;IAGvC,gBAAgB,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS,EAAE,KAAK,YAAY,CAAA;IACvE,gBAAgB,EAAE,CAAC,EAAE,EAAE,YAAY,KAAK,IAAI,CAAA;IAC5C,gBAAgB,EAAE,CAAC,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC,KAAK,IAAI,CAAA;IACnF,eAAe,EAAE,CAAC,EAAE,EAAE,YAAY,EAAE,MAAM,EAAE,SAAS,KAAK,IAAI,CAAA;IAC9D,oBAAoB,EAAE,CAAC,EAAE,EAAE,YAAY,EAAE,MAAM,EAAE,SAAS,KAAK,IAAI,CAAA;CACpE,CAAA;AAID,KAAK,aAAa,GAAG,aAAa,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,GAAG;IACzD,QAAQ,EAAE,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,UAAU,EAAE,OAAO,GAAG,aAAa,GAAG,aAAa,CAAC,CAAC,CAAC,CAAA;CAC7F,CAAA;AAED,QAAA,MAAM,QAAQ,EAAE,aA2Mf,CAAA;AAED,eAAe,QAAQ,CAAA;AAOvB;;;GAGG;AACH,wBAAgB,qBAAqB,SAIpC;AAED,wBAAgB,iBAAiB,SAGhC"}
@@ -78,6 +78,7 @@ const useScene = create()(temporal((set, get) => ({
78
78
  nodes: patchedNodes,
79
79
  rootNodeIds,
80
80
  dirtyNodes: new Set(),
81
+ collections: {},
81
82
  });
82
83
  // Mark all nodes as dirty to trigger re-validation
83
84
  Object.values(patchedNodes).forEach((node) => {
@@ -0,0 +1,18 @@
1
+ import type { AnyNode, AnyNodeId } from '../schema';
2
+ import type { Collection, CollectionId } from '../schema/collections';
3
+ export type SceneGraph = {
4
+ nodes: Record<AnyNodeId, AnyNode>;
5
+ rootNodeIds: AnyNodeId[];
6
+ collections?: Record<CollectionId, Collection>;
7
+ };
8
+ /**
9
+ * Deep clones a scene graph with all node IDs regenerated while preserving
10
+ * parent-child relationships and other internal references.
11
+ *
12
+ * This is useful for:
13
+ * - Copying nodes between different projects
14
+ * - Duplicating a subset of a scene within the same project
15
+ * - Multi-scene in-memory scenarios
16
+ */
17
+ export declare function cloneSceneGraph(sceneGraph: SceneGraph): SceneGraph;
18
+ //# sourceMappingURL=clone-scene-graph.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clone-scene-graph.d.ts","sourceRoot":"","sources":["../../src/utils/clone-scene-graph.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AAEnD,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAA;AAErE,MAAM,MAAM,UAAU,GAAG;IACvB,KAAK,EAAE,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,CAAA;IACjC,WAAW,EAAE,SAAS,EAAE,CAAA;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC,YAAY,EAAE,UAAU,CAAC,CAAA;CAC/C,CAAA;AAUD;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,UAAU,GAAG,UAAU,CA4FlE"}
@@ -0,0 +1,96 @@
1
+ import { generateId } from '../schema/base';
2
+ /**
3
+ * Extracts the type prefix from a node ID (e.g., "wall_abc123" -> "wall")
4
+ */
5
+ function extractIdPrefix(id) {
6
+ const underscoreIndex = id.indexOf('_');
7
+ return underscoreIndex === -1 ? 'node' : id.slice(0, underscoreIndex);
8
+ }
9
+ /**
10
+ * Deep clones a scene graph with all node IDs regenerated while preserving
11
+ * parent-child relationships and other internal references.
12
+ *
13
+ * This is useful for:
14
+ * - Copying nodes between different projects
15
+ * - Duplicating a subset of a scene within the same project
16
+ * - Multi-scene in-memory scenarios
17
+ */
18
+ export function cloneSceneGraph(sceneGraph) {
19
+ const { nodes, rootNodeIds, collections } = sceneGraph;
20
+ // Build ID mapping: old ID -> new ID
21
+ const idMap = new Map();
22
+ // Pass 1: Generate new IDs for all nodes
23
+ for (const nodeId of Object.keys(nodes)) {
24
+ const prefix = extractIdPrefix(nodeId);
25
+ idMap.set(nodeId, generateId(prefix));
26
+ }
27
+ // Pass 2: Deep clone nodes with remapped references
28
+ const clonedNodes = {};
29
+ for (const [oldId, node] of Object.entries(nodes)) {
30
+ const newId = idMap.get(oldId);
31
+ // structuredClone to avoid shared references between original and clone
32
+ const clonedNode = structuredClone({ ...node, id: newId });
33
+ // Remap parentId
34
+ if (clonedNode.parentId && typeof clonedNode.parentId === 'string') {
35
+ clonedNode.parentId = (idMap.get(clonedNode.parentId) ?? null);
36
+ }
37
+ // Remap children array (walls, levels, buildings, sites, items can have children)
38
+ if ('children' in clonedNode && Array.isArray(clonedNode.children)) {
39
+ ;
40
+ clonedNode.children = clonedNode.children
41
+ .map((childId) => idMap.get(childId))
42
+ .filter((id) => id !== undefined);
43
+ }
44
+ // Remap wallId (items/doors/windows attached to walls)
45
+ if ('wallId' in clonedNode && typeof clonedNode.wallId === 'string') {
46
+ ;
47
+ clonedNode.wallId = idMap.get(clonedNode.wallId);
48
+ }
49
+ clonedNodes[newId] = clonedNode;
50
+ }
51
+ // Remap root node IDs
52
+ const clonedRootNodeIds = rootNodeIds
53
+ .map((id) => idMap.get(id))
54
+ .filter((id) => id !== undefined);
55
+ // Clone and remap collections if present
56
+ let clonedCollections;
57
+ if (collections) {
58
+ clonedCollections = {};
59
+ const collectionIdMap = new Map();
60
+ // Generate new collection IDs
61
+ for (const collectionId of Object.keys(collections)) {
62
+ collectionIdMap.set(collectionId, generateId('collection'));
63
+ }
64
+ for (const [oldCollectionId, collection] of Object.entries(collections)) {
65
+ const newCollectionId = collectionIdMap.get(oldCollectionId);
66
+ clonedCollections[newCollectionId] = {
67
+ ...collection,
68
+ id: newCollectionId,
69
+ nodeIds: collection.nodeIds
70
+ .map((nodeId) => idMap.get(nodeId))
71
+ .filter((id) => id !== undefined),
72
+ controlNodeId: collection.controlNodeId
73
+ ? idMap.get(collection.controlNodeId)
74
+ : undefined,
75
+ };
76
+ // Update collectionIds on nodes that reference this collection
77
+ for (const oldNodeId of collection.nodeIds) {
78
+ const newNodeId = idMap.get(oldNodeId);
79
+ if (newNodeId && clonedNodes[newNodeId]) {
80
+ const node = clonedNodes[newNodeId];
81
+ if ('collectionIds' in node && Array.isArray(node.collectionIds)) {
82
+ const oldColIds = node.collectionIds;
83
+ node.collectionIds = oldColIds
84
+ .map((cid) => collectionIdMap.get(cid))
85
+ .filter((id) => id !== undefined);
86
+ }
87
+ }
88
+ }
89
+ }
90
+ }
91
+ return {
92
+ nodes: clonedNodes,
93
+ rootNodeIds: clonedRootNodeIds,
94
+ ...(clonedCollections && { collections: clonedCollections }),
95
+ };
96
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pascal-app/core",
3
- "version": "0.3.1",
3
+ "version": "0.3.2",
4
4
  "description": "Core library for Pascal 3D building editor",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -25,7 +25,7 @@
25
25
  "@react-three/drei": "^10",
26
26
  "@react-three/fiber": "^9",
27
27
  "react": "^18 || ^19",
28
- "three": "^0.183"
28
+ "three": "^0.182"
29
29
  },
30
30
  "dependencies": {
31
31
  "dedent": "^1.7.1",