ogl_beamforming

Ultrasound Beamforming Implemented with OpenGL
git clone anongit@rnpnr.xyz:ogl_beamforming.git
Log | Files | Refs | Feed | Submodules | README | LICENSE

Commit: 7138a16a9bb12a7e30953d2faf55619be0060038
Parent: f5b33a0debee11db5bbb9c71bcce29c417d5d3a6
Author: Randy Palamar
Date:   Fri,  7 Aug 2026 06:31:03 -0700

ui: make live control panel launching more user friendly

* if the user opened a live control panel don't launch another
* if the user moves the auto panel don't auto close it

Diffstat:
Mbeamformer_core.c | 36++++++++++++++++++++++++------------
Mbeamformer_core.meta | 1+
Mgenerated/beamformer_core.c | 13++++++++-----
Mui.c | 21++++++++++++++++-----
4 files changed, 49 insertions(+), 22 deletions(-)

diff --git a/beamformer_core.c b/beamformer_core.c @@ -1905,20 +1905,26 @@ beamformer_frame_step(void *memory, BeamformerInput *input) u32 live_imaging_active = atomic_load_u32(&sm->live_imaging_parameters.active); if (live_imaging_active != ctx->live_imaging_active) { if (ctx->live_imaging_active) { - BeamformerUIPanel *parent = ctx->auto_live_control_panel->parent; - beamformer_command(beamformer_command_infos[BeamformerCommandKind_CloseTab].string, .tree_node = (u64)ctx->auto_live_control_panel); - if (parent->child_count == 1) - beamformer_command(beamformer_command_infos[BeamformerCommandKind_CloseTab].string, .tree_node = (u64)parent); - ctx->auto_live_control_panel = 0; + if (ctx->auto_live_control_panel) { + BeamformerUIPanel *parent = ctx->auto_live_control_panel->parent; + beamformer_command(beamformer_command_infos[BeamformerCommandKind_CloseTab].string, .tree_node = (u64)ctx->auto_live_control_panel); + if (parent->child_count == 1) + beamformer_command(beamformer_command_infos[BeamformerCommandKind_CloseTab].string, .tree_node = (u64)parent); + } } else { + if (beamformer_registers()->live_controls) { + beamformer_command(beamformer_command_infos[BeamformerCommandKind_FocusTab].string, + .tree_node = beamformer_registers()->live_controls); + } else { + ctx->auto_live_control_panel = beamformer_ui_push_panel(0, BeamformerPanelKind_LiveImagingControls); + beamformer_command(beamformer_command_infos[BeamformerCommandKind_SplitTree].string, + .tree_node = (u64)ctx->auto_live_control_panel, + .split_axis = Axis2_X, + .split_left_tree = (u64)ui_context->tree, + .split_right_tree = 0, + .drop_target_tree = (u64)ui_context->tree); + } ctx->live_imaging_active_frame = ctx->frame_index; - ctx->auto_live_control_panel = beamformer_ui_push_panel(0, BeamformerPanelKind_LiveImagingControls); - beamformer_command(beamformer_command_infos[BeamformerCommandKind_SplitTree].string, - .tree_node = (u64)ctx->auto_live_control_panel, - .split_axis = Axis2_X, - .split_left_tree = (u64)ui_context->tree, - .split_right_tree = 0, - .drop_target_tree = (u64)ui_context->tree); } ctx->live_imaging_active = live_imaging_active; } @@ -1959,6 +1965,12 @@ beamformer_frame_step(void *memory, BeamformerInput *input) BeamformerUIPanel *group = (BeamformerUIPanel *)beamformer_registers()->drop_target_tree; u64 new_child_index = beamformer_registers()->drop_child_index; beamformer_panel_group_insert_at(group, move, new_child_index); + + if (move->kind == BeamformerPanelKind_LiveImagingControls) { + beamformer_context->base_registers.v.live_controls = (u64)move; + if (move == ctx->auto_live_control_panel) + ctx->auto_live_control_panel = 0; + } }break; case BeamformerCommandKind_OpenTab:{ diff --git a/beamformer_core.meta b/beamformer_core.meta @@ -44,6 +44,7 @@ [U64 frame Frame ] [U64 frame_view FrameView ] + [U64 live_controls LiveControls ] // NOTE(rnp): Panel Movement and Splitting [U64 split_axis SplitAxis ] diff --git a/generated/beamformer_core.c b/generated/beamformer_core.c @@ -22,11 +22,12 @@ typedef enum { BeamformerRegisterSlot_Window = 2, BeamformerRegisterSlot_Frame = 3, BeamformerRegisterSlot_FrameView = 4, - BeamformerRegisterSlot_SplitAxis = 5, - BeamformerRegisterSlot_SplitLeftTree = 6, - BeamformerRegisterSlot_SplitRightTree = 7, - BeamformerRegisterSlot_DropTargetTree = 8, - BeamformerRegisterSlot_DropChildIndex = 9, + BeamformerRegisterSlot_LiveControls = 5, + BeamformerRegisterSlot_SplitAxis = 6, + BeamformerRegisterSlot_SplitLeftTree = 7, + BeamformerRegisterSlot_SplitRightTree = 8, + BeamformerRegisterSlot_DropTargetTree = 9, + BeamformerRegisterSlot_DropChildIndex = 10, BeamformerRegisterSlot_Count, } BeamformerRegisterSlot; @@ -59,6 +60,7 @@ typedef struct { u64 window; u64 frame; u64 frame_view; + u64 live_controls; u64 split_axis; u64 split_left_tree; u64 split_right_tree; @@ -91,6 +93,7 @@ read_only global BeamformerPanelInfo beamformer_panel_infos[] = { .window = beamformer_registers()->window, \ .frame = beamformer_registers()->frame, \ .frame_view = beamformer_registers()->frame_view, \ + .live_controls = beamformer_registers()->live_controls, \ .split_axis = beamformer_registers()->split_axis, \ .split_left_tree = beamformer_registers()->split_left_tree, \ .split_right_tree = beamformer_registers()->split_right_tree, \ diff --git a/ui.c b/ui.c @@ -2,9 +2,6 @@ /* TODO(rnp): * [ ]: track active panel * - when beamformer gets command to open tab it goes to this location by default - * [ ]: track last active live control panel - * - when live imaging starts make this panel the focus - * - if this exists do not auto open a panel * [ ]: word scan for text input * [ ]: when dragging only tab from group close old group on release * - only keep layout when closing tabs @@ -3625,6 +3622,7 @@ ui_build_live_imaging_controls(BeamformerUIPanel *panel) { ui_top_parent()->child_layout_axis = Axis2_Y; ui_top_parent()->semantic_width = ui_px(4.f * UI_NODE_PAD + 200.f, 1.f); + ui_top_parent()->parent->alignment[Axis2_X] = UIAlign_Center; if (popcount_u64(lip->acquisition_kind_enabled_flags) > 1) UIPrefWidth(ui_children_sum(1.f)) @@ -4792,8 +4790,10 @@ ui_layout_nodes(UINode *root) for (UINode *child = node->first_child; !ui_node_is_nil(child); child = child->next_sibling) { for EachElement(node->alignment, axis) { - f32 size_delta = node->computed_size[axis] - child->computed_size[axis]; - child->computed_position[axis] += ui_alignment_correction(node->alignment[axis], size_delta); + UIAlign align = node->alignment[axis]; + f32 size_delta = node->computed_size[axis] - child->computed_size[axis]; + if (size_delta < 0) align = UIAlign_Left; + child->computed_position[axis] += ui_alignment_correction(align, size_delta); } } @@ -4973,6 +4973,14 @@ ui_kill_panel(BeamformerUIPanel *node) SLLStackPush(ui->view_freelist, bv, next); } + if (node->kind == BeamformerPanelKind_LiveImagingControls && (u64)node == beamformer_context->base_registers.v.live_controls) { + beamformer_context->base_registers.v.live_controls = 0; + // TODO(rnp): find first live control panel and update this with it + } + + if (node->kind == BeamformerPanelKind_LiveImagingControls && node == beamformer_context->auto_live_control_panel) + beamformer_context->auto_live_control_panel = 0; + beamformer_ui_panel_unlink(node); if (node->kind == BeamformerPanelKind_TabGroup) { @@ -5032,6 +5040,9 @@ beamformer_ui_push_panel(BeamformerUIPanel *parent, BeamformerPanelKind kind) result->u.frame_view = beamformer_ui_frame_view_new(view_kind); } + if (kind == BeamformerPanelKind_LiveImagingControls) + beamformer_context->base_registers.v.live_controls = (u64)result; + return result; }