ClusterInstance is working a bit

This commit is contained in:
Pascal Serrarens 2026-01-21 20:39:07 +01:00
parent 8b8e5fc33c
commit f0da7c9c9b
10 changed files with 168 additions and 118 deletions

View File

@ -4,7 +4,7 @@ using Unity.Mathematics;
using static Unity.Mathematics.math;
[CreateAssetMenu(menuName = "Passer/Cluster")]
public class Cluster : ScriptableObject, INucleus {
public class Cluster : ScriptableObject {
public Cluster cluster => this;
@ -14,9 +14,9 @@ public class Cluster : ScriptableObject, INucleus {
[SerializeReference]
public List<IReceptor> nuclei = new();
public List<Cluster> subClusters = new();
public void AddSubCluster(Cluster subCluster) {
this.subClusters.Add(subCluster);
// public List<Cluster> subClusters = new();
public void AddSubCluster(ClusterInstance subCluster) {
this.nuclei.Add(subCluster);
}
public INucleus output => this.nuclei[0] as INucleus;
@ -45,19 +45,19 @@ public class Cluster : ScriptableObject, INucleus {
get { return this.output.receivers; }
set { this.output.receivers = value; }
}
public List<Cluster> clusterReceivers {
get { return this.output.clusterReceivers; }
set { this.output.clusterReceivers = clusterReceivers; }
}
public IEnumerable<INucleus> allReceivers {
get => output.allReceivers;
}
// public List<Cluster> clusterReceivers {
// get { return this.output.clusterReceivers; }
// set { this.output.clusterReceivers = clusterReceivers; }
// }
// public IEnumerable<INucleus> allReceivers {
// get => output.allReceivers;
// }
public INucleus Clone() {
Cluster clone = CreateInstance<Cluster>();
// Lots to add here...
return clone;
}
// public INucleus Clone() {
// Cluster clone = CreateInstance<Cluster>();
// // Lots to add here...
// return clone;
// }
// Call this function to ensure that there is at least one nucleus
// This is an invariant and should be ensured before the nucleus is used
@ -67,7 +67,7 @@ public class Cluster : ScriptableObject, INucleus {
if (nuclei.Count == 0)
new Neuron(this, "Output"); // Every cluster should have at least 1 neuron
}
/*
public void AddReceiver(INucleus receivingNucleus) {
//output.AddReceiver(receiver);
this.output.receivers.Add(receivingNucleus);
@ -92,7 +92,7 @@ public class Cluster : ScriptableObject, INucleus {
synapses.Add(synapse);
return synapse;
}
*/
public void GarbageCollection() {
HashSet<INucleus> visitedNuclei = new();
MarkNuclei(visitedNuclei, this.output);
@ -117,9 +117,9 @@ public class Cluster : ScriptableObject, INucleus {
}
nucleus.synapses.RemoveAll(synapse => visitedSynapses.Contains(synapse) == false);
}
if (nucleus.allReceivers != null) {
if (nucleus.receivers != null) {
HashSet<INucleus> visitedReceivers = new();
foreach (INucleus receiver in nucleus.allReceivers) {
foreach (INucleus receiver in nucleus.receivers) {
if (receiver != null && receiver != null) {
visitedReceivers.Add(receiver);
visitedNuclei.Add(receiver);

View File

@ -1,51 +1,90 @@
public class ClusterInstance {
// The ScriptableObject asset from which the runtime object has been created
public readonly Cluster asset;
using System;
using System.Collections.Generic;
using UnityEngine;
using Unity.Mathematics;
using static Unity.Mathematics.math;
public ClusterInstance parent;
[System.Serializable]
public class ClusterInstance : INucleus {
// The ScriptableObject asset from which the runtime object has been created
public Cluster asset;
public Cluster cluster => this.asset;
public INucleus output => this.asset.nuclei[0] as INucleus;
public float3 outputValue => this.output.outputValue;
public ClusterInstance(Cluster asset) {
this.asset = asset;
}
public NucleusArray array;
public INucleus Clone() {
ClusterInstance clone = new(this.asset);
return clone;
}
#region Properties
public string name {
get { return asset.name; }
set { asset.name = value; }
}
public bool isSleeping => lengthsq(this.outputValue) == 0;
public NucleusArray array { get; set; }
#endregion Properties
#region Synapses
private Synapse[] _synapses = new Synapse[0];
public Synapse[] synapses => _synapses;
public List<Synapse> synapses => new(_synapses);
public void AddSynapse(IReceptor sendingNucleus) {
public Synapse AddSynapse(IReceptor sendingNucleus, string nucleusName = null) {
if (nucleusName == null) {
this.asset.inputs[0].AddSynapse(sendingNucleus);
} else {
INucleus receptor = (INucleus)this.asset.nuclei.Find(nucleus => nucleus is INucleus n && nucleus.name == nucleusName);
receptor.AddSynapse(sendingNucleus);
}
// Add synapse to which neuron?
return null;
}
// Does this even exist already?
public void RemoveSynapse() {
}
#endregion Synapses
#region Receivers
private INucleus[] _nucleiReceivers = new INucleus[0];
public INucleus[] nucleiReceivers => _nucleiReceivers;
[SerializeReference]
private List<INucleus> _receivers = new();
public List<INucleus> receivers {
get { return _receivers; }
set { _receivers = value; }
}
public void AddReceiver(INucleus receivingNucleus) {
int newLength = this._nucleiReceivers.Length + 1;
int newLength = this._receivers.Count + 1;
INucleus[] newReceivers = new INucleus[newLength];
// Copy the existing receivers
for (int ix = 0; ix < this._nucleiReceivers.Length; ix++)
newReceivers[ix] = this._nucleiReceivers[ix];
for (int ix = 0; ix < this._receivers.Count; ix++)
newReceivers[ix] = this._receivers[ix];
// Add the new receivers
newReceivers[this._nucleiReceivers.Length] = receivingNucleus;
newReceivers[this._receivers.Count] = receivingNucleus;
// Replace the receivers with the new receivers
this._nucleiReceivers = newReceivers;
this._receivers = new(newReceivers);
receivingNucleus.AddSynapse(this);
}
public void RemoveReceiver(INucleus receivingNucleus) {
int newLength = this._nucleiReceivers.Length - 1;
int newLength = this._receivers.Count - 1;
if (newLength < 0)
// Array was empty, so we cannot remove anything
return;
@ -54,8 +93,8 @@ public class ClusterInstance {
int newIx = 0;
// Copy all receivers except receivingNucleus
for (int ix = 0; ix < this._nucleiReceivers.Length; ix++) {
if (this._nucleiReceivers[ix] == receivingNucleus)
for (int ix = 0; ix < this._receivers.Count; ix++) {
if (this._receivers[ix] == receivingNucleus)
// skip the receiver we want to remote
continue;
@ -64,11 +103,22 @@ public class ClusterInstance {
// the receivingNucleus is not found
// and the original array is returned
return;
newReceivers[newIx] = this._nucleiReceivers[ix];
newReceivers[newIx] = this._receivers[ix];
newIx++;
}
this._nucleiReceivers = newReceivers;
this._receivers = new(newReceivers);
}
#endregion Receivers
#region Update
public void UpdateState() { }
public void UpdateNuclei() {
foreach (IReceptor nucleus in this.asset.nuclei)
nucleus.UpdateNuclei();
}
#endregion Update
}

View File

@ -10,8 +10,8 @@ public interface INucleus : IReceptor {
// Senders
public List<Synapse> synapses { get; }
public Synapse AddSynapse(IReceptor sender);
public Synapse AddClusterSynapse(Cluster clusterSender);
public Synapse AddSynapse(IReceptor sender, string nucleusName = null);
// public Synapse AddClusterSynapse(Cluster clusterSender);
public NucleusArray array { get; set; }
@ -34,11 +34,11 @@ public interface IReceptor {
// Receivers
public List<INucleus> receivers { get; set; }
public List<Cluster> clusterReceivers { get; set; }
public IEnumerable<INucleus> allReceivers { get; }
// public List<Cluster> clusterReceivers { get; set; }
// public IEnumerable<INucleus> allReceivers { get; }
public void AddReceiver(INucleus receiver);
public void AddClusterReceiver(Cluster clusterReceiver);
// public void AddClusterReceiver(Cluster clusterReceiver);
public void RemoveReceiver(INucleus receiverNucleus);
#endregion static

View File

@ -12,6 +12,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 60a957541c24c57e78018c202ebb1d9b, type: 3}
m_Name: Identity
m_EditorClassIdentifier: Assembly-CSharp::Cluster
asset: {fileID: 0}
nuclei:
- rid: 2243601242842202241
subClusters: []

View File

@ -25,21 +25,21 @@ public class Neuron : INucleus {
get { return _receivers; }
set { _receivers = value; }
}
private List<Cluster> _clusterReceivers = new();
public List<Cluster> clusterReceivers {
get { return _clusterReceivers; }
set { _clusterReceivers = value; }
}
public IEnumerable<INucleus> allReceivers { //=> _receivers.Concat(_clusterReceivers);
get {
if (_receivers == null)
return _clusterReceivers;
else if (_clusterReceivers == null)
return _receivers;
else
return _receivers.Concat(_clusterReceivers);
}
}
// private List<Cluster> _clusterReceivers = new();
// public List<Cluster> clusterReceivers {
// get { return _clusterReceivers; }
// set { _clusterReceivers = value; }
// }
// public IEnumerable<INucleus> allReceivers { //=> _receivers.Concat(_clusterReceivers);
// get {
// if (_receivers == null)
// return _clusterReceivers;
// else if (_clusterReceivers == null)
// return _receivers;
// else
// return _receivers.Concat(_clusterReceivers);
// }
// }
[SerializeReference]
private NucleusArray _array;
@ -152,7 +152,7 @@ public class Neuron : INucleus {
Synapse clonedSynapse = clone.AddSynapse(synapse.nucleus);
clonedSynapse.weight = synapse.weight;
}
foreach (INucleus receiver in this.allReceivers) {
foreach (INucleus receiver in this.receivers) {
clone.AddReceiver(receiver);
}
return clone;
@ -162,10 +162,10 @@ public class Neuron : INucleus {
this._receivers.Add(receivingNucleus);
receivingNucleus.AddSynapse(this);
}
public void AddClusterReceiver(Cluster receivingCluster) {
this._clusterReceivers.Add(receivingCluster);
receivingCluster.AddSynapse(this);
}
// public void AddClusterReceiver(Cluster receivingCluster) {
// this._clusterReceivers.Add(receivingCluster);
// receivingCluster.AddSynapse(this);
// }
public void RemoveReceiver(INucleus receiverNucleus) {
this._receivers.RemoveAll(receiver => receiver == receiverNucleus);
@ -185,7 +185,7 @@ public class Neuron : INucleus {
}
}
}
foreach (INucleus receiver in nucleus.allReceivers) {
foreach (INucleus receiver in nucleus.receivers) {
if (receiver != null && receiver.synapses != null)
receiver.synapses.RemoveAll(s => s.nucleus == nucleus);
}
@ -196,16 +196,16 @@ public class Neuron : INucleus {
}
}
public Synapse AddSynapse(IReceptor sendingNucleus) {
public Synapse AddSynapse(IReceptor sendingNucleus, string nucleusName = null) {
Synapse synapse = new(sendingNucleus);
this.synapses.Add(synapse);
return synapse;
}
public Synapse AddClusterSynapse(Cluster sendingCluster) {
Synapse synapse = new(sendingCluster);
this.synapses.Add(synapse);
return synapse;
}
// public Synapse AddClusterSynapse(Cluster sendingCluster) {
// Synapse synapse = new(sendingCluster);
// this.synapses.Add(synapse);
// return synapse;
// }
public virtual void UpdateState() {
float3 sum = new(0, 0, 0);
@ -250,7 +250,7 @@ public class Neuron : INucleus {
// }
this.outputValue = result;
foreach (INucleus receiver in this.allReceivers)
foreach (INucleus receiver in this.receivers)
receiver.UpdateState();
}

View File

@ -9,12 +9,12 @@ public class NucleusArray {
private Cluster[] _clusters;
public IEnumerable<INucleus> nuclei {
get {
if (_nuclei == null)
return _clusters;
else if (_clusters == null)
// if (_nuclei == null)
// return _clusters;
// else if (_clusters == null)
return _nuclei;
else
return _nuclei.Concat(_clusters);
// else
// return _nuclei.Concat(_clusters);
}
}
public string name;

View File

@ -30,12 +30,12 @@ public class Receptor : IReceptor {
get { return _receivers; }
set { _receivers = value; }
}
private List<Cluster> _clusterReceivers = new();
public List<Cluster> clusterReceivers {
get { return _clusterReceivers; }
set { _clusterReceivers = value; }
}
public IEnumerable<INucleus> allReceivers => _receivers.Concat(_clusterReceivers);
// private List<Cluster> _clusterReceivers = new();
// public List<Cluster> clusterReceivers {
// get { return _clusterReceivers; }
// set { _clusterReceivers = value; }
// }
// public IEnumerable<INucleus> allReceivers => _receivers.Concat(_clusterReceivers);
protected int[] thingIds; // every receiver can handle a thing with this id
@ -43,10 +43,10 @@ public class Receptor : IReceptor {
this._receivers.Add(receivingNucleus);
receivingNucleus.AddSynapse(this);
}
public void AddClusterReceiver(Cluster receivingCluster) {
this._clusterReceivers.Add(receivingCluster);
receivingCluster.AddSynapse(this);
}
// public void AddClusterReceiver(Cluster receivingCluster) {
// this._clusterReceivers.Add(receivingCluster);
// receivingCluster.AddSynapse(this);
// }
public void RemoveReceiver(INucleus receiverNucleus) {
this._receivers.RemoveAll(receiver => receiver == receiverNucleus);
@ -116,7 +116,7 @@ public class Receptor : IReceptor {
int receiverIx = 0;
INucleus selectedReceiver = null;
int selectedReceiverIx = 0;
foreach (INucleus receiver in this.allReceivers) {
foreach (INucleus receiver in this.receivers) {
// selectedReceiver = receiver;
// receiverIx++;

View File

@ -5,14 +5,15 @@ using UnityEditor;
[Serializable]
public class Synapse {
// Support access to cluster of basic nucleus
public IReceptor nucleus => clusterNucleus != null ? clusterNucleus : basicNucleus;
public IReceptor nucleus => basicNucleus; // clusterNucleus != null ? clusterNucleus : basicNucleus;
[SerializeReference]
private IReceptor basicNucleus;
// The Cluster is a ScriptableObject and can therefore not be serialized using [SerializeReference]
private Cluster clusterNucleus;
// private ClusterInstance clusterNucleus;
public Cluster cluster;
[SerializeReference]
public ClusterInstance cluster;
public float weight;
@ -29,10 +30,10 @@ public class Synapse {
this.basicNucleus = nucleus;
this.weight = weight;
}
public Synapse(Cluster cluster, float weight = 1.0f) {
this.clusterNucleus = cluster.asset;
this.weight = weight;
}
// public Synapse(ClusterInstance cluster, float weight = 1.0f) {
// this.clusterNucleus = cluster;
// this.weight = weight;
// }
public static class Presets {
private const int samples = 32;

View File

@ -156,8 +156,8 @@ public class ClusterInspector : Editor {
return;
NeuroidLayer currentLayer = new() { ix = layerIx };
if (selectedNucleus.allReceivers != null) {
foreach (INucleus receiver in selectedNucleus.allReceivers) {
if (selectedNucleus.receivers != null) {
foreach (INucleus receiver in selectedNucleus.receivers) {
INucleus outputNeuroid = receiver;
if (outputNeuroid != null) {
AddToLayer(currentLayer, outputNeuroid);
@ -272,12 +272,12 @@ public class ClusterInspector : Editor {
}
private void DrawReceivers(INucleus nucleus, Vector3 parentPos, float size) {
int nodeCount = nucleus.allReceivers.Count();
int nodeCount = nucleus.receivers.Count();
// Determine the maximum value in this layer
// This is used to 'scale' the output value colors of the nuclei
float maxValue = 0;
foreach (INucleus receiver in nucleus.allReceivers) {
foreach (INucleus receiver in nucleus.receivers) {
if (receiver is Neuron neuroid) {
float value = length(neuroid.outputValue);
if (value > maxValue)
@ -290,7 +290,7 @@ public class ClusterInspector : Editor {
float margin = 10 + spacing / 2;
int row = 0;
foreach (INucleus receiver in nucleus.allReceivers) {
foreach (INucleus receiver in nucleus.receivers) {
INucleus receiverNucleus = receiver;
if (receiverNucleus == null)
continue;
@ -405,7 +405,7 @@ public class ClusterInspector : Editor {
Handles.Label(labelPos, nucleus.name, style);
}
if (nucleus is Cluster cluster) {
if (nucleus is ClusterInstance cluster) {
Handles.color = Color.white;
Handles.DrawWireDisc(position, Vector3.forward, size + 10);
}
@ -552,7 +552,7 @@ public class ClusterInspector : Editor {
if (GUILayout.Button("Delete this neuron"))
DeleteNeuron(this.currentNucleus);
if (this.currentNucleus is Cluster subCluster) {
if (this.currentNucleus is ClusterInstance subCluster) {
if (GUILayout.Button("Edit Cluster"))
EditCluster(subCluster);
}
@ -588,7 +588,7 @@ public class ClusterInspector : Editor {
return;
if (nucleus.cluster != null)
this.currentNucleus = nucleus.cluster.output;
foreach (INucleus receiver in nucleus.allReceivers) {
foreach (INucleus receiver in nucleus.receivers) {
if (receiver != null) {
this.currentNucleus = receiver;
break;
@ -603,17 +603,16 @@ public class ClusterInspector : Editor {
}
private void OnClusterPicked(INucleus nucleus, Cluster subCluster) {
Cluster clusterInstance = Instantiate(subCluster);
clusterInstance.asset = subCluster;
this.cluster.AddSubCluster(subCluster);
ClusterInstance clusterInstance = new(subCluster);
this.cluster.AddSubCluster(clusterInstance);
clusterInstance.AddReceiver(nucleus);
}
private void EditCluster(Cluster subCluster) {
private void EditCluster(ClusterInstance subCluster) {
//var currentActiveObject = Selection.activeObject;
Selection.activeObject = subCluster;
EditorGUIUtility.PingObject(subCluster);
var editor = Editor.CreateEditor(subCluster);
Selection.activeObject = subCluster.asset;
EditorGUIUtility.PingObject(subCluster.asset);
var editor = Editor.CreateEditor(subCluster.asset);
//Selection.activeObject = currentActiveObject;
}

View File

@ -14,19 +14,18 @@ MonoBehaviour:
m_EditorClassIdentifier: Assembly-CSharp::Cluster
asset: {fileID: 0}
nuclei:
- rid: 2243601242842202259
subClusters: []
- rid: 2243601249170358341
references:
version: 2
RefIds:
- rid: 2243601242842202259
- rid: 2243601249170358341
type: {class: Neuron, ns: , asm: Assembly-CSharp}
data:
_name: Output
_synapses: []
_receivers: []
_array:
rid: 2243601242842202260
rid: 2243601249170358342
_curvePreset: 0
curve:
serializedVersion: 2
@ -54,9 +53,9 @@ MonoBehaviour:
m_RotationOrder: 4
curveMax: 1
average: 0
- rid: 2243601242842202260
- rid: 2243601249170358342
type: {class: NucleusArray, ns: , asm: Assembly-CSharp}
data:
_nuclei:
- rid: 2243601242842202259
- rid: 2243601249170358341
name: Output