commit
0ffca7ed1c
36 changed files with 2031 additions and 0 deletions
@ -0,0 +1,5 @@ |
||||
.idea |
||||
.vscode |
||||
.DS_Store |
||||
|
||||
build |
@ -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 |
@ -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) |
@ -0,0 +1,2 @@ |
||||
# mcpaint |
||||
– a simple drawing app whose code could be understood |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1 @@ |
||||
Subproject commit 566c73f4e469ba83b053a0606188cc6b132c1312 |
@ -0,0 +1 @@ |
||||
Subproject commit ceb1a5ea2b7550aa01c103b4b3dac0dbc4d8f8fe |
@ -0,0 +1,279 @@ |
||||
#include <memory> |
||||
#include <raylib.h> |
||||
#include <iostream> |
||||
#define RAYGUI_IMPLEMENTATION |
||||
#include <raygui.h> |
||||
#include <raymath.h> |
||||
#include <algorithm> |
||||
|
||||
#include <vector> |
||||
#include <sstream> |
||||
|
||||
#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<Texture2D> 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<Color> 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<float>(GetScreenWidth()), static_cast<float>(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; |
||||
} |
@ -0,0 +1,134 @@ |
||||
#include <format> |
||||
|
||||
#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<float>(artboard.canvas.texture.width), -static_cast<float>(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(); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,36 @@ |
||||
#pragma once |
||||
|
||||
#include <vector> |
||||
|
||||
#include "gui/View.hpp" |
||||
|
||||
namespace mcpaint { |
||||
|
||||
struct Artboard { |
||||
Vector2 position; |
||||
Vector2 size; |
||||
RenderTexture2D canvas; |
||||
float scale; |
||||
}; |
||||
|
||||
class Artboards : public gui::view { |
||||
protected: |
||||
std::vector<Artboard> 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; |
||||
}; |
||||
|
||||
} |
@ -0,0 +1,7 @@ |
||||
#include "Event.hpp" |
||||
|
||||
namespace mcpaint::events { |
||||
|
||||
std::unique_ptr<Dispatch> Dispatch::Instance_ = nullptr; |
||||
|
||||
} |
@ -0,0 +1,56 @@ |
||||
#pragma once |
||||
|
||||
#include <raylib.h> |
||||
#include <memory> |
||||
#include <unordered_map> |
||||
#include <vector> |
||||
#include <functional> |
||||
|
||||
namespace mcpaint::events { |
||||
|
||||
struct Event { |
||||
enum class Type { |
||||
CLICK, |
||||
POINTER_REQUEST |
||||
}; |
||||
|
||||
Type type; |
||||
Vector2 mouse; |
||||
}; |
||||
|
||||
using EventCallback = std::function<void(Event)>; |
||||
|
||||
class Dispatch { |
||||
private: |
||||
std::unordered_map<Event::Type, std::vector<EventCallback>> handlers; |
||||
static std::unique_ptr<Dispatch> Instance_; |
||||
Dispatch() = default; |
||||
public: |
||||
static Dispatch& Instance() { |
||||
if (Dispatch::Instance_ == nullptr) |
||||
Dispatch::Instance_ = std::unique_ptr<Dispatch>(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(); |
||||
|
||||
} |
@ -0,0 +1,66 @@ |
||||
#include "UndoRedoManager.hpp" |
||||
|
||||
#include <cstdio> |
||||
|
||||
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<float>(img.width), static_cast<float>(img.height)}, {0, 0}, 0, WHITE); |
||||
EndTextureMode(); |
||||
UnloadTexture(img); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,40 @@ |
||||
#pragma once; |
||||
|
||||
#include <type_traits> |
||||
#include <optional> |
||||
#include <raylib.h> |
||||
|
||||
namespace mcpaint { |
||||
|
||||
class UndoRedoManager { |
||||
private: |
||||
constexpr static size_t MAX_UNDO_REDO = 50; |
||||
std::optional<Image> 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; |
||||
}; |
||||
|
||||
} |
@ -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; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,43 @@ |
||||
#pragma once |
||||
|
||||
#include <functional> |
||||
|
||||
#include "../Event.hpp" |
||||
#include "Icon.hpp" |
||||
#include "View.hpp" |
||||
|
||||
using namespace mcpaint::events; |
||||
|
||||
namespace mcpaint::gui { |
||||
|
||||
using ButtonCallback = std::function<void(Event)>; |
||||
|
||||
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)); |
||||
} |
||||
|
||||
} |
@ -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) { |
||||
} |
||||
|
||||
} |
@ -0,0 +1,63 @@ |
||||
#pragma once |
||||
|
||||
#include <raylib.h> |
||||
#include <variant> |
||||
#include <optional> |
||||
|
||||
#include "../util.hpp" |
||||
|
||||
namespace mcpaint::gui { |
||||
|
||||
using Value = std::variant<std::monostate, float, int>; |
||||
|
||||
struct Vec2 { |
||||
Value x; |
||||
Value y; |
||||
|
||||
Vector2 toPixels() const { |
||||
Vector2 windowSize = GetWindowSize(); |
||||
Vector2 outValue; |
||||
|
||||
if (std::holds_alternative<float>(this->x)) |
||||
outValue.x = std::get<float>(this->x) * windowSize.x / 100.0f; |
||||
else |
||||
outValue.x = std::get<int>(this->x); |
||||
|
||||
if (std::holds_alternative<float>(this->y)) |
||||
outValue.y = std::get<float>(this->y) * windowSize.y / 100.0f; |
||||
else |
||||
outValue.y = std::get<int>(this->y); |
||||
|
||||
return outValue; |
||||
} |
||||
}; |
||||
|
||||
class Element { |
||||
protected: |
||||
Vec2 position; |
||||
Vec2 size; |
||||
std::optional<const Element*> 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; |
||||
}; |
||||
|
||||
} |
@ -0,0 +1,38 @@ |
||||
#include "FontManager.hpp" |
||||
|
||||
#include "Icon.hpp" |
||||
|
||||
namespace mcpaint::gui { |
||||
|
||||
std::unique_ptr<FontManager> FontManager::Instance_ = nullptr; |
||||
Font FontManager::IconFont_ = {0}; |
||||
|
||||
FontManager::FontManager() { |
||||
FontManager::IconFont_ = LoadFontEx( |
||||
"assets/fonts/icons-solid.otf", |
||||
FontManager::ICON_SIZE * 2, // HiDPI
|
||||
const_cast<int*>(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_t, Font>({{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); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,39 @@ |
||||
#pragma once |
||||
|
||||
#include <raylib.h> |
||||
#include <string> |
||||
#include <unordered_map> |
||||
|
||||
namespace mcpaint::gui { |
||||
|
||||
class FontManager { |
||||
protected: |
||||
constexpr static size_t ICON_SIZE = 50; |
||||
std::unordered_map<std::string, std::unordered_map<size_t, Font>> fonts; |
||||
|
||||
FontManager(); |
||||
static std::unique_ptr<FontManager> 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<FontManager>(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; |
||||
}; |
||||
|
||||
} |
@ -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<int>(spec.size.first)) { |
||||
fullWidth -= std::get<int>(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<int>(spec.size.first) ? std::get<int>(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); |
||||
} |
||||
|
||||
} |
@ -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<view*> children = {}) { |
||||
return new hstack(children); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,35 @@ |
||||
#pragma once |
||||
|
||||
#include <raylib.h> |
||||
|
||||
#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<wchar_t>(icon), position, size, color); |
||||
} |
||||
|
||||
inline void DrawIcon(Icon icon, int posX, int posY, size_t size, Color color = WHITE) { |
||||
DrawIcon(icon, {static_cast<float>(posX), static_cast<float>(posY)}, size, color); |
||||
} |
||||
|
||||
inline Vector2 MeasureIcon(Icon icon, size_t size) { |
||||
(void) icon; |
||||
return {static_cast<float>(size), static_cast<float>(size)}; |
||||
} |
||||
|
||||
} |
@ -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)); |
||||
} |
||||
|
||||
} |
@ -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; |
||||
}; |
||||
|
||||
} |
@ -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(); |
||||
} |
||||
|
||||
} |
@ -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<int>(spec.size.second)) { |
||||
fullHeight -= std::get<int>(spec.size.second); |
||||
fixedChildren++; |
||||
} |
||||
} |
||||
|
||||
for (const auto& child : this->children) { |
||||
const Spec& spec = child->spec(); |
||||
|
||||
float height = std::holds_alternative<int>(spec.size.second) ? std::get<int>(spec.size.second) : fullHeight / (this->children.size() - fixedChildren); |
||||
int width = this->size_.x - this->spec_.padding * 2; |
||||
|
||||
child->size_ = {static_cast<float>(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); |
||||
} |
||||
|
||||
} |
@ -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<view*> children = {}) { |
||||
return new vstack(children); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,66 @@ |
||||
#include "View.hpp" |
||||
#include "util.hpp" |
||||
|
||||
#include <iostream> |
||||
|
||||
namespace mcpaint::gui { |
||||
|
||||
view::view(std::initializer_list<view*> 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<float>(GetScreenWidth()), static_cast<float>(GetScreenHeight())}; |
||||
float parentPadding = parent != nullptr ? parent->spec().padding : 0; |
||||
|
||||
float width = std::holds_alternative<float>(this->spec_.size.first) ? std::get<float>(this->spec_.size.first) * parentSize.x / 100 : std::get<int>(this->spec_.size.first); |
||||
float height = std::holds_alternative<float>(this->spec_.size.second) ? std::get<float>(this->spec_.size.second) * parentSize.y / 100 : std::get<int>(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); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,140 @@ |
||||
#pragma once |
||||
|
||||
#include <initializer_list> |
||||
#include <variant> |
||||
#include <vector> |
||||
#include <optional> |
||||
#include <raylib.h> |
||||
#include <raymath.h> |
||||
|
||||
#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<float, int>; |
||||
using Tuple = std::pair<Length, Length>; |
||||
|
||||
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> 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<view*> 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<view*> 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<view*> children = {}) { |
||||
return new view(std::move(children)); |
||||
} |
||||
|
||||
} |
@ -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
|
||||
} |
@ -0,0 +1,21 @@ |
||||
#pragma once |
||||
|
||||
#include <raylib.h> |
||||
|
||||
#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); |
||||
}; |
||||
|
||||
} |
@ -0,0 +1,31 @@ |
||||
#pragma once |
||||
|
||||
#include <raylib.h> |
||||
#include <raymath.h> |
||||
|
||||
namespace mcpaint { |
||||
|
||||
inline Vector2 GetWindowSize() { |
||||
return {static_cast<float>(GetScreenWidth()), static_cast<float>(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; |
||||
} |
||||
|
||||
} |
Loading…
Reference in new issue