From 7c9d17f5ca9c49c6d62df6d35d50de37b2a26cef Mon Sep 17 00:00:00 2001 From: Gabriel Machado <97042217+GabrielBRDeveloper@users.noreply.github.com> Date: Tue, 28 Nov 2023 14:54:10 -0400 Subject: [PATCH] TouchScreen input (#6) --- .../panda3ds/pandroid/app/GameActivity.java | 20 ++- .../com/panda3ds/pandroid/math/Vector2.java | 14 +- .../pandroid/view/PandaGlRenderer.java | 78 +++++---- .../pandroid/view/PandaGlSurfaceView.java | 36 +++- .../pandroid/view/PandaLayoutController.java | 2 + .../view/controller/ControllerLayout.java | 14 +- .../view/controller/ControllerNode.java | 4 + .../controller/nodes/TouchScreenNodeImpl.java | 39 +++++ .../view/renderer/ConsoleRenderer.java | 9 + .../view/renderer/layout/ConsoleLayout.java | 15 ++ .../renderer/layout/DefaultScreenLayout.java | 81 +++++++++ .../app/src/main/res/layout/game_activity.xml | 161 +++++++++--------- .../app/src/main/res/values/values.xml | 4 + 13 files changed, 349 insertions(+), 128 deletions(-) create mode 100644 src/pandroid/app/src/main/java/com/panda3ds/pandroid/view/controller/nodes/TouchScreenNodeImpl.java create mode 100644 src/pandroid/app/src/main/java/com/panda3ds/pandroid/view/renderer/ConsoleRenderer.java create mode 100644 src/pandroid/app/src/main/java/com/panda3ds/pandroid/view/renderer/layout/ConsoleLayout.java create mode 100644 src/pandroid/app/src/main/java/com/panda3ds/pandroid/view/renderer/layout/DefaultScreenLayout.java create mode 100644 src/pandroid/app/src/main/res/values/values.xml diff --git a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/app/GameActivity.java b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/app/GameActivity.java index 5c234423..53fb1805 100644 --- a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/app/GameActivity.java +++ b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/app/GameActivity.java @@ -2,24 +2,20 @@ package com.panda3ds.pandroid.app; import android.content.Intent; import android.os.Bundle; -import android.util.Log; -import android.view.KeyEvent; -import android.view.MotionEvent; +import android.os.Handler; import android.view.View; import android.view.ViewGroup; +import android.view.WindowManager; import android.widget.CheckBox; -import android.widget.CompoundButton; import android.widget.FrameLayout; import android.widget.Toast; import androidx.annotation.Nullable; -import com.panda3ds.pandroid.AlberDriver; import com.panda3ds.pandroid.R; import com.panda3ds.pandroid.utils.Constants; import com.panda3ds.pandroid.view.PandaGlSurfaceView; import com.panda3ds.pandroid.view.PandaLayoutController; -import com.panda3ds.pandroid.view.controller.ControllerLayout; public class GameActivity extends BaseActivity { private PandaGlSurfaceView pandaSurface; @@ -46,11 +42,21 @@ public class GameActivity extends BaseActivity { .addView(pandaSurface, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); controllerLayout = findViewById(R.id.controller_layout); + controllerLayout.initialize(); ((CheckBox)findViewById(R.id.hide_screen_controller)) .setOnCheckedChangeListener((buttonView, isChecked) -> { - controllerLayout.setVisibility(isChecked ? View.VISIBLE : View.INVISIBLE); + findViewById(R.id.overlay_controller) + .setVisibility(isChecked ? View.VISIBLE : View.INVISIBLE); }); + + } + + @Override + protected void onResume() { + super.onResume(); + getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION); + getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); } } diff --git a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/math/Vector2.java b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/math/Vector2.java index 9c5b45b7..541d45e1 100644 --- a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/math/Vector2.java +++ b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/math/Vector2.java @@ -2,13 +2,8 @@ package com.panda3ds.pandroid.math; public class Vector2 { public float x,y; - - public Vector2(){ - this(0.0f); - } - - public Vector2(float value){ - this(value,value); + public Vector2(Vector2 value){ + this(value.x,value.y); } public Vector2(float x, float y){ @@ -23,4 +18,9 @@ public class Vector2 { public static float distance(float x, float y, float x2, float y2){ return (float) Math.sqrt((x - x2) * (x - x2) + (y - y2) * (y - y2)); } + + public void set(float x, float y) { + this.x = x; + this.y = y; + } } diff --git a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/view/PandaGlRenderer.java b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/view/PandaGlRenderer.java index b6be4df2..e6adbd9f 100644 --- a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/view/PandaGlRenderer.java +++ b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/view/PandaGlRenderer.java @@ -6,17 +6,19 @@ import javax.microedition.khronos.opengles.GL10; import static android.opengl.GLES32.*; import android.content.res.Resources; +import android.graphics.Rect; import android.opengl.GLSurfaceView; import android.util.Log; import com.panda3ds.pandroid.AlberDriver; -import com.panda3ds.pandroid.utils.Constants; +import com.panda3ds.pandroid.view.renderer.layout.ConsoleLayout; +import com.panda3ds.pandroid.view.renderer.ConsoleRenderer; +import com.panda3ds.pandroid.view.renderer.layout.DefaultScreenLayout; -import java.util.ArrayList; - -public class PandaGlRenderer implements GLSurfaceView.Renderer { +public class PandaGlRenderer implements GLSurfaceView.Renderer, ConsoleRenderer { private final String romPath; + private ConsoleLayout displayLayout; private int screenWidth, screenHeight; private int screenTexture; public int screenFbo; @@ -24,6 +26,10 @@ public class PandaGlRenderer implements GLSurfaceView.Renderer { PandaGlRenderer(String romPath) { super(); this.romPath = romPath; + + screenWidth = Resources.getSystem().getDisplayMetrics().widthPixels; + screenHeight = Resources.getSystem().getDisplayMetrics().heightPixels; + setLayout(new DefaultScreenLayout()); } @Override @@ -40,8 +46,6 @@ public class PandaGlRenderer implements GLSurfaceView.Renderer { public void onSurfaceCreated(GL10 unused, EGLConfig config) { Log.i("pandroid", glGetString(GL_EXTENSIONS)); Log.w("pandroid", glGetString(GL_VERSION)); - screenWidth = Resources.getSystem().getDisplayMetrics().widthPixels; - screenHeight = Resources.getSystem().getDisplayMetrics().heightPixels; glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); @@ -71,40 +75,48 @@ public class PandaGlRenderer implements GLSurfaceView.Renderer { glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); glBindFramebuffer(GL_READ_FRAMEBUFFER, screenFbo); - if (screenWidth > screenHeight) { - int topDisplayWidth = (int)((screenHeight / (float)Constants.N3DS_HEIGHT) * Constants.N3DS_WIDTH); - int topDisplayHeight = screenHeight; + Rect topScreen = displayLayout.getTopDisplayBounds(); + Rect bottomScreen = displayLayout.getBottomDisplayBounds(); - if (topDisplayWidth > screenWidth * 0.7){ - topDisplayWidth = (int)(screenWidth * 0.7); - topDisplayHeight = (int)((topDisplayWidth / (float)Constants.N3DS_WIDTH) * Constants.N3DS_HEIGHT); - } + glBlitFramebuffer( + 0, 480, + 400, 240, + topScreen.left, screenHeight - topScreen.top, + topScreen.right, screenHeight - topScreen.bottom, + GL_COLOR_BUFFER_BIT, GL_LINEAR); - int bottomDisplayHeight = (int)(((screenWidth - topDisplayWidth) / 320) * Constants.N3DS_HEIGHT); - int topDisplayY = screenHeight - topDisplayHeight; - int bottomDisplayY = screenHeight - bottomDisplayHeight; - - glBlitFramebuffer(0, Constants.N3DS_HEIGHT, - Constants.N3DS_WIDTH, Constants.N3DS_HEIGHT * 2, - 0, topDisplayY, - topDisplayWidth,topDisplayY+topDisplayHeight, - GL_COLOR_BUFFER_BIT, GL_LINEAR); - - glBlitFramebuffer( - 40, 0, - 360, Constants.N3DS_HEIGHT, - topDisplayWidth, bottomDisplayY, - screenWidth,bottomDisplayY+bottomDisplayHeight, - GL_COLOR_BUFFER_BIT, GL_LINEAR); - } else { - int h = (int)((screenWidth / (float)Constants.N3DS_WIDTH) * Constants.N3DS_HEIGHT * 2); - glBlitFramebuffer(0, 0, Constants.N3DS_WIDTH, Constants.N3DS_HEIGHT * 2, 0, screenHeight - h, screenWidth, screenHeight, GL_COLOR_BUFFER_BIT, GL_LINEAR); - } + glBlitFramebuffer( + 40, 240, + 360, 0, + bottomScreen.left, screenHeight - bottomScreen.top, + bottomScreen.right, screenHeight - bottomScreen.bottom, + GL_COLOR_BUFFER_BIT, GL_LINEAR); } } public void onSurfaceChanged(GL10 unused, int width, int height) { screenWidth = width; screenHeight = height; + glDisable(GL_SCISSOR_TEST); + + displayLayout.update(screenWidth, screenHeight); + } + + @Override + public void setLayout(ConsoleLayout layout) { + displayLayout = layout; + displayLayout.setTopDisplaySourceSize(400, 240); + displayLayout.setBottomDisplaySourceSize(320, 240); + displayLayout.update(screenWidth, screenHeight); + } + + @Override + public ConsoleLayout getLayout() { + return displayLayout; + } + + @Override + public String getBackendName() { + return "OpenGL"; } } \ No newline at end of file diff --git a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/view/PandaGlSurfaceView.java b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/view/PandaGlSurfaceView.java index 3b5694ed..9f280393 100644 --- a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/view/PandaGlSurfaceView.java +++ b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/view/PandaGlSurfaceView.java @@ -1,10 +1,22 @@ package com.panda3ds.pandroid.view; import android.content.Context; +import android.graphics.Canvas; import android.opengl.GLSurfaceView; +import android.util.Log; -public class PandaGlSurfaceView extends GLSurfaceView { +import androidx.annotation.NonNull; + +import com.panda3ds.pandroid.math.Vector2; +import com.panda3ds.pandroid.utils.Constants; +import com.panda3ds.pandroid.view.controller.TouchEvent; +import com.panda3ds.pandroid.view.controller.nodes.TouchScreenNodeImpl; +import com.panda3ds.pandroid.view.renderer.ConsoleRenderer; + +public class PandaGlSurfaceView extends GLSurfaceView implements TouchScreenNodeImpl { final PandaGlRenderer renderer; + private int size_width; + private int size_height; public PandaGlSurfaceView(Context context, String romPath) { super(context); @@ -13,4 +25,26 @@ public class PandaGlSurfaceView extends GLSurfaceView { renderer = new PandaGlRenderer(romPath); setRenderer(renderer); } + + public ConsoleRenderer getRenderer() { + return renderer; + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + size_width = getMeasuredWidth(); + size_height = getMeasuredHeight(); + } + + @NonNull + @Override + public Vector2 getSize() { + return new Vector2(size_width, size_height); + } + + @Override + public void onTouch(TouchEvent event) { + onTouchScreenPress(renderer, event); + } } \ No newline at end of file diff --git a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/view/PandaLayoutController.java b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/view/PandaLayoutController.java index 63f328da..e7d9438f 100644 --- a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/view/PandaLayoutController.java +++ b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/view/PandaLayoutController.java @@ -58,5 +58,7 @@ public class PandaLayoutController extends ControllerLayout { .setJoystickListener((joystick, axisX, axisY) -> { AlberDriver.SetCirclepadAxis((int)(axisX*0x9C), (int)(axisY*0x9C)*-1); }); + + refreshChildren(); } } diff --git a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/view/controller/ControllerLayout.java b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/view/controller/ControllerLayout.java index 97c8eb12..1ef93c89 100644 --- a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/view/controller/ControllerLayout.java +++ b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/view/controller/ControllerLayout.java @@ -2,14 +2,18 @@ package com.panda3ds.pandroid.view.controller; import android.content.Context; import android.util.AttributeSet; +import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.widget.RelativeLayout; import com.panda3ds.pandroid.math.Vector2; +import com.panda3ds.pandroid.utils.Constants; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; public class ControllerLayout extends RelativeLayout { @@ -34,8 +38,14 @@ public class ControllerLayout extends RelativeLayout { } public void refreshChildren(){ + ArrayList nodes = new ArrayList<>(); + populateNodesArray(this, nodes); + + //Need Reverse: First view is in back and last view is in front for respect android View hierarchy + Collections.reverse(nodes); + controllerNodes.clear(); - populateNodesArray(this, controllerNodes); + controllerNodes.addAll(nodes); } private void populateNodesArray(ViewGroup group, ArrayList list){ @@ -89,7 +99,7 @@ public class ControllerLayout extends RelativeLayout { float cx = (pos.x - globalPosition[0]); float cy = (pos.y - globalPosition[1]); - if( x > cx && x < cx+size.x && y > cy && y < cy+size.y){ + if(item.isVisible() && x > cx && x < cx+size.x && y > cy && y < cy+size.y){ node = item; break; } diff --git a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/view/controller/ControllerNode.java b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/view/controller/ControllerNode.java index 8b01fa97..a29d08a4 100644 --- a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/view/controller/ControllerNode.java +++ b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/view/controller/ControllerNode.java @@ -18,6 +18,10 @@ public interface ControllerNode { return new Vector2(position[0], position[1]); } + default boolean isVisible(){ + return ((View)this).isShown(); + } + @NonNull Vector2 getSize(); void onTouch(TouchEvent event); diff --git a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/view/controller/nodes/TouchScreenNodeImpl.java b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/view/controller/nodes/TouchScreenNodeImpl.java new file mode 100644 index 00000000..85d1ddd6 --- /dev/null +++ b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/view/controller/nodes/TouchScreenNodeImpl.java @@ -0,0 +1,39 @@ +package com.panda3ds.pandroid.view.controller.nodes; + +import android.graphics.Rect; +import android.util.Log; +import android.view.View; + +import com.panda3ds.pandroid.AlberDriver; +import com.panda3ds.pandroid.R; +import com.panda3ds.pandroid.utils.Constants; +import com.panda3ds.pandroid.view.controller.ControllerNode; +import com.panda3ds.pandroid.view.controller.TouchEvent; +import com.panda3ds.pandroid.view.renderer.ConsoleRenderer; + +public interface TouchScreenNodeImpl extends ControllerNode { + default void onTouchScreenPress(ConsoleRenderer renderer, TouchEvent event){ + + View me = (View) this; + boolean hasDownEvent = me.getTag(R.id.TagEventHasDown) != null && (boolean) me.getTag(R.id.TagEventHasDown); + + Rect bounds = renderer.getLayout().getBottomDisplayBounds();; + + if (event.getX() >= bounds.left && event.getY() >= bounds.top && event.getX() <= bounds.right && event.getY() <= bounds.bottom){ + int x = (int) (event.getX() - bounds.left); + int y = (int) (event.getY() - bounds.top); + + x = Math.round((x/(float)bounds.width())*320); + y = Math.round((y/(float)bounds.height())*240); + + AlberDriver.TouchScreenDown(x,y); + + me.setTag(R.id.TagEventHasDown, true); + } + + if (hasDownEvent && event.getAction() == TouchEvent.ACTION_UP){ + AlberDriver.TouchScreenUp(); + me.setTag(R.id.TagEventHasDown, false); + } + } +} diff --git a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/view/renderer/ConsoleRenderer.java b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/view/renderer/ConsoleRenderer.java new file mode 100644 index 00000000..13ad4d39 --- /dev/null +++ b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/view/renderer/ConsoleRenderer.java @@ -0,0 +1,9 @@ +package com.panda3ds.pandroid.view.renderer; + +import com.panda3ds.pandroid.view.renderer.layout.ConsoleLayout; + +public interface ConsoleRenderer { + void setLayout(ConsoleLayout layout); + ConsoleLayout getLayout(); + String getBackendName(); +} diff --git a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/view/renderer/layout/ConsoleLayout.java b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/view/renderer/layout/ConsoleLayout.java new file mode 100644 index 00000000..781f0abd --- /dev/null +++ b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/view/renderer/layout/ConsoleLayout.java @@ -0,0 +1,15 @@ +package com.panda3ds.pandroid.view.renderer.layout; + +import android.graphics.Rect; + +import com.panda3ds.pandroid.math.Vector2; + +public interface ConsoleLayout { + void update(int screenWidth, int screenHeight); + + void setBottomDisplaySourceSize(int width, int height); + void setTopDisplaySourceSize(int width, int height); + + Rect getBottomDisplayBounds(); + Rect getTopDisplayBounds(); +} diff --git a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/view/renderer/layout/DefaultScreenLayout.java b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/view/renderer/layout/DefaultScreenLayout.java new file mode 100644 index 00000000..a54db8f7 --- /dev/null +++ b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/view/renderer/layout/DefaultScreenLayout.java @@ -0,0 +1,81 @@ +package com.panda3ds.pandroid.view.renderer.layout; + +import android.graphics.Rect; +import android.util.Size; + +import com.panda3ds.pandroid.math.Vector2; + +public class DefaultScreenLayout implements ConsoleLayout { + private final Rect topDisplay = new Rect(); + private final Rect bottomDisplay = new Rect(); + + private final Vector2 screenSize = new Vector2(1.0F, 1.0F); + private final Vector2 topSourceSize = new Vector2(1.0F, 1.0F); + private final Vector2 bottomSourceSize = new Vector2(1.0F, 1.0F); + + @Override + public void update(int screenWidth, int screenHeight) { + screenSize.set(screenWidth, screenHeight); + updateBounds(); + } + + @Override + public void setBottomDisplaySourceSize(int width, int height) { + bottomSourceSize.set(width,height); + updateBounds(); + } + @Override + public void setTopDisplaySourceSize(int width, int height) { + topSourceSize.set(width,height); + updateBounds(); + } + + private void updateBounds(){ + int screenWidth = (int) screenSize.x; + int screenHeight = (int) screenSize.y; + + if (screenWidth > screenHeight){ + + int topDisplayWidth = (int) ((screenHeight / topSourceSize.y) * topSourceSize.x); + int topDisplayHeight = screenHeight; + + if (topDisplayWidth > (screenWidth*0.7)){ + topDisplayWidth = (int) (screenWidth * 0.7); + topDisplayHeight = (int) ((topDisplayWidth/topSourceSize.x)* topSourceSize.y); + } + + int bottomDisplayHeight = (int) (((screenWidth-topDisplayWidth)/ bottomSourceSize.x)* bottomSourceSize.y); + + + topDisplay.set(0, 0, topDisplayWidth, topDisplayHeight); + bottomDisplay.set(topDisplayWidth, 0, topDisplayWidth+(screenWidth-topDisplayWidth), bottomDisplayHeight); + } else { + int topScreenHeight = (int) ((screenWidth/ topSourceSize.x) * topSourceSize.y); + topDisplay.set(0,0,screenWidth,topScreenHeight); + + int bottomDisplayHeight = (int)((screenWidth/ bottomSourceSize.x) * bottomSourceSize.y); + int bottomDisplayWidth = screenWidth; + int bottomDisplayX = 0; + + if (topScreenHeight + bottomDisplayHeight > screenHeight){ + bottomDisplayHeight = (screenHeight-topScreenHeight); + bottomDisplayWidth = (int) ((bottomDisplayHeight/ bottomSourceSize.y)*bottomSourceSize.x); + bottomDisplayX = (screenWidth-bottomDisplayX)/2; + } + + topDisplay.set(0,0, screenWidth,topScreenHeight); + bottomDisplay.set(bottomDisplayX, topScreenHeight, bottomDisplayX+bottomDisplayWidth,topScreenHeight+bottomDisplayHeight); + } + } + + + @Override + public Rect getBottomDisplayBounds() { + return bottomDisplay; + } + + @Override + public Rect getTopDisplayBounds() { + return topDisplay; + } +} diff --git a/src/pandroid/app/src/main/res/layout/game_activity.xml b/src/pandroid/app/src/main/res/layout/game_activity.xml index 64f067b2..6f6f65d7 100644 --- a/src/pandroid/app/src/main/res/layout/game_activity.xml +++ b/src/pandroid/app/src/main/res/layout/game_activity.xml @@ -4,105 +4,110 @@ android:layout_height="match_parent" android:background="#000"> - - - + android:layout_height="match_parent"/> - + + + android:layout_height="match_parent" + android:gravity="bottom" + android:padding="20dp"> - - - - - - + android:layout_height="wrap_content"> - - - - - - - - - - - - - + android:layout_height="25dp" + android:layout_gravity="left" + style="@style/ControllerSimpleButton" + android:background="@drawable/simple_card_button_left" + android:text="L"/> + + + + + + + + + + + + + + + + + android:layout_gravity="bottom|center"> - + - + - + - + + + + diff --git a/src/pandroid/app/src/main/res/values/values.xml b/src/pandroid/app/src/main/res/values/values.xml new file mode 100644 index 00000000..9a4071c7 --- /dev/null +++ b/src/pandroid/app/src/main/res/values/values.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file