ran a formatter on all the files for tab consistency

This commit is contained in:
2026-08-24 09:06:57 -05:00
parent 194eef56ab
commit 4dacb370a6
15 changed files with 284 additions and 221 deletions

View File

@@ -42,4 +42,4 @@ p {
.menu-btn:hover { .menu-btn:hover {
background-color: #4a7eb5; background-color: #4a7eb5;
} }

View File

@@ -1,13 +1,15 @@
<rml> <rml>
<head>
<title>gamejam</title> <head>
<link type="text/rcss" href="main.rcss"/> <title>gamejam</title>
</head> <link type="text/rcss" href="main.rcss" />
<body> </head>
<div id="start_menu">
<h1>gamejam</h1> <body>
<p>RmlUi + raylib scaffold is alive.</p> <div id="start_menu">
<button id="start-btn">Start</button> <h1>gamejam</h1>
</div> <p>RmlUi + raylib scaffold is alive.</p>
</body> <button id="start-btn">Start</button>
</rml> </div>
</body>
</rml>

2
flake.lock generated
View File

@@ -58,4 +58,4 @@
}, },
"root": "root", "root": "root",
"version": 7 "version": 7
} }

View File

@@ -2,57 +2,70 @@
#include "Game.h" #include "Game.h"
#include "backend/RaylibInput.h" #include "backend/RaylibInput.h"
#include <raylib.h>
#include <RmlUi/Core.h> #include <RmlUi/Core.h>
#include <RmlUi/Core/DataModelHandle.h>
#include <RmlUi/Debugger.h> #include <RmlUi/Debugger.h>
#include <iostream>
#include <raylib.h>
Game game; Game game;
bool Application::Init(int width, int height, const char* title, const char* documentPath) { bool Application::Init(int width, int height, const char *title,
InitWindow(width, height, title); const char *documentPath) {
SetTargetFPS(60); InitWindow(width, height, title);
SetTargetFPS(60);
Rml::SetSystemInterface(&system_interface); Rml::SetSystemInterface(&system_interface);
Rml::SetRenderInterface(&render_interface); Rml::SetRenderInterface(&render_interface);
Rml::Initialise(); Rml::Initialise();
context = Rml::CreateContext("main", Rml::Vector2i(width, height)); context = Rml::CreateContext("main", Rml::Vector2i(width, height));
Rml::Debugger::Initialise(context); Rml::Debugger::Initialise(context);
// TODO: load a real font // TODO: load a real font
if (Rml::ElementDocument* document = context->LoadDocument(documentPath)) { if (Rml::ElementDocument *document = context->LoadDocument(documentPath)) {
document->Show(); document->Show();
} else { } else {
TraceLog(LOG_WARNING, "Failed to load %s", documentPath); TraceLog(LOG_WARNING, "Failed to load %s", documentPath);
} }
game.Init(context); if (!game.Init(context)) {
TraceLog(LOG_ERROR, "Failed to initialize game instance.");
return false;
}
return true; Rml::DataModelHandle game_data_model_handle;
if (!game.setup_rml_data_binding(context, game_data_model_handle,
game.game_data)) {
TraceLog(LOG_ERROR, "Failed to initialize data bindings for 'game_data'.");
return false;
}
return true;
} }
void Application::Frame() { void Application::Frame() {
if (WindowShouldClose()) { if (WindowShouldClose()) {
running = false; running = false;
return; return;
} }
ForwardInputToRml(context); ForwardInputToRml(context);
context->Update(); context->Update();
game.Update(); game.Update();
BeginDrawing(); BeginDrawing();
ClearBackground(DARKGRAY); ClearBackground(DARKGRAY);
game.Draw2D(); game.Draw2D();
context->Render(); context->Render();
EndDrawing(); EndDrawing();
} }
void Application::Shutdown() { void Application::Shutdown() {
Rml::Shutdown(); Rml::Shutdown();
CloseWindow(); CloseWindow();
} }

View File

@@ -1,20 +1,20 @@
#pragma once #pragma once
#include <RmlUi/Core/Context.h>
#include "backend/RaylibSystemInterface.h"
#include "backend/RaylibRenderInterface.h"
#include "Game.h" #include "Game.h"
#include "backend/RaylibRenderInterface.h"
#include "backend/RaylibSystemInterface.h"
#include <RmlUi/Core/Context.h>
class Application { class Application {
public: public:
bool Init(int width, int height, const char* title, const char* documentPath); bool Init(int width, int height, const char *title, const char *documentPath);
void Frame(); void Frame();
void Shutdown(); void Shutdown();
bool IsRunning() const { return running; } bool IsRunning() const { return running; }
private: private:
RaylibSystemInterface system_interface; RaylibSystemInterface system_interface;
RaylibRenderInterface render_interface; RaylibRenderInterface render_interface;
Rml::Context* context = nullptr; Rml::Context *context = nullptr;
bool running = true; bool running = true;
}; };

View File

@@ -1,20 +1,51 @@
#include "Game.h" #include "Game.h"
#include <RmlUi/Core.h>
#include <RmlUi/Core/Context.h> #include <RmlUi/Core/Context.h>
#include <RmlUi/Core/DataModelHandle.h>
#include <iostream> #include <iostream>
#include <raylib.h> #include <raylib.h>
#include <RmlUi/Core.h>
void Game::Draw2D() {return;} void Game::Draw2D() { return; }
void Game::Update() { void Game::Update() { return; }
// TODO: Remove this debug
std::cout << "Game update" << std::endl;
return;
}
bool Game::Init(Rml::Context *context) { bool Game::Init(Rml::Context *context) {
if (!ctx) return false; if (!ctx)
return false;
ctx = context;
return true; ctx = context;
return true;
}
bool Game::setup_rml_data_binding(Rml::Context *ctx,
Rml::DataModelHandle &model_handle,
GameData &game_data) {
Rml::DataModelConstructor dmc = ctx->CreateDataModel("game_data");
if (!dmc) {
TraceLog(LOG_ERROR, "Failed to construct data model..");
return false;
}
dmc.Bind("game_state", &game_data.game_state);
return true;
}
void Game::ResetGame() {}
void Game::ShowMainMenu() {}
void Game::TrySetGameState(GameState newState) {
GameState currentState = game_data.game_state;
switch (newState) {
case START_MENU:
if (currentState == IN_GAME)
ResetGame();
ShowMainMenu();
break;
default:
break;
}
game_data.game_state = newState;
} }

View File

@@ -2,31 +2,33 @@
#include <RmlUi/Core/Context.h> #include <RmlUi/Core/Context.h>
#include <RmlUi/Core/DataModelHandle.h> #include <RmlUi/Core/DataModelHandle.h>
enum GameState { enum GameState { START_MENU, PAUSE_MENU, STATS_MENU, OPTIONS_MENU, IN_GAME };
START_MENU,
PAUSE_MENU,
STATS_MENU,
OPTIONS_MENU,
IN_GAME
};
struct GameData { struct GameData {
GameState game_state = START_MENU; GameState game_state = START_MENU;
}; };
class Game { class Game {
public: public:
GameData game_data; GameData game_data;
bool Init(Rml::Context *context); bool Init(Rml::Context *context);
bool setup_rml_data_binding(Rml::Context *ctx, Rml::DataModelHandle &model_handle, GameData &game_data); bool setup_rml_data_binding(Rml::Context *ctx,
Rml::DataModelHandle &model_handle,
GameData &game_data);
void Update(); void Update();
void Draw2D(); void Draw2D();
void TrySetGameState(GameState newState);
void StartNewGame();
void ResetGame();
void ShowMainMenu();
void ShowPauseMenu();
private: private:
Rml::Context *ctx = nullptr; Rml::Context *ctx = nullptr;
}; };

View File

@@ -1,22 +1,22 @@
#pragma once #pragma once
#include <RmlUi/Core/Element.h>
#include <RmlUi/Core/Event.h> #include <RmlUi/Core/Event.h>
#include <RmlUi/Core/EventListener.h> #include <RmlUi/Core/EventListener.h>
#include <RmlUi/Core/Element.h>
#include <functional> #include <functional>
class UiCallbackListener : public Rml::EventListener { class UiCallbackListener : public Rml::EventListener {
public: public:
using Callback = std::function<void(Rml::Event&)>; using Callback = std::function<void(Rml::Event &)>;
explicit UiCallbackListener(Callback callback) : callback(std::move(callback)) {} explicit UiCallbackListener(Callback callback)
: callback(std::move(callback)) {}
void ProcessEvent(Rml::Event& event) override { void ProcessEvent(Rml::Event &event) override {
if (callback) callback(event); if (callback)
} callback(event);
}
void OnDetach(Rml::Element* /*element*/) override { void OnDetach(Rml::Element * /*element*/) override { delete this; }
delete this;
}
private: private:
Callback callback; Callback callback;
}; };

View File

@@ -2,24 +2,32 @@
#include <raylib.h> #include <raylib.h>
namespace { namespace {
int GetRmlKeyModifiers() { int GetRmlKeyModifiers() {
int mods = 0; int mods = 0;
if (IsKeyDown(KEY_LEFT_SHIFT) || IsKeyDown(KEY_RIGHT_SHIFT)) mods |= Rml::Input::KM_SHIFT; if (IsKeyDown(KEY_LEFT_SHIFT) || IsKeyDown(KEY_RIGHT_SHIFT))
if (IsKeyDown(KEY_LEFT_CONTROL) || IsKeyDown(KEY_RIGHT_CONTROL)) mods |= Rml::Input::KM_CTRL; mods |= Rml::Input::KM_SHIFT;
if (IsKeyDown(KEY_LEFT_ALT) || IsKeyDown(KEY_RIGHT_ALT)) mods |= Rml::Input::KM_ALT; if (IsKeyDown(KEY_LEFT_CONTROL) || IsKeyDown(KEY_RIGHT_CONTROL))
return mods; mods |= Rml::Input::KM_CTRL;
} if (IsKeyDown(KEY_LEFT_ALT) || IsKeyDown(KEY_RIGHT_ALT))
} mods |= Rml::Input::KM_ALT;
return mods;
}
} // namespace
void ForwardInputToRml(Rml::Context* context) { void ForwardInputToRml(Rml::Context *context) {
Vector2 mouse = GetMousePosition(); Vector2 mouse = GetMousePosition();
context->ProcessMouseMove((int)mouse.x, (int)mouse.y, GetRmlKeyModifiers()); context->ProcessMouseMove((int)mouse.x, (int)mouse.y, GetRmlKeyModifiers());
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) context->ProcessMouseButtonDown(0, GetRmlKeyModifiers()); if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT))
if (IsMouseButtonReleased(MOUSE_BUTTON_LEFT)) context->ProcessMouseButtonUp(0, GetRmlKeyModifiers()); context->ProcessMouseButtonDown(0, GetRmlKeyModifiers());
if (IsMouseButtonPressed(MOUSE_BUTTON_RIGHT)) context->ProcessMouseButtonDown(1, GetRmlKeyModifiers()); if (IsMouseButtonReleased(MOUSE_BUTTON_LEFT))
if (IsMouseButtonReleased(MOUSE_BUTTON_RIGHT)) context->ProcessMouseButtonUp(1, GetRmlKeyModifiers()); context->ProcessMouseButtonUp(0, GetRmlKeyModifiers());
if (IsMouseButtonPressed(MOUSE_BUTTON_RIGHT))
context->ProcessMouseButtonDown(1, GetRmlKeyModifiers());
if (IsMouseButtonReleased(MOUSE_BUTTON_RIGHT))
context->ProcessMouseButtonUp(1, GetRmlKeyModifiers());
float wheel = GetMouseWheelMove(); float wheel = GetMouseWheelMove();
if (wheel != 0.0f) context->ProcessMouseWheel(-wheel, GetRmlKeyModifiers()); if (wheel != 0.0f)
context->ProcessMouseWheel(-wheel, GetRmlKeyModifiers());
} }

View File

@@ -1,4 +1,4 @@
#pragma once #pragma once
#include <RmlUi/Core/Context.h> #include <RmlUi/Core/Context.h>
void ForwardInputToRml(Rml::Context* context); void ForwardInputToRml(Rml::Context *context);

View File

@@ -3,107 +3,114 @@
#include <raylib.h> #include <raylib.h>
#include <rlgl.h> #include <rlgl.h>
#include <vector>
#include <cstring> #include <cstring>
#include <vector>
namespace { namespace {
struct GeometryData { struct GeometryData {
std::vector<Rml::Vertex> vertices; std::vector<Rml::Vertex> vertices;
std::vector<int> indices; std::vector<int> indices;
}; };
} } // namespace
Rml::CompiledGeometryHandle RaylibRenderInterface::CompileGeometry( Rml::CompiledGeometryHandle
Rml::Span<const Rml::Vertex> vertices, Rml::Span<const int> indices) { RaylibRenderInterface::CompileGeometry(Rml::Span<const Rml::Vertex> vertices,
auto* geo = new GeometryData(); Rml::Span<const int> indices) {
geo->vertices.assign(vertices.begin(), vertices.end()); auto *geo = new GeometryData();
geo->indices.assign(indices.begin(), indices.end()); geo->vertices.assign(vertices.begin(), vertices.end());
return reinterpret_cast<Rml::CompiledGeometryHandle>(geo); geo->indices.assign(indices.begin(), indices.end());
return reinterpret_cast<Rml::CompiledGeometryHandle>(geo);
} }
void RaylibRenderInterface::RenderGeometry(Rml::CompiledGeometryHandle handle, void RaylibRenderInterface::RenderGeometry(Rml::CompiledGeometryHandle handle,
Rml::Vector2f translation, Rml::Vector2f translation,
Rml::TextureHandle texture) { Rml::TextureHandle texture) {
auto* geo = reinterpret_cast<GeometryData*>(handle); auto *geo = reinterpret_cast<GeometryData *>(handle);
if (texture) { if (texture) {
Texture2D* tex = reinterpret_cast<Texture2D*>(texture); Texture2D *tex = reinterpret_cast<Texture2D *>(texture);
rlSetTexture(tex->id); rlSetTexture(tex->id);
} else { } else {
rlSetTexture(rlGetTextureIdDefault()); rlSetTexture(rlGetTextureIdDefault());
}
rlPushMatrix();
rlTranslatef(translation.x, translation.y, 0.0f);
rlBegin(RL_TRIANGLES);
for (size_t i = 0; i + 2 < geo->indices.size(); i += 3) {
for (int j = 0; j < 3; ++j) {
const Rml::Vertex &v = geo->vertices[geo->indices[i + j]];
rlColor4ub(v.colour.red, v.colour.green, v.colour.blue, v.colour.alpha);
rlTexCoord2f(v.tex_coord.x, v.tex_coord.y);
rlVertex2f(v.position.x, v.position.y);
} }
}
rlEnd();
rlPushMatrix(); rlPopMatrix();
rlTranslatef(translation.x, translation.y, 0.0f); rlSetTexture(0);
rlBegin(RL_TRIANGLES);
for (size_t i = 0; i + 2 < geo->indices.size(); i += 3) {
for (int j = 0; j < 3; ++j) {
const Rml::Vertex& v = geo->vertices[geo->indices[i + j]];
rlColor4ub(v.colour.red, v.colour.green, v.colour.blue, v.colour.alpha);
rlTexCoord2f(v.tex_coord.x, v.tex_coord.y);
rlVertex2f(v.position.x, v.position.y);
}
}
rlEnd();
rlPopMatrix();
rlSetTexture(0);
} }
void RaylibRenderInterface::ReleaseGeometry(Rml::CompiledGeometryHandle handle) { void RaylibRenderInterface::ReleaseGeometry(
delete reinterpret_cast<GeometryData*>(handle); Rml::CompiledGeometryHandle handle) {
delete reinterpret_cast<GeometryData *>(handle);
} }
Rml::TextureHandle RaylibRenderInterface::LoadTexture(Rml::Vector2i& texture_dimensions, Rml::TextureHandle
const Rml::String& source) { RaylibRenderInterface::LoadTexture(Rml::Vector2i &texture_dimensions,
Texture2D tex = ::LoadTexture(source.c_str()); const Rml::String &source) {
if (tex.id == 0) { Texture2D tex = ::LoadTexture(source.c_str());
TraceLog(LOG_WARNING, "[RmlUi] failed to load texture: %s", source.c_str()); if (tex.id == 0) {
return 0; TraceLog(LOG_WARNING, "[RmlUi] failed to load texture: %s", source.c_str());
} return 0;
texture_dimensions = Rml::Vector2i(tex.width, tex.height); }
return reinterpret_cast<Rml::TextureHandle>(new Texture2D(tex)); texture_dimensions = Rml::Vector2i(tex.width, tex.height);
return reinterpret_cast<Rml::TextureHandle>(new Texture2D(tex));
} }
Rml::TextureHandle RaylibRenderInterface::GenerateTexture(Rml::Span<const Rml::byte> source_data, Rml::TextureHandle
Rml::Vector2i source_dimensions) { RaylibRenderInterface::GenerateTexture(Rml::Span<const Rml::byte> source_data,
Image img{}; Rml::Vector2i source_dimensions) {
img.width = source_dimensions.x; Image img{};
img.height = source_dimensions.y; img.width = source_dimensions.x;
img.mipmaps = 1; img.height = source_dimensions.y;
img.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8; img.mipmaps = 1;
img.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8;
size_t byte_count = static_cast<size_t>(img.width) * img.height * 4; size_t byte_count = static_cast<size_t>(img.width) * img.height * 4;
img.data = RL_MALLOC(byte_count); img.data = RL_MALLOC(byte_count);
std::memcpy(img.data, source_data.data(), byte_count); std::memcpy(img.data, source_data.data(), byte_count);
Texture2D tex = LoadTextureFromImage(img); Texture2D tex = LoadTextureFromImage(img);
UnloadImage(img); // frees img.data UnloadImage(img); // frees img.data
return reinterpret_cast<Rml::TextureHandle>(new Texture2D(tex)); return reinterpret_cast<Rml::TextureHandle>(new Texture2D(tex));
} }
void RaylibRenderInterface::ReleaseTexture(Rml::TextureHandle handle) { void RaylibRenderInterface::ReleaseTexture(Rml::TextureHandle handle) {
Texture2D* tex = reinterpret_cast<Texture2D*>(handle); Texture2D *tex = reinterpret_cast<Texture2D *>(handle);
UnloadTexture(*tex); UnloadTexture(*tex);
delete tex; delete tex;
} }
void RaylibRenderInterface::EnableScissorRegion(bool enable) { void RaylibRenderInterface::EnableScissorRegion(bool enable) {
scissor_enabled = enable; scissor_enabled = enable;
if (enable) ApplyScissor(); if (enable)
else EndScissorMode(); ApplyScissor();
else
EndScissorMode();
} }
void RaylibRenderInterface::SetScissorRegion(Rml::Rectanglei region) { void RaylibRenderInterface::SetScissorRegion(Rml::Rectanglei region) {
scissor_region = region; scissor_region = region;
if (scissor_enabled) ApplyScissor(); if (scissor_enabled)
ApplyScissor();
} }
void RaylibRenderInterface::ApplyScissor() { void RaylibRenderInterface::ApplyScissor() {
BeginScissorMode(scissor_region.Left(), scissor_region.Top(), BeginScissorMode(scissor_region.Left(), scissor_region.Top(),
scissor_region.Width(), scissor_region.Height()); scissor_region.Width(), scissor_region.Height());
} }

View File

@@ -1,7 +1,6 @@
#pragma once #pragma once
#include <RmlUi/Core/RenderInterface.h> #include <RmlUi/Core/RenderInterface.h>
// NOTE: RmlUi's RenderInterface signature has shifted across versions // NOTE: RmlUi's RenderInterface signature has shifted across versions
// (raw pointer+count vs. Rml::Span<>). If this fails to compile against // (raw pointer+count vs. Rml::Span<>). If this fails to compile against
// a different RmlUi commit, check RmlUi/Core/RenderInterface.h and adjust // a different RmlUi commit, check RmlUi/Core/RenderInterface.h and adjust
@@ -10,28 +9,30 @@
class RaylibRenderInterface : public Rml::RenderInterface { class RaylibRenderInterface : public Rml::RenderInterface {
public: public:
Rml::CompiledGeometryHandle CompileGeometry(Rml::Span<const Rml::Vertex> vertices, Rml::CompiledGeometryHandle
Rml::Span<const int> indices) override; CompileGeometry(Rml::Span<const Rml::Vertex> vertices,
Rml::Span<const int> indices) override;
void RenderGeometry(Rml::CompiledGeometryHandle handle, Rml::Vector2f translation, void RenderGeometry(Rml::CompiledGeometryHandle handle,
Rml::TextureHandle texture) override; Rml::Vector2f translation,
Rml::TextureHandle texture) override;
void ReleaseGeometry(Rml::CompiledGeometryHandle handle) override; void ReleaseGeometry(Rml::CompiledGeometryHandle handle) override;
Rml::TextureHandle LoadTexture(Rml::Vector2i& texture_dimensions, Rml::TextureHandle LoadTexture(Rml::Vector2i &texture_dimensions,
const Rml::String& source) override; const Rml::String &source) override;
Rml::TextureHandle GenerateTexture(Rml::Span<const Rml::byte> source_data, Rml::TextureHandle GenerateTexture(Rml::Span<const Rml::byte> source_data,
Rml::Vector2i source_dimensions) override; Rml::Vector2i source_dimensions) override;
void ReleaseTexture(Rml::TextureHandle handle) override; void ReleaseTexture(Rml::TextureHandle handle) override;
void EnableScissorRegion(bool enable) override; void EnableScissorRegion(bool enable) override;
void SetScissorRegion(Rml::Rectanglei region) override; void SetScissorRegion(Rml::Rectanglei region) override;
private: private:
void ApplyScissor(); void ApplyScissor();
bool scissor_enabled = false; bool scissor_enabled = false;
Rml::Rectanglei scissor_region; Rml::Rectanglei scissor_region;
}; };

View File

@@ -1,14 +1,15 @@
#include "RaylibSystemInterface.h" #include "RaylibSystemInterface.h"
#include <raylib.h> #include <raylib.h>
double RaylibSystemInterface::GetElapsedTime() { double RaylibSystemInterface::GetElapsedTime() { return GetTime(); }
return GetTime();
}
bool RaylibSystemInterface::LogMessage(Rml::Log::Type type, const Rml::String& message) { bool RaylibSystemInterface::LogMessage(Rml::Log::Type type,
TraceLogLevel level = LOG_INFO; const Rml::String &message) {
if (type == Rml::Log::LT_WARNING) level = LOG_WARNING; TraceLogLevel level = LOG_INFO;
if (type == Rml::Log::LT_ERROR || type == Rml::Log::LT_ASSERT) level = LOG_ERROR; if (type == Rml::Log::LT_WARNING)
TraceLog(level, "[RmlUi] %s", message.c_str()); level = LOG_WARNING;
return true; if (type == Rml::Log::LT_ERROR || type == Rml::Log::LT_ASSERT)
level = LOG_ERROR;
TraceLog(level, "[RmlUi] %s", message.c_str());
return true;
} }

View File

@@ -3,6 +3,6 @@
class RaylibSystemInterface : public Rml::SystemInterface { class RaylibSystemInterface : public Rml::SystemInterface {
public: public:
double GetElapsedTime() override; double GetElapsedTime() override;
bool LogMessage(Rml::Log::Type type, const Rml::String& message) override; bool LogMessage(Rml::Log::Type type, const Rml::String &message) override;
}; };

View File

@@ -6,28 +6,26 @@
namespace { namespace {
Application* g_app = nullptr; Application *g_app = nullptr;
void MainLoopStep() { void MainLoopStep() { g_app->Frame(); }
g_app->Frame();
}
} // namespace } // namespace
int main() { int main() {
static Application app; static Application app;
g_app = &app; g_app = &app;
app.Init(1280, 720, "gamejam", "assets/main.rml"); app.Init(1280, 720, "gamejam", "assets/main.rml");
#ifdef __EMSCRIPTEN__ #ifdef __EMSCRIPTEN__
emscripten_set_main_loop(MainLoopStep, 0, 1); emscripten_set_main_loop(MainLoopStep, 0, 1);
#else #else
while (app.IsRunning()) { while (app.IsRunning()) {
app.Frame(); app.Frame();
} }
#endif #endif
app.Shutdown(); app.Shutdown();
return 0; return 0;
} }