diff --git a/project.4coder b/project.4coder index 360ba491..0fca26cd 100644 --- a/project.4coder +++ b/project.4coder @@ -49,7 +49,7 @@ commands = // .f1 = { .win = "raddbg_stable --ipc kill_all && build raddbg", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, // .f1 = { .win = "raddbg_stable --ipc kill_all && build raddbg debug telemetry", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, // .f1 = { .win = "raddbg_stable --ipc kill_all && build radbin", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, - .f1 = { .win = "raddbg_stable --ipc kill_all && build raddbg telemetry debug", .linux = "./build.sh raddbg debug meta", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, + .f1 = { .win = "raddbg_stable --ipc kill_all && build raddbg raddbg_server telemetry debug", .linux = "./build.sh raddbg debug meta", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, //- rjf: [raddbg wsl] // .f1 = { .win = "wsl ./build.sh raddbg", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, diff --git a/project.raddbg b/project.raddbg index 08f38bb0..ef217025 100755 --- a/project.raddbg +++ b/project.raddbg @@ -10,6 +10,13 @@ target: enabled: 1 } target: +{ + executable: "build/raddbg_server.exe" + working_directory: build + debug_subprocesses: 1 + arguments: "mule_main.exe" +} +target: { executable: "build/metagen.exe" working_directory: build diff --git a/src/base/base_entry_point.c b/src/base/base_entry_point.c index 169f2573..35c4ee10 100644 --- a/src/base/base_entry_point.c +++ b/src/base/base_entry_point.c @@ -82,7 +82,7 @@ main_thread_base_entry_point(int arguments_count, char **arguments) #if defined(DBG_INFO_H) && !defined(DI_INIT_MANUAL) di_init(&cmdline); #endif -#if defined(DEMON_CORE_H) && !defined(DMN_INIT_MANUAL) +#if defined(DEMON_H) && !defined(DMN_INIT_MANUAL) dmn_init(); #endif #if defined(DBG_ENGINE_CORE_H) && !defined(D_INIT_MANUAL) diff --git a/src/config/config_panels.c b/src/config/config_panels.c index 3746fad0..45396a1c 100644 --- a/src/config/config_panels.c +++ b/src/config/config_panels.c @@ -7,7 +7,7 @@ cfg_window_from_cfg(CFG_Node *cfg) CFG_Node *result = &cfg_nil_node; for(CFG_Node *c = cfg; c != &cfg_nil_node; c = c->parent) { - if(c->parent->parent == cfg_node_root() && str8_match(c->string, str8_lit("window"), 0)) + if(c->parent->parent == cfg_node_root() && str8_match(c->string, s("window"), 0)) { result = c; break; @@ -21,56 +21,69 @@ cfg_panel_tree_from_cfg(Arena *arena, CFG_Node *cfg_root) { Temp scratch = scratch_begin(&arena, 1); CFG_Node *wcfg = cfg_window_from_cfg(cfg_root); - CFG_Node *src_root = cfg_node_child_from_string(wcfg, str8_lit("panels")); + CFG_Node *src_root = cfg_node_child_from_string(wcfg, s("panels")); CFG_PanelNode *dst_root = &cfg_nil_panel_node; CFG_PanelNode *dst_focused = &cfg_nil_panel_node; + CFG_PanelNode *dst_zoom_root = &cfg_nil_panel_node; { - Axis2 active_split_axis = cfg_node_child_from_string(wcfg, str8_lit("split_x")) != &cfg_nil_node ? Axis2_X : Axis2_Y; + Axis2 active_split_axis = cfg_node_child_from_string(wcfg, s("split_x")) != &cfg_nil_node ? Axis2_X : Axis2_Y; CFG_NodeRec rec = {0}; CFG_PanelNode *dst_active_parent = &cfg_nil_panel_node; for(CFG_Node *src = src_root; src != &cfg_nil_node; src = rec.next) { - // rjf: build a panel node - CFG_PanelNode *dst = push_array(arena, CFG_PanelNode, 1); - MemoryCopyStruct(dst, &cfg_nil_panel_node); - dst->parent = dst_active_parent; - if(dst_active_parent != &cfg_nil_panel_node) - { - DLLPushBack_NPZ(&cfg_nil_panel_node, dst_active_parent->first, dst_active_parent->last, dst, next, prev); - dst_active_parent->child_count += 1; - } - if(dst_root == &cfg_nil_panel_node) - { - dst_root = dst; - } + // rjf: unpack this config string + MD_TokenizeResult tokenize = md_tokenize_from_text(scratch.arena, src->string); - // rjf: extract cfg info + // rjf: build a panel node if this is a child panel + CFG_PanelNode *dst = &cfg_nil_panel_node; B32 panel_has_children = 0; - dst->cfg = src; - dst->pct_of_parent = (src == src_root ? 1.f : (F32)f64_from_str8(src->string)); - dst->tab_side = (cfg_node_child_from_string(src, str8_lit("tabs_on_bottom")) != &cfg_nil_node ? Side_Max : Side_Min); - dst->split_axis = active_split_axis; - for(CFG_Node *src_child = src->first; src_child != &cfg_nil_node; src_child = src_child->next) + if(src == src_root || (tokenize.tokens.count == 1 && tokenize.tokens.v[0].flags & MD_TokenFlag_Numeric)) { - MD_TokenizeResult tokenize = md_tokenize_from_text(scratch.arena, src_child->string); - if(tokenize.tokens.count == 1 && tokenize.tokens.v[0].flags & MD_TokenFlag_Numeric) + // rjf: allocate + dst = push_array(arena, CFG_PanelNode, 1); + MemoryCopyStruct(dst, &cfg_nil_panel_node); + dst->parent = dst_active_parent; + if(dst_active_parent != &cfg_nil_panel_node) { - panel_has_children = 1; + DLLPushBack_NPZ(&cfg_nil_panel_node, dst_active_parent->first, dst_active_parent->last, dst, next, prev); + dst_active_parent->child_count += 1; } - else if(str8_match(src_child->string, str8_lit("tabs_on_bottom"), 0)) + if(dst_root == &cfg_nil_panel_node) { - // NOTE(rjf): skip - this is a panel option. + dst_root = dst; } - else if(str8_match(src_child->string, str8_lit("selected"), 0)) + + // rjf: extract cfg info + dst->cfg = src; + dst->pct_of_parent = (src == src_root ? 1.f : (F32)f64_from_str8(src->string)); + dst->tab_side = (cfg_node_child_from_string(src, s("tabs_on_bottom")) != &cfg_nil_node ? Side_Max : Side_Min); + dst->split_axis = active_split_axis; + for(CFG_Node *src_child = src->first; src_child != &cfg_nil_node; src_child = src_child->next) { - dst_focused = dst; - } - else if(tokenize.tokens.count == 1 && tokenize.tokens.v[0].flags & MD_TokenFlag_Identifier) - { - cfg_node_ptr_list_push(arena, &dst->tabs, src_child); - if(cfg_node_child_from_string(src_child, str8_lit("selected")) != &cfg_nil_node) + MD_TokenizeResult tokenize = md_tokenize_from_text(scratch.arena, src_child->string); + if(tokenize.tokens.count == 1 && tokenize.tokens.v[0].flags & MD_TokenFlag_Numeric) { - dst->selected_tab = src_child; + panel_has_children = 1; + } + if(str8_match(src_child->string, s("tabs_on_bottom"), 0)) + { + // NOTE(rjf): skip - this is a panel option. + } + else if(str8_match(src_child->string, s("selected"), 0)) + { + dst_focused = dst; + } + else if(str8_match(src_child->string, s("zoom_root"), 0)) + { + dst_zoom_root = dst; + } + else if(tokenize.tokens.count == 1 && tokenize.tokens.v[0].flags & MD_TokenFlag_Identifier) + { + cfg_node_ptr_list_push(arena, &dst->tabs, src_child); + if(cfg_node_child_from_string(src_child, s("selected")) != &cfg_nil_node) + { + dst->selected_tab = src_child; + } } } } @@ -103,7 +116,7 @@ cfg_panel_tree_from_cfg(Arena *arena, CFG_Node *cfg_root) } } scratch_end(scratch); - CFG_PanelTree tree = {dst_root, dst_focused}; + CFG_PanelTree tree = {dst_root, dst_focused, dst_zoom_root}; return tree; } @@ -179,7 +192,7 @@ cfg_target_rect_from_panel_node(Rng2F32 root_rect, CFG_PanelNode *root, CFG_Pane // rjf: count ancestors U64 ancestor_count = 0; - for(CFG_PanelNode *p = panel->parent; p != &cfg_nil_panel_node; p = p->parent) + for(CFG_PanelNode *p = panel->parent; p != root->parent; p = p->parent) { ancestor_count += 1; } @@ -188,7 +201,7 @@ cfg_target_rect_from_panel_node(Rng2F32 root_rect, CFG_PanelNode *root, CFG_Pane CFG_PanelNode **ancestors = push_array(scratch.arena, CFG_PanelNode *, ancestor_count); { U64 ancestor_idx = 0; - for(CFG_PanelNode *p = panel->parent; p != &cfg_nil_panel_node; p = p->parent) + for(CFG_PanelNode *p = panel->parent; p != root->parent; p = p->parent) { ancestors[ancestor_idx] = p; ancestor_idx += 1; @@ -203,7 +216,7 @@ cfg_target_rect_from_panel_node(Rng2F32 root_rect, CFG_PanelNode *root, CFG_Pane { CFG_PanelNode *ancestor = ancestors[ancestor_idx]; CFG_PanelNode *parent = ancestor->parent; - if(parent != &cfg_nil_panel_node) + if(parent != root->parent) { parent_rect = cfg_target_rect_from_panel_node_child(parent_rect, parent, ancestor); } diff --git a/src/config/config_panels.h b/src/config/config_panels.h index 5733ccf8..a2f0c7d6 100644 --- a/src/config/config_panels.h +++ b/src/config/config_panels.h @@ -33,6 +33,7 @@ struct CFG_PanelTree { CFG_PanelNode *root; CFG_PanelNode *focused; + CFG_PanelNode *zoom_root; }; typedef struct CFG_PanelNodeRec CFG_PanelNodeRec; diff --git a/src/dbg_engine/dbg_engine_ctrl.c b/src/dbg_engine/dbg_engine_ctrl.c index e8f50689..81a2703a 100644 --- a/src/dbg_engine/dbg_engine_ctrl.c +++ b/src/dbg_engine/dbg_engine_ctrl.c @@ -3830,21 +3830,38 @@ d_ctrl_thread__open_remote_server(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg) SOCK_Endpoint endpoint = sock_endpoint_from_string(msg->path); //- rjf: handshake & get state + B32 good_handshake = 1; { Temp scratch = scratch_begin(0, 0); - DS_Msg msg = {0}; + + // rjf: send handshake packet { - msg.kind = DS_MsgKind_Handshake; - msg.msg_id = 1; + DS_Msg server_msg = {0}; + { + server_msg.kind = DS_MsgKind_Handshake; + server_msg.msg_id = 1; + } + String8 send_packet = ds_packet_from_msg(scratch.arena, &server_msg); + sock_send(d_ctrl_state->sock_session, SOCK_Protocol_TCP, endpoint, send_packet, max_U64); } - String8 msg_raw = ds_packet_from_msg(scratch.arena, &msg); - DS_PacketHeader header = + + // rjf: receive state packet(s) { - .magic = DS_PACKET_MAGIC, - .kind = DS_PacketKind_Msg, - .version = DS_PACKET_VERSION, - .payload_size = msg_raw.size, - }; + SOCK_Protocol recv_protocol = SOCK_Protocol_TCP; + SOCK_Endpoint recv_endpoint = {0}; + String8 recv_packet = {0}; + sock_recv(scratch.arena, d_ctrl_state->sock_session, &recv_protocol, &recv_endpoint, &recv_packet, now_time_us()+10000000); + if(recv_packet.size == 0) + { + good_handshake = 0; + } + } + + // rjf: report failure + if(!good_handshake) + { + log_user_errorf("Couldn't successfully connect to server at %S (%S).", sock_string_from_endpoint(scratch.arena, endpoint), msg->path); + } scratch_end(scratch); } diff --git a/src/dbg_server/dbg_server.c b/src/dbg_server/dbg_server.c index a6250862..d2960b0b 100644 --- a/src/dbg_server/dbg_server.c +++ b/src/dbg_server/dbg_server.c @@ -40,6 +40,7 @@ ds_msg_from_packet(Arena *arena, String8 data) String8 string = {0}; off += str8_deserial_read_struct(payload, off, &string.size); string = str8_substr(payload, r1u64(off, off+string.size)); + off += string.size; str8_list_push(arena, &msg.command_line, string); } } @@ -49,6 +50,7 @@ ds_msg_from_packet(Arena *arena, String8 data) String8 string = {0}; off += str8_deserial_read_struct(payload, off, &string.size); string = str8_substr(payload, r1u64(off, off+string.size)); + off += string.size; msg.path = string; } @@ -61,6 +63,7 @@ ds_msg_from_packet(Arena *arena, String8 data) String8 string = {0}; off += str8_deserial_read_struct(payload, off, &string.size); string = str8_substr(payload, r1u64(off, off+string.size)); + off += string.size; str8_list_push(arena, &msg.env, string); } } diff --git a/src/dbg_server/dbg_server.h b/src/dbg_server/dbg_server.h index 1c929482..58583463 100644 --- a/src/dbg_server/dbg_server.h +++ b/src/dbg_server/dbg_server.h @@ -131,6 +131,6 @@ internal String8 ds_packet_from_msg(Arena *arena, DS_Msg *msg); internal DS_Response ds_response_from_packet(Arena *arena, String8 data); internal String8 ds_packet_from_response(Arena *arena, DS_Response *response); internal DMN_EventList ds_dmn_events_from_packet(Arena *arena, String8 data); -internal String8 ds_serialized_from_dmn_events(Arena *arena, DMN_EventList evts); +internal String8 ds_packet_from_dmn_events(Arena *arena, DMN_EventList evts); #endif // DBG_SERVER_H diff --git a/src/raddbg/generated/raddbg.meta.c b/src/raddbg/generated/raddbg.meta.c index 4ccc3127..7e57eff5 100644 --- a/src/raddbg/generated/raddbg.meta.c +++ b/src/raddbg/generated/raddbg.meta.c @@ -62,7 +62,7 @@ str8_lit_comp(""), str8_lit_comp(""), }; -RD_VocabInfo rd_vocab_info_table[375] = +RD_VocabInfo rd_vocab_info_table[379] = { {str8_lit_comp("type_view"), str8_lit_comp("type_views"), str8_lit_comp("Type View"), str8_lit_comp("Type Views"), RD_IconKind_Binoculars}, {str8_lit_comp("file_path_map"), str8_lit_comp("file_path_maps"), str8_lit_comp("File Path Map"), str8_lit_comp("File Path Maps"), RD_IconKind_FileOutline}, @@ -254,11 +254,15 @@ RD_VocabInfo rd_vocab_info_table[375] = {str8_lit_comp("rotate_panel_columns"), str8_lit_comp(""), str8_lit_comp("Rotate Panel Columns"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("next_panel"), str8_lit_comp(""), str8_lit_comp("Focus Next Panel"), str8_lit_comp(""), RD_IconKind_RightArrow}, {str8_lit_comp("prev_panel"), str8_lit_comp(""), str8_lit_comp("Focus Previous Panel"), str8_lit_comp(""), RD_IconKind_LeftArrow}, +{str8_lit_comp("parent_panel"), str8_lit_comp(""), str8_lit_comp("Focus Parent Panel"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("focus_panel"), str8_lit_comp(""), str8_lit_comp("Focus Panel"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("focus_panel_right"), str8_lit_comp(""), str8_lit_comp("Focus Panel Right"), str8_lit_comp(""), RD_IconKind_RightArrow}, {str8_lit_comp("focus_panel_left"), str8_lit_comp(""), str8_lit_comp("Focus Panel Left"), str8_lit_comp(""), RD_IconKind_LeftArrow}, {str8_lit_comp("focus_panel_up"), str8_lit_comp(""), str8_lit_comp("Focus Panel Up"), str8_lit_comp(""), RD_IconKind_UpArrow}, {str8_lit_comp("focus_panel_down"), str8_lit_comp(""), str8_lit_comp("Focus Panel Down"), str8_lit_comp(""), RD_IconKind_DownArrow}, +{str8_lit_comp("zoom_panel"), str8_lit_comp(""), str8_lit_comp("Zoom Panel"), str8_lit_comp(""), RD_IconKind_Window}, +{str8_lit_comp("unzoom_panel"), str8_lit_comp(""), str8_lit_comp("Unzoom Panel"), str8_lit_comp(""), RD_IconKind_Window}, +{str8_lit_comp("toggle_zoom_panel"), str8_lit_comp(""), str8_lit_comp("Toggle Panel Zoom"), str8_lit_comp(""), RD_IconKind_Window}, {str8_lit_comp("undo"), str8_lit_comp(""), str8_lit_comp("Undo"), str8_lit_comp(""), RD_IconKind_Undo}, {str8_lit_comp("redo"), str8_lit_comp(""), str8_lit_comp("Redo"), str8_lit_comp(""), RD_IconKind_Redo}, {str8_lit_comp("go_back"), str8_lit_comp(""), str8_lit_comp("Go Back"), str8_lit_comp(""), RD_IconKind_LeftArrow}, @@ -471,7 +475,7 @@ RD_NameSchemaInfo rd_name_schema_info_table[39] = {str8_lit_comp("color"), 1, str8_lit_comp("@inherit(tab) x:\n{\n @display_name(\"Value\") @description(\"An expression to describe the value or location of the color.\")\n 'expression': expr_string,\n}\n")}, {str8_lit_comp("geo3d"), 1, str8_lit_comp("@inherit(tab) x:\n{\n @display_name(\"Expression\") @description(\"An expression to describe the base address of the index buffer.\")\n 'expression': expr_string,\n 'count': expr_string,\n 'vtx': expr_string,\n 'vtx_size': expr_string,\n 'yaw': @range[0, 1] f32,\n 'pitch': @range[-0.5, 0] f32,\n 'zoom': @range[0, 100] f32,\n}\n")}, {str8_lit_comp("getting_started"), 0, str8_lit_comp("@inherit(tab) x:\n{\n}\n")}, -{str8_lit_comp("target"), 0, str8_lit_comp("@row_commands(@cmd_line save_cfg_to_project, enable_cfg, launch_and_run, launch_and_step_into, duplicate_cfg, remove_cfg)\n@collection_commands(add_target)\nx:\n{\n 'label': code_string,\n 'executable': path,\n 'arguments': string,\n 'working_directory': @folder path,\n 'entry_point': expr_string,\n @default(\"output\") 'output_label': code_string,\n 'stdout_path': @can_not_exist @no_relativize path,\n 'stderr_path': @can_not_exist @no_relativize path,\n 'stdin_path': @can_not_exist @no_relativize path,\n 'environment': set,\n 'debug_subprocesses': bool,\n @no_revert @no_expand @default(0) 'enabled': bool,\n}\n")}, +{str8_lit_comp("target"), 0, str8_lit_comp("@row_commands(@cmd_line save_cfg_to_project, enable_cfg, launch_and_run, launch_and_step_into, duplicate_cfg, remove_cfg)\n@collection_commands(add_target)\nx:\n{\n 'label': code_string,\n 'executable': path,\n 'arguments': string,\n 'working_directory': @folder path,\n 'entry_point': expr_string,\n @default(\"output\") 'output_label': code_string,\n 'stdout_path': @can_not_exist @no_relativize path,\n 'stderr_path': @can_not_exist @no_relativize path,\n 'stdin_path': @can_not_exist @no_relativize path,\n 'environment': set,\n 'debug_subprocesses': bool,\n @display_name('Remote')\n 'remote': bool,\n @expand_if(\"$.remote\") @display_name('Deploy')\n 'deploy': bool,\n @expand_if(\"$.remote\") @display_name('Address')\n 'address': string,\n @no_revert @no_expand @default(0) 'enabled': bool,\n}\n")}, {str8_lit_comp("breakpoint"), 0, str8_lit_comp("@row_commands(enable_cfg, duplicate_cfg, remove_cfg)\n@collection_commands(toggle_breakpoint, add_breakpoint, add_address_breakpoint, add_function_breakpoint, clear_breakpoints)\nx:\n{\n 'label': code_string,\n 'condition': expr_string,\n 'source_location': path_pt,\n 'address_location': expr_string,\n 'hit_count': u64,\n 'address_range_size': @or(0, 1, 2, 4, 8) u64,\n 'break_on_write': bool,\n 'break_on_read': bool,\n 'break_on_execute': bool,\n @display_name(\"Break Selected Thread Only\") 'break_selected_thread_only': bool,\n @no_revert @no_expand @default(1) 'enabled': bool,\n}\n")}, {str8_lit_comp("watch_pin"), 0, str8_lit_comp("@row_commands(duplicate_cfg, remove_cfg)\n@collection_commands(add_watch_pin, toggle_watch_pin)\nx:\n{\n 'expression': expr_string,\n 'source_location': path_pt,\n 'address_location': expr_string,\n}\n")}, {str8_lit_comp("debug_info"), 0, str8_lit_comp("@row_commands(enable_cfg, duplicate_cfg, remove_cfg)\n@collection_commands(load_debug_info)\nx:\n{\n 'path': @no_relativize path,\n @no_revert @no_expand @default(1) 'enabled': bool,\n @query 'guid': string,\n}\n")}, @@ -604,7 +608,7 @@ Rng1U64 rd_reg_slot_range_table[56] = {OffsetOf(RD_Regs, wm_event), OffsetOf(RD_Regs, wm_event) + sizeof(WM_Event *)}, }; -RD_CmdKindInfo rd_cmd_kind_info_table[261] = +RD_CmdKindInfo rd_cmd_kind_info_table[265] = { {0}, { str8_lit_comp("launch_and_run"), str8_lit_comp("Starts debugging a new instance of a target, then runs."), str8_lit_comp("launch,start,run,target"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_Cfg, str8_lit_comp("query:targets")}}, @@ -682,11 +686,15 @@ RD_CmdKindInfo rd_cmd_kind_info_table[261] = { str8_lit_comp("rotate_panel_columns"), str8_lit_comp("Rotates all panels at the closest column level of the panel hierarchy."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp("")}}, { str8_lit_comp("next_panel"), str8_lit_comp("Cycles the active panel forward."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp("")}}, { str8_lit_comp("prev_panel"), str8_lit_comp("Cycles the active panel backwards."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp("")}}, +{ str8_lit_comp("parent_panel"), str8_lit_comp("Focuses the parent of the currently selected panel."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp("")}}, { str8_lit_comp("focus_panel"), str8_lit_comp("Focuses a new panel."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp("")}}, { str8_lit_comp("focus_panel_right"), str8_lit_comp("Focuses a panel rightward of the currently focused panel."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp("")}}, { str8_lit_comp("focus_panel_left"), str8_lit_comp("Focuses a panel leftward of the currently focused panel."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp("")}}, { str8_lit_comp("focus_panel_up"), str8_lit_comp("Focuses a panel upward of the currently focused panel."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp("")}}, { str8_lit_comp("focus_panel_down"), str8_lit_comp("Focuses a panel downward of the currently focused panel."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp("")}}, +{ str8_lit_comp("zoom_panel"), str8_lit_comp("Zooms a panel, making it occupy the entire window."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp("")}}, +{ str8_lit_comp("unzoom_panel"), str8_lit_comp("Unzooms the currently zoomed panel."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp("")}}, +{ str8_lit_comp("toggle_zoom_panel"), str8_lit_comp("Zooms a panel, making it occupy the entire window, or unzooms it, if already zoomed."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp("")}}, { str8_lit_comp("undo"), str8_lit_comp("Undoes the previous action."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp("")}}, { str8_lit_comp("redo"), str8_lit_comp("Redoes the first previously undone action."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp("")}}, { str8_lit_comp("go_back"), str8_lit_comp("Returns to the previously selected panel and tab in recorded history."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp("")}}, diff --git a/src/raddbg/generated/raddbg.meta.h b/src/raddbg/generated/raddbg.meta.h index d18bb78e..c16a335e 100644 --- a/src/raddbg/generated/raddbg.meta.h +++ b/src/raddbg/generated/raddbg.meta.h @@ -145,11 +145,15 @@ RD_CmdKind_SplitPanel, RD_CmdKind_RotatePanelColumns, RD_CmdKind_NextPanel, RD_CmdKind_PrevPanel, +RD_CmdKind_ParentPanel, RD_CmdKind_FocusPanel, RD_CmdKind_FocusPanelRight, RD_CmdKind_FocusPanelLeft, RD_CmdKind_FocusPanelUp, RD_CmdKind_FocusPanelDown, +RD_CmdKind_ZoomPanel, +RD_CmdKind_UnzoomPanel, +RD_CmdKind_ToggleZoomPanel, RD_CmdKind_Undo, RD_CmdKind_Redo, RD_CmdKind_GoBack, @@ -634,7 +638,7 @@ Z(getting_started)\ C_LINKAGE_BEGIN extern String8 rd_tab_fast_path_view_name_table[25]; extern String8 rd_tab_fast_path_query_name_table[25]; -extern RD_VocabInfo rd_vocab_info_table[375]; +extern RD_VocabInfo rd_vocab_info_table[379]; extern RD_NameSchemaInfo rd_name_schema_info_table[39]; extern String8 rd_reg_slot_code_name_table[56]; extern Rng1U64 rd_reg_slot_range_table[56]; diff --git a/src/raddbg/raddbg.mdesk b/src/raddbg/raddbg.mdesk index e6867e3e..9604e5ce 100644 --- a/src/raddbg/raddbg.mdesk +++ b/src/raddbg/raddbg.mdesk @@ -803,6 +803,12 @@ RD_VocabTable: 'stdin_path': @can_not_exist @no_relativize path, 'environment': set, 'debug_subprocesses': bool, + @display_name('Remote') + 'remote': bool, + @expand_if("$.remote") @display_name('Deploy') + 'deploy': bool, + @expand_if("$.remote") @display_name('Address') + 'address': string, @no_revert @no_expand @default(0) 'enabled': bool, } ```, @@ -1095,12 +1101,18 @@ RD_CmdTable: // | | | | //- rjf: focused panel changing {NextPanel 0 1 1 "" Null 0 0 0 0 0 0 0 RightArrow "next_panel" "Focus Next Panel" "Cycles the active panel forward." "" "" } {PrevPanel 0 1 1 "" Null 0 0 0 0 0 0 0 LeftArrow "prev_panel" "Focus Previous Panel" "Cycles the active panel backwards." "" "" } + {ParentPanel 0 1 1 "" Null 0 0 0 0 0 0 0 Null "parent_panel" "Focus Parent Panel" "Focuses the parent of the currently selected panel." "" "" } {FocusPanel 0 0 0 "" Null 0 0 0 0 0 0 0 Null "focus_panel" "Focus Panel" "Focuses a new panel." "" "" } {FocusPanelRight 0 1 1 "" Null 0 0 0 0 0 0 0 RightArrow "focus_panel_right" "Focus Panel Right" "Focuses a panel rightward of the currently focused panel." "" "" } {FocusPanelLeft 0 1 1 "" Null 0 0 0 0 0 0 0 LeftArrow "focus_panel_left" "Focus Panel Left" "Focuses a panel leftward of the currently focused panel." "" "" } {FocusPanelUp 0 1 1 "" Null 0 0 0 0 0 0 0 UpArrow "focus_panel_up" "Focus Panel Up" "Focuses a panel upward of the currently focused panel." "" "" } {FocusPanelDown 0 1 1 "" Null 0 0 0 0 0 0 0 DownArrow "focus_panel_down" "Focus Panel Down" "Focuses a panel downward of the currently focused panel." "" "" } + //- rjf: panel zooming + {ZoomPanel 0 1 1 "" Null 0 0 0 0 0 0 0 Window "zoom_panel" "Zoom Panel" "Zooms a panel, making it occupy the entire window." "" "" } + {UnzoomPanel 0 1 1 "" Null 0 0 0 0 0 0 0 Window "unzoom_panel" "Unzoom Panel" "Unzooms the currently zoomed panel." "" "" } + {ToggleZoomPanel 0 1 1 "" Null 0 0 0 0 0 0 0 Window "toggle_zoom_panel" "Toggle Panel Zoom" "Zooms a panel, making it occupy the entire window, or unzooms it, if already zoomed." "" "" } + //- rjf: undo/redo {Undo 0 0 0 "" Null 0 0 0 0 0 0 0 Undo "undo" "Undo" "Undoes the previous action." "" "" } {Redo 0 0 0 "" Null 0 0 0 0 0 0 0 Redo "redo" "Redo" "Redoes the first previously undone action." "" "" } diff --git a/src/raddbg/raddbg_core.c b/src/raddbg/raddbg_core.c index be5f449e..41075094 100644 --- a/src/raddbg/raddbg_core.c +++ b/src/raddbg/raddbg_core.c @@ -5724,7 +5724,7 @@ rd_window_frame(void) // rd_regs()->panel = panel_tree.focused->cfg->id; rd_regs()->tab = panel_tree.focused->selected_tab->id; - rd_regs()->view = panel_tree.focused->selected_tab->id; + rd_regs()->view = panel_tree.focused->selected_tab->id; ////////////////////////////// //- rjf: @window_frame_part compute window's theme @@ -6054,8 +6054,8 @@ rd_window_frame(void) ui_push_pref_height(ui_px(floor_f32(ui_top_font_size()*3.f), 1.f)); ui_push_blur_size(10.f); FNT_RasterFlags text_raster_flags = 0; - if(rd_setting_b32_from_name(str8_lit("smooth_ui_text"))) {text_raster_flags |= FNT_RasterFlag_Smooth;} - if(rd_setting_b32_from_name(str8_lit("hint_ui_text"))) {text_raster_flags |= FNT_RasterFlag_Hinted;} + if(rd_setting_b32_from_name(s("smooth_ui_text"))) {text_raster_flags |= FNT_RasterFlag_Smooth;} + if(rd_setting_b32_from_name(s("hint_ui_text"))) {text_raster_flags |= FNT_RasterFlag_Hinted;} ui_push_text_raster_flags(text_raster_flags); } @@ -7538,6 +7538,10 @@ rd_window_frame(void) rd_cmd_kind_info_table[RD_CmdKind_NextPanel].string, rd_cmd_kind_info_table[RD_CmdKind_PrevPanel].string, {0},//- + rd_cmd_kind_info_table[RD_CmdKind_ZoomPanel].string, + rd_cmd_kind_info_table[RD_CmdKind_UnzoomPanel].string, + rd_cmd_kind_info_table[RD_CmdKind_ToggleZoomPanel].string, + {0},//- rd_cmd_kind_info_table[RD_CmdKind_TabBarTop].string, rd_cmd_kind_info_table[RD_CmdKind_TabBarBottom].string, {0},//- @@ -7554,6 +7558,10 @@ rd_window_frame(void) 'n', 'p', 0,//- + 'z', + 'm', + 't', + 0,//-- 0, 0, 0,//- @@ -8236,53 +8244,150 @@ rd_window_frame(void) // B32 is_changing_panel_boundaries = 0; ProfScope("non-leaf panel UI") - for(CFG_PanelNode *panel = panel_tree.root; - panel != &cfg_nil_panel_node; - panel = cfg_panel_node_rec__depth_first_pre(panel_tree.root, panel).next) { - ////////////////////////// - //- rjf: continue on leaf panels - // - if(panel->first == &cfg_nil_panel_node) + CFG_PanelNode *panel_tree_root = (panel_tree.zoom_root != &cfg_nil_panel_node) ? panel_tree.zoom_root : panel_tree.root; + for(CFG_PanelNode *panel = panel_tree_root; + panel != &cfg_nil_panel_node; + panel = cfg_panel_node_rec__depth_first_pre(panel_tree_root, panel).next) { - continue; - } - - ////////////////////////// - //- rjf: grab info - // - Axis2 split_axis = panel->split_axis; - Rng2F32 panel_rect = cfg_target_rect_from_panel_node(content_rect, panel_tree.root, panel); - - ////////////////////////// - //- rjf: boundary tab-drag/drop sites - // - { - CFG_Node *drag_view = cfg_node_from_id(rd_state->drag_drop_regs->view); - if(rd_drag_is_active() && rd_state->drag_drop_regs_slot == RD_RegSlot_View && drag_view != &cfg_nil_node) + ////////////////////////// + //- rjf: continue on leaf panels + // + if(panel->first == &cfg_nil_panel_node) { - //- rjf: params - F32 drop_site_major_dim_px = ceil_f32(ui_top_font_size()*7.f); - F32 drop_site_minor_dim_px = ceil_f32(ui_top_font_size()*5.f); - F32 corner_radius = ui_top_font_size()*0.5f; - F32 padding = ceil_f32(ui_top_font_size()*0.5f); - - //- rjf: special case - build Y boundary drop sites on root panel - // - // (this does not naturally follow from the below algorithm, since the - // root level panel only splits on X) - if(panel == panel_tree.root) UI_CornerRadius(corner_radius) + continue; + } + + ////////////////////////// + //- rjf: grab info + // + Axis2 split_axis = panel->split_axis; + Rng2F32 panel_rect = cfg_target_rect_from_panel_node(content_rect, panel_tree_root, panel); + if(panel == panel_tree.zoom_root) + { + panel_rect = content_rect; + } + + ////////////////////////// + //- rjf: boundary tab-drag/drop sites + // + { + CFG_Node *drag_view = cfg_node_from_id(rd_state->drag_drop_regs->view); + if(rd_drag_is_active() && rd_state->drag_drop_regs_slot == RD_RegSlot_View && drag_view != &cfg_nil_node) { - Vec2F32 panel_rect_center = center_2f32(panel_rect); - Axis2 axis = axis2_flip(panel_tree.root->split_axis); - for EachEnumVal(Side, side) + //- rjf: params + F32 drop_site_major_dim_px = ceil_f32(ui_top_font_size()*7.f); + F32 drop_site_minor_dim_px = ceil_f32(ui_top_font_size()*5.f); + F32 corner_radius = ui_top_font_size()*0.5f; + F32 padding = ceil_f32(ui_top_font_size()*0.5f); + + //- rjf: special case - build Y boundary drop sites on root panel + // + // (this does not naturally follow from the below algorithm, since the + // root level panel only splits on X) + if(panel == panel_tree_root) UI_CornerRadius(corner_radius) { - UI_Key key = ui_key_from_stringf(ui_key_zero(), "root_extra_split_%i", side); - Rng2F32 site_rect = panel_rect; - site_rect.p0.v[axis2_flip(axis)] = panel_rect_center.v[axis2_flip(axis)] - drop_site_major_dim_px/2; - site_rect.p1.v[axis2_flip(axis)] = panel_rect_center.v[axis2_flip(axis)] + drop_site_major_dim_px/2; - site_rect.p0.v[axis] = panel_rect.v[side].v[axis] - drop_site_minor_dim_px/2; - site_rect.p1.v[axis] = panel_rect.v[side].v[axis] + drop_site_minor_dim_px/2; + Vec2F32 panel_rect_center = center_2f32(panel_rect); + Axis2 axis = axis2_flip(panel_tree_root->split_axis); + for EachEnumVal(Side, side) + { + UI_Key key = ui_key_from_stringf(ui_key_zero(), "root_extra_split_%i", side); + Rng2F32 site_rect = panel_rect; + site_rect.p0.v[axis2_flip(axis)] = panel_rect_center.v[axis2_flip(axis)] - drop_site_major_dim_px/2; + site_rect.p1.v[axis2_flip(axis)] = panel_rect_center.v[axis2_flip(axis)] + drop_site_major_dim_px/2; + site_rect.p0.v[axis] = panel_rect.v[side].v[axis] - drop_site_minor_dim_px/2; + site_rect.p1.v[axis] = panel_rect.v[side].v[axis] + drop_site_minor_dim_px/2; + + // rjf: build + UI_Box *site_box = &ui_nil_box; + { + F32 site_open_t = ui_anim(ui_key_from_stringf(key, "open_t"), 1.f, .rate = rd_state->menu_animation_rate); + UI_Rect(site_rect) UI_Squish(0.1f-0.1f*site_open_t) UI_Transparency(1-site_open_t) + { + site_box = ui_build_box_from_key(UI_BoxFlag_DropSite|UI_BoxFlag_DrawHotEffects, key); + ui_signal_from_box(site_box); + } + UI_Box *site_box_viz = &ui_nil_box; + UI_Parent(site_box) UI_WidthFill UI_HeightFill + UI_Padding(ui_px(padding, 1.f)) + UI_Column + UI_Padding(ui_px(padding, 1.f)) + UI_GroupKey(key) + { + ui_set_next_child_layout_axis(axis2_flip(axis)); + site_box_viz = ui_build_box_from_key(UI_BoxFlag_DrawBackground| + UI_BoxFlag_DrawBorder| + UI_BoxFlag_DrawDropShadow| + UI_BoxFlag_DrawBackgroundBlur| + UI_BoxFlag_DrawHotEffects, ui_key_zero()); + } + UI_Parent(site_box_viz) UI_WidthFill UI_HeightFill UI_Padding(ui_px(padding, 1.f)) + { + ui_set_next_child_layout_axis(axis); + UI_Box *row_or_column = ui_build_box_from_key(0, ui_key_zero()); UI_Parent(row_or_column) UI_Padding(ui_px(padding, 1.f)) + { + ui_build_box_from_key(UI_BoxFlag_DrawBorder, ui_key_zero()); + ui_spacer(ui_px(padding, 1.f)); + ui_build_box_from_key(UI_BoxFlag_DrawBorder, ui_key_zero()); + } + } + } + + // rjf: viz + if(ui_key_match(site_box->key, ui_drop_hot_key())) + { + Rng2F32 future_split_rect_target = site_rect; + future_split_rect_target.p0.v[axis] -= drop_site_major_dim_px; + future_split_rect_target.p1.v[axis] += drop_site_major_dim_px; + future_split_rect_target.p0.v[axis2_flip(axis)] = panel_rect.p0.v[axis2_flip(axis)]; + future_split_rect_target.p1.v[axis2_flip(axis)] = panel_rect.p1.v[axis2_flip(axis)]; + future_split_rect_target = pad_2f32(future_split_rect_target, -ui_top_font_size()*2.f); + Vec2F32 future_split_rect_target_center = center_2f32(future_split_rect_target); + Rng2F32 future_split_rect = + { + ui_anim(ui_key_from_stringf(ui_key_zero(), "drop_site_v0"), future_split_rect_target.x0, .initial = future_split_rect_target_center.x, .rate = rd_state->menu_animation_rate), + ui_anim(ui_key_from_stringf(ui_key_zero(), "drop_site_v1"), future_split_rect_target.y0, .initial = future_split_rect_target_center.y, .rate = rd_state->menu_animation_rate), + ui_anim(ui_key_from_stringf(ui_key_zero(), "drop_site_v2"), future_split_rect_target.x1, .initial = future_split_rect_target_center.x, .rate = rd_state->menu_animation_rate), + ui_anim(ui_key_from_stringf(ui_key_zero(), "drop_site_v3"), future_split_rect_target.y1, .initial = future_split_rect_target_center.y, .rate = rd_state->menu_animation_rate), + }; + UI_Rect(future_split_rect) UI_TagF("drop_site") UI_CornerRadius(ui_top_font_size()*2.f) + { + ui_build_box_from_key(UI_BoxFlag_DrawBackground|UI_BoxFlag_DrawBorder, ui_key_zero()); + } + } + + // rjf: drop + if(ui_key_match(site_box->key, ui_drop_hot_key()) && rd_drag_drop()) + { + Dir2 dir = (axis == Axis2_Y ? (side == Side_Min ? Dir2_Up : Dir2_Down) : + axis == Axis2_X ? (side == Side_Min ? Dir2_Left : Dir2_Right) : + Dir2_Invalid); + if(dir != Dir2_Invalid) + { + CFG_PanelNode *split_panel = panel; + rd_cmd(RD_CmdKind_SplitPanel, + .dst_panel = split_panel->cfg->id, + .panel = rd_state->drag_drop_regs->panel, + .view = rd_state->drag_drop_regs->view, + .dir2 = dir); + } + } + } + } + + //- rjf: iterate all children, build boundary drop sites + Axis2 split_axis = panel->split_axis; + UI_CornerRadius(corner_radius) for(CFG_PanelNode *child = panel->first;; child = child->next) + { + // rjf: form rect + Rng2F32 child_rect = cfg_target_rect_from_panel_node_child(panel_rect, panel, child); + Vec2F32 child_rect_center = center_2f32(child_rect); + UI_Key key = ui_key_from_stringf(ui_key_zero(), "drop_boundary_%p_%p", panel->cfg, child->cfg); + Rng2F32 site_rect = r2f32(child_rect_center, child_rect_center); + site_rect.p0.v[split_axis] = child_rect.p0.v[split_axis] - drop_site_minor_dim_px/2; + site_rect.p1.v[split_axis] = child_rect.p0.v[split_axis] + drop_site_minor_dim_px/2; + site_rect.p0.v[axis2_flip(split_axis)] -= drop_site_major_dim_px/2; + site_rect.p1.v[axis2_flip(split_axis)] += drop_site_major_dim_px/2; // rjf: build UI_Box *site_box = &ui_nil_box; @@ -8300,7 +8405,7 @@ rd_window_frame(void) UI_Padding(ui_px(padding, 1.f)) UI_GroupKey(key) { - ui_set_next_child_layout_axis(axis2_flip(axis)); + ui_set_next_child_layout_axis(axis2_flip(split_axis)); site_box_viz = ui_build_box_from_key(UI_BoxFlag_DrawBackground| UI_BoxFlag_DrawBorder| UI_BoxFlag_DrawDropShadow| @@ -8309,7 +8414,7 @@ rd_window_frame(void) } UI_Parent(site_box_viz) UI_WidthFill UI_HeightFill UI_Padding(ui_px(padding, 1.f)) { - ui_set_next_child_layout_axis(axis); + ui_set_next_child_layout_axis(split_axis); UI_Box *row_or_column = ui_build_box_from_key(0, ui_key_zero()); UI_Parent(row_or_column) UI_Padding(ui_px(padding, 1.f)) { ui_build_box_from_key(UI_BoxFlag_DrawBorder, ui_key_zero()); @@ -8323,10 +8428,10 @@ rd_window_frame(void) if(ui_key_match(site_box->key, ui_drop_hot_key())) { Rng2F32 future_split_rect_target = site_rect; - future_split_rect_target.p0.v[axis] -= drop_site_major_dim_px; - future_split_rect_target.p1.v[axis] += drop_site_major_dim_px; - future_split_rect_target.p0.v[axis2_flip(axis)] = panel_rect.p0.v[axis2_flip(axis)]; - future_split_rect_target.p1.v[axis2_flip(axis)] = panel_rect.p1.v[axis2_flip(axis)]; + future_split_rect_target.p0.v[split_axis] -= drop_site_major_dim_px; + future_split_rect_target.p1.v[split_axis] += drop_site_major_dim_px; + future_split_rect_target.p0.v[axis2_flip(split_axis)] = child_rect.p0.v[axis2_flip(split_axis)]; + future_split_rect_target.p1.v[axis2_flip(split_axis)] = child_rect.p1.v[axis2_flip(split_axis)]; future_split_rect_target = pad_2f32(future_split_rect_target, -ui_top_font_size()*2.f); Vec2F32 future_split_rect_target_center = center_2f32(future_split_rect_target); Rng2F32 future_split_rect = @@ -8345,187 +8450,97 @@ rd_window_frame(void) // rjf: drop if(ui_key_match(site_box->key, ui_drop_hot_key()) && rd_drag_drop()) { - Dir2 dir = (axis == Axis2_Y ? (side == Side_Min ? Dir2_Up : Dir2_Down) : - axis == Axis2_X ? (side == Side_Min ? Dir2_Left : Dir2_Right) : - Dir2_Invalid); - if(dir != Dir2_Invalid) + Dir2 dir = (panel->split_axis == Axis2_X ? Dir2_Left : Dir2_Up); + CFG_PanelNode *split_panel = child; + if(split_panel == &cfg_nil_panel_node) { - CFG_PanelNode *split_panel = panel; - rd_cmd(RD_CmdKind_SplitPanel, - .dst_panel = split_panel->cfg->id, - .panel = rd_state->drag_drop_regs->panel, - .view = rd_state->drag_drop_regs->view, - .dir2 = dir); + split_panel = panel->last; + dir = (panel->split_axis == Axis2_X ? Dir2_Right : Dir2_Down); } + rd_cmd(RD_CmdKind_SplitPanel, + .dst_panel = split_panel->cfg->id, + .panel = rd_state->drag_drop_regs->panel, + .view = rd_state->drag_drop_regs->view, + .dir2 = dir); + } + + // rjf: exit on opl child + if(child == &cfg_nil_panel_node) + { + break; } } } - - //- rjf: iterate all children, build boundary drop sites - Axis2 split_axis = panel->split_axis; - UI_CornerRadius(corner_radius) for(CFG_PanelNode *child = panel->first;; child = child->next) - { - // rjf: form rect - Rng2F32 child_rect = cfg_target_rect_from_panel_node_child(panel_rect, panel, child); - Vec2F32 child_rect_center = center_2f32(child_rect); - UI_Key key = ui_key_from_stringf(ui_key_zero(), "drop_boundary_%p_%p", panel->cfg, child->cfg); - Rng2F32 site_rect = r2f32(child_rect_center, child_rect_center); - site_rect.p0.v[split_axis] = child_rect.p0.v[split_axis] - drop_site_minor_dim_px/2; - site_rect.p1.v[split_axis] = child_rect.p0.v[split_axis] + drop_site_minor_dim_px/2; - site_rect.p0.v[axis2_flip(split_axis)] -= drop_site_major_dim_px/2; - site_rect.p1.v[axis2_flip(split_axis)] += drop_site_major_dim_px/2; - - // rjf: build - UI_Box *site_box = &ui_nil_box; - { - F32 site_open_t = ui_anim(ui_key_from_stringf(key, "open_t"), 1.f, .rate = rd_state->menu_animation_rate); - UI_Rect(site_rect) UI_Squish(0.1f-0.1f*site_open_t) UI_Transparency(1-site_open_t) - { - site_box = ui_build_box_from_key(UI_BoxFlag_DropSite|UI_BoxFlag_DrawHotEffects, key); - ui_signal_from_box(site_box); - } - UI_Box *site_box_viz = &ui_nil_box; - UI_Parent(site_box) UI_WidthFill UI_HeightFill - UI_Padding(ui_px(padding, 1.f)) - UI_Column - UI_Padding(ui_px(padding, 1.f)) - UI_GroupKey(key) - { - ui_set_next_child_layout_axis(axis2_flip(split_axis)); - site_box_viz = ui_build_box_from_key(UI_BoxFlag_DrawBackground| - UI_BoxFlag_DrawBorder| - UI_BoxFlag_DrawDropShadow| - UI_BoxFlag_DrawBackgroundBlur| - UI_BoxFlag_DrawHotEffects, ui_key_zero()); - } - UI_Parent(site_box_viz) UI_WidthFill UI_HeightFill UI_Padding(ui_px(padding, 1.f)) - { - ui_set_next_child_layout_axis(split_axis); - UI_Box *row_or_column = ui_build_box_from_key(0, ui_key_zero()); UI_Parent(row_or_column) UI_Padding(ui_px(padding, 1.f)) - { - ui_build_box_from_key(UI_BoxFlag_DrawBorder, ui_key_zero()); - ui_spacer(ui_px(padding, 1.f)); - ui_build_box_from_key(UI_BoxFlag_DrawBorder, ui_key_zero()); - } - } - } - - // rjf: viz - if(ui_key_match(site_box->key, ui_drop_hot_key())) - { - Rng2F32 future_split_rect_target = site_rect; - future_split_rect_target.p0.v[split_axis] -= drop_site_major_dim_px; - future_split_rect_target.p1.v[split_axis] += drop_site_major_dim_px; - future_split_rect_target.p0.v[axis2_flip(split_axis)] = child_rect.p0.v[axis2_flip(split_axis)]; - future_split_rect_target.p1.v[axis2_flip(split_axis)] = child_rect.p1.v[axis2_flip(split_axis)]; - future_split_rect_target = pad_2f32(future_split_rect_target, -ui_top_font_size()*2.f); - Vec2F32 future_split_rect_target_center = center_2f32(future_split_rect_target); - Rng2F32 future_split_rect = - { - ui_anim(ui_key_from_stringf(ui_key_zero(), "drop_site_v0"), future_split_rect_target.x0, .initial = future_split_rect_target_center.x, .rate = rd_state->menu_animation_rate), - ui_anim(ui_key_from_stringf(ui_key_zero(), "drop_site_v1"), future_split_rect_target.y0, .initial = future_split_rect_target_center.y, .rate = rd_state->menu_animation_rate), - ui_anim(ui_key_from_stringf(ui_key_zero(), "drop_site_v2"), future_split_rect_target.x1, .initial = future_split_rect_target_center.x, .rate = rd_state->menu_animation_rate), - ui_anim(ui_key_from_stringf(ui_key_zero(), "drop_site_v3"), future_split_rect_target.y1, .initial = future_split_rect_target_center.y, .rate = rd_state->menu_animation_rate), - }; - UI_Rect(future_split_rect) UI_TagF("drop_site") UI_CornerRadius(ui_top_font_size()*2.f) - { - ui_build_box_from_key(UI_BoxFlag_DrawBackground|UI_BoxFlag_DrawBorder, ui_key_zero()); - } - } - - // rjf: drop - if(ui_key_match(site_box->key, ui_drop_hot_key()) && rd_drag_drop()) - { - Dir2 dir = (panel->split_axis == Axis2_X ? Dir2_Left : Dir2_Up); - CFG_PanelNode *split_panel = child; - if(split_panel == &cfg_nil_panel_node) - { - split_panel = panel->last; - dir = (panel->split_axis == Axis2_X ? Dir2_Right : Dir2_Down); - } - rd_cmd(RD_CmdKind_SplitPanel, - .dst_panel = split_panel->cfg->id, - .panel = rd_state->drag_drop_regs->panel, - .view = rd_state->drag_drop_regs->view, - .dir2 = dir); - } - - // rjf: exit on opl child - if(child == &cfg_nil_panel_node) - { - break; - } - } - } - } - - ////////////////////////// - //- rjf: do UI for drag boundaries between all children - // - for(CFG_PanelNode *child = panel->first; - child != &cfg_nil_panel_node && child->next != &cfg_nil_panel_node; - child = child->next) - { - CFG_PanelNode *min_child = child; - CFG_PanelNode *max_child = min_child->next; - Rng2F32 min_child_rect = cfg_target_rect_from_panel_node_child(panel_rect, panel, min_child); - Rng2F32 max_child_rect = cfg_target_rect_from_panel_node_child(panel_rect, panel, max_child); - Rng2F32 boundary_rect = {0}; - { - boundary_rect.p0.v[split_axis] = min_child_rect.p1.v[split_axis] - ui_top_font_size()/3; - boundary_rect.p1.v[split_axis] = max_child_rect.p0.v[split_axis] + ui_top_font_size()/3; - boundary_rect.p0.v[axis2_flip(split_axis)] = panel_rect.p0.v[axis2_flip(split_axis)]; - boundary_rect.p1.v[axis2_flip(split_axis)] = panel_rect.p1.v[axis2_flip(split_axis)]; } - UI_Rect(boundary_rect) + ////////////////////////// + //- rjf: do UI for drag boundaries between all children + // + for(CFG_PanelNode *child = panel->first; + child != &cfg_nil_panel_node && child->next != &cfg_nil_panel_node; + child = child->next) { - ui_set_next_hover_cursor(split_axis == Axis2_X ? WM_Cursor_LeftRight : WM_Cursor_UpDown); - UI_Box *box = ui_build_box_from_stringf(UI_BoxFlag_Clickable, "###%p_%p", min_child->cfg, max_child->cfg); - UI_Signal sig = ui_signal_from_box(box); - if(ui_double_clicked(sig)) + CFG_PanelNode *min_child = child; + CFG_PanelNode *max_child = min_child->next; + Rng2F32 min_child_rect = cfg_target_rect_from_panel_node_child(panel_rect, panel, min_child); + Rng2F32 max_child_rect = cfg_target_rect_from_panel_node_child(panel_rect, panel, max_child); + Rng2F32 boundary_rect = {0}; { - ui_kill_action(); - F32 sum_pct = min_child->pct_of_parent + max_child->pct_of_parent; - min_child->pct_of_parent = 0.5f * sum_pct; - max_child->pct_of_parent = 0.5f * sum_pct; - cfg_node_equip_stringf(rd_state->cfg, min_child->cfg, "%f", min_child->pct_of_parent); - cfg_node_equip_stringf(rd_state->cfg, max_child->cfg, "%f", max_child->pct_of_parent); + boundary_rect.p0.v[split_axis] = min_child_rect.p1.v[split_axis] - ui_top_font_size()/3; + boundary_rect.p1.v[split_axis] = max_child_rect.p0.v[split_axis] + ui_top_font_size()/3; + boundary_rect.p0.v[axis2_flip(split_axis)] = panel_rect.p0.v[axis2_flip(split_axis)]; + boundary_rect.p1.v[axis2_flip(split_axis)] = panel_rect.p1.v[axis2_flip(split_axis)]; } - else if(ui_pressed(sig)) + + UI_Rect(boundary_rect) { - Vec2F32 v = {min_child->pct_of_parent, max_child->pct_of_parent}; - ui_store_drag_struct(&v); - } - else if(ui_dragging(sig)) - { - Vec2F32 v = *ui_get_drag_struct(Vec2F32); - Vec2F32 mouse_delta = ui_drag_delta(); - F32 total_size = dim_2f32(panel_rect).v[split_axis]; - F32 min_pct__before = v.v[0]; - F32 min_pixels__before = min_pct__before * total_size; - F32 min_pixels__after = min_pixels__before + mouse_delta.v[split_axis]; - if(min_pixels__after < 50.f) + ui_set_next_hover_cursor(split_axis == Axis2_X ? WM_Cursor_LeftRight : WM_Cursor_UpDown); + UI_Box *box = ui_build_box_from_stringf(UI_BoxFlag_Clickable, "###%p_%p", min_child->cfg, max_child->cfg); + UI_Signal sig = ui_signal_from_box(box); + if(ui_double_clicked(sig)) { - min_pixels__after = 50.f; + ui_kill_action(); + F32 sum_pct = min_child->pct_of_parent + max_child->pct_of_parent; + min_child->pct_of_parent = 0.5f * sum_pct; + max_child->pct_of_parent = 0.5f * sum_pct; + cfg_node_equip_stringf(rd_state->cfg, min_child->cfg, "%f", min_child->pct_of_parent); + cfg_node_equip_stringf(rd_state->cfg, max_child->cfg, "%f", max_child->pct_of_parent); } - F32 min_pct__after = min_pixels__after / total_size; - F32 pct_delta = min_pct__after - min_pct__before; - F32 max_pct__before = v.v[1]; - F32 max_pct__after = max_pct__before - pct_delta; - F32 max_pixels__after = max_pct__after * total_size; - if(max_pixels__after < 50.f) + else if(ui_pressed(sig)) { - max_pixels__after = 50.f; - max_pct__after = max_pixels__after / total_size; - pct_delta = -(max_pct__after - max_pct__before); - min_pct__after = min_pct__before + pct_delta; + Vec2F32 v = {min_child->pct_of_parent, max_child->pct_of_parent}; + ui_store_drag_struct(&v); + } + else if(ui_dragging(sig)) + { + Vec2F32 v = *ui_get_drag_struct(Vec2F32); + Vec2F32 mouse_delta = ui_drag_delta(); + F32 total_size = dim_2f32(panel_rect).v[split_axis]; + F32 min_pct__before = v.v[0]; + F32 min_pixels__before = min_pct__before * total_size; + F32 min_pixels__after = min_pixels__before + mouse_delta.v[split_axis]; + if(min_pixels__after < 50.f) + { + min_pixels__after = 50.f; + } + F32 min_pct__after = min_pixels__after / total_size; + F32 pct_delta = min_pct__after - min_pct__before; + F32 max_pct__before = v.v[1]; + F32 max_pct__after = max_pct__before - pct_delta; + F32 max_pixels__after = max_pct__after * total_size; + if(max_pixels__after < 50.f) + { + max_pixels__after = 50.f; + max_pct__after = max_pixels__after / total_size; + pct_delta = -(max_pct__after - max_pct__before); + min_pct__after = min_pct__before + pct_delta; + } + min_child->pct_of_parent = min_pct__after; + max_child->pct_of_parent = max_pct__after; + cfg_node_equip_stringf(rd_state->cfg, min_child->cfg, "%f", min_pct__after); + cfg_node_equip_stringf(rd_state->cfg, max_child->cfg, "%f", max_pct__after); + is_changing_panel_boundaries = 1; } - min_child->pct_of_parent = min_pct__after; - max_child->pct_of_parent = max_pct__after; - cfg_node_equip_stringf(rd_state->cfg, min_child->cfg, "%f", min_pct__after); - cfg_node_equip_stringf(rd_state->cfg, max_child->cfg, "%f", max_pct__after); - is_changing_panel_boundaries = 1; } } } @@ -8544,7 +8559,20 @@ rd_window_frame(void) panel != &cfg_nil_panel_node; panel = cfg_panel_node_rec__depth_first_pre(panel_tree.root, panel).next) { - Rng2F32 target_rect_px = cfg_target_rect_from_panel_node(content_rect, panel_tree.root, panel); + B32 is_in_zoom = 0; + for(CFG_PanelNode *p = panel; p != &cfg_nil_panel_node; p = p->parent) + { + if(p == panel_tree.zoom_root) + { + is_in_zoom = 1; + break; + } + } + Rng2F32 target_rect_px = cfg_target_rect_from_panel_node(content_rect, is_in_zoom ? panel_tree.zoom_root : panel_tree.root, panel); + if(panel == panel_tree.zoom_root) + { + target_rect_px = content_rect; + } Rng2F32 target_rect_pct = r2f32p(target_rect_px.x0/content_rect_dim.x, target_rect_px.y0/content_rect_dim.y, target_rect_px.x1/content_rect_dim.x, @@ -8565,12 +8593,23 @@ rd_window_frame(void) if(content_rect.x1 > content_rect.x0 && content_rect.y1 > content_rect.y0) { B32 any_disasm_open = 0; - ProfScope("leaf panel UI") - for(CFG_PanelNode *panel = panel_tree.root; - panel != &cfg_nil_panel_node; - panel = cfg_panel_node_rec__depth_first_pre(panel_tree.root, panel).next) + if(ws->panel_hoist_cfg_id != panel_tree.zoom_root->cfg->id && panel_tree.zoom_root->cfg->id != 0) { - if(panel->first != &cfg_nil_panel_node) {continue;} + ws->panel_hoist_cfg_id = panel_tree.zoom_root->cfg->id; + } + CFG_PanelNode *front_panel = cfg_panel_node_from_tree_cfg(panel_tree.root, cfg_node_from_id(ws->panel_hoist_cfg_id)); + CFG_PanelNode *panel_trees[] = {front_panel, panel_tree.root}; + F32 panel_zoom_t = ui_anim(ui_key_from_stringf(ui_key_zero(), "panel_zoom_t"), (F32)(panel_tree.zoom_root != &cfg_nil_panel_node), .initial = (F32)(panel_tree.zoom_root != &cfg_nil_panel_node)); + ProfScope("leaf panel UI") + for EachElement(panel_tree_idx, panel_trees) + for(CFG_PanelNode *panel = panel_trees[panel_tree_idx]; + panel != &cfg_nil_panel_node; + panel = cfg_panel_node_rec__depth_first_pre(panel_trees[panel_tree_idx], panel).next) + { + if(panel_trees[panel_tree_idx] != front_panel && panel == front_panel) + { + continue; + } B32 panel_is_focused = (window_is_focused && !rd_state->popup_active && !ws->menu_bar_focused && @@ -8586,12 +8625,26 @@ rd_window_frame(void) } ProfScope("leaf panel UI work - %.*s: %.*s", str8_varg(selected_tab->string), str8_varg(rd_expr_from_cfg(selected_tab))) UI_Focus(panel_is_focused ? UI_FocusKind_Null : UI_FocusKind_Off) + UI_Transparency(panel_trees[panel_tree_idx] != front_panel ? panel_zoom_t : 0) { ////////////////////////// //- rjf: calculate UI rectangles // Vec2F32 content_rect_dim = dim_2f32(content_rect); - Rng2F32 target_rect_px = cfg_target_rect_from_panel_node(content_rect, panel_tree.root, panel); + B32 is_in_zoom = 0; + for(CFG_PanelNode *p = panel; p != &cfg_nil_panel_node; p = p->parent) + { + if(p == panel_tree.zoom_root) + { + is_in_zoom = 1; + break; + } + } + Rng2F32 target_rect_px = cfg_target_rect_from_panel_node(content_rect, is_in_zoom ? panel_tree.zoom_root : panel_tree.root, panel); + if(panel == panel_tree.zoom_root) + { + target_rect_px = content_rect; + } Rng2F32 target_rect_pct = r2f32p(target_rect_px.x0 / content_rect_dim.x, target_rect_px.y0 / content_rect_dim.y, target_rect_px.x1 / content_rect_dim.x, @@ -8623,9 +8676,17 @@ rd_window_frame(void) content_rect = intersect_2f32(content_rect, panel_rect); ////////////////////////// - //- rjf: decide to skip this panel (e.g. if it is too small + //- rjf: for non-leaf panels with focus (subtree selection) -> draw border for all children // - B32 build_panel = (content_rect.x1 > content_rect.x0 && content_rect.y1 > content_rect.y0); + if(panel->first != &cfg_nil_panel_node && panel == panel_tree.focused) UI_Rect(pad_2f32(panel_rect, ui_top_font_size()*0.2f)) UI_Focus(UI_FocusKind_On) + { + ui_build_box_from_stringf(UI_BoxFlag_Clickable|UI_BoxFlag_DisableFocusOverlay, "###"); + } + + ////////////////////////// + //- rjf: decide to skip this panel (e.g. if it non-leaf, or is too small) + // + B32 build_panel = ((panel->first == &cfg_nil_panel_node) && content_rect.x1 > content_rect.x0 && content_rect.y1 > content_rect.y0 && ui_top_transparency() < 0.99f); ////////////////////////// //- rjf: build combined split+movetab drag/drop sites @@ -8822,6 +8883,16 @@ rd_window_frame(void) ui_build_box_from_key(UI_BoxFlag_DrawBackground, ui_key_zero()); } + ////////////////////////// + //- rjf: determine how much this panel is occluding others + // + B32 is_occluding = 0; + if(panel_trees[panel_tree_idx] == front_panel) + { + is_occluding = (abs_f32(panel_rect.x0 - target_rect_px.x0) > 2 || + abs_f32(panel_rect.y0 - target_rect_px.y0) > 2); + } + ////////////////////////// //- rjf: build panel container box // @@ -8833,6 +8904,7 @@ rd_window_frame(void) UI_BoxFlag_Clip| UI_BoxFlag_DrawBorder| UI_BoxFlag_DisableFocusOverlay| + (is_occluding*UI_BoxFlag_DrawBackground)| ((panel_tree.focused != panel)*UI_BoxFlag_DisableFocusBorder), panel_key); } @@ -8971,6 +9043,70 @@ rd_window_frame(void) } } + ////////////////////////// + //- rjf: build zoom button + // + if(panel_is_focused) + { + UI_TextAlignment(UI_TextAlign_Center) + UI_TagF(".") + { + ui_set_next_child_layout_axis(Axis2_Y); + UI_Box *container = &ui_nil_box; + UI_Rect(r2f32p(tab_bar_rect.x1 - tab_bar_vheight, tab_bar_rect.y0, tab_bar_rect.x1, tab_bar_rect.y1)) + { + container = ui_build_box_from_stringf(0, "###zoom_panel"); + } + UI_Parent(container) + { + if(panel->tab_side == Side_Max) + { + ui_spacer(ui_px(tab_bar_rv_diff-1.f, 1.f)); + } + else + { + ui_spacer(ui_px(1.f, 1.f)); + } + { + UI_Box *zoom_box = &ui_nil_box; + RD_Font(RD_FontSlot_Icons) + UI_CornerRadius((tab_bar_vheight - tab_bar_vheight/4.f) / 3.f) + UI_VisualMargin(tab_bar_vheight/5.f) + UI_TagF("implicit") + UI_TagF("weak") + UI_FontSize(ui_top_font_size()*0.65f) + { + zoom_box = ui_build_box_from_stringf(UI_BoxFlag_DrawText| + UI_BoxFlag_DrawBorder| + UI_BoxFlag_DrawBackground| + UI_BoxFlag_DrawHotEffects| + UI_BoxFlag_DrawActiveEffects| + UI_BoxFlag_Clickable| + UI_BoxFlag_DisableTextTrunc, + "%S##zoom_panel_button_%p", + rd_icon_kind_text_table[panel_tree.zoom_root == panel ? RD_IconKind_WindowRestore : RD_IconKind_Window], + panel->cfg); + } + UI_Signal sig = ui_signal_from_box(zoom_box); + if(ui_pressed(sig)) + { + rd_cmd(RD_CmdKind_ToggleZoomPanel, .panel = panel->cfg->id); + } + if(ui_hovering(sig)) UI_Tooltip + { + ui_state->tooltip_anchor_key = zoom_box->key; + ui_set_next_pref_width(ui_children_sum(1)); + UI_Row + { + ui_labelf("Toggle Zoom Panel"); + rd_cmd_binding_buttons(rd_cmd_kind_info_table[RD_CmdKind_ToggleZoomPanel].string, s(""), 1, RD_CmdBindingButtonFlag_NoEdit); + } + } + } + } + } + } + ////////////////////////// //- rjf: compute tab build tasks // @@ -8987,7 +9123,7 @@ rd_window_frame(void) U64 tab_task_count = 0; F32 tab_close_width_px = ui_top_font_size()*2.5f; F32 max_tab_width_px = ui_top_font_size()*20.f; - if(build_panel) UI_TagF("tab") + UI_TagF("tab") { B32 reset = (ws->window_layout_reset || ws->frames_alive < 5 || is_changing_panel_boundaries); for(CFG_NodePtrNode *n = panel->tabs.first; n != 0; n = n->next) @@ -8999,19 +9135,24 @@ rd_window_frame(void) } UI_TagF(tab != panel->selected_tab ? "inactive" : "") { - TabTask *t = push_array(scratch.arena, TabTask, 1); - t->tab = tab; - t->fstrs = rd_title_fstrs_from_cfg(scratch.arena, tab, 0); - F32 tab_width_target = dr_dim_from_fstrs(ui_top_tab_size(), &t->fstrs).x + tab_close_width_px + ui_top_font_size()*1.f; + DR_FStrList tab_title_fstrs = rd_title_fstrs_from_cfg(scratch.arena, tab, 0); + F32 tab_width_target = dr_dim_from_fstrs(ui_top_tab_size(), &tab_title_fstrs).x + tab_close_width_px + ui_top_font_size()*1.f; B32 tab_is_selected = (tab == panel->selected_tab); if(tab_is_selected && panel_tree.focused == panel) { tab_width_target += tab_close_width_px; } tab_width_target = Min(max_tab_width_px, tab_width_target); - t->tab_width = floor_f32(ui_anim(ui_key_from_stringf(ui_key_zero(), "tab_width_%p", tab), tab_width_target, .initial = reset ? tab_width_target : 0, .rate = rd_state->menu_animation_rate)); - SLLQueuePush(first_tab_task, last_tab_task, t); - tab_task_count += 1; + F32 tab_width = floor_f32(ui_anim(ui_key_from_stringf(ui_key_zero(), "tab_width_%p", tab), tab_width_target, .initial = reset ? tab_width_target : 0, .rate = rd_state->menu_animation_rate)); + if(build_panel) + { + TabTask *t = push_array(scratch.arena, TabTask, 1); + t->tab = tab; + t->fstrs = tab_title_fstrs; + t->tab_width = tab_width; + SLLQueuePush(first_tab_task, last_tab_task, t); + tab_task_count += 1; + } } } } @@ -9361,6 +9502,7 @@ rd_window_frame(void) ////////////////////////// //- rjf: accept file drops // + if(build_panel) { for(UI_Event *evt = 0; ui_next_event(&evt);) { @@ -11459,9 +11601,9 @@ rd_init(CmdLine *cmdln) for(U64 idx = 1; idx < cmdln->argc; idx += 1) { String8 arg = str8_cstring(cmdln->argv[idx]); - B32 is_flag = (str8_match(str8_prefix(arg, 1), str8_lit("-"), 0) || - str8_match(str8_prefix(arg, 1), str8_lit("--"), 0) || - str8_match(str8_prefix(arg, 1), str8_lit("/"), 0)); + B32 is_flag = (str8_match(str8_prefix(arg, 1), s("-"), 0) || + str8_match(str8_prefix(arg, 1), s("--"), 0) || + str8_match(str8_prefix(arg, 1), s("/"), 0)); B32 is_cfg = 0; B32 is_dmp = 0; if(!is_flag && !after_first_non_flag) @@ -11479,12 +11621,12 @@ rd_init(CmdLine *cmdln) String8 header_suffix = {0}; header_suffix.str = header_suffix_buffer; header_suffix.size = file_read(file, r1u64(10, 10+256), header_suffix_buffer); - String8 header_type_suffix = str8_skip(header_suffix, str8_find_needle(header_suffix, 0, str8_lit(" "), 0)+1); - if(str8_match(header_type_suffix, str8_lit("user"), StringMatchFlag_RightSideSloppy)) + String8 header_type_suffix = str8_skip(header_suffix, str8_find_needle(header_suffix, 0, s(" "), 0)+1); + if(str8_match(header_type_suffix, s("user"), StringMatchFlag_RightSideSloppy)) { implicit_user_arg = path_absolute_dst_from_relative_dst_src(scratch.arena, arg, get_process_info()->initial_path); } - else if(str8_match(header_type_suffix, str8_lit("project"), StringMatchFlag_RightSideSloppy)) + else if(str8_match(header_type_suffix, s("project"), StringMatchFlag_RightSideSloppy)) { implicit_project_arg = path_absolute_dst_from_relative_dst_src(scratch.arena, arg, get_process_info()->initial_path); } @@ -14545,6 +14687,11 @@ rd_frame(void) CFG_Node *split_panel_prev = panel->prev->cfg; CFG_Node *new_parent = cfg_node_alloc(rd_state->cfg); CFG_Node *new_sibling = cfg_node_alloc(rd_state->cfg); + if(panel == panel_tree.zoom_root) + { + CFG_Node *zoom_panel = cfg_node_child_from_string_or_alloc(rd_state->cfg, split_panel, s("zoom_root")); + cfg_node_insert_child(rd_state->cfg, new_parent, &cfg_nil_node, zoom_panel); + } cfg_node_equip_string(rd_state->cfg, new_parent, split_panel->string); cfg_node_equip_string(rd_state->cfg, split_panel, str8_lit("0.5")); cfg_node_equip_string(rd_state->cfg, new_sibling, str8_lit("0.5")); @@ -14726,6 +14873,17 @@ rd_frame(void) } rd_cmd(RD_CmdKind_FocusPanel, .panel = next_focused->cfg->id); }break; + case RD_CmdKind_ParentPanel: + { + CFG_Node *panel = cfg_node_from_id(rd_regs()->panel); + CFG_PanelTree panel_tree = cfg_panel_tree_from_cfg(scratch.arena, cfg_node_from_id(rd_regs()->window)); + CFG_PanelNode *panel_node = cfg_panel_node_from_tree_cfg(panel_tree.root, panel); + CFG_PanelNode *parent_node = panel_node->parent; + if(parent_node != &cfg_nil_panel_node) + { + rd_cmd(RD_CmdKind_FocusPanel, .panel = parent_node->cfg->id); + } + }break; case RD_CmdKind_FocusPanel: { CFG_Node *panel = cfg_node_from_id(rd_regs()->panel); @@ -14804,6 +14962,35 @@ rd_frame(void) } }break; + //- rjf: panel zooming + case RD_CmdKind_ToggleZoomPanel: + case RD_CmdKind_ZoomPanel: + case RD_CmdKind_UnzoomPanel: + { + CFG_Node *window = cfg_node_from_id(rd_regs()->window); + CFG_Node *panel = cfg_node_from_id(rd_regs()->panel); + CFG_PanelTree panel_tree = cfg_panel_tree_from_cfg(scratch.arena, window); + RD_WindowState *ws = rd_window_state_from_cfg(window); + ws->panel_hoist_cfg_id = rd_regs()->panel; + + // rjf: remove existing zoom + B32 already_zoomed = 0; + { + CFG_PanelNode *zoom_root = panel_tree.zoom_root; + if(zoom_root->cfg != &cfg_nil_node) + { + already_zoomed = 1; + cfg_node_release(rd_state->cfg, cfg_node_child_from_string(zoom_root->cfg, s("zoom_root"))); + } + } + + // rjf: not already zoomed? -> zoom + if(!already_zoomed || kind == RD_CmdKind_ZoomPanel) + { + cfg_node_child_from_string_or_alloc(rd_state->cfg, panel, s("zoom_root")); + } + }break; + //- rjf: undo/redo case RD_CmdKind_Undo:{}break; case RD_CmdKind_Redo:{}break; @@ -18595,13 +18782,14 @@ rd_frame(void) F32 scrolling_animations_f = (F32)!!rd_setting_b32_from_name(str8_lit("scrolling_animations")); F32 tooltip_animations_f = (F32)!!rd_setting_b32_from_name(str8_lit("tooltip_animations")); F32 menu_animations_f = (F32)!!rd_setting_b32_from_name(str8_lit("menu_animations")); - rd_state->catchall_animation_rate = 1 - master_animations_f*pow_f32(2, (-60.f * rd_state->frame_dt)); - rd_state->menu_animation_rate = 1 - master_animations_f*menu_animations_f*pow_f32(2, (-70.f * rd_state->frame_dt)); - rd_state->menu_animation_rate__slow = 1 - master_animations_f*menu_animations_f*pow_f32(2, (-50.f * rd_state->frame_dt)); - rd_state->entity_alive_animation_rate = 1 - master_animations_f*menu_animations_f*pow_f32(2, (-30.f * rd_state->frame_dt)); - rd_state->rich_hover_animation_rate = 1 - master_animations_f*menu_animations_f*pow_f32(2, (-50.f * rd_state->frame_dt)); - rd_state->scrolling_animation_rate = 1 - master_animations_f*scrolling_animations_f*pow_f32(2, (-60.f * rd_state->frame_dt)); - rd_state->tooltip_animation_rate = 1 - master_animations_f*tooltip_animations_f*pow_f32(2, (-60.f * rd_state->frame_dt)); + rd_state->catchall_animation_rate = 1 - master_animations_f*pow_f32(2, (-60.f * rd_state->frame_dt)); + rd_state->menu_animation_rate = 1 - master_animations_f*menu_animations_f*pow_f32(2, (-70.f * rd_state->frame_dt)); + rd_state->menu_animation_rate__slow = 1 - master_animations_f*menu_animations_f*pow_f32(2, (-50.f * rd_state->frame_dt)); + rd_state->menu_animation_rate__very_slow = 1 - master_animations_f*menu_animations_f*pow_f32(2, (-20.f * rd_state->frame_dt)); + rd_state->entity_alive_animation_rate = 1 - master_animations_f*menu_animations_f*pow_f32(2, (-30.f * rd_state->frame_dt)); + rd_state->rich_hover_animation_rate = 1 - master_animations_f*menu_animations_f*pow_f32(2, (-50.f * rd_state->frame_dt)); + rd_state->scrolling_animation_rate = 1 - master_animations_f*scrolling_animations_f*pow_f32(2, (-60.f * rd_state->frame_dt)); + rd_state->tooltip_animation_rate = 1 - master_animations_f*tooltip_animations_f*pow_f32(2, (-60.f * rd_state->frame_dt)); } ////////////////////////////// diff --git a/src/raddbg/raddbg_core.h b/src/raddbg/raddbg_core.h index d155c441..8b6ba824 100644 --- a/src/raddbg/raddbg_core.h +++ b/src/raddbg/raddbg_core.h @@ -324,6 +324,9 @@ struct RD_WindowState CFG_ID query_last_bottom_view_id; RD_QueryView *query_top; + // rjf: panel 'hoisting' state - bring-to-front + CFG_ID panel_hoist_cfg_id; + // rjf: hover eval state B32 hover_eval_focused; Arena *hover_eval_arena; @@ -457,6 +460,7 @@ struct RD_State F32 catchall_animation_rate; F32 menu_animation_rate; F32 menu_animation_rate__slow; + F32 menu_animation_rate__very_slow; F32 entity_alive_animation_rate; F32 rich_hover_animation_rate; F32 scrolling_animation_rate; diff --git a/src/raddbg_server/raddbg_server_main.c b/src/raddbg_server/raddbg_server_main.c index 4374eee2..aa82857c 100644 --- a/src/raddbg_server/raddbg_server_main.c +++ b/src/raddbg_server/raddbg_server_main.c @@ -48,7 +48,7 @@ struct RDS_Msg { RDS_Msg *next; SOCK_Endpoint endpoint; - String8 msg_raw; + String8 packet; }; typedef struct RDS_Client RDS_Client; @@ -87,9 +87,6 @@ struct RDS_State Arena *c2d_arena; RDS_Msg *c2d_msg_first; RDS_Msg *c2d_msg_last; - - //- rjf: demon run state - B32 demon_is_running; }; global RDS_State *rds_state = 0; @@ -120,7 +117,7 @@ dmn_thread__entry_point(void *p) RDS_Msg *dst = push_array(scratch.arena, RDS_Msg, 1); SLLQueuePush(msg_first, msg_last, dst); dst->endpoint = src->endpoint; - dst->msg_raw = str8_copy(scratch.arena, src->msg_raw); + dst->packet = str8_copy(scratch.arena, src->packet); } arena_clear(rds_state->c2d_arena); rds_state->c2d_msg_first = rds_state->c2d_msg_last = 0; @@ -135,7 +132,7 @@ dmn_thread__entry_point(void *p) for(RDS_Msg *msg_n = msg_first; msg_n != 0; msg_n = msg_n->next) { //- rjf: unpack message - DS_Msg msg = ds_msg_from_packet(scratch.arena, msg_n->msg_raw); + DS_Msg msg = ds_msg_from_packet(scratch.arena, msg_n->packet); //- rjf: do action, get response DS_Response response = {0}; @@ -197,6 +194,7 @@ dmn_thread__entry_point(void *p) } //- rjf: pack response & send back to the originating endpoint of the message + if(msg_n->endpoint.port != 0) { String8 data = ds_packet_from_response(scratch.arena, &response); sock_send(rds_state->sock_session, SOCK_Protocol_TCP, msg_n->endpoint, data, max_U64); @@ -205,7 +203,7 @@ dmn_thread__entry_point(void *p) //- rjf: pack events & send to all connected client if(events.count != 0) { - String8 data = ds_serialized_from_dmn_events(scratch.arena, events); + String8 data = ds_packet_from_dmn_events(scratch.arena, events); for(RDS_Client *c = rds_state->first_client; c != 0; c = c->order_next) { sock_send(rds_state->sock_session, SOCK_Protocol_TCP, c->endpoint, data, max_U64); @@ -223,6 +221,8 @@ dmn_thread__entry_point(void *p) internal void entry_point(CmdLine *cmd_line) { + Temp scratch = scratch_begin(0, 0); + //- rjf: get port argument U64 port = 7273; { @@ -234,6 +234,42 @@ entry_point(CmdLine *cmd_line) } } + //- rjf: get launch targets from command line + typedef struct Target Target; + struct Target + { + Target *next; + String8List cmd_line; + }; + Target *first_target = 0; + Target *last_target = 0; + { + B32 past_first_non_flag = 0; + for(U64 idx = 1; idx < cmd_line->argc; idx += 1) + { + String8 arg = str8_cstring(cmd_line->argv[idx]); + B32 is_flag = (str8_match(str8_prefix(arg, 1), s("-"), 0) || + str8_match(str8_prefix(arg, 1), s("--"), 0) || + str8_match(str8_prefix(arg, 1), s("/"), 0)); + past_first_non_flag = (past_first_non_flag || !is_flag); + if(past_first_non_flag) + { + // rjf: create new target after ;s, or if we don't have one + if(str8_match(arg, s(";"), 0) || first_target == 0) + { + Target *t = push_array(scratch.arena, Target, 1); + SLLQueuePush(first_target, last_target, t); + } + + // rjf: push this string to the most recently added target + if(last_target != 0) + { + str8_list_push(scratch.arena, &last_target->cmd_line, arg); + } + } + } + } + //- rjf: set up shared state Arena *arena = arena_alloc(); rds_state = push_array(arena, RDS_State, 1); @@ -242,10 +278,41 @@ entry_point(CmdLine *cmd_line) rds_state->c2d_rw_mutex = rw_mutex_alloc(); rds_state->c2d_cv = cond_var_alloc(); rds_state->c2d_arena = arena_alloc(); + rds_state->client_slots_count = 64; + rds_state->client_slots = push_array(arena, RDS_ClientSlot, rds_state->client_slots_count); //- rjf: launch demon thread thread_launch(dmn_thread__entry_point, 0); + //- rjf: do initial launch of all command-line-specified targets + { + String8 current_path = get_current_path(scratch.arena); + for EachNode(t, Target, first_target) + { + fprintf(stderr, "[launching command line target]\n"); + fprintf(stderr, " "); + for EachNode(n, String8Node, t->cmd_line.first) + { + fprintf(stderr, " %.*s", str8_varg(n->string)); + } + fprintf(stderr, "\n"); + DS_Msg msg = + { + .kind = DS_MsgKind_Launch, + .command_line = t->cmd_line, + .path = current_path, + }; + String8 packet = ds_packet_from_msg(scratch.arena, &msg); + RWMutexScope(rds_state->c2d_rw_mutex, 1) + { + RDS_Msg *msg = push_array(rds_state->c2d_arena, RDS_Msg, 1); + msg->packet = str8_copy(rds_state->c2d_arena, packet); + SLLQueuePush(rds_state->c2d_msg_first, rds_state->c2d_msg_last, msg); + } + cond_var_broadcast(rds_state->c2d_cv); + } + } + //- rjf: loop: wait for messages, issue commands to demon for(;;) { @@ -318,15 +385,35 @@ entry_point(CmdLine *cmd_line) if(peek_kind < DS_MsgKind_Launch || DS_MsgKind_SingleStep < peek_kind) { DS_Msg msg = ds_msg_from_packet(scratch.arena, data); + + // rjf: form base response info DS_Response response = {0}; + response.msg_id = msg.msg_id; + response.good = 1; + + // rjf: do message specifics switch(msg.kind) { default:{}break; + + //- rjf: response + case DS_MsgKind_Handshake: + { + // TODO(rjf): send initial state + }break; + + //- rjf: halting case DS_MsgKind_Halt: { dmn_halt(0, 0); }break; } + + // rjf: send response + { + String8 packet = ds_packet_from_response(scratch.arena, &response); + sock_send(rds_state->sock_session, protocol, endpoint, packet, now_time_us()+10000000); + } } } @@ -335,14 +422,16 @@ entry_point(CmdLine *cmd_line) { RWMutexScope(rds_state->c2d_rw_mutex, 1) { - String8 msg_raw = str8_skip(data, sizeof(header)); RDS_Msg *msg = push_array(rds_state->c2d_arena, RDS_Msg, 1); msg->endpoint = endpoint; - msg->msg_raw = str8_copy(rds_state->c2d_arena, msg_raw); + msg->packet = str8_copy(rds_state->c2d_arena, data); + SLLQueuePush(rds_state->c2d_msg_first, rds_state->c2d_msg_last, msg); } cond_var_broadcast(rds_state->c2d_cv); } scratch_end(scratch); } + + scratch_end(scratch); }