From 0679e43efec8e9ca8dc690ea2a59bf7c1d045f7c Mon Sep 17 00:00:00 2001 From: sigmabeta Date: Thu, 25 Jun 2015 21:43:00 -0400 Subject: Android: Show screenshot on EmulationActivity before game starts. --- .../dolphinemu/activities/EmulationActivity.java | 30 ++++++++++++++++++++++ .../dolphinemu/adapters/GameAdapter.java | 1 + 2 files changed, 31 insertions(+) (limited to 'Source/Android/app/src/main/java') diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java index d1e6f47273..ce3f9624c7 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java @@ -12,6 +12,10 @@ import android.view.Menu; import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; +import android.widget.FrameLayout; +import android.widget.ImageView; + +import com.squareup.picasso.Picasso; import org.dolphinemu.dolphinemu.NativeLibrary; import org.dolphinemu.dolphinemu.R; @@ -22,6 +26,8 @@ import java.util.List; public final class EmulationActivity extends AppCompatActivity { private View mDecorView; + private ImageView mImageView; + private FrameLayout mFrameLayout; private boolean mDeviceHasTouchScreen; private boolean mSystemUiVisible; @@ -79,9 +85,33 @@ public final class EmulationActivity extends AppCompatActivity setContentView(R.layout.activity_emulation); + mImageView = (ImageView) findViewById(R.id.image_screenshot); + mFrameLayout = (FrameLayout) findViewById(R.id.frame_content); + Intent gameToEmulate = getIntent(); String path = gameToEmulate.getStringExtra("SelectedGame"); String title = gameToEmulate.getStringExtra("SelectedTitle"); + String screenPath = gameToEmulate.getStringExtra("ScreenPath"); + + Picasso.with(this) + .load(screenPath) + .fit() + .noFade() + .into(mImageView); + + mImageView.animate() + .setStartDelay(2000) + .setDuration(500) + .alpha(0.0f) + .withEndAction(new Runnable() + { + @Override + public void run() + { + mImageView.setVisibility(View.GONE); + mFrameLayout.setVisibility(View.VISIBLE); + } + }); setTitle(title); diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GameAdapter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GameAdapter.java index a9a7be930e..8b279c52c2 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GameAdapter.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GameAdapter.java @@ -220,6 +220,7 @@ public final class GameAdapter extends RecyclerView.Adapter impl intent.putExtra("SelectedGame", holder.path); intent.putExtra("SelectedTitle", holder.title); + intent.putExtra("ScreenPath", holder.screenshotPath); view.getContext().startActivity(intent); } -- cgit v1.2.3 From 0fcf0e1d213892dd316bb57e5932c2e77fba691b Mon Sep 17 00:00:00 2001 From: sigmabeta Date: Fri, 26 Jun 2015 08:32:51 -0400 Subject: Android: Show transition animation while game loads. --- .../dolphinemu/activities/EmulationActivity.java | 49 ++++++++++++++++++++-- .../dolphinemu/adapters/GameAdapter.java | 8 +++- 2 files changed, 53 insertions(+), 4 deletions(-) (limited to 'Source/Android/app/src/main/java') diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java index ce3f9624c7..44bfbb8272 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java @@ -12,9 +12,11 @@ import android.view.Menu; import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; +import android.view.ViewTreeObserver; import android.widget.FrameLayout; import android.widget.ImageView; +import com.squareup.picasso.Callback; import com.squareup.picasso.Picasso; import org.dolphinemu.dolphinemu.NativeLibrary; @@ -51,6 +53,10 @@ public final class EmulationActivity extends AppCompatActivity { super.onCreate(savedInstanceState); + // Picasso will take a while to load these big-ass screenshots. So don't run + // the animation until we say so. + postponeEnterTransition(); + mDeviceHasTouchScreen = getPackageManager().hasSystemFeature("android.hardware.touchscreen"); // Get a handle to the Window containing the UI. @@ -95,21 +101,42 @@ public final class EmulationActivity extends AppCompatActivity Picasso.with(this) .load(screenPath) - .fit() .noFade() - .into(mImageView); + .noPlaceholder() + .into(mImageView, new Callback() + { + @Override + public void onSuccess() + { + scheduleStartPostponedTransition(mImageView); + } + + @Override + public void onError() + { + // Still have to do this, or else the app will crash. + scheduleStartPostponedTransition(mImageView); + } + }); mImageView.animate() .setStartDelay(2000) .setDuration(500) .alpha(0.0f) + .withStartAction(new Runnable() + { + @Override + public void run() + { + mFrameLayout.setVisibility(View.VISIBLE); + } + }) .withEndAction(new Runnable() { @Override public void run() { mImageView.setVisibility(View.GONE); - mFrameLayout.setVisibility(View.VISIBLE); } }); @@ -354,4 +381,20 @@ public final class EmulationActivity extends AppCompatActivity hideSystemUiAfterDelay(); } + + + private void scheduleStartPostponedTransition(final View sharedElement) + { + sharedElement.getViewTreeObserver().addOnPreDrawListener( + new ViewTreeObserver.OnPreDrawListener() + { + @Override + public boolean onPreDraw() + { + sharedElement.getViewTreeObserver().removeOnPreDrawListener(this); + startPostponedEnterTransition(); + return true; + } + }); + } } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GameAdapter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GameAdapter.java index 8b279c52c2..3cb832f91b 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GameAdapter.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GameAdapter.java @@ -1,6 +1,7 @@ package org.dolphinemu.dolphinemu.adapters; import android.app.Activity; +import android.app.ActivityOptions; import android.content.Intent; import android.database.Cursor; import android.database.DataSetObserver; @@ -222,7 +223,12 @@ public final class GameAdapter extends RecyclerView.Adapter impl intent.putExtra("SelectedTitle", holder.title); intent.putExtra("ScreenPath", holder.screenshotPath); - view.getContext().startActivity(intent); + ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation( + (Activity) view.getContext(), + holder.imageScreenshot, + "image_game_screenshot"); + + view.getContext().startActivity(intent, options.toBundle()); } /** -- cgit v1.2.3 From fd82f90fcea42c11435ce88a61cfe5dfd0d03f1a Mon Sep 17 00:00:00 2001 From: sigmabeta Date: Fri, 26 Jun 2015 15:01:23 -0400 Subject: Android: Show transition animation when exiting game. --- .../org/dolphinemu/dolphinemu/NativeLibrary.java | 2 +- .../dolphinemu/activities/EmulationActivity.java | 73 ++++++++++++++++++++-- .../dolphinemu/activities/MainActivity.java | 31 ++++++--- .../dolphinemu/adapters/GameAdapter.java | 14 +++-- .../fragments/PlatformGamesFragment.java | 16 +++-- 5 files changed, 112 insertions(+), 24 deletions(-) (limited to 'Source/Android/app/src/main/java') diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java index c9efb0c790..9fcdbe8cd1 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java @@ -277,7 +277,7 @@ public final class NativeLibrary public static void endEmulationActivity() { Log.v("DolphinEmu", "Ending EmulationActivity."); - mEmulationActivity.finish(); + mEmulationActivity.exitWithAnimation(); } public static void setEmulationActivity(EmulationActivity emulationActivity) diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java index 44bfbb8272..6b27c08c4a 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java @@ -29,11 +29,14 @@ public final class EmulationActivity extends AppCompatActivity { private View mDecorView; private ImageView mImageView; - private FrameLayout mFrameLayout; + private FrameLayout mFrameEmulation; private boolean mDeviceHasTouchScreen; private boolean mSystemUiVisible; + // So that MainActivity knows which view to invalidate before the return animation. + private int mPosition; + /** * Handlers are a way to pass a message to an Activity telling it to do something * on the UI thread. This Handler responds to any message, even blank ones, by @@ -47,6 +50,8 @@ public final class EmulationActivity extends AppCompatActivity hideSystemUI(); } }; + private String mScreenPath; + private FrameLayout mFrameContent; @Override protected void onCreate(Bundle savedInstanceState) @@ -92,15 +97,17 @@ public final class EmulationActivity extends AppCompatActivity setContentView(R.layout.activity_emulation); mImageView = (ImageView) findViewById(R.id.image_screenshot); - mFrameLayout = (FrameLayout) findViewById(R.id.frame_content); + mFrameContent = (FrameLayout) findViewById(R.id.frame_content); + mFrameEmulation = (FrameLayout) findViewById(R.id.frame_emulation_fragment); Intent gameToEmulate = getIntent(); String path = gameToEmulate.getStringExtra("SelectedGame"); String title = gameToEmulate.getStringExtra("SelectedTitle"); - String screenPath = gameToEmulate.getStringExtra("ScreenPath"); + mScreenPath = gameToEmulate.getStringExtra("ScreenPath"); + mPosition = gameToEmulate.getIntExtra("GridPosition", -1); Picasso.with(this) - .load(screenPath) + .load(mScreenPath) .noFade() .noPlaceholder() .into(mImageView, new Callback() @@ -120,6 +127,7 @@ public final class EmulationActivity extends AppCompatActivity }); mImageView.animate() + .withLayer() .setStartDelay(2000) .setDuration(500) .alpha(0.0f) @@ -128,7 +136,7 @@ public final class EmulationActivity extends AppCompatActivity @Override public void run() { - mFrameLayout.setVisibility(View.VISIBLE); + mFrameEmulation.setVisibility(View.VISIBLE); } }) .withEndAction(new Runnable() @@ -147,7 +155,7 @@ public final class EmulationActivity extends AppCompatActivity // Add fragment to the activity - this triggers all its lifecycle callbacks. getFragmentManager().beginTransaction() - .add(R.id.frame_content, emulationFragment, EmulationFragment.FRAGMENT_TAG) + .add(R.id.frame_emulation_fragment, emulationFragment, EmulationFragment.FRAGMENT_TAG) .commit(); } @@ -212,6 +220,59 @@ public final class EmulationActivity extends AppCompatActivity } } + public void exitWithAnimation() + { + runOnUiThread(new Runnable() + { + @Override + public void run() + { + Picasso.with(EmulationActivity.this) + .invalidate(mScreenPath); + + Picasso.with(EmulationActivity.this) + .load(mScreenPath) + .noFade() + .noPlaceholder() + .into(mImageView, new Callback() + { + @Override + public void onSuccess() + { + showScreenshot(); + } + + @Override + public void onError() + { + finish(); + } + }); + } + }); + } + + private void showScreenshot() + { + mImageView.setVisibility(View.VISIBLE); + mImageView.animate() + .withLayer() + .setDuration(500) + .alpha(1.0f) + .withEndAction(afterShowingScreenshot); + } + + private Runnable afterShowingScreenshot = new Runnable() + { + @Override + public void run() + { + mFrameContent.removeView(mFrameEmulation); + setResult(mPosition); + finishAfterTransition(); + } + }; + @Override public boolean onCreateOptionsMenu(Menu menu) { diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/MainActivity.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/MainActivity.java index 7812e6ead5..33cd0b0c15 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/MainActivity.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/MainActivity.java @@ -36,6 +36,7 @@ import org.dolphinemu.dolphinemu.services.AssetCopyService; public final class MainActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks { private static final int REQUEST_ADD_DIRECTORY = 1; + public static final int REQUEST_EMULATE_GAME = 2; /** * It is important to keep track of loader ID separately from platform ID (see Game.java) @@ -115,15 +116,29 @@ public final class MainActivity extends AppCompatActivity implements LoaderManag @Override protected void onActivityResult(int requestCode, int resultCode, Intent result) { - // If the user picked a file, as opposed to just backing out. - if (resultCode == RESULT_OK) + switch (requestCode) { - // Sanity check to make sure the Activity that just returned was the AddDirectoryActivity; - // other activities might use this callback in the future (don't forget to change Javadoc!) - if (requestCode == REQUEST_ADD_DIRECTORY) - { - refreshFragment(); - } + case REQUEST_ADD_DIRECTORY: + // If the user picked a file, as opposed to just backing out. + if (resultCode == RESULT_OK) + { + // Sanity check to make sure the Activity that just returned was the AddDirectoryActivity; + // other activities might use this callback in the future (don't forget to change Javadoc!) + if (requestCode == REQUEST_ADD_DIRECTORY) + { + refreshFragment(); + } + } + break; + + case REQUEST_EMULATE_GAME: + // Invalidate Picasso image so that the new screenshot is animated in. + PlatformGamesFragment fragment = getPlatformFragment(mViewPager.getCurrentItem()); + + if (fragment != null) + { + fragment.refreshScreenshotAtPosition(resultCode); + } } } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GameAdapter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GameAdapter.java index 3cb832f91b..e74bd6f96d 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GameAdapter.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GameAdapter.java @@ -5,6 +5,7 @@ import android.app.ActivityOptions; import android.content.Intent; import android.database.Cursor; import android.database.DataSetObserver; +import android.graphics.Bitmap; import android.graphics.Rect; import android.support.v7.widget.RecyclerView; import android.util.Log; @@ -16,6 +17,7 @@ import com.squareup.picasso.Picasso; import org.dolphinemu.dolphinemu.R; import org.dolphinemu.dolphinemu.activities.EmulationActivity; +import org.dolphinemu.dolphinemu.activities.MainActivity; import org.dolphinemu.dolphinemu.dialogs.GameDetailsDialog; import org.dolphinemu.dolphinemu.model.GameDatabase; import org.dolphinemu.dolphinemu.viewholders.GameViewHolder; @@ -81,14 +83,15 @@ public final class GameAdapter extends RecyclerView.Adapter impl if (mCursor.moveToPosition(position)) { String screenPath = mCursor.getString(GameDatabase.GAME_COLUMN_SCREENSHOT_PATH); - Picasso.with(holder.imageScreenshot.getContext()) - .invalidate(screenPath); // Fill in the view contents. Picasso.with(holder.imageScreenshot.getContext()) .load(screenPath) .fit() .centerCrop() + .noFade() + .noPlaceholder() + .config(Bitmap.Config.RGB_565) .error(R.drawable.no_banner) .into(holder.imageScreenshot); @@ -113,8 +116,6 @@ public final class GameAdapter extends RecyclerView.Adapter impl { Log.e("DolphinEmu", "Can't bind view; dataset is not valid."); } - - } /** @@ -222,13 +223,16 @@ public final class GameAdapter extends RecyclerView.Adapter impl intent.putExtra("SelectedGame", holder.path); intent.putExtra("SelectedTitle", holder.title); intent.putExtra("ScreenPath", holder.screenshotPath); + intent.putExtra("GridPosition", holder.getAdapterPosition()); ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation( (Activity) view.getContext(), holder.imageScreenshot, "image_game_screenshot"); - view.getContext().startActivity(intent, options.toBundle()); + ((Activity) view.getContext()).startActivityForResult(intent, + MainActivity.REQUEST_EMULATE_GAME, + options.toBundle()); } /** diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/PlatformGamesFragment.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/PlatformGamesFragment.java index 4957090ed3..c1d1b1c8e7 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/PlatformGamesFragment.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/PlatformGamesFragment.java @@ -1,12 +1,12 @@ package org.dolphinemu.dolphinemu.fragments; -import android.app.Activity; import android.app.Fragment; import android.app.LoaderManager; import android.content.Loader; import android.database.Cursor; import android.os.Bundle; import android.support.annotation.Nullable; +import android.support.v7.widget.DefaultItemAnimator; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.RecyclerView; import android.util.Log; @@ -57,6 +57,15 @@ public class PlatformGamesFragment extends Fragment RecyclerView.LayoutManager layoutManager = new GridLayoutManager(getActivity(), getResources().getInteger(R.integer.game_grid_columns)); recyclerView.setLayoutManager(layoutManager); + recyclerView.setItemAnimator(new DefaultItemAnimator() + { + @Override + public boolean animateChange(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder, int fromX, int fromY, int toX, int toY) + { + dispatchChangeFinished(newHolder, false); + return true; + } + }); recyclerView.addItemDecoration(new GameAdapter.SpacesItemDecoration(8)); @@ -70,10 +79,9 @@ public class PlatformGamesFragment extends Fragment return rootView; } - @Override - public void onAttach(Activity activity) + public void refreshScreenshotAtPosition(int position) { - super.onAttach(activity); + mAdapter.notifyItemChanged(position); } public void refresh() -- cgit v1.2.3 From 957691444d2c59939ecbf96b2ea0a52bccf720a9 Mon Sep 17 00:00:00 2001 From: sigmabeta Date: Thu, 2 Jul 2015 23:54:32 -0400 Subject: Android TV: Replace toolbar on EmulationActivity with a full-screen menu. --- .../dolphinemu/activities/EmulationActivity.java | 217 +++++++++++++++------ .../dolphinemu/fragments/EmulationFragment.java | 7 +- .../dolphinemu/fragments/MenuFragment.java | 38 ++++ 3 files changed, 196 insertions(+), 66 deletions(-) create mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/MenuFragment.java (limited to 'Source/Android/app/src/main/java') diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java index 6b27c08c4a..00501e10d6 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java @@ -15,6 +15,7 @@ import android.view.View; import android.view.ViewTreeObserver; import android.widget.FrameLayout; import android.widget.ImageView; +import android.widget.LinearLayout; import com.squareup.picasso.Callback; import com.squareup.picasso.Picasso; @@ -29,10 +30,13 @@ public final class EmulationActivity extends AppCompatActivity { private View mDecorView; private ImageView mImageView; + private FrameLayout mFrameEmulation; + private LinearLayout mMenuLayout; private boolean mDeviceHasTouchScreen; private boolean mSystemUiVisible; + private boolean mMenuVisible; // So that MainActivity knows which view to invalidate before the return animation. private int mPosition; @@ -56,49 +60,61 @@ public final class EmulationActivity extends AppCompatActivity @Override protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - // Picasso will take a while to load these big-ass screenshots. So don't run - // the animation until we say so. - postponeEnterTransition(); - mDeviceHasTouchScreen = getPackageManager().hasSystemFeature("android.hardware.touchscreen"); - // Get a handle to the Window containing the UI. - mDecorView = getWindow().getDecorView(); + int themeId; + if (mDeviceHasTouchScreen) + { + themeId = R.style.DolphinEmulationGamecube; - // Set these options now so that the SurfaceView the game renders into is the right size. - mDecorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | - View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | - View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN); + // Get a handle to the Window containing the UI. + mDecorView = getWindow().getDecorView(); - // Set the ActionBar to follow the navigation/status bar's visibility changes. - mDecorView.setOnSystemUiVisibilityChangeListener( - new View.OnSystemUiVisibilityChangeListener() - { - @Override - public void onSystemUiVisibilityChange(int flags) - { - mSystemUiVisible = (flags & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0; + // Set these options now so that the SurfaceView the game renders into is the right size. + mDecorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | + View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | + View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN); - if (mSystemUiVisible) - { - getSupportActionBar().show(); - hideSystemUiAfterDelay(); - } - else + // Set the ActionBar to follow the navigation/status bar's visibility changes. + mDecorView.setOnSystemUiVisibilityChangeListener( + new View.OnSystemUiVisibilityChangeListener() + { + @Override + public void onSystemUiVisibilityChange(int flags) { - getSupportActionBar().hide(); + mSystemUiVisible = (flags & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0; + + if (mSystemUiVisible) + { + getSupportActionBar().show(); + hideSystemUiAfterDelay(); + } + else + { + getSupportActionBar().hide(); + } } } - } - ); + ); + } + else + { + themeId = R.style.DolphinEmulationTvGamecube; + } + + setTheme(themeId); + super.onCreate(savedInstanceState); + + // Picasso will take a while to load these big-ass screenshots. So don't run + // the animation until we say so. + postponeEnterTransition(); setContentView(R.layout.activity_emulation); mImageView = (ImageView) findViewById(R.id.image_screenshot); mFrameContent = (FrameLayout) findViewById(R.id.frame_content); mFrameEmulation = (FrameLayout) findViewById(R.id.frame_emulation_fragment); + mMenuLayout = (LinearLayout) findViewById(R.id.layout_ingame_menu); Intent gameToEmulate = getIntent(); String path = gameToEmulate.getStringExtra("SelectedGame"); @@ -181,8 +197,11 @@ public final class EmulationActivity extends AppCompatActivity { super.onPostCreate(savedInstanceState); - // Give the user a few seconds to see what the controls look like, then hide them. - hideSystemUiAfterDelay(); + if (mDeviceHasTouchScreen) + { + // Give the user a few seconds to see what the controls look like, then hide them. + hideSystemUiAfterDelay(); + } } @Override @@ -190,36 +209,88 @@ public final class EmulationActivity extends AppCompatActivity { super.onWindowFocusChanged(hasFocus); - if (hasFocus) + if (mDeviceHasTouchScreen) { - hideSystemUiAfterDelay(); - } - else - { - // If the window loses focus (i.e. a dialog box, or a popup menu is on screen - // stop hiding the UI. - mSystemUiHider.removeMessages(0); + if (hasFocus) + { + hideSystemUiAfterDelay(); + } + else + { + // If the window loses focus (i.e. a dialog box, or a popup menu is on screen + // stop hiding the UI. + mSystemUiHider.removeMessages(0); + } } } @Override public void onBackPressed() { - if (!mDeviceHasTouchScreen && !mSystemUiVisible) + if (!mDeviceHasTouchScreen) { - showSystemUI(); + toggleMenu(); } else { - // Let the system handle it; i.e. quit the activity TODO or show "are you sure?" dialog. - EmulationFragment fragment = (EmulationFragment) getFragmentManager() - .findFragmentByTag(EmulationFragment.FRAGMENT_TAG); - fragment.notifyEmulationStopped(); + stopEmulation(); + } + } - NativeLibrary.StopEmulation(); + private void toggleMenu() + { + if (mMenuVisible) + { + mMenuLayout.animate() + .withLayer() + .setDuration(200) + .alpha(0.0f) + .scaleX(1.1f) + .scaleY(1.1f) + .withEndAction(new Runnable() + { + @Override + public void run() + { + mMenuLayout.setVisibility(View.GONE); + mMenuVisible = false; + } + }); + } + else + { + mMenuLayout.setVisibility(View.VISIBLE); + + mMenuLayout.setScaleX(1.1f); + mMenuLayout.setScaleY(1.1f); + mMenuLayout.setAlpha(0.0f); + + mMenuLayout.animate() + .withLayer() + .setDuration(300) + .alpha(1.0f) + .scaleX(1.0f) + .scaleY(1.0f) + .withEndAction(new Runnable() + { + @Override + public void run() + { + mMenuVisible = true; + } + }); } } + private void stopEmulation() + { + EmulationFragment fragment = (EmulationFragment) getFragmentManager() + .findFragmentByTag(EmulationFragment.FRAGMENT_TAG); + fragment.notifyEmulationStopped(); + + NativeLibrary.StopEmulation(); + } + public void exitWithAnimation() { runOnUiThread(new Runnable() @@ -257,7 +328,7 @@ public final class EmulationActivity extends AppCompatActivity mImageView.setVisibility(View.VISIBLE); mImageView.animate() .withLayer() - .setDuration(500) + .setDuration(100) .alpha(1.0f) .withEndAction(afterShowingScreenshot); } @@ -284,7 +355,13 @@ public final class EmulationActivity extends AppCompatActivity @Override public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) + onMenuItemClicked(item.getItemId()); + return true; + } + + public void onMenuItemClicked(int id) + { + switch (id) { // Enable/Disable input overlay. case R.id.menu_emulation_input_overlay: @@ -294,67 +371,69 @@ public final class EmulationActivity extends AppCompatActivity emulationFragment.toggleInputOverlayVisibility(); - return true; + return; } // Screenshot capturing case R.id.menu_emulation_screenshot: NativeLibrary.SaveScreenShot(); - return true; + return; // Quicksave / Load case R.id.menu_quicksave: NativeLibrary.SaveState(9); - return true; + return; case R.id.menu_quickload: NativeLibrary.LoadState(9); - return true; + return; // Save state slots case R.id.menu_emulation_save_1: NativeLibrary.SaveState(0); - return true; + return; case R.id.menu_emulation_save_2: NativeLibrary.SaveState(1); - return true; + return; case R.id.menu_emulation_save_3: NativeLibrary.SaveState(2); - return true; + return; case R.id.menu_emulation_save_4: NativeLibrary.SaveState(3); - return true; + return; case R.id.menu_emulation_save_5: NativeLibrary.SaveState(4); - return true; + return; // Load state slots case R.id.menu_emulation_load_1: NativeLibrary.LoadState(0); - return true; + return; case R.id.menu_emulation_load_2: NativeLibrary.LoadState(1); - return true; + return; case R.id.menu_emulation_load_3: NativeLibrary.LoadState(2); - return true; + return; case R.id.menu_emulation_load_4: NativeLibrary.LoadState(3); - return true; + return; case R.id.menu_emulation_load_5: NativeLibrary.LoadState(4); - return true; + return; - default: - return super.onOptionsItemSelected(item); + case R.id.menu_exit: + toggleMenu(); + stopEmulation(); + return; } } @@ -362,6 +441,11 @@ public final class EmulationActivity extends AppCompatActivity @Override public boolean dispatchKeyEvent(KeyEvent event) { + if (mMenuVisible) + { + return super.dispatchKeyEvent(event); + } + int action = 0; switch (event.getAction()) @@ -391,6 +475,11 @@ public final class EmulationActivity extends AppCompatActivity @Override public boolean dispatchGenericMotionEvent(MotionEvent event) { + if (mMenuVisible) + { + return false; + } + if (((event.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) == 0)) { return super.dispatchGenericMotionEvent(event); diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.java index 9d23736cb6..1eb1684531 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.java @@ -81,9 +81,12 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C mSurfaceView.getHolder().addCallback(this); // If the input overlay was previously disabled, then don't show it. - if (!mPreferences.getBoolean("showInputOverlay", true)) + if (mInputOverlay != null) { - mInputOverlay.setVisibility(View.GONE); + if (!mPreferences.getBoolean("showInputOverlay", true)) + { + mInputOverlay.setVisibility(View.GONE); + } } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/MenuFragment.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/MenuFragment.java new file mode 100644 index 0000000000..f57ca36ede --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/MenuFragment.java @@ -0,0 +1,38 @@ +package org.dolphinemu.dolphinemu.fragments; + +import android.app.Fragment; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.LinearLayout; + +import org.dolphinemu.dolphinemu.R; +import org.dolphinemu.dolphinemu.activities.EmulationActivity; + +public final class MenuFragment extends Fragment implements View.OnClickListener +{ + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) + { + LinearLayout rootView = (LinearLayout) inflater.inflate(R.layout.fragment_ingame_menu, container, false); + + for (int childIndex = 0; childIndex < rootView.getChildCount(); childIndex++) + { + Button button = (Button) rootView.getChildAt(childIndex); + + button.setOnClickListener(this); + } + + return rootView; + } + + @Override + public void onClick(View button) + { + ((EmulationActivity) getActivity()).onMenuItemClicked(button.getId()); + } +} -- cgit v1.2.3 From d191d8851a3bc4455c12b5f13f0c87891004fa55 Mon Sep 17 00:00:00 2001 From: sigmabeta Date: Fri, 3 Jul 2015 16:38:23 -0400 Subject: Android TV: Visual tweaks & glitch fixes --- .../dolphinemu/activities/EmulationActivity.java | 34 ++++++++++++---------- 1 file changed, 18 insertions(+), 16 deletions(-) (limited to 'Source/Android/app/src/main/java') diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java index 00501e10d6..e2804de9c9 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java @@ -13,6 +13,9 @@ import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; import android.view.ViewTreeObserver; +import android.view.animation.AccelerateInterpolator; +import android.view.animation.DecelerateInterpolator; +import android.view.animation.Interpolator; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; @@ -41,6 +44,9 @@ public final class EmulationActivity extends AppCompatActivity // So that MainActivity knows which view to invalidate before the return animation. private int mPosition; + private static Interpolator sDecelerator = new DecelerateInterpolator(); + private static Interpolator sAccelerator = new AccelerateInterpolator(); + /** * Handlers are a way to pass a message to an Activity telling it to do something * on the UI thread. This Handler responds to any message, even blank ones, by @@ -241,44 +247,40 @@ public final class EmulationActivity extends AppCompatActivity { if (mMenuVisible) { + mMenuVisible = false; + mMenuLayout.animate() .withLayer() .setDuration(200) + .setInterpolator(sAccelerator) .alpha(0.0f) - .scaleX(1.1f) - .scaleY(1.1f) + .translationX(-400.0f) .withEndAction(new Runnable() { @Override public void run() { - mMenuLayout.setVisibility(View.GONE); - mMenuVisible = false; + if (mMenuVisible) + { + mMenuLayout.setVisibility(View.GONE); + } } }); } else { + mMenuVisible = true; mMenuLayout.setVisibility(View.VISIBLE); - mMenuLayout.setScaleX(1.1f); - mMenuLayout.setScaleY(1.1f); +// mMenuLayout.setTranslationX(-400.0f); mMenuLayout.setAlpha(0.0f); mMenuLayout.animate() .withLayer() .setDuration(300) + .setInterpolator(sDecelerator) .alpha(1.0f) - .scaleX(1.0f) - .scaleY(1.0f) - .withEndAction(new Runnable() - { - @Override - public void run() - { - mMenuVisible = true; - } - }); + .translationX(0.0f); } } -- cgit v1.2.3 From c0315fcf78dc966618b8ead1617571436957aba4 Mon Sep 17 00:00:00 2001 From: sigmabeta Date: Sat, 4 Jul 2015 16:32:15 -0400 Subject: Android TV: Implement Save and Load state menus --- .../dolphinemu/activities/EmulationActivity.java | 98 +++++++++++++++++++++- .../dolphinemu/fragments/LoadStateFragment.java | 55 ++++++++++++ .../dolphinemu/fragments/MenuFragment.java | 6 +- .../dolphinemu/fragments/SaveStateFragment.java | 55 ++++++++++++ 4 files changed, 209 insertions(+), 5 deletions(-) create mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/LoadStateFragment.java create mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/SaveStateFragment.java (limited to 'Source/Android/app/src/main/java') diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java index e2804de9c9..f7608506ed 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java @@ -1,5 +1,6 @@ package org.dolphinemu.dolphinemu.activities; +import android.app.Fragment; import android.content.Intent; import android.os.Bundle; import android.os.Handler; @@ -26,6 +27,8 @@ import com.squareup.picasso.Picasso; import org.dolphinemu.dolphinemu.NativeLibrary; import org.dolphinemu.dolphinemu.R; import org.dolphinemu.dolphinemu.fragments.EmulationFragment; +import org.dolphinemu.dolphinemu.fragments.LoadStateFragment; +import org.dolphinemu.dolphinemu.fragments.SaveStateFragment; import java.util.List; @@ -37,13 +40,15 @@ public final class EmulationActivity extends AppCompatActivity private FrameLayout mFrameEmulation; private LinearLayout mMenuLayout; - private boolean mDeviceHasTouchScreen; - private boolean mSystemUiVisible; - private boolean mMenuVisible; + private String mMenuFragmentTag; // So that MainActivity knows which view to invalidate before the return animation. private int mPosition; + private boolean mDeviceHasTouchScreen; + private boolean mSystemUiVisible; + private boolean mMenuVisible; + private static Interpolator sDecelerator = new DecelerateInterpolator(); private static Interpolator sAccelerator = new AccelerateInterpolator(); @@ -235,7 +240,14 @@ public final class EmulationActivity extends AppCompatActivity { if (!mDeviceHasTouchScreen) { - toggleMenu(); + if (mMenuFragmentTag != null) + { + removeMenu(); + } + else + { + toggleMenu(); + } } else { @@ -390,6 +402,15 @@ public final class EmulationActivity extends AppCompatActivity NativeLibrary.LoadState(9); return; + // TV Menu only + case R.id.menu_emulation_save_root: + showMenu(SaveStateFragment.FRAGMENT_ID); + return; + + case R.id.menu_emulation_load_root: + showMenu(LoadStateFragment.FRAGMENT_ID); + return; + // Save state slots case R.id.menu_emulation_save_1: NativeLibrary.SaveState(0); @@ -549,4 +570,73 @@ public final class EmulationActivity extends AppCompatActivity } }); } + + private void showMenu(int menuId) + { + Fragment fragment; + + switch (menuId) + { + case SaveStateFragment.FRAGMENT_ID: + fragment = SaveStateFragment.newInstance(); + mMenuFragmentTag = SaveStateFragment.FRAGMENT_TAG; + break; + + case LoadStateFragment.FRAGMENT_ID: + fragment = LoadStateFragment.newInstance(); + mMenuFragmentTag = LoadStateFragment.FRAGMENT_TAG; + break; + + default: + return; + } + + getFragmentManager().beginTransaction() + .setCustomAnimations(R.animator.menu_slide_in, R.animator.menu_slide_out) + .replace(R.id.frame_submenu, fragment, mMenuFragmentTag) + .commit(); + } + + private void removeMenu() + { + if (mMenuFragmentTag != null) + { + final Fragment fragment = getFragmentManager().findFragmentByTag(mMenuFragmentTag); + + if (fragment != null) + { + // When removing a fragment without replacement, its aniimation must be done + // manually beforehand. + fragment.getView().animate() + .withLayer() + .setDuration(200) + .setInterpolator(sAccelerator) + .alpha(0.0f) + .translationX(600.0f) + .withEndAction(new Runnable() + { + @Override + public void run() + { + if (mMenuVisible) + { + getFragmentManager().beginTransaction() + .remove(fragment) + .commit(); + } + } + }); + } + else + { + Log.e("DolphinEmu", "[EmulationActivity] Fragment not found, can't remove."); + } + + mMenuFragmentTag = null; + } + else + { + Log.e("DolphinEmu", "[EmulationActivity] Fragment Tag empty."); + } + } } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/LoadStateFragment.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/LoadStateFragment.java new file mode 100644 index 0000000000..bbd9807b9b --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/LoadStateFragment.java @@ -0,0 +1,55 @@ +package org.dolphinemu.dolphinemu.fragments; + +import android.app.Fragment; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.GridLayout; + +import org.dolphinemu.dolphinemu.BuildConfig; +import org.dolphinemu.dolphinemu.R; +import org.dolphinemu.dolphinemu.activities.EmulationActivity; + +public final class LoadStateFragment extends Fragment implements View.OnClickListener +{ + public static final String FRAGMENT_TAG = BuildConfig.APPLICATION_ID + ".load_state"; + public static final int FRAGMENT_ID = R.layout.fragment_state_load; + + public static LoadStateFragment newInstance() + { + LoadStateFragment fragment = new LoadStateFragment(); + + // TODO Add any appropriate arguments to this fragment. + + return fragment; + } + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) + { + View rootView = inflater.inflate(FRAGMENT_ID, container, false); + + GridLayout grid = (GridLayout) rootView.findViewById(R.id.grid_state_slots); + for (int childIndex = 0; childIndex < grid.getChildCount(); childIndex++) + { + Button button = (Button) grid.getChildAt(childIndex); + + button.setOnClickListener(this); + } + + // So that item clicked to start this Fragment is no longer the focused item. + grid.requestFocus(); + + return rootView; + } + + @Override + public void onClick(View button) + { + ((EmulationActivity) getActivity()).onMenuItemClicked(button.getId()); + } +} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/MenuFragment.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/MenuFragment.java index f57ca36ede..5c847ee1b1 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/MenuFragment.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/MenuFragment.java @@ -9,16 +9,20 @@ import android.view.ViewGroup; import android.widget.Button; import android.widget.LinearLayout; +import org.dolphinemu.dolphinemu.BuildConfig; import org.dolphinemu.dolphinemu.R; import org.dolphinemu.dolphinemu.activities.EmulationActivity; public final class MenuFragment extends Fragment implements View.OnClickListener { + public static final String FRAGMENT_TAG = BuildConfig.APPLICATION_ID + ".ingame_menu"; + public static final int FRAGMENT_ID = R.layout.fragment_ingame_menu; + @Nullable @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - LinearLayout rootView = (LinearLayout) inflater.inflate(R.layout.fragment_ingame_menu, container, false); + LinearLayout rootView = (LinearLayout) inflater.inflate(FRAGMENT_ID, container, false); for (int childIndex = 0; childIndex < rootView.getChildCount(); childIndex++) { diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/SaveStateFragment.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/SaveStateFragment.java new file mode 100644 index 0000000000..a5e9e6d441 --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/SaveStateFragment.java @@ -0,0 +1,55 @@ +package org.dolphinemu.dolphinemu.fragments; + +import android.app.Fragment; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.GridLayout; + +import org.dolphinemu.dolphinemu.BuildConfig; +import org.dolphinemu.dolphinemu.R; +import org.dolphinemu.dolphinemu.activities.EmulationActivity; + +public final class SaveStateFragment extends Fragment implements View.OnClickListener +{ + public static final String FRAGMENT_TAG = BuildConfig.APPLICATION_ID + ".save_state"; + public static final int FRAGMENT_ID = R.layout.fragment_state_save; + + public static SaveStateFragment newInstance() + { + SaveStateFragment fragment = new SaveStateFragment(); + + // TODO Add any appropriate arguments to this fragment. + + return fragment; + } + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) + { + View rootView = inflater.inflate(FRAGMENT_ID, container, false); + + GridLayout grid = (GridLayout) rootView.findViewById(R.id.grid_state_slots); + for (int childIndex = 0; childIndex < grid.getChildCount(); childIndex++) + { + Button button = (Button) grid.getChildAt(childIndex); + + button.setOnClickListener(this); + } + + // So that item clicked to start this Fragment is no longer the focused item. + grid.requestFocus(); + + return rootView; + } + + @Override + public void onClick(View button) + { + ((EmulationActivity) getActivity()).onMenuItemClicked(button.getId()); + } +} -- cgit v1.2.3 From 12fd46e12d1e4d6fdc54c20923454f2f17f058bb Mon Sep 17 00:00:00 2001 From: sigmabeta Date: Sun, 5 Jul 2015 00:11:25 -0400 Subject: Android TV: Add title text to in-game menu, and make the menu scrollable. --- .../dolphinemu/activities/EmulationActivity.java | 42 ++++++++++++++++------ .../dolphinemu/fragments/MenuFragment.java | 16 +++++++-- 2 files changed, 44 insertions(+), 14 deletions(-) (limited to 'Source/Android/app/src/main/java') diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java index f7608506ed..c4cc9e1f3a 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java @@ -28,6 +28,7 @@ import org.dolphinemu.dolphinemu.NativeLibrary; import org.dolphinemu.dolphinemu.R; import org.dolphinemu.dolphinemu.fragments.EmulationFragment; import org.dolphinemu.dolphinemu.fragments.LoadStateFragment; +import org.dolphinemu.dolphinemu.fragments.MenuFragment; import org.dolphinemu.dolphinemu.fragments.SaveStateFragment; import java.util.List; @@ -40,7 +41,7 @@ public final class EmulationActivity extends AppCompatActivity private FrameLayout mFrameEmulation; private LinearLayout mMenuLayout; - private String mMenuFragmentTag; + private String mSubmenuFragmentTag; // So that MainActivity knows which view to invalidate before the return animation. private int mPosition; @@ -67,6 +68,7 @@ public final class EmulationActivity extends AppCompatActivity }; private String mScreenPath; private FrameLayout mFrameContent; + private String mSelectedTitle; @Override protected void onCreate(Bundle savedInstanceState) @@ -129,7 +131,7 @@ public final class EmulationActivity extends AppCompatActivity Intent gameToEmulate = getIntent(); String path = gameToEmulate.getStringExtra("SelectedGame"); - String title = gameToEmulate.getStringExtra("SelectedTitle"); + mSelectedTitle = gameToEmulate.getStringExtra("SelectedTitle"); mScreenPath = gameToEmulate.getStringExtra("ScreenPath"); mPosition = gameToEmulate.getIntExtra("GridPosition", -1); @@ -175,8 +177,6 @@ public final class EmulationActivity extends AppCompatActivity } }); - setTitle(title); - // Instantiate an EmulationFragment. EmulationFragment emulationFragment = EmulationFragment.newInstance(path); @@ -184,6 +184,21 @@ public final class EmulationActivity extends AppCompatActivity getFragmentManager().beginTransaction() .add(R.id.frame_emulation_fragment, emulationFragment, EmulationFragment.FRAGMENT_TAG) .commit(); + + if (mDeviceHasTouchScreen) + { + setTitle(mSelectedTitle); + } + else + { + MenuFragment menuFragment = (MenuFragment) getFragmentManager() + .findFragmentById(R.id.fragment_menu); + + if (menuFragment != null) + { + menuFragment.setTitleText(mSelectedTitle); + } + } } @Override @@ -240,7 +255,7 @@ public final class EmulationActivity extends AppCompatActivity { if (!mDeviceHasTouchScreen) { - if (mMenuFragmentTag != null) + if (mSubmenuFragmentTag != null) { removeMenu(); } @@ -579,12 +594,12 @@ public final class EmulationActivity extends AppCompatActivity { case SaveStateFragment.FRAGMENT_ID: fragment = SaveStateFragment.newInstance(); - mMenuFragmentTag = SaveStateFragment.FRAGMENT_TAG; + mSubmenuFragmentTag = SaveStateFragment.FRAGMENT_TAG; break; case LoadStateFragment.FRAGMENT_ID: fragment = LoadStateFragment.newInstance(); - mMenuFragmentTag = LoadStateFragment.FRAGMENT_TAG; + mSubmenuFragmentTag = LoadStateFragment.FRAGMENT_TAG; break; default: @@ -593,15 +608,15 @@ public final class EmulationActivity extends AppCompatActivity getFragmentManager().beginTransaction() .setCustomAnimations(R.animator.menu_slide_in, R.animator.menu_slide_out) - .replace(R.id.frame_submenu, fragment, mMenuFragmentTag) + .replace(R.id.frame_submenu, fragment, mSubmenuFragmentTag) .commit(); } private void removeMenu() { - if (mMenuFragmentTag != null) + if (mSubmenuFragmentTag != null) { - final Fragment fragment = getFragmentManager().findFragmentByTag(mMenuFragmentTag); + final Fragment fragment = getFragmentManager().findFragmentByTag(mSubmenuFragmentTag); if (fragment != null) { @@ -632,11 +647,16 @@ public final class EmulationActivity extends AppCompatActivity Log.e("DolphinEmu", "[EmulationActivity] Fragment not found, can't remove."); } - mMenuFragmentTag = null; + mSubmenuFragmentTag = null; } else { Log.e("DolphinEmu", "[EmulationActivity] Fragment Tag empty."); } } + + public String getSelectedTitle() + { + return mSelectedTitle; + } } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/MenuFragment.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/MenuFragment.java index 5c847ee1b1..d894f32373 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/MenuFragment.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/MenuFragment.java @@ -8,6 +8,7 @@ import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.LinearLayout; +import android.widget.TextView; import org.dolphinemu.dolphinemu.BuildConfig; import org.dolphinemu.dolphinemu.R; @@ -17,20 +18,24 @@ public final class MenuFragment extends Fragment implements View.OnClickListener { public static final String FRAGMENT_TAG = BuildConfig.APPLICATION_ID + ".ingame_menu"; public static final int FRAGMENT_ID = R.layout.fragment_ingame_menu; + private TextView mTitleText; @Nullable @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - LinearLayout rootView = (LinearLayout) inflater.inflate(FRAGMENT_ID, container, false); + View rootView = inflater.inflate(FRAGMENT_ID, container, false); - for (int childIndex = 0; childIndex < rootView.getChildCount(); childIndex++) + LinearLayout options = (LinearLayout) rootView.findViewById(R.id.layout_options); + for (int childIndex = 0; childIndex < options.getChildCount(); childIndex++) { - Button button = (Button) rootView.getChildAt(childIndex); + Button button = (Button) options.getChildAt(childIndex); button.setOnClickListener(this); } + mTitleText = (TextView) rootView.findViewById(R.id.text_game_title); + return rootView; } @@ -39,4 +44,9 @@ public final class MenuFragment extends Fragment implements View.OnClickListener { ((EmulationActivity) getActivity()).onMenuItemClicked(button.getId()); } + + public void setTitleText(String title) + { + mTitleText.setText(title); + } } -- cgit v1.2.3 From a8227ad9b1430d8891f1c6221374dadd94a3a534 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Tue, 21 Jul 2015 21:28:32 -0500 Subject: Add Wiimote support to the Android backend. Not actually wired up to the Android UI for configuration. --- .../org/dolphinemu/dolphinemu/NativeLibrary.java | 55 +++++++++++++--------- .../dolphinemu/services/AssetCopyService.java | 1 + 2 files changed, 34 insertions(+), 22 deletions(-) (limited to 'Source/Android/app/src/main/java') diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java index 9fcdbe8cd1..db387344bd 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java @@ -25,28 +25,39 @@ public final class NativeLibrary */ public static final class ButtonType { - public static final int BUTTON_A = 0; - public static final int BUTTON_B = 1; - public static final int BUTTON_START = 2; - public static final int BUTTON_X = 3; - public static final int BUTTON_Y = 4; - public static final int BUTTON_Z = 5; - public static final int BUTTON_UP = 6; - public static final int BUTTON_DOWN = 7; - public static final int BUTTON_LEFT = 8; - public static final int BUTTON_RIGHT = 9; - public static final int STICK_MAIN = 10; - public static final int STICK_MAIN_UP = 11; - public static final int STICK_MAIN_DOWN = 12; - public static final int STICK_MAIN_LEFT = 13; - public static final int STICK_MAIN_RIGHT = 14; - public static final int STICK_C = 15; - public static final int STICK_C_UP = 16; - public static final int STICK_C_DOWN = 17; - public static final int STICK_C_LEFT = 18; - public static final int STICK_C_RIGHT = 19; - public static final int TRIGGER_L = 20; - public static final int TRIGGER_R = 21; + public static final int BUTTON_A = 0; + public static final int BUTTON_B = 1; + public static final int BUTTON_START = 2; + public static final int BUTTON_X = 3; + public static final int BUTTON_Y = 4; + public static final int BUTTON_Z = 5; + public static final int BUTTON_UP = 6; + public static final int BUTTON_DOWN = 7; + public static final int BUTTON_LEFT = 8; + public static final int BUTTON_RIGHT = 9; + public static final int STICK_MAIN = 10; + public static final int STICK_MAIN_UP = 11; + public static final int STICK_MAIN_DOWN = 12; + public static final int STICK_MAIN_LEFT = 13; + public static final int STICK_MAIN_RIGHT = 14; + public static final int STICK_C = 15; + public static final int STICK_C_UP = 16; + public static final int STICK_C_DOWN = 17; + public static final int STICK_C_LEFT = 18; + public static final int STICK_C_RIGHT = 19; + public static final int TRIGGER_L = 20; + public static final int TRIGGER_R = 21; + public static final int WIIMOTE_BUTTON_A = 22; + public static final int WIIMOTE_BUTTON_B = 23; + public static final int WIIMOTE_BUTTON_MINUS = 24; + public static final int WIIMOTE_BUTTON_PLUS = 25; + public static final int WIIMOTE_BUTTON_HOME = 26; + public static final int WIIMOTE_BUTTON_1 = 27; + public static final int WIIMOTE_BUTTON_2 = 28; + public static final int WIIMOTE_UP = 29; + public static final int WIIMOTE_DOWN = 30; + public static final int WIIMOTE_LEFT = 31; + public static final int WIIMOTE_RIGHT = 32; } /** diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/services/AssetCopyService.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/services/AssetCopyService.java index 1f6f94bc8a..558a34be37 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/services/AssetCopyService.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/services/AssetCopyService.java @@ -61,6 +61,7 @@ public final class AssetCopyService extends IntentService // Always copy over the GCPad config in case of change or corruption. // Not a user configurable file. copyAsset("GCPadNew.ini", ConfigDir + File.separator + "GCPadNew.ini"); + copyAsset("WiimoteNew.ini", ConfigDir + File.separator + "WiimoteNew.ini"); // Load the configuration keys set in the Dolphin ini and gfx ini files // into the application's shared preferences. -- cgit v1.2.3 From 7c14996e3e24b0a4a1064ece1c656bcbe6c923c7 Mon Sep 17 00:00:00 2001 From: sigmabeta Date: Tue, 14 Jul 2015 22:35:52 -0400 Subject: Android TV: Implement game selector activity in new Android TV UI --- .../dolphinemu/activities/MainActivity.java | 2 +- .../dolphinemu/activities/TvMainActivity.java | 141 +++++++++++++++++++++ .../dolphinemu/adapters/GamePresenter.java | 122 ++++++++++++++++++ .../java/org/dolphinemu/dolphinemu/model/Game.java | 33 +---- .../dolphinemu/viewholders/TvGameViewHolder.java | 40 ++++++ 5 files changed, 311 insertions(+), 27 deletions(-) create mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/TvMainActivity.java create mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GamePresenter.java create mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/viewholders/TvGameViewHolder.java (limited to 'Source/Android/app/src/main/java') diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/MainActivity.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/MainActivity.java index 33cd0b0c15..a32b65d566 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/MainActivity.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/MainActivity.java @@ -226,7 +226,7 @@ public final class MainActivity extends AppCompatActivity implements LoaderManag GameProvider.URI_GAME, // URI of table to query null, // Return all columns GameDatabase.KEY_GAME_PLATFORM + " = ?", // Select by platform - new String[]{Integer.toString(id)}, // Platform id is Loader id minus 1 + new String[]{Integer.toString(id)}, // Platform id is Loader id GameDatabase.KEY_GAME_TITLE + " asc" // Sort by game name, ascending order ); diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/TvMainActivity.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/TvMainActivity.java new file mode 100644 index 0000000000..2c191bdaf0 --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/TvMainActivity.java @@ -0,0 +1,141 @@ +package org.dolphinemu.dolphinemu.activities; + +import android.app.Activity; +import android.app.ActivityOptions; +import android.app.FragmentManager; +import android.content.Intent; +import android.database.Cursor; +import android.os.Bundle; +import android.support.v17.leanback.app.BrowseFragment; +import android.support.v17.leanback.database.CursorMapper; +import android.support.v17.leanback.widget.ArrayObjectAdapter; +import android.support.v17.leanback.widget.CursorObjectAdapter; +import android.support.v17.leanback.widget.HeaderItem; +import android.support.v17.leanback.widget.ListRow; +import android.support.v17.leanback.widget.ListRowPresenter; +import android.support.v17.leanback.widget.OnItemViewClickedListener; +import android.support.v17.leanback.widget.Presenter; +import android.support.v17.leanback.widget.Row; +import android.support.v17.leanback.widget.RowPresenter; + +import org.dolphinemu.dolphinemu.R; +import org.dolphinemu.dolphinemu.adapters.GamePresenter; +import org.dolphinemu.dolphinemu.model.Game; +import org.dolphinemu.dolphinemu.model.GameDatabase; +import org.dolphinemu.dolphinemu.model.GameProvider; +import org.dolphinemu.dolphinemu.viewholders.TvGameViewHolder; + +public final class TvMainActivity extends Activity +{ + protected BrowseFragment mBrowseFragment; + + private ArrayObjectAdapter mRowsAdapter; + + @Override + protected void onCreate(Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_tv_main); + + final FragmentManager fragmentManager = getFragmentManager(); + mBrowseFragment = (BrowseFragment) fragmentManager.findFragmentById( + R.id.fragment_game_list); + + // Set display parameters for the BrowseFragment + mBrowseFragment.setHeadersState(BrowseFragment.HEADERS_ENABLED); + mBrowseFragment.setTitle(getString(R.string.app_name)); + mBrowseFragment.setBadgeDrawable(getResources().getDrawable( + R.drawable.ic_launcher, null)); + mBrowseFragment.setBrandColor(getResources().getColor(R.color.dolphin_blue_dark)); + + buildRowsAdapter(); + + mBrowseFragment.setOnItemViewClickedListener( + new OnItemViewClickedListener() + { + @Override + public void onItemClicked(Presenter.ViewHolder itemViewHolder, Object item, RowPresenter.ViewHolder rowViewHolder, Row row) + { + TvGameViewHolder holder = (TvGameViewHolder) itemViewHolder; + // Start the emulation activity and send the path of the clicked ISO to it. + Intent intent = new Intent(TvMainActivity.this, EmulationActivity.class); + + intent.putExtra("SelectedGame", holder.path); + intent.putExtra("SelectedTitle", holder.title); + intent.putExtra("ScreenPath", holder.screenshotPath); + + ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation( + TvMainActivity.this, + holder.imageScreenshot, + "image_game_screenshot"); + + startActivity(intent, options.toBundle()); + } + }); + } + + private void buildRowsAdapter() + { + mRowsAdapter = new ArrayObjectAdapter(new ListRowPresenter()); + + // For each row + for (int platformIndex = 0; platformIndex <= Game.PLATFORM_WII_WARE; ++platformIndex) + { + // Create an adapter for this row. + CursorObjectAdapter row = new CursorObjectAdapter(new GamePresenter(platformIndex)); + + // Add items to the adapter. + Cursor games = getContentResolver().query( + GameProvider.URI_GAME, // URI of table to query + null, // Return all columns + GameDatabase.KEY_GAME_PLATFORM + " = ?", // Select by platform + new String[]{Integer.toString(platformIndex)}, // Platform id + GameDatabase.KEY_GAME_TITLE + " asc" // Sort by game name, ascending order + ); + + row.swapCursor(games); + row.setMapper(new CursorMapper() + { + @Override + protected void bindColumns(Cursor cursor) + { + // No-op? Not sure what this does. + } + + @Override + protected Object bind(Cursor cursor) + { + return Game.fromCursor(cursor); + } + }); + + String headerName; + switch (platformIndex) + { + case Game.PLATFORM_GC: + headerName = "GameCube Games"; + break; + + case Game.PLATFORM_WII: + headerName = "Wii Games"; + break; + + case Game.PLATFORM_WII_WARE: + headerName = "WiiWare"; + break; + + default: + headerName = "Error"; + break; + } + + // Create a header for this row. + HeaderItem header = new HeaderItem(platformIndex, headerName); + + // Create the row, passing it the filled adapter and the header, and give it to the master adapter. + mRowsAdapter.add(new ListRow(header, row)); + } + + mBrowseFragment.setAdapter(mRowsAdapter); + } +} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GamePresenter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GamePresenter.java new file mode 100644 index 0000000000..d9b4487278 --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GamePresenter.java @@ -0,0 +1,122 @@ +package org.dolphinemu.dolphinemu.adapters; + +import android.graphics.Bitmap; +import android.support.v17.leanback.widget.ImageCardView; +import android.support.v17.leanback.widget.Presenter; +import android.view.ViewGroup; +import android.widget.ImageView; + +import com.squareup.picasso.Picasso; + +import org.dolphinemu.dolphinemu.R; +import org.dolphinemu.dolphinemu.model.Game; +import org.dolphinemu.dolphinemu.viewholders.TvGameViewHolder; + +/** + * The Leanback library / docs call this a Presenter, but it works very + * similarly to a RecyclerView.ViewHolder. + */ +public final class GamePresenter extends Presenter +{ + private int mPlatform; + + public GamePresenter(int platform) + { + mPlatform = platform; + } + + public ViewHolder onCreateViewHolder(ViewGroup parent) + { + // Create a new view. + ImageCardView gameCard = new ImageCardView(parent.getContext()) + { + @Override + public void setSelected(boolean selected) + { + setCardBackground(this, selected); + super.setSelected(selected); + } + }; + + gameCard.setMainImageAdjustViewBounds(true); + gameCard.setMainImageDimensions(480, 320); + gameCard.setMainImageScaleType(ImageView.ScaleType.CENTER_CROP); + + gameCard.setFocusable(true); + gameCard.setFocusableInTouchMode(true); + + setCardBackground(gameCard, false); + + // Use that view to create a ViewHolder. + return new TvGameViewHolder(gameCard); + } + + public void onBindViewHolder(ViewHolder viewHolder, Object item) + { + TvGameViewHolder holder = (TvGameViewHolder) viewHolder; + Game game = (Game) item; + + String screenPath = game.getScreenshotPath(); + + // Fill in the view contents. + Picasso.with(holder.imageScreenshot.getContext()) + .load(screenPath) + .fit() + .centerCrop() + .noFade() + .noPlaceholder() + .config(Bitmap.Config.RGB_565) + .error(R.drawable.no_banner) + .into(holder.imageScreenshot); + + holder.cardParent.setTitleText(game.getTitle()); + holder.cardParent.setContentText(game.getCompany()); + + // TODO These shouldn't be necessary once the move to a DB-based model is complete. + holder.gameId = game.getGameId(); + holder.path = game.getPath(); + holder.title = game.getTitle(); + holder.description = game.getDescription(); + holder.country = game.getCountry(); + holder.company = game.getCompany(); + holder.screenshotPath = game.getScreenshotPath(); + } + + public void onUnbindViewHolder(ViewHolder viewHolder) + { + // no op + } + + public void setCardBackground(ImageCardView view, boolean selected) + { + int backgroundColor; + + if (selected) + { + switch (mPlatform) + { + case Game.PLATFORM_GC: + backgroundColor = R.color.dolphin_accent_gamecube; + break; + + case Game.PLATFORM_WII: + backgroundColor = R.color.dolphin_accent_wii; + break; + + case Game.PLATFORM_WII_WARE: + backgroundColor = R.color.dolphin_accent_wiiware; + break; + + default: + backgroundColor = android.R.color.holo_red_dark; + break; + } + } + else + { + backgroundColor = R.color.tv_card_unselected; + } + + view.setInfoAreaBackgroundColor(view.getResources().getColor(backgroundColor)); + } +} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/Game.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/Game.java index f3ef6f7514..2068f01f08 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/Game.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/Game.java @@ -3,8 +3,6 @@ package org.dolphinemu.dolphinemu.model; import android.content.ContentValues; import android.database.Cursor; -import java.io.File; - public final class Game { public static final int PLATFORM_GC = 0; @@ -33,13 +31,13 @@ public final class Game private String mDescription; private String mPath; private String mGameId; - private String mScreenshotFolderPath; + private String mScreenshotPath; private String mCompany; private int mPlatform; private int mCountry; - public Game(int platform, String title, String description, int country, String path, String gameId, String company) + public Game(int platform, String title, String description, int country, String path, String gameId, String company, String screenshotPath) { mPlatform = platform; mTitle = title; @@ -48,7 +46,7 @@ public final class Game mPath = path; mGameId = gameId; mCompany = company; - mScreenshotFolderPath = PATH_SCREENSHOT_FOLDER + getGameId() + "/"; + mScreenshotPath = screenshotPath; } public int getPlatform() @@ -86,27 +84,9 @@ public final class Game return mGameId; } - public String getScreenshotFolderPath() - { - return mScreenshotFolderPath; - } - - public String getScreenPath() + public String getScreenshotPath() { - // Count how many screenshots are available, so we can use the most recent one. - File screenshotFolder = new File(mScreenshotFolderPath.substring(mScreenshotFolderPath.indexOf('s') - 1)); - int screenCount = 0; - - if (screenshotFolder.isDirectory()) - { - screenCount = screenshotFolder.list().length; - } - - String screenPath = mScreenshotFolderPath - + getGameId() + "-" - + screenCount + ".png"; - - return screenPath; + return mScreenshotPath; } public static ContentValues asContentValues(int platform, String title, String description, int country, String path, String gameId, String company) @@ -135,6 +115,7 @@ public final class Game cursor.getInt(GameDatabase.GAME_COLUMN_COUNTRY), cursor.getString(GameDatabase.GAME_COLUMN_PATH), cursor.getString(GameDatabase.GAME_COLUMN_GAME_ID), - cursor.getString(GameDatabase.GAME_COLUMN_COMPANY)); + cursor.getString(GameDatabase.GAME_COLUMN_COMPANY), + cursor.getString(GameDatabase.GAME_COLUMN_SCREENSHOT_PATH)); } } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/viewholders/TvGameViewHolder.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/viewholders/TvGameViewHolder.java new file mode 100644 index 0000000000..dd996ccbe7 --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/viewholders/TvGameViewHolder.java @@ -0,0 +1,40 @@ +package org.dolphinemu.dolphinemu.viewholders; + +import android.support.v17.leanback.widget.ImageCardView; +import android.support.v17.leanback.widget.Presenter; +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; + +/** + * A simple class that stores references to views so that the GameAdapter doesn't need to + * keep calling findViewById(), which is expensive. + */ +public class TvGameViewHolder extends Presenter.ViewHolder +{ + public ImageCardView cardParent; + + public ImageView imageScreenshot; + public TextView textGameTitle; + public TextView textCompany; + + public String gameId; + + // TODO Not need any of this stuff. Currently only the properties dialog needs it. + public String path; + public String title; + public String description; + public int country; + public String company; + public String screenshotPath; + + public TvGameViewHolder(View itemView) + { + super(itemView); + + itemView.setTag(this); + + cardParent = (ImageCardView) itemView; + imageScreenshot = cardParent.getMainImageView(); + } +} -- cgit v1.2.3 From 0b1212b77db43376012756c4219156708316810e Mon Sep 17 00:00:00 2001 From: sigmabeta Date: Mon, 20 Jul 2015 20:15:26 -0400 Subject: Android TV: Add row listing all games --- .../dolphinemu/activities/TvMainActivity.java | 123 ++++++++++++++------- .../java/org/dolphinemu/dolphinemu/model/Game.java | 1 + 2 files changed, 83 insertions(+), 41 deletions(-) (limited to 'Source/Android/app/src/main/java') diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/TvMainActivity.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/TvMainActivity.java index 2c191bdaf0..0e716d6503 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/TvMainActivity.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/TvMainActivity.java @@ -78,64 +78,105 @@ public final class TvMainActivity extends Activity { mRowsAdapter = new ArrayObjectAdapter(new ListRowPresenter()); - // For each row - for (int platformIndex = 0; platformIndex <= Game.PLATFORM_WII_WARE; ++platformIndex) + // For each platform + for (int platformIndex = 0; platformIndex <= Game.PLATFORM_ALL; ++platformIndex) { - // Create an adapter for this row. - CursorObjectAdapter row = new CursorObjectAdapter(new GamePresenter(platformIndex)); + ListRow row = buildGamesRow(platformIndex); - // Add items to the adapter. - Cursor games = getContentResolver().query( + // Add row to the adapter only if it is not empty. + if (row != null) + { + mRowsAdapter.add(row); + } + } + + mBrowseFragment.setAdapter(mRowsAdapter); + } + + private ListRow buildGamesRow(int platform) + { + // Create an adapter for this row. + CursorObjectAdapter row = new CursorObjectAdapter(new GamePresenter(platform)); + + Cursor games; + if (platform == Game.PLATFORM_ALL) + { + // Get all games. + games = getContentResolver().query( + GameProvider.URI_GAME, // URI of table to query + null, // Return all columns + null, // Return all games + null, // Return all games + GameDatabase.KEY_GAME_TITLE + " asc" // Sort by game name, ascending order + ); + } + else + { + // Get games for this particular platform. + games = getContentResolver().query( GameProvider.URI_GAME, // URI of table to query null, // Return all columns GameDatabase.KEY_GAME_PLATFORM + " = ?", // Select by platform - new String[]{Integer.toString(platformIndex)}, // Platform id + new String[]{Integer.toString(platform)}, // Platform id GameDatabase.KEY_GAME_TITLE + " asc" // Sort by game name, ascending order ); + } - row.swapCursor(games); - row.setMapper(new CursorMapper() - { - @Override - protected void bindColumns(Cursor cursor) - { - // No-op? Not sure what this does. - } + // If cursor is empty, don't return a Row. + if (!games.moveToFirst()) + { + return null; + } - @Override - protected Object bind(Cursor cursor) - { - return Game.fromCursor(cursor); - } - }); + row.changeCursor(games); + row.setMapper(new CursorMapper() + { + @Override + protected void bindColumns(Cursor cursor) + { + // No-op? Not sure what this does. + } - String headerName; - switch (platformIndex) + @Override + protected Object bind(Cursor cursor) { - case Game.PLATFORM_GC: - headerName = "GameCube Games"; - break; + return Game.fromCursor(cursor); + } + }); - case Game.PLATFORM_WII: - headerName = "Wii Games"; - break; + String headerName; + switch (platform) + { + case Game.PLATFORM_GC: + headerName = "GameCube Games"; + break; - case Game.PLATFORM_WII_WARE: - headerName = "WiiWare"; - break; + case Game.PLATFORM_WII: + headerName = "Wii Games"; + break; - default: - headerName = "Error"; - break; - } + case Game.PLATFORM_WII_WARE: + headerName = "WiiWare"; + break; - // Create a header for this row. - HeaderItem header = new HeaderItem(platformIndex, headerName); + case Game.PLATFORM_ALL: + headerName = "All Games"; + break; - // Create the row, passing it the filled adapter and the header, and give it to the master adapter. - mRowsAdapter.add(new ListRow(header, row)); + default: + headerName = "Error"; + break; } - mBrowseFragment.setAdapter(mRowsAdapter); + // Create a header for this row. + HeaderItem header = new HeaderItem(platform, headerName); + + // Create the row, passing it the filled adapter and the header, and give it to the master adapter. + return new ListRow(header, row); } + + /*private ListRow buildSettingsRow() + { + + }*/ } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/Game.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/Game.java index 2068f01f08..33a9f27c54 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/Game.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/Game.java @@ -8,6 +8,7 @@ public final class Game public static final int PLATFORM_GC = 0; public static final int PLATFORM_WII = 1; public static final int PLATFORM_WII_WARE = 2; + public static final int PLATFORM_ALL = 3; // Copied from IVolume::ECountry. Update these if that is ever modified. public static final int COUNTRY_EUROPE = 0; -- cgit v1.2.3 From 245b58124eeca6c6a72f072c10ad5d8dfb9e0d93 Mon Sep 17 00:00:00 2001 From: sigmabeta Date: Mon, 20 Jul 2015 22:46:12 -0400 Subject: Android TV: Add settings row, enabling access to other screens. --- .../dolphinemu/activities/EmulationActivity.java | 4 +- .../dolphinemu/activities/MainActivity.java | 3 +- .../dolphinemu/activities/TvMainActivity.java | 117 +++++++++++++++++--- .../dolphinemu/adapters/GamePresenter.java | 122 --------------------- .../dolphinemu/adapters/GameRowPresenter.java | 118 ++++++++++++++++++++ .../dolphinemu/adapters/SettingsRowPresenter.java | 47 ++++++++ .../dolphinemu/model/TvSettingsItem.java | 31 ++++++ .../dolphinemu/viewholders/TvGameViewHolder.java | 7 +- .../viewholders/TvSettingsViewHolder.java | 23 ++++ 9 files changed, 328 insertions(+), 144 deletions(-) delete mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GamePresenter.java create mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GameRowPresenter.java create mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/SettingsRowPresenter.java create mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/TvSettingsItem.java create mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/viewholders/TvSettingsViewHolder.java (limited to 'Source/Android/app/src/main/java') diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java index c4cc9e1f3a..04b5149a0e 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java @@ -50,8 +50,8 @@ public final class EmulationActivity extends AppCompatActivity private boolean mSystemUiVisible; private boolean mMenuVisible; - private static Interpolator sDecelerator = new DecelerateInterpolator(); - private static Interpolator sAccelerator = new AccelerateInterpolator(); + private static final Interpolator sDecelerator = new DecelerateInterpolator(); + private static final Interpolator sAccelerator = new AccelerateInterpolator(); /** * Handlers are a way to pass a message to an Activity telling it to do something diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/MainActivity.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/MainActivity.java index a32b65d566..9ffa651cc2 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/MainActivity.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/MainActivity.java @@ -35,7 +35,7 @@ import org.dolphinemu.dolphinemu.services.AssetCopyService; */ public final class MainActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks { - private static final int REQUEST_ADD_DIRECTORY = 1; + public static final int REQUEST_ADD_DIRECTORY = 1; public static final int REQUEST_EMULATE_GAME = 2; /** @@ -139,6 +139,7 @@ public final class MainActivity extends AppCompatActivity implements LoaderManag { fragment.refreshScreenshotAtPosition(resultCode); } + break; } } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/TvMainActivity.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/TvMainActivity.java index 0e716d6503..1f58698a7e 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/TvMainActivity.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/TvMainActivity.java @@ -17,12 +17,15 @@ import android.support.v17.leanback.widget.OnItemViewClickedListener; import android.support.v17.leanback.widget.Presenter; import android.support.v17.leanback.widget.Row; import android.support.v17.leanback.widget.RowPresenter; +import android.widget.Toast; import org.dolphinemu.dolphinemu.R; -import org.dolphinemu.dolphinemu.adapters.GamePresenter; +import org.dolphinemu.dolphinemu.adapters.GameRowPresenter; +import org.dolphinemu.dolphinemu.adapters.SettingsRowPresenter; import org.dolphinemu.dolphinemu.model.Game; import org.dolphinemu.dolphinemu.model.GameDatabase; import org.dolphinemu.dolphinemu.model.GameProvider; +import org.dolphinemu.dolphinemu.model.TvSettingsItem; import org.dolphinemu.dolphinemu.viewholders.TvGameViewHolder; public final class TvMainActivity extends Activity @@ -56,24 +59,88 @@ public final class TvMainActivity extends Activity @Override public void onItemClicked(Presenter.ViewHolder itemViewHolder, Object item, RowPresenter.ViewHolder rowViewHolder, Row row) { - TvGameViewHolder holder = (TvGameViewHolder) itemViewHolder; - // Start the emulation activity and send the path of the clicked ISO to it. - Intent intent = new Intent(TvMainActivity.this, EmulationActivity.class); + // Special case: user clicked on a settings row item. + if (item instanceof TvSettingsItem) + { + TvSettingsItem settingsItem = (TvSettingsItem) item; - intent.putExtra("SelectedGame", holder.path); - intent.putExtra("SelectedTitle", holder.title); - intent.putExtra("ScreenPath", holder.screenshotPath); + switch (settingsItem.getItemId()) + { + case R.id.menu_refresh: + getContentResolver().insert(GameProvider.URI_REFRESH, null); - ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation( - TvMainActivity.this, - holder.imageScreenshot, - "image_game_screenshot"); + // TODO Let the Activity know the data is refreshed in some other, better way. + recreate(); + break; - startActivity(intent, options.toBundle()); + case R.id.menu_settings: + // Launch the Settings Actvity. + Intent settings = new Intent(TvMainActivity.this, SettingsActivity.class); + startActivity(settings); + break; + + case R.id.button_add_directory: + Intent fileChooser = new Intent(TvMainActivity.this, AddDirectoryActivity.class); + + // The second argument to this method is read below in onActivityResult(). + startActivityForResult(fileChooser, MainActivity.REQUEST_ADD_DIRECTORY); + + break; + + default: + Toast.makeText(TvMainActivity.this, "Unimplemented menu option.", Toast.LENGTH_SHORT).show(); + break; + } + } + else + { + TvGameViewHolder holder = (TvGameViewHolder) itemViewHolder; + // Start the emulation activity and send the path of the clicked ISO to it. + Intent intent = new Intent(TvMainActivity.this, EmulationActivity.class); + + intent.putExtra("SelectedGame", holder.path); + intent.putExtra("SelectedTitle", holder.title); + intent.putExtra("ScreenPath", holder.screenshotPath); + + ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation( + TvMainActivity.this, + holder.imageScreenshot, + "image_game_screenshot"); + + startActivity(intent, options.toBundle()); + } } }); } + /** + * Callback from AddDirectoryActivity. Applies any changes necessary to the GameGridActivity. + * + * @param requestCode An int describing whether the Activity that is returning did so successfully. + * @param resultCode An int describing what Activity is giving us this callback. + * @param result The information the returning Activity is providing us. + */ + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent result) + { + switch (requestCode) + { + case MainActivity.REQUEST_ADD_DIRECTORY: + // If the user picked a file, as opposed to just backing out. + if (resultCode == RESULT_OK) + { + // Sanity check to make sure the Activity that just returned was the AddDirectoryActivity; + // other activities might use this callback in the future (don't forget to change Javadoc!) + if (requestCode == MainActivity.REQUEST_ADD_DIRECTORY) + { + // TODO Let the Activity know the data is refreshed in some other, better way. + recreate(); + } + } + break; + } + } + private void buildRowsAdapter() { mRowsAdapter = new ArrayObjectAdapter(new ListRowPresenter()); @@ -90,13 +157,16 @@ public final class TvMainActivity extends Activity } } + ListRow settingsRow = buildSettingsRow(); + mRowsAdapter.add(settingsRow); + mBrowseFragment.setAdapter(mRowsAdapter); } private ListRow buildGamesRow(int platform) { // Create an adapter for this row. - CursorObjectAdapter row = new CursorObjectAdapter(new GamePresenter(platform)); + CursorObjectAdapter row = new CursorObjectAdapter(new GameRowPresenter()); Cursor games; if (platform == Game.PLATFORM_ALL) @@ -175,8 +245,25 @@ public final class TvMainActivity extends Activity return new ListRow(header, row); } - /*private ListRow buildSettingsRow() + private ListRow buildSettingsRow() { + ArrayObjectAdapter rowItems = new ArrayObjectAdapter(new SettingsRowPresenter()); - }*/ + rowItems.add(new TvSettingsItem(R.id.menu_refresh, + R.drawable.ic_refresh_tv, + R.string.grid_menu_refresh)); + + rowItems.add(new TvSettingsItem(R.id.menu_settings, + R.drawable.ic_settings_tv, + R.string.grid_menu_settings)); + + rowItems.add(new TvSettingsItem(R.id.button_add_directory, + R.drawable.ic_add_tv, + R.string.add_directory_title)); + + // Create a header for this row. + HeaderItem header = new HeaderItem(R.string.settings, getString(R.string.settings)); + + return new ListRow(header, rowItems); + } } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GamePresenter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GamePresenter.java deleted file mode 100644 index d9b4487278..0000000000 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GamePresenter.java +++ /dev/null @@ -1,122 +0,0 @@ -package org.dolphinemu.dolphinemu.adapters; - -import android.graphics.Bitmap; -import android.support.v17.leanback.widget.ImageCardView; -import android.support.v17.leanback.widget.Presenter; -import android.view.ViewGroup; -import android.widget.ImageView; - -import com.squareup.picasso.Picasso; - -import org.dolphinemu.dolphinemu.R; -import org.dolphinemu.dolphinemu.model.Game; -import org.dolphinemu.dolphinemu.viewholders.TvGameViewHolder; - -/** - * The Leanback library / docs call this a Presenter, but it works very - * similarly to a RecyclerView.ViewHolder. - */ -public final class GamePresenter extends Presenter -{ - private int mPlatform; - - public GamePresenter(int platform) - { - mPlatform = platform; - } - - public ViewHolder onCreateViewHolder(ViewGroup parent) - { - // Create a new view. - ImageCardView gameCard = new ImageCardView(parent.getContext()) - { - @Override - public void setSelected(boolean selected) - { - setCardBackground(this, selected); - super.setSelected(selected); - } - }; - - gameCard.setMainImageAdjustViewBounds(true); - gameCard.setMainImageDimensions(480, 320); - gameCard.setMainImageScaleType(ImageView.ScaleType.CENTER_CROP); - - gameCard.setFocusable(true); - gameCard.setFocusableInTouchMode(true); - - setCardBackground(gameCard, false); - - // Use that view to create a ViewHolder. - return new TvGameViewHolder(gameCard); - } - - public void onBindViewHolder(ViewHolder viewHolder, Object item) - { - TvGameViewHolder holder = (TvGameViewHolder) viewHolder; - Game game = (Game) item; - - String screenPath = game.getScreenshotPath(); - - // Fill in the view contents. - Picasso.with(holder.imageScreenshot.getContext()) - .load(screenPath) - .fit() - .centerCrop() - .noFade() - .noPlaceholder() - .config(Bitmap.Config.RGB_565) - .error(R.drawable.no_banner) - .into(holder.imageScreenshot); - - holder.cardParent.setTitleText(game.getTitle()); - holder.cardParent.setContentText(game.getCompany()); - - // TODO These shouldn't be necessary once the move to a DB-based model is complete. - holder.gameId = game.getGameId(); - holder.path = game.getPath(); - holder.title = game.getTitle(); - holder.description = game.getDescription(); - holder.country = game.getCountry(); - holder.company = game.getCompany(); - holder.screenshotPath = game.getScreenshotPath(); - } - - public void onUnbindViewHolder(ViewHolder viewHolder) - { - // no op - } - - public void setCardBackground(ImageCardView view, boolean selected) - { - int backgroundColor; - - if (selected) - { - switch (mPlatform) - { - case Game.PLATFORM_GC: - backgroundColor = R.color.dolphin_accent_gamecube; - break; - - case Game.PLATFORM_WII: - backgroundColor = R.color.dolphin_accent_wii; - break; - - case Game.PLATFORM_WII_WARE: - backgroundColor = R.color.dolphin_accent_wiiware; - break; - - default: - backgroundColor = android.R.color.holo_red_dark; - break; - } - } - else - { - backgroundColor = R.color.tv_card_unselected; - } - - view.setInfoAreaBackgroundColor(view.getResources().getColor(backgroundColor)); - } -} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GameRowPresenter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GameRowPresenter.java new file mode 100644 index 0000000000..3b0b8095ce --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GameRowPresenter.java @@ -0,0 +1,118 @@ +package org.dolphinemu.dolphinemu.adapters; + +import android.graphics.Bitmap; +import android.support.v17.leanback.widget.ImageCardView; +import android.support.v17.leanback.widget.Presenter; +import android.view.ViewGroup; +import android.widget.ImageView; + +import com.squareup.picasso.Picasso; + +import org.dolphinemu.dolphinemu.R; +import org.dolphinemu.dolphinemu.model.Game; +import org.dolphinemu.dolphinemu.viewholders.TvGameViewHolder; + +/** + * The Leanback library / docs call this a Presenter, but it works very + * similarly to a RecyclerView.ViewHolder. + */ +public final class GameRowPresenter extends Presenter +{ + public ViewHolder onCreateViewHolder(ViewGroup parent) + { + // Create a new view. + ImageCardView gameCard = new ImageCardView(parent.getContext()) + { + @Override + public void setSelected(boolean selected) + { + setCardBackground(this, selected); + super.setSelected(selected); + } + }; + + gameCard.setMainImageAdjustViewBounds(true); + gameCard.setMainImageDimensions(480, 320); + gameCard.setMainImageScaleType(ImageView.ScaleType.CENTER_CROP); + + gameCard.setFocusable(true); + gameCard.setFocusableInTouchMode(true); + + setCardBackground(gameCard, false); + + // Use that view to create a ViewHolder. + return new TvGameViewHolder(gameCard); + } + + public void onBindViewHolder(ViewHolder viewHolder, Object item) + { + TvGameViewHolder holder = (TvGameViewHolder) viewHolder; + Game game = (Game) item; + + String screenPath = game.getScreenshotPath(); + + // Fill in the view contents. + Picasso.with(holder.imageScreenshot.getContext()) + .load(screenPath) + .fit() + .centerCrop() + .noFade() + .noPlaceholder() + .config(Bitmap.Config.RGB_565) + .error(R.drawable.no_banner) + .into(holder.imageScreenshot); + + holder.cardParent.setTitleText(game.getTitle()); + holder.cardParent.setContentText(game.getCompany()); + + // TODO These shouldn't be necessary once the move to a DB-based model is complete. + holder.gameId = game.getGameId(); + holder.path = game.getPath(); + holder.title = game.getTitle(); + holder.description = game.getDescription(); + holder.country = game.getCountry(); + holder.company = game.getCompany(); + holder.screenshotPath = game.getScreenshotPath(); + + switch (game.getPlatform()) + { + case Game.PLATFORM_GC: + holder.cardParent.setTag(R.color.dolphin_accent_gamecube); + break; + + case Game.PLATFORM_WII: + holder.cardParent.setTag(R.color.dolphin_accent_wii); + break; + + case Game.PLATFORM_WII_WARE: + holder.cardParent.setTag(R.color.dolphin_accent_wiiware); + break; + + default: + holder.cardParent.setTag(android.R.color.holo_red_dark); + break; + } + } + + public void onUnbindViewHolder(ViewHolder viewHolder) + { + // no op + } + + public void setCardBackground(ImageCardView view, boolean selected) + { + int backgroundColor; + + if (selected) + { + // TODO: 7/20/15 Try using view tag to set color + backgroundColor = (int) view.getTag(); + } + else + { + backgroundColor = R.color.tv_card_unselected; + } + + view.setInfoAreaBackgroundColor(view.getResources().getColor(backgroundColor)); + } +} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/SettingsRowPresenter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/SettingsRowPresenter.java new file mode 100644 index 0000000000..beef06a218 --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/SettingsRowPresenter.java @@ -0,0 +1,47 @@ +package org.dolphinemu.dolphinemu.adapters; + + +import android.content.res.Resources; +import android.support.v17.leanback.widget.ImageCardView; +import android.support.v17.leanback.widget.Presenter; +import android.view.ViewGroup; + +import org.dolphinemu.dolphinemu.model.TvSettingsItem; +import org.dolphinemu.dolphinemu.viewholders.TvSettingsViewHolder; + +public final class SettingsRowPresenter extends Presenter +{ + public Presenter.ViewHolder onCreateViewHolder(ViewGroup parent) + { + // Create a new view. + ImageCardView settingsCard = new ImageCardView(parent.getContext()); + + settingsCard.setMainImageAdjustViewBounds(true); + settingsCard.setMainImageDimensions(192, 160); + + + settingsCard.setFocusable(true); + settingsCard.setFocusableInTouchMode(true); + + // Use that view to create a ViewHolder. + return new TvSettingsViewHolder(settingsCard); + } + + public void onBindViewHolder(Presenter.ViewHolder viewHolder, Object item) + { + TvSettingsViewHolder holder = (TvSettingsViewHolder) viewHolder; + TvSettingsItem settingsItem = (TvSettingsItem) item; + + Resources resources = holder.cardParent.getResources(); + + holder.itemId = settingsItem.getItemId(); + + holder.cardParent.setTitleText(resources.getString(settingsItem.getLabelId())); + holder.cardParent.setMainImage(resources.getDrawable(settingsItem.getIconId(), null)); + } + + public void onUnbindViewHolder(Presenter.ViewHolder viewHolder) + { + // no op + } +} \ No newline at end of file diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/TvSettingsItem.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/TvSettingsItem.java new file mode 100644 index 0000000000..ccd87bfa4c --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/TvSettingsItem.java @@ -0,0 +1,31 @@ +package org.dolphinemu.dolphinemu.model; + + +public final class TvSettingsItem +{ + private final int mItemId; + private final int mIconId; + private final int mLabelId; + + public TvSettingsItem(int itemId, int iconId, int labelId) + { + mItemId = itemId; + mIconId = iconId; + mLabelId = labelId; + } + + public int getItemId() + { + return mItemId; + } + + public int getIconId() + { + return mIconId; + } + + public int getLabelId() + { + return mLabelId; + } +} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/viewholders/TvGameViewHolder.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/viewholders/TvGameViewHolder.java index dd996ccbe7..d27a671c2f 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/viewholders/TvGameViewHolder.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/viewholders/TvGameViewHolder.java @@ -4,19 +4,16 @@ import android.support.v17.leanback.widget.ImageCardView; import android.support.v17.leanback.widget.Presenter; import android.view.View; import android.widget.ImageView; -import android.widget.TextView; /** * A simple class that stores references to views so that the GameAdapter doesn't need to * keep calling findViewById(), which is expensive. */ -public class TvGameViewHolder extends Presenter.ViewHolder +public final class TvGameViewHolder extends Presenter.ViewHolder { public ImageCardView cardParent; public ImageView imageScreenshot; - public TextView textGameTitle; - public TextView textCompany; public String gameId; @@ -28,6 +25,8 @@ public class TvGameViewHolder extends Presenter.ViewHolder public String company; public String screenshotPath; + public int backgroundColor; + public TvGameViewHolder(View itemView) { super(itemView); diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/viewholders/TvSettingsViewHolder.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/viewholders/TvSettingsViewHolder.java new file mode 100644 index 0000000000..3264e93f5b --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/viewholders/TvSettingsViewHolder.java @@ -0,0 +1,23 @@ +package org.dolphinemu.dolphinemu.viewholders; + + +import android.support.v17.leanback.widget.ImageCardView; +import android.support.v17.leanback.widget.Presenter; +import android.view.View; + +public final class TvSettingsViewHolder extends Presenter.ViewHolder +{ + public ImageCardView cardParent; + + // Determines what action to take when this item is clicked. + public int itemId; + + public TvSettingsViewHolder(View itemView) + { + super(itemView); + + itemView.setTag(this); + + cardParent = (ImageCardView) itemView; + } +} -- cgit v1.2.3 From e7f98c7f959e01cdbf6e09805b9f17719a4efd5f Mon Sep 17 00:00:00 2001 From: sigmabeta Date: Sat, 25 Jul 2015 14:09:58 -0400 Subject: Android TV: Add first-run copy operations to TvMainActivity. --- .../dolphinemu/activities/TvMainActivity.java | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'Source/Android/app/src/main/java') diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/TvMainActivity.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/TvMainActivity.java index 1f58698a7e..3f3b8c168d 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/TvMainActivity.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/TvMainActivity.java @@ -4,8 +4,10 @@ import android.app.Activity; import android.app.ActivityOptions; import android.app.FragmentManager; import android.content.Intent; +import android.content.SharedPreferences; import android.database.Cursor; import android.os.Bundle; +import android.preference.PreferenceManager; import android.support.v17.leanback.app.BrowseFragment; import android.support.v17.leanback.database.CursorMapper; import android.support.v17.leanback.widget.ArrayObjectAdapter; @@ -19,6 +21,7 @@ import android.support.v17.leanback.widget.Row; import android.support.v17.leanback.widget.RowPresenter; import android.widget.Toast; +import org.dolphinemu.dolphinemu.NativeLibrary; import org.dolphinemu.dolphinemu.R; import org.dolphinemu.dolphinemu.adapters.GameRowPresenter; import org.dolphinemu.dolphinemu.adapters.SettingsRowPresenter; @@ -26,6 +29,7 @@ import org.dolphinemu.dolphinemu.model.Game; import org.dolphinemu.dolphinemu.model.GameDatabase; import org.dolphinemu.dolphinemu.model.GameProvider; import org.dolphinemu.dolphinemu.model.TvSettingsItem; +import org.dolphinemu.dolphinemu.services.AssetCopyService; import org.dolphinemu.dolphinemu.viewholders.TvGameViewHolder; public final class TvMainActivity extends Activity @@ -111,6 +115,23 @@ public final class TvMainActivity extends Activity } } }); + + // Stuff in this block only happens when this activity is newly created (i.e. not a rotation) + if (savedInstanceState == null) + { + NativeLibrary.SetUserDirectory(""); // Auto-Detect + + SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this); + boolean assetsCopied = preferences.getBoolean("assetsCopied", false); + + // Only perform these extensive copy operations once. + if (!assetsCopied) + { + // Copy assets into appropriate locations. + Intent copyAssets = new Intent(this, AssetCopyService.class); + startService(copyAssets); + } + } } /** -- cgit v1.2.3 From 9bb63bf2eb66a13705ca67f449d4819cbfcdf053 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Fri, 4 Sep 2015 20:06:01 -0500 Subject: [Android] Fix multi-gamecube controller input, config changes --- .../dolphinemu/utils/UserPreferences.java | 25 +++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) (limited to 'Source/Android/app/src/main/java') diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/UserPreferences.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/UserPreferences.java index 168bd2dd93..59573132a4 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/UserPreferences.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/UserPreferences.java @@ -45,14 +45,14 @@ public final class UserPreferences else editor.putString("cpuCorePref", getConfig("Dolphin.ini", "Core", "CPUCore", "3")); - editor.putBoolean("dualCorePref", getConfig("Dolphin.ini", "Core", "CPUThread", "False").equals("True")); - editor.putBoolean("fastmemPref", getConfig("Dolphin.ini", "Core", "Fastmem", "False").equals("True")); + editor.putBoolean("dualCorePref", getConfig("Dolphin.ini", "Core", "CPUThread", "True").equals("True")); + editor.putBoolean("fastmemPref", getConfig("Dolphin.ini", "Core", "Fastmem", "True").equals("True")); editor.putString("gpuPref", getConfig("Dolphin.ini", "Core", "GFXBackend", "OGL")); editor.putBoolean("showFPS", getConfig("gfx_opengl.ini", "Settings", "ShowFPS", "False").equals("True")); editor.putBoolean("drawOnscreenControls", getConfig("Dolphin.ini", "Android", "ScreenControls", "True").equals("True")); - editor.putString("internalResolution", getConfig("gfx_opengl.ini", "Settings", "EFBScale", "2") ); + editor.putString("internalResolution", getConfig("gfx_opengl.ini", "Settings", "EFBScale", "2")); editor.putString("FSAA", getConfig("gfx_opengl.ini", "Settings", "MSAA", "0")); editor.putString("anisotropicFiltering", getConfig("gfx_opengl.ini", "Enhancements", "MaxAnisotropy", "0")); editor.putString("postProcessingShader", getConfig("gfx_opengl.ini", "Enhancements", "PostProcessingShader", "")); @@ -62,10 +62,14 @@ public final class UserPreferences editor.putBoolean("disableFog", getConfig("gfx_opengl.ini", "Settings", "DisableFog", "False").equals("True")); editor.putBoolean("skipEFBAccess", getConfig("gfx_opengl.ini", "Hacks", "EFBAccessEnable", "False").equals("True")); editor.putBoolean("ignoreFormatChanges", getConfig("gfx_opengl.ini", "Hacks", "EFBEmulateFormatChanges", "False").equals("True")); - editor.putString("stereoscopyMode", getConfig("gfx_opengl.ini", "Enhancements", "StereoMode", "0")); + editor.putString("stereoscopyMode", getConfig("gfx_opengl.ini", "Enhancements", "StereoMode", "0")); editor.putBoolean("stereoSwapEyes", getConfig("gfx_opengl.ini", "Enhancements", "StereoSwapEyes", "False").equals("True")); editor.putString("stereoDepth", getConfig("gfx_opengl.ini", "Enhancements", "StereoDepth", "20")); editor.putString("stereoConvergence", getConfig("gfx_opengl.ini", "Enhancements", "StereoConvergence", "20")); + editor.putBoolean("enableController1", getConfig("Dolphin.ini", "Settings", "SIDevice0", "6") == "6"); + editor.putBoolean("enableController2", getConfig("Dolphin.ini", "Settings", "SIDevice1", "0") == "6"); + editor.putBoolean("enableController3", getConfig("Dolphin.ini", "Settings", "SIDevice2", "0") == "6"); + editor.putBoolean("enableController4", getConfig("Dolphin.ini", "Settings", "SIDevice3", "0") == "6"); String efbCopyOn = getConfig("gfx_opengl.ini", "Hacks", "EFBCopyEnable", "True"); String efbToTexture = getConfig("gfx_opengl.ini", "Hacks", "EFBToTextureEnable", "True"); @@ -136,7 +140,7 @@ public final class UserPreferences String currentEmuCore = prefs.getString("cpuCorePref", "0"); // Fastmem JIT core usage - boolean isUsingFastmem = prefs.getBoolean("fastmemPref", false); + boolean isUsingFastmem = prefs.getBoolean("fastmemPref", true); // Current video backend being used. Falls back to software rendering upon error. String currentVideoBackend = prefs.getString("gpuPref", "Software Rendering"); @@ -207,6 +211,13 @@ public final class UserPreferences // Stereoscopy convergence String stereoscopyConvergence = prefs.getString("stereoConvergence", "20"); + // Controllers + // Controller 1 never gets disconnected due to touch screen + //boolean enableController1 = prefs.getBoolean("enableController1", true); + boolean enableController2 = prefs.getBoolean("enableController2", false); + boolean enableController3 = prefs.getBoolean("enableController3", false); + boolean enableController4 = prefs.getBoolean("enableController4", false); + // CPU related Settings NativeLibrary.SetConfig("Dolphin.ini", "Core", "CPUCore", currentEmuCore); NativeLibrary.SetConfig("Dolphin.ini", "Core", "CPUThread", isUsingDualCore ? "True" : "False"); @@ -280,5 +291,9 @@ public final class UserPreferences NativeLibrary.SetConfig("gfx_opengl.ini", "Enhancements", "StereoSwapEyes", stereoscopyEyeSwap ? "True" : "False"); NativeLibrary.SetConfig("gfx_opengl.ini", "Enhancements", "StereoDepth", stereoscopySeparation); NativeLibrary.SetConfig("gfx_opengl.ini", "Enhancements", "StereoConvergence", stereoscopyConvergence); + NativeLibrary.SetConfig("Dolphin.ini", "Settings", "SIDevice0", "6"); + NativeLibrary.SetConfig("Dolphin.ini", "Settings", "SIDevice1", enableController2 ? "6" : "0"); + NativeLibrary.SetConfig("Dolphin.ini", "Settings", "SIDevice2", enableController3 ? "6" : "0"); + NativeLibrary.SetConfig("Dolphin.ini", "Settings", "SIDevice3", enableController4 ? "6" : "0"); } } -- cgit v1.2.3 From 74b20e627ca524366b0a4fa617d59014cd2c967c Mon Sep 17 00:00:00 2001 From: degasus Date: Wed, 9 Sep 2015 21:20:46 +0200 Subject: VideoCommon: Drop "Disable destAlpha" hack This option has no use any more, neither performance nor driver workaround. --- .../main/java/org/dolphinemu/dolphinemu/utils/UserPreferences.java | 5 ----- 1 file changed, 5 deletions(-) (limited to 'Source/Android/app/src/main/java') diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/UserPreferences.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/UserPreferences.java index 59573132a4..8fe609beb1 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/UserPreferences.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/UserPreferences.java @@ -110,7 +110,6 @@ public final class UserPreferences editor.putString("externalFrameBuffer", "Real"); } - editor.putBoolean("disableDestinationAlpha", getConfig("gfx_opengl.ini", "Settings", "DstAlphaPass", "False").equals("True")); editor.putBoolean("fastDepthCalculation", getConfig("gfx_opengl.ini", "Settings", "FastDepthCalc", "True").equals("True")); editor.putString("aspectRatio", getConfig("gfx_opengl.ini", "Settings", "AspectRatio", "0")); @@ -166,9 +165,6 @@ public final class UserPreferences // External frame buffer emulation. Falls back to disabled upon error. String externalFrameBuffer = prefs.getString("externalFrameBuffer", "Disabled"); - // Whether or not to disable destination alpha. - boolean disableDstAlphaPass = prefs.getBoolean("disableDestinationAlpha", false); - // Whether or not to use fast depth calculation. boolean useFastDepthCalc = prefs.getBoolean("fastDepthCalculation", true); @@ -275,7 +271,6 @@ public final class UserPreferences NativeLibrary.SetConfig("gfx_opengl.ini", "Settings", "UseRealXFB", "True"); } - NativeLibrary.SetConfig("gfx_opengl.ini", "Settings", "DstAlphaPass", disableDstAlphaPass ? "True" : "False"); NativeLibrary.SetConfig("gfx_opengl.ini", "Settings", "FastDepthCalc", useFastDepthCalc ? "True" : "False"); //-- Enhancement Settings --// -- cgit v1.2.3 From cbd7b0793fa2815fa963733c6c54cf16b3e07d2a Mon Sep 17 00:00:00 2001 From: Anthony Serna Date: Wed, 9 Sep 2015 13:58:22 -0700 Subject: Removed fastmem from Android UI --- .../main/java/org/dolphinemu/dolphinemu/utils/UserPreferences.java | 5 ----- 1 file changed, 5 deletions(-) (limited to 'Source/Android/app/src/main/java') diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/UserPreferences.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/UserPreferences.java index 59573132a4..4a70c75184 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/UserPreferences.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/UserPreferences.java @@ -46,7 +46,6 @@ public final class UserPreferences editor.putString("cpuCorePref", getConfig("Dolphin.ini", "Core", "CPUCore", "3")); editor.putBoolean("dualCorePref", getConfig("Dolphin.ini", "Core", "CPUThread", "True").equals("True")); - editor.putBoolean("fastmemPref", getConfig("Dolphin.ini", "Core", "Fastmem", "True").equals("True")); editor.putString("gpuPref", getConfig("Dolphin.ini", "Core", "GFXBackend", "OGL")); editor.putBoolean("showFPS", getConfig("gfx_opengl.ini", "Settings", "ShowFPS", "False").equals("True")); @@ -139,9 +138,6 @@ public final class UserPreferences // Current CPU core being used. Falls back to interpreter upon error. String currentEmuCore = prefs.getString("cpuCorePref", "0"); - // Fastmem JIT core usage - boolean isUsingFastmem = prefs.getBoolean("fastmemPref", true); - // Current video backend being used. Falls back to software rendering upon error. String currentVideoBackend = prefs.getString("gpuPref", "Software Rendering"); @@ -221,7 +217,6 @@ public final class UserPreferences // CPU related Settings NativeLibrary.SetConfig("Dolphin.ini", "Core", "CPUCore", currentEmuCore); NativeLibrary.SetConfig("Dolphin.ini", "Core", "CPUThread", isUsingDualCore ? "True" : "False"); - NativeLibrary.SetConfig("Dolphin.ini", "Core", "Fastmem", isUsingFastmem ? "True" : "False"); // General Video Settings NativeLibrary.SetConfig("Dolphin.ini", "Core", "GFXBackend", currentVideoBackend); -- cgit v1.2.3