格式整理

This commit is contained in:
EmsiaetKadosh
2025-03-16 14:18:05 +08:00
parent a1d0f11032
commit c344588924
23 changed files with 467 additions and 257 deletions
+65
View File
@@ -0,0 +1,65 @@
Checks: >
*,
-altera-id-dependent-backward-branch,
-altera-struct-pack-align,
-altera-unroll-loops,
-boost-*,
-bugprone-easily-swappable-parameters,
-bugprone-forward-declaration-namespace,
-bugprone-unhandled-exception-at-new,
-cert-err58-cpp,
-cppcoreguidelines-avoid-*,
-cppcoreguidelines-init-variables,
-cppcoreguidelines-macro-usage,
-cppcoreguidelines-missing-std-forward,
-cppcoreguidelines-owning-memory,
-cppcoreguidelines-pro-bounds-pointer-arithmetic,
-cppcoreguidelines-pro-type-member-init,
-cppcoreguidelines-pro-type-reinterpret-cast,
-cppcoreguidelines-rvalue-reference-param-not-moved,
-cppcoreguidelines-virtual-class-destructor,
-fuchsia-default-arguments-*,
-fuchsia-overloaded-operator,
-fuchsia-statically-constructed-objects,
-fuchsia-trailing-return,
-google-build-using-namespace,
-google-default-arguments,
-google-explicit-constructor,
-google-runtime-int,
-hicpp-avoid-c-arrays,
-hicpp-member-init,
-hicpp-signed-bitwise,
-hicpp-use-auto,
-llvm-header-guard,
-llvm-include-order,
-llvmlibc-*,
-misc-include-cleaner,
-misc-misplaced-const,
-misc-unused-parameters,
-misc-use-internal-linkage,
-modernize-avoid-c-arrays,
-modernize-use-auto,
-modernize-use-designated-initializers,
-modernize-use-ranges,
-modernize-use-trailing-return-type,
-modernize-use-using,
-performance-avoid-endl,
-performance-enum-size,
-performance-no-int-to-ptr,
-readability-avoid-unconditional-preprocessor-if,
-readability-braces-around-statements,
-readability-convert-member-functions-to-static,
-readability-function-cognitive-complexity,
-readability-identifier-length,
-readability-implicit-bool-conversion,
-readability-isolate-declaration,
-readability-magic-numbers,
-readability-math-missing-parentheses,
-readability-redundant-member-init,
-readability-use-std-min-max,
-*-braces-around-statements,
-*-exception-escape,
-*-named-parameter,
-*-non-private-member-variables-in-classes,
-*-special-member-functions,
-*-uppercase-literal-suffix
+6 -6
View File
@@ -30,7 +30,7 @@ private:
bool doReverse = true;
public:
Animation() noexcept {}
Animation() noexcept = default;
Animation& allowPositiveSuper(const bool val = true) noexcept {
positiveSuperAllowed = val;
@@ -42,12 +42,12 @@ public:
return *this;
}
Animation& depends(Depend depend) noexcept {
Animation& depends(const Depend depend) noexcept {
this->depend = depend;
return *this;
}
Animation& features(Style style) noexcept {
Animation& features(const Style style) noexcept {
this->style = style;
return *this;
}
@@ -62,7 +62,7 @@ public:
return *this;
}
Animation& setDuration(const unsigned int val) noexcept {
Animation& setDuration(const int val) noexcept {
if (duration == 0) duration = 1;
duration = val;
return *this;
@@ -70,11 +70,11 @@ public:
void reset() const noexcept { progress = 0; }
double weight(double x) const noexcept {
static double weight(double x) noexcept {
if (x <= 0.0) return 0.0;
if (x >= 1.0) return 1.0;
x *= 2;
return x < 1.0 ? pow(x, 5.0) * 0.5 : 1.0 + pow(x - 2.0, 5.0) * 0.5;
return x < 1.0 ? pow(x, 5.0) * 0.5 : pow(x - 2.0, 5.0) * 0.5 + 1.0;
}
double calculateNext() const noexcept {
+6 -6
View File
@@ -57,18 +57,18 @@ static constexpr wchar Table16[17] = L"0123456789ABCDEF";
String ret;
if (fills >= 8 || value < static_cast<unsigned int>(1) << fills * 4) {
ret.assign(fills, L'0');
for (unsigned int i = fills - 1; i != 0 && value; --i) {
for (unsigned int i = fills - 1; i && value; --i) {
ret[i] = Table16[value & 0xf];
value >>= 4;
}
} else {
unsigned int i = 0;
while (i < 8) {
if ((value >> i) & 0xf) break;
if (value >> i & 0xf) break;
++i;
}
while (i < 8) {
ret.push_back(Table16[(value >> i) & 0xf]);
ret.push_back(Table16[value >> i & 0xf]);
++i;
}
if (ret.empty()) ret = L"0";
@@ -86,18 +86,18 @@ static constexpr wchar Table16[17] = L"0123456789ABCDEF";
String ret;
if (fills >= 16 || value < static_cast<QWORD>(1) << fills * 4) {
ret.assign(fills, L'0');
for (QWORD i = fills - 1; i != 0 && value; --i) {
for (QWORD i = fills - 1; i && value; --i) {
ret[i] = Table16[value & 0xf];
value >>= 4;
}
} else {
QWORD i = 0;
while (i < 16) {
if ((value >> i) & 0xf) break;
if (value >> i & 0xf) break;
++i;
}
while (i < 16) {
ret.push_back(Table16[(value >> i) & 0xf]);
ret.push_back(Table16[value >> i & 0xf]);
++i;
}
if (ret.empty()) ret = L"0";
+83 -9
View File
@@ -4,17 +4,88 @@
#pragma once
class File {
public:
std::wfstream file;
explicit File(const std::wstring& path) : file(path, std::ios::in | std::ios::out | std::ios::binary) {}
String path{};
std::wfstream file{};
int flags = std::ios::in | std::ios::out | std::ios::binary;
File(const String& path) : path(path) {}
File(const File&) = delete;
File(File&&) = delete;
~File() { if (file.is_open()) file.close(); }
File& operator=(const File&) = delete;
File& operator=(File&&) = delete;
File& open() {
if (file.is_open()) file.close();
file.open(path, flags);
return *this;
}
File& close() {
if (file.is_open()) file.close();
return *this;
}
File& clearContent() {
file.clear();
if (file.is_open()) file.close();
file.open(path, flags | std::ios::trunc);
return *this;
}
File& inputs(const bool value = true) {
if (value) flags |= std::ios::in;
else flags &= ~std::ios::in;
return *this;
}
File& outputs(const bool value = true) {
if (value) flags |= std::ios::out;
else flags &= ~std::ios::out;
return *this;
}
File& binary(const bool value = true) {
if (value) flags |= std::ios::binary;
else flags &= ~std::ios::binary;
return *this;
}
File& append(const bool value = true) {
if (value) flags |= std::ios::app;
else flags &= ~std::ios::app;
return *this;
}
File& truncate(const bool value = true) {
if (value) flags |= std::ios::trunc;
else flags &= ~std::ios::trunc;
return *this;
}
template <typename T>
File& operator<<(T&& value) {
if (file.is_open()) file << std::forward<T>(value);
return *this;
}
File& operator<<(decltype(std::endl<wchar, std::char_traits<wchar>>) value) {
if (file.is_open()) file << value;
return *this;
}
template <typename T>
File& operator>>(T&& value) {
if (file.is_open()) file >> std::forward<T>(value);
return *this;
}
};
class Data {
public:
enum class DataType : int {
enum class DataType : unsigned char {
Integer, Double, String, Boolean, Null, List, Object
};
@@ -34,9 +105,7 @@ class DataLoader {
while (!file.file.eof()) {
wchar c = file.file.get();
if (c == L'\"') Success();
if (c == L'\\') {
c = file.file.get();
}
if (c == L'\\') { c = file.file.get(); }
}
errorInfo = L"Error: String never ends. EOF comes before a '\"'";
Failed();
@@ -45,7 +114,7 @@ class DataLoader {
int loadUntil(int& line, wchar at = 0) {
String name = {};
String val = {};
enum { identifier, eq, value, end } status = identifier;
enum : unsigned char { identifier, eq, value, end } status = identifier;
while (!file.file.eof()) {
const wchar c = file.file.get();
if (c == L'\n') ++line;
@@ -72,12 +141,17 @@ class DataLoader {
public:
String errorInfo = {};
explicit DataLoader(const String& path) : file(path) {}
DataLoader(const String& path) : file(path) {}
DataLoader(const DataLoader&) = delete;
DataLoader(DataLoader&&) = delete;
DataLoader& operator=(const DataLoader&) = delete;
DataLoader& operator=(DataLoader&&) = delete;
~DataLoader() = default;
int load() {
int line = 1;
return loadUntil(line);
}
};
inline File& [[carlbeks::releasedat]] MainLogFile = (new File(L"log.txt"))->binary().inputs().outputs().truncate().open().operator<<(L"initialize MainLogFile\n");
+10 -13
View File
@@ -9,10 +9,9 @@
#include "gc.h"
#include "Hud.h"
#include "Task.h"
#include "utils.h"
#include "Window.h"
class Game final : public IRenderable {
class Game final /* : public IRenderable, public ITickable */ {
friend void gameThread();
WindowManager windows;
Hud hud = Hud(); // 8
@@ -21,14 +20,16 @@ class Game final : public IRenderable {
QWORD currentTick = 0; // 8
public:
mutable GarbageCollector gc;
TaskScheduler tasks; // 8
std::minstd_rand random;
explicit Game();
~Game() override;
Game();
~Game();
void render() const noexcept override {
[[nodiscard]] QWORD getTick() const noexcept { return currentTick; }
int closeWindow(Window* const window) noexcept { return windows.pop(window); }
void render() const noexcept {
if (renderer.checkResizing()) return;
renderer.gameStartRender();
caption->render();
@@ -46,7 +47,7 @@ public:
int setWindow(Window* window) noexcept {
if (window) {
if (window->onOpen()) {
for (auto i = windows.begin(); i != windows.end(); ++i) i->passEvent(MouseActionCode::MAC_LEAVE, 0, 0, 0);
for (Window& i : windows) i.passEvent(MouseActionCode::MAC_LEAVE, 0, 0, 0);
windows.pushNewed(window);
Success();
}
@@ -59,15 +60,11 @@ public:
[[nodiscard]] FloatWindow& getFloatWindow() const noexcept { return *floatWindow; }
[[nodiscard]] Window* getWindow() const noexcept {
if (const auto back = windows.back()) return static_cast<Window*>(back);
if (auto *const back = windows.back()) return dynamic_cast<Window*>(back);
Logger.error(L"Game::getWindow returns nullptr");
return nullptr;
}
[[nodiscard]] QWORD getTick() const noexcept { return currentTick; }
int closeWindow(Window* const window) noexcept { return windows.pop(window); }
void tick() noexcept {
++currentTick;
floatWindow->clear();
@@ -89,7 +86,7 @@ public:
void passEvent(const MouseActionCode action, const MouseButtonCode value, const int x, const int y) const noexcept {
caption->passEvent(action, value, x, y);
if (const auto window = getWindow()) window->passEvent(action, value, x, y);
if (Window* const window = getWindow()) window->passEvent(action, value, x, y);
floatWindow->passEvent(action, value, x, y);
}
};
+21 -21
View File
@@ -3,10 +3,11 @@
//
#pragma once
#include <ranges>
#include "Chars.h"
#include "def.h"
#include "Chars.h"
#include "InteractManager.h"
class LiteralText;
@@ -37,7 +38,7 @@ class RenderableString {
FontStyle style = 0;
FontID idFont = 0;
explicit StringConfig() = default;
StringConfig() = default;
void reset() noexcept {
idFont = 0;
@@ -109,10 +110,10 @@ class RenderableString {
using ConstIterator = List<StringConfig>::const_iterator;
public:
explicit RenderableString(const String& string): RenderableString(string.c_str(), string.length()) {}
explicit RenderableString(String&& string) : RenderableString(string.c_str(), string.length()) {}
RenderableString(const String& string): RenderableString(string.c_str(), string.length()) {}
RenderableString(String&& string) : RenderableString(string.c_str(), string.length()) {}
explicit RenderableString(const wchar* const string, const QWORD length = static_cast<QWORD>(-1)) {
RenderableString(const wchar* const string, const QWORD length = static_cast<QWORD>(-1)) {
if (length == -1) parseAppend(string);
else parseAppend(string, length);
}
@@ -171,8 +172,8 @@ public:
return *this;
}
int getHeight() const noexcept;
int getWidth(FontID defaultID = 1) const noexcept;
[[nodiscard]] int getHeight() const noexcept;
[[nodiscard]] int getWidth(FontID defaultID = 0) const noexcept;
int getWidth(RenderConfig* renderConfigs, FontID defaultID) const noexcept;
private:
@@ -353,14 +354,13 @@ private:
}
};
inline RenderableString operator""_renderable(const wchar* const text, const QWORD len) noexcept { return RenderableString(text); }
inline RenderableString operator""_renderable(const wchar* const text, const QWORD) noexcept { return RenderableString(text); }
class Font {
public:
Function<void(int width, int height)> resize;
private:
friend class ObjectHolder<Font>;
friend class FontManager;
friend class RenderableString;
const String name;
@@ -374,9 +374,9 @@ private:
const FontID id;
bool adaptAllSize = false;
explicit Font(const FontID id, const String& name, const double heightModifier, const double yOffset, const long escapement, const long orientation, const bool adaptAllSize) : name{ name }, yOffset(yOffset), heightModifier(heightModifier), height(interactSettings.actual.fontHeight * heightModifier), escapement(escapement), orientation(orientation), yOffsetPx(yOffset * height), id(id), adaptAllSize(adaptAllSize) {}
Font(const FontID id, const String& name, const double heightModifier, const double yOffset, const long escapement, const long orientation, const bool adaptAllSize) : name{ name }, yOffset(yOffset), heightModifier(heightModifier), height(static_cast<long>(interactSettings.actual.fontHeight * heightModifier)), escapement(escapement), orientation(orientation), yOffsetPx(static_cast<long>(yOffset * height)), id(id), adaptAllSize(adaptAllSize) {}
explicit Font(const FontID id, String&& name, const double heightModifier, const double yOffset, const long escapement, const long orientation, const bool adaptAllSize) : name{ std::move(name) }, yOffset(yOffset), heightModifier(heightModifier), height(interactSettings.actual.fontHeight * heightModifier), escapement(escapement), orientation(orientation), yOffsetPx(yOffset * height), id(id), adaptAllSize(adaptAllSize) {}
Font(const FontID id, String&& name, const double heightModifier, const double yOffset, const long escapement, const long orientation, const bool adaptAllSize) : name{ std::move(name) }, yOffset(yOffset), heightModifier(heightModifier), height(static_cast<long>(interactSettings.actual.fontHeight * heightModifier)), escapement(escapement), orientation(orientation), yOffsetPx(static_cast<long>(yOffset * height)), id(id), adaptAllSize(adaptAllSize) {}
public:
Font(const Font&) = default;
@@ -427,11 +427,11 @@ public:
class FontManager {
Map<FontID, Font> fonts;
Font *defaultFont, *captionFont;
FontID assigned = 1;
FontID assigned = 0;
using IterFonts = Map<FontID, Font>::const_iterator;
public:
explicit FontManager() {
FontManager() {
captionFont = &newFont(L"Microsoft YaHei UI Light");
defaultFont = &newFont(L"Microsoft YaHei UI Light");
captionFont->height = interactSettings.actual.captionHeight >> 1;
@@ -463,14 +463,14 @@ public:
return fonts.emplace(assigned, std::move(Font(assigned, std::move(name), heightModifier, yOffset, adaptAllSize, escapement, orientation))).first->second;
}
Font& getDefault() const noexcept { return *defaultFont; }
[[nodiscard]] Font& getDefault() const noexcept { return *defaultFont; }
void resize(const int width, const int height) {
for (auto& font : fonts | std::views::values)
if (font.resize) font.resize(width, height);
else {
font.height = interactSettings.actual.fontHeight * font.heightModifier;
font.yOffsetPx = font.height * font.yOffset;
font.height = static_cast<long>(interactSettings.actual.fontHeight * font.heightModifier);
font.yOffsetPx = static_cast<long>(font.height * font.yOffset);
font.clear();
}
}
@@ -487,8 +487,8 @@ typedef class LiteralText final : public IText {
mutable RenderableString renderableString;
public:
explicit LiteralText(const String& string): string(string), renderableString(string) {}
explicit LiteralText(String&& string): string(std::move(string)), renderableString(this->string) {}
LiteralText(const String& string): string(string), renderableString(string) {}
LiteralText(String&& string): string(std::move(string)), renderableString(this->string) {}
const String& getText() const noexcept override { return string; }
@@ -501,8 +501,8 @@ class TranslatableText final : public IText {
mutable QWORD langConfig = 0;
public:
explicit TranslatableText(const String& id) : idSrc(id) {}
explicit TranslatableText(String&& id) : idSrc(std::move(id)) {}
TranslatableText(const String& id) : idSrc(id) {}
TranslatableText(String&& id) : idSrc(std::move(id)) {}
const String& getText() const noexcept override;
const RenderableString& getRenderableString() const noexcept override;
void refreshText() const noexcept;
@@ -524,7 +524,7 @@ class Translator {
using IterLang = List<Language>::const_iterator;
public:
explicit Translator() { langMap.insert(std::make_pair(String(L"zh-cn"), 1)); }
Translator() { langMap.insert(std::make_pair(String(L"zh-cn"), 1)); }
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();
+1 -1
View File
@@ -280,4 +280,4 @@ bool InteractManager::isInClientCaption() const noexcept { return mouseX > inter
KeyStatus& InteractManager::getKey(const KeyBinding& binding) noexcept { return keyStatus[binding.keyCode]; }
MouseButtonCode InteractManager::getMouseButtonCode() const noexcept { return (keyStatus[VK_LBUTTON].isPressed() ? static_cast<int>(MouseButtonCodeEnum::MBC_L_DOWN) : 0) | (keyStatus[VK_RBUTTON].isPressed() ? static_cast<int>(MouseButtonCodeEnum::MBC_R_DOWN) : 0) | (keyStatus[VK_MBUTTON].isPressed() ? static_cast<int>(MouseButtonCodeEnum::MBC_M_DOWN) : 0); }
MouseButtonCode InteractManager::getMouseButtonCode() const noexcept { return (keyStatus[VK_LBUTTON].isPressed() ? static_cast<unsigned int>(MouseButtonCodeEnum::MBC_L_DOWN) : 0) | (keyStatus[VK_RBUTTON].isPressed() ? static_cast<int>(MouseButtonCodeEnum::MBC_R_DOWN) : 0) | (keyStatus[VK_MBUTTON].isPressed() ? static_cast<int>(MouseButtonCodeEnum::MBC_M_DOWN) : 0); }
+2 -2
View File
@@ -62,7 +62,7 @@ class InteractManager {
public:
void initialize() noexcept { trackMouseEvent.hwndTrack = MainWindowHandle; }
explicit InteractManager();
InteractManager();
void update(const int keyCode, const bool isPressed) noexcept {
if (keyCode >= 256) return;
@@ -100,7 +100,7 @@ public:
[[nodiscard]] bool isInClientCaption() const noexcept;
[[nodiscard]] KeyStatus& getKey(const int keyCode) noexcept { return keyStatus[keyCode]; }
[[nodiscard]] KeyStatus& getKey(const KeyBinding& binding) noexcept;
[[nodiscard]] int getMouseButtonCode() const noexcept;
[[nodiscard]] unsigned int /*MouseButtonCode*/ getMouseButtonCode() const noexcept;
int dealMouseWheel() noexcept {
const int ret = mouseWheel;
+7 -9
View File
@@ -86,7 +86,7 @@ public:
}
if (canvasBitmap && assistBitmap) {
task.pop();
Logger.info(L"Successfully reload bitmap " + ptrtow(reinterpret_cast<QWORD>(static_cast<void*>(canvasBitmap))) + L" " + ptrtow(reinterpret_cast<QWORD>(static_cast<void*>(assistBitmap))));
Logger.info(L"Successfully reload bitmap " + ptrtow(reinterpret_cast<QWORD>(canvasBitmap)) + L" " + ptrtow(reinterpret_cast<QWORD>(assistBitmap)));
this->resizeEnd();
}
Logger.print(task.reserved[0]);
@@ -94,11 +94,10 @@ public:
private:
void gameStartRender() noexcept;
void gameEndRender() noexcept;
public:
explicit Renderer() { Logger.put(L"Renderer created"); }
Renderer() { Logger.put(L"Renderer created"); }
~Renderer() override {
Logger.put(L"Renderer destroyed");
@@ -128,7 +127,7 @@ public:
* @param argb ARGB式颜色
* @return int BGR式颜色
*/
[[nodiscard]] static unsigned int changeColorFormat(const unsigned int argb) { return ((argb << 16) & 0xff0000) | (argb & 0xff00) | ((argb >> 16) & 0xff); }
[[nodiscard]] static unsigned int changeColorFormat(const unsigned int argb) { return argb << 16 & 0xff0000 | argb & 0xff00 | argb >> 16 & 0xff; }
void assertRendering() const noexcept(false) { if (!isRendering) throw InvalidOperationException(L"Operation should be done while rendering"); }
@@ -167,7 +166,7 @@ public:
.right = x + w,
.bottom = y + h
};
HBRUSH clr = CreateSolidBrush(changeColorFormat(color));
const HBRUSH clr = CreateSolidBrush(changeColorFormat(color));
FillRect(canvasDC, &rect, clr);
deleteObject(clr);
} else {
@@ -178,7 +177,7 @@ public:
.bottom = y + h > windowHeight ? windowHeight - y : h
};
blendFunction.SourceConstantAlpha = color >> 24;
HBRUSH clr = CreateSolidBrush(changeColorFormat(color));
const HBRUSH clr = CreateSolidBrush(changeColorFormat(color));
FillRect(assistDC, &rect, clr);
deleteObject(clr);
if (!AlphaBlend(canvasDC, x, y, rect.right, rect.bottom, assistDC, 0, 0, rect.right, rect.bottom, blendFunction)) Logger.error(L"AlphaBlend failed");
@@ -189,8 +188,7 @@ public:
assertRendering();
//assertRenderThread();
if ((color & 0xff000000) == 0) return;
if ((color & 0xff000000) == 0xff000000) {
HBRUSH clr = CreateSolidBrush(changeColorFormat(color));
if ((color & 0xff000000) == 0xff000000) { const HBRUSH clr = CreateSolidBrush(changeColorFormat(color));
FillRect(canvasDC, rect, clr);
deleteObject(clr);
} else {
@@ -201,7 +199,7 @@ public:
.bottom = rect->bottom > windowHeight ? windowHeight : rect->bottom - rect->top
};
blendFunction.SourceConstantAlpha = color >> 24;
HBRUSH clr = CreateSolidBrush(changeColorFormat(color));
const HBRUSH clr = CreateSolidBrush(changeColorFormat(color));
FillRect(assistDC, &r, clr);
deleteObject(clr);
if (!AlphaBlend(canvasDC, rect->left, rect->top, r.right, r.bottom, assistDC, 0, 0, r.right, r.bottom, blendFunction)) Logger.error(L"AlphaBlend failed");
+12 -3
View File
@@ -10,12 +10,15 @@ class TaskScheduler;
class Task final : public AnywhereEditable<Task> {
friend class TaskScheduler;
#ifndef __CARLBEKS_DEBUG__
QWORD triggerInterval = 0, nextExecuteTime = 0, lastExecuteTime = 0;
#endif
public:
Function<void(Task& self)> func;
explicit Task(const Function<void(Task& self)>& func) : func(func) {}
explicit Task(Function<void(Task& self)>&& func) : func(std::move(func)) {}
Task(const Function<void(Task& self)>& func) : func(func) {}
Task(Function<void(Task& self)>&& func) : func(std::move(func)) {}
void schedulePop(const bool pop) noexcept { reserved[0] = pop; }
[[nodiscard]] bool scheduledPop() const noexcept { return reserved[0]; }
@@ -23,6 +26,12 @@ public:
schedulePop(true);
Success();
}
#ifndef __CARLBEKS_DEBUG__
Task& every(QWORD tick);
Task& after(QWORD tick);
Task& until(QWORD tick);
Task& forever();
#endif
};
class TaskScheduler {
@@ -34,7 +43,7 @@ public:
task.func(task);
if (task.scheduledPop()) {
task.schedulePop(false);
tasks.pop(&task);
tasks.pop(&task); // pop后删除了内存,迭代器的current失效
}
}
}
-15
View File
@@ -5,18 +5,3 @@
#pragma once
inline void test() {}
inline void rsa() {
int pk, sk;
int p = 0, q = 0; // = random prime;
int n = p * q;
int phi = (p - 1) * (q - 1);
int d = 0, e = 0;
// assert gcd(e, phi) == 1;
// assert d * e === 1 mod phi;
// encode:
int message = 0, package;
package = static_cast<int>(pow(message, e)) % n;
// decode:
message = static_cast<int>(pow(package, d)) % n;
}
+41 -37
View File
@@ -9,14 +9,14 @@
#include "InteractManager.h"
int Window::pop() noexcept {
game.gc.submit(this);
gc.submit(this);
Success();
}
void Window::render() const noexcept { for (const ObjectHolder<Widget>& widget : widgets) widget->render(); }
void Window::tick() noexcept { for (ObjectHolder<Widget>& widget : widgets) widget->tick(); }
void Window::onResize() { for (ObjectHolder<Widget>& widget : widgets) widget->onResize(); }
void Window::passEvent(const MouseActionCode action, const MouseButtonCode value, const int x, const int y) noexcept { for (ObjectHolder<Widget>& widget : widgets) widget->passEvent(action, value, x, y); }
void Window::render() const noexcept { for (const Widget* widget : widgets) widget->render(); }
void Window::tick() noexcept { for (Widget* widget : widgets) widget->tick(); }
void Window::onResize() { for (Widget* widget : widgets) widget->onResize(); }
void Window::passEvent(const MouseActionCode action, const MouseButtonCode value, const int x, const int y) noexcept { for (Widget* widget : widgets) widget->passEvent(action, value, x, y); }
int WindowManager::pop(Window* value) noexcept {
if (value->list != static_cast<AnywhereEditableList*>(this)) {
@@ -40,19 +40,20 @@ void WindowManager::clear() noexcept {
}
CaptionWindow::CaptionWindow() {
ObjectHolder<Widget>& close = widgets.emplace_back(Button(0, 0, interactSettings.actual.captionHeight, interactSettings.actual.captionHeight, Location::RIGHT_TOP, LiteralText(L"\\f\2\u2716")));
Widget* close = widgets.emplace_back(Button(0, 0, interactSettings.actual.captionHeight, interactSettings.actual.captionHeight, Location::RIGHT_TOP, LiteralText(L"\\f\1\u2716")));
close->mouseClick = [](Widget&, MouseButtonCode) { DestroyWindow(MainWindowHandle); };
close->onTick = [this](const Widget& self, MouseButtonCode) { if (self.containsMouse()) game.getFloatWindow().push(L"\\#ffee0000关闭窗口"_renderable); };
close->absolute();
close->backgroundColor.hover = 0xffee0000;
close->backgroundColor.active = 0;
close->backgroundColor.inactive = 0xffaaaaaa;
close->backgroundColor.clicked = 0xffee8888;
close->mouseDown = [](int) { DestroyWindow(MainWindowHandle); };
close->onTick = [&close, this](int) { if (close->containsMouse()) game.getFloatWindow().push(L"\\#ffee0000关闭窗口"_renderable); };
close->foregroundColor.hover = 0xff000000;
close->foregroundColor.active = 0xff000000;
close->foregroundColor.inactive = 0xff000000;
close->foregroundColor.clicked = 0xff000000;
ObjectHolder<Widget>& minmax = widgets.emplace_back(Button(-interactSettings.actual.captionHeight, 0, interactSettings.actual.captionHeight, interactSettings.actual.captionHeight, Location::RIGHT_TOP, LiteralText(L"\\f\2🗖")));
Widget* minmax = widgets.emplace_back(Button(-interactSettings.actual.captionHeight, 0, interactSettings.actual.captionHeight, interactSettings.actual.captionHeight, Location::RIGHT_TOP, LiteralText(L"\\f\1🗖")));
minmax->absolute();
minmax->backgroundColor.hover = 0xffcccccc;
minmax->backgroundColor.active = 0;
@@ -62,7 +63,9 @@ CaptionWindow::CaptionWindow() {
minmax->foregroundColor.active = 0xff000000;
minmax->foregroundColor.inactive = 0xff000000;
minmax->foregroundColor.clicked = 0xff000000;
ObjectHolder<Widget>& hide = widgets.emplace_back(Button(-2 * interactSettings.actual.captionHeight, 0, interactSettings.actual.captionHeight, interactSettings.actual.captionHeight, Location::RIGHT_TOP, LiteralText(L"🗕")));
Widget* hide = widgets.emplace_back(Button(-2 * interactSettings.actual.captionHeight, 0, interactSettings.actual.captionHeight, interactSettings.actual.captionHeight, Location::RIGHT_TOP, LiteralText(L"\\f\1🗕")));
hide->mouseClick = [](Widget&, MouseButtonCode) { ShowWindow(MainWindowHandle, SW_MINIMIZE); };
hide->absolute();
hide->backgroundColor.hover = 0xffcccccc;
hide->backgroundColor.active = 0;
@@ -72,7 +75,15 @@ CaptionWindow::CaptionWindow() {
hide->foregroundColor.active = 0xff000000;
hide->foregroundColor.inactive = 0xff000000;
hide->foregroundColor.clicked = 0xff000000;
ObjectHolder<Widget>& options = widgets.emplace_back(Button(0, 0, interactSettings.actual.captionHeight, interactSettings.actual.captionHeight, Location::LEFT_TOP, LiteralText(L"\\f\2")));
Widget* options = widgets.emplace_back(Button(0, 0, interactSettings.actual.captionHeight, interactSettings.actual.captionHeight, Location::LEFT_TOP, LiteralText(L"\\f\1")));
options->onTick = [](const Widget& self, MouseButtonCode) {
if (self.containsMouse()) {
game.getFloatWindow().push(L"\\#ff4488aa设置"_renderable);
game.getFloatWindow().push(L"\\.ff4488aa\\#ff000000右键以刷新窗口绘制"_renderable);
}
};
options->mouseClick = [](Widget&, const MouseButtonCode code) { if (static_cast<int>(MouseButtonCodeEnum::MBC_R_DOWN) & code) { game.tasks.pushThis(renderer.resizeReloadBitmap); } };
options->absolute();
options->backgroundColor.hover = 0xffcccccc;
options->backgroundColor.active = 0;
@@ -82,13 +93,6 @@ CaptionWindow::CaptionWindow() {
options->foregroundColor.active = 0xff000000;
options->foregroundColor.inactive = 0xff000000;
options->foregroundColor.clicked = 0xff000000;
options->onTick = [options](int) {
if (options->containsMouse()) {
game.getFloatWindow().push(L"\\#ff4488aa设置"_renderable);
game.getFloatWindow().push(L"\\#ff4488aa右键以刷新窗口绘制"_renderable);
}
};
options->mouseDown = [](int code) { if (static_cast<int>(MouseButtonCodeEnum::MBC_R_DOWN) & code) { game.tasks.pushThis(renderer.resizeReloadBitmap); } };
}
bool CaptionWindow::onOpen() { throw InvalidOperationException(L"Should not open CaptionWindow"); }
@@ -96,12 +100,12 @@ void CaptionWindow::onClose() { throw InvalidOperationException(L"Should not clo
void CaptionWindow::render() const noexcept {
renderer.fill(0, 0, renderer.getWidth(), interactSettings.actual.captionHeight, 0xff666666);
for (const ObjectHolder<Widget>& widget : widgets) widget->render();
for (const Widget* widget : widgets) widget->render();
}
void CaptionWindow::onResize() {
int left = 0, right = 0;
for (ObjectHolder<Widget>& widget : widgets) {
for (Widget* widget : widgets) {
widget->w = interactSettings.actual.captionHeight;
widget->h = interactSettings.actual.captionHeight;
switch (widget->location) {
@@ -132,7 +136,7 @@ void FloatWindow::render() const noexcept {
x = interactManager.getMouseX();
y = interactManager.getMouseY();
int height = 0, width = 0;
for (const ObjectHolder<RenderableString>& str : strings.get()) {
for (const RenderableString* str : strings.get()) {
height += str->getHeight();
if (str->getWidth() > width) width = str->getWidth();
}
@@ -147,8 +151,8 @@ void FloatWindow::render() const noexcept {
const int xf = x + interactSettings.actual.floatWindowMargin;
int yf = y + interactSettings.actual.floatWindowMargin;
for (const ObjectHolder<RenderableString>& str : strings.get()) {
fontManager.get(1).draw(*str, xf, yf);
for (const RenderableString* str : strings.get()) {
fontManager.getDefault().draw(*str, xf, yf);
yf += str->getHeight();
}
@@ -159,7 +163,7 @@ void FloatWindow::render() const noexcept {
unsigned int Widget::colorSelector(const Color& clr) const {
if (!isActive) return clr.inactive;
if (!hasMouse) return clr.active;
if (interactManager.getKey(VK_LBUTTON).isPressed() || interactManager.getKey(VK_RBUTTON).isPressed() || interactManager.getKey(VK_MBUTTON).isPressed()) return clr.clicked;
if (hasMouseTrigger && (interactManager.getKey(VK_LBUTTON).isPressed() || interactManager.getKey(VK_RBUTTON).isPressed() || interactManager.getKey(VK_MBUTTON).isPressed())) return clr.clicked;
return clr.hover;
}
@@ -208,24 +212,24 @@ void Widget::onResize() {
break;
}
} else {
width = renderer.getWidth() * w;
height = renderer.getHeight() * h;
width = static_cast<int>(renderer.getWidth() * w);
height = static_cast<int>(renderer.getHeight() * h);
switch (location) {
case Location::LEFT_TOP:
left = renderer.getWidth() * x;
top = renderer.getHeight() * y;
left = static_cast<int>(renderer.getWidth() * x);
top = static_cast<int>(renderer.getHeight() * y);
break;
case Location::LEFT:
left = renderer.getWidth() * x;
left = static_cast<int>(renderer.getWidth() * x);
top = static_cast<int>(renderer.getHeight() * y) + (renderer.getHeight() - height >> 1);
break;
case Location::LEFT_BOTTOM:
left = renderer.getWidth() * x;
left = static_cast<int>(renderer.getWidth() * x);
top = static_cast<int>(renderer.getHeight() * y) + renderer.getHeight() - height;
break;
case Location::TOP:
left = static_cast<int>(renderer.getWidth() * x) + (renderer.getWidth() - width >> 1);
top = renderer.getHeight() * y;
top = static_cast<int>(renderer.getHeight() * y);
break;
case Location::CENTER:
left = static_cast<int>(renderer.getWidth() * x) + (renderer.getWidth() - width >> 1);
@@ -237,7 +241,7 @@ void Widget::onResize() {
break;
case Location::RIGHT_TOP:
left = static_cast<int>(renderer.getWidth() * x) + renderer.getWidth() - width;
top = renderer.getHeight() * y;
top = static_cast<int>(renderer.getHeight() * y);
break;
case Location::RIGHT:
left = static_cast<int>(renderer.getWidth() * x) + renderer.getWidth() - width;
@@ -277,8 +281,8 @@ ConfirmWindow& ConfirmWindow::requireConfirm(const Function<void(Button&)>& func
confirm->w = 0.5;
confirm->x = 0;
}
confirm->onTick = [this](int) { if (confirm->containsMouse()) confirm->backgroundColor.hover = confirm->animation.adaptsColor(0x99008800, 0x9900ff00); };
confirm->mouseLeave = [this](int) { confirm->animation.reset(); };
confirm->onTick = [](Widget& confirm, MouseButtonCode) { if (confirm.containsMouse()) confirm.backgroundColor.hover = static_cast<Button&>(confirm).animation.adaptsColor(0x99008800, 0x9900ff00); };
confirm->mouseLeave = [](Widget& confirm, MouseButtonCode) { static_cast<Button&>(confirm).animation.reset(); };
if (func) func(*confirm);
confirm->onResize();
return *this;
@@ -286,7 +290,7 @@ ConfirmWindow& ConfirmWindow::requireConfirm(const Function<void(Button&)>& func
ConfirmWindow& ConfirmWindow::requireCancel(const Function<void(Button&)>& func) {
cancel = dynamic_cast<Button*>(widgets.emplace_back(std::move(Button(0, 0.1, 0.4, 0.08, Location::CENTER, LiteralText(L"Cancel")))).ptr());
cancel->mouseUp = [this](int) {
cancel->mouseClick = [this](Widget&, MouseButtonCode) {
game.tasks.pushNewed(allocatedFor(new Task([this](Task& self) {
if (game.closeWindow(this)) this->onClose();
self.pop();
@@ -311,8 +315,8 @@ ConfirmWindow& ConfirmWindow::requireCancel(const Function<void(Button&)>& func)
cancel->x = 0.125;
cancel->w = 0.5;
}
cancel->onTick = [this](int) { if (cancel->containsMouse()) cancel->backgroundColor.hover = cancel->animation.adaptsColor(0x99880000, 0x99ff0000); };
cancel->mouseLeave = [this](int) { cancel->animation.reset(); };
cancel->onTick = [](Widget& cancel, MouseButtonCode) { if (cancel.containsMouse()) cancel.backgroundColor.hover = static_cast<Button&>(cancel).animation.adaptsColor(0x99880000, 0x99ff0000); };
cancel->mouseLeave = [](Widget& cancel, int) { static_cast<Button&>(cancel).animation.reset(); };
if (func) func(*cancel);
cancel->onResize();
return *this;
+38 -25
View File
@@ -12,7 +12,7 @@
class WindowManager;
enum class MouseActionCode : int {
enum class MouseActionCode : unsigned int {
MAC_MOVE = 0,
MAC_HOVER = 1,
MAC_DOWN = 2,
@@ -21,7 +21,7 @@ enum class MouseActionCode : int {
MAC_LEAVE = 5
};
enum class MouseButtonCodeEnum : int {
enum class MouseButtonCodeEnum : unsigned int {
MBC_L_DOWN = 0x1,
MBC_R_DOWN = 0x2,
MBC_M_DOWN = 0x4,
@@ -33,20 +33,20 @@ enum class MouseButtonCodeEnum : int {
/**
* @see MouseButtonCodeEnum
*/
using MouseButtonCode = int;
using MouseButtonCode = unsigned int;
class Widget : public IRenderable, public ITickable {
protected:
int left = 0, top = 0, width = 0, height = 0;
public:
using Action = Function<void(int)>;
using Action = Function<void(Widget&, MouseButtonCode)>;
double x, y, w, h;
Action mouseHover; // 传入int为:0,鼠标移动;其余,鼠标在其上的长时间悬浮
Action mouseDown; // 传入int表示变更按键。0左, 1中, 2右
Action mouseUp; // 传入int表示变更按键。0左, 1中, 2右
Action mouseLeave; // 传入int忽略
Action mouseClick; // 传入int表示变更按键。0x0左, 0x1中, 0x2右;0xf表示是否双击
Action mouseClick; // 传入int表示变更按键。0x0左, 0x1中, 0x2右;0x8表示是否双击
Action onTick; // 传入int忽略
Color backgroundColor;
Color foregroundColor{ TextColor };
@@ -54,6 +54,7 @@ public:
protected:
mutable bool hasMouse = false;
mutable bool isActive = true;
mutable bool hasMouseTrigger = false;
bool isAbsoluteLocation = false;
public:
@@ -61,10 +62,10 @@ public:
Location textLocation = Location::CENTER; // 多余字节预声明备用
protected:
char unused[3]{};
char unused[2]{};
public:
explicit Widget(const double x, const double y, const double w, const double h, const Location location) : x(x), y(y), w(w), h(h), location(location) {}
Widget(const double x, const double y, const double w, const double h, const Location location) : x(x), y(y), w(w), h(h), location(location) {}
unsigned int colorSelector(const Color& clr) const;
void render() const noexcept override;
@@ -95,12 +96,25 @@ public:
}
virtual void onResize();
virtual void onHover(const int value) noexcept { if (mouseHover) mouseHover(value); }
virtual void onMouseDown(const MouseButtonCode code) noexcept { if (mouseDown) mouseDown(code); }
virtual void onMouseUp(const MouseButtonCode code) noexcept { if (mouseUp) mouseUp(code); }
virtual void onMouseLeave(const int value) noexcept { if (mouseLeave) mouseLeave(value); }
virtual void onMouseClick(const int value) noexcept { if (mouseClick) mouseClick(value); }
void tick() noexcept override { if (onTick) onTick(0); }
virtual void onHover(const int value) noexcept { if (mouseHover) mouseHover(*this, value); }
virtual void onMouseDown(const MouseButtonCode code) noexcept {
hasMouseTrigger = true;
if (mouseDown) mouseDown(*this, code);
}
virtual void onMouseUp(const MouseButtonCode code) noexcept {
if (mouseUp) mouseUp(*this, code);
if (hasMouseTrigger) onMouseClick(code);
}
virtual void onMouseLeave(const MouseButtonCode value) noexcept {
hasMouseTrigger = false;
if (mouseLeave) mouseLeave(*this, value);
}
virtual void onMouseClick(const MouseButtonCode value) noexcept { if (mouseClick) mouseClick(*this, value); }
void tick() noexcept override { if (onTick) onTick(*this, 0); }
virtual void passEvent(const MouseActionCode action, const MouseButtonCode value, const int x, const int y) noexcept {
if (action == MouseActionCode::MAC_LEAVE || !isMouseIn(x, y)) {
@@ -123,7 +137,7 @@ public:
onMouseUp(value);
break;
case MouseActionCode::MAC_DOUBLE:
onMouseClick(1);
onMouseClick(0x80);
break;
default:
break;
@@ -139,7 +153,7 @@ protected:
Window() = default;
~Window() override {}
~Window() override = default;
public:
int pop() noexcept override;
@@ -164,7 +178,7 @@ public:
class WindowManager final : public AnywhereEditableList<Window, WindowManager>, public IRenderable, public ITickable {
public:
void render() const noexcept override { for (Window& i : *this) i.render(); }
void render() const noexcept override { for (const Window& i : *this) i.render(); }
void tick() noexcept override { for (Window& i : *this) i.tick(); }
int pop(Window* value) noexcept override;
void clear() noexcept;
@@ -173,7 +187,7 @@ public:
class CaptionWindow final : public Window {
public:
explicit CaptionWindow();
CaptionWindow();
bool onOpen() override;
void onClose() override;
void render() const noexcept override;
@@ -184,10 +198,10 @@ class FloatWindow final : public Window {
mutable int x = 0; // 标记渲染起始点
mutable int y = 0; // 标记渲染起始点
typedef List<ObjectHolder<RenderableString>> lt;
SynchronizedHolder<lt> strings{};
SynchronizedHolder<lt> strings;
public:
explicit FloatWindow() : Window() {
FloatWindow() : Window() {
strings.setNew<lt>(std::move(lt()));
strings.ok();
strings.async();
@@ -208,8 +222,8 @@ class Button : public Widget {
public:
ObjectHolder<IText> name;
Animation animation = Animation().features(Animation::AS_CUBIC).setDuration(20);
explicit Button(const double x, const double y, const double w, const double h, const Location location, const ObjectHolder<IText>& text) : Widget(x, y, w, h, location), name(text) {}
explicit Button(const double x, const double y, const double w, const double h, const Location location, ObjectHolder<IText>&& text) : Widget(x, y, w, h, location), name(std::move(text)) {}
Button(const double x, const double y, const double w, const double h, const Location location, const ObjectHolder<IText>& text) : Widget(x, y, w, h, location), name(text) {}
Button(const double x, const double y, const double w, const double h, const Location location, ObjectHolder<IText>&& text) : Widget(x, y, w, h, location), name(std::move(text)) {}
void render() const noexcept override;
};
@@ -222,12 +236,11 @@ public:
*cancel = nullptr;
private:
explicit ConfirmWindow(const ObjectHolder<IText>& text) : Window(), text(text) {}
explicit ConfirmWindow(ObjectHolder<IText>&& text) : Window(), text(std::move(text)) {}
ConfirmWindow(const ObjectHolder<IText>& text) : Window(), text(text) {}
ConfirmWindow(ObjectHolder<IText>&& text) : Window(), text(std::move(text)) {}
public:
~ConfirmWindow() override { /* 不需要delete,析构时Window会自动delete */
}
~ConfirmWindow() override = default; // 不需要delete,析构时Window会自动delete
void render() const noexcept override {
int w, h;
+4 -2
View File
@@ -6,6 +6,7 @@
#include "Chars.h"
#include "exception.h"
#include "Game.h"
template<TypeName Base> template<NewCopyable T> requires std::is_base_of_v<Base, T> && TypeName<T>
void ObjectHolder<Base>::set(const T& value) {
@@ -26,8 +27,9 @@ void ObjectHolder<Base>::set(T&& value) {
}
void requireNonnull(const void* value) noexcept(false) { if (!value) throw NullPointerException(L"value is null"); }
void checkAllocation(const void* value) noexcept(false) { if (!value) throw BadAllocationException(L"bad allocation"); }
void printAllocate(void* value, size_t size, const String& msg) {
void printAllocate(void* value, const size_t size, const String& msg) {
const String str = L"alloc " + ptrtow(reinterpret_cast<QWORD>(value)) + L" " + std::to_wstring(size) + String(L"B ") + msg;
Logger.log(str);
#if __CARLBEKS_MEMORY__ > 2
@@ -35,7 +37,7 @@ void printAllocate(void* value, size_t size, const String& msg) {
#endif
}
void printDeallocate(void* value, size_t size, const String& msg) {
void printDeallocate(void* value, const size_t size, const String& msg) {
const String str = L"dealloc " + ptrtow(reinterpret_cast<QWORD>(value)) + L" " + std::to_wstring(size) + String(L"B ") + msg;
Logger.log(str);
#if __CARLBEKS_MEMORY__ > 2
+23 -17
View File
@@ -18,7 +18,7 @@
#include <atomic>
#include <thread>
#include <fstream>
#include <math.h>
#include <cmath>
using wchar = wchar_t;
using QWORD = unsigned long long int;
@@ -31,7 +31,10 @@ template<typename F> using Function = std::function<F>;
#define Success() { return 0; }
#define Failed() { return 1; }
#define Error() { return -1; }
#define Comment(PARAMS) /##/ PARAMS
#define SameAs(PARAMS) Comment(PARAMS)
//NOLINTNEXTLINE(*-reserved-identifier)
#define _WINSOCKAPI_ /* 防止winsock.h被引入。winsock.h和winsock2.h冲突。 */
#if false
#include <WinSock2.h>
@@ -45,7 +48,6 @@ template<typename F> using Function = std::function<F>;
#include <wingdi.h>
#include <WinUser.h>
#include <Uxtheme.h>
#include <iostream>
#include <dwmapi.h>
#define WM_APP_LBUTTONUP (WM_APP + 1)
@@ -76,18 +78,19 @@ concept PointerType = std::is_pointer_v<T>;
template<typename T>
concept TypeName = NonreferenceType<T> && NonpointerType<T>;
inline std::wfstream& MainLogFile = *new std::wfstream(L"log.txt", std::ios::out | std::ios::trunc);
struct MemoryManager {
struct MemoryInfo {
std::size_t size;
const String msg;
std::size_t size;
};
Map<void*, MemoryInfo> allocated;
Map<void*, MemoryInfo> allocated {};
constexpr MemoryManager() noexcept = default;
} inline memoryManager;
void requireNonnull(const void* value) noexcept(false);
void checkAllocation(const void* value) noexcept(false);
inline String ptrtow(QWORD value);
#if defined __CARLBEKS_DEBUG__ || defined __CARLBEKS_MEMORY__
@@ -95,16 +98,16 @@ void printAllocate(void* value, std::size_t size, const String&);
void printDeallocate(void* value, std::size_t size, const String&);
extern String atow(const char* chars);
template<typename T> T* _allocatedFor(T* value, const String& msg = L"", std::size_t size = sizeof(T)) {
template<typename T> T* allocatedFor$(T* value, const String& msg = L"", std::size_t size = sizeof(T)) {
requireNonnull(value);
const auto& k = memoryManager.allocated.emplace(value, MemoryManager::MemoryInfo{ size, L"[" + atow(typeid(T).name()) + L"] " + msg }).first;
const auto& k = memoryManager.allocated.emplace(value, MemoryManager::MemoryInfo{ L"[" + atow(typeid(T).name()) + L"] " + msg , size}).first;
#if __CARLBEKS_MEMORY__ > 1
printAllocate(value, k->second.size, k->second.msg);
#endif
return value;
}
template<typename T> T* _deallocating(T* value) {
template<typename T> T* deallocating$(T* value) {
#if __CARLBEKS_MEMORY__ > 1
const MemoryManager::MemoryInfo* info = nullptr;
if (memoryManager.allocated.contains(value)) info = &memoryManager.allocated.at(value);
@@ -115,11 +118,11 @@ template<typename T> T* _deallocating(T* value) {
}
#if __CARLBEKS_MEMORY__ > 3
#define allocatedFor(val, ...) _allocatedFor(val, L"\n From " __FUNCSIG__ "\n At " __FILE__ ":" _STL_STRINGIZE(__LINE__) __VA_OPT__(,) __VA_ARGS__)
#define allocatedFor(val, ...) allocatedFor$(val, L"\n From " __FUNCSIG__ "\n At " __FILE__ ":" _STL_STRINGIZE(__LINE__) __VA_OPT__(,) __VA_ARGS__)
#else
#define allocatedFor(val, ...) _allocatedFor(val, L"" __VA_OPT__(,) __VA_ARGS__)
#define allocatedFor(val, ...) allocatedFor$(val, L"" __VA_OPT__(,) __VA_ARGS__)
#endif
#define deallocating(val) _deallocating(val)
#define deallocating(val) deallocating$(val)
#else
#define allocatedFor(val, ...) val
#define deallocating(val) val
@@ -137,14 +140,11 @@ public:
*/
ObjectHolder() : value(nullptr), hasValue(false) {}
// ReSharper disable once CppNonExplicitConvertingConstructor
ObjectHolder(Base* value) : value(value), hasValue(false) {}
// ReSharper disable once CppNonExplicitConvertingConstructor
template<NewCopyable T> requires (std::is_base_of_v<Base, T> || std::is_same_v<Base, T>) && TypeName<T>
ObjectHolder(const T& value) : value(allocatedFor(new T(value))), hasValue(true) {}
// ReSharper disable once CppNonExplicitConvertingConstructor
template<NewMoveable T> requires (std::is_base_of_v<Base, T> || std::is_same_v<Base, T>) && TypeName<T>
ObjectHolder(T&& value) : value(allocatedFor(new T(std::forward<T>(value)))), hasValue(true) {}
@@ -196,11 +196,17 @@ public:
return *value;
}
// ReSharper disable once CppNonExplicitConversionOperator
[[nodiscard]] operator Base*() const noexcept(false) { return value; }
Base* ptr() const noexcept { return value; }
operator bool() const noexcept { return value; }
bool operator!() const noexcept { return value == nullptr; }
bool isManager() const noexcept { return hasValue; }
[[nodiscard]] bool isManager() const noexcept { return hasValue; }
template<typename T> ObjectHolder<T> referenceof(const T& other) {
ObjectHolder ret{};
ret.value = &other;
return ret;
}
};
template<TypeName Base> class SynchronizedHolder {
+17 -9
View File
@@ -23,31 +23,39 @@ 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) {}
NullPointerException(String&& msg) : Exception(std::move(msg), &type) {}
NullPointerException(const String& msg) : Exception(msg, &type) {}
};
class BadAllocationException final : public Exception {
inline static const String type = L"BadAllocationException";
public:
BadAllocationException(String&& msg) : Exception(std::move(msg), &type) {}
BadAllocationException(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) {}
ArrayIndexOutOfBoundException(String&& msg) : Exception(std::move(msg), &type) {}
ArrayIndexOutOfBoundException(const String& msg) : Exception(msg, &type) {}
};
class InvalidOperationException final : public Exception {
inline static const String type = L"InvalidOperationException";
public:
explicit InvalidOperationException(String&& msg) : Exception(std::move(msg), &type) {}
explicit InvalidOperationException(const String& msg) : Exception(msg, &type) {}
InvalidOperationException(String&& msg) : Exception(std::move(msg), &type) {}
InvalidOperationException(const String& msg) : Exception(msg, &type) {}
};
class RuntimeException final : public Exception {
inline static const String type = L"RuntimeException";
public:
explicit RuntimeException(String&& msg) : Exception(std::move(msg), &type) {}
explicit RuntimeException(const String& msg) : Exception(msg, &type) {}
RuntimeException(String&& msg) : Exception(std::move(msg), &type) {}
RuntimeException(const String& msg) : Exception(msg, &type) {}
};
@@ -68,7 +76,7 @@ class PublicLogger final {
public:
const String name;
explicit PublicLogger(const String& name): name(L" [" + name + L"] ") { std::wcout << L"PublicLogger created\n"; }
PublicLogger(const String& name): name(L" [" + name + L"] ") { std::wcout << L"PublicLogger created\n"; }
PublicLogger& put(const String& msg) noexcept {
std::wcout << L"[] [Root]" + name + msg + L"\n";
+18 -10
View File
@@ -4,7 +4,9 @@
#pragma once
#include "warnings.h"
#include "def.h"
#include "File.h"
struct IGarbage;
template <typename T>
@@ -18,7 +20,7 @@ private:
protected:
void* ptr;
explicit IGarbage(void* ptr) : ptr(ptr) {}
IGarbage(void* ptr) : ptr(ptr) {}
virtual ~IGarbage() = default;
virtual void collect() = 0;
virtual void deleteThis() = 0;
@@ -29,7 +31,7 @@ class Garbage final : public IGarbage {
friend class GarbageCollector;
public:
explicit Garbage(T* ptr) : IGarbage(ptr) {}
Garbage(T* ptr) : IGarbage(ptr) {}
void collect() override { delete static_cast<T*>(deallocating(ptr)); }
protected:
@@ -44,14 +46,14 @@ class GarbageCollector {
IGarbage* processing = nullptr;
public:
GarbageCollector() = default;
GarbageCollector() { MainLogFile << L"initialize GarbageCollector" << std::endl; }
GarbageCollector(const GarbageCollector&) = delete;
GarbageCollector(GarbageCollector&&) = delete;
GarbageCollector& operator=(const GarbageCollector&) = delete;
GarbageCollector& operator=(GarbageCollector&&) = delete;
~GarbageCollector() {
IGarbage* iter = processing;
IGarbage* iter;
while (processing) {
iter = processing->next;
processing->collect();
@@ -76,17 +78,21 @@ public:
/** 只能在gameThread调用 */
template <TypeName T>
void submit(T* ptr) noexcept(false) {
IGarbage* garbage = allocatedFor(new Garbage<T>(ptr));
IGarbage* newedGarbage = allocatedFor(new Garbage<T>(ptr));
builtinSubmit(newedGarbage);
}
void builtinSubmit(IGarbage* const newedGarbage) noexcept(false) {
if (IGarbage* end = submittedEnd) { // 后续添加,可能存在线程竞争
while (end->next) end = end->next; // 理论上不会进入循环,但防止万一
end->next = garbage;
if (submitted) submittedEnd = garbage; // 参考pack()submitted会被先置空
end->next = newedGarbage;
if (submitted) submittedEnd = newedGarbage; // 参考pack()submitted会被先置空
std::atomic_thread_fence(std::memory_order_acquire);
if (!submitted) submittedEnd = nullptr; // 防止submittedEnd = garbage在pack()中置空后进行。此函数是同步的,所以可以这样操作。
}
else { // 添加首个,一定不会有线程竞争;或先前的已经pack
submitted = garbage;
submittedEnd = garbage;
submitted = newedGarbage;
submittedEnd = newedGarbage;
}
}
@@ -115,7 +121,7 @@ public:
/** 只能在gameThread调用 */
void collect() {
IGarbage* next = processing;
IGarbage* next;
while (processing) {
next = processing->next;
processing->next = nullptr;
@@ -140,3 +146,5 @@ public:
}
}
};
inline GarbageCollector& [[carlbeks::releasedat("main.cpp")]] gc = *new GarbageCollector();
+2 -2
View File
@@ -12,14 +12,14 @@ inline BOOL NewProcess(const String& cmdline) noexcept {
return CreateProcessW(nullptr, const_cast<wchar*>(cmdline.c_str()), nullptr, nullptr, 0, 0, nullptr, nullptr, &si, &pi);
}
inline HRESULT RemoveDefaultCaption(HWND hWnd, const MARGINS* p) noexcept { return DwmExtendFrameIntoClientArea(hWnd, p); }
inline HRESULT RemoveDefaultCaption(const HWND hWnd, const MARGINS* p) noexcept { return DwmExtendFrameIntoClientArea(hWnd, p); }
inline bool ShowConsoleIO() noexcept {
AllocConsole();
FILE* pCout;
freopen_s(&pCout, "CONOUT$", "w", stdout);
FILE* pCin;
freopen_s(&pCin, "CONIN$", "r", stdin);
freopen_s(&pCin, "CONOUT$", "r+", stdin);
return true;
}
+4 -2
View File
@@ -4,15 +4,17 @@
#pragma once
#include "warnings.h"
#include "def.h"
#include "File.h"
#include "exception.h"
#include "gc.h"
#include "utils.h"
#include "hbp.h"
#include "Chars.h"
#include "gc.h"
#include "Task.h"
#include "File.h"
#include "Renderer.h"
#include "Animation.h"
#include "InteractManager.h"
+53 -46
View File
@@ -3,7 +3,7 @@
#include "IText.h"
#include "TestCode.h"
LRESULT __stdcall WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
LRESULT __stdcall WndProc(const HWND hwnd, const UINT uMsg, const WPARAM wParam, const LPARAM lParam) {
switch (uMsg) {
[[likely]]
case WM_PAINT: {
@@ -68,7 +68,7 @@ LRESULT __stdcall WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
default:
break;
}
renderer.windowSize = wParam;
renderer.windowSize = static_cast<byte>(wParam);
break;
case WM_KEYDOWN:
interactManager.update(static_cast<int>(wParam), true);
@@ -86,40 +86,40 @@ LRESULT __stdcall WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
case WM_NCLBUTTONDOWN:
if (interactManager.isInClientCaption()) {
interactManager.update(VK_LBUTTON, true);
game.passEvent(MouseActionCode::MAC_DOWN, interactManager.getMouseButtonCode() | static_cast<int>(MouseButtonCodeEnum::MBC_L_CHANGE), interactManager.getMouseX(), interactManager.getMouseY());
game.passEvent(MouseActionCode::MAC_DOWN, interactManager.getMouseButtonCode() | static_cast<unsigned int>(MouseButtonCodeEnum::MBC_L_CHANGE), interactManager.getMouseX(), interactManager.getMouseY());
}
break;
case WM_RBUTTONDOWN:
case WM_NCRBUTTONDOWN:
if (interactManager.isInClientCaption()) {
interactManager.update(VK_RBUTTON, true);
game.passEvent(MouseActionCode::MAC_DOWN, interactManager.getMouseButtonCode() | static_cast<int>(MouseButtonCodeEnum::MBC_R_CHANGE), interactManager.getMouseX(), interactManager.getMouseY());
game.passEvent(MouseActionCode::MAC_DOWN, interactManager.getMouseButtonCode() | static_cast<unsigned int>(MouseButtonCodeEnum::MBC_R_CHANGE), interactManager.getMouseX(), interactManager.getMouseY());
}
break;
case WM_APP_LBUTTONUP: // case WM_LBUTTONUP: case WM_NCLBUTTONUP:
case WM_APP_LBUTTONUP:
if (interactManager.isInClientCaption()) {
interactManager.update(VK_LBUTTON, false);
game.passEvent(MouseActionCode::MAC_UP, interactManager.getMouseButtonCode() | static_cast<int>(MouseButtonCodeEnum::MBC_L_CHANGE), interactManager.getMouseX(), interactManager.getMouseY());
game.passEvent(MouseActionCode::MAC_UP, interactManager.getMouseButtonCode() | static_cast<unsigned int>(MouseButtonCodeEnum::MBC_L_CHANGE), interactManager.getMouseX(), interactManager.getMouseY());
}
break;
case WM_RBUTTONUP:
case WM_NCRBUTTONUP:
if (interactManager.isInClientCaption()) {
interactManager.update(VK_RBUTTON, false);
game.passEvent(MouseActionCode::MAC_UP, interactManager.getMouseButtonCode() | static_cast<int>(MouseButtonCodeEnum::MBC_R_CHANGE), interactManager.getMouseX(), interactManager.getMouseY());
game.passEvent(MouseActionCode::MAC_UP, interactManager.getMouseButtonCode() | static_cast<unsigned int>(MouseButtonCodeEnum::MBC_R_CHANGE), interactManager.getMouseX(), interactManager.getMouseY());
}
break;
case WM_APP_MBUTTONDOWN: // case WM_MBUTTONDOWN: case WM_NCMBUTTONDOWN:
case WM_APP_MBUTTONDOWN:
if (interactManager.isInClientCaption()) {
if (wParam & 0x10) interactManager.update(VK_MBUTTON, true);
game.passEvent(MouseActionCode::MAC_DOWN, interactManager.getMouseButtonCode() | static_cast<int>(MouseButtonCodeEnum::MBC_M_CHANGE), interactManager.getMouseX(), interactManager.getMouseY());
if (static_cast<QWORD>(wParam) & 0x10u) interactManager.update(VK_MBUTTON, true);
game.passEvent(MouseActionCode::MAC_DOWN, interactManager.getMouseButtonCode() | static_cast<unsigned int>(MouseButtonCodeEnum::MBC_M_CHANGE), interactManager.getMouseX(), interactManager.getMouseY());
}
break;
case WM_MBUTTONUP:
case WM_NCMBUTTONUP:
if (interactManager.isInClientCaption()) {
interactManager.update(VK_MBUTTON, false);
game.passEvent(MouseActionCode::MAC_UP, interactManager.getMouseButtonCode() | static_cast<int>(MouseButtonCodeEnum::MBC_M_CHANGE), interactManager.getMouseX(), interactManager.getMouseY());
game.passEvent(MouseActionCode::MAC_UP, interactManager.getMouseButtonCode() | static_cast<unsigned int>(MouseButtonCodeEnum::MBC_M_CHANGE), interactManager.getMouseX(), interactManager.getMouseY());
}
break;
case WM_MOUSEWHEEL:
@@ -138,23 +138,22 @@ LRESULT __stdcall WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
if (!interactManager.isInWindow()) game.passEvent(MouseActionCode::MAC_LEAVE, 0, interactManager.getMouseX(), interactManager.getMouseY());
break;
case WM_DWMCOMPOSITIONCHANGED: {
MARGINS margins{
constexpr MARGINS margins{
.cxLeftWidth = 0,
.cxRightWidth = 0,
.cyTopHeight = 0,
.cyBottomHeight = 0
};
margins = { -1 };
RemoveDefaultCaption(hwnd, &margins);
break;
}
case WM_NCCALCSIZE:
if (wParam == 1) {
NCCALCSIZE_PARAMS* pncsp = reinterpret_cast<NCCALCSIZE_PARAMS*>(lParam);
pncsp->rgrc[0].left = pncsp->rgrc[0].left + 0;
pncsp->rgrc[0].top = pncsp->rgrc[0].top + 0;
pncsp->rgrc[0].right = pncsp->rgrc[0].right - 0;
pncsp->rgrc[0].bottom = pncsp->rgrc[0].bottom - 0;
NCCALCSIZE_PARAMS* params = reinterpret_cast<NCCALCSIZE_PARAMS*>(lParam);
params->rgrc[0].left = params->rgrc[0].left + 0;
params->rgrc[0].top = params->rgrc[0].top + 0;
params->rgrc[0].right = params->rgrc[0].right - 0;
params->rgrc[0].bottom = params->rgrc[0].bottom - 0;
renderer.resizeStart();
return 0;
}
@@ -170,7 +169,7 @@ LRESULT __stdcall WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
return 0;
[[unlikely]]
case WM_CREATE:
SetWindowPos(hwnd, nullptr, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOOWNERZORDER); // Force post NCCALCSIZE
SetWindowPos(hwnd, nullptr, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOOWNERZORDER);
renderer.resizeEnd();
break;
default:
@@ -179,7 +178,7 @@ LRESULT __stdcall WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
return DefWindowProcW(hwnd, uMsg, wParam, lParam);
}
LRESULT __stdcall HookProc(int code, WPARAM wParam, LPARAM lParam) {
LRESULT __stdcall HookProc(const int code, const WPARAM wParam, const LPARAM lParam) {
if (code < 0) {
Logger.log(L"HookProc nCode < 0");
return CallNextHookEx(nullptr, code, wParam, lParam);
@@ -188,10 +187,12 @@ LRESULT __stdcall HookProc(int code, WPARAM wParam, LPARAM lParam) {
case WM_LBUTTONUP:
case WM_NCLBUTTONUP:
PostMessageW(MainWindowHandle, WM_APP_LBUTTONUP, p->wParam, p->lParam);
MainLogFile << L"BUTTON-UP\n";
return 0;
case WM_MBUTTONDOWN:
case WM_NCMBUTTONDOWN:
PostMessageW(MainWindowHandle, WM_APP_MBUTTONDOWN, p->wParam, p->lParam);
MainLogFile << L"BUTTON-DOWN\n";
return 0;
default:
break;
@@ -205,7 +206,7 @@ void gameThread() {
using Time = time_point<system_clock>;
Time lastTick = system_clock::now();
while (isRunning) {
Time thisTime = system_clock::now();
const Time thisTime = system_clock::now();
if (thisTime - lastTick < milliseconds(45)) {
Sleep(1);
continue;
@@ -228,7 +229,7 @@ void renderThread() {
renderer.initialize();
Time lastRender = system_clock::now();
while (isRunning) {
Time thisTime = system_clock::now();
const Time thisTime = system_clock::now();
if (thisTime - lastRender < milliseconds(12)) {
Sleep(1);
continue;
@@ -243,7 +244,8 @@ void renderThread() {
DestroyWindow(MainWindowHandle);
}
int __stdcall wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow) {
int __stdcall wWinMain(const HINSTANCE hInstance, const HINSTANCE, [[maybe_unused]] const LPWSTR lpCmdLine, [[maybe_unused]] const int nShowCmd) {
MainLogFile << L"wWinMain started" << std::endl;
game.setWindow(StartWindow::create()); // 次序提前至最先
for (const auto& [addr, info] : memoryManager.allocated) { Logger.print(L" using", addr, info.size, L"B", info.msg); }
MainLogFile << L"--------Program Start--------" << std::endl;
@@ -257,60 +259,64 @@ int __stdcall wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCm
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(nullptr, IDI_APPLICATION);
wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
wc.hbrBackground = (HBRUSH) GetStockObject(BLACK_BRUSH);
wc.hbrBackground = static_cast<HBRUSH>(GetStockObject(BLACK_BRUSH));
wc.lpszMenuName = L"None";
wc.lpszClassName = ApplicationName.c_str();
if (!RegisterClassExW(&wc)) return FALSE;
if (!SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE)) Logger.print(L"SetProcessDpiAwarenessContext failed. LastError:", GetLastError());
MainInstance = hInstance;
MainWindowHandle = CreateWindowExW(0, wc.lpszClassName, wc.lpszClassName, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, nullptr, nullptr, hInstance, nullptr);
SetWindowLongW(MainWindowHandle, GWL_STYLE, WS_VISIBLE | WS_MAXIMIZEBOX);
MARGINS margins{
SetWindowLongW(MainWindowHandle, GWL_STYLE, WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE);
constexpr MARGINS margins{
.cxLeftWidth = 0,
.cxRightWidth = 0,
.cyTopHeight = 0,
.cyBottomHeight = 0
};
// margins = { -1 };
RemoveDefaultCaption(MainWindowHandle, &margins);
// DWM_BLURBEHIND blur{
// .dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION | DWM_BB_TRANSITIONONMAXIMIZED,
// .fEnable = TRUE,
// .hRgnBlur = CreateRectRgn(0, 0, 400, 400),
// .fTransitionOnMaximized = FALSE
// };
// DwmEnableBlurBehindWindow(MainWindowHandle, &blur);
// DeleteObject(blur.hRgnBlur);
SetWindowLongW(MainWindowHandle, GWL_EXSTYLE, GetWindowLongW(MainWindowHaTndle, GWL_EXSTYLE) | WS_EX_LAYERED);
int a = -40;
game.tasks.pushNewed(new Task([&a](Task& self) {
if (a) {
++a;
SetLayeredWindowAttributes(MainWindowHandle, 0xffffff, static_cast<BYTE>(0xff * (40 + a) / 40), LWA_COLORKEY | LWA_ALPHA);
} else {
SetLayeredWindowAttributes(MainWindowHandle, 0xffffff, 0xff, LWA_COLORKEY | LWA_ALPHA);
self.schedulePop(true);
SetWindowLongW(MainWindowHandle, GWL_EXSTYLE, GetWindowLongW(MainWindowHandle, GWL_EXSTYLE) & ~WS_EX_LAYERED);
}
return 0;
}));
SetWindowLongW(MainWindowHandle, GWL_EXSTYLE, GetWindowLongW(MainWindowHandle, GWL_EXSTYLE) | WS_EX_LAYERED);
SetLayeredWindowAttributes(MainWindowHandle, 0xffffff, 0xe0, LWA_COLORKEY | LWA_ALPHA);
ShowWindow(MainWindowHandle, nCmdShow);
ShowWindow(MainWindowHandle, SW_SHOWMAXIMIZED);
SetConsoleOutputCP(65001);
const HHOOK hook = SetWindowsHookW(WH_GETMESSAGE, HookProc);
const HACCEL hAccelTable = LoadAcceleratorsW(hInstance, MAKEINTRESOURCE(109));
if (!hook) MainLogFile << L"SetWindowsHookW failed. LastError: " << GetLastError() << std::endl;
test();
{
interactManager.initialize();
}
SetConsoleOutputCP(65001);
HHOOK hook = SetWindowsHookW(WH_GETMESSAGE, HookProc);
test();
HACCEL hAccelTable = LoadAcceleratorsW(hInstance, MAKEINTRESOURCE(109));
MSG msg = { nullptr };
GameThread = Thread(gameThread);
RenderThread = Thread(renderThread);
}
MSG msg = { nullptr };
while (GetMessageW(&msg, nullptr, 0, 0)) {
if (!TranslateAcceleratorW(msg.hwnd, hAccelTable, &msg)) {
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
}
{
isRunning = false;
if (GameThread.joinable()) GameThread.join();
if (RenderThread.joinable()) RenderThread.join();
}
DestroyAcceleratorTable(hAccelTable);
UnhookWindowsHookEx(hook);
_wsystem(L"pause");
for (const auto& [addr, info] : memoryManager.allocated) { Logger.print(L"using", addr, info.size, L"B", info.msg); }
MainLogFile << L"-------- Program End --------" << std::endl;
for (const auto& [addr, info] : memoryManager.allocated) { MainLogFile << L" using " << addr << L" " << info.size << L"B " << info.msg << std::endl; }
_wsystem(L"pause");
_wsystem(L"pause");
return static_cast<int>(msg.wParam);
}
@@ -318,9 +324,10 @@ struct Release {
Release() = default;
~Release() {
delete &gc;
MainLogFile << L"--------- Last Check ---------" << std::endl;
for (const auto& [addr, info] : memoryManager.allocated) { MainLogFile << L" using " << addr << L" " << info.size << L"B " << info.msg << std::endl; }
MainLogFile.close();
delete &MainLogFile;
}
} x;
} NEVER_REFERENCED_release;
+15 -6
View File
@@ -1,8 +1,11 @@
//
// Created by EmsiaetKadosh on 25-3-4.
//
#pragma once
#include "gc.h"
template <typename T, typename L = void>
class AnywhereEditable;
template <typename T, typename L = void>
@@ -11,6 +14,7 @@ template <typename T, typename L = void>
class AnywhereIterator;
class AnywhereIteratorEnd;
/**
* 此处无法进行代码编译层面的直接约束
* @tparam T 满足T extends AnywhereEditable<T, L>
@@ -33,9 +37,8 @@ private:
public:
byte reserved[7]{}; // reserved[0]: Task::schedulePop
public:
AnywhereEditable() = default;
AnywhereEditable(const AnywhereEditable& other) {}
AnywhereEditable(const AnywhereEditable&) {}
AnywhereEditable(AnywhereEditable&& other) noexcept : prev(other->prev), next(other->next), list(other->list) {
other->prev = nullptr;
@@ -65,7 +68,7 @@ class AnywhereIterator {
AnywhereEditable<T, L>* current;
public:
explicit AnywhereIterator(AnywhereEditable<T, L>* current) : current(current) {}
AnywhereIterator(AnywhereEditable<T, L>* current) : current(current) {}
AnywhereIterator(const AnywhereIterator& other) = default;
T& operator*() noexcept(false) {
@@ -116,7 +119,7 @@ public:
class AnywhereIteratorEnd {
public:
AnywhereIteratorEnd() {}
AnywhereIteratorEnd() = default;
AnywhereIteratorEnd(const AnywhereIteratorEnd& other) = delete;
AnywhereIteratorEnd(AnywhereIteratorEnd&& other) = delete;
@@ -160,7 +163,13 @@ template <typename T, typename L>
int AnywhereEditable<T, L>::pushThis(AnywhereEditableList<T, L>& list) noexcept { return list.pushThis(static_cast<T*>(this)); }
template <typename T, typename L>
int AnywhereEditable<T, L>::pop() noexcept { return list->pop(static_cast<T*>(this)); }
int AnywhereEditable<T, L>::pop() noexcept {
if (!list) {
Logger.error(L"AnywhereEditable::pop() : list is null");
Failed();
}
return list->pop(static_cast<T*>(this));
}
template <typename T, typename L>
bool AnywhereIterator<T, L>::operator!=(const AnywhereIteratorEnd& other) const noexcept { return other != *this; }
@@ -205,6 +214,6 @@ int AnywhereEditableList<T, L>::pop(T* value) noexcept {
value->list = nullptr;
value->next->prev = value->prev;
value->prev->next = value->next;
if (value->managedByList) delete deallocating(value);
if (value->managedByList) gc.submit(value);
Success();
}
+9
View File
@@ -0,0 +1,9 @@
//
// Created by EmsiaetKadosh on 25-3-13.
//
#pragma once
#pragma warning(disable: 4554)
#pragma warning(default: 4555)
#pragma warning(disable: 5030)
+24 -10
View File
@@ -8,28 +8,42 @@
class StartWindow final : public Window {
TranslatableText title = TranslatableText(L"hbp.title");
StartWindow() {
Button* start = dynamic_cast<Button*>(widgets.emplace_back(std::move(Button(0, 0.1, 0.4, 0.08, Location::CENTER, LiteralText(L"\\#ff44ee66Exit")))).ptr());
start->onTick = [start, this](int) { if (start->containsMouse()) game.getFloatWindow().push(L"\\#ff44ee66退出游戏"_renderable); };
start->mouseUp = [](int) {
Button* start = dynamic_cast<Button*>(widgets.emplace_back(std::move(Button(0, 0.1, 0.4, 0.08, Location::CENTER, LiteralText(L"\\f\4\\#ff44ee66Exit")))).ptr());
start->onTick = [](const Widget& self, MouseButtonCode) { if (self.containsMouse()) game.getFloatWindow().push(L"\\#ff44ee66退出游戏"_renderable); };
start->mouseClick = [](Widget&, MouseButtonCode) {
game.setWindow(&ConfirmWindow::of(LiteralText(L"是否\\#ff44ee66退出游戏\\r"))->requireCancel().requireConfirm([](Button& confirm) {
confirm.mouseUp = [](int) { DestroyWindow(MainWindowHandle); };
confirm.onTick = [&confirm](int) {
if (confirm.containsMouse()) {
confirm.mouseClick = [](Widget&, MouseButtonCode) { DestroyWindow(MainWindowHandle); };
confirm.onTick = [](Widget& self, MouseButtonCode) {
if (self.containsMouse()) {
game.getFloatWindow().push(L"\\#ff44ee66确定退出游戏"_renderable);
confirm.backgroundColor.hover = confirm.animation.adaptsColor(0x99008800, 0x9900ff00);
self.backgroundColor.hover = static_cast<Button&>(self).animation.adaptsColor(0x99008800, 0x9900ff00);
}
};
}));
};
Button* optn = dynamic_cast<Button*>(widgets.emplace_back(std::move(Button(0, 0.2, 0.4, 0.08, Location::CENTER, LiteralText(L"\\f\4\\#ff4488eeOptions")))).ptr());
optn->onTick = [](const Widget& self, MouseButtonCode) { if (self.containsMouse()) game.getFloatWindow().push(L"\\#ff4488ee设置"_renderable); };
Button* exit = dynamic_cast<Button*>(widgets.emplace_back(std::move(Button(0, 0.3, 0.4, 0.08, Location::CENTER, LiteralText(L"\\f\4\\#ffee0000Start")))).ptr());
exit->onTick = [](const Widget& self, MouseButtonCode) { if (self.containsMouse()) game.getFloatWindow().push(L"\\#ffee0000开始游戏"_renderable); };
exit->mouseClick = [](Widget&, MouseButtonCode) {
game.setWindow(&ConfirmWindow::of(LiteralText(L"是否\\#ffee0000退出游戏\\r"))->requireCancel().requireConfirm([](Button& confirm) {
confirm.mouseClick = [](Widget&, MouseButtonCode) { DestroyWindow(MainWindowHandle); };
confirm.onTick = [](Widget& self, MouseButtonCode) {
if (self.containsMouse()) {
game.getFloatWindow().push(L"\\#ff44ee66确定退出游戏"_renderable);
self.backgroundColor.hover = static_cast<Button&>(self).animation.adaptsColor(0x99008800, 0x9900ff00);
}
};
}));
};
Button* test = dynamic_cast<Button*>(widgets.emplace_back(std::move(Button(0, 0.2, 0.4, 0.08, Location::CENTER, LiteralText(L"\\#ff4488eeOptions")))).ptr());
Button* exit = dynamic_cast<Button*>(widgets.emplace_back(std::move(Button(0, 0.3, 0.4, 0.08, Location::CENTER, LiteralText(L"\\#ffee0000Start")))).ptr());
exit->onTick = [exit](int) { if (exit->containsMouse()) game.getFloatWindow().push(L"\\#ffee0000开始游戏"_renderable); };
}
public:
static StartWindow* create() noexcept { return allocatedFor(new StartWindow()); }
void onClose() override { pop(); }
void render() const noexcept override {
fontManager.getDefault().drawCenter(title.getRenderableString(), 0, 0, renderer.getWidth(), renderer.getHeight());
Window::render();