Compare commits

...

2 Commits

Author SHA1 Message Date
3a6ede0428 Update CI configuration.
Some checks failed
continuous-integration/drone/push Build is failing
2022-12-19 14:10:21 -06:00
b1a11de050 Upgrade to Bevy 0.9. 2022-12-19 14:08:31 -06:00
13 changed files with 138 additions and 108 deletions

View File

@ -8,7 +8,7 @@ steps:
commands: commands:
- rustup component add clippy rustfmt - rustup component add clippy rustfmt
- apt-get update -qq - apt-get update -qq
- apt-get install -qqy llvm-dev libclang-dev clang libspeechd-dev pkg-config libx11-dev libasound2-dev libudev-dev libxcb-xfixes0-dev libwayland-dev libxkbcommon-dev libvulkan-dev cmake - apt-get install -qqy llvm-dev libspeechd-dev pkg-config libx11-dev libasound2-dev libudev-dev libxcb-xfixes0-dev libwayland-dev libxkbcommon-dev libvulkan-dev cmake
- cargo fmt --check - cargo fmt --check
- cargo test --no-default-features --features=speech_dispatcher_0_10 - cargo test --no-default-features --features=speech_dispatcher_0_10
- cargo clippy --no-default-features --features=speech_dispatcher_0_10 - cargo clippy --no-default-features --features=speech_dispatcher_0_10

View File

@ -8,11 +8,12 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[features] [features]
speech_dispatcher_0_9 = ["bevy_tts/speech_dispatcher_0_9"]
speech_dispatcher_0_10 = ["bevy_tts/speech_dispatcher_0_10"] speech_dispatcher_0_10 = ["bevy_tts/speech_dispatcher_0_10"]
speech_dispatcher_0_11 = ["bevy_tts/speech_dispatcher_0_11"] speech_dispatcher_0_11 = ["bevy_tts/speech_dispatcher_0_11"]
[dependencies.bevy] [dependencies.bevy]
version = "0.8" version = "0.9"
default-features = false default-features = false
features = [ features = [
"bevy_gilrs", "bevy_gilrs",
@ -25,18 +26,18 @@ features = [
[dependencies] [dependencies]
backtrace = "0.3" backtrace = "0.3"
bevy_rapier2d = "0.17" bevy_rapier2d = "0.19"
bevy_synthizer = { git = "https://labs.lightsout.games/projects/bevy_synthizer" } bevy_synthizer = "0.1"
bevy_tts = { version = "0.1", default-features = false, features = ["tolk"] } bevy_tts = { version = "0.2", default-features = false, features = ["tolk"] }
coord_2d = "0.3" coord_2d = "0.3"
futures-lite = "1" futures-lite = "1"
gilrs = "0.9" gilrs = "0.10"
here_be_dragons = "0.2" here_be_dragons = "0.2"
leafwing_input_manager = { git = "https://github.com/leafwing-studios/leafwing-input-manager", branch = "dev" } leafwing-input-manager = "0.7"
maze_generator = "2" maze_generator = "2"
once_cell = "1" once_cell = "1"
pathfinding = "3" pathfinding = "4"
rand = "0.8" rand = "0.8"
sentry = "0.27" sentry = "0.29"
serde = "1" serde = "1"
shadowcast = "0.8" shadowcast = "0.8"

View File

@ -7,11 +7,11 @@ use std::{
sync::RwLock, sync::RwLock,
}; };
use bevy::{ecs::query::WorldQuery, prelude::*, utils::FloatOrd}; use bevy::{app::PluginGroupBuilder, ecs::query::WorldQuery, prelude::*, utils::FloatOrd};
use bevy_rapier2d::{ use bevy_rapier2d::{
parry::query::{closest_points, distance, ClosestPoints}, parry::query::{closest_points, distance, ClosestPoints},
prelude::*, prelude::*,
rapier::{math::Isometry, prelude::AABB}, rapier::{math::Isometry, prelude::Aabb},
}; };
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use rand::prelude::*; use rand::prelude::*;
@ -143,7 +143,7 @@ impl Sub for Angle {
} }
} }
#[derive(Clone, Copy, Debug, Eq, PartialEq)] #[derive(Clone, Copy, Debug, Eq, PartialEq, Reflect)]
pub enum MovementDirection { pub enum MovementDirection {
North, North,
NorthNortheast, NorthNortheast,
@ -222,8 +222,10 @@ impl Display for MovementDirection {
} }
} }
#[derive(Component, Clone, Copy, Debug, Eq, PartialEq)] #[derive(Component, Clone, Copy, Default, Debug, Eq, PartialEq, Reflect)]
#[reflect(Component)]
pub enum CardinalDirection { pub enum CardinalDirection {
#[default]
North, North,
East, East,
South, South,
@ -570,7 +572,7 @@ impl GlobalTransformExt for GlobalTransform {
} }
#[derive(Component, Copy, Clone, Debug, Deref, DerefMut, PartialEq)] #[derive(Component, Copy, Clone, Debug, Deref, DerefMut, PartialEq)]
pub struct Area(pub AABB); pub struct Area(pub Aabb);
#[derive(Component, Clone, Copy, Debug, Default, Reflect)] #[derive(Component, Clone, Copy, Debug, Default, Reflect)]
#[reflect(Component)] #[reflect(Component)]
@ -642,7 +644,7 @@ fn setup(core_config: Res<CoreConfig>) {
*mode = core_config.relative_direction_mode; *mode = core_config.relative_direction_mode;
} }
#[derive(Clone, Copy, Debug)] #[derive(Resource, Clone, Copy, Debug)]
pub struct CoreConfig { pub struct CoreConfig {
pub relative_direction_mode: RelativeDirectionMode, pub relative_direction_mode: RelativeDirectionMode,
pub pixels_per_unit: u8, pub pixels_per_unit: u8,
@ -678,7 +680,8 @@ impl<RapierUserData: 'static + WorldQuery + Send + Sync> Plugin for CorePlugin<R
app.insert_resource(CoreConfig::default()); app.insert_resource(CoreConfig::default());
} }
let config = *app.world.get_resource::<CoreConfig>().unwrap(); let config = *app.world.get_resource::<CoreConfig>().unwrap();
app.add_plugin(RapierPhysicsPlugin::<RapierUserData>::pixels_per_meter( app.register_type::<CardinalDirection>()
.add_plugin(RapierPhysicsPlugin::<RapierUserData>::pixels_per_meter(
config.pixels_per_unit as f32, config.pixels_per_unit as f32,
)) ))
.add_startup_system(setup) .add_startup_system(setup)
@ -697,10 +700,10 @@ impl<RapierUserData> Default for CorePlugins<RapierUserData> {
impl<RapierUserData: 'static + WorldQuery + Send + Sync> PluginGroup impl<RapierUserData: 'static + WorldQuery + Send + Sync> PluginGroup
for CorePlugins<RapierUserData> for CorePlugins<RapierUserData>
{ {
fn build(&mut self, group: &mut bevy::app::PluginGroupBuilder) { fn build(self) -> PluginGroupBuilder {
group PluginGroupBuilder::start::<Self>()
.add(crate::bevy_tts::TtsPlugin) .add(crate::bevy_tts::TtsPlugin)
.add(crate::bevy_synthizer::SynthizerPlugin) .add(crate::bevy_synthizer::SynthizerPlugin::default())
.add(CorePlugin::<RapierUserData>::default()); .add(CorePlugin::<RapierUserData>::default())
} }
} }

View File

@ -4,6 +4,9 @@ use std::{panic, thread};
use backtrace::Backtrace; use backtrace::Backtrace;
use bevy::prelude::*; use bevy::prelude::*;
#[derive(Resource)]
struct Guard(sentry::ClientInitGuard);
pub fn error_handler(In(result): In<Result<(), Box<dyn Error>>>) { pub fn error_handler(In(result): In<Result<(), Box<dyn Error>>>) {
if let Err(e) = result { if let Err(e) = result {
error!("{}", e); error!("{}", e);
@ -44,7 +47,7 @@ fn init_panic_handler() {
})); }));
} }
#[derive(Clone, Debug, Default)] #[derive(Resource, Clone, Debug, Default)]
pub struct ErrorConfig { pub struct ErrorConfig {
pub sentry_dsn: Option<String>, pub sentry_dsn: Option<String>,
pub version: Option<String>, pub version: Option<String>,
@ -57,7 +60,7 @@ impl Plugin for ErrorPlugin {
init_panic_handler(); init_panic_handler();
if let Some(config) = app.world.get_resource::<ErrorConfig>() { if let Some(config) = app.world.get_resource::<ErrorConfig>() {
if let Some(dsn) = &config.sentry_dsn { if let Some(dsn) = &config.sentry_dsn {
let release = config.version.clone().unwrap_or_else(|| "".to_string()); let release = config.version.clone().unwrap_or_default();
let guard = sentry::init(( let guard = sentry::init((
dsn.as_str(), dsn.as_str(),
sentry::ClientOptions { sentry::ClientOptions {
@ -65,7 +68,7 @@ impl Plugin for ErrorPlugin {
..default() ..default()
}, },
)); ));
app.insert_resource(guard); app.insert_resource(Guard(guard));
} }
} }
} }

View File

@ -41,7 +41,9 @@ pub struct Exploring(pub (f32, f32));
impl_pointlike_for_tuple_component!(Exploring); impl_pointlike_for_tuple_component!(Exploring);
#[derive(Component, Clone, Debug, Default, Deref, DerefMut)] #[derive(Component, Clone, Debug, Default, Deref, DerefMut)]
pub struct FocusedExplorationType<T>(pub Option<T>); pub struct FocusedExplorationType<T>(pub Option<T>)
where
T: Component + Default;
#[derive(Component, Clone, Copy, Debug, Default, Reflect)] #[derive(Component, Clone, Copy, Debug, Default, Reflect)]
#[reflect(Component)] #[reflect(Component)]
@ -57,7 +59,7 @@ fn exploration_type_change<T, S>(
features: Query<&T>, features: Query<&T>,
) -> Result<(), Box<dyn Error>> ) -> Result<(), Box<dyn Error>>
where where
T: Component + Copy + Ord, T: Component + Default + Copy + Ord,
S: 'static + Clone + Debug + Eq + Hash + Send + Sync, S: 'static + Clone + Debug + Eq + Hash + Send + Sync,
{ {
for (actions, visible, mut focused) in explorers.iter_mut() { for (actions, visible, mut focused) in explorers.iter_mut() {
@ -123,7 +125,7 @@ fn exploration_type_focus<T, S>(
features: Query<(Entity, &Transform, &T)>, features: Query<(Entity, &Transform, &T)>,
) -> Result<(), Box<dyn Error>> ) -> Result<(), Box<dyn Error>>
where where
T: Component + PartialEq, T: Component + Default + PartialEq,
S: 'static + Clone + Debug + Eq + Hash + Send + Sync, S: 'static + Clone + Debug + Eq + Hash + Send + Sync,
{ {
for (entity, actions, visible_entities, focused_type, exploring) in explorers.iter() { for (entity, actions, visible_entities, focused_type, exploring) in explorers.iter() {
@ -181,7 +183,7 @@ fn exploration_type_changed_announcement<T>(
>, >,
) -> Result<(), Box<dyn Error>> ) -> Result<(), Box<dyn Error>>
where where
T: Component + Copy + Into<String>, T: Component + Default + Copy + Into<String>,
{ {
for (focused, changed) in focused.iter() { for (focused, changed) in focused.iter() {
if changed.is_added() { if changed.is_added() {
@ -367,7 +369,7 @@ fn cleanup(
} }
} }
#[derive(Clone, Debug)] #[derive(Resource, Clone, Debug)]
pub struct ExplorationConfig<S> { pub struct ExplorationConfig<S> {
pub exploration_control_states: Vec<S>, pub exploration_control_states: Vec<S>,
} }
@ -411,16 +413,17 @@ where
.clone(); .clone();
app.register_type::<ExplorationFocused>() app.register_type::<ExplorationFocused>()
.register_type::<Mappable>() .register_type::<Mappable>()
.register_type::<Explorable>()
.add_plugin(InputManagerPlugin::<ExplorationAction>::default()) .add_plugin(InputManagerPlugin::<ExplorationAction>::default())
.add_system(exploration_changed_announcement::<T, D>.chain(error_handler)); .add_system(exploration_changed_announcement::<T, D>.pipe(error_handler));
if config.exploration_control_states.is_empty() { if config.exploration_control_states.is_empty() {
app.add_system(exploration_focus::<S, D>) app.add_system(exploration_focus::<S, D>)
.add_system(exploration_type_focus::<T, S>.chain(error_handler)) .add_system(exploration_type_focus::<T, S>.pipe(error_handler))
.add_system(exploration_type_change::<T, S>.chain(error_handler)) .add_system(exploration_type_change::<T, S>.pipe(error_handler))
.add_system(navigate_to_explored::<S, D>) .add_system(navigate_to_explored::<S, D>)
.add_system_to_stage( .add_system_to_stage(
CoreStage::PostUpdate, CoreStage::PostUpdate,
exploration_type_changed_announcement::<T>.chain(error_handler), exploration_type_changed_announcement::<T>.pipe(error_handler),
); );
} else { } else {
let states = config.exploration_control_states; let states = config.exploration_control_states;
@ -428,11 +431,11 @@ where
app.add_system_set( app.add_system_set(
SystemSet::on_update(state.clone()) SystemSet::on_update(state.clone())
.with_system(exploration_focus::<S, D>) .with_system(exploration_focus::<S, D>)
.with_system(exploration_type_focus::<T, S>.chain(error_handler)) .with_system(exploration_type_focus::<T, S>.pipe(error_handler))
.with_system(exploration_type_change::<T, S>.chain(error_handler)) .with_system(exploration_type_change::<T, S>.pipe(error_handler))
.with_system(navigate_to_explored::<S, D>) .with_system(navigate_to_explored::<S, D>)
.with_system( .with_system(
exploration_type_changed_announcement::<T>.chain(error_handler), exploration_type_changed_announcement::<T>.pipe(error_handler),
), ),
) )
.add_system_set(SystemSet::on_exit(state).with_system(cleanup)); .add_system_set(SystemSet::on_exit(state).with_system(cleanup));

View File

@ -17,7 +17,7 @@ impl Log {
} }
} }
#[derive(Component, Clone, Debug)] #[derive(Component, Clone, Debug, Reflect)]
pub struct LogEntry { pub struct LogEntry {
pub time: Instant, pub time: Instant,
pub message: String, pub message: String,
@ -33,7 +33,7 @@ impl From<String> for LogEntry {
} }
fn setup(mut commands: Commands) { fn setup(mut commands: Commands) {
commands.spawn().insert(Log::default()); commands.spawn(Log::default());
} }
fn read_log( fn read_log(
@ -59,7 +59,8 @@ pub struct LogPlugin;
impl Plugin for LogPlugin { impl Plugin for LogPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
app.add_startup_system(setup) app.register_type::<LogEntry>()
.add_system_to_stage(CoreStage::PostUpdate, read_log.chain(error_handler)); .add_startup_system(setup)
.add_system_to_stage(CoreStage::PostUpdate, read_log.pipe(error_handler));
} }
} }

View File

@ -78,7 +78,7 @@ impl ITileType for Tile {
} }
} }
#[derive(Clone, Debug, Default)] #[derive(Resource, Clone, Debug, Default)]
pub struct MapConfig { pub struct MapConfig {
pub start_revealed: bool, pub start_revealed: bool,
} }
@ -151,22 +151,22 @@ impl<D: Clone + Default> MapFilter<D> for GridBuilder {
if field.has_passage(&North) { if field.has_passage(&North) {
let x = x_offset + half_width; let x = x_offset + half_width;
let y = y_offset + self.room_height; let y = y_offset + self.room_height;
map.set_tile(x as usize, y as usize, Tile::floor()); map.set_tile(x, y, Tile::floor());
} }
if field.has_passage(&South) { if field.has_passage(&South) {
let x = x_offset + half_width; let x = x_offset + half_width;
let y = y_offset; let y = y_offset;
map.set_tile(x as usize, y as usize, Tile::floor()); map.set_tile(x, y, Tile::floor());
} }
if field.has_passage(&East) { if field.has_passage(&East) {
let x = x_offset + self.room_width; let x = x_offset + self.room_width;
let y = y_offset + half_height; let y = y_offset + half_height;
map.set_tile(x as usize, y as usize, Tile::floor()); map.set_tile(x, y, Tile::floor());
} }
if field.has_passage(&West) { if field.has_passage(&West) {
let x = x_offset; let x = x_offset;
let y = y_offset + half_height; let y = y_offset + half_height;
map.set_tile(x as usize, y as usize, Tile::floor()); map.set_tile(x, y, Tile::floor());
} }
} }
} }
@ -198,13 +198,16 @@ fn spawn_colliders<D: 'static + Clone + Default + Send + Sync>(
for x in 0..map.width { for x in 0..map.width {
if let Some(tile) = map.at(x, y) { if let Some(tile) = map.at(x, y) {
if tile.blocks_motion() { if tile.blocks_motion() {
let id = let id = commands
commands .spawn((
.spawn_bundle(TransformBundle::from_transform( TransformBundle::from_transform(Transform::from_xyz(
Transform::from_xyz(x as f32 + 0.5, y as f32 + 0.5, 0.), x as f32 + 0.5,
y as f32 + 0.5,
0.,
)),
Collider::cuboid(0.5, 0.5),
MapObstruction,
)) ))
.insert(Collider::cuboid(0.5, 0.5))
.insert(MapObstruction)
.id(); .id();
if tile.blocks_visibility() { if tile.blocks_visibility() {
commands.entity(id).insert(Visible::opaque()); commands.entity(id).insert(Visible::opaque());
@ -223,16 +226,18 @@ fn spawn_colliders<D: 'static + Clone + Default + Send + Sync>(
Isometry2::new(Vector2::new(room.center().x(), room.center().y()), 0.); Isometry2::new(Vector2::new(room.center().x(), room.center().y()), 0.);
let aabb = shape.raw.compute_aabb(&position); let aabb = shape.raw.compute_aabb(&position);
let id = commands let id = commands
.spawn_bundle(TransformBundle::from_transform(Transform::from_xyz( .spawn((
TransformBundle::from_transform(Transform::from_xyz(
position.translation.x, position.translation.x,
position.translation.y, position.translation.y,
0., 0.,
))) )),
.insert(shape) shape,
.insert(Sensor) Sensor,
.insert(ActiveEvents::COLLISION_EVENTS) ActiveEvents::COLLISION_EVENTS,
.insert(Area(aabb)) Area(aabb),
.insert(Zone) Zone,
))
.id(); .id();
commands.entity(map_entity).push_children(&[id]); commands.entity(map_entity).push_children(&[id]);
} }
@ -281,7 +286,7 @@ fn spawn_portals<D: 'static + Clone + Default + Send + Sync>(
} }
for (x, y) in portals { for (x, y) in portals {
let portal = commands let portal = commands
.spawn_bundle(PortalBundle { .spawn(PortalBundle {
transform: Transform::from_translation(Vec3::new(x, y, 0.)), transform: Transform::from_translation(Vec3::new(x, y, 0.)),
..default() ..default()
}) })

View File

@ -49,19 +49,22 @@ pub struct RotationSpeed(pub Angle);
#[reflect(Component)] #[reflect(Component)]
pub struct Speed(pub f32); pub struct Speed(pub f32);
#[derive(Component, Deref, DerefMut)] #[derive(Deref, DerefMut)]
struct SnapTimer(Timer); struct SnapTimer(Timer);
impl Default for SnapTimer { impl Default for SnapTimer {
fn default() -> Self { fn default() -> Self {
Self(Timer::from_seconds(0.2, false)) Self(Timer::from_seconds(0.2, TimerMode::Once))
} }
} }
#[derive(Resource, Default, Deref, DerefMut)]
struct SnapTimers(HashMap<Entity, SnapTimer>);
fn movement_controls<S>( fn movement_controls<S>(
mut commands: Commands, mut commands: Commands,
config: Res<NavigationConfig<S>>, config: Res<NavigationConfig<S>>,
snap_timers: Res<HashMap<Entity, SnapTimer>>, snap_timers: Res<SnapTimers>,
mut query: Query<( mut query: Query<(
Entity, Entity,
&mut ActionState<NavigationAction>, &mut ActionState<NavigationAction>,
@ -118,14 +121,14 @@ fn movement_controls<S>(
.axis_pair = Some(DualAxisData::from_xy(v)); .axis_pair = Some(DualAxisData::from_xy(v));
} }
} }
if actions.released(NavigationAction::Move) { if actions.released(NavigationAction::Move)
if actions.axis_pair(NavigationAction::Move).is_some() { && actions.axis_pair(NavigationAction::Move).is_some()
{
actions.press(NavigationAction::SetLinearVelocity); actions.press(NavigationAction::SetLinearVelocity);
actions actions
.action_data_mut(NavigationAction::SetLinearVelocity) .action_data_mut(NavigationAction::SetLinearVelocity)
.axis_pair = None; .axis_pair = None;
} }
}
if actions.pressed(NavigationAction::SetLinearVelocity) { if actions.pressed(NavigationAction::SetLinearVelocity) {
if let Some(pair) = actions.axis_pair(NavigationAction::SetLinearVelocity) { if let Some(pair) = actions.axis_pair(NavigationAction::SetLinearVelocity) {
velocity.linvel = pair.into(); velocity.linvel = pair.into();
@ -167,7 +170,7 @@ fn movement_controls<S>(
fn snap( fn snap(
mut tts: ResMut<Tts>, mut tts: ResMut<Tts>,
mut snap_timers: ResMut<HashMap<Entity, SnapTimer>>, mut snap_timers: ResMut<SnapTimers>,
mut query: Query< mut query: Query<
( (
Entity, Entity,
@ -210,7 +213,7 @@ fn snap(
Ok(()) Ok(())
} }
fn tick_snap_timers(time: Res<Time>, mut snap_timers: ResMut<HashMap<Entity, SnapTimer>>) { fn tick_snap_timers(time: Res<Time>, mut snap_timers: ResMut<SnapTimers>) {
for timer in snap_timers.values_mut() { for timer in snap_timers.values_mut() {
timer.tick(time.delta()); timer.tick(time.delta());
} }
@ -336,7 +339,7 @@ fn log_area_descriptions<S, A>(
} }
} }
#[derive(Clone, Debug)] #[derive(Resource, Clone, Debug)]
pub struct NavigationConfig<S> { pub struct NavigationConfig<S> {
pub forward_movement_factor: f32, pub forward_movement_factor: f32,
pub backward_movement_factor: f32, pub backward_movement_factor: f32,
@ -383,14 +386,15 @@ where
.get_resource::<NavigationConfig<S>>() .get_resource::<NavigationConfig<S>>()
.unwrap() .unwrap()
.clone(); .clone();
app.init_resource::<HashMap<Entity, SnapTimer>>() app.init_resource::<SnapTimers>()
.register_type::<MaxSpeed>() .register_type::<MaxSpeed>()
.register_type::<RotationSpeed>() .register_type::<RotationSpeed>()
.register_type::<Speed>()
.add_plugin(InputManagerPlugin::<NavigationAction>::default()) .add_plugin(InputManagerPlugin::<NavigationAction>::default())
.add_system_to_stage(CoreStage::PreUpdate, update_direction) .add_system_to_stage(CoreStage::PreUpdate, update_direction)
.add_system_to_stage(CoreStage::PostUpdate, remove_direction) .add_system_to_stage(CoreStage::PostUpdate, remove_direction)
.add_system(tick_snap_timers) .add_system(tick_snap_timers)
.add_system(speak_direction.chain(error_handler)) .add_system(speak_direction.pipe(error_handler))
.add_system(add_speed) .add_system(add_speed)
.add_system(limit_speed) .add_system(limit_speed)
.add_system_to_stage(CoreStage::PostUpdate, remove_speed) .add_system_to_stage(CoreStage::PostUpdate, remove_speed)
@ -402,14 +406,14 @@ where
.label(MOVEMENT_CONTROLS) .label(MOVEMENT_CONTROLS)
.after(limit_speed), .after(limit_speed),
) )
.add_system(snap.chain(error_handler).before(MOVEMENT_CONTROLS)); .add_system(snap.pipe(error_handler).before(MOVEMENT_CONTROLS));
} else { } else {
let states = config.movement_control_states; let states = config.movement_control_states;
for state in states { for state in states {
app.add_system_set( app.add_system_set(
SystemSet::on_update(state) SystemSet::on_update(state)
.with_system(movement_controls::<S>.label(MOVEMENT_CONTROLS)) .with_system(movement_controls::<S>.label(MOVEMENT_CONTROLS))
.with_system(snap.chain(error_handler).before(MOVEMENT_CONTROLS)), .with_system(snap.pipe(error_handler).before(MOVEMENT_CONTROLS)),
); );
} }
} }

View File

@ -59,7 +59,7 @@ impl CostMap {
} }
pub fn set_modifier(&mut self, x: usize, y: usize, cost: f32) { pub fn set_modifier(&mut self, x: usize, y: usize, cost: f32) {
let idx = (y as usize) * self.width + (x as usize); let idx = y * self.width + x;
self.costs[idx] = cost; self.costs[idx] = cost;
} }
} }
@ -109,8 +109,8 @@ fn find_path_for_shape(
&start.i32(), &start.i32(),
|p| { |p| {
let mut successors: Vec<((i32, i32), u32)> = vec![]; let mut successors: Vec<((i32, i32), u32)> = vec![];
let x = p.0 as i32; let x = p.0;
let y = p.1 as i32; let y = p.1;
let exits = vec![ let exits = vec![
((x - 1, y), 1.), ((x - 1, y), 1.),
((x + 1, y), 1.), ((x + 1, y), 1.),
@ -325,7 +325,11 @@ pub struct PathfindingPlugin;
impl Plugin for PathfindingPlugin { impl Plugin for PathfindingPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
app.add_system(calculate_path) app.register_type::<Destination>()
.register_type::<NoPath>()
.register_type::<Path>()
.register_type::<CostMap>()
.add_system(calculate_path)
.add_system_to_stage(CoreStage::PostUpdate, remove_destination) .add_system_to_stage(CoreStage::PostUpdate, remove_destination)
.add_system(poll_tasks) .add_system(poll_tasks)
.add_system_to_stage(CoreStage::PostUpdate, negotiate_path); .add_system_to_stage(CoreStage::PostUpdate, negotiate_path);

View File

@ -8,10 +8,11 @@ use crate::{
sound::SoundIcon, sound::SoundIcon,
}; };
#[derive(Component, Clone, Copy, Debug, Default)] #[derive(Component, Clone, Copy, Debug, Default, Reflect)]
#[reflect(Component)]
struct Behind; struct Behind;
#[derive(Clone, Copy, Debug)] #[derive(Resource, Clone, Copy, Debug)]
pub struct PitchShiftConfig { pub struct PitchShiftConfig {
pub downshift_behind: bool, pub downshift_behind: bool,
pub downshift: f64, pub downshift: f64,
@ -63,10 +64,10 @@ fn tag_behind(
} }
} }
#[derive(Clone, Debug, Default, Deref, DerefMut)] #[derive(Resource, Clone, Debug, Default, Deref, DerefMut)]
struct LastIconPitch(HashMap<Entity, f64>); struct LastIconPitch(HashMap<Entity, f64>);
#[derive(Clone, Debug, Default, Deref, DerefMut)] #[derive(Resource, Clone, Debug, Default, Deref, DerefMut)]
struct LastSoundPitch(HashMap<Entity, f64>); struct LastSoundPitch(HashMap<Entity, f64>);
fn behind_added( fn behind_added(
@ -158,7 +159,8 @@ pub struct PitchShiftPlugin;
impl Plugin for PitchShiftPlugin { impl Plugin for PitchShiftPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
app.init_resource::<PitchShiftConfig>() app.register_type::<Behind>()
.init_resource::<PitchShiftConfig>()
.init_resource::<LastIconPitch>() .init_resource::<LastIconPitch>()
.init_resource::<LastSoundPitch>() .init_resource::<LastSoundPitch>()
.add_system_to_stage(CoreStage::PreUpdate, tag_behind) .add_system_to_stage(CoreStage::PreUpdate, tag_behind)

View File

@ -12,7 +12,8 @@ use crate::{
visibility::{VisibilityChanged, Visible, VisibleEntities}, visibility::{VisibilityChanged, Visible, VisibleEntities},
}; };
#[derive(Component, Clone, Debug)] #[derive(Component, Clone, Debug, Reflect)]
#[reflect(Component)]
pub struct SoundIcon { pub struct SoundIcon {
pub buffer: Handle<Buffer>, pub buffer: Handle<Buffer>,
pub gain: f64, pub gain: f64,
@ -27,7 +28,7 @@ impl Default for SoundIcon {
buffer: default(), buffer: default(),
gain: 1., gain: 1.,
pitch: 1., pitch: 1.,
interval: Some(Timer::from_seconds(seconds, true)), interval: Some(Timer::from_seconds(seconds, TimerMode::Repeating)),
}; };
if let Some(ref mut interval) = icon.interval { if let Some(ref mut interval) = icon.interval {
let seconds = Duration::from_secs_f32(seconds - 0.1); let seconds = Duration::from_secs_f32(seconds - 0.1);
@ -71,7 +72,7 @@ fn update<S>(
) where ) where
S: 'static + Clone + Debug + Eq + Hash + Send + Sync, S: 'static + Clone + Debug + Eq + Hash + Send + Sync,
{ {
if !(*config).states.is_empty() && !config.states.contains(state.current()) { if !config.states.is_empty() && !config.states.contains(state.current()) {
return; return;
} }
for visible in viewers.iter() { for visible in viewers.iter() {
@ -166,7 +167,7 @@ fn reset_timer_on_visibility_gain(
if let Ok(children) = children.get(*viewed) { if let Ok(children) = children.get(*viewed) {
for child in children.iter() { for child in children.iter() {
if icons.get(*child).is_ok() { if icons.get(*child).is_ok() {
targets.push(&*child); targets.push(child);
} }
} }
} }
@ -182,7 +183,7 @@ fn reset_timer_on_visibility_gain(
} }
} }
#[derive(Clone, Debug, Default)] #[derive(Resource, Clone, Debug, Default)]
pub struct SoundIconConfig<S> { pub struct SoundIconConfig<S> {
pub states: Vec<S>, pub states: Vec<S>,
} }
@ -200,7 +201,8 @@ where
S: 'static + Clone + Debug + Eq + Hash + Send + Sync, S: 'static + Clone + Debug + Eq + Hash + Send + Sync,
{ {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
app.add_system(added) app.register_type::<SoundIcon>()
.add_system(added)
.add_system_to_stage(CoreStage::PostUpdate, update::<S>) .add_system_to_stage(CoreStage::PostUpdate, update::<S>)
.add_system_to_stage( .add_system_to_stage(
CoreStage::PostUpdate, CoreStage::PostUpdate,

View File

@ -4,7 +4,8 @@ use bevy_synthizer::{Listener, Sound};
use crate::{commands::RunIfExistsExt, core::GlobalTransformExt}; use crate::{commands::RunIfExistsExt, core::GlobalTransformExt};
#[derive(Component, Clone, Copy, Debug)] #[derive(Component, Default, Reflect, Clone, Copy, Debug)]
#[reflect(Component)]
pub struct Volumetric; pub struct Volumetric;
fn update( fn update(
@ -41,7 +42,7 @@ fn update(
fn removed(mut commands: Commands, removed: RemovedComponents<Volumetric>) { fn removed(mut commands: Commands, removed: RemovedComponents<Volumetric>) {
for entity in removed.iter() { for entity in removed.iter() {
commands.run_if_exists(entity, |mut entity| { commands.run_if_exists(entity, |mut entity| {
entity.insert_bundle(TransformBundle::default()); entity.insert(TransformBundle::default());
}); });
} }
} }
@ -50,7 +51,8 @@ pub struct VolumetricPlugin;
impl Plugin for VolumetricPlugin { impl Plugin for VolumetricPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
app.add_system_to_stage( app.register_type::<Volumetric>()
.add_system_to_stage(
CoreStage::PostUpdate, CoreStage::PostUpdate,
update.before(TransformSystem::TransformPropagate), update.before(TransformSystem::TransformPropagate),
) )

View File

@ -354,7 +354,7 @@ fn remove_visible(
&viewer_entity, &viewer_entity,
&mut visible_entities, &mut visible_entities,
start, start,
&*rapier_context, &rapier_context,
&visible, &visible,
&obstructions, &obstructions,
&mut changed, &mut changed,
@ -422,7 +422,7 @@ fn log_visible(
} }
} }
} else if let VisibilityChanged::Lost { viewed, .. } = event { } else if let VisibilityChanged::Lost { viewed, .. } = event {
recently_lost.insert(*viewed, Timer::from_seconds(2., false)); recently_lost.insert(*viewed, Timer::from_seconds(2., TimerMode::Once));
} }
} }
} }