From b86053c3a75158ef6e7a9d2bb0ff55bfee114ba1 Mon Sep 17 00:00:00 2001 From: EmsiaetKadosh Date: Sat, 18 Jan 2025 10:36:08 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=87=E5=AD=97=E7=B3=BB=E7=BB=9F=E5=A4=A7?= =?UTF-8?q?=E4=BD=93=E5=AE=8C=E5=B7=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 3 +- Hud.h | 2 +- Renderer.h | 9 +++- Text.cpp | 17 ++++++++ Text.h | 113 +++++++++++++++++++++++++++++++++++++++++++++++++ Window.h | 62 ++++++++++++++++++++------- dev.md | 2 + 7 files changed, 188 insertions(+), 20 deletions(-) create mode 100644 Text.cpp create mode 100644 dev.md diff --git a/CMakeLists.txt b/CMakeLists.txt index 055a360..b9dd69f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,7 +29,8 @@ add_executable(${PROJECT_NAME} main.cpp Hud.h includes.h Text.h - Chars.h) + Chars.h + Text.cpp) set(CPACK_PROJECT_NAME ${PROJECT_NAME}) set(CPACK_PROJECT_VERSION ${PROJECT_VERSION}) include(CPack) diff --git a/Hud.h b/Hud.h index f309118..c017942 100644 --- a/Hud.h +++ b/Hud.h @@ -5,7 +5,7 @@ #pragma once #include "Renderer.h" -class Hud : public Renderable { +class Hud : public IRenderable { public: void render() const noexcept override; }; diff --git a/Renderer.h b/Renderer.h index fc52c29..d1c7366 100644 --- a/Renderer.h +++ b/Renderer.h @@ -6,8 +6,13 @@ #include "def.h" -interface Renderable { - virtual ~Renderable() = default; +/** + * 用于标记相对位置。 + */ +enum class Location { LEFT_TOP, LEFT, LEFT_BOTTOM, TOP, CENTER, BOTTOM, RIGHT_TOP, RIGHT, RIGHT_BOTTOM }; + +interface IRenderable { + virtual ~IRenderable() = default; virtual void render() const noexcept = 0; }; diff --git a/Text.cpp b/Text.cpp new file mode 100644 index 0000000..4f8c016 --- /dev/null +++ b/Text.cpp @@ -0,0 +1,17 @@ +// +// Created by EmsiaetKadosh on 25-1-18. +// + +#include "Text.h" + +#include "def.h" + +const String& TranslatableText::getText() const noexcept { + if (target == nullptr || langConfig == translator.getConfigVersion()) { + target = translator.getText(idSrc); + langConfig = translator.getConfigVersion(); + } + return *target; +} + + diff --git a/Text.h b/Text.h index af01739..a8a05d3 100644 --- a/Text.h +++ b/Text.h @@ -8,6 +8,11 @@ class IdentifiedText {}; +/** + * 注意一些默认值。 + * FontID=0,表示继承使用默认字体; + * color和background=0xffffffff,表示继承使用默认颜色; + */ class RenderableString { struct StringConfig { String text; @@ -51,6 +56,20 @@ class RenderableString { return ret; } + [[nodiscard]] StringConfig copy() const noexcept { + StringConfig ret; + ret.idFont = idFont; + ret.text = text; + ret.idFont = idFont; + ret.color = color; + ret.background = background; + ret.bold = bold; + ret.italic = italic; + ret.underline = underline; + ret.strikeThrough = strikeThrough; + return ret; + } + [[nodiscard]] String toString() const noexcept { String ret; ret.append(L"#"); @@ -71,6 +90,8 @@ class RenderableString { }; List configs; + using Iterator = List::iterator; + using ConstIterator = List::const_iterator; public: explicit RenderableString(const String& string): RenderableString(string.c_str(), string.length()) {} @@ -262,4 +283,96 @@ private: } configs.push_back(std::move(config)); } + + RenderableString& append(const RenderableString& other) { + auto iterator = other.configs.cbegin(); + int flags = 0; + bool clr = true, bg = true, font = true; + unsigned int color = configs.back().color; + unsigned int background = configs.back().background; + wchar idFont = configs.back().idFont; + while (iterator != other.configs.cend()) { + if (flags >= 3) break; + StringConfig config = iterator->copy(); + if (font) { + if (config.idFont == idFont || config.idFont != 0) { + font = false; + ++flags; + } else config.idFont = idFont; + } + if (clr) { + if (config.color == color || config.color != 0xffffffff) { + clr = false; + ++flags; + } else config.color = color; + } + if (bg) { + if (config.background == background || config.background != 0xffffffff) { + bg = false; + ++flags; + } else config.background = background; + } + configs.push_back(std::move(config)); + ++iterator; + } + while (iterator != other.configs.cend()) configs.push_back(iterator->copy()); + return *this; + } + + RenderableString& append(const String& other) { + parseAppend(other.c_str(), other.length()); + return *this; + } }; + +interface Text { + virtual ~Text() = default; + virtual const String& getText() const noexcept = 0; +}; + +class Translator; + +class TranslatableText final : public Text { + const String idSrc; + mutable const String* target = nullptr; + mutable QWORD langConfig = 0; + +public: + explicit TranslatableText(const String& id) : idSrc(id) {} + explicit TranslatableText(String&& id) : idSrc(std::move(id)) {} + const String& getText() const noexcept override; +}; + +struct Language { + Map translateTable; + int id = 1; +}; + +class Translator { + Map langMap{}; + List langList{}; + String lang = L"zh-cn"; + String nullText = L""; + QWORD langConfig = 1; + int idLangMax = 1; + using IterID = Map::const_iterator; + using IterLang = List::const_iterator; + +public: + explicit Translator() { langMap.insert(std::make_pair(String(L"zh-cn"), 1)); } + void addLang(const String& lang) noexcept(this->langMap.insert(std::make_pair(lang, this->idLangMax))) { langMap.insert(std::make_pair(lang, ++idLangMax)); } + void addLang(String&& lang) noexcept(this->langMap.insert(std::make_pair(lang, this->idLangMax))) { langMap.insert(std::make_pair(lang, ++idLangMax)); } + void loadLang(); + + const String* getText(const String& id) const noexcept { + for (const auto& [translateTable, _] : langList) { + IterID iterator = translateTable.find(id); + if (iterator != translateTable.cend()) return &iterator->second; + } + return &nullText; + } + + int getConfigVersion() const noexcept { return langConfig; } +}; + +inline static Translator translator = Translator(); diff --git a/Window.h b/Window.h index 9b9c68d..cfd1c84 100644 --- a/Window.h +++ b/Window.h @@ -7,19 +7,24 @@ #include "def.h" #include "Renderer.h" -class Widget : public Renderable { +enum class MouseActionCode : char { + MAC_MOVE, MAC_HOVER, MAC_DOWN, MAC_UP, MAC_DOUBLE +}; + +class Widget : public IRenderable { protected: int left = 0, top = 0, width = 0, height = 0; mutable bool hasMouse = false; public: - using Action = Function; + using Action = Function; double x, y, w, h; - Action hover; - Action longHover; - Action mouseDown; - Action mouseUp; - Action mouseLeave; + Action hover;// 传入int忽略 + Action longHover;// 传入int表示时间 + Action mouseDown;// 传入int表示变更按键。0左, 1中, 2右 + Action mouseUp;// 传入int表示变更按键。0左, 1中, 2右 + Action mouseLeave;// 传入int忽略 + Action mouseClick;// 传入int表示变更按键。0x0左, 0x1中, 0x2右;0xf表示是否双击 explicit Widget(const double x, const double y, const double w, const double h) : x(x), y(y), w(w), h(h) {} void render() const noexcept override {} virtual void onResize() {} @@ -27,19 +32,44 @@ public: virtual bool isMouseIn(int x, int y) noexcept { x -= left; y -= top; - if (0 <= x and x <= width and 0 <= y and y <= height) hasMouse = true; - hasMouse = false; - return hasMouse; + return 0 <= x and x <= width and 0 <= y and y <= height; } - virtual void onHover() noexcept { if (hover) hover(); } - virtual void onLongHover() noexcept { if (longHover) longHover(); } - virtual void onMouseDown() noexcept { if (mouseDown) mouseDown(); } - virtual void onMouseUp() noexcept { if (mouseUp) mouseUp(); } - virtual void onMouseLeave() noexcept { if (mouseLeave) mouseLeave(); } + virtual void onHover(const int value) noexcept { if (hover) hover(value); } + virtual void onLongHover(const int value) noexcept { if (longHover) longHover(value); } + virtual void onMouseDown(const int value) noexcept { if (mouseDown) mouseDown(value); } + virtual void onMouseUp(const int value) noexcept { if (mouseUp) mouseUp(value); } + virtual void onMouseLeave(const int value) noexcept { if (mouseLeave) mouseLeave(value); } + virtual void onMouseClick(const int value) noexcept { if (mouseClick) mouseClick(value); } + + virtual void passEvent(int action, int value, int x, int y) noexcept { + if (!isMouseIn(x, y)) { + if (hasMouse) onMouseLeave(0); + hasMouse = false; + } + hasMouse = true; + switch (action & 0xf) { + case MouseActionCode::MAC_HOVER: + onLongHover(0); + break; + case MouseActionCode::MAC_MOVE: + onHover(0); + break; + case MouseActionCode::MAC_DOWN: + onMouseDown(value); + break; + case MouseActionCode::MAC_UP: + onMouseUp(value); + break; + case MouseActionCode::MAC_DOUBLE: + onMouseClick(1); + break; + default: + } + } }; -class Window : public Renderable { +class Window : public IRenderable { protected: List widgets; diff --git a/dev.md b/dev.md new file mode 100644 index 0000000..a659cbb --- /dev/null +++ b/dev.md @@ -0,0 +1,2 @@ +# dev +**class TranslatableText**及**class Translator**对应需要的文件处理系统;**class Texture**等对应需要的资源文件处理系统。