From c8c5da4f4a4595fa1cfab3cdeaee4544bd8d1098 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Thu, 25 Jan 2024 11:49:05 -0800 Subject: [PATCH] improve flow around multi-target debugging: prefer one-target-only in default path; only enable command line specified target if present; explicit commands for enabling/disabling targets, as well as mutually-exclusive selection of targets; make default clicking path in UI go through mutually exclusive selection, whereas ctrl+clicks will do multi-target selection --- src/df/core/df_core.c | 109 ++++++++++++++++++--------- src/df/core/df_core.mdesk | 3 + src/df/core/generated/df_core.meta.c | 3 + src/df/core/generated/df_core.meta.h | 3 + src/df/gfx/df_gfx.c | 7 +- src/df/gfx/df_views.c | 15 +++- 6 files changed, 101 insertions(+), 39 deletions(-) diff --git a/src/df/core/df_core.c b/src/df/core/df_core.c index 3d406cb5..e5a2f648 100644 --- a/src/df/core/df_core.c +++ b/src/df/core/df_core.c @@ -7571,46 +7571,63 @@ df_core_begin_frame(Arena *arena, DF_CmdList *cmds, F32 dt) //- rjf: apply targets DF_CfgVal *targets = df_cfg_val_from_string(table, str8_lit("target")); - for(DF_CfgNode *target = targets->first; - target != &df_g_nil_cfg_node; - target = target->next) { - if(target->source == src) + B32 cmd_line_target_present = 0; { - DF_CfgNode *label_cfg = df_cfg_node_child_from_string(target, str8_lit("label"), StringMatchFlag_CaseInsensitive); - DF_CfgNode *exe_cfg = df_cfg_node_child_from_string(target, str8_lit("exe"), StringMatchFlag_CaseInsensitive); - if(exe_cfg == &df_g_nil_cfg_node) + DF_EntityList existing_target_entities = df_query_cached_entity_list_with_kind(DF_EntityKind_Target); + for(DF_EntityNode *n = existing_target_entities.first; n != 0; n = n->next) { - exe_cfg = df_cfg_node_child_from_string(target, str8_lit("name"), StringMatchFlag_CaseInsensitive); + DF_Entity *target = n->entity; + if(target->cfg_src == DF_CfgSrc_CommandLine && target->b32) + { + cmd_line_target_present = 1; + } } - DF_CfgNode *args_cfg = df_cfg_node_child_from_string(target, str8_lit("arguments"), StringMatchFlag_CaseInsensitive); - DF_CfgNode *wdir_cfg = df_cfg_node_child_from_string(target, str8_lit("working_directory"), StringMatchFlag_CaseInsensitive); - DF_CfgNode *entry_cfg = df_cfg_node_child_from_string(target, str8_lit("entry_point"), StringMatchFlag_CaseInsensitive); - DF_CfgNode *active_cfg = df_cfg_node_child_from_string(target, str8_lit("active"), StringMatchFlag_CaseInsensitive); - Vec4F32 hsva = df_hsva_from_cfg_node(target); - U64 is_active_u64 = 0; - try_u64_from_str8_c_rules(active_cfg->first->string, &is_active_u64); - DF_Entity *target__ent = df_entity_alloc(0, df_entity_root(), DF_EntityKind_Target); - DF_Entity *exe__ent = df_entity_alloc(0, target__ent, DF_EntityKind_Executable); - DF_Entity *args__ent = df_entity_alloc(0, target__ent, DF_EntityKind_Arguments); - DF_Entity *path__ent = df_entity_alloc(0, target__ent, DF_EntityKind_ExecutionPath); - DF_Entity *entry__ent = df_entity_alloc(0, target__ent, DF_EntityKind_EntryPointName); - String8 saved_label = label_cfg->first->string; - String8 saved_exe = exe_cfg->first->string; - String8 saved_exe_absolute = path_absolute_dst_from_relative_dst_src(scratch.arena, saved_exe, cfg_folder); - String8 saved_wdir = wdir_cfg->first->string; - String8 saved_wdir_absolute = path_absolute_dst_from_relative_dst_src(scratch.arena, saved_wdir, cfg_folder); - String8 saved_entry_point = entry_cfg->first->string; - df_entity_equip_b32(target__ent, active_cfg != &df_g_nil_cfg_node ? !!is_active_u64 : 1); - df_entity_equip_name(0, target__ent, saved_label); - df_entity_equip_name(0, exe__ent, saved_exe_absolute); - df_entity_equip_name(0, args__ent, args_cfg->first->string); - df_entity_equip_name(0, path__ent, saved_wdir_absolute); - df_entity_equip_name(0, entry__ent, saved_entry_point); - df_entity_equip_cfg_src(target__ent, src); - if(!memory_is_zero(&hsva, sizeof(hsva))) + } + for(DF_CfgNode *target = targets->first; + target != &df_g_nil_cfg_node; + target = target->next) + { + if(target->source == src) { - df_entity_equip_color_hsva(target__ent, hsva); + DF_CfgNode *label_cfg = df_cfg_node_child_from_string(target, str8_lit("label"), StringMatchFlag_CaseInsensitive); + DF_CfgNode *exe_cfg = df_cfg_node_child_from_string(target, str8_lit("exe"), StringMatchFlag_CaseInsensitive); + if(exe_cfg == &df_g_nil_cfg_node) + { + exe_cfg = df_cfg_node_child_from_string(target, str8_lit("name"), StringMatchFlag_CaseInsensitive); + } + DF_CfgNode *args_cfg = df_cfg_node_child_from_string(target, str8_lit("arguments"), StringMatchFlag_CaseInsensitive); + DF_CfgNode *wdir_cfg = df_cfg_node_child_from_string(target, str8_lit("working_directory"), StringMatchFlag_CaseInsensitive); + DF_CfgNode *entry_cfg = df_cfg_node_child_from_string(target, str8_lit("entry_point"), StringMatchFlag_CaseInsensitive); + DF_CfgNode *active_cfg = df_cfg_node_child_from_string(target, str8_lit("active"), StringMatchFlag_CaseInsensitive); + Vec4F32 hsva = df_hsva_from_cfg_node(target); + U64 is_active_u64 = 0; + if(!cmd_line_target_present) + { + try_u64_from_str8_c_rules(active_cfg->first->string, &is_active_u64); + } + DF_Entity *target__ent = df_entity_alloc(0, df_entity_root(), DF_EntityKind_Target); + DF_Entity *exe__ent = df_entity_alloc(0, target__ent, DF_EntityKind_Executable); + DF_Entity *args__ent = df_entity_alloc(0, target__ent, DF_EntityKind_Arguments); + DF_Entity *path__ent = df_entity_alloc(0, target__ent, DF_EntityKind_ExecutionPath); + DF_Entity *entry__ent = df_entity_alloc(0, target__ent, DF_EntityKind_EntryPointName); + String8 saved_label = label_cfg->first->string; + String8 saved_exe = exe_cfg->first->string; + String8 saved_exe_absolute = path_absolute_dst_from_relative_dst_src(scratch.arena, saved_exe, cfg_folder); + String8 saved_wdir = wdir_cfg->first->string; + String8 saved_wdir_absolute = path_absolute_dst_from_relative_dst_src(scratch.arena, saved_wdir, cfg_folder); + String8 saved_entry_point = entry_cfg->first->string; + df_entity_equip_b32(target__ent, active_cfg != &df_g_nil_cfg_node ? !!is_active_u64 : 1); + df_entity_equip_name(0, target__ent, saved_label); + df_entity_equip_name(0, exe__ent, saved_exe_absolute); + df_entity_equip_name(0, args__ent, args_cfg->first->string); + df_entity_equip_name(0, path__ent, saved_wdir_absolute); + df_entity_equip_name(0, entry__ent, saved_entry_point); + df_entity_equip_cfg_src(target__ent, src); + if(!memory_is_zero(&hsva, sizeof(hsva))) + { + df_entity_equip_color_hsva(target__ent, hsva); + } } } } @@ -7971,6 +7988,7 @@ df_core_begin_frame(Arena *arena, DF_CmdList *cmds, F32 dt) //- rjf: general entity operations case DF_CoreCmdKind_EnableEntity: case DF_CoreCmdKind_EnableBreakpoint: + case DF_CoreCmdKind_EnableTarget: { DF_Entity *entity = df_entity_from_handle(params.entity); df_state_delta_history_push_batch(df_state->hist, &entity->generation); @@ -7979,6 +7997,7 @@ df_core_begin_frame(Arena *arena, DF_CmdList *cmds, F32 dt) }break; case DF_CoreCmdKind_DisableEntity: case DF_CoreCmdKind_DisableBreakpoint: + case DF_CoreCmdKind_DisableTarget: { DF_Entity *entity = df_entity_from_handle(params.entity); df_state_delta_history_push_batch(df_state->hist, &entity->generation); @@ -8196,7 +8215,6 @@ df_core_begin_frame(Arena *arena, DF_CmdList *cmds, F32 dt) // rjf: build target df_state_delta_history_push_batch(df_state_delta_history(), 0); DF_Entity *entity = df_entity_alloc(df_state_delta_history(), df_entity_root(), DF_EntityKind_Target); - df_entity_equip_b32(entity, 1); df_entity_equip_cfg_src(entity, DF_CfgSrc_Profile); DF_Entity *exe = df_entity_alloc(df_state_delta_history(), entity, DF_EntityKind_Executable); df_entity_equip_name(df_state_delta_history(), exe, params.file_path); @@ -8211,6 +8229,25 @@ df_core_begin_frame(Arena *arena, DF_CmdList *cmds, F32 dt) p.entity = df_handle_from_entity(entity); df_cmd_params_mark_slot(&p, DF_CmdParamSlot_Entity); df_cmd_list_push(arena, cmds, &p, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_EditTarget)); + df_cmd_list_push(arena, cmds, &p, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_SelectTarget)); + }break; + case DF_CoreCmdKind_SelectTarget: + { + DF_Entity *entity = df_entity_from_handle(params.entity); + if(entity->kind == DF_EntityKind_Target) + { + DF_EntityList all_targets = df_query_cached_entity_list_with_kind(DF_EntityKind_Target); + B32 is_selected = entity->b32; + for(DF_EntityNode *n = all_targets.first; n != 0; n = n->next) + { + DF_Entity *target = n->entity; + df_entity_equip_b32(target, 0); + } + if(!is_selected) + { + df_entity_equip_b32(entity, 1); + } + } }break; //- rjf: ended processes diff --git a/src/df/core/df_core.mdesk b/src/df/core/df_core.mdesk index 9e03e81e..90f0b07c 100644 --- a/src/df/core/df_core.mdesk +++ b/src/df/core/df_core.mdesk @@ -337,6 +337,9 @@ DF_CoreCmdTable:// | | | {AddTarget 0 FilePath Nil 1 0 0 0 0 1 Target "add_target" "Add Target" "Adds a new target." "application,executable,debug" } {RemoveTarget 0 Entity Target 0 0 0 0 0 1 Trash "remove_target" "Remove Target" "Removes an existing target." "delete,remove,target" } {EditTarget 0 Entity Target 0 0 0 0 0 1 Pencil "edit_target" "Edit Target" "Edits an existing target." "" } + {SelectTarget 0 Entity Target 0 0 0 0 0 1 Target "select_target" "Select Target" "Selects a target." "" } + {EnableTarget 0 Entity Target 0 0 0 0 0 1 CheckFilled "enable_target" "Enable Target" "Enables a target, in addition to all targets currently enabled." "" } + {DisableTarget 0 Entity Target 0 0 0 0 0 1 CheckHollow "disable_target" "Disable Target" "Disables a target." "" } //- rjf: ended processes {RetryEndedProcess 1 Entity Process 0 0 0 0 0 0 Null "retry_ended_process" "Retry Ended Process" "Launches a new process with the same options as the passed ended process." "" } diff --git a/src/df/core/generated/df_core.meta.c b/src/df/core/generated/df_core.meta.c index 9529ab7c..b7627334 100644 --- a/src/df/core/generated/df_core.meta.c +++ b/src/df/core/generated/df_core.meta.c @@ -170,6 +170,9 @@ DF_CmdSpecInfo df_g_core_cmd_kind_spec_info_table[] = { str8_lit_comp("add_target"), str8_lit_comp("Adds a new target."), str8_lit_comp("application,executable,debug"), str8_lit_comp("Add Target"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_FilePath, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*1)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_Target}, { str8_lit_comp("remove_target"), str8_lit_comp("Removes an existing target."), str8_lit_comp("delete,remove,target"), str8_lit_comp("Remove Target"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Entity, DF_EntityKind_Target, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_Trash}, { str8_lit_comp("edit_target"), str8_lit_comp("Edits an existing target."), str8_lit_comp(""), str8_lit_comp("Edit Target"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Entity, DF_EntityKind_Target, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_Pencil}, +{ str8_lit_comp("select_target"), str8_lit_comp("Selects a target."), str8_lit_comp(""), str8_lit_comp("Select Target"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Entity, DF_EntityKind_Target, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_Target}, +{ str8_lit_comp("enable_target"), str8_lit_comp("Enables a target, in addition to all targets currently enabled."), str8_lit_comp(""), str8_lit_comp("Enable Target"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Entity, DF_EntityKind_Target, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_CheckFilled}, +{ str8_lit_comp("disable_target"), str8_lit_comp("Disables a target."), str8_lit_comp(""), str8_lit_comp("Disable Target"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Entity, DF_EntityKind_Target, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_CheckHollow}, { str8_lit_comp("retry_ended_process"), str8_lit_comp("Launches a new process with the same options as the passed ended process."), str8_lit_comp(""), str8_lit_comp("Retry Ended Process"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Entity, DF_EntityKind_Process, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null}, { str8_lit_comp("attach"), str8_lit_comp("Attaches to a process that is already running on the local machine."), str8_lit_comp(""), str8_lit_comp("Attach"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_ID, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*1)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_Null}, { str8_lit_comp("register_as_jit_debugger"), str8_lit_comp("Registers the RAD debugger as the just-in-time (JIT) debugger used by the operating system."), str8_lit_comp(""), str8_lit_comp("Register As Just-In-Time (JIT) Debugger"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null}, diff --git a/src/df/core/generated/df_core.meta.h b/src/df/core/generated/df_core.meta.h index e858451b..2779c5ba 100644 --- a/src/df/core/generated/df_core.meta.h +++ b/src/df/core/generated/df_core.meta.h @@ -221,6 +221,9 @@ DF_CoreCmdKind_ToggleWatchPinAtCursor, DF_CoreCmdKind_AddTarget, DF_CoreCmdKind_RemoveTarget, DF_CoreCmdKind_EditTarget, +DF_CoreCmdKind_SelectTarget, +DF_CoreCmdKind_EnableTarget, +DF_CoreCmdKind_DisableTarget, DF_CoreCmdKind_RetryEndedProcess, DF_CoreCmdKind_Attach, DF_CoreCmdKind_RegisterAsJITDebugger, diff --git a/src/df/gfx/df_gfx.c b/src/df/gfx/df_gfx.c index 54ace1a9..adf440eb 100644 --- a/src/df/gfx/df_gfx.c +++ b/src/df/gfx/df_gfx.c @@ -8692,12 +8692,17 @@ df_entity_desc_button(DF_Window *ws, DF_Entity *entity) ui_set_next_background_color(special_color); } } - ui_set_next_hover_cursor(OS_Cursor_HandPoint); if(entity->cfg_src == DF_CfgSrc_CommandLine) { Vec4F32 bg_color = mix_4f32(ui_top_background_color(), df_rgba_from_theme_color(DF_ThemeColor_Highlight0), 0.25f); ui_set_next_background_color(bg_color); } + else if(entity->kind == DF_EntityKind_Target && entity->b32 != 0) + { + Vec4F32 bg_color = mix_4f32(ui_top_background_color(), df_rgba_from_theme_color(DF_ThemeColor_Highlight1), 0.25f); + ui_set_next_background_color(bg_color); + } + ui_set_next_hover_cursor(OS_Cursor_HandPoint); UI_Key key = ui_key_from_stringf(ui_top_parent()->key, "entity_ref_button_%p", entity); UI_Box *box = ui_build_box_from_key(UI_BoxFlag_Clickable| UI_BoxFlag_DrawBorder| diff --git a/src/df/gfx/df_views.c b/src/df/gfx/df_views.c index 78da164c..5956a31f 100644 --- a/src/df/gfx/df_views.c +++ b/src/df/gfx/df_views.c @@ -3216,9 +3216,20 @@ DF_VIEW_UI_FUNCTION_DEF(Targets) // rjf: enabled UI_PrefWidth(ui_em(2.25f, 1)) UI_FocusHot((row_selected && cursor.x == 0) ? UI_FocusKind_On : UI_FocusKind_Off) - if(df_icon_buttonf(target->b32 ? DF_IconKind_CheckFilled : DF_IconKind_CheckHollow, "###ebl_%p", target).clicked) { - df_entity_equip_b32(target, !target->b32); + UI_Signal sig = df_icon_buttonf(target->b32 ? DF_IconKind_CheckFilled : DF_IconKind_CheckHollow, "###ebl_%p", target); + if(sig.clicked && sig.event_flags == 0) + { + DF_CmdParams p = df_cmd_params_from_view(ws, panel, view); + p.entity = df_handle_from_entity(target); + df_push_cmd__root(&p, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_SelectTarget)); + } + else if(sig.clicked && sig.event_flags == OS_EventFlag_Ctrl) + { + DF_CmdParams p = df_cmd_params_from_view(ws, panel, view); + p.entity = df_handle_from_entity(target); + df_push_cmd__root(&p, df_cmd_spec_from_core_cmd_kind(target->b32 ? DF_CoreCmdKind_DisableTarget : DF_CoreCmdKind_EnableTarget)); + } } // rjf: target name