diff --git a/ClusterPrefab.cs b/ClusterPrefab.cs index 2fc6867..0839d42 100644 --- a/ClusterPrefab.cs +++ b/ClusterPrefab.cs @@ -4,7 +4,6 @@ using UnityEngine; [CreateAssetMenu(menuName = "Passer/Cluster")] public class ClusterPrefab : ScriptableObject { // The ScriptableObject asset from which the runtime object has been created - public string hello = "hello"; [SerializeReference] public List nuclei = new(); diff --git a/Editor/ClusterInspector.cs b/Editor/ClusterInspector.cs index 1710cb7..b8b787d 100644 --- a/Editor/ClusterInspector.cs +++ b/Editor/ClusterInspector.cs @@ -77,7 +77,7 @@ public class ClusterInspector : Editor { private bool expandArray = false; ClusterWrapper currentWrapper; - PopupField outputsField; + readonly PopupField outputsField; public GraphView(ClusterPrefab prefab) { this.prefab = prefab; @@ -414,37 +414,37 @@ public class ClusterInspector : Editor { fontStyle = FontStyle.Bold, }; //if (nucleus is Nucleus neuron) { - if (nucleus.array == null || nucleus.array.nuclei == null || nucleus.array.nuclei.Count() == 0) - nucleus.array = new NucleusArray(nucleus); + if (nucleus.array == null || nucleus.array.nuclei == null || nucleus.array.nuclei.Count() == 0) + nucleus.array = new NucleusArray(nucleus); - if ((!expandArray || nucleus.array.nuclei.First() != this.currentNucleus) && nucleus.array.nuclei.Count() > 1) { - Handles.Label(labelPosition, nucleus.array.nuclei.Count().ToString(), style); + if ((!expandArray || nucleus.array.nuclei.First() != this.currentNucleus) && nucleus.array.nuclei.Count() > 1) { + Handles.Label(labelPosition, nucleus.array.nuclei.Count().ToString(), style); + } + if (expandArray && nucleus.array.nuclei.First() == this.currentNucleus) { + int arrayIx = 0; + foreach (Nucleus n in nucleus.array.nuclei) { + if (n == nucleus) + break; + arrayIx++; } - if (expandArray && nucleus.array.nuclei.First() == this.currentNucleus) { - int arrayIx = 0; - foreach (Nucleus n in nucleus.array.nuclei) { - if (n == nucleus) - break; - arrayIx++; - } - Handles.Label(labelPosition, $"[{arrayIx}]", style); - } - else { - style.alignment = TextAnchor.UpperCenter; - Vector3 labelPos = position - Vector3.down * (size + 10f); // below disc along up axis - int colonPos = nucleus.name.IndexOf(":"); - if (colonPos > 0) { - string baseName = nucleus.name[..colonPos]; - Handles.Label(labelPos, baseName, style); - } - else - Handles.Label(labelPos, nucleus.name, style); + Handles.Label(labelPosition, $"[{arrayIx}]", style); + } + else { + style.alignment = TextAnchor.UpperCenter; + Vector3 labelPos = position - Vector3.down * (size + 10f); // below disc along up axis + int colonPos = nucleus.name.IndexOf(":"); + if (colonPos > 0) { + string baseName = nucleus.name[..colonPos]; + Handles.Label(labelPos, baseName, style); } + else + Handles.Label(labelPos, nucleus.name, style); + } - if (nucleus is Cluster) { - Handles.color = Color.white; - Handles.DrawWireDisc(position, Vector3.forward, size + 10); - } + if (nucleus is Cluster) { + Handles.color = Color.white; + Handles.DrawWireDisc(position, Vector3.forward, size + 10); + } // } // else { // style.alignment = TextAnchor.UpperCenter; @@ -528,6 +528,9 @@ public class ClusterInspector : Editor { }; GUILayout.Label(this.currentNucleus.GetType().ToString(), headerStyle); + if (this.currentNucleus is Neuron neuron1) { + neuron1.type = (Nucleus.Type)EditorGUILayout.EnumPopup(neuron1.type); + } string newName = EditorGUILayout.TextField(this.currentNucleus.name, boldTextFieldStyle); if (newName != this.currentNucleus.name) { this.currentNucleus.name = newName; @@ -707,15 +710,24 @@ public class ClusterInspector : Editor { protected virtual void DeleteNeuron(Nucleus nucleus) { if (nucleus == null) return; - if (nucleus.cluster != null) - this.currentNucleus = nucleus.cluster.output; + foreach (Nucleus receiver in nucleus.receivers) { if (receiver != null) { this.currentNucleus = receiver; break; } } + this.prefab.nuclei.Remove(nucleus); + + if (outputsField.value == nucleus.name) { + this.prefab.RefreshOutputs(); + outputsField.choices = this.prefab.outputs.Select(output => output.name).ToList(); + outputsField.index = 0; + } + Neuron.Delete(nucleus); + + this.currentNucleus = this.prefab.output; BuildLayers(); } diff --git a/Neuron.cs b/Neuron.cs index 4c7d0eb..2b74465 100644 --- a/Neuron.cs +++ b/Neuron.cs @@ -26,6 +26,8 @@ public class Neuron : Nucleus { #region Serialization + public Type type = Type.Neuron; + public enum CurvePresets { Linear, Power, @@ -150,6 +152,7 @@ public class Neuron : Nucleus { protected virtual void CloneFields(Neuron clone) { clone.array = null; clone.bias = this.bias; + clone.type = this.type; clone.curve = this.curve; clone.curvePreset = this.curvePreset; clone.curveMax = this.curveMax; @@ -181,28 +184,55 @@ public class Neuron : Nucleus { } public override void UpdateStateIsolated() { - Vector3 sum = this.bias; - int n = 0; + switch (this.type) { + case Type.Neuron: + UpdateSum(); + break; + case Type.Pulsar: + UpdateProduct(); + break; + default: + UpdateSum(); + break; + } + // Vector3 sum = this.bias; + // int n = 0; - //Applying the weight factgors - foreach (Synapse synapse in this.synapses) { + // //Applying the weight factgors + // foreach (Synapse synapse in this.synapses) { + // sum += synapse.weight * synapse.nucleus.outputValue; + + // // Perhaps synapses should be removed when the output value goes to 0.... + // if (lengthsq(synapse.nucleus.outputValue) != 0) { + // n++; + // this.stale = 0; + // } + // } + // if (this.average && n > 0) + // sum /= n; + + // // Activation function + // float3 result = Activation(sum); + // if (this.stale > staleValueForSleep) + // this.outputValue = new float3(0, 0, 0); + // else + // this.outputValue = result; + } + + public void UpdateSum() { + Vector3 sum = this.bias; + foreach (Synapse synapse in this.synapses) sum += synapse.weight * synapse.nucleus.outputValue; - // Perhaps synapses should be removed when the output value goes to 0.... - if (lengthsq(synapse.nucleus.outputValue) != 0) { - n++; - this.stale = 0; - } - } - if (this.average && n > 0) - sum /= n; + this.outputValue = Activation(sum); + } - // Activation function - float3 result = Activation(sum); - if (this.stale > staleValueForSleep) - this.outputValue = new float3(0, 0, 0); - else - this.outputValue = result; + public void UpdateProduct() { + float3 product = this.bias; + foreach (Synapse synapse in this.synapses) + product *= synapse.weight * synapse.nucleus.outputValue; + + this.outputValue = Activation(product); } protected float3 Activation(float3 input) { @@ -236,4 +266,5 @@ public class Neuron : Nucleus { this.bias = inputValue; this.parent.UpdateFromNucleus(this); } + } \ No newline at end of file