Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Scene Serialization dropping Sprite Component #3746

Open
mwbryant opened this issue Jan 22, 2022 · 6 comments
Open

Scene Serialization dropping Sprite Component #3746

mwbryant opened this issue Jan 22, 2022 · 6 comments
Labels
A-Scenes Serialized ECS data stored on the disk C-Bug An unexpected or incorrect behavior S-Needs-Investigation This issue requires detective work to figure out what's going wrong

Comments

@mwbryant
Copy link
Contributor

Bevy version

0.6.0

Operating system & version

Ubuntu 20.04

What you did

I tried to use the scene.rs example code to serialize and load a scene which had entities with the Sprite component. On load (after calling world.clear_entities) the Sprite component was missing off of the entity and the Image Handle was missing its reference.

What you expected to happen

Saving and loading the scene should result in no change

What actually happened

The sprite becomes invisible as its component is missing

Additional information

Here is a repo showing the bug (saving is mapped to P and loading is mapped to L on the keyboard), loading multiple times seems to make the image handle find the image on alternating loads.

https://github.com/mwbryant/weird_loading_bug

This also happens with TextureAtlasSprite and when using binary serialization techniques.

@mwbryant mwbryant added C-Bug An unexpected or incorrect behavior S-Needs-Triage This issue needs to be labelled labels Jan 22, 2022
@alice-i-cecile alice-i-cecile added A-Scenes Serialized ECS data stored on the disk S-Needs-Investigation This issue requires detective work to figure out what's going wrong and removed S-Needs-Triage This issue needs to be labelled labels Jan 23, 2022
@mneilly
Copy link

mneilly commented Mar 18, 2022

FWIW - I see in DynamicScene::from_world the loop over archtype components assigns None to reflect_component for sprites (at least in my scene) because the TypeRegistration data field is empty. As a result the sprite component is not pushed to the entity.

I.e. - this line sets reflect_component to None:

.and_then(|registration| registration.data::<ReflectComponent>());

@mneilly
Copy link

mneilly commented Mar 18, 2022

If I change sprite.rs as follows to add the #[reflect(Component)] attribute to the struct and the #[reflect(ignore)] attribute to custom_size it works for me:

use bevy_ecs::{component::Component, reflect::ReflectComponent};
use bevy_math::Vec2;
use bevy_reflect::{Reflect, TypeUuid};
use bevy_render::color::Color;

#[derive(Component, Debug, Default, Clone, TypeUuid, Reflect)]
#[reflect(Component)]
#[uuid = "7233c597-ccfa-411f-bd59-9af349432ada"]
#[repr(C)]
pub struct Sprite {
    /// The sprite's color tint
    pub color: Color,
    /// Flip the sprite along the X axis
    pub flip_x: bool,
    /// Flip the sprite along the Y axis
    pub flip_y: bool,
    /// An optional custom size for the sprite that will be used when rendering, instead of the size
    /// of the sprite's image
    #[reflect(ignore)]
    pub custom_size: Option<Vec2>,
}

Without ignoring custom_size, I get the following error:

WARN bevy_asset::asset_server: encountered an error while loading an asset: No registration found for core::option::Optionglam::vec2::Vec2

@youth95
Copy link

youth95 commented Jun 7, 2022

I had the same problem. but no need #[reflect(ignore)] in bevy 0.7.

Is it necessary to add #[reflect(Component)] to all components ?

@youth95
Copy link

youth95 commented Jun 7, 2022

I want use commands.spawn_scene(...). but some Internal component do not have #[reflect(Component, Default)] added.
Can I submit a PR for this?

#[derive(Component, Debug, Default)]
pub struct Clusters {
/// Tile size
pub(crate) tile_size: UVec2,
/// Number of clusters in x / y / z in the view frustum
pub(crate) dimensions: UVec3,
/// Distance to the far plane of the first depth slice. The first depth slice is special
/// and explicitly-configured to avoid having unnecessarily many slices close to the camera.
pub(crate) near: f32,
pub(crate) far: f32,
pub(crate) lights: Vec<VisiblePointLights>,
}

#[derive(Component)]
pub struct ExtractedPointLight {
color: Color,
/// luminous intensity in lumens per steradian
intensity: f32,
range: f32,
radius: f32,
transform: GlobalTransform,
shadows_enabled: bool,
shadow_depth_bias: f32,
shadow_normal_bias: f32,
}

#[derive(Component)]
pub struct ExtractedDirectionalLight {
color: Color,
illuminance: f32,
direction: Vec3,
projection: Mat4,
shadows_enabled: bool,
shadow_depth_bias: f32,
shadow_normal_bias: f32,
}

pub struct ExtractedClusterConfig {
/// Special near value for cluster calculations
near: f32,
far: f32,
/// Number of clusters in x / y / z in the view frustum
dimensions: UVec3,
}
#[derive(Component)]
pub struct ExtractedClustersPointLights {
data: Vec<VisiblePointLights>,
}

#[derive(Component)]
pub struct ShadowView {
pub depth_texture_view: TextureView,
pub pass_name: String,
}
#[derive(Component)]
pub struct ViewShadowBindings {
pub point_light_depth_texture: Texture,
pub point_light_depth_texture_view: TextureView,
pub directional_light_depth_texture: Texture,
pub directional_light_depth_texture_view: TextureView,
}
#[derive(Component)]
pub struct ViewLightEntities {
pub lights: Vec<Entity>,
}
#[derive(Component)]
pub struct ViewLightsUniformOffset {
pub offset: u32,
}

#[derive(Default)]
pub struct LightMeta {
pub view_gpu_lights: DynamicUniformBuffer<GpuLights>,
pub shadow_view_bind_group: Option<BindGroup>,
}
#[derive(Component)]
pub enum LightEntity {
Directional {
light_entity: Entity,
},
Point {
light_entity: Entity,
face_index: usize,
},
}

#[derive(Component)]
pub struct ViewClusterBindings {
n_indices: usize,
n_offsets: usize,
buffers: ViewClusterBuffers,
}

#[derive(Component, ShaderType, Clone)]
pub struct MeshUniform {
pub transform: Mat4,
pub inverse_transpose_model: Mat4,
pub flags: u32,
}

#[derive(Debug, Default)]
pub struct ExtractedJoints {
pub buffer: Vec<Mat4>,
}
#[derive(Component)]
pub struct SkinnedMeshJoints {
pub index: u32,
}

@zicklag
Copy link
Member

zicklag commented Jun 29, 2022

I just ran into the same thing. TextureAtlasSprite needs to derive Reflect and be registered on the app with app.register_type so I can spawn my scene with a sprite in it.

@paul-hansen
Copy link
Contributor

As a workaround, adding this to my app allowed me to save and load scenes with Sprites on Bevy 0.9.0:

app
    .register_type::<Cow<'static, str>>()
    .register_type::<Anchor>()
    .register_type::<Option<Rect>>()
    .register_type::<Option<Vec2>>()
    .register_type_data::<Option<Vec2>, ReflectSerialize>()
    .register_type_data::<Option<Vec2>, ReflectDeserialize>()
    .register_type_data::<Sprite, ReflectComponent>()
    .register_type::<Sprite>()

I think some of these have already been added on main but I know #[reflect(Component)] is still missing from Sprite.
#[reflect(Component)] can be added without modifying bevy using the .register_type_data::<Sprite, ReflectComponent>() from above in your own app.

I think before 0.9.0 this might have been held up by enum reflection being not fully supported. I would think a PR would be appreciated and should be fairly easy now if you still want to go for it. Would just need to add #[reflect(Component)] to Sprite and any of the other type registrations from above that are still needed to make this work on main. (Note I'm just another Bevy user, no one with authority)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Scenes Serialized ECS data stored on the disk C-Bug An unexpected or incorrect behavior S-Needs-Investigation This issue requires detective work to figure out what's going wrong
Projects
None yet
Development

No branches or pull requests

6 participants