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
};
///
/// The type of this thing. This can be either a Thing::Type (needs casting)
/// or a byte value for custom types.
///
public byte type;
#endregion Types
#region Properties
///
/// The participant to which this thing belongs
///
public RemoteParticipant participant;
public delegate void ChangeHandler();
public delegate void SphericalHandler(Spherical v);
///
/// The network ID of this thing.
///
public byte networkId;
///
/// The ID of this thing
///
public byte id;
///
/// Event which is triggered when the parent changes
///
public event ChangeHandler OnParentChanged = delegate { };
private Thing _parent;
///
/// The parent of this thing
///
public Thing parent {
get => _parent;
set {
if (_parent == value)
return;
if (value == null) {
_parent?.RemoveChild(this);
_parent = null;
}
else {
value.AddChild(this);
OnParentChanged?.Invoke();
}
}
}
///
/// Attach a thing as a child of this thing
///
/// The thing to attach as a child
public void AddChild(Thing child) {
if (children.Find(thing => thing == child) != null)
return;
child._parent = this;
children.Add(child);
}
///
/// Remove the given thing as a child of this thing
///
///
public void RemoveChild(Thing child) {
children.Remove(child);
}
///
/// The list of children of this thing
///
[NonSerialized]
public List children = new List();
///
/// Event which is triggered when the name changes
///
public event ChangeHandler OnNameChanged = delegate { };
private string _name = "";
///
/// The name of the thing
///
public virtual string name {
get => _name;
set {
if (_name != value) {
_name = value;
OnNameChanged?.Invoke();
}
}
}
///
/// An URL pointing to the location where a model of the thing can be found
///
public string modelUrl = "";
///
/// Event triggered when the position has changed
///
public event ChangeHandler OnPositionChanged = delegate { };
private Spherical _position = Spherical.zero;
///
/// The position of the thing in local space, in meters.
///
public Spherical position {
get { return _position; }
set {
if (_position != value) {
_position = value;
OnPositionChanged?.Invoke();
}
}
}
///
/// Event triggered when the orientation has changed
///
public event ChangeHandler OnOrientationChanged = delegate { };
private SwingTwist _orientation = SwingTwist.zero;
///
/// The orientation of the thing in local space
///
public SwingTwist orientation {
get { return _orientation; }
set {
if (_orientation != value) {
_orientation = value;
OnOrientationChanged?.Invoke();
}
}
}
///
/// Event triggered when the linear velocity has changed
///
public event SphericalHandler OnLinearVelocityChanged = delegate { };
private Spherical _linearVelocity = Spherical.zero;
///
/// The linear velocity of the thing in local space in meters per second
///
public Spherical linearVelocity {
get => _linearVelocity;
set {
if (_linearVelocity != value) {
_linearVelocity = value;
OnLinearVelocityChanged?.Invoke(_linearVelocity);
}
}
}
///
/// The angular velocity of the thing in local space
///
public Spherical angularVelocity = Spherical.zero;
#if UNITY_5_3_OR_NEWER
///
/// A reference to the representation of the thing in Unity
///
[NonSerialized]
public Unity.Thing component = null;
#endif
#endregion Properties
#region Init
///
/// Create a new thing for the given participant
///
/// The participant for which this thing is created
/// True when a new thing event should be triggered
public Thing(RemoteParticipant participant, bool invokeEvent = false) {
this.participant = participant;
if (invokeEvent)
InvokeNewThing(this);
}
///
/// Create a new thing for the given participant
///
/// The participant for which this thing is created
/// The network ID of the thing
/// The ID of the thing
/// The type of thing
public Thing(RemoteParticipant participant, byte networkId, byte thingId, byte thingType = 0) {
this.participant = participant;
this.id = thingId;
this.type = thingType;
this.networkId = networkId;
}
///
/// Function which can be used to create components in external engines.
///
/// Currently this is used to create GameObjects in Unity
public virtual void CreateComponent() { }
#endregion Init
#region Update
#if UNITY_5_3_OR_NEWER
///
/// Convience function for use in Unity which removes the need for a currentTime argument
///
public void Update() {
Update((ulong)UnityEngine.Time.time * 1000);
}
#endif
///
/// Update this thing
///
/// The current time in milliseconds
public virtual void Update(ulong currentTime) {
// should recurse over children...
}
///
/// Function used to generate binary data for this thing
///
/// a byte array with the binary data
/// @sa Passer::RoboidControl::BinaryMsg
public virtual byte[] GenerateBinary() { return new byte[0]; }
///
/// Function used to process binary data received for this thing
///
/// The binary data
public virtual void ProcessBinary(byte[] bytes) {
}
#endregion Update
public delegate void ThingHandler(Thing t);
///
/// Event triggered when a new thing has been created
///
public static event ThingHandler OnNewThing = delegate { };
///
/// Trigger the creation for the given thing
///
/// The created thing
public static void InvokeNewThing(Thing thing) {
OnNewThing?.Invoke(thing);
}
///
/// Check if the thing has the given properaties
///
/// The thing to check
/// The network ID to compare to
/// The thing ID to compare to
/// True when the thing has the given properties
public static bool IsThing(Thing thing, byte networkId, byte thingId) {
if (thing == null)
return false;
return (thing.networkId == networkId) && (thing.id == thingId);
}
}
}