Răsfoiți Sursa

Text visible on the screen

Marko Pintera 12 ani în urmă
părinte
comite
1cfbcc30a9

+ 71 - 0
CamelotClient/CamelotClient.cpp

@@ -22,6 +22,7 @@
 #include "CmFontImportOptions.h"
 
 #include "CmDebugCamera.h"
+#include "CmTestTextSprite.h"
 
 #define DX11
 //#define DX9
@@ -29,6 +30,69 @@
 
 using namespace CamelotEngine;
 
+MaterialHandle createTextMaterial()
+{
+	#if defined DX9
+	// TODO
+	#elif defined DX11
+	String textShader_dx11psLoc = "C:\\Projects\\CamelotEngine\\Data\\textShader_hlsl11_ps.gpuprog";
+	String textShader_dx11vsLoc = "C:\\Projects\\CamelotEngine\\Data\\textShader_hlsl11_vs.gpuprog";
+
+	ImportOptionsPtr gpuProgImportOptions = Importer::instance().createImportOptions(textShader_dx11psLoc);
+	if(rtti_is_of_type<GpuProgramImportOptions>(gpuProgImportOptions))
+	{
+		GpuProgramImportOptions* importOptions = static_cast<GpuProgramImportOptions*>(gpuProgImportOptions.get());
+
+		importOptions->setEntryPoint("ps_main");
+		importOptions->setLanguage("hlsl");
+		importOptions->setProfile(GPP_PS_4_0);
+		importOptions->setType(GPT_FRAGMENT_PROGRAM);
+	}
+
+	HighLevelGpuProgramHandle textShaderFragProgRef = Importer::instance().import(textShader_dx11psLoc, gpuProgImportOptions);
+
+	gpuProgImportOptions = Importer::instance().createImportOptions(textShader_dx11vsLoc);
+	if(rtti_is_of_type<GpuProgramImportOptions>(gpuProgImportOptions))
+	{
+		GpuProgramImportOptions* importOptions = static_cast<GpuProgramImportOptions*>(gpuProgImportOptions.get());
+
+		importOptions->setEntryPoint("vs_main");
+		importOptions->setLanguage("hlsl");
+		importOptions->setProfile(GPP_VS_4_0);
+		importOptions->setType(GPT_VERTEX_PROGRAM);
+	}
+
+	HighLevelGpuProgramHandle textShaderVertProgRef = Importer::instance().import(textShader_dx11vsLoc, gpuProgImportOptions);
+
+	#else
+	// TODO
+#endif
+
+	ShaderPtr textShader = Shader::create("TextShader");
+
+	textShader->addParameter("samp", "samp", GPOT_SAMPLER2D);
+	textShader->addParameter("tex", "tex", GPOT_TEXTURE2D);
+	//TechniquePtr newTechniqueGL = textShader->addTechnique("GLRenderSystem", "ForwardRenderer");
+	//PassPtr newPassGL = newTechniqueGL->addPass();
+	//newPassGL->setVertexProgram(textShaderVertProgRef);
+	//newPassGL->setFragmentProgram(textShaderFragProgRef);
+
+	//TechniquePtr newTechniqueDX = textShader->addTechnique("D3D9RenderSystem", "ForwardRenderer");
+	//PassPtr newPassDX = newTechniqueDX->addPass();
+	//newPassDX->setVertexProgram(textShaderVertProgRef);
+	//newPassDX->setFragmentProgram(textShaderFragProgRef);
+
+	TechniquePtr newTechniqueDX11 = textShader->addTechnique("D3D11RenderSystem", "ForwardRenderer");
+	PassPtr newPassDX11 = newTechniqueDX11->addPass();
+	newPassDX11->setVertexProgram(textShaderVertProgRef);
+	newPassDX11->setFragmentProgram(textShaderFragProgRef);
+
+	MaterialHandle textMaterial = Material::create();
+	textMaterial->setShader(textShader);
+
+	return textMaterial;
+}
+
 int CALLBACK WinMain(
 	_In_  HINSTANCE hInstance,
 	_In_  HINSTANCE hPrevInstance,
@@ -61,6 +125,9 @@ int CALLBACK WinMain(
 	GameObjectPtr testModelGO = GameObject::create("TestMesh");
 	RenderablePtr testRenderable = testModelGO->addComponent<Renderable>();
 
+	GameObjectPtr testTextGO = GameObject::create("TestText");
+	std::shared_ptr<TestTextSprite> textSprite = testTextGO->addComponent<TestTextSprite>();
+
 	// Debug test fonts
 	ImportOptionsPtr fontImportOptions = Importer::instance().createImportOptions("C:\\arial.ttf");
 	if(rtti_is_of_type<FontImportOptions>(fontImportOptions))
@@ -74,6 +141,10 @@ int CALLBACK WinMain(
 
 	FontHandle font = Importer::instance().import("C:\\arial.ttf", fontImportOptions);
 
+	MaterialHandle textMaterial = createTextMaterial();
+
+	textSprite->setText("TESTfAV", font, 12, textMaterial);
+
 #if defined DX9
 	///////////////// HLSL 9 SHADERS //////////////////////////
 	String dx9psLoc = "C:\\Projects\\CamelotEngine\\Data\\hlsl9_ps.gpuprog";

+ 2 - 0
CamelotClient/CamelotClient.vcxproj

@@ -167,12 +167,14 @@
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="CmDebugCamera.h" />
+    <ClInclude Include="CmTestTextSprite.h" />
     <ClInclude Include="stdafx.h" />
     <ClInclude Include="targetver.h" />
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="CamelotClient.cpp" />
     <ClCompile Include="CmDebugCamera.cpp" />
+    <ClCompile Include="CmTestTextSprite.cpp" />
     <ClCompile Include="stdafx.cpp" />
   </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+ 6 - 0
CamelotClient/CamelotClient.vcxproj.filters

@@ -27,6 +27,9 @@
     <ClInclude Include="CmDebugCamera.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="CmTestTextSprite.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="stdafx.cpp">
@@ -38,5 +41,8 @@
     <ClCompile Include="CmDebugCamera.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="CmTestTextSprite.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>

+ 82 - 0
CamelotClient/CmTestTextSprite.cpp

@@ -0,0 +1,82 @@
+#include "CmTestTextSprite.h"
+#include "CmGameObject.h"
+#include "CmRenderable.h"
+#include "CmMesh.h"
+#include "CmVector2.h"
+#include "CmTextSprite.h"
+#include "CmFont.h"
+#include "CmMaterial.h"
+
+namespace CamelotEngine
+{
+	TestTextSprite::TestTextSprite(GameObjectPtr parent)
+		:Component(parent), mTextSprite(nullptr)
+	{
+		mTextRenderable = gameObject()->addComponent<Renderable>();
+		mTextMesh = Mesh::create();
+
+		mTextSprite = new TextSprite();
+	}
+
+	TestTextSprite::~TestTextSprite()
+	{
+		if(mTextSprite != nullptr)
+			delete mTextSprite;
+	}
+
+	void TestTextSprite::setText(const String& text, FontHandle font, UINT32 fontSize, MaterialHandle textMaterial)
+	{
+		mTextSprite->setText(text);
+		mTextSprite->setFont(font.getInternalPtr(), fontSize);
+
+		UINT32 numTextFaces = mTextSprite->getNumFaces();
+		UINT32 numVertices = numTextFaces * 4;
+		UINT32 numIndices = numTextFaces * 6;
+
+		std::shared_ptr<MeshData> textData(new MeshData());
+		textData->declaration->addElement(0, 0, VET_FLOAT3, VES_POSITION);
+		textData->declaration->addElement(0, 12, VET_FLOAT2, VES_TEXCOORD);
+
+		textData->index = new int[numIndices];
+		textData->indexCount = numIndices;
+		textData->vertexCount = numVertices;
+		
+		std::shared_ptr<MeshData::VertexData> vertData(new MeshData::VertexData(numVertices));
+		vertData->vertex = new Vector3[numVertices];
+		vertData->uv0 = new Vector2[numVertices];
+
+		Vector2* vec2Buffer = new Vector2[numVertices];
+
+		mTextSprite->fillBuffer(vec2Buffer, vertData->uv0, (UINT32*)textData->index, 0, numTextFaces);
+
+		for(UINT32 i = 0; i < numVertices; i++)
+		{
+			vertData->vertex[i] = Vector3(vec2Buffer[i].x, vec2Buffer[i].y, 0.0f);
+		}
+
+		textData->vertexBuffers[0] = vertData;
+
+		MeshData::SubMeshData subMeshData;
+		subMeshData.indexOffset = 0;
+		subMeshData.indexCount = numIndices;
+		textData->subMeshes.push_back(subMeshData);
+
+		mTextMesh->setMeshData(textData);
+
+		delete[] vec2Buffer;
+
+		mTextRenderable->setMesh(mTextMesh);
+
+		UINT32 nearestSize = font->getClosestAvailableSize(12);
+		const FontData* fontData = font->getFontDataForSize(nearestSize);
+
+		TextureHandle texturePage = fontData->texturePages[0]; // TODO - This won't work if font uses multiple pages
+		textMaterial->setTexture("tex", texturePage);
+		mTextRenderable->setMaterial(textMaterial);
+	}
+
+	void TestTextSprite::update()
+	{
+
+	}
+}

+ 24 - 0
CamelotClient/CmTestTextSprite.h

@@ -0,0 +1,24 @@
+#include "CmPrerequisites.h"
+#include "CmComponent.h"
+
+namespace CamelotEngine
+{
+	class TestTextSprite : public Component
+	{
+	private:
+		friend class GameObject;
+
+		TestTextSprite(GameObjectPtr parent);
+
+		RenderablePtr mTextRenderable;
+		MeshHandle mTextMesh;
+		TextSprite* mTextSprite;
+
+	public:
+		~TestTextSprite();
+
+		virtual void update();
+
+		void setText(const String& text, FontHandle font, UINT32 fontSize, MaterialHandle textMaterial);
+	};
+}

+ 1 - 1
CamelotCore/Include/CmCoreObject.h

@@ -129,7 +129,7 @@ o		 *
 	private:
 		friend class CoreGpuObjectManager;
 
-		UINT8 mFlags;
+		volatile UINT8 mFlags;
 		UINT64 mInternalID; // ID == 0 is not a valid ID
 		std::weak_ptr<CoreObject> mThis;
 

+ 1 - 1
CamelotCore/Include/CmFont.h

@@ -10,7 +10,7 @@ namespace CamelotEngine
 	{
 		UINT32 size;
 		FONT_DESC fontDesc;
-		vector<TexturePtr>::type texturePages;
+		vector<TextureHandle>::type texturePages;
 
 		const CHAR_DESC& getCharDesc(UINT32 charId) const;
 

+ 1 - 1
CamelotCore/Include/CmFontDesc.h

@@ -26,7 +26,7 @@ namespace CamelotEngine
 	struct FONT_DESC
 	{
 		map<UINT32, CHAR_DESC>::type characters;
-		UINT32 baselineOffset;
+		INT32 baselineOffset;
 		UINT32 lineHeight;
 		CHAR_DESC missingGlyph;
 		UINT32 spaceWidth;

+ 3 - 3
CamelotCore/Include/CmFontRTTI.h

@@ -31,12 +31,12 @@ namespace CamelotEngine
 			obj->fontDesc = val;
 		}
 
-		TexturePtr getTexture(FontData* obj, UINT32 idx)
+		TextureHandle& getTexture(FontData* obj, UINT32 idx)
 		{
 			return obj->texturePages.at(idx);
 		}
 
-		void setTexture(FontData* obj, UINT32 idx, TexturePtr value)
+		void setTexture(FontData* obj, UINT32 idx, TextureHandle& value)
 		{
 			obj->texturePages[idx] = value;
 		}
@@ -56,7 +56,7 @@ namespace CamelotEngine
 		{
 			addPlainField("size", 0, &FontDataRTTI::getSize, &FontDataRTTI::setSize);
 			addPlainField("fontDesc", 1, &FontDataRTTI::getFontDesc, &FontDataRTTI::setFontDesc);
-			addReflectablePtrArrayField("texturePages", 2, &FontDataRTTI::getTexture, &FontDataRTTI::getTextureArraySize, &FontDataRTTI::setTexture, &FontDataRTTI::setTextureArraySize);
+			addReflectableArrayField("texturePages", 2, &FontDataRTTI::getTexture, &FontDataRTTI::getTextureArraySize, &FontDataRTTI::setTexture, &FontDataRTTI::setTextureArraySize);
 		}
 
 		virtual const String& getRTTIName()

+ 2 - 0
CamelotCore/Include/CmPrerequisites.h

@@ -147,6 +147,7 @@ namespace CamelotEngine {
 	class CoreObject;
 	class ImportOptions;
 	struct FontData;
+	class TextSprite;
 	// Asset import
 	class SpecificImporter;
 	class Importer;
@@ -217,6 +218,7 @@ namespace CamelotEngine
 	typedef std::shared_ptr<ImportOptions> ImportOptionsPtr;
 	typedef std::shared_ptr<const ImportOptions> ConstImportOptionsPtr;
 	typedef std::shared_ptr<Font> FontPtr;
+	typedef std::shared_ptr<TextSprite> TextSpritePtr;
 }
 
 /************************************************************************/

+ 1 - 0
CamelotCore/Include/CmSprite.h

@@ -37,6 +37,7 @@ namespace CamelotEngine
 		SpriteAnchor getAnchor() const { return mAnchor; }
 
 		UINT32 fillBuffer(Vector2* vertices, Vector2* uv, UINT32* indices, UINT32 startingQuad, UINT32 maxNumQuads);
+		UINT32 getNumFaces();
 
 	protected:
 		Point mOffset;

+ 1 - 0
CamelotCore/Include/CmTextSprite.h

@@ -18,6 +18,7 @@ namespace CamelotEngine
 	class CM_EXPORT TextSprite : public Sprite
 	{
 	public:
+		TextSprite();
 		TextSprite(const String& text, FontPtr font, UINT32 fontSize);
 
 		void setText(const String& text) { mText = text; setDirty(); }

+ 2 - 2
CamelotCore/Source/CmMesh.cpp

@@ -62,7 +62,7 @@ namespace CamelotEngine
 			mIndexData->indexCount, 
 			GBU_STATIC);
 
-		UINT32* idxData = static_cast<UINT32*>(mIndexData->indexBuffer->lock(GBL_READ_WRITE));
+		UINT32* idxData = static_cast<UINT32*>(mIndexData->indexBuffer->lock(GBL_WRITE_ONLY_DISCARD));
 
 		for(UINT32 i = 0; i < mIndexData->indexCount; i++)
 		{
@@ -89,7 +89,7 @@ namespace CamelotEngine
 			mVertexData->setBuffer(streamIdx, vertexBuffer);
 
 			UINT32 vertexSize = vertexBuffer->getVertexSize();
-			UINT8* vertBufferData = static_cast<UINT8*>(vertexBuffer->lock(GBL_READ_WRITE));
+			UINT8* vertBufferData = static_cast<UINT8*>(vertexBuffer->lock(GBL_WRITE_ONLY_DISCARD));
 
 			UINT32 numElements = mVertexData->vertexDeclaration->getElementCount();
 

+ 20 - 3
CamelotCore/Source/CmSprite.cpp

@@ -17,6 +17,12 @@ namespace CamelotEngine
 
 	UINT32 Sprite::fillBuffer(Vector2* vertices, Vector2* uv, UINT32* indices, UINT32 startingQuad, UINT32 maxNumQuads)
 	{
+		if(mIsDirty)
+		{
+			updateMesh();
+			mIsDirty = false;
+		}
+
 		UINT32 startVert = startingQuad * 4;
 		UINT32 startIndex = startingQuad * 4;
 
@@ -26,12 +32,23 @@ namespace CamelotEngine
 		UINT32 mNumVertices = mNumMeshQuads * 4;
 		UINT32 mNumIndices = mNumMeshQuads * 6;
 
-		assert((startVert + mNumVertices) < maxVertIdx);
-		assert((startIndex + mNumIndices) < maxIndexIdx);
+		assert((startVert + mNumVertices) <= maxVertIdx);
+		assert((startIndex + mNumIndices) <= maxIndexIdx);
 
 		memcpy(&vertices[startVert], mVertices, mNumVertices * sizeof(Vector2));
 		memcpy(&uv[startVert], mUVs, mNumVertices * sizeof(Vector2));
-		memcpy(&indices[startIndex], mIndexes, mNumVertices * sizeof(UINT32));
+		memcpy(&indices[startIndex], mIndexes, mNumIndices * sizeof(UINT32));
+
+		return mNumMeshQuads;
+	}
+
+	UINT32 Sprite::getNumFaces()
+	{
+		if(mIsDirty)
+		{
+			updateMesh();
+			mIsDirty = false;
+		}
 
 		return mNumMeshQuads;
 	}

+ 18 - 9
CamelotCore/Source/CmTextSprite.cpp

@@ -93,6 +93,8 @@ namespace CamelotEngine
 				mLastWord = newWord;
 
 				mWords.push_back(mLastWord);
+
+				mLastWord->addChar(charDesc);
 			}
 			else
 			{
@@ -182,20 +184,20 @@ namespace CamelotEngine
 
 						vertices[curVert + 0] = Vector2((float)curX, (float)curY);
 						vertices[curVert + 1] = Vector2((float)(curX + charIter->width), (float)curY);
-						vertices[curVert + 2] = Vector2((float)curX, (float)(curY + charIter->height));
-						vertices[curVert + 3] = Vector2((float)(curX + charIter->width), (float)(curY + charIter->height));
+						vertices[curVert + 2] = Vector2((float)curX, (float)curY - (float)charIter->height);
+						vertices[curVert + 3] = Vector2((float)(curX + charIter->width), (float)curY - (float)charIter->height);
 
 						uv[curVert + 0] = Vector2(charIter->uvX, charIter->uvY);
 						uv[curVert + 1] = Vector2(charIter->uvX + charIter->uvWidth, charIter->uvY);
 						uv[curVert + 2] = Vector2(charIter->uvX, charIter->uvY + charIter->uvHeight);
 						uv[curVert + 3] = Vector2(charIter->uvX + charIter->uvWidth, charIter->uvY + charIter->uvHeight);
 
-						indices[curIndex + 0] = 0;
-						indices[curIndex + 1] = 2;
-						indices[curIndex + 2] = 1;
-						indices[curIndex + 3] = 1;
-						indices[curIndex + 4] = 2;
-						indices[curIndex + 5] = 3;
+						indices[curIndex + 0] = curVert + 0;
+						indices[curIndex + 1] = curVert + 1;
+						indices[curIndex + 2] = curVert + 2;
+						indices[curIndex + 3] = curVert + 1;
+						indices[curIndex + 4] = curVert + 3;
+						indices[curIndex + 5] = curVert + 2;
 
 						penX += charIter->xAdvance + kerning;
 						curVert += 4;
@@ -236,6 +238,12 @@ namespace CamelotEngine
 		}
 	};
 
+	TextSprite::TextSprite()
+		:mFontSize(0), mWordWrap(false), mHorzAlign(THA_Left), mVertAlign(TVA_Top)
+	{
+
+	}
+
 	TextSprite::TextSprite(const String& text, FontPtr font, UINT32 fontSize)
 		:mText(text), mFont(font), mFontSize(fontSize), mWordWrap(false), mHorzAlign(THA_Left), mVertAlign(TVA_Top)
 	{
@@ -257,6 +265,7 @@ namespace CamelotEngine
 		}
 
 		bool heightIsLimited = mHeight > 0;
+		bool widthIsLimited = mWidth > 0;
 
 		TextLine* curLine = new TextLine();
 		vector<TextLine*>::type textLines;
@@ -291,7 +300,7 @@ namespace CamelotEngine
 			if(charDesc.charId != SPACE_CHAR)
 				mNumMeshQuads++;
 
-			if(curLine->getWidth() > mWidth)
+			if(widthIsLimited && curLine->getWidth() > mWidth)
 			{
 				if(mWordWrap)
 				{

+ 10 - 0
CamelotD3D11RenderSystem/Source/CmD3D11RenderSystem.cpp

@@ -511,6 +511,11 @@ namespace CamelotEngine
 		applyInputLayout();
 
 		mDevice->getImmediateContext()->Draw(vertexCount, 0);
+
+#if CM_DEBUG_MODE
+		if(mDevice->hasError())
+			LOGWRN(mDevice->getErrorDescription());
+#endif
 	}
 
 	void D3D11RenderSystem::drawIndexed(UINT32 startIndex, UINT32 indexCount, UINT32 vertexCount)
@@ -520,6 +525,11 @@ namespace CamelotEngine
 		applyInputLayout();
 
 		mDevice->getImmediateContext()->DrawIndexed(indexCount, startIndex, 0);
+
+#if CM_DEBUG_MODE
+		if(mDevice->hasError())
+			LOGWRN(mDevice->getErrorDescription());
+#endif
 	}
 
 	void D3D11RenderSystem::setScissorRect(UINT32 left, UINT32 top, UINT32 right, UINT32 bottom)

+ 4 - 4
CamelotFontImporter/Source/CmFontImporter.cpp

@@ -122,7 +122,7 @@ namespace CamelotEngine
 			TexAtlasGenerator texAtlasGen(false, MAXIMUM_TEXTURE_SIZE, MAXIMUM_TEXTURE_SIZE);
 			vector<TexAtlasPageDesc>::type pages = texAtlasGen.createAtlasLayout(atlasElements);
 
-			UINT32 baselineOffset = 0;
+			INT32 baselineOffset = 0;
 			UINT32 lineHeight = 0;
 
 			// Create char bitmap atlas textures and load character information
@@ -198,7 +198,7 @@ namespace CamelotEngine
 					charDesc.xAdvance = slot->advance.x >> 6;
 					charDesc.yAdvance = slot->advance.y >> 6;
 
-					baselineOffset = std::max(baselineOffset, (UINT32)(slot->metrics.horiBearingY >> 6));
+					baselineOffset = std::max(baselineOffset, (INT32)(slot->metrics.horiBearingY >> 6));
 					lineHeight = std::max(lineHeight, charDesc.height);
 
 					// Load kerning and store char
@@ -238,10 +238,10 @@ namespace CamelotEngine
 				}
 
 				TextureHandle newTex = Texture::create(TEX_TYPE_2D, pageIter->width, pageIter->height, 0, PF_R8G8);
-				newTex->waitUntilInitialized();
+				newTex.waitUntilLoaded();
 				newTex->setRawPixels(pixelData);
 
-				fontData.texturePages.push_back(newTex.getInternalPtr());
+				fontData.texturePages.push_back(newTex);
 
 				pageIdx++;
 			}

+ 23 - 2
CamelotUtility/Source/CmTexAtlasGenerator.cpp

@@ -124,7 +124,7 @@ namespace CamelotEngine
 
 		UINT32 lastPageWidth = mMaxTexWidth;
 		UINT32 lastPageHeight = mMaxTexHeight;
-		UINT32 lastPageIdx = numPages - 1;
+		INT32 lastPageIdx = numPages - 1;
 
 		// If size isn't fixed, try to reduce the size of the last page
 		if(!mFixedSize)
@@ -155,7 +155,7 @@ namespace CamelotEngine
 				// Clear page indexes so we know which pages to process
 				for(size_t i = 0; i < elements.size(); i++)
 				{
-					if(elements[i].output.page == lastPageIdx)
+					if(elements[i].output.page >= lastPageIdx)
 						elements[i].output.page = -1;
 				}
 
@@ -165,7 +165,28 @@ namespace CamelotEngine
 					lastPageHeight = newLastPageHeight;
 				}
 				else
+				{
+					// We're done but we need to re-do all the pages with the last valid size
+					for(size_t i = 0; i < elements.size(); i++)
+					{
+						if(elements[i].output.page >= lastPageIdx)
+							elements[i].output.page = -1;
+					}
+
+					generatePagesForSize(elements, lastPageWidth, lastPageHeight, lastPageIdx);
+
 					break;
+				}
+			}
+		}
+
+		// Handle degenerate case
+		for(size_t i = 0; i < elements.size(); i++)
+		{
+			if(elements[i].output.page == -1 && elements[i].input.width == 0 && elements[i].input.height == 0)
+			{
+				elements[i].output.x = 0;
+				elements[i].output.y = 0;
 			}
 		}
 

+ 23 - 2
TODO.txt

@@ -19,8 +19,29 @@ Figure out how to store texture references in a font?
 	 - In inspector they can be expanded as children of the main resource, but cannot be directly modified?
 	 - Deleting the main resource deletes the children too
 
-Add Debug.SaveToBMP(PixelData)
-Add TextureAtlas.Generate() -> accepts coords and returns new coords. Doesn't deal with actual textures
+Move Debug to CamelotCore and add SetFillMode
+
+Add HLSL9 and GLSL text materials & shaders
+Add resolution to GUI shader
+Add 0.5 offset to GUI shader (depending on render system)
+Add transparency to GUI shader
+TextSprite needs to return multiple buffers in case characters are from different pages
+
+
+Mesh usability overhaul:
+ I need to be able to initialize Mesh without manually populating MeshData because it's very inconvenient
+ I need to be able to provide non-fixed vertex data. Right now for example VertexData only accepts Vector3 as vertex data. While for UI stuff I need Vector2.
+ A way to clear a mesh  (Mesh.Clear)
+ A way to update mesh buffers without recreating vertex/index buffers (Setting data currently does exactly that)
+
+Mesh
+ -> Make sure MeshData can use 16bit index buffers, and variable size elements (not just limited for Vector3 for position for example)
+ -> Make sure buffers aren't re-created each time SetMeshData is called. Instead clear existing buffers and update them. Possibly delete extra sub-mesh buffers.
+ -> setVertices(data, num, stream = 0, submesh = 0)
+ -> setVertices2D(data, num, stream = 0, submesh = 0)
+ -> setUV(data, num, stream = 0, submesh = 0)
+ - > similar methods for Normal, Color, Tangent Bitangent, UV1 and indices
+ -> make MeshData.index a UINT32* ptr
 
  Names: TextMesh & SpriteMesh instead of 2DText and 2DSprite!