Initial nucleus array UI

This commit is contained in:
Pascal Serrarens 2026-01-13 17:18:03 +01:00
parent 4f2f230335
commit 394df2167d
2 changed files with 133 additions and 74 deletions

View File

@ -2,6 +2,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using UnityEngine; using UnityEngine;
using Unity.Mathematics; using Unity.Mathematics;
using static Unity.Mathematics.math;
public class Receptor : IReceptor { public class Receptor : IReceptor {
[SerializeField] [SerializeField]
@ -11,10 +12,23 @@ public class Receptor : IReceptor {
set => _name = value; set => _name = value;
} }
class Receiver {
public INucleus nucleus;
public int thingId;
public string thingName;
public Receiver(INucleus nucleus, int thingId, string thingName) {
this.nucleus = nucleus;
this.thingId = thingId;
this.thingName = thingName;
}
}
[SerializeReference] [SerializeReference]
private List<INucleus> _receivers = new(); private List<INucleus> _receivers = new();
public List<INucleus> receivers => _receivers; public List<INucleus> receivers => _receivers;
protected int[] thingIds; // every receiver can handle a thing with this id
public virtual void AddReceiver(INucleus receivingNucleus) { public virtual void AddReceiver(INucleus receivingNucleus) {
this.receivers.Add(receivingNucleus); this.receivers.Add(receivingNucleus);
receivingNucleus.AddSynapse(this); receivingNucleus.AddSynapse(this);
@ -25,7 +39,6 @@ public class Receptor : IReceptor {
receiverNucleus.synapses.RemoveAll(synapse => synapse.nucleus == this); receiverNucleus.synapses.RemoveAll(synapse => synapse.nucleus == this);
} }
//public bool isSleeping => false;
private int stale = 1000; private int stale = 1000;
private bool _isSleeping = false; private bool _isSleeping = false;
@ -42,7 +55,6 @@ public class Receptor : IReceptor {
public float distanceResolution = 0.1f; public float distanceResolution = 0.1f;
public float directionResolution = 5; public float directionResolution = 5;
//public float3 outputValue => this.localPosition;
private float3 _outputValue; private float3 _outputValue;
public float3 outputValue { public float3 outputValue {
get { return this._outputValue; } get { return this._outputValue; }
@ -53,6 +65,11 @@ public class Receptor : IReceptor {
} }
} }
public Receptor(Cluster cluster) {
if (cluster != null)
cluster.nuclei.Add(this);
}
public Receptor(Cluster cluster, INucleus nucleus) { public Receptor(Cluster cluster, INucleus nucleus) {
if (cluster != null) if (cluster != null)
cluster.nuclei.Add(this); cluster.nuclei.Add(this);
@ -63,65 +80,67 @@ public class Receptor : IReceptor {
if (cluster == null) if (cluster == null)
return null; return null;
Receptor receptor = new(cluster);
foreach (INucleus nucleus in cluster.inputs) { foreach (INucleus nucleus in cluster.inputs) {
if (nucleus != null && nucleus.name == nucleusName) { if (nucleus != null && nucleus.name == nucleusName) {
Receptor receptor = new(cluster, nucleus); // Receptor receptor = new(cluster, nucleus);
return receptor; // return receptor;
receptor.AddReceiver(nucleus);
} }
} }
if (receptor.receivers.Count == 0)
return null; return null;
else
return receptor;
} }
public virtual void ProcessStimulus(int thingId, Vector3 newLocalPositionVector, string thingName = null) { public virtual void ProcessStimulus(int thingId, Vector3 newLocalPositionVector, string thingName = null) {
this.localPosition = newLocalPositionVector; this.localPosition = newLocalPositionVector;
thingIds ??= new int[this.receivers.Count];
int receiverIx = 0;
INucleus selectedReceiver = null; INucleus selectedReceiver = null;
int selectedReceiverIx = 0;
foreach (INucleus receiver in this.receivers) { foreach (INucleus receiver in this.receivers) {
// selectedReceiver = receiver;
// receiverIx++;
if (thingIds[receiverIx] == thingId) {
// We found an existing receiver for this thing
selectedReceiver = receiver; selectedReceiver = receiver;
selectedReceiverIx = receiverIx;
// Do not look any further
break;
} }
// selectedReceiver.thingId = thingId; else if (receiver.isSleeping) {
// A sleeping receiver is not active and can therefore always be used
selectedReceiver = receiver;
selectedReceiverIx = receiverIx;
// Look further because we may find an existing receiver for this thing
}
else if (selectedReceiver == null) {
// If we haven't found a receiver yet, just start by taking the first
selectedReceiver = receiver;
selectedReceiverIx = receiverIx;
}
else if (selectedReceiver.isSleeping == false) {
// If no existing or sleeping receiver is found, we look for
// the receiver with the furthest/least interesting stimulus
if (length(receiver.outputValue) < length(selectedReceiver.outputValue)) {
// Debug.Log($"{selectedReceiver.name}[{selectedReceiverIx}] {length(selectedReceiver.outputValue)}" +
// $" {receiver.name}[{receiverIx}] {length(receiver.outputValue)} ");
selectedReceiver = receiver;
selectedReceiverIx = receiverIx;
}
}
receiverIx++;
}
// Debug.Log($"Receiver {selectedReceiver.name}[{selectedReceiverIx}] for thing {thingId}");
thingIds[selectedReceiverIx] = thingId;
// if (thingName != null) // if (thingName != null)
// selectedReceiver.nucleus.name = selectedReceiver.nucleus.baseName + " " + thingName; // selectedReceiver.nucleus.name = selectedReceiver.nucleus.baseName + " " + thingName;
selectedReceiver.UpdateState(); selectedReceiver.UpdateState();
// Perceptoid selectedPerceptoid = null;
// foreach (Perceptoid perceptoid in this.perceptei) {
// if (perceptoid.thingId == thingId) {
// // We found an existing perceptoid for this thing
// selectedPerceptoid = perceptoid;
// // Do not look any further
// break;
// }
// else if (perceptoid.isSleeping) {
// // A sleeping perceptoid is not active and can therefore always be reused
// selectedPerceptoid = perceptoid;
// // Look further because we could find a existing perceptoid for this thing
// }
// else if (selectedPerceptoid == null) {
// // If we haven't found a perceptoid yet, just start by taking the first
// selectedPerceptoid = perceptoid;
// }
// else if (selectedPerceptoid.isSleeping == false) {
// // If no existing or sleeping perceptoid is found, we look for the perceptoid
// // we the furthest (least interesting) stimulus
// if (perceptoid.receptor.localPosition.magnitude < selectedPerceptoid.receptor.localPosition.magnitude) {
// Debug.Log($"{selectedPerceptoid.name} {selectedPerceptoid.receptor.localPosition.magnitude} {perceptoid.receptor.localPosition.magnitude} ");
// selectedPerceptoid = perceptoid;
// }
// }
// }
// if (selectedPerceptoid == null) {
// Debug.Log("No perceptoid selected, stimulus is ignored");
// return;
// }
// // Debug.Log($"Stimulus {thingType} {thingId} {selectedPerceptoid.name}");
// selectedPerceptoid.thingId = thingId;
// if (thingName != null)
// selectedPerceptoid.name = selectedPerceptoid.baseName + " " + thingName;
// selectedPerceptoid.UpdateState();
} }
public void UpdateNuclei() { public void UpdateNuclei() {

View File

@ -78,11 +78,12 @@ public class ClusterInspector : Editor {
GameObject gameObject; GameObject gameObject;
private List<NeuroidLayer> layers = new(); private List<NeuroidLayer> layers = new();
private readonly Dictionary<IReceptor, Vector2Int> neuroidPositions = new(); private readonly Dictionary<IReceptor, Vector2Int> neuroidPositions = new();
private bool expandArray = false;
Vector2 pan = Vector2.zero; //Vector2 pan = Vector2.zero;
//float zoom = 1f; //float zoom = 1f;
bool draggingCanvas = false; //bool draggingCanvas = false;
Vector2 lastMouse; //Vector2 lastMouse;
ClusterWrapper currentWrapper; ClusterWrapper currentWrapper;
public GraphView() { public GraphView() {
@ -98,9 +99,9 @@ public class ClusterInspector : Editor {
Add(imguiContainer); Add(imguiContainer);
//RegisterCallback<WheelEvent>(OnWheel); //RegisterCallback<WheelEvent>(OnWheel);
RegisterCallback<MouseDownEvent>(OnMouseDown); // RegisterCallback<MouseDownEvent>(OnMouseDown);
RegisterCallback<MouseMoveEvent>(OnMouseMove); // RegisterCallback<MouseMoveEvent>(OnMouseMove);
RegisterCallback<MouseUpEvent>(OnMouseUp); // RegisterCallback<MouseUpEvent>(OnMouseUp);
} }
public void SetGraph(GameObject gameObject, Cluster brain, INucleus nucleus, VisualElement inspectorContainer) { public void SetGraph(GameObject gameObject, Cluster brain, INucleus nucleus, VisualElement inspectorContainer) {
@ -181,19 +182,19 @@ public class ClusterInspector : Editor {
} }
void OnMouseDown(MouseDownEvent e) { // void OnMouseDown(MouseDownEvent e) {
if (e.button == 2) { draggingCanvas = true; lastMouse = e.mousePosition; e.StopPropagation(); } // if (e.button == 2) { draggingCanvas = true; lastMouse = e.mousePosition; e.StopPropagation(); }
} // }
void OnMouseMove(MouseMoveEvent e) { // void OnMouseMove(MouseMoveEvent e) {
if (draggingCanvas) { // if (draggingCanvas) {
var delta = e.mousePosition - lastMouse; // var delta = e.mousePosition - lastMouse;
pan += delta; // pan += delta;
//content.style.left = pan.x; // //content.style.left = pan.x;
//content.style.top = pan.y; // //content.style.top = pan.y;
lastMouse = e.mousePosition; // lastMouse = e.mousePosition;
} // }
} // }
void OnMouseUp(MouseUpEvent e) { if (e.button == 2) draggingCanvas = false; } // void OnMouseUp(MouseUpEvent e) { if (e.button == 2) draggingCanvas = false; }
void OnIMGUI() { void OnIMGUI() {
if (currentNucleus == null) if (currentNucleus == null)
@ -217,9 +218,24 @@ public class ClusterInspector : Editor {
// Draw selected Nucleus // Draw selected Nucleus
Handles.color = Color.white; Handles.color = Color.white;
if (expandArray) {
float spacing = 400f / this.currentNucleus.array.nuclei.Length;
float margin = 10 + spacing / 2;
int row = 0;
foreach (INucleus nucleus in this.currentNucleus.array.nuclei) {
Vector3 pos = new(150, margin + row * spacing, 0.0f);
Handles.color = Color.white;
//Handles.DrawLine(parentPos, pos);
DrawNucleus(nucleus, pos, 0, size);
row++;
}
}
else {
Handles.DrawSolidDisc(position, Vector3.forward, size + 2); Handles.DrawSolidDisc(position, Vector3.forward, size + 2);
DrawNucleus(this.currentNucleus, position, length(this.currentNucleus.outputValue), 20); DrawNucleus(this.currentNucleus, position, length(this.currentNucleus.outputValue), 20);
} }
}
private void DrawReceivers(INucleus nucleus, Vector3 parentPos, float size) { private void DrawReceivers(INucleus nucleus, Vector3 parentPos, float size) {
int nodeCount = nucleus.receivers.Count; int nodeCount = nucleus.receivers.Count;
@ -318,18 +334,36 @@ public class ClusterInspector : Editor {
normal = { textColor = Color.white }, normal = { textColor = Color.white },
fontStyle = FontStyle.Bold, fontStyle = FontStyle.Bold,
}; };
if (nucleus is Neuron neuron) { if (nucleus is INucleus neuron) {
if (neuron.array == null || neuron.array.nuclei == null || neuron.array.nuclei.Length == 0) if (neuron.array == null || neuron.array.nuclei == null || neuron.array.nuclei.Length == 0)
neuron.array = new NucleusArray(neuron); neuron.array = new NucleusArray(neuron);
if (neuron.array.nuclei.Length > 1) { if ((!expandArray || neuron.array.nuclei[0] != this.currentNucleus) && neuron.array.nuclei.Length > 1) {
Handles.Label(labelPosition, neuron.array.nuclei.Length.ToString(), style); Handles.Label(labelPosition, neuron.array.nuclei.Length.ToString(), style);
} }
style.alignment = TextAnchor.UpperCenter;
Vector3 labelPos = position - Vector3.down * (size + 0.2f); // below disc along up axis
// if ((!expandArray || neuron.array.nuclei[0] != this.currentNucleus) && neuron.array.nuclei.Length > 1) {
// Handles.Label(labelPos, nucleus.name, style);
// }
// else {
if (expandArray && neuron.array.nuclei[0] == this.currentNucleus) {
int arrayIx = 0;
foreach (INucleus n in neuron.array.nuclei) {
if (n == neuron)
break;
arrayIx++;
} }
Handles.Label(labelPos, $"{nucleus.name}[{arrayIx}]", style);
}
else
Handles.Label(labelPos, nucleus.name, style);
}
else {
style.alignment = TextAnchor.UpperCenter; style.alignment = TextAnchor.UpperCenter;
Vector3 labelPos = position - Vector3.down * (size + 0.2f); // below disc along up axis Vector3 labelPos = position - Vector3.down * (size + 0.2f); // below disc along up axis
Handles.Label(labelPos, nucleus.name, style); Handles.Label(labelPos, nucleus.name, style);
}
Rect neuronRect = new(position.x - size, position.y - size, size * 2, size * 2); Rect neuronRect = new(position.x - size, position.y - size, size * 2, size * 2);
int id = GUIUtility.GetControlID(FocusType.Passive); int id = GUIUtility.GetControlID(FocusType.Passive);
@ -371,7 +405,13 @@ public class ClusterInspector : Editor {
} }
private void HandleClicked(IReceptor nucleus) { private void HandleClicked(IReceptor nucleus) {
if (nucleus == this.currentNucleus) {
if (nucleus is INucleus n) { if (nucleus is INucleus n) {
expandArray = !expandArray;
return;
}
}
else if (nucleus is INucleus n) {
this.currentNucleus = n; this.currentNucleus = n;
BuildLayers(); BuildLayers();
} }