From 7be7cf46d13b9debf059489d100d43dfe6b78558 Mon Sep 17 00:00:00 2001 From: SSimco <37044560+SSimco@users.noreply.github.com> Date: Mon, 8 Jul 2024 19:46:53 +0300 Subject: [PATCH] Added overlay settings --- src/android/app/src/main/cpp/native-lib.cpp | 104 ++++++++++++++++++ .../main/java/info/cemu/Cemu/DPadInput.java | 1 - .../java/info/cemu/Cemu/NativeLibrary.java | 56 +++++++++- .../java/info/cemu/Cemu/OptionsFragment.java | 1 + .../cemu/Cemu/OverlaySettingsFragment.java | 74 +++++++++++++ .../res/layout/fragment_overlay_settings.xml | 17 +++ .../res/navigation/nav_settings_graph.xml | 8 ++ .../app/src/main/res/values/strings.xml | 20 ++++ 8 files changed, 278 insertions(+), 3 deletions(-) create mode 100644 src/android/app/src/main/java/info/cemu/Cemu/OverlaySettingsFragment.java create mode 100644 src/android/app/src/main/res/layout/fragment_overlay_settings.xml diff --git a/src/android/app/src/main/cpp/native-lib.cpp b/src/android/app/src/main/cpp/native-lib.cpp index 293d610b..01d4f9e9 100644 --- a/src/android/app/src/main/cpp/native-lib.cpp +++ b/src/android/app/src/main/cpp/native-lib.cpp @@ -413,3 +413,107 @@ Java_info_cemu_Cemu_NativeLibrary_onOverlayAxis([[maybe_unused]] JNIEnv* env, [[ { s_emulationState.getEmulatedController(controllerIndex).setAxisValue(mappingId, value); } + +extern "C" JNIEXPORT jint JNICALL +Java_info_cemu_Cemu_NativeLibrary_getOverlayPosition([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz) +{ + return static_cast(g_config.data().overlay.position); +} + +extern "C" JNIEXPORT void JNICALL +Java_info_cemu_Cemu_NativeLibrary_setOverlayPosition([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jint position) +{ + g_config.data().overlay.position = static_cast(position); + g_config.Save(); +} + +extern "C" JNIEXPORT jboolean JNICALL +Java_info_cemu_Cemu_NativeLibrary_isOverlayFPSEnabled([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz) +{ + return g_config.data().overlay.fps; +} + +extern "C" JNIEXPORT void JNICALL +Java_info_cemu_Cemu_NativeLibrary_setOverlayFPSEnabled([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jboolean enabled) +{ + g_config.data().overlay.fps = enabled; + g_config.Save(); +} + +extern "C" JNIEXPORT jboolean JNICALL +Java_info_cemu_Cemu_NativeLibrary_isOverlayDrawCallsPerFrameEnabled([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz) +{ + return g_config.data().overlay.drawcalls; +} + +extern "C" JNIEXPORT void JNICALL +Java_info_cemu_Cemu_NativeLibrary_setOverlayDrawCallsPerFrameEnabled([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jboolean enabled) +{ + g_config.data().overlay.drawcalls = enabled; + g_config.Save(); +} + +extern "C" JNIEXPORT jboolean JNICALL +Java_info_cemu_Cemu_NativeLibrary_isOverlayCPUUsageEnabled([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz) +{ + return g_config.data().overlay.cpu_usage; +} + +extern "C" JNIEXPORT void JNICALL +Java_info_cemu_Cemu_NativeLibrary_setOverlayCPUUsageEnabled([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jboolean enabled) +{ + g_config.data().overlay.cpu_usage = enabled; + g_config.Save(); +} + +extern "C" JNIEXPORT jboolean JNICALL +Java_info_cemu_Cemu_NativeLibrary_isOverlayCPUPerCoreUsageEnabled([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz) +{ + return g_config.data().overlay.cpu_per_core_usage; +} + +extern "C" JNIEXPORT void JNICALL +Java_info_cemu_Cemu_NativeLibrary_setOverlayCPUPerCoreUsageEnabled([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jboolean enabled) +{ + g_config.data().overlay.cpu_per_core_usage = enabled; + g_config.Save(); +} + +extern "C" JNIEXPORT jboolean JNICALL +Java_info_cemu_Cemu_NativeLibrary_isOverlayRAMUsageEnabled([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz) +{ + return g_config.data().overlay.ram_usage; +} + +extern "C" JNIEXPORT void JNICALL +Java_info_cemu_Cemu_NativeLibrary_setOverlayRAMUsageEnabled([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jboolean enabled) +{ + g_config.data().overlay.ram_usage = enabled; + g_config.Save(); +} + +extern "C" JNIEXPORT jboolean JNICALL +Java_info_cemu_Cemu_NativeLibrary_isOverlayVRAMUsageEnabled([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz) +{ + return g_config.data().overlay.vram_usage; +} + +extern "C" JNIEXPORT void JNICALL +Java_info_cemu_Cemu_NativeLibrary_setOverlayVRAMUsageEnabled([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jboolean enabled) +{ + g_config.data().overlay.vram_usage = enabled; + g_config.Save(); +} + +extern "C" JNIEXPORT jboolean JNICALL +Java_info_cemu_Cemu_NativeLibrary_isOverlayDebugEnabled([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz) +{ + return g_config.data().overlay.debug; +} + +extern "C" JNIEXPORT void JNICALL +Java_info_cemu_Cemu_NativeLibrary_setOverlayDebugEnabled([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jboolean enabled) +{ + g_config.data().overlay.debug = enabled; + g_config.Save(); +} \ No newline at end of file diff --git a/src/android/app/src/main/java/info/cemu/Cemu/DPadInput.java b/src/android/app/src/main/java/info/cemu/Cemu/DPadInput.java index 87b0f7c8..afaec324 100644 --- a/src/android/app/src/main/java/info/cemu/Cemu/DPadInput.java +++ b/src/android/app/src/main/java/info/cemu/Cemu/DPadInput.java @@ -95,7 +95,6 @@ public class DPadInput extends Input { iconDpadRightPressed, iconDpadRightNotPressed ); - Log.i("INPUT", "Dpad reconfigure: " + rect); } public DPadInput(Resources resources, @DrawableRes int backgroundId, @DrawableRes int pressedButtonId, @DrawableRes int notPressedButtonId, ButtonStateChangeListener buttonStateChangeListener, InputOverlaySettingsProvider.InputOverlaySettings settings) { diff --git a/src/android/app/src/main/java/info/cemu/Cemu/NativeLibrary.java b/src/android/app/src/main/java/info/cemu/Cemu/NativeLibrary.java index 0aa1e735..27db83d3 100644 --- a/src/android/app/src/main/java/info/cemu/Cemu/NativeLibrary.java +++ b/src/android/app/src/main/java/info/cemu/Cemu/NativeLibrary.java @@ -29,8 +29,6 @@ public class NativeLibrary { boolean exists(String uri); } - public static native void setFileSystemCallbacks(FileSystemCallbacks fileSystemCallbacks); - public static native void setDPI(float dpi); public static native void setSurface(Surface surface, boolean isMainCanvas); @@ -383,4 +381,58 @@ public class NativeLibrary { public static native void onOverlayButton(int controllerIndex, int mappingId, boolean value); public static native void onOverlayAxis(int controllerIndex, int mappingId, float value); + + static final int OVERLAY_SCREEN_POSITION_DISABLED = 0; + static final int OVERLAY_SCREEN_POSITION_TOP_LEFT = 1; + static final int OVERLAY_SCREEN_POSITION_TOP_CENTER = 2; + static final int OVERLAY_SCREEN_POSITION_TOP_RIGHT = 3; + static final int OVERLAY_SCREEN_POSITION_BOTTOM_LEFT = 4; + static final int OVERLAY_SCREEN_POSITION_BOTTOM_CENTER = 5; + static final int OVERLAY_SCREEN_POSITION_BOTTOM_RIGHT = 6; + + public static int overlayScreenPositionToResourceNameId(int overlayScreenPosition) { + return switch (overlayScreenPosition) { + case OVERLAY_SCREEN_POSITION_DISABLED -> R.string.overlay_position_disabled; + case OVERLAY_SCREEN_POSITION_TOP_LEFT -> R.string.overlay_position_top_left; + case OVERLAY_SCREEN_POSITION_TOP_CENTER -> R.string.overlay_position_top_center; + case OVERLAY_SCREEN_POSITION_TOP_RIGHT -> R.string.overlay_position_top_right; + case OVERLAY_SCREEN_POSITION_BOTTOM_LEFT -> R.string.overlay_position_bottom_left; + case OVERLAY_SCREEN_POSITION_BOTTOM_CENTER -> R.string.overlay_position_bottom_center; + case OVERLAY_SCREEN_POSITION_BOTTOM_RIGHT -> R.string.overlay_position_bottom_right; + default -> + throw new RuntimeException("Invalid overlay position: " + overlayScreenPosition); + }; + } + + public static native int getOverlayPosition(); + + public static native void setOverlayPosition(int position); + + public static native boolean isOverlayFPSEnabled(); + + public static native void setOverlayFPSEnabled(boolean enabled); + + public static native boolean isOverlayDrawCallsPerFrameEnabled(); + + public static native void setOverlayDrawCallsPerFrameEnabled(boolean enabled); + + public static native boolean isOverlayCPUUsageEnabled(); + + public static native void setOverlayCPUUsageEnabled(boolean enabled); + + public static native boolean isOverlayCPUPerCoreUsageEnabled(); + + public static native void setOverlayCPUPerCoreUsageEnabled(boolean enabled); + + public static native boolean isOverlayRAMUsageEnabled(); + + public static native void setOverlayRAMUsageEnabled(boolean enabled); + + public static native boolean isOverlayVRAMUsageEnabled(); + + public static native void setOverlayVRAMUsageEnabled(boolean enabled); + + public static native boolean isOverlayDebugEnabled(); + + public static native void setOverlayDebugEnabled(boolean enabled); } diff --git a/src/android/app/src/main/java/info/cemu/Cemu/OptionsFragment.java b/src/android/app/src/main/java/info/cemu/Cemu/OptionsFragment.java index 83bb18ba..184f434d 100644 --- a/src/android/app/src/main/java/info/cemu/Cemu/OptionsFragment.java +++ b/src/android/app/src/main/java/info/cemu/Cemu/OptionsFragment.java @@ -52,6 +52,7 @@ public class OptionsFragment extends Fragment { genericRecyclerViewAdapter.addRecyclerViewItem(new SimpleButtonRecyclerViewItem(getString(R.string.graphics_settings), () -> NavHostFragment.findNavController(OptionsFragment.this).navigate(R.id.action_optionsFragment_to_graphicSettingsFragment))); genericRecyclerViewAdapter.addRecyclerViewItem(new SimpleButtonRecyclerViewItem(getString(R.string.audio_settings), () -> NavHostFragment.findNavController(OptionsFragment.this).navigate(R.id.action_optionsFragment_to_audioSettingsFragment))); genericRecyclerViewAdapter.addRecyclerViewItem(new SimpleButtonRecyclerViewItem(getString(R.string.graphic_packs), () -> NavHostFragment.findNavController(OptionsFragment.this).navigate(R.id.action_optionsFragment_to_graphicPacksRootFragment))); + genericRecyclerViewAdapter.addRecyclerViewItem(new SimpleButtonRecyclerViewItem(getString(R.string.overlay), () -> NavHostFragment.findNavController(OptionsFragment.this).navigate(R.id.action_optionsFragment_to_overlaySettingsFragment))); binding.optionsRecyclerView.setAdapter(genericRecyclerViewAdapter); return binding.getRoot(); diff --git a/src/android/app/src/main/java/info/cemu/Cemu/OverlaySettingsFragment.java b/src/android/app/src/main/java/info/cemu/Cemu/OverlaySettingsFragment.java new file mode 100644 index 00000000..5787f21d --- /dev/null +++ b/src/android/app/src/main/java/info/cemu/Cemu/OverlaySettingsFragment.java @@ -0,0 +1,74 @@ +package info.cemu.Cemu; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.fragment.app.Fragment; + +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import info.cemu.Cemu.databinding.FragmentOverlaySettingsBinding; + +public class OverlaySettingsFragment extends Fragment { + + @Override + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + FragmentOverlaySettingsBinding binding = FragmentOverlaySettingsBinding.inflate(inflater, container, false); + + GenericRecyclerViewAdapter genericRecyclerViewAdapter = new GenericRecyclerViewAdapter(); + + var overlayPositionChoices = Stream.of( + NativeLibrary.OVERLAY_SCREEN_POSITION_DISABLED, + NativeLibrary.OVERLAY_SCREEN_POSITION_TOP_LEFT, + NativeLibrary.OVERLAY_SCREEN_POSITION_TOP_CENTER, + NativeLibrary.OVERLAY_SCREEN_POSITION_TOP_RIGHT, + NativeLibrary.OVERLAY_SCREEN_POSITION_BOTTOM_LEFT, + NativeLibrary.OVERLAY_SCREEN_POSITION_BOTTOM_CENTER, + NativeLibrary.OVERLAY_SCREEN_POSITION_BOTTOM_RIGHT) + .map(position -> new SelectionAdapter.ChoiceItem<>(t -> t.setText(NativeLibrary.overlayScreenPositionToResourceNameId(position)), position)) + .collect(Collectors.toList()); + int overlayPosition = NativeLibrary.getOverlayPosition(); + SelectionAdapter tvChannelsSelectionAdapter = new SelectionAdapter<>(overlayPositionChoices, overlayPosition); + SingleSelectionRecyclerViewItem tvChannelsModeSelection = new SingleSelectionRecyclerViewItem<>(getString(R.string.overlay_position), + getString(NativeLibrary.overlayScreenPositionToResourceNameId(overlayPosition)), tvChannelsSelectionAdapter, + (position, selectionRecyclerViewItem) -> { + NativeLibrary.setOverlayPosition(position); + selectionRecyclerViewItem.setDescription(getString(NativeLibrary.overlayScreenPositionToResourceNameId(position))); + }); + genericRecyclerViewAdapter.addRecyclerViewItem(tvChannelsModeSelection); + + CheckboxRecyclerViewItem overlayFps = new CheckboxRecyclerViewItem(getString(R.string.fps_label), + getString(R.string.fps_description), NativeLibrary.isOverlayFPSEnabled(), + NativeLibrary::setOverlayFPSEnabled); + genericRecyclerViewAdapter.addRecyclerViewItem(overlayFps); + + CheckboxRecyclerViewItem drawCallsCheckbox = new CheckboxRecyclerViewItem(getString(R.string.draw_calls_per_frame_label), + getString(R.string.draw_calls_per_frame_label_desription), NativeLibrary.isOverlayDrawCallsPerFrameEnabled(), + NativeLibrary::setOverlayDrawCallsPerFrameEnabled); + genericRecyclerViewAdapter.addRecyclerViewItem(drawCallsCheckbox); + + CheckboxRecyclerViewItem cpuUsageCheckbox = new CheckboxRecyclerViewItem(getString(R.string.cpu_usage_label), + getString(R.string.cpu_usage_description), NativeLibrary.isOverlayCPUUsageEnabled(), + NativeLibrary::setOverlayCPUUsageEnabled); + genericRecyclerViewAdapter.addRecyclerViewItem(cpuUsageCheckbox); + + CheckboxRecyclerViewItem ramUsageCheckbox = new CheckboxRecyclerViewItem(getString(R.string.ram_usage_label), + getString(R.string.ram_usage_description), NativeLibrary.isOverlayRAMUsageEnabled(), + NativeLibrary::setOverlayRAMUsageEnabled); + genericRecyclerViewAdapter.addRecyclerViewItem(ramUsageCheckbox); + + CheckboxRecyclerViewItem vramUsageCheckbox = new CheckboxRecyclerViewItem(getString(R.string.vram_usage_label), + getString(R.string.vram_usage_description), NativeLibrary.isOverlayVRAMUsageEnabled(), + NativeLibrary::setOverlayVRAMUsageEnabled); + genericRecyclerViewAdapter.addRecyclerViewItem(vramUsageCheckbox); + + binding.audioSettingsRecyclerView.setAdapter(genericRecyclerViewAdapter); + + return binding.getRoot(); + } +} \ No newline at end of file diff --git a/src/android/app/src/main/res/layout/fragment_overlay_settings.xml b/src/android/app/src/main/res/layout/fragment_overlay_settings.xml new file mode 100644 index 00000000..6acf8b84 --- /dev/null +++ b/src/android/app/src/main/res/layout/fragment_overlay_settings.xml @@ -0,0 +1,17 @@ + + + + + + \ No newline at end of file diff --git a/src/android/app/src/main/res/navigation/nav_settings_graph.xml b/src/android/app/src/main/res/navigation/nav_settings_graph.xml index 02c437c2..b5eeb5d1 100644 --- a/src/android/app/src/main/res/navigation/nav_settings_graph.xml +++ b/src/android/app/src/main/res/navigation/nav_settings_graph.xml @@ -55,6 +55,9 @@ + + Reset the positions and sizes of the inputs Vibrate Enable vibrate on touch + Overlay settings + Disabled + Top left + Top center + Top right + Bottom left + Bottom center + Bottom right + Position + Overlay + FPS + The number of frames per second. Average over last 5 seconds + Draw calls per frame + The number of draw calls per frame. Average over last 5 seconds + CPU usage + CPU usage of Cemu in percent + RAM usage + Cemu RAM usage in MB + VRAM usage + The VRAM usage of Cemu in MB \ No newline at end of file