use crate::fyrox::{
core::{
algebra::{Point2, Vector2},
pool::Handle,
reflect::prelude::*,
type_traits::prelude::*,
uuid_provider,
visitor::prelude::*,
},
gui::{
define_widget_deref,
draw::{CommandTexture, Draw, DrawingContext},
message::UiMessage,
widget::{Widget, WidgetBuilder},
BuildContext, Control, UiNode, UserInterface,
},
};
use fyrox::gui::curve::CurveTransformCell;
use fyrox::gui::message::MessageData;
use fyrox::gui::style::resource::StyleResourceExt;
use fyrox::gui::style::Style;
#[derive(Debug, Clone, PartialEq)]
pub enum ThumbMessage {
Zoom(f32),
ViewPosition(f32),
Position(f32),
}
impl MessageData for ThumbMessage {}
#[derive(Clone, Visit, Reflect, Debug, ComponentProvider)]
#[reflect(derived_type = "UiNode")]
pub struct Thumb {
widget: Widget,
#[visit(skip)]
#[reflect(hidden)]
transform: CurveTransformCell,
position: f32,
}
define_widget_deref!(Thumb);
impl Thumb {
fn local_to_view(&self, x: f32) -> f32 {
self.transform
.curve_to_local()
.transform_point(&Point2::new(x, 0.0))
.x
}
}
uuid_provider!(Thumb = "820ba009-54e0-4050-ba7e-28f1f5b40429");
impl Control for Thumb {
fn draw(&self, ctx: &mut DrawingContext) {
self.transform.set_bounds(self.screen_bounds());
self.transform.update_transform();
let local_bounds = self.bounding_rect();
let half_width = 5.0;
let view_position = self.local_to_view(self.position);
let origin = Vector2::new(view_position, 0.0);
ctx.push_triangle_filled([
origin - Vector2::new(half_width, 0.0),
origin + Vector2::new(half_width, 0.0),
origin + Vector2::new(0.0, 2.0 * half_width),
]);
ctx.push_line(origin, origin + Vector2::new(0.0, local_bounds.h()), 1.0);
ctx.commit(
self.clip_bounds(),
self.foreground(),
CommandTexture::None,
&self.material,
None,
);
}
fn handle_routed_message(&mut self, ui: &mut UserInterface, message: &mut UiMessage) {
self.widget.handle_routed_message(ui, message);
if let Some(msg) = message.data_for::<ThumbMessage>(self.handle) {
match msg {
ThumbMessage::Zoom(zoom) => {
self.transform.set_scale(Vector2::new(*zoom, 1.0));
self.invalidate_visual();
}
ThumbMessage::ViewPosition(position) => {
self.transform.set_position(Vector2::new(*position, 0.0));
self.invalidate_visual();
}
ThumbMessage::Position(value) => {
if value.ne(&self.position) {
self.position = *value;
ui.send_message(message.reverse());
self.invalidate_visual();
}
}
}
}
}
}
pub struct ThumbBuilder {
widget_builder: WidgetBuilder,
}
impl ThumbBuilder {
pub fn new(widget_builder: WidgetBuilder) -> Self {
Self { widget_builder }
}
pub fn build(self, ctx: &mut BuildContext) -> Handle<Thumb> {
let ruler = Thumb {
widget: self
.widget_builder
.with_hit_test_visibility(false)
.with_foreground(ctx.style.property(Style::BRUSH_BRIGHT))
.build(ctx),
transform: CurveTransformCell::default(),
position: 0.0,
};
ctx.add(ruler)
}
}
#[cfg(test)]
mod test {
use crate::plugins::animation::thumb::ThumbBuilder;
use fyrox::{gui::test::test_widget_deletion, gui::widget::WidgetBuilder};
#[test]
fn test_deletion() {
test_widget_deletion(|ctx| ThumbBuilder::new(WidgetBuilder::new()).build(ctx));
}
}