Parcourir la source

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 il y a 10 ans
Parent
commit
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);
 	}