Libgdx - How to draw filled rectangle in the right place in scene2d?

ShapeRenderer has its own transform matrix and projection matrix. These are separate to those in the SpriteBatch that the scene2d Stage uses. If you update the ShapeRenderer's matrices to match those that scene2d is using when Actor.draw() is called then you should get the results that you want.


The best solution for me. Cause when you using ShapeRenderer it's doesn't react on moving/zooming camera.

public class Rectangle extends Actor {

    private Texture texture;

    public Rectangle(float x, float y, float width, float height, Color color) {
        createTexture((int)width, (int)height, color);
        setX(x);
        setY(y);
        setWidth(width);
        setHeight(height);
    }

    private void createTexture(int width, int height, Color color) {
        Pixmap pixmap = new Pixmap(width, height, Pixmap.Format.RGBA8888);
        pixmap.setColor(color);
        pixmap.fillRectangle(0, 0, width, height);
        texture = new Texture(pixmap);
        pixmap.dispose();
    }
    
    @Override
    public void draw(Batch batch, float parentAlpha) {
        Color color = getColor();
        batch.setColor(color.r, color.g, color.b, color.a * parentAlpha);
        batch.draw(texture, getX(), getY(), getWidth(), getHeight());
    }
}

As Rod Hyde mentions, ShapeRenderer has its own transform matrix and projection matrix. So you would have to get the SpriteBatch's projection Matrix first. I am not sure if there is an elegant way to do it, I did it like this:

public class myActor extends Actor{

    private ShapeRenderer shapeRenderer;
    static private boolean projectionMatrixSet;

    public myActor(){
        shapeRenderer = new ShapeRenderer();
        projectionMatrixSet = false;
    }

    @Override
    public void draw(SpriteBatch batch, float alpha){
        batch.end();
        if(!projectionMatrixSet){
            shapeRenderer.setProjectionMatrix(batch.getProjectionMatrix());
        }
        shapeRenderer.begin(ShapeType.Filled);
        shapeRenderer.setColor(Color.RED);
        shapeRenderer.rect(0, 0, 50, 50);
        shapeRenderer.end();
        batch.begin();
    }
}