Browse Source

SceneGrid renders (but doesn't look pretty)

Marko Pintera 11 years ago
parent
commit
17d906d731

+ 2 - 7
BansheeCore/Include/BsRenderer.h

@@ -67,13 +67,8 @@ namespace BansheeEngine
 		virtual void renderAll() = 0;
 
 		/**
-		 * @brief	Allows you to register a callback for the specified viewport. The callback
-		 * 			will be called before rendering and you will be able to populate the
-		 * 			render queue with render commands that will be executed when rendering.
+		 * @brief	Callback that gets triggered before a viewport gets rendered.
 		 */
-		void addRenderCallback(const Viewport* viewport, std::function<void(const Viewport*, DrawList&)> callback);
-
-	protected:
-		UnorderedMap<const Viewport*, Vector<std::function<void(const Viewport*, DrawList&)>>> mRenderCallbacks;
+		Event<void(const Viewport*, DrawList&)> onRenderViewport;
 	};
 }

+ 1 - 4
BansheeCore/Source/BsRenderer.cpp

@@ -2,8 +2,5 @@
 
 namespace BansheeEngine
 {
-	void Renderer::addRenderCallback(const Viewport* viewport, std::function<void(const Viewport*, DrawList&)> callback)
-	{
-		mRenderCallbacks[viewport].push_back(callback);
-	}
+
 }

+ 2 - 3
BansheeEditor/Include/BsDockManager.h

@@ -121,13 +121,12 @@ namespace BansheeEngine
 		Vector2* mBotDropPolygon;
 		Vector2* mLeftDropPolygon;
 		Vector2* mRightDropPolygon;
-		bool mAddedRenderCallback;
+
+		HEvent mRenderCallback;
 
 		void updateDropOverlay(INT32 x, INT32 y, UINT32 width, UINT32 height);
 
 		bool mouseEvent(const GUIMouseEvent& event);
 		bool insidePolygon(Vector2* polyPoints, UINT32 numPoints, Vector2 point) const;
-
-		void _changeParentWidget(GUIWidget* widget);
 	};
 }

+ 1 - 0
BansheeEditor/Include/BsEditorPrerequisites.h

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

+ 1 - 0
BansheeEditor/Include/BsEditorWidget.h

@@ -40,6 +40,7 @@ namespace BansheeEngine
 
 		virtual void doOnMoved(INT32 x, INT32 y);
 		virtual void doOnResized(UINT32 width, UINT32 height);
+		virtual void doOnParentChanged();
 
 		String mName;
 		HString mDisplayName;

+ 4 - 0
BansheeEditor/Include/BsSceneEditorWidget.h

@@ -22,6 +22,7 @@ namespace BansheeEngine
 		void doOnResized(UINT32 width, UINT32 height);
 
 		void updateRenderTexture(UINT32 width, UINT32 height);
+		void render(const Viewport* viewport, DrawList& drawList);
 
 	private:
 		static SceneEditorWidget* Instance;
@@ -29,5 +30,8 @@ namespace BansheeEngine
 		RenderTexturePtr mSceneRenderTarget;
 		GUIRenderTexture* mGUIRenderTexture;
 		HCamera mCamera;
+		SceneGrid* mSceneGrid;
+
+		HEvent mRenderCallback;
 	};
 }

+ 5 - 1
BansheeEditor/Include/BsSceneGrid.h

@@ -3,6 +3,7 @@
 #include "BsEditorPrerequisites.h"
 #include "BsVector3.h"
 #include "BsColor.h"
+#include "BsMaterial.h"
 
 namespace BansheeEngine
 {
@@ -17,15 +18,18 @@ namespace BansheeEngine
 		void setMajorAxisSpacing(UINT32 spacing);
 		void setAxisMarkerSpacing(UINT32 spacing);
 
+		void render(const CameraPtr& camera, DrawList& drawList);
 	private:
 		void updateGridMesh();
 
 		HMesh mGridMesh;
+		HMaterial mGridMaterial;
+		GpuParamMat4 mViewProjParam;
 		VertexDataDescPtr mVertexDesc;
 
 		Vector3 mOrigin;
 		float mSpacing = 1.0f;
-		float mSize = 256.0f;
+		float mSize = 257.0f;
 		UINT32 mMajorAxisSpacing = 10;
 		UINT32 mAxisMarkerSpacing = 25;
 

+ 15 - 7
BansheeEditor/Source/BsBuiltinEditorResources.cpp

@@ -31,6 +31,7 @@
 #include "BsMaterial.h"
 #include "BsBlendState.h"
 #include "BsDepthStencilState.h"
+#include "BsRasterizerState.h"
 #include "BsGpuProgramImportOptions.h"
 #include "BsResources.h"
 #include "BsRTTIType.h"
@@ -1214,7 +1215,7 @@ namespace BansheeEngine
 		HGpuProgram vsProgram = getGpuProgram(SceneGridVSFile);
 		HGpuProgram psProgram = getGpuProgram(SceneGridPSFile);
 
-		mShaderSceneGrid = Shader::create("DebugDraw3DShader");
+		mShaderSceneGrid = Shader::create("SceneGridShader");
 
 		mShaderSceneGrid->addParameter("matViewProj", "matViewProj", GPDT_MATRIX_4X4);
 
@@ -1223,14 +1224,21 @@ namespace BansheeEngine
 		newPass->setVertexProgram(vsProgram);
 		newPass->setFragmentProgram(psProgram);
 
-		BLEND_STATE_DESC desc;
-		desc.renderTargetDesc[0].blendEnable = true;
-		desc.renderTargetDesc[0].srcBlend = BF_SOURCE_ALPHA;
-		desc.renderTargetDesc[0].dstBlend = BF_INV_SOURCE_ALPHA;
-		desc.renderTargetDesc[0].blendOp = BO_ADD;
+		BLEND_STATE_DESC blendDesc;
+		blendDesc.renderTargetDesc[0].blendEnable = true;
+		blendDesc.renderTargetDesc[0].srcBlend = BF_SOURCE_ALPHA;
+		blendDesc.renderTargetDesc[0].dstBlend = BF_INV_SOURCE_ALPHA;
+		blendDesc.renderTargetDesc[0].blendOp = BO_ADD;
+		blendDesc.renderTargetDesc[0].renderTargetWriteMask = 0x7; // Don't write to alpha
 
-		HBlendState blendState = BlendState::create(desc);
+		HBlendState blendState = BlendState::create(blendDesc);
 		newPass->setBlendState(blendState);
+
+		RASTERIZER_STATE_DESC rasterizerDesc;
+		rasterizerDesc.cullMode = CULL_NONE;
+
+		HRasterizerState rasterizerState = RasterizerState::create(rasterizerDesc);
+		newPass->setRasterizerState(rasterizerState);
 	}
 
 	HMaterial BuiltinEditorResources::createDockDropOverlayMaterial() const

+ 8 - 19
BansheeEditor/Source/BsDockManager.cpp

@@ -409,7 +409,7 @@ namespace BansheeEngine
 
 	DockManager::DockManager(RenderWindow* parentWindow, const GUILayoutOptions& layoutOptions)
 		:GUIElementContainer(layoutOptions), mParentWindow(parentWindow), mMouseOverContainer(nullptr), mHighlightedDropLoc(DockLocation::None),
-		mShowOverlay(false), mAddedRenderCallback(false), mRootContainer(this)
+		mShowOverlay(false), mRootContainer(this)
 	{
 		mTopDropPolygon = bs_newN<Vector2>(4);
 		mBotDropPolygon = bs_newN<Vector2>(4);
@@ -417,10 +417,14 @@ namespace BansheeEngine
 		mRightDropPolygon = bs_newN<Vector2>(4);
 
 		mDropOverlayMat = BuiltinEditorResources::instance().createDockDropOverlayMaterial();
+
+		mRenderCallback = RendererManager::instance().getActive()->onRenderViewport.connect(std::bind(&DockManager::render, this, _1, _2));
 	}
 
 	DockManager::~DockManager()
 	{
+		mRenderCallback.disconnect();
+
 		bs_deleteN(mTopDropPolygon, 4);
 		bs_deleteN(mBotDropPolygon, 4);
 		bs_deleteN(mLeftDropPolygon, 4);
@@ -445,6 +449,9 @@ namespace BansheeEngine
 
 	void DockManager::render(const Viewport* viewport, DrawList& drawList)
 	{
+		if (_getParentWidget() == nullptr || _getParentWidget()->getTarget() != viewport)
+			return;
+
 		if(!mShowOverlay)
 			return;
 
@@ -1008,24 +1015,6 @@ namespace BansheeEngine
 		return false;
 	}
 	
-	void DockManager::_changeParentWidget(GUIWidget* widget)
-	{
-		GUIElement::_changeParentWidget(widget);
-
-		if(widget != nullptr)
-		{
-			if(mAddedRenderCallback)
-			{
-				// Note: Adding support for this should be fairly simple though, I just didn't bother with it. You could
-				// remove the current render callback and register a new one. Will likely need to make other minor fixes.
-				BS_EXCEPT(InvalidStateException, "Attempting to change parent widget of a DockManager. This is not supported");
-			}
-
-			RendererManager::instance().getActive()->addRenderCallback(widget->getTarget(), std::bind(&DockManager::render, this, _1, _2));
-			mAddedRenderCallback = true;
-		}
-	}
-
 	// TODO - Move to a separate Polygon class?
 	bool DockManager::insidePolygon(Vector2* polyPoints, UINT32 numPoints, Vector2 point) const
 	{

+ 7 - 0
BansheeEditor/Source/BsEditorWidget.cpp

@@ -74,6 +74,11 @@ namespace BansheeEngine
 			onResized(width, height);
 	}
 
+	void EditorWidgetBase::doOnParentChanged()
+	{
+
+	}
+
 	// Note: Must not be virtual as parent container uses it in constructor
 	void EditorWidgetBase::_changeParent(EditorWidgetContainer* parent)
 	{
@@ -94,6 +99,8 @@ namespace BansheeEngine
 
 			mParent = parent;
 
+			doOnParentChanged();
+
 			if(!onParentChanged.empty())
 				onParentChanged(mParent);
 		}

+ 3 - 3
BansheeEditor/Source/BsSceneCameraController.cpp

@@ -20,9 +20,9 @@ namespace BansheeEngine
 	const String SceneCameraController::HORIZONTAL_AXIS = "SceneHorizontal";
 	const String SceneCameraController::VERTICAL_AXIS = "SceneVertical";
 
-	const float SceneCameraController::START_SPEED = 40.0f;
-	const float SceneCameraController::TOP_SPEED = 130.0f;
-	const float SceneCameraController::ACCELERATION = 10.0f;
+	const float SceneCameraController::START_SPEED = 4.0f;
+	const float SceneCameraController::TOP_SPEED = 12.0f;
+	const float SceneCameraController::ACCELERATION = 1.0f;
 	const float SceneCameraController::FAST_MODE_MULTIPLIER = 2.0f;
 	const float SceneCameraController::ROTATION_SPEED = 360.0f; // Degrees/second
 

+ 26 - 7
BansheeEditor/Source/BsSceneEditorWidget.cpp

@@ -13,6 +13,13 @@
 #include "BsCamera.h"
 #include "BsGUIRenderTexture.h"
 #include "BsCoreThread.h"
+#include "BsEditorWidgetContainer.h"
+#include "BsRendererManager.h"
+#include "BsRenderer.h"
+#include "BsGUIWidget.h"
+#include "BsSceneGrid.h"
+
+using namespace std::placeholders;
 
 namespace BansheeEngine
 {
@@ -22,11 +29,15 @@ namespace BansheeEngine
 		:EditorWidget<SceneEditorWidget>(HString(L"SceneEditorWidget"), parentContainer), mGUIRenderTexture(nullptr)
 	{
 		updateRenderTexture(getWidth(), getHeight());
+
+		mRenderCallback = RendererManager::instance().getActive()->onRenderViewport.connect(std::bind(&SceneEditorWidget::render, this, _1, _2));
+		mSceneGrid = bs_new<SceneGrid>();
 	}
 
 	SceneEditorWidget::~SceneEditorWidget()
 	{
-
+		bs_delete(mSceneGrid);
+		mRenderCallback.disconnect();
 	}
 
 	void SceneEditorWidget::_update()
@@ -41,6 +52,17 @@ namespace BansheeEngine
 		updateRenderTexture(width, height);
 	}
 
+	void SceneEditorWidget::render(const Viewport* viewport, DrawList& drawList)
+	{
+		if (mCamera == nullptr)
+			return;
+
+		if (mCamera->getViewport().get() != viewport)
+			return;
+
+		mSceneGrid->render(mCamera.getInternalPtr(), drawList);
+	}
+
 	void SceneEditorWidget::updateRenderTexture(UINT32 width, UINT32 height)
 	{
 		width = std::max(20U, width);
@@ -57,15 +79,12 @@ namespace BansheeEngine
 			HSceneObject sceneCameraSO = SceneObject::create("SceneCamera");
 			mCamera = sceneCameraSO->addComponent<Camera>(mSceneRenderTarget, 0.0f, 0.0f, 1.0f, 1.0f);
 
-			sceneCameraSO->setPosition(Vector3(0, 0, 0));
-			sceneCameraSO->lookAt(Vector3(0, 0, -3));
-
-			// DEBUG ONLY
-			sceneCameraSO->setPosition(Vector3(-130.0f, 140.0f, 650.0f));
+			sceneCameraSO->setPosition(Vector3(0, 0.5f, 1));
 			sceneCameraSO->lookAt(Vector3(0, 0, 0));
 
 			mCamera->setPriority(1);
-			mCamera->setNearClipDistance(5);
+			mCamera->setNearClipDistance(0.005f);
+			mCamera->setFarClipDistance(1000.0f);
 
 			sceneCameraSO->addComponent<SceneCameraController>();
 

+ 27 - 4
BansheeEditor/Source/BsSceneGrid.cpp

@@ -2,7 +2,11 @@
 #include "BsMath.h"
 #include "BsDrawHelper3D.h"
 #include "BsVertexDataDesc.h"
+#include "BsMaterial.h"
 #include "BsMesh.h"
+#include "BsDrawList.h"
+#include "BsBuiltinEditorResources.h"
+#include "BsCamera.h"
 
 namespace BansheeEngine
 {
@@ -20,6 +24,11 @@ namespace BansheeEngine
 		mVertexDesc = bs_shared_ptr<VertexDataDesc>();
 		mVertexDesc->addVertElem(VET_FLOAT3, VES_POSITION);
 		mVertexDesc->addVertElem(VET_COLOR, VES_COLOR);
+
+		mGridMaterial = BuiltinEditorResources::instance().createSceneGridMaterial();
+		mViewProjParam = mGridMaterial->getParamMat4("matViewProj");
+
+		updateGridMesh();
 	}
 
 	void SceneGrid::setOrigin(const Vector3& origin)
@@ -52,9 +61,23 @@ namespace BansheeEngine
 		updateGridMesh();
 	}
 
+	void SceneGrid::render(const CameraPtr& camera, DrawList& drawList)
+	{
+		MaterialPtr mat = mGridMaterial.getInternalPtr();
+		MeshPtr mesh = mGridMesh.getInternalPtr();
+
+		Matrix4 projMatrix = camera->getProjectionMatrix();
+		Matrix4 viewMatrix = camera->getViewMatrix();
+
+		Matrix4 viewProjMatrix = projMatrix * viewMatrix;
+		mViewProjParam.set(viewProjMatrix);
+
+		drawList.add(mat, mesh, 0, Vector3::ZERO);
+	}
+
 	void SceneGrid::updateGridMesh()
 	{
-		UINT32 numLines = (UINT32)Math::roundToInt(mSize / mSpacing);
+		UINT32 numLines = (UINT32)Math::roundToInt(mSize / mSpacing) - 1;
 		if (numLines % 2 != 0)
 			numLines++;
 
@@ -70,14 +93,14 @@ namespace BansheeEngine
 		float maxX = (startX + numLines) * mSpacing;
 		float maxZ = (startZ + numLines) * mSpacing;
 
-		UINT32 totalNumVertices = DrawHelper3D::NUM_VERTICES_AA_LINE * numLines * 2;
-		UINT32 totalNumIndices = DrawHelper3D::NUM_INDICES_AA_LINE * numLines * 2;
+		UINT32 totalNumVertices = DrawHelper3D::NUM_VERTICES_AA_LINE * (numLines + 1) * 2;
+		UINT32 totalNumIndices = DrawHelper3D::NUM_INDICES_AA_LINE * (numLines + 1) * 2;
 
 		MeshDataPtr meshData = bs_shared_ptr<MeshData, PoolAlloc>(totalNumVertices, totalNumIndices, mVertexDesc);
 		UINT32 vertexOffset = 0;
 		UINT32 indexOffset = 0;
 
-		for (UINT32 i = 0; i < numLines; i++)
+		for (UINT32 i = 0; i <= numLines; i++)
 		{
 			INT32 x = startX + i;
 			float linePosX = x * mSpacing;

+ 10 - 9
BansheeEngine/Source/BsDrawHelper2D.cpp

@@ -318,6 +318,7 @@ namespace BansheeEngine
 		UINT32 numCoords = (UINT32)points.size();
 
 		outVertices += vertexOffset * vertexStride;
+		outColors += vertexOffset * vertexStride;
 		Vector<Vector2> tempNormals(numCoords);
 
 		for(UINT32 i = 0, j = numCoords - 1; i < numCoords; j = i++)
@@ -384,20 +385,20 @@ namespace BansheeEngine
 		UINT32 idxCnt = 0;
 		for(UINT32 i = 0, j = numCoords - 1; i < numCoords; j = i++)
 		{
-			outIndices[idxCnt++] = i;
-			outIndices[idxCnt++] = j;
-			outIndices[idxCnt++] = numCoords + j;
+			outIndices[idxCnt++] = vertexOffset + i;
+			outIndices[idxCnt++] = vertexOffset + j;
+			outIndices[idxCnt++] = vertexOffset + numCoords + j;
 
-			outIndices[idxCnt++] = numCoords + j;
-			outIndices[idxCnt++] = numCoords + i;
-			outIndices[idxCnt++] = i;
+			outIndices[idxCnt++] = vertexOffset + numCoords + j;
+			outIndices[idxCnt++] = vertexOffset + numCoords + i;
+			outIndices[idxCnt++] = vertexOffset + i;
 		}
 
 		for(UINT32 i = 2; i < numCoords; ++i)
 		{
-			outIndices[idxCnt++] = 0;
-			outIndices[idxCnt++] = i - 1;
-			outIndices[idxCnt++] = i;
+			outIndices[idxCnt++] = vertexOffset + 0;
+			outIndices[idxCnt++] = vertexOffset + i - 1;
+			outIndices[idxCnt++] = vertexOffset + i;
 		}
 	}
 

+ 10 - 9
BansheeEngine/Source/BsDrawHelper3D.cpp

@@ -335,6 +335,7 @@ namespace BansheeEngine
 		UINT32 numCoords = (UINT32)points.size();
 
 		outVertices += vertexOffset * vertexStride;
+		outColors += vertexOffset * vertexStride;
 		Vector<Vector3> tempNormals(numCoords);
 
 		for (UINT32 i = 0, j = numCoords - 1; i < numCoords; j = i++)
@@ -398,20 +399,20 @@ namespace BansheeEngine
 		UINT32 idxCnt = 0;
 		for (UINT32 i = 0, j = numCoords - 1; i < numCoords; j = i++)
 		{
-			outIndices[idxCnt++] = i;
-			outIndices[idxCnt++] = j;
-			outIndices[idxCnt++] = numCoords + j;
+			outIndices[idxCnt++] = vertexOffset + i;
+			outIndices[idxCnt++] = vertexOffset + j;
+			outIndices[idxCnt++] = vertexOffset + numCoords + j;
 
-			outIndices[idxCnt++] = numCoords + j;
-			outIndices[idxCnt++] = numCoords + i;
-			outIndices[idxCnt++] = i;
+			outIndices[idxCnt++] = vertexOffset + numCoords + j;
+			outIndices[idxCnt++] = vertexOffset + numCoords + i;
+			outIndices[idxCnt++] = vertexOffset + i;
 		}
 
 		for (UINT32 i = 2; i < numCoords; ++i)
 		{
-			outIndices[idxCnt++] = 0;
-			outIndices[idxCnt++] = i - 1;
-			outIndices[idxCnt++] = i;
+			outIndices[idxCnt++] = vertexOffset + 0;
+			outIndices[idxCnt++] = vertexOffset + i - 1;
+			outIndices[idxCnt++] = vertexOffset + i;
 		}
 	}
 }

+ 1 - 4
BansheeRenderer/Source/BsBansheeRenderer.cpp

@@ -325,10 +325,7 @@ namespace BansheeEngine
 
 			// Get any operations from hooked up callbacks
 			const Viewport* viewportRawPtr = camera->getViewport().get();
-			auto callbacksForViewport = mRenderCallbacks[viewportRawPtr];
-
-			for (auto& callback : callbacksForViewport)
-				callback(viewportRawPtr, *drawList);
+			onRenderViewport(viewportRawPtr, *drawList);
 
 			RenderQueuePtr renderQueue = bs_shared_ptr<RenderQueue>();
 			const Vector<DrawOperation>& drawOps = drawList->getDrawOperations();

+ 16 - 0
BansheeUtility/Include/BsEvent.h

@@ -40,6 +40,22 @@ namespace BansheeEngine
 				mDisconnectCallback(mConnection, mEvent);
 		}
 
+		struct Bool_struct
+		{
+			int _Member;
+		};
+
+		/**
+		* @brief	Allows direct conversion of a handle to bool.
+		*
+		* @note		This is needed because we can't directly convert to bool
+		*			since then we can assign pointer to bool and that's wrong.
+		*/
+		operator int Bool_struct::*() const
+		{
+			return ((mConnection != nullptr && mConnection->isValid) ? &Bool_struct::_Member : 0);
+		}
+
 	private:
 		void(*mDisconnectCallback) (const std::shared_ptr<BaseConnectionData>&, void*);
 		std::shared_ptr<BaseConnectionData> mConnection;

+ 2 - 1
BansheeUtility/Include/BsVector2.h

@@ -15,10 +15,11 @@ namespace BansheeEngine
 
     public:
         Vector2()
+			:x(0.0f), y(0.0f)
         { }
 
         Vector2(float x, float y)
-            : x(x), y(y)
+            :x(x), y(y)
         { }
 
 		/**

+ 2 - 1
BansheeUtility/Include/BsVector3.h

@@ -15,10 +15,11 @@ namespace BansheeEngine
 
     public:
         Vector3()
+			:x(0.0f), y(0.0f), z(0.0f)
         { }
 
         Vector3(float x, float y, float z)
-            : x(x), y(y), z(z)
+            :x(x), y(y), z(z)
         { }
 
 		/**

+ 1 - 0
BansheeUtility/Include/BsVector4.h

@@ -15,6 +15,7 @@ namespace BansheeEngine
 
     public:
         Vector4()
+			:x(0.0f), y(0.0f), z(0.0f), w(0.0f)
         { }
 
         Vector4(float x, float y, float z, float w)

+ 3 - 0
Notes.txt

@@ -67,6 +67,9 @@ Reminders:
   - I shouldn't use WeakRef with GameObjects. They need be deserialized in the order of their hierarchy and weak ref can break that.
   - Make sure to add fixedUpdate() to run your game logic in. This should have an adjustable update rate. See: http://gameprogrammingpatterns.com/game-loop.html
   - Will also need GameObject::destroy and GameObject::destroyImmediate. So I can remove GameObjects that might still be referenced that same frame (destroy() would just queue for destruction)
+  - When unloading unused resources I should do it recursively so it unloads any new ones that might have been released during the first unload. 
+    (e.g. unloading a sprite texture will probably release its atlas texture as well)
+
 
 Potential optimizations:
  - bulkPixelConversion is EXTREMELY poorly unoptimized. Each pixel it calls a separate method that does redudant operations every pixel.

+ 61 - 27
SceneView.txt

@@ -4,11 +4,6 @@ TODO:
 
 Weekend:
  - Set up grid material and hook it up to renderer (+ actually instantiate it in EditorApplication)
- 
- - Fix up shader so I can reference two different gpu vars with a single shader var (e.g. DX11 sampler variables will have different names than DX9 or GL sampler variables)
- - When unloading unused resources I should do it recursively so it unloads any new ones that might have been released during the first unload
-
- - Think about picking implementation and possibly Handles implementation
 
 TODO - Think about:
  - How will I allow user from C# to draw gizmos and handles?
@@ -37,16 +32,34 @@ See for inspiration: http://docs.unity3d.com/ScriptReference/Handles.html
 ----------------------------------------------------------------------
 Picking
 
-TODO - Think about this
+BsPicking
+ - HGameObject PickClosestGameObject(Camera cam, Vector2 position, Vector2 area)
+ - PickResult PickClosestObject(Camera cam, Vector2 position, Vector2 area)
+ - void PickGameObjects(Camera cam, Vector2 position, Vector2 area, Vector<HGameObject>& selection)
+ - void PickObjects(Camera cam, Vector2 position, Vector2 area, Vector<PickResults>& selection)
 
-Picking
- - Create core thread class that accepts a screen coordinate and a camera and it determines object at its position
- - System then renders all visible objects with diferent colors 
- - Image then needs to be read back to determine what was hit
- - Result is returned via async op
- - Needs to support multi-select where I draw a rectangle on screen
- - NOTE: I will also need to render gizmos which I assume will all be within a single buffer. This might require special care since normally I can color each buffer with a different color, which won't work in this case.
-     - Similar issue might happen with particles and other systems
+PickResult
+ Type (GameObject or Gizmo)
+ Data (Handle to GameObject or gizmo ID)
+
+Picking will internally:
+ - Be performed on the Scene render target just before actual rendering
+ - Use scissor rect to limit itself to the specified screen area
+    - TODO later - I could also limit the camera frustum to this area for additional culling
+
+ - Go through every scene object and find all renderables
+ - Perform culling over all renderables and generate a list of visible nodes
+ - Access GizmoManager and get a list of all gizmos and their IDs
+ - Generate unique colors for all renderables and gizmos
+ - Send meshes/colors/ids to core thread to be rendered with a special shader
+ - Wait until core thread completes and returns an AsyncOp with a list of selected IDs
+
+ - Ensure I can read-back from a render target on the core thread
+  - Check DX9, DX11 and OpenGL implementations for both render textures and render windows
+
+Also:
+ - I need to send the primary used texture so I properly determine transparent areas using alpha
+   - TODO - But I do not have a way of defining a primary texture in-engine. Add a renderer semantic?
 
 ----------------------------------------------------------------------
 Rendering selection
@@ -71,8 +84,39 @@ This can be drawn directly using the draw list and not a renderable
 ----------------------------------------------------------------------
 Gizmos
 
-GizmoSetups
- - Determines what to display for a certain component (or a SceneObject) itself
+Custom gizmos:
+ - Users can override the Gizmo class to create their own custom gizmos
+ - It contains various methods that can be used for constructing the gizmo
+   - DrawCube
+   - DrawSphere
+   - DrawWireCube
+   - DrawWireSphere
+   - DrawRay
+   - DrawLine
+   - DrawFrustum
+   - DrawIcon
+
+ - Any Gizmo is registered with GizmoTypes manager
+ 
+ - Components may associate themselves with a gizmo using [SetGizmo(Gizmo)] attribute
+  - It contains other properties, like when should gizmo be displayed (active, selected, not selected, parent selected) and whether
+    or not the gizmo is pickable
+
+ - When drawing an icon
+   - It should always face the camera
+   - It can be static size in screen space, or resizable with distance
+
+ - Need a way to notify the gizmo needs updating from component with the gizmo
+   - Gizmos.MarkDirty(GameObject)
+
+ - How do I assign a texture to DrawIcon? I'm assuming Gizmo class will not have an inspector.
+   - A special ManagedResource that allows you to assign textures to it?
+     - WIll need a Dictionary inspector?
+
+Gizmo rendering:
+GizmoTypes
+ - All gizmo types are registered here
+ - It contains prebuilt gizmo meshes and textures
 
 GizmoManager
  - Every frame goes through all game objects and create/removes their gizmos. It keeps a cached version of all gizmos
@@ -82,16 +126,6 @@ GizmoManager
 GizmosRenderer
  - Batches all gizmos into a single buffer and renders them with a single call
  - It might be a bit problematic if custom textures are used for gizmos
-    - Just don't batch those?
+    - Just don't batch those? Yep, probably not worth batching at this point.
 
 When picking GizmosRenderer can draw the gizmos as normal but using a special shader.
-
---------
-
-Need to allow the user to specify custom gizmos.
- - Have a set of methods like Gizmos.DrawSphere, DrawIcon, DrawLine, DrawCube, DrawFrustum, etc.
- - Have a CustomGizmo attribute which you can attach to a method
- - That method can then call above methods
- - Additionally in the attribute you can specify when is the gizmo displayed: Active, Selected, NotSelected, SelectedOrChild
- - And an option if gizmo can be picked or not
- - These methods will somehow automatically be registered with the GizmoSetups