using System; using System.Collections.Generic; using Passer.LinearAlgebra; namespace Passer.Control.Core { /// /// A thing is the basic building block /// [Serializable] public class Thing { #region Types public enum Type { Undeterment, // Sensor Switch, DistanceSensor, DirectionalSensor, TemperatureSensor, // Motor ControlledMotor, UncontrolledMotor, Servo, // Other Roboid, Humanoid, ExternalSensor }; #endregion Types #region Properties public RemoteParticipant 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 virtual 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; #if UNITY_5_3_OR_NEWER [NonSerialized] public Unity.Thing component; #endif #endregion Properties #region Init // public virtual void Init(bool invokeEvent = false) { // if (invokeEvent) // InvokeNewThing(this); // } public Thing(bool invokeEvent = false) { if (invokeEvent) InvokeNewThing(this); } public Thing(RemoteParticipant sender, byte networkId, byte thingId, byte thingType = 0) { this.participant = sender; this.id = thingId; this.type = thingType; this.networkId = networkId; //this.Init(); //OnNewThing?.Invoke(this); //Thing.Add(this); } public virtual void CreateComponent() {} #endregion Init #region Update #if UNITY_5_3_OR_NEWER public void Update() { Update((ulong)UnityEngine.Time.time * 1000); } #endif public virtual void Update(ulong currentTime) { // should recurse over children... } public virtual byte[] GenerateBinary() { return new byte[0]; } public virtual void ProcessBinary(byte[] bytes) { //if (sensor != null) // sensor.ProcessBytes(bytes); } #endregion Update // 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 InvokeNewThing(Thing thing) { OnNewThing?.Invoke(thing); } public static bool IsThing(Thing thing, byte networkId, byte thingId) { if (thing == null) return false; return (thing.networkId == networkId) && (thing.id == thingId); } } }