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 ArrayPerceptoid[] perceptei;
[SerializeReference]
public Perceptoid[] perceptei;
public string name;
public PercepteiArray(NanoBrain brain, int thingType, string baseName, uint count) {
this.name = baseName;
this.perceptei = new ArrayPerceptoid[count];
for (uint i = 0; i < count; i++) {
this.perceptei[i] = new ArrayPerceptoid(brain, thingType, $"{baseName}[{i}]") {
array = this
};
}
// public PercepteiArray(NanoBrain brain, int thingType, string baseName, uint count) {
// this.name = baseName;
// this.perceptei = new Perceptoid[count];
// for (uint i = 0; i < count; i++) {
// this.perceptei[i] = new Perceptoid(brain, thingType, $"{baseName}[{i}]") {
// 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 PercepteiArray array;
// public class ArrayPerceptoid : Perceptoid {
// 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 LinearAlgebra;
[System.Serializable]
public class Perceptoid : Neuroid {
@ -8,16 +7,24 @@ public class Perceptoid : Neuroid {
public Receptor receptor;
public string baseName;
public int thingId;
//[SerializeField]
// Needs serialization!!!!
[SerializeReference]
public PercepteiArray array;
#region Serialization
[SerializeField]
public int thingType;
public int thingId;
public override void Rebuild(NanoBrain brain) {
base.Rebuild(brain);
this.receptor = Receptor.GetReceptor(brain, thingType);
this.receptor.perceptei.Add(this);
if (string.IsNullOrEmpty(this.baseName))
this.baseName = this.name;
}
public override void Deserialize(Nucleus nucleus) {
@ -62,30 +69,30 @@ public class Perceptoid : Neuroid {
this.thingType = thingType;
this.receptor = Receptor.GetReceptor(brain, thingType);
this.receptor.perceptei.Add(this);
this.array = new PercepteiArray(this);
}
// public void Replace(int thingType, string name = "sensor") {
// this.name = name;
public Perceptoid(PercepteiArray array) : base(array.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.receptor.thingType = thingType;
// this.receptor.localPosition = Vector3.zero;
// this.outputValue = Vector3.zero;
// this.receivers = new();
// }
this.nucleusType = nameof(Perceptoid);
this.name = source.baseName;
this.baseName = source.baseName;
this.thingType = source.thingType;
this.receptor = Receptor.GetReceptor(this.brain, this.thingType);
this.receptor.perceptei.Add(this);
}
public override void UpdateState() {
Vector3 result = this.receptor.localPosition;
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);
Handles.color = Color.white;
Handles.DrawLine(parentPos, pos);
if (synapse.nucleus is ArrayPerceptoid perceptoid) {
if (drawnArrays.Contains(perceptoid.array))
// We already drawn this array
continue;
// if (synapse.nucleus is Perceptoid perceptoid && perceptoid.array != null) {
// // if (drawnArrays.Contains(perceptoid.array))
// // // We already drawn this array
// // continue;
drawnArrays.Add(perceptoid.array);
DrawArray(perceptoid.array, pos, size);
}
else {
// drawnArrays.Add(perceptoid.array);
// DrawArray(perceptoid.array, pos, size);
// }
// else {
DrawNucleus(synapse.nucleus, pos, maxValue, size);
row++;
}
DrawNucleus(synapse.nucleus, pos, maxValue, size);
row++;
// }
}
}
@ -298,16 +298,35 @@ public class NanoBrainInspector : Editor {
if (nucleus.isSleeping)
Handles.color = Color.darkRed;
else {
float brightness = nucleus.outputValue.magnitude / maxValue;
Handles.color = new Color(brightness, brightness, brightness);
if (Application.isPlaying) {
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);
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) {
alignment = TextAnchor.UpperCenter,
alignment = TextAnchor.MiddleCenter,
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);
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) {
Vector3 offset = new(size/4, size/4, 0);
Handles.color = Color.darkGray;
Handles.DrawSolidDisc(position + offset * 2, Vector3.forward, size);
Handles.color = Color.lightGray;
Handles.DrawSolidDisc(position + offset, Vector3.forward, size);
Handles.color = Color.white;
private void DrawArray(PercepteiArray array, Vector3 position, float size) {
Vector3 offset = new(size / 4, size / 4, 0);
Handles.color = Color.black;
Handles.DrawSolidDisc(position, Vector3.forward, size);
Vector3 labelPos = position - Vector3.down * (size + 0.2f); // below disc along up axis
GUIStyle style = new GUIStyle(EditorStyles.label) {
GUIStyle style = new(EditorStyles.label) {
alignment = TextAnchor.UpperCenter,
normal = { textColor = Color.white },
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);
// To do: add HandleClick (see above) to expand the array
@ -403,8 +419,18 @@ public class NanoBrainInspector : Editor {
return;
this.currentNucleus.name = EditorGUILayout.TextField(this.currentNucleus.name);
if (this.currentNucleus is Perceptoid currentPerceptoid) {
currentPerceptoid.receptor.thingType = EditorGUILayout.IntField("Thing Type", currentPerceptoid.receptor.thingType);
if (this.currentNucleus is Perceptoid perceptoid) {
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) {
EditorGUILayout.BeginHorizontal();
@ -427,12 +453,21 @@ public class NanoBrainInspector : Editor {
foreach (Synapse synapse in synapses) {
if (synapse.nucleus != null) {
EditorGUILayout.Space();
EditorGUI.BeginDisabledGroup(synapse.nucleus.isSleeping);
if (Application.isPlaying)
EditorGUILayout.FloatField(synapse.nucleus.name, synapse.nucleus.outputValue.magnitude * synapse.weight);
else {
EditorGUILayout.BeginHorizontal();
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"))
synapse.nucleus.RemoveReceiver(this.currentNucleus);
EditorGUILayout.EndHorizontal();

View File

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

View File

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