diff options
author | chai <chaifix@163.com> | 2021-11-05 12:14:59 +0800 |
---|---|---|
committer | chai <chaifix@163.com> | 2021-11-05 12:14:59 +0800 |
commit | 6d5787d8da9ad1685864668dd4c3d6aa73a563db (patch) | |
tree | f4d28a553b13b369a580c482e187bcc4b42f39de | |
parent | be9870f5c1ba4f6ae8cd9764f1a8ed56ee81ddd5 (diff) |
TextMeshGenerator
-rw-r--r-- | Data/Scripts/Editor/AssetBrowser.lua | 4 | ||||
-rw-r--r-- | Runtime/GUI/Font.h | 3 | ||||
-rw-r--r-- | Runtime/GUI/TextMeshGenerator.cpp | 89 | ||||
-rw-r--r-- | Runtime/GUI/TextMeshGenerator.h | 14 | ||||
-rw-r--r-- | Runtime/GUI/UITextMesh.cpp | 25 | ||||
-rw-r--r-- | Runtime/GUI/UITextMesh.h | 33 | ||||
-rw-r--r-- | Runtime/Graphics/Color.h | 6 | ||||
-rw-r--r-- | Runtime/Scripting/GUI/Font.bind.cpp | 8 | ||||
-rw-r--r-- | Runtime/Utilities/UtilMacros.h | 3 |
9 files changed, 163 insertions, 22 deletions
diff --git a/Data/Scripts/Editor/AssetBrowser.lua b/Data/Scripts/Editor/AssetBrowser.lua index c1542c2..d975934 100644 --- a/Data/Scripts/Editor/AssetBrowser.lua +++ b/Data/Scripts/Editor/AssetBrowser.lua @@ -39,6 +39,10 @@ AssetBrowser.OnGUI = function(self) --Engine.Rendering.SetTexture("gamelab_main_tex", tex)
--Engine.Rendering.DrawUIQuad({0, 0, 200, 200})
_G["default_font"]:GetCharacters("你好世界!\nHello,World!\nProject Window Properties", 12)
+
+ Engine.Rendering.SetVector2("gamelab_ui_position", {0, 100})
+ _G["default_font"]:GetCharacters("结构体A中包含了4字节长度的int一个", 12)
+
--Engine.Rendering.DrawUI9Slicing(1, {25, 25}, {25, 25}, {80, 80}, {400, 50} )
end
diff --git a/Runtime/GUI/Font.h b/Runtime/GUI/Font.h index cd546af..565fafc 100644 --- a/Runtime/GUI/Font.h +++ b/Runtime/GUI/Font.h @@ -31,10 +31,13 @@ namespace character union Hash { unsigned int hashCode; +#pragma pack(1) struct { Unicode codepoint; unsigned short size;//С }; +#pragma pack() + bool operator==(const Hash &other) const { return codepoint == other.codepoint && size == other.size; diff --git a/Runtime/GUI/TextMeshGenerator.cpp b/Runtime/GUI/TextMeshGenerator.cpp index 98d3b09..b4c8c4d 100644 --- a/Runtime/GUI/TextMeshGenerator.cpp +++ b/Runtime/GUI/TextMeshGenerator.cpp @@ -1,10 +1,89 @@ #include "TextMeshGenerator.h" -UITextMesh* TextMeshGenerator::GetTextMesh(const UnicodeString& str, Font* font, int pixelSize, int lineHeight, Color32 col32, ETextAnchor anchor, ETextAlignment alignment, bool wordwrap, float preferred) +// һϣֵ +static uint32_t GetStrHash(const UnicodeString& str) { - for (int i = 0; i < m_TextMeshes.size(); ++i) - { - UITextMesh* tm = m_TextMeshes[i]; + if (str.length == 0) + return 0; - } + int len = str.length; + uint32_t hash = (uint32_t)len; // seed + size_t step = (len >> 5) + 1;
+ for (int l = len; l >= step; l -= step)
+ {
+ unsigned short unicode = str.str[l - 1];
+ unsigned char hicode = *((unsigned char*)&unicode);
+ unsigned char locode = *(((unsigned char*)&unicode) + 1);
+ hash = hash ^ ((hash << 5) + (hash >> 2) + hicode + locode);
+ }
+ return hash;
+} + +const UITextMesh* TextMeshGenerator::GetTextMesh(
+ const UnicodeString& str
+ , Font* font
+ , int pixelSize
+ , int lineHeight
+ , Color32 col32
+ , ETextAnchor anchor
+ , ETextAlignment alignment
+ , bool wordwrap
+ , float preferred
+){ + uint32_t hash = GetStrHash(str); + UITextMeshList* tm = NULL; + bool hasHash = m_TextMeshes.count(hash); + if (hasHash) + { + tm = m_TextMeshes[hash]; + while (tm) + { + UITextMesh* mesh = tm->mesh; + if (mesh->GetFont() != font + || mesh->GetPixelSize() != pixelSize + || mesh->GetLineHeight() != lineHeight + || mesh->GetAnchor() != anchor + || mesh->GetAlignment() != alignment + || mesh->GetWordwrap() != wordwrap + || mesh->GetPreferred() != preferred + || mesh->GetColor() != col32 + ){ + tm = tm->next; + continue; + } + const UnicodeString& content = mesh->GetContent(); + if (content.length != str.length) + { + tm = tm->next; + continue; + } + if (memcmp(str.str, content.str, sizeof(character::Unicode) * str.length) == 0) + { + return tm->mesh; + } + tm = tm->next; + } + } + tm = new UITextMeshList(); + try { + tm->mesh = new UITextMesh(str, font, pixelSize, lineHeight, col32, anchor, alignment, wordwrap, preferred); + log_info("Text", "New UITextMesh"); + } + catch(TextMeshException& e) + { + delete tm; + throw; + } + if (hasHash) + { + UITextMeshList* list = m_TextMeshes[hash]; + tm->next = list; + m_TextMeshes[hash] = tm; + } + else + { + tm->next = NULL; + m_TextMeshes.insert(std::pair<uint32_t, UITextMeshList*>(hash, tm)); + } + return tm->mesh; } diff --git a/Runtime/GUI/TextMeshGenerator.h b/Runtime/GUI/TextMeshGenerator.h index dd4f1d9..815f4c4 100644 --- a/Runtime/GUI/TextMeshGenerator.h +++ b/Runtime/GUI/TextMeshGenerator.h @@ -3,9 +3,11 @@ #include "UITextMesh.h"
#include "Runtime/Utilities/IIncrementalTask.h"
#include "Font.h"
+#include "Runtime/Debug/Log.h"
#include <vector>
+#include <unordered_map>
-// collect unused text mesh gradually
+// ճûõtextmesh
class GraduallyReleaseTextMesh : public IIncrementalTask
{
public:
@@ -21,14 +23,18 @@ public: };
+struct UITextMeshList {
+ UITextMesh* mesh;
+ UITextMeshList* next;
+};
+
class TextMeshGenerator : public Singleton<TextMeshGenerator>
{
public:
- UITextMesh* GetTextMesh(const UnicodeString& str, Font* font, int pixelSize, int lineHeight, Color32 col32, ETextAnchor anchor, ETextAlignment alignment, bool wordwrap, float preferred);
+ const UITextMesh* GetTextMesh(const UnicodeString& str, Font* font, int pixelSize, int lineHeight, Color32 col32, ETextAnchor anchor, ETextAlignment alignment, bool wordwrap, float preferred);
private:
- std::vector<UITextMesh*> m_TextMeshes;
-
+ std::unordered_map<uint32_t, UITextMeshList*> m_TextMeshes;
};
#define g_TextMeshGenerator (*TextMeshGenerator::Instance())
\ No newline at end of file diff --git a/Runtime/GUI/UITextMesh.cpp b/Runtime/GUI/UITextMesh.cpp index 24aff47..23c0a9c 100644 --- a/Runtime/GUI/UITextMesh.cpp +++ b/Runtime/GUI/UITextMesh.cpp @@ -33,7 +33,6 @@ struct TextInfo { int line; // 0ʼ }; -static unordered_map<unsigned int, vector<TextInfo>> s_TextInfos; InitializeStaticVariables([]() { VertexAttributeDescriptor POSITION = VertexAttributeDescriptor(0, 2, VertexAttrFormat_Float, sizeof(TextMeshVBOLayout)); @@ -63,6 +62,20 @@ UITextMesh::UITextMesh( , bool wordwrap // Զ , float preferred // ԶС ){ + m_Font = font; + m_PixelSize = pixelSize; + m_LineHeight = lineHeight; + m_Color = color32; + m_Alignment = alignment; + m_Anchor = anchor; + m_Wordwrap = wordwrap; + m_Preferred = preferred; + m_Content.length = str.length; + m_Content.str = (character::Unicode*)malloc(str.length * sizeof(character::Unicode)); + memcpy(m_Content.str, str.str, str.length * sizeof(character::Unicode)); + + // ¼ıatlas + static unordered_map<unsigned int, vector<TextInfo>> s_TextInfos; s_TextInfos.clear(); // ¼ıÿеij @@ -76,9 +89,9 @@ UITextMesh::UITextMesh( InvokeWhenLeave([]() { s_LineWidths.clear(); s_LineOffsets.clear(); + s_TextInfos.clear(); }); - m_Font = font; const Vector2 atlasSize = font->GetAtlasSize(); //----------------------------------------------------------------- @@ -149,8 +162,10 @@ UITextMesh::UITextMesh( textRegion.y = (line + 1) * lineHeight; - if (s_TextInfos.size() == 0) - return; + if (s_TextInfos.size() == 0) + { + return; + } Vector2i textOffset; Vector2 halfRegion = Vector2(textRegion.x/ 2.f, textRegion.y / 2.f); @@ -240,7 +255,7 @@ UITextMesh::UITextMesh( WipeGLError(); } -void UITextMesh::Draw() +void UITextMesh::Draw() const { for (auto subText : m_VBOs) { diff --git a/Runtime/GUI/UITextMesh.h b/Runtime/GUI/UITextMesh.h index c298cb0..505b390 100644 --- a/Runtime/GUI/UITextMesh.h +++ b/Runtime/GUI/UITextMesh.h @@ -34,15 +34,34 @@ namespace TextHelper class UITextMesh { public: - UITextMesh(const UnicodeString& str, Font* font, int pixelSize, int lineHeight, Color32 color32 = Color32::white, ETextAnchor anchor = TextAnchor_UpperLeft, ETextAlignment alignment = TextAlignment_Left, bool wordwrap = false, float preferred = 0)/*throw TextMeshException*/; + void Draw() const; - ~UITextMesh(); + GET(const Font*, Font, m_Font); + GET(int, PixelSize, m_PixelSize); + GET(int, LineHeight, m_LineHeight); + GET(Color32, Color, m_Color); + GET(ETextAlignment, Alignment, m_Alignment); + GET(ETextAnchor, Anchor, m_Anchor); + GET(bool, Wordwrap, m_Wordwrap); + GET(float, Preferred, m_Preferred); + GET(const UnicodeString&, Content, m_Content); - void Draw(); +private: + friend class TextMeshGenerator; -private: - unsigned long long m_NotUniqueHash; - Font* m_Font; - std::unordered_map<int/*IndexOfAtlas*/, VertexBuffer*> m_VBOs; + UITextMesh(const UnicodeString& str, Font* font, int pixelSize, int lineHeight, Color32 color32 = Color32::white, ETextAnchor anchor = TextAnchor_UpperLeft, ETextAlignment alignment = TextAlignment_Left, bool wordwrap = false, float preferred = 0)/*throw TextMeshException*/; + ~UITextMesh(); + + std::unordered_map<int, VertexBuffer*> m_VBOs; + + Font* m_Font; + UnicodeString m_Content; + int m_PixelSize; + int m_LineHeight; + Color32 m_Color; + ETextAlignment m_Alignment; + ETextAnchor m_Anchor; + bool m_Wordwrap; + float m_Preferred; };
\ No newline at end of file diff --git a/Runtime/Graphics/Color.h b/Runtime/Graphics/Color.h index 41ca2a4..043590b 100644 --- a/Runtime/Graphics/Color.h +++ b/Runtime/Graphics/Color.h @@ -40,6 +40,12 @@ namespace Internal this->b = b; this->a = a; } + + bool operator !=(const Color32& col) + { + return !(r == col.r && g == col.g && b == col.b && a == col.a); + } + unsigned char r, g, b, a; static const Color32 white; diff --git a/Runtime/Scripting/GUI/Font.bind.cpp b/Runtime/Scripting/GUI/Font.bind.cpp index 7d7e3f2..0570df0 100644 --- a/Runtime/Scripting/GUI/Font.bind.cpp +++ b/Runtime/Scripting/GUI/Font.bind.cpp @@ -7,6 +7,8 @@ #include "Runtime/Utilities/StaticInitiator.h"
#include "Runtime/GUI/UITextMesh.h"
#include "Runtime/Math/Math.h" +#include "Runtime/GUI/TextMeshGenerator.h" +#include "Runtime/Utilities/AutoInvoke.h" static std::vector<character::Unicode>* s_Codepoints;
@@ -102,6 +104,10 @@ LUA_BIND_IMPL_METHOD(Font, _GetCharacters) int encoding = state.GetValue<int>(6, EEncoding::Encoding_UTF8);
s_Codepoints->clear();
+ InvokeWhenLeave([]() {
+ s_Codepoints->clear();
+ });
+
if (encoding == EEncoding::Encoding_UTF8)
{
while (*buf != 0) {
@@ -137,7 +143,7 @@ LUA_BIND_IMPL_METHOD(Font, _GetCharacters) WipeGLError();
- UITextMesh* tm = new UITextMesh(str, self, size, size + 3, Color32::white, TextAnchor_UpperLeft, TextAlignment_Left, wordwrap, preferred);
+ const UITextMesh* tm = g_TextMeshGenerator.GetTextMesh(str, self, size, size + 3, Color32::white, TextAnchor_UpperLeft, TextAlignment_Left, wordwrap, preferred);
tm->Draw();
return 0;
diff --git a/Runtime/Utilities/UtilMacros.h b/Runtime/Utilities/UtilMacros.h index 1941d7f..f48be5c 100644 --- a/Runtime/Utilities/UtilMacros.h +++ b/Runtime/Utilities/UtilMacros.h @@ -13,4 +13,7 @@ #define Mask(v) (1 << v) +#define cast(T, v) \ +((T)(v)) + #endif
\ No newline at end of file |