Saving progress. This is the moment I stopped understanding what I am doing
This commit is contained in:
parent
8cb684d82e
commit
648621eb42
@ -116,4 +116,9 @@ NODISCARD VecU8 codegen_include_relative_to_root(SpanU8 bonus_ns, SpanU8 abs_pat
|
||||
return res;
|
||||
}
|
||||
|
||||
/* returns back `type` string, but if it is "", returns "void" instead */
|
||||
SpanU8 c_type_empty_means_void(SpanU8 type){
|
||||
return type.len > 0 ? type : cstr("void");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
#include "l1_5_templ_very_base.h"
|
||||
#include "margaret.h"
|
||||
#include "lucy.h"
|
||||
#include "gui.h"
|
||||
|
||||
int main() {
|
||||
mkdir_nofail("l1_5");
|
||||
@ -12,6 +13,7 @@ int main() {
|
||||
generate_l1_5_template_instantiation_for_base_types();
|
||||
generate_l1_5_template_instantiations_for_margaret();
|
||||
generate_l1_5_lucy_headers();
|
||||
generate_l1_5_gui_headers();
|
||||
finish_layer(cstr("l1_5"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
47
src/l1_5/anne/gui.h
Normal file
47
src/l1_5/anne/gui.h
Normal file
@ -0,0 +1,47 @@
|
||||
#ifndef prototype1_src_l1_5_anne_gui_h
|
||||
#define prototype1_src_l1_5_anne_gui_h
|
||||
|
||||
#include "../codegen/trait_wrap_boil.h"
|
||||
|
||||
void generate_l1_5_gui_headers(){
|
||||
mkdir_nofail("l1_5/eve/gui");
|
||||
SpanU8 l = cstr("l1_5"), ns = cstr("gui");
|
||||
generate_trait_wrapper_templ_inst_eve_header(l, ns, (trait_wrapper_boil_options){
|
||||
.trait = {
|
||||
.name = cstr("Widget"),
|
||||
.methods = (SpanNamedMethodSignatureRecordRef){
|
||||
.data = (NamedMethodSignatureRecordRef[]){
|
||||
{
|
||||
.takes_self = true,
|
||||
.takes_mut_self = true,
|
||||
.params = (SpanNamedVariableRecordRef){
|
||||
.data = (NamedVariableRecordRef[]){
|
||||
{ .type = cstr("uvec2"), .name = cstr("max_limits") }
|
||||
}, .len = 1
|
||||
},
|
||||
.return_type = cstr("uvec2"),
|
||||
.name = cstr("DRAW_PREPARE"),
|
||||
},
|
||||
{
|
||||
.takes_self = true,
|
||||
.takes_mut_self = true,
|
||||
.params = (SpanNamedVariableRecordRef){
|
||||
.data = (NamedVariableRecordRef[]){
|
||||
{ .type = cstr("ivec2"), .name = cstr("drawing_offset") },
|
||||
{ .type = cstr("uvec2"), .name = cstr("surface_sz") },
|
||||
{ .type = cstr("BorderS32"), .name = cstr("border") },
|
||||
}, .len = 3
|
||||
},
|
||||
.return_type = cstr(""),
|
||||
.name = cstr("DRAW"),
|
||||
}
|
||||
}, .len = 2
|
||||
},
|
||||
.drop_primitive = false,
|
||||
.base_struct_name = cstr("Widget"),
|
||||
},
|
||||
.box = true, .mut_ref = true
|
||||
});
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -24,7 +24,9 @@ void generate_l1_5_liza_headers() {
|
||||
.name = cstr("ding"),
|
||||
}
|
||||
}, .len = 1
|
||||
}
|
||||
},
|
||||
.drop_primitive = false,
|
||||
.base_struct_name = cstr(""),
|
||||
},
|
||||
.box = true, .ref = true, .mut_ref = true
|
||||
});
|
||||
|
||||
@ -24,15 +24,19 @@ typedef struct {
|
||||
SpanNamedMethodSignatureRecordRef methods;
|
||||
bool drop_primitive;
|
||||
SpanU8 name;
|
||||
/* It is usually either name or "void" */
|
||||
SpanU8 base_struct_name;
|
||||
} NamedTraitDefRecordRef;
|
||||
|
||||
NODISCARD VecU8 generate_trait_table_structure(NamedTraitDefRecordRef trait){
|
||||
VecU8 res = VecU8_from_cstr("typedef struct {\n");
|
||||
for (size_t i = 0; i < trait.methods.len; i++) {
|
||||
NamedMethodSignatureRecordRef method = *SpanNamedMethodSignatureRecordRef_at(trait.methods, i);
|
||||
VecU8_append_vec(&res, VecU8_fmt(SPACE "%s (*%s)(", method.return_type, method.name));
|
||||
VecU8_append_vec(&res, VecU8_fmt(SPACE "%s (*%s)(", c_type_empty_means_void(method.return_type), method.name));
|
||||
if (method.takes_self) {
|
||||
VecU8_append_span(&res, method.takes_mut_self ? cstr("void*") : cstr("const void*"));
|
||||
VecU8_append_vec(&res, VecU8_fmt(
|
||||
method.takes_mut_self ? "%s*" : "const %s*",
|
||||
c_type_empty_means_void(trait.base_struct_name)));
|
||||
}
|
||||
for (size_t p = 0; p < method.params.len; p++) {
|
||||
NamedVariableRecordRef param = *SpanNamedVariableRecordRef_at(method.params, p);
|
||||
@ -43,7 +47,9 @@ NODISCARD VecU8 generate_trait_table_structure(NamedTraitDefRecordRef trait){
|
||||
VecU8_append_span(&res, cstr(");\n"));
|
||||
}
|
||||
if (!trait.drop_primitive) {
|
||||
VecU8_append_span(&res, cstr(SPACE "void (*drop)(void*);\n"));
|
||||
VecU8_append_vec(&res, VecU8_fmt(
|
||||
SPACE "void (*drop)(%s*);\n",
|
||||
c_type_empty_means_void(trait.base_struct_name)));
|
||||
}
|
||||
VecU8_append_vec(&res, VecU8_fmt("} %s_Table;\n\n", trait.name));
|
||||
return res;
|
||||
@ -56,19 +62,33 @@ typedef struct {
|
||||
bool mut_ref;
|
||||
} trait_wrapper_boil_options;
|
||||
|
||||
/* (refkind, mut) in {(Ref, false), (MutRef, true), (Box, true)} */
|
||||
void codegen_append_trait_wrapper_structure_some_refkind(VecU8* res, NamedTraitDefRecordRef trait,
|
||||
SpanU8 refkind, bool mut){
|
||||
VecU8_append_vec(res, VecU8_fmt(
|
||||
"typedef struct {\n"
|
||||
SPACE "%s%s* r;\n" /* epsilon / const, op.trait.base_struct_name */
|
||||
SPACE "const %s_Table* t;\n" /* op.trait.name */
|
||||
"} %s%s;\n\n", /* refkind, op.trait.name */
|
||||
mut ? cstr("") : cstr("const "),
|
||||
c_type_empty_means_void(trait.base_struct_name),
|
||||
trait.name, refkind, trait.name));
|
||||
}
|
||||
|
||||
/* (refkind, self_as_ptr) in {(Ref, false), (MutRef, false), (Box, true)} */
|
||||
void codegen_append_trait_wrapper_some_method_some_refkind(VecU8* res, SpanU8 trait_name,
|
||||
NamedMethodSignatureRecordRef method, SpanU8 refkind, bool self_as_ptr){
|
||||
VecU8_append_vec(res, VecU8_fmt(
|
||||
"%s %s%s_%s(%s%s%s self",
|
||||
/* return_type, refkind, trait.name, method.name, refkind, trait.name */
|
||||
method.return_type, refkind, trait_name, method.name, refkind, trait_name, self_as_ptr ? cstr("*") : cstr("")));
|
||||
c_type_empty_means_void(method.return_type),
|
||||
refkind, trait_name, method.name, refkind, trait_name, self_as_ptr ? cstr("*") : cstr("")));
|
||||
for (size_t p = 0; p < method.params.len; p++) {
|
||||
NamedVariableRecordRef param = method.params.data[p];
|
||||
VecU8_append_vec(res, VecU8_fmt(", %s %s", param.type, param.name));
|
||||
}
|
||||
VecU8_append_span(res, cstr("){\n" SPACE));
|
||||
if (!SpanU8_cont_equal(method.return_type, cstr("void")))
|
||||
if (method.return_type.len > 0)
|
||||
VecU8_append_span(res, cstr("return "));
|
||||
VecU8_append_vec(res, VecU8_fmt("self%s""t->%s(",
|
||||
self_as_ptr ? cstr("->") : cstr("."),
|
||||
@ -95,12 +115,7 @@ NODISCARD VecU8 generate_trait_wrapper_boilerplate(trait_wrapper_boil_options op
|
||||
VecU8 res = VecU8_new();
|
||||
VecU8_append_vec(&res, generate_trait_table_structure(op.trait));
|
||||
if (op.ref) {
|
||||
VecU8_append_vec(&res, VecU8_fmt(
|
||||
"typedef struct {\n"
|
||||
SPACE "const void* r;\n"
|
||||
SPACE "const %s_Table* t;\n" /* op.trait.name */
|
||||
"} Ref%s;\n\n", /* op.trait.name */
|
||||
op.trait.name, op.trait.name));
|
||||
codegen_append_trait_wrapper_structure_some_refkind(&res, op.trait, cstr("Ref"), false);
|
||||
for (size_t i = 0; i < op.trait.methods.len; i++) {
|
||||
NamedMethodSignatureRecordRef method = op.trait.methods.data[i];
|
||||
if (method.takes_mut_self)
|
||||
@ -109,24 +124,14 @@ NODISCARD VecU8 generate_trait_wrapper_boilerplate(trait_wrapper_boil_options op
|
||||
}
|
||||
}
|
||||
if (op.mut_ref) {
|
||||
VecU8_append_vec(&res, VecU8_fmt(
|
||||
"typedef struct {\n"
|
||||
SPACE "void* r;\n"
|
||||
SPACE "const %s_Table* t;\n"
|
||||
"} MutRef%s;\n\n",
|
||||
op.trait.name, op.trait.name));
|
||||
codegen_append_trait_wrapper_structure_some_refkind(&res, op.trait, cstr("MutRef"), true);
|
||||
for (size_t i = 0; i < op.trait.methods.len; i++) {
|
||||
NamedMethodSignatureRecordRef method = op.trait.methods.data[i];
|
||||
codegen_append_trait_wrapper_some_method_some_refkind(&res, op.trait.name, method, cstr("MutRef"), false);
|
||||
}
|
||||
}
|
||||
if (op.box) {
|
||||
VecU8_append_vec(&res, VecU8_fmt(
|
||||
"typedef struct {\n"
|
||||
SPACE "void* r;\n"
|
||||
SPACE "const %s_Table* t;\n"
|
||||
"} Box%s;\n\n",
|
||||
op.trait.name, op.trait.name));
|
||||
codegen_append_trait_wrapper_structure_some_refkind(&res, op.trait, cstr("Box"), true);
|
||||
for (size_t i = 0; i < op.trait.methods.len; i++) {
|
||||
NamedMethodSignatureRecordRef method = op.trait.methods.data[i];
|
||||
codegen_append_trait_wrapper_some_method_some_refkind(&res, op.trait.name, method, cstr("Box"), true);
|
||||
|
||||
7
src/l2/gui/label.h
Normal file
7
src/l2/gui/label.h
Normal file
@ -0,0 +1,7 @@
|
||||
#ifndef prototype1_src_l2_gui_label_h
|
||||
#define prototype1_src_l2_gui_label_h
|
||||
|
||||
#include "../lucy/glyph_render.h"
|
||||
|
||||
|
||||
#endif
|
||||
104
src/l2/gui/widget.h
Normal file
104
src/l2/gui/widget.h
Normal file
@ -0,0 +1,104 @@
|
||||
#ifndef prototype1_src_l2_gui_widget_h
|
||||
#define prototype1_src_l2_gui_widget_h
|
||||
|
||||
#include "../../../gen/l1/geom.h"
|
||||
#include "../../l1/core/util.h"
|
||||
|
||||
#define WIDGET_DIM_INF 1000000
|
||||
|
||||
bool is_widget_size_limit_contain_inf(uvec2 max_limits){
|
||||
return max_limits.x >= WIDGET_DIM_INF || max_limits.y >= WIDGET_DIM_INF;
|
||||
}
|
||||
|
||||
void assert_sane_widget_size(uvec2 sz){
|
||||
assert(sz.x < WIDGET_DIM_INF || sz.y < WIDGET_DIM_INF);
|
||||
}
|
||||
|
||||
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)},
|
||||
{MAX_S32(a.rb.x, b.rb.x), MAX_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)};
|
||||
}
|
||||
|
||||
uvec2 widget_size_min_of_all(uvec2 a, uvec2 b){
|
||||
return (uvec2){MIN_U32(a.x, b.x), MIN_U32(a.y, b.y)};
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
/* .x == WIDGET_DIM_INF indicates that no preparation was made before the draw operation.
|
||||
* Calling draw at that state will cause abort. draw operation will reset this flag. This makes framework foolproof.
|
||||
* Initialize and reset with {WIDGET_DIM_INF, 0} */
|
||||
uvec2 sz_my_choice;
|
||||
} Widget;
|
||||
|
||||
Widget Widget_new(){
|
||||
return (Widget){.sz_my_choice = {WIDGET_DIM_INF, 0}};
|
||||
}
|
||||
|
||||
#include "../../../gen/l1_5/eve/gui/Widget.h"
|
||||
|
||||
uvec2 MutRefWidget_draw_prepare(MutRefWidget self, uvec2 max_limits){
|
||||
if (!self.r)
|
||||
return (uvec2){0};
|
||||
self.r->sz_my_choice = MutRefWidget_DRAW_PREPARE(self, max_limits);
|
||||
assert_sane_widget_size(self.r->sz_my_choice);
|
||||
return self.r->sz_my_choice;
|
||||
}
|
||||
|
||||
void MutRefWidget_draw(MutRefWidget self, ivec2 drawing_offset, uvec2 surface_sz, BorderS32 border){
|
||||
if (!self.r)
|
||||
return;
|
||||
if (self.r->sz_my_choice.x >= WIDGET_DIM_INF)
|
||||
abortf("Drawing widget before negotiating it's size\n");
|
||||
MutRefWidget_draw(self, drawing_offset, surface_sz, border);
|
||||
self.r->sz_my_choice = (uvec2){WIDGET_DIM_INF, 0};
|
||||
}
|
||||
|
||||
/* Some very simple widgets */
|
||||
|
||||
typedef struct {
|
||||
Widget base;
|
||||
U32 width;
|
||||
U32 height;
|
||||
} EmptyWidget;
|
||||
|
||||
uvec2 Widget_Table_EmptyWidget_DRAW_PREPARE(Widget* ug, uvec2 limits){
|
||||
EmptyWidget* self = (EmptyWidget*)ug;
|
||||
uvec2 R = widget_size_min_of_all((uvec2){self->width, self->height}, limits);
|
||||
return is_widget_size_limit_contain_inf(R) ? (uvec2){0, 0} : R;
|
||||
}
|
||||
|
||||
void Widget_Table_EmptyWidget_DRAW(Widget* ug, ivec2 drawing_offset, uvec2 surface_sz, BorderS32 border){}
|
||||
|
||||
void Widget_Table_EmptyWidget_drop(Widget* ug){}
|
||||
|
||||
const Widget_Table Widget_Table_EmptyWidget = {
|
||||
.DRAW_PREPARE = Widget_Table_EmptyWidget_DRAW_PREPARE,
|
||||
.DRAW = Widget_Table_EmptyWidget_DRAW,
|
||||
.drop = Widget_Table_EmptyWidget_drop,
|
||||
};
|
||||
|
||||
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};
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -98,5 +98,8 @@ mat4 marie_3d_scal_mat4(float scale){
|
||||
0, 0, 0, 1);
|
||||
}
|
||||
|
||||
vec2 ivec2_to_vec2(ivec2 v){
|
||||
return (vec2){(float)v.x, (float)v.y};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@ -1,135 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
"""
|
||||
Convert between custom bottom‑up raw files (.r8g8b8a8 / .r8b8g8 / .r8 / .a8)
|
||||
and normal PNG using Pillow.
|
||||
|
||||
Format
|
||||
------
|
||||
uint32 width (little‑endian)
|
||||
uint32 height (little‑endian)
|
||||
pixel data rows bottom‑first:
|
||||
* .r8g8b8a8 : R G B A (4× uint8)
|
||||
* .r8b8g8 : R G B (3× uint8)
|
||||
* .r8 : R (1× uint8 <- grayscale)
|
||||
* .a8 : A (can convert from it, but can't convert to it)
|
||||
|
||||
CLI
|
||||
---
|
||||
raw -> png : python raw_png_conv.py to_png input.raw output.png
|
||||
png -> raw : python raw_png_conv.py to_raw input.png output.raw
|
||||
"""
|
||||
import argparse
|
||||
import struct
|
||||
from pathlib import Path
|
||||
from PIL import Image
|
||||
|
||||
# --------------------------------------------------------------------- #
|
||||
# Helpers
|
||||
# --------------------------------------------------------------------- #
|
||||
|
||||
|
||||
RAW_FORMATS = {
|
||||
".r8g8b8a8": {"pix_size": 4, "mode": "RGBA"},
|
||||
".r8g8b8": {"pix_size": 3, "mode": "RGB"},
|
||||
".r8": {"pix_size": 1, "mode": "L"},
|
||||
".a8": {"pix_size": 1, "mode": None}, # special-cased (alpha-only)
|
||||
}
|
||||
|
||||
|
||||
def get_fmt(path: Path):
|
||||
fmt = RAW_FORMATS.get(path.suffix.lower())
|
||||
if not fmt:
|
||||
raise ValueError(f"Unknown raw extension: {path.suffix}")
|
||||
return fmt
|
||||
|
||||
|
||||
def read_header_and_data(path: Path, pix_size: int):
|
||||
with path.open("rb") as f:
|
||||
header = f.read(8)
|
||||
if len(header) != 8:
|
||||
raise ValueError("File too short for header")
|
||||
w, h = struct.unpack("<II", header)
|
||||
expected = w * h * pix_size
|
||||
data = f.read()
|
||||
if len(data) != expected:
|
||||
raise ValueError(
|
||||
f"Pixel data length mismatch: expected {expected}, got {len(data)}"
|
||||
)
|
||||
return w, h, data
|
||||
|
||||
|
||||
def read_raw(path: Path) -> Image.Image:
|
||||
"""Load any supported raw file -> Pillow Image."""
|
||||
spec = get_fmt(path)
|
||||
w, h, data = read_header_and_data(path, spec["pix_size"])
|
||||
|
||||
row_len = w * spec["pix_size"]
|
||||
rows = [data[i : i + row_len] for i in range(0, len(data), row_len)]
|
||||
top_down = b"".join(reversed(rows)) # flip bottom‑up -> top‑down
|
||||
|
||||
# Special handling for .a8 (alpha-only -> LA with black color)
|
||||
if path.suffix.lower() == ".a8":
|
||||
big = bytearray(4 * len(top_down))
|
||||
big[3::4] = top_down
|
||||
big = bytes(big)
|
||||
return Image.frombytes("RGBA", (w, h), big)
|
||||
|
||||
# Normal cases can be constructed directly
|
||||
return Image.frombytes(spec["mode"], (w, h), top_down)
|
||||
|
||||
|
||||
def write_raw(img: Image.Image, path: Path) -> None:
|
||||
"""Write Pillow Image -> raw file chosen by path suffix."""
|
||||
ext = path.suffix.lower()
|
||||
spec = get_fmt(path)
|
||||
|
||||
if ext == ".a8":
|
||||
raise ValueError("Don't convert to .a8 format")
|
||||
|
||||
target_mode = spec["mode"]
|
||||
if img.mode != target_mode:
|
||||
img = img.convert(target_mode)
|
||||
|
||||
w, h = img.size
|
||||
data = img.tobytes()
|
||||
row_len = w * spec["pix_size"]
|
||||
rows = [data[i : i + row_len] for i in range(0, len(data), row_len)]
|
||||
bottom_first = b"".join(reversed(rows)) # top‑down -> bottom‑up
|
||||
|
||||
with path.open("wb") as f:
|
||||
f.write(struct.pack("<II", w, h))
|
||||
f.write(bottom_first)
|
||||
|
||||
|
||||
# --------------------------------------------------------------------- #
|
||||
# CLI
|
||||
# --------------------------------------------------------------------- #
|
||||
|
||||
def to_png(src: Path, dst: Path):
|
||||
read_raw(src).save(dst, "PNG")
|
||||
|
||||
|
||||
def to_raw(src: Path, dst: Path):
|
||||
write_raw(Image.open(src), dst)
|
||||
|
||||
|
||||
def main():
|
||||
ap = argparse.ArgumentParser(description="Convert raw <-> PNG")
|
||||
sub = ap.add_subparsers(dest="cmd", required=True)
|
||||
p_png = sub.add_parser("to_png", help="raw -> png")
|
||||
p_png.add_argument("src", type=Path)
|
||||
p_png.add_argument("dst", type=Path)
|
||||
p_raw = sub.add_parser("to_raw", help="png -> raw")
|
||||
p_raw.add_argument("src", type=Path)
|
||||
p_raw.add_argument("dst", type=Path)
|
||||
args = ap.parse_args()
|
||||
|
||||
if args.cmd == "to_png":
|
||||
to_png(args.src, args.dst)
|
||||
else:
|
||||
to_raw(args.src, args.dst)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Loading…
x
Reference in New Issue
Block a user