ugui/src/main.c3

307 lines
8.0 KiB

import std::io;
import vtree;
import cache;
import ugui;
import rl;
import std::time;
import std::collections::ringbuffer;
import std::core::string;
def Times = ringbuffer::RingBuffer(<time::NanoDuration, 128>);
fn void Times.print_stats(&times)
{
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(&times)
{
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 TimeStats{.min = min, .max = max, .avg = avg};
}
const ZString FONT_FS = `
#version 330
// Input vertex attributes (from vertex shader)
in vec2 fragTexCoord;
in vec4 fragColor;
// Input uniform values
uniform sampler2D texture0;
uniform vec4 colDiffuse;
// Output fragment color
out vec4 finalColor;
void main()
{
vec4 alpha = texture(texture0, fragTexCoord);
finalColor = colDiffuse*fragColor;
finalColor.a *= alpha.r;
}
`;
fn int main(String[] args)
{
ugui::Ctx ui;
ui.init()!!;
ui.load_font("font1", "resources/hack-nerd.ttf", 16)!!;
short width = 800;
short height = 450;
rl::set_config_flags(rl::FLAG_WINDOW_RESIZABLE);
rl::init_window(width, height, "Ugui Test");
ui.input_window_size(width, height)!!;
rl::set_target_fps(60);
rl::enable_event_waiting();
isz frame;
bool toggle = true;
time::Clock clock;
Times ui_times;
Times draw_times;
// font stuff
rl::Shader font_shader = rl::load_shader_from_memory(null, FONT_FS);
rl::Image font_atlas;
rl::Texture2D font_texture;
ugui::Id font_id = ui.get_font_id("font1");
// Main loop
while (!rl::window_should_close()) {
clock.mark();
/* Start Input Handling */
if (rl::is_window_resized()) {
width = (short)rl::get_screen_width();
height = (short)rl::get_screen_height();
ui.input_window_size(width, height)!!;
}
ui.input_changefocus(rl::is_window_focused());
rl::Vector2 mpos = rl::get_mouse_position();
ui.input_mouse_abs((short)mpos.x, (short)mpos.y);
ugui::MouseButtons buttons;
buttons.btn_left = rl::is_mouse_button_down(rl::MOUSE_BUTTON_LEFT);
buttons.btn_right = rl::is_mouse_button_down(rl::MOUSE_BUTTON_RIGHT);
buttons.btn_middle = rl::is_mouse_button_down(rl::MOUSE_BUTTON_MIDDLE);
ui.input_mouse_button(buttons);
/* End Input Handling */
/* Start UI Handling */
ui.frame_begin()!!;
// main div, fill the whole window
ui.div_begin("main", ugui::Rect{.w=ui.width/2})!!;
{|
ui.layout_set_column()!!;
if (ui.button("button0", ugui::Rect{0,0,30,30}, toggle)!!.mouse_press) {
io::printn("press button0");
toggle = !toggle;
}
//ui.layout_next_column()!!;
if (ui.button("button1", ugui::Rect{0,0,30,30})!!.mouse_press) {
io::printn("press button1");
}
//ui.layout_next_column()!!;
if (ui.button("button2", ugui::Rect{0,0,30,30})!!.mouse_release) {
io::printn("release button2");
}
ui.layout_set_row()!!;
ui.layout_next_row()!!;
static float rf, gf, bf, af;
ui.slider_ver("slider_r", ugui::Rect{0,0,30,100}, &rf)!!;
ui.slider_ver("slider_g", ugui::Rect{0,0,30,100}, &gf)!!;
ui.slider_ver("slider_b", ugui::Rect{0,0,30,100}, &bf)!!;
ui.slider_ver("slider_a", ugui::Rect{0,0,30,100}, &af)!!;
ui.layout_next_column()!!;
ui.text_unbounded("text1", "Ciao Mamma\nAbilità ⚡")!!;
ui.layout_next_column()!!;
ui.button_label("Continua!")!!;
|};
ui.div_end()!!;
ui.div_begin("second", ugui::DIV_FILL, scroll_x: true, scroll_y: true)!!;
{|
ui.layout_set_column()!!;
static float slider2 = 0.5;
if (ui.slider_ver("slider", ugui::Rect{0,0,30,100}, &slider2)!!.update) {
io::printfn("other slider: %f", slider2);
}
ui.button("button0", ugui::Rect{0,0,50,50})!!;
ui.button("button1", ugui::Rect{0,0,50,50})!!;
ui.button("button2", ugui::Rect{0,0,50,50})!!;
ui.button("button3", ugui::Rect{0,0,50,50})!!;
if (toggle) {
ui.button("button4", ugui::Rect{0,0,50,50})!!;
ui.button("button5", ugui::Rect{0,0,50,50})!!;
ui.button("button6", ugui::Rect{0,0,50,50})!!;
ui.button("button7", ugui::Rect{0,0,50,50})!!;
}
ui.layout_next_column()!!;
ui.layout_set_row()!!;
static float f1, f2;
ui.slider_hor("hs1", ugui::Rect{0,0,100,30}, &f1)!!;
ui.slider_hor("hs2", ugui::Rect{0,0,100,30}, &f2)!!;
|};
ui.div_end()!!;
// Timings counter
TimeStats dts = draw_times.get_stats();
TimeStats uts = ui_times.get_stats();
ui.layout_set_floating()!!;
ui.div_begin("fps", ugui::Rect{0, ui.height-60, 200, 60})!!;
{|
ui.layout_set_row()!!;
ui.text_unbounded("ui avg", string::tformat("ui avg: %s\ndraw avg: %s\nTOT: %s", uts.avg, dts.avg, uts.avg+dts.avg))!!;
|};
ui.div_end()!!;
ui.frame_end()!!;
/* End UI Handling */
ui_times.push(clock.mark());
//ui_times.print_stats();
/* Start UI Drawing */
rl::begin_drawing();
// ClearBackground(BLACK);
rl::Color c;
rl::Rectangle r;
for (Cmd* cmd; (cmd = ui.cmd_queue.dequeue() ?? null) != null;) {
switch (cmd.type) {
case ugui::CmdType.CMD_RECT:
c = rl::Color{
.r = cmd.rect.color.r,
.g = cmd.rect.color.g,
.b = cmd.rect.color.b,
.a = cmd.rect.color.a,
};
r = rl::Rectangle{
.x = cmd.rect.rect.x,
.y = cmd.rect.rect.y,
.height = cmd.rect.rect.h,
.width = cmd.rect.rect.w,
};
float rad = cmd.rect.radius;
// for some weird-ass reason the straight forward inverse formula does not work
float roundness = r.width > r.height ? (2.1*rad)/r.height : (2.1*rad)/r.width;
rl::draw_rectangle_rounded(r, roundness, 0, c);
case ugui::CmdType.CMD_UPDATE_ATLAS:
if (cmd.update_atlas.id != font_id) { break; }
//rl::unload_image(font_atlas);
font_atlas.data = cmd.update_atlas.raw_buffer;
font_atlas.width = cmd.update_atlas.width;
font_atlas.height = cmd.update_atlas.height;
font_atlas.mipmaps = 1;
//font_atlas.format = rl::PixelFormat.PIXELFORMAT_UNCOMPRESSED_GRAYSCALE;
font_atlas.format = 1;
if (rl::is_texture_ready(font_texture)) {
rl::unload_texture(font_texture);
}
font_texture = rl::load_texture_from_image(font_atlas);
case ugui::CmdType.CMD_SPRITE:
if (cmd.sprite.texture_id != font_id) { break; }
rl::Rectangle source = {
.x = cmd.sprite.texture_rect.x,
.y = cmd.sprite.texture_rect.y,
.width = cmd.sprite.texture_rect.w,
.height = cmd.sprite.texture_rect.h,
};
rl::Vector2 position = {
.x = cmd.sprite.rect.x,
.y = cmd.sprite.rect.y,
};
rl::begin_shader_mode(font_shader);
rl::draw_texture_rec(font_texture, source, position, rl::WHITE);
rl::end_shader_mode();
case ugui::CmdType.CMD_SCISSOR:
if (cmd.scissor.rect.w == 0 && cmd.scissor.rect.h == 0) {
rl::end_scissor_mode();
} else {
rl::begin_scissor_mode(cmd.scissor.rect.x, cmd.scissor.rect.y, cmd.scissor.rect.w, cmd.scissor.rect.h);
}
default:
io::printfn("Unknown cmd type: %s", cmd.type);
}
}
draw_times.push(clock.mark());
//draw_times.print_stats();
rl::end_drawing();
/* End Drawing */
}
rl::close_window();
ui.free();
return 0;
}
/*
fn void! test_vtree() @test
{
vtree::VTree(<String>) vt;
vt.init(10)!!;
defer vt.free();
assert(vt.size() == 10, "Size is incorrect");
isz ref = vt.add("Ciao Mamma", 0)!!;
String s = vt.get(ref)!!;
assert(s == "Ciao Mamma", "String is incorrect");
isz par = vt.parentof(0)!!;
assert(ref == par, "Not Root");
vt.print();
}
def StrCache = cache::Cache(<int, String, 256>);
fn void! test_cache() @test
{
StrCache cc;
cc.init()!!;
defer cc.free();
String*! r = cc.search(1);
if (catch ex = r) {
if (ex != SearchResult.MISSING) {
return ex?;
}
}
r = cc.get_or_insert(&&"Ciao Mamma", 1)!;
assert(*r!! == "Ciao Mamma", "incorrect string");
}
*/