3

I'm trying to create a "progress bar" of sorts but the clipping doesn't seem to work the way I expect it to. Is this something I am doing wrong or something I've misinterpreted?

The draw() routine that should clip:

    @Override
    public void draw(SpriteBatch batch, float parentAlpha) {
        Rectangle scissors = new Rectangle();
        Rectangle clipBounds = new Rectangle(getX(), getY(), getWidth() * 0.75f, getHeight());

        ScissorStack.calculateScissors(
                getStage().getCamera(),
                getStage().getGutterWidth(),
                getStage().getGutterHeight(),
                getStage().getCamera().viewportWidth,
                getStage().getCamera().viewportHeight,
                batch.getTransformMatrix(),
                clipBounds, scissors);

        if (ScissorStack.pushScissors(scissors)) {
            super.draw(batch, parentAlpha);
            ScissorStack.popScissors();
        }
    }
}

Complete sample code for ClipTest group class, TestScreen and screenshot.

enter image description here

  • ClipTest is a subclass of group used to demonstrate the "bug".
  • ClipImage is a subclass of Image, which performs the clipping on draw().
  • ClipTest has 2 images, background and foreground.

The background is a black image and it should always be the full size of the progress bar.

The foreground is a white image and it's width is clipped depending on the percentage of the bar.

The strange result I've found is that although the foreground is using the clipping class, the background image is the one actually clipped.

The expected result was created using photoshop (as I couldn't produce it via code).

Any idea what's wrong?

P.T.
  • 24,557
  • 7
  • 64
  • 95
twig
  • 4,034
  • 5
  • 37
  • 47
  • I know you said "of sorts" so it might not be what you need but just in case you don't know about it - if you get a nightly release then there is a progress bar http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/scenes/scene2d/ui/ProgressBar.html – Chase Apr 06 '14 at 06:07
  • @Chase: I was really tempted to do that, but it also broke my project because of all the other syntax changes (constructors for stage was changed, etc). I was hoping this would be a small oversight, which it turned out to be – twig Apr 06 '14 at 08:40
  • You should probably ask this on http://gamedev.stackexchange.com instead – ashes999 May 31 '14 at 20:29

1 Answers1

5

Actual drawing doesn't happen until the Batch "flushes", its not the draw call you need to wrap, as that just queues up drawing to be done later.

You need to make sure the OpenGL draw calls happen between enabling and disabling your scissors, so add a flush after the draw. See https://github.com/libgdx/libgdx/wiki/Clipping,-with-the-use-of-scissorstack

Because a draw call might cause a flush to happen, you need to keep the draw calls inside the active-scissor region. You may also need to flush or end the batch before starting the active scissor region to prevent queued draw calls from before the scissor start getting flushed inside the active scissor region.

P.T.
  • 24,557
  • 7
  • 64
  • 95
  • 1
    YES!!! It's been 3 days now and thank you for restoring my sanity! That advice was perfect and lead me on the right path. For those wondering, I had to call batch.flush() at the start of my draw() override to ensure everything was drawn out as expected before continuing with the clipping. Another call to batch.flush() was needed after super.draw() in order to make sure the right content was being snipped. – twig Apr 06 '14 at 08:37
  • 1
    @P.T. Flushing before enabling scissors did the trick for me. BTW, I have updated the link and also updated original wiki with the excerpt from your answer. – Denys Kniazhev-Support Ukraine Nov 21 '15 at 14:30