@colijnit/homedecorator 261.20.4 → 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
@@ -6874,7 +6877,7 @@ class HomedecoratorConnectorService {
6874
6877
  });
6875
6878
  this.articleReceived.next(article);
6876
6879
  this._article = article;
6877
- this._articlePrice = article.price;
6880
+ this._articlePrice = article ? article.price : null;
6878
6881
  // Sometimes the sku is not returned in Article
6879
6882
  this._article.sku = sku;
6880
6883
  return article;
@@ -9820,8 +9823,8 @@ class OutputSettings {
9820
9823
  }
9821
9824
  class SceneSettings {
9822
9825
  }
9823
- let RenderSettings$1 = class RenderSettings {
9824
- };
9826
+ class RenderSettings {
9827
+ }
9825
9828
  class Camera {
9826
9829
  }
9827
9830
  class CameraDOF {
@@ -10026,7 +10029,7 @@ class ApiServiceModule {
10026
10029
  };
10027
10030
  }
10028
10031
  _setRenderSettings(renderParameters) {
10029
- const settings = new RenderSettings$1();
10032
+ const settings = new RenderSettings();
10030
10033
  settings.width = renderParameters.width;
10031
10034
  settings.height = renderParameters.height;
10032
10035
  settings.outputType = OutputType.Jpeg;
@@ -10036,7 +10039,7 @@ class ApiServiceModule {
10036
10039
  return settings;
10037
10040
  }
10038
10041
  _setProductRenderSettings(renderParameters) {
10039
- const settings = new RenderSettings$1();
10042
+ const settings = new RenderSettings();
10040
10043
  settings.width = renderParameters.width;
10041
10044
  settings.height = renderParameters.height;
10042
10045
  settings.outputType = OutputType.Jpeg;
@@ -14780,7 +14783,7 @@ class BaseWall extends Mesh {
14780
14783
  this.remove(item);
14781
14784
  this.onItems = this.onItems.filter(i => i !== item);
14782
14785
  this.itemsChanged = true;
14783
- this._reCreateWallGeometry();
14786
+ // this._reCreateWallGeometry();
14784
14787
  }
14785
14788
  resetRoom() {
14786
14789
  this.oppositeCache.clear();
@@ -15064,12 +15067,26 @@ class BaseWall extends Mesh {
15064
15067
  this.items
15065
15068
  .filter((item) => item.getMaskedGeometry())
15066
15069
  .forEach((item) => {
15067
- 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();
15068
15076
  const holesBrush = new Brush(geo);
15077
+ holesBrush.material = this.material[this.frontMaterialIndex];
15069
15078
  holesBrush.position.copy(item.position);
15070
15079
  holesBrush.quaternion.copy(item.quaternion);
15071
15080
  holesBrush.updateMatrixWorld();
15072
- 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
+ }
15073
15090
  this._tempHoles.push(holesBrush);
15074
15091
  });
15075
15092
  const newGeometry = this.brush.geometry;
@@ -15107,6 +15124,22 @@ class Wall extends BaseWall {
15107
15124
  this.userData = new Object();
15108
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);
15109
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
+ }
15110
15143
  cloned.userData = tempUserData;
15111
15144
  this.userData = tempUserData;
15112
15145
  return cloned;
@@ -15269,14 +15302,50 @@ class WallService {
15269
15302
  if (!wall || !corner) {
15270
15303
  return;
15271
15304
  }
15272
- 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);
15273
15317
  const prevCorner = wall.getEnd();
15274
15318
  wall.setEnd(corner);
15319
+ // setEnd only swaps the corner reference; rebuild the 3D geometry of the shortened wall
15320
+ wall.cornerMoved();
15275
15321
  corner.removeDuplicateWalls();
15276
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
+ });
15277
15332
  this._updatePrevAndNextWalls();
15278
15333
  this._prepareOrphanWalls();
15279
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
+ }
15280
15349
  updatePrevWall(wallId, prevWallId) {
15281
15350
  if (wallId && prevWallId) {
15282
15351
  const wall = this.walls.find(w => w.wallId === wallId);
@@ -15358,6 +15427,56 @@ class WallService {
15358
15427
  Utils$1.RemoveValue(this.walls, wall);
15359
15428
  wall.removeWall();
15360
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
+ }
15361
15480
  updateWallHeights(newHeight) {
15362
15481
  this.walls.forEach(wall => {
15363
15482
  wall.height = newHeight / 100;
@@ -16948,6 +17067,9 @@ class WallItem extends Item {
16948
17067
  else {
16949
17068
  DistanceUtils.UpdateSideDistances(this.distancesObject, this, this.currentWall, this.worldPosVec.clone(), this.getHalfSize(), this.worldRotation.y);
16950
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();
16951
17073
  this.add(this.distancesObject);
16952
17074
  return null;
16953
17075
  }
@@ -16989,12 +17111,20 @@ class WallItem extends Item {
16989
17111
  }
16990
17112
  return new Vector3();
16991
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
+ }
16992
17122
  _createHeightMeasurement() {
16993
17123
  this.heightMesh = MeasurementUtils.makeHeightTextMesh(this.getHeight(), itemMeasurementsTextColor, itemMeasurementsTextSize, false, true);
16994
17124
  this.heightMesh.geometry.computeBoundingBox();
16995
17125
  const width = this.heightMesh.geometry.boundingBox.max.x - this.heightMesh.geometry.boundingBox.min.x;
16996
17126
  this.heightMesh.name = this.heightMeshName;
16997
- 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());
16998
17128
  this.add(this.heightMesh);
16999
17129
  }
17000
17130
  _createWidthMeasurement() {
@@ -17002,7 +17132,7 @@ class WallItem extends Item {
17002
17132
  this.widthMesh.geometry.computeBoundingBox();
17003
17133
  const width = this.widthMesh.geometry.boundingBox.max.x - this.widthMesh.geometry.boundingBox.min.x;
17004
17134
  this.widthMesh.name = this.widthMeshName;
17005
- 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());
17006
17136
  this.add(this.widthMesh);
17007
17137
  }
17008
17138
  _getMaskedGeometry() {
@@ -17090,10 +17220,9 @@ class WallItem extends Item {
17090
17220
  // if elevation is higher than the wall, use maxY
17091
17221
  // vec3.y = Math.min(this._getMaxY(wall) / 2, this.halfSize.y + this.elevation);
17092
17222
  vec3.y = Math.min(maxY, this.halfSize.y + this.elevation);
17093
- }
17094
- else if (this.elevationAdjustable && this.onWall) {
17095
- // if the item is adjustable & is placed on the wall
17096
- 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);
17097
17226
  }
17098
17227
  else {
17099
17228
  if (vec3.y < minY) {
@@ -17191,6 +17320,8 @@ class InWallItem extends WallItem {
17191
17320
  this._openCloseIndicatorColor = '#606E8C';
17192
17321
  this._frameWidth = 0.07;
17193
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;
17194
17325
  this._isWindow = false;
17195
17326
  this._doorpost = false;
17196
17327
  this._setDefault();
@@ -17214,6 +17345,25 @@ class InWallItem extends WallItem {
17214
17345
  ObjectUtils.DisposeMaterial(this.frameMaterial);
17215
17346
  ObjectUtils.DisposeMaterial(this.doorMaterialFront);
17216
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();
17217
17367
  }
17218
17368
  updateOpeningObject() {
17219
17369
  if (this.openCloseIndicatorObject) {
@@ -17265,6 +17415,10 @@ class InWallItem extends WallItem {
17265
17415
  this.createCustomMesh(this.getWidth(), this.getHeight());
17266
17416
  }
17267
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();
17268
17422
  }
17269
17423
  /** */
17270
17424
  getWallOffset() {
@@ -17344,16 +17498,22 @@ class InWallItem extends WallItem {
17344
17498
  return meshes;
17345
17499
  }
17346
17500
  else {
17347
- const visibleMeshes = [];
17348
- if (!this.visible) {
17349
- return [];
17350
- }
17351
- this.traverse(c => {
17352
- if (c.visible && !this.excludedMeshes.includes(c.name) && c instanceof Mesh) {
17353
- visibleMeshes.push(c);
17354
- }
17355
- });
17356
- 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;
17357
17517
  }
17358
17518
  }
17359
17519
  async createTextureMaterial(options) {
@@ -17396,6 +17556,8 @@ class InWallItem extends WallItem {
17396
17556
  createCustomMesh(width, height) {
17397
17557
  const halfWidth = width / 2;
17398
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);
17399
17561
  this.leftFrame = this._createFrameSide(this._frameWidth, this._getHeightFrame(height), this._frameDepth);
17400
17562
  this.leftFrame.rotation.set(this._isWindow ? 180 * (Math.PI / 180) : 0, 0, 0);
17401
17563
  this.leftFrame.position.x = -halfWidth + halfFrame;
@@ -17429,7 +17591,9 @@ class InWallItem extends WallItem {
17429
17591
  }
17430
17592
  this.customMesh = new THREE.Mesh(customGeo, this._isWindow ? this.windowMaterial : this.doorMaterialFront);
17431
17593
  this.customMesh.castShadow = this._isWindow ? false : !this.isGlass;
17432
- 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;
17433
17597
  this.customMesh.name = 'customMesh';
17434
17598
  if (this._isWindow) {
17435
17599
  this.customMesh.name += 'Window';
@@ -17549,17 +17713,22 @@ class InWallItem extends WallItem {
17549
17713
  this.frameMaterial = new THREE.MeshPhongMaterial({ side: side, name: 'frameMaterial' });
17550
17714
  this.frameMaterial.color = new THREE.Color(this.frameColor);
17551
17715
  if (this._isWindow) {
17552
- 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' });
17553
17719
  this.windowMaterial.transparent = true;
17554
17720
  this.windowMaterial.alphaTest = 0;
17555
17721
  this.windowMaterial.opacity = 0.2;
17556
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;
17557
17726
  this.windowMaterial.needsUpdate = true;
17558
- this.windowMaterial.side = THREE.FrontSide;
17727
+ // this.windowMaterial.side = THREE.FrontSide;
17559
17728
  this.object.material = [this.frameMaterial, this.windowMaterial];
17560
17729
  }
17561
17730
  else {
17562
- this.doorMaterialFront = new THREE.MeshPhongMaterial({ side: side, name: 'doorMaterialFront' });
17731
+ this.doorMaterialFront = new THREE.MeshPhongMaterial({ side: side, name: 'doorGlassMaterialFront' });
17563
17732
  this.doorMaterialFront.color = new THREE.Color(this.doorColor);
17564
17733
  if (this._doorpost) {
17565
17734
  this.doorMaterialFront.transparent = true;
@@ -17568,6 +17737,22 @@ class InWallItem extends WallItem {
17568
17737
  this.object.material = [this.frameMaterial, this.doorMaterialFront];
17569
17738
  }
17570
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
+ }
17571
17756
  _getHeightFrame(height) {
17572
17757
  return height - (this._isWindow ? 2 * (this._frameWidth - 0.02) : this._frameWidth - 0.02);
17573
17758
  }
@@ -17698,6 +17883,13 @@ class InWallItem extends WallItem {
17698
17883
  this._createDepthMeasurement();
17699
17884
  }
17700
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
+ }
17701
17893
  _createDepthMeasurement() {
17702
17894
  const depth = this.opening && this.opening.double ? Math.round((this.getWidth() / 2) * 100) / 100 : this.getWidth();
17703
17895
  this.depthMesh = MeasurementUtils.makeDepthTextMesh(depth, 0xFF00FF, 0.08, false, true);
@@ -18120,6 +18312,15 @@ class ItemService {
18120
18312
  }
18121
18313
  // todo: fix the any
18122
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
+ }
18123
18324
  this.items.push(obj);
18124
18325
  if (addToScene) {
18125
18326
  this._sceneService.addObject(obj);
@@ -18153,7 +18354,7 @@ class ItemService {
18153
18354
  getFurniture() {
18154
18355
  const allItems = this.items.concat(...this.items.map(i => {
18155
18356
  if (i instanceof Wall) {
18156
- return i.items.filter(wi => !wi.configurable).concat(i.onItems.filter(woi => !woi.configurable));
18357
+ return i.items.concat(i.onItems);
18157
18358
  }
18158
18359
  })).filter(i => i !== undefined);
18159
18360
  return allItems
@@ -19502,7 +19703,11 @@ class BluePrintFloorplanService extends BaseBluePrintService {
19502
19703
  return this.wallService.createWall(start, end, height, thickness);
19503
19704
  }
19504
19705
  removeWall(wall) {
19706
+ const corner1 = wall.getStart();
19707
+ const corner2 = wall.getEnd();
19505
19708
  this.roomService.removeWall(wall);
19709
+ this.wallService.joinCollinearWallsAt(corner1);
19710
+ this.wallService.joinCollinearWallsAt(corner2);
19506
19711
  this.cornerService.removeOrphanCorners();
19507
19712
  this.update();
19508
19713
  }
@@ -22917,7 +23122,25 @@ class SceneEventService {
22917
23122
  }
22918
23123
  this._switchState(SceneEventState.DND);
22919
23124
  this._dragAndDropService.draggedStatus.dragEnter();
22920
- 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
+ }
22921
23144
  if (this._dragAndDropService.draggedItem) {
22922
23145
  this._dragAndDropService.draggedStatus.objectLoaded();
22923
23146
  this._dragAndDropService.updateDraggedPosition(vec3);
@@ -22929,6 +23152,35 @@ class SceneEventService {
22929
23152
  this._dragAndDropService.dragFloorDecoration(this._floorIntersection(this._sceneService.positionInSceneToScreen(vec3)));
22930
23153
  }
22931
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
+ }
22932
23184
  intersectingVec3(vec2, intersection) {
22933
23185
  if (!intersection) {
22934
23186
  const gIntersections = this._groundIntersections(vec2);
@@ -28159,64 +28411,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
28159
28411
  type: Injectable
28160
28412
  }], ctorParameters: () => [{ type: ThreedInPhotoBuildService }, { type: ThreedInPhotoViewService }, { type: ThreedInPhotoConnectionService }, { type: ThreedInPhotoSceneService }, { type: ThreedInPhotoRenderService }, { type: i1$2.MatDialog }, { type: SceneEventService }, { type: CameraService }, { type: ViewModeService }] });
28161
28413
 
28162
- var ConnectionStatus;
28163
- (function (ConnectionStatus) {
28164
- ConnectionStatus[ConnectionStatus["IsUndefined"] = 0] = "IsUndefined";
28165
- ConnectionStatus[ConnectionStatus["IsConnected"] = 1] = "IsConnected";
28166
- ConnectionStatus[ConnectionStatus["TryingToConnect"] = 2] = "TryingToConnect";
28167
- ConnectionStatus[ConnectionStatus["IsDisConnected"] = 3] = "IsDisConnected";
28168
- })(ConnectionStatus || (ConnectionStatus = {}));
28169
-
28170
- var RenderStatus;
28171
- (function (RenderStatus) {
28172
- RenderStatus[RenderStatus["IsUndefined"] = 0] = "IsUndefined";
28173
- RenderStatus[RenderStatus["IsRunning"] = 1] = "IsRunning";
28174
- RenderStatus[RenderStatus["IsSuccess"] = 2] = "IsSuccess";
28175
- RenderStatus[RenderStatus["IsStopped"] = 3] = "IsStopped";
28176
- RenderStatus[RenderStatus["IsWaiting"] = 4] = "IsWaiting";
28177
- })(RenderStatus || (RenderStatus = {}));
28178
-
28179
- class RenderQueueItem {
28180
- constructor() {
28181
- this.startDateTime = new Date();
28182
- this.rendered = false;
28183
- this.renderProgress = 0;
28184
- this.renderIterations = 0;
28185
- this.renderStatus = RenderStatus.IsUndefined;
28186
- }
28187
- }
28188
-
28189
- var ToastType;
28190
- (function (ToastType) {
28191
- ToastType[ToastType["Success"] = 0] = "Success";
28192
- ToastType[ToastType["Warning"] = 1] = "Warning";
28193
- ToastType[ToastType["Error"] = 2] = "Error";
28194
- })(ToastType || (ToastType = {}));
28195
-
28196
- class Toast {
28197
- constructor() {
28198
- this.type = ToastType.Success;
28199
- }
28200
- }
28201
-
28202
- class RenderData {
28203
- constructor() {
28204
- this.cameraFOV = 45;
28205
- }
28206
- }
28207
-
28208
- class RenderSettings {
28209
- constructor() {
28210
- this.camRotationX = 0.24;
28211
- this.camRotationY = 0;
28212
- this.environmentName = '';
28213
- this.environmentHdr = '';
28214
- this.environmentRotation = 0;
28215
- this.environmentIntensity = null;
28216
- this.extraLights = [];
28217
- }
28218
- }
28219
-
28220
28414
  class ExportObject {
28221
28415
  }
28222
28416
 
@@ -28308,6 +28502,25 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
28308
28502
  type: Injectable
28309
28503
  }], ctorParameters: () => [{ type: HomedecoratorSettingsService }, { type: HomedecoratorConnectorAdapterService }, { type: ThreedselectorService }] });
28310
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
+
28311
28524
  class ToastService {
28312
28525
  constructor(_dictionaryService) {
28313
28526
  this._dictionaryService = _dictionaryService;
@@ -28324,597 +28537,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
28324
28537
  type: Injectable
28325
28538
  }], ctorParameters: () => [{ type: HomedecoratorDictionaryService }] });
28326
28539
 
28327
- class RenderService {
28328
- static MakeWindowMaterialTransparent(material) {
28329
- // console.log(material);
28330
- material.transparent = true;
28331
- material.opacity = Math.min(material.opacity, 0.4);
28332
- return material;
28333
- }
28334
- constructor(_settingsService, _exportService, _cameraService, _sceneService, _toastService, _messageBusService, _googleTagManager, _roomService, _floorService) {
28335
- this._settingsService = _settingsService;
28336
- this._exportService = _exportService;
28337
- this._cameraService = _cameraService;
28338
- this._sceneService = _sceneService;
28339
- this._toastService = _toastService;
28340
- this._messageBusService = _messageBusService;
28341
- this._googleTagManager = _googleTagManager;
28342
- this._roomService = _roomService;
28343
- this._floorService = _floorService;
28344
- this.renderModes = RenderModes;
28345
- this.streaming = {};
28346
- this.renderedRoomImages = [];
28347
- this.connectionStatus = ConnectionStatus.IsUndefined;
28348
- this.renders = [];
28349
- this.cameraPositions = [];
28350
- this.imageSizes = [
28351
- { id: 1, name: ' 720p (HD)', width: 1280, height: 720 },
28352
- { id: 2, name: '1080P (HD)', width: 1920, height: 1080 },
28353
- { id: 3, name: '1440p (2K)', width: 2560, height: 1440 },
28354
- { id: 4, name: '2160p (4K)', width: 4096, height: 2160 }
28355
- ];
28356
- this.lightnings = [
28357
- { id: 1, name: 'Light', settings: [] },
28358
- { id: 2, name: 'Medium', settings: [] },
28359
- { id: 3, name: 'Heay', settings: [] }
28360
- ];
28361
- this.renderEnvironments = [
28362
- { id: 1, name: 'None', hdrFile: '', intensity: 1.0 },
28363
- { id: 2, name: 'Modern city', hdrFile: 'canary_wharf_2k.hdr', intensity: 2.5 },
28364
- { id: 3, name: 'City park', hdrFile: 'dresden_moat_2k.hdr', intensity: 2.5 },
28365
- { id: 4, name: 'Night in the city', hdrFile: 'hansaplatz_2k.hdr', intensity: 1.0 },
28366
- { id: 5, name: 'Night in the countryside', hdrFile: 'kloppenheim_02_2k.hdr', intensity: 1.0 },
28367
- { id: 6, name: 'Forest', hdrFile: 'nagoya_wall_path_2k.hdr', intensity: 1.0 },
28368
- { id: 7, name: 'Snow', hdrFile: 'snowy_forest_path_01_2k.hdr', intensity: 1.0 },
28369
- { id: 8, name: 'Pasture', hdrFile: 'spruit_sunrise_2k.hdr', intensity: 1.0 },
28370
- { id: 9, name: 'Field', hdrFile: 'sunflowers_2k.hdr', intensity: 1.0 },
28371
- { id: 10, name: 'Old city and canals', hdrFile: 'tears_of_steel_bridge_2k.hdr', intensity: 1.0 },
28372
- { id: 11, name: 'Estate', hdrFile: 'tiergarten_2k.hdr', intensity: 1.0 },
28373
- { id: 12, name: 'Beach', hdrFile: 'umhlanga_sunrise_2k.hdr', intensity: 2.5 },
28374
- { id: 13, name: 'Residential area with park', hdrFile: 'urban_street_01_2k.hdr', intensity: 1.0 },
28375
- { id: 14, name: 'Residential area', hdrFile: 'urban_street_03_2k.hdr', intensity: 1.0 },
28376
- ];
28377
- this.renderScenes = [
28378
- { id: 1, name: 'scene_grass_cycles_MRP', sceneAssetId: 'scene_grass_cycles_MRP' },
28379
- { id: 2, name: 'scene_lake_cycles_MRP', sceneAssetId: 'scene_lake_cycles_MRP' },
28380
- { id: 3, name: 'scene_sky_cycles_MRP', sceneAssetId: 'scene_sky_cycles_MRP' },
28381
- { id: 4, name: 'scene_garden_cycles_MRP', sceneAssetId: 'scene_garden_cycles_MRP' },
28382
- { id: 5, name: 'scene_nature_cycles_MRP', sceneAssetId: 'scene_nature_cycles_MRP' },
28383
- { id: 5, name: 'scene_01', sceneAssetId: 'scene_01' }
28384
- ];
28385
- this._ceilingLightMargin = 0.5;
28386
- this.selectedImageSize = 2;
28387
- this.selectedEnvironment = 1;
28388
- this.selectedRenderScene = this.renderScenes[0].sceneAssetId;
28389
- this.blendFilesRender = this._settingsService.settings.blendFilesRender;
28390
- this.positions = 1;
28391
- this.save = false;
28392
- this.renderRoomImageChanged = new BehaviorSubject('');
28393
- this.renderingStarted = new Subject();
28394
- this.renderImageChanged = new BehaviorSubject('');
28395
- this.renderQueue = [];
28396
- this.currentQueueRenderItem = new RenderQueueItem();
28397
- this.currentProductHash = '';
28398
- this._subs = [];
28399
- this.sceneData = {};
28400
- this._subs.push(this._settingsService.settingsLoaded.subscribe((loaded) => {
28401
- if (loaded) {
28402
- this.serverData = this._settingsService.settings.renderParameters;
28403
- if (this.serverData) {
28404
- this.serverData.setup = false;
28405
- this.checkConnection();
28406
- this._renderServiceHeartBeat();
28407
- }
28408
- }
28409
- }));
28410
- }
28411
- ngOnDestroy() {
28412
- this._subs.forEach(s => s.unsubscribe());
28413
- }
28414
- async checkConnection() {
28415
- //
28416
- // if (this.service.validate() === false) {
28417
- //
28418
- // try {
28419
- //
28420
- // const url = `${(this.serverData.secure ? 'wss' : 'ws')}://${this.serverData.host}:${this.serverData.port}/service/`;
28421
- // await this.service.connect(url).then(() => {
28422
- // this.serverData.setup = true;
28423
- // }).catch((rej) => {
28424
- // });
28425
- //
28426
- // this.service.on('error', async (object) => {
28427
- // this.serverData.setup = false;
28428
- // if (this.connectionStatus !== ConnectionStatus.TryingToConnect) {
28429
- // this.connectionStatus = ConnectionStatus.IsDisConnected;
28430
- // }
28431
- // await this._onRenderError();
28432
- // });
28433
- // this.service.on('close', async (object) => {
28434
- // this.serverData.setup = false;
28435
- // if (this.connectionStatus !== ConnectionStatus.TryingToConnect) {
28436
- // this.connectionStatus = ConnectionStatus.IsDisConnected;
28437
- // }
28438
- // await this._onRenderClose();
28439
- // });
28440
- //
28441
- // } catch (err) {
28442
- //
28443
- // this.serverData.setup = false;
28444
- // }
28445
- // }
28446
- }
28447
- _renderServiceHeartBeat() {
28448
- setInterval(() => {
28449
- if (this.connectionStatus === ConnectionStatus.IsDisConnected) {
28450
- if (this._settingsService.settings.options.showRenderConnectionInfo) {
28451
- const toast = new Toast();
28452
- toast.message = 'CONNECTION_WITH_RENDER_SERVICE_LOST';
28453
- toast.type = ToastType.Error;
28454
- this._toastService.showToast(toast);
28455
- }
28456
- this.connectionStatus = ConnectionStatus.TryingToConnect;
28457
- this.checkConnection();
28458
- }
28459
- else if (this.connectionStatus === ConnectionStatus.TryingToConnect) {
28460
- if (this.serverData.setup === false) {
28461
- this._messageBusService.emit(MessageType.RenderServiceTryToConnect);
28462
- this.checkConnection();
28463
- }
28464
- else {
28465
- if (this._settingsService.settings.options.showRenderConnectionInfo) {
28466
- const toast = new Toast();
28467
- toast.message = 'RE_CONNECTED_WITH_RENDER_SERVICE';
28468
- toast.type = ToastType.Success;
28469
- this._toastService.showToast(toast);
28470
- }
28471
- this.connectionStatus = ConnectionStatus.IsConnected;
28472
- }
28473
- }
28474
- else if (this.connectionStatus === ConnectionStatus.IsConnected) {
28475
- this._messageBusService.emit(MessageType.RenderServiceConnected);
28476
- }
28477
- }, 2000);
28478
- }
28479
- getRenderParameters(type) {
28480
- const params = new RenderData();
28481
- if (type !== RenderModes.RenderIone) {
28482
- const currentImageSize = this.getImageSizeOnId(this.selectedImageSize);
28483
- params.imageWidth = Number(currentImageSize.width);
28484
- params.imageHeight = Number(currentImageSize.height);
28485
- }
28486
- params.configuredItem = this._getConfiguredFurnitureItem();
28487
- params.cameraFOV = this._cameraService.camera.fov;
28488
- params.type = type;
28489
- if (type === this.renderModes.RenderShop) {
28490
- params.cameraFOV = 30;
28491
- if (this._settingsService.settings.renderParameters.settings !== undefined) {
28492
- params.settings = this._settingsService.settings.renderParameters.settings;
28493
- }
28494
- }
28495
- else if (type === this.renderModes.RenderRoom) {
28496
- const renderEnvironment = this.getRenderEnvironmentOnId(this.selectedEnvironment);
28497
- params.settings = new RenderSettings();
28498
- params.settings.environmentHdr = renderEnvironment.hdrFile;
28499
- params.settings.environmentIntensity = renderEnvironment.intensity;
28500
- const floorPlanHasRooms = this._roomService.rooms[0];
28501
- const ceilingOrFloor = floorPlanHasRooms ? this._roomService.rooms[0].ceilingPlane : this._floorService.getFloorPlane();
28502
- const bb = new Box3().setFromObject(ceilingOrFloor);
28503
- const bbSize = new Vector3();
28504
- bb.getSize(bbSize);
28505
- params.settings.extraLights = [
28506
- {
28507
- x1: bb.min.x + this._ceilingLightMargin,
28508
- z1: bb.min.z + this._ceilingLightMargin,
28509
- x2: bb.max.x - this._ceilingLightMargin,
28510
- z2: bb.max.z - this._ceilingLightMargin,
28511
- height: floorPlanHasRooms ? ceilingOrFloor.position.y : 2.6,
28512
- }
28513
- ];
28514
- }
28515
- return params;
28516
- }
28517
- // The GLTFExporter needs lights to be configured like this,
28518
- // otherwise they will all point in the same direction.
28519
- _fixLight(element) {
28520
- element.target.parent = element;
28521
- element.lookAt(element.target.position);
28522
- element.target.position.x = 0;
28523
- element.target.position.y = 0;
28524
- element.target.position.z = -1;
28525
- }
28526
- _elementMustBeRemoved(element) {
28527
- if (element.type === 'PerspectiveCamera') {
28528
- return true;
28529
- }
28530
- if (!element.name) {
28531
- return false;
28532
- }
28533
- const lcName = element.name.toLowerCase();
28534
- // elements with a name starting with c_ are connectors,
28535
- // which should not be visible.
28536
- if (lcName.startsWith('c_')) {
28537
- return true;
28538
- }
28539
- if (element.name.startsWith('snapping-preview-mesh')) {
28540
- return true;
28541
- }
28542
- return false;
28543
- }
28544
- async _exportToGlb() {
28545
- const assetPath = this._settingsService.settings.assetPath;
28546
- // The ground plane looks odd in renders.
28547
- // The hud-ring and hud-circle are the walkthrough mode marker,
28548
- // which is not supposed to be rendered.
28549
- const elementsToRemove = ['ground-plane', 'hud-ring', 'hud-circle'];
28550
- let scene;
28551
- try {
28552
- scene = this._sceneService.scene.clone();
28553
- elementsToRemove.forEach(elementName => {
28554
- const selectedObject = scene.getObjectByName(elementName);
28555
- scene.remove(selectedObject);
28556
- });
28557
- // Using the parents, because scene.remove does not seem to work correctly.
28558
- const parents = [];
28559
- scene.traverse(element => {
28560
- if (element instanceof DirectionalLight || element instanceof SpotLight) {
28561
- this._fixLight(element);
28562
- }
28563
- if (element.visible === false) {
28564
- // console.log("Element " + element.name + " was invisible, making it visible.");
28565
- element.visible = true;
28566
- }
28567
- if (element instanceof Mesh && element.name && element.name.startsWith('customMeshWindow')) {
28568
- let hasCustomTexture = false;
28569
- if (element.material instanceof Material$1) {
28570
- if (element.material instanceof MeshPhongMaterial && element.material.map) {
28571
- hasCustomTexture = true;
28572
- }
28573
- element.material = RenderService.MakeWindowMaterialTransparent(element.material);
28574
- }
28575
- else if (Array.isArray(element.material)) {
28576
- element.material.forEach(function (material, index) {
28577
- if (material instanceof MeshPhongMaterial && material.map) {
28578
- hasCustomTexture = true;
28579
- }
28580
- element.material[index] = RenderService.MakeWindowMaterialTransparent(material);
28581
- });
28582
- }
28583
- if (!hasCustomTexture) {
28584
- element.name = 'glass';
28585
- }
28586
- }
28587
- if (this._elementMustBeRemoved(element)) {
28588
- parents.push(element.parent);
28589
- }
28590
- });
28591
- parents.forEach(parent => {
28592
- for (let i = parent.children.length - 1; i >= 0; i--) {
28593
- if (this._elementMustBeRemoved(parent.children[i])) {
28594
- parent.remove(parent.children[i]);
28595
- }
28596
- }
28597
- });
28598
- scene.add(this._cameraService.camera.clone());
28599
- const options = {
28600
- trs: false,
28601
- onlyVisible: false,
28602
- truncateDrawRange: true,
28603
- binary: true,
28604
- forceIndices: false,
28605
- forcePowerOfTwoTextures: false,
28606
- // maxTextureSize: 500,
28607
- embedImages: true,
28608
- };
28609
- const exporter = new GLTFExporter();
28610
- let filename = '';
28611
- return new Promise((resolve, reject) => {
28612
- exporter.parse(scene, async (exportedScene) => {
28613
- const blob = new Blob([exportedScene], { type: 'application/octet-stream' });
28614
- const result = await FileUtils.SaveGLBFile(blob, assetPath);
28615
- if (result !== false) {
28616
- filename = result.path;
28617
- }
28618
- resolve(filename);
28619
- }, () => {
28620
- }, options);
28621
- });
28622
- }
28623
- catch (e) {
28624
- throw (e);
28625
- }
28626
- }
28627
- async startRendering() {
28628
- if (this.renderQueue.length > 0) {
28629
- await this.checkConnection();
28630
- if (this.renderQueue[0].renderProgress === 0 || this.renderQueue[0].renderProgress === undefined) {
28631
- this.renderQueue[0].renderStatus = RenderStatus.IsRunning;
28632
- this.currentQueueRenderItem = this.renderQueue[0];
28633
- this.renderQueue.shift();
28634
- this.currentQueueRenderItem.params.glbPath = await this._exportToGlb()
28635
- .catch((e) => {
28636
- return Promise.reject(e);
28637
- });
28638
- await this._startRenderLoop();
28639
- }
28640
- }
28641
- }
28642
- async _colijnRenderScene(params) {
28643
- return new Promise((resolve, reject) => {
28644
- const requestParams = [{
28645
- id: 1,
28646
- jsonrpc: '2.0',
28647
- method: 'colijn_render_scene_from_glb',
28648
- params: params
28649
- }];
28650
- const xhr = new XMLHttpRequest();
28651
- xhr.open('POST', this._getRenderServiceUrl());
28652
- xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
28653
- xhr.onload = () => {
28654
- if (xhr.status >= 200 && xhr.status < 300) {
28655
- resolve(JSON.parse(xhr.responseText));
28656
- }
28657
- else {
28658
- reject(xhr.statusText);
28659
- }
28660
- };
28661
- xhr.onerror = () => reject(xhr.statusText);
28662
- xhr.send(JSON.stringify(requestParams));
28663
- });
28664
- }
28665
- async _startRenderLoop() {
28666
- // temporary solution because large request over websockets are not working because of an error in the software of migenius
28667
- let [info] = await this._colijnRenderScene(this.currentQueueRenderItem.params);
28668
- info = info.result;
28669
- /*
28670
- const [ info ] = await this.service.queue_commands()
28671
- .queue(new Command('colijn_render_scene', this.currentQueueRenderItem.params), true)
28672
- .execute();
28673
- */
28674
- this.currentQueueRenderItem.host = this._settingsService.settings.url;
28675
- this.currentQueueRenderItem.key = info.scene_name;
28676
- this.currentQueueRenderItem.type = this.currentQueueRenderItem.params.type;
28677
- this.currentQueueRenderItem.startDateTime = new Date();
28678
- this.currentQueueRenderItem.imageSize = this.currentQueueRenderItem.params.imageWidth + ' x ' + this.currentQueueRenderItem.params.imageHeight;
28679
- this._setRenderProgress(RenderStatus.IsRunning, 0, 0);
28680
- this.sceneData = info;
28681
- if (!this.sceneData || this.sceneData.error) {
28682
- return;
28683
- }
28684
- if (this.sceneData.image_info && this.sceneData.image_info.needs_render === true) {
28685
- this.currentQueueRenderItem.rendered = true;
28686
- await this._startRenderStream();
28687
- }
28688
- else {
28689
- this._afterRendering();
28690
- }
28691
- }
28692
- async _quitRenderLoop() {
28693
- // if (this.sceneData.loop_name !== undefined && this.service.validate() !== false) {
28694
- // const [] = await this.service.queue_commands()
28695
- // .queue(new Command('render_loop_quit', {
28696
- // render_loop_name: this.sceneData.loop_name
28697
- // }))
28698
- // .execute();
28699
- // this.service.remove_stream(this.sceneData.loop_name);
28700
- // }
28701
- }
28702
- async _startRenderStream() {
28703
- //
28704
- // try {
28705
- //
28706
- // this.streaming.stream = this.service.create_stream();
28707
- // await this.streaming.stream.start({render_loop_name: this.sceneData.loop_name, image_format: 'jpg', quality: '100'});
28708
- //
28709
- // this.streaming.stream.on('image', async (object) => {
28710
- // this._htmlImageDisplay(object, null);
28711
- // const [progress] = await this.service.queue_commands()
28712
- // .queue(new Command('render_loop_get_render_progress', {
28713
- // render_loop_name: this.sceneData.loop_name
28714
- // }), true)
28715
- // .execute();
28716
- //
28717
- // if (progress.progression !== undefined) {
28718
- // this._setRenderProgress(RenderStatus.IsRunning, Math.ceil((progress.progression * 100)), progress.iteration);
28719
- // }
28720
- //
28721
- // if (object.result === 1) {
28722
- //
28723
- // await this.service.queue_commands()
28724
- // .queue(new Command('render_loop_save_to_disk', {
28725
- // render_loop_name: this.sceneData.loop_name,
28726
- // format: 'jpg',
28727
- // quality: 90,
28728
- // path: this.sceneData.image_info.url
28729
- // }), true)
28730
- // .execute();
28731
- //
28732
- // if (this.streaming.stream !== undefined) {
28733
- // this.streaming.stream.stop();
28734
- // }
28735
- // await this._quitRenderLoop();
28736
- // this._afterRendering();
28737
- // return;
28738
- //
28739
- // } else if (object.result < 0) {
28740
- //
28741
- // await this._onRenderError();
28742
- // return;
28743
- // }
28744
- // });
28745
- //
28746
- // } catch (err) {
28747
- //
28748
- // await this._onRenderError();
28749
- // return;
28750
- // }
28751
- }
28752
- _setRenderProgress(status, progress, iterations) {
28753
- if (!this.serverData) {
28754
- return;
28755
- }
28756
- this.currentQueueRenderItem.endDateTime = new Date();
28757
- this.currentQueueRenderItem.renderStatus = status;
28758
- this.currentQueueRenderItem.renderProgress = progress;
28759
- if (iterations > 0) {
28760
- this.currentQueueRenderItem.renderIterations = iterations;
28761
- }
28762
- if (this.serverData.renderMode === RenderModes.RenderIone) {
28763
- const render = this.getRenderOnId(this.currentQueueRenderItem.params.render.id);
28764
- render.status = status;
28765
- render.progress = progress;
28766
- }
28767
- }
28768
- async _onRenderError() {
28769
- this._setRenderProgress(RenderStatus.IsStopped, 0, 0);
28770
- await this._quitRenderLoop();
28771
- }
28772
- async _onRenderClose() {
28773
- this._setRenderProgress(RenderStatus.IsStopped, 0, 0);
28774
- }
28775
- _afterRendering() {
28776
- if (!this.serverData) {
28777
- return;
28778
- }
28779
- this._setRenderProgress(RenderStatus.IsSuccess, 100, 0);
28780
- const imageUrl = this._settingsService.settings.assetPath.replace('content43/', '') + this.sceneData.image_info.url;
28781
- if (this.serverData.renderMode === RenderModes.RenderRoom) {
28782
- this.renderedRoomImages.unshift(imageUrl);
28783
- }
28784
- this.renderImageChanged.next(imageUrl);
28785
- if (this.serverData.renderMode === RenderModes.RenderIone) {
28786
- const render = this.getRenderOnId(this.currentQueueRenderItem.params.render.id);
28787
- render.url = imageUrl;
28788
- }
28789
- const configuredItem = this.currentQueueRenderItem.params.configuredItem;
28790
- const isSingleItem = this.serverData.renderMode !== RenderModes.RenderRoom;
28791
- this._googleTagManager.sendEvent(GoogleTagManagerEvent.Render, {
28792
- 'articleNr': isSingleItem ? configuredItem.sku : 'renderRoom',
28793
- 'product': isSingleItem ? configuredItem.name : 'renderRoom',
28794
- 'dimensions': this.currentQueueRenderItem.imageSize
28795
- });
28796
- this.startRendering();
28797
- }
28798
- _getRenderServiceUrl() {
28799
- return `${(this.serverData.secure ? 'https' : 'http')}://${this.serverData.host}:${this.serverData.port}`;
28800
- }
28801
- forceRenderImage() {
28802
- const floorGroup = this._getFirstCustomFloorItemFromScene();
28803
- if (floorGroup !== null) {
28804
- this._checkVisibleUpdates(floorGroup, true);
28805
- }
28806
- }
28807
- async _checkVisibleUpdates(furniture, forceRender = false) {
28808
- if (!this.serverData) {
28809
- return;
28810
- }
28811
- if (!furniture) {
28812
- return;
28813
- }
28814
- if (this.serverData.renderMode === this.renderModes.RenderIone) {
28815
- const object = this._exportService.getExportObjectFromCustomFloorGroup(furniture);
28816
- this.currentProductHash = object.defaultRenderPath;
28817
- }
28818
- else if (this.serverData.renderMode === this.renderModes.RenderShop) {
28819
- const object = this._exportService.getExportObjectFromCustomFloorGroup(furniture);
28820
- if (!(JSON.stringify(this.prevItem) !== JSON.stringify(object) || forceRender)) {
28821
- return;
28822
- }
28823
- this.renderingStarted.next();
28824
- this.prevItem = object;
28825
- const queueItem = new RenderQueueItem();
28826
- queueItem.params = this.getRenderParameters(this.renderModes.RenderShop);
28827
- queueItem.params.cameraMatrix = this._cameraService.camera.matrixWorldInverse.elements;
28828
- queueItem.params.forceRender = forceRender;
28829
- this.renderQueue = [];
28830
- this.renderQueue.push(queueItem);
28831
- await this.startRendering();
28832
- }
28833
- }
28834
- _htmlImageDisplay(image, urlCreator) {
28835
- try {
28836
- urlCreator = urlCreator || (window ? (window.URL || window.webkitURL) : undefined);
28837
- }
28838
- catch (e) {
28839
- }
28840
- const blob = new Blob([image.image], { type: image.mime_type });
28841
- const url = urlCreator.createObjectURL(blob);
28842
- this.renderRoomImageChanged.next(url);
28843
- }
28844
- getRenderOnId(id) {
28845
- let returnRender = null;
28846
- this.renders.forEach((x) => {
28847
- if (x.id === id) {
28848
- returnRender = x;
28849
- }
28850
- });
28851
- return returnRender;
28852
- }
28853
- getImageSizeOnId(id) {
28854
- let returnSize = null;
28855
- this.imageSizes.forEach((x) => {
28856
- if (x.id === id) {
28857
- returnSize = x;
28858
- }
28859
- });
28860
- return returnSize;
28861
- }
28862
- getRenderEnvironmentOnId(id) {
28863
- let returnEnvironment = null;
28864
- this.renderEnvironments.forEach((renderEnvironment) => {
28865
- if (renderEnvironment.id === id) {
28866
- returnEnvironment = renderEnvironment;
28867
- return;
28868
- }
28869
- });
28870
- return returnEnvironment;
28871
- }
28872
- getLightningOnId(id) {
28873
- let returnLightning = null;
28874
- this.lightnings.forEach((x) => {
28875
- if (x.id === id) {
28876
- returnLightning = x;
28877
- }
28878
- });
28879
- return returnLightning;
28880
- }
28881
- /******************************************** Export functions ********************************************/
28882
- _getFirstCustomFloorItemFromScene() {
28883
- const children = this._sceneService.scene.children;
28884
- if (children.length <= 0) {
28885
- return null;
28886
- }
28887
- for (let a = 0; a < children.length; a++) {
28888
- if (children[a] instanceof CustomFloorItem) {
28889
- return children[a];
28890
- }
28891
- if (children[a] instanceof ItemGroup) {
28892
- const itemGroup = children[a];
28893
- if (itemGroup.items.length > 0) {
28894
- itemGroup.items.forEach((item) => {
28895
- if (item instanceof CustomFloorItem) {
28896
- return item;
28897
- }
28898
- });
28899
- }
28900
- }
28901
- }
28902
- return null;
28903
- }
28904
- _getConfiguredFurnitureItem() {
28905
- const floorgroup = this._getFirstCustomFloorItemFromScene();
28906
- if (floorgroup === null) {
28907
- return null;
28908
- }
28909
- return this._exportService.getExportObjectFromCustomFloorGroup(floorgroup);
28910
- }
28911
- 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 }); }
28912
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: RenderService }); }
28913
- }
28914
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: RenderService, decorators: [{
28915
- type: Injectable
28916
- }], ctorParameters: () => [{ type: HomedecoratorSettingsService }, { type: ExportService }, { type: CameraService }, { type: SceneService }, { type: ToastService }, { type: MessageBusService }, { type: GoogleTagManagerService }, { type: RoomService }, { type: FloorService }] });
28917
-
28918
28540
  class LoadFurnitureWithoutSceneService extends LoadFurnitureBaseService {
28919
28541
  loadFurniture(furnitureData, shouldCopyInstance, looseOriginalConfiguration, standAlone, fromScratch, fromPreset, loadFromProject) {
28920
28542
  throw new Error('Method not implemented.');
@@ -28957,7 +28579,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
28957
28579
  type: Injectable
28958
28580
  }], ctorParameters: () => [{ type: LoadFurnitureService }, { type: LoadFurnitureWithoutSceneService }, { type: HomedecoratorSettingsService }, { type: HomedecoratorConnectorService }] });
28959
28581
 
28960
- class NewRenderService {
28582
+ class RenderService {
28961
28583
  constructor(messageService, _settingsService, _buildFurnitureService, _cameraService, _sceneService, _ione, _ioneConnectorAdapter, _threedSelectorService, _toastService, _messageBusService, _googleTagManager, _roomService, _floorService, _wallService, _ceilingService, _loadFurnitureService, _utilsService, _presetService, _apiServiceModule, _appEventService, _dictionaryService) {
28962
28584
  this.messageService = messageService;
28963
28585
  this._settingsService = _settingsService;
@@ -28981,15 +28603,20 @@ class NewRenderService {
28981
28603
  this._appEventService = _appEventService;
28982
28604
  this._dictionaryService = _dictionaryService;
28983
28605
  this.renderImageChanged = new BehaviorSubject('');
28984
- this.renderImageError = new BehaviorSubject('');
28606
+ this.renderImageError = new Subject();
28985
28607
  this.blenderRenderStarted = new Subject();
28986
28608
  this.renderUpdateImageChanged = new BehaviorSubject(undefined);
28987
28609
  this.renderRoomImageChanged = new BehaviorSubject('');
28988
28610
  this.currentQueueRenderItem = new RenderQueueItem();
28989
28611
  this.renderedRoomImages = [];
28612
+ this.blendFilesRender = false;
28990
28613
  this._overWriteTransparency = false;
28991
28614
  this._subs = [];
28992
- 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
+ }));
28993
28620
  }
28994
28621
  ngOnDestroy() {
28995
28622
  this._subs.forEach(s => s.unsubscribe());
@@ -29014,7 +28641,14 @@ class NewRenderService {
29014
28641
  }
29015
28642
  }
29016
28643
  async renderRoom(settings, preview = false) {
29017
- 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
+ }
29018
28652
  const data = this._getDataForRoomRender(settings);
29019
28653
  data.files = {
29020
28654
  glbData: this._arrayBufferToBase64(sceneData)
@@ -29038,6 +28672,21 @@ class NewRenderService {
29038
28672
  let scene;
29039
28673
  try {
29040
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
+ });
29041
28690
  const lightsToRemove = scene.children.filter(c => c instanceof Light);
29042
28691
  lightsToRemove.forEach(light => {
29043
28692
  if ((light instanceof SpotLight || light instanceof DirectionalLight) && light.target) {
@@ -29058,6 +28707,10 @@ class NewRenderService {
29058
28707
  if (!this._cameraService.isCameraFacingFront(wall) && !wall.orphan && !wall.isInnerWall()) {
29059
28708
  wall.name = 'CULLING_wall';
29060
28709
  }
28710
+ wall.userData = {};
28711
+ // for (let i = wall.children.length; i >= 0; i--) {
28712
+ // wall.remove(wall.children[i]);
28713
+ // }
29061
28714
  });
29062
28715
  const ceilings = scene.children.filter(c => c.name && c.name === this._ceilingService.ceilingName);
29063
28716
  ceilings.forEach(ceiling => {
@@ -29076,7 +28729,9 @@ class NewRenderService {
29076
28729
  embedImages: true,
29077
28730
  };
29078
28731
  scene.name = 'mrp_room_' + scene.uuid;
29079
- const glb = await this._getGlbFromObject(scene, options);
28732
+ const glb = await this._getGlbFromObject(scene, options).catch((error) => {
28733
+ throw (error);
28734
+ });
29080
28735
  // this._utilsService.downloadFile(scene.name + '.glb', new Blob([glb], {type: 'model/gltf-binary'}));
29081
28736
  ObjectUtils.DisposeObject(scene);
29082
28737
  scene = null;
@@ -29091,7 +28746,8 @@ class NewRenderService {
29091
28746
  return new Promise((resolve, reject) => {
29092
28747
  exporter.parse(object, async (exportedScene) => {
29093
28748
  resolve(exportedScene);
29094
- }, () => {
28749
+ }, (error) => {
28750
+ reject(error);
29095
28751
  }, options);
29096
28752
  });
29097
28753
  }
@@ -29210,7 +28866,19 @@ class NewRenderService {
29210
28866
  method: 'POST',
29211
28867
  data: JSON.stringify(data),
29212
28868
  url: `${host}getRenderFromGlb`,
29213
- 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;
29214
28882
  });
29215
28883
  if (result.status === 200) {
29216
28884
  // const image = `data:${result.data.fileType};base64,${result.data.image}`;
@@ -29231,7 +28899,12 @@ class NewRenderService {
29231
28899
  this.renderImageError.next(this._dictionaryService.get('BLENDER_PRODUCT_RENDER_ERROR'));
29232
28900
  }
29233
28901
  // Remove the loading indicator.
29234
- 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);
29235
28908
  }
29236
28909
  }
29237
28910
  }
@@ -29550,10 +29223,10 @@ class NewRenderService {
29550
29223
  this._overWriteTransparency = true;
29551
29224
  }
29552
29225
  }
29553
- 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 }); }
29554
- 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 }); }
29555
29228
  }
29556
- 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: [{
29557
29230
  type: Injectable
29558
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 }] });
29559
29232
 
@@ -30415,6 +30088,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
30415
30088
  type: Injectable
30416
30089
  }], ctorParameters: () => [{ type: HomedecoratorSettingsService }, { type: HomedecoratorConnectorService }] });
30417
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
+
30418
30104
  class ConnectionHeathService {
30419
30105
  constructor(_http, _settingService, _toastService, _messageService) {
30420
30106
  this._http = _http;
@@ -30799,9 +30485,9 @@ class FloorplanRenderService {
30799
30485
  }
30800
30486
  this._clear();
30801
30487
  this._drawGrid();
30802
- // if (this.diagramBackground && this.showDiagramBackground) {
30803
- // this._drawBackground();
30804
- // }
30488
+ if (this.diagramBackground && this.showDiagramBackground) {
30489
+ this._drawBackground();
30490
+ }
30805
30491
  this._drawRooms();
30806
30492
  this._drawWallsWithNoRoom();
30807
30493
  if (this._state.showWallItemMeasurements && this._state.activeItem) {
@@ -30841,6 +30527,24 @@ class FloorplanRenderService {
30841
30527
  ContextUtils.DrawLine(context, 0, gridSpacing * y + offsetY, canvas.width, gridSpacing * y + offsetY, gridWidth, gridColor);
30842
30528
  }
30843
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
+ }
30844
30548
  _drawRooms() {
30845
30549
  const rooms = this._state.rooms;
30846
30550
  rooms.forEach(room => {
@@ -31499,9 +31203,8 @@ const APPLICATION_SERVICES_PROVIDERS = [
31499
31203
  DynamicCameraService,
31500
31204
  ThreedInPhotoInitializerService,
31501
31205
  ThreedInPhotoBuildService,
31502
- RenderService,
31503
31206
  ExportService,
31504
- NewRenderService,
31207
+ RenderService,
31505
31208
  AppInitializerService,
31506
31209
  JsonUtilsService,
31507
31210
  RalService,
@@ -33745,108 +33448,142 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
33745
33448
  class BlenderRenderSettings {
33746
33449
  }
33747
33450
 
33748
- class RenderProgressComponent {
33749
- set show(show) {
33750
- this._show = show;
33751
- if (show) {
33752
- this._progressService.progressBarType = ProgressType.Upload;
33753
- 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 '';
33754
33456
  }
33755
- else {
33756
- this._progressService.progressBarType = ProgressType.Download;
33757
- this._progressService.total = 0;
33457
+ if (!append) {
33458
+ return value;
33758
33459
  }
33460
+ return value + append;
33759
33461
  }
33760
- get show() {
33761
- return this._show;
33762
- }
33763
- get progressValue() {
33764
- return this.progress + '/ 100%';
33765
- }
33766
- 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) {
33767
33475
  this._messageService = _messageService;
33768
- this._progressService = _progressService;
33476
+ this.title = 'UPLOADING_ROOM';
33769
33477
  this.progress = 0;
33478
+ this.rendering = false;
33770
33479
  this._subs = [];
33771
- this._show = false;
33772
- 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)));
33773
33486
  }
33774
33487
  ngOnDestroy() {
33775
33488
  this._subs.forEach(sub => sub.unsubscribe());
33776
33489
  }
33777
33490
  updateProgress(progress) {
33778
- this.progress = progress;
33779
- this._progressService.progress = progress;
33491
+ this.progress = Math.max(0, Math.min(100, progress));
33780
33492
  }
33781
- 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 }); }
33782
- 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: `
33783
- @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: `
33784
33495
  <div class="render-progress-model">
33785
33496
  <div class="model">
33786
33497
  <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>
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
+ -->
33791
33504
  </div>
33792
33505
  <div class="model-content-container">
33793
- <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
+ }
33794
33518
  </div>
33795
33519
  </div>
33796
33520
  </div>
33797
- }
33798
- `, 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" }] }); }
33799
33522
  }
33800
33523
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: RenderProgressComponent, decorators: [{
33801
33524
  type: Component,
33802
33525
  args: [{ selector: 'rp-render-progress', template: `
33803
- @if (show) {
33804
33526
  <div class="render-progress-model">
33805
33527
  <div class="model">
33806
33528
  <div class="model-header-container">
33807
- <h3 class="model-header" [textContent]="title"></h3>
33808
- <div class="close" (click)="show = false">
33809
- <mat-icon class="homedecorator-material-icons">cancel</mat-icon>
33810
- </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
+ -->
33811
33535
  </div>
33812
33536
  <div class="model-content-container">
33813
- <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
+ }
33814
33549
  </div>
33815
33550
  </div>
33816
33551
  </div>
33817
- }
33818
- `, 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"] }]
33819
- }], ctorParameters: () => [{ type: MessageBusService }, { type: ProgressService }], propDecorators: { show: [{
33820
- type: Input
33821
- }], title: [{
33822
- type: Input
33823
- }] } });
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 }] });
33824
33554
 
33825
33555
  class RenderControlsComponent {
33826
33556
  get disablePictureButton() {
33827
- return this._newRenderService.currentQueueRenderItem.renderStatus === this.renderStatus.IsRunning;
33557
+ return this.renderService.currentQueueRenderItem.renderStatus === this.renderStatus.IsRunning;
33828
33558
  }
33829
- constructor(renderService, messageService, viewModeService, settingsService, iconService, _dialog, _sceneService, _cameraService, _configurationService, _settingsService, _newRenderService, _utilsService, _roomService, _wallMeasurementsService, _connectionHealthService, _dictionaryService) {
33830
- this.renderService = renderService;
33559
+ constructor(messageService, viewModeService, settingsService, iconService, renderService, _dialog, _sceneService, _cameraService, _configurationService, _settingsService, _utilsService, _roomService, _wallMeasurementsService, _connectionHealthService, _dictionaryService, _dialogService) {
33831
33560
  this.messageService = messageService;
33832
33561
  this.viewModeService = viewModeService;
33833
33562
  this.settingsService = settingsService;
33834
33563
  this.iconService = iconService;
33564
+ this.renderService = renderService;
33835
33565
  this._dialog = _dialog;
33836
33566
  this._sceneService = _sceneService;
33837
33567
  this._cameraService = _cameraService;
33838
33568
  this._configurationService = _configurationService;
33839
33569
  this._settingsService = _settingsService;
33840
- this._newRenderService = _newRenderService;
33841
33570
  this._utilsService = _utilsService;
33842
33571
  this._roomService = _roomService;
33843
33572
  this._wallMeasurementsService = _wallMeasurementsService;
33844
33573
  this._connectionHealthService = _connectionHealthService;
33845
33574
  this._dictionaryService = _dictionaryService;
33575
+ this._dialogService = _dialogService;
33846
33576
  this.viewModes = ViewMode;
33847
33577
  this.renderStatus = RenderStatus;
33848
33578
  this.icons = IconEnum;
33849
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];
33850
33587
  this.hdriIntensity = 1;
33851
33588
  this.hdriRotation = 0;
33852
33589
  this.lightingExposure = 1;
@@ -33859,14 +33596,22 @@ class RenderControlsComponent {
33859
33596
  this.showCullingErrorDialog = false;
33860
33597
  this.startUploading = false;
33861
33598
  this._subs = [];
33862
- 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(() => {
33863
33600
  this._validateRenderPosition();
33864
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
+ }
33865
33607
  }));
33866
33608
  }
33867
33609
  ngOnInit() {
33868
33610
  this.getRenderScenesFromSettings();
33869
33611
  }
33612
+ ngOnDestroy() {
33613
+ this._subs.forEach((sub) => sub.unsubscribe());
33614
+ }
33870
33615
  showRenderForm(event) {
33871
33616
  this.inPictureMode = !this.inPictureMode;
33872
33617
  this._validateRenderPosition();
@@ -33880,16 +33625,14 @@ class RenderControlsComponent {
33880
33625
  this.startUploading = false;
33881
33626
  }
33882
33627
  }
33883
- createBlenderRender() {
33628
+ createBlenderRender(preview = false) {
33884
33629
  if (!this.showCullingErrorDialog) {
33885
33630
  if (this.viewModeService.isTopViewActive()) {
33886
33631
  this._wallMeasurementsService.prepMeasurementsForRender();
33887
33632
  }
33888
- this.messageService.emit(MessageType.ShowLoadingIndicator, { title: this._dictionaryService.get('PREPARE_TO_RENDER') });
33889
33633
  this.startUploading = true;
33890
33634
  // only render when the showCullingErrorDialog is false
33891
33635
  // this.messageService.emit(MessageType.ShowLoadingIndicator, {title: 'Uploading...'});
33892
- const renderSize = this.renderService.getImageSizeOnId(this.renderService.selectedImageSize);
33893
33636
  const renderSceneAssetId = this.selectedRenderScene;
33894
33637
  if (this.lightingExposure < 1) {
33895
33638
  this.lightingExposure = 1;
@@ -33897,15 +33640,15 @@ class RenderControlsComponent {
33897
33640
  this._validateRenderPosition(); // Check the camera position
33898
33641
  const allowCulling = this._allowCulling(this.hasError);
33899
33642
  const renderInput = new BlenderRenderSettings();
33900
- renderInput.height = renderSize.height;
33901
- renderInput.width = renderSize.width;
33643
+ renderInput.height = preview ? 150 : this.selectedImageSize.height;
33644
+ renderInput.width = preview ? 275 : this.selectedImageSize.width;
33902
33645
  renderInput.sceneAsset = renderSceneAssetId;
33903
33646
  renderInput.hdriIntensity = this.hdriIntensity;
33904
33647
  renderInput.hdriRotation = this.hdriRotation;
33905
33648
  renderInput.lightingExposure = this.lightingExposure;
33906
33649
  renderInput.allowCulling = allowCulling;
33907
33650
  // this._utilsService.prepRoomForRender(false, renderInput);
33908
- this._newRenderService.renderRoom(renderInput);
33651
+ this.renderService.renderRoom(renderInput, preview);
33909
33652
  if (this.viewModeService.isTopViewActive()) {
33910
33653
  this._wallMeasurementsService.restoreMeasurementsAfterRender();
33911
33654
  }
@@ -33933,35 +33676,6 @@ class RenderControlsComponent {
33933
33676
  this._cameraService.camera.position.set(movingPosition.x, movingPosition.y, movingPosition.z);
33934
33677
  this._cameraService.cameraMovementChanged.next();
33935
33678
  }
33936
- createPreviewRender() {
33937
- if (!this.showCullingErrorDialog) {
33938
- if (this.viewModeService.isTopViewActive()) {
33939
- this._wallMeasurementsService.prepMeasurementsForRender();
33940
- }
33941
- const renderSceneAssetId = this.selectedRenderScene;
33942
- // this.messageService.emit(MessageType.ShowLoadingIndicator, {title: 'Uploading...'});
33943
- // this.messageService.emit(MessageType.ShowLoadingIndicator, {title: this._dictionaryService.get('PREPARE_TO_RENDER')});
33944
- this.startUploading = true;
33945
- if (this.lightingExposure < 1) {
33946
- this.lightingExposure = 1;
33947
- }
33948
- this._validateRenderPosition(); // Check the camera position
33949
- const allowCulling = this._allowCulling(this.hasError);
33950
- const renderInput = new BlenderRenderSettings();
33951
- renderInput.height = 150;
33952
- renderInput.width = 275;
33953
- renderInput.sceneAsset = renderSceneAssetId;
33954
- renderInput.hdriIntensity = this.hdriIntensity;
33955
- renderInput.hdriRotation = this.hdriRotation;
33956
- renderInput.lightingExposure = this.lightingExposure;
33957
- renderInput.allowCulling = allowCulling;
33958
- // this._utilsService.prepRoomForRender(false, renderInput, true);
33959
- this._newRenderService.renderRoom(renderInput, true);
33960
- if (this.viewModeService.isTopViewActive()) {
33961
- this._wallMeasurementsService.restoreMeasurementsAfterRender();
33962
- }
33963
- }
33964
- }
33965
33679
  showPreview(image) {
33966
33680
  this.blenderPreviewRender = image;
33967
33681
  }
@@ -34046,465 +33760,413 @@ class RenderControlsComponent {
34046
33760
  // }
34047
33761
  // return allowCulling;
34048
33762
  }
34049
- 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 }); }
34050
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: `
34051
- @if (renderService.serverData && renderService.serverData.renderMode !== renderService.renderModes.RenderShop) {
34052
- <div class="render-container"
34053
- >
34054
- @if (renderService.currentQueueRenderItem.renderStatus === renderStatus.IsRunning || renderService.currentQueueRenderItem.renderStatus === renderStatus.IsSuccess) {
34055
- <div class="render-progress"
34056
- >
34057
- {{ (renderService.currentQueueRenderItem.renderStatus === renderStatus.IsSuccess && renderService.currentQueueRenderItem.renderProgress === 100 ? "RENDER_READY" : "") | localize }}
34058
- {{ (renderService.currentQueueRenderItem.renderStatus === renderStatus.IsSuccess && renderService.currentQueueRenderItem.renderProgress !== 100 ? "RENDER_STOPPED" : "") | localize }}
34059
- {{ (renderService.currentQueueRenderItem.renderStatus === renderStatus.IsRunning) ? renderService.currentQueueRenderItem.renderProgress + "%" : "" }}
34060
- </div>
34061
- }
34062
- <!-- the Yellow render indicators -->
34063
- @if (inPictureMode) {
34064
- <div class="render-indicators">
34065
- <div class="render-indicator-top-left"></div>
34066
- <div class="render-indicator-top-right"></div>
34067
- <div class="render-indicator-bottom-left"></div>
34068
- <div class="render-indicator-bottom-right"></div>
34069
- </div>
34070
- }
34071
- @if (inPictureMode) {
34072
- <div class="render-popup-container">
34073
- <div class="render-popup-header">
34074
- <h3>
34075
- <span>{{ 'PICTURE_MODE' | localize }}</span>
34076
- @if (hasError) {
34077
- <co-icon class="renderErrorIcon" [iconData]="iconService.getIcon(icons.TriangleExclamation)"
34078
- [matTooltip]="'BLENDER_RENDER_ERROR' | localize"></co-icon>
34079
- }
34080
- </h3>
34081
- <button
34082
- class="close-popup-container"
34083
- (click)="resetBlenderRenderScene()">
34084
- <co-icon [iconData]="iconService.getIcon(icons.Cross)"></co-icon>
34085
- </button>
34086
- </div>
34087
- <div class="render-popup-preview">
34088
- @if (blenderPreviewRender) {
34089
- <img [src]="blenderPreviewRender" alt="">
34090
- }
34091
- @if (!blenderPreviewRender) {
34092
- <div class="render-popup-preview-placeholder">
34093
- <span>{{ 'PREVIEW' | localize }}</span>
34094
- </div>
34095
- }
34096
- <button
34097
- class="render-popup-refresh-preview"
34098
- (click)="createPreviewRender()"
34099
- >
34100
- <co-icon [iconData]="iconService.getIcon(icons.RetryButton)"></co-icon>
34101
- </button>
34102
- </div>
34103
- @if (renderService.blendFilesRender) {
34104
- <div class="render-popup-dropdown">
34105
- <div class="toggleable" (click)="toggleRenderSettings()">
34106
- <p>
34107
- @if (!showRenderSettings) {
34108
- <span [textContent]="'RENDER_ADVANCED_SETTINGS_SHOW' | localize"></span>
34109
- }
34110
- @if (showRenderSettings) {
34111
- <span [textContent]="'RENDER_ADVANCED_SETTINGS_HIDE' | localize"></span>
34112
- }
34113
- </p>
34114
- <co-icon [ngClass]="{'icon-rotate': showRenderSettings}"
34115
- [iconData]="iconService.getIcon(icons.ArrowPointDown)"></co-icon>
34116
- </div>
34117
- @if (showRenderSettings) {
34118
- <div class="advanced-render-settings">
34119
- <div class="setting-part-container">
34120
- @if (renderService.serverData.renderMode === renderModes.RenderRoom) {
34121
- <mat-form-field
34122
- class="face-select-form"
34123
- >
34124
- <mat-label>{{ "ENVIRONMENT" | localize }}</mat-label>
34125
- <mat-select [(ngModel)]="selectedRenderScene" (selectionChange)="updateBlenderSceneSettings($event)">
34126
- @for (scene of sceneList; track scene) {
34127
- <mat-option
34128
- [value]="scene">{{ scene.name }}
34129
- </mat-option>
34130
- }
34131
- </mat-select>
34132
- </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="">
34133
33795
  }
34134
- </div>
34135
- <div class="setting-part-container">
34136
- <mat-form-field class="third-width">
34137
- <mat-label [textContent]="'ENVIRONMENT_LIGHT' | localize"></mat-label>
34138
- <input
34139
- [type]="'number'"
34140
- matInput
34141
- [(ngModel)]="hdriIntensity"
34142
- (ngModelChange)="hdriIntensity = +$event">
34143
- </mat-form-field>
34144
- <div class="setting-part-buttons">
34145
- <button class="amount-button" (click)="hdriIntensity = +hdriIntensity - 1">
34146
- <co-icon [iconData]="iconService.getIcon(icons.CircleMinusLight)"></co-icon>
34147
- </button>
34148
- <button class="amount-button" (click)="hdriIntensity = +hdriIntensity + 1">
34149
- <co-icon [iconData]="iconService.getIcon(icons.CirclePlusLight)"></co-icon>
34150
- </button>
34151
- </div>
34152
- <div class="setting-part-slider">
34153
- <mat-slider class="value" min="1" max="20" step="1" [(ngModel)]="hdriIntensity"></mat-slider>
34154
- </div>
34155
- </div>
34156
- <div class="setting-part-container">
34157
- <mat-form-field class="third-width">
34158
- <mat-label [textContent]="'ROTATION' | localize"></mat-label>
34159
- <input
34160
- [type]="'number'"
34161
- matInput
34162
- [(ngModel)]="hdriRotation"
34163
- (ngModelChange)="hdriRotation = +$event">
34164
- </mat-form-field>
34165
- <div class="setting-part-buttons">
34166
- <button class="amount-button" (click)="hdriRotation = +hdriRotation - 1">
34167
- <co-icon [iconData]="iconService.getIcon(icons.CircleMinusLight)"></co-icon>
34168
- </button>
34169
- <button class="amount-button" (click)="hdriRotation = +hdriRotation + 1">
34170
- <co-icon [iconData]="iconService.getIcon(icons.CirclePlusLight)"></co-icon>
34171
- </button>
33796
+ @if (!blenderPreviewRender) {
33797
+ <div class="render-popup-preview-placeholder">
33798
+ <span>{{ 'PREVIEW' | localize }}</span>
34172
33799
  </div>
34173
- <div class="setting-part-slider">
34174
- <mat-slider class="value" min="0" max="360" step="1" [(ngModel)]="hdriRotation"></mat-slider>
34175
- </div>
34176
- </div>
34177
- <div class="setting-part-container">
34178
- <mat-form-field class="third-width">
34179
- <mat-label [textContent]="'LIGHTS' | localize"></mat-label>
34180
- <input
34181
- [type]="'number'"
34182
- matInput
34183
- [(ngModel)]="lightingExposure"
34184
- (ngModelChange)="lightingExposure = +$event">
34185
- </mat-form-field>
34186
- <div class="setting-part-buttons">
34187
- <button class="amount-button" (click)="lightingExposure = +lightingExposure - 1">
34188
- <co-icon [iconData]="iconService.getIcon(icons.CircleMinusLight)"></co-icon>
34189
- </button>
34190
- <button class="amount-button" (click)="lightingExposure = +lightingExposure + 1">
34191
- <co-icon [iconData]="iconService.getIcon(icons.CirclePlusLight)"></co-icon>
34192
- </button>
34193
- </div>
34194
- <div class="setting-part-slider">
34195
- <mat-slider class="value" min="1" max="10" step="1" [(ngModel)]="lightingExposure"></mat-slider>
34196
- </div>
34197
- </div>
34198
- </div>
34199
33800
  }
34200
- </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>
34201
33901
  }
34202
- @if (renderService.serverData.renderMode === renderModes.RenderRoom) {
34203
- <div class="render-popup-dropdown">
33902
+ <div class="render-popup-dropdown">
34204
33903
  <mat-form-field class="face-select-form">
34205
- <mat-label>{{ "IMAGE_SIZE" | localize }}</mat-label>
34206
- <mat-select [(ngModel)]="renderService.selectedImageSize">
34207
- @for (size of renderService.imageSizes; track size) {
34208
- <mat-option [value]="size.id">{{ size.name }} {{ size.width }}
34209
- x{{ size.height }}
34210
- </mat-option>
34211
- }
34212
- </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>
34213
33912
  </mat-form-field>
34214
- </div>
34215
- }
33913
+ </div>
34216
33914
  <div class="render-popup-button-container">
34217
- <button class="render-popup-button photo-button"
34218
- (click)="createBlenderRender()"
34219
- title="{{'MAKE_A_PICTURE' | localize}}"
34220
- [disabled]="disablePictureButton">
34221
- <co-icon [iconData]="iconService.getIcon(icons.CircleCheck)"></co-icon>
34222
- {{ 'MAKE_A_PICTURE' | localize }}
34223
- </button>
34224
- <button
34225
- class="render-popup-button cancel-button"
34226
- (click)="resetBlenderRenderScene()">
34227
- <co-icon [iconData]="iconService.getIcon(icons.CircleXmark)"></co-icon>
34228
- {{ 'CLOSE_PHOTO_MODE' | localize }}
34229
- </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>
34230
33928
  </div>
34231
- </div>
34232
- }
34233
- @if (showCullingErrorDialog) {
34234
- <div class="render-warning">
33929
+ </div>
33930
+ }
33931
+ @if (showCullingErrorDialog) {
33932
+ <div class="render-warning">
34235
33933
  <div class="render-warming-header">
34236
- <h2>{{ 'BLENDER_RENDER_ERROR_TITLE' | localize }}</h2>
34237
- <div class="render-warning-close" (click)="showCullingErrorDialog = false">
34238
- <mat-icon class="homedecorator-material-icons">cancel</mat-icon>
34239
- </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>
34240
33938
  </div>
34241
33939
  <div class="render-warning-body">
34242
- <p>{{ 'BLENDER_RENDER_WARNING_CULLING' | localize }}</p>
33940
+ <p>{{ 'BLENDER_RENDER_WARNING_CULLING' | localize }}</p>
34243
33941
  </div>
34244
33942
  <div class="render-warning-footer">
34245
- <button
34246
- class="render-popup-button cancel-button"
34247
- (click)="showCullingErrorDialog = false">
34248
- <co-icon [iconData]="iconService.getIcon(icons.CircleXmark)"></co-icon>
34249
- {{ 'CLOSE' | localize }}
34250
- </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>
34251
33949
  </div>
34252
- </div>
34253
- }
34254
- <rp-render-progress
34255
- [title]="'PREPARE_TO_RENDER' | localize"
34256
- [show]="startUploading"
34257
- >
34258
- </rp-render-progress>
34259
- <button
34260
- #renderButton
34261
- mat-raised-button
34262
- matTooltip="{{'RENDER_TAKE_A_PICTURE' | localize}}"
34263
- [id]="'standalone_render_picture'"
34264
- [class.active]="(
34265
- (renderService.serverData.renderMode === renderService.renderModes.RenderRoom && viewModeService.viewMode === viewModes.WalkThrough) ||
34266
- (renderService.serverData.renderMode === renderService.renderModes.RenderIone))"
34267
- (click)="showRenderForm($event)"
34268
- >
34269
- <mat-icon class="icon homedecorator-material-icons"
34270
- aria-hidden="true">{{ (renderService.currentQueueRenderItem.renderStatus === renderStatus.IsRunning ? 'open_in_browser' : 'photo_camera') }}
34271
- </mat-icon>
34272
- </button>
34273
- </div>
33950
+ </div>
34274
33951
  }
34275
-
34276
- `, 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" }] }); }
34277
33965
  }
34278
33966
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: RenderControlsComponent, decorators: [{
34279
33967
  type: Component,
34280
33968
  args: [{ selector: 'rp-render-controls', template: `
34281
- @if (renderService.serverData && renderService.serverData.renderMode !== renderService.renderModes.RenderShop) {
34282
- <div class="render-container"
34283
- >
34284
- @if (renderService.currentQueueRenderItem.renderStatus === renderStatus.IsRunning || renderService.currentQueueRenderItem.renderStatus === renderStatus.IsSuccess) {
34285
- <div class="render-progress"
34286
- >
34287
- {{ (renderService.currentQueueRenderItem.renderStatus === renderStatus.IsSuccess && renderService.currentQueueRenderItem.renderProgress === 100 ? "RENDER_READY" : "") | localize }}
34288
- {{ (renderService.currentQueueRenderItem.renderStatus === renderStatus.IsSuccess && renderService.currentQueueRenderItem.renderProgress !== 100 ? "RENDER_STOPPED" : "") | localize }}
34289
- {{ (renderService.currentQueueRenderItem.renderStatus === renderStatus.IsRunning) ? renderService.currentQueueRenderItem.renderProgress + "%" : "" }}
34290
- </div>
34291
- }
34292
- <!-- the Yellow render indicators -->
34293
- @if (inPictureMode) {
34294
- <div class="render-indicators">
34295
- <div class="render-indicator-top-left"></div>
34296
- <div class="render-indicator-top-right"></div>
34297
- <div class="render-indicator-bottom-left"></div>
34298
- <div class="render-indicator-bottom-right"></div>
34299
- </div>
34300
- }
34301
- @if (inPictureMode) {
34302
- <div class="render-popup-container">
34303
- <div class="render-popup-header">
34304
- <h3>
34305
- <span>{{ 'PICTURE_MODE' | localize }}</span>
34306
- @if (hasError) {
34307
- <co-icon class="renderErrorIcon" [iconData]="iconService.getIcon(icons.TriangleExclamation)"
34308
- [matTooltip]="'BLENDER_RENDER_ERROR' | localize"></co-icon>
34309
- }
34310
- </h3>
34311
- <button
34312
- class="close-popup-container"
34313
- (click)="resetBlenderRenderScene()">
34314
- <co-icon [iconData]="iconService.getIcon(icons.Cross)"></co-icon>
34315
- </button>
34316
- </div>
34317
- <div class="render-popup-preview">
34318
- @if (blenderPreviewRender) {
34319
- <img [src]="blenderPreviewRender" alt="">
34320
- }
34321
- @if (!blenderPreviewRender) {
34322
- <div class="render-popup-preview-placeholder">
34323
- <span>{{ 'PREVIEW' | localize }}</span>
34324
- </div>
34325
- }
34326
- <button
34327
- class="render-popup-refresh-preview"
34328
- (click)="createPreviewRender()"
34329
- >
34330
- <co-icon [iconData]="iconService.getIcon(icons.RetryButton)"></co-icon>
34331
- </button>
34332
- </div>
34333
- @if (renderService.blendFilesRender) {
34334
- <div class="render-popup-dropdown">
34335
- <div class="toggleable" (click)="toggleRenderSettings()">
34336
- <p>
34337
- @if (!showRenderSettings) {
34338
- <span [textContent]="'RENDER_ADVANCED_SETTINGS_SHOW' | localize"></span>
34339
- }
34340
- @if (showRenderSettings) {
34341
- <span [textContent]="'RENDER_ADVANCED_SETTINGS_HIDE' | localize"></span>
34342
- }
34343
- </p>
34344
- <co-icon [ngClass]="{'icon-rotate': showRenderSettings}"
34345
- [iconData]="iconService.getIcon(icons.ArrowPointDown)"></co-icon>
34346
- </div>
34347
- @if (showRenderSettings) {
34348
- <div class="advanced-render-settings">
34349
- <div class="setting-part-container">
34350
- @if (renderService.serverData.renderMode === renderModes.RenderRoom) {
34351
- <mat-form-field
34352
- class="face-select-form"
34353
- >
34354
- <mat-label>{{ "ENVIRONMENT" | localize }}</mat-label>
34355
- <mat-select [(ngModel)]="selectedRenderScene" (selectionChange)="updateBlenderSceneSettings($event)">
34356
- @for (scene of sceneList; track scene) {
34357
- <mat-option
34358
- [value]="scene">{{ scene.name }}
34359
- </mat-option>
34360
- }
34361
- </mat-select>
34362
- </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="">
34363
33999
  }
34364
- </div>
34365
- <div class="setting-part-container">
34366
- <mat-form-field class="third-width">
34367
- <mat-label [textContent]="'ENVIRONMENT_LIGHT' | localize"></mat-label>
34368
- <input
34369
- [type]="'number'"
34370
- matInput
34371
- [(ngModel)]="hdriIntensity"
34372
- (ngModelChange)="hdriIntensity = +$event">
34373
- </mat-form-field>
34374
- <div class="setting-part-buttons">
34375
- <button class="amount-button" (click)="hdriIntensity = +hdriIntensity - 1">
34376
- <co-icon [iconData]="iconService.getIcon(icons.CircleMinusLight)"></co-icon>
34377
- </button>
34378
- <button class="amount-button" (click)="hdriIntensity = +hdriIntensity + 1">
34379
- <co-icon [iconData]="iconService.getIcon(icons.CirclePlusLight)"></co-icon>
34380
- </button>
34381
- </div>
34382
- <div class="setting-part-slider">
34383
- <mat-slider class="value" min="1" max="20" step="1" [(ngModel)]="hdriIntensity"></mat-slider>
34384
- </div>
34385
- </div>
34386
- <div class="setting-part-container">
34387
- <mat-form-field class="third-width">
34388
- <mat-label [textContent]="'ROTATION' | localize"></mat-label>
34389
- <input
34390
- [type]="'number'"
34391
- matInput
34392
- [(ngModel)]="hdriRotation"
34393
- (ngModelChange)="hdriRotation = +$event">
34394
- </mat-form-field>
34395
- <div class="setting-part-buttons">
34396
- <button class="amount-button" (click)="hdriRotation = +hdriRotation - 1">
34397
- <co-icon [iconData]="iconService.getIcon(icons.CircleMinusLight)"></co-icon>
34398
- </button>
34399
- <button class="amount-button" (click)="hdriRotation = +hdriRotation + 1">
34400
- <co-icon [iconData]="iconService.getIcon(icons.CirclePlusLight)"></co-icon>
34401
- </button>
34000
+ @if (!blenderPreviewRender) {
34001
+ <div class="render-popup-preview-placeholder">
34002
+ <span>{{ 'PREVIEW' | localize }}</span>
34402
34003
  </div>
34403
- <div class="setting-part-slider">
34404
- <mat-slider class="value" min="0" max="360" step="1" [(ngModel)]="hdriRotation"></mat-slider>
34405
- </div>
34406
- </div>
34407
- <div class="setting-part-container">
34408
- <mat-form-field class="third-width">
34409
- <mat-label [textContent]="'LIGHTS' | localize"></mat-label>
34410
- <input
34411
- [type]="'number'"
34412
- matInput
34413
- [(ngModel)]="lightingExposure"
34414
- (ngModelChange)="lightingExposure = +$event">
34415
- </mat-form-field>
34416
- <div class="setting-part-buttons">
34417
- <button class="amount-button" (click)="lightingExposure = +lightingExposure - 1">
34418
- <co-icon [iconData]="iconService.getIcon(icons.CircleMinusLight)"></co-icon>
34419
- </button>
34420
- <button class="amount-button" (click)="lightingExposure = +lightingExposure + 1">
34421
- <co-icon [iconData]="iconService.getIcon(icons.CirclePlusLight)"></co-icon>
34422
- </button>
34423
- </div>
34424
- <div class="setting-part-slider">
34425
- <mat-slider class="value" min="1" max="10" step="1" [(ngModel)]="lightingExposure"></mat-slider>
34426
- </div>
34427
- </div>
34428
- </div>
34429
34004
  }
34430
- </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>
34431
34105
  }
34432
- @if (renderService.serverData.renderMode === renderModes.RenderRoom) {
34433
- <div class="render-popup-dropdown">
34106
+ <div class="render-popup-dropdown">
34434
34107
  <mat-form-field class="face-select-form">
34435
- <mat-label>{{ "IMAGE_SIZE" | localize }}</mat-label>
34436
- <mat-select [(ngModel)]="renderService.selectedImageSize">
34437
- @for (size of renderService.imageSizes; track size) {
34438
- <mat-option [value]="size.id">{{ size.name }} {{ size.width }}
34439
- x{{ size.height }}
34440
- </mat-option>
34441
- }
34442
- </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>
34443
34116
  </mat-form-field>
34444
- </div>
34445
- }
34117
+ </div>
34446
34118
  <div class="render-popup-button-container">
34447
- <button class="render-popup-button photo-button"
34448
- (click)="createBlenderRender()"
34449
- title="{{'MAKE_A_PICTURE' | localize}}"
34450
- [disabled]="disablePictureButton">
34451
- <co-icon [iconData]="iconService.getIcon(icons.CircleCheck)"></co-icon>
34452
- {{ 'MAKE_A_PICTURE' | localize }}
34453
- </button>
34454
- <button
34455
- class="render-popup-button cancel-button"
34456
- (click)="resetBlenderRenderScene()">
34457
- <co-icon [iconData]="iconService.getIcon(icons.CircleXmark)"></co-icon>
34458
- {{ 'CLOSE_PHOTO_MODE' | localize }}
34459
- </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>
34460
34132
  </div>
34461
- </div>
34462
- }
34463
- @if (showCullingErrorDialog) {
34464
- <div class="render-warning">
34133
+ </div>
34134
+ }
34135
+ @if (showCullingErrorDialog) {
34136
+ <div class="render-warning">
34465
34137
  <div class="render-warming-header">
34466
- <h2>{{ 'BLENDER_RENDER_ERROR_TITLE' | localize }}</h2>
34467
- <div class="render-warning-close" (click)="showCullingErrorDialog = false">
34468
- <mat-icon class="homedecorator-material-icons">cancel</mat-icon>
34469
- </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>
34470
34142
  </div>
34471
34143
  <div class="render-warning-body">
34472
- <p>{{ 'BLENDER_RENDER_WARNING_CULLING' | localize }}</p>
34144
+ <p>{{ 'BLENDER_RENDER_WARNING_CULLING' | localize }}</p>
34473
34145
  </div>
34474
34146
  <div class="render-warning-footer">
34475
- <button
34476
- class="render-popup-button cancel-button"
34477
- (click)="showCullingErrorDialog = false">
34478
- <co-icon [iconData]="iconService.getIcon(icons.CircleXmark)"></co-icon>
34479
- {{ 'CLOSE' | localize }}
34480
- </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>
34481
34153
  </div>
34482
- </div>
34483
- }
34484
- <rp-render-progress
34485
- [title]="'PREPARE_TO_RENDER' | localize"
34486
- [show]="startUploading"
34487
- >
34488
- </rp-render-progress>
34489
- <button
34490
- #renderButton
34491
- mat-raised-button
34492
- matTooltip="{{'RENDER_TAKE_A_PICTURE' | localize}}"
34493
- [id]="'standalone_render_picture'"
34494
- [class.active]="(
34495
- (renderService.serverData.renderMode === renderService.renderModes.RenderRoom && viewModeService.viewMode === viewModes.WalkThrough) ||
34496
- (renderService.serverData.renderMode === renderService.renderModes.RenderIone))"
34497
- (click)="showRenderForm($event)"
34498
- >
34499
- <mat-icon class="icon homedecorator-material-icons"
34500
- aria-hidden="true">{{ (renderService.currentQueueRenderItem.renderStatus === renderStatus.IsRunning ? 'open_in_browser' : 'photo_camera') }}
34501
- </mat-icon>
34502
- </button>
34503
- </div>
34154
+ </div>
34504
34155
  }
34505
-
34506
- `, 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"] }]
34507
- }], 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: [{
34508
34170
  type: ViewChild,
34509
34171
  args: ['renderButton']
34510
34172
  }] } });
@@ -36472,11 +36134,6 @@ class FloorplannerComponent {
36472
36134
  this._lastNode = null;
36473
36135
  this._subs = [];
36474
36136
  this._selectedFloor = null;
36475
- this._diagramBackgroundScale = 1;
36476
- this._diagramBackgroundCurrentScale = 100;
36477
- this._diagramBackgroundActiveZoom = false;
36478
- this._diagramBackgroundAlpha = 0.5;
36479
- this._showDiagramBackground = true;
36480
36137
  this._readyToDraw = false;
36481
36138
  this._needsRedraw = false;
36482
36139
  Object.keys(this._configToSync).forEach((key) => {
@@ -36509,7 +36166,7 @@ class FloorplannerComponent {
36509
36166
  const dataUrl = this._canvas.toDataURL('image/jpeg');
36510
36167
  FileUtils.DownloadFromDataUri(dataUrl, `MyRoomplan${new Date().toISOString()}.jpeg`);
36511
36168
  }
36512
- }), 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()));
36513
36170
  this.touchMode = this._configurationService.getValue(ConfigurationKey.EnableTouch);
36514
36171
  this.currentDimensioning = this._configurationService.getValue(ConfigurationKey.DimensioningUnit);
36515
36172
  this.currentRoundingDecimals = this._configurationService.getValue(ConfigurationKey.RoundingDecimals);
@@ -36573,10 +36230,13 @@ class FloorplannerComponent {
36573
36230
  this._draw();
36574
36231
  });
36575
36232
  }
36576
- showStartMessage() {
36577
- if (this._diagramBackground) {
36578
- this._diagramBackground.src = '';
36233
+ _clearBackground() {
36234
+ if (this._renderService.diagramBackground) {
36235
+ this._renderService.diagramBackground = undefined;
36579
36236
  }
36237
+ }
36238
+ showStartMessage() {
36239
+ this._clearBackground();
36580
36240
  this._bluePrintService.reset();
36581
36241
  this.showStartingMessages = true;
36582
36242
  this._requestDraw();
@@ -36602,10 +36262,9 @@ class FloorplannerComponent {
36602
36262
  if (!this._coordinatesService.canZoomIn) {
36603
36263
  return;
36604
36264
  }
36605
- this._clear();
36606
36265
  this._coordinatesService.zoomIn();
36607
- this._diagramBackgroundScale *= this._coordinatesService.scalingFactor;
36608
- this._diagramBackgroundActiveZoom = true;
36266
+ this._renderService.diagramBackgroundScale *= this._coordinatesService.scalingFactor;
36267
+ this._renderService.diagramBackgroundActiveZoom = true;
36609
36268
  this._scale(this._coordinatesService.scalingFactor, this._coordinatesService.scalingFactor);
36610
36269
  this.resizeView();
36611
36270
  this._requestDraw();
@@ -36614,16 +36273,14 @@ class FloorplannerComponent {
36614
36273
  if (!this._coordinatesService.canZoomOut) {
36615
36274
  return;
36616
36275
  }
36617
- this._clear();
36618
36276
  this._coordinatesService.zoomOut();
36619
- this._diagramBackgroundScale *= (1 / this._coordinatesService.scalingFactor);
36620
- this._diagramBackgroundActiveZoom = true;
36277
+ this._renderService.diagramBackgroundScale *= (1 / this._coordinatesService.scalingFactor);
36278
+ this._renderService.diagramBackgroundActiveZoom = true;
36621
36279
  this._scale(1 / this._coordinatesService.scalingFactor, 1 / this._coordinatesService.scalingFactor);
36622
36280
  this.resizeView();
36623
36281
  this._requestDraw();
36624
36282
  }
36625
36283
  zoomReset() {
36626
- this._clear();
36627
36284
  this._scale(1 / this._viewScale, 1 / this._viewScale);
36628
36285
  this.reset();
36629
36286
  }
@@ -36968,15 +36625,15 @@ class FloorplannerComponent {
36968
36625
  this._coordinatesService.resetOrigin();
36969
36626
  this._viewScale = 100;
36970
36627
  this._bluePrintService.reset();
36971
- this._diagramBackground = input.background;
36972
- this._diagramBackgroundHeight = input.backgroundHeight;
36973
- this._diagramBackgroundWidth = input.backgroundWidth;
36974
- 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;
36975
36632
  this._cameraZoom = input.cameraZoom;
36976
36633
  this._requestDraw();
36977
36634
  }
36978
36635
  toggleDiagram() {
36979
- this._showDiagramBackground = !this._showDiagramBackground;
36636
+ this._renderService.showDiagramBackground = !this._renderService.showDiagramBackground;
36980
36637
  this._requestDraw();
36981
36638
  }
36982
36639
  _removeWall() {
@@ -37050,23 +36707,6 @@ class FloorplannerComponent {
37050
36707
  await this._bluePrintService.update();
37051
36708
  this._requestDraw();
37052
36709
  }
37053
- _drawBackground() {
37054
- if (this._diagramBackgroundActiveZoom) {
37055
- if (this._diagramBackgroundCurrentScale <= this._viewScale) {
37056
- this._diagramBackgroundWidth = this._diagramBackgroundWidth * this._coordinatesService.scalingFactor;
37057
- this._diagramBackgroundHeight = this._diagramBackgroundHeight * this._coordinatesService.scalingFactor;
37058
- }
37059
- else {
37060
- this._diagramBackgroundWidth = this._diagramBackgroundWidth * (1 / this._coordinatesService.scalingFactor);
37061
- this._diagramBackgroundHeight = this._diagramBackgroundHeight * (1 / this._coordinatesService.scalingFactor);
37062
- }
37063
- this._diagramBackgroundActiveZoom = false;
37064
- }
37065
- this._diagramBackgroundCurrentScale = this._viewScale;
37066
- this._context.globalAlpha = this._diagramBackgroundAlpha;
37067
- 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);
37068
- this._context.globalAlpha = 1;
37069
- }
37070
36710
  _handleWindowResize() {
37071
36711
  if (this._canvas) {
37072
36712
  const parent = this._canvas.parentElement;
@@ -37079,11 +36719,6 @@ class FloorplannerComponent {
37079
36719
  this._requestDraw();
37080
36720
  }
37081
36721
  }
37082
- _clear() {
37083
- if (this._context && this._canvas) {
37084
- this._context.clearRect(0, 0, this._canvas.width, this._canvas.height);
37085
- }
37086
- }
37087
36722
  _updateWallPosition() {
37088
36723
  if (this._wallLength) {
37089
36724
  const startPoint = this._lastNode;
@@ -46528,7 +46163,7 @@ class DrawDialogComponent {
46528
46163
  this.customerInputLenght = this.inputLength.nativeElement.value;
46529
46164
  }
46530
46165
  handleMouseDown(event) {
46531
- if (this.draftingMode === 'movement') {
46166
+ if (event.button === 2) { // right mouse button -> drag
46532
46167
  this.isDragging = true;
46533
46168
  this.dragStart.x = this.getEventLocation(event).x / this.cameraZoom - this.cameraOffset.x;
46534
46169
  this.dragStart.y = this.getEventLocation(event).y / this.cameraZoom - this.cameraOffset.y;
@@ -46541,11 +46176,9 @@ class DrawDialogComponent {
46541
46176
  }
46542
46177
  }
46543
46178
  handleMouseMove(event) {
46544
- if (this.draftingMode === 'movement') {
46545
- if (this.isDragging) {
46546
- this.cameraOffset.x = this.getEventLocation(event).x / this.cameraZoom - this.dragStart.x;
46547
- this.cameraOffset.y = this.getEventLocation(event).y / this.cameraZoom - this.dragStart.y;
46548
- }
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;
46549
46182
  }
46550
46183
  }
46551
46184
  handleMouseUp(event) {
@@ -46555,22 +46188,6 @@ class DrawDialogComponent {
46555
46188
  }
46556
46189
  handleMouseLeave(event) {
46557
46190
  }
46558
- clickingZoom(option) {
46559
- const zoomIn = -0.5;
46560
- const zoomOut = 0.5;
46561
- const zoomReset = 1;
46562
- if (option === 'in') {
46563
- this.cameraZoom -= zoomIn;
46564
- }
46565
- else if (option === 'out') {
46566
- this.cameraZoom -= zoomOut;
46567
- }
46568
- else if (option === 'reset') {
46569
- this.cameraZoom = zoomReset;
46570
- }
46571
- this.cameraZoom = Math.min(this.cameraZoom, this.maxZoom);
46572
- this.cameraZoom = Math.max(this.cameraZoom, this.minZoom);
46573
- }
46574
46191
  handleMouseWheel(event) {
46575
46192
  const zoomAmount = event.deltaY * this.scrollSensitivity;
46576
46193
  if (!this.isDragging) {
@@ -46581,6 +46198,9 @@ class DrawDialogComponent {
46581
46198
  this.cameraZoom = Math.max(this.cameraZoom, this.minZoom);
46582
46199
  }
46583
46200
  }
46201
+ handleContextMenu(event) {
46202
+ return false;
46203
+ }
46584
46204
  getEventLocation(e) {
46585
46205
  if (e.touches && e.touches.length === 1) {
46586
46206
  return { x: e.touches[0].clientX, y: e.touches[0].clientY };
@@ -46664,11 +46284,11 @@ class DrawDialogComponent {
46664
46284
  return new Vector2(canvasX, canvasY);
46665
46285
  }
46666
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 }); }
46667
- 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" }] }); }
46668
46288
  }
46669
46289
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DrawDialogComponent, decorators: [{
46670
46290
  type: Component,
46671
- 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"] }]
46672
46292
  }], ctorParameters: () => [{ type: undefined, decorators: [{
46673
46293
  type: Inject,
46674
46294
  args: [MAT_DIALOG_DATA]
@@ -48273,7 +47893,7 @@ class ToolbarComponent {
48273
47893
  this.leftSidebar.close();
48274
47894
  }
48275
47895
  }
48276
- 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 }); }
48277
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: `
48278
47898
  <!--
48279
47899
  <div class="layer layer&#45;&#45;toolbar">
@@ -48803,7 +48423,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
48803
48423
  ])
48804
48424
  ] /*,
48805
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"] }]
48806
- }], 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: [{
48807
48427
  type: Output
48808
48428
  }], leftSidebar: [{
48809
48429
  type: ViewChild,
@@ -48984,28 +48604,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
48984
48604
  args: ['fileUpload']
48985
48605
  }] } });
48986
48606
 
48987
- // A pipe for appending strings to other strings in view templates.
48988
- class AppendPipe {
48989
- transform(value, append) {
48990
- if (!value) {
48991
- return '';
48992
- }
48993
- if (!append) {
48994
- return value;
48995
- }
48996
- return value + append;
48997
- }
48998
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AppendPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
48999
- static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.3.16", ngImport: i0, type: AppendPipe, isStandalone: false, name: "append" }); }
49000
- }
49001
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AppendPipe, decorators: [{
49002
- type: Pipe,
49003
- args: [{
49004
- name: 'append',
49005
- standalone: false
49006
- }]
49007
- }] });
49008
-
49009
48607
  class ProductCatalogComponent {
49010
48608
  get shown() {
49011
48609
  return this._showCatalog;
@@ -49428,7 +49026,7 @@ class HomedecoratorComponent {
49428
49026
  return this._settings;
49429
49027
  }
49430
49028
  constructor(appService, // don't remove this, needs to be created on a high level
49431
- 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) {
49432
49030
  this.appService = appService;
49433
49031
  this.controllerService = controllerService;
49434
49032
  this.appState = appState;
@@ -49443,6 +49041,7 @@ class HomedecoratorComponent {
49443
49041
  this._integrationService = _integrationService;
49444
49042
  this._sceneService = _sceneService;
49445
49043
  this._webWorkerService = _webWorkerService;
49044
+ this._injector = _injector;
49446
49045
  this.generalFilterOrders = [
49447
49046
  { name: 'CATEGORY', order: 1 },
49448
49047
  { name: 'TURNOVER_GROUP', order: 2 },
@@ -49528,6 +49127,7 @@ class HomedecoratorComponent {
49528
49127
  // };
49529
49128
  this._subs = [];
49530
49129
  this._initCommunication = false;
49130
+ ServiceLocator.injector = this._injector;
49531
49131
  this._eventService = _parentEventService || _ownEventService;
49532
49132
  this._webWorkerService.initWorkers();
49533
49133
  }
@@ -49646,7 +49246,7 @@ class HomedecoratorComponent {
49646
49246
  _initConnection() {
49647
49247
  this._homedecoratorService.init(this._settings);
49648
49248
  }
49649
- 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 }); }
49650
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: [
49651
49251
  APPLICATION_SERVICES_PROVIDERS
49652
49252
  ], ngImport: i0, template: `
@@ -49740,7 +49340,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
49740
49340
  type: Optional
49741
49341
  }, {
49742
49342
  type: Self
49743
- }] }, { type: IntegrationService }, { type: SceneService }, { type: WebWorkerService }], propDecorators: { generalFilterOrders: [{
49343
+ }] }, { type: IntegrationService }, { type: SceneService }, { type: WebWorkerService }, { type: i0.Injector }], propDecorators: { generalFilterOrders: [{
49744
49344
  type: Input
49745
49345
  }], purchaseFilterOrders: [{
49746
49346
  type: Input
@@ -52558,11 +52158,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
52558
52158
  }] });
52559
52159
 
52560
52160
  class HomedecoratorModule {
52561
- constructor(_injector) {
52562
- this._injector = _injector;
52563
- ServiceLocator.injector = this._injector;
52564
- }
52565
- 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 }); }
52566
52162
  static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.16", ngImport: i0, type: HomedecoratorModule, bootstrap: [HomedecoratorComponent], declarations: [HomedecoratorComponent], imports: [CommonModule,
52567
52163
  ProgressBarModule,
52568
52164
  LoadingOverlayModule,
@@ -52611,7 +52207,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
52611
52207
  ],
52612
52208
  bootstrap: [HomedecoratorComponent]
52613
52209
  }]
52614
- }], ctorParameters: () => [{ type: i0.Injector }] });
52210
+ }] });
52615
52211
 
52616
52212
  class MaterialBuilderComponent {
52617
52213
  set settings(value) {