Browse Source

Fixed lag between material updates when rendering GUI
WIP implementations of rotate and scale handles
Various fixes to disc sliders and torus intersection code as well as equation solvers
Made arc/disc rendering double sided
Fixed to C# GUIToggle so ToggleOn and ToggleOff methods work

Marko Pintera 11 years ago
parent
commit
f33b14ebe1
40 changed files with 866 additions and 383 deletions
  1. 3 0
      BansheeCore/Include/BsMaterial.h
  2. 0 3
      BansheeCore/Source/BsCoreApplication.cpp
  3. 6 6
      BansheeD3D9RenderSystem/BansheeD3D9RenderSystem.vcxproj
  4. 12 6
      BansheeEditor/Include/BsEditorSettings.h
  5. 2 1
      BansheeEditor/Include/BsHandleSlider.h
  6. 4 4
      BansheeEditor/Include/BsHandleSliderDisc.h
  7. 3 0
      BansheeEditor/Source/BsBuiltinEditorResources.cpp
  8. 1 0
      BansheeEditor/Source/BsEditorApplication.cpp
  9. 3 3
      BansheeEditor/Source/BsEditorSettings.cpp
  10. 30 38
      BansheeEditor/Source/BsHandleSliderDisc.cpp
  11. 4 4
      BansheeEngine/Include/BsShapeMeshes3D.h
  12. 25 7
      BansheeEngine/Source/BsShapeMeshes3D.cpp
  13. 1 1
      BansheeGLRenderSystem/Source/BsGLRenderAPI.cpp
  14. 4 0
      BansheeRenderer/Source/BsBansheeRenderer.cpp
  15. 121 142
      BansheeUtility/Include/BsMath.h
  16. 2 1
      BansheeUtility/Include/BsTorus.h
  17. 0 3
      BansheeUtility/Source/BsAABox.cpp
  18. 16 14
      BansheeUtility/Source/BsTorus.cpp
  19. 8 8
      MBansheeEditor/DbgGizmo.cs
  20. 3 3
      MBansheeEditor/DebugCameraHandle.cs
  21. 9 13
      MBansheeEditor/EditorApplication.cs
  22. 43 24
      MBansheeEditor/EditorSettings.cs
  23. 14 12
      MBansheeEditor/Scene/DefaultHandleManager.cs
  24. 15 2
      MBansheeEditor/Scene/HandleSliderDisc.cs
  25. 8 15
      MBansheeEditor/Scene/Handles.cs
  26. 132 3
      MBansheeEditor/Scene/RotateHandle.cs
  27. 92 3
      MBansheeEditor/Scene/ScaleHandle.cs
  28. 5 5
      MBansheeEditor/Scene/SceneCamera.cs
  29. 159 6
      MBansheeEditor/Scene/SceneWindow.cs
  30. 4 4
      MBansheeEngine/GUI/GUIToggle.cs
  31. 8 0
      MBansheeEngine/Math/Matrix4.cs
  32. 31 0
      MBansheeEngine/Math/Vector3.cs
  33. 5 0
      MBansheeEngine/Math/Vector4.cs
  34. 12 12
      MBansheeEngine/SceneObject.cs
  35. 7 4
      SBansheeEditor/Include/BsScriptEditorSettings.h
  36. 1 0
      SBansheeEditor/Include/BsScriptHandleSliderDisc.h
  37. 45 24
      SBansheeEditor/Source/BsScriptEditorSettings.cpp
  38. 7 1
      SBansheeEditor/Source/BsScriptHandleSliderDisc.cpp
  39. 8 4
      SBansheeEngine/Source/BsScriptGUIToggle.cpp
  40. 13 7
      TODO.txt

+ 3 - 0
BansheeCore/Include/BsMaterial.h

@@ -139,6 +139,9 @@ namespace BansheeEngine
 		Map<String, String> mValidParams; // Also maps Shader param name -> gpu variable name
 		Map<String, String> mValidParams; // Also maps Shader param name -> gpu variable name
 	};
 	};
 
 
+	/**
+	 * @copydoc	MaterialBase
+	 */
 	template<bool Core>
 	template<bool Core>
 	class BS_CORE_EXPORT TMaterial : public MaterialBase
 	class BS_CORE_EXPORT TMaterial : public MaterialBase
 	{
 	{

+ 0 - 3
BansheeCore/Source/BsCoreApplication.cpp

@@ -195,9 +195,6 @@ namespace BansheeEngine
 			// Send out resource events in case any were loaded/destroyed/modified
 			// Send out resource events in case any were loaded/destroyed/modified
 			ResourceListenerManager::instance().update();
 			ResourceListenerManager::instance().update();
 
 
-			// Sync all dirty sim thread CoreObject data to core thread
-			CoreObjectManager::instance().syncToCore(gCoreAccessor());
-
 			PROFILE_CALL(RendererManager::instance().getActive()->renderAll(), "Render");
 			PROFILE_CALL(RendererManager::instance().getActive()->renderAll(), "Render");
 
 
 			// Core and sim thread run in lockstep. This will result in a larger input latency than if I was 
 			// Core and sim thread run in lockstep. This will result in a larger input latency than if I was 

+ 6 - 6
BansheeD3D9RenderSystem/BansheeD3D9RenderSystem.vcxproj

@@ -122,7 +122,7 @@
     <ClCompile>
     <ClCompile>
       <WarningLevel>Level3</WarningLevel>
       <WarningLevel>Level3</WarningLevel>
       <Optimization>Disabled</Optimization>
       <Optimization>Disabled</Optimization>
-      <AdditionalIncludeDirectories>C:\Program Files %28x86%29\Microsoft DirectX SDK %28June 2010%29\Include;.\Include;..\BansheeCore\Include;..\BansheeUtility\Include;..\Dependencies\Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>$(DXSDK_DIR)Include;.\Include;..\BansheeCore\Include;..\BansheeUtility\Include;..\Dependencies\Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>BS_RSD3D9_EXPORTS;_WINDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <PreprocessorDefinitions>BS_RSD3D9_EXPORTS;_WINDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
       <AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
       <InlineFunctionExpansion>Default</InlineFunctionExpansion>
       <InlineFunctionExpansion>Default</InlineFunctionExpansion>
@@ -138,7 +138,7 @@
     <ClCompile>
     <ClCompile>
       <WarningLevel>Level3</WarningLevel>
       <WarningLevel>Level3</WarningLevel>
       <Optimization>Disabled</Optimization>
       <Optimization>Disabled</Optimization>
-      <AdditionalIncludeDirectories>C:\Program Files %28x86%29\Microsoft DirectX SDK %28June 2010%29\Include;.\Include;..\BansheeCore\Include;..\BansheeUtility\Include;..\Dependencies\Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>$(DXSDK_DIR)Include;.\Include;..\BansheeCore\Include;..\BansheeUtility\Include;..\Dependencies\Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>BS_RSD3D9_EXPORTS;_WINDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <PreprocessorDefinitions>BS_RSD3D9_EXPORTS;_WINDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
       <AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
       <InlineFunctionExpansion>Default</InlineFunctionExpansion>
       <InlineFunctionExpansion>Default</InlineFunctionExpansion>
@@ -156,7 +156,7 @@
       <Optimization>MaxSpeed</Optimization>
       <Optimization>MaxSpeed</Optimization>
       <FunctionLevelLinking>true</FunctionLevelLinking>
       <FunctionLevelLinking>true</FunctionLevelLinking>
       <IntrinsicFunctions>true</IntrinsicFunctions>
       <IntrinsicFunctions>true</IntrinsicFunctions>
-      <AdditionalIncludeDirectories>C:\Program Files %28x86%29\Microsoft DirectX SDK %28June 2010%29\Include;.\Include;..\BansheeCore\Include;..\BansheeUtility\Include;..\Dependencies\Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>$(DXSDK_DIR)Include;.\Include;..\BansheeCore\Include;..\BansheeUtility\Include;..\Dependencies\Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>BS_RSD3D9_EXPORTS;_WINDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <PreprocessorDefinitions>BS_RSD3D9_EXPORTS;_WINDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
       <AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
       <BufferSecurityCheck>false</BufferSecurityCheck>
       <BufferSecurityCheck>false</BufferSecurityCheck>
@@ -178,7 +178,7 @@
       <Optimization>MaxSpeed</Optimization>
       <Optimization>MaxSpeed</Optimization>
       <FunctionLevelLinking>true</FunctionLevelLinking>
       <FunctionLevelLinking>true</FunctionLevelLinking>
       <IntrinsicFunctions>true</IntrinsicFunctions>
       <IntrinsicFunctions>true</IntrinsicFunctions>
-      <AdditionalIncludeDirectories>C:\Program Files %28x86%29\Microsoft DirectX SDK %28June 2010%29\Include;.\Include;..\BansheeCore\Include;..\BansheeUtility\Include;..\Dependencies\Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>$(DXSDK_DIR)Include;.\Include;..\BansheeCore\Include;..\BansheeUtility\Include;..\Dependencies\Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>BS_RSD3D9_EXPORTS;_WINDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <PreprocessorDefinitions>BS_RSD3D9_EXPORTS;_WINDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
       <AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
       <BufferSecurityCheck>false</BufferSecurityCheck>
       <BufferSecurityCheck>false</BufferSecurityCheck>
@@ -200,7 +200,7 @@
       <Optimization>MaxSpeed</Optimization>
       <Optimization>MaxSpeed</Optimization>
       <FunctionLevelLinking>true</FunctionLevelLinking>
       <FunctionLevelLinking>true</FunctionLevelLinking>
       <IntrinsicFunctions>true</IntrinsicFunctions>
       <IntrinsicFunctions>true</IntrinsicFunctions>
-      <AdditionalIncludeDirectories>C:\Program Files %28x86%29\Microsoft DirectX SDK %28June 2010%29\Include;.\Include;..\BansheeCore\Include;..\BansheeUtility\Include;..\Dependencies\Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>$(DXSDK_DIR)Include;.\Include;..\BansheeCore\Include;..\BansheeUtility\Include;..\Dependencies\Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>BS_RSD3D9_EXPORTS;_WINDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <PreprocessorDefinitions>BS_RSD3D9_EXPORTS;_WINDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
       <AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
       <BufferSecurityCheck>false</BufferSecurityCheck>
       <BufferSecurityCheck>false</BufferSecurityCheck>
@@ -222,7 +222,7 @@
       <Optimization>MaxSpeed</Optimization>
       <Optimization>MaxSpeed</Optimization>
       <FunctionLevelLinking>true</FunctionLevelLinking>
       <FunctionLevelLinking>true</FunctionLevelLinking>
       <IntrinsicFunctions>true</IntrinsicFunctions>
       <IntrinsicFunctions>true</IntrinsicFunctions>
-      <AdditionalIncludeDirectories>C:\Program Files %28x86%29\Microsoft DirectX SDK %28June 2010%29\Include;.\Include;..\BansheeCore\Include;..\BansheeUtility\Include;..\Dependencies\Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>$(DXSDK_DIR)Include;.\Include;..\BansheeCore\Include;..\BansheeUtility\Include;..\Dependencies\Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>BS_RSD3D9_EXPORTS;_WINDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <PreprocessorDefinitions>BS_RSD3D9_EXPORTS;_WINDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
       <AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
       <BufferSecurityCheck>false</BufferSecurityCheck>
       <BufferSecurityCheck>false</BufferSecurityCheck>

+ 12 - 6
BansheeEditor/Include/BsEditorSettings.h

@@ -12,11 +12,9 @@ namespace BansheeEngine
 
 
 		bool getMoveHandleSnapActive() const { return mMoveSnapActive; }
 		bool getMoveHandleSnapActive() const { return mMoveSnapActive; }
 		bool getRotateHandleSnapActive() const { return mRotateSnapActive; }
 		bool getRotateHandleSnapActive() const { return mRotateSnapActive; }
-		bool getScaleHandleSnapActive() const { return mScaleSnapActive; }
 
 
 		float getMoveHandleSnap() const { return mMoveSnap; }
 		float getMoveHandleSnap() const { return mMoveSnap; }
 		Degree getRotationHandleSnap() const { return mRotationSnap; }
 		Degree getRotationHandleSnap() const { return mRotationSnap; }
-		float getScaleHandleSnap() const { return mScaleSnap; }
 
 
 		UINT32 getGridSize() const { return mGridSize; }
 		UINT32 getGridSize() const { return mGridSize; }
 		float getGridSpacing() const { return mGridAxisSpacing; }
 		float getGridSpacing() const { return mGridAxisSpacing; }
@@ -25,13 +23,15 @@ namespace BansheeEngine
 
 
 		float getHandleSize() const { return mHandleSize; }
 		float getHandleSize() const { return mHandleSize; }
 
 
+		UINT32 getActiveSceneTool() const { return mActiveSceneTool; }
+		UINT32 getActiveCoordinateMode() const { return mActiveCoordinateMode; }
+		UINT32 getActivePivotMode() const { return mActivePivotMode; }
+
 		void setMoveHandleSnapActive(bool snapActive) { mMoveSnapActive = snapActive; markAsDirty(); }
 		void setMoveHandleSnapActive(bool snapActive) { mMoveSnapActive = snapActive; markAsDirty(); }
 		void setRotateHandleSnapActive(bool snapActive) { mRotateSnapActive = snapActive; markAsDirty(); }
 		void setRotateHandleSnapActive(bool snapActive) { mRotateSnapActive = snapActive; markAsDirty(); }
-		void setScaleHandleSnapActive(bool snapActive) { mScaleSnapActive = snapActive; markAsDirty(); }
 
 
 		void setMoveHandleSnap(float value) { mMoveSnap = value; markAsDirty(); }
 		void setMoveHandleSnap(float value) { mMoveSnap = value; markAsDirty(); }
 		void setRotationHandleSnap(Degree value) { mRotationSnap = value; markAsDirty(); }
 		void setRotationHandleSnap(Degree value) { mRotationSnap = value; markAsDirty(); }
-		void setScaleHandleSnap(float value) { mScaleSnap = value; markAsDirty(); }
 
 
 		void setGridSize(UINT32 value) { mGridSize = value; markAsDirty(); }
 		void setGridSize(UINT32 value) { mGridSize = value; markAsDirty(); }
 		void setGridSpacing(float value) { mGridAxisSpacing = value; markAsDirty(); }
 		void setGridSpacing(float value) { mGridAxisSpacing = value; markAsDirty(); }
@@ -40,6 +40,10 @@ namespace BansheeEngine
 
 
 		void setHandleSize(float value) { mHandleSize = value; markAsDirty(); }
 		void setHandleSize(float value) { mHandleSize = value; markAsDirty(); }
 
 
+		void setActiveSceneTool(UINT32 value) { mActiveSceneTool = value; markAsDirty(); }
+		void setActiveCoordinateMode(UINT32 value) { mActiveCoordinateMode = value; markAsDirty(); }
+		void setActivePivotMode(UINT32 value) { mActivePivotMode = value; markAsDirty(); }
+
 		UINT32 getHash() const { return mHash; }
 		UINT32 getHash() const { return mHash; }
 
 
 	private:
 	private:
@@ -47,17 +51,19 @@ namespace BansheeEngine
 
 
 		bool mMoveSnapActive;
 		bool mMoveSnapActive;
 		bool mRotateSnapActive;
 		bool mRotateSnapActive;
-		bool mScaleSnapActive;
 
 
 		float mMoveSnap;
 		float mMoveSnap;
 		Degree mRotationSnap;
 		Degree mRotationSnap;
-		float mScaleSnap;
 
 
 		UINT32 mGridSize;
 		UINT32 mGridSize;
 		float mGridAxisSpacing;
 		float mGridAxisSpacing;
 		UINT32 mGridMajorAxisSpacing;
 		UINT32 mGridMajorAxisSpacing;
 		UINT32 mGridAxisMarkerSpacing;
 		UINT32 mGridAxisMarkerSpacing;
 
 
+		UINT32 mActiveSceneTool;
+		UINT32 mActiveCoordinateMode;
+		UINT32 mActivePivotMode;
+
 		float mHandleSize;
 		float mHandleSize;
 
 
 		mutable UINT32 mHash;
 		mutable UINT32 mHash;

+ 2 - 1
BansheeEditor/Include/BsHandleSlider.h

@@ -47,7 +47,8 @@ namespace BansheeEngine
 
 
 		virtual void activate(const CameraHandlerPtr& camera, const Vector2I& pointerPos) { }
 		virtual void activate(const CameraHandlerPtr& camera, const Vector2I& pointerPos) { }
 		virtual void reset() { }
 		virtual void reset() { }
-		virtual void updateCachedTransform() const;
+
+		void updateCachedTransform() const;
 
 
 		float calcDelta(const CameraHandlerPtr& camera, const Vector3& position, const Vector3& direction,
 		float calcDelta(const CameraHandlerPtr& camera, const Vector3& position, const Vector3& direction,
 			const Vector2I& pointerStart, const Vector2I& pointerEnd);
 			const Vector2I& pointerStart, const Vector2I& pointerEnd);

+ 4 - 4
BansheeEditor/Include/BsHandleSliderDisc.h

@@ -15,12 +15,12 @@ namespace BansheeEngine
 		bool intersects(const Ray& ray, float& t) const;
 		bool intersects(const Ray& ray, float& t) const;
 		void handleInput(const CameraHandlerPtr& camera, const Vector2I& inputDelta);
 		void handleInput(const CameraHandlerPtr& camera, const Vector2I& inputDelta);
 
 
-		float getDelta() const { return mDelta; }
+		Radian getDelta() const { return mDelta; }
+		Radian getStartAngle() const { return mStartAngle; }
 
 
 	protected:
 	protected:
 		void activate(const CameraHandlerPtr& camera, const Vector2I& pointerPos);
 		void activate(const CameraHandlerPtr& camera, const Vector2I& pointerPos);
 		void reset() { mDelta = 0.0f; }
 		void reset() { mDelta = 0.0f; }
-		virtual void updateCachedTransform() const;
 
 
 		Vector3 calculateClosestPointOnArc(const Ray& inputRay, const Vector3& center, const Vector3& up,
 		Vector3 calculateClosestPointOnArc(const Ray& inputRay, const Vector3& center, const Vector3& up,
 			float radius, Degree startAngle, Degree angleAmount);
 			float radius, Degree startAngle, Degree angleAmount);
@@ -31,11 +31,11 @@ namespace BansheeEngine
 
 
 		Vector3 mNormal;
 		Vector3 mNormal;
 		float mRadius;
 		float mRadius;
-		Matrix4 mTorusRotation;
 
 
 		Vector3 mDirection;
 		Vector3 mDirection;
 		Vector3 mStartPosition;
 		Vector3 mStartPosition;
-		float mDelta;
+		Degree mStartAngle;
+		Degree mDelta;
 
 
 		Torus mCollider;
 		Torus mCollider;
 	};
 	};

+ 3 - 0
BansheeEditor/Source/BsBuiltinEditorResources.cpp

@@ -280,6 +280,9 @@ namespace BansheeEngine
 		buttonStyle.normal.texture = getGUITexture(ButtonNormalTex);
 		buttonStyle.normal.texture = getGUITexture(ButtonNormalTex);
 		buttonStyle.hover.texture = getGUITexture(ButtonHoverTex);
 		buttonStyle.hover.texture = getGUITexture(ButtonHoverTex);
 		buttonStyle.active.texture = getGUITexture(ButtonActiveTex);
 		buttonStyle.active.texture = getGUITexture(ButtonActiveTex);
+		buttonStyle.normalOn.texture = getGUITexture(ButtonActiveTex);
+		buttonStyle.hoverOn.texture = getGUITexture(ButtonActiveTex);
+		buttonStyle.activeOn.texture = getGUITexture(ButtonActiveTex);
 		buttonStyle.border.left = 6;
 		buttonStyle.border.left = 6;
 		buttonStyle.border.right = 6;
 		buttonStyle.border.right = 6;
 		buttonStyle.border.top = 6;
 		buttonStyle.border.top = 6;

+ 1 - 0
BansheeEditor/Source/BsEditorApplication.cpp

@@ -41,6 +41,7 @@
 #include "BsCoreRenderer.h"
 #include "BsCoreRenderer.h"
 #include "BsEditorSettings.h"
 #include "BsEditorSettings.h"
 #include "BsMesh.h"
 #include "BsMesh.h"
+#include "BsMath.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {

+ 3 - 3
BansheeEditor/Source/BsEditorSettings.cpp

@@ -3,8 +3,8 @@
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
 	EditorSettings::EditorSettings()
 	EditorSettings::EditorSettings()
-		:mMoveSnapActive(false), mRotateSnapActive(false), mScaleSnapActive(false), mMoveSnap(0.1f),
-		mRotationSnap(20.0f), mScaleSnap(0.1f), mGridSize(256), mGridAxisSpacing(1.0f), mGridMajorAxisSpacing(10),
-		mGridAxisMarkerSpacing(25), mHandleSize(0.15f), mHash(0)
+		:mMoveSnapActive(false), mRotateSnapActive(false), mMoveSnap(0.1f), mRotationSnap(20.0f), 
+		mGridSize(256), mGridAxisSpacing(1.0f), mGridMajorAxisSpacing(10), mGridAxisMarkerSpacing(25), 
+		mHandleSize(0.15f), mHash(0), mActiveSceneTool(0), mActiveCoordinateMode(0), mActivePivotMode(0)
 	{ }
 	{ }
 }
 }

+ 30 - 38
BansheeEditor/Source/BsHandleSliderDisc.cpp

@@ -6,19 +6,17 @@
 #include "BsQuaternion.h"
 #include "BsQuaternion.h"
 #include "BsCamera.h"
 #include "BsCamera.h"
 
 
+// DEBUG ONLY
+#include "BsDebug.h"
+
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
-	const float HandleSliderDisc::TORUS_RADIUS = 0.5f;
+	const float HandleSliderDisc::TORUS_RADIUS = 0.1f;
 
 
 	HandleSliderDisc::HandleSliderDisc(const Vector3& normal, float radius, bool fixedScale)
 	HandleSliderDisc::HandleSliderDisc(const Vector3& normal, float radius, bool fixedScale)
-		:HandleSlider(fixedScale), mRadius(radius), mDelta(0.0f)
+		:HandleSlider(fixedScale), mRadius(radius), mNormal(normal), mDelta(0.0f)
 	{
 	{
-		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
-
-		mCollider = Torus(radius, TORUS_RADIUS);
+		mCollider = Torus(normal, radius, TORUS_RADIUS);
 
 
 		HandleSliderManager& sliderManager = HandleManager::instance().getSliderManager();
 		HandleSliderManager& sliderManager = HandleManager::instance().getSliderManager();
 		sliderManager._registerSlider(this);
 		sliderManager._registerSlider(this);
@@ -30,18 +28,6 @@ namespace BansheeEngine
 		sliderManager._unregisterSlider(this);
 		sliderManager._unregisterSlider(this);
 	}
 	}
 
 
-	void HandleSliderDisc::updateCachedTransform() const
-	{
-		if (mFixedScale)
-			mTransform.setTRS(mPosition, mRotation, mScale * mDistanceScale);
-		else
-			mTransform.setTRS(mPosition, mRotation, mScale);
-
-		mTransform = mTransform * mTorusRotation;
-		mTransformInv = mTransform.inverseAffine();
-		mTransformDirty = false;
-	}
-
 	bool HandleSliderDisc::intersects(const Ray& ray, float& t) const
 	bool HandleSliderDisc::intersects(const Ray& ray, float& t) const
 	{
 	{
 		Ray localRay = ray;
 		Ray localRay = ray;
@@ -79,8 +65,8 @@ namespace BansheeEngine
 		auto intersectResult = plane.intersects(inputRay);
 		auto intersectResult = plane.intersects(inputRay);
 
 
 		float t = 0.0f;
 		float t = 0.0f;
-		if (intersectResult.second)
-			pointOnPlane = inputRay.getPoint(intersectResult.first);
+		if (intersectResult.first)
+			pointOnPlane = inputRay.getPoint(intersectResult.second);
 		else
 		else
 			pointOnPlane = Vector3::ZERO;
 			pointOnPlane = Vector3::ZERO;
 
 
@@ -97,23 +83,33 @@ namespace BansheeEngine
 		Radian angle = Math::atan2(-closestPoint2D.y, -closestPoint2D.x) + Math::PI;
 		Radian angle = Math::atan2(-closestPoint2D.y, -closestPoint2D.x) + Math::PI;
 
 
 		float angleRad = angle.valueRadians();
 		float angleRad = angle.valueRadians();
+		float angleAmountRad = Math::clamp(angleAmount.valueRadians(), 0.0f, Math::PI * 2);
+
 		float startAngleRad = startAngle.wrap().valueRadians();
 		float startAngleRad = startAngle.wrap().valueRadians();
-		float endAngleRad = (startAngle + angleAmount).wrap().valueRadians();
+		float endAngleRad = startAngleRad + angleAmountRad;
 
 
-		float clampedAngle;
-		if (startAngleRad <= endAngleRad)
+		float clampedAngle = angleRad;
+		if (endAngleRad <= Math::PI * 2)
+		{
 			clampedAngle = Math::clamp(angleRad, startAngleRad, endAngleRad);
 			clampedAngle = Math::clamp(angleRad, startAngleRad, endAngleRad);
+		}
 		else
 		else
 		{
 		{
-			if ((angleRad < startAngleRad) && (angleRad > endAngleRad))
+			if (angleRad >= startAngleRad)
+				clampedAngle = Math::clamp(angleRad, startAngleRad, Math::PI * 2);
+			else
 			{
 			{
-				if ((startAngleRad - angleRad) > (angleRad - endAngleRad))
-					clampedAngle = endAngleRad;
+				endAngleRad -= Math::PI * 2;
+				if (angleRad > endAngleRad)
+				{
+					if ((startAngleRad - angleRad) > (angleRad - endAngleRad))
+						clampedAngle = endAngleRad;
+					else
+						clampedAngle = startAngleRad;
+				}
 				else
 				else
-					clampedAngle = startAngleRad;
+					clampedAngle = angleRad;
 			}
 			}
-			else
-				clampedAngle = angleRad;
 		}
 		}
 
 
 		Vector3 clampedAnglePoint;
 		Vector3 clampedAnglePoint;
@@ -144,12 +140,8 @@ namespace BansheeEngine
 		Ray localRay = camera->screenPointToRay(pointerPos);
 		Ray localRay = camera->screenPointToRay(pointerPos);
 		localRay.transformAffine(getTransformInv());
 		localRay.transformAffine(getTransformInv());
 
 
-		Quaternion camLocalRotation = camera->getRotation() * getRotation().inverse();
-
-		Vector3 startDir = camLocalRotation.zAxis().cross(mNormal);
-		Degree startAngle = pointOnCircleToAngle(mNormal, startDir);
-
-		mStartPosition = calculateClosestPointOnArc(localRay, Vector3::ZERO, mNormal, mRadius, startAngle, Degree(180.0f));
+		mStartPosition = calculateClosestPointOnArc(localRay, Vector3::ZERO, mNormal, mRadius, Degree(0.0f), Degree(360.0f));
+		mStartAngle = pointOnCircleToAngle(mNormal, mStartPosition);
 		mStartPosition = getTransform().multiplyAffine(mStartPosition);
 		mStartPosition = getTransform().multiplyAffine(mStartPosition);
 
 
 		mDirection = mNormal.cross(mStartPosition - getPosition());
 		mDirection = mNormal.cross(mStartPosition - getPosition());
@@ -161,6 +153,6 @@ namespace BansheeEngine
 		assert(getState() == State::Active);
 		assert(getState() == State::Active);
 
 
 		mCurrentPointerPos += inputDelta;
 		mCurrentPointerPos += inputDelta;
-		mDelta = calcDelta(camera, mStartPosition, mDirection, mStartPointerPos, mCurrentPointerPos);
+		mDelta = calcDelta(camera, mStartPosition, mDirection, mStartPointerPos, mCurrentPointerPos) * Math::RAD2DEG;
 	}
 	}
 }
 }

+ 4 - 4
BansheeEngine/Include/BsShapeMeshes3D.h

@@ -132,8 +132,8 @@ namespace BansheeEngine
 		 * 			  Vector3 VES_POSITION
 		 * 			  Vector3 VES_POSITION
 		 *			  Vector3 VES_NORMAL
 		 *			  Vector3 VES_NORMAL
 		 * 			  32bit index buffer
 		 * 			  32bit index buffer
-		 * 			  Enough space for ((quality + 1) * 5 + 1) vertices 
-		 *			  Enough space for (((quality + 1) * 5 - 1) * 3) indices
+		 * 			  Enough space for ((quality + 1) * 5 + 1) * 2 vertices 
+		 *			  Enough space for (((quality + 1) * 5 - 1) * 6) indices
 		 *
 		 *
 		 *			Primitives are output in the form of a triangle list.
 		 *			Primitives are output in the form of a triangle list.
 		 */
 		 */
@@ -179,8 +179,8 @@ namespace BansheeEngine
 		 * 			  Vector3 VES_POSITION
 		 * 			  Vector3 VES_POSITION
 		 *			  Vector3 VES_NORMAL
 		 *			  Vector3 VES_NORMAL
 		 * 			  32bit index buffer
 		 * 			  32bit index buffer
-		 * 			  Enough space for ((quality + 1) * 5 + 1) vertices 
-		 *			  Enough space for (((quality + 1) * 5 - 1) * 3) indices
+		 * 			  Enough space for ((quality + 1) * 5 + 1) * 2 vertices 
+		 *			  Enough space for (((quality + 1) * 5 - 1) * 6) indices
 		 *
 		 *
 		 *			Primitives are output in the form of a triangle list.
 		 *			Primitives are output in the form of a triangle list.
 		 */
 		 */

+ 25 - 7
BansheeEngine/Source/BsShapeMeshes3D.cpp

@@ -14,6 +14,9 @@
 #include "BsBuiltinResources.h"
 #include "BsBuiltinResources.h"
 #include "BsVertexDataDesc.h"
 #include "BsVertexDataDesc.h"
 
 
+// DEBUG ONLY
+#include "BsDebug.h"
+
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
 	const UINT32 ShapeMeshes3D::NUM_VERTICES_AA_LINE = 8;
 	const UINT32 ShapeMeshes3D::NUM_VERTICES_AA_LINE = 8;
@@ -266,8 +269,8 @@ namespace BansheeEngine
 
 
 	void ShapeMeshes3D::getNumElementsArc(UINT32 quality, UINT32& numVertices, UINT32& numIndices)
 	void ShapeMeshes3D::getNumElementsArc(UINT32 quality, UINT32& numVertices, UINT32& numIndices)
 	{
 	{
-		numVertices = (quality + 1) * 5 + 1;
-		numIndices = ((quality + 1) * 5 - 1) * 3;
+		numVertices = ((quality + 1) * 5 + 1) * 2;
+		numIndices = ((quality + 1) * 5 - 1) * 6;
 	}
 	}
 
 
 	void ShapeMeshes3D::getNumElementsWireArc(UINT32 quality, UINT32& numVertices, UINT32& numIndices)
 	void ShapeMeshes3D::getNumElementsWireArc(UINT32 quality, UINT32& numVertices, UINT32& numIndices)
@@ -505,18 +508,35 @@ namespace BansheeEngine
 
 
 		UINT32 totalNumVertices = numArcVertices + 1;
 		UINT32 totalNumVertices = numArcVertices + 1;
 		outNormals += vertexOffset * vertexStride;
 		outNormals += vertexOffset * vertexStride;
+		outVertices += vertexOffset * vertexStride;
+
+		UINT8* otherSideVertices = outVertices + (totalNumVertices * vertexStride);
+		UINT8* otherSideNormals = outNormals + (totalNumVertices * vertexStride);
 		for (UINT32 i = 0; i < totalNumVertices; i++)
 		for (UINT32 i = 0; i < totalNumVertices; i++)
 		{
 		{
+			otherSideVertices = writeVector3(otherSideVertices, vertexStride, *(Vector3*)outVertices);
+			outVertices += vertexStride;
+
 			outNormals = writeVector3(outNormals, vertexStride, normal);
 			outNormals = writeVector3(outNormals, vertexStride, normal);
+			otherSideNormals = writeVector3(otherSideNormals, vertexStride, -normal);
 		}
 		}
 
 
 		outIndices += indexOffset;
 		outIndices += indexOffset;
 		UINT32 numTriangles = numArcVertices - 1;
 		UINT32 numTriangles = numArcVertices - 1;
+
+		// If angle is negative the order of vertices is reversed so we need to reverse the indexes too
+		UINT32 frontSideOffset = vertexOffset + (amountAngle.valueDegrees() < 0.0f ? totalNumVertices : 0);
+		UINT32 backSideOffset = vertexOffset + (amountAngle.valueDegrees() >= 0.0f ? totalNumVertices : 0);
+
 		for (UINT32 i = 0; i < numTriangles; i++)
 		for (UINT32 i = 0; i < numTriangles; i++)
 		{
 		{
-			outIndices[i * 3 + 0] = vertexOffset + 0;
-			outIndices[i * 3 + 1] = vertexOffset + i;
-			outIndices[i * 3 + 2] = vertexOffset + i + 1;
+			outIndices[i * 6 + 0] = frontSideOffset + 0;
+			outIndices[i * 6 + 1] = frontSideOffset + i;
+			outIndices[i * 6 + 2] = frontSideOffset + i + 1;
+
+			outIndices[i * 6 + 3] = backSideOffset + 0;
+			outIndices[i * 6 + 4] = backSideOffset + i + 1;
+			outIndices[i * 6 + 5] = backSideOffset + i;
 		}
 		}
 	}
 	}
 
 
@@ -947,8 +967,6 @@ namespace BansheeEngine
 	{
 	{
 		assert(numVertices >= 2);
 		assert(numVertices >= 2);
 
 
-		startAngle += Degree(90.0f); // Offset so arc starts the same as trig functions
-
 		Vector3 normalizedUp = Vector3::normalize(up);
 		Vector3 normalizedUp = Vector3::normalize(up);
 		Vector3 right;
 		Vector3 right;
 
 

+ 1 - 1
BansheeGLRenderSystem/Source/BsGLRenderAPI.cpp

@@ -301,7 +301,7 @@ namespace BansheeEngine
 				if (uniformBufferData == nullptr && paramBlockBuffer->getSize() > 0)
 				if (uniformBufferData == nullptr && paramBlockBuffer->getSize() > 0)
 				{
 				{
 					uniformBufferData = (UINT8*)bs_alloc<ScratchAlloc>(paramBlockBuffer->getSize());
 					uniformBufferData = (UINT8*)bs_alloc<ScratchAlloc>(paramBlockBuffer->getSize());
-					paramBlockBuffer->readFromGPU(uniformBufferData);
+					paramBlockBuffer->readFromGPU(uniformBufferData); // TODO - Don't read from GPU!? Just read the cached version
 				}
 				}
 
 
 				continue;
 				continue;

+ 4 - 0
BansheeRenderer/Source/BsBansheeRenderer.cpp

@@ -28,6 +28,7 @@
 #include "BsTime.h"
 #include "BsTime.h"
 #include "BsRenderableElement.h"
 #include "BsRenderableElement.h"
 #include "BsFrameAlloc.h"
 #include "BsFrameAlloc.h"
+#include "BsCoreObjectManager.h"
 
 
 using namespace std::placeholders;
 using namespace std::placeholders;
 
 
@@ -195,6 +196,9 @@ namespace BansheeEngine
 			gCoreAccessor().queueCommand(std::bind(&BansheeRenderer::addToRenderQueue, this, camera->getCore(), renderQueue));
 			gCoreAccessor().queueCommand(std::bind(&BansheeRenderer::addToRenderQueue, this, camera->getCore(), renderQueue));
 		}
 		}
 
 
+		// Sync all dirty sim thread CoreObject data to core thread
+		CoreObjectManager::instance().syncToCore(gCoreAccessor());
+
 		gCoreAccessor().queueCommand(std::bind(&BansheeRenderer::renderAllCore, this, gTime().getTime()));
 		gCoreAccessor().queueCommand(std::bind(&BansheeRenderer::renderAllCore, this, gTime().getTime()));
 	}
 	}
 
 

+ 121 - 142
BansheeUtility/Include/BsMath.h

@@ -361,18 +361,14 @@ namespace BansheeEngine
 		template <typename T>
 		template <typename T>
 		static UINT32 solveLinear(T A, T B, T* roots)
 		static UINT32 solveLinear(T A, T B, T* roots)
 		{
 		{
-			if (!approxEquals(B, (T)0))
+			if (!approxEquals(A, (T)0))
 			{
 			{
-				roots[0] = -A / B;
-				return 1;
-			}
-			else if (approxEquals(A, (T)0))
-			{
-				roots[0] = 0.0f;
+				roots[0] = -B / A;
 				return 1;
 				return 1;
 			}
 			}
 
 
-			return 0;
+			roots[0] = 0.0f;
+			return 1;
 		}
 		}
 
 
 		/**
 		/**
@@ -387,32 +383,34 @@ namespace BansheeEngine
 		template <typename T>
 		template <typename T>
 		static UINT32 solveQuadratic(T A, T B, T C, T* roots)
 		static UINT32 solveQuadratic(T A, T B, T C, T* roots)
 		{
 		{
-			if (!approxEquals(C, (T)0))
+			if (!approxEquals(A, (T)0))
 			{
 			{
-				T discr = B * B - 4 * A * C;
-				if (discr > std::numeric_limits<T>::epsilon())
-				{
-					float temp = ((T)0.5) / C;
-					discr = std::sqrt(discr);
+				T p = B / (2 * A);
+				T q = C / A;
+				T D = p * p - q;
 
 
-					roots[0] = temp * (-B - discr);
-					roots[1] = temp * (-B + discr);
+				if (!approxEquals(D, (T)0))
+				{
+					if (D < (T)0)
+						return 0;
+					
+					T sqrtD = sqrt(D);
+					roots[0] = sqrtD - p;
+					roots[1] = -sqrtD - p;
 
 
 					return 2;
 					return 2;
 				}
 				}
-				else if (discr < -std::numeric_limits<T>::epsilon())
-				{
-					return 0;
-				}
 				else
 				else
 				{
 				{
-					roots[0] = ((T)-0.5) * (B / C);
+					roots[0] = -p;
+					roots[1] = -p;
+
 					return 1;
 					return 1;
 				}
 				}
 			}
 			}
 			else
 			else
 			{
 			{
-				return solveLinear(A, B, roots);
+				return solveLinear(B, C, roots);
 			}
 			}
 		}
 		}
 
 
@@ -430,70 +428,67 @@ namespace BansheeEngine
 		{
 		{
 			static const T THIRD = (1 / (T)3);
 			static const T THIRD = (1 / (T)3);
 
 
-			if (!approxEquals(D, (T)0))
-			{
-				T invD = 1 / D;
-				T k0 = A * invD;
-				T k1 = B * invD;
-				T k2 = C * invD;
-
-				T offset = THIRD * k2;
-				T a = k1 - k2 * offset;
-				T b = k0 + k2 * (2 * k2 * k2 - 9 * k1) * (1 / (T)27);
-				T halfB = ((T)0.5) * b;
-
-				T discr = halfB * halfB + a * a * a * (1 / (T)27);
-				if (discr > std::numeric_limits<T>::epsilon())
-				{
-					discr = std::sqrt(discr);
-					T temp = -halfB + discr;
-					if (temp >= (T)0)
-						roots[0] = pow(temp, THIRD);
-					else
-						roots[0] = -pow(-temp, THIRD);
+			T invA = 1 / A;
+			A = B * invA;
+			B = C * invA;
+			C = D * invA;
 
 
-					temp = -halfB - discr;
-					if (temp >= 0)
-						roots[0] += pow(temp, THIRD);
-					else
-						roots[0] -= -pow(-temp, THIRD);
+			T sqA = A * A;
+			T p = THIRD * (-THIRD * sqA + B);
+			T q = ((T)0.5) * ((2 / (T)27) * A * sqA - THIRD * A * B + C);
 
 
-					roots[0] -= offset;
-					return 1;
-				}
-				else if (discr < -std::numeric_limits<T>::epsilon())
+			T cbp = p * p * p;
+			D = q * q + cbp;
+
+			UINT32 numRoots = 0;
+			if (!approxEquals(D, (T)0))
+			{
+				if (D < 0.0)
 				{
 				{
-					T sqrtThree = std::sqrt((T)3);
-					T dist = sqrt(-THIRD * a);
-					T angle = THIRD * atan2(std::sqrt(-discr), -halfB).valueRadians();
-					T angleCos = cos(angle);
-					T angleSin = sin(angle);
+					T phi = THIRD * ::acos(-q / sqrt(-cbp));
+					T t = 2 * sqrt(-p);
 
 
-					roots[0] = 2 * dist * angleCos - offset;
-					roots[1] = -dist * (angleCos + sqrtThree * angleSin) - offset;
-					roots[2] = -dist * (angleCos - sqrtThree * angleSin) - offset;
+					roots[0] = t * cos(phi);
+					roots[1] = -t * cos(phi + PI * THIRD);
+					roots[2] = -t * cos(phi - PI * THIRD);
 
 
-					return 3;
+					numRoots = 3;
 				}
 				}
 				else
 				else
 				{
 				{
-					T temp;
-					if (halfB >= (T)0)
-						temp = -pow(halfB, THIRD);
-					else
-						temp = pow(-halfB, THIRD);
+					T sqrtD = sqrt(D);
+					T u = cbrt(sqrtD + fabs(q));
 
 
-					roots[0] = 2 * temp - offset;
-					roots[1] = -temp - offset;
-					roots[2] = roots[1];
+					if (q > (T)0)
+						roots[0] = -u + p / u;
+					else
+						roots[0] = u - p / u;
 
 
-					return 3;
+					numRoots = 1;
 				}
 				}
 			}
 			}
 			else
 			else
 			{
 			{
-				return solveQuadratic(A, B, C, roots);
+				if (!approxEquals(q, (T)0))
+				{
+					T u = cbrt(-q);
+					roots[0] = 2 * u;
+					roots[1] = -u;
+
+					numRoots = 2;
+				}
+				else
+				{
+					roots[0] = 0.0f;
+					numRoots = 1;
+				}
 			}
 			}
+
+			T sub = THIRD * A;
+			for (UINT32 i = 0; i < numRoots; i++)
+				roots[i] -= sub;
+
+			return numRoots;
 		}
 		}
 
 
 		/**
 		/**
@@ -508,84 +503,68 @@ namespace BansheeEngine
 		template <typename T>
 		template <typename T>
 		static UINT32 solveQuartic(T A, T B, T C, T D, T E, T* roots)
 		static UINT32 solveQuartic(T A, T B, T C, T D, T E, T* roots)
 		{
 		{
-			if (!approxEquals(E, (T)0))
+			T invA = 1 / A;
+			A = B * invA;
+			B = C * invA;
+			C = D * invA;
+			D = E * invA;
+
+			T sqA = A*A;
+			T p = -(3 / (T)8) * sqA + B;
+			T q = (1 / (T)8) * sqA * A - (T)0.5 * A * B + C;
+			T r = -(3 / (T)256) * sqA * sqA + (1 / (T)16) * sqA * B - (1 / (T)4) * A * C + D;
+
+			UINT32 numRoots = 0;
+			if (!approxEquals(r, (T)0))
 			{
 			{
-				T invE = 1 / E;
-				T k0 = A * invE;
-				T k1 = B * invE;
-				T k2 = C * invE;
-				T k3 = D * invE;
-
-				T r0 = k0 * (4 * k2 - k3 * k3) - k1 * k1;
-				T r1 = k3 * k1 - 4 * k0;
-				T r2 = -k2;
-				solveCubic(r0, r1, r2, (T)1, roots);
-				T y = roots[0];
-
-				UINT32 numRoots = 0;
-				T discr = ((T)0.25) * k3 * k3 - k2 + y;
-				if (discr > std::numeric_limits<T>::epsilon())
-				{
-					T r = sqrt(discr);
-					T t1 = ((T)0.75) * k3 * k3 - r * r - 2*k2;
-					T t2 = (k3 * k2 - 2 * k1 - ((T)0.25) * k3 * k3 * k3) / r;
-
-					T tPlus = t1 + t2;
-					if (tPlus >= ((T)0))
-					{
-						T d = std::sqrt(tPlus);
-						roots[0] = ((T)-0.25) * k3 + ((T)0.5) * (r + d);
-						roots[1] = ((T)-0.25) * k3 + ((T)0.5) * (r - d);
-
-						numRoots += 2;
-					}
-
-					T tMinus = t1 - t2;
-					if (tMinus >= ((T)0))
-					{
-						T e = std::sqrt(tMinus);
-						roots[numRoots++] = ((T)-0.25) * k3 + ((T)0.5) * (e - r);
-						roots[numRoots++] = ((T)-0.25) * k3 - ((T)0.5) * (e + r);
-					}
-				}
-				else if (discr < -std::numeric_limits<T>::epsilon())
-				{
-					numRoots = 0;
-				}
+				T cubicA = 1;
+				T cubicB = -(T)0.5 * p ;
+				T cubicC = -r;
+				T cubicD = (T)0.5 * r * p - (1 / (T)8) * q * q;
+
+				solveCubic(cubicA, cubicB, cubicC, cubicD, roots);
+				T z = roots[0];
+
+				T u = z * z - r;
+				T v = 2 * z - p;
+
+				if (approxEquals(u, T(0)))
+					u = 0;
+				else if (u > 0)
+					u = sqrt(u);
 				else
 				else
-				{
-					T t2 = y * y - 4 * k0;
-					if (t2 >= ((T)0))
-					{
-						t2 = 2 * std::sqrt(t2);
-						T t1 = ((T)0.75) * k3 * k3 - 2 * k2;
-
-						T tPlus = t1 + t2;
-						if (tPlus >= ((T)0))
-						{
-							T d = std::sqrt(tPlus);
-							roots[0] = ((T)-0.25) * k3 + ((T)0.5) * d;
-							roots[1] = ((T)-0.25) * k3 + ((T)0.5) * d;
-
-							numRoots += 2;
-						}
-
-						T tMinus = t1 - t2;
-						if (tMinus >= ((T)0))
-						{
-							T e = std::sqrt(tMinus);
-							roots[numRoots++] = ((T)-0.25) * k3 + ((T)0.5) * e;
-							roots[numRoots++] = ((T)-0.25) * k3 - ((T)0.5) * e;
-						}
-					}
-				}
+					return 0;
+
+				if (approxEquals(v, T(0)))
+					v = 0;
+				else if (v > 0)
+					v = sqrt(v);
+				else
+					return 0;
 
 
-				return numRoots;
+				T quadraticA = 1;
+				T quadraticB = q < 0 ? -v : v;
+				T quadraticC = z - u;
+
+				numRoots = solveQuadratic(quadraticA, quadraticB, quadraticC, roots);
+
+				quadraticA = 1;
+				quadraticB = q < 0 ? v : -v;
+				quadraticC = z + u;
+
+				numRoots += solveQuadratic(quadraticA, quadraticB, quadraticC, roots + numRoots);
 			}
 			}
 			else
 			else
 			{
 			{
-				return solveCubic(A, B, C, D, roots);
+				numRoots = solveCubic(q, p, (T)0, (T)1, roots);
+				roots[numRoots++] = 0;
 			}
 			}
+
+			T sub = (1/(T)4) * A;
+			for (UINT32 i = 0; i < numRoots; i++)
+				roots[i] -= sub;
+
+			return numRoots;
 		}
 		}
 
 
         static const float POS_INFINITY;
         static const float POS_INFINITY;

+ 2 - 1
BansheeUtility/Include/BsTorus.h

@@ -14,13 +14,14 @@ namespace BansheeEngine
 	{
 	{
 	public:
 	public:
 		Torus();
 		Torus();
-		Torus(float outerRadius, float innerRadius);
+		Torus(const Vector3& normal, float outerRadius, float innerRadius);
 
 
 		/**
 		/**
 		 * @brief	Ray/torus intersection, returns boolean result and distance to nearest intersection point.
 		 * @brief	Ray/torus intersection, returns boolean result and distance to nearest intersection point.
 		 */
 		 */
 		std::pair<bool, float> intersects(const Ray& ray) const;
 		std::pair<bool, float> intersects(const Ray& ray) const;
 
 
+		Vector3 normal;
 		float outerRadius;
 		float outerRadius;
 		float innerRadius;
 		float innerRadius;
 	};
 	};

+ 0 - 3
BansheeUtility/Source/BsAABox.cpp

@@ -36,9 +36,6 @@ namespace BansheeEngine
 
 
 	void AABox::setExtents(const Vector3& min, const Vector3& max)
 	void AABox::setExtents(const Vector3& min, const Vector3& max)
 	{
 	{
-        assert( (min.x <= max.x && min.y <= max.y && min.z <= max.z) &&
-            "The minimum corner of the box must be less than or equal to maximum corner" );
-
 		mMinimum = min;
 		mMinimum = min;
 		mMaximum = max;
 		mMaximum = max;
 	}
 	}

+ 16 - 14
BansheeUtility/Source/BsTorus.cpp

@@ -1,6 +1,7 @@
 #include "BsTorus.h"
 #include "BsTorus.h"
 #include "BsRay.h"
 #include "BsRay.h"
 #include "BsMath.h"
 #include "BsMath.h"
+#include "BsDebug.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
@@ -8,8 +9,8 @@ namespace BansheeEngine
 		:outerRadius(0.0f), innerRadius(0.0f)
 		:outerRadius(0.0f), innerRadius(0.0f)
 	{ }
 	{ }
 
 
-	Torus::Torus(float outerRadius, float innerRadius)
-		:outerRadius(outerRadius), innerRadius(innerRadius)
+	Torus::Torus(const Vector3& normal, float outerRadius, float innerRadius)
+		:normal(normal), outerRadius(outerRadius), innerRadius(innerRadius)
 	{ }
 	{ }
 
 
 	std::pair<bool, float> Torus::intersects(const Ray& ray) const
 	std::pair<bool, float> Torus::intersects(const Ray& ray) const
@@ -17,18 +18,19 @@ namespace BansheeEngine
 		const Vector3& org = ray.getOrigin();
 		const Vector3& org = ray.getOrigin();
 		const Vector3& dir = ray.getDirection();
 		const Vector3& dir = ray.getDirection();
 
 
-		float a = org.dot(dir);
-		float b = org.dot(org);
+		float u = normal.dot(org);
+		float v = normal.dot(dir);
 
 
-		float outerSqrd = outerRadius*outerRadius;
-		float innerSqrd = innerRadius*innerRadius;
-		float K = a - innerSqrd - outerSqrd;
+		float a = dir.dot(dir) - v * v;
+		float b = 2 * (org.dot(dir) - u * v);
+		float c = org.dot(org) - u * u;
+		float d = org.dot(org) + outerRadius*outerRadius - innerRadius*innerRadius;
 
 
-		float E = 1.0f;
-		float D = 4 * b;
-		float C = 2 * (2 * b*b + K + 2 * outerSqrd*dir.z*dir.z);
-		float B = 4 * (K*b + 2 * outerSqrd*org.z*dir.z);
-		float A = K*K + 4 * outerSqrd*(org.z*org.z - innerSqrd);
+		float A = 1.0f;
+		float B = 4 * org.dot(dir);
+		float C = 2 * d + 0.25f * B * B - 4 * outerRadius * outerRadius * a;
+		float D = B * d - 4 * outerRadius * outerRadius * b;
+		float E = d * d - 4 * outerRadius * outerRadius * c;
 
 
 		float roots[4];
 		float roots[4];
 		UINT32 numRoots = Math::solveQuartic(A, B, C, D, E, roots);
 		UINT32 numRoots = Math::solveQuartic(A, B, C, D, E, roots);
@@ -41,7 +43,7 @@ namespace BansheeEngine
 			{
 			{
 				float t = roots[i];
 				float t = roots[i];
 				float x = org.x + t*dir.x;
 				float x = org.x + t*dir.x;
-				float y = org.x + t*dir.y;
+				float y = org.y + t*dir.y;
 				float l = outerRadius*(Math::PI / 2 - Math::atan2(y, x).valueRadians());
 				float l = outerRadius*(Math::PI / 2 - Math::atan2(y, x).valueRadians());
 
 
 				if (l >= 0 && t < nearestT)
 				if (l >= 0 && t < nearestT)
@@ -51,6 +53,6 @@ namespace BansheeEngine
 			return std::make_pair(true, nearestT);
 			return std::make_pair(true, nearestT);
 		}
 		}
 
 
-		return std::make_pair(false, 0.0f);
+		return std::make_pair(false, 0.0f); 
 	}
 	}
 }
 }

+ 8 - 8
MBansheeEditor/DbgGizmo.cs

@@ -20,15 +20,15 @@ namespace BansheeEditor
                 iconTexture = new SpriteTexture(iconTex);
                 iconTexture = new SpriteTexture(iconTex);
             }
             }
 
 
-            Gizmos.DrawCube(target.sceneObject.position, new Vector3(1, 1, 1));
-            Gizmos.DrawSphere(target.sceneObject.position + 2 * Vector3.xAxis, 1.0f);
-            Gizmos.DrawWireCube(target.sceneObject.position + 4 * Vector3.xAxis, new Vector3(1, 1, 1));
-            Gizmos.DrawWireSphere(target.sceneObject.position + 6 * Vector3.xAxis, 1.0f);
-            Gizmos.DrawLine(target.sceneObject.position + 7.5f * Vector3.xAxis,
-                target.sceneObject.position + 8.5f * Vector3.xAxis);
-            Gizmos.DrawFrustum(target.sceneObject.position + 10 * Vector3.xAxis, 1920.0f / 1080.0f, 90, 1.0f, 1000.0f);
+            Gizmos.DrawCube(target.sceneObject.Position, new Vector3(1, 1, 1));
+            Gizmos.DrawSphere(target.sceneObject.Position + 2 * Vector3.xAxis, 1.0f);
+            Gizmos.DrawWireCube(target.sceneObject.Position + 4 * Vector3.xAxis, new Vector3(1, 1, 1));
+            Gizmos.DrawWireSphere(target.sceneObject.Position + 6 * Vector3.xAxis, 1.0f);
+            Gizmos.DrawLine(target.sceneObject.Position + 7.5f * Vector3.xAxis,
+                target.sceneObject.Position + 8.5f * Vector3.xAxis);
+            Gizmos.DrawFrustum(target.sceneObject.Position + 10 * Vector3.xAxis, 1920.0f / 1080.0f, 90, 1.0f, 1000.0f);
 
 
-            Gizmos.DrawIcon(target.sceneObject.position + new Vector3(0, 10, 0), iconTexture, false);
+            Gizmos.DrawIcon(target.sceneObject.Position + new Vector3(0, 10, 0), iconTexture, false);
         }
         }
     }
     }
 }
 }

+ 3 - 3
MBansheeEditor/DebugCameraHandle.cs

@@ -18,7 +18,7 @@ namespace BansheeEditor
 
 
         protected override void PreInput()
         protected override void PreInput()
         {
         {
-            xAxis.Position = target.sceneObject.position;
+            xAxis.Position = target.sceneObject.Position;
         }
         }
 
 
         protected override void PostInput()
         protected override void PostInput()
@@ -28,14 +28,14 @@ namespace BansheeEditor
 
 
         protected override void Draw()
         protected override void Draw()
         {
         {
-            Vector3 end = target.sceneObject.position + Vector3.xAxis * 5;
+            Vector3 end = target.sceneObject.Position + Vector3.xAxis * 5;
 
 
             if (xAxis.State == HandleSlider.StateType.Active)
             if (xAxis.State == HandleSlider.StateType.Active)
                 HandleDrawing.SetColor(Color.white);
                 HandleDrawing.SetColor(Color.white);
             else
             else
                 HandleDrawing.SetColor(Color.green);
                 HandleDrawing.SetColor(Color.green);
 
 
-            HandleDrawing.DrawLine(target.sceneObject.position, end);
+            HandleDrawing.DrawLine(target.sceneObject.Position, end);
         }
         }
     }
     }
 }
 }

+ 9 - 13
MBansheeEditor/EditorApplication.cs

@@ -12,7 +12,7 @@ namespace BansheeEditor
         Scale
         Scale
     }
     }
 
 
-    public enum HandlePositionMode
+    public enum HandlePivotMode
     {
     {
         Center,
         Center,
         Pivot
         Pivot
@@ -26,26 +26,22 @@ namespace BansheeEditor
 
 
     public class EditorApplication
     public class EditorApplication
     {
     {
-        private static SceneViewTool activeSceneTool = SceneViewTool.Move; // TODO - Actually retrieve this from somewhere
-        private static HandlePositionMode handlePositionMode = HandlePositionMode.Pivot; // TODO - Actually retrieve this from somewhere
-        private static HandleCoordinateMode handleCoordinateMode = HandleCoordinateMode.World; // TODO - Actually retrieve this from somewhere
-
         public static SceneViewTool ActiveSceneTool
         public static SceneViewTool ActiveSceneTool
         {
         {
-            get { return activeSceneTool; }
-            set { activeSceneTool = value; } // TODO - Will likely need to update active GUI button when this changes
+            get { return EditorSettings.ActiveSceneTool; }
+            set { EditorSettings.ActiveSceneTool = value; }
         }
         }
 
 
-        public static HandlePositionMode HandlePositionMode
+        public static HandleCoordinateMode ActiveCoordinateMode
         {
         {
-            get { return handlePositionMode; }
-            set { handlePositionMode = value; } // TODO - Will likely need to update active GUI button when this changes
+            get { return EditorSettings.ActiveCoordinateMode; }
+            set { EditorSettings.ActiveCoordinateMode = value; }
         }
         }
 
 
-        public static HandleCoordinateMode HandleCoordinateMode
+        public static HandlePivotMode ActivePivotMode
         {
         {
-            get { return handleCoordinateMode; }
-            set { handleCoordinateMode = value; } // TODO - Will likely need to update active GUI button when this changes
+            get { return EditorSettings.ActivePivotMode; }
+            set { EditorSettings.ActivePivotMode = value; }
         }
         }
 
 
         public static Camera SceneViewCamera
         public static Camera SceneViewCamera

+ 43 - 24
MBansheeEditor/EditorSettings.cs

@@ -8,7 +8,7 @@ using BansheeEngine;
 
 
 namespace BansheeEditor
 namespace BansheeEditor
 {
 {
-    public static class EditorSettings
+    internal static class EditorSettings
     {
     {
         public static bool MoveHandleSnapActive
         public static bool MoveHandleSnapActive
         {
         {
@@ -22,28 +22,16 @@ namespace BansheeEditor
             set { Internal_SetRotateHandleSnapActive(value); }
             set { Internal_SetRotateHandleSnapActive(value); }
         }
         }
 
 
-        public static bool ScaleHandleSnapActive
-        {
-            get { return Internal_GetScaleHandleSnapActive(); }
-            set { Internal_SetScaleHandleSnapActive(value); }
-        }
-
         public static float MoveHandleSnapAmount
         public static float MoveHandleSnapAmount
         {
         {
             get { return Internal_GetMoveHandleSnapAmount(); }
             get { return Internal_GetMoveHandleSnapAmount(); }
             set { Internal_SetMoveHandleSnapAmount(value); }
             set { Internal_SetMoveHandleSnapAmount(value); }
         }
         }
 
 
-        public static float RotateHandleSnapAmount
+        public static Degree RotateHandleSnapAmount
         {
         {
             get { return Internal_GetRotateHandleSnapAmount(); }
             get { return Internal_GetRotateHandleSnapAmount(); }
-            set { Internal_SetRotateHandleSnapAmount(value); }
-        }
-
-        public static float ScaleHandleSnapAmount
-        {
-            get { return Internal_GetScaleHandleSnapAmount(); }
-            set { Internal_SetScaleHandleSnapAmount(value); }
+            set { Internal_SetRotateHandleSnapAmount(value.GetDegrees()); }
         }
         }
 
 
         public static float DefaultHandleSize
         public static float DefaultHandleSize
@@ -52,6 +40,29 @@ namespace BansheeEditor
             set { Internal_SetDefaultHandleSize(value); }
             set { Internal_SetDefaultHandleSize(value); }
         }
         }
 
 
+        public static SceneViewTool ActiveSceneTool
+        {
+            get { return (SceneViewTool)Internal_GetActiveSceneTool(); }
+            set { Internal_SetActiveSceneTool((int)value); }
+        }
+
+        public static HandleCoordinateMode ActiveCoordinateMode
+        {
+            get { return (HandleCoordinateMode)Internal_GetActiveCoordinateMode(); }
+            set { Internal_SetActiveCoordinateMode((int)value); }
+        }
+
+        public static HandlePivotMode ActivePivotMode
+        {
+            get { return (HandlePivotMode)Internal_GetActivePivotMode(); }
+            set { Internal_SetActivePivotMode((int)value); }
+        }
+
+        public static int Hash
+        {
+            get { return Internal_GetHash(); }
+        }
+
         [MethodImpl(MethodImplOptions.InternalCall)]
         [MethodImpl(MethodImplOptions.InternalCall)]
         private static extern bool Internal_GetMoveHandleSnapActive();
         private static extern bool Internal_GetMoveHandleSnapActive();
         [MethodImpl(MethodImplOptions.InternalCall)]
         [MethodImpl(MethodImplOptions.InternalCall)]
@@ -62,11 +73,6 @@ namespace BansheeEditor
         [MethodImpl(MethodImplOptions.InternalCall)]
         [MethodImpl(MethodImplOptions.InternalCall)]
         private static extern void Internal_SetRotateHandleSnapActive(bool value);
         private static extern void Internal_SetRotateHandleSnapActive(bool value);
 
 
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern bool Internal_GetScaleHandleSnapActive();
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_SetScaleHandleSnapActive(bool value);
-
         [MethodImpl(MethodImplOptions.InternalCall)]
         [MethodImpl(MethodImplOptions.InternalCall)]
         private static extern float Internal_GetMoveHandleSnapAmount();
         private static extern float Internal_GetMoveHandleSnapAmount();
         [MethodImpl(MethodImplOptions.InternalCall)]
         [MethodImpl(MethodImplOptions.InternalCall)]
@@ -78,13 +84,26 @@ namespace BansheeEditor
         private static extern void Internal_SetRotateHandleSnapAmount(float value);
         private static extern void Internal_SetRotateHandleSnapAmount(float value);
 
 
         [MethodImpl(MethodImplOptions.InternalCall)]
         [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern float Internal_GetScaleHandleSnapAmount();
+        private static extern float Internal_GetDefaultHandleSize();
         [MethodImpl(MethodImplOptions.InternalCall)]
         [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_SetScaleHandleSnapAmount(float value);
+        private static extern void Internal_SetDefaultHandleSize(float value);
 
 
         [MethodImpl(MethodImplOptions.InternalCall)]
         [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern float Internal_GetDefaultHandleSize();
+        private static extern int Internal_GetActiveSceneTool();
         [MethodImpl(MethodImplOptions.InternalCall)]
         [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_SetDefaultHandleSize(float value);
+        private static extern void Internal_SetActiveSceneTool(int value);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern int Internal_GetActiveCoordinateMode();
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_SetActiveCoordinateMode(int value);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern int Internal_GetActivePivotMode();
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_SetActivePivotMode(int value);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern int Internal_GetHash();
     }
     }
 }
 }

+ 14 - 12
MBansheeEditor/Scene/DefaultHandleManager.cs

@@ -10,11 +10,15 @@ namespace BansheeEditor
             public HandledObject(SceneObject so)
             public HandledObject(SceneObject so)
             {
             {
                 this.so = so;
                 this.so = so;
-                initialPosition = so.position;
+                initialPosition = so.Position;
+                initialRotation = so.Rotation;
+                initialScale = so.LocalScale;
             }
             }
 
 
             public SceneObject so;
             public SceneObject so;
             public Vector3 initialPosition;
             public Vector3 initialPosition;
+            public Quaternion initialRotation;
+            public Vector3 initialScale;
         }
         }
 
 
         private SceneViewTool activeHandleType = SceneViewTool.View;
         private SceneViewTool activeHandleType = SceneViewTool.View;
@@ -65,14 +69,14 @@ namespace BansheeEditor
             if (activeHandle != null)
             if (activeHandle != null)
             {
             {
                 Quaternion rotation;
                 Quaternion rotation;
-                if (EditorApplication.HandleCoordinateMode == HandleCoordinateMode.World)
+                if (EditorApplication.ActiveCoordinateMode == HandleCoordinateMode.World)
                     rotation = Quaternion.identity;
                     rotation = Quaternion.identity;
                 else
                 else
-                    rotation = selectedSceneObjects[0].rotation; // We don't average rotation in case of multi-selection
+                    rotation = selectedSceneObjects[0].Rotation; // We don't average rotation in case of multi-selection
 
 
                 Vector3 position;
                 Vector3 position;
-                if (EditorApplication.HandlePositionMode == HandlePositionMode.Pivot)
-                    position = selectedSceneObjects[0].position; // Just take pivot from the first one, no averaging
+                if (EditorApplication.ActivePivotMode == HandlePivotMode.Pivot)
+                    position = selectedSceneObjects[0].Position; // Just take pivot from the first one, no averaging
                 else
                 else
                 {
                 {
                     List<SceneObject> flatenedHierarchy = new List<SceneObject>();
                     List<SceneObject> flatenedHierarchy = new List<SceneObject>();
@@ -125,7 +129,7 @@ namespace BansheeEditor
                             MoveHandle moveHandle = (MoveHandle) activeHandle;
                             MoveHandle moveHandle = (MoveHandle) activeHandle;
 
 
                             foreach (var selectedObj in activeSelection)
                             foreach (var selectedObj in activeSelection)
-                                selectedObj.so.position = selectedObj.initialPosition + moveHandle.Delta;
+                                selectedObj.so.Position = selectedObj.initialPosition + moveHandle.Delta;
                         }
                         }
 
 
                             break;
                             break;
@@ -133,18 +137,16 @@ namespace BansheeEditor
                         {
                         {
                             RotateHandle rotateHandle = (RotateHandle) activeHandle;
                             RotateHandle rotateHandle = (RotateHandle) activeHandle;
 
 
-                            // TODO - Add delta rotation
-                            //foreach (var so in selectedSceneObjects)
-                            //    so.rotation += rotateHandle.Delta;
+                            foreach (var selectedObj in activeSelection)
+                                selectedObj.so.Rotation = selectedObj.initialRotation * rotateHandle.Delta;
                         }
                         }
                             break;
                             break;
                         case SceneViewTool.Scale:
                         case SceneViewTool.Scale:
                         {
                         {
                             ScaleHandle scaleHandle = (ScaleHandle) activeHandle;
                             ScaleHandle scaleHandle = (ScaleHandle) activeHandle;
 
 
-                            // TODO - Add delta scale
-                            //foreach (var so in selectedSceneObjects)
-                            //    so.localScale += scaleHandle.Delta;
+                            foreach (var selectedObj in activeSelection)
+                                selectedObj.so.LocalScale = selectedObj.initialScale + scaleHandle.Delta;
                         }
                         }
                             break;
                             break;
                     }
                     }

+ 15 - 2
MBansheeEditor/Scene/HandleSliderDisc.cs

@@ -6,13 +6,13 @@ namespace BansheeEditor
 {
 {
     public sealed class HandleSliderDisc : HandleSlider
     public sealed class HandleSliderDisc : HandleSlider
     {
     {
-        public HandleSliderDisc(Handle parentHandle, Vector3 normal, float radius, bool fixedScale = true, float snapValue = 0.0f)
+        public HandleSliderDisc(Handle parentHandle, Vector3 normal, float radius, bool fixedScale = true)
             :base(parentHandle)
             :base(parentHandle)
         {
         {
             Internal_CreateInstance(this, normal, radius, fixedScale);
             Internal_CreateInstance(this, normal, radius, fixedScale);
         }
         }
 
 
-        public float Delta
+        public Degree Delta
         {
         {
             get
             get
             {
             {
@@ -22,10 +22,23 @@ namespace BansheeEditor
             }
             }
         }
         }
 
 
+        public Degree StartAngle
+        {
+            get
+            {
+                float value;
+                Internal_GetStartAngle(mCachedPtr, out value);
+                return value;
+            }
+        }
+
         [MethodImpl(MethodImplOptions.InternalCall)]
         [MethodImpl(MethodImplOptions.InternalCall)]
         private static extern void Internal_CreateInstance(HandleSliderDisc instance, Vector3 normal, float radius, bool fixedScale);
         private static extern void Internal_CreateInstance(HandleSliderDisc instance, Vector3 normal, float radius, bool fixedScale);
 
 
         [MethodImpl(MethodImplOptions.InternalCall)]
         [MethodImpl(MethodImplOptions.InternalCall)]
         private static extern void Internal_GetDelta(IntPtr nativeInstance, out float value);
         private static extern void Internal_GetDelta(IntPtr nativeInstance, out float value);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_GetStartAngle(IntPtr nativeInstance, out float value);
     }
     }
 }
 }

+ 8 - 15
MBansheeEditor/Scene/Handles.cs

@@ -17,12 +17,6 @@ namespace BansheeEditor
             set { EditorSettings.RotateHandleSnapActive = value; }
             set { EditorSettings.RotateHandleSnapActive = value; }
         }
         }
 
 
-        public static bool ScaleHandleSnapActive
-        {
-            get { return EditorSettings.ScaleHandleSnapActive; }
-            set { EditorSettings.ScaleHandleSnapActive = value; }
-        }
-
         public static float MoveSnapAmount
         public static float MoveSnapAmount
         {
         {
             get { return EditorSettings.MoveHandleSnapAmount; }
             get { return EditorSettings.MoveHandleSnapAmount; }
@@ -32,13 +26,7 @@ namespace BansheeEditor
         public static Degree RotateSnapAmount
         public static Degree RotateSnapAmount
         {
         {
             get { return EditorSettings.RotateHandleSnapAmount; }
             get { return EditorSettings.RotateHandleSnapAmount; }
-            set { EditorSettings.RotateHandleSnapAmount = value.GetDegrees(); }
-        }
-
-        public static float ScaleSnapAmount
-        {
-            get { return EditorSettings.ScaleHandleSnapAmount; }
-            set { EditorSettings.MoveHandleSnapAmount = value; }
+            set { EditorSettings.RotateHandleSnapAmount = value; }
         }
         }
 
 
         public static float SnapValue(float value, float snapAmount)
         public static float SnapValue(float value, float snapAmount)
@@ -49,12 +37,17 @@ namespace BansheeEditor
             return value;
             return value;
         }
         }
 
 
+        public static Degree SnapValue(Degree value, Degree snapAmount)
+        {
+            return SnapValue(value.GetDegrees(), snapAmount.GetDegrees());
+        }
+
         public static float GetHandleSize(Camera camera, Vector3 position)
         public static float GetHandleSize(Camera camera, Vector3 position)
         {
         {
-            Vector3 cameraPos = camera.sceneObject.position;
+            Vector3 cameraPos = camera.sceneObject.Position;
 
 
 		    Vector3 diff = position - cameraPos;
 		    Vector3 diff = position - cameraPos;
-		    float distAlongViewDir = Math.Abs(Vector3.Dot(diff, camera.sceneObject.rotation.Forward));
+		    float distAlongViewDir = Math.Abs(Vector3.Dot(diff, camera.sceneObject.Rotation.Forward));
 
 
             return distAlongViewDir * EditorSettings.DefaultHandleSize;
             return distAlongViewDir * EditorSettings.DefaultHandleSize;
         }
         }

+ 132 - 3
MBansheeEditor/Scene/RotateHandle.cs

@@ -4,29 +4,158 @@ namespace BansheeEditor
 {
 {
     public sealed class RotateHandle : DefaultHandle
     public sealed class RotateHandle : DefaultHandle
     {
     {
-        public RotateHandle()
-        {
+        private Quaternion delta;
+
+        private HandleSliderDisc xAxis;
+        private HandleSliderDisc yAxis;
+        private HandleSliderDisc zAxis;
 
 
+        public Quaternion Delta
+        {
+            get { return delta; }
         }
         }
 
 
         internal override bool IsDragged()
         internal override bool IsDragged()
         {
         {
-            return false;
+            return xAxis.State == HandleSlider.StateType.Active;
+            //return xAxis.State == HandleSlider.StateType.Active ||
+            //        yAxis.State == HandleSlider.StateType.Active ||
+            //        zAxis.State == HandleSlider.StateType.Active;
+        }
+
+        public RotateHandle()
+        {
+            xAxis = new HandleSliderDisc(this, Vector3.xAxis, 1.0f);
+            //yAxis = new HandleSliderDisc(this, Vector3.yAxis, 1.0f);
+            //zAxis = new HandleSliderDisc(this, Vector3.zAxis, 1.0f);
         }
         }
 
 
         protected override void PreInput()
         protected override void PreInput()
         {
         {
+            xAxis.Position = position;
+           // yAxis.Position = position;
+            //zAxis.Position = position;
 
 
+            xAxis.Rotation = rotation;
+            //yAxis.Rotation = rotation;
+            //zAxis.Rotation = rotation;
         }
         }
 
 
         protected override void PostInput()
         protected override void PostInput()
         {
         {
+            delta = Quaternion.identity;
+
+            Degree xValue = 0.0f;
+            Degree yValue = 0.0f;
+            Degree zValue = 0.0f;
+
+            if (Handles.RotateHandleSnapActive)
+            {
+                xValue = Handles.SnapValue(xAxis.Delta, Handles.RotateSnapAmount);
+                //yValue = Handles.SnapValue(yAxis.Delta, Handles.RotateSnapAmount);
+                //zValue = Handles.SnapValue(zAxis.Delta, Handles.RotateSnapAmount);
+            }
+            else
+            {
+                xValue = xAxis.Delta;
+                //yValue = yAxis.Delta;
+               // zValue = zAxis.Delta;
+            }
 
 
+            delta = Quaternion.FromAxisAngle(GetXDir(), xValue) * delta;
+           // delta = Quaternion.FromAxisAngle(GetYDir(), yValue) * delta;
+           // delta = Quaternion.FromAxisAngle(GetZDir(), zValue) * delta;
         }
         }
 
 
         protected override void Draw()
         protected override void Draw()
         {
         {
+            HandleDrawing.SetTransform(Matrix4.TRS(Position, Rotation, Vector3.one));
+            float handleSize = Handles.GetHandleSize(EditorApplication.SceneViewCamera, position);
+
+            // Draw arcs
+            Color axisHover = new Color(0.8f, 0.8f, 0.8f, 1.0f);
+
+            if (xAxis.State == HandleSlider.StateType.Active)
+                HandleDrawing.SetColor(Color.white);
+            else if(xAxis.State == HandleSlider.StateType.Hover)
+                HandleDrawing.SetColor(Color.red * axisHover);
+            else
+                HandleDrawing.SetColor(Color.red);
+
+            Vector3 xStartDir = Vector3.Cross(EditorApplication.SceneViewCamera.sceneObject.Forward, GetXDir());
+            Degree xStartAngle = PointOnCircleToAngle(GetXDir(), xStartDir);
+
+            Debug.Log("START ARC: " + xStartDir + " -- " + xStartAngle);
+
+            HandleDrawing.DrawWireArc(Vector3.zero, GetXDir(), 1.0f, xStartAngle, 180.0f, handleSize);
+
+            //if (yAxis.State == HandleSlider.StateType.Active)
+            //    HandleDrawing.SetColor(Color.white);
+            //else if (yAxis.State == HandleSlider.StateType.Hover)
+            //    HandleDrawing.SetColor(Color.green * axisHover);
+            //else
+            //    HandleDrawing.SetColor(Color.green);
+
+            //Vector3 yStartDir = Vector3.Cross(EditorApplication.SceneViewCamera.sceneObject.Forward, GetYDir());
+            //Degree yStartAngle = PointOnCircleToAngle(GetYDir(), yStartDir);
+
+            //HandleDrawing.DrawWireArc(Vector3.zero, GetYDir(), 1.0f, yStartAngle, 180.0f, handleSize);
+
+            //if (zAxis.State == HandleSlider.StateType.Active)
+            //    HandleDrawing.SetColor(Color.white);
+            //else if (zAxis.State == HandleSlider.StateType.Hover)
+            //    HandleDrawing.SetColor(Color.blue * axisHover);
+            //else
+            //    HandleDrawing.SetColor(Color.blue);
+
+            //Vector3 zStartDir = Vector3.Cross(EditorApplication.SceneViewCamera.sceneObject.Forward, -GetZDir());
+            //Degree zStartAngle = PointOnCircleToAngle(-GetZDir(), zStartDir);
+
+            //HandleDrawing.DrawWireArc(Vector3.zero, -GetZDir(), 1.0f, zStartAngle, 180.0f, handleSize);
+
+            // Draw active rotation pie
+            Color gray = new Color(1.0f, 1.0f, 1.0f, 0.3f);
+            HandleDrawing.SetColor(gray);
+
+            if (xAxis.State == HandleSlider.StateType.Active)
+                HandleDrawing.DrawArc(Vector3.zero, GetXDir(), 1.0f, xAxis.StartAngle, xAxis.Delta, handleSize);
+            //else if (yAxis.State == HandleSlider.StateType.Active)
+            //    HandleDrawing.DrawArc(Vector3.zero, GetYDir(), 1.0f, yAxis.StartAngle, yAxis.Delta, handleSize);
+            //else if (zAxis.State == HandleSlider.StateType.Active)
+            //    HandleDrawing.DrawArc(Vector3.zero, -GetZDir(), 1.0f, zAxis.StartAngle, zAxis.Delta, handleSize);
+
+            // TODO - Free rotate handle
+        }
+
+        private Vector3 GetXDir()
+        {
+             return rotation.Rotate(Vector3.xAxis);
+        }
+
+        private Vector3 GetYDir()
+        {
+            return rotation.Rotate(Vector3.yAxis);
+        }
+
+        private Vector3 GetZDir()
+        {
+            return rotation.Rotate(Vector3.zAxis);
+        }
+
+        private Degree PointOnCircleToAngle(Vector3 up, Vector3 point)
+        {
+            Vector3[] arcBasis = new Vector3[3];
+            arcBasis[1] = up;
+            Vector3.OrthogonalComplement(arcBasis[1], out arcBasis[2], out arcBasis[0]);
+
+            Matrix4 worldToPlane = Matrix4.identity;
+            worldToPlane.SetColumn(0, (Vector4)arcBasis[0]);
+            worldToPlane.SetColumn(1, (Vector4)arcBasis[1]);
+            worldToPlane.SetColumn(2, (Vector4)arcBasis[2]);
+
+            point = worldToPlane.Multiply(point);
 
 
+            return (MathEx.Atan2(-point.z, -point.x) + MathEx.Pi) * MathEx.Rad2Deg;
         }
         }
     }
     }
 }
 }

+ 92 - 3
MBansheeEditor/Scene/ScaleHandle.cs

@@ -4,29 +4,118 @@ namespace BansheeEditor
 {
 {
     public sealed class ScaleHandle : DefaultHandle
     public sealed class ScaleHandle : DefaultHandle
     {
     {
-        public ScaleHandle()
-        {
+        private const float SMALL_CUBE_SIZE = 0.175f;
+        private const float CENTER_CUBE_SIZE = 0.33f;
+
+        private Vector3 delta;
+
+        private HandleSliderLine xAxis;
+        private HandleSliderLine yAxis;
+        private HandleSliderLine zAxis;
 
 
+        public Vector3 Delta
+        {
+            get { return delta; }
         }
         }
 
 
         internal override bool IsDragged()
         internal override bool IsDragged()
         {
         {
-            return false;
+            return xAxis.State == HandleSlider.StateType.Active ||
+                    yAxis.State == HandleSlider.StateType.Active ||
+                    zAxis.State == HandleSlider.StateType.Active;
+        }
+
+        public ScaleHandle()
+        {
+            xAxis = new HandleSliderLine(this, Vector3.xAxis, 1.0f);
+            yAxis = new HandleSliderLine(this, Vector3.yAxis, 1.0f);
+            zAxis = new HandleSliderLine(this, Vector3.zAxis, 1.0f);
         }
         }
 
 
         protected override void PreInput()
         protected override void PreInput()
         {
         {
+            xAxis.Position = position;
+            yAxis.Position = position;
+            zAxis.Position = position;
 
 
+            xAxis.Rotation = rotation;
+            yAxis.Rotation = rotation;
+            zAxis.Rotation = rotation;
         }
         }
 
 
         protected override void PostInput()
         protected override void PostInput()
         {
         {
+            delta = Vector3.zero;
 
 
+            delta += xAxis.Delta * GetXDir();
+            delta += yAxis.Delta * GetYDir();
+            delta += zAxis.Delta * GetZDir();
         }
         }
 
 
         protected override void Draw()
         protected override void Draw()
         {
         {
+            HandleDrawing.SetTransform(Matrix4.TRS(Position, Rotation, Vector3.one));
+            float handleSize = Handles.GetHandleSize(EditorApplication.SceneViewCamera, position);
+
+            // Draw 1D sliders
+            Vector3 smallCubeExtents = new Vector3(SMALL_CUBE_SIZE*0.5f, SMALL_CUBE_SIZE*0.5f, SMALL_CUBE_SIZE*0.5f);
+            Color axisHover = new Color(0.8f, 0.8f, 0.8f, 1.0f);
+
+            if (xAxis.State == HandleSlider.StateType.Active)
+                HandleDrawing.SetColor(Color.white);
+            else if (xAxis.State == HandleSlider.StateType.Hover)
+                HandleDrawing.SetColor(Color.red * axisHover);
+            else
+                HandleDrawing.SetColor(Color.red);
+
+            Vector3 xCubeOffset = Vector3.xAxis * SMALL_CUBE_SIZE * 0.5f;
+            Vector3 xCubeStart = Vector3.xAxis - xCubeOffset;
+            
+            HandleDrawing.DrawLine(Vector3.zero, xCubeStart, handleSize);
+            HandleDrawing.DrawCube(xCubeStart + xCubeOffset, smallCubeExtents, handleSize);
+
+            if (yAxis.State == HandleSlider.StateType.Active)
+                HandleDrawing.SetColor(Color.white);
+            else if (yAxis.State == HandleSlider.StateType.Hover)
+                HandleDrawing.SetColor(Color.green * axisHover);
+            else
+                HandleDrawing.SetColor(Color.green);
+
+            Vector3 yCubeOffset = Vector3.yAxis * SMALL_CUBE_SIZE * 0.5f;
+            Vector3 yCubeStart = Vector3.yAxis - yCubeOffset;
 
 
+            HandleDrawing.DrawLine(Vector3.zero, yCubeStart, handleSize);
+            HandleDrawing.DrawCube(yCubeStart + yCubeOffset, smallCubeExtents, handleSize);
+
+            if (zAxis.State == HandleSlider.StateType.Active)
+                HandleDrawing.SetColor(Color.white);
+            else if (zAxis.State == HandleSlider.StateType.Hover)
+                HandleDrawing.SetColor(Color.blue * axisHover);
+            else
+                HandleDrawing.SetColor(Color.blue);
+
+            Vector3 zCubeOffset = Vector3.zAxis * SMALL_CUBE_SIZE * 0.5f;
+            Vector3 zCubeStart = Vector3.zAxis - zCubeOffset;
+
+            HandleDrawing.DrawLine(Vector3.zero, zCubeStart, handleSize);
+            HandleDrawing.DrawCube(zCubeStart + zCubeOffset, smallCubeExtents, handleSize);
+
+            // TODO - Draw free scale handle
+        }
+
+        private Vector3 GetXDir()
+        {
+            return rotation.Rotate(Vector3.xAxis);
+        }
+
+        private Vector3 GetYDir()
+        {
+            return rotation.Rotate(Vector3.yAxis);
+        }
+
+        private Vector3 GetZDir()
+        {
+            return rotation.Rotate(Vector3.zAxis);
         }
         }
     }
     }
 }
 }

+ 5 - 5
MBansheeEditor/Scene/SceneCamera.cs

@@ -89,14 +89,14 @@ namespace BansheeEditor
                 Quaternion camRot = yRot * xRot;
                 Quaternion camRot = yRot * xRot;
                 camRot.Normalize();
                 camRot.Normalize();
 
 
-                sceneObject.rotation = camRot;
+                sceneObject.Rotation = camRot;
 		    }
 		    }
 
 
             Vector3 direction = Vector3.zero;
             Vector3 direction = Vector3.zero;
-            if (goingForward) direction += sceneObject.forward;
-            if (goingBack) direction -= sceneObject.forward;
-            if (goingRight) direction += sceneObject.right;
-            if (goingLeft) direction -= sceneObject.right;
+            if (goingForward) direction += sceneObject.Forward;
+            if (goingBack) direction -= sceneObject.Forward;
+            if (goingRight) direction += sceneObject.Right;
+            if (goingLeft) direction -= sceneObject.Right;
 
 
             if (direction.sqrdMagnitude != 0)
             if (direction.sqrdMagnitude != 0)
             {
             {

+ 159 - 6
MBansheeEditor/Scene/SceneWindow.cs

@@ -24,6 +24,20 @@ namespace BansheeEditor
         private GUIToggle rotateButton;
         private GUIToggle rotateButton;
         private GUIToggle scaleButton;
         private GUIToggle scaleButton;
 
 
+        private GUIToggle localCoordButton;
+        private GUIToggle worldCoordButton;
+
+        private GUIToggle pivotButton;
+        private GUIToggle centerButton;
+
+        private GUIToggle moveSnapButton;
+        private GUIFloatField moveSnapInput;
+
+        private GUIToggle rotateSnapButton;
+        private GUIFloatField rotateSnapInput;
+
+        private int editorSettingsHash = int.MaxValue;
+
         public Camera GetCamera()
         public Camera GetCamera()
         {
         {
             return camera;
             return camera;
@@ -37,23 +51,59 @@ namespace BansheeEditor
             mainLayout = GUI.layout.AddLayoutY();
             mainLayout = GUI.layout.AddLayoutY();
 
 
             GUIToggleGroup handlesTG = new GUIToggleGroup();
             GUIToggleGroup handlesTG = new GUIToggleGroup();
-
             viewButton = new GUIToggle("V", handlesTG, EditorStyles.Button);
             viewButton = new GUIToggle("V", handlesTG, EditorStyles.Button);
             moveButton = new GUIToggle("M", handlesTG, EditorStyles.Button);
             moveButton = new GUIToggle("M", handlesTG, EditorStyles.Button);
             rotateButton = new GUIToggle("R", handlesTG, EditorStyles.Button);
             rotateButton = new GUIToggle("R", handlesTG, EditorStyles.Button);
             scaleButton = new GUIToggle("S", handlesTG, EditorStyles.Button);
             scaleButton = new GUIToggle("S", handlesTG, EditorStyles.Button);
 
 
-            viewButton.OnClick += () => EditorApplication.ActiveSceneTool = SceneViewTool.View;
-            moveButton.OnClick += () => EditorApplication.ActiveSceneTool = SceneViewTool.Move;
-            rotateButton.OnClick += () => EditorApplication.ActiveSceneTool = SceneViewTool.Rotate;
-            scaleButton.OnClick += () => EditorApplication.ActiveSceneTool = SceneViewTool.Scale;
+            GUIToggleGroup coordModeTG = new GUIToggleGroup();
+            localCoordButton = new GUIToggle("L", coordModeTG, EditorStyles.Button);
+            worldCoordButton = new GUIToggle("W", coordModeTG, EditorStyles.Button);
+
+            GUIToggleGroup pivotModeTG = new GUIToggleGroup();
+            pivotButton = new GUIToggle("P", pivotModeTG, EditorStyles.Button);
+            centerButton = new GUIToggle("C", pivotModeTG, EditorStyles.Button);
+
+            moveSnapButton = new GUIToggle("MS", EditorStyles.Button);
+            moveSnapInput = new GUIFloatField();
+
+            rotateSnapButton = new GUIToggle("RS", EditorStyles.Button);
+            rotateSnapInput = new GUIFloatField();
+
+            viewButton.OnClick += () => OnSceneToolButtonClicked(SceneViewTool.View);
+            moveButton.OnClick += () => OnSceneToolButtonClicked(SceneViewTool.Move);
+            rotateButton.OnClick += () => OnSceneToolButtonClicked(SceneViewTool.Rotate);
+            scaleButton.OnClick += () => OnSceneToolButtonClicked(SceneViewTool.Scale);
+
+            localCoordButton.OnClick += () => OnCoordinateModeButtonClicked(HandleCoordinateMode.Local);
+            worldCoordButton.OnClick += () => OnCoordinateModeButtonClicked(HandleCoordinateMode.World);
+
+            pivotButton.OnClick += () => OnPivotModeButtonClicked(HandlePivotMode.Pivot);
+            centerButton.OnClick += () => OnPivotModeButtonClicked(HandlePivotMode.Center);
+
+            moveSnapButton.OnToggled += (bool active) => OnMoveSnapToggled(active);
+            moveSnapInput.OnChanged += (float value) => OnMoveSnapValueChanged(value);
+
+            rotateSnapButton.OnToggled += (bool active) => OnRotateSnapToggled(active);
+            rotateSnapInput.OnChanged += (float value) => OnRotateSnapValueChanged(value);
 
 
             GUILayout handlesLayout = mainLayout.AddLayoutX();
             GUILayout handlesLayout = mainLayout.AddLayoutX();
             handlesLayout.AddElement(viewButton);
             handlesLayout.AddElement(viewButton);
             handlesLayout.AddElement(moveButton);
             handlesLayout.AddElement(moveButton);
             handlesLayout.AddElement(rotateButton);
             handlesLayout.AddElement(rotateButton);
             handlesLayout.AddElement(scaleButton);
             handlesLayout.AddElement(scaleButton);
+            handlesLayout.AddSpace(10);
+            handlesLayout.AddElement(localCoordButton);
+            handlesLayout.AddElement(worldCoordButton);
+            handlesLayout.AddSpace(10);
+            handlesLayout.AddElement(pivotButton);
+            handlesLayout.AddElement(centerButton);
             handlesLayout.AddFlexibleSpace();
             handlesLayout.AddFlexibleSpace();
+            handlesLayout.AddElement(moveSnapButton);
+            handlesLayout.AddElement(moveSnapInput);
+            handlesLayout.AddSpace(10);
+            handlesLayout.AddElement(rotateSnapButton);
+            handlesLayout.AddElement(rotateSnapInput);
 
 
             UpdateRenderTexture(Width, Height - HeaderHeight);
             UpdateRenderTexture(Width, Height - HeaderHeight);
         }
         }
@@ -86,6 +136,14 @@ namespace BansheeEditor
 
 
         private void EditorUpdate()
         private void EditorUpdate()
         {
         {
+            // Refresh GUI buttons if needed (in case someones changes the values from script)
+            if (editorSettingsHash != EditorSettings.Hash)
+            {
+                UpdateButtonStates();
+                editorSettingsHash = EditorSettings.Hash;
+            }
+
+            // Update scene view handles and selection
             sceneViewHandler.Update();
             sceneViewHandler.Update();
 
 
             bool handleActive = false;
             bool handleActive = false;
@@ -138,6 +196,101 @@ namespace BansheeEditor
             }
             }
         }
         }
 
 
+        private void OnSceneToolButtonClicked(SceneViewTool tool)
+        {
+            EditorApplication.ActiveSceneTool = tool;
+            editorSettingsHash = EditorSettings.Hash;
+        }
+
+        private void OnCoordinateModeButtonClicked(HandleCoordinateMode mode)
+        {
+            EditorApplication.ActiveCoordinateMode = mode;
+            editorSettingsHash = EditorSettings.Hash;
+        }
+
+        private void OnPivotModeButtonClicked(HandlePivotMode mode)
+        {
+            EditorApplication.ActivePivotMode = mode;
+            editorSettingsHash = EditorSettings.Hash;
+        }
+
+        private void OnMoveSnapToggled(bool active)
+        {
+            Handles.MoveHandleSnapActive = active;
+            editorSettingsHash = EditorSettings.Hash;
+        }
+
+        private void OnMoveSnapValueChanged(float value)
+        {
+            Handles.MoveSnapAmount = MathEx.Clamp(value, 0.01f, 1000.0f);
+            editorSettingsHash = EditorSettings.Hash;
+        }
+
+        private void OnRotateSnapToggled(bool active)
+        {
+            Handles.RotateHandleSnapActive = active;
+            editorSettingsHash = EditorSettings.Hash;
+        }
+
+        private void OnRotateSnapValueChanged(float value)
+        {
+            Handles.RotateSnapAmount = MathEx.Clamp(value, 0.01f, 360.0f);
+            editorSettingsHash = EditorSettings.Hash;
+        }
+
+        private void UpdateButtonStates()
+        {
+            switch (EditorApplication.ActiveSceneTool)
+            {
+                case SceneViewTool.View:
+                    viewButton.ToggleOn();
+                    break;
+                case SceneViewTool.Move:
+                    moveButton.ToggleOn();
+                    break;
+                case SceneViewTool.Rotate:
+                    rotateButton.ToggleOn();
+                    break;
+                case SceneViewTool.Scale:
+                    scaleButton.ToggleOn();
+                    break;
+            }
+
+            switch (EditorApplication.ActiveCoordinateMode)
+            {
+                case HandleCoordinateMode.Local:
+                    localCoordButton.ToggleOn();
+                    break;
+                case HandleCoordinateMode.World:
+                    worldCoordButton.ToggleOn();
+                    break;
+            }
+
+            switch (EditorApplication.ActivePivotMode)
+            {
+                case HandlePivotMode.Center:
+                    centerButton.ToggleOn();
+                    break;
+                case HandlePivotMode.Pivot:
+                    pivotButton.ToggleOn();
+                    break;
+            }
+
+            if (Handles.MoveHandleSnapActive)
+                moveSnapButton.ToggleOn();
+            else
+                moveSnapButton.ToggleOff();
+
+            moveSnapInput.Value = Handles.MoveSnapAmount;
+
+            if (Handles.RotateHandleSnapActive)
+                rotateSnapButton.ToggleOn();
+            else
+                rotateSnapButton.ToggleOff();
+
+            moveSnapInput.Value = Handles.RotateSnapAmount.GetDegrees();
+        }
+
         private void UpdateRenderTexture(int width, int height)
         private void UpdateRenderTexture(int width, int height)
 	    {
 	    {
             width = MathEx.Max(20, width);
             width = MathEx.Max(20, width);
@@ -153,7 +306,7 @@ namespace BansheeEditor
                 camera.target = renderTexture;
                 camera.target = renderTexture;
                 camera.viewportRect = new Rect2(0.0f, 0.0f, 1.0f, 1.0f);
                 camera.viewportRect = new Rect2(0.0f, 0.0f, 1.0f, 1.0f);
 
 
-                sceneCameraSO.position = new Vector3(0, 0.5f, 1);
+                sceneCameraSO.Position = new Vector3(0, 0.5f, 1);
                 sceneCameraSO.LookAt(new Vector3(0, 0, 0));
                 sceneCameraSO.LookAt(new Vector3(0, 0, 0));
 
 
                 camera.priority = 1;
                 camera.priority = 1;

+ 4 - 4
MBansheeEngine/GUI/GUIToggle.cs

@@ -52,12 +52,12 @@ namespace BansheeEngine
 
 
         public void ToggleOn()
         public void ToggleOn()
         {
         {
-            Internal_ToggleOn();
+            Internal_ToggleOn(mCachedPtr);
         }
         }
 
 
         public void ToggleOff()
         public void ToggleOff()
         {
         {
-            Internal_ToggleOff();
+            Internal_ToggleOff(mCachedPtr);
         }
         }
 
 
         private void DoOnClick()
         private void DoOnClick()
@@ -92,9 +92,9 @@ namespace BansheeEngine
         private static extern void Internal_SetContent(IntPtr nativeInstance, GUIContent content);
         private static extern void Internal_SetContent(IntPtr nativeInstance, GUIContent content);
 
 
         [MethodImpl(MethodImplOptions.InternalCall)]
         [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_ToggleOn();
+        private static extern void Internal_ToggleOn(IntPtr nativeInstance);
 
 
         [MethodImpl(MethodImplOptions.InternalCall)]
         [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_ToggleOff();
+        private static extern void Internal_ToggleOff(IntPtr nativeInstance);
     }
     }
 }
 }

+ 8 - 0
MBansheeEngine/Math/Matrix4.cs

@@ -447,6 +447,14 @@ namespace BansheeEngine
                 m30 * v.x + m31 * v.y + m32 * v.z + m33 * v.w);
                 m30 * v.x + m31 * v.y + m32 * v.z + m33 * v.w);
         }
         }
 
 
+        public void SetColumn(int columnIdx, Vector4 column)
+        {
+            this[0, columnIdx] = column.x;
+            this[1, columnIdx] = column.y;
+            this[2, columnIdx] = column.z;
+            this[3, columnIdx] = column.w;
+        }
+
         public static Matrix4 TRS(Vector3 translation, Quaternion rotation, Vector3 scale)
         public static Matrix4 TRS(Vector3 translation, Quaternion rotation, Vector3 scale)
         {
         {
             Matrix3 rot3x3 = rotation.ToRotationMatrix();
             Matrix3 rot3x3 = rotation.ToRotationMatrix();

+ 31 - 0
MBansheeEngine/Math/Vector3.cs

@@ -83,6 +83,11 @@ namespace BansheeEngine
             this.z = z;
             this.z = z;
         }
         }
 
 
+        public static explicit operator Vector4(Vector3 vec)
+        {
+            return new Vector4(vec.x, vec.y, vec.z, 0.0f);
+        }
+
         public static Vector3 operator+ (Vector3 a, Vector3 b)
         public static Vector3 operator+ (Vector3 a, Vector3 b)
         {
         {
             return new Vector3(a.x + b.x, a.y + b.y, a.z + b.z);
             return new Vector3(a.x + b.x, a.y + b.y, a.z + b.z);
@@ -200,5 +205,31 @@ namespace BansheeEngine
         {
         {
             return "(" + x + ", " + y + ", " + z + ")";
             return "(" + x + ", " + y + ", " + z + ")";
         }
         }
+
+        public static void OrthogonalComplement(Vector3 x, out Vector3 y, out Vector3 z)
+        {
+            if (MathEx.Abs(x.x) > MathEx.Abs(x.y))
+                y = new Vector3(-x.z, 0, x.x);
+            else
+                y = new Vector3(0, x.z, -x.y);
+
+            z = Cross(x, y);
+
+            Orthonormalize(ref x, ref y, ref z);
+        }
+
+        public static void Orthonormalize(ref Vector3 x, ref Vector3 y, ref Vector3 z)
+        {
+            x.Normalize();
+
+            float dot0 = Vector3.Dot(x, y);
+            y -= dot0 * x;
+            y.Normalize();
+
+            float dot1 = Vector3.Dot(y, z);
+            dot0 = Vector3.Dot(x, z);
+            z -= dot0 * x + dot1 * y;
+            z.Normalize();
+        }
     }
     }
 }
 }

+ 5 - 0
MBansheeEngine/Math/Vector4.cs

@@ -90,6 +90,11 @@ namespace BansheeEngine
             this.w = w;
             this.w = w;
         }
         }
 
 
+        public static explicit operator Vector3(Vector4 vec)
+        {
+            return new Vector3(vec.x, vec.y, vec.z);
+        }
+
         public static Vector4 operator+ (Vector4 a, Vector4 b)
         public static Vector4 operator+ (Vector4 a, Vector4 b)
         {
         {
             return new Vector4(a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w);
             return new Vector4(a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w);

+ 12 - 12
MBansheeEngine/SceneObject.cs

@@ -5,13 +5,13 @@ namespace BansheeEngine
 {
 {
     public sealed class SceneObject : GameObject
     public sealed class SceneObject : GameObject
     {
     {
-        public SceneObject parent
+        public SceneObject Parent
         {
         {
             set { Internal_SetParent(mCachedPtr, value); }
             set { Internal_SetParent(mCachedPtr, value); }
             get { return Internal_GetParent(mCachedPtr); }
             get { return Internal_GetParent(mCachedPtr); }
         }
         }
 
 
-        public Vector3 position
+        public Vector3 Position
         {
         {
             get
             get
             {
             {
@@ -26,7 +26,7 @@ namespace BansheeEngine
             }
             }
         }
         }
 
 
-        public Vector3 localPosition
+        public Vector3 LocalPosition
         {
         {
             get
             get
             {
             {
@@ -41,7 +41,7 @@ namespace BansheeEngine
             }
             }
         }
         }
 
 
-        public Quaternion rotation
+        public Quaternion Rotation
         {
         {
             get
             get
             {
             {
@@ -56,7 +56,7 @@ namespace BansheeEngine
             }
             }
         }
         }
 
 
-        public Quaternion localRotation
+        public Quaternion LocalRotation
         {
         {
             get
             get
             {
             {
@@ -71,7 +71,7 @@ namespace BansheeEngine
             }
             }
         }
         }
 
 
-        public Vector3 scale
+        public Vector3 Scale
         {
         {
             get
             get
             {
             {
@@ -81,7 +81,7 @@ namespace BansheeEngine
             }
             }
         }
         }
 
 
-        public Vector3 localScale
+        public Vector3 LocalScale
         {
         {
             get
             get
             {
             {
@@ -96,7 +96,7 @@ namespace BansheeEngine
             }
             }
         }
         }
 
 
-        public Matrix4 worldTransform
+        public Matrix4 WorldTransform
         {
         {
             get
             get
             {
             {
@@ -106,7 +106,7 @@ namespace BansheeEngine
             }
             }
         }
         }
 
 
-        public Matrix4 localTransform
+        public Matrix4 LocalTransform
         {
         {
             get
             get
             {
             {
@@ -116,7 +116,7 @@ namespace BansheeEngine
             }
             }
         }
         }
 
 
-        public Vector3 forward
+        public Vector3 Forward
         {
         {
             get
             get
             {
             {
@@ -130,7 +130,7 @@ namespace BansheeEngine
             }
             }
         }
         }
 
 
-        public Vector3 right
+        public Vector3 Right
         {
         {
             get
             get
             {
             {
@@ -140,7 +140,7 @@ namespace BansheeEngine
             }
             }
         }
         }
 
 
-        public Vector3 up
+        public Vector3 Up
         {
         {
             get
             get
             {
             {

+ 7 - 4
SBansheeEditor/Include/BsScriptEditorSettings.h

@@ -17,15 +17,18 @@ namespace BansheeEngine
 		static void internal_SetMoveHandleSnapActive(bool value);
 		static void internal_SetMoveHandleSnapActive(bool value);
 		static bool internal_GetRotateHandleSnapActive();
 		static bool internal_GetRotateHandleSnapActive();
 		static void internal_SetRotateHandleSnapActive(bool value);
 		static void internal_SetRotateHandleSnapActive(bool value);
-		static bool internal_GetScaleHandleSnapActive();
-		static void internal_SetScaleHandleSnapActive(bool value);
 		static float internal_GetMoveHandleSnapAmount();
 		static float internal_GetMoveHandleSnapAmount();
 		static void internal_SetMoveHandleSnapAmount(float value);
 		static void internal_SetMoveHandleSnapAmount(float value);
 		static float internal_GetRotateHandleSnapAmount();
 		static float internal_GetRotateHandleSnapAmount();
 		static void internal_SetRotateHandleSnapAmount(float value);
 		static void internal_SetRotateHandleSnapAmount(float value);
-		static float internal_GetScaleHandleSnapAmount();
-		static void internal_SetScaleHandleSnapAmount(float value);
 		static float internal_GetDefaultHandleSize();
 		static float internal_GetDefaultHandleSize();
 		static void internal_SetDefaultHandleSize(float value);
 		static void internal_SetDefaultHandleSize(float value);
+		static UINT32 internal_GetActiveSceneTool();
+		static void internal_SetActiveSceneTool(UINT32 value);
+		static UINT32 internal_GetActiveCoordinateMode();
+		static void internal_SetActiveCoordinateMode(UINT32 value);
+		static UINT32 internal_GetActivePivotMode();
+		static void internal_SetActivePivotMode(UINT32 value);
+		static UINT32 internal_GetHash();
 	};
 	};
 }
 }

+ 1 - 0
SBansheeEditor/Include/BsScriptHandleSliderDisc.h

@@ -20,6 +20,7 @@ namespace BansheeEngine
 	private:
 	private:
 		static void internal_CreateInstance(MonoObject* instance, Vector3 normal, float radius, bool fixedScale);
 		static void internal_CreateInstance(MonoObject* instance, Vector3 normal, float radius, bool fixedScale);
 		static void internal_GetDelta(ScriptHandleSliderDisc* nativeInstance, float* value);
 		static void internal_GetDelta(ScriptHandleSliderDisc* nativeInstance, float* value);
+		static void internal_GetStartAngle(ScriptHandleSliderDisc* nativeInstance, float* value);
 
 
 		ScriptHandleSliderDisc(MonoObject* instance, const Vector3& normal, float radius, bool fixedScale);
 		ScriptHandleSliderDisc(MonoObject* instance, const Vector3& normal, float radius, bool fixedScale);
 		~ScriptHandleSliderDisc();
 		~ScriptHandleSliderDisc();

+ 45 - 24
SBansheeEditor/Source/BsScriptEditorSettings.cpp

@@ -18,16 +18,19 @@ namespace BansheeEngine
 		metaData.scriptClass->addInternalCall("Internal_SetMoveHandleSnapActive", &ScriptEditorSettings::internal_SetMoveHandleSnapActive);
 		metaData.scriptClass->addInternalCall("Internal_SetMoveHandleSnapActive", &ScriptEditorSettings::internal_SetMoveHandleSnapActive);
 		metaData.scriptClass->addInternalCall("Internal_GetRotateHandleSnapActive", &ScriptEditorSettings::internal_GetRotateHandleSnapActive);
 		metaData.scriptClass->addInternalCall("Internal_GetRotateHandleSnapActive", &ScriptEditorSettings::internal_GetRotateHandleSnapActive);
 		metaData.scriptClass->addInternalCall("Internal_SetRotateHandleSnapActive", &ScriptEditorSettings::internal_SetRotateHandleSnapActive);
 		metaData.scriptClass->addInternalCall("Internal_SetRotateHandleSnapActive", &ScriptEditorSettings::internal_SetRotateHandleSnapActive);
-		metaData.scriptClass->addInternalCall("Internal_GetScaleHandleSnapActive", &ScriptEditorSettings::internal_GetScaleHandleSnapActive);
-		metaData.scriptClass->addInternalCall("Internal_SetScaleHandleSnapActive", &ScriptEditorSettings::internal_SetScaleHandleSnapActive);
 		metaData.scriptClass->addInternalCall("Internal_GetMoveHandleSnapAmount", &ScriptEditorSettings::internal_GetMoveHandleSnapAmount);
 		metaData.scriptClass->addInternalCall("Internal_GetMoveHandleSnapAmount", &ScriptEditorSettings::internal_GetMoveHandleSnapAmount);
 		metaData.scriptClass->addInternalCall("Internal_SetMoveHandleSnapAmount", &ScriptEditorSettings::internal_SetMoveHandleSnapAmount);
 		metaData.scriptClass->addInternalCall("Internal_SetMoveHandleSnapAmount", &ScriptEditorSettings::internal_SetMoveHandleSnapAmount);
 		metaData.scriptClass->addInternalCall("Internal_GetRotateHandleSnapAmount", &ScriptEditorSettings::internal_GetRotateHandleSnapAmount);
 		metaData.scriptClass->addInternalCall("Internal_GetRotateHandleSnapAmount", &ScriptEditorSettings::internal_GetRotateHandleSnapAmount);
 		metaData.scriptClass->addInternalCall("Internal_SetRotateHandleSnapAmount", &ScriptEditorSettings::internal_SetRotateHandleSnapAmount);
 		metaData.scriptClass->addInternalCall("Internal_SetRotateHandleSnapAmount", &ScriptEditorSettings::internal_SetRotateHandleSnapAmount);
-		metaData.scriptClass->addInternalCall("Internal_GetScaleHandleSnapAmount", &ScriptEditorSettings::internal_GetScaleHandleSnapAmount);
-		metaData.scriptClass->addInternalCall("Internal_SetScaleHandleSnapAmount", &ScriptEditorSettings::internal_SetScaleHandleSnapAmount);
 		metaData.scriptClass->addInternalCall("Internal_GetDefaultHandleSize", &ScriptEditorSettings::internal_GetDefaultHandleSize);
 		metaData.scriptClass->addInternalCall("Internal_GetDefaultHandleSize", &ScriptEditorSettings::internal_GetDefaultHandleSize);
 		metaData.scriptClass->addInternalCall("Internal_SetDefaultHandleSize", &ScriptEditorSettings::internal_SetDefaultHandleSize);
 		metaData.scriptClass->addInternalCall("Internal_SetDefaultHandleSize", &ScriptEditorSettings::internal_SetDefaultHandleSize);
+		metaData.scriptClass->addInternalCall("Internal_GetActiveSceneTool", &ScriptEditorSettings::internal_GetActiveSceneTool);
+		metaData.scriptClass->addInternalCall("Internal_SetActiveSceneTool", &ScriptEditorSettings::internal_SetActiveSceneTool);
+		metaData.scriptClass->addInternalCall("Internal_GetActiveCoordinateMode", &ScriptEditorSettings::internal_GetActiveCoordinateMode);
+		metaData.scriptClass->addInternalCall("Internal_SetActiveCoordinateMode", &ScriptEditorSettings::internal_SetActiveCoordinateMode);
+		metaData.scriptClass->addInternalCall("Internal_GetActivePivotMode", &ScriptEditorSettings::internal_GetActivePivotMode);
+		metaData.scriptClass->addInternalCall("Internal_SetActivePivotMode", &ScriptEditorSettings::internal_SetActivePivotMode);
+		metaData.scriptClass->addInternalCall("Internal_GetHash", &ScriptEditorSettings::internal_GetHash);
 	}
 	}
 
 
 	bool ScriptEditorSettings::internal_GetMoveHandleSnapActive()
 	bool ScriptEditorSettings::internal_GetMoveHandleSnapActive()
@@ -54,18 +57,6 @@ namespace BansheeEngine
 		settings->setRotateHandleSnapActive(value);
 		settings->setRotateHandleSnapActive(value);
 	}
 	}
 
 
-	bool ScriptEditorSettings::internal_GetScaleHandleSnapActive()
-	{
-		EditorSettingsPtr settings = gEditorApplication().getEditorSettings();
-		return settings->getScaleHandleSnapActive();
-	}
-
-	void ScriptEditorSettings::internal_SetScaleHandleSnapActive(bool value)
-	{
-		EditorSettingsPtr settings = gEditorApplication().getEditorSettings();
-		settings->setScaleHandleSnapActive(value);
-	}
-
 	float ScriptEditorSettings::internal_GetMoveHandleSnapAmount()
 	float ScriptEditorSettings::internal_GetMoveHandleSnapAmount()
 	{
 	{
 		EditorSettingsPtr settings = gEditorApplication().getEditorSettings();
 		EditorSettingsPtr settings = gEditorApplication().getEditorSettings();
@@ -90,27 +81,57 @@ namespace BansheeEngine
 		settings->setRotationHandleSnap(Degree(value));
 		settings->setRotationHandleSnap(Degree(value));
 	}
 	}
 
 
-	float ScriptEditorSettings::internal_GetScaleHandleSnapAmount()
+	float ScriptEditorSettings::internal_GetDefaultHandleSize()
 	{
 	{
 		EditorSettingsPtr settings = gEditorApplication().getEditorSettings();
 		EditorSettingsPtr settings = gEditorApplication().getEditorSettings();
-		return settings->getScaleHandleSnap();
+		return settings->getHandleSize();
 	}
 	}
 
 
-	void ScriptEditorSettings::internal_SetScaleHandleSnapAmount(float value)
+	void ScriptEditorSettings::internal_SetDefaultHandleSize(float value)
 	{
 	{
 		EditorSettingsPtr settings = gEditorApplication().getEditorSettings();
 		EditorSettingsPtr settings = gEditorApplication().getEditorSettings();
-		settings->setScaleHandleSnap(value);
+		settings->setHandleSize(value);
 	}
 	}
 
 
-	float ScriptEditorSettings::internal_GetDefaultHandleSize()
+	UINT32 ScriptEditorSettings::internal_GetActiveSceneTool()
 	{
 	{
 		EditorSettingsPtr settings = gEditorApplication().getEditorSettings();
 		EditorSettingsPtr settings = gEditorApplication().getEditorSettings();
-		return settings->getHandleSize();
+		return settings->getActiveSceneTool();
 	}
 	}
 
 
-	void ScriptEditorSettings::internal_SetDefaultHandleSize(float value)
+	void ScriptEditorSettings::internal_SetActiveSceneTool(UINT32 value)
 	{
 	{
 		EditorSettingsPtr settings = gEditorApplication().getEditorSettings();
 		EditorSettingsPtr settings = gEditorApplication().getEditorSettings();
-		settings->setHandleSize(value);
+		settings->setActiveSceneTool(value);
+	}
+
+	UINT32 ScriptEditorSettings::internal_GetActiveCoordinateMode()
+	{
+		EditorSettingsPtr settings = gEditorApplication().getEditorSettings();
+		return settings->getActiveCoordinateMode();
+	}
+
+	void ScriptEditorSettings::internal_SetActiveCoordinateMode(UINT32 value)
+	{
+		EditorSettingsPtr settings = gEditorApplication().getEditorSettings();
+		settings->setActiveCoordinateMode(value);
+	}
+
+	UINT32 ScriptEditorSettings::internal_GetActivePivotMode()
+	{
+		EditorSettingsPtr settings = gEditorApplication().getEditorSettings();
+		return settings->getActivePivotMode();
+	}
+
+	void ScriptEditorSettings::internal_SetActivePivotMode(UINT32 value)
+	{
+		EditorSettingsPtr settings = gEditorApplication().getEditorSettings();
+		settings->setActivePivotMode(value);
+	}
+
+	UINT32 ScriptEditorSettings::internal_GetHash()
+	{
+		EditorSettingsPtr settings = gEditorApplication().getEditorSettings();
+		return settings->getHash();
 	}
 	}
 }
 }

+ 7 - 1
SBansheeEditor/Source/BsScriptHandleSliderDisc.cpp

@@ -30,6 +30,7 @@ namespace BansheeEngine
 	{
 	{
 		metaData.scriptClass->addInternalCall("Internal_CreateInstance", &ScriptHandleSliderDisc::internal_CreateInstance);
 		metaData.scriptClass->addInternalCall("Internal_CreateInstance", &ScriptHandleSliderDisc::internal_CreateInstance);
 		metaData.scriptClass->addInternalCall("Internal_GetDelta", &ScriptHandleSliderDisc::internal_GetDelta);
 		metaData.scriptClass->addInternalCall("Internal_GetDelta", &ScriptHandleSliderDisc::internal_GetDelta);
+		metaData.scriptClass->addInternalCall("Internal_GetStartAngle", &ScriptHandleSliderDisc::internal_GetStartAngle);
 	}
 	}
 
 
 	void ScriptHandleSliderDisc::internal_CreateInstance(MonoObject* instance, Vector3 normal, float radius, bool fixedScale)
 	void ScriptHandleSliderDisc::internal_CreateInstance(MonoObject* instance, Vector3 normal, float radius, bool fixedScale)
@@ -40,6 +41,11 @@ namespace BansheeEngine
 
 
 	void ScriptHandleSliderDisc::internal_GetDelta(ScriptHandleSliderDisc* nativeInstance, float* value)
 	void ScriptHandleSliderDisc::internal_GetDelta(ScriptHandleSliderDisc* nativeInstance, float* value)
 	{
 	{
-		*value = nativeInstance->mSlider->getDelta();
+		*value = nativeInstance->mSlider->getDelta().valueDegrees();
+	}
+
+	void ScriptHandleSliderDisc::internal_GetStartAngle(ScriptHandleSliderDisc* nativeInstance, float* value)
+	{
+		*value = nativeInstance->mSlider->getStartAngle().valueDegrees();
 	}
 	}
 }
 }

+ 8 - 4
SBansheeEngine/Source/BsScriptGUIToggle.cpp

@@ -46,7 +46,7 @@ namespace BansheeEngine
 	}
 	}
 
 
 	void ScriptGUIToggle::internal_createInstance(MonoObject* instance, MonoObject* content, 
 	void ScriptGUIToggle::internal_createInstance(MonoObject* instance, MonoObject* content, 
-		MonoObject* toggleGroup, MonoString* style, MonoArray* guiOptions)
+		MonoObject* monoToggleGroup, MonoString* style, MonoArray* guiOptions)
 	{
 	{
 		GUIOptions options;
 		GUIOptions options;
 
 
@@ -55,11 +55,15 @@ namespace BansheeEngine
 			options.addOption(mono_array_get(guiOptions, GUIOption, i));
 			options.addOption(mono_array_get(guiOptions, GUIOption, i));
 
 
 		ScriptGUIToggleGroup* scriptToggleGroup = nullptr;
 		ScriptGUIToggleGroup* scriptToggleGroup = nullptr;
-		if (toggleGroup != nullptr)
-			scriptToggleGroup = ScriptGUIToggleGroup::toNative(toggleGroup);
+		std::shared_ptr<GUIToggleGroup> toggleGroup;
+		if (monoToggleGroup != nullptr)
+		{
+			scriptToggleGroup = ScriptGUIToggleGroup::toNative(monoToggleGroup);
+			toggleGroup = scriptToggleGroup->getInternalValue();
+		}
 
 
 		GUIContent nativeContent(ScriptGUIContent::getText(content), ScriptGUIContent::getImage(content), ScriptGUIContent::getTooltip(content));
 		GUIContent nativeContent(ScriptGUIContent::getText(content), ScriptGUIContent::getImage(content), ScriptGUIContent::getTooltip(content));
-		GUIToggle* guiToggle = GUIToggle::create(nativeContent, scriptToggleGroup->getInternalValue(), options, toString(MonoUtil::monoToWString(style)));
+		GUIToggle* guiToggle = GUIToggle::create(nativeContent, toggleGroup, options, toString(MonoUtil::monoToWString(style)));
 
 
 		guiToggle->onClick.connect(std::bind(&ScriptGUIToggle::onClick, instance));
 		guiToggle->onClick.connect(std::bind(&ScriptGUIToggle::onClick, instance));
 		guiToggle->onHover.connect(std::bind(&ScriptGUIToggle::onHover, instance));
 		guiToggle->onHover.connect(std::bind(&ScriptGUIToggle::onHover, instance));

+ 13 - 7
TODO.txt

@@ -1,7 +1,6 @@
 --------- ALL LONG TERM TASKS / FIXES BELONG TO GOOGLE DOCS: ImplementationTODO OR PossibleImprovements ----------
 --------- ALL LONG TERM TASKS / FIXES BELONG TO GOOGLE DOCS: ImplementationTODO OR PossibleImprovements ----------
 
 
 Do a cleanup pass on the editor? Fix the annoying little issues:
 Do a cleanup pass on the editor? Fix the annoying little issues:
- - When GUIToggle is initialy toggled the texture is missing
  - Switching between button states seem to cause 1 frame of no texture for the gui element
  - Switching between button states seem to cause 1 frame of no texture for the gui element
  - Much more I can't think of right now
  - Much more I can't think of right now
 
 
@@ -12,14 +11,21 @@ Possibly set up automatic refresh in debug mode after initialization? As an ad-h
 
 
 <<<<<<Handles>>>>>>>>
 <<<<<<Handles>>>>>>>>
 
 
-When active handle in EditorApplication changes externally, update the GUI button in scene view
-Save/load active handle tool (it should also probably persist assembly refresh)
+Add free rotate handle
+Add free scale handle
 
 
-Movement of plane (and possible line) sliders might need tweaking
- - Move handle was moving object in the opposite direction at one point
- - It also seems to move too slow
-Need to update ShapeMeshes3D::solidQuad to render both sides of the quad
+Rotate handle:
+ - Transparent angle start is at the wrong position
+ - Red arc is on the wrong side when viewed from above
+ - Missing two free rotate arcs
 
 
+Cursor wrap only works when cursor moves really slowly over the border, and even then it's spotty
+When changing handle types they do not refresh until you click on the scene view
+
+The first time I mouse over a GUI button it flashes for a frame as if it has no texture
+ - It seems that the ParamBlockBuffer for the vertex shader gets updated one frame too late
+ - First frame it is set to all zeroes, but fragment data seems valid (both the param block and texture/sampler)
+ - Then syncToCore() happens next frame and data is updated.
 
 
 <<<<Multi-resource saving>>>>:
 <<<<Multi-resource saving>>>>:
  - Modify Font so it doesn't contain a texture, but instead keeps a handle to it
  - Modify Font so it doesn't contain a texture, but instead keeps a handle to it