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 UnityEngine;
using Unity.Mathematics;
using static Unity.Mathematics.math;
public class Receptor : IReceptor {
[SerializeField]
@ -11,10 +12,23 @@ public class Receptor : IReceptor {
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]
private List<INucleus> _receivers = new();
public List<INucleus> receivers => _receivers;
protected int[] thingIds; // every receiver can handle a thing with this id
public virtual void AddReceiver(INucleus receivingNucleus) {
this.receivers.Add(receivingNucleus);
receivingNucleus.AddSynapse(this);
@ -25,7 +39,6 @@ public class Receptor : IReceptor {
receiverNucleus.synapses.RemoveAll(synapse => synapse.nucleus == this);
}
//public bool isSleeping => false;
private int stale = 1000;
private bool _isSleeping = false;
@ -42,7 +55,6 @@ public class Receptor : IReceptor {
public float distanceResolution = 0.1f;
public float directionResolution = 5;
//public float3 outputValue => this.localPosition;
private float3 _outputValue;
public float3 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) {
if (cluster != null)
cluster.nuclei.Add(this);
@ -63,65 +80,67 @@ public class Receptor : IReceptor {
if (cluster == null)
return null;
Receptor receptor = new(cluster);
foreach (INucleus nucleus in cluster.inputs) {
if (nucleus != null && nucleus.name == nucleusName) {
Receptor receptor = new(cluster, nucleus);
return receptor;
// Receptor receptor = new(cluster, nucleus);
// return receptor;
receptor.AddReceiver(nucleus);
}
}
return null;
if (receptor.receivers.Count == 0)
return null;
else
return receptor;
}
public virtual void ProcessStimulus(int thingId, Vector3 newLocalPositionVector, string thingName = null) {
this.localPosition = newLocalPositionVector;
thingIds ??= new int[this.receivers.Count];
int receiverIx = 0;
INucleus selectedReceiver = null;
int selectedReceiverIx = 0;
foreach (INucleus receiver in this.receivers) {
selectedReceiver = receiver;
// selectedReceiver = receiver;
// receiverIx++;
if (thingIds[receiverIx] == thingId) {
// We found an existing receiver for this thing
selectedReceiver = receiver;
selectedReceiverIx = receiverIx;
// Do not look any further
break;
}
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++;
}
// selectedReceiver.thingId = thingId;
// Debug.Log($"Receiver {selectedReceiver.name}[{selectedReceiverIx}] for thing {thingId}");
thingIds[selectedReceiverIx] = thingId;
// if (thingName != null)
// selectedReceiver.nucleus.name = selectedReceiver.nucleus.baseName + " " + thingName;
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() {

View File

@ -78,11 +78,12 @@ public class ClusterInspector : Editor {
GameObject gameObject;
private List<NeuroidLayer> layers = new();
private readonly Dictionary<IReceptor, Vector2Int> neuroidPositions = new();
private bool expandArray = false;
Vector2 pan = Vector2.zero;
//Vector2 pan = Vector2.zero;
//float zoom = 1f;
bool draggingCanvas = false;
Vector2 lastMouse;
//bool draggingCanvas = false;
//Vector2 lastMouse;
ClusterWrapper currentWrapper;
public GraphView() {
@ -98,9 +99,9 @@ public class ClusterInspector : Editor {
Add(imguiContainer);
//RegisterCallback<WheelEvent>(OnWheel);
RegisterCallback<MouseDownEvent>(OnMouseDown);
RegisterCallback<MouseMoveEvent>(OnMouseMove);
RegisterCallback<MouseUpEvent>(OnMouseUp);
// RegisterCallback<MouseDownEvent>(OnMouseDown);
// RegisterCallback<MouseMoveEvent>(OnMouseMove);
// RegisterCallback<MouseUpEvent>(OnMouseUp);
}
public void SetGraph(GameObject gameObject, Cluster brain, INucleus nucleus, VisualElement inspectorContainer) {
@ -181,19 +182,19 @@ public class ClusterInspector : Editor {
}
void OnMouseDown(MouseDownEvent e) {
if (e.button == 2) { draggingCanvas = true; lastMouse = e.mousePosition; e.StopPropagation(); }
}
void OnMouseMove(MouseMoveEvent e) {
if (draggingCanvas) {
var delta = e.mousePosition - lastMouse;
pan += delta;
//content.style.left = pan.x;
//content.style.top = pan.y;
lastMouse = e.mousePosition;
}
}
void OnMouseUp(MouseUpEvent e) { if (e.button == 2) draggingCanvas = false; }
// void OnMouseDown(MouseDownEvent e) {
// if (e.button == 2) { draggingCanvas = true; lastMouse = e.mousePosition; e.StopPropagation(); }
// }
// void OnMouseMove(MouseMoveEvent e) {
// if (draggingCanvas) {
// var delta = e.mousePosition - lastMouse;
// pan += delta;
// //content.style.left = pan.x;
// //content.style.top = pan.y;
// lastMouse = e.mousePosition;
// }
// }
// void OnMouseUp(MouseUpEvent e) { if (e.button == 2) draggingCanvas = false; }
void OnIMGUI() {
if (currentNucleus == null)
@ -217,8 +218,23 @@ public class ClusterInspector : Editor {
// Draw selected Nucleus
Handles.color = Color.white;
Handles.DrawSolidDisc(position, Vector3.forward, size + 2);
DrawNucleus(this.currentNucleus, position, length(this.currentNucleus.outputValue), 20);
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);
DrawNucleus(this.currentNucleus, position, length(this.currentNucleus.outputValue), 20);
}
}
private void DrawReceivers(INucleus nucleus, Vector3 parentPos, float size) {
@ -318,18 +334,36 @@ public class ClusterInspector : Editor {
normal = { textColor = Color.white },
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)
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);
}
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;
Vector3 labelPos = position - Vector3.down * (size + 0.2f); // below disc along up axis
Handles.Label(labelPos, nucleus.name, style);
}
style.alignment = TextAnchor.UpperCenter;
Vector3 labelPos = position - Vector3.down * (size + 0.2f); // below disc along up axis
Handles.Label(labelPos, nucleus.name, style);
Rect neuronRect = new(position.x - size, position.y - size, size * 2, size * 2);
int id = GUIUtility.GetControlID(FocusType.Passive);
@ -371,7 +405,13 @@ public class ClusterInspector : Editor {
}
private void HandleClicked(IReceptor nucleus) {
if (nucleus is INucleus n) {
if (nucleus == this.currentNucleus) {
if (nucleus is INucleus n) {
expandArray = !expandArray;
return;
}
}
else if (nucleus is INucleus n) {
this.currentNucleus = n;
BuildLayers();
}