#bevy_trenchbroom
1 messages · Page 3 of 1
maybe bevy_trenchbroom is exporting geomtries with some kind of offset by mistake which makes geometries intersect?
just separating them by 0.125 (the minimum trenchbroom grid value) the issued is fixed
so it indeed screams to me like an overlap problem
@foggy glade just a heads up, Discord doesn't tell me when people post messages in here, so you should ping me in cases like this
If you make a minimal example and look in/send the map file, we should be able to see if a half-space-defining triangle is slightly offset like 0.0001
If nothing looks wrong there, quake-util and BTB imports geometry at double-precision, but by default Avian will convert to single-precision. If you aren't already, try setting Avian to use f64s with the features ["parry-f64", "f64"]
Also if you don't know #[*_class] implies #[derive(Component, Reflect)], but if you're doing that to be able to more easily tell that the type is a component at a glance I understand that
Also also you could just scale down all physics objects by a very small amount on spawn as a workaround
This is what I did, I can post that minimal example to github
so that you can take a look into it, but I've been fiddling with more kinds of towers and it just doesn't happen
so idk, maybe it was a really weird edgecase
@urban zealot I don't know if I've got bad or good news:
It's not happening anymore, so now I'm not sure what was the cause. 🥲
I saved the .map file where the error happened but opening it now everything is stable
However while experimenting yesterday I coded something that you might be interested in implementing into bevy_trenchbroom
While trying to get stacks of rigidbodies to behave nicely Jondolf told me that cuboids might work better than convexhulls (don't really know why, I guess because of the simplicity) so I coded the edge-case so that if an imported solid_class is made up of a single brush that is also a cuboid, instead of generating a convex hull it creates a cuboid collider with its dimensions.
These towers have been generated by bevy_trenchbroom, no convex hulls 🙂
Oooh, yeah if you hand over the code I'd be happy to stick it in!
I should be able to put in the convex_hulls compound collider so cuboid colliders can exist in the same entity as convex as well!
Yeah I think that would be a lovely optimization 🙂
too late already implemented it :)
@foggy glade Give main a try
I also see you're adding the colliders afterward through an observer, you should be doing this through a spawn hook (hooks(SpawnHooks::new().convex_collider()) or set TrenchBroomConfig::default_solid_spawn_hooks) as it has direct access to the double-precision brush data. It's also where I implemented your idea
fuck
well at least I gave you the idea
hahaha
hope you had fun doing it 🙂
this was my version
chatgpt was of great help lol
and then I just grab the brush info and hand it over, which is a bit verbose but tidy
now it will probably be much much easier hahah
Is there a difference between both approaches @urban zealot? The reason I'm doing it on observers is to be homogeneuos
because I can add the convex hull with the spawnhook, but I cannot add arbitrary components
with arbitrary logic
maybe I should be using another mechanism instead of observers? Can I invoke a system with spawnhooks?
besides, is there any chance you might add a parameter that allows for scaling down the colliders just a tiny lil bit? in order for them to not touch/overlap when put next to each other.
Something opt-in ofc
although it works perfectly (thanks for the quick response ❤️) I really need this "margin/threshold" thing for it to work with avian...
the thing is that if the colliders are touching they won't be put to sleep, so I need them to be just a tiny bit separate
Redirected this to Avian, and looks like sleeping is only a thing for touching dynamic rigid bodies #1124043933886976171 message
Since brushes are supposed to be static geometry, this should not be an issue, right?
Spawn hooks run in the scene world on load (async), and have better access to the map source data
You can add arbitrary components and logic, internally SpawnHooks is just a Vec of functions, use .with(...) to easily add a component, and .push(...) to add a function to the Vec
It does have the limitation that all components added in there must have #[reflect(Component)] so they can be spawned with the scene, I feel like either Avian or Rapier had trouble with that and rigid bodies, but I forget which
Ah, I didn't even think about solving for rotation, my implementation only works for axis-aligned cuboids
I probably won't worry about it for now
well, brushes are static geometry as long as you keep them that way 😝
I'm using brushes to define arbitrary shaped (although cuboids for now) dynamic rigidbodies
I'm probably going to use a mix of:
- brushes for generating the static "base" of the level
- brushes for generating the interactive/destructible parts of the level
- point classes for "props" or basically pregenerated meshes
at least that's the plan for now
still interested in my PR then? 😀
Tried it and saw that even some "native" basic bevy components lack this, such as MotionBlur 😦
not loving the idea of having multiple types of spawners, so for now I think I'll stick with the observer pattern and just resource to spawnhooks whenever I need something trenchbroom specific
Not loving it either, but I haven't been able to find or come up with anything else that can do all the things SpawnHooks has to
Also, with the observer pattern, saving and loading might be a bit messed up because loaded entities might have components unwantedly overridden by an OnAdd, but I haven't made a save/load system with BTB yet so I haven't encountered this
If you want to add support for rotated cuboids, I won't stop you :)
@urban zealot tada!
Textures can now be sent to the navmesh editor 🙂
This is a TrenchBroom test scene. Making sure at every step that it plays well with BTB!
I now have serialized versions of Mesh, Image, and StandardMaterial. Dunno if any of that may be of use to you too
Pretty cool! I'm so glad an official editor is picking some steam
If I were to make BTB now, I'd probably not, and instead work on making Bevy's level editor has nice to use for hard-surface geometry as TB
Disclaimer, this is not the #editor-dev prototype 😄
I could have made it part of that, but I would prefer it to be usable right now with pre-existing level design tools like BTB, so I made it work with remote inspection
Which is not yet part of the prototype
But I hope I can upstream this editor too, as a dev tool, until it becomes part of the editor prototype
@rapid turtle is interested in that!!
They asked me to detail what a brush-based workflow in the editor would look like and are on board with adding that at some point 🙂
Here's the issue for dumping info: https://github.com/bevyengine/bevy_editor_prototypes/pull/217
@urban zealot if you feel like it, I believe you could share a lot of knowledge in this regard 🙂
BTB?
bevy_trenchbroom
Ah
After seeing Source 2's Hammer, I wonder if there would be a better option than brushes actually, in my experience the main thing that TB gives that something like Blender doesn't is lessening the friction between seeing a space in your head and placing down geometry
Still theorizing what that could look like though
I would be happy to share anything I know!
I haven't user Hammer 2 yet, do you have a quick rundown of its differences with Hammer 1?
Valve ditched BSPs, It's completely mesh-based, kinda blurring the line between world geometry and props
Then come say hi in #editor-dev every now and then 😉
oh whaaaaaat
wow, that must have been an engineering challenge
But yeah as long as you can draw geometry quickly and see it in action, I'm also not attached to BSPs and brushes
Just didn't think there was technology like this 👀
(am realizing i just woke up and conversation is hard, i'll come back later if i can formulate my thoughts better)
sure 😄
I think something voxel based is the future where you can just sculpt right there.
Many people say "just use Blender" but navigating in that app with the camera sucks, same with every other 3D modeling software.
Unreal is trying to phase out their BSPs too but tbh I think I disagree on it.
I think a brush based workflow is great and I think they will find it is a mistake to phase out.
But it just needs to be modernized. Basically what I said, you draw a wall, then you can sculpt it
Then convert it to Nanite/Meshlet
And i say voxel because I should be able to just start punching holes in it without having to think about topology.
I want to be able to place down a pillar and start carving chunks out of it to weather it.
Voxels are also easier to work with programmatically. For example you could just procedurally weather things.
And then ya like I said you have a baking process in the end that converts it all to actual meshes, ideally high res ones like a Nanite/Meshlet system allows.
For what it's worth, Unreal is phasing out BSP but it's being replaced by in-editor modeling tools, so I guess it's the same philosophy just more modern.
Please keep me in the loop with this discussion, have lots of opinions!
For the voxels im thinking something very high resolution BTW, not Minecraft lmao.
Substance 3D Modeler is a good example of the workflow I am thinking. It's basically doing all the meshing on the GPU, so it's highly performant. But when you export it, it's converting it to a proper mesh with options to decimate it and stuff.
Then youre not bound to just making walls. You can make terrain, and not just heightmap bound terrain but caves, cliffs, hoodoos, whatever!
The real caveat is that it means larger files. But my mentality with that is, if you need the detail your files will be large, if youre just making Quake-like geometry then the meshing process would be efficient and thus the files would be small.
We should probably open an issue on the editor prototype 🙂
Since all in this channel are interested in a brush-based or brush-adjacent solution landing in Bevy and the editor folks are broadly on board
We could add some of our thought to an issue so it’s easier to reference in the future
honestly even if it's just basic basic stuff, being able to make stuff in-editor without jumping around between programs is important at the very least for early level design
but ya like I said I think it can be taken further with the intent that you can make a full detailed level all within the editor
If we actually did go a sculpting capability route, could look at baby_shark for that.
It has a bunch of meshing algorithms, decimation, voxel remeshing etc.
There's also the csgrs crate
Ive dipped my toes in this area in the past and personally I want high poly capabilities, but thats when you need to start doing work on the GPU which I think likely complicates things
But ya there's plenty of arguments to make that if you need such detail just use Blender.
Im biased, I think I value doing everything in editor more than most
You know blender has like 3 navigation modes right?
Like they have all 3 of the major methods
They all suck imo
Actually, the walking is cook
Cool*
But like have you actually tried to build a full map in Blender?
Although now that I think of it you could probably script what you need
Ive never been good a scene building most my blender time was in the node graphs
Ah. Yeah its not good for it. Very good for making individual props and what not though
Can confirm that Blender really doesn't want you to create levels in it, no matter what you do :/
There's definetly improvements to be made but blender does have everything needed to make levels
Ive used far worse
Godot and the Creation kit both have far weaker scene creation tools yet people love em (well not CK.. People hate CK.. But amazing stuff in it)
You're right, you can definitely build something in Blender, as well as Godot and co. if you want
It's just not something I personally want to go back to since I've started using TrenchBroom
Definitely a question of taste as well
I'll have to take a look at trench broom some point
I can imagine people who work in Blender all day anyways really disliking the idea of switching programs for level design when they can do everything in one program
Which is totally valid
There's an elegance to not having the friction of exporting and importing models around the place 🙂
Let me know if you need help 😄
@urban zealot I just migrated to the newest BTB and wow! You improved the API a lot! Really good work, you should be proud of yourself 😄
Awe, thank you! I am currently in a maintenance-only mode for BTB, so I'm glad it's up to your standard!
Yeah I don’t think we need any fancy new features, it’s good as-is 🙂
This is an interesting concept
With the different behavior based on degrees of axis-alignment, I'm assuming things wouldn't be on the same grid; a diagonal wall would be a different voxel volume than an axis-aligned one, kinda like how it's done in Teardown.
If that's the case, assuming we're going to be meshing (probably before an optimization pass) with a technique like duel contouring, since we would have to generate an SDF for the voxel grid anyway, we could expand it to be an SDF modeler with a voxel volume as just a possible SDF
I'm not too knowledgeable on the pros and cons SDF modelers though, all I know is that they exist and are cool
One thing I've always wanted in both brush and mesh modeling is the ability to be able to say, just place a doorway prefab in a wall, it'll automatically make a hole, and moving/removing it automatically moves/removes said hole
This would work really nicely with the composability of SDFs
SDFs mentioned @granite hollow
SDFs?!
I was looking at crater-rs today to see how easy if doable at all it is to get working with Bevy. TL;DR is it generates the marching cubes on the GPU with webgpu, vulkan, metal support. And then you can extract it on the CPU.
Might be an uber fast way to generate these things and then possibly run them thru some kind of mesh decimator.
Definitely some unanswered questions in this area
Have only read stuff tho, havent coded it
In this part of the server, localized entirely within #1359582967613100282 ‽
Hey, we like making maps. Hoorah
Is the goal to have a non-destructive workflow, or just use the additive properties you normally see with voxels?
There almost certainly is, there was a tiny voxel game I found called Meor that generates meshes every frame on the GPU, and it is super fast
My goal is more of the prior
Hmmm, yea want to keep a tree of operations around then rather than actual voxel values ... Then ideally have that be calculatable on the GPU
I remember there being some funny tricks to contain every part involved in the CSG to only the area it has influence over which could speed things up too
(+partial rebuilds of the mesh maybe?)
ya make sense
although I think being able to rasterize is important too but should not be the expected workflow
I mean you could always rasterize it later and give up the non-destructive properties
still learning, been reading up on it a lot today
Hehe, BTB 0.9.2 with the optimized cuboids uncovered a bug in rerecast
had to do a new breaking release
Great that it happened on that specific PR and I was able to diagnose the problem! Would have been annoying to randomly run into this one day in some random project 🙂
ok i took a look at trenchbroom tho i dont really see what it offers? it looks like a fairly classic editor focused on mesh edits
It's a fairly normal brush-based editor. If you look at Radiant, Hammer (1), DromEd, etc. they will all be similar
brush-based workflows are not inherently better, they just offer a different set of tradeoffs compared to prefab-based editors or modelling software 🙂
In particular, they allow you to prototype things extremely quickly, if that workflow vibes with you
Sec
This is for example how you create a fairly simple corner in TrenchBroom
there's a lot more that you can do, but that's the basics
for example, this scene in Foxtrot was made with TrenchBroom
Note how the brushes here are polyhedra, e.g. the bevels here
You of course don't need a brush based editor for this. You could also create this in a modelling editor like Blender and then import it as a prefab. Or your prefab editor offers modelling capabilities
But a brush-based editor will make this specific workflow of simply drawing your level out of convex polyhedra extremely easy, which is great for prototyping. I can whip something up for grayboxing in seconds. If I don't like it, I can change it in seconds again, all hot-reloaded (no need to e.g. reexport stuff from Blender)
Again, you can have this with a prefab-based editor too, it's just a different set of tradeoffs 🙂
And for some people like me, these tradeoffs play right into the kinds of levels we wish to make, enabling us to create things really quickly
Here's for example the developer of Blood Thief talking about how he uses TrenchBroom: https://www.youtube.com/watch?v=DMJ7i4nuMVA&t=297s
In this Devlog I talk about how I'm using Godot and Trenchbroom to make levels inspired by games like Quake!
➤ WISHLIST BLOODTHIEF ON STEAM: https://store.steampowered.com/app/2533600/Bloodthief/
➤ JOIN THE DISCORD: https://discord.gg/aU5naj2fgY
Welcome to the latest video for Bloodthief: My Retro first person melee action game made wit...
Note how he uses it to quickly draw little zones and areas that trigger things 🙂
And at the risk of repeating myself, this is not something unique to TrenchBroom, just something that is really frictionless to do in that editor.
wait a damn second
This is just blenders blockout tool with a texture added!
note im not using any shortcuts in that
yeah it's similar
I already had that in my features wish list lol
trenchbroom does feel way nicer than blender for this sort of blocky design ime
Some noteable differences that TB has:
- grid snapping
- textures aligned with the world (so two blocks next to each other have textures flowing seamlessly)
- textures set to repeat
- Can extrude blocks out of other blocks (again aligned to grid)
- each face has a different texture
- Can easily copy-paste textures across faces of different objects
Again, you can certainly set your Blender up to emulate all of these
But I kinda want to just work on my level instead 😄
mhm
blender's out of box experince doesnt focus on that
but it does have most of that if you set it up
but safe to say we can def have brush tooling
here's what I mean
that would be really really really cool 
seriously I would pay money for a brush-based Bevy editor 🙂
mhm and we could improve on this... the texture map adjustments couldve been a simple shortcut + mouse grab/scroll to resize and move
not just copy the workflow but accelerate it.
yeah totally!
@rapid turtle here's something else you may be interested in
The cut tool works pretty much like in Blender, with the catch that it also is always grid-snapped
One cool thing to note at the end is how I cal alt-click the texture to align them with another
Note how in the last few seconds, the wooden board texture aligns across faces
That is a pretty widely-used feature in brush-based
what determines it? as you manip the mesh it just starts auto moving to the mesh
is it based off the texture? assuming direction is right side up oriented
I shift-click on a face to set it as the "reference"
Then alt-click on another face to make sure it aligns with that reference
hmmm
there are also different settings for how to lock the textures
But that's less important
hmm i see
there's also alt+shift click if you want the projection to be relative to each face
http://born-robotic.net/spog/thumbnails/dragapplytexture2.gif
holy crap that embed failed
Oh wow that's cool, thanks for showing me 😄
@urban zealot I noticed the CI was broken, so I fixed it 🙂
@rare chasm you mentioned something about bevy_trenchbroom's scene hierarchy
Did I understand you correctly in that you suggest adding a child entity to the scene that itself contains the rest of the entities?
my idea was basically to allow scenes to setup relationships with the "owning" parent of the scene.
so a scene would be Scene {world: World, parent_id: Entity } and when spawned into the main world, the entity mapper would map all references to parent_id to the parent under which the scene is spawned.
then a scene loader like gltf could internally set up all the entities with AnimationPlayers with an AnimationPlayerOf(parent_id) and when spawned, an AnimationPlayers([...]) would automatically be inserted into the parent entity. this means "spilling" some parts of the scene out, which might be weird/bad, but I think as long as it's just relationships and not arbitrary components, that's fine.
I’ll have think about this before I really understand it, but bevy_trenchbroom can easily be changed to better accommodate your plan if necessary 🙂
I don't think my idea will work with bsn scenes currently
so it's probably not the right solution
@urban zealot I just opened https://github.com/bevyengine/bevy/issues/20987
Could BTB also implicitly load the scene from the .map and .bsp files?
I don't see why not! :)
@urban zealot you may like this!
I managed to implement path corners using relations 🙂
every target you set on an NPC results in a Target(Entity) relationship
And that target may be a path corner
path corners themselves can have a NextPathCorner(Entity) relationship to the next one
Nothing fit for upstreaming since it requires calling .observe(link_a_bunch_of_stuff) on your scene
though maybe that observer could check if it was called on a trenchbroom scene specifically?
Since it needs to run after all path corners have been spawned
So fun to watch him go! 😄
It's here if you're curious: https://github.com/janhohenheim/thief_sense_demo/tree/main/src/demo
This is sick! Reminds me that the current components for target and targetname could be relationships too 
Gonna go try that real quick
yeah that's precisely what I did 😄
it's all regular target and targetname from TB's perspective
Looking through the relationship API, it doesn't seem like both sides of the relationship can consist of collections of entities, which is pretty necessary for general use-cases
Oh well
Yeah n:m relations are not implemented yet
But I thought target could only be a single entity in TB?
As far as I know, target will connect to all entities with a matching targetname
yep
oh wow I didn't know
yeah then n:m is necessary 
Some people have done workarounds for that, but I'm out of the loop what exactly
@urban zealot what's the state on 0.17 RC?
Do you need help?
Dunno if you've seen it, but we have auto type registration now, so we can remove that from our instructions 🙂
Even if I'm not adding major features, I try to keep it as up-to-date as fast as possible :)
Does bevy_trenchbroom uses gltf custom properties to export bevy components ?
nope!
it exports FDG files: https://book.leveldesignbook.com/appendix/resources/formats/fgd
I tried setting up bevy_trenchbroom and the files that got written out using the default plugin configuration and information in the readme seem totally disconnected from the map file. There's also no information in the readme that describes how to fix the connection or how to "select" the files that get written out by the plugin.
What do you mean by "disconnected"? The files aren’t really "connected" to the map, but to the game you’re making. TrenchBroom expects every game you’re mapping for to have some own file in ~/.TrenchBroom/games
Then, when you create a new map, you can select your game from the list
like point_class registered types are getting written out to /Users/chris/Library/Application Support/TrenchBroom/games/skein_trenchbroom_yay directory, but they don't show up in the Trenchbroom application at all
(also yes that is what I named my project lol)
Did you create a map and during that process click on the name of your game on the list of supported games? 🙂
I mean, it doesn't exist there lol
Heh, that’s suboptimal
And just to make sure, there weren’t any write errors?
and there doesn't seem to be any settings that will like "correct" that one a "generic" game is created
no errors that I can see, everything is logging success
2025-09-15T20:42:33.631303Z INFO bevy_trenchbroom::config::writing: Successfully wrote TrenchBroom game config to /Users/chris/Library/Application Support/TrenchBroom/games/skein_trenchbroom_yay
2025-09-15T20:42:33.631872Z INFO bevy_trenchbroom::config::writing: Successfully wrote TrenchBroom preferences to /Users/chris/Library/Application Support/TrenchBroom/Preferences.json
well the path looks correct 
Are there other dirs in /Users/chris/Library/Application Support/TrenchBroom/games/ ?
nope
oh nvm there wouldn't be

Okay, could you check your /Users/chris/Library/Application Support/TrenchBroom/Preferences.json?
leaving everything in that directory also feels very strange, like how would I share the work with someone else?
this is how mine looks
Yeah it's not cool, agreed. I think that's a genuine limitation of TrenchBroom.
Other can just run the game once to fill the dir
but ideally that shouldn't be necessary imo
okie well I might get back to debugging it later then lol
has anyone else worked with trenchbroom on a mac?
TB is definitely tested intensively on macOS, as its developer uses macOS pretty much exclusively
bevy_trenchbroom on the other hand, I don't know
It's possible some path is being written in a wrong way
yeah, that was what stopped me and made me ask here instead. The readme claims it "just works" and doesn't supply any information about how its supposed to work
Yeah that should definitely be improved then
It does direct to the manual, but it should probably also link to the Configuration section which I believe holds the information you are looking for
Also, make sure to ping me if you need help, as Discord doesn't notify me for normal messages here
Introduction
In /Users/chris/Library/Application Support/TrenchBroom/games/skein_trenchbroom_yay, is there a .fgd and GameConfig.cfg?
I did read this but since it's already supposed to happen with the default plugin setup and it doesn't describe how the files are supposed to be used it didn't really help me debug
Yes iirc, I'll check for sure when I get back to my computer
I'm not sure what you mean as you shouldn't have to interact with the files directly, perhaps are you looking for the relevant TrenchBroom documentation?
If both files are in there, from my experience TB is very loud when it fails to load, strange. Could it not be reading from that folder?
Just to make sure, what version of TB are you using?
well I don't know what was going on but after a few more restarts of the application it showed up
is the version info
Same version here lol
I think you ran into a TrenchBroom bug?
possibly, but I don't have enough experience with the tool to say what it would be
anyway, I was trying to confirm skein/trenchbroom working together and it does officially. gltf exported using skein, used in a trenchbroom level, loaded through trenchbroom's .map format
heck yeah!
Great to know 😄
Sick!
I was surprised I didn't need Skein + BTB yet, I honestly thought I would have by now
now my blog post can say "it does" instead of "I've been told" 😆
you build very quake-style games with it though right?
Since I remember in another older project I used Blenvy to place some markers in a model for where constraints should be placed
Hmm, more imsim-ish
But yeah I'm very excited to have a reason to use Skein
Which blog post?
Literally everything I've seen from it looks lovely
@urban zealot FYI avian has a 0.17 branch now. I can open a PR to the 0.17 BTB branch tomorrow for it
I don't think we are affected by any breaking changes in Avian
but we need to bump it for the avian feature
In that case, I can probably just do it tonight
that'd be great too, thanks 🙂
then I'm almost unblocked for the full rerecast stack
TrenchBroom is just used in some examples, but it would be neat to port those too so we can verify that everything is working together
It's done, it just looks like Avian's f64 support is currently broken, hopefully you don't use that!
great, thanks! Yeah I'm safe from that 😄
@urban zealot trying out the 0.17 branch RN and I get this:
2025-09-16T17:27:24.194975Z ERROR presentation::third_party::trenchbroom: Could not write TrenchBroom preferences: Failed to deserialize preferences to JSON from /home/hhh/.TrenchBroom/Preferences.json: EOF while parsing a value at line 1 column 0
my prefs.json looks fairly normal:
{
"Controls/Camera/Look speed": 0.4949494898319245,
"Controls/Camera/Move forward": "D",
"Controls/Camera/Move right": "H",
"Controls/Camera/Move speed": 0.2929292917251587,
"Controls/Camera/Pan speed": 0.4949494898319245,
"Editor/UV lock": true,
"Games/Generic/Path": "/home/hhh/git/bevy_trenchbroom/assets",
"Games/Quake/Path": "/home/hhh/.local/share/trenchbroom",
"Games/Quake/Tool Path/light": "/home/hhh/.local/share/trenchbroom/tools/current/light",
"Games/Quake/Tool Path/qbsp": "/home/hhh/.local/share/trenchbroom/tools/current/qbsp",
"Games/Quake/Tool Path/vis": "/home/hhh/.local/share/trenchbroom/tools/current/vis",
"Games/Thief Sense Demo/Path": "/home/hhh/git/thief_sense_demo",
"Games/avian_navmesh/Path": "/home/hhh/git/avian_navmesh",
"Games/bevy_rerecast/Path": "/home/hhh/git/rerecast",
"Games/bevy_trenchbroom_example/Path": "/home/hhh/git/bevy_trenchbroom/example/map_loading",
"Games/boomchain/Path": "/home/hhh/git/chainboom",
"Games/foxtrot/Path": "/home/hhh/git/foxtrot",
"Games/presentation/Path": "/home/hhh/git/presentation",
"Games/trenchbroom_playground/Path": "/home/hhh/git/trenchbroom_playground",
"Games/your_game_name/Path": "/home/hhh/git/avian_navmesh",
"Map view/Entity link mode": "transitive",
"Texture Browser/Icon size": 2,
"render/Font size": 17,
"updater/Ask for auto updates": false,
"updater/Check for updates automatically": true,
"updater/Include pre-releases": true
}
let me just verify that the old BTB version works
Oh okay nvm
I'm a silly goose
this was an old project I just migrated from BTB 0.16(!)
and it had a manual implementation of the prefs writing
removed that and now it works haha
all good 🙂
I wonder if it would be possible for bevy_trenchbroom to automatically traverse a class's required components to add base classes
okay you can get a list of transitively required components in an exclusive system
Neat 👀 we could run that at startup, right?
yeah :3
We switched away from this because some required classes aren't QuakeClasses (we were getting the required components from the macro).
That said, it just came to me that now that we use Bevy's reflection system and have ReflectQuakeClass, with what you're saying we could pretty easily only use the required components that implement QuakeClass
On the other hand, I think having the base(...) attribute with all the other class attributes feels/looks nicer, but I would love to hear if you have a different opinion!
yeah that's fair, I think using transitively required components would be more "bevy like" and would also mean that requiring e.g PointLight would automatically include Transform and Visibility
I'm not sure what you're pointing out as a hypothetical on the latter half of this statement, #[require(...)] as well as base(...) are already both recursive (unless I'm completely missing what you're trying to say)
so can you set a non-quakeclass component in base()?
No
right, that's the point I was trying to make
(probably should've used a different component for my example 😅)
Hmm, I just re-read your messages like 5 times I still don't know what you're trying to get across, sorry!
I don't know if my brain is failing me but it is not coming to me
Things like Visibility and Transform implement QuakeClass FYI
I should be more explicit:
component A requires B and implements QuakeClass
component B requires C
component C implements QuakeClass
component A automatically inherits from C despite B not implementing QuakeClass
e.g C could be Transform and B could be a first-party bevy component that requires Transform but doesn't implement QuakeClass
Oh! I see it now, thanks for clarifying! I agree, if we were to switch to using required components for base classes this would most certainly be how it would work
yeah sorry for being confusing 😅
Thought I'd ask here, sorry if it's not super on topic. Was just wondering if it was possible to get the kind of "quad"y style ground that old school runescape has in trenchbroom?
Can you send a screenshot of what you mean?
(Also I think it's on topic enough)
I don't know if all the ground is just height mapped evenly sized quads but it has that rough look
Replicating that look exactly would probably be a little challenging, but you could get pretty far by
- making a grid of brushes in TB and moving the vertices up and down to your liking
- not smoothing brush normals (default behavior)
- having the texture be a scaled up grass-colored gradient, and moving each face around a little in texture space to further disconnect each quad
Thanks for the suggestions! Will try give it a shot when I have a sec 🙂
@urban zealot trivial PR: https://github.com/Noxmore/bevy_trenchbroom/pull/132
Nope. I'll look into it
At least it's not breaking or anything, Foxtrot runs fine despite it
Hi @urban zealot I'm loading Quake1 BSPs and have started getting triggers etc all set up. The one thing that's really baking my noodle is how to work out the end / target positions for doors and platforms. Do you have any guidance or pointers to docs / examples? I think I'm getting confuised about what is in Bevy space and what is still in Quake space (eg, the lip value) 🙂
Sure! Any custom value you have as a property that you want to use for distance (lip value) will need to be converted to Bevy space, which you can do via a function from TrenchBroomConfig
For the rotation, assuming you're doing it the Quake-y way, Quake does it by having rotation fields like angle, angles, and mangle not apply to brush geometry, and instead they get used for the open direction. This is emulated in BTB and you can just get the entity transform's forward direction
You could also do a more general path-based system where the object slides to the position of another, and that shouldn't have to care about Quake space at all
We do plan to add a func_door-like class called func_slide, but the project is on maintenance mode from me at the moment, so I haven't gotten around to it
Random reminder that BTB is very cool 
I've been heavily prototyping the last few weeks and it's been a breeze
I'm extremely certain that I'll need to implement that eventually, but it's gonna be a while
When you do, upstreaming it would be pretty poggers of you
Yeah that's my plan 🙂
Maybe I'll also upstream shitty DIY n:m target and targetname, we'll see
For docs, the most comprehensive source is the manual, and you can find all the examples here, while functionally examples, I mainly use them for testing
very helpful thank you @urban zealot ! so, for basic platform moving I can just convert the lip value and move the transform forward? Is this the child transform where the mesh / collider is on?
If I remember correctly the mesh entity is counter-rotated to the root brush entity, so no, you'll want the root brush entity's transform
That worked a treat, thank you! I can now navigate from start to finish with most levels. That’s far enough for tonight 😄
@urban zealot I spent a few hours today trying to work out why one of the platforms in Quake E1M1 was going left rather than up. I think there might be an issue with default_global_spawner - I've written a workaround system for my project which seems to fix it. Do you want me to put my notes here or create an issue on github? Tbh I'm not 100% sure I'm right ... all this ye olde Quake map lore is 🫠 (I used to find it easy in the 90's 😄 )
@urban zealot trivial bump: https://github.com/Noxmore/bevy_trenchbroom/pull/133
also, this may be related toooo (sec)
#1124043933886976171 message
I don't think it is, since that __base thingy doesn't have anything to do with glTFs
but there's still a connection, maybe?
Oh lol I see BTB also stepped right into https://github.com/bevyengine/bevy/issues/21253
Bevy version and features 0.17.0-rc.2 What you did There are reasons to use MeshPlugin explicitly outside of DefaultPlugins. The most important one is testing mesh-related functionality (e.g. when ...
Oh, is that what your "fix import" commit fixed?
I assumed it was tests leaking into each other with auto registration that I couldn't see because I had to wait for avian and rapier to update to run those tests at all
I would love to hear all the details! And yeah, I had to really scavenge around both documentation and implementations to find a lot of the things for BTB out
yep!
Sick! Thank you!
threw my rough notes into a 🤖 to clean it up. Apologies for the very AI tone
oooooh I see
good catch!
It was quite a fun bug to find. Walked up to a platform, pressed the button to go up....got punched through a wall 😄
@stable crater I'm trying to recreate this, can you point out an exact broken door on E1M1?
It's the platform in the second room (before the water) ..here's the screenshot
the green arrow is the direction the platform moves
After my hacky work around (and a system that sets the doors / platforms into the right place)
The other platform and door transform forwards are correct
What's your work-around? Because it looks like this platform doesn't have an angle
what's that editor? 👀
bspguy
also some debug outputs from BTB confirming this
Ok("func_plat"): {"classname": "func_plat", "model": "*7", "sounds": "1"}
Ok("func_plat"): {"spawnflags": "1", "height": "400", "classname": "func_plat", "angle": "-1", "model": "*22", "sounds": "1"}
(those are the only 2 func_plats in the level)
@urban zealot I'm playing around with steam audio integration, and I need to create trimeshes of the brushes, along with their materials
I know that brushes in Bevy have a Brushes component
And from there, I can get the individual surfaces
and each surface has a String for its material. That works great already
But I'm not entirely clear on how I would turn that into a trimesh for that given surface
Or maybe there's an easier way to accomplish this?
IIRC we already create a single Bevy Mesh per material, no?
If so, I could just reuse that
Oooh, absolutely tell me how that goes!
Yep!
neat!
which steam audio integration are you using?
this will also go into "how do I know which material my character is stepping on" territory, if you remember our discussions there
I'm trying audionimbus
but either my setup is borked, or the recent updates broke it
Or cpal is weird
The 0.16 demo with audionimbus works for me, the non-bevy CPAL demo on the current main of audionimbus does not
pinged the author
Sweet, I had heard of it, but never got around to using it
I found other previous bindings really clunky, and I'm pretty sure this one is a lot better
Hope you get that working!
IMO audio is one of the most slept on areas of modern games, hearing Steam Audio for the first time in HL:A kinda blew my mind
yeah relatable
very relatable haha
Not quite sure how we wanted to tackle that 
And some of the demos i've seen on youtube makes it sound like I'm not even wearing headphones
We have one big compound collider for everything, right?
For convex colliders, yes
oh hey that sounds smart
It might be a little hacky, but you could try to just use MeshRaycast
What's that?
built-in Bevy raycasting system param
you didn't know about that ??
That would work great 👀
I mean, I knew something like it existed for picking
but I never used it directly, no
Let me think, is there any limitation there?
there's even a filter
Yeah the API is really nice in my personal experience
so I could hack together something akin to collision layers
And I suppose the Entity I get back is the one holding the Handle<Mesh>?
Yep
NP!
In case I do circle back to the Avian collider solution, this is the method to check: https://docs.rs/parry3d/0.17.6/parry3d/shape/struct.ConvexPolyhedron.html#method.faces
A convex polyhedron without degenerate faces.
It should give an ordered list of faces that one can reuse for the mapping
I would like to use that, but as I said in the issue, it wouldn't work with the BRUSHLIST BSPX lump, as it doesn't store material data
We'd either need to find a work-around like also reading a .map, or just not support that case
oh yeah I forgot about that
yeah let's do the mesh raycast then
Though I wonder if there is even anything to upstream in that case 
Like, should we have a BrushMaterialRayCaster? That seems like overkill
Probably not, no
Maybe the issue is then best addressed by just documenting somewhere how one could do it
or adding an example for the non-avian solution
or both, actually
I like that idea, let me know after you implement it just in case there's any extra implementation details to worry about
Though hmm, not sure how well the avian solution is doable without upstreamed code
Yeah I'll try to add a minimal example, something like a raycast from the mouse location down so the UI in the example says the name of the material your mouse is on 🙂
But first need to figure out this audionimbus business haha
Just to make sure, we're talking footstep/collision sounds with the raycasting stuff, right?
yeah exactly
Not sure I actually need anything beyond footsteps
Hmm, I guess putting down loot on carpets should be quieter than on stone
but that's very much optional
the footsteps are vital
(I'm recreating Thief's AI)
I was thinking I'd put a section of the manual with probably a few code snippets for this, a whole example might be a little overkill
sounds good to me!
Really interesting! Thank you for digging into this. To save you from my horrible code, my current hack does this :
1. Reads the `angle` value from MoveableFunc (which is passed from the map)
2. Calculates the expected rotation using angle_to_quat (usingfunction from bevy_trenchbroom)
3. Compares expected vs actual Transform.rotation
4. If mismatch detected: Fixes Transform.rotation and logs the correction
So it assumes the angle is right. - Since I wrote the code, let's assume it's not 😄 - Looking at my entities for FuncPlat (which sets MoveableFunc value) I can see this line
let angle = view.src_entity.get::<f32>("angle").unwrap_or(-1.0);
Was this a wrong assumption? I might have got confused with Quake specs
(Note: in my buttons and doors I'm doing let angle = view.src_entity.get::<f32>("angle").unwrap_or(0.0);)
Set the default angle to 0.0 and disabled the work around system and the arrow is still pointing the wrong way (see screen).
This is the 🤮 system which works with the angle defaulting -1.0 https://gist.github.com/robinlacey/399793e9f97cfff5c9bf0186bf0c413a
I did it!
If you want to hear it, do cargo run on this branch here 🙂 https://github.com/janhohenheim/audionimbus-demo/tree/bevy-0.17
This is just porting the audionimbus stuff to the newest Bevy and co
next step: seedling integration, then TrenchBroom integration 
@dim warren on the subject of platforms - could recast/rerecast handle linking navmeshes that would require a platform?
Yep
Just attach a collider to the platform and rerecast does the rest 🙂
🤯 that’s amazing, how does it know that the platform can go up/down bridging the two nav meshes?
It doesn’t 😄 but you can generate the navmesh on command. Simply regenerate it every now and then to account for the moving platform 🙂
Future versions should be smart enough to only regenerate the parts that actually changed, but for for regenerating everything is surprisingly fast
Did not know Quake defaulted specifically func_plats to have a default angle of up
I'm currently very hesitant to upstream a hack for that specifically, but I can (and already have on main) make a simple change that would let you put a hack at the start of the global spawner much easier with something like this in your TrenchBroomConfig
.global_spawner_fn(|prev_spawner| Arc::new(move |view| {
if view.class.info.derives_from::<MoveableFunc>() && !view.src_entity.properties.contains_key("angle") {
view.world.entity_mut(view.entity).insert(Transform {
translation: read_translation_from_entity(view.src_entity, view.tb_config)?,
rotation: angle_to_quat(-1.),
scale: Vec3::ONE,
});
}
prev_spawner(view)
}))
It also looks like you have a custom class MoveableFunc that provides angle, the default of which can't be considered in global_spawner out of the box, just in case you had that impression
Woot!
That's very helpful, thank you. My knowledge of this is shallow, so you're right to be very hesitant about my findings / code 😄
Gotcha. I thinking of using a version of the navmesh reachability analysis - so I can generate [nav flows] (https://developer.valvesoftware.com/wiki/L4D_Level_Design/Nav_Flow) - I was thinking I could add something like off mesh connections where the platforms were?
Off mesh connections are supported by the landmass-rerecast integration 🙂
There’s just not yet an option to add them visually in the editor
But it works programmatically
Im going to have to work out a way of turning all the quake platform types in to off mesh connections 🫠
If rerecast is as fast as you say, a bit of brute forcing is going to get me most of the way
Yeah IME just brute forcing it works pretty well lol
@urban zealot #art-audio-animation message
we did it!
It should be very doable to integrate this fully with TrenchBroom 🙂
will continue tinkering with that
Hell yeah!!! If I ever actually get around to making a game, I will 100% use this!
@urban zealot @dim warren is anyone working on the bevy 0.17 upgrade?
It’s done on the branch
ahaaa i was only checking if there is a PR (or draft PR)
Just updated to 0.17 using the latest branch. I'm getting a crash on loading one map (good 'ol E1M1.bsp) with :
thread 'Async Compute Task Pool (1)' (103272) panicked at C:\Users\Robin\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\wgpu-26.0.1\src\backend\wgpu_core.rs:1327:26:
wgpu error: Validation Error
Caused by:
In Device::create_render_pipeline, label = 'pbr_opaque_mesh_pipeline'
Error matching ShaderStages(FRAGMENT) shader requirements against the pipeline
Shader global ResourceBinding { group: 2, binding: 100 } is not available in the pipeline layout
Binding is missing from the pipeline layout
This looks like one of the shaders being used hasn't been updated to use the new group
Most users who are not using mid-level render APIs will simply need to switch their material bind groups from @group(2) to @group(#{MATERIAL_BIND_GROUP})
I've deleted all my shaders so this might be Trenchboom. Perhaps one of the common level materials / shaders (eg sky) - is there a way I can turn these off to test?
I've updated the liquid and quake_sky shaders and it fixes it for me. It's a private repo so can't make a PR - so here they are 🙂 (or add me robinlacey and i'll push)
Make sure to ping me, I don't get notified here otherwise
I swore I already fixed this, and sure enough I just forgot to push the commit, should be working now :)
I'm not sure what you're talking about, BTB isn't a private repo
I assume their own project in which they fixed the shaders is private
probably my mistake! I just tried to push a new branch for the PR and it didn't let me -probably user error 😄
will do in the future, thanks for fixing 🫡
@urban zealot avian 0.4 has been released so you can change 0.4.0-dev to 0.4.0 on the branch
@urban zealot are there any blockers on a new release?
-# just ignore rapier, it's fine, shhhh
I've thought about removing Rapier support for this reason, I wish there was a way to see how many people use the feature on BTB
But yeah, it's just Rapier, here's the 0.17 PR: https://github.com/dimforge/bevy_rapier/pull/678
Hey!
First time contributor. I don't quite know what I'm doing (no this is not in any way a vibecoded PR) but I was starting on a Bevy 0.17 project and needed bevy rapier for 0.17. ...
looks like it might still be a little while
there is! You remove the feature and wait for bug reports 
seriously, most people put their avian / rapier support in an extra crate for that reason
see landmass, tnua, rerecast
that way you can update the main crate independently of the physics integration
Oooh, I hadn't considered that
I'll look into it
worst case, it's not really breaking if you remove it rn
rapier users can't use the newest BTB whether you have that feature or not
you can still add the rapier feature back in a patch release if you want
I suspect not many will need it though
For my own crates, I tend to tell people that they are very welcome to submit PRs for rapier if they want support, given that the support code is just like 100 LOC or so they can mostly copy-paste
and I never heard back from any of them
¯_(ツ)_/¯
whoa unrelated but thanks for linking this, I noticed that they're apparently using the Message suffix for all message types, which is very much not recommended unless necessary lol
Cart even explicitly calls out the collision event naming there :P
left a quick comment suggesting against the suffix
Not sure I actually understand the reasoning for not using the suffix but thnx for pointing that out, I'll fix that up in my own stuff
in the quickstart guide theres no mention of how a map should be configured on the trenchbroom side. should i just use the generic template?
No, starting the bevy app once will create a new template with the name of your app
@urban zealot how come my point class contains a Brushes component
Is that intentional or a bug
This messes with my invariants when setting up acoustic materials in the Steam Audio <-> BTB integration
since I assume that we can automatically set up all acoustics for brushes, I basically yeet any acoustics that my Avian integration might already have set up automatically
but if regular point classes also contain Brushes, then I just yeeted the acoustics material that the user specified for e.g. a chair
Sounds like a bug, let me see if I can reproduce
not happening in bsp_loading
on main
It's happening for me with https://github.com/janhohenheim/thief_sense_demo/blob/main/src/demo/npc/mod.rs
NPC point class:
Ingame:
If you want to compile it yourself, activate the "auto-install" feature on bevy_steam_audio
(so it downloads libphonon.so for you)
I'm loading a .map, maybe that's relevant?
yep, you are right
Looks like I didn't check to make sure there are actually brushes before adding that
I have now found another problem, when loading maps, Transform will sometimes be added as a required component by things like lights, making this fail in the global spawner
// We can assume that the entity doesn't derive from Transform
if !ent.contains::<Transform>() {
if view.tb_config.global_transform_application {
ent.insert(Transform {
translation: read_translation_from_entity(view.src_entity, view.tb_config)?,
rotation: read_rotation_from_entity(view.src_entity)?,
scale: Vec3::ONE,
});
} else {
ent.insert(Transform::default());
}
}
I have of course not documented why we changed this, but I believe it was talked about in this channel?
I don't recall that conversation
but very possible that I missed it
here is it for my convenience
i think
Or not, I changed it back and that problem works fine
I might just add an implicit_transform_override into QuakeClassSpawnView, it's a little hacky, but I can't think of anything better right now
Thanks to a bug you'll have to change the code above the replied message to view.transform_override = Some(Transform { ... on latest main
Just letting you know so it doesn't sneak up on you
could you ping me when the Brushes thingy is fixed? 🙂
it should be on main
thanks!
0.10 has been released
Yayyyy! 
is there anything to take into consideration when spawning multiple maps at the same time?
I'm spawining the same map 4 times, as different children of different entities with different transforms
and I would expect the transform to be properly propagated
but it is behaving really weird
even more so with physics (avian)
so b4 I go mad looking for a reason I might ask here 😅
it kind of looks like worldspawn doesn't correctly apply the transform
while the other brushes do seem to work consistently
okay it's not related to the brush
it's related to the way I'm adding the physics
If I do this:
#[solid_class(hooks(SpawnHooks::new().convex_collider()))]
struct Brick;
fn brick_spawner(event: On<Add, Brick>, mut commands: Commands) {
commands.entity(event.event_target());
}
``` it works
if I do this:
#[solid_class(hooks(SpawnHooks::new().convex_collider()))]
struct Brick;
fn brick_spawner(event: On<Add, Brick>, mut commands: Commands) {
commands
.entity(event.event_target())
.insert(RigidBody::Dynamic);
}
``` it doesn't

doing it like this doesn't work either
#[solid_class(hooks(SpawnHooks::new().convex_collider().with(RigidBody::Dynamic)))]
struct Brick;
the colliders are properly created, and they're set as rigidbody dynamic
but the transform just says
is bsp worth it
No
I really tried hard to work with it, but the limitations are just not worth it in my opinion
Are you using insert(children![…]) anywhere?
FYI the upstream Bevy style is to call that event add, and then use add.entity instead of event.event_target() 🙂
Yes, why?
That yeets the existing children
And for solid brushes, TrenchBroom inserts its own children
I think it might have to do with the fact that brushes get automatically spawned with RigidBody::Static, and I'm rewriting that component with RigidBody::Static
but then why does it work if I do not add the RigidBody component again
¯_(ツ)_/¯
Just make sure in general to only ever use children! with .spawn() and never with .insert()
Use .with_children() for .insert()
If this is the cause of your problem, then I have myself already lost an entire day debugging it
That’s not a TrenchBroom specific footgun, but a Bevy footgun in general
using children! wasn't the problem
and I am in fact not using it in insert
but thanks for letting me now it yeets other children
do you happen to know if swapping rigidbody types is supported in avian?
Then that sounds like a bevy_trenchbroom bug, to me your setup seems reasonable 👀
You don’t have rigid bodies as children of other rigid bodies, right?
Because that fucks up transforms in Avian
Are you inserting the component into a child of the other rigid body accidentally?
Maybe call commands.entity(add.entity).log_components()
That prints all the components on the entity in a very hard to read list (I fixed that on Bevy main)
But it should be alright here
If that list does not contain a rigid body, we know the issue
nop
I have them as children of other entities with transforms and such
but no rigidbodies
Mind calling that command I sent?
give me a second
Ah, call it before the insert call
I can’t see it on mobile, sorry. But is there a rigid body before the insert?
If not, I think we found the bug
what the fuck
there is
in fact
no rigidbody
in the before
only in the after
im puzzled af
Heh, then we are making debugging progress
Take a look at the full hierarchy with the egui inspector and see which entity actually holds the rigid body
In my opinion, yes, it really just depends on what workflow you want to/are used to/are fine using, I made a pros and cons list in the manual
Introduction
Don't listen to Jan's anti-bsp propaganda
I stuck with it - but my game is more like an old Quake TC - so being able to use old quake maps from the internet is a part of it. If you are building maps in trenchboom, then use .map 😄
hehehe
I will say this: "At the time of writing, BSPs are probably the easiest way to get baked lighting in Bevy" that is not to be understated
you need to be a turbonerd to get baked lighting in Bevy any other way
Yeah, probably the #1 reason I prefer them currently
Yeah, i wrote my own AO library.. then found ericw tooling and kicked myself
I love the ericw stuff 
I actually tried writing a Bevy lighting baker recently, and realized it was way out of my depth
Maybe after the editor is in good shape someone smarter than I could come along and make that
Wish there was something for baking Solari
@urban zealot can I grab your attention for a moment please 😅
yes hello
I think I've found a bug on Trenchbroom
on the Avian integration
if you haven't read anything from above
basically when adding the Rigidbody property to a brush spawned by trenchbroom
the entity gets teleported to 0,0,0
well, not to 0,0,0 exactly
but rather its own local transform
so it is correctly positioned inside the .map
but not inside the bevy world (doesn't follow child hierarchies and transform propagation)
but again, this only happens when adding RigidBody::Dynamic or RigidBody::Static to it
just like I explained here
Just to make sure, you're using 0.10, right?
haha yep! I was originally building this in MonoGame (for nostalgia) ...and they havent really updated the graphics since DX11. So when I started hand rolling my own Forward+ rendering (CPU based, because no compute shaders 😢 ) I realised i was just punishing myself for no reason. Sometimes the most liberating feeling is burning a codebase to the ground and starting again
I'm using revision: 2a125b54a23a6b01c117a75ec6849c40ded09941
so yeah technically 0.10
I believe that is the commit that was published to crates.io
I'm recreating the problem, I'll look into it
I'm not really getting this photo
is it also happening to you?
In the physics_avian example, I've made those brush entities #[require(RigidBody::Dynamic)], and they seem to be spawning at or near the world origin
Great! I was a bit worried it was something wrong on my end
Tag me if you need anything else from me
You got it
BSPs as in Binary Space Partitioning? I've been under the impression that it's kind of an ancient technique and everyone just uses BVHs nowadays
yes, but in this context specifically .bsp files that tools can produce by processing .map files
The important bit here is not the fact that it's using a Binary Space Partition, but that it is preprocessed
preprocessed in really really cool ways
Hmm okay
It does stuff like trimming things outside the play area, combine brushes into simpler geometry, bake light, generate occlusion data, ...
but the tools that do so expect your .map file to adhere to 1990s practices, like only using 15 characters for the textures names. And those 15 characters include the name of the subdirectories 
i could still very well just add runtime lighting yeh? assuming performance never becomes problematic
You could, BSP also gives you bounce lighting and baked ambient occlusion for free (runtime) though
Yeah, that's what I'm doing. Just know that
- Baked lighting is much more beautiful and
- vastly more cheap
did you find anything?
Here are my notes currently
From my testing, if you insert a RigidBody into an entity at the same time it gets spawned from a BTB scene, it sets its global position to its local position.
without RB
local: [1.0159998, 0.6096, -1.016], global: [6.016, 0.6096, -1.016]
with RB
local: [-3.984, 0.6096, -1.016], global: [1.016, 0.6096, -1.016]
- If you don't add any colliders, it still happens.
- The transform is fine in the scene world, it only gets messed up when it gets spawned in the main world.
- It doesn't happen when manually creating a scene with a similar setup, I can't get a small situation to reproduce it in.
- It seems to happen after or during
Addobservers are run, as my observer printed the correct local coordinates, but even systems running inFirstprint the wrong coordinates. - When restarting repeatedly it very occasionally it doesn't break, so it's probably an ordering issue.
This bug is pretty annoying :P
yikes
looks rough af
my guess based on literally just observing the behaviour is that this is probably an avian teleportation issue, which may explain why it doesn't always happen and why the positioning isn't fixed and kind of random
maybe it's getting spawned at a position with given physics properties, and then the transform is edited again after adding the rigidbody again somehow?
not sure of anything but it definitely is a weird bug
thanks for the efforts my man ❤️
no problem :)
Are avian teleportation issues known?
I've vaguely seen some discussions over at the avian thread
about teleporting active physics entities
and it is indeed a common issue in most phyisic engines I've used
so the guess comes from that
but I wouldn't want to misslead you based on conjecture tbh
it's just a gut feeling
okay @urban zealot I just tested on a small example
to try and teleport rigidbodie
both dynamic and static
and although they get awaken and move a lil bit
they do not seem to bug out significantly
I also tested switching them from dynamic to static and viceversa
and it's also okay
so i don't really know, maybe these aren't part of the issue at all, or maybe its just because of a weird interaction on spawn
To be honest, I don't know how to further debug this, everything I've tried has led to a dead end
This workaround seems to work, it might have to be good for now
#[solid_class]
#[require(DynamicRigidBodyHack)]
pub struct FuncDoor;
#[derive(Component, Reflect, Default)]
#[reflect(Component)]
struct DynamicRigidBodyHack;
fn dynamic_rigid_body_hack(
mut commands: Commands,
query: Query<Entity, With<DynamicRigidBodyHack>>,
) {
for entity in &query {
commands.entity(entity).insert(RigidBody::Dynamic).remove::<DynamicRigidBodyHack>();
}
}
When does trenchbroom insert the Rigidbody static component?
because entities by default do get an static component inserted
Can you try to temporally change that to insert a dynamic instead of static and see if it sticks?
When colliders get added, but this seems to happen even without colliders
idk, just saying because the default insertion seems to work just fine
I did, and it worked fine actually
however if you manually insert an static it also fails
Probably because that happens in a system after the entity spawns
@digital heath am I remembering correctly that having rigid bodies be children of something else at a non-identity transform is not well behaved in general?
Because I think that’s what’s happening here
Did you try to not insert the rigidbody with trenchbroom
and just insert one using the requires?
so basically removing the default behavior of trenchbroom of autoinserting the rigidbody component
Just did, it has the transform problem
My current best guess is it's some kind of internal Avian ordering issue
will have to be that
lets see if Jondolf can shine some light on it
I'll put in the workaround temporarilly
Jondolf Jondolf I summon thee
Satana Perkele Vittulainen
yeah I'm trying to read context
*saatana
Guys I actually feel so bad, I'm always coming to bother you with obscure bugs
Your names will be big in the credits of our game
It's alright, better we find them sooner than later
This is benign compared to when @urban zealot and I learned about .insert(children![]) lol
Oh god don't remind me
Hope you use rerecast then :p
I just cant find enough time for everything
I'm not sure I understand the full context, but there's a system that effectively converts the global Position and Rotation components into a local space Transform at the end of the physics step
it sounds like that is somehow maybe breaking something?
but again idk if I understood the problem correctly
Basically
When spawning a brush with Trenchbroom
if you hook/observe it to insert a RigidBody component on it
the transform gets resetted to origin
Sounds very plausible
or smth like that
it's not exactly to origin
but rather I think it ignores the parent's transform
so it is positioned well with respect to .map positioning, but wrong with respect to the entity transform hierarchy
looks like it ignores it or something weird
And I'm guessing this is new in 0.4? Or was it also happening in 0.3
it is new, but I don't know whether it's wrong with avian or trenchbroom
well
actually 🤔
I'm not really sure because I have never spawned trenchbroom scenes nested on a hierarchy before
it was most likely this PR if it was avian
https://github.com/avianphysics/avian/pull/785
or wait was there another related one
oh this is what I was thinking of
https://github.com/avianphysics/avian/pull/760
@urban zealot does Trenchbroom do any reparenting on spawn maybe?
bevy_trenchbroom I mean
I just set PhysicsTransformConfig::position_to_transform to false and it's spawning in the right place (not moving, but I think that is expected)
not doing that it breaks
So it was indeed this one
I wonder if transforms sometimes aren't propagated by the time position_to_transform runs
by default Avian runs an additional propagation pass right before physics
to make sure global transforms are up to date for collision detection
I need to double-check the logic in this
hook, it's one of the more likely places where things might be going wrong
https://github.com/avianphysics/avian/blob/05718697caedf47d9831557ff79a47924c178e37/src/physics_transform/transform.rs#L1116
but I won't have time for that until some time tomorrow, it's uhh 2:30 AM right now and I have an exam tomorrow lol
It also looks like transform_to_position runs between those two things, that could be a point of failure
Sounds good, goodnight!
good luck with the exam
good night!
the issue can wait 😇
nvm wrong chat
wow okay this is several increasingly cursed problems stacked on top of each other
I know how to fix it in theory, but I'm trying to figure out how to do it in a non-breaking way so I can ship the fix in a patch release
wait wha
how exactly does ChildOf work for scenes?
it is None in one component's on_add hook and Some in another
I would have assumed that the relationships are kinda baked in to the scene and not inserted deferred somehow
oh so scene spawning is done in archetype order, and there's no guarantee on the order, so the hierarchy may not be finalized in hooks yet
well shit
this is so cursed omg
on_addforColliderfiresinit_physics_transform, butChildOfisNone-> the entity'sTransform(often identity) is used for the globalPositionandRotationon_addforRigidBodyfiresinit_physics_transformagain, because it doesn't know that it was already called for the rigid body. But this timeChildOfis actuallySome, andPositionandRotationno longer use the placeholder values because they were computed earlier, so they now overwrite theTransformwith the new parent's global transform, but based on the old global transform where there was no parent yet
this does not happen normally when just spawning hierarchies with pre-defined child-parent relationships, it only happens with scenes (from what I've tested)
Wait are you saying that this may even escalate up to a bevy problem?
If there's no way to fetch the state of "scene spawning" on hooks/observers
that leads to all sorts of problems doesn't it?
Related to this? https://github.com/bevyengine/bevy/issues/21428
we can work around this, but it is kinda annoying that hooks or observers for scenes may not have the hierarchy available yet
which I gues could only be solved by being able to explicitly state the insertion order of components in scenes
this I believe
https://github.com/bevyengine/bevy/issues/18671
lovely that he even included a sample workaround 😄
I guess that's good news
in a sense
@urban zealot @foggy glade this should fix it
https://github.com/avianphysics/avian/pull/873
it's kind of a crappy fix but I don't think I can do it much better without breaking changes :p
THanks for the fix! ❤️
however I might suggest that with avian 0.4 having been released just some days ago
it might just happen to be the best time for breaking changes? 🤔
as people has to migrate anyway
@tawny elbow ^
@wooden yarrow This may also fix the issue you were having with ldtk and transforms being reset to the origin, though I haven't tested ldtk specifically
yeah, I just hope it didn't silently break something else in the progress lol
from what I tested, everything seems to work, but this transform logic has historically been very fickle
transforms and hierarchies are the bane of my existence in avian ngl
0.5 got it technically i can just not add Rigidbody in that specific cast
although i worry about my dynamic bodies e.e
Nice, ill try it out. Someone also made this hacky fix so ils try otu both
no, there's already a workaround on main / 0.4.1 when it releases
I intend to release 0.4.1 this weekend
@digital heath this also fixed the issue i was having.
ive been using ColliderConstructorHierarchy::new(ColliderConstructor::ConvexHullFromMesh), to generate colliders from my blender maps, and it seems to work on btm maps as well.
are thsee functions an alternative to that or is it just for classes?
they're the same afaik
besides maybe the fact that convex_collider generates a box collider (simpler than a generic polyhedra) if your brush is a box
but I guess that's an edge case
ah
i imagine thats faster if ur talkin bout a ton of brushes but i dont think imma hit that limit anytime soon
It is, although I haven't looked into it
is it a lot to setup
it probably is as simple as loading it with the hot reloading asset server
as scenes are simple assets
oh this is bevy ur talkin about
here i am trynna find hot reloading in the btm docs
ah its just watching_for_changes on AssetServer
if i want to enabled that, do i just &mut asset_server in my setup and replace it? surely I cant insert_resource on a built-in resource?
nvm i discovered plugin overrides
DefaultPlugins.set(AssetPlugin {
watch_for_changes_override: Some(true),
..Default::default()
}),
just add this to your plugins @foggy glade
curious that watching for changes isn't turned on by default
ok actually this doesnt seem to be doing anything
yeh hard to say, it seems really clutch
the assetserver is watching changes on the .map but i believe its still up to the btm plugin to acknowledge those changes and react accordingly?
Have you enabled the file_watcher feature on Bevy?
set the scale here, ran the game, opened trenchbroom, and still the default scale is 1
naw im not familiar
i thought it was just the one setting in AssetPlugin that needed to change
That's all you need to do, you don't even need to configure the plugin
oh ic
I'll try to reproduce in a second
One thing it probably won't work with is if you have brushes with faces set to no texture so non-visible faces aren't included (I'm surprised how few people do this)
for like invisibile walls?
And those too
But I mean faces that the player can't possibly see or interact with in normal gameplay
Just wasting processing power
are you saying that bevys version wouldnt work for that, like its only supported by btm
Unless those generated convex hulls can be 0 width on an axis actually, I haven't tested if that's the case
Just generating from the mesh, they certainly wouldn't be the full shape of the brush
i set this feature and it hot reloads now but actually the bevy mesh generation deleted itself. i was gonna put it off but ig i gotta use the spawnhooks now lol
Just tried, it seems to be working for me
If you want all brush entities to have collision blanketly, you can add this to your TrenchBroomConfig:
.default_solid_spawn_hooks(|| SpawnHooks::new().convex_collider())
really?
damn i have no idea why its not workin for me. ik its hooked up and all, i can see my custom class
Just to make sure, what exactly are you doing in-editor to see if it works?
setting a face on a brush
oh
dude
its bc i was setting it on an already existing brush
lol
Lol i was literally just typing
"If it's an existing brush it might not update"
XD
Well good that it's sorted
no problem
You just enable the file_watcher feature on bevy, done
Oh I see you figured it out 🙂
It is if you have the feature enabled
hey y'all; Been running into a similar, but different, problem possibly related to this. After updating to 0.17, bevy_trenchbroom seems to be spawning convex colliders that I intend to move (like platforms) incorrectly. It does generate the correct shape, just offset from the visuals. The brush mesh itself, despite being a child of the collider, is in the correct location. Setting the mesh's translation to be equal to the collider's translation causes them to overlap (at the collider's incorrect position), and then setting the collider's translation to zero puts it in the correct location. If I'm not mistaken, it's as if the collider's own vertices are having its world position baked in rather than being local to the center of the object and then the object being offset. Other entities across the map that are static seem to be fine; and all have their transforms at zero no matter where they actually are
this seems to be a change from 0.16 somehow as before this update the platform logic was working fine
ah, here's something maybe useful: One of the movables looks like this
{
"classname" "movable"
"name" "fence_01"
"target" "target_fence_01"
"rotation" "true"
// brush 0
{
( 1151.375 256 -240 ) ( 1151.375 256 -239 ) ( 1151.375 255 -240 ) fence [ 1.9967346175427393e-16 1 0 0 ] [ 0 0 -1 16 ] 90 1 1
( 1168 0 -208 ) ( 1168 0 -207 ) ( 1169 0 -208 ) fence [ -1 1.9967346175427393e-16 0 0 ] [ 0 0 -1 16 ] 90 1 1
( 1136 256 -240 ) ( 1136 255 -240 ) ( 1137 256 -240 ) fence [ -1 0 0 0 ] [ 0 -1 0 0 ] 270 1 1
( 1168 0 272 ) ( 1169 0 272 ) ( 1168 -1 272 ) fence [ 1 0 0 0 ] [ 0 -1 0 0 ] 270 1 1
( 1136 256 -240 ) ( 1137 256 -240 ) ( 1136 256 -239 ) fence [ 1 -1.9967346175427393e-16 0 0 ] [ 0 0 -1 16 ] 90 1 1
( 1152 0 -208 ) ( 1152 -1 -208 ) ( 1152 0 -207 ) fence [ -1.9967346175427393e-16 -1 0 0 ] [ 0 0 -1 16 ] 90 1 1
}
// brush 1
{
( 1136 -16 -240 ) ( 1136 -15 -240 ) ( 1136 -16 -239 ) origin [ 0 -1 0 0 ] [ 0 0 -1 0 ] 180 1 1
( 1136 -16 -240 ) ( 1136 -16 -239 ) ( 1137 -16 -240 ) origin [ 1 0 0 0 ] [ 0 0 -1 0 ] 180 1 1
( 1136 -16 -240 ) ( 1137 -16 -240 ) ( 1136 -15 -240 ) origin [ -1 0 0 0 ] [ 0 -1 0 0 ] 180 1 1
( 1168 16 -224 ) ( 1168 17 -224 ) ( 1169 16 -224 ) origin [ 1 0 0 0 ] [ 0 -1 0 0 ] 180 1 1
( 1168 16 -224 ) ( 1169 16 -224 ) ( 1168 16 -223 ) origin [ -1 0 0 0 ] [ 0 0 -1 0 ] 180 1 1
( 1168 16 -224 ) ( 1168 16 -223 ) ( 1168 17 -224 ) origin [ 0 1 0 0 ] [ 0 0 -1 0 ] 180 1 1
}
}
commenting out brush 1 (that is; the brush with origin in it rather than a contextually relevant name) causes their initial position to work but their final position seems to break badly. At least then the visuals and collider stay together. I'm not the one that made this map nor am I very familiar with trenchbroom itself so I'm not certain what I'm looking at, I just noticed that origin brushes are unique to the broken entities.
@urban zealot @digital heath I think I have bad news again 😅
The bug that Jondolf solved a couple of days ago has a new version
basically the exact same happens if you spawn the entities with Disabled
I guess this is even more of an edgecase, but it is still a bug nonetheless
idk if now that you've worked around it it can be easier to fix
to reproduce just take the exact same example you used last time and add the #[require(Disabled)]
then remove the Disabled (so you can see the gizmos) (or use a system to draw disabled entities) and all of them will be at origin
I'm so sorry 🥴
Classic missing Allow<Disabled> in an observer
I haven't messed with Disabled at all to be honest, I don't really know how it works
I'm currently very deep in getting Quake 2 maps working so I can't help for a little bit
I don't think it's in your end
you're probably doing fine, its jondolf spawning logic
although the only thing Disabled does is basically hide the entitiy from appearing in queries by default, they only appear if you explicitly ask for Disabled entities
but by the time they have disabled your library is done with the job so again I don't think there's anything in your end
crazy to me to see this working
It is indeed crazy
Great work ❤️
Now imagine it with Solari baked lighting
Or even realtime heheh
What map is that? 🙂
Forgot the filename, but it's just after the beginning tram ride in Half-Life
HA! I knew I knew from somewhere 😄
Talking about HL, did you ever experiment with decals?
They were added to TB to support them in GoldSrc, but should work for Bevy too imo
Oh lol forgot I commented there
Btw I moved away from preload hooks due to the fact that bevy only caches subassets
Not sure if you’re aware, but if you load both a #Scene0 and an #Animation0 and even an #Animation1, it will load the entire glTF 3 times
so I nowadays preload the entire Handle<Gltf>
Which means the only spawn hook I have left in my code is the one for creating solid classes 
I was thinking; could spawn hooks be replaced with entity observers that BTB adds and triggers for you?
You would still have to specify them in the attribute, but at least they would be regular old Bevy observers
I am way too tired to think about this or talk right atm, will get back to you tomorrow
Yeah no pressure haha
It’s all working lovely as-is 🙂
Good night :)
I have a draft PR up with an initial implementation of getting translucent glass working if you want to check that out
I think you’ll probably need to implement emissive textures in bevy_trenchbroom for Q2 too. It shouldn’t be too hard, I put that emissive_scale method in the Q2 texinfo and that should be all you need to make it work. Honestly I’m not sure if Q2 uses it at runtime or if it’s just for qrad but now that we’re in ✨ the future✨ and have proper HDR rendering it makes a big difference, the qbsp PR was based on an old project of mine that could render Q2 maps and I used to just fly around maps playing with tonemapping algorithms and stuff 😅
There’s a PR that fixes this for me (and I’m patching my bevy dependency to my fork that rebases it on main) but it’s marked draft and there doesn’t seem to be any movement https://github.com/bevyengine/bevy/pull/20449
I saw it! I'll hopefully look fully into it later today
No rush, I don’t think it’s holding anyone up or whatever 😅 Just thought you might be interested
The whole reason spawn hooks exist is because they run in the scene world (maybe they should be renamed to scene hooks?)
Hypothetically they could be replaced by observers, but I can't think of anything useful that would give them. There isn't anything interesting in the scene world I can think of, and this is during the entity hierarchy construction, so you can't safely look at any other entities
The useful part is getting rid of spawn_hooks 😛
The hooks attribute, or the infrastructure?
the infrastructure and the concept
Having a concept less is a worthy goal imo
if an existing Bevy thing already deal with it
Idk how the hooks attribute could be removed :/
Just had a quick look into the implementation side of this. We would have to get QuakeClassSpawnView or its contents feeding into the observer, and it seems like both observers and resources require static lifetimes, so as far as I know this isn't actually possible
Ah heck, yep that's true
Could you elaborate on this? I’m not sure exactly how scenes interact with systems etc and I should probably know 😅
In Bevy, scenes are just wrappers over other Worlds. Spawn hooks are function pointers that get run on every entity in the scene world when the entity hierarchy is being built in it.
This is done in the asset loader, so it all runs parallel to main operation, and doesn't have access to the main world.
You can see exactly where they get run if you expand a QuakeClass macro
#[automatically_derived]
impl ::bevy_trenchbroom::class::QuakeClass for FuncPlat {
const CLASS_INFO: ::bevy_trenchbroom::class::QuakeClassInfo =
::bevy_trenchbroom::class::QuakeClassInfo {
ty: ::bevy_trenchbroom::class::QuakeClassType::Solid,
name: "func_plat",
description: None,
base: &[<BspSolidEntity as ::bevy_trenchbroom::class::QuakeClass>::ERASED_CLASS],
model: None,
color: None,
iconsprite: None,
size: None,
decal: false,
properties: &[],
};
fn class_spawn(
view: &mut ::bevy_trenchbroom::class::QuakeClassSpawnView,
) -> ::bevy_trenchbroom::anyhow::Result<()> {
use ::bevy_trenchbroom::qmap::QuakeEntityErrorResultExt;
view.world.entity_mut(view.entity).insert(Self);
let hooks: ::bevy_trenchbroom::class::spawn_hooks::SpawnHooks =
(view.tb_config.default_solid_spawn_hooks)();
hooks.apply(view)?;
Ok(())
}
}
Once the scene gets spawned it’s all in the main world though, right?
Yep, this is before that
Interesting point about them running on the asset server thread, I hadn’t considered that
This is also why I kinda want to rename them
Yeah I def think that makes more sense
The issue with them is that it ties data and behaviour together though, and one of the biggest strengths of Bevy is that it separates them
A lot of that is an issue with Bevy's scene and asset system in general though
I agree, but I also think that's kinda inherit with Quake's class system that I have to conform to
I don’t think you need to conform to it, entities are just configuration at the end of the day
Even from my perspective of making a Quake engine it’s useful to split the two, not even mentioning people building their own games. I’m currently rewriting my QuakeC VM so that entities aren’t a singleton bc it makes a lot of other future features a lot simpler to implement
but on the other hand, stuff like this PR that I mentioned aren’t really possible to do in the regular ECS, or at least they’d be spaghetti to do without some kind of hook
Just had an idea
// Type parameter for what the scene is a subasset of?
.add_scene_system::<Bsp>(PostSpawn, add_convex_collision_to_solid_classes)
fn add_convex_collision_to_solid_classes(
mut commands: Commands,
query: Query<Entity, With<SolidClass>>,
) {
for entity in &query {
commands.entity(entity).insert(ConvexCollision);
}
}
This could also make it so global transform application doesn't have to be as special-cased
👀 Yeah hooks as systems would def be useful
Or systems as hooks, whichever way you want to think about it
I wonder if someone’s made an RFC for something like that in Bevy already
That’d be really useful for more than just bevy_trenchbroom too
I feel like some functionality like this might've been addressed with bsn, I'll have a quick look over that PR again
There’s also this PR that might be somewhat useful https://github.com/bevyengine/bevy/issues/11266
This is the one I meant to link, but they’re both somewhat similar https://github.com/bevyengine/bevy/issues/1833
I guess one problem with using systems is that what’s available is way less discoverable. Maybe so long as you still have that BspData singleton that gives you a first place to look
Pretty sure I was thinking of patches, which function more like hooks. Perhaps these systems could be a decent Bevy addition
This is true, being able to do a view. and see everything you have access to is nice for developers
Speaking of which, we come back to lifetime problems, for reference, here's QuakeClassSpawnView
pub struct QuakeClassSpawnView<'l, 'w, 'sw> {
// 'l: local, 'w: world, 'sw: scene world
/// The file type of the map being loaded.
pub file_type: MapFileType,
pub tb_config: &'l TrenchBroomConfig,
pub type_registry: &'l TypeRegistry,
/// A map of classnames to classes.
pub class_map: &'l HashMap<&'static str, &'static ErasedQuakeClass>,
pub src_entity: &'l QuakeMapEntity,
pub src_entity_idx: usize,
/// The class of the entity that is being spawned. Not the class of the [`QuakeClass`] in which this view is passed to (if it is a base class).
pub class: &'l ErasedQuakeClass,
/// The scene world being written to.
pub world: &'sw mut World,
/// Entity in the scene world.
pub entity: Entity,
pub load_context: &'l mut LoadContext<'w>,
/// Information about the mesh entities this entity contains.
pub meshes: &'l mut Vec<QuakeClassMeshView<'l>>,
}
LoadContext stands out to me especially for looking quite hard to get access to in these systems
Is there anything in loadcontext that users would need to access synchronously? Maybe it can be handled with messages or something similar
I guess provisioning new handles would be a pain
Being able to immediately load assets is one, though I don't think I currently use it in a hook
Hm, yeah I’m having trouble figuring out an approach that allows both the kind of copy-on-write asset modification needed for the goldsrc glass and lets you load sub-assets from other files
Am I under the right impression that we need a separate material and mesh for each different render mode configuration?
I don’t think you need a separate mesh, just a separate material
There’s no way to change face-to-material mapping with render modes (and I think it’s fair to not support that) so you can reuse the mesh
Forgot render modes aren't separate per brush
Ah yeah, they’re per entity (and therefore per model)
Honestly I kinda feel like scene loading has such different constraints to both regular asset loading and regular gameplay systems, maybe it could even make sense to just do the core in-memory format as an asset, without actually creating a scene at all, and then do initialisation in a subapp or something so you get the full power of the ECS. Configuration could still be done in the regular world and/or with extension methods on the app/world and the fact that it uses a sub-app would be an implementation detail.
Although having said that, you don’t need it to continuously run
So that’s probably not the right abstraction
Just thought through it, I don't think we need render modes to be handled in the scene world, if we don't mind a possible 1-frame delay before windows are transparent
1 frame delay isn’t the end of the world because you can start it disabled
I am not sure what you mean by "core in-memory format as an asset"
Like, just the BspData without any handles, which would be processed by whatever the replacement for hooks is, then once all processing is done the handles would be created and the scene would be considered ready
Also I don't think a subapp would be more powerful than the current solution in terms of ECS, everything (like systems and resources) is stored and handled in the World struct anyway
I actually think that passing the loadcontext would be fine, you’d just need it to pass it as an In(..)-style parameter https://docs.rs/bevy/latest/bevy/prelude/struct.World.html#method.run_system_with
Stores and exposes operations on entities, components, resources, and their associated metadata.
Like, if you had some SQuakeSpawnView that implemented SystemInput<Inner<'a> = QuakeSpawnView<'a>>
Oooh, I did not know about this
Yeah I actually didn’t realise either 😅 I use SystemIds for my console commands and thought I had to clone the arguments to pass them into the systems that implement the commands, I should look into changing that
Can we call an entire schedule with an input is the question
I guess I could just store a Vec of SystemIds, but it'd be cool if I didn't have to
I mean, if the input is a mutable borrow then you need to run all the systems serially anyway
Oh that's true
You can still use schedules to get all the nice ordering constraint stuff but then ultimately just read the execution graph and run all the systems in a loop
That sounds good. I think I have a pretty good idea of that this'd look like now, I'll get to prototyping :)
Nice! I’d love if you pinged me if/when you’ve got a draft PR up, this is very interesting and I’m currently using my own fork of bevy_trenchbroom because the hook system doesn’t fit my (admittedly very unconventional) needs 😅 From this chat I think that this would address my needs
This is what I mean by the execution graph btw, since I had the page open anyway I might as well link you it in case it’s useful https://docs.rs/bevy/latest/bevy/ecs/schedule/struct.ScheduleGraph.html#method.dependency
Metadata for a Schedule.
Oh wait, even more useful. Just ScheduleGraph::topsort_graph::<SystemKey> https://docs.rs/bevy/latest/bevy/ecs/schedule/struct.ScheduleGraph.html#method.topsort_graph
Metadata for a Schedule.
@halcyon frigate It doesn't look like schedule graphs support systems with inputs or outputs unfortunately
We might just have to stick to a Vec<SystemId>
Another problem, &'l mut LoadContext<'w> would need both the 'l (local), and 'w (main world) lifetimes, and SystemInput only supplies one
Looks like LoadContext only uses its lifetime parameter for the AssetServer, if only it cloned an Arc of it
This is looking less and less promising
You could probably work around it since it uses SystemKeys, so you could maintain the graph and the systems separately, but for an initial implementation it’s probably better to keep it simple anyway
Now that’s definitely more of a pain
You could create a new LoadContext with begin_labeled_asset so you don't need to worry about 'l, you're loading a #Scene subasset anyway
Then you’ll only have one lifetime
I made an issue on the Bevy github about adding In/Out type parameters to schedules, in case you’re interested https://github.com/bevyengine/bevy/issues/21658
Posted on that issue, but with some mildly-hairy uses of unsafe it could be possible to have a library for scoped non-'static resources
We could do that, apparently I didn't know you could transmute between lifetimes
// Insert as a non-send resource
pub struct LoadContextRes {
ptr: *mut LoadContext<'static>,
}
impl LoadContextRes {
pub unsafe fn new(load_context: &mut LoadContext) -> Self {
Self { ptr: unsafe { std::mem::transmute(load_context) } }
}
}
Not the prettiest Rust in the world, but the more I poke around, the more it seems like this about the best we can do without that issue you posted being resolved
(We could also make it not a pointer with the trick you described above)
After making that issue, do you still think this is possible? From what I've seen the graph stores the systems themselves
I was thinking that you’d need to use dummy systems as a facsimile of the real systems (which I guess would be in a hashmap or something) but making the issue def makes me think that, firstly, that would be even more of a filthy hack than I originally thought, and secondly, it’s probably possible to have a cleaner solution
Heh, TIL
I do worry that there’s going to be some way of taking it out of the World (e.g with a &mut World-taking system), maybe the static type would have to be private and only the public <LoadContextRes as SystemParam>::Inner<'a> type would be publicly-exported (so it can be a parameter to the systems)
That's a good point. Edge cases like that are why I'm very weary shipping this type of code
Yep 🙃
I don't trust myself to catch every one of them
Even if this gets implemented quickly, we would still have to wait until 0.18 for it to land
Unless we have any other options, perhaps we consider this non-blocking for the next release, and keep the branch in wait for now?
@halcyon frigate You mentioned replacing spawn hooks with your own system, right? What exactly did you replace it with?
It’s not a better system, it’s just that the hooks didn’t allow me to make the map loading work the way I wanted (where I kinda want to go in the opposite direction, loading it as a bag of models where each model in the model lump is its own sub-asset) so I forked it to hard-code that
I can’t remember exactly what I changed and I’m not even 100% sure it’s necessary 😅 I just wanted to get it working
I’m slowly converging on a clean codebase but at any given time one system or other is in a dire state as I do a big refactor
Like, I think that loading each model as a complete subasset with a predictable name required forking, I’m just not sure if the rest of the changes were necessary
following up on this; i was able to fix my problems and restore functionality to before the upgrade by using this simple-ish system:
fn fix_target_tb_entities(
mut commands: Commands,
mut entities: Query<(Entity, &Transform, &Collider), With<Target>>,
) {
for (entity, tf, coll) in entities.iter_mut() {
if let Some(shape) = coll.shape().as_compound() {
let mut shapes: Vec<> = shape.shapes().iter().cloned().collect();
for shape in shapes.iter_mut() {
shape.0.translation.vector -= SVector::<f32, 3>::from(tf.translation.to_array());
}
commands
.entity(entity)
.insert(Collider::from(SharedShape::compound(shapes)));
}
}
}
