Add perception array UI

This commit is contained in:
Pascal Serrarens 2026-01-09 10:08:06 +01:00
parent 5206469764
commit de7503bb4a
5 changed files with 161 additions and 68 deletions

View File

@ -1,22 +1,61 @@
using UnityEngine;
[System.Serializable]
public class PercepteiArray { public class PercepteiArray {
public ArrayPerceptoid[] perceptei; [SerializeReference]
public Perceptoid[] perceptei;
public string name; public string name;
public PercepteiArray(NanoBrain brain, int thingType, string baseName, uint count) { // public PercepteiArray(NanoBrain brain, int thingType, string baseName, uint count) {
this.name = baseName; // this.name = baseName;
this.perceptei = new ArrayPerceptoid[count]; // this.perceptei = new Perceptoid[count];
for (uint i = 0; i < count; i++) { // for (uint i = 0; i < count; i++) {
this.perceptei[i] = new ArrayPerceptoid(brain, thingType, $"{baseName}[{i}]") { // this.perceptei[i] = new Perceptoid(brain, thingType, $"{baseName}[{i}]") {
array = this // array = this
}; // };
// }
// }
public PercepteiArray(Perceptoid perceptoid) {
this.name = perceptoid.baseName;
this.perceptei = new Perceptoid[1];
this.perceptei[0] = perceptoid;
}
public void AddPerceptoid() {
if (this.perceptei.Length == 0) {
Debug.LogError("Empty perceptoid array, cannot add");
return;
} }
int newLength = this.perceptei.Length + 1;
Perceptoid[] newPerceptei = new Perceptoid[newLength];
for (int i = 0; i < this.perceptei.Length; i++)
newPerceptei[i] = this.perceptei[i];
newPerceptei[newLength - 1] = new Perceptoid(this);
this.perceptei = newPerceptei;
}
public void RemovePerceptoid() {
int newLength = this.perceptei.Length - 1;
if (newLength == 0) {
Debug.LogWarning("Perceptoid array cannot be empty");
return;
}
Perceptoid[] newPerceptei = new Perceptoid[newLength];
for (int i = 0; i < newLength; i++)
newPerceptei[i++] = this.perceptei[i];
// Delete the last perception
Nucleus.Delete(this.perceptei[newLength]);
this.perceptei = newPerceptei;
} }
} }
public class ArrayPerceptoid : Perceptoid { // public class ArrayPerceptoid : Perceptoid {
public PercepteiArray array; // public PercepteiArray array;
public ArrayPerceptoid(NanoBrain brain, int thingType, string name = "sensor") : base(brain, thingType, name) { // public ArrayPerceptoid(NanoBrain brain, int thingType, string name = "sensor") : base(brain, thingType, name) {
} // }
} // }

View File

@ -1,5 +1,4 @@
using UnityEngine; using UnityEngine;
using LinearAlgebra;
[System.Serializable] [System.Serializable]
public class Perceptoid : Neuroid { public class Perceptoid : Neuroid {
@ -8,16 +7,24 @@ public class Perceptoid : Neuroid {
public Receptor receptor; public Receptor receptor;
public string baseName; public string baseName;
public int thingId;
//[SerializeField]
// Needs serialization!!!!
[SerializeReference]
public PercepteiArray array;
#region Serialization #region Serialization
[SerializeField] [SerializeField]
public int thingType; public int thingType;
public int thingId;
public override void Rebuild(NanoBrain brain) { public override void Rebuild(NanoBrain brain) {
base.Rebuild(brain); base.Rebuild(brain);
this.receptor = Receptor.GetReceptor(brain, thingType); this.receptor = Receptor.GetReceptor(brain, thingType);
this.receptor.perceptei.Add(this); this.receptor.perceptei.Add(this);
if (string.IsNullOrEmpty(this.baseName))
this.baseName = this.name;
} }
public override void Deserialize(Nucleus nucleus) { public override void Deserialize(Nucleus nucleus) {
@ -62,30 +69,30 @@ public class Perceptoid : Neuroid {
this.thingType = thingType; this.thingType = thingType;
this.receptor = Receptor.GetReceptor(brain, thingType); this.receptor = Receptor.GetReceptor(brain, thingType);
this.receptor.perceptei.Add(this); this.receptor.perceptei.Add(this);
this.array = new PercepteiArray(this);
} }
// public void Replace(int thingType, string name = "sensor") { public Perceptoid(PercepteiArray array) : base(array.name) {
// this.name = name; this.array = array;
Perceptoid source = array.perceptei[0];
this.brain = source.brain;
if (this.brain != null) {
this.brain.perceptei.Add(this);
}
else
Debug.LogError("No neuroid network");
// this.thingType = thingType; this.nucleusType = nameof(Perceptoid);
// this.receptor.thingType = thingType; this.name = source.baseName;
// this.receptor.localPosition = Vector3.zero; this.baseName = source.baseName;
this.thingType = source.thingType;
// this.outputValue = Vector3.zero; this.receptor = Receptor.GetReceptor(this.brain, this.thingType);
// this.receivers = new(); this.receptor.perceptei.Add(this);
// } }
public override void UpdateState() { public override void UpdateState() {
Vector3 result = this.receptor.localPosition; Vector3 result = this.receptor.localPosition;
UpdateResult(result); UpdateResult(result);
} }
// public static Perceptoid GetPerception(NanoBrain brain, int thingType = 0) {
// foreach (Nucleus nucleus in brain.nuclei) {
// if (nucleus is Perceptoid perceptoid && (thingType == 0 || perceptoid.receptor.thingType == thingType))
// return perceptoid;
// }
// return null;
// }
} }

View File

@ -278,19 +278,19 @@ public class NanoBrainInspector : Editor {
Vector3 pos = new(250, margin + row * spacing, 0.0f); Vector3 pos = new(250, margin + row * spacing, 0.0f);
Handles.color = Color.white; Handles.color = Color.white;
Handles.DrawLine(parentPos, pos); Handles.DrawLine(parentPos, pos);
if (synapse.nucleus is ArrayPerceptoid perceptoid) { // if (synapse.nucleus is Perceptoid perceptoid && perceptoid.array != null) {
if (drawnArrays.Contains(perceptoid.array)) // // if (drawnArrays.Contains(perceptoid.array))
// We already drawn this array // // // We already drawn this array
continue; // // continue;
drawnArrays.Add(perceptoid.array); // drawnArrays.Add(perceptoid.array);
DrawArray(perceptoid.array, pos, size); // DrawArray(perceptoid.array, pos, size);
} // }
else { // else {
DrawNucleus(synapse.nucleus, pos, maxValue, size); DrawNucleus(synapse.nucleus, pos, maxValue, size);
row++; row++;
} // }
} }
} }
@ -298,16 +298,35 @@ public class NanoBrainInspector : Editor {
if (nucleus.isSleeping) if (nucleus.isSleeping)
Handles.color = Color.darkRed; Handles.color = Color.darkRed;
else { else {
float brightness = nucleus.outputValue.magnitude / maxValue; if (Application.isPlaying) {
Handles.color = new Color(brightness, brightness, brightness); float brightness = nucleus.outputValue.magnitude / maxValue;
Handles.color = new Color(brightness, brightness, brightness, 1f);
}
else
Handles.color = Color.black;
} }
Handles.DrawSolidDisc(position, Vector3.forward, size); Handles.DrawSolidDisc(position, Vector3.forward, size);
Vector3 labelPos = position - Vector3.down * (size + 0.2f); // below disc along up axis
Handles.color = Color.white;
// Position the label in front of the disc
Vector3 labelPosition = position + (Vector3.forward * 0.1f);
GUIStyle style = new(EditorStyles.label) { GUIStyle style = new(EditorStyles.label) {
alignment = TextAnchor.UpperCenter, alignment = TextAnchor.MiddleCenter,
normal = { textColor = Color.white }, normal = { textColor = Color.white },
fontStyle = FontStyle.Bold fontStyle = FontStyle.Bold,
}; };
if (nucleus is Perceptoid perceptoid) {
if (perceptoid.array == null || perceptoid.array.perceptei == null || perceptoid.array.perceptei.Length == 0)
perceptoid.array = new PercepteiArray(perceptoid);
if (perceptoid.array.perceptei.Length > 1) {
Handles.Label(labelPosition, perceptoid.array.perceptei.Length.ToString(), style);
}
}
style.alignment = TextAnchor.UpperCenter;
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);
@ -326,21 +345,18 @@ public class NanoBrainInspector : Editor {
} }
} }
private void DrawArray(PercepteiArray array, Vector3 position, float size) { private void DrawArray(PercepteiArray array, Vector3 position, float size) {
Vector3 offset = new(size/4, size/4, 0); Vector3 offset = new(size / 4, size / 4, 0);
Handles.color = Color.darkGray; Handles.color = Color.black;
Handles.DrawSolidDisc(position + offset * 2, Vector3.forward, size);
Handles.color = Color.lightGray;
Handles.DrawSolidDisc(position + offset, Vector3.forward, size);
Handles.color = Color.white;
Handles.DrawSolidDisc(position, Vector3.forward, size); Handles.DrawSolidDisc(position, Vector3.forward, size);
Vector3 labelPos = position - Vector3.down * (size + 0.2f); // below disc along up axis GUIStyle style = new(EditorStyles.label) {
GUIStyle style = new GUIStyle(EditorStyles.label) {
alignment = TextAnchor.UpperCenter, alignment = TextAnchor.UpperCenter,
normal = { textColor = Color.white }, normal = { textColor = Color.white },
fontStyle = FontStyle.Bold fontStyle = FontStyle.Bold
}; };
Handles.Label(position, array.perceptei.Length.ToString(), style);
Vector3 labelPos = position - Vector3.down * (size + 0.2f); // below disc along up axis
Handles.Label(labelPos, array.name, style); Handles.Label(labelPos, array.name, style);
// To do: add HandleClick (see above) to expand the array // To do: add HandleClick (see above) to expand the array
@ -403,8 +419,18 @@ public class NanoBrainInspector : Editor {
return; return;
this.currentNucleus.name = EditorGUILayout.TextField(this.currentNucleus.name); this.currentNucleus.name = EditorGUILayout.TextField(this.currentNucleus.name);
if (this.currentNucleus is Perceptoid currentPerceptoid) { if (this.currentNucleus is Perceptoid perceptoid) {
currentPerceptoid.receptor.thingType = EditorGUILayout.IntField("Thing Type", currentPerceptoid.receptor.thingType); perceptoid.receptor.thingType = EditorGUILayout.IntField("Thing Type", perceptoid.receptor.thingType);
if (perceptoid.array == null || perceptoid.array.perceptei == null || perceptoid.array.perceptei.Length == 0)
perceptoid.array = new PercepteiArray(perceptoid);
EditorGUILayout.BeginHorizontal();
EditorGUILayout.IntField("Array size", perceptoid.array.perceptei.Length);
if (GUILayout.Button("Add"))
perceptoid.array.AddPerceptoid();
if (GUILayout.Button("Del"))
perceptoid.array.RemovePerceptoid();
EditorGUILayout.EndHorizontal();
} }
else if (this.currentNucleus is Neuroid neuroid) { else if (this.currentNucleus is Neuroid neuroid) {
EditorGUILayout.BeginHorizontal(); EditorGUILayout.BeginHorizontal();
@ -427,12 +453,21 @@ public class NanoBrainInspector : Editor {
foreach (Synapse synapse in synapses) { foreach (Synapse synapse in synapses) {
if (synapse.nucleus != null) { if (synapse.nucleus != null) {
EditorGUILayout.Space(); EditorGUILayout.Space();
EditorGUI.BeginDisabledGroup(synapse.nucleus.isSleeping); EditorGUI.BeginDisabledGroup(synapse.nucleus.isSleeping);
if (Application.isPlaying) if (Application.isPlaying)
EditorGUILayout.FloatField(synapse.nucleus.name, synapse.nucleus.outputValue.magnitude * synapse.weight); EditorGUILayout.FloatField(synapse.nucleus.name, synapse.nucleus.outputValue.magnitude * synapse.weight);
else { else {
EditorGUILayout.BeginHorizontal(); EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField(synapse.nucleus.name); EditorGUILayout.LabelField(synapse.nucleus.name);
// if (synapse.nucleus is Perceptoid perceptoid) {
// if (perceptoid.array == null || perceptoid.array.perceptei == null || perceptoid.array.perceptei.Length == 0) {
// perceptoid.array = new PercepteiArray(perceptoid);
// }
// EditorGUILayout.IntField(perceptoid.array.perceptei.Length);
// if (GUILayout.Button("Add"))
// perceptoid.array.AddPerceptoid();
// }
if (GUILayout.Button("Disconnect")) if (GUILayout.Button("Disconnect"))
synapse.nucleus.RemoveReceiver(this.currentNucleus); synapse.nucleus.RemoveReceiver(this.currentNucleus);
EditorGUILayout.EndHorizontal(); EditorGUILayout.EndHorizontal();

View File

@ -375,7 +375,7 @@ MonoBehaviour:
m_EditorClassIdentifier: Assembly-CSharp::SwarmControl m_EditorClassIdentifier: Assembly-CSharp::SwarmControl
speed: 1 speed: 1
inertia: 0.7 inertia: 0.7
alignmentForce: 0.5 alignmentForce: 0.4
cohesionForce: 0.1 cohesionForce: 0.1
separationForce: -0.1 separationForce: -0.1
avoidanceForce: 1 avoidanceForce: 1

View File

@ -142,8 +142,8 @@ MonoBehaviour:
inWeight: 0 inWeight: 0
outWeight: 0 outWeight: 0
- serializedVersion: 3 - serializedVersion: 3
time: 1 time: 1000
value: 1 value: 1000
inSlope: 1 inSlope: 1
outSlope: 0 outSlope: 0
tangentMode: 0 tangentMode: 0
@ -250,8 +250,8 @@ MonoBehaviour:
inWeight: 0 inWeight: 0
outWeight: 0 outWeight: 0
- serializedVersion: 3 - serializedVersion: 3
time: 1 time: 1000
value: 1 value: 1000
inSlope: 1 inSlope: 1
outSlope: 0 outSlope: 0
tangentMode: 0 tangentMode: 0
@ -3786,7 +3786,10 @@ MonoBehaviour:
exponent: 1 exponent: 1
- id: 763145504 - id: 763145504
_name: Inverse Boid D _name: Inverse Boid D
synapses: [] synapses:
- nucleusId: -1095934288
weight: 1
curveMax: 1
receivers: receivers:
- nucleusId: 1641120128 - nucleusId: 1641120128
nucleusType: nucleusType:
@ -4956,7 +4959,10 @@ MonoBehaviour:
exponent: 1 exponent: 1
- id: 1469392160 - id: 1469392160
_name: Inverse Boid E _name: Inverse Boid E
synapses: [] synapses:
- nucleusId: -1413006832
weight: 1
curveMax: 1
receivers: receivers:
- nucleusId: 1641120128 - nucleusId: 1641120128
nucleusType: nucleusType:
@ -6126,7 +6132,10 @@ MonoBehaviour:
exponent: 1 exponent: 1
- id: -1828317248 - id: -1828317248
_name: Inverse Bodi F _name: Inverse Bodi F
synapses: [] synapses:
- nucleusId: -61245040
weight: 1
curveMax: 1
receivers: receivers:
- nucleusId: 1641120128 - nucleusId: 1641120128
nucleusType: nucleusType:
@ -7387,6 +7396,7 @@ MonoBehaviour:
synapses: [] synapses: []
receivers: receivers:
- nucleusId: 1938577052 - nucleusId: 1938577052
- nucleusId: 763145504
nucleusType: Perceptoid nucleusType: Perceptoid
isSleeping: 0 isSleeping: 0
_curvePreset: 0 _curvePreset: 0
@ -7408,6 +7418,7 @@ MonoBehaviour:
synapses: [] synapses: []
receivers: receivers:
- nucleusId: 1938577052 - nucleusId: 1938577052
- nucleusId: 1469392160
nucleusType: Perceptoid nucleusType: Perceptoid
isSleeping: 0 isSleeping: 0
_curvePreset: 0 _curvePreset: 0
@ -7429,6 +7440,7 @@ MonoBehaviour:
synapses: [] synapses: []
receivers: receivers:
- nucleusId: 1938577052 - nucleusId: 1938577052
- nucleusId: -1828317248
nucleusType: Perceptoid nucleusType: Perceptoid
isSleeping: 0 isSleeping: 0
_curvePreset: 0 _curvePreset: 0