Skip to content

Commit

Permalink
Add SequentialActions marker for required components (#106)
Browse files Browse the repository at this point in the history
  • Loading branch information
hikikones authored Nov 6, 2024
1 parent 685a8c7 commit b05e78a
Show file tree
Hide file tree
Showing 11 changed files with 66 additions and 32 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## Version 0.12.0-dev

- [Update to Bevy 0.15][103]
- [Add `SequentialActions` marker for required components][106]
- [Add skip amount in `ModifyActions::skip`][105]
- [Add multiple actions with a tuple][104]
- Removes `add_many` as `add` can now be used instead
Expand All @@ -12,6 +13,7 @@
- Replaces all unwraps with logging
- Adds `on_remove_hook` and `on_remove_trigger` for both `CurrentAction` and `ActionQueue`

[106]: https://github.com/hikikones/bevy-sequential-actions/pull/106
[105]: https://github.com/hikikones/bevy-sequential-actions/pull/105
[104]: https://github.com/hikikones/bevy-sequential-actions/pull/104
[103]: https://github.com/hikikones/bevy-sequential-actions/pull/103
Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,15 +104,15 @@ fn wait_system(mut wait_timer_q: Query<&mut WaitTimer>, time: Res<Time>) {

#### Modifying Actions

Actions can be added to any `Entity` that contains the `ActionsBundle`.
This is is done through the `actions(agent)`
Actions can be added to any `Entity` with the `SequentialActions` marker component.
Adding and modifying actions is done through the `actions(agent)`
extension method implemented for both `Commands` and `World`.
See the `ModifyActions` trait for available methods.

```rust
fn setup(mut commands: Commands) {
// Spawn entity with the bundle
let agent = commands.spawn(ActionsBundle::new()).id();
// Spawn entity with the marker component
let agent = commands.spawn(SequentialActions).id();
commands
.actions(agent)
// Add a single action
Expand Down
2 changes: 1 addition & 1 deletion benches/benches.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ fn run_many_countdowns(agents: u32) {
});

for i in 0..agents {
let agent = app.world_mut().spawn(ActionsBundle::new()).id();
let agent = app.world_mut().spawn(SequentialActions).id();
app.world_mut().actions(agent).add(CountdownAction {
count: i,
current: None,
Expand Down
4 changes: 2 additions & 2 deletions examples/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ fn main() {
}

fn setup(mut commands: Commands) {
// Spawn entity with the bundle
let agent = commands.spawn(ActionsBundle::new()).id();
// Spawn entity with the marker component
let agent = commands.spawn(SequentialActions).id();
commands
.actions(agent)
// Add a single action
Expand Down
13 changes: 3 additions & 10 deletions examples/custom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,24 +37,17 @@ struct EvenMarker;
#[derive(Component)]
struct OddMarker;

#[derive(Component)]
struct Agent;

fn setup(mut commands: Commands) {
// Spawn agent with even marker for even schedule
let agent_even = commands
.spawn((ActionsBundle::new(), EvenMarker, Agent))
.id();
let agent_even = commands.spawn((SequentialActions, EvenMarker)).id();
commands
.actions(agent_even)
.add(PrintForeverAction::new(format!(
"Even: is_finished is called every even frame for agent {agent_even}."
)));

// Spawn agent with odd marker for odd schedule
let agent_odd = commands
.spawn((ActionsBundle::new(), OddMarker, Agent))
.id();
let agent_odd = commands.spawn((SequentialActions, OddMarker)).id();
commands
.actions(agent_odd)
.add(PrintForeverAction::new(format!(
Expand All @@ -65,7 +58,7 @@ fn setup(mut commands: Commands) {
fn run_custom_schedules(
world: &mut World,
mut frame_count: Local<u32>,
mut agent_q: Local<QueryState<Entity, With<Agent>>>,
mut agent_q: Local<QueryState<Entity, With<SequentialActions>>>,
) {
if *frame_count % 2 == 0 {
world.run_schedule(EvenSchedule);
Expand Down
2 changes: 1 addition & 1 deletion examples/parallel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ fn main() {
}

fn setup(mut commands: Commands) {
let agent = commands.spawn(ActionsBundle::new()).id();
let agent = commands.spawn(SequentialActions).id();
commands.actions(agent).add((
ParallelActions::new(actions![
PrintAction("hello"),
Expand Down
11 changes: 6 additions & 5 deletions examples/pause.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,16 @@ fn main() {
.run();
}

#[derive(Component)]
struct Agent;

fn setup(mut commands: Commands) {
let agent = commands.spawn((ActionsBundle::new(), Agent)).id();
let agent = commands.spawn(SequentialActions).id();
commands.actions(agent).add(CountForeverAction);
}

fn frame_logic(mut frame: Local<u32>, mut commands: Commands, agent_q: Query<Entity, With<Agent>>) {
fn frame_logic(
mut frame: Local<u32>,
mut commands: Commands,
agent_q: Query<Entity, With<SequentialActions>>,
) {
const PAUSE_FRAME: u32 = 10;
const RESUME_FRAME: u32 = PAUSE_FRAME * 2;
const EXIT_FRAME: u32 = PAUSE_FRAME * 3;
Expand Down
2 changes: 1 addition & 1 deletion examples/repeat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ fn main() {
}

fn setup(mut commands: Commands) {
let agent = commands.spawn(ActionsBundle::new()).id();
let agent = commands.spawn(SequentialActions).id();
commands.actions(agent).add((
RepeatAction {
action: PrintAction("hello"),
Expand Down
2 changes: 1 addition & 1 deletion examples/sequence.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ fn main() {
}

fn setup(mut commands: Commands) {
let agent = commands.spawn(ActionsBundle::new()).id();
let agent = commands.spawn(SequentialActions).id();
commands.actions(agent).add(ActionSequence::new(actions![
PrintAction("see"),
PrintAction("you"),
Expand Down
25 changes: 19 additions & 6 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,8 @@ fn wait_system(mut wait_timer_q: Query<&mut WaitTimer>, time: Res<Time>) {
#### Modifying Actions
Actions can be added to any [`Entity`] that contains the [`ActionsBundle`].
This is is done through the [`actions(agent)`](ActionsProxy::actions)
Actions can be added to any [`Entity`] with the [`SequentialActions`] marker component.
Adding and modifying actions is done through the [`actions(agent)`](ActionsProxy::actions)
extension method implemented for both [`Commands`] and [`World`].
See the [`ModifyActions`] trait for available methods.
Expand All @@ -141,8 +141,8 @@ fn setup(mut commands: Commands) {
# let action_e = EmptyAction;
# let action_f = EmptyAction;
#
// Spawn entity with the bundle
let agent = commands.spawn(ActionsBundle::new()).id();
// Spawn entity with the marker component
let agent = commands.spawn(SequentialActions).id();
commands
.actions(agent)
// Add a single action
Expand Down Expand Up @@ -228,6 +228,19 @@ pub use world::*;
/// A boxed [`Action`].
pub type BoxedAction = Box<dyn Action>;

/// Marker component for entities with actions.
///
/// This component is all that is needed for spawning an agent that you can add actions to.
/// Required components will bring in the necessary components,
/// namely [CurrentAction] and [ActionQueue].
///
/// If you do not care for the marker,
/// or perhaps don't want to use required components,
/// there is still the [ActionsBundle] for spawning an agent as before.
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Component)]
#[require(CurrentAction, ActionQueue)]
pub struct SequentialActions;

/// The component bundle that all entities with actions must have.
#[derive(Default, Bundle)]
pub struct ActionsBundle {
Expand Down Expand Up @@ -333,7 +346,7 @@ impl ActionQueue {
}

/// Configuration for actions to be added.
#[derive(Debug, Clone, Copy)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct AddConfig {
/// Start the next action in the queue if nothing is currently running.
pub start: bool,
Expand Down Expand Up @@ -382,7 +395,7 @@ pub enum DropReason {
/// without being skipped or cleared from the action queue.
Done,
/// The action was skipped. This happens either deliberately,
/// or because an action was added to an `agent` that does not exist or is missing the [`ActionsBundle`].
/// or because an action was added to an `agent` that does not exist or is missing a component.
Skipped,
/// The action queue was cleared. This happens either deliberately,
/// or because an `agent` was despawned.
Expand Down
27 changes: 26 additions & 1 deletion tests/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ impl TestApp {
}

fn spawn_agent(&mut self) -> Entity {
self.world_mut().spawn(ActionsBundle::new()).id()
self.world_mut().spawn(SequentialActions).id()
}

fn actions(&mut self, agent: Entity) -> impl ModifyActions + use<'_> {
Expand Down Expand Up @@ -235,6 +235,30 @@ fn countup(mut countup_q: Query<&mut Countup>) {
}
}

#[test]
fn spawn_and_remove() {
let mut app = TestApp::new();
let a = app.world_mut().spawn(SequentialActions).id();

assert_eq!(app.entity(a).contains::<SequentialActions>(), true);
assert_eq!(app.entity(a).contains::<CurrentAction>(), true);
assert_eq!(app.entity(a).contains::<ActionQueue>(), true);

app.world_mut().entity_mut(a).remove::<SequentialActions>();

assert_eq!(app.entity(a).contains::<SequentialActions>(), false);
assert_eq!(app.entity(a).contains::<CurrentAction>(), true);
assert_eq!(app.entity(a).contains::<ActionQueue>(), true);

app.world_mut()
.entity_mut(a)
.remove_with_requires::<SequentialActions>();

assert_eq!(app.entity(a).contains::<SequentialActions>(), false);
assert_eq!(app.entity(a).contains::<CurrentAction>(), false);
assert_eq!(app.entity(a).contains::<ActionQueue>(), false);
}

#[test]
fn add() {
let mut app = TestApp::new();
Expand Down Expand Up @@ -895,6 +919,7 @@ fn bad_add_action() {

#[test]
#[should_panic]
#[cfg(debug_assertions)]
fn forever_action() {
struct ForeverAction;
impl Action for ForeverAction {
Expand Down

0 comments on commit b05e78a

Please sign in to comment.