Run clang-format on .java files

This commit is contained in:
offtkp 2023-11-28 21:41:57 +02:00
parent a40e74a15d
commit ed0864d24f
24 changed files with 634 additions and 771 deletions

View file

@ -1 +0,0 @@
/build

View file

@ -36,11 +36,7 @@ android {
}
dependencies {
implementation("androidx.appcompat:appcompat:1.6.1")
implementation("com.google.android.material:material:1.8.0")
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.5")
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
}

View file

@ -1,24 +1,19 @@
package com.panda3ds.pandroid;
public class AlberDriver {
AlberDriver() { super(); }
AlberDriver() {
super();
}
public static native void Initialize();
public static native void RunFrame(int fbo);
public static native boolean HasRomLoaded();
public static native void LoadRom(String path);
public static native void Finalize();
public static native void Initialize();
public static native void RunFrame(int fbo);
public static native boolean HasRomLoaded();
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);
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");
}
static { System.loadLibrary("Alber"); }
}

View file

@ -2,5 +2,4 @@ package com.panda3ds.pandroid.app;
import androidx.appcompat.app.AppCompatActivity;
public class BaseActivity extends AppCompatActivity {
}
public class BaseActivity extends AppCompatActivity {}

View file

@ -9,54 +9,48 @@ import android.view.WindowManager;
import android.widget.CheckBox;
import android.widget.FrameLayout;
import android.widget.Toast;
import androidx.annotation.Nullable;
import com.panda3ds.pandroid.R;
import com.panda3ds.pandroid.utils.Constants;
import com.panda3ds.pandroid.view.PandaGlSurfaceView;
import com.panda3ds.pandroid.view.PandaLayoutController;
public class GameActivity extends BaseActivity {
private PandaGlSurfaceView pandaSurface;
private PandaLayoutController controllerLayout;
private PandaGlSurfaceView pandaSurface;
private PandaLayoutController controllerLayout;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = getIntent();
if(!intent.hasExtra(Constants.EXTRA_PATH)){
Intent intent = getIntent();
if (!intent.hasExtra(Constants.EXTRA_PATH)) {
setContentView(new FrameLayout(this));
Toast.makeText(this, "Invalid rom path!", Toast.LENGTH_LONG).show();
finish();
return;
}
setContentView(new FrameLayout(this));
Toast.makeText(this, "Invalid rom path!", Toast.LENGTH_LONG).show();
finish();
return;
}
pandaSurface = new PandaGlSurfaceView(this, intent.getStringExtra(Constants.EXTRA_PATH));
pandaSurface = new PandaGlSurfaceView(this, intent.getStringExtra(Constants.EXTRA_PATH));
setContentView(R.layout.game_activity);
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));
((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 = findViewById(R.id.controller_layout);
controllerLayout.initialize();
controllerLayout.initialize();
((CheckBox) findViewById(R.id.hide_screen_controller)).setOnCheckedChangeListener((buttonView, isChecked) -> {
findViewById(R.id.overlay_controller).setVisibility(isChecked ? View.VISIBLE : View.INVISIBLE);
});
}
((CheckBox)findViewById(R.id.hide_screen_controller))
.setOnCheckedChangeListener((buttonView, isChecked) -> {
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);
}
@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);
}
}

View file

@ -1,5 +1,7 @@
package com.panda3ds.pandroid.app;
import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
import static android.provider.Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION;
import android.content.Intent;
@ -7,58 +9,50 @@ import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
import androidx.core.app.ActivityCompat;
import com.panda3ds.pandroid.utils.Constants;
import com.panda3ds.pandroid.R;
import com.panda3ds.pandroid.utils.Constants;
import com.panda3ds.pandroid.utils.PathUtils;
public class MainActivity extends BaseActivity {
private static final int PICK_3DS_ROM = 2;
private static final int PERMISSION_REQUEST_CODE = 3;
private static final int PICK_3DS_ROM = 2;
private static final int PERMISSION_REQUEST_CODE = 3;
private void openFile() {
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");
startActivityForResult(intent, PICK_3DS_ROM);
}
private void openFile() {
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");
startActivityForResult(intent, PICK_3DS_ROM);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
if (!Environment.isExternalStorageManager()) {
Intent intent = new Intent(ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION);
startActivity(intent);
}
} else {
ActivityCompat.requestPermissions(this, new String[]{READ_EXTERNAL_STORAGE}, PERMISSION_REQUEST_CODE);
ActivityCompat.requestPermissions(this, new String[]{WRITE_EXTERNAL_STORAGE}, PERMISSION_REQUEST_CODE);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
if (!Environment.isExternalStorageManager()) {
Intent intent = new Intent(ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION);
startActivity(intent);
}
} else {
ActivityCompat.requestPermissions(this, new String[] {READ_EXTERNAL_STORAGE}, PERMISSION_REQUEST_CODE);
ActivityCompat.requestPermissions(this, new String[] {WRITE_EXTERNAL_STORAGE}, PERMISSION_REQUEST_CODE);
}
setContentView(R.layout.activity_main);
setContentView(R.layout.activity_main);
findViewById(R.id.load_rom).setOnClickListener(v->{
openFile();
});
}
findViewById(R.id.load_rom).setOnClickListener(v -> { openFile(); });
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == PICK_3DS_ROM) {
if (resultCode == RESULT_OK) {
String path = PathUtils.getPath(getApplicationContext(), data.getData());
Toast.makeText(getApplicationContext(), "pandroid opening " + path, Toast.LENGTH_LONG).show();
startActivity(new Intent(this, GameActivity.class)
.putExtra(Constants.EXTRA_PATH, path));
}
super.onActivityResult(requestCode, resultCode, data);
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == PICK_3DS_ROM) {
if (resultCode == RESULT_OK) {
String path = PathUtils.getPath(getApplicationContext(), data.getData());
Toast.makeText(getApplicationContext(), "pandroid opening " + path, Toast.LENGTH_LONG).show();
startActivity(new Intent(this, GameActivity.class).putExtra(Constants.EXTRA_PATH, path));
}
super.onActivityResult(requestCode, resultCode, data);
}
}
}

View file

@ -1,26 +1,20 @@
package com.panda3ds.pandroid.math;
public class Vector2 {
public float x,y;
public Vector2(Vector2 value){
this(value.x,value.y);
}
public float x, y;
public Vector2(Vector2 value) { this(value.x, value.y); }
public Vector2(float x, float y){
this.x = x;
this.y = y;
}
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 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));
}
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;
}
public void set(float x, float y) {
this.x = x;
this.y = y;
}
}

View file

@ -1,27 +1,26 @@
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_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_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_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 int INPUT_KEY_START = 1 << 3;
public static final int INPUT_KEY_SELECT = 1 << 2;
public static final int N3DS_WIDTH = 400;
public static final int N3DS_HALF_HEIGHT = 240;
public static final int N3DS_FULL_HEIGHT = 480;
public static final int N3DS_WIDTH = 400;
public static final int N3DS_HALF_HEIGHT = 240;
public static final int N3DS_FULL_HEIGHT = 480;
public static final String EXTRA_PATH = "path";
public static final String LOG_TAG = "Alber";
public static final String EXTRA_PATH = "path";
public static final String LOG_TAG = "Alber";
}

View file

@ -10,116 +10,92 @@ import android.provider.DocumentsContract;
import android.provider.MediaStore;
public class PathUtils {
public static String getPath(final Context context, final Uri uri) {
// DocumentProvider
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && DocumentsContract.isDocumentUri(context, uri)) {
if (isExternalStorageDocument(uri)) { // ExternalStorageProvider
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
String storageDefinition;
public static String getPath(final Context context, final Uri uri) {
if ("primary".equalsIgnoreCase(type)) {
return Environment.getExternalStorageDirectory() + "/" + split[1];
// DocumentProvider
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && DocumentsContract.isDocumentUri(context, uri)) {
} else {
if (Environment.isExternalStorageRemovable()) {
storageDefinition = "EXTERNAL_STORAGE";
if (isExternalStorageDocument(uri)) {// ExternalStorageProvider
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
String storageDefinition;
} else {
storageDefinition = "SECONDARY_STORAGE";
}
return System.getenv(storageDefinition) + "/" + split[1];
}
if("primary".equalsIgnoreCase(type)){
} else if (isDownloadsDocument(uri)) { // DownloadsProvider
return Environment.getExternalStorageDirectory() + "/" + split[1];
final String id = DocumentsContract.getDocumentId(uri);
final Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
} else {
return getDataColumn(context, contentUri, null, null);
if(Environment.isExternalStorageRemovable()){
storageDefinition = "EXTERNAL_STORAGE";
} else if (isMediaDocument(uri)) { // MediaProvider
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
} else{
storageDefinition = "SECONDARY_STORAGE";
}
Uri contentUri = null;
if ("image".equals(type)) {
contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
} else if ("video".equals(type)) {
contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
} else if ("audio".equals(type)) {
contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
}
return System.getenv(storageDefinition) + "/" + split[1];
}
} else if (isDownloadsDocument(uri)) {// DownloadsProvider
final String selection = "_id=?";
final String[] selectionArgs = new String[] {split[1]};
final String id = DocumentsContract.getDocumentId(uri);
final Uri contentUri = ContentUris.withAppendedId(
Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
return getDataColumn(context, contentUri, selection, selectionArgs);
}
return getDataColumn(context, contentUri, null, null);
} else if ("content".equalsIgnoreCase(uri.getScheme())) { // MediaStore (and general)
} else if (isMediaDocument(uri)) {// MediaProvider
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
// Return the remote address
if (isGooglePhotosUri(uri)) return uri.getLastPathSegment();
Uri contentUri = null;
if ("image".equals(type)) {
contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
} else if ("video".equals(type)) {
contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
} else if ("audio".equals(type)) {
contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
}
return getDataColumn(context, uri, null, null);
final String selection = "_id=?";
final String[] selectionArgs = new String[]{
split[1]
};
} else if ("file".equalsIgnoreCase(uri.getScheme())) { // File
return uri.getPath();
}
return getDataColumn(context, contentUri, selection, selectionArgs);
}
return null;
}
} else if ("content".equalsIgnoreCase(uri.getScheme())) {// MediaStore (and general)
public static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) {
Cursor cursor = null;
final String column = "_data";
final String[] projection = {column};
// Return the remote address
if (isGooglePhotosUri(uri))
return uri.getLastPathSegment();
try {
cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null);
if (cursor != null && cursor.moveToFirst()) {
final int column_index = cursor.getColumnIndexOrThrow(column);
return cursor.getString(column_index);
}
} finally {
if (cursor != null) cursor.close();
}
return null;
}
return getDataColumn(context, uri, null, null);
public static boolean isExternalStorageDocument(Uri uri) { return "com.android.externalstorage.documents".equals(uri.getAuthority()); }
} else if ("file".equalsIgnoreCase(uri.getScheme())) {// File
return uri.getPath();
}
public static boolean isDownloadsDocument(Uri uri) { return "com.android.providers.downloads.documents".equals(uri.getAuthority()); }
return null;
}
public static boolean isMediaDocument(Uri uri) { return "com.android.providers.media.documents".equals(uri.getAuthority()); }
public static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) {
Cursor cursor = null;
final String column = "_data";
final String[] projection = {
column
};
try {
cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null);
if (cursor != null && cursor.moveToFirst()) {
final int column_index = cursor.getColumnIndexOrThrow(column);
return cursor.getString(column_index);
}
} finally {
if (cursor != null)
cursor.close();
}
return null;
}
public static boolean isExternalStorageDocument(Uri uri) {
return "com.android.externalstorage.documents".equals(uri.getAuthority());
}
public static boolean isDownloadsDocument(Uri uri) {
return "com.android.providers.downloads.documents".equals(uri.getAuthority());
}
public static boolean isMediaDocument(Uri uri) {
return "com.android.providers.media.documents".equals(uri.getAuthority());
}
public static boolean isGooglePhotosUri(Uri uri) {
return "com.google.android.apps.photos.content".equals(uri.getAuthority());
}
public static boolean isGooglePhotosUri(Uri uri) { return "com.google.android.apps.photos.content".equals(uri.getAuthority()); }
}

View file

@ -1,122 +1,116 @@
package com.panda3ds.pandroid.view;
import javax.microedition.khronos.egl.EGLConfig;
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.view.renderer.layout.ConsoleLayout;
import com.panda3ds.pandroid.utils.Constants;
import com.panda3ds.pandroid.view.renderer.ConsoleRenderer;
import com.panda3ds.pandroid.view.renderer.layout.ConsoleLayout;
import com.panda3ds.pandroid.view.renderer.layout.DefaultScreenLayout;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
public class PandaGlRenderer implements GLSurfaceView.Renderer, ConsoleRenderer {
private final String romPath;
private ConsoleLayout displayLayout;
private int screenWidth, screenHeight;
private int screenTexture;
public int screenFbo;
private final String romPath;
private ConsoleLayout displayLayout;
private int screenWidth, screenHeight;
private int screenTexture;
public int screenFbo;
PandaGlRenderer(String romPath) {
super();
this.romPath = romPath;
PandaGlRenderer(String romPath) {
super();
this.romPath = romPath;
screenWidth = Resources.getSystem().getDisplayMetrics().widthPixels;
screenHeight = Resources.getSystem().getDisplayMetrics().heightPixels;
setLayout(new DefaultScreenLayout());
}
screenWidth = Resources.getSystem().getDisplayMetrics().widthPixels;
screenHeight = Resources.getSystem().getDisplayMetrics().heightPixels;
setLayout(new DefaultScreenLayout());
}
@Override
protected void finalize() throws Throwable {
if (screenTexture != 0) {
glDeleteTextures(1, new int[] {screenTexture}, 0);
}
if (screenFbo != 0) {
glDeleteFramebuffers(1, new int[] {screenFbo}, 0);
}
super.finalize();
}
@Override
protected void finalize() throws Throwable {
if (screenTexture != 0) {
glDeleteTextures(1, new int[]{screenTexture}, 0);
}
if (screenFbo != 0) {
glDeleteFramebuffers(1, new int[]{screenFbo}, 0);
}
super.finalize();
}
public void onSurfaceCreated(GL10 unused, EGLConfig config) {
Log.i("pandroid", glGetString(GL_EXTENSIONS));
Log.w("pandroid", glGetString(GL_VERSION));
public void onSurfaceCreated(GL10 unused, EGLConfig config) {
Log.i("pandroid", glGetString(GL_EXTENSIONS));
Log.w("pandroid", glGetString(GL_VERSION));
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
int[] generateBuffer = new int[1];
glGenTextures(1, generateBuffer, 0);
screenTexture = generateBuffer[0];
glBindTexture(GL_TEXTURE_2D, screenTexture);
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, screenWidth, screenHeight);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glBindTexture(GL_TEXTURE_2D, 0);
int[] generateBuffer = new int[1];
glGenTextures(1, generateBuffer, 0);
screenTexture = generateBuffer[0];
glBindTexture(GL_TEXTURE_2D, screenTexture);
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, screenWidth, screenHeight);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glBindTexture(GL_TEXTURE_2D, 0);
glGenFramebuffers(1, generateBuffer, 0);
screenFbo = generateBuffer[0];
glBindFramebuffer(GL_FRAMEBUFFER, screenFbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, screenTexture, 0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glGenFramebuffers(1, generateBuffer, 0);
screenFbo = generateBuffer[0];
glBindFramebuffer(GL_FRAMEBUFFER, screenFbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, screenTexture, 0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
AlberDriver.Initialize();
AlberDriver.LoadRom(romPath);
}
AlberDriver.Initialize();
AlberDriver.LoadRom(romPath);
}
public void onDrawFrame(GL10 unused) {
if (AlberDriver.HasRomLoaded()) {
AlberDriver.RunFrame(screenFbo);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glBindFramebuffer(GL_READ_FRAMEBUFFER, screenFbo);
public void onDrawFrame(GL10 unused) {
if (AlberDriver.HasRomLoaded()) {
AlberDriver.RunFrame(screenFbo);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glBindFramebuffer(GL_READ_FRAMEBUFFER, screenFbo);
Rect topScreen = displayLayout.getTopDisplayBounds();
Rect bottomScreen = displayLayout.getBottomDisplayBounds();
Rect topScreen = displayLayout.getTopDisplayBounds();
Rect bottomScreen = displayLayout.getBottomDisplayBounds();
glBlitFramebuffer(
0, Constants.N3DS_FULL_HEIGHT, Constants.N3DS_WIDTH, Constants.N3DS_HALF_HEIGHT, topScreen.left, screenHeight - topScreen.top,
topScreen.right, screenHeight - topScreen.bottom, GL_COLOR_BUFFER_BIT, GL_LINEAR
);
glBlitFramebuffer(
0, Constants.N3DS_FULL_HEIGHT,
Constants.N3DS_WIDTH, Constants.N3DS_HALF_HEIGHT,
topScreen.left, screenHeight - topScreen.top,
topScreen.right, screenHeight - topScreen.bottom,
GL_COLOR_BUFFER_BIT, GL_LINEAR);
// Remove the black bars on the bottom screen
glBlitFramebuffer(
40, Constants.N3DS_HALF_HEIGHT, Constants.N3DS_WIDTH - 40, 0, bottomScreen.left, screenHeight - bottomScreen.top, bottomScreen.right,
screenHeight - bottomScreen.bottom, GL_COLOR_BUFFER_BIT, GL_LINEAR
);
}
}
// Remove the black bars on the bottom screen
glBlitFramebuffer(
40, Constants.N3DS_HALF_HEIGHT,
Constants.N3DS_WIDTH - 40, 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;
public void onSurfaceChanged(GL10 unused, int width, int height) {
screenWidth = width;
screenHeight = height;
displayLayout.update(screenWidth, screenHeight);
}
displayLayout.update(screenWidth, screenHeight);
}
@Override
public void setLayout(ConsoleLayout layout) {
displayLayout = layout;
displayLayout.setTopDisplaySourceSize(Constants.N3DS_WIDTH, Constants.N3DS_HALF_HEIGHT);
displayLayout.setBottomDisplaySourceSize(Constants.N3DS_WIDTH - 40 - 40, Constants.N3DS_HALF_HEIGHT);
displayLayout.update(screenWidth, screenHeight);
}
@Override
public void setLayout(ConsoleLayout layout) {
displayLayout = layout;
displayLayout.setTopDisplaySourceSize(Constants.N3DS_WIDTH, Constants.N3DS_HALF_HEIGHT);
displayLayout.setBottomDisplaySourceSize(Constants.N3DS_WIDTH - 40 - 40, Constants.N3DS_HALF_HEIGHT);
displayLayout.update(screenWidth, screenHeight);
}
@Override
public ConsoleLayout getLayout() {
return displayLayout;
}
@Override
public ConsoleLayout getLayout() {
return displayLayout;
}
@Override
public String getBackendName() {
return "OpenGL";
}
@Override
public String getBackendName() {
return "OpenGL";
}
}

View file

@ -4,9 +4,7 @@ import android.content.Context;
import android.graphics.Canvas;
import android.opengl.GLSurfaceView;
import android.util.Log;
import androidx.annotation.NonNull;
import com.panda3ds.pandroid.math.Vector2;
import com.panda3ds.pandroid.utils.Constants;
import com.panda3ds.pandroid.view.controller.TouchEvent;
@ -14,37 +12,35 @@ 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;
final PandaGlRenderer renderer;
private int size_width;
private int size_height;
public PandaGlSurfaceView(Context context, String romPath) {
super(context);
setEGLContextClientVersion(3);
setDebugFlags(DEBUG_LOG_GL_CALLS);
renderer = new PandaGlRenderer(romPath);
setRenderer(renderer);
}
public PandaGlSurfaceView(Context context, String romPath) {
super(context);
setEGLContextClientVersion(3);
setDebugFlags(DEBUG_LOG_GL_CALLS);
renderer = new PandaGlRenderer(romPath);
setRenderer(renderer);
}
public ConsoleRenderer getRenderer() {
return renderer;
}
public ConsoleRenderer getRenderer() { return renderer; }
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
size_width = getMeasuredWidth();
size_height = getMeasuredHeight();
}
@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);
}
@NonNull
@Override
public Vector2 getSize() {
return new Vector2(size_width, size_height);
}
@Override
public void onTouch(TouchEvent event) {
onTouchScreenPress(renderer, event);
}
@Override
public void onTouch(TouchEvent event) {
onTouchScreenPress(renderer, event);
}
}

View file

@ -2,7 +2,6 @@ package com.panda3ds.pandroid.view;
import android.content.Context;
import android.util.AttributeSet;
import com.panda3ds.pandroid.AlberDriver;
import com.panda3ds.pandroid.R;
import com.panda3ds.pandroid.utils.Constants;
@ -11,54 +10,41 @@ 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) { super(context); }
public PandaLayoutController(Context context, AttributeSet attrs) {
super(context, attrs);
}
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) { super(context, attrs, defStyleAttr); }
public PandaLayoutController(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
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,
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_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_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
};
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);
});
}
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);
});
((Joystick) findViewById(R.id.left_analog)).setJoystickListener((joystick, axisX, axisY) -> {
AlberDriver.SetCirclepadAxis((int) (axisX * 0x9C), (int) (axisY * 0x9C) * -1);
});
refreshChildren();
}
refreshChildren();
}
}

View file

@ -7,150 +7,140 @@ 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 {
private final HashMap<Integer, ControllerNode> activeTouchEvents = new HashMap<>();
private final ArrayList<ControllerNode> controllerNodes = new ArrayList<>();
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) {
this(context,null);
}
public ControllerLayout(Context context, AttributeSet attrs) { this(context, attrs, 0); }
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) {
this(context, attrs, defStyleAttr,0 );
}
public ControllerLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
public ControllerLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
public void refreshChildren() {
ArrayList<ControllerNode> nodes = new ArrayList<>();
populateNodesArray(this, nodes);
public void refreshChildren(){
ArrayList<ControllerNode> 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);
//Need Reverse: First view is in back and last view is in front for respect android View hierarchy
Collections.reverse(nodes);
controllerNodes.clear();
controllerNodes.addAll(nodes);
}
controllerNodes.clear();
controllerNodes.addAll(nodes);
}
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);
}
}
}
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();
@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;
}
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);
private void processTouch(boolean up, float x, float y, int index){
int[] globalPosition = new int[2];
getLocationInWindow(globalPosition);
int action = TouchEvent.ACTION_MOVE;
int action = TouchEvent.ACTION_MOVE;
if ((!activeTouchEvents.containsKey(index))) {
if (up) return;
ControllerNode node = null;
for (ControllerNode item : controllerNodes) {
Vector2 pos = item.getPosition();
Vector2 size = item.getSize();
if ((!activeTouchEvents.containsKey(index))){
if (up)return;
ControllerNode node = 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 (item.isVisible() && x > cx && x < cx + size.x && y > cy && y < cy + size.y) {
node = item;
break;
}
}
if (node != null) {
activeTouchEvents.put(index, node);
action = TouchEvent.ACTION_DOWN;
} else {
return;
}
}
float cx = (pos.x - globalPosition[0]);
float cy = (pos.y - globalPosition[1]);
if(item.isVisible() && x > cx && x < cx+size.x && y > cy && y < cy+size.y){
node = item;
break;
}
}
if (node != null){
activeTouchEvents.put(index, node);
action = TouchEvent.ACTION_DOWN;
} else {
return;
}
}
if (up) action = TouchEvent.ACTION_UP;
if (up) action = TouchEvent.ACTION_UP;
ControllerNode node = activeTouchEvents.get(index);
Vector2 pos = node.getPosition();
pos.x -= globalPosition[0];
pos.y -= globalPosition[1];
ControllerNode node = activeTouchEvents.get(index);
Vector2 pos = node.getPosition();
pos.x -= globalPosition[0];
pos.y -= globalPosition[1];
x -= pos.x;
y -= pos.y;
x -= pos.x;
y -= pos.y;
node.onTouch(new TouchEvent(x, y, action));
node.onTouch(new TouchEvent(x,y,action));
if (up) {
activeTouchEvents.remove(index);
}
}
if(up){
activeTouchEvents.remove(index);
}
}
@Override
public void onViewAdded(View child) {
super.onViewAdded(child);
refreshChildren();
}
@Override
public void onViewAdded(View child) {
super.onViewAdded(child);
refreshChildren();
}
@Override
public void onViewRemoved(View child) {
super.onViewRemoved(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*/
/*@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;
}
@Override
public ArrayList<View> getTouchables() {
return new ArrayList<>();
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return true;
}
}

View file

@ -1,28 +1,22 @@
package com.panda3ds.pandroid.view.controller;
import android.view.View;
import androidx.annotation.NonNull;
import com.panda3ds.pandroid.math.Vector2;
public interface ControllerNode {
@NonNull
default Vector2 getPosition() {
View me = (View) this;
@NonNull
default Vector2 getPosition(){
View me = (View) this;
int[] position = new int[2];
me.getLocationInWindow(position);
return new Vector2(position[0], position[1]);
}
int[] position = new int[2];
me.getLocationInWindow(position);
return new Vector2(position[0], position[1]);
}
default boolean isVisible() { return ((View) this).isShown(); }
default boolean isVisible(){
return ((View)this).isShown();
}
@NonNull Vector2 getSize();
@NonNull Vector2 getSize();
void onTouch(TouchEvent event);
void onTouch(TouchEvent event);
}

View file

@ -1,28 +1,22 @@
package com.panda3ds.pandroid.view.controller;
public class TouchEvent {
public static final int ACTION_DOWN = 0;
public static final int ACTION_MOVE = 1;
public static final int ACTION_UP = 2;
public static final int ACTION_DOWN = 0;
public static final int ACTION_MOVE = 1;
public static final int ACTION_UP = 2;
private final int action;
private final float x,y;
private final int action;
private final float x, y;
public float getX() {
return x;
}
public float getX() { return x; }
public float getY() {
return y;
}
public float getY() { return y; }
public int getAction() {
return action;
}
public int getAction() { return action; }
public TouchEvent(float x, float y, int action){
this.x = x;
this.y = y;
this.action = action;
}
public TouchEvent(float x, float y, int action) {
this.x = x;
this.y = y;
this.action = action;
}
}

View file

@ -3,5 +3,5 @@ package com.panda3ds.pandroid.view.controller.listeners;
import com.panda3ds.pandroid.view.controller.nodes.Button;
public interface ButtonStateListener {
void onButtonPressedChange(Button button, boolean pressed);
void onButtonPressedChange(Button button, boolean pressed);
}

View file

@ -3,5 +3,5 @@ package com.panda3ds.pandroid.view.controller.listeners;
import com.panda3ds.pandroid.view.controller.nodes.Joystick;
public interface JoystickListener {
void onJoystickAxisChange(Joystick joystick, float axisX, float axisY);
void onJoystickAxisChange(Joystick joystick, float axisX, float axisY);
}

View file

@ -2,23 +2,15 @@ package com.panda3ds.pandroid.view.controller.nodes;
import android.content.Context;
import android.util.AttributeSet;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatTextView;
import com.panda3ds.pandroid.view.controller.ControllerNode;
public abstract class BasicControllerNode extends AppCompatTextView implements ControllerNode {
public BasicControllerNode(@NonNull Context context) {
super(context);
}
public BasicControllerNode(@NonNull Context context) { super(context); }
public BasicControllerNode(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public BasicControllerNode(@NonNull Context context, @Nullable AttributeSet attrs) { super(context, attrs); }
public BasicControllerNode(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public BasicControllerNode(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); }
}

View file

@ -5,69 +5,63 @@ import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.Gravity;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatTextView;
import com.panda3ds.pandroid.math.Vector2;
import com.panda3ds.pandroid.view.controller.ControllerNode;
import com.panda3ds.pandroid.view.controller.TouchEvent;
import com.panda3ds.pandroid.view.controller.listeners.ButtonStateListener;
public class Button extends BasicControllerNode {
private boolean pressed = false;
private int width,height;
private boolean pressed = false;
private int width, height;
private ButtonStateListener stateListener;
private ButtonStateListener stateListener;
public Button(@NonNull Context context) {
super(context);
init();
}
public Button(@NonNull Context context) {
super(context);
init();
}
public Button(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public Button(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public Button(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
public Button(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
width = getWidth();
height = getHeight();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
width = getWidth();
height = getHeight();
}
private void init(){
setTextAlignment(TEXT_ALIGNMENT_CENTER);
setGravity(Gravity.CENTER);
}
private void init() {
setTextAlignment(TEXT_ALIGNMENT_CENTER);
setGravity(Gravity.CENTER);
}
public void setStateListener(ButtonStateListener stateListener) {
this.stateListener = stateListener;
}
public void setStateListener(ButtonStateListener stateListener) { this.stateListener = stateListener; }
public boolean isPressed() {
return pressed;
}
public boolean isPressed() { return pressed; }
@NonNull
@Override
public Vector2 getSize() {
return new Vector2(width,height);
}
@NonNull
@Override
public Vector2 getSize() {
return new Vector2(width, height);
}
@Override
public void onTouch(TouchEvent event) {
pressed = event.getAction() != TouchEvent.ACTION_UP;
setAlpha(pressed ? 0.2F : 1.0F);
if (stateListener != null){
stateListener.onButtonPressedChange(this, pressed);
}
}
@Override
public void onTouch(TouchEvent event) {
pressed = event.getAction() != TouchEvent.ACTION_UP;
setAlpha(pressed ? 0.2F : 1.0F);
if (stateListener != null) {
stateListener.onButtonPressedChange(this, pressed);
}
}
}

View file

@ -6,127 +6,110 @@ import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.AppCompatTextView;
import com.panda3ds.pandroid.math.Vector2;
import com.panda3ds.pandroid.view.controller.ControllerNode;
import com.panda3ds.pandroid.view.controller.TouchEvent;
import com.panda3ds.pandroid.view.controller.listeners.JoystickListener;
public class Joystick extends BasicControllerNode implements ControllerNode {
private float stick_x = 0;
private float stick_y = 0;
private float stick_x = 0;
private float stick_y = 0;
private int size_width = 0;
private int size_height= 0;
private int size_width = 0;
private int size_height = 0;
private JoystickListener joystickListener;
private JoystickListener joystickListener;
public Joystick(Context context) {
this(context,null);
}
public Joystick(Context context) { this(context, null); }
public Joystick(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public Joystick(Context context, AttributeSet attrs) { this(context, attrs, 0); }
public Joystick(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
public Joystick(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
paint.setColor(Color.RED);
invalidate();
}
paint.setColor(Color.RED);
invalidate();
}
private final Paint paint = new Paint();
private final Paint paint = new Paint();
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
}
@Override
public void onDrawForeground(Canvas canvas) {
size_width = getWidth();
size_height = getHeight();
@Override
public void onDrawForeground(Canvas canvas) {
size_width = getWidth();
size_height = getHeight();
int analogIconSize = size_width-getPaddingLeft();
int analogIconSize = size_width - getPaddingLeft();
float middleIconSize = analogIconSize / 2.0F;
float middle = size_width / 2.0F;
float middleIconSize = analogIconSize / 2.0F;
float middle = size_width / 2.0F;
float maxDistance = (middle - middleIconSize) * 0.9F;
float maxDistance = (middle - middleIconSize) * 0.9F;
float tx = maxDistance * stick_x;
float ty = maxDistance * stick_y;
float tx = maxDistance * stick_x;
float ty = maxDistance * stick_y;
float radius = Vector2.distance(0.0F, 0.0F, Math.abs(tx), Math.abs(ty));
radius = Math.min(maxDistance, radius);
float radius = Vector2.distance(0.0F, 0.0F, Math.abs(tx), Math.abs(ty));
radius = Math.min(maxDistance, radius);
double deg = Math.atan2(ty,tx) * (180.0/Math.PI);
float rx = (float) (radius*Math.cos(Math.PI * 2 * deg/360.0));
float ry = (float) (radius*Math.sin(Math.PI * 2 * deg/360.0));
double deg = Math.atan2(ty, tx) * (180.0 / Math.PI);
float rx = (float) (radius * Math.cos(Math.PI * 2 * deg / 360.0));
float ry = (float) (radius * Math.sin(Math.PI * 2 * deg / 360.0));
stick_x = Math.max(-1.0f, Math.min(1.0f, stick_x));
stick_y = Math.max(-1.0f, Math.min(1.0f, stick_y));
stick_x = Math.max(-1.0f, Math.min(1.0f, stick_x));
stick_y = Math.max(-1.0f, Math.min(1.0f, stick_y));
float x = middle - middleIconSize + rx;
float y = middle - middleIconSize + ry;
float x = middle-middleIconSize+rx;
float y = middle-middleIconSize+ry;
Drawable foreground = getForeground();
if (foreground != null) {
foreground.setBounds((int) x, (int) y, (int) (x + analogIconSize), (int) (y + analogIconSize));
foreground.draw(canvas);
} else {
canvas.drawOval(x, y, x + analogIconSize, y + analogIconSize, paint);
}
}
public Vector2 getAxis() { return new Vector2(Math.max(-1.0F, Math.min(1.0F, stick_x)), Math.max(-1.0F, Math.min(1.0F, stick_y))); }
Drawable foreground = getForeground();
if (foreground != null){
foreground.setBounds((int) x, (int) y, (int) (x+analogIconSize), (int) (y+analogIconSize));
foreground.draw(canvas);
} else {
canvas.drawOval(x, y, x+analogIconSize,y+analogIconSize,paint);
}
}
public void setJoystickListener(JoystickListener joystickListener) { this.joystickListener = joystickListener; }
public Vector2 getAxis() {
return new Vector2(
Math.max(-1.0F, Math.min(1.0F, stick_x)),
Math.max(-1.0F, Math.min(1.0F, stick_y))
);
}
@NonNull
@Override
public Vector2 getSize() {
return new Vector2(size_width, size_height);
}
public void setJoystickListener(JoystickListener joystickListener) {
this.joystickListener = joystickListener;
}
@Override
public void onTouch(TouchEvent event) {
float middle = size_width / 2.0F;
@NonNull
@Override
public Vector2 getSize() {
return new Vector2(size_width,size_height);
}
float x = event.getX();
float y = event.getY();
@Override
public void onTouch(TouchEvent event) {
x = Math.max(0, Math.min(middle * 2, x));
y = Math.max(0, Math.min(middle * 2, y));
float middle = size_width/2.0F;
stick_x = ((x - middle) / middle);
float x = event.getX();
float y = event.getY();
stick_y = ((y - middle) / middle);
x = Math.max(0, Math.min(middle*2, x));
y = Math.max(0, Math.min(middle*2, y));
if (event.getAction() == TouchEvent.ACTION_UP) {
stick_x = 0;
stick_y = 0;
}
stick_x = ((x-middle)/middle);
if (joystickListener != null) {
joystickListener.onJoystickAxisChange(this, stick_x, stick_y);
}
stick_y = ((y-middle)/middle);
if (event.getAction() == TouchEvent.ACTION_UP){
stick_x = 0;
stick_y = 0;
}
if (joystickListener != null){
joystickListener.onJoystickAxisChange(this, stick_x, stick_y);
}
invalidate();
}
invalidate();
}
}

View file

@ -3,7 +3,6 @@ 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;
@ -12,28 +11,28 @@ 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){
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);
View me = (View) this;
boolean hasDownEvent = me.getTag(R.id.TagEventHasDown) != null && (boolean) me.getTag(R.id.TagEventHasDown);
Rect bounds = renderer.getLayout().getBottomDisplayBounds();
;
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);
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);
x = Math.round((x/(float)bounds.width())*320);
y = Math.round((y/(float)bounds.height())*240);
AlberDriver.TouchScreenDown(x, y);
AlberDriver.TouchScreenDown(x,y);
me.setTag(R.id.TagEventHasDown, true);
}
me.setTag(R.id.TagEventHasDown, true);
}
if (hasDownEvent && event.getAction() == TouchEvent.ACTION_UP){
AlberDriver.TouchScreenUp();
me.setTag(R.id.TagEventHasDown, false);
}
}
if (hasDownEvent && event.getAction() == TouchEvent.ACTION_UP) {
AlberDriver.TouchScreenUp();
me.setTag(R.id.TagEventHasDown, false);
}
}
}

View file

@ -3,7 +3,7 @@ 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();
void setLayout(ConsoleLayout layout);
ConsoleLayout getLayout();
String getBackendName();
}

View file

@ -1,15 +1,14 @@
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 update(int screenWidth, int screenHeight);
void setBottomDisplaySourceSize(int width, int height);
void setTopDisplaySourceSize(int width, int height);
void setBottomDisplaySourceSize(int width, int height);
void setTopDisplaySourceSize(int width, int height);
Rect getBottomDisplayBounds();
Rect getTopDisplayBounds();
Rect getBottomDisplayBounds();
Rect getTopDisplayBounds();
}

View file

@ -2,80 +2,76 @@ 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 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);
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 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();
}
@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;
private void updateBounds() {
int screenWidth = (int) screenSize.x;
int screenHeight = (int) screenSize.y;
if (screenWidth > screenHeight){
if (screenWidth > screenHeight) {
int topDisplayWidth = (int) ((screenHeight / topSourceSize.y) * topSourceSize.x);
int topDisplayHeight = 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);
}
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);
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;
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);
if (topScreenHeight + bottomDisplayHeight > screenHeight) {
bottomDisplayHeight = (screenHeight - topScreenHeight);
bottomDisplayWidth = (int) ((bottomDisplayHeight / bottomSourceSize.y) * bottomSourceSize.x);
bottomDisplayX = (screenWidth - bottomDisplayX) / 2;
}
int bottomDisplayHeight = (int)((screenWidth/ bottomSourceSize.x) * bottomSourceSize.y);
int bottomDisplayWidth = screenWidth;
int bottomDisplayX = 0;
topDisplay.set(0, 0, screenWidth, topScreenHeight);
bottomDisplay.set(bottomDisplayX, topScreenHeight, bottomDisplayX + bottomDisplayWidth, topScreenHeight + bottomDisplayHeight);
}
}
if (topScreenHeight + bottomDisplayHeight > screenHeight){
bottomDisplayHeight = (screenHeight-topScreenHeight);
bottomDisplayWidth = (int) ((bottomDisplayHeight/ bottomSourceSize.y)*bottomSourceSize.x);
bottomDisplayX = (screenWidth-bottomDisplayX)/2;
}
@Override
public Rect getBottomDisplayBounds() {
return bottomDisplay;
}
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;
}
@Override
public Rect getTopDisplayBounds() {
return topDisplay;
}
}