UNPKG

kitchen-simulator

Version:

It is a kitchen simulator (self-contained micro-frontend).

972 lines (957 loc) 154 kB
import _defineProperty from "@babel/runtime/helpers/esm/defineProperty"; import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray"; 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; } } }; } 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; } } 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; } 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; } 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; } import * as Three from 'three'; import { Color, Group } from 'three'; import createGrid from "./grid-creator"; import { disposeObject } from "./three-memory-cleaner"; 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, WALL_CABINET_LAYOUTPOS } from "../../constants"; import { GeometryUtils, IDBroker, MoldingUtils } from "../../utils/export"; import { convert } from "../../utils/convert-units-lite"; import { verticesDistance } from "../../utils/geometry"; import * as GeomUtils from "../../catalog/utils/geom-utils"; import { loadTexture } from "../../catalog/utils/item-loader"; import { returnReplaceableDeepSearchType } from "../viewer2d/utils"; import { animateDoor, isElevationView, isEmpty, replaceMeshesWithLineSegments, translateDrawer } from "../../utils/helper"; import { formatNumber } from "../../utils/math"; var transformBox; export var fVLine = []; var scene_mode = null; export function parseData(sceneData, actions, catalog, camera, renderer, mode) { var planData = { catalog: catalog, sceneData: sceneData }; window.planData = planData; planData.sceneGraph = { unit: sceneData.unit, layers: {}, busyResources: { layers: {} }, width: sceneData.width, height: sceneData.height, LODs: {} }; planData.plan = new Three.Object3D(); planData.plan.name = 'plan'; planData.cam = new Three.Object3D(); planData.cam.name = 'cam'; // Add a grid to the plan planData.grid = createGrid(sceneData); planData.grid.name = 'grid'; planData.boundingBox = new Three.Box3().setFromObject(planData.grid); planData.boundingBox.name = 'boundingBox'; var promises = []; sceneData.layers.forEach(function (layer) { if (layer.id === sceneData.selectedLayer || layer.visible) { promises = promises.concat(createLayerObjects(layer, planData, sceneData, actions, catalog, mode, camera, renderer)); } }); var p1 = new Promise(function (resolve) { Promise.all(promises).then(function (value) { if (planData.plan.parent !== null && planData.plan.children.length !== 0) { updateBoundingBox(planData, false, mode); // if mode is elevation, build elevation scene if (isElevationView(mode)) buildElevationScene(planData, mode); } resolve('success'); }); }); return { promise: p1, planData: planData }; // return planData; } export function visibleTransformBox(flag) { // if (transformBox instanceof Three.Mesh) // transformBox.visible = flag; } var buildElevationScene = function buildElevationScene(planData, mode) { var scene = planData.plan.parent; scene.updateMatrixWorld(); var ELEV_GRP = 'ELEV_GRP'; var oldElevationGroup = scene.getObjectByName(ELEV_GRP); if (oldElevationGroup) oldElevationGroup.parent.remove(oldElevationGroup); var elevationGroup = new Three.Group(); scene.traverse(function (obj) { if (obj.name == 'MainObject') { var clone = obj.clone(); clone.name = ''; clone.visible = obj.parent.visible; clone.applyMatrix4(obj.parent.matrixWorld); elevationGroup.add(clone); } }); elevationGroup.name = ELEV_GRP; elevationGroup.visible = false; planData.elevationGroup = elevationGroup; scene.traverse(function (obj) { if (obj.name == 'MainObject') { replaceMeshesWithLineSegments(obj); } }); scene.add(elevationGroup); }; function createLayerObjects(layer, planData, sceneData, actions, catalog, mode, camera, renderer) { var promises = []; var moldingGroups = MoldingUtils.getAllMoldingGroups(layer); planData.sceneGraph.layers[layer.id] = { id: layer.id, lines: {}, holes: {}, areas: {}, items: {}, countertops: [], moldingGroups: moldingGroups, backsplashes: [], visible: layer.visible, altitude: layer.altitude }; planData.sceneGraph.busyResources.layers[layer.id] = { id: layer.id, lines: {}, holes: {}, areas: {}, items: {}, moldingGroups: {} }; // Import lines layer.lines.forEach(function (line) { promises.push(addLine(sceneData, planData, layer, line.id, catalog, actions.linesActions, mode)); line.holes.forEach(function (holeID) { promises.push(addHole(sceneData, planData, layer, holeID, catalog, actions.holesActions, mode)); }); }); // Import areas layer.areas.forEach(function (area) { promises.push(addArea(sceneData, planData, layer, area.id, catalog, actions.areaActions, mode)); }); // Import items layer.items.forEach(function (item) { promises.push(addItem(sceneData, planData, layer, item.id, catalog, actions.itemsActions, mode, null, null // false )); }); return promises; } var canvas = document.createElement('canvas'); canvas.width = 50; canvas.height = 100; canvas.style.width = 50 + 'px'; canvas.style.height = 100 + 'px'; var ctx = canvas.getContext('2d'); ctx.fillStyle = '#FFFFFF'; ctx.strokeStyle = '#ff7400'; ctx.beginPath(); ctx.arc(25, 25, 20, 0, 2 * Math.PI); ctx.fill(); ctx.stroke(); var img1 = new Image(); img1.crossOrigin = 'anonymous'; img1.src = '/assets/img/svg/3d_item_warning_info.svg'; img1.onload = function () { ctx.drawImage(img1, 0, 0, 50, 50); }; ctx.lineWidth = 4; ctx.beginPath(); ctx.arc(25, 75, 20, 0, 2 * Math.PI); ctx.fill(); ctx.stroke(); var img2 = new Image(); img2.crossOrigin = 'anonymous'; img2.src = '/assets/img/svg/3d_item_warning_edit.svg'; img2.onload = function () { ctx.drawImage(img2, 8, 58, 34, 34); }; export function createWarningObject() { var warningTexture = new Three.Texture(canvas); warningTexture.needsUpdate = true; var warningObj = new Three.Sprite(new Three.SpriteMaterial({ map: warningTexture, sizeAttenuation: true })); warningObj.material.transparent = true; warningObj.material.depthTest = false; warningObj.scale.set(20, 40, 20); warningObj.renderOrder = 3; warningObj.name = 'warningObj'; return warningObj; } export function updateScene(planData, sceneData, oldSceneData, diffArray, actions, catalog) { var _draggingItem$toJS, _filteredDiffs, _filteredDiffs2; var mode = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : null; var toolObj = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : null; var angleObj = arguments.length > 8 && arguments[8] !== undefined ? arguments[8] : null; var draggingItem = arguments.length > 9 && arguments[9] !== undefined ? arguments[9] : null; var result = []; if (mode != null) { scene_mode = mode; } var splitted = diffArray.map(function (el) { return { op: el.op, path: el.path.split('/'), value: el.value }; }); var filteredDiffs = filterDiffs(splitted, sceneData, oldSceneData); //***testing additional filter*** filteredDiffs = filteredDiffs.filter(function (_ref) { var path = _ref.path; return path[3] !== 'selected'; }); filteredDiffs = filteredDiffs.filter(function (_ref2) { var path = _ref2.path; return path[1] !== 'groups'; }); //******************************* //This is executed when dragging item is end and performs the updateing filteredDiffs. if ((sceneData === null || sceneData === void 0 ? void 0 : sceneData.isEndDragging) === true && draggingItem && !isEmpty((_draggingItem$toJS = draggingItem.toJS) === null || _draggingItem$toJS === void 0 ? void 0 : _draggingItem$toJS.call(draggingItem)) && ((_filteredDiffs = filteredDiffs) === null || _filteredDiffs === void 0 || (_filteredDiffs = _filteredDiffs[0]) === null || _filteredDiffs === void 0 || (_filteredDiffs = _filteredDiffs.path) === null || _filteredDiffs === void 0 ? void 0 : _filteredDiffs.length) < DIFFERENT_VALUES_PATH_LENGTH && (_filteredDiffs2 = filteredDiffs) !== null && _filteredDiffs2 !== void 0 && (_filteredDiffs2 = _filteredDiffs2[0]) !== null && _filteredDiffs2 !== void 0 && (_filteredDiffs2 = _filteredDiffs2.path) !== null && _filteredDiffs2 !== void 0 && _filteredDiffs2.includes('showfg')) { var _draggingItem$getIn, _draggingItem$getIn2; var layerID = (_draggingItem$getIn = draggingItem.getIn) === null || _draggingItem$getIn === void 0 ? void 0 : _draggingItem$getIn.call(draggingItem, ['layerID']); var itemID = (_draggingItem$getIn2 = draggingItem.getIn) === null || _draggingItem$getIn2 === void 0 ? void 0 : _draggingItem$getIn2.call(draggingItem, ['itemID']); if (layerID && itemID) { var _sceneData$getIn, _sceneData$getIn$toJS, _selLayer$items; filteredDiffs[0].path = ['', 'layers', layerID, 'items', itemID, 'distArray']; var selLayer = (_sceneData$getIn = sceneData.getIn) === null || _sceneData$getIn === void 0 || (_sceneData$getIn = _sceneData$getIn.call(sceneData, ['layers', layerID])) === null || _sceneData$getIn === void 0 || (_sceneData$getIn$toJS = _sceneData$getIn.toJS) === null || _sceneData$getIn$toJS === void 0 ? void 0 : _sceneData$getIn$toJS.call(_sceneData$getIn); var distArray = selLayer === null || selLayer === void 0 || (_selLayer$items = selLayer.items) === null || _selLayer$items === void 0 || (_selLayer$items = _selLayer$items[itemID]) === null || _selLayer$items === void 0 ? void 0 : _selLayer$items.distArray; filteredDiffs[0].value = distArray; } } // Check to see if diffs includes changes associated with doorStyle and global molding simultaneously. var isSettingDoorStyle = false; // If it includes any doorStyle change var isUpdateMolding = false; // If it includes any global molding change filteredDiffs.forEach(function (_ref3) { var path = _ref3.path; /** * Every 'doorStyle' change has a 'door_style_id' change. * So, if door_style_id changes, it indicates 'doorStyle' change. */ if (['id'].includes(path[path.length - 1])) isSettingDoorStyle = true; // If there are any molding change of layer if (path[1] === 'layers' && path[3] === 'molding') isUpdateMolding = true; }); if (isSettingDoorStyle && isUpdateMolding) /** * If so, any other changes could be ignored. * Because the molding change of layer invokes 'createLayerObject()' * and that function re-renders an whole layer. */ filteredDiffs = filteredDiffs.filter(function (_ref4) { var path = _ref4.path; return path[1] === 'layers' && path[3] === 'molding'; }); filteredDiffs.forEach(function (_ref5) { var op = _ref5.op, path = _ref5.path, value = _ref5.value; /* First of all I need to find the object I need to update */ if (path[1] === 'layers') { var layer = sceneData.getIn(['layers', path[2]]); if (path.length === 3 && op === 'remove') { removeLayer(path[2], planData); } else if (path.length > 3) { if (path.length > 5) if (path[5] === 'submodule' || path[5] === 'doorStyle' || path[5] === 'properties') op = 'replace'; switch (op) { case 'replace': var promiseValue = replaceObject(path, layer, planData, actions, sceneData, oldSceneData, catalog, mode, value); if (promiseValue !== undefined) { result.push(promiseValue.promise); } break; case 'add': addObject(path, layer, planData, actions, sceneData, oldSceneData, catalog, mode, toolObj); break; case 'remove': if (angleObj) planData.plan.parent.remove(angleObj); if (toolObj) planData.plan.parent.remove(toolObj); deleteSpecifiedMeshObjects('WarningBox' + path[4]); deleteSpecifiedMeshObjects('backsplash' + path[4]); var item = oldSceneData.getIn(['layers', path[2]]).getIn(['items', path[4]]); deleteCountertop(planData.sceneGraph.layers[layer.id].countertops, item, planData, layer); removeObject(path, layer, planData, actions, sceneData, oldSceneData, catalog); break; } } } else if (path[1] === 'selectedLayer') { var layerSelectedID = value; var layerSelected = sceneData.getIn(['layers', layerSelectedID]); // First of all I check if the new selected layer is not visible if (!layerSelected.visible) { // I need to create the objects for this layer var promises = createLayerObjects(layerSelected, planData, sceneData, actions, catalog, mode); Promise.all(promises).then(function () { return updateBoundingBox(planData, false, mode); }); } var layerGraph = planData.sceneGraph.layers[oldSceneData.selectedLayer]; if (layerGraph) { if (!layerGraph.visible) { // I need to remove the objects for this layer for (var lineID in layerGraph.lines) removeLine(planData, layerGraph.id, lineID); for (var areaID in layerGraph.areas) removeArea(planData, layerGraph.id, areaID); for (var _itemID in layerGraph.items) removeItem(planData, layerGraph.id, _itemID); for (var holeID in layerGraph.holes) removeHole(planData, layerGraph.id, holeID); } } } }); var p1 = new Promise(function (resolve) { Promise.all(result).then(function (replaceValue) { // if mode is elevation, build elevation scene // When scene is updated, replaceValue is not empty. if (isElevationView(mode) && !isEmpty(replaceValue)) buildElevationScene(planData, mode); resolve('successPromise'); }); }); return { promise: p1, planData: planData }; } var animate_objects = {}; function myAnimRotate(obj, open_doors, item, isCorner) { var animateStep = animate_objects[obj.name].animateStep; // if open the door, animateStep increases to ANIMATE_STEP_MAX and if close the door, animateStep decreases to ANIMATE_STEP_MIN animateStep = open_doors ? animateStep + 1 : animateStep - 1; // clear interval when the opening or closing door is ended. if (animateStep > ANIMATE_STEP_MAX || animateStep < ANIMATE_STEP_MIN) { clearInterval(animate_objects[obj.name].animate_intervalID); return; } animate_objects[obj.name].animateStep = animateStep; animateDoor(animate_objects[obj.name].offset, obj, open_doors, item, isCorner, 'Opened3D'); } function myAnimTranslate(obj, open_doors, item) { var animateStep = animate_objects[obj.name].animateStep; animateStep = open_doors ? animateStep + 1 : animateStep - 1; if (animateStep > ANIMATE_STEP_MAX || animateStep < ANIMATE_STEP_MIN) { clearInterval(animate_objects[obj.name].animate_intervalID); return; } animate_objects[obj.name].animateStep = animateStep; translateDrawer(item, obj, open_doors, 'Opened3D'); } function replaceObject(modifiedPath, layer, planData, actions, sceneData, oldSceneData, catalog) { var mode = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : null; var value = arguments.length > 8 && arguments[8] !== undefined ? arguments[8] : null; var promises = []; var matchStr = /\d_(door[^LR1-9]*)(_[LR])?(_[1-9])?$/; switch (modifiedPath[3]) { case 'vertices': if (modifiedPath[5] !== 'selected') { var vertex = layer.getIn(['vertices', modifiedPath[4]]); if (modifiedPath[5] === 'x' || modifiedPath[5] === 'y') { vertex.lines.forEach(function (lineID) { var lineHoles = oldSceneData.getIn(['layers', layer.id, 'lines', lineID, 'holes']); if (lineHoles) lineHoles.forEach(function (holeID) { replaceObject([0, 0, 0, 'holes', holeID, 'selected'], layer, planData, actions, sceneData, oldSceneData, catalog, mode); }); return replaceObject([0, 0, 0, 'lines', lineID], layer, planData, actions, sceneData, oldSceneData, catalog, mode); }); vertex.areas.forEach(function (areaID) { return replaceObject([0, 0, 0, 'areas', areaID], layer, planData, actions, sceneData, oldSceneData, catalog, mode); }); } if (modifiedPath[5] === 'areas') { var areaID = vertex.getIn(['areas', ~~modifiedPath[6]]); replaceObject([0, 0, 0, 'areas', areaID], layer, planData, actions, sceneData, oldSceneData, catalog, mode); } } break; case 'holes': var newHoleData = layer.getIn(['holes', modifiedPath[4]]); if (catalog.getElement(newHoleData.type).updateRender3D) { promises.push(updateHole(sceneData, oldSceneData, planData, layer, modifiedPath[4], modifiedPath.slice(5), catalog, actions.holesActions, function () { return removeHole(planData, layer.id, newHoleData.id); }, function () { return addHole(sceneData, planData, layer, newHoleData.id, catalog, actions.holesActions, mode); })); } else { var lineID = newHoleData.line; if (modifiedPath[5] === 'selected' || scene_mode === 'MODE_DRAWING_HOLE_3D' || scene_mode === 'MODE_DRAGGING_HOLE_3D') { // I remove only the hole without removing the wall removeHole(planData, layer.id, newHoleData.id); promises.push(addHole(sceneData, planData, layer, newHoleData.id, catalog, actions.holesActions, mode)); } else { layer.getIn(['lines', lineID, 'holes']).forEach(function (holeID) { removeHole(planData, layer.id, holeID); }); removeLine(planData, layer.id, lineID); promises.push(addLine(sceneData, planData, layer, lineID, catalog, actions.linesActions)); layer.getIn(['lines', lineID, 'holes']).forEach(function (holeID) { promises.push(addHole(sceneData, planData, layer, holeID, catalog, actions.holesActions, mode)); }); } } break; case 'lines': var line = layer.getIn(['lines', modifiedPath[4]]); if (catalog.getElement(line.type).updateRender3D) { promises.push(updateLine(sceneData, oldSceneData, planData, layer, modifiedPath[4], modifiedPath.slice(5), catalog, actions.linesActions, function () { return removeLine(planData, layer.id, modifiedPath[4]); }, function () { return addLine(sceneData, planData, layer, modifiedPath[4], catalog, actions.linesActions); })); } else { removeLine(planData, layer.id, modifiedPath[4]); promises.push(addLine(sceneData, planData, layer, modifiedPath[4], catalog, actions.linesActions)); } break; case 'areas': var area = layer.getIn(['areas', modifiedPath[4]]); if (catalog.getElement(area.type).updateRender3D) { promises.push(updateArea(sceneData, oldSceneData, planData, layer, modifiedPath[4], modifiedPath.slice(5), catalog, actions.areaActions, function () { return removeArea(planData, layer.id, modifiedPath[4]); }, function () { return addArea(sceneData, planData, layer, modifiedPath[4], catalog, actions.areaActions); })); } else { if (planData.sceneGraph.layers[layer.id].areas[modifiedPath[4]]) { removeArea(planData, layer.id, modifiedPath[4]); } promises.push(addArea(sceneData, planData, layer, modifiedPath[4], catalog, actions.areaActions)); } break; case 'items': var item = layer.getIn(['items', modifiedPath[4]]); if (isEmpty(item)) break; deleteCountertop(planData.sceneGraph.layers[layer.id].countertops, item, planData, layer); var tmpMoldings = _toConsumableArray(planData.sceneGraph.layers[layer.id].moldingGroups); if (catalog.getElement(item.type).updateRender3D) { promises.push(updateItem(sceneData, oldSceneData, planData, layer, modifiedPath[4], modifiedPath.slice(5), catalog, actions.itemsActions, function () { return removeItem(planData, layer.id, modifiedPath[4], oldSceneData.getIn(['layers', layer.id]), layer); }, function () { return addItem(sceneData, planData, layer, modifiedPath[4], catalog, actions.itemsActions, mode); })); } else { var item3D = null; try { item3D = planData.sceneGraph.layers[layer.id].items[modifiedPath[4]]; } catch (err) { console.log('modifiedPath: ', modifiedPath, '\nError: ', err); return; } if (!item3D) return; var keyIndex = modifiedPath.length - 1; if (modifiedPath[keyIndex] == 'rotation') { item3D.rotation.set(0, value * Math.PI / 180 + Math.PI, 0); setTimeout(function () { getDistances(layer); }, 50); removeSelItemMesh(tmpMoldings, item, planData, mode); } else if (modifiedPath[keyIndex] == 'x') { item3D.position.x = value; setTimeout(function () { getDistances(layer); }, 50); removeSelItemMesh(tmpMoldings, item, planData, mode); } else if (modifiedPath[keyIndex] == 'y') { item3D.position.z = -value; setTimeout(function () { getDistances(layer); }, 50); removeSelItemMesh(tmpMoldings, item, planData, mode); } else if (modifiedPath[keyIndex] == 'selected') { var itemType = !!catalog.elements[item.type] ? catalog.elements[item.type].type : catalog.elements[returnReplaceableDeepSearchType(item.type)].type; if (value == false) { item3D.children[0].children = item3D.children[0].children.filter(function (item3DElement) { return item3DElement.name !== 'TransformBox' && item3DElement.name !== 'TransformGizmo'; }); if (item3D) { if (item3D.children.length > 1) { item3D.children.pop(); } var mBoxColor = 0x99c3fb; var _item = item.toJS(); if (_item.doorStyle.doorStyles !== undefined && _item.doorStyle.doorStyles.cds) { if (showYelloBox(_item)) { mBoxColor = 'rgba(232,187,47,1)'; var mBox = GeomUtils.makeMBoxfromObject(item3D, mBoxColor); var warningObj = createWarningObject(); warningObj.position.set(0, item.properties.get('height').get('length') / 3, 0); if (mBox) { mBox.add(warningObj); item3D.add(mBox); } } } } var temp_MGArray = planData.sceneGraph.layers[layer.id].moldingGroups; } else { if (item3D.name !== 'pivot' && item3D.children[0].children[item3D.children[0].children.length - 1].name == 'TransformGizmo') return; if (item3D.children[0].children[item3D.children[0].children.length - 1].name == 'TransformGizmo') { item3D.children[0].children.pop(); } var object = item3D.children[0].clone(); if (item3D.children.length > 1) { item3D.children.pop(); } item3D.children.pop(); var altitude = item.properties.get('altitude').get('length'); var scalevec = new Three.Vector3(object.scale.x, object.scale.y, object.scale.z); var posVec = new Three.Vector3(object.position.x, object.position.y, object.position.z); var newAltitude = item.properties.get('altitude').get('_length'); var newUnit = item.properties.get('altitude').get('_unit') || 'in'; newAltitude = convert(newAltitude).from(newUnit).to(sceneData.unit); var newWidth = item.properties.get('width').get('_length'); var newWidthUnit = item.properties.get('width').get('_unit') || 'in'; newWidth = convert(newWidth).from(newWidthUnit).to('in'); var newHeight = item.properties.get('height').get('_length'); var newHeightUnit = item.properties.get('height').get('_unit') || 'in'; newHeight = convert(newHeight).from(newHeightUnit).to('in'); var newDepth = item.properties.get('depth').get('_length'); var newDepthUnit = item.properties.get('depth').get('_unit') || 'in'; newDepth = convert(newDepth).from(newDepthUnit).to('in'); var sizeinfo = !!catalog.elements[item.type] ? catalog.elements[item.type].info.sizeinfo : catalog.elements[returnReplaceableDeepSearchType(item.type)].info.sizeinfo; object.scale.set(1 * newWidth / sizeinfo.width, 1 * newHeight / sizeinfo.height, 1 * newDepth / sizeinfo.depth); object.position.set(0, 0, 0); object.rotation.set(0, 0, 0); var box = GeomUtils.baseBoxHelper(object, 0xffffff); box.material.lineWidth = 0.01; var boundingBox = GeomUtils.baseBox3FromObject(object); var max = boundingBox.max; var min = boundingBox.min; var radius = Math.sqrt((boundingBox.max.x - boundingBox.min.x) * (boundingBox.max.x - boundingBox.min.x) + (boundingBox.max.z - boundingBox.min.z) * (boundingBox.max.z - boundingBox.min.z)) / 2; var moveBox = new Three.BoxGeometry(max.x - min.x, max.y - min.y, max.z - min.z); // translate Object var controlGeom = GeomUtils.controlGeom(); // rotate Object ////////// var rotGeom = GeomUtils.rotGeoms(radius + 0.05); // ////////////////////////////////// // upwards Geometry/////////// var upwardsGeom = GeomUtils.upwardsGeom(); var vLineGeom = new Three.BufferGeometry(); var vertices = [(max.x - min.x) / 2 + min.x, 0, max.z, (max.x - min.x) / 2 + min.x, 0, max.z + 1.3]; vLineGeom.setAttribute('position', new Three.BufferAttribute(new Float32Array(vertices), 3)); vLineGeom.attributes.position.needsUpdate = true; var vLineGeom1 = new Three.BufferGeometry(); var vertices1 = [(max.x - min.x) / 2 + min.x, 0, min.z, (max.x - min.x) / 2 + min.x, 0, min.z - 1.3]; vLineGeom1.setAttribute('position', new Three.BufferAttribute(new Float32Array(vertices1), 3)); vLineGeom1.attributes.position.needsUpdate = true; var vLineGeom2 = new Three.BufferGeometry(); var vertices2 = [max.x, 0, max.z - (max.z - min.z) / 2, max.x + 1.3, 0, max.z - (max.z - min.z) / 2]; vLineGeom2.setAttribute('position', new Three.BufferAttribute(new Float32Array(vertices2), 3)); var vLineGeom3 = new Three.BufferGeometry(); var vertices3 = [min.x, 0, max.z - (max.z - min.z) / 2, min.x - 1.3, 0, max.z - (max.z - min.z) / 2]; vLineGeom3.setAttribute('position', new Three.BufferAttribute(new Float32Array(vertices3), 3)); // /////////////////////////////////////// // set names of transform object var rotFillObj = new Three.Mesh(rotGeom.rotFill, new Three.MeshPhongMaterial({ color: 0x000000, side: Three.DoubleSide, colorWrite: true })); var rotStrokeObj = new Three.Line(rotGeom.rotStroke, new Three.LineBasicMaterial({ color: 0xffffff, colorWrite: true })); rotFillObj.name = 'rotate'; var upObj = new Three.Mesh(upwardsGeom, new Three.MeshBasicMaterial({ color: 0x000000, side: Three.DoubleSide })); // let upLine = new Three.Line(upwardsGeom, new Three.LineBasicMaterial({ color: 0x000000 })); // upLine.name = "transUp"; // upObj.add(upLine); upObj.name = 'transUp'; var upwardbox = new Three.BoxHelper(upObj, 0x326780); upwardbox.material.lineWidth = 0.01; fVLine = []; // let obj = new Three.Mesh(controlGeom, new Three.MeshPhongMaterial({ color: 0xffffff, side: Three.DoubleSide, colorWrite: true })); // obj.name = "translateX"; var color = SHADE_DARK_PURPLE_COLOR; var _mBox = new Three.Mesh(moveBox, new Three.MeshBasicMaterial({ color: 0xdd6699, side: Three.DoubleSide, transparent: true, opacity: 0.4 })); var vLine = new Three.Line(vLineGeom, new Three.LineBasicMaterial({ color: color })); var vLine1 = new Three.Line(vLineGeom1, new Three.LineBasicMaterial({ color: color })); var vLine2 = new Three.Line(vLineGeom2, new Three.LineBasicMaterial({ color: color })); var vLine3 = new Three.Line(vLineGeom3, new Three.LineBasicMaterial({ color: color })); fVLine.push(vLine); fVLine.push(vLine1); fVLine.push(vLine2); fVLine.push(vLine3); vLine.renderOrder = 1; vLine1.renderOrder = 1; vLine2.renderOrder = 1; vLine3.renderOrder = 1; vLine.material.transparent = true; vLine1.material.transparent = true; vLine2.material.transparent = true; vLine3.material.transparent = true; vLine.material.depthTest = false; vLine1.material.depthTest = false; vLine2.material.depthTest = false; vLine3.material.depthTest = false; var uVec = new Three.Vector3(-posVec.x / scalevec.x, -posVec.y / scalevec.y, -posVec.z / scalevec.z); var blLighting = item.type.includes('Light'); vLine.translateY(blLighting ? 1.6 : 0.1); vLine1.translateY(blLighting ? 1.6 : 0.1); vLine2.translateY(blLighting ? 1.6 : 0.1); vLine3.translateY(blLighting ? 1.6 : 0.1); upObj.translateOnAxis(uVec, 1); upObj.translateY(max.y - min.y); _mBox.name = 'TransformBox'; _mBox.translateOnAxis(new Three.Vector3(uVec.x, uVec.y + (max.y - min.y) / 2, uVec.z), 1); _mBox.scale.set(1.01, 1.01, 1.01); var rotFillObj1 = rotFillObj.clone(); var rotStrokeObj1 = rotStrokeObj.clone(); rotFillObj1.rotateY(Math.PI); rotStrokeObj1.rotateY(Math.PI); var asrtObj = new Three.Group(); // let asrtObj1 = new Three.Group(); // asrtObj.add(obj); // asrtObj.add(obj1); rotFillObj.translateY(blLighting ? 1.6 : 0.1); rotFillObj1.translateY(blLighting ? 1.6 : 0.1); rotStrokeObj.translateY(blLighting ? 1.6 : 0.1); rotStrokeObj1.translateY(blLighting ? 1.6 : 0.1); upObj.translateY(posVec.y / scalevec.y); upObj.add(upwardbox); //asrtObj.add(upObj); // vLine.translateY(posVec.y / scalevec.y); // vLine1.translateY(posVec.y / scalevec.y); // vLine2.translateY(posVec.y / scalevec.y); // vLine3.translateY(posVec.y / scalevec.y); _mBox.translateY(posVec.y / scalevec.y); // asrtObj.add(rotFillObj); // asrtObj.add(rotFillObj1); // asrtObj.add(rotStrokeObj); // asrtObj.add(rotStrokeObj1); asrtObj.add(vLine); asrtObj.add(vLine1); asrtObj.add(vLine2); asrtObj.add(vLine3); asrtObj.add(box); asrtObj.scale.set(1 / object.scale.x, object.scale.y, 1 / object.scale.z); _mBox.visible = false; // transformBox = mBox; // asrtObj.add(mBox); asrtObj.name = 'TransformGizmo'; object.add(asrtObj); object.position.x = posVec.x; object.position.y = posVec.y; object.position.z = posVec.z; // object.rotation.y = Math.PI; object.scale.set(scalevec.x, scalevec.y, scalevec.z); item3D.add(object); if (item3D) { var _mBoxColor = 0x99c3fb; var _item2 = item.toJS(); if (_item2.doorStyle.doorStyles !== undefined && _item2.doorStyle.doorStyles.cds) { if (showYelloBox(_item2)) { _mBoxColor = 'rgba(232,187,47,1)'; var _mBox2 = GeomUtils.makeMBoxfromObject(item3D, _mBoxColor); var _warningObj = createWarningObject(); _warningObj.position.set(0, item.properties.get('height').get('length') / 3, 0); if (_mBox2) { _mBox2.add(_warningObj); item3D.add(_mBox2); } } } } applyInteract(item3D, function () { // closes the setting dialog if (document.getElementById('setting_dialog')) { document.getElementById('setting_dialog').style.display = 'none'; } return actions.itemsActions.selectItem(layer.id, modifiedPath[4]); }); setTimeout(function () { getDistances(layer); }, 100); } } else if (modifiedPath[keyIndex] == 'length') { var _object = item3D.children[0]; var prevPos = _object.position; _object.position.set(prevPos.x, value, prevPos.z); } else if (modifiedPath[keyIndex] == 'flip_doorhandle') { updateDoorHandleMesh(item, item3D, value); var _object2 = item3D.children[0]; var door_animate_offset = _object2.userData.door_animate_offset; var _loop = function _loop(it) { if (_object2.children.filter(function (elem) { return elem.name === it; }).length) { var door_match = it.match(matchStr); var rotate_match_text = item.properties.toJS().flip_doorhandle ? 'rotate_L' : 'rotate_R'; if (door_match[2] === '_L') { rotate_match_text = item.properties.toJS().flip_doorhandle ? 'rotate_R' : 'rotate_L'; } _object2.children.filter(function (elem) { return elem.name === it; })[0].children[0].children.forEach(function (child) { if (child.name.endsWith(rotate_match_text)) { door_animate_offset[it] = { x: child.position.x, y: child.position.y, z: child.position.z }; } }); } }; for (var it in door_animate_offset) { _loop(it); } _object2.userData.door_animate_offset = door_animate_offset; } else if (modifiedPath[keyIndex] == 'animValue') { return; } else if (modifiedPath[keyIndex] == 'open_doors') { var _object3 = item3D.children[0]; var userData = item3D.children[0].userData; var moveObjectChildrens = []; var selectedItem = layer.getIn(['items', layer.selected.toJS().items[0]]).toJS(); _object3.children.forEach(function (child, idx) { var object_match = child.name.match(/\d_(interior_drawer[^LR1-9]*)(_[LR1-9])?$/) || child.name.match(matchStr); if (object_match && object_match.length > 2) { moveObjectChildrens.push({ type: object_match[1], obj: child }); animate_objects[child.name] = animate_objects[child.name] || {}; } }); var temp = moveObjectChildrens.filter(function (item) { var _object3$userData$doo; return (_object3$userData$doo = _object3.userData.door_animate_offset[item.obj.name]) === null || _object3$userData$doo === void 0 ? void 0 : _object3$userData$doo.isCorner; }); var isCorner = temp.length > 0; moveObjectChildrens.forEach(function (element) { var _animate_objects$elem, _animate_objects$elem2; if (((_animate_objects$elem = animate_objects[element.obj.name]) === null || _animate_objects$elem === void 0 ? void 0 : _animate_objects$elem.animateStep) === undefined) { animate_objects[element.obj.name].animateStep = selectedItem.properties.open_doors ? ANIMATE_STEP_MIN : ANIMATE_STEP_MAX; } // clear origin Interval. if ((_animate_objects$elem2 = animate_objects[element.obj.name]) !== null && _animate_objects$elem2 !== void 0 && _animate_objects$elem2.animate_intervalID) { var _animate_objects$elem3; clearInterval((_animate_objects$elem3 = animate_objects[element.obj.name]) === null || _animate_objects$elem3 === void 0 ? void 0 : _animate_objects$elem3.animate_intervalID); } if (element.type === 'door') { var _userData$door_animat, _element$obj; // This is excuted when item has door. var offset = userData === null || userData === void 0 || (_userData$door_animat = userData.door_animate_offset) === null || _userData$door_animat === void 0 ? void 0 : _userData$door_animat[element === null || element === void 0 || (_element$obj = element.obj) === null || _element$obj === void 0 ? void 0 : _element$obj.name]; if (offset) { var _offset$x, _offset$y, _offset$z; animate_objects[element.obj.name].offset = { x: (_offset$x = offset.x) !== null && _offset$x !== void 0 ? _offset$x : 0, y: (_offset$y = offset.y) !== null && _offset$y !== void 0 ? _offset$y : 0, z: (_offset$z = offset.z) !== null && _offset$z !== void 0 ? _offset$z : 0 }; } else { var _element$obj2; console.warn('⚠ Missing door_animate_offset for', element === null || element === void 0 || (_element$obj2 = element.obj) === null || _element$obj2 === void 0 ? void 0 : _element$obj2.name); animate_objects[element.obj.name].offset = { x: 0, y: 0, z: 0 }; } // Set the interval ID to new interval ID animate_objects[element.obj.name].animate_intervalID = setInterval(function () { myAnimRotate(element.obj, selectedItem.properties.open_doors, selectedItem, isCorner); }, 30); } else { // This is excuted when item has drawer box // Set the interval ID to new interval ID animate_objects[element.obj.name].animate_intervalID = setInterval(function () { myAnimTranslate(element.obj, selectedItem.properties.open_doors, selectedItem); }, 30); } }); } else if (['_length', 'doorStyle', 'cabinet_door_style_id', 'counterTop', 'texture', 'drawer_door_handle_1_gltf'].includes(modifiedPath[keyIndex])) { var rItem = planData.sceneGraph.layers[layer.id].items[modifiedPath[4]]; if (rItem) { if (rItem.children.length > 1) { rItem.children.pop(); } var _mBoxColor2 = 0x99c3fb; var _item3 = item.toJS(); if (_item3.doorStyle.doorStyles !== undefined && _item3.doorStyle.doorStyles.cds) { if (showYelloBox(_item3)) { _mBoxColor2 = 'rgba(232,187,47,1)'; } } rItem.children[0].children.forEach(function (rItemElement) { rItemElement.visible = false; }); var _mBox3 = GeomUtils.makeMBoxfromObject(rItem, _mBoxColor2); if (_mBox3) { //rItem.add (mBox); } } if (rItem != null) { removeItemWithoutItem(planData, layer.id, modifiedPath[4]); promises.push(addItem(sceneData, planData, layer, modifiedPath[4], catalog, actions.itemsActions, mode, null, rItem)); setTimeout(function () { getDistances(layer); }, 100); } break; } } item = layer.getIn(['items', modifiedPath[4]]); addCountertop(planData.sceneGraph.layers[layer.id].countertops, item, planData, layer); // Toggle selection should not update molding if (item.category === 'cabinet' && modifiedPath[modifiedPath.length - 1] !== 'selected') { planData.sceneGraph.layers[layer.id].moldingGroups = addMolding(tmpMoldings, item, planData, layer, actions.itemsActions, mode) || _toConsumableArray(tmpMoldings); } break; case 'visible': if (!layer.visible) { var _layerGraph = planData.sceneGraph.layers[layer.id]; for (var _lineID in _layerGraph.lines) removeLine(planData, layer.id, _lineID); for (var _areaID in _layerGraph.areas) removeArea(planData, layer.id, _areaID); for (var itemID in _layerGraph.items) removeItem(planData, layer.id, itemID); for (var holeID in _layerGraph.holes) removeHole(planData, layer.id, holeID); } else { promises = promises.concat(createLayerObjects(layer, planData, sceneData, actions, catalog, mode)); } break; case 'unit': case 'ceilHeight': case 'opacity': case 'altitude': case 'molding': var layerGraph = planData.sceneGraph.layers[layer.id]; for (var _lineID2 in layerGraph.lines) removeLine(planData, layer.id, _lineID2); for (var _areaID2 in layerGraph.areas) removeArea(planData, layer.id, _areaID2); for (var _itemID2 in layerGraph.items) removeItem(planData, layer.id, _itemID2); for (var _holeID in layerGraph.holes) removeHole(planData, layer.id, _holeID); promises = promises.concat(createLayerObjects(layer, planData, sceneData, actions, catalog, mode)); } var p1 = new Promise(function (resolve) { Promise.all(promises).then(function (values) { updateBoundingBox(planData, true, mode); resolve('replaceObject'); }); }); return { promise: p1 }; } export function getDistances(layer, isCalcWall) { fVLine.forEach(function (line, index) { getLineDistance(line, layer, isCalcWall === undefined ? false : isCalcWall, index); }); } function getLineDistance(obj, layer, isCalcWall, index) { if (obj === undefined) return; var positionAttribute = obj.geometry.attributes.position; if (positionAttribute === undefined) return; var wPoint0 = new Three.Vector3().fromBufferAttribute(positionAttribute, 0).applyMatrix4(obj.matrixWorld); var wPoint1 = new Three.Vector3().fromBufferAttribute(positionAttribute, 1).applyMatrix4(obj.matrixWorld); var raycaster = new Three.Raycaster(wPoint0, new Three.Vector3(wPoint1.x - wPoint0.x, wPoint1.y - wPoint0.y, wPoint1.z - wPoint0.z)); var rayDirection = raycaster.ray.direction; raycaster.camera = new Three.Camera(); rayDirection.normalize(); var meshes = []; planData.plan.traverse(function (child) { if (child.isMesh && child.geometry) { meshes.push(child); } }); var intersects = raycaster.intersectObjects(meshes, true); var lx = wPoint0.x - wPoint1.x; var ly = wPoint0.y - wPoint1.y; var lz = wPoint0.z - wPoint1.z; var length = Math.sqrt(lx * lx + ly * ly + lz * lz); var scale = 1; var extrudeSettings = { steps: 2, depth: 0.01, bevelEnabled: false }; var w = 0.2; var h = w * (Math.sqrt(3) / 2); var shape = new Three.Shape(); shape.moveTo(0, 0); shape.lineTo(-w / 4, h / 2); shape.lineTo(w / 4, h / 2); var geom = new Three.ExtrudeGeometry(shape, extrudeSettings); geom.center(); if (!isCalcWall) { for (var i = 0; i < intersects.length; i++) { if (intersects[i].object.name != 'TransformBox' && !intersects[i].object.name.includes('WarningBox') && intersects[i].object.type != 'Line' && intersects[i].object.name != 'rotate' && intersects[i].object.name != 'lineText' && intersects[i].object.type != 'BoxHelper' && !intersects[i].object.name.includes('molding') && intersects[i].object.name != 'soul') { scale = intersects[i].distance / length; if (intersects[i].distance <= 0.1) { scale = 0.1 / length; } obj.userData.distance = intersects[i].distance; obj.userData.target = intersects[i].object; var originPoint = obj.geometry.attributes.position.array.slice(0, 3); var _lx = obj.geometry.attributes.position.array[3] - obj.geometry.attributes.position.array[0]; var _ly = obj.geometry.attributes.position.array[4] - obj.geometry.attributes.position.array[1]; var _lz = obj.geometry.attributes.position.array[5] - obj.geometry.attributes.position.array[2]; var newVec = new Three.Vector3(originPoint[0] + _lx * scale, originPoint[1] + _ly * scale, originPoint[2] + _lz * scale); obj.geometry.attributes.position.array[3] = newVec.x; obj.geometry.attributes.position.array[4] = newVec.y; obj.geometry.attributes.position.array[5] = newVec.z; obj.geometry.attributes.position.needsUpdate = true; obj.geometry.computeBoundingSphere(); obj.geometry.computeBoundingBox(); var dist = formatNumber(convert(intersects[i].distance).from('cm').to('in'), DECIMAL_PLACES_2); if (dist > 3) { var _canvas = getTextCanvas(dist); var wid = _canvas.width / window.innerWidth * 30; var hei = _canvas.height / window.innerHeight * 30; var texture = new Three.Texture(_canvas); texture.minFilter = Three.LinearFilter; texture.needsUpdate = true; var geometry = new Three.PlaneGeometry(wid / 5, hei / 5); geometry.computeBoundingBox(); var material = new Three.MeshBasicMaterial({ map: texture, side: Three.DoubleSide }); var textMesh = new Three.Mesh(geometry, material); for (; obj.children.length != 0;) { var temp = obj.children.pop(); disposeObject(temp); } textMesh.rotation.set(Math.PI / 2, Math.PI, 0); // obj.add(textMesh); textMesh.position.set((obj.geometry.attributes.position.array[0] + obj.geometry.attributes.position.array[3]) / 2, 0.01, (obj.geometry.attributes.position.array[2] + obj.geometry.attributes.position.array[5]) / 2); textMesh.name = 'lineText'; textMesh.renderOrder = 2; textMesh.material.depthTest = false; textMesh.material.transparent = true; var sprite1 = new Three.Sprite(new Three.SpriteMaterial({ map: texture })); sprite1.position.set((obj.geometry.attributes.position.array[0] + obj.geometry.attributes.position.array[3]) / 2, 0.01, (obj.geometry.attributes.position.array[2] + obj.geometry.attributes.position.array[5]) / 2); sprite1.name = 'lineText'; sprite1.renderOrder = 2; sprite1.scale.set(0.2, 0.1, 0.2); sprite1.layers.set(1); obj.add(sprite1); if (obj.parent != null) { // is not lighting var item3D = obj.parent.parent.parent; var max = item3D.children[0].userData.max; var min = item3D.children[0].userData.min; var objW = (max.x - min.x) / 100, objL = (max.z - min.z) / 100; var triangle = new Three.Mesh(geom, new Three.MeshBasicMaterial({ color: SHADE_DARK_PURPLE_COLOR })); var triangle1 = new Three.Mesh(geom, new Three.MeshBasicMaterial({