Improved ClusterReceptor
This commit is contained in:
parent
b0ee3add3a
commit
463bef0868
26
Cluster.cs
26
Cluster.cs
@ -78,21 +78,21 @@ public class Cluster : Nucleus {
|
||||
}
|
||||
}
|
||||
|
||||
// Copy nucleus arrays
|
||||
// Copy nucleus arrays for receptors
|
||||
for (int nucleusIx = 0; nucleusIx < prefabNuclei.Length; nucleusIx++) {
|
||||
Nucleus prefabReceptor = prefabNuclei[nucleusIx];
|
||||
if (prefabReceptor is not Receptor prefabNucleus)
|
||||
Nucleus prefabNucleus = prefabNuclei[nucleusIx];
|
||||
if (prefabNucleus is not IReceptor prefabReceptor)
|
||||
continue;
|
||||
|
||||
if (prefabNucleus.nucleiArray == null || prefabNucleus.nucleiArray.Length == 0)
|
||||
if (prefabReceptor.nucleiArray == null || prefabReceptor.nucleiArray.Length == 0)
|
||||
continue;
|
||||
|
||||
Receptor clonedNucleus = clonedNuclei[nucleusIx] as Receptor;
|
||||
if (prefabNucleus == prefabNucleus.nucleiArray[0]) {
|
||||
IReceptor clonedNucleus = clonedNuclei[nucleusIx] as IReceptor;
|
||||
if (prefabReceptor == prefabReceptor.nucleiArray[0]) {
|
||||
// We clone the array only for the first entry
|
||||
NucleusArray clonedArray = new(prefabNucleus.nucleiArray.Length, "array");
|
||||
NucleusArray clonedArray = new(prefabReceptor.nucleiArray.Length, "array");
|
||||
int arrayIx = 0;
|
||||
foreach (Nucleus prefabArrayNucleus in prefabNucleus.nucleiArray) {
|
||||
foreach (Nucleus prefabArrayNucleus in prefabReceptor.nucleiArray) {
|
||||
int arrayNucleusIx = GetNucleusIndex(prefabNuclei, prefabArrayNucleus);
|
||||
if (arrayNucleusIx >= 0) {
|
||||
Nucleus clonedArrayNucleus = clonedNuclei[arrayNucleusIx];
|
||||
@ -103,12 +103,13 @@ public class Cluster : Nucleus {
|
||||
}
|
||||
arrayIx++;
|
||||
}
|
||||
clonedNucleus.array = clonedArray;
|
||||
//clonedNucleus.array = clonedArray;
|
||||
clonedNucleus.nucleiArray = clonedArray.nuclei;
|
||||
}
|
||||
else {
|
||||
// The others will refer to the array created for the first nucleus in the array
|
||||
int firstNucleusIx = GetNucleusIndex(prefabNuclei, prefabNucleus.nucleiArray[0]);
|
||||
Receptor clonedFirstNucleus = clonedNuclei[firstNucleusIx] as Receptor;
|
||||
int firstNucleusIx = GetNucleusIndex(prefabNuclei, prefabReceptor.nucleiArray[0]);
|
||||
IReceptor clonedFirstNucleus = clonedNuclei[firstNucleusIx] as IReceptor;
|
||||
clonedNucleus.nucleiArray = clonedFirstNucleus.nucleiArray;
|
||||
}
|
||||
}
|
||||
@ -237,12 +238,13 @@ public class Cluster : Nucleus {
|
||||
return -1;
|
||||
}
|
||||
|
||||
protected int GetNucleusIndex(List<Nucleus> nuclei, Nucleus nucleus) {
|
||||
public int GetNucleusIndex(List<Nucleus> nuclei, Nucleus nucleus) {
|
||||
int i = 0;
|
||||
foreach (Nucleus nucleiElement in nuclei) {
|
||||
//for (int i = 0; i < nuclei.Length; i++) {
|
||||
if (nucleus == nucleiElement)
|
||||
return i;
|
||||
i++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -25,9 +25,9 @@ public class ClusterReceptor : Cluster, IReceptor {
|
||||
public override Nucleus ShallowCloneTo(Cluster parent) {
|
||||
ClusterReceptor clone = new(this.prefab, parent, this.name) {
|
||||
clusterPrefab = this.clusterPrefab,
|
||||
array = this.array
|
||||
//array = this.array
|
||||
};
|
||||
|
||||
//CloneFields(clone);
|
||||
// This cloned the prefab with the clusternuclei,
|
||||
// but did not clone the receivers outside the cluster
|
||||
RestoreExternalReceivers(clone, this.clusterPrefab, parent);
|
||||
@ -37,9 +37,10 @@ public class ClusterReceptor : Cluster, IReceptor {
|
||||
|
||||
public override Nucleus Clone(ClusterPrefab parent) {
|
||||
ClusterReceptor clone = new(prefab, parent, this.name) {
|
||||
array = this.array
|
||||
array = this._array
|
||||
};
|
||||
|
||||
//CloneFields(clone);
|
||||
foreach (Synapse synapse in this.synapses) {
|
||||
Synapse clonedSynapse = clone.AddSynapse(synapse.nucleus);
|
||||
clonedSynapse.weight = synapse.weight;
|
||||
@ -61,10 +62,29 @@ public class ClusterReceptor : Cluster, IReceptor {
|
||||
return clone;
|
||||
}
|
||||
|
||||
public override List<Nucleus> CollectReceivers() {
|
||||
List<Nucleus> receivers = new();
|
||||
foreach (Nucleus element in this.nucleiArray) {
|
||||
if (element is not Cluster clusterElement)
|
||||
continue;
|
||||
|
||||
//receivers.AddRange(clusterElement.CollectReceivers());
|
||||
foreach (Neuron output in clusterElement.outputs) {
|
||||
foreach (Nucleus receiver in output.receivers) {
|
||||
// Only add receivers outside clusterElement cluster
|
||||
if (receiver.clusterPrefab != clusterElement.prefab &&
|
||||
receivers.Contains(receiver) == false)
|
||||
receivers.Add(receiver);
|
||||
}
|
||||
}
|
||||
}
|
||||
return receivers;
|
||||
}
|
||||
|
||||
[SerializeReference]
|
||||
private NucleusArray _array;
|
||||
public NucleusArray array {
|
||||
get { return _array; }
|
||||
//get { return _array; }
|
||||
set { _array = value; }
|
||||
}
|
||||
|
||||
@ -76,11 +96,15 @@ public class ClusterReceptor : Cluster, IReceptor {
|
||||
}
|
||||
|
||||
public void AddReceptorElement(ClusterPrefab prefab) {
|
||||
this.nucleiArray = IReceptorHelpers.AddReceptorElement(this.nucleiArray, prefab);
|
||||
IReceptorHelpers.AddReceptorElement(this, prefab);
|
||||
}
|
||||
|
||||
public void RemoveReceptorElement() {
|
||||
this.nucleiArray = IReceptorHelpers.RemoveReceptorElement(this.nucleiArray);
|
||||
IReceptorHelpers.RemoveReceptorElement(this);
|
||||
}
|
||||
|
||||
public void AddArrayReceiver(Nucleus receiverToAdd, float weight = 1) {
|
||||
IReceptorHelpers.AddArrayReceiver(this, receiverToAdd, weight);
|
||||
}
|
||||
|
||||
public override void UpdateStateIsolated() {
|
||||
@ -107,7 +131,7 @@ public class ClusterReceptor : Cluster, IReceptor {
|
||||
}
|
||||
|
||||
public override void ProcessStimulus(Vector3 inputValue, int thingId = 0, string thingName = null) {
|
||||
this.array ??= new NucleusArray(this.parent);
|
||||
this.array.ProcessStimulus(thingId, inputValue, thingName);
|
||||
this._array ??= new NucleusArray(this.parent);
|
||||
this._array.ProcessStimulus(thingId, inputValue, thingName);
|
||||
}
|
||||
}
|
||||
@ -16,25 +16,9 @@ public class ClusterInspector : Editor {
|
||||
|
||||
#region Start
|
||||
|
||||
private void OnEnable() {
|
||||
// Load an icon from resources or assets
|
||||
Texture2D icon = Resources.Load<Texture2D>("ClusterIcon.png");
|
||||
|
||||
// Ensure the texture is valid; set the icon for the ScriptableObject
|
||||
if (icon != null) {
|
||||
EditorGUIUtility.SetIconForObject(target, icon);
|
||||
}
|
||||
}
|
||||
|
||||
public override VisualElement CreateInspectorGUI() {
|
||||
ClusterPrefab prefab = target as ClusterPrefab;
|
||||
|
||||
// string path = AssetDatabase.GetAssetPath(prefab); // or known path
|
||||
// Debug.Log($"{path}");
|
||||
// ClusterPrefab currentWrapper = AssetDatabase.LoadAssetAtPath<ClusterPrefab>(path);
|
||||
// if (currentWrapper == null)
|
||||
// Debug.LogError("CreateInspectorGUI: Cluster Prefab is not found on disk");
|
||||
|
||||
if (prefab != null)
|
||||
prefab.EnsureInitialization();
|
||||
|
||||
@ -482,9 +466,9 @@ public class ClusterInspector : Editor {
|
||||
fontStyle = FontStyle.Bold,
|
||||
};
|
||||
|
||||
if (nucleus is Receptor receptor1) {
|
||||
// draw the array size label
|
||||
if (nucleus is IReceptor receptor1) {
|
||||
if (expandArray) {
|
||||
// Put array indices above elements
|
||||
style.alignment = TextAnchor.LowerCenter;
|
||||
Vector3 labelPos1 = position + Vector3.down * (size + 5); // below disc
|
||||
int colonPos1 = nucleus.name.IndexOf(":");
|
||||
@ -494,6 +478,7 @@ public class ClusterInspector : Editor {
|
||||
}
|
||||
}
|
||||
else {
|
||||
// draw the array size label
|
||||
if (color.grayscale > 0.5f)
|
||||
style.normal.textColor = Color.black;
|
||||
else
|
||||
@ -503,33 +488,14 @@ public class ClusterInspector : Editor {
|
||||
}
|
||||
}
|
||||
|
||||
if (nucleus is ClusterReceptor clusterReceptor) {
|
||||
// draw the array size label
|
||||
if (expandArray && clusterReceptor.array.nuclei.First() == this.currentNucleus) {
|
||||
style.alignment = TextAnchor.LowerCenter;
|
||||
Vector3 labelPos2 = position + Vector3.down * (size + 5); // below disc
|
||||
int colonPos2 = nucleus.name.IndexOf(":");
|
||||
if (colonPos2 > 0) {
|
||||
string extName = nucleus.name[(colonPos2 + 2)..];
|
||||
Handles.Label(labelPos2, extName, style);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (color.grayscale > 0.5f)
|
||||
style.normal.textColor = Color.black;
|
||||
else
|
||||
style.normal.textColor = Color.white;
|
||||
Handles.Label(labelPosition, clusterReceptor.array.nuclei.Length.ToString(), style);
|
||||
style.normal.textColor = Color.white;
|
||||
}
|
||||
}
|
||||
|
||||
if (!expandArray || nucleus is not Receptor) {
|
||||
if (expandArray == false) {
|
||||
// put name below nucleus
|
||||
Vector3 labelPos = position - Vector3.down * (size + 5); // below neuron
|
||||
style.alignment = TextAnchor.UpperCenter;
|
||||
|
||||
int colonPos = nucleus.name.IndexOf(":");
|
||||
if (colonPos > 0 && colonPos < nucleus.name.Length - 2) {
|
||||
// if it is an array, we should not show the :0 of the first element
|
||||
string baseName = nucleus.name[..colonPos];
|
||||
Handles.Label(labelPos, baseName, style);
|
||||
}
|
||||
@ -652,22 +618,8 @@ public class ClusterInspector : Editor {
|
||||
if (this.currentNucleus is MemoryCell memory) {
|
||||
memory.staticMemory = EditorGUILayout.Toggle("Static Memory", memory.staticMemory);
|
||||
}
|
||||
// if (this.currentNucleus is ReceptorArray receptor) {
|
||||
// EditorGUILayout.BeginHorizontal();
|
||||
// EditorGUILayout.IntField("Receptor size", receptor.instances.Count());
|
||||
// if (GUILayout.Button("Add")) {
|
||||
// Undo.RecordObject(prefabAsset, "Receptor add " + prefabAsset.name);
|
||||
// receptor.AddReceptor(this.prefab);
|
||||
// anythingChanged = true;
|
||||
// }
|
||||
// if (GUILayout.Button("Del")) {
|
||||
// Undo.RecordObject(prefabAsset, "Receptor delete " + prefabAsset.name);
|
||||
// receptor.RemoveReceptor();
|
||||
// anythingChanged = true;
|
||||
// }
|
||||
// EditorGUILayout.EndHorizontal();
|
||||
// }
|
||||
if (this.currentNucleus is Receptor receptor1) {
|
||||
|
||||
if (this.currentNucleus is IReceptor receptor1) {
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
EditorGUILayout.IntField("Array size", receptor1.nucleiArray.Count());
|
||||
if (GUILayout.Button("Add")) {
|
||||
@ -684,21 +636,21 @@ public class ClusterInspector : Editor {
|
||||
}
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
else if (this.currentNucleus is ClusterReceptor receptor2) {
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
EditorGUILayout.IntField("Array size", receptor2.array.nuclei.Count());
|
||||
if (GUILayout.Button("Add")) {
|
||||
Undo.RecordObject(prefabAsset, "Array add " + prefabAsset.name);
|
||||
receptor2.array.AddNucleus(this.prefab);
|
||||
anythingChanged = true;
|
||||
}
|
||||
if (GUILayout.Button("Del")) {
|
||||
Undo.RecordObject(prefabAsset, "Array delete " + prefabAsset.name);
|
||||
receptor2.array.RemoveNucleus();
|
||||
anythingChanged = true;
|
||||
}
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
// else if (this.currentNucleus is ClusterReceptor receptor2) {
|
||||
// EditorGUILayout.BeginHorizontal();
|
||||
// EditorGUILayout.IntField("Array size", receptor2.array.nuclei.Count());
|
||||
// if (GUILayout.Button("Add")) {
|
||||
// Undo.RecordObject(prefabAsset, "Array add " + prefabAsset.name);
|
||||
// receptor2.array.AddNucleus(this.prefab);
|
||||
// anythingChanged = true;
|
||||
// }
|
||||
// if (GUILayout.Button("Del")) {
|
||||
// Undo.RecordObject(prefabAsset, "Array delete " + prefabAsset.name);
|
||||
// receptor2.array.RemoveNucleus();
|
||||
// anythingChanged = true;
|
||||
// }
|
||||
// EditorGUILayout.EndHorizontal();
|
||||
// }
|
||||
|
||||
|
||||
// Synapses
|
||||
@ -749,6 +701,7 @@ public class ClusterInspector : Editor {
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
|
||||
if (synapse.nucleus.parent != null && synapse.nucleus.parent != this.currentNucleus) {
|
||||
// If it is a cluster
|
||||
GUIStyle labelStyle = new(GUI.skin.label);
|
||||
float labelWidth = 200;
|
||||
if (synapse.nucleus.clusterPrefab != null) {
|
||||
@ -997,7 +950,7 @@ public class ClusterInspector : Editor {
|
||||
EditorGUILayout.EndHorizontal();
|
||||
if (connecting) {
|
||||
Nucleus nucleus = nuclei.ElementAt(selectedConnectNucleus);
|
||||
if (nucleus is Receptor receptor)
|
||||
if (nucleus is IReceptor receptor)
|
||||
receptor.AddArrayReceiver(this.currentNucleus);
|
||||
else if (nucleus is Neuron neuron)
|
||||
neuron.AddReceiver(this.currentNucleus);
|
||||
@ -1058,9 +1011,36 @@ public class ClusterInspector : Editor {
|
||||
protected virtual void ChangeSynapse(Synapse synapse, Neuron newNucleus) {
|
||||
Neuron synapseNeuron = synapse.nucleus as Neuron;
|
||||
if (synapse.nucleus.parent is Cluster subCluster && subCluster.prefab != this.prefab) {
|
||||
// it is a neuron in a subcluster
|
||||
synapseNeuron.RemoveReceiver(this.currentNucleus);
|
||||
newNucleus.AddReceiver(this.currentNucleus);
|
||||
if (synapse.nucleus.parent is ClusterReceptor receptor) {
|
||||
// the new nucleus is part of a (cluster) receptor,
|
||||
// so we have to change all synapses to this nucleus array elements
|
||||
int oldNucleusIx = subCluster.GetNucleusIndex(subCluster.clusterNuclei, synapse.nucleus);
|
||||
int newNucleusIx = subCluster.GetNucleusIndex(subCluster.clusterNuclei, newNucleus);
|
||||
foreach(Nucleus element in receptor.nucleiArray) {
|
||||
if (element is not ClusterReceptor clusterReceptor)
|
||||
continue;
|
||||
// Get the same neuron as the synapse.nucleus in a different element
|
||||
// of the ClusterReceptor array
|
||||
Nucleus oldElementNucleus = clusterReceptor.clusterNuclei[oldNucleusIx];
|
||||
if (oldElementNucleus is not Neuron oldElementNeuron)
|
||||
continue;
|
||||
// Get the same neuron as newNucleus in a different element
|
||||
// of the ClusterReceptor array
|
||||
Nucleus newElementNucleus = clusterReceptor.clusterNuclei[newNucleusIx];
|
||||
if (newElementNucleus is not Neuron newElementNeuron)
|
||||
continue;
|
||||
|
||||
oldElementNeuron.RemoveReceiver(this.currentNucleus);
|
||||
newElementNeuron.AddReceiver(this.currentNucleus);
|
||||
// Now find the synapse which pointed to the old Neuron
|
||||
// Synapse synapseForUpdate = this.currentNucleus.GetSynapse(oldElementNeuron);
|
||||
// synapseForUpdate.nucleus = newElementNeuron;
|
||||
}
|
||||
} else {
|
||||
// it is a neuron in a subcluster
|
||||
synapseNeuron.RemoveReceiver(this.currentNucleus);
|
||||
newNucleus.AddReceiver(this.currentNucleus);
|
||||
}
|
||||
}
|
||||
else {
|
||||
synapseNeuron.RemoveReceiver(this.currentNucleus);
|
||||
|
||||
57
IReceptor.cs
57
IReceptor.cs
@ -11,41 +11,66 @@ public interface IReceptor {
|
||||
public void AddReceptorElement(ClusterPrefab prefab);
|
||||
public void RemoveReceptorElement();
|
||||
|
||||
public void AddArrayReceiver(Nucleus receiverToAdd, float weight = 1);
|
||||
|
||||
public void ProcessStimulus(Vector3 inputValue, int thingId = 0, string thingName = null);
|
||||
}
|
||||
|
||||
public static class IReceptorHelpers {
|
||||
public static Nucleus[] AddReceptorElement(Nucleus[] nucleiArray, ClusterPrefab prefab) {
|
||||
if (nucleiArray.Length == 0) {
|
||||
|
||||
public static void AddReceptorElement(IReceptor receptor, ClusterPrefab prefab) {
|
||||
if (receptor.nucleiArray.Length == 0) {
|
||||
Debug.LogError("Empty perceptoid array, cannot add");
|
||||
return null;
|
||||
}
|
||||
int newLength = nucleiArray.Length + 1;
|
||||
int newLength = receptor.nucleiArray.Length + 1;
|
||||
Nucleus[] newArray = new Nucleus[newLength];
|
||||
|
||||
for (int i = 0; i < nucleiArray.Length; i++)
|
||||
newArray[i] = nucleiArray[i];
|
||||
if (nucleiArray[0] is Nucleus nucleus) {
|
||||
string baseName = receptor.GetName();
|
||||
int colonPos = baseName.IndexOf(":");
|
||||
if (colonPos > 0)
|
||||
baseName = baseName[..colonPos];
|
||||
|
||||
for (int i = 0; i < receptor.nucleiArray.Length; i++)
|
||||
newArray[i] = receptor.nucleiArray[i];
|
||||
if (receptor.nucleiArray[0] is Nucleus nucleus) {
|
||||
newArray[newLength - 1] = nucleus.Clone(prefab);
|
||||
newArray[newLength - 1].name += $": {newLength - 1}";
|
||||
newArray[newLength - 1].name = $"{baseName}: {newLength - 1}";
|
||||
}
|
||||
|
||||
return newArray;
|
||||
foreach (Nucleus element in receptor.nucleiArray) {
|
||||
if (element is IReceptor receptorElement) {
|
||||
receptorElement.nucleiArray = newArray;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static Nucleus[] RemoveReceptorElement(Nucleus[] nucleiArray) {
|
||||
int newLength = nucleiArray.Length - 1;
|
||||
public static void RemoveReceptorElement(IReceptor receptor) {
|
||||
int newLength = receptor.nucleiArray.Length - 1;
|
||||
if (newLength == 0) {
|
||||
Debug.LogWarning("Perceptoid array cannot be empty");
|
||||
return null;
|
||||
}
|
||||
Nucleus[] newPerceptei = new Nucleus[newLength];
|
||||
Nucleus[] newArray = new Nucleus[newLength];
|
||||
for (int i = 0; i < newLength; i++)
|
||||
newPerceptei[i] = nucleiArray[i];
|
||||
newArray[i] = receptor.nucleiArray[i];
|
||||
// Delete the last perception
|
||||
if (nucleiArray[newLength] is Nucleus nucleus)
|
||||
if (receptor.nucleiArray[newLength] is Nucleus nucleus)
|
||||
Neuron.Delete(nucleus); //this._nuclei[newLength]);
|
||||
|
||||
return newPerceptei;
|
||||
foreach (Nucleus element in receptor.nucleiArray) {
|
||||
if (element is IReceptor receptorElement) {
|
||||
receptorElement.nucleiArray = newArray;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void AddArrayReceiver(IReceptor receptor, Nucleus receiverToAdd, float weight = 1) {
|
||||
foreach (Nucleus element in receptor.nucleiArray) {
|
||||
if (element is Cluster cluster)
|
||||
cluster.defaultOutput.AddReceiver(receiverToAdd, weight);
|
||||
if (element is Neuron neuron)
|
||||
neuron.AddReceiver(receiverToAdd, weight);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
17
Receptor.cs
17
Receptor.cs
@ -48,11 +48,13 @@ public class Receptor : Neuron, IReceptor {
|
||||
}
|
||||
|
||||
public void AddReceptorElement(ClusterPrefab prefab) {
|
||||
this.nucleiArray = IReceptorHelpers.AddReceptorElement(this.nucleiArray, prefab);
|
||||
//this.nucleiArray = IReceptorHelpers.AddReceptorElement(this.nucleiArray, prefab);
|
||||
IReceptorHelpers.AddReceptorElement(this, prefab);
|
||||
}
|
||||
|
||||
public void RemoveReceptorElement() {
|
||||
this.nucleiArray = IReceptorHelpers.RemoveReceptorElement(this.nucleiArray);
|
||||
// this.nucleiArray = IReceptorHelpers.RemoveReceptorElement(this.nucleiArray);
|
||||
IReceptorHelpers.RemoveReceptorElement(this);
|
||||
}
|
||||
|
||||
// public override void AddReceiver(Nucleus receiverToAdd, float weight = 1) {
|
||||
@ -65,11 +67,12 @@ public class Receptor : Neuron, IReceptor {
|
||||
|
||||
// }
|
||||
public virtual void AddArrayReceiver(Nucleus receiverToAdd, float weight = 1) {
|
||||
foreach (Nucleus element in this._array.nuclei) {
|
||||
if (element is Neuron neuron) {
|
||||
neuron.AddReceiver(receiverToAdd, weight);
|
||||
}
|
||||
}
|
||||
IReceptorHelpers.AddArrayReceiver(this, receiverToAdd, weight);
|
||||
// foreach (Nucleus element in this._array.nuclei) {
|
||||
// if (element is Neuron neuron) {
|
||||
// neuron.AddReceiver(receiverToAdd, weight);
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
public override void UpdateStateIsolated() {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user