feat(editor): integrate docking into editor_demo
Add full-frame-cycle integration test to dock.rs (16 tests total) and update editor_demo to use DockTree layout instead of a single panel. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -531,4 +531,28 @@ mod tests {
|
|||||||
let first_bg = &ui.draw_list.vertices[0];
|
let first_bg = &ui.draw_list.vertices[0];
|
||||||
assert_eq!(first_bg.color, [40, 40, 40, 255]);
|
assert_eq!(first_bg.color, [40, 40, 40, 255]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_full_frame_cycle() {
|
||||||
|
let mut dock = DockTree::new(
|
||||||
|
DockNode::split(Axis::Horizontal, 0.3,
|
||||||
|
DockNode::Leaf { tabs: vec![0, 1], active: 0 },
|
||||||
|
DockNode::split(Axis::Vertical, 0.6, DockNode::leaf(vec![2]), DockNode::leaf(vec![3])),
|
||||||
|
),
|
||||||
|
vec!["Hierarchy", "Inspector", "Viewport", "Console"],
|
||||||
|
);
|
||||||
|
let mut ui = UiContext::new(1280.0, 720.0);
|
||||||
|
for _ in 0..3 {
|
||||||
|
ui.begin_frame(100.0, 100.0, false);
|
||||||
|
let areas = dock.layout(Rect { x: 0.0, y: 0.0, w: 1280.0, h: 720.0 });
|
||||||
|
dock.update(100.0, 100.0, false);
|
||||||
|
dock.draw_chrome(&mut ui);
|
||||||
|
assert_eq!(areas.len(), 3);
|
||||||
|
for (_, r) in &areas {
|
||||||
|
assert!(r.w > 0.0);
|
||||||
|
assert!(r.h > 0.0);
|
||||||
|
}
|
||||||
|
ui.end_frame();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use winit::{
|
|||||||
};
|
};
|
||||||
use voltex_platform::{VoltexWindow, WindowConfig, InputState, GameTimer};
|
use voltex_platform::{VoltexWindow, WindowConfig, InputState, GameTimer};
|
||||||
use voltex_renderer::GpuContext;
|
use voltex_renderer::GpuContext;
|
||||||
use voltex_editor::{UiContext, UiRenderer};
|
use voltex_editor::{UiContext, UiRenderer, DockTree, DockNode, Axis, Rect, LayoutState};
|
||||||
|
|
||||||
struct EditorDemoApp {
|
struct EditorDemoApp {
|
||||||
state: Option<AppState>,
|
state: Option<AppState>,
|
||||||
@@ -20,6 +20,7 @@ struct AppState {
|
|||||||
timer: GameTimer,
|
timer: GameTimer,
|
||||||
ui: UiContext,
|
ui: UiContext,
|
||||||
ui_renderer: UiRenderer,
|
ui_renderer: UiRenderer,
|
||||||
|
dock: DockTree,
|
||||||
// Widget state
|
// Widget state
|
||||||
counter: u32,
|
counter: u32,
|
||||||
speed: f32,
|
speed: f32,
|
||||||
@@ -48,6 +49,19 @@ impl ApplicationHandler for EditorDemoApp {
|
|||||||
&ui.font,
|
&ui.font,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let dock = DockTree::new(
|
||||||
|
DockNode::split(
|
||||||
|
Axis::Horizontal, 0.25,
|
||||||
|
DockNode::leaf(vec![0]),
|
||||||
|
DockNode::split(
|
||||||
|
Axis::Vertical, 0.7,
|
||||||
|
DockNode::leaf(vec![1]),
|
||||||
|
DockNode::Leaf { tabs: vec![2, 3], active: 0 },
|
||||||
|
),
|
||||||
|
),
|
||||||
|
vec!["Debug", "Viewport", "Properties", "Console"],
|
||||||
|
);
|
||||||
|
|
||||||
self.state = Some(AppState {
|
self.state = Some(AppState {
|
||||||
window,
|
window,
|
||||||
gpu,
|
gpu,
|
||||||
@@ -55,6 +69,7 @@ impl ApplicationHandler for EditorDemoApp {
|
|||||||
timer: GameTimer::new(60),
|
timer: GameTimer::new(60),
|
||||||
ui,
|
ui,
|
||||||
ui_renderer,
|
ui_renderer,
|
||||||
|
dock,
|
||||||
counter: 0,
|
counter: 0,
|
||||||
speed: 5.0,
|
speed: 5.0,
|
||||||
show_grid: true,
|
show_grid: true,
|
||||||
@@ -128,20 +143,43 @@ impl ApplicationHandler for EditorDemoApp {
|
|||||||
state.ui.begin_frame(mx as f32, my as f32, mouse_down);
|
state.ui.begin_frame(mx as f32, my as f32, mouse_down);
|
||||||
|
|
||||||
|
|
||||||
// Draw widgets inside a panel
|
// Dock layout
|
||||||
state.ui.begin_panel("Debug", 10.0, 10.0, 250.0, 400.0);
|
let screen_w = state.gpu.config.width as f32;
|
||||||
state.ui.text("Voltex Editor Demo");
|
let screen_h = state.gpu.config.height as f32;
|
||||||
state.ui.text(&format!("FPS: {:.0}", fps));
|
let areas = state.dock.layout(Rect { x: 0.0, y: 0.0, w: screen_w, h: screen_h });
|
||||||
|
state.dock.update(mx as f32, my as f32, mouse_down);
|
||||||
|
state.dock.draw_chrome(&mut state.ui);
|
||||||
|
|
||||||
if state.ui.button("Click Me") {
|
for (panel_id, rect) in &areas {
|
||||||
state.counter += 1;
|
state.ui.layout = LayoutState::new(rect.x + 4.0, rect.y + 4.0);
|
||||||
|
match panel_id {
|
||||||
|
0 => {
|
||||||
|
state.ui.text("Debug Panel");
|
||||||
|
state.ui.text(&format!("FPS: {:.0}", fps));
|
||||||
|
if state.ui.button("Click Me") {
|
||||||
|
state.counter += 1;
|
||||||
|
}
|
||||||
|
state.ui.text(&format!("Count: {}", state.counter));
|
||||||
|
state.speed = state.ui.slider("Speed", state.speed, 0.0, 10.0);
|
||||||
|
state.show_grid = state.ui.checkbox("Show Grid", state.show_grid);
|
||||||
|
}
|
||||||
|
1 => {
|
||||||
|
state.ui.text("Viewport");
|
||||||
|
state.ui.text("(3D scene here)");
|
||||||
|
}
|
||||||
|
2 => {
|
||||||
|
state.ui.text("Properties");
|
||||||
|
state.ui.text(&format!("Speed: {:.1}", state.speed));
|
||||||
|
state.ui.text(&format!("Grid: {}", state.show_grid));
|
||||||
|
}
|
||||||
|
3 => {
|
||||||
|
state.ui.text("Console");
|
||||||
|
state.ui.text("> Ready.");
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
state.ui.text(&format!("Clicked: {}", state.counter));
|
|
||||||
|
|
||||||
state.speed = state.ui.slider("Speed", state.speed, 0.0, 10.0);
|
|
||||||
state.show_grid = state.ui.checkbox("Show Grid", state.show_grid);
|
|
||||||
|
|
||||||
state.ui.end_panel();
|
|
||||||
state.ui.end_frame();
|
state.ui.end_frame();
|
||||||
|
|
||||||
// Acquire surface texture
|
// Acquire surface texture
|
||||||
|
|||||||
Reference in New Issue
Block a user