From c10e0d92f46e5eaf25a69e1fafe5f4dbd8eaab9d Mon Sep 17 00:00:00 2001 From: chai Date: Wed, 3 Nov 2021 09:52:26 +0800 Subject: *misc --- Runtime/GUI/Font.cpp | 7 +- Runtime/GUI/TextMesh.cpp | 168 -------------------------------------- Runtime/GUI/TextMesh.h | 50 ------------ Runtime/GUI/TextMeshGenerator.h | 4 +- Runtime/GUI/UI9Slicing.cpp | 30 +++++++ Runtime/GUI/UI9Slicing.h | 25 ++++++ Runtime/GUI/UIMesh.cpp | 15 ++++ Runtime/GUI/UIMesh.h | 32 ++++++++ Runtime/GUI/UIQuad.h | 4 +- Runtime/GUI/UITextMesh.cpp | 175 ++++++++++++++++++++++++++++++++++++++++ Runtime/GUI/UITextMesh.h | 50 ++++++++++++ 11 files changed, 336 insertions(+), 224 deletions(-) delete mode 100644 Runtime/GUI/TextMesh.cpp delete mode 100644 Runtime/GUI/TextMesh.h create mode 100644 Runtime/GUI/UI9Slicing.cpp create mode 100644 Runtime/GUI/UI9Slicing.h create mode 100644 Runtime/GUI/UIMesh.cpp create mode 100644 Runtime/GUI/UIMesh.h create mode 100644 Runtime/GUI/UITextMesh.cpp create mode 100644 Runtime/GUI/UITextMesh.h (limited to 'Runtime/GUI') diff --git a/Runtime/GUI/Font.cpp b/Runtime/GUI/Font.cpp index 8cdfdf3..614792a 100644 --- a/Runtime/GUI/Font.cpp +++ b/Runtime/GUI/Font.cpp @@ -146,8 +146,8 @@ void Font::RenderCharacter(character::Codepoint codepoint, int pixelSize) int w = m_FTFace->glyph->bitmap.width; int h = m_FTFace->glyph->bitmap.rows; - - //TextHelper::print_glyph(m_FTFace->glyph->bitmap.buffer, w, h); + + TextHelper::print_glyph(m_FTFace->glyph->bitmap.buffer, w, h); GlyphAtals* atlas = RequestAtlas(pixelSize, Internal::Vector2(w, h)); Assert(atlas); @@ -173,6 +173,9 @@ void Font::RenderCharacter(character::Codepoint codepoint, int pixelSize) character.advance = m_FTFace->glyph->advance.x * 1/64.f; m_Characters.insert(std::pair(hash, character)); +/* + FT_Done_Face(m_FTFace); + FT_Done_FreeType(m_FTLibrary);*/ } const GlyphAtals* Font::GetGlyphAtlas(int index) diff --git a/Runtime/GUI/TextMesh.cpp b/Runtime/GUI/TextMesh.cpp deleted file mode 100644 index 2f66170..0000000 --- a/Runtime/GUI/TextMesh.cpp +++ /dev/null @@ -1,168 +0,0 @@ -#include "../Graphics/CustomVertexLayout.h" -#include "Runtime/Utilities/StaticInitiator.h" -#include "../Math/Math.h" -#include "../Graphics/Color.h" -#include "TextMesh.h" -#include "../Graphics/DefaultVertexLayout.h" -#include "Runtime/Debug/Log.h" -#include -#include -#include "Runtime/Graphics/GfxDevice.h" - -using namespace std; - -struct TextMeshVBOLayout -{ - Vector2 position; - Vector2 uv; - Color32 color; -}; - -static CustomVertexLayout s_TextMeshVBOLayout; - -static unsigned int s_VertexPerText; -static unsigned int s_SizePerVertex; -static unsigned int s_SizePerText; -static unsigned int s_SizePerIndex; -static unsigned int s_IndicesPerText; - -struct TextInfo { - const Character* ch; - float offset; -}; - -static unordered_map> s_TextInfos; - -InitializeStaticVariables([]() { - VertexAttributeDescriptor POSITION = VertexAttributeDescriptor(0, 2, VertexAttrFormat_Float, sizeof(TextMeshVBOLayout)); - VertexAttributeDescriptor UV = VertexAttributeDescriptor(sizeof(Vector2), 2, VertexAttrFormat_Float, sizeof(TextMeshVBOLayout)); - VertexAttributeDescriptor COLOR = VertexAttributeDescriptor(sizeof(Vector2)*2, 4, VertexAttrFormat_Unsigned_Byte, sizeof(TextMeshVBOLayout), true); - s_TextMeshVBOLayout.attributes.push_back(POSITION); - s_TextMeshVBOLayout.attributes.push_back(UV); - s_TextMeshVBOLayout.attributes.push_back(COLOR); - - s_VertexPerText = 4; - s_SizePerVertex = sizeof(TextMeshVBOLayout); - - s_IndicesPerText = 6; - s_SizePerIndex = VertexLayout::GetDefaultIndexSize(); - - s_SizePerText = sizeof(TextMeshVBOLayout) * 4; -}); - -// 一段文字里面的网格可能会来自不同的atlas,在生成TextMesh时做好合批 - -TextMesh::TextMesh(const UnicodeString& str, Font* font,int pixelSize, ETextAnchor anchor, ETextAlignment alignment) -{ - m_Font = font; - s_TextInfos.clear(); - const Vector2 atlasSize = font->GetAtlasSize(); - - // 按照不同的atlas分类到s_TextInfos - float offset = 0; - for (int i = 0; i < str.length; ++i) - { - character::Codepoint c = str.str[i]; - const Character* ch = font->GetCharacter(c, pixelSize); - unsigned int atlasIndex = ch->atlas; - - TextInfo info; - info.ch = ch; - info.offset = offset; - - auto list = s_TextInfos.find(atlasIndex); - if (list == s_TextInfos.end()) - s_TextInfos.insert(std::pair>(atlasIndex, vector())); - - vector& v = s_TextInfos[atlasIndex]; - v.push_back(info); - - offset += ch->advance; - } - - if (s_TextInfos.size() == 0) - return; - - // 填充VBO和IBO - for (auto iter : s_TextInfos) { - unsigned int atlasIndex = iter.first; // atlas atlasIndex - vector& texts = iter.second; - int textCount = texts.size(); - - VertexBuffer* vb = new VertexBuffer(textCount * s_SizePerText, textCount * s_IndicesPerText * s_SizePerIndex, VertexBuffer::VertexBufferType_Static); - void* pVB; - uint16* pIB; - - vb->GetChunk(s_SizePerVertex, s_SizePerIndex, s_VertexPerText * textCount, s_IndicesPerText * textCount, EPrimitive::Primitive_Triangle, &pVB,(void**) &pIB); - - TextMeshVBOLayout* dst = (TextMeshVBOLayout*)pVB; - for (int i = 0; i < textCount; ++i) - { - TextInfo& text = texts[i]; - - int vOff = i * s_VertexPerText; - float pos[] = { - text.offset + text.ch->bearing.x, text.ch->bearing.y - text.ch->position.height, // bottom-left - text.offset + text.ch->bearing.x + text.ch->position.width, text.ch->bearing.y - text.ch->position.height, // bottom-right - text.offset + text.ch->bearing.x + text.ch->position.width, text.ch->bearing.y, // top-right - text.offset + text.ch->bearing.x, text.ch->bearing.y, // top-left - }; - // 左上角为UV原点,所以在shader里采样的时候要镜像y - Vector4 uvQuad = Vector4(text.ch->position.x / atlasSize.x, text.ch->position.y / atlasSize.y, text.ch->position.width / atlasSize.x, text.ch->position.height / atlasSize.y); - float uv[] = { - uvQuad.x, uvQuad.y + uvQuad.w, - uvQuad.x + uvQuad.z, uvQuad.y + uvQuad.w, - uvQuad.x + uvQuad.z, uvQuad.y, - uvQuad.x, uvQuad.y, - }; - for (int j = 0; j < s_VertexPerText; ++j) - { - dst[vOff + j].position.Set(pos[2 * j], pos[2 * j + 1]); - dst[vOff + j].uv.Set(uv[2 * j], uv[2 * j + 1]); - dst[vOff + j].color.Set(255 , 255, 255, 255); - } - - int iOff = i * s_IndicesPerText; - int indices[] = { - 0, 1, 3, // right-top - 1, 2, 3, // left-bottom - }; - for (int j = 0; j < s_IndicesPerText; ++j) - pIB[iOff + j] = vOff + indices[j]; - } - - vb->FlushChunk(s_VertexPerText * textCount, s_IndicesPerText * textCount); - - m_VBOs.insert(std::pair(atlasIndex, vb)); - } - - WipeGLError(); -} - -void TextMesh::Draw() -{ - for (auto subText : m_VBOs) - { - int atlasIndex = subText.first; // atlasIndex of atlas - VertexBuffer* vbo = subText.second; - - const GlyphAtals* atlas = m_Font->GetGlyphAtlas(atlasIndex); - if (atlas == NULL) - { - log_error("Render text failed, no glyph atlas."); - continue; - } - - g_GfxDevice.SetUniformTexture("gamelab_main_tex", atlas->altas); - - CheckGLError( - throw GLException(error); - ); - vbo->Draw(s_TextMeshVBOLayout); - - CheckGLError( - throw GLException(error); - ); - g_GfxDevice.ResetUniformsState(); - } -} diff --git a/Runtime/GUI/TextMesh.h b/Runtime/GUI/TextMesh.h deleted file mode 100644 index c5f05a2..0000000 --- a/Runtime/GUI/TextMesh.h +++ /dev/null @@ -1,50 +0,0 @@ -#pragma once -#include "../Graphics/VertexBuffer.h" -#include "Font.h" -#include "Runtime/Utilities/Exception.h" -#include - -CustomException(TextMeshException); - -enum ETextAnchor -{ - TextAnchor_UpperLeft, - TextAnchor_UpperCenter, - TextAnchor_UpperRight, - TextAnchor_MiddleLeft, - TextAnchor_MiddleCenter, - TextAnchor_MiddleRight, - TextAnchor_LowerLeft, - TextAnchor_LowerCenter, - TextAnchor_LowerRight, - TextAnchor_DontCare -}; - -enum ETextAlignment { - TextAlignment_Left, - TextAlignment_Center, - TextAlignment_Right, - TextAlignment_Auto, -}; - -typedef unsigned long long TextMeshHash; - -namespace TextHelper -{ - TextMeshHash GetTextMeshHash(); -} - -class TextMesh -{ -public: - TextMesh(const UnicodeString& str, Font* font, int pixelSize, ETextAnchor anchor, ETextAlignment alignment)/*throw TextMeshException*/; - - ~TextMesh(); - - void Draw(); - -private: - Font* m_Font; - std::unordered_map m_VBOs; - -}; \ No newline at end of file diff --git a/Runtime/GUI/TextMeshGenerator.h b/Runtime/GUI/TextMeshGenerator.h index baeaf16..94bcaa2 100644 --- a/Runtime/GUI/TextMeshGenerator.h +++ b/Runtime/GUI/TextMeshGenerator.h @@ -1,6 +1,6 @@ #pragma once -#include "TextMesh.h" +#include "UITextMesh.h" #include "Runtime/Utilities/IIncrementalTask.h" #include "Font.h" @@ -24,7 +24,7 @@ public: class TextMeshGenerator : public Singleton { public: - TextMesh* GetTextMesh(const UnicodeString& str); + UITextMesh* GetTextMesh(const UnicodeString& str); private: diff --git a/Runtime/GUI/UI9Slicing.cpp b/Runtime/GUI/UI9Slicing.cpp new file mode 100644 index 0000000..01a0143 --- /dev/null +++ b/Runtime/GUI/UI9Slicing.cpp @@ -0,0 +1,30 @@ +#include "UI9Slicing.h" + +UI9Slicing::UI9Slicing(ESlicing mode, Vector2 horizontal, Vector2 vertical, Vector2 texPixelSize, Vector2 size) +{ + m_Slicing = mode; + m_Horizontal = horizontal.Clamp(0, texPixelSize.x, 0, texPixelSize.x); + m_Vertical = vertical.Clamp(0, texPixelSize.y, 0, texPixelSize.y); + + if (m_Horizontal[0] + m_Horizontal[1] > texPixelSize.x || m_Vertical[0] + m_Vertical[1] > texPixelSize.y) + { + throw UIMeshException("UI9Slicing wrong parameter."); + } + m_TexSize = texPixelSize; + m_Size = size; +} + +void UI9Slicing::Draw() +{ + + + uint8* vb; + uint16* ib; + + g_SharedVBO.GetChunk(sizeof(UIVertexLayout), sizeof(uint16), 4, 6, Primitive_Triangle, (void**)&vb, (void**)&ib); + + + + g_SharedVBO.ReleaseChunk(4, 6); + g_SharedVBO.DrawChunk(UIMesh::s_UIVertexLayout); +} diff --git a/Runtime/GUI/UI9Slicing.h b/Runtime/GUI/UI9Slicing.h new file mode 100644 index 0000000..c88ba05 --- /dev/null +++ b/Runtime/GUI/UI9Slicing.h @@ -0,0 +1,25 @@ +#pragma once + +#include "UIMesh.h" + +enum ESlicing +{ + Slicing_Simple, + Slicing_Tiled, +}; + +// 九宫格 +class UI9Slicing : public UIMesh +{ +public: + UI9Slicing(ESlicing mode, Vector2 horizontal, Vector2 vertical, Vector2 texPixelSize, Vector2 size)/*throw UIMeshException*/; + + void Draw() override; + +private: + ESlicing m_Slicing; + Vector2 m_Horizontal; // 左右两条切割线到左边和右边的距离 + Vector2 m_Vertical; // 同上 + Vector2 m_TexSize; + Vector2 m_Size; +}; diff --git a/Runtime/GUI/UIMesh.cpp b/Runtime/GUI/UIMesh.cpp new file mode 100644 index 0000000..a68b6fd --- /dev/null +++ b/Runtime/GUI/UIMesh.cpp @@ -0,0 +1,15 @@ +#include "UIMesh.h" + +CustomVertexLayout UIMesh::s_UIVertexLayout; +unsigned int UIMesh::s_SizePerVertex; + +InitializeStaticVariables([]() { + VertexAttributeDescriptor POSITION = VertexAttributeDescriptor(0, 2, VertexAttrFormat_Float, sizeof(UIVertexLayout)); + VertexAttributeDescriptor UV = VertexAttributeDescriptor(sizeof(Vector2), 2, VertexAttrFormat_Float, sizeof(UIVertexLayout)); + VertexAttributeDescriptor COLOR = VertexAttributeDescriptor(sizeof(Vector2) * 2, 4, VertexAttrFormat_Unsigned_Byte, sizeof(UIVertexLayout), true); + UIMesh::s_UIVertexLayout.attributes.push_back(POSITION); + UIMesh::s_UIVertexLayout.attributes.push_back(UV); + UIMesh::s_UIVertexLayout.attributes.push_back(COLOR); + + UIMesh::s_SizePerVertex = sizeof(UIVertexLayout); +}); diff --git a/Runtime/GUI/UIMesh.h b/Runtime/GUI/UIMesh.h new file mode 100644 index 0000000..dd83e6e --- /dev/null +++ b/Runtime/GUI/UIMesh.h @@ -0,0 +1,32 @@ +#pragma once + +#include "Runtime/Utilities/Exception.h" +#include "Runtime/Rendering/DynamicMesh.h" +#include "Runtime/Math/Math.h" +#include "Runtime/Utilities/StaticInitiator.h" +#include "Runtime/Graphics/CustomVertexLayout.h" +#include "Runtime/Graphics/DefaultVertexLayout.h" +#include "Runtime/Graphics/Color.h" +#include "Runtime/Graphics/GfxDevice.h" + +struct UIVertexLayout +{ + Vector2 position; + Vector2 uv; + Color32 color; +}; + +CustomException(UIMeshException); + +// 所有的UIMesh都是左上角为原点 +class UIMesh : public DynamicMesh +{ +public: + UIMesh() : DynamicMesh() {} + virtual ~UIMesh() {} + + virtual void Draw() = 0; + + static CustomVertexLayout s_UIVertexLayout; + static unsigned int s_SizePerVertex; +}; diff --git a/Runtime/GUI/UIQuad.h b/Runtime/GUI/UIQuad.h index bcd95a0..278848a 100644 --- a/Runtime/GUI/UIQuad.h +++ b/Runtime/GUI/UIQuad.h @@ -1,8 +1,8 @@ #pragma once -#include "../Rendering/DynamicMesh.h" #include "../Utilities/StaticInitiator.h" +#include "UIMesh.h" -class UIQuad : public DynamicMesh +class UIQuad : public UIMesh { public : UIQuad(float l, float r, float t, float b) diff --git a/Runtime/GUI/UITextMesh.cpp b/Runtime/GUI/UITextMesh.cpp new file mode 100644 index 0000000..6a10f88 --- /dev/null +++ b/Runtime/GUI/UITextMesh.cpp @@ -0,0 +1,175 @@ +#include "../Graphics/CustomVertexLayout.h" +#include "Runtime/Utilities/StaticInitiator.h" +#include "../Math/Math.h" +#include "../Graphics/Color.h" +#include "UITextMesh.h" +#include "../Graphics/DefaultVertexLayout.h" +#include "Runtime/Debug/Log.h" +#include +#include +#include "Runtime/Graphics/GfxDevice.h" + +using namespace std; + +struct TextMeshVBOLayout +{ + Vector2 position; + Vector2 uv; + Color32 color; +}; + +static CustomVertexLayout s_TextMeshVBOLayout; + +static unsigned int s_VertexPerText; +static unsigned int s_SizePerVertex; +static unsigned int s_SizePerText; +static unsigned int s_SizePerIndex; +static unsigned int s_IndicesPerText; + +struct TextInfo { + const Character* ch; + float offset; +}; + +static unordered_map> s_TextInfos; + +InitializeStaticVariables([]() { + VertexAttributeDescriptor POSITION = VertexAttributeDescriptor(0, 2, VertexAttrFormat_Float, sizeof(TextMeshVBOLayout)); + VertexAttributeDescriptor UV = VertexAttributeDescriptor(sizeof(Vector2), 2, VertexAttrFormat_Float, sizeof(TextMeshVBOLayout)); + VertexAttributeDescriptor COLOR = VertexAttributeDescriptor(sizeof(Vector2)*2, 4, VertexAttrFormat_Unsigned_Byte, sizeof(TextMeshVBOLayout), true); + s_TextMeshVBOLayout.attributes.push_back(POSITION); + s_TextMeshVBOLayout.attributes.push_back(UV); + s_TextMeshVBOLayout.attributes.push_back(COLOR); + + s_VertexPerText = 4; + s_SizePerVertex = sizeof(TextMeshVBOLayout); + + s_IndicesPerText = 6; + s_SizePerIndex = VertexLayout::GetDefaultIndexSize(); + + s_SizePerText = sizeof(TextMeshVBOLayout) * 4; +}); + +// 一段文字里面的网格可能会来自不同的atlas,在生成UITextMesh时做好合批 + +// 需要支持 +// * 大小 +// * 锚点 +// * 对齐方式 +// * 换行 +// * 颜色 + +UITextMesh::UITextMesh(const UnicodeString& str, Font* font,int pixelSize, ETextAnchor anchor, ETextAlignment alignment) +{ + m_Font = font; + s_TextInfos.clear(); + const Vector2 atlasSize = font->GetAtlasSize(); + + // 按照不同的atlas分类到s_TextInfos + float offset = 0; + for (int i = 0; i < str.length; ++i) + { + character::Codepoint c = str.str[i]; + const Character* ch = font->GetCharacter(c, pixelSize); + unsigned int atlasIndex = ch->atlas; + + TextInfo info; + info.ch = ch; + info.offset = offset; + + auto list = s_TextInfos.find(atlasIndex); + if (list == s_TextInfos.end()) + s_TextInfos.insert(std::pair>(atlasIndex, vector())); + + vector& v = s_TextInfos[atlasIndex]; + v.push_back(info); + + offset += ch->advance; + } + + if (s_TextInfos.size() == 0) + return; + + // 填充VBO和IBO + for (auto iter : s_TextInfos) { + unsigned int atlasIndex = iter.first; // atlas atlasIndex + vector& texts = iter.second; + int textCount = texts.size(); + + VertexBuffer* vb = new VertexBuffer(textCount * s_SizePerText, textCount * s_IndicesPerText * s_SizePerIndex, VertexBuffer::VertexBufferType_Static); + void* pVB; + uint16* pIB; + + vb->GetChunk(s_SizePerVertex, s_SizePerIndex, s_VertexPerText * textCount, s_IndicesPerText * textCount, EPrimitive::Primitive_Triangle, &pVB,(void**) &pIB); + + TextMeshVBOLayout* dst = (TextMeshVBOLayout*)pVB; + for (int i = 0; i < textCount; ++i) + { + TextInfo& text = texts[i]; + + int vOff = i * s_VertexPerText; + // 左上角是原点 + float pos[] = { + text.offset + text.ch->bearing.x, pixelSize - text.ch->bearing.y + text.ch->position.height, // bottom-left + text.offset + text.ch->bearing.x + text.ch->position.width, pixelSize - text.ch->bearing.y + text.ch->position.height, // bottom-right + text.offset + text.ch->bearing.x + text.ch->position.width, pixelSize - text.ch->bearing.y, // top-right + text.offset + text.ch->bearing.x, pixelSize - text.ch->bearing.y, // top-left + }; + Vector4 uvQuad = Vector4(text.ch->position.x / atlasSize.x, text.ch->position.y / atlasSize.y, text.ch->position.width / atlasSize.x, text.ch->position.height / atlasSize.y); + float uv[] = { + uvQuad.x, uvQuad.y + uvQuad.w, + uvQuad.x + uvQuad.z, uvQuad.y + uvQuad.w, + uvQuad.x + uvQuad.z, uvQuad.y, + uvQuad.x, uvQuad.y, + }; + for (int j = 0; j < s_VertexPerText; ++j) + { + dst[vOff + j].position.Set(pos[2 * j], pos[2 * j + 1]); + dst[vOff + j].uv.Set(uv[2 * j], uv[2 * j + 1]); + dst[vOff + j].color.Set(255 , 255, 255, 255); + } + + int iOff = i * s_IndicesPerText; + int indices[] = { + 0, 1, 3, // right-top + 1, 2, 3, // left-bottom + }; + for (int j = 0; j < s_IndicesPerText; ++j) + pIB[iOff + j] = vOff + indices[j]; + } + + vb->FlushChunk(s_VertexPerText * textCount, s_IndicesPerText * textCount); + + m_VBOs.insert(std::pair(atlasIndex, vb)); + } + + WipeGLError(); +} + +void UITextMesh::Draw() +{ + for (auto subText : m_VBOs) + { + int atlasIndex = subText.first; // atlasIndex of atlas + VertexBuffer* vbo = subText.second; + + const GlyphAtals* atlas = m_Font->GetGlyphAtlas(atlasIndex); + if (atlas == NULL) + { + log_error("Render text failed, no glyph atlas."); + continue; + } + + g_GfxDevice.SetUniformTexture("gamelab_main_tex", atlas->altas); + + CheckGLError( + throw GLException(error); + ); + vbo->Draw(s_TextMeshVBOLayout); + + CheckGLError( + throw GLException(error); + ); + g_GfxDevice.ResetUniformsState(); + } +} diff --git a/Runtime/GUI/UITextMesh.h b/Runtime/GUI/UITextMesh.h new file mode 100644 index 0000000..c88e52f --- /dev/null +++ b/Runtime/GUI/UITextMesh.h @@ -0,0 +1,50 @@ +#pragma once +#include "../Graphics/VertexBuffer.h" +#include "Font.h" +#include "Runtime/Utilities/Exception.h" +#include + +CustomException(TextMeshException); + +enum ETextAnchor +{ + TextAnchor_UpperLeft, + TextAnchor_UpperCenter, + TextAnchor_UpperRight, + TextAnchor_MiddleLeft, + TextAnchor_MiddleCenter, + TextAnchor_MiddleRight, + TextAnchor_LowerLeft, + TextAnchor_LowerCenter, + TextAnchor_LowerRight, + TextAnchor_DontCare +}; + +enum ETextAlignment { + TextAlignment_Left, + TextAlignment_Center, + TextAlignment_Right, + TextAlignment_Auto, +}; + +typedef unsigned long long TextMeshHash; + +namespace TextHelper +{ + TextMeshHash GetTextMeshHash(); +} + +class UITextMesh +{ +public: + UITextMesh(const UnicodeString& str, Font* font, int pixelSize, ETextAnchor anchor, ETextAlignment alignment)/*throw TextMeshException*/; + + ~UITextMesh(); + + void Draw(); + +private: + Font* m_Font; + std::unordered_map m_VBOs; + +}; \ No newline at end of file -- cgit v1.1-26-g67d0