Преглед на файлове

Properly handling input for handle sliders from multiple cameras
Properly handling rendering of handles from multiple cameras
GUI render textures can now have transparent background

BearishSun преди 10 години
родител
ревизия
0e5e1e9c99

+ 486 - 484
BansheeEditor/Include/BsGizmoManager.h

@@ -1,485 +1,487 @@
-#pragma once
-
-#include "BsEditorPrerequisites.h"
-#include "BsModule.h"
-#include "BsColor.h"
-#include "BsVector2I.h"
-#include "BsMatrix4.h"
-#include "BsGpuParam.h"
-
-namespace BansheeEngine
-{
-	class GizmoManagerCore;
-
-	/**
-	 * @brief	Handles the rendering and picking of gizmo elements. Gizmos are icons and 3D objects
-	 *			usually rendered in scene view for various visualization purposes (e.g. a Camera component
-	 *			will have a gizmo that draws a Camera icon since otherwise it has no visual representation).
-	 *			Aside from being rendered, gizmos can also be selected by the user as if they were normal
-	 *			scene elements.
-	 */
-	class BS_ED_EXPORT GizmoManager : public Module<GizmoManager>
-	{
-	public:
-		GizmoManager();
-		~GizmoManager();
-
-		/**
-		 * @brief	Starts gizmo creation. All further call will be referencing this gizmo. 
-		 *			Must be followed by a matching "endGizmo".
-		 *
-		 * @note	gizmoParent	Scene object this gizmo is attached to. Selecting the gizmo will
-		 *			select this scene object.
-		 */
-		void startGizmo(const HSceneObject& gizmoParent);
-
-		/**
-		 * @brief	Ends gizmo creation. Must be called after a matching "startGizmo".
-		 */
-		void endGizmo();
-
-		/**
-		 * @brief	Changes the color of any further gizmo draw calls. 
-		 */
-		void setColor(const Color& color);
-
-		/**
-		 * @brief	Changes the transform that will be applied to meshes of any further gizmo draw calls. 
-		 */
-		void setTransform(const Matrix4& transform);
-
-		/**
-		 * @brief	If pickable is set to true, gizmo can be selected by the user, otherwise it will be
-		 *			drawn but cannot be interacted with.
-		 *
-		 * @note	Must be called between startGizmo/endGizmo calls.
-		 */
-		void setPickable(bool pickable) { mPickable = pickable; }
-
-		/**
-		 * @brief	Returns the currently set gizmo color.
-		 */
-		Color getColor() const { return mColor; }
-
-		/**
-		 * @brief	Returns the currently set gizmo transform.
-		 */
-		Matrix4 getTransform() const { return mTransform; }
-
-		/**
-		 * @brief	Draws an axis aligned cuboid.
-		 *
-		 * @param	position	Center of the cuboid.
-		 * @param	extents		Radius of the cuboid in each axis.
-		 *
-		 * @note	Must be called between startGizmo/endGizmo calls.
-		 */
-		void drawCube(const Vector3& position, const Vector3& extents);
-
-		/**
-		 * @brief	Draws a sphere.
-		 *
-		 * @note	Must be called between startGizmo/endGizmo calls.
-		 */
-		void drawSphere(const Vector3& position, float radius);
-
-		/**
-		 * @brief	Draws a wireframe axis aligned cuboid.
-		 *
-		 * @param	position	Center of the cuboid.
-		 * @param	extents		Radius of the cuboid in each axis.
-		 *
-		 * @note	Must be called between startGizmo/endGizmo calls.
-		 */
-		void drawWireCube(const Vector3& position, const Vector3& extents);
-
-		/**
-		 * @brief	Draws a wireframe sphere represented by three discs.
-		 *
-		 * @note	Must be called between startGizmo/endGizmo calls.
-		 */
-		void drawWireSphere(const Vector3& position, float radius);
-
-		/**
-		 * @brief	Draws a line between two points.
-		 *
-		 * @note	Must be called between startGizmo/endGizmo calls.
-		 */
-		void drawLine(const Vector3& start, const Vector3& end);
-
-		/**
-		 * @brief	Draws a wireframe frustum.
-		 *
-		 * @param	position	Origin of the frustum, or the eye point.
-		 * @param	aspect		Ratio of frustum width over frustum height.
-		 * @param	FOV			Horizontal field of view in degrees.
-		 * @param	near		Distance to the near frustum plane.
-		 * @param	far			Distance to the far frustum plane.
-		 *
-		 * @note	Must be called between startGizmo/endGizmo calls.
-		 */
-		void drawFrustum(const Vector3& position, float aspect, Degree FOV, float near, float far);
-
-		/**
-		 * @brief	Draws an icon that always faces the camera.
-		 *
-		 * @param	position	Position of the center of the icon.
-		 * @param	image		Sprite image for the icon to draw.
-		 * @param	fixedScale	If true then the icon will remain the same size
-		 *						regardless of the distance from camera.
-		 *
-		 * @note	Must be called between startGizmo/endGizmo calls.
-		 */
-		void drawIcon(Vector3 position, HSpriteTexture image, bool fixedScale);
-
-		/**
-		 * @brief	Updates all the gizmo meshes to reflect all draw calls submitted since "clearGizmos".
-		 *
-		 * @note	Internal method.
-		 */
-		void update(const CameraPtr& camera);
-
-		/**
-		 * @brief	Queues all gizmos to be rendered for picking. Each gizmo is draw with a separate
-		 *			color so we can identify them later.
-		 *
-		 * @param	camera				Camera to draw the gizmos on.
-		 * @param	idxToColorCallback	Callback that assigns a unique color to each gizmo index.
-		 *
-		 * @note	Internal method.
-		 */
-		void renderForPicking(const CameraPtr& camera, std::function<Color(UINT32)> idxToColorCallback);
-
-		/**
-		 * @brief	Clears all gizmo data, but doesn't update the meshes
-		 *			or the render data. (Calling update would create empty
-		 *			meshes, but before calling update gizmos will still be drawn).
-		 */
-		void clearGizmos();
-
-		/**
-		 * @brief	Clears gizmo render data like meshes, but doesn't clear the original gizmo data.
-		 *			(Calling update would just recreate the render data).
-		 */
-		void clearRenderData();
-
-		/**
-		 * @brief	Returns a scene object that was attached to a specific gizmo.
-		 *
-		 * @param	gizmoIdx	Index of the gizmo to look for.
-		 */
-		HSceneObject getSceneObject(UINT32 gizmoIdx);
-
-	private:
-		friend class GizmoManagerCore;
-
-		/**
-		 * @brief	Supported types of gizmo materials (i.e. shaders)
-		 */
-		enum class GizmoMaterial
-		{
-			Solid, Wire, Picking
-		};
-
-		/**
-		 * @brief	Common data shared by all gizmo types.
-		 */
-		struct CommonData
-		{
-			UINT32 idx;
-			Color color;
-			Matrix4 transform;
-			HSceneObject sceneObject;
-			bool pickable;
-		};
-
-		/**
-		 * @brief	Data required for rendering a cuboid gizmo.
-		 */
-		struct CubeData : public CommonData
-		{
-			Vector3 position;
-			Vector3 extents;
-		};
-
-		/**
-		 * @brief	Data required for rendering a sphere gizmo.
-		 */
-		struct SphereData : public CommonData
-		{
-			Vector3 position;
-			float radius;
-		};
-
-		/**
-		 * @brief	Data required for rendering a line gizmo.
-		 */
-		struct LineData : public CommonData
-		{
-			Vector3 start;
-			Vector3 end;
-		};
-
-		/**
-		 * @brief	Data required for rendering a frustum gizmo.
-		 */
-		struct FrustumData : public CommonData
-		{
-			Vector3 position;
-			float aspect;
-			Degree FOV;
-			float near;
-			float far;
-		};
-
-		/**
-		 * @brief	Data required for rendering an icon gizmo.
-		 */
-		struct IconData : public CommonData
-		{
-			Vector3 position;
-			bool fixedScale;
-			HSpriteTexture texture;
-		};
-
-		/**
-		 * @brief	Stores how many icons use a specific texture.
-		 */
-		struct IconRenderData
-		{
-			UINT32 count;
-			SPtr<TextureCore> texture;
-		};
-
-		/**
-		 * @brief	Data used for initializing the core thread equivalent of the gizmo manager.
-		 */
-		struct CoreInitData
-		{
-			SPtr<MaterialCore> solidMat;
-			SPtr<MaterialCore> wireMat;
-			SPtr<MaterialCore> iconMat;
-			SPtr<MaterialCore> pickingMat;
-			SPtr<MaterialCore> alphaPickingMat;
-		};
-
-		typedef Vector<IconRenderData> IconRenderDataVec;
-		typedef std::shared_ptr<IconRenderDataVec> IconRenderDataVecPtr;
-
-		/**
-		 * @brief	Builds a brand new mesh that can be used for rendering all icon gizmos.
-		 *
-		 * @param	camera		Camera the mesh will be rendered to.
-		 * @param	iconData	A list of all icons and their properties.
-		 * @param	forPicking	Whether the icons will be rendered normally, or with a special material for picking.
-		 * @param	renderData	Output data that outlines the structure of the returned mesh. It tells us which portions of the
-		 *						mesh use which icon texture.
-		 *
-		 * @returns	A mesh containing all of the visible icons. Mesh is allocated using the icon mesh heap and should be deallocated manually.
-		 */
-		TransientMeshPtr buildIconMesh(const CameraPtr& camera, const Vector<IconData>& iconData, bool forPicking, IconRenderDataVecPtr& renderData);
-
-		/**
-		 * @brief	Resizes the icon width/height so it is always scaled to optimal size (with preserved aspect).
-		 */
-		void limitIconSize(UINT32& width, UINT32& height);
-
-		/**
-		 * @brief	Calculates colors for an icon based on its position in the camera. e.g. icons too close to too far might be faded.
-		 *
-		 * @param	tint		Primary tint for the icon.
-		 * @param	camera		Camera in which the icon will be rendered in.
-		 * @param	iconHeight	Height of the icon in pixels.
-		 * @param	fixedScale	Whether the icon size changes depending on distance from the camera.
-		 * @param	normalColor	Normal color of the icon.
-		 * @param	fadedColor	Faded color to be used when icon is occluded by geometry.
-		 */
-		void calculateIconColors(const Color& tint, const CameraPtr& camera, UINT32 iconHeight, bool fixedScale,
-			Color& normalColor, Color& fadedColor);
-
-		/**
-		 * @brief	Initializes the core thread version of the gizmo manager.
-		 */
-		void initializeCore(const CoreInitData& initData);
-
-		/**
-		 * @brief	Destroys the core thread version of the gizmo manager.
-		 */
-		void destroyCore(GizmoManagerCore* core);
-
-		static const UINT32 VERTEX_BUFFER_GROWTH;
-		static const UINT32 INDEX_BUFFER_GROWTH;
-		static const UINT32 SPHERE_QUALITY;
-		static const UINT32 WIRE_SPHERE_QUALITY;
-		static const float MAX_ICON_RANGE;
-		static const UINT32 OPTIMAL_ICON_SIZE;
-		static const float ICON_TEXEL_WORLD_SIZE;
-
-		typedef Set<IconData, std::function<bool(const IconData&, const IconData&)>> IconSet;
-
-		Color mColor;
-		Matrix4 mTransform;
-		HSceneObject mActiveSO;
-		bool mPickable;
-		UINT32 mCurrentIdx;
-
-		DrawHelper* mDrawHelper;
-		DrawHelper* mPickingDrawHelper;
-
-		Vector<CubeData> mSolidCubeData;
-		Vector<CubeData> mWireCubeData;
-		Vector<SphereData> mSolidSphereData;
-		Vector<SphereData> mWireSphereData;
-		Vector<LineData> mLineData;
-		Vector<FrustumData> mFrustumData;
-		Vector<IconData> mIconData;
-		Map<UINT32, HSceneObject> mIdxToSceneObjectMap;
-
-		MeshHeapPtr mIconMeshHeap;
-
-		TransientMeshPtr mIconMesh;
-
-		std::atomic<GizmoManagerCore*> mCore;
-
-		// Immutable
-		VertexDataDescPtr mIconVertexDesc;
-
-		// Transient
-		struct SortedIconData
-		{
-			float distance;
-			Vector2I screenPosition;
-			UINT32 iconIdx;
-		};
-
-		Vector<SortedIconData> mSortedIconData;
-	};
-
-	/**
-	 * @brief	Core thread version of the gizmo manager that handles most of the rendering
-	 *			of meshes provided by the gizmo manager.
-	 */
-	class GizmoManagerCore
-	{
-		friend class GizmoManager;
-
-		/**
-		 * @brief	Solid gizmo material and parameter handles.
-		 */
-		struct SolidMaterialData
-		{
-			SPtr<MaterialCore> mat;
-			GpuParamMat4Core mViewProj;
-			GpuParamVec4Core mViewDir;
-		};
-
-		/**
-		 * @brief	Wire gizmo material and parameter handles.
-		 */
-		struct WireMaterialData
-		{
-			SPtr<MaterialCore> mat;
-			GpuParamMat4Core mViewProj;
-		};
-
-		/**
-		 * @brief	Icon gizmo material and parameter handles.
-		 */
-		struct IconMaterialData
-		{
-			SPtr<MaterialCore> mat;
-			SPtr<GpuParamsCore> mFragParams[2];
-			GpuParamMat4Core mViewProj[2];
-			GpuParamTextureCore mTexture[2];
-		};
-
-		/**
-		 * @brief	Gizmo material and parameter handles used for picking.
-		 */
-		struct PickingMaterialData
-		{
-			SPtr<MaterialCore> mat;
-			GpuParamMat4Core mViewProj;
-		};
-
-		/**
-		 * @brief	Gizmo material and parameter handles used for picking, with
-		 *			blending support (generally used for icon picking).
-		 */
-		struct AlphaPickingMaterialData
-		{
-			SPtr<MaterialCore> mat;
-			SPtr<GpuParamsCore> mFragParams;
-			GpuParamMat4Core mViewProj;
-			GpuParamTextureCore mTexture;
-		};
-
-		struct PrivatelyConstuct { };
-
-	public:
-		GizmoManagerCore(const PrivatelyConstuct& dummy);
-		~GizmoManagerCore();
-
-	private:
-		/**
-		 * @brief	Initializes the core gizmo manager. Must be called right after creation.
-		 */
-		void initialize(const GizmoManager::CoreInitData& initData);
-
-		/**
-		 * @brief	Renders all gizmos in the parent camera.
-		 */
-		void render();
-
-		/**
-		 * @brief	Renders a non-icon gizmo mesh using the provided parameters.
-		 *
-		 * @param	viewMatrix	View matrix of the camera we are rendering with.
-		 * @param	projMatrix	Projection matrix of the camera we are rendering with.
-		 * @param	viewDir		View direction of the camera we are rendering with.
-		 * @param	mesh		Mesh to render. This is normally the solid or wireframe gizmo mesh.
-		 * @param	material	Material to use for rendering. This is normally the solid, wireframe or picking material.
-		 */
-		void renderGizmos(Matrix4 viewMatrix, Matrix4 projMatrix, Vector3 viewDir, SPtr<MeshCoreBase> mesh, GizmoManager::GizmoMaterial material);
-
-		/**
-		 * @brief	Renders the icon gizmo mesh using the provided parameters.
-		 *
-		 * @param	screenArea			Area of the viewport to render the gizmos in, in pixels.
-		 * @param	mesh				Mesh containing the icons.
-		 * @param	renderData			Icon render data outlining which parts of the icon mesh use which textures.
-		 * @param	usePickingMaterial	Should the icons be rendered normally or for picking.
-		 */
-		void renderIconGizmos(Rect2I screenArea, SPtr<MeshCoreBase> mesh, GizmoManager::IconRenderDataVecPtr renderData, bool usePickingMaterial);
-
-		/**
-		 * @brief	Updates the internal data that is used for rendering. Normally you would call this after 
-		 *			updating the camera or meshes on the sim thread.
-		 *
-		 * @param	camera			Sets the camera all rendering will be performed to.
-		 * @param	solidMesh		Mesh containing solid gizmos.
-		 * @param	wireMesh		Mesh containing wireframe gizmos.
-		 * @param	iconMesh		Mesh containing icon meshes.
-		 * @param	iconRenderData	Icon render data outlining which parts of the icon mesh use which textures.
-		 */
-		void updateData(const SPtr<CameraCore>& camera, const SPtr<MeshCoreBase>& solidMesh, const SPtr<MeshCoreBase>& wireMesh,
-			const SPtr<MeshCoreBase>& iconMesh, const GizmoManager::IconRenderDataVecPtr& iconRenderData);
-
-		static const float PICKING_ALPHA_CUTOFF;
-
-		SPtr<CameraCore> mCamera;
-
-		SPtr<MeshCoreBase> mSolidMesh;
-		SPtr<MeshCoreBase> mWireMesh;
-		SPtr<MeshCoreBase> mIconMesh;
-		GizmoManager::IconRenderDataVecPtr mIconRenderData;
-
-		// Immutable
-		SolidMaterialData mSolidMaterial;
-		WireMaterialData mWireMaterial;
-		IconMaterialData mIconMaterial;
-
-		PickingMaterialData mPickingMaterial;
-		AlphaPickingMaterialData mAlphaPickingMaterial;
-	};
+#pragma once
+
+#include "BsEditorPrerequisites.h"
+#include "BsModule.h"
+#include "BsColor.h"
+#include "BsVector2I.h"
+#include "BsMatrix4.h"
+#include "BsGpuParam.h"
+#include "BsDrawHelper.h"
+
+namespace BansheeEngine
+{
+	class GizmoManagerCore;
+
+	/**
+	 * @brief	Handles the rendering and picking of gizmo elements. Gizmos are icons and 3D objects
+	 *			usually rendered in scene view for various visualization purposes (e.g. a Camera component
+	 *			will have a gizmo that draws a Camera icon since otherwise it has no visual representation).
+	 *			Aside from being rendered, gizmos can also be selected by the user as if they were normal
+	 *			scene elements.
+	 */
+	class BS_ED_EXPORT GizmoManager : public Module<GizmoManager>
+	{
+	public:
+		GizmoManager();
+		~GizmoManager();
+
+		/**
+		 * @brief	Starts gizmo creation. All further call will be referencing this gizmo. 
+		 *			Must be followed by a matching "endGizmo".
+		 *
+		 * @note	gizmoParent	Scene object this gizmo is attached to. Selecting the gizmo will
+		 *			select this scene object.
+		 */
+		void startGizmo(const HSceneObject& gizmoParent);
+
+		/**
+		 * @brief	Ends gizmo creation. Must be called after a matching "startGizmo".
+		 */
+		void endGizmo();
+
+		/**
+		 * @brief	Changes the color of any further gizmo draw calls. 
+		 */
+		void setColor(const Color& color);
+
+		/**
+		 * @brief	Changes the transform that will be applied to meshes of any further gizmo draw calls. 
+		 */
+		void setTransform(const Matrix4& transform);
+
+		/**
+		 * @brief	If pickable is set to true, gizmo can be selected by the user, otherwise it will be
+		 *			drawn but cannot be interacted with.
+		 *
+		 * @note	Must be called between startGizmo/endGizmo calls.
+		 */
+		void setPickable(bool pickable) { mPickable = pickable; }
+
+		/**
+		 * @brief	Returns the currently set gizmo color.
+		 */
+		Color getColor() const { return mColor; }
+
+		/**
+		 * @brief	Returns the currently set gizmo transform.
+		 */
+		Matrix4 getTransform() const { return mTransform; }
+
+		/**
+		 * @brief	Draws an axis aligned cuboid.
+		 *
+		 * @param	position	Center of the cuboid.
+		 * @param	extents		Radius of the cuboid in each axis.
+		 *
+		 * @note	Must be called between startGizmo/endGizmo calls.
+		 */
+		void drawCube(const Vector3& position, const Vector3& extents);
+
+		/**
+		 * @brief	Draws a sphere.
+		 *
+		 * @note	Must be called between startGizmo/endGizmo calls.
+		 */
+		void drawSphere(const Vector3& position, float radius);
+
+		/**
+		 * @brief	Draws a wireframe axis aligned cuboid.
+		 *
+		 * @param	position	Center of the cuboid.
+		 * @param	extents		Radius of the cuboid in each axis.
+		 *
+		 * @note	Must be called between startGizmo/endGizmo calls.
+		 */
+		void drawWireCube(const Vector3& position, const Vector3& extents);
+
+		/**
+		 * @brief	Draws a wireframe sphere represented by three discs.
+		 *
+		 * @note	Must be called between startGizmo/endGizmo calls.
+		 */
+		void drawWireSphere(const Vector3& position, float radius);
+
+		/**
+		 * @brief	Draws a line between two points.
+		 *
+		 * @note	Must be called between startGizmo/endGizmo calls.
+		 */
+		void drawLine(const Vector3& start, const Vector3& end);
+
+		/**
+		 * @brief	Draws a wireframe frustum.
+		 *
+		 * @param	position	Origin of the frustum, or the eye point.
+		 * @param	aspect		Ratio of frustum width over frustum height.
+		 * @param	FOV			Horizontal field of view in degrees.
+		 * @param	near		Distance to the near frustum plane.
+		 * @param	far			Distance to the far frustum plane.
+		 *
+		 * @note	Must be called between startGizmo/endGizmo calls.
+		 */
+		void drawFrustum(const Vector3& position, float aspect, Degree FOV, float near, float far);
+
+		/**
+		 * @brief	Draws an icon that always faces the camera.
+		 *
+		 * @param	position	Position of the center of the icon.
+		 * @param	image		Sprite image for the icon to draw.
+		 * @param	fixedScale	If true then the icon will remain the same size
+		 *						regardless of the distance from camera.
+		 *
+		 * @note	Must be called between startGizmo/endGizmo calls.
+		 */
+		void drawIcon(Vector3 position, HSpriteTexture image, bool fixedScale);
+
+		/**
+		 * @brief	Updates all the gizmo meshes to reflect all draw calls submitted since "clearGizmos".
+		 *
+		 * @note	Internal method.
+		 */
+		void update(const CameraPtr& camera);
+
+		/**
+		 * @brief	Queues all gizmos to be rendered for picking. Each gizmo is draw with a separate
+		 *			color so we can identify them later.
+		 *
+		 * @param	camera				Camera to draw the gizmos on.
+		 * @param	idxToColorCallback	Callback that assigns a unique color to each gizmo index.
+		 *
+		 * @note	Internal method.
+		 */
+		void renderForPicking(const CameraPtr& camera, std::function<Color(UINT32)> idxToColorCallback);
+
+		/**
+		 * @brief	Clears all gizmo data, but doesn't update the meshes
+		 *			or the render data. (Calling update would create empty
+		 *			meshes, but before calling update gizmos will still be drawn).
+		 */
+		void clearGizmos();
+
+		/**
+		 * @brief	Clears gizmo render data like meshes, but doesn't clear the original gizmo data.
+		 *			(Calling update would just recreate the render data).
+		 */
+		void clearRenderData();
+
+		/**
+		 * @brief	Returns a scene object that was attached to a specific gizmo.
+		 *
+		 * @param	gizmoIdx	Index of the gizmo to look for.
+		 */
+		HSceneObject getSceneObject(UINT32 gizmoIdx);
+
+	private:
+		friend class GizmoManagerCore;
+
+		/**
+		 * @brief	Supported types of gizmo materials (i.e. shaders)
+		 */
+		enum class GizmoMaterial
+		{
+			Solid, Wire, Picking
+		};
+
+		/**
+		 * @brief	Common data shared by all gizmo types.
+		 */
+		struct CommonData
+		{
+			UINT32 idx;
+			Color color;
+			Matrix4 transform;
+			HSceneObject sceneObject;
+			bool pickable;
+		};
+
+		/**
+		 * @brief	Data required for rendering a cuboid gizmo.
+		 */
+		struct CubeData : public CommonData
+		{
+			Vector3 position;
+			Vector3 extents;
+		};
+
+		/**
+		 * @brief	Data required for rendering a sphere gizmo.
+		 */
+		struct SphereData : public CommonData
+		{
+			Vector3 position;
+			float radius;
+		};
+
+		/**
+		 * @brief	Data required for rendering a line gizmo.
+		 */
+		struct LineData : public CommonData
+		{
+			Vector3 start;
+			Vector3 end;
+		};
+
+		/**
+		 * @brief	Data required for rendering a frustum gizmo.
+		 */
+		struct FrustumData : public CommonData
+		{
+			Vector3 position;
+			float aspect;
+			Degree FOV;
+			float near;
+			float far;
+		};
+
+		/**
+		 * @brief	Data required for rendering an icon gizmo.
+		 */
+		struct IconData : public CommonData
+		{
+			Vector3 position;
+			bool fixedScale;
+			HSpriteTexture texture;
+		};
+
+		/**
+		 * @brief	Stores how many icons use a specific texture.
+		 */
+		struct IconRenderData
+		{
+			UINT32 count;
+			SPtr<TextureCore> texture;
+		};
+
+		/**
+		 * @brief	Data used for initializing the core thread equivalent of the gizmo manager.
+		 */
+		struct CoreInitData
+		{
+			SPtr<MaterialCore> solidMat;
+			SPtr<MaterialCore> wireMat;
+			SPtr<MaterialCore> iconMat;
+			SPtr<MaterialCore> pickingMat;
+			SPtr<MaterialCore> alphaPickingMat;
+		};
+
+		typedef Vector<IconRenderData> IconRenderDataVec;
+		typedef std::shared_ptr<IconRenderDataVec> IconRenderDataVecPtr;
+
+		/**
+		 * @brief	Builds a brand new mesh that can be used for rendering all icon gizmos.
+		 *
+		 * @param	camera		Camera the mesh will be rendered to.
+		 * @param	iconData	A list of all icons and their properties.
+		 * @param	forPicking	Whether the icons will be rendered normally, or with a special material for picking.
+		 * @param	renderData	Output data that outlines the structure of the returned mesh. It tells us which portions of the
+		 *						mesh use which icon texture.
+		 *
+		 * @returns	A mesh containing all of the visible icons. Mesh is allocated using the icon mesh heap and should be deallocated manually.
+		 */
+		TransientMeshPtr buildIconMesh(const CameraPtr& camera, const Vector<IconData>& iconData, bool forPicking, IconRenderDataVecPtr& renderData);
+
+		/**
+		 * @brief	Resizes the icon width/height so it is always scaled to optimal size (with preserved aspect).
+		 */
+		void limitIconSize(UINT32& width, UINT32& height);
+
+		/**
+		 * @brief	Calculates colors for an icon based on its position in the camera. e.g. icons too close to too far might be faded.
+		 *
+		 * @param	tint		Primary tint for the icon.
+		 * @param	camera		Camera in which the icon will be rendered in.
+		 * @param	iconHeight	Height of the icon in pixels.
+		 * @param	fixedScale	Whether the icon size changes depending on distance from the camera.
+		 * @param	normalColor	Normal color of the icon.
+		 * @param	fadedColor	Faded color to be used when icon is occluded by geometry.
+		 */
+		void calculateIconColors(const Color& tint, const CameraPtr& camera, UINT32 iconHeight, bool fixedScale,
+			Color& normalColor, Color& fadedColor);
+
+		/**
+		 * @brief	Initializes the core thread version of the gizmo manager.
+		 */
+		void initializeCore(const CoreInitData& initData);
+
+		/**
+		 * @brief	Destroys the core thread version of the gizmo manager.
+		 */
+		void destroyCore(GizmoManagerCore* core);
+
+		static const UINT32 VERTEX_BUFFER_GROWTH;
+		static const UINT32 INDEX_BUFFER_GROWTH;
+		static const UINT32 SPHERE_QUALITY;
+		static const UINT32 WIRE_SPHERE_QUALITY;
+		static const float MAX_ICON_RANGE;
+		static const UINT32 OPTIMAL_ICON_SIZE;
+		static const float ICON_TEXEL_WORLD_SIZE;
+
+		typedef Set<IconData, std::function<bool(const IconData&, const IconData&)>> IconSet;
+
+		Color mColor;
+		Matrix4 mTransform;
+		HSceneObject mActiveSO;
+		bool mPickable;
+		UINT32 mCurrentIdx;
+
+		DrawHelper* mDrawHelper;
+		DrawHelper* mPickingDrawHelper;
+
+		Vector<CubeData> mSolidCubeData;
+		Vector<CubeData> mWireCubeData;
+		Vector<SphereData> mSolidSphereData;
+		Vector<SphereData> mWireSphereData;
+		Vector<LineData> mLineData;
+		Vector<FrustumData> mFrustumData;
+		Vector<IconData> mIconData;
+		Map<UINT32, HSceneObject> mIdxToSceneObjectMap;
+
+		Vector<DrawHelper::ShapeMeshData> mActiveMeshes;
+
+		MeshHeapPtr mIconMeshHeap;
+		TransientMeshPtr mIconMesh;
+
+		std::atomic<GizmoManagerCore*> mCore;
+
+		// Immutable
+		VertexDataDescPtr mIconVertexDesc;
+
+		// Transient
+		struct SortedIconData
+		{
+			float distance;
+			Vector2I screenPosition;
+			UINT32 iconIdx;
+		};
+
+		Vector<SortedIconData> mSortedIconData;
+	};
+
+	/**
+	 * @brief	Core thread version of the gizmo manager that handles most of the rendering
+	 *			of meshes provided by the gizmo manager.
+	 */
+	class GizmoManagerCore
+	{
+		friend class GizmoManager;
+
+		/**
+		 * @brief	Solid gizmo material and parameter handles.
+		 */
+		struct SolidMaterialData
+		{
+			SPtr<MaterialCore> mat;
+			GpuParamMat4Core mViewProj;
+			GpuParamVec4Core mViewDir;
+		};
+
+		/**
+		 * @brief	Wire gizmo material and parameter handles.
+		 */
+		struct WireMaterialData
+		{
+			SPtr<MaterialCore> mat;
+			GpuParamMat4Core mViewProj;
+		};
+
+		/**
+		 * @brief	Icon gizmo material and parameter handles.
+		 */
+		struct IconMaterialData
+		{
+			SPtr<MaterialCore> mat;
+			SPtr<GpuParamsCore> mFragParams[2];
+			GpuParamMat4Core mViewProj[2];
+			GpuParamTextureCore mTexture[2];
+		};
+
+		/**
+		 * @brief	Gizmo material and parameter handles used for picking.
+		 */
+		struct PickingMaterialData
+		{
+			SPtr<MaterialCore> mat;
+			GpuParamMat4Core mViewProj;
+		};
+
+		/**
+		 * @brief	Gizmo material and parameter handles used for picking, with
+		 *			blending support (generally used for icon picking).
+		 */
+		struct AlphaPickingMaterialData
+		{
+			SPtr<MaterialCore> mat;
+			SPtr<GpuParamsCore> mFragParams;
+			GpuParamMat4Core mViewProj;
+			GpuParamTextureCore mTexture;
+		};
+
+		struct PrivatelyConstuct { };
+
+	public:
+		GizmoManagerCore(const PrivatelyConstuct& dummy);
+		~GizmoManagerCore();
+
+	private:
+		/**
+		 * @brief	Initializes the core gizmo manager. Must be called right after creation.
+		 */
+		void initialize(const GizmoManager::CoreInitData& initData);
+
+		/**
+		 * @brief	Renders all gizmos in the parent camera.
+		 */
+		void render();
+
+		/**
+		 * @brief	Renders a non-icon gizmo mesh using the provided parameters.
+		 *
+		 * @param	viewMatrix	View matrix of the camera we are rendering with.
+		 * @param	projMatrix	Projection matrix of the camera we are rendering with.
+		 * @param	viewDir		View direction of the camera we are rendering with.
+		 * @param	mesh		Mesh to render. This is normally the solid or wireframe gizmo mesh.
+		 * @param	material	Material to use for rendering. This is normally the solid, wireframe or picking material.
+		 */
+		void renderGizmos(Matrix4 viewMatrix, Matrix4 projMatrix, Vector3 viewDir, SPtr<MeshCoreBase> mesh, GizmoManager::GizmoMaterial material);
+
+		/**
+		 * @brief	Renders the icon gizmo mesh using the provided parameters.
+		 *
+		 * @param	screenArea			Area of the viewport to render the gizmos in, in pixels.
+		 * @param	mesh				Mesh containing the icons.
+		 * @param	renderData			Icon render data outlining which parts of the icon mesh use which textures.
+		 * @param	usePickingMaterial	Should the icons be rendered normally or for picking.
+		 */
+		void renderIconGizmos(Rect2I screenArea, SPtr<MeshCoreBase> mesh, GizmoManager::IconRenderDataVecPtr renderData, bool usePickingMaterial);
+
+		/**
+		 * @brief	Updates the internal data that is used for rendering. Normally you would call this after 
+		 *			updating the camera or meshes on the sim thread.
+		 *
+		 * @param	camera			Sets the camera all rendering will be performed to.
+		 * @param	solidMesh		Mesh containing solid gizmos.
+		 * @param	wireMesh		Mesh containing wireframe gizmos.
+		 * @param	iconMesh		Mesh containing icon meshes.
+		 * @param	iconRenderData	Icon render data outlining which parts of the icon mesh use which textures.
+		 */
+		void updateData(const SPtr<CameraCore>& camera, const SPtr<MeshCoreBase>& solidMesh, const SPtr<MeshCoreBase>& wireMesh,
+			const SPtr<MeshCoreBase>& iconMesh, const GizmoManager::IconRenderDataVecPtr& iconRenderData);
+
+		static const float PICKING_ALPHA_CUTOFF;
+
+		SPtr<CameraCore> mCamera;
+
+		SPtr<MeshCoreBase> mSolidMesh;
+		SPtr<MeshCoreBase> mWireMesh;
+		SPtr<MeshCoreBase> mIconMesh;
+		GizmoManager::IconRenderDataVecPtr mIconRenderData;
+
+		// Immutable
+		SolidMaterialData mSolidMaterial;
+		WireMaterialData mWireMaterial;
+		IconMaterialData mIconMaterial;
+
+		PickingMaterialData mPickingMaterial;
+		AlphaPickingMaterialData mAlphaPickingMaterial;
+	};
 }

+ 36 - 37
BansheeEditor/Include/BsHandleDrawManager.h

@@ -2,6 +2,7 @@
 
 #include "BsEditorPrerequisites.h"
 #include "BsGpuParams.h"
+#include "BsDrawHelper.h"
 
 namespace BansheeEngine
 {
@@ -145,47 +146,45 @@ namespace BansheeEngine
 		 */
 		void drawRect(const Rect3& area, float size = 1.0f);
 
-		/**
-		 * @brief	Queues all the handle draw commands executed so far for rendering. All commands
-		 *			are cleared and will need to be called again to draw them again.
-		 */
+		/**	Queues all the handle draw commands queued since the last call to clear() for rendering. */
 		void draw(const CameraPtr& camera);
 
+		/** Clears all handle draw commands. */
+		void clear();
+
 	private:
 		friend class HandleDrawManagerCore;
 
 		/**
-		 * @brief	Initializes the core thread portion of the draw manager.
+		 * Initializes the core thread portion of the draw manager.
 		 *
-		 * @param	wireMat		Material used for drawing the wireframe objects.
-		 * @param	solidMat	Material used for drawing the solid objects.
+		 * @param[in]	wireMat		Material used for drawing the wireframe objects.
+		 * @param[in]	solidMat	Material used for drawing the solid objects.
 		 */
 		void initializeCore(const SPtr<MaterialCore>& wireMat, const SPtr<MaterialCore>& solidMat);
 
-		/**
-		 * @brief	Destroys the core thread portion of the draw manager.
-		 */
+		/** Destroys the core thread portion of the draw manager. */
 		void destroyCore(HandleDrawManagerCore* core);
 
+		/** Destroys all meshes allocated since the last call to this method. */
+		void clearMeshes();
+
 		static const UINT32 SPHERE_QUALITY;
 		static const UINT32 WIRE_SPHERE_QUALITY;
 		static const UINT32 ARC_QUALITY;
 
+		Vector<Vector<DrawHelper::ShapeMeshData>> mActiveMeshes;
+		UINT64 mLastFrameIdx;
+
 		Matrix4 mTransform;
 		std::atomic<HandleDrawManagerCore*> mCore;
 		DrawHelper* mDrawHelper;
 	};
 
-	/**
-	 * @brief	Core thread specific portion of the HandleDrawManager that
-	 *			handles actual rendering.
-	 */
+	/** Core thread specific portion of the HandleDrawManager that handles actual rendering. */
 	class BS_ED_EXPORT HandleDrawManagerCore
 	{
-		/**
-		 * @brief	Contains information about the material used for 
-		 *			drawing solid objects and its parameters.
-		 */
+		/** Contains information about the material used for drawing solid objects and its parameters. */
 		struct SolidMaterialData
 		{
 			SPtr<MaterialCore> mat;
@@ -193,27 +192,20 @@ namespace BansheeEngine
 			GpuParamVec4Core mViewDir;
 		};
 
-		/**
-		 * @brief	Contains information about the material used for 
-		 *			drawing wireframe objects and its parameters.
-		 */
+		/**	Contains information about the material used for drawing wireframe objects and its parameters. */
 		struct WireMaterialData
 		{
 			SPtr<MaterialCore> mat;
 			GpuParamMat4Core mViewProj;
 		};
 
-		/**
-		 * @brief	Type of mesh that can be drawn.
-		 */
+		/** Type of mesh that can be drawn. */
 		enum class MeshType
 		{
 			Solid, Wire
 		};
 
-		/**
-		 * @brief	Contains data about a render mesh.
-		 */
+		/** Data about a mesh rendered by the draw manager. */
 		struct MeshData
 		{
 			MeshData(const SPtr<MeshCoreBase>& mesh, MeshType type)
@@ -224,6 +216,13 @@ namespace BansheeEngine
 			MeshType type;
 		};
 
+		/** Data about a camera and the meshes that are queued for rendering on it */
+		struct QueuedData
+		{
+			SPtr<CameraCore> camera;
+			Vector<MeshData> meshes;
+		};
+
 		struct PrivatelyConstruct { };
 
 	public:
@@ -234,7 +233,7 @@ namespace BansheeEngine
 		friend class HandleDrawManager;
 
 		/**
-		 * @brief	Initializes the object. Must be called right after construction.
+		 * Initializes the object. Must be called right after construction.
 		 *
 		 * @param	wireMat		Material used for drawing the wireframe objects.
 		 * @param	solidMat	Material used for drawing the solid objects.
@@ -242,20 +241,20 @@ namespace BansheeEngine
 		void initialize(const SPtr<MaterialCore>& wireMat, const SPtr<MaterialCore>& solidMat);
 
 		/**
-		 * @brief	Updates the data that will be used for rendering the new frame.
+		 * Queues new data for rendering.
 		 *
 		 * @param	camera	Camera to render to.
 		 * @param	meshes	Meshes to render.
 		 */
-		void updateData(const SPtr<CameraCore>& camera, const Vector<MeshData>& meshes);
+		void queueForDraw(const SPtr<CameraCore>& camera, const Vector<MeshData>& meshes);
 
-		/**
-		 * @brief	Callback triggered by the renderer. Draws the stored meshes.
-		 */
-		void render();
+		/** Deletes any meshes queued for rendering. */
+		void clearQueued();
+
+		/** Callback triggered by the renderer. Draws all queued meshes. */
+		void render(UINT32 queuedDataIdx);
 
-		SPtr<CameraCore> mCamera;
-		Vector<MeshData> mMeshes;
+		Vector<QueuedData> mQueuedData;
 
 		// Immutable
 		SolidMaterialData mSolidMaterial;

+ 43 - 54
BansheeEditor/Include/BsHandleManager.h

@@ -6,110 +6,99 @@
 
 namespace BansheeEngine
 {
-	/**
-	 * @brief	The central place for interacting with and drawing handles.
-	 */
+	/** The central place for interacting with and drawing handles. */
 	class BS_ED_EXPORT HandleManager : public Module<HandleManager>
 	{
 	public:
 		HandleManager();
 		virtual ~HandleManager();
 
+		/** 
+		 * Triggers handle pre-input callbacks. Must be called before all updateInput() calls and followed by endInput(). 
+		 * This should be called once per frame.
+		 */
+		void beginInput();
+
 		/**
-		 * To be called every frame. Updates interactable handle sliders based on provided input.
+		 * To be called every frame. Updates interactable handle sliders based on provided input. Make sure to call 
+		 * beginInput() before this method, followed by endInput() when done.
 		 *
-		 * @param	camera		Camera that the input positions are relative to.
-		 * @param	inputPos	Position of the pointer, relative to the provided camera viewport.
-		 * @param	inputDelta	Determines pointer movement since last call to this method.
+		 * @param[in]	camera		Camera that the input positions are relative to.
+		 * @param[in]	inputPos	Position of the pointer, relative to the provided camera viewport.
+		 * @param[in]	inputDelta	Determines pointer movement since last call to this method.
 		 */
 		void updateInput(const CameraPtr& camera, const Vector2I& inputPos, const Vector2I& inputDelta);
 
+		/** 
+		 * Triggers handle post-input callbacks. Must be called after all updateInput() calls and after beginInput().
+		 * This should be called once per frame.
+		 */
+		void endInput();
+
 		/**
 		 * To be called every frame. Queues handles for drawing.
 		 *
-		 * @param	camera		Camera to draw the handles to.
+		 * @param[in]	camera		Camera to draw the handles to.
 		 */
 		void draw(const CameraPtr& camera);
 
 		/**
-		 * @brief	Select a handle slider at the specified location, if there is any under the pointer. Makes
-		 *			the selected slider active and draggable.
+		 * Select a handle slider at the specified location, if there is any under the pointer. Makes the selected slider 
+		 * active and draggable.
 		 *
-		 * @param	camera		Camera that the input positions are relative to, and destination to draw the handles to.
-		 * @param	inputPos	Position of the pointer, relative to the provided camera viewport.
+		 * @param[in]	camera		Camera that the input positions are relative to, and destination to draw the handles to.
+		 * @param[in]	inputPos	Position of the pointer, relative to the provided camera viewport.
 		 */
 		void trySelect(const CameraPtr& camera, const Vector2I& inputPos);
 
-		/**
-		 * @brief	Clears the currently selected/active handle slider.
-		 */
-		void clearSelection();
+		/**	Clears the currently selected/active handle slider for the specified camera. */
+		void clearSelection(const CameraPtr& camera);
 
-		/**
-		 * @brief	Is any handle slider selected/active.
-		 */
-		bool isHandleActive() const;
+		/**	Is any handle slider selected/active on the specified camera. */
+		bool isHandleActive(const CameraPtr& camera) const;
 
-		/**
-		 * @brief	Returns the manager that can be used for interacting with handle sliders.
-		 */
+		/** Returns the manager that can be used for interacting with handle sliders. */
 		HandleSliderManager& getSliderManager() const { return *mSliderManager; }
 
-		/**
-		 * @brief	Returns the manager that can be used for drawing handle geometry.
-		 */
+		/** Returns the manager that can be used for drawing handle geometry. */
 		HandleDrawManager& getDrawManager() const { return *mDrawManager; }
 
-		/**
-		 * @brief	Returns the uniform size for a handle rendered in @p camera, at the world
-		 *			position @p handlePos. The handles will be scaled so that they appear
-		 *			the same size regardless of distance from camera.
+		/**	
+		 * Returns the uniform size for a handle rendered in @p camera, at the world position @p handlePos. The handles 
+		 * will be scaled so that they appear the same size regardless of distance from camera.
 		 */
 		float getHandleSize(const CameraPtr& camera, const Vector3& handlePos) const;
 
-		/**
-		 * @brief	Sets the default handle size. This controls the uniform scale returned from
-		 *			::getHandleSize method.
-		 */
+		/** Sets the default handle size. This controls the uniform scale returned from getHandleSize() method. */
 		void setDefaultHandleSize(float value) { mDefaultHandleSize = value; }
 
-		/**
-		 * @brief	Sets editor settings that will be used for controlling various 
-		 *			handle behaviour.
-		 */
+		/** Sets editor settings that will be used for controlling various handle behaviour. */
 		void setSettings(const EditorSettingsPtr& settings);
 
 	protected:
-		/**
-		 * @brief	Updates the internal properties from editor settings.
-		 */
+		/** Updates the internal properties from editor settings. */
 		void updateFromEditorSettings();
 
-		/**
-		 * @brief	Called during handle update. Allows handle sliders to be created or 
-		 *			destroyed before any input is handled.
-		 */
-		virtual void refreshHandles() = 0;
+		/** Called during handle update. Allows handle sliders to be created or destroyed before any input is handled. */
+		virtual void triggerPreInput() = 0;
 
 		/**
-		 * @brief	Called during handle update after handle input is processed.
-		 *			Allows implementation to respond to delta values calculated in sliders
-		 *			due to input.
+		 * Called during handle update after handle input is processed. Allows implementation to respond to delta values 
+		 * calculated in sliders due to input.
 		 */
-		virtual void triggerHandles() = 0;
+		virtual void triggerPostInput() = 0;
 
-		/**
-		 * @brief	Called during handle update. Allows implementation to
-		 *			queue handle draw commands.
-		 */
+		/** Called during handle update. Allows implementation to queue handle draw commands. */
 		virtual void queueDrawCommands() = 0;
 
 		HandleSliderManager* mSliderManager;
 		HandleDrawManager* mDrawManager;
 
 		float mDefaultHandleSize = 20.0f;
+		bool mInputStarted;
 
 		EditorSettingsPtr mSettings;
 		UINT32 mSettingsHash;
+		UINT64 mLastDrawFrameIdx;
 	};
 }

+ 27 - 35
BansheeEditor/Include/BsHandleSliderManager.h

@@ -4,67 +4,59 @@
 
 namespace BansheeEngine
 {
-	/**
-	 * @brief	Controls all instantiated HandleSlider%s.
-	 */
+	/** Controls all instantiated HandleSlider%s. */
 	class BS_ED_EXPORT HandleSliderManager
 	{
-	public:
-		HandleSliderManager();
-		~HandleSliderManager();
+		/** Contains active/hover sliders for each camera. */
+		struct StatePerCamera
+		{
+			HandleSlider* activeSlider = nullptr;
+			HandleSlider* hoverSlider = nullptr;
+		};
 
+	public:
 		/**
-		 * @brief	Updates all underlying sliders, changing their state and dragging them depending
-		 *			on their state and pointer movement.
+		 * Updates all underlying sliders, changing their state and dragging them depending on their state and pointer 
+		 * movement.
 		 *
-		 * @param	camera		Camera through which we're interacting with sliders.
-		 * @param	inputPos	Position of the pointer.
-		 * @param	inputDelta	Movement of the pointer since last frame.
+		 * @param[in]	camera		Camera through which we're interacting with sliders.
+		 * @param[in]	inputPos	Position of the pointer.
+		 * @param[in]	inputDelta	Movement of the pointer since last frame.
 		 */
 		void update(const CameraPtr& camera, const Vector2I& inputPos, const Vector2I& inputDelta);
 
 		/**
-		 * @brief	Attempts to select (activate) a slider at the specified position (if there is any).
+		 * Attempts to select (activate) a slider at the specified position.
 		 *
-		 * @param	camera		Camera through which we're interacting with sliders.
-		 * @param	inputPos	Position of the pointer.
+		 * @param[in]	camera		Camera through which we're interacting with sliders.
+		 * @param[in]	inputPos	Position of the pointer.
 		 */
 		void trySelect(const CameraPtr& camera, const Vector2I& inputPos);
 
-		/**
-		 * @brief	Clears the active slider (deactivates it).
-		 */
-		void clearSelection();
+		/** Clears the active slider (deactivates it) for the specified camera. */
+		void clearSelection(const CameraPtr& camera);
 
-		/**
-		 * @brief	Checks is any slider active.
-		 */
-		bool isSliderActive() const { return mActiveSlider != nullptr; }
+		/** Checks is any slider active for the specified camera. */
+		bool isSliderActive(const CameraPtr& camera) const;
 
-		/**
-		 * @brief	Registers a new instantiated slider.
-		 */
+		/** Registers a new instantiated slider. */
 		void _registerSlider(HandleSlider* slider);
 
-		/**
-		 * @brief	Unregisters a previously instantiated slider.
-		 */
+		/**	Unregisters a previously instantiated slider. */
 		void _unregisterSlider(HandleSlider* slider);
 
 	private:
 
 		/**
-		 * @brief	Attempts to find slider at the specified position.
-		 *
-		 * @param	camera		Camera through which we're interacting with sliders.
-		 * @param	inputPos	Position of the pointer.
+		 * Attempts to find slider at the specified position.
 		 *
-		 * @return	Slider if we're intersecting with one, or null otherwise.
+		 * @param[in]	camera		Camera through which we're interacting with sliders.
+		 * @param[in]	inputPos	Position of the pointer.
+		 * @return					Slider if we're intersecting with one, or null otherwise.
 		 */
 		HandleSlider* findUnderCursor(const CameraPtr& camera, const Vector2I& inputPos) const;
 
-		HandleSlider* mActiveSlider;
-		HandleSlider* mHoverSlider;
+		UnorderedMap<UINT64, StatePerCamera> mStates;
 		UnorderedSet<HandleSlider*> mSliders;
 	};
 }

+ 11 - 6
BansheeEditor/Source/BsGizmoManager.cpp

@@ -66,6 +66,9 @@ namespace BansheeEngine
 
 	GizmoManager::~GizmoManager()
 	{
+		mDrawHelper->clearMeshes(mActiveMeshes);
+		mActiveMeshes.clear();
+
 		if (mIconMesh != nullptr)
 			mIconMeshHeap->dealloc(mIconMesh);
 
@@ -231,7 +234,8 @@ namespace BansheeEngine
 
 	void GizmoManager::update(const CameraPtr& camera)
 	{
-		mDrawHelper->clearMeshes();
+		mDrawHelper->clearMeshes(mActiveMeshes);
+		mActiveMeshes.clear();
 
 		if (mIconMesh != nullptr)
 			mIconMeshHeap->dealloc(mIconMesh);
@@ -239,11 +243,11 @@ namespace BansheeEngine
 		IconRenderDataVecPtr iconRenderData;
 
 		mDrawHelper->buildMeshes();
-		const Vector<DrawHelper::ShapeMeshData>& meshes = mDrawHelper->getMeshes();
+		mActiveMeshes = mDrawHelper->getMeshes();
 
 		SPtr<MeshCoreBase> solidMesh = nullptr;
 		SPtr<MeshCoreBase> wireMesh = nullptr;
-		for (auto& meshData : meshes)
+		for (auto& meshData : mActiveMeshes)
 		{
 			if (meshData.type == DrawHelper::MeshType::Solid)
 			{
@@ -259,7 +263,7 @@ namespace BansheeEngine
 
 		// Since there is no sorting used with draw helper meshes we only expect up to two of them,
 		// one for solids, one for wireframe
-		assert(meshes.size() <= 2);
+		assert(mActiveMeshes.size() <= 2);
 
 		mIconMesh = buildIconMesh(camera, mIconData, false, iconRenderData);
 		SPtr<MeshCoreBase> iconMesh = mIconMesh->getCore();
@@ -384,7 +388,7 @@ namespace BansheeEngine
 		gCoreAccessor().queueCommand(std::bind(&GizmoManagerCore::renderIconGizmos,
 			core, screenArea, iconMesh->getCore(), iconRenderData, true));
 
-		mPickingDrawHelper->clearMeshes();
+		mPickingDrawHelper->clearMeshes(meshes);
 		mIconMeshHeap->dealloc(iconMesh);
 	}
 
@@ -406,7 +410,8 @@ namespace BansheeEngine
 
 	void GizmoManager::clearRenderData()
 	{
-		mDrawHelper->clearMeshes();
+		mDrawHelper->clearMeshes(mActiveMeshes);
+		mActiveMeshes.clear();
 
 		if (mIconMesh != nullptr)
 			mIconMeshHeap->dealloc(mIconMesh);

+ 55 - 29
BansheeEditor/Source/BsHandleDrawManager.cpp

@@ -9,6 +9,7 @@
 #include "BsCamera.h"
 #include "BsRendererUtility.h"
 #include "BsSceneObject.h"
+#include "BsTime.h"
 
 using namespace std::placeholders;
 
@@ -19,7 +20,7 @@ namespace BansheeEngine
 	const UINT32 HandleDrawManager::ARC_QUALITY = 10;
 
 	HandleDrawManager::HandleDrawManager()
-		:mCore(nullptr)
+		:mCore(nullptr), mLastFrameIdx((UINT64)-1)
 	{
 		mTransform = Matrix4::IDENTITY;
 		mDrawHelper = bs_new<DrawHelper>();
@@ -37,6 +38,7 @@ namespace BansheeEngine
 
 	HandleDrawManager::~HandleDrawManager()
 	{
+		clearMeshes();
 		bs_delete(mDrawHelper);
 
 		gCoreAccessor().queueCommand(std::bind(&HandleDrawManager::destroyCore, this, mCore.load(std::memory_order_relaxed)));
@@ -161,11 +163,23 @@ namespace BansheeEngine
 
 	void HandleDrawManager::draw(const CameraPtr& camera)
 	{
-		mDrawHelper->clearMeshes();
+		HandleDrawManagerCore* core = mCore.load(std::memory_order_relaxed);
+
+		// Clear meshes from previous frame
+		UINT64 frameIdx = gTime().getFrameIdx();
+		if(frameIdx != mLastFrameIdx)
+		{
+			gCoreAccessor().queueCommand(std::bind(&HandleDrawManagerCore::clearQueued, core));
+
+			clearMeshes();
+			mLastFrameIdx = frameIdx;
+		}
+
 		mDrawHelper->buildMeshes(DrawHelper::SortType::BackToFront, camera->getPosition(), camera->getLayers());
 
 		const Vector<DrawHelper::ShapeMeshData>& meshes = mDrawHelper->getMeshes();
-		
+		mActiveMeshes.push_back(meshes);
+
 		Vector<HandleDrawManagerCore::MeshData> proxyData;
 		for (auto& meshData : meshes)
 		{
@@ -181,19 +195,25 @@ namespace BansheeEngine
 			}
 		}
 
-		HandleDrawManagerCore* core = mCore.load(std::memory_order_relaxed);
-
-		gCoreAccessor().queueCommand(std::bind(&HandleDrawManagerCore::updateData, core,
-			camera->getCore(), proxyData));
+		gCoreAccessor().queueCommand(std::bind(&HandleDrawManagerCore::queueForDraw, core, camera->getCore(), proxyData));
+	}
 
+	void HandleDrawManager::clear()
+	{
 		mDrawHelper->clear();
 	}
 
+	void HandleDrawManager::clearMeshes()
+	{
+		for (auto entry : mActiveMeshes)
+			mDrawHelper->clearMeshes(entry);
+
+		mActiveMeshes.clear();
+	}
+
 	HandleDrawManagerCore::~HandleDrawManagerCore()
 	{
-		CoreRendererPtr activeRenderer = RendererManager::instance().getActive();
-		if (mCamera != nullptr)
-			activeRenderer->_unregisterRenderCallback(mCamera.get(), 20);
+		clearQueued();
 	}
 
 	void HandleDrawManagerCore::initialize(const SPtr<MaterialCore>& wireMat, const SPtr<MaterialCore>& solidMat)
@@ -215,35 +235,41 @@ namespace BansheeEngine
 		}
 	}
 
-	void HandleDrawManagerCore::updateData(const SPtr<CameraCore>& camera, const Vector<MeshData>& meshes)
+	void HandleDrawManagerCore::queueForDraw(const SPtr<CameraCore>& camera, const Vector<MeshData>& meshes)
 	{
-		if (mCamera != camera)
+		CoreRendererPtr activeRenderer = RendererManager::instance().getActive();
+		if (camera != nullptr)
 		{
-			CoreRendererPtr activeRenderer = RendererManager::instance().getActive();
-			if (mCamera != nullptr)
-				activeRenderer->_unregisterRenderCallback(mCamera.get(), 20);
+			UINT32 idx = (UINT32)mQueuedData.size();
+			mQueuedData.push_back({ camera, meshes });
 
-			if (camera != nullptr)
-				activeRenderer->_registerRenderCallback(camera.get(), 20, std::bind(&HandleDrawManagerCore::render, this));
+			activeRenderer->_registerRenderCallback(camera.get(), 20, std::bind(&HandleDrawManagerCore::render, this, idx));
 		}
+	}
 
-		mCamera = camera;
-		mMeshes = meshes;
+	void HandleDrawManagerCore::clearQueued()
+	{
+		CoreRendererPtr activeRenderer = RendererManager::instance().getActive();
+		for (auto& entry : mQueuedData)
+			activeRenderer->_unregisterRenderCallback(entry.camera.get(), 20);
+
+		mQueuedData.clear();
 	}
 
-	void HandleDrawManagerCore::render()
+	void HandleDrawManagerCore::render(UINT32 queuedDataIdx)
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
-		if (mCamera == nullptr)
-			return;
+		const QueuedData& queueData = mQueuedData[queuedDataIdx];
+		SPtr<CameraCore> camera = queueData.camera;
+		const Vector<MeshData>& meshes = queueData.meshes;
 
-		SPtr<RenderTargetCore> renderTarget = mCamera->getViewport()->getTarget();
+		SPtr<RenderTargetCore> renderTarget = camera->getViewport()->getTarget();
 
 		float width = (float)renderTarget->getProperties().getWidth();
 		float height = (float)renderTarget->getProperties().getHeight();
 
-		Rect2 normArea = mCamera->getViewport()->getNormArea();
+		Rect2 normArea = camera->getViewport()->getNormArea();
 
 		Rect2I screenArea;
 		screenArea.x = (int)(normArea.x * width);
@@ -251,15 +277,15 @@ namespace BansheeEngine
 		screenArea.width = (int)(normArea.width * width);
 		screenArea.height = (int)(normArea.height * height);
 
-		Matrix4 viewProjMat = mCamera->getProjectionMatrixRS() * mCamera->getViewMatrix();
+		Matrix4 viewProjMat = camera->getProjectionMatrixRS() * camera->getViewMatrix();
 		mSolidMaterial.mViewProj.set(viewProjMat);
-		mSolidMaterial.mViewDir.set((Vector4)mCamera->getForward());
+		mSolidMaterial.mViewDir.set((Vector4)camera->getForward());
 		mWireMaterial.mViewProj.set(viewProjMat);
 
 		MeshType currentType = MeshType::Solid;
-		if (mMeshes.size() > 0)
+		if (meshes.size() > 0)
 		{
-			currentType = mMeshes[0].type;
+			currentType = meshes[0].type;
 
 			if (currentType == MeshType::Solid)
 				gRendererUtility().setPass(mSolidMaterial.mat, 0);
@@ -267,7 +293,7 @@ namespace BansheeEngine
 				gRendererUtility().setPass(mWireMaterial.mat, 0);
 		}
 
-		for (auto& meshData : mMeshes)
+		for (auto& meshData : meshes)
 		{
 			if (currentType != meshData.type)
 			{

+ 33 - 8
BansheeEditor/Source/BsHandleManager.cpp

@@ -4,11 +4,13 @@
 #include "BsCCamera.h"
 #include "BsSceneObject.h"
 #include "BsEditorSettings.h"
+#include "BsTime.h"
 
 namespace BansheeEngine
 {
 	HandleManager::HandleManager()
-		:mSliderManager(nullptr), mDrawManager(nullptr), mSettingsHash(0xFFFFFFFF)
+		:mSliderManager(nullptr), mDrawManager(nullptr), mSettingsHash(0xFFFFFFFF),
+		mLastDrawFrameIdx((UINT64)-1), mInputStarted(false)
 	{
 		mSliderManager = bs_new<HandleSliderManager>();
 		mDrawManager = bs_new<HandleDrawManager>();
@@ -20,24 +22,47 @@ namespace BansheeEngine
 		bs_delete(mDrawManager);
 	}
 
-	bool HandleManager::isHandleActive() const
+	bool HandleManager::isHandleActive(const CameraPtr& camera) const
 	{
-		return mSliderManager->isSliderActive();
+		return mSliderManager->isSliderActive(camera);
+	}
+
+	void HandleManager::beginInput()
+	{
+		triggerPreInput();
+		mInputStarted = true;
 	}
 
 	void HandleManager::updateInput(const CameraPtr& camera, const Vector2I& inputPos, const Vector2I& inputDelta)
 	{
+		if(!mInputStarted)
+		{
+			LOGWRN("Updating handle input without calling beginInput() first. Input won't be processed.");
+			return;
+		}
+
 		if (mSettings != nullptr && mSettingsHash != mSettings->getHash())
 			updateFromEditorSettings();
 
-		refreshHandles();
 		mSliderManager->update(camera, inputPos, inputDelta);
-		triggerHandles();
+	}
+
+	void HandleManager::endInput()
+	{
+		triggerPostInput();
+		mInputStarted = false;
 	}
 
 	void HandleManager::draw(const CameraPtr& camera)
 	{
-		queueDrawCommands();
+		UINT64 frameIdx = gTime().getFrameIdx();
+		if (frameIdx != mLastDrawFrameIdx)
+		{
+			mDrawManager->clear();
+			queueDrawCommands();
+			mLastDrawFrameIdx = frameIdx;
+		}
+
 		mDrawManager->draw(camera);
 	}
 
@@ -60,9 +85,9 @@ namespace BansheeEngine
 		return mSliderManager->trySelect(camera, inputPos);
 	}
 
-	void HandleManager::clearSelection()
+	void HandleManager::clearSelection(const CameraPtr& camera)
 	{
-		return mSliderManager->clearSelection();
+		return mSliderManager->clearSelection(camera);
 	}
 
 	float HandleManager::getHandleSize(const CameraPtr& camera, const Vector3& handlePos) const

+ 49 - 43
BansheeEditor/Source/BsHandleSliderManager.cpp

@@ -1,11 +1,5 @@
 #include "BsHandleSliderManager.h"
-#include "BsDrawHelper.h"
-#include "BsMaterial.h"
 #include "BsBuiltinEditorResources.h"
-#include "BsCoreThread.h"
-#include "BsRendererManager.h"
-#include "BsCoreRenderer.h"
-#include "BsTransientMesh.h"
 #include "BsCCamera.h"
 #include "BsHandleSlider.h"
 
@@ -13,42 +7,40 @@ using namespace std::placeholders;
 
 namespace BansheeEngine
 {
-	HandleSliderManager::HandleSliderManager()
-		:mActiveSlider(nullptr), mHoverSlider(nullptr)
-	{
-
-	}
-
-	HandleSliderManager::~HandleSliderManager()
-	{
-
-	}
-
 	void HandleSliderManager::update(const CameraPtr& camera, const Vector2I& inputPos, const Vector2I& inputDelta)
 	{
 		for (auto& slider : mSliders)
-			slider->update(camera);
+		{
+			bool layerMatches = (camera->getLayers() & slider->getLayer()) != 0;
 
-		if (mActiveSlider != nullptr)
+			if(layerMatches)
+				slider->update(camera);
+		}
+
+		StatePerCamera& state = mStates[camera->getInternalID()];
+		if (state.activeSlider != nullptr)
 		{
-			mActiveSlider->handleInput(camera, inputDelta);
+			bool layerMatches = (camera->getLayers() & state.activeSlider->getLayer()) != 0;
+
+			if (layerMatches)
+				state.activeSlider->handleInput(camera, inputDelta);
 		}
 		else
 		{
 			HandleSlider* newHoverSlider = findUnderCursor(camera, inputPos);
 
-			if (newHoverSlider != mHoverSlider)
+			if (newHoverSlider != state.hoverSlider)
 			{
-				if (mHoverSlider != nullptr)
+				if (state.hoverSlider != nullptr)
 				{
-					mHoverSlider->setInactive();
-					mHoverSlider = nullptr;
+					state.hoverSlider->setInactive();
+					state.hoverSlider = nullptr;
 				}
 
 				if (newHoverSlider != nullptr)
 				{
-					mHoverSlider = newHoverSlider;
-					mHoverSlider->setHover();
+					state.hoverSlider = newHoverSlider;
+					state.hoverSlider->setHover();
 				}
 			}
 		}
@@ -58,34 +50,45 @@ namespace BansheeEngine
 	{
 		HandleSlider* newActiveSlider = findUnderCursor(camera, inputPos);
 
-		if (mHoverSlider != nullptr)
+		StatePerCamera& state = mStates[camera->getInternalID()];
+		if (state.hoverSlider != nullptr)
 		{
-			mHoverSlider->setInactive();
-			mHoverSlider = nullptr;
+			state.hoverSlider->setInactive();
+			state.hoverSlider = nullptr;
 		}
 
-		if (newActiveSlider != mActiveSlider)
+		if (newActiveSlider != state.activeSlider)
 		{
-			if (mActiveSlider != nullptr)
+			if (state.activeSlider != nullptr)
 			{
-				mActiveSlider->setInactive();
-				mActiveSlider = nullptr;
+				state.activeSlider->setInactive();
+				state.activeSlider = nullptr;
 			}
 
 			if (newActiveSlider != nullptr)
 			{
-				mActiveSlider = newActiveSlider;
-				mActiveSlider->setActive(camera, inputPos);
+				state.activeSlider = newActiveSlider;
+				state.activeSlider->setActive(camera, inputPos);
 			}
 		}
 	}
 
-	void HandleSliderManager::clearSelection()
+	bool HandleSliderManager::isSliderActive(const CameraPtr& camera) const
 	{
-		if (mActiveSlider != nullptr)
+		auto iterFind = mStates.find(camera->getInternalID());
+		if (iterFind == mStates.end())
+			return false;
+
+		return iterFind->second.activeSlider != nullptr;
+	}
+
+	void HandleSliderManager::clearSelection(const CameraPtr& camera)
+	{
+		StatePerCamera& state = mStates[camera->getInternalID()];
+		if (state.activeSlider != nullptr)
 		{
-			mActiveSlider->setInactive();
-			mActiveSlider = nullptr;
+			state.activeSlider->setInactive();
+			state.activeSlider = nullptr;
 		}
 	}
 
@@ -123,10 +126,13 @@ namespace BansheeEngine
 	{
 		mSliders.erase(slider);
 
-		if (mActiveSlider == slider)
-			mActiveSlider = nullptr;
+		for(auto& entry : mStates)
+		{
+			if (entry.second.activeSlider == slider)
+				entry.second.activeSlider = nullptr;
 
-		if (mHoverSlider == slider)
-			mHoverSlider = nullptr;
+			if (entry.second.hoverSlider == slider)
+				entry.second.hoverSlider = nullptr;
+		}
 	}
 }

+ 6 - 10
BansheeEngine/Include/BsDrawHelper.h

@@ -139,9 +139,8 @@ namespace BansheeEngine
 		void clear();
 
 		/**
-		 * @brief	Generates a set of meshes from all the recorded solid and wireframe shapes.
-		 *			The meshes can be accessed via getMeshes() and released via clearMeshes(). 
-		 *			Any previously active meshes will be cleared when this method is called.
+		 * Generates a set of meshes from all the recorded solid and wireframe shapes. The meshes can be accessed via 
+		 * getMeshes() and released via clearMeshes().
 		 *
 		 * @param	sorting		(optional) Determines how (and if) should elements be sorted
 		 *						based on their distance from the reference point.
@@ -155,15 +154,11 @@ namespace BansheeEngine
 		void buildMeshes(SortType sorting = SortType::None, const Vector3& reference = Vector3::ZERO, 
 			UINT64 layers = 0xFFFFFFFFFFFFFFFF);
 
-		/**
-		 * @brief	Returns a set of meshes that were previously built using buildMeshes().
-		 */
+		/** Returns a set of meshes that were built using the last call to buildMeshes(). */
 		const Vector<ShapeMeshData>& getMeshes() const { return mMeshes; }
 
-		/**
-		 * @brief	Deallocates all active meshes.
-		 */
-		void clearMeshes();
+		/** Deallocates meshes previously built with buildMeshes(). */
+		void clearMeshes(const Vector<ShapeMeshData>& meshes);
 
 	private:
 		struct CommonData
@@ -264,6 +259,7 @@ namespace BansheeEngine
 		Vector<Text2DData> mText2DData;
 
 		Vector<ShapeMeshData> mMeshes;
+		UINT32 mNumActiveMeshes;
 
 		MeshHeapPtr mSolidMeshHeap;
 		MeshHeapPtr mWireMeshHeap;

+ 40 - 23
BansheeEngine/Include/BsGUIRenderTexture.h

@@ -6,53 +6,70 @@
 namespace BansheeEngine
 {
 	/**
-	 * @brief	Allows you to display a render texture in the GUI. Has the same functionality as GUITexture, but also forwards
-	 *			any input to underlying GUI elements being rendered on the provided render texture.
+	 * Allows you to display a render texture in the GUI. Has the same functionality as GUITexture, but also forwards any 
+	 * input to underlying GUI elements being rendered on the provided render texture.
 	 */
 	class BS_EXPORT GUIRenderTexture : public GUITexture
 	{
 	public:
+		/** Returns type name of the GUI element used for finding GUI element styles. */
+		static const String& getGUITypeName();
+
 		/**
-		 * Returns type name of the GUI element used for finding GUI element styles. 
+		 * Creates a new element with the provided render texture.
+		 *
+		 * @param[in]	texture			Render texture to display.
+		 * @param[in]	transparent		Determines should the texture be rendered with transparency active.
+		 * @param[in]	styleName		Optional style to use for the element. Style will be retrieved from GUISkin of the 
+		 *								GUIWidget the element is used on. If not specified default style is used.
 		 */
-		static const String& getGUITypeName();
+		static GUIRenderTexture* create(const RenderTexturePtr& texture, bool transparent, 
+			const String& styleName = StringUtil::BLANK);
 
 		/**
-		 * @brief	Creates a new element with the provided render texture.
+		 * Creates a new element with the provided render texture.
 		 *
-		 * @param	texture			Render texture to display.
-		 * @param	styleName		Optional style to use for the element. Style will be retrieved
-		 *							from GUISkin of the GUIWidget the element is used on. If not specified
-		 *							default style is used.
+		 * @param[in]	texture			Render texture to display.
+		 * @param[in]	transparent		Determines should the texture be rendered with transparency active.
+		 * @param[in]	options			Options that allow you to control how is the element positioned and sized.
+		 *								This will override any similar options set by style.
+		 * @param[in]	styleName		Optional style to use for the element. Style will be retrieved from GUISkin of the 
+		 *								GUIWidget the element is used on. If not specified default style is used.
 		 */
-		static GUIRenderTexture* create(const RenderTexturePtr& texture, const String& styleName = StringUtil::BLANK);
+		static GUIRenderTexture* create(const RenderTexturePtr& texture, bool transparent, const GUIOptions& options, 
+			const String& styleName = StringUtil::BLANK);
 
 		/**
-		 * @brief	Creates a new element with the provided render texture.
+		 * Creates a new element with the provided render texture.
 		 *
-		 * @param	texture			Render texture to display.
-		 * @param	options			Options that allow you to control how is the element positioned and sized.
-		 *							This will override any similar options set by style.
-		 * @param	styleName		Optional style to use for the element. Style will be retrieved
-		 *							from GUISkin of the GUIWidget the element is used on. If not specified
-		 *							default style is used.
+		 * @param[in]	texture			Render texture to display.
+		 * @param[in]	styleName		Optional style to use for the element. Style will be retrieved from GUISkin of the 
+		 *								GUIWidget the element is used on. If not specified default style is used.
 		 */
-		static GUIRenderTexture* create(const RenderTexturePtr& texture, const GUIOptions& options, const String& styleName = StringUtil::BLANK);
+		static GUIRenderTexture* create(const RenderTexturePtr& texture, const String& styleName = StringUtil::BLANK);
 
 		/**
-		 * @brief	Changes the active render texture whose contents to display in the GUI element.
+		 * Creates a new element with the provided render texture.
+		 *
+		 * @param[in]	texture			Render texture to display.
+		 * @param[in]	options			Options that allow you to control how is the element positioned and sized.
+		 *								This will override any similar options set by style.
+		 * @param[in]	styleName		Optional style to use for the element. Style will be retrieved from GUISkin of the 
+		 *								GUIWidget the element is used on. If not specified default style is used.
 		 */
+		static GUIRenderTexture* create(const RenderTexturePtr& texture, const GUIOptions& options, const String& styleName = StringUtil::BLANK);
+
+		/** Changes the active render texture whose contents to display in the GUI element. */
 		void setRenderTexture(const RenderTexturePtr& texture);
 
 	protected:
-		GUIRenderTexture(const String& styleName, const RenderTexturePtr& texture, const GUIDimensions& dimensions);
+		GUIRenderTexture(const String& styleName, const RenderTexturePtr& texture, bool transparent, const GUIDimensions& dimensions);
 		virtual ~GUIRenderTexture();
 
-		/**
-		 * @copydoc GUIElement::updateRenderElementsInternal
-		 */
+		/** @copydoc GUIElement::updateRenderElementsInternal */
 		virtual void updateRenderElementsInternal() override;
 
 		RenderTexturePtr mSourceTexture;
+		bool mTransparent;
 	};
 }

+ 8 - 6
BansheeEngine/Source/BsDrawHelper.cpp

@@ -14,7 +14,7 @@ namespace BansheeEngine
 	const UINT32 DrawHelper::INDEX_BUFFER_GROWTH = 4096 * 2;
 
 	DrawHelper::DrawHelper()
-		:mLayer(1)
+		:mLayer(1), mNumActiveMeshes(0)
 	{
 		mTransform = Matrix4::IDENTITY;
 
@@ -39,7 +39,7 @@ namespace BansheeEngine
 
 	DrawHelper::~DrawHelper()
 	{
-		clearMeshes();
+		BS_ASSERT(mNumActiveMeshes == 0 && "Not all DrawHelper meshes were freed on shutdown.");
 	}
 
 	void DrawHelper::setColor(const Color& color)
@@ -272,7 +272,7 @@ namespace BansheeEngine
 
 	void DrawHelper::buildMeshes(SortType sorting, const Vector3& reference, UINT64 layers)
 	{
-		clearMeshes();
+		mMeshes.clear();
 
 		enum class ShapeType
 		{
@@ -974,11 +974,13 @@ namespace BansheeEngine
 				newMesh.type = MeshType::Text;
 			}
 		}
+
+		mNumActiveMeshes += (UINT32)mMeshes.size();
 	}
 
-	void DrawHelper::clearMeshes()
+	void DrawHelper::clearMeshes(const Vector<ShapeMeshData>& meshes)
 	{
-		for (auto meshData : mMeshes)
+		for (auto meshData : meshes)
 		{
 			if (meshData.type == MeshType::Solid)
 				mSolidMeshHeap->dealloc(meshData.mesh);
@@ -988,6 +990,6 @@ namespace BansheeEngine
 				mTextMeshHeap->dealloc(meshData.mesh);
 		}
 
-		mMeshes.clear();
+		mNumActiveMeshes -= (UINT32)meshes.size();
 	}
 }

+ 17 - 5
BansheeEngine/Source/BsGUIRenderTexture.cpp

@@ -13,8 +13,9 @@ namespace BansheeEngine
 		return name;
 	}
 
-	GUIRenderTexture::GUIRenderTexture(const String& styleName, const RenderTexturePtr& texture, const GUIDimensions& dimensions)
-		:GUITexture(styleName, HSpriteTexture(), GUIImageScaleMode::StretchToFit, false, dimensions)
+	GUIRenderTexture::GUIRenderTexture(const String& styleName, const RenderTexturePtr& texture, bool transparent, 
+		const GUIDimensions& dimensions)
+		:GUITexture(styleName, HSpriteTexture(), GUIImageScaleMode::StretchToFit, false, dimensions), mTransparent(transparent)
 	{
 		setRenderTexture(texture);
 	}
@@ -25,14 +26,25 @@ namespace BansheeEngine
 			GUIManager::instance().setInputBridge(mSourceTexture.get(), nullptr);
 	}
 
+	GUIRenderTexture* GUIRenderTexture::create(const RenderTexturePtr& texture, bool transparent, const String& styleName)
+	{
+		return new (bs_alloc<GUIRenderTexture>()) GUIRenderTexture(styleName, texture, transparent, GUIDimensions::create());
+	}
+
+	GUIRenderTexture* GUIRenderTexture::create(const RenderTexturePtr& texture, bool transparent, const GUIOptions& options, 
+		const String& styleName)
+	{
+		return new (bs_alloc<GUIRenderTexture>()) GUIRenderTexture(styleName, texture, transparent, GUIDimensions::create(options));
+	}
+
 	GUIRenderTexture* GUIRenderTexture::create(const RenderTexturePtr& texture, const String& styleName)
 	{
-		return new (bs_alloc<GUIRenderTexture>()) GUIRenderTexture(styleName, texture, GUIDimensions::create());
+		return new (bs_alloc<GUIRenderTexture>()) GUIRenderTexture(styleName, texture, false, GUIDimensions::create());
 	}
 
 	GUIRenderTexture* GUIRenderTexture::create(const RenderTexturePtr& texture, const GUIOptions& options, const String& styleName)
 	{
-		return new (bs_alloc<GUIRenderTexture>()) GUIRenderTexture(styleName, texture, GUIDimensions::create(options));
+		return new (bs_alloc<GUIRenderTexture>()) GUIRenderTexture(styleName, texture, false, GUIDimensions::create(options));
 	}
 
 	void GUIRenderTexture::setRenderTexture(const RenderTexturePtr& texture)
@@ -71,7 +83,7 @@ namespace BansheeEngine
 
 		mDesc.width = mLayoutData.area.width;
 		mDesc.height = mLayoutData.area.height;
-		mDesc.transparent = false;
+		mDesc.transparent = mTransparent;
 		mDesc.color = getTint();
 
 		mImageSprite->update(mDesc, (UINT64)_getParentWidget());

+ 1 - 1
MBansheeEditor/Scene/SceneAxesGUI.cs

@@ -43,7 +43,7 @@ namespace BansheeEditor
             camera.AspectRatio = 1.0f;
             camera.OrthoHeight = 2.0f;
 
-            renderTextureGUI = new GUIRenderTexture(renderTexture);
+            renderTextureGUI = new GUIRenderTexture(renderTexture, true);
             panel.AddElement(renderTextureGUI);
 
             Rect2I bounds = new Rect2I(0, 0, width, height);

+ 26 - 1
MBansheeEditor/Scene/SceneHandles.cs

@@ -20,7 +20,26 @@ namespace BansheeEditor
         }
 
         /// <summary>
-        /// Updates active handles by moving them as a result of any input.
+        /// Triggers handle pre-input callbacks. Must be called before all <see cref="UpdateInput"/> calls and followed by 
+        /// <see cref="EndInput"/>. This should be called only once per frame.
+        /// </summary>
+        internal static void BeginInput()
+        {
+            Internal_BeginInput();
+        }
+
+        /// <summary>
+        /// Triggers handle post-input callbacks. Must be called after all <see cref="UpdateInput"/> calls and after 
+        /// <see cref="BeginInput"/>. This should be called only once per frame.
+        /// </summary>
+        internal static void EndInput()
+        {
+            Internal_EndInput();
+        }
+
+        /// <summary>
+        /// Updates active handles by moving them as a result of any input. Make sure to call <see cref="BeginInput"/> before
+        /// this method, followed by <see cref="EndInput"/> when done.
         /// </summary>
         /// <param name="pointerPos">Position of the pointer relative to the scene camera viewport.</param>
         /// <param name="inputDelta">Movement of the pointer since last frame.</param>
@@ -66,6 +85,12 @@ namespace BansheeEditor
         [MethodImpl(MethodImplOptions.InternalCall)]
         private static extern void Internal_Create(SceneHandles managedInstance, IntPtr parentWindow, IntPtr camera);
 
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_BeginInput();
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_EndInput();
+
         [MethodImpl(MethodImplOptions.InternalCall)]
         private static extern void Internal_UpdateInput(IntPtr thisPtr, ref Vector2I pointerPos, ref Vector2I inputDelta);
 

+ 2 - 0
MBansheeEditor/Scene/SceneWindow.cs

@@ -504,11 +504,13 @@ namespace BansheeEditor
             else
                 cameraController.EnableInput(false);
 
+            SceneHandles.BeginInput();
             sceneHandles.UpdateInput(scenePos, Input.PointerDelta);
             sceneHandles.Draw();
 
             sceneAxesGUI.UpdateInput(scenePos);
             sceneAxesGUI.Draw();
+            SceneHandles.EndInput();
 
             sceneSelection.Draw();
 

+ 38 - 3
MBansheeEngine/GUI/GUIRenderTexture.cs

@@ -32,6 +32,41 @@ namespace BansheeEngine
             }
         }
 
+        /// <summary>
+        /// Creates a new render texture element.
+        /// </summary>
+        /// <param name="texture">Render texture to display in the element.</param>
+        /// <param name="transparent">Determines should the texture be rendered with transparency active.</param>
+        /// <param name="style">Optional style to use for the element. Style controls the look of the element, as well as 
+        ///                     default layout options. Style will be retrieved from the active GUISkin. If not specified 
+        ///                     default element style is used.</param>
+        /// <param name="options">Options that allow you to control how is the element  positioned and sized. This will 
+        ///                       override any similar options set by style.</param>
+        public GUIRenderTexture(RenderTexture2D texture, bool transparent, string style, params GUIOption[] options)
+        {
+            IntPtr texturePtr = IntPtr.Zero;
+            if (texture != null)
+                texturePtr = texture.GetCachedPtr();
+
+            Internal_CreateInstance(this, texturePtr, transparent, style, options);
+        }
+
+        /// <summary>
+        /// Creates a new render texture element.
+        /// </summary>
+        /// <param name="texture">Render texture to display in the element.</param>
+        /// <param name="transparent">Determines should the texture be rendered with transparency active.</param>
+        /// <param name="options">Options that allow you to control how is the element  positioned and sized. This will 
+        ///                       override any similar options set by style.</param>
+        public GUIRenderTexture(RenderTexture2D texture, bool transparent, params GUIOption[] options)
+        {
+            IntPtr texturePtr = IntPtr.Zero;
+            if (texture != null)
+                texturePtr = texture.GetCachedPtr();
+
+            Internal_CreateInstance(this, texturePtr, transparent, "", options);
+        }
+
         /// <summary>
         /// Creates a new render texture element.
         /// </summary>
@@ -47,7 +82,7 @@ namespace BansheeEngine
             if (texture != null)
                 texturePtr = texture.GetCachedPtr();
 
-            Internal_CreateInstance(this, texturePtr, style, options);
+            Internal_CreateInstance(this, texturePtr, false, style, options);
         }
 
         /// <summary>
@@ -62,7 +97,7 @@ namespace BansheeEngine
             if (texture != null)
                 texturePtr = texture.GetCachedPtr();
 
-            Internal_CreateInstance(this, texturePtr, "", options);
+            Internal_CreateInstance(this, texturePtr, false, "", options);
         }
 
         /// <summary>
@@ -75,7 +110,7 @@ namespace BansheeEngine
         }
 
         [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_CreateInstance(GUIRenderTexture instance, IntPtr texture,
+        private static extern void Internal_CreateInstance(GUIRenderTexture instance, IntPtr texture, bool transparency,
             string style, GUIOption[] options);
 
         [MethodImpl(MethodImplOptions.InternalCall)]

+ 4 - 4
SBansheeEditor/Include/BsScriptHandleManager.h

@@ -53,14 +53,14 @@ namespace BansheeEngine
 
 	protected:
 		/**
-		 * @copydoc	HandleManager::refreshHandles
+		 * @copydoc	HandleManager::triggerPreInput
 		 */
-		void refreshHandles() override;
+		void triggerPreInput() override;
 
 		/**
-		 * @copydoc	HandleManager::triggerHandles
+		 * @copydoc	HandleManager::triggerPostInput
 		 */
-		void triggerHandles() override;
+		void triggerPostInput() override;
 
 		/**
 		 * @copydoc	HandleManager::queueDrawCommands

+ 2 - 0
SBansheeEditor/Include/BsScriptSceneHandles.h

@@ -34,6 +34,8 @@ namespace BansheeEngine
 		/************************************************************************/
 		static void internal_Create(MonoObject* managedInstance, ScriptEditorWindow* parentWindow, ScriptCamera* camera);
 		static void internal_Draw(ScriptSceneHandles* thisPtr);
+		static void internal_BeginInput();
+		static void internal_EndInput();
 		static void internal_UpdateInput(ScriptSceneHandles* thisPtr, Vector2I* inputPos, Vector2I* inputDelta);
 		static void internal_TrySelect(ScriptSceneHandles* thisPtr, Vector2I* inputPos);
 		static bool internal_IsActive(ScriptSceneHandles* thisPtr);

+ 2 - 2
SBansheeEditor/Source/BsScriptHandleManager.cpp

@@ -31,7 +31,7 @@ namespace BansheeEngine
 		mDomainLoadConn.disconnect();
 	}
 
-	void ScriptHandleManager::refreshHandles()
+	void ScriptHandleManager::triggerPreInput()
 	{
 		// Activate global handles
 		for(auto& handle : mGlobalHandlesToCreate)
@@ -114,7 +114,7 @@ namespace BansheeEngine
 			callPreInput(handle.object);
 	}
 
-	void ScriptHandleManager::triggerHandles()
+	void ScriptHandleManager::triggerPostInput()
 	{
 		callPostInput(mDefaultHandleManager);
 

+ 15 - 3
SBansheeEditor/Source/BsScriptSceneHandles.cpp

@@ -25,6 +25,8 @@ namespace BansheeEngine
 	{
 		metaData.scriptClass->addInternalCall("Internal_Create", &ScriptSceneHandles::internal_Create);
 		metaData.scriptClass->addInternalCall("Internal_Draw", &ScriptSceneHandles::internal_Draw);
+		metaData.scriptClass->addInternalCall("Internal_BeginInput", &ScriptSceneHandles::internal_BeginInput);
+		metaData.scriptClass->addInternalCall("Internal_EndInput", &ScriptSceneHandles::internal_EndInput);
 		metaData.scriptClass->addInternalCall("Internal_UpdateInput", &ScriptSceneHandles::internal_UpdateInput);
 		metaData.scriptClass->addInternalCall("Internal_TrySelect", &ScriptSceneHandles::internal_TrySelect);
 		metaData.scriptClass->addInternalCall("Internal_IsActive", &ScriptSceneHandles::internal_IsActive);
@@ -78,13 +80,23 @@ namespace BansheeEngine
 		HandleManager::instance().draw(thisPtr->mCamera);
 	}
 
+	void ScriptSceneHandles::internal_BeginInput()
+	{
+		HandleManager::instance().beginInput();
+	}
+
+	void ScriptSceneHandles::internal_EndInput()
+	{
+		HandleManager::instance().endInput();
+	}
+
 	void ScriptSceneHandles::internal_UpdateInput(ScriptSceneHandles* thisPtr, Vector2I* inputPos, Vector2I* inputDelta)
 	{
 		// If mouse wrapped around last frame then we need to compensate for the jump amount
 		Vector2I realDelta = *inputDelta - thisPtr->mMouseDeltaCompensate;
 		thisPtr->mMouseDeltaCompensate = Vector2I::ZERO;
 
-		if (HandleManager::instance().isHandleActive())
+		if (HandleManager::instance().isHandleActive(thisPtr->mCamera))
 			thisPtr->mMouseDeltaCompensate = thisPtr->wrapCursorToWindow();
 
 		HandleManager::instance().updateInput(thisPtr->mCamera, *inputPos, realDelta);
@@ -97,11 +109,11 @@ namespace BansheeEngine
 
 	bool ScriptSceneHandles::internal_IsActive(ScriptSceneHandles* thisPtr)
 	{
-		return HandleManager::instance().isHandleActive();
+		return HandleManager::instance().isHandleActive(thisPtr->mCamera);
 	}
 
 	void ScriptSceneHandles::internal_ClearSelection(ScriptSceneHandles* thisPtr)
 	{
-		HandleManager::instance().clearSelection();
+		HandleManager::instance().clearSelection(thisPtr->mCamera);
 	}
 }

+ 1 - 1
SBansheeEngine/Include/BsScriptGUIRenderTexture.h

@@ -19,7 +19,7 @@ namespace BansheeEngine
 		/************************************************************************/
 		/* 								CLR HOOKS						   		*/
 		/************************************************************************/
-		static void internal_createInstance(MonoObject* instance, ScriptRenderTexture2D* texture,
+		static void internal_createInstance(MonoObject* instance, ScriptRenderTexture2D* texture, bool transparent,
 			MonoString* style, MonoArray* guiOptions);
 		static void internal_setTexture(ScriptGUIRenderTexture* nativeInstance, ScriptRenderTexture2D* texture);
 		static void internal_setTint(ScriptGUIRenderTexture* nativeInstance, Color* color);

+ 2 - 2
SBansheeEngine/Source/BsScriptGUIRenderTexture.cpp

@@ -30,7 +30,7 @@ namespace BansheeEngine
 	}
 
 	void ScriptGUIRenderTexture::internal_createInstance(MonoObject* instance, 
-		ScriptRenderTexture2D* texture, MonoString* style, MonoArray* guiOptions)
+		ScriptRenderTexture2D* texture, bool transparent, MonoString* style, MonoArray* guiOptions)
 	{
 		GUIOptions options;
 
@@ -42,7 +42,7 @@ namespace BansheeEngine
 		if (texture != nullptr)
 			renderTexture = texture->getRenderTexture();
 
-		GUIRenderTexture* guiTexture = GUIRenderTexture::create(renderTexture, options, toString(MonoUtil::monoToWString(style)));
+		GUIRenderTexture* guiTexture = GUIRenderTexture::create(renderTexture, transparent, options, toString(MonoUtil::monoToWString(style)));
 
 		ScriptGUIRenderTexture* nativeInstance = new (bs_alloc<ScriptGUIRenderTexture>()) ScriptGUIRenderTexture(instance, guiTexture);
 	}