Skip to content

Commit f2f2b0a

Browse files
feat(bevy): Upgrade to bevy 0.14.0 (#101)
1 parent 128f55e commit f2f2b0a

File tree

4 files changed

+85
-30
lines changed

4 files changed

+85
-30
lines changed

Cargo.toml

+2-3
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,12 @@ homepage = "https://github.com/zkat/big-brain"
1515
[workspace]
1616

1717
[dependencies]
18-
bevy = { version = "0.13.2", default-features = false }
18+
bevy = { version = "0.14.0", default-features = false }
1919
big-brain-derive = { version = "=0.19.0", path = "./derive" }
2020

2121
[dev-dependencies]
22-
bevy = { version = "0.13.2", default-features = true }
22+
bevy = { version = "0.14.0", default-features = true }
2323
rand = { version = "0.8.5", features = ["small_rng"] }
24-
bevy-scene-hook = "10.0.0"
2524

2625
[features]
2726
trace = []

examples/farming_sim.rs

+78-25
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@
66
//! - When not tired, find the farm field and harvest items over time
77
//! - When inventory is full, find the market and sell items for money
88
9-
use bevy::{log::LogPlugin, prelude::*};
10-
use bevy_scene_hook::{HookPlugin, HookedSceneBundle, SceneHook};
9+
use bevy::scene::SceneInstance;
10+
use bevy::{color::palettes::css, log::LogPlugin, prelude::*};
1111
use big_brain::prelude::*;
1212
use big_brain_derive::ActionBuilder;
1313

14-
const DEFAULT_COLOR: Color = Color::BLACK;
15-
const SLEEP_COLOR: Color = Color::RED;
16-
const FARM_COLOR: Color = Color::BLUE;
14+
const DEFAULT_COLOR: Color = Color::Srgba(css::BLACK);
15+
const SLEEP_COLOR: Color = Color::Srgba(css::RED);
16+
const FARM_COLOR: Color = Color::Srgba(css::BLUE);
1717
const MAX_DISTANCE: f32 = 0.1;
1818
const MAX_INVENTORY_ITEMS: f32 = 20.0;
1919
const WORK_NEED_SCORE: f32 = 0.6;
@@ -386,8 +386,10 @@ pub fn move_to_nearest_system<T: Component + std::fmt::Debug + Clone>(
386386
let delta_b = *b - actor_transform.translation;
387387
delta_a.length().partial_cmp(&delta_b.length()).unwrap()
388388
})
389-
.unwrap()
390-
.1;
389+
.and_then(|t| Some(t.1));
390+
let Some(goal_transform) = goal_transform else {
391+
continue;
392+
};
391393
let delta = goal_transform.translation - actor_transform.translation;
392394
let distance = delta.xz().length();
393395

@@ -498,24 +500,13 @@ fn init_entities(
498500
},
499501
));
500502

501-
// We use a HookedSceneBundle to attach a SceneHook to the entity. This hook
502-
// will be called when the entity is spawned, and will allow us to insert
503-
// additional components into the spawned entities.
503+
// Loading our scene here. Note we'll still need to add components to different parts
504+
// of the gltf in order to query their positions. We do this through an observer further below.
504505
commands.spawn((
505506
Name::new("Town"),
506-
HookedSceneBundle {
507-
scene: SceneBundle {
508-
scene: asset_server.load("models/town.glb#Scene0"),
509-
..default()
510-
},
511-
hook: SceneHook::new(|entity, cmds| {
512-
match entity.get::<Name>().map(|t| t.as_str()) {
513-
Some("Farm_Marker") => cmds.insert(Field),
514-
Some("Market_Marker") => cmds.insert(Market),
515-
Some("House_Marker") => cmds.insert(House),
516-
_ => cmds,
517-
};
518-
}),
507+
SceneBundle {
508+
scene: asset_server.load("models/town.glb#Scene0"),
509+
..default()
519510
},
520511
));
521512

@@ -601,16 +592,78 @@ fn init_entities(
601592
});
602593
}
603594

595+
// ================================================================================
596+
// Scene Loading 🏗️
597+
// ================================================================================
598+
599+
// Define a custom event for our scene loading
600+
#[derive(Event)]
601+
struct SceneLoaded {
602+
/// The entities in this scene
603+
entities: Vec<Entity>,
604+
}
605+
606+
// Define a marker component to indicate what entities we've already processed
607+
#[derive(Component)]
608+
struct SceneProcessed;
609+
610+
// System to check if a scene has finished loading
611+
fn check_scene_loaded(
612+
mut commands: Commands,
613+
query: Query<(Entity, &SceneInstance), Without<SceneProcessed>>,
614+
scene_spawner: Res<SceneSpawner>,
615+
) {
616+
for (entity, instance) in query.iter() {
617+
if scene_spawner.instance_is_ready(**instance) {
618+
commands.entity(entity).insert(SceneProcessed);
619+
620+
let entities = scene_spawner
621+
.iter_instance_entities(**instance)
622+
.chain(std::iter::once(entity));
623+
624+
commands.trigger(SceneLoaded {
625+
entities: entities.collect(),
626+
});
627+
}
628+
}
629+
}
630+
604631
fn main() {
605632
App::new()
606633
.add_plugins(DefaultPlugins.set(LogPlugin {
607634
level: bevy::log::Level::WARN,
608635
// Use `RUST_LOG=big_brain=trace,farming_sim=trace cargo run --example
609636
// farming_sim --features=trace` to see extra tracing output.
610637
filter: "big_brain=debug,farming_sim=debug".to_string(),
611-
update_subscriber: None,
638+
custom_layer: |_| None,
612639
}))
613-
.add_plugins(HookPlugin)
640+
.add_event::<SceneLoaded>()
641+
.add_systems(Update, check_scene_loaded)
642+
// This observer will attach components to entities in the scene based on their names.
643+
.observe(
644+
|trigger: Trigger<SceneLoaded>,
645+
query: Query<(Entity, &Name)>,
646+
mut commands: Commands| {
647+
for entity in trigger.event().entities.iter() {
648+
if let Ok((entity, name)) = query.get(*entity) {
649+
let mut entity_commands = commands.entity(entity);
650+
651+
match name.as_str() {
652+
"Farm_Marker" => {
653+
entity_commands.insert(Field);
654+
}
655+
"Market_Marker" => {
656+
entity_commands.insert(Market);
657+
}
658+
"House_Marker" => {
659+
entity_commands.insert(House);
660+
}
661+
_ => (),
662+
}
663+
}
664+
}
665+
},
666+
)
614667
.add_plugins(BigBrainPlugin::new(PreUpdate))
615668
.add_systems(Startup, init_entities)
616669
.add_systems(Update, (fatigue_system, update_ui))

src/lib.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,10 @@ pub mod prelude {
202202
};
203203
}
204204

205-
use bevy::{ecs::schedule::ScheduleLabel, prelude::*, utils::intern::Interned};
205+
use bevy::{
206+
ecs::{intern::Interned, schedule::ScheduleLabel},
207+
prelude::*,
208+
};
206209

207210
/// Core [`Plugin`] for Big Brain behavior. Required for any of the
208211
/// [`Thinker`](thinker::Thinker)-related magic to work.

tests/steps.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ fn exit_action(
7070
*state = ActionState::Executing;
7171
}
7272
if *state == ActionState::Executing {
73-
app_exit_events.send(AppExit);
73+
app_exit_events.send(AppExit::Success);
7474
}
7575
}
7676
}

0 commit comments

Comments
 (0)