Browse Source

Added SceneObject inspector fields
Fixed a bug in euler angle -> quaternion conversion

Marko Pintera 10 years ago
parent
commit
f3b2014804

+ 3 - 0
BansheeEngine/Source/BsGUIInputBox.cpp

@@ -64,6 +64,9 @@ namespace BansheeEngine
 
 
 	void GUIInputBox::setText(const WString& text)
 	void GUIInputBox::setText(const WString& text)
 	{
 	{
+		if (mText == text)
+			return;
+
 		bool filterOkay = true;
 		bool filterOkay = true;
 		if(mFilter != nullptr)
 		if(mFilter != nullptr)
 		{
 		{

+ 6 - 14
BansheeUtility/Source/BsQuaternion.cpp

@@ -93,24 +93,16 @@ namespace BansheeEngine
 
 
 	void Quaternion::fromEulerAngles(const Radian& xAngle, const Radian& yAngle, const Radian& zAngle)
 	void Quaternion::fromEulerAngles(const Radian& xAngle, const Radian& yAngle, const Radian& zAngle)
 	{
 	{
-		Quaternion quats[3];
-		quats[0].fromAxisAngle(Vector3::UNIT_X, xAngle);
-		quats[1].fromAxisAngle(Vector3::UNIT_Y, yAngle);
-		quats[2].fromAxisAngle(Vector3::UNIT_Z, zAngle);
-
-		*this = quats[2]*(quats[0] * quats[1]);
+		Matrix3 mat;
+		mat.fromEulerAngles(xAngle, yAngle, zAngle);
+		mat.toQuaternion(*this);
 	}
 	}
 
 
 	void Quaternion::fromEulerAngles(const Radian& xAngle, const Radian& yAngle, const Radian& zAngle, EulerAngleOrder order)
 	void Quaternion::fromEulerAngles(const Radian& xAngle, const Radian& yAngle, const Radian& zAngle, EulerAngleOrder order)
 	{
 	{
-		const EulerAngleOrderData& l = EA_LOOKUP[(int)order];
-
-		Quaternion quats[3];
-		quats[0].fromAxisAngle(Vector3::UNIT_X, xAngle);
-		quats[1].fromAxisAngle(Vector3::UNIT_Y, yAngle);
-		quats[2].fromAxisAngle(Vector3::UNIT_Z, zAngle);
-
-		*this = quats[l.c]*(quats[l.a] * quats[l.b]);
+		Matrix3 mat;
+		mat.fromEulerAngles(xAngle, yAngle, zAngle, order);
+		mat.toQuaternion(*this);
 	}
 	}
 
 
 	void Quaternion::toRotationMatrix(Matrix3& mat) const
 	void Quaternion::toRotationMatrix(Matrix3& mat) const

+ 234 - 3
MBansheeEditor/Inspector/InspectorWindow.cs

@@ -18,6 +18,20 @@ namespace BansheeEditor
         private GUIScrollArea inspectorScrollArea;
         private GUIScrollArea inspectorScrollArea;
         private GUILayout inspectorLayout;
         private GUILayout inspectorLayout;
 
 
+        private SceneObject activeSO;
+        private GUITextBox soNameInput;
+        private GUILayout soPrefabLayout;
+        private bool soHasPrefab;
+        private GUIFloatField soPosX;
+        private GUIFloatField soPosY;
+        private GUIFloatField soPosZ;
+        private GUIFloatField soRotX;
+        private GUIFloatField soRotY;
+        private GUIFloatField soRotZ;
+        private GUIFloatField soScaleX;
+        private GUIFloatField soScaleY;
+        private GUIFloatField soScaleZ;
+
         [MenuItem("Windows/Inspector", ButtonModifier.CtrlAlt, ButtonCode.I)]
         [MenuItem("Windows/Inspector", ButtonModifier.CtrlAlt, ButtonCode.I)]
         private static void OpenHierarchyWindow()
         private static void OpenHierarchyWindow()
         {
         {
@@ -28,12 +42,20 @@ namespace BansheeEditor
         {
         {
             Clear();
             Clear();
 
 
-            // TODO - Create SceneObject gui elements (name + transform)
+            activeSO = so;
+
+            if (activeSO == null)
+                return;
 
 
             inspectorScrollArea = new GUIScrollArea();
             inspectorScrollArea = new GUIScrollArea();
             GUI.AddElement(inspectorScrollArea);
             GUI.AddElement(inspectorScrollArea);
             inspectorLayout = inspectorScrollArea.Layout;
             inspectorLayout = inspectorScrollArea.Layout;
 
 
+            // SceneObject fields
+            CreateSceneObjectFields();
+            RefreshSceneObjectFields(true);
+
+            // Components
             Component[] allComponents = so.GetComponents();
             Component[] allComponents = so.GetComponents();
             for (int i = 0; i < allComponents.Length; i++)
             for (int i = 0; i < allComponents.Length; i++)
             {
             {
@@ -63,8 +85,150 @@ namespace BansheeEditor
             inspectorData.inspector.SetVisible(expanded);
             inspectorData.inspector.SetVisible(expanded);
         }
         }
 
 
+        private void CreateSceneObjectFields()
+        {
+            GUIPanel sceneObjectPanel = inspectorLayout.AddPanel();
+            GUILayoutY sceneObjectLayout = sceneObjectPanel.AddLayoutY();
+
+            GUILayoutX nameLayout = sceneObjectLayout.AddLayoutX();
+            GUILabel nameLbl = new GUILabel("Name", GUIOption.FixedWidth(70));
+            soNameInput = new GUITextBox(false, GUIOption.FlexibleWidth(200));
+            soNameInput.Text = activeSO.Name;
+            soNameInput.OnChanged += (x) => { if (activeSO != null) activeSO.Name = x; };
+
+            nameLayout.AddElement(nameLbl);
+            nameLayout.AddElement(soNameInput);
+            nameLayout.AddFlexibleSpace();
+
+            soPrefabLayout = sceneObjectLayout.AddLayoutX();
+
+            GUILayoutX positionLayout = sceneObjectLayout.AddLayoutX();
+            GUILabel positionLbl = new GUILabel("Position", GUIOption.FixedWidth(70));
+            soPosX = new GUIFloatField(new GUIContent("X"), 10, "", GUIOption.FlexibleWidth(50));
+            soPosY = new GUIFloatField(new GUIContent("Y"), 10, "", GUIOption.FlexibleWidth(50));
+            soPosZ = new GUIFloatField(new GUIContent("Z"), 10, "", GUIOption.FlexibleWidth(50));
+
+            soPosX.OnChanged += (x) => OnPositionChanged(0, x);
+            soPosY.OnChanged += (y) => OnPositionChanged(1, y);
+            soPosZ.OnChanged += (z) => OnPositionChanged(2, z);
+
+            positionLayout.AddElement(positionLbl);
+            positionLayout.AddElement(soPosX);
+            positionLayout.AddSpace(10);
+            positionLayout.AddElement(soPosY);
+            positionLayout.AddSpace(10);
+            positionLayout.AddElement(soPosZ);
+            positionLayout.AddFlexibleSpace();
+
+            GUILayoutX rotationLayout = sceneObjectLayout.AddLayoutX();
+            GUILabel rotationLbl = new GUILabel("Rotation", GUIOption.FixedWidth(70));
+            soRotX = new GUIFloatField(new GUIContent("X"), 10, "", GUIOption.FlexibleWidth(50));
+            soRotY = new GUIFloatField(new GUIContent("Y"), 10, "", GUIOption.FlexibleWidth(50));
+            soRotZ = new GUIFloatField(new GUIContent("Z"), 10, "", GUIOption.FlexibleWidth(50));
+
+            soRotX.OnChanged += (x) => OnRotationChanged(0, x);
+            soRotY.OnChanged += (y) => OnRotationChanged(1, y);
+            soRotZ.OnChanged += (z) => OnRotationChanged(2, z);
+
+            rotationLayout.AddElement(rotationLbl);
+            rotationLayout.AddElement(soRotX);
+            rotationLayout.AddSpace(10);
+            rotationLayout.AddElement(soRotY);
+            rotationLayout.AddSpace(10);
+            rotationLayout.AddElement(soRotZ);
+            rotationLayout.AddFlexibleSpace();
+
+            GUILayoutX scaleLayout = sceneObjectLayout.AddLayoutX();
+            GUILabel scaleLbl = new GUILabel("Scale", GUIOption.FixedWidth(70));
+            soScaleX = new GUIFloatField(new GUIContent("X"), 10, "", GUIOption.FlexibleWidth(50));
+            soScaleY = new GUIFloatField(new GUIContent("Y"), 10, "", GUIOption.FlexibleWidth(50));
+            soScaleZ = new GUIFloatField(new GUIContent("Z"), 10, "", GUIOption.FlexibleWidth(50));
+
+            soScaleX.OnChanged += (x) => OnScaleChanged(0, x);
+            soScaleY.OnChanged += (y) => OnScaleChanged(1, y);
+            soScaleX.OnChanged += (z) => OnScaleChanged(2, z);
+
+            scaleLayout.AddElement(scaleLbl);
+            scaleLayout.AddElement(soScaleX);
+            scaleLayout.AddSpace(10);
+            scaleLayout.AddElement(soScaleY);
+            scaleLayout.AddSpace(10);
+            scaleLayout.AddElement(soScaleZ);
+            scaleLayout.AddFlexibleSpace();
+        }
+
+        private void RefreshSceneObjectFields(bool forceUpdate)
+        {
+            if (activeSO == null)
+                return;
+
+            soNameInput.Text = activeSO.Name;
+
+            bool hasPrefab = PrefabUtility.HasPrefabLink(activeSO);
+            if (soHasPrefab != hasPrefab || forceUpdate)
+            {
+                int numChildren = soPrefabLayout.GetNumChildren();
+                for (int i = 0; i < numChildren; i++)
+                    soPrefabLayout.GetChild(0).Destroy();
+
+                GUILabel prefabLabel =new GUILabel("Prefab", GUIOption.FixedWidth(70));
+                soPrefabLayout.AddElement(prefabLabel);
+
+                //if (hasPrefab) // TODO - Disabled check for preview purposes
+                {
+                    GUIButton btnApplyPrefab = new GUIButton("Apply");
+                    GUIButton btnRevertPrefab = new GUIButton("Revert");
+                    GUIButton btnBreakPrefab = new GUIButton("Break");
+
+                    btnApplyPrefab.OnClick += () => PrefabUtility.ApplyPrefab(activeSO);
+                    btnRevertPrefab.OnClick += () => PrefabUtility.RevertPrefab(activeSO);
+                    btnBreakPrefab.OnClick += () => PrefabUtility.BreakPrefab(activeSO);
+
+                    soPrefabLayout.AddElement(btnApplyPrefab);
+                    soPrefabLayout.AddElement(btnRevertPrefab);
+                    soPrefabLayout.AddElement(btnBreakPrefab);
+                }
+                //else
+                //{
+                //    GUILabel noPrefabLabel = new GUILabel("None");
+                //    soPrefabLayout.AddElement(noPrefabLabel);
+                //}
+
+                soHasPrefab = hasPrefab;
+            }
+
+            Vector3 position;
+            Vector3 angles;
+            if (EditorApplication.ActiveCoordinateMode == HandleCoordinateMode.World)
+            {
+                position = activeSO.Position;
+                angles = activeSO.Rotation.ToEuler();
+            }
+            else
+            {
+                position = activeSO.LocalPosition;
+                angles = activeSO.LocalRotation.ToEuler();
+            }
+
+            Vector3 scale = activeSO.LocalScale;
+
+            soPosX.Value = position.x;
+            soPosY.Value = position.y;
+            soPosZ.Value = position.z;
+
+            soRotX.Value = angles.x;
+            soRotY.Value = angles.y;
+            soRotZ.Value = angles.z;
+
+            soScaleX.Value = scale.x;
+            soScaleY.Value = scale.y;
+            soScaleZ.Value = scale.z;
+        }
+
         private void OnEditorUpdate()
         private void OnEditorUpdate()
         {
         {
+            RefreshSceneObjectFields(false);
+
             for (int i = 0; i < inspectorData.Count; i++)
             for (int i = 0; i < inspectorData.Count; i++)
             {
             {
                 inspectorData[i].inspector.Refresh();
                 inspectorData[i].inspector.Refresh();
@@ -73,8 +237,6 @@ namespace BansheeEditor
 
 
         internal void Destroy()
         internal void Destroy()
         {
         {
-            // TODO - Destroy SceneObject GUI elements
-
             Clear();
             Clear();
         }
         }
 
 
@@ -93,6 +255,75 @@ namespace BansheeEditor
                 inspectorScrollArea.Destroy();
                 inspectorScrollArea.Destroy();
                 inspectorScrollArea = null;
                 inspectorScrollArea = null;
             }
             }
+
+            activeSO = null;
+            soNameInput = null;
+            soPrefabLayout = null;
+            soHasPrefab = false;
+            soPosX = null;
+            soPosY = null;
+            soPosZ = null;
+            soRotX = null;
+            soRotY = null;
+            soRotZ = null;
+            soScaleX = null;
+            soScaleY = null;
+            soScaleZ = null;
+        }
+
+        private void OnPositionChanged(int idx, float value)
+        {
+            if (activeSO == null)
+                return;
+
+            if (EditorApplication.ActiveCoordinateMode == HandleCoordinateMode.World)
+            {
+                Vector3 position = activeSO.Position;
+                position[idx] = value;
+                activeSO.Position = position;
+            }
+            else
+            {
+                Vector3 position = activeSO.LocalPosition;
+                position[idx] = value;
+                activeSO.LocalPosition = position;
+            }
+        }
+
+        private void OnRotationChanged(int idx, float value)
+        {
+            if (activeSO == null)
+                return;
+
+            if (EditorApplication.ActiveCoordinateMode == HandleCoordinateMode.World)
+            {
+                Vector3 angles = activeSO.Rotation.ToEuler();
+                angles[idx] = value;
+                activeSO.Rotation = Quaternion.FromEuler(angles);
+            }
+            else
+            {
+                Vector3 angles = activeSO.LocalRotation.ToEuler();
+                angles[idx] = value;
+                activeSO.LocalRotation = Quaternion.FromEuler(angles);
+
+                Debug.Log("ROTATION CHANGED: " + idx + " - " + value + " - " + angles + " - " + activeSO.LocalRotation + " - " + activeSO.LocalRotation.ToEuler());
+
+                Quaternion dbg = Quaternion.FromEuler(angles);
+
+                Debug.Log("LOCAL CHECK: " + angles + " - " + dbg + " - " + dbg.ToEuler());
+                
+            }
+        }
+
+        private void OnScaleChanged(int idx, float value)
+        {
+            if (activeSO == null)
+                return;
+
+            Vector3 scale = activeSO.LocalScale;
+            scale[idx] = value;
+            activeSO.LocalScale = scale;
         }
         }
 
 
         private Inspector GetInspector(Type type)
         private Inspector GetInspector(Type type)

+ 12 - 0
MBansheeEditor/PrefabUtility.cs

@@ -37,6 +37,15 @@ namespace BansheeEditor
             Internal_RevertPrefab(objPtr);
             Internal_RevertPrefab(objPtr);
         }
         }
 
 
+        public static bool HasPrefabLink(SceneObject obj)
+        {
+            if (obj == null)
+                return false;
+
+            IntPtr objPtr = obj.GetCachedPtr();
+            return Internal_HasPrefabLink(objPtr);
+        }
+
         [MethodImpl(MethodImplOptions.InternalCall)]
         [MethodImpl(MethodImplOptions.InternalCall)]
         private static extern void Internal_BreakPrefab(IntPtr nativeInstance);
         private static extern void Internal_BreakPrefab(IntPtr nativeInstance);
 
 
@@ -45,5 +54,8 @@ namespace BansheeEditor
 
 
         [MethodImpl(MethodImplOptions.InternalCall)]
         [MethodImpl(MethodImplOptions.InternalCall)]
         private static extern void Internal_RevertPrefab(IntPtr nativeInstance);
         private static extern void Internal_RevertPrefab(IntPtr nativeInstance);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern bool Internal_HasPrefabLink(IntPtr nativeInstance);
     }
     }
 }
 }

+ 5 - 11
MBansheeEngine/Math/Quaternion.cs

@@ -360,7 +360,7 @@ namespace BansheeEngine
         }
         }
 
 
         // Returns angles in degrees
         // Returns angles in degrees
-        public Vector3 ToEulerAngles(EulerAngleOrder order = EulerAngleOrder.XYZ)
+        public Vector3 ToEuler(EulerAngleOrder order = EulerAngleOrder.XYZ)
         {
         {
             Matrix3 matRot = ToRotationMatrix();
             Matrix3 matRot = ToRotationMatrix();
             return matRot.ToEulerAngles(order);
             return matRot.ToEulerAngles(order);
@@ -426,9 +426,9 @@ namespace BansheeEngine
             return quat;
             return quat;
         }
         }
 
 
-        public static Vector3 ToEulerAngles(Quaternion rotation, EulerAngleOrder order = EulerAngleOrder.XYZ)
+        public static Vector3 ToEuler(Quaternion rotation, EulerAngleOrder order = EulerAngleOrder.XYZ)
         {
         {
-            return rotation.ToEulerAngles(order);
+            return rotation.ToEuler(order);
         }
         }
 
 
         public static void ToAxisAngle(Quaternion rotation, out Vector3 axis, out Degree angleDeg)
         public static void ToAxisAngle(Quaternion rotation, out Vector3 axis, out Degree angleDeg)
@@ -501,14 +501,8 @@ namespace BansheeEngine
 
 
         public static Quaternion FromEuler(float xDeg, float yDeg, float zDeg, EulerAngleOrder order = EulerAngleOrder.XYZ)
         public static Quaternion FromEuler(float xDeg, float yDeg, float zDeg, EulerAngleOrder order = EulerAngleOrder.XYZ)
         {
         {
-            EulerAngleOrderData l = EA_LOOKUP[(int)order];
-
-            Quaternion[] quats = new Quaternion[3];
-		    quats[0] = FromAxisAngle(Vector3.xAxis, xDeg);
-		    quats[1] = FromAxisAngle(Vector3.yAxis, yDeg);
-		    quats[2] = FromAxisAngle(Vector3.zAxis, zDeg);
-
-            return quats[l.c]*(quats[l.a] * quats[l.b]);
+            Matrix3 mat = Matrix3.FromEuler(new Vector3(xDeg, yDeg, zDeg), order);
+            return mat.ToQuaternion();
         }
         }
 
 
         /**
         /**

+ 1 - 0
SBansheeEditor/Include/BsScriptPrefabUtility.h

@@ -14,6 +14,7 @@ namespace BansheeEngine
 		static void internal_breakPrefab(ScriptSceneObject* nativeInstance);
 		static void internal_breakPrefab(ScriptSceneObject* nativeInstance);
 		static void internal_applyPrefab(ScriptSceneObject* nativeInstance);
 		static void internal_applyPrefab(ScriptSceneObject* nativeInstance);
 		static void internal_revertPrefab(ScriptSceneObject* nativeInstance);
 		static void internal_revertPrefab(ScriptSceneObject* nativeInstance);
+		static bool internal_hasPrefabLink(ScriptSceneObject* nativeInstance);
 
 
 		ScriptPrefabUtility(MonoObject* instance);
 		ScriptPrefabUtility(MonoObject* instance);
 	};
 	};

+ 9 - 0
SBansheeEditor/Source/BsScriptPrefabUtility.cpp

@@ -20,6 +20,7 @@ namespace BansheeEngine
 		metaData.scriptClass->addInternalCall("Internal_BreakPrefab", &ScriptPrefabUtility::internal_breakPrefab);
 		metaData.scriptClass->addInternalCall("Internal_BreakPrefab", &ScriptPrefabUtility::internal_breakPrefab);
 		metaData.scriptClass->addInternalCall("Internal_ApplyPrefab", &ScriptPrefabUtility::internal_applyPrefab);
 		metaData.scriptClass->addInternalCall("Internal_ApplyPrefab", &ScriptPrefabUtility::internal_applyPrefab);
 		metaData.scriptClass->addInternalCall("Internal_RevertPrefab", &ScriptPrefabUtility::internal_revertPrefab);
 		metaData.scriptClass->addInternalCall("Internal_RevertPrefab", &ScriptPrefabUtility::internal_revertPrefab);
+		metaData.scriptClass->addInternalCall("Internal_HasPrefabLink", &ScriptPrefabUtility::internal_hasPrefabLink);
 	}
 	}
 
 
 	void ScriptPrefabUtility::internal_breakPrefab(ScriptSceneObject* nativeInstance)
 	void ScriptPrefabUtility::internal_breakPrefab(ScriptSceneObject* nativeInstance)
@@ -51,4 +52,12 @@ namespace BansheeEngine
 
 
 		PrefabUtility::revertToPrefab(nativeInstance->getNativeSceneObject());
 		PrefabUtility::revertToPrefab(nativeInstance->getNativeSceneObject());
 	}
 	}
+
+	bool ScriptPrefabUtility::internal_hasPrefabLink(ScriptSceneObject* nativeInstance)
+	{
+		if (ScriptSceneObject::checkIfDestroyed(nativeInstance))
+			return false;
+
+		return !nativeInstance->getNativeSceneObject()->getPrefabLink().empty();
+	}
 }
 }

+ 7 - 0
TODO.txt

@@ -56,15 +56,19 @@ Code quality improvements:
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 Polish stage 1
 Polish stage 1
 
 
+Int/Float field mouse scrolling doesn't work
 Fix DX11 (and possibly DX9) rendering
 Fix DX11 (and possibly DX9) rendering
 After undocking ProjectWindow the auto-scroll seems to be stuck in up position
 After undocking ProjectWindow the auto-scroll seems to be stuck in up position
 Decent looking default layout
 Decent looking default layout
 When selecting an gizmo icon the selection seems delayed and its gizmos flash for a frame before hiding
 When selecting an gizmo icon the selection seems delayed and its gizmos flash for a frame before hiding
 Make sure that scene camera controls only work when scene view is in focus
 Make sure that scene camera controls only work when scene view is in focus
+Make proper window names instead of InspectorWindow
+Selection wireframe seems to render in front of handles
 
 
 Fix handles
 Fix handles
  - Some handle functionality is unfinished
  - Some handle functionality is unfinished
  - Handles look too large when scene view is enlarged
  - Handles look too large when scene view is enlarged
+ - Moving around XZ plane seems to be wrong (it doesn't move as fast as the mouse)
 
 
 Add ping to SceneTreeView
 Add ping to SceneTreeView
  - Hook up ping effect so it triggers when I select a resource or sceneobject
  - Hook up ping effect so it triggers when I select a resource or sceneobject
@@ -84,6 +88,9 @@ For later: I could record undo/redo per-property using the new diff system
 Remember: Record all portions where objects & components get modified so I can mark them dirty, will likely need
 Remember: Record all portions where objects & components get modified so I can mark them dirty, will likely need
  to use those some points for undo/redo
  to use those some points for undo/redo
 
 
+UndoRedo reminders:
+ - When breaking or reverting a scene object
+
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 Project window
 Project window