@colijnit/homedecorator 261.20.3 → 261.20.5

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.
@@ -82,7 +82,7 @@ import { DecoNodeType } from '@colijnit/configuratorapi/build/enum/deco-node-typ
82
82
  import JSZip from 'jszip';
83
83
  import { Answer } from '@colijnit/configuratorapi/build/model/answer';
84
84
  import { SelectorStructure } from '@colijnit/configuratorapi/build/model/selector-structure.bo';
85
- import { Evaluator, Brush, HOLLOW_SUBTRACTION } from 'three-bvh-csg';
85
+ import { Evaluator, Brush, SUBTRACTION } from 'three-bvh-csg';
86
86
  import { Line2 } from 'three/examples/jsm/lines/Line2.js';
87
87
  import { LineGeometry } from 'three/examples/jsm/lines/LineGeometry.js';
88
88
  import { LineMaterial } from 'three/examples/jsm/lines/LineMaterial.js';
@@ -252,6 +252,7 @@ var MessageType;
252
252
  MessageType["ChangeArticleConfigurationType"] = "ChangeArticleConfigurationType";
253
253
  MessageType["RenderUploadProgress"] = "RenderUploadProgress";
254
254
  MessageType["RenderUploadFinished"] = "RenderUploadFinished";
255
+ MessageType["RenderFinished"] = "RenderFinished";
255
256
  MessageType["RemoveSlowConnectionToast"] = "RemoveSlowConnectionToast";
256
257
  MessageType["OpenConfigurator"] = "OpenConfigurator";
257
258
  })(MessageType || (MessageType = {}));
@@ -3433,6 +3434,8 @@ const roomColor = '#ffecc147'; // '#f9f9f9';
3433
3434
  const selectedRoomColor = '#f9f9f9'; // same as roomColor for now
3434
3435
  const roomPolygonOffset = -0.3; // negative is offset to the inside
3435
3436
  const cornerTolerance = 0.2;
3437
+ // two walls count as collinear when the angle at the shared corner is within this margin of 180°
3438
+ const collinearAngleTolerance = Math.PI / 180; // ~1 degree
3436
3439
  const defaultWallColor = 0xffffff;
3437
3440
  const defaultEdgeColor = 0xcccccc;
3438
3441
  // wall config
@@ -4157,6 +4160,17 @@ class HomedecoratorConnectorAdapterService {
4157
4160
  }
4158
4161
  return 'nl'; // just to be safe
4159
4162
  }
4163
+ async getPublicParams(url, upId) {
4164
+ const tempSettings = new HomedecoratorSettings();
4165
+ tempSettings.url = url;
4166
+ tempSettings.schema = upId.toString();
4167
+ // @ts-ignore
4168
+ const tempMainConnector = new MainApi(tempSettings);
4169
+ const response = await tempMainConnector.getPublicParams(upId);
4170
+ if (response) {
4171
+ return response;
4172
+ }
4173
+ }
4160
4174
  async store3DModelCDN(filename, fileContents) {
4161
4175
  try {
4162
4176
  const response = await this.mainApi.uploadModelToCDN(filename, fileContents);
@@ -4314,6 +4328,10 @@ class HomedecoratorConnectorAdapterService {
4314
4328
  }
4315
4329
  }
4316
4330
  }
4331
+ getCatalogDefinition(id) {
4332
+ return this._catalogDefinitions && this._catalogDefinitions.length > 0 ?
4333
+ this._catalogDefinitions.find(c => c.id === id) : null;
4334
+ }
4317
4335
  async getArticleExtended(articleNumber) {
4318
4336
  const requestObject = new ArticleExtendedRequest();
4319
4337
  requestObject.articleNumber = articleNumber;
@@ -6859,7 +6877,7 @@ class HomedecoratorConnectorService {
6859
6877
  });
6860
6878
  this.articleReceived.next(article);
6861
6879
  this._article = article;
6862
- this._articlePrice = article.price;
6880
+ this._articlePrice = article ? article.price : null;
6863
6881
  // Sometimes the sku is not returned in Article
6864
6882
  this._article.sku = sku;
6865
6883
  return article;
@@ -9805,8 +9823,8 @@ class OutputSettings {
9805
9823
  }
9806
9824
  class SceneSettings {
9807
9825
  }
9808
- let RenderSettings$1 = class RenderSettings {
9809
- };
9826
+ class RenderSettings {
9827
+ }
9810
9828
  class Camera {
9811
9829
  }
9812
9830
  class CameraDOF {
@@ -10011,7 +10029,7 @@ class ApiServiceModule {
10011
10029
  };
10012
10030
  }
10013
10031
  _setRenderSettings(renderParameters) {
10014
- const settings = new RenderSettings$1();
10032
+ const settings = new RenderSettings();
10015
10033
  settings.width = renderParameters.width;
10016
10034
  settings.height = renderParameters.height;
10017
10035
  settings.outputType = OutputType.Jpeg;
@@ -10021,7 +10039,7 @@ class ApiServiceModule {
10021
10039
  return settings;
10022
10040
  }
10023
10041
  _setProductRenderSettings(renderParameters) {
10024
- const settings = new RenderSettings$1();
10042
+ const settings = new RenderSettings();
10025
10043
  settings.width = renderParameters.width;
10026
10044
  settings.height = renderParameters.height;
10027
10045
  settings.outputType = OutputType.Jpeg;
@@ -14765,7 +14783,7 @@ class BaseWall extends Mesh {
14765
14783
  this.remove(item);
14766
14784
  this.onItems = this.onItems.filter(i => i !== item);
14767
14785
  this.itemsChanged = true;
14768
- this._reCreateWallGeometry();
14786
+ // this._reCreateWallGeometry();
14769
14787
  }
14770
14788
  resetRoom() {
14771
14789
  this.oppositeCache.clear();
@@ -15049,12 +15067,26 @@ class BaseWall extends Mesh {
15049
15067
  this.items
15050
15068
  .filter((item) => item.getMaskedGeometry())
15051
15069
  .forEach((item) => {
15052
- const geo = item.getMaskedGeometry();
15070
+ // Subtract the opening as a single material group. A multi-group mask (a BoxGeometry has 6
15071
+ // groups) makes SUBTRACTION emit triangles for only the groups that actually cut the wall,
15072
+ // leaving empty groups that crash the evaluator (assignBufferData reads an absent group).
15073
+ // Clone first so the item's own geometry is never mutated or disposed by the wall.
15074
+ const geo = item.getMaskedGeometry().clone();
15075
+ geo.clearGroups();
15053
15076
  const holesBrush = new Brush(geo);
15077
+ holesBrush.material = this.material[this.frontMaterialIndex];
15054
15078
  holesBrush.position.copy(item.position);
15055
15079
  holesBrush.quaternion.copy(item.quaternion);
15056
15080
  holesBrush.updateMatrixWorld();
15057
- this.brush = this._evaluator.evaluate(this.brush, holesBrush, HOLLOW_SUBTRACTION);
15081
+ try {
15082
+ this.brush = this._evaluator.evaluate(this.brush, holesBrush, SUBTRACTION);
15083
+ }
15084
+ catch (e) {
15085
+ // The mask produced no geometry - it doesn't intersect the wall (e.g. a transient placement
15086
+ // position before the item is positioned on the wall). SUBTRACTION then leaves an empty
15087
+ // material group that the evaluator chokes on. Skip this hole; the cut runs again once the
15088
+ // item is positioned correctly (see InWallItem.placeOnWall). this.brush is left untouched.
15089
+ }
15058
15090
  this._tempHoles.push(holesBrush);
15059
15091
  });
15060
15092
  const newGeometry = this.brush.geometry;
@@ -15092,6 +15124,22 @@ class Wall extends BaseWall {
15092
15124
  this.userData = new Object();
15093
15125
  const cloned = new this.constructor(new Corner(this.start.x, this.start.y), new Corner(this.end.x, this.end.y), this.height, this.thickness, this.frontColor, this.backColor, this.version, this.frontTexture, this.backTexture, false);
15094
15126
  Object3D.prototype.copy.call(cloned, this, recursive);
15127
+ // Object3D.copy does not carry over geometry, so the constructor's plain box (built with an
15128
+ // empty items list, i.e. without window/door openings) would survive. A recursive clone -
15129
+ // such as the scene clone used for GLB export - must preserve the CSG-cut geometry. Use an
15130
+ // owned copy so disposing the export scene cannot free the live wall's geometry. The
15131
+ // non-recursive clone (the intersection wall) intentionally keeps its solid box for raycasting.
15132
+ if (recursive && this.geometry) {
15133
+ const cutGeometry = this.geometry.clone();
15134
+ cloned.geometry = cutGeometry;
15135
+ // The constructor built colour-only materials (createTextures = false), so the live wall's
15136
+ // textures would be missing from the export. Copy the live materials, cloned together with
15137
+ // their textures, so the export scene owns its own copies - disposing that scene must not
15138
+ // free the textures still in use by the live wall.
15139
+ ObjectUtils.DisposeMaterial(cloned.material);
15140
+ const clonedMaterial = ObjectUtils.CloneMaterial(this.material, false);
15141
+ cloned.material = clonedMaterial;
15142
+ }
15095
15143
  cloned.userData = tempUserData;
15096
15144
  this.userData = tempUserData;
15097
15145
  return cloned;
@@ -15254,14 +15302,50 @@ class WallService {
15254
15302
  if (!wall || !corner) {
15255
15303
  return;
15256
15304
  }
15257
- this.createNewWall(corner, wall.getEnd(), wall.height, wall.thickness);
15305
+ // Capture items + world position before the split: afterwards they must be
15306
+ // distributed across the correct wall segment (otherwise they all stay on the
15307
+ // shortened wall and shift along as its center moves).
15308
+ const itemWorldPositions = [];
15309
+ [...wall.items, ...wall.onItems].forEach((item) => {
15310
+ if (item instanceof WallItem) {
15311
+ const worldPosition = new Vector3();
15312
+ item.getWorldPosition(worldPosition);
15313
+ itemWorldPositions.push({ item, x: worldPosition.x, z: worldPosition.z });
15314
+ }
15315
+ });
15316
+ const newWall = this.createNewWall(corner, wall.getEnd(), wall.height, wall.thickness);
15258
15317
  const prevCorner = wall.getEnd();
15259
15318
  wall.setEnd(corner);
15319
+ // setEnd only swaps the corner reference; rebuild the 3D geometry of the shortened wall
15320
+ wall.cornerMoved();
15260
15321
  corner.removeDuplicateWalls();
15261
15322
  prevCorner.removeDuplicateWalls();
15323
+ // Re-place each item on the wall segment it falls on, at its original world position.
15324
+ itemWorldPositions.forEach(({ item, x, z }) => {
15325
+ const candidates = [wall, newWall].filter((w) => this.walls.indexOf(w) !== -1);
15326
+ if (candidates.length === 0) {
15327
+ return;
15328
+ }
15329
+ const target = candidates.length === 1 ? candidates[0] : this._closestWallForPoint(candidates, x, z);
15330
+ item.moveTo2dPosition(x, z, target);
15331
+ });
15262
15332
  this._updatePrevAndNextWalls();
15263
15333
  this._prepareOrphanWalls();
15264
15334
  }
15335
+ /** Picks the wall whose closest point (clamped to the segment) is nearest to (x, z). */
15336
+ _closestWallForPoint(walls, x, z) {
15337
+ let best = walls[0];
15338
+ let bestDistance = Number.POSITIVE_INFINITY;
15339
+ walls.forEach((w) => {
15340
+ const closest = w.closestPointTo(x, z);
15341
+ const distance = Utils$1.Distance(x, z, closest.x, closest.y);
15342
+ if (distance < bestDistance) {
15343
+ bestDistance = distance;
15344
+ best = w;
15345
+ }
15346
+ });
15347
+ return best;
15348
+ }
15265
15349
  updatePrevWall(wallId, prevWallId) {
15266
15350
  if (wallId && prevWallId) {
15267
15351
  const wall = this.walls.find(w => w.wallId === wallId);
@@ -15343,6 +15427,56 @@ class WallService {
15343
15427
  Utils$1.RemoveValue(this.walls, wall);
15344
15428
  wall.removeWall();
15345
15429
  }
15430
+ /** Merges two collinear walls around a degree-2 corner into a single wall. */
15431
+ joinCollinearWallsAt(corner) {
15432
+ const attached = [...corner.wallStarts, ...corner.wallEnds];
15433
+ if (attached.length !== 2) {
15434
+ return;
15435
+ }
15436
+ const keep = attached[0];
15437
+ const absorb = attached[1];
15438
+ const farKeep = keep.getStart() === corner ? keep.getEnd() : keep.getStart();
15439
+ const farAbsorb = absorb.getStart() === corner ? absorb.getEnd() : absorb.getStart();
15440
+ if (farKeep === farAbsorb) {
15441
+ return; // safety: degenerate case
15442
+ }
15443
+ if (!this._areCollinearThroughCorner(farKeep, corner, farAbsorb)) {
15444
+ return; // not in line with each other -> leave as is
15445
+ }
15446
+ // Capture the world position of all items on BOTH walls before the structural change.
15447
+ // Items already on 'keep' must be re-placed too: extending 'keep' shifts its center, so
15448
+ // their (fixed) local position would otherwise map to a different world position.
15449
+ const itemWorldPositions = [];
15450
+ [...keep.items, ...keep.onItems, ...absorb.items, ...absorb.onItems].forEach((item) => {
15451
+ if (item instanceof WallItem) {
15452
+ const worldPosition = new Vector3();
15453
+ item.getWorldPosition(worldPosition);
15454
+ itemWorldPositions.push({ item, x: worldPosition.x, z: worldPosition.z });
15455
+ }
15456
+ });
15457
+ // extend 'keep' so it spans from farKeep to farAbsorb
15458
+ if (keep.getEnd() === corner) {
15459
+ keep.setEnd(farAbsorb);
15460
+ }
15461
+ else {
15462
+ keep.setStart(farAbsorb);
15463
+ }
15464
+ // setStart/setEnd only swaps the corner reference; rebuild the 3D geometry and
15465
+ // transform for the new span (otherwise the old mesh stays in place).
15466
+ keep.cornerMoved();
15467
+ // Re-place each item on the merged wall at its original world position.
15468
+ // moveTo2dPosition sets currentWall to 'keep', detaches the item from 'absorb' and
15469
+ // bounds the position within the wall (doors/windows get their opening re-cut).
15470
+ itemWorldPositions.forEach(({ item, x, z }) => item.moveTo2dPosition(x, z, keep));
15471
+ this.removeWall(absorb); // also detaches from corner -> corner becomes orphan
15472
+ this._updatePrevAndNextWalls();
15473
+ this._prepareOrphanWalls();
15474
+ }
15475
+ /** True when the two walls are in line through 'corner' (angle ~180°). */
15476
+ _areCollinearThroughCorner(a, corner, b) {
15477
+ const angle = Utils$1.Angle(a.x - corner.x, a.y - corner.y, b.x - corner.x, b.y - corner.y);
15478
+ return Math.abs(Math.abs(angle) - Math.PI) < collinearAngleTolerance;
15479
+ }
15346
15480
  updateWallHeights(newHeight) {
15347
15481
  this.walls.forEach(wall => {
15348
15482
  wall.height = newHeight / 100;
@@ -16933,6 +17067,9 @@ class WallItem extends Item {
16933
17067
  else {
16934
17068
  DistanceUtils.UpdateSideDistances(this.distancesObject, this, this.currentWall, this.worldPosVec.clone(), this.getHalfSize(), this.worldRotation.y);
16935
17069
  }
17070
+ // The arrows are built in the item's x/y plane at z ~= 0 (the item origin). For an in-wall item that
17071
+ // origin is the wall centre, so push the whole group forward to the wall face like the labels.
17072
+ this.distancesObject.position.z = this._measurementZOffset();
16936
17073
  this.add(this.distancesObject);
16937
17074
  return null;
16938
17075
  }
@@ -16974,12 +17111,20 @@ class WallItem extends Item {
16974
17111
  }
16975
17112
  return new Vector3();
16976
17113
  }
17114
+ /**
17115
+ * Local z at which measurement labels/distance arrows are drawn so they sit just in front of the wall.
17116
+ * Surface-mounted items sit on the wall face, so a small offset suffices. In-wall items override this
17117
+ * (they are centred inside the wall, so the offset must clear half the wall thickness).
17118
+ */
17119
+ _measurementZOffset() {
17120
+ return 0.01;
17121
+ }
16977
17122
  _createHeightMeasurement() {
16978
17123
  this.heightMesh = MeasurementUtils.makeHeightTextMesh(this.getHeight(), itemMeasurementsTextColor, itemMeasurementsTextSize, false, true);
16979
17124
  this.heightMesh.geometry.computeBoundingBox();
16980
17125
  const width = this.heightMesh.geometry.boundingBox.max.x - this.heightMesh.geometry.boundingBox.min.x;
16981
17126
  this.heightMesh.name = this.heightMeshName;
16982
- this.heightMesh.position.set(-this.halfSize.x - width, this.showDistances ? this._measurementYPositionOffset : 0, 0.01);
17127
+ this.heightMesh.position.set(-this.halfSize.x - width, this.showDistances ? this._measurementYPositionOffset : 0, this._measurementZOffset());
16983
17128
  this.add(this.heightMesh);
16984
17129
  }
16985
17130
  _createWidthMeasurement() {
@@ -16987,7 +17132,7 @@ class WallItem extends Item {
16987
17132
  this.widthMesh.geometry.computeBoundingBox();
16988
17133
  const width = this.widthMesh.geometry.boundingBox.max.x - this.widthMesh.geometry.boundingBox.min.x;
16989
17134
  this.widthMesh.name = this.widthMeshName;
16990
- this.widthMesh.position.set(0 - (width / 2), this.halfSize.y, 0.01);
17135
+ this.widthMesh.position.set(0 - (width / 2), this.halfSize.y, this._measurementZOffset());
16991
17136
  this.add(this.widthMesh);
16992
17137
  }
16993
17138
  _getMaskedGeometry() {
@@ -17075,10 +17220,9 @@ class WallItem extends Item {
17075
17220
  // if elevation is higher than the wall, use maxY
17076
17221
  // vec3.y = Math.min(this._getMaxY(wall) / 2, this.halfSize.y + this.elevation);
17077
17222
  vec3.y = Math.min(maxY, this.halfSize.y + this.elevation);
17078
- }
17079
- else if (this.elevationAdjustable && this.onWall) {
17080
- // if the item is adjustable & is placed on the wall
17081
- vec3.y = Math.min(this._getMaxY(wall), this.halfSize.y + this.elevation);
17223
+ // } else if (this.elevationAdjustable && this.onWall) { /* no idea why this is done, but it causes problems for positioning items */
17224
+ // // if the item is adjustable & is placed on the wall
17225
+ // vec3.y = Math.min(this._getMaxY(wall), this.halfSize.y + this.elevation);
17082
17226
  }
17083
17227
  else {
17084
17228
  if (vec3.y < minY) {
@@ -17176,6 +17320,8 @@ class InWallItem extends WallItem {
17176
17320
  this._openCloseIndicatorColor = '#606E8C';
17177
17321
  this._frameWidth = 0.07;
17178
17322
  this._frameDepth = 0.1;
17323
+ /** Extra depth added on top of the wall thickness so the dynamically built mask always pierces the wall. */
17324
+ this._maskDepthMargin = 0.1;
17179
17325
  this._isWindow = false;
17180
17326
  this._doorpost = false;
17181
17327
  this._setDefault();
@@ -17199,6 +17345,25 @@ class InWallItem extends WallItem {
17199
17345
  ObjectUtils.DisposeMaterial(this.frameMaterial);
17200
17346
  ObjectUtils.DisposeMaterial(this.doorMaterialFront);
17201
17347
  ObjectUtils.DisposeMaterial(this.windowMaterial);
17348
+ if (this._customMaskGeometry) {
17349
+ this._customMaskGeometry.dispose();
17350
+ this._customMaskGeometry = undefined;
17351
+ }
17352
+ }
17353
+ /**
17354
+ * Custom doors/windows are built at runtime and have no GLB `_mask` mesh, so the base lookup finds
17355
+ * nothing usable. Return the dynamically generated opening mask instead. Build it lazily here so any
17356
+ * instance (incl. clones that never ran createCustomMesh) yields a mask as soon as the wall asks for
17357
+ * one - otherwise the wall is left solid for that item.
17358
+ */
17359
+ getMaskedGeometry() {
17360
+ if (this.isCustom) {
17361
+ if (!this._customMaskGeometry && this.getWidth() > 0 && this.getHeight() > 0) {
17362
+ this._updateCustomMaskGeometry(this.getWidth(), this.getHeight());
17363
+ }
17364
+ return this._customMaskGeometry ? this._customMaskGeometry : null;
17365
+ }
17366
+ return super.getMaskedGeometry();
17202
17367
  }
17203
17368
  updateOpeningObject() {
17204
17369
  if (this.openCloseIndicatorObject) {
@@ -17250,6 +17415,10 @@ class InWallItem extends WallItem {
17250
17415
  this.createCustomMesh(this.getWidth(), this.getHeight());
17251
17416
  }
17252
17417
  super.placeOnWall(wall);
17418
+ // super.placeOnWall positions the item on the wall (_boundMove) only AFTER the initial addItem cut,
17419
+ // and _boundMove itself does not redraw. Re-cut now so the opening is subtracted at the item's final
17420
+ // position (the addItem cut ran at a transient position where the mask may not intersect the wall).
17421
+ this.redrawWall();
17253
17422
  }
17254
17423
  /** */
17255
17424
  getWallOffset() {
@@ -17329,16 +17498,22 @@ class InWallItem extends WallItem {
17329
17498
  return meshes;
17330
17499
  }
17331
17500
  else {
17332
- const visibleMeshes = [];
17333
- if (!this.visible) {
17334
- return [];
17335
- }
17336
- this.traverse(c => {
17337
- if (c.visible && !this.excludedMeshes.includes(c.name) && c instanceof Mesh) {
17338
- visibleMeshes.push(c);
17339
- }
17340
- });
17341
- return visibleMeshes;
17501
+ return super.getVisibleMeshes();
17502
+ // const visibleMeshes: (Mesh)[] = [];
17503
+ // if (!this.visible) {
17504
+ // return [];
17505
+ // }
17506
+ // this.traverse(c => {
17507
+ // if (c.visible &&
17508
+ // !this.excludedMeshes.includes(c.name) &&
17509
+ // !ObjectUtils.ChildOf(c, this.heightMeshName) &&
17510
+ // !ObjectUtils.ChildOf(c, this.widthMeshName) &&
17511
+ // !ObjectUtils.ChildOf(c, this.distancesObjectName) &&
17512
+ // c instanceof Mesh) {
17513
+ // visibleMeshes.push(c);
17514
+ // }
17515
+ // });
17516
+ // return visibleMeshes;
17342
17517
  }
17343
17518
  }
17344
17519
  async createTextureMaterial(options) {
@@ -17381,6 +17556,8 @@ class InWallItem extends WallItem {
17381
17556
  createCustomMesh(width, height) {
17382
17557
  const halfWidth = width / 2;
17383
17558
  const halfFrame = (this._frameWidth / 2);
17559
+ // Rebuild the opening mask on every (re)build so it tracks the current size of the custom item.
17560
+ this._updateCustomMaskGeometry(width, height);
17384
17561
  this.leftFrame = this._createFrameSide(this._frameWidth, this._getHeightFrame(height), this._frameDepth);
17385
17562
  this.leftFrame.rotation.set(this._isWindow ? 180 * (Math.PI / 180) : 0, 0, 0);
17386
17563
  this.leftFrame.position.x = -halfWidth + halfFrame;
@@ -17414,7 +17591,9 @@ class InWallItem extends WallItem {
17414
17591
  }
17415
17592
  this.customMesh = new THREE.Mesh(customGeo, this._isWindow ? this.windowMaterial : this.doorMaterialFront);
17416
17593
  this.customMesh.castShadow = this._isWindow ? false : !this.isGlass;
17417
- this.customMesh.renderOrder = -1;
17594
+ // Windows are transparent glass: let them render in the normal (post-opaque) transparent pass so
17595
+ // you see through the opening. renderOrder -1 (before opaque) is kept for the opaque door panel.
17596
+ this.customMesh.renderOrder = this._isWindow ? 0 : -1;
17418
17597
  this.customMesh.name = 'customMesh';
17419
17598
  if (this._isWindow) {
17420
17599
  this.customMesh.name += 'Window';
@@ -17534,17 +17713,22 @@ class InWallItem extends WallItem {
17534
17713
  this.frameMaterial = new THREE.MeshPhongMaterial({ side: side, name: 'frameMaterial' });
17535
17714
  this.frameMaterial.color = new THREE.Color(this.frameColor);
17536
17715
  if (this._isWindow) {
17537
- this.windowMaterial = new THREE.MeshPhongMaterial({ side: side, color: this.windowColor, name: 'windowMaterial' });
17716
+ // Name must contain 'glass' so MaterialUtils.ShowHideMaterials keeps it transparent when the wall
17717
+ // is shown - otherwise it forces transparent=false/opacity=1 and the pane looks solid.
17718
+ this.windowMaterial = new THREE.MeshPhongMaterial({ side: side, color: this.windowColor, name: 'windowGlassMaterial' });
17538
17719
  this.windowMaterial.transparent = true;
17539
17720
  this.windowMaterial.alphaTest = 0;
17540
17721
  this.windowMaterial.opacity = 0.2;
17541
17722
  this.windowMaterial.map = undefined;
17723
+ // Glass must not write depth, otherwise it occludes the view through the wall opening and the
17724
+ // pane looks solid instead of see-through.
17725
+ this.windowMaterial.depthWrite = false;
17542
17726
  this.windowMaterial.needsUpdate = true;
17543
- this.windowMaterial.side = THREE.FrontSide;
17727
+ // this.windowMaterial.side = THREE.FrontSide;
17544
17728
  this.object.material = [this.frameMaterial, this.windowMaterial];
17545
17729
  }
17546
17730
  else {
17547
- this.doorMaterialFront = new THREE.MeshPhongMaterial({ side: side, name: 'doorMaterialFront' });
17731
+ this.doorMaterialFront = new THREE.MeshPhongMaterial({ side: side, name: 'doorGlassMaterialFront' });
17548
17732
  this.doorMaterialFront.color = new THREE.Color(this.doorColor);
17549
17733
  if (this._doorpost) {
17550
17734
  this.doorMaterialFront.transparent = true;
@@ -17553,6 +17737,22 @@ class InWallItem extends WallItem {
17553
17737
  this.object.material = [this.frameMaterial, this.doorMaterialFront];
17554
17738
  }
17555
17739
  }
17740
+ /**
17741
+ * Builds the geometry used to subtract the opening from the wall. It spans the full width/height of
17742
+ * the custom item and is made deeper than the wall (plus a margin) so the CSG subtraction always
17743
+ * pierces the wall completely. base-wall positions it via the item's own position/quaternion, so the
17744
+ * box is centred on the item origin (the opening centre on the wall plane).
17745
+ */
17746
+ _updateCustomMaskGeometry(width, height) {
17747
+ const wallThickness = this.currentWall ? this.currentWall.thickness : 0.5;
17748
+ const maskDepth = wallThickness + (2 * this._maskDepthMargin);
17749
+ if (this._customMaskGeometry) {
17750
+ this._customMaskGeometry.dispose();
17751
+ }
17752
+ // The wall (base-wall) subtracts this as a single group, so the BoxGeometry's material groups are
17753
+ // irrelevant here - we only need a box of the right opening size and a depth that pierces the wall.
17754
+ this._customMaskGeometry = new BoxGeometry(width, height, maskDepth);
17755
+ }
17556
17756
  _getHeightFrame(height) {
17557
17757
  return height - (this._isWindow ? 2 * (this._frameWidth - 0.02) : this._frameWidth - 0.02);
17558
17758
  }
@@ -17683,6 +17883,13 @@ class InWallItem extends WallItem {
17683
17883
  this._createDepthMeasurement();
17684
17884
  }
17685
17885
  }
17886
+ /**
17887
+ * In-wall items sit centred inside the wall (getWallOffset() === 0), so the labels/arrows must clear
17888
+ * half the wall thickness to end up in front of the wall face instead of buried inside it.
17889
+ */
17890
+ _measurementZOffset() {
17891
+ return (this.currentWall ? this.currentWall.thickness / 2 : 0) + 0.02;
17892
+ }
17686
17893
  _createDepthMeasurement() {
17687
17894
  const depth = this.opening && this.opening.double ? Math.round((this.getWidth() / 2) * 100) / 100 : this.getWidth();
17688
17895
  this.depthMesh = MeasurementUtils.makeDepthTextMesh(depth, 0xFF00FF, 0.08, false, true);
@@ -18105,6 +18312,15 @@ class ItemService {
18105
18312
  }
18106
18313
  // todo: fix the any
18107
18314
  addItem(obj, addToScene = true) {
18315
+ // Wall-only custom shapes/cylinders live exclusively on their wall (wall.onItems) and are added to
18316
+ // the scene graph by placeOnWall() via Wall.addOnItem(). They must NOT also be tracked here: keeping
18317
+ // them in `items` double-lists them on save (getFurniture/getNonFurniture read items + wall.onItems)
18318
+ // and the scene.add() below would re-parent them off the wall, breaking their world position. They
18319
+ // are disposed together with their wall and surfaced for save/selection through wall.onItems.
18320
+ // (Detected via itemType rather than instanceof to avoid an item.service <-> wall-item-class import cycle.)
18321
+ if (obj && obj.metadata && (isCustomShapeWallType(obj.metadata.itemType) || isCustomCylinderWallType(obj.metadata.itemType))) {
18322
+ return;
18323
+ }
18108
18324
  this.items.push(obj);
18109
18325
  if (addToScene) {
18110
18326
  this._sceneService.addObject(obj);
@@ -18138,7 +18354,7 @@ class ItemService {
18138
18354
  getFurniture() {
18139
18355
  const allItems = this.items.concat(...this.items.map(i => {
18140
18356
  if (i instanceof Wall) {
18141
- return i.items.filter(wi => !wi.configurable).concat(i.onItems.filter(woi => !woi.configurable));
18357
+ return i.items.concat(i.onItems);
18142
18358
  }
18143
18359
  })).filter(i => i !== undefined);
18144
18360
  return allItems
@@ -19487,7 +19703,11 @@ class BluePrintFloorplanService extends BaseBluePrintService {
19487
19703
  return this.wallService.createWall(start, end, height, thickness);
19488
19704
  }
19489
19705
  removeWall(wall) {
19706
+ const corner1 = wall.getStart();
19707
+ const corner2 = wall.getEnd();
19490
19708
  this.roomService.removeWall(wall);
19709
+ this.wallService.joinCollinearWallsAt(corner1);
19710
+ this.wallService.joinCollinearWallsAt(corner2);
19491
19711
  this.cornerService.removeOrphanCorners();
19492
19712
  this.update();
19493
19713
  }
@@ -19607,6 +19827,9 @@ class BluePrintService extends BluePrintFloorplanService {
19607
19827
  }
19608
19828
  await this.loadTheFloorplan(floorplan);
19609
19829
  }
19830
+ getRoomCenter() {
19831
+ return this.roomService.getRoomCenter();
19832
+ }
19610
19833
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: BluePrintService, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
19611
19834
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: BluePrintService, providedIn: 'root' }); }
19612
19835
  }
@@ -22899,7 +23122,25 @@ class SceneEventService {
22899
23122
  }
22900
23123
  this._switchState(SceneEventState.DND);
22901
23124
  this._dragAndDropService.draggedStatus.dragEnter();
22902
- const vec3 = z ? new Vector3(x, y, z) : this.intersectingVec3(new Vector2(x, y));
23125
+ let screenPoint = new Vector2(x, y);
23126
+ const useViewportCentre = !z && x === 0 && y === 0 && !!this._element;
23127
+ if (useViewportCentre) {
23128
+ // The object library adds items with a (0,0) sentinel (there is no real cursor). Screen (0,0) is
23129
+ // the top-left corner, so the floor raycast lands at an arbitrary, camera-dependent spot. Use the
23130
+ // viewport centre instead.
23131
+ screenPoint = new Vector2(this._element.clientWidth / 2, this._element.clientHeight / 2);
23132
+ }
23133
+ const vec3 = z ? new Vector3(x, y, z) : this.intersectingVec3(screenPoint);
23134
+ if (useViewportCentre && isWallType(draggedData.type)) {
23135
+ // No cursor was used (library add), so there is no hit wall and getClosestWall() on a floor point
23136
+ // picks an arbitrary wall. Target the wall whose front the camera is looking at instead, and seed
23137
+ // it so the existing _changeWall() flow attaches the item to that wall. getClosestWall() itself is
23138
+ // left untouched (project loading via presets.service relies on it).
23139
+ const facingWall = this._wallMostFacingCamera();
23140
+ if (facingWall) {
23141
+ this._dragAndDropService.intersectedWall = { object: facingWall, point: vec3 ? vec3.clone() : new Vector3() };
23142
+ }
23143
+ }
22903
23144
  if (this._dragAndDropService.draggedItem) {
22904
23145
  this._dragAndDropService.draggedStatus.objectLoaded();
22905
23146
  this._dragAndDropService.updateDraggedPosition(vec3);
@@ -22911,6 +23152,35 @@ class SceneEventService {
22911
23152
  this._dragAndDropService.dragFloorDecoration(this._floorIntersection(this._sceneService.positionInSceneToScreen(vec3)));
22912
23153
  }
22913
23154
  }
23155
+ /**
23156
+ * The wall whose front face the camera is looking at most directly. Used to pick a sensible target
23157
+ * wall when an item is added without a cursor (object library). A wall's front normal is its +Z axis
23158
+ * in world space; the wall most facing the camera maximises frontNormal · (cameraPos - wallPos), which
23159
+ * naturally excludes the transparent near wall (its front points away from the camera).
23160
+ */
23161
+ _wallMostFacingCamera() {
23162
+ const walls = this._wallService.walls;
23163
+ if (!walls || !walls.length) {
23164
+ return null;
23165
+ }
23166
+ const cameraPosition = this._cameraService.camera.position;
23167
+ const wallPosition = new Vector3();
23168
+ const frontNormal = new Vector3();
23169
+ const toCamera = new Vector3();
23170
+ let best = null;
23171
+ let bestDot = -Infinity;
23172
+ for (const wall of walls) {
23173
+ wall.getWorldPosition(wallPosition);
23174
+ wall.getWorldDirection(frontNormal).normalize();
23175
+ toCamera.subVectors(cameraPosition, wallPosition).normalize();
23176
+ const dot = frontNormal.dot(toCamera);
23177
+ if (dot > bestDot) {
23178
+ bestDot = dot;
23179
+ best = wall;
23180
+ }
23181
+ }
23182
+ return best;
23183
+ }
22914
23184
  intersectingVec3(vec2, intersection) {
22915
23185
  if (!intersection) {
22916
23186
  const gIntersections = this._groundIntersections(vec2);
@@ -22997,7 +23267,9 @@ class SceneEventService {
22997
23267
  let intersection = null;
22998
23268
  if (isWallType(draggedData.type) || (isWallFloorType(draggedData.type) && this._intersectedWall)) {
22999
23269
  intersection = this._intersectedWall;
23000
- position = this._intersectedWall.object.localToWorld(this._intersectedWall.point);
23270
+ if (this._intersectedWall.object) {
23271
+ position = this._intersectedWall.object.localToWorld(this._intersectedWall.point);
23272
+ }
23001
23273
  // position = this._intersectedWall && this._intersectedWall.point;
23002
23274
  }
23003
23275
  else if (isFloorType(draggedData.type) || isFloorDecoration(draggedData.type) || (isWallFloorType(draggedData.type) && this._intersectedFloor)) {
@@ -28139,64 +28411,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
28139
28411
  type: Injectable
28140
28412
  }], ctorParameters: () => [{ type: ThreedInPhotoBuildService }, { type: ThreedInPhotoViewService }, { type: ThreedInPhotoConnectionService }, { type: ThreedInPhotoSceneService }, { type: ThreedInPhotoRenderService }, { type: i1$2.MatDialog }, { type: SceneEventService }, { type: CameraService }, { type: ViewModeService }] });
28141
28413
 
28142
- var ConnectionStatus;
28143
- (function (ConnectionStatus) {
28144
- ConnectionStatus[ConnectionStatus["IsUndefined"] = 0] = "IsUndefined";
28145
- ConnectionStatus[ConnectionStatus["IsConnected"] = 1] = "IsConnected";
28146
- ConnectionStatus[ConnectionStatus["TryingToConnect"] = 2] = "TryingToConnect";
28147
- ConnectionStatus[ConnectionStatus["IsDisConnected"] = 3] = "IsDisConnected";
28148
- })(ConnectionStatus || (ConnectionStatus = {}));
28149
-
28150
- var RenderStatus;
28151
- (function (RenderStatus) {
28152
- RenderStatus[RenderStatus["IsUndefined"] = 0] = "IsUndefined";
28153
- RenderStatus[RenderStatus["IsRunning"] = 1] = "IsRunning";
28154
- RenderStatus[RenderStatus["IsSuccess"] = 2] = "IsSuccess";
28155
- RenderStatus[RenderStatus["IsStopped"] = 3] = "IsStopped";
28156
- RenderStatus[RenderStatus["IsWaiting"] = 4] = "IsWaiting";
28157
- })(RenderStatus || (RenderStatus = {}));
28158
-
28159
- class RenderQueueItem {
28160
- constructor() {
28161
- this.startDateTime = new Date();
28162
- this.rendered = false;
28163
- this.renderProgress = 0;
28164
- this.renderIterations = 0;
28165
- this.renderStatus = RenderStatus.IsUndefined;
28166
- }
28167
- }
28168
-
28169
- var ToastType;
28170
- (function (ToastType) {
28171
- ToastType[ToastType["Success"] = 0] = "Success";
28172
- ToastType[ToastType["Warning"] = 1] = "Warning";
28173
- ToastType[ToastType["Error"] = 2] = "Error";
28174
- })(ToastType || (ToastType = {}));
28175
-
28176
- class Toast {
28177
- constructor() {
28178
- this.type = ToastType.Success;
28179
- }
28180
- }
28181
-
28182
- class RenderData {
28183
- constructor() {
28184
- this.cameraFOV = 45;
28185
- }
28186
- }
28187
-
28188
- class RenderSettings {
28189
- constructor() {
28190
- this.camRotationX = 0.24;
28191
- this.camRotationY = 0;
28192
- this.environmentName = '';
28193
- this.environmentHdr = '';
28194
- this.environmentRotation = 0;
28195
- this.environmentIntensity = null;
28196
- this.extraLights = [];
28197
- }
28198
- }
28199
-
28200
28414
  class ExportObject {
28201
28415
  }
28202
28416
 
@@ -28288,6 +28502,25 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
28288
28502
  type: Injectable
28289
28503
  }], ctorParameters: () => [{ type: HomedecoratorSettingsService }, { type: HomedecoratorConnectorAdapterService }, { type: ThreedselectorService }] });
28290
28504
 
28505
+ var RenderStatus;
28506
+ (function (RenderStatus) {
28507
+ RenderStatus[RenderStatus["IsUndefined"] = 0] = "IsUndefined";
28508
+ RenderStatus[RenderStatus["IsRunning"] = 1] = "IsRunning";
28509
+ RenderStatus[RenderStatus["IsSuccess"] = 2] = "IsSuccess";
28510
+ RenderStatus[RenderStatus["IsStopped"] = 3] = "IsStopped";
28511
+ RenderStatus[RenderStatus["IsWaiting"] = 4] = "IsWaiting";
28512
+ })(RenderStatus || (RenderStatus = {}));
28513
+
28514
+ class RenderQueueItem {
28515
+ constructor() {
28516
+ this.startDateTime = new Date();
28517
+ this.rendered = false;
28518
+ this.renderProgress = 0;
28519
+ this.renderIterations = 0;
28520
+ this.renderStatus = RenderStatus.IsUndefined;
28521
+ }
28522
+ }
28523
+
28291
28524
  class ToastService {
28292
28525
  constructor(_dictionaryService) {
28293
28526
  this._dictionaryService = _dictionaryService;
@@ -28304,597 +28537,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
28304
28537
  type: Injectable
28305
28538
  }], ctorParameters: () => [{ type: HomedecoratorDictionaryService }] });
28306
28539
 
28307
- class RenderService {
28308
- static MakeWindowMaterialTransparent(material) {
28309
- // console.log(material);
28310
- material.transparent = true;
28311
- material.opacity = Math.min(material.opacity, 0.4);
28312
- return material;
28313
- }
28314
- constructor(_settingsService, _exportService, _cameraService, _sceneService, _toastService, _messageBusService, _googleTagManager, _roomService, _floorService) {
28315
- this._settingsService = _settingsService;
28316
- this._exportService = _exportService;
28317
- this._cameraService = _cameraService;
28318
- this._sceneService = _sceneService;
28319
- this._toastService = _toastService;
28320
- this._messageBusService = _messageBusService;
28321
- this._googleTagManager = _googleTagManager;
28322
- this._roomService = _roomService;
28323
- this._floorService = _floorService;
28324
- this.renderModes = RenderModes;
28325
- this.streaming = {};
28326
- this.renderedRoomImages = [];
28327
- this.connectionStatus = ConnectionStatus.IsUndefined;
28328
- this.renders = [];
28329
- this.cameraPositions = [];
28330
- this.imageSizes = [
28331
- { id: 1, name: ' 720p (HD)', width: 1280, height: 720 },
28332
- { id: 2, name: '1080P (HD)', width: 1920, height: 1080 },
28333
- { id: 3, name: '1440p (2K)', width: 2560, height: 1440 },
28334
- { id: 4, name: '2160p (4K)', width: 4096, height: 2160 }
28335
- ];
28336
- this.lightnings = [
28337
- { id: 1, name: 'Light', settings: [] },
28338
- { id: 2, name: 'Medium', settings: [] },
28339
- { id: 3, name: 'Heay', settings: [] }
28340
- ];
28341
- this.renderEnvironments = [
28342
- { id: 1, name: 'None', hdrFile: '', intensity: 1.0 },
28343
- { id: 2, name: 'Modern city', hdrFile: 'canary_wharf_2k.hdr', intensity: 2.5 },
28344
- { id: 3, name: 'City park', hdrFile: 'dresden_moat_2k.hdr', intensity: 2.5 },
28345
- { id: 4, name: 'Night in the city', hdrFile: 'hansaplatz_2k.hdr', intensity: 1.0 },
28346
- { id: 5, name: 'Night in the countryside', hdrFile: 'kloppenheim_02_2k.hdr', intensity: 1.0 },
28347
- { id: 6, name: 'Forest', hdrFile: 'nagoya_wall_path_2k.hdr', intensity: 1.0 },
28348
- { id: 7, name: 'Snow', hdrFile: 'snowy_forest_path_01_2k.hdr', intensity: 1.0 },
28349
- { id: 8, name: 'Pasture', hdrFile: 'spruit_sunrise_2k.hdr', intensity: 1.0 },
28350
- { id: 9, name: 'Field', hdrFile: 'sunflowers_2k.hdr', intensity: 1.0 },
28351
- { id: 10, name: 'Old city and canals', hdrFile: 'tears_of_steel_bridge_2k.hdr', intensity: 1.0 },
28352
- { id: 11, name: 'Estate', hdrFile: 'tiergarten_2k.hdr', intensity: 1.0 },
28353
- { id: 12, name: 'Beach', hdrFile: 'umhlanga_sunrise_2k.hdr', intensity: 2.5 },
28354
- { id: 13, name: 'Residential area with park', hdrFile: 'urban_street_01_2k.hdr', intensity: 1.0 },
28355
- { id: 14, name: 'Residential area', hdrFile: 'urban_street_03_2k.hdr', intensity: 1.0 },
28356
- ];
28357
- this.renderScenes = [
28358
- { id: 1, name: 'scene_grass_cycles_MRP', sceneAssetId: 'scene_grass_cycles_MRP' },
28359
- { id: 2, name: 'scene_lake_cycles_MRP', sceneAssetId: 'scene_lake_cycles_MRP' },
28360
- { id: 3, name: 'scene_sky_cycles_MRP', sceneAssetId: 'scene_sky_cycles_MRP' },
28361
- { id: 4, name: 'scene_garden_cycles_MRP', sceneAssetId: 'scene_garden_cycles_MRP' },
28362
- { id: 5, name: 'scene_nature_cycles_MRP', sceneAssetId: 'scene_nature_cycles_MRP' },
28363
- { id: 5, name: 'scene_01', sceneAssetId: 'scene_01' }
28364
- ];
28365
- this._ceilingLightMargin = 0.5;
28366
- this.selectedImageSize = 2;
28367
- this.selectedEnvironment = 1;
28368
- this.selectedRenderScene = this.renderScenes[0].sceneAssetId;
28369
- this.blendFilesRender = this._settingsService.settings.blendFilesRender;
28370
- this.positions = 1;
28371
- this.save = false;
28372
- this.renderRoomImageChanged = new BehaviorSubject('');
28373
- this.renderingStarted = new Subject();
28374
- this.renderImageChanged = new BehaviorSubject('');
28375
- this.renderQueue = [];
28376
- this.currentQueueRenderItem = new RenderQueueItem();
28377
- this.currentProductHash = '';
28378
- this._subs = [];
28379
- this.sceneData = {};
28380
- this._subs.push(this._settingsService.settingsLoaded.subscribe((loaded) => {
28381
- if (loaded) {
28382
- this.serverData = this._settingsService.settings.renderParameters;
28383
- if (this.serverData) {
28384
- this.serverData.setup = false;
28385
- this.checkConnection();
28386
- this._renderServiceHeartBeat();
28387
- }
28388
- }
28389
- }));
28390
- }
28391
- ngOnDestroy() {
28392
- this._subs.forEach(s => s.unsubscribe());
28393
- }
28394
- async checkConnection() {
28395
- //
28396
- // if (this.service.validate() === false) {
28397
- //
28398
- // try {
28399
- //
28400
- // const url = `${(this.serverData.secure ? 'wss' : 'ws')}://${this.serverData.host}:${this.serverData.port}/service/`;
28401
- // await this.service.connect(url).then(() => {
28402
- // this.serverData.setup = true;
28403
- // }).catch((rej) => {
28404
- // });
28405
- //
28406
- // this.service.on('error', async (object) => {
28407
- // this.serverData.setup = false;
28408
- // if (this.connectionStatus !== ConnectionStatus.TryingToConnect) {
28409
- // this.connectionStatus = ConnectionStatus.IsDisConnected;
28410
- // }
28411
- // await this._onRenderError();
28412
- // });
28413
- // this.service.on('close', async (object) => {
28414
- // this.serverData.setup = false;
28415
- // if (this.connectionStatus !== ConnectionStatus.TryingToConnect) {
28416
- // this.connectionStatus = ConnectionStatus.IsDisConnected;
28417
- // }
28418
- // await this._onRenderClose();
28419
- // });
28420
- //
28421
- // } catch (err) {
28422
- //
28423
- // this.serverData.setup = false;
28424
- // }
28425
- // }
28426
- }
28427
- _renderServiceHeartBeat() {
28428
- setInterval(() => {
28429
- if (this.connectionStatus === ConnectionStatus.IsDisConnected) {
28430
- if (this._settingsService.settings.options.showRenderConnectionInfo) {
28431
- const toast = new Toast();
28432
- toast.message = 'CONNECTION_WITH_RENDER_SERVICE_LOST';
28433
- toast.type = ToastType.Error;
28434
- this._toastService.showToast(toast);
28435
- }
28436
- this.connectionStatus = ConnectionStatus.TryingToConnect;
28437
- this.checkConnection();
28438
- }
28439
- else if (this.connectionStatus === ConnectionStatus.TryingToConnect) {
28440
- if (this.serverData.setup === false) {
28441
- this._messageBusService.emit(MessageType.RenderServiceTryToConnect);
28442
- this.checkConnection();
28443
- }
28444
- else {
28445
- if (this._settingsService.settings.options.showRenderConnectionInfo) {
28446
- const toast = new Toast();
28447
- toast.message = 'RE_CONNECTED_WITH_RENDER_SERVICE';
28448
- toast.type = ToastType.Success;
28449
- this._toastService.showToast(toast);
28450
- }
28451
- this.connectionStatus = ConnectionStatus.IsConnected;
28452
- }
28453
- }
28454
- else if (this.connectionStatus === ConnectionStatus.IsConnected) {
28455
- this._messageBusService.emit(MessageType.RenderServiceConnected);
28456
- }
28457
- }, 2000);
28458
- }
28459
- getRenderParameters(type) {
28460
- const params = new RenderData();
28461
- if (type !== RenderModes.RenderIone) {
28462
- const currentImageSize = this.getImageSizeOnId(this.selectedImageSize);
28463
- params.imageWidth = Number(currentImageSize.width);
28464
- params.imageHeight = Number(currentImageSize.height);
28465
- }
28466
- params.configuredItem = this._getConfiguredFurnitureItem();
28467
- params.cameraFOV = this._cameraService.camera.fov;
28468
- params.type = type;
28469
- if (type === this.renderModes.RenderShop) {
28470
- params.cameraFOV = 30;
28471
- if (this._settingsService.settings.renderParameters.settings !== undefined) {
28472
- params.settings = this._settingsService.settings.renderParameters.settings;
28473
- }
28474
- }
28475
- else if (type === this.renderModes.RenderRoom) {
28476
- const renderEnvironment = this.getRenderEnvironmentOnId(this.selectedEnvironment);
28477
- params.settings = new RenderSettings();
28478
- params.settings.environmentHdr = renderEnvironment.hdrFile;
28479
- params.settings.environmentIntensity = renderEnvironment.intensity;
28480
- const floorPlanHasRooms = this._roomService.rooms[0];
28481
- const ceilingOrFloor = floorPlanHasRooms ? this._roomService.rooms[0].ceilingPlane : this._floorService.getFloorPlane();
28482
- const bb = new Box3().setFromObject(ceilingOrFloor);
28483
- const bbSize = new Vector3();
28484
- bb.getSize(bbSize);
28485
- params.settings.extraLights = [
28486
- {
28487
- x1: bb.min.x + this._ceilingLightMargin,
28488
- z1: bb.min.z + this._ceilingLightMargin,
28489
- x2: bb.max.x - this._ceilingLightMargin,
28490
- z2: bb.max.z - this._ceilingLightMargin,
28491
- height: floorPlanHasRooms ? ceilingOrFloor.position.y : 2.6,
28492
- }
28493
- ];
28494
- }
28495
- return params;
28496
- }
28497
- // The GLTFExporter needs lights to be configured like this,
28498
- // otherwise they will all point in the same direction.
28499
- _fixLight(element) {
28500
- element.target.parent = element;
28501
- element.lookAt(element.target.position);
28502
- element.target.position.x = 0;
28503
- element.target.position.y = 0;
28504
- element.target.position.z = -1;
28505
- }
28506
- _elementMustBeRemoved(element) {
28507
- if (element.type === 'PerspectiveCamera') {
28508
- return true;
28509
- }
28510
- if (!element.name) {
28511
- return false;
28512
- }
28513
- const lcName = element.name.toLowerCase();
28514
- // elements with a name starting with c_ are connectors,
28515
- // which should not be visible.
28516
- if (lcName.startsWith('c_')) {
28517
- return true;
28518
- }
28519
- if (element.name.startsWith('snapping-preview-mesh')) {
28520
- return true;
28521
- }
28522
- return false;
28523
- }
28524
- async _exportToGlb() {
28525
- const assetPath = this._settingsService.settings.assetPath;
28526
- // The ground plane looks odd in renders.
28527
- // The hud-ring and hud-circle are the walkthrough mode marker,
28528
- // which is not supposed to be rendered.
28529
- const elementsToRemove = ['ground-plane', 'hud-ring', 'hud-circle'];
28530
- let scene;
28531
- try {
28532
- scene = this._sceneService.scene.clone();
28533
- elementsToRemove.forEach(elementName => {
28534
- const selectedObject = scene.getObjectByName(elementName);
28535
- scene.remove(selectedObject);
28536
- });
28537
- // Using the parents, because scene.remove does not seem to work correctly.
28538
- const parents = [];
28539
- scene.traverse(element => {
28540
- if (element instanceof DirectionalLight || element instanceof SpotLight) {
28541
- this._fixLight(element);
28542
- }
28543
- if (element.visible === false) {
28544
- // console.log("Element " + element.name + " was invisible, making it visible.");
28545
- element.visible = true;
28546
- }
28547
- if (element instanceof Mesh && element.name && element.name.startsWith('customMeshWindow')) {
28548
- let hasCustomTexture = false;
28549
- if (element.material instanceof Material$1) {
28550
- if (element.material instanceof MeshPhongMaterial && element.material.map) {
28551
- hasCustomTexture = true;
28552
- }
28553
- element.material = RenderService.MakeWindowMaterialTransparent(element.material);
28554
- }
28555
- else if (Array.isArray(element.material)) {
28556
- element.material.forEach(function (material, index) {
28557
- if (material instanceof MeshPhongMaterial && material.map) {
28558
- hasCustomTexture = true;
28559
- }
28560
- element.material[index] = RenderService.MakeWindowMaterialTransparent(material);
28561
- });
28562
- }
28563
- if (!hasCustomTexture) {
28564
- element.name = 'glass';
28565
- }
28566
- }
28567
- if (this._elementMustBeRemoved(element)) {
28568
- parents.push(element.parent);
28569
- }
28570
- });
28571
- parents.forEach(parent => {
28572
- for (let i = parent.children.length - 1; i >= 0; i--) {
28573
- if (this._elementMustBeRemoved(parent.children[i])) {
28574
- parent.remove(parent.children[i]);
28575
- }
28576
- }
28577
- });
28578
- scene.add(this._cameraService.camera.clone());
28579
- const options = {
28580
- trs: false,
28581
- onlyVisible: false,
28582
- truncateDrawRange: true,
28583
- binary: true,
28584
- forceIndices: false,
28585
- forcePowerOfTwoTextures: false,
28586
- // maxTextureSize: 500,
28587
- embedImages: true,
28588
- };
28589
- const exporter = new GLTFExporter();
28590
- let filename = '';
28591
- return new Promise((resolve, reject) => {
28592
- exporter.parse(scene, async (exportedScene) => {
28593
- const blob = new Blob([exportedScene], { type: 'application/octet-stream' });
28594
- const result = await FileUtils.SaveGLBFile(blob, assetPath);
28595
- if (result !== false) {
28596
- filename = result.path;
28597
- }
28598
- resolve(filename);
28599
- }, () => {
28600
- }, options);
28601
- });
28602
- }
28603
- catch (e) {
28604
- throw (e);
28605
- }
28606
- }
28607
- async startRendering() {
28608
- if (this.renderQueue.length > 0) {
28609
- await this.checkConnection();
28610
- if (this.renderQueue[0].renderProgress === 0 || this.renderQueue[0].renderProgress === undefined) {
28611
- this.renderQueue[0].renderStatus = RenderStatus.IsRunning;
28612
- this.currentQueueRenderItem = this.renderQueue[0];
28613
- this.renderQueue.shift();
28614
- this.currentQueueRenderItem.params.glbPath = await this._exportToGlb()
28615
- .catch((e) => {
28616
- return Promise.reject(e);
28617
- });
28618
- await this._startRenderLoop();
28619
- }
28620
- }
28621
- }
28622
- async _colijnRenderScene(params) {
28623
- return new Promise((resolve, reject) => {
28624
- const requestParams = [{
28625
- id: 1,
28626
- jsonrpc: '2.0',
28627
- method: 'colijn_render_scene_from_glb',
28628
- params: params
28629
- }];
28630
- const xhr = new XMLHttpRequest();
28631
- xhr.open('POST', this._getRenderServiceUrl());
28632
- xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
28633
- xhr.onload = () => {
28634
- if (xhr.status >= 200 && xhr.status < 300) {
28635
- resolve(JSON.parse(xhr.responseText));
28636
- }
28637
- else {
28638
- reject(xhr.statusText);
28639
- }
28640
- };
28641
- xhr.onerror = () => reject(xhr.statusText);
28642
- xhr.send(JSON.stringify(requestParams));
28643
- });
28644
- }
28645
- async _startRenderLoop() {
28646
- // temporary solution because large request over websockets are not working because of an error in the software of migenius
28647
- let [info] = await this._colijnRenderScene(this.currentQueueRenderItem.params);
28648
- info = info.result;
28649
- /*
28650
- const [ info ] = await this.service.queue_commands()
28651
- .queue(new Command('colijn_render_scene', this.currentQueueRenderItem.params), true)
28652
- .execute();
28653
- */
28654
- this.currentQueueRenderItem.host = this._settingsService.settings.url;
28655
- this.currentQueueRenderItem.key = info.scene_name;
28656
- this.currentQueueRenderItem.type = this.currentQueueRenderItem.params.type;
28657
- this.currentQueueRenderItem.startDateTime = new Date();
28658
- this.currentQueueRenderItem.imageSize = this.currentQueueRenderItem.params.imageWidth + ' x ' + this.currentQueueRenderItem.params.imageHeight;
28659
- this._setRenderProgress(RenderStatus.IsRunning, 0, 0);
28660
- this.sceneData = info;
28661
- if (!this.sceneData || this.sceneData.error) {
28662
- return;
28663
- }
28664
- if (this.sceneData.image_info && this.sceneData.image_info.needs_render === true) {
28665
- this.currentQueueRenderItem.rendered = true;
28666
- await this._startRenderStream();
28667
- }
28668
- else {
28669
- this._afterRendering();
28670
- }
28671
- }
28672
- async _quitRenderLoop() {
28673
- // if (this.sceneData.loop_name !== undefined && this.service.validate() !== false) {
28674
- // const [] = await this.service.queue_commands()
28675
- // .queue(new Command('render_loop_quit', {
28676
- // render_loop_name: this.sceneData.loop_name
28677
- // }))
28678
- // .execute();
28679
- // this.service.remove_stream(this.sceneData.loop_name);
28680
- // }
28681
- }
28682
- async _startRenderStream() {
28683
- //
28684
- // try {
28685
- //
28686
- // this.streaming.stream = this.service.create_stream();
28687
- // await this.streaming.stream.start({render_loop_name: this.sceneData.loop_name, image_format: 'jpg', quality: '100'});
28688
- //
28689
- // this.streaming.stream.on('image', async (object) => {
28690
- // this._htmlImageDisplay(object, null);
28691
- // const [progress] = await this.service.queue_commands()
28692
- // .queue(new Command('render_loop_get_render_progress', {
28693
- // render_loop_name: this.sceneData.loop_name
28694
- // }), true)
28695
- // .execute();
28696
- //
28697
- // if (progress.progression !== undefined) {
28698
- // this._setRenderProgress(RenderStatus.IsRunning, Math.ceil((progress.progression * 100)), progress.iteration);
28699
- // }
28700
- //
28701
- // if (object.result === 1) {
28702
- //
28703
- // await this.service.queue_commands()
28704
- // .queue(new Command('render_loop_save_to_disk', {
28705
- // render_loop_name: this.sceneData.loop_name,
28706
- // format: 'jpg',
28707
- // quality: 90,
28708
- // path: this.sceneData.image_info.url
28709
- // }), true)
28710
- // .execute();
28711
- //
28712
- // if (this.streaming.stream !== undefined) {
28713
- // this.streaming.stream.stop();
28714
- // }
28715
- // await this._quitRenderLoop();
28716
- // this._afterRendering();
28717
- // return;
28718
- //
28719
- // } else if (object.result < 0) {
28720
- //
28721
- // await this._onRenderError();
28722
- // return;
28723
- // }
28724
- // });
28725
- //
28726
- // } catch (err) {
28727
- //
28728
- // await this._onRenderError();
28729
- // return;
28730
- // }
28731
- }
28732
- _setRenderProgress(status, progress, iterations) {
28733
- if (!this.serverData) {
28734
- return;
28735
- }
28736
- this.currentQueueRenderItem.endDateTime = new Date();
28737
- this.currentQueueRenderItem.renderStatus = status;
28738
- this.currentQueueRenderItem.renderProgress = progress;
28739
- if (iterations > 0) {
28740
- this.currentQueueRenderItem.renderIterations = iterations;
28741
- }
28742
- if (this.serverData.renderMode === RenderModes.RenderIone) {
28743
- const render = this.getRenderOnId(this.currentQueueRenderItem.params.render.id);
28744
- render.status = status;
28745
- render.progress = progress;
28746
- }
28747
- }
28748
- async _onRenderError() {
28749
- this._setRenderProgress(RenderStatus.IsStopped, 0, 0);
28750
- await this._quitRenderLoop();
28751
- }
28752
- async _onRenderClose() {
28753
- this._setRenderProgress(RenderStatus.IsStopped, 0, 0);
28754
- }
28755
- _afterRendering() {
28756
- if (!this.serverData) {
28757
- return;
28758
- }
28759
- this._setRenderProgress(RenderStatus.IsSuccess, 100, 0);
28760
- const imageUrl = this._settingsService.settings.assetPath.replace('content43/', '') + this.sceneData.image_info.url;
28761
- if (this.serverData.renderMode === RenderModes.RenderRoom) {
28762
- this.renderedRoomImages.unshift(imageUrl);
28763
- }
28764
- this.renderImageChanged.next(imageUrl);
28765
- if (this.serverData.renderMode === RenderModes.RenderIone) {
28766
- const render = this.getRenderOnId(this.currentQueueRenderItem.params.render.id);
28767
- render.url = imageUrl;
28768
- }
28769
- const configuredItem = this.currentQueueRenderItem.params.configuredItem;
28770
- const isSingleItem = this.serverData.renderMode !== RenderModes.RenderRoom;
28771
- this._googleTagManager.sendEvent(GoogleTagManagerEvent.Render, {
28772
- 'articleNr': isSingleItem ? configuredItem.sku : 'renderRoom',
28773
- 'product': isSingleItem ? configuredItem.name : 'renderRoom',
28774
- 'dimensions': this.currentQueueRenderItem.imageSize
28775
- });
28776
- this.startRendering();
28777
- }
28778
- _getRenderServiceUrl() {
28779
- return `${(this.serverData.secure ? 'https' : 'http')}://${this.serverData.host}:${this.serverData.port}`;
28780
- }
28781
- forceRenderImage() {
28782
- const floorGroup = this._getFirstCustomFloorItemFromScene();
28783
- if (floorGroup !== null) {
28784
- this._checkVisibleUpdates(floorGroup, true);
28785
- }
28786
- }
28787
- async _checkVisibleUpdates(furniture, forceRender = false) {
28788
- if (!this.serverData) {
28789
- return;
28790
- }
28791
- if (!furniture) {
28792
- return;
28793
- }
28794
- if (this.serverData.renderMode === this.renderModes.RenderIone) {
28795
- const object = this._exportService.getExportObjectFromCustomFloorGroup(furniture);
28796
- this.currentProductHash = object.defaultRenderPath;
28797
- }
28798
- else if (this.serverData.renderMode === this.renderModes.RenderShop) {
28799
- const object = this._exportService.getExportObjectFromCustomFloorGroup(furniture);
28800
- if (!(JSON.stringify(this.prevItem) !== JSON.stringify(object) || forceRender)) {
28801
- return;
28802
- }
28803
- this.renderingStarted.next();
28804
- this.prevItem = object;
28805
- const queueItem = new RenderQueueItem();
28806
- queueItem.params = this.getRenderParameters(this.renderModes.RenderShop);
28807
- queueItem.params.cameraMatrix = this._cameraService.camera.matrixWorldInverse.elements;
28808
- queueItem.params.forceRender = forceRender;
28809
- this.renderQueue = [];
28810
- this.renderQueue.push(queueItem);
28811
- await this.startRendering();
28812
- }
28813
- }
28814
- _htmlImageDisplay(image, urlCreator) {
28815
- try {
28816
- urlCreator = urlCreator || (window ? (window.URL || window.webkitURL) : undefined);
28817
- }
28818
- catch (e) {
28819
- }
28820
- const blob = new Blob([image.image], { type: image.mime_type });
28821
- const url = urlCreator.createObjectURL(blob);
28822
- this.renderRoomImageChanged.next(url);
28823
- }
28824
- getRenderOnId(id) {
28825
- let returnRender = null;
28826
- this.renders.forEach((x) => {
28827
- if (x.id === id) {
28828
- returnRender = x;
28829
- }
28830
- });
28831
- return returnRender;
28832
- }
28833
- getImageSizeOnId(id) {
28834
- let returnSize = null;
28835
- this.imageSizes.forEach((x) => {
28836
- if (x.id === id) {
28837
- returnSize = x;
28838
- }
28839
- });
28840
- return returnSize;
28841
- }
28842
- getRenderEnvironmentOnId(id) {
28843
- let returnEnvironment = null;
28844
- this.renderEnvironments.forEach((renderEnvironment) => {
28845
- if (renderEnvironment.id === id) {
28846
- returnEnvironment = renderEnvironment;
28847
- return;
28848
- }
28849
- });
28850
- return returnEnvironment;
28851
- }
28852
- getLightningOnId(id) {
28853
- let returnLightning = null;
28854
- this.lightnings.forEach((x) => {
28855
- if (x.id === id) {
28856
- returnLightning = x;
28857
- }
28858
- });
28859
- return returnLightning;
28860
- }
28861
- /******************************************** Export functions ********************************************/
28862
- _getFirstCustomFloorItemFromScene() {
28863
- const children = this._sceneService.scene.children;
28864
- if (children.length <= 0) {
28865
- return null;
28866
- }
28867
- for (let a = 0; a < children.length; a++) {
28868
- if (children[a] instanceof CustomFloorItem) {
28869
- return children[a];
28870
- }
28871
- if (children[a] instanceof ItemGroup) {
28872
- const itemGroup = children[a];
28873
- if (itemGroup.items.length > 0) {
28874
- itemGroup.items.forEach((item) => {
28875
- if (item instanceof CustomFloorItem) {
28876
- return item;
28877
- }
28878
- });
28879
- }
28880
- }
28881
- }
28882
- return null;
28883
- }
28884
- _getConfiguredFurnitureItem() {
28885
- const floorgroup = this._getFirstCustomFloorItemFromScene();
28886
- if (floorgroup === null) {
28887
- return null;
28888
- }
28889
- return this._exportService.getExportObjectFromCustomFloorGroup(floorgroup);
28890
- }
28891
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: RenderService, deps: [{ token: HomedecoratorSettingsService }, { token: ExportService }, { token: CameraService }, { token: SceneService }, { token: ToastService }, { token: MessageBusService }, { token: GoogleTagManagerService }, { token: RoomService }, { token: FloorService }], target: i0.ɵɵFactoryTarget.Injectable }); }
28892
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: RenderService }); }
28893
- }
28894
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: RenderService, decorators: [{
28895
- type: Injectable
28896
- }], ctorParameters: () => [{ type: HomedecoratorSettingsService }, { type: ExportService }, { type: CameraService }, { type: SceneService }, { type: ToastService }, { type: MessageBusService }, { type: GoogleTagManagerService }, { type: RoomService }, { type: FloorService }] });
28897
-
28898
28540
  class LoadFurnitureWithoutSceneService extends LoadFurnitureBaseService {
28899
28541
  loadFurniture(furnitureData, shouldCopyInstance, looseOriginalConfiguration, standAlone, fromScratch, fromPreset, loadFromProject) {
28900
28542
  throw new Error('Method not implemented.');
@@ -28937,7 +28579,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
28937
28579
  type: Injectable
28938
28580
  }], ctorParameters: () => [{ type: LoadFurnitureService }, { type: LoadFurnitureWithoutSceneService }, { type: HomedecoratorSettingsService }, { type: HomedecoratorConnectorService }] });
28939
28581
 
28940
- class NewRenderService {
28582
+ class RenderService {
28941
28583
  constructor(messageService, _settingsService, _buildFurnitureService, _cameraService, _sceneService, _ione, _ioneConnectorAdapter, _threedSelectorService, _toastService, _messageBusService, _googleTagManager, _roomService, _floorService, _wallService, _ceilingService, _loadFurnitureService, _utilsService, _presetService, _apiServiceModule, _appEventService, _dictionaryService) {
28942
28584
  this.messageService = messageService;
28943
28585
  this._settingsService = _settingsService;
@@ -28961,15 +28603,20 @@ class NewRenderService {
28961
28603
  this._appEventService = _appEventService;
28962
28604
  this._dictionaryService = _dictionaryService;
28963
28605
  this.renderImageChanged = new BehaviorSubject('');
28964
- this.renderImageError = new BehaviorSubject('');
28606
+ this.renderImageError = new Subject();
28965
28607
  this.blenderRenderStarted = new Subject();
28966
28608
  this.renderUpdateImageChanged = new BehaviorSubject(undefined);
28967
28609
  this.renderRoomImageChanged = new BehaviorSubject('');
28968
28610
  this.currentQueueRenderItem = new RenderQueueItem();
28969
28611
  this.renderedRoomImages = [];
28612
+ this.blendFilesRender = false;
28970
28613
  this._overWriteTransparency = false;
28971
28614
  this._subs = [];
28972
- this._subs.push(this.messageService.subscribe(MessageType.BlenderRenderFileReady, (file) => this.procesRenderFile(file)));
28615
+ this._subs.push(this.messageService.subscribe(MessageType.BlenderRenderFileReady, (file) => this.procesRenderFile(file)), this._settingsService.settingsLoaded.subscribe((loaded) => {
28616
+ if (loaded) {
28617
+ this.blendFilesRender = this._settingsService.settings.blendFilesRender;
28618
+ }
28619
+ }));
28973
28620
  }
28974
28621
  ngOnDestroy() {
28975
28622
  this._subs.forEach(s => s.unsubscribe());
@@ -28994,7 +28641,14 @@ class NewRenderService {
28994
28641
  }
28995
28642
  }
28996
28643
  async renderRoom(settings, preview = false) {
28997
- const sceneData = await this._exportToGlb();
28644
+ let sceneData;
28645
+ try {
28646
+ sceneData = await this._exportToGlb();
28647
+ }
28648
+ catch (e) {
28649
+ this.renderImageError.next(this._dictionaryService.get(e.message));
28650
+ return;
28651
+ }
28998
28652
  const data = this._getDataForRoomRender(settings);
28999
28653
  data.files = {
29000
28654
  glbData: this._arrayBufferToBase64(sceneData)
@@ -29018,6 +28672,21 @@ class NewRenderService {
29018
28672
  let scene;
29019
28673
  try {
29020
28674
  scene = this._sceneService.scene.clone(true);
28675
+ const masksToRemove = new Map();
28676
+ scene.traverse((child) => {
28677
+ if (child.parent && child instanceof Mesh && child.name && child.name.toLowerCase().indexOf('_mask') > -1) {
28678
+ masksToRemove.set(child.parent.uuid, child.uuid);
28679
+ }
28680
+ });
28681
+ masksToRemove.forEach((maskUuid, parentUuid) => {
28682
+ const parent = scene.getObjectByProperty('uuid', parentUuid);
28683
+ if (parent) {
28684
+ const mask = parent.getObjectByProperty('uuid', maskUuid);
28685
+ if (mask) {
28686
+ parent.remove(mask);
28687
+ }
28688
+ }
28689
+ });
29021
28690
  const lightsToRemove = scene.children.filter(c => c instanceof Light);
29022
28691
  lightsToRemove.forEach(light => {
29023
28692
  if ((light instanceof SpotLight || light instanceof DirectionalLight) && light.target) {
@@ -29038,6 +28707,10 @@ class NewRenderService {
29038
28707
  if (!this._cameraService.isCameraFacingFront(wall) && !wall.orphan && !wall.isInnerWall()) {
29039
28708
  wall.name = 'CULLING_wall';
29040
28709
  }
28710
+ wall.userData = {};
28711
+ // for (let i = wall.children.length; i >= 0; i--) {
28712
+ // wall.remove(wall.children[i]);
28713
+ // }
29041
28714
  });
29042
28715
  const ceilings = scene.children.filter(c => c.name && c.name === this._ceilingService.ceilingName);
29043
28716
  ceilings.forEach(ceiling => {
@@ -29056,7 +28729,9 @@ class NewRenderService {
29056
28729
  embedImages: true,
29057
28730
  };
29058
28731
  scene.name = 'mrp_room_' + scene.uuid;
29059
- const glb = await this._getGlbFromObject(scene, options);
28732
+ const glb = await this._getGlbFromObject(scene, options).catch((error) => {
28733
+ throw (error);
28734
+ });
29060
28735
  // this._utilsService.downloadFile(scene.name + '.glb', new Blob([glb], {type: 'model/gltf-binary'}));
29061
28736
  ObjectUtils.DisposeObject(scene);
29062
28737
  scene = null;
@@ -29071,7 +28746,8 @@ class NewRenderService {
29071
28746
  return new Promise((resolve, reject) => {
29072
28747
  exporter.parse(object, async (exportedScene) => {
29073
28748
  resolve(exportedScene);
29074
- }, () => {
28749
+ }, (error) => {
28750
+ reject(error);
29075
28751
  }, options);
29076
28752
  });
29077
28753
  }
@@ -29190,7 +28866,19 @@ class NewRenderService {
29190
28866
  method: 'POST',
29191
28867
  data: JSON.stringify(data),
29192
28868
  url: `${host}getRenderFromGlb`,
29193
- responseType: 'json'
28869
+ responseType: 'json',
28870
+ onUploadProgress: (progressEvent) => {
28871
+ const total = progressEvent.total ?? 0;
28872
+ if (total > 0) {
28873
+ const percent = Math.round((progressEvent.loaded * 100) / total);
28874
+ this._messageBusService.emit(MessageType.RenderUploadProgress, percent);
28875
+ if (percent >= 100) {
28876
+ this._messageBusService.emit(MessageType.RenderUploadFinished, true);
28877
+ }
28878
+ }
28879
+ }
28880
+ }).catch((error) => {
28881
+ return error;
29194
28882
  });
29195
28883
  if (result.status === 200) {
29196
28884
  // const image = `data:${result.data.fileType};base64,${result.data.image}`;
@@ -29211,7 +28899,12 @@ class NewRenderService {
29211
28899
  this.renderImageError.next(this._dictionaryService.get('BLENDER_PRODUCT_RENDER_ERROR'));
29212
28900
  }
29213
28901
  // Remove the loading indicator.
29214
- this._messageBusService.emit(MessageType.RenderUploadFinished, true);
28902
+ this._messageBusService.emit(MessageType.RenderFinished, true);
28903
+ }
28904
+ else {
28905
+ this.renderImageChanged.next('');
28906
+ this.renderImageError.next(this._dictionaryService.get('BLENDER_PRODUCT_RENDER_ERROR'));
28907
+ this._messageBusService.emit(MessageType.RenderFinished, true);
29215
28908
  }
29216
28909
  }
29217
28910
  }
@@ -29530,10 +29223,10 @@ class NewRenderService {
29530
29223
  this._overWriteTransparency = true;
29531
29224
  }
29532
29225
  }
29533
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: NewRenderService, deps: [{ token: MessageBusService }, { token: HomedecoratorSettingsService }, { token: SwitchBuildFurnitureService }, { token: CameraService }, { token: SceneService }, { token: HomedecoratorConnectorService }, { token: HomedecoratorConnectorAdapterService }, { token: ThreedselectorService }, { token: ToastService }, { token: MessageBusService }, { token: GoogleTagManagerService }, { token: RoomService }, { token: FloorService }, { token: WallService }, { token: CeilingService }, { token: SwitchLoadFurnitureService }, { token: UtilsService }, { token: PresetsService }, { token: ApiServiceModule }, { token: HomedecoratorAppEventService }, { token: HomedecoratorDictionaryService }], target: i0.ɵɵFactoryTarget.Injectable }); }
29534
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: NewRenderService }); }
29226
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: RenderService, deps: [{ token: MessageBusService }, { token: HomedecoratorSettingsService }, { token: SwitchBuildFurnitureService }, { token: CameraService }, { token: SceneService }, { token: HomedecoratorConnectorService }, { token: HomedecoratorConnectorAdapterService }, { token: ThreedselectorService }, { token: ToastService }, { token: MessageBusService }, { token: GoogleTagManagerService }, { token: RoomService }, { token: FloorService }, { token: WallService }, { token: CeilingService }, { token: SwitchLoadFurnitureService }, { token: UtilsService }, { token: PresetsService }, { token: ApiServiceModule }, { token: HomedecoratorAppEventService }, { token: HomedecoratorDictionaryService }], target: i0.ɵɵFactoryTarget.Injectable }); }
29227
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: RenderService }); }
29535
29228
  }
29536
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: NewRenderService, decorators: [{
29229
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: RenderService, decorators: [{
29537
29230
  type: Injectable
29538
29231
  }], ctorParameters: () => [{ type: MessageBusService }, { type: HomedecoratorSettingsService }, { type: SwitchBuildFurnitureService }, { type: CameraService }, { type: SceneService }, { type: HomedecoratorConnectorService }, { type: HomedecoratorConnectorAdapterService }, { type: ThreedselectorService }, { type: ToastService }, { type: MessageBusService }, { type: GoogleTagManagerService }, { type: RoomService }, { type: FloorService }, { type: WallService }, { type: CeilingService }, { type: SwitchLoadFurnitureService }, { type: UtilsService }, { type: PresetsService }, { type: ApiServiceModule }, { type: HomedecoratorAppEventService }, { type: HomedecoratorDictionaryService }] });
29539
29232
 
@@ -30395,6 +30088,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
30395
30088
  type: Injectable
30396
30089
  }], ctorParameters: () => [{ type: HomedecoratorSettingsService }, { type: HomedecoratorConnectorService }] });
30397
30090
 
30091
+ var ToastType;
30092
+ (function (ToastType) {
30093
+ ToastType[ToastType["Success"] = 0] = "Success";
30094
+ ToastType[ToastType["Warning"] = 1] = "Warning";
30095
+ ToastType[ToastType["Error"] = 2] = "Error";
30096
+ })(ToastType || (ToastType = {}));
30097
+
30098
+ class Toast {
30099
+ constructor() {
30100
+ this.type = ToastType.Success;
30101
+ }
30102
+ }
30103
+
30398
30104
  class ConnectionHeathService {
30399
30105
  constructor(_http, _settingService, _toastService, _messageService) {
30400
30106
  this._http = _http;
@@ -30779,9 +30485,9 @@ class FloorplanRenderService {
30779
30485
  }
30780
30486
  this._clear();
30781
30487
  this._drawGrid();
30782
- // if (this.diagramBackground && this.showDiagramBackground) {
30783
- // this._drawBackground();
30784
- // }
30488
+ if (this.diagramBackground && this.showDiagramBackground) {
30489
+ this._drawBackground();
30490
+ }
30785
30491
  this._drawRooms();
30786
30492
  this._drawWallsWithNoRoom();
30787
30493
  if (this._state.showWallItemMeasurements && this._state.activeItem) {
@@ -30821,6 +30527,24 @@ class FloorplanRenderService {
30821
30527
  ContextUtils.DrawLine(context, 0, gridSpacing * y + offsetY, canvas.width, gridSpacing * y + offsetY, gridWidth, gridColor);
30822
30528
  }
30823
30529
  }
30530
+ _drawBackground() {
30531
+ const context = this._state.context;
30532
+ if (this.diagramBackgroundActiveZoom) {
30533
+ if (this.diagramBackgroundCurrentScale <= this._coordinatesService.viewScale) {
30534
+ this.diagramBackgroundWidth = this.diagramBackgroundWidth * this._coordinatesService.scalingFactor;
30535
+ this.diagramBackgroundHeight = this.diagramBackgroundHeight * this._coordinatesService.scalingFactor;
30536
+ }
30537
+ else {
30538
+ this.diagramBackgroundWidth = this.diagramBackgroundWidth * (1 / this._coordinatesService.scalingFactor);
30539
+ this.diagramBackgroundHeight = this.diagramBackgroundHeight * (1 / this._coordinatesService.scalingFactor);
30540
+ }
30541
+ this.diagramBackgroundActiveZoom = false;
30542
+ }
30543
+ this.diagramBackgroundCurrentScale = this._coordinatesService.viewScale;
30544
+ context.globalAlpha = this.diagramBackgroundAlpha;
30545
+ context.drawImage(this.diagramBackground, Math.abs(this._coordinatesService.originX) - (this.diagramBackgroundWidth * this.diagramBackgroundScale / 2), Math.abs(this._coordinatesService.originY) - (this.diagramBackgroundHeight * this.diagramBackgroundScale / 2), this.diagramBackgroundWidth * this.diagramBackgroundScale, this.diagramBackgroundHeight * this.diagramBackgroundScale);
30546
+ context.globalAlpha = 1;
30547
+ }
30824
30548
  _drawRooms() {
30825
30549
  const rooms = this._state.rooms;
30826
30550
  rooms.forEach(room => {
@@ -31479,9 +31203,8 @@ const APPLICATION_SERVICES_PROVIDERS = [
31479
31203
  DynamicCameraService,
31480
31204
  ThreedInPhotoInitializerService,
31481
31205
  ThreedInPhotoBuildService,
31482
- RenderService,
31483
31206
  ExportService,
31484
- NewRenderService,
31207
+ RenderService,
31485
31208
  AppInitializerService,
31486
31209
  JsonUtilsService,
31487
31210
  RalService,
@@ -33725,108 +33448,142 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
33725
33448
  class BlenderRenderSettings {
33726
33449
  }
33727
33450
 
33728
- class RenderProgressComponent {
33729
- set show(show) {
33730
- this._show = show;
33731
- if (show) {
33732
- this._progressService.progressBarType = ProgressType.Upload;
33733
- this._progressService.total = 100;
33451
+ // A pipe for appending strings to other strings in view templates.
33452
+ class AppendPipe {
33453
+ transform(value, append) {
33454
+ if (!value) {
33455
+ return '';
33734
33456
  }
33735
- else {
33736
- this._progressService.progressBarType = ProgressType.Download;
33737
- this._progressService.total = 0;
33457
+ if (!append) {
33458
+ return value;
33738
33459
  }
33460
+ return value + append;
33739
33461
  }
33740
- get show() {
33741
- return this._show;
33742
- }
33743
- get progressValue() {
33744
- return this.progress + '/ 100%';
33745
- }
33746
- constructor(_messageService, _progressService) {
33462
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AppendPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
33463
+ static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.3.16", ngImport: i0, type: AppendPipe, isStandalone: false, name: "append" }); }
33464
+ }
33465
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AppendPipe, decorators: [{
33466
+ type: Pipe,
33467
+ args: [{
33468
+ name: 'append',
33469
+ standalone: false
33470
+ }]
33471
+ }] });
33472
+
33473
+ class RenderProgressComponent {
33474
+ constructor(_messageService) {
33747
33475
  this._messageService = _messageService;
33748
- this._progressService = _progressService;
33476
+ this.title = 'UPLOADING_ROOM';
33749
33477
  this.progress = 0;
33478
+ this.rendering = false;
33750
33479
  this._subs = [];
33751
- this._show = false;
33752
- this._subs.push(this._messageService.subscribe(MessageType.RenderUploadProgress, (progress) => this.updateProgress(progress)));
33480
+ this._subs.push(this._messageService.subscribe(MessageType.RenderUploadFinished, (ready) => {
33481
+ if (ready) {
33482
+ this.title = 'RENDERING_ROOM';
33483
+ this.rendering = true;
33484
+ }
33485
+ }), this._messageService.subscribe(MessageType.RenderUploadProgress, (progress) => this.updateProgress(progress)));
33753
33486
  }
33754
33487
  ngOnDestroy() {
33755
33488
  this._subs.forEach(sub => sub.unsubscribe());
33756
33489
  }
33757
33490
  updateProgress(progress) {
33758
- this.progress = progress;
33759
- this._progressService.progress = progress;
33491
+ this.progress = Math.max(0, Math.min(100, progress));
33760
33492
  }
33761
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: RenderProgressComponent, deps: [{ token: MessageBusService }, { token: ProgressService }], target: i0.ɵɵFactoryTarget.Component }); }
33762
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: RenderProgressComponent, isStandalone: false, selector: "rp-render-progress", inputs: { show: "show", title: "title" }, ngImport: i0, template: `
33763
- @if (show) {
33493
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: RenderProgressComponent, deps: [{ token: MessageBusService }], target: i0.ɵɵFactoryTarget.Component }); }
33494
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: RenderProgressComponent, isStandalone: false, selector: "rp-render-progress", ngImport: i0, template: `
33764
33495
  <div class="render-progress-model">
33765
33496
  <div class="model">
33766
33497
  <div class="model-header-container">
33767
- <h3 class="model-header" [textContent]="title"></h3>
33768
- <div class="close" (click)="show = false">
33769
- <mat-icon class="homedecorator-material-icons">cancel</mat-icon>
33770
- </div>
33498
+ <h3 class="model-header" [textContent]="title | localize"></h3>
33499
+ <!--
33500
+ <div class="close" (click)="show = false">
33501
+ <mat-icon class="homedecorator-material-icons">cancel</mat-icon>
33502
+ </div>
33503
+ -->
33771
33504
  </div>
33772
33505
  <div class="model-content-container">
33773
- <span class="progress-text" [textContent]="progressValue"></span>
33506
+ @if (!rendering) {
33507
+ <div class="progress-bar" role="progressbar" [attr.aria-valuenow]="progress" aria-valuemin="0" aria-valuemax="100">
33508
+ <div class="progress-bar-fill" [style.width.%]="progress"></div>
33509
+ <span class="progress-bar-text" [textContent]="progress.toString() | append:'%'"></span>
33510
+ </div>
33511
+ } @else {
33512
+ <span class="loading-dots" aria-hidden="true">
33513
+ <span></span>
33514
+ <span></span>
33515
+ <span></span>
33516
+ </span>
33517
+ }
33774
33518
  </div>
33775
33519
  </div>
33776
33520
  </div>
33777
- }
33778
- `, isInline: true, styles: [".render-progress-model{position:fixed;inset:0;z-index:100;background-color:#0003}.render-progress-model .model{width:400px;position:relative;top:20%;left:50%;margin-left:-200px;background:#fff;border-radius:10px;box-sizing:border-box;box-shadow:1px 0 20px #0000001f}.render-progress-model .model .model-header-container{display:flex;justify-content:space-between;border-bottom:1px solid #c5c3c6;padding:20px 20px 10px;align-items:center}.render-progress-model .model .model-header-container .close mat-icon{fill:#c5c3c6;color:#c5c3c6;cursor:pointer;transition:all .2s ease}.render-progress-model .model .model-header-container .close:hover mat-icon{fill:#46494c;color:#46494c}.render-progress-model .model .model-content-container{padding:20px}.render-progress-model .model .model-content-container .progress-text{text-align:center;margin-top:10px;display:block}.render-progress-model .model .model-content-container .progress-container{width:100%;height:25px;background-color:#e0e0e0;border-radius:12px;overflow:hidden}.render-progress-model .model .model-content-container .progress-fill{height:100%;background-color:#da9803;transition:width .3s ease-in-out}\n"], dependencies: [{ kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }] }); }
33521
+ `, isInline: true, styles: [".render-progress-model{position:fixed;inset:0;z-index:100;background-color:#0003}.render-progress-model .model{width:400px;position:relative;top:20%;left:50%;margin-left:-200px;background:#fff;border-radius:10px;box-sizing:border-box;box-shadow:1px 0 20px #0000001f}.render-progress-model .model .model-header-container{display:flex;justify-content:space-between;border-bottom:1px solid #c5c3c6;padding:20px 20px 10px;align-items:center}.render-progress-model .model .model-header-container .close mat-icon{fill:#c5c3c6;color:#c5c3c6;cursor:pointer;transition:all .2s ease}.render-progress-model .model .model-header-container .close:hover mat-icon{fill:#46494c;color:#46494c}.render-progress-model .model .model-content-container{display:flex;justify-content:center;padding:20px}.render-progress-model .model .model-content-container .progress-container{width:100%;height:25px;background-color:#e0e0e0;border-radius:12px;overflow:hidden}.render-progress-model .model .model-content-container .progress-bar{position:relative;width:100%;height:18px;overflow:hidden;border-radius:999px;background-color:#e5e7eb}.render-progress-model .model .model-content-container .progress-bar-text{position:absolute;inset:0;color:#171721;display:flex;align-items:center;justify-content:center}.render-progress-model .model .model-content-container .progress-bar-fill{height:100%;width:0;background:linear-gradient(90deg,#da9803,#fff);transition:width .3s ease}.render-progress-model .model .model-content-container .loading-dots{display:inline-flex;gap:2px;margin-left:4px}.render-progress-model .model .model-content-container .loading-dots span{width:4px;height:4px;border-radius:50%;background-color:#171721;opacity:.25;animation:loading-dot 1.2s infinite ease-in-out}.render-progress-model .model .model-content-container .loading-dots span:nth-child(2){animation-delay:.2s}.render-progress-model .model .model-content-container .loading-dots span:nth-child(3){animation-delay:.4s}@keyframes loading-dot{0%,80%,to{opacity:.25;transform:translateY(0)}40%{opacity:1;transform:translateY(-2px)}}\n"], dependencies: [{ kind: "pipe", type: LocalizePipe, name: "localize" }, { kind: "pipe", type: AppendPipe, name: "append" }] }); }
33779
33522
  }
33780
33523
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: RenderProgressComponent, decorators: [{
33781
33524
  type: Component,
33782
33525
  args: [{ selector: 'rp-render-progress', template: `
33783
- @if (show) {
33784
33526
  <div class="render-progress-model">
33785
33527
  <div class="model">
33786
33528
  <div class="model-header-container">
33787
- <h3 class="model-header" [textContent]="title"></h3>
33788
- <div class="close" (click)="show = false">
33789
- <mat-icon class="homedecorator-material-icons">cancel</mat-icon>
33790
- </div>
33529
+ <h3 class="model-header" [textContent]="title | localize"></h3>
33530
+ <!--
33531
+ <div class="close" (click)="show = false">
33532
+ <mat-icon class="homedecorator-material-icons">cancel</mat-icon>
33533
+ </div>
33534
+ -->
33791
33535
  </div>
33792
33536
  <div class="model-content-container">
33793
- <span class="progress-text" [textContent]="progressValue"></span>
33537
+ @if (!rendering) {
33538
+ <div class="progress-bar" role="progressbar" [attr.aria-valuenow]="progress" aria-valuemin="0" aria-valuemax="100">
33539
+ <div class="progress-bar-fill" [style.width.%]="progress"></div>
33540
+ <span class="progress-bar-text" [textContent]="progress.toString() | append:'%'"></span>
33541
+ </div>
33542
+ } @else {
33543
+ <span class="loading-dots" aria-hidden="true">
33544
+ <span></span>
33545
+ <span></span>
33546
+ <span></span>
33547
+ </span>
33548
+ }
33794
33549
  </div>
33795
33550
  </div>
33796
33551
  </div>
33797
- }
33798
- `, standalone: false, styles: [".render-progress-model{position:fixed;inset:0;z-index:100;background-color:#0003}.render-progress-model .model{width:400px;position:relative;top:20%;left:50%;margin-left:-200px;background:#fff;border-radius:10px;box-sizing:border-box;box-shadow:1px 0 20px #0000001f}.render-progress-model .model .model-header-container{display:flex;justify-content:space-between;border-bottom:1px solid #c5c3c6;padding:20px 20px 10px;align-items:center}.render-progress-model .model .model-header-container .close mat-icon{fill:#c5c3c6;color:#c5c3c6;cursor:pointer;transition:all .2s ease}.render-progress-model .model .model-header-container .close:hover mat-icon{fill:#46494c;color:#46494c}.render-progress-model .model .model-content-container{padding:20px}.render-progress-model .model .model-content-container .progress-text{text-align:center;margin-top:10px;display:block}.render-progress-model .model .model-content-container .progress-container{width:100%;height:25px;background-color:#e0e0e0;border-radius:12px;overflow:hidden}.render-progress-model .model .model-content-container .progress-fill{height:100%;background-color:#da9803;transition:width .3s ease-in-out}\n"] }]
33799
- }], ctorParameters: () => [{ type: MessageBusService }, { type: ProgressService }], propDecorators: { show: [{
33800
- type: Input
33801
- }], title: [{
33802
- type: Input
33803
- }] } });
33552
+ `, standalone: false, styles: [".render-progress-model{position:fixed;inset:0;z-index:100;background-color:#0003}.render-progress-model .model{width:400px;position:relative;top:20%;left:50%;margin-left:-200px;background:#fff;border-radius:10px;box-sizing:border-box;box-shadow:1px 0 20px #0000001f}.render-progress-model .model .model-header-container{display:flex;justify-content:space-between;border-bottom:1px solid #c5c3c6;padding:20px 20px 10px;align-items:center}.render-progress-model .model .model-header-container .close mat-icon{fill:#c5c3c6;color:#c5c3c6;cursor:pointer;transition:all .2s ease}.render-progress-model .model .model-header-container .close:hover mat-icon{fill:#46494c;color:#46494c}.render-progress-model .model .model-content-container{display:flex;justify-content:center;padding:20px}.render-progress-model .model .model-content-container .progress-container{width:100%;height:25px;background-color:#e0e0e0;border-radius:12px;overflow:hidden}.render-progress-model .model .model-content-container .progress-bar{position:relative;width:100%;height:18px;overflow:hidden;border-radius:999px;background-color:#e5e7eb}.render-progress-model .model .model-content-container .progress-bar-text{position:absolute;inset:0;color:#171721;display:flex;align-items:center;justify-content:center}.render-progress-model .model .model-content-container .progress-bar-fill{height:100%;width:0;background:linear-gradient(90deg,#da9803,#fff);transition:width .3s ease}.render-progress-model .model .model-content-container .loading-dots{display:inline-flex;gap:2px;margin-left:4px}.render-progress-model .model .model-content-container .loading-dots span{width:4px;height:4px;border-radius:50%;background-color:#171721;opacity:.25;animation:loading-dot 1.2s infinite ease-in-out}.render-progress-model .model .model-content-container .loading-dots span:nth-child(2){animation-delay:.2s}.render-progress-model .model .model-content-container .loading-dots span:nth-child(3){animation-delay:.4s}@keyframes loading-dot{0%,80%,to{opacity:.25;transform:translateY(0)}40%{opacity:1;transform:translateY(-2px)}}\n"] }]
33553
+ }], ctorParameters: () => [{ type: MessageBusService }] });
33804
33554
 
33805
33555
  class RenderControlsComponent {
33806
33556
  get disablePictureButton() {
33807
- return this._newRenderService.currentQueueRenderItem.renderStatus === this.renderStatus.IsRunning;
33557
+ return this.renderService.currentQueueRenderItem.renderStatus === this.renderStatus.IsRunning;
33808
33558
  }
33809
- constructor(renderService, messageService, viewModeService, settingsService, iconService, _dialog, _sceneService, _cameraService, _configurationService, _settingsService, _newRenderService, _utilsService, _roomService, _wallMeasurementsService, _connectionHealthService, _dictionaryService) {
33810
- this.renderService = renderService;
33559
+ constructor(messageService, viewModeService, settingsService, iconService, renderService, _dialog, _sceneService, _cameraService, _configurationService, _settingsService, _utilsService, _roomService, _wallMeasurementsService, _connectionHealthService, _dictionaryService, _dialogService) {
33811
33560
  this.messageService = messageService;
33812
33561
  this.viewModeService = viewModeService;
33813
33562
  this.settingsService = settingsService;
33814
33563
  this.iconService = iconService;
33564
+ this.renderService = renderService;
33815
33565
  this._dialog = _dialog;
33816
33566
  this._sceneService = _sceneService;
33817
33567
  this._cameraService = _cameraService;
33818
33568
  this._configurationService = _configurationService;
33819
33569
  this._settingsService = _settingsService;
33820
- this._newRenderService = _newRenderService;
33821
33570
  this._utilsService = _utilsService;
33822
33571
  this._roomService = _roomService;
33823
33572
  this._wallMeasurementsService = _wallMeasurementsService;
33824
33573
  this._connectionHealthService = _connectionHealthService;
33825
33574
  this._dictionaryService = _dictionaryService;
33575
+ this._dialogService = _dialogService;
33826
33576
  this.viewModes = ViewMode;
33827
33577
  this.renderStatus = RenderStatus;
33828
33578
  this.icons = IconEnum;
33829
33579
  this.renderModes = RenderModes;
33580
+ this.imageSizes = [
33581
+ { id: 1, name: ' 720p (HD)', width: 1280, height: 720 },
33582
+ { id: 2, name: '1080P (HD)', width: 1920, height: 1080 },
33583
+ { id: 3, name: '1440p (2K)', width: 2560, height: 1440 },
33584
+ { id: 4, name: '2160p (4K)', width: 4096, height: 2160 }
33585
+ ];
33586
+ this.selectedImageSize = this.imageSizes[1];
33830
33587
  this.hdriIntensity = 1;
33831
33588
  this.hdriRotation = 0;
33832
33589
  this.lightingExposure = 1;
@@ -33839,14 +33596,22 @@ class RenderControlsComponent {
33839
33596
  this.showCullingErrorDialog = false;
33840
33597
  this.startUploading = false;
33841
33598
  this._subs = [];
33842
- this._subs.push(this.messageService.subscribe(MessageType.BlenderRenderPreviewReady, (file) => this.showPreview(file)), this.messageService.subscribe(MessageType.RenderUploadFinished, (ready) => this.hideUploadDialog(ready)), this.messageService.subscribe(MessageType.RenderError, () => this.hideUploadDialog(true)), this._cameraService.cameraMovementChanged.subscribe(() => {
33599
+ this._subs.push(this.messageService.subscribe(MessageType.BlenderRenderPreviewReady, (file) => this.showPreview(file)), this.messageService.subscribe(MessageType.RenderFinished, (ready) => this.hideUploadDialog(ready)), this.messageService.subscribe(MessageType.RenderError, () => this.hideUploadDialog(true)), this._cameraService.cameraMovementChanged.subscribe(() => {
33843
33600
  this._validateRenderPosition();
33844
33601
  // Make sure when the camera moves, we recheck the position and if we still need to show the render warning.
33602
+ }), this.renderService.renderImageError.subscribe((error) => {
33603
+ if (error) {
33604
+ this.hideUploadDialog(true);
33605
+ this._dialogService.showDialog({ data: { title: 'Error', messages: [{ message: error }], type: 'error' } });
33606
+ }
33845
33607
  }));
33846
33608
  }
33847
33609
  ngOnInit() {
33848
33610
  this.getRenderScenesFromSettings();
33849
33611
  }
33612
+ ngOnDestroy() {
33613
+ this._subs.forEach((sub) => sub.unsubscribe());
33614
+ }
33850
33615
  showRenderForm(event) {
33851
33616
  this.inPictureMode = !this.inPictureMode;
33852
33617
  this._validateRenderPosition();
@@ -33860,16 +33625,14 @@ class RenderControlsComponent {
33860
33625
  this.startUploading = false;
33861
33626
  }
33862
33627
  }
33863
- createBlenderRender() {
33628
+ createBlenderRender(preview = false) {
33864
33629
  if (!this.showCullingErrorDialog) {
33865
33630
  if (this.viewModeService.isTopViewActive()) {
33866
33631
  this._wallMeasurementsService.prepMeasurementsForRender();
33867
33632
  }
33868
- this.messageService.emit(MessageType.ShowLoadingIndicator, { title: this._dictionaryService.get('PREPARE_TO_RENDER') });
33869
33633
  this.startUploading = true;
33870
33634
  // only render when the showCullingErrorDialog is false
33871
33635
  // this.messageService.emit(MessageType.ShowLoadingIndicator, {title: 'Uploading...'});
33872
- const renderSize = this.renderService.getImageSizeOnId(this.renderService.selectedImageSize);
33873
33636
  const renderSceneAssetId = this.selectedRenderScene;
33874
33637
  if (this.lightingExposure < 1) {
33875
33638
  this.lightingExposure = 1;
@@ -33877,15 +33640,15 @@ class RenderControlsComponent {
33877
33640
  this._validateRenderPosition(); // Check the camera position
33878
33641
  const allowCulling = this._allowCulling(this.hasError);
33879
33642
  const renderInput = new BlenderRenderSettings();
33880
- renderInput.height = renderSize.height;
33881
- renderInput.width = renderSize.width;
33643
+ renderInput.height = preview ? 150 : this.selectedImageSize.height;
33644
+ renderInput.width = preview ? 275 : this.selectedImageSize.width;
33882
33645
  renderInput.sceneAsset = renderSceneAssetId;
33883
33646
  renderInput.hdriIntensity = this.hdriIntensity;
33884
33647
  renderInput.hdriRotation = this.hdriRotation;
33885
33648
  renderInput.lightingExposure = this.lightingExposure;
33886
33649
  renderInput.allowCulling = allowCulling;
33887
33650
  // this._utilsService.prepRoomForRender(false, renderInput);
33888
- this._newRenderService.renderRoom(renderInput);
33651
+ this.renderService.renderRoom(renderInput, preview);
33889
33652
  if (this.viewModeService.isTopViewActive()) {
33890
33653
  this._wallMeasurementsService.restoreMeasurementsAfterRender();
33891
33654
  }
@@ -33913,35 +33676,6 @@ class RenderControlsComponent {
33913
33676
  this._cameraService.camera.position.set(movingPosition.x, movingPosition.y, movingPosition.z);
33914
33677
  this._cameraService.cameraMovementChanged.next();
33915
33678
  }
33916
- createPreviewRender() {
33917
- if (!this.showCullingErrorDialog) {
33918
- if (this.viewModeService.isTopViewActive()) {
33919
- this._wallMeasurementsService.prepMeasurementsForRender();
33920
- }
33921
- const renderSceneAssetId = this.selectedRenderScene;
33922
- // this.messageService.emit(MessageType.ShowLoadingIndicator, {title: 'Uploading...'});
33923
- // this.messageService.emit(MessageType.ShowLoadingIndicator, {title: this._dictionaryService.get('PREPARE_TO_RENDER')});
33924
- this.startUploading = true;
33925
- if (this.lightingExposure < 1) {
33926
- this.lightingExposure = 1;
33927
- }
33928
- this._validateRenderPosition(); // Check the camera position
33929
- const allowCulling = this._allowCulling(this.hasError);
33930
- const renderInput = new BlenderRenderSettings();
33931
- renderInput.height = 150;
33932
- renderInput.width = 275;
33933
- renderInput.sceneAsset = renderSceneAssetId;
33934
- renderInput.hdriIntensity = this.hdriIntensity;
33935
- renderInput.hdriRotation = this.hdriRotation;
33936
- renderInput.lightingExposure = this.lightingExposure;
33937
- renderInput.allowCulling = allowCulling;
33938
- // this._utilsService.prepRoomForRender(false, renderInput, true);
33939
- this._newRenderService.renderRoom(renderInput, true);
33940
- if (this.viewModeService.isTopViewActive()) {
33941
- this._wallMeasurementsService.restoreMeasurementsAfterRender();
33942
- }
33943
- }
33944
- }
33945
33679
  showPreview(image) {
33946
33680
  this.blenderPreviewRender = image;
33947
33681
  }
@@ -34026,465 +33760,413 @@ class RenderControlsComponent {
34026
33760
  // }
34027
33761
  // return allowCulling;
34028
33762
  }
34029
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: RenderControlsComponent, deps: [{ token: RenderService }, { token: MessageBusService }, { token: ViewModeService }, { token: HomedecoratorSettingsService }, { token: HomedecoratorIconCacheService }, { token: i1$2.MatDialog }, { token: SceneService }, { token: CameraService }, { token: ConfigurationService }, { token: HomedecoratorSettingsService }, { token: NewRenderService }, { token: UtilsService }, { token: RoomService }, { token: WallMeasurementsService }, { token: ConnectionHeathService }, { token: HomedecoratorDictionaryService }], target: i0.ɵɵFactoryTarget.Component }); }
33763
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: RenderControlsComponent, deps: [{ token: MessageBusService }, { token: ViewModeService }, { token: HomedecoratorSettingsService }, { token: HomedecoratorIconCacheService }, { token: RenderService }, { token: i1$2.MatDialog }, { token: SceneService }, { token: CameraService }, { token: ConfigurationService }, { token: HomedecoratorSettingsService }, { token: UtilsService }, { token: RoomService }, { token: WallMeasurementsService }, { token: ConnectionHeathService }, { token: HomedecoratorDictionaryService }, { token: DialogService }], target: i0.ɵɵFactoryTarget.Component }); }
34030
33764
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: RenderControlsComponent, isStandalone: false, selector: "rp-render-controls", viewQueries: [{ propertyName: "renderButton", first: true, predicate: ["renderButton"], descendants: true }], ngImport: i0, template: `
34031
- @if (renderService.serverData && renderService.serverData.renderMode !== renderService.renderModes.RenderShop) {
34032
- <div class="render-container"
34033
- >
34034
- @if (renderService.currentQueueRenderItem.renderStatus === renderStatus.IsRunning || renderService.currentQueueRenderItem.renderStatus === renderStatus.IsSuccess) {
34035
- <div class="render-progress"
34036
- >
34037
- {{ (renderService.currentQueueRenderItem.renderStatus === renderStatus.IsSuccess && renderService.currentQueueRenderItem.renderProgress === 100 ? "RENDER_READY" : "") | localize }}
34038
- {{ (renderService.currentQueueRenderItem.renderStatus === renderStatus.IsSuccess && renderService.currentQueueRenderItem.renderProgress !== 100 ? "RENDER_STOPPED" : "") | localize }}
34039
- {{ (renderService.currentQueueRenderItem.renderStatus === renderStatus.IsRunning) ? renderService.currentQueueRenderItem.renderProgress + "%" : "" }}
34040
- </div>
34041
- }
34042
- <!-- the Yellow render indicators -->
34043
- @if (inPictureMode) {
34044
- <div class="render-indicators">
34045
- <div class="render-indicator-top-left"></div>
34046
- <div class="render-indicator-top-right"></div>
34047
- <div class="render-indicator-bottom-left"></div>
34048
- <div class="render-indicator-bottom-right"></div>
34049
- </div>
34050
- }
34051
- @if (inPictureMode) {
34052
- <div class="render-popup-container">
34053
- <div class="render-popup-header">
34054
- <h3>
34055
- <span>{{ 'PICTURE_MODE' | localize }}</span>
34056
- @if (hasError) {
34057
- <co-icon class="renderErrorIcon" [iconData]="iconService.getIcon(icons.TriangleExclamation)"
34058
- [matTooltip]="'BLENDER_RENDER_ERROR' | localize"></co-icon>
34059
- }
34060
- </h3>
34061
- <button
34062
- class="close-popup-container"
34063
- (click)="resetBlenderRenderScene()">
34064
- <co-icon [iconData]="iconService.getIcon(icons.Cross)"></co-icon>
34065
- </button>
34066
- </div>
34067
- <div class="render-popup-preview">
34068
- @if (blenderPreviewRender) {
34069
- <img [src]="blenderPreviewRender" alt="">
34070
- }
34071
- @if (!blenderPreviewRender) {
34072
- <div class="render-popup-preview-placeholder">
34073
- <span>{{ 'PREVIEW' | localize }}</span>
34074
- </div>
34075
- }
34076
- <button
34077
- class="render-popup-refresh-preview"
34078
- (click)="createPreviewRender()"
34079
- >
34080
- <co-icon [iconData]="iconService.getIcon(icons.RetryButton)"></co-icon>
34081
- </button>
34082
- </div>
34083
- @if (renderService.blendFilesRender) {
34084
- <div class="render-popup-dropdown">
34085
- <div class="toggleable" (click)="toggleRenderSettings()">
34086
- <p>
34087
- @if (!showRenderSettings) {
34088
- <span [textContent]="'RENDER_ADVANCED_SETTINGS_SHOW' | localize"></span>
34089
- }
34090
- @if (showRenderSettings) {
34091
- <span [textContent]="'RENDER_ADVANCED_SETTINGS_HIDE' | localize"></span>
34092
- }
34093
- </p>
34094
- <co-icon [ngClass]="{'icon-rotate': showRenderSettings}"
34095
- [iconData]="iconService.getIcon(icons.ArrowPointDown)"></co-icon>
34096
- </div>
34097
- @if (showRenderSettings) {
34098
- <div class="advanced-render-settings">
34099
- <div class="setting-part-container">
34100
- @if (renderService.serverData.renderMode === renderModes.RenderRoom) {
34101
- <mat-form-field
34102
- class="face-select-form"
34103
- >
34104
- <mat-label>{{ "ENVIRONMENT" | localize }}</mat-label>
34105
- <mat-select [(ngModel)]="selectedRenderScene" (selectionChange)="updateBlenderSceneSettings($event)">
34106
- @for (scene of sceneList; track scene) {
34107
- <mat-option
34108
- [value]="scene">{{ scene.name }}
34109
- </mat-option>
34110
- }
34111
- </mat-select>
34112
- </mat-form-field>
33765
+ <div class="render-container">
33766
+ @if (startUploading) {
33767
+ <rp-render-progress></rp-render-progress>
33768
+ }
33769
+ <!-- the Yellow render indicators -->
33770
+ @if (inPictureMode) {
33771
+ <div class="render-indicators">
33772
+ <div class="render-indicator-top-left"></div>
33773
+ <div class="render-indicator-top-right"></div>
33774
+ <div class="render-indicator-bottom-left"></div>
33775
+ <div class="render-indicator-bottom-right"></div>
33776
+ </div>
33777
+ <div class="render-popup-container">
33778
+ <div class="render-popup-header">
33779
+ <h3>
33780
+ <span>{{ 'PICTURE_MODE' | localize }}</span>
33781
+ @if (hasError) {
33782
+ <co-icon class="renderErrorIcon" [iconData]="iconService.getIcon(icons.TriangleExclamation)"
33783
+ [matTooltip]="'BLENDER_RENDER_ERROR' | localize"></co-icon>
33784
+ }
33785
+ </h3>
33786
+ <button
33787
+ class="close-popup-container"
33788
+ (click)="resetBlenderRenderScene()">
33789
+ <co-icon [iconData]="iconService.getIcon(icons.Cross)"></co-icon>
33790
+ </button>
33791
+ </div>
33792
+ <div class="render-popup-preview">
33793
+ @if (blenderPreviewRender) {
33794
+ <img [src]="blenderPreviewRender" alt="">
34113
33795
  }
34114
- </div>
34115
- <div class="setting-part-container">
34116
- <mat-form-field class="third-width">
34117
- <mat-label [textContent]="'ENVIRONMENT_LIGHT' | localize"></mat-label>
34118
- <input
34119
- [type]="'number'"
34120
- matInput
34121
- [(ngModel)]="hdriIntensity"
34122
- (ngModelChange)="hdriIntensity = +$event">
34123
- </mat-form-field>
34124
- <div class="setting-part-buttons">
34125
- <button class="amount-button" (click)="hdriIntensity = +hdriIntensity - 1">
34126
- <co-icon [iconData]="iconService.getIcon(icons.CircleMinusLight)"></co-icon>
34127
- </button>
34128
- <button class="amount-button" (click)="hdriIntensity = +hdriIntensity + 1">
34129
- <co-icon [iconData]="iconService.getIcon(icons.CirclePlusLight)"></co-icon>
34130
- </button>
34131
- </div>
34132
- <div class="setting-part-slider">
34133
- <mat-slider class="value" min="1" max="20" step="1" [(ngModel)]="hdriIntensity"></mat-slider>
34134
- </div>
34135
- </div>
34136
- <div class="setting-part-container">
34137
- <mat-form-field class="third-width">
34138
- <mat-label [textContent]="'ROTATION' | localize"></mat-label>
34139
- <input
34140
- [type]="'number'"
34141
- matInput
34142
- [(ngModel)]="hdriRotation"
34143
- (ngModelChange)="hdriRotation = +$event">
34144
- </mat-form-field>
34145
- <div class="setting-part-buttons">
34146
- <button class="amount-button" (click)="hdriRotation = +hdriRotation - 1">
34147
- <co-icon [iconData]="iconService.getIcon(icons.CircleMinusLight)"></co-icon>
34148
- </button>
34149
- <button class="amount-button" (click)="hdriRotation = +hdriRotation + 1">
34150
- <co-icon [iconData]="iconService.getIcon(icons.CirclePlusLight)"></co-icon>
34151
- </button>
33796
+ @if (!blenderPreviewRender) {
33797
+ <div class="render-popup-preview-placeholder">
33798
+ <span>{{ 'PREVIEW' | localize }}</span>
34152
33799
  </div>
34153
- <div class="setting-part-slider">
34154
- <mat-slider class="value" min="0" max="360" step="1" [(ngModel)]="hdriRotation"></mat-slider>
34155
- </div>
34156
- </div>
34157
- <div class="setting-part-container">
34158
- <mat-form-field class="third-width">
34159
- <mat-label [textContent]="'LIGHTS' | localize"></mat-label>
34160
- <input
34161
- [type]="'number'"
34162
- matInput
34163
- [(ngModel)]="lightingExposure"
34164
- (ngModelChange)="lightingExposure = +$event">
34165
- </mat-form-field>
34166
- <div class="setting-part-buttons">
34167
- <button class="amount-button" (click)="lightingExposure = +lightingExposure - 1">
34168
- <co-icon [iconData]="iconService.getIcon(icons.CircleMinusLight)"></co-icon>
34169
- </button>
34170
- <button class="amount-button" (click)="lightingExposure = +lightingExposure + 1">
34171
- <co-icon [iconData]="iconService.getIcon(icons.CirclePlusLight)"></co-icon>
34172
- </button>
34173
- </div>
34174
- <div class="setting-part-slider">
34175
- <mat-slider class="value" min="1" max="10" step="1" [(ngModel)]="lightingExposure"></mat-slider>
34176
- </div>
34177
- </div>
34178
- </div>
34179
33800
  }
34180
- </div>
33801
+ <button class="render-popup-refresh-preview" (click)="createBlenderRender(true)">
33802
+ <co-icon [iconData]="iconService.getIcon(icons.RetryButton)"></co-icon>
33803
+ </button>
33804
+ </div>
33805
+ @if (renderService.blendFilesRender) {
33806
+ <div class="render-popup-dropdown">
33807
+ <div class="toggleable" (click)="toggleRenderSettings()">
33808
+ <p>
33809
+ @if (!showRenderSettings) {
33810
+ <span [textContent]="'RENDER_ADVANCED_SETTINGS_SHOW' | localize"></span>
33811
+ }
33812
+ @if (showRenderSettings) {
33813
+ <span [textContent]="'RENDER_ADVANCED_SETTINGS_HIDE' | localize"></span>
33814
+ }
33815
+ </p>
33816
+ <co-icon [ngClass]="{'icon-rotate': showRenderSettings}"
33817
+ [iconData]="iconService.getIcon(icons.ArrowPointDown)"></co-icon>
33818
+ </div>
33819
+ @if (showRenderSettings) {
33820
+ <div class="advanced-render-settings">
33821
+ <div class="setting-part-container">
33822
+ <mat-form-field
33823
+ class="face-select-form"
33824
+ >
33825
+ <mat-label>{{ "ENVIRONMENT" | localize }}</mat-label>
33826
+ <mat-select [(ngModel)]="selectedRenderScene" (selectionChange)="updateBlenderSceneSettings($event)">
33827
+ @for (scene of sceneList; track scene) {
33828
+ <mat-option
33829
+ [value]="scene">{{ scene.name }}
33830
+ </mat-option>
33831
+ }
33832
+ </mat-select>
33833
+ </mat-form-field>
33834
+ </div>
33835
+ <div class="setting-part-container">
33836
+ <mat-form-field class="third-width">
33837
+ <mat-label [textContent]="'ENVIRONMENT_LIGHT' | localize"></mat-label>
33838
+ <input
33839
+ [type]="'number'"
33840
+ matInput
33841
+ [(ngModel)]="hdriIntensity"
33842
+ (ngModelChange)="hdriIntensity = +$event">
33843
+ </mat-form-field>
33844
+ <div class="setting-part-buttons">
33845
+ <button class="amount-button" (click)="hdriIntensity = +hdriIntensity - 1">
33846
+ <co-icon [iconData]="iconService.getIcon(icons.CircleMinusLight)"></co-icon>
33847
+ </button>
33848
+ <button class="amount-button" (click)="hdriIntensity = +hdriIntensity + 1">
33849
+ <co-icon [iconData]="iconService.getIcon(icons.CirclePlusLight)"></co-icon>
33850
+ </button>
33851
+ </div>
33852
+ <div class="setting-part-slider">
33853
+ <mat-slider class="value" min="1" max="20" step="1" [(ngModel)]="hdriIntensity"></mat-slider>
33854
+ </div>
33855
+ </div>
33856
+ <div class="setting-part-container">
33857
+ <mat-form-field class="third-width">
33858
+ <mat-label [textContent]="'ROTATION' | localize"></mat-label>
33859
+ <input
33860
+ [type]="'number'"
33861
+ matInput
33862
+ [(ngModel)]="hdriRotation"
33863
+ (ngModelChange)="hdriRotation = +$event">
33864
+ </mat-form-field>
33865
+ <div class="setting-part-buttons">
33866
+ <button class="amount-button" (click)="hdriRotation = +hdriRotation - 1">
33867
+ <co-icon [iconData]="iconService.getIcon(icons.CircleMinusLight)"></co-icon>
33868
+ </button>
33869
+ <button class="amount-button" (click)="hdriRotation = +hdriRotation + 1">
33870
+ <co-icon [iconData]="iconService.getIcon(icons.CirclePlusLight)"></co-icon>
33871
+ </button>
33872
+ </div>
33873
+ <div class="setting-part-slider">
33874
+ <mat-slider class="value" min="0" max="360" step="1" [(ngModel)]="hdriRotation"></mat-slider>
33875
+ </div>
33876
+ </div>
33877
+ <div class="setting-part-container">
33878
+ <mat-form-field class="third-width">
33879
+ <mat-label [textContent]="'LIGHTS' | localize"></mat-label>
33880
+ <input
33881
+ [type]="'number'"
33882
+ matInput
33883
+ [(ngModel)]="lightingExposure"
33884
+ (ngModelChange)="lightingExposure = +$event">
33885
+ </mat-form-field>
33886
+ <div class="setting-part-buttons">
33887
+ <button class="amount-button" (click)="lightingExposure = +lightingExposure - 1">
33888
+ <co-icon [iconData]="iconService.getIcon(icons.CircleMinusLight)"></co-icon>
33889
+ </button>
33890
+ <button class="amount-button" (click)="lightingExposure = +lightingExposure + 1">
33891
+ <co-icon [iconData]="iconService.getIcon(icons.CirclePlusLight)"></co-icon>
33892
+ </button>
33893
+ </div>
33894
+ <div class="setting-part-slider">
33895
+ <mat-slider class="value" min="1" max="10" step="1" [(ngModel)]="lightingExposure"></mat-slider>
33896
+ </div>
33897
+ </div>
33898
+ </div>
33899
+ }
33900
+ </div>
34181
33901
  }
34182
- @if (renderService.serverData.renderMode === renderModes.RenderRoom) {
34183
- <div class="render-popup-dropdown">
33902
+ <div class="render-popup-dropdown">
34184
33903
  <mat-form-field class="face-select-form">
34185
- <mat-label>{{ "IMAGE_SIZE" | localize }}</mat-label>
34186
- <mat-select [(ngModel)]="renderService.selectedImageSize">
34187
- @for (size of renderService.imageSizes; track size) {
34188
- <mat-option [value]="size.id">{{ size.name }} {{ size.width }}
34189
- x{{ size.height }}
34190
- </mat-option>
34191
- }
34192
- </mat-select>
33904
+ <mat-label>{{ "IMAGE_SIZE" | localize }}</mat-label>
33905
+ <mat-select [(value)]="selectedImageSize">
33906
+ @for (size of imageSizes; track size) {
33907
+ <mat-option [value]="size">{{ size.name }} {{ size.width }}
33908
+ x{{ size.height }}
33909
+ </mat-option>
33910
+ }
33911
+ </mat-select>
34193
33912
  </mat-form-field>
34194
- </div>
34195
- }
33913
+ </div>
34196
33914
  <div class="render-popup-button-container">
34197
- <button class="render-popup-button photo-button"
34198
- (click)="createBlenderRender()"
34199
- title="{{'MAKE_A_PICTURE' | localize}}"
34200
- [disabled]="disablePictureButton">
34201
- <co-icon [iconData]="iconService.getIcon(icons.CircleCheck)"></co-icon>
34202
- {{ 'MAKE_A_PICTURE' | localize }}
34203
- </button>
34204
- <button
34205
- class="render-popup-button cancel-button"
34206
- (click)="resetBlenderRenderScene()">
34207
- <co-icon [iconData]="iconService.getIcon(icons.CircleXmark)"></co-icon>
34208
- {{ 'CLOSE_PHOTO_MODE' | localize }}
34209
- </button>
33915
+ <button class="render-popup-button photo-button"
33916
+ (click)="createBlenderRender()"
33917
+ title="{{'MAKE_A_PICTURE' | localize}}"
33918
+ [disabled]="disablePictureButton">
33919
+ <co-icon [iconData]="iconService.getIcon(icons.CircleCheck)"></co-icon>
33920
+ {{ 'MAKE_A_PICTURE' | localize }}
33921
+ </button>
33922
+ <button
33923
+ class="render-popup-button cancel-button"
33924
+ (click)="resetBlenderRenderScene()">
33925
+ <co-icon [iconData]="iconService.getIcon(icons.CircleXmark)"></co-icon>
33926
+ {{ 'CLOSE_PHOTO_MODE' | localize }}
33927
+ </button>
34210
33928
  </div>
34211
- </div>
34212
- }
34213
- @if (showCullingErrorDialog) {
34214
- <div class="render-warning">
33929
+ </div>
33930
+ }
33931
+ @if (showCullingErrorDialog) {
33932
+ <div class="render-warning">
34215
33933
  <div class="render-warming-header">
34216
- <h2>{{ 'BLENDER_RENDER_ERROR_TITLE' | localize }}</h2>
34217
- <div class="render-warning-close" (click)="showCullingErrorDialog = false">
34218
- <mat-icon class="homedecorator-material-icons">cancel</mat-icon>
34219
- </div>
33934
+ <h2>{{ 'BLENDER_RENDER_ERROR_TITLE' | localize }}</h2>
33935
+ <div class="render-warning-close" (click)="showCullingErrorDialog = false">
33936
+ <mat-icon class="homedecorator-material-icons">cancel</mat-icon>
33937
+ </div>
34220
33938
  </div>
34221
33939
  <div class="render-warning-body">
34222
- <p>{{ 'BLENDER_RENDER_WARNING_CULLING' | localize }}</p>
33940
+ <p>{{ 'BLENDER_RENDER_WARNING_CULLING' | localize }}</p>
34223
33941
  </div>
34224
33942
  <div class="render-warning-footer">
34225
- <button
34226
- class="render-popup-button cancel-button"
34227
- (click)="showCullingErrorDialog = false">
34228
- <co-icon [iconData]="iconService.getIcon(icons.CircleXmark)"></co-icon>
34229
- {{ 'CLOSE' | localize }}
34230
- </button>
33943
+ <button
33944
+ class="render-popup-button cancel-button"
33945
+ (click)="showCullingErrorDialog = false">
33946
+ <co-icon [iconData]="iconService.getIcon(icons.CircleXmark)"></co-icon>
33947
+ {{ 'CLOSE' | localize }}
33948
+ </button>
34231
33949
  </div>
34232
- </div>
34233
- }
34234
- <rp-render-progress
34235
- [title]="'PREPARE_TO_RENDER' | localize"
34236
- [show]="startUploading"
34237
- >
34238
- </rp-render-progress>
34239
- <button
34240
- #renderButton
34241
- mat-raised-button
34242
- matTooltip="{{'RENDER_TAKE_A_PICTURE' | localize}}"
34243
- [id]="'standalone_render_picture'"
34244
- [class.active]="(
34245
- (renderService.serverData.renderMode === renderService.renderModes.RenderRoom && viewModeService.viewMode === viewModes.WalkThrough) ||
34246
- (renderService.serverData.renderMode === renderService.renderModes.RenderIone))"
34247
- (click)="showRenderForm($event)"
34248
- >
34249
- <mat-icon class="icon homedecorator-material-icons"
34250
- aria-hidden="true">{{ (renderService.currentQueueRenderItem.renderStatus === renderStatus.IsRunning ? 'open_in_browser' : 'photo_camera') }}
34251
- </mat-icon>
34252
- </button>
34253
- </div>
33950
+ </div>
34254
33951
  }
34255
-
34256
- `, isInline: true, styles: [".render-container{position:relative}.render-container .render-popup-container{background:#ffffffb3;padding:10px 25px 25px;border-radius:5px;box-shadow:0 1px 5px #0000001f}.render-container .render-popup-container .render-popup-header{display:flex;justify-content:space-between;font-family:inherit}.render-container .render-popup-container .render-popup-header h3{display:flex;justify-content:space-between}.render-container .render-popup-container .render-popup-header h3 ::ng-deep .renderErrorIcon{width:20px;height:20px;margin-left:20px}.render-container .render-popup-container .render-popup-header h3 ::ng-deep .renderErrorIcon svg,.render-container .render-popup-container .render-popup-header h3 ::ng-deep .renderErrorIcon svg polygon{fill:#dc143c}.render-container .render-popup-container .render-popup-header .close-popup-container{cursor:pointer;border:none;background:none;float:none;height:auto;width:auto}.render-container .render-popup-container .render-popup-button-container{display:flex;justify-content:space-between;font-family:inherit}.render-container .render-popup-container .render-popup-button-container .render-popup-button{float:none;width:100%;max-width:130px;border-radius:3px;cursor:pointer;border:none;display:flex;height:40px;align-items:center;justify-content:space-evenly}.render-container .render-popup-container .render-popup-button-container .render-popup-button ::ng-deep co-icon{display:inline-block;height:18px;width:18px}.render-container .render-popup-container .render-popup-button-container .render-popup-button ::ng-deep co-icon svg path{fill:#fff}.render-container .render-popup-container .render-popup-button-container .photo-button{color:#fff;background-color:#dda73f}.render-container .render-popup-container .render-popup-button-container .cancel-button{color:#fff;background-color:#5b6875}.render-container .render-popup-container .render-popup-preview{background-color:#fff;min-height:150px;min-width:275px;margin:5px 0;position:relative;width:275px;height:150px}.render-container .render-popup-container .render-popup-preview .render-popup-preview-placeholder{background-color:#fff;display:flex;justify-content:space-around;align-items:center;vertical-align:middle;min-height:150px;border:1px solid #ddd;color:#ddd;font-size:14px}.render-container .render-popup-container .render-popup-preview .render-popup-refresh-preview{position:absolute;bottom:0;right:0;cursor:pointer;border-radius:0;border:none;height:30px;width:30px;background-color:#dda73f;color:#fff;margin:0}.render-container .render-popup-container .render-popup-preview .render-popup-refresh-preview ::ng-deep co-icon svg path{fill:#fff}.render-container .render-popup-container .render-popup-dropdown{margin:5px 0;width:100%}.render-container .render-popup-container .render-popup-dropdown .toggleable{cursor:pointer;display:flex;justify-content:right;align-content:center}.render-container .render-popup-container .render-popup-dropdown .toggleable p{padding:0;margin:0;font-size:12px;line-height:30px}.render-container .render-popup-container .render-popup-dropdown .toggleable .icon-rotate{transform:rotate(180deg)}.render-container .render-popup-container .render-popup-dropdown .mat-mdc-form-field{width:100%;font-size:14px}.render-container .render-popup-container .render-popup-dropdown .mat-mdc-form-field ::ng-deep .mat-mdc-form-field-flex{background-color:#fff;color:#000;padding:3px 6px;border:1px solid #ddd}.render-container .render-popup-container .render-popup-dropdown .mat-mdc-form-field ::ng-deep .mat-mdc-form-field-underline{display:none}.render-container .render-popup-container .render-popup-dropdown .mat-mdc-form-field ::ng-deep .mat-mdc-form-field-wrapper{padding-bottom:0}.render-container .render-popup-container .render-popup-dropdown .setting-part-container{display:flex;justify-content:space-between;align-items:center;margin-bottom:5px}.render-container .render-popup-container .render-popup-dropdown .setting-part-container .third-width{width:32%}.render-container .render-popup-container .render-popup-dropdown .setting-part-container .setting-part-buttons .amount-button{float:none;box-sizing:border-box;padding:2px;background:none;cursor:pointer;border:none;width:25px;height:25px;margin:0 5px}.render-container .render-popup-container .render-popup-dropdown .setting-part-container .setting-part-buttons .amount-button co-icon{display:block;width:25px;height:25px}.render-container .render-popup-container .render-popup-dropdown .setting-part-container .setting-part-buttons .amount-button co-icon ::ng-deep svg{fill:#5b6875}.render-container .render-popup-container .render-popup-dropdown .setting-part-container .setting-part-slider .mat-slider-horizontal{min-width:110px;height:28px}.render-container .render-progress{float:left;min-width:50px;border-radius:25px;line-height:50px;text-align:center;padding:0 60px 0 20px;background:#fff;color:#74b77f;font-weight:700;margin:0 -50px 0 0}.render-container .render-input-container{float:right}.render-container .render-input-container input{width:100px;height:24px;margin:5px 0;padding:0 10px;font-size:14px}.render-container button{pointer-events:all;width:50px;height:50px;float:right;border-radius:100%;position:relative;z-index:2;margin-bottom:10px}.render-container button.active{background:#74b77f;color:#fff}.render-container button>*{pointer-events:none}.render-indicators div{position:fixed;width:100px;height:100px}.render-indicators .render-indicator-top-left{left:5vw;top:10vh;border-left:10px solid #dda73f;border-top:10px solid #dda73f;border-top-left-radius:20px}.render-indicators .render-indicator-top-right{right:5vw;top:10vh;border-right:10px solid #dda73f;border-top:10px solid #dda73f;border-top-right-radius:20px}.render-indicators .render-indicator-bottom-left{left:5vw;bottom:5vh;border-left:10px solid #dda73f;border-bottom:10px solid #dda73f;border-bottom-left-radius:20px}.render-indicators .render-indicator-bottom-right{right:5vw;bottom:5vh;border-right:10px solid #dda73f;border-bottom:10px solid #dda73f;border-bottom-right-radius:20px}.render-warning{width:500px;position:fixed;top:20%;left:calc(50% - 250px);border-radius:15px;box-sizing:border-box;background-color:#fff;box-shadow:1px 0 20px #0000001f}.render-warning .render-warming-header{display:flex;justify-content:space-between;border-bottom:1px solid #c5c3c6;padding:20px 20px 10px;align-items:center}.render-warning .render-warming-header h2{padding:0;margin:0}.render-warning .render-warming-header .render-warning-close mat-icon{fill:#c5c3c6;color:#c5c3c6;cursor:pointer;transition:all .2s ease}.render-warning .render-warming-header .render-warning-close:hover mat-icon{fill:#46494c;color:#46494c}.render-warning .render-warning-body{padding:10px 20px}.render-warning .render-warning-footer{display:flex;justify-content:center;padding:0 20px 10px}.render-warning .render-warning-footer .render-popup-button{float:none;width:110px;border-radius:3px;cursor:pointer;border:none;display:flex;height:40px;align-items:center;justify-content:space-evenly;color:#fff;background-color:#5b6875}.render-warning .render-warning-footer .render-popup-button ::ng-deep co-icon{display:inline-block;height:18px;width:18px}.render-warning .render-warning-footer .render-popup-button ::ng-deep co-icon svg path{fill:#fff}\n"], dependencies: [{ kind: "directive", type: i2$2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: i3.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "directive", type: i4$1.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: i3$2.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "component", type: i2$3.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$3.MatLabel, selector: "mat-label" }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i13.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i13.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "directive", type: i3$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i5.IconComponent, selector: "co-icon", inputs: ["icon", "iconData"] }, { kind: "component", type: i4$2.MatSlider, selector: "mat-slider", inputs: ["disabled", "discrete", "showTickMarks", "min", "color", "disableRipple", "max", "step", "displayWith"], exportAs: ["matSlider"] }, { kind: "component", type: RenderProgressComponent, selector: "rp-render-progress", inputs: ["show", "title"] }, { kind: "pipe", type: LocalizePipe, name: "localize" }] }); }
33952
+ <button
33953
+ #renderButton
33954
+ mat-raised-button
33955
+ matTooltip="{{'RENDER_TAKE_A_PICTURE' | localize}}"
33956
+ [id]="'standalone_render_picture'"
33957
+ [class.active]="viewModeService.viewMode === viewModes.WalkThrough"
33958
+ (click)="showRenderForm($event)">
33959
+ <mat-icon class="icon homedecorator-material-icons"
33960
+ aria-hidden="true">{{ 'photo_camera' }}
33961
+ </mat-icon>
33962
+ </button>
33963
+ </div>
33964
+ `, isInline: true, styles: [".render-container{position:relative}.render-container .render-popup-container{background:#ffffffb3;padding:10px 25px 25px;border-radius:5px;box-shadow:0 1px 5px #0000001f}.render-container .render-popup-container .render-popup-header{display:flex;justify-content:space-between;font-family:inherit}.render-container .render-popup-container .render-popup-header h3{display:flex;justify-content:space-between}.render-container .render-popup-container .render-popup-header h3 ::ng-deep .renderErrorIcon{width:20px;height:20px;margin-left:20px}.render-container .render-popup-container .render-popup-header h3 ::ng-deep .renderErrorIcon svg,.render-container .render-popup-container .render-popup-header h3 ::ng-deep .renderErrorIcon svg polygon{fill:#dc143c}.render-container .render-popup-container .render-popup-header .close-popup-container{cursor:pointer;border:none;background:none;float:none;height:auto;width:auto}.render-container .render-popup-container .render-popup-button-container{display:flex;justify-content:space-between;font-family:inherit}.render-container .render-popup-container .render-popup-button-container .render-popup-button{float:none;width:100%;max-width:130px;border-radius:3px;cursor:pointer;border:none;display:flex;height:40px;align-items:center;justify-content:space-evenly}.render-container .render-popup-container .render-popup-button-container .render-popup-button ::ng-deep co-icon{display:inline-block;height:18px;width:18px}.render-container .render-popup-container .render-popup-button-container .render-popup-button ::ng-deep co-icon svg path{fill:#fff}.render-container .render-popup-container .render-popup-button-container .photo-button{color:#fff;background-color:#dda73f}.render-container .render-popup-container .render-popup-button-container .cancel-button{color:#fff;background-color:#5b6875}.render-container .render-popup-container .render-popup-preview{background-color:#fff;min-height:150px;min-width:275px;margin:5px 0;position:relative;width:275px;height:150px}.render-container .render-popup-container .render-popup-preview .render-popup-preview-placeholder{background-color:#fff;display:flex;justify-content:space-around;align-items:center;vertical-align:middle;min-height:150px;border:1px solid #ddd;color:#ddd;font-size:14px}.render-container .render-popup-container .render-popup-preview .render-popup-refresh-preview{position:absolute;bottom:0;right:0;cursor:pointer;border-radius:0;border:none;height:30px;width:30px;background-color:#dda73f;color:#fff;margin:0}.render-container .render-popup-container .render-popup-preview .render-popup-refresh-preview ::ng-deep co-icon svg path{fill:#fff}.render-container .render-popup-container .render-popup-dropdown{margin:5px 0;width:100%}.render-container .render-popup-container .render-popup-dropdown .toggleable{cursor:pointer;display:flex;justify-content:right;align-content:center}.render-container .render-popup-container .render-popup-dropdown .toggleable p{padding:0;margin:0;font-size:12px;line-height:30px}.render-container .render-popup-container .render-popup-dropdown .toggleable .icon-rotate{transform:rotate(180deg)}.render-container .render-popup-container .render-popup-dropdown .mat-mdc-form-field{width:100%;font-size:14px}.render-container .render-popup-container .render-popup-dropdown .mat-mdc-form-field ::ng-deep .mat-mdc-form-field-flex{background-color:#fff;color:#000;padding:3px 6px;border:1px solid #ddd}.render-container .render-popup-container .render-popup-dropdown .mat-mdc-form-field ::ng-deep .mat-mdc-form-field-underline{display:none}.render-container .render-popup-container .render-popup-dropdown .mat-mdc-form-field ::ng-deep .mat-mdc-form-field-wrapper{padding-bottom:0}.render-container .render-popup-container .render-popup-dropdown .setting-part-container{display:flex;justify-content:space-between;align-items:center;margin-bottom:5px}.render-container .render-popup-container .render-popup-dropdown .setting-part-container .third-width{width:32%}.render-container .render-popup-container .render-popup-dropdown .setting-part-container .setting-part-buttons .amount-button{float:none;box-sizing:border-box;padding:2px;background:none;cursor:pointer;border:none;width:25px;height:25px;margin:0 5px}.render-container .render-popup-container .render-popup-dropdown .setting-part-container .setting-part-buttons .amount-button co-icon{display:block;width:25px;height:25px}.render-container .render-popup-container .render-popup-dropdown .setting-part-container .setting-part-buttons .amount-button co-icon ::ng-deep svg{fill:#5b6875}.render-container .render-popup-container .render-popup-dropdown .setting-part-container .setting-part-slider .mat-slider-horizontal{min-width:110px;height:28px}.render-container .render-progress{float:left;min-width:50px;border-radius:25px;line-height:50px;text-align:center;padding:0 60px 0 20px;background:#fff;color:#74b77f;font-weight:700;margin:0 -50px 0 0}.render-container .render-input-container{float:right}.render-container .render-input-container input{width:100px;height:24px;margin:5px 0;padding:0 10px;font-size:14px}.render-container button{pointer-events:all;width:50px;height:50px;float:right;border-radius:100%;position:relative;z-index:2;margin-bottom:10px}.render-container button.active{background:#74b77f;color:#fff}.render-container button>*{pointer-events:none}.render-indicators div{position:fixed;width:100px;height:100px}.render-indicators .render-indicator-top-left{left:5vw;top:10vh;border-left:10px solid #dda73f;border-top:10px solid #dda73f;border-top-left-radius:20px}.render-indicators .render-indicator-top-right{right:5vw;top:10vh;border-right:10px solid #dda73f;border-top:10px solid #dda73f;border-top-right-radius:20px}.render-indicators .render-indicator-bottom-left{left:5vw;bottom:5vh;border-left:10px solid #dda73f;border-bottom:10px solid #dda73f;border-bottom-left-radius:20px}.render-indicators .render-indicator-bottom-right{right:5vw;bottom:5vh;border-right:10px solid #dda73f;border-bottom:10px solid #dda73f;border-bottom-right-radius:20px}.render-warning{width:500px;position:fixed;top:20%;left:calc(50% - 250px);border-radius:15px;box-sizing:border-box;background-color:#fff;box-shadow:1px 0 20px #0000001f}.render-warning .render-warming-header{display:flex;justify-content:space-between;border-bottom:1px solid #c5c3c6;padding:20px 20px 10px;align-items:center}.render-warning .render-warming-header h2{padding:0;margin:0}.render-warning .render-warming-header .render-warning-close mat-icon{fill:#c5c3c6;color:#c5c3c6;cursor:pointer;transition:all .2s ease}.render-warning .render-warming-header .render-warning-close:hover mat-icon{fill:#46494c;color:#46494c}.render-warning .render-warning-body{padding:10px 20px}.render-warning .render-warning-footer{display:flex;justify-content:center;padding:0 20px 10px}.render-warning .render-warning-footer .render-popup-button{float:none;width:110px;border-radius:3px;cursor:pointer;border:none;display:flex;height:40px;align-items:center;justify-content:space-evenly;color:#fff;background-color:#5b6875}.render-warning .render-warning-footer .render-popup-button ::ng-deep co-icon{display:inline-block;height:18px;width:18px}.render-warning .render-warning-footer .render-popup-button ::ng-deep co-icon svg path{fill:#fff}\n"], dependencies: [{ kind: "directive", type: i2$2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: i3.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "directive", type: i4$1.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: i3$2.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "component", type: i2$3.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$3.MatLabel, selector: "mat-label" }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i13.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i13.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "directive", type: i3$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i5.IconComponent, selector: "co-icon", inputs: ["icon", "iconData"] }, { kind: "component", type: i4$2.MatSlider, selector: "mat-slider", inputs: ["disabled", "discrete", "showTickMarks", "min", "color", "disableRipple", "max", "step", "displayWith"], exportAs: ["matSlider"] }, { kind: "component", type: RenderProgressComponent, selector: "rp-render-progress" }, { kind: "pipe", type: LocalizePipe, name: "localize" }] }); }
34257
33965
  }
34258
33966
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: RenderControlsComponent, decorators: [{
34259
33967
  type: Component,
34260
33968
  args: [{ selector: 'rp-render-controls', template: `
34261
- @if (renderService.serverData && renderService.serverData.renderMode !== renderService.renderModes.RenderShop) {
34262
- <div class="render-container"
34263
- >
34264
- @if (renderService.currentQueueRenderItem.renderStatus === renderStatus.IsRunning || renderService.currentQueueRenderItem.renderStatus === renderStatus.IsSuccess) {
34265
- <div class="render-progress"
34266
- >
34267
- {{ (renderService.currentQueueRenderItem.renderStatus === renderStatus.IsSuccess && renderService.currentQueueRenderItem.renderProgress === 100 ? "RENDER_READY" : "") | localize }}
34268
- {{ (renderService.currentQueueRenderItem.renderStatus === renderStatus.IsSuccess && renderService.currentQueueRenderItem.renderProgress !== 100 ? "RENDER_STOPPED" : "") | localize }}
34269
- {{ (renderService.currentQueueRenderItem.renderStatus === renderStatus.IsRunning) ? renderService.currentQueueRenderItem.renderProgress + "%" : "" }}
34270
- </div>
34271
- }
34272
- <!-- the Yellow render indicators -->
34273
- @if (inPictureMode) {
34274
- <div class="render-indicators">
34275
- <div class="render-indicator-top-left"></div>
34276
- <div class="render-indicator-top-right"></div>
34277
- <div class="render-indicator-bottom-left"></div>
34278
- <div class="render-indicator-bottom-right"></div>
34279
- </div>
34280
- }
34281
- @if (inPictureMode) {
34282
- <div class="render-popup-container">
34283
- <div class="render-popup-header">
34284
- <h3>
34285
- <span>{{ 'PICTURE_MODE' | localize }}</span>
34286
- @if (hasError) {
34287
- <co-icon class="renderErrorIcon" [iconData]="iconService.getIcon(icons.TriangleExclamation)"
34288
- [matTooltip]="'BLENDER_RENDER_ERROR' | localize"></co-icon>
34289
- }
34290
- </h3>
34291
- <button
34292
- class="close-popup-container"
34293
- (click)="resetBlenderRenderScene()">
34294
- <co-icon [iconData]="iconService.getIcon(icons.Cross)"></co-icon>
34295
- </button>
34296
- </div>
34297
- <div class="render-popup-preview">
34298
- @if (blenderPreviewRender) {
34299
- <img [src]="blenderPreviewRender" alt="">
34300
- }
34301
- @if (!blenderPreviewRender) {
34302
- <div class="render-popup-preview-placeholder">
34303
- <span>{{ 'PREVIEW' | localize }}</span>
34304
- </div>
34305
- }
34306
- <button
34307
- class="render-popup-refresh-preview"
34308
- (click)="createPreviewRender()"
34309
- >
34310
- <co-icon [iconData]="iconService.getIcon(icons.RetryButton)"></co-icon>
34311
- </button>
34312
- </div>
34313
- @if (renderService.blendFilesRender) {
34314
- <div class="render-popup-dropdown">
34315
- <div class="toggleable" (click)="toggleRenderSettings()">
34316
- <p>
34317
- @if (!showRenderSettings) {
34318
- <span [textContent]="'RENDER_ADVANCED_SETTINGS_SHOW' | localize"></span>
34319
- }
34320
- @if (showRenderSettings) {
34321
- <span [textContent]="'RENDER_ADVANCED_SETTINGS_HIDE' | localize"></span>
34322
- }
34323
- </p>
34324
- <co-icon [ngClass]="{'icon-rotate': showRenderSettings}"
34325
- [iconData]="iconService.getIcon(icons.ArrowPointDown)"></co-icon>
34326
- </div>
34327
- @if (showRenderSettings) {
34328
- <div class="advanced-render-settings">
34329
- <div class="setting-part-container">
34330
- @if (renderService.serverData.renderMode === renderModes.RenderRoom) {
34331
- <mat-form-field
34332
- class="face-select-form"
34333
- >
34334
- <mat-label>{{ "ENVIRONMENT" | localize }}</mat-label>
34335
- <mat-select [(ngModel)]="selectedRenderScene" (selectionChange)="updateBlenderSceneSettings($event)">
34336
- @for (scene of sceneList; track scene) {
34337
- <mat-option
34338
- [value]="scene">{{ scene.name }}
34339
- </mat-option>
34340
- }
34341
- </mat-select>
34342
- </mat-form-field>
33969
+ <div class="render-container">
33970
+ @if (startUploading) {
33971
+ <rp-render-progress></rp-render-progress>
33972
+ }
33973
+ <!-- the Yellow render indicators -->
33974
+ @if (inPictureMode) {
33975
+ <div class="render-indicators">
33976
+ <div class="render-indicator-top-left"></div>
33977
+ <div class="render-indicator-top-right"></div>
33978
+ <div class="render-indicator-bottom-left"></div>
33979
+ <div class="render-indicator-bottom-right"></div>
33980
+ </div>
33981
+ <div class="render-popup-container">
33982
+ <div class="render-popup-header">
33983
+ <h3>
33984
+ <span>{{ 'PICTURE_MODE' | localize }}</span>
33985
+ @if (hasError) {
33986
+ <co-icon class="renderErrorIcon" [iconData]="iconService.getIcon(icons.TriangleExclamation)"
33987
+ [matTooltip]="'BLENDER_RENDER_ERROR' | localize"></co-icon>
33988
+ }
33989
+ </h3>
33990
+ <button
33991
+ class="close-popup-container"
33992
+ (click)="resetBlenderRenderScene()">
33993
+ <co-icon [iconData]="iconService.getIcon(icons.Cross)"></co-icon>
33994
+ </button>
33995
+ </div>
33996
+ <div class="render-popup-preview">
33997
+ @if (blenderPreviewRender) {
33998
+ <img [src]="blenderPreviewRender" alt="">
34343
33999
  }
34344
- </div>
34345
- <div class="setting-part-container">
34346
- <mat-form-field class="third-width">
34347
- <mat-label [textContent]="'ENVIRONMENT_LIGHT' | localize"></mat-label>
34348
- <input
34349
- [type]="'number'"
34350
- matInput
34351
- [(ngModel)]="hdriIntensity"
34352
- (ngModelChange)="hdriIntensity = +$event">
34353
- </mat-form-field>
34354
- <div class="setting-part-buttons">
34355
- <button class="amount-button" (click)="hdriIntensity = +hdriIntensity - 1">
34356
- <co-icon [iconData]="iconService.getIcon(icons.CircleMinusLight)"></co-icon>
34357
- </button>
34358
- <button class="amount-button" (click)="hdriIntensity = +hdriIntensity + 1">
34359
- <co-icon [iconData]="iconService.getIcon(icons.CirclePlusLight)"></co-icon>
34360
- </button>
34361
- </div>
34362
- <div class="setting-part-slider">
34363
- <mat-slider class="value" min="1" max="20" step="1" [(ngModel)]="hdriIntensity"></mat-slider>
34364
- </div>
34365
- </div>
34366
- <div class="setting-part-container">
34367
- <mat-form-field class="third-width">
34368
- <mat-label [textContent]="'ROTATION' | localize"></mat-label>
34369
- <input
34370
- [type]="'number'"
34371
- matInput
34372
- [(ngModel)]="hdriRotation"
34373
- (ngModelChange)="hdriRotation = +$event">
34374
- </mat-form-field>
34375
- <div class="setting-part-buttons">
34376
- <button class="amount-button" (click)="hdriRotation = +hdriRotation - 1">
34377
- <co-icon [iconData]="iconService.getIcon(icons.CircleMinusLight)"></co-icon>
34378
- </button>
34379
- <button class="amount-button" (click)="hdriRotation = +hdriRotation + 1">
34380
- <co-icon [iconData]="iconService.getIcon(icons.CirclePlusLight)"></co-icon>
34381
- </button>
34382
- </div>
34383
- <div class="setting-part-slider">
34384
- <mat-slider class="value" min="0" max="360" step="1" [(ngModel)]="hdriRotation"></mat-slider>
34385
- </div>
34386
- </div>
34387
- <div class="setting-part-container">
34388
- <mat-form-field class="third-width">
34389
- <mat-label [textContent]="'LIGHTS' | localize"></mat-label>
34390
- <input
34391
- [type]="'number'"
34392
- matInput
34393
- [(ngModel)]="lightingExposure"
34394
- (ngModelChange)="lightingExposure = +$event">
34395
- </mat-form-field>
34396
- <div class="setting-part-buttons">
34397
- <button class="amount-button" (click)="lightingExposure = +lightingExposure - 1">
34398
- <co-icon [iconData]="iconService.getIcon(icons.CircleMinusLight)"></co-icon>
34399
- </button>
34400
- <button class="amount-button" (click)="lightingExposure = +lightingExposure + 1">
34401
- <co-icon [iconData]="iconService.getIcon(icons.CirclePlusLight)"></co-icon>
34402
- </button>
34403
- </div>
34404
- <div class="setting-part-slider">
34405
- <mat-slider class="value" min="1" max="10" step="1" [(ngModel)]="lightingExposure"></mat-slider>
34406
- </div>
34000
+ @if (!blenderPreviewRender) {
34001
+ <div class="render-popup-preview-placeholder">
34002
+ <span>{{ 'PREVIEW' | localize }}</span>
34407
34003
  </div>
34408
- </div>
34409
34004
  }
34410
- </div>
34005
+ <button class="render-popup-refresh-preview" (click)="createBlenderRender(true)">
34006
+ <co-icon [iconData]="iconService.getIcon(icons.RetryButton)"></co-icon>
34007
+ </button>
34008
+ </div>
34009
+ @if (renderService.blendFilesRender) {
34010
+ <div class="render-popup-dropdown">
34011
+ <div class="toggleable" (click)="toggleRenderSettings()">
34012
+ <p>
34013
+ @if (!showRenderSettings) {
34014
+ <span [textContent]="'RENDER_ADVANCED_SETTINGS_SHOW' | localize"></span>
34015
+ }
34016
+ @if (showRenderSettings) {
34017
+ <span [textContent]="'RENDER_ADVANCED_SETTINGS_HIDE' | localize"></span>
34018
+ }
34019
+ </p>
34020
+ <co-icon [ngClass]="{'icon-rotate': showRenderSettings}"
34021
+ [iconData]="iconService.getIcon(icons.ArrowPointDown)"></co-icon>
34022
+ </div>
34023
+ @if (showRenderSettings) {
34024
+ <div class="advanced-render-settings">
34025
+ <div class="setting-part-container">
34026
+ <mat-form-field
34027
+ class="face-select-form"
34028
+ >
34029
+ <mat-label>{{ "ENVIRONMENT" | localize }}</mat-label>
34030
+ <mat-select [(ngModel)]="selectedRenderScene" (selectionChange)="updateBlenderSceneSettings($event)">
34031
+ @for (scene of sceneList; track scene) {
34032
+ <mat-option
34033
+ [value]="scene">{{ scene.name }}
34034
+ </mat-option>
34035
+ }
34036
+ </mat-select>
34037
+ </mat-form-field>
34038
+ </div>
34039
+ <div class="setting-part-container">
34040
+ <mat-form-field class="third-width">
34041
+ <mat-label [textContent]="'ENVIRONMENT_LIGHT' | localize"></mat-label>
34042
+ <input
34043
+ [type]="'number'"
34044
+ matInput
34045
+ [(ngModel)]="hdriIntensity"
34046
+ (ngModelChange)="hdriIntensity = +$event">
34047
+ </mat-form-field>
34048
+ <div class="setting-part-buttons">
34049
+ <button class="amount-button" (click)="hdriIntensity = +hdriIntensity - 1">
34050
+ <co-icon [iconData]="iconService.getIcon(icons.CircleMinusLight)"></co-icon>
34051
+ </button>
34052
+ <button class="amount-button" (click)="hdriIntensity = +hdriIntensity + 1">
34053
+ <co-icon [iconData]="iconService.getIcon(icons.CirclePlusLight)"></co-icon>
34054
+ </button>
34055
+ </div>
34056
+ <div class="setting-part-slider">
34057
+ <mat-slider class="value" min="1" max="20" step="1" [(ngModel)]="hdriIntensity"></mat-slider>
34058
+ </div>
34059
+ </div>
34060
+ <div class="setting-part-container">
34061
+ <mat-form-field class="third-width">
34062
+ <mat-label [textContent]="'ROTATION' | localize"></mat-label>
34063
+ <input
34064
+ [type]="'number'"
34065
+ matInput
34066
+ [(ngModel)]="hdriRotation"
34067
+ (ngModelChange)="hdriRotation = +$event">
34068
+ </mat-form-field>
34069
+ <div class="setting-part-buttons">
34070
+ <button class="amount-button" (click)="hdriRotation = +hdriRotation - 1">
34071
+ <co-icon [iconData]="iconService.getIcon(icons.CircleMinusLight)"></co-icon>
34072
+ </button>
34073
+ <button class="amount-button" (click)="hdriRotation = +hdriRotation + 1">
34074
+ <co-icon [iconData]="iconService.getIcon(icons.CirclePlusLight)"></co-icon>
34075
+ </button>
34076
+ </div>
34077
+ <div class="setting-part-slider">
34078
+ <mat-slider class="value" min="0" max="360" step="1" [(ngModel)]="hdriRotation"></mat-slider>
34079
+ </div>
34080
+ </div>
34081
+ <div class="setting-part-container">
34082
+ <mat-form-field class="third-width">
34083
+ <mat-label [textContent]="'LIGHTS' | localize"></mat-label>
34084
+ <input
34085
+ [type]="'number'"
34086
+ matInput
34087
+ [(ngModel)]="lightingExposure"
34088
+ (ngModelChange)="lightingExposure = +$event">
34089
+ </mat-form-field>
34090
+ <div class="setting-part-buttons">
34091
+ <button class="amount-button" (click)="lightingExposure = +lightingExposure - 1">
34092
+ <co-icon [iconData]="iconService.getIcon(icons.CircleMinusLight)"></co-icon>
34093
+ </button>
34094
+ <button class="amount-button" (click)="lightingExposure = +lightingExposure + 1">
34095
+ <co-icon [iconData]="iconService.getIcon(icons.CirclePlusLight)"></co-icon>
34096
+ </button>
34097
+ </div>
34098
+ <div class="setting-part-slider">
34099
+ <mat-slider class="value" min="1" max="10" step="1" [(ngModel)]="lightingExposure"></mat-slider>
34100
+ </div>
34101
+ </div>
34102
+ </div>
34103
+ }
34104
+ </div>
34411
34105
  }
34412
- @if (renderService.serverData.renderMode === renderModes.RenderRoom) {
34413
- <div class="render-popup-dropdown">
34106
+ <div class="render-popup-dropdown">
34414
34107
  <mat-form-field class="face-select-form">
34415
- <mat-label>{{ "IMAGE_SIZE" | localize }}</mat-label>
34416
- <mat-select [(ngModel)]="renderService.selectedImageSize">
34417
- @for (size of renderService.imageSizes; track size) {
34418
- <mat-option [value]="size.id">{{ size.name }} {{ size.width }}
34419
- x{{ size.height }}
34420
- </mat-option>
34421
- }
34422
- </mat-select>
34108
+ <mat-label>{{ "IMAGE_SIZE" | localize }}</mat-label>
34109
+ <mat-select [(value)]="selectedImageSize">
34110
+ @for (size of imageSizes; track size) {
34111
+ <mat-option [value]="size">{{ size.name }} {{ size.width }}
34112
+ x{{ size.height }}
34113
+ </mat-option>
34114
+ }
34115
+ </mat-select>
34423
34116
  </mat-form-field>
34424
- </div>
34425
- }
34117
+ </div>
34426
34118
  <div class="render-popup-button-container">
34427
- <button class="render-popup-button photo-button"
34428
- (click)="createBlenderRender()"
34429
- title="{{'MAKE_A_PICTURE' | localize}}"
34430
- [disabled]="disablePictureButton">
34431
- <co-icon [iconData]="iconService.getIcon(icons.CircleCheck)"></co-icon>
34432
- {{ 'MAKE_A_PICTURE' | localize }}
34433
- </button>
34434
- <button
34435
- class="render-popup-button cancel-button"
34436
- (click)="resetBlenderRenderScene()">
34437
- <co-icon [iconData]="iconService.getIcon(icons.CircleXmark)"></co-icon>
34438
- {{ 'CLOSE_PHOTO_MODE' | localize }}
34439
- </button>
34119
+ <button class="render-popup-button photo-button"
34120
+ (click)="createBlenderRender()"
34121
+ title="{{'MAKE_A_PICTURE' | localize}}"
34122
+ [disabled]="disablePictureButton">
34123
+ <co-icon [iconData]="iconService.getIcon(icons.CircleCheck)"></co-icon>
34124
+ {{ 'MAKE_A_PICTURE' | localize }}
34125
+ </button>
34126
+ <button
34127
+ class="render-popup-button cancel-button"
34128
+ (click)="resetBlenderRenderScene()">
34129
+ <co-icon [iconData]="iconService.getIcon(icons.CircleXmark)"></co-icon>
34130
+ {{ 'CLOSE_PHOTO_MODE' | localize }}
34131
+ </button>
34440
34132
  </div>
34441
- </div>
34442
- }
34443
- @if (showCullingErrorDialog) {
34444
- <div class="render-warning">
34133
+ </div>
34134
+ }
34135
+ @if (showCullingErrorDialog) {
34136
+ <div class="render-warning">
34445
34137
  <div class="render-warming-header">
34446
- <h2>{{ 'BLENDER_RENDER_ERROR_TITLE' | localize }}</h2>
34447
- <div class="render-warning-close" (click)="showCullingErrorDialog = false">
34448
- <mat-icon class="homedecorator-material-icons">cancel</mat-icon>
34449
- </div>
34138
+ <h2>{{ 'BLENDER_RENDER_ERROR_TITLE' | localize }}</h2>
34139
+ <div class="render-warning-close" (click)="showCullingErrorDialog = false">
34140
+ <mat-icon class="homedecorator-material-icons">cancel</mat-icon>
34141
+ </div>
34450
34142
  </div>
34451
34143
  <div class="render-warning-body">
34452
- <p>{{ 'BLENDER_RENDER_WARNING_CULLING' | localize }}</p>
34144
+ <p>{{ 'BLENDER_RENDER_WARNING_CULLING' | localize }}</p>
34453
34145
  </div>
34454
34146
  <div class="render-warning-footer">
34455
- <button
34456
- class="render-popup-button cancel-button"
34457
- (click)="showCullingErrorDialog = false">
34458
- <co-icon [iconData]="iconService.getIcon(icons.CircleXmark)"></co-icon>
34459
- {{ 'CLOSE' | localize }}
34460
- </button>
34147
+ <button
34148
+ class="render-popup-button cancel-button"
34149
+ (click)="showCullingErrorDialog = false">
34150
+ <co-icon [iconData]="iconService.getIcon(icons.CircleXmark)"></co-icon>
34151
+ {{ 'CLOSE' | localize }}
34152
+ </button>
34461
34153
  </div>
34462
- </div>
34463
- }
34464
- <rp-render-progress
34465
- [title]="'PREPARE_TO_RENDER' | localize"
34466
- [show]="startUploading"
34467
- >
34468
- </rp-render-progress>
34469
- <button
34470
- #renderButton
34471
- mat-raised-button
34472
- matTooltip="{{'RENDER_TAKE_A_PICTURE' | localize}}"
34473
- [id]="'standalone_render_picture'"
34474
- [class.active]="(
34475
- (renderService.serverData.renderMode === renderService.renderModes.RenderRoom && viewModeService.viewMode === viewModes.WalkThrough) ||
34476
- (renderService.serverData.renderMode === renderService.renderModes.RenderIone))"
34477
- (click)="showRenderForm($event)"
34478
- >
34479
- <mat-icon class="icon homedecorator-material-icons"
34480
- aria-hidden="true">{{ (renderService.currentQueueRenderItem.renderStatus === renderStatus.IsRunning ? 'open_in_browser' : 'photo_camera') }}
34481
- </mat-icon>
34482
- </button>
34483
- </div>
34154
+ </div>
34484
34155
  }
34485
-
34486
- `, standalone: false, styles: [".render-container{position:relative}.render-container .render-popup-container{background:#ffffffb3;padding:10px 25px 25px;border-radius:5px;box-shadow:0 1px 5px #0000001f}.render-container .render-popup-container .render-popup-header{display:flex;justify-content:space-between;font-family:inherit}.render-container .render-popup-container .render-popup-header h3{display:flex;justify-content:space-between}.render-container .render-popup-container .render-popup-header h3 ::ng-deep .renderErrorIcon{width:20px;height:20px;margin-left:20px}.render-container .render-popup-container .render-popup-header h3 ::ng-deep .renderErrorIcon svg,.render-container .render-popup-container .render-popup-header h3 ::ng-deep .renderErrorIcon svg polygon{fill:#dc143c}.render-container .render-popup-container .render-popup-header .close-popup-container{cursor:pointer;border:none;background:none;float:none;height:auto;width:auto}.render-container .render-popup-container .render-popup-button-container{display:flex;justify-content:space-between;font-family:inherit}.render-container .render-popup-container .render-popup-button-container .render-popup-button{float:none;width:100%;max-width:130px;border-radius:3px;cursor:pointer;border:none;display:flex;height:40px;align-items:center;justify-content:space-evenly}.render-container .render-popup-container .render-popup-button-container .render-popup-button ::ng-deep co-icon{display:inline-block;height:18px;width:18px}.render-container .render-popup-container .render-popup-button-container .render-popup-button ::ng-deep co-icon svg path{fill:#fff}.render-container .render-popup-container .render-popup-button-container .photo-button{color:#fff;background-color:#dda73f}.render-container .render-popup-container .render-popup-button-container .cancel-button{color:#fff;background-color:#5b6875}.render-container .render-popup-container .render-popup-preview{background-color:#fff;min-height:150px;min-width:275px;margin:5px 0;position:relative;width:275px;height:150px}.render-container .render-popup-container .render-popup-preview .render-popup-preview-placeholder{background-color:#fff;display:flex;justify-content:space-around;align-items:center;vertical-align:middle;min-height:150px;border:1px solid #ddd;color:#ddd;font-size:14px}.render-container .render-popup-container .render-popup-preview .render-popup-refresh-preview{position:absolute;bottom:0;right:0;cursor:pointer;border-radius:0;border:none;height:30px;width:30px;background-color:#dda73f;color:#fff;margin:0}.render-container .render-popup-container .render-popup-preview .render-popup-refresh-preview ::ng-deep co-icon svg path{fill:#fff}.render-container .render-popup-container .render-popup-dropdown{margin:5px 0;width:100%}.render-container .render-popup-container .render-popup-dropdown .toggleable{cursor:pointer;display:flex;justify-content:right;align-content:center}.render-container .render-popup-container .render-popup-dropdown .toggleable p{padding:0;margin:0;font-size:12px;line-height:30px}.render-container .render-popup-container .render-popup-dropdown .toggleable .icon-rotate{transform:rotate(180deg)}.render-container .render-popup-container .render-popup-dropdown .mat-mdc-form-field{width:100%;font-size:14px}.render-container .render-popup-container .render-popup-dropdown .mat-mdc-form-field ::ng-deep .mat-mdc-form-field-flex{background-color:#fff;color:#000;padding:3px 6px;border:1px solid #ddd}.render-container .render-popup-container .render-popup-dropdown .mat-mdc-form-field ::ng-deep .mat-mdc-form-field-underline{display:none}.render-container .render-popup-container .render-popup-dropdown .mat-mdc-form-field ::ng-deep .mat-mdc-form-field-wrapper{padding-bottom:0}.render-container .render-popup-container .render-popup-dropdown .setting-part-container{display:flex;justify-content:space-between;align-items:center;margin-bottom:5px}.render-container .render-popup-container .render-popup-dropdown .setting-part-container .third-width{width:32%}.render-container .render-popup-container .render-popup-dropdown .setting-part-container .setting-part-buttons .amount-button{float:none;box-sizing:border-box;padding:2px;background:none;cursor:pointer;border:none;width:25px;height:25px;margin:0 5px}.render-container .render-popup-container .render-popup-dropdown .setting-part-container .setting-part-buttons .amount-button co-icon{display:block;width:25px;height:25px}.render-container .render-popup-container .render-popup-dropdown .setting-part-container .setting-part-buttons .amount-button co-icon ::ng-deep svg{fill:#5b6875}.render-container .render-popup-container .render-popup-dropdown .setting-part-container .setting-part-slider .mat-slider-horizontal{min-width:110px;height:28px}.render-container .render-progress{float:left;min-width:50px;border-radius:25px;line-height:50px;text-align:center;padding:0 60px 0 20px;background:#fff;color:#74b77f;font-weight:700;margin:0 -50px 0 0}.render-container .render-input-container{float:right}.render-container .render-input-container input{width:100px;height:24px;margin:5px 0;padding:0 10px;font-size:14px}.render-container button{pointer-events:all;width:50px;height:50px;float:right;border-radius:100%;position:relative;z-index:2;margin-bottom:10px}.render-container button.active{background:#74b77f;color:#fff}.render-container button>*{pointer-events:none}.render-indicators div{position:fixed;width:100px;height:100px}.render-indicators .render-indicator-top-left{left:5vw;top:10vh;border-left:10px solid #dda73f;border-top:10px solid #dda73f;border-top-left-radius:20px}.render-indicators .render-indicator-top-right{right:5vw;top:10vh;border-right:10px solid #dda73f;border-top:10px solid #dda73f;border-top-right-radius:20px}.render-indicators .render-indicator-bottom-left{left:5vw;bottom:5vh;border-left:10px solid #dda73f;border-bottom:10px solid #dda73f;border-bottom-left-radius:20px}.render-indicators .render-indicator-bottom-right{right:5vw;bottom:5vh;border-right:10px solid #dda73f;border-bottom:10px solid #dda73f;border-bottom-right-radius:20px}.render-warning{width:500px;position:fixed;top:20%;left:calc(50% - 250px);border-radius:15px;box-sizing:border-box;background-color:#fff;box-shadow:1px 0 20px #0000001f}.render-warning .render-warming-header{display:flex;justify-content:space-between;border-bottom:1px solid #c5c3c6;padding:20px 20px 10px;align-items:center}.render-warning .render-warming-header h2{padding:0;margin:0}.render-warning .render-warming-header .render-warning-close mat-icon{fill:#c5c3c6;color:#c5c3c6;cursor:pointer;transition:all .2s ease}.render-warning .render-warming-header .render-warning-close:hover mat-icon{fill:#46494c;color:#46494c}.render-warning .render-warning-body{padding:10px 20px}.render-warning .render-warning-footer{display:flex;justify-content:center;padding:0 20px 10px}.render-warning .render-warning-footer .render-popup-button{float:none;width:110px;border-radius:3px;cursor:pointer;border:none;display:flex;height:40px;align-items:center;justify-content:space-evenly;color:#fff;background-color:#5b6875}.render-warning .render-warning-footer .render-popup-button ::ng-deep co-icon{display:inline-block;height:18px;width:18px}.render-warning .render-warning-footer .render-popup-button ::ng-deep co-icon svg path{fill:#fff}\n"] }]
34487
- }], ctorParameters: () => [{ type: RenderService }, { type: MessageBusService }, { type: ViewModeService }, { type: HomedecoratorSettingsService }, { type: HomedecoratorIconCacheService }, { type: i1$2.MatDialog }, { type: SceneService }, { type: CameraService }, { type: ConfigurationService }, { type: HomedecoratorSettingsService }, { type: NewRenderService }, { type: UtilsService }, { type: RoomService }, { type: WallMeasurementsService }, { type: ConnectionHeathService }, { type: HomedecoratorDictionaryService }], propDecorators: { renderButton: [{
34156
+ <button
34157
+ #renderButton
34158
+ mat-raised-button
34159
+ matTooltip="{{'RENDER_TAKE_A_PICTURE' | localize}}"
34160
+ [id]="'standalone_render_picture'"
34161
+ [class.active]="viewModeService.viewMode === viewModes.WalkThrough"
34162
+ (click)="showRenderForm($event)">
34163
+ <mat-icon class="icon homedecorator-material-icons"
34164
+ aria-hidden="true">{{ 'photo_camera' }}
34165
+ </mat-icon>
34166
+ </button>
34167
+ </div>
34168
+ `, standalone: false, styles: [".render-container{position:relative}.render-container .render-popup-container{background:#ffffffb3;padding:10px 25px 25px;border-radius:5px;box-shadow:0 1px 5px #0000001f}.render-container .render-popup-container .render-popup-header{display:flex;justify-content:space-between;font-family:inherit}.render-container .render-popup-container .render-popup-header h3{display:flex;justify-content:space-between}.render-container .render-popup-container .render-popup-header h3 ::ng-deep .renderErrorIcon{width:20px;height:20px;margin-left:20px}.render-container .render-popup-container .render-popup-header h3 ::ng-deep .renderErrorIcon svg,.render-container .render-popup-container .render-popup-header h3 ::ng-deep .renderErrorIcon svg polygon{fill:#dc143c}.render-container .render-popup-container .render-popup-header .close-popup-container{cursor:pointer;border:none;background:none;float:none;height:auto;width:auto}.render-container .render-popup-container .render-popup-button-container{display:flex;justify-content:space-between;font-family:inherit}.render-container .render-popup-container .render-popup-button-container .render-popup-button{float:none;width:100%;max-width:130px;border-radius:3px;cursor:pointer;border:none;display:flex;height:40px;align-items:center;justify-content:space-evenly}.render-container .render-popup-container .render-popup-button-container .render-popup-button ::ng-deep co-icon{display:inline-block;height:18px;width:18px}.render-container .render-popup-container .render-popup-button-container .render-popup-button ::ng-deep co-icon svg path{fill:#fff}.render-container .render-popup-container .render-popup-button-container .photo-button{color:#fff;background-color:#dda73f}.render-container .render-popup-container .render-popup-button-container .cancel-button{color:#fff;background-color:#5b6875}.render-container .render-popup-container .render-popup-preview{background-color:#fff;min-height:150px;min-width:275px;margin:5px 0;position:relative;width:275px;height:150px}.render-container .render-popup-container .render-popup-preview .render-popup-preview-placeholder{background-color:#fff;display:flex;justify-content:space-around;align-items:center;vertical-align:middle;min-height:150px;border:1px solid #ddd;color:#ddd;font-size:14px}.render-container .render-popup-container .render-popup-preview .render-popup-refresh-preview{position:absolute;bottom:0;right:0;cursor:pointer;border-radius:0;border:none;height:30px;width:30px;background-color:#dda73f;color:#fff;margin:0}.render-container .render-popup-container .render-popup-preview .render-popup-refresh-preview ::ng-deep co-icon svg path{fill:#fff}.render-container .render-popup-container .render-popup-dropdown{margin:5px 0;width:100%}.render-container .render-popup-container .render-popup-dropdown .toggleable{cursor:pointer;display:flex;justify-content:right;align-content:center}.render-container .render-popup-container .render-popup-dropdown .toggleable p{padding:0;margin:0;font-size:12px;line-height:30px}.render-container .render-popup-container .render-popup-dropdown .toggleable .icon-rotate{transform:rotate(180deg)}.render-container .render-popup-container .render-popup-dropdown .mat-mdc-form-field{width:100%;font-size:14px}.render-container .render-popup-container .render-popup-dropdown .mat-mdc-form-field ::ng-deep .mat-mdc-form-field-flex{background-color:#fff;color:#000;padding:3px 6px;border:1px solid #ddd}.render-container .render-popup-container .render-popup-dropdown .mat-mdc-form-field ::ng-deep .mat-mdc-form-field-underline{display:none}.render-container .render-popup-container .render-popup-dropdown .mat-mdc-form-field ::ng-deep .mat-mdc-form-field-wrapper{padding-bottom:0}.render-container .render-popup-container .render-popup-dropdown .setting-part-container{display:flex;justify-content:space-between;align-items:center;margin-bottom:5px}.render-container .render-popup-container .render-popup-dropdown .setting-part-container .third-width{width:32%}.render-container .render-popup-container .render-popup-dropdown .setting-part-container .setting-part-buttons .amount-button{float:none;box-sizing:border-box;padding:2px;background:none;cursor:pointer;border:none;width:25px;height:25px;margin:0 5px}.render-container .render-popup-container .render-popup-dropdown .setting-part-container .setting-part-buttons .amount-button co-icon{display:block;width:25px;height:25px}.render-container .render-popup-container .render-popup-dropdown .setting-part-container .setting-part-buttons .amount-button co-icon ::ng-deep svg{fill:#5b6875}.render-container .render-popup-container .render-popup-dropdown .setting-part-container .setting-part-slider .mat-slider-horizontal{min-width:110px;height:28px}.render-container .render-progress{float:left;min-width:50px;border-radius:25px;line-height:50px;text-align:center;padding:0 60px 0 20px;background:#fff;color:#74b77f;font-weight:700;margin:0 -50px 0 0}.render-container .render-input-container{float:right}.render-container .render-input-container input{width:100px;height:24px;margin:5px 0;padding:0 10px;font-size:14px}.render-container button{pointer-events:all;width:50px;height:50px;float:right;border-radius:100%;position:relative;z-index:2;margin-bottom:10px}.render-container button.active{background:#74b77f;color:#fff}.render-container button>*{pointer-events:none}.render-indicators div{position:fixed;width:100px;height:100px}.render-indicators .render-indicator-top-left{left:5vw;top:10vh;border-left:10px solid #dda73f;border-top:10px solid #dda73f;border-top-left-radius:20px}.render-indicators .render-indicator-top-right{right:5vw;top:10vh;border-right:10px solid #dda73f;border-top:10px solid #dda73f;border-top-right-radius:20px}.render-indicators .render-indicator-bottom-left{left:5vw;bottom:5vh;border-left:10px solid #dda73f;border-bottom:10px solid #dda73f;border-bottom-left-radius:20px}.render-indicators .render-indicator-bottom-right{right:5vw;bottom:5vh;border-right:10px solid #dda73f;border-bottom:10px solid #dda73f;border-bottom-right-radius:20px}.render-warning{width:500px;position:fixed;top:20%;left:calc(50% - 250px);border-radius:15px;box-sizing:border-box;background-color:#fff;box-shadow:1px 0 20px #0000001f}.render-warning .render-warming-header{display:flex;justify-content:space-between;border-bottom:1px solid #c5c3c6;padding:20px 20px 10px;align-items:center}.render-warning .render-warming-header h2{padding:0;margin:0}.render-warning .render-warming-header .render-warning-close mat-icon{fill:#c5c3c6;color:#c5c3c6;cursor:pointer;transition:all .2s ease}.render-warning .render-warming-header .render-warning-close:hover mat-icon{fill:#46494c;color:#46494c}.render-warning .render-warning-body{padding:10px 20px}.render-warning .render-warning-footer{display:flex;justify-content:center;padding:0 20px 10px}.render-warning .render-warning-footer .render-popup-button{float:none;width:110px;border-radius:3px;cursor:pointer;border:none;display:flex;height:40px;align-items:center;justify-content:space-evenly;color:#fff;background-color:#5b6875}.render-warning .render-warning-footer .render-popup-button ::ng-deep co-icon{display:inline-block;height:18px;width:18px}.render-warning .render-warning-footer .render-popup-button ::ng-deep co-icon svg path{fill:#fff}\n"] }]
34169
+ }], ctorParameters: () => [{ type: MessageBusService }, { type: ViewModeService }, { type: HomedecoratorSettingsService }, { type: HomedecoratorIconCacheService }, { type: RenderService }, { type: i1$2.MatDialog }, { type: SceneService }, { type: CameraService }, { type: ConfigurationService }, { type: HomedecoratorSettingsService }, { type: UtilsService }, { type: RoomService }, { type: WallMeasurementsService }, { type: ConnectionHeathService }, { type: HomedecoratorDictionaryService }, { type: DialogService }], propDecorators: { renderButton: [{
34488
34170
  type: ViewChild,
34489
34171
  args: ['renderButton']
34490
34172
  }] } });
@@ -36452,11 +36134,6 @@ class FloorplannerComponent {
36452
36134
  this._lastNode = null;
36453
36135
  this._subs = [];
36454
36136
  this._selectedFloor = null;
36455
- this._diagramBackgroundScale = 1;
36456
- this._diagramBackgroundCurrentScale = 100;
36457
- this._diagramBackgroundActiveZoom = false;
36458
- this._diagramBackgroundAlpha = 0.5;
36459
- this._showDiagramBackground = true;
36460
36137
  this._readyToDraw = false;
36461
36138
  this._needsRedraw = false;
36462
36139
  Object.keys(this._configToSync).forEach((key) => {
@@ -36489,7 +36166,7 @@ class FloorplannerComponent {
36489
36166
  const dataUrl = this._canvas.toDataURL('image/jpeg');
36490
36167
  FileUtils.DownloadFromDataUri(dataUrl, `MyRoomplan${new Date().toISOString()}.jpeg`);
36491
36168
  }
36492
- }), this._messageBusService.subscribe(MessageType.StartWithEmptyRoom, () => this.showStartMessage()), this._messageBusService.subscribe(MessageType.LoadScaledDiagram, (input) => this.setDiagramSettings(input)), this._messageBusService.subscribe(MessageType.ToggleDiagram, () => this.toggleDiagram()));
36169
+ }), this._messageBusService.subscribe(MessageType.StartWithPreset, () => this._clearBackground()), this._messageBusService.subscribe(MessageType.LoadRoomFromPreset, () => this._clearBackground()), this._messageBusService.subscribe(MessageType.LoadRoomFromCloud, () => this._clearBackground()), this._messageBusService.subscribe(MessageType.NewRoom, () => this._clearBackground()), this._messageBusService.subscribe(MessageType.ResetRoomplan, () => this._clearBackground()), this._messageBusService.subscribe(MessageType.LoadScaledDiagram, () => this._clearBackground()), this._messageBusService.subscribe(MessageType.StartWithEmptyRoom, () => this.showStartMessage()), this._messageBusService.subscribe(MessageType.LoadScaledDiagram, (input) => this.setDiagramSettings(input)), this._messageBusService.subscribe(MessageType.ToggleDiagram, () => this.toggleDiagram()));
36493
36170
  this.touchMode = this._configurationService.getValue(ConfigurationKey.EnableTouch);
36494
36171
  this.currentDimensioning = this._configurationService.getValue(ConfigurationKey.DimensioningUnit);
36495
36172
  this.currentRoundingDecimals = this._configurationService.getValue(ConfigurationKey.RoundingDecimals);
@@ -36553,10 +36230,13 @@ class FloorplannerComponent {
36553
36230
  this._draw();
36554
36231
  });
36555
36232
  }
36556
- showStartMessage() {
36557
- if (this._diagramBackground) {
36558
- this._diagramBackground.src = '';
36233
+ _clearBackground() {
36234
+ if (this._renderService.diagramBackground) {
36235
+ this._renderService.diagramBackground = undefined;
36559
36236
  }
36237
+ }
36238
+ showStartMessage() {
36239
+ this._clearBackground();
36560
36240
  this._bluePrintService.reset();
36561
36241
  this.showStartingMessages = true;
36562
36242
  this._requestDraw();
@@ -36582,10 +36262,9 @@ class FloorplannerComponent {
36582
36262
  if (!this._coordinatesService.canZoomIn) {
36583
36263
  return;
36584
36264
  }
36585
- this._clear();
36586
36265
  this._coordinatesService.zoomIn();
36587
- this._diagramBackgroundScale *= this._coordinatesService.scalingFactor;
36588
- this._diagramBackgroundActiveZoom = true;
36266
+ this._renderService.diagramBackgroundScale *= this._coordinatesService.scalingFactor;
36267
+ this._renderService.diagramBackgroundActiveZoom = true;
36589
36268
  this._scale(this._coordinatesService.scalingFactor, this._coordinatesService.scalingFactor);
36590
36269
  this.resizeView();
36591
36270
  this._requestDraw();
@@ -36594,16 +36273,14 @@ class FloorplannerComponent {
36594
36273
  if (!this._coordinatesService.canZoomOut) {
36595
36274
  return;
36596
36275
  }
36597
- this._clear();
36598
36276
  this._coordinatesService.zoomOut();
36599
- this._diagramBackgroundScale *= (1 / this._coordinatesService.scalingFactor);
36600
- this._diagramBackgroundActiveZoom = true;
36277
+ this._renderService.diagramBackgroundScale *= (1 / this._coordinatesService.scalingFactor);
36278
+ this._renderService.diagramBackgroundActiveZoom = true;
36601
36279
  this._scale(1 / this._coordinatesService.scalingFactor, 1 / this._coordinatesService.scalingFactor);
36602
36280
  this.resizeView();
36603
36281
  this._requestDraw();
36604
36282
  }
36605
36283
  zoomReset() {
36606
- this._clear();
36607
36284
  this._scale(1 / this._viewScale, 1 / this._viewScale);
36608
36285
  this.reset();
36609
36286
  }
@@ -36948,15 +36625,15 @@ class FloorplannerComponent {
36948
36625
  this._coordinatesService.resetOrigin();
36949
36626
  this._viewScale = 100;
36950
36627
  this._bluePrintService.reset();
36951
- this._diagramBackground = input.background;
36952
- this._diagramBackgroundHeight = input.backgroundHeight;
36953
- this._diagramBackgroundWidth = input.backgroundWidth;
36954
- this._diagramScale = input.scale;
36628
+ this._renderService.diagramBackground = input.background;
36629
+ this._renderService.diagramBackgroundHeight = input.backgroundHeight;
36630
+ this._renderService.diagramBackgroundWidth = input.backgroundWidth;
36631
+ this._renderService.diagramBackgroundScale = input.scale;
36955
36632
  this._cameraZoom = input.cameraZoom;
36956
36633
  this._requestDraw();
36957
36634
  }
36958
36635
  toggleDiagram() {
36959
- this._showDiagramBackground = !this._showDiagramBackground;
36636
+ this._renderService.showDiagramBackground = !this._renderService.showDiagramBackground;
36960
36637
  this._requestDraw();
36961
36638
  }
36962
36639
  _removeWall() {
@@ -37030,23 +36707,6 @@ class FloorplannerComponent {
37030
36707
  await this._bluePrintService.update();
37031
36708
  this._requestDraw();
37032
36709
  }
37033
- _drawBackground() {
37034
- if (this._diagramBackgroundActiveZoom) {
37035
- if (this._diagramBackgroundCurrentScale <= this._viewScale) {
37036
- this._diagramBackgroundWidth = this._diagramBackgroundWidth * this._coordinatesService.scalingFactor;
37037
- this._diagramBackgroundHeight = this._diagramBackgroundHeight * this._coordinatesService.scalingFactor;
37038
- }
37039
- else {
37040
- this._diagramBackgroundWidth = this._diagramBackgroundWidth * (1 / this._coordinatesService.scalingFactor);
37041
- this._diagramBackgroundHeight = this._diagramBackgroundHeight * (1 / this._coordinatesService.scalingFactor);
37042
- }
37043
- this._diagramBackgroundActiveZoom = false;
37044
- }
37045
- this._diagramBackgroundCurrentScale = this._viewScale;
37046
- this._context.globalAlpha = this._diagramBackgroundAlpha;
37047
- this._context.drawImage(this._diagramBackground, Math.abs(this._coordinatesService.originX) - (this._diagramBackgroundWidth * this._diagramScale / 2), Math.abs(this._coordinatesService.originY) - (this._diagramBackgroundHeight * this._diagramScale / 2), this._diagramBackgroundWidth * this._diagramScale, this._diagramBackgroundHeight * this._diagramScale);
37048
- this._context.globalAlpha = 1;
37049
- }
37050
36710
  _handleWindowResize() {
37051
36711
  if (this._canvas) {
37052
36712
  const parent = this._canvas.parentElement;
@@ -37059,11 +36719,6 @@ class FloorplannerComponent {
37059
36719
  this._requestDraw();
37060
36720
  }
37061
36721
  }
37062
- _clear() {
37063
- if (this._context && this._canvas) {
37064
- this._context.clearRect(0, 0, this._canvas.width, this._canvas.height);
37065
- }
37066
- }
37067
36722
  _updateWallPosition() {
37068
36723
  if (this._wallLength) {
37069
36724
  const startPoint = this._lastNode;
@@ -44489,7 +44144,7 @@ class ThreedselectorComponent {
44489
44144
  this.handleBuildResult(result);
44490
44145
  }), this._buildFurnitureService.currentActiveService.configureModeChanged.subscribe(configuringModeChange => this._handleConfigureModeChange(configuringModeChange)), this._buildFurnitureService.currentActiveService.toggleSelectedElement.subscribe((element) => this._selectedElementToggle(element)), this._buildFurnitureService.currentActiveService.buildFinished.subscribe((result) => this._handleBuildFinished(result)), this._buildFurnitureService.currentActiveService.answerSelected.subscribe((result) => this._answerSelected(result)), this._sceneService.onAfterRender.subscribe(() => this._handleRender()),
44491
44146
  // this._appService.skuSet.subscribe(sku => this._handleSkuSet(sku)),
44492
- this._appService.materialPreviewSet.subscribe(material => this._handleMaterialSet(material)), this._appService.materialPreviewUpdate.subscribe(material => this._updateMaterialPreview(material)), this._appEventService.articleInfoReceived.subscribe(info => this._handleInfoClick(info)), this._messageService.subscribe(MessageType.UndefinedErrorOccured, () => this._handleUndefinedErrorOccured()), this._presetsService.afterLoad.subscribe(() => this._afterLoadFromPreset()), this._messageBus.subscribe(MessageType.Undo, () => this._clearItems()), this._messageBus.subscribe(MessageType.Redo, () => this._clearItems()), this._messageBus.subscribe(MessageType.StartWithEmptyRoom, () => this._clearItems()), this._messageBus.subscribe(MessageType.StartWithPreset, () => this._clearItems()), this._messageBus.subscribe(MessageType.LoadRoomFromPreset, () => this._clearItems()), this._messageBus.subscribe(MessageType.LoadRoomFromCloud, () => this._clearItems()), this._messageBus.subscribe(MessageType.NewRoom, () => this._clearItems()), this._messageBus.subscribe(MessageType.ResetRoomplan, () => this._clearItems()), this._messageBus.subscribe(MessageType.LoadScaledDiagram, () => this._clearItems()), this._presetsService.beforeLoad.subscribe(() => this._clearItems()), this._messageService.subscribe(MessageType.ItemSelected, (item) => this.objectSelected(item)), this._messageService.subscribe(MessageType.ItemUnselected, () => this._removeButtons()), this.screenSizeService.screenSizeChanged.subscribe((info) => {
44147
+ this._appService.materialPreviewSet.subscribe(material => this._handleMaterialSet(material)), this._appService.materialPreviewUpdate.subscribe(material => this._updateMaterialPreview(material)), this._appEventService.articleInfoReceived.subscribe(info => this._handleInfoClick(info)), this._messageService.subscribe(MessageType.UndefinedErrorOccured, () => this._handleUndefinedErrorOccured()), this._presetsService.afterLoad.subscribe(() => this._afterLoadFromPreset()), this._messageBus.subscribe(MessageType.Undo, () => this._clearItems()), this._messageBus.subscribe(MessageType.Redo, () => this._clearItems()), this._messageBus.subscribe(MessageType.StartWithEmptyRoom, () => this._clearItems()), this._messageBus.subscribe(MessageType.StartWithPreset, () => this._clearItems()), this._messageBus.subscribe(MessageType.LoadRoomFromPreset, () => this._clearItems()), this._messageBus.subscribe(MessageType.LoadRoomFromCloud, () => this._clearItems()), this._messageBus.subscribe(MessageType.NewRoom, () => this._clearItems()), this._messageBus.subscribe(MessageType.ResetRoomplan, () => this._clearItems()), this._messageBus.subscribe(MessageType.LoadScaledDiagram, () => this._clearItems()), this._presetsService.beforeLoad.subscribe(() => this._clearItems()), this._messageService.subscribe(MessageType.ItemSelected, (item) => this.objectSelected(item)), this._messageService.subscribe(MessageType.ItemUnselected, () => this._removeButtons()), this._messageService.subscribe(MessageType.UserModelUploaded, (data) => this._addUploadedItem(data)), this.screenSizeService.screenSizeChanged.subscribe((info) => {
44493
44148
  this.shouldShowLabel = info.isPhoneSize;
44494
44149
  }), this._messageService.subscribe(MessageType.ChangeArticleConfigurationType, (showFullConfig) => this._setTemplateType(showFullConfig)), this._settingsService.settingsLoaded.subscribe((loaded) => {
44495
44150
  if (loaded) {
@@ -44565,6 +44220,9 @@ class ThreedselectorComponent {
44565
44220
  getObjects() {
44566
44221
  // return {furniture: this.threeService.model.saveFurniture()};
44567
44222
  }
44223
+ async saveObjects() {
44224
+ return Promise.resolve();
44225
+ }
44568
44226
  objectSelected(object) {
44569
44227
  this._removeCustomButtons();
44570
44228
  this.showCustomizeButtons = true;
@@ -44625,7 +44283,7 @@ class ThreedselectorComponent {
44625
44283
  }
44626
44284
  // NEW CONFIGURATOR
44627
44285
  async handleBuildResult(result) {
44628
- if (!result || this.firstBuild) {
44286
+ if (!result || this.firstBuild || !this._sceneService.scene) {
44629
44287
  return;
44630
44288
  }
44631
44289
  const customFloorGroupResult = new CustomFloorGroupResult();
@@ -44662,10 +44320,12 @@ class ThreedselectorComponent {
44662
44320
  if (customFloorGroupResult.furniture) {
44663
44321
  const closestWall = this._wallService.getClosestWall(customFloorGroupResult.furniture.position.x, customFloorGroupResult.furniture.position.z);
44664
44322
  if (customFloorGroupResult.furniture instanceof CustomWallFloorItem && customFloorGroupResult.furniture.onWall) {
44323
+ this._itemService.removeItem(customFloorGroupResult.furniture, false, false);
44665
44324
  customFloorGroupResult.furniture.placeOnWall(closestWall);
44666
44325
  customFloorGroupResult.furniture.moveFromFloorToWall();
44667
44326
  }
44668
44327
  else if (customFloorGroupResult.furniture instanceof WallItem && !(customFloorGroupResult.furniture instanceof CustomWallFloorItem)) {
44328
+ this._itemService.removeItem(customFloorGroupResult.furniture, false, false);
44669
44329
  customFloorGroupResult.furniture.placeOnWall(closestWall);
44670
44330
  }
44671
44331
  if (customFloorGroupResult.metaData.configurable) {
@@ -44735,7 +44395,7 @@ class ThreedselectorComponent {
44735
44395
  this._messageBus.emit(MessageType.FinishedIOneFurnitureBuild);
44736
44396
  }
44737
44397
  setMetadateFromObject(result) {
44738
- if (result.originalMetadata) {
44398
+ if (result && result.originalMetadata) {
44739
44399
  const metadata = Object.assign({}, result.originalMetadata);
44740
44400
  metadata.decos = result.decos;
44741
44401
  metadata.selections = result.selections;
@@ -44784,21 +44444,29 @@ class ThreedselectorComponent {
44784
44444
  if (configuratorExternalSourceId) {
44785
44445
  if (settings.hasOwnProperty('settings')) {
44786
44446
  const settingsInterface = settings['settings'];
44447
+ configuratorSettingsClone.externalSourceId = configuratorExternalSourceId;
44787
44448
  configuratorSettingsClone.username = settingsInterface.username;
44788
- configuratorSettingsClone.password = settingsInterface.password;
44789
44449
  configuratorSettingsClone.url = settingsInterface.url;
44790
44450
  configuratorSettingsClone.version = settingsInterface.version;
44791
44451
  configuratorSettingsClone.schema = settingsInterface.schema;
44452
+ configuratorSettingsClone.mainUrl = settings.mainUrl;
44453
+ configuratorSettingsClone.mainSchema = settings.mainSchema;
44454
+ configuratorSettingsClone.mainVersion = settings.mainVersion;
44792
44455
  // Set here to just save it, when it comes back from the configurator, we need to add it to the metadata.
44793
44456
  this._externalSourceData = settings;
44794
44457
  }
44795
44458
  }
44796
44459
  this._configuringService.scene = this._sceneService.scene;
44797
- this._initConfigurator(configuratorSettingsClone, sku);
44460
+ this._initConfigurator(configuratorSettingsClone, sku, !!configuratorExternalSourceId);
44461
+ // await this._configuringService.init(configuratorSettingsClone);
44462
+ // const furnitureData: ConfigurationResultObject = new ConfigurationResultObject();
44463
+ // furnitureData.sku = sku;
44464
+ // this._configuringService.isConfiguring = false;
44465
+ // await this._configuringService.configure(furnitureData);
44798
44466
  this._startPosition = position;
44799
44467
  this.loadConfigurator = true;
44800
44468
  this._changeDetector.detectChanges();
44801
- return this._waitForBuildToFinish();
44469
+ return this._waitForBuildToFinish(); // handleBuildResult(this._configuringService.buildResult);
44802
44470
  }
44803
44471
  async configureFurniture(object) {
44804
44472
  if (object instanceof Item) {
@@ -44809,16 +44477,33 @@ class ThreedselectorComponent {
44809
44477
  if (configuratorExternalSourceId) {
44810
44478
  this._externalSourceData = object.metadata.externalSettings; // set it so we can restore them with the new config.
44811
44479
  }
44812
- this._initConfigurator(configuratorSettingsClone, object.metadata.itemIdentifier, object.metadata.itemId);
44480
+ // make sure that if the object contains metadata, we set from project true
44481
+ // await this._configuringService.init(configuratorSettingsClone);
44482
+ this._initConfigurator(configuratorSettingsClone, object.metadata.itemIdentifier, !!configuratorExternalSourceId, object.metadata.itemId);
44483
+ // const furnitureData: ConfigurationResultObject = new ConfigurationResultObject();
44484
+ // furnitureData.sku = object.metadata.itemIdentifier;
44485
+ // furnitureData.instanceId = object.metadata.itemId;
44486
+ // this._configuringService.isConfiguring = true;
44487
+ // await this._configuringService.configure(furnitureData);
44813
44488
  this._loadFurnitureService.currentActiveService.configurationDirty = true;
44814
44489
  this.loadConfigurator = true;
44815
44490
  }
44816
44491
  }
44817
- _initConfigurator(settings, sku, instanceId) {
44818
- this.configuratorSettings = settings;
44492
+ _initConfigurator(settings, sku, external, instanceId) {
44493
+ this.configuratorSettings = this._prepareSettings(settings, external);
44819
44494
  this.configuratorSku = sku;
44820
44495
  this.configuratorInstanceId = instanceId;
44821
44496
  }
44497
+ _prepareSettings(settings, external = false) {
44498
+ if (external) {
44499
+ // no pre-defined stuff for external sources
44500
+ settings.password = undefined;
44501
+ settings.dataSessionId = undefined;
44502
+ settings.sessionId = undefined;
44503
+ settings.getAccessTokenFunction = undefined;
44504
+ }
44505
+ return settings;
44506
+ }
44822
44507
  _resetConfigurator() {
44823
44508
  this.configuratorSettings = undefined;
44824
44509
  this.configuratorSku = undefined;
@@ -44858,6 +44543,7 @@ class ThreedselectorComponent {
44858
44543
  return configuratorSettingsClone;
44859
44544
  }
44860
44545
  _closeConfigurator() {
44546
+ // this._configuringService.isConfiguring = false;
44861
44547
  this.loadConfigurator = false;
44862
44548
  }
44863
44549
  _clearItems() {
@@ -45302,6 +44988,7 @@ class ThreedselectorComponent {
45302
44988
  }
45303
44989
  this._prepareAddButtons();
45304
44990
  }
44991
+ // this.handleBuildResult(result);
45305
44992
  }
45306
44993
  _resetElementPosition() {
45307
44994
  if (this.selectedElement && !this.standAlone) {
@@ -45511,6 +45198,38 @@ class ThreedselectorComponent {
45511
45198
  }
45512
45199
  }*/
45513
45200
  }
45201
+ _addUploadedItem(data) {
45202
+ if (!data) {
45203
+ return;
45204
+ }
45205
+ const result = new ConfigurationResultObject();
45206
+ result.object = data.object;
45207
+ result.placement = data.placement;
45208
+ result.resultType = ResultType.Loaded;
45209
+ const type = itemTypeFromPlacement(result.placement);
45210
+ result.position = isFloorType(type) ? this._bluePrintService.getRoomCenter() : new Vector3();
45211
+ result.originalMetadata = {
45212
+ itemName: data.object.name,
45213
+ itemType: type,
45214
+ configurable: false,
45215
+ ione: false,
45216
+ // rotation?: number | Euler;
45217
+ // scale?: Vector3;
45218
+ // centerPivot?: boolean;
45219
+ thirdPartyModel: true,
45220
+ // canElevate?: boolean;
45221
+ // modelUrl?: string;
45222
+ // scalable?: boolean;
45223
+ // elevation?: number;
45224
+ // elevationFixed?: boolean;
45225
+ // elevationAdjustable?: boolean;
45226
+ canScaleX: true,
45227
+ canScaleY: true,
45228
+ canScaleZ: true,
45229
+ colorable: true
45230
+ };
45231
+ this.handleBuildResult(result);
45232
+ }
45514
45233
  async _handleLoadIOneFurnitureIntoSceneBySKU(sku, settings, position) {
45515
45234
  const toast = new Toast();
45516
45235
  toast.message = 'MODEL_LOADING';
@@ -45521,6 +45240,32 @@ class ThreedselectorComponent {
45521
45240
  if (article.placement === HdecoPlacement.FloorDecoration) {
45522
45241
  this._floorService.selectedFloorArticle = article;
45523
45242
  }
45243
+ if (article.externalCatalogId && article.externalSourceKey) {
45244
+ try {
45245
+ sku = article.externalSourceKey;
45246
+ const catalogDefinition = this._connectorAdapterService.getCatalogDefinition(article.externalCatalogId);
45247
+ const externalSource = this._connectorAdapterService.getExternalSourceFromId(catalogDefinition.externalSourceId);
45248
+ const params = await this._connectorAdapterService.getPublicParams(externalSource.url, parseInt(externalSource.schema));
45249
+ const homeDecoSettings = Object.assign(JSON.parse(params.homeDecoSettings ? params.homeDecoSettings : params.catalogSettings), new HomedecoratorSettings());
45250
+ settings = {
45251
+ name: catalogDefinition.name,
45252
+ settings: homeDecoSettings,
45253
+ externalSourceId: externalSource.sourceId,
45254
+ catalogDefinition: catalogDefinition,
45255
+ schema: externalSource.schema,
45256
+ mainUrl: this._settingsService.settings.url,
45257
+ mainSchema: this._settingsService.settings.schema,
45258
+ mainVersion: this._settingsService.settings.version
45259
+ };
45260
+ settings.settings.password = '';
45261
+ settings.settings.username = 'external';
45262
+ }
45263
+ catch (e) {
45264
+ console.error(e);
45265
+ this._messageBus.emit(MessageType.UndefinedErrorOccured);
45266
+ return;
45267
+ }
45268
+ }
45524
45269
  const draggedData = {
45525
45270
  name: sku,
45526
45271
  constructFn: async (pos) => this.loadFurnitureFromSku(pos, sku, settings),
@@ -45547,7 +45292,8 @@ class ThreedselectorComponent {
45547
45292
  async _loadIOneFurnitureFromOriginal(md, pos, rot) {
45548
45293
  const newMetaData = { ...md };
45549
45294
  newMetaData.rotation = new Euler().copy(rot);
45550
- return this._handleLoadAndBuildFurniture(newMetaData, true, false, false, false, false);
45295
+ await this._handleLoadAndBuildFurniture(newMetaData, true, false, false, false, false);
45296
+ return this.handleBuildResult(this._configuringService.buildResult);
45551
45297
  }
45552
45298
  _loadIOneFurnitureFromSku(pos, sku, settings, standAlone = false) {
45553
45299
  const md = {
@@ -45672,6 +45418,7 @@ class ThreedselectorComponent {
45672
45418
  this._externalSourceData = furnitureData.externalSettings; // set it so we can restore them with the new config.
45673
45419
  }
45674
45420
  this._configuringService.scene = this._sceneService.scene;
45421
+ // await this._configuringService.init(configuratorSettingsClone);
45675
45422
  const data = new ConfigurationResultObject();
45676
45423
  data.sku = furnitureData.itemIdentifier;
45677
45424
  data.articleName = furnitureData.itemName;
@@ -45691,6 +45438,7 @@ class ThreedselectorComponent {
45691
45438
  data.rotation = furnitureData.rotation;
45692
45439
  data.originalMetadata = furnitureData;
45693
45440
  await this._configuringService.configure(data, shouldCopyInstance, looseOriginalConfiguration, standAlone, fromScratch, fromPreset, loadFromProject);
45441
+ // this._configuringService.isConfiguring = false;
45694
45442
  this.loadConfigurator = true;
45695
45443
  }
45696
45444
  _answerSelected(result) {
@@ -46415,7 +46163,7 @@ class DrawDialogComponent {
46415
46163
  this.customerInputLenght = this.inputLength.nativeElement.value;
46416
46164
  }
46417
46165
  handleMouseDown(event) {
46418
- if (this.draftingMode === 'movement') {
46166
+ if (event.button === 2) { // right mouse button -> drag
46419
46167
  this.isDragging = true;
46420
46168
  this.dragStart.x = this.getEventLocation(event).x / this.cameraZoom - this.cameraOffset.x;
46421
46169
  this.dragStart.y = this.getEventLocation(event).y / this.cameraZoom - this.cameraOffset.y;
@@ -46428,11 +46176,9 @@ class DrawDialogComponent {
46428
46176
  }
46429
46177
  }
46430
46178
  handleMouseMove(event) {
46431
- if (this.draftingMode === 'movement') {
46432
- if (this.isDragging) {
46433
- this.cameraOffset.x = this.getEventLocation(event).x / this.cameraZoom - this.dragStart.x;
46434
- this.cameraOffset.y = this.getEventLocation(event).y / this.cameraZoom - this.dragStart.y;
46435
- }
46179
+ if (this.isDragging) {
46180
+ this.cameraOffset.x = this.getEventLocation(event).x / this.cameraZoom - this.dragStart.x;
46181
+ this.cameraOffset.y = this.getEventLocation(event).y / this.cameraZoom - this.dragStart.y;
46436
46182
  }
46437
46183
  }
46438
46184
  handleMouseUp(event) {
@@ -46442,22 +46188,6 @@ class DrawDialogComponent {
46442
46188
  }
46443
46189
  handleMouseLeave(event) {
46444
46190
  }
46445
- clickingZoom(option) {
46446
- const zoomIn = -0.5;
46447
- const zoomOut = 0.5;
46448
- const zoomReset = 1;
46449
- if (option === 'in') {
46450
- this.cameraZoom -= zoomIn;
46451
- }
46452
- else if (option === 'out') {
46453
- this.cameraZoom -= zoomOut;
46454
- }
46455
- else if (option === 'reset') {
46456
- this.cameraZoom = zoomReset;
46457
- }
46458
- this.cameraZoom = Math.min(this.cameraZoom, this.maxZoom);
46459
- this.cameraZoom = Math.max(this.cameraZoom, this.minZoom);
46460
- }
46461
46191
  handleMouseWheel(event) {
46462
46192
  const zoomAmount = event.deltaY * this.scrollSensitivity;
46463
46193
  if (!this.isDragging) {
@@ -46468,6 +46198,9 @@ class DrawDialogComponent {
46468
46198
  this.cameraZoom = Math.max(this.cameraZoom, this.minZoom);
46469
46199
  }
46470
46200
  }
46201
+ handleContextMenu(event) {
46202
+ return false;
46203
+ }
46471
46204
  getEventLocation(e) {
46472
46205
  if (e.touches && e.touches.length === 1) {
46473
46206
  return { x: e.touches[0].clientX, y: e.touches[0].clientY };
@@ -46551,11 +46284,11 @@ class DrawDialogComponent {
46551
46284
  return new Vector2(canvasX, canvasY);
46552
46285
  }
46553
46286
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DrawDialogComponent, deps: [{ token: MAT_DIALOG_DATA }, { token: i1$2.MatDialogRef }, { token: i1$2.MatDialog }, { token: MessageBusService }], target: i0.ɵɵFactoryTarget.Component }); }
46554
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: DrawDialogComponent, isStandalone: false, selector: "rp-draw-dialog", viewQueries: [{ propertyName: "canvasElement", first: true, predicate: ["drawCanvas"], descendants: true, read: ElementRef, static: true }, { propertyName: "inputLength", first: true, predicate: ["inputLength"], descendants: true }, { propertyName: "hiddenImage", first: true, predicate: ["hiddenImage"], descendants: true }], ngImport: i0, template: "<div class=\"model-header\">\r\n <h1 mat-dialog-title>{{ 'OPEN_A_DIAGRAM' | localize }}</h1>\r\n <button (click)=\"cancelAndReset()\" class=\"close-button\">\r\n <mat-icon class=\"homedecorator-material-icons\">close</mat-icon>\r\n </button>\r\n</div>\r\n<div class=\"top-bar-container\">\r\n @if (draftingMode === 'movement') {\r\n <div class=\"zoom-button-containers\">\r\n <button (click)=\"clickingZoom('in')\">\r\n <mat-icon class=\"homedecorator-material-icons\">zoom_in</mat-icon>\r\n </button>\r\n <button (click)=\"clickingZoom('reset')\">\r\n <mat-icon class=\"homedecorator-material-icons\">all_out</mat-icon>\r\n </button>\r\n <button (click)=\"clickingZoom('out')\">\r\n <mat-icon class=\"homedecorator-material-icons\">zoom_out</mat-icon>\r\n </button>\r\n </div>\r\n }\r\n</div>\r\n<div class=\"main-button-container\">\r\n <mat-button-toggle-group\r\n class=\"mode-toggle\"\r\n (change)=\"setModus($event.value)\"\r\n [value]=\"draftingMode\">\r\n <mat-button-toggle [value]=\"'movement'\" [matTooltip]=\"'Zoom / verplaats modus'\">\r\n <mat-icon svgIcon=\"hand-pointer\"></mat-icon>\r\n </mat-button-toggle>\r\n <mat-button-toggle [value]=\"'scaling'\" [matTooltip]=\"'Maak referentie meting'\">\r\n <mat-icon svgIcon=\"pen-ruler\"></mat-icon>\r\n </mat-button-toggle>\r\n </mat-button-toggle-group>\r\n</div>\r\n\r\n<div class=\"canvas-wrapper\">\r\n <canvas\r\n #drawCanvas\r\n (mousedown)=\"handleMouseDown($event)\"\r\n (mousemove)=\"handleMouseMove($event)\"\r\n (mouseup)=\"handleMouseUp($event)\"\r\n (mouseleave)=\"handleMouseLeave($event)\"\r\n (wheel)=\"handleMouseWheel($event)\"\r\n ></canvas>\r\n</div>\r\n\r\n<div class=\"modal-footer\">\r\n @if (draftingMode === 'scaling') {\r\n <div class=\"reference-input-container\">\r\n <div class=\"input-button-container\">\r\n <input\r\n (change)=\"updateUserValue()\"\r\n [value]=\"customerInputLenght\"\r\n #inputLength\r\n type=\"number\"\r\n placeholder=\"{{ 'PDF_REFERENCE_PLACEHOLDER' | localize}}\"\r\n [attr.disabled]=\"this.measurePoints.length === 0 ? '' : null\"\r\n >\r\n <button (click)=\"resetPoints()\" title=\"Reset referentie meting\">\r\n <mat-icon class=\"homedecorator-material-icons\">refresh</mat-icon>\r\n </button>\r\n </div>\r\n <p class=\"helper-text\">{{ 'PDF_REFERENCE_HELPER' | localize }}</p>\r\n </div>\r\n }\r\n\r\n <div class=\"save-cancel-button-container\">\r\n @if (draftingMode === 'scaling') {\r\n <button (click)=\"submitLength()\" title=\"Opslaan\">\r\n <mat-icon class=\"homedecorator-material-icons\">check_circle</mat-icon>\r\n <span>{{'NEXT' | localize}}</span>\r\n </button>\r\n }\r\n </div>\r\n </div>\r\n\r\n\r\n\r\n <img #hiddenImage src=\"\" style=\"display: none;\">\r\n", styles: ["canvas{position:relative}button{cursor:pointer;color:#fff;background:#da9803;border:1px solid #da9803;border-radius:3px;box-sizing:border-box;padding:5px;display:flex;align-items:center}button:hover{background:#da9803;color:#fff}.main-button-container{display:flex;justify-content:center;margin-bottom:15px}.main-button-container .mat-button-toggle-checked{background:#da9803;color:#fff}.model-header{display:flex;justify-content:space-between;align-items:start}.model-header .close-button{background:none;color:#333;border:none;padding:0}.modal-footer{display:flex;justify-content:space-between;align-items:flex-end;margin-top:30px}.reference-input-container .input-button-container{display:flex;align-items:center}.reference-input-container .input-button-container input{min-width:285px;border:1px solid #f7f7f9;border-radius:3px;height:35px;line-height:35px;box-sizing:border-box;padding:10px}.reference-input-container .input-button-container input:disabled{background:#f7f7f9;cursor:default}.reference-input-container .input-button-container button{border:none;display:inline-block}.reference-input-container .helper-text{font-size:13px;font-style:italic;margin:0;padding:0;display:block}.zoom-button-containers{display:flex;justify-items:center;justify-content:right}.zoom-button-containers button{margin:0 5px}.save-cancel-button-container{display:flex;justify-content:center;justify-items:center}.save-cancel-button-container button{margin:3px 10px;padding:8px 15px}.save-cancel-button-container button .homedecorator-material-icons{font-size:18px}.save-cancel-button-container button span{line-height:18px;font-size:15px}.canvas-wrapper{overflow:hidden;max-height:60vh;max-width:80vw}\n"], dependencies: [{ kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i4$1.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: i1$2.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i10.MatButtonToggleGroup, selector: "mat-button-toggle-group", inputs: ["appearance", "name", "vertical", "value", "multiple", "disabled", "disabledInteractive", "hideSingleSelectionIndicator", "hideMultipleSelectionIndicator"], outputs: ["valueChange", "change"], exportAs: ["matButtonToggleGroup"] }, { kind: "component", type: i10.MatButtonToggle, selector: "mat-button-toggle", inputs: ["aria-label", "aria-labelledby", "id", "name", "value", "tabIndex", "disableRipple", "appearance", "checked", "disabled", "disabledInteractive"], outputs: ["change"], exportAs: ["matButtonToggle"] }, { kind: "pipe", type: LocalizePipe, name: "localize" }] }); }
46287
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: DrawDialogComponent, isStandalone: false, selector: "rp-draw-dialog", viewQueries: [{ propertyName: "canvasElement", first: true, predicate: ["drawCanvas"], descendants: true, read: ElementRef, static: true }, { propertyName: "inputLength", first: true, predicate: ["inputLength"], descendants: true }, { propertyName: "hiddenImage", first: true, predicate: ["hiddenImage"], descendants: true }], ngImport: i0, template: "<div class=\"model-header\">\r\n <h1 mat-dialog-title>{{ 'OPEN_A_DIAGRAM' | localize }}</h1>\r\n <button (click)=\"cancelAndReset()\" class=\"close-button\">\r\n <mat-icon class=\"homedecorator-material-icons\">close</mat-icon>\r\n </button>\r\n</div>\r\n<div class=\"canvas-wrapper\">\r\n <canvas\r\n #drawCanvas\r\n (mousedown)=\"handleMouseDown($event)\"\r\n (mousemove)=\"handleMouseMove($event)\"\r\n (mouseup)=\"handleMouseUp($event)\"\r\n (mouseleave)=\"handleMouseLeave($event)\"\r\n (wheel)=\"handleMouseWheel($event)\"\r\n (contextmenu)=\"handleContextMenu($event)\"\r\n ></canvas>\r\n</div>\r\n\r\n<div class=\"modal-footer\">\r\n @if (draftingMode === 'scaling') {\r\n <div class=\"reference-input-container\">\r\n <div class=\"input-button-container\">\r\n <input\r\n (change)=\"updateUserValue()\"\r\n [value]=\"customerInputLenght\"\r\n #inputLength\r\n type=\"number\"\r\n placeholder=\"{{ 'PDF_REFERENCE_PLACEHOLDER' | localize}}\"\r\n [attr.disabled]=\"this.measurePoints.length === 0 ? '' : null\"\r\n >\r\n <button (click)=\"resetPoints()\" title=\"Reset referentie meting\">\r\n <mat-icon class=\"homedecorator-material-icons\">refresh</mat-icon>\r\n </button>\r\n </div>\r\n <p class=\"helper-text\">{{ 'PDF_REFERENCE_HELPER' | localize }}</p>\r\n </div>\r\n }\r\n\r\n <div class=\"save-cancel-button-container\">\r\n @if (draftingMode === 'scaling') {\r\n <button (click)=\"submitLength()\" title=\"Opslaan\">\r\n <mat-icon class=\"homedecorator-material-icons\">check_circle</mat-icon>\r\n <span>{{'NEXT' | localize}}</span>\r\n </button>\r\n }\r\n </div>\r\n </div>\r\n\r\n\r\n\r\n <img #hiddenImage src=\"\" style=\"display: none;\">\r\n", styles: ["canvas{position:relative}button{cursor:pointer;color:#fff;background:#da9803;border:1px solid #da9803;border-radius:3px;box-sizing:border-box;padding:5px;display:flex;align-items:center}button:hover{background:#da9803;color:#fff}.main-button-container{display:flex;justify-content:center;margin-bottom:15px}.main-button-container .mat-button-toggle-checked{background:#da9803;color:#fff}.model-header{display:flex;justify-content:space-between;align-items:start}.model-header .close-button{background:none;color:#333;border:none;padding:0}.modal-footer{display:flex;justify-content:space-between;align-items:flex-end;margin-top:30px}.reference-input-container .input-button-container{display:flex;align-items:center}.reference-input-container .input-button-container input{min-width:285px;border:1px solid #f7f7f9;border-radius:3px;height:35px;line-height:35px;box-sizing:border-box;padding:10px}.reference-input-container .input-button-container input:disabled{background:#f7f7f9;cursor:default}.reference-input-container .input-button-container button{border:none;display:inline-block}.reference-input-container .helper-text{font-size:13px;font-style:italic;margin:0;padding:0;display:block}.zoom-button-containers{display:flex;justify-items:center;justify-content:right}.zoom-button-containers button{margin:0 5px}.save-cancel-button-container{display:flex;justify-content:center;justify-items:center}.save-cancel-button-container button{margin:3px 10px;padding:8px 15px}.save-cancel-button-container button .homedecorator-material-icons{font-size:18px}.save-cancel-button-container button span{line-height:18px;font-size:15px}.canvas-wrapper{overflow:hidden;max-height:60vh;max-width:80vw}\n"], dependencies: [{ kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i1$2.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "pipe", type: LocalizePipe, name: "localize" }] }); }
46555
46288
  }
46556
46289
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DrawDialogComponent, decorators: [{
46557
46290
  type: Component,
46558
- args: [{ selector: 'rp-draw-dialog', standalone: false, template: "<div class=\"model-header\">\r\n <h1 mat-dialog-title>{{ 'OPEN_A_DIAGRAM' | localize }}</h1>\r\n <button (click)=\"cancelAndReset()\" class=\"close-button\">\r\n <mat-icon class=\"homedecorator-material-icons\">close</mat-icon>\r\n </button>\r\n</div>\r\n<div class=\"top-bar-container\">\r\n @if (draftingMode === 'movement') {\r\n <div class=\"zoom-button-containers\">\r\n <button (click)=\"clickingZoom('in')\">\r\n <mat-icon class=\"homedecorator-material-icons\">zoom_in</mat-icon>\r\n </button>\r\n <button (click)=\"clickingZoom('reset')\">\r\n <mat-icon class=\"homedecorator-material-icons\">all_out</mat-icon>\r\n </button>\r\n <button (click)=\"clickingZoom('out')\">\r\n <mat-icon class=\"homedecorator-material-icons\">zoom_out</mat-icon>\r\n </button>\r\n </div>\r\n }\r\n</div>\r\n<div class=\"main-button-container\">\r\n <mat-button-toggle-group\r\n class=\"mode-toggle\"\r\n (change)=\"setModus($event.value)\"\r\n [value]=\"draftingMode\">\r\n <mat-button-toggle [value]=\"'movement'\" [matTooltip]=\"'Zoom / verplaats modus'\">\r\n <mat-icon svgIcon=\"hand-pointer\"></mat-icon>\r\n </mat-button-toggle>\r\n <mat-button-toggle [value]=\"'scaling'\" [matTooltip]=\"'Maak referentie meting'\">\r\n <mat-icon svgIcon=\"pen-ruler\"></mat-icon>\r\n </mat-button-toggle>\r\n </mat-button-toggle-group>\r\n</div>\r\n\r\n<div class=\"canvas-wrapper\">\r\n <canvas\r\n #drawCanvas\r\n (mousedown)=\"handleMouseDown($event)\"\r\n (mousemove)=\"handleMouseMove($event)\"\r\n (mouseup)=\"handleMouseUp($event)\"\r\n (mouseleave)=\"handleMouseLeave($event)\"\r\n (wheel)=\"handleMouseWheel($event)\"\r\n ></canvas>\r\n</div>\r\n\r\n<div class=\"modal-footer\">\r\n @if (draftingMode === 'scaling') {\r\n <div class=\"reference-input-container\">\r\n <div class=\"input-button-container\">\r\n <input\r\n (change)=\"updateUserValue()\"\r\n [value]=\"customerInputLenght\"\r\n #inputLength\r\n type=\"number\"\r\n placeholder=\"{{ 'PDF_REFERENCE_PLACEHOLDER' | localize}}\"\r\n [attr.disabled]=\"this.measurePoints.length === 0 ? '' : null\"\r\n >\r\n <button (click)=\"resetPoints()\" title=\"Reset referentie meting\">\r\n <mat-icon class=\"homedecorator-material-icons\">refresh</mat-icon>\r\n </button>\r\n </div>\r\n <p class=\"helper-text\">{{ 'PDF_REFERENCE_HELPER' | localize }}</p>\r\n </div>\r\n }\r\n\r\n <div class=\"save-cancel-button-container\">\r\n @if (draftingMode === 'scaling') {\r\n <button (click)=\"submitLength()\" title=\"Opslaan\">\r\n <mat-icon class=\"homedecorator-material-icons\">check_circle</mat-icon>\r\n <span>{{'NEXT' | localize}}</span>\r\n </button>\r\n }\r\n </div>\r\n </div>\r\n\r\n\r\n\r\n <img #hiddenImage src=\"\" style=\"display: none;\">\r\n", styles: ["canvas{position:relative}button{cursor:pointer;color:#fff;background:#da9803;border:1px solid #da9803;border-radius:3px;box-sizing:border-box;padding:5px;display:flex;align-items:center}button:hover{background:#da9803;color:#fff}.main-button-container{display:flex;justify-content:center;margin-bottom:15px}.main-button-container .mat-button-toggle-checked{background:#da9803;color:#fff}.model-header{display:flex;justify-content:space-between;align-items:start}.model-header .close-button{background:none;color:#333;border:none;padding:0}.modal-footer{display:flex;justify-content:space-between;align-items:flex-end;margin-top:30px}.reference-input-container .input-button-container{display:flex;align-items:center}.reference-input-container .input-button-container input{min-width:285px;border:1px solid #f7f7f9;border-radius:3px;height:35px;line-height:35px;box-sizing:border-box;padding:10px}.reference-input-container .input-button-container input:disabled{background:#f7f7f9;cursor:default}.reference-input-container .input-button-container button{border:none;display:inline-block}.reference-input-container .helper-text{font-size:13px;font-style:italic;margin:0;padding:0;display:block}.zoom-button-containers{display:flex;justify-items:center;justify-content:right}.zoom-button-containers button{margin:0 5px}.save-cancel-button-container{display:flex;justify-content:center;justify-items:center}.save-cancel-button-container button{margin:3px 10px;padding:8px 15px}.save-cancel-button-container button .homedecorator-material-icons{font-size:18px}.save-cancel-button-container button span{line-height:18px;font-size:15px}.canvas-wrapper{overflow:hidden;max-height:60vh;max-width:80vw}\n"] }]
46291
+ args: [{ selector: 'rp-draw-dialog', standalone: false, template: "<div class=\"model-header\">\r\n <h1 mat-dialog-title>{{ 'OPEN_A_DIAGRAM' | localize }}</h1>\r\n <button (click)=\"cancelAndReset()\" class=\"close-button\">\r\n <mat-icon class=\"homedecorator-material-icons\">close</mat-icon>\r\n </button>\r\n</div>\r\n<div class=\"canvas-wrapper\">\r\n <canvas\r\n #drawCanvas\r\n (mousedown)=\"handleMouseDown($event)\"\r\n (mousemove)=\"handleMouseMove($event)\"\r\n (mouseup)=\"handleMouseUp($event)\"\r\n (mouseleave)=\"handleMouseLeave($event)\"\r\n (wheel)=\"handleMouseWheel($event)\"\r\n (contextmenu)=\"handleContextMenu($event)\"\r\n ></canvas>\r\n</div>\r\n\r\n<div class=\"modal-footer\">\r\n @if (draftingMode === 'scaling') {\r\n <div class=\"reference-input-container\">\r\n <div class=\"input-button-container\">\r\n <input\r\n (change)=\"updateUserValue()\"\r\n [value]=\"customerInputLenght\"\r\n #inputLength\r\n type=\"number\"\r\n placeholder=\"{{ 'PDF_REFERENCE_PLACEHOLDER' | localize}}\"\r\n [attr.disabled]=\"this.measurePoints.length === 0 ? '' : null\"\r\n >\r\n <button (click)=\"resetPoints()\" title=\"Reset referentie meting\">\r\n <mat-icon class=\"homedecorator-material-icons\">refresh</mat-icon>\r\n </button>\r\n </div>\r\n <p class=\"helper-text\">{{ 'PDF_REFERENCE_HELPER' | localize }}</p>\r\n </div>\r\n }\r\n\r\n <div class=\"save-cancel-button-container\">\r\n @if (draftingMode === 'scaling') {\r\n <button (click)=\"submitLength()\" title=\"Opslaan\">\r\n <mat-icon class=\"homedecorator-material-icons\">check_circle</mat-icon>\r\n <span>{{'NEXT' | localize}}</span>\r\n </button>\r\n }\r\n </div>\r\n </div>\r\n\r\n\r\n\r\n <img #hiddenImage src=\"\" style=\"display: none;\">\r\n", styles: ["canvas{position:relative}button{cursor:pointer;color:#fff;background:#da9803;border:1px solid #da9803;border-radius:3px;box-sizing:border-box;padding:5px;display:flex;align-items:center}button:hover{background:#da9803;color:#fff}.main-button-container{display:flex;justify-content:center;margin-bottom:15px}.main-button-container .mat-button-toggle-checked{background:#da9803;color:#fff}.model-header{display:flex;justify-content:space-between;align-items:start}.model-header .close-button{background:none;color:#333;border:none;padding:0}.modal-footer{display:flex;justify-content:space-between;align-items:flex-end;margin-top:30px}.reference-input-container .input-button-container{display:flex;align-items:center}.reference-input-container .input-button-container input{min-width:285px;border:1px solid #f7f7f9;border-radius:3px;height:35px;line-height:35px;box-sizing:border-box;padding:10px}.reference-input-container .input-button-container input:disabled{background:#f7f7f9;cursor:default}.reference-input-container .input-button-container button{border:none;display:inline-block}.reference-input-container .helper-text{font-size:13px;font-style:italic;margin:0;padding:0;display:block}.zoom-button-containers{display:flex;justify-items:center;justify-content:right}.zoom-button-containers button{margin:0 5px}.save-cancel-button-container{display:flex;justify-content:center;justify-items:center}.save-cancel-button-container button{margin:3px 10px;padding:8px 15px}.save-cancel-button-container button .homedecorator-material-icons{font-size:18px}.save-cancel-button-container button span{line-height:18px;font-size:15px}.canvas-wrapper{overflow:hidden;max-height:60vh;max-width:80vw}\n"] }]
46559
46292
  }], ctorParameters: () => [{ type: undefined, decorators: [{
46560
46293
  type: Inject,
46561
46294
  args: [MAT_DIALOG_DATA]
@@ -48160,7 +47893,7 @@ class ToolbarComponent {
48160
47893
  this.leftSidebar.close();
48161
47894
  }
48162
47895
  }
48163
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: ToolbarComponent, deps: [{ token: AppStateService }, { token: PresetsService }, { token: MessageBusService }, { token: HomedecoratorSettingsService }, { token: LocalStorageService }, { token: HomedecoratorIconCacheService }, { token: ScreenSizeAnalysisService }, { token: i1$2.MatDialog }, { token: ToastService }, { token: HomedecoratorAppService }, { token: PermanentStoreService }, { token: UtilsService }, { token: ItemService }, { token: FloorService }, { token: AnimationService }, { token: DevelopmentService }, { token: NewRenderService }, { token: ThirdPartyModelService }, { token: LightPresetsService }, { token: HomedecoratorConnectorAdapterService }, { token: ConnectionHeathService }, { token: HomedecoratorAppEventService }], target: i0.ɵɵFactoryTarget.Component }); }
47896
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: ToolbarComponent, deps: [{ token: AppStateService }, { token: PresetsService }, { token: MessageBusService }, { token: HomedecoratorSettingsService }, { token: LocalStorageService }, { token: HomedecoratorIconCacheService }, { token: ScreenSizeAnalysisService }, { token: i1$2.MatDialog }, { token: ToastService }, { token: HomedecoratorAppService }, { token: PermanentStoreService }, { token: UtilsService }, { token: ItemService }, { token: FloorService }, { token: AnimationService }, { token: DevelopmentService }, { token: RenderService }, { token: ThirdPartyModelService }, { token: LightPresetsService }, { token: HomedecoratorConnectorAdapterService }, { token: ConnectionHeathService }, { token: HomedecoratorAppEventService }], target: i0.ɵɵFactoryTarget.Component }); }
48164
47897
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: ToolbarComponent, isStandalone: false, selector: "rp-toolbar", outputs: { externalSave: "externalSave" }, host: { listeners: { "document:keydown": "handleKeyDown($event)" } }, viewQueries: [{ propertyName: "leftSidebar", first: true, predicate: ["leftSidebar"], descendants: true, static: true }], ngImport: i0, template: `
48165
47898
  <!--
48166
47899
  <div class="layer layer&#45;&#45;toolbar">
@@ -48690,7 +48423,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
48690
48423
  ])
48691
48424
  ] /*,
48692
48425
  changeDetection: ChangeDetectionStrategy.OnPush*/, standalone: false, styles: [":host{display:flex;flex-direction:column;position:absolute;top:0;z-index:100;height:100%;width:100%;pointer-events:none}:host h2{font-weight:600}:host h3{font-weight:600}:host .mat-toolbar.mat-primary{box-shadow:none;padding:0;background:transparent;height:40px;justify-content:space-between}:host .mat-toolbar .mat-icon{height:20px;width:20px;font-size:20px;line-height:20px}:host .hd-toolbar-spacer{display:flex;flex-basis:100%}:host .toast-wrapper{height:auto;position:absolute;top:0;left:50%;-webkit-user-select:none;user-select:none;pointer-events:none;background:#74b77f;padding:30px;border-radius:0 0 10px 10px;min-width:150px;max-width:90%;color:#fff;text-align:center;transform:translate(-50%,-100%)}:host .toast-wrapper.warning{background:#f17300}:host .toast-wrapper.error{background:#cc2936}:host ::ng-deep .drawer__header{display:flex;align-items:center;min-height:40px;margin-bottom:16px}:host ::ng-deep .drawer__header h2{margin:0 auto 0 0;font-weight:600}:host ::ng-deep .mat-headline-6{font-weight:600}:host ::ng-deep .mat-subtitle-1{font-weight:600}:host ::ng-deep mat-tab-header,:host ::ng-deep .FileDrop{margin-bottom:16px}:host ::ng-deep .tab--skin ::ng-deep .mat-tab-label{height:52px;min-width:auto}:host ::ng-deep .drawer p{white-space:pre-wrap}:host ::ng-deep .mat-divider{margin:16px 0 24px}:host ::ng-deep .mat-drawer-backdrop{display:none}.storage-error{min-width:30px;height:30px;display:flex;align-items:center;align-self:center;border-radius:50%;justify-content:center;background:#fff;color:#c00;font-size:25px;font-weight:700}.layer--toolbar{display:flex;flex-direction:column}.toolbar{display:flex;z-index:101;flex-wrap:nowrap}.toolbar .menu-icon{min-width:50px;display:flex;justify-content:center;margin-left:-16px}.toolbar .left-toolbar,.toolbar .right-toolbar{display:flex;align-items:center;background:#da9803;border-radius:0 0 10px;padding:0 20px 0 10px;box-shadow:0 3px 6px #00000029,0 3px 6px #0000003b;height:100%;gap:12px}.toolbar .right-toolbar{border-radius:0 0 0 10px;padding:0 5px 0 10px}.toolbar .toolbar-icon-list{display:flex;align-items:center;justify-content:center}.toolbar .toolbar-icon-sub{display:flex;align-items:center;justify-content:center;padding:0 10px;gap:5px;border-right:1px solid rgba(255,255,255,.3803921569)}.toolbar .toolbar-icon-sub:last-child{border-right:none}.toolbar .toolbar-icon-sub:first-child{border-left:1px solid rgba(255,255,255,.3803921569);margin-left:10px}.toolbar .toolbar-icon{height:30px;width:30px;display:flex;align-items:center;justify-content:center;cursor:pointer}.toolbar .toolbar-icon co-icon ::ng-deep{width:20px;height:20px}.toolbar .toolbar-icon co-icon ::ng-deep svg,.toolbar .toolbar-icon co-icon ::ng-deep path{fill:#fff}.toolbar .toolbar-icon co-icon.loading-green ::ng-deep svg,.toolbar .toolbar-icon co-icon.loading-green ::ng-deep path{fill:#74b77f}.toolbar .toolbar-icon co-icon.loading-orange ::ng-deep svg,.toolbar .toolbar-icon co-icon.loading-orange ::ng-deep path{fill:#f17300}.toolbar .toolbar-icon co-icon.loading-yellow ::ng-deep svg,.toolbar .toolbar-icon co-icon.loading-yellow ::ng-deep path{fill:#cc2936}.toolbar .toolbar-icon co-icon.loading-red ::ng-deep svg,.toolbar .toolbar-icon co-icon.loading-red ::ng-deep path{fill:#cc2936}.toolbar .toolbar-icon.search co-icon{height:30px;width:30px}.toolbar .toolbar-icon.disabled{cursor:default}.toolbar .toolbar-icon.disabled co-icon ::ng-deep svg{fill:#00000042}.toolbar-logo{height:20px}.secondary-logo{margin-left:20px}.toolbar__nav{display:flex;flex-direction:row;padding-top:0}.toolbar__nav .mat-mdc-list-item{color:#fff;height:40px}.toolbar-row{flex:auto;display:flex;flex-direction:column;padding:0;pointer-events:none;position:relative;align-items:baseline;height:100%}::ng-deep mat-toolbar-row .toolbar--secondary{width:50px;padding:15px 0;flex-direction:column;background:#17253391;height:100%;gap:5px}::ng-deep mat-toolbar-row .toolbar--secondary button ::ng-deep{width:30px;height:30px;line-height:30px;color:#fff;display:flex;justify-content:center}::ng-deep mat-toolbar-row .toolbar--secondary .add-to-cart-button button ::ng-deep{color:#da9803}.toolbar--secondary .drawer{flex:auto;pointer-events:none;background:transparent}.wip-card{margin-left:5px;padding:0 10px;color:#fff;background-color:#7a828a}.wip-card .mat-mdc-card-content{font-size:12px}.drawer-container{position:static;box-shadow:0 1px 3px #0000001f,0 1px 2px #0000003d}.drawer{width:420px;padding:16px;display:flex;flex-direction:column;left:50px}::ng-deep rp-category-library .mat-mdc-list-item ::ng-deep{border-color:#747c84}::ng-deep rp-category-library .mdc-list-item__primary-text{color:#000}::ng-deep rp-category-library .mdc-list-item:hover .mdc-list-item__primary-text{color:#000}.toolbar,.toolbar--secondary>*,.drawer-container>*,.drawer>*{pointer-events:all}.drawer__button{min-width:initial;padding:0;border:none;position:absolute;top:0;right:0;border-radius:50%}.blinker{animation:blinker 1s linear infinite}.badge-tooltip{position:relative}.badge-tooltip .mat-badge{position:absolute;margin:0;display:flex;align-items:center;justify-content:center;right:-2px;bottom:13px}.badge-tooltip .mat-badge .mat-badge-content{background-color:transparent;color:#b71c1c;border:1px solid #b71c1c;animation:bounce 2s ease-out;animation-iteration-count:infinite;right:initial;left:initial;position:relative;height:12px;width:12px;line-height:12px;font-size:10px;bottom:initial}::ng-deep .tooltip-red{background:#b71c1c}@keyframes bounce{0%{transform:scale(1) translateY(0)}10%{transform:scale(1.1,.9) translateY(0)}30%{transform:scale(.9,1.1) translateY(-20px)}50%{transform:scale(1.05,.95) translateY(0)}57%{transform:scale(1) translateY(-7px)}64%{transform:scale(1) translateY(0)}to{transform:scale(1) translateY(0)}}@keyframes blinker{50%{opacity:0}}::ng-deep .mat-mdc-menu-panel{width:256px!important}::ng-deep .mat-mdc-menu-panel .mat-mdc-menu-content{display:flex;flex-direction:column;padding-left:10px;padding-right:10px}::ng-deep mat-drawer-content.mat-drawer-content{display:flex;height:100%;flex-direction:column}\n"] }]
48693
- }], ctorParameters: () => [{ type: AppStateService }, { type: PresetsService }, { type: MessageBusService }, { type: HomedecoratorSettingsService }, { type: LocalStorageService }, { type: HomedecoratorIconCacheService }, { type: ScreenSizeAnalysisService }, { type: i1$2.MatDialog }, { type: ToastService }, { type: HomedecoratorAppService }, { type: PermanentStoreService }, { type: UtilsService }, { type: ItemService }, { type: FloorService }, { type: AnimationService }, { type: DevelopmentService }, { type: NewRenderService }, { type: ThirdPartyModelService }, { type: LightPresetsService }, { type: HomedecoratorConnectorAdapterService }, { type: ConnectionHeathService }, { type: HomedecoratorAppEventService }], propDecorators: { externalSave: [{
48426
+ }], ctorParameters: () => [{ type: AppStateService }, { type: PresetsService }, { type: MessageBusService }, { type: HomedecoratorSettingsService }, { type: LocalStorageService }, { type: HomedecoratorIconCacheService }, { type: ScreenSizeAnalysisService }, { type: i1$2.MatDialog }, { type: ToastService }, { type: HomedecoratorAppService }, { type: PermanentStoreService }, { type: UtilsService }, { type: ItemService }, { type: FloorService }, { type: AnimationService }, { type: DevelopmentService }, { type: RenderService }, { type: ThirdPartyModelService }, { type: LightPresetsService }, { type: HomedecoratorConnectorAdapterService }, { type: ConnectionHeathService }, { type: HomedecoratorAppEventService }], propDecorators: { externalSave: [{
48694
48427
  type: Output
48695
48428
  }], leftSidebar: [{
48696
48429
  type: ViewChild,
@@ -48871,28 +48604,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
48871
48604
  args: ['fileUpload']
48872
48605
  }] } });
48873
48606
 
48874
- // A pipe for appending strings to other strings in view templates.
48875
- class AppendPipe {
48876
- transform(value, append) {
48877
- if (!value) {
48878
- return '';
48879
- }
48880
- if (!append) {
48881
- return value;
48882
- }
48883
- return value + append;
48884
- }
48885
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AppendPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
48886
- static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.3.16", ngImport: i0, type: AppendPipe, isStandalone: false, name: "append" }); }
48887
- }
48888
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AppendPipe, decorators: [{
48889
- type: Pipe,
48890
- args: [{
48891
- name: 'append',
48892
- standalone: false
48893
- }]
48894
- }] });
48895
-
48896
48607
  class ProductCatalogComponent {
48897
48608
  get shown() {
48898
48609
  return this._showCatalog;
@@ -49315,7 +49026,7 @@ class HomedecoratorComponent {
49315
49026
  return this._settings;
49316
49027
  }
49317
49028
  constructor(appService, // don't remove this, needs to be created on a high level
49318
- controllerService, appState, presetsService, screenAnalysis, _iconRegistry, _domSanitizer, _messageService, _homedecoratorService, _parentEventService, _ownEventService, _integrationService, _sceneService, _webWorkerService) {
49029
+ controllerService, appState, presetsService, screenAnalysis, _iconRegistry, _domSanitizer, _messageService, _homedecoratorService, _parentEventService, _ownEventService, _integrationService, _sceneService, _webWorkerService, _injector) {
49319
49030
  this.appService = appService;
49320
49031
  this.controllerService = controllerService;
49321
49032
  this.appState = appState;
@@ -49330,6 +49041,7 @@ class HomedecoratorComponent {
49330
49041
  this._integrationService = _integrationService;
49331
49042
  this._sceneService = _sceneService;
49332
49043
  this._webWorkerService = _webWorkerService;
49044
+ this._injector = _injector;
49333
49045
  this.generalFilterOrders = [
49334
49046
  { name: 'CATEGORY', order: 1 },
49335
49047
  { name: 'TURNOVER_GROUP', order: 2 },
@@ -49415,6 +49127,7 @@ class HomedecoratorComponent {
49415
49127
  // };
49416
49128
  this._subs = [];
49417
49129
  this._initCommunication = false;
49130
+ ServiceLocator.injector = this._injector;
49418
49131
  this._eventService = _parentEventService || _ownEventService;
49419
49132
  this._webWorkerService.initWorkers();
49420
49133
  }
@@ -49533,87 +49246,85 @@ class HomedecoratorComponent {
49533
49246
  _initConnection() {
49534
49247
  this._homedecoratorService.init(this._settings);
49535
49248
  }
49536
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: HomedecoratorComponent, deps: [{ token: HomedecoratorAppService }, { token: HomedecoratorConnectorService }, { token: AppStateService }, { token: PresetsService }, { token: ScreenSizeAnalysisService }, { token: i4.MatIconRegistry }, { token: i1$1.DomSanitizer }, { token: MessageBusService }, { token: HomedecoratorService }, { token: HomedecoratorAppEventService, optional: true, skipSelf: true }, { token: HomedecoratorAppEventService, optional: true, self: true }, { token: IntegrationService }, { token: SceneService }, { token: WebWorkerService }], target: i0.ɵɵFactoryTarget.Component }); }
49249
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: HomedecoratorComponent, deps: [{ token: HomedecoratorAppService }, { token: HomedecoratorConnectorService }, { token: AppStateService }, { token: PresetsService }, { token: ScreenSizeAnalysisService }, { token: i4.MatIconRegistry }, { token: i1$1.DomSanitizer }, { token: MessageBusService }, { token: HomedecoratorService }, { token: HomedecoratorAppEventService, optional: true, skipSelf: true }, { token: HomedecoratorAppEventService, optional: true, self: true }, { token: IntegrationService }, { token: SceneService }, { token: WebWorkerService }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Component }); }
49537
49250
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: HomedecoratorComponent, isStandalone: false, selector: "co-homedecorator", inputs: { generalFilterOrders: "generalFilterOrders", purchaseFilterOrders: "purchaseFilterOrders", logisticsFilterOrders: "logisticsFilterOrders", initCommunication: "initCommunication", projectToLoad: "projectToLoad", settings: "settings" }, host: { listeners: { "document:keyup": "keyup($event)" }, properties: { "class.co-homedecorator": "this.showClass" } }, providers: [
49538
49251
  APPLICATION_SERVICES_PROVIDERS
49539
- ], ngImport: i0, template: `
49540
- @if (loaded) {
49541
- @if (loaded) {
49542
- <div class="viewport">
49543
- <progress-bar></progress-bar>
49544
- <rp-loading-overlay>
49545
- <rp-core3d></rp-core3d>
49546
- <rp-room-planner></rp-room-planner>
49547
- <rp-furniture-manager></rp-furniture-manager>
49548
- <rp-presets [openNewRoomDialog]="!projectToLoad"></rp-presets>
49549
- <rp-threedselector></rp-threedselector>
49550
- <rp-toolbar (externalSave)="handleExternalSave()"></rp-toolbar>
49551
- <rp-product-catalog
49552
- [generalFilterOrders]="generalFilterOrders"
49553
- [purchaseFilterOrders]="purchaseFilterOrders"
49554
- [logisticsFilterOrders]="logisticsFilterOrders"
49555
- ></rp-product-catalog>
49556
- <co-lite-selector></co-lite-selector>
49557
- <rp-help></rp-help>
49558
- </rp-loading-overlay>
49559
- </div>
49560
- }
49561
- <rp-loader [show]="controllerService.shouldShowLoader"></rp-loader>
49562
- @if (shouldShowLandscapeMessage) {
49563
- <div class="mobile-portrait-overlay">
49564
- <!--
49565
- <mat-icon svgIcon="tilt-phone" class="tilt-phone-icon"></mat-icon>
49566
- -->
49567
- <div>
49568
- <!--
49569
- {{'PLEASE_USE_PHONE_IN_LANDSCAPE_MODE' | localize}}
49570
- -->
49571
- </div>
49572
- </div>
49573
- }
49574
- }
49575
- `, isInline: true, dependencies: [{ kind: "component", type: ProgressBarComponent, selector: "progress-bar" }, { kind: "component", type: LoadingOverlayComponent, selector: "rp-loading-overlay" }, { kind: "component", type: HdLoaderComponent, selector: "rp-loader", inputs: ["show"] }, { kind: "component", type: Core3dComponent, selector: "rp-core3d" }, { kind: "component", type: RoomPlannerComponent, selector: "rp-room-planner", inputs: ["isLoading"], outputs: ["done", "showPlugin", "focusControls"] }, { kind: "component", type: FurnitureManagerComponent, selector: "rp-furniture-manager" }, { kind: "component", type: PresetsComponent, selector: "rp-presets", inputs: ["openNewRoomDialog"] }, { kind: "component", type: ThreedselectorComponent, selector: "rp-threedselector", inputs: ["selections"], outputs: ["customizeButtonClicked"] }, { kind: "component", type: ToolbarComponent, selector: "rp-toolbar", outputs: ["externalSave"] }, { kind: "component", type: ProductCatalogComponent, selector: "rp-product-catalog", inputs: ["generalFilterOrders", "purchaseFilterOrders", "logisticsFilterOrders"] }, { kind: "component", type: HelpComponent, selector: "rp-help" }, { kind: "component", type: i27.LiteSelectorComponent, selector: "co-lite-selector", inputs: ["show", "showLabel", "canClose", "animateSlideout", "customDimensions"], outputs: ["showChange", "answerChosen"] }], encapsulation: i0.ViewEncapsulation.None }); }
49252
+ ], ngImport: i0, template: `
49253
+ @if (loaded) {
49254
+ @if (loaded) {
49255
+ <div class="viewport">
49256
+ <progress-bar></progress-bar>
49257
+ <rp-loading-overlay>
49258
+ <rp-core3d></rp-core3d>
49259
+ <rp-room-planner></rp-room-planner>
49260
+ <rp-furniture-manager></rp-furniture-manager>
49261
+ <rp-presets [openNewRoomDialog]="!projectToLoad"></rp-presets>
49262
+ <rp-threedselector></rp-threedselector>
49263
+ <rp-toolbar (externalSave)="handleExternalSave()"></rp-toolbar>
49264
+ <rp-product-catalog
49265
+ [generalFilterOrders]="generalFilterOrders"
49266
+ [purchaseFilterOrders]="purchaseFilterOrders"
49267
+ [logisticsFilterOrders]="logisticsFilterOrders"
49268
+ ></rp-product-catalog>
49269
+ <rp-help></rp-help>
49270
+ </rp-loading-overlay>
49271
+ </div>
49272
+ }
49273
+ <rp-loader [show]="controllerService.shouldShowLoader"></rp-loader>
49274
+ @if (shouldShowLandscapeMessage) {
49275
+ <div class="mobile-portrait-overlay">
49276
+ <!--
49277
+ <mat-icon svgIcon="tilt-phone" class="tilt-phone-icon"></mat-icon>
49278
+ -->
49279
+ <div>
49280
+ <!--
49281
+ {{'PLEASE_USE_PHONE_IN_LANDSCAPE_MODE' | localize}}
49282
+ -->
49283
+ </div>
49284
+ </div>
49285
+ }
49286
+ }
49287
+ `, isInline: true, dependencies: [{ kind: "component", type: ProgressBarComponent, selector: "progress-bar" }, { kind: "component", type: LoadingOverlayComponent, selector: "rp-loading-overlay" }, { kind: "component", type: HdLoaderComponent, selector: "rp-loader", inputs: ["show"] }, { kind: "component", type: Core3dComponent, selector: "rp-core3d" }, { kind: "component", type: RoomPlannerComponent, selector: "rp-room-planner", inputs: ["isLoading"], outputs: ["done", "showPlugin", "focusControls"] }, { kind: "component", type: FurnitureManagerComponent, selector: "rp-furniture-manager" }, { kind: "component", type: PresetsComponent, selector: "rp-presets", inputs: ["openNewRoomDialog"] }, { kind: "component", type: ThreedselectorComponent, selector: "rp-threedselector", inputs: ["selections"], outputs: ["customizeButtonClicked"] }, { kind: "component", type: ToolbarComponent, selector: "rp-toolbar", outputs: ["externalSave"] }, { kind: "component", type: ProductCatalogComponent, selector: "rp-product-catalog", inputs: ["generalFilterOrders", "purchaseFilterOrders", "logisticsFilterOrders"] }, { kind: "component", type: HelpComponent, selector: "rp-help" }], encapsulation: i0.ViewEncapsulation.None }); }
49576
49288
  }
49577
49289
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: HomedecoratorComponent, decorators: [{
49578
49290
  type: Component,
49579
49291
  args: [{
49580
49292
  selector: 'co-homedecorator',
49581
- template: `
49582
- @if (loaded) {
49583
- @if (loaded) {
49584
- <div class="viewport">
49585
- <progress-bar></progress-bar>
49586
- <rp-loading-overlay>
49587
- <rp-core3d></rp-core3d>
49588
- <rp-room-planner></rp-room-planner>
49589
- <rp-furniture-manager></rp-furniture-manager>
49590
- <rp-presets [openNewRoomDialog]="!projectToLoad"></rp-presets>
49591
- <rp-threedselector></rp-threedselector>
49592
- <rp-toolbar (externalSave)="handleExternalSave()"></rp-toolbar>
49593
- <rp-product-catalog
49594
- [generalFilterOrders]="generalFilterOrders"
49595
- [purchaseFilterOrders]="purchaseFilterOrders"
49596
- [logisticsFilterOrders]="logisticsFilterOrders"
49597
- ></rp-product-catalog>
49598
- <co-lite-selector></co-lite-selector>
49599
- <rp-help></rp-help>
49600
- </rp-loading-overlay>
49601
- </div>
49602
- }
49603
- <rp-loader [show]="controllerService.shouldShowLoader"></rp-loader>
49604
- @if (shouldShowLandscapeMessage) {
49605
- <div class="mobile-portrait-overlay">
49606
- <!--
49607
- <mat-icon svgIcon="tilt-phone" class="tilt-phone-icon"></mat-icon>
49608
- -->
49609
- <div>
49610
- <!--
49611
- {{'PLEASE_USE_PHONE_IN_LANDSCAPE_MODE' | localize}}
49612
- -->
49613
- </div>
49614
- </div>
49615
- }
49616
- }
49293
+ template: `
49294
+ @if (loaded) {
49295
+ @if (loaded) {
49296
+ <div class="viewport">
49297
+ <progress-bar></progress-bar>
49298
+ <rp-loading-overlay>
49299
+ <rp-core3d></rp-core3d>
49300
+ <rp-room-planner></rp-room-planner>
49301
+ <rp-furniture-manager></rp-furniture-manager>
49302
+ <rp-presets [openNewRoomDialog]="!projectToLoad"></rp-presets>
49303
+ <rp-threedselector></rp-threedselector>
49304
+ <rp-toolbar (externalSave)="handleExternalSave()"></rp-toolbar>
49305
+ <rp-product-catalog
49306
+ [generalFilterOrders]="generalFilterOrders"
49307
+ [purchaseFilterOrders]="purchaseFilterOrders"
49308
+ [logisticsFilterOrders]="logisticsFilterOrders"
49309
+ ></rp-product-catalog>
49310
+ <rp-help></rp-help>
49311
+ </rp-loading-overlay>
49312
+ </div>
49313
+ }
49314
+ <rp-loader [show]="controllerService.shouldShowLoader"></rp-loader>
49315
+ @if (shouldShowLandscapeMessage) {
49316
+ <div class="mobile-portrait-overlay">
49317
+ <!--
49318
+ <mat-icon svgIcon="tilt-phone" class="tilt-phone-icon"></mat-icon>
49319
+ -->
49320
+ <div>
49321
+ <!--
49322
+ {{'PLEASE_USE_PHONE_IN_LANDSCAPE_MODE' | localize}}
49323
+ -->
49324
+ </div>
49325
+ </div>
49326
+ }
49327
+ }
49617
49328
  `,
49618
49329
  encapsulation: ViewEncapsulation.None,
49619
49330
  providers: [
@@ -49629,7 +49340,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
49629
49340
  type: Optional
49630
49341
  }, {
49631
49342
  type: Self
49632
- }] }, { type: IntegrationService }, { type: SceneService }, { type: WebWorkerService }], propDecorators: { generalFilterOrders: [{
49343
+ }] }, { type: IntegrationService }, { type: SceneService }, { type: WebWorkerService }, { type: i0.Injector }], propDecorators: { generalFilterOrders: [{
49633
49344
  type: Input
49634
49345
  }], purchaseFilterOrders: [{
49635
49346
  type: Input
@@ -52447,11 +52158,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
52447
52158
  }] });
52448
52159
 
52449
52160
  class HomedecoratorModule {
52450
- constructor(_injector) {
52451
- this._injector = _injector;
52452
- ServiceLocator.injector = this._injector;
52453
- }
52454
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: HomedecoratorModule, deps: [{ token: i0.Injector }], target: i0.ɵɵFactoryTarget.NgModule }); }
52161
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: HomedecoratorModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
52455
52162
  static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.16", ngImport: i0, type: HomedecoratorModule, bootstrap: [HomedecoratorComponent], declarations: [HomedecoratorComponent], imports: [CommonModule,
52456
52163
  ProgressBarModule,
52457
52164
  LoadingOverlayModule,
@@ -52500,7 +52207,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
52500
52207
  ],
52501
52208
  bootstrap: [HomedecoratorComponent]
52502
52209
  }]
52503
- }], ctorParameters: () => [{ type: i0.Injector }] });
52210
+ }] });
52504
52211
 
52505
52212
  class MaterialBuilderComponent {
52506
52213
  set settings(value) {