Skip to content

Commit b373115

Browse files
committed
Right-aligned viewport render toggles with per-flag colors; reshape UI workspace layout
1 parent ada1ff0 commit b373115

2 files changed

Lines changed: 92 additions & 30 deletions

File tree

crates/renzora_ui/src/layouts.rs

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -312,36 +312,33 @@ fn layout_shaders() -> DockTree {
312312
}
313313

314314
/// Physics: Hierarchy | Viewport+all physics tabs | Inspector+Shapes
315-
/// UI: Hierarchy+WidgetLibrary | Canvas+Console | UiInspector+Assets
315+
/// UI: Hierarchy | Assets | WidgetLibrary (left) | UI Canvas (center) | UiInspector+Inspector (right)
316316
fn layout_ui() -> DockTree {
317317
DockTree::horizontal(
318-
// Left: hierarchy on top, widget palette below
318+
// Left: hierarchy on top, assets in the middle, widget palette at the bottom.
319319
DockTree::vertical(
320320
DockTree::leaf("hierarchy"),
321-
DockTree::leaf("widget_library"),
322-
0.6,
323-
),
324-
DockTree::horizontal(
325-
// Center: UI canvas on top, assets+console below
326321
DockTree::vertical(
327-
DockTree::Leaf {
328-
tabs: vec!["ui_canvas".into(), "viewport".into()],
329-
active_tab: 0,
330-
},
331-
DockTree::Leaf {
332-
tabs: vec!["assets".into(), "console".into()],
333-
active_tab: 0,
334-
},
335-
0.75,
322+
DockTree::leaf("assets"),
323+
DockTree::leaf("widget_library"),
324+
0.5,
336325
),
337-
// Right: UI inspector + scene inspector
326+
0.4,
327+
),
328+
DockTree::horizontal(
329+
// Center: UI canvas fills the full column.
330+
DockTree::Leaf {
331+
tabs: vec!["ui_canvas".into(), "viewport".into()],
332+
active_tab: 0,
333+
},
334+
// Right: UI inspector + scene inspector (narrower column).
338335
DockTree::Leaf {
339336
tabs: vec!["ui_inspector".into(), "inspector".into()],
340337
active_tab: 0,
341338
},
342-
0.75,
339+
0.82,
343340
),
344-
0.15,
341+
0.16,
345342
)
346343
}
347344

crates/renzora_viewport/src/header.rs

Lines changed: 76 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -86,16 +86,21 @@ pub fn viewport_header(ui: &mut egui::Ui, world: &World) {
8686
// tool, so they don't get hidden by the mode-specific drawers below.
8787
let actions_w = render_left_actions(ui, world, cmds, theme, inner, hovered);
8888

89+
// Right-aligned render-flag toggles (Textures/Wireframe/Lighting/Shadows).
90+
// Also fixed; they sit on the far right and stay put across mode changes.
91+
let toggles_w = render_right_toggles(ui, settings, cmds, theme, inner, hovered);
92+
8993
// Render once per frame at a centered rect of the last measured width.
9094
// Two-pass rendering was doubling popups (sizing pass still spawned Areas).
9195
let width_id = ui.id().with("viewport_header_width");
9296
let cached_w: f32 = ui.memory(|m| m.data.get_temp(width_id)).unwrap_or(600.0);
9397
// Shrink the available-for-centering width so the centered strip never
94-
// overlaps the left action buttons.
98+
// overlaps the left actions or the right toggles.
9599
let centering_min_x = inner.min.x + actions_w + 8.0;
96-
let available_for_center = (inner.max.x - centering_min_x).max(0.0);
100+
let centering_max_x = inner.max.x - toggles_w - 8.0;
101+
let available_for_center = (centering_max_x - centering_min_x).max(0.0);
97102
let content_w = cached_w.min(available_for_center);
98-
let centering_center_x = (centering_min_x + inner.max.x) / 2.0;
103+
let centering_center_x = (centering_min_x + centering_max_x) / 2.0;
99104
let content_x = centering_center_x - content_w / 2.0;
100105
let centered_rect = Rect::from_min_size(
101106
egui::Pos2::new(content_x, inner.min.y),
@@ -162,14 +167,8 @@ fn render_strip_contents(
162167
return;
163168
}
164169

165-
// ── Render flag toggles (textures/wireframe/lighting/shadows) ─────────────
166-
let t = &settings.render_toggles;
167-
toggle_btn(ui, IMAGE, t.textures, "Textures", active, inactive, hovered, cmds, |s| &mut s.render_toggles.textures);
168-
toggle_btn(ui, POLYGON, t.wireframe, "Wireframe", active, inactive, hovered, cmds, |s| &mut s.render_toggles.wireframe);
169-
toggle_btn(ui, SUN, t.lighting, "Lighting", active, inactive, hovered, cmds, |s| &mut s.render_toggles.lighting);
170-
toggle_btn(ui, CLOUD, t.shadows, "Shadows", active, inactive, hovered, cmds, |s| &mut s.render_toggles.shadows);
171-
172-
separator(ui);
170+
// Note: render-flag toggles (Textures/Wireframe/Lighting/Shadows) have
171+
// moved to the right-aligned strip in `render_right_toggles`.
173172

174173
// ── Overlay toggles (grid, axis gizmo) ────────────────────────────────────
175174
toggle_btn(ui, GRID_FOUR, settings.show_grid, "Grid", active, inactive, hovered, cmds, |s| &mut s.show_grid);
@@ -474,6 +473,72 @@ fn render_left_actions(
474473
(x - inner.min.x).max(0.0)
475474
}
476475

476+
/// Right-aligned render-flag toggle strip. Styled like the left actions: no
477+
/// background fill by default, `hovered_bg` on hover. Toggled state is shown
478+
/// by tinting the icon with the theme accent instead of painting a bg rect.
479+
/// Returns the total width consumed so the centered strip can make room.
480+
fn render_right_toggles(
481+
ui: &mut egui::Ui,
482+
settings: &ViewportSettings,
483+
cmds: &EditorCommands,
484+
theme: &renzora_theme::Theme,
485+
inner: Rect,
486+
hovered_bg: Color32,
487+
) -> f32 {
488+
let t = &settings.render_toggles;
489+
// Per-toggle "on" color so each flag has a recognizable identity.
490+
const TEXTURES_ON: Color32 = Color32::from_rgb(120, 200, 255); // cyan
491+
const WIREFRAME_ON: Color32 = Color32::from_rgb(130, 220, 140); // green
492+
const LIGHTING_ON: Color32 = Color32::from_rgb(245, 205, 90); // yellow
493+
const SHADOWS_ON: Color32 = Color32::from_rgb(180, 150, 230); // purple
494+
495+
let entries: &[(&str, bool, &str, fn(&mut ViewportSettings) -> &mut bool, &str, Color32)] = &[
496+
(IMAGE, t.textures, "Textures", |s| &mut s.render_toggles.textures, "vp_hdr_tog_tex", TEXTURES_ON),
497+
(POLYGON, t.wireframe, "Wireframe", |s| &mut s.render_toggles.wireframe, "vp_hdr_tog_wire", WIREFRAME_ON),
498+
(SUN, t.lighting, "Lighting", |s| &mut s.render_toggles.lighting, "vp_hdr_tog_light", LIGHTING_ON),
499+
(CLOUD, t.shadows, "Shadows", |s| &mut s.render_toggles.shadows, "vp_hdr_tog_shadow", SHADOWS_ON),
500+
];
501+
502+
let btn_size = Vec2::new(26.0, BTN_H);
503+
let gap = 2.0;
504+
let total_w = entries.len() as f32 * btn_size.x + (entries.len() as f32 - 1.0).max(0.0) * gap;
505+
506+
let icon_muted = theme.text.secondary.to_color32();
507+
let y = inner.min.y;
508+
let mut x = inner.max.x - total_w;
509+
510+
for (icon, is_on, tip, field, id_salt, on_color) in entries {
511+
let rect = Rect::from_min_size(Pos2::new(x, y), btn_size);
512+
let resp = ui.interact(rect, ui.id().with(*id_salt), Sense::click());
513+
if resp.hovered() {
514+
ui.ctx().set_cursor_icon(egui::CursorIcon::PointingHand);
515+
ui.painter().rect_filled(rect, CornerRadius::same(3), hovered_bg);
516+
}
517+
let glyph_color = if *is_on { *on_color } else { icon_muted };
518+
ui.painter().text(
519+
rect.center(),
520+
egui::Align2::CENTER_CENTER,
521+
icon,
522+
FontId::proportional(14.0),
523+
glyph_color,
524+
);
525+
let tip_full = format!("{}: {}", tip, if *is_on { "ON" } else { "OFF" });
526+
resp.clone().on_hover_text(tip_full);
527+
if resp.clicked() {
528+
let field = *field;
529+
cmds.push(move |w: &mut World| {
530+
if let Some(mut s) = w.get_resource_mut::<ViewportSettings>() {
531+
let v = field(&mut s);
532+
*v = !*v;
533+
}
534+
});
535+
}
536+
x += btn_size.x + gap;
537+
}
538+
539+
total_w
540+
}
541+
477542
fn toggle_btn(
478543
ui: &mut egui::Ui, icon: &str, is_on: bool, tip: &str,
479544
active: Color32, inactive: Color32, hovered: Color32,

0 commit comments

Comments
 (0)