use std::{ rc::Rc, sync::Mutex };
use thiserror::Error;
use super::{
logger::Log,
node_path::{ PathSeg, NodePath },
node_scene::NodeScene,
node_tree_base::{ NodeTreeBase, TerminationReason },
tree_pointer::{ TPError, Tp, TpDyn },
tree_result::TreeResult,
rid::RID
};
use crate::traits::{ node::Node, node_tree::NodeTree, node_getter::NodeGetter, instanceable::Instanceable };
use crate::utils::functions::ensure_unique_name;
#[derive(Error, Debug, Clone, PartialEq, Eq, Hash)]
pub enum NodeError {
#[error("Index {index} was out of the range of this node's children count of {children_count}")]
IndexOutOfRange { index: usize, children_count: usize },
#[error("The path \"{0}\" is invalid")]
InvalidPath(Box<str>),
#[error("The root path \"{0}\" is invalid")]
InvalidRootPath(Box<str>),
#[error("This node has no parent")]
NoParent,
#[error("The following Tree Pointer error occured: {0:?}")]
TPError(TPError)
}
#[derive(Debug, Clone)]
pub enum NodeStatus {
Normal,
JustWarned(String),
JustPanicked(String)
}
pub struct NodeBase {
name: String,
rid: RID,
parent: Option<RID>,
owner: Option<RID>,
tree: Option<*mut dyn NodeTree>, children: Vec<RID>,
status: Rc<Mutex<NodeStatus>>,
loaded: bool,
depth: usize }
impl NodeBase {
pub fn new(name: String) -> Self {
NodeBase {
name,
rid: RID::default(),
parent: None,
owner: None,
tree: None,
children: Vec::new(),
status: Rc::new(Mutex::new(NodeStatus::Normal)),
loaded: false,
depth: 0
}
}
pub fn this<S: Node>(&self) -> Tp<S> {
if self.tree.is_none() {
panic!("Cannot get a tree pointer to a node that is not in a `NodeTree`!");
}
unsafe {
Tp::new(self.tree.unwrap_unchecked(), self.rid, self.rid).expect("Called `this` with the wrong type provided")
}
}
pub fn this_dyn(&self) -> TpDyn {
if self.tree.is_none() {
panic!("Cannot get a tree pointer to a node that is not in a `NodeTree`!");
}
unsafe {
TpDyn::new(self.tree.unwrap_unchecked(), self.rid, self.rid).unwrap_unchecked()
}
}
pub fn name(&self) -> &str {
&self.name
}
pub fn set_name(&mut self, name: &str) {
if let (Some(parent), Some(tree)) = (self.parent, self.tree()) {
let parent: &dyn Node = unsafe { tree.get_node(parent).unwrap_unchecked() };
let siblings: &[String] = &parent.children().iter().map(|a| a.name().to_string()).collect::<Vec<_>>();
unsafe {
self.set_name_unchecked(&ensure_unique_name(name, siblings));
}
} else {
unsafe {
self.set_name_unchecked(name);
}
}
}
pub fn register_as_singleton(&mut self, name: String) -> bool {
let rid: RID = self.rid;
match self.tree_mut() {
None => panic!("Cannot register a node that is not apart of the Nodetree as a singleton!"),
Some(tree) => tree.register_as_singleton(rid, name).unwrap()
}
}
pub fn add_child<I: Instanceable>(&mut self, child: I) {
child.iterate(|parent, node, is_owner| {
if let Some(parent) = parent {
unsafe {
let parent: &mut dyn Node = &mut *parent;
parent.add_child_from_ptr(node, is_owner, false);
}
} else {
unsafe {
self.add_child_from_ptr(node, is_owner, false);
}
}
});
}
pub unsafe fn add_child_from_ptr(&mut self, child_ptr: *mut dyn Node, owner_is_self: bool, ignore_ready: bool) -> RID {
if self.tree.is_none() {
panic!("Cannot add a child to a node that is not in a `NodeTree`!");
}
let names_of_children: &[String] = &self.children().iter().map(|c| c.name().to_string()).collect::<Vec<_>>();
let child_name: &str = unsafe { &*child_ptr }.name();
let unique_name: String = ensure_unique_name(child_name, names_of_children);
let child_rid: RID = unsafe {
let owner_rid: RID = self.owner.unwrap_unchecked();
let parent_rid: RID = self.rid;
let new_depth: usize = self.depth() + 1;
let tree_raw: *mut dyn NodeTree = self.tree.unwrap_unchecked();
let tree: &mut dyn NodeTree = self.tree_mut().unwrap_unchecked();
let rid: RID = tree.register_node(child_ptr);
let child: &mut dyn Node = tree.get_node_mut(rid).unwrap_unchecked();
child.set_name_unchecked(&unique_name);
child.set_parent(parent_rid);
child.set_owner(if owner_is_self { rid } else { owner_rid });
child.set_tree(tree_raw);
child.set_depth(new_depth);
child.set_rid(rid);
rid
};
self.children.push(child_rid);
if !ignore_ready {
unsafe {
let child: &mut dyn Node = self.tree_mut().unwrap_unchecked().get_node_mut(child_rid).unwrap_unchecked();
if child.has_just_loaded() {
child.loaded();
child.mark_as_final();
}
child.ready();
}
}
let child: &dyn Node = unsafe { self.tree().unwrap_unchecked().get_node(child_rid).unwrap_unchecked() };
self.post(Log::Debug(&format!("Node \"{}\" added to the scene as the child of \"{}\"! Unique ID of \"{}\" generated!", child.name(), self.name(), child.rid)));
child_rid
}
pub fn remove_child(&mut self, name: &str) -> bool {
if self.tree.is_none() {
panic!("Cannot add a child to a node that is not in a `NodeTree`!");
}
let child: Option<(usize, TpDyn)> = self.children()
.into_iter()
.enumerate()
.find(|(_, c)| c.name() == name);
if child.is_none() {
self.post(Log::Warn(&format!("Attempted to remove invalid node of name \"{}\" from node \"{}\"!", name, self.name())));
return false;
}
let (
child_idx,
child_name,
connected
): (usize, String, Vec<RID>) = unsafe {
child.map(|(idx, child)| (
idx,
child.name().to_string(),
child.top_down(true)
)).unwrap_unchecked()
};
self.children.remove(child_idx);
for (idx, queued_rid) in connected.into_iter().enumerate() { unsafe {
let _is_root_child: bool = idx == 0; let queued_node: &mut dyn Node = self.tree_mut().unwrap_unchecked().get_node_mut(queued_rid).unwrap_unchecked();
queued_node.terminal(TerminationReason::RemovedAsChild);
queued_node.disconnnect_parent();
queued_node.disconnnect_owner();
queued_node.disconnnect_tree();
self.tree_mut().unwrap_unchecked().unregister_node(queued_rid);
}}
self.post(Log::Debug(&format!("Removed child node \"{}\" from parent node \"{}\"!", child_name, self.name())));
true
}
pub fn get_child<T: Node>(&self, i: usize) -> TreeResult<Tp<T>, NodeError> {
if self.tree().is_none() {
panic!("Cannot get a node from a node that is not a part of a NodeTree!");
}
if i >= self.num_children() {
unsafe {
TreeResult::new(self.tree.unwrap_unchecked(), self.rid, Err(NodeError::IndexOutOfRange { index: i, children_count: self.num_children() }))
}
} else {
unsafe {
Tp::new(self.tree.unwrap_unchecked(), self.rid, self.children[i])
.map_err(|err| NodeError::TPError(err))
}
}
}
pub fn get_child_dyn(&self, i: usize) -> TreeResult<TpDyn, NodeError> {
if self.tree().is_none() {
panic!("Cannot get a node from a node that is not a part of a NodeTree!");
}
if i >= self.num_children() {
unsafe {
TreeResult::new(self.tree.unwrap_unchecked(), self.rid, Err(NodeError::IndexOutOfRange { index: i, children_count: self.num_children() }))
}
} else {
unsafe {
TpDyn::new(self.tree.unwrap_unchecked(), self.rid, self.children[i])
.map_err(|err| NodeError::TPError(err))
}
}
}
pub fn children(&self) -> Vec<TpDyn> {
if self.tree().is_none() {
panic!("Cannot get children from a node that is not a part of a NodeTree!");
}
self.children.iter().map(|&c| unsafe { TpDyn::new(self.tree.unwrap_unchecked(), self.rid, c).unwrap_unchecked() }).collect()
}
pub fn get_node<T: Node>(&self, path: impl NodeGetter) -> TreeResult<Tp<T>, NodeError> {
if self.tree().is_none() {
panic!("Cannot get a node from a node that is not a part of a NodeTree!");
}
let path_str: String = format!("{path:?}");
match unsafe { self.tree().unwrap_unchecked() }.get_node_rid(path, Some(self.rid)) {
Some(node_rid) => {
unsafe {
Tp::new(self.tree.unwrap_unchecked(), self.rid, node_rid)
.map_err(|err| NodeError::TPError(err))
}
},
None => unsafe {
TreeResult::new(self.tree.unwrap_unchecked(), self.rid, Err(NodeError::InvalidPath(path_str.into())))
}
}
}
pub fn get_node_dyn(&self, path: impl NodeGetter) -> TreeResult<TpDyn, NodeError> {
if self.tree().is_none() {
panic!("Cannot get a node from a node that is not a part of a NodeTree!");
}
let path_str: String = format!("{path:?}");
match unsafe { self.tree().unwrap_unchecked() }.get_node_rid(path, Some(self.rid)) {
Some(node_rid) => {
unsafe {
TpDyn::new(self.tree.unwrap_unchecked(), self.rid, node_rid)
.map_err(|err| NodeError::TPError(err))
}
},
None => unsafe {
TreeResult::new(self.tree.unwrap_unchecked(), self.rid, Err(NodeError::InvalidRootPath(path_str.into())))
}
}
}
pub fn get_node_raw(&self, mut path: NodePath) -> Option<RID> {
if self.tree().is_none() {
panic!("Cannot get a node from a node that is not a part of a NodeTree!");
}
let next_node: Option<PathSeg> = path.pop_front();
match next_node {
Some(target) => {
match target {
PathSeg::Node(target_node) => {
for child in self.children() {
if *child.name() == *target_node {
return child.get_node_raw(path);
}
}
None
},
PathSeg::This => {
self.get_node_raw(path)
},
PathSeg::Parent => {
if let Some(parent) = self.parent_dyn().to_option() {
parent.get_node_raw(path)
} else {
None
}
}
}
},
None => Some(self.rid())
}
}
pub fn top_down(&self, contains_self: bool) -> Vec<RID> {
let mut iter: Vec<RID> = if contains_self { vec![self.rid()] } else { Vec::new() };
self.top_down_tail(&mut iter, vec![self.rid()]);
iter
}
fn top_down_tail(&self, iter: &mut Vec<RID>, layer: Vec<RID>) {
if self.tree().is_none() {
panic!("Cannot get nodes from a node that is not a part of a NodeTree!");
}
let new_layer: Vec<RID> = unsafe { self.tree().unwrap_unchecked() }.get_all_valid_nodes(&layer)
.into_iter()
.flat_map(|node| node.children.to_owned() )
.collect();
if new_layer.is_empty() {
return;
}
iter.append(&mut new_layer.clone());
self.top_down_tail(iter, new_layer)
}
pub fn get_absolute_path(&self) -> NodePath {
let mut path: String = String::new();
self.get_absolute_path_tail(&mut path);
NodePath::from_str(&path)
}
fn get_absolute_path_tail(&self, path: &mut String) {
if self.tree().is_none() {
panic!("Cannot get nodes from a node that is not a part of a NodeTree!");
}
*path = self.name().to_string() + &(if path.is_empty() { String::new() } else { "/".to_string() + path });
if !self.is_root() {
unsafe {
self.tree().unwrap_unchecked().get_node(self.parent.unwrap_unchecked()).unwrap_unchecked().get_absolute_path_tail(path);
}
}
}
pub fn post(&self, log: Log) {
unsafe {
match &log {
Log::Warn(str) => self.set_status(NodeStatus::JustWarned(str.to_string())),
Log::Panic(str) => self.set_status(NodeStatus::JustPanicked(str.to_string())),
_ => ()
}
}
let rid: RID = self.rid();
match self.tree_mut() {
Some(root) => {
root.post(rid, log);
},
None => panic!("Cannot post to log on a disconnected node!")
}
}
pub fn free(&mut self) {
if self.tree().is_none() {
panic!("Cannot free a node that is not a part of a NodeTree! Instead, simply let the unbound Node drop out of scope or use drop()!");
}
for node in self.top_down(true) {
let is_self: bool = node == self.rid;
let tree: &mut NodeTreeBase = unsafe { self.tree_mut().unwrap_unchecked() };
unsafe {
tree.get_node_mut(self.rid).unwrap_unchecked().terminal(TerminationReason::Freed); }
if is_self {
if let Some(parent) = self.parent {
unsafe {
let rid: RID = self.rid;
let parent: &mut dyn Node = self.tree_mut().unwrap_unchecked().get_node_mut(parent).unwrap_unchecked();
let child_idx: usize = parent.children.iter().position(|&c_rid| c_rid == rid).unwrap_unchecked();
parent.children.remove(child_idx);
}
}
}
unsafe {
tree.unregister_node(node);
}
}
if self.is_root() {
self.tree_mut().unwrap().terminate();
}
}
pub fn save_as_branch(&self) -> NodeScene {
if self.tree().is_none() {
panic!("Cannot free a node that is not a part of a NodeTree! Instead, simply let the unbound Node drop out of scope or use drop()!");
}
self.save_as_branch_tail()
}
fn save_as_branch_tail(&self) -> NodeScene {
let root: Box<dyn Node> = unsafe { (&*self.tree.unwrap_unchecked()).get_node(self.rid).unwrap_unchecked() }.clone_as_instance();
let mut scene: NodeScene = NodeScene::new_dyn(root);
for &child in &self.children {
let child: &dyn Node = unsafe { (&*self.tree.unwrap_unchecked()).get_node(child).unwrap_unchecked() };
if child.is_owner() {
scene.append_as_owner(child.save_as_branch_tail());
} else {
scene.append(child.save_as_branch_tail());
}
}
scene
}
pub unsafe fn set_name_unchecked(&mut self, name: &str) {
self.name = name.to_string();
}
pub fn rid(&self) -> RID {
self.rid
}
pub unsafe fn set_rid(&mut self, rid: RID) {
self.rid = rid;
}
pub fn tree(&self) -> Option<&dyn NodeTree> {
unsafe {
self.tree.map(|x| &*x)
}
}
pub fn tree_mut(&self) -> Option<&mut dyn NodeTree> {
unsafe {
self.tree.map(|x| &mut *x)
}
}
pub unsafe fn set_tree(&mut self, tree: *mut dyn NodeTree) {
self.tree = Some(tree);
}
pub unsafe fn disconnnect_tree(&mut self) {
self.tree = None;
}
pub fn owner<T: Node>(&self) -> TreeResult<Tp<T>, NodeError> {
if self.tree().is_none() {
panic!("Cannot get a node from a node that is not a part of a NodeTree!");
}
unsafe {
Tp::new(self.tree.unwrap_unchecked(), self.rid, self.owner.unwrap_unchecked())
.map_err(|err| NodeError::TPError(err))
}
}
pub fn owner_dyn(&self) -> TpDyn {
if self.tree().is_none() {
panic!("Cannot get a node from a node that is not a part of a NodeTree!");
}
unsafe {
TpDyn::new(self.tree.unwrap_unchecked(), self.rid, self.owner.unwrap_unchecked()).unwrap_unchecked()
}
}
pub unsafe fn set_owner(&mut self, owner: RID) {
self.owner = Some(owner);
}
pub unsafe fn disconnnect_owner(&mut self) {
self.owner = None;
}
pub fn parent<T: Node>(&self) -> TreeResult<Tp<T>, NodeError> {
if self.tree().is_none() {
panic!("Cannot get a node from a node that is not a part of a NodeTree!");
}
match self.parent {
Some(parent) => {
unsafe {
Tp::new(self.tree.unwrap_unchecked(), self.rid, parent)
.map_err(|err| NodeError::TPError(err))
}
},
None => unsafe {
TreeResult::new(self.tree.unwrap_unchecked(), self.rid, Err(NodeError::NoParent))
}
}
}
pub fn parent_dyn(&self) -> TreeResult<TpDyn, NodeError> {
if self.tree().is_none() {
panic!("Cannot get a node from a node that is not a part of a NodeTree!");
}
match self.parent {
Some(parent) => {
unsafe {
TpDyn::new(self.tree.unwrap_unchecked(), self.rid, parent)
.map_err(|err| NodeError::TPError(err))
}
},
None => unsafe {
TreeResult::new(self.tree.unwrap_unchecked(), self.rid, Err(NodeError::NoParent))
}
}
}
pub unsafe fn set_parent(&mut self, parent: RID) {
self.parent = Some(parent);
}
pub unsafe fn disconnnect_parent(&mut self) {
self.parent = None;
}
pub fn status(&self) -> NodeStatus {
self.status.lock().unwrap().to_owned()
}
pub unsafe fn set_status(&self, status: NodeStatus) {
*self.status.lock().unwrap() = status;
}
pub fn depth(&self) -> usize {
self.depth
}
pub unsafe fn set_depth(&mut self, depth: usize) {
self.depth = depth;
}
pub fn in_tree(&self) -> bool {
self.tree().is_some()
}
pub fn is_stray(&self) -> bool {
self.tree().is_none()
}
pub fn is_root(&self) -> bool {
self.parent.is_none() && self.in_tree()
}
pub fn is_owner(&self) -> bool {
match self.owner {
Some(owner) => self.rid == owner,
None => false
}
}
pub fn num_children(&self) -> usize {
self.children().len()
}
pub fn childless(&self) -> bool {
self.num_children() == 0
}
pub unsafe fn mark_as_loaded(&mut self) {
self.loaded = true;
}
pub unsafe fn mark_as_final(&mut self) {
self.loaded = false;
}
pub fn has_just_loaded(&self) -> bool {
self.loaded
}
}
impl std::fmt::Debug for NodeBase {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(&format!("Inner[{}] {{ ", self.name))?;
if let Some(parent) = &self.parent {
f.write_str(&format!("Parent: {}, ", parent))?;
}
if let Some(owner) = &self.owner {
f.write_str(&format!("Owner: {}, ", owner))?;
}
f.write_str(&format!("Connected to Tree: {}, ", self.tree.is_some()))?;
f.write_str(&format!("Children: {:?}, ", &self.children))?;
f.write_str(&format!("Depth: {} ", self.depth))?;
f.write_str("}")?;
Ok(())
}
}
impl Clone for NodeBase {
fn clone(&self) -> Self {
Self::new(self.name.clone())
}
}