Early UI work.
This commit is contained in:
247
lib/ui/examples/explicit_ui_prototype.rs
Normal file
247
lib/ui/examples/explicit_ui_prototype.rs
Normal file
@@ -0,0 +1,247 @@
|
||||
use ruin_reactivity::{Cell, cell};
|
||||
use ruin_ui::{
|
||||
Color, PlatformEvent, Point, PreparedText, Rect, SceneSnapshot, UiRuntime, UiSize,
|
||||
WindowController, WindowSpec, WindowUpdate,
|
||||
};
|
||||
use tracing_subscriber::layer::SubscriberExt;
|
||||
use tracing_subscriber::util::SubscriberInitExt;
|
||||
use tracing_subscriber::{EnvFilter, fmt};
|
||||
|
||||
fn install_tracing() {
|
||||
let filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| {
|
||||
EnvFilter::new(
|
||||
"info,ruin_runtime::runtime=debug,ruin_ui::platform=debug,ruin_reactivity::effect=debug",
|
||||
)
|
||||
});
|
||||
|
||||
let fmt_layer = fmt::layer()
|
||||
.with_target(true)
|
||||
.with_thread_ids(true)
|
||||
.with_thread_names(true)
|
||||
.compact();
|
||||
|
||||
let _ = tracing_subscriber::registry()
|
||||
.with(filter)
|
||||
.with(fmt_layer)
|
||||
.try_init();
|
||||
}
|
||||
|
||||
fn log_platform_event(event: &PlatformEvent) {
|
||||
match event {
|
||||
PlatformEvent::Opened { window_id } => {
|
||||
tracing::info!(event = "window_opened", window_id = window_id.raw());
|
||||
}
|
||||
PlatformEvent::Configured {
|
||||
window_id,
|
||||
configuration,
|
||||
} => {
|
||||
tracing::info!(
|
||||
event = "window_configured",
|
||||
window_id = window_id.raw(),
|
||||
width = configuration.actual_inner_size.width,
|
||||
height = configuration.actual_inner_size.height,
|
||||
visible = configuration.visible,
|
||||
"window configured"
|
||||
);
|
||||
}
|
||||
PlatformEvent::VisibilityChanged { window_id, visible } => {
|
||||
tracing::info!(
|
||||
event = "visibility_changed",
|
||||
window_id = window_id.raw(),
|
||||
visible,
|
||||
"window visibility changed"
|
||||
);
|
||||
}
|
||||
PlatformEvent::FramePresented {
|
||||
window_id,
|
||||
scene_version,
|
||||
item_count,
|
||||
} => {
|
||||
tracing::info!(
|
||||
event = "frame_presented",
|
||||
window_id = window_id.raw(),
|
||||
scene_version,
|
||||
item_count,
|
||||
"headless backend presented scene"
|
||||
);
|
||||
}
|
||||
PlatformEvent::Closed { window_id } => {
|
||||
tracing::info!(event = "window_closed", window_id = window_id.raw());
|
||||
}
|
||||
PlatformEvent::CloseRequested { window_id } => {
|
||||
tracing::info!(
|
||||
event = "close_requested",
|
||||
window_id = window_id.raw(),
|
||||
"compositor-like close request received"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn attach_window_scene(window: &WindowController) -> (Cell<usize>, ruin_reactivity::EffectHandle) {
|
||||
let counter = cell(0usize);
|
||||
let scene_window = window.clone();
|
||||
let scene_effect = scene_window.attach_scene_effect({
|
||||
let counter = counter.clone();
|
||||
move || {
|
||||
let version = counter.get() as u64 + 1;
|
||||
let value = counter.get();
|
||||
let mut scene = SceneSnapshot::new(version, UiSize::new(640.0, 360.0));
|
||||
scene
|
||||
.push_quad(
|
||||
Rect::new(0.0, 0.0, 640.0, 360.0),
|
||||
Color::rgb(0x12, 0x19, 0x28),
|
||||
)
|
||||
.push_quad(
|
||||
Rect::new(24.0, 24.0, 592.0, 64.0),
|
||||
Color::rgb(0x2B, 0x3A, 0x67),
|
||||
)
|
||||
.push_text(PreparedText::monospace(
|
||||
format!("RUIN explicit prototype | counter = {value}"),
|
||||
Point::new(40.0, 64.0),
|
||||
18.0,
|
||||
9.0,
|
||||
Color::rgb(0xFF, 0xFF, 0xFF),
|
||||
));
|
||||
scene
|
||||
}
|
||||
});
|
||||
|
||||
(counter, scene_effect)
|
||||
}
|
||||
|
||||
#[ruin_runtime::async_main]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
install_tracing();
|
||||
|
||||
tracing::info!(
|
||||
event = "prototype_start",
|
||||
"starting explicit-construction UI prototype with a headless backend"
|
||||
);
|
||||
|
||||
let mut ui = UiRuntime::headless();
|
||||
let window = ui.create_window(
|
||||
WindowSpec::new("RUIN Explicit Prototype")
|
||||
.app_id("dev.ruin.prototype")
|
||||
.requested_inner_size(UiSize::new(640.0, 360.0)),
|
||||
)?;
|
||||
let (counter, _scene_effect) = attach_window_scene(&window);
|
||||
let _ = counter.set(1);
|
||||
let _ = counter.set(2);
|
||||
let _ = counter.set(3);
|
||||
|
||||
let event = ui
|
||||
.wait_for_event_matching(|event| {
|
||||
matches!(
|
||||
event,
|
||||
PlatformEvent::Configured { window_id, .. } if *window_id == window.id()
|
||||
)
|
||||
})
|
||||
.await?;
|
||||
log_platform_event(&event);
|
||||
|
||||
let event = ui
|
||||
.wait_for_event_matching(
|
||||
|event| matches!(event, PlatformEvent::Opened { window_id } if *window_id == window.id()),
|
||||
)
|
||||
.await?;
|
||||
log_platform_event(&event);
|
||||
|
||||
let event = ui
|
||||
.wait_for_event_matching(|event| {
|
||||
matches!(
|
||||
event,
|
||||
PlatformEvent::FramePresented {
|
||||
window_id,
|
||||
scene_version: 4,
|
||||
..
|
||||
} if *window_id == window.id()
|
||||
)
|
||||
})
|
||||
.await?;
|
||||
log_platform_event(&event);
|
||||
|
||||
window.update(WindowUpdate::new().visible(false))?;
|
||||
let event = ui
|
||||
.wait_for_event_matching(|event| {
|
||||
matches!(
|
||||
event,
|
||||
PlatformEvent::VisibilityChanged {
|
||||
window_id,
|
||||
visible: false,
|
||||
} if *window_id == window.id()
|
||||
)
|
||||
})
|
||||
.await?;
|
||||
log_platform_event(&event);
|
||||
|
||||
window.update(WindowUpdate::new().visible(true))?;
|
||||
let event = ui
|
||||
.wait_for_event_matching(|event| {
|
||||
matches!(
|
||||
event,
|
||||
PlatformEvent::VisibilityChanged {
|
||||
window_id,
|
||||
visible: true,
|
||||
} if *window_id == window.id()
|
||||
)
|
||||
})
|
||||
.await?;
|
||||
log_platform_event(&event);
|
||||
|
||||
let _ = counter.set(4);
|
||||
let event = ui
|
||||
.wait_for_event_matching(|event| {
|
||||
matches!(
|
||||
event,
|
||||
PlatformEvent::FramePresented {
|
||||
window_id,
|
||||
scene_version: 4,
|
||||
..
|
||||
} if *window_id == window.id()
|
||||
)
|
||||
})
|
||||
.await?;
|
||||
log_platform_event(&event);
|
||||
|
||||
let event = ui
|
||||
.wait_for_event_matching(|event| {
|
||||
matches!(
|
||||
event,
|
||||
PlatformEvent::FramePresented {
|
||||
window_id,
|
||||
scene_version: 5,
|
||||
..
|
||||
} if *window_id == window.id()
|
||||
)
|
||||
})
|
||||
.await?;
|
||||
log_platform_event(&event);
|
||||
|
||||
window.emit_close_requested()?;
|
||||
let event = ui
|
||||
.wait_for_event_matching(|event| {
|
||||
matches!(
|
||||
event,
|
||||
PlatformEvent::CloseRequested { window_id } if *window_id == window.id()
|
||||
)
|
||||
})
|
||||
.await?;
|
||||
log_platform_event(&event);
|
||||
|
||||
window.update(WindowUpdate::new().open(false))?;
|
||||
let event = ui
|
||||
.wait_for_event_matching(
|
||||
|event| matches!(event, PlatformEvent::Closed { window_id } if *window_id == window.id()),
|
||||
)
|
||||
.await?;
|
||||
log_platform_event(&event);
|
||||
|
||||
ui.shutdown()?;
|
||||
|
||||
tracing::info!(
|
||||
event = "prototype_done",
|
||||
"explicit-construction UI prototype finished"
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
Reference in New Issue
Block a user