mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-19 20:19:13 +12:00
Add game to launcher and some clear code.
This commit is contained in:
parent
3a0ca3baa0
commit
94b9f3137d
39 changed files with 354 additions and 271 deletions
|
@ -32,6 +32,8 @@
|
|||
<activity
|
||||
android:name=".app.GameActivity"
|
||||
android:supportsPictureInPicture="true"
|
||||
android:taskAffinity="emulator.GameActivity"
|
||||
android:launchMode="singleTop"
|
||||
android:configChanges="screenSize|screenLayout|smallestScreenSize|orientation|density|uiMode">
|
||||
</activity>
|
||||
<activity
|
||||
|
@ -57,6 +59,15 @@
|
|||
</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>
|
||||
|
|
|
@ -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;
|
||||
|
@ -11,11 +14,9 @@ import android.view.WindowManager;
|
|||
import android.widget.CheckBox;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import android.app.PictureInPictureParams;
|
||||
import android.content.res.Configuration;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Rational;
|
||||
|
||||
import com.panda3ds.pandroid.AlberDriver;
|
||||
import com.panda3ds.pandroid.R;
|
||||
import com.panda3ds.pandroid.app.game.AlberInputListener;
|
||||
|
@ -61,9 +62,7 @@ public class GameActivity extends BaseActivity implements EmulatorCallback {
|
|||
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));
|
||||
|
@ -74,6 +73,13 @@ public class GameActivity extends BaseActivity implements EmulatorCallback {
|
|||
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
|
||||
|
@ -84,51 +90,20 @@ public class GameActivity extends BaseActivity implements EmulatorCallback {
|
|||
InputHandler.reset();
|
||||
InputHandler.setMotionDeadZone(InputMap.getDeadZone());
|
||||
InputHandler.setEventListener(inputListener);
|
||||
if (GlobalConfig.get(GlobalConfig.KEY_PICTURE_IN_PICTURE)) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
if (!drawerFragment.isOpened()) {
|
||||
setPictureInPictureParams(new PictureInPictureParams.Builder().setAutoEnterEnabled(true).build());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
|
||||
getTheme().applyStyle(R.style.GameActivityNavigationBar, true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode, Configuration newConfig) {
|
||||
super.onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig);
|
||||
if (isInPictureInPictureMode) {
|
||||
findViewById(R.id.overlay_controller).setVisibility(View.GONE);
|
||||
} else {
|
||||
if (GlobalConfig.get(GlobalConfig.KEY_SCREEN_GAMEPAD_VISIBLE)) {
|
||||
findViewById(R.id.overlay_controller).setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUserLeaveHint() {
|
||||
super.onUserLeaveHint();
|
||||
DisplayMetrics displayMetrics = new DisplayMetrics();
|
||||
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
|
||||
|
||||
int widthPixels = displayMetrics.widthPixels;
|
||||
int heightPixels = displayMetrics.heightPixels;
|
||||
|
||||
// Calculate aspect ratio
|
||||
float aspectRatio = (float) widthPixels / (float) heightPixels;
|
||||
|
||||
if (GlobalConfig.get(GlobalConfig.KEY_PICTURE_IN_PICTURE)) {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
|
||||
if (!drawerFragment.isOpened()) {
|
||||
Rational aspectRatioRational = new Rational(widthPixels, heightPixels);
|
||||
PictureInPictureParams.Builder pipBuilder = new PictureInPictureParams.Builder();
|
||||
pipBuilder.setAspectRatio(aspectRatioRational);
|
||||
enterPictureInPictureMode(pipBuilder.build());
|
||||
}
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -137,8 +112,14 @@ public class GameActivity extends BaseActivity implements EmulatorCallback {
|
|||
super.onPause();
|
||||
|
||||
InputHandler.reset();
|
||||
if (GlobalConfig.get(GlobalConfig.KEY_PICTURE_IN_PICTURE)) {
|
||||
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O) {
|
||||
goToPictureInPicture();
|
||||
}
|
||||
} else {
|
||||
drawerFragment.open();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dispatchKeyEvent(KeyEvent event) {
|
||||
|
@ -159,8 +140,9 @@ public class GameActivity extends BaseActivity implements EmulatorCallback {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void swapScreens() {
|
||||
currentDsLayout = currentDsLayout + 1 < DsLayoutManager.getLayoutCount() ? currentDsLayout + 1 : 0;
|
||||
public void swapScreens(int index) {
|
||||
currentDsLayout = index;
|
||||
GlobalConfig.set(GlobalConfig.KEY_CURRENT_DS_LAYOUT,index);
|
||||
renderer.setLayout(DsLayoutManager.createLayout(currentDsLayout));
|
||||
}
|
||||
|
||||
|
@ -176,11 +158,14 @@ public class GameActivity extends BaseActivity implements EmulatorCallback {
|
|||
@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 onUserLeaveHint() {
|
||||
super.onUserLeaveHint();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -188,7 +173,6 @@ public class GameActivity extends BaseActivity implements EmulatorCallback {
|
|||
if (AlberDriver.HasRomLoaded()) {
|
||||
AlberDriver.Finalize();
|
||||
}
|
||||
|
||||
super.onDestroy();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import androidx.appcompat.app.ActionBar;
|
|||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceFragmentCompat;
|
||||
import androidx.preference.SwitchPreferenceCompat;
|
||||
|
||||
import com.panda3ds.pandroid.lang.Function;
|
||||
|
||||
|
@ -21,6 +22,10 @@ public abstract class BasePreferenceFragment extends PreferenceFragmentCompat {
|
|||
});
|
||||
}
|
||||
|
||||
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) {
|
||||
|
|
|
@ -1,16 +1,23 @@
|
|||
package com.panda3ds.pandroid.app.base;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.content.pm.ShortcutInfoCompat;
|
||||
import androidx.core.content.pm.ShortcutManagerCompat;
|
||||
import androidx.core.graphics.drawable.IconCompat;
|
||||
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialog;
|
||||
import com.panda3ds.pandroid.R;
|
||||
import com.panda3ds.pandroid.app.PandroidApplication;
|
||||
import com.panda3ds.pandroid.app.game.GameLauncher;
|
||||
import com.panda3ds.pandroid.data.game.GameMetadata;
|
||||
import com.panda3ds.pandroid.utils.CompatUtils;
|
||||
import com.panda3ds.pandroid.utils.FileUtils;
|
||||
import com.panda3ds.pandroid.utils.GameUtils;
|
||||
import com.panda3ds.pandroid.view.gamesgrid.GameIconView;
|
||||
|
@ -32,11 +39,14 @@ public class GameAboutDialog extends BaseSheetDialog {
|
|||
((TextView) findViewById(R.id.game_publisher)).setText(game.getPublisher());
|
||||
((TextView) findViewById(R.id.region)).setText(game.getRegions()[0].localizedName());
|
||||
((TextView) findViewById(R.id.directory)).setText(FileUtils.obtainUri(game.getRealPath()).getPath());
|
||||
|
||||
findViewById(R.id.play).setOnClickListener(v -> {
|
||||
dismiss();
|
||||
GameUtils.launch(getContext(), game);
|
||||
});
|
||||
findViewById(R.id.shortcut).setOnClickListener(v -> {
|
||||
dismiss();
|
||||
makeShortcut();
|
||||
});
|
||||
|
||||
if (game.getRomPath().startsWith("folder:")) {
|
||||
findViewById(R.id.remove).setVisibility(View.GONE);
|
||||
|
@ -50,4 +60,22 @@ public class GameAboutDialog extends BaseSheetDialog {
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void makeShortcut() {
|
||||
Context context = CompatUtils.findActivity(getContext());
|
||||
ShortcutInfoCompat.Builder shortcut = new ShortcutInfoCompat.Builder(context, game.getId());
|
||||
if (game.getIcon() != null){
|
||||
shortcut.setIcon(IconCompat.createWithAdaptiveBitmap(game.getIcon()));
|
||||
} else {
|
||||
shortcut.setIcon(IconCompat.createWithResource(getContext(), R.mipmap.ic_launcher));
|
||||
}
|
||||
shortcut.setActivity(new ComponentName(context, GameLauncher.class));
|
||||
shortcut.setLongLabel(game.getTitle());
|
||||
shortcut.setShortLabel(game.getTitle());
|
||||
Intent intent = new Intent(PandroidApplication.getAppContext(), GameLauncher.class);
|
||||
intent.setAction(Intent.ACTION_VIEW);
|
||||
intent.setData(new Uri.Builder().scheme("pandroid-game").authority(game.getId()).build());
|
||||
shortcut.setIntent(intent);
|
||||
ShortcutManagerCompat.requestPinShortcut(context,shortcut.build(),null);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,9 @@ import com.panda3ds.pandroid.view.gamesgrid.GameIconView;
|
|||
|
||||
public class DrawerFragment extends Fragment implements DrawerLayout.DrawerListener, NavigationView.OnNavigationItemSelectedListener {
|
||||
private DrawerLayout drawerContainer;
|
||||
private View drawerLayout;
|
||||
private EmulatorCallback emulator;
|
||||
private GameMetadata game;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
|
@ -44,21 +46,21 @@ public class DrawerFragment extends Fragment implements DrawerLayout.DrawerListe
|
|||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
drawerContainer.setVisibility(View.GONE);
|
||||
drawerLayout = view.findViewById(R.id.drawer_layout);
|
||||
|
||||
((NavigationView)view.findViewById(R.id.menu)).setNavigationItemSelectedListener(this);
|
||||
refresh();
|
||||
}
|
||||
|
||||
private void refresh(){
|
||||
GameMetadata game = GameUtils.getCurrentGame();
|
||||
View view = getView();
|
||||
game = GameUtils.getCurrentGame();
|
||||
if (game.getIcon() != null && !game.getIcon().isRecycled()) {
|
||||
((GameIconView) view.findViewById(R.id.game_icon)).setImageBitmap(game.getIcon());
|
||||
((GameIconView) drawerLayout.findViewById(R.id.game_icon)).setImageBitmap(game.getIcon());
|
||||
} else {
|
||||
((GameIconView) view.findViewById(R.id.game_icon)).setImageDrawable(new ColorDrawable(Color.TRANSPARENT));
|
||||
((GameIconView) drawerLayout.findViewById(R.id.game_icon)).setImageDrawable(new ColorDrawable(Color.TRANSPARENT));
|
||||
}
|
||||
((AppCompatTextView)view.findViewById(R.id.game_title)).setText(game.getTitle());
|
||||
((AppCompatTextView)view.findViewById(R.id.game_publisher)).setText(game.getPublisher());
|
||||
((AppCompatTextView)drawerLayout.findViewById(R.id.game_title)).setText(game.getTitle());
|
||||
((AppCompatTextView)drawerLayout.findViewById(R.id.game_publisher)).setText(game.getPublisher());
|
||||
|
||||
}
|
||||
|
||||
|
@ -119,7 +121,7 @@ public class DrawerFragment extends Fragment implements DrawerLayout.DrawerListe
|
|||
emulator.swapScreens();
|
||||
close();
|
||||
} else if (id == R.id.exit) {
|
||||
requireActivity().finish();
|
||||
requireActivity().finishAndRemoveTask();
|
||||
} else if (id == R.id.lua_script) {
|
||||
new LuaDialogFragment().show(getParentFragmentManager(), null);
|
||||
} else if (id == R.id.change_orientation) {
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
package com.panda3ds.pandroid.app.game;
|
||||
|
||||
import com.panda3ds.pandroid.data.config.GlobalConfig;
|
||||
|
||||
public interface EmulatorCallback {
|
||||
void onBackPressed();
|
||||
|
||||
void swapScreens();
|
||||
void swapScreens(int index);
|
||||
default void swapScreens() {
|
||||
swapScreens(GlobalConfig.get(GlobalConfig.KEY_CURRENT_DS_LAYOUT)+1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
package com.panda3ds.pandroid.app.game;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.pm.ShortcutManagerCompat;
|
||||
|
||||
import com.panda3ds.pandroid.R;
|
||||
import com.panda3ds.pandroid.app.BaseActivity;
|
||||
import com.panda3ds.pandroid.data.game.GameMetadata;
|
||||
import com.panda3ds.pandroid.utils.GameUtils;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class GameLauncher extends BaseActivity {
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(new TextView(this));
|
||||
Uri uri = getIntent().getData();
|
||||
if(uri != null && uri.getScheme().equals("pandroid-game")){
|
||||
String gameId = uri.getAuthority();
|
||||
GameMetadata game = GameUtils.findGameById(gameId);
|
||||
if (game != null){
|
||||
GameUtils.launch(this, game);
|
||||
} else {
|
||||
Toast.makeText(this, R.string.invalid_game,Toast.LENGTH_LONG).show();
|
||||
ShortcutManagerCompat.removeDynamicShortcuts(this, Arrays.asList(gameId));
|
||||
ShortcutManagerCompat.removeLongLivedShortcuts(this, Arrays.asList(gameId));
|
||||
}
|
||||
}
|
||||
finish();
|
||||
}
|
||||
}
|
|
@ -21,7 +21,6 @@ public class AdvancedPreferences extends BasePreferenceFragment {
|
|||
setActivityTitle(R.string.advanced_options);
|
||||
|
||||
setItemClick("performanceMonitor", pref -> GlobalConfig.set(GlobalConfig.KEY_SHOW_PERFORMANCE_OVERLAY, ((SwitchPreferenceCompat) pref).isChecked()));
|
||||
setItemClick("pictureInPicture", pref -> GlobalConfig.set(GlobalConfig.KEY_PICTURE_IN_PICTURE, ((SwitchPreferenceCompat) pref).isChecked()));
|
||||
setItemClick("shaderJit", pref -> GlobalConfig.set(GlobalConfig.KEY_SHADER_JIT, ((SwitchPreferenceCompat) pref).isChecked()));
|
||||
setItemClick("loggerService", pref -> {
|
||||
boolean checked = ((SwitchPreferenceCompat) pref).isChecked();
|
||||
|
@ -45,14 +44,7 @@ public class AdvancedPreferences extends BasePreferenceFragment {
|
|||
|
||||
private void refresh() {
|
||||
((SwitchPreferenceCompat) findPreference("performanceMonitor")).setChecked(GlobalConfig.get(GlobalConfig.KEY_SHOW_PERFORMANCE_OVERLAY));
|
||||
((SwitchPreferenceCompat) findPreference("pictureInPicture")).setChecked(GlobalConfig.get(GlobalConfig.KEY_PICTURE_IN_PICTURE));
|
||||
((SwitchPreferenceCompat) findPreference("loggerService")).setChecked(GlobalConfig.get(GlobalConfig.KEY_LOGGER_SERVICE));
|
||||
((SwitchPreferenceCompat) findPreference("shaderJit")).setChecked(GlobalConfig.get(GlobalConfig.KEY_SHADER_JIT));
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
findPreference("pictureInPicture").setEnabled(true);
|
||||
} else {
|
||||
findPreference("pictureInPicture").setEnabled(false);
|
||||
findPreference("pictureInPicture").setSummary("Your device does not support this feature");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,6 @@ import androidx.annotation.Nullable;
|
|||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialog;
|
||||
import com.panda3ds.pandroid.R;
|
||||
import com.panda3ds.pandroid.app.base.BasePreferenceFragment;
|
||||
import com.panda3ds.pandroid.app.base.BaseSheetDialog;
|
||||
|
@ -29,7 +28,7 @@ public class GamesFoldersPreferences extends BasePreferenceFragment implements A
|
|||
@Override
|
||||
public void onCreatePreferences(@Nullable Bundle savedInstanceState, @Nullable String rootKey) {
|
||||
setPreferencesFromResource(R.xml.empty_preferences, rootKey);
|
||||
setActivityTitle(R.string.pref_games_folders);
|
||||
setActivityTitle(R.string.pref_game_folders);
|
||||
refreshList();
|
||||
pickFolderRequest = registerForActivityResult(openFolderContract, this);
|
||||
}
|
||||
|
|
|
@ -3,19 +3,33 @@ package com.panda3ds.pandroid.app.preferences;
|
|||
import android.os.Bundle;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.preference.SwitchPreferenceCompat;
|
||||
|
||||
import com.panda3ds.pandroid.R;
|
||||
import com.panda3ds.pandroid.app.PreferenceActivity;
|
||||
import com.panda3ds.pandroid.app.base.BasePreferenceFragment;
|
||||
import com.panda3ds.pandroid.app.preferences.ds.DsListPreferences;
|
||||
import com.panda3ds.pandroid.app.preferences.screen_editor.ScreenLayoutsPreference;
|
||||
import com.panda3ds.pandroid.data.config.GlobalConfig;
|
||||
|
||||
public class GeneralPreferences extends BasePreferenceFragment {
|
||||
@Override
|
||||
public void onCreatePreferences(@Nullable Bundle savedInstanceState, @Nullable String rootKey) {
|
||||
setPreferencesFromResource(R.xml.general_preference, rootKey);
|
||||
setItemClick("appearance.theme", (pref) -> new ThemeSelectorDialog(requireActivity()).show());
|
||||
setItemClick("appearance.ds", (pref) -> PreferenceActivity.launch(requireActivity(), DsListPreferences.class));
|
||||
setItemClick("appearance.ds", (pref) -> PreferenceActivity.launch(requireActivity(), ScreenLayoutsPreference.class));
|
||||
setItemClick("games.folders", (pref) -> PreferenceActivity.launch(requireActivity(), GamesFoldersPreferences.class));
|
||||
setItemClick("behavior.pictureInPicture", (pref)-> GlobalConfig.set(GlobalConfig.KEY_PICTURE_IN_PICTURE, ((SwitchPreferenceCompat)pref).isChecked()));
|
||||
setActivityTitle(R.string.general);
|
||||
refresh();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
refresh();
|
||||
}
|
||||
|
||||
private void refresh(){
|
||||
setSwitchValue("behavior.pictureInPicture", GlobalConfig.get(GlobalConfig.KEY_PICTURE_IN_PICTURE));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package com.panda3ds.pandroid.app.preferences.ds;
|
||||
package com.panda3ds.pandroid.app.preferences.screen_editor;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
|
@ -16,9 +16,8 @@ import com.panda3ds.pandroid.app.BaseActivity;
|
|||
import com.panda3ds.pandroid.view.ds.DsEditorView;
|
||||
import com.panda3ds.pandroid.view.ds.DsLayoutManager;
|
||||
|
||||
public class DsEditorPreferences extends Fragment {
|
||||
public class ScreenEditorPreference extends Fragment {
|
||||
private LinearLayout layout;
|
||||
private DsEditorView editor;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
|
@ -33,7 +32,7 @@ public class DsEditorPreferences extends Fragment {
|
|||
super.onViewCreated(view, savedInstanceState);
|
||||
int index = getArguments().getInt("index");
|
||||
layout.removeAllViews();
|
||||
layout.addView(editor = new DsEditorView(view.getContext(), index), new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
|
||||
layout.addView(new DsEditorView(view.getContext(), index), new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
|
||||
((BaseActivity)requireActivity()).getSupportActionBar().hide();
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.panda3ds.pandroid.app.preferences.ds;
|
||||
package com.panda3ds.pandroid.app.preferences.screen_editor;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
|
@ -12,7 +12,7 @@ import com.panda3ds.pandroid.app.PreferenceActivity;
|
|||
import com.panda3ds.pandroid.app.base.BasePreferenceFragment;
|
||||
import com.panda3ds.pandroid.view.ds.DsLayoutManager;
|
||||
|
||||
public class DsListPreferences extends BasePreferenceFragment {
|
||||
public class ScreenLayoutsPreference extends BasePreferenceFragment {
|
||||
@Override
|
||||
public void onCreatePreferences(@Nullable Bundle savedInstanceState, @Nullable String rootKey) {
|
||||
setPreferencesFromResource(R.xml.empty_preferences, rootKey);
|
||||
|
@ -33,7 +33,7 @@ public class DsListPreferences extends BasePreferenceFragment {
|
|||
|
||||
final int index = i;
|
||||
pref.setOnPreferenceClickListener(preference -> {
|
||||
PreferenceActivity.launch(requireContext(), DsEditorPreferences.class, new Intent().putExtra("index", index));
|
||||
PreferenceActivity.launch(requireContext(), ScreenEditorPreference.class, new Intent().putExtra("index", index));
|
||||
return false;
|
||||
});
|
||||
screen.addPreference(pref);
|
|
@ -13,9 +13,12 @@ import androidx.annotation.Nullable;
|
|||
|
||||
import com.panda3ds.pandroid.R;
|
||||
import com.panda3ds.pandroid.app.PandroidApplication;
|
||||
import com.panda3ds.pandroid.utils.FileUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
|
||||
public class AppDataDocumentProvider extends DocumentsProvider {
|
||||
private static final String ROOT_ID = "root";
|
||||
|
@ -89,8 +92,10 @@ public class AppDataDocumentProvider extends DocumentsProvider {
|
|||
|
||||
private void includeFile(MatrixCursor cursor, File file) {
|
||||
int flags = 0;
|
||||
if (file.isFile()) {
|
||||
flags = Document.FLAG_SUPPORTS_WRITE;
|
||||
if (file.isDirectory()) {
|
||||
flags = Document.FLAG_DIR_SUPPORTS_CREATE;
|
||||
} else {
|
||||
flags = Document.FLAG_SUPPORTS_WRITE | Document.FLAG_SUPPORTS_REMOVE | Document.FLAG_SUPPORTS_DELETE;
|
||||
}
|
||||
cursor.newRow()
|
||||
.add(Document.COLUMN_DOCUMENT_ID, obtainDocumentId(file))
|
||||
|
@ -116,6 +121,40 @@ public class AppDataDocumentProvider extends DocumentsProvider {
|
|||
return cursor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String createDocument(String parentDocumentId, String mimeType, String displayName) throws FileNotFoundException {
|
||||
File parent = obtainFile(parentDocumentId);
|
||||
File file = new File(parent, displayName);
|
||||
if (!parent.exists()){
|
||||
throw new FileNotFoundException("Parent don't exists");
|
||||
}
|
||||
|
||||
if (Objects.equals(mimeType, Document.MIME_TYPE_DIR)){
|
||||
if (!file.mkdirs()){
|
||||
throw new FileNotFoundException("Error on create directory");
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
if (!file.createNewFile()){
|
||||
throw new Exception("Error on create file");
|
||||
}
|
||||
} catch (Exception e){
|
||||
throw new FileNotFoundException(e.getMessage());
|
||||
}
|
||||
}
|
||||
return obtainDocumentId(file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteDocument(String documentId) throws FileNotFoundException {
|
||||
File file = obtainFile(documentId);
|
||||
if (file.exists()){
|
||||
FileUtils.delete(file.getAbsolutePath());
|
||||
} else {
|
||||
throw new FileNotFoundException("File not exists");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParcelFileDescriptor openDocument(String documentId, String mode, @Nullable CancellationSignal signal) throws FileNotFoundException {
|
||||
return ParcelFileDescriptor.open(obtainFile(documentId), ParcelFileDescriptor.parseMode(mode));
|
||||
|
|
|
@ -93,7 +93,7 @@ public class SMDH {
|
|||
smdh.position(META_OFFSET + (512 * i) + 0x80);
|
||||
data = new byte[0x100];
|
||||
smdh.get(data);
|
||||
title[i] = convertString(data).replaceAll("\n", " ");
|
||||
title[i] = convertString(data);
|
||||
|
||||
smdh.position(META_OFFSET + (512 * i) + 0x180);
|
||||
data = new byte[0x80];
|
||||
|
|
|
@ -22,11 +22,12 @@ public class GlobalConfig {
|
|||
public static DataModel data;
|
||||
|
||||
public static final Key<Boolean> KEY_SHADER_JIT = new Key<>("emu.shader_jit", false);
|
||||
public static final Key<Boolean> KEY_PICTURE_IN_PICTURE = new Key<>("app.behavior.pictureInPicture", false);
|
||||
public static final Key<Boolean> KEY_SHOW_PERFORMANCE_OVERLAY = new Key<>("dev.performanceOverlay", false);
|
||||
public static final Key<Boolean> KEY_PICTURE_IN_PICTURE = new Key<>("dev.pictureInPicture", false);
|
||||
public static final Key<Boolean> KEY_LOGGER_SERVICE = new Key<>("dev.loggerService", false);
|
||||
public static final Key<Integer> KEY_APP_THEME = new Key<>("app.theme", THEME_ANDROID);
|
||||
public static final Key<Boolean> KEY_SCREEN_GAMEPAD_VISIBLE = new Key<>("app.screen_gamepad.visible", true);
|
||||
public static final Key<Integer> KEY_CURRENT_DS_LAYOUT = new Key<>("app.ds.current_layout",0);
|
||||
public static final Key<String> KEY_DS_LAYOUTS = new Key<>("app.ds.layouts", "");
|
||||
|
||||
public static void initialize() {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package com.panda3ds.pandroid.utils;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.ActivityManager;
|
||||
import android.content.Context;
|
||||
import android.content.ContextWrapper;
|
||||
import android.content.res.TypedArray;
|
||||
|
|
|
@ -157,6 +157,15 @@ public class GameUtils {
|
|||
writeChanges();
|
||||
}
|
||||
|
||||
public static GameMetadata findGameById(String id) {
|
||||
for (GameMetadata game: getGames()){
|
||||
if (game.getId().equals(id)){
|
||||
return game;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static class DataModel {
|
||||
public final List<GameMetadata> games = new ArrayList<>();
|
||||
public final HashMap<String, GamesFolder> folders = new HashMap<>();
|
||||
|
|
|
@ -16,6 +16,7 @@ import com.panda3ds.pandroid.app.base.BottomAlertDialog;
|
|||
import com.panda3ds.pandroid.data.SMDH;
|
||||
import com.panda3ds.pandroid.data.config.GlobalConfig;
|
||||
import com.panda3ds.pandroid.data.game.GameMetadata;
|
||||
import com.panda3ds.pandroid.utils.CompatUtils;
|
||||
import com.panda3ds.pandroid.utils.Constants;
|
||||
import com.panda3ds.pandroid.utils.GameUtils;
|
||||
import com.panda3ds.pandroid.utils.PerformanceMonitor;
|
||||
|
@ -103,7 +104,7 @@ public class PandaGlRenderer implements GLSurfaceView.Renderer, ConsoleRenderer
|
|||
.setMessage(R.string.dialog_message_invalid_rom)
|
||||
.setPositiveButton(android.R.string.ok, (dialog, witch) -> {
|
||||
dialog.dismiss();
|
||||
((Activity) context).finish();
|
||||
CompatUtils.findActivity(context).finishAndRemoveTask();
|
||||
})
|
||||
.setCancelable(false)
|
||||
.show();
|
||||
|
|
|
@ -30,10 +30,8 @@ import com.panda3ds.pandroid.math.Vector2;
|
|||
import com.panda3ds.pandroid.utils.CompatUtils;
|
||||
import com.panda3ds.pandroid.utils.Constants;
|
||||
|
||||
@SuppressLint("ViewConstructor")
|
||||
public class DsEditorView extends FrameLayout {
|
||||
|
||||
private final int COLOR_TOP_SELECTION;
|
||||
private final int COLOR_BOTTOM_SELECTION;
|
||||
private final float SIZE_DP;
|
||||
|
||||
private final Paint selectionPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
|
@ -54,10 +52,10 @@ public class DsEditorView extends FrameLayout {
|
|||
super(context);
|
||||
layout = (DsLayout) DsLayoutManager.createLayout(index);
|
||||
SIZE_DP = CompatUtils.applyDimen(TypedValue.COMPLEX_UNIT_DIP, 1);
|
||||
COLOR_BOTTOM_SELECTION = CompatUtils.resolveColor(context, androidx.appcompat.R.attr.colorPrimary);
|
||||
COLOR_TOP_SELECTION = CompatUtils.resolveColor(context, com.google.android.material.R.attr.colorAccent);
|
||||
int colorBottomSelection = CompatUtils.resolveColor(context, androidx.appcompat.R.attr.colorPrimary);
|
||||
int colorTopSelection = CompatUtils.resolveColor(context, com.google.android.material.R.attr.colorAccent);
|
||||
|
||||
selectionPaint.setColor(COLOR_TOP_SELECTION);
|
||||
selectionPaint.setColor(colorTopSelection);
|
||||
selectionPaint.setStrokeWidth(SIZE_DP * 2);
|
||||
selectionPaint.setPathEffect(new DashPathEffect(new float[]{SIZE_DP * 10, SIZE_DP * 10}, 0.0f));
|
||||
selectionPaint.setStyle(Paint.Style.STROKE);
|
||||
|
@ -100,9 +98,7 @@ public class DsEditorView extends FrameLayout {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onNothingSelected(AdapterView<?> parent) {
|
||||
|
||||
}
|
||||
public void onNothingSelected(AdapterView<?> parent) {}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -113,7 +109,7 @@ public class DsEditorView extends FrameLayout {
|
|||
});
|
||||
|
||||
spacePoint = new PointView();
|
||||
spacePoint.setColor(Color.WHITE, COLOR_TOP_SELECTION);
|
||||
spacePoint.setColor(CompatUtils.resolveColor(context, com.google.android.material.R.attr.colorOnPrimary), colorTopSelection);
|
||||
spacePoint.setOnTouchListener((view, motion) -> {
|
||||
layout.getCurrentModel().space = (motion.getX() + spacePoint.x()) / (float) width;
|
||||
refreshPoints();
|
||||
|
@ -124,7 +120,7 @@ public class DsEditorView extends FrameLayout {
|
|||
|
||||
setOnClickListener(v -> {
|
||||
if (layout.getCurrentModel().mode == Mode.SINGLE) {
|
||||
layout.getCurrentModel().singleTop = !layout.getCurrentModel().singleTop;
|
||||
layout.getCurrentModel().onlyTop = !layout.getCurrentModel().onlyTop;
|
||||
refreshPoints();
|
||||
}
|
||||
});
|
||||
|
@ -132,40 +128,38 @@ public class DsEditorView extends FrameLayout {
|
|||
topDisplay = new PointView();
|
||||
topDisplay.setText(R.string.top_display);
|
||||
topDisplay.setOnTouchListener(new DisplayTouchEvent(true));
|
||||
topDisplay.setTextColor(COLOR_TOP_SELECTION);
|
||||
topDisplay.setBackground(new SelectionDrawable(COLOR_TOP_SELECTION));
|
||||
topDisplay.setTextColor(colorTopSelection);
|
||||
topDisplay.setBackground(new SelectionDrawable(colorTopSelection));
|
||||
|
||||
bottomDisplay = new PointView();
|
||||
bottomDisplay.setText(R.string.bottom_display);
|
||||
bottomDisplay.setOnTouchListener(new DisplayTouchEvent(false));
|
||||
bottomDisplay.setTextColor(COLOR_BOTTOM_SELECTION);
|
||||
bottomDisplay.setBackground(new SelectionDrawable(COLOR_BOTTOM_SELECTION));
|
||||
bottomDisplay.setTextColor(colorBottomSelection);
|
||||
bottomDisplay.setBackground(new SelectionDrawable(colorBottomSelection));
|
||||
|
||||
topDisplayResizer = new PointView();
|
||||
topDisplayResizer.setColor(0, COLOR_TOP_SELECTION);
|
||||
topDisplayResizer.setColor(0, colorTopSelection);
|
||||
topDisplayResizer.setOnTouchListener(new DisplayResizeTouchEvent(true));
|
||||
|
||||
bottomDisplayResizer = new PointView();
|
||||
bottomDisplayResizer.setColor(0, COLOR_BOTTOM_SELECTION);
|
||||
bottomDisplayResizer.setColor(0, colorBottomSelection);
|
||||
bottomDisplayResizer.setOnTouchListener(new DisplayResizeTouchEvent(false));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
int width = getMeasuredWidth();
|
||||
int height = getMeasuredHeight();
|
||||
if (this.width != width || this.height != height) {
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
public void draw(Canvas canvas) {
|
||||
super.draw(canvas);
|
||||
if (this.width != getWidth() || this.height != getHeight()) {
|
||||
this.width = getWidth();
|
||||
this.height = getHeight();
|
||||
refreshLayout();
|
||||
}
|
||||
}
|
||||
|
||||
private void refreshPoints() {
|
||||
Model data = layout.getCurrentModel();
|
||||
data.preferredTop.fixOverlay(width, height, (int) (SIZE_DP*5));
|
||||
data.preferredBottom.fixOverlay(width, height, (int) (SIZE_DP*30));
|
||||
data.preferredTop.fixOverlay(width, height, (int) (SIZE_DP * 5));
|
||||
data.preferredBottom.fixOverlay(width, height, (int) (SIZE_DP * 30));
|
||||
layout.update(width, height);
|
||||
Rect bottomDisplay = layout.getBottomDisplayBounds();
|
||||
Rect topDisplay = layout.getTopDisplayBounds();
|
||||
|
@ -322,6 +316,7 @@ public class DsEditorView extends FrameLayout {
|
|||
|
||||
private class DisplayResizeTouchEvent implements OnTouchListener {
|
||||
private final boolean topScreen;
|
||||
|
||||
private DisplayResizeTouchEvent(boolean topScreen) {
|
||||
this.topScreen = topScreen;
|
||||
}
|
||||
|
|
|
@ -10,17 +10,17 @@ class DsLayout implements ConsoleLayout {
|
|||
private final Rect topDisplay = new Rect();
|
||||
private final Rect bottomDisplay = new Rect();
|
||||
|
||||
private final Vector2 screenSize = new Vector2(0,0);
|
||||
private final Vector2 sourceTop = new Vector2(0,0);
|
||||
private final Vector2 sourceBottom = new Vector2(0,0);
|
||||
private final Vector2 screenSize = new Vector2(0, 0);
|
||||
private final Vector2 sourceTop = new Vector2(0, 0);
|
||||
private final Vector2 sourceBottom = new Vector2(0, 0);
|
||||
private final Model[] modes = new Model[2];
|
||||
|
||||
public DsLayout(Model landscape, Model portrait){
|
||||
public DsLayout(Model landscape, Model portrait) {
|
||||
modes[0] = landscape;
|
||||
modes[1] = portrait;
|
||||
}
|
||||
|
||||
public DsLayout(){
|
||||
public DsLayout() {
|
||||
this(new Model(), new Model());
|
||||
}
|
||||
|
||||
|
@ -52,10 +52,10 @@ class DsLayout implements ConsoleLayout {
|
|||
return topDisplay;
|
||||
}
|
||||
|
||||
public void update(){
|
||||
public void update() {
|
||||
Model data = getCurrentModel();
|
||||
Mode mode = data.mode;
|
||||
switch (mode){
|
||||
switch (mode) {
|
||||
case RELATIVE:
|
||||
relative(data);
|
||||
break;
|
||||
|
@ -69,22 +69,18 @@ class DsLayout implements ConsoleLayout {
|
|||
}
|
||||
|
||||
private void absolute(Model data) {
|
||||
if (data.lockAspect){
|
||||
data.preferredTop.applyWithAspect(topDisplay, (int) screenSize.x, (double) sourceTop.y/sourceTop.x);
|
||||
data.preferredBottom.applyWithAspect(bottomDisplay, (int) screenSize.x, (double) sourceBottom.y/sourceBottom.x);
|
||||
if (data.lockAspect) {
|
||||
data.preferredTop.applyWithAspect(topDisplay, (int) screenSize.x, (double) sourceTop.y / sourceTop.x);
|
||||
data.preferredBottom.applyWithAspect(bottomDisplay, (int) screenSize.x, (double) sourceBottom.y / sourceBottom.x);
|
||||
} else {
|
||||
data.preferredTop.apply(topDisplay, (int) screenSize.x, (int) screenSize.y);
|
||||
data.preferredBottom.apply(bottomDisplay, (int) screenSize.x, (int) screenSize.y);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* SINGLE LAYOUT:
|
||||
* SHOW ONLY SCREEN IN FIT MODE
|
||||
*/
|
||||
private void single(Model data) {
|
||||
Vector2 source = data.singleTop ? sourceTop : sourceBottom;
|
||||
Rect dest = data.singleTop ? topDisplay : bottomDisplay;
|
||||
Vector2 source = data.onlyTop ? sourceTop : sourceBottom;
|
||||
Rect dest = data.onlyTop ? topDisplay : bottomDisplay;
|
||||
|
||||
if (data.lockAspect) {
|
||||
int x = 0, y = 0;
|
||||
|
@ -99,11 +95,11 @@ class DsLayout implements ConsoleLayout {
|
|||
height = (int) screenSize.y;
|
||||
x = (int) ((screenSize.x - width) / 2);
|
||||
}
|
||||
dest.set(x,y,x+width,y+height);
|
||||
dest.set(x, y, x + width, y + height);
|
||||
} else {
|
||||
dest.set(0,0, (int) screenSize.x, (int) screenSize.y);
|
||||
dest.set(0, 0, (int) screenSize.x, (int) screenSize.y);
|
||||
}
|
||||
(data.singleTop ? bottomDisplay : topDisplay).set(0,0,0,0);
|
||||
(data.onlyTop ? bottomDisplay : topDisplay).set(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
|
@ -122,7 +118,7 @@ class DsLayout implements ConsoleLayout {
|
|||
Rect topDisplay = this.topDisplay;
|
||||
Rect bottomDisplay = this.bottomDisplay;
|
||||
|
||||
if (data.reverse){
|
||||
if (data.reverse) {
|
||||
topSourceSize = this.sourceBottom;
|
||||
bottomSourceSize = this.sourceTop;
|
||||
|
||||
|
@ -144,15 +140,17 @@ class DsLayout implements ConsoleLayout {
|
|||
topDisplay.set(0, 0, topDisplayWidth, topDisplayHeight);
|
||||
bottomDisplay.set(topDisplayWidth, 0, topDisplayWidth + (screenWidth - topDisplayWidth), bottomDisplayHeight);
|
||||
|
||||
switch (data.gravity){
|
||||
case Gravity.CENTER:{
|
||||
bottomDisplay.offset(0, (screenHeight-bottomDisplay.height())/2);
|
||||
topDisplay.offset(0, (screenHeight-topDisplay.height())/2);
|
||||
}break;
|
||||
case Gravity.BOTTOM:{
|
||||
bottomDisplay.offset(0, (screenHeight-bottomDisplay.height()));
|
||||
topDisplay.offset(0, (screenHeight-topDisplay.height()));
|
||||
}break;
|
||||
switch (data.gravity) {
|
||||
case Gravity.CENTER: {
|
||||
bottomDisplay.offset(0, (screenHeight - bottomDisplay.height()) / 2);
|
||||
topDisplay.offset(0, (screenHeight - topDisplay.height()) / 2);
|
||||
}
|
||||
break;
|
||||
case Gravity.BOTTOM: {
|
||||
bottomDisplay.offset(0, (screenHeight - bottomDisplay.height()));
|
||||
topDisplay.offset(0, (screenHeight - topDisplay.height()));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
|
|
@ -20,11 +20,11 @@ public class DsLayoutManager {
|
|||
|
||||
Model model2 = new Model();
|
||||
model2.mode = Mode.SINGLE;
|
||||
model2.singleTop = false;
|
||||
model2.onlyTop = false;
|
||||
|
||||
Model model3 = new Model();
|
||||
model3.mode = Mode.SINGLE;
|
||||
model3.singleTop = true;
|
||||
model3.onlyTop = true;
|
||||
|
||||
data.models.add(new Model[]{model1, model1.clone()});
|
||||
data.models.add(new Model[]{model2, model2.clone()});
|
||||
|
|
|
@ -12,7 +12,7 @@ class Model implements Cloneable {
|
|||
public final Bounds preferredTop = new Bounds();
|
||||
public final Bounds preferredBottom = new Bounds();
|
||||
public boolean reverse = false;
|
||||
public boolean singleTop = true;
|
||||
public boolean onlyTop = true;
|
||||
public float space = 0.6f;
|
||||
public int gravity = Gravity.CENTER;
|
||||
public boolean lockAspect = true;
|
||||
|
|
|
@ -4,6 +4,6 @@
|
|||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:fillColor="#FFF"
|
||||
android:pathData="M8,19h3v4h2v-4h3l-4,-4 -4,4zM16,5h-3L13,1h-2v4L8,5l4,4 4,-4zM4,11v2h16v-2L4,11z"/>
|
||||
</vector>
|
||||
|
|
|
@ -2,8 +2,9 @@
|
|||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
android:viewportHeight="24"
|
||||
android:tint="?colorOnSurface">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:fillColor="#FFF"
|
||||
android:pathData="M7.41,8.59 L12,13.17l4.59,-4.58L18,10l-6,6 -6,-6 1.41,-1.41z"/>
|
||||
</vector>
|
||||
|
|
|
@ -2,8 +2,9 @@
|
|||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
android:viewportHeight="24"
|
||||
android:tint="?colorOnSurface">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:fillColor="#FFF"
|
||||
android:pathData="M7.41,15.41 L12,10.83l4.59,4.58L18,14l-6,-6 -6,6z"/>
|
||||
</vector>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<vector android:height="24dp" android:tint="#000000"
|
||||
<vector android:height="24dp" android:tint="?colorOnSurface"
|
||||
android:viewportHeight="24" android:viewportWidth="24"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="@android:color/white" android:pathData="M9.4,16.6L4.8,12l4.6,-4.6L8,6l-6,6 6,6 1.4,-1.4zM14.6,16.6l4.6,-4.6 -4.6,-4.6L16,6l6,6 -6,6 -1.4,-1.4z"/>
|
||||
|
|
|
@ -2,8 +2,9 @@
|
|||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
android:viewportHeight="24"
|
||||
android:tint="?colorOnSurface">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:fillColor="#FFF"
|
||||
android:pathData="M9.01,14L2,14v2h7.01v3L13,15l-3.99,-4v3zM14.99,13v-3L22,10L22,8h-7.01L14.99,5L11,9l3.99,4z"/>
|
||||
</vector>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<vector android:height="24dp" android:tint="#000000"
|
||||
<vector android:height="24dp" android:tint="?colorOnSurface"
|
||||
android:viewportHeight="24" android:viewportWidth="24"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="@android:color/white" android:pathData="M9,16.2L4.8,12l-1.4,1.4L9,19 21,7l-1.4,-1.4L9,16.2z"/>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<vector android:autoMirrored="true" android:height="24dp"
|
||||
android:tint="#000000" android:viewportHeight="24"
|
||||
android:tint="?colorOnSurface" android:viewportHeight="24"
|
||||
android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="@android:color/white" android:pathData="M10.09,15.59L11.5,17l5,-5 -5,-5 -1.41,1.41L12.67,11H3v2h9.67l-2.58,2.59zM19,3H5c-1.11,0 -2,0.9 -2,2v4h2V5h14v14H5v-4H3v4c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2V5c0,-1.1 -0.9,-2 -2,-2z"/>
|
||||
</vector>
|
||||
|
|
|
@ -2,8 +2,9 @@
|
|||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
android:viewportHeight="24"
|
||||
android:tint="?colorOnSurface">
|
||||
<path
|
||||
android:fillColor="?colorOnSurface"
|
||||
android:fillColor="#FFF"
|
||||
android:pathData="M10,4H4c-1.1,0 -1.99,0.9 -1.99,2L2,18c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2V8c0,-1.1 -0.9,-2 -2,-2h-8l-2,-2z"/>
|
||||
</vector>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<vector android:autoMirrored="true" android:height="24dp"
|
||||
android:tint="#000000" android:viewportHeight="24"
|
||||
android:tint="?colorOnSurface" android:viewportHeight="24"
|
||||
android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="@android:color/white" android:pathData="M21,11l-6,-6v5H8c-2.76,0 -5,2.24 -5,5v4h2v-4c0,-1.65 1.35,-3 3,-3h7v5L21,11z"/>
|
||||
</vector>
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:state_checked="true">
|
||||
<layer-list>
|
||||
<item>
|
||||
<shape>
|
||||
<padding android:bottom="3dp" android:top="3dp" android:right="3dp" android:left="3dp"/>
|
||||
<solid android:color="#0000"/>
|
||||
</shape>
|
||||
</item>
|
||||
<item>
|
||||
<shape>
|
||||
<size android:width="18dp" android:height="18dp"/>
|
||||
<corners android:radius="999dp"/>
|
||||
<solid android:color="?colorPrimary"/>
|
||||
</shape>
|
||||
</item>
|
||||
</layer-list>
|
||||
</item>
|
||||
<item>
|
||||
<layer-list>
|
||||
<item>
|
||||
<shape>
|
||||
<padding android:bottom="3dp" android:top="3dp" android:right="3dp" android:left="3dp"/>
|
||||
<solid android:color="#0000"/>
|
||||
</shape>
|
||||
</item>
|
||||
<item>
|
||||
<shape android:tintMode="multiply" android:tint="#2FFF">
|
||||
<size android:width="18dp" android:height="18dp"/>
|
||||
<corners android:radius="999dp"/>
|
||||
<solid android:color="?colorOnSurface"/>
|
||||
</shape>
|
||||
</item>
|
||||
</layer-list>
|
||||
</item>
|
||||
</selector>
|
|
@ -1,19 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:state_checked="true">
|
||||
<shape android:tintMode="multiply" android:tint="#5FFF">
|
||||
<padding android:left="5dp" android:right="5dp" />
|
||||
<solid android:color="?colorPrimary"/>
|
||||
<corners android:radius="24dp"/>
|
||||
<size android:width="32dp" android:height="22dp"/>
|
||||
</shape>
|
||||
</item>
|
||||
<item>
|
||||
<shape android:tintMode="multiply" android:tint="#2FFF">
|
||||
<padding android:left="5dp" android:right="5dp" />
|
||||
<solid android:color="?colorOnSurface"/>
|
||||
<corners android:radius="24dp"/>
|
||||
<size android:width="32dp" android:height="22dp"/>
|
||||
</shape>
|
||||
</item>
|
||||
</selector>
|
|
@ -92,15 +92,26 @@
|
|||
android:gravity="end|center">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/remove"
|
||||
android:id="@+id/shortcut"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/remove"
|
||||
app:icon="@drawable/ic_delete"
|
||||
app:icon="@drawable/ic_shortcut"
|
||||
app:iconTint="?colorOnSurfaceVariant"
|
||||
android:textColor="?colorOnSurfaceVariant"
|
||||
android:backgroundTint="?colorSurfaceVariant"
|
||||
android:layout_marginHorizontal="10dp"/>
|
||||
android:layout_marginHorizontal="10dp"
|
||||
style="@style/Widget.Material3.Button.IconButton"/>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/remove"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:icon="@drawable/ic_delete"
|
||||
app:iconTint="?colorSurfaceVariant"
|
||||
android:textColor="?colorOnSurfaceVariant"
|
||||
android:backgroundTint="?colorOnSurfaceVariant"
|
||||
android:layout_marginHorizontal="10dp"
|
||||
style="@style/Widget.Material3.Button.IconButton"/>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/play"
|
||||
|
@ -111,6 +122,7 @@
|
|||
android:textColor="?colorOnPrimary"
|
||||
android:backgroundTint="?colorPrimary"
|
||||
app:icon="@drawable/ic_play"
|
||||
app:rippleColor="?colorOnPrimary"
|
||||
app:iconTint="?colorOnPrimary"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
android:textColor="?colorOnSurface"
|
||||
android:text="@string/app_name"
|
||||
android:textStyle="bold"
|
||||
android:textSize="14sp"
|
||||
android:gravity="center"
|
||||
android:layout_marginTop="10dp"/>
|
||||
|
||||
|
|
|
@ -53,6 +53,8 @@
|
|||
<string name="pref_logger_service_summary">Grave os registros para um arquivo.</string>
|
||||
<string name="pref_shader_jit_title">Shader Jit</string>
|
||||
<string name="pref_shader_jit_summary">Usar recompilador de shaders.</string>
|
||||
<string name="pref_picture_in_picture_title">Picture In Picture</string>
|
||||
<string name="pref_picture_in_picture_summary">Entrar em modo picture in picture quando a janela sai de foco</string>
|
||||
<string name="graphics">Gráficos</string>
|
||||
<string name="loading">Carregando</string>
|
||||
<string name="rotate">Rotacionar</string>
|
||||
|
@ -67,12 +69,12 @@
|
|||
<string name="bottom_display">Tela inferior</string>
|
||||
<string name="top_display">Tela superior</string>
|
||||
<string name="fix_aspect">Manter porporção</string>
|
||||
<string name="dual_screen_layouts">Disposições para as duas telas.</string>
|
||||
<string name="dual_screen_layouts">Disposição das telas</string>
|
||||
<string name="dual_screen_layouts_summary">Altere as disposições disponiveis para as telas do console</string>
|
||||
<string name="click_to_change">Clique para mudar</string>
|
||||
<string name="swap_screen">Mudar telas</string>
|
||||
<string name="pref_games_folders_summary">Pastas usadas para importar os jogos</string>
|
||||
<string name="pref_games_folders">Pastas de jogos</string>
|
||||
<string name="pref_game_folders_summary">Pastas usadas para importar os jogos</string>
|
||||
<string name="pref_game_folders">Pastas de jogos</string>
|
||||
<string name="import_folder">Adicionar pasta</string>
|
||||
<string name="games_count_f">%d Jogos</string>
|
||||
<string name="directory">Diretorio</string>
|
||||
|
@ -85,4 +87,7 @@
|
|||
<string name="region_australia">Australia</string>
|
||||
<string name="region_korean">Coréia</string>
|
||||
<string name="region_taiwan">Taiwan</string>
|
||||
<string name="behavior">Comportamento</string>
|
||||
<string name="invalid_game">Jogo invalido</string>
|
||||
<string name="tools">Ferramentas</string>
|
||||
</resources>
|
||||
|
|
|
@ -52,7 +52,6 @@
|
|||
<!-- Advanced Settings -->
|
||||
<string name="advanced_options">Advanced options</string>
|
||||
<string name="pref_advanced_summary">Logger, performance statistics, etc.</string>
|
||||
<string name="display">Display</string>
|
||||
<string name="pref_performance_monitor_title">Performance monitor</string>
|
||||
<string name="pref_performance_monitor_summary">Show overlay with fps, memory, etc.</string>
|
||||
<string name="pref_picture_in_picture_title">Picture In Picture</string>
|
||||
|
@ -60,7 +59,7 @@
|
|||
<string name="graphics">Graphics</string>
|
||||
<string name="pref_shader_jit_title">Shader JIT</string>
|
||||
<string name="pref_shader_jit_summary">Use shader recompiler.</string>
|
||||
<string name="debug">Debug</string>
|
||||
<string name="tools">Tools</string>
|
||||
<string name="pref_logger_service_title">Logger</string>
|
||||
<string name="pref_logger_service_summary">Store application logs to file.</string>
|
||||
<string name="loading">Loading</string>
|
||||
|
@ -71,21 +70,23 @@
|
|||
<string name="dialog_message_invalid_rom">Make sure it\'s a valid 3DS ROM and that storage permissions are configured properly.</string>
|
||||
<string name="system">System</string>
|
||||
<string name="general">General</string>
|
||||
<string name="pref_general_summary">General application configurations.</string>
|
||||
<string name="bottom_display">Bottom Display</string>
|
||||
<string name="top_display">Top Display</string>
|
||||
<string name="fix_aspect">Fix aspect</string>
|
||||
<string name="dual_screen_layouts">Dual Screen layouts</string>
|
||||
<string name="pref_general_summary">General application configuration.</string>
|
||||
<string name="dual_screen_layouts">Screen layouts</string>
|
||||
<string name="dual_screen_layouts_summary">Change layout of console screens.</string>
|
||||
<string name="click_to_change">Click to change</string>
|
||||
<string name="swap_screen">Swap screen</string>
|
||||
<string name="pref_games_folders_summary">Folders for auto import games</string>
|
||||
<string name="pref_games_folders">Games folders</string>
|
||||
<string name="pref_game_folders_summary">Folders for importing games</string>
|
||||
<string name="pref_game_folders">Game folders</string>
|
||||
<string name="import_folder">Import folder</string>
|
||||
<string name="games_count_f">%d Games</string>
|
||||
<string name="directory">Directory</string>
|
||||
<string name="remove">Remove</string>
|
||||
<string name="play">Play</string>
|
||||
<!-- Screen layout editor -->
|
||||
<string name="fix_aspect">Maintain aspect ratio</string>
|
||||
<string name="bottom_display">Bottom Display</string>
|
||||
<string name="top_display">Top Display</string>
|
||||
<!-- Game about -->
|
||||
<string name="region">Region</string>
|
||||
<string name="region_north_armerican">North American</string>
|
||||
<string name="region_japan">Japan</string>
|
||||
|
@ -93,4 +94,6 @@
|
|||
<string name="region_australia">Australia</string>
|
||||
<string name="region_korean">Korean</string>
|
||||
<string name="region_taiwan">Taiwan</string>
|
||||
<string name="behavior">Behavior</string>
|
||||
<string name="invalid_game">Invalid game</string>
|
||||
</resources>
|
||||
|
|
|
@ -3,9 +3,8 @@
|
|||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<PreferenceCategory
|
||||
app:iconSpaceReserved="false"
|
||||
app:title="@string/display">
|
||||
|
||||
app:title="@string/tools"
|
||||
app:iconSpaceReserved="false">
|
||||
<SwitchPreferenceCompat
|
||||
android:key="performanceMonitor"
|
||||
app:title="@string/pref_performance_monitor_title"
|
||||
|
@ -30,17 +29,4 @@
|
|||
app:iconSpaceReserved="false"/>
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory
|
||||
app:iconSpaceReserved="false"
|
||||
app:title="@string/debug">
|
||||
|
||||
<SwitchPreferenceCompat
|
||||
android:key="loggerService"
|
||||
app:iconSpaceReserved="false"
|
||||
app:title="@string/pref_logger_service_title"
|
||||
android:defaultValue="true"
|
||||
android:summaryOn="@string/pref_logger_service_summary"
|
||||
android:summaryOff="@string/pref_logger_service_summary"/>
|
||||
</PreferenceCategory>
|
||||
</PreferenceScreen>
|
|
@ -20,8 +20,17 @@
|
|||
app:iconSpaceReserved="false">
|
||||
<Preference
|
||||
android:key="games.folders"
|
||||
app:title="@string/pref_games_folders"
|
||||
app:summary="@string/pref_games_folders_summary"
|
||||
app:title="@string/pref_game_folders"
|
||||
app:summary="@string/pref_game_folders_summary"
|
||||
app:iconSpaceReserved="false"/>
|
||||
</PreferenceCategory>
|
||||
<PreferenceCategory
|
||||
app:title="@string/behavior"
|
||||
app:iconSpaceReserved="false">
|
||||
<SwitchPreferenceCompat
|
||||
android:key="behavior.pictureInPicture"
|
||||
app:title="@string/pref_picture_in_picture_title"
|
||||
app:summary="@string/pref_picture_in_picture_summary"
|
||||
app:iconSpaceReserved="false"/>
|
||||
</PreferenceCategory>
|
||||
</PreferenceScreen>
|
Loading…
Add table
Add a link
Reference in a new issue