use std::f32::consts::PI;
use std::fmt::Display;
use std::hash::Hash;
use crate::bevy::prelude::{Res, Vec2};
use crate::visualization::wrappers::{ActiveState, SimulationRenderEntity};
use crate::engine::{
fields::network::{Edge, Network},
location::Real2D,
state::State,
};
pub use bevy::prelude::Color;
use bevy::prelude::{Commands, Component, Query, Transform};
use bevy_prototype_lyon::draw::Stroke;
use bevy_prototype_lyon::entity::Shape;
use bevy_prototype_lyon::prelude::tess::path::path::Builder;
use bevy_prototype_lyon::prelude::{Geometry, ShapeBuilder, ShapeBuilderBase};
use bevy_prototype_lyon::shapes::Line;
pub extern crate bevy_prototype_lyon;
pub struct ArrowOptions {
pub length: f32,
pub angle: f32,
}
impl Default for ArrowOptions {
fn default() -> Self {
ArrowOptions {
length: 10.,
angle: PI / 12.,
}
}
}
pub enum LineType {
Line,
Arrow(ArrowOptions),
}
#[derive(Component)]
pub struct EdgeRenderInfo {
pub line_color: Color,
pub line_width: f32,
pub source_loc: Real2D,
pub target_loc: Real2D,
pub is_static: bool, }
#[derive(Component)]
pub struct EdgeRender(u32, u32, Real2D, Real2D);
pub trait NetworkRender<O: Hash + Eq + Clone + Display, L: Clone + Hash + Display, S: State> {
fn get_network(state: &S) -> &Network<O, L>;
fn get_edge_info(edge: &Edge<L>, network: &Network<O, L>) -> EdgeRenderInfo;
fn get_loc(network: &Network<O, L>, node: u32) -> Real2D;
fn init_network_graphics(state: &S, commands: &mut Commands) {
let network = Self::get_network(&*state);
for node_edges in network.edges.values() {
for edge in node_edges {
let EdgeRenderInfo {
source_loc,
target_loc,
line_color,
line_width,
is_static,
} = Self::get_edge_info(edge, network);
let shape = ShapeBuilder::with(&Line(
Vec2::new(source_loc.x, source_loc.y),
Vec2::new(target_loc.x, target_loc.y),
))
.stroke(Stroke::new(line_color, line_width))
.build();
let mut spawn_command = commands.spawn((shape, Transform::default()));
spawn_command.insert(SimulationRenderEntity);
if !is_static {
spawn_command.insert(EdgeRender(edge.u, edge.v, source_loc, target_loc));
}
}
}
}
fn render(state_wrapper: Res<ActiveState<S>>, mut query: Query<(&mut Shape, &mut EdgeRender)>) {
let state = state_wrapper.0.lock().expect("error on lock");
let network = Self::get_network(&*state);
for (mut shape, mut edge_render) in query.iter_mut() {
let source_loc = Self::get_loc(network, edge_render.0);
let target_loc = Self::get_loc(network, edge_render.1);
if source_loc != edge_render.2 || target_loc != edge_render.3 {
let mut builder = Builder::new();
Line(
Vec2::new(source_loc.x, source_loc.y),
Vec2::new(target_loc.x, target_loc.y),
)
.add_geometry(&mut builder);
shape.path = builder.build();
edge_render.2 = source_loc;
edge_render.3 = target_loc;
}
}
}
}