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