use crate::fyrox::{
core::{
algebra::Vector2, color::Color, math::Rect, pool::Handle, reflect::prelude::*,
type_traits::prelude::*, uuid_provider, visitor::prelude::*,
},
gui::{
brush::Brush,
define_widget_deref,
draw::{CommandTexture, Draw, DrawingContext},
message::UiMessage,
widget::{Widget, WidgetBuilder, WidgetMessage},
BuildContext, Control, UiNode, UserInterface,
},
};
use crate::plugins::absm::segment::Segment;
use crate::utils::fetch_node_screen_center;
use fyrox::graph::SceneGraph;
use crate::plugins::absm::canvas::AbsmCanvas;
use crate::plugins::absm::socket::Socket;
use fyrox::material::MaterialResource;
const PICKED_BRUSH: Brush = Brush::Solid(Color::opaque(100, 100, 100));
const NORMAL_BRUSH: Brush = Brush::Solid(Color::opaque(80, 80, 80));
#[derive(Debug, Clone, Visit, Reflect, ComponentProvider)]
#[reflect(derived_type = "UiNode")]
pub struct Connection {
widget: Widget,
pub segment: Segment,
pub source_node: Handle<UiNode>,
pub dest_node: Handle<UiNode>,
}
define_widget_deref!(Connection);
pub fn draw_connection(
drawing_context: &mut DrawingContext,
source: Vector2<f32>,
dest: Vector2<f32>,
clip_bounds: Rect<f32>,
brush: Brush,
material: &MaterialResource,
) {
let k = 75.0;
drawing_context.push_bezier(
source,
source + Vector2::new(k, 0.0),
dest - Vector2::new(k, 0.0),
dest,
20,
4.0,
);
drawing_context.commit(clip_bounds, brush, CommandTexture::None, material, None);
}
uuid_provider!(Connection = "c802b6fa-a5ef-4464-a097-749c731ffde0");
impl Control for Connection {
fn draw(&self, drawing_context: &mut DrawingContext) {
draw_connection(
drawing_context,
self.segment.source_pos,
self.segment.dest_pos,
self.clip_bounds(),
self.foreground(),
&self.material,
);
}
fn handle_routed_message(&mut self, ui: &mut UserInterface, message: &mut UiMessage) {
self.widget.handle_routed_message(ui, message);
if self.segment.handle_routed_message(self.handle(), message) {
self.invalidate_visual();
}
if let Some(msg) = message.data::<WidgetMessage>() {
match msg {
WidgetMessage::MouseEnter => {
ui.send(
self.handle(),
WidgetMessage::Foreground(PICKED_BRUSH.clone().into()),
);
}
WidgetMessage::MouseLeave => {
ui.send(
self.handle(),
WidgetMessage::Foreground(NORMAL_BRUSH.clone().into()),
);
}
_ => (),
}
}
}
}
pub struct ConnectionBuilder {
widget_builder: WidgetBuilder,
source_socket: Handle<Socket>,
source_node: Handle<UiNode>,
dest_socket: Handle<Socket>,
dest_node: Handle<UiNode>,
}
impl ConnectionBuilder {
pub fn new(widget_builder: WidgetBuilder) -> Self {
Self {
widget_builder,
source_socket: Default::default(),
source_node: Default::default(),
dest_socket: Default::default(),
dest_node: Default::default(),
}
}
pub fn with_source_socket(mut self, source: Handle<Socket>) -> Self {
self.source_socket = source;
self
}
pub fn with_dest_socket(mut self, dest: Handle<Socket>) -> Self {
self.dest_socket = dest;
self
}
pub fn with_source_node(mut self, source: Handle<UiNode>) -> Self {
self.source_node = source;
self
}
pub fn with_dest_node(mut self, dest: Handle<UiNode>) -> Self {
self.dest_node = dest;
self
}
pub fn build(self, canvas: Handle<AbsmCanvas>, ctx: &mut BuildContext) -> Handle<Connection> {
let canvas_ref = ctx.inner().try_get(canvas).ok();
let connection = Connection {
widget: self
.widget_builder
.with_foreground(NORMAL_BRUSH.into())
.with_clip_to_bounds(false)
.build(ctx),
segment: Segment {
source: self.source_socket.to_base(),
source_pos: canvas_ref
.map(|c| c.screen_to_local(fetch_node_screen_center(self.source_socket, ctx)))
.unwrap_or_default(),
dest: self.dest_socket.to_base(),
dest_pos: canvas_ref
.map(|c| c.screen_to_local(fetch_node_screen_center(self.dest_socket, ctx)))
.unwrap_or_default(),
},
source_node: self.source_node,
dest_node: self.dest_node,
};
ctx.add(connection)
}
}
#[cfg(test)]
mod test {
use crate::plugins::absm::connection::ConnectionBuilder;
use fyrox::{gui::test::test_widget_deletion, gui::widget::WidgetBuilder};
#[test]
fn test_deletion() {
test_widget_deletion(|ctx| {
ConnectionBuilder::new(WidgetBuilder::new()).build(Default::default(), ctx)
});
}
}