using System.Collections.Generic; using Passer.LinearAlgebra; namespace Passer.Control.Core { /// /// A thing is the basic building block /// public class Thing { public Participant participant; public delegate void ChangeHandler(); public delegate void SphericalHandler(Spherical v); public byte networkId; public byte id; public event ChangeHandler OnParentChanged; private Thing _parent; public Thing parent { get => _parent; set { if (_parent == value) return; if (value == null) { _parent.RemoveChild(this); _parent = null; } else { value.AddChild(this); OnParentChanged?.Invoke(); } } } public void AddChild(Thing child) { if (children.Find(thing => thing == child) != null) return; child._parent = this; children.Add(child); } public void RemoveChild(Thing child) { children.Remove(child); } [System.NonSerialized] public List children = new List(); public byte type; public event ChangeHandler OnNameChanged; private string _name; public string name { get => _name; set { if (_name != value) { _name = value; OnNameChanged?.Invoke(); } } } public string modelUrl; public byte poseUpdated = 0x00; public event ChangeHandler OnPositionChanged; private Spherical _position; public Spherical position { get { return _position; } set { if (_position != value) { _position = value; OnPositionChanged?.Invoke(); } } } public event ChangeHandler OnOrientationChanged; private SwingTwist _orientation; public SwingTwist orientation { get { return _orientation; } set { if (_orientation != value) { _orientation = value; OnOrientationChanged?.Invoke(); } } } public event SphericalHandler OnLinearVelocityChanged; private Spherical _linearVelocity; public Spherical linearVelocity { get => _linearVelocity; set { if (_linearVelocity != value) { _linearVelocity = value; OnLinearVelocityChanged?.Invoke(_linearVelocity); } } } public Spherical angularVelocity; public virtual void Init(bool invokeEvent = true) { Thing.Add(this, invokeEvent); } public Thing(bool initialize = true) { if (initialize) { //this.Init(); Thing.Add(this); } } public Thing(Participant client, byte networkId, byte thingId, byte thingType = 0) { this.participant = client; this.id = thingId; this.type = thingType; this.networkId = networkId; this.Init(); Thing.Add(this); } public virtual void Update(float currentTime) { // should recurse over children... } public virtual void ProcessBytes(byte[] bytes) { //if (sensor != null) // sensor.ProcessBytes(bytes); } // Experimental // public float stressLevel = 0; // protected delegate void ReceptorFunc(Sensor sensor); // protected void SetupReceptor(Sensor sensor, ReceptorFunc receptor) { // sensor.Signaller += (sensor => Receptor(receptor, sensor)); // } // protected void Receptor(ReceptorFunc receptor, Sensor sensor) { // if (sensor.signalStrength <= stressLevel) // return; // receptor(sensor); // } //---------- All Things private static readonly List allThings = new(); public delegate void ThingHandler(Thing t); public static event ThingHandler OnNewThing; public static void Add(Thing thing, bool invokeEvent = true) { Thing foundThing = Get(thing.networkId, thing.id); if (foundThing == null) { if (thing.id == 0) thing.id = (byte)(allThings.Count + 1); allThings.Add(thing); if (invokeEvent) OnNewThing?.Invoke(thing); // UnityEngine.Debug.Log($"Add thing [{thing.networkId}/{thing.id}] {thing.name}"); } } public static Thing Get(byte networkId, byte thingId) { Thing thing = allThings.Find(aThing => IsThing(aThing, networkId, thingId)); return thing; } private static bool IsThing(Thing thing, byte networkId, byte thingId) { if (thing == null) return false; return (thing.networkId == networkId) && (thing.id == thingId); } public static void Remove(byte networkId, byte thingId) { allThings.RemoveAll(t => t.networkId == networkId && t.id == thingId); } public static Thing[] GetAllThings() { return allThings.ToArray(); } public static void UpdateAll(float currentTime) { foreach (Thing thing in allThings) { if (thing.parent == null) // update only root things thing.Update(currentTime); } } } }