#0.14 Bevy Jam
1 messages ยท Page 8 of 1
https://github.com/TheBevyFlock/bevy_quickstart/pull/230 is ready again
Yeah that's definitely something that would be neat as an own crate, but may be confusing / increasing the mental burden in a template imo
approved
thanks!
Then the only things left from Alice's notes are the asset stuff (PR is ready for review there), the spawning stuff you're working on and the game module
imo game -> demo and call it good
not quite imo
The asset module is not something you will yeet
Neither the audio stuff
well, we can pull some stuff out of there
animation, movement, and player (my PR removes spawn/ and level) can remain in demo
also i'd like to rename ui -> theme at some point
Yeah that's fair
Was the current vibe that we had too much or too little nesting and grouping?
I forgot
I think it changed at some point?
i think too much has generally been the vibe
for modules
well my pr compiles but he's tiny ๐
For the record, I still prefer the wayyy more nested and grouped variant that is currently in https://github.com/benfrankel/bevy_jam_template/
i've kinda been coming around to less nesting than before (especially wrt game), but
i am still personally strongly in favor of a util/ and a core/
Same
but i understand that bevy_quickstart is a pretty small template so as it currently stands, the template itself doesn't need those folders
But I won't die on that hill if cart himself is strongly against it ๐
yeah, the good old "will the user need to extend this" versus "how neatly packaged is the current functionality" debate
aww
i also noticed in some bevy jam games, some people really like having almost everything in the top-level folder
ah the level entity is missing a SpatialBundle, and i'm now spawning the player as a child
i'm surprised the player renders at all like that
well ig it makes sense
entity spawning pr: https://github.com/TheBevyFlock/bevy_quickstart/pull/231
oh i forgot to move the buttons into separate systems so they can register their one-shots in-place
I feel like this is jam priorities/first bevy game more than anything else
According to Francois, this is ultimately undefined behavior.
@agile dirge I bet you have thoughts on this
Why are all spawning functions not called spawn_*?
because then you'd do commands.spawn_fn(spawn_player)
and they aren't actually spawning the player, they're inserting the necessary components onto the already-spawned empty player entity
so you can also do commands.spawn(my_bundle).add(my_thing) etc
Hmm, I see. But the current naming is a bit whack.
current naming makes perfect sense to me personally
populate_player, prepare_player, insert_player, finish_player, deferred_spawn_player... hmm, can't think of anything good
I agree that it makes sense in context, but when I open the file as a newcomer and read fn player, I'm a bit surprised.
for example, we don't call NodeBundle something like InsertNodeBundle, but we're not confused about commands.spawn(NodeBundle)
even though internally what it's doing is commands.spawn_empty().insert(NodeBundle)
Why does the documentation comment say /// Spawn a player entity. then 
fair ๐
"create a player entity" may be more realistic
or "construct" ๐
i have not read the bsn proposal yet
Agreed, but structs have a naming expectation to be generally nouns, so it's pretty unsurprising. It also behaves as if it itself were the whole thing to spawn, so you don't need to know the internals and thus you don't need to leak the detail about insertion.
plugin fns are named like nouns too
In that situation, the function itself is the plugin. The function player is not the player.
well, the function player is the player spawning system
:p
i mean
you can think of the system as representing the entity itself
which makes more sense with e.g. struct Projectile
but not really
commands.spawn_fn(spawn::player)?
and commands.add_fn(spawn::player) as well
You can still use spawn_fn(player)
the function represents an entity, what you do with that entity is the commands.xyz call
I'm not arguing against the calling site, that's completely fine
I'm saying that the definition is a potentially confusing thing
Hmmm
If anything, it represents, a kind of mapping for that entity
not quite a map, but some kind of processing pipeline for the entity
That pipeline analogy would be stronger if we returned the Entity at the end. That way, you could progressively add stuff to it.
Not sure if that makes sense though
we do return it from the commands.spawn_fn though
just not from the system itself
ok how about this
the systems are analogous to plugins, but instead of operating on App, they operate on an entity
in which case the naming convention is consistent
that analogy would only hold if there was a shared name for this concept, just as we name all plugins plugin imo
like player_spawn?
Just fn spawn
oh but we have different things we want to spawn tho
potentially in the same file
Fair enough
I'll have to think about this for a while. Can't come up with anything nice right now.
I do like this a lot for the game feedback, but it should probably wait until the current two PRs are merged to avoid merge conflicts.
yeah for sure
pattern appr, but i went over it quickly, i can review better tmrw
sounds good, i'll leave it up for a while probably. i need to update the design doc as well
I like your doc comment calling it construct
What if we called it fn construct and, if we need multiple per file, we added a mod around the function?
I'm also fine with calling them construct_*
that one gets bonus points for being both a noun and a verb though ๐
About add_fn, wouldn't it be more consistent with rust to call it insert_with?
so the parallel is to add, which is for adding an EntityCommand, which is what's being used for the data-having version
i'll admit that the spawn -> insert vs. spawn -> add parallel is a little odd
i'll think whether the whole EntityCommand thing can be skipped entirely now
well it could but we'd need a new trait to replace it..
basically if you want to do commands.spawn_with(MyStruct), we need to be able to associate MyStruct with a particular system
currently that link is created by writing the 5-liner impl EntityCommand for MyStruct { world.run_system_once_with((id, self), Self::spawn); }
ideally we would have a trait with Self::spawn as a trait method. but then it wouldn't be able to accept any system params while still matching the trait's definition
so since MyStruct is technically an EntityCommand, it can be applied via EntityCommands::add for free, which is why add_fn comes in to match
Where is the struct coming from? Is that like an analogy to a Command?
I left some review comments
yeah it's analogous to struct vs function form of a command
where the struct can contain data, like struct Projectile { lifetime, .. }
Hope my review comments don't sound too negative. I like the pattern and think something like this should be in Bevy proper, I'm just not happy about the onboarding.
so what's happening is that in present-day bevy, "spawn" only supports bundles. so spawn = bundle, and insert = bundle
and commands are fully relegated to "add"
IMO if I could change bevy proper however i want rn
i'd make spawn take an EntityCommand, impl EntityCommand for Bundles, and remove insert
assuming rust doesn't complain about the blanket impl
so you would .add a bundle to insert it
then spawn_with is not needed because it's just spawn, and there's no insert vs add weirdness
and i'd implement EntityCommand for systems taking In<Entity> as their first arg, so spawn_fn and add_fn wouldn't be needed either
again assuming that's even possible
I've done very similar things to that in the past, pretty sure that works
so you'd have spawn(bundle), spawn(entity_command), spawn(entity_fn), and add(bundle), add(entity_command), add(entity_fn)
The more I think about it, the more I like it.
RFC time?
well i'm not sure rust will even allow it ๐ but i can test it out later
At least this part is definitely possible, I do something very very similar in Yarn Spinner for systems that have In<ValidYarnSpinnerValueMightBeABunchOfTuplesOrAnOptionEtc> as their first param.
icic
i think that requires owning EntityCommand because of orphan rule at least, so it would have to be upstream
Yep, definitely
@prisma delta do you have some trick for removing the to_string() calls from https://github.com/TheBevyFlock/bevy_quickstart/pull/225 ?
I could turn the involved constants into functions returning String, but that feels a bit weird.
I could also wrap some HashMap functionality behind functions that take impl Into<String>, but that would make the thing more complex for little gain, so I don't want to do that.
You might be able to swap out AsRef<str> for Borrow<str>
But IMO you should just simplify this further to take a 'static str
that would work, but wasn't the entire point of using strings in this case to allow dynamic loading from disk?
My issue is primarily with calls like this
Since the underlying HashMap is storing String, we cannot pass &str to it.
Except by wrapping everything with custom functions and constructors that accept some variant of impl Into<String>, impl Into<Cow<'_, str>>, impl AsRef<str>, or impl Borrow<str>, but that again is just more boilerplate
I'll wait with more work on the template until https://github.com/TheBevyFlock/bevy_quickstart/pull/225 is merged, as it touches quite a few files that I would like to move around, but I don't want to get into merge conflicts.
Update: managed to remove all the to_string() calls that annoyed me ๐
Pretty happy with the result.
@bitter sparrow @bright ledge I just realized something. If we register a one-shot system when we create a button, is that not a memory leak? AFAIK we cannot "deregister" a system later, but we can very well build the same button multiple times when re-creating a menu. Wouldn't the storage holding the one-shot systems just grow and grow?
It's not that critical since it's very little memory, and it increases only rarely. But still, it makes me a bit nervous.
I'm not sure
I'm fairly sure since we're storing them in a component once the buttons despawned it should delete the SystemId
so it should be fine
do SystemIds act like Handles? i thought they were more like Entity
they are not handles
wouldn't despawning the button get rid of it though
since it's attached
oh wait no
Yes, but the actual system is not stored there
it'd get rid of the SystemId but not the one-shot system entity, since we don't have relations or anything to do that kind of cleanup
I see what you mean
Now you just deleted the only way to access that memory
well you can still access with a query :p
but you'd be accessing all the other one-shots as well
Oh, one-shot systems are components?
i mean they're entities one way or another
idk what components those entities have
it might be possible to deregister the system in the function that handles key presses
pub fn register_boxed_system<I: 'static, O: 'static>(
&mut self,
system: BoxedSystem<I, O>,
) -> SystemId<I, O> {
SystemId {
entity: self
.spawn(RegisteredSystem {
initialized: false,
system,
})
.id(),
marker: std::marker::PhantomData,
}
}
So we could clean them up?
I think so
i mean
we can attach our own marker component lol
SystemId::entity() and then attach
that's clever
Now if we had relationships, the rest would be trivial
so despawn_recursive cleans it up automatically
Clever idea again ๐
I think that should work
but wouldn't that run into the problem of system id storting the entity
question is if that's too ugly for the template compared to using observers instead of one-shots
Not sure if at that point we should just switch to observers though
yeah exactly
yeah
what do you mean?
one-shots being potential memory leaks is an interesting footgun though. i haven't heard about it before
if the system id is a child and then we despawn it we run into the same problem of the SystemId being an entity and it wouldn't actually delete the stored system
oh i meant the actual system entity as a child
yeah, SystemId internally includes its Entity id
oh yeah
which you can access with a method
Ignoring the whackiness, that would be a pretty cool interaction, hehe
yeah that could definitely work
i'm personally fine with either approach
the closure / one-shot approach is a nicer API
it's also easily extendable which is the main benefit personally
Update: adding a closure directly to fn button is rather cumbersome, as ChildBuilder cannot register one shot systems directly, which means we would have to re-implement it:
let entity = self.spawn_empty().id();
self.push(RegisterSystem::new(system, entity));
SystemId::from_entity(entity)
which is very very meh
it should be able to
couldn't you use impl IntoSystem as the button type
you can do ChildBuilder::add_command
which I'm fairly sure it what register system uses
It can, but it lacks the function
exactly, that's what I meant
yeah another bevy gap
i have extension traits for all of these gaps so i forget anyways
Yes, but when calling button on a ChildBuilder it does not have a register_one_shot_system method
You need to do it manually
would be cool if EntityCommands had register_system :)
maybe a little confusing though idk
isn't EntityCommans meant to be scoped to the entity being referenced
which might be why they're not doing it
yeah, i was thinking like it would spawn the one-shot system entity as a child
Can't you get Commands back out of EntityCommands?
right you can child_builder.spawn() and then get the .commands() out of that EntityCommands lmao
and then despawn the entity because you only spawned it to access Commands, obviously /j
that is truly one of the most APIs in Bevy
@bitter sparrow I can't load your PR anymore at https://github.com/TheBevyFlock/bevy_quickstart/pull/231
yep i get that on your pr as well
Oh actually I cannot open any PRs on bevy_quickstart anymore
Also Bevy's PRs
F in the chat
bitbucket time
or just write commits into a book on a Minecraft server
GitHub back
Now I can nag y'all again about reviewing https://github.com/TheBevyFlock/bevy_quickstart/pull/225 ๐
https://gitlab.com/gitlab-org/gitlab/-/issues/425296
good luck ๐
Thanks for reviewing, @bitter sparrow ๐
Dunno if you're still on it, but I addressed all of your comments.
for sure, i'll do another pass
@bitter sparrow I addressed all of your comments and made sure to point it out when you may want to add your review comment to the upstream PR as well
ah, forgot to do the one about mod-level documentation, sec
ok, i'll approve after that
not 100% satisfied, but good enough to merge and maybe iterate later
Done
Is it alright for you if I do the game module cleanup now? It will probably cause merge conflicts in your PR, so I'll respect it if you say "no".
hm yeah i'll just update my pr
wait how do the buttons even work, without an OnPress component?
i think adding that component to the bundle was just missed
Part of #203
This makes the README.md outdated. I'll fix that in a follow-up.
oh yeah my bad ๐
I'll add it to my current PR haha
same
readyyyy
So, about our cool "make the one-shot system a child of the button" idea @bright ledge @bitter sparrow
ah
Do I, like, add an empty style????
So that it automatically gets removed with the button
ah
We could also add an ugly SystemIdLink to the button and handle it in the on_remove hook.
wait wouldn't that still happen if it wasn't a child?
The child is the actual actual system registered
That one never gets cleaned up by Bevy
So we need to ensure that somehow
who knew that having kids would be so complicated
Thanks for the addition to #1256006995656441898 message
๐ก
bad warning, unsubscribed
but what if it's a button that doesn't cause the entire menu to despawn when you press it
like a button in a settings menu
(And hope the same SystemId is not used for two buttons because two systems despawning the same entity is pure fun)
How is that a problem?
the oneshot will run the first time then be gone the next time you press, right?
passing in a closure that gets registered internally would statically prevent this tbf
that is true
no, if I remove it on Trigger<OnRemove, OnPress> it will be gone when the button is despawned (I think?)
At which point you cannot click the button
(I hope)
ah i read it as despawning inside the OnPress one-shot itself
the real problem here is that this warning is a false positive though?
i dont see why it's wrong to have a non-UI child of a UI entity
you can have a non-spatial child of a spatial entity right
I think we should also keep in mind that we may want some buttons to stay after they're pressed
if we ever add a settings menu I imagine we've want to keep the main menu
yeah, as long as we're only despawning the one-shot when the button despawns it should be ok
wouldn't we still want to keep the system though
would be re-adding it every time the button is spawned
we could avoid the memory leak without despawns by persisting the one-shot system, but that would require pre-registering them and storing them in a resource
which is a thing
As long as that one then does not itself have a spatial child again, yes
True. I think that's way worse ergonomics though.
I addressed your comments @bitter sparrow
oh wow this just panicked on my Windows machine on closing the window 
unwrap considered harmful. unwrap considered harmful. unwrap considered harmful. unwrap considered harmful. unwrap considered harmful.
this
let size = r!(window_query.get_single()).size() + 256.0;
Ah tiny_bail, my beloved.
I sneakily sneakily bloated my PR with a fix for the panic and the warning
as a treat
Doing that as well
good idea
PR ready again
this ci failure is one of a few reasons i personally use one import per line c:
i recognize that it's not the common style in the rust ecosystem tho, and not the rustfmt default
rustfmt is not really opinionated in this case
is it?
hm i think stable rustfmt doesn't know how to format imports yeah
nightly rustfmt has some options
in my rustfmt.toml:
# Unstable
group_imports = "StdExternalCrate"
imports_granularity = "Item"
imports_layout = "HorizontalVertical"
match_block_trailing_comma = true
normalize_doc_attributes = true
Yeah mine is pretty similar except for imports_granularity = "Crate"
understandable
Sometimes, my style preferences are truly just vibes based
I'll update the design doc and readme now
Your PR is the only thing missing from Alice's feedback issue ๐
working on the merge conflicts
i get a crash in despawn_one_shot_system when i hit play
oh wait
that's because i am both childing the system and now manually despawning
not better like this imo but it's w/e since i have my own template :p
oh i forgot to replace the In<(Entity, Self)> stuff, will do that now EDIT: pushed
Honestly, I think I like it now. I totally see how you come to this conclusion, but I think we've got a good compromise now.
it looks reasonable in the template, but in a real game you end up with stuff like this https://github.com/benfrankel/blobo_party/blob/main/src/game/actor/player.rs#L45
you have to use SystemState to access system params that aren't queries or resources, and then you have to clone everything you'll need out of them before doing world.entity_mut... for lifetime reasons
Using custom SystemParams is a bit advanced, isn't it?
I mean, it's not hard or anything
i mean, not really
it's not just custom SystemParams, it's anything world doesn't happen to support
or supports but not ergonomically
3rd-party libraries may also provide SystemParams
calling world.resource::<Xyz>() a bunch of times at the top of the function to avoid SystemState isn't ergonomic either anyways
anyways like i said i'm not too concerned about this personally, because i know that in my own code i won't have to deal with these shenanigans
if we think this is better for bevy_quickstart's target audience then it's fine
Can't you use resource_scope for that?
That is true
I know it's easy, I just think it's a safe bet to say that most games for this jam probably didn't use that feature
(e.g. SpatialQuery from Avian, which you'd need to do raycasts when spawning something, which might be realistic)
i think that only gives you one resource at a time?
also if you're calling world.resource_scope with a closure inside...
at that point you could just call world.run_system_once_with((id, self), closure_or_fn) and be happy :p
that is true
Btw, I left you some review comments. Nothing big.
Really curious to hear @prisma delta's feedback (this is the last task from your feedback list that has not yet been addressed and merged FYI)
https://github.com/TheBevyFlock/bevy_quickstart/pull/240, needs a review from @prisma delta as well to make sure I'm using her pattern correctly.
@prisma delta, do you think you could take a look at this over the next few days? It's the last controversial thing to get sorted out before the template is ready to be discussed with the other Bevy maintainers imo
Done
alright well we have until bevy 0.16 to improve things upstream anyways
ig there's no adequate solution that can also be considered "simple enough for beginners" in bevy 0.14
Looks like it
Since the goal is to get this under review by the other Bevy contributors way before then, I don't a reason to merge it now
Bit unfortunate for the work, sorry @bitter sparrow
Yeah. I think we can get there, and I think this is a step in the right direction
You mean upstreaming spawn_with and add?
i should probably read the bsn proposal and maybe test if this is viable first
that sounds reasonable
For the moment, I guess we go back to the variant where we don't return anything from spawn, but use a command instead of an observer?
if it's not viable, then spawn_with + impl EntityCommand for functions that take Entity as their first arg
fwiw, without any extension traits we can do commands.spawn_empty().add(player) :P
i think that might not work in all the ChildBuilder / World / etc. variants though
hold up, really?
yeah i think so. that's what spawn_with does internally. also spawn(bundle) = spawn_empty().insert(bundle)
Yep, this plus the blanket over EntityCommand seems nice
We have enough folks here that we should be able to review and merge it easily
@prisma delta I don't know if you've seen this bit of bikeshed, but I'd like to have a third opinion here
I really prefer construct_player
@bitter sparrow, do you wanna tackle that? Ping me and I'll review it instantly 
sure, after i read the bsn proposal etc. i'll do that. that might take some time though
yeah, we've got time
want to make sure i'm not doing something that will be redundant, or something that could be better
That makes sense, yeah. Later, when cart is reviewing the template, he may even have some thoughts on that himself.
I'll do a PR now for the crappy but simple version of entity spawning
Btw, could you take a look at my 2 open PRs?
@prisma delta is this what you had in mind for the simple but limited spawning? https://github.com/TheBevyFlock/bevy_quickstart/pull/242
Or would you prefer if I used a struct SpawnPlayer that the user then manually adds?
@bitter sparrow I responded to https://github.com/TheBevyFlock/bevy_quickstart/pull/239
Btw, thoughts on SFX vs sound effects? I renamed them to the verbose variant a while ago, but it's starting to annoy me, so I'd like to go back to SFX
soundtrack is verbose too, i like music better ๐ค
good idea
I'll do a rename with both
even though i will admit "soundtrack" is technically slightly more accurate
How about we name it music in the code and leave it as soundtrack in the comments?
I think readers will understand
hmm, what about the assets/soundtracks dir? assets/music?
@bitter sparrow may I also get a view on https://github.com/TheBevyFlock/bevy_quickstart/pull/240 before the SFX rename so I don't run into merge conflicts?
ok. i mainly feel like it's confusing that we now have this layer that maps path -> handle, when that's the same thing that AssetServer does
since previously it was mapping key -> handle which is different
also we could rename key -> path if we're actually committing to always using path as key (which we may not be?)
I would just do commands.add(SpawnLevel {level_data})
Alright, I'll change it in a few mins then ๐
Extension traits are nice, but they're another layer of complexity just for some ergonomics
what about the extension traits we're using for UI / audio?
i think the UI ones are worth it at least
I'd keep them both.
Yeah those at least are essential.
Yes I like that!
Yeah those don't have great alternatives
@bitter sparrow https://github.com/TheBevyFlock/bevy_quickstart/pull/241 is ready now. I wrote it assuming that my other PRs will get merged.
will review in like a couple hours
thanks ๐
Rest of the PRs should also be ready
@prisma delta once we get the currently open PRs merged, we are ready for another round of feedback. Would you prefer taking a look at it on your own again or should I ping the other Bevy maintainers as well this time?
I'll do a first pass for you ๐
Appreciate it, thanks!
Also @sinful hull since you've been following a bit along and are imo exactly in our target demographic of "wants to create games using Bevy in a simple way", feel free to tell us if we've been making anything worse through these updates, or if there's anything big missing, or we're missing documentation anywhere, etc.
(or if things feel confusing and over-engineered anywhere!)
Same goes to everyone else lurking around this channel. I greatly appreciate the feedback ๐
I gave our little collection of patterns better individual names. Feel free to bikeshed, I'm not overly attached to any names and will probably just accept whatever you suggest ๐
As I mentioned over in #general the template was really great for the jam, thanks for all your hard work.
One thing I'm may be not 100% clear on is the liberal sprinkling of #[derive(Reflect)]. As far as I can tell this isn't required, and there isn't any info in the PR for why this was necessary. During the game I experimented removing it from a few places and... nothing happened? ๐คทโโ๏ธ
That is required for components and resources to show up in debug editors like bevy_inspector_egui. Would it help if we added a comment for this on a random component? Or should it go in the design doc?
ah yeah ok thanks. I think design docs might be better, its probably in too many places to comment against each usage?
Agreed, this is better in the design docs
BTW @slender belfry have you started work on the survey at all yet?
No, sorry :/
Fair enough, just thought I would ask
I'll try and get started this weekend if you don't get to it before me.
@bitter sparrow I addressed all comments on https://github.com/TheBevyFlock/bevy_quickstart/pull/241
Also, is there anything I can do to help the other two PRs get along?
@bitter sparrow ready again. Btw, I'm tending towards renaming theme to ui_tools again, due to stuff like interaction being in there. Thoughts?
i think theme is still better
there's InteractionPalette which is visual and OnPress is the outlier
but i wouldn't rename it for just the one outlier
Yeah, that's true
should I maybe move it out?
yeah, I can see how a future review will be unhappy about a module called ui_tools only containing one submodule
meh
You're right, I'll leave it then.
i need to figure out a way to rationalize how OnPress is actually theming
maybe you play a sound effect on press ๐
Play a random animation on every press
hehehe we had the same thought
Well, trigger_interaction_sfx is already in there
And apply_interaction_palette
which are both definitely theming
Just the callback stuff is iffy
behavioral theming
@bitter sparrow good idea. I'll do a follow up in a few mins. How about having a parent field on SpawnPlayer so that we can insert it as a child of Level?
That way, I can also remove the comment about expanding the struct
Yeah, RIP EntityCommands
honestly in that case i'd rather not spawn a parent level entity ๐ค
But spawning something as a child will come up, so we should have an answer for it.
Or we just shrug and point at Bevy?
Hmm fair enough
I'll leave it as-is then
Something rubs me the wrong way about changing the screen/playing.rs plugin to just spawn the player directly
sounds like an ugly implementation detail leak
i mean personally i think it's totally reasonable
you spawn the HUD, the player, the enemies (or a "wave" entity that spawns enemies periodically or w/e)
possibly delegating some of that logic to other modules that want to take responsibility for it
so a level.rs is fine but i don't think it's conceptually required
funny
another option would be to actually include some little bit of data in there
and then the comment can be removed completely
like "scale" since we 8x the sprite
I can add the max speed
Also fixed a naming inconsistency
@bitter sparrow
Might need to do world.flush_commands() after this
Isn't that stuff done completely automatically nowadays?
between systems with system ordering yes
i dont remember the exact reason but i had a bug that was fixed by adding it here:
impl AddExt for EntityWorldMut<'_> {
fn add<M: 'static>(&mut self, command: impl EntityCommand<M>) -> &mut Self {
let id = self.id();
self.world_scope(|world| {
world.commands().add(command.with_entity(id));
world.flush_commands();
});
self
}
}
during the jam
Oh, you mean so that we actually apply the inner command right now?
i think it's for an ordering reason (relative to other commands) yeah
but i'm not 100% sure
would be nice to have world.run_command(x) == world.commands().add(x); world.flush_commands() maybe
idk it's another api diff
BTW our CI is having a bit of a struggle
Thoughts on https://github.com/TheBevyFlock/bevy_quickstart/pull/240 ?
I liked your suggestion @bitter sparrow, but I really struggled to implement them without a lot of ugly boilerplate
I think asset boilerplate can quickly become a particularly nasty part of Bevy in general
i agree. the asset system is too low level
Not as bad as rendering boilerplate; thank god we don't have any of that.
or rather there is no high level built on top of it provided by the engine
something like loading a .ron that links to other assets, loading those, and then being able to track all of that in a loading screen
the asset system is capable of that but you really have to know what you're doing, and there's gonna be boilerplate
(i literally have this set up in my jam template, but i'm using iyes_progress and it's still pretty manual :p)
Completely agree with the reasonableness of that system
Will probably yoink that for Foxtrot when I get around to it
I think at this point my vision for Foxtrot 0.14 might just be your template, but in 3D
it's pretty useful. i think it could prob be improved a bit more
lmao
(And with Yarn Spinner integration)
Yeah, but that's all just plugging in third-party libraries
The features are the easy part
The high-level organization is the hard part, imo
(that and some crate-specific hacks)
template convergence is cool though, especially if the main differentiating factors are what the templates are optimized for
like game jams vs 3d games vs pixel art etc
Yeah, agreed
the underlying patterns don't have to be unique each time
I think a world in which bevy_quickstart, Foxtrot and your template share most underlying patterns is a pretty good one for users and newcomers trying to learn
Also, give approval plz ๐
yeah, even better if the patterns dissolve into bevy ๐
ok i was gonna check the ci first
it seems the Tests job is taking 12m each time, but it is hitting the cache
the heck
not even restoring from a fallback cache, it's just a hit
i suspect we're pulling in a new version of cargo-cache with the same @v2 tag
nvm there has not been a recent release
huh
so checking the first CI run where it was slow and the one immediately before
we went from cargo 1.80.0 to cargo 1.80.1
but it seems like cargo --version is returning the same output?
wild
cargo 1.80.0 (376290515 2024-07-16)
cargo 1.80.1 (376290515 2024-07-16)
we can manually clear our cache as a workaround to repopulate it EDIT: done
do we want to rebrand KEY_XYZ to PATH_XYZ to make it explicit?
sounds good
ok, in that case also rename let files = to let paths =
also the design doc will need to be updated
done ๐
ah you did it
I was anticipating a review comment of "why do a whole iterator when it's just one entry" down the line
But I personally agree
yeah the iterator separates the boilerplate from the data
Also, this way we make it a bit more explicit that the Ducky in particular needs the pixel art settings
The iterator approach would imo require a pixel_art_paths and such
or a triple
but in my mind we would apply the pixel art settings to every image :p
Yeah, but that will definitely not fly through a future review ๐
oh i mean it would be a pair in the original list
and then it'd still be a pair after so technically not a triple
I also had this as an iterator at some point and reverted it
yeah in my own code that would definitely be an iterator
I tried to orient myself around the fact that for official Bevy examples, iterators for such things are usually avoided
But yeah, same
tbf I'm an iterator supremacist
Here's the version with iterators for the ducky
@prisma delta all PRs are merged now, we've addressed all of the concerns you noted the last time, we have addressed some feedback by others, and we updated the readme and design doc accordingly.
We're ready for another first pass from you ๐
Awesome; I'll round out my work day with a review!
@bitter sparrow I've got a tiny PR to clean up the docs dir: https://github.com/TheBevyFlock/bevy_quickstart/pull/243
Thanks!
yeah i wanted this change
I think our cache is somehow out of date?
I'll push a trivial change to Cargo.toml to force invalidation
hrrmmmm why is it still receiving a cache?
Eh, I'll just accept it for now.
It is what it is.
is it still hitting the cache but rebuilding anyways after this?
seems like it was fine
it pulled the cache from a different job, so it's a fallback not a hit
@bitter sparrow @slender belfry re https://github.com/TheBevyFlock/bevy_quickstart/pull/242, I'm trying to work backwards to find the ultimate reason "we should use commands not observers here" and I can't seem to find the reason (there are a lot of links to links so maybe I missed it).
I know it was from Alice's feedback:
I'm not convinced that spawning things like the player should be an observer; that seems like a pointless layer of indirection over just using a custom command
But I'm not really clear on the why in this feedback. Is the pointless indirection to do with performance? Or with ergonomics?
Related to the linked merged PR, it's not clear to me from the comment attached to world.flush_commands(); why this needs to be done, or what happens if this wasn't done.
All in all, if this is the recommended official approach, that's great and I'm glad to see it rather than being lead astray with bad observer patterns, but also it looks scarier than what was there previously with "simple observer code".
(@prisma delta , correct me if I'm wrong here)
The point is that the observer in question will trigger a command, which means that the flow of control looks like this:
gameplay system -> triggers an observer -> adds a command
by using a command directly, we simplify this to
gameplay system -> adds a command
Now there's a caveat (as far as I understand, I'm not entirely 100% certain on this one). If we spawn the level, we call another command in there, so the flow becomes:
gameplay system -> adds a command -> adds a command
flush_commands applies all commands added to the queue, so it becomes
gameplay system -> adds nested commands and executes them all
I personally agree that observers are preferable in this case because of better ergonomics (and I don't care about the indirection), but multiple experienced Bevy users reported something along the lines of "I'm confused why you would use an observer there; why not just a command?", so we changed it.
Exactly
Interestingly, you are the second person to report that they find the new way more scary than the observer way, so this may be something to reconsider
I think exclusive world access is scary ๐
Maybe there is a divide there between how seasoned Bevy users and newer users see things? How would you describe your skill level, @willow remnant ?
I suspect losing the ergonomics of regular systems is scary.
That's actually a good question. @sinful hull and @willow remnant, can you describe what exactly feels worse in the command approach?
I've been using Bevy since around March this year, but I'd probably still class myself as a Bevy and Rust novice rather than intermediate.
Then I am really really interested in your feedback, as imo we've been having too little feedback from this audience.
I think some of the scariness comes from just more perceived boilerplate. E.g. run_system_once_with In(config): In<PlaySoundtrack>, is all just longer and IMHO "more annoying" than it was before.
As in more noisy syntax due to multiple concepts (like In params and exclusive World access) being used at the same time?
Also, please tell us if anything else in the template seems over-engineered or too complex for the job.
Also, could you take a look at this PR and tell me whether you prefer the version before or after?
I have no idea if it's out of context to share my code, but the first pass of this template with observers looked great to me and I naively followed it (which is fine). I ended up with a bunch of systems/plugins looking like this:
app.observe(setup_player1_army);
app.observe(setup_player2_army);
app.observe(spawn_regiment);
app.observe(auto_deploy_regiment);
app.observe(auto_deploy_player1_regiments);
app.observe(auto_deploy_player2_regiments);
app.observe(deploy_regiment);
app.observe(spawn_unit);
app.observe(change_regiment_ranks);
app.add_systems(
Update,
(
(|mut commands: Commands| {
commands.trigger(AutoDeployPlayer1Regiments);
})
.run_if(input_just_pressed(KeyCode::KeyA)),
(|mut commands: Commands| {
commands.trigger(AutoDeployPlayer2Regiments);
})
.run_if(input_just_pressed(KeyCode::KeyJ)),
(|mut commands: Commands| {
commands.trigger(ChangeRegimentRanks::Increase);
})
.run_if(input_just_pressed(KeyCode::Equal)),
(|mut commands: Commands| {
commands.trigger(ChangeRegimentRanks::Decrease);
})
.run_if(input_just_pressed(KeyCode::Minus)),
)
.run_if(in_state(BattleState::Deployment)),
);
I guess you could say I did "observers all the way down" and, since seeing the updated template, it just made me wonder "oh wait, did I abuse observers, should I use commands for some of this stuff"
Yeah more noisy. E.g. before observers, I wrote a couple of one-shot systems and they are just more noisy and inconvenient. I've been meaning to see if changing those systems to observers would work. I know they'd look nicer and feel more ergonomic, but I'm not sure if they'd technically be the right thing to do.
I think much of a muchness. If there was a reason to be able to call play_soundtrack in multiple places, I guess that makes more sense. But really world.run_system_once_with(self, play_soundtrack); does itself feel like pointless indirection at a glance even if it's done to keep the system as a neat separate func. Probably just a personal nit but run_system_once_with as a name just looks ugly. I don't have a better naming suggestion so that's not super constructive.
So would you rather keep the version before the PR?
I think it's a bit early to say what is "right" or "wrong" for observers, outside of very clear cases.
Some users, as far as I can tell, are using the following principles:
- custom command for when they expect to use commands in their systems (as in
bevy_quickstart) - observers when they want to mutate existing components, react to
OnAddand friends, or need bubbling behavior - hooks for when a hierarchy needs to be built
- events for when stuff needs to be parallelized or handled in a specific schedule
I personally am currently using observers for nearly all of these, pretty much the same way as you, as I really like the ergonomics so far and don't care much about the "purity" factor behind it or the minor performance impact. This may very well change in the future, but that is my current leaning.
Actually, might be useful to share: But what led me down the path of checking if commands should be preferred to observers.
I was debugging why one of my observer functions can't find a certain UI entity from a query. I can see through my logs that the UI entity is spawned, then I trigger a certain observer, and that runs immediately and it fails to find the entity. No need to debug this here, but assuming I don't have a silly bug I just wondered if I shouldn't be using observers for this, rather I need to use commands to have them applied before my observer func can successfully run and query for that entity.
In general, Commands are currently often seen as the default and observers the exception that needs justification.
Yeah, the exact timing and order that happens between all of these concepts is fairly arcane.
With commands (and flush_commands), you can be certain that whatever you do, at the end of your command everything will actually exist in the world.
commands should be used for something that "performs a simple operation on the world"
which is what we're doing when we spawn something
If I have to pick, yep let's say the version before. But please don't change anything on account of that, I'm still a bit on the fence ๐
events should be used for something that happens, and we want to react
the fact that commands are less ergonomic to write than observers is a bevy issue
Yeah, upstreaming an API that lets regular systems be added as commands while passing In params would solve all issues
And further blur the line between observers and commands ๐
well observers effectively means running an entire schedule when an event occurs
commands do one thing
I know that, but someone just looking at Bevy code has no chance of catching that. The naming also does not help.
yeah that's a more general bevy issue where there's a proliferation of ecs tools with overlapping use cases
Definitely agreed. We have commands, observers, one-shot systems, (to a lesser extent) event readers, and hooks.
#ecs message
Oh, I remember
i also feel like observers ought to support run conditions and system ordering
aka order between two observers listening for the same event
rn you just can't
Yeah, when they first dropped I naively just added a run condition on them and was confused
at which point it will look even more like a schedule, but using an event as the schedule label instead
(At least they support piping in 0.14.1)
oh interesting
Yeah, I opened an issue and @lavish robin just fixed it like 1 hour later. I was so amazed, thanks for that ๐
observers are basically "run a schedule with an input", which you could also do by setting a temporary resource with the value of the input
Anyhoot, @willow remnant, is there anything else that caught your eye as overengineered or confusing?
Again, I'm really interested in your feedback here ๐
i mean i fully agree that World access absolutely sucks compared to systems
it feels like dropping down to unsafe
Yeah, I think we are all in agreement about the following:
Commands are conceptually the right tool for this- Observers have the better ergonomics
and improving World ergonomics upstream would be tough because of lifetime issues
which systems avoid by (behind the scenes) removing the particular things you're interested in from the World then putting them back in iirc
Unlike resource_scope, they don't actually remove them: instead, they use unsafe to split the World apart
By giving out multiple mutable pointers to disjoint parts
ah okay, ig they would need to for parallelism
"use unsafe to split the World apart" sounds pretty metal, ngl
I used the version around the time the jam started (I didn't finish my entry) and it was a welcomed template and I found it really useful. Not to harp on, but when I saw the patterns for spawning stuff with observers I was like "oh cool that makes sense, I love that", and that was the stand out for me. As above, I'm glad to iterate on it and adjust based on official best practices, so it's all good if that initial happiness goes away for the sake of doing things a better way.
I've seen the changes to SFX, E.g. now it's commands.play_sound_effect(SoundEffectHandles::PATH_BUTTON_PRESS). Maybe a nit: but I actually think you should just use sfx, seems better and SFX seems like a pretty universal term in game dev, no? It would become: commands.play_sfx(SfxHandles::PATH_BUTTON_PRESS). I think the PATH_ thing looks a bit odd compared to before. I could actually see you ditching the PATH_ prefix actually. The Handles in the name implies a path in some ways so it may be redundant. So it could go to commands.play_sfx(SfxHandles::BUTTON_PRESS).
FYI I'll do a pass on the template again tomorrow, and see if there's anything I can simplify
oh i think we agreed to change "sound effects" -> "sfx" and "soundtracks" -> "music" but we haven't done that yet :)
oh heck, I wanted to do the Sfx change yesterday and forgot ๐
I'll do that right now haha
the SfxHandles::BUTTON_PRESS vs SfxHandles::PATH_BUTTON_PRESS is due to a concern that the former reads like you have an actual Handle
when it's actually a string with the file path to the asset
it is wordier this way. it would read best if it was SfxPaths::BUTTON_PRESS somehow
yeah that used to not be a concern when we had a dedicated SfxKey enum
yep
I mean, I could easily take the const out of the handles and into an own struct
Yeah that's a good one to take a stance on, too. E.g. in my own I wasn't sure if background_music, bgm, soundtrack, or music was what I wanted to use. I know this is also a nit and YMMV, but it's kind of nice to have a semi-official stance of the term.
Dunno if that's worth the mental overhead of two structs for the same concept tho
true. imo "soundtracks" is technically slightly more accurate than "music", because it specifies that it's the main music that plays in the background
but i don't think it's worth the extra 6 characters
Some things read a bit weird when I used the word "music" in my local branch
So I opted to use "soundtrack" in comments and "music" in the code
But then I realized the path on disc was "assets/soundtracks" and that made more sense to me than "assets/music"
ik we chose not to use the ImageMap naming because of potential confusion with texture atlases, but ImageMap::DUCKY would be fine imo
Didn't consider "bgm", that's neat too
Ooooh I forgot about that
I like how ImageHandles is explicit about holding handles and not images though
ImageMap sounds a bit like it's holding images
that's true
I'm a bit cautious here because I've seen beginners struggle with handle vs asset a lot
so I want to be extra explicit on that
i just like that bgm is the same length as sfx
Minor thing, not sure if it was just me, but I seemed to need to add "rust-analyzer.check.command": "clippy", to my .vscode/settings to match what CI was checking. I think I pushed a change to GH, clippy failed but there was no issue in my VS Code until I added this setting to make the template also use clippy. I was going to make a PR but wasn't entirely sure if it's the right call or just a me thing.
Yes, that is true. It's set to check by default because clippy is way more expensive to run
bgm passes the duckduckgo test as well. the results are all background music
that's cool!
I kinda like having long names on disk and short names in code. Thoughts on that?
Because bgm and sfx kinda blur together when I see two directories like that next to each other
But in code, these are never in close proximity
i can understand it, idk if i would do it myself
I just have bad memories of exporting dozens of assets when doing some content passes and having to make extra sure I'm placing them all where they actually belong ๐
We should maybe add that to the tooling document
oh right. yeah i just push a quick clippy warning fix commit if i get an email about failing CI
it's more expensive to run + it doesn't always catch actual errors, often it's like style stuff that you can fix later
wouldn't hurt to mention
I think I'd personally just use the same thing in code and file names. Again, SFX is universal so if I saw assets/sfx I would know what it means. If I see assets/bgm and I don't know what it means, maybe it indicates BGM isn't a universal enough term and so is a bad choice. But yeah, I'm impartial here. If I had to pick, I'd probably go with "bgm" and in code I'd just have a comment on the main type saying "Background music" so that users have a way to learn if they are confused. Anyway, I defer to more experienced people here.
i'm personally fine with either "music" or "bgm"
but at the very least the module name has to match so it would be music.rs or bgm.rs
I'll do a separate PR for SFX and BGM
yeah that concern is more about a poor sound engineer exporting 30 soundtracks and SFX and having to click the correct 3 letter directory each time on export ๐
that could make a good jam game
the directory names get shorter and shorter each level
Huh, our SFX dir is already called sfx
Apparently it was not renamed to sound_effects
Here's the SFX rename
hurray, the cache works again
hmm?
Ah, I see what you mean. I was referring to nvm thenassets/sfx ๐
saving 28 characters in one line
hehe
way better for autocomplete too
the trait methods
do you have / use ripgrep?
i would do like rg -i 'sound_?effect' then ctrl+click the linked files
well this is a small refactor so i might not have done that here
Usually do the same, but in the regex find/replace window of VS Code
But yeah, also didn't think of it here ๐
there, fixed
Two missed occurrences SoundEffectCommands, SoundEffects (sorry didn't get to review in time)
can throw that in with the soundtracks rename
On it, thanks ๐
this reminds me of my Ssa = SpritesheetAnimation heh
except that one is definitely not standard
I hate to even say it, but is it "sprite sheet" or "spritesheet" ๐
hm bevy has it as SpriteSheetBundle
SheetOfSprites
s18a
perfect
ready now
I somehow have a feeling that BGM is a bit too rare to pass future reviews and we'll have to revert, but I'm ready to throw those dice 
this is how you negotiate
soundtrack -> bgm -> music ๐ค
i think there are some missed cases, follow up? IsSoundtrack, PlaySoundtrack, soundtrack_handles, soundtrack_query, soundtrack_key
How am I this bad at a simple rename ๐
You'll get there for the 3rd thing I make you rename.
naming things is the hardest problem in programming
so it stands to reason that renaming is just as hard
Also includes the rename suggestion you had in the last PR that the automerge swallowed
wanna rename Image to Img next? ๐
The only logical next step is to then rename asset to ass, for the three letter consistency
ui -> gui
bev
nah it's bvy this has already been done
at least src, lib, and mod are already there
Ah, there we go
i love that it's still using query.iter_mut() instead of &mut query in the sample code
hehehe
Yeah I'm not sure this is useful? @lament horizon
Honestly, I don't know. I just reflect everything available and assume that's good? ๐คทโโ๏ธ
@bitter sparrow is it possible that your PR is using "native" VS Code snippets while I'm talking about dedicated rust-analyzer snippets supported in the rust-analyzer.completion.snippets.custom key?
yes i believe so
rust-analyzer has its own little snippets implementation it seems
because vs code wouldn't know how to make "requires" work in rust (or expression-scoped postfix snippets for that matter)
do we want to use rust-analyzer snippets for this?
Pretty sure that would be better, yeah
I'm off to bed now, but I'll take a look at what you come up with when I wake up ๐
alright cya
It basically makes the Debug output of a dyn Reflect use the concrete type's Debug impl. In general, there shouldn't be much of a difference in the output. The main difference comes when a type (or one of its nested types) has either a custom Debug impl or when some of its fields are marked #[reflect(ignore)]
There's even a PR to deprecate the attribute and have it automatically use Debug if available , but personally I'm hesitant to add autoref specialization magic to bevy_reflect
For me the code seems less readable and ergonomic. The previous mental model of "triggering a spawn" feels more in line with what I'm trying to do.
I think as I said elsewhere the code here feels more indirect even though under the hood it's the opposite.
Warning personal opinion: For things like this that aren't on the hot path I guess I'd usually favour readability. Having said that in a game jam id likely be happy to keep whatever's in the template so I don't feel like it's a big deal.
I've been using bevy since 0.3 (I think?) mostly sporadically for game jams. I don't think I've ever written a "world" system FWIW.
And now I am very late for something so I should get off discord ๐คฃ
@bitter sparrow Fix for the caching bug with the new rust version: https://github.com/Leafwing-Studios/cargo-cache/pull/26
so i'm curious, i wasn't able to find any changelogs / release tag / etc. for cargo 1.80.1
is it just 1.80.0 + rustc version bump?
That's what I'm assuming, that it always matches the Rust version, but the commit hash and date is of the cargo crate itself
i was expecting the fix to be to include the entire cargo --version string which would catch the 1.80.0 vs 1.80.1 diff
Right, I wasn't sure if that works for all nightly cases as well
ic
What would you think if I keep the part about including rustc --version, but remove the part that only includes the part in paranthesis?
so the full cargo --version and the full rustc --version?
it sounds reasonable to me on a surface level, but it really depends on how exactly those strings change
i'll do a little bit of digging first
True, we might get some unnecessary cache invalidations depending on how they are determined
This whole caching thing is so cursed, I never thought that we'd run into so many edge cases when I started setting up the action lol
$ cargo +stable --version
cargo 1.80.0 (376290515 2024-07-16)
$ rustc +stable --version
rustc 1.80.0 (051478957 2024-07-21)
$ rustup update
$ cargo +stable --version
cargo 1.80.1 (376290515 2024-07-16)
$ rustc +stable --version
rustc 1.80.1 (3f5fd8dd4 2024-08-06)
just ran this on my own pc
it seems like the version number is intentionally in lockstep even though cargo itself didn't have a point release
but rustc did have a point release yesterday
honestly could probably get away with only using rustc --version hash
actually idk. would they do an empty rustc point release to fix a bug in cargo?
but anyways since they update together, i don't think it'll cause unnecessary cache invalidations
it might just make the cache key more verbose, which is probably fine
i found an example where they bumped the entire rust version only for a single cargo bug fix: https://blog.rust-lang.org/2023/01/10/Rust-1.66.1.html
also this doc has the full changelog for 1.80.1: https://github.com/rust-lang/rust/blob/stable/RELEASES.md#version-1801-2024-08-08
ok my conclusion is we want both rustc and cargo hashes but not the version numbers
which is what the pr already does :)
did not end up doing this today, will do tomorrow
Got it. My takeaway from this is: we need to have better command ergonomics by 0.16 or go back to observers.
@bitter sparrow @bright ledge today, @limber dragon reminded me that calling .observe directly on EntityCommands was a thing, which I totally forgot.
I changed our little OnPress pattern to use that instead: https://github.com/TheBevyFlock/bevy_quickstart/pull/249
ooh
Yes, this pattern is really good ๐
I think it might be worth pointing out the SystemId method because there are some things that the observer pattern can't do but otherwise this is really cool
also thanks for pointing it out
Hmm? Which limitations would that be?
i like that a lot
I likely wouldn't have found it otherwise
I don't think you can return things from them
and in my case I don't think you can store them like SystemId's
You can, as long as you pipe it into something else ๐
I'm pretty sure running systems manually returns the system output though?
yes
I'm missing the point then
that's something I use to return the next bit of dialogue from my buttons actions
I wasn't sure if I observers could do that
ah, i see
Only if you add that to a resource or something:
fn spawn_button(mut commands: Commands) {
commands.button("talk").observe(hello.pipe(store_dialog));
}
fn hello(_trigger: Trigger<OnPress>) -> String {
"Hello there".to_string()
}
fn store_dialog(In(dialog): In<String>, mut dialogs: ResMut<Dialogs>) {
dialogs.append(dialog);
}
does the observer entity despawn when the button entity despawns?
The observer is just an entity, so in theory, you can store that. That said, getting the actual Entity of the observer is a little bit of a hassle.
not if you add it on the entity its observing directly, Observer is just a component
I'm omitting raw API
TIL
and it still technically has Entity
it also won't work in my case because I need to spawn buttons after I create the system
If it's just a component, I suppose?
.observe() does create a new entity, but you can also technically use Observer directly (edit: but you probably shouldn't, see Mini below)
I think
so the current implementation in the pr would still be a memory leak?
I'm not entirely clear on under the hood becy
that is... a good question
I'll investigate
I've talked with James about this, and attaching observers by hand can lead to unusual problems
while it's totally valid, I wouldn't recommend using it unless you have in-depth knowledge
which most users dont
i wonder if you could attach the one-shot system's components to the button entity itself too
I'm pretty sure observers are despawned when they don't have active sources anymore
from Bevy source
// Despawn Observer if it has no more active sources.
if total_entities == despawned_watched_entities {
world.commands().entity(e).despawn();
}
and docs
If all entities watched by a given
Observerare despawned, theObserverentity will also be despawned.
This protects against observer "garbage" building up over time.
it's funny seeing despawn and knowing it means your game will crash if you add a parent or child to that entity ๐
Just checked in practice. You're right, no leak ๐
that reminds me, observer API still doesn't return the Observer entity in some(?) cases
i dont remember the exact issue, but it was pretty inconsistent
(According to this highly sophisticated leak detection device)
fn valgrind_at_home(query: Query<Entity>) {
let count = query.iter().count();
info!("Entity count: {}", count);
}
there's a diagnostic plugin for entity count also
TIL
who needs valgrind
Not me 
I really like how template evolved and now provides a very nice feedback to a lot of Bevy API
this template for sure makes it to the bevy ui
Totally agreed. It's a good way to dogfood Bevy.
@agile dirge I'm struggling to implement a function returning a closure according to your suggestion. Could you help out?
sure
thx ๐
let my update my template and ill see if i can get it working
that seems so much nicer...
fn change_state<S: FreelyMutableState>(
new_state: S,
) -> impl Fn(Trigger<OnPress>, ResMut<NextState<S>>) {
move |_trigger, mut next_state| next_state.set(new_state.clone())
}
i was ๐ค from having it the exact same line footprint as original
and then i had to add move and it reformatted itself
I'm still compiling to see if it doesn't break at runtime
is the clone necessary since you're moving it?
clone is necessary because it's not an FnOnce
ah
move moves the original into the closure data
.clone() makes a new copy for each execution
got it thanks
TIL about FreelyMutableState
๐
should just be one type of State
yeah
will get there eventually
yup
I'm a bit torn. On one hand, I myself would definitely want this. On the other, I can already see how this will not fly when a Bevy maintainer makes a review pass for "overengineeredness".
Using the helper function in one place as an example and not in the others feels... morally wrong?
I'll have more time again starting second half of next month
Keep it in a comment then ๐
Yeah while this works fine if you only have one observer component (as that's how all the normal observers work) or each observer component is disjoint, it starts getting real funky if they overlap (since the entity id is used as a key in the observer cache) and breaks down entirely if you have two observers with the same bundle type.
How about adding the entire pattern to the design.md?
I feel like we have more freedom there.
sure
@limber dragon FYI
so it's fair to assume Entity is an identifier for the observer
like actually actually, not a coincidence
Yep, ideally every place we need a unique identifier it should just be Entity, a lot of progress is being made in that direction
that mostly implies everything as entities, which I'm all for
how about ComponentId is that also going to change to Entity?
components as entities is a thing, flecs has it
There could still be a ComponentId type but it would just wrap Entity
Just one step before relations
I'm not sure if the implication of "unloading" a component is something we want
but holes like this can be said for everything basically
It needs to exist for relations to exist, not to get too offtopic for this wg when we have a relations one
Since a pair of (ChildOf, entity) can be added effectively as a component and will stop being valid when entity is despawned
But yes in general you shouldn't be despawning components
@agile dirge your function works perfectly, thanks ๐
Added it to the design doc: https://github.com/TheBevyFlock/bevy_quickstart/pull/249/commits/4529b0fb7a9cd9fbd0a372f85952560ebd022d37
can't wait for new ui to land so we can replace Interaction
buttons that act on mouse down ๐คข
hover and press are disjoint but they're mutually exclusive with Interaction ๐ซ
@bitter sparrow I addressed your comments
approved
fyi signing for macos is going to get more important, probably before next jam: https://developer.apple.com/news/?id=saqachfa
In macOS Sequoia, users will no longer be able to Control-click to override Gatekeeper when opening software that isnโt signed correctly or notarized. Theyโll need to visit Systemย Settingsย > Privacy & Security to review security information for software before allowing it to run.If you distribute software outside of the Macย Appย Store, we recomme...
I could have been control-clicking this whole time?!
uh yeah ๐
I also felt like an idiot when someone first showed that to me ๐
That sounds like such a hassle ๐
You see, by using an old Intel macBook, I cannot get that update in the first place, enabling to to ctrl-click forever 
yeah, which makes it a good candidate to be "taken care of" by the jam template ๐
I noticed the windows builds from the template also came with runtime warnings
Bleh
I hope some CI and packaging wizard swoops along to fix it
That stuff is so annoying to fix
Yeah, agreed, although I suppose the user still has to create a macOS developer ID on their own
Those are just regular old builds. Not sure what Windows expects?
I know I have fixed it by creating an app installer in Foxtrot, but that is such a huge amount of config lurking in some deeply nested directory
I wouldnโt want to replicate that if possible
ok so rust-analyzer snippet isn't gonna work
there are three supported scopes: expr, item, and type
the default scope is expr
none of the scopes support top-level code like defining a type outside of a function
Hmm? But how does my plugin snippet work then?
which plugin snippet
Wait
"rust-analyzer.completion.snippets.custom": {
"plugin": {
"prefix": [
"plugin"
],
"body": [
"pub(super) fn plugin(app: &mut App) {",
"",
"}"
],
"requires": "bevy::prelude::*",
"description": "Create a new Bevy plugin",
"scope": "item"
},
}
(I omitted the rest of the default snippets)
this works for me when entering plugin in a new file.
okay item scope works i think, vs code / rust-analyzer is really bad about updating to a new version of the snippet when settings.json changes
have to fully close and reopen IDE to make sure it updates
restarting rust-analyzer extension is not sufficient
changes to bevy.code-snippet were processed immediately on save otoh
i get a warning that the snippet is invalid after adding "requires": "bevy::prelude::*",
brilliant
you sure this works for you??
It adds the import
weird
I think it's fine to use the regular snippets then
well why does it work for you but not me though
is it a false warning?
I'm on macOS right now, but I remember getting a similar warning on Windows, even though everything works fine
nah it doesn't work
that doesn't seem to be using requires
It is the exact thing I posted above
are you sure your vs code isn't using an old version of the snippet?
Yeah, I have it since like a month
I have nothing else related to snippets in my settings
what rust-analyzer extension version? i'm on v0.3.2062
even when closing and reopening vs code completely?
yep
weird ๐ฅด
Where the heck is this being cached????
Yeah, let's stay clear of the rust-analyzer snippets
Seems haunted
another thing to check, if you use plugin snippet lower in the file, will it put the use right above the fn plugin?
or at the top of the file
yep
Looks like it's a regular old VS Code snippet then
that does not appear in my settings
great
yeah i tried replacing bevy::prelude::* with bevy::prelude::App
and it put the use at the top of my file successfully
actually somehow it even knew to import it from bevy::app instead of bevy::prelude
so ig requires specifically supports a list of items that must be in scope, and it knows how to find the path where they're originally defined
so no glob import
AHA! I found the cache / settings
ah it was in there?
well we can still use rust-analyzer snippets, we just can't have it auto-insert a glob import
in this case we're not currently using any of the additional features that rust-analyzer snippets support compared to vs code snippets
but there might be a use case?
I'm currently so skeptical about rust-analyzer snippets after this that I'd prefer VS Code snippets
those at least are guaranteed to work by VS Code itself
We can still change them to RA snippets if needed
But I'll approve a PR doing either
okay
anyways we can have plain text snippets as vs code snippets and if we later want a rust-analyzer snippet
we can add one while keeping the old snippets as vs code snippets
updated pr
Ah right, also a possibility
In the end, I'll trust your judgement on this ๐
huh, you removed the descriptions?
yep
fair enough, I guess they don't add much to such short code
my vs code is being really weird about the terminating newline
