文字系统大体完工
This commit is contained in:
+2
-1
@@ -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)
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#pragma once
|
||||
#include "Renderer.h"
|
||||
|
||||
class Hud : public Renderable {
|
||||
class Hud : public IRenderable {
|
||||
public:
|
||||
void render() const noexcept override;
|
||||
};
|
||||
|
||||
+7
-2
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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<StringConfig> configs;
|
||||
using Iterator = List<StringConfig>::iterator;
|
||||
using ConstIterator = List<StringConfig>::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<String, String> translateTable;
|
||||
int id = 1;
|
||||
};
|
||||
|
||||
class Translator {
|
||||
Map<String, int> langMap{};
|
||||
List<Language> langList{};
|
||||
String lang = L"zh-cn";
|
||||
String nullText = L"<translator-null>";
|
||||
QWORD langConfig = 1;
|
||||
int idLangMax = 1;
|
||||
using IterID = Map<String, String>::const_iterator;
|
||||
using IterLang = List<Language>::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();
|
||||
|
||||
@@ -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<void()>;
|
||||
using Action = Function<void(int)>;
|
||||
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<Widget*> widgets;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user