diff --git a/Editor/ClusterEditor.cs b/Editor/ClusterEditor.cs index b3b3aad..9b33553 100644 --- a/Editor/ClusterEditor.cs +++ b/Editor/ClusterEditor.cs @@ -64,6 +64,22 @@ namespace NanoBrain { public class GraphEditor : GraphView { protected ClusterPrefab prefab; + protected Nucleus currentPrefabNucleus; + + protected override Nucleus currentNucleus { + get => base.currentNucleus; + set { + base.currentNucleus = value; + this.currentPrefabNucleus = this.prefab.GetNucleus(value.name); + // int nucleusIx = this.prefab.nuclei.IndexOf(base.currentNucleus); + // if (nucleusIx >= 0) + // this.currentPrefabNucleus = this.prefab.nuclei[nucleusIx]; + // else { + // Debug.LogWarning("Could not find nucleus in prefab"); + // this.currentPrefabNucleus = this.prefab.GetNucleus(value.name); + // } + } + } public GraphEditor(ClusterPrefab prefab) : base(prefab.output.parent) { this.prefab = prefab; @@ -146,10 +162,10 @@ namespace NanoBrain { return; } else { - GUIStyle headerStyle = new(EditorStyles.boldLabel) { - alignment = TextAnchor.MiddleLeft, - margin = new RectOffset(10, 0, 4, 4) - }; + GUIStyle headerStyle = new(EditorStyles.boldLabel) { + alignment = TextAnchor.MiddleLeft, + margin = new RectOffset(10, 0, 4, 4) + }; // Nucleus type string nucleusType = this.currentNucleus.GetType().Name; GUILayout.Label(nucleusType, headerStyle); @@ -170,6 +186,9 @@ namespace NanoBrain { else { string newName = EditorGUILayout.TextField(this.currentNucleus.name, boldTextFieldStyle); if (newName != this.currentNucleus.name) { + Nucleus prefabNucleus = this.prefab.GetNucleus(this.currentNucleus.name); + prefabNucleus.name = newName; + // This changes it in the temporary cluster instance this.currentNucleus.name = newName; this.prefab.RefreshOutputs(); // outputsPopup.choices = this.prefab.outputs.Select(output => output.name).ToList(); @@ -222,7 +241,7 @@ namespace NanoBrain { Nucleus newOutput = new Neuron(this.prefab, "New Output"); // Regenerate the temporary clsuter instance // See also the constructor - this.currentCluster = new (this.prefab); + this.currentCluster = new(this.prefab); this.currentNucleus = newOutput; this.selectedOutput = this.currentNucleus; } @@ -290,14 +309,17 @@ namespace NanoBrain { EditorGUIUtility.labelWidth = 100; Vector3 newBias = EditorGUILayout.Vector3Field("Bias", this.currentNucleus.bias); - anythingChanged |= newBias != this.currentNucleus.bias; - this.currentNucleus.bias = newBias; + if (newBias != this.currentPrefabNucleus.bias) { + anythingChanged |= newBias != this.currentNucleus.bias; + this.currentPrefabNucleus.bias = newBias; + this.currentNucleus.bias = newBias; + } EditorGUIUtility.labelWidth = previousLabelWidth; Nucleus[] array = null; int elementIx = -1; - if (this.currentNucleus.synapses.Count > 0) { - Synapse[] synapses = this.currentNucleus.synapses.ToArray(); + if (this.currentPrefabNucleus.synapses.Count > 0) { + Synapse[] synapses = this.currentPrefabNucleus.synapses.ToArray(); foreach (Synapse synapse in synapses) { if (synapse.neuron == null) continue; @@ -336,24 +358,20 @@ namespace NanoBrain { EditorGUILayout.BeginHorizontal(); if (synapse.neuron.clusterPrefab != this.currentNucleus.clusterPrefab) { - // If it is a cluster + // If it is a different cluster GUIStyle labelStyle = new(GUI.skin.label); float labelWidth = 200; if (synapse.neuron.clusterPrefab != null) { labelWidth = labelStyle.CalcSize(new GUIContent($"{synapse.neuron.clusterPrefab.name}.")).x; GUILayout.Label($"{synapse.neuron.clusterPrefab.name}", GUILayout.Width(labelWidth)); } - //string[] options = synapse.neuron.parent.clusterNuclei.Select(n => n.name).ToArray(); string[] options = synapse.neuron.clusterPrefab.nuclei.Select(n => n.name).ToArray(); int selectedIndex = System.Array.IndexOf(options, synapse.neuron.name); int newIndex = EditorGUILayout.Popup(selectedIndex, options); - // if (newIndex != selectedIndex && synapse.neuron.clusterPrefab.nuclei[newIndex] is Neuron newNeuron) - // ChangeSynapse(synapse, newNeuron); if (newIndex != selectedIndex) { - // It shall be ensured that the parent.clusterNuclei and - // clusterPrefab.nuclei contain the same neurons in the same order.... - Nucleus selectedNucleus = synapse.neuron.parent.clusterNuclei[newIndex]; - Neuron newNeuron = selectedNucleus as Neuron; + // Nucleus selectedNucleus = synapse.neuron.parent.clusterNuclei[newIndex]; + // Neuron newNeuron = selectedNucleus as Neuron; + Neuron newNeuron = synapse.neuron.clusterPrefab.nuclei[newIndex] as Neuron; ChangeSynapse(synapse, newNeuron); } } @@ -373,14 +391,6 @@ namespace NanoBrain { EditorGUI.indentLevel++; float newWeight = EditorGUILayout.FloatField("Weight", synapse.weight); if (newWeight != synapse.weight) { - // if (synapse.neuron.parent is IReceptor receptor) { - // Nucleus[] receptorArray = receptor.nucleiArray; - // foreach (Synapse s in this.currentNucleus.synapses) { - // if (s.neuron.parent is IReceptor r && r.nucleiArray == receptorArray) - // s.weight = newWeight; - // } - // } - // else synapse.weight = newWeight; anythingChanged = true; } @@ -537,7 +547,7 @@ namespace NanoBrain { // this.prefab.nuclei.Remove(nucleus); // Neuron.Delete(nucleus); this.prefab.RefreshOutputs(); - + this.currentNucleus = this.prefab.output; this.selectedOutput = this.currentNucleus; @@ -565,7 +575,7 @@ namespace NanoBrain { } protected virtual void ChangeSynapse(Synapse synapse, Neuron newNucleus) { - Neuron synapseNeuron = synapse.neuron as Neuron; + Neuron synapseNeuron = synapse.neuron; if (synapse.neuron.parent is Cluster subCluster && subCluster.prefab != this.prefab) { // if (synapse.neuron.parent is ClusterReceptor receptor) { // // the new nucleus is part of a (cluster) receptor, @@ -595,8 +605,8 @@ namespace NanoBrain { // } // else { // it is a neuron in a subcluster - synapseNeuron.RemoveReceiver(this.currentNucleus); - newNucleus.AddReceiver(this.currentNucleus); + synapseNeuron.RemoveReceiver(this.currentPrefabNucleus); + newNucleus.AddReceiver(this.currentPrefabNucleus); // } } else { diff --git a/Editor/ClusterViewer.cs b/Editor/ClusterViewer.cs index 11013d3..46e303c 100644 --- a/Editor/ClusterViewer.cs +++ b/Editor/ClusterViewer.cs @@ -15,7 +15,12 @@ namespace NanoBrain { //protected readonly ClusterPrefab prefab; protected Cluster currentCluster; protected SerializedObject serializedBrain; - protected Nucleus currentNucleus; + protected Nucleus _currentNucleus; + protected virtual Nucleus currentNucleus { + get => _currentNucleus; + set => _currentNucleus = value; + } + //protected Nucleus currentNucleus; protected Nucleus selectedOutput; protected GameObject gameObject; diff --git a/Runtime/Scripts/Core/Cluster.cs b/Runtime/Scripts/Core/Cluster.cs index 9e905f9..52ef65c 100644 --- a/Runtime/Scripts/Core/Cluster.cs +++ b/Runtime/Scripts/Core/Cluster.cs @@ -93,6 +93,8 @@ namespace NanoBrain { nucleus.ShallowCloneTo(this); } Nucleus[] clonedNuclei = this.clusterNuclei.ToArray(); + // foreach (Nucleus n in clonedNuclei) + // n.name += "(c)"; // Now clone the connections for (int nucleusIx = 0; nucleusIx < prefabNuclei.Length; nucleusIx++) { @@ -106,19 +108,15 @@ namespace NanoBrain { foreach (Synapse prefabSynapse in prefabNeuron.synapses) { Neuron synapseNeuron = prefabSynapse.neuron; - if (synapseNeuron.parent is not null && synapseNeuron.clusterPrefab != this.clusterPrefab) { + if (synapseNeuron.clusterPrefab != null && synapseNeuron.clusterPrefab != this.prefab) { // Neuron is in another cluster, find the cloned cluster first - Cluster prefabCluster = synapseNeuron.parent; - int clusterIx = GetNucleusIndex(prefabNuclei, prefabCluster); - if (clusterIx < 0) - // Could not find the cluster in the prefab - continue; - if (clonedNuclei[clusterIx] is not Cluster clonedCluster) - // Could not find the cloned cluster + ClusterPrefab prefabCluster = synapseNeuron.clusterPrefab; + Cluster clonedCluster = this.clusterNuclei.Find(n => n.name == prefabCluster.name) as Cluster; + if (clonedCluster == null) continue; // Now find the neuron in that cloned cluster - int neuronIx = GetNucleusIndex(prefabCluster.prefab.nuclei, prefabSynapse.neuron); + int neuronIx = GetNucleusIndex(prefabCluster.nuclei, prefabSynapse.neuron.name); if (neuronIx < 0) // Could not find the neuron in the prefab cluster continue; @@ -402,13 +400,25 @@ namespace NanoBrain { int i = 0; foreach (Nucleus nucleiElement in nuclei) { //for (int i = 0; i < nuclei.Length; i++) { - if (nucleus == nucleiElement) + if (nucleiElement == nucleus) return i; i++; } return -1; } + public static int GetNucleusIndex(List nuclei, string nucleusName) { + int i = 0; + foreach (Nucleus nucleiElement in nuclei) { + //for (int i = 0; i < nuclei.Length; i++) { + if (nucleiElement.name == nucleusName) + return i; + i++; + } + return -1; + } + + #endregion Init #region Cluster Array @@ -690,7 +700,7 @@ namespace NanoBrain { if (TryGetNucleus(nucleus.name, out nucleus) == false) return false; } - + Neuron.Delete(nucleus); int nucleusIx = this.clusterNuclei.IndexOf(nucleus); this.clusterNuclei.Remove(nucleus);