Changes
This commit is contained in:
+8
-2
@@ -28,9 +28,15 @@ add_executable(${PROJECT_NAME} main.cpp
|
|||||||
Hud.cpp
|
Hud.cpp
|
||||||
Hud.h
|
Hud.h
|
||||||
includes.h
|
includes.h
|
||||||
Text.h
|
IText.h
|
||||||
Chars.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_NAME ${PROJECT_NAME})
|
||||||
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
|
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
|
||||||
include(CPack)
|
include(CPack)
|
||||||
|
|||||||
@@ -3,3 +3,6 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#include "Game.h"
|
#include "Game.h"
|
||||||
|
|
||||||
|
void Game::initialize() noexcept { renderer.setGame(game); }
|
||||||
|
|
||||||
|
|||||||
@@ -7,13 +7,14 @@
|
|||||||
#include "Hud.h"
|
#include "Hud.h"
|
||||||
#include "Window.h"
|
#include "Window.h"
|
||||||
|
|
||||||
class Game {
|
class Game : public IRenderable {
|
||||||
Hud hud = Hud();
|
Hud hud = Hud();
|
||||||
Window* window = nullptr;
|
Window* window = nullptr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit Game() = default;
|
explicit Game() = default;
|
||||||
void render() const noexcept {
|
static void initialize() noexcept;
|
||||||
|
void render() const noexcept override {
|
||||||
if (window) window->render();
|
if (window) window->render();
|
||||||
hud.render();
|
hud.render();
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-2
@@ -2,16 +2,25 @@
|
|||||||
// Created by EmsiaetKadosh on 25-1-18.
|
// Created by EmsiaetKadosh on 25-1-18.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "Text.h"
|
#include "IText.h"
|
||||||
|
|
||||||
#include "def.h"
|
#include "def.h"
|
||||||
|
|
||||||
const String& TranslatableText::getText() const noexcept {
|
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()) {
|
if (target == nullptr || langConfig == translator.getConfigVersion()) {
|
||||||
target = translator.getText(idSrc);
|
target = translator.getText(idSrc);
|
||||||
langConfig = translator.getConfigVersion();
|
langConfig = translator.getConfigVersion();
|
||||||
}
|
}
|
||||||
return *target;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
+73
-56
@@ -6,7 +6,8 @@
|
|||||||
#include "Chars.h"
|
#include "Chars.h"
|
||||||
#include "def.h"
|
#include "def.h"
|
||||||
|
|
||||||
class IdentifiedText {};
|
class LiteralText;
|
||||||
|
class Translator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 注意一些默认值。
|
* 注意一些默认值。
|
||||||
@@ -14,6 +15,8 @@ class IdentifiedText {};
|
|||||||
* color和background=0xffffffff,表示继承使用默认颜色;
|
* color和background=0xffffffff,表示继承使用默认颜色;
|
||||||
*/
|
*/
|
||||||
class RenderableString {
|
class RenderableString {
|
||||||
|
friend class LiteralText;
|
||||||
|
|
||||||
struct StringConfig {
|
struct StringConfig {
|
||||||
String text;
|
String text;
|
||||||
/**
|
/**
|
||||||
@@ -111,6 +114,46 @@ public:
|
|||||||
return ret;
|
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:
|
private:
|
||||||
void parseAppend(const wchar* string) noexcept {
|
void parseAppend(const wchar* string) noexcept {
|
||||||
StringConfig config;
|
StringConfig config;
|
||||||
@@ -283,88 +326,62 @@ private:
|
|||||||
}
|
}
|
||||||
configs.push_back(std::move(config));
|
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 {
|
interface IText {
|
||||||
virtual ~Text() = default;
|
virtual ~IText() = default;
|
||||||
virtual const String& getText() const noexcept = 0;
|
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;
|
const String idSrc;
|
||||||
mutable const String* target = nullptr;
|
mutable const LiteralText* target = nullptr;
|
||||||
mutable QWORD langConfig = 0;
|
mutable QWORD langConfig = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit TranslatableText(const String& id) : idSrc(id) {}
|
explicit TranslatableText(const String& id) : idSrc(id) { std::wcout << L"Lvalue init\n"; }
|
||||||
explicit TranslatableText(String&& id) : idSrc(std::move(id)) {}
|
explicit TranslatableText(String&& id) : idSrc(std::move(id)) { std::wcout << L"Rvalue init\n"; }
|
||||||
const String& getText() const noexcept override;
|
const String& getText() const noexcept override;
|
||||||
|
const RenderableString& getRenderableString() const noexcept override;
|
||||||
|
void refreshText() const noexcept;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Language {
|
struct Language {
|
||||||
Map<String, String> translateTable;
|
Map<String, TranslatedText> translateTable;
|
||||||
int id = 1;
|
int id = 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Translator {
|
class Translator {
|
||||||
Map<String, int> langMap{};
|
Map<String, int> langMap{};
|
||||||
List<Language> langList{};
|
List<Language> langList{};
|
||||||
|
TranslatedText nullText{ L"\\#FF""EE0000<translator-null>" };
|
||||||
String lang = L"zh-cn";
|
String lang = L"zh-cn";
|
||||||
String nullText = L"<translator-null>";
|
int langConfig = 1;
|
||||||
QWORD langConfig = 1;
|
|
||||||
int idLangMax = 1;
|
int idLangMax = 1;
|
||||||
using IterID = Map<String, String>::const_iterator;
|
using IterID = Map<String, TranslatedText>::const_iterator;
|
||||||
using IterLang = List<Language>::const_iterator;
|
using IterLang = List<Language>::const_iterator;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit Translator() { langMap.insert(std::make_pair(String(L"zh-cn"), 1)); }
|
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(const String& lang) noexcept { 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(String&& lang) noexcept { langMap.insert(std::make_pair(lang, ++idLangMax)); }
|
||||||
void loadLang();
|
void loadLang();
|
||||||
|
|
||||||
const String* getText(const String& id) const noexcept {
|
[[nodiscard]] const TranslatedText* getText(const String& id) const noexcept {
|
||||||
for (const auto& [translateTable, _] : langList) {
|
for (const auto& [translateTable, _] : langList) {
|
||||||
IterID iterator = translateTable.find(id);
|
IterID iterator = translateTable.find(id);
|
||||||
if (iterator != translateTable.cend()) return &iterator->second;
|
if (iterator != translateTable.cend()) return &iterator->second;
|
||||||
@@ -372,7 +389,7 @@ public:
|
|||||||
return &nullText;
|
return &nullText;
|
||||||
}
|
}
|
||||||
|
|
||||||
int getConfigVersion() const noexcept { return langConfig; }
|
[[nodiscard]] int getConfigVersion() const noexcept { return langConfig; }
|
||||||
};
|
};
|
||||||
|
|
||||||
inline static Translator translator = Translator();
|
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) {
|
void Renderer::resize(const int width, const int height) noexcept(false) {
|
||||||
windowWidth = width;
|
windowWidth = width;
|
||||||
windowHeight = height;
|
windowHeight = height;
|
||||||
|
if (resizeTime > 0) return; // 防抖、防止频繁触发
|
||||||
|
if (resizeTime < 0) {
|
||||||
|
resizeTime = 20;
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (game.getWindow()) game.getWindow()->onResize();
|
if (game.getWindow()) game.getWindow()->onResize();
|
||||||
}
|
}
|
||||||
|
|||||||
+23
-4
@@ -6,28 +6,47 @@
|
|||||||
|
|
||||||
#include "def.h"
|
#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 {
|
interface IRenderable {
|
||||||
virtual ~IRenderable() = default;
|
virtual ~IRenderable() = default;
|
||||||
virtual void render() const noexcept = 0;
|
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;
|
inline static HDC MainDC;
|
||||||
int windowWidth = 0, windowHeight = 0;
|
int windowWidth = 0, windowHeight = 0;
|
||||||
|
int resizeTime = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static void initialize() noexcept;
|
static void initialize() noexcept;
|
||||||
explicit Renderer() = default;
|
explicit Renderer() = default;
|
||||||
|
|
||||||
void resize(int width, int height) noexcept(false);
|
void resize(int width, int height) noexcept(false);
|
||||||
|
void setGame(Game& game) noexcept { pGame = &game; }
|
||||||
[[nodiscard]] int getWidth() const noexcept { return windowWidth; }
|
[[nodiscard]] int getWidth() const noexcept { return windowWidth; }
|
||||||
[[nodiscard]] int getHeight() const noexcept { return windowHeight; }
|
[[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();
|
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 "def.h"
|
||||||
#include "Renderer.h"
|
#include "Renderer.h"
|
||||||
|
#include "IText.h"
|
||||||
|
|
||||||
enum class MouseActionCode : char {
|
enum class MouseActionCode : char {
|
||||||
MAC_MOVE, MAC_HOVER, MAC_DOWN, MAC_UP, MAC_DOUBLE
|
MAC_MOVE, MAC_HOVER, MAC_DOWN, MAC_UP, MAC_DOUBLE
|
||||||
@@ -17,6 +18,7 @@ protected:
|
|||||||
mutable bool hasMouse = false;
|
mutable bool hasMouse = false;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
Location location;
|
||||||
using Action = Function<void(int)>;
|
using Action = Function<void(int)>;
|
||||||
double x, y, w, h;
|
double x, y, w, h;
|
||||||
Action hover;// 传入int忽略
|
Action hover;// 传入int忽略
|
||||||
@@ -25,7 +27,7 @@ public:
|
|||||||
Action mouseUp;// 传入int表示变更按键。0左, 1中, 2右
|
Action mouseUp;// 传入int表示变更按键。0左, 1中, 2右
|
||||||
Action mouseLeave;// 传入int忽略
|
Action mouseLeave;// 传入int忽略
|
||||||
Action mouseClick;// 传入int表示变更按键。0x0左, 0x1中, 0x2右;0xf表示是否双击
|
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 {}
|
void render() const noexcept override {}
|
||||||
virtual void onResize() {}
|
virtual void onResize() {}
|
||||||
|
|
||||||
@@ -48,23 +50,24 @@ public:
|
|||||||
hasMouse = false;
|
hasMouse = false;
|
||||||
}
|
}
|
||||||
hasMouse = true;
|
hasMouse = true;
|
||||||
switch (action & 0xf) {
|
switch (static_cast<char>(action & 0xf)) {
|
||||||
case MouseActionCode::MAC_HOVER:
|
case static_cast<char>(MouseActionCode::MAC_HOVER):
|
||||||
onLongHover(0);
|
onLongHover(0);
|
||||||
break;
|
break;
|
||||||
case MouseActionCode::MAC_MOVE:
|
case static_cast<char>(MouseActionCode::MAC_MOVE):
|
||||||
onHover(0);
|
onHover(0);
|
||||||
break;
|
break;
|
||||||
case MouseActionCode::MAC_DOWN:
|
case static_cast<char>(MouseActionCode::MAC_DOWN):
|
||||||
onMouseDown(value);
|
onMouseDown(value);
|
||||||
break;
|
break;
|
||||||
case MouseActionCode::MAC_UP:
|
case static_cast<char>(MouseActionCode::MAC_UP):
|
||||||
onMouseUp(value);
|
onMouseUp(value);
|
||||||
break;
|
break;
|
||||||
case MouseActionCode::MAC_DOUBLE:
|
case static_cast<char>(MouseActionCode::MAC_DOUBLE):
|
||||||
onMouseClick(1);
|
onMouseClick(1);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -75,6 +78,8 @@ protected:
|
|||||||
|
|
||||||
Window() = default;
|
Window() = default;
|
||||||
|
|
||||||
|
~Window() override { for (Widget*& widget : widgets) { delete widget; } }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* 在Game.setWindow()时,本窗口开启时调用。
|
* 在Game.setWindow()时,本窗口开启时调用。
|
||||||
@@ -101,5 +106,6 @@ public:
|
|||||||
|
|
||||||
class Button final : public Widget {
|
class Button final : public Widget {
|
||||||
public:
|
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 <list>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
using wchar = wchar_t;
|
using wchar = wchar_t;
|
||||||
using QWORD = unsigned long long int;
|
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, "dwmapi.lib")
|
||||||
#pragma comment(lib, "Uxtheme.lib")
|
#pragma comment(lib, "Uxtheme.lib")
|
||||||
#pragma comment(lib, "winmm.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
|
#pragma once
|
||||||
|
|
||||||
#include "def.h"
|
#include "def.h"
|
||||||
|
#include "exception.h"
|
||||||
#include "hbp.h"
|
#include "hbp.h"
|
||||||
#include "Renderer.h"
|
#include "Renderer.h"
|
||||||
#include "InteractManager.h"
|
#include "InteractManager.h"
|
||||||
|
#include "TextureManager.h"
|
||||||
|
|
||||||
#include "Hud.h"
|
#include "Hud.h"
|
||||||
#include "Window.h"
|
#include "Window.h"
|
||||||
|
|
||||||
#include "Game.h"
|
#include "Game.h"
|
||||||
|
|
||||||
|
#include "xWindows.h"
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
|
|
||||||
#include "includes.h"
|
#include "includes.h"
|
||||||
#include "Text.h"
|
#include "IText.h"
|
||||||
|
#include "TestCode.h"
|
||||||
|
|
||||||
LRESULT __stdcall WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
|
LRESULT __stdcall WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
|
||||||
switch (uMsg) {
|
switch (uMsg) {
|
||||||
@@ -159,20 +160,19 @@ int __stdcall wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCm
|
|||||||
ShowWindow(MainWindowHandle, nCmdShow);
|
ShowWindow(MainWindowHandle, nCmdShow);
|
||||||
InteractManager::initialize();
|
InteractManager::initialize();
|
||||||
Renderer::initialize();
|
Renderer::initialize();
|
||||||
|
Game::initialize();
|
||||||
SetConsoleOutputCP(65001);
|
SetConsoleOutputCP(65001);
|
||||||
const String string = String(L"\\#12345678Hello\\/\\f\1Well\\.87654321你好\\r\\r\\u\\-");
|
{
|
||||||
std::cout << "你好" << std::endl;
|
const String string = String(L"\\#12345678Hello\\/\\f\1Well\\.87654321你好\\r\\r\\u\\-");
|
||||||
std::wcout.imbue(std::locale("zh_CN"));
|
std::cout << "你好" << std::endl;
|
||||||
std::wcout
|
std::wcout.imbue(std::locale("zh_CN"));
|
||||||
<< sizeof(L"你好") << " " << sizeof("Hu") << std::endl
|
std::wcout
|
||||||
<< L"GetConsoleOutputCP => " << GetConsoleOutputCP() << std::endl
|
<< sizeof(L"你好") << " " << sizeof("Hu") << std::endl
|
||||||
#if defined(UNICODE)
|
<< L"GetConsoleOutputCP => " << GetConsoleOutputCP() << std::endl
|
||||||
<< L"UNICODE" << std::endl
|
<< string << std::endl
|
||||||
#else
|
<< RenderableString(string).toString() << std::endl;
|
||||||
<< L"Non-UNICODE" << std::endl
|
test();
|
||||||
#endif
|
}
|
||||||
<< string << std::endl
|
|
||||||
<< RenderableString(string).toString() << std::endl;
|
|
||||||
HACCEL hAccelTable = LoadAcceleratorsW(hInstance, MAKEINTRESOURCE(109));
|
HACCEL hAccelTable = LoadAcceleratorsW(hInstance, MAKEINTRESOURCE(109));
|
||||||
MSG msg = { nullptr };
|
MSG msg = { nullptr };
|
||||||
while (GetMessageW(&msg, nullptr, 0, 0)) {
|
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