Improved receptor
This commit is contained in:
parent
537064d84b
commit
19398ade98
@ -263,35 +263,69 @@ public class ClusterInspector : Editor {
|
|||||||
|
|
||||||
// Draw selected Nucleus
|
// Draw selected Nucleus
|
||||||
if (expandArray) {
|
if (expandArray) {
|
||||||
float maxValue = 0;
|
if (this.currentNucleus is Receptor receptor) {
|
||||||
foreach (Nucleus nucleus in this.currentNucleus.array.nuclei) {
|
float maxValue = 0;
|
||||||
float value = length(nucleus.outputValue);
|
foreach (Nucleus nucleus in receptor.instances) {
|
||||||
if (value > maxValue)
|
float value = length(nucleus.outputValue);
|
||||||
maxValue = value;
|
if (value > maxValue)
|
||||||
}
|
maxValue = value;
|
||||||
|
}
|
||||||
|
|
||||||
float spacing = 400f / this.currentNucleus.array.nuclei.Count();
|
float spacing = 400f / receptor.instances.Count();
|
||||||
float margin = 10 + spacing / 2;
|
float margin = 10 + spacing / 2;
|
||||||
float xMin = 150 - size;
|
float xMin = 150 - size;
|
||||||
float xMax = 150 + size;
|
float xMax = 150 + size;
|
||||||
float yMin = 10 + margin - size / 2;
|
float yMin = 10 + margin - size / 2;
|
||||||
float yMax = 400 - margin + size;
|
float yMax = 400 - margin + size;
|
||||||
Vector3[] verts = new Vector3[4] {
|
Vector3[] verts = new Vector3[4] {
|
||||||
new(xMin, yMin, 0),
|
new(xMin, yMin, 0),
|
||||||
new(xMax, yMin, 0),
|
new(xMax, yMin, 0),
|
||||||
new(xMax, yMax, 0),
|
new(xMax, yMax, 0),
|
||||||
new(xMin, yMax, 0)
|
new(xMin, yMax, 0)
|
||||||
};
|
};
|
||||||
Handles.color = Color.black;
|
Handles.color = Color.black;
|
||||||
Handles.DrawAAConvexPolygon(verts);
|
Handles.DrawAAConvexPolygon(verts);
|
||||||
int row = 0;
|
int row = 0;
|
||||||
foreach (Nucleus nucleus in this.currentNucleus.array.nuclei) {
|
foreach (Nucleus nucleus in receptor.instances) {
|
||||||
Vector3 pos = new(150, margin + row * spacing, 0.0f);
|
Vector3 pos = new(150, margin + row * spacing, 0.0f);
|
||||||
Handles.color = Color.white;
|
Handles.color = Color.white;
|
||||||
// The selected nucleus highlight ring
|
// The selected nucleus highlight ring
|
||||||
Handles.DrawSolidDisc(pos, Vector3.forward, size + 2);
|
Handles.DrawSolidDisc(pos, Vector3.forward, size + 2);
|
||||||
DrawNucleus(nucleus, pos, maxValue, size);
|
DrawNucleus(nucleus, pos, maxValue, size);
|
||||||
row++;
|
row++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
float maxValue = 0;
|
||||||
|
foreach (Nucleus nucleus in this.currentNucleus.array.nuclei) {
|
||||||
|
float value = length(nucleus.outputValue);
|
||||||
|
if (value > maxValue)
|
||||||
|
maxValue = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
float spacing = 400f / this.currentNucleus.array.nuclei.Count();
|
||||||
|
float margin = 10 + spacing / 2;
|
||||||
|
float xMin = 150 - size;
|
||||||
|
float xMax = 150 + size;
|
||||||
|
float yMin = 10 + margin - size / 2;
|
||||||
|
float yMax = 400 - margin + size;
|
||||||
|
Vector3[] verts = new Vector3[4] {
|
||||||
|
new(xMin, yMin, 0),
|
||||||
|
new(xMax, yMin, 0),
|
||||||
|
new(xMax, yMax, 0),
|
||||||
|
new(xMin, yMax, 0)
|
||||||
|
};
|
||||||
|
Handles.color = Color.black;
|
||||||
|
Handles.DrawAAConvexPolygon(verts);
|
||||||
|
int row = 0;
|
||||||
|
foreach (Nucleus nucleus in this.currentNucleus.array.nuclei) {
|
||||||
|
Vector3 pos = new(150, margin + row * spacing, 0.0f);
|
||||||
|
Handles.color = Color.white;
|
||||||
|
// The selected nucleus highlight ring
|
||||||
|
Handles.DrawSolidDisc(pos, Vector3.forward, size + 2);
|
||||||
|
DrawNucleus(nucleus, pos, maxValue, size);
|
||||||
|
row++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -431,9 +465,20 @@ public class ClusterInspector : Editor {
|
|||||||
if ((!expandArray || nucleus.array.nuclei.First() != this.currentNucleus) && nucleus.array.nuclei.Count() > 1) {
|
if ((!expandArray || nucleus.array.nuclei.First() != this.currentNucleus) && nucleus.array.nuclei.Count() > 1) {
|
||||||
Handles.Label(labelPosition, nucleus.array.nuclei.Count().ToString(), style);
|
Handles.Label(labelPosition, nucleus.array.nuclei.Count().ToString(), style);
|
||||||
}
|
}
|
||||||
if (!expandArray && nucleus is ReceptorArray receptor) {
|
if (nucleus is Receptor receptor) {
|
||||||
Handles.Label(labelPosition, receptor.receptors.Count().ToString(), style);
|
Handles.Label(labelPosition, receptor.instances.Count().ToString(), style);
|
||||||
}
|
}
|
||||||
|
// else if (nucleus is ReceptorInstance receptorI) {
|
||||||
|
// if (expandArray) {
|
||||||
|
// int arrayIx = 0;
|
||||||
|
// foreach (ReceptorInstance n in receptorI.receptorArray.receptors) {
|
||||||
|
// if (n == receptorI)
|
||||||
|
// break;
|
||||||
|
// arrayIx++;
|
||||||
|
// }
|
||||||
|
// Handles.Label(labelPosition, $"[{arrayIx}]", style);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
if (expandArray && nucleus.array.nuclei.First() == this.currentNucleus) {
|
if (expandArray && nucleus.array.nuclei.First() == this.currentNucleus) {
|
||||||
int arrayIx = 0;
|
int arrayIx = 0;
|
||||||
foreach (Nucleus n in nucleus.array.nuclei) {
|
foreach (Nucleus n in nucleus.array.nuclei) {
|
||||||
@ -494,10 +539,12 @@ public class ClusterInspector : Editor {
|
|||||||
|
|
||||||
private void HandleClicked(Nucleus nucleus) {
|
private void HandleClicked(Nucleus nucleus) {
|
||||||
if (nucleus == this.currentNucleus) {
|
if (nucleus == this.currentNucleus) {
|
||||||
if (nucleus is Nucleus n) {
|
expandArray = !expandArray;
|
||||||
expandArray = !expandArray;
|
}
|
||||||
return;
|
else if (nucleus is ReceptorInstance receptor) {
|
||||||
}
|
expandArray = false;
|
||||||
|
this.currentNucleus = receptor.receptor;
|
||||||
|
BuildLayers();
|
||||||
}
|
}
|
||||||
else if (nucleus is Nucleus n) {
|
else if (nucleus is Nucleus n) {
|
||||||
this.currentNucleus = n;
|
this.currentNucleus = n;
|
||||||
@ -562,9 +609,9 @@ public class ClusterInspector : Editor {
|
|||||||
if (this.currentNucleus is MemoryCell memory) {
|
if (this.currentNucleus is MemoryCell memory) {
|
||||||
memory.staticMemory = EditorGUILayout.Toggle("Static Memory", memory.staticMemory);
|
memory.staticMemory = EditorGUILayout.Toggle("Static Memory", memory.staticMemory);
|
||||||
}
|
}
|
||||||
if (this.currentNucleus is ReceptorArray receptor) {
|
if (this.currentNucleus is Receptor receptor) {
|
||||||
EditorGUILayout.BeginHorizontal();
|
EditorGUILayout.BeginHorizontal();
|
||||||
EditorGUILayout.IntField("Receptor size", receptor.receptors.Count());
|
EditorGUILayout.IntField("Receptor size", receptor.instances.Count());
|
||||||
if (GUILayout.Button("Add")) {
|
if (GUILayout.Button("Add")) {
|
||||||
Undo.RecordObject(prefabAsset, "Receptor add " + prefabAsset.name);
|
Undo.RecordObject(prefabAsset, "Receptor add " + prefabAsset.name);
|
||||||
receptor.AddReceptor(this.prefab);
|
receptor.AddReceptor(this.prefab);
|
||||||
@ -621,8 +668,11 @@ public class ClusterInspector : Editor {
|
|||||||
else {
|
else {
|
||||||
EditorGUILayout.BeginHorizontal();
|
EditorGUILayout.BeginHorizontal();
|
||||||
EditorGUILayout.LabelField(synapse.nucleus.name);
|
EditorGUILayout.LabelField(synapse.nucleus.name);
|
||||||
if (GUILayout.Button("Disconnect"))
|
if (GUILayout.Button("Disconnect")) {
|
||||||
synapse.nucleus.RemoveReceiver(this.currentNucleus);
|
synapse.nucleus.RemoveReceiver(this.currentNucleus);
|
||||||
|
this.prefab.GarbageCollection();
|
||||||
|
anythingChanged = true;
|
||||||
|
}
|
||||||
EditorGUILayout.EndHorizontal();
|
EditorGUILayout.EndHorizontal();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -701,8 +751,8 @@ public class ClusterInspector : Editor {
|
|||||||
|
|
||||||
void OnSceneGUI(SceneView sceneView) {
|
void OnSceneGUI(SceneView sceneView) {
|
||||||
if (this.gameObject != null) {
|
if (this.gameObject != null) {
|
||||||
if (this.currentNucleus is ReceptorArray receptor) {
|
if (this.currentNucleus is Receptor receptor && expandArray) {
|
||||||
foreach (Nucleus nucleus in receptor.receptors) {
|
foreach (Nucleus nucleus in receptor.instances) {
|
||||||
Vector3 worldVector = this.gameObject.transform.TransformVector(nucleus.outputValue);
|
Vector3 worldVector = this.gameObject.transform.TransformVector(nucleus.outputValue);
|
||||||
Handles.color = Color.yellow;
|
Handles.color = Color.yellow;
|
||||||
Handles.DrawLine(this.gameObject.transform.position, this.gameObject.transform.position + worldVector);
|
Handles.DrawLine(this.gameObject.transform.position, this.gameObject.transform.position + worldVector);
|
||||||
@ -819,7 +869,7 @@ public class ClusterInspector : Editor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void AddReceptorInput(Nucleus nucleus) {
|
protected virtual void AddReceptorInput(Nucleus nucleus) {
|
||||||
ReceptorArray newReceptor = new(this.prefab, "New Receptor");
|
Receptor newReceptor = new(this.prefab, "New Receptor");
|
||||||
newReceptor.AddReceiver(nucleus);
|
newReceptor.AddReceiver(nucleus);
|
||||||
this.currentNucleus = newReceptor;
|
this.currentNucleus = newReceptor;
|
||||||
BuildLayers();
|
BuildLayers();
|
||||||
|
|||||||
@ -18,31 +18,43 @@ public class ReceptorInstance : Nucleus {
|
|||||||
// We explicitly do not add this to the prefab, as it is serialized in the ReceptorArray
|
// We explicitly do not add this to the prefab, as it is serialized in the ReceptorArray
|
||||||
}
|
}
|
||||||
public override Nucleus ShallowCloneTo(Cluster parent) {
|
public override Nucleus ShallowCloneTo(Cluster parent) {
|
||||||
ReceptorInstance clone = new(parent, name + " +1");
|
ReceptorInstance clone = new(parent, name + " +1") {
|
||||||
|
receptor = this.receptor
|
||||||
|
};
|
||||||
return clone;
|
return clone;
|
||||||
}
|
}
|
||||||
public override Nucleus Clone(ClusterPrefab prefab) {
|
public override Nucleus Clone(ClusterPrefab prefab) {
|
||||||
ReceptorInstance clone = new(prefab, name);
|
ReceptorInstance clone = new(prefab, name) {
|
||||||
|
receptor = this.receptor
|
||||||
|
};
|
||||||
return clone;
|
return clone;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[SerializeReference]
|
||||||
|
public Receptor receptor;
|
||||||
|
|
||||||
public override void UpdateStateIsolated() {
|
public override void UpdateStateIsolated() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Serializable]
|
[Serializable]
|
||||||
public class ReceptorArray : Nucleus {
|
public class Receptor : Nucleus {
|
||||||
public ReceptorArray(Cluster parent, string name) {
|
public Receptor(Cluster parent, string name) {
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this._receptors = new ReceptorInstance[1];
|
this._instances = new ReceptorInstance[1];
|
||||||
this._receptors[0] = new ReceptorInstance(parent, this.name + "[0]");
|
this._instances[0] = new ReceptorInstance(parent, this.name + "[0]") {
|
||||||
|
receptor = this
|
||||||
|
};
|
||||||
this.parent?.nuclei.Add(this);
|
this.parent?.nuclei.Add(this);
|
||||||
}
|
}
|
||||||
public ReceptorArray(ClusterPrefab prefab, string name) {
|
public Receptor(ClusterPrefab prefab, string name) {
|
||||||
this.cluster = prefab;
|
this.cluster = prefab;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this._receptors = new ReceptorInstance[1];
|
this._instances = new ReceptorInstance[1];
|
||||||
this._receptors[0] = new ReceptorInstance(prefab, this.name + "[0]");
|
this._instances[0] = new ReceptorInstance(prefab, this.name + "[0]") {
|
||||||
|
receptor = this
|
||||||
|
};
|
||||||
if (this.cluster != null)
|
if (this.cluster != null)
|
||||||
this.cluster.nuclei.Add(this);
|
this.cluster.nuclei.Add(this);
|
||||||
else
|
else
|
||||||
@ -51,22 +63,26 @@ public class ReceptorArray : Nucleus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public override Nucleus ShallowCloneTo(Cluster parent) {
|
public override Nucleus ShallowCloneTo(Cluster parent) {
|
||||||
ReceptorArray clone = new(parent, name) {
|
Receptor clone = new(parent, name) {
|
||||||
_receptors = new ReceptorInstance[this.receptors.Length]
|
_instances = new ReceptorInstance[this.instances.Length]
|
||||||
};
|
};
|
||||||
for (int ix = 0; ix < this.receptors.Length; ix++) {
|
for (int ix = 0; ix < this.instances.Length; ix++) {
|
||||||
clone._receptors[ix] = new ReceptorInstance(parent, $"{this.name} [{ix}]");
|
clone._instances[ix] = new ReceptorInstance(parent, $"{this.name} [{ix}]") {
|
||||||
|
receptor = clone
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return clone;
|
return clone;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Nucleus Clone(ClusterPrefab prefab) {
|
public override Nucleus Clone(ClusterPrefab prefab) {
|
||||||
ReceptorArray clone = new(prefab, this.name) {
|
Receptor clone = new(prefab, this.name) {
|
||||||
|
_instances = new ReceptorInstance[this.instances.Length]
|
||||||
};
|
};
|
||||||
clone._receptors = new ReceptorInstance[this.receptors.Length];
|
for (int ix = 0; ix < this.instances.Length; ix++) {
|
||||||
for (int ix = 0; ix < this.receptors.Length; ix++) {
|
clone._instances[ix] = new ReceptorInstance(prefab, this.name) {
|
||||||
clone._receptors[ix] = new ReceptorInstance(prefab, this.name);
|
receptor = this
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (Synapse synapse in this.synapses) {
|
foreach (Synapse synapse in this.synapses) {
|
||||||
@ -80,42 +96,44 @@ public class ReceptorArray : Nucleus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
[SerializeReference]
|
[SerializeReference]
|
||||||
private ReceptorInstance[] _receptors;
|
private ReceptorInstance[] _instances;
|
||||||
public ReceptorInstance[] receptors {
|
public ReceptorInstance[] instances {
|
||||||
get {
|
get {
|
||||||
return _receptors;
|
return _instances;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddReceptor(ClusterPrefab prefab) {
|
public void AddReceptor(ClusterPrefab prefab) {
|
||||||
if (this._receptors.Length == 0) {
|
if (this._instances.Length == 0) {
|
||||||
Debug.LogError("Empty receptor array, cannot add");
|
Debug.LogError("Empty receptor array, cannot add");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int newLength = this._receptors.Length + 1;
|
int newLength = this._instances.Length + 1;
|
||||||
ReceptorInstance[] newArray = new ReceptorInstance[newLength];
|
ReceptorInstance[] newArray = new ReceptorInstance[newLength];
|
||||||
|
|
||||||
for (int i = 0; i < this._receptors.Length; i++)
|
for (int i = 0; i < this._instances.Length; i++)
|
||||||
newArray[i] = this._receptors[i];
|
newArray[i] = this._instances[i];
|
||||||
newArray[newLength - 1] = (ReceptorInstance)this._receptors[0].Clone(prefab);
|
ReceptorInstance newReceptor = (ReceptorInstance)this._instances[0].Clone(prefab);
|
||||||
|
newReceptor.name = $"{this.name} [{this._instances.Length}]";
|
||||||
|
newArray[newLength - 1] = newReceptor;
|
||||||
|
|
||||||
this._receptors = newArray;
|
this._instances = newArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemoveReceptor() {
|
public void RemoveReceptor() {
|
||||||
int newLength = this._receptors.Length - 1;
|
int newLength = this._instances.Length - 1;
|
||||||
if (newLength == 0) {
|
if (newLength == 0) {
|
||||||
Debug.LogWarning("Receptor array cannot be empty");
|
Debug.LogWarning("Receptor array cannot be empty");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ReceptorInstance[] newPerceptei = new ReceptorInstance[newLength];
|
ReceptorInstance[] newPerceptei = new ReceptorInstance[newLength];
|
||||||
for (int i = 0; i < newLength; i++)
|
for (int i = 0; i < newLength; i++)
|
||||||
newPerceptei[i] = this._receptors[i];
|
newPerceptei[i] = this._instances[i];
|
||||||
// Delete the last perception
|
// Delete the last perception
|
||||||
if (this._receptors[newLength] is Nucleus nucleus)
|
if (this._instances[newLength] is Nucleus nucleus)
|
||||||
Neuron.Delete(nucleus); //this._nuclei[newLength]);
|
Neuron.Delete(nucleus); //this._nuclei[newLength]);
|
||||||
|
|
||||||
this._receptors = newPerceptei;
|
this._instances = newPerceptei;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Dictionary<int, Nucleus> thingReceivers = new();
|
private Dictionary<int, Nucleus> thingReceivers = new();
|
||||||
@ -152,6 +170,8 @@ public class ReceptorArray : Nucleus {
|
|||||||
private void CleanupReceivers() {
|
private void CleanupReceivers() {
|
||||||
// Remove a thing-receiver connection when the nucleus is inactive
|
// Remove a thing-receiver connection when the nucleus is inactive
|
||||||
List<int> receiversToRemove = new();
|
List<int> receiversToRemove = new();
|
||||||
|
thingReceivers ??= new();
|
||||||
|
|
||||||
foreach (KeyValuePair<int, Nucleus> item in thingReceivers) {
|
foreach (KeyValuePair<int, Nucleus> item in thingReceivers) {
|
||||||
if (item.Value.isSleeping)
|
if (item.Value.isSleeping)
|
||||||
receiversToRemove.Add(item.Key);
|
receiversToRemove.Add(item.Key);
|
||||||
@ -165,7 +185,8 @@ public class ReceptorArray : Nucleus {
|
|||||||
int colonPos = selectedReceiver.name.IndexOf(":");
|
int colonPos = selectedReceiver.name.IndexOf(":");
|
||||||
if (colonPos > 0)
|
if (colonPos > 0)
|
||||||
selectedReceiver.name = selectedReceiver.name[..colonPos];
|
selectedReceiver.name = selectedReceiver.name[..colonPos];
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Nucleus SelectReceptor(int thingId, float3 inputValue) {
|
private Nucleus SelectReceptor(int thingId, float3 inputValue) {
|
||||||
@ -173,7 +194,7 @@ public class ReceptorArray : Nucleus {
|
|||||||
float inputMagnitude = length(inputValue);
|
float inputMagnitude = length(inputValue);
|
||||||
Nucleus selectedReceiver = null;
|
Nucleus selectedReceiver = null;
|
||||||
float selectedMagnitude = 0;
|
float selectedMagnitude = 0;
|
||||||
foreach (Nucleus receiver in this._receptors) {
|
foreach (Nucleus receiver in this._instances) {
|
||||||
if (thingReceivers.ContainsValue(receiver) == false) {
|
if (thingReceivers.ContainsValue(receiver) == false) {
|
||||||
// We found an unusued receiver
|
// We found an unusued receiver
|
||||||
Debug.Log($"{thingId} -> [{receiver.name}]");
|
Debug.Log($"{thingId} -> [{receiver.name}]");
|
||||||
@ -217,21 +238,22 @@ public class ReceptorArray : Nucleus {
|
|||||||
float3 sum = this.bias;
|
float3 sum = this.bias;
|
||||||
|
|
||||||
// Receptors do not have inputs, so we ignore the synapses
|
// Receptors do not have inputs, so we ignore the synapses
|
||||||
foreach (Nucleus nucleus in this._receptors)
|
foreach (Nucleus nucleus in this._instances)
|
||||||
sum += nucleus.outputValue;
|
sum += nucleus.outputValue;
|
||||||
|
|
||||||
this.outputValue = sum / _receptors.Length;
|
this.outputValue = sum / _instances.Length;
|
||||||
this.stale = 0;
|
this.stale = 0;
|
||||||
|
|
||||||
UpdateNuclei();
|
UpdateNuclei();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void UpdateNuclei() {
|
public override void UpdateNuclei() {
|
||||||
foreach (Nucleus nucleus in this.receptors) {
|
foreach (Nucleus nucleus in this.instances) {
|
||||||
nucleus.stale++;
|
nucleus.stale++;
|
||||||
if (nucleus.stale > staleValueForSleep && lengthsq(nucleus.outputValue) > 0) {
|
if (nucleus.stale > staleValueForSleep && lengthsq(nucleus.outputValue) > 0) {
|
||||||
nucleus.outputValue = Vector3.zero;
|
nucleus.outputValue = Vector3.zero;
|
||||||
this.UpdateStateIsolated();
|
//this.UpdateStateIsolated();
|
||||||
|
this.parent.UpdateFromNucleus(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user