From 5fea9880de83aa50c9f721dad413cf4e250872a8 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Mon, 16 Feb 2026 12:30:07 +0100 Subject: [PATCH] Added ClusterReceptor --- ClusterReceptor.cs | 68 ++++++++++++++++++++++++++++++++++++++ ClusterReceptor.cs.meta | 2 ++ Editor/ClusterInspector.cs | 54 ++++++++++++++++++++++++++++++ Nucleus.cs | 3 +- 4 files changed, 126 insertions(+), 1 deletion(-) create mode 100644 ClusterReceptor.cs create mode 100644 ClusterReceptor.cs.meta diff --git a/ClusterReceptor.cs b/ClusterReceptor.cs new file mode 100644 index 0000000..38ecb0d --- /dev/null +++ b/ClusterReceptor.cs @@ -0,0 +1,68 @@ +using System; +using UnityEngine; +using Unity.Mathematics; +using static Unity.Mathematics.math; + + +[Serializable] +public class ClusterReceptor : Cluster { + public ClusterReceptor(ClusterPrefab prefab, Cluster parent, string name) : base(prefab, parent) { + this.name = name; + this.array ??= new NucleusArray(this); + } + public ClusterReceptor(ClusterPrefab prefab, ClusterPrefab parent, string name) : base(prefab, parent) { + this.name = name; + this.array = new NucleusArray(this); + } + + public override Nucleus ShallowCloneTo(Cluster parent) { + ClusterReceptor clone = new(this.prefab, parent, this.name) { + array = this.array + }; + return clone; + } + + public override Nucleus Clone(ClusterPrefab prefab) { + ClusterReceptor clone = new(prefab, parent, this.name); + clone.array = this.array; + + foreach (Synapse synapse in this.synapses) { + Synapse clonedSynapse = clone.AddSynapse(synapse.nucleus); + clonedSynapse.weight = synapse.weight; + } + foreach (Nucleus receiver in this.receivers) { + clone.AddReceiver(receiver); + } + return clone; + } + + public NucleusArray array { get; set; } + + public override void UpdateStateIsolated() { + float3 sum = this.bias; + + foreach (Nucleus nucleus in this.sortedNuclei) + nucleus.UpdateStateIsolated(); + + this.outputValue = this.output.outputValue; + this.stale = 0; + + UpdateNuclei(); + } + + public override void UpdateNuclei() { + this.stale++; + if (this.stale > staleValueForSleep && lengthsq(this.bias) > 0) { + this.bias = new float3(0, 0, 0); + this.parent.UpdateFromNucleus(this); + } + + foreach (Nucleus nucleus in this.nuclei) + nucleus.UpdateNuclei(); + } + + public virtual void ProcessStimulus(Vector3 inputValue, int thingId = 0, string thingName = null) { + this.array ??= new NucleusArray(this.parent); + this.array.ProcessStimulus(thingId, inputValue, thingName); + } +} \ No newline at end of file diff --git a/ClusterReceptor.cs.meta b/ClusterReceptor.cs.meta new file mode 100644 index 0000000..027f164 --- /dev/null +++ b/ClusterReceptor.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 4f64f5d72a422a7c8bb9ace598432aad \ No newline at end of file diff --git a/Editor/ClusterInspector.cs b/Editor/ClusterInspector.cs index e4813da..b8b8e30 100644 --- a/Editor/ClusterInspector.cs +++ b/Editor/ClusterInspector.cs @@ -340,6 +340,13 @@ public class ClusterInspector : Editor { else Handles.Label(labelPos, receptor1.name, style); } + else { + Handles.color = Color.white; + // The selected nucleus highlight ring + Handles.DrawSolidDisc(position, Vector3.forward, size + 2); + DrawNucleus(this.currentNucleus, position, length(this.currentNucleus.outputValue), 20); + + } } else { Handles.color = Color.white; @@ -488,6 +495,26 @@ public class ClusterInspector : Editor { // style.normal.textColor = Color.white; // Handles.Label(labelPosition, receptor.instances.Count().ToString(), style); // } + if (nucleus is ClusterReceptor clusterReceptor) { + if (expandArray && clusterReceptor.array.nuclei.First() == this.currentNucleus) { + style.alignment = TextAnchor.LowerCenter; + Vector3 labelPos = position + Vector3.down * (size + 5); // below disc along up axis + int colonPos = nucleus.name.IndexOf(":"); + if (colonPos > 0) { + string extName = nucleus.name[(colonPos + 2)..]; + Handles.Label(labelPos, 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 Receptor receptor2 && receptor2.array.nuclei.First() == this.currentNucleus) { style.alignment = TextAnchor.LowerCenter; Vector3 labelPos = position + Vector3.down * (size + 5); // below disc along up axis @@ -647,6 +674,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(); + } // Synapses @@ -812,6 +854,9 @@ public class ClusterInspector : Editor { case Nucleus.Type.ReceptorArray: AddReceptorArrayInput(nucleus); break; + case Nucleus.Type.ClusterReceptor: + AddClusterReceptorInput(nucleus); + break; default: break; } @@ -887,6 +932,10 @@ public class ClusterInspector : Editor { BuildLayers(); } + protected virtual void AddClusterReceptorInput(Nucleus nucleus) { + ClusterPickerWindow.ShowPicker(brain => OnClusterReceptorPicked(nucleus, brain), "Select Cluster"); + } + private void OnClusterPicked(Nucleus nucleus, ClusterPrefab prefab) { Cluster subclusterInstance = new(prefab, this.prefab); subclusterInstance.AddReceiver(nucleus); @@ -895,6 +944,11 @@ public class ClusterInspector : Editor { // BuildLayers(); } + private void OnClusterReceptorPicked(Nucleus nucleus, ClusterPrefab prefab) { + ClusterReceptor clusterInstance = new(prefab, this.prefab, "New " + prefab.name); + clusterInstance.AddReceiver(nucleus); + } + private void EditCluster(Cluster subCluster) { // May be used with storedPrefab... Selection.activeObject = subCluster.prefab; diff --git a/Nucleus.cs b/Nucleus.cs index 57ad5f4..1a014b3 100644 --- a/Nucleus.cs +++ b/Nucleus.cs @@ -42,7 +42,8 @@ public abstract class Nucleus { Cluster, Pulsar, Receptor, - ReceptorArray + ReceptorArray, + ClusterReceptor, } #region Synapses