From b7310c9cce95bfc9bfe135063ee0e97fbc654928 Mon Sep 17 00:00:00 2001 From: chai Date: Mon, 1 Nov 2021 16:53:51 +0800 Subject: *misc --- Data/Libraries/GameLab/Editor/GUI/FontManager.lua | 0 Data/Scripts/EditorApplication.lua | 2 + Editor/EditorMain.cpp | 16 ++-- Editor/Scripting/EditorScripting.cpp | 4 +- Projects/VisualStudio/Editor/Editor.vcxproj | 2 + .../VisualStudio/Editor/Editor.vcxproj.filters | 9 ++ Runtime/Common/DataBuffer.h | 6 +- Runtime/GUI/Font.cpp | 89 +++++++++++++++--- Runtime/GUI/Font.h | 56 ++++++++--- Runtime/Graphics/Texture.h | 4 + Runtime/Lua/LuaHelper.cpp | 1 + Runtime/Scripting/GUI/Font.bind.cpp | 103 +++++++++++++++++++++ Runtime/Scripting/GUI/GUI.bind.cpp | 24 +++++ 13 files changed, 282 insertions(+), 34 deletions(-) create mode 100644 Data/Libraries/GameLab/Editor/GUI/FontManager.lua create mode 100644 Runtime/Scripting/GUI/Font.bind.cpp create mode 100644 Runtime/Scripting/GUI/GUI.bind.cpp diff --git a/Data/Libraries/GameLab/Editor/GUI/FontManager.lua b/Data/Libraries/GameLab/Editor/GUI/FontManager.lua new file mode 100644 index 0000000..e69de29 diff --git a/Data/Scripts/EditorApplication.lua b/Data/Scripts/EditorApplication.lua index e9dbc32..00b72b5 100644 --- a/Data/Scripts/EditorApplication.lua +++ b/Data/Scripts/EditorApplication.lua @@ -112,6 +112,8 @@ local fsh = [[ ]] BeforeMainLoop() + +_G["default_font"] = while true do diff --git a/Editor/EditorMain.cpp b/Editor/EditorMain.cpp index 187df1c..a74a0b2 100644 --- a/Editor/EditorMain.cpp +++ b/Editor/EditorMain.cpp @@ -20,14 +20,14 @@ void ErrorHandle(cc8* msg) void TestFont() { - TextGeneratingSettings setting; - setting.margin = 5; - setting.padding = 5; - setting.atlasSize = Internal::Vector2(512, 512); - - Font::Instance()->Setup(setting); - auto content = L"abcdf与电子计算机的区别 与电子计算机的最大区别在于: 只是简单的计算工具,有些机型具备函数计算功能,有些机型具备一定的贮存功能,但一般只能存储几组数据。计算机则具备复杂存贮功能、控制功能,更加"; - Font::Instance()->RenderCharacters((character::Codepoint*)content, wcslen(content), 14); + //TextGeneratingSettings setting; + //setting.margin = 5; + //setting.padding = 5; + //setting.atlasSize = Internal::Vector2(512, 512); + + //Font::Instance()->Setup(setting); + //auto content = L"abcdf与电子计算机的区别 与电子计算机的最大区别在于: 只是简单的计算工具,有些机型具备函数计算功能,有些机型具备一定的贮存功能,但一般只能存储几组数据。计算机则具备复杂存贮功能、控制功能,更加"; + // Font::Instance()->RenderCharacters((character::Codepoint*)content, wcslen(content), 14); } int BeforeMainLoop(lua_State* L) diff --git a/Editor/Scripting/EditorScripting.cpp b/Editor/Scripting/EditorScripting.cpp index 43ed666..c8cfbbb 100644 --- a/Editor/Scripting/EditorScripting.cpp +++ b/Editor/Scripting/EditorScripting.cpp @@ -14,6 +14,7 @@ extern int luaopen_GameLab_Engine_Networking(lua_State* L); // GameLab.Engine.Ne extern int luaopen_GameLab_Engine_Animation(lua_State* L); // GameLab.Engine.Animation extern int luaopen_GameLab_Engine_GL(lua_State* L);// GameLab.Engine.GL extern int luaopen_GameLab_Engine_Resource(lua_State* L); // GameLab.Engine.Resource +extern int luaopen_GameLab_Engine_GUI(lua_State* L); extern int luaopen_GameLab_Editor(lua_State* L); // GameLab.Editor extern int luaopen_GameLab_Editor_GUI(lua_State* L); // GameLab.Editor.GUI @@ -44,7 +45,8 @@ bool SetupGameLabEditorScripting(lua_State* L) openlib(luaopen_GameLab_Engine_Rendering); openlib(luaopen_GameLab_Engine_GL); - openlib(luaopen_GameLab_Engine_Resource); + openlib(luaopen_GameLab_Engine_Resource); + openlib(luaopen_GameLab_Engine_GUI); openlib(luaopen_GameLab_Editor); openlib(luaopen_GameLab_Editor_GUI); diff --git a/Projects/VisualStudio/Editor/Editor.vcxproj b/Projects/VisualStudio/Editor/Editor.vcxproj index f732067..8e3b015 100644 --- a/Projects/VisualStudio/Editor/Editor.vcxproj +++ b/Projects/VisualStudio/Editor/Editor.vcxproj @@ -222,6 +222,8 @@ + + diff --git a/Projects/VisualStudio/Editor/Editor.vcxproj.filters b/Projects/VisualStudio/Editor/Editor.vcxproj.filters index edda3e3..4963b95 100644 --- a/Projects/VisualStudio/Editor/Editor.vcxproj.filters +++ b/Projects/VisualStudio/Editor/Editor.vcxproj.filters @@ -115,6 +115,9 @@ {c87ed6d9-48d6-4c07-8b94-d33e8f5a5f9c} + + {f209c361-c009-43ac-9e02-aa06804da376} + @@ -393,6 +396,12 @@ Runtime\GUI + + Runtime\Scripting\GUI + + + Runtime\Scripting\GUI + diff --git a/Runtime/Common/DataBuffer.h b/Runtime/Common/DataBuffer.h index 7b89ab5..dbe7c30 100644 --- a/Runtime/Common/DataBuffer.h +++ b/Runtime/Common/DataBuffer.h @@ -23,7 +23,11 @@ public: delete data; } - char* data; + union { + char* data; + unsigned char* udata; + char* sdata; + }; int length; EDataBufferType type; diff --git a/Runtime/GUI/Font.cpp b/Runtime/GUI/Font.cpp index f00f33d..67a2e3b 100644 --- a/Runtime/GUI/Font.cpp +++ b/Runtime/GUI/Font.cpp @@ -13,21 +13,86 @@ using namespace character; //https://baike.baidu.com/item/%E5%9F%BA%E6%9C%AC%E5%A4%9A%E6%96%87%E7%A7%8D%E5%B9%B3%E9%9D%A2/10788078 //https://stackoverflow.com/questions/27331819/whats-the-difference-between-a-character-a-code-point-a-glyph-and-a-grapheme -void Font::Setup(TextGeneratingSettings settings) +static std::string s_FontError; + +Font::Font(std::string path, TextGeneratingSettings settings) + : LuaBind::NativeClass() { - m_AtlasMargin = settings.margin; - m_GlyphPadding = settings.padding; - m_AtlasSize = settings.atlasSize; + m_AtlasMargin = settings.margin; + m_GlyphPadding = settings.padding; + m_AtlasSize = settings.atlasSize; - if (FT_Init_FreeType(&m_FTLibrary)) - { - return; - } + if (FT_Init_FreeType(&m_FTLibrary)) + { + s_FontError = "Init freetype error. Font path " + path; + throw FontException(s_FontError.c_str()); + } - if (FT_New_Face(m_FTLibrary, "Resources/Font/Deng.ttf", 0, &m_FTFace)) - { - return; - } + if (FT_New_Face(m_FTLibrary, path.c_str(), 0, &m_FTFace)) + { + s_FontError = "Create freetype face error. Font path " + path; + throw FontException(s_FontError.c_str()); + } +} + +Font::Font(LuaBind::VM* vm, std::string path, TextGeneratingSettings settings) + : LuaBind::NativeClass(vm) +{ + m_AtlasMargin = settings.margin; + m_GlyphPadding = settings.padding; + m_AtlasSize = settings.atlasSize; + + if (FT_Init_FreeType(&m_FTLibrary)) + { + s_FontError = "Init freetype error. Font path " + path; + throw FontException(s_FontError.c_str()); + } + + if (FT_New_Face(m_FTLibrary, path.c_str(), 0, &m_FTFace)) + { + s_FontError = "Create freetype face error. Font path " + path; + throw FontException(s_FontError.c_str()); + } +} + +Font::Font(DataBuffer* db, TextGeneratingSettings settings) + : LuaBind::NativeClass() +{ + m_AtlasMargin = settings.margin; + m_GlyphPadding = settings.padding; + m_AtlasSize = settings.atlasSize; + + if (FT_Init_FreeType(&m_FTLibrary)) + { + s_FontError = "Init freetype error."; + throw FontException(s_FontError.c_str()); + } + + if (FT_New_Memory_Face(m_FTLibrary, db->udata, db->length, 0, &m_FTFace)) + { + s_FontError = "Create freetype face error."; + throw FontException(s_FontError.c_str()); + } +} + +Font::Font(DataBuffer* db, LuaBind::VM* vm, std::string path, TextGeneratingSettings settings) + : LuaBind::NativeClass(vm) +{ + m_AtlasMargin = settings.margin; + m_GlyphPadding = settings.padding; + m_AtlasSize = settings.atlasSize; + + if (FT_Init_FreeType(&m_FTLibrary)) + { + s_FontError = "Init freetype error."; + throw FontException(s_FontError.c_str()); + } + + if (FT_New_Memory_Face(m_FTLibrary, db->udata, db->length, 0, &m_FTFace)) + { + s_FontError = "Create freetype face error."; + throw FontException(s_FontError.c_str()); + } } character::Hash Font::GetHash(Codepoint codepoint, int pixelSize) diff --git a/Runtime/GUI/Font.h b/Runtime/GUI/Font.h index da9ef55..242bd19 100644 --- a/Runtime/GUI/Font.h +++ b/Runtime/GUI/Font.h @@ -4,9 +4,11 @@ #include "Runtime/Graphics/Texture.h" #include "freetype.h" #include "Runtime/Lua/LuaHelper.h" +#include "Runtime/Common/DataBuffer.h" #include #include +#include #include //https://learnopengl.com/In-Practice/Text-Rendering @@ -64,10 +66,30 @@ struct TextGeneratingSettings int padding; // glyph相互之间的间距,防止采样的时候越界 }; -class Font : public Singleton +class FontException : public std::exception { public: - void Setup(TextGeneratingSettings settings); + FontException(const char* what) + : std::exception(what) + { + } +}; + +enum EEncoding +{ + Encoding_ASCII, + Encoding_UTF8, + Encoding_UTF16, +}; + +// 单个字体 +class Font : public LuaBind::NativeClass +{ +public: + Font(std::string path, TextGeneratingSettings setting)/*throw FontException*/; + Font(LuaBind::VM* vm, std::string path, TextGeneratingSettings setting)/*throw FontException*/; + Font(DataBuffer* db, TextGeneratingSettings setting)/*throw FontException*/; + Font(DataBuffer* db, LuaBind::VM* vm, std::string path, TextGeneratingSettings setting)/*throw FontException*/; const Character* GetCharacter(character::Codepoint codepoint, int pixelSize); const GlyphAtals* GetGlyphAtlas(int index); @@ -76,31 +98,41 @@ public: void RenderCharacter(character::Codepoint codepoint, int pixelSize); void RenderCharacters(character::Codepoint* codepoint, int n, int pixelSize); -private: - +private: Texture* CreateAtlas(); GlyphAtals* RequestAtlas(int pixelSize, Internal::Vector2 preferSize); - Internal::Rect GetRenderChartAndMove(GlyphAtals* atlas, Internal::Vector2 preferSize); bool HasEnoughSpace(GlyphAtals* atlas, Internal::Vector2 preferSize); - character::Hash GetHash(character::Codepoint Codepoint, int pixelSize); + //------------------------------------------------------------------------- + std::unordered_map m_Characters; // 渲染完的文字 - std::vector m_Atlases; // 当前所有的atlas - std::unordered_map m_AtlasCache; // 快速找到可用的atlas + std::vector m_Atlases; // 当前所有的atlas,由font完全拥有所有权,所以是lightuserdata + std::unordered_map m_AtlasCache; // 快速找到可用的atlas + + bool m_IsEnabled; - int m_AtlasMargin; - int m_GlyphPadding; Internal::Vector2 m_AtlasSize; + int m_AtlasMargin; + int m_GlyphPadding; FT_Library m_FTLibrary; - FT_Face m_FTFace; + FT_Face m_FTFace; + + //------------------------------------------------------------------------- + + LUA_BIND_DECL_CLASS(Font); + + LUA_BIND_DECL_METHOD(_New); + LUA_BIND_DECL_METHOD(_GetCharacter); + LUA_BIND_DECL_METHOD(_GetCharacters); + LUA_BIND_DECL_METHOD(_GetGlyphAtlas); }; -#define g_TextGenerator (*Font::Instance()) +//#define g_TextGenerator (*Font::Instance()) namespace TextHelper { diff --git a/Runtime/Graphics/Texture.h b/Runtime/Graphics/Texture.h index 6ead2fb..9633db5 100644 --- a/Runtime/Graphics/Texture.h +++ b/Runtime/Graphics/Texture.h @@ -76,6 +76,8 @@ public: private: void Init(TextureSetting setting, ImageData* imgData); + //------------------------------------------------------------------------------ + GLuint m_GPUID; int m_Width, m_Height; @@ -89,6 +91,8 @@ private: LuaBind::MemberRef m_ImageData; //图片像素数据 + //------------------------------------------------------------------------------ + LUA_BIND_DECL_CLASS(Texture); LUA_BIND_DECL_METHOD(_New); diff --git a/Runtime/Lua/LuaHelper.cpp b/Runtime/Lua/LuaHelper.cpp index e7247c0..2c95043 100644 --- a/Runtime/Lua/LuaHelper.cpp +++ b/Runtime/Lua/LuaHelper.cpp @@ -4,6 +4,7 @@ #include "Runtime/Math/Vector3.h" #include "Runtime/Math/Vector4.h" #include "Runtime/Math/Matrix44.h" +#include "Runtime/GUI/Font.h" using namespace LuaBind; diff --git a/Runtime/Scripting/GUI/Font.bind.cpp b/Runtime/Scripting/GUI/Font.bind.cpp new file mode 100644 index 0000000..73fb7e6 --- /dev/null +++ b/Runtime/Scripting/GUI/Font.bind.cpp @@ -0,0 +1,103 @@ +#include "Runtime/GUI/Font.h" +#include "Runtime/Graphics/Shader.h" +#include "Runtime/Debug/Log.h" +#include "Runtime/Graphics/GfxDevice.h" +#include "Runtime/Common/DataBuffer.h" + +LUA_BIND_REGISTRY(Font) +{ + LUA_BIND_REGISTER_METHODS(state, + { "New", _New }, + { "GetCharacter", _GetCharacter }, + { "GetGlyphAtlas", _GetGlyphAtlas } + ); +} + +LUA_BIND_POSTPROCESS(Font) +{ +} + +// Font.New(ttfPath, atlasSize, margin, padding) +// Font.New(ttfData, atlasSize, margin, padding) +LUA_BIND_IMPL_METHOD(Font, _New) +{ + LUA_BIND_STATE(L); + LUA_BIND_CHECK(L, "STNN!|UTNN!"); + + Font* font = NULL; + if (state.CheckParams(1, "STNN!")) + { + const char* path = state.GetValue(1, ""); + TextGeneratingSettings setting; + setting.atlasSize = state.GetValue(2, Internal::Vector2(128, 128)); + setting.margin = state.GetValue(3, 0); + setting.padding = state.GetValue(4, 0); + try { + font = new Font(path, setting); + } + catch (FontException& e) + { + log_error(e.what()); + state.PushNil(); + return 1; + } + } + else if (state.CheckParams(1, "UTNN!")) + { + DataBuffer* buffer = state.GetUserdata(1); + if (buffer == NULL) + { + log_error("Create font failed, DataBuffer is invalid."); + state.PushNil(); + return 1; + } + TextGeneratingSettings setting; + setting.atlasSize = state.GetValue(2, Internal::Vector2(128, 128)); + setting.margin = state.GetValue(3, 0); + setting.padding = state.GetValue(4, 0); + try { + font = new Font(buffer, setting); + } + catch (FontException& e) + { + log_error(e.what()); + state.PushNil(); + return 1; + } + } + + font->PushUserdata(state); + + return 1; +} + +// font:GetCharacter(char, size, encoding) +LUA_BIND_IMPL_METHOD(Font, _GetCharacter) +{ + LUA_BIND_PREPARE(L, Font); +// Character character = self->GetCharacter(character); + return 1; +} + +// font:GetCharacter(str, size, encoding) +LUA_BIND_IMPL_METHOD(Font, _GetCharacters) +{ + LUA_BIND_PREPARE(L, Font); +// Character character = self->GetCharacter(character); + return 1; +} + +// font:GetAtlas(i) +// return lightuserdata +LUA_BIND_IMPL_METHOD(Font, _GetGlyphAtlas) +{ + LUA_BIND_PREPARE(L, Font); + //LUA_BIND_CHECK(L, "UN"); + + //int i = state.GetValue(2, 0); + //GlyphAtals atlas = self->m_Atlases[i]; + + //state.Push((const void*)atlas.altas); + + return 1; +} \ No newline at end of file diff --git a/Runtime/Scripting/GUI/GUI.bind.cpp b/Runtime/Scripting/GUI/GUI.bind.cpp new file mode 100644 index 0000000..4f6ed7a --- /dev/null +++ b/Runtime/Scripting/GUI/GUI.bind.cpp @@ -0,0 +1,24 @@ +#include "Runtime/Lua/LuaHelper.h" +#include "Runtime/Debug/Log.h" +#include "Runtime/Common/DataBuffer.h" +#include "Runtime/FileSystem/FileJobs.h" +#include "Runtime/GUI/Font.h" + +using namespace std; +using namespace LuaBind; + +int luaopen_GameLab_Engine_GUI(lua_State* L) +{ + log_info_tag("Scripting", "luaopen_GameLab_Engine_GUI()"); + + LUA_BIND_STATE(L); + + state.PushGlobalNamespace(); + state.PushNamespace("GameLab"); + state.PushNamespace("Engine"); + state.PushNamespace("GUI"); + + state.RegisterNativeClass(); + + return 1; +} \ No newline at end of file -- cgit v1.1-26-g67d0