diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5ed9eee..4a86cd2 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -10,6 +10,7 @@ endif()
find_package(raylib REQUIRED)
find_package(RmlUi REQUIRED)
+find_package(OpenGL REQUIRED)
add_library(rmlui_backend STATIC
src/backend/RaylibSystemInterface.cpp
@@ -23,6 +24,7 @@ add_executable(${PROJECT_NAME}
target_link_libraries(${PROJECT_NAME} PRIVATE
raylib
+ OpenGL::GL
rmlui_backend
RmlUi::Core
RmlUi::Debugger
diff --git a/assets/main.rml b/assets/main.rml
index fa19728..88b98a9 100644
--- a/assets/main.rml
+++ b/assets/main.rml
@@ -5,7 +5,8 @@
+
diff --git a/flake.lock b/flake.lock
index 700d2c3..5d2aa29 100644
--- a/flake.lock
+++ b/flake.lock
@@ -2,11 +2,11 @@
"nodes": {
"nixpkgs": {
"locked": {
- "lastModified": 1788039129,
- "narHash": "sha256-pa4Q0qErvCvzCaaUph7Sm37RhR4xvPrYI8Lgz6k85+A=",
+ "lastModified": 1788179007,
+ "narHash": "sha256-hn1oU2rue2SYK8dAr8+WNZWtbsz1S2W5mnHlSEuh3bo=",
"owner": "nixos",
"repo": "nixpkgs",
- "rev": "d2f67949798825fe853f7c5d0492b8bf016d3f88",
+ "rev": "34ab99075ac4f7e40cf037eef32cb1c360bb85e9",
"type": "github"
},
"original": {
diff --git a/flake.nix b/flake.nix
index 002a243..2576a7e 100644
--- a/flake.nix
+++ b/flake.nix
@@ -14,8 +14,8 @@
rmluiSrc = pkgs.fetchFromGitHub {
owner = "mikke89";
repo = "RmlUi";
- rev = "9c74c4fadc2ad7f1496239e560bab19ca2fe5072";
- hash = "sha256-YZz41ViE3+a0VPypnbJ1Orlf5Hyxd65se5yzyHIY7ZI=";
+ tag = "6.3";
+ hash = "sha256-ZoK6H3ldrgHjCoMgDg+6XAD+ZaCwLuUgPq0fK+GdlCs=";
};
rmluiCmakeFlags = [
@@ -27,13 +27,23 @@
rmlui = pkgs.stdenv.mkDerivation {
pname = "rmlui";
- version = "master";
+ version = "6.3";
src = rmluiSrc;
nativeBuildInputs = [ pkgs.cmake pkgs.pkg-config ];
buildInputs = [ pkgs.freetype ];
cmakeFlags = rmluiCmakeFlags ++ [ "-DBUILD_SHARED_LIBS=ON" ];
};
+ raylibPatched = pkgs.raylib.overrideAttrs (old: {
+ postPatch = (old.postPatch or "") + ''
+ substituteInPlace src/platforms/rcore_desktop_glfw.c \
+ --replace-fail \
+ 'glfwSetJoystickCallback(NULL);' \
+ 'glfwWindowHint(GLFW_STENCIL_BITS, 8);
+ glfwSetJoystickCallback(NULL);'
+ '';
+ });
+
nativeBuildTools = with pkgs; [
cmake
pkg-config
@@ -41,7 +51,7 @@
];
nativeRuntimeDeps = with pkgs; [
- raylib
+ raylibPatched
libGL
libX11
libXcursor
@@ -79,6 +89,8 @@
--prefix LD_LIBRARY_PATH : "${pkgs.lib.makeLibraryPath nativeRuntimeDeps}"
'';
};
+
+ packages.raylibPatched = raylibPatched;
}
);
}
diff --git a/readme.md b/readme.md
index 2af3ca0..7abf2c2 100644
--- a/readme.md
+++ b/readme.md
@@ -7,7 +7,7 @@ I originally began creating this for a Game Jam project where I got the basic re
## Roadmap
*Rendering features (from the RmlUi render interfface documentation https://mikke89.github.io/RmlUiDoc/pages/cpp_manual/interfaces/render.html#feature-table):*
- [x] Basic rendering
-- [ ] Clip Mask
+- [x] Clip Mask
- [x] Transforms
- [ ] Layers
- [ ] Render textures
diff --git a/src/backend/RaylibRenderInterface.cpp b/src/backend/RaylibRenderInterface.cpp
index 90b5c7c..ea908b0 100644
--- a/src/backend/RaylibRenderInterface.cpp
+++ b/src/backend/RaylibRenderInterface.cpp
@@ -3,6 +3,8 @@
#include
#include
+#include
+
#include
#include
@@ -127,3 +129,77 @@ void RaylibRenderInterface::SetTransform(const Rml::Matrix4f *transform) {
has_transform = false;
}
}
+
+void RaylibRenderInterface::DrawGeometryTriangles(Rml::CompiledGeometryHandle handle,
+ Rml::Vector2f translation) {
+ auto *geo = reinterpret_cast(handle);
+
+ rlPushMatrix();
+ rlTranslatef(translation.x, translation.y, 0.0f);
+ if (has_transform) {
+ rlMultMatrixf(current_transform.data());
+ }
+
+ 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]];
+ rlVertex2f(v.position.x, v.position.y);
+ }
+ }
+ rlEnd();
+
+ rlPopMatrix();
+}
+
+void RaylibRenderInterface::EnableClipMask(bool enable) {
+ rlDrawRenderBatchActive();
+ clip_mask_enabled = enable;
+
+ if (enable) {
+ glEnable(GL_STENCIL_TEST);
+ glStencilFunc(GL_EQUAL, static_cast(clip_mask_level), 0xFF);
+ glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+ } else {
+ glDisable(GL_STENCIL_TEST);
+ }
+}
+
+void RaylibRenderInterface::RenderToClipMask(Rml::ClipMaskOperation operation,
+ Rml::CompiledGeometryHandle geometry,
+ Rml::Vector2f translation) {
+ rlDrawRenderBatchActive();
+ glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+
+ switch (operation) {
+ case Rml::ClipMaskOperation::Set:
+ glClearStencil(0);
+ glClear(GL_STENCIL_BUFFER_BIT);
+ glStencilFunc(GL_ALWAYS, 1, 0xFF);
+ glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
+ clip_mask_level = 1;
+ break;
+
+ case Rml::ClipMaskOperation::SetInverse:
+ glClearStencil(1);
+ glClear(GL_STENCIL_BUFFER_BIT);
+ glStencilFunc(GL_ALWAYS, 0, 0xFF);
+ glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
+ clip_mask_level = 1;
+ break;
+
+ case Rml::ClipMaskOperation::Intersect:
+ glStencilFunc(GL_EQUAL, static_cast(clip_mask_level), 0xFF);
+ glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
+ clip_mask_level += 1;
+ break;
+ }
+
+ DrawGeometryTriangles(geometry, translation);
+ rlDrawRenderBatchActive();
+
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+
+ glStencilFunc(GL_EQUAL, static_cast(clip_mask_level), 0xFF);
+ glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+}
diff --git a/src/backend/RaylibRenderInterface.h b/src/backend/RaylibRenderInterface.h
index 45de261..bfefe7b 100644
--- a/src/backend/RaylibRenderInterface.h
+++ b/src/backend/RaylibRenderInterface.h
@@ -32,6 +32,11 @@ public:
void SetTransform(const Rml::Matrix4f *transform) override;
+ void EnableClipMask(bool enable) override;
+ void RenderToClipMask(Rml::ClipMaskOperation operation,
+ Rml::CompiledGeometryHandle geometry,
+ Rml::Vector2f translation) override;
+
private:
void ApplyScissor();
@@ -40,4 +45,8 @@ private:
bool has_transform = false;
Rml::Matrix4f current_transform;
+
+ bool clip_mask_enabled = false;
+ unsigned int clip_mask_level = 0;
+ void DrawGeometryTriangles(Rml::CompiledGeometryHandle geometry, Rml::Vector2f translation);
};
diff --git a/src/main.cpp b/src/main.cpp
index cd28cee..0f261a1 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -10,6 +10,8 @@
#include "backend/RaylibSystemInterface.h"
#include "backend/RaylibInput.h"
+#include
+
static RaylibSystemInterface system_interface;
static RaylibRenderInterface render_interface;
static Rml::Context *ctx;
@@ -24,12 +26,24 @@ int main() {
Rml::SetSystemInterface(&system_interface);
Rml::SetRenderInterface(&render_interface);
Rml::Initialise();
+ TraceLog(LOG_INFO, "RmlUi version: %s", Rml::GetVersion().c_str());
ctx = Rml::CreateContext("main", Rml::Vector2i(600, 800));
Rml::Debugger::Initialise(ctx);
auto doc = ctx->LoadDocument("assets/main.rml");
doc->Show();
+
+ Camera3D cam3;
+ cam3.position = Vector3 {0.0f, 10.0f, 10.0f};
+ cam3.target = Vector3 {0.0f, 0.0f, 0.0f};
+ cam3.up = Vector3 {0, 1.0f, 0.0f};
+ cam3.fovy = 45.0f;
+ cam3.projection = CAMERA_PERSPECTIVE;
+
+ Vector3 cubePos = Vector3 {0.0f, 0.0f, 0.0f};
+
+ // DisableCursor();
while (!WindowShouldClose()) {
@@ -37,14 +51,24 @@ int main() {
ctx->SetDimensions(Rml::Vector2i(GetScreenWidth(), GetScreenHeight()));
}
+ // UpdateCamera(&cam3, CAMERA_FREE);
+
ForwardInputToRml(ctx);
ctx->Update();
-
+
+ if (IsKeyPressed(KEY_Z)) cam3.target = Vector3 {0.0f, 0.0f, 0.0f};
BeginDrawing();
ClearBackground(BLACK);
DrawFPS(10, 10);
- DrawText("Hello!", GetScreenWidth()/2, GetScreenHeight()/2, 10, RAYWHITE);
+ // DrawText("Hello!", GetScreenWidth()/2, GetScreenHeight()/2, 10, RAYWHITE);
+
+ BeginMode3D(cam3);
+ DrawCube(cubePos, 2.0f, 2.0f, 2.0f, RED);
+ DrawCubeWires(cubePos, 2.0f, 2.0f, 2.0f, BLUE);
+ DrawGrid(10, 1.0f);
+ EndMode3D();
+
ctx->Render();
EndDrawing();
}