Add scrollbar and image objects, cropping, layout properties
This commit is contained in:
parent
295c882100
commit
6d5ba6037c
@ -4,18 +4,20 @@
|
|||||||
#include"k3font.h"
|
#include"k3font.h"
|
||||||
#include"k3menu.h"
|
#include"k3menu.h"
|
||||||
|
|
||||||
|
extern uint16_t GameWndH;
|
||||||
|
|
||||||
static inline void immdraw_fill_rect(int16_t x, int16_t y, int16_t w, int16_t h, float r, float g, float b, float a, float borderRadius) {
|
static inline void immdraw_fill_rect(int16_t x, int16_t y, int16_t w, int16_t h, float r, float g, float b, float a, float borderRadius) {
|
||||||
k3BatchAdd(NULL, (struct k3RectF) {0, 0, 1, 1}, (struct k3RectF) {
|
k3BatchAdd(NULL, (struct k3RectF) {0, 0, 1, 1}, (struct k3RectF) {
|
||||||
x, y,
|
x, GameWndH - y - h,
|
||||||
w, h
|
w, h
|
||||||
}, 0, (vec4) {r, g, b, a}, borderRadius);
|
}, 0, (vec4) {r, g, b, a}, borderRadius);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void immdraw_font_draw(struct k3Font *font, int16_t x, int16_t y, int16_t w, float sz, size_t len, const char *txt, int alignment, float r, float g, float b, float a) {
|
static inline void immdraw_font_draw(struct k3Font *font, int16_t x, int16_t y, int16_t w, float sz, size_t len, const char *txt, int alignment, float r, float g, float b, float a) {
|
||||||
if(alignment != k3M_ALIGN_LEFT) {
|
|
||||||
struct k3RectF txtsz;
|
struct k3RectF txtsz;
|
||||||
k3FontSz(font, sz, txt, &txtsz);
|
k3FontSz(font, sz, txt, &txtsz);
|
||||||
|
|
||||||
|
if(alignment != k3M_ALIGN_LEFT) {
|
||||||
if(alignment == k3M_ALIGN_CENTER) {
|
if(alignment == k3M_ALIGN_CENTER) {
|
||||||
x += w / 2.0f - txtsz.w / 2.0f;
|
x += w / 2.0f - txtsz.w / 2.0f;
|
||||||
} else {
|
} else {
|
||||||
@ -23,5 +25,51 @@ static inline void immdraw_font_draw(struct k3Font *font, int16_t x, int16_t y,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
k3FontDraw(font, x, y, sz, txt, (vec4) {r, g, b, a});
|
k3FontDraw(font, x, GameWndH - y - sz, sz, txt, (vec4) {r, g, b, a});
|
||||||
|
}
|
||||||
|
static inline void immdraw_font_size(struct k3Font *font, float sz, const char *txt, int16_t aabb[2]) {
|
||||||
|
struct k3RectF txtsz;
|
||||||
|
k3FontSz(font, sz, txt, &txtsz);
|
||||||
|
|
||||||
|
aabb[0] = ceilf(txtsz.w);
|
||||||
|
aabb[1] = ceilf(txtsz.h);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void immdraw_image_draw(k3MImageData *data, int16_t x, int16_t y, int16_t w, int16_t h, float r, float g, float b, float a) {
|
||||||
|
struct k3Tex *tex = *data;
|
||||||
|
k3BatchAdd(tex, (struct k3RectF) {0, 0, 1, 1}, (struct k3RectF) {x, GameWndH - y - h, w, h}, 0, (vec4) {r, g, b, a}, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int16_t crop_aabb[4] = {-1, -1, -1, -1};
|
||||||
|
static inline void immdraw_crop_get(int16_t aabb[4]) {
|
||||||
|
memcpy(aabb, crop_aabb, sizeof(crop_aabb));
|
||||||
|
}
|
||||||
|
static inline void immdraw_crop_set(int16_t aabb[4]) {
|
||||||
|
memcpy(crop_aabb, aabb, sizeof(crop_aabb));
|
||||||
|
|
||||||
|
if(aabb[0] == -1 && aabb[1] == -1 && aabb[2] == -1 && aabb[3] == -1) {
|
||||||
|
glDisable(GL_SCISSOR_TEST);
|
||||||
|
} else {
|
||||||
|
glEnable(GL_SCISSOR_TEST);
|
||||||
|
glScissor(aabb[0], GameWndH - aabb[3], aabb[2] - aabb[0], aabb[3] - aabb[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static inline void immdraw_crop_add(int16_t aabb[4]) {
|
||||||
|
int16_t newaabb[4];
|
||||||
|
memcpy(newaabb, crop_aabb, sizeof(newaabb));
|
||||||
|
|
||||||
|
if(aabb[0] > newaabb[0] || newaabb[0] == -1) {
|
||||||
|
newaabb[0] = aabb[0];
|
||||||
|
}
|
||||||
|
if(aabb[1] > newaabb[1] || newaabb[1] == -1) {
|
||||||
|
newaabb[1] = aabb[1];
|
||||||
|
}
|
||||||
|
if(aabb[2] < newaabb[2] || newaabb[2] == -1) {
|
||||||
|
newaabb[2] = aabb[2];
|
||||||
|
}
|
||||||
|
if(aabb[3] < newaabb[3] || newaabb[3] == -1) {
|
||||||
|
newaabb[3] = aabb[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
immdraw_crop_set(newaabb);
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
#define GL_FROM_K3ARBFP(k3m) ((GLuint) (uintptr_t) (k3m))
|
#define GL_FROM_K3ARBFP(k3m) ((GLuint) (uintptr_t) (k3m))
|
||||||
#define GL_FROM_K3GLSL(k3m) ((GLuint) (uintptr_t) (k3m))
|
#define GL_FROM_K3GLSL(k3m) ((GLuint) (uintptr_t) (k3m))
|
||||||
|
|
||||||
|
extern bool k3IsCore;
|
||||||
|
|
||||||
struct k3Tex {
|
struct k3Tex {
|
||||||
GLuint tex;
|
GLuint tex;
|
||||||
int cubemap;
|
int cubemap;
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include"gl.h"
|
#include"gl.h"
|
||||||
#include<string.h>
|
#include<string.h>
|
||||||
|
#include"k3_internal.h"
|
||||||
|
|
||||||
struct S {
|
struct S {
|
||||||
struct k3RectF src;
|
struct k3RectF src;
|
||||||
@ -19,6 +20,10 @@ static struct S *S;
|
|||||||
|
|
||||||
static struct k3GLSLP *coreProg;
|
static struct k3GLSLP *coreProg;
|
||||||
static GLuint coreVBO;
|
static GLuint coreVBO;
|
||||||
|
static GLuint coreUResolution;
|
||||||
|
|
||||||
|
static float ResolutionX;
|
||||||
|
static float ResolutionY;
|
||||||
|
|
||||||
void k3BatchInit() {
|
void k3BatchInit() {
|
||||||
if(k3IsCore) {
|
if(k3IsCore) {
|
||||||
@ -31,11 +36,12 @@ void k3BatchInit() {
|
|||||||
"out vec2 v_uv;\n"
|
"out vec2 v_uv;\n"
|
||||||
"out vec4 v_color;\n"
|
"out vec4 v_color;\n"
|
||||||
"out vec2 v_size;\n"
|
"out vec2 v_size;\n"
|
||||||
|
"uniform vec2 u_resolution;\n"
|
||||||
"void main() {\n"
|
"void main() {\n"
|
||||||
" v_uv = a_uv;\n"
|
" v_uv = a_uv;\n"
|
||||||
" v_color = a_color;\n"
|
" v_color = a_color;\n"
|
||||||
" v_size = a_size;\n"
|
" v_size = a_size;\n"
|
||||||
" gl_Position = vec4(vec2(a_pos.x / 3600.0, a_pos.y / 2025.0) * 2.0 - 1.0, 0.0, 1.0);\n"
|
" gl_Position = vec4(vec2(a_pos.x / u_resolution.x, a_pos.y / u_resolution.y) * 2.0 - 1.0, 0.0, 1.0);\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
, NULL), k3ShaderGLSLF(
|
, NULL), k3ShaderGLSLF(
|
||||||
"#version 330\n"
|
"#version 330\n"
|
||||||
@ -58,6 +64,8 @@ void k3BatchInit() {
|
|||||||
"}\n"
|
"}\n"
|
||||||
, NULL), NULL);
|
, NULL), NULL);
|
||||||
|
|
||||||
|
coreUResolution = k3ProgramGetUId(coreProg, "u_resolution");
|
||||||
|
|
||||||
glGenBuffers(1, &coreVBO);
|
glGenBuffers(1, &coreVBO);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -101,6 +109,7 @@ void k3BatchFlush() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
glDisable(GL_DEPTH_TEST);
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
glDisable(GL_CULL_FACE);
|
||||||
|
|
||||||
if(GLAD_GL_ARB_vertex_program) {
|
if(GLAD_GL_ARB_vertex_program) {
|
||||||
glDisable(GL_VERTEX_PROGRAM_ARB);
|
glDisable(GL_VERTEX_PROGRAM_ARB);
|
||||||
@ -124,6 +133,7 @@ void k3BatchFlush() {
|
|||||||
|
|
||||||
if(k3IsCore) {
|
if(k3IsCore) {
|
||||||
glUseProgram((GLuint) coreProg);
|
glUseProgram((GLuint) coreProg);
|
||||||
|
glUniform2f(coreUResolution, ResolutionX, ResolutionY);
|
||||||
|
|
||||||
float *farr = alloca(SCount * 60 * sizeof(*farr));
|
float *farr = alloca(SCount * 60 * sizeof(*farr));
|
||||||
|
|
||||||
@ -257,3 +267,16 @@ void k3BatchFlush() {
|
|||||||
|
|
||||||
SCount = 0;
|
SCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void k3BatchSetResolution(float w, float h) {
|
||||||
|
ResolutionX = w;
|
||||||
|
ResolutionY = h;
|
||||||
|
|
||||||
|
if(!k3IsCore) {
|
||||||
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
glLoadIdentity();
|
||||||
|
glOrtho(0, ResolutionX, 0, ResolutionY, -1, 1);
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
glLoadIdentity();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -12,3 +12,5 @@ struct k3RectF {
|
|||||||
|
|
||||||
void k3BatchAdd(struct k3Tex *tex, struct k3RectF src, struct k3RectF dst, float rot, vec4 color, float borderRadius);
|
void k3BatchAdd(struct k3Tex *tex, struct k3RectF src, struct k3RectF dst, float rot, vec4 color, float borderRadius);
|
||||||
void k3BatchFlush();
|
void k3BatchFlush();
|
||||||
|
|
||||||
|
void k3BatchSetResolution(float w, float h);
|
||||||
|
@ -98,12 +98,17 @@ static uint32_t read_utf8(const char **txt_) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void k3FontSz(struct k3Font *this, float sz, const char *txt, struct k3RectF *ret) {
|
void k3FontSz(struct k3Font *this, float sz, const char *txt, struct k3RectF *ret) {
|
||||||
float x = 0, y = 0;
|
float x = 0, y = sz;
|
||||||
while(1) {
|
while(1) {
|
||||||
uint32_t cp = read_utf8(&txt);
|
uint32_t cp = read_utf8(&txt);
|
||||||
|
|
||||||
if(!cp) break;
|
if(!cp) break;
|
||||||
|
|
||||||
|
if(cp == 10) {
|
||||||
|
x = 0;
|
||||||
|
y += sz;
|
||||||
|
}
|
||||||
|
|
||||||
struct k3FontGlyph *g = k3FontGetGlyph(this, cp);
|
struct k3FontGlyph *g = k3FontGetGlyph(this, cp);
|
||||||
|
|
||||||
if(!g) continue;
|
if(!g) continue;
|
||||||
@ -111,6 +116,7 @@ void k3FontSz(struct k3Font *this, float sz, const char *txt, struct k3RectF *re
|
|||||||
x += g->xadvance * this->lineScale * sz;
|
x += g->xadvance * this->lineScale * sz;
|
||||||
}
|
}
|
||||||
ret->w = x;
|
ret->w = x;
|
||||||
|
ret->h = y;
|
||||||
}
|
}
|
||||||
void k3FontDraw(struct k3Font *this, float xStart, float yStart, float sz, const char *txt, vec4 color) {
|
void k3FontDraw(struct k3Font *this, float xStart, float yStart, float sz, const char *txt, vec4 color) {
|
||||||
float x = xStart, y = yStart;
|
float x = xStart, y = yStart;
|
||||||
|
308
src/k3menu.c
308
src/k3menu.c
@ -1,5 +1,6 @@
|
|||||||
#include"k3menu.h"
|
#include"k3menu.h"
|
||||||
|
|
||||||
|
#include"gl.h"
|
||||||
#include<string.h>
|
#include<string.h>
|
||||||
#include<stdio.h>
|
#include<stdio.h>
|
||||||
#include<GLFW/glfw3.h>
|
#include<GLFW/glfw3.h>
|
||||||
@ -36,6 +37,15 @@ void k3MArrange(struct k3MObj *this) {
|
|||||||
for(size_t c = 0; c < this->childCount; c++) {
|
for(size_t c = 0; c < this->childCount; c++) {
|
||||||
k3MArrange(this->children[c]);
|
k3MArrange(this->children[c]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
newev = (struct k3MEvent) {
|
||||||
|
.code = k3M_EVENT_POST_ARRANGE,
|
||||||
|
.kind = k3M_EVENTKIND_DIRECT,
|
||||||
|
|
||||||
|
.original = (void*) this,
|
||||||
|
.target = (void*) this,
|
||||||
|
};
|
||||||
|
k3MEventSend(&newev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool linear_measure(struct k3MEvent *ev, uint8_t *ud) {
|
static bool linear_measure(struct k3MEvent *ev, uint8_t *ud) {
|
||||||
@ -57,15 +67,27 @@ static bool linear_measure(struct k3MEvent *ev, uint8_t *ud) {
|
|||||||
static bool linear_arrange(struct k3MEvent *ev, uint8_t *ud) {
|
static bool linear_arrange(struct k3MEvent *ev, uint8_t *ud) {
|
||||||
struct k3MObj *o = ev->target;
|
struct k3MObj *o = ev->target;
|
||||||
|
|
||||||
size_t y = o->y;
|
intmax_t padding[4] = {};
|
||||||
|
struct k3MProperty *paddingProp = k3MFindProperty(o, k3M_PROP_PADDING, true);
|
||||||
|
if(paddingProp) {
|
||||||
|
for(int s = 0; s < 4; s++) {
|
||||||
|
if(paddingProp->units[s] == k3M_UNIT_ABSOLUTE) {
|
||||||
|
padding[s] = paddingProp->f[s];
|
||||||
|
} else if(paddingProp->units[s] == k3M_UNIT_PROPORTION && o->parent) {
|
||||||
|
padding[s] = paddingProp->f[s] * (s % 2 == 0 ? o->h : o->w);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t y = o->y + padding[0];
|
||||||
|
|
||||||
for(size_t i = 0; i < o->childCount; i++) {
|
for(size_t i = 0; i < o->childCount; i++) {
|
||||||
struct k3MObj *c = o->children[i];
|
struct k3MObj *c = o->children[i];
|
||||||
|
|
||||||
c->x = o->x;
|
c->x = o->x + padding[3];
|
||||||
c->y = y;
|
c->y = y;
|
||||||
|
|
||||||
c->w = c->wDesired;
|
c->w = c->wDesired - padding[1] - padding[3];
|
||||||
c->h = c->hDesired;
|
c->h = c->hDesired;
|
||||||
|
|
||||||
y += c->h;
|
y += c->h;
|
||||||
@ -115,14 +137,25 @@ int k3MRegisterEventHandler_(struct k3MObj *obj, uint16_t evcode, k3MEventHandle
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool k3MEventSend(struct k3MEvent *ev) {
|
bool k3MEventSend(struct k3MEvent *ev) {
|
||||||
|
struct k3MObj *target = ev->target; // ev->target can change
|
||||||
|
|
||||||
|
int16_t aabb[4];
|
||||||
|
if(ev->code == k3M_EVENT_DRAW && target->crop) {
|
||||||
|
immdraw_crop_get(aabb);
|
||||||
|
immdraw_crop_add(&(int16_t[4]) {target->x, target->y, target->x + target->w, target->y + target->h});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool status;
|
||||||
while(!event_send_nonrecur(ev)) {
|
while(!event_send_nonrecur(ev)) {
|
||||||
if(ev->kind == k3M_EVENTKIND_DIRECT) {
|
if(ev->kind == k3M_EVENTKIND_DIRECT) {
|
||||||
return false;
|
status = false;
|
||||||
|
goto ret;
|
||||||
} else if(ev->kind == k3M_EVENTKIND_BUBBLE) {
|
} else if(ev->kind == k3M_EVENTKIND_BUBBLE) {
|
||||||
ev->target = ev->target->parent;
|
ev->target = ev->target->parent;
|
||||||
|
|
||||||
if(ev->target == ev->original || !ev->target) {
|
if(ev->target == ev->original || !ev->target) {
|
||||||
return false;
|
status = false;
|
||||||
|
goto ret;
|
||||||
}
|
}
|
||||||
} else if(ev->kind == k3M_EVENTKIND_CAPTURE) {
|
} else if(ev->kind == k3M_EVENTKIND_CAPTURE) {
|
||||||
struct k3MObj *parent = ev->target;
|
struct k3MObj *parent = ev->target;
|
||||||
@ -132,19 +165,28 @@ bool k3MEventSend(struct k3MEvent *ev) {
|
|||||||
ev->target = parent->children[i];
|
ev->target = parent->children[i];
|
||||||
|
|
||||||
if(k3MEventSend(ev)) {
|
if(k3MEventSend(ev)) {
|
||||||
return true;
|
status = true;
|
||||||
|
goto ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
status = false;
|
||||||
|
goto ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
status = true;
|
||||||
|
|
||||||
|
ret:
|
||||||
|
if(ev->code == k3M_EVENT_DRAW && target->crop) {
|
||||||
|
immdraw_crop_set(aabb);
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void obj_draw(struct k3MObj *this) {
|
static void obj_draw_direct(struct k3MObj *this) {
|
||||||
struct k3MProperty *borderRadiusProp = k3MFindProperty(this, k3M_PROP_BORDER_RADIUS, false);
|
struct k3MProperty *borderRadiusProp = k3MFindProperty(this, k3M_PROP_BORDER_RADIUS, false);
|
||||||
float borderRadius = borderRadiusProp ? borderRadiusProp->si[0] : 0;
|
float borderRadius = borderRadiusProp ? borderRadiusProp->si[0] : 0;
|
||||||
|
|
||||||
@ -165,15 +207,19 @@ static void obj_draw(struct k3MObj *this) {
|
|||||||
static bool label_draw(struct k3MEvent *ev, uint8_t *ud) {
|
static bool label_draw(struct k3MEvent *ev, uint8_t *ud) {
|
||||||
struct k3MLabel *this = (void*) ev->target;
|
struct k3MLabel *this = (void*) ev->target;
|
||||||
|
|
||||||
obj_draw((void*) this);
|
obj_draw_direct((void*) this);
|
||||||
|
|
||||||
if(this->txt) {
|
if(this->txt) {
|
||||||
int alignment = k3M_ALIGN_CENTER;
|
int alignment = k3M_ALIGN_CENTER;
|
||||||
|
|
||||||
struct k3MProperty *prop = k3MFindProperty(this, k3M_PROP_HORIZONTAL_ALIGNMENT, false);
|
struct k3MProperty *propHA = k3MFindProperty(this, k3M_PROP_HORIZONTAL_ALIGNMENT, false);
|
||||||
if(prop) alignment = prop->si[0];
|
if(propHA) alignment = propHA->si[0];
|
||||||
|
|
||||||
immdraw_font_draw(this->font, this->x, this->y, this->w, this->sz, strlen(this->txt), this->txt, alignment,
|
float sz = this->sz;
|
||||||
|
struct k3MProperty *fontSize = k3MFindProperty(this, k3M_PROP_FONT_SIZE, false);
|
||||||
|
if(fontSize) sz = fontSize->f[0];
|
||||||
|
|
||||||
|
immdraw_font_draw(this->font, this->x, this->y, this->w, sz, strlen(this->txt), this->txt, alignment,
|
||||||
1, 1, 1, 1);
|
1, 1, 1, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -188,6 +234,11 @@ struct k3MLabel *k3MLabel(struct k3Font *font, float sz, const char *txt) {
|
|||||||
|
|
||||||
k3MRegisterEventHandler(ret, k3M_EVENT_DRAW, label_draw, NULL, 0);
|
k3MRegisterEventHandler(ret, k3M_EVENT_DRAW, label_draw, NULL, 0);
|
||||||
|
|
||||||
|
int16_t lblsz[2];
|
||||||
|
immdraw_font_size(font, sz, txt, lblsz);
|
||||||
|
ret->w = lblsz[0];
|
||||||
|
ret->h = lblsz[1];
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -273,6 +324,32 @@ static bool screen_ev(struct k3MEvent *ev, uint8_t *ud) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(innermost != this->lastHover) {
|
if(innermost != this->lastHover) {
|
||||||
|
if(this->lastHover) {
|
||||||
|
k3MEventSend(&(struct k3MEvent) {
|
||||||
|
.code = k3M_EVENT_MOUSE_LEAVE,
|
||||||
|
|
||||||
|
.kind = k3M_EVENTKIND_DIRECT,
|
||||||
|
|
||||||
|
.original = ev->original,
|
||||||
|
.target = this->lastHover,
|
||||||
|
|
||||||
|
.mouse = ev->mouse,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if(innermost != (void*) this) {
|
||||||
|
k3MEventSend(&(struct k3MEvent) {
|
||||||
|
.code = k3M_EVENT_MOUSE_ENTER,
|
||||||
|
|
||||||
|
.kind = k3M_EVENTKIND_DIRECT,
|
||||||
|
|
||||||
|
.original = ev->original,
|
||||||
|
.target = innermost,
|
||||||
|
|
||||||
|
.mouse = ev->mouse,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
this->lastHover->hovered = false;
|
this->lastHover->hovered = false;
|
||||||
innermost->hovered = true;
|
innermost->hovered = true;
|
||||||
this->lastHover = innermost;
|
this->lastHover = innermost;
|
||||||
@ -323,11 +400,57 @@ static bool screen_ev(struct k3MEvent *ev, uint8_t *ud) {
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
static bool screen_arrange(struct k3MEvent *ev, uint8_t *ud) {
|
||||||
|
struct k3MObj *this = ev->target;
|
||||||
|
|
||||||
|
for(size_t c = 0; c < this->childCount; c++) {
|
||||||
|
struct k3MObj *child = this->children[c];
|
||||||
|
|
||||||
|
struct k3MProperty *left = k3MFindProperty(child, k3M_PROP_LEFT, true);
|
||||||
|
if(left) {
|
||||||
|
if(left->units[0] == k3M_UNIT_ABSOLUTE) {
|
||||||
|
child->x = this->x + left->f[0];
|
||||||
|
} else if(left->units[0] == k3M_UNIT_PROPORTION) {
|
||||||
|
child->x = this->x + this->w * left->f[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct k3MProperty *top = k3MFindProperty(child, k3M_PROP_TOP, true);
|
||||||
|
if(top) {
|
||||||
|
if(top->units[0] == k3M_UNIT_ABSOLUTE) {
|
||||||
|
child->y = this->y + top->f[0];
|
||||||
|
} else if(top->units[0] == k3M_UNIT_PROPORTION) {
|
||||||
|
child->y = this->y + this->h * top->f[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct k3MProperty *width = k3MFindProperty(child, k3M_PROP_WIDTH, true);
|
||||||
|
if(width) {
|
||||||
|
if(width->units[0] == k3M_UNIT_ABSOLUTE) {
|
||||||
|
child->w = width->f[0];
|
||||||
|
} else if(width->units[0] == k3M_UNIT_PROPORTION) {
|
||||||
|
child->w = this->w * width->f[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct k3MProperty *height = k3MFindProperty(child, k3M_PROP_HEIGHT, true);
|
||||||
|
if(height) {
|
||||||
|
if(height->units[0] == k3M_UNIT_ABSOLUTE) {
|
||||||
|
child->h = height->f[0];
|
||||||
|
} else if(height->units[0] == k3M_UNIT_PROPORTION) {
|
||||||
|
child->h = this->h * height->f[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
struct k3MScreen *k3MScreen() {
|
struct k3MScreen *k3MScreen() {
|
||||||
struct k3MScreen *ret = calloc(1, sizeof(*ret));
|
struct k3MScreen *ret = calloc(1, sizeof(*ret));
|
||||||
|
|
||||||
ret->lastHover = (void*) ret;
|
ret->lastHover = (void*) ret;
|
||||||
|
|
||||||
|
k3MRegisterEventHandler(ret, k3M_EVENT_ARRANGE, screen_arrange, NULL, 0);
|
||||||
k3MRegisterEventHandler(ret, k3M_EVENT_ALL, screen_ev, NULL, 0);
|
k3MRegisterEventHandler(ret, k3M_EVENT_ALL, screen_ev, NULL, 0);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@ -336,7 +459,7 @@ struct k3MScreen *k3MScreen() {
|
|||||||
static bool textbutton_draw(struct k3MEvent *ev, uint8_t *ud) {
|
static bool textbutton_draw(struct k3MEvent *ev, uint8_t *ud) {
|
||||||
struct k3MTextButton *this = (void*) ev->target;
|
struct k3MTextButton *this = (void*) ev->target;
|
||||||
|
|
||||||
obj_draw((void*) this);
|
obj_draw_direct((void*) this);
|
||||||
|
|
||||||
if(this->txt) {
|
if(this->txt) {
|
||||||
/*struct k3RectF txtsz;
|
/*struct k3RectF txtsz;
|
||||||
@ -371,7 +494,7 @@ struct k3MTextButton *k3MTextButton(struct k3Font *font, float sz, const char *t
|
|||||||
static bool textinput_draw(struct k3MEvent *ev, uint8_t *ud) {
|
static bool textinput_draw(struct k3MEvent *ev, uint8_t *ud) {
|
||||||
struct k3MTextInput *this = (void*) ev->target;
|
struct k3MTextInput *this = (void*) ev->target;
|
||||||
|
|
||||||
obj_draw((void*) this);
|
obj_draw_direct((void*) this);
|
||||||
|
|
||||||
if(this->txt) {
|
if(this->txt) {
|
||||||
bool isPlaceholder = strlen(this->txt) == 0;
|
bool isPlaceholder = strlen(this->txt) == 0;
|
||||||
@ -437,7 +560,162 @@ struct k3MTextInput *k3MTextInput(struct k3Font *font, float sz, const char *pla
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool obj_draw(struct k3MEvent *ev, uint8_t *ud) {
|
||||||
|
obj_draw_direct(ev->target);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
struct k3MObj *k3MObj() {
|
struct k3MObj *k3MObj() {
|
||||||
struct k3MObj *ret = calloc(1, sizeof(*ret));
|
struct k3MObj *ret = calloc(1, sizeof(*ret));
|
||||||
|
k3MRegisterEventHandler(ret, k3M_EVENT_DRAW, obj_draw, NULL, 0);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool image_draw(struct k3MEvent *ev, uint8_t *ud) {
|
||||||
|
struct k3MImage *this = (void*) ev->target;
|
||||||
|
|
||||||
|
struct k3MProperty *propFGColor = k3MFindProperty(ev->target, k3M_PROP_FG_COLOR, false);
|
||||||
|
|
||||||
|
vec4 color = {1, 1, 1, 1};
|
||||||
|
if(propFGColor) {
|
||||||
|
color[0] = propFGColor->si[0] / 255.0;
|
||||||
|
color[1] = propFGColor->si[1] / 255.0;
|
||||||
|
color[2] = propFGColor->si[2] / 255.0;
|
||||||
|
color[3] = propFGColor->si[3] / 255.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
immdraw_image_draw(&this->data, this->x, this->y, this->w, this->h, color[0], color[1], color[2], color[3]);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
struct k3MImage *k3MImage(k3MImageData data) {
|
||||||
|
struct k3MImage *ret = calloc(1, sizeof(*ret));
|
||||||
|
ret->data = data;
|
||||||
|
k3MRegisterEventHandler(ret, k3M_EVENT_DRAW, image_draw, NULL, 0);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SCROLLBAR_WIDTH_DEFAULT 16
|
||||||
|
static bool scrollbox_arrange(struct k3MEvent *ev, uint8_t *ud) {
|
||||||
|
struct k3MScrollbox *this = (void*) ev->target;
|
||||||
|
|
||||||
|
struct k3MObj *contentBox = this->children[0];
|
||||||
|
contentBox->x = this->x;
|
||||||
|
contentBox->y = this->y;
|
||||||
|
contentBox->w = this->w - 16;
|
||||||
|
contentBox->h = 16384;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
static bool scrollbox_post_arrange(struct k3MEvent *ev, uint8_t *ud) {
|
||||||
|
struct k3MScrollbox *this = (void*) ev->target;
|
||||||
|
|
||||||
|
struct k3MObj *contentBox = this->children[0];
|
||||||
|
|
||||||
|
size_t maxY2 = 0;
|
||||||
|
for(size_t c = 0; c < contentBox->childCount; c++) {
|
||||||
|
size_t y2 = contentBox->children[c]->y + contentBox->children[c]->h;
|
||||||
|
|
||||||
|
if(maxY2 < y2) {
|
||||||
|
maxY2 = y2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
contentBox->h = maxY2 - contentBox->y;
|
||||||
|
|
||||||
|
if(this->h > contentBox->h) {
|
||||||
|
this->scrollbarLength = this->h;
|
||||||
|
} else {
|
||||||
|
this->scrollbarLength = this->h * this->h / contentBox->h;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
static bool scrollbox_draw(struct k3MEvent *ev, uint8_t *ud) {
|
||||||
|
struct k3MScrollbox *this = (void*) ev->target;
|
||||||
|
|
||||||
|
int scrollbarWidth = SCROLLBAR_WIDTH_DEFAULT;
|
||||||
|
struct k3MProperty *prop = k3MFindProperty(ev->target, k3M_PROP_SCROLLBAR_SIZE, false);
|
||||||
|
if(prop) {
|
||||||
|
scrollbarWidth = prop->si[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
immdraw_fill_rect(this->x + this->w - scrollbarWidth, this->y + this->scrollbarOffset, scrollbarWidth, this->scrollbarLength, 1, 1, 1, 1, 0);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
static bool scrollbox_mouseshit(struct k3MEvent *ev, uint8_t *ud) {
|
||||||
|
struct k3MScrollbox *this = (void*) ev->target;
|
||||||
|
|
||||||
|
if(ev->code == k3M_EVENT_MOUSE_PRESS) {
|
||||||
|
struct k3MProperty *prop = k3MFindProperty(ev->target, k3M_PROP_SCROLL_ANYWHERE, false);
|
||||||
|
bool scrollAnywhere = prop ? prop->si[0] : false;
|
||||||
|
|
||||||
|
int scrollbarWidth = SCROLLBAR_WIDTH_DEFAULT;
|
||||||
|
prop = k3MFindProperty(ev->target, k3M_PROP_SCROLLBAR_SIZE, false);
|
||||||
|
if(prop) {
|
||||||
|
scrollbarWidth = prop->si[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ev->mouse.x >= this->x + this->w - scrollbarWidth) {
|
||||||
|
this->mouseHeld = 1;
|
||||||
|
} else if(scrollAnywhere) {
|
||||||
|
this->mouseHeld = 2;
|
||||||
|
} else {
|
||||||
|
this->mouseHeld = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->mouseX = ev->mouse.x;
|
||||||
|
this->mouseY = ev->mouse.y;
|
||||||
|
} else if(ev->code == k3M_EVENT_MOUSE_RELEASE) {
|
||||||
|
this->mouseHeld = false;
|
||||||
|
} else if(ev->code == k3M_EVENT_MOUSE_MOTION) {
|
||||||
|
if(this->mouseHeld) {
|
||||||
|
|
||||||
|
int16_t diffX = ev->mouse.x - this->mouseX;
|
||||||
|
int16_t diffY = ev->mouse.y - this->mouseY;
|
||||||
|
this->mouseX = ev->mouse.x;
|
||||||
|
this->mouseY = ev->mouse.y;
|
||||||
|
|
||||||
|
struct k3MObj *contentBox = this->children[0];
|
||||||
|
|
||||||
|
if(this->mouseHeld == 1) {
|
||||||
|
this->scrollbarOffset += diffY;
|
||||||
|
contentBox->y = (float) this->y + this->scrollbarOffset * (-contentBox->h + this->h) / (this->h - this->scrollbarLength);
|
||||||
|
} else if(this->mouseHeld == 2) {
|
||||||
|
contentBox->y += diffY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(contentBox->y > this->y) {
|
||||||
|
contentBox->y = this->y;
|
||||||
|
} else if(contentBox->y < this->y - contentBox->h + this->h) {
|
||||||
|
contentBox->y = this->y - contentBox->h + this->h;
|
||||||
|
}
|
||||||
|
this->scrollbarOffset = (float) (contentBox->y - this->y) * (this->h - this->scrollbarLength) / (this->h - contentBox->h);
|
||||||
|
|
||||||
|
k3MArrange(contentBox);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
struct k3MScrollbox *k3MScrollbox() {
|
||||||
|
struct k3MScrollbox *this = calloc(1, sizeof(*this));
|
||||||
|
|
||||||
|
struct k3MObj *contentBox = k3MObj();
|
||||||
|
k3MAddChild(this, contentBox);
|
||||||
|
|
||||||
|
k3MRegisterEventHandler(this, k3M_EVENT_ARRANGE, scrollbox_arrange, NULL, 0);
|
||||||
|
k3MRegisterEventHandler(this, k3M_EVENT_POST_ARRANGE, scrollbox_post_arrange, NULL, 0);
|
||||||
|
k3MRegisterEventHandler(this, k3M_EVENT_DRAW, scrollbox_draw, NULL, 0);
|
||||||
|
k3MRegisterEventHandler(this, k3M_EVENT_MOUSE_PRESS, scrollbox_mouseshit, NULL, 0);
|
||||||
|
k3MRegisterEventHandler(this, k3M_EVENT_MOUSE_MOTION, scrollbox_mouseshit, NULL, 0);
|
||||||
|
k3MRegisterEventHandler(this, k3M_EVENT_MOUSE_RELEASE, scrollbox_mouseshit, NULL, 0);
|
||||||
|
|
||||||
|
this->crop = true;
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
struct k3MObj *k3MScrollboxGetContent(struct k3MScrollbox *this) {
|
||||||
|
return this->children[0];
|
||||||
|
}
|
||||||
|
55
src/k3menu.h
55
src/k3menu.h
@ -21,7 +21,8 @@ struct k3MObj;
|
|||||||
#define k3M_EVENT_COMPLETE 10
|
#define k3M_EVENT_COMPLETE 10
|
||||||
#define k3M_EVENT_MEASURE 11
|
#define k3M_EVENT_MEASURE 11
|
||||||
#define k3M_EVENT_ARRANGE 12
|
#define k3M_EVENT_ARRANGE 12
|
||||||
#define k3M_EVENT_ALL 13
|
#define k3M_EVENT_POST_ARRANGE 13
|
||||||
|
#define k3M_EVENT_ALL 14
|
||||||
|
|
||||||
#define k3M_MOUSE_BUTTON_0 0
|
#define k3M_MOUSE_BUTTON_0 0
|
||||||
#define k3M_MOUSE_BUTTON_1 1
|
#define k3M_MOUSE_BUTTON_1 1
|
||||||
@ -31,11 +32,18 @@ struct k3MObj;
|
|||||||
#define k3M_EVENTKIND_CAPTURE 1
|
#define k3M_EVENTKIND_CAPTURE 1
|
||||||
#define k3M_EVENTKIND_BUBBLE 2
|
#define k3M_EVENTKIND_BUBBLE 2
|
||||||
|
|
||||||
#define k3M_USERDATA_SIZE 16
|
#define k3M_USERDATA_SIZE 32
|
||||||
|
|
||||||
#define k3M_ALIGN_LEFT 0
|
#define k3M_ALIGN_LEFT 0
|
||||||
|
#define k3M_ALIGN_TOP 3
|
||||||
#define k3M_ALIGN_CENTER 1
|
#define k3M_ALIGN_CENTER 1
|
||||||
#define k3M_ALIGN_RIGHT 2
|
#define k3M_ALIGN_RIGHT 2
|
||||||
|
#define k3M_ALIGN_BOTTOM 4
|
||||||
|
|
||||||
|
#define k3M_IDX_TOP 0
|
||||||
|
#define k3M_IDX_RIGHT 1
|
||||||
|
#define k3M_IDX_BOTTOM 2
|
||||||
|
#define k3M_IDX_LEFT 3
|
||||||
|
|
||||||
#ifdef k3M_FIXED_POINT
|
#ifdef k3M_FIXED_POINT
|
||||||
typedef uint8_t k3MCC;
|
typedef uint8_t k3MCC;
|
||||||
@ -43,6 +51,11 @@ typedef uint8_t k3MCC;
|
|||||||
typedef float k3MCC;
|
typedef float k3MCC;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define k3M_UNIT_ABSOLUTE 0
|
||||||
|
#define k3M_UNIT_PROPORTION 1
|
||||||
|
|
||||||
|
#include"k3menu_internal.h"
|
||||||
|
|
||||||
struct k3MEvent {
|
struct k3MEvent {
|
||||||
uint16_t code;
|
uint16_t code;
|
||||||
|
|
||||||
@ -76,16 +89,28 @@ typedef struct k3MEventHandler {
|
|||||||
|
|
||||||
enum k3MPropertyType {
|
enum k3MPropertyType {
|
||||||
k3M_PROP_BG_COLOR,
|
k3M_PROP_BG_COLOR,
|
||||||
|
k3M_PROP_FG_COLOR,
|
||||||
k3M_PROP_BORDER_RADIUS,
|
k3M_PROP_BORDER_RADIUS,
|
||||||
k3M_PROP_MARGIN,
|
k3M_PROP_MARGIN,
|
||||||
|
k3M_PROP_PADDING,
|
||||||
k3M_PROP_HORIZONTAL_ALIGNMENT,
|
k3M_PROP_HORIZONTAL_ALIGNMENT,
|
||||||
|
k3M_PROP_VERTICAL_ALIGNMENT,
|
||||||
|
k3M_PROP_LEFT,
|
||||||
|
k3M_PROP_TOP,
|
||||||
|
k3M_PROP_WIDTH,
|
||||||
|
k3M_PROP_HEIGHT,
|
||||||
|
k3M_PROP_FONT_SIZE,
|
||||||
|
k3M_PROP_SCROLL_ANYWHERE,
|
||||||
|
k3M_PROP_SCROLLBAR_SIZE,
|
||||||
};
|
};
|
||||||
struct k3MProperty {
|
struct k3MProperty {
|
||||||
enum k3MPropertyType type;
|
enum k3MPropertyType type;
|
||||||
|
uint8_t units[4];
|
||||||
union {
|
union {
|
||||||
intmax_t si[4];
|
intmax_t si[4];
|
||||||
void *ptr;
|
void *ptr[4];
|
||||||
uint8_t buf[32];
|
uint8_t buf[32];
|
||||||
|
float f[4];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -103,7 +128,7 @@ struct k3MObj {
|
|||||||
int16_t wDesired;
|
int16_t wDesired;
|
||||||
int16_t hDesired;
|
int16_t hDesired;
|
||||||
|
|
||||||
bool invisible, hovered, disabled;
|
bool invisible, hovered, disabled, crop;
|
||||||
|
|
||||||
k3MEventHandler *handlers;
|
k3MEventHandler *handlers;
|
||||||
size_t handlerCount;
|
size_t handlerCount;
|
||||||
@ -150,6 +175,8 @@ struct k3MScreen {
|
|||||||
|
|
||||||
struct k3MObj *keyboardFocus;
|
struct k3MObj *keyboardFocus;
|
||||||
struct k3MObj *lastHover;
|
struct k3MObj *lastHover;
|
||||||
|
|
||||||
|
struct k3MObj *mouseCapture;
|
||||||
};
|
};
|
||||||
struct k3MScreen *k3MScreen();
|
struct k3MScreen *k3MScreen();
|
||||||
|
|
||||||
@ -173,3 +200,23 @@ struct k3MTextInput {
|
|||||||
char *txt;
|
char *txt;
|
||||||
};
|
};
|
||||||
struct k3MTextInput *k3MTextInput(struct k3Font *font, float sz, const char *placeholder, const char *txt);
|
struct k3MTextInput *k3MTextInput(struct k3Font *font, float sz, const char *placeholder, const char *txt);
|
||||||
|
|
||||||
|
struct k3MImage {
|
||||||
|
struct k3MObj;
|
||||||
|
|
||||||
|
k3MImageData data;
|
||||||
|
};
|
||||||
|
struct k3MImage *k3MImage(k3MImageData);
|
||||||
|
|
||||||
|
struct k3MScrollbox {
|
||||||
|
struct k3MObj;
|
||||||
|
|
||||||
|
int mouseHeld;
|
||||||
|
int16_t mouseX;
|
||||||
|
int16_t mouseY;
|
||||||
|
|
||||||
|
float scrollbarOffset;
|
||||||
|
int16_t scrollbarLength;
|
||||||
|
};
|
||||||
|
struct k3MScrollbox *k3MScrollbox();
|
||||||
|
struct k3MObj *k3MScrollboxGetContent(struct k3MScrollbox*);
|
||||||
|
Loading…
Reference in New Issue
Block a user