marco.bellan 9 лет назад
Родитель
Сommit
d848ef320c

+ 38 - 3
Source/MBansheeEditor/Windows/Scene/SceneSelection.cs

@@ -10,6 +10,22 @@ namespace BansheeEditor
      *  @{
      *  @{
      */
      */
 
 
+    /// <summary>
+    /// Contains information regarding object snapping.
+    /// </summary>
+    struct SnapData
+    {
+        /// <summary>
+        /// The normal to the object surface at the snapping point.
+        /// </summary>
+        public Vector3 normal;
+
+        /// <summary>
+        /// The 3D position on the surface of the object
+        /// </summary>
+        public Vector3 position;
+    }
+
     /// <summary>
     /// <summary>
     /// Handles rendering of the selection overlay and picking of objects in the target camera's view.
     /// Handles rendering of the selection overlay and picking of objects in the target camera's view.
     /// </summary>
     /// </summary>
@@ -37,9 +53,25 @@ namespace BansheeEditor
         /// </summary>
         /// </summary>
         /// <param name="pointerPos">Position of the pointer relative to the scene camera viewport.</param>
         /// <param name="pointerPos">Position of the pointer relative to the scene camera viewport.</param>
         /// <param name="controlHeld">Should this selection add to the existing selection, or replace it.</param>
         /// <param name="controlHeld">Should this selection add to the existing selection, or replace it.</param>
-        internal void PickObject(Vector2I pointerPos, bool controlHeld)
+        /// <param name="ignoreRenderables">An array of renderables that should not be rendered during scene picking.</param>
+        internal void PickObject(Vector2I pointerPos, bool controlHeld, SceneObject[] ignoreRenderables = null)
         {
         {
-            Internal_PickObject(mCachedPtr, ref pointerPos, controlHeld);
+            Internal_PickObject(mCachedPtr, ref pointerPos, controlHeld, ignoreRenderables);
+        }
+
+        /// <summary>
+        /// Returns the 3D position of an object under the cursor, along with the surface normal in that point.
+        /// </summary>
+        /// <param name="pointerPos">Position of the pointer relative to the scene camera viewport.</param>
+        /// <param name="ignoreRenderables">An array of renderables that should not be rendered during scene picking.</param>
+        /// <returns>The position on the object surface and the normal in that point.</returns>
+        internal SnapData Snap(Vector2I pointerPos, SceneObject[] ignoreRenderables = null)
+        {
+            SnapData data;
+            if (ignoreRenderables == null)
+                ignoreRenderables = new SceneObject[0];
+            Internal_Snap(mCachedPtr, ref pointerPos, out data, ignoreRenderables);
+            return data;
         }
         }
 
 
         [MethodImpl(MethodImplOptions.InternalCall)]
         [MethodImpl(MethodImplOptions.InternalCall)]
@@ -49,7 +81,10 @@ namespace BansheeEditor
         private static extern void Internal_Draw(IntPtr thisPtr);
         private static extern void Internal_Draw(IntPtr thisPtr);
 
 
         [MethodImpl(MethodImplOptions.InternalCall)]
         [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_PickObject(IntPtr thisPtr, ref Vector2I pointerPos, bool controlHeld);
+        private static extern void Internal_PickObject(IntPtr thisPtr, ref Vector2I pointerPos, bool controlHeld, SceneObject[] ignoreRenderables);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_Snap(IntPtr thisPtr, ref Vector2I pointerPos, out SnapData data, SceneObject[] ignoreRenderables);
     }
     }
 
 
     /** @} */
     /** @} */

+ 21 - 4
Source/MBansheeEditor/Windows/Scene/SceneWindow.cs

@@ -85,6 +85,7 @@ namespace BansheeEditor
         private bool dragActive;
         private bool dragActive;
         private SceneObject draggedSO;
         private SceneObject draggedSO;
         private Vector3 draggedSOOffset;
         private Vector3 draggedSOOffset;
+        private Vector2I dragBegin;
 
 
         /// <summary>
         /// <summary>
         /// Returns the scene camera.
         /// Returns the scene camera.
@@ -512,6 +513,11 @@ namespace BansheeEditor
                         Selection.SceneObject = draggedSO;
                         Selection.SceneObject = draggedSO;
                         EditorApplication.SetSceneDirty();
                         EditorApplication.SetSceneDirty();
                     }
                     }
+                    else
+                    {
+                        //Selection.SceneObjects = sceneSelection.PickObjects(dragBegin, scenePos - dragBegin,
+                        //    Input.IsButtonHeld(ButtonCode.LeftControl));
+                    }
 
 
                     draggedSO = null;
                     draggedSO = null;
                 }
                 }
@@ -520,6 +526,7 @@ namespace BansheeEditor
                     if (!dragActive)
                     if (!dragActive)
                     {
                     {
                         dragActive = true;
                         dragActive = true;
+                        dragBegin = scenePos;
 
 
                         ResourceDragDropData dragData = (ResourceDragDropData)DragDrop.Data;
                         ResourceDragDropData dragData = (ResourceDragDropData)DragDrop.Data;
 
 
@@ -540,7 +547,6 @@ namespace BansheeEditor
 
 
                                         Renderable renderable = draggedSO.AddComponent<Renderable>();
                                         Renderable renderable = draggedSO.AddComponent<Renderable>();
                                         renderable.Mesh = mesh;
                                         renderable.Mesh = mesh;
-
                                         if (mesh != null)
                                         if (mesh != null)
                                             draggedSOOffset = mesh.Bounds.Box.Center;
                                             draggedSOOffset = mesh.Bounds.Box.Center;
                                         else
                                         else
@@ -573,8 +579,19 @@ namespace BansheeEditor
 
 
                     if (draggedSO != null)
                     if (draggedSO != null)
                     {
                     {
-                        Ray worldRay = camera.ViewportToWorldRay(scenePos);
-                        draggedSO.Position = worldRay*DefaultPlacementDepth - draggedSOOffset;
+                        if (Input.IsButtonHeld(ButtonCode.Space))
+                        {
+                            SnapData snapData = sceneSelection.Snap(scenePos, new SceneObject[] {draggedSO});
+                            Debug.Log(snapData.normal);
+                            Debug.Log(snapData.position);
+                            draggedSO.Position = snapData.position;
+                            draggedSO.Rotation = Quaternion.FromAxisAngle(snapData.normal, new Degree(0));
+                        }
+                        else
+                        {
+                            Ray worldRay = camera.ViewportToWorldRay(scenePos);
+                            draggedSO.Position = worldRay * DefaultPlacementDepth - draggedSOOffset;
+                        }
                     }
                     }
                 }
                 }
 
 
@@ -617,7 +634,7 @@ namespace BansheeEditor
                             bool ctrlHeld = Input.IsButtonHeld(ButtonCode.LeftControl) ||
                             bool ctrlHeld = Input.IsButtonHeld(ButtonCode.LeftControl) ||
                                             Input.IsButtonHeld(ButtonCode.RightControl);
                                             Input.IsButtonHeld(ButtonCode.RightControl);
 
 
-                            sceneSelection.PickObject(scenePos, ctrlHeld);
+                            sceneSelection.PickObject(scenePos, ctrlHeld, new SceneObject[] { draggedSO });
                         }
                         }
                     }
                     }
                 }
                 }

+ 3 - 1
Source/SBansheeEditor/Include/BsScriptSceneSelection.h

@@ -4,6 +4,7 @@
 
 
 #include "BsScriptEditorPrerequisites.h"
 #include "BsScriptEditorPrerequisites.h"
 #include "BsScriptObject.h"
 #include "BsScriptObject.h"
+#include "BsScenePicking.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
@@ -29,7 +30,8 @@ namespace BansheeEngine
 		/************************************************************************/
 		/************************************************************************/
 		static void internal_Create(MonoObject* managedInstance, ScriptCamera* camera);
 		static void internal_Create(MonoObject* managedInstance, ScriptCamera* camera);
 		static void internal_Draw(ScriptSceneSelection* thisPtr);
 		static void internal_Draw(ScriptSceneSelection* thisPtr);
-		static void internal_PickObject(ScriptSceneSelection* thisPtr, Vector2I* inputPos, bool additive);
+		static void internal_PickObject(ScriptSceneSelection* thisPtr, Vector2I* inputPos, bool additive, MonoArray* ignoreRenderables);
+		static void internal_Snap(ScriptSceneSelection* thisPtr, Vector2I* inputPos, SnapData* data, MonoArray* ignoreRenderables);
 	};
 	};
 
 
 	/** @} */
 	/** @} */

+ 54 - 4
Source/SBansheeEditor/Source/BsScriptSceneSelection.cpp

@@ -3,8 +3,10 @@
 #include "BsScriptSceneSelection.h"
 #include "BsScriptSceneSelection.h"
 #include "BsScriptCamera.h"
 #include "BsScriptCamera.h"
 #include "BsSelectionRenderer.h"
 #include "BsSelectionRenderer.h"
+#include "BsScriptSceneObject.h"
 #include "BsScenePicking.h"
 #include "BsScenePicking.h"
 #include "BsSelection.h"
 #include "BsSelection.h"
+#include <BsMonoArray.h>
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
@@ -24,6 +26,7 @@ namespace BansheeEngine
 		metaData.scriptClass->addInternalCall("Internal_Create", &ScriptSceneSelection::internal_Create);
 		metaData.scriptClass->addInternalCall("Internal_Create", &ScriptSceneSelection::internal_Create);
 		metaData.scriptClass->addInternalCall("Internal_Draw", &ScriptSceneSelection::internal_Draw);
 		metaData.scriptClass->addInternalCall("Internal_Draw", &ScriptSceneSelection::internal_Draw);
 		metaData.scriptClass->addInternalCall("Internal_PickObject", &ScriptSceneSelection::internal_PickObject);
 		metaData.scriptClass->addInternalCall("Internal_PickObject", &ScriptSceneSelection::internal_PickObject);
+		metaData.scriptClass->addInternalCall("Internal_Snap", &ScriptSceneSelection::internal_Snap);
 	}
 	}
 
 
 	void ScriptSceneSelection::internal_Create(MonoObject* managedInstance, ScriptCamera* camera)
 	void ScriptSceneSelection::internal_Create(MonoObject* managedInstance, ScriptCamera* camera)
@@ -36,11 +39,32 @@ namespace BansheeEngine
 		thisPtr->mSelectionRenderer->update(thisPtr->mCamera);
 		thisPtr->mSelectionRenderer->update(thisPtr->mCamera);
 	}
 	}
 
 
-	void ScriptSceneSelection::internal_PickObject(ScriptSceneSelection* thisPtr, Vector2I* inputPos, bool additive)
+	void ScriptSceneSelection::internal_PickObject(ScriptSceneSelection* thisPtr, Vector2I* inputPos, bool additive, MonoArray* ignoreRenderables)
 	{
 	{
 		// TODO - Handle multi-selection (i.e. selection rectangle when dragging)
 		// TODO - Handle multi-selection (i.e. selection rectangle when dragging)
-		PickData data;
-		HSceneObject pickedObject = ScenePicking::instance().pickClosestObject(thisPtr->mCamera, *inputPos, Vector2I(1, 1), data);
+		SnapData data;
+
+		Vector<HSceneObject> ignoredSceneObjects;
+
+		if (ignoreRenderables != nullptr)
+		{
+			ScriptArray scriptArray(ignoreRenderables);
+
+			UINT32 arrayLen = scriptArray.size();
+			for (UINT32 i = 0; i < arrayLen; i++)
+			{
+				MonoObject* monoSO = scriptArray.get<MonoObject*>(i);
+				ScriptSceneObject* scriptSO = ScriptSceneObject::toNative(monoSO);
+
+				if (scriptSO == nullptr)
+					continue;
+
+				HSceneObject so = static_object_cast<SceneObject>(scriptSO->getNativeHandle());
+				ignoredSceneObjects.push_back(so);
+			}
+		}
+
+		HSceneObject pickedObject = ScenePicking::instance().pickClosestObject(thisPtr->mCamera, *inputPos, Vector2I(1, 1), data, ignoredSceneObjects);
 
 
 		if (pickedObject)
 		if (pickedObject)
 		{
 		{
@@ -67,4 +91,30 @@ namespace BansheeEngine
 		else
 		else
 			Selection::instance().clearSceneSelection();
 			Selection::instance().clearSceneSelection();
 	}
 	}
-}
+
+	void ScriptSceneSelection::internal_Snap(ScriptSceneSelection* thisPtr, Vector2I* inputPos, SnapData* data, MonoArray* ignoreRenderables)
+	{
+		Vector<HSceneObject> ignoredSceneObjects;
+
+		if (ignoreRenderables != nullptr)
+		{
+			ScriptArray scriptArray(ignoreRenderables);
+
+			UINT32 arrayLen = scriptArray.size();
+			for (UINT32 i = 0; i < arrayLen; i++)
+			{
+				MonoObject* monoSO = scriptArray.get<MonoObject*>(i);
+				ScriptSceneObject* scriptSO = ScriptSceneObject::toNative(monoSO);
+
+				if (scriptSO == nullptr)
+					continue;
+
+				HSceneObject so = static_object_cast<SceneObject>(scriptSO->getNativeHandle());
+				ignoredSceneObjects.push_back(so);
+			}
+		}
+
+  		ScenePicking::instance().pickClosestObject(thisPtr->mCamera, *inputPos, Vector2I(1, 1), *data, ignoredSceneObjects);
+	}
+
+}