commit 0ffca7ed1c49ea2c6ecceaab865a5c7f53dc27a2 Author: Michael Ochmann Date: Thu Apr 3 23:39:37 2025 +0200 initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9199d93 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +.idea +.vscode +.DS_Store + +build diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..676b840 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,6 @@ +[submodule "lib/raylib"] + path = lib/raylib + url = git@github.com:raysan5/raylib.git +[submodule "lib/raygui"] + path = lib/raygui + url = git@github.com:raysan5/raygui.git diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..54b2457 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,30 @@ +cmake_minimum_required(VERSION 3.30) + +project( + mcpaint + VERSION 0.0.1 + LANGUAGES CXX +) + +SET (CMAKE_CXX_STANDARD 23) +SET (CMAKE_BUILD_TYPE release) +SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -Wall") + +set(EXE_NAME "mcpaint_${CMAKE_PROJECT_VERSION}") + +file(GLOB_RECURSE sources src/*.hpp src/*.cpp) + +message("sources: ${sources}") + +file(COPY assets DESTINATION ${CMAKE_BINARY_DIR}) + +add_executable(mcpaint main.cpp ${sources}) +include_directories("lib/raygui/src") + +add_subdirectory(lib/raylib) + +target_link_libraries(mcpaint raylib) + +set_target_properties(mcpaint PROPERTIES OUTPUT_NAME ${EXE_NAME}) +target_compile_options(mcpaint PUBLIC -Wall -Wextra -pedantic -Wno-missing-field-initializers -Wno-unused-parameter -Wno-c++11-narrowing) +target_include_directories(mcpaint PRIVATE src lib/raylib) diff --git a/README.md b/README.md new file mode 100644 index 0000000..36c96a3 --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# mcpaint +– a simple drawing app whose code could be understood diff --git a/assets/fonts/icons-solid.otf b/assets/fonts/icons-solid.otf new file mode 100644 index 0000000..00a0b3e Binary files /dev/null and b/assets/fonts/icons-solid.otf differ diff --git a/assets/fonts/icons.otf b/assets/fonts/icons.otf new file mode 100644 index 0000000..17a8350 Binary files /dev/null and b/assets/fonts/icons.otf differ diff --git a/assets/fonts/roboto_regular.ttf b/assets/fonts/roboto_regular.ttf new file mode 100755 index 0000000..5af42d4 Binary files /dev/null and b/assets/fonts/roboto_regular.ttf differ diff --git a/assets/fonts/sf-pro.otf b/assets/fonts/sf-pro.otf new file mode 100644 index 0000000..3c50b18 Binary files /dev/null and b/assets/fonts/sf-pro.otf differ diff --git a/lib/raygui b/lib/raygui new file mode 160000 index 0000000..566c73f --- /dev/null +++ b/lib/raygui @@ -0,0 +1 @@ +Subproject commit 566c73f4e469ba83b053a0606188cc6b132c1312 diff --git a/lib/raylib b/lib/raylib new file mode 160000 index 0000000..ceb1a5e --- /dev/null +++ b/lib/raylib @@ -0,0 +1 @@ +Subproject commit ceb1a5ea2b7550aa01c103b4b3dac0dbc4d8f8fe diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..f2bfa68 --- /dev/null +++ b/main.cpp @@ -0,0 +1,279 @@ +#include +#include +#include +#define RAYGUI_IMPLEMENTATION +#include +#include +#include + +#include +#include + +#include "src/gui/styleDark.hpp" +#include "src/gui/Panel.hpp" +#include "src/util.hpp" +#include "src/UndoRedoManager.hpp" +#include "src/Artboards.hpp" + +#include "src/gui/View.hpp" +#include "src/gui/VStack.hpp" +#include "src/gui/HStack.hpp" +#include "src/gui/Button.hpp" +#include "src/gui/Spacer.hpp" +#include "src/gui/Icon.hpp" + +std::ostream& operator<<(std::ostream& os, const Color& c) { + os << "Color(" << (int)c.r << ", " << (int)c.g << ", " << (int)c.b << ", " << (int)c.a << ")"; + return os; +} + +using namespace mcpaint; +using namespace mcpaint::gui; + +int main() { + + Vector2 windowSize = {1080, 720}; + SetTargetFPS(100); + SetConfigFlags(FLAG_WINDOW_RESIZABLE | FLAG_MSAA_4X_HINT); + InitWindow(windowSize.x, windowSize.y, "mcpaint"); + HideCursor(); + + bool mouseDrag = false; + + Dispatch& dispatcher = Dispatch::Instance(); + dispatcher.addListener(Event::Type::POINTER_REQUEST, [&mouseDrag](Event e) { + mouseDrag = true; + }); + //SetExitKey(KEY_NULL); + + Artboards* artboards = new Artboards(); + + auto gui = View({ + VStack({ + HStack({ + Button(Icon::BRUSH, [](Event e) { + std::cout << "CLICK" << std::endl; + }), + Button("Load", [](Event e) { + std::cout << "CLICK" << std::endl; + }), + Button("clear", [](Event e) { + std::cout << "CLICK" << std::endl; + }), + Spacer(), + Button("Tool", [](Event e) { + std::cout << "CLICK" << std::endl; + }), + Button("erase", [](Event e) { + std::cout << "CLICK" << std::endl; + }), + })->background(Theme::ELEMENT)->size({100.0f, 35})->padding(3)->border({.color = Theme::ELEMENT_BORDER, .width = 1}), + HStack({ + artboards, + VStack({ + Button("Test"), + Spacer() + })->background(Theme::ELEMENT)->size({200, 100.0f}) + })->background(Theme::ARTBOARD), + View()->background(RED)->size({100.0f, 50}), + })->background(Theme::ELEMENT) + }); + + UndoRedoManager undoStack; + std::vector images; + Panel toolBar = Panel({0, 0}, {100.0f, 50}); + Panel inspector = Panel({70.0f, 50}, {30.0f, 100.0f}); + + Font roboto = LoadFontEx("resources/sf-pro.otf", 40, nullptr, 0); + SetTextureFilter(roboto.texture, TEXTURE_FILTER_BILINEAR); + + SetConfigFlags(FLAG_VSYNC_HINT | FLAG_MSAA_4X_HINT | FLAG_WINDOW_HIGHDPI); + //SetWindowSize(1920, 1080); + RenderTexture2D canvas = LoadRenderTexture(1080, 720); + SetTextureFilter(canvas.texture, TEXTURE_FILTER_TRILINEAR); + + GuiLoadStyleDark(); + GuiSetFont(roboto); + GuiSetStyle(DEFAULT, TEXT_SIZE, 15); + GuiSetStyle(DEFAULT, BORDER_COLOR_NORMAL, 0x00000000); + GuiSetStyle(DEFAULT, BORDER_COLOR_FOCUSED, 0x00000000); + + Color mainColor = ColorFromHex(0x000000FF); + + std::vector colors = { + ColorFromHex(0x000000FF), + ColorFromHex(0xFF0000FF), + ColorFromHex(0x00FF00FF), + ColorFromHex(0x0000FFFF), + ColorFromHex(0xFFFF00FF), + ColorFromHex(0xFF00FFFF), + ColorFromHex(0x00FFFFFF), + ColorFromHex(0xFFFFFFFF), + }; + + BeginTextureMode(canvas); + ClearBackground(WHITE); + for (int x = 0; x < canvas.texture.width; x += 10) { + for (int y = 0; y < canvas.texture.height; y += 10) { + if (((x + y) / 10) % 2 == 0) + DrawRectangle(x, y, 10, 10, ColorFromHex(0xCCCCCCFF)); + } + } + EndTextureMode(); + RenderTexture2D stackCopy = canvas; + undoStack.push(canvas); + + Vector2 lastMouse = { 0, 0 }; + + bool stroke = false; + float strokeWidth = 10; + + Rectangle canvasRect = {10, 50, canvas.texture.width, canvas.texture.height}; + + while (!WindowShouldClose()) { + float deltaTime = GetFrameTime(); + mouseDrag = false; + + gui->update(deltaTime); // GUI + + windowSize = {static_cast(GetScreenWidth()), static_cast(GetScreenHeight())}; + + toolBar.update(deltaTime); + + Vector2 mouse = GetMousePosition(); + + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON) && CheckCollisionPointRec(mouse, canvasRect)) { + mouse = {mouse.x - canvasRect.x, mouse.y - canvasRect.y}; + BeginTextureMode(canvas); + if (stroke) { + Vector2 diff = lastMouse - mouse; + float len = Vector2Length(diff); + + for (int i = 0; i < len / (strokeWidth/2); i++) { + Vector2 lerp = Vector2Lerp(lastMouse, mouse, (float)i / (len / (strokeWidth/2))); + DrawCircleV(lerp, strokeWidth, mainColor); + } + + //DrawLineEx(lastMouse, mouse, 10, BLACK); + } + stroke = true; + EndTextureMode(); + } else { + stroke = false; + } + Rectangle inspectorRect = {inspector.getPosition().x, inspector.getPosition().y, inspector.getSize().x, inspector.getSize().y}; + if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON) && + CheckCollisionPointRec(mouse, canvasRect) && + !CheckCollisionPointRec(mouse, inspectorRect) && + !IsFileDropped()) { + undoStack.push(canvas); + } + + if (IsMouseButtonPressed(MOUSE_RIGHT_BUTTON)) { + BeginTextureMode(canvas); + ClearBackground(WHITE); + for (int x = 0; x < canvas.texture.width; x += 10) { + for (int y = 0; y < canvas.texture.height; y += 10) { + if (((x + y) / 10) % 2 == 0) + DrawRectangle(x, y, 10, 10, ColorFromHex(0xCCCCCCFF)); + } + } + EndTextureMode(); + } + + if (IsFileDropped()) { + FilePathList files = LoadDroppedFiles(); + for (int i = 0; i < files.count; i++) { + std::cout << files.paths[i] << std::endl; + BeginTextureMode(canvas); + DrawTexture(LoadTextureFromImage(LoadImage(files.paths[i])), 0, 0, WHITE); + EndTextureMode(); + } + if (files.count > 0) + undoStack.push(canvas); + UnloadDroppedFiles(files); + } + + BeginDrawing(); + ClearBackground(ColorFromHex(0x222222FF)); + + gui->render(deltaTime); // GUI + + /* + float x = 10; + float y = 10; + + Vector2 pointer = GetMousePosition(); + DrawTexturePro(canvas.texture, {0, 0, (float)canvas.texture.width, (float)-canvas.texture.height }, canvasRect, {0, 0}, 0, WHITE); + if (CheckCollisionPointRec(pointer, canvasRect)) + DrawCircleLinesV(pointer, strokeWidth, mainColor); + + toolBar.render(deltaTime); + GuiButton({x, y, 25, 25}, "#02#"); + x += 35; + GuiButton({x, y, 25, 25}, "#24#"); + x += 35; + GuiSetState(STATE_DISABLED); + if (undoStack.canUndo()) + GuiSetState(STATE_NORMAL); + if (GuiButton({x, y, 25, 25}, "#056#")) + undoStack.undo(canvas); + x += 35; + GuiSetState(STATE_DISABLED); + if (undoStack.canRedo()) + GuiSetState(STATE_NORMAL); + if (GuiButton({x, y, 25, 25}, "#057#")) + undoStack.redo(canvas); + x += 35; + y += 50; + GuiSetState(STATE_NORMAL); + + inspector.render(deltaTime); + x = inspector.getPosition().x + 10; + y = inspector.getPosition().y + 10; + float pickerWidth = GuiGetStyle(COLORPICKER, HUEBAR_WIDTH) - GuiGetStyle(COLORPICKER, HUEBAR_PADDING); + GuiColorPicker({inspector.getPosition().x + 10, inspector.getPosition().y + 10, inspector.getSize().x - 35 - pickerWidth, 300}, "color", &mainColor); + y += 300 + 10; + bool l = false; + std::string val = std::to_string(strokeWidth); + char* c = "ddd"; + //GuiTextInputBox({x, y, 90, 25}, "brush size", "mess", nullptr_t, &c, 20, &l); + std::string sliderLabel = "brush size"; + float labelWidth = GetTextWidth(sliderLabel.c_str()); + x += labelWidth + 10; + GuiSliderBar({ x, y, inspector.getSize().x - labelWidth - 30, 15}, sliderLabel.c_str(), nullptr, &strokeWidth, 1, 20); + x = inspector.getPosition().x + 10; + y += 25; + DrawCircle(x + 10 + strokeWidth, y + 10 + strokeWidth, strokeWidth, mainColor); + DrawCircleLines(x + 10 + strokeWidth, y + 10 + strokeWidth, strokeWidth, WHITE); + */ + size_t cursorSize = 15; + Vector2 cursorPosition = GetMousePosition(); + int x = cursorPosition.x; + int y = cursorPosition.y; + Icon cursor = Icon::REGULAR;; + Color cursorColor = BLACK; + Color cursorOutline = WHITE; + + if (mouseDrag) { + cursor = Icon::MOVE; + cursorColor = WHITE; + cursorOutline = BLACK; + } + // outline + DrawIcon(cursor, x + 1, y + 1, cursorSize, cursorOutline); + DrawIcon(cursor, x - 1, y - 1, cursorSize, cursorOutline); + DrawIcon(cursor, x + 1, y - 1, cursorSize, cursorOutline); + DrawIcon(cursor, x - 1, y + 1, cursorSize, cursorOutline); + + DrawIcon(cursor, x, y, cursorSize, cursorColor); + + EndDrawing(); + + lastMouse = mouse; + } + delete gui; + CloseWindow(); + + return 0; +} \ No newline at end of file diff --git a/src/Artboards.cpp b/src/Artboards.cpp new file mode 100644 index 0000000..0a7b71f --- /dev/null +++ b/src/Artboards.cpp @@ -0,0 +1,134 @@ +#include + +#include "gui/FontManager.hpp" +#include "Artboards.hpp" +#include "Event.hpp" +#include "gui/theme.hpp" + +namespace mcpaint { + +using namespace gui; +using namespace events; + +Artboards::Artboards() { + this->artboards.push_back(Artboard({ + .position = {0, 0}, + .size = {1920.0f, 1080.0f}, + .canvas = LoadRenderTexture(1920, 1080), + .scale = 1.0f + })); +} + +void Artboards::initialScale() { + if (this->size_.x == 0.0f || this->artboards.size() < 1) + return; + + float max = this->artboards.at(0).size.x; + + this->scale = this->size_.x * .9f / max; +} + +void Artboards::update(float deltaTime, const gui::view* const parent) { + if (this->scale == 0.0f) + this->initialScale(); + + BeginTextureMode(this->artboards.at(this->currentArtboard).canvas); + ClearBackground(WHITE); + DrawPixel(100, 100, BLACK); + DrawCircle(100, 100, 50, RED); + EndTextureMode(); + + Vector2 scroll = GetMouseWheelMoveV(); + + if (scroll.y != 0) { + if (this->scale + scroll.y / 100 > 0.05f && this->scale + scroll.y / 100 <= 3.0f) + this->scale += scroll.y / 100; + } + + Vector2 mouse = GetMousePosition(); + if (this->hovered()) { + if (IsKeyDown(KEY_SPACE)) { + dispatch << Event(Event::Type::POINTER_REQUEST, mouse); + + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) { + Vector2 mouseDelta = GetMouseDelta(); + + if (mouseDelta.x != 0 || mouseDelta.y != 0) + this->offset += mouseDelta; + } + } else if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) { + size_t i = 0; + for (const auto& artboard : this->artboards) { + if (CheckCollisionPointRec(mouse, {artboard.position.x, artboard.position.y, artboard.size.x * this->scale, artboard.size.y * this->scale})) { + this->currentArtboard = i; + break; + } + i++; + } + } + } +} + +Artboards::Artboards(Artboard initialArtboard) { + this->artboards.push_back(std::move(initialArtboard)); +} + +void Artboards::render(float deltaTime) { + FontManager& fontManager = FontManager::Instance(); + + BeginScissorMode(this->position_.x, this->position_.y, this->size_.x, this->size_.y); + + std::string hud = std::format( + "x: {}, y: {}\nwidth: {}, height: {}\nscale: {}\noffset: {}, {}", + this->position_.x, + this->position_.y, + this->size_.x, + this->size_.y, + this->scale, + this->offset.x, this->offset.y + ); + + size_t i = 0; + float localOffset = 0; + for (auto& artboard : this->artboards) { + Vector2 scaled = artboard.size * this->scale; + Vector2 position = this->position_ + this->size_ * .5f - scaled * .5f + this->offset; + //DrawRectangleV(position, scaled, WHITE); + DrawTexturePro(artboard.canvas.texture, {0, 0, static_cast(artboard.canvas.texture.width), -static_cast(artboard.canvas.texture.height)}, {position.x, position.y, scaled.x, scaled.y}, {0, 0}, 0, WHITE); + + float border = 2; + if (this->currentArtboard == i) + DrawRectangleLinesEx({position.x - border * .5f - 3, position.y - border * .5f - 3, scaled.x + border + 6, scaled.y + border + 6}, border, SKYBLUE); + i++; + } + + + + Vector2 bounds = MeasureTextEx( + fontManager.get("assets/fonts/sf-pro.otf", 20), + hud.c_str(), + 20, + 0 + ); + DrawRectangle( + this->position_.x, + this->position_.y, + bounds.x + 20, + bounds.y + 20, + ColorFromHex(0x00000066) + ); + DrawTextPro( + fontManager.get("assets/fonts/sf-pro.otf", 20), + hud.c_str(), + {this->position_.x + 10, this->position_.y + 10}, + {0, 0}, + 0, + 20, + 0, + WHITE + ); + + EndScissorMode(); +} + +} \ No newline at end of file diff --git a/src/Artboards.hpp b/src/Artboards.hpp new file mode 100644 index 0000000..48b967c --- /dev/null +++ b/src/Artboards.hpp @@ -0,0 +1,36 @@ +#pragma once + +#include + +#include "gui/View.hpp" + +namespace mcpaint { + +struct Artboard { + Vector2 position; + Vector2 size; + RenderTexture2D canvas; + float scale; +}; + +class Artboards : public gui::view { + protected: + std::vector artboards; + float scale = 0.0f; + Vector2 offset; + size_t currentArtboard = 0; + + void initialScale(); + public: + Artboards(); + Artboards(Artboard initialArtboard); + + virtual gui::view::Type type() const override { + return gui::view::Type::ARTBOARDS; + } + + void update(float deltaTime, const gui::view* const parent = nullptr) override; + void render(float deltaTime) override; +}; + +} \ No newline at end of file diff --git a/src/Event.cpp b/src/Event.cpp new file mode 100644 index 0000000..87ee3b9 --- /dev/null +++ b/src/Event.cpp @@ -0,0 +1,7 @@ +#include "Event.hpp" + +namespace mcpaint::events { + +std::unique_ptr Dispatch::Instance_ = nullptr; + +} \ No newline at end of file diff --git a/src/Event.hpp b/src/Event.hpp new file mode 100644 index 0000000..b63fe24 --- /dev/null +++ b/src/Event.hpp @@ -0,0 +1,56 @@ +#pragma once + +#include +#include +#include +#include +#include + +namespace mcpaint::events { + +struct Event { + enum class Type { + CLICK, + POINTER_REQUEST + }; + + Type type; + Vector2 mouse; +}; + +using EventCallback = std::function; + +class Dispatch { + private: + std::unordered_map> handlers; + static std::unique_ptr Instance_; + Dispatch() = default; + public: + static Dispatch& Instance() { + if (Dispatch::Instance_ == nullptr) + Dispatch::Instance_ = std::unique_ptr(new Dispatch()); + + return *Dispatch::Instance_.get(); + } + + void addListener(Event::Type type, EventCallback callback) { + this->handlers[type].push_back(callback); + } + + const Dispatch& operator <<(const Event& event) const { + for (const auto& handler : this->handlers.at(event.type)) { + handler(event); + } + + return *this; + } + + Dispatch(const Dispatch&) = delete; + Dispatch& operator=(const Dispatch&) = delete; + Dispatch(Dispatch&&) = delete; + Dispatch& operator=(Dispatch&&) = delete; +}; + +inline const Dispatch& dispatch = Dispatch::Instance(); + +} \ No newline at end of file diff --git a/src/UndoRedoManager.cpp b/src/UndoRedoManager.cpp new file mode 100644 index 0000000..efaac0f --- /dev/null +++ b/src/UndoRedoManager.cpp @@ -0,0 +1,66 @@ +#include "UndoRedoManager.hpp" + +#include + +namespace mcpaint { + +UndoRedoManager::UndoRedoManager() : pointer(-1), size(0) { +} + +void UndoRedoManager::push(const RenderTexture2D& texture) { + Image image = LoadImageFromTexture(texture.texture); // getting the current buffer + // if the stack is full, remove the first element and shift subsequent images + if (this->pointer >= 0 && this->pointer >= UndoRedoManager::MAX_UNDO_REDO - 1) { + printf("PUSH %u, max: %u\n", this->pointer, UndoRedoManager::MAX_UNDO_REDO); + if (this->stack[0].has_value()) + UnloadImage(this->stack[0].value()); + for (size_t i = 0; i < this->size; ++i) + this->stack[i] = this->stack[i + 1]; + + this->pointer = UndoRedoManager::MAX_UNDO_REDO - 1; + this->size = UndoRedoManager::MAX_UNDO_REDO; + + this->stack[this->pointer] = image; + } else if (this->pointer >= 0 && this->pointer + 1 < this->size) { + this->pointer++; + // here we clear all subsequent images, because the stack is broken if a + // push is performed in the middle of the stack + for (size_t i = this->pointer; i < this->size; ++i) { + if (!this->stack[i].has_value()) + continue; + UnloadImage(this->stack[i].value()); + this->stack[i] = std::nullopt; + } + this->size = this->pointer + 1; + this->stack[this->pointer] = image; + } else { + this->stack[++this->pointer] = image; + this->size++; + } +} + +void UndoRedoManager::undo(const RenderTexture2D& canvas) { + if (this->pointer > 0) + this->pointer--; + + if (this->stack[this->pointer].has_value()) + UndoRedoManager::RenderImage(canvas, this->stack[this->pointer].value()); +} + +void UndoRedoManager::redo(const RenderTexture2D& canvas) { + if (this->pointer + 1 < this->size) + this->pointer++; + + if (this->stack[this->pointer].has_value()) + UndoRedoManager::RenderImage(canvas, this->stack[this->pointer].value()); +} + +void UndoRedoManager::RenderImage(const RenderTexture2D& canvas, const Image& image) { + Texture2D img = LoadTextureFromImage(image); + BeginTextureMode(canvas); + DrawTexturePro(img, {0, 0, (float)img.width, (float)-img.height }, {0, 0, static_cast(img.width), static_cast(img.height)}, {0, 0}, 0, WHITE); + EndTextureMode(); + UnloadTexture(img); +} + +} \ No newline at end of file diff --git a/src/UndoRedoManager.hpp b/src/UndoRedoManager.hpp new file mode 100644 index 0000000..f4fb902 --- /dev/null +++ b/src/UndoRedoManager.hpp @@ -0,0 +1,40 @@ +#pragma once; + +#include +#include +#include + +namespace mcpaint { + +class UndoRedoManager { + private: + constexpr static size_t MAX_UNDO_REDO = 50; + std::optional stack[UndoRedoManager::MAX_UNDO_REDO]; + int64_t pointer; + size_t size; + public: + UndoRedoManager(); + ~UndoRedoManager() = default; + + void push(const RenderTexture2D& texture); + void undo(const RenderTexture2D& canvas); + void redo(const RenderTexture2D& canvas); + + bool canUndo() const { + return this->pointer > 0; + } + + bool canRedo() const { + return this->pointer + 1 < this->size; + } + + static void RenderImage(const RenderTexture2D& canvas, const Image& image); + + UndoRedoManager(const UndoRedoManager&) = delete; + UndoRedoManager& operator=(const UndoRedoManager&) = delete; + + UndoRedoManager(UndoRedoManager&&) = delete; + UndoRedoManager& operator=(UndoRedoManager&&) = delete; +}; + +} \ No newline at end of file diff --git a/src/gui/Button.cpp b/src/gui/Button.cpp new file mode 100644 index 0000000..48ba606 --- /dev/null +++ b/src/gui/Button.cpp @@ -0,0 +1,75 @@ +#include "Button.hpp" +#include "FontManager.hpp" + +namespace mcpaint::gui { + +button::button(std::string label, ButtonCallback callback) : + label_(std::move(label)), + callback(std::move(callback)) { + this->spec_.display = Display::INLINE; + this->spec_.padding = 5; + this->spec_.color = Theme::ELEMENT_FG; + this->spec_.background = Theme::ELEMENT; + this->spec_.hoverBackground = Theme::ELEMENT_HOVER; + this->spec_.radius = 3; +} +button::button(Icon icon, ButtonCallback callback) : + isIcon(true), + icon(icon), + callback(std::move(callback)) { + this->spec_.display = Display::INLINE; + this->spec_.padding = 5; + this->spec_.color = Theme::ELEMENT_FG; + this->spec_.background = Theme::ELEMENT; + this->spec_.hoverBackground = Theme::ELEMENT_HOVER; + this->spec_.radius = 3; +} + +void button::update(float deltaTime, const view* const parent) { + Vector2 mouse = GetMousePosition(); + + if (this->hovered()) { + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) { + Event event = {Event::Type::CLICK, mouse}; + this->callback(event); + } + } + + view::update(deltaTime, parent); +} + +void button::render(float deltaTime) { + FontManager& fontManager = FontManager::Instance(); + const Font& font = fontManager.get(this->spec_.font, this->spec_.fontSize); + + view::render(deltaTime); + float textWidth = this->contentWidth(); + Vector2 textPosition = { + round(this->position_.x + (this->size_.x + this->spec_.padding * 2) / 2 - textWidth * .5f), + round(this->position_.y + this->size_.y / 2 - this->spec_.fontSize * .5f) + }; + + if (this->active() || this->hovered()) { + Color color = this->active() ? this->spec_.activeBackground : this->spec_.hoverBackground; + + DrawRectangleRounded({this->position_.x, this->position_.y, this->size_.x, this->size_.y}, this->roundness(), 0, color); + DrawRectangleRoundedLinesEx({this->position_.x, this->position_.y, this->size_.x, this->size_.y}, this->roundness(), 0, 1, ColorFromHex(0x636363FF)); + } + + if (this->isIcon) + DrawIcon(this->icon, textPosition, this->spec_.fontSize, this->spec_.color); + else + DrawTextPro(font, this->label_.c_str(), textPosition, {0, 0}, 0, this->spec_.fontSize, 0, this->spec_.hoverColor); +} + +size_t button::contentWidth() const { + if (this->isIcon) + return MeasureIcon(this->icon, this->spec_.fontSize).x + this->spec_.padding * 2; + + FontManager& fontManager = FontManager::Instance(); + const Font& font = fontManager.get(this->spec_.font, this->spec_.fontSize); + + return MeasureTextEx(font, this->label_.c_str(), this->spec_.fontSize, 0).x + this->spec_.padding * 2; +} + +} \ No newline at end of file diff --git a/src/gui/Button.hpp b/src/gui/Button.hpp new file mode 100644 index 0000000..3d2212f --- /dev/null +++ b/src/gui/Button.hpp @@ -0,0 +1,43 @@ +#pragma once + +#include + +#include "../Event.hpp" +#include "Icon.hpp" +#include "View.hpp" + +using namespace mcpaint::events; + +namespace mcpaint::gui { + +using ButtonCallback = std::function; + +class button : public view { + protected: + bool isIcon = false; + Icon icon; + std::string label_; + ButtonCallback callback; + public: + button(std::string label = "", ButtonCallback callback = [](Event) {}); + button(Icon icon, ButtonCallback callback = [](Event) {}); + + virtual void update(float deltaTime, const view* const parent = nullptr) override; + virtual void render(float deltaTime) override; + + size_t contentWidth() const override; + + virtual Type type() const override { + return Type::BUTTON; + } +}; + +inline button* Button(std::string label = "", ButtonCallback callback = [](Event) {}) { + return new button(std::move(label), std::move(callback)); +} + +inline button* Button(Icon icon, ButtonCallback callback = [](Event) {}) { + return new button(icon, std::move(callback)); +} + +} \ No newline at end of file diff --git a/src/gui/Element.cpp b/src/gui/Element.cpp new file mode 100644 index 0000000..bdd8ef6 --- /dev/null +++ b/src/gui/Element.cpp @@ -0,0 +1,17 @@ +#include "Element.hpp" + +namespace mcpaint::gui { + +Element::Element(Vec2 position, Vec2 size) : position(position), size(size) { +} + +Element::Element(Vec2 position, Vec2 size, const Element* parent) : position(position), size(size), parent(parent) { +} + +void Element::update(float deltaTime) { +} + +void Element::render(float deltaTime) { +} + +} \ No newline at end of file diff --git a/src/gui/Element.hpp b/src/gui/Element.hpp new file mode 100644 index 0000000..04b2163 --- /dev/null +++ b/src/gui/Element.hpp @@ -0,0 +1,63 @@ +#pragma once + +#include +#include +#include + +#include "../util.hpp" + +namespace mcpaint::gui { + +using Value = std::variant; + +struct Vec2 { + Value x; + Value y; + + Vector2 toPixels() const { + Vector2 windowSize = GetWindowSize(); + Vector2 outValue; + + if (std::holds_alternative(this->x)) + outValue.x = std::get(this->x) * windowSize.x / 100.0f; + else + outValue.x = std::get(this->x); + + if (std::holds_alternative(this->y)) + outValue.y = std::get(this->y) * windowSize.y / 100.0f; + else + outValue.y = std::get(this->y); + + return outValue; + } +}; + +class Element { + protected: + Vec2 position; + Vec2 size; + std::optional parent; + public: + Element(Vec2 position, Vec2 size); + Element(Vec2 position, Vec2 size, const Element* parent); + virtual ~Element() = default; + + virtual void update(float deltaTime); + virtual void render(float deltaTime); + + Vector2 getPosition() const { + return this->position.toPixels(); + } + + Vector2 getSize() { + return this->size.toPixels(); + } + + Element(const Element&) = delete; + Element& operator=(const Element&) = delete; + + Element(Element&&) = delete; + Element& operator=(Element&&) = delete; +}; + +} \ No newline at end of file diff --git a/src/gui/FontManager.cpp b/src/gui/FontManager.cpp new file mode 100644 index 0000000..6e92ebe --- /dev/null +++ b/src/gui/FontManager.cpp @@ -0,0 +1,38 @@ +#include "FontManager.hpp" + +#include "Icon.hpp" + +namespace mcpaint::gui { + +std::unique_ptr FontManager::Instance_ = nullptr; +Font FontManager::IconFont_ = {0}; + +FontManager::FontManager() { + FontManager::IconFont_ = LoadFontEx( + "assets/fonts/icons-solid.otf", + FontManager::ICON_SIZE * 2, // HiDPI + const_cast(Iconset), + sizeof(Iconset) / sizeof(Iconset[0]) + ); +} + +FontManager::~FontManager() { + for (auto& font : this->fonts) { + for (auto& size : font.second) + UnloadFont(size.second); + } +} + +Font FontManager::get(std::string path, size_t size) { + size *= 2; // this is for high DPI + if (this->fonts.find(path) == this->fonts.end()) + this->fonts.emplace(path, std::unordered_map({{size, LoadFontEx(path.c_str(), size, nullptr, 0)}})); + else if (this->fonts.at(path).find(size) == this->fonts.at(path).end()) + this->fonts.at(path).emplace(size, LoadFontEx(path.c_str(), size, nullptr, 0)); + + SetTextureFilter(this->fonts.at(path).at(size).texture, TEXTURE_FILTER_BILINEAR); + + return this->fonts.at(path).at(size); +} + +} \ No newline at end of file diff --git a/src/gui/FontManager.hpp b/src/gui/FontManager.hpp new file mode 100644 index 0000000..6032898 --- /dev/null +++ b/src/gui/FontManager.hpp @@ -0,0 +1,39 @@ +#pragma once + +#include +#include +#include + +namespace mcpaint::gui { + +class FontManager { + protected: + constexpr static size_t ICON_SIZE = 50; + std::unordered_map> fonts; + + FontManager(); + static std::unique_ptr Instance_; + static Font IconFont_; + public: + ~FontManager(); + + Font get(std::string path, size_t size); + + static FontManager& Instance() { + if (FontManager::Instance_ == nullptr) + FontManager::Instance_ = std::unique_ptr(new FontManager()); + + return *FontManager::Instance_.get(); + } + + inline static const Font& IconFont() { + return FontManager::IconFont_; + } + + FontManager(const FontManager&) = delete; + FontManager& operator=(const FontManager&) = delete; + FontManager(FontManager&&) = delete; + FontManager& operator=(FontManager&&) = delete; +}; + +} \ No newline at end of file diff --git a/src/gui/HStack.cpp b/src/gui/HStack.cpp new file mode 100644 index 0000000..b207833 --- /dev/null +++ b/src/gui/HStack.cpp @@ -0,0 +1,52 @@ +#include "HStack.hpp" + +namespace mcpaint::gui { + +void hstack::update(float deltaTime, const view* const parent) { + //this->updateSelf(deltaTime, parent); + this->updateChildren(deltaTime); + + float offset = this->spec_.padding; + float fullWidth = this->size_.x - this->spec_.padding * 2 - ((this->children.size() - 1) * this->spec_.gap); + size_t fixedChildren = 0; + + for (const auto& child : this->children) { + const Spec& spec = child->spec(); + + if (spec.display == Display::INLINE) { + fullWidth -= child->contentWidth(); + fixedChildren++; + } else if (std::holds_alternative(spec.size.first)) { + fullWidth -= std::get(spec.size.first); + fixedChildren++; + } + } + + for (const auto& child : this->children) { + const Spec& spec = child->spec(); + + float width; + + switch(spec.display) { + case Display::INLINE: + width = child->contentWidth(); + break; + default: + width = std::holds_alternative(spec.size.first) ? std::get(spec.size.first) : fullWidth / (this->children.size() - fixedChildren); + break; + } + + float height = this->size_.y - this->spec_.padding * 2; + + child->size_ = {round(width), height}; + child->position({this->position_.x + offset, this->position_.y + this->spec_.padding}); + offset += width + this->spec_.gap; + } + +} + +void hstack::render(float deltaTime) { + view::render(deltaTime); +} + +} \ No newline at end of file diff --git a/src/gui/HStack.hpp b/src/gui/HStack.hpp new file mode 100644 index 0000000..6ed8708 --- /dev/null +++ b/src/gui/HStack.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include "View.hpp" + +namespace mcpaint::gui { + +class hstack : public view { + public: + using view::view; + + virtual void update(float deltaTime, const view* const parent = nullptr) override; + virtual void render(float deltaTime) override; + + virtual Type type() const override { + return Type::HSTACK; + } +}; + +inline hstack* HStack(std::initializer_list children = {}) { + return new hstack(children); +} + +} \ No newline at end of file diff --git a/src/gui/Icon.hpp b/src/gui/Icon.hpp new file mode 100644 index 0000000..521b60c --- /dev/null +++ b/src/gui/Icon.hpp @@ -0,0 +1,35 @@ +#pragma once + +#include + +#include "FontManager.hpp" +#include "View.hpp" + +namespace mcpaint::gui { + +enum class Icon : wchar_t { + REGULAR = 0xf245, + MOVE = 0xf256, + BRUSH = 0xf1fc, +}; + +constexpr static int Iconset[] = { + 0xf245, // REGULAR + 0xf256, // MOVE + 0xf1fc, // BRUSH +}; + +inline void DrawIcon(Icon icon, Vector2 position, size_t size, Color color = WHITE) { + DrawTextCodepoint(FontManager::IconFont(), static_cast(icon), position, size, color); +} + +inline void DrawIcon(Icon icon, int posX, int posY, size_t size, Color color = WHITE) { + DrawIcon(icon, {static_cast(posX), static_cast(posY)}, size, color); +} + +inline Vector2 MeasureIcon(Icon icon, size_t size) { + (void) icon; + return {static_cast(size), static_cast(size)}; +} + +} \ No newline at end of file diff --git a/src/gui/Panel.cpp b/src/gui/Panel.cpp new file mode 100644 index 0000000..d49475e --- /dev/null +++ b/src/gui/Panel.cpp @@ -0,0 +1,15 @@ +#include "Panel.hpp" +#include "util.hpp" + +namespace mcpaint::gui { + +void Panel::render(float deltaTime) { + Vector2 position = this->position.toPixels(); + Vector2 size = this->size.toPixels(); + + Rectangle rect = {position.x, position.y, size.x, size.y}; + DrawRectangleRec(rect, ColorFromHex(0x333333FF)); + DrawRectangleLinesEx(rect, 1, ColorFromHex(0x555555FF)); +} + +} \ No newline at end of file diff --git a/src/gui/Panel.hpp b/src/gui/Panel.hpp new file mode 100644 index 0000000..3b19ce4 --- /dev/null +++ b/src/gui/Panel.hpp @@ -0,0 +1,15 @@ +#pragma once + +#include "Element.hpp" + +namespace mcpaint::gui { + +class Panel : public Element { + public: + Panel(Vec2 position, Vec2 size) : Element(position, size) {} + virtual ~Panel() = default; + + void render(float deltaTime) override; +}; + +} \ No newline at end of file diff --git a/src/gui/Spacer.hpp b/src/gui/Spacer.hpp new file mode 100644 index 0000000..f537f35 --- /dev/null +++ b/src/gui/Spacer.hpp @@ -0,0 +1,42 @@ +#pragma once + +#include "View.hpp" + +namespace mcpaint::gui { + +class spacer : public view { + protected: + size_t thickness; + public: + spacer() : view(), thickness(1) { + this->spec_.display = Display::INLINE; + this->spec_.size = {1, 100.0f}; + this->spec_.padding = 5; + } + + virtual void render(float deltaTime) override { + bool horizontal = this->size_.x > this->size_.y; + + float middle = round(this->position_.x + this->size_.x / 2); + float padding = this->spec_.padding; + + if (horizontal) + DrawLineEx({this->position_.x + padding, middle}, {this->position_.x + this->size_.x - padding, middle}, 1, Theme::ELEMENT_BORDER); + else + DrawLineEx({middle, this->position_.y + padding}, {middle, this->position_.y + this->size_.y - padding}, 1, Theme::ELEMENT_BORDER); + } + + virtual inline size_t contentWidth() const override { + return this->spec_.padding * 2 + this->thickness; + } + + virtual inline Type type() const override { + return Type::SPACER; + } +}; + +inline spacer* Spacer() { + return new spacer(); +} + +} \ No newline at end of file diff --git a/src/gui/VStack.cpp b/src/gui/VStack.cpp new file mode 100644 index 0000000..cf7bedf --- /dev/null +++ b/src/gui/VStack.cpp @@ -0,0 +1,39 @@ +#include "VStack.hpp" + +namespace mcpaint::gui { + +void vstack::update(float deltaTime, const view* const parent) { + this->updateSelf(deltaTime, parent); + + float offset = this->spec_.padding; + float fullHeight = this->size_.y - this->spec_.padding * 2; + size_t fixedChildren = 0; + + for (const auto& child : this->children) { + const Spec& spec = child->spec(); + + if (std::holds_alternative(spec.size.second)) { + fullHeight -= std::get(spec.size.second); + fixedChildren++; + } + } + + for (const auto& child : this->children) { + const Spec& spec = child->spec(); + + float height = std::holds_alternative(spec.size.second) ? std::get(spec.size.second) : fullHeight / (this->children.size() - fixedChildren); + int width = this->size_.x - this->spec_.padding * 2; + + child->size_ = {static_cast(width), height}; + child->position({this->position_.x + this->spec_.padding, this->position_.y + offset}); + offset += height; + } + + this->updateChildren(deltaTime); +} + +void vstack::render(float deltaTime) { + view::render(deltaTime); +} + +} \ No newline at end of file diff --git a/src/gui/VStack.hpp b/src/gui/VStack.hpp new file mode 100644 index 0000000..d756504 --- /dev/null +++ b/src/gui/VStack.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include "View.hpp" + +namespace mcpaint::gui { + +class vstack : public view { + public: + using view::view; + + virtual void update(float deltaTime, const view* const parent = nullptr) override; + virtual void render(float deltaTime) override; + + virtual Type type() const override { + return Type::VSTACK; + } +}; + +inline vstack* VStack(std::initializer_list children = {}) { + return new vstack(children); +} + +} \ No newline at end of file diff --git a/src/gui/View.cpp b/src/gui/View.cpp new file mode 100644 index 0000000..219392c --- /dev/null +++ b/src/gui/View.cpp @@ -0,0 +1,66 @@ +#include "View.hpp" +#include "util.hpp" + +#include + +namespace mcpaint::gui { + +view::view(std::initializer_list children) : children(std::move(children)) { +} + +view::~view() { + for (auto& child : this->children) + delete child; +} + +void view::updateSelf(float deltaTime, const view* const parent) { + Vector2 parentSize = parent != nullptr ? parent->size() : Vector2{static_cast(GetScreenWidth()), static_cast(GetScreenHeight())}; + float parentPadding = parent != nullptr ? parent->spec().padding : 0; + + float width = std::holds_alternative(this->spec_.size.first) ? std::get(this->spec_.size.first) * parentSize.x / 100 : std::get(this->spec_.size.first); + float height = std::holds_alternative(this->spec_.size.second) ? std::get(this->spec_.size.second) * parentSize.y / 100 : std::get(this->spec_.size.second); + + width -= this->spec_.margin * 2; + height -= this->spec_.margin * 2; + + this->size_ = {width, height}; + this->margin_ = this->spec_.margin; +} + +void view::updateChildren(float deltaTime) { + for (auto& child : this->children) + child->update(deltaTime, this); +} + +void view::update(float deltaTime, const view* const parent) { + this->updateSelf(deltaTime, parent); + this->updateChildren(deltaTime); +} + +void view::render(float deltaTime) { + Vector2 position = this->position_; + position += this->margin_; + + DrawRectangleRounded({position.x, position.y, this->size_.x, this->size_.y}, this->roundness(), 0, this->spec_.background); + + if (this->spec_.border.has_value()) { + float borderWidth = this->spec_.border.value().width; + DrawRectangleRoundedLinesEx({position.x + borderWidth, position.y + borderWidth, this->size_.x - borderWidth * 2, this->size_.y - borderWidth * 2}, this->roundness(), 0, this->spec_.border.value().width, this->spec_.border.value().color); + } + + for (auto& child : this->children) + child->render(deltaTime); +} + +bool view::hovered() const { + Vector2 mouse = GetMousePosition(); + Rectangle bounds = {this->position_.x, this->position_.y, this->size_.x, this->size_.y}; + + return CheckCollisionPointRec(mouse, bounds); +} + +bool view::active() const { + return this->hovered() && IsMouseButtonDown(MOUSE_LEFT_BUTTON); +} + +} \ No newline at end of file diff --git a/src/gui/View.hpp b/src/gui/View.hpp new file mode 100644 index 0000000..4011fe8 --- /dev/null +++ b/src/gui/View.hpp @@ -0,0 +1,140 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +#include "theme.hpp" + +namespace mcpaint::gui { + +enum class Display { + INLINE, + BLOCK, + FLEX +}; + +struct Border { + Color color = Theme::ELEMENT_BORDER; + float width = 1; +}; + +using Length = std::variant; +using Tuple = std::pair; + +struct Spec { + Vector2 position = {0, 0}; + Tuple size = {100.0f, 100.0f}; + Color color = WHITE; + Color background = MAGENTA; + Color hoverBackground = Theme::TRANSPARENT; + Color hoverColor = color; + Color activeBackground = Theme::ELEMENT_ACTIVE; + float padding = 0; + float margin = 0; + float gap = 5; + std::optional border; + size_t fontSize = 12; + size_t radius = 0; + std::string font = "assets/fonts/sf-pro.otf"; + uint8_t flex = 1; + Display display = Display::FLEX; +}; + +class view { + protected: + std::vector children; + Spec spec_; + Vector2 position_; + float margin_; + + void updateSelf(float deltaTime, const view* const parent = nullptr); + void updateChildren(float deltaTime); + public: + enum class Type { + VIEW, + BUTTON, + HSTACK, + VSTACK, + SPACER, + ARTBOARDS + }; + Vector2 size_; + Vector2 renderSize; + + view(std::initializer_list children = {}); + virtual ~view(); + + virtual void update(float deltaTime, const view* const parent = nullptr); + virtual void render(float deltaTime); + + virtual bool hovered() const; + virtual bool active() const; + + virtual view* border(Border border) { + this->spec_.border = std::move(border); + + return this; + } + + virtual Type type() const { + return Type::VIEW; + } + + virtual size_t contentWidth() const { + return 0; + } + + inline float roundness() const { + return this->size_.x > this->size_.y ? this->spec_.radius / this->size_.y : this->spec_.radius / this->size_.x; + } + + inline const Spec& spec() const { + return this->spec_; + } + + inline Vector2 size() const { + return this->size_; + } + inline view* size(Tuple size) { + this->spec_.size = size; + return this; + } + + inline void position(Vector2 position) { + this->position_ = position; + } + inline Vector2 position() const { + return this->position_; + } + + inline view* margin(float margin) { + this->spec_.margin = margin; + return this; + } + + inline view* padding(float padding) { + this->spec_.padding = padding; + return this; + } + + inline view* background(Color color) { + this->spec_.background = color; + return this; + } + + view(const view&) = delete; + view& operator=(const view&) = delete; + + view(view&&) = delete; + view& operator=(view&&) = delete; +}; + +inline view* View(std::initializer_list children = {}) { + return new view(std::move(children)); +} + +} \ No newline at end of file diff --git a/src/gui/styleDark.hpp b/src/gui/styleDark.hpp new file mode 100644 index 0000000..a457e58 --- /dev/null +++ b/src/gui/styleDark.hpp @@ -0,0 +1,591 @@ +#pragma once + +////////////////////////////////////////////////////////////////////////////////// +// // +// StyleAsCode exporter v2.0 - Style data exported as a values array // +// // +// USAGE: On init call: GuiLoadStyleDark(); // +// // +// more info and bugs-report: github.com/raysan5/raygui // +// feedback and support: ray[at]raylibtech.com // +// // +// Copyright (c) 2020-2024 raylib technologies (@raylibtech) // +// // +////////////////////////////////////////////////////////////////////////////////// + +#define DARK_STYLE_PROPS_COUNT 23 + +// Custom style name: Dark +static const GuiStyleProp darkStyleProps[DARK_STYLE_PROPS_COUNT] = { + { 0, 0, 0x878787ff }, // DEFAULT_BORDER_COLOR_NORMAL + { 0, 1, 0x2c2c2cff }, // DEFAULT_BASE_COLOR_NORMAL + { 0, 2, 0xc3c3c3ff }, // DEFAULT_TEXT_COLOR_NORMAL + { 0, 3, 0xe1e1e1ff }, // DEFAULT_BORDER_COLOR_FOCUSED + { 0, 4, 0x848484ff }, // DEFAULT_BASE_COLOR_FOCUSED + { 0, 5, 0x181818ff }, // DEFAULT_TEXT_COLOR_FOCUSED + { 0, 6, 0x000000ff }, // DEFAULT_BORDER_COLOR_PRESSED + { 0, 7, 0xefefefff }, // DEFAULT_BASE_COLOR_PRESSED + { 0, 8, 0x202020ff }, // DEFAULT_TEXT_COLOR_PRESSED + { 0, 9, 0x6a6a6aff }, // DEFAULT_BORDER_COLOR_DISABLED + { 0, 10, 0x818181ff }, // DEFAULT_BASE_COLOR_DISABLED + { 0, 11, 0x606060ff }, // DEFAULT_TEXT_COLOR_DISABLED + { 0, 16, 0x00000010 }, // DEFAULT_TEXT_SIZE + { 0, 17, 0x00000000 }, // DEFAULT_TEXT_SPACING + { 0, 18, 0x9d9d9dff }, // DEFAULT_LINE_COLOR + { 0, 19, 0x3c3c3cff }, // DEFAULT_BACKGROUND_COLOR + { 0, 20, 0x00000018 }, // DEFAULT_TEXT_LINE_SPACING + { 1, 5, 0xf7f7f7ff }, // LABEL_TEXT_COLOR_FOCUSED + { 1, 8, 0x898989ff }, // LABEL_TEXT_COLOR_PRESSED + { 4, 5, 0xb0b0b0ff }, // SLIDER_TEXT_COLOR_FOCUSED + { 5, 5, 0x848484ff }, // PROGRESSBAR_TEXT_COLOR_FOCUSED + { 9, 5, 0xf5f5f5ff }, // TEXTBOX_TEXT_COLOR_FOCUSED + { 10, 5, 0xf6f6f6ff }, // VALUEBOX_TEXT_COLOR_FOCUSED +}; + +// WARNING: This style uses a custom font: "PixelOperator.ttf" (size: 16, spacing: 0) + +#define DARK_STYLE_FONT_ATLAS_COMP_SIZE 2126 + +// Font atlas image pixels data: DEFLATE compressed +static unsigned char darkFontData[DARK_STYLE_FONT_ATLAS_COMP_SIZE] = { 0xed, + 0xdd, 0xdb, 0x72, 0xa4, 0x3a, 0x12, 0x05, 0x50, 0xfd, 0xff, 0x4f, 0xe7, 0x3c, 0x4c, 0x4c, 0x4c, 0x74, 0x9c, 0xd3, 0x20, + 0xa5, 0x52, 0x17, 0xec, 0xd5, 0xeb, 0xcd, 0xe5, 0x76, 0x51, 0xa0, 0x94, 0x84, 0x28, 0x36, 0xd1, 0x00, 0x00, 0x00, 0x80, + 0x5f, 0x2f, 0xfe, 0xf5, 0x27, 0xf1, 0xd7, 0xdf, 0x8c, 0xee, 0xbf, 0xf3, 0xfc, 0xf3, 0xff, 0xbd, 0x1a, 0x0f, 0xef, 0xd5, + 0xb7, 0xad, 0xa3, 0xef, 0x1b, 0x03, 0x7b, 0xe2, 0xdf, 0xb7, 0x2f, 0xba, 0xff, 0xee, 0xdf, 0x3e, 0xdf, 0xf8, 0xef, 0x3f, + 0xfd, 0xa5, 0xe7, 0xad, 0x8f, 0xa1, 0xfd, 0x3e, 0xfe, 0x7f, 0xc6, 0x8e, 0x62, 0x2c, 0xd9, 0xf7, 0xef, 0x5b, 0x37, 0xbe, + 0xed, 0x95, 0xff, 0x27, 0x1e, 0x3e, 0x4f, 0xe6, 0x28, 0xf5, 0xd4, 0xd6, 0x0d, 0xf5, 0x1f, 0x5d, 0x95, 0x18, 0xa5, 0x2d, + 0xe7, 0xff, 0xef, 0x1a, 0x85, 0x3d, 0x55, 0x76, 0x4f, 0x3e, 0x55, 0xfa, 0xf8, 0xfe, 0x78, 0x6a, 0xfd, 0xe3, 0x3d, 0x60, + 0x94, 0x7c, 0x96, 0xf9, 0xd6, 0x18, 0xd3, 0xbf, 0xdd, 0xd7, 0x92, 0x6a, 0x3e, 0xd5, 0xcc, 0x2b, 0xad, 0xe4, 0x28, 0x9d, + 0xa8, 0xff, 0x48, 0xf7, 0x54, 0x31, 0x58, 0xd1, 0x15, 0x7b, 0x30, 0xd3, 0x0f, 0xb7, 0x8d, 0xf5, 0x1f, 0xa5, 0x73, 0x97, + 0x28, 0x6b, 0x73, 0x27, 0xea, 0xff, 0x79, 0xd4, 0x6e, 0x25, 0xed, 0x26, 0x5e, 0xf6, 0x51, 0x6d, 0x2d, 0xaf, 0x9d, 0xa7, + 0xae, 0xae, 0xff, 0xe7, 0xdf, 0x1c, 0x1d, 0x6f, 0x63, 0x70, 0xec, 0xae, 0xd8, 0x4f, 0xb9, 0xf1, 0xbf, 0x7e, 0x3f, 0xc6, + 0x5f, 0xc7, 0xe6, 0xec, 0x3c, 0x64, 0x64, 0x0f, 0xc7, 0xe0, 0xd9, 0xd5, 0xec, 0x08, 0x7b, 0x72, 0xfc, 0xef, 0x9b, 0x0b, + 0xaa, 0xff, 0xb5, 0xf5, 0x9f, 0xf9, 0x24, 0xd1, 0xb9, 0x05, 0x99, 0x31, 0xb1, 0x5d, 0x50, 0xff, 0xa3, 0xfd, 0xd0, 0xf3, + 0xbe, 0xaa, 0x9a, 0xcb, 0x8f, 0xae, 0x4b, 0xf4, 0x9d, 0x61, 0xef, 0x6b, 0x85, 0xe3, 0x73, 0xa3, 0xf1, 0xfa, 0x1f, 0xef, + 0x3d, 0xdf, 0xfe, 0xda, 0xe8, 0x5e, 0xfd, 0xfb, 0x99, 0xdd, 0xfc, 0x1e, 0xdf, 0x57, 0xff, 0x91, 0x18, 0x53, 0xce, 0xd7, + 0x73, 0x4d, 0xfd, 0x47, 0x62, 0xe5, 0xa2, 0x95, 0xad, 0xf2, 0xe5, 0xd6, 0x25, 0xea, 0xd6, 0x0c, 0xce, 0x1f, 0x81, 0xf7, + 0xfa, 0x7f, 0x3b, 0x1f, 0x3c, 0x3f, 0xfe, 0xc7, 0x15, 0xe3, 0x7f, 0xa4, 0xd7, 0x86, 0x5b, 0xa2, 0xf7, 0xfd, 0x5a, 0xfd, + 0x47, 0xa2, 0x66, 0xa2, 0xe4, 0xbc, 0xbc, 0x2d, 0x59, 0xcb, 0xab, 0x5d, 0x33, 0xdc, 0x73, 0xb4, 0xde, 0x46, 0xd1, 0xaa, + 0xb3, 0x9a, 0x9f, 0x55, 0xff, 0xad, 0x60, 0xfc, 0xef, 0x9b, 0x03, 0xcc, 0x7e, 0x8e, 0xf8, 0xd8, 0xe8, 0x5f, 0x59, 0xff, + 0xbb, 0x56, 0xec, 0xd7, 0xb7, 0xc6, 0xb8, 0xe2, 0xc8, 0x58, 0xff, 0xaf, 0x9c, 0xff, 0xe7, 0xd7, 0x00, 0xc6, 0xce, 0x63, + 0xe2, 0xd2, 0xea, 0xcf, 0x9c, 0x33, 0x57, 0x5d, 0xb1, 0xaf, 0xfd, 0x36, 0x41, 0x24, 0xbe, 0xab, 0x51, 0xb3, 0x8a, 0xb3, + 0xfa, 0x18, 0x8c, 0x8f, 0xff, 0xbb, 0xae, 0xff, 0xbf, 0xcf, 0xb9, 0xef, 0x18, 0xff, 0xdb, 0xeb, 0xe8, 0x7e, 0xcb, 0xf6, + 0x00, 0x7b, 0x7b, 0x80, 0x50, 0xfd, 0xe0, 0x7b, 0xc4, 0x80, 0xfa, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0a, 0xbf, 0x9f, 0x5f, 0x9f, 0x63, 0x30, 0x9e, 0x84, 0xbd, 0x3e, 0x81, 0x7d, 0x26, 0x13, 0x38, 0xbb, + 0x87, 0xaa, 0xfe, 0xe2, 0x73, 0x76, 0xfc, 0x48, 0xd2, 0x42, 0x7f, 0xcb, 0x88, 0xe1, 0xa7, 0x1f, 0x54, 0x26, 0x0a, 0x64, + 0x32, 0x0d, 0xda, 0x60, 0x9b, 0xa8, 0xcd, 0x52, 0x1a, 0xdb, 0xfa, 0x3d, 0x2d, 0xfe, 0x0b, 0xf5, 0x7f, 0xfe, 0x95, 0x96, + 0xc8, 0xef, 0xd9, 0x59, 0xff, 0xa3, 0x6d, 0x2f, 0x97, 0x8f, 0x3b, 0x37, 0x96, 0xec, 0x4e, 0x14, 0x8b, 0xc2, 0x63, 0xb8, + 0x6f, 0x5c, 0xfd, 0x33, 0x43, 0x67, 0x47, 0xbb, 0x9e, 0xa9, 0xff, 0xd1, 0xec, 0xd3, 0x78, 0xe8, 0x85, 0xef, 0xa9, 0xff, + 0xb6, 0xa5, 0xfe, 0xe3, 0x23, 0xf5, 0x5f, 0x9d, 0x24, 0x53, 0x95, 0x42, 0x9e, 0x49, 0xbe, 0x19, 0x3f, 0x86, 0xf9, 0x84, + 0xdf, 0x6c, 0x8b, 0xfb, 0x4e, 0xfd, 0x67, 0xda, 0xd6, 0x73, 0xce, 0xaa, 0xfa, 0x7f, 0xdf, 0xb7, 0x99, 0xd1, 0x64, 0xfe, + 0xe7, 0x35, 0x95, 0xbf, 0x27, 0x47, 0xf7, 0xed, 0x39, 0x5a, 0x6b, 0xdb, 0xca, 0xec, 0x58, 0xf9, 0x95, 0xfa, 0x8f, 0xe4, + 0x5f, 0x89, 0x97, 0x1e, 0xa5, 0x36, 0x81, 0xbd, 0x26, 0xb5, 0x6d, 0x6f, 0xfd, 0x57, 0x3f, 0xf7, 0xe7, 0x8e, 0xfa, 0x3f, + 0x9f, 0xa3, 0xbb, 0xea, 0x1c, 0xae, 0x76, 0xac, 0xfc, 0xd9, 0xe3, 0xff, 0x7b, 0x2f, 0xb9, 0xa3, 0x7d, 0xcc, 0x8c, 0xf4, + 0x27, 0xc7, 0xff, 0x73, 0x3f, 0x3f, 0x5b, 0xff, 0x55, 0xad, 0x3d, 0x36, 0xce, 0x4c, 0xb2, 0x63, 0xe5, 0xce, 0x55, 0xb2, + 0xdd, 0xe7, 0xff, 0xab, 0x3e, 0x59, 0x1b, 0x9e, 0x4d, 0xc4, 0xb5, 0xf5, 0x3f, 0xb3, 0x0a, 0xb9, 0x6e, 0xbe, 0x70, 0x66, + 0xfe, 0x9f, 0x7b, 0xbe, 0x6d, 0xe6, 0xa9, 0x80, 0xb7, 0x8d, 0xff, 0xbb, 0xae, 0x92, 0xb5, 0xcd, 0x35, 0xb9, 0xf7, 0xbd, + 0x2a, 0x9f, 0x52, 0x37, 0x9e, 0xdf, 0x1f, 0xc5, 0x33, 0xbc, 0xaf, 0xd7, 0x7f, 0x7e, 0x95, 0xbf, 0x15, 0xad, 0x4a, 0x9e, + 0x9b, 0xff, 0xef, 0x7e, 0xd2, 0x49, 0xe6, 0x5d, 0x6a, 0xfa, 0xdf, 0xbe, 0xab, 0xc2, 0xb5, 0xa3, 0xc0, 0xdf, 0xaf, 0x36, + 0x44, 0xd1, 0xc8, 0x51, 0x95, 0xdf, 0xff, 0xe7, 0xb6, 0x8d, 0x3f, 0xf1, 0x6c, 0xfc, 0x4a, 0x7c, 0x0c, 0x3e, 0x4f, 0xff, + 0x44, 0xfd, 0x67, 0xde, 0x39, 0xf3, 0xbf, 0x46, 0x8f, 0x61, 0x65, 0xfd, 0x9f, 0xeb, 0x01, 0xe4, 0x6e, 0xc2, 0x8d, 0xb3, + 0x18, 0xe0, 0xe7, 0xf4, 0x00, 0x9e, 0x70, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xec, 0xbe, 0x13, 0xfb, 0xef, 0xd9, 0x5c, 0x99, 0xd4, 0xf8, 0xf1, 0xfb, 0xa4, 0x77, 0x26, 0xe6, 0xb7, 0x97, 0x14, 0xb2, + 0xe7, 0xdf, 0xfa, 0xf3, 0x95, 0x8a, 0x3c, 0xde, 0x28, 0xbc, 0x6b, 0xfd, 0x29, 0x93, 0xe4, 0x39, 0x4b, 0x71, 0x34, 0x77, + 0xe0, 0x7d, 0x0f, 0x8f, 0x1f, 0x97, 0x99, 0xd7, 0x5a, 0x61, 0x9a, 0x42, 0x24, 0xd2, 0x5e, 0xde, 0xf6, 0x7a, 0x7f, 0x36, + 0x70, 0x94, 0x6d, 0xf1, 0x58, 0x1d, 0x55, 0x65, 0x27, 0xdf, 0x9e, 0x98, 0x3f, 0x9f, 0xbc, 0x13, 0x2f, 0xad, 0xae, 0xbf, + 0xfe, 0x7b, 0x92, 0x23, 0xd6, 0xe7, 0x18, 0xf5, 0xfc, 0x34, 0x93, 0x7a, 0x31, 0x96, 0xc1, 0x36, 0xd7, 0x06, 0x56, 0x8f, + 0x50, 0x6d, 0xb2, 0x42, 0x62, 0xaa, 0xa5, 0xcc, 0x67, 0xff, 0xbd, 0x6f, 0x69, 0x1b, 0x1c, 0xb9, 0x6e, 0x48, 0xcc, 0x8c, + 0xce, 0xfa, 0xaa, 0xfe, 0x69, 0x1b, 0xec, 0x6f, 0x32, 0x79, 0x75, 0x51, 0x9a, 0x44, 0x91, 0xff, 0x3f, 0x91, 0x48, 0x6d, + 0x6e, 0xc9, 0x2c, 0xbe, 0x7c, 0x46, 0x7c, 0x26, 0xa7, 0x2a, 0x16, 0xef, 0xd9, 0x4c, 0xfd, 0xb7, 0x43, 0xf5, 0x9f, 0x49, + 0x3d, 0x38, 0x9f, 0x98, 0x1d, 0xa9, 0xda, 0xdd, 0x5b, 0xff, 0xd1, 0xd1, 0x7f, 0x65, 0x66, 0xd7, 0x51, 0x78, 0xce, 0xf0, + 0x3e, 0xe3, 0xad, 0x1e, 0xff, 0xdb, 0xe3, 0x7e, 0x1a, 0x4f, 0x75, 0x5b, 0x3f, 0x42, 0x65, 0x7a, 0x93, 0xb1, 0xfa, 0x5f, + 0xdd, 0x63, 0xcd, 0x3c, 0x07, 0x29, 0x3e, 0x37, 0xfe, 0x9f, 0x49, 0xcc, 0x8e, 0xc4, 0xd9, 0x75, 0xe6, 0x7d, 0xeb, 0xd7, + 0x5e, 0xa2, 0xb0, 0xfe, 0x33, 0x3d, 0x40, 0xbe, 0xfe, 0x77, 0xce, 0xa6, 0xb3, 0x79, 0x93, 0x31, 0xdd, 0x86, 0xce, 0xd4, + 0x7f, 0xe5, 0xd3, 0x96, 0x56, 0x24, 0xe6, 0x8e, 0x3f, 0xd9, 0xf1, 0xd4, 0xf8, 0xdf, 0x52, 0xe3, 0x7f, 0x6e, 0x9c, 0xa8, + 0x3b, 0xf6, 0xb5, 0x73, 0xe5, 0xf7, 0xfa, 0x8f, 0x0d, 0xef, 0xb6, 0xaf, 0xfe, 0x33, 0x3d, 0x61, 0x2c, 0x9b, 0xff, 0x67, + 0xab, 0x25, 0x86, 0xe7, 0xd7, 0x3b, 0x13, 0x73, 0x33, 0xeb, 0xcc, 0xf7, 0xd7, 0x7f, 0xe5, 0x33, 0x4c, 0xda, 0x54, 0xfa, + 0x72, 0x94, 0x8e, 0xc8, 0xfb, 0xc6, 0xff, 0x15, 0xb3, 0xe9, 0x4c, 0xfa, 0xfe, 0x3d, 0xeb, 0x7f, 0xad, 0xf8, 0x88, 0xb5, + 0xe3, 0x79, 0x88, 0x2b, 0x66, 0x85, 0x27, 0xce, 0xff, 0xab, 0x12, 0xd8, 0x73, 0xe7, 0xff, 0xd5, 0x2b, 0xf2, 0x73, 0xc7, + 0xf2, 0xde, 0xf1, 0x3f, 0xd7, 0x42, 0x62, 0x68, 0x7c, 0x6e, 0x9f, 0xaa, 0xff, 0x5b, 0xbe, 0xd1, 0x50, 0xd1, 0x6f, 0x45, + 0x49, 0xef, 0x96, 0x79, 0x6e, 0x4b, 0xe5, 0x3c, 0xaa, 0x72, 0xfd, 0x6a, 0xe6, 0xfa, 0xff, 0xcc, 0xb7, 0x53, 0x56, 0xbf, + 0x5b, 0xfe, 0xfa, 0xff, 0xda, 0xfa, 0x8f, 0xe2, 0x2d, 0xe6, 0x9e, 0x5e, 0xea, 0xe6, 0xf7, 0xd3, 0x7e, 0xee, 0x38, 0x82, + 0x6a, 0x59, 0xeb, 0x39, 0x71, 0x3e, 0xc4, 0xef, 0x9a, 0x33, 0xf3, 0xd3, 0xbf, 0xe1, 0x6d, 0x3f, 0x18, 0x9b, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xef, 0xde, 0xc3, 0x14, 0xaf, 0x77, 0x38, 0xbc, 0x65, 0x4b, + 0x64, 0x72, 0x29, 0x5b, 0x69, 0xce, 0x5d, 0x4b, 0x24, 0xf3, 0x67, 0xb7, 0xae, 0x77, 0xaf, 0xac, 0xff, 0x64, 0xb3, 0x69, + 0xe6, 0x99, 0xc4, 0xf9, 0xcc, 0x3e, 0x3e, 0x7b, 0x34, 0xdf, 0x32, 0x3c, 0x22, 0x91, 0xc6, 0x5a, 0x79, 0xbc, 0x5a, 0x6a, + 0xdf, 0x65, 0x5b, 0x59, 0x6f, 0x0f, 0xd0, 0x9f, 0x0f, 0x53, 0x7f, 0x8f, 0x69, 0xa4, 0xf6, 0x79, 0x4d, 0x32, 0xff, 0x4c, + 0x5b, 0x6a, 0xe9, 0x04, 0xe2, 0x6c, 0xab, 0xe9, 0xfd, 0x5b, 0x31, 0xfd, 0x97, 0xdf, 0xb3, 0x5a, 0xe3, 0x73, 0x47, 0x33, + 0x9b, 0x17, 0x5f, 0x7d, 0xbc, 0x6a, 0xd3, 0xdb, 0x6a, 0x7a, 0x80, 0x8a, 0xfa, 0xaf, 0xdb, 0xca, 0xfd, 0xf7, 0xc6, 0x46, + 0xf2, 0x7e, 0xfa, 0xf8, 0xfc, 0xfd, 0xa7, 0xf1, 0xd1, 0x24, 0x81, 0x5c, 0xca, 0xe4, 0xae, 0x4f, 0x95, 0xcb, 0xe5, 0xca, + 0xa7, 0xb7, 0xed, 0x1c, 0xff, 0x33, 0x49, 0x52, 0x99, 0xb4, 0xd0, 0xea, 0x57, 0xb2, 0xbd, 0x65, 0xae, 0xfe, 0x33, 0x99, + 0x4d, 0x51, 0x94, 0x67, 0x5c, 0xf7, 0xdc, 0x93, 0x48, 0xce, 0xaf, 0x4f, 0x1e, 0xcd, 0x78, 0x4d, 0x25, 0xaf, 0xca, 0xd8, + 0xdd, 0xfb, 0x4a, 0x4c, 0x26, 0x3e, 0x44, 0xd7, 0xf1, 0x8e, 0xe9, 0xb1, 0x70, 0xd7, 0xd3, 0x02, 0x33, 0xcf, 0xa4, 0x68, + 0xc9, 0xd4, 0xcc, 0x28, 0x9b, 0xe1, 0x57, 0xbf, 0xb2, 0xa2, 0xfe, 0xe3, 0xe1, 0x3c, 0xb9, 0xfa, 0x99, 0x65, 0xd5, 0x47, + 0xb3, 0xa7, 0x67, 0xf8, 0x62, 0xfd, 0xaf, 0x9d, 0xa7, 0xd5, 0x9c, 0xff, 0x47, 0xfa, 0x59, 0x3c, 0x77, 0xb6, 0x98, 0xe8, + 0x4c, 0x77, 0xfe, 0x69, 0xf5, 0xbf, 0x77, 0x1f, 0x57, 0xf7, 0xe6, 0xcf, 0x33, 0xec, 0xf6, 0xd1, 0xfa, 0x9f, 0x49, 0x8b, + 0xaf, 0x39, 0x5f, 0x79, 0x5f, 0xff, 0xaf, 0x5c, 0xd9, 0xb8, 0xa3, 0xfe, 0x6f, 0xa9, 0xf2, 0xb1, 0x7d, 0xbe, 0xb6, 0xfe, + 0xcf, 0xd7, 0xd0, 0x6c, 0xf2, 0xfb, 0xf9, 0x6d, 0x8f, 0xb2, 0xf3, 0xff, 0x9a, 0x75, 0xa1, 0xea, 0x79, 0xc4, 0x6d, 0x3d, + 0xe8, 0xaa, 0xa7, 0xab, 0xbd, 0xcd, 0x1d, 0xaa, 0xcf, 0x77, 0xef, 0x18, 0xff, 0x43, 0xfd, 0x2f, 0x58, 0x0b, 0xaf, 0x1d, + 0x25, 0xf3, 0x2b, 0xcc, 0x33, 0xfd, 0xc9, 0xf8, 0xb3, 0xec, 0x6b, 0x57, 0xc9, 0x32, 0x7d, 0x68, 0xcf, 0x2b, 0xf9, 0x27, + 0x6e, 0x7c, 0x75, 0xfe, 0xdf, 0xf3, 0x54, 0xa0, 0x6f, 0xd5, 0x7f, 0x24, 0xd7, 0xb7, 0xee, 0xa8, 0xff, 0xb5, 0x57, 0x06, + 0xd6, 0x5f, 0xcb, 0xbf, 0x79, 0xfe, 0xbf, 0xa2, 0xcf, 0xfb, 0x76, 0xfd, 0x7f, 0x61, 0x0e, 0xbd, 0xe6, 0x5b, 0x28, 0xe7, + 0xea, 0x7f, 0x6e, 0xdc, 0x56, 0xff, 0x2b, 0x56, 0x8c, 0xf3, 0x9f, 0x7a, 0xc5, 0xf9, 0x7f, 0xef, 0x4c, 0xe3, 0xe7, 0xd7, + 0x7f, 0x7d, 0xd2, 0xf9, 0x9a, 0xf3, 0xcd, 0x76, 0xe9, 0x77, 0x61, 0xee, 0xfa, 0x4e, 0xf2, 0x9e, 0x16, 0xb3, 0x66, 0xed, + 0x23, 0xf3, 0x94, 0xde, 0xda, 0xa7, 0x39, 0xc5, 0xa2, 0x4a, 0xcf, 0x5d, 0xe5, 0xdd, 0x73, 0xfd, 0x7f, 0xef, 0x37, 0x8a, + 0xaa, 0xb7, 0x50, 0xfd, 0x7f, 0xa3, 0x0f, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xdb, + 0xee, 0xd0, 0xdb, 0x9b, 0xa8, 0x5f, 0x9f, 0x82, 0x71, 0x7b, 0xa2, 0xfe, 0xdb, 0x5d, 0x33, 0xed, 0xda, 0x44, 0xfd, 0xd6, + 0x95, 0x4c, 0xf4, 0xbd, 0x44, 0xfd, 0xdf, 0x78, 0xc7, 0xc7, 0x6d, 0x89, 0xfa, 0x75, 0x77, 0x4e, 0xdf, 0x9e, 0xa8, 0xdf, + 0x5e, 0xf2, 0x87, 0x6e, 0x4e, 0xd4, 0xcf, 0xdf, 0x3b, 0x75, 0x6b, 0xa2, 0x3e, 0x6b, 0xef, 0x98, 0xec, 0xed, 0xfb, 0xe3, + 0xe0, 0x31, 0x5b, 0x75, 0x77, 0x69, 0x7c, 0xf4, 0xce, 0xcf, 0xf1, 0x8c, 0xa6, 0x15, 0x3d, 0x4a, 0xe5, 0x5d, 0x9a, 0xeb, + 0x13, 0xf5, 0x7f, 0x4a, 0xbd, 0xee, 0x4a, 0xd4, 0x7f, 0xcf, 0x19, 0x8b, 0x4d, 0xdb, 0x1f, 0x43, 0xf3, 0xc6, 0xb5, 0x89, + 0x5a, 0xcf, 0xfd, 0xe8, 0xbd, 0xcf, 0x47, 0xf8, 0x76, 0xa2, 0xf6, 0x6f, 0xab, 0xff, 0x55, 0xfb, 0x29, 0x8a, 0xaa, 0xae, + 0xf7, 0x95, 0x7d, 0x59, 0x41, 0x75, 0xf5, 0x1f, 0xe5, 0xaf, 0xed, 0x4d, 0xd4, 0xca, 0xae, 0x27, 0xa8, 0xff, 0xef, 0xac, + 0x01, 0xe4, 0xd6, 0xad, 0xe6, 0x12, 0x75, 0x4f, 0xb6, 0x80, 0x9d, 0x89, 0x5a, 0x5f, 0xaf, 0xff, 0xcc, 0xac, 0x5c, 0xfd, + 0xdf, 0x39, 0xff, 0x8f, 0xb2, 0x57, 0x32, 0xbd, 0x46, 0x7e, 0xfd, 0xff, 0xcb, 0x4f, 0xd4, 0xfa, 0x99, 0xf5, 0x7f, 0x47, + 0xa2, 0xae, 0xfa, 0x3f, 0x33, 0xff, 0x5f, 0xf7, 0x54, 0x82, 0x9d, 0x89, 0xba, 0xc6, 0xff, 0x55, 0x15, 0x71, 0x77, 0x95, + 0xdf, 0x95, 0x9b, 0xfb, 0xcd, 0xf3, 0xff, 0xdc, 0x93, 0x40, 0xb3, 0x3d, 0xc0, 0xbe, 0x84, 0xd6, 0x13, 0x89, 0xfa, 0x12, + 0x75, 0x67, 0x8e, 0xd7, 0xf3, 0xec, 0xef, 0x9b, 0xd7, 0x63, 0x6e, 0x9f, 0xff, 0xd7, 0x5e, 0xab, 0xf9, 0xe7, 0x9a, 0xd2, + 0xea, 0x15, 0xef, 0x55, 0xf3, 0xff, 0xda, 0x2b, 0x5b, 0x12, 0x75, 0xab, 0x8f, 0xda, 0x6f, 0x5f, 0xff, 0x3b, 0xdb, 0xd3, + 0xc0, 0xee, 0x79, 0xed, 0xf9, 0x9e, 0x10, 0xf8, 0xda, 0x37, 0xb9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0xf9, 0xef, 0x3f, 0xfb, 0x01, 0xd4, 0x3f, + 0xf0, 0xeb, 0xea, 0xff, 0x3f }; + +// Font glyphs rectangles data (on atlas) +static const Rectangle darkFontRecs[189] = { + { 4, 4, 4 , 16 }, + { 16, 4, 1 , 9 }, + { 25, 4, 3 , 3 }, + { 36, 4, 6 , 9 }, + { 50, 4, 5 , 13 }, + { 63, 4, 7 , 9 }, + { 78, 4, 5 , 9 }, + { 91, 4, 1 , 3 }, + { 100, 4, 3 , 9 }, + { 111, 4, 3 , 9 }, + { 122, 4, 5 , 5 }, + { 135, 4, 5 , 5 }, + { 148, 4, 2 , 3 }, + { 158, 4, 4 , 1 }, + { 170, 4, 1 , 1 }, + { 179, 4, 3 , 9 }, + { 190, 4, 5 , 9 }, + { 203, 4, 3 , 9 }, + { 214, 4, 5 , 9 }, + { 227, 4, 5 , 9 }, + { 240, 4, 5 , 9 }, + { 253, 4, 5 , 9 }, + { 266, 4, 5 , 9 }, + { 279, 4, 5 , 9 }, + { 292, 4, 5 , 9 }, + { 305, 4, 5 , 9 }, + { 318, 4, 1 , 7 }, + { 327, 4, 2 , 9 }, + { 337, 4, 3 , 5 }, + { 348, 4, 4 , 3 }, + { 360, 4, 3 , 5 }, + { 371, 4, 5 , 9 }, + { 384, 4, 7 , 9 }, + { 399, 4, 5 , 9 }, + { 412, 4, 5 , 9 }, + { 425, 4, 5 , 9 }, + { 438, 4, 5 , 9 }, + { 451, 4, 5 , 9 }, + { 464, 4, 5 , 9 }, + { 477, 4, 5 , 9 }, + { 490, 4, 5 , 9 }, + { 4, 28, 1 , 9 }, + { 13, 28, 5 , 9 }, + { 26, 28, 5 , 9 }, + { 39, 28, 5 , 9 }, + { 52, 28, 7 , 9 }, + { 67, 28, 5 , 9 }, + { 80, 28, 5 , 9 }, + { 93, 28, 5 , 9 }, + { 106, 28, 5 , 9 }, + { 119, 28, 5 , 9 }, + { 132, 28, 5 , 9 }, + { 145, 28, 5 , 9 }, + { 158, 28, 5 , 9 }, + { 171, 28, 5 , 9 }, + { 184, 28, 7 , 9 }, + { 199, 28, 5 , 9 }, + { 212, 28, 5 , 9 }, + { 225, 28, 5 , 9 }, + { 238, 28, 3 , 9 }, + { 249, 28, 3 , 9 }, + { 260, 28, 3 , 9 }, + { 271, 28, 5 , 3 }, + { 284, 28, 5 , 1 }, + { 297, 28, 2 , 2 }, + { 307, 28, 5 , 7 }, + { 320, 28, 5 , 9 }, + { 333, 28, 5 , 7 }, + { 346, 28, 5 , 9 }, + { 359, 28, 5 , 7 }, + { 372, 28, 4 , 9 }, + { 384, 28, 5 , 9 }, + { 397, 28, 5 , 9 }, + { 410, 28, 1 , 9 }, + { 419, 28, 5 , 11 }, + { 432, 28, 5 , 9 }, + { 445, 28, 2 , 9 }, + { 455, 28, 7 , 7 }, + { 470, 28, 5 , 7 }, + { 483, 28, 5 , 7 }, + { 496, 28, 5 , 9 }, + { 4, 52, 5 , 9 }, + { 17, 52, 5 , 7 }, + { 30, 52, 5 , 7 }, + { 43, 52, 4 , 8 }, + { 55, 52, 5 , 7 }, + { 68, 52, 5 , 7 }, + { 81, 52, 7 , 7 }, + { 96, 52, 5 , 7 }, + { 109, 52, 5 , 9 }, + { 122, 52, 5 , 7 }, + { 135, 52, 4 , 9 }, + { 147, 52, 1 , 9 }, + { 156, 52, 4 , 9 }, + { 168, 52, 6 , 2 }, + { 182, 52, 1 , 9 }, + { 191, 52, 5 , 11 }, + { 204, 52, 6 , 9 }, + { 218, 52, 6 , 9 }, + { 232, 52, 5 , 9 }, + { 245, 52, 5 , 12 }, + { 258, 52, 5 , 9 }, + { 271, 52, 5 , 10 }, + { 284, 52, 7 , 9 }, + { 299, 52, 5 , 9 }, + { 312, 52, 6 , 5 }, + { 326, 52, 5 , 3 }, + { 339, 52, 7 , 9 }, + { 354, 52, 5 , 9 }, + { 367, 52, 4 , 4 }, + { 379, 52, 5 , 7 }, + { 392, 52, 5 , 9 }, + { 405, 52, 5 , 9 }, + { 418, 52, 5 , 12 }, + { 431, 52, 5 , 9 }, + { 444, 52, 7 , 9 }, + { 459, 52, 1 , 1 }, + { 468, 52, 5 , 10 }, + { 481, 52, 5 , 9 }, + { 494, 52, 5 , 9 }, + { 4, 76, 6 , 5 }, + { 18, 76, 9 , 9 }, + { 35, 76, 9 , 7 }, + { 52, 76, 5 , 11 }, + { 65, 76, 5 , 9 }, + { 78, 76, 5 , 12 }, + { 91, 76, 5 , 12 }, + { 104, 76, 5 , 12 }, + { 117, 76, 6 , 12 }, + { 131, 76, 5 , 11 }, + { 144, 76, 5 , 13 }, + { 157, 76, 9 , 9 }, + { 174, 76, 5 , 12 }, + { 187, 76, 5 , 12 }, + { 200, 76, 5 , 12 }, + { 213, 76, 5 , 12 }, + { 226, 76, 5 , 11 }, + { 239, 76, 2 , 12 }, + { 249, 76, 2 , 12 }, + { 259, 76, 3 , 12 }, + { 270, 76, 3 , 11 }, + { 281, 76, 6 , 9 }, + { 295, 76, 6 , 12 }, + { 309, 76, 5 , 12 }, + { 322, 76, 5 , 12 }, + { 335, 76, 5 , 12 }, + { 348, 76, 6 , 12 }, + { 362, 76, 5 , 11 }, + { 375, 76, 5 , 5 }, + { 388, 76, 7 , 9 }, + { 403, 76, 5 , 12 }, + { 416, 76, 5 , 12 }, + { 429, 76, 5 , 12 }, + { 442, 76, 5 , 11 }, + { 455, 76, 5 , 12 }, + { 468, 76, 5 , 9 }, + { 481, 76, 5 , 9 }, + { 494, 76, 5 , 10 }, + { 4, 100, 5 , 10 }, + { 17, 100, 5 , 10 }, + { 30, 100, 6 , 10 }, + { 44, 100, 5 , 9 }, + { 57, 100, 5 , 11 }, + { 70, 100, 9 , 7 }, + { 87, 100, 5 , 10 }, + { 100, 100, 5 , 10 }, + { 113, 100, 5 , 10 }, + { 126, 100, 5 , 10 }, + { 139, 100, 5 , 9 }, + { 152, 100, 2 , 10 }, + { 162, 100, 2 , 10 }, + { 172, 100, 3 , 10 }, + { 183, 100, 3 , 9 }, + { 194, 100, 6 , 9 }, + { 208, 100, 6 , 10 }, + { 222, 100, 5 , 10 }, + { 235, 100, 5 , 10 }, + { 248, 100, 5 , 10 }, + { 261, 100, 6 , 10 }, + { 275, 100, 5 , 9 }, + { 288, 100, 5 , 5 }, + { 301, 100, 7 , 7 }, + { 316, 100, 5 , 10 }, + { 329, 100, 5 , 10 }, + { 342, 100, 5 , 10 }, + { 355, 100, 5 , 9 }, + { 368, 100, 5 , 12 }, + { 381, 100, 5 , 11 }, + { 394, 100, 5 , 11 }, +}; + +// Font glyphs info data +// NOTE: No glyphs.image data provided +static const GlyphInfo darkFontGlyphs[189] = { + { 32, 0, 13, 4, { 0 }}, + { 33, 2, 4, 5, { 0 }}, + { 34, 2, 4, 7, { 0 }}, + { 35, 1, 4, 8, { 0 }}, + { 36, 1, 2, 7, { 0 }}, + { 37, 1, 4, 9, { 0 }}, + { 38, 1, 4, 7, { 0 }}, + { 39, 2, 4, 5, { 0 }}, + { 40, 3, 4, 7, { 0 }}, + { 41, 1, 4, 7, { 0 }}, + { 42, 1, 4, 7, { 0 }}, + { 43, 1, 6, 7, { 0 }}, + { 44, 1, 12, 5, { 0 }}, + { 45, 1, 8, 6, { 0 }}, + { 46, 2, 12, 5, { 0 }}, + { 47, 1, 4, 5, { 0 }}, + { 48, 1, 4, 7, { 0 }}, + { 49, 2, 4, 7, { 0 }}, + { 50, 1, 4, 7, { 0 }}, + { 51, 1, 4, 7, { 0 }}, + { 52, 1, 4, 7, { 0 }}, + { 53, 1, 4, 7, { 0 }}, + { 54, 1, 4, 7, { 0 }}, + { 55, 1, 4, 7, { 0 }}, + { 56, 1, 4, 7, { 0 }}, + { 57, 1, 4, 7, { 0 }}, + { 58, 2, 6, 5, { 0 }}, + { 59, 1, 6, 5, { 0 }}, + { 60, 1, 6, 5, { 0 }}, + { 61, 1, 7, 6, { 0 }}, + { 62, 1, 6, 5, { 0 }}, + { 63, 1, 4, 7, { 0 }}, + { 64, 1, 4, 9, { 0 }}, + { 65, 1, 4, 7, { 0 }}, + { 66, 1, 4, 7, { 0 }}, + { 67, 1, 4, 7, { 0 }}, + { 68, 1, 4, 7, { 0 }}, + { 69, 1, 4, 7, { 0 }}, + { 70, 1, 4, 7, { 0 }}, + { 71, 1, 4, 7, { 0 }}, + { 72, 1, 4, 7, { 0 }}, + { 73, 2, 4, 5, { 0 }}, + { 74, 1, 4, 7, { 0 }}, + { 75, 1, 4, 7, { 0 }}, + { 76, 1, 4, 7, { 0 }}, + { 77, 1, 4, 9, { 0 }}, + { 78, 1, 4, 7, { 0 }}, + { 79, 1, 4, 7, { 0 }}, + { 80, 1, 4, 7, { 0 }}, + { 81, 1, 4, 7, { 0 }}, + { 82, 1, 4, 7, { 0 }}, + { 83, 1, 4, 7, { 0 }}, + { 84, 1, 4, 7, { 0 }}, + { 85, 1, 4, 7, { 0 }}, + { 86, 1, 4, 7, { 0 }}, + { 87, 1, 4, 9, { 0 }}, + { 88, 1, 4, 7, { 0 }}, + { 89, 1, 4, 7, { 0 }}, + { 90, 1, 4, 7, { 0 }}, + { 91, 3, 4, 7, { 0 }}, + { 92, 1, 4, 5, { 0 }}, + { 93, 1, 4, 7, { 0 }}, + { 94, 1, 4, 7, { 0 }}, + { 95, 0, 14, 5, { 0 }}, + { 96, 1, 4, 5, { 0 }}, + { 97, 1, 6, 7, { 0 }}, + { 98, 1, 4, 7, { 0 }}, + { 99, 1, 6, 7, { 0 }}, + { 100, 1, 4, 7, { 0 }}, + { 101, 1, 6, 7, { 0 }}, + { 102, 1, 4, 6, { 0 }}, + { 103, 1, 6, 7, { 0 }}, + { 104, 1, 4, 7, { 0 }}, + { 105, 2, 4, 5, { 0 }}, + { 106, 1, 4, 7, { 0 }}, + { 107, 1, 4, 7, { 0 }}, + { 108, 2, 4, 5, { 0 }}, + { 109, 1, 6, 9, { 0 }}, + { 110, 1, 6, 7, { 0 }}, + { 111, 1, 6, 7, { 0 }}, + { 112, 1, 6, 7, { 0 }}, + { 113, 1, 6, 7, { 0 }}, + { 114, 1, 6, 7, { 0 }}, + { 115, 1, 6, 7, { 0 }}, + { 116, 1, 5, 6, { 0 }}, + { 117, 1, 6, 7, { 0 }}, + { 118, 1, 6, 7, { 0 }}, + { 119, 1, 6, 9, { 0 }}, + { 120, 1, 6, 7, { 0 }}, + { 121, 1, 6, 7, { 0 }}, + { 122, 1, 6, 7, { 0 }}, + { 123, 2, 4, 7, { 0 }}, + { 124, 2, 4, 5, { 0 }}, + { 125, 1, 4, 7, { 0 }}, + { 126, 1, 4, 8, { 0 }}, + { 161, 2, 6, 5, { 0 }}, + { 162, 1, 4, 7, { 0 }}, + { 163, 1, 4, 8, { 0 }}, + { 8364, 1, 4, 8, { 0 }}, + { 165, 1, 4, 7, { 0 }}, + { 352, 1, 1, 7, { 0 }}, + { 167, 2, 4, 9, { 0 }}, + { 353, 1, 3, 7, { 0 }}, + { 169, 1, 4, 9, { 0 }}, + { 170, 2, 4, 9, { 0 }}, + { 171, 1, 6, 8, { 0 }}, + { 172, 1, 8, 7, { 0 }}, + { 174, 1, 4, 9, { 0 }}, + { 175, 2, 4, 9, { 0 }}, + { 176, 1, 4, 6, { 0 }}, + { 177, 1, 6, 7, { 0 }}, + { 178, 2, 4, 9, { 0 }}, + { 179, 2, 4, 9, { 0 }}, + { 381, 1, 1, 7, { 0 }}, + { 181, 1, 6, 7, { 0 }}, + { 182, 1, 4, 9, { 0 }}, + { 183, 2, 8, 5, { 0 }}, + { 382, 1, 3, 7, { 0 }}, + { 185, 2, 4, 9, { 0 }}, + { 186, 2, 4, 9, { 0 }}, + { 187, 1, 6, 8, { 0 }}, + { 338, 1, 4, 11, { 0 }}, + { 339, 1, 6, 11, { 0 }}, + { 376, 1, 2, 7, { 0 }}, + { 191, 1, 6, 7, { 0 }}, + { 192, 1, 1, 7, { 0 }}, + { 193, 1, 1, 7, { 0 }}, + { 194, 1, 1, 7, { 0 }}, + { 195, 1, 1, 7, { 0 }}, + { 196, 1, 2, 7, { 0 }}, + { 197, 1, 0, 7, { 0 }}, + { 198, 1, 4, 11, { 0 }}, + { 199, 1, 4, 7, { 0 }}, + { 200, 1, 1, 7, { 0 }}, + { 201, 1, 1, 7, { 0 }}, + { 202, 1, 1, 7, { 0 }}, + { 203, 1, 2, 7, { 0 }}, + { 204, 1, 1, 5, { 0 }}, + { 205, 2, 1, 5, { 0 }}, + { 206, 1, 1, 5, { 0 }}, + { 207, 1, 2, 5, { 0 }}, + { 208, 0, 4, 7, { 0 }}, + { 209, 1, 1, 7, { 0 }}, + { 210, 1, 1, 7, { 0 }}, + { 211, 1, 1, 7, { 0 }}, + { 212, 1, 1, 7, { 0 }}, + { 213, 1, 1, 7, { 0 }}, + { 214, 1, 2, 7, { 0 }}, + { 215, 1, 6, 7, { 0 }}, + { 216, 0, 4, 7, { 0 }}, + { 217, 1, 1, 7, { 0 }}, + { 218, 1, 1, 7, { 0 }}, + { 219, 1, 1, 7, { 0 }}, + { 220, 1, 2, 7, { 0 }}, + { 221, 1, 1, 7, { 0 }}, + { 222, 1, 4, 7, { 0 }}, + { 223, 1, 4, 7, { 0 }}, + { 224, 1, 3, 7, { 0 }}, + { 225, 1, 3, 7, { 0 }}, + { 226, 1, 3, 7, { 0 }}, + { 227, 1, 3, 7, { 0 }}, + { 228, 1, 4, 7, { 0 }}, + { 229, 1, 2, 7, { 0 }}, + { 230, 1, 6, 11, { 0 }}, + { 231, 1, 6, 7, { 0 }}, + { 232, 1, 3, 7, { 0 }}, + { 233, 1, 3, 7, { 0 }}, + { 234, 1, 3, 7, { 0 }}, + { 235, 1, 4, 7, { 0 }}, + { 236, 1, 3, 5, { 0 }}, + { 237, 2, 3, 5, { 0 }}, + { 238, 1, 3, 5, { 0 }}, + { 239, 1, 4, 5, { 0 }}, + { 240, 1, 4, 7, { 0 }}, + { 241, 1, 3, 7, { 0 }}, + { 242, 1, 3, 7, { 0 }}, + { 243, 1, 3, 7, { 0 }}, + { 244, 1, 3, 7, { 0 }}, + { 245, 1, 3, 7, { 0 }}, + { 246, 1, 4, 7, { 0 }}, + { 247, 1, 6, 7, { 0 }}, + { 248, 0, 6, 7, { 0 }}, + { 249, 1, 3, 7, { 0 }}, + { 250, 1, 3, 7, { 0 }}, + { 251, 1, 3, 7, { 0 }}, + { 252, 1, 4, 7, { 0 }}, + { 253, 1, 3, 7, { 0 }}, + { 254, 1, 4, 7, { 0 }}, + { 255, 1, 4, 7, { 0 }}, +}; + +// Style loading function: Dark +static void GuiLoadStyleDark(void) +{ + // Load style properties provided + // NOTE: Default properties are propagated + for (int i = 0; i < DARK_STYLE_PROPS_COUNT; i++) + { + GuiSetStyle(darkStyleProps[i].controlId, darkStyleProps[i].propertyId, darkStyleProps[i].propertyValue); + } + + // Custom font loading + // NOTE: Compressed font image data (DEFLATE), it requires DecompressData() function + int darkFontDataSize = 0; + unsigned char *data = DecompressData(darkFontData, DARK_STYLE_FONT_ATLAS_COMP_SIZE, &darkFontDataSize); + Image imFont = { data, 512, 256, 1, 2 }; + + Font font = { 0 }; + font.baseSize = 16; + font.glyphCount = 189; + + // Load texture from image + font.texture = LoadTextureFromImage(imFont); + UnloadImage(imFont); // Uncompressed image data can be unloaded from memory + + // Copy char recs data from global fontRecs + // NOTE: Required to avoid issues if trying to free font + font.recs = (Rectangle *)RAYGUI_MALLOC(font.glyphCount*sizeof(Rectangle)); + memcpy(font.recs, darkFontRecs, font.glyphCount*sizeof(Rectangle)); + + // Copy font char info data from global fontChars + // NOTE: Required to avoid issues if trying to free font + font.glyphs = (GlyphInfo *)RAYGUI_MALLOC(font.glyphCount*sizeof(GlyphInfo)); + memcpy(font.glyphs, darkFontGlyphs, font.glyphCount*sizeof(GlyphInfo)); + + GuiSetFont(font); + + // Setup a white rectangle on the font to be used on shapes drawing, + // it makes possible to draw shapes and text (full UI) in a single draw call + Rectangle fontWhiteRec = { 510, 254, 1, 1 }; + SetShapesTexture(font.texture, fontWhiteRec); + + //----------------------------------------------------------------- + + // TODO: Custom user style setup: Set specific properties here (if required) + // i.e. Controls specific BORDER_WIDTH, TEXT_PADDING, TEXT_ALIGNMENT +} \ No newline at end of file diff --git a/src/gui/theme.hpp b/src/gui/theme.hpp new file mode 100644 index 0000000..8edb244 --- /dev/null +++ b/src/gui/theme.hpp @@ -0,0 +1,21 @@ +#pragma once + +#include + +#include "util.hpp" + +namespace mcpaint::gui { + +using namespace mcpaint; + +struct Theme { + constexpr static Color TRANSPARENT = ColorFromHex(0x00000000); + constexpr static Color ELEMENT = ColorFromHex(0x535353FF); + constexpr static Color ELEMENT_BORDER = ColorFromHex(0x383838FF); + constexpr static Color ELEMENT_ACTIVE = ColorFromHex(0x383838FF); + constexpr static Color ELEMENT_HOVER = ColorFromHex(0x454545FF); + constexpr static Color ELEMENT_FG = ColorFromHex(0xECECECFF); + constexpr static Color ARTBOARD = ColorFromHex(0x282828FF); +}; + +} \ No newline at end of file diff --git a/src/util.hpp b/src/util.hpp new file mode 100644 index 0000000..8709e25 --- /dev/null +++ b/src/util.hpp @@ -0,0 +1,31 @@ +#pragma once + +#include +#include + +namespace mcpaint { + +inline Vector2 GetWindowSize() { + return {static_cast(GetScreenWidth()), static_cast(GetScreenHeight())}; +} + +inline constexpr Color ColorFromHex(uint32_t color) { + uint8_t r = (color >> 24) & 0xFF; + uint8_t g = (color >> 16) & 0xFF; + uint8_t b = (color >> 8) & 0xFF; + uint8_t a = color & 0xFF; + + return { r, g, b, a }; +} + +inline const Vector2& operator -= (Vector2& lhs, float rhs) { + lhs = Vector2SubtractValue(lhs, rhs); + return lhs; +} + +inline const Vector2& operator += (Vector2& lhs, float rhs) { + lhs = Vector2AddValue(lhs, rhs); + return lhs; +} + +} \ No newline at end of file