Skip to content

Commit

Permalink
Create input (JNI and java)
Browse files Browse the repository at this point in the history
  • Loading branch information
GabrielBRDeveloper committed Nov 28, 2023
1 parent e76531f commit 88170a1
Show file tree
Hide file tree
Showing 29 changed files with 889 additions and 5 deletions.
30 changes: 29 additions & 1 deletion src/jni_driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ extern "C" JNIEXPORT void JNICALL Java_com_panda3ds_pandroid_AlberDriver_RunFram
renderer->setFBO(fbo);
renderer->resetStateManager();
emulator->runFrame();

emulator->getServiceManager().getHID().updateInputs(emulator->getTicks());
}

extern "C" JNIEXPORT void JNICALL Java_com_panda3ds_pandroid_AlberDriver_Finalize(JNIEnv* env, jobject obj) {
Expand All @@ -43,4 +45,30 @@ extern "C" JNIEXPORT void JNICALL Java_com_panda3ds_pandroid_AlberDriver_LoadRom
__android_log_print(ANDROID_LOG_INFO, "AlberDriver", "Loading ROM %s", pathStr);
romLoaded = emulator->loadROM(pathStr);
env->ReleaseStringUTFChars(path, pathStr);
}
}



extern "C" JNIEXPORT void JNICALL Java_com_panda3ds_pandroid_AlberDriver_TouchScreenDown(JNIEnv* env, jobject obj, jint x, jint y) {
emulator->getServiceManager().getHID().setTouchScreenPress((u16)x, (u16)y);
}

extern "C" JNIEXPORT void JNICALL Java_com_panda3ds_pandroid_AlberDriver_TouchScreenUp(JNIEnv* env, jobject obj) {
emulator->getServiceManager().getHID().releaseTouchScreen();
}


extern "C" JNIEXPORT void JNICALL Java_com_panda3ds_pandroid_AlberDriver_KeyUp(JNIEnv* env, jobject obj, jint keyCode) {
emulator->getServiceManager().getHID().releaseKey((u32)keyCode);
}

extern "C" JNIEXPORT void JNICALL Java_com_panda3ds_pandroid_AlberDriver_KeyDown(JNIEnv* env, jobject obj, jint keyCode) {
emulator->getServiceManager().getHID().pressKey((u32)keyCode);
}

extern "C" JNIEXPORT void JNICALL Java_com_panda3ds_pandroid_AlberDriver_SetCirclepadAxis(JNIEnv* env, jobject obj, jint x, jint y) {
emulator->getServiceManager().getHID().setCirclepadX((s16)x);
emulator->getServiceManager().getHID().setCirclepadY((s16)y);
}


2 changes: 1 addition & 1 deletion src/pandroid/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<uses-feature
android:required="true"
android:glEsVersion="0x0030000"/>
android:glEsVersion="0x0030002"/>

<application
android:allowBackup="true"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ public class AlberDriver {
public static native void LoadRom(String path);
public static native void Finalize();

public static native void KeyDown(int code);
public static native void KeyUp(int code);
public static native void SetCirclepadAxis(int x, int y);
public static native void TouchScreenUp();
public static native void TouchScreenDown(int x, int y);

static {
System.loadLibrary("Alber");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,28 @@

import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
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;
private PandaLayoutController controllerLayout;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
Expand All @@ -27,6 +39,18 @@ protected void onCreate(@Nullable Bundle savedInstanceState) {
}

pandaSurface = new PandaGlSurfaceView(this, intent.getStringExtra(Constants.EXTRA_PATH));;
setContentView(pandaSurface);

setContentView(R.layout.game_activity);

((FrameLayout)findViewById(R.id.panda_gl_frame))
.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);
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
import com.panda3ds.pandroid.R;
import com.panda3ds.pandroid.utils.PathUtils;

public class MainActivity extends AppCompatActivity {
public class MainActivity extends BaseActivity {
private static final int PICK_3DS_ROM = 2;

private void openFile() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
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(float x, float y){
this.x = x;
this.y = y;
}

public float distanceTo(Vector2 vec){
return distance(x,y,vec.x, vec.y);
}
public static float distance(float x, float y, float x2, float y2){
return (float) Math.sqrt((x - x2) * (x - x2) + (y - y2) * (y - y2));
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,23 @@
package com.panda3ds.pandroid.utils;

public class Constants {

public static final int INPUT_KEY_UP = 1 << 6;
public static final int INPUT_KEY_DOWN = 1 << 7;
public static final int INPUT_KEY_LEFT = 1 << 5;
public static final int INPUT_KEY_RIGHT = 1 << 4;

public static final int INPUT_KEY_A = 1 << 0;
public static final int INPUT_KEY_B = 1 << 1;
public static final int INPUT_KEY_X = 1 << 10;
public static final int INPUT_KEY_Y = 1 << 11;

public static final int INPUT_KEY_R = 1 << 8;
public static final int INPUT_KEY_L = 1 << 9;

public static final int INPUT_KEY_START = 1 << 3;
public static final int INPUT_KEY_SELECT = 1 << 2;

public static final String EXTRA_PATH = "path";
public static final String LOG_TAG = "Alber";
}
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,10 @@ public void onSurfaceCreated(GL10 unused, EGLConfig config) {
public void onDrawFrame(GL10 unused) {
if (AlberDriver.HasRomLoaded()) {
AlberDriver.RunFrame(screenFbo);
int h = (int) ((screenWidth/400.0)*480);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glBindFramebuffer(GL_READ_FRAMEBUFFER, screenFbo);
glBlitFramebuffer(0, 0, 400, 480, 0, 0, screenWidth, screenHeight, GL_COLOR_BUFFER_BIT, GL_LINEAR);
glBlitFramebuffer(0, 0, 400, 480, 0, screenHeight-h, screenWidth, screenHeight, GL_COLOR_BUFFER_BIT, GL_LINEAR);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package com.panda3ds.pandroid.view;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;

import com.panda3ds.pandroid.AlberDriver;
import com.panda3ds.pandroid.R;
import com.panda3ds.pandroid.utils.Constants;
import com.panda3ds.pandroid.view.controller.ControllerLayout;
import com.panda3ds.pandroid.view.controller.listeners.JoystickListener;
import com.panda3ds.pandroid.view.controller.nodes.Button;
import com.panda3ds.pandroid.view.controller.nodes.Joystick;

public class PandaLayoutController extends ControllerLayout {
public PandaLayoutController(Context context) {
super(context);
}

public PandaLayoutController(Context context, AttributeSet attrs) {
super(context, attrs);
}

public PandaLayoutController(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}

public PandaLayoutController(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}

public void initialize(){
int[] keyButtonList = {
R.id.button_a, Constants.INPUT_KEY_A,
R.id.button_b, Constants.INPUT_KEY_B,
R.id.button_y, Constants.INPUT_KEY_Y,
R.id.button_x, Constants.INPUT_KEY_X,

R.id.button_left, Constants.INPUT_KEY_LEFT,
R.id.button_right, Constants.INPUT_KEY_RIGHT,
R.id.button_up, Constants.INPUT_KEY_UP,
R.id.button_down, Constants.INPUT_KEY_DOWN,

R.id.button_start, Constants.INPUT_KEY_START,
R.id.button_select, Constants.INPUT_KEY_SELECT,

R.id.button_l, Constants.INPUT_KEY_L,
R.id.button_r, Constants.INPUT_KEY_R
};

for (int i = 0; i < keyButtonList.length; i+=2){
final int keyCode = keyButtonList[i+1];
((Button)findViewById(keyButtonList[i])).setStateListener((btn, pressed)->{
if (pressed) AlberDriver.KeyDown(keyCode);
else AlberDriver.KeyUp(keyCode);
});
}

((Joystick)findViewById(R.id.left_analog))
.setJoystickListener((joystick, axisX, axisY) -> {
AlberDriver.SetCirclepadAxis((int)(axisX*0x9C), (int)(axisY*0x9C)*-1);
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
package com.panda3ds.pandroid.view.controller;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RelativeLayout;

import com.panda3ds.pandroid.math.Vector2;

import java.util.ArrayList;
import java.util.HashMap;

public class ControllerLayout extends RelativeLayout {

private final HashMap<Integer, ControllerNode> activeTouchEvents = new HashMap<>();
private final ArrayList<ControllerNode> controllerNodes = new ArrayList<>();

public ControllerLayout(Context context) {
this(context,null);
}

public ControllerLayout(Context context, AttributeSet attrs) {
this(context, attrs,0);
}

public ControllerLayout(Context context, AttributeSet attrs, int defStyleAttr) {
this(context, attrs, defStyleAttr,0 );
}

public ControllerLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}

public void refreshChildren(){
controllerNodes.clear();
populateNodesArray(this, controllerNodes);
}

private void populateNodesArray(ViewGroup group, ArrayList<ControllerNode> list){
for (int i = 0; i < group.getChildCount(); i++){
View view = group.getChildAt(i);
if(view instanceof ControllerNode){
list.add((ControllerNode) view);
} else if (view instanceof ViewGroup) {
populateNodesArray((ViewGroup) view, list);
}
}
}

@Override
public boolean onTouchEvent(MotionEvent event) {
int index = event.getActionIndex();

switch (event.getActionMasked()){
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_POINTER_UP: {
int id = event.getPointerId(index);
processTouch(true, event.getX(index), event.getY(index), id);
}break;
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_DOWN: {
int id = event.getPointerId(index);
processTouch(false, event.getX(index), event.getY(index), id);
}break;
case MotionEvent.ACTION_MOVE:
for (int id = 0; id < event.getPointerCount(); id++){
processTouch(false, event.getX(id), event.getY(id), id);
}
break;
}
return true;
}

private void processTouch(boolean up, float x, float y, int index){
int[] globalPosition = new int[2];
getLocationInWindow(globalPosition);

int action = TouchEvent.ACTION_MOVE;

if ((!activeTouchEvents.containsKey(index))){
if (up)return;
ControllerNode touch = null;
for (ControllerNode item: controllerNodes){
Vector2 pos = item.getPosition();
Vector2 size= item.getSize();

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){
touch = item;
break;
}
}
if (touch != null){
activeTouchEvents.put(index, touch);
action = TouchEvent.ACTION_DOWN;
} else {
return;
}
}

if (up) action = TouchEvent.ACTION_UP;

ControllerNode touch = activeTouchEvents.get(index);
Vector2 pos = touch.getPosition();
pos.x -= globalPosition[0];
pos.y -= globalPosition[1];

x -= pos.x;
y -= pos.y;

touch.onTouch(new TouchEvent(x,y,action));

if(up){
activeTouchEvents.remove(index);
}
}

@Override
public void onViewAdded(View child) {
super.onViewAdded(child);
refreshChildren();
}

@Override
public void onViewRemoved(View child) {
super.onViewRemoved(child);
refreshChildren();
}

/*@TODO: Need replace that methods for prevent Android send events directly to children*/

@Override
public ArrayList<View> getTouchables() {
return new ArrayList<>();
}

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return true;
}

}
Loading

0 comments on commit 88170a1

Please sign in to comment.