There is an on-add hook that can be used to maintain invariants. I'll
use it to ensure the label text always gets the current fuel value upon
spawning the widget, regardless of whether or not the caller remembers
to set it up themselves.
This does a linear search through all existing FuelGauges, but we're not
expecting that to be a problem. There should only be zero or one of them
on screen at any moment.
It also doesn't work because the rest of the game state isn't correct...
The UIs aren't *any* UIs. They are specifically *machine* UIs. They need
to be able to fetch data from components on those machine entities,
which means they need some way to find the machine. Passing an entity ID
is the easiest way, IMO.
Added a `FuelChanged` event which is to be used to trigger Observers
watching for a machine's fuel level change.
I've written a slapdash observer to emit these events when the cutting
machine's big red button is pressed. That observer *must* be replaced
because of how it feeds the machine ID into the UI (it only works when
there is exactly 1 CuttingMachine, which won't be the case).
The dummy machines are missing their machine components. I've added the
`CuttingMachine` component to the cutting machine just to test the event
passing.
Spawn a machine entity for each kind of machine. This is where the trait
impl becomes important -- now the compiler will make copies of that
function for each concrete machine struct so I don't have to.
This finally shows the basic operating principle of the machine UIs.
There will be some object out in the world that, when clicked, will open
a new UI screen to operate the machine.
Next up is to attach various bits of info, like a `Fuel` component on
the machine which the UI widget locates and displays as text. This gives
me the infrastructure necessary to begin that work.
Normally this would be a compilation error, but Bevy has an
`impl Bundle for ()` somewhere.
The intended bundle content gets discarded and a unit is implicitly
returned. That unit is implicitly converted into a `Bundle`, satisfying
the compiler.
The `BigRedButton` should be a real struct and component so that I can
query for it later.
I'm following the same API pattern as the `CloseButton` struct, in that
there is a spawner using the `Commands` (or `ChildSpawnerCommands`) and
the observer functions are static methods.
That was much easier than I expected it to be. I'm still going to alter
how the `machine_ui_base` function works so that I don't have to
remember to attach a button all the time.
I was originally planning to search up the entity hierarchy to find the
top-most entity and despawn that. This will become a problem if I ever
want to have panels in panels.
Instead, just record the target entity and despawn it.
This means the current usage doesn't work, so I've removed it from the
base machine UI bundle.
I'm trying out a new scope strategy. The CloseButton exists as a real
struct with the `Component` trait. There's a bundle spawning utility
function and several observer systems. The observer systems have been
added directly to the app, which I *believe* means they won't be
duplicated the way the Big Red Button's observers will.
Fixed struct field visibility, initialize the resource, and register it
with the EGUI Debug overlay. The button observers have also been updated
to use the resource.
Observers are "just" systems with a Trigger as their first parameter.
I've made 4 systems to handle the start and stop of the press and hover
actions.
Having the button *actually* do something (not just change colors) will
be achieved by attaching another button to the on-press trigger. I'm
expecting that the machine-ui-spawning system will do that, but in
principle it could be done by anything with access to the UI's button
entity ID.