From c344588924ef1a4a2e3c817750315b3e33d149ec Mon Sep 17 00:00:00 2001 From: EmsiaetKadosh Date: Sun, 16 Mar 2025 14:18:05 +0800 Subject: [PATCH] =?UTF-8?q?=E6=A0=BC=E5=BC=8F=E6=95=B4=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .clang-tidy | 65 +++++++++++++++++++++++++++ Animation.h | 12 ++--- Chars.h | 12 ++--- File.h | 94 ++++++++++++++++++++++++++++++++++----- Game.h | 23 +++++----- IText.h | 42 +++++++++--------- InteractManager.cpp | 2 +- InteractManager.h | 4 +- Renderer.h | 20 ++++----- Task.h | 15 +++++-- TestCode.h | 15 ------- Window.cpp | 78 ++++++++++++++++---------------- Window.h | 63 +++++++++++++++----------- def.cpp | 6 ++- def.h | 40 ++++++++++------- exception.h | 26 +++++++---- gc.h | 28 +++++++----- hbp.h | 4 +- includes.h | 6 ++- main.cpp | 105 +++++++++++++++++++++++--------------------- utils.h | 21 ++++++--- warnings.h | 9 ++++ xWindows.h | 34 +++++++++----- 23 files changed, 467 insertions(+), 257 deletions(-) create mode 100644 .clang-tidy create mode 100644 warnings.h diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 0000000..bb71363 --- /dev/null +++ b/.clang-tidy @@ -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 diff --git a/Animation.h b/Animation.h index 9a0fbc7..7413f7b 100644 --- a/Animation.h +++ b/Animation.h @@ -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 { diff --git a/Chars.h b/Chars.h index 04c816f..11a3629 100644 --- a/Chars.h +++ b/Chars.h @@ -57,18 +57,18 @@ static constexpr wchar Table16[17] = L"0123456789ABCDEF"; String ret; if (fills >= 8 || value < static_cast(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(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"; diff --git a/File.h b/File.h index e7fe83a..ad9de35 100644 --- a/File.h +++ b/File.h @@ -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 + File& operator<<(T&& value) { + if (file.is_open()) file << std::forward(value); + return *this; + } + + File& operator<<(decltype(std::endl>) value) { + if (file.is_open()) file << value; + return *this; + } + + template + File& operator>>(T&& value) { + if (file.is_open()) file >> std::forward(value); + return *this; + } }; class Data { public: - enum class DataType : int { + enum class DataType : unsigned char { Integer, Double, String, Boolean, Null, List, Object }; @@ -34,18 +105,16 @@ 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 '\"'"; + errorInfo = L"Error: String never ends. EOF comes before a '\"'"; Failed(); } 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"); diff --git a/Game.h b/Game.h index 27dbbaf..0e8d4af 100644 --- a/Game.h +++ b/Game.h @@ -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(back); + if (auto *const back = windows.back()) return dynamic_cast(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); } }; diff --git a/IText.h b/IText.h index b3fb99f..2c153fb 100644 --- a/IText.h +++ b/IText.h @@ -3,10 +3,11 @@ // #pragma once + #include -#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::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(-1)) { + RenderableString(const wchar* const string, const QWORD length = static_cast(-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 resize; private: - friend class ObjectHolder; 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(interactSettings.actual.fontHeight * heightModifier)), escapement(escapement), orientation(orientation), yOffsetPx(static_cast(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(interactSettings.actual.fontHeight * heightModifier)), escapement(escapement), orientation(orientation), yOffsetPx(static_cast(yOffset * height)), id(id), adaptAllSize(adaptAllSize) {} public: Font(const Font&) = default; @@ -427,11 +427,11 @@ public: class FontManager { Map fonts; Font *defaultFont, *captionFont; - FontID assigned = 1; + FontID assigned = 0; using IterFonts = Map::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(interactSettings.actual.fontHeight * font.heightModifier); + font.yOffsetPx = static_cast(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::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(); diff --git a/InteractManager.cpp b/InteractManager.cpp index 3b69791..1604820 100644 --- a/InteractManager.cpp +++ b/InteractManager.cpp @@ -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(MouseButtonCodeEnum::MBC_L_DOWN) : 0) | (keyStatus[VK_RBUTTON].isPressed() ? static_cast(MouseButtonCodeEnum::MBC_R_DOWN) : 0) | (keyStatus[VK_MBUTTON].isPressed() ? static_cast(MouseButtonCodeEnum::MBC_M_DOWN) : 0); } +MouseButtonCode InteractManager::getMouseButtonCode() const noexcept { return (keyStatus[VK_LBUTTON].isPressed() ? static_cast(MouseButtonCodeEnum::MBC_L_DOWN) : 0) | (keyStatus[VK_RBUTTON].isPressed() ? static_cast(MouseButtonCodeEnum::MBC_R_DOWN) : 0) | (keyStatus[VK_MBUTTON].isPressed() ? static_cast(MouseButtonCodeEnum::MBC_M_DOWN) : 0); } diff --git a/InteractManager.h b/InteractManager.h index eaaeb45..102ff47 100644 --- a/InteractManager.h +++ b/InteractManager.h @@ -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; diff --git a/Renderer.h b/Renderer.h index 75b045a..1b75f4a 100644 --- a/Renderer.h +++ b/Renderer.h @@ -73,8 +73,8 @@ class Renderer final : public ITickable { public: byte windowSize = 0; // 1, Windows: SIZE_*** - byte reserved[5] {}; - Task resizeReloadBitmap { [this](Task& task) { + byte reserved[5]{}; + Task resizeReloadBitmap{ [this](Task& task) { Logger.info(L"Scheduled task: resize reload bitmap " + std::to_wstring(windowWidth) + L" * " + std::to_wstring(windowHeight)); if (!canvasBitmap) { canvasBitmap = CreateCompatibleBitmap(MainDC, windowWidth, windowHeight); @@ -86,7 +86,7 @@ public: } if (canvasBitmap && assistBitmap) { task.pop(); - Logger.info(L"Successfully reload bitmap " + ptrtow(reinterpret_cast(static_cast(canvasBitmap))) + L" " + ptrtow(reinterpret_cast(static_cast(assistBitmap)))); + Logger.info(L"Successfully reload bitmap " + ptrtow(reinterpret_cast(canvasBitmap)) + L" " + ptrtow(reinterpret_cast(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"); diff --git a/Task.h b/Task.h index de9bcf3..32a8d07 100644 --- a/Task.h +++ b/Task.h @@ -10,12 +10,15 @@ class TaskScheduler; class Task final : public AnywhereEditable { friend class TaskScheduler; +#ifndef __CARLBEKS_DEBUG__ + QWORD triggerInterval = 0, nextExecuteTime = 0, lastExecuteTime = 0; +#endif public: Function func; - explicit Task(const Function& func) : func(func) {} - explicit Task(Function&& func) : func(std::move(func)) {} + Task(const Function& func) : func(func) {} + Task(Function&& 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失效 } } } diff --git a/TestCode.h b/TestCode.h index 3d05f6a..75173ef 100644 --- a/TestCode.h +++ b/TestCode.h @@ -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(pow(message, e)) % n; - // decode: - message = static_cast(pow(package, d)) % n; -} diff --git a/Window.cpp b/Window.cpp index e08ae7f..83771f8 100644 --- a/Window.cpp +++ b/Window.cpp @@ -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 : widgets) widget->render(); } -void Window::tick() noexcept { for (ObjectHolder& widget : widgets) widget->tick(); } -void Window::onResize() { for (ObjectHolder& widget : widgets) widget->onResize(); } -void Window::passEvent(const MouseActionCode action, const MouseButtonCode value, const int x, const int y) noexcept { for (ObjectHolder& 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(this)) { @@ -40,19 +40,20 @@ void WindowManager::clear() noexcept { } CaptionWindow::CaptionWindow() { - ObjectHolder& 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& 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& 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& 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(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(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 : widgets) widget->render(); + for (const Widget* widget : widgets) widget->render(); } void CaptionWindow::onResize() { int left = 0, right = 0; - for (ObjectHolder& 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& 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& 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(renderer.getWidth() * w); + height = static_cast(renderer.getHeight() * h); switch (location) { case Location::LEFT_TOP: - left = renderer.getWidth() * x; - top = renderer.getHeight() * y; + left = static_cast(renderer.getWidth() * x); + top = static_cast(renderer.getHeight() * y); break; case Location::LEFT: - left = renderer.getWidth() * x; + left = static_cast(renderer.getWidth() * x); top = static_cast(renderer.getHeight() * y) + (renderer.getHeight() - height >> 1); break; case Location::LEFT_BOTTOM: - left = renderer.getWidth() * x; + left = static_cast(renderer.getWidth() * x); top = static_cast(renderer.getHeight() * y) + renderer.getHeight() - height; break; case Location::TOP: left = static_cast(renderer.getWidth() * x) + (renderer.getWidth() - width >> 1); - top = renderer.getHeight() * y; + top = static_cast(renderer.getHeight() * y); break; case Location::CENTER: left = static_cast(renderer.getWidth() * x) + (renderer.getWidth() - width >> 1); @@ -237,7 +241,7 @@ void Widget::onResize() { break; case Location::RIGHT_TOP: left = static_cast(renderer.getWidth() * x) + renderer.getWidth() - width; - top = renderer.getHeight() * y; + top = static_cast(renderer.getHeight() * y); break; case Location::RIGHT: left = static_cast(renderer.getWidth() * x) + renderer.getWidth() - width; @@ -277,8 +281,8 @@ ConfirmWindow& ConfirmWindow::requireConfirm(const Function& 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(confirm).animation.adaptsColor(0x99008800, 0x9900ff00); }; + confirm->mouseLeave = [](Widget& confirm, MouseButtonCode) { static_cast(confirm).animation.reset(); }; if (func) func(*confirm); confirm->onResize(); return *this; @@ -286,7 +290,7 @@ ConfirmWindow& ConfirmWindow::requireConfirm(const Function& func ConfirmWindow& ConfirmWindow::requireCancel(const Function& func) { cancel = dynamic_cast(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& 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(cancel).animation.adaptsColor(0x99880000, 0x99ff0000); }; + cancel->mouseLeave = [](Widget& cancel, int) { static_cast(cancel).animation.reset(); }; if (func) func(*cancel); cancel->onResize(); return *this; diff --git a/Window.h b/Window.h index 1565631..77d38f6 100644 --- a/Window.h +++ b/Window.h @@ -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; + using Action = Function; 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, 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> lt; - SynchronizedHolder strings{}; + SynchronizedHolder strings; public: - explicit FloatWindow() : Window() { + FloatWindow() : Window() { strings.setNew(std::move(lt())); strings.ok(); strings.async(); @@ -208,8 +222,8 @@ class Button : public Widget { public: ObjectHolder 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& 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&& 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& 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&& 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& text) : Window(), text(text) {} - explicit ConfirmWindow(ObjectHolder&& text) : Window(), text(std::move(text)) {} + ConfirmWindow(const ObjectHolder& text) : Window(), text(text) {} + ConfirmWindow(ObjectHolder&& 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; diff --git a/def.cpp b/def.cpp index f246991..5daefb1 100644 --- a/def.cpp +++ b/def.cpp @@ -6,6 +6,7 @@ #include "Chars.h" #include "exception.h" +#include "Game.h" template template requires std::is_base_of_v && TypeName void ObjectHolder::set(const T& value) { @@ -26,8 +27,9 @@ void ObjectHolder::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(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(value)) + L" " + std::to_wstring(size) + String(L"B ") + msg; Logger.log(str); #if __CARLBEKS_MEMORY__ > 2 diff --git a/def.h b/def.h index fb55d3d..6391881 100644 --- a/def.h +++ b/def.h @@ -18,7 +18,7 @@ #include #include #include -#include +#include using wchar = wchar_t; using QWORD = unsigned long long int; @@ -31,7 +31,10 @@ template using Function = std::function; #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 @@ -45,7 +48,6 @@ template using Function = std::function; #include #include #include -#include #include #define WM_APP_LBUTTONUP (WM_APP + 1) @@ -76,18 +78,19 @@ concept PointerType = std::is_pointer_v; template concept TypeName = NonreferenceType && NonpointerType; -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 allocated; + Map 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 T* _allocatedFor(T* value, const String& msg = L"", std::size_t size = sizeof(T)) { +template 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 T* _deallocating(T* value) { +template 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 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 requires (std::is_base_of_v || std::is_same_v) && TypeName ObjectHolder(const T& value) : value(allocatedFor(new T(value))), hasValue(true) {} - // ReSharper disable once CppNonExplicitConvertingConstructor template requires (std::is_base_of_v || std::is_same_v) && TypeName ObjectHolder(T&& value) : value(allocatedFor(new T(std::forward(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 ObjectHolder referenceof(const T& other) { + ObjectHolder ret{}; + ret.value = &other; + return ret; + } }; template class SynchronizedHolder { diff --git a/exception.h b/exception.h index f70438b..d668f23 100644 --- a/exception.h +++ b/exception.h @@ -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"; diff --git a/gc.h b/gc.h index 8d4b3ef..a155de7 100644 --- a/gc.h +++ b/gc.h @@ -4,7 +4,9 @@ #pragma once +#include "warnings.h" #include "def.h" +#include "File.h" struct IGarbage; template @@ -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(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 void submit(T* ptr) noexcept(false) { - IGarbage* garbage = allocatedFor(new Garbage(ptr)); + IGarbage* newedGarbage = allocatedFor(new Garbage(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(); diff --git a/hbp.h b/hbp.h index 1d51664..0a29fe6 100644 --- a/hbp.h +++ b/hbp.h @@ -12,14 +12,14 @@ inline BOOL NewProcess(const String& cmdline) noexcept { return CreateProcessW(nullptr, const_cast(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; } diff --git a/includes.h b/includes.h index 2344b9f..3dea687 100644 --- a/includes.h +++ b/includes.h @@ -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" diff --git a/main.cpp b/main.cpp index ea08995..307fd69 100644 --- a/main.cpp +++ b/main.cpp @@ -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(wParam); break; case WM_KEYDOWN: interactManager.update(static_cast(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(MouseButtonCodeEnum::MBC_L_CHANGE), interactManager.getMouseX(), interactManager.getMouseY()); + game.passEvent(MouseActionCode::MAC_DOWN, interactManager.getMouseButtonCode() | static_cast(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(MouseButtonCodeEnum::MBC_R_CHANGE), interactManager.getMouseX(), interactManager.getMouseY()); + game.passEvent(MouseActionCode::MAC_DOWN, interactManager.getMouseButtonCode() | static_cast(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(MouseButtonCodeEnum::MBC_L_CHANGE), interactManager.getMouseX(), interactManager.getMouseY()); + game.passEvent(MouseActionCode::MAC_UP, interactManager.getMouseButtonCode() | static_cast(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(MouseButtonCodeEnum::MBC_R_CHANGE), interactManager.getMouseX(), interactManager.getMouseY()); + game.passEvent(MouseActionCode::MAC_UP, interactManager.getMouseButtonCode() | static_cast(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(MouseButtonCodeEnum::MBC_M_CHANGE), interactManager.getMouseX(), interactManager.getMouseY()); + if (static_cast(wParam) & 0x10u) interactManager.update(VK_MBUTTON, true); + game.passEvent(MouseActionCode::MAC_DOWN, interactManager.getMouseButtonCode() | static_cast(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(MouseButtonCodeEnum::MBC_M_CHANGE), interactManager.getMouseX(), interactManager.getMouseY()); + game.passEvent(MouseActionCode::MAC_UP, interactManager.getMouseButtonCode() | static_cast(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(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(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; 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(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(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(); + GameThread = Thread(gameThread); + RenderThread = Thread(renderThread); } - SetConsoleOutputCP(65001); - HHOOK hook = SetWindowsHookW(WH_GETMESSAGE, HookProc); - test(); - HACCEL hAccelTable = LoadAcceleratorsW(hInstance, MAKEINTRESOURCE(109)); MSG msg = { nullptr }; - GameThread = Thread(gameThread); - RenderThread = Thread(renderThread); 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(); + { + 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(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; diff --git a/utils.h b/utils.h index f7f05f7..7aff0b7 100644 --- a/utils.h +++ b/utils.h @@ -1,8 +1,11 @@ // // Created by EmsiaetKadosh on 25-3-4. // + #pragma once +#include "gc.h" + template class AnywhereEditable; template @@ -11,6 +14,7 @@ template class AnywhereIterator; class AnywhereIteratorEnd; + /** * 此处无法进行代码编译层面的直接约束 * @tparam T 满足T extends AnywhereEditable @@ -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* current; public: - explicit AnywhereIterator(AnywhereEditable* current) : current(current) {} + AnywhereIterator(AnywhereEditable* 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 int AnywhereEditable::pushThis(AnywhereEditableList& list) noexcept { return list.pushThis(static_cast(this)); } template -int AnywhereEditable::pop() noexcept { return list->pop(static_cast(this)); } +int AnywhereEditable::pop() noexcept { + if (!list) { + Logger.error(L"AnywhereEditable::pop() : list is null"); + Failed(); + } + return list->pop(static_cast(this)); +} template bool AnywhereIterator::operator!=(const AnywhereIteratorEnd& other) const noexcept { return other != *this; } @@ -205,6 +214,6 @@ int AnywhereEditableList::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(); } diff --git a/warnings.h b/warnings.h new file mode 100644 index 0000000..47fa544 --- /dev/null +++ b/warnings.h @@ -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) diff --git a/xWindows.h b/xWindows.h index 0ca2b89..933e393 100644 --- a/xWindows.h +++ b/xWindows.h @@ -8,28 +8,42 @@ class StartWindow final : public Window { TranslatableText title = TranslatableText(L"hbp.title"); + StartWindow() { - Button* start = dynamic_cast(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(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(self).animation.adaptsColor(0x99008800, 0x9900ff00); + } + }; + })); + }; + Button* optn = dynamic_cast(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(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(self).animation.adaptsColor(0x99008800, 0x9900ff00); } }; })); }; - Button* test = dynamic_cast(widgets.emplace_back(std::move(Button(0, 0.2, 0.4, 0.08, Location::CENTER, LiteralText(L"\\#ff4488eeOptions")))).ptr()); - Button* exit = dynamic_cast(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();