Skip to content

Commit cbdb99e

Browse files
committed
fix: repair color to pull entirely from state, no cache in ProbeManager
1 parent 8d2c860 commit cbdb99e

File tree

3 files changed

+117
-81
lines changed

3 files changed

+117
-81
lines changed

Assets/Scripts/Pinpoint/Probes/ProbeManager.cs

Lines changed: 60 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public class ProbeManager : MonoBehaviour
4848

4949
// Static events
5050
public static readonly UnityEvent<HashSet<ProbeManager>> EphysLinkControlledProbesChangedEvent =
51-
new();
51+
new();
5252
public static readonly UnityEvent ActiveProbeUIUpdateEvent = new();
5353
#endregion
5454

@@ -145,7 +145,7 @@ public static string[] GetAllChannelAnnotationData()
145145
private Vector3 _recRegionTopCoordWorldU;
146146

147147
public (Vector3 tipCoordU, Vector3 endCoordU) RecRegionCoordWorldU =>
148-
(_recRegionBaseCoordWorldU, _recRegionTopCoordWorldU);
148+
(_recRegionBaseCoordWorldU, _recRegionTopCoordWorldU);
149149

150150
// Text
151151
private const float minYaw = -180;
@@ -187,7 +187,7 @@ public bool Locked
187187
}
188188

189189
public ManipulatorBehaviorController ManipulatorBehaviorController =>
190-
gameObject.GetComponent<ManipulatorBehaviorController>();
190+
gameObject.GetComponent<ManipulatorBehaviorController>();
191191

192192
public bool IsEphysLinkControlled
193193
{
@@ -198,31 +198,28 @@ private set
198198
EphysLinkControlChangeEvent.Invoke();
199199
EphysLinkControlledProbesChangedEvent.Invoke(
200200
Instances.Where(manager => manager.IsEphysLinkControlled).ToHashSet()
201-
);
201+
);
202202
}
203203
}
204204

205205
public string APITarget { get; set; }
206206

207-
private Color _color;
207+
/// <summary>
208+
/// Get the probe color from Redux state. This property is read-only and should not be used to set color.
209+
/// To set color, dispatch SceneActions.SET_PROBE_COLOR to Redux.
210+
/// </summary>
208211
public Color Color
209212
{
210-
get => _color;
211-
set
213+
get
212214
{
213-
// try to return the current color
214-
ProbeProperties.ReturnColor(_color);
215-
216-
_color = value;
217-
_probeRenderer.material.color = _color;
218-
219-
foreach (ProbeUIManager puiManager in _probeUIManagers)
220-
puiManager.UpdateColors();
221-
222-
UIUpdateEvent.Invoke();
223-
if (ActiveProbeManager == this)
224-
ActiveProbeUIUpdateEvent.Invoke();
225-
Debug.Log(_color);
215+
#if APP_UI
216+
if (_probeStateCache != null)
217+
{
218+
return _probeStateCache.ColorValue;
219+
}
220+
#endif
221+
// Fallback to renderer color if state not available
222+
return _probeRenderer != null ? _probeRenderer.material.color : Color.white;
226223
}
227224
}
228225

@@ -259,10 +256,6 @@ private async void Awake()
259256
UUID = Guid.NewGuid().ToString();
260257
UpdateName();
261258

262-
// Set color
263-
if (_probeRenderer != null)
264-
_color = ProbeProperties.NextColor;
265-
266259
// Record default materials
267260
_defaultMaterials = new Dictionary<GameObject, Material>();
268261
_activeRenderers = new();
@@ -299,11 +292,6 @@ private void Start()
299292
#if UNITY_EDITOR
300293
Debug.Log($"(ProbeManager) New probe created with UUID: {UUID}");
301294
#endif
302-
// Force update color
303-
foreach (ProbeUIManager puiManager in _probeUIManagers)
304-
puiManager.UpdateColors();
305-
if (_probeRenderer)
306-
_probeRenderer.material.color = _color;
307295

308296
UIUpdateEvent.Invoke();
309297

@@ -313,18 +301,18 @@ private void Start()
313301
#if APP_UI
314302
// Subscribe to state and initialize properties.
315303
_probeStateSubscription = PinpointApp.StoreServiceStore.Subscribe(
316-
state =>
304+
state =>
317305
state
318-
.Get<SceneState>(SliceNames.SCENE_SLICE)
319-
.Probes.FirstOrDefault(probeState => probeState.Name == name),
320-
state =>
321-
{
322-
if (state == _probeStateCache) return;
323-
_probeStateCache = state;
324-
OnProbeStateChanged(state);
325-
},
326-
new SubscribeOptions<ProbeState> { fireImmediately = true }
327-
);
306+
.Get<SceneState>(SliceNames.SCENE_SLICE)
307+
.Probes.FirstOrDefault(probeState => probeState.Name == name),
308+
state =>
309+
{
310+
if (state == _probeStateCache) return;
311+
_probeStateCache = state;
312+
OnProbeStateChanged(state);
313+
},
314+
new SubscribeOptions<ProbeState> { fireImmediately = true }
315+
);
328316
#endif
329317
}
330318

@@ -335,8 +323,6 @@ private void Start()
335323
/// </summary>
336324
public void Cleanup()
337325
{
338-
ProbeProperties.ReturnColor(Color);
339-
340326
ColliderManager.RemoveProbeColliderInstances(_probeColliders);
341327

342328
// Force disable Ephys Link
@@ -382,11 +368,22 @@ private async void OnProbeStateChanged(ProbeState state)
382368
// Core Identity.
383369
name = state.Name;
384370

385-
// Probe Configuration.
386-
_probeRenderer.material.color = state.ColorValue;
371+
// Probe Configuration - Update renderer color from state.
372+
if (_probeRenderer != null)
373+
{
374+
_probeRenderer.material.color = state.ColorValue;
375+
}
387376

388377
ProbeDisplay = state.ProbeDisplayType;
389378

379+
// Notify UI managers to update their colors from state.
380+
foreach (ProbeUIManager puiManager in _probeUIManagers)
381+
puiManager.UpdateColors();
382+
383+
UIUpdateEvent.Invoke();
384+
if (ActiveProbeManager == this)
385+
ActiveProbeUIUpdateEvent.Invoke();
386+
390387
// Channel Maps.
391388
await _channelMapLoadedSource.Task;
392389
_channelMap.SetSelectionLayer(state.SelectionLayerName);
@@ -433,8 +430,8 @@ public async Task<ChannelMap> GetChannelMap()
433430
public void Update2ActiveTransform()
434431
{
435432
_probeController.SetSpaceTransform(
436-
BrainAtlasManager.ActiveReferenceAtlas.AtlasSpace,
437-
BrainAtlasManager.ActiveAtlasTransform
433+
BrainAtlasManager.ActiveReferenceAtlas.AtlasSpace,
434+
BrainAtlasManager.ActiveAtlasTransform
438435
);
439436
}
440437

@@ -459,13 +456,13 @@ public void UpdateName()
459456
#if !APP_UI
460457
if (OverrideName != null)
461458
{
462-
name = OverrideName;
463-
}
459+
name = OverrideName;
460+
}
464461
else
465462
{
466463

467464
// Check if this probe is in the brain
468-
name = _probeInBrain ? $"{_probeUIManagers[0].MaxArea}-{UUID[..8]}" : UUID[..8];
465+
name = _probeInBrain ? $"{_probeUIManagers[0].MaxArea}-{UUID[..8]}" : UUID[..8];
469466

470467
}
471468
#endif
@@ -482,11 +479,11 @@ public void ProbeMoved()
482479

483480
// Update the world coordinates for the tip position
484481
Vector3 startCoordWorldT =
485-
_probeController.ProbeTipT.position
486-
+ -_probeController.ProbeTipT.forward * channelCoords.startPosmm;
482+
_probeController.ProbeTipT.position
483+
+ -_probeController.ProbeTipT.forward * channelCoords.startPosmm;
487484
Vector3 endCoordWorldT =
488-
_probeController.ProbeTipT.position
489-
+ -_probeController.ProbeTipT.forward * channelCoords.endPosmm;
485+
_probeController.ProbeTipT.position
486+
+ -_probeController.ProbeTipT.forward * channelCoords.endPosmm;
490487
_recRegionBaseCoordWorldU = BrainAtlasManager.WorldT2WorldU(startCoordWorldT, true);
491488
_recRegionTopCoordWorldU = BrainAtlasManager.WorldT2WorldU(endCoordWorldT, true);
492489
}
@@ -499,7 +496,7 @@ public void ProbeMoved()
499496
private void DispatchProbeWorldState()
500497
{
501498
// Get tip world coordinates
502-
var (tipCoordWorldU, tipRightWorldU, tipUpWorldU, tipForwardWorldU) =
499+
var (tipCoordWorldU, tipRightWorldU, tipUpWorldU, tipForwardWorldU) =
503500
_probeController.GetTipWorldU();
504501

505502
// Get tip position in WorldT
@@ -558,7 +555,7 @@ public async void UpdateSelectionLayer(string selectionLayerName)
558555
/// <summary>
559556
/// Update the channel map data according to the selected channels
560557
/// Defaults to the first 384 channels
561-
///
558+
///
562559
/// Sets channelMinY/channelMaxY in mm
563560
/// </summary>
564561
public void UpdateChannelMap()
@@ -1056,9 +1053,9 @@ public void UpdateSurfacePosition()
10561053
)
10571054
{
10581055
if (BrainAtlasManager.Instance == null || BrainAtlasManager.ActiveReferenceAtlas == null)
1059-
return (new Vector3(float.NaN, float.NaN, float.NaN), false);
1060-
1061-
// note: the backward axis on the probe is the probe's "up" axis
1056+
return (new Vector3(float.NaN, float.NaN, float.NaN), false);
1057+
1058+
// note: the backward axis on the probe is the probe's "up" axis
10621059
(Vector3 tipCoordWorldU, _, _, Vector3 tipForwardWorldU) = _probeController.GetTipWorldU();
10631060

10641061
Vector3 tipAtlasIdxU = BrainAtlasManager.ActiveReferenceAtlas.World2AtlasIdx(
@@ -1135,8 +1132,8 @@ public void UpdateSurfacePosition()
11351132
public Vector3 FindEntryIdxCoordinate(Vector3 bottomIdxCoordU, Vector3 downVector)
11361133
{
11371134
if (BrainAtlasManager.Instance == null || BrainAtlasManager.ActiveReferenceAtlas == null)
1138-
return new Vector3(float.NaN, float.NaN, float.NaN);
1139-
1135+
return new Vector3(float.NaN, float.NaN, float.NaN);
1136+
11401137
float searchDistance =
11411138
BrainAtlasManager.ActiveReferenceAtlas.Dimensions.z
11421139
* 1000f
@@ -1313,7 +1310,7 @@ private void SetMaterialsDefault()
13131310
private void SetMaterialsLine()
13141311
{
13151312
#if UNITY_EDITOR && !APP_UI
1316-
Debug.Log($"Setting materials for {name} to line");
1313+
Debug.Log($"Setting materials for {name} to line");
13171314
#endif
13181315
foreach (var childRenderer in _activeRenderers)
13191316
childRenderer.enabled = false;
@@ -1338,8 +1335,8 @@ private void SetMaterialsLine()
13381335

13391336
var channelData = GetChannelRangemm();
13401337
_lineRenderer.SetPositions(
1341-
new Vector3[] { Vector3.zero, Vector3.up * channelData.fullHeight }
1342-
);
1338+
new Vector3[] { Vector3.zero, Vector3.up * channelData.fullHeight }
1339+
);
13431340
}
13441341
}
13451342

Assets/Scripts/Pinpoint/Probes/UI/ProbeUIManager.cs

Lines changed: 56 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,28 @@
11
using BrainAtlas;
22
using System;
33
using System.Collections.Generic;
4+
using System.Linq;
5+
using Models;
6+
using Models.Scene;
7+
using Services;
8+
using UI;
9+
using Unity.AppUI.MVVM;
10+
using Unity.AppUI.Redux;
411
using UnityEngine;
512
using UnityEngine.Serialization;
613
using UnityEngine.UI;
714

815
public class ProbeUIManager : MonoBehaviour
916
{
10-
[FormerlySerializedAs("probePanelPrefab")] [SerializeField] private GameObject _probePanelPrefab;
17+
[FormerlySerializedAs("probePanelPrefab")][SerializeField] private GameObject _probePanelPrefab;
1118
private GameObject probePanelGO;
1219
private TP_ProbePanel probePanel;
1320

14-
[FormerlySerializedAs("probeManager")] [SerializeField] private ProbeManager _probeManager;
21+
[FormerlySerializedAs("probeManager")][SerializeField] private ProbeManager _probeManager;
1522

16-
[FormerlySerializedAs("electrodeBase")] [SerializeField] private GameObject _electrodeBase;
17-
[FormerlySerializedAs("order")] [SerializeField] private int _order;
23+
[FormerlySerializedAs("electrodeBase")][SerializeField] private GameObject _electrodeBase;
24+
[FormerlySerializedAs("order")][SerializeField] private int _order;
1825

19-
private Color defaultColor;
20-
private Color selectedColor;
2126
private bool _selected;
2227

2328
private bool probeMovedDirty = false;
@@ -76,14 +81,12 @@ public Transform ShankTipT()
7681
return _electrodeBase.transform;
7782
}
7883

84+
/// <summary>
85+
/// Update colors by pulling directly from Redux state.
86+
/// This method retrieves the color from state and applies it to the UI.
87+
/// </summary>
7988
public void UpdateColors()
8089
{
81-
defaultColor = _probeManager.Color;
82-
defaultColor.a = 0.5f;
83-
84-
selectedColor = defaultColor;
85-
selectedColor.a = 0.75f;
86-
8790
UpdateUIManagerColor();
8891
}
8992

@@ -202,7 +205,7 @@ private async void ProbedMovedHelper()
202205
/// <param name="tipIdxWorldT"></param>
203206
/// <param name="topIdxWorldT"></param>
204207
/// <returns></returns>
205-
private (List<int>, List<int>, List<string>) InterpolateAnnotationIDs(Vector3 tipIdxWorldT, Vector3 topIdxWorldT)
208+
private (List<int>, List<int>, List<string>) InterpolateAnnotationIDs(Vector3 tipIdxWorldT, Vector3 topIdxWorldT)
206209
{
207210
// pixel height at which changes happen
208211
List<int> areaPositionPixels = new();
@@ -293,12 +296,48 @@ public void ProbeSelected(bool selected)
293296
UpdateUIManagerColor();
294297
}
295298

299+
/// <summary>
300+
/// Update the UI manager color by pulling the probe color from Redux state.
301+
/// Computes default and selected colors with appropriate alpha values on demand.
302+
/// </summary>
296303
private void UpdateUIManagerColor()
297304
{
298-
if (_selected)
299-
probePanelGO.GetComponent<Image>().color = selectedColor;
300-
else
301-
probePanelGO.GetComponent<Image>().color = defaultColor;
305+
#if APP_UI
306+
// Get color from Redux state
307+
var storeService = PinpointApp.Services.GetRequiredService<StoreService>();
308+
var sceneState = storeService.Store.GetState<SceneState>(SliceNames.SCENE_SLICE);
309+
var probeState = sceneState.Probes.FirstOrDefault(p => p.Name == _probeManager.name);
310+
311+
if (probeState != null)
312+
{
313+
// Compute colors from state with appropriate alpha values
314+
Color defaultColor = probeState.ColorValue;
315+
defaultColor.a = 0.5f;
316+
317+
Color selectedColor = probeState.ColorValue;
318+
selectedColor.a = 0.75f;
319+
320+
// Apply the appropriate color
321+
var imageComponent = probePanelGO.GetComponent<Image>();
322+
if (imageComponent != null)
323+
{
324+
imageComponent.color = _selected ? selectedColor : defaultColor;
325+
}
326+
}
327+
#else
328+
// Fallback for non-APP_UI builds - get color from ProbeManager
329+
Color defaultColor = _probeManager.Color;
330+
defaultColor.a = 0.5f;
331+
332+
Color selectedColor = _probeManager.Color;
333+
selectedColor.a = 0.75f;
334+
335+
var imageComponent = probePanelGO.GetComponent<Image>();
336+
if (imageComponent != null)
337+
{
338+
imageComponent.color = _selected ? selectedColor : defaultColor;
339+
}
340+
#endif
302341
}
303342

304343
public void ResizeProbePanel(int newPxHeight)

Assets/Scripts/Pinpoint/TrajectoryPlannerManager.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -989,7 +989,7 @@ private void LoadSavedProbesFromStringArray(string[] savedProbes)
989989

990990
newProbeManager.UpdateSelectionLayer(probeData.SelectionLayerName);
991991
newProbeManager.OverrideName = probeData.Name;
992-
newProbeManager.Color = probeData.Color;
992+
//newProbeManager.Color = probeData.Color;
993993
newProbeManager.APITarget = probeData.APITarget;
994994
}
995995
}

0 commit comments

Comments
 (0)