From d0314447eef484d1261c921759e232aa5d75f122 Mon Sep 17 00:00:00 2001 From: ChestnutYueyue <952134128@qq.com> Date: Wed, 11 Feb 2026 12:20:43 +0800 Subject: [PATCH] =?UTF-8?q?refactor(ui):=20=E9=87=8D=E6=9E=84UI=E7=BB=84?= =?UTF-8?q?=E4=BB=B6=E5=B9=B6=E7=A7=BB=E9=99=A4Squirrel=E8=84=9A=E6=9C=AC?= =?UTF-8?q?=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 重构UI组件系统,将Text组件从scene模块移动到ui模块,并新增CheckBox、RadioButton、Slider等UI控件 移除Squirrel脚本引擎及相关绑定代码,简化项目结构 调整.gitignore文件,添加.trae目录忽略 优化String类实现,使用Windows API进行GBK/UTF-8转换 更新构建配置,移除Squirrel相关依赖 --- .gitignore | 2 +- Extra2D/include/extra2d/core/string.h | 444 +++----------- Extra2D/include/extra2d/core/types.h | 6 + Extra2D/include/extra2d/extra2d.h | 11 +- Extra2D/include/extra2d/graphics/font.h | 1 - .../include/extra2d/graphics/render_backend.h | 1 - .../include/extra2d/script/script_engine.h | 41 -- Extra2D/include/extra2d/script/script_node.h | 33 -- Extra2D/include/extra2d/script/sq_binding.h | 263 -------- .../extra2d/script/sq_binding_action.h | 11 - .../extra2d/script/sq_binding_animation.h | 11 - .../include/extra2d/script/sq_binding_audio.h | 11 - .../include/extra2d/script/sq_binding_input.h | 13 - .../include/extra2d/script/sq_binding_node.h | 16 - .../include/extra2d/script/sq_binding_types.h | 31 - Extra2D/include/extra2d/ui/button.h | 1 + Extra2D/include/extra2d/ui/check_box.h | 74 +++ Extra2D/include/extra2d/ui/label.h | 149 +++++ Extra2D/include/extra2d/ui/progress_bar.h | 218 +++++++ Extra2D/include/extra2d/ui/radio_button.h | 96 +++ Extra2D/include/extra2d/ui/slider.h | 125 ++++ Extra2D/include/extra2d/{scene => ui}/text.h | 34 +- Extra2D/include/extra2d/ui/widget.h | 46 ++ Extra2D/src/core/string.cpp | 228 +------ Extra2D/src/graphics/opengl/gl_font_atlas.cpp | 9 +- Extra2D/src/graphics/opengl/gl_renderer.cpp | 3 +- Extra2D/src/script/script_engine.cpp | 187 ------ Extra2D/src/script/script_node.cpp | 202 ------- Extra2D/src/script/sq_binding_action.cpp | 222 ------- Extra2D/src/script/sq_binding_animation.cpp | 277 --------- Extra2D/src/script/sq_binding_audio.cpp | 91 --- Extra2D/src/script/sq_binding_input.cpp | 288 --------- Extra2D/src/script/sq_binding_node.cpp | 561 ------------------ Extra2D/src/script/sq_binding_types.cpp | 398 ------------- Extra2D/src/ui/button.cpp | 1 + Extra2D/src/ui/check_box.cpp | 135 +++++ Extra2D/src/ui/label.cpp | 313 ++++++++++ Extra2D/src/ui/progress_bar.cpp | 373 ++++++++++++ Extra2D/src/ui/radio_button.cpp | 185 ++++++ Extra2D/src/ui/slider.cpp | 337 +++++++++++ Extra2D/src/{scene => ui}/text.cpp | 98 ++- Extra2D/src/ui/widget.cpp | 4 +- xmake/engine.lua | 3 - 43 files changed, 2246 insertions(+), 3307 deletions(-) delete mode 100644 Extra2D/include/extra2d/script/script_engine.h delete mode 100644 Extra2D/include/extra2d/script/script_node.h delete mode 100644 Extra2D/include/extra2d/script/sq_binding.h delete mode 100644 Extra2D/include/extra2d/script/sq_binding_action.h delete mode 100644 Extra2D/include/extra2d/script/sq_binding_animation.h delete mode 100644 Extra2D/include/extra2d/script/sq_binding_audio.h delete mode 100644 Extra2D/include/extra2d/script/sq_binding_input.h delete mode 100644 Extra2D/include/extra2d/script/sq_binding_node.h delete mode 100644 Extra2D/include/extra2d/script/sq_binding_types.h create mode 100644 Extra2D/include/extra2d/ui/check_box.h create mode 100644 Extra2D/include/extra2d/ui/label.h create mode 100644 Extra2D/include/extra2d/ui/progress_bar.h create mode 100644 Extra2D/include/extra2d/ui/radio_button.h create mode 100644 Extra2D/include/extra2d/ui/slider.h rename Extra2D/include/extra2d/{scene => ui}/text.h (80%) delete mode 100644 Extra2D/src/script/script_engine.cpp delete mode 100644 Extra2D/src/script/script_node.cpp delete mode 100644 Extra2D/src/script/sq_binding_action.cpp delete mode 100644 Extra2D/src/script/sq_binding_animation.cpp delete mode 100644 Extra2D/src/script/sq_binding_audio.cpp delete mode 100644 Extra2D/src/script/sq_binding_input.cpp delete mode 100644 Extra2D/src/script/sq_binding_node.cpp delete mode 100644 Extra2D/src/script/sq_binding_types.cpp create mode 100644 Extra2D/src/ui/check_box.cpp create mode 100644 Extra2D/src/ui/label.cpp create mode 100644 Extra2D/src/ui/progress_bar.cpp create mode 100644 Extra2D/src/ui/radio_button.cpp create mode 100644 Extra2D/src/ui/slider.cpp rename Extra2D/src/{scene => ui}/text.cpp (61%) diff --git a/.gitignore b/.gitignore index a871c03..3a2cb15 100644 --- a/.gitignore +++ b/.gitignore @@ -14,7 +14,7 @@ /x64/ /x86/ /.build/ - +/.trae/ # -------------------------------------------- # xmake 构建系统 # -------------------------------------------- diff --git a/Extra2D/include/extra2d/core/string.h b/Extra2D/include/extra2d/core/string.h index c9752d9..ddd51f5 100644 --- a/Extra2D/include/extra2d/core/string.h +++ b/Extra2D/include/extra2d/core/string.h @@ -1,228 +1,39 @@ #pragma once -#include #include -#include -#include namespace extra2d { // ============================================================================ -// String 类 - 跨平台字符串,内部统一使用 UTF-8 存储 +// 字符串编码转换工具函数 +// 统一使用 std::string (UTF-8) 作为项目标准字符串类型 // ============================================================================ -class String { -public: - // ------------------------------------------------------------------------ - // 构造函数 - // ------------------------------------------------------------------------ - String() = default; - - String(const char* utf8) : data_(utf8 ? utf8 : "") {} - String(const std::string& utf8) : data_(utf8) {} - explicit String(const wchar_t* wide); - explicit String(const std::wstring& wide); - explicit String(const char16_t* utf16); - explicit String(const std::u16string& utf16); - explicit String(const char32_t* utf32); - explicit String(const std::u32string& utf32); - // ------------------------------------------------------------------------ - // 静态工厂方法 - // ------------------------------------------------------------------------ - static String fromUtf8(const char* utf8); - static String fromUtf8(const std::string& utf8); - static String fromWide(const wchar_t* wide); - static String fromWide(const std::wstring& wide); - static String fromUtf16(const char16_t* utf16); - static String fromUtf16(const std::u16string& utf16); - static String fromUtf32(const char32_t* utf32); - static String fromUtf32(const std::u32string& utf32); - - /// 从 GBK/GB2312 编码构造(Windows 中文系统常用) - static String fromGBK(const char* gbk); - static String fromGBK(const std::string& gbk); +// UTF-8 ↔ UTF-16 转换 +std::u16string utf8ToUtf16(const std::string& utf8); +std::string utf16ToUtf8(const std::u16string& utf16); - // ------------------------------------------------------------------------ - // 编码转换 - // ------------------------------------------------------------------------ - const std::string& toUtf8() const { return data_; } - std::string toUtf8String() const { return data_; } - - std::wstring toWide() const; - std::u16string toUtf16() const; - std::u32string toUtf32() const; - - /// 转换为 GBK/GB2312 编码(Windows 中文系统常用) - std::string toGBK() const; +// UTF-8 ↔ UTF-32 转换 +std::u32string utf8ToUtf32(const std::string& utf8); +std::string utf32ToUtf8(const std::u32string& utf32); - // ------------------------------------------------------------------------ - // 基础操作 - // ------------------------------------------------------------------------ - /// 返回 Unicode 字符数(不是字节数) - size_t length() const; - - /// 返回 UTF-8 字节数 - size_t byteSize() const { return data_.size(); } - - bool empty() const { return data_.empty(); } - - const char* c_str() const { return data_.c_str(); } - const std::string& str() const { return data_; } - std::string& str() { return data_; } +// UTF-8 ↔ Wide String 转换 +std::wstring utf8ToWide(const std::string& utf8); +std::string wideToUtf8(const std::wstring& wide); - // ------------------------------------------------------------------------ - // 字符串操作 - // ------------------------------------------------------------------------ - void clear() { data_.clear(); } - - String& append(const String& other); - String& append(const char* utf8); - - String substring(size_t start, size_t len = npos) const; - - /// 查找子串,返回 Unicode 字符索引,未找到返回 npos - size_t find(const String& substr, size_t start = 0) const; - - /// 是否以指定字符串开头 - bool startsWith(const String& prefix) const; - - /// 是否以指定字符串结尾 - bool endsWith(const String& suffix) const; - - /// 去除首尾空白字符 - String trim() const; - - /// 分割字符串 - std::vector split(const String& delimiter) const; - - /// 替换所有匹配子串 - String replaceAll(const String& from, const String& to) const; - - // ------------------------------------------------------------------------ - // 运算符重载 - // ------------------------------------------------------------------------ - String operator+(const String& other) const; - String& operator+=(const String& other); - - bool operator==(const String& other) const { return data_ == other.data_; } - bool operator!=(const String& other) const { return data_ != other.data_; } - bool operator<(const String& other) const { return data_ < other.data_; } - bool operator>(const String& other) const { return data_ > other.data_; } - - char operator[](size_t index) const { return data_[index]; } - - // ------------------------------------------------------------------------ - // 迭代器支持 - // ------------------------------------------------------------------------ - auto begin() { return data_.begin(); } - auto end() { return data_.end(); } - auto begin() const { return data_.begin(); } - auto end() const { return data_.end(); } - auto cbegin() const { return data_.cbegin(); } - auto cend() const { return data_.cend(); } - - // ------------------------------------------------------------------------ - // 静态常量 - // ------------------------------------------------------------------------ - static constexpr size_t npos = static_cast(-1); - - // ------------------------------------------------------------------------ - // 格式化字符串(类似 sprintf) - // ------------------------------------------------------------------------ - template - static String format(const char* fmt, Args&&... args); - -private: - std::string data_; // 内部使用 UTF-8 存储 - - // UTF-8 辅助函数 - static size_t utf8Length(const std::string& str); - static std::string utf8Substring(const std::string& str, size_t start, size_t len); - static size_t utf8CharIndexToByteIndex(const std::string& str, size_t charIndex); -}; +// UTF-8 ↔ GBK/GB2312 转换(Windows 中文系统常用) +std::string utf8ToGbk(const std::string& utf8); +std::string gbkToUtf8(const std::string& gbk); // ============================================================================ // 内联实现 // ============================================================================ -inline String::String(const wchar_t* wide) { - if (wide) { - std::wstring wstr(wide); - *this = fromWide(wstr); - } -} - -inline String::String(const std::wstring& wide) { - *this = fromWide(wide); -} - -inline String::String(const char16_t* utf16) { - if (utf16) { - std::u16string u16str(utf16); - *this = fromUtf16(u16str); - } -} - -inline String::String(const std::u16string& utf16) { - *this = fromUtf16(utf16); -} - -inline String::String(const char32_t* utf32) { - if (utf32) { - std::u32string u32str(utf32); - *this = fromUtf32(u32str); - } -} - -inline String::String(const std::u32string& utf32) { - *this = fromUtf32(utf32); -} - -// 静态工厂方法 -inline String String::fromUtf8(const char* utf8) { - return String(utf8 ? utf8 : ""); -} - -inline String String::fromUtf8(const std::string& utf8) { - return String(utf8); -} - -// 编码转换实现 -inline std::wstring String::toWide() const { - if (data_.empty()) return std::wstring(); - - if constexpr (sizeof(wchar_t) == 4) { - // wchar_t is 32-bit (Linux/Switch): same as UTF-32 - std::u32string u32 = toUtf32(); - return std::wstring(u32.begin(), u32.end()); - } else { - // wchar_t is 16-bit (Windows): same as UTF-16 - std::u16string u16 = toUtf16(); - return std::wstring(u16.begin(), u16.end()); - } -} - -inline String String::fromWide(const std::wstring& wide) { - if (wide.empty()) return String(); - - if constexpr (sizeof(wchar_t) == 4) { - std::u32string u32(wide.begin(), wide.end()); - return fromUtf32(u32); - } else { - std::u16string u16(wide.begin(), wide.end()); - return fromUtf16(u16); - } -} - -inline String String::fromWide(const wchar_t* wide) { - return wide ? fromWide(std::wstring(wide)) : String(); -} - -inline std::u16string String::toUtf16() const { - if (data_.empty()) return std::u16string(); +inline std::u16string utf8ToUtf16(const std::string& utf8) { + if (utf8.empty()) return std::u16string(); // UTF-8 → UTF-32 → UTF-16 (with surrogate pairs) - std::u32string u32 = toUtf32(); + std::u32string u32 = utf8ToUtf32(utf8); std::u16string result; result.reserve(u32.size()); @@ -240,8 +51,8 @@ inline std::u16string String::toUtf16() const { return result; } -inline String String::fromUtf16(const std::u16string& utf16) { - if (utf16.empty()) return String(); +inline std::string utf16ToUtf8(const std::u16string& utf16) { + if (utf16.empty()) return std::string(); // UTF-16 → UTF-32 → UTF-8 std::u32string u32; @@ -266,24 +77,20 @@ inline String String::fromUtf16(const std::u16string& utf16) { u32.push_back(ch); } - return fromUtf32(u32); + return utf32ToUtf8(u32); } -inline String String::fromUtf16(const char16_t* utf16) { - return utf16 ? fromUtf16(std::u16string(utf16)) : String(); -} - -inline std::u32string String::toUtf32() const { +inline std::u32string utf8ToUtf32(const std::string& utf8) { std::u32string result; - result.reserve(length()); - - const char* ptr = data_.c_str(); - const char* end = ptr + data_.size(); - + result.reserve(utf8.size()); + + const char* ptr = utf8.c_str(); + const char* end = ptr + utf8.size(); + while (ptr < end) { char32_t ch = 0; unsigned char byte = static_cast(*ptr); - + if ((byte & 0x80) == 0) { // 1-byte sequence ch = byte; @@ -311,16 +118,16 @@ inline std::u32string String::toUtf32() const { ptr += 1; continue; } - + result.push_back(ch); } - + return result; } -inline String String::fromUtf32(const std::u32string& utf32) { +inline std::string utf32ToUtf8(const std::u32string& utf32) { std::string result; - + for (char32_t ch : utf32) { if (ch <= 0x7F) { // 1-byte @@ -342,166 +149,61 @@ inline String String::fromUtf32(const std::u32string& utf32) { result.push_back(static_cast(0x80 | (ch & 0x3F))); } } - - return String(result); -} -inline String String::fromUtf32(const char32_t* utf32) { - return utf32 ? fromUtf32(std::u32string(utf32)) : String(); -} - -// UTF-8 辅助函数 -inline size_t String::utf8Length(const std::string& str) { - size_t len = 0; - for (unsigned char c : str) { - if ((c & 0xC0) != 0x80) { - ++len; - } - } - return len; -} - -inline size_t String::length() const { - return utf8Length(data_); -} - -inline size_t String::utf8CharIndexToByteIndex(const std::string& str, size_t charIndex) { - size_t charCount = 0; - size_t byteIndex = 0; - - while (byteIndex < str.size() && charCount < charIndex) { - unsigned char c = static_cast(str[byteIndex]); - if ((c & 0xC0) != 0x80) { - ++charCount; - } - ++byteIndex; - } - - return byteIndex; -} - -inline std::string String::utf8Substring(const std::string& str, size_t start, size_t len) { - size_t startByte = utf8CharIndexToByteIndex(str, start); - size_t endByte = (len == npos) ? str.size() : utf8CharIndexToByteIndex(str, start + len); - - return str.substr(startByte, endByte - startByte); -} - -inline String String::substring(size_t start, size_t len) const { - return String(utf8Substring(data_, start, len)); -} - -// 字符串操作 -inline String& String::append(const String& other) { - data_.append(other.data_); - return *this; -} - -inline String& String::append(const char* utf8) { - if (utf8) data_.append(utf8); - return *this; -} - -inline size_t String::find(const String& substr, size_t start) const { - if (substr.empty() || start >= length()) return npos; - - size_t startByte = utf8CharIndexToByteIndex(data_, start); - size_t pos = data_.find(substr.data_, startByte); - - if (pos == std::string::npos) return npos; - - // 转换字节索引到字符索引 - return utf8Length(data_.substr(0, pos)); -} - -inline bool String::startsWith(const String& prefix) const { - if (prefix.data_.size() > data_.size()) return false; - return data_.compare(0, prefix.data_.size(), prefix.data_) == 0; -} - -inline bool String::endsWith(const String& suffix) const { - if (suffix.data_.size() > data_.size()) return false; - return data_.compare(data_.size() - suffix.data_.size(), suffix.data_.size(), suffix.data_) == 0; -} - -inline String String::trim() const { - size_t start = 0; - while (start < data_.size() && std::isspace(static_cast(data_[start]))) { - ++start; - } - - size_t end = data_.size(); - while (end > start && std::isspace(static_cast(data_[end - 1]))) { - --end; - } - - return String(data_.substr(start, end - start)); -} - -inline std::vector String::split(const String& delimiter) const { - std::vector result; - - if (delimiter.empty()) { - result.push_back(*this); - return result; - } - - size_t start = 0; - size_t end = data_.find(delimiter.data_, start); - - while (end != std::string::npos) { - result.push_back(String(data_.substr(start, end - start))); - start = end + delimiter.data_.size(); - end = data_.find(delimiter.data_, start); - } - - result.push_back(String(data_.substr(start))); - return result; } -inline String String::replaceAll(const String& from, const String& to) const { - if (from.empty()) return *this; - - std::string result = data_; - size_t pos = 0; - - while ((pos = result.find(from.data_, pos)) != std::string::npos) { - result.replace(pos, from.data_.size(), to.data_); - pos += to.data_.size(); +inline std::wstring utf8ToWide(const std::string& utf8) { + if (utf8.empty()) return std::wstring(); + + if constexpr (sizeof(wchar_t) == 4) { + // wchar_t is 32-bit (Linux/Switch): same as UTF-32 + std::u32string u32 = utf8ToUtf32(utf8); + return std::wstring(u32.begin(), u32.end()); + } else { + // wchar_t is 16-bit (Windows): same as UTF-16 + std::u16string u16 = utf8ToUtf16(utf8); + return std::wstring(u16.begin(), u16.end()); } - - return String(result); } -// 运算符重载 -inline String String::operator+(const String& other) const { - String result(*this); - result.append(other); - return result; +inline std::string wideToUtf8(const std::wstring& wide) { + if (wide.empty()) return std::string(); + + if constexpr (sizeof(wchar_t) == 4) { + std::u32string u32(wide.begin(), wide.end()); + return utf32ToUtf8(u32); + } else { + std::u16string u16(wide.begin(), wide.end()); + return utf16ToUtf8(u16); + } } -inline String& String::operator+=(const String& other) { - return append(other); +// GBK/GB2312 转换(Windows 平台实现) +// 注意:Windows 实现在 .cpp 文件中,避免头文件包含 windows.h 导致冲突 +#ifdef _WIN32 +// 前向声明,实现在 .cpp 文件中 +std::string utf8ToGbkImpl(const std::string& utf8); +std::string gbkToUtf8Impl(const std::string& gbk); + +inline std::string utf8ToGbk(const std::string& utf8) { + return utf8ToGbkImpl(utf8); } -// 格式化字符串 -#include - -template -String String::format(const char* fmt, Args&&... args) { - int size = std::snprintf(nullptr, 0, fmt, std::forward(args)...); - if (size <= 0) return String(); - - std::string result(size, '\0'); - std::snprintf(&result[0], size + 1, fmt, std::forward(args)...); - - return String(result); +inline std::string gbkToUtf8(const std::string& gbk) { + return gbkToUtf8Impl(gbk); +} +#else +// 非 Windows 平台,GBK 转换使用 iconv 或返回原字符串 +inline std::string utf8ToGbk(const std::string& utf8) { + // TODO: 使用 iconv 实现 + return utf8; } -// 全局运算符 -inline String operator+(const char* lhs, const String& rhs) { - return String(lhs) + rhs; +inline std::string gbkToUtf8(const std::string& gbk) { + // TODO: 使用 iconv 实现 + return gbk; } +#endif } // namespace extra2d diff --git a/Extra2D/include/extra2d/core/types.h b/Extra2D/include/extra2d/core/types.h index 1b51f75..860bbc0 100644 --- a/Extra2D/include/extra2d/core/types.h +++ b/Extra2D/include/extra2d/core/types.h @@ -3,9 +3,15 @@ #include #include #include +#include namespace extra2d { +// --------------------------------------------------------------------------- +// 字符串别名 - 统一使用 std::string (UTF-8) +// --------------------------------------------------------------------------- +using String = std::string; + // --------------------------------------------------------------------------- // 智能指针别名 // --------------------------------------------------------------------------- diff --git a/Extra2D/include/extra2d/extra2d.h b/Extra2D/include/extra2d/extra2d.h index 6cde05b..6ec0de3 100644 --- a/Extra2D/include/extra2d/extra2d.h +++ b/Extra2D/include/extra2d/extra2d.h @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include @@ -53,6 +52,12 @@ // UI #include #include +#include +#include +#include +#include +#include +#include // Action #include @@ -92,10 +97,6 @@ // Application #include -// Script -#include -#include - #ifdef __SWITCH__ #include #endif \ No newline at end of file diff --git a/Extra2D/include/extra2d/graphics/font.h b/Extra2D/include/extra2d/graphics/font.h index 3c807f7..8fbf7e9 100644 --- a/Extra2D/include/extra2d/graphics/font.h +++ b/Extra2D/include/extra2d/graphics/font.h @@ -2,7 +2,6 @@ #include #include -#include #include namespace extra2d { diff --git a/Extra2D/include/extra2d/graphics/render_backend.h b/Extra2D/include/extra2d/graphics/render_backend.h index 7c9f7eb..4e7bc7a 100644 --- a/Extra2D/include/extra2d/graphics/render_backend.h +++ b/Extra2D/include/extra2d/graphics/render_backend.h @@ -2,7 +2,6 @@ #include #include -#include #include #include diff --git a/Extra2D/include/extra2d/script/script_engine.h b/Extra2D/include/extra2d/script/script_engine.h deleted file mode 100644 index a5ce1ae..0000000 --- a/Extra2D/include/extra2d/script/script_engine.h +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once - -#include -#include -#include - -namespace extra2d { - -class ScriptEngine { -public: - static ScriptEngine &getInstance(); - - ScriptEngine(const ScriptEngine &) = delete; - ScriptEngine &operator=(const ScriptEngine &) = delete; - - bool initialize(); - void shutdown(); - - bool executeString(const std::string &code); - bool executeFile(const std::string &filepath); - - HSQUIRRELVM getVM() const { return vm_; } - bool isInitialized() const { return vm_ != nullptr; } - -private: - ScriptEngine() = default; - ~ScriptEngine(); - - bool compileAndRun(const std::string &source, const std::string &sourceName); - - static void printFunc(HSQUIRRELVM vm, const SQChar *fmt, ...); - static void errorFunc(HSQUIRRELVM vm, const SQChar *fmt, ...); - static SQInteger errorHandler(HSQUIRRELVM vm); - static void compilerError(HSQUIRRELVM vm, const SQChar *desc, - const SQChar *source, SQInteger line, - SQInteger column); - - HSQUIRRELVM vm_ = nullptr; -}; - -} // namespace extra2d diff --git a/Extra2D/include/extra2d/script/script_node.h b/Extra2D/include/extra2d/script/script_node.h deleted file mode 100644 index 87d7551..0000000 --- a/Extra2D/include/extra2d/script/script_node.h +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once - -#include -#include -#include - -namespace extra2d { - -class ScriptNode : public Node { -public: - ScriptNode(); - ~ScriptNode() override; - - static Ptr create(const std::string &scriptPath); - - bool loadScript(const std::string &scriptPath); - const std::string &getScriptPath() const { return scriptPath_; } - - void onEnter() override; - void onExit() override; - void onUpdate(float dt) override; - -private: - bool callMethod(const char *name); - bool callMethodWithFloat(const char *name, float arg); - void pushSelf(); - - std::string scriptPath_; - HSQOBJECT scriptTable_; - bool tableValid_ = false; -}; - -} // namespace extra2d diff --git a/Extra2D/include/extra2d/script/sq_binding.h b/Extra2D/include/extra2d/script/sq_binding.h deleted file mode 100644 index d541ed4..0000000 --- a/Extra2D/include/extra2d/script/sq_binding.h +++ /dev/null @@ -1,263 +0,0 @@ -#pragma once - -#include -#include -#include - -namespace extra2d { -namespace sq { - -// ============================================================================ -// Type tag helpers — unique address per type -// ============================================================================ -template inline SQUserPointer typeTag() { - static int tag; - return &tag; -} - -// ============================================================================ -// SqClassName trait — maps C++ types to Squirrel class names -// ============================================================================ -template struct SqClassName { - static const char *name(); -}; - -// ============================================================================ -// push / get primitives -// ============================================================================ -inline void push(HSQUIRRELVM vm, int v) { - sq_pushinteger(vm, static_cast(v)); -} -inline void push(HSQUIRRELVM vm, float v) { - sq_pushfloat(vm, static_cast(v)); -} -inline void push(HSQUIRRELVM vm, double v) { - sq_pushfloat(vm, static_cast(v)); -} -inline void push(HSQUIRRELVM vm, bool v) { - sq_pushbool(vm, v ? SQTrue : SQFalse); -} -inline void push(HSQUIRRELVM vm, const char *v) { sq_pushstring(vm, v, -1); } -inline void push(HSQUIRRELVM vm, const std::string &v) { - sq_pushstring(vm, v.c_str(), static_cast(v.size())); -} -inline void pushNull(HSQUIRRELVM vm) { sq_pushnull(vm); } - -inline SQInteger getInt(HSQUIRRELVM vm, SQInteger idx) { - SQInteger val = 0; - sq_getinteger(vm, idx, &val); - return val; -} - -inline SQFloat getFloat(HSQUIRRELVM vm, SQInteger idx) { - SQFloat val = 0; - if (SQ_FAILED(sq_getfloat(vm, idx, &val))) { - SQInteger ival = 0; - if (SQ_SUCCEEDED(sq_getinteger(vm, idx, &ival))) - val = static_cast(ival); - } - return val; -} - -inline bool getBool(HSQUIRRELVM vm, SQInteger idx) { - SQBool val = SQFalse; - sq_getbool(vm, idx, &val); - return val != SQFalse; -} - -inline std::string getString(HSQUIRRELVM vm, SQInteger idx) { - const SQChar *str = nullptr; - sq_getstring(vm, idx, &str); - return str ? std::string(str) : std::string(); -} - -// ============================================================================ -// Value type userdata helpers -// ============================================================================ -template T *pushValueInstance(HSQUIRRELVM vm, const T &val) { - sq_pushroottable(vm); - sq_pushstring(vm, SqClassName::name(), -1); - if (SQ_FAILED(sq_get(vm, -2))) { - sq_pop(vm, 1); - return nullptr; - } - if (SQ_FAILED(sq_createinstance(vm, -1))) { - sq_pop(vm, 2); - return nullptr; - } - - T *ud = nullptr; - sq_getinstanceup(vm, -1, reinterpret_cast(&ud), nullptr, - SQFalse); - if (ud) - *ud = val; - - sq_remove(vm, -2); // class - sq_remove(vm, -2); // roottable - return ud; -} - -template T *getValueInstance(HSQUIRRELVM vm, SQInteger idx) { - T *ud = nullptr; - sq_getinstanceup(vm, idx, reinterpret_cast(&ud), - typeTag(), SQFalse); - return ud; -} - -// ============================================================================ -// Shared pointer bridge for reference types -// ============================================================================ -template void pushPtr(HSQUIRRELVM vm, Ptr ptr) { - if (!ptr) { - sq_pushnull(vm); - return; - } - - sq_pushroottable(vm); - sq_pushstring(vm, SqClassName::name(), -1); - if (SQ_FAILED(sq_get(vm, -2))) { - sq_pop(vm, 1); - sq_pushnull(vm); - return; - } - if (SQ_FAILED(sq_createinstance(vm, -1))) { - sq_pop(vm, 2); - sq_pushnull(vm); - return; - } - - auto *storage = new Ptr(std::move(ptr)); - sq_setinstanceup(vm, -1, storage); - sq_setreleasehook(vm, -1, [](SQUserPointer p, SQInteger) -> SQInteger { - delete static_cast *>(p); - return 0; - }); - - sq_remove(vm, -2); // class - sq_remove(vm, -2); // roottable -} - -template Ptr getPtr(HSQUIRRELVM vm, SQInteger idx) { - SQUserPointer up = nullptr; - sq_getinstanceup(vm, idx, &up, typeTag(), SQFalse); - if (!up) - return nullptr; - return *static_cast *>(up); -} - -template T *getRawPtr(HSQUIRRELVM vm, SQInteger idx) { - auto p = getPtr(vm, idx); - return p ? p.get() : nullptr; -} - -// ============================================================================ -// Singleton pointer (no release hook) -// ============================================================================ -template -void pushSingleton(HSQUIRRELVM vm, T *ptr, const char *className) { - sq_pushroottable(vm); - sq_pushstring(vm, className, -1); - if (SQ_FAILED(sq_get(vm, -2))) { - sq_pop(vm, 1); - sq_pushnull(vm); - return; - } - if (SQ_FAILED(sq_createinstance(vm, -1))) { - sq_pop(vm, 2); - sq_pushnull(vm); - return; - } - sq_setinstanceup(vm, -1, ptr); - sq_remove(vm, -2); // class - sq_remove(vm, -2); // roottable -} - -template T *getSingleton(HSQUIRRELVM vm, SQInteger idx) { - SQUserPointer up = nullptr; - sq_getinstanceup(vm, idx, &up, nullptr, SQFalse); - return static_cast(up); -} - -// ============================================================================ -// ClassDef — fluent API for registering a class -// ============================================================================ -struct ClassDef { - HSQUIRRELVM vm; - - ClassDef(HSQUIRRELVM v, const char *name, const char *base = nullptr) - : vm(v) { - sq_pushroottable(vm); - sq_pushstring(vm, name, -1); - - if (base) { - sq_pushstring(vm, base, -1); - if (SQ_FAILED(sq_get(vm, -3))) { - sq_newclass(vm, SQFalse); - } else { - sq_newclass(vm, SQTrue); - } - } else { - sq_newclass(vm, SQFalse); - } - } - - ClassDef &setTypeTag(SQUserPointer tag) { - sq_settypetag(vm, -1, tag); - return *this; - } - - ClassDef &method(const char *name, SQFUNCTION fn, SQInteger nparams = 0, - const char *typemask = nullptr) { - sq_pushstring(vm, name, -1); - sq_newclosure(vm, fn, 0); - if (nparams > 0 && typemask) - sq_setparamscheck(vm, nparams, typemask); - sq_newslot(vm, -3, SQFalse); - return *this; - } - - ClassDef &staticMethod(const char *name, SQFUNCTION fn, SQInteger nparams = 0, - const char *typemask = nullptr) { - sq_pushstring(vm, name, -1); - sq_newclosure(vm, fn, 0); - if (nparams > 0 && typemask) - sq_setparamscheck(vm, nparams, typemask); - sq_newslot(vm, -3, SQTrue); - return *this; - } - - template ClassDef &setValueType(SQFUNCTION constructor) { - sq_settypetag(vm, -1, typeTag()); - sq_setclassudsize(vm, -1, sizeof(T)); - sq_pushstring(vm, "constructor", -1); - sq_newclosure(vm, constructor, 0); - sq_newslot(vm, -3, SQFalse); - return *this; - } - - void commit() { - sq_newslot(vm, -3, SQFalse); - sq_pop(vm, 1); - } -}; - -// ============================================================================ -// Register a table of integer constants -// ============================================================================ -inline void registerConstTable(HSQUIRRELVM vm, const char *tableName, - const char *const *names, - const SQInteger *values, int count) { - sq_pushroottable(vm); - sq_pushstring(vm, tableName, -1); - sq_newtable(vm); - for (int i = 0; i < count; ++i) { - sq_pushstring(vm, names[i], -1); - sq_pushinteger(vm, values[i]); - sq_newslot(vm, -3, SQFalse); - } - sq_newslot(vm, -3, SQFalse); - sq_pop(vm, 1); -} - -} // namespace sq -} // namespace extra2d diff --git a/Extra2D/include/extra2d/script/sq_binding_action.h b/Extra2D/include/extra2d/script/sq_binding_action.h deleted file mode 100644 index ae3cee1..0000000 --- a/Extra2D/include/extra2d/script/sq_binding_action.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include - -namespace extra2d { -namespace sq { - -void registerActionBindings(HSQUIRRELVM vm); - -} // namespace sq -} // namespace extra2d diff --git a/Extra2D/include/extra2d/script/sq_binding_animation.h b/Extra2D/include/extra2d/script/sq_binding_animation.h deleted file mode 100644 index dc4f9ee..0000000 --- a/Extra2D/include/extra2d/script/sq_binding_animation.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include - -namespace extra2d { -namespace sq { - -void registerAnimationBindings(HSQUIRRELVM vm); - -} // namespace sq -} // namespace extra2d diff --git a/Extra2D/include/extra2d/script/sq_binding_audio.h b/Extra2D/include/extra2d/script/sq_binding_audio.h deleted file mode 100644 index aa106e0..0000000 --- a/Extra2D/include/extra2d/script/sq_binding_audio.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include - -namespace extra2d { -namespace sq { - -void registerAudioBindings(HSQUIRRELVM vm); - -} // namespace sq -} // namespace extra2d diff --git a/Extra2D/include/extra2d/script/sq_binding_input.h b/Extra2D/include/extra2d/script/sq_binding_input.h deleted file mode 100644 index 371748e..0000000 --- a/Extra2D/include/extra2d/script/sq_binding_input.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#include - -namespace extra2d { -namespace sq { - -void registerInput(HSQUIRRELVM vm); -void registerKeyConstants(HSQUIRRELVM vm); -void registerInputBindings(HSQUIRRELVM vm); - -} // namespace sq -} // namespace extra2d diff --git a/Extra2D/include/extra2d/script/sq_binding_node.h b/Extra2D/include/extra2d/script/sq_binding_node.h deleted file mode 100644 index 69505e3..0000000 --- a/Extra2D/include/extra2d/script/sq_binding_node.h +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include - -namespace extra2d { -namespace sq { - -void registerNode(HSQUIRRELVM vm); -void registerSprite(HSQUIRRELVM vm); -void registerScene(HSQUIRRELVM vm); -void registerSceneManager(HSQUIRRELVM vm); -void registerApplication(HSQUIRRELVM vm); -void registerNodeBindings(HSQUIRRELVM vm); - -} // namespace sq -} // namespace extra2d diff --git a/Extra2D/include/extra2d/script/sq_binding_types.h b/Extra2D/include/extra2d/script/sq_binding_types.h deleted file mode 100644 index 63a24ee..0000000 --- a/Extra2D/include/extra2d/script/sq_binding_types.h +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once - -#include -#include -#include - -namespace extra2d { -namespace sq { - -// SqClassName specializations for value types -template <> struct SqClassName { - static const char *name() { return "Vec2"; } -}; -template <> struct SqClassName { - static const char *name() { return "Size"; } -}; -template <> struct SqClassName { - static const char *name() { return "Rect"; } -}; -template <> struct SqClassName { - static const char *name() { return "Color"; } -}; - -void registerVec2(HSQUIRRELVM vm); -void registerSize(HSQUIRRELVM vm); -void registerRect(HSQUIRRELVM vm); -void registerColor(HSQUIRRELVM vm); -void registerValueTypes(HSQUIRRELVM vm); - -} // namespace sq -} // namespace extra2d diff --git a/Extra2D/include/extra2d/ui/button.h b/Extra2D/include/extra2d/ui/button.h index 7d1d822..980bed0 100644 --- a/Extra2D/include/extra2d/ui/button.h +++ b/Extra2D/include/extra2d/ui/button.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include diff --git a/Extra2D/include/extra2d/ui/check_box.h b/Extra2D/include/extra2d/ui/check_box.h new file mode 100644 index 0000000..ba4b1df --- /dev/null +++ b/Extra2D/include/extra2d/ui/check_box.h @@ -0,0 +1,74 @@ +#pragma once + +#include +#include +#include + +namespace extra2d { + +// ============================================================================ +// 复选框组件 +// ============================================================================ +class CheckBox : public Widget { +public: + CheckBox(); + ~CheckBox() override = default; + + static Ptr create(); + static Ptr create(const String &label); + + void setChecked(bool checked); + bool isChecked() const { return checked_; } + void toggle(); + + void setLabel(const String &label); + const String &getLabel() const { return label_; } + + void setFont(Ptr font); + Ptr getFont() const { return font_; } + + void setTextColor(const Color &color); + Color getTextColor() const { return textColor_; } + + void setBoxSize(float size); + float getBoxSize() const { return boxSize_; } + + void setSpacing(float spacing); + float getSpacing() const { return spacing_; } + + void setCheckedColor(const Color &color); + Color getCheckedColor() const { return checkedColor_; } + + void setUncheckedColor(const Color &color); + Color getUncheckedColor() const { return uncheckedColor_; } + + void setCheckMarkColor(const Color &color); + Color getCheckMarkColor() const { return checkMarkColor_; } + + void setOnStateChange(Function callback); + + Rect getBoundingBox() const override; + +protected: + void onDraw(RenderBackend &renderer) override; + bool onMousePress(const MouseEvent &event) override; + bool onMouseRelease(const MouseEvent &event) override; + +private: + bool checked_ = false; + String label_; + Ptr font_; + Color textColor_ = Colors::White; + + float boxSize_ = 20.0f; + float spacing_ = 8.0f; + + Color checkedColor_ = Color(0.2f, 0.6f, 1.0f, 1.0f); + Color uncheckedColor_ = Color(0.3f, 0.3f, 0.3f, 1.0f); + Color checkMarkColor_ = Colors::White; + + bool pressed_ = false; + Function onStateChange_; +}; + +} // namespace extra2d diff --git a/Extra2D/include/extra2d/ui/label.h b/Extra2D/include/extra2d/ui/label.h new file mode 100644 index 0000000..8be0ee9 --- /dev/null +++ b/Extra2D/include/extra2d/ui/label.h @@ -0,0 +1,149 @@ +#pragma once + +#include +#include +#include + +namespace extra2d { + +// ============================================================================ +// 文本标签组件 - 用于显示静态文本 +// 支持多行、对齐、阴影、描边等游戏常用效果 +// ============================================================================ +class Label : public Widget { +public: + Label(); + explicit Label(const String &text); + ~Label() override = default; + + // ------------------------------------------------------------------------ + // 静态创建方法 + // ------------------------------------------------------------------------ + static Ptr