Skip to content

Commit

Permalink
Pandroid: Screen layout editor (wheremyfoodat#425)
Browse files Browse the repository at this point in the history
* Add Dynamic colors option for Android 12 or above  (#8)

* Dynamic color for android 12 or above @Ishan09811

* Revert "Add Dynamic colors option for Android 12 or above  (#8)" (#9)

This reverts commit 6ee1a39.

* Material Switch  (#10) | ISHAN | REVIEW

* Review Material Switch

* basic implement, ds editor, and remake theme selector

* add swap screen in drawer

* basic file provider for access private folder from file explorer

* Pandroid: Game about dialog (#7)

* Alert dialog idea

* Reimplement ishan game dialog.

* Add Picture In Picture support with a option  (#11)

- Ishan picture in picture pr

* some fixes

* Add game to launcher and some clear code.

---------

Co-authored-by: Ishan09811 <[email protected]>
Co-authored-by: gabriel <gabriel>
  • Loading branch information
GabrielBRDeveloper and Ishan09811 authored Feb 29, 2024
1 parent 90f8fbf commit 02496b5
Show file tree
Hide file tree
Showing 84 changed files with 2,674 additions and 371 deletions.
25 changes: 24 additions & 1 deletion src/pandroid/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,10 @@
</activity>
<activity
android:name=".app.GameActivity"
android:configChanges="screenSize|screenLayout|orientation|density|uiMode">
android:supportsPictureInPicture="true"
android:taskAffinity="emulator.GameActivity"
android:launchMode="singleTop"
android:configChanges="screenSize|screenLayout|smallestScreenSize|orientation|density|uiMode">
</activity>
<activity
android:name=".app.editor.CodeEditorActivity"
Expand All @@ -49,6 +52,26 @@
<activity android:name=".app.preferences.InputMapActivity"
android:configChanges="density|orientation|screenSize"/>

<provider
android:authorities="com.panda3ds.pandroid.user"
android:name="com.panda3ds.pandroid.app.provider.AppDataDocumentProvider"
android:exported="true"
android:grantUriPermissions="true"
android:permission="android.permission.MANAGE_DOCUMENTS">
<intent-filter>
<action android:name="android.content.action.DOCUMENTS_PROVIDER" />
</intent-filter>
</provider>

<activity
android:name=".app.game.GameLauncher"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<data android:scheme="pandroid-game"/>
</intent-filter>
</activity>

<service android:name=".app.services.LoggerService" android:process=":logger_service"/>
</application>
</manifest>
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package com.panda3ds.pandroid.app;

import android.os.Bundle;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import com.panda3ds.pandroid.R;

import com.google.android.material.color.DynamicColors;
import com.panda3ds.pandroid.data.config.GlobalConfig;


Expand All @@ -28,5 +30,8 @@ protected void onResume() {
private void applyTheme() {
currentTheme = PandroidApplication.getThemeId();
setTheme(currentTheme);
if (GlobalConfig.get(GlobalConfig.KEY_APP_THEME) == GlobalConfig.THEME_ANDROID){
DynamicColors.applyToActivityIfAvailable(this);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package com.panda3ds.pandroid.app;

import android.app.ActivityManager;
import android.app.PictureInPictureParams;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.util.Rational;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
Expand All @@ -11,22 +14,29 @@
import android.widget.CheckBox;
import android.widget.FrameLayout;
import android.widget.Toast;

import androidx.annotation.Nullable;

import com.panda3ds.pandroid.AlberDriver;
import com.panda3ds.pandroid.R;
import com.panda3ds.pandroid.app.game.AlberInputListener;
import com.panda3ds.pandroid.app.game.DrawerFragment;
import com.panda3ds.pandroid.app.game.EmulatorCallback;
import com.panda3ds.pandroid.data.config.GlobalConfig;
import com.panda3ds.pandroid.input.InputHandler;
import com.panda3ds.pandroid.input.InputMap;
import com.panda3ds.pandroid.utils.Constants;
import com.panda3ds.pandroid.view.PandaGlSurfaceView;
import com.panda3ds.pandroid.view.PandaLayoutController;
import com.panda3ds.pandroid.view.ds.DsLayoutManager;
import com.panda3ds.pandroid.view.renderer.ConsoleRenderer;
import com.panda3ds.pandroid.view.utils.PerformanceView;

public class GameActivity extends BaseActivity {
public class GameActivity extends BaseActivity implements EmulatorCallback {
private final DrawerFragment drawerFragment = new DrawerFragment();
private final AlberInputListener inputListener = new AlberInputListener(this::onBackPressed);
private final AlberInputListener inputListener = new AlberInputListener(this);
private ConsoleRenderer renderer;
private int currentDsLayout;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
Expand All @@ -43,16 +53,16 @@ protected void onCreate(@Nullable Bundle savedInstanceState) {
PandaGlSurfaceView pandaSurface = new PandaGlSurfaceView(this, intent.getStringExtra(Constants.ACTIVITY_PARAMETER_PATH));
setContentView(R.layout.game_activity);

renderer = pandaSurface.getRenderer();

((FrameLayout) findViewById(R.id.panda_gl_frame))
.addView(pandaSurface, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
.addView(pandaSurface, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));

PandaLayoutController controllerLayout = findViewById(R.id.controller_layout);
controllerLayout.initialize();

((CheckBox) findViewById(R.id.hide_screen_controller)).setOnCheckedChangeListener((buttonView, checked) -> {
findViewById(R.id.overlay_controller).setVisibility(checked ? View.VISIBLE : View.GONE);
findViewById(R.id.overlay_controller).invalidate();
findViewById(R.id.overlay_controller).requestLayout();
changeOverlayVisibility(checked);
GlobalConfig.set(GlobalConfig.KEY_SCREEN_GAMEPAD_VISIBLE, checked);
});
((CheckBox) findViewById(R.id.hide_screen_controller)).setChecked(GlobalConfig.get(GlobalConfig.KEY_SCREEN_GAMEPAD_VISIBLE));
Expand All @@ -63,6 +73,13 @@ protected void onCreate(@Nullable Bundle savedInstanceState) {
PerformanceView view = new PerformanceView(this);
((FrameLayout) findViewById(R.id.panda_gl_frame)).addView(view, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
}
swapScreens(GlobalConfig.get(GlobalConfig.KEY_CURRENT_DS_LAYOUT));
}

private void changeOverlayVisibility(boolean visible){
findViewById(R.id.overlay_controller).setVisibility(visible ? View.VISIBLE : View.GONE);
findViewById(R.id.overlay_controller).invalidate();
findViewById(R.id.overlay_controller).requestLayout();
}

@Override
Expand All @@ -78,12 +95,30 @@ protected void onResume() {
}
}

private void goToPictureInPicture() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
PictureInPictureParams.Builder builder = new PictureInPictureParams.Builder();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
builder.setAutoEnterEnabled(true);
builder.setSeamlessResizeEnabled(true);
}
builder.setAspectRatio(new Rational(10, 14));
enterPictureInPictureMode(builder.build());
}
}

@Override
protected void onPause() {
super.onPause();

InputHandler.reset();
drawerFragment.open();
if (GlobalConfig.get(GlobalConfig.KEY_PICTURE_IN_PICTURE)) {
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O) {
goToPictureInPicture();
}
} else {
drawerFragment.open();
}
}

@Override
Expand All @@ -104,6 +139,13 @@ public void onBackPressed() {
}
}

@Override
public void swapScreens(int index) {
currentDsLayout = index;
GlobalConfig.set(GlobalConfig.KEY_CURRENT_DS_LAYOUT,index);
renderer.setLayout(DsLayoutManager.createLayout(currentDsLayout));
}

@Override
public boolean dispatchGenericMotionEvent(MotionEvent ev) {
if ((!drawerFragment.isOpened()) && InputHandler.processMotionEvent(ev)) {
Expand All @@ -113,12 +155,24 @@ public boolean dispatchGenericMotionEvent(MotionEvent ev) {
return super.dispatchGenericMotionEvent(ev);
}

@Override
public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode) {
super.onPictureInPictureModeChanged(isInPictureInPictureMode);
changeOverlayVisibility(!isInPictureInPictureMode && GlobalConfig.get(GlobalConfig.KEY_SCREEN_GAMEPAD_VISIBLE));
findViewById(R.id.hide_screen_controller).setVisibility(isInPictureInPictureMode ? View.INVISIBLE : View.VISIBLE);
if (isInPictureInPictureMode){
getWindow().getDecorView().postDelayed(drawerFragment::close, 250);
} else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S){
ActivityManager manager = ((ActivityManager) getSystemService(ACTIVITY_SERVICE));
manager.getAppTasks().forEach(ActivityManager.AppTask::moveToFront);
}
}

@Override
protected void onDestroy() {
if (AlberDriver.HasRomLoaded()) {
AlberDriver.Finalize();
}

super.onDestroy();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import android.os.Bundle;
import android.view.MenuItem;

import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
Expand All @@ -16,15 +17,25 @@ public class MainActivity extends BaseActivity implements NavigationBarView.OnIt
private final GamesFragment gamesFragment = new GamesFragment();
private final SearchFragment searchFragment = new SearchFragment();
private final SettingsFragment settingsFragment = new SettingsFragment();
private NavigationBarView navigationBar;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

NavigationBarView bar = findViewById(R.id.navigation);
bar.setOnItemSelectedListener(this);
bar.postDelayed(() -> bar.setSelectedItemId(bar.getSelectedItemId()), 5);
navigationBar = findViewById(R.id.navigation);
navigationBar.setOnItemSelectedListener(this);
navigationBar.postDelayed(() -> navigationBar.setSelectedItemId(navigationBar.getSelectedItemId()), 5);
}

@Override
public void onBackPressed() {
if (navigationBar.getSelectedItemId() != R.id.games){
navigationBar.setSelectedItemId(R.id.games);
return;
}
super.onBackPressed();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import androidx.appcompat.app.AppCompatActivity;
import androidx.preference.Preference;
import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.SwitchPreference;
import androidx.preference.SwitchPreferenceCompat;

import com.panda3ds.pandroid.lang.Function;

Expand All @@ -22,10 +22,14 @@ protected void setItemClick(String key, Function<Preference> listener) {
});
}

protected void setSwitchValue(String id, boolean value){
((SwitchPreferenceCompat)findPreference(id)).setChecked(value);
}

protected void setActivityTitle(@StringRes int titleId) {
ActionBar header = ((AppCompatActivity) requireActivity()).getSupportActionBar();
if (header != null) {
header.setTitle(titleId);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.panda3ds.pandroid.app.base;

import android.content.Context;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;

import androidx.annotation.NonNull;

import com.google.android.material.bottomsheet.BottomSheetDialog;
import com.panda3ds.pandroid.R;
import com.panda3ds.pandroid.utils.CompatUtils;

import org.jetbrains.annotations.NotNull;

public class BaseSheetDialog extends BottomSheetDialog {
private final LinearLayout contentView;
public BaseSheetDialog(@NonNull Context context) {
super(CompatUtils.findActivity(context));
int width = CompatUtils.findActivity(context).getWindow().getDecorView().getMeasuredWidth();
int height = CompatUtils.findActivity(context).getWindow().getDecorView().getMeasuredHeight();
getBehavior().setPeekHeight((int) (height*0.87));
getBehavior().setMaxWidth(width);
getBehavior().setMaxHeight((int) (height*0.87));
super.setContentView(R.layout.dialog_bottom_sheet);
contentView = super.findViewById(R.id.content);
}

@Override
public void setContentView(View view) {
contentView.removeAllViews();
contentView.addView(view);
}

@Override
public void setContentView(int layoutResId) {
setContentView(LayoutInflater.from(getContext()).inflate(layoutResId, null, false));
}

@NotNull
@Override
public <T extends View> T findViewById(int id) {
return contentView.findViewById(id);
}
}
Loading

0 comments on commit 02496b5

Please sign in to comment.