Commit: 4745b839c6ea4cbcbbe5d2c32af65e294c1442b5
Parent: bef621fa14ac73e312ee176bbad54ffb854475f7
Author: Randy Palamar
Date: Tue, 26 Nov 2024 16:44:57 -0700
add ruler display interaction
Diffstat:
5 files changed, 98 insertions(+), 38 deletions(-)
diff --git a/beamformer.h b/beamformer.h
@@ -69,7 +69,7 @@ typedef struct {
Variable active;
u32 hot_state;
u32 state;
- b32 var_changed_last_frame;
+ v2 last_mouse_click_p;
} InteractionState;
typedef struct {
diff --git a/main_generic.c b/main_generic.c
@@ -62,6 +62,8 @@ main(void)
reload_shaders(&ctx, temp_memory);
}
+ input.last_mouse = input.mouse;
+ input.mouse.rl = GetMousePosition();
input.pipe_data_available = os_poll_pipe(data_pipe);
beamformer_frame_step(&ctx, &temp_memory, &input);
diff --git a/ui.c b/ui.c
@@ -143,7 +143,8 @@ do_text_input_listing(s8 prefix, s8 suffix, Variable var, BeamformerUI *ui, Rect
v2 mouse, f32 *hover_t)
{
InputState *is = &ui->text_input_state;
- b32 text_input_active = ui->interaction.active.store == var.store;
+ b32 text_input_active = (ui->interaction.state == IS_TEXT) &&
+ (var.store == ui->interaction.active.store);
Arena arena = ui->arena_for_frame;
Stream buf = arena_stream(&arena);
@@ -678,6 +679,8 @@ ui_end_interact(BeamformerCtx *ctx, BeamformerUI *ui)
}
} break;
case IS_DISPLAY:
+ is->last_mouse_click_p = (v2){0};
+ /* FALLTHROUGH */
case IS_SCROLL: {
f32 delta = GetMouseWheelMove() * is->active.scroll_scale;
switch (is->active.type) {
@@ -714,33 +717,29 @@ ui_end_interact(BeamformerCtx *ctx, BeamformerUI *ui)
static void
ui_interact(BeamformerCtx *ctx, BeamformerInput *input)
{
- BeamformerUI *ui = ctx->ui;
- InteractionState *is = &ui->interaction;
- if (is->state != IS_NONE) {
- if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) {
+ BeamformerUI *ui = ctx->ui;
+ InteractionState *is = &ui->interaction;
+ b32 mouse_left_pressed = IsMouseButtonPressed(MOUSE_BUTTON_LEFT);
+ b32 wheel_moved = GetMouseWheelMove();
+ if (mouse_left_pressed || wheel_moved) {
+ if (is->state != IS_NONE)
ui_end_interact(ctx, ui);
- ui_begin_interact(ui, input, 0);
- }
+ ui_begin_interact(ui, input, wheel_moved);
+ }
- if (GetMouseWheelMove()) {
- ui_end_interact(ctx, ui);
- ui_begin_interact(ui, input, 1);
- }
+ if (IsKeyPressed(KEY_ENTER) && is->state == IS_TEXT)
+ ui_end_interact(ctx, ui);
- if (IsKeyPressed(KEY_ENTER))
+ switch (is->state) {
+ case IS_DISPLAY: {
+ b32 should_end = wheel_moved || IsMouseButtonPressed(MOUSE_BUTTON_RIGHT) ||
+ (is->active.store != is->hot.store);
+ if (should_end) {
ui_end_interact(ctx, ui);
-
- } else {
- if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) {
- ui_begin_interact(ui, input, 0);
+ } else if (mouse_left_pressed) {
+ is->last_mouse_click_p = input->mouse;
}
- if (GetMouseWheelMove()) {
- ui_begin_interact(ui, input, 1);
- }
- }
-
- switch (is->state) {
- case IS_DISPLAY: ui_end_interact(ctx, ui); break;
+ } break;
case IS_SCROLL: ui_end_interact(ctx, ui); break;
case IS_SET: ui_end_interact(ctx, ui); break;
case IS_TEXT: update_text_input(&ui->text_input_state); break;
@@ -796,18 +795,20 @@ draw_ui(BeamformerCtx *ctx, BeamformerInput *input)
.y = bp->output_max_coordinate.z - bp->output_min_coordinate.z,
};
- v2 mouse = { .rl = GetMousePosition() };
+ v2 mouse = input->mouse;
Rect wr = {.size = {.w = (f32)ctx->window_size.w, .h = (f32)ctx->window_size.h}};
Rect lr = wr, rr = wr;
lr.size.w = INFO_COLUMN_WIDTH;
rr.size.w = wr.size.w - lr.size.w;
rr.pos.x = lr.pos.x + lr.size.w;
+ Rect vr = INVERTED_INFINITY_RECT;
if (output_dim.x > 1e-6 && output_dim.y > 1e-6) {
Stream buf = stream_alloc(&ui->arena_for_frame, 64);
stream_append_f64(&buf, -188.8f, 10);
stream_append_s8(&buf, s8(" mm"));
v2 txt_s = measure_text(ui->small_font, stream_to_s8(&buf));
+ buf.widx = 0;
rr.pos.x += 0.02 * rr.size.w;
rr.pos.y += 0.02 * rr.size.h;
@@ -817,7 +818,7 @@ draw_ui(BeamformerCtx *ctx, BeamformerInput *input)
f32 tick_len = 20;
f32 pad = 1.2 * txt_s.x + tick_len;
- Rect vr = rr;
+ vr = rr;
vr.pos.x += 0.5 * txt_s.y;
vr.pos.y += 0.5 * txt_s.y;
vr.size.h = rr.size.h - pad;
@@ -836,17 +837,6 @@ draw_ui(BeamformerCtx *ctx, BeamformerInput *input)
NPatchInfo tex_np = { tex_r, 0, 0, 0, 0, NPATCH_NINE_PATCH };
DrawTextureNPatch(*output, tex_np, vr.rl, (Vector2){0}, 0, WHITE);
- if (CheckCollisionPointRec(mouse.rl, vr.rl)) {
- InteractionState *is = &ui->interaction;
- is->hot_state = IS_DISPLAY;
- is->hot.store = &ctx->fsctx.threshold;
- is->hot.type = VT_F32;
- is->hot.f32_limits = (v2){.y = 240};
- is->hot.flags = V_GEN_MIPMAPS;
- is->hot.display_scale = 1;
- is->hot.scroll_scale = 1;
- }
-
static f32 txt_colour_t[2];
for (u32 i = 0; i < 2; i++) {
u32 line_count = vr.size.E[i] / (1.5 * txt_s.h);
@@ -906,5 +896,39 @@ draw_ui(BeamformerCtx *ctx, BeamformerInput *input)
draw_settings_ui(ctx, lr, mouse);
draw_debug_overlay(ctx, ui->arena_for_frame, lr);
+
+ if (CheckCollisionPointRec(mouse.rl, vr.rl)) {
+ InteractionState *is = &ui->interaction;
+ is->hot_state = IS_DISPLAY;
+ is->hot.store = &ctx->fsctx.threshold;
+ is->hot.type = VT_F32;
+ is->hot.f32_limits = (v2){.y = 240};
+ is->hot.flags = V_GEN_MIPMAPS;
+ is->hot.display_scale = 1;
+ is->hot.scroll_scale = 1;
+
+ /* NOTE: check and draw Ruler */
+ if (CheckCollisionPointRec(is->last_mouse_click_p.rl, vr.rl)) {
+ Stream buf = arena_stream(&ui->arena_for_frame);
+
+ Color colour = colour_from_normalized(HOVERED_COLOUR);
+ DrawCircleV(is->last_mouse_click_p.rl, 3, colour);
+ DrawLineEx(mouse.rl, is->last_mouse_click_p.rl, 2, colour);
+ v2 pixels_to_mm = output_dim;
+ pixels_to_mm.x /= vr.size.x * 1e-3;
+ pixels_to_mm.y /= vr.size.y * 1e-3;
+
+ v2 pixel_delta = sub_v2(is->last_mouse_click_p, mouse);
+ v2 mm_delta = mul_v2(pixels_to_mm, pixel_delta);
+
+ stream_append_f64(&buf, magnitude_v2(mm_delta), 100);
+ stream_append_s8(&buf, s8(" mm"));
+ v2 txt_p = is->last_mouse_click_p;
+ v2 txt_s = measure_text(ui->small_font, stream_to_s8(&buf));
+ if (pixel_delta.y < 0) txt_p.y -= txt_s.y;
+ if (pixel_delta.x < 0) txt_p.x -= txt_s.x;
+ draw_text(ui->small_font, stream_to_s8(&buf), txt_p, 0, colour);
+ }
+ }
EndDrawing();
}
diff --git a/util.c b/util.c
@@ -325,6 +325,37 @@ normalize_v3(v3 a)
return result;
}
+static v2
+sub_v2(v2 a, v2 b)
+{
+ v2 result = {
+ .x = a.x - b.x,
+ .y = a.y - b.y,
+ };
+ return result;
+}
+
+static v2
+mul_v2(v2 a, v2 b)
+{
+ v2 result = {
+ .x = a.x * b.x,
+ .y = a.y * b.y,
+ };
+ return result;
+}
+
+
+static f32
+magnitude_v2(v2 a)
+{
+ v4 result;
+ __m128 av = _mm_set_ps(0, 0, a.x, a.y);
+ av = _mm_mul_ps(av, av);
+ _mm_store_ps(result.E, _mm_sqrt_ps(_mm_hadd_ps(av, av)));
+ return result.x;
+}
+
static f64
parse_f64(s8 s)
{
diff --git a/util.h b/util.h
@@ -51,7 +51,8 @@
#define MEGABYTE (1024ULL * 1024ULL)
#define GIGABYTE (1024ULL * 1024ULL * 1024ULL)
-#define U32_MAX (0xFFFFFFFFUL)
+#define U32_MAX (0xFFFFFFFFUL)
+#define F32_INFINITY (__builtin_inff())
typedef char c8;
typedef uint8_t u8;
@@ -143,6 +144,8 @@ typedef union {
struct { v2 pos, size; };
Rectangle rl;
} Rect;
+#define INVERTED_INFINITY_RECT (Rect){.pos = {.x = -F32_INFINITY, .y = -F32_INFINITY}, \
+ .size = {.x = -F32_INFINITY, .y = -F32_INFINITY}}
typedef struct {
iptr file;