mirror of
https://github.com/SSimco/Cemu.git
synced 2024-11-23 13:29:38 +00:00
Added options to show the gamepad & added a menu when in game
This commit is contained in:
parent
c1fc52d169
commit
dceec9e20a
@ -24,13 +24,6 @@
|
||||
android:parentActivityName=".MainActivity"
|
||||
android:screenOrientation="userLandscape"
|
||||
tools:ignore="DiscouragedApi" />
|
||||
<activity
|
||||
android:name=".inputoverlay.InputOverlayConfigureActivity"
|
||||
android:launchMode="singleTop"
|
||||
android:parentActivityName=".settings.SettingsActivity"
|
||||
android:screenOrientation="userLandscape"
|
||||
tools:ignore="DiscouragedApi" />
|
||||
|
||||
<activity
|
||||
android:name=".settings.SettingsActivity"
|
||||
android:exported="false"
|
||||
|
@ -35,10 +35,10 @@ class EmulationState
|
||||
m_graphicPacks[reinterpret_cast<int64_t>(graphicPack.get())] = graphicPack;
|
||||
}
|
||||
}
|
||||
void onTouchEvent(sint32 x, sint32 y, bool isPad, std::optional<bool> status = {})
|
||||
void onTouchEvent(sint32 x, sint32 y, bool isTV, std::optional<bool> status = {})
|
||||
{
|
||||
auto& instance = InputManager::instance();
|
||||
auto& touchInfo = isPad ? instance.m_pad_mouse : instance.m_main_mouse;
|
||||
auto& touchInfo = isTV ? instance.m_main_mouse : instance.m_pad_mouse;
|
||||
std::scoped_lock lock(touchInfo.m_mutex);
|
||||
touchInfo.position = {x, y};
|
||||
if (status.has_value())
|
||||
@ -68,6 +68,12 @@ class EmulationState
|
||||
|
||||
void clearSurface(bool isMainCanvas)
|
||||
{
|
||||
if (!isMainCanvas)
|
||||
{
|
||||
auto renderer = static_cast<VulkanRenderer*>(g_renderer.get());
|
||||
if (renderer)
|
||||
renderer->StopUsingPadAndWait();
|
||||
}
|
||||
}
|
||||
|
||||
void notifySurfaceChanged(bool isMainCanvas)
|
||||
@ -76,16 +82,20 @@ class EmulationState
|
||||
|
||||
void setSurface(JNIEnv* env, jobject surface, bool isMainCanvas)
|
||||
{
|
||||
cemu_assert_debug(surface != nullptr);
|
||||
auto& windowHandleInfo = isMainCanvas ? GuiSystem::getWindowInfo().canvas_main : GuiSystem::getWindowInfo().canvas_pad;
|
||||
if (windowHandleInfo.surface)
|
||||
{
|
||||
ANativeWindow_release(static_cast<ANativeWindow*>(windowHandleInfo.surface));
|
||||
windowHandleInfo.surface = nullptr;
|
||||
}
|
||||
if (surface)
|
||||
windowHandleInfo.surface = ANativeWindow_fromSurface(env, surface);
|
||||
windowHandleInfo.surface = ANativeWindow_fromSurface(env, surface);
|
||||
int width, height;
|
||||
if (isMainCanvas)
|
||||
GuiSystem::getWindowInfo().window_main.surface = windowHandleInfo.surface;
|
||||
GuiSystem::getWindowPhysSize(width, height);
|
||||
else
|
||||
GuiSystem::getPadWindowPhysSize(width, height);
|
||||
VulkanRenderer::GetInstance()->InitializeSurface({width, height}, isMainCanvas);
|
||||
}
|
||||
|
||||
void setSurfaceSize(int width, int height, bool isMainCanvas)
|
||||
@ -178,20 +188,19 @@ class EmulationState
|
||||
else
|
||||
androidEmulatedController.setDisabled();
|
||||
}
|
||||
void initializeRenderer()
|
||||
|
||||
void initializeRenderer(JNIEnv* env, jobject testSurface)
|
||||
{
|
||||
cemu_assert_debug(testSurface != nullptr);
|
||||
// TODO: cleanup surface
|
||||
GuiSystem::getWindowInfo().window_main.surface = ANativeWindow_fromSurface(env, testSurface);
|
||||
g_renderer = std::make_unique<VulkanRenderer>();
|
||||
}
|
||||
void initializeRenderSurface(bool isMainCanvas)
|
||||
void setReplaceTVWithPadView(bool showDRC)
|
||||
{
|
||||
int width, height;
|
||||
if (isMainCanvas)
|
||||
GuiSystem::getWindowPhysSize(width, height);
|
||||
else
|
||||
GuiSystem::getPadWindowPhysSize(width, height);
|
||||
VulkanRenderer::GetInstance()->InitializeSurface({width, height}, isMainCanvas);
|
||||
// Emulate pressing the TAB key for showing DRC instead of TV
|
||||
GuiSystem::getWindowInfo().set_keystate(GuiSystem::PlatformKeyCodes::TAB, showDRC);
|
||||
}
|
||||
|
||||
void setDPI(float dpi)
|
||||
{
|
||||
auto& windowInfo = GuiSystem::getWindowInfo();
|
||||
@ -256,6 +265,7 @@ class EmulationState
|
||||
|
||||
void startGame(TitleId titleId)
|
||||
{
|
||||
GuiSystem::getWindowInfo().set_keystates_up();
|
||||
initializeAudioDevices();
|
||||
CafeSystemUtils::startGame(titleId);
|
||||
}
|
||||
@ -315,16 +325,16 @@ class EmulationState
|
||||
}
|
||||
g_config.Save();
|
||||
}
|
||||
void onTouchMove(sint32 x, sint32 y, bool isPad)
|
||||
void onTouchMove(sint32 x, sint32 y, bool isTV)
|
||||
{
|
||||
onTouchEvent(x, y, isPad);
|
||||
onTouchEvent(x, y, isTV);
|
||||
}
|
||||
void onTouchUp(sint32 x, sint32 y, bool isPad)
|
||||
void onTouchUp(sint32 x, sint32 y, bool isTV)
|
||||
{
|
||||
onTouchEvent(x, y, isPad, false);
|
||||
onTouchEvent(x, y, isTV, false);
|
||||
}
|
||||
void onTouchDown(sint32 x, sint32 y, bool isPad)
|
||||
void onTouchDown(sint32 x, sint32 y, bool isTV)
|
||||
{
|
||||
onTouchEvent(x, y, isPad, true);
|
||||
onTouchEvent(x, y, isTV, true);
|
||||
}
|
||||
};
|
@ -72,15 +72,11 @@ Java_info_cemu_Cemu_NativeLibrary_initializeEmulation([[maybe_unused]] JNIEnv* e
|
||||
s_emulationState.initializeEmulation();
|
||||
}
|
||||
extern "C" [[maybe_unused]] JNIEXPORT void JNICALL
|
||||
Java_info_cemu_Cemu_NativeLibrary_initializerRenderer([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz)
|
||||
Java_info_cemu_Cemu_NativeLibrary_initializerRenderer(JNIEnv* env, [[maybe_unused]] jclass clazz, jobject testSurface)
|
||||
{
|
||||
s_emulationState.initializeRenderer();
|
||||
}
|
||||
extern "C" [[maybe_unused]] JNIEXPORT void JNICALL
|
||||
Java_info_cemu_Cemu_NativeLibrary_initializeRendererSurface([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jboolean is_main_canvas)
|
||||
{
|
||||
s_emulationState.initializeRenderSurface(is_main_canvas);
|
||||
s_emulationState.initializeRenderer(env, testSurface);
|
||||
}
|
||||
|
||||
extern "C" [[maybe_unused]] JNIEXPORT void JNICALL
|
||||
Java_info_cemu_Cemu_NativeLibrary_setDPI([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jfloat dpi)
|
||||
{
|
||||
@ -571,19 +567,25 @@ Java_info_cemu_Cemu_NativeLibrary_setNotificationFriendListEnabled([[maybe_unuse
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_info_cemu_Cemu_NativeLibrary_onTouchDown([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jint x, jint y, jboolean isPad)
|
||||
Java_info_cemu_Cemu_NativeLibrary_setReplaceTVWithPadView([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jboolean swapped)
|
||||
{
|
||||
s_emulationState.onTouchDown(x, y, isPad);
|
||||
s_emulationState.setReplaceTVWithPadView(swapped);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_info_cemu_Cemu_NativeLibrary_onTouchUp([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jint x, jint y, jboolean isPad)
|
||||
Java_info_cemu_Cemu_NativeLibrary_onTouchDown([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jint x, jint y, jboolean isTV)
|
||||
{
|
||||
s_emulationState.onTouchUp(x, y, isPad);
|
||||
s_emulationState.onTouchDown(x, y, isTV);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_info_cemu_Cemu_NativeLibrary_onTouchMove([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jint x, jint y, jboolean isPad)
|
||||
Java_info_cemu_Cemu_NativeLibrary_onTouchUp([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jint x, jint y, jboolean isTV)
|
||||
{
|
||||
s_emulationState.onTouchMove(x, y, isPad);
|
||||
s_emulationState.onTouchUp(x, y, isTV);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_info_cemu_Cemu_NativeLibrary_onTouchMove([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jint x, jint y, jboolean isTV)
|
||||
{
|
||||
s_emulationState.onTouchMove(x, y, isTV);
|
||||
}
|
||||
|
@ -20,12 +20,12 @@ public class NativeLibrary {
|
||||
|
||||
public static native void setSurfaceSize(int width, int height, boolean isMainCanvas);
|
||||
|
||||
public static native void initializerRenderer();
|
||||
|
||||
public static native void initializeRendererSurface(boolean isMainCanvas);
|
||||
public static native void initializerRenderer(Surface surface);
|
||||
|
||||
public static native void startGame(long titleId);
|
||||
|
||||
public static native void setReplaceTVWithPadView(boolean swapped);
|
||||
|
||||
public static native void recreateRenderSurface(boolean isMainCanvas);
|
||||
|
||||
|
||||
@ -388,9 +388,9 @@ public class NativeLibrary {
|
||||
|
||||
public static native void setNotificationFriendListEnabled(boolean enabled);
|
||||
|
||||
public static native void onTouchDown(int x, int y, boolean isPad);
|
||||
public static native void onTouchDown(int x, int y, boolean isTV);
|
||||
|
||||
public static native void onTouchMove(int x, int y, boolean isPad);
|
||||
public static native void onTouchMove(int x, int y, boolean isTV);
|
||||
|
||||
public static native void onTouchUp(int x, int y, boolean isPad);
|
||||
public static native void onTouchUp(int x, int y, boolean isTV);
|
||||
}
|
||||
|
@ -1,51 +1,40 @@
|
||||
package info.cemu.Cemu.emulation;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.graphics.SurfaceTexture;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.Surface;
|
||||
import android.view.SurfaceHolder;
|
||||
import android.view.SurfaceView;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.appcompat.widget.PopupMenu;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import info.cemu.Cemu.NativeLibrary;
|
||||
import info.cemu.Cemu.R;
|
||||
import info.cemu.Cemu.databinding.FragmentEmulationBinding;
|
||||
import info.cemu.Cemu.inputoverlay.InputOverlaySettingsProvider;
|
||||
import info.cemu.Cemu.inputoverlay.InputOverlaySurfaceView;
|
||||
import info.cemu.Cemu.NativeLibrary;
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
public class EmulationFragment extends Fragment implements SurfaceHolder.Callback {
|
||||
private final long gameTitleId;
|
||||
private boolean isGameRunning;
|
||||
private SurfaceHolder mainCanvasSurfaceHolder;
|
||||
private Toast toast;
|
||||
|
||||
public EmulationFragment(long gameTitleId) {
|
||||
this.gameTitleId = gameTitleId;
|
||||
}
|
||||
|
||||
InputOverlaySettingsProvider.OverlaySettings overlaySettings;
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
var inputOverlaySettingsProvider = new InputOverlaySettingsProvider(requireContext());
|
||||
overlaySettings = inputOverlaySettingsProvider.getOverlaySettings();
|
||||
}
|
||||
public class EmulationFragment extends Fragment implements PopupMenu.OnMenuItemClickListener {
|
||||
|
||||
static private class OnSurfaceTouchListener implements View.OnTouchListener {
|
||||
int currentPointerId = -1;
|
||||
final boolean isPad;
|
||||
final boolean isTV;
|
||||
|
||||
public OnSurfaceTouchListener(boolean isPad) {
|
||||
this.isPad = isPad;
|
||||
public OnSurfaceTouchListener(boolean isTV) {
|
||||
this.isTV = isTV;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -59,15 +48,15 @@ public class EmulationFragment extends Fragment implements SurfaceHolder.Callbac
|
||||
int y = (int) event.getY(pointerIndex);
|
||||
switch (event.getActionMasked()) {
|
||||
case MotionEvent.ACTION_DOWN, MotionEvent.ACTION_POINTER_DOWN -> {
|
||||
NativeLibrary.onTouchDown(x, y, isPad);
|
||||
NativeLibrary.onTouchDown(x, y, isTV);
|
||||
return true;
|
||||
}
|
||||
case MotionEvent.ACTION_UP, MotionEvent.ACTION_POINTER_UP -> {
|
||||
NativeLibrary.onTouchUp(x, y, isPad);
|
||||
NativeLibrary.onTouchUp(x, y, isTV);
|
||||
return true;
|
||||
}
|
||||
case MotionEvent.ACTION_MOVE -> {
|
||||
NativeLibrary.onTouchMove(x, y, isPad);
|
||||
NativeLibrary.onTouchMove(x, y, isTV);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -75,70 +64,186 @@ public class EmulationFragment extends Fragment implements SurfaceHolder.Callbac
|
||||
}
|
||||
}
|
||||
|
||||
private static class SurfaceHolderCallback implements SurfaceHolder.Callback {
|
||||
final boolean isMainCanvas;
|
||||
boolean surfaceSet;
|
||||
|
||||
public SurfaceHolderCallback(boolean isMainCanvas) {
|
||||
this.isMainCanvas = isMainCanvas;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void surfaceCreated(@NonNull SurfaceHolder surfaceHolder) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void surfaceChanged(@NonNull SurfaceHolder surfaceHolder, int format, int width, int height) {
|
||||
NativeLibrary.setSurfaceSize(width, height, isMainCanvas);
|
||||
if (!surfaceSet) {
|
||||
surfaceSet = true;
|
||||
NativeLibrary.setSurface(surfaceHolder.getSurface(), isMainCanvas);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void surfaceDestroyed(@NonNull SurfaceHolder surfaceHolder) {
|
||||
NativeLibrary.clearSurface(isMainCanvas);
|
||||
surfaceSet = false;
|
||||
}
|
||||
}
|
||||
|
||||
private final long gameTitleId;
|
||||
private boolean isGameRunning;
|
||||
private SurfaceView padCanvas;
|
||||
private SurfaceTexture testSurfaceTexture;
|
||||
private Surface testSurface;
|
||||
private Toast toast;
|
||||
private FragmentEmulationBinding binding;
|
||||
private PopupMenu settingsMenu;
|
||||
private InputOverlaySurfaceView inputOverlaySurfaceView;
|
||||
|
||||
public EmulationFragment(long gameTitleId) {
|
||||
this.gameTitleId = gameTitleId;
|
||||
}
|
||||
|
||||
InputOverlaySettingsProvider.OverlaySettings overlaySettings;
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
var inputOverlaySettingsProvider = new InputOverlaySettingsProvider(requireContext());
|
||||
overlaySettings = inputOverlaySettingsProvider.getOverlaySettings();
|
||||
testSurfaceTexture = new SurfaceTexture(0);
|
||||
testSurface = new Surface(testSurfaceTexture);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (testSurface != null) testSurface.release();
|
||||
if (testSurfaceTexture != null) testSurfaceTexture.release();
|
||||
}
|
||||
|
||||
private void createPadCanvas() {
|
||||
if (padCanvas != null) return;
|
||||
padCanvas = new SurfaceView(requireContext());
|
||||
binding.canvasesLayout.addView(
|
||||
padCanvas,
|
||||
new LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.MATCH_PARENT, 1.0f)
|
||||
);
|
||||
padCanvas.getHolder().addCallback(new SurfaceHolderCallback(false));
|
||||
padCanvas.setOnTouchListener(new OnSurfaceTouchListener(false));
|
||||
}
|
||||
|
||||
private void toastMessage(@StringRes int toastTextResId) {
|
||||
if (toast != null) {
|
||||
toast.cancel();
|
||||
}
|
||||
toast = Toast.makeText(requireContext(), toastTextResId, Toast.LENGTH_SHORT);
|
||||
toast.show();
|
||||
}
|
||||
|
||||
private void destroyPadCanvas() {
|
||||
if (padCanvas == null) return;
|
||||
binding.canvasesLayout.removeView(padCanvas);
|
||||
padCanvas = null;
|
||||
}
|
||||
|
||||
private void setPadViewVisibility(boolean visible) {
|
||||
if (visible) {
|
||||
createPadCanvas();
|
||||
return;
|
||||
}
|
||||
destroyPadCanvas();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
int itemId = item.getItemId();
|
||||
if (itemId == R.id.show_pad) {
|
||||
boolean padVisibility = !item.isChecked();
|
||||
setPadViewVisibility(padVisibility);
|
||||
item.setChecked(padVisibility);
|
||||
return true;
|
||||
}
|
||||
if (itemId == R.id.edit_inputs) {
|
||||
binding.editInputsLayout.setVisibility(View.VISIBLE);
|
||||
binding.finishEditInputsButton.setVisibility(View.VISIBLE);
|
||||
binding.moveInputsButton.performClick();
|
||||
return true;
|
||||
}
|
||||
if (itemId == R.id.replace_tv_with_pad) {
|
||||
boolean replaceTVWithPad = !item.isChecked();
|
||||
NativeLibrary.setReplaceTVWithPadView(replaceTVWithPad);
|
||||
item.setChecked(replaceTVWithPad);
|
||||
return true;
|
||||
}
|
||||
if (itemId == R.id.reset_inputs) {
|
||||
inputOverlaySurfaceView.resetInputs();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
FragmentEmulationBinding binding = FragmentEmulationBinding.inflate(inflater, container, false);
|
||||
binding = FragmentEmulationBinding.inflate(inflater, container, false);
|
||||
inputOverlaySurfaceView = binding.inputOverlay;
|
||||
|
||||
InputOverlaySurfaceView surfaceView = binding.inputOverlay;
|
||||
binding.inputModeButton.setOnClickListener(v -> {
|
||||
InputOverlaySurfaceView.InputMode nextMode = InputOverlaySurfaceView.InputMode.DEFAULT;
|
||||
int toastTextResId = R.string.input_mode_default;
|
||||
switch (surfaceView.getInputMode()) {
|
||||
case EDIT_POSITION -> {
|
||||
nextMode = InputOverlaySurfaceView.InputMode.EDIT_SIZE;
|
||||
toastTextResId = R.string.input_mode_edit_size;
|
||||
}
|
||||
case EDIT_SIZE -> {
|
||||
nextMode = InputOverlaySurfaceView.InputMode.DEFAULT;
|
||||
toastTextResId = R.string.input_mode_default;
|
||||
}
|
||||
case DEFAULT -> {
|
||||
nextMode = InputOverlaySurfaceView.InputMode.EDIT_POSITION;
|
||||
toastTextResId = R.string.input_mode_edit_position;
|
||||
}
|
||||
}
|
||||
if (toast != null) {
|
||||
toast.cancel();
|
||||
}
|
||||
toast = Toast.makeText(requireContext(), toastTextResId, Toast.LENGTH_SHORT);
|
||||
toast.show();
|
||||
surfaceView.setInputMode(nextMode);
|
||||
binding.moveInputsButton.setOnClickListener(v -> {
|
||||
if (inputOverlaySurfaceView.getInputMode() == InputOverlaySurfaceView.InputMode.EDIT_POSITION)
|
||||
return;
|
||||
binding.resizeInputsButton.setAlpha(0.5f);
|
||||
binding.moveInputsButton.setAlpha(1.0f);
|
||||
toastMessage(R.string.input_mode_edit_position);
|
||||
inputOverlaySurfaceView.setInputMode(InputOverlaySurfaceView.InputMode.EDIT_POSITION);
|
||||
});
|
||||
binding.resizeInputsButton.setOnClickListener(v -> {
|
||||
if (inputOverlaySurfaceView.getInputMode() == InputOverlaySurfaceView.InputMode.EDIT_SIZE)
|
||||
return;
|
||||
binding.moveInputsButton.setAlpha(0.5f);
|
||||
binding.resizeInputsButton.setAlpha(1.0f);
|
||||
toastMessage(R.string.input_mode_edit_size);
|
||||
inputOverlaySurfaceView.setInputMode(InputOverlaySurfaceView.InputMode.EDIT_SIZE);
|
||||
});
|
||||
binding.finishEditInputsButton.setOnClickListener(v -> {
|
||||
inputOverlaySurfaceView.setInputMode(InputOverlaySurfaceView.InputMode.DEFAULT);
|
||||
binding.finishEditInputsButton.setVisibility(View.GONE);
|
||||
binding.editInputsLayout.setVisibility(View.GONE);
|
||||
toastMessage(R.string.input_mode_default);
|
||||
});
|
||||
settingsMenu = new PopupMenu(requireContext(), binding.emulationSettingsButton);
|
||||
settingsMenu.getMenuInflater().inflate(R.menu.menu_emulation_in_game, settingsMenu.getMenu());
|
||||
settingsMenu.setOnMenuItemClickListener(EmulationFragment.this);
|
||||
binding.emulationSettingsButton.setOnClickListener(v -> settingsMenu.show());
|
||||
|
||||
if (!overlaySettings.isOverlayEnabled()) {
|
||||
binding.inputModeButton.setVisibility(View.GONE);
|
||||
surfaceView.setVisibility(View.GONE);
|
||||
inputOverlaySurfaceView.setVisibility(View.GONE);
|
||||
}
|
||||
SurfaceView mainCanvas = binding.mainCanvas;
|
||||
mainCanvas.getHolder().addCallback(this);
|
||||
mainCanvas.setOnTouchListener(new OnSurfaceTouchListener(false));
|
||||
|
||||
NativeLibrary.initializerRenderer(testSurface);
|
||||
|
||||
var mainCanvasHolder = mainCanvas.getHolder();
|
||||
mainCanvasHolder.addCallback(new SurfaceHolderCallback(true));
|
||||
mainCanvasHolder.addCallback(new SurfaceHolder.Callback() {
|
||||
@Override
|
||||
public void surfaceCreated(@NonNull SurfaceHolder holder) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) {
|
||||
if (!isGameRunning) {
|
||||
isGameRunning = true;
|
||||
NativeLibrary.startGame(gameTitleId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void surfaceDestroyed(@NonNull SurfaceHolder holder) {
|
||||
}
|
||||
});
|
||||
mainCanvas.setOnTouchListener(new OnSurfaceTouchListener(true));
|
||||
return binding.getRoot();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void surfaceCreated(@NonNull SurfaceHolder surfaceHolder) {
|
||||
mainCanvasSurfaceHolder = surfaceHolder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void surfaceChanged(@NonNull SurfaceHolder surfaceHolder, int format, int width, int height) {
|
||||
NativeLibrary.setSurfaceSize(width, height, true);
|
||||
if (!isGameRunning) {
|
||||
isGameRunning = true;
|
||||
NativeLibrary.setSurface(surfaceHolder.getSurface(), true);
|
||||
NativeLibrary.initializerRenderer();
|
||||
NativeLibrary.initializeRendererSurface(true);
|
||||
NativeLibrary.startGame(gameTitleId);
|
||||
} else {
|
||||
if (mainCanvasSurfaceHolder == surfaceHolder)
|
||||
return;
|
||||
NativeLibrary.setSurface(surfaceHolder.getSurface(), true);
|
||||
NativeLibrary.recreateRenderSurface(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void surfaceDestroyed(@NonNull SurfaceHolder surfaceHolder) {
|
||||
mainCanvasSurfaceHolder = null;
|
||||
NativeLibrary.clearSurface(true);
|
||||
}
|
||||
}
|
@ -36,7 +36,7 @@ public abstract class Input {
|
||||
configure();
|
||||
}
|
||||
|
||||
private static final float MIN_WIDTH_HEIGHT = 100;
|
||||
private static final float MIN_WIDTH_HEIGHT = 200;
|
||||
|
||||
public void resize(int diffX, int diffY, int maxWidth, int maxHeight) {
|
||||
var rect = settings.getRect();
|
||||
|
@ -1,56 +0,0 @@
|
||||
package info.cemu.Cemu.inputoverlay;
|
||||
|
||||
|
||||
|
||||
import static info.cemu.Cemu.inputoverlay.InputOverlaySurfaceView.InputMode.EDIT_POSITION;
|
||||
import static info.cemu.Cemu.inputoverlay.InputOverlaySurfaceView.InputMode.EDIT_SIZE;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.view.WindowCompat;
|
||||
import androidx.core.view.WindowInsetsCompat;
|
||||
import androidx.core.view.WindowInsetsControllerCompat;
|
||||
|
||||
import info.cemu.Cemu.R;
|
||||
import info.cemu.Cemu.databinding.ActivityOverlayConfigureBinding;
|
||||
|
||||
public class InputOverlayConfigureActivity extends AppCompatActivity {
|
||||
private Toast toast;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setFullscreen();
|
||||
ActivityOverlayConfigureBinding binding = ActivityOverlayConfigureBinding.inflate(getLayoutInflater());
|
||||
InputOverlaySurfaceView surfaceView = binding.inputConfigureOverlay;
|
||||
surfaceView.setInputMode(EDIT_POSITION);
|
||||
binding.configureModeButton.setOnClickListener(v -> {
|
||||
InputOverlaySurfaceView.InputMode nextMode;
|
||||
int toastTextResId;
|
||||
if (surfaceView.getInputMode() == EDIT_POSITION) {
|
||||
toastTextResId = R.string.input_mode_edit_size;
|
||||
nextMode = EDIT_SIZE;
|
||||
} else {
|
||||
toastTextResId = R.string.input_mode_edit_position;
|
||||
nextMode = EDIT_POSITION;
|
||||
}
|
||||
if (toast != null) {
|
||||
toast.cancel();
|
||||
}
|
||||
toast = Toast.makeText(InputOverlayConfigureActivity.this, toastTextResId, Toast.LENGTH_SHORT);
|
||||
toast.show();
|
||||
surfaceView.setInputMode(nextMode);
|
||||
});
|
||||
binding.resetOverlayButton.setOnClickListener(v -> surfaceView.resetInputs());
|
||||
setContentView(binding.getRoot());
|
||||
}
|
||||
|
||||
private void setFullscreen() {
|
||||
WindowCompat.setDecorFitsSystemWindows(getWindow(), false);
|
||||
WindowInsetsControllerCompat controller = new WindowInsetsControllerCompat(getWindow(), getWindow().getDecorView());
|
||||
controller.hide(WindowInsetsCompat.Type.systemBars());
|
||||
controller.setSystemBarsBehavior(WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE);
|
||||
}
|
||||
}
|
@ -91,14 +91,6 @@ public class InputOverlaySettingsFragment extends Fragment {
|
||||
});
|
||||
genericRecyclerViewAdapter.addRecyclerViewItem(controllerSelection);
|
||||
|
||||
genericRecyclerViewAdapter.addRecyclerViewItem(
|
||||
new ButtonRecyclerViewItem(
|
||||
getString(R.string.configure_inputs_label),
|
||||
getString(R.string.configure_inputs_description),
|
||||
() -> startActivity(new Intent(requireActivity(), InputOverlayConfigureActivity.class))
|
||||
)
|
||||
);
|
||||
|
||||
binding.recyclerView.setAdapter(genericRecyclerViewAdapter);
|
||||
|
||||
return binding.getRoot();
|
||||
|
10
src/android/app/src/main/res/drawable/ic_move.xml
Normal file
10
src/android/app/src/main/res/drawable/ic_move.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M480,880L310,710L367,653L440,726L440,520L235,520L308,592L250,650L80,480L249,311L306,368L234,440L440,440L440,234L367,307L310,250L480,80L650,250L593,307L520,234L520,440L725,440L652,368L710,310L880,480L710,650L653,593L726,520L520,520L520,725L592,652L650,710L480,880Z"/>
|
||||
</vector>
|
10
src/android/app/src/main/res/drawable/ic_resize.xml
Normal file
10
src/android/app/src/main/res/drawable/ic_resize.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M120,840L120,520L200,520L200,704L704,200L520,200L520,120L840,120L840,440L760,440L760,256L256,760L440,760L440,840L120,840Z"/>
|
||||
</vector>
|
@ -1,38 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".inputoverlay.InputOverlayConfigureActivity">
|
||||
|
||||
<info.cemu.Cemu.inputoverlay.InputOverlaySurfaceView
|
||||
android:id="@+id/input_configure_overlay"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<Button
|
||||
android:id="@+id/configure_mode_button"
|
||||
style="?attr/materialIconButtonStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="@string/configure_input_mode_button_desc"
|
||||
app:icon="@drawable/ic_settings"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/reset_overlay_button"
|
||||
style="?attr/materialIconButtonStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="@string/reset_overlay_button_desc"
|
||||
app:icon="@drawable/ic_restart"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</FrameLayout>
|
@ -6,10 +6,18 @@
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".emulation.EmulationFragment">
|
||||
|
||||
<SurfaceView
|
||||
android:id="@+id/main_canvas"
|
||||
<LinearLayout
|
||||
android:id="@+id/canvases_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<SurfaceView
|
||||
android:id="@+id/main_canvas"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1" />
|
||||
</LinearLayout>
|
||||
|
||||
<info.cemu.Cemu.inputoverlay.InputOverlaySurfaceView
|
||||
android:id="@+id/input_overlay"
|
||||
@ -17,7 +25,41 @@
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/inputModeButton"
|
||||
android:id="@+id/finish_edit_inputs_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:text="@string/input_finish_edit_label"
|
||||
android:visibility="gone" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/edit_inputs_layout"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_margin="8dp"
|
||||
android:visibility="gone">
|
||||
|
||||
<Button
|
||||
android:id="@+id/move_inputs_button"
|
||||
style="?attr/materialIconButtonFilledStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:contentDescription="@string/move_inputs_description"
|
||||
app:icon="@drawable/ic_move" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/resize_inputs_button"
|
||||
style="?attr/materialIconButtonFilledStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="@string/resize_inputs_description"
|
||||
app:icon="@drawable/ic_resize" />
|
||||
</LinearLayout>
|
||||
|
||||
<Button
|
||||
android:id="@+id/emulation_settings_button"
|
||||
style="?attr/materialIconButtonStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
|
17
src/android/app/src/main/res/menu/menu_emulation_in_game.xml
Normal file
17
src/android/app/src/main/res/menu/menu_emulation_in_game.xml
Normal file
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item
|
||||
android:id="@+id/replace_tv_with_pad"
|
||||
android:checkable="true"
|
||||
android:title="@string/replace_tv_with_pad" />
|
||||
<item
|
||||
android:id="@+id/show_pad"
|
||||
android:checkable="true"
|
||||
android:title="@string/show_pad" />
|
||||
<item
|
||||
android:id="@+id/edit_inputs"
|
||||
android:title="@string/edit_inputs" />
|
||||
<item
|
||||
android:id="@+id/reset_inputs"
|
||||
android:title="@string/reset_overlay_inputs" />
|
||||
</menu>
|
@ -137,14 +137,30 @@
|
||||
<string name="overlay_position_bottom_right">Bottom right</string>
|
||||
<string name="overlay_position">Position</string>
|
||||
<string name="overlay">Overlay</string>
|
||||
<string name="fps_label">FPS</string>
|
||||
<string name="fps_description">The number of frames per second. Average over last 5 seconds</string>
|
||||
<string name="draw_calls_per_frame_label">Draw calls per frame</string>
|
||||
<string name="draw_calls_per_frame_label_desription">The number of draw calls per frame. Average over last 5 seconds</string>
|
||||
<string name="cpu_usage_label">CPU usage</string>
|
||||
<string name="cpu_usage_description">CPU usage of Cemu in percent</string>
|
||||
<string name="ram_usage_label">RAM usage</string>
|
||||
<string name="ram_usage_description">Cemu RAM usage in MB</string>
|
||||
<string name="vram_usage_label">VRAM usage</string>
|
||||
<string name="fps">FPS</string>
|
||||
<string name="fps_overlay_description">The number of frames per second. Average over last 5 seconds</string>
|
||||
<string name="draw_calls_per_frame">Draw calls per frame</string>
|
||||
<string name="draw_calls_per_frame_overlay_description">The number of draw calls per frame. Average over last 5 seconds</string>
|
||||
<string name="cpu_usage">CPU usage</string>
|
||||
<string name="cpu_usage_overlay_description">CPU usage of Cemu in percent</string>
|
||||
<string name="ram_usage">RAM usage</string>
|
||||
<string name="ram_usage_overlay_description">Cemu RAM usage in MB</string>
|
||||
<string name="vram_usage">VRAM usage</string>
|
||||
<string name="vram_usage_description">The VRAM usage of Cemu in MB</string>
|
||||
<string name="debug">Debug</string>
|
||||
<string name="debug_overlay_description">Displays internal debug information (Vulkan only)</string>
|
||||
<string name="notifications">Notifications</string>
|
||||
<string name="shader_compiler">Shader compiler</string>
|
||||
<string name="shader_compiler_notification_description">Shows a notification after shaders have been compiled</string>
|
||||
<string name="controller_profiles">Controller profiles</string>
|
||||
<string name="controller_profiles_notification_description">Displays the active controller profile when starting a game</string>
|
||||
<string name="friend_list">Friend list</string>
|
||||
<string name="friend_list_notification_description">Shows friend list related data if online</string>
|
||||
<string name="input_finish_edit_label">Done</string>
|
||||
<string name="move_inputs_description">Move inputs</string>
|
||||
<string name="resize_inputs_description">Resize inputs</string>
|
||||
<string name="reset_overlay_inputs">Reset overlay inputs</string>
|
||||
<string name="edit_inputs">Edit inputs</string>
|
||||
<string name="show_pad">Show pad</string>
|
||||
<string name="replace_tv_with_pad">Replace TV with PAD</string>
|
||||
</resources>
|
Loading…
Reference in New Issue
Block a user