Latest commit 46c1480

use bevy::prelude::*;

/// 创建父实体和子实体的层次
fn main() {
    App::new()
        .add_plugin(DefaultPlugin)
        .add_startup_system(初始设置)
        .add_system(旋转)
        .run();
}

fn 初始设置(
    mut commands: Commands,
    asset_server: Res<AssetServer>,
) {
    commands.spawn_bundle(OrthographicCameraBundle::new_2d());
    let image_handle = asset_server.load("icon.png");

    // 生成一个无父实体的根实体
    let parent = commands
        .spawn_bundle(SpriteBundle {
            transform: Transform::from_scale(Vec3::splat(0.75)),
            texture: image_handle.clone(),
            ..Default::default()
        })
        // 把该实体作为父实体,运行lambda来生成它的子实体
        .with_children(|child_builder| {
            // 父实体是一个ChildBuilder,有一个类似Commands的API
            child_builder.spawn_bundle(SpriteBundle {
                transform: Transform {
                    translation: Vec3::new(250.0, 0.0, 0.0),
                    scale: Vec3::splat(0.75),
                    ..Default::default()
                },
                texture: image_handle.clone(),
                sprite: Sprite {
                    color: Color::BLUE,
                    ..Default::default()
                }
                ..Default::default()
            });
        })
        // 存储父实体,下面会用到
        .id();

    // 另一种创建层次结构的方法是在实体中添加一个Parent组件,Paren组件会通过其他方法自动添加到父组件中
    // 同理,添加一个Parent组件会自动给父实体添加一个Children组件
    commands
        .spawn_bundle(SpriteBundle {
            transform: Transform {
                translation: Vec3::new(-250.0, 0.0, 0.0),
                scale: Vec3::splat(0.75),
                ..Default::default()
            },
            texture: image_handle.clone(),
            sprite: Sprite {
                color: Color::RED,
                ..Default::default()
            }
            ..Default::default()
        })
        // 使用的是上面存储的父实体
        .insert(Parent(parent));

    // 另一种方法是在生成父实体之后,用push_children函数添加实体
    let child = commands
        .spawn_bundle(SpriteBundle {
            transform: Transform {
                translation: Vec3::new(0.0, 250.0, 0.0),
                scale: Vec3::splat(0.75),
                ..Default::default()
            },
            texture: image_handle,
            sprite: Sprite {
                color: Color::GREEN,
                ..Default::default()
            }
            ..Default::default()
        })
        .id();

    // 用子实体的切片来推送
    commands.entity(parent).push_children(&[child]);
}

// 这个系统用来旋转根实体,并分别旋转所有子代实体
fn 旋转(
    mut commands: Commands,
    time: Res<Time>,
    mut parents_query: Query<(Entity, &Children), With<Sprite>>,
    mut transform_query: Query<&mut Transform, With<Sprite>>,
) {
    let angle = std::f32::consts::TAU / 4.0;
    for (parent, children) in parents_query.iter_mut() {
        if let Ok(mut transform) = transform_query.get_mut(parent) {
            transform.rotate(Quat::from_rotation_z(-angle * time.delta_seconds()));
        }

        // 要遍历实体的子代,只需把Children组件视为一个Vec,或者,可以查询带有Parent组件的实体
        for child in children.iter() {
            if let Ok(mut transform) = transform_query.get_mut(*child) {
                transform.rotate(Quat::from_rotation_z(angle * 2.0 * time.delta_seconds()));
            }
        }

        // 为了演示删除子实体,下面的代码会在几秒钟后删除子实体
        if time.seconds_since_startup() >= 2.0 && children.len() == 3 {
            let child = children.last().copied().unwrap();
            commands.entity(child).despawn_recursive();
        }

        if time.seconds_since_startup() >= 4.0 {
            // 这会把实体从其父实体的子代列表中移除,并取消该实体拥有的所有子实体
            commands.entity(parent).despawn_recursive();
        }
    }
}