Marko Pintera 11 лет назад
Родитель
Сommit
a4c60121f4

+ 10 - 0
BansheeEditor/BansheeEditor.vcxproj

@@ -291,6 +291,11 @@
     <ClInclude Include="Include\BsGUIToggleField.h" />
     <ClInclude Include="Include\BsGUIVector3Field.h" />
     <ClInclude Include="Include\BsGUIVector4Field.h" />
+    <ClInclude Include="Include\BsHandleManager.h" />
+    <ClInclude Include="Include\BsHandleSlider.h" />
+    <ClInclude Include="Include\BsHandleSliderDisc.h" />
+    <ClInclude Include="Include\BsHandleSliderLine.h" />
+    <ClInclude Include="Include\BsHandleSliderPlane.h" />
     <ClInclude Include="Include\BsScenePicking.h" />
     <ClInclude Include="Include\BsProjectLibraryEntriesRTTI.h" />
     <ClInclude Include="Include\BsEditorPrerequisites.h" />
@@ -367,6 +372,11 @@
     <ClCompile Include="Source\BsGUIWindowFrame.cpp" />
     <ClCompile Include="Source\BsGUIWindowFrameWidget.cpp" />
     <ClCompile Include="Source\BsGUIWindowDropArea.cpp" />
+    <ClCompile Include="Source\BsHandleManager.cpp" />
+    <ClCompile Include="Source\BsHandleSlider.cpp" />
+    <ClCompile Include="Source\BsHandleSliderDisc.cpp" />
+    <ClCompile Include="Source\BsHandleSliderLine.cpp" />
+    <ClCompile Include="Source\BsHandleSliderPlane.cpp" />
     <ClCompile Include="Source\BsMainEditorWindow.cpp" />
     <ClCompile Include="Source\BsScenePicking.cpp" />
     <ClCompile Include="Source\BsProjectLibrary.cpp" />

+ 30 - 0
BansheeEditor/BansheeEditor.vcxproj.filters

@@ -219,6 +219,21 @@
     <ClInclude Include="Include\BsSelection.h">
       <Filter>Header Files\Editor</Filter>
     </ClInclude>
+    <ClInclude Include="Include\BsHandleManager.h">
+      <Filter>Header Files\Editor</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsHandleSliderLine.h">
+      <Filter>Header Files\Editor</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsHandleSlider.h">
+      <Filter>Header Files\Editor</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsHandleSliderPlane.h">
+      <Filter>Header Files\Editor</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsHandleSliderDisc.h">
+      <Filter>Header Files\Editor</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\BsEditorWidgetContainer.cpp">
@@ -386,5 +401,20 @@
     <ClCompile Include="Source\BsSelection.cpp">
       <Filter>Source Files\Editor</Filter>
     </ClCompile>
+    <ClCompile Include="Source\BsHandleManager.cpp">
+      <Filter>Source Files\Editor</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsHandleSlider.cpp">
+      <Filter>Source Files\Editor</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsHandleSliderLine.cpp">
+      <Filter>Source Files\Editor</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsHandleSliderPlane.cpp">
+      <Filter>Source Files\Editor</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsHandleSliderDisc.cpp">
+      <Filter>Source Files\Editor</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>

+ 1 - 0
BansheeEditor/Include/BsEditorPrerequisites.h

@@ -56,6 +56,7 @@ namespace BansheeEngine
 	class EditorCommand;
 	class ProjectResourceMeta;
 	class SceneGrid;
+	class HandleSlider;
 
 	typedef std::shared_ptr<ProjectResourceMeta> ProjectResourceMetaPtr;
 	typedef std::shared_ptr<DockManagerLayout> DockManagerLayoutPtr;

+ 44 - 0
BansheeEditor/Include/BsHandleManager.h

@@ -0,0 +1,44 @@
+#pragma once
+
+#include "BsEditorPrerequisites.h"
+#include "BsModule.h"
+#include "BsCapsule.h"
+#include "BsSphere.h"
+#include "BsRect3.h"
+#include "BsTorus.h"
+
+namespace BansheeEngine
+{
+	class BS_ED_EXPORT HandleManager : public Module<HandleManager>
+	{
+	public:
+		// TODO - Add a bunch of draw methods similar to GizmoManager
+		//      - And a similar render method
+
+		//void drawCube(const Vector3& position, const Vector3& extents);
+		//void drawSphere(const Vector3& position, float radius);
+		//void drawWireCube(const Vector3& position, const Vector3& extents);
+		//void drawWireSphere(const Vector3& position, float radius);
+		//void drawCone(const Vector3& base, const Vector3& normal, float height, float radius);
+		//void drawLine(const Vector3& start, const Vector3& end);
+		//void drawDisc(const Vector3& position, const Vector3& normal, float radius);
+		//void drawWireDisc(const Vector3& position, const Vector3& normal, float radius);
+		//void drawArc(const Vector3& position, const Vector3& normal, float radius, Degree startAngle, Degree amountAngle);
+		//void drawWireArc(const Vector3& position, const Vector3& normal, float radius, Degree startAngle, Degree amountAngle);
+
+		// TODO - Add update method that handles mouse input
+
+		void _registerCapsuleCollider(const Capsule& collider, HandleSlider* slider);
+		void _registerSphereCollider(const Sphere& collider, HandleSlider* slider);
+		void _registerRectCollider(const Rect3& collider, HandleSlider* slider);
+		void _registerTorusCollider(const Torus& collider, HandleSlider* slider);
+		void _unregisterSlider(HandleSlider* slider);
+	private:
+		UnorderedSet<HandleSlider*> mSliders;
+
+		UnorderedMap<HandleSlider*, Capsule> mCapsuleColliders;
+		UnorderedMap<HandleSlider*, Sphere> mSphereColliders;
+		UnorderedMap<HandleSlider*, Rect3> mRectColliders;
+		UnorderedMap<HandleSlider*, Torus> mTorusColliders;
+	};
+}

+ 45 - 0
BansheeEditor/Include/BsHandleSlider.h

@@ -0,0 +1,45 @@
+#pragma once
+
+#include "BsEditorPrerequisites.h"
+#include "BsVector2I.h"
+#include "BsMatrix4.h"
+
+namespace BansheeEngine
+{
+	class BS_ED_EXPORT HandleSlider
+	{
+	public:
+		enum class State
+		{
+			Inactive,
+			Active,
+			Hover
+		};
+
+		HandleSlider(bool fixedScale, float snapValue);
+		virtual ~HandleSlider() { }
+
+		State getState() const { return mState; }
+		bool getFixedScale() const { return mFixedScale; }
+		float getSnapValue() const { return mSnapValue; }
+
+		virtual void setCustomTransform(const Matrix4& transform) { mCustomTransform = transform; }
+		virtual const Matrix4& getCustomTransform() const { return mCustomTransform; }
+
+	protected:
+		friend class HandleManager;
+
+		void setInactive() { mState = State::Inactive; }
+		void setActive(const Vector2I& pointerPos) { mState = State::Active; mLastPointerPos = pointerPos; }
+		void setHover() { mState = State::Hover; }
+		void registerDrag(const Vector2I& pointerPos);
+
+		bool mFixedScale;
+		float mSnapValue;
+		Matrix4 mCustomTransform;
+
+		Vector2I mLastPointerPos;
+		Vector2I mCurPointerPos;
+		State mState;
+	};
+}

+ 24 - 0
BansheeEditor/Include/BsHandleSliderDisc.h

@@ -0,0 +1,24 @@
+#pragma once
+
+#include "BsEditorPrerequisites.h"
+#include "BsHandleSlider.h"
+
+namespace BansheeEngine
+{
+	class BS_ED_EXPORT HandleSliderDisc : public HandleSlider
+	{
+	public:
+		HandleSliderDisc(const Vector3& normal, float radius, float snapValue, bool fixedScale);
+		~HandleSliderDisc();
+
+		Quaternion updateDelta(const Quaternion& oldValue) const;
+
+		void setCustomTransform(const Matrix4& transform);
+	protected:
+		static const float TORUS_RADIUS;
+
+		Vector3 mNormal;
+		float mRadius;
+		Matrix4 mTorusRotation;
+	};
+}

+ 21 - 0
BansheeEditor/Include/BsHandleSliderPlane.h

@@ -0,0 +1,21 @@
+#pragma once
+
+#include "BsEditorPrerequisites.h"
+#include "BsHandleSlider.h"
+
+namespace BansheeEngine
+{
+	class BS_ED_EXPORT HandleSliderPlane : public HandleSlider
+	{
+	public:
+		HandleSliderPlane(const Vector3& dir1, const Vector3& dir2, float length, float snapValue, bool fixedScale);
+		~HandleSliderPlane();
+
+		Vector3 updateDelta(const Vector3& oldValue) const;
+
+	protected:
+		Vector3 mDirection1;
+		Vector3 mDirection2;
+		float mLength;
+	};
+}

+ 45 - 0
BansheeEditor/Source/BsHandleManager.cpp

@@ -0,0 +1,45 @@
+#include "BsHandleManager.h"
+
+namespace BansheeEngine
+{
+	void HandleManager::_registerCapsuleCollider(const Capsule& collider, HandleSlider* slider)
+	{
+		if (mSliders.find(slider) == mSliders.end())
+			mSliders.insert(slider);
+
+		mCapsuleColliders[slider] = collider;
+	}
+
+	void HandleManager::_registerSphereCollider(const Sphere& collider, HandleSlider* slider)
+	{
+		if (mSliders.find(slider) == mSliders.end())
+			mSliders.insert(slider);
+
+		mSphereColliders[slider] = collider;
+	}
+
+	void HandleManager::_registerRectCollider(const Rect3& collider, HandleSlider* slider)
+	{
+		if (mSliders.find(slider) == mSliders.end())
+			mSliders.insert(slider);
+
+		mRectColliders[slider] = collider;
+	}
+
+	void HandleManager::_registerTorusCollider(const Torus& collider, HandleSlider* slider)
+	{
+		if (mSliders.find(slider) == mSliders.end())
+			mSliders.insert(slider);
+
+		mTorusColliders[slider] = collider;
+	}
+
+	void HandleManager::_unregisterSlider(HandleSlider* slider)
+	{
+		mCapsuleColliders.erase(slider);
+		mSphereColliders.erase(slider);
+		mRectColliders.erase(slider);
+		mTorusColliders.erase(slider);
+		mSliders.erase(slider);
+	}
+}

+ 18 - 0
BansheeEditor/Source/BsHandleSlider.cpp

@@ -0,0 +1,18 @@
+#include "BsHandleSlider.h"
+
+namespace BansheeEngine
+{
+	HandleSlider::HandleSlider(bool fixedScale, float snapValue)
+		:mFixedScale(fixedScale), mSnapValue(snapValue)
+	{
+
+	}
+
+	void HandleSlider::registerDrag(const Vector2I& pointerPos)
+	{
+		assert(getState() == State::Active);
+
+		mLastPointerPos = mCurPointerPos;
+		mCurPointerPos = pointerPos;
+	}
+}

+ 40 - 0
BansheeEditor/Source/BsHandleSliderDisc.cpp

@@ -0,0 +1,40 @@
+#include "BsHandleSliderDisc.h"
+#include "BsHandleManager.h"
+#include "BsTorus.h"
+#include "BsVector3.h"
+#include "BsQuaternion.h"
+
+namespace BansheeEngine
+{
+	const float HandleSliderDisc::TORUS_RADIUS = 0.5f;
+
+	HandleSliderDisc::HandleSliderDisc(const Vector3& normal, float radius, float snapValue, bool fixedScale)
+		:HandleSlider(fixedScale, snapValue), mRadius(radius)
+	{
+		Vector3 x, z;
+		mNormal.orthogonalComplement(x, z);
+
+		mTorusRotation = (Matrix4)Matrix3(x, mNormal, z); // Our Torus class doesn't allow us to specify a normal so we embed it here
+
+		Torus collider(radius, TORUS_RADIUS);
+		HandleManager::instance()._registerTorusCollider(collider, this);
+	}
+
+	HandleSliderDisc::~HandleSliderDisc()
+	{
+		HandleManager::instance()._unregisterSlider(this);
+	}
+
+	Quaternion HandleSliderDisc::updateDelta(const Quaternion& oldValue) const
+	{
+		return oldValue;
+
+		// TODO - Don't  forget to consider currently active transform (and also custom handle transform)
+		// - Both position and direction need to consider it
+	}
+
+	void HandleSliderDisc::setCustomTransform(const Matrix4& transform)
+	{
+		HandleSlider::setCustomTransform(transform * mTorusRotation);
+	}
+}

+ 38 - 0
BansheeEditor/Source/BsHandleSliderLine.cpp

@@ -0,0 +1,38 @@
+#include "BsHandleSliderLine.h"
+#include "BsHandleManager.h"
+#include "BsCapsule.h"
+#include "BsLineSegment3.h"
+#include "BsSphere.h"
+
+namespace BansheeEngine
+{
+	const float HandleSliderLine::CAPSULE_RADIUS = 0.2f;
+	const float HandleSliderLine::SPHERE_RADIUS = 0.5f;
+
+	HandleSliderLine::HandleSliderLine(const Vector3& direction, float length, float snapValue, bool fixedScale)
+		:HandleSlider(fixedScale, snapValue), mLength(length)
+	{
+		mDirection = Vector3::normalize(direction);
+
+		Vector3 start = Vector3::ZERO;
+		Vector3 end = start + mDirection * length;
+
+		Vector3 sphereCenter = start + mDirection * std::max(0.0f, length - SPHERE_RADIUS * 2);
+
+		HandleManager::instance()._registerCapsuleCollider(Capsule(LineSegment3(start, end), CAPSULE_RADIUS), this);
+		HandleManager::instance()._registerSphereCollider(Sphere(sphereCenter, SPHERE_RADIUS), this);
+	}
+
+	HandleSliderLine::~HandleSliderLine()
+	{
+		HandleManager::instance()._unregisterSlider(this);
+	}
+
+	Vector3 HandleSliderLine::updateDelta(const Vector3& oldValue) const
+	{
+		return oldValue;
+
+		// TODO - Don't  forget to consider currently active transform (and also custom handle transform)
+		// - Both position and direction need to consider it
+	}
+}

+ 33 - 0
BansheeEditor/Source/BsHandleSliderPlane.cpp

@@ -0,0 +1,33 @@
+#include "BsHandleSliderPlane.h"
+#include "BsHandleManager.h"
+#include "BsRect3.h"
+#include "BsVector3.h"
+
+namespace BansheeEngine
+{
+	HandleSliderPlane::HandleSliderPlane(const Vector3& dir1, const Vector3& dir2, float length, float snapValue, bool fixedScale)
+		:HandleSlider(fixedScale, snapValue), mLength(length)
+	{
+		mDirection1 = Vector3::normalize(dir1);
+		mDirection2 = Vector3::normalize(dir2);
+
+		std::array<Vector3, 2> axes = { mDirection1, mDirection2 };
+		std::array<float, 2> extents = { length, length };
+
+		Rect3 collider(Vector3::ZERO, axes, extents);
+		HandleManager::instance()._registerRectCollider(collider, this);
+	}
+
+	HandleSliderPlane::~HandleSliderPlane()
+	{
+		HandleManager::instance()._unregisterSlider(this);
+	}
+
+	Vector3 HandleSliderPlane::updateDelta(const Vector3& oldValue) const
+	{
+		return oldValue;
+
+		// TODO - Don't  forget to consider currently active transform (and also custom handle transform)
+		// - Both position and direction need to consider it
+	}
+}

+ 32 - 0
BansheeEngine/Include/BsDrawHelper3D.h

@@ -5,6 +5,7 @@
 #include "BsModule.h"
 #include "BsColor.h"
 #include "BsAABox.h"
+#include "BsRect3.h"
 
 namespace BansheeEngine
 {
@@ -237,6 +238,24 @@ namespace BansheeEngine
 		void solidCone(const Vector3& base, const Vector3& normal, float height, float radius,
 			const MeshDataPtr& meshData, UINT32 vertexOffset, UINT32 indexOffset, UINT32 quality = 10);
 
+		/**
+		 * @brief	Fills the mesh data with vertices representing a quad (2 triangles).
+		 *
+		 * @param	area			Area in which to draw the quad.
+		 * @param	meshData		Mesh data that will be populated.
+		 * @param	vertexOffset	Offset in number of vertices from the start of the buffer to start writing at.
+		 * @param	indexOffset 	Offset in number of indices from the start of the buffer to start writing at.
+		 * 							
+		 * @note	Provided MeshData must have some specific elements at least:
+		 * 			  Vector3 VES_POSITION
+		 *			  Vector3 VES_NORMAL
+		 * 			  32bit index buffer
+		 * 			  Enough space for 4 vertices and 6 indices
+		 *
+		 *			Primitives are output in the form of a triangle list.
+		 */
+		void solidQuad(const Rect3& area, const MeshDataPtr& meshData, UINT32 vertexOffset, UINT32 indexOffset);
+
 		/**
 		 * @copydoc	DrawHelperTemplate::pixelLine
 		 */
@@ -492,6 +511,19 @@ namespace BansheeEngine
 		void solidCone(const Vector3& base, const Vector3& normal, float height, float radius,
 			UINT8* outVertices, UINT8* outNormals, UINT32 vertexOffset, UINT32 vertexStride, UINT32* outIndices, UINT32 indexOffset, UINT32 quality);
 
+		/**
+		 * @brief	Fills the provided buffers with position and index data representing a solid quad.
+		 *
+		 * @param	area			Area covered by the quad.
+		 * @param	outVertices		Output buffer that will store the vertex position data.
+		 * @param	outNormals		Output buffer that will store the vertex normal data.
+		 * @param	vertexOffset	Offset in number of vertices from the start of the buffer to start writing at.
+		 * @param	vertexStride	Size of a single vertex, in bytes. (Same for both position and normal buffer)
+		 * @param	outIndices		Output buffer that will store the index data. Indices are 32bit.
+		 * @param	indexOffset 	Offset in number of indices from the start of the buffer to start writing at.
+		 */
+		void solidQuad(const Rect3& area, UINT8* outVertices, UINT8* outNormals, UINT32 vertexOffset, UINT32 vertexStride, UINT32* outIndices, UINT32 indexOffset);
+
 	private:
 		/**
 		 * @brief	Calculates the center of the provided vertices.

+ 45 - 0
BansheeEngine/Source/BsDrawHelper3D.cpp

@@ -166,6 +166,19 @@ namespace BansheeEngine
 			meshData->getVertexDesc()->getVertexStride(), indexData, indexOffset, quality);
 	}
 
+	void DrawHelper3D::solidQuad(const Rect3& area, const MeshDataPtr& meshData, UINT32 vertexOffset, UINT32 indexOffset)
+	{
+		UINT32* indexData = meshData->getIndices32();
+		UINT8* positionData = meshData->getElementData(VES_POSITION);
+		UINT8* normalData = meshData->getElementData(VES_NORMAL);
+
+		assert((vertexOffset + 4) <= meshData->getNumVertices());
+		assert((indexOffset + 6) <= meshData->getNumIndices());
+
+		solidQuad(area, positionData, normalData, vertexOffset,
+			meshData->getVertexDesc()->getVertexStride(), indexData, indexOffset);
+	}
+
 	void DrawHelper3D::pixelLine(const Vector3& a, const Vector3& b, const MeshDataPtr& meshData, UINT32 vertexOffset, UINT32 indexOffset)
 	{
 		DrawHelperTemplate<Vector3>::pixelLine(a, b, meshData, vertexOffset, indexOffset);
@@ -730,6 +743,38 @@ namespace BansheeEngine
 		}
 	}
 
+	void DrawHelper3D::solidQuad(const Rect3& area, UINT8* outVertices, UINT8* outNormals, UINT32 vertexOffset, UINT32 vertexStride, UINT32* outIndices, UINT32 indexOffset)
+	{
+		outVertices += (vertexOffset * vertexStride);
+
+		Vector3 topLeft = area.getCenter() - area.getAxisHorz() * area.getExtentHorz() + area.getAxisVert() * area.getExtentVertical();
+		Vector3 topRight = area.getCenter() + area.getAxisHorz() * area.getExtentHorz() + area.getAxisVert() * area.getExtentVertical();
+		Vector3 botRight = area.getCenter() + area.getAxisHorz() * area.getExtentHorz() - area.getAxisVert() * area.getExtentVertical();
+		Vector3 botLeft = area.getCenter() - area.getAxisHorz() * area.getExtentHorz() - area.getAxisVert() * area.getExtentVertical();
+
+		outVertices = writeVector3(outVertices, vertexStride, topLeft);
+		outVertices = writeVector3(outVertices, vertexStride, topRight);
+		outVertices = writeVector3(outVertices, vertexStride, botRight);
+		outVertices = writeVector3(outVertices, vertexStride, botLeft);
+
+		Vector3 normal = area.getAxisHorz().cross(area.getAxisVert());
+
+		outNormals += (vertexOffset + vertexStride);
+		outNormals = writeVector3(outNormals, vertexStride, normal);
+		outNormals = writeVector3(outNormals, vertexStride, normal);
+		outNormals = writeVector3(outNormals, vertexStride, normal);
+		outNormals = writeVector3(outNormals, vertexStride, normal);
+
+		outIndices += indexOffset;
+		outIndices[0] = vertexOffset;
+		outIndices[1] = vertexOffset + 1;
+		outIndices[2] = vertexOffset + 2;
+
+		outIndices[3] = vertexOffset;
+		outIndices[4] = vertexOffset + 2;
+		outIndices[5] = vertexOffset + 3;
+	}
+
 	Vector3 DrawHelper3D::calcCenter(UINT8* vertices, UINT32 numVertices, UINT32 vertexStride)
 	{
 		Vector3 center = Vector3::ZERO;

+ 1 - 0
BansheeUtility/Include/BsCapsule.h

@@ -13,6 +13,7 @@ namespace BansheeEngine
 	class BS_UTILITY_EXPORT Capsule
 	{
 	public:
+		Capsule();
 		Capsule(const LineSegment3& segment, float radius);
 
 		/**

+ 1 - 0
BansheeUtility/Include/BsLineSegment3.h

@@ -12,6 +12,7 @@ namespace BansheeEngine
 	class BS_UTILITY_EXPORT LineSegment3
 	{
 	public:
+		LineSegment3();
 		LineSegment3(const Vector3& start, const Vector3& end);
 
 		/**

+ 30 - 1
BansheeUtility/Include/BsRect3.h

@@ -6,11 +6,16 @@
 namespace BansheeEngine
 {
 	/**
-	 * @brief	Represents a rectangle in three dimensional space.
+	 * @brief	Represents a rectangle in three dimensional space. It is represented
+	 *			by two axes that extend from the specified origin. Axes should be perpendicular
+	 *			to each other and they extend in both positive and negative directions from the
+	 *			origin by the amount specified by extents.
 	 */
 	class BS_UTILITY_EXPORT Rect3
 	{
 	public:
+		Rect3();
+
 		Rect3(const Vector3& center, const std::array<Vector3, 2>& axes,
 			const std::array<float, 2>& extents);
 
@@ -38,6 +43,30 @@ namespace BansheeEngine
 		 */
 		std::pair<bool, float> intersects(const Ray& ray) const;
 
+		/**
+		 * @brief	Gets the origin of the rectangle. 
+		 */
+		const Vector3& getCenter() const { return mCenter; }
+
+		/**
+		 * @brief	Returns the rectangles horizontal axis.
+		 */
+		const Vector3& getAxisHorz() const { return mAxes[0]; }
+
+		/**
+		 * @brief	Returns the rectangles vertical axis.
+		 */
+		const Vector3& getAxisVert() const { return mAxes[1]; }
+
+		/**
+		 * @brief	Gets the extent of the rectangle along its horizontal axis.
+		 */
+		const float& getExtentHorz() const { return mExtents[0]; }
+
+		/**
+		 * @brief	Gets the extent of the rectangle along its vertical axis.
+		 */
+		const float& getExtentVertical() const { return mExtents[1]; }
 	private:
 		Vector3 mCenter;
 		std::array<Vector3, 2> mAxes;

+ 1 - 0
BansheeUtility/Include/BsTorus.h

@@ -13,6 +13,7 @@ namespace BansheeEngine
 	class BS_UTILITY_EXPORT Torus
 	{
 	public:
+		Torus();
 		Torus(float outerRadius, float innerRadius);
 
 		/**

+ 4 - 0
BansheeUtility/Source/BsCapsule.cpp

@@ -3,6 +3,10 @@
 
 namespace BansheeEngine
 {
+	Capsule::Capsule()
+		:mRadius(0.0f)
+	{ }
+
 	Capsule::Capsule(const LineSegment3& segment, float radius)
 		:mSegment(segment), mRadius(radius)
 	{ }

+ 3 - 0
BansheeUtility/Source/BsLineSegment3.cpp

@@ -3,6 +3,9 @@
 
 namespace BansheeEngine
 {
+	LineSegment3::LineSegment3()
+	{ }
+
 	LineSegment3::LineSegment3(const Vector3& start, const Vector3& end)
 		:mStart(start), mEnd(end)
 	{ 

+ 3 - 0
BansheeUtility/Source/BsRect3.cpp

@@ -4,6 +4,9 @@
 
 namespace BansheeEngine
 {
+	Rect3::Rect3()
+	{ }
+
 	Rect3::Rect3(const Vector3& center, const std::array<Vector3, 2>& axes,
 		const std::array<float, 2>& extents)
 		:mCenter(center), mAxes(axes), mExtents(extents)

+ 4 - 0
BansheeUtility/Source/BsTorus.cpp

@@ -4,6 +4,10 @@
 
 namespace BansheeEngine
 {
+	Torus::Torus()
+		:outerRadius(0.0f), innerRadius(0.0f)
+	{ }
+
 	Torus::Torus(float outerRadius, float innerRadius)
 		:outerRadius(outerRadius), innerRadius(innerRadius)
 	{ }

+ 93 - 6
SceneView.txt

@@ -47,15 +47,31 @@ SliderDisc - position, normal, radius
 
 Handles are always the same size regardless of the distance from camera. (Use same code as from gizmo rendering?)
 These three types can be used for creating MoveHandle, RotationHandle, ScaleHandle
-  - I can potentially move the colliders out of the sliders and add them to the *Handle classes as well
-  - Handle classes will also handle the rendering (using the existing DrawHelper methods)
+
+In C# user can call Handles class for managing handles
+ - It will allow you to draw various handle shapes, similar to gizmo drawing (unify that code? - probably not initially)
+   - e.g. DrawCone, DrawSphere, DrawWireDisc, etc.
+ - Including more complex ones like DrawArrow and similar
+ - Using the same class user can also set up Sliders which don't have a visible representation
+ - AND finally user can also set up combined premade handles like FreeMove which sets up all sliders and draw methods needed automatically
+
+SliderLine, SliderPlane, SliderDisc will all be separate classes in C# and C++
+ - They need to have a matrix and color property you can modify on the go 
+ - As well a specific properties like length/size/radius (possibly others)
+ - Since all of the above are just normal classes C++ can follow the same approach for default handles and custom user ones
+
+Certain classes are marked with [Handle] attribute. The attribute also accepts a type the handle is to be used on.
+Each such class must implement IHandle interface which requires you to implement an Update method
+ - Update method receives the instance of the object currently being processed
+ - Then you may call handle specific methods like "position = mySliderLine.Update(object.currentPosition)"
+ - Drawing - Immediate mode in the Update method. You call Handle.DrawArrow, etc.
+   - Complex handles like FreeMoveHandle are also their own class, but  they have their own Update in which they call immediate mode drawing
+ - TODO: Since this entire class essentially boils down to a single method it might be worth making handle sliders immediate mode as well
+   - ACTUALLY looking at Unity code I definitely don't want to do that. It's too clumsy and impossible to guarantee selection if the order of handles changes
 
 CONCRETE TASKS:
- - Need to add capsule, torus and OOB colliders
-    - They need ray intersection code
- - Line, plane and disc need code for finding nearest point to a ray
+ - Need nearest point to disc/arc code
 
-Think about C# implementation.
 Take into consideration local vs. global handles
 Free move/rotate/scale handles need to exist as well
  - Scale is easy, just perform uniform scale. Use SliderPlane oriented towards camera
@@ -64,6 +80,77 @@ Free move/rotate/scale handles need to exist as well
 
 See for inspiration: http://docs.unity3d.com/ScriptReference/Handles.html
 
+EXAMPLE:
+
+[CustomHandle(typeof(Camera))]
+class CameraHandle : IHandle
+{
+     SliderLine xAxis;
+     SliderLine yAxis;
+     
+     CameraHandle()
+     {
+         xAxis = new SliderLine(Vector3.right, 10.0f);
+         yAxis = new SliderLine(Vector3.up, 10.0f);
+
+         xAxis.onDragged += onXAxis();
+         yAxis.onDragged += onYAxis();
+     }
+
+     void onXAxis()
+     {
+          // Here I can decide whether or not I want to use handle data or not, per object instance
+          target.position = xAxis.getMove(target.position);
+     }
+
+     void onYAxis()
+     {
+          target.position = yAxis.getMove(target.position);
+     }
+
+     void Update()
+     {
+           // Resize handle, change matrix, etc.
+     }
+
+     void Draw()
+     {
+           xAxis.Draw();
+
+           HandleDraw.Arrow(target.position, Vector3.right, 10.0f);
+           HandleDraw.Arrow(target.position, Vector3.up, 10.0f);
+     }
+}
+
+
+------------
+
+What if I want a different handle per-object (e.g. object has some flag that makes different handles render)
+ - SOLVED
+
+How I can easily access the current target object
+ - Manually implement a generic getter?
+
+How will I implement this in C++ and use for default handles?
+ - I'm still using classes in C# and C++ can use equivalents. Handle manager can do a special pass to draw default handles before calling the custom handle code.
+
+Do I want to unify gizmo and handle drawing?
+ - Not at the moment. Too much to think about, I can always refactor and it will be easier.
+
+Handles can be mouse overed and selected. How will I handle that if I just use normal drawing methods???
+ - This can be set in HandleSlider class itself with "isHovering", "isActive". And then its draw method can change appearance appropriately.
+
+Do I handle handle transforms via a matrix that is automatically set by the handle manager, or manually like unity does? 
+  - I shouldn't allow non-uniform scale.
+  - In both cases I need to set handle transform in its Update() method
+  - ALLOW custom matrix (or just custom offset and rotation?) but have handle manager set it normally
+    - custom matrix sounds better for easier control?
+
+How do I handle when an object with a custom handle is deleted?
+ - How do I detect that and remove the handle.
+   - I SHOULDN'T HAVE TO
+ - I should probably just instantiate he IHandle implementation class once object is selected, and destroy it after
+
 ----------------------------------------------------------------------
 SelectionRenderer