diff --git a/4ed.cpp b/4ed.cpp index c6b9d1c9..32ba4d9a 100644 --- a/4ed.cpp +++ b/4ed.cpp @@ -20,7 +20,7 @@ enum App_State{ struct App_State_Resizing{ Panel_Divider *divider; - i32 min, max; + f32 min, max; }; struct CLI_Process{ @@ -797,9 +797,14 @@ COMMAND_DECL(open_panel_vsplit){ panel2->screen_region = panel1->screen_region; - panel2->full.x0 = split.divider->pos; + i32 x_pos = ROUND32(lerp((f32)panel1->full.x0, + split.divider->pos, + (f32)panel1->full.x1) + ); + + panel2->full.x0 = x_pos; panel2->full.x1 = panel1->full.x1; - panel1->full.x1 = split.divider->pos; + panel1->full.x1 = x_pos; panel_fix_internal_area(panel1); panel_fix_internal_area(panel2); @@ -823,9 +828,14 @@ COMMAND_DECL(open_panel_hsplit){ panel2->screen_region = panel1->screen_region; - panel2->full.y0 = split.divider->pos; + i32 y_pos = ROUND32(lerp((f32)panel1->full.y0, + split.divider->pos, + (f32)panel1->full.y1) + ); + + panel2->full.y0 = y_pos; panel2->full.y1 = panel1->full.y1; - panel1->full.y1 = split.divider->pos; + panel1->full.y1 = y_pos; panel_fix_internal_area(panel1); panel_fix_internal_area(panel2); @@ -2697,26 +2707,22 @@ App_Step_Sig(app_step){ Divider_And_ID div = layout_get_divider(&models->layout, mouse_divider_id); vars->resizing.divider = div.divider; - i32 min, max; + f32 min = 0; + f32 max = 0; { - i32 mid, MIN, MAX; - mid = div.divider->pos; + f32 mid = layout_get_position(&models->layout, mouse_divider_id); if (mouse_divider_vertical){ - MIN = 0; - MAX = MIN + models->layout.full_width; + max = (f32)models->layout.full_width; } else{ - MIN = 0; - MAX = MIN + models->layout.full_height; + max = (f32)models->layout.full_height; } - min = MIN; - max = MAX; i32 divider_id = div.id; do{ Divider_And_ID other_div = layout_get_divider(&models->layout, divider_id); b32 divider_match = (other_div.divider->v_divider == mouse_divider_vertical); - i32 pos = other_div.divider->pos; + f32 pos = layout_get_position(&models->layout, divider_id); if (divider_match && pos > mid && pos < max){ max = pos; } @@ -2732,9 +2738,10 @@ App_Step_Sig(app_step){ divider_stack[top++] = div.id; while (top > 0){ - Divider_And_ID other_div = layout_get_divider(&models->layout, divider_stack[--top]); + --top; + Divider_And_ID other_div = layout_get_divider(&models->layout, divider_stack[top]); b32 divider_match = (other_div.divider->v_divider == mouse_divider_vertical); - i32 pos = other_div.divider->pos; + f32 pos = layout_get_position(&models->layout, divider_stack[top]); if (divider_match && pos > mid && pos < max){ max = pos; } @@ -2752,8 +2759,8 @@ App_Step_Sig(app_step){ end_temp_memory(temp); } - vars->resizing.min = min; - vars->resizing.max = max; + vars->resizing.min = 0.f; + vars->resizing.max = 1.f; } }break; @@ -2761,12 +2768,14 @@ App_Step_Sig(app_step){ { if (input->mouse.l){ Panel_Divider *divider = vars->resizing.divider; + i32 pos = 0; if (divider->v_divider){ - divider->pos = mx; + pos = clamp(0, mx, models->layout.full_width); } else{ - divider->pos = my; + pos = clamp(0, my, models->layout.full_height); } + divider->pos = layout_compute_position(&models->layout, divider, pos); if (divider->pos < vars->resizing.min){ divider->pos = vars->resizing.min; diff --git a/4ed_layout.cpp b/4ed_layout.cpp index cd410f22..d8776f39 100644 --- a/4ed_layout.cpp +++ b/4ed_layout.cpp @@ -15,7 +15,7 @@ struct Panel_Divider{ i32 which_child; i32 child1, child2; b32 v_divider; - i32 pos; + f32 pos; }; struct Screen_Region{ @@ -188,11 +188,13 @@ layout_split_panel(Editing_Layout *layout, Panel *panel, b32 vertical){ div.divider->which_child = panel->which_child; if (vertical){ div.divider->v_divider = 1; - div.divider->pos = (panel->full.x0 + panel->full.x1) / 2; + //div.divider->pos = (panel->full.x0 + panel->full.x1) / 2; + div.divider->pos = 0.5f; } else{ div.divider->v_divider = 0; - div.divider->pos = (panel->full.y0 + panel->full.y1) / 2; + //div.divider->pos = (panel->full.y0 + panel->full.y1) / 2; + div.divider->pos = 0.5f; } new_panel = layout_alloc_panel(layout); @@ -215,64 +217,111 @@ panel_fix_internal_area(Panel *panel){ panel->inner.y1 = panel->full.y1 - panel->b_margin; } +internal i32_Rect +layout_get_rect(Editing_Layout *layout, i32 id, i32 which_child){ + i32 divider_chain[16]; + i32 chain_count = 0; + + Panel_Divider *dividers = layout->dividers; + Panel_Divider *original_div = dividers + id; + i32 root = layout->root; + + Assert(0 <= id && id <= layout->panel_max_count - 1); + + divider_chain[chain_count++] = id; + for (;id != root;){ + Panel_Divider *div = dividers + id; + id = div->parent; + divider_chain[chain_count++] = id; + } + + i32_Rect r = i32R(0, 0, layout->full_width, layout->full_height); + + for (i32 i = chain_count-1; i > 0; --i){ + Panel_Divider *div = dividers + divider_chain[i]; + if (div->v_divider){ + if (div->child1 == divider_chain[i-1]){ + r.x1 = ROUND32(lerp((f32)r.x0, + div->pos, + (f32)r.x1)); + } + else{ + r.x0 = ROUND32(lerp((f32)r.x0, + div->pos, + (f32)r.x1)); + } + } + else{ + if (div->child1 == divider_chain[i-1]){ + r.y1 = ROUND32(lerp((f32)r.y0, + div->pos, + (f32)r.y1)); + } + else{ + r.y0 = ROUND32(lerp((f32)r.y0, + div->pos, + (f32)r.y1)); + } + } + } + + switch (which_child){ + case 1: + { + if (original_div->v_divider){ + r.x0 = ROUND32(lerp((f32)r.x0, + original_div->pos, + (f32)r.x1)); + } + else{ + r.y0 = ROUND32(lerp((f32)r.y0, + original_div->pos, + (f32)r.y1)); + } + }break; + + case -1: + { + if (original_div->v_divider){ + r.x1 = ROUND32(lerp((f32)r.x0, + original_div->pos, + (f32)r.x1)); + } + else{ + r.y1 = ROUND32(lerp((f32)r.y0, + original_div->pos, + (f32)r.y1)); + } + }break; + } + + return(r); +} + +internal i32_Rect +layout_get_panel_rect(Editing_Layout *layout, Panel *panel){ + Assert(layout->panel_count > 1); + + i32_Rect r = layout_get_rect(layout, panel->parent, panel->which_child); + + return(r); +} + internal void layout_fix_all_panels(Editing_Layout *layout){ Panel *panel; - Panel_Divider *dividers = layout->dividers; + Panel_Divider *dividers = layout->dividers; AllowLocal(dividers); i32 panel_count = layout->panel_count; - i32_Rect r; - i32 pos, which_child, action; - Divider_And_ID div; if (panel_count > 1){ for (panel = layout->used_sentinel.next; - panel != &layout->used_sentinel; - panel = panel->next){ - - r.x0 = 0; - r.x1 = r.x0 + layout->full_width; - r.y0 = 0; - r.y1 = r.y0 + layout->full_height; - - which_child = panel->which_child; - - div.id = panel->parent; - - for (;;){ - Assert(div.id != -1); - div.divider = dividers + div.id; - pos = div.divider->pos; - - action = (div.divider->v_divider << 1) | (which_child > 0); - switch (action){ - case 0: // v_divider : 0, which_child : -1 - if (pos < r.y1) r.y1 = pos; - break; - case 1: // v_divider : 0, which_child : 1 - if (pos > r.y0) r.y0 = pos; - break; - case 2: // v_divider : 1, which_child : -1 - if (pos < r.x1) r.x1 = pos; - break; - case 3: // v_divider : 1, which_child : 1 - if (pos > r.x0) r.x0 = pos; - break; - } - - if (div.id != layout->root){ - div.id = div.divider->parent; - which_child = div.divider->which_child; - } - else{ - break; - } - } - - panel->full = r; + panel != &layout->used_sentinel; + panel = panel->next){ + panel->full = layout_get_panel_rect(layout, panel); panel_fix_internal_area(panel); } } - + else{ panel = layout->used_sentinel.next; panel->full.x0 = 0; @@ -289,29 +338,60 @@ layout_refit(Editing_Layout *layout, i32 prev_width, i32 prev_height){ Panel_Divider *dividers = layout->dividers; i32 max = layout->panel_max_count - 1; - f32 h_ratio, v_ratio; - Panel_Divider *divider = dividers; - i32 i; - + if (layout->panel_count > 1){ Assert(prev_width != 0 && prev_height != 0); - - h_ratio = ((f32)layout->full_width) / prev_width; - v_ratio = ((f32)layout->full_height) / prev_height; - - for (i = 0; i < max; ++i, ++divider){ + + for (i32 i = 0; i < max; ++i, ++divider){ if (divider->v_divider){ - divider->pos = ROUND32((divider->pos) * h_ratio); + divider->pos = divider->pos; } else{ - divider->pos = ROUND32((divider->pos) * v_ratio); + divider->pos = divider->pos; } } } - + layout_fix_all_panels(layout); } +internal f32 +layout_get_position(Editing_Layout *layout, i32 id){ + Panel_Divider *dividers = layout->dividers; + Panel_Divider *original_div = dividers + id; + + i32_Rect r = layout_get_rect(layout, id, 0); + f32 pos = 0; + if (original_div->v_divider){ + pos = lerp((f32)r.x0, original_div->pos, (f32)r.x1); + } + else{ + pos = lerp((f32)r.y0, original_div->pos, (f32)r.y1); + } + + return(pos); +} + +internal f32 +layout_compute_position(Editing_Layout *layout, Panel_Divider *divider, i32 pos){ + Panel_Divider *dividers = layout->dividers; + Panel_Divider *original_div = divider; + i32 id = (i32)(divider - dividers); + + i32_Rect r = layout_get_rect(layout, id, 0); + f32 l = 0; + if (original_div->v_divider){ + l = unlerp((f32)r.x0, (f32)pos, (f32)r.x1); + } + else{ + l = unlerp((f32)r.y0, (f32)pos, (f32)r.y1); + } + + Assert(0.f <= l && l <= 1.f); + + return(l); +} + // BOTTOM