This commit is contained in:
2026-02-25 08:36:11 +01:00
parent 06f784d0b1
commit 6a1392b9b6
6 changed files with 128 additions and 63 deletions

2
build
View File

@@ -5,7 +5,7 @@ COMMON_FLAGS="-DOS_LINUX=1 -DCOMPOSITOR_WAYLAND=1 -xc -std=c99 -Wno-initializer-
echo [Building target] echo [Building target]
if [ $DEBUG ]; then if [ $DEBUG ]; then
time clang -O0 -g -g2 $COMMON_FLAGS -DDJSTDLIB_DEBUG=1 ./src/main.c -o ./target/somaesque $LIB_INCLUDE time clang -O1 -g -g2 $COMMON_FLAGS -O1 -fsanitize=address,undefined -DDJSTDLIB_DEBUG=1 ./src/main.c -o ./target/somaesque $LIB_INCLUDE
else else
time clang -O2 $COMMON_FLAGS ./src/main.c -o ./target/somaesque $LIB_INCLUDE time clang -O2 $COMMON_FLAGS ./src/main.c -o ./target/somaesque $LIB_INCLUDE
fi fi

View File

@@ -1,4 +1,6 @@
#include "Texture.h" #include "Texture.h"
#include <asm-generic/errno-base.h>
#include <errno.h>
Texture createTexture(const char* bitmap, int32 width, int32 height) { Texture createTexture(const char* bitmap, int32 width, int32 height) {
Texture result = {0}; Texture result = {0};
@@ -20,16 +22,44 @@ Texture createTexture(const char* bitmap, int32 width, int32 height) {
DefineList(stbtt_bakedchar, STBBakedChar); DefineList(stbtt_bakedchar, STBBakedChar);
static void saveGrayscaleTarga(string location, const char *bytes, int width, int height) {
char tgaHeader[18] = {
// Image ID length
0x0,
// Color map type
0x0,
// Image type
0x3,
// Color map info (unused)
0x0, 0x0, 0x0, 0x0, 0x0,
// Image spec
0x0, 0x0, // x origin
0x0, 0x0, // y origin
width & 0xFF, (width >> 8) & 0xFF, // width
height & 0xFF, (height >> 8) & 0xFF, // width
0x8, // bits per px (depth)
0b00001000, // image descriptor
};
os_writeEntireFile(location, tgaHeader, ArrayCount(tgaHeader));
os_fileAppend(location, bytes, width * height);
}
Font createFont(Arena *arena, string ttfLocation, real32 lineHeight) { Font createFont(Arena *arena, string ttfLocation, real32 lineHeight) {
const int CODEPOINT_START = 32; const int CODEPOINT_START = 32;
const int CODEPOINT_END = 126; const int CODEPOINT_END = 126;
int32 atlasWidth = 16 * lineHeight; int32 atlasWidth = 512;//16 * lineHeight;
int32 atlasHeight = 6 * lineHeight; int32 atlasHeight = 512;// * lineHeight;
STBBakedCharList bakedCharlist = PushFullListZero(arena, STBBakedCharList, CODEPOINT_END - CODEPOINT_START); STBBakedCharList bakedCharlist = PushFullListZero(arena, STBBakedCharList, CODEPOINT_END - CODEPOINT_START);
string fontFile = os_readEntireFile(arena, ttfLocation); string fontFile = os_readEntireFile(arena, ttfLocation);
stbtt_fontinfo info;
stbtt_InitFont(&info, (unsigned char *)fontFile.str, stbtt_GetFontOffsetForIndex((unsigned char *)fontFile.str, 0));
int ascent, descent, lineGap;
stbtt_GetFontVMetrics(&info, &ascent, &descent, &lineGap);
real32 scale = stbtt_ScaleForPixelHeight(&info, 96);
char *bakedFontBitmap = PushArrayZero(arena, char, atlasWidth*atlasHeight); char *bakedFontBitmap = PushArrayZero(arena, char, atlasWidth*atlasHeight);
int32 bake_result = stbtt_BakeFontBitmap( int32 bake_result = stbtt_BakeFontBitmap(
(unsigned char *)fontFile.str, 0, (unsigned char *)fontFile.str, 0,
@@ -38,6 +68,8 @@ Font createFont(Arena *arena, string ttfLocation, real32 lineHeight) {
CODEPOINT_START, CODEPOINT_END - CODEPOINT_START, CODEPOINT_START, CODEPOINT_END - CODEPOINT_START,
bakedCharlist.data); bakedCharlist.data);
saveGrayscaleTarga(s("bakedfont.tga"), bakedFontBitmap, atlasWidth, atlasHeight);
GlyphMetaList glyphMeta = PushFullListZero(arena, GlyphMetaList, bakedCharlist.length); GlyphMetaList glyphMeta = PushFullListZero(arena, GlyphMetaList, bakedCharlist.length);
real32 x, y; real32 x, y;
real32 lastX, lastY; real32 lastX, lastY;
@@ -48,7 +80,7 @@ Font createFont(Arena *arena, string ttfLocation, real32 lineHeight) {
.uv0=(RLVector2){q.s0, q.t1}, .uv0=(RLVector2){q.s0, q.t1},
.uv1=(RLVector2){q.s1, q.t0}, .uv1=(RLVector2){q.s1, q.t0},
.xOffset=q.x0 - lastX, .xOffset=q.x0 - lastX,
.yOffset=q.y0 + lineHeight, .yOffset=q.y0 + lineHeight + scale * descent,
.width=q.x1-q.x0, .width=q.x1-q.x0,
.height=q.y1-q.y0, .height=q.y1-q.y0,
}; };
@@ -63,7 +95,6 @@ Font createFont(Arena *arena, string ttfLocation, real32 lineHeight) {
glGenTextures(1, &result.texId); glGenTextures(1, &result.texId);
glBindTexture(GL_TEXTURE_2D, result.texId); glBindTexture(GL_TEXTURE_2D, result.texId);
//glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, atlasWidth, atlasHeight, 0, GL_RED, GL_UNSIGNED_BYTE, bakedFontBitmap); glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, atlasWidth, atlasHeight, 0, GL_RED, GL_UNSIGNED_BYTE, bakedFontBitmap);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

View File

@@ -140,16 +140,15 @@ void framebufferSizeCallback(GLFWwindow *window, int width, int height) {
} }
GLFWwindow *initWindowAndGL(uint32 windowWidth, uint32 windowHeight) { GLFWwindow *initWindowAndGL(uint32 windowWidth, uint32 windowHeight) {
#ifdef OS_LINUX if (!glfwInit()) {
glfwInitHint(GLFW_PLATFORM, GLFW_PLATFORM_X11); return NULL;
#endif }
glfwWindowHintString(GLFW_WAYLAND_APP_ID, "Somaesque");
glfwInit();
//glfwWindowHintString(GLFW_WAYLAND_APP_ID, "Somaesque");
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_SAMPLES, 4);
GLFWwindow *window = glfwCreateWindow( GLFWwindow *window = glfwCreateWindow(
windowWidth, windowWidth,
windowHeight, windowHeight,
@@ -174,11 +173,11 @@ GLFWwindow *initWindowAndGL(uint32 windowWidth, uint32 windowHeight) {
} }
glViewport(0, 0, windowWidth, windowHeight); glViewport(0, 0, windowWidth, windowHeight);
glfwSwapInterval(0); glfwSwapInterval(1);
glfwSetFramebufferSizeCallback(window, framebufferSizeCallback);
glfwSetInputMode(window, GLFW_CURSOR | GLFW_RAW_MOUSE_MOTION, GLFW_CURSOR_NORMAL); glfwSetInputMode(window, GLFW_CURSOR | GLFW_RAW_MOUSE_MOTION, GLFW_CURSOR_NORMAL);
glfwSetWindowSize(window, windowWidth, windowHeight); glfwSetWindowSize(window, windowWidth, windowHeight);
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
glEnable(GL_MULTISAMPLE);
return window; return window;
} }
@@ -365,7 +364,7 @@ static void ui_Interaction(UI_Context *ui, Soma *soma) {
for (int y = 0; y < currentPolycube->repr.dim_y; y++) UI(.childGap=childGap) { for (int y = 0; y < currentPolycube->repr.dim_y; y++) UI(.childGap=childGap) {
for (int z = 0; z < currentPolycube->repr.dim_z; z++) { for (int z = 0; z < currentPolycube->repr.dim_z; z++) {
bool cellActive = filledAt(&currentPolycube->repr, x, y, z); bool cellActive = filledAt(&currentPolycube->repr, x, y, z);
if (ui_CheckboxRect(ui, &cellActive, UI_CreateRect( if (ui_CheckboxRect(ui, &cellActive, UI_RectAttr(
.width = boxSize, .width = boxSize,
.height = boxSize, .height = boxSize,
.borderRadius = 2, .borderRadius = 2,
@@ -385,39 +384,35 @@ static void ui_Interaction(UI_Context *ui, Soma *soma) {
static void DJUI_Soma(UI_Context *ui, Soma *soma) { static void DJUI_Soma(UI_Context *ui, Soma *soma) {
RLVector4 darkgrey = {0.2, 0.2, 0.2, 1}; RLVector4 darkgrey = {0.2, 0.2, 0.2, 1};
RLVector4 grey = {0.4, 0.4, 0.4, 1}; RLVector4 grey = {0.4, 0.4, 0.4, 1};
UI_Padding btnPad = {.left=10, .right=10, .top=5, .bottom=5};
UI(.flags=UI_Flag_HeightGrow | UI_Flag_WidthGrow) { UI(.flags=UI_Flag_HeightGrow | UI_Flag_WidthGrow) {
UI(.padding={.left=20, .right=20, .top=5}, .color=darkgrey, .flags=UI_Flag_HeightGrow | UI_Flag_Vertical) { UI(.padding={.left=20, .right=20}, .color=darkgrey, .flags=UI_Flag_HeightGrow | UI_Flag_Vertical) {
UI() UI_Text(s("Somaesque"), .lineHeight=26); UI(.padding=UI_PadUniform(10)) UI_Txt(s("Somaesque"), .lineHeight=26);
ui_Interaction(ui, soma); ui_Interaction(ui, soma);
} }
UI(.flags=UI_Flag_Vertical | UI_Flag_HeightGrow | UI_Flag_WidthGrow) { UI(.flags=UI_Flag_Vertical | UI_Flag_HeightGrow | UI_Flag_WidthGrow) {
UI(.padding=UI_PadUniform(10), .color=darkgrey, .flags=UI_Flag_WidthGrow) { UI(.padding=UI_PadUniform(10), .color=darkgrey, .flags=UI_Flag_WidthGrow) {
UI(.flags=UI_Flag_WidthGrow) {
UI(.childGap=10) { UI(.childGap=10) {
if (ui_Button(ui, UI_CreateRect(.height=30, .padding={.left=10, .right=10}, .color=grey), UI_CreateText(s("Previous"), .lineHeight=20))) { if (ui_Button(ui, UI_RectAttr(.padding=btnPad, .color=grey), UI_TxtAttr(s("Previous"), .lineHeight=20))) {
advanceDisplayReverse(soma); advanceDisplayReverse(soma);
} }
if (ui_Button(ui, UI_CreateRect(.height=30, .padding={.left=10, .right=10}, .color=grey), UI_CreateText(s("Next"), .lineHeight=20))) { if (ui_Button(ui, UI_RectAttr(.padding=btnPad, .color=grey), UI_TxtAttr(s("Next"), .lineHeight=20))) {
advanceDisplay(soma); advanceDisplay(soma);
} }
} }
} UI(.flags=UI_Flag_WidthGrow);
UI(.childGap=10) { UI(.childGap=10) {
if (ui_Button(ui, UI_CreateRect( if (ui_Button(ui, UI_RectAttr(
.width=30, .padding=btnPad,
.height=30,
.padding={.left=10, .right=10},
.color=soma->state.displayingSolutions ? grey : (RLVector4){0.2, 0.2, 0.7, 1}, .color=soma->state.displayingSolutions ? grey : (RLVector4){0.2, 0.2, 0.7, 1},
), UI_CreateText(s("Design"), .lineHeight=20))) { ), UI_TxtAttr(s("Design"), .lineHeight=20))) {
soma->state.displayingSolutions = false; soma->state.displayingSolutions = false;
} }
if (ui_Button(ui, UI_CreateRect( if (ui_Button(ui, UI_RectAttr(
.width=30, .padding=btnPad,
.height=30,
.padding={.left=10, .right=10},
.color=soma->state.displayingSolutions ? (RLVector4){0.2, 0.2, 0.7, 1} : grey, .color=soma->state.displayingSolutions ? (RLVector4){0.2, 0.2, 0.7, 1} : grey,
), UI_CreateText(s("Solve"), .lineHeight=20))) { ), UI_TxtAttr(s("Solve"), .lineHeight=20))) {
if (!soma->state.displayingSolutions) { if (!soma->state.displayingSolutions) {
tryScheduleSolve(soma); tryScheduleSolve(soma);
} else { } else {
@@ -426,7 +421,22 @@ static void DJUI_Soma(UI_Context *ui, Soma *soma) {
} }
} }
} }
UI(.flags=UI_Flag_WidthGrow | UI_Flag_HeightGrow | UI_Flag_3DScene); UI(.flags=UI_Flag_Vertical | UI_Flag_WidthGrow | UI_Flag_HeightGrow | UI_Flag_3DScene) {
UI(.flags=UI_Flag_HeightGrow);
UI(.flags=UI_Flag_WidthGrow, .padding=UI_PadUniform(10)) {
if (soma->solveTaskCtx.taskStatus == SolveTaskStatus_Solving) {
UI_Txt(s("Solving..."), .lineHeight=26);
} else {
bool soln = soma->state.displayingSolutions;
UI_TxtSeg(soln ? s("Solution") : s("Polycube"), .lineHeight=26);
UI_TxtSeg(
strPrintf(ui->arena, " #%d (%d total)",
(soln ? soma->state.displayedSolution : soma->state.displayedPolycube) + 1,
soln ? soma->solutions.length : soma->polycubeInput.length),
.lineHeight=26);
}
}
}
} }
} }
} }
@@ -499,6 +509,13 @@ static void updateWindow(Soma *soma) {
const int32 MAX_POLYCUBE_INPUT = 64; const int32 MAX_POLYCUBE_INPUT = 64;
const int32 TARGET_FPS = 144; const int32 TARGET_FPS = 144;
void APIENTRY glDebugCallback(GLenum source, GLenum type, GLuint id,
GLenum severity, GLsizei length,
const GLchar* message, const void* userParam)
{
fprintf(stderr, "GL: %s\n", message);
}
int mainGfx() { int mainGfx() {
Arena *arena = arenaAlloc(Megabytes(128)); Arena *arena = arenaAlloc(Megabytes(128));
Arena *solutionsArena = arenaAlloc(Megabytes(128)); Arena *solutionsArena = arenaAlloc(Megabytes(128));
@@ -510,6 +527,10 @@ int mainGfx() {
return 1; return 1;
} }
glEnable(GL_DEBUG_OUTPUT);
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
glDebugMessageCallback(glDebugCallback, NULL);
Scene mainScene = createScene(arena); Scene mainScene = createScene(arena);
Camera cam = createCamera(winWidth, winHeight); Camera cam = createCamera(winWidth, winHeight);
Renderer renderer = createRenderer(arena, &mainScene, &cam, createSceneGraphNode(&mainScene)); Renderer renderer = createRenderer(arena, &mainScene, &cam, createSceneGraphNode(&mainScene));
@@ -564,6 +585,7 @@ int mainGfx() {
}; };
glfwSetWindowUserPointer(windowHandle, &soma); glfwSetWindowUserPointer(windowHandle, &soma);
glfwSetFramebufferSizeCallback(windowHandle, framebufferSizeCallback);
glfwSetScrollCallback(windowHandle, onMouseScroll); glfwSetScrollCallback(windowHandle, onMouseScroll);
VoxelSpaceReprList stdSoma = AsList(VoxelSpaceReprList, STD_SOMA); VoxelSpaceReprList stdSoma = AsList(VoxelSpaceReprList, STD_SOMA);

View File

@@ -130,7 +130,6 @@ static void updateCharObjectBuffers(Renderer *r) {
GL_UpdateBuffer(r->chars.color); GL_UpdateBuffer(r->chars.color);
} }
static void updateRectangleObjectBuffers(Renderer *r) { static void updateRectangleObjectBuffers(Renderer *r) {
glBindVertexArray(r->rects.vao); glBindVertexArray(r->rects.vao);
GL_UpdateBuffer(r->rects.p0); GL_UpdateBuffer(r->rects.p0);
@@ -170,6 +169,8 @@ void renderBegin(Renderer *r) {
r->sceneY = 0; r->sceneY = 0;
} }
#define CHECK() do{ GLenum e=glGetError(); if(e) printf("GL err 0x%x at %s:%d\n",e,__FILE__,__LINE__); }while(0)
void renderEnd(Renderer *r) { void renderEnd(Renderer *r) {
// 3D Scene // 3D Scene
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
@@ -222,22 +223,25 @@ void renderEnd(Renderer *r) {
updateCharObjectBuffers(r); updateCharObjectBuffers(r);
glUseProgram(r->textShader->progId); glUseProgram(r->textShader->progId);
setUniformMat4fv(r->textShader, "projection", &ortho); setUniformMat4fv(r->textShader, "projection", &ortho);
glEnable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0); CHECK();
glBindTexture(GL_TEXTURE_2D, r->activeFont->texId); glBindTexture(GL_TEXTURE_2D, r->activeFont->texId); CHECK();
glActiveTexture(GL_TEXTURE1); glActiveTexture(GL_TEXTURE1); CHECK();
glBindTexture(GL_TEXTURE_BUFFER, r->activeFont->glyphTableTexId); glBindTexture(GL_TEXTURE_BUFFER, r->activeFont->glyphTableTexId); CHECK();
setUniform1i(r->textShader, "glyph_table", 1); setUniform1i(r->textShader, "glyph_table", 1); CHECK();
glBindVertexArray(r->chars.vao); glBindVertexArray(r->chars.vao); CHECK();
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, r->chars.begin.buf.length); glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, r->chars.begin.buf.length); CHECK();
glDisable(GL_BLEND); glDisable(GL_BLEND);
} }
void rendererPlaceRectangle(Renderer *r, real32 x, real32 y, real32 width, real32 height, RLVector4 color, real32 borderRadius, real32 borderThickness) { void rendererPlaceRectangle(Renderer *r, real32 x, real32 y, real32 width, real32 height, RLVector4 color, real32 borderRadius, real32 borderThickness) {
x = roundf(x);
y = roundf(y);
width = roundf(width);
height = roundf(height);
ListAppend(r->rects.p0.buf, ((RLVector2){ x, y })); ListAppend(r->rects.p0.buf, ((RLVector2){ x, y }));
ListAppend(r->rects.p1.buf, ((RLVector2){ x + width, y + height })); ListAppend(r->rects.p1.buf, ((RLVector2){ x + width, y + height }));
ListAppend(r->rects.color.buf, color); ListAppend(r->rects.color.buf, color);

View File

@@ -1,8 +1,6 @@
#include "ui.h" #include "ui.h"
#include "GLFW/glfw3.h" #include "GLFW/glfw3.h"
#include "lib/djstdlib/core.h" #include "lib/djstdlib/core.h"
#include <stdio.h>
#include <string.h>
UI_Context *__UI_current_ctx__ = NULL; UI_Context *__UI_current_ctx__ = NULL;
@@ -186,14 +184,15 @@ void ui_begin(UI_Context *ui) {
void ui_end(UI_Context *ui) { void ui_end(UI_Context *ui) {
ui_closeElement(ui); ui_closeElement(ui);
// 1. Calculate layout // 1) a. Calculate layout
ui_sizingPass(ui, true, ui->rootRect); ui_sizingPass(ui, true, ui->rootRect); // x
ui_sizingPass(ui, false, ui->rootRect); ui_sizingPass(ui, false, ui->rootRect); // y
ui_calcLayout(ui, true, ui->rootRect); // 1) b.
ui_calcLayout(ui, false, ui->rootRect); ui_calcLayout(ui, true, ui->rootRect); // x
ui_calcLayout(ui, false, ui->rootRect); // y
// 2. Create render commands: // 2) Create render commands:
for (EachEl(ui->rects, UI_Rect, rect)) { for (EachEl(ui->rects, UI_Rect, rect)) {
rendererPlaceRectangle( rendererPlaceRectangle(
@@ -211,8 +210,8 @@ void ui_end(UI_Context *ui) {
rendererPlaceString( rendererPlaceString(
ui->renderer, ui->renderer,
str->s, str->s,
rect->x + str->xOffset, rect->x + str->xOffset + rect->padding.left,
rect->y + str->yOffset, rect->y + str->yOffset + rect->padding.top,
str->color, str->color,
str->lineHeight str->lineHeight
); );
@@ -266,8 +265,7 @@ void ui_closeElement(UI_Context *ui) {
if (currRect->width != -1) { if (currRect->width != -1) {
currRect->resolvedWidth = currRect->width; currRect->resolvedWidth = currRect->width;
} } else if (currRect->minWidth == -1) {
if (currRect->minWidth == -1) {
if (currRect->stringData) { if (currRect->stringData) {
real32 charWidth = currRect->stringData->lineHeight / ui->renderer->activeFont->lineHeight * ui->renderer->activeFont->charWidth; real32 charWidth = currRect->stringData->lineHeight / ui->renderer->activeFont->lineHeight * ui->renderer->activeFont->charWidth;
currRect->minWidth = charWidth*currRect->stringData->s.length; currRect->minWidth = charWidth*currRect->stringData->s.length;
@@ -278,7 +276,7 @@ void ui_closeElement(UI_Context *ui) {
currRect->resolvedWidth = currRect->padding.left + currRect->padding.right + (currRect->resolvedWidth < currRect->minWidth ? currRect->minWidth : currRect->resolvedWidth); currRect->resolvedWidth = currRect->padding.left + currRect->padding.right + (currRect->resolvedWidth < currRect->minWidth ? currRect->minWidth : currRect->resolvedWidth);
if (currRect->height != -1) { if (currRect->height != -1) {
currRect->resolvedHeight = currRect->height; currRect->resolvedHeight = currRect->height - currRect->padding.top - currRect->padding.bottom;
} else if (currRect->minHeight == -1) { } else if (currRect->minHeight == -1) {
if (currRect->stringData) { if (currRect->stringData) {
currRect->minHeight = currRect->stringData->lineHeight; currRect->minHeight = currRect->stringData->lineHeight;

View File

@@ -38,10 +38,12 @@ struct Input {
enum UI_Flag { enum UI_Flag {
UI_Flag_WidthGrow=1<<0, // Default is fixed UI_Flag_WidthGrow=1<<0, // Default is fixed
UI_Flag_HeightGrow=1<<1, UI_Flag_HeightGrow=1<<1, // Default is fixed
UI_Flag_Vertical=1<<2, // Default is horizontal UI_Flag_Vertical=1<<2, // Default is horizontal
UI_Flag_3DScene=1<<3, UI_Flag_3DScene=1<<3,
UI_Flag_Center=1<<4, UI_Flag_Center=1<<4,
UI_Flag_Textalign_Right=1<<5, // Default is left
UI_Flag_Textalign_Center=1<<6,
// .. // ..
UI_Flag_COUNT, UI_Flag_COUNT,
}; };
@@ -61,12 +63,13 @@ struct UI_RectStr {
real32 yOffset; real32 yOffset;
real32 lineHeight; real32 lineHeight;
RLVector4 color; RLVector4 color;
int8 alignment;
}; };
typedef struct UI_Rect UI_Rect; typedef struct UI_Rect UI_Rect;
struct UI_Rect { struct UI_Rect {
/** UI_Rect_LayoutFlag */ /** UI_Rect_LayoutFlag */
uint64 flags; enum UI_Flag flags;
int32 parent; int32 parent;
int32 firstChild; int32 firstChild;
@@ -135,13 +138,20 @@ bool ui_CheckboxRect(UI_Context *ui, bool *value, UI_Rect rect);
extern UI_Context *__UI_current_ctx__; extern UI_Context *__UI_current_ctx__;
#define UI(...) DeferLoop(ui_openElement((__UI_current_ctx__), UI_CreateRect(__VA_ARGS__)), ui_closeElement((__UI_current_ctx__))) #if 0
#define UI_CreateRect(...) ((UI_Rect){.minHeight=-1, .minWidth=-1, .width=-1, .height=-1, __VA_ARGS__}) #define UI_WIREFRAME .color=COLOR_RED, .borderThickness=1,
#else
#define UI_WIREFRAME
#endif
#define UI(...) DeferLoop(ui_openElement((__UI_current_ctx__), UI_RectAttr(__VA_ARGS__)), ui_closeElement((__UI_current_ctx__)))
#define UI_RectAttr(...) ((UI_Rect){UI_WIREFRAME .minHeight=-1, .minWidth=-1, .width=-1, .height=-1, __VA_ARGS__})
#define UI_FromRect(rect) DeferLoop(ui_openElement((__UI_current_ctx__), (rect)), ui_closeElement((__UI_current_ctx__))) #define UI_FromRect(rect) DeferLoop(ui_openElement((__UI_current_ctx__), (rect)), ui_closeElement((__UI_current_ctx__)))
#define UI_Pass(ui) DeferLoop(ui_begin((ui)), ui_end((ui))) #define UI_Pass(ui) DeferLoop(ui_begin((ui)), ui_end((ui)))
#define UI_PadUniform(padding) ((UI_Padding){ (padding), (padding), (padding), (padding) }) #define UI_PadUniform(padding) ((UI_Padding){ (padding), (padding), (padding), (padding) })
#define UI_NextID() ((__UI_current_ctx__)->rects.length) #define UI_NextID() ((__UI_current_ctx__)->rects.length)
#define UI_Text(str, ...) (ui_placeText((__UI_current_ctx__), ((UI_RectStr){ .xOffset=0, .yOffset=0, .lineHeight=-1, .s=(str), __VA_ARGS__ }))) #define UI_Txt(str, ...) (ui_placeText((__UI_current_ctx__), ((UI_RectStr){ .xOffset=0, .yOffset=0, .lineHeight=-1, .s=(str), __VA_ARGS__ })))
#define UI_CreateText(str, ...) ((UI_RectStr){ .xOffset=0, .yOffset=0, .lineHeight=-1, .s=(str), __VA_ARGS__ }) #define UI_TxtSeg(str, ...) UI() (UI_Txt((str), __VA_ARGS__))
#define UI_TxtAttr(str, ...) ((UI_RectStr){ .xOffset=0, .yOffset=0, .lineHeight=-1, .s=(str), __VA_ARGS__ })
#endif #endif