Reflect::try_clone_box

- `#[reflect(non_cloneable)]` for types that cannot be cloned
This commit is contained in:
Dmitry Stepanov
2025-05-16 23:26:34 +03:00
parent f2a96f3307
commit ef4e4b46ca
65 changed files with 506 additions and 126 deletions
-1
View File
@@ -18,7 +18,6 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
use crate::fyrox::core::reflect::Reflect;
use crate::fyrox::graph::BaseSceneGraph;
use crate::fyrox::{
asset::{manager::ResourceManager, options::BaseImportOptions},
+1 -1
View File
@@ -47,7 +47,7 @@ use std::{
sync::Arc,
};
#[derive(Reflect, Debug)]
#[derive(Reflect, Clone, Debug)]
struct LightmapperSettings {
#[reflect(
description = "Amount of texels per unit. It defines 'pixels density' per unit of area (square meters). The \
+1 -1
View File
@@ -69,7 +69,7 @@ use fyrox::asset::manager::ResourceManager;
use fyrox::gui::inspector::InspectorContextArgs;
use std::{ops::Range, sync::Arc};
#[derive(Reflect, Debug)]
#[derive(Reflect, Clone, Debug)]
pub struct RagdollPreset {
#[reflect(description = "A handle of a hips (pelvis) bone.")]
hips: Handle<Node>,
+4
View File
@@ -172,6 +172,10 @@ impl ResourceData for AutoTileInstance {
fn can_be_saved(&self) -> bool {
false
}
fn try_clone_box(&self) -> Option<Box<dyn ResourceData>> {
Some(Box::new(self.clone()))
}
}
pub struct TileSetTerrainSource<'a, 'b> {
@@ -39,7 +39,7 @@ const REMOVE_TOOLTIP: &str = "Remove the selected cell from this macro.";
const CELL_WITH_MACRO_COLOR: Color = Color::DARK_SLATE_BLUE;
const CELL_WITHOUT_MACRO_COLOR: Color = Color::opaque(50, 50, 50);
#[derive(Visit, Reflect)]
#[derive(Visit, Clone, Reflect)]
pub struct MacroInspector {
handle: Handle<UiNode>,
content: Handle<UiNode>,
@@ -66,16 +66,19 @@ impl Debug for MacroInspector {
}
}
#[derive(Clone)]
struct Item {
macro_id: Uuid,
editor: Option<ItemEditor>,
}
#[derive(Clone)]
struct ItemEditor {
handle: Handle<UiNode>,
header: ItemHeader,
}
#[derive(Clone)]
struct ItemHeader {
handle: Handle<UiNode>,
label: Handle<UiNode>,
+1 -1
View File
@@ -722,7 +722,7 @@ impl ColliderEditors {
}
}
#[derive(Visit, Reflect)]
#[derive(Visit, Reflect, Clone)]
pub struct TileInspector {
handle: Handle<UiNode>,
/// The shared state that represents the user's currently selected tool and tiles.
+4
View File
@@ -254,6 +254,10 @@ impl ResourceData for WfcInstance {
fn can_be_saved(&self) -> bool {
false
}
fn try_clone_box(&self) -> Option<Box<dyn ResourceData>> {
Some(Box::new(self.clone()))
}
}
impl BrushMacro for WfcMacro {
+1 -1
View File
@@ -255,7 +255,7 @@ impl GameScene {
let scene = &mut engine.scenes[self.scene];
let editor_root = self.editor_objects_root;
let (pure_scene, _) = scene.clone(
let (pure_scene, _) = scene.clone_ex(
self.scene_content_root,
&mut |node, _| node != editor_root,
&mut |_, _| {},
+4
View File
@@ -135,6 +135,10 @@ impl ResourceData for AnimationTracksData {
fn can_be_saved(&self) -> bool {
true
}
fn try_clone_box(&self) -> Option<Box<dyn ResourceData>> {
Some(Box::new(self.clone()))
}
}
/// A resource that holds animation tracks. This resource can be shared across multiple animations.
@@ -74,6 +74,10 @@ macro_rules! define_two_args_node {
Self::derived_types()
}
fn try_clone_box(&self) -> Option<Box<dyn Reflect>> {
Some(Box::new(self.clone()))
}
fn type_name(&self) -> &'static str {
type_name::<Self>()
}
@@ -347,6 +351,10 @@ impl<T: EntityId> Reflect for NotNode<T> {
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()))
}
}
/// A node responsible for logical operations evaluation. It can have any number of descendant nodes.
+2 -2
View File
@@ -473,7 +473,7 @@ mod test {
use crate::value::{BoundValue, TrackValue, ValueBinding, ValueType};
use fyrox_core::{reflect::prelude::*, variable::InheritableVariable};
#[derive(Reflect, Debug, PartialEq)]
#[derive(Reflect, Debug, Clone, PartialEq)]
struct OtherStruct {
field: u32,
inheritable_variable: InheritableVariable<u32>,
@@ -488,7 +488,7 @@ mod test {
}
}
#[derive(Default, Reflect, Debug, PartialEq)]
#[derive(Default, Reflect, Clone, Debug, PartialEq)]
struct MyStruct {
some_bool: bool,
some_property: f32,
+16
View File
@@ -321,6 +321,20 @@ fn gen_impl(
}
});
let try_clone_box = if ty_args.non_cloneable {
quote! {
fn try_clone_box(&self) -> Option<Box<dyn Reflect>> {
None
}
}
} else {
quote! {
fn try_clone_box(&self) -> Option<Box<dyn Reflect>> {
Some(Box::new(self.clone()))
}
}
};
let types = ty_args
.derived_type
.iter()
@@ -337,6 +351,8 @@ fn gen_impl(
file!()
}
#try_clone_box
fn type_name(&self) -> &'static str {
std::any::type_name::<Self>()
}
+4
View File
@@ -23,6 +23,7 @@
use darling::*;
use proc_macro2::TokenStream as TokenStream2;
use quote::quote;
use syn::__private::bool;
use syn::*;
pub type Fields = ast::Fields<FieldArgs>;
@@ -58,6 +59,9 @@ pub struct TypeArgs {
#[darling(multiple)]
pub derived_type: Vec<Path>,
#[darling(default)]
pub non_cloneable: bool,
}
impl TypeArgs {
+24 -23
View File
@@ -40,10 +40,10 @@ pub struct Struct {
hidden: usize,
}
#[derive(Reflect, Debug)]
#[derive(Reflect, Clone, Debug)]
pub struct Tuple(usize, usize);
#[derive(Reflect, Debug)]
#[derive(Reflect, Clone, Debug)]
pub enum Enum {
Named { field: usize },
Tuple(usize),
@@ -122,7 +122,7 @@ fn reflect_field_accessors() {
#[test]
fn reflect_containers() {
#[derive(Debug)]
#[derive(Debug, Clone)]
struct DerefContainer<T> {
data: T,
}
@@ -140,7 +140,7 @@ fn reflect_containers() {
}
}
#[derive(Reflect, Debug)]
#[derive(Reflect, Clone, Debug)]
struct X {
#[reflect(deref)]
container: DerefContainer<Struct>,
@@ -161,8 +161,8 @@ fn reflect_containers() {
x.get_resolve_path::<usize>("container.field", &mut |result| assert_eq!(result, Ok(&0)));
#[derive(Reflect, Debug)]
#[reflect(bounds = "T: Reflect")]
#[derive(Reflect, Clone, Debug)]
#[reflect(bounds = "T: Reflect + Clone")]
struct B<T> {
#[reflect(deref)]
data: Box<T>,
@@ -181,7 +181,7 @@ fn reflect_containers() {
#[test]
fn reflect_path() {
#[derive(Reflect, Debug)]
#[derive(Reflect, Clone, Debug)]
struct Hierarchy {
s: Struct,
e: Enum,
@@ -222,12 +222,12 @@ fn reflect_list_path() {
let data = vec![vec![0usize, 1], vec![2, 3, 4]];
data.get_resolve_path("[0][1]", &mut |result| assert_eq!(result, Ok(&1usize)));
#[derive(Reflect, Debug)]
#[derive(Reflect, Clone, Debug)]
struct X {
data: Vec<usize>,
}
#[derive(Reflect, Debug)]
#[derive(Reflect, Clone, Debug)]
struct A {
xs: Vec<X>,
}
@@ -248,7 +248,8 @@ fn reflect_list_path() {
#[test]
fn reflect_custom_setter() {
#[derive(Reflect, Debug)]
#[derive(Reflect, Clone, Debug)]
#[reflect(bounds = "T: Reflect + Clone")]
pub struct Wrapper<T> {
#[reflect(setter = "set_value")]
value: T,
@@ -276,7 +277,7 @@ fn reflect_custom_setter() {
#[test]
fn reflect_fields_list_of_struct() {
#[derive(Reflect, Debug)]
#[derive(Reflect, Clone, Debug)]
struct Foo {
field_a: f32,
field_b: String,
@@ -306,7 +307,7 @@ fn reflect_fields_list_of_struct() {
#[test]
fn reflect_fields_list_of_enum() {
#[derive(Reflect, Debug)]
#[derive(Reflect, Clone, Debug)]
enum Foo {
Bar { field_a: f32 },
Baz { field_b: u32, field_c: String },
@@ -362,7 +363,7 @@ fn default_prop_metadata() -> FieldMetadata<'static> {
#[test]
fn inspect_default() {
#[derive(Debug, Default, Reflect)]
#[derive(Debug, Default, Clone, Reflect)]
pub struct Data {
the_field: String,
another_field: f32,
@@ -398,13 +399,13 @@ fn inspect_default() {
#[test]
fn inspect_attributes() {
#[derive(Debug, Default, Reflect)]
#[derive(Debug, Default, Clone, Reflect)]
pub struct AarGee {
aar: u32,
gee: u32,
}
#[derive(Debug, Default, Reflect)]
#[derive(Debug, Default, Clone, Reflect)]
pub struct Data {
// NOTE: Even though this field is skipped, the next field is given index `1` for simplicity
#[reflect(hidden)]
@@ -459,7 +460,7 @@ fn inspect_attributes() {
#[test]
fn inspect_struct() {
#[derive(Debug, Default, Reflect)]
#[derive(Debug, Default, Clone, Reflect)]
struct Tuple(f32, f32);
let x = Tuple::default();
@@ -488,7 +489,7 @@ fn inspect_struct() {
)
});
#[derive(Debug, Default, Reflect)]
#[derive(Debug, Default, Clone, Reflect)]
struct Unit;
let x = Unit;
@@ -497,12 +498,12 @@ fn inspect_struct() {
#[test]
fn inspect_enum() {
#[derive(Debug, Reflect)]
#[derive(Debug, Clone, Reflect)]
pub struct NonCopy {
inner: u32,
}
#[derive(Debug, Reflect)]
#[derive(Debug, Clone, Reflect)]
pub enum Data {
Named { x: u32, y: u32, z: NonCopy },
Tuple(f32, f32),
@@ -596,7 +597,7 @@ fn inspect_enum() {
#[test]
fn inspect_prop_key_constants() {
#[allow(dead_code)]
#[derive(Reflect, Debug)]
#[derive(Reflect, Clone, Debug)]
pub struct SStruct {
field: usize,
#[reflect(hidden)]
@@ -609,11 +610,11 @@ fn inspect_prop_key_constants() {
// hidden properties
// assert_eq!(SStruct::HIDDEN, "hidden");
#[derive(Reflect, Debug)]
#[derive(Reflect, Clone, Debug)]
pub struct STuple(usize);
assert_eq!(STuple::F_0, "0");
#[derive(Reflect, Debug)]
#[derive(Reflect, Clone, Debug)]
#[allow(unused)]
pub enum E {
Tuple(usize),
@@ -689,7 +690,7 @@ fn test_hash_map() {
});
// Check path resolution.
#[derive(Reflect, Debug)]
#[derive(Reflect, Clone, Debug)]
struct Something {
hash_map: HashMap<String, Struct>,
}
+1 -1
View File
@@ -38,7 +38,7 @@ use fyrox_core_derive::{impl_reflect, impl_visit};
use std::fmt::Debug;
impl_reflect!(
pub struct Rect<T: Debug> {}
pub struct Rect<T: Debug + Copy> {}
);
impl<T> Visit for Rect<T>
+4
View File
@@ -123,6 +123,10 @@ impl<T: Reflect> Reflect for Handle<T> {
T::derived_types()
}
fn try_clone_box(&self) -> Option<Box<dyn Reflect>> {
Some(Box::new(*self))
}
fn query_derived_types(&self) -> &'static [TypeId] {
Self::derived_types()
}
+6
View File
@@ -98,6 +98,7 @@ impl<T, P> Reflect for Pool<T, P>
where
T: Reflect,
P: PayloadContainer<Element = T> + Reflect,
Pool<T, P>: Clone,
{
#[inline]
fn source_path() -> &'static str {
@@ -111,6 +112,10 @@ where
&[]
}
fn try_clone_box(&self) -> Option<Box<dyn Reflect>> {
Some(Box::new(self.clone()))
}
fn query_derived_types(&self) -> &'static [TypeId] {
Self::derived_types()
}
@@ -189,6 +194,7 @@ impl<T, P> ReflectArray for Pool<T, P>
where
T: Reflect,
P: PayloadContainer<Element = T> + Reflect,
Pool<T, P>: Clone,
{
#[inline]
fn reflect_index(&self, index: usize) -> Option<&dyn Reflect> {
+18 -5
View File
@@ -219,7 +219,10 @@ pub trait ReflectBase: Any + Debug {
fn as_any_raw_mut(&mut self) -> &mut dyn Any;
}
impl<T: Reflect> ReflectBase for T {
impl<T> ReflectBase for T
where
T: Reflect,
{
fn as_any_raw(&self) -> &dyn Any {
self
}
@@ -257,6 +260,8 @@ pub trait Reflect: ReflectBase {
where
Self: Sized;
fn try_clone_box(&self) -> Option<Box<dyn Reflect>>;
fn query_derived_types(&self) -> &'static [TypeId];
fn type_name(&self) -> &'static str;
@@ -1203,6 +1208,10 @@ macro_rules! blank_reflect {
&[]
}
fn try_clone_box(&self) -> Option<Box<dyn Reflect>> {
Some(Box::new(self.clone()))
}
fn query_derived_types(&self) -> &'static [std::any::TypeId] {
Self::derived_types()
}
@@ -1279,6 +1288,10 @@ macro_rules! delegate_reflect {
&[]
}
fn try_clone_box(&self) -> Option<Box<dyn Reflect>> {
Some(Box::new(self.clone()))
}
fn query_derived_types(&self) -> &'static [std::any::TypeId] {
Self::derived_types()
}
@@ -1456,7 +1469,7 @@ mod test {
use std::any::TypeId;
use std::collections::HashMap;
#[derive(Reflect, Default, Debug)]
#[derive(Reflect, Clone, Default, Debug)]
struct Foo {
bar: Bar,
baz: f32,
@@ -1464,12 +1477,12 @@ mod test {
hash_map: HashMap<String, Item>,
}
#[derive(Reflect, Default, Debug)]
#[derive(Reflect, Clone, Default, Debug)]
struct Item {
payload: u32,
}
#[derive(Reflect, Default, Debug)]
#[derive(Reflect, Clone, Default, Debug)]
struct Bar {
stuff: String,
}
@@ -1503,7 +1516,7 @@ mod test {
assert_eq!(names[9], "hash_map[Foobar].payload");
}
#[derive(Reflect, Debug)]
#[derive(Reflect, Clone, Debug)]
#[reflect(derived_type = "Derived")]
struct Base;
+4 -4
View File
@@ -27,24 +27,24 @@ use std::fmt::Debug;
use crate::reflect::prelude::*;
impl_reflect! {
pub struct Matrix<T: 'static, R: Dim + 'static, C: Dim + 'static, S: 'static> {
pub struct Matrix<T: Copy + 'static, R: Dim + 'static, C: Dim + 'static, S: Copy + 'static> {
pub data: S,
// _phantoms: PhantomData<(T, R, C)>,
}
}
impl_reflect! {
pub struct ArrayStorage<T: Debug, const R: usize, const C: usize>(pub [[T; R]; C]);
pub struct ArrayStorage<T: Copy + Debug, const R: usize, const C: usize>(pub [[T; R]; C]);
}
impl_reflect! {
pub struct Unit<T: Debug + 'static> {
pub struct Unit<T: Copy + Debug + 'static> {
// pub(crate) value: T,
}
}
impl_reflect! {
pub struct Quaternion<T: Debug> {
pub struct Quaternion<T: Copy + Debug> {
pub coords: Vector4<T>,
}
}
+30 -25
View File
@@ -67,7 +67,7 @@ macro_rules! impl_reflect_tuple {
)*
) => {
$(
impl< $($t: Reflect),* > Reflect for ( $($t,)* ) {
impl< $($t: Clone + Reflect),* > Reflect for ( $($t,)* ) {
blank_reflect!();
}
)*
@@ -82,7 +82,7 @@ impl_reflect_tuple! {
(T0, T1, T2, T3, T4,);
}
impl<const N: usize, T: Reflect> Reflect for [T; N] {
impl<const N: usize, T: Reflect + Clone> Reflect for [T; N] {
blank_reflect!();
fn as_array(&self, func: &mut dyn FnMut(Option<&dyn ReflectArray>)) {
@@ -94,7 +94,7 @@ impl<const N: usize, T: Reflect> Reflect for [T; N] {
}
}
impl<const N: usize, T: Reflect> ReflectArray for [T; N] {
impl<const N: usize, T: Reflect + Clone> ReflectArray for [T; N] {
fn reflect_index(&self, index: usize) -> Option<&dyn Reflect> {
if let Some(item) = self.get(index) {
Some(item)
@@ -118,10 +118,10 @@ impl<const N: usize, T: Reflect> ReflectArray for [T; N] {
impl_reflect! {
#[reflect(ReflectList, ReflectArray)]
pub struct Vec<T: Reflect>;
pub struct Vec<T: Reflect + Clone>;
}
impl<T: Reflect> ReflectArray for Vec<T> {
impl<T: Reflect + Clone> ReflectArray for Vec<T> {
fn reflect_index(&self, index: usize) -> Option<&dyn Reflect> {
self.get(index).map(|x| x as &dyn Reflect)
}
@@ -136,7 +136,7 @@ impl<T: Reflect> ReflectArray for Vec<T> {
}
/// REMARK: `Reflect` is implemented for `Vec<T>` where `T: Reflect` only.
impl<T: Reflect> ReflectList for Vec<T> {
impl<T: Reflect + Clone> ReflectList for Vec<T> {
fn reflect_push(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>> {
self.push(*value.downcast::<T>()?);
Ok(())
@@ -170,9 +170,9 @@ impl<T: Reflect> ReflectList for Vec<T> {
impl<K, V, S> Reflect for HashMap<K, V, S>
where
K: Reflect + Eq + Hash + 'static,
V: Reflect,
S: BuildHasher + 'static,
K: Reflect + Eq + Hash + Clone + 'static,
V: Reflect + Clone,
S: BuildHasher + Clone + 'static,
{
blank_reflect!();
@@ -187,9 +187,9 @@ where
impl<K, V, S> ReflectHashMap for HashMap<K, V, S>
where
K: Reflect + Eq + Hash + 'static,
V: Reflect,
S: BuildHasher + 'static,
K: Reflect + Eq + Hash + Clone + 'static,
V: Reflect + Clone,
S: BuildHasher + Clone + 'static,
{
fn reflect_insert(
&mut self,
@@ -281,20 +281,20 @@ impl_reflect! {
}
impl_reflect! {
pub enum Option<T> {
pub enum Option<T: Clone> {
Some(T),
None
}
}
impl_reflect! {
pub struct Range<Idx> {
pub struct Range<Idx: Clone> {
pub start: Idx,
pub end: Idx,
}
}
impl<T: ?Sized + Reflect> Reflect for Box<T> {
impl<T: Reflect + Clone> Reflect for Box<T> {
delegate_reflect!();
}
@@ -310,6 +310,11 @@ macro_rules! impl_reflect_inner_mutability {
&[]
}
fn try_clone_box(&$self) -> Option<Box<dyn Reflect>> {
let guard = $acquire_lock_guard;
Some(Box::new(guard.clone()))
}
fn query_derived_types(&self) -> &'static [std::any::TypeId] {
T::derived_types()
}
@@ -438,24 +443,24 @@ macro_rules! impl_reflect_inner_mutability {
};
}
impl<T: Reflect> Reflect for parking_lot::Mutex<T> {
impl<T: Reflect + Clone> Reflect for parking_lot::Mutex<T> {
impl_reflect_inner_mutability!(self, { self.lock() }, { self.into_inner() });
}
impl<T: Reflect> Reflect for parking_lot::RwLock<T> {
impl<T: Reflect + Clone> Reflect for parking_lot::RwLock<T> {
impl_reflect_inner_mutability!(self, { self.write() }, { self.into_inner() });
}
#[allow(clippy::mut_mutex_lock)]
impl<T: Reflect> Reflect for std::sync::Mutex<T> {
impl<T: Reflect + Clone> Reflect for std::sync::Mutex<T> {
impl_reflect_inner_mutability!(self, { self.lock().unwrap() }, { self.into_inner() });
}
impl<T: Reflect> Reflect for std::sync::RwLock<T> {
impl<T: Reflect + Clone> Reflect for std::sync::RwLock<T> {
impl_reflect_inner_mutability!(self, { self.write().unwrap() }, { self.into_inner() });
}
impl<T: Reflect> Reflect for Arc<parking_lot::Mutex<T>> {
impl<T: Reflect + Clone> Reflect for Arc<parking_lot::Mutex<T>> {
impl_reflect_inner_mutability!(self, { self.lock() }, {
Arc::into_inner(*self)
.expect("Value cannot be shared!")
@@ -463,7 +468,7 @@ impl<T: Reflect> Reflect for Arc<parking_lot::Mutex<T>> {
});
}
impl<T: Reflect> Reflect for Arc<std::sync::Mutex<T>> {
impl<T: Reflect + Clone> Reflect for Arc<std::sync::Mutex<T>> {
impl_reflect_inner_mutability!(self, { self.lock().unwrap() }, {
Arc::into_inner(*self)
.expect("Value cannot be shared!")
@@ -471,7 +476,7 @@ impl<T: Reflect> Reflect for Arc<std::sync::Mutex<T>> {
});
}
impl<T: Reflect> Reflect for Arc<std::sync::RwLock<T>> {
impl<T: Reflect + Clone> Reflect for Arc<std::sync::RwLock<T>> {
impl_reflect_inner_mutability!(self, { self.write().unwrap() }, {
Arc::into_inner(*self)
.expect("Value cannot be shared!")
@@ -479,7 +484,7 @@ impl<T: Reflect> Reflect for Arc<std::sync::RwLock<T>> {
});
}
impl<T: Reflect> Reflect for Arc<parking_lot::RwLock<T>> {
impl<T: Reflect + Clone> Reflect for Arc<parking_lot::RwLock<T>> {
impl_reflect_inner_mutability!(self, { self.write() }, {
Arc::into_inner(*self)
.expect("Value cannot be shared!")
@@ -487,11 +492,11 @@ impl<T: Reflect> Reflect for Arc<parking_lot::RwLock<T>> {
});
}
impl<T: Reflect> Reflect for RefCell<T> {
impl<T: Reflect + Clone> Reflect for RefCell<T> {
impl_reflect_inner_mutability!(self, { self.borrow_mut() }, { self.into_inner() });
}
impl<T: Reflect> Reflect for Rc<RefCell<T>> {
impl<T: Reflect + Clone> Reflect for Rc<RefCell<T>> {
impl_reflect_inner_mutability!(self, { self.borrow_mut() }, {
Rc::into_inner(*self)
.expect("Value cannot be shared!")
+5 -1
View File
@@ -381,6 +381,10 @@ where
file!()
}
fn try_clone_box(&self) -> Option<Box<dyn Reflect>> {
Some(Box::new(self.clone()))
}
fn derived_types() -> &'static [TypeId]
where
Self: Sized,
@@ -839,7 +843,7 @@ mod test {
assert!(va.value_equals(&vb))
}
#[derive(Reflect, Debug)]
#[derive(Reflect, Clone, Debug)]
enum SomeEnum {
Bar(InheritableVariable<f32>),
Baz {
+10 -2
View File
@@ -1598,6 +1598,10 @@ mod test {
fn query_derived_types(&self) -> &'static [TypeId] {
Self::derived_types()
}
fn try_clone_box(&self) -> Option<Box<dyn Reflect>> {
Some(Box::new(self.clone()))
}
}
impl NameProvider for Node {
@@ -1622,7 +1626,7 @@ mod test {
/// A wrapper for node pool record that allows to define custom visit method to have full
/// control over instantiation process at deserialization.
#[derive(Debug, Default, Reflect)]
#[derive(Debug, Default, Clone, Reflect)]
pub struct NodeContainer(Option<Node>);
impl Visit for NodeContainer {
@@ -1711,7 +1715,7 @@ mod test {
}
}
#[derive(Default, TypeUuidProvider, Visit, Reflect, Debug)]
#[derive(Default, Clone, TypeUuidProvider, Visit, Reflect, Debug)]
#[type_uuid(id = "fc887063-7780-44af-8710-5e0bcf9a83fd")]
pub struct Graph {
root: Handle<Node>,
@@ -1730,6 +1734,10 @@ mod test {
fn can_be_saved(&self) -> bool {
false
}
fn try_clone_box(&self) -> Option<Box<dyn ResourceData>> {
Some(Box::new(self.clone()))
}
}
impl PrefabData for Graph {
+2 -1
View File
@@ -283,6 +283,7 @@ struct SceneLoadingOptions {
/// use std::path::Path;
///
/// #[derive(Visit, Reflect, Debug)]
/// #[reflect(non_cloneable)]
/// struct MyGame {
/// scene: Handle<Scene>,
/// }
@@ -1707,7 +1708,7 @@ impl Engine {
// some methods (`Base::root_resource` in particular) won't work
// correctly.
scene: scene
.clone(
.clone_ex(
scene.graph.get_root(),
&mut |_, _| true,
&mut |_, _| {},
+1
View File
@@ -103,6 +103,7 @@ impl TaskPoolHandler {
/// # use std::{fs::File, io::Read};
///
/// #[derive(Visit, Reflect, Debug)]
/// #[reflect(non_cloneable)]
/// struct MyGame {
/// data: Option<Vec<u8>>,
/// }
+4
View File
@@ -765,6 +765,10 @@ impl ResourceData for Material {
fn can_be_saved(&self) -> bool {
true
}
fn try_clone_box(&self) -> Option<Box<dyn ResourceData>> {
Some(Box::new(self.clone()))
}
}
/// A set of possible errors that can occur when working with materials.
+7 -3
View File
@@ -543,7 +543,7 @@ pub const STANDARD_SHADER_SOURCES: [&str; 6] = [
///
/// Usually you don't need to access internals of the shader, but there sometimes could be a need to
/// read shader definition, to get supported passes and properties.
#[derive(Default, Debug, Reflect, Visit)]
#[derive(Default, Debug, Clone, Reflect, Visit)]
pub struct Shader {
/// Shader definition contains description of properties and render passes.
#[visit(optional)]
@@ -561,7 +561,7 @@ impl TypeUuidProvider for Shader {
}
/// A render pass definition. See [`ShaderResource`] docs for more info about render passes.
#[derive(Default, Serialize, Deserialize, Debug, PartialEq, Eq, Reflect, Visit)]
#[derive(Default, Clone, Serialize, Deserialize, Debug, PartialEq, Eq, Reflect, Visit)]
pub struct RenderPassDefinition {
/// A name of render pass.
pub name: String,
@@ -581,7 +581,7 @@ pub struct RenderPassDefinition {
}
/// A definition of the shader.
#[derive(Default, Serialize, Deserialize, Debug, PartialEq, Reflect, Visit)]
#[derive(Default, Clone, Serialize, Deserialize, Debug, PartialEq, Reflect, Visit)]
pub struct ShaderDefinition {
/// A name of the shader.
pub name: String,
@@ -845,6 +845,10 @@ impl ResourceData for Shader {
fn can_be_saved(&self) -> bool {
true
}
fn try_clone_box(&self) -> Option<Box<dyn ResourceData>> {
Some(Box::new(self.clone()))
}
}
/// A set of possible error variants that can occur during shader loading.
+1
View File
@@ -227,6 +227,7 @@ impl dyn Plugin {
/// # use std::str::FromStr;
///
/// #[derive(Default, Visit, Reflect, Debug)]
/// #[reflect(non_cloneable)]
/// struct MyPlugin {}
///
/// impl Plugin for MyPlugin {
+5 -1
View File
@@ -74,7 +74,7 @@ impl From<VisitError> for CurveResourceError {
}
/// State of the [`CurveResource`]
#[derive(Debug, Visit, Default, Reflect)]
#[derive(Debug, Clone, Visit, Default, Reflect)]
pub struct CurveResourceState {
/// Actual curve.
pub curve: Curve,
@@ -93,6 +93,10 @@ impl ResourceData for CurveResourceState {
fn can_be_saved(&self) -> bool {
false
}
fn try_clone_box(&self) -> Option<Box<dyn ResourceData>> {
Some(Box::new(self.clone()))
}
}
impl TypeUuidProvider for CurveResourceState {
+5 -1
View File
@@ -80,7 +80,7 @@ use strum_macros::{AsRefStr, EnumString, VariantNames};
pub mod loader;
/// See module docs.
#[derive(Debug, Visit, Reflect)]
#[derive(Debug, Clone, Visit, Reflect)]
pub struct Model {
#[visit(skip)]
pub(crate) mapping: NodeMapping,
@@ -612,6 +612,10 @@ impl ResourceData for Model {
fn can_be_saved(&self) -> bool {
true
}
fn try_clone_box(&self) -> Option<Box<dyn ResourceData>> {
Some(Box::new(self.clone()))
}
}
impl Default for Model {
+13 -1
View File
@@ -186,6 +186,18 @@ pub struct Graph {
instance_id_map: FxHashMap<SceneNodeId, Handle<Node>>,
}
impl Clone for Graph {
fn clone(&self) -> Self {
self.clone_ex(
self.root,
&mut |_, _| true,
&mut |_, _| {},
&mut |_, _, _| {},
)
.0
}
}
impl Default for Graph {
fn default() -> Self {
let (script_message_sender, script_message_receiver) = channel();
@@ -1408,7 +1420,7 @@ impl Graph {
/// Creates deep copy of graph. Allows filtering while copying, returns copy and
/// old-to-new node mapping.
#[inline]
pub fn clone<F, Pre, Post>(
pub fn clone_ex<F, Pre, Post>(
&self,
root: Handle<Node>,
filter: &mut F,
+4
View File
@@ -250,6 +250,10 @@ impl ResourceData for SurfaceData {
fn can_be_saved(&self) -> bool {
true
}
fn try_clone_box(&self) -> Option<Box<dyn ResourceData>> {
Some(Box::new(self.clone()))
}
}
impl SurfaceData {
+9 -3
View File
@@ -238,6 +238,12 @@ pub struct Scene {
pub enabled: InheritableVariable<bool>,
}
impl Clone for Scene {
fn clone(&self) -> Self {
self.clone_one_to_one().0
}
}
impl Default for Scene {
fn default() -> Self {
Self {
@@ -465,7 +471,7 @@ impl Scene {
/// Creates deep copy of a scene, filter predicate allows you to filter out nodes
/// by your criteria.
pub fn clone<F, Pre, Post>(
pub fn clone_ex<F, Pre, Post>(
&self,
root: Handle<Node>,
filter: &mut F,
@@ -479,7 +485,7 @@ impl Scene {
{
let (graph, old_new_map) =
self.graph
.clone(root, filter, pre_process_callback, post_process_callback);
.clone_ex(root, filter, pre_process_callback, post_process_callback);
(
Self {
@@ -495,7 +501,7 @@ impl Scene {
/// Creates deep copy of a scene. Same as [`Self::clone`], but does 1:1 cloning.
pub fn clone_one_to_one(&self) -> (Self, NodeHandleMap<Node>) {
self.clone(
self.clone_ex(
self.graph.get_root(),
&mut |_, _| true,
&mut |_, _| {},
+1 -1
View File
@@ -35,7 +35,7 @@ use fyrox_core::visitor::error::VisitError;
/// A wrapper for node pool record that allows to define custom visit method to have full
/// control over instantiation process at deserialization.
#[derive(Debug, Default, Reflect)]
#[derive(Debug, Clone, Default, Reflect)]
pub struct NodeContainer(Option<Node>);
fn read_node(name: &str, visitor: &mut Visitor) -> Result<Node, VisitError> {
+4
View File
@@ -611,6 +611,10 @@ impl Reflect for Node {
fn field_mut(&mut self, name: &str, func: &mut dyn FnMut(Option<&mut dyn Reflect>)) {
self.0.deref_mut().field_mut(name, func)
}
fn try_clone_box(&self) -> Option<Box<dyn Reflect>> {
Some(Box::new(self.clone()))
}
}
#[cfg(test)]
+4
View File
@@ -243,6 +243,10 @@ impl Reflect for Limb {
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 {
+4
View File
@@ -568,6 +568,10 @@ impl ResourceData for TileMapBrush {
fn can_be_saved(&self) -> bool {
true
}
fn try_clone_box(&self) -> Option<Box<dyn ResourceData>> {
Some(Box::new(self.clone()))
}
}
/// Standard tile map brush loader.
+4
View File
@@ -207,6 +207,10 @@ impl ResourceData for TileMapData {
fn can_be_saved(&self) -> bool {
false
}
fn try_clone_box(&self) -> Option<Box<dyn ResourceData>> {
Some(Box::new(self.clone()))
}
}
impl TileSource for TileMapData {
+1 -1
View File
@@ -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)]
#[derive(Clone, Copy, Debug, PartialEq, Reflect)]
pub enum ResourceTilePosition {
/// This position refers to some page, and so it lacks tile coordinates.
Page(Vector2<i32>),
@@ -194,6 +194,10 @@ impl ResourceData for CustomTileCollider {
fn can_be_saved(&self) -> bool {
false
}
fn try_clone_box(&self) -> Option<Box<dyn ResourceData>> {
Some(Box::new(self.clone()))
}
}
impl OrthoTransform for CustomTileCollider {
+5 -5
View File
@@ -57,22 +57,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>(FxHashMap<Vector2<i32>, V>);
pub struct TileGridMap<V: Debug + Clone>(FxHashMap<Vector2<i32>, V>);
impl<V: Visit + Default + Debug> Visit for TileGridMap<V> {
impl<V: Visit + Default + Debug + Clone> Visit for TileGridMap<V> {
fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
self.0.visit(name, visitor)
}
}
impl<V: Debug> Deref for TileGridMap<V> {
impl<V: Debug + Clone> Deref for TileGridMap<V> {
type Target = FxHashMap<Vector2<i32>, V>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<V: Debug> DerefMut for TileGridMap<V> {
impl<V: Debug + Clone> DerefMut for TileGridMap<V> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
@@ -381,7 +381,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)]
#[derive(Clone, Debug, Reflect)]
pub struct StampElement {
/// The stamp cell's tile handle
pub handle: TileDefinitionHandle,
+4
View File
@@ -2118,6 +2118,10 @@ impl ResourceData for TileSet {
fn can_be_saved(&self) -> bool {
true
}
fn try_clone_box(&self) -> Option<Box<dyn ResourceData>> {
Some(Box::new(self.clone()))
}
}
/// An alias for `Resource<TileSet>`.
+1 -1
View File
@@ -585,7 +585,7 @@ impl TileSetUpdate {
/// A stamp element plus the transformation of the [`Stamp`] where the element is taken from,
/// allowing the stamp element itself to be later transformed before it is applied to a tile map,
/// tile set, or brush.
#[derive(Debug, Clone)]
#[derive(Debug, Clone, Reflect)]
pub struct RotTileHandle {
/// The transformation of the element.
pub transform: OrthoTransformation,
+5
View File
@@ -334,6 +334,7 @@ pub struct ScriptContext<'a, 'b, 'c> {
/// # };
/// #
/// #[derive(Visit, Reflect, Default, Debug)]
/// #[reflect(non_cloneable)]
/// struct Game {
/// player_name: String,
/// }
@@ -751,6 +752,10 @@ impl Reflect for Script {
fn as_list_mut(&mut self, func: &mut dyn FnMut(Option<&mut dyn ReflectList>)) {
self.instance.deref_mut().as_list_mut(func)
}
fn try_clone_box(&self) -> Option<Box<dyn Reflect>> {
Some(Box::new(self.clone()))
}
}
impl Deref for Script {
+1 -1
View File
@@ -126,7 +126,7 @@ where
#[derive(Debug, PartialEq, Visit, Clone)]
pub struct BehaviorTree<B>
where
B: Clone,
B: Clone + 'static,
{
nodes: Pool<BehaviorNode<B>>,
root: Handle<BehaviorNode<B>>,
+1 -1
View File
@@ -14,7 +14,7 @@ repository = "https://github.com/FyroxEngine/Fyrox"
rust-version = "1.86"
[dependencies]
rectutils = "0.3.0"
rectutils = "0.4.0"
nalgebra = { version = "0.33", features = ["bytemuck"] }
arrayvec = "0.7.4"
num-traits = "0.2.18"
+5 -1
View File
@@ -93,7 +93,7 @@ pub struct UntypedBuiltInResource {
/// };
/// use std::{error::Error, path::Path};
///
/// #[derive(TypeUuidProvider, Default, Debug, Visit, Reflect)]
/// #[derive(TypeUuidProvider, Default, Debug, Clone, Visit, Reflect)]
/// #[type_uuid(id = "00d036bb-fbed-47f7-94e3-b3fce93dee17")]
/// struct MyResource {
/// some_data: String,
@@ -111,6 +111,10 @@ pub struct UntypedBuiltInResource {
/// fn can_be_saved(&self) -> bool {
/// false
/// }
///
/// fn try_clone_box(&self) -> Option<Box<dyn ResourceData>> {
/// Some(Box::new(self.clone()))
/// }
/// }
///
/// fn register_built_in_resource(resource_manager: &ResourceManager) {
+5 -1
View File
@@ -112,7 +112,7 @@ mod test {
use super::*;
#[derive(Debug, Default, Reflect, Visit)]
#[derive(Debug, Default, Clone, Reflect, Visit)]
struct Stub {}
impl ResourceData for Stub {
@@ -127,6 +127,10 @@ mod test {
fn can_be_saved(&self) -> bool {
false
}
fn try_clone_box(&self) -> Option<Box<dyn ResourceData>> {
Some(Box::new(self.clone()))
}
}
impl TypeUuidProvider for Stub {
+11 -9
View File
@@ -96,6 +96,10 @@ pub trait ResourceData: Debug + Visit + Send + Reflect {
/// resource type supports saving, for example there might be temporary resource type that is
/// used only at runtime which does not need saving at all.
fn can_be_saved(&self) -> bool;
/// Tries to clone the resource data. This method can return `None` if the underlying type is
/// non-cloneable.
fn try_clone_box(&self) -> Option<Box<dyn ResourceData>>;
}
/// Extension trait for a resource data of a particular type, which adds additional functionality,
@@ -159,10 +163,7 @@ where
///
/// Default state of the resource will be [`ResourceState::Ok`] with `T::default`.
#[derive(Debug, Reflect)]
pub struct Resource<T>
where
T: TypedResourceData,
{
pub struct Resource<T: Debug> {
untyped: UntypedResource,
#[reflect(hidden)]
phantom: PhantomData<T>,
@@ -409,10 +410,7 @@ where
}
}
impl<T> Clone for Resource<T>
where
T: TypedResourceData,
{
impl<T: Debug> Clone for Resource<T> {
#[inline]
fn clone(&self) -> Self {
Self {
@@ -696,7 +694,7 @@ mod tests {
sync::Arc,
};
#[derive(Serialize, Deserialize, Default, Debug, Visit, Reflect, TypeUuidProvider)]
#[derive(Serialize, Deserialize, Default, Debug, Clone, Visit, Reflect, TypeUuidProvider)]
#[type_uuid(id = "241d14c7-079e-4395-a63c-364f0fc3e6ea")]
struct MyData {
data: u32,
@@ -741,6 +739,10 @@ mod tests {
fn can_be_saved(&self) -> bool {
true
}
fn try_clone_box(&self) -> Option<Box<dyn ResourceData>> {
Some(Box::new(self.clone()))
}
}
struct MyDataLoader {}
+7 -2
View File
@@ -22,6 +22,7 @@
//! docs for more info.
pub use crate::builtin::*;
use crate::state::ResourceDataWrapper;
use crate::{
constructor::ResourceConstructorContainer,
core::{
@@ -737,7 +738,7 @@ impl ResourceManagerState {
assert!(mutex_guard.kind.is_external());
mutex_guard.state.commit(ResourceState::Ok {
data,
data: ResourceDataWrapper(data),
resource_uuid,
});
@@ -947,7 +948,7 @@ mod test {
};
use std::{error::Error, fs::File, time::Duration};
#[derive(Debug, Default, Reflect, Visit)]
#[derive(Debug, Default, Clone, Reflect, Visit)]
struct Stub {}
impl TypeUuidProvider for Stub {
@@ -968,6 +969,10 @@ mod test {
fn can_be_saved(&self) -> bool {
false
}
fn try_clone_box(&self) -> Option<Box<dyn ResourceData>> {
Some(Box::new(self.clone()))
}
}
impl ResourceLoader for Stub {
+175 -7
View File
@@ -26,7 +26,9 @@ use crate::{
manager::ResourceManager,
ResourceData, ResourceLoadError,
};
use fyrox_core::reflect::ReflectHandle;
use fyrox_core::warn;
use std::any::{Any, TypeId};
use std::path::PathBuf;
use std::{
ops::{Deref, DerefMut},
@@ -75,6 +77,168 @@ impl LoadError {
}
}
#[doc(hidden)]
#[derive(Debug)]
pub struct ResourceDataWrapper(pub Box<dyn ResourceData>);
impl Reflect for ResourceDataWrapper {
fn source_path() -> &'static str
where
Self: Sized,
{
file!()
}
fn derived_types() -> &'static [TypeId]
where
Self: Sized,
{
&[]
}
fn try_clone_box(&self) -> Option<Box<dyn Reflect>> {
Reflect::try_clone_box(&*self.0)
}
fn query_derived_types(&self) -> &'static [TypeId] {
self.deref().query_derived_types()
}
fn type_name(&self) -> &'static str {
self.deref().type_name()
}
fn doc(&self) -> &'static str {
self.deref().doc()
}
fn fields_ref(&self, func: &mut dyn FnMut(&[FieldRef])) {
self.deref().fields_ref(func)
}
fn fields_mut(&mut self, func: &mut dyn FnMut(&mut [FieldMut])) {
self.deref_mut().fields_mut(func)
}
fn into_any(self: Box<Self>) -> Box<dyn Any> {
self
}
fn as_any(&self, func: &mut dyn FnMut(&dyn Any)) {
self.deref().as_any(func)
}
fn as_any_mut(&mut self, func: &mut dyn FnMut(&mut dyn Any)) {
self.deref_mut().as_any_mut(func)
}
fn as_reflect(&self, func: &mut dyn FnMut(&dyn Reflect)) {
self.deref().as_reflect(func)
}
fn as_reflect_mut(&mut self, func: &mut dyn FnMut(&mut dyn Reflect)) {
self.deref_mut().as_reflect_mut(func)
}
fn set(&mut self, value: Box<dyn Reflect>) -> Result<Box<dyn Reflect>, Box<dyn Reflect>> {
self.deref_mut().set(value)
}
fn assembly_name(&self) -> &'static str {
env!("CARGO_PKG_NAME")
}
fn type_assembly_name() -> &'static str
where
Self: Sized,
{
env!("CARGO_PKG_NAME")
}
fn set_field(
&mut self,
field: &str,
value: Box<dyn Reflect>,
func: &mut dyn FnMut(Result<Box<dyn Reflect>, Box<dyn Reflect>>),
) {
self.deref_mut().set_field(field, value, func)
}
fn field(&self, name: &str, func: &mut dyn FnMut(Option<&dyn Reflect>)) {
self.deref().field(name, func)
}
fn field_mut(&mut self, name: &str, func: &mut dyn FnMut(Option<&mut dyn Reflect>)) {
self.deref_mut().field_mut(name, func)
}
fn as_array(&self, func: &mut dyn FnMut(Option<&dyn ReflectArray>)) {
self.deref().as_array(func)
}
fn as_array_mut(&mut self, func: &mut dyn FnMut(Option<&mut dyn ReflectArray>)) {
self.deref_mut().as_array_mut(func)
}
fn as_list(&self, func: &mut dyn FnMut(Option<&dyn ReflectList>)) {
self.deref().as_list(func)
}
fn as_list_mut(&mut self, func: &mut dyn FnMut(Option<&mut dyn ReflectList>)) {
self.deref_mut().as_list_mut(func)
}
fn as_inheritable_variable(
&self,
func: &mut dyn FnMut(Option<&dyn ReflectInheritableVariable>),
) {
self.deref().as_inheritable_variable(func)
}
fn as_inheritable_variable_mut(
&mut self,
func: &mut dyn FnMut(Option<&mut dyn ReflectInheritableVariable>),
) {
self.deref_mut().as_inheritable_variable_mut(func)
}
fn as_hash_map(&self, func: &mut dyn FnMut(Option<&dyn ReflectHashMap>)) {
self.deref().as_hash_map(func)
}
fn as_hash_map_mut(&mut self, func: &mut dyn FnMut(Option<&mut dyn ReflectHashMap>)) {
self.deref_mut().as_hash_map_mut(func)
}
fn as_handle(&self, func: &mut dyn FnMut(Option<&dyn ReflectHandle>)) {
self.deref().as_handle(func)
}
fn as_handle_mut(&mut self, func: &mut dyn FnMut(Option<&mut dyn ReflectHandle>)) {
self.deref_mut().as_handle_mut(func)
}
}
impl Deref for ResourceDataWrapper {
type Target = dyn ResourceData;
fn deref(&self) -> &Self::Target {
&*self.0
}
}
impl DerefMut for ResourceDataWrapper {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut *self.0
}
}
impl Clone for ResourceDataWrapper {
fn clone(&self) -> Self {
Self(ResourceData::try_clone_box(&*self.0).unwrap())
}
}
/// Resource could be in three possible states (a small state machine):
///
/// 1. Pending - it is loading or queued for loading.
@@ -101,7 +265,7 @@ impl LoadError {
/// to get the UUID earlier: the UUID is stored in a metadata file which exists only if the resource
/// is present. It is somewhat possible to get a UUID when a resource is failed to load, but not in
/// 100% cases.
#[derive(Debug, Reflect)]
#[derive(Debug, Clone, Reflect)]
pub enum ResourceState {
/// Resource is loading from external resource or in the queue to load.
Pending {
@@ -127,7 +291,7 @@ pub enum ResourceState {
/// Unique id of the resource.
resource_uuid: Uuid,
/// Actual data of the resource.
data: Box<dyn ResourceData>,
data: ResourceDataWrapper,
},
}
@@ -185,7 +349,7 @@ impl ResourceState {
*self = Self::Ok {
resource_uuid,
data: instance,
data: ResourceDataWrapper(instance),
};
} else {
return Err(VisitError::User(format!(
@@ -235,7 +399,7 @@ impl ResourceState {
pub fn new_ok<T: ResourceData>(resource_uuid: Uuid, data: T) -> Self {
Self::Ok {
resource_uuid,
data: Box::new(data),
data: ResourceDataWrapper(Box::new(data)),
}
}
@@ -244,7 +408,7 @@ impl ResourceState {
pub fn new_ok_untyped(resource_uuid: Uuid, data: Box<dyn ResourceData>) -> Self {
Self::Ok {
resource_uuid,
data,
data: ResourceDataWrapper(data),
}
}
@@ -294,7 +458,7 @@ impl ResourceState {
pub fn commit_ok<T: ResourceData>(&mut self, resource_uuid: Uuid, data: T) {
self.commit(ResourceState::Ok {
resource_uuid,
data: Box::new(data),
data: ResourceDataWrapper(Box::new(data)),
})
}
@@ -318,7 +482,7 @@ mod test {
use super::*;
#[derive(Debug, Default, Reflect, Visit)]
#[derive(Debug, Default, Clone, Reflect, Visit)]
struct Stub {}
impl ResourceData for Stub {
@@ -333,6 +497,10 @@ mod test {
fn can_be_saved(&self) -> bool {
false
}
fn try_clone_box(&self) -> Option<Box<dyn ResourceData>> {
Some(Box::new(self.clone()))
}
}
impl TypeUuidProvider for Stub {
+8 -3
View File
@@ -20,6 +20,7 @@
//! A module for untyped resources. See [`UntypedResource`] docs for more info.
use crate::state::ResourceDataWrapper;
use crate::{
core::{
math::curve::Curve, parking_lot::Mutex, reflect::prelude::*, uuid, uuid::Uuid,
@@ -154,7 +155,7 @@ impl Display for ResourceKind {
/// Header of a resource, it contains a common data about the resource, such as its data type uuid,
/// its kind, etc.
#[derive(Reflect, Debug)]
#[derive(Reflect, Clone, Debug)]
pub struct ResourceHeader {
/// Kind of the resource. See [`ResourceKind`] for more info.
pub kind: ResourceKind,
@@ -214,7 +215,7 @@ impl Visit for ResourceHeader {
instance.visit("Details", &mut region)?;
self.state = ResourceState::Ok {
data: instance,
data: ResourceDataWrapper(instance),
// The old format does not contain an uuid.
resource_uuid: Uuid::nil(),
};
@@ -609,6 +610,10 @@ mod test {
fn can_be_saved(&self) -> bool {
false
}
fn try_clone_box(&self) -> Option<Box<dyn ResourceData>> {
Some(Box::new(*self))
}
}
impl TypeUuidProvider for Stub {
@@ -660,7 +665,7 @@ mod test {
let mut r = UntypedResource(Arc::new(Mutex::new(ResourceHeader {
kind: ResourceKind::External,
state: ResourceState::Ok {
data: Box::new(stub),
data: ResourceDataWrapper(Box::new(stub)),
resource_uuid: Uuid::new_v4(),
},
old_format_path: None,
+1
View File
@@ -36,6 +36,7 @@ pub mod camera;
/// # };
/// #
/// # #[derive(Visit, Reflect, Debug)]
/// # #[reflect(non_cloneable)]
/// # struct Game;
/// #
/// # impl Plugin for Game {
+2 -2
View File
@@ -51,7 +51,7 @@ use std::time::Duration;
use super::SoundBufferResourceLoadError;
/// Samples container.
#[derive(Debug, Default, Visit, Reflect)]
#[derive(Debug, Default, Visit, Clone, Reflect)]
pub struct Samples(pub Vec<f32>);
impl Deref for Samples {
@@ -69,7 +69,7 @@ impl DerefMut for Samples {
}
/// Generic sound buffer that contains decoded samples and allows random access.
#[derive(Debug, Default, Visit, Reflect)]
#[derive(Debug, Clone, Default, Visit, Reflect)]
pub struct GenericBuffer {
/// Interleaved decoded samples (mono sounds: L..., stereo sounds: LR...)
/// For streaming buffers it contains only small part of decoded data
+5
View File
@@ -239,6 +239,7 @@ impl std::error::Error for SoundBufferResourceLoadError {}
/// Sound buffer is a data source for sound sources. See module documentation for more info.
#[derive(Debug, Visit, Reflect)]
#[reflect(non_cloneable)]
pub enum SoundBuffer {
/// General-purpose buffer, usually contains all the data and allows random
/// access to samples. It is also used to make streaming buffer via composition.
@@ -357,4 +358,8 @@ impl ResourceData for SoundBuffer {
fn can_be_saved(&self) -> bool {
false
}
fn try_clone_box(&self) -> Option<Box<dyn ResourceData>> {
None
}
}
+1
View File
@@ -61,6 +61,7 @@ use std::{
/// Streaming buffer for long sounds. Does not support random access.
#[derive(Debug, Default, Visit, Reflect)]
#[reflect(non_cloneable)]
pub struct StreamingBuffer {
pub(crate) generic: GenericBuffer,
/// Count of sources that share this buffer, it is important to keep only one
+5 -1
View File
@@ -203,7 +203,7 @@ impl HrtfRenderer {
/// Wrapper for [`HrirSphere`] to be able to use it in the resource manager, that will handle async resource
/// loading automatically.
#[derive(Reflect, Default, Visit)]
#[derive(Reflect, Default, Clone, Visit)]
pub struct HrirSphereResourceData {
#[reflect(hidden)]
#[visit(skip)]
@@ -234,6 +234,10 @@ impl ResourceData for HrirSphereResourceData {
fn can_be_saved(&self) -> bool {
false
}
fn try_clone_box(&self) -> Option<Box<dyn ResourceData>> {
Some(Box::new(self.clone()))
}
}
/// Resource loader for [`HrirSphereResource`].
+4
View File
@@ -345,6 +345,10 @@ impl ResourceData for Texture {
fn can_be_saved(&self) -> bool {
true
}
fn try_clone_box(&self) -> Option<Box<dyn ResourceData>> {
Some(Box::new(self.clone()))
}
}
impl Visit for Texture {
+8 -3
View File
@@ -43,7 +43,7 @@ use std::{
pub mod loader;
#[derive(Debug)]
#[derive(Debug, Clone)]
pub struct FontGlyph {
pub bitmap_top: f32,
pub bitmap_left: f32,
@@ -56,6 +56,7 @@ pub struct FontGlyph {
}
/// Page is a storage for rasterized glyphs.
#[derive(Clone)]
pub struct Page {
pub pixels: Vec<u8>,
pub texture: Option<UntypedResource>,
@@ -75,7 +76,7 @@ impl Debug for Page {
/// Atlas is a storage for glyphs of a particular size, each atlas could have any number of pages to
/// store the rasterized glyphs.
#[derive(Default, Debug)]
#[derive(Default, Clone, Debug)]
pub struct Atlas {
pub glyphs: Vec<FontGlyph>,
pub char_map: FxHashMap<char, usize>,
@@ -210,7 +211,7 @@ impl Atlas {
}
}
#[derive(Default, Debug, Reflect, Visit)]
#[derive(Default, Clone, Debug, Reflect, Visit)]
#[reflect(hide_all)]
pub struct Font {
#[visit(skip)]
@@ -235,6 +236,10 @@ impl ResourceData for Font {
fn can_be_saved(&self) -> bool {
false
}
fn try_clone_box(&self) -> Option<Box<dyn ResourceData>> {
Some(Box::new(self.clone()))
}
}
#[derive(Copy, Clone, Default, Debug)]
+8 -2
View File
@@ -795,7 +795,7 @@ impl PropertyEditorDefinitionContainer {
pub fn register_inheritable_styleable_inspectable<T>(&self)
where
T: Reflect + FieldValue,
T: Reflect + FieldValue + Clone + PartialEq,
{
assert!(self
.insert(InspectablePropertyEditorDefinition::<T>::new())
@@ -829,7 +829,13 @@ impl PropertyEditorDefinitionContainer {
pub fn register_inheritable_styleable_enum<T, E: Debug>(&self)
where
T: InspectableEnum + FieldValue + VariantNames + AsRef<str> + FromStr<Err = E> + Debug,
T: InspectableEnum
+ FieldValue
+ VariantNames
+ AsRef<str>
+ FromStr<Err = E>
+ Debug
+ PartialEq,
{
assert!(self
.insert(EnumPropertyEditorDefinition::<T>::new())
+5 -1
View File
@@ -338,7 +338,7 @@ use fyrox_core::pool::{BorrowAs, ErasedHandle};
use fyrox_resource::untyped::ResourceKind;
pub use fyrox_texture as texture;
#[derive(Default, Reflect, Debug)]
#[derive(Default, Clone, Reflect, Debug)]
pub(crate) struct RcUiNodeHandleInner {
handle: Handle<UiNode>,
#[reflect(hidden)]
@@ -3548,6 +3548,10 @@ impl ResourceData for UserInterface {
fn can_be_saved(&self) -> bool {
true
}
fn try_clone_box(&self) -> Option<Box<dyn ResourceData>> {
Some(Box::new(self.clone()))
}
}
pub mod test {
+1 -1
View File
@@ -35,7 +35,7 @@ use fyrox_core::visitor::error::VisitError;
/// A wrapper for widget pool record that allows to define custom visit method to have full
/// control over instantiation process at deserialization.
#[derive(Debug, Default, Reflect)]
#[derive(Debug, Clone, Default, Reflect)]
pub struct WidgetContainer(Option<UiNode>);
fn read_widget(name: &str, visitor: &mut Visitor) -> Result<UiNode, VisitError> {
+4
View File
@@ -355,4 +355,8 @@ impl Reflect for UiNode {
fn field_mut(&mut self, name: &str, func: &mut dyn FnMut(Option<&mut dyn Reflect>)) {
self.0.deref_mut().field_mut(name, func)
}
fn try_clone_box(&self) -> Option<Box<dyn Reflect>> {
Some(Box::new(self.clone()))
}
}
+3 -2
View File
@@ -118,7 +118,8 @@ lazy_static! {
/// the style and why do we need to store the value as well? The answer is flexibility. In this
/// approach style becomes not necessary and the value can be hardcoded. Also, the values of such
/// properties can be updated individually.
#[derive(Clone, Debug, Default, Reflect)]
#[derive(Clone, Debug, Reflect, Default)]
#[reflect(bounds = "T: Reflect + Clone")]
pub struct StyledProperty<T> {
/// Property value.
pub property: T,
@@ -252,7 +253,7 @@ impl<T: Visit> Visit for StyledProperty<T> {
/// ui.set_style(StyleResource::new_embedded(style));
/// }
/// ```
#[derive(Visit, Reflect, Default, Debug, TypeUuidProvider)]
#[derive(Visit, Reflect, Clone, Default, Debug, TypeUuidProvider)]
#[type_uuid(id = "38a63b49-d765-4c01-8fb5-202cc43d607e")]
pub struct Style {
parent: Option<StyleResource>,
+4
View File
@@ -96,6 +96,10 @@ impl ResourceData for Style {
fn can_be_saved(&self) -> bool {
true
}
fn try_clone_box(&self) -> Option<Box<dyn ResourceData>> {
Some(Box::new(self.clone()))
}
}
/// A loader for style resource.
+2 -2
View File
@@ -91,7 +91,7 @@ pub static DATA_DIR: LazyLock<PathBuf> = LazyLock::new(|| {
data_dir
});
#[derive(Default, Serialize, Deserialize, Reflect, Debug)]
#[derive(Default, Serialize, Deserialize, Reflect, Clone, Debug)]
pub struct SettingsData {
#[serde(default = "default_open_ide_command")]
#[reflect(
@@ -203,7 +203,7 @@ impl Settings {
}
}
#[derive(Serialize, Deserialize, Debug)]
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct Project {
pub manifest_path: PathBuf,
pub name: String,