public override void Bind(Entity result, Main main, bool creating = false) { Property<Direction> dir = result.GetOrMakeProperty<Direction>("Direction", true); Property<int> minimum = result.GetOrMakeProperty<int>("Minimum", true); Property<int> maximum = result.GetOrMakeProperty<int>("Maximum", true); Property<bool> locked = result.GetOrMakeProperty<bool>("Locked", true); Property<float> speed = result.GetOrMakeProperty<float>("Speed", true, 5); Property<float> maxForce = result.GetOrMakeProperty<float>("MaxForce", true); Property<float> damping = result.GetOrMakeProperty<float>("Damping", true); Property<float> stiffness = result.GetOrMakeProperty<float>("Stiffness", true); Property<int> goal = result.GetOrMakeProperty<int>("Goal", true); PrismaticJoint joint = null; Action setLimits = delegate() { if (joint != null) { int min = minimum, max = maximum; if (max > min) { joint.Limit.IsActive = true; joint.Limit.Minimum = minimum; joint.Limit.Maximum = maximum; } else joint.Limit.IsActive = false; } }; result.Add(new NotifyBinding(setLimits, minimum, maximum)); Action setMaxForce = delegate() { if (joint != null) { if (maxForce > 0.001f) joint.Motor.Settings.MaximumForce = maxForce * result.Get<DynamicMap>().PhysicsEntity.Mass; else joint.Motor.Settings.MaximumForce = float.MaxValue; } }; result.Add(new NotifyBinding(setMaxForce, maxForce)); Action setSpeed = delegate() { if (joint != null) joint.Motor.Settings.Servo.BaseCorrectiveSpeed = speed; }; result.Add(new NotifyBinding(setSpeed, speed)); Action setLocked = delegate() { if (joint != null) joint.Motor.IsActive = locked; }; result.Add(new NotifyBinding(setLocked, locked)); Action setGoal = delegate() { if (joint != null) joint.Motor.Settings.Servo.Goal = goal; }; result.Add(new NotifyBinding(setGoal, goal)); Action setDamping = delegate() { if (joint != null && damping != 0) joint.Motor.Settings.Servo.SpringSettings.DampingConstant = damping; }; result.Add(new NotifyBinding(setDamping, damping)); Action setStiffness = delegate() { if (joint != null && stiffness != 0) joint.Motor.Settings.Servo.SpringSettings.StiffnessConstant = stiffness; }; result.Add(new NotifyBinding(setStiffness, stiffness)); Func<BEPUphysics.Entities.Entity, BEPUphysics.Entities.Entity, Vector3, Vector3, Vector3, ISpaceObject> createJoint = delegate(BEPUphysics.Entities.Entity entity1, BEPUphysics.Entities.Entity entity2, Vector3 pos, Vector3 direction, Vector3 anchor) { joint = new PrismaticJoint(entity1, entity2, pos, -direction, anchor); joint.Motor.Settings.Mode = MotorMode.Servomechanism; setLimits(); setLocked(); setSpeed(); setMaxForce(); setGoal(); setDamping(); setStiffness(); return joint; }; JointFactory.Bind(result, main, createJoint, false, creating); result.Add("Forward", new Command { Action = delegate() { if (joint != null && locked) goal.Value = maximum; }, }); result.Add("Backward", new Command { Action = delegate() { if (joint != null && locked) goal.Value = minimum; }, }); Command hitMax = new Command(); result.Add("HitMax", hitMax); Command hitMin = new Command(); result.Add("HitMin", hitMin); bool lastLimitExceeded = false; result.Add(new Updater { delegate(float dt) { if (joint != null) { bool limitExceeded = joint.Limit.IsLimitExceeded; if (limitExceeded && !lastLimitExceeded) { if (joint.Limit.Error < 0) hitMin.Execute(); else hitMax.Execute(); } lastLimitExceeded = limitExceeded; } } }); }
public override void Bind(Entity result, Main main, bool creating = false) { Property<Direction> dir = result.GetOrMakeProperty<Direction>("Direction", true); Property<float> minimum = result.GetOrMakeProperty<float>("Minimum", true); Property<float> maximum = result.GetOrMakeProperty<float>("Maximum", true); Property<bool> locked = result.GetOrMakeProperty<bool>("Locked", true); Property<bool> servo = result.GetOrMakeProperty<bool>("Servo", true, true); Property<float> speed = result.GetOrMakeProperty<float>("Speed", true, 5); Property<float> goal = result.GetOrMakeProperty<float>("Goal", true); RevoluteJoint joint = null; Action setLimits = delegate() { if (joint != null) { float min = minimum, max = maximum; if (max > min) { joint.Limit.IsActive = true; joint.Limit.MinimumAngle = minimum; joint.Limit.MaximumAngle = maximum; } else joint.Limit.IsActive = false; } }; result.Add(new NotifyBinding(setLimits, minimum, maximum)); Action setSpeed = delegate() { if (joint != null) { joint.Motor.Settings.Servo.BaseCorrectiveSpeed = joint.Motor.Settings.Servo.MaxCorrectiveVelocity = speed; joint.Motor.Settings.VelocityMotor.GoalVelocity = speed; } }; result.Add(new NotifyBinding(setSpeed, speed)); Action setGoal = delegate() { if (joint != null) joint.Motor.Settings.Servo.Goal = goal; }; result.Add(new NotifyBinding(setGoal, goal)); Action setLocked = delegate() { if (joint != null) joint.Motor.IsActive = locked; }; result.Add(new NotifyBinding(setLocked, locked)); DynamicMap map = result.Get<DynamicMap>(); Action setServo = delegate() { if (joint != null) joint.Motor.Settings.Mode = servo ? MotorMode.Servomechanism : MotorMode.VelocityMotor; }; result.Add(new NotifyBinding(setServo, servo)); Func<BEPUphysics.Entities.Entity, BEPUphysics.Entities.Entity, Vector3, Vector3, Vector3, ISpaceObject> createJoint = delegate(BEPUphysics.Entities.Entity entity1, BEPUphysics.Entities.Entity entity2, Vector3 pos, Vector3 direction, Vector3 anchor) { joint = new RevoluteJoint(entity1, entity2, pos, direction); float multiplier = Math.Max(1.0f, map.PhysicsEntity.Mass); joint.AngularJoint.SpringSettings.StiffnessConstant *= multiplier; joint.Limit.SpringSettings.StiffnessConstant *= multiplier; joint.Motor.Settings.Mode = MotorMode.Servomechanism; setLimits(); setLocked(); setSpeed(); setServo(); setGoal(); return joint; }; JointFactory.Bind(result, main, createJoint, true, creating); result.Add("On", new Command { Action = delegate() { if (joint != null && locked) servo.Value = false; }, }); result.Add("Off", new Command { Action = delegate() { if (joint != null && locked) { BEPUphysics.Constraints.JointBasis2D basis = joint.Motor.Basis; basis.RotationMatrix = joint.Motor.ConnectionA.OrientationMatrix; Vector3 localTestAxis = joint.Motor.LocalTestAxis; Vector3 worldTestAxis; BEPUutilities.Matrix3x3 orientationMatrix = joint.Motor.ConnectionB.OrientationMatrix; BEPUutilities.Matrix3x3.Transform(ref localTestAxis, ref orientationMatrix, out worldTestAxis); float y, x; Vector3 yAxis = Vector3.Cross(basis.PrimaryAxis, basis.XAxis); Vector3.Dot(ref worldTestAxis, ref yAxis, out y); x = Vector3.Dot(worldTestAxis, basis.XAxis); goal.Value = (float)Math.Atan2(y, x); servo.Value = true; } }, }); result.Add("Forward", new Command { Action = delegate() { if (joint != null && locked) joint.Motor.Settings.Servo.Goal = maximum; }, }); result.Add("Backward", new Command { Action = delegate() { if (joint != null && locked) joint.Motor.Settings.Servo.Goal = minimum; }, }); Command hitMax = new Command(); result.Add("HitMax", hitMax); Command hitMin = new Command(); result.Add("HitMin", hitMin); bool lastLimitExceeded = false; result.Add(new Updater { delegate(float dt) { if (joint != null) { bool limitExceeded = joint.Limit.IsLimitExceeded; if (limitExceeded && !lastLimitExceeded) { if (joint.Limit.Error.X > 0) hitMin.Execute(); else hitMax.Execute(); } lastLimitExceeded = limitExceeded; } } }); }