diff --git a/Client Release build.bat b/Client Release build.bat
new file mode 100644
index 00000000..caa4044d
--- /dev/null
+++ b/Client Release build.bat
@@ -0,0 +1,9 @@
+@echo off
+call "C:\Program Files\Microsoft Visual Studio\18\Community\VC\Auxiliary\Build\vcvars64.bat"
+
+rem Regenerate build system using the windows64 preset (clears stale cache)
+if exist build\windows64\CMakeCache.txt del build\windows64\CMakeCache.txt
+cmake --preset windows64
+if %errorlevel% neq 0 exit /b %errorlevel%
+
+cmake --build build\windows64 --config Release --target Minecraft.Client
\ No newline at end of file
diff --git a/Minecraft.Client/Assets/UI/SettingsUIMenu.rcss b/Minecraft.Client/Assets/UI/SettingsUIMenu.rcss
new file mode 100644
index 00000000..557d73a3
--- /dev/null
+++ b/Minecraft.Client/Assets/UI/SettingsUIMenu.rcss
@@ -0,0 +1,162 @@
+body
+{
+ width: 100%;
+ height: 100%;
+ font-family: Minecraft Default;
+ font-size: 26dp;
+ font-effect: shadow(1dp 1dp #000000);
+ color: #333333;
+ background: transparent;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+div#settings_ui_menu
+{
+ width: 449dp;
+ height: auto;
+ margin: auto;
+ margin-top: 320dp;
+ padding: 20dp 34dp;
+ decorator: image(images/lce/frame_MessageBox_background.png);
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+}
+
+p#title
+{
+ color: #333333;
+ font-size: 29dp;
+ font-weight: bold;
+ margin-bottom: 10dp;
+ text-align: center;
+ width: 100%;
+}
+
+div#controls
+{
+ width: 100%;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+}
+
+.toggle_row
+{
+ display: flex;
+ align-items: center;
+ width: 100%;
+ min-height: 30dp;
+ padding: 1dp 0;
+ margin-bottom: 3dp;
+}
+
+.toggle_row button
+{
+ display: inline-block;
+ width: 30dp;
+ height: 30dp;
+ padding: 0;
+ border: none;
+ background: transparent;
+ cursor: pointer;
+}
+
+.toggle_row .toggle_switch
+{
+ display: block;
+ width: 30dp;
+ height: 30dp;
+ decorator: image(images/lce/Tickbox_Background.png);
+ position: relative;
+}
+
+.toggle_row button:hover .toggle_switch
+{
+ decorator: image(images/lce/Tickbox_Over.png);
+}
+
+.tick_mark
+{
+ display: block;
+ width: 100%;
+ height: 100%;
+ decorator: image(images/lce/Tick.png);
+}
+
+.toggle_row:not(.checked) .tick_mark
+{
+ display: none;
+}
+
+.toggle_label
+{
+ display: inline-block;
+ font-size: 20dp;
+ color: #333333;
+ margin-left: 9dp;
+ line-height: 30dp;
+}
+
+.slider_row
+{
+ display: flex;
+ flex-direction: column;
+ width: 100%;
+ margin-bottom: 6dp;
+ padding: 2dp 0;
+}
+
+.slider_container
+{
+ width: 100%;
+ height: 30dp;
+ position: relative;
+ decorator: image(images/lce/Slider_Background.png);
+ border: 1dp transparent;
+}
+
+.slider_container:hover
+{
+ border-color: #ffff00;
+}
+
+.slider_label
+{
+ position: absolute;
+ left: 0;
+ top: 0;
+ width: 100%;
+ height: 100%;
+ font-size: 20dp;
+ color: #ffffff;
+ text-align: center;
+ line-height: 30dp;
+}
+
+.slider_container:hover .slider_label
+{
+ color: #ffff00;
+}
+
+.slider_track
+{
+ position: absolute;
+ left: 8dp;
+ right: 8dp;
+ top: 0;
+ height: 100%;
+ cursor: resize;
+}
+
+.slider_thumb
+{
+ position: absolute;
+ width: 12dp;
+ height: 30dp;
+ decorator: image(images/lce/Slider.png);
+ cursor: resize;
+ transform: translateX(-50%);
+}
diff --git a/Minecraft.Client/Assets/UI/SettingsUIMenu.rml b/Minecraft.Client/Assets/UI/SettingsUIMenu.rml
new file mode 100644
index 00000000..f2db8b0c
--- /dev/null
+++ b/Minecraft.Client/Assets/UI/SettingsUIMenu.rml
@@ -0,0 +1,57 @@
+
+
+ UI Settings
+
+
+
+
+
+
diff --git a/Minecraft.Client/CMakeLists.txt b/Minecraft.Client/CMakeLists.txt
index b0819f3d..ed9932f0 100644
--- a/Minecraft.Client/CMakeLists.txt
+++ b/Minecraft.Client/CMakeLists.txt
@@ -76,6 +76,8 @@ if(PLATFORM_NAME STREQUAL "Windows64")
# not to the whole target (avoids PCH macro conflicts with windows.h).
set(RMLUI_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/Windows64/Libs/RmlUi/Include")
set(_RMLUI_SOURCES
+ "${CMAKE_CURRENT_SOURCE_DIR}/Common/UI/UIScene_RmlBase.cpp"
+ "${CMAKE_CURRENT_SOURCE_DIR}/Common/UI/UIScene_RmlBase.h"
"${CMAKE_CURRENT_SOURCE_DIR}/Common/UI/UIScene_HelpAndOptionsMenu.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Common/UI/UIScene_HelpAndOptionsMenu.h"
"${CMAKE_CURRENT_SOURCE_DIR}/Common/UI/UIScene_PauseMenu.cpp"
@@ -86,6 +88,8 @@ if(PLATFORM_NAME STREQUAL "Windows64")
"${CMAKE_CURRENT_SOURCE_DIR}/Common/UI/UIScene_SkinSelectMenu.h"
"${CMAKE_CURRENT_SOURCE_DIR}/Common/UI/UIScene_LoadCreateJoinMenu.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Common/UI/UIScene_LoadCreateJoinMenu.h"
+ "${CMAKE_CURRENT_SOURCE_DIR}/Common/UI/UIScene_MessageBox.cpp"
+ "${CMAKE_CURRENT_SOURCE_DIR}/Common/UI/UIScene_MessageBox.h"
"${CMAKE_CURRENT_SOURCE_DIR}/Windows64/RmlUi_Renderer_D3D11.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Windows64/RmlUi_Renderer_D3D11.h"
"${CMAKE_CURRENT_SOURCE_DIR}/Windows64/RmlUi_SystemInterface_Win64.cpp"
diff --git a/Minecraft.Client/Common/UI/UIScene_HelpAndOptionsMenu.cpp b/Minecraft.Client/Common/UI/UIScene_HelpAndOptionsMenu.cpp
index e2f0f85a..da7a0e71 100644
--- a/Minecraft.Client/Common/UI/UIScene_HelpAndOptionsMenu.cpp
+++ b/Minecraft.Client/Common/UI/UIScene_HelpAndOptionsMenu.cpp
@@ -1,8 +1,6 @@
-// Non-RmlUi includes that depend on Windows macros
#include "UI.h"
#include "../../Minecraft.h"
-// RmlUi includes (Windows macros temporarily suppressed)
#pragma push_macro("byte")
#pragma push_macro("GetNextSibling")
#pragma push_macro("GetFirstChild")
@@ -21,8 +19,7 @@
#pragma pop_macro("byte")
UIScene_HelpAndOptionsMenu::UIScene_HelpAndOptionsMenu(int iPad, void *initData, UILayer *parentLayer)
- : UIScene(iPad, parentLayer)
- , m_document(nullptr)
+ : UIScene_RmlBase(iPad, parentLayer)
{
Rml::Context* ctx = RmlManager::Get().GetContext();
if (!ctx)
@@ -32,43 +29,30 @@ UIScene_HelpAndOptionsMenu::UIScene_HelpAndOptionsMenu(int iPad, void *initData,
}
m_document = ctx->LoadDocument("HelpOptions.rml");
- if (m_document)
- {
- m_document->Show();
-
- bool bNotInGame = (Minecraft::GetInstance()->level == nullptr);
-
- // Change Skin: hide if not full version
- if (!ProfileManager.IsFullVersion())
- {
- auto* el = m_document->GetElementById("change_skin");
- if (el) el->SetProperty("display", "none");
- }
-
- // Credits: hide in splitscreen
- if (app.GetLocalPlayerCount() > 1)
- {
- auto* el = m_document->GetElementById("credits");
- if (el) el->SetProperty("display", "none");
- }
-
- // Register button click listeners
- m_document->GetElementById("change_skin")->AddEventListener(Rml::EventId::Click, this);
- m_document->GetElementById("how_to_play")->AddEventListener(Rml::EventId::Click, this);
- m_document->GetElementById("controls")->AddEventListener(Rml::EventId::Click, this);
- m_document->GetElementById("settings")->AddEventListener(Rml::EventId::Click, this);
- m_document->GetElementById("credits")->AddEventListener(Rml::EventId::Click, this);
-
- // Focus first visible button
- m_document->GetElementById("change_skin")->Focus();
- }
- else
+ if (!m_document)
{
app.DebugPrintf("[RmlHelpAndOptions] Failed to load HelpOptions.rml\n");
+ return;
}
- ui.HidePressStart();
+ m_document->Show();
+ if (!ProfileManager.IsFullVersion())
+ {
+ auto* el = m_document->GetElementById("change_skin");
+ if (el) el->SetProperty("display", "none");
+ }
+
+ if (app.GetLocalPlayerCount() > 1)
+ {
+ auto* el = m_document->GetElementById("credits");
+ if (el) el->SetProperty("display", "none");
+ }
+
+ RegisterEvents({ "change_skin", "how_to_play", "controls", "settings", "credits" });
+ m_document->GetElementById("change_skin")->Focus();
+
+ ui.HidePressStart();
TelemetryManager->RecordMenuShown(m_iPad, eUIScene_HelpAndOptionsMenu, 0);
}
@@ -76,76 +60,11 @@ UIScene_HelpAndOptionsMenu::~UIScene_HelpAndOptionsMenu()
{
if (m_document)
{
- m_document->GetElementById("change_skin")->RemoveEventListener(Rml::EventId::Click, this);
- m_document->GetElementById("how_to_play")->RemoveEventListener(Rml::EventId::Click, this);
- m_document->GetElementById("controls")->RemoveEventListener(Rml::EventId::Click, this);
- m_document->GetElementById("settings")->RemoveEventListener(Rml::EventId::Click, this);
- m_document->GetElementById("credits")->RemoveEventListener(Rml::EventId::Click, this);
+ UnregisterEvents({ "change_skin", "how_to_play", "controls", "settings", "credits" });
m_document->Close();
- m_document = nullptr;
}
}
-void UIScene_HelpAndOptionsMenu::gainFocus()
-{
- if (!bHasFocus && stealsFocus())
- {
- bHasFocus = true;
- updateTooltips();
- updateComponents();
- if (!m_bFocussedOnce)
- {
- }
- handleGainFocus(m_bFocussedOnce);
- if (bHasFocus)
- m_bFocussedOnce = true;
- if (m_document)
- m_document->Show();
- }
-}
-
-void UIScene_HelpAndOptionsMenu::handleLoseFocus()
-{
- if (m_document)
- m_document->Hide();
-}
-
-void UIScene_HelpAndOptionsMenu::reloadMovie(bool force)
-{
-}
-
-void UIScene_HelpAndOptionsMenu::tick()
-{
- m_hasTickedOnce = true;
-
- UIScene::tick();
-
- Rml::Context* ctx = RmlManager::Get().GetContext();
- if (!ctx || !bHasFocus)
- return;
-
- ctx->ProcessMouseMove(g_KBMInput.GetMouseX(), g_KBMInput.GetMouseY(), 0);
-
- if (g_KBMInput.IsMouseButtonPressed(KeyboardMouseInput::MOUSE_LEFT))
- ctx->ProcessMouseButtonDown(0, 0);
- if (g_KBMInput.IsMouseButtonReleased(KeyboardMouseInput::MOUSE_LEFT))
- ctx->ProcessMouseButtonUp(0, 0);
- if (g_KBMInput.IsMouseButtonPressed(KeyboardMouseInput::MOUSE_RIGHT))
- ctx->ProcessMouseButtonDown(1, 0);
- if (g_KBMInput.IsMouseButtonReleased(KeyboardMouseInput::MOUSE_RIGHT))
- ctx->ProcessMouseButtonUp(1, 0);
-
- int wheelDelta = g_KBMInput.GetMouseWheel();
- if (wheelDelta != 0)
- ctx->ProcessMouseWheel(wheelDelta / -120, 0);
-
- ctx->Update();
-}
-
-void UIScene_HelpAndOptionsMenu::render(S32 width, S32 height, C4JRender::eViewportType viewport)
-{
-}
-
void UIScene_HelpAndOptionsMenu::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled)
{
Rml::Context* ctx = RmlManager::Get().GetContext();
@@ -196,10 +115,6 @@ void UIScene_HelpAndOptionsMenu::ProcessEvent(Rml::Event& event)
}
}
-void UIScene_HelpAndOptionsMenu::updateTooltips()
-{
-}
-
void UIScene_HelpAndOptionsMenu::updateComponents()
{
bool bNotInGame = (Minecraft::GetInstance()->level == nullptr);
@@ -211,11 +126,7 @@ void UIScene_HelpAndOptionsMenu::updateComponents()
else
{
m_parentLayer->showComponent(m_iPad, eUIComponent_Panorama, false);
-
- if (app.GetLocalPlayerCount() == 1)
- m_parentLayer->showComponent(m_iPad, eUIComponent_Logo, true);
- else
- m_parentLayer->showComponent(m_iPad, eUIComponent_Logo, false);
+ m_parentLayer->showComponent(m_iPad, eUIComponent_Logo, app.GetLocalPlayerCount() == 1);
}
}
@@ -254,5 +165,3 @@ void UIScene_HelpAndOptionsMenu::OnCredits()
ui.PlayUISFX(eSFX_Press);
ui.NavigateToScene(m_iPad, eUIScene_Credits);
}
-
-
diff --git a/Minecraft.Client/Common/UI/UIScene_HelpAndOptionsMenu.h b/Minecraft.Client/Common/UI/UIScene_HelpAndOptionsMenu.h
index a8c720d4..ae012ad0 100644
--- a/Minecraft.Client/Common/UI/UIScene_HelpAndOptionsMenu.h
+++ b/Minecraft.Client/Common/UI/UIScene_HelpAndOptionsMenu.h
@@ -7,39 +7,21 @@
#undef GetNextSibling
#undef GetFirstChild
-#include "UIScene.h"
-#include
-#include
+#include "UIScene_RmlBase.h"
-// NOTE: pop_macro at end of file
-
-class UIScene_HelpAndOptionsMenu : public UIScene, public Rml::EventListener
+class UIScene_HelpAndOptionsMenu : public UIScene_RmlBase
{
public:
UIScene_HelpAndOptionsMenu(int iPad, void *initData, UILayer *parentLayer);
virtual ~UIScene_HelpAndOptionsMenu();
- virtual EUIScene getSceneType() { return eUIScene_HelpAndOptionsMenu; }
+ EUIScene getSceneType() override { return eUIScene_HelpAndOptionsMenu; }
+ void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled) override;
+ void updateComponents() override;
- virtual void tick();
- virtual void render(S32 width, S32 height, C4JRender::eViewportType viewport);
-
- virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled);
-
- // Override focus/movie lifecycle for RmlUi (no Iggy movie)
- virtual void gainFocus() override;
- virtual void reloadMovie(bool force) override;
-
- // Rml::EventListener
void ProcessEvent(Rml::Event& event) override;
-protected:
- virtual wstring getMoviePath() { return L""; }
-
- virtual void handleLoseFocus() override;
- virtual void updateTooltips() override;
- virtual void updateComponents() override;
-
+private:
void navigateBack();
void OnChangeSkin();
@@ -47,9 +29,6 @@ protected:
void OnControls();
void OnSettings();
void OnCredits();
-
-private:
- Rml::ElementDocument* m_document;
};
#pragma pop_macro("GetFirstChild")
diff --git a/Minecraft.Client/Common/UI/UIScene_LoadCreateJoinMenu.cpp b/Minecraft.Client/Common/UI/UIScene_LoadCreateJoinMenu.cpp
index 989f78ae..d01a344d 100644
--- a/Minecraft.Client/Common/UI/UIScene_LoadCreateJoinMenu.cpp
+++ b/Minecraft.Client/Common/UI/UIScene_LoadCreateJoinMenu.cpp
@@ -251,12 +251,11 @@ void UIScene_LoadCreateJoinMenu::SetListTexture(int itemIndex, const char* listI
// -- Construction / Destruction --
-UIScene_LoadCreateJoinMenu::UIScene_LoadCreateJoinMenu(int iPad, void* initData, UILayer* parentLayer) : UIScene(iPad, parentLayer)
+UIScene_LoadCreateJoinMenu::UIScene_LoadCreateJoinMenu(int iPad, void* initData, UILayer* parentLayer) : UIScene_RmlBase(iPad, parentLayer)
{
constexpr uint64_t MAXIMUM_SAVE_STORAGE = 4LL * 1024LL * 1024LL * 1024LL;
// Initialize all members before any function calls
- m_document = nullptr;
m_iRequestingThumbnailId = 0;
m_iSaveInfoC = 0;
m_bIgnoreInput = false;
@@ -383,44 +382,6 @@ UIScene_LoadCreateJoinMenu::~UIScene_LoadCreateJoinMenu()
}
}
-// -- RmlUi lifecycle overrides --
-
-void UIScene_LoadCreateJoinMenu::gainFocus()
-{
- if (!bHasFocus && stealsFocus())
- {
- bHasFocus = true;
- updateTooltips();
- updateComponents();
-
- if (!m_bFocussedOnce)
- {
- }
-
- handleGainFocus(m_bFocussedOnce);
-
- if (bHasFocus)
- m_bFocussedOnce = true;
-
- if (m_document)
- m_document->Show();
- }
-}
-
-void UIScene_LoadCreateJoinMenu::handleLoseFocus()
-{
- if (m_document)
- m_document->Hide();
-}
-
-void UIScene_LoadCreateJoinMenu::reloadMovie(bool force)
-{
-}
-
-void UIScene_LoadCreateJoinMenu::render(S32 width, S32 height, C4JRender::eViewportType viewport)
-{
-}
-
void UIScene_LoadCreateJoinMenu::ProcessEvent(Rml::Event& event)
{
if (m_bIgnoreInput)
@@ -917,29 +878,7 @@ void UIScene_LoadCreateJoinMenu::UpdateGamesListCallback(LPVOID pParam)
void UIScene_LoadCreateJoinMenu::tick()
{
- UIScene::tick();
-
- m_hasTickedOnce = true;
-
- // Forward mouse/input to RmlUi context
- Rml::Context* rmlCtx = RmlManager::Get().GetContext();
- if (rmlCtx && bHasFocus)
- {
- rmlCtx->ProcessMouseMove(g_KBMInput.GetMouseX(), g_KBMInput.GetMouseY(), 0);
- if (g_KBMInput.IsMouseButtonPressed(KeyboardMouseInput::MOUSE_LEFT))
- rmlCtx->ProcessMouseButtonDown(0, 0);
- if (g_KBMInput.IsMouseButtonReleased(KeyboardMouseInput::MOUSE_LEFT))
- rmlCtx->ProcessMouseButtonUp(0, 0);
- if (g_KBMInput.IsMouseButtonPressed(KeyboardMouseInput::MOUSE_RIGHT))
- rmlCtx->ProcessMouseButtonDown(1, 0);
- if (g_KBMInput.IsMouseButtonReleased(KeyboardMouseInput::MOUSE_RIGHT))
- rmlCtx->ProcessMouseButtonUp(1, 0);
- int wheelDelta = g_KBMInput.GetMouseWheel();
- if (wheelDelta != 0)
- rmlCtx->ProcessMouseWheel(wheelDelta / -120, 0);
-
- rmlCtx->Update();
- }
+ UIScene_RmlBase::tick();
if (m_bExitScene)
if (!m_bRetrievingSaveThumbnails)
diff --git a/Minecraft.Client/Common/UI/UIScene_LoadCreateJoinMenu.h b/Minecraft.Client/Common/UI/UIScene_LoadCreateJoinMenu.h
index 67a577f7..caa25ac6 100644
--- a/Minecraft.Client/Common/UI/UIScene_LoadCreateJoinMenu.h
+++ b/Minecraft.Client/Common/UI/UIScene_LoadCreateJoinMenu.h
@@ -7,16 +7,12 @@
#undef GetNextSibling
#undef GetFirstChild
-#include "UIScene.h"
-#include
-#include
-
-// NOTE: pop_macro at end of file
+#include "UIScene_RmlBase.h"
class LevelGenerationOptions;
class C4JThread;
-class UIScene_LoadCreateJoinMenu : public UIScene, public Rml::EventListener
+class UIScene_LoadCreateJoinMenu : public UIScene_RmlBase
{
private:
enum EControls
@@ -112,29 +108,22 @@ public:
UIScene_LoadCreateJoinMenu(int iPad, void *initData, UILayer *parentLayer);
virtual ~UIScene_LoadCreateJoinMenu();
- virtual void updateTooltips();
- virtual void updateComponents();
+ virtual void updateTooltips() override;
+ virtual void updateComponents() override;
virtual UIControl* GetMainPanel();
- virtual void handleDestroy();
- virtual void handleLoseFocus();
- virtual void handleGainFocus(bool navBack);
- virtual void handleTimerComplete(int id);
- // INPUT
- virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled);
- virtual void handleFocusChange(F64 controlId, F64 childId);
- virtual void handleInitFocus(F64 controlId, F64 childId);
+ virtual void handleDestroy() override;
+ virtual void handleGainFocus(bool navBack) override;
+ virtual void handleTimerComplete(int id) override;
+ virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled) override;
+ virtual void handleFocusChange(F64 controlId, F64 childId) override;
+ virtual void handleInitFocus(F64 controlId, F64 childId) override;
- virtual EUIScene getSceneType() { return eUIScene_LoadCreateJoinMenu; }
+ virtual EUIScene getSceneType() override { return eUIScene_LoadCreateJoinMenu; }
static void UpdateGamesListCallback(LPVOID pParam);
- virtual void tick();
-
- // Override focus/movie lifecycle for RmlUi (no Iggy movie)
- virtual void gainFocus() override;
- virtual void reloadMovie(bool force) override;
- virtual void render(S32 width, S32 height, C4JRender::eViewportType viewport) override;
+ void tick() override;
// Rml::EventListener
void ProcessEvent(Rml::Event& event) override;
@@ -166,7 +155,7 @@ private:
int GetListItemCount(const char* listId);
protected:
- virtual wstring getMoviePath();
+ virtual wstring getMoviePath() override;
public:
static int LoadSaveDataThumbnailReturned(LPVOID lpParam,PBYTE pbThumbnail,DWORD dwThumbnailBytes);
@@ -184,7 +173,7 @@ protected:
void LoadSaveFromDisk(File *saveFile, ESavePlatform savePlatform = SAVE_FILE_PLATFORM_LOCAL);
public:
- virtual void HandleDLCMountingComplete();
+ virtual void HandleDLCMountingComplete() override;
private:
void CheckAndJoinGame(int gameIndex);
@@ -200,12 +189,8 @@ private:
void AppendServerToFile(const wstring& ip, const wstring& port, const wstring& name);
static int AddServerKeyboardCallback(LPVOID lpParam, bool bRes);
#endif
-
-// RmlUi document
-private:
- Rml::ElementDocument* m_document;
};
#pragma pop_macro("GetFirstChild")
#pragma pop_macro("GetNextSibling")
-#pragma pop_macro("byte")
\ No newline at end of file
+#pragma pop_macro("byte")
diff --git a/Minecraft.Client/Common/UI/UIScene_MessageBox.cpp b/Minecraft.Client/Common/UI/UIScene_MessageBox.cpp
index 77a0b907..4fb727e5 100644
--- a/Minecraft.Client/Common/UI/UIScene_MessageBox.cpp
+++ b/Minecraft.Client/Common/UI/UIScene_MessageBox.cpp
@@ -17,11 +17,8 @@
#pragma pop_macro("GetNextSibling")
#pragma pop_macro("byte")
-extern KeyboardMouseInput g_KBMInput;
-
UIScene_MessageBox::UIScene_MessageBox(int iPad, void *initData, UILayer *parentLayer)
- : UIScene(iPad, parentLayer)
- , m_document(nullptr)
+ : UIScene_RmlBase(iPad, parentLayer)
, m_buttonCount(0)
, m_Func(nullptr)
, m_lpParam(nullptr)
@@ -59,7 +56,6 @@ UIScene_MessageBox::UIScene_MessageBox(int iPad, void *initData, UILayer *parent
if (auto* descEl = m_document->GetElementById("description"))
descEl->SetInnerRML(descUtf8);
- int buttonIndex = 0;
Rml::Element* buttons[4] = {
m_document->GetElementById("button0"),
m_document->GetElementById("button1"),
@@ -76,10 +72,7 @@ UIScene_MessageBox::UIScene_MessageBox(int iPad, void *initData, UILayer *parent
}
}
- int startIndex = 4 - m_buttonCount;
- if (startIndex < 0)
- startIndex = 0;
-
+ int startIndex = max(0, 4 - m_buttonCount);
int labelIndex = 0;
for (int i = startIndex; i < 4; i++)
{
@@ -98,7 +91,6 @@ UIScene_MessageBox::UIScene_MessageBox(int iPad, void *initData, UILayer *parent
buttons[focusButton]->Focus();
m_document->Show();
-
parentLayer->addComponent(iPad, eUIComponent_MenuBackground);
}
@@ -106,79 +98,23 @@ UIScene_MessageBox::~UIScene_MessageBox()
{
if (m_document)
{
- m_document->GetElementById("button0")->RemoveEventListener(Rml::EventId::Click, this);
- m_document->GetElementById("button1")->RemoveEventListener(Rml::EventId::Click, this);
- m_document->GetElementById("button2")->RemoveEventListener(Rml::EventId::Click, this);
- m_document->GetElementById("button3")->RemoveEventListener(Rml::EventId::Click, this);
+ Rml::Element* buttons[4] = {
+ m_document->GetElementById("button0"),
+ m_document->GetElementById("button1"),
+ m_document->GetElementById("button2"),
+ m_document->GetElementById("button3")
+ };
+ for (int i = 0; i < 4; i++)
+ {
+ if (buttons[i])
+ buttons[i]->RemoveEventListener(Rml::EventId::Click, this);
+ }
m_document->Close();
- m_document = nullptr;
}
m_parentLayer->removeComponent(eUIComponent_MenuBackground);
}
-void UIScene_MessageBox::gainFocus()
-{
- if (!bHasFocus && stealsFocus())
- {
- bHasFocus = true;
- updateTooltips();
- updateComponents();
- handleGainFocus(m_bFocussedOnce);
- if (bHasFocus)
- m_bFocussedOnce = true;
-
- if (m_document)
- m_document->Show();
- }
-}
-
-void UIScene_MessageBox::handleLoseFocus()
-{
- if (m_document)
- m_document->Hide();
-}
-
-void UIScene_MessageBox::reloadMovie(bool force)
-{
-}
-
-//GabsPuN: When Iggy is completely replaced, some functions should be moved to UIScene.cpp.
-//This way, the tick() function won't be repeated in every UIScene_ cpp file.
-//Also, since iggy no longer exists, we can take liberties with optimization or code
-//that is easier to work with.
-void UIScene_MessageBox::tick()
-{
- m_hasTickedOnce = true;
-
- UIScene::tick();
-
- Rml::Context* ctx = RmlManager::Get().GetContext();
- if (!ctx || !bHasFocus)
- return;
-
- ctx->ProcessMouseMove(g_KBMInput.GetMouseX(), g_KBMInput.GetMouseY(), 0);
-
- if (g_KBMInput.IsMouseButtonPressed(KeyboardMouseInput::MOUSE_LEFT))
- ctx->ProcessMouseButtonDown(0, 0);
- if (g_KBMInput.IsMouseButtonReleased(KeyboardMouseInput::MOUSE_LEFT))
- ctx->ProcessMouseButtonUp(0, 0);
- if (g_KBMInput.IsMouseButtonPressed(KeyboardMouseInput::MOUSE_RIGHT))
- ctx->ProcessMouseButtonDown(1, 0);
- if (g_KBMInput.IsMouseButtonReleased(KeyboardMouseInput::MOUSE_RIGHT))
- ctx->ProcessMouseButtonUp(1, 0);
-
- int wheelDelta = g_KBMInput.GetMouseWheel();
- if (wheelDelta != 0)
- ctx->ProcessMouseWheel(wheelDelta / -120, 0);
-
- ctx->Update();
-}
-
-void UIScene_MessageBox::render(S32 width, S32 height, C4JRender::eViewportType viewport)
-{
-}
-
void UIScene_MessageBox::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled)
{
Rml::Context* ctx = RmlManager::Get().GetContext();
@@ -208,7 +144,7 @@ void UIScene_MessageBox::handleInput(int iPad, int key, bool repeat, bool presse
case ACTION_MENU_CANCEL:
{
C4JStorage::EMessageResult result = C4JStorage::EMessage_Cancelled;
- int( *tmpFunc)(LPVOID,int,const C4JStorage::EMessageResult) = m_Func;
+ auto tmpFunc = m_Func;
LPVOID tmpParam = m_lpParam;
int tmpPad = m_iPad;
@@ -227,11 +163,11 @@ void UIScene_MessageBox::handleInput(int iPad, int key, bool repeat, bool presse
bool UIScene_MessageBox::hasFocus(int iPad)
{
- if (m_iPad == 255) // Message box is for everyone
+ if (m_iPad == 255)
return bHasFocus;
- else if (ProfileManager.IsSignedIn(m_iPad)) // Owner is still present
+ else if (ProfileManager.IsSignedIn(m_iPad))
return bHasFocus && (iPad == m_iPad);
- else // Original owner has left so let everyone interact
+ else
return bHasFocus;
}
@@ -250,12 +186,7 @@ void UIScene_MessageBox::ProcessEvent(Rml::Event& event)
void UIScene_MessageBox::OnButtonClicked(int buttonIndex)
{
- //GabsPuN: Something is wrong with the IDs. This fixed it but
- //I don't know if this is the right way to do it
- int startIndex = 4 - m_buttonCount;
- if (startIndex < 0)
- startIndex = 0;
-
+ int startIndex = max(0, 4 - m_buttonCount);
int RButtonIndex = buttonIndex - startIndex;
C4JStorage::EMessageResult result = C4JStorage::EMessage_Cancelled;
@@ -269,7 +200,7 @@ void UIScene_MessageBox::OnButtonClicked(int buttonIndex)
ui.PlayUISFX(eSFX_Press);
- int( *tmpFunc)(LPVOID,int,const C4JStorage::EMessageResult) = m_Func;
+ auto tmpFunc = m_Func;
LPVOID tmpParam = m_lpParam;
int tmpPad = m_iPad;
diff --git a/Minecraft.Client/Common/UI/UIScene_MessageBox.h b/Minecraft.Client/Common/UI/UIScene_MessageBox.h
index c2bc5967..84c13213 100644
--- a/Minecraft.Client/Common/UI/UIScene_MessageBox.h
+++ b/Minecraft.Client/Common/UI/UIScene_MessageBox.h
@@ -7,41 +7,28 @@
#undef GetNextSibling
#undef GetFirstChild
-#include "UIScene.h"
-#include
-#include
+#include "UIScene_RmlBase.h"
-class UIScene_MessageBox : public UIScene, public Rml::EventListener
+class UIScene_MessageBox : public UIScene_RmlBase
{
public:
UIScene_MessageBox(int iPad, void *initData, UILayer *parentLayer);
virtual ~UIScene_MessageBox();
- virtual EUIScene getSceneType() { return eUIScene_MessageBox; }
+ EUIScene getSceneType() override { return eUIScene_MessageBox; }
- virtual bool hidesLowerScenes() { return false; }
- virtual bool blocksInput() { return true; }
+ bool hidesLowerScenes() override { return false; }
+ bool blocksInput() override { return true; }
- virtual void tick();
- virtual void render(S32 width, S32 height, C4JRender::eViewportType viewport);
-
- virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled);
- virtual bool hasFocus(int iPad);
-
- virtual void gainFocus() override;
- virtual void reloadMovie(bool force) override;
+ void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled) override;
+ bool hasFocus(int iPad) override;
void ProcessEvent(Rml::Event& event) override;
-protected:
- virtual wstring getMoviePath() { return L""; }
- virtual void handleLoseFocus() override;
-
+private:
void OnButtonClicked(int buttonIndex);
void navigateBack();
-private:
- Rml::ElementDocument* m_document;
int m_buttonCount;
int(*m_Func)(LPVOID, int, const C4JStorage::EMessageResult);
LPVOID m_lpParam;
diff --git a/Minecraft.Client/Common/UI/UIScene_PauseMenu.cpp b/Minecraft.Client/Common/UI/UIScene_PauseMenu.cpp
index 38d9415f..386131af 100644
--- a/Minecraft.Client/Common/UI/UIScene_PauseMenu.cpp
+++ b/Minecraft.Client/Common/UI/UIScene_PauseMenu.cpp
@@ -1,9 +1,7 @@
-// Non-RmlUi includes that depend on Windows macros
#include "UI.h"
#include "../../MinecraftServer.h"
#include "../../MultiPlayerLocalPlayer.h"
-// RmlUi includes (Windows macros temporarily suppressed)
#pragma push_macro("byte")
#pragma push_macro("GetNextSibling")
#pragma push_macro("GetFirstChild")
@@ -22,9 +20,7 @@
#pragma pop_macro("byte")
UIScene_PauseMenu::UIScene_PauseMenu(int iPad, void *initData, UILayer *parentLayer)
- : UIScene(iPad, parentLayer)
- , m_document(nullptr)
- , m_bIgnoreInput(false)
+ : UIScene_RmlBase(iPad, parentLayer)
{
Rml::Context* ctx = RmlManager::Get().GetContext();
if (!ctx)
@@ -40,11 +36,8 @@ UIScene_PauseMenu::UIScene_PauseMenu(int iPad, void *initData, UILayer *parentLa
m_document->Show();
app.DebugPrintf("[RmlPauseMenu] Document shown, visible=%d, context docs=%d\n",
m_document->IsVisible(), ctx->GetNumDocuments());
- m_document->GetElementById("resume")->AddEventListener(Rml::EventId::Click, this);
- m_document->GetElementById("help_options")->AddEventListener(Rml::EventId::Click, this);
- m_document->GetElementById("achievements")->AddEventListener(Rml::EventId::Click, this);
- m_document->GetElementById("save_game")->AddEventListener(Rml::EventId::Click, this);
- m_document->GetElementById("exit_game")->AddEventListener(Rml::EventId::Click, this);
+
+ RegisterEvents({ "resume", "help_options", "achievements", "save_game", "exit_game" });
m_document->GetElementById("resume")->Focus();
}
else
@@ -67,13 +60,8 @@ UIScene_PauseMenu::~UIScene_PauseMenu()
{
if (m_document)
{
- m_document->GetElementById("resume")->RemoveEventListener(Rml::EventId::Click, this);
- m_document->GetElementById("help_options")->RemoveEventListener(Rml::EventId::Click, this);
- m_document->GetElementById("achievements")->RemoveEventListener(Rml::EventId::Click, this);
- m_document->GetElementById("save_game")->RemoveEventListener(Rml::EventId::Click, this);
- m_document->GetElementById("exit_game")->RemoveEventListener(Rml::EventId::Click, this);
+ UnregisterEvents({ "resume", "help_options", "achievements", "save_game", "exit_game" });
m_document->Close();
- m_document = nullptr;
}
m_parentLayer->showComponent(m_iPad, eUIComponent_Panorama, false);
@@ -81,74 +69,6 @@ UIScene_PauseMenu::~UIScene_PauseMenu()
m_parentLayer->showComponent(m_iPad, eUIComponent_Logo, false);
}
-void UIScene_PauseMenu::gainFocus()
-{
- if (!bHasFocus && stealsFocus())
- {
- bHasFocus = true;
- updateTooltips();
- updateComponents();
-
- if (!m_bFocussedOnce)
- // No Iggy set-focus call needed for RmlUi scene
-
- handleGainFocus(m_bFocussedOnce);
-
- if (bHasFocus)
- m_bFocussedOnce = true;
-
- if (m_document)
- m_document->Show();
- }
-}
-
-void UIScene_PauseMenu::handleLoseFocus()
-{
- if (m_document)
- m_document->Hide();
-}
-
-void UIScene_PauseMenu::reloadMovie(bool force)
-{
-}
-
-void UIScene_PauseMenu::tick()
-{
- // Signal the base class that we've ticked once, so it sets m_bCanHandleInput
- // (the Iggy while-loop that normally sets this never runs without a loaded SWF)
- m_hasTickedOnce = true;
-
- UIScene::tick();
-
- Rml::Context* ctx = RmlManager::Get().GetContext();
- if (!ctx || !bHasFocus)
- return;
-
- // Forward mouse position (for hover effects and correct click targeting)
- ctx->ProcessMouseMove(g_KBMInput.GetMouseX(), g_KBMInput.GetMouseY(), 0);
-
- // Forward mouse button presses/releases
- if (g_KBMInput.IsMouseButtonPressed(KeyboardMouseInput::MOUSE_LEFT))
- ctx->ProcessMouseButtonDown(0, 0);
- if (g_KBMInput.IsMouseButtonReleased(KeyboardMouseInput::MOUSE_LEFT))
- ctx->ProcessMouseButtonUp(0, 0);
- if (g_KBMInput.IsMouseButtonPressed(KeyboardMouseInput::MOUSE_RIGHT))
- ctx->ProcessMouseButtonDown(1, 0);
- if (g_KBMInput.IsMouseButtonReleased(KeyboardMouseInput::MOUSE_RIGHT))
- ctx->ProcessMouseButtonUp(1, 0);
-
- // Forward scroll wheel
- int wheelDelta = g_KBMInput.GetMouseWheel();
- if (wheelDelta != 0)
- ctx->ProcessMouseWheel(wheelDelta / -120, 0);
-
- ctx->Update();
-}
-
-void UIScene_PauseMenu::render(S32 width, S32 height, C4JRender::eViewportType viewport)
-{
-}
-
void UIScene_PauseMenu::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled)
{
if (m_bIgnoreInput)
@@ -164,9 +84,6 @@ void UIScene_PauseMenu::handleInput(int iPad, int key, bool repeat, bool pressed
if (!ctx)
return;
- // Translate game actions to RmlUi key events.
- // Mouse clicks are forwarded in tick() via ProcessMouseButtonDown/Up,
- // so here we only handle keyboard-originated actions.
if (!pressed)
return;
@@ -179,8 +96,6 @@ void UIScene_PauseMenu::handleInput(int iPad, int key, bool repeat, bool pressed
ctx->ProcessKeyDown(Rml::Input::KI_DOWN, 0);
break;
case ACTION_MENU_OK:
- // Only forward as keyboard Enter if actually coming from keyboard,
- // not from mouse click (mouse is handled in tick()).
if (g_KBMInput.IsKeyPressed(VK_RETURN))
ctx->ProcessKeyDown(Rml::Input::KI_RETURN, 0);
break;
@@ -253,11 +168,9 @@ void UIScene_PauseMenu::OnSaveGame()
if (m_iPad != ProfileManager.GetPrimaryPad())
return;
- // Does the save exist?
bool bSaveExists;
StorageManager.DoesSaveExist(&bSaveExists);
- // We need to ask if they are sure they want to overwrite the existing game
if (bSaveExists)
{
UINT uiIDA[2];
@@ -267,7 +180,6 @@ void UIScene_PauseMenu::OnSaveGame()
}
else
{
- // Flag a app action of save game
app.SetAction(m_iPad, eAppAction_SaveGame);
}
}
@@ -278,7 +190,6 @@ void UIScene_PauseMenu::OnExitGame()
UINT uiIDA[3];
- // Is it the primary player exiting?
if (m_iPad == ProfileManager.GetPrimaryPad())
{
int playTime = -1;
@@ -313,7 +224,7 @@ void UIScene_PauseMenu::OnExitGame()
}
}
}
- else // Non-primary pad: exit directly without dialog
+ else
{
int playTime = -1;
if (pMinecraft->localplayers[m_iPad] != NULL)
@@ -325,4 +236,4 @@ void UIScene_PauseMenu::OnExitGame()
app.SetAction(m_iPad, eAppAction_ExitPlayer);
return;
}
-}
\ No newline at end of file
+}
diff --git a/Minecraft.Client/Common/UI/UIScene_PauseMenu.h b/Minecraft.Client/Common/UI/UIScene_PauseMenu.h
index 8ec681ed..03ef5d0e 100644
--- a/Minecraft.Client/Common/UI/UIScene_PauseMenu.h
+++ b/Minecraft.Client/Common/UI/UIScene_PauseMenu.h
@@ -7,38 +7,22 @@
#undef GetNextSibling
#undef GetFirstChild
-#include "UIScene.h"
+#include "UIScene_RmlBase.h"
#include "IUIScene_PauseMenu.h"
-#include
-#include
-// NOTE: pop_macro at end of file
-
-class UIScene_PauseMenu : public UIScene, public IUIScene_PauseMenu, public Rml::EventListener
+class UIScene_PauseMenu : public UIScene_RmlBase, public IUIScene_PauseMenu
{
public:
UIScene_PauseMenu(int iPad, void *initData, UILayer *parentLayer);
virtual ~UIScene_PauseMenu();
- virtual EUIScene getSceneType() { return eUIScene_PauseMenu; }
+ EUIScene getSceneType() override { return eUIScene_PauseMenu; }
- virtual void tick();
- virtual void render(S32 width, S32 height, C4JRender::eViewportType viewport);
+ void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled) override;
- virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled);
-
- // Override focus/movie lifecycle for RmlUi (no Iggy movie)
- virtual void gainFocus() override;
- virtual void reloadMovie(bool force) override;
-
- // Rml::EventListener
void ProcessEvent(Rml::Event& event) override;
protected:
- virtual wstring getMoviePath() { return L""; }
-
- virtual void handleLoseFocus() override;
-
void ShowScene(bool show) override;
void SetIgnoreInput(bool ignoreInput) override { m_bIgnoreInput = ignoreInput; }
@@ -51,8 +35,7 @@ protected:
void OnExitGame();
private:
- Rml::ElementDocument* m_document;
- bool m_bIgnoreInput;
+ bool m_bIgnoreInput = false;
};
#pragma pop_macro("GetFirstChild")
diff --git a/Minecraft.Client/Common/UI/UIScene_RmlBase.cpp b/Minecraft.Client/Common/UI/UIScene_RmlBase.cpp
new file mode 100644
index 00000000..d27ebaf6
--- /dev/null
+++ b/Minecraft.Client/Common/UI/UIScene_RmlBase.cpp
@@ -0,0 +1,99 @@
+#include "UI.h"
+
+#pragma push_macro("byte")
+#pragma push_macro("GetNextSibling")
+#pragma push_macro("GetFirstChild")
+#undef byte
+#undef GetNextSibling
+#undef GetFirstChild
+
+#include "UIScene_RmlBase.h"
+#include "RmlManager.h"
+#include "../../Windows64/KeyboardMouseInput.h"
+#include
+#include
+
+#pragma pop_macro("GetFirstChild")
+#pragma pop_macro("GetNextSibling")
+#pragma pop_macro("byte")
+
+UIScene_RmlBase::UIScene_RmlBase(int iPad, UILayer *parentLayer)
+ : UIScene(iPad, parentLayer)
+{
+}
+
+UIScene_RmlBase::~UIScene_RmlBase()
+{
+}
+
+void UIScene_RmlBase::tick()
+{
+ m_hasTickedOnce = true;
+ UIScene::tick();
+
+ Rml::Context* ctx = RmlManager::Get().GetContext();
+ if (!ctx || !bHasFocus)
+ return;
+
+ ForwardRmlInput(ctx);
+ ctx->Update();
+}
+
+void UIScene_RmlBase::gainFocus()
+{
+ if (!bHasFocus && stealsFocus())
+ {
+ bHasFocus = true;
+ updateTooltips();
+ updateComponents();
+ handleGainFocus(m_bFocussedOnce);
+ if (bHasFocus)
+ m_bFocussedOnce = true;
+ if (m_document)
+ m_document->Show();
+ }
+}
+
+void UIScene_RmlBase::handleLoseFocus()
+{
+ if (m_document)
+ m_document->Hide();
+}
+
+void UIScene_RmlBase::ForwardRmlInput(Rml::Context* ctx)
+{
+ ctx->ProcessMouseMove(g_KBMInput.GetMouseX(), g_KBMInput.GetMouseY(), 0);
+
+ if (g_KBMInput.IsMouseButtonPressed(KeyboardMouseInput::MOUSE_LEFT))
+ ctx->ProcessMouseButtonDown(0, 0);
+ if (g_KBMInput.IsMouseButtonReleased(KeyboardMouseInput::MOUSE_LEFT))
+ ctx->ProcessMouseButtonUp(0, 0);
+ if (g_KBMInput.IsMouseButtonPressed(KeyboardMouseInput::MOUSE_RIGHT))
+ ctx->ProcessMouseButtonDown(1, 0);
+ if (g_KBMInput.IsMouseButtonReleased(KeyboardMouseInput::MOUSE_RIGHT))
+ ctx->ProcessMouseButtonUp(1, 0);
+
+ int wheelDelta = g_KBMInput.GetMouseWheel();
+ if (wheelDelta != 0)
+ ctx->ProcessMouseWheel(wheelDelta / -120, 0);
+}
+
+void UIScene_RmlBase::RegisterEvents(std::initializer_list ids)
+{
+ if (!m_document) return;
+ for (const char* id : ids)
+ {
+ auto* el = m_document->GetElementById(id);
+ if (el) el->AddEventListener(Rml::EventId::Click, this);
+ }
+}
+
+void UIScene_RmlBase::UnregisterEvents(std::initializer_list ids)
+{
+ if (!m_document) return;
+ for (const char* id : ids)
+ {
+ auto* el = m_document->GetElementById(id);
+ if (el) el->RemoveEventListener(Rml::EventId::Click, this);
+ }
+}
diff --git a/Minecraft.Client/Common/UI/UIScene_RmlBase.h b/Minecraft.Client/Common/UI/UIScene_RmlBase.h
new file mode 100644
index 00000000..7d0ed222
--- /dev/null
+++ b/Minecraft.Client/Common/UI/UIScene_RmlBase.h
@@ -0,0 +1,38 @@
+#pragma once
+
+#pragma push_macro("byte")
+#pragma push_macro("GetNextSibling")
+#pragma push_macro("GetFirstChild")
+#undef byte
+#undef GetNextSibling
+#undef GetFirstChild
+
+#include "UIScene.h"
+#include
+#include
+
+class UIScene_RmlBase : public UIScene, public Rml::EventListener
+{
+public:
+ UIScene_RmlBase(int iPad, UILayer *parentLayer);
+ virtual ~UIScene_RmlBase();
+
+ void tick() override;
+ void render(S32 width, S32 height, C4JRender::eViewportType viewport) override {}
+ void gainFocus() override;
+ void reloadMovie(bool force) override {}
+
+protected:
+ wstring getMoviePath() override { return L""; }
+ void handleLoseFocus() override;
+
+ void ForwardRmlInput(Rml::Context* ctx);
+ void RegisterEvents(std::initializer_list ids);
+ void UnregisterEvents(std::initializer_list ids);
+
+ Rml::ElementDocument* m_document = nullptr;
+};
+
+#pragma pop_macro("GetFirstChild")
+#pragma pop_macro("GetNextSibling")
+#pragma pop_macro("byte")
diff --git a/Minecraft.Client/Common/UI/UIScene_SettingsMenu.cpp b/Minecraft.Client/Common/UI/UIScene_SettingsMenu.cpp
index 3b70694d..e2997753 100644
--- a/Minecraft.Client/Common/UI/UIScene_SettingsMenu.cpp
+++ b/Minecraft.Client/Common/UI/UIScene_SettingsMenu.cpp
@@ -1,8 +1,6 @@
-// Non-RmlUi includes that depend on Windows macros
#include "UI.h"
#include "../../Minecraft.h"
-// RmlUi includes (Windows macros temporarily suppressed)
#pragma push_macro("byte")
#pragma push_macro("GetNextSibling")
#pragma push_macro("GetFirstChild")
@@ -21,8 +19,7 @@
#pragma pop_macro("byte")
UIScene_SettingsMenu::UIScene_SettingsMenu(int iPad, void *initData, UILayer *parentLayer)
- : UIScene(iPad, parentLayer)
- , m_document(nullptr)
+ : UIScene_RmlBase(iPad, parentLayer)
{
Rml::Context* ctx = RmlManager::Get().GetContext();
if (!ctx)
@@ -32,40 +29,26 @@ UIScene_SettingsMenu::UIScene_SettingsMenu(int iPad, void *initData, UILayer *pa
}
m_document = ctx->LoadDocument("SettingsMenu.rml");
- if (m_document)
- {
- m_document->Show();
-
- // Apply conditional visibility matching original Iggy scene behavior
- bool bNotInGame = (Minecraft::GetInstance()->level == nullptr);
-
- // Audio and Graphics: hidden if not primary pad
- if (ProfileManager.GetPrimaryPad() != m_iPad)
- {
- auto* elAudio = m_document->GetElementById("audio");
- if (elAudio) elAudio->SetProperty("display", "none");
- auto* elGraphics = m_document->GetElementById("graphics");
- if (elGraphics) elGraphics->SetProperty("display", "none");
- }
-
- // Register button click listeners
- m_document->GetElementById("options")->AddEventListener(Rml::EventId::Click, this);
- m_document->GetElementById("audio")->AddEventListener(Rml::EventId::Click, this);
- m_document->GetElementById("controls")->AddEventListener(Rml::EventId::Click, this);
- m_document->GetElementById("graphics")->AddEventListener(Rml::EventId::Click, this);
- m_document->GetElementById("ui")->AddEventListener(Rml::EventId::Click, this);
- m_document->GetElementById("reset_defaults")->AddEventListener(Rml::EventId::Click, this);
-
- // Focus first visible button
- m_document->GetElementById("options")->Focus();
- }
- else
+ if (!m_document)
{
app.DebugPrintf("[RmlSettingsMenu] Failed to load SettingsMenu.rml\n");
+ return;
}
- updateComponents();
+ m_document->Show();
+ if (ProfileManager.GetPrimaryPad() != m_iPad)
+ {
+ auto* elAudio = m_document->GetElementById("audio");
+ if (elAudio) elAudio->SetProperty("display", "none");
+ auto* elGraphics = m_document->GetElementById("graphics");
+ if (elGraphics) elGraphics->SetProperty("display", "none");
+ }
+
+ RegisterEvents({ "options", "audio", "controls", "graphics", "ui", "reset_defaults" });
+ m_document->GetElementById("options")->Focus();
+
+ updateComponents();
ui.HidePressStart();
TelemetryManager->RecordMenuShown(m_iPad, eUIScene_SettingsMenu, 0);
}
@@ -74,101 +57,11 @@ UIScene_SettingsMenu::~UIScene_SettingsMenu()
{
if (m_document)
{
- m_document->GetElementById("options")->RemoveEventListener(Rml::EventId::Click, this);
- m_document->GetElementById("audio")->RemoveEventListener(Rml::EventId::Click, this);
- m_document->GetElementById("controls")->RemoveEventListener(Rml::EventId::Click, this);
- m_document->GetElementById("graphics")->RemoveEventListener(Rml::EventId::Click, this);
- m_document->GetElementById("ui")->RemoveEventListener(Rml::EventId::Click, this);
- m_document->GetElementById("reset_defaults")->RemoveEventListener(Rml::EventId::Click, this);
+ UnregisterEvents({ "options", "audio", "controls", "graphics", "ui", "reset_defaults" });
m_document->Close();
- m_document = nullptr;
}
}
-void UIScene_SettingsMenu::gainFocus()
-{
- if (!bHasFocus && stealsFocus())
- {
- bHasFocus = true;
- updateTooltips();
- updateComponents();
- if (!m_bFocussedOnce)
- {
- }
- handleGainFocus(m_bFocussedOnce);
- if (bHasFocus)
- m_bFocussedOnce = true;
- if (m_document)
- m_document->Show();
- }
-}
-
-void UIScene_SettingsMenu::handleLoseFocus()
-{
- if (m_document)
- m_document->Hide();
-}
-
-void UIScene_SettingsMenu::updateTooltips()
-{
-}
-
-void UIScene_SettingsMenu::updateComponents()
-{
- bool bNotInGame = (Minecraft::GetInstance()->level == nullptr);
-
- if (bNotInGame)
- {
- m_parentLayer->showComponent(m_iPad, eUIComponent_Panorama, true);
- m_parentLayer->showComponent(m_iPad, eUIComponent_Logo, true);
- }
- else
- {
- m_parentLayer->showComponent(m_iPad, eUIComponent_Panorama, false);
-
- if (app.GetLocalPlayerCount() == 1)
- m_parentLayer->showComponent(m_iPad, eUIComponent_Logo, true);
- else
- m_parentLayer->showComponent(m_iPad, eUIComponent_Logo, false);
- }
-}
-
-void UIScene_SettingsMenu::reloadMovie(bool force)
-{
-}
-
-void UIScene_SettingsMenu::tick()
-{
- m_hasTickedOnce = true;
-
- UIScene::tick();
-
- Rml::Context* ctx = RmlManager::Get().GetContext();
- if (!ctx || !bHasFocus)
- return;
-
- ctx->ProcessMouseMove(g_KBMInput.GetMouseX(), g_KBMInput.GetMouseY(), 0);
-
- if (g_KBMInput.IsMouseButtonPressed(KeyboardMouseInput::MOUSE_LEFT))
- ctx->ProcessMouseButtonDown(0, 0);
- if (g_KBMInput.IsMouseButtonReleased(KeyboardMouseInput::MOUSE_LEFT))
- ctx->ProcessMouseButtonUp(0, 0);
- if (g_KBMInput.IsMouseButtonPressed(KeyboardMouseInput::MOUSE_RIGHT))
- ctx->ProcessMouseButtonDown(1, 0);
- if (g_KBMInput.IsMouseButtonReleased(KeyboardMouseInput::MOUSE_RIGHT))
- ctx->ProcessMouseButtonUp(1, 0);
-
- int wheelDelta = g_KBMInput.GetMouseWheel();
- if (wheelDelta != 0)
- ctx->ProcessMouseWheel(wheelDelta / -120, 0);
-
- ctx->Update();
-}
-
-void UIScene_SettingsMenu::render(S32 width, S32 height, C4JRender::eViewportType viewport)
-{
-}
-
void UIScene_SettingsMenu::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled)
{
Rml::Context* ctx = RmlManager::Get().GetContext();
@@ -192,8 +85,8 @@ void UIScene_SettingsMenu::handleInput(int iPad, int key, bool repeat, bool pres
break;
case ACTION_MENU_CANCEL:
case ACTION_MENU_PAUSEMENU:
- app.CheckGameSettingsChanged(true, iPad);
- navigateBack();
+ app.CheckGameSettingsChanged(true, iPad);
+ navigateBack();
break;
default:
break;
@@ -217,6 +110,21 @@ void UIScene_SettingsMenu::ProcessEvent(Rml::Event& event)
}
}
+void UIScene_SettingsMenu::updateComponents()
+{
+ bool bNotInGame = (Minecraft::GetInstance()->level == nullptr);
+ if (bNotInGame)
+ {
+ m_parentLayer->showComponent(m_iPad, eUIComponent_Panorama, true);
+ m_parentLayer->showComponent(m_iPad, eUIComponent_Logo, true);
+ }
+ else
+ {
+ m_parentLayer->showComponent(m_iPad, eUIComponent_Panorama, false);
+ m_parentLayer->showComponent(m_iPad, eUIComponent_Logo, app.GetLocalPlayerCount() == 1);
+ }
+}
+
void UIScene_SettingsMenu::navigateBack()
{
ui.PlayUISFX(eSFX_Back);
@@ -256,24 +164,20 @@ void UIScene_SettingsMenu::OnUI()
void UIScene_SettingsMenu::OnResetToDefaults()
{
UINT uiIDA[2];
- uiIDA[0]=IDS_CONFIRM_CANCEL;
- uiIDA[1]=IDS_CONFIRM_OK;
+ uiIDA[0] = IDS_CONFIRM_CANCEL;
+ uiIDA[1] = IDS_CONFIRM_OK;
- ui.RequestAlertMessage(IDS_DEFAULTS_TITLE, IDS_DEFAULTS_TEXT, uiIDA, 2, m_iPad,&UIScene_SettingsMenu::ResetDefaultsDialogReturned,this);
+ ui.RequestAlertMessage(IDS_DEFAULTS_TITLE, IDS_DEFAULTS_TEXT, uiIDA, 2, m_iPad, &UIScene_SettingsMenu::ResetDefaultsDialogReturned, this);
}
-int UIScene_SettingsMenu::ResetDefaultsDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result)
+int UIScene_SettingsMenu::ResetDefaultsDialogReturned(void *pParam, int iPad, C4JStorage::EMessageResult result)
{
- UIScene_SettingsMenu* pClass = (UIScene_SettingsMenu*)pParam;
+ auto pClass = static_cast(pParam);
- // results switched for this dialog
- if(result==C4JStorage::EMessage_ResultDecline)
+ if (result == C4JStorage::EMessage_ResultDecline)
{
- app.SetDefaultOptions(ProfileManager.GetDashboardProfileSettings(pClass->m_iPad),pClass->m_iPad);
-
- // if the profile data has been changed, then force a profile write
- // It seems we're allowed to break the 5 minute rule if it's the result of a user action
- app.CheckGameSettingsChanged(true,iPad);
+ app.SetDefaultOptions(ProfileManager.GetDashboardProfileSettings(pClass->m_iPad), pClass->m_iPad);
+ app.CheckGameSettingsChanged(true, iPad);
}
return 0;
-}
\ No newline at end of file
+}
diff --git a/Minecraft.Client/Common/UI/UIScene_SettingsMenu.h b/Minecraft.Client/Common/UI/UIScene_SettingsMenu.h
index 7987d825..bf853909 100644
--- a/Minecraft.Client/Common/UI/UIScene_SettingsMenu.h
+++ b/Minecraft.Client/Common/UI/UIScene_SettingsMenu.h
@@ -7,39 +7,21 @@
#undef GetNextSibling
#undef GetFirstChild
-#include "UIScene.h"
-#include
-#include
+#include "UIScene_RmlBase.h"
-// NOTE: pop_macro at end of file
-
-class UIScene_SettingsMenu : public UIScene, public Rml::EventListener
+class UIScene_SettingsMenu : public UIScene_RmlBase
{
public:
UIScene_SettingsMenu(int iPad, void *initData, UILayer *parentLayer);
virtual ~UIScene_SettingsMenu();
- virtual EUIScene getSceneType() { return eUIScene_SettingsMenu; }
+ EUIScene getSceneType() override { return eUIScene_SettingsMenu; }
+ void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled) override;
+ void updateComponents() override;
- virtual void tick();
- virtual void render(S32 width, S32 height, C4JRender::eViewportType viewport);
-
- virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled);
-
- // Override focus/movie lifecycle for RmlUi (no Iggy movie)
- virtual void gainFocus() override;
- virtual void reloadMovie(bool force) override;
-
- // Rml::EventListener
void ProcessEvent(Rml::Event& event) override;
-protected:
- virtual wstring getMoviePath() { return L""; }
-
- virtual void handleLoseFocus() override;
- virtual void updateTooltips() override;
- virtual void updateComponents() override;
-
+private:
void navigateBack();
void OnOptions();
@@ -49,10 +31,7 @@ protected:
void OnUI();
void OnResetToDefaults();
- static int ResetDefaultsDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result);
-
-private:
- Rml::ElementDocument* m_document;
+ static int ResetDefaultsDialogReturned(void *pParam, int iPad, C4JStorage::EMessageResult result);
};
#pragma pop_macro("GetFirstChild")
diff --git a/Minecraft.Client/Common/UI/UIScene_SettingsUIMenu.cpp b/Minecraft.Client/Common/UI/UIScene_SettingsUIMenu.cpp
index 1a3db51e..3706d01c 100644
--- a/Minecraft.Client/Common/UI/UIScene_SettingsUIMenu.cpp
+++ b/Minecraft.Client/Common/UI/UIScene_SettingsUIMenu.cpp
@@ -1,184 +1,419 @@
+#include "stdafx.h"
+
+// Non-RmlUi includes that depend on Windows macros
#include "UI.h"
+#include "../../Minecraft.h"
+
+// RmlUi includes (Windows macros temporarily suppressed)
+#pragma push_macro("byte")
+#pragma push_macro("GetNextSibling")
+#pragma push_macro("GetFirstChild")
+#undef byte
+#undef GetNextSibling
+#undef GetFirstChild
+
#include "UIScene_SettingsUIMenu.h"
+#include "RmlManager.h"
+#include "../../Windows64/KeyboardMouseInput.h"
+#include
+#include
+#include
+#include
-UIScene_SettingsUIMenu::UIScene_SettingsUIMenu(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer)
+#pragma pop_macro("GetFirstChild")
+#pragma pop_macro("GetNextSibling")
+#pragma pop_macro("byte")
+
+static Rml::String WideToUTF8(LPCWSTR wsz)
{
- // Setup all the Iggy references we need for this scene
- initialiseMovie();
-
- m_bNotInGame=(Minecraft::GetInstance()->level==nullptr);
-
- m_checkboxDisplayHUD.init(app.GetString(IDS_CHECKBOX_DISPLAY_HUD),eControl_DisplayHUD,(app.GetGameSettings(m_iPad,eGameSetting_DisplayHUD)!=0));
- m_checkboxDisplayHand.init(app.GetString(IDS_CHECKBOX_DISPLAY_HAND),eControl_DisplayHand,(app.GetGameSettings(m_iPad,eGameSetting_DisplayHand)!=0));
- m_checkboxDisplayDeathMessages.init(app.GetString(IDS_CHECKBOX_DEATH_MESSAGES),eControl_DisplayDeathMessages,(app.GetGameSettings(m_iPad,eGameSetting_DeathMessages)!=0));
- m_checkboxDisplayAnimatedCharacter.init(app.GetString(IDS_CHECKBOX_ANIMATED_CHARACTER),eControl_DisplayAnimatedCharacter,(app.GetGameSettings(m_iPad,eGameSetting_AnimatedCharacter)!=0));
- m_checkboxSplitscreen.init(app.GetString(IDS_CHECKBOX_VERTICAL_SPLIT_SCREEN),eControl_Splitscreen,(app.GetGameSettings(m_iPad,eGameSetting_SplitScreenVertical)!=0));
- m_checkboxShowSplitscreenGamertags.init(app.GetString(IDS_CHECKBOX_DISPLAY_SPLITSCREENGAMERTAGS),eControl_ShowSplitscreenGamertags,(app.GetGameSettings(m_iPad,eGameSetting_DisplaySplitscreenGamertags)!=0));
- m_checkboxShowClassicCrafting.init(IDS_CHECKBOX_CLASSICCRAFTING, eControl_ShowClassicCrafting,(app.GetGameSettings(m_iPad,eGameSetting_ClassicCrafting)!=0));
-
- WCHAR TempString[256];
-
- swprintf( (WCHAR *)TempString, 256, L"%ls: %d", app.GetString( IDS_SLIDER_UISIZE ),app.GetGameSettings(m_iPad,eGameSetting_UISize)+1);
- m_sliderUISize.init(TempString,eControl_UISize,1,3,app.GetGameSettings(m_iPad,eGameSetting_UISize)+1);
-
- swprintf( (WCHAR *)TempString, 256, L"%ls: %d", app.GetString( IDS_SLIDER_UISIZESPLITSCREEN ),app.GetGameSettings(m_iPad,eGameSetting_UISizeSplitscreen)+1);
- m_sliderUISizeSplitscreen.init(TempString,eControl_UISizeSplitscreen,1,3,app.GetGameSettings(m_iPad,eGameSetting_UISizeSplitscreen)+1);
-
- doHorizontalResizeCheck();
-
- bool bInGame=(Minecraft::GetInstance()->level!=nullptr);
- bool bPrimaryPlayer = ProfileManager.GetPrimaryPad()==m_iPad;
-
- // if we're not in the game, we need to use basescene 0
- if(bInGame)
- {
- // If the game has started, then you need to be the host to change the in-game gamertags
- if(!bPrimaryPlayer)
- {
- // hide things we don't want the splitscreen player changing
- removeControl(&m_checkboxSplitscreen, true);
- removeControl(&m_checkboxShowSplitscreenGamertags, true);
- }
- }
-
-
- if(app.GetLocalPlayerCount()>1)
- {
-#if TO_BE_IMPLEMENTED
- app.AdjustSplitscreenScene(m_hObj,&m_OriginalPosition,m_iPad);
-#endif
- }
+ if (!wsz) return Rml::String();
+ int len = WideCharToMultiByte(CP_UTF8, 0, wsz, -1, nullptr, 0, nullptr, nullptr);
+ if (len <= 0) return Rml::String();
+ Rml::String result(static_cast(len) - 1, '\0');
+ WideCharToMultiByte(CP_UTF8, 0, wsz, -1, &result[0], len, nullptr, nullptr);
+ return result;
}
-void UIScene_SettingsUIMenu::updateTooltips()
+struct ToggleEntry { const char* id; eGameSetting setting; };
+struct SliderEntry { const char* id; int* value; int idsString; int setting; };
+
+static const ToggleEntry s_toggles[] =
{
- ui.SetTooltips( m_iPad, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK);
-}
+ { "DisplayHUD", eGameSetting_DisplayHUD },
+ { "DisplayHand", eGameSetting_DisplayHand },
+ { "DisplayDeathMessages", eGameSetting_DeathMessages },
+ { "DisplayAnimatedCharacter", eGameSetting_AnimatedCharacter },
+ { "Splitscreen", eGameSetting_SplitScreenVertical },
+ { "ShowSplitscreenGamertags", eGameSetting_DisplaySplitscreenGamertags },
+ { "ShowClassicCrafting", eGameSetting_ClassicCrafting },
+};
-void UIScene_SettingsUIMenu::updateComponents()
+static const char* s_sliderIds[] = { "UISize", "UISizeSplitscreen" };
+
+UIScene_SettingsUIMenu::UIScene_SettingsUIMenu(int iPad, void *initData, UILayer *parentLayer)
+ : UIScene(iPad, parentLayer)
+ , m_document(nullptr)
+ , m_uiSizeValue(2)
+ , m_uiSizeSplitscreenValue(2)
+ , m_dragSliderIndex(-1)
{
- bool bNotInGame=(Minecraft::GetInstance()->level==nullptr);
- if(bNotInGame)
+ Rml::Context* ctx = RmlManager::Get().GetContext();
+ if (!ctx)
{
- m_parentLayer->showComponent(m_iPad,eUIComponent_Panorama,true);
- m_parentLayer->showComponent(m_iPad,eUIComponent_Logo,true);
+ app.DebugPrintf("[RmlSettingsUIMenu] No RmlUi context available\n");
+ return;
}
- else
+
+ m_document = ctx->LoadDocument("SettingsUIMenu.rml");
+ if (!m_document)
{
- m_parentLayer->showComponent(m_iPad,eUIComponent_Panorama,false);
-
- if( app.GetLocalPlayerCount() == 1 ) m_parentLayer->showComponent(m_iPad,eUIComponent_Logo,true);
- else m_parentLayer->showComponent(m_iPad,eUIComponent_Logo,false);
-
+ app.DebugPrintf("[RmlSettingsUIMenu] Failed to load SettingsUIMenu.rml\n");
+ return;
}
+
+ m_document->Show();
+
+ for (size_t i = 0; i < sizeof(s_toggles) / sizeof(s_toggles[0]); i++)
+ setToggleChecked(s_toggles[i].id, app.GetGameSettings(m_iPad, s_toggles[i].setting) != 0);
+
+ m_uiSizeValue = app.GetGameSettings(m_iPad, eGameSetting_UISize) + 1;
+ m_uiSizeSplitscreenValue = app.GetGameSettings(m_iPad, eGameSetting_UISizeSplitscreen) + 1;
+
+ setSliderValue("UISize", WideToUTF8(app.GetString(IDS_SLIDER_UISIZE)), m_uiSizeValue, 1, 3);
+ setSliderValue("UISizeSplitscreen", WideToUTF8(app.GetString(IDS_SLIDER_UISIZESPLITSCREEN)), m_uiSizeSplitscreenValue, 1, 3);
+
+ registerEvents();
+
+ bool bInGame = (Minecraft::GetInstance()->level != nullptr);
+ bool bPrimaryPlayer = ProfileManager.GetPrimaryPad() == m_iPad;
+
+ if (bInGame && !bPrimaryPlayer)
+ {
+ Rml::Element* el = m_document->GetElementById("Splitscreen");
+ if (el) el->SetProperty("display", "none");
+ el = m_document->GetElementById("ShowSplitscreenGamertags");
+ if (el) el->SetProperty("display", "none");
+ }
+
+ ui.HidePressStart();
+ TelemetryManager->RecordMenuShown(m_iPad, eUIScene_SettingsUIMenu, 0);
}
UIScene_SettingsUIMenu::~UIScene_SettingsUIMenu()
{
+ if (m_document)
+ {
+ deregisterEvents();
+ m_document->Close();
+ m_document = nullptr;
+ }
}
-wstring UIScene_SettingsUIMenu::getMoviePath()
+void UIScene_SettingsUIMenu::registerEvents()
{
- if(app.GetLocalPlayerCount() > 1)
+ for (size_t i = 0; i < sizeof(s_toggles) / sizeof(s_toggles[0]); i++)
{
- return L"SettingsUIMenuSplit";
+ Rml::Element* el = m_document->GetElementById(Rml::String(s_toggles[i].id) + "_toggle");
+ if (el) el->AddEventListener(Rml::EventId::Click, this);
+ }
+
+ for (size_t i = 0; i < sizeof(s_sliderIds) / sizeof(s_sliderIds[0]); i++)
+ {
+ Rml::Element* elTrack = m_document->GetElementById(Rml::String(s_sliderIds[i]) + "_track");
+ if (elTrack) elTrack->AddEventListener(Rml::EventId::Mousedown, this);
+
+ Rml::Element* elThumb = m_document->GetElementById(Rml::String(s_sliderIds[i]) + "_thumb");
+ if (elThumb) elThumb->AddEventListener(Rml::EventId::Mousedown, this);
+ }
+
+ m_document->AddEventListener(Rml::EventId::Mousemove, this);
+ m_document->AddEventListener(Rml::EventId::Mouseup, this);
+}
+
+void UIScene_SettingsUIMenu::deregisterEvents()
+{
+ for (size_t i = 0; i < sizeof(s_toggles) / sizeof(s_toggles[0]); i++)
+ {
+ Rml::Element* el = m_document->GetElementById(Rml::String(s_toggles[i].id) + "_toggle");
+ if (el) el->RemoveEventListener(Rml::EventId::Click, this);
+ }
+
+ for (size_t i = 0; i < sizeof(s_sliderIds) / sizeof(s_sliderIds[0]); i++)
+ {
+ Rml::Element* elTrack = m_document->GetElementById(Rml::String(s_sliderIds[i]) + "_track");
+ if (elTrack) elTrack->RemoveEventListener(Rml::EventId::Mousedown, this);
+
+ Rml::Element* elThumb = m_document->GetElementById(Rml::String(s_sliderIds[i]) + "_thumb");
+ if (elThumb) elThumb->RemoveEventListener(Rml::EventId::Mousedown, this);
+ }
+
+ m_document->RemoveEventListener(Rml::EventId::Mousemove, this);
+ m_document->RemoveEventListener(Rml::EventId::Mouseup, this);
+}
+
+void UIScene_SettingsUIMenu::setToggleChecked(const Rml::String& id, bool checked)
+{
+ Rml::Element* el = m_document->GetElementById(id);
+ if (!el) return;
+ el->SetClass("checked", checked);
+}
+
+bool UIScene_SettingsUIMenu::isToggleChecked(const Rml::String& id)
+{
+ Rml::Element* el = m_document->GetElementById(id);
+ return el && el->IsClassSet("checked");
+}
+
+void UIScene_SettingsUIMenu::setSliderValue(const Rml::String& id, const Rml::String& labelPrefix, int value, int min, int max)
+{
+ Rml::Element* label = m_document->GetElementById(id + "_label");
+ if (label)
+ {
+ char buf[64];
+ snprintf(buf, sizeof(buf), "%s: %d", labelPrefix.c_str(), value);
+ label->SetInnerRML(Rml::String(buf));
+ }
+
+ Rml::Element* thumb = m_document->GetElementById(id + "_thumb");
+ if (thumb)
+ {
+ float fraction = (max > min) ? (float)(value - min) / (float)(max - min) : 0.0f;
+ char buf[16];
+ snprintf(buf, sizeof(buf), "%.0f%%", fraction * 100.0f);
+ thumb->SetProperty("left", Rml::String(buf));
+ }
+}
+
+int UIScene_SettingsUIMenu::getSliderValue(const Rml::String& id)
+{
+ if (id == "UISize")
+ return m_uiSizeValue;
+ if (id == "UISizeSplitscreen")
+ return m_uiSizeSplitscreenValue;
+ return 0;
+}
+
+void UIScene_SettingsUIMenu::handleSliderMouseEvent(int sliderIndex, const Rml::Event& event)
+{
+ if (!m_document) return;
+
+ Rml::String trackId = Rml::String(s_sliderIds[sliderIndex]) + "_track";
+ Rml::Element* track = m_document->GetElementById(trackId);
+ if (!track) return;
+
+ float mouseX = event.GetParameter("mouse_x", 0.0f);
+ Rml::Box box = track->GetBox();
+ float boxLeft = track->GetAbsoluteOffset().x;
+ float boxWidth = box.GetSize().x;
+
+ if (boxWidth > 0.0f)
+ {
+ float fraction = (mouseX - boxLeft) / boxWidth;
+ if (fraction < 0.0f) fraction = 0.0f;
+ if (fraction > 1.0f) fraction = 1.0f;
+
+ int newValue = 1 + static_cast(fraction * 2.0f + 0.5f);
+ if (newValue < 1) newValue = 1;
+ if (newValue > 3) newValue = 3;
+
+ handleSliderMove(sliderIndex, newValue);
+ }
+}
+
+void UIScene_SettingsUIMenu::updateComponents()
+{
+ bool bNotInGame = (Minecraft::GetInstance()->level == nullptr);
+ if (bNotInGame)
+ {
+ m_parentLayer->showComponent(m_iPad, eUIComponent_Panorama, true);
+ m_parentLayer->showComponent(m_iPad, eUIComponent_Logo, true);
}
else
{
- return L"SettingsUIMenu";
+ m_parentLayer->showComponent(m_iPad, eUIComponent_Panorama, false);
+
+ if (app.GetLocalPlayerCount() == 1) m_parentLayer->showComponent(m_iPad, eUIComponent_Logo, true);
+ else m_parentLayer->showComponent(m_iPad, eUIComponent_Logo, false);
}
}
+void UIScene_SettingsUIMenu::gainFocus()
+{
+ if (!bHasFocus && stealsFocus())
+ {
+ bHasFocus = true;
+ updateComponents();
+ handleGainFocus(m_bFocussedOnce);
+ if (bHasFocus)
+ m_bFocussedOnce = true;
+ if (m_document)
+ m_document->Show();
+ }
+}
+
+void UIScene_SettingsUIMenu::handleLoseFocus()
+{
+ if (m_document)
+ m_document->Hide();
+}
+
+void UIScene_SettingsUIMenu::tick()
+{
+ m_hasTickedOnce = true;
+
+ UIScene::tick();
+
+ Rml::Context* ctx = RmlManager::Get().GetContext();
+ if (!ctx || !bHasFocus)
+ return;
+
+ ctx->ProcessMouseMove(g_KBMInput.GetMouseX(), g_KBMInput.GetMouseY(), 0);
+
+ if (g_KBMInput.IsMouseButtonPressed(KeyboardMouseInput::MOUSE_LEFT))
+ ctx->ProcessMouseButtonDown(0, 0);
+ if (g_KBMInput.IsMouseButtonReleased(KeyboardMouseInput::MOUSE_LEFT))
+ ctx->ProcessMouseButtonUp(0, 0);
+ if (g_KBMInput.IsMouseButtonPressed(KeyboardMouseInput::MOUSE_RIGHT))
+ ctx->ProcessMouseButtonDown(1, 0);
+ if (g_KBMInput.IsMouseButtonReleased(KeyboardMouseInput::MOUSE_RIGHT))
+ ctx->ProcessMouseButtonUp(1, 0);
+
+ int wheelDelta = g_KBMInput.GetMouseWheel();
+ if (wheelDelta != 0)
+ ctx->ProcessMouseWheel(wheelDelta / -120, 0);
+
+ RmlManager::Get().Update();
+}
+
+void UIScene_SettingsUIMenu::ProcessEvent(Rml::Event& event)
+{
+ if (event.GetId() == Rml::EventId::Click)
+ {
+ Rml::Element* el = event.GetCurrentElement();
+ const Rml::String& id = el->GetId();
+
+ for (size_t i = 0; i < sizeof(s_toggles) / sizeof(s_toggles[0]); i++)
+ {
+ if (id == Rml::String(s_toggles[i].id) + "_toggle")
+ {
+ Rml::Element* row = el->GetParentNode();
+ if (row)
+ row->SetClass("checked", !row->IsClassSet("checked"));
+ ui.PlayUISFX(eSFX_Press);
+ return;
+ }
+ }
+ }
+ else if (event.GetId() == Rml::EventId::Mousedown)
+ {
+ Rml::Element* el = event.GetCurrentElement();
+ const Rml::String& id = el->GetId();
+
+ for (size_t i = 0; i < sizeof(s_sliderIds) / sizeof(s_sliderIds[0]); i++)
+ {
+ Rml::String trackId = Rml::String(s_sliderIds[i]) + "_track";
+ Rml::String thumbId = Rml::String(s_sliderIds[i]) + "_thumb";
+ if (id == trackId || id == thumbId)
+ {
+ m_dragSliderIndex = static_cast(i);
+ handleSliderMouseEvent(static_cast(i), event);
+ ui.PlayUISFX(eSFX_Scroll);
+ return;
+ }
+ }
+ }
+ else if (event.GetId() == Rml::EventId::Mousemove)
+ {
+ if (m_dragSliderIndex >= 0)
+ {
+ int oldValue = getSliderValue(s_sliderIds[m_dragSliderIndex]);
+ handleSliderMouseEvent(m_dragSliderIndex, event);
+ if (getSliderValue(s_sliderIds[m_dragSliderIndex]) != oldValue)
+ ui.PlayUISFX(eSFX_Scroll);
+ }
+ }
+ else if (event.GetId() == Rml::EventId::Mouseup)
+ {
+ m_dragSliderIndex = -1;
+ }
+}
+
+static void saveToggle(Rml::ElementDocument* doc, int iPad, const ToggleEntry& t)
+{
+ Rml::Element* el = doc->GetElementById(t.id);
+ bool checked = el && el->IsClassSet("checked");
+ app.SetGameSettings(iPad, t.setting, checked ? 1 : 0);
+}
+
void UIScene_SettingsUIMenu::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled)
{
- ui.AnimateKeyPress(iPad, key, repeat, pressed, released);
+ Rml::Context* ctx = RmlManager::Get().GetContext();
+ if (!ctx)
+ return;
- switch(key)
+ if (!pressed)
+ return;
+
+ switch (key)
{
- case ACTION_MENU_CANCEL:
- if(pressed)
- {
- // check the checkboxes
- app.SetGameSettings(m_iPad,eGameSetting_DisplayHUD,m_checkboxDisplayHUD.IsChecked()?1:0);
- app.SetGameSettings(m_iPad,eGameSetting_DisplayHand,m_checkboxDisplayHand.IsChecked()?1:0);
- app.SetGameSettings(m_iPad,eGameSetting_DisplaySplitscreenGamertags,m_checkboxShowSplitscreenGamertags.IsChecked()?1:0);
- app.SetGameSettings(m_iPad,eGameSetting_ClassicCrafting,m_checkboxShowClassicCrafting.IsChecked()?1:0);
- app.SetGameSettings(m_iPad,eGameSetting_DeathMessages,m_checkboxDisplayDeathMessages.IsChecked()?1:0);
- app.SetGameSettings(m_iPad,eGameSetting_AnimatedCharacter,m_checkboxDisplayAnimatedCharacter.IsChecked()?1:0);
-
- // if the splitscreen vertical/horizontal has changed, need to update the scenes
- if(app.GetGameSettings(m_iPad,eGameSetting_SplitScreenVertical)!=(m_checkboxSplitscreen.IsChecked()?1:0))
- {
- // changed
- app.SetGameSettings(m_iPad,eGameSetting_SplitScreenVertical,m_checkboxSplitscreen.IsChecked()?1:0);
-
- // close the xui scenes, so we don't have the navigate backed to menu at the wrong place
- if(app.GetLocalPlayerCount()==2)
- {
- ui.CloseAllPlayersScenes();
- }
- else
- {
- navigateBack();
- }
- }
- else
- {
- navigateBack();
- }
- handled = true;
- }
+ case ACTION_MENU_UP:
+ ctx->ProcessKeyDown(Rml::Input::KI_UP, 0);
+ handled = true;
+ break;
+ case ACTION_MENU_DOWN:
+ ctx->ProcessKeyDown(Rml::Input::KI_DOWN, 0);
+ handled = true;
+ break;
+ case ACTION_MENU_LEFT:
+ ctx->ProcessKeyDown(Rml::Input::KI_LEFT, 0);
+ handled = true;
+ break;
+ case ACTION_MENU_RIGHT:
+ ctx->ProcessKeyDown(Rml::Input::KI_RIGHT, 0);
+ handled = true;
break;
case ACTION_MENU_OK:
-#ifdef __ORBIS__
- case ACTION_MENU_TOUCHPAD_PRESS:
-#endif
- sendInputToMovie(key, repeat, pressed, released);
+ ctx->ProcessKeyDown(Rml::Input::KI_RETURN, 0);
+ handled = true;
break;
- case ACTION_MENU_UP:
- case ACTION_MENU_DOWN:
- case ACTION_MENU_LEFT:
- case ACTION_MENU_RIGHT:
- sendInputToMovie(key, repeat, pressed, released);
+ case ACTION_MENU_CANCEL:
+ case ACTION_MENU_PAUSEMENU:
+ for (size_t i = 0; i < sizeof(s_toggles) / sizeof(s_toggles[0]); i++)
+ saveToggle(m_document, m_iPad, s_toggles[i]);
+
+ if (app.GetGameSettings(m_iPad, eGameSetting_SplitScreenVertical) != (isToggleChecked("Splitscreen") ? 1 : 0))
+ {
+ app.SetGameSettings(m_iPad, eGameSetting_SplitScreenVertical, isToggleChecked("Splitscreen") ? 1 : 0);
+ if (app.GetLocalPlayerCount() == 2)
+ ui.CloseAllPlayersScenes();
+ else
+ navigateBack();
+ }
+ else
+ {
+ navigateBack();
+ }
+ handled = true;
+ break;
+ default:
break;
}
}
-void UIScene_SettingsUIMenu::handleSliderMove(F64 sliderId, F64 currentValue)
+void UIScene_SettingsUIMenu::handleSliderMove(int sliderIndex, int value)
{
- WCHAR TempString[256];
- int value = static_cast(currentValue);
- switch(static_cast(sliderId))
+ int* member = (sliderIndex == 0) ? &m_uiSizeValue : &m_uiSizeSplitscreenValue;
+ const char* id = s_sliderIds[sliderIndex];
+ int idsString = (sliderIndex == 0) ? IDS_SLIDER_UISIZE : IDS_SLIDER_UISIZESPLITSCREEN;
+ eGameSetting setting = (sliderIndex == 0) ? eGameSetting_UISize : eGameSetting_UISizeSplitscreen;
+
+ *member = value;
+ Rml::String prefix = WideToUTF8(app.GetString(idsString));
+ setSliderValue(id, prefix, value, 1, 3);
+
+ if (value != app.GetGameSettings(m_iPad, setting) + 1)
{
- case eControl_UISize:
- m_sliderUISize.handleSliderMove(value);
-
- swprintf( (WCHAR *)TempString, 256, L"%ls: %d", app.GetString( IDS_SLIDER_UISIZE ),value);
- m_sliderUISize.setLabel(TempString);
-
- // is this different from the current value?
- if(value != app.GetGameSettings(m_iPad,eGameSetting_UISize)+1)
- {
- app.SetGameSettings(m_iPad,eGameSetting_UISize,value-1);
- // Apply the changes to the selected text position
- ui.UpdateSelectedItemPos(m_iPad);
- }
-
- break;
- case eControl_UISizeSplitscreen:
- m_sliderUISizeSplitscreen.handleSliderMove(value);
-
- swprintf( (WCHAR *)TempString, 256, L"%ls: %d", app.GetString( IDS_SLIDER_UISIZESPLITSCREEN ),value);
- m_sliderUISizeSplitscreen.setLabel(TempString);
-
- if(value != app.GetGameSettings(m_iPad,eGameSetting_UISizeSplitscreen)+1)
- {
- // slider is 1 to 3
- app.SetGameSettings(m_iPad,eGameSetting_UISizeSplitscreen,value-1);
- // Apply the changes to the selected text position
- ui.UpdateSelectedItemPos(m_iPad);
- }
-
- break;
+ app.SetGameSettings(m_iPad, setting, value - 1);
+ ui.UpdateSelectedItemPos(m_iPad);
}
}
diff --git a/Minecraft.Client/Common/UI/UIScene_SettingsUIMenu.h b/Minecraft.Client/Common/UI/UIScene_SettingsUIMenu.h
index a7635fec..15471482 100644
--- a/Minecraft.Client/Common/UI/UIScene_SettingsUIMenu.h
+++ b/Minecraft.Client/Common/UI/UIScene_SettingsUIMenu.h
@@ -1,55 +1,57 @@
#pragma once
-#include "UIScene.h"
+#pragma push_macro("byte")
+#pragma push_macro("GetNextSibling")
+#pragma push_macro("GetFirstChild")
+#undef byte
+#undef GetNextSibling
+#undef GetFirstChild
-class UIScene_SettingsUIMenu : public UIScene
+#include "UIScene.h"
+#include
+#include
+
+class UIScene_SettingsUIMenu : public UIScene, public Rml::EventListener
{
private:
- enum EControls
- {
- eControl_DisplayHUD,
- eControl_DisplayHand,
- eControl_DisplayDeathMessages,
- eControl_DisplayAnimatedCharacter,
- eControl_Splitscreen,
- eControl_ShowSplitscreenGamertags,
- eControl_ShowClassicCrafting,
- eControl_UISize,
- eControl_UISizeSplitscreen
- };
+ Rml::ElementDocument* m_document;
- UIControl_CheckBox m_checkboxDisplayHUD, m_checkboxDisplayHand, m_checkboxDisplayDeathMessages, m_checkboxDisplayAnimatedCharacter, m_checkboxSplitscreen, m_checkboxShowSplitscreenGamertags, m_checkboxShowClassicCrafting; // Checkboxes
- UIControl_Slider m_sliderUISize, m_sliderUISizeSplitscreen; // Sliders
- UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene)
- UI_MAP_ELEMENT( m_checkboxDisplayHUD, "DisplayHUD")
- UI_MAP_ELEMENT( m_checkboxDisplayHand, "DisplayHand")
- UI_MAP_ELEMENT( m_checkboxDisplayDeathMessages, "DisplayDeathMessages")
- UI_MAP_ELEMENT( m_checkboxDisplayAnimatedCharacter, "DisplayAnimatedCharacter")
- UI_MAP_ELEMENT( m_checkboxSplitscreen, "Splitscreen")
- UI_MAP_ELEMENT( m_checkboxShowSplitscreenGamertags, "ShowSplitscreenGamertags")
- UI_MAP_ELEMENT( m_checkboxShowClassicCrafting, "ShowClassicCrafting")
+ int m_uiSizeValue;
+ int m_uiSizeSplitscreenValue;
+ int m_dragSliderIndex;
- UI_MAP_ELEMENT( m_sliderUISize, "UISize")
- UI_MAP_ELEMENT( m_sliderUISizeSplitscreen, "UISizeSplitscreen")
- UI_END_MAP_ELEMENTS_AND_NAMES()
+ void setToggleChecked(const Rml::String& id, bool checked);
+ bool isToggleChecked(const Rml::String& id);
+ void setSliderValue(const Rml::String& id, const Rml::String& labelPrefix, int value, int min, int max);
+ int getSliderValue(const Rml::String& id);
+
+ void registerEvents();
+ void deregisterEvents();
- bool m_bNotInGame;
public:
UIScene_SettingsUIMenu(int iPad, void *initData, UILayer *parentLayer);
virtual ~UIScene_SettingsUIMenu();
- virtual EUIScene getSceneType() { return eUIScene_SettingsUIMenu;}
-
- virtual void updateTooltips();
+ virtual EUIScene getSceneType() { return eUIScene_SettingsUIMenu; }
+
+ virtual void tick();
virtual void updateComponents();
-protected:
- // TODO: This should be pure virtual in this class
- virtual wstring getMoviePath();
+ virtual void gainFocus() override;
+
+ void ProcessEvent(Rml::Event& event) override;
+
+protected:
+ virtual wstring getMoviePath() { return L""; }
+
+ virtual void handleLoseFocus() override;
-public:
- // INPUT
virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled);
- virtual void handleSliderMove(F64 sliderId, F64 currentValue);
-};
\ No newline at end of file
+ virtual void handleSliderMove(int sliderIndex, int value);
+ void handleSliderMouseEvent(int sliderIndex, const Rml::Event& event);
+};
+
+#pragma pop_macro("GetFirstChild")
+#pragma pop_macro("GetNextSibling")
+#pragma pop_macro("byte")
diff --git a/Minecraft.Client/cmake/sources/Windows.cmake b/Minecraft.Client/cmake/sources/Windows.cmake
index 357e987e..55d5fdda 100644
--- a/Minecraft.Client/cmake/sources/Windows.cmake
+++ b/Minecraft.Client/cmake/sources/Windows.cmake
@@ -123,6 +123,8 @@ set(_MINECRAFT_CLIENT_WINDOWS_COMMON_UI_SCENES
"${CMAKE_CURRENT_SOURCE_DIR}/Common/UI/UIScene_Keyboard.h"
"${CMAKE_CURRENT_SOURCE_DIR}/Common/UI/UIScene_MessageBox.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Common/UI/UIScene_MessageBox.h"
+ "${CMAKE_CURRENT_SOURCE_DIR}/Common/UI/UIScene_RmlBase.cpp"
+ "${CMAKE_CURRENT_SOURCE_DIR}/Common/UI/UIScene_RmlBase.h"
"${CMAKE_CURRENT_SOURCE_DIR}/Common/UI/UIScene_QuadrantSignin.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Common/UI/UIScene_QuadrantSignin.h"
"${CMAKE_CURRENT_SOURCE_DIR}/Common/UI/UIScene_Timer.cpp"