Add "Fullscreen UI"

This commit is contained in:
Connor McLaughlin 2021-01-30 21:37:49 +10:00
parent 0cdd1a70c0
commit 61e4e6f140
27 changed files with 6109 additions and 13 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

BIN
data/resources/duck.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

BIN
data/resources/flag-eu.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

BIN
data/resources/flag-jp.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

BIN
data/resources/flag-uc.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

BIN
data/resources/star-0.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

BIN
data/resources/star-1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6 KiB

BIN
data/resources/star-2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

BIN
data/resources/star-3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

BIN
data/resources/star-4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

BIN
data/resources/star-5.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

View file

@ -5,6 +5,10 @@ add_library(frontend-common
controller_interface.h
cubeb_audio_stream.cpp
cubeb_audio_stream.h
fullscreen_ui.cpp
fullscreen_ui.h
fullscreen_ui_progress_callback.cpp
fullscreen_ui_progress_callback.h
game_list.cpp
game_list.h
game_settings.cpp
@ -13,6 +17,8 @@ add_library(frontend-common
icon.h
ini_settings_interface.cpp
ini_settings_interface.h
imgui_fullscreen.h
imgui_fullscreen.cpp
imgui_impl_opengl3.cpp
imgui_impl_opengl3.h
imgui_impl_vulkan.cpp

File diff suppressed because it is too large Load diff

View file

@ -21,6 +21,7 @@
#include "core/texture_replacements.h"
#include "core/timers.h"
#include "cubeb_audio_stream.h"
#include "fullscreen_ui.h"
#include "game_list.h"
#include "icon.h"
#include "imgui.h"
@ -786,7 +787,7 @@ void CommonHostInterface::OnSystemPaused(bool paused)
if (paused)
{
if (IsFullscreen())
if (IsFullscreen() && !m_fullscreen_ui_enabled)
SetFullscreen(false);
StopControllerRumble();
@ -827,6 +828,12 @@ void CommonHostInterface::OnControllerTypeChanged(u32 slot)
void CommonHostInterface::DrawImGuiWindows()
{
if (m_fullscreen_ui_enabled)
{
FullscreenUI::Render();
return;
}
if (System::IsValid())
{
DrawDebugWindows();
@ -1569,6 +1576,11 @@ void CommonHostInterface::RegisterHotkeys()
void CommonHostInterface::RegisterGeneralHotkeys()
{
RegisterHotkey(StaticString(TRANSLATABLE("Hotkeys", "General")), StaticString("OpenQuickMenu"),
TRANSLATABLE("Hotkeys", "Open Quick Menu"), [this](bool pressed) {
if (pressed && m_fullscreen_ui_enabled)
FullscreenUI::OpenQuickMenu();
});
RegisterHotkey(StaticString(TRANSLATABLE("Hotkeys", "General")), StaticString("FastForward"),
TRANSLATABLE("Hotkeys", "Fast Forward"), [this](bool pressed) { SetFastForwardEnabled(pressed); });
@ -2869,7 +2881,10 @@ std::unique_ptr<ByteStream> CommonHostInterface::OpenPackageFile(const char* pat
bool CommonHostInterface::SetControllerNavigationButtonState(FrontendCommon::ControllerNavigationButton button,
bool pressed)
{
return false;
if (!m_fullscreen_ui_enabled)
return false;
return FullscreenUI::SetControllerNavInput(button, pressed);
}
#ifdef WITH_DISCORD_PRESENCE

View file

@ -130,6 +130,9 @@ public:
/// Returns true if running in batch mode, i.e. exit after emulation.
ALWAYS_INLINE bool InBatchMode() const { return m_command_line_flags.batch_mode; }
/// Returns true if the fullscreen UI is enabled.
ALWAYS_INLINE bool IsFullscreenUIEnabled() const { return m_fullscreen_ui_enabled; }
/// Parses command line parameters for all frontends.
bool ParseCommandLineParameters(int argc, char* argv[], std::unique_ptr<SystemBootParameters>* out_boot_params);
@ -383,6 +386,7 @@ protected:
std::deque<OSDMessage> m_osd_messages;
std::mutex m_osd_messages_lock;
bool m_fullscreen_ui_enabled = false;
bool m_frame_step_request = false;
bool m_fast_forward_enabled = false;
bool m_turbo_enabled = false;
@ -390,6 +394,17 @@ protected:
bool m_throttler_enabled = true;
bool m_display_all_frames = true;
union
{
u8 bits;
// running in batch mode? i.e. exit after stopping emulation
BitField<u8, bool, 0, 1> batch_mode;
// disable controller interface (buggy devices with SDL)
BitField<u8, bool, 1, 1> disable_controller_interface;
} m_command_line_flags = {};
private:
void InitializeUserDirectory();
void RegisterGeneralHotkeys();
@ -434,17 +449,6 @@ private:
};
std::vector<ControllerRumbleState> m_controller_vibration_motors;
union
{
u8 bits;
// running in batch mode? i.e. exit after stopping emulation
BitField<u8, bool, 0, 1> batch_mode;
// disable controller interface (buggy devices with SDL)
BitField<u8, bool, 1, 1> disable_controller_interface;
} m_command_line_flags = {};
#ifdef WITH_DISCORD_PRESENCE
// discord rich presence
bool m_discord_presence_enabled = false;

View file

@ -88,9 +88,12 @@
<ClCompile Include="cubeb_audio_stream.cpp" />
<ClCompile Include="d3d11_host_display.cpp" />
<ClCompile Include="dinput_controller_interface.cpp" />
<ClCompile Include="fullscreen_ui.cpp" />
<ClCompile Include="fullscreen_ui_progress_callback.cpp" />
<ClCompile Include="game_list.cpp" />
<ClCompile Include="game_settings.cpp" />
<ClCompile Include="icon.cpp" />
<ClCompile Include="imgui_fullscreen.cpp" />
<ClCompile Include="imgui_impl_dx11.cpp" />
<ClCompile Include="imgui_impl_opengl3.cpp" />
<ClCompile Include="imgui_impl_vulkan.cpp" />
@ -113,9 +116,12 @@
<ClInclude Include="cubeb_audio_stream.h" />
<ClInclude Include="d3d11_host_display.h" />
<ClInclude Include="dinput_controller_interface.h" />
<ClInclude Include="fullscreen_ui.h" />
<ClInclude Include="fullscreen_ui_progress_callback.h" />
<ClInclude Include="game_list.h" />
<ClInclude Include="game_settings.h" />
<ClInclude Include="icon.h" />
<ClInclude Include="imgui_fullscreen.h" />
<ClInclude Include="imgui_impl_dx11.h" />
<ClInclude Include="imgui_impl_opengl3.h" />
<ClInclude Include="imgui_impl_vulkan.h" />

View file

@ -24,6 +24,9 @@
<ClCompile Include="postprocessing_chain.cpp" />
<ClCompile Include="cubeb_audio_stream.cpp" />
<ClCompile Include="dinput_controller_interface.cpp" />
<ClCompile Include="imgui_fullscreen.cpp" />
<ClCompile Include="fullscreen_ui.cpp" />
<ClCompile Include="fullscreen_ui_progress_callback.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="icon.h" />
@ -49,6 +52,9 @@
<ClInclude Include="postprocessing_chain.h" />
<ClInclude Include="cubeb_audio_stream.h" />
<ClInclude Include="dinput_controller_interface.h" />
<ClInclude Include="imgui_fullscreen.h" />
<ClInclude Include="fullscreen_ui.h" />
<ClInclude Include="fullscreen_ui_progress_callback.h" />
</ItemGroup>
<ItemGroup>
<None Include="font_roboto_regular.inl" />

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,63 @@
#pragma once
#include "common/types.h"
class CommonHostInterface;
class SettingsInterface;
struct Settings;
namespace FrontendCommon {
enum class ControllerNavigationButton : u32;
}
namespace FullscreenUI {
enum class MainWindowType
{
None,
Landing,
GameList,
Settings,
QuickMenu,
MoreQuickMenu
};
enum class SettingsPage
{
InterfaceSettings,
GameListSettings,
ConsoleSettings,
EmulationSettings,
BIOSSettings,
ControllerSettings,
HotkeySettings,
MemoryCardSettings,
DisplaySettings,
EnhancementSettings,
AudioSettings,
AdvancedSettings,
Count
};
bool Initialize(CommonHostInterface* host_interface, SettingsInterface* settings_interface);
bool HasActiveWindow();
void SystemCreated();
void SystemDestroyed();
void SystemPaused(bool paused);
void OpenQuickMenu();
void CloseQuickMenu();
void Shutdown();
void Render();
void EnsureGameListLoaded();
Settings& GetSettingsCopy();
void SaveAndApplySettings();
void SetDebugMenuEnabled(bool enabled, bool save_to_ini = false);
/// Only ImGuiNavInput_Activate, ImGuiNavInput_Cancel, and DPad should be forwarded.
/// Returns true if the UI consumed the event, and it should not execute the normal handler.
bool SetControllerNavInput(FrontendCommon::ControllerNavigationButton button, bool value);
/// Forwards the controller navigation to ImGui for fullscreen navigation. Call before NewFrame().
void SetImGuiNavInputs();
} // namespace FullscreenUI

View file

@ -0,0 +1,117 @@
#include "fullscreen_ui_progress_callback.h"
#include "common/log.h"
#include "core/host_interface.h"
#include "imgui_fullscreen.h"
Log_SetChannel(ProgressCallback);
namespace FullscreenUI {
ProgressCallback::ProgressCallback(String name) : BaseProgressCallback(), m_name(std::move(name))
{
ImGuiFullscreen::OpenBackgroundProgressDialog(m_name, "", 0, 100, 0);
}
ProgressCallback::~ProgressCallback()
{
ImGuiFullscreen::CloseBackgroundProgressDialog(m_name);
}
void ProgressCallback::PushState()
{
BaseProgressCallback::PushState();
}
void ProgressCallback::PopState()
{
BaseProgressCallback::PopState();
Redraw(true);
}
void ProgressCallback::SetCancellable(bool cancellable)
{
BaseProgressCallback::SetCancellable(cancellable);
Redraw(true);
}
void ProgressCallback::SetTitle(const char* title)
{
// todo?
}
void ProgressCallback::SetStatusText(const char* text)
{
BaseProgressCallback::SetStatusText(text);
Redraw(true);
}
void ProgressCallback::SetProgressRange(u32 range)
{
u32 last_range = m_progress_range;
BaseProgressCallback::SetProgressRange(range);
if (m_progress_range != last_range)
Redraw(false);
}
void ProgressCallback::SetProgressValue(u32 value)
{
u32 lastValue = m_progress_value;
BaseProgressCallback::SetProgressValue(value);
if (m_progress_value != lastValue)
Redraw(false);
}
void ProgressCallback::Redraw(bool force)
{
const int percent =
static_cast<int>((static_cast<float>(m_progress_value) / static_cast<float>(m_progress_range)) * 100.0f);
if (percent == m_last_progress_percent && !force)
return;
m_last_progress_percent = percent;
ImGuiFullscreen::UpdateBackgroundProgressDialog(
m_name, m_status_text.GetCharArray(), 0, 100, percent);
}
void ProgressCallback::DisplayError(const char* message)
{
Log_ErrorPrint(message);
}
void ProgressCallback::DisplayWarning(const char* message)
{
Log_WarningPrint(message);
}
void ProgressCallback::DisplayInformation(const char* message)
{
Log_InfoPrint(message);
}
void ProgressCallback::DisplayDebugMessage(const char* message)
{
Log_DevPrint(message);
}
void ProgressCallback::ModalError(const char* message)
{
Log_ErrorPrint(message);
g_host_interface->ReportError(message);
}
bool ProgressCallback::ModalConfirmation(const char* message)
{
Log_InfoPrint(message);
return g_host_interface->ConfirmMessage(message);
}
void ProgressCallback::ModalInformation(const char* message)
{
Log_InfoPrint(message);
g_host_interface->ReportMessage(message);
}
} // namespace FullscreenUI

View file

@ -0,0 +1,38 @@
#pragma once
#include "common/progress_callback.h"
#include "common/string.h"
namespace FullscreenUI {
class ProgressCallback final : public BaseProgressCallback
{
public:
ProgressCallback(String name);
~ProgressCallback() override;
void PushState() override;
void PopState() override;
void SetCancellable(bool cancellable) override;
void SetTitle(const char* title) override;
void SetStatusText(const char* text) override;
void SetProgressRange(u32 range) override;
void SetProgressValue(u32 value) override;
void DisplayError(const char* message) override;
void DisplayWarning(const char* message) override;
void DisplayInformation(const char* message) override;
void DisplayDebugMessage(const char* message) override;
void ModalError(const char* message) override;
bool ModalConfirmation(const char* message) override;
void ModalInformation(const char* message) override;
private:
void Redraw(bool force);
String m_name;
int m_last_progress_percent = -1;
};
} // namespace FullscreenUI

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,226 @@
#pragma once
#include "common/types.h"
#include "imgui.h"
#include <functional>
#include <string>
namespace ImGuiFullscreen {
#define HEX_TO_IMVEC4(hex, alpha) \
ImVec4(static_cast<float>((hex >> 16) & 0xFFu) / 255.0f, static_cast<float>((hex >> 8) & 0xFFu) / 255.0f, \
static_cast<float>(hex & 0xFFu) / 255.0f, static_cast<float>(alpha) / 255.0f)
static constexpr float LAYOUT_SCREEN_WIDTH = 1280.0f;
static constexpr float LAYOUT_SCREEN_HEIGHT = 720.0f;
static constexpr float LAYOUT_LARGE_FONT_SIZE = 26.0f;
static constexpr float LAYOUT_MEDIUM_FONT_SIZE = 16.0f;
static constexpr float LAYOUT_SMALL_FONT_SIZE = 10.0f;
static constexpr float LAYOUT_MENU_BUTTON_HEIGHT = 50.0f;
static constexpr float LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY = 26.0f;
static constexpr float LAYOUT_MENU_BUTTON_X_PADDING = 15.0f;
static constexpr float LAYOUT_MENU_BUTTON_Y_PADDING = 10.0f;
extern ImFont* g_standard_font;
extern ImFont* g_medium_font;
extern ImFont* g_large_font;
extern float g_layout_scale;
extern float g_layout_padding_left;
extern float g_layout_padding_top;
static ALWAYS_INLINE float DPIScale(float v)
{
return ImGui::GetIO().DisplayFramebufferScale.x * v;
}
static ALWAYS_INLINE float DPIScale(int v)
{
return ImGui::GetIO().DisplayFramebufferScale.x * static_cast<float>(v);
}
static ALWAYS_INLINE ImVec2 DPIScale(const ImVec2& v)
{
const ImVec2& fbs = ImGui::GetIO().DisplayFramebufferScale;
return ImVec2(v.x * fbs.x, v.y * fbs.y);
}
static ALWAYS_INLINE float WindowWidthScale(float v)
{
return ImGui::GetWindowWidth() * v;
}
static ALWAYS_INLINE float WindowHeightScale(float v)
{
return ImGui::GetWindowHeight() * v;
}
static ALWAYS_INLINE float LayoutScale(float v)
{
return g_layout_scale * v;
}
static ALWAYS_INLINE ImVec2 LayoutScale(const ImVec2& v)
{
return ImVec2(v.x * g_layout_scale, v.y * g_layout_scale);
}
static ALWAYS_INLINE ImVec2 LayoutScale(float x, float y)
{
return ImVec2(x * g_layout_scale, y * g_layout_scale);
}
static ALWAYS_INLINE ImVec4 UIPrimaryColor()
{
return HEX_TO_IMVEC4(0x212121, 0xff);
}
static ALWAYS_INLINE ImVec4 UIPrimaryLightColor()
{
return HEX_TO_IMVEC4(0x484848, 0xff);
}
static ALWAYS_INLINE ImVec4 UIPrimaryDarkColor()
{
return HEX_TO_IMVEC4(0x484848, 0xff);
}
static ALWAYS_INLINE ImVec4 UIPrimaryTextColor()
{
return HEX_TO_IMVEC4(0xffffff, 0xff);
}
static ALWAYS_INLINE ImVec4 UIPrimaryDisabledTextColor()
{
return HEX_TO_IMVEC4(0xaaaaaa, 0xff);
}
static ALWAYS_INLINE ImVec4 UITextHighlightColor()
{
return HEX_TO_IMVEC4(0x90caf9, 0xff);
}
static ALWAYS_INLINE ImVec4 UIPrimaryLineColor()
{
return HEX_TO_IMVEC4(0xffffff, 0xff);
}
static ALWAYS_INLINE ImVec4 UISecondaryColor()
{
return HEX_TO_IMVEC4(0x1565c0, 0xff);
}
static ALWAYS_INLINE ImVec4 UISecondaryLightColor()
{
return HEX_TO_IMVEC4(0x5e92f3, 0xff);
}
static ALWAYS_INLINE ImVec4 UISecondaryDarkColor()
{
return HEX_TO_IMVEC4(0x003c8f, 0xff);
}
static ALWAYS_INLINE ImVec4 UISecondaryTextColor()
{
return HEX_TO_IMVEC4(0xffffff, 0xff);
}
void SetFontFilename(std::string filename);
void SetIconFontFilename(std::string icon_font_filename);
void SetIconFontData(std::vector<u8> data);
void SetFontSize(float size_pixels);
void SetFontGlyphRanges(const ImWchar* glyph_ranges);
/// Changes the menu bar size. Don't forget to call UpdateLayoutScale() and UpdateFonts().
void SetMenuBarSize(float size);
/// Rebuilds fonts to a new scale if needed. Returns true if fonts have changed and the texture needs updating.
bool UpdateFonts();
bool UpdateLayoutScale();
void BeginLayout();
void EndLayout();
void DrawWindowTitle(const char* title);
bool BeginFullscreenColumns(const char* title = nullptr);
void EndFullscreenColumns();
bool BeginFullscreenColumnWindow(float start, float end, const char* name,
const ImVec4& background = HEX_TO_IMVEC4(0x212121, 0xFF));
void EndFullscreenColumnWindow();
bool BeginFullscreenWindow(float left, float top, float width, float height, const char* name,
const ImVec4& background = HEX_TO_IMVEC4(0x212121, 0xFF), float rounding = 0.0f,
float padding = 0.0f, ImGuiWindowFlags flags = 0);
void EndFullscreenWindow();
void BeginMenuButtons(u32 num_items = 0, float y_align = 0.0f, float x_padding = LAYOUT_MENU_BUTTON_X_PADDING,
float y_padding = LAYOUT_MENU_BUTTON_Y_PADDING, float item_height = LAYOUT_MENU_BUTTON_HEIGHT);
void EndMenuButtons();
bool MenuButtonFrame(const char* str_id, bool enabled, float height, bool* visible, bool* hovered, ImVec2* min,
ImVec2* max, ImGuiButtonFlags flags = 0);
void MenuHeading(const char* title, bool draw_line = true);
bool ActiveButton(const char* title, bool is_active, bool enabled = true,
float height = LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY, ImFont* font = g_large_font);
bool MenuButton(const char* title, const char* summary, bool enabled = true, float height = LAYOUT_MENU_BUTTON_HEIGHT,
ImFont* font = g_large_font, ImFont* summary_font = g_medium_font);
bool MenuButtonWithValue(const char* title, const char* summary, const char* value, bool enabled = true,
float height = LAYOUT_MENU_BUTTON_HEIGHT, ImFont* font = g_large_font,
ImFont* summary_font = g_medium_font);
bool MenuImageButton(const char* title, const char* summary, ImTextureID user_texture_id, const ImVec2& image_size,
bool enabled = true, float height = LAYOUT_MENU_BUTTON_HEIGHT,
const ImVec2& uv0 = ImVec2(0.0f, 0.0f), const ImVec2& uv1 = ImVec2(1.0f, 1.0f),
ImFont* font = g_large_font, ImFont* summary_font = g_medium_font);
bool ToggleButton(const char* title, const char* summary, bool* v, bool enabled = true,
float height = LAYOUT_MENU_BUTTON_HEIGHT, ImFont* font = g_large_font,
ImFont* summary_font = g_medium_font);
bool RangeButton(const char* title, const char* summary, s32* value, s32 min, s32 max, s32 increment,
const char* format = "%d", bool enabled = true, float height = LAYOUT_MENU_BUTTON_HEIGHT,
ImFont* font = g_large_font, ImFont* summary_font = g_medium_font);
bool RangeButton(const char* title, const char* summary, float* value, float min, float max, float increment,
const char* format = "%f", bool enabled = true, float height = LAYOUT_MENU_BUTTON_HEIGHT,
ImFont* font = g_large_font, ImFont* summary_font = g_medium_font);
bool EnumChoiceButtonImpl(const char* title, const char* summary, s32* value_pointer,
const char* (*to_display_name_function)(s32 value, void* opaque), void* opaque, u32 count,
bool enabled, float height, ImFont* font, ImFont* summary_font);
template<typename DataType, typename CountType>
static ALWAYS_INLINE bool EnumChoiceButton(const char* title, const char* summary, DataType* value_pointer,
const char* (*to_display_name_function)(DataType value), CountType count,
bool enabled = true, float height = LAYOUT_MENU_BUTTON_HEIGHT,
ImFont* font = g_large_font, ImFont* summary_font = g_medium_font)
{
s32 value = static_cast<s32>(*value_pointer);
auto to_display_name_wrapper = [](s32 value, void* opaque) -> const char* {
return (*static_cast<decltype(to_display_name_function)*>(opaque))(static_cast<DataType>(value));
};
if (EnumChoiceButtonImpl(title, summary, &value, to_display_name_wrapper, &to_display_name_function,
static_cast<u32>(count), enabled, height, font, summary_font))
{
*value_pointer = static_cast<DataType>(value);
return true;
}
else
{
return false;
}
}
using FileSelectorCallback = std::function<void(const std::string& path)>;
using FileSelectorFilters = std::vector<std::string>;
void OpenFileSelector(const char* title, bool select_directory, FileSelectorCallback callback,
FileSelectorFilters filters = FileSelectorFilters(),
std::string initial_directory = std::string());
void CloseFileSelector();
using ChoiceDialogCallback = std::function<void(s32 index, const std::string& title, bool checked)>;
using ChoiceDialogOptions = std::vector<std::pair<std::string, bool>>;
void OpenChoiceDialog(const char* title, bool checkable, ChoiceDialogOptions options, ChoiceDialogCallback callback);
void CloseChoiceDialog();
void OpenBackgroundProgressDialog(const char* str_id, std::string message, s32 min, s32 max, s32 value);
void UpdateBackgroundProgressDialog(const char* str_id, std::string message, s32 min, s32 max, s32 value);
void CloseBackgroundProgressDialog(const char* str_id);
} // namespace ImGuiFullscreen