All Articles

Tuesday Time #7 - Tuesday Time

Tuesday Time

And we’re back. On Tuesdays now.

Let’s get it good.


Let’s begin with sort of a glimpse into what technical development is like when you’re an asshole who doesn’t know what they’re doing and is just beating on things until they work.

(For the moment) Bevy only really exposes a pretty low level input system. There’s click events and you can get mouse cursor position but there’s no real higher level “mouse is over thing” or “mouse is clicking on ui” api.

This isn’t really an issue but it means you have to do a bit more work. For example, if you want to do something when you click on the world such as click and drag to place a wall, if you just check the basic input events it will treat even clicks on interfaces as being “click inputs.”

So naturally actually having your ui “block clicks” from going down to the world view is a fairly common problem so I go and ask in the bevy discord “hey is there an easy way to do this thing?” Naturally the answer I got was “no not really” because there’s not an easy way to do it in a generic capacity that will work regardless of how you’re handling ui elements. I talked a bit about methods of handling this, and it seemed like something a few people were doing that I had considered was to just check if the cursor is in the bounds of the UI before handling world clicks. I didn’t really like this solution but figured I would have to do it eventually. I just wanted a quick hack in the mean time, so I did that.

I then put it aside, not wanting to actually write that, and came back a few weeks later ready to actually fully implement it.

I’m using bevy_egui which provides a clean api way of using egui, an immediate mode ui renderer, into bevy. Bevy has a built in ui system but it’s a bit unfinished and the API is awkward so egui provides a more finished and easier to use system to really quickly draft interfaces.

There was just one major problem.

While the Bevy ui system works directly with the ECS system and draws ui based on entities with ui components, egui is made to be easy to plug into any system and renderer and so doesn’t do that. Now I need to figure out some way of getting all UIs to know their regions, so I ended up digging into the egui documention.

While browsing the egui documention, I ended up discovering that the context struct used to draw UIs actually exposed a function called “wants cursor” or some crap like that I’m too lazy to look it up now. And would you look at that, it’s whether or not ui elements “want the cursor,” ie is the mouse currently over a ui region of any sorts. And it even would properly handle things like a click drag that starts on a world view! Score! Easy implementation!

So I quickly plugged this into my system to provide the status of the cursor and then quickly realized something about it. It worked as intended for windows! Except it didn’t for panels.

With egui “windows” are floating boxes that contain things and can be configured to be anchored or draggable by the user and so on etc etc, while “panels” occupy an entire side of the view and aren’t movable by the user. For whatever reason the “wants cursor” function didn’t like panels. But that’s ok, because egui also has a function off the context to get the remaining region of the view that isn’t occupied by panels!

So then I can just use the value of the “wants cursor” part and if it’s false check if the cursor is inside the remaining region and still have a pretty simple implementation! I still am not sure why but for some reason the “available space” reported by egui was very sporadically incorrect. I think this has something to do with bevy’s internal system scheduler and the order things would run in but I don’t really know. Sometimes it was the real remaining space, and sometimes it changed between the correct space and the whole region every frame. Great.

Naturally the solution to this was to store what the last frame reported and then just use whichever one was smaller because that’s the real remaining space. This galaxy brained hack didn’t work because also sometimes it was just always reporting the whole window region. Awesome.

So then I started writing this system to have fixed sizes for each panel so I could hand calculate my own real remaining space and it was a pain in the ass and sucked and was annoying to work with and-

Then I realized.

“wait why does it even have to be a panel in the first place.”

I changed it to a window, and boom problem solved and it actually looked nicer in the process. See the slightly improved control bar in the video below.

So now I have a very clean api to check if the mouse cursor is currently on a ui element or the game world, and the implementation is one line. What a way to spend a day’s work.


Because everything I do has to be done in nonsensical orders, I figured “hey I should implement a grid overlay and preview cursor before actually writing the part that does the actual real fucking game functionality.”

So here’s a (100% real) little clip of that

Wow! It’s a lie!

I just did a quick hack to show intended functionality for that clip, and it’s done pretty sloppily. Instead of rendering as part of the actual map pass it’s just an extra shape entity of the correct size overlaid on top.

It’s using an extension bevy_prototype_lyon to actually draw it as a batched mesh that’s pre-pushed to the gpu. It’s borderline free to actually render as a result which is awesome. Also means it moves around and scales super cleanly.

I need to properly hook it into the tilemap renderer so it can be chunked and occluded based on the visibility and this uses parts of Bevy I’m unfamiliar with. Ran out of time because I forever procrastinate.

The selection/preview cursor following the cursor exactly was mostly just to test the spawning and despawning of it. Actual tracking and shifting on the grid Coming Soon.


That’s about it, trying to get more into the flow of things after being pretty out of it for a few weeks.

Hopefully going to have a workable and extendable version of construction by next update, and I want to get entities pathfinding around the grid cleanly.

I need a better name idea than “Tuesday Time” so shout at me ideas in my discord or something.

ai something something.