//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
//**************** Copyright (c) 2016 Marko Pintera (marko.pintera@gmail.com). All rights reserved. **********************//
using System;
using BansheeEngine;
namespace BansheeEditor
{
/** @addtogroup Inspectors
* @{
*/
///
/// Renders an inspector for the component.
///
[CustomInspector(typeof(D6Joint))]
internal class D6JointInspector : JointInspector
{
private GUIEnumField[] motionFields = new GUIEnumField[(int) D6JointAxis.Count];
private GUIToggle linearLimitFoldout = new GUIToggle(new LocEdString("Linear limit"), EditorStyles.Foldout);
private LimitLinearGUI limitLinearGUI;
private GUIToggle twistLimitFoldout = new GUIToggle(new LocEdString("Twist limit"), EditorStyles.Foldout);
private LimitAngularRangeGUI limitTwistGUI;
private GUIToggle swingLimitFoldout = new GUIToggle(new LocEdString("Swing limit"), EditorStyles.Foldout);
private LimitConeRangeGUI limitSwingGUI;
private GUIToggle driveFoldout = new GUIToggle(new LocEdString("Drive"), EditorStyles.Foldout);
private D6JointDriveGUI[] drivesGUI = new D6JointDriveGUI[(int)D6JointDriveType.Count];
private GUIVector3Field drivePositionField = new GUIVector3Field(new LocEdString("Drive position"));
private GUIVector3Field driveRotationField = new GUIVector3Field(new LocEdString("Drive rotation"));
private GUIVector3Field driveLinVelocityField = new GUIVector3Field(new LocEdString("Drive linear velocity"));
private GUIVector3Field driveAngVelocityField = new GUIVector3Field(new LocEdString("Drive angular velocity"));
private GUILayoutX linearLimitLayout;
private GUILayoutX twistLimitLayout;
private GUILayoutX swingLimitLayout;
private GUILayoutX driveLayout;
///
protected internal override void Initialize()
{
D6Joint joint = InspectedObject as D6Joint;
if (joint != null)
BuildGUI(joint);
}
///
protected internal override InspectableState Refresh()
{
D6Joint joint = InspectedObject as D6Joint;
if (joint == null)
return InspectableState.NotModified;
Refresh(joint);
InspectableState oldState = modifyState;
if (modifyState.HasFlag(InspectableState.Modified))
modifyState = InspectableState.NotModified;
return oldState;
}
///
/// Creates GUI elements for fields specific to the spherical joint.
///
protected void BuildGUI(D6Joint joint)
{
for (int i = 0; i < (int) D6JointAxis.Count; i++)
{
D6JointAxis axis = (D6JointAxis) i;
string entryName = Enum.GetName(typeof (D6JointAxis), axis);
motionFields[i] = new GUIEnumField(typeof (D6JointMotion), new LocEdString(entryName));
motionFields[i].OnSelectionChanged += x =>
{
joint.SetMotion(axis, (D6JointMotion)x);
MarkAsModified();
ConfirmModify();
};
}
linearLimitFoldout.AcceptsKeyFocus = false;
linearLimitFoldout.OnToggled += x =>
{
linearLimitLayout.Active = x;
Persistent.SetBool("linearLimit_Expanded", x);
};
twistLimitFoldout.AcceptsKeyFocus = false;
twistLimitFoldout.OnToggled += x =>
{
twistLimitLayout.Active = x;
Persistent.SetBool("twistLimit_Expanded", x);
};
swingLimitFoldout.AcceptsKeyFocus = false;
swingLimitFoldout.OnToggled += x =>
{
swingLimitLayout.Active = x;
Persistent.SetBool("swingLimit_Expanded", x);
};
driveFoldout.AcceptsKeyFocus = false;
driveFoldout.OnToggled += x =>
{
driveLayout.Active = x;
Persistent.SetBool("drive_Expanded", x);
};
drivePositionField.OnChanged += x => { joint.SetDriveTransform(x, joint.DriveRotation); MarkAsModified(); };
drivePositionField.OnFocusLost += ConfirmModify;
drivePositionField.OnConfirmed += ConfirmModify;
driveRotationField.OnChanged += x => { joint.SetDriveTransform(joint.DrivePosition, Quaternion.FromEuler(x)); MarkAsModified(); };
driveRotationField.OnFocusLost += ConfirmModify;
driveRotationField.OnConfirmed += ConfirmModify;
driveLinVelocityField.OnChanged += x => { joint.SetDriveVelocity(x, joint.DriveAngularVelocity); MarkAsModified(); };
driveLinVelocityField.OnFocusLost += ConfirmModify;
driveLinVelocityField.OnConfirmed += ConfirmModify;
driveAngVelocityField.OnChanged += x => { joint.SetDriveVelocity(joint.DriveLinearVelocity, x); MarkAsModified(); };
driveAngVelocityField.OnFocusLost += ConfirmModify;
driveAngVelocityField.OnConfirmed += ConfirmModify;
for (int i = 0; i < (int) D6JointAxis.Count; i++)
Layout.AddElement(motionFields[i]);
Layout.AddElement(linearLimitFoldout);
linearLimitLayout = Layout.AddLayoutX();
{
linearLimitLayout.AddSpace(10);
GUILayoutY linearLimitContentsLayout = linearLimitLayout.AddLayoutY();
limitLinearGUI = new LimitLinearGUI(joint.LimitLinear, linearLimitContentsLayout, Persistent);
limitLinearGUI.OnChanged += (x, y) =>
{
joint.LimitLinear = x;
joint.LimitLinear.SetBase(y);
MarkAsModified();
};
limitLinearGUI.OnConfirmed += ConfirmModify;
}
Layout.AddElement(twistLimitFoldout);
twistLimitLayout = Layout.AddLayoutX();
{
twistLimitLayout.AddSpace(10);
GUILayoutY twistLimitContentsLayout = twistLimitLayout.AddLayoutY();
limitTwistGUI = new LimitAngularRangeGUI(joint.LimitTwist, twistLimitContentsLayout, Persistent);
limitTwistGUI.OnChanged += (x, y) =>
{
joint.LimitTwist = x;
joint.LimitTwist.SetBase(y);
MarkAsModified();
};
limitTwistGUI.OnConfirmed += ConfirmModify;
}
Layout.AddElement(swingLimitFoldout);
swingLimitLayout = Layout.AddLayoutX();
{
swingLimitLayout.AddSpace(10);
GUILayoutY swingLimitContentsLayout = swingLimitLayout.AddLayoutY();
limitSwingGUI = new LimitConeRangeGUI(joint.LimitSwing, swingLimitContentsLayout, Persistent);
limitSwingGUI.OnChanged += (x, y) =>
{
joint.LimitSwing = x;
joint.LimitSwing.SetBase(y);
MarkAsModified();
};
limitSwingGUI.OnConfirmed += ConfirmModify;
}
Layout.AddElement(driveFoldout);
driveLayout = Layout.AddLayoutX();
{
driveLayout.AddSpace(10);
GUILayoutY driveContentsLayout = driveLayout.AddLayoutY();
for (int i = 0; i < (int) D6JointDriveType.Count; i++)
{
D6JointDriveType type = (D6JointDriveType)i;
drivesGUI[i] = new D6JointDriveGUI(joint.GetDrive(type), driveContentsLayout);
drivesGUI[i].OnChanged += x => { joint.SetDrive(type, x); MarkAsModified(); };
drivesGUI[i].OnConfirmed += ConfirmModify;
}
driveContentsLayout.AddElement(drivePositionField);
driveContentsLayout.AddElement(driveRotationField);
driveContentsLayout.AddElement(driveLinVelocityField);
driveContentsLayout.AddElement(driveAngVelocityField);
}
linearLimitLayout.Active = Persistent.GetBool("linearLimit_Expanded");
twistLimitLayout.Active = Persistent.GetBool("twistLimit_Expanded");
swingLimitLayout.Active = Persistent.GetBool("swingLimit_Expanded");
driveLayout.Active = Persistent.GetBool("drive_Expanded");
base.BuildGUI(joint, true);
}
///
/// Updates all GUI elements from current values in the joint.
///
/// Joint to update the GUI from.
protected void Refresh(D6Joint joint)
{
for (int i = 0; i < (int) D6JointAxis.Count; i++)
motionFields[i].Value = (ulong)joint.GetMotion((D6JointAxis) i);
limitLinearGUI.Limit = joint.LimitLinear;
limitTwistGUI.Limit = joint.LimitTwist;
limitSwingGUI.Limit = joint.LimitSwing;
for (int i = 0; i < (int) D6JointDriveType.Count; i++)
drivesGUI[i].Drive = joint.GetDrive((D6JointDriveType) i);
drivePositionField.Value = joint.DrivePosition;
driveRotationField.Value = joint.DriveRotation.ToEuler();
driveLinVelocityField.Value = joint.DriveLinearVelocity;
driveAngVelocityField.Value = joint.DriveAngularVelocity;
base.Refresh(joint);
}
}
///
/// Draws GUI elements for inspecting an object.
///
internal class D6JointDriveGUI
{
private D6JointDrive driveData;
private GUIFloatField stiffnessField = new GUIFloatField(new LocEdString("Stiffness"));
private GUIFloatField dampingField = new GUIFloatField(new LocEdString("Damping"));
private GUIFloatField forceLimitField = new GUIFloatField(new LocEdString("Force limit"));
private GUIToggleField accelerationField = new GUIToggleField(new LocEdString("Acceleration"));
public Action OnChanged;
public Action OnConfirmed;
///
/// Current drive properties.
///
public D6JointDrive Drive
{
set
{
driveData = value;
stiffnessField.Value = driveData.stiffness;
dampingField.Value = driveData.damping;
forceLimitField.Value = driveData.forceLimit;
accelerationField.Value = driveData.acceleration;
}
}
///
/// Constructs a new set of GUI elements for inspecting the drive object.
///
/// Initial values to assign to the GUI elements.
/// Layout to append the GUI elements to.
public D6JointDriveGUI(D6JointDrive drive, GUILayout layout)
{
driveData = drive;
stiffnessField.OnChanged += x => { driveData.stiffness = x; MarkAsModified(); };
stiffnessField.OnFocusLost += ConfirmModify;
stiffnessField.OnConfirmed += ConfirmModify;
dampingField.OnChanged += x => { driveData.damping = x; MarkAsModified(); };
dampingField.OnFocusLost += ConfirmModify;
dampingField.OnConfirmed += ConfirmModify;
forceLimitField.OnChanged += x => { driveData.forceLimit = x; MarkAsModified(); };
forceLimitField.OnFocusLost += ConfirmModify;
forceLimitField.OnConfirmed += ConfirmModify;
accelerationField.OnChanged += x => { driveData.acceleration = x; MarkAsModified(); ConfirmModify(); };
layout.AddElement(stiffnessField);
layout.AddElement(dampingField);
layout.AddElement(forceLimitField);
layout.AddElement(accelerationField);
}
///
/// Marks the contents of the inspector as modified.
///
private void MarkAsModified()
{
if (OnChanged != null)
OnChanged(driveData);
}
///
/// Confirms any queued modifications.
///
private void ConfirmModify()
{
if (OnConfirmed != null)
OnConfirmed();
}
}
/** @} */
}