Reputation: 6545
The basic premise is that I have 2 Android Views... A background view that fills the screen (ImageView
in this case), and a LibGDX GLSurfaceView
that is in the foreground, and is the LibGDX
application. I want to punch a hole in the LibGDX GLSurfaceView
, so that I can see the background ImageView
show through. ie, the LibGDX
part is behaving like an overlay. Sadly I cannot get this to work at all. I've stripped away all the code to leave just the bare necessities that hopefully demonstrate what I'm trying to do.
In the full application, it is an Android application where the background View
is a Video, and the foreground, being rendered by LibGdx
is a set of video controls, that needs to be overlaid on the video.
public class MiniClientGDXTestActivity extends AndroidApplication implements ApplicationListener {
@Bind(R.id.surface)
FrameLayout uiFrameHolder;
Stage stage;
Batch batch;
Camera camera;
Viewport viewport;
ShapeRenderer shapeRenderer;
private View miniClientView;
public MiniClientGDXTestActivity() {
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
hideSystemUI(this);
setContentView(R.layout.miniclientgltest_layout);
ButterKnife.bind(this);
AndroidApplicationConfiguration cfg = new AndroidApplicationConfiguration();
//cfg.useGL20 = false;
// we need to change the default pixel format - since it does not include an alpha channel
// we need the alpha channel so the camera preview will be seen behind the GL scene
cfg.r = 8;
cfg.g = 8;
cfg.b = 8;
cfg.a = 8;
miniClientView = initializeForView(this, cfg);
if (graphics.getView() instanceof SurfaceView) {
SurfaceView glView = (SurfaceView) graphics.getView();
glView.setBackgroundColor(android.graphics.Color.TRANSPARENT);
// force alpha channel - I'm not sure we need this as the GL surface is already using alpha channel
glView.getHolder().setFormat(PixelFormat.TRANSLUCENT);
}
uiFrameHolder.addView(miniClientView);
}
@Override
public void create() {
camera = new OrthographicCamera();
viewport = new StretchViewport(1920, 1080, camera);
stage = new Stage(viewport);
batch = stage.getBatch();
shapeRenderer = new ShapeRenderer();
Gdx.graphics.setContinuousRendering(false);
Gdx.graphics.requestRendering();
}
@Override
public void resize(int width, int height) {
stage.getViewport().setWorldSize(1920, 1080);
stage.getViewport().update(width, height, true);
Gdx.graphics.requestRendering();
}
@Override
public void render() {
Gdx.gl20.glClearColor(0, 0, 0, 0);
Gdx.gl20.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
// draw whatever we have on the stage
stage.draw();
// draw red rectangle
drawRect(10, 10, 1000, 1000);
// draw a blue box
fillRect(50, 50, 800, 800);
// punch a hole in the surface (ie, clear an area) so that we can see the view that is
// behind this view
clearRect(200, 200, 1600, 600);
}
@Override
public void pause() {
}
@Override
public void resume() {
}
@Override
public void dispose() {
}
public void drawRect(final int x, final int y, final int width, final int height) {
shapeRenderer.setProjectionMatrix(camera.combined);
shapeRenderer.begin(ShapeRenderer.ShapeType.Line);
shapeRenderer.rect(x, y, width, height, Color.RED, Color.RED, Color.RED, Color.RED);
shapeRenderer.end();
}
public void fillRect(final int x, final int y, final int width, final int height) {
shapeRenderer.setProjectionMatrix(camera.combined);
shapeRenderer.begin(ShapeRenderer.ShapeType.Filled);
shapeRenderer.rect(x, y, width, height, Color.BLUE, Color.BLUE, Color.BLUE, Color.BLUE);
shapeRenderer.end();
}
public void clearRect(final int x, final int y, final int width, final int height) {
// Gdx.gl.glEnable(GL20.GL_BLEND);
// Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
shapeRenderer.setProjectionMatrix(camera.combined);
shapeRenderer.begin(ShapeRenderer.ShapeType.Filled);
shapeRenderer.setColor(Color.CLEAR);
shapeRenderer.rect(x, y, width, height);
shapeRenderer.end();
// Gdx.gl.glDisable(GL20.GL_BLEND);
}
}
And here's the XML layout
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent"
android:keepScreenOn="true">
<FrameLayout
android:visibility="visible"
android:id="@+id/surface"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<!-- to see if we can see this -->
<ImageView
android:layout_width="fill_parent"
android:layout_height="match_parent" android:scaleType="fitXY" android:src="@drawable/background"/>
<!-- gdx gets added here -->
</FrameLayout>
</FrameLayout>
Upvotes: 4
Views: 1147
Reputation: 6545
It would appear that calling setZOrderOnTop
with using PixelFormat.RGBA_8888
did the trick.
if (graphics.getView() instanceof SurfaceView) {
GLSurfaceView glView = (GLSurfaceView) graphics.getView();
glView.setZOrderOnTop(true);
glView.getHolder().setFormat(PixelFormat.RGBA_8888);
}
now when the clearRect
method is called it will punch a hole in the GLSurfaceView to see the Android view that is below.
Upvotes: 4