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 { dependencies {
implementation("androidx.appcompat:appcompat:1.6.1") implementation("androidx.appcompat:appcompat:1.6.1")
implementation("com.google.android.material:material:1.8.0") implementation("com.google.android.material:material:1.8.0")
implementation("androidx.constraintlayout:constraintlayout:2.1.4") 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; package com.panda3ds.pandroid;
public class AlberDriver { public class AlberDriver {
AlberDriver() { super(); }
AlberDriver() { public static native void Initialize();
super(); 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 KeyDown(int code);
public static native void RunFrame(int fbo); public static native void KeyUp(int code);
public static native boolean HasRomLoaded(); public static native void SetCirclepadAxis(int x, int y);
public static native void LoadRom(String path); public static native void TouchScreenUp();
public static native void Finalize(); public static native void TouchScreenDown(int x, int y);
public static native void KeyDown(int code); static { System.loadLibrary("Alber"); }
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");
}
} }

View file

@ -2,5 +2,4 @@ package com.panda3ds.pandroid.app;
import androidx.appcompat.app.AppCompatActivity; 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.CheckBox;
import android.widget.FrameLayout; import android.widget.FrameLayout;
import android.widget.Toast; import android.widget.Toast;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.panda3ds.pandroid.R; import com.panda3ds.pandroid.R;
import com.panda3ds.pandroid.utils.Constants; import com.panda3ds.pandroid.utils.Constants;
import com.panda3ds.pandroid.view.PandaGlSurfaceView; import com.panda3ds.pandroid.view.PandaGlSurfaceView;
import com.panda3ds.pandroid.view.PandaLayoutController; import com.panda3ds.pandroid.view.PandaLayoutController;
public class GameActivity extends BaseActivity { public class GameActivity extends BaseActivity {
private PandaGlSurfaceView pandaSurface; private PandaGlSurfaceView pandaSurface;
private PandaLayoutController controllerLayout; private PandaLayoutController controllerLayout;
@Override @Override
protected void onCreate(@Nullable Bundle savedInstanceState) { protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
Intent intent = getIntent(); Intent intent = getIntent();
if(!intent.hasExtra(Constants.EXTRA_PATH)){ 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)); pandaSurface = new PandaGlSurfaceView(this, intent.getStringExtra(Constants.EXTRA_PATH));
Toast.makeText(this, "Invalid rom path!", Toast.LENGTH_LONG).show();
finish();
return;
}
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)) controllerLayout = findViewById(R.id.controller_layout);
.addView(pandaSurface, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
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)) @Override
.setOnCheckedChangeListener((buttonView, isChecked) -> { protected void onResume() {
findViewById(R.id.overlay_controller) super.onResume();
.setVisibility(isChecked ? View.VISIBLE : View.INVISIBLE); 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; 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 static android.provider.Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION;
import android.content.Intent; import android.content.Intent;
@ -7,58 +9,50 @@ import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.Environment; import android.os.Environment;
import android.widget.Toast; import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity; 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 androidx.core.app.ActivityCompat;
import com.panda3ds.pandroid.utils.Constants;
import com.panda3ds.pandroid.R; import com.panda3ds.pandroid.R;
import com.panda3ds.pandroid.utils.Constants;
import com.panda3ds.pandroid.utils.PathUtils; import com.panda3ds.pandroid.utils.PathUtils;
public class MainActivity extends BaseActivity { public class MainActivity extends BaseActivity {
private static final int PICK_3DS_ROM = 2; private static final int PICK_3DS_ROM = 2;
private static final int PERMISSION_REQUEST_CODE = 3; private static final int PERMISSION_REQUEST_CODE = 3;
private void openFile() { private void openFile() {
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE); intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*"); intent.setType("*/*");
startActivityForResult(intent, PICK_3DS_ROM); startActivityForResult(intent, PICK_3DS_ROM);
} }
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
if (!Environment.isExternalStorageManager()) { if (!Environment.isExternalStorageManager()) {
Intent intent = new Intent(ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION); Intent intent = new Intent(ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION);
startActivity(intent); startActivity(intent);
} }
} else { } else {
ActivityCompat.requestPermissions(this, new String[]{READ_EXTERNAL_STORAGE}, PERMISSION_REQUEST_CODE); ActivityCompat.requestPermissions(this, new String[] {READ_EXTERNAL_STORAGE}, PERMISSION_REQUEST_CODE);
ActivityCompat.requestPermissions(this, new String[]{WRITE_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->{ findViewById(R.id.load_rom).setOnClickListener(v -> { openFile(); });
openFile(); }
});
}
@Override @Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) { protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == PICK_3DS_ROM) { if (requestCode == PICK_3DS_ROM) {
if (resultCode == RESULT_OK) { if (resultCode == RESULT_OK) {
String path = PathUtils.getPath(getApplicationContext(), data.getData()); String path = PathUtils.getPath(getApplicationContext(), data.getData());
Toast.makeText(getApplicationContext(), "pandroid opening " + path, Toast.LENGTH_LONG).show(); Toast.makeText(getApplicationContext(), "pandroid opening " + path, Toast.LENGTH_LONG).show();
startActivity(new Intent(this, GameActivity.class) startActivity(new Intent(this, GameActivity.class).putExtra(Constants.EXTRA_PATH, path));
.putExtra(Constants.EXTRA_PATH, path)); }
} super.onActivityResult(requestCode, resultCode, data);
super.onActivityResult(requestCode, resultCode, data); }
} }
}
} }

View file

@ -1,26 +1,20 @@
package com.panda3ds.pandroid.math; package com.panda3ds.pandroid.math;
public class Vector2 { public class Vector2 {
public float x,y; public float x, y;
public Vector2(Vector2 value){ public Vector2(Vector2 value) { this(value.x, value.y); }
this(value.x,value.y);
}
public Vector2(float x, float y){ public Vector2(float x, float y) {
this.x = x; this.x = x;
this.y = y; this.y = y;
} }
public float distanceTo(Vector2 vec){ public float distanceTo(Vector2 vec) { return distance(x, y, vec.x, vec.y); }
return distance(x,y,vec.x, vec.y);
}
public static float distance(float x, float y, float x2, float 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)); }
return (float) Math.sqrt((x - x2) * (x - x2) + (y - y2) * (y - y2));
}
public void set(float x, float y) { public void set(float x, float y) {
this.x = x; this.x = x;
this.y = y; this.y = y;
} }
} }

View file

@ -1,27 +1,26 @@
package com.panda3ds.pandroid.utils; package com.panda3ds.pandroid.utils;
public class Constants { 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_A = 1 << 0;
public static final int INPUT_KEY_DOWN = 1 << 7; public static final int INPUT_KEY_B = 1 << 1;
public static final int INPUT_KEY_LEFT = 1 << 5; public static final int INPUT_KEY_X = 1 << 10;
public static final int INPUT_KEY_RIGHT = 1 << 4; public static final int INPUT_KEY_Y = 1 << 11;
public static final int INPUT_KEY_A = 1 << 0; public static final int INPUT_KEY_R = 1 << 8;
public static final int INPUT_KEY_B = 1 << 1; public static final int INPUT_KEY_L = 1 << 9;
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_START = 1 << 3;
public static final int INPUT_KEY_L = 1 << 9; public static final int INPUT_KEY_SELECT = 1 << 2;
public static final int INPUT_KEY_START = 1 << 3; public static final int N3DS_WIDTH = 400;
public static final int INPUT_KEY_SELECT = 1 << 2; 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 String EXTRA_PATH = "path";
public static final int N3DS_HALF_HEIGHT = 240; public static final String LOG_TAG = "Alber";
public static final int N3DS_FULL_HEIGHT = 480;
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; import android.provider.MediaStore;
public class PathUtils { 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 } else {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && DocumentsContract.isDocumentUri(context, uri)) { if (Environment.isExternalStorageRemovable()) {
storageDefinition = "EXTERNAL_STORAGE";
if (isExternalStorageDocument(uri)) {// ExternalStorageProvider } else {
final String docId = DocumentsContract.getDocumentId(uri); storageDefinition = "SECONDARY_STORAGE";
final String[] split = docId.split(":"); }
final String type = split[0];
String storageDefinition;
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()){ } else if (isMediaDocument(uri)) { // MediaProvider
storageDefinition = "EXTERNAL_STORAGE"; final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
} else{ Uri contentUri = null;
storageDefinition = "SECONDARY_STORAGE"; 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]; final String selection = "_id=?";
} final String[] selectionArgs = new String[] {split[1]};
} else if (isDownloadsDocument(uri)) {// DownloadsProvider
final String id = DocumentsContract.getDocumentId(uri); return getDataColumn(context, contentUri, selection, selectionArgs);
final Uri contentUri = ContentUris.withAppendedId( }
Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
return getDataColumn(context, contentUri, null, null); } else if ("content".equalsIgnoreCase(uri.getScheme())) { // MediaStore (and general)
} else if (isMediaDocument(uri)) {// MediaProvider // Return the remote address
final String docId = DocumentsContract.getDocumentId(uri); if (isGooglePhotosUri(uri)) return uri.getLastPathSegment();
final String[] split = docId.split(":");
final String type = split[0];
Uri contentUri = null; return getDataColumn(context, uri, null, 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;
}
final String selection = "_id=?"; } else if ("file".equalsIgnoreCase(uri.getScheme())) { // File
final String[] selectionArgs = new String[]{ return uri.getPath();
split[1] }
};
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 try {
if (isGooglePhotosUri(uri)) cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null);
return uri.getLastPathSegment(); 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 public static boolean isDownloadsDocument(Uri uri) { return "com.android.providers.downloads.documents".equals(uri.getAuthority()); }
return uri.getPath();
}
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) { public static boolean isGooglePhotosUri(Uri uri) { return "com.google.android.apps.photos.content".equals(uri.getAuthority()); }
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());
}
} }

View file

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

View file

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

View file

@ -2,7 +2,6 @@ package com.panda3ds.pandroid.view;
import android.content.Context; import android.content.Context;
import android.util.AttributeSet; import android.util.AttributeSet;
import com.panda3ds.pandroid.AlberDriver; import com.panda3ds.pandroid.AlberDriver;
import com.panda3ds.pandroid.R; import com.panda3ds.pandroid.R;
import com.panda3ds.pandroid.utils.Constants; 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; import com.panda3ds.pandroid.view.controller.nodes.Joystick;
public class PandaLayoutController extends ControllerLayout { public class PandaLayoutController extends ControllerLayout {
public PandaLayoutController(Context context) { public PandaLayoutController(Context context) { super(context); }
super(context);
}
public PandaLayoutController(Context context, AttributeSet attrs) { public PandaLayoutController(Context context, AttributeSet attrs) { super(context, attrs); }
super(context, attrs);
}
public PandaLayoutController(Context context, AttributeSet attrs, int defStyleAttr) { public PandaLayoutController(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); }
super(context, attrs, defStyleAttr);
}
public PandaLayoutController(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { public PandaLayoutController(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes); super(context, attrs, defStyleAttr, defStyleRes);
} }
public void initialize(){ public void initialize() {
int[] keyButtonList = { int[] keyButtonList = {R.id.button_a, Constants.INPUT_KEY_A, R.id.button_b, Constants.INPUT_KEY_B,
R.id.button_a, Constants.INPUT_KEY_A, R.id.button_y, Constants.INPUT_KEY_Y, R.id.button_x, Constants.INPUT_KEY_X,
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_left, Constants.INPUT_KEY_LEFT, R.id.button_right, Constants.INPUT_KEY_RIGHT,
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_up, Constants.INPUT_KEY_UP,
R.id.button_down, Constants.INPUT_KEY_DOWN,
R.id.button_start, Constants.INPUT_KEY_START, R.id.button_start, Constants.INPUT_KEY_START, R.id.button_select, Constants.INPUT_KEY_SELECT,
R.id.button_select, Constants.INPUT_KEY_SELECT,
R.id.button_l, Constants.INPUT_KEY_L, R.id.button_l, Constants.INPUT_KEY_L, R.id.button_r, Constants.INPUT_KEY_R};
R.id.button_r, Constants.INPUT_KEY_R
};
for (int i = 0; i < keyButtonList.length; i+=2){ for (int i = 0; i < keyButtonList.length; i += 2) {
final int keyCode = keyButtonList[i+1]; final int keyCode = keyButtonList[i + 1];
((Button)findViewById(keyButtonList[i])).setStateListener((btn, pressed)->{ ((Button) findViewById(keyButtonList[i])).setStateListener((btn, pressed) -> {
if (pressed) AlberDriver.KeyDown(keyCode); if (pressed)
else AlberDriver.KeyUp(keyCode); AlberDriver.KeyDown(keyCode);
}); else
} AlberDriver.KeyUp(keyCode);
});
}
((Joystick)findViewById(R.id.left_analog)) ((Joystick) findViewById(R.id.left_analog)).setJoystickListener((joystick, axisX, axisY) -> {
.setJoystickListener((joystick, axisX, axisY) -> { AlberDriver.SetCirclepadAxis((int) (axisX * 0x9C), (int) (axisY * 0x9C) * -1);
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.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.RelativeLayout; import android.widget.RelativeLayout;
import com.panda3ds.pandroid.math.Vector2; import com.panda3ds.pandroid.math.Vector2;
import com.panda3ds.pandroid.utils.Constants; import com.panda3ds.pandroid.utils.Constants;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
public class ControllerLayout extends RelativeLayout { 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<>(); public ControllerLayout(Context context) { this(context, null); }
private final ArrayList<ControllerNode> controllerNodes = new ArrayList<>();
public ControllerLayout(Context context) { public ControllerLayout(Context context, AttributeSet attrs) { this(context, attrs, 0); }
this(context,null);
}
public ControllerLayout(Context context, AttributeSet attrs) { public ControllerLayout(Context context, AttributeSet attrs, int defStyleAttr) { this(context, attrs, defStyleAttr, 0); }
this(context, attrs,0);
}
public ControllerLayout(Context context, AttributeSet attrs, int defStyleAttr) { public ControllerLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
this(context, attrs, defStyleAttr,0 ); super(context, attrs, defStyleAttr, defStyleRes);
} }
public ControllerLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { public void refreshChildren() {
super(context, attrs, defStyleAttr, defStyleRes); ArrayList<ControllerNode> nodes = new ArrayList<>();
} populateNodesArray(this, nodes);
public void refreshChildren(){ // Need Reverse: First view is in back and last view is in front for respect android View hierarchy
ArrayList<ControllerNode> nodes = new ArrayList<>(); Collections.reverse(nodes);
populateNodesArray(this, nodes);
//Need Reverse: First view is in back and last view is in front for respect android View hierarchy controllerNodes.clear();
Collections.reverse(nodes); controllerNodes.addAll(nodes);
}
controllerNodes.clear(); private void populateNodesArray(ViewGroup group, ArrayList<ControllerNode> list) {
controllerNodes.addAll(nodes); 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){ @Override
for (int i = 0; i < group.getChildCount(); i++){ public boolean onTouchEvent(MotionEvent event) {
View view = group.getChildAt(i); int index = event.getActionIndex();
if(view instanceof ControllerNode){
list.add((ControllerNode) view);
} else if (view instanceof ViewGroup) {
populateNodesArray((ViewGroup) view, list);
}
}
}
@Override switch (event.getActionMasked()) {
public boolean onTouchEvent(MotionEvent event) { case MotionEvent.ACTION_UP:
int index = event.getActionIndex(); 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()){ private void processTouch(boolean up, float x, float y, int index) {
case MotionEvent.ACTION_UP: int[] globalPosition = new int[2];
case MotionEvent.ACTION_CANCEL: getLocationInWindow(globalPosition);
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 action = TouchEvent.ACTION_MOVE;
int[] globalPosition = new int[2];
getLocationInWindow(globalPosition);
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))){ float cx = (pos.x - globalPosition[0]);
if (up)return; float cy = (pos.y - globalPosition[1]);
ControllerNode node = null; if (item.isVisible() && x > cx && x < cx + size.x && y > cy && y < cy + size.y) {
for (ControllerNode item: controllerNodes){ node = item;
Vector2 pos = item.getPosition(); break;
Vector2 size= item.getSize(); }
}
if (node != null) {
activeTouchEvents.put(index, node);
action = TouchEvent.ACTION_DOWN;
} else {
return;
}
}
float cx = (pos.x - globalPosition[0]); if (up) action = TouchEvent.ACTION_UP;
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; ControllerNode node = activeTouchEvents.get(index);
Vector2 pos = node.getPosition();
pos.x -= globalPosition[0];
pos.y -= globalPosition[1];
ControllerNode node = activeTouchEvents.get(index); x -= pos.x;
Vector2 pos = node.getPosition(); y -= pos.y;
pos.x -= globalPosition[0];
pos.y -= globalPosition[1];
x -= pos.x; node.onTouch(new TouchEvent(x, y, action));
y -= pos.y;
node.onTouch(new TouchEvent(x,y,action)); if (up) {
activeTouchEvents.remove(index);
}
}
if(up){ @Override
activeTouchEvents.remove(index); public void onViewAdded(View child) {
} super.onViewAdded(child);
} refreshChildren();
}
@Override @Override
public void onViewAdded(View child) { public void onViewRemoved(View child) {
super.onViewAdded(child); super.onViewRemoved(child);
refreshChildren(); refreshChildren();
} }
@Override /*@TODO: Need replace that methods for prevent Android send events directly to children*/
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() {
@Override return new ArrayList<>();
public ArrayList<View> getTouchables() { }
return new ArrayList<>();
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return true;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return true;
}
} }

View file

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

View file

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

View file

@ -3,5 +3,5 @@ package com.panda3ds.pandroid.view.controller.listeners;
import com.panda3ds.pandroid.view.controller.nodes.Button; import com.panda3ds.pandroid.view.controller.nodes.Button;
public interface ButtonStateListener { 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; import com.panda3ds.pandroid.view.controller.nodes.Joystick;
public interface JoystickListener { 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.content.Context;
import android.util.AttributeSet; import android.util.AttributeSet;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatTextView; import androidx.appcompat.widget.AppCompatTextView;
import com.panda3ds.pandroid.view.controller.ControllerNode; import com.panda3ds.pandroid.view.controller.ControllerNode;
public abstract class BasicControllerNode extends AppCompatTextView implements ControllerNode { public abstract class BasicControllerNode extends AppCompatTextView implements ControllerNode {
public BasicControllerNode(@NonNull Context context) { public BasicControllerNode(@NonNull Context context) { super(context); }
super(context);
}
public BasicControllerNode(@NonNull Context context, @Nullable AttributeSet attrs) { public BasicControllerNode(@NonNull Context context, @Nullable AttributeSet attrs) { super(context, attrs); }
super(context, attrs);
}
public BasicControllerNode(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { public BasicControllerNode(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); }
super(context, attrs, defStyleAttr);
}
} }

View file

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

View file

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

View file

@ -3,7 +3,6 @@ package com.panda3ds.pandroid.view.controller.nodes;
import android.graphics.Rect; import android.graphics.Rect;
import android.util.Log; import android.util.Log;
import android.view.View; import android.view.View;
import com.panda3ds.pandroid.AlberDriver; import com.panda3ds.pandroid.AlberDriver;
import com.panda3ds.pandroid.R; import com.panda3ds.pandroid.R;
import com.panda3ds.pandroid.utils.Constants; import com.panda3ds.pandroid.utils.Constants;
@ -12,28 +11,28 @@ import com.panda3ds.pandroid.view.controller.TouchEvent;
import com.panda3ds.pandroid.view.renderer.ConsoleRenderer; import com.panda3ds.pandroid.view.renderer.ConsoleRenderer;
public interface TouchScreenNodeImpl extends ControllerNode { 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; Rect bounds = renderer.getLayout().getBottomDisplayBounds();
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);
if (event.getX() >= bounds.left && event.getY() >= bounds.top && event.getX() <= bounds.right && event.getY() <= bounds.bottom){ x = Math.round((x / (float) bounds.width()) * 320);
int x = (int) (event.getX() - bounds.left); y = Math.round((y / (float) bounds.height()) * 240);
int y = (int) (event.getY() - bounds.top);
x = Math.round((x/(float)bounds.width())*320); AlberDriver.TouchScreenDown(x, y);
y = Math.round((y/(float)bounds.height())*240);
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; import com.panda3ds.pandroid.view.renderer.layout.ConsoleLayout;
public interface ConsoleRenderer { public interface ConsoleRenderer {
void setLayout(ConsoleLayout layout); void setLayout(ConsoleLayout layout);
ConsoleLayout getLayout(); ConsoleLayout getLayout();
String getBackendName(); String getBackendName();
} }

View file

@ -1,15 +1,14 @@
package com.panda3ds.pandroid.view.renderer.layout; package com.panda3ds.pandroid.view.renderer.layout;
import android.graphics.Rect; import android.graphics.Rect;
import com.panda3ds.pandroid.math.Vector2; import com.panda3ds.pandroid.math.Vector2;
public interface ConsoleLayout { public interface ConsoleLayout {
void update(int screenWidth, int screenHeight); void update(int screenWidth, int screenHeight);
void setBottomDisplaySourceSize(int width, int height); void setBottomDisplaySourceSize(int width, int height);
void setTopDisplaySourceSize(int width, int height); void setTopDisplaySourceSize(int width, int height);
Rect getBottomDisplayBounds(); Rect getBottomDisplayBounds();
Rect getTopDisplayBounds(); Rect getTopDisplayBounds();
} }

View file

@ -2,80 +2,76 @@ package com.panda3ds.pandroid.view.renderer.layout;
import android.graphics.Rect; import android.graphics.Rect;
import android.util.Size; import android.util.Size;
import com.panda3ds.pandroid.math.Vector2; import com.panda3ds.pandroid.math.Vector2;
public class DefaultScreenLayout implements ConsoleLayout { public class DefaultScreenLayout implements ConsoleLayout {
private final Rect topDisplay = new Rect(); private final Rect topDisplay = new Rect();
private final Rect bottomDisplay = new Rect(); private final Rect bottomDisplay = new Rect();
private final Vector2 screenSize = 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 topSourceSize = new Vector2(1.0F, 1.0F);
private final Vector2 bottomSourceSize = new Vector2(1.0F, 1.0F); private final Vector2 bottomSourceSize = new Vector2(1.0F, 1.0F);
@Override @Override
public void update(int screenWidth, int screenHeight) { public void update(int screenWidth, int screenHeight) {
screenSize.set(screenWidth, screenHeight); screenSize.set(screenWidth, screenHeight);
updateBounds(); updateBounds();
} }
@Override @Override
public void setBottomDisplaySourceSize(int width, int height) { public void setBottomDisplaySourceSize(int width, int height) {
bottomSourceSize.set(width,height); bottomSourceSize.set(width, height);
updateBounds(); updateBounds();
} }
@Override @Override
public void setTopDisplaySourceSize(int width, int height) { public void setTopDisplaySourceSize(int width, int height) {
topSourceSize.set(width,height); topSourceSize.set(width, height);
updateBounds(); updateBounds();
} }
private void updateBounds(){ private void updateBounds() {
int screenWidth = (int) screenSize.x; int screenWidth = (int) screenSize.x;
int screenHeight = (int) screenSize.y; 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); if (topDisplayWidth > (screenWidth * 0.7)) {
int topDisplayHeight = screenHeight; topDisplayWidth = (int) (screenWidth * 0.7);
topDisplayHeight = (int) ((topDisplayWidth / topSourceSize.x) * topSourceSize.y);
}
if (topDisplayWidth > (screenWidth*0.7)){ int bottomDisplayHeight = (int) (((screenWidth - topDisplayWidth) / bottomSourceSize.x) * bottomSourceSize.y);
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;
topDisplay.set(0, 0, topDisplayWidth, topDisplayHeight); if (topScreenHeight + bottomDisplayHeight > screenHeight) {
bottomDisplay.set(topDisplayWidth, 0, topDisplayWidth+(screenWidth-topDisplayWidth), bottomDisplayHeight); bottomDisplayHeight = (screenHeight - topScreenHeight);
} else { bottomDisplayWidth = (int) ((bottomDisplayHeight / bottomSourceSize.y) * bottomSourceSize.x);
int topScreenHeight = (int) ((screenWidth/ topSourceSize.x) * topSourceSize.y); bottomDisplayX = (screenWidth - bottomDisplayX) / 2;
topDisplay.set(0,0,screenWidth,topScreenHeight); }
int bottomDisplayHeight = (int)((screenWidth/ bottomSourceSize.x) * bottomSourceSize.y); topDisplay.set(0, 0, screenWidth, topScreenHeight);
int bottomDisplayWidth = screenWidth; bottomDisplay.set(bottomDisplayX, topScreenHeight, bottomDisplayX + bottomDisplayWidth, topScreenHeight + bottomDisplayHeight);
int bottomDisplayX = 0; }
}
if (topScreenHeight + bottomDisplayHeight > screenHeight){ @Override
bottomDisplayHeight = (screenHeight-topScreenHeight); public Rect getBottomDisplayBounds() {
bottomDisplayWidth = (int) ((bottomDisplayHeight/ bottomSourceSize.y)*bottomSourceSize.x); return bottomDisplay;
bottomDisplayX = (screenWidth-bottomDisplayX)/2; }
}
topDisplay.set(0,0, screenWidth,topScreenHeight); @Override
bottomDisplay.set(bottomDisplayX, topScreenHeight, bottomDisplayX+bottomDisplayWidth,topScreenHeight+bottomDisplayHeight); public Rect getTopDisplayBounds() {
} return topDisplay;
} }
@Override
public Rect getBottomDisplayBounds() {
return bottomDisplay;
}
@Override
public Rect getTopDisplayBounds() {
return topDisplay;
}
} }