float panels into config layer

This commit is contained in:
Ryan Fleury
2025-10-16 15:26:07 -07:00
parent 7844761748
commit 0f277d6e6e
7 changed files with 525 additions and 501 deletions
+1
View File
@@ -2,6 +2,7 @@
// Licensed under the MIT license (https://opensource.org/license/mit/)
#include "config_core.c"
#include "config_panels.c"
#if defined(OS_GFX_H)
# include "config_bindings.c"
#endif
+1
View File
@@ -5,6 +5,7 @@
#define CONFIG_INC_H
#include "config_core.h"
#include "config_panels.h"
#if defined(OS_GFX_H)
# include "config_bindings.h"
#endif
+217
View File
@@ -0,0 +1,217 @@
// Copyright (c) Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
internal CFG_Node *
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))
{
result = c;
break;
}
}
return result;
}
internal CFG_PanelTree
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_PanelNode *dst_root = &cfg_nil_panel_node;
CFG_PanelNode *dst_focused = &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;
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: extract cfg info
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)
{
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)
{
panel_has_children = 1;
}
else if(str8_match(src_child->string, str8_lit("tabs_on_bottom"), 0))
{
// NOTE(rjf): skip - this is a panel option.
}
else if(str8_match(src_child->string, str8_lit("selected"), 0))
{
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)
{
dst->selected_tab = src_child;
}
}
}
// rjf: recurse
rec = cfg_node_rec__depth_first(src_root, src);
if(!panel_has_children)
{
MemoryZeroStruct(&rec);
rec.next = &cfg_nil_node;
for(CFG_Node *p = src; p != src_root && p != &cfg_nil_node; p = p->parent, rec.pop_count += 1)
{
if(p->next != &cfg_nil_node)
{
rec.next = p->next;
break;
}
}
}
if(rec.push_count > 0)
{
dst_active_parent = dst;
active_split_axis = axis2_flip(active_split_axis);
}
else for(S32 pop_idx = 0; pop_idx < rec.pop_count; pop_idx += 1)
{
dst_active_parent = dst_active_parent->parent;
active_split_axis = axis2_flip(active_split_axis);
}
}
}
scratch_end(scratch);
CFG_PanelTree tree = {dst_root, dst_focused};
return tree;
}
internal CFG_PanelNodeRec
cfg_panel_node_rec__depth_first(CFG_PanelNode *root, CFG_PanelNode *panel, U64 sib_off, U64 child_off)
{
CFG_PanelNodeRec rec = {&cfg_nil_panel_node};
if(*MemberFromOffset(CFG_PanelNode **, panel, child_off) != &cfg_nil_panel_node)
{
rec.next = *MemberFromOffset(CFG_PanelNode **, panel, child_off);
rec.push_count += 1;
}
else for(CFG_PanelNode *p = panel; p != &cfg_nil_panel_node && p != root; p = p->parent, rec.pop_count += 1)
{
if(*MemberFromOffset(CFG_PanelNode **, p, sib_off) != &cfg_nil_panel_node)
{
rec.next = *MemberFromOffset(CFG_PanelNode **, p, sib_off);
break;
}
}
return rec;
}
internal CFG_PanelNode *
cfg_panel_node_from_tree_cfg(CFG_PanelNode *root, CFG_Node *cfg)
{
CFG_PanelNode *result = &cfg_nil_panel_node;
for(CFG_PanelNode *p = root;
p != &cfg_nil_panel_node;
p = cfg_panel_node_rec__depth_first_pre(root, p).next)
{
if(p->cfg == cfg)
{
result = p;
break;
}
}
return result;
}
internal Rng2F32
cfg_target_rect_from_panel_node_child(Rng2F32 parent_rect, CFG_PanelNode *parent, CFG_PanelNode *panel)
{
Rng2F32 rect = parent_rect;
if(parent != &cfg_nil_panel_node)
{
Vec2F32 parent_rect_size = dim_2f32(parent_rect);
Axis2 axis = parent->split_axis;
rect.p1.v[axis] = rect.p0.v[axis];
for(CFG_PanelNode *child = parent->first; child != &cfg_nil_panel_node; child = child->next)
{
rect.p1.v[axis] += parent_rect_size.v[axis] * child->pct_of_parent;
if(child == panel)
{
break;
}
rect.p0.v[axis] = rect.p1.v[axis];
}
//rect.p0.v[axis] += parent_rect_size.v[axis] * panel->off_pct_of_parent.v[axis];
//rect.p0.v[axis2_flip(axis)] += parent_rect_size.v[axis2_flip(axis)] * panel->off_pct_of_parent.v[axis2_flip(axis)];
}
rect.x0 = round_f32(rect.x0);
rect.x1 = round_f32(rect.x1);
rect.y0 = round_f32(rect.y0);
rect.y1 = round_f32(rect.y1);
return rect;
}
internal Rng2F32
cfg_target_rect_from_panel_node(Rng2F32 root_rect, CFG_PanelNode *root, CFG_PanelNode *panel)
{
Temp scratch = scratch_begin(0, 0);
// rjf: count ancestors
U64 ancestor_count = 0;
for(CFG_PanelNode *p = panel->parent; p != &cfg_nil_panel_node; p = p->parent)
{
ancestor_count += 1;
}
// rjf: gather ancestors
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)
{
ancestors[ancestor_idx] = p;
ancestor_idx += 1;
}
}
// rjf: go from highest ancestor => panel and calculate rect
Rng2F32 parent_rect = root_rect;
for(S64 ancestor_idx = (S64)ancestor_count-1;
0 <= ancestor_idx && ancestor_idx < ancestor_count;
ancestor_idx -= 1)
{
CFG_PanelNode *ancestor = ancestors[ancestor_idx];
CFG_PanelNode *parent = ancestor->parent;
if(parent != &cfg_nil_panel_node)
{
parent_rect = cfg_target_rect_from_panel_node_child(parent_rect, parent, ancestor);
}
}
// rjf: calculate final rect
Rng2F32 rect = cfg_target_rect_from_panel_node_child(parent_rect, panel->parent, panel);
scratch_end(scratch);
return rect;
}
+67
View File
@@ -0,0 +1,67 @@
// Copyright (c) Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef CONFIG_PANELS_H
#define CONFIG_PANELS_H
typedef struct CFG_PanelNode CFG_PanelNode;
struct CFG_PanelNode
{
// rjf: links data
CFG_PanelNode *first;
CFG_PanelNode *last;
CFG_PanelNode *next;
CFG_PanelNode *prev;
CFG_PanelNode *parent;
U64 child_count;
CFG_Node *cfg;
// rjf: split data
Axis2 split_axis;
F32 pct_of_parent;
// rjf: tab params
Side tab_side;
// rjf: which tabs are attached
CFG_NodePtrList tabs;
CFG_Node *selected_tab;
};
typedef struct CFG_PanelTree CFG_PanelTree;
struct CFG_PanelTree
{
CFG_PanelNode *root;
CFG_PanelNode *focused;
};
typedef struct CFG_PanelNodeRec CFG_PanelNodeRec;
struct CFG_PanelNodeRec
{
CFG_PanelNode *next;
S32 push_count;
S32 pop_count;
};
read_only global CFG_PanelNode cfg_nil_panel_node =
{
&cfg_nil_panel_node,
&cfg_nil_panel_node,
&cfg_nil_panel_node,
&cfg_nil_panel_node,
&cfg_nil_panel_node,
0,
&cfg_nil_node,
.selected_tab = &cfg_nil_node,
};
internal CFG_Node *cfg_window_from_cfg(CFG_Node *cfg);
internal CFG_PanelTree cfg_panel_tree_from_cfg(Arena *arena, CFG_Node *cfg_root);
internal CFG_PanelNodeRec cfg_panel_node_rec__depth_first(CFG_PanelNode *root, CFG_PanelNode *panel, U64 sib_off, U64 child_off);
#define cfg_panel_node_rec__depth_first_pre(root, p) cfg_panel_node_rec__depth_first((root), (p), OffsetOf(CFG_PanelNode, next), OffsetOf(CFG_PanelNode, first))
#define cfg_panel_node_rec__depth_first_pre_rev(root, p) cfg_panel_node_rec__depth_first((root), (p), OffsetOf(CFG_PanelNode, prev), OffsetOf(CFG_PanelNode, last))
internal CFG_PanelNode *cfg_panel_node_from_tree_cfg(CFG_PanelNode *root, CFG_Node *cfg);
internal Rng2F32 cfg_target_rect_from_panel_node_child(Rng2F32 parent_rect, CFG_PanelNode *parent, CFG_PanelNode *panel);
internal Rng2F32 cfg_target_rect_from_panel_node(Rng2F32 root_rect, CFG_PanelNode *root, CFG_PanelNode *panel);
#endif // CONFIG_PANELS_H
+238 -438
View File
File diff suppressed because it is too large Load Diff
-62
View File
@@ -207,48 +207,6 @@ struct RD_Location
String8 expr;
};
////////////////////////////////
//~ rjf: Structured Panel Trees, Parsed From Config Trees
typedef struct RD_PanelNode RD_PanelNode;
struct RD_PanelNode
{
// rjf: links data
RD_PanelNode *first;
RD_PanelNode *last;
RD_PanelNode *next;
RD_PanelNode *prev;
RD_PanelNode *parent;
U64 child_count;
CFG_Node *cfg;
// rjf: split data
Axis2 split_axis;
F32 pct_of_parent;
// rjf: tab params
Side tab_side;
// rjf: which tabs are attached
CFG_NodePtrList tabs;
CFG_Node *selected_tab;
};
typedef struct RD_PanelTree RD_PanelTree;
struct RD_PanelTree
{
RD_PanelNode *root;
RD_PanelNode *focused;
};
typedef struct RD_PanelNodeRec RD_PanelNodeRec;
struct RD_PanelNodeRec
{
RD_PanelNode *next;
S32 push_count;
S32 pop_count;
};
////////////////////////////////
//~ rjf: Command Types
@@ -554,18 +512,6 @@ struct RD_State
read_only global RD_VocabInfo rd_nil_vocab_info = {0};
read_only global RD_PanelNode rd_nil_panel_node =
{
&rd_nil_panel_node,
&rd_nil_panel_node,
&rd_nil_panel_node,
&rd_nil_panel_node,
&rd_nil_panel_node,
0,
&cfg_nil_node,
.selected_tab = &cfg_nil_node,
};
read_only global RD_CmdKindInfo rd_nil_cmd_kind_info = {0};
RD_VIEW_UI_FUNCTION_DEF(null);
@@ -626,14 +572,6 @@ internal RD_Regs *rd_get_hover_regs(void);
////////////////////////////////
//~ rjf: Config Functions
internal RD_PanelTree rd_panel_tree_from_cfg(Arena *arena, CFG_Node *cfg_root);
internal RD_PanelNodeRec rd_panel_node_rec__depth_first(RD_PanelNode *root, RD_PanelNode *panel, U64 sib_off, U64 child_off);
#define rd_panel_node_rec__depth_first_pre(root, p) rd_panel_node_rec__depth_first((root), (p), OffsetOf(RD_PanelNode, next), OffsetOf(RD_PanelNode, first))
#define rd_panel_node_rec__depth_first_pre_rev(root, p) rd_panel_node_rec__depth_first((root), (p), OffsetOf(RD_PanelNode, prev), OffsetOf(RD_PanelNode, last))
internal RD_PanelNode *rd_panel_node_from_tree_cfg(RD_PanelNode *root, CFG_Node *cfg);
internal Rng2F32 rd_target_rect_from_panel_node_child(Rng2F32 parent_rect, RD_PanelNode *parent, RD_PanelNode *panel);
internal Rng2F32 rd_target_rect_from_panel_node(Rng2F32 root_rect, RD_PanelNode *root, RD_PanelNode *panel);
internal B32 rd_cfg_is_project_filtered(CFG_Node *cfg);
internal Vec4F32 rd_hsva_from_cfg(CFG_Node *cfg);
+1 -1
View File
@@ -582,7 +582,7 @@ entry_point(CmdLine *cmd_line)
if(dst_ws->cfg_id != rd_regs()->window)
{
Temp scratch = scratch_begin(0, 0);
RD_PanelTree panel_tree = rd_panel_tree_from_cfg(scratch.arena, cfg_node_from_id(dst_ws->cfg_id));
CFG_PanelTree panel_tree = cfg_panel_tree_from_cfg(scratch.arena, cfg_node_from_id(dst_ws->cfg_id));
rd_regs()->window = dst_ws->cfg_id;
rd_regs()->panel = panel_tree.focused->cfg->id;
rd_regs()->tab = panel_tree.focused->selected_tab->id;