using System; using System.Collections.Generic; using Passer.LinearAlgebra; namespace Passer.RoboidControl { /// /// A thing is the primitive building block /// [Serializable] public class Thing { #region Types /// /// Predefined thing types /// public enum Type { Undetermined, // 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 = delegate {}; 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 = delegate {}; 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 = delegate {}; private Spherical _position = Spherical.zero; public Spherical position { get { return _position; } set { if (_position != value) { _position = value; OnPositionChanged?.Invoke(); } } } public event ChangeHandler OnOrientationChanged = delegate {}; private SwingTwist _orientation = SwingTwist.zero; public SwingTwist orientation { get { return _orientation; } set { if (_orientation != value) { _orientation = value; OnOrientationChanged?.Invoke(); } } } public event SphericalHandler OnLinearVelocityChanged = delegate {}; private Spherical _linearVelocity = Spherical.zero; public Spherical linearVelocity { get => _linearVelocity; set { if (_linearVelocity != value) { _linearVelocity = value; OnLinearVelocityChanged?.Invoke(_linearVelocity); } } } public Spherical angularVelocity = Spherical.zero; #if UNITY_5_3_OR_NEWER [NonSerialized] public Unity.Thing component = null; #endif #endregion Properties #region Init public Thing(RemoteParticipant participant, bool invokeEvent = false) { this.participant = participant; 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; } 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 = delegate {}; 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); } } }