diff --git a/.ecode/project_build.json b/.ecode/project_build.json deleted file mode 100644 index 304f2f4..0000000 --- a/.ecode/project_build.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "Debug": { - "build": [ - { - "args": "-C resources/shaders", - "command": "make", - "working_dir": "" - }, - { - "args": "build -g --threads 8", - "command": "c3c", - "working_dir": "" - } - ], - "build_types": [], - "clean": [ - { - "args": "clean", - "command": "c3c", - "working_dir": "" - } - ], - "config": { - "clear_sys_env": false - }, - "os": [ - "linux" - ], - "output_parser": { - "config": { - "relative_file_paths": true - } - }, - "run": [ - { - "args": "", - "command": "build/ugui", - "name": "Custom Executable", - "working_dir": "" - } - ] - } -} \ No newline at end of file diff --git a/.gitmodules b/.gitmodules index 256daf0..e69de29 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,15 +0,0 @@ -[submodule "lib/schrift.c3l/thirdparty/libschrift"] - path = lib/schrift.c3l/thirdparty/libschrift - url = https://github.com/tomolt/libschrift - ignore = dirty -[submodule "lib/sdl3.c3l"] - path = lib/sdl3.c3l - url = https://git.alemauri.eu/alema/sdl3.c3l - ignore = dirty -[submodule "lib/vendor"] - path = lib/vendor - url = https://github.com/c3lang/vendor - ignore = dirty -[submodule "lib/ugui_sdl.c3l"] - path = lib/ugui_sdl.c3l - url = https://git.alemauri.eu/alema/ugui_sdl.c3l.git diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md deleted file mode 100644 index b533650..0000000 --- a/ARCHITECTURE.md +++ /dev/null @@ -1,184 +0,0 @@ -## High level overview - -Under the hood every element has an id, this id allows the library to store state -between frames. -Elements are also cached such that when the ui tree is rebuilt at the beginning of -every frame the element data structure doesn't have to be rebuilt. - -Elements are arranged in a tree, nodes are container elements that can contain other -elements, leafs are elements that cannot contain other elements. - -Every element has a size and a position, containers also have to keep track of their -layout information and some other state. - -Elements can push commands into the draw stack, which is a structure that contains -all the draw commands that the user application has to perform do display the ui -correctly, such commands include drawing lines, rectangles, sprites, text, etc. - - -```text - +-----------+ - | ug_init() | - +-----+-----+ - | - | - | - +---------v----------+ - |ug_input_keyboard() | - |ug_input_mouse() <----+ - |ug_input_clipboard()| | - | ... | | - +---------+----------+ | - | | - | | - +-------v--------+ | - |ug_frame_begin()| | - +-------+--------+ | - | | - | | - +---------v----------+ | - |ug_window_start() | | - +---->ug_container_start()| | - | |ug_div_start() | | - | | ... | | - | +---------+----------+ | - | | | - | | | -multiple +--------v---------+ | - times |ug_layout_row() | | - | |ug_layout_column()| | - | |ug_layout_float() | | - | | ... | | - | +--------+---------+ | - | | | - | | | - | +------v------+ | - | |ug_button() | | - | |ug_text_box()| | - | |ug_slider() | | - | | ... | | - | +------+------+ | - | | | - +--------------+ | - | | - +--------v---------+ | - |ug_window_end() | | - |ug_container_end()| | - |ug_div_end() | | - | ... | | - +--------+---------+ | - | | - | | - | | - +------v-------+ | - |ug_frame_end()| | - +------+-------+ | - | | - | | - | | - +------v-------+ | - |user draws the| | - | ui +-------+ - +------+-------+ - | - |quit - | - +------v-------+ - | ug_destroy() | - +--------------+ -``` - -### Layouting - -Layouting happens in a dynamic grid, when a new element is inserted in a non-floating -manner it reserves a space in the grid, new elements are placed following this grid. - -Every div has two points of origin, one for the row layout and one for the column -layout, named origin_r and origin_c respectively - -origin_r is used when the row layout is used and it is used to position the child -elements one next to the other, as such it always points to the top-right edge -of the last row element - -```text -Layout: row -#: lost space - Parent div -x---------------------------------+ -|[origin_c] | -|[origin_r] | -| | -| | -| | -| | -| | -| | -| | -+---------------------------------+ - - Parent div -+-----x---------------------------+ -| |[origin_r] | -| E1 | | -| | | -x-----+---------------------------+ -|[origin_c] | -| | | -| | | -| | | -| | | -| | | -+-----+---------------------------+ - - Parent div -+-----+----------+-----x----------+ -| | E2 | |[origin_r]| -| E1 +----------+ | | -| |##########| E3 | | -+-----+##########| | | -|################| | | -+----------------x-----+----------+ -| [origin_c] | -| | | -| | | -| | | -+----------------+----------------+ -``` - -TODO: handle when the content overflows the div -- Use a different concept, like a view or relative space, for example the child -div could have position `[0,0]` but in reality it is relative to the origin of the -parent div -- each div could have a view and a total area of the content, when drawing everything -is clipped to the view and scrollbars are shown -- individual elements accept dimensions and the x/y coordinates could be interpreted -as offset if the layout is row/column or absolute coordinates if the leayout is floating - -A div can be marked resizeable or fixed, and static or dynamic. The difference being -that resizeable adds a resize handle to the div and dynamic lets the content overflow -causing scrollbars to be drawn - -### Notes - -How elements determine if they have focus or not - -```C -// in begin_{container} code -calculate focus -set has_focus property - - - -// in the element code -if(PARENT_HAS_FOCUS()) { - update stuff -} else { - fast path to return -} -``` - -How to get ids: - 1. use a name for each element - 2. supply an id for each element - 3. use a macro and the line position as id and then hash it - 4. use a macro, get the code line and hash it diff --git a/lib/ugui.c3l/LAYOUT b/LAYOUT similarity index 100% rename from lib/ugui.c3l/LAYOUT rename to LAYOUT diff --git a/Makefile b/Makefile deleted file mode 100644 index 7b9969a..0000000 --- a/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -C3FLAGS = -g - -main: src/main.c3 $(wildcard lib/ugui.c3l/src/*.c3) $(wildcard lib/ugui_sdl.c3l/) - make -C resources/shaders - c3c build ${C3FLAGS} diff --git a/README.md b/README.md index bb62933..151118a 100644 --- a/README.md +++ b/README.md @@ -1,43 +1 @@ -# UGUI - -Immediate mode ui library for C3. (Name subject to change). - -This repo contains the library itself, a renderer based on SLD3's new GPU API and a test program. -The library is located at `lib/ugui.c3l`. - -The layout algorithm is similar to flexbox. A graphical description of the layout algorithm is located in the [LAYOUT](lib/ugui.c3l/LAYOUT) file. The structure of the library is (was) described in the [ARCHITECTURE](ARCHITECTURE.md) file, most of it is now irrelevant and will be updated in the future. - -## Dependencies - -* `shaderc` for `glslc` -* `c3c` version >0.7.5 -* `SDL3` -* A C compiler - -## Building - -1. Clone the repo and all dependencies -```sh -git clone https://github.com/ma-ale/ugui -cd ugui -git submodule update --recursive --init -``` - -2. Build libgrapheme -```sh -cd lib/grapheme.c3l -make -cd ../.. -``` - -3. Compile libschrift -```sh -cd lib/schrift.c3l -make -cd ../.. -``` - -4. Build and run the project -```sh -make && build/ugui -``` \ No newline at end of file +Welcome to the ugui library. diff --git a/lib/.gitkeep b/lib/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/lib/schrift.c3l/Makefile b/lib/schrift.c3l/Makefile deleted file mode 100644 index 1de46d5..0000000 --- a/lib/schrift.c3l/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -all: - make -C thirdparty/libschrift - mkdir -p linux-x64 - cp thirdparty/libschrift/libschrift.a linux-x64/libschrift.a diff --git a/lib/schrift.c3l/libschrift.c3 b/lib/schrift.c3l/libschrift.c3 deleted file mode 100644 index 699d296..0000000 --- a/lib/schrift.c3l/libschrift.c3 +++ /dev/null @@ -1,58 +0,0 @@ -module schrift; - -alias SftFont = void*; -alias SftUChar = uint; -alias SftGlyph = uint; - -const int SFT_DOWNWARD_Y = 0x01; - -struct Sft -{ - SftFont font; - double xScale; - double yScale; - double xOffset; - double yOffset; - int flags; -} - -struct SftLMetrics -{ - double ascender; - double descender; - double lineGap; -} - -struct SftGMetrics -{ - double advanceWidth; - double leftSideBearing; - int yOffset; - int minWidth; - int minHeight; -} - -struct SftKerning -{ - double xShift; - double yShift; -} - -struct SftImage -{ - void *pixels; - int width; - int height; -} - -extern fn ZString sft_version() @extern("sft_version"); - -extern fn SftFont loadmem(void* mem, usz size) @extern("sft_loadmem"); -extern fn SftFont loadfile(ZString filename) @extern("sft_loadfile"); -extern fn void freefont(SftFont font) @extern("sft_freefont"); - -extern fn int lmetrics(Sft* sft, SftLMetrics* metrics) @extern("sft_lmetrics"); -extern fn int lookup(Sft* sft, SftUChar codepoint, SftGlyph* glyph) @extern("sft_lookup"); -extern fn int gmetrics(Sft* sft, SftGlyph glyph, SftGMetrics* metrics) @extern("sft_gmetrics"); -extern fn int kerning(Sft* sft, SftGlyph leftGlyph, SftGlyph rightGlyph, SftKerning* kerning) @extern("sft_kerning"); -extern fn int render(Sft* sft, SftGlyph glyph, SftImage image) @extern("sft_render"); diff --git a/lib/schrift.c3l/manifest.json b/lib/schrift.c3l/manifest.json deleted file mode 100644 index efb7f23..0000000 --- a/lib/schrift.c3l/manifest.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "provides" : "schrift", - "targets" : { - "linux-x64" : { - "dependencies" : [], - "linked-libraries" : ["schrift", "c"] - } - } -} diff --git a/lib/schrift.c3l/project.json b/lib/schrift.c3l/project.json deleted file mode 100644 index 92b049c..0000000 --- a/lib/schrift.c3l/project.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "langrev": "1", - "warnings": [ "no-unused" ], - "dependency-search-paths": [ ".." ], - "dependencies": [ "schrift" ], - "authors": [ "Alessandro Mauri ", "Thomas Oltmann " ], - "version": "0.1.0", - "sources": [ ], - "output": "build", - "target": "linux-x64", - "features": [], - "cpu": "generic", - "opt": "O0", -} diff --git a/lib/schrift.c3l/thirdparty/libschrift b/lib/schrift.c3l/thirdparty/libschrift deleted file mode 160000 index 24737d2..0000000 --- a/lib/schrift.c3l/thirdparty/libschrift +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 24737d2922b23df4a5692014f5ba03da0c296112 diff --git a/lib/sdl3.c3l b/lib/sdl3.c3l deleted file mode 160000 index e7356df..0000000 --- a/lib/sdl3.c3l +++ /dev/null @@ -1 +0,0 @@ -Subproject commit e7356df5d1d0c22a6bba822bda6994062b0b75d7 diff --git a/lib/ugui.c3l/LICENSE b/lib/ugui.c3l/LICENSE deleted file mode 100644 index e69de29..0000000 diff --git a/lib/ugui.c3l/README.md b/lib/ugui.c3l/README.md deleted file mode 100644 index 151118a..0000000 --- a/lib/ugui.c3l/README.md +++ /dev/null @@ -1 +0,0 @@ -Welcome to the ugui library. diff --git a/lib/ugui.c3l/linux-x64/.gitkeep b/lib/ugui.c3l/linux-x64/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/lib/ugui.c3l/scripts/.gitkeep b/lib/ugui.c3l/scripts/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/lib/ugui_sdl.c3l b/lib/ugui_sdl.c3l deleted file mode 160000 index 050624f..0000000 --- a/lib/ugui_sdl.c3l +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 050624fd67c2d80190114c7774ccfa64b0f449b9 diff --git a/lib/vendor b/lib/vendor deleted file mode 160000 index db00622..0000000 --- a/lib/vendor +++ /dev/null @@ -1 +0,0 @@ -Subproject commit db006221a8af625630fdb8b56707f3d07d4314a2 diff --git a/docs/.gitkeep b/linux-x64/.gitkeep similarity index 100% rename from docs/.gitkeep rename to linux-x64/.gitkeep diff --git a/lib/ugui.c3l/manifest.json b/manifest.json similarity index 100% rename from lib/ugui.c3l/manifest.json rename to manifest.json diff --git a/project.json b/project.json deleted file mode 100644 index 0440f28..0000000 --- a/project.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "langrev": "1", - "warnings": ["no-unused"], - "dependency-search-paths": ["lib", "lib/vendor/libraries"], - "dependencies": ["sdl3", "ugui", "ugui_sdl3"], - "features": ["DEBUG_POINTER"], - "authors": ["Alessandro Mauri "], - "version": "0.1.0", - "sources": ["src/**"], - "output": "build", - "target": "linux-x64", - "targets": { - "ugui": { - "type": "executable" - } - }, - "safe": true, - "opt": "O1", - "debug-info": "full" -} diff --git a/resources/.gitkeep b/resources/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/resources/hack-nerd.ttf b/resources/hack-nerd.ttf deleted file mode 100644 index f397f20..0000000 Binary files a/resources/hack-nerd.ttf and /dev/null differ diff --git a/resources/shaders/Makefile b/resources/shaders/Makefile deleted file mode 100644 index cdc4a01..0000000 --- a/resources/shaders/Makefile +++ /dev/null @@ -1,33 +0,0 @@ -SOURCE_DIR := ./source -COMPILED_DIR := ./compiled - -SOURCE_FILES := $(wildcard $(SOURCE_DIR)/*.glsl) - -COMPILED_FILES := $(patsubst $(SOURCE_DIR)/%.glsl,$(COMPILED_DIR)/%.spv,$(SOURCE_FILES)) - -all: $(COMPILED_FILES) - @echo "Compiling shaders from $(SOURCE_DIR) -> $(COMPILED_DIR)" - -$(COMPILED_DIR)/%.spv: $(SOURCE_DIR)/%.glsl - @mkdir -p $(COMPILED_DIR) - @stage=$$(basename $< .glsl | cut -d. -f2); \ - if [ "$$stage" = "frag" ] || [ "$$stage" = "vert" ]; then \ - echo "$$stage $(notdir $<) > $(notdir $@)"; \ - glslc -O0 -g -fshader-stage=$$stage $< -o $@; \ - else \ - echo "Skipping $<: unsupported stage $$stage"; \ - fi - -$(COMPILED_DIR): - mkdir -p $(COMPILED_DIR) - -.PHONY: clean -clean: - rm -rf $(COMPILED_DIR) - -.PHONY: tree -tree: - tree $(COMPILED_DIR) - -.PHONY: compile_all -compile_all: clean all tree diff --git a/resources/shaders/source/ugui.frag.glsl b/resources/shaders/source/ugui.frag.glsl deleted file mode 100644 index 2618c2e..0000000 --- a/resources/shaders/source/ugui.frag.glsl +++ /dev/null @@ -1,118 +0,0 @@ -#version 450 - -/* Combined fragment shader to render UGUI commands */ - -// type values, these are the same as in renderer.c3 -const uint TYPE_RECT = 0; -const uint TYPE_FONT = 1; -const uint TYPE_SPRITE = 2; -const uint TYPE_MSDF = 3; - -// viewport size -layout(set = 3, binding = 0) uniform Viewport { - ivec2 view; -}; - -// textures -layout(set = 2, binding = 0) uniform sampler2D font_atlas; -layout(set = 2, binding = 1) uniform sampler2D sprite_atlas; - -// inputs -layout(location = 0) in vec4 in_color; -layout(location = 1) in vec2 in_uv; -layout(location = 2) in vec4 in_quad_size; -layout(location = 3) in float in_radius; -layout(location = 4) flat in uint in_type; - -// outputs -layout(location = 0) out vec4 fragColor; - - -// SDF for a rounded rectangle given the centerpoint, half size and radius, all in pixels -float sdf_rr(vec2 p, vec2 half_size, float radius) { - vec2 q = abs(p) - half_size + radius; - return length(max(q, 0.0)) + min(max(q.x, q.y), 0.0) - radius; -} - - -const float PX_RANGE = 4.0f; -float screen_px_range(vec2 uv, sampler2D tx) { - vec2 unit_range = vec2(PX_RANGE)/vec2(textureSize(tx, 0)); - vec2 texel_size = vec2(1.0)/fwidth(uv); - return max(0.5*dot(unit_range, texel_size), 1.0); -} - - -float median(float r, float g, float b) { - return max(min(r, g), min(max(r, g), b)); -} - - -// main for TYPE_RECT, draw a rouded rectangle with a SDF -void rect_main() -{ - vec2 centerpoint = in_quad_size.xy + in_quad_size.zw * 0.5; - vec2 half_size = in_quad_size.zw * 0.5; - float distance = sdf_rr(vec2(gl_FragCoord) - centerpoint, half_size, in_radius); - float alpha = 1.0 - smoothstep(0.0, 1.5, distance); - fragColor = vec4(in_color.rgb, in_color.a * alpha); -} - - -// main for TYPE_SPRITE, draws a sprite sampled from an atlas -void sprite_main() -{ - ivec2 ts = textureSize(sprite_atlas, 0); - vec2 fts = vec2(ts); - vec2 real_uv = in_uv.xy / fts; - fragColor = texture(sprite_atlas, real_uv); -} - - -// main for TYPE_FONT, draws a character sampled from an atlas that contains only the alpha channel -void font_main() -{ - ivec2 ts = textureSize(font_atlas, 0); - vec2 fts = vec2(ts); - vec2 real_uv = in_uv.xy / fts; - - vec4 opacity = texture(font_atlas, real_uv); - fragColor = vec4(in_color.rgb, in_color.a*opacity.r); -} - - -// main for TYPE_MSDF, draws a sprite that is stored as a multi-channel SDF -void msdf_main() { - ivec2 ts = textureSize(sprite_atlas, 0); - vec2 fts = vec2(ts); - vec2 real_uv = in_uv.xy / fts; - - vec3 msd = texture(sprite_atlas, real_uv).rgb; - float sd = median(msd.r, msd.g, msd.b); - float distance = screen_px_range(real_uv, sprite_atlas)*(sd - 0.5); - float opacity = clamp(distance + 0.5, 0.0, 1.0); - fragColor = in_color * opacity; -} - - -// shader main -void main() -{ - switch (in_type) { - case TYPE_RECT: - rect_main(); - break; - case TYPE_FONT: - font_main(); - break; - case TYPE_SPRITE: - sprite_main(); - break; - case TYPE_MSDF: - msdf_main(); - break; - default: - // ERROR, invalid type, return magenta - fragColor = vec4(1.0, 0.0, 1.0, 1.0); - } -} \ No newline at end of file diff --git a/resources/shaders/source/ugui.vert.glsl b/resources/shaders/source/ugui.vert.glsl deleted file mode 100644 index ee29724..0000000 --- a/resources/shaders/source/ugui.vert.glsl +++ /dev/null @@ -1,47 +0,0 @@ -#version 450 - -/* Combined vertex shader to render UGUI commands */ - -// Viewport size in pixels -layout(set = 1, binding = 0) uniform Viewport { - ivec2 view; -}; - -// inputs -layout(location = 0) in ivec2 in_position; -layout(location = 1) in ivec4 in_attr; // quad x,y,w,h -layout(location = 2) in ivec4 in_uv; -layout(location = 3) in uvec4 in_color; -layout(location = 4) in uint in_type; - -// outputs -layout(location = 0) out vec4 out_color; -layout(location = 1) out vec2 out_uv; -layout(location = 2) out vec4 out_quad_size; -layout(location = 3) out float out_radius; -layout(location = 4) out uint out_type; - - -void main() -{ - // vertex position - ivec2 px_pos = in_attr.xy + in_position.xy * in_attr.zw; - vec2 clip_pos; - clip_pos.x = float(px_pos.x)*2.0 / view.x - 1.0; - clip_pos.y = -(float(px_pos.y)*2.0 / view.y - 1.0); - gl_Position = vec4(clip_pos, 0.0, 1.0); - - // color output - out_color = vec4(in_color) / 255.0; - - // uv output. only useful if the type is SPRITE - vec2 px_uv = in_uv.xy + in_position.xy * in_uv.zw; - out_uv = vec2(px_uv); - - // quad size and radius output, only useful if type is RECT - out_quad_size = vec4(in_attr); - out_radius = float(abs(in_uv.x)); - - // type output - out_type = in_type; -} \ No newline at end of file diff --git a/resources/style.css b/resources/style.css deleted file mode 100644 index c043b0b..0000000 --- a/resources/style.css +++ /dev/null @@ -1,86 +0,0 @@ -div { - bg: #282828; - fg: #fbf1c7ff; - primary: #cc241dff; - secondary: #6c19ca8f; - accent: #fabd2fff; - border: 1; - padding: 0; - margin: 0; - radius: 0; -} - -button { - margin: 2; - border: 2; - padding: 2; - radius: 10; - size: 32; - - bg: #3c3836ff; - fg: #fbf1c7ff; - primary: #cc241dff; - secondary: #458588ff; - accent: #504945ff; -} - -checkbox { - margin: 2; - border: 2; - padding: 1; - radius: 10; - size: 20; - bg: #3c3836ff; - fg: #fbf1c7ff; - primary: #cc241dff; - secondary: #458588ff; - accent: #fabd2fff; -} - -toggle { - margin: 2; - border: 2; - padding: 1; - radius: 10; - size: 20; - bg: #3c3836ff; - fg: #fbf1c7ff; - primary: #cc241dff; - secondary: #458588ff; - accent: #fabd2fff; -} - -slider { - margin: 2; - padding: 2; - border: 1; - radius: 4; - size: 8; - bg: #3c3836ff; - fg: #fbf1c7ff; - primary: #cc241dff; - secondary: #458588ff; - accent: #fabd2fff; -} - -scrollbar { - padding: 2; - size: 8; - bg: #45858842; - fg: #fbf1c7ff; - primary: #cc241dff; - secondary: #458588ff; - accent: #fabd2fff; -} - - -text-box { - bg: #4a4543ff; - fg: #fbf1c7ff; - primary: #cc241dff; - secondary: #458588ff; - accent: #8f3f61a8; - border: 1; - padding: 4; - margin: 2; -} diff --git a/resources/tick_sdf.qoi b/resources/tick_sdf.qoi deleted file mode 100644 index 51a8f81..0000000 Binary files a/resources/tick_sdf.qoi and /dev/null differ diff --git a/resources/tux.qoi b/resources/tux.qoi deleted file mode 100644 index 57d6333..0000000 Binary files a/resources/tux.qoi and /dev/null differ diff --git a/resources/tux_inv.qoi b/resources/tux_inv.qoi deleted file mode 100644 index 947fb28..0000000 Binary files a/resources/tux_inv.qoi and /dev/null differ diff --git a/src/.gitkeep b/src/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/lib/ugui.c3l/src/atlas.c3 b/src/atlas.c3 similarity index 100% rename from lib/ugui.c3l/src/atlas.c3 rename to src/atlas.c3 diff --git a/lib/ugui.c3l/src/cache.c3 b/src/cache.c3 similarity index 100% rename from lib/ugui.c3l/src/cache.c3 rename to src/cache.c3 diff --git a/lib/ugui.c3l/src/cmd.c3 b/src/cmd.c3 similarity index 100% rename from lib/ugui.c3l/src/cmd.c3 rename to src/cmd.c3 diff --git a/lib/ugui.c3l/src/core.c3 b/src/core.c3 similarity index 100% rename from lib/ugui.c3l/src/core.c3 rename to src/core.c3 diff --git a/lib/ugui.c3l/src/font.c3 b/src/font.c3 similarity index 100% rename from lib/ugui.c3l/src/font.c3 rename to src/font.c3 diff --git a/lib/ugui.c3l/src/input.c3 b/src/input.c3 similarity index 100% rename from lib/ugui.c3l/src/input.c3 rename to src/input.c3 diff --git a/lib/ugui.c3l/src/layout.c3 b/src/layout.c3 similarity index 100% rename from lib/ugui.c3l/src/layout.c3 rename to src/layout.c3 diff --git a/src/main.c3 b/src/main.c3 deleted file mode 100644 index 7489ef5..0000000 --- a/src/main.c3 +++ /dev/null @@ -1,420 +0,0 @@ -import std::io; -import ugui; -import std::time; -import std::collections::ringbuffer; -import std::core::string; -import std::core::mem::allocator; -import ugui::sdl::ren; - - -alias Times = ringbuffer::RingBuffer{time::NanoDuration[128]}; - -fn void Times.print_stats(×) -{ - time::NanoDuration min, max, avg, x; - min = times.get(0); - for (usz i = 0; i < times.written; i++) { - x = times.get(i); - if (x < min) { min = x; } - if (x > max) { max = x; } - avg += x; - } - avg = (NanoDuration)((ulong)avg/128.0); - - io::printfn("min=%s, max=%s, avg=%s", min, max, avg); -} - -struct TimeStats { - time::NanoDuration min, max, avg; -} - -fn TimeStats Times.get_stats(×) -{ - time::NanoDuration min, max, avg, x; - min = times.get(0); - for (usz i = 0; i < times.written; i++) { - x = times.get(i); - if (x < min) { min = x; } - if (x > max) { max = x; } - avg += x; - } - avg = (NanoDuration)((ulong)avg/128.0); - - return {.min = min, .max = max, .avg = avg}; -} - - -const char[*] VS_PATH = "resources/shaders/compiled/ugui.vert.spv"; -const char[*] FS_PATH = "resources/shaders/compiled/ugui.frag.spv"; - -const char[*] STYLESHEET_PATH = "resources/style.css"; - -const bool LIMIT_FPS = true; -const bool VSYNC = true; - -fn int main(String[] args) -{ - ArenaAllocator arena; - char[] mem = mem::new_array(char, 1024*1024); - defer (void)mem::free(mem); - arena.init(mem); - - ugui::Ctx ui; - ui.init(&arena)!!; - defer ui.free(); - - ren::Renderer ren; - ren.init("Ugui Test", 800, 600, VSYNC); - defer ren.free(); - ui.input_window_size(800, 600)!!; - - // ========================================================================================== // - // FONT LOADING // - // ========================================================================================== // - // import font in the ui context - ui.load_font(&arena, "font1", "resources/hack-nerd.ttf", 16)!!; - - // set the renderer's font atlas - ren.font_atlas_id = ui.get_font_id("font1"); - - // send the atlas to the gpu - Atlas* font_atlas = ui.get_font_atlas("font1")!!; - ren.new_texture("font1", JUST_ALPHA, font_atlas.buffer, font_atlas.width, font_atlas.height); - - // ========================================================================================== // - // ICON LOADING // - // ========================================================================================== // - // create the atlas and upload some icons - ui.sprite_atlas_create("icons", AtlasType.ATLAS_R8G8B8A8, 512, 512)!!; - ui.import_sprite_file_qoi("tux", "resources/tux.qoi")!!; - ui.import_sprite_file_qoi("tick", "resources/tick_sdf.qoi", SpriteType.SPRITE_MSDF)!!; - - // set the renderer's sprite atlas - ren.sprite_atlas_id = ui.get_sprite_atlas_id("icons"); - - // upload the atlas to the gpu - Atlas atlas = ui.sprite_atlas.atlas; - ren.new_texture("icons", FULL_COLOR, atlas.buffer, atlas.width, atlas.height); - - // ========================================================================================== // - // PIPELINE SETUP // - // ========================================================================================== // - ren.load_spirv_shader_from_file("UGUI_PIPELINE", VS_PATH, FS_PATH, 2, 0); - ren.create_pipeline("UGUI_PIPELINE", RECT); - - // ========================================================================================== // - // CSS INPUT // - // ========================================================================================== // - io::printfn("imported %d styles", ui.import_style_from_file(STYLESHEET_PATH)); - - // ========================================================================================== // - // OTHER VARIABLES // - // ========================================================================================== // - TextEdit te; - te.buffer = mem::new_array(char, 256); - defer mem::free(te.buffer); - - isz frame; - double fps; - time::Clock clock; - time::Clock fps_clock; - time::Clock sleep_clock; - Times ui_times; - Times draw_times; - - // ========================================================================================== // - // MAIN LOOP // - // ========================================================================================== // - ren::pre(ren.win); - - bool quit; - while (!quit) { - clock.mark(); - fps_clock.mark(); - sleep_clock.mark(); - - quit = ui.handle_events()!!; - - /* End Input Handling */ - - /* Start UI Handling */ - ui.frame_begin()!!; - - if (ui.check_key_combo(ugui::KMOD_CTRL, "q")) quit = true; - -const String APPLICATION = "calculator"; -$switch APPLICATION: -$case "debug": - debug_app(&ui); -$case "calculator": - calculator(&ui, &te); -$case "popup": - popup(&ui); -$endswitch - - // Timings counter - TimeStats dts = draw_times.get_stats(); - TimeStats uts = ui_times.get_stats(); - - ui.@div(ugui::@fit(), ugui::@fit(), COLUMN, TOP_LEFT, absolute: true, off: {10, 10}) { - ui.text(string::tformat("frame %d, fps = %.2f", frame, fps))!!; - ui.text(string::tformat("ui avg: %s\ndraw avg: %s\nTOT: %s", uts.avg, dts.avg, uts.avg+dts.avg))!!; - }!!; - - ui.frame_end()!!; - /* End UI Handling */ - ui_times.push(clock.mark()); - //ui_times.print_stats(); - - /* Start UI Drawing */ - ren.begin_render(true); - - ren.render_ugui(&ui.cmd_queue); - - ren.end_render(); - - draw_times.push(clock.mark()); - //draw_times.print_stats(); - /* End Drawing */ - - // wait for the next event, timeout after 100ms - int timeout = LIMIT_FPS ? (int)(100.0-sleep_clock.mark().to_ms()-0.5) : 0; - if (ui.skip_frame) timeout = 0; - ren::wait_events(timeout); - - fps = 1.0 / fps_clock.mark().to_sec(); - frame++; - } - - return 0; -} - -fn void debug_app(ugui::Ctx* ui) -{ - static LayoutDirection d = ROW; - ui.@div(ugui::@grow(), ugui::@grow(), anchor: CENTER) { - ui.@div(ugui::@exact(300), ugui::@exact(300), d, scroll_x: true, scroll_y: true) { - if (ui.button("one")!!.mouse_release) d = COLUMN; - if (ui.button("two")!!.mouse_release) d = ROW; - ui.button("three")!!; - ui.button("four")!!; - ui.button("five")!!; - ui.button("six")!!; - ui.button("seven")!!; - ui.button("eight")!!; - ui.button("nine")!!; - ui.button("ten")!!; - }!!; - }!!; -} - -/* -fn void debug_app(ugui::Ctx* ui) -{ - static bool toggle; - ui.div_begin({.w=-100})!!; - { - ui.layout_set_column()!!; - if (ui.button(icon:"tux")!!.mouse_press) { - io::printn("press button0"); - toggle = !toggle; - } - //ui.layout_next_column()!!; - if (ui.button(label: "ciao", icon: "tick")!!.mouse_press) { - io::printn("press button1"); - } - //ui.layout_next_column()!!; - if (ui.button()!!.mouse_release) { - io::printn("release button2"); - } - - ui.layout_set_row()!!; - ui.layout_next_row()!!; - static float rf, gf, bf, af; - ui.slider_ver({0,0,30,100}, &rf)!!; - ui.slider_ver({0,0,30,100}, &gf)!!; - ui.slider_ver({0,0,30,100}, &bf)!!; - ui.slider_ver({0,0,30,100}, &af)!!; - - ui.layout_next_column()!!; - ui.text_unbounded("Ciao Mamma\nAbilità ⚡\n'\udb80\udd2c'")!!; - - ui.layout_next_column()!!; - ui.button("Continua!")!!; - - ui.layout_next_row()!!; - static bool check; - ui.checkbox("", {}, &check, "tick")!!; - ui.checkbox("", {}, &check)!!; - ui.toggle("", {}, &toggle)!!; - - ui.sprite("tux")!!; - static char[128] text_box = "ciao mamma"; - static usz text_len = "ciao mamma".len; - ui.text_box({0,0,200,200}, text_box[..], &text_len)!!; - }; - ui.div_end()!!; - - ui.div_begin(ugui::DIV_FILL, scroll_x: true, scroll_y: true)!!; - { - ui.layout_set_column()!!; - static float slider2 = 0.5; - if (ui.slider_ver({0,0,30,100}, &slider2)!!.update) { - io::printfn("other slider: %f", slider2); - } - ui.button()!!; - ui.button()!!; - ui.button()!!; - ui.button()!!; - if (toggle) { - ui.button()!!; - ui.button()!!; - ui.button()!!; - ui.button()!!; - } - ui.layout_next_column()!!; - ui.layout_set_row()!!; - static float f1, f2; - ui.slider_hor({0,0,100,30}, &f1)!!; - ui.slider_hor({0,0,100,30}, &f2)!!; - }; - ui.div_end()!!; -} -*/ - -import std::os::process; - -fn void calculator(ugui::Ctx* ui, TextEdit* te) -{ - static char[128] buffer; - static usz len; - bool eval; - - // keyboard input - switch(ui.get_keys()) { - case "+": nextcase; - case "-": nextcase; - case "*": nextcase; - case "/": nextcase; - case "(": nextcase; - case ")": nextcase; - case ".": nextcase; - case "0": nextcase; - case "1": nextcase; - case "2": nextcase; - case "3": nextcase; - case "4": nextcase; - case "5": nextcase; - case "6": nextcase; - case "7": nextcase; - case "8": nextcase; - case "9": - buffer[len++] = ui.get_keys()[0]; - case "\n": - eval = len != 0; - case "c": - len = 0; - case "d": - if (len > 0) len--; - } - - static bool toggle; - static ugui::Point pos; - if (ui.is_mouse_released(ugui::BTN_RIGHT)) { - pos = ui.input.mouse.pos; - toggle = !toggle; - } - if (toggle) { - toggle = ui.popup_begin(pos, ugui::@fit(50), ugui::@fit(100), COLUMN)!!; - ui.button("Uno")!!; - ui.button("Due")!!; - ui.button("Tre")!!; - ui.button("Quattro")!!; - ui.div_end()!!; - } - - // ui input/output - ui.@div(ugui::@grow(), ugui::@grow(), ROW, CENTER) { // center everything on the screen - ui.@div(ugui::@fit(), ugui::@fit(), COLUMN, TOP_LEFT) { - - ui.@div(ugui::@grow(), ugui::@fit(), ROW, CENTER) {ui.text("SHITTY AHH CALCULATOR")!!;}!!; - ui.@div(ugui::@grow(), ugui::@exact(100), ROW, RIGHT) { - ui.text((String)buffer[:len])!!; - }!!; - ui.@row() { - ui.@column() { - ui.button("7")!!.mouse_press ? buffer[len++] = '7' : 0; - ui.button("4")!!.mouse_press ? buffer[len++] = '4' : 0; - ui.button("1")!!.mouse_press ? buffer[len++] = '1' : 0; - ui.button("0")!!.mouse_press ? buffer[len++] = '0' : 0; - }!!; - ui.@column() { - ui.button("8")!!.mouse_press ? buffer[len++] = '8' : 0; - ui.button("5")!!.mouse_press ? buffer[len++] = '5' : 0; - ui.button("2")!!.mouse_press ? buffer[len++] = '2' : 0; - ui.button(".")!!.mouse_press ? buffer[len++] = '.' : 0; - }!!; - ui.@column() { - ui.button("9")!!.mouse_press ? buffer[len++] = '9' : 0; - ui.button("6")!!.mouse_press ? buffer[len++] = '6' : 0; - ui.button("3")!!.mouse_press ? buffer[len++] = '3' : 0; - ui.button("(")!!.mouse_press ? buffer[len++] = '(' : 0; - }!!; - ui.@div(ugui::@exact(10), ugui::@exact(10)) {}!!; - ui.@column() { - ui.button("x")!!.mouse_press ? buffer[len++] = '*' : 0; - ui.button("/")!!.mouse_press ? buffer[len++] = '/' : 0; - ui.button("+")!!.mouse_press ? buffer[len++] = '+' : 0; - ui.button(")")!!.mouse_press ? buffer[len++] = ')' : 0; - }!!; - ui.@column() { - ui.button("C")!!.mouse_press ? len = 0 : 0; - ui.button("D")!!.mouse_press ? len > 0 ? len-- : 0 : 0; - ui.button("-")!!.mouse_press ? buffer[len++] = '-' : 0; - - // eval the expression with 'bc' - if (ui.button("=")!!.mouse_press || eval) { - char[128] out; - String y = string::tformat("echo '%s' | bc", (String)buffer[:len]); - String x = process::execute_stdout_to_buffer(out[:128], (String[]){"sh", "-c", y}) ?? ""; - buffer[:x.len] = x[..]; - len = x.len; - } - }!!; - }!!; - ui.@div(ugui::@grow(), ugui::@fit(), anchor: CENTER) { - static bool state; - ui.checkbox("boolean", &state, "tick")!!; - ui.sprite("tux", 32)!!; - ui.toggle("lmao", &state)!!; - }!!; - ui.@div(ugui::@grow(), ugui::@exact(50), anchor: CENTER, scroll_y: true) { - static float f; - ui.slider_hor(ugui::@exact(100), ugui::@exact(20), &f)!!; - ui.slider_ver(ugui::@exact(20), ugui::@exact(100), &f)!!; - }!!; - ui.@div(ugui::@grow(), ugui::@fit(), anchor: CENTER) { - ui.text_box(ugui::@grow(), ugui::@exact(100), te, TOP_LEFT)!!; - }!!; - }!!; }!!; -} - -fn void popup(ugui::Ctx* ui) -{ - static bool toggle; - static ugui::Point pos; - - if (toggle) { - toggle = ui.popup_begin(pos, ugui::@fit(), ugui::@fit(), COLUMN)!!; - ui.button("POP")!!; - ui.button("UP")!!; - ui.div_end()!!; - } - ui.@center(COLUMN) { - if (ui.button("ciao")!!.mouse_release) { - pos = ui.input.mouse.pos; - toggle = ~toggle; - } - if (ui.button("mamma")!!.mouse_press) ugui::println("pressed!"); - }!!; -} diff --git a/lib/ugui.c3l/src/mtree.c3 b/src/mtree.c3 similarity index 100% rename from lib/ugui.c3l/src/mtree.c3 rename to src/mtree.c3 diff --git a/lib/ugui.c3l/src/shapes.c3 b/src/shapes.c3 similarity index 100% rename from lib/ugui.c3l/src/shapes.c3 rename to src/shapes.c3 diff --git a/lib/ugui.c3l/src/sprite.c3 b/src/sprite.c3 similarity index 100% rename from lib/ugui.c3l/src/sprite.c3 rename to src/sprite.c3 diff --git a/lib/ugui.c3l/src/string.c3 b/src/string.c3 similarity index 100% rename from lib/ugui.c3l/src/string.c3 rename to src/string.c3 diff --git a/lib/ugui.c3l/src/style.c3 b/src/style.c3 similarity index 89% rename from lib/ugui.c3l/src/style.c3 rename to src/style.c3 index ebfefd2..53cdf04 100644 --- a/lib/ugui.c3l/src/style.c3 +++ b/src/style.c3 @@ -90,7 +90,7 @@ fn int Ctx.import_style_from_file(&ctx, String path) *