-
-
Notifications
You must be signed in to change notification settings - Fork 3.9k
feat: allow for Trigger
to provide the Entity
on which an event w…
#18710
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
…as observed. `Trigger` in an observer system has provided the `target` method which gives the entity on which an event was triggered. This may be different to the entity that is being observed. This change introduces a `current_target` method on `Trigger`, which returns the id of the entity being observed. In some cases, code that uses the result of `Trigger::target` may now actually need `Trigger::target`.
Welcome, new contributor! Please make sure you've read our contributing guide and we look forward to reviewing your pull request shortly ✨ |
How is this different from |
|
so when bubbling you would have access to the current entity, and the entity that started the bubbling? |
Yes. That’s right |
I've been using Relationships, event bubbling, and triggers / observers. I found the current Trigger::target and Trigger::observer to be confusing -- is the target the entity that the event was sent with, or the entity that is being observed? Turns out sometimes I want to know both the originally targeted entity and the related entity with the observer that the event was bubbled to. So, this change is helpful to me. May I suggest some different naming? I find "current_target" and "target" a bit confusing. My suggestion is as follows: Trigger::target = the entity that was triggered With no event bubbling, Trigger::target == Trigger::observed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I'm reading this right, then the value returned by target()
today will be returned by current_target()
after this change, and the target()
method will change from returning the current target to the original target. Is that right?
If that's the case, then I think you need a migration guide, since it's a change to the behavior of the existing target()
method. (And you may also need to update some target != Entity::PLACEHOLDER
checks to use current_target
.)
/// Returns the [`Entity`] that is currently being observed. It may be [`Entity::PLACEHOLDER`] | ||
/// if the observer is a global observer. | ||
/// | ||
/// To get the entity that was targeted by the event use [`Trigger::target`]. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given how confusing this has been, it might help to explicitly mention event propagation here. Maybe something along the lines of
/// When [propagation](Trigger::propagate) is used,
/// an observer may be invoked multiple times for a single event.
/// [`Trigger::target`] will be the same for each invocation,
/// while [`Trigger::current_target`] will be different.
Today, |
... okay, I must be reading this wrong somehow. Let me try to walk through it slowly. Before the change, So within That calls Where am I going wrong? It sure looks like |
I think this is correct. Said another way: currently, the value returned by
Yes. My game uses emfax wrote:
I do not think this is correct. I am relying on "target" changing in my game code today. If it helps, I can post an example showing that it does in fact change, as event bubbling proceeds. |
@SteveAlexander You're correct about what I was so sure that I was correct, I've been trying to figure this out for an hour. I was using the So yes, the result of |
@emfax thanks. I can certainly recognise the situation of spending an hour chasing a mirage! What do you think about the naming of I could make a case to myself that either would be the "current" one, and so I find it hard to remember which one I want. I think perhaps the confusion you spoke to in your comment above also suggests that the naming isn't as clear as it could be. If the events were named differently, I think I'd find it easier to remember. For example, |
I checked what javascript does, as that's an existing example of an event bubbling API. And it's consistent with the name and meanings for "target" and "current target" in this PR.
|
#[test]
fn current_target() {
struct Bubbling;
impl Event for Bubbling {
const AUTO_PROPAGATE: bool = true;
type Traversal = &'static ChildOf;
}
#[derive(Debug, Default, PartialEq, Eq, Resource)]
struct BubblingStorage {
observer: Vec<Entity>,
target: Vec<Entity>,
}
fn bubble(trigger: Trigger<Bubbling>, mut storage: ResMut<BubblingStorage>) {
storage.observer.push(trigger.observer());
storage.target.push(trigger.target());
}
let mut world = World::new();
world.init_resource::<BubblingStorage>();
let root = world.spawn_empty().id();
let a = world.spawn(ChildOf(root)).id();
let b = world.spawn(ChildOf(a)).id();
let c = world.spawn(ChildOf(b)).id();
let d = world.spawn(ChildOf(c)).id();
let observer = world
.spawn(
Observer::new(bubble)
.with_entity(root)
.with_entity(a)
.with_entity(b)
.with_entity(c)
.with_entity(d),
)
.id();
world.trigger_targets(Bubbling, d);
let expected = BubblingStorage {
observer: vec![observer, observer, observer, observer, observer],
target: vec![d, c, b, a, root],
};
assert_eq!(&expected, world.get_resource::<BubblingStorage>().unwrap());
} this passes with the current implementation |
It looks like your PR is a breaking change, but you didn't provide a migration guide. Please review the instructions for writing migration guides, then expand or revise the content in the migration guides directory to reflect your changes. |
I think if I add the "needs migration guide" label, then a bot will add a comment with instructions... yup, there is goes! (If you wind up changing the names so that it no longer needs a migration guide, leave a comment and someone with triage access can remove the label.) |
Yeah, I decided to use similar names to web here. |
…as observed.
Trigger
in an observer system has provided thetarget
method which gives the entity on which an event was triggered. This may be different to the entity that is being observed. This change introduces acurrent_target
method onTrigger
, which returns the id of the entity being observed.In some cases, code that uses the result of
Trigger::target
may now actually needTrigger::target
.Objective
Solution
Testing
Showcase
While a showcase should aim to be brief and digestible, you can use a toggleable section to save space on longer showcases:
Click to view showcase