I was THIS close from drawing amogus with my new widgets

This commit is contained in:
Андреев Григорий 2026-02-21 03:40:24 +03:00
parent 2655c2be3e
commit 6e13ceb267
9 changed files with 192 additions and 44 deletions

View File

@ -3,7 +3,7 @@
#include "../codegen/util_template_inst.h"
void generate_util_temp_geom_headers() {
SpanU8 T[] = {cstr("cvec3"), cstr("cvec4"), cstr("vec2"), cstr("vec3"), cstr("vec4"), cstr("s64vec2")};
SpanU8 T[] = {cstr("cvec3"), cstr("cvec4"), cstr("vec2"), cstr("vec3"), cstr("vec4"), cstr("s64vec2"), cstr("ivec2")};
for (size_t i = 0; i < ARRAY_SIZE(T); i++) {
generate_guarded_span_company_for_primitive(cstr("l1"), cstr(""), T[i],
cstr("#include \"geom.h\"\n"), true, true);

View File

@ -73,4 +73,8 @@ void generate_util_temp_very_base_headers() {
generate_Option_templ_inst_eve_header(l, ns,
(option_template_instantiation_op){.T = cstr("Json"), .t_clonable = false});
mkdir_nofail("l1/gui");
generate_guarded_span_company_for_primitive(l, cstr("gui"), cstr("MutRefWidget"),
cstr("#include \"../../../src/l2/gui/widget.h\""), true, false);
}

View File

@ -108,3 +108,18 @@ uvec2 ivec2_to_uvec2(ivec2 v) {
ivec2 uvec2_to_ivec2(uvec2 v) {
return (ivec2){(S32)v.x, (S32)v.y};
}
typedef struct{
ivec2 lt, rb;
} BorderS32;
bool BorderS32_empty(BorderS32 self){
return self.lt.x >= self.rb.x || self.lt.y >= self.rb.y;
}
BorderS32 BorderS32_intersect(BorderS32 a, BorderS32 b){
return (BorderS32){
{MAX_S32(a.lt.x, b.lt.x), MAX_S32(a.lt.y, b.lt.y)},
{MIN_S32(a.rb.x, b.rb.x), MIN_S32(a.rb.y, b.rb.y)},
};
}

View File

@ -2,7 +2,9 @@
#include "margaret/vulkan_utils.h"
#include "../../gen/l1/geom.h"
#include "../l1_5/marie/graphics_geom.h"
/* todo: replace vec4 color with cvec4 color */
typedef struct {
vec2 pos;
vec4 color;
@ -103,4 +105,14 @@ void Plain2dShapeRenderer_add_rectangle(Plain2dShapeRenderer* self, vec4 color,
(vec2){start.x + width, start.y}, start, (vec2){start.x, start.y + height});
Plain2dShapeRenderer_add_triangle(self, color,
(vec2){start.x + width, start.y}, (vec2){start.x, start.y + height}, (vec2){start.x + width, start.y + height});
}
void Plain2dShapeRenderer_add_rect_clipped(Plain2dShapeRenderer* self, vec4 color,
ivec2 start, S32 width, S32 height, BorderS32 border) {
BorderS32 rect = BorderS32_intersect(border,
(BorderS32){.lt = start, .rb.x = start.x + width, .rb.y = start.y + height});
if (!BorderS32_empty(rect)) {
Plain2dShapeRenderer_add_rectangle(self, color, ivec2_to_vec2(rect.lt),
(float)(rect.rb.x - rect.lt.x), (float)(rect.rb.y - rect.lt.y));
}
}

View File

@ -2,7 +2,6 @@
#include "../drawer_2d.h"
#include "widget.h"
#include "../../l1_5/marie/graphics_geom.h"
typedef struct {
EmptyWidget base;
@ -17,14 +16,9 @@ uvec2 Widget_Table_ColorblockWidget_DRAW_PREPARE(Widget* ug, uvec2 limits) {
void Widget_Table_ColorblockWidget_DRAW(Widget* ug, ivec2 drawing_offset, uvec2 surface_sz, BorderS32 border) {
ColorblockWidget* self = (ColorblockWidget*)ug;
assert_sane_widget_size(self->base.base.sz_my_choice);
BorderS32 rect = BorderS32_intersect(
(BorderS32){.lt = drawing_offset,
.rb = ivec2_add_ivec2(drawing_offset, uvec2_to_ivec2(self->base.base.sz_my_choice))},
border);
if (BorderS32_empty(rect))
return;
Plain2dShapeRenderer_add_rectangle(self->drawer, self->color,
ivec2_to_vec2(rect.lt), (float)(rect.rb.x - rect.lt.x), (float)(rect.rb.y - rect.lt.x));
S32 width = (S32)self->base.base.sz_my_choice.x;
S32 height = (S32)self->base.base.sz_my_choice.y;
Plain2dShapeRenderer_add_rect_clipped(self->drawer, self->color, drawing_offset, width, height, border);
}
void Widget_Table_ColorblockWidget_drop(Widget* ug) {}
@ -35,13 +29,13 @@ const Widget_Table Widget_Table_ColorblockWidget = {
.drop = Widget_Table_ColorblockWidget_drop,
};
ColorblockWidget ColorblockWidget_new(U32 width, U32 height, vec4 color, Plain2dShapeRenderer* drawer) {
ColorblockWidget ColorblockWidget_new(S32 width, S32 height, vec4 color, Plain2dShapeRenderer* drawer) {
return (ColorblockWidget){.base = (EmptyWidget){.base = Widget_new(), .width = width, .height = height},
.color = color, .drawer = drawer};
}
BoxWidget ColorblockWidget_new_box(U32 width, U32 height, vec4 color, Plain2dShapeRenderer* drawer){
ColorblockWidget* r = (ColorblockWidget*)safe_malloc(sizeof(ColorblockWidget));
*r = ColorblockWidget_new(width, height, color, drawer);
return (BoxWidget){.r = (Widget*)r, .t = &Widget_Table_ColorblockWidget};
}
// BoxWidget ColorblockWidget_new_box(U32 width, U32 height, vec4 color, Plain2dShapeRenderer* drawer){
// ColorblockWidget* r = (ColorblockWidget*)safe_malloc(sizeof(ColorblockWidget));
// *r = ColorblockWidget_new(width, height, color, drawer);
// return (BoxWidget){.r = (Widget*)r, .t = &Widget_Table_ColorblockWidget};
// }

63
src/l2/gui/colorframe.h Normal file
View File

@ -0,0 +1,63 @@
#pragma once
#include "../drawer_2d.h"
#include "widget.h"
typedef struct {
Widget base;
S32 left_p, right_p, bottom_p, top_p;
Plain2dShapeRenderer* drawer;
vec4 color;
MutRefWidget child;
} ColorframeWidget;
uvec2 Widget_Table_ColorframeWidget_DRAW_PREPARE(Widget* ug, uvec2 limits) {
ColorframeWidget* self = (ColorframeWidget*)ug;
S32 taken_width = self->left_p + self->right_p;
S32 taken_height = self->top_p + self->bottom_p;
S32 rem_width = MAX_S32((S32)limits.x - taken_width, 0);
S32 rem_height = MAX_S32((S32)limits.y - taken_height, 0);
/* It can be useful even when one of the dimensions is zero */
uvec2 child_chose = MutRefWidget_draw_prepare(self->child, (uvec2){rem_width, rem_height});
return widget_size_min_of_all(limits, (uvec2){child_chose.x + taken_width, child_chose.y + taken_height});
}
void Widget_Table_ColorframeWidget_DRAW(Widget* ug, ivec2 drawing_offset, uvec2 surface_sz, BorderS32 border) {
ColorframeWidget* self = (ColorframeWidget*)ug;
S32 taken_width = self->left_p + self->right_p;
S32 taken_height = self->top_p + self->bottom_p;
S32 width = (S32)self->base.sz_my_choice.x;
S32 height = (S32)self->base.sz_my_choice.y;
if (width == 0 || height == 0)
return;
if (taken_width >= width || taken_height >= height) {
Plain2dShapeRenderer_add_rect_clipped(self->drawer, self->color, drawing_offset, width, height, border);
} else {
Plain2dShapeRenderer_add_rect_clipped(self->drawer, self->color, drawing_offset, width, self->top_p, border);
Plain2dShapeRenderer_add_rect_clipped(self->drawer, self->color,
(ivec2){drawing_offset.x, drawing_offset.y + self->top_p}, self->left_p, height - taken_height, border);
Plain2dShapeRenderer_add_rect_clipped(self->drawer, self->color,
(ivec2){drawing_offset.x + width - self->right_p, drawing_offset.y + self->top_p}, self->right_p, height - taken_height, border);
Plain2dShapeRenderer_add_rect_clipped(self->drawer, self->color,
(ivec2){drawing_offset.x, drawing_offset.y + height - self->bottom_p}, width, self->bottom_p, border);
MutRefWidget_draw(self->child, (ivec2){drawing_offset.x + self->left_p, drawing_offset.y + self->top_p}, surface_sz, border);
}
}
void Widget_Table_ColorframeWidget_drop(Widget* ug){}
const Widget_Table Widget_Table_ColorframeWidget = {
.DRAW_PREPARE = Widget_Table_ColorframeWidget_DRAW_PREPARE,
.DRAW = Widget_Table_ColorframeWidget_DRAW,
.drop = Widget_Table_ColorframeWidget_drop,
};
ColorframeWidget ColorframeWidget_new(S32 left_p, S32 right_p, S32 bottom_p, S32 top_p,
Plain2dShapeRenderer* drawer, vec4 color, MutRefWidget child
) {
return (ColorframeWidget){.base = Widget_new(),
.left_p = left_p, .right_p = right_p, .bottom_p = bottom_p, .top_p = top_p,
.drawer = drawer, .color = color, .child = child
};
}

57
src/l2/gui/stacks.h Normal file
View File

@ -0,0 +1,57 @@
#pragma once
#include "widget.h"
#include "../../../gen/l1/gui/VecMutRefWidget.h"
#include "../../../gen/l1/VecAndSpan_S32.h"
typedef struct {
Widget base;
VecMutRefWidget children;
VecS32 decided_positions;
} LtoRStackWidget;
uvec2 Widget_Table_LtoRStackWidget_DRAW_PREPARE(Widget* ug, uvec2 limits) {
LtoRStackWidget* self = (LtoRStackWidget*)ug;
S32 pos = 0;
S32 max_w = 0;
self->decided_positions.len = 0;
U64 n = self->children.len;
for (U64 i = 0; i < n; i++) {
if (pos >= (S32)limits.y)
break;
uvec2 child_sz = MutRefWidget_draw_prepare(self->children.buf[i], (uvec2){.x = limits.x, .y = limits.y - pos});
max_w = MAX_S32(max_w, child_sz.x);
VecS32_append(&self->decided_positions, pos);
pos += (S32)child_sz.y;
}
return (uvec2){max_w, pos};
}
void Widget_Table_LtoRStackWidget_DRAW(Widget* ug, ivec2 drawing_offset, uvec2 surface_sz, BorderS32 border) {
LtoRStackWidget* self = (LtoRStackWidget*)ug;
for (U64 i = 0; i < self->decided_positions.len; i++) {
S32 pos = self->decided_positions.buf[i];
assert(i < self->children.len);
MutRefWidget_draw(self->children.buf[i], (ivec2){drawing_offset.x, drawing_offset.y + pos}, surface_sz, border);
}
}
void LtoRStackWidget_drop(LtoRStackWidget self) {
VecMutRefWidget_drop(self.children);
VecS32_drop(self.decided_positions);
}
void Widget_Table_LtoRStackWidget_drop(Widget* self) {
LtoRStackWidget_drop(*(LtoRStackWidget*)self);
}
const Widget_Table Widget_Table_LtoRStack = {
.DRAW_PREPARE = Widget_Table_LtoRStackWidget_DRAW_PREPARE,
.DRAW = Widget_Table_LtoRStackWidget_DRAW,
.drop = Widget_Table_LtoRStackWidget_drop,
};
LtoRStackWidget LtoRStackWidget_new() {
return (LtoRStackWidget){.base = Widget_new(),
.children = VecMutRefWidget_new(), .decided_positions = VecS32_new()};
}

View File

@ -1,7 +1,6 @@
#pragma once
#include "../../../gen/l1/geom.h"
#include "../../l1/core/util.h"
#include "../../l1_5/marie/graphics_geom.h"
#define WIDGET_DIM_INF 1000000
@ -17,21 +16,6 @@ void assert_sane_widget_size_limits(uvec2 max_limits){
assert(max_limits.x <= WIDGET_DIM_INF || max_limits.y <= WIDGET_DIM_INF);
}
typedef struct{
ivec2 lt, rb;
} BorderS32;
bool BorderS32_empty(BorderS32 self){
return self.lt.x >= self.rb.x || self.lt.y >= self.rb.y;
}
BorderS32 BorderS32_intersect(BorderS32 a, BorderS32 b){
return (BorderS32){
{MAX_S32(a.lt.x, b.lt.x), MAX_S32(a.lt.y, b.lt.y)},
{MIN_S32(a.rb.x, b.rb.x), MIN_S32(a.rb.y, b.rb.y)},
};
}
uvec2 widget_size_max_of_all(uvec2 a, uvec2 b){
return (uvec2){MAX_U32(a.x, b.x), MAX_U32(a.y, b.y)};
}
@ -76,8 +60,8 @@ void MutRefWidget_draw(MutRefWidget self, ivec2 drawing_offset, uvec2 surface_sz
typedef struct {
Widget base;
U32 width;
U32 height;
S32 width;
S32 height;
} EmptyWidget;
uvec2 Widget_Table_EmptyWidget_DRAW_PREPARE(Widget* ug, uvec2 limits){
@ -98,12 +82,13 @@ const Widget_Table Widget_Table_EmptyWidget = {
.drop = Widget_Table_EmptyWidget_drop,
};
EmptyWidget EmptyWidget_new(U32 width, U32 height) {
EmptyWidget EmptyWidget_new(S32 width, S32 height) {
assert(width >= 0 && height >= 0);
return (EmptyWidget){.base = Widget_new(), .width = width, .height = height};
}
BoxWidget EmptyWidget_new_box(U32 width, U32 height){
EmptyWidget* r = safe_malloc(sizeof(EmptyWidget));
*r = (EmptyWidget){.base = Widget_new(), .width = width, .height = height};
return (BoxWidget){.r = (Widget*)r, .t = &Widget_Table_EmptyWidget};
}
// BoxWidget EmptyWidget_new_box(U32 width, U32 height){
// EmptyWidget* r = safe_malloc(sizeof(EmptyWidget));
// *r = (EmptyWidget){.base = Widget_new(), .width = width, .height = height};
// return (BoxWidget){.r = (Widget*)r, .t = &Widget_Table_EmptyWidget};
// }

View File

@ -4,6 +4,8 @@
#include "../../../gen/l1/VecAndSpan_vec3.h"
#include "../../l1_5/core/color.h"
#include "../../l2/gui/colorblock.h"
#include "../../l2/gui/colorframe.h"
#include "../../l2/gui/stacks.h"
#include "linux/input-event-codes.h"
@ -26,7 +28,7 @@ typedef struct{
typedef struct {
float mass; /* In kg, Not zero */
quad_form3_t inertia_moment; /* Qadratic form, yields kg*m^2 */
quad_form3_t inertia_moment; /* Quadratic form, yields kg*m^2 */
/* Center of mass relative to "center of mesh" */
vec3 mass_center;
} RigidBodyConfig;
@ -104,6 +106,11 @@ typedef struct{
/* overlay ui */
ColorblockWidget gui_0;
ColorframeWidget gui_1;
ColorblockWidget gui_2;
ColorblockWidget gui_3;
LtoRStackWidget gui_4;
ColorframeWidget gui_5;
} R4BetaState;
/* We are surrounded by a giant cubic mesh of light sources */
@ -330,8 +337,19 @@ void run_app(){
LucyRenderer_add_simple_label(&st.alice->lucy_renderer, st.font_face_of_size_40, (vec4){0, 0, 0, 1}, 0,
cstr("..."), (ivec2){10, 10});
st.gui_0 = ColorblockWidget_new(400, 200, (vec4){0.3f, 0.8f, 0.4f, 0.6f}, &alice->plain_shape_renderer);
alice->overlay_ui_root = (MutRefWidget){.r = &st.gui_0.base.base, .t = &Widget_Table_ColorblockWidget};
/* Recursion depth is 2 */
st.gui_0 = ColorblockWidget_new(100, 50, (vec4){0.3f, 0.8f, 0.4f, 0.6f}, &alice->plain_shape_renderer);
st.gui_1 = ColorframeWidget_new(100, 300, 150, 50, &alice->plain_shape_renderer, (vec4){0.7f, 0.4f, 0.2f, 0.5f},
(MutRefWidget){.r = (Widget*)&st.gui_0, .t = &Widget_Table_ColorblockWidget});
st.gui_2 = ColorblockWidget_new(5000, 30, (vec4){0.1f, 0.5f, 0.6f, 0.4f}, &alice->plain_shape_renderer);
st.gui_3 = ColorblockWidget_new(120, 50, (vec4){0.2f, 0.67f, 0.4f, 0.5f}, &alice->plain_shape_renderer);
st.gui_4 = LtoRStackWidget_new();
VecMutRefWidget_append(&st.gui_4.children, (MutRefWidget){.r = (Widget*)&st.gui_1, &Widget_Table_ColorframeWidget});
VecMutRefWidget_append(&st.gui_4.children, (MutRefWidget){.r = (Widget*)&st.gui_2, &Widget_Table_ColorblockWidget});
VecMutRefWidget_append(&st.gui_4.children, (MutRefWidget){.r = (Widget*)&st.gui_3, &Widget_Table_ColorblockWidget});
st.gui_5 = ColorframeWidget_new(70, 70, 0, 70, &alice->plain_shape_renderer, (vec4){0.1f, 0.5f, 0.3f, 0.8f},
(MutRefWidget){.r = (Widget*)&st.gui_4, &Widget_Table_LtoRStack});
alice->overlay_ui_root = (MutRefWidget){.r = &st.gui_5.base, .t = &Widget_Table_ColorframeWidget};
VecU8 ROA_mesh_path = vcstr("./gen/l2/models/log_10_2_6.AliceGenericMesh");
st.ROA_topology = alice_expect_read_generic_mesh_from_file(ROA_mesh_path);