single global observers root node (#25)

plus auto name observer macro `global_observer`
This commit is contained in:
extrawurst
2025-04-07 18:22:29 +02:00
committed by GitHub
parent 92da1587ba
commit ddc57ec1e8
17 changed files with 94 additions and 37 deletions

View File

@@ -1,7 +1,7 @@
use super::{Projectile, TriggerGun};
use crate::{
GameState, billboards::Billboard, loading_assets::GameAssets, physics_layers::GameLayer,
sounds::PlaySound, utils::sprite_3d_animation::AnimationTimer,
GameState, billboards::Billboard, global_observer, loading_assets::GameAssets,
physics_layers::GameLayer, sounds::PlaySound, utils::sprite_3d_animation::AnimationTimer,
};
use avian3d::prelude::{
Collider, CollisionLayers, CollisionStarted, LayerMask, PhysicsLayer, Sensor,
@@ -30,7 +30,8 @@ pub fn plugin(app: &mut App) {
Update,
(update, shot_collision, timeout).run_if(in_state(GameState::Playing)),
);
app.add_observer(on_trigger_state);
global_observer!(app, on_trigger_gun);
}
fn setup(mut commands: Commands, assets: Res<GameAssets>, mut sprite_params: Sprite3dParams) {
@@ -43,7 +44,7 @@ fn setup(mut commands: Commands, assets: Res<GameAssets>, mut sprite_params: Spr
});
}
fn on_trigger_state(
fn on_trigger_gun(
trigger: Trigger<TriggerGun>,
mut commands: Commands,
query_transform: Query<&Transform>,

View File

@@ -4,6 +4,7 @@ mod thrown;
use crate::{
GameState,
aim::AimTarget,
global_observer,
heads::ActiveHeads,
hitpoints::Hit,
physics_layers::GameLayer,
@@ -74,7 +75,7 @@ pub fn plugin(app: &mut App) {
app.add_systems(Update, enemy_hit.run_if(in_state(GameState::Playing)));
app.add_observer(on_trigger_state);
global_observer!(app, on_trigger_state);
}
fn enemy_hit(

View File

@@ -1,7 +1,12 @@
use super::TriggerThrow;
use crate::{
GameState, billboards::Billboard, hitpoints::Hit, loading_assets::GameAssets,
physics_layers::GameLayer, sounds::PlaySound, utils::sprite_3d_animation::AnimationTimer,
GameState,
billboards::Billboard,
hitpoints::Hit,
loading_assets::GameAssets,
physics_layers::GameLayer,
sounds::PlaySound,
utils::{global_observer, sprite_3d_animation::AnimationTimer},
};
use avian3d::prelude::*;
use bevy::{pbr::NotShadowCaster, prelude::*};
@@ -35,8 +40,9 @@ pub fn plugin(app: &mut App) {
app.add_systems(OnEnter(GameState::Playing), setup);
app.add_systems(Update, shot_collision.run_if(in_state(GameState::Playing)));
app.add_systems(FixedUpdate, update_auto_rotation);
app.add_observer(on_trigger_state);
app.add_observer(on_explosion);
global_observer!(app, on_trigger_thrown);
global_observer!(app, on_explosion);
}
fn on_explosion(
@@ -75,7 +81,7 @@ fn setup(mut commands: Commands, assets: Res<GameAssets>, mut sprite_params: Spr
});
}
fn on_trigger_state(
fn on_trigger_thrown(
trigger: Trigger<TriggerThrow>,
mut commands: Commands,
query_transform: Query<&Transform>,

View File

@@ -1,4 +1,4 @@
use crate::{GameState, loading_assets::UIAssets, utils::billboards::Billboard};
use crate::{GameState, global_observer, loading_assets::UIAssets, utils::billboards::Billboard};
use bevy::prelude::*;
use bevy_sprite3d::{Sprite3dBuilder, Sprite3dParams};
use ops::sin;
@@ -15,7 +15,7 @@ pub enum MarkerEvent {
pub fn plugin(app: &mut App) {
app.add_systems(Update, move_marker.run_if(in_state(GameState::Playing)));
app.add_observer(marker_event);
global_observer!(app, marker_event);
}
fn move_marker(mut query: Query<&mut Transform, With<TargetMarker>>, time: Res<Time>) {

View File

@@ -1,5 +1,7 @@
use super::{BackbackSwapEvent, Backpack, UiHeadState};
use crate::{GameState, heads::HeadsImages, loading_assets::UIAssets, sounds::PlaySound};
use crate::{
GameState, global_observer, heads::HeadsImages, loading_assets::UIAssets, sounds::PlaySound,
};
use bevy::prelude::*;
static HEAD_SLOTS: usize = 5;
@@ -51,7 +53,7 @@ pub fn plugin(app: &mut App) {
.run_if(in_state(GameState::Playing)),
);
app.add_observer(swap_head_inputs);
global_observer!(app, swap_head_inputs);
}
fn setup(mut commands: Commands, assets: Res<UIAssets>) {

View File

@@ -1,4 +1,4 @@
use crate::{GameState, loading_assets::UIAssets, sounds::PlaySound};
use crate::{GameState, global_observer, loading_assets::UIAssets, sounds::PlaySound};
use bevy::prelude::*;
#[derive(Component, Reflect, Default)]
@@ -25,10 +25,11 @@ pub fn plugin(app: &mut App) {
Update,
(rotate, update_ui).run_if(in_state(GameState::Playing)),
);
app.add_observer(on_collect);
global_observer!(app, on_cash_collect);
}
fn on_collect(
fn on_cash_collect(
_trigger: Trigger<CashCollectEvent>,
mut commands: Commands,
mut cash: ResMut<CashResource>,

View File

@@ -1,11 +1,11 @@
use crate::{
abilities::TriggerCashHeal, cash::CashResource, hitpoints::Hitpoints, player::Player,
sounds::PlaySound,
abilities::TriggerCashHeal, cash::CashResource, global_observer, hitpoints::Hitpoints,
player::Player, sounds::PlaySound,
};
use bevy::prelude::*;
pub fn plugin(app: &mut App) {
app.add_observer(on_heal_trigger);
global_observer!(app, on_heal_trigger);
}
fn on_heal_trigger(

View File

@@ -1,6 +1,7 @@
use crate::{
GameState,
camera::{CameraState, MainCamera},
global_observer,
tb_entities::{CameraTarget, CutsceneCamera, CutsceneCameraMovementEnd},
};
use bevy::prelude::*;
@@ -23,7 +24,8 @@ enum CutsceneState {
pub fn plugin(app: &mut App) {
app.init_resource::<CutsceneState>();
app.add_systems(Update, update.run_if(in_state(GameState::Playing)));
app.add_observer(on_start_cutscene);
global_observer!(app, on_start_cutscene);
}
fn on_start_cutscene(

View File

@@ -1,13 +1,14 @@
use crate::{
cutscene::StartCutscene, keys::KeyCollected, movables::TriggerMovableEvent, sounds::PlaySound,
cutscene::StartCutscene, global_observer, keys::KeyCollected, movables::TriggerMovableEvent,
sounds::PlaySound,
};
use bevy::{prelude::*, utils::hashbrown::HashSet};
pub fn plugin(app: &mut App) {
app.add_observer(on_key);
global_observer!(app, on_key_collected);
}
fn on_key(trigger: Trigger<KeyCollected>, mut commands: Commands) {
fn on_key_collected(trigger: Trigger<KeyCollected>, mut commands: Commands) {
match trigger.event().0.as_str() {
"fence_gate" => {
commands.trigger(StartCutscene("fence_01".to_string()));

View File

@@ -4,6 +4,7 @@ use crate::{
GameState,
abilities::HeadAbility,
backpack::{BackbackSwapEvent, Backpack},
global_observer,
hitpoints::Hitpoints,
player::{Player, head_id_to_str},
sounds::PlaySound,
@@ -133,8 +134,8 @@ pub fn plugin(app: &mut App) {
(reload, sync_hp).run_if(in_state(GameState::Playing)),
);
app.add_observer(on_select_active_head);
app.add_observer(on_swap_backpack);
global_observer!(app, on_select_active_head);
global_observer!(app, on_swap_backpack);
}
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {

View File

@@ -1,5 +1,5 @@
use crate::{
GameState, billboards::Billboard, loading_assets::GameAssets, player::Player,
GameState, billboards::Billboard, global_observer, loading_assets::GameAssets, player::Player,
sounds::PlaySound, squish_animation::SquishAnimation,
};
use avian3d::prelude::*;
@@ -18,10 +18,11 @@ pub struct KeyCollected(pub String);
pub fn plugin(app: &mut App) {
app.add_systems(Update, collect_key.run_if(in_state(GameState::Playing)));
app.add_observer(on_spawn);
global_observer!(app, on_spawn_key);
}
fn on_spawn(trigger: Trigger<KeySpawn>, mut commands: Commands, assets: Res<GameAssets>) {
fn on_spawn_key(trigger: Trigger<KeySpawn>, mut commands: Commands, assets: Res<GameAssets>) {
let KeySpawn(position, id) = trigger.event();
let angle = rand::random::<f32>() * PI * 2.;

View File

@@ -145,6 +145,7 @@ fn main() {
app.add_plugins(hitpoints::plugin);
app.add_plugins(cash_heal::plugin);
app.add_plugins(debug::plugin);
app.add_plugins(utils::observers::plugin);
app.init_state::<GameState>();

View File

@@ -1,5 +1,5 @@
use crate::{
GameState,
GameState, global_observer,
tb_entities::{Movable, MoveTarget},
};
use bevy::{prelude::*, utils::HashSet};
@@ -20,10 +20,11 @@ pub struct TriggerMovableEvent(pub HashSet<String>);
pub fn plugin(app: &mut App) {
app.register_type::<ActiveMovable>();
app.add_systems(Update, move_active.run_if(in_state(GameState::Playing)));
app.add_observer(trigger);
global_observer!(app, on_movable_event);
}
fn trigger(
fn on_movable_event(
trigger: Trigger<TriggerMovableEvent>,
mut commands: Commands,
uninit_movables: Query<

View File

@@ -7,6 +7,7 @@ use crate::{
Controls,
controller::{CharacterControllerBundle, MovementBundle, PlayerMovement},
},
global_observer,
heads::HeadChanged,
hitpoints::Hitpoints,
loading_assets::GameAssets,
@@ -57,7 +58,7 @@ pub fn plugin(app: &mut App) {
(rotate_view_keyboard, rotate_view_gamepad).run_if(in_state(GameState::Playing)),
);
app.add_observer(update_head);
global_observer!(app, on_update_head);
}
fn spawn(
@@ -242,7 +243,7 @@ fn toggle_animation(
}
}
fn update_head(
fn on_update_head(
trigger: Trigger<HeadChanged>,
mut commands: Commands,
asset_server: Res<AssetServer>,

View File

@@ -1,4 +1,4 @@
use crate::loading_assets::AudioAssets;
use crate::{global_observer, loading_assets::AudioAssets};
use bevy::prelude::*;
#[derive(Event, Clone, Debug)]
@@ -19,10 +19,10 @@ pub enum PlaySound {
}
pub fn plugin(app: &mut App) {
app.add_observer(spawn_sounds);
global_observer!(app, on_spawn_sounds);
}
fn spawn_sounds(
fn on_spawn_sounds(
trigger: Trigger<PlaySound>,
mut commands: Commands,
// sound_res: Res<AudioAssets>,

View File

@@ -1,3 +1,6 @@
pub mod billboards;
pub mod observers;
pub mod sprite_3d_animation;
pub mod squish_animation;
pub(crate) use observers::global_observer;

35
src/utils/observers.rs Normal file
View File

@@ -0,0 +1,35 @@
use bevy::prelude::*;
#[macro_export]
macro_rules! global_observer {
($app:expr,$system:expr) => {{
$app.world_mut()
.add_observer($system)
.insert(Name::new(stringify!($system)))
}};
}
pub use global_observer;
pub fn plugin(app: &mut App) {
app.add_systems(Update, global_observers);
}
fn global_observers(
mut cmds: Commands,
query: Query<Entity, (With<Observer>, Without<Parent>, Added<Observer>)>,
mut root: Local<Option<Entity>>,
) {
if root.is_none() {
let new_root = cmds.spawn(Name::new("Observers")).id();
*root = Some(new_root);
}
let Some(root) = *root else {
return;
};
for o in query.iter() {
cmds.entity(root).add_child(o);
}
}