overriding drawing order scene2D's stage

耗尽温柔 提交于 2019-12-09 16:06:27

问题


You are given a complex Scene2D graph in libgdx with several Group's and Actor's. You want the user to select some Actors and draw those at the end so they appear focussed on top of any other Actors.

I would like to iterate over the Stage twice. The first time it draws the unselected Actors, the second time it draws the selected actors. I don't see any 'good' way to enforce this behaviour however.

I would prefer options that are clean. I would not like to copy an entire method implementation just for the sake of this small addition.

What doesn't work:

  • the Actor's toFront() method only works for it's siblings.
  • swapping places of Actor's in the Stage: this modifies the transformations the Actors have.

Scenario to think about: you have a Root with a group gA and a group gB. Group gA contains two images iA1 and iA2. Group gB contains one image iB. Given that Group gA is added first to the stage and that image iA1 overlaps with iB; now you want to select iA1 and make it appear over iB. I don't want to only call gA.toFront(); this would put the whole Group gA to the front, which means also iA2 is put to the front. Putting iA2 in front has the undesired effect of hiding parts of images inside Group gB


回答1:


There are two solutions-

1 - Stop using [multiple] groups. Sucks but this may be the easier option. If you look at how rendering/drawing is done you start at the root Group for a Stage and get its children and render them. For each of those children, if they are a Group then render that Groups children. ZIndex is nothing more than the order of children within a group. If you look at the Actor's setZIndex you can see why toFront or setZIndex only affect siblings.

public void setZIndex (int index) {
    if (index < 0) 
        throw new IllegalArgumentException("ZIndex cannot be < 0.");

    Group parent = this.parent;
    if (parent == null) 
        return;

    Array<Actor> children = parent.getChildren();
    if (children.size == 1) 
        return;

    if (!children.removeValue(this, true)) 
        return;

    if (index >= children.size)
        children.add(this);
    else
        children.insert(index, this);
}

2 - The only other option would be to change the drawing order of all the actors. You'd have to extend Stage and replace the draw method to draw based on a different order of your choosing. You'd probably have to incorporate a lot of the functionality from the Group.drawChildren method.

TLDR; The way things are implemented in LibGDX - a Group is a layer. If you don't want layers then either change what groups do or stop using groups.




回答2:


You can work around this by overriding draw on the parent:

Group parent = new Group() {
    // Do not render the child as we will render it later
    @Override
    protected void drawChildren(Batch batch, float parentAlpha) {
        child.setVisible(false);
        super.drawChildren(batch, parentAlpha);
        child.setVisible(true);
    }

    // Render the child after the draw method so it's always on top
    @Override
    public void draw(Batch batch, float parentAlpha) {
        super.draw(batch, parentAlpha);
        child.draw(batch, parentAlpha);
    }
};

Group child = new Group();
parent.addActor(child);


来源:https://stackoverflow.com/questions/21839302/overriding-drawing-order-scene2ds-stage

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!