mirror of
https://github.com/wayvr-org/wayvr.git
synced 2026-10-28 14:02:26 +01:00
Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
af733b6817 | ||
|
|
936c8bf27d | ||
|
|
998c566fc6 |
No files matched your search
@@ -9,9 +9,7 @@ assignees: ''
|
||||
|
||||
## Description
|
||||
<!--
|
||||
*** Do NOT use AI to generate a bug report! ***
|
||||
Simply write down what's wrong and maybe provide screenshots or a video.
|
||||
If this has worked before, please mention which version was last working.
|
||||
If this is a regression, please mention which version was working previously.
|
||||
-->
|
||||
|
||||
## System Info
|
||||
|
||||
@@ -9,9 +9,8 @@
|
||||
gap="8"
|
||||
round="8"/>
|
||||
|
||||
<!-- id -->
|
||||
<template name="GroupBox">
|
||||
<rectangle macro="group_box" id="rect">
|
||||
<rectangle macro="group_box">
|
||||
<CHILDREN/>
|
||||
</rectangle>
|
||||
</template>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
<!-- device_name, device_icon -->
|
||||
<template name="DeviceSlider">
|
||||
<GroupBox id="rect">
|
||||
<GroupBox>
|
||||
<div width="100%" align_items="center" justify_content="center" gap="8">
|
||||
<sprite src_builtin="${device_icon}" width="16" height="16" color="on_background" />
|
||||
<label text="${device_name}" margin_right="8" size="12" weight="bold" color="on_background" />
|
||||
@@ -47,17 +47,8 @@
|
||||
|
||||
<elements>
|
||||
<div flex_direction="column" gap="4">
|
||||
<!--
|
||||
this div shouldn't be technically needed, but there's a bug in
|
||||
the newest taffy version (or we're doing something wrong),
|
||||
causing the scrollbar to show up, even if it's not overflowing.
|
||||
OVERFLOW_START_THRESHOLD_UNITS is already set to 3, but it's not
|
||||
sufficient enough in this case?? (margin_bottom="4" fixes that).
|
||||
-->
|
||||
<div width="100%" flex_direction="column" max_height="400" overflow_y="scroll">
|
||||
<div id="devices" width="100%" flex_direction="column" gap="4" margin_bottom="4">
|
||||
<div id="devices" flex_direction="column" gap="4" max_height="400" overflow_y="scroll">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- bottom buttons -->
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
</template>
|
||||
|
||||
<elements>
|
||||
<div flex_direction="column" gap="8" width="100%" align_items="center" overflow_y="scroll">
|
||||
<div flex_direction="column" gap="8" width="100%" align_items="center">
|
||||
<div id="list_parent" flex_grow="1" flex_wrap="wrap" flex_direction="row" gap="4" width="100%" justify_content="center"></div>
|
||||
</div>
|
||||
</elements>
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<rectangle position="absolute" width="100%" height="3" round="4" color="highlight(opacity-0.1)" />
|
||||
|
||||
<!-- Top bar contents -->
|
||||
<div gap="16" align_items="center" id="top_bar_contents">
|
||||
<div gap="16" align_items="center">
|
||||
<!-- Back button -->
|
||||
<Button id="but_back" width="48" height="48" color="on_background_contrast(transparent)" border_color="on_background_contrast(transparent)">
|
||||
<sprite src_builtin="@/dashboard/back.svg" width="24" height="24" color="on_background_contrast" />
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
<layout version="2">
|
||||
<elements>
|
||||
<div flex_direction="column" overflow_y="scroll">
|
||||
<div id="list" gap="8" flex_direction="row" flex_wrap="wrap">
|
||||
<!-- filled-in at runtime -->
|
||||
</div>
|
||||
<div id="list" gap="8" flex_wrap="wrap" align_self="baseline">
|
||||
<!-- filled-in at runtime -->
|
||||
</div>
|
||||
</elements>
|
||||
</layout>
|
||||
@@ -1,11 +1,11 @@
|
||||
<layout version="2">
|
||||
<elements>
|
||||
<div flex_direction="column" gap="8" width="100%" >
|
||||
<div flex_direction="column" gap="8" width="100%" align_items="center">
|
||||
<div flex_direction="row" gap="4" align_self="end">
|
||||
<Button id="btn_refresh" tooltip="RELOAD_FROM_DISK" width="32" height="32" sprite_src_builtin="@/dashboard/refresh.svg" />
|
||||
<Button id="btn_download_skymaps" height="32" translation="APP_SETTINGS.BROWSE_ONLINE_CATALOG" sprite_src_builtin="@/dashboard/download.svg"/>
|
||||
</div>
|
||||
<div id="list_parent" gap="8" flex_direction="row" flex_wrap="wrap" overflow_y="scroll" justify_content="center"/>
|
||||
<div id="list_parent" gap="8" flex_direction="row" flex_wrap="wrap" />
|
||||
</div>
|
||||
</elements>
|
||||
</layout>
|
||||
@@ -15,12 +15,9 @@
|
||||
flex_direction="column"
|
||||
gap="4"
|
||||
width="256"
|
||||
max_width="450"
|
||||
height="200"
|
||||
align_items="center"
|
||||
flex_grow="1"
|
||||
align_self="start">
|
||||
<image id="image_preview" width="100%" aspect_ratio="2.0" round="6">
|
||||
<image id="image_preview" width="100%" height="128" round="6">
|
||||
<!-- new_pass is required, because we need to render rectangles at the top of the image. Sorry. -->
|
||||
<div new_pass="1" id="resolution_pips" gap="4" margin="6"/>
|
||||
</image>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::{marker::PhantomData, rc::Rc};
|
||||
|
||||
use wgui::{
|
||||
animation::{Animation, AnimationDuration, AnimationEasing},
|
||||
animation::{Animation, AnimationEasing},
|
||||
assets::AssetPathRef,
|
||||
color::{WguiColor, WguiColorName, WguiNamedColor},
|
||||
components::{ComponentTrait, button::ComponentButton},
|
||||
@@ -61,7 +61,7 @@ fn get_supporter_anim(
|
||||
Animation::new_ex(
|
||||
btn.base().get_id(),
|
||||
1234,
|
||||
AnimationDuration::SecondsFixed(8.0),
|
||||
480,
|
||||
AnimationEasing::Linear,
|
||||
Box::new(move |common, data| {
|
||||
let opacity_in = f32::clamp(data.pos * FADE_SPEED, 0.0, 1.0);
|
||||
|
||||
@@ -3,9 +3,7 @@ use std::{
|
||||
rc::{Rc, Weak},
|
||||
};
|
||||
|
||||
use glam::Vec2;
|
||||
use wgui::{
|
||||
animation::{Animation, AnimationDuration, AnimationEasing},
|
||||
assets::AssetPathRef,
|
||||
components::button::ComponentButton,
|
||||
event::{EventAlterables, StyleSetRequest},
|
||||
@@ -14,7 +12,7 @@ use wgui::{
|
||||
layout::{Layout, LayoutTask, LayoutTasks, WidgetID},
|
||||
parser::{Fetchable, ParseDocumentParams, ParserState},
|
||||
taffy::Rect,
|
||||
widget::{WidgetObj, label::WidgetLabel},
|
||||
widget::label::WidgetLabel,
|
||||
};
|
||||
use wlx_common::config::GeneralConfig;
|
||||
|
||||
@@ -253,13 +251,6 @@ impl State {
|
||||
}
|
||||
}
|
||||
|
||||
struct MountPopupPrepareResult {
|
||||
popup_handle: PopupHandle,
|
||||
id_content: WidgetID,
|
||||
id_top_bar_contents: WidgetID,
|
||||
id_popup_title: WidgetID,
|
||||
}
|
||||
|
||||
impl PopupManager {
|
||||
pub fn new(params: PopupManagerParams) -> Self {
|
||||
Self {
|
||||
@@ -282,7 +273,7 @@ impl PopupManager {
|
||||
frontend_tasks: &FrontendTasks,
|
||||
popup_title: &Translation,
|
||||
popup_padding: PopupPadding,
|
||||
) -> anyhow::Result<MountPopupPrepareResult> {
|
||||
) -> anyhow::Result<(PopupHandle, WidgetID /* content widget ID */)> {
|
||||
let doc_params = &ParseDocumentParams {
|
||||
globals: globals.clone(),
|
||||
path: AssetPathRef::BuiltIn("gui/view/popup_window.xml"),
|
||||
@@ -292,7 +283,6 @@ impl PopupManager {
|
||||
|
||||
let id_root = state.get_widget_id("root")?;
|
||||
let id_content = state.get_widget_id("content")?;
|
||||
let id_top_bar_contents = state.get_widget_id("top_bar_contents")?;
|
||||
|
||||
let padding = match popup_padding {
|
||||
PopupPadding::Normal => 16.0_f32,
|
||||
@@ -304,11 +294,10 @@ impl PopupManager {
|
||||
StyleSetRequest::Padding(Rect::length(padding)),
|
||||
));
|
||||
|
||||
let id_popup_title = {
|
||||
{
|
||||
let mut label_title = state.fetch_widget_as::<WidgetLabel>(&layout.state, "popup_title")?;
|
||||
label_title.set_text_simple(&mut globals.get(), popup_title.clone());
|
||||
label_title.get_id()
|
||||
};
|
||||
}
|
||||
|
||||
let but_back = state.fetch_component_as::<ComponentButton>("but_back")?;
|
||||
|
||||
@@ -349,13 +338,7 @@ impl PopupManager {
|
||||
});
|
||||
|
||||
frontend_tasks.push(FrontendTask::RefreshPopupManager);
|
||||
|
||||
Ok(MountPopupPrepareResult {
|
||||
popup_handle,
|
||||
id_content,
|
||||
id_top_bar_contents,
|
||||
id_popup_title,
|
||||
})
|
||||
Ok((popup_handle, id_content))
|
||||
}
|
||||
|
||||
/// Mount a new popup on top of the existing popup stack.
|
||||
@@ -373,43 +356,18 @@ impl PopupManager {
|
||||
anyhow::bail!("mount_popup_once called more than once");
|
||||
};
|
||||
|
||||
let res = self.mount_popup_prepare(globals, layout, frontend_tasks, ¶ms.title, params.extra.padding)?;
|
||||
|
||||
// text fade-in
|
||||
Animation::effect_label_fade_in(
|
||||
res.id_popup_title,
|
||||
AnimationDuration::Seconds(0.25),
|
||||
AnimationEasing::OutQuad,
|
||||
)
|
||||
.submit_l(layout);
|
||||
|
||||
// top bar slide
|
||||
Animation::effect_slide(
|
||||
res.id_top_bar_contents,
|
||||
AnimationDuration::Seconds(0.5),
|
||||
AnimationEasing::OutQuint,
|
||||
Vec2::new(10.0, 0.0),
|
||||
)
|
||||
.submit_l(layout);
|
||||
|
||||
// content slide
|
||||
Animation::effect_slide(
|
||||
res.id_content,
|
||||
AnimationDuration::Seconds(0.5),
|
||||
AnimationEasing::OutQuint,
|
||||
Vec2::new(5.0, 0.0),
|
||||
)
|
||||
.submit_l(layout);
|
||||
let (popup_handle, id_content) =
|
||||
self.mount_popup_prepare(globals, layout, frontend_tasks, ¶ms.title, params.extra.padding)?;
|
||||
|
||||
// mount user-set popup content
|
||||
let closed_callback = on_content_func(PopupContentFuncData {
|
||||
layout,
|
||||
handle: res.popup_handle.clone(),
|
||||
id_content: res.id_content,
|
||||
handle: popup_handle.clone(),
|
||||
id_content,
|
||||
config,
|
||||
})?;
|
||||
|
||||
res.popup_handle.state.borrow_mut().closed_callback = Some(closed_callback);
|
||||
popup_handle.state.borrow_mut().closed_callback = Some(closed_callback);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use glam::{Mat4, Vec3};
|
||||
use std::{cell::RefCell, collections::VecDeque, rc::Rc};
|
||||
use wgui::{
|
||||
animation::{Animation, AnimationDuration, AnimationEasing},
|
||||
animation::{Animation, AnimationEasing},
|
||||
color::{WguiColor, WguiColorName},
|
||||
components::tooltip::{TOOLTIP_BORDER_COLOR, TOOLTIP_COLOR},
|
||||
i18n::Translation,
|
||||
@@ -45,9 +45,7 @@ impl Drop for MountedToast {
|
||||
}
|
||||
}
|
||||
|
||||
fn def_toast_duration() -> AnimationDuration {
|
||||
AnimationDuration::Seconds(2.5)
|
||||
}
|
||||
const TOAST_DURATION_TICKS: u32 = 150;
|
||||
|
||||
impl ToastManager {
|
||||
pub fn new() -> Self {
|
||||
@@ -118,9 +116,9 @@ impl ToastManager {
|
||||
let (label, _) = layout.add_child(rect.id, label, taffy::Style { ..Default::default() })?;
|
||||
|
||||
// show-up animation
|
||||
Animation::new(
|
||||
layout.animations.add(Animation::new(
|
||||
rect.id,
|
||||
def_toast_duration(),
|
||||
(TOAST_DURATION_TICKS as f32 * layout.state.theme.animation_mult) as u32,
|
||||
AnimationEasing::Linear,
|
||||
Box::new(move |common, data| {
|
||||
let pos_showup = AnimationEasing::OutQuint.interpolate((data.pos * 4.0).min(1.0));
|
||||
@@ -145,8 +143,7 @@ impl ToastManager {
|
||||
);
|
||||
common.alterables.mark_redraw();
|
||||
}),
|
||||
)
|
||||
.submit_l(layout);
|
||||
));
|
||||
|
||||
state.toast = Some(MountedToast {
|
||||
id_root: root.id,
|
||||
@@ -168,7 +165,7 @@ impl ToastManager {
|
||||
|
||||
if state.timeout == 0 {
|
||||
state.toast = None;
|
||||
state.timeout = def_toast_duration().to_ticks(layout.state.ticks_per_second, layout.state.theme.animation_mult);
|
||||
state.timeout = TOAST_DURATION_TICKS;
|
||||
// mount next
|
||||
if let Some(content) = state.queue.pop_front() {
|
||||
self.mount_toast(layout, &mut state, content)?;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use glam::{Mat4, Vec2};
|
||||
use wgui::{
|
||||
animation::{Animation, AnimationDuration, AnimationEasing},
|
||||
animation::{Animation, AnimationEasing},
|
||||
assets::AssetPathRef,
|
||||
color::WguiColorName,
|
||||
components::{self, button::ButtonClickCallback},
|
||||
@@ -145,9 +145,9 @@ pub fn create_loading(par: CreateLoadingParams) -> anyhow::Result<WidgetID> {
|
||||
let id_root = data.get_widget_id("root")?;
|
||||
let id_sprite_loading = data.get_widget_id("sprite_loading")?;
|
||||
|
||||
Animation::new(
|
||||
par.layout.animations.add(Animation::new(
|
||||
id_sprite_loading,
|
||||
AnimationDuration::SecondsFixed(120.0), /* spin it for 120 seconds at most */
|
||||
60 * 30, /* spin it for 30 seconds at most */
|
||||
AnimationEasing::Linear,
|
||||
Box::new(move |common, data| {
|
||||
// spin it
|
||||
@@ -161,8 +161,7 @@ pub fn create_loading(par: CreateLoadingParams) -> anyhow::Result<WidgetID> {
|
||||
}
|
||||
common.alterables.mark_redraw();
|
||||
}),
|
||||
)
|
||||
.submit_l(par.layout);
|
||||
));
|
||||
|
||||
Ok(id_root)
|
||||
}
|
||||
@@ -14,7 +14,7 @@ use wgui::{
|
||||
layout::{Layout, WidgetID},
|
||||
parser::{Fetchable, ParseDocumentParams, ParserState, TemplateParams},
|
||||
task::Tasks,
|
||||
widget::{ConstructEssentials, rectangle::WidgetRectangle},
|
||||
widget::ConstructEssentials,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
@@ -802,13 +802,6 @@ impl View {
|
||||
par,
|
||||
)?;
|
||||
|
||||
if params.checked {
|
||||
let rect = data.fetch_widget(¶ms.layout.state, "rect")?;
|
||||
let mut rect = rect.widget.cast::<WidgetRectangle>()?;
|
||||
rect.set_color(&mut params.layout.common(), WguiColorName::BackgroundVariant.into());
|
||||
rect.set_border_color(&mut params.layout.common(), WguiColorName::Primary.into());
|
||||
}
|
||||
|
||||
let mut common = params.layout.common();
|
||||
let checkbox = data.fetch_component_as::<ComponentCheckbox>("checkbox")?;
|
||||
let btn_mute = data.fetch_component_as::<ComponentButton>("btn_mute")?;
|
||||
|
||||
@@ -501,7 +501,7 @@ fn subpath_dropdown(
|
||||
mp.layout,
|
||||
parent,
|
||||
Vec2::new(32.0, 32.0),
|
||||
AssetPathRef::BuiltIn(&format!("dashboard/hand_{}.svg", side.as_ref())),
|
||||
AssetPathRef::BuiltIn(&format!("@/dashboard/hand_{}.svg", side.as_ref())),
|
||||
)?;
|
||||
|
||||
let current_text = current
|
||||
|
||||
@@ -6,23 +6,22 @@
|
||||
padding="16"
|
||||
flex_direction="column"
|
||||
gap="8"
|
||||
color="background" border_color="outline" border="2" round="8"
|
||||
id="rect">
|
||||
color="background" border_color="outline" border="2" round="8">
|
||||
|
||||
<!-- Toast title -->
|
||||
<div flex_direction="row" align_items="center" gap="8" id="div_title">
|
||||
<sprite id="sprite_bell" src="@/icons/bell.svg" color="primary" min_width="32" min_height="32" max_width="32" max_height="32" flex_grow="1" />
|
||||
<label wrap="1" id="label_title" color="primary" weight="bold" size="25" padding_left="16" padding_right="16" />
|
||||
<div flex_direction="row" align_items="center" gap="8">
|
||||
<sprite src="@/icons/bell.svg" color="primary" min_width="32" min_height="32" max_width="32" max_height="32" flex_grow="1" />
|
||||
<label wrap="1" id="toast_title" color="primary" weight="bold" size="25" padding_left="16" padding_right="16" />
|
||||
</div>
|
||||
|
||||
<!-- A simple separator -->
|
||||
<rectangle id="rect_separator" width="100%" height="2" color="outline" />
|
||||
<rectangle width="100%" height="2" color="outline" />
|
||||
|
||||
<div>
|
||||
<!-- Toast message -->
|
||||
<label id="label_body" color="on_background" wrap="1" size="20" padding_left="16" padding_right="16" />
|
||||
<label id="toast_body" color="on_background" wrap="1" size="20" padding_left="16" padding_right="16" />
|
||||
</div>
|
||||
</rectangle>
|
||||
</div>
|
||||
</elements>
|
||||
</layout>
|
||||
</layout>
|
||||
@@ -625,7 +625,6 @@ pub(super) fn setup_custom_button<S: 'static>(
|
||||
)
|
||||
.with_timeout(1.0)
|
||||
.with_lerp_amount(1.0)
|
||||
.with_animate(false)
|
||||
.with_sound(i == 0)
|
||||
.submit_at(app, now + Duration::from_secs(i as _));
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ use std::rc::Rc;
|
||||
|
||||
use anyhow::Context;
|
||||
use wgui::{
|
||||
animation::{Animation, AnimationDuration, AnimationEasing},
|
||||
animation::{Animation, AnimationEasing},
|
||||
color::{WguiColor, WguiColorName},
|
||||
components::button::ComponentButton,
|
||||
event::CallbackDataCommon,
|
||||
@@ -76,7 +76,11 @@ impl InteractLockHandler {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn toggle(&mut self, common: &mut CallbackDataCommon) -> Box<ModifyOverlayTask> {
|
||||
pub fn toggle(
|
||||
&mut self,
|
||||
common: &mut CallbackDataCommon,
|
||||
anim_mult: f32,
|
||||
) -> Box<ModifyOverlayTask> {
|
||||
let rect_color = self.color;
|
||||
|
||||
self.interactable = !self.interactable;
|
||||
@@ -87,7 +91,7 @@ impl InteractLockHandler {
|
||||
let anim = if self.interactable {
|
||||
Animation::new(
|
||||
self.id,
|
||||
AnimationDuration::Seconds(0.1666),
|
||||
(10. * anim_mult) as _,
|
||||
AnimationEasing::OutQuad,
|
||||
Box::new(move |common, data| {
|
||||
let rect = data.obj.get_as_mut::<WidgetRectangle>().unwrap();
|
||||
@@ -104,7 +108,7 @@ impl InteractLockHandler {
|
||||
} else {
|
||||
Animation::new(
|
||||
self.id,
|
||||
AnimationDuration::Seconds(0.1666),
|
||||
(10. * anim_mult) as _,
|
||||
AnimationEasing::OutBack,
|
||||
Box::new(move |common, data| {
|
||||
let rect = data.obj.get_as_mut::<WidgetRectangle>().unwrap();
|
||||
|
||||
@@ -365,6 +365,8 @@ fn make_edit_panel(app: &mut AppState) -> anyhow::Result<EditModeWrapPanel> {
|
||||
resize: ResizeState::None,
|
||||
};
|
||||
|
||||
let anim_mult = app.wgui_theme.animation_mult;
|
||||
|
||||
let on_custom_attrib: OnCustomAttribFunc = Box::new(move |layout, parser, attribs, _app| {
|
||||
let Ok(button) = parser
|
||||
.fetch_component_from_widget_id_as::<ComponentButton>(&layout.state, attribs.widget_id)
|
||||
@@ -393,7 +395,7 @@ fn make_edit_panel(app: &mut AppState) -> anyhow::Result<EditModeWrapPanel> {
|
||||
}
|
||||
|
||||
let sel = OverlaySelector::Id(*state.id.borrow());
|
||||
let task = state.lock.toggle(common);
|
||||
let task = state.lock.toggle(common, anim_mult);
|
||||
app.tasks
|
||||
.enqueue(TaskType::Overlay(OverlayTask::Modify(sel, task)));
|
||||
Ok(EventResult::Consumed)
|
||||
|
||||
@@ -15,7 +15,7 @@ use anyhow::Context;
|
||||
use glam::{FloatExt, Mat4, Vec2, vec2, vec3};
|
||||
use smallvec::{SmallVec, smallvec};
|
||||
use wgui::{
|
||||
animation::{Animation, AnimationDuration, AnimationEasing},
|
||||
animation::{Animation, AnimationEasing},
|
||||
assets::AssetPathRef,
|
||||
color::{WguiColor, WguiColorName},
|
||||
event::{self, CallbackMetadata, EventListenerKind},
|
||||
@@ -74,6 +74,8 @@ pub(super) fn create_keyboard_panel(
|
||||
|
||||
let doc_params = new_doc_params(&mut panel);
|
||||
|
||||
let anim_mult = app.wgui_theme.animation_mult;
|
||||
|
||||
let root = panel
|
||||
.parser_state
|
||||
.get_widget_id("keyboard_root")
|
||||
@@ -204,7 +206,7 @@ pub(super) fn create_keyboard_panel(
|
||||
let k = key_state.clone();
|
||||
move |common, data, _app, _state| {
|
||||
common.alterables.trigger_haptics();
|
||||
on_enter_anim(k.clone(), common, data, width_mul);
|
||||
on_enter_anim(k.clone(), common, data, anim_mult, width_mul);
|
||||
Ok(EventResult::Pass)
|
||||
}
|
||||
}),
|
||||
@@ -216,7 +218,7 @@ pub(super) fn create_keyboard_panel(
|
||||
let k = key_state.clone();
|
||||
move |common, data, _app, _state| {
|
||||
common.alterables.trigger_haptics();
|
||||
on_leave_anim(k.clone(), common, data, width_mul);
|
||||
on_leave_anim(k.clone(), common, data, anim_mult, width_mul);
|
||||
Ok(EventResult::Pass)
|
||||
}
|
||||
}),
|
||||
@@ -413,11 +415,12 @@ fn on_enter_anim(
|
||||
key_state: Rc<KeyState>,
|
||||
common: &mut event::CallbackDataCommon,
|
||||
data: &event::CallbackData,
|
||||
anim_mult: f32,
|
||||
width_mult: f32,
|
||||
) {
|
||||
Animation::new(
|
||||
common.alterables.animate(Animation::new(
|
||||
data.widget_id,
|
||||
AnimationDuration::Seconds(0.1666),
|
||||
(10. * anim_mult) as _,
|
||||
AnimationEasing::OutBack,
|
||||
Box::new(move |common, data| {
|
||||
let rect = data.obj.get_as_mut::<WidgetRectangle>().unwrap();
|
||||
@@ -453,19 +456,19 @@ fn on_enter_anim(
|
||||
get_anim_transform(data.pos, data.widget_boundary.size, width_mult);
|
||||
common.alterables.mark_redraw();
|
||||
}),
|
||||
)
|
||||
.submit(common.alterables);
|
||||
));
|
||||
}
|
||||
|
||||
fn on_leave_anim(
|
||||
key_state: Rc<KeyState>,
|
||||
common: &mut event::CallbackDataCommon,
|
||||
data: &event::CallbackData,
|
||||
anim_mult: f32,
|
||||
width_mult: f32,
|
||||
) {
|
||||
Animation::new(
|
||||
common.alterables.animate(Animation::new(
|
||||
data.widget_id,
|
||||
AnimationDuration::Seconds(0.25),
|
||||
(15. * anim_mult) as _,
|
||||
AnimationEasing::OutQuad,
|
||||
Box::new(move |common, data| {
|
||||
let rect = data.obj.get_as_mut::<WidgetRectangle>().unwrap();
|
||||
@@ -503,8 +506,7 @@ fn on_leave_anim(
|
||||
get_anim_transform(1.0 - data.pos, data.widget_boundary.size, width_mult);
|
||||
common.alterables.mark_redraw();
|
||||
}),
|
||||
)
|
||||
.submit(common.alterables);
|
||||
));
|
||||
}
|
||||
|
||||
fn on_press_anim(
|
||||
|
||||
@@ -138,7 +138,6 @@ impl OverlayBackend for PassthruBackend {
|
||||
Ok(())
|
||||
}
|
||||
fn resume(&mut self, _app: &mut AppState) -> anyhow::Result<()> {
|
||||
self.dirty = true;
|
||||
Ok(())
|
||||
}
|
||||
fn should_render(&mut self, _app: &mut AppState) -> anyhow::Result<ShouldRender> {
|
||||
|
||||
+5
-115
@@ -5,11 +5,9 @@ use std::{
|
||||
};
|
||||
|
||||
use anyhow::Context;
|
||||
use glam::{Affine3A, Quat, Vec2, Vec3, vec3};
|
||||
use glam::{Affine3A, Quat, Vec3, vec3};
|
||||
use wgui::{
|
||||
animation::{Animation, AnimationDuration, AnimationEasing, AnimationStartDelay},
|
||||
i18n::{I18n, Translation},
|
||||
parser::Fetchable,
|
||||
widget::label::WidgetLabel,
|
||||
};
|
||||
use wlx_common::{
|
||||
@@ -32,7 +30,6 @@ pub struct ToastParams {
|
||||
pub opacity: f32,
|
||||
pub timeout: f32,
|
||||
pub lerp_amount: f32,
|
||||
pub animate: bool,
|
||||
pub sound: bool,
|
||||
pub topic: ToastTopic,
|
||||
}
|
||||
@@ -59,7 +56,6 @@ impl Toast {
|
||||
opacity: 1.0,
|
||||
lerp_amount: 0.1,
|
||||
timeout: 3.0,
|
||||
animate: true,
|
||||
sound: false,
|
||||
topic,
|
||||
},
|
||||
@@ -86,11 +82,6 @@ impl Toast {
|
||||
self
|
||||
}
|
||||
|
||||
pub const fn with_animate(mut self, animate: bool) -> Self {
|
||||
self.params.animate = animate;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn submit(self, app: &mut AppState) {
|
||||
self.submit_at(app, Instant::now());
|
||||
}
|
||||
@@ -209,21 +200,21 @@ fn new_toast(toast: BakedToast, app: &mut AppState) -> Option<OverlayWindowConfi
|
||||
|
||||
let on_custom_id: OnCustomIdFunc<()> =
|
||||
Box::new(move |id, widget, _doc_params, layout, _parser_state, ()| {
|
||||
if &*id == "label_title" {
|
||||
if &*id == "toast_title" {
|
||||
let mut label = layout
|
||||
.state
|
||||
.widgets
|
||||
.get_as::<WidgetLabel>(widget)
|
||||
.context("toast.xml: missing element with id: label_title")?;
|
||||
.context("toast.xml: missing element with id: toast_title")?;
|
||||
let mut globals = layout.state.globals.get();
|
||||
label.set_text_simple(&mut globals, title.clone());
|
||||
}
|
||||
if &*id == "label_body" {
|
||||
if &*id == "toast_body" {
|
||||
let mut label = layout
|
||||
.state
|
||||
.widgets
|
||||
.get_as::<WidgetLabel>(widget)
|
||||
.context("toast.xml: missing element with id: label_body")?;
|
||||
.context("toast.xml: missing element with id: toast_body")?;
|
||||
let mut globals = layout.state.globals.get();
|
||||
label.set_text_simple(&mut globals, body.clone());
|
||||
}
|
||||
@@ -242,107 +233,6 @@ fn new_toast(toast: BakedToast, app: &mut AppState) -> Option<OverlayWindowConfi
|
||||
.inspect_err(|e| log::error!("Could not create toast: {e:?}"))
|
||||
.ok()?;
|
||||
|
||||
// animations
|
||||
if toast.params.animate {
|
||||
let id_div_title = panel.parser_state.get_widget_id("div_title").ok()?;
|
||||
let id_label_body = panel.parser_state.get_widget_id("label_body").ok()?;
|
||||
let id_label_title = panel.parser_state.get_widget_id("label_title").ok()?;
|
||||
let id_rect = panel.parser_state.get_widget_id("rect").ok()?;
|
||||
let id_rect_separator = panel.parser_state.get_widget_id("rect_separator").ok()?;
|
||||
let id_sprite_bell = panel.parser_state.get_widget_id("sprite_bell").ok()?;
|
||||
|
||||
// schedule timeouts
|
||||
let time_window = 0.5;
|
||||
if toast.params.timeout > time_window && toast.params.timeout < 150.0 {
|
||||
let dur = AnimationDuration::SecondsFixed(time_window);
|
||||
let easing = AnimationEasing::OutQuad;
|
||||
|
||||
let mut add = |a: Animation| {
|
||||
a.reversed()
|
||||
.delayed(AnimationStartDelay::SecondsFixed(
|
||||
toast.params.timeout - time_window,
|
||||
))
|
||||
.with_id(1)
|
||||
.submit_l(&mut panel.layout);
|
||||
};
|
||||
|
||||
add(Animation::effect_rectangle_fade_in(id_rect, dur, easing));
|
||||
add(Animation::effect_scale(
|
||||
id_rect_separator,
|
||||
dur,
|
||||
easing,
|
||||
Vec2::new(0.0, 1.0),
|
||||
Vec2::new(1.0, 1.0),
|
||||
));
|
||||
add(Animation::effect_label_fade_in(id_label_title, dur, easing));
|
||||
add(Animation::effect_label_fade_in(id_label_body, dur, easing));
|
||||
add(Animation::effect_sprite_fade_in(
|
||||
id_sprite_bell,
|
||||
dur,
|
||||
easing,
|
||||
));
|
||||
}
|
||||
|
||||
// separator scale
|
||||
Animation::effect_scale(
|
||||
id_rect_separator,
|
||||
AnimationDuration::Seconds(1.0),
|
||||
AnimationEasing::OutBack,
|
||||
Vec2::new(0.0, 1.0),
|
||||
Vec2::new(1.0, 1.0),
|
||||
)
|
||||
.submit_l(&mut panel.layout);
|
||||
|
||||
// rectangle opacity
|
||||
Animation::effect_rectangle_fade_in(
|
||||
id_rect,
|
||||
AnimationDuration::Seconds(0.5),
|
||||
AnimationEasing::OutQuad,
|
||||
)
|
||||
.submit_l(&mut panel.layout);
|
||||
|
||||
// title animation
|
||||
Animation::effect_slide(
|
||||
id_div_title,
|
||||
AnimationDuration::Seconds(1.0),
|
||||
AnimationEasing::OutQuint,
|
||||
Vec2::new(15.0, 0.0),
|
||||
)
|
||||
.submit_l(&mut panel.layout);
|
||||
|
||||
Animation::effect_label_fade_in(
|
||||
id_label_title,
|
||||
AnimationDuration::Seconds(0.5),
|
||||
AnimationEasing::OutQuad,
|
||||
)
|
||||
.submit_l(&mut panel.layout);
|
||||
|
||||
Animation::effect_sprite_fade_in(
|
||||
id_sprite_bell,
|
||||
AnimationDuration::Seconds(0.5),
|
||||
AnimationEasing::OutQuad,
|
||||
)
|
||||
.submit_l(&mut panel.layout);
|
||||
|
||||
// body animation
|
||||
Animation::effect_slide(
|
||||
id_label_body,
|
||||
AnimationDuration::Seconds(1.0),
|
||||
AnimationEasing::OutQuint,
|
||||
Vec2::new(15.0, 0.0),
|
||||
)
|
||||
.delayed(AnimationStartDelay::Seconds(0.3))
|
||||
.submit_l(&mut panel.layout);
|
||||
|
||||
Animation::effect_label_fade_in(
|
||||
id_label_body,
|
||||
AnimationDuration::Seconds(0.5),
|
||||
AnimationEasing::OutQuint,
|
||||
)
|
||||
.delayed(AnimationStartDelay::Seconds(0.3))
|
||||
.submit_l(&mut panel.layout);
|
||||
}
|
||||
|
||||
panel
|
||||
.update_layout(app)
|
||||
.context("layout update failed")
|
||||
|
||||
@@ -2,7 +2,7 @@ use std::{cell::RefCell, rc::Rc, time::Duration};
|
||||
|
||||
use glam::Affine3A;
|
||||
use wgui::{
|
||||
animation::{Animation, AnimationDuration, AnimationEasing},
|
||||
animation::{Animation, AnimationEasing},
|
||||
color::WguiColor,
|
||||
components::button::ComponentButton,
|
||||
drawing::Color,
|
||||
@@ -97,10 +97,10 @@ fn start_progress_state(
|
||||
let id_rect_vu_meter = state.id_rect_vu_meter;
|
||||
let id_label_progress = state.id_label_progress;
|
||||
|
||||
Animation::new_ex(
|
||||
common.alterables.animate(Animation::new_ex(
|
||||
id_rect_vu_meter, /* any tbh */
|
||||
0,
|
||||
AnimationDuration::SecondsFixed(120.0), // max 120 seconds (whisper_stt MAX_DURATION is currently set to 30, account for processing time)
|
||||
60 * 120, // max 120 seconds (whisper_stt MAX_DURATION is currently set to 30, account for processing time)
|
||||
AnimationEasing::Linear,
|
||||
Box::new(move |common, data| {
|
||||
let rect_vu_meter = data.obj.cast_mut::<WidgetRectangle>().unwrap();
|
||||
@@ -156,8 +156,7 @@ fn start_progress_state(
|
||||
);
|
||||
}
|
||||
}),
|
||||
)
|
||||
.submit(common.alterables);
|
||||
));
|
||||
}
|
||||
|
||||
fn reset_progress_state(common: &mut CallbackDataCommon, state: &WhisperState) {
|
||||
|
||||
@@ -62,26 +62,24 @@
|
||||
},
|
||||
{
|
||||
"path": "/user/hand/right/input/trackpad",
|
||||
"mode": "trackpad",
|
||||
"mode": "scroll",
|
||||
"parameters": {
|
||||
"exponent" : "0.25",
|
||||
"maxzone_pct" : "5"
|
||||
"scroll_mode": "discrete"
|
||||
},
|
||||
"inputs": {
|
||||
"position": {
|
||||
"scroll": {
|
||||
"output": "/actions/default/in/scroll"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/user/hand/left/input/trackpad",
|
||||
"mode": "trackpad",
|
||||
"mode": "scroll",
|
||||
"parameters": {
|
||||
"exponent" : "0.25",
|
||||
"maxzone_pct" : "5"
|
||||
"scroll_mode": "discrete"
|
||||
},
|
||||
"inputs": {
|
||||
"position": {
|
||||
"scroll": {
|
||||
"output": "/actions/default/in/scroll"
|
||||
}
|
||||
}
|
||||
|
||||
+17
-217
@@ -1,14 +1,12 @@
|
||||
use glam::{FloatExt, Mat4, Vec2, Vec3};
|
||||
use glam::FloatExt;
|
||||
|
||||
use crate::{
|
||||
drawing::Boundary,
|
||||
event::{CallbackDataCommon, EventAlterables},
|
||||
layout::{Layout, LayoutState, WidgetID},
|
||||
renderer_vk::{self},
|
||||
widget::{WidgetData, WidgetObj, label::WidgetLabel, rectangle::WidgetRectangle, sprite::WidgetSprite},
|
||||
layout::{LayoutState, WidgetID},
|
||||
widget::{WidgetData, WidgetObj},
|
||||
};
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum AnimationEasing {
|
||||
Linear,
|
||||
InQuad, // ^2
|
||||
@@ -55,55 +53,12 @@ pub struct CallbackData<'a> {
|
||||
}
|
||||
|
||||
pub type AnimationCallback = Box<dyn Fn(&mut CallbackDataCommon, &mut CallbackData)>;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum AnimationDuration {
|
||||
Seconds(f32), // multiplied by animation_mult
|
||||
SecondsFixed(f32),
|
||||
Infinity,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum AnimationStartDelay {
|
||||
Seconds(f32), // multiplied by animation_mult
|
||||
SecondsFixed(f32),
|
||||
}
|
||||
|
||||
impl AnimationDuration {
|
||||
pub fn to_ticks(&self, ticks_per_seconds: u32, animation_mult: f32) -> u32 {
|
||||
match self {
|
||||
AnimationDuration::Seconds(secs) => (secs * ticks_per_seconds as f32 * animation_mult) as u32,
|
||||
AnimationDuration::SecondsFixed(secs) => (secs * ticks_per_seconds as f32) as u32,
|
||||
AnimationDuration::Infinity => u32::MAX,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AnimationStartDelay {
|
||||
pub fn to_ticks(&self, ticks_per_seconds: u32, animation_mult: f32) -> u32 {
|
||||
match self {
|
||||
AnimationStartDelay::Seconds(secs) => (secs * ticks_per_seconds as f32 * animation_mult) as u32,
|
||||
AnimationStartDelay::SecondsFixed(secs) => (secs * ticks_per_seconds as f32) as u32,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Ticks {
|
||||
delay: u32,
|
||||
remaining: u32,
|
||||
duration: u32,
|
||||
}
|
||||
|
||||
pub struct Animation {
|
||||
target_widget: WidgetID,
|
||||
|
||||
id: u32,
|
||||
duration: AnimationDuration,
|
||||
start_delay_secs: Option<AnimationStartDelay>,
|
||||
reversed: bool,
|
||||
|
||||
// filled-in at first iteration
|
||||
ticks: Option<Ticks>,
|
||||
ticks_remaining: u32,
|
||||
ticks_duration: u32,
|
||||
|
||||
easing: AnimationEasing,
|
||||
|
||||
@@ -115,136 +70,14 @@ pub struct Animation {
|
||||
}
|
||||
|
||||
impl Animation {
|
||||
pub fn new(
|
||||
target_widget: WidgetID,
|
||||
duration: AnimationDuration,
|
||||
easing: AnimationEasing,
|
||||
callback: AnimationCallback,
|
||||
) -> Self {
|
||||
Self::new_ex(target_widget, 0, duration, easing, callback)
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub const fn delayed(self, delay: AnimationStartDelay) -> Self {
|
||||
let mut this = self;
|
||||
this.start_delay_secs = Some(delay);
|
||||
this
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub const fn with_id(self, id: u32) -> Self {
|
||||
let mut this = self;
|
||||
this.id = id;
|
||||
this
|
||||
}
|
||||
|
||||
// invert pos with 1.0 - pos
|
||||
#[must_use]
|
||||
pub const fn reversed(self) -> Self {
|
||||
let mut this = self;
|
||||
this.reversed = true;
|
||||
this
|
||||
}
|
||||
|
||||
pub fn submit(self, alterables: &mut EventAlterables) {
|
||||
alterables.animate(self);
|
||||
}
|
||||
|
||||
pub fn submit_l(self, layout: &mut Layout) {
|
||||
self.submit(&mut layout.alterables);
|
||||
}
|
||||
|
||||
pub fn effect_slide(
|
||||
target_widget: WidgetID,
|
||||
duration: AnimationDuration,
|
||||
easing: AnimationEasing,
|
||||
dir: Vec2,
|
||||
) -> Self {
|
||||
Animation::new(
|
||||
target_widget,
|
||||
duration,
|
||||
easing,
|
||||
Box::new(move |common, data| {
|
||||
data.data.transform =
|
||||
Mat4::from_translation(Vec3::new((1.0 - data.pos) * dir.x, (1.0 - data.pos) * dir.y, 0.0));
|
||||
common.alterables.mark_redraw();
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn effect_scale(
|
||||
target_widget: WidgetID,
|
||||
duration: AnimationDuration,
|
||||
easing: AnimationEasing,
|
||||
from: Vec2,
|
||||
to: Vec2, // (1.0, 1.0) - normal scale
|
||||
) -> Self {
|
||||
Animation::new(
|
||||
target_widget,
|
||||
duration,
|
||||
easing,
|
||||
Box::new(move |common, data| {
|
||||
let scale = Vec3::new(from.x.lerp(to.x, data.pos), from.y.lerp(to.y, data.pos), 0.0);
|
||||
data.data.transform = renderer_vk::util::centered_matrix(data.widget_boundary.size, &Mat4::from_scale(scale));
|
||||
common.alterables.mark_redraw();
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn effect_label_fade_in(target_widget: WidgetID, duration: AnimationDuration, easing: AnimationEasing) -> Self {
|
||||
Animation::new(
|
||||
target_widget,
|
||||
duration,
|
||||
easing,
|
||||
Box::new(move |common, data| {
|
||||
let Ok(label) = data.obj.cast_mut::<WidgetLabel>() else {
|
||||
debug_assert!(false); // cast failed
|
||||
return;
|
||||
};
|
||||
label.set_color(common, label.get_color().with_alpha(data.pos), true);
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn effect_rectangle_fade_in(
|
||||
target_widget: WidgetID,
|
||||
duration: AnimationDuration,
|
||||
easing: AnimationEasing,
|
||||
) -> Self {
|
||||
Animation::new(
|
||||
target_widget,
|
||||
duration,
|
||||
easing,
|
||||
Box::new(move |common, data| {
|
||||
let Ok(rectangle) = data.obj.cast_mut::<WidgetRectangle>() else {
|
||||
debug_assert!(false); // cast failed
|
||||
return;
|
||||
};
|
||||
rectangle.set_color(common, rectangle.get_color().with_alpha(data.pos));
|
||||
rectangle.set_border_color(common, rectangle.get_border_color().with_alpha(data.pos));
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn effect_sprite_fade_in(target_widget: WidgetID, duration: AnimationDuration, easing: AnimationEasing) -> Self {
|
||||
Animation::new(
|
||||
target_widget,
|
||||
duration,
|
||||
easing,
|
||||
Box::new(move |common, data| {
|
||||
let Ok(sprite) = data.obj.cast_mut::<WidgetSprite>() else {
|
||||
debug_assert!(false); // cast failed
|
||||
return;
|
||||
};
|
||||
sprite.set_color(common, sprite.get_color().with_alpha(data.pos));
|
||||
}),
|
||||
)
|
||||
pub fn new(target_widget: WidgetID, ticks: u32, easing: AnimationEasing, callback: AnimationCallback) -> Self {
|
||||
Self::new_ex(target_widget, 0, ticks, easing, callback)
|
||||
}
|
||||
|
||||
pub fn new_ex(
|
||||
target_widget: WidgetID,
|
||||
animation_id: u32,
|
||||
duration: AnimationDuration,
|
||||
ticks: u32,
|
||||
easing: AnimationEasing,
|
||||
callback: AnimationCallback,
|
||||
) -> Self {
|
||||
@@ -253,25 +86,21 @@ impl Animation {
|
||||
id: animation_id,
|
||||
callback,
|
||||
easing,
|
||||
duration,
|
||||
ticks: None,
|
||||
ticks_duration: ticks,
|
||||
ticks_remaining: ticks,
|
||||
last_tick: false,
|
||||
pos: 0.0,
|
||||
pos_prev: 0.0,
|
||||
start_delay_secs: None,
|
||||
reversed: false,
|
||||
}
|
||||
}
|
||||
|
||||
/// @returns false if it wants to be stopped
|
||||
#[must_use]
|
||||
fn call(&self, state: &LayoutState, alterables: &mut EventAlterables, raw_pos: f32) -> bool {
|
||||
fn call(&self, state: &LayoutState, alterables: &mut EventAlterables, pos: f32) -> bool {
|
||||
let Some(widget) = state.widgets.get(self.target_widget).cloned() else {
|
||||
return false; // failed
|
||||
};
|
||||
|
||||
let pos = if self.reversed { 1.0 - raw_pos } else { raw_pos };
|
||||
|
||||
let mut widget_state = widget.state();
|
||||
let (data, obj) = widget_state.get_data_obj_mut();
|
||||
let mut stop_me = false;
|
||||
@@ -301,27 +130,8 @@ pub struct Animations {
|
||||
impl Animations {
|
||||
pub fn tick(&mut self, state: &LayoutState, alterables: &mut EventAlterables) {
|
||||
for anim in &mut self.running_animations {
|
||||
let mut ticks = anim.ticks.take().unwrap_or_else(|| {
|
||||
let ticks = anim
|
||||
.duration
|
||||
.to_ticks(state.ticks_per_second, state.theme.animation_mult);
|
||||
Ticks {
|
||||
remaining: ticks,
|
||||
duration: ticks,
|
||||
delay: anim.start_delay_secs.map_or(0, |delay| {
|
||||
delay.to_ticks(state.ticks_per_second, state.theme.animation_mult)
|
||||
}),
|
||||
}
|
||||
});
|
||||
|
||||
if ticks.delay > 0 {
|
||||
ticks.delay -= 1;
|
||||
anim.ticks = Some(ticks);
|
||||
continue;
|
||||
}
|
||||
|
||||
let x = 1.0 - (ticks.remaining as f32 / ticks.duration as f32);
|
||||
let pos = if ticks.remaining > 0 {
|
||||
let x = 1.0 - (anim.ticks_remaining as f32 / anim.ticks_duration as f32);
|
||||
let pos = if anim.ticks_remaining > 0 {
|
||||
anim.easing.interpolate(x)
|
||||
} else {
|
||||
anim.last_tick = true;
|
||||
@@ -335,10 +145,8 @@ impl Animations {
|
||||
let _ = anim.call(state, alterables, 1.0);
|
||||
alterables.needs_redraw = true;
|
||||
} else {
|
||||
ticks.remaining -= 1;
|
||||
anim.ticks_remaining -= 1;
|
||||
}
|
||||
|
||||
anim.ticks = Some(ticks);
|
||||
}
|
||||
|
||||
self.running_animations.retain(|anim| !anim.last_tick);
|
||||
@@ -347,23 +155,15 @@ impl Animations {
|
||||
pub fn process(&mut self, state: &LayoutState, alterables: &mut EventAlterables, alpha: f32) {
|
||||
for anim in &mut self.running_animations {
|
||||
let pos = anim.pos_prev.lerp(anim.pos, alpha);
|
||||
if !anim.call(state, alterables, pos)
|
||||
&& let Some(ticks) = &mut anim.ticks
|
||||
{
|
||||
ticks.remaining = 0;
|
||||
if !anim.call(state, alterables, pos) {
|
||||
anim.ticks_remaining = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add(&mut self, anim: Animation, state: &LayoutState, alterables: &mut EventAlterables) {
|
||||
pub fn add(&mut self, anim: Animation) {
|
||||
// prevent running two animations at once
|
||||
self.stop_by_widget(anim.target_widget, Some(anim.id));
|
||||
|
||||
// call the animation for the first time with pos 0.0
|
||||
if !anim.call(state, alterables, 0.0) {
|
||||
return;
|
||||
}
|
||||
|
||||
self.running_animations.push(anim);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::{
|
||||
animation::{Animation, AnimationDuration, AnimationEasing},
|
||||
animation::{Animation, AnimationEasing},
|
||||
assets::AssetPathRef,
|
||||
color::{ParentColor, WguiColor, WguiColorName},
|
||||
components::{
|
||||
@@ -266,15 +266,17 @@ impl ComponentButton {
|
||||
return;
|
||||
}
|
||||
|
||||
let gradient_intensity = {
|
||||
let (anim_mult, gradient_intensity) = {
|
||||
let theme = &common.state.theme;
|
||||
theme.gradient_intensity
|
||||
(theme.animation_mult, theme.gradient_intensity)
|
||||
};
|
||||
|
||||
let anim_ticks = if sticky_down { 5. } else { 10. };
|
||||
|
||||
let state = self.state.clone();
|
||||
let anim = Animation::new(
|
||||
self.data.id_rect,
|
||||
AnimationDuration::Seconds(if sticky_down { 0.083 } else { 0.1666 }),
|
||||
(anim_ticks * anim_mult) as _,
|
||||
AnimationEasing::OutCubic,
|
||||
Box::new(move |common, anim_data| {
|
||||
let rect = anim_data.obj.get_as_mut::<WidgetRectangle>().unwrap();
|
||||
@@ -381,10 +383,10 @@ fn anim_hover(
|
||||
rect.params.border_color = init_border_color.lerp(&globals.palette, &colors.hover_border_color, mult);
|
||||
}
|
||||
|
||||
fn anim_hover_create(state: Rc<RefCell<State>>, widget_id: WidgetID, fade_in: bool) -> Animation {
|
||||
fn anim_hover_create(state: Rc<RefCell<State>>, widget_id: WidgetID, fade_in: bool, anim_mult: f32) -> Animation {
|
||||
Animation::new(
|
||||
widget_id,
|
||||
AnimationDuration::Seconds(if fade_in { 0.0833 } else { 0.1666 }),
|
||||
((if fade_in { 5. } else { 10. }) * anim_mult) as _,
|
||||
AnimationEasing::OutCubic,
|
||||
Box::new(move |common, anim_data| {
|
||||
let rect = anim_data.obj.get_as_mut::<WidgetRectangle>().unwrap();
|
||||
@@ -411,6 +413,7 @@ fn register_event_mouse_enter(
|
||||
state: Rc<RefCell<State>>,
|
||||
listeners: &mut EventListenerCollection,
|
||||
tooltip_info: Option<components::tooltip::TooltipInfo>,
|
||||
anim_mult: f32,
|
||||
) -> EventListenerID {
|
||||
listeners.register(
|
||||
EventListenerKind::MouseEnter,
|
||||
@@ -420,7 +423,7 @@ fn register_event_mouse_enter(
|
||||
common.alterables.mark_redraw();
|
||||
common
|
||||
.alterables
|
||||
.animate(anim_hover_create(state.clone(), event_data.widget_id, true));
|
||||
.animate(anim_hover_create(state.clone(), event_data.widget_id, true, anim_mult));
|
||||
|
||||
ComponentTooltip::register_hover_in(common, &tooltip_info, data.id_rect, state.clone());
|
||||
|
||||
@@ -430,14 +433,18 @@ fn register_event_mouse_enter(
|
||||
)
|
||||
}
|
||||
|
||||
fn register_event_mouse_leave(state: Rc<RefCell<State>>, listeners: &mut EventListenerCollection) -> EventListenerID {
|
||||
fn register_event_mouse_leave(
|
||||
state: Rc<RefCell<State>>,
|
||||
listeners: &mut EventListenerCollection,
|
||||
anim_mult: f32,
|
||||
) -> EventListenerID {
|
||||
listeners.register(
|
||||
EventListenerKind::MouseLeave,
|
||||
Box::new(move |common, event_data, (), ()| {
|
||||
common.alterables.trigger_haptics();
|
||||
common
|
||||
.alterables
|
||||
.animate(anim_hover_create(state.clone(), event_data.widget_id, false));
|
||||
.animate(anim_hover_create(state.clone(), event_data.widget_id, false, anim_mult));
|
||||
let mut state = state.borrow_mut();
|
||||
state.active_tooltip = None;
|
||||
state.hovered = false;
|
||||
@@ -695,10 +702,11 @@ pub fn construct(ess: &mut ConstructEssentials, params: Params) -> anyhow::Resul
|
||||
id: root.id,
|
||||
lhandles: {
|
||||
let listeners = &mut root.widget.state().event_listeners;
|
||||
let anim_mult = ess.layout.state.theme.animation_mult;
|
||||
vec![
|
||||
register_event_mouse_cancel(state.clone(), listeners),
|
||||
register_event_mouse_enter(data.clone(), state.clone(), listeners, params.tooltip),
|
||||
register_event_mouse_leave(state.clone(), listeners),
|
||||
register_event_mouse_enter(data.clone(), state.clone(), listeners, params.tooltip, anim_mult),
|
||||
register_event_mouse_leave(state.clone(), listeners, anim_mult),
|
||||
register_event_mouse_press(state.clone(), listeners),
|
||||
register_event_mouse_release(data.clone(), state.clone(), listeners),
|
||||
]
|
||||
|
||||
@@ -8,7 +8,7 @@ use taffy::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
animation::{Animation, AnimationDuration, AnimationEasing},
|
||||
animation::{Animation, AnimationEasing},
|
||||
color::{WguiColor, WguiColorName},
|
||||
components::{
|
||||
Component, ComponentBase, ComponentTrait, DestroyData, RefreshData,
|
||||
@@ -182,11 +182,11 @@ fn anim_hover(anim_data: &mut crate::animation::CallbackData<'_>, pos: f32, _pre
|
||||
};
|
||||
}
|
||||
|
||||
fn anim_hover_in(state: &Rc<RefCell<State>>, data: &Rc<Data>) -> Animation {
|
||||
fn anim_hover_in(state: &Rc<RefCell<State>>, data: &Rc<Data>, anim_mult: f32) -> Animation {
|
||||
let down = state.borrow().down;
|
||||
Animation::new(
|
||||
data.id_outer_box,
|
||||
AnimationDuration::Seconds(0.0833),
|
||||
(5. * anim_mult) as _,
|
||||
AnimationEasing::OutQuad,
|
||||
Box::new(move |common, anim_data| {
|
||||
anim_hover(anim_data, anim_data.pos, down);
|
||||
@@ -195,11 +195,11 @@ fn anim_hover_in(state: &Rc<RefCell<State>>, data: &Rc<Data>) -> Animation {
|
||||
)
|
||||
}
|
||||
|
||||
fn anim_hover_out(state: &Rc<RefCell<State>>, data: &Rc<Data>) -> Animation {
|
||||
fn anim_hover_out(state: &Rc<RefCell<State>>, data: &Rc<Data>, anim_mult: f32) -> Animation {
|
||||
let down = state.borrow().down;
|
||||
Animation::new(
|
||||
data.id_outer_box,
|
||||
AnimationDuration::Seconds(0.0833),
|
||||
(8. * anim_mult) as _,
|
||||
AnimationEasing::OutQuad,
|
||||
Box::new(move |common, anim_data| {
|
||||
anim_hover(anim_data, 1.0 - anim_data.pos, down);
|
||||
@@ -213,12 +213,13 @@ fn register_event_mouse_enter(
|
||||
data: Rc<Data>,
|
||||
listeners: &mut EventListenerCollection,
|
||||
tooltip_info: Option<tooltip::TooltipInfo>,
|
||||
anim_mult: f32,
|
||||
) -> EventListenerID {
|
||||
listeners.register(
|
||||
EventListenerKind::MouseEnter,
|
||||
Box::new(move |common, _event_data, (), ()| {
|
||||
common.alterables.trigger_haptics();
|
||||
anim_hover_in(&state, &data).submit(common.alterables);
|
||||
common.alterables.animate(anim_hover_in(&state, &data, anim_mult));
|
||||
|
||||
ComponentTooltip::register_hover_in(common, &tooltip_info, data.id_container, state.clone());
|
||||
|
||||
@@ -246,12 +247,13 @@ fn register_event_mouse_leave(
|
||||
state: Rc<RefCell<State>>,
|
||||
data: Rc<Data>,
|
||||
listeners: &mut EventListenerCollection,
|
||||
anim_mult: f32,
|
||||
) -> EventListenerID {
|
||||
listeners.register(
|
||||
EventListenerKind::MouseLeave,
|
||||
Box::new(move |common, _event_data, (), ()| {
|
||||
common.alterables.trigger_haptics();
|
||||
anim_hover_out(&state, &data).submit(common.alterables);
|
||||
common.alterables.animate(anim_hover_out(&state, &data, anim_mult));
|
||||
|
||||
let checked = {
|
||||
let mut state = state.borrow_mut();
|
||||
@@ -507,9 +509,10 @@ pub fn construct(ess: &mut ConstructEssentials, params: Params) -> anyhow::Resul
|
||||
id: root.id,
|
||||
lhandles: {
|
||||
let listeners = &mut root.widget.state().event_listeners;
|
||||
let anim_mult = ess.layout.state.theme.animation_mult;
|
||||
vec![
|
||||
register_event_mouse_enter(state.clone(), data.clone(), listeners, params.tooltip),
|
||||
register_event_mouse_leave(state.clone(), data.clone(), listeners),
|
||||
register_event_mouse_enter(state.clone(), data.clone(), listeners, params.tooltip, anim_mult),
|
||||
register_event_mouse_leave(state.clone(), data.clone(), listeners, anim_mult),
|
||||
register_event_mouse_cancel(state.clone(), listeners),
|
||||
register_event_mouse_press(state.clone(), data.clone(), listeners),
|
||||
register_event_mouse_release(data.clone(), state.clone(), listeners),
|
||||
|
||||
@@ -7,7 +7,7 @@ use glam::FloatExt;
|
||||
use taffy::prelude::{auto, length, percent};
|
||||
|
||||
use crate::{
|
||||
animation::{Animation, AnimationDuration, AnimationEasing},
|
||||
animation::{Animation, AnimationEasing},
|
||||
color::{WguiColor, WguiColorName},
|
||||
components::{Component, ComponentBase, ComponentTrait, FocusChangeData, RefreshData},
|
||||
event::{self, CallbackDataCommon, CallbackMetadata, EventListenerCollection, EventListenerKind, StyleSetRequest},
|
||||
@@ -53,46 +53,58 @@ pub struct ComponentEditBox {
|
||||
state: Rc<RefCell<State>>,
|
||||
}
|
||||
|
||||
fn anim_bottom_rect(common: &mut CallbackDataCommon, accent_color: WguiColor, id_rect: WidgetID, focused: bool) {
|
||||
Animation::new(id_rect, AnimationDuration::Seconds(0.1666), AnimationEasing::OutQuad, {
|
||||
Box::new(move |common, data| {
|
||||
let rect = data.obj.get_as_mut::<WidgetRectangle>().unwrap();
|
||||
let pos_bidir = if focused { data.pos } else { 1.0 - data.pos };
|
||||
fn anim_bottom_rect(
|
||||
common: &mut CallbackDataCommon,
|
||||
accent_color: WguiColor,
|
||||
id_rect: WidgetID,
|
||||
anim_mult: f32,
|
||||
focused: bool,
|
||||
) {
|
||||
common.alterables.animate(Animation::new(
|
||||
id_rect,
|
||||
(10.0 * anim_mult) as _,
|
||||
AnimationEasing::OutQuad,
|
||||
{
|
||||
Box::new(move |common, data| {
|
||||
let rect = data.obj.get_as_mut::<WidgetRectangle>().unwrap();
|
||||
let pos_bidir = if focused { data.pos } else { 1.0 - data.pos };
|
||||
|
||||
let color_lerped = accent_color.lerp(
|
||||
&common.globals().palette,
|
||||
&WguiColorName::OnBackgroundVariant.into(),
|
||||
pos_bidir,
|
||||
);
|
||||
rect.set_color(common, color_lerped);
|
||||
let color_lerped = accent_color.lerp(
|
||||
&common.globals().palette,
|
||||
&WguiColorName::OnBackgroundVariant.into(),
|
||||
pos_bidir,
|
||||
);
|
||||
rect.set_color(common, color_lerped);
|
||||
|
||||
common.alterables.set_style(
|
||||
data.widget_id,
|
||||
StyleSetRequest::Size(taffy::Size {
|
||||
width: percent(0.95.lerp(1.0, pos_bidir)),
|
||||
height: length(1.0 + pos_bidir),
|
||||
}),
|
||||
);
|
||||
common.alterables.set_style(
|
||||
data.widget_id,
|
||||
StyleSetRequest::Size(taffy::Size {
|
||||
width: percent(0.95.lerp(1.0, pos_bidir)),
|
||||
height: length(1.0 + pos_bidir),
|
||||
}),
|
||||
);
|
||||
|
||||
common.alterables.set_style(
|
||||
data.widget_id,
|
||||
StyleSetRequest::Margin(taffy::Rect {
|
||||
bottom: length(pos_bidir),
|
||||
left: auto(),
|
||||
right: auto(),
|
||||
top: auto(),
|
||||
}),
|
||||
);
|
||||
common.alterables.set_style(
|
||||
data.widget_id,
|
||||
StyleSetRequest::Margin(taffy::Rect {
|
||||
bottom: length(pos_bidir),
|
||||
left: auto(),
|
||||
right: auto(),
|
||||
top: auto(),
|
||||
}),
|
||||
);
|
||||
|
||||
common.alterables.mark_redraw();
|
||||
})
|
||||
})
|
||||
.submit(common.alterables);
|
||||
common.alterables.mark_redraw();
|
||||
})
|
||||
},
|
||||
));
|
||||
}
|
||||
|
||||
fn refresh_all(common: &mut CallbackDataCommon, data: &Data, state: &mut State) -> Option<()> {
|
||||
let theme = &common.state.theme;
|
||||
let editbox_color = WguiColor::from(WguiColorName::BackgroundVariant);
|
||||
let accent_color = WguiColor::from(WguiColorName::Primary);
|
||||
let anim_mult = theme.animation_mult;
|
||||
|
||||
let (rect_color, border_color) = if state.focused {
|
||||
(editbox_color.add_rgb(0.15), editbox_color.add_rgb(0.15 + 0.25))
|
||||
@@ -108,7 +120,7 @@ fn refresh_all(common: &mut CallbackDataCommon, data: &Data, state: &mut State)
|
||||
rect.set_color(common, rect_color);
|
||||
|
||||
if state.focused_prev != state.focused || state.first_refresh {
|
||||
anim_bottom_rect(common, accent_color, data.id_rect_bottom, state.focused);
|
||||
anim_bottom_rect(common, accent_color, data.id_rect_bottom, anim_mult, state.focused);
|
||||
state.focused_prev = state.focused;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ use glam::{Mat4, Vec2, Vec3};
|
||||
use taffy::prelude::{length, percent};
|
||||
|
||||
use crate::{
|
||||
animation::{Animation, AnimationCallback, AnimationDuration, AnimationEasing},
|
||||
animation::{Animation, AnimationCallback, AnimationEasing},
|
||||
color::{WguiColor, WguiColorName},
|
||||
components::{
|
||||
Component, ComponentBase, ComponentTrait, DestroyData, RefreshData,
|
||||
@@ -404,23 +404,53 @@ fn get_callback_label(inverse: bool) -> AnimationCallback {
|
||||
})
|
||||
}
|
||||
|
||||
fn on_enter_anim(common: &mut event::CallbackDataCommon, id_handle: WidgetID, id_label: Option<WidgetID>) {
|
||||
let duration = AnimationDuration::Seconds(0.333);
|
||||
fn on_enter_anim(
|
||||
common: &mut event::CallbackDataCommon,
|
||||
id_handle: WidgetID,
|
||||
id_label: Option<WidgetID>,
|
||||
anim_mult: f32,
|
||||
) {
|
||||
let duration = 20. * anim_mult;
|
||||
|
||||
Animation::new(id_handle, duration, AnimationEasing::OutBack, get_callback_rect(false)).submit(common.alterables);
|
||||
common.alterables.animate(Animation::new(
|
||||
id_handle,
|
||||
duration as _,
|
||||
AnimationEasing::OutBack,
|
||||
get_callback_rect(false),
|
||||
));
|
||||
|
||||
if let Some(id_label) = id_label {
|
||||
Animation::new(id_label, duration, AnimationEasing::OutBack, get_callback_label(false)).submit(common.alterables);
|
||||
common.alterables.animate(Animation::new(
|
||||
id_label,
|
||||
duration as _,
|
||||
AnimationEasing::OutBack,
|
||||
get_callback_label(false),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
fn on_leave_anim(common: &mut event::CallbackDataCommon, id_handle: WidgetID, id_label: Option<WidgetID>) {
|
||||
let duration = AnimationDuration::Seconds(0.0833);
|
||||
fn on_leave_anim(
|
||||
common: &mut event::CallbackDataCommon,
|
||||
id_handle: WidgetID,
|
||||
id_label: Option<WidgetID>,
|
||||
anim_mult: f32,
|
||||
) {
|
||||
let duration = 10. * anim_mult;
|
||||
|
||||
Animation::new(id_handle, duration, AnimationEasing::OutQuad, get_callback_rect(true)).submit(common.alterables);
|
||||
common.alterables.animate(Animation::new(
|
||||
id_handle,
|
||||
duration as _,
|
||||
AnimationEasing::OutQuad,
|
||||
get_callback_rect(true),
|
||||
));
|
||||
|
||||
if let Some(id_label) = id_label {
|
||||
Animation::new(id_label, duration, AnimationEasing::OutQuad, get_callback_label(true)).submit(common.alterables);
|
||||
common.alterables.animate(Animation::new(
|
||||
id_label,
|
||||
duration as _,
|
||||
AnimationEasing::OutQuad,
|
||||
get_callback_label(true),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -469,7 +499,13 @@ fn get_handle_dist(common: &mut CallbackDataCommon, handle: &SliderHandleData, m
|
||||
|
||||
const MAX_HOVER_DIST: f32 = 64.0;
|
||||
|
||||
fn update_handle_hovers(common: &mut CallbackDataCommon, data: &Data, state: &mut State, mouse_pos: Vec2) {
|
||||
fn update_handle_hovers(
|
||||
common: &mut CallbackDataCommon,
|
||||
data: &Data,
|
||||
state: &mut State,
|
||||
anim_mult: f32,
|
||||
mouse_pos: Vec2,
|
||||
) {
|
||||
let hovered1_prev = state.hovered1;
|
||||
let hovered2_prev = state.hovered2;
|
||||
|
||||
@@ -500,9 +536,9 @@ fn update_handle_hovers(common: &mut CallbackDataCommon, data: &Data, state: &mu
|
||||
// hover state changed, run animations
|
||||
if state.hovered1 != hovered1_prev {
|
||||
if state.hovered1 && !hovered1_prev {
|
||||
on_enter_anim(common, data.handle1.id_handle_rect, data.handle1.id_label);
|
||||
on_enter_anim(common, data.handle1.id_handle_rect, data.handle1.id_label, anim_mult);
|
||||
} else {
|
||||
on_leave_anim(common, data.handle1.id_handle_rect, data.handle1.id_label);
|
||||
on_leave_anim(common, data.handle1.id_handle_rect, data.handle1.id_label, anim_mult);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -510,9 +546,9 @@ fn update_handle_hovers(common: &mut CallbackDataCommon, data: &Data, state: &mu
|
||||
&& let Some(handle2) = data.handle2.as_ref()
|
||||
{
|
||||
if state.hovered2 && !hovered2_prev {
|
||||
on_enter_anim(common, handle2.id_handle_rect, handle2.id_label);
|
||||
on_enter_anim(common, handle2.id_handle_rect, handle2.id_label, anim_mult);
|
||||
} else {
|
||||
on_leave_anim(common, handle2.id_handle_rect, handle2.id_label);
|
||||
on_leave_anim(common, handle2.id_handle_rect, handle2.id_label, anim_mult);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -521,6 +557,7 @@ fn register_event_mouse_motion(
|
||||
data: Rc<Data>,
|
||||
state: Rc<RefCell<State>>,
|
||||
listeners: &mut EventListenerCollection,
|
||||
anim_mult: f32,
|
||||
) -> event::EventListenerID {
|
||||
listeners.register(
|
||||
EventListenerKind::MouseMotion,
|
||||
@@ -538,7 +575,7 @@ fn register_event_mouse_motion(
|
||||
unreachable!();
|
||||
};
|
||||
|
||||
update_handle_hovers(common, &data, &mut state, pos_relative);
|
||||
update_handle_hovers(common, &data, &mut state, anim_mult, pos_relative);
|
||||
|
||||
if let Some(dragged_by) = &state.dragged_by
|
||||
&& dragged_by.device == pos.device
|
||||
@@ -732,10 +769,11 @@ pub fn construct(ess: &mut ConstructEssentials, params: Params) -> anyhow::Resul
|
||||
id: root.id,
|
||||
lhandles: {
|
||||
let listeners = &mut root.widget.state().event_listeners;
|
||||
let anim_mult = ess.layout.state.theme.animation_mult;
|
||||
vec![
|
||||
register_event_mouse_enter(state.clone(), listeners, params.tooltip),
|
||||
register_event_mouse_leave(state.clone(), listeners),
|
||||
register_event_mouse_motion(data.clone(), state.clone(), listeners),
|
||||
register_event_mouse_motion(data.clone(), state.clone(), listeners, anim_mult),
|
||||
register_event_mouse_press(data.clone(), state.clone(), listeners),
|
||||
register_event_mouse_release(state.clone(), listeners),
|
||||
]
|
||||
|
||||
@@ -3,7 +3,7 @@ use std::{cell::RefCell, rc::Rc};
|
||||
use taffy::prelude::length;
|
||||
|
||||
use crate::{
|
||||
animation::{Animation, AnimationDuration, AnimationEasing},
|
||||
animation::{Animation, AnimationEasing},
|
||||
color::{WguiColor, WguiColorName},
|
||||
components::{self, Component, ComponentBase, ComponentTrait, RefreshData},
|
||||
event::CallbackDataCommon,
|
||||
@@ -292,34 +292,39 @@ pub fn construct(ess: &mut ConstructEssentials, params: Params) -> anyhow::Resul
|
||||
TooltipSide::Bottom => Vec2::new(0.0, 1.0),
|
||||
};
|
||||
|
||||
Animation::new(rect.id, AnimationDuration::Seconds(0.1666), AnimationEasing::OutQuad, {
|
||||
Box::new(move |common, data| {
|
||||
let rect = data.obj.get_as_mut::<WidgetRectangle>().unwrap(); /* safe */
|
||||
let alpha = data.pos;
|
||||
rect.params.color = rect.params.color.with_alpha(alpha);
|
||||
rect.params.border_color = rect.params.border_color.with_alpha(alpha);
|
||||
let anim_mult = ess.layout.state.theme.animation_mult;
|
||||
ess.layout.animations.add(Animation::new(
|
||||
rect.id,
|
||||
(10.0 * anim_mult) as u32,
|
||||
AnimationEasing::OutQuad,
|
||||
{
|
||||
Box::new(move |common, data| {
|
||||
let rect = data.obj.get_as_mut::<WidgetRectangle>().unwrap(); /* safe */
|
||||
let alpha = data.pos;
|
||||
rect.params.color = rect.params.color.with_alpha(alpha);
|
||||
rect.params.border_color = rect.params.border_color.with_alpha(alpha);
|
||||
|
||||
let position_shift = state.borrow().position_shift;
|
||||
let position_shift = state.borrow().position_shift;
|
||||
|
||||
let dir_mult = (1.0 - data.pos) * 5.0;
|
||||
data.data.transform = Mat4::from_translation(Vec3::new(
|
||||
direction.x * dir_mult + position_shift.x,
|
||||
direction.y * dir_mult + position_shift.y,
|
||||
0.0,
|
||||
));
|
||||
let dir_mult = (1.0 - data.pos) * 5.0;
|
||||
data.data.transform = Mat4::from_translation(Vec3::new(
|
||||
direction.x * dir_mult + position_shift.x,
|
||||
direction.y * dir_mult + position_shift.y,
|
||||
0.0,
|
||||
));
|
||||
|
||||
if let Some(mut label) = common.state.widgets.get_as::<WidgetLabel>(label.id) {
|
||||
label.set_color(
|
||||
common,
|
||||
WguiColor::from(WguiColorName::OnBackground).with_alpha(alpha),
|
||||
true,
|
||||
);
|
||||
}
|
||||
if let Some(mut label) = common.state.widgets.get_as::<WidgetLabel>(label.id) {
|
||||
label.set_color(
|
||||
common,
|
||||
WguiColor::from(WguiColorName::OnBackground).with_alpha(alpha),
|
||||
true,
|
||||
);
|
||||
}
|
||||
|
||||
common.alterables.mark_redraw();
|
||||
})
|
||||
})
|
||||
.submit_l(ess.layout);
|
||||
common.alterables.mark_redraw();
|
||||
})
|
||||
},
|
||||
));
|
||||
|
||||
ess.layout.defer_component_refresh(Component(tooltip.clone()));
|
||||
Ok((div, tooltip))
|
||||
|
||||
@@ -2,7 +2,7 @@ use image::ImageBuffer;
|
||||
use taffy::prelude::percent;
|
||||
|
||||
use crate::{
|
||||
animation::{Animation, AnimationDuration},
|
||||
animation::Animation,
|
||||
assets::AssetPathRef,
|
||||
color::WguiColorName,
|
||||
components::{Component, ComponentBase, ComponentTrait, RefreshData},
|
||||
@@ -112,10 +112,10 @@ impl ComponentVideo {
|
||||
let start_time = get_millis();
|
||||
// log::info!("num frames: {}", source.demuxer.num_frames);
|
||||
|
||||
Animation::new_ex(
|
||||
layout.animations.add(Animation::new_ex(
|
||||
self.data.id_image,
|
||||
PLAYBACK_ANIMATION_ID,
|
||||
AnimationDuration::Infinity,
|
||||
u32::MAX, // infinity
|
||||
crate::animation::AnimationEasing::Linear,
|
||||
Box::new({
|
||||
let state_ref = self.state.clone();
|
||||
@@ -163,8 +163,7 @@ impl ComponentVideo {
|
||||
}
|
||||
}
|
||||
}),
|
||||
)
|
||||
.submit_l(layout);
|
||||
));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
+2
-4
@@ -129,7 +129,6 @@ pub struct LayoutState {
|
||||
pub nodes: WidgetNodeMap,
|
||||
pub tree: taffy::tree::TaffyTree<WidgetID>,
|
||||
pub components_by_widget_id: SecondaryMap<WidgetID, ComponentWeak>,
|
||||
pub ticks_per_second: u32,
|
||||
}
|
||||
|
||||
pub struct ModifyLayoutStateData<'a> {
|
||||
@@ -573,7 +572,6 @@ impl Layout {
|
||||
globals,
|
||||
theme: params.theme,
|
||||
components_by_widget_id: SecondaryMap::default(),
|
||||
ticks_per_second: 60, // hard-coded
|
||||
};
|
||||
|
||||
let size = if params.resize_to_parent {
|
||||
@@ -757,7 +755,7 @@ impl Layout {
|
||||
while let Some(task) = tasks.pop_front() {
|
||||
match task {
|
||||
LayoutTask::PlayAnimation(animation) => {
|
||||
self.alterables.animate(animation);
|
||||
self.animations.add(animation);
|
||||
}
|
||||
LayoutTask::RefreshPalette => {
|
||||
let root = self.tree_root_widget;
|
||||
@@ -896,7 +894,7 @@ impl Layout {
|
||||
if !alterables.animations.is_empty() {
|
||||
self.mark_redraw();
|
||||
for anim in alterables.animations {
|
||||
self.animations.add(anim, &self.state, &mut self.alterables);
|
||||
self.animations.add(anim);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ impl TooltipAttribs {
|
||||
pub fn get_info(self) -> Option<tooltip::TooltipInfo> {
|
||||
self.tooltip.map(|text| tooltip::TooltipInfo {
|
||||
text,
|
||||
side: self.tooltip_side.unwrap_or(tooltip::TooltipSide::Top),
|
||||
side: self.tooltip_side.map_or(tooltip::TooltipSide::Top, |f| f),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -971,8 +971,10 @@ fn process_attribs<'a>(
|
||||
ctx.doc_params.path.get_str()
|
||||
);
|
||||
}
|
||||
} else if let Some(pair) = process_attrib(&file.template_parameters, ctx, key, value) {
|
||||
res.push(pair);
|
||||
} else {
|
||||
if let Some(pair) = process_attrib(&file.template_parameters, ctx, key, value) {
|
||||
res.push(pair);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+5
-15
@@ -38,7 +38,7 @@ pub struct WidgetData {
|
||||
scrolling_cur: Vec2, // normalized, used for smooth scrolling animation
|
||||
scrolling_cur_prev: Vec2, // for motion interpolation while rendering between ticks
|
||||
scrolling_velocity: Vec2,
|
||||
press_down_start_mouse_pos: Option<(Vec2, DeviceBitmask)>,
|
||||
press_down_start_mouse_pos: Option<Vec2>,
|
||||
swipe_running: bool,
|
||||
swipe_scroll_start: Vec2, // normalized, 0.0-1.0
|
||||
pub transform: glam::Mat4,
|
||||
@@ -588,9 +588,7 @@ impl WidgetState {
|
||||
self.data.press_down_start_mouse_pos = None;
|
||||
}
|
||||
Event::MouseMotion(e) => {
|
||||
if let Some((start_mouse_pos, start_device)) = &self.data.press_down_start_mouse_pos
|
||||
&& *start_device == e.device
|
||||
{
|
||||
if let Some(start_mouse_pos) = &self.data.press_down_start_mouse_pos {
|
||||
let (active_x, active_y) = get_scroll_active_axis(params.style, params.taffy_layout);
|
||||
|
||||
if !self.data.swipe_running
|
||||
@@ -608,16 +606,8 @@ impl WidgetState {
|
||||
|
||||
let mult = scrollbar_info.get_potential_scroll_axis_multiplier(params.taffy_layout);
|
||||
|
||||
let scroll_diff_x = if mult.x == 0.0 || !active_x {
|
||||
0.0
|
||||
} else {
|
||||
-mouse_diff.x / mult.x
|
||||
};
|
||||
let scroll_diff_y = if mult.y == 0.0 || !active_y {
|
||||
0.0
|
||||
} else {
|
||||
-mouse_diff.y / mult.y
|
||||
};
|
||||
let scroll_diff_x = if mult.x == 0.0 { 0.0 } else { -mouse_diff.x / mult.x };
|
||||
let scroll_diff_y = if mult.y == 0.0 { 0.0 } else { -mouse_diff.y / mult.y };
|
||||
|
||||
self.data.scrolling_target = self.data.swipe_scroll_start + Vec2::new(scroll_diff_x, scroll_diff_y);
|
||||
params.alterables.mark_tick(self.obj.get_id());
|
||||
@@ -650,7 +640,7 @@ impl WidgetState {
|
||||
return;
|
||||
}
|
||||
|
||||
self.data.press_down_start_mouse_pos = Some((evt.pos, evt.device));
|
||||
self.data.press_down_start_mouse_pos = Some(evt.pos);
|
||||
self.data.swipe_scroll_start = self.data.scrolling_target;
|
||||
}
|
||||
|
||||
|
||||
@@ -44,18 +44,10 @@ impl WidgetRectangle {
|
||||
common.mark_widget_dirty(self.id);
|
||||
}
|
||||
|
||||
pub const fn get_color(&self) -> WguiColor {
|
||||
self.params.color
|
||||
}
|
||||
|
||||
pub fn set_border_color(&mut self, common: &mut CallbackDataCommon, color: WguiColor) {
|
||||
self.params.border_color = color;
|
||||
common.mark_widget_dirty(self.id);
|
||||
}
|
||||
|
||||
pub const fn get_border_color(&self) -> WguiColor {
|
||||
self.params.border_color
|
||||
}
|
||||
}
|
||||
|
||||
impl WidgetObj for WidgetRectangle {
|
||||
|
||||
@@ -4,7 +4,7 @@ use glam::Vec2;
|
||||
use taffy::prelude::{length, percent};
|
||||
|
||||
use crate::{
|
||||
animation::{Animation, AnimationDuration, AnimationEasing},
|
||||
animation::{Animation, AnimationEasing},
|
||||
assets::AssetPathRef,
|
||||
components::button::ComponentButton,
|
||||
drawing,
|
||||
@@ -183,17 +183,16 @@ impl WguiWindow {
|
||||
)?;
|
||||
|
||||
// Fade animation
|
||||
Animation::new(
|
||||
params.layout.animations.add(Animation::new(
|
||||
widget.id,
|
||||
AnimationDuration::Seconds(0.333),
|
||||
20,
|
||||
AnimationEasing::OutQuad,
|
||||
Box::new(|common, data| {
|
||||
let rect = data.obj.get_as_mut::<WidgetRectangle>().unwrap() /* should always succeed */;
|
||||
rect.params.color = drawing::Color::new(0.0, 0.0, 0.0, data.pos * 0.3).into();
|
||||
common.alterables.mark_redraw();
|
||||
}),
|
||||
)
|
||||
.submit_l(params.layout);
|
||||
));
|
||||
|
||||
Some(widget)
|
||||
} else {
|
||||
@@ -217,15 +216,6 @@ impl WguiWindow {
|
||||
|
||||
let globals = params.layout.state.globals.clone();
|
||||
|
||||
// window slide animation
|
||||
Animation::effect_slide(
|
||||
widget.id,
|
||||
AnimationDuration::Seconds(0.5),
|
||||
AnimationEasing::OutQuint,
|
||||
Vec2::new(0.0, 16.0),
|
||||
)
|
||||
.submit_l(params.layout);
|
||||
|
||||
let content_id = if params.extra.with_decorations {
|
||||
let xml_path: AssetPathRef = AssetPathRef::WguiInternal("wgui/window_frame.xml");
|
||||
|
||||
|
||||
Reference in new issue
Block a user