fix animations, fix SlotMap dirty widget panic, set gui scale, set dash to 1080p
[skip ci]
This commit is contained in:
@@ -125,8 +125,7 @@ impl Frontend {
|
||||
let id_label_time = state.get_widget_id("label_time")?;
|
||||
let id_rect_content = state.get_widget_id("rect_content")?;
|
||||
|
||||
let mut timestep = Timestep::new();
|
||||
timestep.set_tps(30.0); // 30 ticks per second
|
||||
let timestep = Timestep::new(60.0);
|
||||
|
||||
let mut frontend = Self {
|
||||
layout,
|
||||
|
||||
@@ -47,7 +47,7 @@ impl Drop for MountedToast {
|
||||
}
|
||||
}
|
||||
|
||||
const TOAST_DURATION_TICKS: u32 = 90;
|
||||
const TOAST_DURATION_TICKS: u32 = 150;
|
||||
|
||||
impl ToastManager {
|
||||
pub fn new() -> Self {
|
||||
@@ -130,7 +130,7 @@ impl ToastManager {
|
||||
// show-up animation
|
||||
layout.animations.add(Animation::new(
|
||||
rect.id,
|
||||
(120.0 * globals.defaults.animation_mult) as u32,
|
||||
(TOAST_DURATION_TICKS as f32 * globals.defaults.animation_mult) as u32,
|
||||
AnimationEasing::Linear,
|
||||
Box::new(move |common, data| {
|
||||
let pos_showup = AnimationEasing::OutQuint.interpolate((data.pos * 4.0).min(1.0));
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
use glam::{Vec2, vec2};
|
||||
use std::sync::Arc;
|
||||
use testbed::{Testbed, testbed_any::TestbedAny};
|
||||
use timestep::Timestep;
|
||||
use tracing_subscriber::EnvFilter;
|
||||
use tracing_subscriber::filter::LevelFilter;
|
||||
use tracing_subscriber::layer::SubscriberExt;
|
||||
@@ -28,6 +27,7 @@ use winit::{
|
||||
event_loop::ControlFlow,
|
||||
keyboard::{KeyCode, PhysicalKey},
|
||||
};
|
||||
use wlx_common::timestep::Timestep;
|
||||
|
||||
use crate::{
|
||||
rate_limiter::RateLimiter,
|
||||
@@ -40,7 +40,6 @@ mod assets;
|
||||
mod profiler;
|
||||
mod rate_limiter;
|
||||
mod testbed;
|
||||
mod timestep;
|
||||
mod vulkan;
|
||||
|
||||
fn init_logging() {
|
||||
@@ -114,8 +113,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let mut profiler = profiler::Profiler::new(1000);
|
||||
let mut frame_index: u64 = 0;
|
||||
|
||||
let mut timestep = Timestep::new();
|
||||
timestep.set_tps(60.0);
|
||||
let mut timestep = Timestep::new(60.0);
|
||||
|
||||
let mut limiter = RateLimiter::new();
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::timestep::get_micros;
|
||||
use wlx_common::timestep::get_micros;
|
||||
|
||||
pub struct Profiler {
|
||||
interval_us: u64,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::timestep::get_micros;
|
||||
use wlx_common::timestep::get_micros;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct RateLimiter {
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
use std::{sync::LazyLock, time::Instant};
|
||||
static TIME_START: LazyLock<Instant> = LazyLock::new(Instant::now);
|
||||
|
||||
pub fn get_micros() -> u64 {
|
||||
TIME_START.elapsed().as_micros() as u64
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Timestep {
|
||||
current_time_us: u64,
|
||||
accumulator: f32,
|
||||
time_micros: u64,
|
||||
ticks: u32,
|
||||
speed: f32,
|
||||
pub alpha: f32,
|
||||
delta: f32,
|
||||
loopnum: u8,
|
||||
}
|
||||
|
||||
impl Timestep {
|
||||
pub fn new() -> Timestep {
|
||||
let mut timestep = Timestep {
|
||||
speed: 1.0,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
timestep.reset();
|
||||
timestep
|
||||
}
|
||||
|
||||
fn calculate_alpha(&mut self) {
|
||||
self.alpha = (self.accumulator / self.delta).clamp(0.0, 1.0);
|
||||
}
|
||||
|
||||
pub fn set_tps(&mut self, tps: f32) {
|
||||
self.delta = 1000.0 / tps;
|
||||
}
|
||||
|
||||
pub fn reset(&mut self) {
|
||||
self.current_time_us = get_micros();
|
||||
self.accumulator = 0.0;
|
||||
}
|
||||
|
||||
pub fn on_tick(&mut self) -> bool {
|
||||
let newtime = get_micros();
|
||||
let frametime = newtime - self.current_time_us;
|
||||
self.time_micros += frametime;
|
||||
self.current_time_us = newtime;
|
||||
self.accumulator += frametime as f32 * self.speed / 1000.0;
|
||||
self.calculate_alpha();
|
||||
|
||||
if self.accumulator >= self.delta {
|
||||
self.accumulator -= self.delta;
|
||||
self.loopnum += 1;
|
||||
self.ticks += 1;
|
||||
|
||||
if self.loopnum > 5 {
|
||||
// cannot keep up!
|
||||
self.loopnum = 0;
|
||||
self.accumulator = 0.0;
|
||||
return false;
|
||||
}
|
||||
|
||||
true
|
||||
} else {
|
||||
self.loopnum = 0;
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,11 +18,11 @@ use crate::{
|
||||
util,
|
||||
},
|
||||
widget::{
|
||||
ConstructEssentials, EventResult,
|
||||
div::WidgetDiv,
|
||||
label::{WidgetLabel, WidgetLabelParams},
|
||||
rectangle::{WidgetRectangle, WidgetRectangleParams},
|
||||
util::WLength,
|
||||
ConstructEssentials, EventResult,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -224,7 +224,7 @@ impl State {
|
||||
return; // nothing changed visually
|
||||
}
|
||||
|
||||
common.alterables.mark_dirty(data.slider_handle_node_id);
|
||||
common.alterables.mark_dirty(data.slider_handle_id);
|
||||
common.alterables.mark_redraw();
|
||||
|
||||
if let Some(slider_text_id) = data.slider_text_id
|
||||
|
||||
@@ -104,7 +104,7 @@ pub enum StyleSetRequest {
|
||||
// alterables which will be dispatched in the next loop iteration phase
|
||||
#[derive(Default)]
|
||||
pub struct EventAlterables {
|
||||
pub dirty_nodes: Vec<taffy::NodeId>,
|
||||
pub dirty_widgets: Vec<WidgetID>,
|
||||
pub style_set_requests: Vec<(WidgetID, StyleSetRequest)>,
|
||||
pub animations: Vec<animation::Animation>,
|
||||
pub widgets_to_tick: HashSet<WidgetID>, // widgets which needs to be ticked in the next `Layout::update()` fn
|
||||
@@ -125,8 +125,8 @@ impl EventAlterables {
|
||||
self.style_set_requests.push((widget_id, request));
|
||||
}
|
||||
|
||||
pub fn mark_dirty(&mut self, node_id: taffy::NodeId) {
|
||||
self.dirty_nodes.push(node_id);
|
||||
pub fn mark_dirty(&mut self, widget_id: WidgetID) {
|
||||
self.dirty_widgets.push(widget_id);
|
||||
}
|
||||
|
||||
pub fn mark_tick(&mut self, widget_id: WidgetID) {
|
||||
@@ -154,9 +154,7 @@ impl CallbackDataCommon<'_> {
|
||||
|
||||
// helper function
|
||||
pub fn mark_widget_dirty(&mut self, id: WidgetID) {
|
||||
if let Some(node_id) = self.state.nodes.get(id) {
|
||||
self.alterables.mark_dirty(*node_id);
|
||||
}
|
||||
self.alterables.mark_dirty(id);
|
||||
self.alterables.mark_redraw();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -683,8 +683,10 @@ impl Layout {
|
||||
|
||||
self.process_tasks()?;
|
||||
|
||||
for node in alterables.dirty_nodes {
|
||||
self.state.tree.mark_dirty(node)?;
|
||||
for dirty_widget_id in alterables.dirty_widgets {
|
||||
if let Some(dirty_node_id) = self.state.nodes.get(dirty_widget_id) {
|
||||
self.state.tree.mark_dirty(*dirty_node_id)?;
|
||||
}
|
||||
}
|
||||
|
||||
if alterables.needs_redraw {
|
||||
|
||||
@@ -18,13 +18,14 @@ pub struct Timestep {
|
||||
}
|
||||
|
||||
impl Timestep {
|
||||
pub fn new() -> Self {
|
||||
pub fn new(ticks_per_second: f32) -> Self {
|
||||
let mut timestep = Self {
|
||||
speed: 1.0,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
timestep.reset();
|
||||
timestep.set_tps(ticks_per_second);
|
||||
timestep
|
||||
}
|
||||
|
||||
|
||||
@@ -160,8 +160,7 @@ impl<S: 'static> GuiPanel<S> {
|
||||
}
|
||||
|
||||
let context = WguiContext::new(&mut app.wgui_shared, 1.0)?;
|
||||
let mut timestep = Timestep::new();
|
||||
timestep.set_tps(60.0);
|
||||
let timestep = Timestep::new(60.0);
|
||||
|
||||
Ok(Self {
|
||||
layout,
|
||||
@@ -192,8 +191,7 @@ impl<S: 'static> GuiPanel<S> {
|
||||
},
|
||||
)?;
|
||||
let context = WguiContext::new(&mut app.wgui_shared, 1.0)?;
|
||||
let mut timestep = Timestep::new();
|
||||
timestep.set_tps(60.0);
|
||||
let timestep = Timestep::new(60.0);
|
||||
|
||||
Ok(Self {
|
||||
layout,
|
||||
|
||||
@@ -37,7 +37,7 @@ use crate::{
|
||||
|
||||
pub const DASH_NAME: &str = "Dashboard";
|
||||
|
||||
const DASH_RES_U32A: [u32; 2] = [1280, 720];
|
||||
const DASH_RES_U32A: [u32; 2] = [1920, 1080];
|
||||
const DASH_RES_VEC2: Vec2 = vec2(DASH_RES_U32A[0] as _, DASH_RES_U32A[1] as _);
|
||||
|
||||
//FIXME: replace with proper impl
|
||||
@@ -86,6 +86,8 @@ pub struct DashFrontend {
|
||||
context: WguiContext,
|
||||
}
|
||||
|
||||
const GUI_SCALE: f32 = 2.0;
|
||||
|
||||
impl DashFrontend {
|
||||
fn new(app: &mut AppState) -> anyhow::Result<Self> {
|
||||
let settings = SimpleSettingsIO::new();
|
||||
@@ -100,15 +102,18 @@ impl DashFrontend {
|
||||
inner: frontend,
|
||||
initialized: false,
|
||||
interaction_transform: None,
|
||||
timestep: Timestep::new(),
|
||||
timestep: Timestep::new(60.0),
|
||||
has_focus: [false, false],
|
||||
context,
|
||||
})
|
||||
}
|
||||
|
||||
fn update(&mut self) -> anyhow::Result<()> {
|
||||
log::info!("update layout");
|
||||
self.inner.update(DASH_RES_VEC2.x, DASH_RES_VEC2.y, 0.0)
|
||||
fn update(&mut self, timestep_alpha: f32) -> anyhow::Result<()> {
|
||||
self.inner.update(
|
||||
DASH_RES_VEC2.x / GUI_SCALE,
|
||||
DASH_RES_VEC2.y / GUI_SCALE,
|
||||
timestep_alpha,
|
||||
)
|
||||
}
|
||||
|
||||
fn push_event(&mut self, event: &WguiEvent) -> EventResult {
|
||||
@@ -125,11 +130,11 @@ impl DashFrontend {
|
||||
impl OverlayBackend for DashFrontend {
|
||||
fn init(&mut self, app: &mut AppState) -> anyhow::Result<()> {
|
||||
self.context
|
||||
.update_viewport(&mut app.wgui_shared, DASH_RES_U32A, 1.0)?;
|
||||
.update_viewport(&mut app.wgui_shared, DASH_RES_U32A, GUI_SCALE)?;
|
||||
self.interaction_transform = Some(ui_transform(DASH_RES_U32A));
|
||||
|
||||
if self.inner.layout.content_size.x * self.inner.layout.content_size.y != 0.0 {
|
||||
self.update()?;
|
||||
self.update(0.0)?;
|
||||
self.initialized = true;
|
||||
}
|
||||
Ok(())
|
||||
@@ -150,6 +155,10 @@ impl OverlayBackend for DashFrontend {
|
||||
self.inner.layout.tick()?;
|
||||
}
|
||||
|
||||
if let Err(e) = self.update(self.timestep.alpha) {
|
||||
log::error!("uncaught exception: {e:?}");
|
||||
}
|
||||
|
||||
Ok(if self.inner.layout.check_toggle_needs_redraw() {
|
||||
ShouldRender::Should
|
||||
} else {
|
||||
@@ -158,14 +167,6 @@ impl OverlayBackend for DashFrontend {
|
||||
}
|
||||
|
||||
fn render(&mut self, app: &mut AppState, rdr: &mut RenderResources) -> anyhow::Result<()> {
|
||||
self.inner
|
||||
.layout
|
||||
.update(DASH_RES_VEC2, self.timestep.alpha)?;
|
||||
|
||||
if let Err(e) = self.update() {
|
||||
log::error!("uncaught exception: {e:?}");
|
||||
}
|
||||
|
||||
let globals = self.inner.layout.state.globals.clone(); // sorry
|
||||
let mut globals = globals.get();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user