edit overlay design

This commit is contained in:
galister
2025-11-12 23:27:26 +09:00
parent 278420b2ce
commit d26ddd66bd
5 changed files with 78 additions and 32 deletions

View File

@@ -1,7 +1,7 @@
use std::{cell::RefCell, rc::Rc};
use taffy::{
AlignItems, JustifyContent,
prelude::{length, percent},
AlignItems, JustifyContent,
};
use crate::{
@@ -13,10 +13,10 @@ use crate::{
layout::{self, WidgetID, WidgetPair},
renderer_vk::text::{FontWeight, TextStyle},
widget::{
ConstructEssentials, EventResult,
label::{WidgetLabel, WidgetLabelParams},
rectangle::{WidgetRectangle, WidgetRectangleParams},
util::WLength,
ConstructEssentials, EventResult,
},
};

View File

@@ -15,11 +15,11 @@ use crate::{
util,
},
widget::{
ConstructEssentials, EventResult,
div::WidgetDiv,
label::{WidgetLabel, WidgetLabelParams},
rectangle::{WidgetRectangle, WidgetRectangleParams},
util::WLength,
ConstructEssentials, EventResult,
},
};
@@ -50,6 +50,7 @@ struct State {
dragging: bool,
hovered: bool,
values: ValuesMinMax,
on_value_changed: Option<SliderValueChangedCallback>,
}
struct Data {
@@ -61,6 +62,13 @@ struct Data {
slider_body_node: taffy::NodeId,
}
pub struct SliderValueChangedEvent {
pub value: f32,
}
pub type SliderValueChangedCallback =
Box<dyn Fn(&mut CallbackDataCommon, SliderValueChangedEvent) -> anyhow::Result<()>>;
pub struct ComponentSlider {
base: ComponentBase,
data: Rc<Data>,
@@ -79,6 +87,20 @@ impl ComponentTrait for ComponentSlider {
}
}
impl ComponentSlider {
pub fn get_value(&self) -> f32 {
self.state.borrow().values.value
}
pub fn set_value(&mut self, common: &mut CallbackDataCommon, value: f32) {
let mut state = self.state.borrow_mut();
state.set_value(common, &self.data, value);
}
pub fn on_value_changed(&self, func: SliderValueChangedCallback) {
self.state.borrow_mut().on_value_changed = Some(func);
}
}
// NOTICE: this can be re-used in the future
fn map_mouse_x_to_normalized(mouse_x_rel: f32, widget_width: f32) -> f32 {
(mouse_x_rel / widget_width).clamp(0.0, 1.0)
@@ -137,6 +159,9 @@ impl State {
fn set_value(&mut self, common: &mut CallbackDataCommon, data: &Data, value: f32) {
//common.call_on_widget(data.slider_handle_id, |_div: &mut Div| {});
let changed = (self.values.value - value).abs() > f32::EPSILON;
self.values.value = value;
let mut style = common.state.tree.style(data.slider_handle_node).unwrap().clone();
conf_handle_style(&self.values, data.slider_body_node, &mut style, &common.state.tree);
@@ -147,6 +172,12 @@ impl State {
if let Some(mut label) = common.state.widgets.get_as::<WidgetLabel>(data.slider_text_id) {
Self::update_text(common, &mut label, value);
}
if changed && let Some(on_value_changed) = &self.on_value_changed {
if let Err(e) = on_value_changed(common, SliderValueChangedEvent { value }) {
log::error!("{e:?}"); // FIXME: proper error handling
}
}
}
}
@@ -362,6 +393,7 @@ pub fn construct(ess: &mut ConstructEssentials, params: Params) -> anyhow::Resul
dragging: false,
hovered: false,
values: params.values,
on_value_changed: None,
};
let globals = ess.layout.state.globals.clone();

View File

@@ -4,40 +4,54 @@
<var key="tint_color" value="#0044CC99" />
</theme>
<template name="TopButton">
<rectangle id="~id" color="~bg_color" padding="8" round="50%">
<sprite color="~device_color" width="48" height="48" src="${src}" />
</rectangle>
</template>
<macro name="button_style"
margin="2" overflow="hidden" box_sizing="border_box" align_items="center" justify_content="center"
border_color="#0044CC" border="2" round="8" color="#000A1C" color2="#000002" gradient="vertical" />
border="2" round="50%" padding="8" gradient="vertical" tooltip_side="bottom" />
<template name="TopButton">
<Button id="${id}" macro="button_style" tooltip="${tooltip}" _press="${press}" border_color="#0044CC" color="#000A1C" color2="#000002" >
<sprite color="~device_color" width="48" height="48" src="${src}" />
</Button>
</template>
<template name="TopButtonDanger">
<Button id="${id}" macro="button_style" tooltip="${tooltip}" _press="${press}" border_color="#CC0000" color="#110000" color2="#020000" >
<sprite color="~device_color" width="48" height="48" src="${src}" />
</Button>
</template>
<template name="TopButtonFaded">
<Button id="${id}" macro="button_style" tooltip="${tooltip}" _press="${press}" border_color="#707070" color="#202020" color2="#010101" >
<sprite color="~device_color" width="48" height="48" src="${src}" />
</Button>
</template>
<elements>
<div width="100%" height="100%">
<rectangle width="100%" height="100%" padding="4" gap="4" align_items="center" justify_content="center" color="#000000DD" flex_direction="row">
<div></div>
<div flex_direction="column">
<div></div>
<rectangle padding="10" gap="8" round="100%" color="~bg_color" justify_content="center" >
<TopButton id="lock" src="bar/lock_open.svg" />
<TopButton id="anchor" src="bar/anchor.svg" />
<TopButton id="mouse" src="bar/mouse.svg" />
<TopButton id="fade" src="bar/fade.svg" />
<TopButton id="move" src="bar/move-all.svg" />
<TopButton id="resize" src="bar/resize.svg" />
<TopButton id="inout" src="bar/inout.svg" />
<TopButton id="delete" src="bar/delete.svg" />
</rectangle>
<rectangle padding="8" gap="8" round="100%" color="~bg_color_active" justify_content="center" align_items="center">
<label text="range 10-20 value 15" />
<Slider width="200" height="16" min_value="10" max_value="20" value="15" />
<CheckBox id="test0" text="AM/PM clock" />
</rectangle>
<div></div>
<rectangle padding="20" gap="8" round="100%" color="~bg_color" justify_content="center" >
<div flex_direction="column" gap="8">
<label align="center" translation="Point on a window to change its parameters.&#xA;Once done, leave edit mode using the button on the right." />
<div flex_direction="row" gap="4">
<TopButton id="lock" src="bar/lock_open.svg" tooltip="Lock interaction" kind="btn_primary" />
<TopButton id="anchor" src="bar/anchor.svg" tooltip="Positioning" kind="btn_primary" />
<TopButton id="fade" src="bar/fade.svg" tooltip="Opacity" kind="btn_primary" />
<TopButton id="move" src="bar/move-all.svg" tooltip="Move (click &amp; drag)" kind="btn_primary" />
<TopButton id="resize" src="bar/resize.svg" tooltip="Resize (click &amp; drag)" kind="btn_primary" />
<TopButton id="inout" src="bar/inout.svg" tooltip="Adjust distance (click &amp; drag)" kind="btn_primary" />
<TopButtonDanger id="delete" src="bar/delete.svg" tooltip="Delete" kind="btn_danger" />
<div width="8" height="100%" />
<TopButtonFaded src="watch/edit.svg" tooltip="Leave edit mode" press="::EditToggle" kind="btn_faded" />
</div>
<div padding="8" gap="8" justify_content="center" align_items="center">
<label translation="Opacity" />
<Slider width="200" height="16" min_value="5" max_value="100" value="100" />
<CheckBox id="additive" translation="Additive" tooltip="Alpha blend mode" tooltip_side="bottom" />
</div>
</div>
<div></div>
</rectangle>
</div>
</rectangle>
</div>
</elements>

View File

@@ -4,7 +4,7 @@ use std::{collections::VecDeque, time::Instant};
use glam::{Affine3A, Vec2, Vec3, Vec3A, Vec3Swizzles};
use smallvec::{SmallVec, smallvec};
use smallvec::{smallvec, SmallVec};
use crate::overlays::anchor::ANCHOR_NAME;
use crate::state::{AppSession, AppState};
@@ -521,6 +521,7 @@ where
let pointer = &mut app.input_state.pointers[pointer_idx];
let ray_origin = pointer.pose;
let mode = pointer.interaction.mode;
let edit_mode = overlays.get_edit_mode();
let mut hits: SmallVec<[RayHit; 8]> = smallvec!();
@@ -528,7 +529,7 @@ where
let Some(overlay_state) = overlay.config.active_state.as_ref() else {
continue;
};
if !overlay_state.interactable {
if !overlay_state.interactable && !edit_mode {
continue;
}

View File

@@ -60,7 +60,6 @@ pub(super) fn setup_custom_button<S: 'static>(
"::WatchHide" => todo!(),
"::WatchSwapHand" => todo!(),
// TODO
#[allow(clippy::match_same_arms)]
"::EditToggle" => Box::new(move |_common, _data, app, _| {
app.tasks.enqueue(TaskType::ToggleEditMode);
Ok(EventResult::Consumed)