Преглед изворни кода

Feature: Added a 2D handle slider that can be used for creating 2D handles in editor

BearishSun пре 8 година
родитељ
комит
d3c05debd1

+ 2 - 0
Source/BansheeEditor/CMakeSources.cmake

@@ -150,6 +150,7 @@ set(BS_BANSHEEEDITOR_INC_HANDLES
 	"Handles/BsHandleSliderManager.h"
 	"Handles/BsHandleSliderPlane.h"
 	"Handles/BsHandleSliderSphere.h"
+	"Handles/BsHandleSlider2D.h"
 )
 
 set(BS_BANSHEEEDITOR_SRC_UTILITY
@@ -219,6 +220,7 @@ set(BS_BANSHEEEDITOR_SRC_HANDLES
 	"Handles/BsHandleSliderManager.cpp"
 	"Handles/BsHandleSliderPlane.cpp"
 	"Handles/BsHandleSliderSphere.cpp"
+	"Handles/BsHandleSlider2D.cpp"
 )
 
 set(BS_BANSHEEEDITOR_INC_TESTING

+ 6 - 4
Source/BansheeEditor/Handles/BsHandleSlider.h

@@ -42,11 +42,13 @@ namespace bs
 		/**
 		 * Attempts to find an intersection between the provided ray and the slider geometry.
 		 *
-		 * @param[in]	ray	Ray in world space to try to interect with geometry.
-		 * @param[in]	t	Position of the intersection along the ray. Only if intersection happened.
-		 * @return			Whether an intersection was detected.
+		 * @param[in]	screenPos	Position in screen space at which to look for intersection. Some sliders might ignore
+		 *							this and use the @p ray instead.
+		 * @param[in]	ray			Ray in world space to try to interect with geometry.
+		 * @param[in]	t			Position of the intersection along the ray. Only if intersection happened.
+		 * @return					Whether an intersection was detected.
 		 */
-		virtual bool intersects(const Ray& ray, float& t) const = 0;
+		virtual bool intersects(const Vector2I& screenPos, const Ray& ray, float& t) const = 0;
 
 		/**
 		 * Updates a slider that is currently active (being dragged).

+ 51 - 0
Source/BansheeEditor/Handles/BsHandleSlider2D.cpp

@@ -0,0 +1,51 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2018 Marko Pintera ([email protected]). All rights reserved. **********************//
+#include "Handles/BsHandleSlider2D.h"
+#include "Handles/BsHandleManager.h"
+#include "Handles/BsHandleSliderManager.h"
+#include "Math/BsRay.h"
+#include "Math/BsRect2I.h"
+#include "Renderer/BsCamera.h"
+
+namespace bs
+{
+	HandleSlider2D::HandleSlider2D(UINT32 width, UINT32 height, UINT64 layer, Slider2DConstraint constraint)
+		: HandleSlider(true, layer), mWidth(width), mHeight(height), mConstraint(constraint), mDelta(BsZero)
+		, mStartPosition(BsZero)
+	{
+		HandleSliderManager& sliderManager = HandleManager::instance().getSliderManager();
+		sliderManager._registerSlider(this);
+	}
+
+	HandleSlider2D::~HandleSlider2D()
+	{
+		HandleSliderManager& sliderManager = HandleManager::instance().getSliderManager();
+		sliderManager._unregisterSlider(this);
+	}
+
+	bool HandleSlider2D::intersects(const Vector2I& screenPos, const Ray& ray, float& t) const
+	{
+		Vector2I center((INT32)mPosition.x, (INT32)mPosition.y);
+
+		Rect2I currentArea(center.x - mWidth / 2, center.y - mHeight, mWidth, mHeight);
+		return currentArea.contains(screenPos);
+	}
+
+	void HandleSlider2D::handleInput(const SPtr<Camera>& camera, const Vector2I& inputDelta)
+	{
+		assert(getState() == State::Active);
+
+		mCurrentPointerPos += inputDelta;
+		mDelta = mCurrentPointerPos - mStartPosition;
+
+		if(mConstraint == Slider2DConstraint::Horizontal)
+			mDelta.y = 0;
+		else if(mConstraint == Slider2DConstraint::Vertical)
+			mDelta.x = 0;
+	}
+
+	void HandleSlider2D::activate(const SPtr<Camera>& camera, const Vector2I& pointerPos)
+	{
+		mStartPosition = pointerPos;
+	}
+}

+ 70 - 0
Source/BansheeEditor/Handles/BsHandleSlider2D.h

@@ -0,0 +1,70 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2018 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsEditorPrerequisites.h"
+#include "Handles/BsHandleSlider.h"
+#include "Math/BsVector2.h"
+
+namespace bs
+{
+	/** @addtogroup Handles
+	 *  @{
+	 */
+
+	/** Constraint that determines in which direction can a HandleSlider2D be moved. */
+	enum class Slider2DConstraint
+	{
+		None, /**< Slider can be moved in both dimensions. */
+		Horizontal, /**< Slider can only be moved horizontally. */
+		Vertical /**< Slider can only be moved vertically. */
+	};
+
+	/**
+	 * Handle slider that is positioned in screen-space, and reports 2D movement in screen space (in pixels). When setting
+	 * the position the Z coordinate will be ignored, and XY coordinates will be interpreted as pixels relative to the
+	 * camera its viewed through.
+	 */
+	class BS_ED_EXPORT HandleSlider2D : public HandleSlider
+	{
+	public:
+		/**
+		 * Constructs a new 2D slider.
+		 *
+		 * @param[in]	width		Width of the area of the slider that can be interacted with, in pixels.
+		 * @param[in]	height		Height of the area of the slider that can be interacted with, in pixels.
+		 * @param[in]	layer		Layer that allows filtering of which sliders are interacted with from a specific camera.
+		 * @param[in]	constraint	Optional constraint that determines in which direction is the slider allowed to be
+		 *							moved in.
+		 */
+		HandleSlider2D(UINT32 width, UINT32 height, UINT64 layer, Slider2DConstraint constraint = Slider2DConstraint::None);
+		~HandleSlider2D();
+
+		/** @copydoc HandleSlider::intersects */
+		bool intersects(const Vector2I& screenPos, const Ray& ray, float& t) const override;
+
+		/** @copydoc HandleSlider::handleInput */
+		void handleInput(const SPtr<Camera>& camera, const Vector2I& inputDelta) override;
+
+		/**
+		 * Returns a delta value that is the result of dragging/sliding the pointer. This changes every frame and will be
+		 * zero unless the slider is active. The value is in screen space (pixels).
+		 */
+		Vector2I getDelta() const { return mDelta; }
+
+	protected:
+		/** @copydoc HandleSlider::activate */
+		void activate(const SPtr<Camera>& camera, const Vector2I& pointerPos) override;
+
+		/** @copydoc HandleSlider::reset */
+		void reset() override { mDelta = Vector2I::ZERO; }
+
+		UINT32 mWidth, mHeight;
+		Slider2DConstraint mConstraint;
+
+		Vector2I mDelta;
+		Vector2I mStartPosition;
+	};
+
+	/** @} */
+}

+ 1 - 1
Source/BansheeEditor/Handles/BsHandleSliderDisc.cpp

@@ -48,7 +48,7 @@ namespace bs
 		}
 	}
 
-	bool HandleSliderDisc::intersects(const Ray& ray, float& t) const
+	bool HandleSliderDisc::intersects(const Vector2I& screenPos, const Ray& ray, float& t) const
 	{
 		Ray localRay = ray;
 		localRay.transform(getTransformInv());

+ 1 - 1
Source/BansheeEditor/Handles/BsHandleSliderDisc.h

@@ -32,7 +32,7 @@ namespace bs
 		~HandleSliderDisc();
 
 		/** @copydoc	HandleSlider::intersects */
-		bool intersects(const Ray& ray, float& t) const override;
+		bool intersects(const Vector2I& screenPos, const Ray& ray, float& t) const override;
 
 		/** @copydoc	HandleSlider::handleInput */
 		void handleInput(const SPtr<Camera>& camera, const Vector2I& inputDelta) override;

+ 1 - 1
Source/BansheeEditor/Handles/BsHandleSliderLine.cpp

@@ -36,7 +36,7 @@ namespace bs
 		sliderManager._unregisterSlider(this);
 	}
 
-	bool HandleSliderLine::intersects(const Ray& ray, float& t) const
+	bool HandleSliderLine::intersects(const Vector2I& screenPos, const Ray& ray, float& t) const
 	{
 		Ray localRay = ray;
 		localRay.transformAffine(getTransformInv());

+ 1 - 1
Source/BansheeEditor/Handles/BsHandleSliderLine.h

@@ -33,7 +33,7 @@ namespace bs
 		~HandleSliderLine();
 
 		/** @copydoc	HandleSlider::intersects */
-		bool intersects(const Ray& ray, float& t) const override;
+		bool intersects(const Vector2I& screenPos, const Ray& ray, float& t) const override;
 
 		/** @copydoc	HandleSlider::handleInput */
 		void handleInput(const SPtr<Camera>& camera, const Vector2I& inputDelta) override;

+ 1 - 1
Source/BansheeEditor/Handles/BsHandleSliderManager.cpp

@@ -109,7 +109,7 @@ namespace bs
 			bool layerMatches = (camera->getLayers() & slider->getLayer()) != 0;
 
 			float t;
-			if (layerMatches && slider->intersects(inputRay, t))
+			if (layerMatches && slider->intersects(inputPos, inputRay, t))
 			{
 				if (t < nearestT)
 				{

+ 1 - 1
Source/BansheeEditor/Handles/BsHandleSliderPlane.cpp

@@ -31,7 +31,7 @@ namespace bs
 		sliderManager._unregisterSlider(this);
 	}
 
-	bool HandleSliderPlane::intersects(const Ray& ray, float& t) const
+	bool HandleSliderPlane::intersects(const Vector2I& screenPos, const Ray& ray, float& t) const
 	{
 		Ray localRay = ray;
 		localRay.transform(getTransformInv());

+ 1 - 1
Source/BansheeEditor/Handles/BsHandleSliderPlane.h

@@ -36,7 +36,7 @@ namespace bs
 		~HandleSliderPlane();
 
 		/** @copydoc HandleSlider::intersects */
-		bool intersects(const Ray& ray, float& t) const override;
+		bool intersects(const Vector2I& screenPos, const Ray& ray, float& t) const override;
 
 		/** @copydoc HandleSlider::handleInput */
 		void handleInput(const SPtr<Camera>& camera, const Vector2I& inputDelta) override;

+ 1 - 1
Source/BansheeEditor/Handles/BsHandleSliderSphere.cpp

@@ -23,7 +23,7 @@ namespace bs
 		sliderManager._unregisterSlider(this);
 	}
 
-	bool HandleSliderSphere::intersects(const Ray& ray, float& t) const
+	bool HandleSliderSphere::intersects(const Vector2I& screenPos, const Ray& ray, float& t) const
 	{
 		Ray localRay = ray;
 		localRay.transformAffine(getTransformInv());

+ 1 - 1
Source/BansheeEditor/Handles/BsHandleSliderSphere.h

@@ -31,7 +31,7 @@ namespace bs
 		~HandleSliderSphere();
 
 		/** @copydoc	HandleSlider::intersects */
-		bool intersects(const Ray& ray, float& t) const override;
+		bool intersects(const Vector2I& screenPos, const Ray& ray, float& t) const override;
 
 		/** @copydoc	HandleSlider::handleInput */
 		void handleInput(const SPtr<Camera>& camera, const Vector2I& inputDelta) override;

+ 1 - 0
Source/MBansheeEditor/MBansheeEditor.csproj

@@ -101,6 +101,7 @@
     <Compile Include="Windows\Scene\Gizmos\CameraGizmo.cs" />
     <Compile Include="Windows\Scene\Gizmos\LightProbeVolumeGizmo.cs" />
     <Compile Include="Windows\Scene\Gizmos\ReflectionProbeGizmo.cs" />
+    <Compile Include="Windows\Scene\Handles\HandleSlider2D.cs" />
     <Compile Include="Windows\Scene\Handles\HandleSliderSphere.cs" />
     <Compile Include="Window\DefaultSize.cs" />
     <Compile Include="Windows\DialogBox.cs" />

+ 3 - 3
Source/MBansheeEditor/Windows/Scene/Handles/HandleSlider.cs

@@ -24,11 +24,11 @@ namespace BansheeEditor
         public enum StateType
         {
             /// <summary>Slider is not being interacted with.</summary>
-	        Inactive,
+            Inactive,
             /// <summary>Slider is clicked on and being dragged.</summary>
-	        Active,
+            Active,
             /// <summary>Slider is being hovered over but isn't clicked on.</summary>
-	        Hover
+            Hover
         };
 
         /// <summary>

+ 83 - 0
Source/MBansheeEditor/Windows/Scene/Handles/HandleSlider2D.cs

@@ -0,0 +1,83 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+using System;
+using System.Runtime.CompilerServices;
+using BansheeEngine;
+
+namespace BansheeEditor
+{
+    /** @addtogroup Handles
+     *  @{
+     */
+
+    /// <summary>
+    /// Constraint that determines in which direction can a HandleSlider2D be moved.
+    /// </summary>
+    public enum Slider2DConstraint // Note: Must match C++ enum Slider2DConstraint
+    {
+        /// <summary>
+        /// Slider can be moved in both dimensions.
+        /// </summary>
+        None,
+
+        
+        /// <summary>
+        /// Slider can only be moved horizontally. 
+        /// </summary>
+        Horizontal,
+
+        /// <summary>
+        /// Slider can only be moved vertically.
+        /// </summary>
+        Vertical
+    };
+
+    /// <summary>
+    /// Handle slider that is positioned in screen-space, and reports 2D movement in screen space (in pixels). When setting
+    /// the position the Z coordinate will be ignored, and XY coordinates will be interpreted as pixels relative to the
+    /// camera its viewed through.
+    /// </summary>
+    public sealed class HandleSlider2D : HandleSlider
+    {
+        /// <summary>
+        /// Creates a new 2D handle slider. 
+        /// </summary>
+        /// <param name="parentHandle">Handle that the slider belongs to.</param>
+        /// <param name="width">Width of the area of the slider that can be interacted with, in pixels.</param>
+        /// <param name="height">Height of the area of the slider that can be interacted with, in pixels.</param>
+        /// <param name="layer">
+        /// Layer that allows filtering of which sliders are interacted with from a specific camera.
+        /// </param>
+        /// <param name="constraint">
+        /// Optional constraint that determines in which direction is the slider allowed to be moved in.
+        /// </param>
+        public HandleSlider2D(Handle parentHandle, int width, int height, Slider2DConstraint constraint, UInt64 layer = 1)
+            :base(parentHandle)
+        {
+            Internal_CreateInstance(this, width, height, constraint, layer);
+        }
+
+        /// <summary>
+        /// Returns a delta value that is the result of dragging/sliding the pointer. This changes every frame and will be
+        /// zero unless the slider is active. The value is in screen space (pixels).
+        /// </summary>
+        public Vector2I Delta
+        {
+            get
+            {
+                Vector2I value;
+                Internal_GetDelta(mCachedPtr, out value);
+                return value;
+            }
+        }
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_CreateInstance(HandleSlider2D instance, int width, int height, 
+            Slider2DConstraint constraint, UInt64 layer);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_GetDelta(IntPtr nativeInstance, out Vector2I value);
+    }
+
+    /** @} */
+}

+ 2 - 0
Source/SBansheeEditor/CMakeSources.cmake

@@ -55,6 +55,7 @@ set(BS_SBANSHEEEDITOR_SRC_WRAPPERS
 	"Wrappers/BsScriptHandleSliderManager.cpp"
 	"Wrappers/BsScriptHandleSliderPlane.cpp"
 	"Wrappers/BsScriptHandleSliderSphere.cpp"
+	"Wrappers/BsScriptHandleSlider2D.cpp"
 	"Wrappers/BsScriptImportOptions.cpp"
 	"Wrappers/BsScriptInspectorUtility.cpp"
 	"Wrappers/BsScriptModalWindow.cpp"
@@ -125,6 +126,7 @@ set(BS_SBANSHEEEDITOR_INC_WRAPPERS
 	"Wrappers/BsScriptHandleSliderLine.h"
 	"Wrappers/BsScriptHandleSliderDisc.h"
 	"Wrappers/BsScriptHandleSliderSphere.h"
+	"Wrappers/BsScriptHandleSlider2D.h"
 	"Wrappers/BsScriptHandleSlider.h"
 	"Wrappers/BsScriptHandleDrawing.h"
 	"Wrappers/BsScriptSerializedObject.h"

+ 48 - 0
Source/SBansheeEditor/Wrappers/BsScriptHandleSlider2D.cpp

@@ -0,0 +1,48 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2018 Marko Pintera ([email protected]). All rights reserved. **********************//
+#include "Wrappers/BsScriptHandleSlider2D.h"
+#include "BsScriptMeta.h"
+#include "BsMonoField.h"
+#include "BsMonoClass.h"
+#include "BsMonoManager.h"
+
+namespace bs
+{
+	ScriptHandleSlider2D::ScriptHandleSlider2D(MonoObject* instance, UINT32 width, UINT32 height, 
+		Slider2DConstraint constraint, UINT64 layer)
+		:ScriptObject(instance), mSlider(nullptr)
+	{
+		mSlider = bs_new<HandleSlider2D>(width, height, layer, constraint);
+	}
+
+	ScriptHandleSlider2D::~ScriptHandleSlider2D()
+	{
+		if (mSlider != nullptr)
+			bs_delete(mSlider);
+	}
+
+	void ScriptHandleSlider2D::destroyInternal()
+	{
+		if (mSlider != nullptr)
+			bs_delete(mSlider);
+
+		mSlider = nullptr;
+	}
+
+	void ScriptHandleSlider2D::initRuntimeData()
+	{
+		metaData.scriptClass->addInternalCall("Internal_CreateInstance", (void*)&ScriptHandleSlider2D::internal_CreateInstance);
+		metaData.scriptClass->addInternalCall("Internal_GetDelta", (void*)&ScriptHandleSlider2D::internal_GetDelta);
+	}
+
+	void ScriptHandleSlider2D::internal_CreateInstance(MonoObject* instance, UINT32 width, UINT32 height, 
+		Slider2DConstraint constraint, UINT64 layer)
+	{
+		new (bs_alloc<ScriptHandleSlider2D>()) ScriptHandleSlider2D(instance, width, height, constraint, layer);
+	}
+
+	void ScriptHandleSlider2D::internal_GetDelta(ScriptHandleSlider2D* nativeInstance, Vector2I* value)
+	{
+		*value = nativeInstance->mSlider->getDelta();
+	}
+}

+ 44 - 0
Source/SBansheeEditor/Wrappers/BsScriptHandleSlider2D.h

@@ -0,0 +1,44 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2018 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsScriptEditorPrerequisites.h"
+#include "BsScriptObject.h"
+#include "Wrappers/BsScriptHandleSlider.h"
+#include "Handles/BsHandleSlider2D.h"
+
+namespace bs
+{
+	/** @addtogroup ScriptInteropEditor
+	 *  @{
+	 */
+
+	/**	Interop class between C++ & CLR for HandleSlider2D. */
+	class BS_SCR_BED_EXPORT ScriptHandleSlider2D : public ScriptObject <ScriptHandleSlider2D, ScriptHandleSliderBase>
+	{
+	public:
+		SCRIPT_OBJ(EDITOR_ASSEMBLY, "BansheeEditor", "HandleSlider2D")
+
+	protected:
+		/** @copydoc ScriptHandleSliderBase::getSlider */
+		HandleSlider* getSlider() const override { return mSlider; }
+
+		/** @copydoc ScriptHandleSliderBase::getSlider */
+		void destroyInternal() override;
+
+	private:
+		ScriptHandleSlider2D(MonoObject* instance, UINT32 width, UINT32 height, Slider2DConstraint constraint, UINT64 layer);
+		~ScriptHandleSlider2D();
+
+		HandleSlider2D* mSlider;
+
+		/************************************************************************/
+		/* 								CLR HOOKS						   		*/
+		/************************************************************************/
+		static void internal_CreateInstance(MonoObject* instance, UINT32 width, UINT32 height, 
+			Slider2DConstraint constraint, UINT64 layer);
+		static void internal_GetDelta(ScriptHandleSlider2D* nativeInstance, Vector2I* value);
+	};
+
+	/** @} */
+}

+ 2 - 2
Source/SBansheeEditor/Wrappers/BsScriptHandleSliderLine.h

@@ -22,10 +22,10 @@ namespace bs
 
 	protected:
 		/** @copydoc ScriptHandleSliderBase::getSlider */
-		virtual HandleSlider* getSlider() const override { return mSlider; }
+		HandleSlider* getSlider() const override { return mSlider; }
 
 		/** @copydoc ScriptHandleSliderBase::getSlider */
-		virtual void destroyInternal() override;
+		void destroyInternal() override;
 
 	private:
 		ScriptHandleSliderLine(MonoObject* instance, const Vector3& direction, float length, bool fixedScale, UINT64 layer);

+ 2 - 2
Source/SBansheeEditor/Wrappers/BsScriptHandleSliderPlane.h

@@ -22,10 +22,10 @@ namespace bs
 
 	protected:
 		/** @copydoc ScriptHandleSliderBase::getSlider */
-		virtual HandleSlider* getSlider() const override { return mSlider; }
+		HandleSlider* getSlider() const override { return mSlider; }
 
 		/** @copydoc ScriptHandleSliderBase::getSlider */
-		virtual void destroyInternal() override;
+		void destroyInternal() override;
 
 	private:
 		ScriptHandleSliderPlane(MonoObject* instance, const Vector3& dir1, const Vector3& dir2, float length,