@nice2dev/ui-3d 1.3.15 → 1.3.17

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 (108) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/cjs/collaborative/collaborativeScene.js +160 -206
  3. package/dist/cjs/core/editorAsk.js +51 -41
  4. package/dist/cjs/core/i18n.js +13 -14
  5. package/dist/cjs/core/threeCompat.js +29 -42
  6. package/dist/cjs/dance/DanceBridge.js +148 -177
  7. package/dist/cjs/dance/DanceScoreEngine.js +209 -221
  8. package/dist/cjs/dance/PoseDetector.js +302 -275
  9. package/dist/cjs/index.js +110 -113
  10. package/dist/cjs/material/MaterialEditor.module.css.js +242 -5
  11. package/dist/cjs/material/NiceMaterialEditor.js +1213 -757
  12. package/dist/cjs/material/materialEditorTypes.js +35 -49
  13. package/dist/cjs/material/materialEditorUtils.js +684 -747
  14. package/dist/cjs/material/materialNodeDefinitions.js +1411 -1459
  15. package/dist/cjs/model/ModelEditor.js +90 -40
  16. package/dist/cjs/model/ModelEditor.module.css.js +257 -5
  17. package/dist/cjs/model/ModelEditorLeftPanel.js +126 -47
  18. package/dist/cjs/model/ModelEditorMenuBar.js +359 -32
  19. package/dist/cjs/model/ModelEditorRightPanel.js +647 -131
  20. package/dist/cjs/model/ModelEditorSubComponents.js +277 -112
  21. package/dist/cjs/model/ModelEditorTimeline.js +232 -34
  22. package/dist/cjs/model/ModelEditorToolbar.js +170 -14
  23. package/dist/cjs/model/ModelEditorViewport.js +231 -39
  24. package/dist/cjs/model/ModelViewer.js +388 -63
  25. package/dist/cjs/model/ModelViewer.module.css.js +77 -5
  26. package/dist/cjs/model/NiceArmatureEditor.js +473 -274
  27. package/dist/cjs/model/NiceMorphTargetEditor.js +333 -227
  28. package/dist/cjs/model/NiceOctree.js +372 -320
  29. package/dist/cjs/model/NicePhysicsSimulation.js +528 -298
  30. package/dist/cjs/model/NiceProceduralGeometry.js +673 -300
  31. package/dist/cjs/model/NiceTerrainEditor.js +595 -385
  32. package/dist/cjs/model/NiceWeightPainter.js +384 -261
  33. package/dist/cjs/model/NiceXRPreview.js +385 -308
  34. package/dist/cjs/model/cadModeUtils.js +103 -106
  35. package/dist/cjs/model/editorShortcuts.js +171 -194
  36. package/dist/cjs/model/modelEditorTypes.js +100 -118
  37. package/dist/cjs/model/modelEditorUtils.js +1061 -1146
  38. package/dist/cjs/model/simsModeUtils.js +1023 -1053
  39. package/dist/cjs/model/useModelEditor.js +1977 -1933
  40. package/dist/cjs/model/useModelViewer.js +633 -665
  41. package/dist/cjs/nice2dev-ui-3d.css +1 -1
  42. package/dist/cjs/particle/NiceParticleEditor.js +1186 -571
  43. package/dist/cjs/particle/ParticleEditor.module.css.js +122 -5
  44. package/dist/cjs/particle/particleEditorTypes.js +62 -70
  45. package/dist/cjs/particle/particleEditorUtils.js +998 -1013
  46. package/dist/cjs/rendering/NiceCascadedShadows.js +381 -259
  47. package/dist/cjs/rendering/NiceRenderExport.js +424 -337
  48. package/dist/cjs/rendering/NiceSSAO.js +454 -337
  49. package/dist/cjs/rendering/NiceSSR.js +387 -261
  50. package/dist/cjs/rendering/NiceWebGPURenderer.js +359 -230
  51. package/dist/cjs/uv/NiceUVEditor.js +787 -550
  52. package/dist/cjs/uv/UVEditor.module.css.js +53 -5
  53. package/dist/cjs/uv/uvEditorTypes.js +59 -76
  54. package/dist/cjs/uv/uvEditorUtils.js +501 -575
  55. package/dist/esm/collaborative/collaborativeScene.js +163 -205
  56. package/dist/esm/core/editorAsk.js +53 -40
  57. package/dist/esm/core/i18n.js +15 -13
  58. package/dist/esm/core/threeCompat.js +18 -26
  59. package/dist/esm/dance/DanceBridge.js +151 -176
  60. package/dist/esm/dance/DanceScoreEngine.js +211 -220
  61. package/dist/esm/dance/PoseDetector.js +304 -274
  62. package/dist/esm/index.js +258 -36
  63. package/dist/esm/material/MaterialEditor.module.css.js +242 -3
  64. package/dist/esm/material/NiceMaterialEditor.js +1215 -756
  65. package/dist/esm/material/materialEditorTypes.js +45 -48
  66. package/dist/esm/material/materialEditorUtils.js +713 -746
  67. package/dist/esm/material/materialNodeDefinitions.js +1415 -1458
  68. package/dist/esm/model/ModelEditor.js +91 -39
  69. package/dist/esm/model/ModelEditor.module.css.js +257 -3
  70. package/dist/esm/model/ModelEditorLeftPanel.js +126 -45
  71. package/dist/esm/model/ModelEditorMenuBar.js +359 -30
  72. package/dist/esm/model/ModelEditorRightPanel.js +634 -114
  73. package/dist/esm/model/ModelEditorSubComponents.js +265 -94
  74. package/dist/esm/model/ModelEditorTimeline.js +232 -32
  75. package/dist/esm/model/ModelEditorToolbar.js +170 -12
  76. package/dist/esm/model/ModelEditorViewport.js +231 -37
  77. package/dist/esm/model/ModelViewer.js +389 -62
  78. package/dist/esm/model/ModelViewer.module.css.js +77 -3
  79. package/dist/esm/model/NiceArmatureEditor.js +462 -258
  80. package/dist/esm/model/NiceMorphTargetEditor.js +322 -211
  81. package/dist/esm/model/NiceOctree.js +361 -304
  82. package/dist/esm/model/NicePhysicsSimulation.js +517 -282
  83. package/dist/esm/model/NiceProceduralGeometry.js +667 -284
  84. package/dist/esm/model/NiceTerrainEditor.js +584 -369
  85. package/dist/esm/model/NiceWeightPainter.js +373 -245
  86. package/dist/esm/model/NiceXRPreview.js +374 -292
  87. package/dist/esm/model/cadModeUtils.js +95 -88
  88. package/dist/esm/model/editorShortcuts.js +172 -193
  89. package/dist/esm/model/modelEditorTypes.js +90 -100
  90. package/dist/esm/model/modelEditorUtils.js +1056 -1128
  91. package/dist/esm/model/simsModeUtils.js +1021 -1035
  92. package/dist/esm/model/useModelEditor.js +1946 -1920
  93. package/dist/esm/model/useModelViewer.js +619 -647
  94. package/dist/esm/nice2dev-ui-3d.css +1 -1
  95. package/dist/esm/particle/NiceParticleEditor.js +1188 -570
  96. package/dist/esm/particle/ParticleEditor.module.css.js +122 -3
  97. package/dist/esm/particle/particleEditorTypes.js +69 -69
  98. package/dist/esm/particle/particleEditorUtils.js +1027 -1012
  99. package/dist/esm/rendering/NiceCascadedShadows.js +370 -243
  100. package/dist/esm/rendering/NiceRenderExport.js +413 -321
  101. package/dist/esm/rendering/NiceSSAO.js +450 -328
  102. package/dist/esm/rendering/NiceSSR.js +383 -252
  103. package/dist/esm/rendering/NiceWebGPURenderer.js +326 -214
  104. package/dist/esm/uv/NiceUVEditor.js +788 -549
  105. package/dist/esm/uv/UVEditor.module.css.js +53 -3
  106. package/dist/esm/uv/uvEditorTypes.js +68 -75
  107. package/dist/esm/uv/uvEditorUtils.js +515 -557
  108. package/package.json +7 -12
@@ -1,1069 +1,1055 @@
1
- import * as THREE from 'three';
2
-
3
- /**
4
- * simsModeUtils.ts — Sims-style simplified drag-drop mode for ModelEditor.
5
- *
6
- * Provides: furniture catalog, room decorator, drag-drop placement,
7
- * grid snapping, resize handles, and room preset layouts.
8
- */
9
- /* ════════════════════════════════════════════════════════════════
10
- FURNITURE CATALOG
11
- ════════════════════════════════════════════════════════════════ */
1
+ import * as THREE from "three";
12
2
  const FURNITURE_CATALOG = [
13
- // Seating
14
- {
15
- id: 'sofa-3seat',
16
- name: '3-Seat Sofa',
17
- category: 'seating',
18
- icon: 'sofa',
19
- width: 2.2,
20
- depth: 0.9,
21
- height: 0.85,
22
- color: '#8B7355',
23
- tags: ['living', 'comfort'],
24
- stackable: false,
25
- wallMounted: false,
26
- price: 599,
27
- },
28
- {
29
- id: 'sofa-2seat',
30
- name: 'Love Seat',
31
- category: 'seating',
32
- icon: 'sofa',
33
- width: 1.5,
34
- depth: 0.85,
35
- height: 0.82,
36
- color: '#A0522D',
37
- tags: ['living'],
38
- stackable: false,
39
- wallMounted: false,
40
- price: 399,
41
- },
42
- {
43
- id: 'armchair',
44
- name: 'Armchair',
45
- category: 'seating',
46
- icon: 'chair',
47
- width: 0.85,
48
- depth: 0.85,
49
- height: 0.9,
50
- color: '#6B4423',
51
- tags: ['living', 'comfort'],
52
- stackable: false,
53
- wallMounted: false,
54
- price: 249,
55
- },
56
- {
57
- id: 'dining-chair',
58
- name: 'Dining Chair',
59
- category: 'seating',
60
- icon: 'chair',
61
- width: 0.45,
62
- depth: 0.45,
63
- height: 0.9,
64
- color: '#8B7355',
65
- tags: ['dining'],
66
- stackable: true,
67
- wallMounted: false,
68
- price: 79,
69
- },
70
- {
71
- id: 'office-chair',
72
- name: 'Office Chair',
73
- category: 'seating',
74
- icon: 'chair',
75
- width: 0.6,
76
- depth: 0.6,
77
- height: 1.1,
78
- color: '#333333',
79
- tags: ['office'],
80
- stackable: false,
81
- wallMounted: false,
82
- price: 199,
83
- },
84
- {
85
- id: 'bar-stool',
86
- name: 'Bar Stool',
87
- category: 'seating',
88
- icon: 'chair',
89
- width: 0.4,
90
- depth: 0.4,
91
- height: 0.75,
92
- color: '#696969',
93
- tags: ['kitchen', 'bar'],
94
- stackable: true,
95
- wallMounted: false,
96
- price: 89,
97
- },
98
- {
99
- id: 'bean-bag',
100
- name: 'Bean Bag',
101
- category: 'seating',
102
- icon: 'droplet',
103
- width: 0.8,
104
- depth: 0.8,
105
- height: 0.7,
106
- color: '#ff6b6b',
107
- tags: ['casual'],
108
- stackable: false,
109
- wallMounted: false,
110
- price: 59,
111
- },
112
- // Tables
113
- {
114
- id: 'dining-table-6',
115
- name: 'Dining Table (6p)',
116
- category: 'tables',
117
- icon: 'box',
118
- width: 1.8,
119
- depth: 0.9,
120
- height: 0.75,
121
- color: '#8B6914',
122
- tags: ['dining'],
123
- stackable: false,
124
- wallMounted: false,
125
- price: 499,
126
- },
127
- {
128
- id: 'dining-table-4',
129
- name: 'Dining Table (4p)',
130
- category: 'tables',
131
- icon: 'box',
132
- width: 1.2,
133
- depth: 0.8,
134
- height: 0.75,
135
- color: '#A0522D',
136
- tags: ['dining'],
137
- stackable: false,
138
- wallMounted: false,
139
- price: 349,
140
- },
141
- {
142
- id: 'coffee-table',
143
- name: 'Coffee Table',
144
- category: 'tables',
145
- icon: 'box',
146
- width: 1.2,
147
- depth: 0.6,
148
- height: 0.45,
149
- color: '#654321',
150
- tags: ['living'],
151
- stackable: false,
152
- wallMounted: false,
153
- price: 179,
154
- },
155
- {
156
- id: 'side-table',
157
- name: 'Side Table',
158
- category: 'tables',
159
- icon: 'box',
160
- width: 0.5,
161
- depth: 0.5,
162
- height: 0.55,
163
- color: '#8B6914',
164
- tags: ['living', 'bedroom'],
165
- stackable: false,
166
- wallMounted: false,
167
- price: 99,
168
- },
169
- {
170
- id: 'desk',
171
- name: 'Office Desk',
172
- category: 'tables',
173
- icon: 'box',
174
- width: 1.4,
175
- depth: 0.7,
176
- height: 0.75,
177
- color: '#696969',
178
- tags: ['office'],
179
- stackable: false,
180
- wallMounted: false,
181
- price: 299,
182
- },
183
- {
184
- id: 'console-table',
185
- name: 'Console Table',
186
- category: 'tables',
187
- icon: 'box',
188
- width: 1.2,
189
- depth: 0.35,
190
- height: 0.8,
191
- color: '#B8860B',
192
- tags: ['hallway'],
193
- stackable: false,
194
- wallMounted: false,
195
- price: 199,
196
- },
197
- // Beds
198
- {
199
- id: 'bed-king',
200
- name: 'King Bed',
201
- category: 'beds',
202
- icon: 'bed',
203
- width: 1.9,
204
- depth: 2.1,
205
- height: 0.6,
206
- color: '#F5DEB3',
207
- tags: ['bedroom'],
208
- stackable: false,
209
- wallMounted: false,
210
- price: 899,
211
- },
212
- {
213
- id: 'bed-queen',
214
- name: 'Queen Bed',
215
- category: 'beds',
216
- icon: 'bed',
217
- width: 1.6,
218
- depth: 2.0,
219
- height: 0.6,
220
- color: '#DEB887',
221
- tags: ['bedroom'],
222
- stackable: false,
223
- wallMounted: false,
224
- price: 699,
225
- },
226
- {
227
- id: 'bed-single',
228
- name: 'Single Bed',
229
- category: 'beds',
230
- icon: 'bed',
231
- width: 1.0,
232
- depth: 2.0,
233
- height: 0.55,
234
- color: '#87CEEB',
235
- tags: ['bedroom', 'kids'],
236
- stackable: false,
237
- wallMounted: false,
238
- price: 349,
239
- },
240
- {
241
- id: 'bunk-bed',
242
- name: 'Bunk Bed',
243
- category: 'beds',
244
- icon: 'bed',
245
- width: 1.0,
246
- depth: 2.0,
247
- height: 1.7,
248
- color: '#BC8F8F',
249
- tags: ['kids'],
250
- stackable: false,
251
- wallMounted: false,
252
- price: 499,
253
- },
254
- {
255
- id: 'crib',
256
- name: 'Baby Crib',
257
- category: 'beds',
258
- icon: 'bed',
259
- width: 0.7,
260
- depth: 1.3,
261
- height: 1.0,
262
- color: '#FFFAF0',
263
- tags: ['nursery'],
264
- stackable: false,
265
- wallMounted: false,
266
- price: 299,
267
- },
268
- // Storage
269
- {
270
- id: 'bookshelf',
271
- name: 'Bookshelf',
272
- category: 'storage',
273
- icon: 'book',
274
- width: 0.8,
275
- depth: 0.35,
276
- height: 1.8,
277
- color: '#8B6914',
278
- tags: ['living', 'office'],
279
- stackable: false,
280
- wallMounted: false,
281
- price: 229,
282
- },
283
- {
284
- id: 'wardrobe',
285
- name: 'Wardrobe',
286
- category: 'storage',
287
- icon: 'door',
288
- width: 1.2,
289
- depth: 0.6,
290
- height: 2.0,
291
- color: '#A0522D',
292
- tags: ['bedroom'],
293
- stackable: false,
294
- wallMounted: false,
295
- price: 449,
296
- },
297
- {
298
- id: 'tv-unit',
299
- name: 'TV Unit',
300
- category: 'storage',
301
- icon: 'monitor',
302
- width: 1.6,
303
- depth: 0.45,
304
- height: 0.55,
305
- color: '#36454F',
306
- tags: ['living'],
307
- stackable: false,
308
- wallMounted: false,
309
- price: 329,
310
- },
311
- {
312
- id: 'dresser',
313
- name: 'Dresser',
314
- category: 'storage',
315
- icon: 'archive',
316
- width: 1.0,
317
- depth: 0.5,
318
- height: 0.85,
319
- color: '#DEB887',
320
- tags: ['bedroom'],
321
- stackable: false,
322
- wallMounted: false,
323
- price: 279,
324
- },
325
- {
326
- id: 'shelf-wall',
327
- name: 'Wall Shelf',
328
- category: 'storage',
329
- icon: 'ruler',
330
- width: 0.8,
331
- depth: 0.2,
332
- height: 0.03,
333
- color: '#8B6914',
334
- tags: ['any'],
335
- stackable: false,
336
- wallMounted: true,
337
- price: 49,
338
- },
339
- // Lighting
340
- {
341
- id: 'floor-lamp',
342
- name: 'Floor Lamp',
343
- category: 'lighting',
344
- icon: 'lightbulb',
345
- width: 0.4,
346
- depth: 0.4,
347
- height: 1.7,
348
- color: '#FFD700',
349
- tags: ['living'],
350
- stackable: false,
351
- wallMounted: false,
352
- price: 119,
353
- },
354
- {
355
- id: 'table-lamp',
356
- name: 'Table Lamp',
357
- category: 'lighting',
358
- icon: 'lightbulb',
359
- width: 0.3,
360
- depth: 0.3,
361
- height: 0.5,
362
- color: '#FAFAD2',
363
- tags: ['bedroom', 'living'],
364
- stackable: false,
365
- wallMounted: false,
366
- price: 59,
367
- },
368
- {
369
- id: 'ceiling-fan',
370
- name: 'Ceiling Fan',
371
- category: 'lighting',
372
- icon: 'refresh',
373
- width: 1.2,
374
- depth: 1.2,
375
- height: 0.35,
376
- color: '#C0C0C0',
377
- tags: ['any'],
378
- stackable: false,
379
- wallMounted: false,
380
- price: 179,
381
- },
382
- {
383
- id: 'pendant',
384
- name: 'Pendant Light',
385
- category: 'lighting',
386
- icon: 'lightbulb',
387
- width: 0.4,
388
- depth: 0.4,
389
- height: 0.6,
390
- color: '#FFD700',
391
- tags: ['kitchen', 'dining'],
392
- stackable: false,
393
- wallMounted: false,
394
- price: 149,
395
- },
396
- // Appliances
397
- {
398
- id: 'fridge',
399
- name: 'Refrigerator',
400
- category: 'appliances',
401
- icon: 'box',
402
- width: 0.7,
403
- depth: 0.7,
404
- height: 1.8,
405
- color: '#C0C0C0',
406
- tags: ['kitchen'],
407
- stackable: false,
408
- wallMounted: false,
409
- price: 999,
410
- },
411
- {
412
- id: 'stove',
413
- name: 'Stove/Oven',
414
- category: 'appliances',
415
- icon: 'utensils',
416
- width: 0.6,
417
- depth: 0.6,
418
- height: 0.9,
419
- color: '#696969',
420
- tags: ['kitchen'],
421
- stackable: false,
422
- wallMounted: false,
423
- price: 799,
424
- },
425
- {
426
- id: 'dishwasher',
427
- name: 'Dishwasher',
428
- category: 'appliances',
429
- icon: 'utensils',
430
- width: 0.6,
431
- depth: 0.6,
432
- height: 0.85,
433
- color: '#C0C0C0',
434
- tags: ['kitchen'],
435
- stackable: false,
436
- wallMounted: false,
437
- price: 549,
438
- },
439
- {
440
- id: 'washer',
441
- name: 'Washing Machine',
442
- category: 'appliances',
443
- icon: 'box',
444
- width: 0.6,
445
- depth: 0.6,
446
- height: 0.85,
447
- color: '#f5f5f5',
448
- tags: ['laundry'],
449
- stackable: false,
450
- wallMounted: false,
451
- price: 599,
452
- },
453
- {
454
- id: 'microwave',
455
- name: 'Microwave',
456
- category: 'appliances',
457
- icon: 'music',
458
- width: 0.5,
459
- depth: 0.4,
460
- height: 0.3,
461
- color: '#333333',
462
- tags: ['kitchen'],
463
- stackable: true,
464
- wallMounted: false,
465
- price: 149,
466
- },
467
- // Bathroom
468
- {
469
- id: 'toilet',
470
- name: 'Toilet',
471
- category: 'bathroom',
472
- icon: 'droplet',
473
- width: 0.4,
474
- depth: 0.7,
475
- height: 0.75,
476
- color: '#FFFFF0',
477
- tags: ['bathroom'],
478
- stackable: false,
479
- wallMounted: false,
480
- price: 199,
481
- },
482
- {
483
- id: 'bathtub',
484
- name: 'Bathtub',
485
- category: 'bathroom',
486
- icon: 'droplet',
487
- width: 0.75,
488
- depth: 1.7,
489
- height: 0.6,
490
- color: '#FFFFF0',
491
- tags: ['bathroom'],
492
- stackable: false,
493
- wallMounted: false,
494
- price: 599,
495
- },
496
- {
497
- id: 'shower',
498
- name: 'Shower Cabin',
499
- category: 'bathroom',
500
- icon: 'droplet',
501
- width: 0.9,
502
- depth: 0.9,
503
- height: 2.1,
504
- color: '#E0FFFF',
505
- tags: ['bathroom'],
506
- stackable: false,
507
- wallMounted: false,
508
- price: 449,
509
- },
510
- {
511
- id: 'vanity',
512
- name: 'Bathroom Vanity',
513
- category: 'bathroom',
514
- icon: 'copy',
515
- width: 0.8,
516
- depth: 0.5,
517
- height: 0.85,
518
- color: '#FFFFF0',
519
- tags: ['bathroom'],
520
- stackable: false,
521
- wallMounted: false,
522
- price: 349,
523
- },
524
- {
525
- id: 'sink-kitchen',
526
- name: 'Kitchen Sink',
527
- category: 'kitchen',
528
- icon: 'droplet',
529
- width: 0.6,
530
- depth: 0.5,
531
- height: 0.85,
532
- color: '#C0C0C0',
533
- tags: ['kitchen'],
534
- stackable: false,
535
- wallMounted: false,
536
- price: 199,
537
- },
538
- // Decor
539
- {
540
- id: 'painting-large',
541
- name: 'Large Painting',
542
- category: 'decor',
543
- icon: 'image',
544
- width: 1.0,
545
- depth: 0.05,
546
- height: 0.7,
547
- color: '#B8860B',
548
- tags: ['any'],
549
- stackable: false,
550
- wallMounted: true,
551
- price: 89,
552
- },
553
- {
554
- id: 'mirror',
555
- name: 'Wall Mirror',
556
- category: 'decor',
557
- icon: 'copy',
558
- width: 0.6,
559
- depth: 0.03,
560
- height: 0.9,
561
- color: '#e0e0e0',
562
- tags: ['bathroom', 'hallway'],
563
- stackable: false,
564
- wallMounted: true,
565
- price: 69,
566
- },
567
- {
568
- id: 'clock',
569
- name: 'Wall Clock',
570
- category: 'decor',
571
- icon: 'clock',
572
- width: 0.3,
573
- depth: 0.05,
574
- height: 0.3,
575
- color: '#333333',
576
- tags: ['any'],
577
- stackable: false,
578
- wallMounted: true,
579
- price: 39,
580
- },
581
- // Plants
582
- {
583
- id: 'plant-large',
584
- name: 'Large Plant',
585
- category: 'plants',
586
- icon: 'tree',
587
- width: 0.5,
588
- depth: 0.5,
589
- height: 1.4,
590
- color: '#228B22',
591
- tags: ['any'],
592
- stackable: false,
593
- wallMounted: false,
594
- price: 49,
595
- },
596
- {
597
- id: 'plant-small',
598
- name: 'Small Plant',
599
- category: 'plants',
600
- icon: 'tree',
601
- width: 0.2,
602
- depth: 0.2,
603
- height: 0.35,
604
- color: '#2E8B57',
605
- tags: ['any'],
606
- stackable: true,
607
- wallMounted: false,
608
- price: 19,
609
- },
610
- {
611
- id: 'flower-vase',
612
- name: 'Flower Vase',
613
- category: 'plants',
614
- icon: 'tree',
615
- width: 0.15,
616
- depth: 0.15,
617
- height: 0.35,
618
- color: '#FF69B4',
619
- tags: ['decor'],
620
- stackable: true,
621
- wallMounted: false,
622
- price: 25,
623
- },
624
- // Electronics
625
- {
626
- id: 'tv-65',
627
- name: '65" TV',
628
- category: 'electronics',
629
- icon: 'monitor',
630
- width: 1.45,
631
- depth: 0.08,
632
- height: 0.85,
633
- color: '#1a1a1a',
634
- tags: ['living'],
635
- stackable: false,
636
- wallMounted: true,
637
- price: 799,
638
- },
639
- {
640
- id: 'tv-50',
641
- name: '50" TV',
642
- category: 'electronics',
643
- icon: 'monitor',
644
- width: 1.12,
645
- depth: 0.08,
646
- height: 0.65,
647
- color: '#1a1a1a',
648
- tags: ['living', 'bedroom'],
649
- stackable: false,
650
- wallMounted: true,
651
- price: 449,
652
- },
653
- {
654
- id: 'computer',
655
- name: 'Desktop Computer',
656
- category: 'electronics',
657
- icon: 'monitor',
658
- width: 0.55,
659
- depth: 0.3,
660
- height: 0.45,
661
- color: '#2F4F4F',
662
- tags: ['office'],
663
- stackable: false,
664
- wallMounted: false,
665
- price: 999,
666
- },
667
- // Rugs
668
- {
669
- id: 'rug-large',
670
- name: 'Large Area Rug',
671
- category: 'rugs',
672
- icon: 'box',
673
- width: 2.5,
674
- depth: 3.5,
675
- height: 0.02,
676
- color: '#8B4513',
677
- tags: ['living'],
678
- stackable: false,
679
- wallMounted: false,
680
- price: 199,
681
- },
682
- {
683
- id: 'rug-round',
684
- name: 'Round Rug',
685
- category: 'rugs',
686
- icon: 'circle',
687
- width: 1.5,
688
- depth: 1.5,
689
- height: 0.02,
690
- color: '#CD853F',
691
- tags: ['any'],
692
- stackable: false,
693
- wallMounted: false,
694
- price: 129,
695
- },
696
- // Outdoor
697
- {
698
- id: 'patio-table',
699
- name: 'Patio Table',
700
- category: 'outdoor',
701
- icon: 'cloud',
702
- width: 1.0,
703
- depth: 1.0,
704
- height: 0.72,
705
- color: '#808080',
706
- tags: ['outdoor'],
707
- stackable: false,
708
- wallMounted: false,
709
- price: 249,
710
- },
711
- {
712
- id: 'patio-chair',
713
- name: 'Patio Chair',
714
- category: 'outdoor',
715
- icon: 'chair',
716
- width: 0.55,
717
- depth: 0.55,
718
- height: 0.85,
719
- color: '#808080',
720
- tags: ['outdoor'],
721
- stackable: true,
722
- wallMounted: false,
723
- price: 99,
724
- },
725
- {
726
- id: 'bbq-grill',
727
- name: 'BBQ Grill',
728
- category: 'outdoor',
729
- icon: 'zap',
730
- width: 1.2,
731
- depth: 0.6,
732
- height: 1.1,
733
- color: '#333333',
734
- tags: ['outdoor'],
735
- stackable: false,
736
- wallMounted: false,
737
- price: 399,
738
- },
739
- // Kitchen
740
- {
741
- id: 'counter',
742
- name: 'Kitchen Counter',
743
- category: 'kitchen',
744
- icon: 'box',
745
- width: 0.6,
746
- depth: 0.6,
747
- height: 0.9,
748
- color: '#D2B48C',
749
- tags: ['kitchen'],
750
- stackable: false,
751
- wallMounted: false,
752
- price: 199,
753
- },
754
- {
755
- id: 'island',
756
- name: 'Kitchen Island',
757
- category: 'kitchen',
758
- icon: 'box',
759
- width: 1.5,
760
- depth: 0.8,
761
- height: 0.9,
762
- color: '#DCDCDC',
763
- tags: ['kitchen'],
764
- stackable: false,
765
- wallMounted: false,
766
- price: 599,
767
- },
768
- {
769
- id: 'cabinet-upper',
770
- name: 'Upper Cabinet',
771
- category: 'kitchen',
772
- icon: 'archive',
773
- width: 0.6,
774
- depth: 0.35,
775
- height: 0.7,
776
- color: '#F5DEB3',
777
- tags: ['kitchen'],
778
- stackable: false,
779
- wallMounted: true,
780
- price: 149,
781
- },
782
- // Office
783
- {
784
- id: 'filing-cabinet',
785
- name: 'Filing Cabinet',
786
- category: 'office',
787
- icon: 'archive',
788
- width: 0.4,
789
- depth: 0.6,
790
- height: 1.0,
791
- color: '#808080',
792
- tags: ['office'],
793
- stackable: false,
794
- wallMounted: false,
795
- price: 129,
796
- },
797
- {
798
- id: 'whiteboard',
799
- name: 'Whiteboard',
800
- category: 'office',
801
- icon: 'clipboard',
802
- width: 1.2,
803
- depth: 0.05,
804
- height: 0.9,
805
- color: '#ffffff',
806
- tags: ['office'],
807
- stackable: false,
808
- wallMounted: true,
809
- price: 99,
810
- },
3
+ // Seating
4
+ {
5
+ id: "sofa-3seat",
6
+ name: "3-Seat Sofa",
7
+ category: "seating",
8
+ icon: "sofa",
9
+ width: 2.2,
10
+ depth: 0.9,
11
+ height: 0.85,
12
+ color: "#8B7355",
13
+ tags: ["living", "comfort"],
14
+ stackable: false,
15
+ wallMounted: false,
16
+ price: 599
17
+ },
18
+ {
19
+ id: "sofa-2seat",
20
+ name: "Love Seat",
21
+ category: "seating",
22
+ icon: "sofa",
23
+ width: 1.5,
24
+ depth: 0.85,
25
+ height: 0.82,
26
+ color: "#A0522D",
27
+ tags: ["living"],
28
+ stackable: false,
29
+ wallMounted: false,
30
+ price: 399
31
+ },
32
+ {
33
+ id: "armchair",
34
+ name: "Armchair",
35
+ category: "seating",
36
+ icon: "chair",
37
+ width: 0.85,
38
+ depth: 0.85,
39
+ height: 0.9,
40
+ color: "#6B4423",
41
+ tags: ["living", "comfort"],
42
+ stackable: false,
43
+ wallMounted: false,
44
+ price: 249
45
+ },
46
+ {
47
+ id: "dining-chair",
48
+ name: "Dining Chair",
49
+ category: "seating",
50
+ icon: "chair",
51
+ width: 0.45,
52
+ depth: 0.45,
53
+ height: 0.9,
54
+ color: "#8B7355",
55
+ tags: ["dining"],
56
+ stackable: true,
57
+ wallMounted: false,
58
+ price: 79
59
+ },
60
+ {
61
+ id: "office-chair",
62
+ name: "Office Chair",
63
+ category: "seating",
64
+ icon: "chair",
65
+ width: 0.6,
66
+ depth: 0.6,
67
+ height: 1.1,
68
+ color: "#333333",
69
+ tags: ["office"],
70
+ stackable: false,
71
+ wallMounted: false,
72
+ price: 199
73
+ },
74
+ {
75
+ id: "bar-stool",
76
+ name: "Bar Stool",
77
+ category: "seating",
78
+ icon: "chair",
79
+ width: 0.4,
80
+ depth: 0.4,
81
+ height: 0.75,
82
+ color: "#696969",
83
+ tags: ["kitchen", "bar"],
84
+ stackable: true,
85
+ wallMounted: false,
86
+ price: 89
87
+ },
88
+ {
89
+ id: "bean-bag",
90
+ name: "Bean Bag",
91
+ category: "seating",
92
+ icon: "droplet",
93
+ width: 0.8,
94
+ depth: 0.8,
95
+ height: 0.7,
96
+ color: "#ff6b6b",
97
+ tags: ["casual"],
98
+ stackable: false,
99
+ wallMounted: false,
100
+ price: 59
101
+ },
102
+ // Tables
103
+ {
104
+ id: "dining-table-6",
105
+ name: "Dining Table (6p)",
106
+ category: "tables",
107
+ icon: "box",
108
+ width: 1.8,
109
+ depth: 0.9,
110
+ height: 0.75,
111
+ color: "#8B6914",
112
+ tags: ["dining"],
113
+ stackable: false,
114
+ wallMounted: false,
115
+ price: 499
116
+ },
117
+ {
118
+ id: "dining-table-4",
119
+ name: "Dining Table (4p)",
120
+ category: "tables",
121
+ icon: "box",
122
+ width: 1.2,
123
+ depth: 0.8,
124
+ height: 0.75,
125
+ color: "#A0522D",
126
+ tags: ["dining"],
127
+ stackable: false,
128
+ wallMounted: false,
129
+ price: 349
130
+ },
131
+ {
132
+ id: "coffee-table",
133
+ name: "Coffee Table",
134
+ category: "tables",
135
+ icon: "box",
136
+ width: 1.2,
137
+ depth: 0.6,
138
+ height: 0.45,
139
+ color: "#654321",
140
+ tags: ["living"],
141
+ stackable: false,
142
+ wallMounted: false,
143
+ price: 179
144
+ },
145
+ {
146
+ id: "side-table",
147
+ name: "Side Table",
148
+ category: "tables",
149
+ icon: "box",
150
+ width: 0.5,
151
+ depth: 0.5,
152
+ height: 0.55,
153
+ color: "#8B6914",
154
+ tags: ["living", "bedroom"],
155
+ stackable: false,
156
+ wallMounted: false,
157
+ price: 99
158
+ },
159
+ {
160
+ id: "desk",
161
+ name: "Office Desk",
162
+ category: "tables",
163
+ icon: "box",
164
+ width: 1.4,
165
+ depth: 0.7,
166
+ height: 0.75,
167
+ color: "#696969",
168
+ tags: ["office"],
169
+ stackable: false,
170
+ wallMounted: false,
171
+ price: 299
172
+ },
173
+ {
174
+ id: "console-table",
175
+ name: "Console Table",
176
+ category: "tables",
177
+ icon: "box",
178
+ width: 1.2,
179
+ depth: 0.35,
180
+ height: 0.8,
181
+ color: "#B8860B",
182
+ tags: ["hallway"],
183
+ stackable: false,
184
+ wallMounted: false,
185
+ price: 199
186
+ },
187
+ // Beds
188
+ {
189
+ id: "bed-king",
190
+ name: "King Bed",
191
+ category: "beds",
192
+ icon: "bed",
193
+ width: 1.9,
194
+ depth: 2.1,
195
+ height: 0.6,
196
+ color: "#F5DEB3",
197
+ tags: ["bedroom"],
198
+ stackable: false,
199
+ wallMounted: false,
200
+ price: 899
201
+ },
202
+ {
203
+ id: "bed-queen",
204
+ name: "Queen Bed",
205
+ category: "beds",
206
+ icon: "bed",
207
+ width: 1.6,
208
+ depth: 2,
209
+ height: 0.6,
210
+ color: "#DEB887",
211
+ tags: ["bedroom"],
212
+ stackable: false,
213
+ wallMounted: false,
214
+ price: 699
215
+ },
216
+ {
217
+ id: "bed-single",
218
+ name: "Single Bed",
219
+ category: "beds",
220
+ icon: "bed",
221
+ width: 1,
222
+ depth: 2,
223
+ height: 0.55,
224
+ color: "#87CEEB",
225
+ tags: ["bedroom", "kids"],
226
+ stackable: false,
227
+ wallMounted: false,
228
+ price: 349
229
+ },
230
+ {
231
+ id: "bunk-bed",
232
+ name: "Bunk Bed",
233
+ category: "beds",
234
+ icon: "bed",
235
+ width: 1,
236
+ depth: 2,
237
+ height: 1.7,
238
+ color: "#BC8F8F",
239
+ tags: ["kids"],
240
+ stackable: false,
241
+ wallMounted: false,
242
+ price: 499
243
+ },
244
+ {
245
+ id: "crib",
246
+ name: "Baby Crib",
247
+ category: "beds",
248
+ icon: "bed",
249
+ width: 0.7,
250
+ depth: 1.3,
251
+ height: 1,
252
+ color: "#FFFAF0",
253
+ tags: ["nursery"],
254
+ stackable: false,
255
+ wallMounted: false,
256
+ price: 299
257
+ },
258
+ // Storage
259
+ {
260
+ id: "bookshelf",
261
+ name: "Bookshelf",
262
+ category: "storage",
263
+ icon: "book",
264
+ width: 0.8,
265
+ depth: 0.35,
266
+ height: 1.8,
267
+ color: "#8B6914",
268
+ tags: ["living", "office"],
269
+ stackable: false,
270
+ wallMounted: false,
271
+ price: 229
272
+ },
273
+ {
274
+ id: "wardrobe",
275
+ name: "Wardrobe",
276
+ category: "storage",
277
+ icon: "door",
278
+ width: 1.2,
279
+ depth: 0.6,
280
+ height: 2,
281
+ color: "#A0522D",
282
+ tags: ["bedroom"],
283
+ stackable: false,
284
+ wallMounted: false,
285
+ price: 449
286
+ },
287
+ {
288
+ id: "tv-unit",
289
+ name: "TV Unit",
290
+ category: "storage",
291
+ icon: "monitor",
292
+ width: 1.6,
293
+ depth: 0.45,
294
+ height: 0.55,
295
+ color: "#36454F",
296
+ tags: ["living"],
297
+ stackable: false,
298
+ wallMounted: false,
299
+ price: 329
300
+ },
301
+ {
302
+ id: "dresser",
303
+ name: "Dresser",
304
+ category: "storage",
305
+ icon: "archive",
306
+ width: 1,
307
+ depth: 0.5,
308
+ height: 0.85,
309
+ color: "#DEB887",
310
+ tags: ["bedroom"],
311
+ stackable: false,
312
+ wallMounted: false,
313
+ price: 279
314
+ },
315
+ {
316
+ id: "shelf-wall",
317
+ name: "Wall Shelf",
318
+ category: "storage",
319
+ icon: "ruler",
320
+ width: 0.8,
321
+ depth: 0.2,
322
+ height: 0.03,
323
+ color: "#8B6914",
324
+ tags: ["any"],
325
+ stackable: false,
326
+ wallMounted: true,
327
+ price: 49
328
+ },
329
+ // Lighting
330
+ {
331
+ id: "floor-lamp",
332
+ name: "Floor Lamp",
333
+ category: "lighting",
334
+ icon: "lightbulb",
335
+ width: 0.4,
336
+ depth: 0.4,
337
+ height: 1.7,
338
+ color: "#FFD700",
339
+ tags: ["living"],
340
+ stackable: false,
341
+ wallMounted: false,
342
+ price: 119
343
+ },
344
+ {
345
+ id: "table-lamp",
346
+ name: "Table Lamp",
347
+ category: "lighting",
348
+ icon: "lightbulb",
349
+ width: 0.3,
350
+ depth: 0.3,
351
+ height: 0.5,
352
+ color: "#FAFAD2",
353
+ tags: ["bedroom", "living"],
354
+ stackable: false,
355
+ wallMounted: false,
356
+ price: 59
357
+ },
358
+ {
359
+ id: "ceiling-fan",
360
+ name: "Ceiling Fan",
361
+ category: "lighting",
362
+ icon: "refresh",
363
+ width: 1.2,
364
+ depth: 1.2,
365
+ height: 0.35,
366
+ color: "#C0C0C0",
367
+ tags: ["any"],
368
+ stackable: false,
369
+ wallMounted: false,
370
+ price: 179
371
+ },
372
+ {
373
+ id: "pendant",
374
+ name: "Pendant Light",
375
+ category: "lighting",
376
+ icon: "lightbulb",
377
+ width: 0.4,
378
+ depth: 0.4,
379
+ height: 0.6,
380
+ color: "#FFD700",
381
+ tags: ["kitchen", "dining"],
382
+ stackable: false,
383
+ wallMounted: false,
384
+ price: 149
385
+ },
386
+ // Appliances
387
+ {
388
+ id: "fridge",
389
+ name: "Refrigerator",
390
+ category: "appliances",
391
+ icon: "box",
392
+ width: 0.7,
393
+ depth: 0.7,
394
+ height: 1.8,
395
+ color: "#C0C0C0",
396
+ tags: ["kitchen"],
397
+ stackable: false,
398
+ wallMounted: false,
399
+ price: 999
400
+ },
401
+ {
402
+ id: "stove",
403
+ name: "Stove/Oven",
404
+ category: "appliances",
405
+ icon: "utensils",
406
+ width: 0.6,
407
+ depth: 0.6,
408
+ height: 0.9,
409
+ color: "#696969",
410
+ tags: ["kitchen"],
411
+ stackable: false,
412
+ wallMounted: false,
413
+ price: 799
414
+ },
415
+ {
416
+ id: "dishwasher",
417
+ name: "Dishwasher",
418
+ category: "appliances",
419
+ icon: "utensils",
420
+ width: 0.6,
421
+ depth: 0.6,
422
+ height: 0.85,
423
+ color: "#C0C0C0",
424
+ tags: ["kitchen"],
425
+ stackable: false,
426
+ wallMounted: false,
427
+ price: 549
428
+ },
429
+ {
430
+ id: "washer",
431
+ name: "Washing Machine",
432
+ category: "appliances",
433
+ icon: "box",
434
+ width: 0.6,
435
+ depth: 0.6,
436
+ height: 0.85,
437
+ color: "#f5f5f5",
438
+ tags: ["laundry"],
439
+ stackable: false,
440
+ wallMounted: false,
441
+ price: 599
442
+ },
443
+ {
444
+ id: "microwave",
445
+ name: "Microwave",
446
+ category: "appliances",
447
+ icon: "music",
448
+ width: 0.5,
449
+ depth: 0.4,
450
+ height: 0.3,
451
+ color: "#333333",
452
+ tags: ["kitchen"],
453
+ stackable: true,
454
+ wallMounted: false,
455
+ price: 149
456
+ },
457
+ // Bathroom
458
+ {
459
+ id: "toilet",
460
+ name: "Toilet",
461
+ category: "bathroom",
462
+ icon: "droplet",
463
+ width: 0.4,
464
+ depth: 0.7,
465
+ height: 0.75,
466
+ color: "#FFFFF0",
467
+ tags: ["bathroom"],
468
+ stackable: false,
469
+ wallMounted: false,
470
+ price: 199
471
+ },
472
+ {
473
+ id: "bathtub",
474
+ name: "Bathtub",
475
+ category: "bathroom",
476
+ icon: "droplet",
477
+ width: 0.75,
478
+ depth: 1.7,
479
+ height: 0.6,
480
+ color: "#FFFFF0",
481
+ tags: ["bathroom"],
482
+ stackable: false,
483
+ wallMounted: false,
484
+ price: 599
485
+ },
486
+ {
487
+ id: "shower",
488
+ name: "Shower Cabin",
489
+ category: "bathroom",
490
+ icon: "droplet",
491
+ width: 0.9,
492
+ depth: 0.9,
493
+ height: 2.1,
494
+ color: "#E0FFFF",
495
+ tags: ["bathroom"],
496
+ stackable: false,
497
+ wallMounted: false,
498
+ price: 449
499
+ },
500
+ {
501
+ id: "vanity",
502
+ name: "Bathroom Vanity",
503
+ category: "bathroom",
504
+ icon: "copy",
505
+ width: 0.8,
506
+ depth: 0.5,
507
+ height: 0.85,
508
+ color: "#FFFFF0",
509
+ tags: ["bathroom"],
510
+ stackable: false,
511
+ wallMounted: false,
512
+ price: 349
513
+ },
514
+ {
515
+ id: "sink-kitchen",
516
+ name: "Kitchen Sink",
517
+ category: "kitchen",
518
+ icon: "droplet",
519
+ width: 0.6,
520
+ depth: 0.5,
521
+ height: 0.85,
522
+ color: "#C0C0C0",
523
+ tags: ["kitchen"],
524
+ stackable: false,
525
+ wallMounted: false,
526
+ price: 199
527
+ },
528
+ // Decor
529
+ {
530
+ id: "painting-large",
531
+ name: "Large Painting",
532
+ category: "decor",
533
+ icon: "image",
534
+ width: 1,
535
+ depth: 0.05,
536
+ height: 0.7,
537
+ color: "#B8860B",
538
+ tags: ["any"],
539
+ stackable: false,
540
+ wallMounted: true,
541
+ price: 89
542
+ },
543
+ {
544
+ id: "mirror",
545
+ name: "Wall Mirror",
546
+ category: "decor",
547
+ icon: "copy",
548
+ width: 0.6,
549
+ depth: 0.03,
550
+ height: 0.9,
551
+ color: "#e0e0e0",
552
+ tags: ["bathroom", "hallway"],
553
+ stackable: false,
554
+ wallMounted: true,
555
+ price: 69
556
+ },
557
+ {
558
+ id: "clock",
559
+ name: "Wall Clock",
560
+ category: "decor",
561
+ icon: "clock",
562
+ width: 0.3,
563
+ depth: 0.05,
564
+ height: 0.3,
565
+ color: "#333333",
566
+ tags: ["any"],
567
+ stackable: false,
568
+ wallMounted: true,
569
+ price: 39
570
+ },
571
+ // Plants
572
+ {
573
+ id: "plant-large",
574
+ name: "Large Plant",
575
+ category: "plants",
576
+ icon: "tree",
577
+ width: 0.5,
578
+ depth: 0.5,
579
+ height: 1.4,
580
+ color: "#228B22",
581
+ tags: ["any"],
582
+ stackable: false,
583
+ wallMounted: false,
584
+ price: 49
585
+ },
586
+ {
587
+ id: "plant-small",
588
+ name: "Small Plant",
589
+ category: "plants",
590
+ icon: "tree",
591
+ width: 0.2,
592
+ depth: 0.2,
593
+ height: 0.35,
594
+ color: "#2E8B57",
595
+ tags: ["any"],
596
+ stackable: true,
597
+ wallMounted: false,
598
+ price: 19
599
+ },
600
+ {
601
+ id: "flower-vase",
602
+ name: "Flower Vase",
603
+ category: "plants",
604
+ icon: "tree",
605
+ width: 0.15,
606
+ depth: 0.15,
607
+ height: 0.35,
608
+ color: "#FF69B4",
609
+ tags: ["decor"],
610
+ stackable: true,
611
+ wallMounted: false,
612
+ price: 25
613
+ },
614
+ // Electronics
615
+ {
616
+ id: "tv-65",
617
+ name: '65" TV',
618
+ category: "electronics",
619
+ icon: "monitor",
620
+ width: 1.45,
621
+ depth: 0.08,
622
+ height: 0.85,
623
+ color: "#1a1a1a",
624
+ tags: ["living"],
625
+ stackable: false,
626
+ wallMounted: true,
627
+ price: 799
628
+ },
629
+ {
630
+ id: "tv-50",
631
+ name: '50" TV',
632
+ category: "electronics",
633
+ icon: "monitor",
634
+ width: 1.12,
635
+ depth: 0.08,
636
+ height: 0.65,
637
+ color: "#1a1a1a",
638
+ tags: ["living", "bedroom"],
639
+ stackable: false,
640
+ wallMounted: true,
641
+ price: 449
642
+ },
643
+ {
644
+ id: "computer",
645
+ name: "Desktop Computer",
646
+ category: "electronics",
647
+ icon: "monitor",
648
+ width: 0.55,
649
+ depth: 0.3,
650
+ height: 0.45,
651
+ color: "#2F4F4F",
652
+ tags: ["office"],
653
+ stackable: false,
654
+ wallMounted: false,
655
+ price: 999
656
+ },
657
+ // Rugs
658
+ {
659
+ id: "rug-large",
660
+ name: "Large Area Rug",
661
+ category: "rugs",
662
+ icon: "box",
663
+ width: 2.5,
664
+ depth: 3.5,
665
+ height: 0.02,
666
+ color: "#8B4513",
667
+ tags: ["living"],
668
+ stackable: false,
669
+ wallMounted: false,
670
+ price: 199
671
+ },
672
+ {
673
+ id: "rug-round",
674
+ name: "Round Rug",
675
+ category: "rugs",
676
+ icon: "circle",
677
+ width: 1.5,
678
+ depth: 1.5,
679
+ height: 0.02,
680
+ color: "#CD853F",
681
+ tags: ["any"],
682
+ stackable: false,
683
+ wallMounted: false,
684
+ price: 129
685
+ },
686
+ // Outdoor
687
+ {
688
+ id: "patio-table",
689
+ name: "Patio Table",
690
+ category: "outdoor",
691
+ icon: "cloud",
692
+ width: 1,
693
+ depth: 1,
694
+ height: 0.72,
695
+ color: "#808080",
696
+ tags: ["outdoor"],
697
+ stackable: false,
698
+ wallMounted: false,
699
+ price: 249
700
+ },
701
+ {
702
+ id: "patio-chair",
703
+ name: "Patio Chair",
704
+ category: "outdoor",
705
+ icon: "chair",
706
+ width: 0.55,
707
+ depth: 0.55,
708
+ height: 0.85,
709
+ color: "#808080",
710
+ tags: ["outdoor"],
711
+ stackable: true,
712
+ wallMounted: false,
713
+ price: 99
714
+ },
715
+ {
716
+ id: "bbq-grill",
717
+ name: "BBQ Grill",
718
+ category: "outdoor",
719
+ icon: "zap",
720
+ width: 1.2,
721
+ depth: 0.6,
722
+ height: 1.1,
723
+ color: "#333333",
724
+ tags: ["outdoor"],
725
+ stackable: false,
726
+ wallMounted: false,
727
+ price: 399
728
+ },
729
+ // Kitchen
730
+ {
731
+ id: "counter",
732
+ name: "Kitchen Counter",
733
+ category: "kitchen",
734
+ icon: "box",
735
+ width: 0.6,
736
+ depth: 0.6,
737
+ height: 0.9,
738
+ color: "#D2B48C",
739
+ tags: ["kitchen"],
740
+ stackable: false,
741
+ wallMounted: false,
742
+ price: 199
743
+ },
744
+ {
745
+ id: "island",
746
+ name: "Kitchen Island",
747
+ category: "kitchen",
748
+ icon: "box",
749
+ width: 1.5,
750
+ depth: 0.8,
751
+ height: 0.9,
752
+ color: "#DCDCDC",
753
+ tags: ["kitchen"],
754
+ stackable: false,
755
+ wallMounted: false,
756
+ price: 599
757
+ },
758
+ {
759
+ id: "cabinet-upper",
760
+ name: "Upper Cabinet",
761
+ category: "kitchen",
762
+ icon: "archive",
763
+ width: 0.6,
764
+ depth: 0.35,
765
+ height: 0.7,
766
+ color: "#F5DEB3",
767
+ tags: ["kitchen"],
768
+ stackable: false,
769
+ wallMounted: true,
770
+ price: 149
771
+ },
772
+ // Office
773
+ {
774
+ id: "filing-cabinet",
775
+ name: "Filing Cabinet",
776
+ category: "office",
777
+ icon: "archive",
778
+ width: 0.4,
779
+ depth: 0.6,
780
+ height: 1,
781
+ color: "#808080",
782
+ tags: ["office"],
783
+ stackable: false,
784
+ wallMounted: false,
785
+ price: 129
786
+ },
787
+ {
788
+ id: "whiteboard",
789
+ name: "Whiteboard",
790
+ category: "office",
791
+ icon: "clipboard",
792
+ width: 1.2,
793
+ depth: 0.05,
794
+ height: 0.9,
795
+ color: "#ffffff",
796
+ tags: ["office"],
797
+ stackable: false,
798
+ wallMounted: true,
799
+ price: 99
800
+ }
811
801
  ];
812
802
  const FURNITURE_CATEGORIES = [
813
- { id: 'seating', name: 'Seating', icon: 'sofa' },
814
- { id: 'tables', name: 'Tables', icon: 'box' },
815
- { id: 'beds', name: 'Beds', icon: 'bed' },
816
- { id: 'storage', name: 'Storage', icon: 'book' },
817
- { id: 'lighting', name: 'Lighting', icon: 'lightbulb' },
818
- { id: 'appliances', name: 'Appliances', icon: 'box' },
819
- { id: 'bathroom', name: 'Bathroom', icon: 'droplet' },
820
- { id: 'kitchen', name: 'Kitchen', icon: 'utensils' },
821
- { id: 'decor', name: 'Decor', icon: 'image' },
822
- { id: 'plants', name: 'Plants', icon: 'tree' },
823
- { id: 'electronics', name: 'Electronics', icon: 'monitor' },
824
- { id: 'rugs', name: 'Rugs', icon: 'box' },
825
- { id: 'outdoor', name: 'Outdoor', icon: 'cloud' },
826
- { id: 'office', name: 'Office', icon: 'monitor' },
803
+ { id: "seating", name: "Seating", icon: "sofa" },
804
+ { id: "tables", name: "Tables", icon: "box" },
805
+ { id: "beds", name: "Beds", icon: "bed" },
806
+ { id: "storage", name: "Storage", icon: "book" },
807
+ { id: "lighting", name: "Lighting", icon: "lightbulb" },
808
+ { id: "appliances", name: "Appliances", icon: "box" },
809
+ { id: "bathroom", name: "Bathroom", icon: "droplet" },
810
+ { id: "kitchen", name: "Kitchen", icon: "utensils" },
811
+ { id: "decor", name: "Decor", icon: "image" },
812
+ { id: "plants", name: "Plants", icon: "tree" },
813
+ { id: "electronics", name: "Electronics", icon: "monitor" },
814
+ { id: "rugs", name: "Rugs", icon: "box" },
815
+ { id: "outdoor", name: "Outdoor", icon: "cloud" },
816
+ { id: "office", name: "Office", icon: "monitor" }
827
817
  ];
828
- /* ════════════════════════════════════════════════════════════════
829
- ROOM PRESETS
830
- ════════════════════════════════════════════════════════════════ */
831
818
  const ROOM_PRESETS = [
832
- {
833
- id: 'living-modern',
834
- name: 'Modern Living Room',
835
- icon: 'sofa',
836
- items: [
837
- { itemId: 'sofa-3seat', x: 0, z: -1.5, rotation: 0 },
838
- { itemId: 'coffee-table', x: 0, z: 0, rotation: 0 },
839
- { itemId: 'tv-unit', x: 0, z: 2, rotation: 180 },
840
- { itemId: 'tv-65', x: 0, z: 2.2, rotation: 180 },
841
- { itemId: 'floor-lamp', x: -1.5, z: -1.5, rotation: 0 },
842
- { itemId: 'rug-large', x: 0, z: 0, rotation: 0 },
843
- { itemId: 'plant-large', x: 1.8, z: -1.8, rotation: 0 },
844
- ],
845
- },
846
- {
847
- id: 'bedroom-master',
848
- name: 'Master Bedroom',
849
- icon: 'bed',
850
- items: [
851
- { itemId: 'bed-queen', x: 0, z: -0.5, rotation: 0 },
852
- { itemId: 'side-table', x: -1.1, z: -0.5, rotation: 0 },
853
- { itemId: 'side-table', x: 1.1, z: -0.5, rotation: 0 },
854
- { itemId: 'table-lamp', x: -1.1, z: -0.5, rotation: 0 },
855
- { itemId: 'table-lamp', x: 1.1, z: -0.5, rotation: 0 },
856
- { itemId: 'wardrobe', x: -2, z: 1.5, rotation: 90 },
857
- { itemId: 'dresser', x: 2, z: 1, rotation: -90 },
858
- ],
859
- },
860
- {
861
- id: 'kitchen-l',
862
- name: 'L-Shaped Kitchen',
863
- icon: 'utensils',
864
- items: [
865
- { itemId: 'counter', x: -1.5, z: -2, rotation: 0 },
866
- { itemId: 'counter', x: -0.9, z: -2, rotation: 0 },
867
- { itemId: 'sink-kitchen', x: -0.3, z: -2, rotation: 0 },
868
- { itemId: 'counter', x: 0.3, z: -2, rotation: 0 },
869
- { itemId: 'stove', x: 0.9, z: -2, rotation: 0 },
870
- { itemId: 'counter', x: 1.5, z: -2, rotation: 0 },
871
- { itemId: 'fridge', x: 1.5, z: -1.2, rotation: 90 },
872
- { itemId: 'island', x: 0, z: 0, rotation: 0 },
873
- { itemId: 'bar-stool', x: -0.4, z: 0.6, rotation: 0 },
874
- { itemId: 'bar-stool', x: 0.4, z: 0.6, rotation: 0 },
875
- ],
876
- },
877
- {
878
- id: 'bathroom-main',
879
- name: 'Main Bathroom',
880
- icon: 'droplet',
881
- items: [
882
- { itemId: 'bathtub', x: -0.6, z: -1, rotation: 0 },
883
- { itemId: 'vanity', x: 0.8, z: -1.5, rotation: 90 },
884
- { itemId: 'toilet', x: 0.8, z: 0, rotation: 90 },
885
- { itemId: 'mirror', x: 0.8, z: -1.5, rotation: 90 },
886
- ],
887
- },
888
- {
889
- id: 'office-home',
890
- name: 'Home Office',
891
- icon: 'monitor',
892
- items: [
893
- { itemId: 'desk', x: 0, z: -1.2, rotation: 0 },
894
- { itemId: 'office-chair', x: 0, z: -0.3, rotation: 0 },
895
- { itemId: 'computer', x: 0, z: -1.3, rotation: 0 },
896
- { itemId: 'bookshelf', x: 1.5, z: -1.5, rotation: 90 },
897
- { itemId: 'filing-cabinet', x: -1.2, z: -1.5, rotation: 0 },
898
- { itemId: 'plant-small', x: 0.6, z: -1.3, rotation: 0 },
899
- ],
900
- },
901
- {
902
- id: 'dining-formal',
903
- name: 'Formal Dining Room',
904
- icon: 'utensils',
905
- items: [
906
- { itemId: 'dining-table-6', x: 0, z: 0, rotation: 0 },
907
- { itemId: 'dining-chair', x: -0.7, z: -0.6, rotation: 0 },
908
- { itemId: 'dining-chair', x: 0, z: -0.6, rotation: 0 },
909
- { itemId: 'dining-chair', x: 0.7, z: -0.6, rotation: 0 },
910
- { itemId: 'dining-chair', x: -0.7, z: 0.6, rotation: 180 },
911
- { itemId: 'dining-chair', x: 0, z: 0.6, rotation: 180 },
912
- { itemId: 'dining-chair', x: 0.7, z: 0.6, rotation: 180 },
913
- { itemId: 'console-table', x: -2, z: 0, rotation: 90 },
914
- { itemId: 'painting-large', x: -2.5, z: 0, rotation: 90 },
915
- ],
916
- },
819
+ {
820
+ id: "living-modern",
821
+ name: "Modern Living Room",
822
+ icon: "sofa",
823
+ items: [
824
+ { itemId: "sofa-3seat", x: 0, z: -1.5, rotation: 0 },
825
+ { itemId: "coffee-table", x: 0, z: 0, rotation: 0 },
826
+ { itemId: "tv-unit", x: 0, z: 2, rotation: 180 },
827
+ { itemId: "tv-65", x: 0, z: 2.2, rotation: 180 },
828
+ { itemId: "floor-lamp", x: -1.5, z: -1.5, rotation: 0 },
829
+ { itemId: "rug-large", x: 0, z: 0, rotation: 0 },
830
+ { itemId: "plant-large", x: 1.8, z: -1.8, rotation: 0 }
831
+ ]
832
+ },
833
+ {
834
+ id: "bedroom-master",
835
+ name: "Master Bedroom",
836
+ icon: "bed",
837
+ items: [
838
+ { itemId: "bed-queen", x: 0, z: -0.5, rotation: 0 },
839
+ { itemId: "side-table", x: -1.1, z: -0.5, rotation: 0 },
840
+ { itemId: "side-table", x: 1.1, z: -0.5, rotation: 0 },
841
+ { itemId: "table-lamp", x: -1.1, z: -0.5, rotation: 0 },
842
+ { itemId: "table-lamp", x: 1.1, z: -0.5, rotation: 0 },
843
+ { itemId: "wardrobe", x: -2, z: 1.5, rotation: 90 },
844
+ { itemId: "dresser", x: 2, z: 1, rotation: -90 }
845
+ ]
846
+ },
847
+ {
848
+ id: "kitchen-l",
849
+ name: "L-Shaped Kitchen",
850
+ icon: "utensils",
851
+ items: [
852
+ { itemId: "counter", x: -1.5, z: -2, rotation: 0 },
853
+ { itemId: "counter", x: -0.9, z: -2, rotation: 0 },
854
+ { itemId: "sink-kitchen", x: -0.3, z: -2, rotation: 0 },
855
+ { itemId: "counter", x: 0.3, z: -2, rotation: 0 },
856
+ { itemId: "stove", x: 0.9, z: -2, rotation: 0 },
857
+ { itemId: "counter", x: 1.5, z: -2, rotation: 0 },
858
+ { itemId: "fridge", x: 1.5, z: -1.2, rotation: 90 },
859
+ { itemId: "island", x: 0, z: 0, rotation: 0 },
860
+ { itemId: "bar-stool", x: -0.4, z: 0.6, rotation: 0 },
861
+ { itemId: "bar-stool", x: 0.4, z: 0.6, rotation: 0 }
862
+ ]
863
+ },
864
+ {
865
+ id: "bathroom-main",
866
+ name: "Main Bathroom",
867
+ icon: "droplet",
868
+ items: [
869
+ { itemId: "bathtub", x: -0.6, z: -1, rotation: 0 },
870
+ { itemId: "vanity", x: 0.8, z: -1.5, rotation: 90 },
871
+ { itemId: "toilet", x: 0.8, z: 0, rotation: 90 },
872
+ { itemId: "mirror", x: 0.8, z: -1.5, rotation: 90 }
873
+ ]
874
+ },
875
+ {
876
+ id: "office-home",
877
+ name: "Home Office",
878
+ icon: "monitor",
879
+ items: [
880
+ { itemId: "desk", x: 0, z: -1.2, rotation: 0 },
881
+ { itemId: "office-chair", x: 0, z: -0.3, rotation: 0 },
882
+ { itemId: "computer", x: 0, z: -1.3, rotation: 0 },
883
+ { itemId: "bookshelf", x: 1.5, z: -1.5, rotation: 90 },
884
+ { itemId: "filing-cabinet", x: -1.2, z: -1.5, rotation: 0 },
885
+ { itemId: "plant-small", x: 0.6, z: -1.3, rotation: 0 }
886
+ ]
887
+ },
888
+ {
889
+ id: "dining-formal",
890
+ name: "Formal Dining Room",
891
+ icon: "utensils",
892
+ items: [
893
+ { itemId: "dining-table-6", x: 0, z: 0, rotation: 0 },
894
+ { itemId: "dining-chair", x: -0.7, z: -0.6, rotation: 0 },
895
+ { itemId: "dining-chair", x: 0, z: -0.6, rotation: 0 },
896
+ { itemId: "dining-chair", x: 0.7, z: -0.6, rotation: 0 },
897
+ { itemId: "dining-chair", x: -0.7, z: 0.6, rotation: 180 },
898
+ { itemId: "dining-chair", x: 0, z: 0.6, rotation: 180 },
899
+ { itemId: "dining-chair", x: 0.7, z: 0.6, rotation: 180 },
900
+ { itemId: "console-table", x: -2, z: 0, rotation: 90 },
901
+ { itemId: "painting-large", x: -2.5, z: 0, rotation: 90 }
902
+ ]
903
+ }
917
904
  ];
918
- /* ════════════════════════════════════════════════════════════════
919
- FURNITURE MESH CREATION
920
- ════════════════════════════════════════════════════════════════ */
921
905
  function createFurnitureMesh(item, color) {
922
- const geometry = new THREE.BoxGeometry(item.width, item.height, item.depth);
923
- const material = new THREE.MeshStandardMaterial({
924
- color: color || item.color,
925
- roughness: 0.7,
926
- metalness: 0.1,
927
- });
928
- const mesh = new THREE.Mesh(geometry, material);
929
- mesh.name = item.name;
930
- mesh.position.y = item.height / 2;
931
- mesh.castShadow = true;
932
- mesh.receiveShadow = true;
933
- mesh.userData = { simsType: 'furniture', itemData: item };
934
- return mesh;
906
+ const geometry = new THREE.BoxGeometry(item.width, item.height, item.depth);
907
+ const material = new THREE.MeshStandardMaterial({
908
+ color: color || item.color,
909
+ roughness: 0.7,
910
+ metalness: 0.1
911
+ });
912
+ const mesh = new THREE.Mesh(geometry, material);
913
+ mesh.name = item.name;
914
+ mesh.position.y = item.height / 2;
915
+ mesh.castShadow = true;
916
+ mesh.receiveShadow = true;
917
+ mesh.userData = { simsType: "furniture", itemData: item };
918
+ return mesh;
935
919
  }
936
920
  function placeFurnitureInScene(scene, item, position, rotation = 0, gridSize = 0.5, snapEnabled = true) {
937
- const mesh = createFurnitureMesh(item);
938
- const pos = snapEnabled
939
- ? new THREE.Vector3(Math.round(position.x / gridSize) * gridSize, position.y, Math.round(position.z / gridSize) * gridSize)
940
- : position.clone();
941
- mesh.position.set(pos.x, item.height / 2, pos.z);
942
- mesh.rotation.y = (rotation * Math.PI) / 180;
943
- const id = `placed_${item.id}_${Date.now()}`;
944
- mesh.userData.placedId = id;
945
- scene.add(mesh);
946
- return {
947
- id,
948
- itemId: item.id,
949
- position: pos,
950
- rotation,
951
- scale: new THREE.Vector3(1, 1, 1),
952
- locked: false,
953
- };
921
+ const mesh = createFurnitureMesh(item);
922
+ const pos = snapEnabled ? new THREE.Vector3(
923
+ Math.round(position.x / gridSize) * gridSize,
924
+ position.y,
925
+ Math.round(position.z / gridSize) * gridSize
926
+ ) : position.clone();
927
+ mesh.position.set(pos.x, item.height / 2, pos.z);
928
+ mesh.rotation.y = rotation * Math.PI / 180;
929
+ const id = `placed_${item.id}_${Date.now()}`;
930
+ mesh.userData.placedId = id;
931
+ scene.add(mesh);
932
+ return {
933
+ id,
934
+ itemId: item.id,
935
+ position: pos,
936
+ rotation,
937
+ scale: new THREE.Vector3(1, 1, 1),
938
+ locked: false
939
+ };
954
940
  }
955
941
  function removeFurnitureFromScene(scene, placedId) {
956
- const obj = scene.children.find((c) => { var _a; return ((_a = c.userData) === null || _a === void 0 ? void 0 : _a.placedId) === placedId; });
957
- if (obj) {
958
- scene.remove(obj);
959
- if (obj instanceof THREE.Mesh) {
960
- obj.geometry.dispose();
961
- if (Array.isArray(obj.material)) {
962
- obj.material.forEach((m) => m.dispose());
963
- }
964
- else {
965
- obj.material.dispose();
966
- }
967
- }
942
+ const obj = scene.children.find((c) => c.userData?.placedId === placedId);
943
+ if (obj) {
944
+ scene.remove(obj);
945
+ if (obj instanceof THREE.Mesh) {
946
+ obj.geometry.dispose();
947
+ if (Array.isArray(obj.material)) {
948
+ obj.material.forEach((m) => m.dispose());
949
+ } else {
950
+ obj.material.dispose();
951
+ }
968
952
  }
953
+ }
969
954
  }
970
955
  function rotatePlacedItem(scene, placedId, degrees) {
971
- const obj = scene.children.find((c) => { var _a; return ((_a = c.userData) === null || _a === void 0 ? void 0 : _a.placedId) === placedId; });
972
- if (obj) {
973
- obj.rotation.y += (degrees * Math.PI) / 180;
974
- }
956
+ const obj = scene.children.find((c) => c.userData?.placedId === placedId);
957
+ if (obj) {
958
+ obj.rotation.y += degrees * Math.PI / 180;
959
+ }
975
960
  }
976
961
  function resizePlacedItem(scene, placedId, scale) {
977
- const obj = scene.children.find((c) => { var _a; return ((_a = c.userData) === null || _a === void 0 ? void 0 : _a.placedId) === placedId; });
978
- if (obj) {
979
- obj.scale.copy(scale);
980
- }
962
+ const obj = scene.children.find((c) => c.userData?.placedId === placedId);
963
+ if (obj) {
964
+ obj.scale.copy(scale);
965
+ }
981
966
  }
982
- /* ════════════════════════════════════════════════════════════════
983
- DRAG & DROP HELPERS
984
- ════════════════════════════════════════════════════════════════ */
985
967
  function createDragPreview(item) {
986
- const geometry = new THREE.BoxGeometry(item.width, item.height, item.depth);
987
- const material = new THREE.MeshStandardMaterial({
988
- color: item.color,
989
- transparent: true,
990
- opacity: 0.5,
991
- depthWrite: false,
992
- });
993
- const mesh = new THREE.Mesh(geometry, material);
994
- mesh.name = '__dragPreview';
995
- mesh.position.y = item.height / 2;
996
- return mesh;
968
+ const geometry = new THREE.BoxGeometry(item.width, item.height, item.depth);
969
+ const material = new THREE.MeshStandardMaterial({
970
+ color: item.color,
971
+ transparent: true,
972
+ opacity: 0.5,
973
+ depthWrite: false
974
+ });
975
+ const mesh = new THREE.Mesh(geometry, material);
976
+ mesh.name = "__dragPreview";
977
+ mesh.position.y = item.height / 2;
978
+ return mesh;
997
979
  }
998
980
  function getFloorIntersection(raycaster, camera, mouse, floorY = 0) {
999
- raycaster.setFromCamera(mouse, camera);
1000
- const plane = new THREE.Plane(new THREE.Vector3(0, 1, 0), -floorY);
1001
- const target = new THREE.Vector3();
1002
- const hit = raycaster.ray.intersectPlane(plane, target);
1003
- return hit;
981
+ raycaster.setFromCamera(mouse, camera);
982
+ const plane = new THREE.Plane(new THREE.Vector3(0, 1, 0), -floorY);
983
+ const target = new THREE.Vector3();
984
+ const hit = raycaster.ray.intersectPlane(plane, target);
985
+ return hit;
1004
986
  }
1005
- /* ════════════════════════════════════════════════════════════════
1006
- COLLISION CHECK
1007
- ════════════════════════════════════════════════════════════════ */
1008
987
  function checkFurnitureCollision(item, position, rotation, existing, catalog) {
1009
- const bounds = getRotatedBounds(item, position, rotation);
1010
- for (const placed of existing) {
1011
- const existingItem = catalog.find((c) => c.id === placed.itemId);
1012
- if (!existingItem) {
1013
- continue;
1014
- }
1015
- const existBounds = getRotatedBounds(existingItem, placed.position, placed.rotation);
1016
- if (boundsOverlap(bounds, existBounds)) {
1017
- return true;
1018
- }
988
+ const bounds = getRotatedBounds(item, position, rotation);
989
+ for (const placed of existing) {
990
+ const existingItem = catalog.find((c) => c.id === placed.itemId);
991
+ if (!existingItem) {
992
+ continue;
993
+ }
994
+ const existBounds = getRotatedBounds(existingItem, placed.position, placed.rotation);
995
+ if (boundsOverlap(bounds, existBounds)) {
996
+ return true;
1019
997
  }
1020
- return false;
998
+ }
999
+ return false;
1021
1000
  }
1022
1001
  function getRotatedBounds(item, pos, rotation) {
1023
- const rad = (rotation * Math.PI) / 180;
1024
- const cos = Math.abs(Math.cos(rad));
1025
- const sin = Math.abs(Math.sin(rad));
1026
- const w = item.width * cos + item.depth * sin;
1027
- const d = item.width * sin + item.depth * cos;
1028
- return {
1029
- minX: pos.x - w / 2,
1030
- maxX: pos.x + w / 2,
1031
- minZ: pos.z - d / 2,
1032
- maxZ: pos.z + d / 2,
1033
- };
1002
+ const rad = rotation * Math.PI / 180;
1003
+ const cos = Math.abs(Math.cos(rad));
1004
+ const sin = Math.abs(Math.sin(rad));
1005
+ const w = item.width * cos + item.depth * sin;
1006
+ const d = item.width * sin + item.depth * cos;
1007
+ return {
1008
+ minX: pos.x - w / 2,
1009
+ maxX: pos.x + w / 2,
1010
+ minZ: pos.z - d / 2,
1011
+ maxZ: pos.z + d / 2
1012
+ };
1034
1013
  }
1035
1014
  function boundsOverlap(a, b) {
1036
- return a.minX < b.maxX && a.maxX > b.minX && a.minZ < b.maxZ && a.maxZ > b.minZ;
1015
+ return a.minX < b.maxX && a.maxX > b.minX && a.minZ < b.maxZ && a.maxZ > b.minZ;
1037
1016
  }
1038
- /* ════════════════════════════════════════════════════════════════
1039
- LAYOUT APPLICATION
1040
- ════════════════════════════════════════════════════════════════ */
1041
1017
  function applyRoomLayout(scene, layout, offset = new THREE.Vector3(0, 0, 0)) {
1042
- const placed = [];
1043
- for (const layoutItem of layout.items) {
1044
- const item = FURNITURE_CATALOG.find((f) => f.id === layoutItem.itemId);
1045
- if (!item) {
1046
- continue;
1047
- }
1048
- const pos = new THREE.Vector3(layoutItem.x + offset.x, offset.y, layoutItem.z + offset.z);
1049
- placed.push(placeFurnitureInScene(scene, item, pos, layoutItem.rotation, 0.5, false));
1018
+ const placed = [];
1019
+ for (const layoutItem of layout.items) {
1020
+ const item = FURNITURE_CATALOG.find((f) => f.id === layoutItem.itemId);
1021
+ if (!item) {
1022
+ continue;
1050
1023
  }
1051
- return placed;
1024
+ const pos = new THREE.Vector3(layoutItem.x + offset.x, offset.y, layoutItem.z + offset.z);
1025
+ placed.push(placeFurnitureInScene(scene, item, pos, layoutItem.rotation, 0.5, false));
1026
+ }
1027
+ return placed;
1052
1028
  }
1053
- /* ════════════════════════════════════════════════════════════════
1054
- BUDGET CALCULATOR
1055
- ════════════════════════════════════════════════════════════════ */
1056
1029
  function calculateBudget(placed) {
1057
- const breakdown = [];
1058
- let total = 0;
1059
- for (const p of placed) {
1060
- const item = FURNITURE_CATALOG.find((f) => f.id === p.itemId);
1061
- if (item && item.price) {
1062
- breakdown.push({ name: item.name, price: item.price });
1063
- total += item.price;
1064
- }
1030
+ const breakdown = [];
1031
+ let total = 0;
1032
+ for (const p of placed) {
1033
+ const item = FURNITURE_CATALOG.find((f) => f.id === p.itemId);
1034
+ if (item && item.price) {
1035
+ breakdown.push({ name: item.name, price: item.price });
1036
+ total += item.price;
1065
1037
  }
1066
- return { total, breakdown };
1038
+ }
1039
+ return { total, breakdown };
1067
1040
  }
1068
-
1069
- export { FURNITURE_CATALOG, FURNITURE_CATEGORIES, ROOM_PRESETS, applyRoomLayout, calculateBudget, checkFurnitureCollision, createDragPreview, createFurnitureMesh, getFloorIntersection, placeFurnitureInScene, removeFurnitureFromScene, resizePlacedItem, rotatePlacedItem };
1041
+ export {
1042
+ FURNITURE_CATALOG,
1043
+ FURNITURE_CATEGORIES,
1044
+ ROOM_PRESETS,
1045
+ applyRoomLayout,
1046
+ calculateBudget,
1047
+ checkFurnitureCollision,
1048
+ createDragPreview,
1049
+ createFurnitureMesh,
1050
+ getFloorIntersection,
1051
+ placeFurnitureInScene,
1052
+ removeFurnitureFromScene,
1053
+ resizePlacedItem,
1054
+ rotatePlacedItem
1055
+ };