use crate::command::{Command, SetPropertyCommand};
use crate::fyrox::{
core::{math::TriangleEdge, pool::Handle},
scene::node::Node,
};
use crate::message::MessageSender;
use crate::scene::commands::GameSceneContext;
use crate::scene::controller::SceneController;
use crate::scene::{EntityInfo, GameScene, SelectionContainer};
use fyrox::core::reflect::Reflect;
use fyrox::core::some_or_return;
use fyrox::engine::Engine;
use fyrox::graph::SceneGraph;
use fyrox::gui::inspector::PropertyChanged;
use fyrox::scene::SceneContainer;
use std::{
cell::{Cell, Ref, RefCell},
collections::BTreeSet,
};
#[derive(PartialEq, Clone, Debug, Eq)]
pub enum NavmeshEntity {
Vertex(usize),
Edge(TriangleEdge),
}
#[derive(PartialEq, Clone, Debug, Eq)]
pub struct NavmeshSelection {
dirty: Cell<bool>,
navmesh_node: Handle<Node>,
entities: Vec<NavmeshEntity>,
unique_vertices: RefCell<BTreeSet<usize>>,
}
impl SelectionContainer for NavmeshSelection {
fn len(&self) -> usize {
self.entities.len()
}
fn first_selected_entity(
&self,
controller: &dyn SceneController,
scenes: &SceneContainer,
callback: &mut dyn FnMut(EntityInfo),
) {
let game_scene = some_or_return!(controller.downcast_ref::<GameScene>());
let scene = &scenes[game_scene.scene];
let node = scene.graph.try_get_node(self.navmesh_node).unwrap();
(callback)(EntityInfo {
entity: node as &dyn Reflect,
has_inheritance_parent: node.has_inheritance_parent(),
read_only: false,
});
}
fn on_property_changed(
&mut self,
controller: &mut dyn SceneController,
args: &PropertyChanged,
engine: &mut Engine,
sender: &MessageSender,
) {
let game_scene = some_or_return!(controller.downcast_mut::<GameScene>());
let scene = &mut engine.scenes[game_scene.scene];
if let Some(command) = game_scene.node_property_changed_handler.handle(
args,
self.navmesh_node,
&mut scene.graph[self.navmesh_node],
) {
sender.send_command(command);
}
}
fn paste_property(&mut self, path: &str, value: &dyn Reflect, sender: &MessageSender) {
let navmesh_node = self.navmesh_node;
if let Some(command) = value.try_clone_box().map(|value| {
Command::new(SetPropertyCommand::new(
path.to_string(),
value,
move |ctx| {
ctx.get_mut::<GameSceneContext>()
.scene
.graph
.try_get_node_mut(navmesh_node)
.ok()
.map(|n| n as &mut dyn Reflect)
},
))
}) {
sender.send_command(command)
}
}
fn provide_docs(&self, controller: &dyn SceneController, engine: &Engine) -> Option<String> {
let game_scene = controller.downcast_ref::<GameScene>()?;
let scene = &engine.scenes[game_scene.scene];
Some(scene.graph[self.navmesh_node()].doc().to_string())
}
}
impl NavmeshSelection {
pub fn empty(navmesh: Handle<Node>) -> Self {
Self {
dirty: Cell::new(false),
navmesh_node: navmesh,
entities: vec![],
unique_vertices: Default::default(),
}
}
pub fn new(navmesh: Handle<Node>, entities: Vec<NavmeshEntity>) -> Self {
Self {
dirty: Cell::new(true),
navmesh_node: navmesh,
entities,
unique_vertices: Default::default(),
}
}
pub fn navmesh_node(&self) -> Handle<Node> {
self.navmesh_node
}
pub fn add(&mut self, entity: NavmeshEntity) {
self.entities.push(entity);
self.dirty.set(true);
}
pub fn clear(&mut self) {
self.entities.clear();
self.unique_vertices.borrow_mut().clear();
self.dirty.set(false);
}
pub fn first(&self) -> Option<&NavmeshEntity> {
self.entities.first()
}
pub fn unique_vertices(&self) -> Ref<'_, BTreeSet<usize>> {
if self.dirty.get() {
let mut unique_vertices = self.unique_vertices.borrow_mut();
unique_vertices.clear();
for entity in self.entities.iter() {
match entity {
NavmeshEntity::Vertex(v) => {
unique_vertices.insert(*v);
}
NavmeshEntity::Edge(edge) => {
unique_vertices.insert(edge.a as usize);
unique_vertices.insert(edge.b as usize);
}
}
}
}
self.unique_vertices.borrow()
}
pub fn entities(&self) -> &[NavmeshEntity] {
&self.entities
}
pub fn contains_edge(&self, edge: TriangleEdge) -> bool {
self.entities.contains(&NavmeshEntity::Edge(edge))
}
}