Commit: 496fbce8d1966ad4cc434913767a5a3df6fb111d
Parent: 9848525e35a25ff68b6da1157ade4de6e673580e
Author: Randy Palamar
Date: Sat, 9 Aug 2025 12:57:53 -0600
ui/lib: add save file name tag field to live parameters
Diffstat:
4 files changed, 95 insertions(+), 21 deletions(-)
diff --git a/beamformer_parameters.h b/beamformer_parameters.h
@@ -147,7 +147,8 @@ enum {BEAMFORMER_CONSTANTS_LIST};
X(beamform_plane, int32_t, , 1, int, , "/* Plane to Beamform in TPW/VLS/HERCULES */") \
X(f_number, float, , 1, float, , "/* F# (set to 0 to disable) */") \
X(interpolate, uint32_t, , 1, bool, , "/* Perform Cubic Interpolation of RF Samples */") \
- X(coherency_weighting, uint32_t, , 1, bool, , "/* Apply coherency weighting to output data */")
+ X(coherency_weighting, uint32_t, , 1, bool, , "/* Apply coherency weighting to output data */") \
+ X(decimation_rate, uint32_t, , 1, uint, , "/* Number of times to decimate */")
#define BEAMFORMER_PARAMS_HEAD \
X(xdc_transform, float, [16], 16, mat4, , "/* IMPORTANT: column major order */") \
@@ -160,7 +161,6 @@ enum {BEAMFORMER_CONSTANTS_LIST};
X(time_offset, float, , 1, float, , "/* pulse length correction time [s] */")
#define BEAMFORMER_PARAMS_TAIL \
- X(decimation_rate, uint32_t, , 1, uint, , "/* Number of times to decimate */") \
X(readi_group_id, uint32_t, , 1, uint, , "/* Which readi group this data is from */") \
X(readi_group_size, uint32_t, , 1, uint, , "/* Size of readi transmit group */")
@@ -191,16 +191,19 @@ _Static_assert((sizeof(BeamformerParameters) & 15) == 0, "UBO size must be a mul
X(TransmitPower, 1) \
X(TGCControlPoints, 2) \
X(SaveData, 3) \
- X(StopImaging, 4)
+ X(SaveNameTag, 4) \
+ X(StopImaging, 5)
/* NOTE(rnp): if this exceeds 32 you need to fix the flag handling code */
#define BEAMFORMER_LIVE_IMAGING_PARAMETERS_LIST \
- X(active, uint32_t, , 1) \
- X(save_enabled, uint32_t, , 1) \
- X(save_active, uint32_t, , 1) \
- X(transmit_power, float, , 1) \
- X(image_plane_offsets, float, [BeamformerViewPlaneTag_Count], BeamformerViewPlaneTag_Count) \
- X(tgc_control_points, float, [8], 8)
+ X(active, uint32_t, , 1) \
+ X(save_enabled, uint32_t, , 1) \
+ X(save_active, uint32_t, , 1) \
+ X(transmit_power, float, , 1) \
+ X(image_plane_offsets, float, [BeamformerViewPlaneTag_Count], BeamformerViewPlaneTag_Count) \
+ X(tgc_control_points, float, [8], 8) \
+ X(save_name_tag_length, int32_t, , 1) \
+ X(save_name_tag, char, [128], 128)
#define X(name, type, size, ...) type name size;
typedef struct {BEAMFORMER_LIVE_IMAGING_PARAMETERS_LIST} BeamformerLiveImagingParameters;
diff --git a/beamformer_shared_memory.c b/beamformer_shared_memory.c
@@ -1,5 +1,5 @@
/* See LICENSE for license details. */
-#define BEAMFORMER_SHARED_MEMORY_VERSION (12UL)
+#define BEAMFORMER_SHARED_MEMORY_VERSION (13UL)
typedef struct BeamformerFrame BeamformerFrame;
typedef struct ShaderReloadContext ShaderReloadContext;
@@ -41,9 +41,7 @@ typedef struct {
u32 size;
} BeamformerExportContext;
-/* TODO(rnp): remove the None lock */
#define BEAMFORMER_SHARED_MEMORY_LOCKS \
- X(None) \
X(ScratchSpace) \
X(UploadRF) \
X(ExportSync) \
@@ -86,7 +84,7 @@ typedef struct {
} BeamformWorkQueue;
#define BEAMFORMER_SHARED_MEMORY_SIZE (GB(2))
-#define BEAMFORMER_SHARED_MEMORY_MIN_SCRATCH_SIZE (BEAMFORMER_SHARED_MEMORY_SIZE - \
+#define BEAMFORMER_SHARED_MEMORY_MAX_SCRATCH_SIZE (BEAMFORMER_SHARED_MEMORY_SIZE - \
sizeof(BeamformerSharedMemory) - \
sizeof(BeamformerParameterBlock))
diff --git a/helpers/ogl_beamformer_lib.c b/helpers/ogl_beamformer_lib.c
@@ -560,7 +560,7 @@ beamform_data_synchronized(void *data, u32 data_size, i32 output_points[3], f32
b32
beamformer_compute_timings(BeamformerComputeStatsTable *output, i32 timeout_ms)
{
- static_assert(sizeof(*output) <= BEAMFORMER_SHARED_MEMORY_MIN_SCRATCH_SIZE,
+ static_assert(sizeof(*output) <= BEAMFORMER_SHARED_MEMORY_MAX_SCRATCH_SIZE,
"timing table size exceeds scratch space");
b32 result = 0;
diff --git a/ui.c b/ui.c
@@ -1,5 +1,30 @@
/* See LICENSE for license details. */
/* TODO(rnp):
+ * [ ]: refactor: ui kind of needs to be mostly thrown away
+ * - want all drawing to be immediate mode
+ * - only layout information should be retained
+ * - leaf nodes of layout have a kind associated which
+ * instructs the builder code on how to build the view
+ * - ui items (currently called Variables) are stored in a hash
+ * table and are looked up for state information at frame building time
+ * - removed/recycled when last building frame index is less than drawing frame index
+ * - building:
+ * - loop over tiled layout tree and floating layout tree as is currently done
+ * - this will build current frame ui draw tree
+ * - for each view use a stack structure with grouping, similar to how tables are made
+ * - more general though: sub groups contain a draw axis (x or y)
+ * - each ui item gets looked up in the hash table for previous frame drawing info
+ * - this can then be used to construct a "ui comm" which contains relevant info
+ * about how that ui item is being interacted with
+ * - drawing:
+ * - must be separated into layout constraint solving and rendering
+ * - layout constraint solving handles sizing, clipping, etc.
+ * - this will need multiple passes per subgroup to allow for autosizing
+ * - pay attention to the fixed size points in the hierarchy. fixed size
+ * items are complete once their children are complete.
+ * - rendering simply uses the rect/clipping regions produced by layout
+ * to send draw commands
+ * [ ]: bug: resizing live view causes texture to jump around
* [ ]: bug: group at end of parameter listing
* [ ]: refactor: ui should be in its own thread and that thread should only be concerned with the ui
* [ ]: refactor: remove all the excessive measure_texts (cell drawing, hover_interaction in params table)
@@ -76,9 +101,10 @@ typedef struct BeamformerUI BeamformerUI;
typedef struct Variable Variable;
typedef struct {
- u8 buf[64];
+ u8 buf[128];
i32 count;
i32 cursor;
+ b32 numeric;
UIBlinker cursor_blink;
Font *font, *hot_font;
Variable *container;
@@ -159,6 +185,7 @@ typedef enum {
VT_COMPUTE_STATS_VIEW,
VT_COMPUTE_PROGRESS_BAR,
VT_LIVE_CONTROLS_VIEW,
+ VT_LIVE_CONTROLS_STRING,
VT_SCALE_BAR,
VT_UI_BUTTON,
VT_UI_MENU,
@@ -339,8 +366,10 @@ struct BeamformerLiveControlsView {
Variable tgc_control_points[countof(((BeamformerLiveImagingParameters *)0)->tgc_control_points)];
Variable save_button;
Variable stop_button;
+ Variable save_text;
UIBlinker save_button_blink;
u32 hot_field_flag;
+ u32 active_field_flag;
};
typedef enum {
@@ -595,6 +624,11 @@ stream_append_variable(Stream *s, Variable *var)
if (var->cycler.labels) stream_append_s8(s, var->cycler.labels[index]);
else stream_append_u64(s, index);
}break;
+ case VT_LIVE_CONTROLS_STRING:{
+ BeamformerLiveImagingParameters *lip = var->generic;
+ stream_append_s8(s, (s8){.data = (u8 *)lip->save_name_tag, .len = lip->save_name_tag_length});
+ if (lip->save_name_tag_length <= 0) stream_append_s8(s, s8("Tag..."));
+ }break;
InvalidDefaultCase;
}
}
@@ -1390,6 +1424,10 @@ add_live_controls_view(BeamformerUI *ui, Variable *parent, Arena *arena)
VT_CYCLER, ui->small_font);
fill_variable_cycler(&lv->save_button, &lip->save_active, save_labels, countof(save_labels));
+ fill_variable(&lv->save_text, view, s8(""), V_INPUT|V_TEXT|V_LIVE_CONTROL,
+ VT_LIVE_CONTROLS_STRING, ui->small_font);
+ lv->save_text.generic = lip;
+
return result;
}
@@ -2790,14 +2828,13 @@ draw_compute_stats_view(BeamformerUI *ui, Arena arena, Variable *view, Rect r, v
}
function v2
-draw_live_controls_view(BeamformerUI *ui, Variable *var, Rect r, v2 mouse)
+draw_live_controls_view(BeamformerUI *ui, Variable *var, Rect r, v2 mouse, Arena arena)
{
BeamformerSharedMemory *sm = ui->shared_memory.region;
BeamformerLiveImagingParameters *lip = &sm->live_imaging_parameters;
BeamformerLiveControlsView *lv = var->generic;
TextSpec text_spec = {.font = &ui->font, .colour = FG_COLOUR, .flags = TF_LIMITED};
- text_spec.limits.size.w = r.size.w;
v2 slider_size = {{MIN(140.0f, r.size.w), (f32)ui->font.baseSize}};
v2 button_size = {{MIN(r.size.w, slider_size.x + (f32)ui->font.baseSize), (f32)ui->font.baseSize * 1.5f}};
@@ -2806,6 +2843,8 @@ draw_live_controls_view(BeamformerUI *ui, Variable *var, Rect r, v2 mouse)
f32 slider_off = r.pos.x + 0.5f * (r.size.w - slider_size.w);
f32 button_off = r.pos.x + 0.5f * (r.size.w - button_size.w);
+ text_spec.limits.size.w = r.size.w - (text_off - r.pos.x);
+
v2 at = {{text_off, r.pos.y}};
v4 hsv_power_slider = {{0.35f * ease_in_out_cubic(1.0f - lip->transmit_power), 0.65f, 0.65f, 1}};
@@ -2840,10 +2879,24 @@ draw_live_controls_view(BeamformerUI *ui, Variable *var, Rect r, v2 mouse)
v4 border_colour = BORDER_COLOUR;
if (active) border_colour = v4_lerp(BORDER_COLOUR, FOCUSED_COLOUR, ease_in_out_cubic(save_t));
+ at.x = text_off;
+ at.y += draw_text(s8("File Tag:"), at, &text_spec).y;
+ at.x += (f32)text_spec.font->baseSize / 2;
+ text_spec.limits.size.w -= (f32)text_spec.font->baseSize;
+
+ v4 save_text_colour = FG_COLOUR;
+ if (lip->save_name_tag_length <= 0)
+ save_text_colour.a = 0.6f;
+ at.y += draw_variable(ui, arena, &lv->save_text, at, mouse, save_text_colour, text_spec).y;
+ text_spec.limits.size.w += (f32)text_spec.font->baseSize;
+
+ at.x = button_off;
at.y += (f32)ui->font.baseSize * 0.25f;
at.y += draw_fancy_button(ui, &lv->save_button, label, (Rect){.pos = at, .size = button_size},
border_colour, mouse, text_spec).y;
+ if (interaction_is_hot(ui, auto_interaction(r, &lv->save_text)))
+ lv->hot_field_flag = BeamformerLiveImagingDirtyFlags_SaveNameTag;
if (interaction_is_hot(ui, auto_interaction(r, &lv->save_button)))
lv->hot_field_flag = BeamformerLiveImagingDirtyFlags_SaveData;
}
@@ -3060,7 +3113,7 @@ draw_ui_view(BeamformerUI *ui, Variable *ui_view, Rect r, v2 mouse, TextSpec tex
r.pos.y += 0.5f * (r.size.h - view->rect.size.h);
BeamformerSharedMemory *sm = ui->shared_memory.region;
if (sm->live_imaging_parameters.active)
- size = draw_live_controls_view(ui, var, r, mouse);
+ size = draw_live_controls_view(ui, var, r, mouse, ui->arena);
}break;
InvalidDefaultCase;
}
@@ -3254,6 +3307,13 @@ begin_text_input(InputState *is, Rect r, Variable *container, v2 mouse)
is->count = s.widx;
is->container = container;
+ is->numeric = container->view.child->type != VT_LIVE_CONTROLS_STRING;
+ if (container->view.child->type == VT_LIVE_CONTROLS_STRING) {
+ BeamformerLiveImagingParameters *lip = container->view.child->generic;
+ if (lip->save_name_tag_length <= 0)
+ is->count = 0;
+ }
+
/* NOTE: extra offset to help with putting a cursor at idx 0 */
f32 text_half_char_width = 10.0f;
f32 hover_p = CLAMP01((mouse.x - r.pos.x) / r.size.w);
@@ -3272,7 +3332,8 @@ begin_text_input(InputState *is, Rect r, Variable *container, v2 mouse)
function void
end_text_input(InputState *is, Variable *var)
{
- f32 value = (f32)parse_f64((s8){.len = is->count, .data = is->buf});
+ f32 value = 0;
+ if (is->numeric) value = (f32)parse_f64((s8){.len = is->count, .data = is->buf});
switch (var->type) {
case VT_SCALED_F32:{ var->scaled_real32.val = value; }break;
@@ -3282,6 +3343,11 @@ end_text_input(InputState *is, Variable *var)
*bv->store = CLAMP(value / bv->display_scale, bv->limits.x, bv->limits.y);
var->hover_t = 0;
}break;
+ case VT_LIVE_CONTROLS_STRING:{
+ BeamformerLiveImagingParameters *lip = var->generic;
+ mem_copy(lip->save_name_tag, is->buf, (uz)is->count % countof(lip->save_name_tag));
+ lip->save_name_tag_length = is->count % countof(lip->save_name_tag);
+ }break;
InvalidDefaultCase;
}
}
@@ -3301,7 +3367,7 @@ update_text_input(InputState *is, Variable *var)
is->count < countof(is->buf) && key > 0;
key = GetCharPressed())
{
- b32 allow_key = (BETWEEN(key, '0', '9') || (key == '.') ||
+ b32 allow_key = !is->numeric || (BETWEEN(key, '0', '9') || (key == '.') ||
(key == '-' && is->cursor == 0));
if (allow_key) {
mem_move(is->buf + is->cursor + 1,
@@ -3543,6 +3609,7 @@ ui_begin_interact(BeamformerUI *ui, BeamformerInput *input, b32 scroll)
else hot.kind = InteractionKind_Set;
}break;
case VT_BEAMFORMER_VARIABLE:
+ case VT_LIVE_CONTROLS_STRING:
case VT_F32:
case VT_SCALED_F32:
{
@@ -3564,6 +3631,12 @@ ui_begin_interact(BeamformerUI *ui, BeamformerInput *input, b32 scroll)
ui->interaction = hot;
+ if (ui->interaction.var->flags & V_LIVE_CONTROL) {
+ assert(ui->interaction.var->parent->type == VT_LIVE_CONTROLS_VIEW);
+ BeamformerLiveControlsView *lv = ui->interaction.var->parent->generic;
+ lv->active_field_flag = lv->hot_field_flag;
+ }
+
if (ui->interaction.var->flags & V_HIDES_CURSOR) {
HideCursor();
DisableCursor();
@@ -3614,7 +3687,7 @@ ui_live_control_update(BeamformerUI *ui, Variable *controls)
assert(controls->type == VT_LIVE_CONTROLS_VIEW);
BeamformerSharedMemory *sm = ui->shared_memory.region;
BeamformerLiveControlsView *lv = controls->generic;
- atomic_or_u32(&sm->live_imaging_dirty_flags, lv->hot_field_flag);
+ atomic_or_u32(&sm->live_imaging_dirty_flags, lv->active_field_flag);
}
function void