afonsolage / bevy_ecss

Bevy crate which uses a subset of CSS to update Bevy ECS components
Apache License 2.0
98 stars 11 forks source link

Changes to `Class` do not get applied (even with manual `StyleSheet` refresh) #62

Open Zeenobit opened 4 months ago

Zeenobit commented 4 months ago

I've managed to get most of this crate functional in my project by having a root UI node with a couple of style sheets. I have a system which refreshes my stylesheet on any changes:

fn refresh_style(
    added_nodes: Query<(), Added<Node>>,
    removed_nodes: RemovedComponents<Node>,
    changed_classes: Query<(), Changed<Class>>,
    mut style_sheet: Query<&mut StyleSheet>,
) {
    let root_entity: Entity = ...;
    if !added_nodes.is_empty() || !removed_nodes.is_empty() || !changed_classes.is_empty() {
        style_sheet.get_mut(root_entity).unwrap().refresh();
    }
}

This system runs in Update schedule after all my UI logic is finished. Specifically, it runs after a system which adds/removes a class to a specific node:

fn refresh_panel(
    mut query: Query<&mut Class, With<ControlPanel>>,
    control_targets: ResMut<ControlTargets>,
) {
    if control_targets.is_changed() {
        let mut class = query.single_mut();
        if control_targets.is_empty() {
            class.add("hide");
        } else {
            class.remove("hide");
        }
    }
}

The style is defined as:

.hide {
    display: none;
}

#ControlPanel {
    display: flex;
    width: 400px;
    min-height: 200px;
    align-self: flex-start;
    flex-direction: column;
    background-color: pink;
}

I've verified that this class does indeed get added. If I turn on tracing for bevy_ecss, I do get:

2024-04-30T16:33:11.177898Z TRACE bevy_ecss::system: Applying rule (#ControlPanel) on 1 entities
...
2024-04-30T16:33:11.178392Z TRACE bevy_ecss::system: Tracking element Class("hide"): 1
2024-04-30T16:33:11.178459Z TRACE bevy_ecss::system: Applying rule (.hide) on 1 entities
2024-04-30T16:33:11.178687Z TRACE bevy_ecss::system: StyleSheetState resource changed! Skipping watch tracked entities

However, the observed behavior is that display is always set to flex. Despite the .hide class being added/removed correctly and the style sheet getting refreshed.

At this point I'm not sure if this an issue with my CSS, setup, or the crate. As far as I can tell, my setup and CSS is fine, although my CSS knowledge is a bit outdated; so it's entirely possible the issue is on my end. :)

Any help would be appreciated!

Zeenobit commented 4 months ago

So far, I've tried all of the following, and nothing seems to work:

I've been trying to debug the crate on my own, but I'm having trouble understanding how/where the class rules are being applied. Based on my debugging so far, my entity is definitely being picked up by select_entities_node. But I can't find where the class rules are actually being applied after a .refresh() request is sent out.

I've been looking at the examples as well, and as far as I can tell, none of them deal with adding/removing classes dynamically. Is this supported at all?

Any information would be greatly appreciated!

Zeenobit commented 4 months ago

I managed to solve it by defining #ControlPanel.hide as an explicit rule:

#ControlPanel.hide {
    display: none;
}

Note the difference between #ControlPanel.hide and #ControlPanel .hide from my previous comment. 🫠 It would've been amazing if these types of issues generated warnings/errors.

For some reason, having the class defined globally as .hide doesn't work at all.