//********************************** 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(); } } /** @} */ }