Changes
This commit is contained in:
+8
-2
@@ -28,9 +28,15 @@ add_executable(${PROJECT_NAME} main.cpp
|
||||
Hud.cpp
|
||||
Hud.h
|
||||
includes.h
|
||||
Text.h
|
||||
IText.h
|
||||
Chars.h
|
||||
Text.cpp)
|
||||
IText.cpp
|
||||
xWindows.h
|
||||
exception.h
|
||||
def.cpp
|
||||
TestCode.h
|
||||
TextureManager.cpp
|
||||
TextureManager.h)
|
||||
set(CPACK_PROJECT_NAME ${PROJECT_NAME})
|
||||
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
|
||||
include(CPack)
|
||||
|
||||
@@ -3,3 +3,6 @@
|
||||
//
|
||||
|
||||
#include "Game.h"
|
||||
|
||||
void Game::initialize() noexcept { renderer.setGame(game); }
|
||||
|
||||
|
||||
@@ -7,13 +7,14 @@
|
||||
#include "Hud.h"
|
||||
#include "Window.h"
|
||||
|
||||
class Game {
|
||||
class Game : public IRenderable {
|
||||
Hud hud = Hud();
|
||||
Window* window = nullptr;
|
||||
|
||||
public:
|
||||
explicit Game() = default;
|
||||
void render() const noexcept {
|
||||
static void initialize() noexcept;
|
||||
void render() const noexcept override {
|
||||
if (window) window->render();
|
||||
hud.render();
|
||||
}
|
||||
|
||||
+11
-2
@@ -2,16 +2,25 @@
|
||||
// Created by EmsiaetKadosh on 25-1-18.
|
||||
//
|
||||
|
||||
#include "Text.h"
|
||||
#include "IText.h"
|
||||
|
||||
#include "def.h"
|
||||
|
||||
const String& TranslatableText::getText() const noexcept {
|
||||
refreshText();
|
||||
return target->getText();
|
||||
}
|
||||
|
||||
const RenderableString& TranslatableText::getRenderableString() const noexcept {
|
||||
refreshText();
|
||||
return target->getRenderableString();
|
||||
}
|
||||
|
||||
void TranslatableText::refreshText() const noexcept {
|
||||
if (target == nullptr || langConfig == translator.getConfigVersion()) {
|
||||
target = translator.getText(idSrc);
|
||||
langConfig = translator.getConfigVersion();
|
||||
}
|
||||
return *target;
|
||||
}
|
||||
|
||||
|
||||
+73
-56
@@ -6,7 +6,8 @@
|
||||
#include "Chars.h"
|
||||
#include "def.h"
|
||||
|
||||
class IdentifiedText {};
|
||||
class LiteralText;
|
||||
class Translator;
|
||||
|
||||
/**
|
||||
* 注意一些默认值。
|
||||
@@ -14,6 +15,8 @@ class IdentifiedText {};
|
||||
* color和background=0xffffffff,表示继承使用默认颜色;
|
||||
*/
|
||||
class RenderableString {
|
||||
friend class LiteralText;
|
||||
|
||||
struct StringConfig {
|
||||
String text;
|
||||
/**
|
||||
@@ -111,6 +114,46 @@ public:
|
||||
return ret;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
private:
|
||||
void parseAppend(const wchar* string) noexcept {
|
||||
StringConfig config;
|
||||
@@ -283,88 +326,62 @@ 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;
|
||||
interface IText {
|
||||
virtual ~IText() = default;
|
||||
virtual const String& getText() const noexcept = 0;
|
||||
virtual const RenderableString& getRenderableString() const noexcept = 0;
|
||||
};
|
||||
|
||||
class Translator;
|
||||
typedef class LiteralText : public IText {
|
||||
const String string;
|
||||
mutable RenderableString renderableString;
|
||||
|
||||
class TranslatableText final : public Text {
|
||||
public:
|
||||
LiteralText(const String& string): string(string), renderableString(string) {}
|
||||
LiteralText(String&& string): string(std::move(string)), renderableString(string) {}
|
||||
|
||||
const String& getText() const noexcept override { return string; }
|
||||
|
||||
const RenderableString& getRenderableString() const noexcept override { return renderableString; }
|
||||
} TranslatedText;
|
||||
|
||||
class TranslatableText final : public IText {
|
||||
const String idSrc;
|
||||
mutable const String* target = nullptr;
|
||||
mutable const LiteralText* target = nullptr;
|
||||
mutable QWORD langConfig = 0;
|
||||
|
||||
public:
|
||||
explicit TranslatableText(const String& id) : idSrc(id) {}
|
||||
explicit TranslatableText(String&& id) : idSrc(std::move(id)) {}
|
||||
explicit TranslatableText(const String& id) : idSrc(id) { std::wcout << L"Lvalue init\n"; }
|
||||
explicit TranslatableText(String&& id) : idSrc(std::move(id)) { std::wcout << L"Rvalue init\n"; }
|
||||
const String& getText() const noexcept override;
|
||||
const RenderableString& getRenderableString() const noexcept override;
|
||||
void refreshText() const noexcept;
|
||||
};
|
||||
|
||||
struct Language {
|
||||
Map<String, String> translateTable;
|
||||
Map<String, TranslatedText> translateTable;
|
||||
int id = 1;
|
||||
};
|
||||
|
||||
class Translator {
|
||||
Map<String, int> langMap{};
|
||||
List<Language> langList{};
|
||||
TranslatedText nullText{ L"\\#FF""EE0000<translator-null>" };
|
||||
String lang = L"zh-cn";
|
||||
String nullText = L"<translator-null>";
|
||||
QWORD langConfig = 1;
|
||||
int langConfig = 1;
|
||||
int idLangMax = 1;
|
||||
using IterID = Map<String, String>::const_iterator;
|
||||
using IterID = Map<String, TranslatedText>::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 addLang(const String& lang) noexcept { langMap.insert(std::make_pair(lang, ++idLangMax)); }
|
||||
void addLang(String&& lang) noexcept { langMap.insert(std::make_pair(lang, ++idLangMax)); }
|
||||
void loadLang();
|
||||
|
||||
const String* getText(const String& id) const noexcept {
|
||||
[[nodiscard]] const TranslatedText* getText(const String& id) const noexcept {
|
||||
for (const auto& [translateTable, _] : langList) {
|
||||
IterID iterator = translateTable.find(id);
|
||||
if (iterator != translateTable.cend()) return &iterator->second;
|
||||
@@ -372,7 +389,7 @@ public:
|
||||
return &nullText;
|
||||
}
|
||||
|
||||
int getConfigVersion() const noexcept { return langConfig; }
|
||||
[[nodiscard]] int getConfigVersion() const noexcept { return langConfig; }
|
||||
};
|
||||
|
||||
inline static Translator translator = Translator();
|
||||
@@ -12,5 +12,10 @@ void Renderer::initialize() noexcept { MainDC = GetDC(MainWindowHandle); }
|
||||
void Renderer::resize(const int width, const int height) noexcept(false) {
|
||||
windowWidth = width;
|
||||
windowHeight = height;
|
||||
if (resizeTime > 0) return; // 防抖、防止频繁触发
|
||||
if (resizeTime < 0) {
|
||||
resizeTime = 20;
|
||||
return;
|
||||
}
|
||||
if (game.getWindow()) game.getWindow()->onResize();
|
||||
}
|
||||
|
||||
+23
-4
@@ -6,28 +6,47 @@
|
||||
|
||||
#include "def.h"
|
||||
|
||||
class Game;
|
||||
/**
|
||||
* 用于标记相对位置。
|
||||
*/
|
||||
enum class Location { LEFT_TOP, LEFT, LEFT_BOTTOM, TOP, CENTER, BOTTOM, RIGHT_TOP, RIGHT, RIGHT_BOTTOM };
|
||||
enum class Location : char { LEFT_TOP, LEFT, LEFT_BOTTOM, TOP, CENTER, BOTTOM, RIGHT_TOP, RIGHT, RIGHT_BOTTOM };
|
||||
|
||||
interface IRenderable {
|
||||
virtual ~IRenderable() = default;
|
||||
virtual void render() const noexcept = 0;
|
||||
};
|
||||
|
||||
class Renderer {
|
||||
interface ITickable {
|
||||
virtual ~ITickable() = default;
|
||||
virtual void tick() noexcept = 0;
|
||||
};
|
||||
|
||||
class Renderer : public ITickable {
|
||||
/**
|
||||
* 后续可能用不到,可能可删
|
||||
*/
|
||||
Game* pGame = nullptr;
|
||||
inline static HDC MainDC;
|
||||
int windowWidth = 0, windowHeight = 0;
|
||||
int resizeTime = 0;
|
||||
|
||||
public:
|
||||
static void initialize() noexcept;
|
||||
explicit Renderer() = default;
|
||||
|
||||
void resize(int width, int height) noexcept(false);
|
||||
|
||||
void setGame(Game& game) noexcept { pGame = &game; }
|
||||
[[nodiscard]] int getWidth() const noexcept { return windowWidth; }
|
||||
[[nodiscard]] int getHeight() const noexcept { return windowHeight; }
|
||||
|
||||
void tick() noexcept override {
|
||||
// 联合处理resize防抖
|
||||
if (resizeTime > 0) --resizeTime;
|
||||
else if (resizeTime == 0) {
|
||||
resize(windowWidth, windowHeight);
|
||||
resizeTime = -1;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
inline static Renderer renderer = Renderer();
|
||||
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
//
|
||||
// Created by EmsiaetKadosh on 25-1-20.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
struct B {
|
||||
int a = 1;
|
||||
B() { std::wcout << L"common constructor\n"; }
|
||||
B(B&) { std::wcout << L"copy constructor\n"; }
|
||||
// B(B&& other) noexcept { std::wcout << L"move constructor\n"; }
|
||||
};
|
||||
|
||||
struct A {
|
||||
B b;
|
||||
|
||||
explicit A(B&& other) : b(other) {}
|
||||
};
|
||||
|
||||
inline void test() {
|
||||
B b;
|
||||
A a{ B() };
|
||||
a = A(std::move(a.b));
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
//
|
||||
// Created by EmsiaetKadosh on 25-1-21.
|
||||
//
|
||||
|
||||
#include "TextureManager.h"
|
||||
@@ -0,0 +1,81 @@
|
||||
//
|
||||
// Created by EmsiaetKadosh on 25-1-21.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "def.h"
|
||||
#include "exception.h"
|
||||
|
||||
class ITexture {};
|
||||
|
||||
class Font {
|
||||
String name;
|
||||
HFONT fonts[16]{};
|
||||
|
||||
static int idOf(const bool italic, const bool bold, const bool underline, const bool strike) {
|
||||
int ret = 0;
|
||||
if (italic) ret |= 8;
|
||||
if (bold) ret |= 4;
|
||||
if (underline) ret |= 2;
|
||||
if (strike) ret |= 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
public:
|
||||
explicit Font(const String& name) : name(name) {}
|
||||
|
||||
void load(const int size) noexcept(false) {
|
||||
LOGFONTW font{
|
||||
.lfHeight = size,
|
||||
.lfWidth = 0,
|
||||
.lfEscapement = 0,
|
||||
.lfOrientation = 0,
|
||||
.lfCharSet = ANSI_CHARSET,
|
||||
.lfOutPrecision = OUT_DEFAULT_PRECIS,
|
||||
.lfClipPrecision = CLIP_DEFAULT_PRECIS,
|
||||
.lfQuality = DEFAULT_QUALITY,
|
||||
.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE,
|
||||
};
|
||||
if (name.size() < LF_FACESIZE) memcpy(font.lfFaceName, name.c_str(), name.size());
|
||||
else throw ArrayIndexOutOfBoundException(L"Font name is too long: " + name);
|
||||
for (int i = 0; i < 16; i++) {
|
||||
font.lfWeight = i & 4 ? 700 : 400;
|
||||
font.lfItalic = i & 8;
|
||||
font.lfUnderline = i & 2;
|
||||
font.lfStrikeOut = i & 1;
|
||||
fonts[i] = CreateFontIndirectW(&font);
|
||||
}
|
||||
}
|
||||
|
||||
void unload() noexcept(false) {
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
DeleteObject(fonts[i]);
|
||||
fonts[i] = nullptr;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class TextureManager {
|
||||
Map<int, Font> fonts;
|
||||
Map<String, ObjectHolder<ITexture>> textures;
|
||||
Font* defaultFont = nullptr;
|
||||
using IterFont = Map<int, Font>::const_iterator;
|
||||
using IterTexture = Map<String, ObjectHolder<ITexture>>::const_iterator;
|
||||
public:
|
||||
TextureManager() {
|
||||
try {
|
||||
fonts.insert(std::make_pair(0, Font(L"Arial")));
|
||||
defaultFont = &fonts.at(0);
|
||||
}
|
||||
catch (...) {
|
||||
|
||||
}
|
||||
}
|
||||
Font& getFont(const int id) const noexcept {
|
||||
IterFont iterator = fonts.find(id);
|
||||
if (iterator == fonts.cend()) return
|
||||
}
|
||||
};
|
||||
|
||||
inline static TextureManager textureManager = TextureManager();
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include "def.h"
|
||||
#include "Renderer.h"
|
||||
#include "IText.h"
|
||||
|
||||
enum class MouseActionCode : char {
|
||||
MAC_MOVE, MAC_HOVER, MAC_DOWN, MAC_UP, MAC_DOUBLE
|
||||
@@ -17,6 +18,7 @@ protected:
|
||||
mutable bool hasMouse = false;
|
||||
|
||||
public:
|
||||
Location location;
|
||||
using Action = Function<void(int)>;
|
||||
double x, y, w, h;
|
||||
Action hover;// 传入int忽略
|
||||
@@ -25,7 +27,7 @@ public:
|
||||
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) {}
|
||||
explicit Widget(const double x, const double y, const double w, const double h, Location location) : x(x), y(y), w(w), h(h), location(location) {}
|
||||
void render() const noexcept override {}
|
||||
virtual void onResize() {}
|
||||
|
||||
@@ -48,23 +50,24 @@ public:
|
||||
hasMouse = false;
|
||||
}
|
||||
hasMouse = true;
|
||||
switch (action & 0xf) {
|
||||
case MouseActionCode::MAC_HOVER:
|
||||
switch (static_cast<char>(action & 0xf)) {
|
||||
case static_cast<char>(MouseActionCode::MAC_HOVER):
|
||||
onLongHover(0);
|
||||
break;
|
||||
case MouseActionCode::MAC_MOVE:
|
||||
case static_cast<char>(MouseActionCode::MAC_MOVE):
|
||||
onHover(0);
|
||||
break;
|
||||
case MouseActionCode::MAC_DOWN:
|
||||
case static_cast<char>(MouseActionCode::MAC_DOWN):
|
||||
onMouseDown(value);
|
||||
break;
|
||||
case MouseActionCode::MAC_UP:
|
||||
case static_cast<char>(MouseActionCode::MAC_UP):
|
||||
onMouseUp(value);
|
||||
break;
|
||||
case MouseActionCode::MAC_DOUBLE:
|
||||
case static_cast<char>(MouseActionCode::MAC_DOUBLE):
|
||||
onMouseClick(1);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -75,6 +78,8 @@ protected:
|
||||
|
||||
Window() = default;
|
||||
|
||||
~Window() override { for (Widget*& widget : widgets) { delete widget; } }
|
||||
|
||||
public:
|
||||
/**
|
||||
* 在Game.setWindow()时,本窗口开启时调用。
|
||||
@@ -101,5 +106,6 @@ public:
|
||||
|
||||
class Button final : public Widget {
|
||||
public:
|
||||
explicit Button(const double x, const double y, const double w, const double h) : Widget(x, y, w, h) {}
|
||||
ObjectHolder<IText> name;
|
||||
explicit Button(const double x, const double y, const double w, const double h, Location location, ObjectHolder<IText> text) : Widget(x, y, w, h, location), name(text) {}
|
||||
};
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
//
|
||||
// Created by EmsiaetKadosh on 25-1-18.
|
||||
//
|
||||
|
||||
#include "def.h"
|
||||
|
||||
#include "exception.h"
|
||||
|
||||
template<TypeName Base> Base& ObjectHolder<Base>::operator->() noexcept(false) {
|
||||
if (value) return *value;
|
||||
throw NullPointerException(L"value is null");
|
||||
}
|
||||
|
||||
template<TypeName Base> const Base& ObjectHolder<Base>::operator->() const noexcept(false) {
|
||||
if (value) return *value;
|
||||
throw NullPointerException(L"value is null");
|
||||
}
|
||||
|
||||
template<TypeName Base> Base& ObjectHolder<Base>::operator*() noexcept(false) {
|
||||
if (value) return *value;
|
||||
throw NullPointerException(L"value is null");
|
||||
}
|
||||
|
||||
template<TypeName Base> const Base& ObjectHolder<Base>::operator*() const noexcept(false) {
|
||||
if (value) return *value;
|
||||
throw NullPointerException(L"value is null");
|
||||
}
|
||||
|
||||
template<TypeName Base> template<NewCopyable T> requires std::is_base_of_v<Base, T> && TypeName<T>
|
||||
void ObjectHolder<Base>::set(const T& value) {
|
||||
if (!value) this->value = new T(value);
|
||||
else {
|
||||
if (hasValue) delete this->value;
|
||||
this->value = new T(value);
|
||||
}
|
||||
}
|
||||
|
||||
template<TypeName Base> template<NewMoveable T> requires std::is_base_of_v<Base, T> && TypeName<T>
|
||||
void ObjectHolder<Base>::set(T&& value) {
|
||||
if (!value) this->value = new T(value);
|
||||
else {
|
||||
if (hasValue) delete this->value;
|
||||
this->value = new T(value);
|
||||
}
|
||||
}
|
||||
|
||||
template<TypeName T> const T& Reference<T>::getLvalue() const noexcept(false) {
|
||||
if (type == ReferenceValueType::LVALUE) return *lvalue;
|
||||
throw NullPointerException(L"reference is rvalue");
|
||||
}
|
||||
|
||||
template<TypeName T> T&& Reference<T>::getRvalue() noexcept(false) {
|
||||
if (type == ReferenceValueType::RVALUE) return std::move(*rvalue);
|
||||
throw NullPointerException(L"reference is lvalue");
|
||||
}
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <atomic>
|
||||
|
||||
using wchar = wchar_t;
|
||||
using QWORD = unsigned long long int;
|
||||
@@ -51,3 +52,99 @@ template<typename F> using Function = std::function<F>;
|
||||
#pragma comment(lib, "dwmapi.lib")
|
||||
#pragma comment(lib, "Uxtheme.lib")
|
||||
#pragma comment(lib, "winmm.lib")
|
||||
|
||||
template<typename T>
|
||||
concept Copyable = requires(const T& t) { T(t); };
|
||||
template<typename T>
|
||||
concept NewCopyable = requires(const T& t) { delete new T(t); };
|
||||
template<typename T>
|
||||
concept Moveable = requires(T&& t) { T(std::move(t)); };
|
||||
template<typename T>
|
||||
concept NewMoveable = requires(T&& t) { delete new T(std::move(t)); };
|
||||
template<typename T>
|
||||
concept NonreferenceType = !std::is_reference_v<T>;
|
||||
template<typename T>
|
||||
concept NonpointerType = !std::is_pointer_v<T>;
|
||||
template<typename T>
|
||||
concept ReferenceType = std::is_reference_v<T>;
|
||||
template<typename T>
|
||||
concept PointerType = std::is_pointer_v<T>;
|
||||
template<typename T>
|
||||
concept TypeName = NonreferenceType<T> && NonpointerType<T>;
|
||||
|
||||
template<TypeName Base> class ObjectHolder {
|
||||
Base* value;
|
||||
bool hasValue;
|
||||
char padding[7]{};
|
||||
|
||||
public:
|
||||
/**
|
||||
* 用于延迟初始化。
|
||||
*/
|
||||
ObjectHolder() : value(nullptr), hasValue(false) {}
|
||||
|
||||
ObjectHolder(Base* const value) : value(value), hasValue(false) {}
|
||||
|
||||
template<NewCopyable T> requires std::is_base_of_v<Base, T> && TypeName<T>
|
||||
ObjectHolder(const T& value) : value(new T(value)), hasValue(true) {}
|
||||
|
||||
template<NewMoveable T> requires std::is_base_of_v<Base, T> && TypeName<T>
|
||||
ObjectHolder(T&& value) : value(new T(std::forward<T>(value))), hasValue(true) {}
|
||||
|
||||
ObjectHolder(const ObjectHolder& other) noexcept: value(other.value), hasValue(false) {}
|
||||
|
||||
ObjectHolder(ObjectHolder&& other) noexcept: value(other.value), hasValue(other.hasValue) {
|
||||
other.value = nullptr;
|
||||
other.hasValue = false;
|
||||
}
|
||||
|
||||
template<NewCopyable T> requires std::is_base_of_v<Base, T> && TypeName<T>
|
||||
void set(const T& value);
|
||||
|
||||
template<NewMoveable T> requires std::is_base_of_v<Base, T> && TypeName<T>
|
||||
void set(T&& value);
|
||||
|
||||
|
||||
~ObjectHolder() {
|
||||
if (hasValue) delete value;
|
||||
value = nullptr;
|
||||
}
|
||||
|
||||
Base& operator->() noexcept(false);
|
||||
const Base& operator->() const noexcept(false);
|
||||
Base& operator*() noexcept(false);
|
||||
const Base& operator*() const noexcept(false);
|
||||
operator bool() const noexcept { return value; }
|
||||
};
|
||||
|
||||
enum class ReferenceValueType {
|
||||
LVALUE,
|
||||
RVALUE
|
||||
};
|
||||
|
||||
template<TypeName T> class Reference {
|
||||
const T* lvalue = nullptr;
|
||||
T* rvalue = nullptr;
|
||||
|
||||
public:
|
||||
const ReferenceValueType type;
|
||||
Reference(const T& lvalue) : lvalue(&lvalue), type(ReferenceValueType::LVALUE) {}
|
||||
Reference(T&& rvalue) : rvalue(&rvalue), type(ReferenceValueType::RVALUE) {}
|
||||
Reference& operator=(const Reference&) = delete;
|
||||
Reference& operator=(Reference&&) = delete;
|
||||
|
||||
Reference& operator=(const T& lvalue) {
|
||||
this->lvalue = &lvalue;
|
||||
this->type = ReferenceValueType::LVALUE;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Reference& operator=(T&& rvalue) {
|
||||
this->rvalue = &rvalue;
|
||||
this->type = ReferenceValueType::RVALUE;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const T& getLvalue() const noexcept(false);
|
||||
T&& getRvalue() noexcept(false);
|
||||
};
|
||||
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
//
|
||||
// Created by EmsiaetKadosh on 25-1-18.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
class Exception : public std::exception {
|
||||
const String* type;
|
||||
|
||||
protected:
|
||||
String msg;
|
||||
|
||||
Exception(String&& msg, const String* type) : type(type), msg(std::move(msg)) {}
|
||||
Exception(const String& msg, const String* type) : type(type), msg(msg) {}
|
||||
|
||||
public:
|
||||
[[nodiscard]] String getMessage() const noexcept { return msg; }
|
||||
[[nodiscard]] const String* getType() const noexcept { return type; }
|
||||
[[nodiscard]] const char* what() const override { return "Use Exception::getMessage() instead.";}
|
||||
};
|
||||
|
||||
class NullPointerException final : public Exception {
|
||||
inline static const String type = L"NullPointerException";
|
||||
|
||||
public:
|
||||
explicit NullPointerException(String&& msg) : Exception(std::move(msg), &type) {}
|
||||
explicit NullPointerException(const String& msg) : Exception(msg, &type) {}
|
||||
};
|
||||
|
||||
class ArrayIndexOutOfBoundException final : public Exception {
|
||||
inline static const String type = L"ArrayIndexOutOfBoundException";
|
||||
|
||||
public:
|
||||
explicit ArrayIndexOutOfBoundException(String&& msg) : Exception(std::move(msg), &type) {}
|
||||
explicit ArrayIndexOutOfBoundException(const String& msg) : Exception(msg, &type) {}
|
||||
};
|
||||
@@ -5,11 +5,15 @@
|
||||
#pragma once
|
||||
|
||||
#include "def.h"
|
||||
#include "exception.h"
|
||||
#include "hbp.h"
|
||||
#include "Renderer.h"
|
||||
#include "InteractManager.h"
|
||||
#include "TextureManager.h"
|
||||
|
||||
#include "Hud.h"
|
||||
#include "Window.h"
|
||||
|
||||
#include "Game.h"
|
||||
|
||||
#include "xWindows.h"
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
|
||||
#include "includes.h"
|
||||
#include "Text.h"
|
||||
#include "IText.h"
|
||||
#include "TestCode.h"
|
||||
|
||||
LRESULT __stdcall WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
|
||||
switch (uMsg) {
|
||||
@@ -159,20 +160,19 @@ int __stdcall wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCm
|
||||
ShowWindow(MainWindowHandle, nCmdShow);
|
||||
InteractManager::initialize();
|
||||
Renderer::initialize();
|
||||
Game::initialize();
|
||||
SetConsoleOutputCP(65001);
|
||||
const String string = String(L"\\#12345678Hello\\/\\f\1Well\\.87654321你好\\r\\r\\u\\-");
|
||||
std::cout << "你好" << std::endl;
|
||||
std::wcout.imbue(std::locale("zh_CN"));
|
||||
std::wcout
|
||||
<< sizeof(L"你好") << " " << sizeof("Hu") << std::endl
|
||||
<< L"GetConsoleOutputCP => " << GetConsoleOutputCP() << std::endl
|
||||
#if defined(UNICODE)
|
||||
<< L"UNICODE" << std::endl
|
||||
#else
|
||||
<< L"Non-UNICODE" << std::endl
|
||||
#endif
|
||||
<< string << std::endl
|
||||
<< RenderableString(string).toString() << std::endl;
|
||||
{
|
||||
const String string = String(L"\\#12345678Hello\\/\\f\1Well\\.87654321你好\\r\\r\\u\\-");
|
||||
std::cout << "你好" << std::endl;
|
||||
std::wcout.imbue(std::locale("zh_CN"));
|
||||
std::wcout
|
||||
<< sizeof(L"你好") << " " << sizeof("Hu") << std::endl
|
||||
<< L"GetConsoleOutputCP => " << GetConsoleOutputCP() << std::endl
|
||||
<< string << std::endl
|
||||
<< RenderableString(string).toString() << std::endl;
|
||||
test();
|
||||
}
|
||||
HACCEL hAccelTable = LoadAcceleratorsW(hInstance, MAKEINTRESOURCE(109));
|
||||
MSG msg = { nullptr };
|
||||
while (GetMessageW(&msg, nullptr, 0, 0)) {
|
||||
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
//
|
||||
// Created by EmsiaetKadosh on 25-1-18.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Window.h"
|
||||
|
||||
class StartWindow : public Window {
|
||||
public:
|
||||
StartWindow() {
|
||||
Button* button = new Button(0, 0, 0.4, 0.08, Location::CENTER, TranslatableText(L"123"));
|
||||
widgets.push_back(button);
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user