From 3a9f95538863b0139657e5ceb11b493532b55642 Mon Sep 17 00:00:00 2001
From: psychedelicious <4822129+psychedelicious@users.noreply.github.com>
Date: Wed, 31 Jul 2024 15:06:46 +1000
Subject: [PATCH] feat(ui): add `repr` methods to layer and object classes

---
 .../controlLayers/konva/CanvasBrushLine.ts    | 20 +++++++++++++++-
 .../controlLayers/konva/CanvasEraserLine.ts   | 20 +++++++++++++++-
 .../controlLayers/konva/CanvasImage.ts        | 21 ++++++++++++++++
 .../controlLayers/konva/CanvasLayer.ts        | 24 +++++++++++++------
 .../controlLayers/konva/CanvasRect.ts         | 20 +++++++++++++++-
 5 files changed, 95 insertions(+), 10 deletions(-)

diff --git a/invokeai/frontend/web/src/features/controlLayers/konva/CanvasBrushLine.ts b/invokeai/frontend/web/src/features/controlLayers/konva/CanvasBrushLine.ts
index c052a55775..794ce82b17 100644
--- a/invokeai/frontend/web/src/features/controlLayers/konva/CanvasBrushLine.ts
+++ b/invokeai/frontend/web/src/features/controlLayers/konva/CanvasBrushLine.ts
@@ -1,4 +1,5 @@
 import { rgbaColorToString } from 'common/util/colorCodeTransformers';
+import { deepClone } from 'common/util/deepClone';
 import type { CanvasLayer } from 'features/controlLayers/konva/CanvasLayer';
 import type { BrushLine } from 'features/controlLayers/store/types';
 import Konva from 'konva';
@@ -52,7 +53,7 @@ export class CanvasBrushLine {
     this.state = state;
   }
 
-  async update(state: BrushLine, force?: boolean): Promise<boolean> {
+  update(state: BrushLine, force?: boolean): boolean {
     if (force || this.state !== state) {
       this.parent._log.trace(`Updating brush line ${this.id}`);
       const { points, color, clip, strokeWidth } = state;
@@ -74,4 +75,21 @@ export class CanvasBrushLine {
     this.parent._log.trace(`Destroying brush line ${this.id}`);
     this.konva.group.destroy();
   }
+
+  show() {
+    this.konva.group.visible(true);
+  }
+
+  hide() {
+    this.konva.group.visible(false);
+  }
+
+  repr() {
+    return {
+      id: this.id,
+      type: this.type,
+      parent: this.parent.id,
+      state: deepClone(this.state),
+    };
+  }
 }
diff --git a/invokeai/frontend/web/src/features/controlLayers/konva/CanvasEraserLine.ts b/invokeai/frontend/web/src/features/controlLayers/konva/CanvasEraserLine.ts
index a1d8d19311..7ba26b02f9 100644
--- a/invokeai/frontend/web/src/features/controlLayers/konva/CanvasEraserLine.ts
+++ b/invokeai/frontend/web/src/features/controlLayers/konva/CanvasEraserLine.ts
@@ -1,4 +1,5 @@
 import { rgbaColorToString } from 'common/util/colorCodeTransformers';
+import { deepClone } from 'common/util/deepClone';
 import type { CanvasLayer } from 'features/controlLayers/konva/CanvasLayer';
 import type { EraserLine } from 'features/controlLayers/store/types';
 import { RGBA_RED } from 'features/controlLayers/store/types';
@@ -53,7 +54,7 @@ export class CanvasEraserLine {
     this.state = state;
   }
 
-  async update(state: EraserLine, force?: boolean): Promise<boolean> {
+  update(state: EraserLine, force?: boolean): boolean {
     if (force || this.state !== state) {
       this.parent._log.trace(`Updating eraser line ${this.id}`);
       const { points, clip, strokeWidth } = state;
@@ -74,4 +75,21 @@ export class CanvasEraserLine {
     this.parent._log.trace(`Destroying eraser line ${this.id}`);
     this.konva.group.destroy();
   }
+
+  show() {
+    this.konva.group.visible(true);
+  }
+
+  hide() {
+    this.konva.group.visible(false);
+  }
+
+  repr() {
+    return {
+      id: this.id,
+      type: this.type,
+      parent: this.parent.id,
+      state: deepClone(this.state),
+    };
+  }
 }
diff --git a/invokeai/frontend/web/src/features/controlLayers/konva/CanvasImage.ts b/invokeai/frontend/web/src/features/controlLayers/konva/CanvasImage.ts
index 91650fef60..9fb722a3bc 100644
--- a/invokeai/frontend/web/src/features/controlLayers/konva/CanvasImage.ts
+++ b/invokeai/frontend/web/src/features/controlLayers/konva/CanvasImage.ts
@@ -1,3 +1,4 @@
+import { deepClone } from 'common/util/deepClone';
 import type { CanvasLayer } from 'features/controlLayers/konva/CanvasLayer';
 import { FILTER_MAP } from 'features/controlLayers/konva/filters';
 import { loadImage } from 'features/controlLayers/konva/util';
@@ -157,4 +158,24 @@ export class CanvasImage {
     this.parent._log.trace(`Destroying image ${this.id}`);
     this.konva.group.destroy();
   }
+
+  show() {
+    this.konva.group.visible(true);
+  }
+
+  hide() {
+    this.konva.group.visible(false);
+  }
+
+  repr() {
+    return {
+      id: this.id,
+      type: this.type,
+      parent: this.parent.id,
+      imageName: this.imageName,
+      isLoading: this.isLoading,
+      isError: this.isError,
+      state: deepClone(this.state),
+    };
+  }
 }
diff --git a/invokeai/frontend/web/src/features/controlLayers/konva/CanvasLayer.ts b/invokeai/frontend/web/src/features/controlLayers/konva/CanvasLayer.ts
index d6f9197438..7cf905053c 100644
--- a/invokeai/frontend/web/src/features/controlLayers/konva/CanvasLayer.ts
+++ b/invokeai/frontend/web/src/features/controlLayers/konva/CanvasLayer.ts
@@ -655,14 +655,24 @@ export class CanvasLayer {
     );
   }, CanvasManager.BBOX_DEBOUNCE_MS);
 
-  logDebugInfo(msg = 'Debug info') {
-    const debugInfo = {
+  repr() {
+    return {
       id: this.id,
-      state: this._state,
-      rect: this.rect,
-      bbox: this.bbox,
-      objects: Array.from(this.objects.values()).map((obj) => obj.id),
+      type: 'layer',
+      state: deepClone(this._state),
+      rect: deepClone(this.rect),
+      bbox: deepClone(this.bbox),
+      bboxNeedsUpdate: this._bboxNeedsUpdate,
+      isFirstRender: this._isFirstRender,
       isTransforming: this.isTransforming,
+      isPendingBboxCalculation: this.isPendingBboxCalculation,
+      objects: Array.from(this.objects.values()).map((obj) => obj.repr()),
+    };
+  }
+
+  logDebugInfo(msg = 'Debug info') {
+    const info = {
+      repr: this.repr(),
       interactionRectAttrs: {
         x: this.konva.interactionRect.x(),
         y: this.konva.interactionRect.y(),
@@ -684,6 +694,6 @@ export class CanvasLayer {
         offsetY: this.konva.objectGroup.offsetY(),
       },
     };
-    this._log.debug(debugInfo, msg);
+    this._log.trace(info, msg);
   }
 }
diff --git a/invokeai/frontend/web/src/features/controlLayers/konva/CanvasRect.ts b/invokeai/frontend/web/src/features/controlLayers/konva/CanvasRect.ts
index 47386717b1..13d1ef1d65 100644
--- a/invokeai/frontend/web/src/features/controlLayers/konva/CanvasRect.ts
+++ b/invokeai/frontend/web/src/features/controlLayers/konva/CanvasRect.ts
@@ -1,4 +1,5 @@
 import { rgbaColorToString } from 'common/util/colorCodeTransformers';
+import { deepClone } from 'common/util/deepClone';
 import type { CanvasLayer } from 'features/controlLayers/konva/CanvasLayer';
 import type { RectShape } from 'features/controlLayers/store/types';
 import Konva from 'konva';
@@ -45,7 +46,7 @@ export class CanvasRect {
     this.state = state;
   }
 
-  async update(state: RectShape, force?: boolean): Promise<boolean> {
+  update(state: RectShape, force?: boolean): boolean {
     if (this.state !== state || force) {
       this.parent._log.trace(`Updating rect ${this.id}`);
       const { x, y, width, height, color } = state;
@@ -67,4 +68,21 @@ export class CanvasRect {
     this.parent._log.trace(`Destroying rect ${this.id}`);
     this.konva.group.destroy();
   }
+
+  show() {
+    this.konva.group.visible(true);
+  }
+
+  hide() {
+    this.konva.group.visible(false);
+  }
+
+  repr() {
+    return {
+      id: this.id,
+      type: this.type,
+      parent: this.parent.id,
+      state: deepClone(this.state),
+    };
+  }
 }