From b9e91c3119e8aad9443b3c5255af2d3f60633d35 Mon Sep 17 00:00:00 2001 From: Alessandro Mauri Date: Sat, 11 Oct 2025 22:32:00 +0200 Subject: [PATCH] implemented a frame skip request --- lib/ugui.c3l/src/cmd.c3 | 3 +++ lib/ugui.c3l/src/core.c3 | 9 +++++++++ lib/ugui.c3l/src/shapes.c3 | 2 ++ lib/ugui.c3l/src/widgets/div.c3 | 7 +++++++ src/renderer.c3 | 5 +++++ 5 files changed, 26 insertions(+) diff --git a/lib/ugui.c3l/src/cmd.c3 b/lib/ugui.c3l/src/cmd.c3 index 6e47715..5a14b07 100644 --- a/lib/ugui.c3l/src/cmd.c3 +++ b/lib/ugui.c3l/src/cmd.c3 @@ -9,6 +9,7 @@ enum CmdType { CMD_UPDATE_ATLAS, CMD_SPRITE, CMD_SCISSOR, + CMD_REQ_SKIP_FRAME, } // command to draw a rect @@ -107,6 +108,8 @@ fn usz? Cmd.to_format(Cmd* cmd, Formatter *f) @dynamic case CMD_UPDATE_ATLAS: ret += f.print("CmdUpdateAtlas")!; ret += io::struct_to_format(cmd.update_atlas, f, false)!; + case CMD_REQ_SKIP_FRAME: + ret += f.print("Skip Frame Request")!; } ret += f.print("}")!; diff --git a/lib/ugui.c3l/src/core.c3 b/lib/ugui.c3l/src/core.c3 index aafb30b..cf11634 100644 --- a/lib/ugui.c3l/src/core.c3 +++ b/lib/ugui.c3l/src/core.c3 @@ -120,6 +120,8 @@ struct Ctx { Font font; SpriteAtlas sprite_atlas; + bool skip_frame; + bool has_focus; InputData input, current_input; @@ -262,6 +264,8 @@ fn void? Ctx.frame_begin(&ctx) elem.layout.h = @exact(ctx.height); ctx.div_scissor = elem.bounds; + + ctx.skip_frame = false; } fn void? Ctx.frame_end(&ctx) @@ -306,6 +310,11 @@ fn void? Ctx.frame_end(&ctx) ctx.push_update_atlas(&ctx.sprite_atlas.atlas)!; ctx.sprite_atlas.should_update = false; } + + // send skip frame request + if (ctx.skip_frame) { + ctx.cmd_queue.push({.type = CMD_REQ_SKIP_FRAME}); + } // sort the command buffer by the z-index // FIXME: sorting the buffer fucks with scissor commands that have to be kept in place diff --git a/lib/ugui.c3l/src/shapes.c3 b/lib/ugui.c3l/src/shapes.c3 index e57f494..822f259 100644 --- a/lib/ugui.c3l/src/shapes.c3 +++ b/lib/ugui.c3l/src/shapes.c3 @@ -208,6 +208,8 @@ macro Point Point.neg(Point p) @operator_s(-) => {-p.x, -p.y}; macro Point Point.max(Point a, Point b) => {.x = max(a.x, b.x), .y = max(a.y, b.y)}; macro Point Point.min(Point a, Point b) => {.x = min(a.x, b.x), .y = min(a.y, b.y)}; +macro bool Point.equals(Point a, Point b) @operator_s(==) => a.x == b.x && a.y == b.y; + // ---------------------------------------------------------------------------------- // // COLOR // // ---------------------------------------------------------------------------------- // diff --git a/lib/ugui.c3l/src/widgets/div.c3 b/lib/ugui.c3l/src/widgets/div.c3 index a00dd1f..cd74c23 100644 --- a/lib/ugui.c3l/src/widgets/div.c3 +++ b/lib/ugui.c3l/src/widgets/div.c3 @@ -211,6 +211,13 @@ fn bool? Ctx.popup_begin_id(&ctx, .origin.y = pos.y - parent.bounds.y, }; + // if the position is not the one expected then request a frame-skip to not flash appear in the + // wrong position for one frame + if (elem.bounds.position() != pos) { + ctx.skip_frame = true; + return true; + } + ctx.push_rect(elem.bounds.pad(style.margin), elem.z_index, style)!; // update the ctx scissor, it HAS to be after drawing the background diff --git a/src/renderer.c3 b/src/renderer.c3 index 6110220..f2a8f60 100644 --- a/src/renderer.c3 +++ b/src/renderer.c3 @@ -988,6 +988,7 @@ fn void Renderer.render_ugui(&self, CmdQueue* queue) self.start_render_pass("UGUI_PIPELINE"); self.bind_textures_id(self.font_atlas_id, self.sprite_atlas_id); + bool no_draws; uint calls = 0; uint off; while (true) { @@ -997,6 +998,8 @@ fn void Renderer.render_ugui(&self, CmdQueue* queue) break; } switch (cmd.type) { + case CMD_REQ_SKIP_FRAME: + no_draws = true; case CMD_UPDATE_ATLAS: // TODO: verify the correct type CmdUpdateAtlas u = cmd.update_atlas; @@ -1012,6 +1015,8 @@ fn void Renderer.render_ugui(&self, CmdQueue* queue) self.scissor_w = s.w; self.scissor_h = s.h; default: + if (no_draws) break; + self.set_scissor(self.scissor_x, self.scissor_y, self.scissor_w, self.scissor_h); uint count = 1; while (queue.len() != 0 && (queue.get(0).type == CMD_RECT || queue.get(0).type == CMD_SPRITE)) {