From 3747a657ab6e277ac54f79ca1ae975f95bc1c193 Mon Sep 17 00:00:00 2001 From: Dhairya Jangir <183471878+dhairyajangir@users.noreply.github.com> Date: Tue, 6 Oct 2026 00:39:51 +0530 Subject: [PATCH] fix(event-display): restore cell color when disabling selection Restore the original color of a hovered instanced calorimeter cell when selection is disabled. Reuse the existing cleanup helper so the color attribute is marked for an update and cached instance state is cleared. Add regression cases for instance indices zero and one, checking color restoration, neighboring-cell preservation and the update notification. --- .../three-manager/selection-manager.ts | 1 + .../three-manager/selection-manager.test.ts | 67 ++++++++++++++++++- 2 files changed, 67 insertions(+), 1 deletion(-) diff --git a/packages/phoenix-event-display/src/managers/three-manager/selection-manager.ts b/packages/phoenix-event-display/src/managers/three-manager/selection-manager.ts index 3f5103fb0..664277d6d 100644 --- a/packages/phoenix-event-display/src/managers/three-manager/selection-manager.ts +++ b/packages/phoenix-event-display/src/managers/three-manager/selection-manager.ts @@ -511,6 +511,7 @@ export class SelectionManager { this.selectionIsDragging = false; // Clear all outlines and selections + this.clearInstanceHighlight(); this.effectsManager.clearAllSelections(); this.effectsManager.setHoverOutline(null); this.selectedObjects.clear(); diff --git a/packages/phoenix-event-display/src/tests/managers/three-manager/selection-manager.test.ts b/packages/phoenix-event-display/src/tests/managers/three-manager/selection-manager.test.ts index 1721d011c..a5cb15185 100644 --- a/packages/phoenix-event-display/src/tests/managers/three-manager/selection-manager.test.ts +++ b/packages/phoenix-event-display/src/tests/managers/three-manager/selection-manager.test.ts @@ -3,7 +3,17 @@ */ import { InfoLogger } from '../../../helpers/info-logger'; import { EffectsManager } from '../../../managers/three-manager/effects-manager'; -import { Object3D, PerspectiveCamera, Scene, Vector2, Vector3 } from 'three'; +import { + BoxGeometry, + Color, + InstancedMesh, + MeshBasicMaterial, + Object3D, + PerspectiveCamera, + Scene, + Vector2, + Vector3, +} from 'three'; import { SelectionManager } from '../../../managers/three-manager/selection-manager'; import THREE from '../../helpers/webgl-mock'; @@ -67,6 +77,61 @@ describe('SelectionManager', () => { expect(activeObj['callbacks']).toEqual([]); }); + it.each([0, 1])( + 'should restore hovered cell %i when selection is disabled', + (instanceId) => { + const canvas = document.createElement('canvas'); + canvas.id = 'three-canvas'; + document.body.appendChild(canvas); + const camera = new PerspectiveCamera(); + const scene = new Scene(); + const effectsManager = new EffectsManager( + camera, + scene, + new THREE.WebGLRenderer(), + ); + const geometry = new BoxGeometry(); + const material = new MeshBasicMaterial(); + const cells = new InstancedMesh(geometry, material, 2); + cells.setColorAt(0, new Color(1, 0, 0)); + cells.setColorAt(1, new Color(0, 1, 0)); + cells.userData = { + _isInstancedCaloCells: true, + _lastHitInstanceId: instanceId, + }; + const originalColors = cells.instanceColor.array.slice(); + + selectionManager.init( + () => ({ object: camera }), + undefined, + undefined, + scene, + effectsManager, + new InfoLogger(), + ); + selectionManager.setSelectedObject({ name: '', attributes: [] }); + + try { + selectionManager.setSelecting(true); + selectionManager.applyIntersectionResult(cells); + const hoveredColor = new Color(); + cells.getColorAt(instanceId, hoveredColor); + expect(hoveredColor).toEqual(new Color(1, 1, 1)); + const highlightedVersion = cells.instanceColor.version; + + selectionManager.setSelecting(false); + + expect(cells.instanceColor.array).toEqual(originalColors); + expect(cells.instanceColor.version).toBeGreaterThan(highlightedVersion); + } finally { + selectionManager.cleanup(); + canvas.remove(); + geometry.dispose(); + material.dispose(); + } + }, + ); + it('should set if selecting is to be enabled or disabled', () => { jest.spyOn(selectionManagerPrivate, 'enableSelecting'); selectionManager['isInit'] = true;