kitchen-simulator 4.4.0 → 4.4.2-dynamic-holes

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.
@@ -1,19 +1,13 @@
1
1
  import _extends from "@babel/runtime/helpers/esm/extends";
2
- import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
3
2
  import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutProperties";
4
- import _classCallCheck from "@babel/runtime/helpers/esm/classCallCheck";
5
- import _createClass from "@babel/runtime/helpers/esm/createClass";
6
- import _possibleConstructorReturn from "@babel/runtime/helpers/esm/possibleConstructorReturn";
7
- import _getPrototypeOf from "@babel/runtime/helpers/esm/getPrototypeOf";
8
- import _inherits from "@babel/runtime/helpers/esm/inherits";
9
- var _excluded = ["width", "height", "configData", "externalEvent", "onInternalEvent", "onError"];
10
- function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
11
- function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
3
+ import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
4
+ import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
5
+ var _excluded = ["width", "height", "configData", "externalEvent", "onInternalEvent", "onError", "holes"];
12
6
  function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }
13
7
  function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
14
8
  function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
15
- function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }
16
- function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }
9
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
10
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
17
11
  // LiteRenderer.jsx
18
12
  import React, { useCallback, useEffect, useMemo, useRef } from 'react';
19
13
  import PropTypes from 'prop-types';
@@ -79,48 +73,147 @@ function serializeError(err) {
79
73
  };
80
74
  }
81
75
  }
82
-
83
- /* ---------- Error Boundary that pushes into buffer ---------- */
84
- var ToolErrorBoundary = /*#__PURE__*/function (_React$Component) {
85
- function ToolErrorBoundary() {
86
- _classCallCheck(this, ToolErrorBoundary);
87
- return _callSuper(this, ToolErrorBoundary, arguments);
76
+ var INCH_TO_CM = 2.54;
77
+ var normalizeKey = function normalizeKey(value) {
78
+ return (value !== null && value !== void 0 ? value : '').toString().toLowerCase().replace(/[^a-z0-9]+/g, '');
79
+ };
80
+ var safeParseJson = function safeParseJson(value) {
81
+ if (!value) return null;
82
+ try {
83
+ return JSON.parse(value);
84
+ } catch (_unused3) {
85
+ return null;
88
86
  }
89
- _inherits(ToolErrorBoundary, _React$Component);
90
- return _createClass(ToolErrorBoundary, [{
91
- key: "componentDidCatch",
92
- value: function componentDidCatch(error, info) {
93
- var pushError = this.props.pushError;
94
- pushError({
95
- type: 'render-error',
96
- error: serializeError(error),
97
- info: {
98
- componentStack: info === null || info === void 0 ? void 0 : info.componentStack
99
- }
100
- });
101
- }
102
- }, {
103
- key: "render",
104
- value: function render() {
105
- return this.props.children;
87
+ };
88
+ var toCatalogLength = function toCatalogLength(value, prop) {
89
+ var _prop$defaultValue;
90
+ if (value == null) return null;
91
+ var unit = prop === null || prop === void 0 || (_prop$defaultValue = prop.defaultValue) === null || _prop$defaultValue === void 0 ? void 0 : _prop$defaultValue.unit;
92
+ if (unit && unit.toLowerCase() === 'in') return value;
93
+ return value * INCH_TO_CM;
94
+ };
95
+ var overrideLengthProperty = function overrideLengthProperty(prop, value) {
96
+ if (!prop || value == null) return prop;
97
+ var length = toCatalogLength(value, prop);
98
+ if (length == null) return prop;
99
+ return _objectSpread(_objectSpread({}, prop), {}, {
100
+ defaultValue: _objectSpread(_objectSpread({}, prop.defaultValue), {}, {
101
+ length: length
102
+ })
103
+ });
104
+ };
105
+ var findBaseHoleTemplate = function findBaseHoleTemplate(hole, templates) {
106
+ var target = normalizeKey(hole === null || hole === void 0 ? void 0 : hole.name);
107
+ if (!target) return null;
108
+ return templates.find(function (template) {
109
+ var _template$info, _template$info2;
110
+ var candidates = [template === null || template === void 0 ? void 0 : template.name, template === null || template === void 0 || (_template$info = template.info) === null || _template$info === void 0 ? void 0 : _template$info.title, template === null || template === void 0 || (_template$info2 = template.info) === null || _template$info2 === void 0 ? void 0 : _template$info2.description].map(normalizeKey);
111
+ return candidates.includes(target);
112
+ }) || null;
113
+ };
114
+ var buildHoleElementFromTemplate = function buildHoleElementFromTemplate(hole, base) {
115
+ var _base$info, _base$info2, _base$info3, _base$info4, _base$info5, _base$structure_json;
116
+ if (!hole || !base) return null;
117
+ var nextInfo = _objectSpread(_objectSpread({}, base.info), {}, {
118
+ title: hole.name || ((_base$info = base.info) === null || _base$info === void 0 ? void 0 : _base$info.title),
119
+ description: ((_base$info2 = base.info) === null || _base$info2 === void 0 ? void 0 : _base$info2.description) || hole.name || ((_base$info3 = base.info) === null || _base$info3 === void 0 ? void 0 : _base$info3.title),
120
+ image: hole.menu_thumbnail || ((_base$info4 = base.info) === null || _base$info4 === void 0 ? void 0 : _base$info4.image),
121
+ url: hole.gltf || ((_base$info5 = base.info) === null || _base$info5 === void 0 ? void 0 : _base$info5.url)
122
+ });
123
+ var nextProperties = _objectSpread({}, base.properties);
124
+ if (nextProperties.width) {
125
+ nextProperties.width = overrideLengthProperty(nextProperties.width, hole.width);
126
+ }
127
+ if (nextProperties.height) {
128
+ nextProperties.height = overrideLengthProperty(nextProperties.height, hole.height);
129
+ }
130
+ if (nextProperties.length) {
131
+ nextProperties.length = overrideLengthProperty(nextProperties.length, hole.length);
132
+ }
133
+ var customConfig = safeParseJson(hole.custom_config);
134
+ var customProps = (customConfig === null || customConfig === void 0 ? void 0 : customConfig.properties) || {};
135
+ Object.keys(customProps).forEach(function (key) {
136
+ if (!nextProperties[key]) return;
137
+ nextProperties[key] = overrideLengthProperty(nextProperties[key], customProps[key]);
138
+ });
139
+ return _objectSpread(_objectSpread({}, base), {}, {
140
+ name: hole.name || base.name,
141
+ info: nextInfo,
142
+ properties: nextProperties,
143
+ structure_json: _objectSpread(_objectSpread({}, base.structure_json || {}), {}, {
144
+ hole_id: hole.id || ((_base$structure_json = base.structure_json) === null || _base$structure_json === void 0 ? void 0 : _base$structure_json.hole_id)
145
+ })
146
+ });
147
+ };
148
+ var buildHoleElements = function buildHoleElements(holes) {
149
+ var categories = {
150
+ Doors: [],
151
+ Windows: []
152
+ };
153
+ var elements = [];
154
+ if (!Array.isArray(holes)) return {
155
+ elements: elements,
156
+ categories: categories
157
+ };
158
+ var templates = Object.values(Holes);
159
+ var usedNames = new Set();
160
+ holes.forEach(function (hole) {
161
+ var _base$info6;
162
+ if (!hole || hole.is_deleted) return;
163
+ var base = findBaseHoleTemplate(hole, templates);
164
+ if (!base) return;
165
+ var element = buildHoleElementFromTemplate(hole, base);
166
+ if (!element || !element.name || usedNames.has(element.name)) return;
167
+ usedNames.add(element.name);
168
+ elements.push(element);
169
+ var typeKey = normalizeKey(hole.type);
170
+ if (typeKey === 'window') {
171
+ categories.Windows.push(element);
172
+ } else if (typeKey === 'door') {
173
+ categories.Doors.push(element);
174
+ } else if ((_base$info6 = base.info) !== null && _base$info6 !== void 0 && (_base$info6 = _base$info6.tag) !== null && _base$info6 !== void 0 && _base$info6.includes('window')) {
175
+ categories.Windows.push(element);
176
+ } else {
177
+ categories.Doors.push(element);
106
178
  }
107
- }]);
108
- }(React.Component);
109
- ToolErrorBoundary.propTypes = {
110
- pushError: PropTypes.func.isRequired,
111
- children: PropTypes.any
179
+ });
180
+ return {
181
+ elements: elements,
182
+ categories: categories
183
+ };
112
184
  };
113
185
 
114
186
  // ----------------- catalog init -----------------
115
- function initCatalogOnce(catalog) {
187
+ function initCatalogOnce(catalog, holePayload) {
116
188
  if (!catalog) return;
117
- if (catalog.__ksInitialized) return;
118
- for (var x in Areas) catalog.registerElement(Areas[x]);
119
- for (var _x in Lines) catalog.registerElement(Lines[_x]);
120
- for (var _x2 in Holes) catalog.registerElement(Holes[_x2]);
121
- catalog.registerCategory('Windows', 'Windows', [Holes.windowClear, Holes.windowCross, Holes.windowDoubleHung, Holes.windowVertical]);
122
- catalog.registerCategory('Doors', 'Doors', [Holes.doorInterior, Holes.doorExterior, Holes.doorCloset, Holes.doorSliding, Holes.doorwayFramed, Holes.doorwayFrameless]);
123
- catalog.__ksInitialized = true;
189
+ if (!catalog.__ksInitialized) {
190
+ for (var x in Areas) catalog.registerElement(Areas[x]);
191
+ for (var _x in Lines) catalog.registerElement(Lines[_x]);
192
+ catalog.__ksInitialized = true;
193
+ }
194
+ var holeElements = (holePayload === null || holePayload === void 0 ? void 0 : holePayload.elements) || [];
195
+ holeElements.forEach(function (element) {
196
+ if (!catalog.hasElement(element.name)) {
197
+ console.log(element);
198
+ catalog.registerElement(element);
199
+ }
200
+ });
201
+ var categories = (holePayload === null || holePayload === void 0 ? void 0 : holePayload.categories) || {};
202
+ Object.entries(categories).forEach(function (_ref) {
203
+ var _ref2 = _slicedToArray(_ref, 2),
204
+ name = _ref2[0],
205
+ elements = _ref2[1];
206
+ if (!elements.length) return;
207
+ if (!catalog.hasCategory(name)) {
208
+ catalog.registerCategory(name, name, elements);
209
+ return;
210
+ }
211
+ elements.forEach(function (element) {
212
+ if (!catalog.categoryHasElement(name, element.name)) {
213
+ catalog.addToCategory(name, element);
214
+ }
215
+ });
216
+ });
124
217
  }
125
218
 
126
219
  // ----------------- store factory -----------------
@@ -164,7 +257,11 @@ export default function LiteRenderer(props) {
164
257
  externalEvent = props.externalEvent,
165
258
  onInternalEvent = props.onInternalEvent,
166
259
  onError = props.onError,
260
+ holes = props.holes,
167
261
  passThrough = _objectWithoutProperties(props, _excluded);
262
+ var holePayload = useMemo(function () {
263
+ return buildHoleElements(holes);
264
+ }, [holes]);
168
265
 
169
266
  // ✅ instance-scoped store (no module singleton)
170
267
  var storeRef = useRef(null);
@@ -174,8 +271,8 @@ export default function LiteRenderer(props) {
174
271
  var catalogRef = useRef(null);
175
272
  if (!catalogRef.current) {
176
273
  catalogRef.current = new Catalog();
177
- initCatalogOnce(catalogRef.current);
178
274
  }
275
+ initCatalogOnce(catalogRef.current, holePayload);
179
276
 
180
277
  // ✅ stable plugins array
181
278
  var plugins = useMemo(function () {
@@ -198,7 +295,7 @@ export default function LiteRenderer(props) {
198
295
  try {
199
296
  var maybeCleanup = p === null || p === void 0 ? void 0 : p(store, stateExtractor);
200
297
  if (typeof maybeCleanup === 'function') cleanups.push(maybeCleanup);
201
- } catch (_unused4) {
298
+ } catch (_unused5) {
202
299
  // keep prior behavior: do not crash
203
300
  }
204
301
  }
@@ -216,7 +313,7 @@ export default function LiteRenderer(props) {
216
313
  var fn = _step2.value;
217
314
  try {
218
315
  fn();
219
- } catch (_unused3) {}
316
+ } catch (_unused4) {}
220
317
  }
221
318
  } catch (err) {
222
319
  _iterator2.e(err);
@@ -247,7 +344,7 @@ export default function LiteRenderer(props) {
247
344
  };
248
345
  try {
249
346
  onError === null || onError === void 0 || onError(payload);
250
- } catch (_unused5) {}
347
+ } catch (_unused6) {}
251
348
  // eslint-disable-next-line no-console
252
349
  console.debug('[LiteRenderer:onError]', payload);
253
350
  lastEmittedRef.current = payload;
@@ -308,13 +405,11 @@ export default function LiteRenderer(props) {
308
405
  emit(lastExternalEventRef.current, last.errors);
309
406
  }
310
407
  }, [externalEvent, emit]);
311
- var _ref = configData || {},
312
- logoImg = _ref.logoImg,
313
- companyUrl = _ref.companyUrl;
408
+ var _ref3 = configData || {},
409
+ logoImg = _ref3.logoImg,
410
+ companyUrl = _ref3.companyUrl;
314
411
  return /*#__PURE__*/React.createElement(AppContext.Provider, null, /*#__PURE__*/React.createElement(Provider, {
315
412
  store: storeRef.current
316
- }, /*#__PURE__*/React.createElement(ToolErrorBoundary, {
317
- pushError: pushError
318
413
  }, /*#__PURE__*/React.createElement(LiteKitchenConfigurator, _extends({
319
414
  catalog: catalogRef.current,
320
415
  width: width,
@@ -328,7 +423,7 @@ export default function LiteRenderer(props) {
328
423
  configData: configData,
329
424
  externalEvent: externalEvent,
330
425
  onInternalEvent: onInternalEvent
331
- }, passThrough)))));
426
+ }, passThrough))));
332
427
  }
333
428
  LiteRenderer.propTypes = {
334
429
  width: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
@@ -348,5 +443,6 @@ LiteRenderer.propTypes = {
348
443
  externalEvent: PropTypes.object,
349
444
  onInternalEvent: PropTypes.func,
350
445
  onError: PropTypes.func,
446
+ holes: PropTypes.array,
351
447
  store: PropTypes.object
352
448
  };
Binary file
@@ -1410,10 +1410,9 @@ export default function Viewer2D(_ref, _ref2) {
1410
1410
  detectAutoPan: mode2DetectAutopan(mode),
1411
1411
  onMouseDown: onMouseDown,
1412
1412
  onMouseMove: onMouseMove,
1413
- onMouseUp: onMouseUp
1414
- // miniaturePosition="none"
1415
- // toolbarPosition="none"
1416
- ,
1413
+ onMouseUp: onMouseUp,
1414
+ miniaturePosition: "none",
1415
+ toolbarPosition: "none",
1417
1416
  detectPinchGesture: false,
1418
1417
  disableDoubleClickZoomWithToolAuto: true,
1419
1418
  ref: Viewer
@@ -9,7 +9,7 @@ import { disposeObject } from "./three-memory-cleaner";
9
9
  import { ANIMATE_STEP_MAX, ANIMATE_STEP_MIN, ARRAY_3D_MODES, ARROW_TEXT_BACKCOLOR, ARROW_TEXT_FONTFACE, ARROW_TEXT_FORECOLOR, BASE_CABINET_LAYOUTPOS, BOTTOM_MOLDING_LOCATION, DECIMAL_PLACES_2, DIFFERENT_VALUES_PATH_LENGTH, DISTANCE_EPSILON, EPSILON, MIDDLE_MOLDING_LOCATION, MODE_DRAGGING_ITEM_3D, MODE_DRAWING_ITEM_3D, MODE_IDLE, MODE_IDLE_3D, MODE_ROTATING_ITEM_3D, OBJTYPE_MESH, SHADE_DARK_PURPLE_COLOR, TOP_MOLDING_LOCATION, UNIT_CENTIMETER, UNIT_FOOT, UNIT_INCH, UNIT_METER, WALL_CABINET_LAYOUTPOS } from "../../constants";
10
10
  import { GeometryUtils, IDBroker, MoldingUtils } from "../../utils/export";
11
11
  import { convert } from "../../utils/convert-units-lite";
12
- import { calcDistancesFromItemToWalls, getSnappedWallLines, verticesDistance } from "../../utils/geometry";
12
+ import { calcDistancesFromItemToWalls, getLineSnapPointsOfItem, getSnappedWallLines, isOverlappedTwoItemsOnOneLine, pointsDistance, verticesDistance } from "../../utils/geometry";
13
13
  import * as GeomUtils from "../../catalog/utils/geom-utils";
14
14
  import { loadTexture } from "../../catalog/utils/item-loader";
15
15
  import { returnReplaceableDeepSearchType } from "../viewer2d/utils";
@@ -3035,13 +3035,23 @@ export function createBacksplash(item, layer, planData, scene) {
3035
3035
  */
3036
3036
  var altItems = [],
3037
3037
  flag = false;
3038
+ var D0 = {},
3039
+ D1 = {};
3038
3040
  wallItems.map(function (wallItem) {
3039
3041
  var _wallItem$itemInfo, _wallItem$itemInfo2;
3040
3042
  var altitude = (_wallItem$itemInfo = wallItem.itemInfo) === null || _wallItem$itemInfo === void 0 || (_wallItem$itemInfo = _wallItem$itemInfo.properties) === null || _wallItem$itemInfo === void 0 ? void 0 : _wallItem$itemInfo.get('altitude').get('_length');
3041
3043
  var altitudeUnit = ((_wallItem$itemInfo2 = wallItem.itemInfo) === null || _wallItem$itemInfo2 === void 0 || (_wallItem$itemInfo2 = _wallItem$itemInfo2.properties) === null || _wallItem$itemInfo2 === void 0 ? void 0 : _wallItem$itemInfo2.get('altitude').get('_unit')) || 'cm';
3042
3044
  if (!isEmpty(altitude) && !isEmpty(altitudeUnit)) {
3043
3045
  altitude = convert(altitude).from(altitudeUnit).to('cm');
3046
+ var altPoints = getLineSnapPointsOfItem(layer, curLine, wallItem);
3047
+ if (altPoints.length > 1) {
3048
+ D0 = altPoints[0];
3049
+ D1 = altPoints[1];
3050
+ }
3044
3051
  altItems.push({
3052
+ D0: D0,
3053
+ // D0, D1: item's snapped points with line
3054
+ D1: D1,
3045
3055
  x: wallItem.pos.x,
3046
3056
  width: wallItem.size.width,
3047
3057
  altitude: altitude
@@ -3049,10 +3059,29 @@ export function createBacksplash(item, layer, planData, scene) {
3049
3059
  }
3050
3060
  });
3051
3061
  layer.holes.map(function (hole) {
3052
- var _hole$properties, _hole$properties2;
3062
+ var _hole$properties, _hole$properties2, _layer$lines, _layer$vertices, _line$vertices, _layer$vertices2, _line$vertices2;
3053
3063
  var width = (_hole$properties = hole.properties) === null || _hole$properties === void 0 ? void 0 : _hole$properties.getIn(['width', 'length']);
3054
3064
  var altitude = (_hole$properties2 = hole.properties) === null || _hole$properties2 === void 0 ? void 0 : _hole$properties2.getIn(['altitude', 'length']);
3065
+ var line = (_layer$lines = layer.lines) === null || _layer$lines === void 0 ? void 0 : _layer$lines.get(curLine === null || curLine === void 0 ? void 0 : curLine.id);
3066
+ var v0 = (_layer$vertices = layer.vertices) === null || _layer$vertices === void 0 ? void 0 : _layer$vertices.get(line === null || line === void 0 || (_line$vertices = line.vertices) === null || _line$vertices === void 0 ? void 0 : _line$vertices.get(0));
3067
+ var v1 = (_layer$vertices2 = layer.vertices) === null || _layer$vertices2 === void 0 ? void 0 : _layer$vertices2.get(line === null || line === void 0 || (_line$vertices2 = line.vertices) === null || _line$vertices2 === void 0 ? void 0 : _line$vertices2.get(1));
3068
+ if (!isEmpty(v0) || !isEmpty(v1)) {
3069
+ var lineLength = pointsDistance(v0.x, v0.y, v1.x, v1.y);
3070
+ var disD0 = lineLength * hole.offset - width / 2;
3071
+ var disD1 = lineLength * hole.offset + width / 2;
3072
+ D0 = {
3073
+ x: v0.x + disD0 * Math.cos(hole.rotRad),
3074
+ y: v0.y + disD0 * Math.sin(hole.rotRad)
3075
+ };
3076
+ D1 = {
3077
+ x: v0.x + disD1 * Math.cos(hole.rotRad),
3078
+ y: v0.y + disD1 * Math.sin(hole.rotRad)
3079
+ };
3080
+ }
3055
3081
  if (!isEmpty(width) && !isEmpty(altitude) && hole.line === (curLine === null || curLine === void 0 ? void 0 : curLine.id)) altItems.push({
3082
+ D0: D0,
3083
+ // D0, D1: hole's two points
3084
+ D1: D1,
3056
3085
  x: hole.x,
3057
3086
  width: width,
3058
3087
  altitude: altitude
@@ -3061,7 +3090,7 @@ export function createBacksplash(item, layer, planData, scene) {
3061
3090
  if (altItems.length > 0) {
3062
3091
  depth = altItems[0].altitude;
3063
3092
  altItems.map(function (altItem) {
3064
- if (item.pos.x + item.size.width / 2 >= altItem.x - altItem.width / 2 && item.pos.x - item.size.width / 2 <= altItem.x + altItem.width / 2) {
3093
+ if (isOverlappedTwoItemsOnOneLine(layer, curLine, item, altItem)) {
3065
3094
  if (depth >= altItem.altitude) {
3066
3095
  depth = altItem.altitude;
3067
3096
  flag = true;
@@ -3171,9 +3200,9 @@ export function createBacksplash(item, layer, planData, scene) {
3171
3200
  }
3172
3201
  itemToSave.info.id = item.itemInfo.id;
3173
3202
  deleteSpecifiedMeshObjects('backsplash' + item.itemInfo.id);
3174
- if (Math.abs(item.rotRad % (Math.PI / 2)) < EPSILON) planData.plan.add(backsplash);
3203
+ if (Math.abs(item.rotRad % (Math.PI / 2)) < EPSILON || Math.abs(item.rotRad % (Math.PI / 2) - Math.PI / 2) < EPSILON) planData.plan.add(backsplash);
3175
3204
  backsplash.name = name;
3176
- backsplash.visible = item.itemInfo.get('backsplashVisible') && backsplashApplied && Math.abs(item.rotRad % (Math.PI / 2)) < EPSILON;
3205
+ backsplash.visible = item.itemInfo.get('backsplashVisible') && backsplashApplied && Math.abs(item.rotRad % (Math.PI / 2)) < EPSILON || Math.abs(item.rotRad % (Math.PI / 2) - Math.PI / 2) < EPSILON;
3177
3206
 
3178
3207
  // Save to scene graph
3179
3208
 
package/es/constants.js CHANGED
@@ -657,16 +657,16 @@ export var PROJECT_SETTING_OPTION = {
657
657
  CHANGE_MEASUREMENT_UNIT: CHANGE_MEASUREMENT_UNIT
658
658
  };
659
659
  export var HOLE_NAMES = {
660
- WINDOW_CLEAR: 'Window',
661
- WINDOW_CROSS: 'Cross Window',
662
- WINDOW_DOUBLE_HUNG: 'Double Hung Window',
663
- WINDOW_VERTICAL: 'window-vertical',
660
+ WINDOW_CLEAR: 'Clear',
661
+ WINDOW_CROSS: 'Cross',
662
+ WINDOW_DOUBLE_HUNG: 'Double Hung',
663
+ WINDOW_VERTICAL: 'Vertical',
664
664
  DOOR_CLOSET: 'Closet',
665
665
  DOOR_EXTERIOR: 'Exterior',
666
666
  DOOR_INTERIOR: 'Interior',
667
667
  DOOR_SLIDING: 'Sliding',
668
668
  DOOR_FRAMED: 'Framed Doorway',
669
- DOOR_FRAMELESS: 'FrameLess Doorway'
669
+ DOOR_FRAMELESS: 'Frameless Doorway'
670
670
  };
671
671
 
672
672
  // direction type
@@ -17,6 +17,7 @@ import furnishingPayload from "./mocks/furnishingPayload.json";
17
17
  import rectangleData from "./mocks/rectangleShape.json";
18
18
  import moldingPayload from "./mocks/moldingPayload.json";
19
19
  import replaceCabinetPayload from "./mocks/replaceCabinetPayload.json";
20
+ import holesPayload from "./mocks/holesPayload.json";
20
21
  import ReactDOM from 'react-dom';
21
22
  import LiteRenderer from "./LiteRenderer";
22
23
  import { Button } from 'antd';
@@ -860,6 +861,7 @@ function WorkSpace(props) {
860
861
  logoImg: "/assets/logo.png",
861
862
  companyUrl: "https://example.com",
862
863
  toolbarButtons: [],
864
+ holes: holesPayload,
863
865
  externalEvent: externalEvent,
864
866
  onInternalEvent: onInternalEvent,
865
867
  onError: function onError(payload) {
@@ -2845,4 +2845,83 @@ export function getSnappedWallLines(item, layer, catalog) {
2845
2845
  }
2846
2846
  }
2847
2847
  return snappedWallLines;
2848
+ }
2849
+ export function getLineSnapPointsOfItem(layer, curLine, item) {
2850
+ var _layer$lines2, _layer$vertices4, _line$vertices3, _layer$vertices5, _line$vertices4;
2851
+ // V0
2852
+ // /|
2853
+ // D0 /|-----------|
2854
+ // /| |
2855
+ // /| Item | ====> get D0, D1
2856
+ // /| |
2857
+ // D1 /|-----------|
2858
+ // /|
2859
+ // get v0, v1 of line
2860
+ var line = (_layer$lines2 = layer.lines) === null || _layer$lines2 === void 0 ? void 0 : _layer$lines2.get(curLine === null || curLine === void 0 ? void 0 : curLine.id);
2861
+ var v0 = (_layer$vertices4 = layer.vertices) === null || _layer$vertices4 === void 0 ? void 0 : _layer$vertices4.get(line === null || line === void 0 || (_line$vertices3 = line.vertices) === null || _line$vertices3 === void 0 ? void 0 : _line$vertices3.get(0));
2862
+ var v1 = (_layer$vertices5 = layer.vertices) === null || _layer$vertices5 === void 0 ? void 0 : _layer$vertices5.get(line === null || line === void 0 || (_line$vertices4 = line.vertices) === null || _line$vertices4 === void 0 ? void 0 : _line$vertices4.get(1));
2863
+ var pointGroup = [];
2864
+ if (isEmpty(v0) || isEmpty(v1)) return pointGroup;
2865
+ var itemRect = item === null || item === void 0 ? void 0 : item.rect;
2866
+ if (!isEmpty(itemRect)) {
2867
+ for (var i = 0; i < itemRect.length; i++) {
2868
+ if (distancePointFromLineSegment(v0, v1, itemRect[i].x, itemRect[i].y) < EPSILON) {
2869
+ pointGroup.push(itemRect[i]);
2870
+ }
2871
+ }
2872
+ }
2873
+ return pointGroup;
2874
+ }
2875
+ export function isOverlappedTwoItemsOnOneLine(layer, curLine, srcItem, desItem) {
2876
+ var _layer$lines3, _layer$vertices6, _line$vertices5, _layer$vertices7, _line$vertices6, _S, _S2, _S3, _S4;
2877
+ if (isEmpty(layer) || isEmpty(curLine) || isEmpty(srcItem) || isEmpty(desItem) || isEmpty(desItem.D0) || isEmpty(desItem.D1)) return false;
2878
+ // get v0, v1 of line
2879
+ var line = (_layer$lines3 = layer.lines) === null || _layer$lines3 === void 0 ? void 0 : _layer$lines3.get(curLine === null || curLine === void 0 ? void 0 : curLine.id);
2880
+ var v0 = (_layer$vertices6 = layer.vertices) === null || _layer$vertices6 === void 0 ? void 0 : _layer$vertices6.get(line === null || line === void 0 || (_line$vertices5 = line.vertices) === null || _line$vertices5 === void 0 ? void 0 : _line$vertices5.get(0));
2881
+ var v1 = (_layer$vertices7 = layer.vertices) === null || _layer$vertices7 === void 0 ? void 0 : _layer$vertices7.get(line === null || line === void 0 || (_line$vertices6 = line.vertices) === null || _line$vertices6 === void 0 ? void 0 : _line$vertices6.get(1));
2882
+ var S0,
2883
+ S1,
2884
+ D0 = desItem === null || desItem === void 0 ? void 0 : desItem.D0,
2885
+ D1 = desItem === null || desItem === void 0 ? void 0 : desItem.D1;
2886
+ if (isEmpty(v0) || isEmpty(v1)) return false;
2887
+ // get distance from v0 to srcItem's S0, S1 and desItem(item or hole)'s D0, D1 are placed on line
2888
+ var srcPoints = getLineSnapPointsOfItem(layer, curLine, srcItem);
2889
+ if (srcPoints.length > 1) {
2890
+ S0 = srcPoints[0];
2891
+ S1 = srcPoints[1];
2892
+ }
2893
+ var disV0S0 = pointsDistance(v0.x, v0.y, (_S = S0) === null || _S === void 0 ? void 0 : _S.x, (_S2 = S0) === null || _S2 === void 0 ? void 0 : _S2.y);
2894
+ var disV0S1 = pointsDistance(v0.x, v0.y, (_S3 = S1) === null || _S3 === void 0 ? void 0 : _S3.x, (_S4 = S1) === null || _S4 === void 0 ? void 0 : _S4.y);
2895
+ var disV0D0 = pointsDistance(v0.x, v0.y, D0.x, D0.y);
2896
+ var disV0D1 = pointsDistance(v0.x, v0.y, D1.x, D1.y);
2897
+ // detect two items are overlapped
2898
+ var maxDisV0S = Math.max(disV0S0, disV0S1);
2899
+ var minDisV0S = Math.min(disV0S0, disV0S1);
2900
+ var maxDisV0D = Math.max(disV0D0, disV0D1);
2901
+ var minDisV0D = Math.min(disV0D0, disV0D1);
2902
+ if (maxDisV0S > maxDisV0D && maxDisV0D - minDisV0S > EPSILON) {
2903
+ // d0 s0 d1 s1 ===> maxDisV0S: v0s1, minDisV0S: v0s0, maxDisV0D: v0d1, minDisV0D: v0d0
2904
+ // v0 __________________________ v1
2905
+ // | | | |
2906
+ // | | | |
2907
+ // |__DI__|__| |
2908
+ // |__SI__|
2909
+ /////////////////////////////////////////
2910
+ // s0 d0 d1 s1 ===> maxDisV0S: v0s1, minDisV0S: v0s0, maxDisV0D: v0d1, minDisV0D: v0d0
2911
+ // v0 __________________________ v1
2912
+ // | | | |
2913
+ // | |__DI__| |
2914
+ // |_________SI_______|
2915
+ return true;
2916
+ } else if (minDisV0S < minDisV0D && maxDisV0S - minDisV0D > EPSILON) {
2917
+ // s0 d0 s1 d1 ===> maxDisV0S: v0s1, minDisV0S: v0s0, maxDisV0D: v0d1, minDisV0D: v0d0
2918
+ // v0 __________________________ v1
2919
+ // | | | |
2920
+ // | |__DI__|
2921
+ // |__SI_____|
2922
+ //
2923
+ return true;
2924
+ } else {
2925
+ return false;
2926
+ }
2848
2927
  }
@@ -7,13 +7,9 @@ Object.defineProperty(exports, "__esModule", {
7
7
  });
8
8
  exports["default"] = LiteRenderer;
9
9
  var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
10
- var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
11
10
  var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
12
- var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
13
- var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
14
- var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn"));
15
- var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf"));
16
- var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits"));
11
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
12
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
17
13
  var _react = _interopRequireWildcard(require("react"));
18
14
  var _propTypes = _interopRequireDefault(require("prop-types"));
19
15
  var _reactRedux = require("react-redux");
@@ -31,15 +27,13 @@ var Lines = _interopRequireWildcard(require("./catalog/lines/wall/planner-elemen
31
27
  var Holes = _interopRequireWildcard(require("./catalog/holes/export"));
32
28
  var _export2 = require("./plugins/export");
33
29
  var _LiteKitchenConfigurator = _interopRequireDefault(require("./LiteKitchenConfigurator"));
34
- var _excluded = ["width", "height", "configData", "externalEvent", "onInternalEvent", "onError"];
30
+ var _excluded = ["width", "height", "configData", "externalEvent", "onInternalEvent", "onError", "holes"];
35
31
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, "default": e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
36
- function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
37
- function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2["default"])(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
38
32
  function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }
39
33
  function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
40
34
  function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
41
- function _callSuper(t, o, e) { return o = (0, _getPrototypeOf2["default"])(o), (0, _possibleConstructorReturn2["default"])(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], (0, _getPrototypeOf2["default"])(t).constructor) : o.apply(t, e)); }
42
- function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); } // LiteRenderer.jsx
35
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
36
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2["default"])(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } // LiteRenderer.jsx
43
37
  var isBrowser = typeof window !== 'undefined';
44
38
  if (isBrowser) window.THREE = THREE;
45
39
 
@@ -87,48 +81,147 @@ function serializeError(err) {
87
81
  };
88
82
  }
89
83
  }
90
-
91
- /* ---------- Error Boundary that pushes into buffer ---------- */
92
- var ToolErrorBoundary = /*#__PURE__*/function (_React$Component) {
93
- function ToolErrorBoundary() {
94
- (0, _classCallCheck2["default"])(this, ToolErrorBoundary);
95
- return _callSuper(this, ToolErrorBoundary, arguments);
84
+ var INCH_TO_CM = 2.54;
85
+ var normalizeKey = function normalizeKey(value) {
86
+ return (value !== null && value !== void 0 ? value : '').toString().toLowerCase().replace(/[^a-z0-9]+/g, '');
87
+ };
88
+ var safeParseJson = function safeParseJson(value) {
89
+ if (!value) return null;
90
+ try {
91
+ return JSON.parse(value);
92
+ } catch (_unused3) {
93
+ return null;
96
94
  }
97
- (0, _inherits2["default"])(ToolErrorBoundary, _React$Component);
98
- return (0, _createClass2["default"])(ToolErrorBoundary, [{
99
- key: "componentDidCatch",
100
- value: function componentDidCatch(error, info) {
101
- var pushError = this.props.pushError;
102
- pushError({
103
- type: 'render-error',
104
- error: serializeError(error),
105
- info: {
106
- componentStack: info === null || info === void 0 ? void 0 : info.componentStack
107
- }
108
- });
109
- }
110
- }, {
111
- key: "render",
112
- value: function render() {
113
- return this.props.children;
95
+ };
96
+ var toCatalogLength = function toCatalogLength(value, prop) {
97
+ var _prop$defaultValue;
98
+ if (value == null) return null;
99
+ var unit = prop === null || prop === void 0 || (_prop$defaultValue = prop.defaultValue) === null || _prop$defaultValue === void 0 ? void 0 : _prop$defaultValue.unit;
100
+ if (unit && unit.toLowerCase() === 'in') return value;
101
+ return value * INCH_TO_CM;
102
+ };
103
+ var overrideLengthProperty = function overrideLengthProperty(prop, value) {
104
+ if (!prop || value == null) return prop;
105
+ var length = toCatalogLength(value, prop);
106
+ if (length == null) return prop;
107
+ return _objectSpread(_objectSpread({}, prop), {}, {
108
+ defaultValue: _objectSpread(_objectSpread({}, prop.defaultValue), {}, {
109
+ length: length
110
+ })
111
+ });
112
+ };
113
+ var findBaseHoleTemplate = function findBaseHoleTemplate(hole, templates) {
114
+ var target = normalizeKey(hole === null || hole === void 0 ? void 0 : hole.name);
115
+ if (!target) return null;
116
+ return templates.find(function (template) {
117
+ var _template$info, _template$info2;
118
+ var candidates = [template === null || template === void 0 ? void 0 : template.name, template === null || template === void 0 || (_template$info = template.info) === null || _template$info === void 0 ? void 0 : _template$info.title, template === null || template === void 0 || (_template$info2 = template.info) === null || _template$info2 === void 0 ? void 0 : _template$info2.description].map(normalizeKey);
119
+ return candidates.includes(target);
120
+ }) || null;
121
+ };
122
+ var buildHoleElementFromTemplate = function buildHoleElementFromTemplate(hole, base) {
123
+ var _base$info, _base$info2, _base$info3, _base$info4, _base$info5, _base$structure_json;
124
+ if (!hole || !base) return null;
125
+ var nextInfo = _objectSpread(_objectSpread({}, base.info), {}, {
126
+ title: hole.name || ((_base$info = base.info) === null || _base$info === void 0 ? void 0 : _base$info.title),
127
+ description: ((_base$info2 = base.info) === null || _base$info2 === void 0 ? void 0 : _base$info2.description) || hole.name || ((_base$info3 = base.info) === null || _base$info3 === void 0 ? void 0 : _base$info3.title),
128
+ image: hole.menu_thumbnail || ((_base$info4 = base.info) === null || _base$info4 === void 0 ? void 0 : _base$info4.image),
129
+ url: hole.gltf || ((_base$info5 = base.info) === null || _base$info5 === void 0 ? void 0 : _base$info5.url)
130
+ });
131
+ var nextProperties = _objectSpread({}, base.properties);
132
+ if (nextProperties.width) {
133
+ nextProperties.width = overrideLengthProperty(nextProperties.width, hole.width);
134
+ }
135
+ if (nextProperties.height) {
136
+ nextProperties.height = overrideLengthProperty(nextProperties.height, hole.height);
137
+ }
138
+ if (nextProperties.length) {
139
+ nextProperties.length = overrideLengthProperty(nextProperties.length, hole.length);
140
+ }
141
+ var customConfig = safeParseJson(hole.custom_config);
142
+ var customProps = (customConfig === null || customConfig === void 0 ? void 0 : customConfig.properties) || {};
143
+ Object.keys(customProps).forEach(function (key) {
144
+ if (!nextProperties[key]) return;
145
+ nextProperties[key] = overrideLengthProperty(nextProperties[key], customProps[key]);
146
+ });
147
+ return _objectSpread(_objectSpread({}, base), {}, {
148
+ name: hole.name || base.name,
149
+ info: nextInfo,
150
+ properties: nextProperties,
151
+ structure_json: _objectSpread(_objectSpread({}, base.structure_json || {}), {}, {
152
+ hole_id: hole.id || ((_base$structure_json = base.structure_json) === null || _base$structure_json === void 0 ? void 0 : _base$structure_json.hole_id)
153
+ })
154
+ });
155
+ };
156
+ var buildHoleElements = function buildHoleElements(holes) {
157
+ var categories = {
158
+ Doors: [],
159
+ Windows: []
160
+ };
161
+ var elements = [];
162
+ if (!Array.isArray(holes)) return {
163
+ elements: elements,
164
+ categories: categories
165
+ };
166
+ var templates = Object.values(Holes);
167
+ var usedNames = new Set();
168
+ holes.forEach(function (hole) {
169
+ var _base$info6;
170
+ if (!hole || hole.is_deleted) return;
171
+ var base = findBaseHoleTemplate(hole, templates);
172
+ if (!base) return;
173
+ var element = buildHoleElementFromTemplate(hole, base);
174
+ if (!element || !element.name || usedNames.has(element.name)) return;
175
+ usedNames.add(element.name);
176
+ elements.push(element);
177
+ var typeKey = normalizeKey(hole.type);
178
+ if (typeKey === 'window') {
179
+ categories.Windows.push(element);
180
+ } else if (typeKey === 'door') {
181
+ categories.Doors.push(element);
182
+ } else if ((_base$info6 = base.info) !== null && _base$info6 !== void 0 && (_base$info6 = _base$info6.tag) !== null && _base$info6 !== void 0 && _base$info6.includes('window')) {
183
+ categories.Windows.push(element);
184
+ } else {
185
+ categories.Doors.push(element);
114
186
  }
115
- }]);
116
- }(_react["default"].Component);
117
- ToolErrorBoundary.propTypes = {
118
- pushError: _propTypes["default"].func.isRequired,
119
- children: _propTypes["default"].any
187
+ });
188
+ return {
189
+ elements: elements,
190
+ categories: categories
191
+ };
120
192
  };
121
193
 
122
194
  // ----------------- catalog init -----------------
123
- function initCatalogOnce(catalog) {
195
+ function initCatalogOnce(catalog, holePayload) {
124
196
  if (!catalog) return;
125
- if (catalog.__ksInitialized) return;
126
- for (var x in Areas) catalog.registerElement(Areas[x]);
127
- for (var _x in Lines) catalog.registerElement(Lines[_x]);
128
- for (var _x2 in Holes) catalog.registerElement(Holes[_x2]);
129
- catalog.registerCategory('Windows', 'Windows', [Holes.windowClear, Holes.windowCross, Holes.windowDoubleHung, Holes.windowVertical]);
130
- catalog.registerCategory('Doors', 'Doors', [Holes.doorInterior, Holes.doorExterior, Holes.doorCloset, Holes.doorSliding, Holes.doorwayFramed, Holes.doorwayFrameless]);
131
- catalog.__ksInitialized = true;
197
+ if (!catalog.__ksInitialized) {
198
+ for (var x in Areas) catalog.registerElement(Areas[x]);
199
+ for (var _x in Lines) catalog.registerElement(Lines[_x]);
200
+ catalog.__ksInitialized = true;
201
+ }
202
+ var holeElements = (holePayload === null || holePayload === void 0 ? void 0 : holePayload.elements) || [];
203
+ holeElements.forEach(function (element) {
204
+ if (!catalog.hasElement(element.name)) {
205
+ console.log(element);
206
+ catalog.registerElement(element);
207
+ }
208
+ });
209
+ var categories = (holePayload === null || holePayload === void 0 ? void 0 : holePayload.categories) || {};
210
+ Object.entries(categories).forEach(function (_ref) {
211
+ var _ref2 = (0, _slicedToArray2["default"])(_ref, 2),
212
+ name = _ref2[0],
213
+ elements = _ref2[1];
214
+ if (!elements.length) return;
215
+ if (!catalog.hasCategory(name)) {
216
+ catalog.registerCategory(name, name, elements);
217
+ return;
218
+ }
219
+ elements.forEach(function (element) {
220
+ if (!catalog.categoryHasElement(name, element.name)) {
221
+ catalog.addToCategory(name, element);
222
+ }
223
+ });
224
+ });
132
225
  }
133
226
 
134
227
  // ----------------- store factory -----------------
@@ -172,7 +265,11 @@ function LiteRenderer(props) {
172
265
  externalEvent = props.externalEvent,
173
266
  onInternalEvent = props.onInternalEvent,
174
267
  onError = props.onError,
268
+ holes = props.holes,
175
269
  passThrough = (0, _objectWithoutProperties2["default"])(props, _excluded);
270
+ var holePayload = (0, _react.useMemo)(function () {
271
+ return buildHoleElements(holes);
272
+ }, [holes]);
176
273
 
177
274
  // ✅ instance-scoped store (no module singleton)
178
275
  var storeRef = (0, _react.useRef)(null);
@@ -182,8 +279,8 @@ function LiteRenderer(props) {
182
279
  var catalogRef = (0, _react.useRef)(null);
183
280
  if (!catalogRef.current) {
184
281
  catalogRef.current = new _catalog["default"]();
185
- initCatalogOnce(catalogRef.current);
186
282
  }
283
+ initCatalogOnce(catalogRef.current, holePayload);
187
284
 
188
285
  // ✅ stable plugins array
189
286
  var plugins = (0, _react.useMemo)(function () {
@@ -206,7 +303,7 @@ function LiteRenderer(props) {
206
303
  try {
207
304
  var maybeCleanup = p === null || p === void 0 ? void 0 : p(store, stateExtractor);
208
305
  if (typeof maybeCleanup === 'function') cleanups.push(maybeCleanup);
209
- } catch (_unused4) {
306
+ } catch (_unused5) {
210
307
  // keep prior behavior: do not crash
211
308
  }
212
309
  }
@@ -224,7 +321,7 @@ function LiteRenderer(props) {
224
321
  var fn = _step2.value;
225
322
  try {
226
323
  fn();
227
- } catch (_unused3) {}
324
+ } catch (_unused4) {}
228
325
  }
229
326
  } catch (err) {
230
327
  _iterator2.e(err);
@@ -255,7 +352,7 @@ function LiteRenderer(props) {
255
352
  };
256
353
  try {
257
354
  onError === null || onError === void 0 || onError(payload);
258
- } catch (_unused5) {}
355
+ } catch (_unused6) {}
259
356
  // eslint-disable-next-line no-console
260
357
  console.debug('[LiteRenderer:onError]', payload);
261
358
  lastEmittedRef.current = payload;
@@ -316,13 +413,11 @@ function LiteRenderer(props) {
316
413
  emit(lastExternalEventRef.current, last.errors);
317
414
  }
318
415
  }, [externalEvent, emit]);
319
- var _ref = configData || {},
320
- logoImg = _ref.logoImg,
321
- companyUrl = _ref.companyUrl;
416
+ var _ref3 = configData || {},
417
+ logoImg = _ref3.logoImg,
418
+ companyUrl = _ref3.companyUrl;
322
419
  return /*#__PURE__*/_react["default"].createElement(_AppContext["default"].Provider, null, /*#__PURE__*/_react["default"].createElement(_reactRedux.Provider, {
323
420
  store: storeRef.current
324
- }, /*#__PURE__*/_react["default"].createElement(ToolErrorBoundary, {
325
- pushError: pushError
326
421
  }, /*#__PURE__*/_react["default"].createElement(_LiteKitchenConfigurator["default"], (0, _extends2["default"])({
327
422
  catalog: catalogRef.current,
328
423
  width: width,
@@ -336,7 +431,7 @@ function LiteRenderer(props) {
336
431
  configData: configData,
337
432
  externalEvent: externalEvent,
338
433
  onInternalEvent: onInternalEvent
339
- }, passThrough)))));
434
+ }, passThrough))));
340
435
  }
341
436
  LiteRenderer.propTypes = {
342
437
  width: _propTypes["default"].oneOfType([_propTypes["default"].number, _propTypes["default"].string]),
@@ -356,6 +451,7 @@ LiteRenderer.propTypes = {
356
451
  externalEvent: _propTypes["default"].object,
357
452
  onInternalEvent: _propTypes["default"].func,
358
453
  onError: _propTypes["default"].func,
454
+ holes: _propTypes["default"].array,
359
455
  store: _propTypes["default"].object
360
456
  };
361
457
  module.exports = exports.default;
Binary file
@@ -1419,10 +1419,9 @@ function Viewer2D(_ref, _ref2) {
1419
1419
  detectAutoPan: mode2DetectAutopan(mode),
1420
1420
  onMouseDown: onMouseDown,
1421
1421
  onMouseMove: onMouseMove,
1422
- onMouseUp: onMouseUp
1423
- // miniaturePosition="none"
1424
- // toolbarPosition="none"
1425
- ,
1422
+ onMouseUp: onMouseUp,
1423
+ miniaturePosition: "none",
1424
+ toolbarPosition: "none",
1426
1425
  detectPinchGesture: false,
1427
1426
  disableDoubleClickZoomWithToolAuto: true,
1428
1427
  ref: Viewer
@@ -3070,13 +3070,23 @@ function createBacksplash(item, layer, planData, scene) {
3070
3070
  */
3071
3071
  var altItems = [],
3072
3072
  flag = false;
3073
+ var D0 = {},
3074
+ D1 = {};
3073
3075
  wallItems.map(function (wallItem) {
3074
3076
  var _wallItem$itemInfo, _wallItem$itemInfo2;
3075
3077
  var altitude = (_wallItem$itemInfo = wallItem.itemInfo) === null || _wallItem$itemInfo === void 0 || (_wallItem$itemInfo = _wallItem$itemInfo.properties) === null || _wallItem$itemInfo === void 0 ? void 0 : _wallItem$itemInfo.get('altitude').get('_length');
3076
3078
  var altitudeUnit = ((_wallItem$itemInfo2 = wallItem.itemInfo) === null || _wallItem$itemInfo2 === void 0 || (_wallItem$itemInfo2 = _wallItem$itemInfo2.properties) === null || _wallItem$itemInfo2 === void 0 ? void 0 : _wallItem$itemInfo2.get('altitude').get('_unit')) || 'cm';
3077
3079
  if (!(0, _helper.isEmpty)(altitude) && !(0, _helper.isEmpty)(altitudeUnit)) {
3078
3080
  altitude = (0, _convertUnitsLite.convert)(altitude).from(altitudeUnit).to('cm');
3081
+ var altPoints = (0, _geometry2.getLineSnapPointsOfItem)(layer, curLine, wallItem);
3082
+ if (altPoints.length > 1) {
3083
+ D0 = altPoints[0];
3084
+ D1 = altPoints[1];
3085
+ }
3079
3086
  altItems.push({
3087
+ D0: D0,
3088
+ // D0, D1: item's snapped points with line
3089
+ D1: D1,
3080
3090
  x: wallItem.pos.x,
3081
3091
  width: wallItem.size.width,
3082
3092
  altitude: altitude
@@ -3084,10 +3094,29 @@ function createBacksplash(item, layer, planData, scene) {
3084
3094
  }
3085
3095
  });
3086
3096
  layer.holes.map(function (hole) {
3087
- var _hole$properties, _hole$properties2;
3097
+ var _hole$properties, _hole$properties2, _layer$lines, _layer$vertices, _line$vertices, _layer$vertices2, _line$vertices2;
3088
3098
  var width = (_hole$properties = hole.properties) === null || _hole$properties === void 0 ? void 0 : _hole$properties.getIn(['width', 'length']);
3089
3099
  var altitude = (_hole$properties2 = hole.properties) === null || _hole$properties2 === void 0 ? void 0 : _hole$properties2.getIn(['altitude', 'length']);
3100
+ var line = (_layer$lines = layer.lines) === null || _layer$lines === void 0 ? void 0 : _layer$lines.get(curLine === null || curLine === void 0 ? void 0 : curLine.id);
3101
+ var v0 = (_layer$vertices = layer.vertices) === null || _layer$vertices === void 0 ? void 0 : _layer$vertices.get(line === null || line === void 0 || (_line$vertices = line.vertices) === null || _line$vertices === void 0 ? void 0 : _line$vertices.get(0));
3102
+ var v1 = (_layer$vertices2 = layer.vertices) === null || _layer$vertices2 === void 0 ? void 0 : _layer$vertices2.get(line === null || line === void 0 || (_line$vertices2 = line.vertices) === null || _line$vertices2 === void 0 ? void 0 : _line$vertices2.get(1));
3103
+ if (!(0, _helper.isEmpty)(v0) || !(0, _helper.isEmpty)(v1)) {
3104
+ var lineLength = (0, _geometry2.pointsDistance)(v0.x, v0.y, v1.x, v1.y);
3105
+ var disD0 = lineLength * hole.offset - width / 2;
3106
+ var disD1 = lineLength * hole.offset + width / 2;
3107
+ D0 = {
3108
+ x: v0.x + disD0 * Math.cos(hole.rotRad),
3109
+ y: v0.y + disD0 * Math.sin(hole.rotRad)
3110
+ };
3111
+ D1 = {
3112
+ x: v0.x + disD1 * Math.cos(hole.rotRad),
3113
+ y: v0.y + disD1 * Math.sin(hole.rotRad)
3114
+ };
3115
+ }
3090
3116
  if (!(0, _helper.isEmpty)(width) && !(0, _helper.isEmpty)(altitude) && hole.line === (curLine === null || curLine === void 0 ? void 0 : curLine.id)) altItems.push({
3117
+ D0: D0,
3118
+ // D0, D1: hole's two points
3119
+ D1: D1,
3091
3120
  x: hole.x,
3092
3121
  width: width,
3093
3122
  altitude: altitude
@@ -3096,7 +3125,7 @@ function createBacksplash(item, layer, planData, scene) {
3096
3125
  if (altItems.length > 0) {
3097
3126
  depth = altItems[0].altitude;
3098
3127
  altItems.map(function (altItem) {
3099
- if (item.pos.x + item.size.width / 2 >= altItem.x - altItem.width / 2 && item.pos.x - item.size.width / 2 <= altItem.x + altItem.width / 2) {
3128
+ if ((0, _geometry2.isOverlappedTwoItemsOnOneLine)(layer, curLine, item, altItem)) {
3100
3129
  if (depth >= altItem.altitude) {
3101
3130
  depth = altItem.altitude;
3102
3131
  flag = true;
@@ -3206,9 +3235,9 @@ function createBacksplash(item, layer, planData, scene) {
3206
3235
  }
3207
3236
  itemToSave.info.id = item.itemInfo.id;
3208
3237
  deleteSpecifiedMeshObjects('backsplash' + item.itemInfo.id);
3209
- if (Math.abs(item.rotRad % (Math.PI / 2)) < _constants.EPSILON) planData.plan.add(backsplash);
3238
+ if (Math.abs(item.rotRad % (Math.PI / 2)) < _constants.EPSILON || Math.abs(item.rotRad % (Math.PI / 2) - Math.PI / 2) < _constants.EPSILON) planData.plan.add(backsplash);
3210
3239
  backsplash.name = name;
3211
- backsplash.visible = item.itemInfo.get('backsplashVisible') && backsplashApplied && Math.abs(item.rotRad % (Math.PI / 2)) < _constants.EPSILON;
3240
+ backsplash.visible = item.itemInfo.get('backsplashVisible') && backsplashApplied && Math.abs(item.rotRad % (Math.PI / 2)) < _constants.EPSILON || Math.abs(item.rotRad % (Math.PI / 2) - Math.PI / 2) < _constants.EPSILON;
3212
3241
 
3213
3242
  // Save to scene graph
3214
3243
 
package/lib/constants.js CHANGED
@@ -667,16 +667,16 @@ var PROJECT_SETTING_OPTION = exports.PROJECT_SETTING_OPTION = {
667
667
  CHANGE_MEASUREMENT_UNIT: CHANGE_MEASUREMENT_UNIT
668
668
  };
669
669
  var HOLE_NAMES = exports.HOLE_NAMES = {
670
- WINDOW_CLEAR: 'Window',
671
- WINDOW_CROSS: 'Cross Window',
672
- WINDOW_DOUBLE_HUNG: 'Double Hung Window',
673
- WINDOW_VERTICAL: 'window-vertical',
670
+ WINDOW_CLEAR: 'Clear',
671
+ WINDOW_CROSS: 'Cross',
672
+ WINDOW_DOUBLE_HUNG: 'Double Hung',
673
+ WINDOW_VERTICAL: 'Vertical',
674
674
  DOOR_CLOSET: 'Closet',
675
675
  DOOR_EXTERIOR: 'Exterior',
676
676
  DOOR_INTERIOR: 'Interior',
677
677
  DOOR_SLIDING: 'Sliding',
678
678
  DOOR_FRAMED: 'Framed Doorway',
679
- DOOR_FRAMELESS: 'FrameLess Doorway'
679
+ DOOR_FRAMELESS: 'Frameless Doorway'
680
680
  };
681
681
 
682
682
  // direction type
@@ -21,6 +21,7 @@ var _furnishingPayload = _interopRequireDefault(require("./mocks/furnishingPaylo
21
21
  var _rectangleShape = _interopRequireDefault(require("./mocks/rectangleShape.json"));
22
22
  var _moldingPayload = _interopRequireDefault(require("./mocks/moldingPayload.json"));
23
23
  var _replaceCabinetPayload = _interopRequireDefault(require("./mocks/replaceCabinetPayload.json"));
24
+ var _holesPayload = _interopRequireDefault(require("./mocks/holesPayload.json"));
24
25
  var _reactDom = _interopRequireDefault(require("react-dom"));
25
26
  var _LiteRenderer = _interopRequireDefault(require("./LiteRenderer"));
26
27
  var _antd = require("antd");
@@ -864,6 +865,7 @@ function WorkSpace(props) {
864
865
  logoImg: "/assets/logo.png",
865
866
  companyUrl: "https://example.com",
866
867
  toolbarButtons: [],
868
+ holes: _holesPayload["default"],
867
869
  externalEvent: externalEvent,
868
870
  onInternalEvent: onInternalEvent,
869
871
  onError: function onError(payload) {
@@ -51,6 +51,7 @@ exports.getCentroidOfPolygon = getCentroidOfPolygon;
51
51
  exports.getHoleItems = getHoleItems;
52
52
  exports.getInterSect = getInterSect;
53
53
  exports.getLineInterSect = getLineInterSect;
54
+ exports.getLineSnapPointsOfItem = getLineSnapPointsOfItem;
54
55
  exports.getNormaline = getNormaline;
55
56
  exports.getPoylgonPoints = getPoylgonPoints;
56
57
  exports.getRelatedLines = void 0;
@@ -61,6 +62,7 @@ exports.intersectRect = intersectRect;
61
62
  exports.isBackWall = isBackWall;
62
63
  exports.isFrontWall = isFrontWall;
63
64
  exports.isLeftWall = isLeftWall;
65
+ exports.isOverlappedTwoItemsOnOneLine = isOverlappedTwoItemsOnOneLine;
64
66
  exports.isPointInArea = isPointInArea;
65
67
  exports.isPointInRect = isPointInRect;
66
68
  exports.isPointOnLineSegment = isPointOnLineSegment;
@@ -2947,4 +2949,83 @@ function getSnappedWallLines(item, layer, catalog) {
2947
2949
  }
2948
2950
  }
2949
2951
  return snappedWallLines;
2952
+ }
2953
+ function getLineSnapPointsOfItem(layer, curLine, item) {
2954
+ var _layer$lines2, _layer$vertices4, _line$vertices3, _layer$vertices5, _line$vertices4;
2955
+ // V0
2956
+ // /|
2957
+ // D0 /|-----------|
2958
+ // /| |
2959
+ // /| Item | ====> get D0, D1
2960
+ // /| |
2961
+ // D1 /|-----------|
2962
+ // /|
2963
+ // get v0, v1 of line
2964
+ var line = (_layer$lines2 = layer.lines) === null || _layer$lines2 === void 0 ? void 0 : _layer$lines2.get(curLine === null || curLine === void 0 ? void 0 : curLine.id);
2965
+ var v0 = (_layer$vertices4 = layer.vertices) === null || _layer$vertices4 === void 0 ? void 0 : _layer$vertices4.get(line === null || line === void 0 || (_line$vertices3 = line.vertices) === null || _line$vertices3 === void 0 ? void 0 : _line$vertices3.get(0));
2966
+ var v1 = (_layer$vertices5 = layer.vertices) === null || _layer$vertices5 === void 0 ? void 0 : _layer$vertices5.get(line === null || line === void 0 || (_line$vertices4 = line.vertices) === null || _line$vertices4 === void 0 ? void 0 : _line$vertices4.get(1));
2967
+ var pointGroup = [];
2968
+ if ((0, _helper.isEmpty)(v0) || (0, _helper.isEmpty)(v1)) return pointGroup;
2969
+ var itemRect = item === null || item === void 0 ? void 0 : item.rect;
2970
+ if (!(0, _helper.isEmpty)(itemRect)) {
2971
+ for (var i = 0; i < itemRect.length; i++) {
2972
+ if (distancePointFromLineSegment(v0, v1, itemRect[i].x, itemRect[i].y) < _constants.EPSILON) {
2973
+ pointGroup.push(itemRect[i]);
2974
+ }
2975
+ }
2976
+ }
2977
+ return pointGroup;
2978
+ }
2979
+ function isOverlappedTwoItemsOnOneLine(layer, curLine, srcItem, desItem) {
2980
+ var _layer$lines3, _layer$vertices6, _line$vertices5, _layer$vertices7, _line$vertices6, _S, _S2, _S3, _S4;
2981
+ if ((0, _helper.isEmpty)(layer) || (0, _helper.isEmpty)(curLine) || (0, _helper.isEmpty)(srcItem) || (0, _helper.isEmpty)(desItem) || (0, _helper.isEmpty)(desItem.D0) || (0, _helper.isEmpty)(desItem.D1)) return false;
2982
+ // get v0, v1 of line
2983
+ var line = (_layer$lines3 = layer.lines) === null || _layer$lines3 === void 0 ? void 0 : _layer$lines3.get(curLine === null || curLine === void 0 ? void 0 : curLine.id);
2984
+ var v0 = (_layer$vertices6 = layer.vertices) === null || _layer$vertices6 === void 0 ? void 0 : _layer$vertices6.get(line === null || line === void 0 || (_line$vertices5 = line.vertices) === null || _line$vertices5 === void 0 ? void 0 : _line$vertices5.get(0));
2985
+ var v1 = (_layer$vertices7 = layer.vertices) === null || _layer$vertices7 === void 0 ? void 0 : _layer$vertices7.get(line === null || line === void 0 || (_line$vertices6 = line.vertices) === null || _line$vertices6 === void 0 ? void 0 : _line$vertices6.get(1));
2986
+ var S0,
2987
+ S1,
2988
+ D0 = desItem === null || desItem === void 0 ? void 0 : desItem.D0,
2989
+ D1 = desItem === null || desItem === void 0 ? void 0 : desItem.D1;
2990
+ if ((0, _helper.isEmpty)(v0) || (0, _helper.isEmpty)(v1)) return false;
2991
+ // get distance from v0 to srcItem's S0, S1 and desItem(item or hole)'s D0, D1 are placed on line
2992
+ var srcPoints = getLineSnapPointsOfItem(layer, curLine, srcItem);
2993
+ if (srcPoints.length > 1) {
2994
+ S0 = srcPoints[0];
2995
+ S1 = srcPoints[1];
2996
+ }
2997
+ var disV0S0 = pointsDistance(v0.x, v0.y, (_S = S0) === null || _S === void 0 ? void 0 : _S.x, (_S2 = S0) === null || _S2 === void 0 ? void 0 : _S2.y);
2998
+ var disV0S1 = pointsDistance(v0.x, v0.y, (_S3 = S1) === null || _S3 === void 0 ? void 0 : _S3.x, (_S4 = S1) === null || _S4 === void 0 ? void 0 : _S4.y);
2999
+ var disV0D0 = pointsDistance(v0.x, v0.y, D0.x, D0.y);
3000
+ var disV0D1 = pointsDistance(v0.x, v0.y, D1.x, D1.y);
3001
+ // detect two items are overlapped
3002
+ var maxDisV0S = Math.max(disV0S0, disV0S1);
3003
+ var minDisV0S = Math.min(disV0S0, disV0S1);
3004
+ var maxDisV0D = Math.max(disV0D0, disV0D1);
3005
+ var minDisV0D = Math.min(disV0D0, disV0D1);
3006
+ if (maxDisV0S > maxDisV0D && maxDisV0D - minDisV0S > _constants.EPSILON) {
3007
+ // d0 s0 d1 s1 ===> maxDisV0S: v0s1, minDisV0S: v0s0, maxDisV0D: v0d1, minDisV0D: v0d0
3008
+ // v0 __________________________ v1
3009
+ // | | | |
3010
+ // | | | |
3011
+ // |__DI__|__| |
3012
+ // |__SI__|
3013
+ /////////////////////////////////////////
3014
+ // s0 d0 d1 s1 ===> maxDisV0S: v0s1, minDisV0S: v0s0, maxDisV0D: v0d1, minDisV0D: v0d0
3015
+ // v0 __________________________ v1
3016
+ // | | | |
3017
+ // | |__DI__| |
3018
+ // |_________SI_______|
3019
+ return true;
3020
+ } else if (minDisV0S < minDisV0D && maxDisV0S - minDisV0D > _constants.EPSILON) {
3021
+ // s0 d0 s1 d1 ===> maxDisV0S: v0s1, minDisV0S: v0s0, maxDisV0D: v0d1, minDisV0D: v0d0
3022
+ // v0 __________________________ v1
3023
+ // | | | |
3024
+ // | |__DI__|
3025
+ // |__SI_____|
3026
+ //
3027
+ return true;
3028
+ } else {
3029
+ return false;
3030
+ }
2950
3031
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kitchen-simulator",
3
- "version": "4.4.0",
3
+ "version": "4.4.2-dynamic-holes",
4
4
  "description": "It is a kitchen simulator (self-contained micro-frontend).",
5
5
  "license": "MIT",
6
6
  "main": "lib/index.js",