mirror of
https://github.com/FyroxEngine/Fyrox.git
synced 2026-10-12 02:02:20 +00:00
fixed infinite recursion in trait bounds for Visit and Reflect procmacro
- this bug was rare, but very annoying
This commit is contained in:
@@ -41,9 +41,9 @@ use strum_macros::{AsRefStr, EnumString, VariantNames};
|
||||
pub mod signal;
|
||||
|
||||
/// Trait for anything that can be used as a texture.
|
||||
pub trait SpriteSheetTexture: PartialEq + Clone + Visit + Reflect {}
|
||||
pub trait SpriteSheetTexture: PartialEq + Clone + Visit + Reflect + Default {}
|
||||
|
||||
impl<T: PartialEq + Clone + Visit + Reflect> SpriteSheetTexture for T {}
|
||||
impl<T: PartialEq + Clone + Visit + Reflect + Default> SpriteSheetTexture for T {}
|
||||
|
||||
/// Animation playback status.
|
||||
#[derive(
|
||||
@@ -292,7 +292,7 @@ where
|
||||
/// # };
|
||||
/// # use fyrox_core::{reflect::prelude::*, visitor::prelude::*};
|
||||
/// #
|
||||
/// #[derive(PartialEq, Clone, Reflect, Visit, Debug)]
|
||||
/// #[derive(PartialEq, Clone, Reflect, Visit, Debug, Default)]
|
||||
/// struct MyTexture {}
|
||||
///
|
||||
/// fn extract_animations() {
|
||||
@@ -595,7 +595,7 @@ mod test {
|
||||
};
|
||||
use fyrox_core::{algebra::Vector2, math::Rect, reflect::prelude::*, visitor::prelude::*};
|
||||
|
||||
#[derive(PartialEq, Clone, Reflect, Visit, Debug)]
|
||||
#[derive(PartialEq, Clone, Reflect, Visit, Debug, Default)]
|
||||
struct MyTexture {}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -41,7 +41,7 @@ use syn::{parse_macro_input, DeriveInput};
|
||||
/// ```
|
||||
/// use fyrox_core::visitor::{Visit, VisitResult, Visitor};
|
||||
/// #[derive(Visit)]
|
||||
/// struct Foo<T> {
|
||||
/// struct Foo<T: Visit> {
|
||||
/// example_one: String,
|
||||
/// example_two: T,
|
||||
/// }
|
||||
|
||||
@@ -92,19 +92,6 @@ impl TypeArgs {
|
||||
return generics;
|
||||
}
|
||||
|
||||
// Add where clause for every reflectable field
|
||||
let fields: Box<dyn Iterator<Item = &FieldArgs>> = match &self.data {
|
||||
ast::Data::Struct(data) => Box::new(data.fields.iter()),
|
||||
ast::Data::Enum(variants) => Box::new(variants.iter().flat_map(|v| v.fields.iter())),
|
||||
};
|
||||
|
||||
clause.predicates.extend(
|
||||
fields
|
||||
.filter(|f| !(f.hidden || f.deref || f.field.is_some()))
|
||||
.map(|f| &f.ty)
|
||||
.map::<WherePredicate, _>(|ty| parse_quote! { #ty: Reflect }),
|
||||
);
|
||||
|
||||
generics
|
||||
}
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ fn impl_visit_struct(
|
||||
}
|
||||
};
|
||||
|
||||
utils::create_impl(ty_args, field_args.iter().cloned(), visit_fn_body)
|
||||
utils::create_impl(ty_args, visit_fn_body)
|
||||
}
|
||||
|
||||
/// impl `Visit` for `enum`
|
||||
@@ -235,7 +235,6 @@ fn impl_visit_enum(ty_args: &args::TypeArgs, variant_args: &[args::VariantArgs])
|
||||
|
||||
utils::create_impl(
|
||||
ty_args,
|
||||
variant_args.iter().flat_map(|v| v.fields.iter()).cloned(),
|
||||
quote! {
|
||||
let mut region = match visitor.enter_region(name) {
|
||||
Ok(x) => x,
|
||||
|
||||
@@ -40,10 +40,7 @@ pub struct TypeArgs {
|
||||
#[darling(attributes(visit))]
|
||||
pub struct FieldArgs {
|
||||
pub ident: Option<Ident>,
|
||||
// pub vis: Visibility,
|
||||
pub ty: Type,
|
||||
// pub attrs: Vec<Attribute>,
|
||||
// ---
|
||||
|
||||
/// `#[visit(skip)]`
|
||||
///
|
||||
/// Skip on read and write
|
||||
|
||||
@@ -28,14 +28,9 @@ use convert_case::*;
|
||||
|
||||
use crate::visit::args;
|
||||
|
||||
pub fn create_impl(
|
||||
ty_args: &args::TypeArgs,
|
||||
field_args: impl Iterator<Item = args::FieldArgs>,
|
||||
impl_body: TokenStream2,
|
||||
) -> TokenStream2 {
|
||||
pub fn create_impl(ty_args: &args::TypeArgs, impl_body: TokenStream2) -> TokenStream2 {
|
||||
let ty_ident = &ty_args.ident;
|
||||
let generics = self::create_impl_generics(&ty_args.generics, field_args);
|
||||
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
|
||||
let (impl_generics, ty_generics, where_clause) = ty_args.generics.split_for_impl();
|
||||
|
||||
quote! {
|
||||
#[allow(clippy::question_mark)]
|
||||
@@ -51,23 +46,6 @@ pub fn create_impl(
|
||||
}
|
||||
}
|
||||
|
||||
fn create_impl_generics(
|
||||
generics: &Generics,
|
||||
field_args: impl Iterator<Item = args::FieldArgs>,
|
||||
) -> Generics {
|
||||
let mut generics = generics.clone();
|
||||
|
||||
// Add where clause for every visited field
|
||||
generics.make_where_clause().predicates.extend(
|
||||
field_args
|
||||
.filter(|f| !f.skip)
|
||||
.map(|f| f.ty)
|
||||
.map::<WherePredicate, _>(|ty| parse_quote! { #ty: Visit }),
|
||||
);
|
||||
|
||||
generics
|
||||
}
|
||||
|
||||
/// `<prefix>field.visit("name", visitor)?;`
|
||||
pub fn create_field_visits<'a>(
|
||||
// false if enum variant
|
||||
|
||||
@@ -45,7 +45,7 @@ struct SkipAttr {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Visit)]
|
||||
struct Generics<T> {
|
||||
struct Generics<T: Visit + Default + 'static> {
|
||||
items: Vec<T>,
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ enum ComplexEnum {
|
||||
#[derive(Debug, Clone, PartialEq, Visit)]
|
||||
enum GenericEnum<T>
|
||||
where
|
||||
T: std::fmt::Debug,
|
||||
T: std::fmt::Debug + Default + Visit + 'static,
|
||||
{
|
||||
UnitVariant,
|
||||
Tuple(i32, Vec<T>),
|
||||
@@ -141,17 +141,6 @@ fn skip_attr() {
|
||||
|
||||
#[test]
|
||||
fn generics() {
|
||||
struct NotVisit;
|
||||
|
||||
#[allow(warnings)]
|
||||
let mut not_compile = Generics {
|
||||
items: vec![NotVisit],
|
||||
};
|
||||
|
||||
// Compile error because `Generics<NotVisit> is not `Visit`:
|
||||
// let mut visitor = Visitor::new();
|
||||
// not_compile.visit("Data", &mut visitor).unwrap();
|
||||
|
||||
// But `Generics<T: Visit` is `Visit`
|
||||
let mut data = Generics {
|
||||
items: vec![100u32],
|
||||
@@ -198,16 +187,6 @@ fn complex_enum() {
|
||||
|
||||
#[test]
|
||||
fn generic_enum() {
|
||||
#[derive(Debug)]
|
||||
struct NotVisit;
|
||||
|
||||
#[allow(warnings)]
|
||||
let mut not_compile = GenericEnum::Tuple(1, vec![NotVisit]);
|
||||
|
||||
// Compile error because `Generics<NotVisit> is not `Visit`:
|
||||
// let mut visitor = Visitor::new();
|
||||
// not_compile.visit("Data", &mut visitor).unwrap();
|
||||
|
||||
let mut data = GenericEnum::Tuple(1, vec![100u32]);
|
||||
let mut data_default = GenericEnum::UnitVariant;
|
||||
|
||||
|
||||
@@ -26,7 +26,6 @@ pub use fyrox_math::*;
|
||||
use crate::math::curve::Curve;
|
||||
use crate::math::curve::CurveKey;
|
||||
use crate::math::curve::CurveKeyKind;
|
||||
use crate::Uuid;
|
||||
use crate::{
|
||||
algebra::Scalar,
|
||||
math::{aabb::AxisAlignedBoundingBox, frustum::Frustum, plane::Plane},
|
||||
|
||||
@@ -27,14 +27,14 @@ use std::fmt::Debug;
|
||||
use crate::reflect::prelude::*;
|
||||
|
||||
impl_reflect! {
|
||||
pub struct Matrix<T: Copy + 'static, R: Dim + 'static, C: Dim + 'static, S: Copy + 'static> {
|
||||
pub struct Matrix<T: Copy + 'static, R: Dim + 'static, C: Dim + 'static, S: Copy + Debug + FieldValue + 'static> {
|
||||
pub data: S,
|
||||
// _phantoms: PhantomData<(T, R, C)>,
|
||||
}
|
||||
}
|
||||
|
||||
impl_reflect! {
|
||||
pub struct ArrayStorage<T: Copy + Debug, const R: usize, const C: usize>(pub [[T; R]; C]);
|
||||
pub struct ArrayStorage<T: Copy + Debug + Reflect, const R: usize, const C: usize>(pub [[T; R]; C]);
|
||||
}
|
||||
|
||||
impl_reflect! {
|
||||
@@ -44,7 +44,7 @@ impl_reflect! {
|
||||
}
|
||||
|
||||
impl_reflect! {
|
||||
pub struct Quaternion<T: Copy + Debug> {
|
||||
pub struct Quaternion<T: Copy + Debug + Reflect> {
|
||||
pub coords: Vector4<T>,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -282,14 +282,14 @@ impl_reflect! {
|
||||
}
|
||||
|
||||
impl_reflect! {
|
||||
pub enum Option<T: Clone> {
|
||||
pub enum Option<T: Clone + Debug + Reflect> {
|
||||
Some(T),
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl_reflect! {
|
||||
pub struct Range<Idx: Clone> {
|
||||
pub struct Range<Idx: Clone + Debug + Reflect> {
|
||||
pub start: Idx,
|
||||
pub end: Idx,
|
||||
}
|
||||
|
||||
@@ -45,14 +45,11 @@ use crate::{
|
||||
},
|
||||
};
|
||||
use fyrox_graph::constructor::ConstructorProvider;
|
||||
use std::{
|
||||
any::{type_name, Any, TypeId},
|
||||
ops::{Deref, DerefMut},
|
||||
};
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
/// A part of ragdoll, that has a physical rigid body, a bone and zero or more children limbs.
|
||||
/// Multiple limbs together forms a ragdoll.
|
||||
#[derive(Clone, Debug, PartialEq, Default)]
|
||||
#[derive(Clone, Debug, PartialEq, Default, Visit, Reflect)]
|
||||
pub struct Limb {
|
||||
/// A handle of a scene node, that is used as a bone in some other scene node (mesh).
|
||||
pub bone: Handle<Node>,
|
||||
@@ -64,196 +61,6 @@ pub struct Limb {
|
||||
|
||||
uuid_provider!(Limb = "6d5bc2f7-8acc-4b64-8e4b-65d4551150bf");
|
||||
|
||||
// Rust has a compiler bug `overflow evaluating the requirement` that prevents deriving this impl.
|
||||
impl Reflect for Limb {
|
||||
fn source_path() -> &'static str {
|
||||
file!()
|
||||
}
|
||||
|
||||
fn derived_types() -> &'static [TypeId] {
|
||||
&[]
|
||||
}
|
||||
|
||||
fn query_derived_types(&self) -> &'static [TypeId] {
|
||||
Self::derived_types()
|
||||
}
|
||||
|
||||
fn type_name(&self) -> &'static str {
|
||||
type_name::<Self>()
|
||||
}
|
||||
|
||||
fn doc(&self) -> &'static str {
|
||||
""
|
||||
}
|
||||
|
||||
fn assembly_name(&self) -> &'static str {
|
||||
env!("CARGO_PKG_NAME")
|
||||
}
|
||||
|
||||
fn type_assembly_name() -> &'static str {
|
||||
env!("CARGO_PKG_NAME")
|
||||
}
|
||||
|
||||
fn fields_ref(&self, func: &mut dyn FnMut(&[FieldRef])) {
|
||||
func(&[
|
||||
{
|
||||
static METADATA: FieldMetadata = FieldMetadata {
|
||||
name: "Bone",
|
||||
display_name: "Bone",
|
||||
tag: "",
|
||||
read_only: false,
|
||||
immutable_collection: false,
|
||||
min_value: None,
|
||||
max_value: None,
|
||||
step: None,
|
||||
precision: None,
|
||||
doc: "",
|
||||
};
|
||||
FieldRef {
|
||||
metadata: &METADATA,
|
||||
value: &self.bone,
|
||||
}
|
||||
},
|
||||
{
|
||||
static METADATA: FieldMetadata = FieldMetadata {
|
||||
name: "PhysicalBone",
|
||||
display_name: "Physical Bone",
|
||||
tag: "",
|
||||
read_only: false,
|
||||
immutable_collection: false,
|
||||
min_value: None,
|
||||
max_value: None,
|
||||
step: None,
|
||||
precision: None,
|
||||
doc: "",
|
||||
};
|
||||
FieldRef {
|
||||
metadata: &METADATA,
|
||||
value: &self.physical_bone,
|
||||
}
|
||||
},
|
||||
{
|
||||
static METADATA: FieldMetadata = FieldMetadata {
|
||||
name: "Children",
|
||||
display_name: "Children",
|
||||
tag: "",
|
||||
read_only: false,
|
||||
immutable_collection: false,
|
||||
min_value: None,
|
||||
max_value: None,
|
||||
step: None,
|
||||
precision: None,
|
||||
doc: "",
|
||||
};
|
||||
FieldRef {
|
||||
metadata: &METADATA,
|
||||
value: &self.children,
|
||||
}
|
||||
},
|
||||
])
|
||||
}
|
||||
|
||||
fn fields_mut(&mut self, func: &mut dyn FnMut(&mut [FieldMut])) {
|
||||
func(&mut [
|
||||
{
|
||||
static METADATA: FieldMetadata = FieldMetadata {
|
||||
name: "Bone",
|
||||
display_name: "Bone",
|
||||
tag: "",
|
||||
read_only: false,
|
||||
immutable_collection: false,
|
||||
min_value: None,
|
||||
max_value: None,
|
||||
step: None,
|
||||
precision: None,
|
||||
doc: "",
|
||||
};
|
||||
FieldMut {
|
||||
metadata: &METADATA,
|
||||
value: &mut self.bone,
|
||||
}
|
||||
},
|
||||
{
|
||||
static METADATA: FieldMetadata = FieldMetadata {
|
||||
name: "PhysicalBone",
|
||||
display_name: "Physical Bone",
|
||||
tag: "",
|
||||
read_only: false,
|
||||
immutable_collection: false,
|
||||
min_value: None,
|
||||
max_value: None,
|
||||
step: None,
|
||||
precision: None,
|
||||
doc: "",
|
||||
};
|
||||
FieldMut {
|
||||
metadata: &METADATA,
|
||||
value: &mut self.physical_bone,
|
||||
}
|
||||
},
|
||||
{
|
||||
static METADATA: FieldMetadata = FieldMetadata {
|
||||
name: "Children",
|
||||
display_name: "Children",
|
||||
tag: "",
|
||||
read_only: false,
|
||||
immutable_collection: false,
|
||||
min_value: None,
|
||||
max_value: None,
|
||||
step: None,
|
||||
precision: None,
|
||||
doc: "",
|
||||
};
|
||||
FieldMut {
|
||||
metadata: &METADATA,
|
||||
value: &mut self.children,
|
||||
}
|
||||
},
|
||||
])
|
||||
}
|
||||
|
||||
fn into_any(self: Box<Self>) -> Box<dyn Any> {
|
||||
self
|
||||
}
|
||||
|
||||
fn as_any(&self, func: &mut dyn FnMut(&dyn Any)) {
|
||||
func(self)
|
||||
}
|
||||
|
||||
fn as_any_mut(&mut self, func: &mut dyn FnMut(&mut dyn Any)) {
|
||||
func(self)
|
||||
}
|
||||
|
||||
fn as_reflect(&self, func: &mut dyn FnMut(&dyn Reflect)) {
|
||||
func(self)
|
||||
}
|
||||
|
||||
fn as_reflect_mut(&mut self, func: &mut dyn FnMut(&mut dyn Reflect)) {
|
||||
func(self)
|
||||
}
|
||||
|
||||
fn set(&mut self, value: Box<dyn Reflect>) -> Result<Box<dyn Reflect>, Box<dyn Reflect>> {
|
||||
let this = std::mem::replace(self, value.take()?);
|
||||
Ok(Box::new(this))
|
||||
}
|
||||
|
||||
fn try_clone_box(&self) -> Option<Box<dyn Reflect>> {
|
||||
Some(Box::new(self.clone()))
|
||||
}
|
||||
}
|
||||
|
||||
impl Visit for Limb {
|
||||
fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
|
||||
let mut guard = visitor.enter_region(name)?;
|
||||
|
||||
self.bone.visit("Bone", &mut guard)?;
|
||||
self.physical_bone.visit("PhysicalBone", &mut guard)?;
|
||||
self.children.visit("Children", &mut guard)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Limb {
|
||||
/// Iterates recursively across the entire tree of descendant limbs and does the specified action
|
||||
/// with every limb along the way.
|
||||
|
||||
@@ -402,7 +402,7 @@ pub enum PageType {
|
||||
/// Both pages and tiles have a TileDefinitionHandle and are rendered using
|
||||
/// [`TileRenderData`]. For pages this is due to having an icon to allow the user to select the page.
|
||||
/// Both pages and tiles can be selected by the user, moved, and deleted.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Reflect)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Visit, Reflect)]
|
||||
pub enum ResourceTilePosition {
|
||||
/// This position refers to some page, and so it lacks tile coordinates.
|
||||
Page(Vector2<i32>),
|
||||
@@ -411,6 +411,12 @@ pub enum ResourceTilePosition {
|
||||
Tile(Vector2<i32>, Vector2<i32>),
|
||||
}
|
||||
|
||||
impl Default for ResourceTilePosition {
|
||||
fn default() -> Self {
|
||||
Self::Page(Default::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for ResourceTilePosition {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
|
||||
@@ -58,22 +58,22 @@ fn position_to_vector(source: PalettePosition) -> Vector2<i32> {
|
||||
|
||||
/// A 2D grid that contains tile data.
|
||||
#[derive(Default, Debug, Clone, PartialEq, Reflect)]
|
||||
pub struct TileGridMap<V: Debug + Clone>(FxHashMap<Vector2<i32>, V>);
|
||||
pub struct TileGridMap<V: Debug + Clone + Reflect>(FxHashMap<Vector2<i32>, V>);
|
||||
|
||||
impl<V: Visit + Default + Debug + Clone> Visit for TileGridMap<V> {
|
||||
impl<V: Visit + Default + Debug + Clone + Reflect> Visit for TileGridMap<V> {
|
||||
fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
|
||||
self.0.visit(name, visitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: Debug + Clone> Deref for TileGridMap<V> {
|
||||
impl<V: Debug + Clone + Reflect> Deref for TileGridMap<V> {
|
||||
type Target = FxHashMap<Vector2<i32>, V>;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: Debug + Clone> DerefMut for TileGridMap<V> {
|
||||
impl<V: Debug + Clone + Reflect> DerefMut for TileGridMap<V> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.0
|
||||
}
|
||||
@@ -382,7 +382,7 @@ pub struct Stamp {
|
||||
|
||||
/// Each cell of a stamp must have a tile handle and it may optionally have
|
||||
/// the handle of a brush cell where the tile was taken from.
|
||||
#[derive(Clone, Debug, Reflect)]
|
||||
#[derive(Clone, Debug, Reflect, Visit, Default)]
|
||||
pub struct StampElement {
|
||||
/// The stamp cell's tile handle
|
||||
pub handle: TileDefinitionHandle,
|
||||
|
||||
@@ -54,7 +54,7 @@ pub struct OrthoTransformation(i8);
|
||||
|
||||
/// A map from `Vector2<i32>` to values. It can be transformed to flip and rotate the positions of the values.
|
||||
#[derive(Clone, Debug, Visit)]
|
||||
pub struct OrthoTransformMap<V> {
|
||||
pub struct OrthoTransformMap<V: Visit + Default> {
|
||||
transform: OrthoTransformation,
|
||||
map: FxHashMap<Vector2<i32>, V>,
|
||||
}
|
||||
@@ -249,7 +249,7 @@ impl<V: Number + SimdPartialOrd + Add + AddAssign + Neg<Output = V> + Scalar> Or
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> OrthoTransformMap<V> {
|
||||
impl<V: Visit + Default> OrthoTransformMap<V> {
|
||||
/// Bounding rectangle the contains the keys.
|
||||
pub fn bounding_rect(&self) -> OptionTileRect {
|
||||
let mut result = OptionTileRect::default();
|
||||
@@ -316,7 +316,7 @@ impl<V> OrthoTransformMap<V> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> Default for OrthoTransformMap<V> {
|
||||
impl<V: Visit + Default> Default for OrthoTransformMap<V> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
transform: Default::default(),
|
||||
@@ -325,7 +325,7 @@ impl<V> Default for OrthoTransformMap<V> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> OrthoTransform for OrthoTransformMap<V> {
|
||||
impl<V: Visit + Default> OrthoTransform for OrthoTransformMap<V> {
|
||||
fn x_flipped(self) -> Self {
|
||||
Self {
|
||||
transform: self.transform.x_flipped(),
|
||||
|
||||
@@ -75,7 +75,10 @@ impl VertexData {
|
||||
|
||||
/// A trait, that describes and arbitrary vertex that could be used in a graph. It allows you to
|
||||
/// use your structure to store additional info in the graph.
|
||||
pub trait VertexDataProvider: Deref<Target = VertexData> + DerefMut + PositionProvider {}
|
||||
pub trait VertexDataProvider:
|
||||
Deref<Target = VertexData> + DerefMut + PositionProvider + Default + Visit + 'static
|
||||
{
|
||||
}
|
||||
|
||||
/// A default graph vertex with no additional data.
|
||||
#[derive(Default, PartialEq, Debug)]
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
//! is returned from any descendant node. In other worlds `Selector` implement OR logical
|
||||
//! function.
|
||||
|
||||
use crate::utils::behavior::BaseBehavior;
|
||||
use crate::{
|
||||
core::{pool::Handle, visitor::prelude::*},
|
||||
utils::behavior::{BehaviorNode, BehaviorTree},
|
||||
@@ -48,7 +49,7 @@ pub enum CompositeNodeKind {
|
||||
#[derive(Debug, PartialEq, Visit, Eq, Clone)]
|
||||
pub struct CompositeNode<B>
|
||||
where
|
||||
B: Clone,
|
||||
B: BaseBehavior,
|
||||
{
|
||||
/// A set of children.
|
||||
pub children: Vec<Handle<BehaviorNode<B>>>,
|
||||
@@ -58,7 +59,7 @@ where
|
||||
|
||||
impl<B> Default for CompositeNode<B>
|
||||
where
|
||||
B: Clone,
|
||||
B: BaseBehavior,
|
||||
{
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
@@ -70,7 +71,7 @@ where
|
||||
|
||||
impl<B> CompositeNode<B>
|
||||
where
|
||||
B: Clone + 'static,
|
||||
B: BaseBehavior,
|
||||
{
|
||||
/// Creates new composite node of given kind and set of children nodes.
|
||||
pub fn new(kind: CompositeNodeKind, children: Vec<Handle<BehaviorNode<B>>>) -> Self {
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
//! A node, that inverts its child state ([`super::Status::Failure`] becomes [`super::Status::Success`] and vice versa, [`super::Status::Running`] remains
|
||||
//! unchanged)
|
||||
|
||||
use crate::utils::behavior::BaseBehavior;
|
||||
use crate::{
|
||||
core::{pool::Handle, visitor::prelude::*},
|
||||
utils::behavior::{BehaviorNode, BehaviorTree},
|
||||
@@ -30,7 +31,7 @@ use crate::{
|
||||
#[derive(Debug, PartialEq, Visit, Eq, Clone)]
|
||||
pub struct Inverter<B>
|
||||
where
|
||||
B: Clone,
|
||||
B: BaseBehavior,
|
||||
{
|
||||
/// A handle of child node, the state of which will be inverted.
|
||||
pub child: Handle<BehaviorNode<B>>,
|
||||
@@ -38,7 +39,7 @@ where
|
||||
|
||||
impl<B> Default for Inverter<B>
|
||||
where
|
||||
B: Clone,
|
||||
B: BaseBehavior,
|
||||
{
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
@@ -49,7 +50,7 @@ where
|
||||
|
||||
impl<B> Inverter<B>
|
||||
where
|
||||
B: Clone + 'static,
|
||||
B: BaseBehavior,
|
||||
{
|
||||
/// Creates new inverter node with given action.
|
||||
pub fn new(child: Handle<BehaviorNode<B>>) -> Self {
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
//! Leaf is a "final" node of a behavior tree. It contains user-defined action which
|
||||
//! is able to mutate given context.
|
||||
|
||||
use crate::utils::behavior::BaseBehavior;
|
||||
use crate::{
|
||||
core::{pool::Handle, visitor::prelude::*},
|
||||
utils::behavior::{BehaviorNode, BehaviorTree},
|
||||
@@ -31,7 +32,7 @@ use std::cell::RefCell;
|
||||
#[derive(Debug, PartialEq, Visit, Eq, Clone)]
|
||||
pub struct LeafNode<B>
|
||||
where
|
||||
B: Clone,
|
||||
B: BaseBehavior,
|
||||
{
|
||||
/// User-defined behavior.
|
||||
pub behavior: Option<RefCell<B>>,
|
||||
@@ -39,7 +40,7 @@ where
|
||||
|
||||
impl<B> Default for LeafNode<B>
|
||||
where
|
||||
B: Clone,
|
||||
B: BaseBehavior,
|
||||
{
|
||||
fn default() -> Self {
|
||||
Self { behavior: None }
|
||||
@@ -48,7 +49,7 @@ where
|
||||
|
||||
impl<B> LeafNode<B>
|
||||
where
|
||||
B: Clone + 'static,
|
||||
B: BaseBehavior,
|
||||
{
|
||||
/// Creates new leaf node with given action.
|
||||
pub fn new(behavior: B) -> Self {
|
||||
|
||||
@@ -65,8 +65,12 @@ pub enum Status {
|
||||
Running,
|
||||
}
|
||||
|
||||
/// Base trait for all behaviors. This trait has auto-impl.
|
||||
pub trait BaseBehavior: Visit + Default + PartialEq + Debug + Clone + 'static {}
|
||||
impl<T: Visit + Default + PartialEq + Debug + Clone + 'static> BaseBehavior for T {}
|
||||
|
||||
/// A trait for user-defined actions for behavior tree.
|
||||
pub trait Behavior<'a>: Visit + Default + PartialEq + Debug + Clone {
|
||||
pub trait Behavior<'a>: BaseBehavior {
|
||||
/// A context in which the behavior will be performed.
|
||||
type Context;
|
||||
|
||||
@@ -80,14 +84,14 @@ pub trait Behavior<'a>: Visit + Default + PartialEq + Debug + Clone {
|
||||
#[derive(Debug, PartialEq, Visit, Eq, Clone)]
|
||||
pub struct RootNode<B>
|
||||
where
|
||||
B: Clone,
|
||||
B: BaseBehavior,
|
||||
{
|
||||
child: Handle<BehaviorNode<B>>,
|
||||
}
|
||||
|
||||
impl<B> Default for RootNode<B>
|
||||
where
|
||||
B: Clone,
|
||||
B: BaseBehavior,
|
||||
{
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
@@ -100,7 +104,7 @@ where
|
||||
#[derive(Debug, PartialEq, Visit, Eq, Clone, Default)]
|
||||
pub enum BehaviorNode<B>
|
||||
where
|
||||
B: Clone,
|
||||
B: BaseBehavior,
|
||||
{
|
||||
#[doc(hidden)]
|
||||
#[default]
|
||||
@@ -120,7 +124,7 @@ where
|
||||
#[derive(Debug, PartialEq, Visit, Clone)]
|
||||
pub struct BehaviorTree<B>
|
||||
where
|
||||
B: Clone + 'static,
|
||||
B: BaseBehavior,
|
||||
{
|
||||
nodes: Pool<BehaviorNode<B>>,
|
||||
root: Handle<BehaviorNode<B>>,
|
||||
@@ -128,7 +132,7 @@ where
|
||||
|
||||
impl<B> Default for BehaviorTree<B>
|
||||
where
|
||||
B: Clone + 'static,
|
||||
B: BaseBehavior,
|
||||
{
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
@@ -140,7 +144,7 @@ where
|
||||
|
||||
impl<B> BehaviorTree<B>
|
||||
where
|
||||
B: Clone + 'static,
|
||||
B: BaseBehavior,
|
||||
{
|
||||
/// Creates new behavior tree with single root node.
|
||||
pub fn new() -> Self {
|
||||
@@ -251,7 +255,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Clone + 'static> Index<Handle<BehaviorNode<B>>> for BehaviorTree<B> {
|
||||
impl<B: BaseBehavior> Index<Handle<BehaviorNode<B>>> for BehaviorTree<B> {
|
||||
type Output = BehaviorNode<B>;
|
||||
|
||||
fn index(&self, index: Handle<BehaviorNode<B>>) -> &Self::Output {
|
||||
@@ -259,7 +263,7 @@ impl<B: Clone + 'static> Index<Handle<BehaviorNode<B>>> for BehaviorTree<B> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Clone + 'static> IndexMut<Handle<BehaviorNode<B>>> for BehaviorTree<B> {
|
||||
impl<B: BaseBehavior> IndexMut<Handle<BehaviorNode<B>>> for BehaviorTree<B> {
|
||||
fn index_mut(&mut self, index: Handle<BehaviorNode<B>>) -> &mut Self::Output {
|
||||
&mut self.nodes[index]
|
||||
}
|
||||
@@ -271,7 +275,7 @@ pub fn sequence<B, const N: usize>(
|
||||
tree: &mut BehaviorTree<B>,
|
||||
) -> Handle<BehaviorNode<B>>
|
||||
where
|
||||
B: Clone + 'static,
|
||||
B: BaseBehavior,
|
||||
{
|
||||
CompositeNode::new_sequence(children.to_vec()).add_to(tree)
|
||||
}
|
||||
@@ -282,7 +286,7 @@ pub fn selector<B, const N: usize>(
|
||||
tree: &mut BehaviorTree<B>,
|
||||
) -> Handle<BehaviorNode<B>>
|
||||
where
|
||||
B: Clone + 'static,
|
||||
B: BaseBehavior,
|
||||
{
|
||||
CompositeNode::new_selector(children.to_vec()).add_to(tree)
|
||||
}
|
||||
@@ -290,7 +294,7 @@ where
|
||||
/// Creates a new leaf.
|
||||
pub fn leaf<B>(behavior: B, tree: &mut BehaviorTree<B>) -> Handle<BehaviorNode<B>>
|
||||
where
|
||||
B: Clone + 'static,
|
||||
B: BaseBehavior,
|
||||
{
|
||||
LeafNode::new(behavior).add_to(tree)
|
||||
}
|
||||
@@ -301,7 +305,7 @@ pub fn inverter<B>(
|
||||
tree: &mut BehaviorTree<B>,
|
||||
) -> Handle<BehaviorNode<B>>
|
||||
where
|
||||
B: Clone + 'static,
|
||||
B: BaseBehavior,
|
||||
{
|
||||
Inverter::new(child).add_to(tree)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user