First steps to using instanceCount for clusters
This commit is contained in:
parent
8801fa2ff2
commit
b6630ad84e
@ -196,13 +196,16 @@ namespace NanoBrain {
|
||||
|
||||
if (this.currentNucleus is Cluster cluster) {
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
if (cluster.siblingClusters != null && cluster.siblingClusters.Length > 1)
|
||||
if (cluster.instanceCount > 1)
|
||||
EditorGUILayout.IntField("Array size", cluster.instanceCount, GUILayout.MinWidth(150));
|
||||
else if (cluster.siblingClusters != null && cluster.siblingClusters.Length > 1)
|
||||
EditorGUILayout.IntField("Array size", cluster.siblingClusters.Count(), GUILayout.MinWidth(150));
|
||||
else
|
||||
EditorGUILayout.IntField("Array size", 1, GUILayout.MinWidth(150));
|
||||
if (GUILayout.Button("Add")) {
|
||||
Undo.RecordObject(prefabAsset, "Array add " + prefabAsset.name);
|
||||
cluster.AddInstance(this.prefab);
|
||||
//cluster.AddInstance(this.prefab);
|
||||
cluster.AddInstance();
|
||||
anythingChanged = true;
|
||||
}
|
||||
if (GUILayout.Button("Del")) {
|
||||
@ -213,8 +216,36 @@ namespace NanoBrain {
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
// Synapses
|
||||
SynapsesInspector(ref anythingChanged);
|
||||
ActivationInspector(ref anythingChanged);
|
||||
|
||||
if (GUILayout.Button("Delete this neuron"))
|
||||
DeleteNucleus(this.currentNucleus);
|
||||
|
||||
if (this.currentNucleus is Cluster subCluster) {
|
||||
if (GUILayout.Button("Reimport Cluster"))
|
||||
ReimportCluster(subCluster);
|
||||
if (GUILayout.Button("Edit Cluster"))
|
||||
EditCluster(subCluster);
|
||||
}
|
||||
|
||||
EditorGUILayout.Space();
|
||||
breakOnWake = EditorGUILayout.Toggle("Break on wake", breakOnWake);
|
||||
if (breakOnWake && this.currentNucleus is Neuron currentNeuron) {
|
||||
if (currentNeuron.isSleeping == false)
|
||||
Debug.Break();
|
||||
}
|
||||
trace = EditorGUILayout.Toggle("Trace", trace);
|
||||
this.currentNucleus.trace = trace;
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
if (anythingChanged) {
|
||||
EditorUtility.SetDirty(prefabAsset);
|
||||
AssetDatabase.SaveAssets();
|
||||
}
|
||||
}
|
||||
|
||||
protected void SynapsesInspector(ref bool anythingChanged) {
|
||||
showSynapses = EditorGUILayout.BeginFoldoutHeaderGroup(showSynapses, "Synapses");
|
||||
if (showSynapses) {
|
||||
if (this.currentNucleus is Neuron neuron2) {
|
||||
@ -248,19 +279,17 @@ namespace NanoBrain {
|
||||
else
|
||||
elementIx = thisElementIx;
|
||||
}
|
||||
// if (array.Contains(synapse.nucleus))
|
||||
// continue;
|
||||
if (array.Contains(synapse.neuron))
|
||||
continue;
|
||||
else if (array.Contains(synapse.neuron.parent))
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
// if (synapse.neuron.parent is IReceptor iReceptor) {
|
||||
// array = iReceptor.nucleiArray;
|
||||
// if (iReceptor is Cluster iCluster)
|
||||
// elementIx = Cluster.GetNucleusIndex(iCluster.clusterNuclei, synapse.neuron);
|
||||
// }
|
||||
// else if (synapse.nucleus is Receptor receptor2) // && receptor2.array != null && receptor2.array.nuclei.Length > 1)
|
||||
// array = receptor2.nucleiArray;
|
||||
if (synapse.neuron.parent is Cluster iReceptor) {
|
||||
array = iReceptor.siblingClusters;
|
||||
if (iReceptor is Cluster iCluster)
|
||||
elementIx = Cluster.GetNucleusIndex(iCluster.clusterNuclei, synapse.neuron);
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUILayout.Space();
|
||||
@ -325,8 +354,9 @@ namespace NanoBrain {
|
||||
anythingChanged |= AddSynapse(this.prefab, this.currentNucleus);
|
||||
}
|
||||
EditorGUILayout.EndFoldoutHeaderGroup();
|
||||
}
|
||||
|
||||
// Activation
|
||||
protected void ActivationInspector(ref bool anythingChanged) {
|
||||
|
||||
if (this.currentNucleus is not Cluster) {
|
||||
EditorGUILayout.Space();
|
||||
@ -356,30 +386,6 @@ namespace NanoBrain {
|
||||
EditorGUILayout.EndFoldoutHeaderGroup();
|
||||
}
|
||||
|
||||
if (GUILayout.Button("Delete this neuron"))
|
||||
DeleteNucleus(this.currentNucleus);
|
||||
|
||||
if (this.currentNucleus is Cluster subCluster) {
|
||||
if (GUILayout.Button("Reimport Cluster"))
|
||||
ReimportCluster(subCluster);
|
||||
if (GUILayout.Button("Edit Cluster"))
|
||||
EditCluster(subCluster);
|
||||
}
|
||||
|
||||
EditorGUILayout.Space();
|
||||
breakOnWake = EditorGUILayout.Toggle("Break on wake", breakOnWake);
|
||||
if (breakOnWake && this.currentNucleus is Neuron currentNeuron) {
|
||||
if (currentNeuron.isSleeping == false)
|
||||
Debug.Break();
|
||||
}
|
||||
trace = EditorGUILayout.Toggle("Trace", trace);
|
||||
this.currentNucleus.trace = trace;
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
if (anythingChanged) {
|
||||
EditorUtility.SetDirty(prefabAsset);
|
||||
AssetDatabase.SaveAssets();
|
||||
}
|
||||
}
|
||||
|
||||
#region Synapses
|
||||
@ -426,8 +432,8 @@ namespace NanoBrain {
|
||||
protected virtual void AddClusterInput(Nucleus nucleus) {
|
||||
ClusterPickerWindow.ShowPicker(brain => OnClusterPicked(nucleus, brain), "Select Cluster");
|
||||
}
|
||||
private void OnClusterPicked(Nucleus nucleus, ClusterPrefab prefab) {
|
||||
Cluster subclusterInstance = new(prefab, this.prefab);
|
||||
private void OnClusterPicked(Nucleus nucleus, ClusterPrefab selectedPrefab) {
|
||||
Cluster subclusterInstance = new(selectedPrefab, this.prefab);
|
||||
subclusterInstance.defaultOutput.AddReceiver(nucleus);
|
||||
}
|
||||
|
||||
@ -443,8 +449,10 @@ namespace NanoBrain {
|
||||
Cluster reimportedCluster = new(subCluster.prefab, this.prefab);
|
||||
subCluster.MoveReceivers(reimportedCluster);
|
||||
// subcluster should be garbage now...
|
||||
this.currentNucleus = reimportedCluster;
|
||||
}
|
||||
else {
|
||||
this.currentNucleus = null;
|
||||
List<Cluster> newSiblingsList = new();
|
||||
foreach (Cluster sibling in subCluster.siblingClusters) {
|
||||
Cluster reimportedCluster = new(sibling.prefab, this.prefab) {
|
||||
@ -452,6 +460,8 @@ namespace NanoBrain {
|
||||
};
|
||||
sibling.MoveReceivers(reimportedCluster);
|
||||
newSiblingsList.Add(reimportedCluster);
|
||||
// make the first reimportedCluster the new current nucleus
|
||||
this.currentNucleus ??= reimportedCluster;
|
||||
}
|
||||
Cluster[] newSiblings = newSiblingsList.ToArray();
|
||||
foreach (Cluster sibling in newSiblings)
|
||||
@ -460,7 +470,7 @@ namespace NanoBrain {
|
||||
}
|
||||
|
||||
int selectedConnectNucleus = -1;
|
||||
// Connect to another nucleus in the same cluster
|
||||
// Connect to another nucleus
|
||||
protected virtual bool ConnectNucleus(ClusterPrefab cluster, Nucleus nucleusToConnect) {
|
||||
if (cluster == null)
|
||||
return false;
|
||||
@ -485,14 +495,10 @@ namespace NanoBrain {
|
||||
EditorGUILayout.EndHorizontal();
|
||||
if (connecting) {
|
||||
Nucleus nucleus = nuclei.ElementAt(selectedConnectNucleus);
|
||||
// if (nucleus is IReceptor receptor)
|
||||
// receptor.AddArrayReceiver(this.currentNucleus);
|
||||
// else
|
||||
if (nucleus is Neuron neuron)
|
||||
if (nucleus is Cluster subCluster)
|
||||
subCluster.AddArrayReceiver(this.currentNucleus);
|
||||
else if (nucleus is Neuron neuron)
|
||||
neuron.AddReceiver(this.currentNucleus);
|
||||
else if (nucleus is Cluster subCluster)
|
||||
subCluster.defaultOutput.AddReceiver(this.currentNucleus);
|
||||
|
||||
}
|
||||
return connecting;
|
||||
}
|
||||
|
||||
@ -557,8 +557,16 @@ namespace NanoBrain {
|
||||
Handles.Label(labelPos1, "0", style);
|
||||
}
|
||||
else {
|
||||
if (parentCluster.siblingClusters != null && parentCluster.siblingClusters.Length > 1) {
|
||||
// draw the array size label
|
||||
// draw the array size label
|
||||
if (parentCluster.instanceCount > 1) {
|
||||
if (color.grayscale > 0.5f)
|
||||
style.normal.textColor = Color.black;
|
||||
else
|
||||
style.normal.textColor = Color.white;
|
||||
Handles.Label(labelPosition, parentCluster.instanceCount.ToString(), style);
|
||||
style.normal.textColor = Color.white;
|
||||
}
|
||||
else if (parentCluster.siblingClusters != null && parentCluster.siblingClusters.Length > 1) {
|
||||
if (color.grayscale > 0.5f)
|
||||
style.normal.textColor = Color.black;
|
||||
else
|
||||
@ -582,8 +590,16 @@ namespace NanoBrain {
|
||||
Handles.Label(labelPos1, "0", style);
|
||||
}
|
||||
else {
|
||||
if (cluster.siblingClusters != null && cluster.siblingClusters.Length > 1) {
|
||||
// draw the array size label
|
||||
// draw the array size label
|
||||
if (cluster.instanceCount > 1) {
|
||||
if (color.grayscale > 0.5f)
|
||||
style.normal.textColor = Color.black;
|
||||
else
|
||||
style.normal.textColor = Color.white;
|
||||
Handles.Label(labelPosition, cluster.instanceCount.ToString(), style);
|
||||
style.normal.textColor = Color.white;
|
||||
}
|
||||
else if (cluster.siblingClusters != null && cluster.siblingClusters.Length > 1) {
|
||||
if (color.grayscale > 0.5f)
|
||||
style.normal.textColor = Color.black;
|
||||
else
|
||||
|
||||
@ -15,6 +15,7 @@ namespace NanoBrain {
|
||||
/// Clusters can be nested inside other clusters.
|
||||
[Serializable]
|
||||
public class Cluster : Nucleus {
|
||||
// It may be that clusters will not be nuclei anymore in the future....
|
||||
|
||||
/// <summary>
|
||||
/// The base name of the cluster. I don't think this is actively used at this moment
|
||||
@ -28,8 +29,11 @@ namespace NanoBrain {
|
||||
}
|
||||
}
|
||||
|
||||
// This should not be serialized
|
||||
[SerializeReference]
|
||||
public Cluster[] siblingClusters;
|
||||
// This serialization should be enough
|
||||
public int instanceCount = 1;
|
||||
public Dictionary<int, Cluster> thingClusters = new();
|
||||
|
||||
#region Init
|
||||
@ -141,7 +145,6 @@ namespace NanoBrain {
|
||||
}
|
||||
arrayIx++;
|
||||
}
|
||||
//clonedNucleus.array = clonedArray;
|
||||
clonedNucleus.siblingClusters = clonedArray;
|
||||
}
|
||||
else {
|
||||
@ -152,6 +155,50 @@ namespace NanoBrain {
|
||||
}
|
||||
}
|
||||
|
||||
// Collect the subclusters
|
||||
List<Cluster> subClusters = new();
|
||||
foreach (Nucleus nucleus in prefabNuclei) {
|
||||
foreach (Synapse synapse in nucleus.synapses) {
|
||||
Nucleus synapseNucleus = synapse.neuron;
|
||||
if (synapseNucleus is not Cluster subCluster)
|
||||
continue;
|
||||
if (subClusters.Contains(subCluster))
|
||||
continue;
|
||||
subClusters.Add(subCluster);
|
||||
}
|
||||
}
|
||||
// Create the subcluster instances
|
||||
foreach (Cluster subCluster in subClusters) {
|
||||
for (int ix = 0; ix < subCluster.instanceCount; ix++) {
|
||||
// create the new instance
|
||||
Cluster clusterInstance = new(subCluster.prefab);
|
||||
// connect it
|
||||
foreach ((Neuron sender, Nucleus receiver) in subCluster.CollectConnections()) {
|
||||
int receiverIx = GetNucleusIndex(prefabNuclei, receiver);
|
||||
if (receiverIx < 0)
|
||||
continue;
|
||||
|
||||
if (clonedNuclei[receiverIx] is not Nucleus clonedReceiver)
|
||||
continue;
|
||||
|
||||
// Find the synapse for the weight
|
||||
float weight = 1;
|
||||
foreach (Synapse synapse in receiver.synapses) {
|
||||
// Find the weight for this synapse
|
||||
if (synapse.neuron == sender) {
|
||||
weight = synapse.weight;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (clusterInstance.GetNucleus(sender.name) is not Neuron clonedSender)
|
||||
continue;
|
||||
|
||||
clonedSender.AddReceiver(clonedReceiver, weight);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
foreach (Nucleus nucleus in this.clusterNuclei) {
|
||||
if (nucleus is Cluster clonedSubCluster)
|
||||
@ -245,6 +292,7 @@ namespace NanoBrain {
|
||||
}
|
||||
|
||||
public override Nucleus ShallowCloneTo(Cluster parent) {
|
||||
// Clusters should not be cloned, but instantiated from the prefab....
|
||||
Cluster clone = new(this.prefab, parent) {
|
||||
name = this.name,
|
||||
clusterPrefab = this.clusterPrefab,
|
||||
@ -314,6 +362,10 @@ namespace NanoBrain {
|
||||
|
||||
#region Cluster Array
|
||||
|
||||
public void AddInstance() {
|
||||
this.instanceCount++;
|
||||
}
|
||||
|
||||
public void AddInstance(ClusterPrefab prefab) {
|
||||
// Ensure siblingClusters exists
|
||||
if (this.siblingClusters == null || this.siblingClusters.Length == 0)
|
||||
@ -340,18 +392,22 @@ namespace NanoBrain {
|
||||
}
|
||||
|
||||
public void RemoveInstance() {
|
||||
if (this.siblingClusters == null || this.siblingClusters.Length <= 1)
|
||||
return;
|
||||
if (instanceCount > 1)
|
||||
instanceCount--;
|
||||
else {
|
||||
if (this.siblingClusters == null || this.siblingClusters.Length <= 1)
|
||||
return;
|
||||
|
||||
// Prepare the new array
|
||||
int newLength = this.siblingClusters.Length - 1;
|
||||
Cluster[] newClusters = new Cluster[newLength];
|
||||
// Prepare the new array
|
||||
int newLength = this.siblingClusters.Length - 1;
|
||||
Cluster[] newClusters = new Cluster[newLength];
|
||||
|
||||
for (int i = 0; i < newLength; i++)
|
||||
newClusters[i] = this.siblingClusters[i];
|
||||
for (int i = 0; i < newLength; i++)
|
||||
newClusters[i] = this.siblingClusters[i];
|
||||
|
||||
Neuron.Delete(this.siblingClusters[^1]);
|
||||
this.siblingClusters = newClusters;
|
||||
Neuron.Delete(this.siblingClusters[^1]);
|
||||
this.siblingClusters = newClusters;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual Cluster GetThingCluster() {
|
||||
@ -411,6 +467,13 @@ namespace NanoBrain {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void AddArrayReceiver(Nucleus receiverToAdd, float weight = 1) {
|
||||
foreach (Cluster cluster in this.siblingClusters) {
|
||||
cluster.defaultOutput.AddReceiver(receiverToAdd, weight);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endregion ClusterArray
|
||||
|
||||
public ClusterPrefab prefab;
|
||||
@ -593,6 +656,22 @@ namespace NanoBrain {
|
||||
return receivers;
|
||||
}
|
||||
|
||||
public List<(Neuron, Nucleus)> CollectConnections() {
|
||||
List<(Neuron, Nucleus)> connections = new();
|
||||
|
||||
foreach (Nucleus outputNucleus in this.clusterNuclei) {
|
||||
if (outputNucleus is not Neuron output)
|
||||
continue;
|
||||
|
||||
foreach (Nucleus receiver in output.receivers) {
|
||||
// Only add receivers outside this cluster
|
||||
if (receiver.clusterPrefab != this.prefab)
|
||||
connections.Add((output, receiver));
|
||||
}
|
||||
}
|
||||
return connections;
|
||||
}
|
||||
|
||||
public void MoveReceivers(Cluster newCluster) {
|
||||
Debug.Log($"Move receivers for {this.name} to {newCluster.name}");
|
||||
foreach (Nucleus outputNucleus in this.clusterNuclei) {
|
||||
|
||||
@ -88,6 +88,10 @@ public abstract class Nucleus {
|
||||
return synapse;
|
||||
}
|
||||
|
||||
// public Synapse AddSynapse(ClusterPrefab clusterPrefab, string neuronName, float weight = 1) {
|
||||
|
||||
// }
|
||||
|
||||
/// <summary>
|
||||
/// Find a synapse
|
||||
/// </summary>
|
||||
|
||||
@ -10,6 +10,7 @@ namespace NanoBrain {
|
||||
public class ClusterPrefab : ScriptableObject {
|
||||
/// The nuclei in this cluster
|
||||
[SerializeReference]
|
||||
// This list should not include any clusters...
|
||||
public List<Nucleus> nuclei = new();
|
||||
|
||||
/// <summary>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user