Add RmlUi: SettingsUIMenu. And RMLUI Menu Cleanup (#8)

This commit is contained in:
GabsPuNs
2026-06-20 16:34:34 -04:00
committed by GitHub
32 changed files with 959 additions and 688 deletions

View File

@@ -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%);
}

View File

@@ -0,0 +1,57 @@
<rml>
<head>
<title>UI Settings</title>
<link type="text/rcss" href="SettingsUIMenu.rcss"/>
</head>
<body>
<div id="settings_ui_menu">
<div id="controls">
<div id="DisplayHUD" class="toggle_row checked">
<button id="DisplayHUD_toggle"><span class="toggle_switch"><span class="tick_mark"></span></span></button>
<span class="toggle_label">[IDS_CHECKBOX_DISPLAY_HUD]</span>
</div>
<div id="DisplayHand" class="toggle_row checked">
<button id="DisplayHand_toggle"><span class="toggle_switch"><span class="tick_mark"></span></span></button>
<span class="toggle_label">[IDS_CHECKBOX_DISPLAY_HAND]</span>
</div>
<div id="DisplayDeathMessages" class="toggle_row checked">
<button id="DisplayDeathMessages_toggle"><span class="toggle_switch"><span class="tick_mark"></span></span></button>
<span class="toggle_label">[IDS_CHECKBOX_DEATH_MESSAGES]</span>
</div>
<div id="DisplayAnimatedCharacter" class="toggle_row checked">
<button id="DisplayAnimatedCharacter_toggle"><span class="toggle_switch"><span class="tick_mark"></span></span></button>
<span class="toggle_label">[IDS_CHECKBOX_ANIMATED_CHARACTER]</span>
</div>
<div id="Splitscreen" class="toggle_row checked">
<button id="Splitscreen_toggle"><span class="toggle_switch"><span class="tick_mark"></span></span></button>
<span class="toggle_label">[IDS_CHECKBOX_VERTICAL_SPLIT_SCREEN]</span>
</div>
<div id="ShowSplitscreenGamertags" class="toggle_row checked">
<button id="ShowSplitscreenGamertags_toggle"><span class="toggle_switch"><span class="tick_mark"></span></span></button>
<span class="toggle_label">[IDS_CHECKBOX_DISPLAY_SPLITSCREENGAMERTAGS]</span>
</div>
<div id="ShowClassicCrafting" class="toggle_row checked">
<button id="ShowClassicCrafting_toggle"><span class="toggle_switch"><span class="tick_mark"></span></span></button>
<span class="toggle_label">[IDS_CHECKBOX_CLASSICCRAFTING]</span>
</div>
<div id="UISize" class="slider_row">
<div class="slider_container">
<div class="slider_track" id="UISize_track">
<div class="slider_thumb" id="UISize_thumb"></div>
<span class="slider_label" id="UISize_label">[IDS_SLIDER_UISIZE]: 2</span>
</div>
</div>
</div>
<div id="UISizeSplitscreen" class="slider_row">
<div class="slider_container">
<div class="slider_track" id="UISizeSplitscreen_track">
<div class="slider_thumb" id="UISizeSplitscreen_thumb"></div>
<span class="slider_label" id="UISizeSplitscreen_label">[IDS_SLIDER_UISIZESPLITSCREEN]: 2</span>
</div>
</div>
</div>
</div>
</div>
</body>
</rml>

View File

@@ -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"

View File

@@ -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);
}

View File

@@ -7,39 +7,21 @@
#undef GetNextSibling
#undef GetFirstChild
#include "UIScene.h"
#include <RmlUi/Core/EventListener.h>
#include <RmlUi/Core/ElementDocument.h>
#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")

View File

@@ -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)

View File

@@ -7,16 +7,12 @@
#undef GetNextSibling
#undef GetFirstChild
#include "UIScene.h"
#include <RmlUi/Core/EventListener.h>
#include <RmlUi/Core/ElementDocument.h>
// 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")
#pragma pop_macro("byte")

View File

@@ -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,12 +98,18 @@ 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);
@@ -204,7 +202,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;
@@ -223,11 +221,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;
}
@@ -246,12 +244,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;
@@ -265,7 +258,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;

View File

@@ -7,41 +7,28 @@
#undef GetNextSibling
#undef GetFirstChild
#include "UIScene.h"
#include <RmlUi/Core/EventListener.h>
#include <RmlUi/Core/ElementDocument.h>
#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;

View File

@@ -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);
@@ -181,9 +169,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;
@@ -198,8 +183,6 @@ void UIScene_PauseMenu::handleInput(int iPad, int key, bool repeat, bool pressed
handled = true;
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);
@@ -274,11 +257,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];
@@ -288,7 +269,6 @@ void UIScene_PauseMenu::OnSaveGame()
}
else
{
// Flag a app action of save game
app.SetAction(m_iPad, eAppAction_SaveGame);
}
}
@@ -299,7 +279,6 @@ void UIScene_PauseMenu::OnExitGame()
UINT uiIDA[3];
// Is it the primary player exiting?
if (m_iPad == ProfileManager.GetPrimaryPad())
{
int playTime = -1;
@@ -334,7 +313,7 @@ void UIScene_PauseMenu::OnExitGame()
}
}
}
else // Non-primary pad: exit directly without dialog
else
{
int playTime = -1;
if (pMinecraft->localplayers[m_iPad] != NULL)
@@ -346,4 +325,4 @@ void UIScene_PauseMenu::OnExitGame()
app.SetAction(m_iPad, eAppAction_ExitPlayer);
return;
}
}
}

View File

@@ -7,38 +7,22 @@
#undef GetNextSibling
#undef GetFirstChild
#include "UIScene.h"
#include "UIScene_RmlBase.h"
#include "IUIScene_PauseMenu.h"
#include <RmlUi/Core/EventListener.h>
#include <RmlUi/Core/ElementDocument.h>
// 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")

View File

@@ -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 <RmlUi/Core/Input.h>
#include <RmlUi/Core/Context.h>
#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<const char*> 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<const char*> ids)
{
if (!m_document) return;
for (const char* id : ids)
{
auto* el = m_document->GetElementById(id);
if (el) el->RemoveEventListener(Rml::EventId::Click, this);
}
}

View File

@@ -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 <RmlUi/Core/EventListener.h>
#include <RmlUi/Core/ElementDocument.h>
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<const char*> ids);
void UnregisterEvents(std::initializer_list<const char*> ids);
Rml::ElementDocument* m_document = nullptr;
};
#pragma pop_macro("GetFirstChild")
#pragma pop_macro("GetNextSibling")
#pragma pop_macro("byte")

View File

@@ -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();
@@ -221,6 +114,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);
@@ -260,24 +168,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<UIScene_SettingsMenu*>(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;
}
}

View File

@@ -7,39 +7,21 @@
#undef GetNextSibling
#undef GetFirstChild
#include "UIScene.h"
#include <RmlUi/Core/EventListener.h>
#include <RmlUi/Core/ElementDocument.h>
#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")

View File

@@ -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 <RmlUi/Core/Input.h>
#include <RmlUi/Core/Context.h>
#include <RmlUi/Core/Box.h>
#include <RmlUi/Core/Element.h>
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<size_t>(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<float>("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<int>(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<int>(i);
handleSliderMouseEvent(static_cast<int>(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<int>(currentValue);
switch(static_cast<int>(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);
}
}

View File

@@ -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 <RmlUi/Core/EventListener.h>
#include <RmlUi/Core/ElementDocument.h>
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);
};
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")

View File

@@ -1,4 +1,4 @@
#include "RmlUi_Renderer_DX12.h"
#include "RmlUi_Renderer_DX12.h"
#include "RmlUi_Backend.h"
#include <RmlUi/Core/Core.h>
#include <RmlUi/Core/DecorationTypes.h>

View File

@@ -98,7 +98,11 @@ endfunction()
- target: The name of the target to set
]]
function(set_common_target_options target)
target_compile_features(${target} PUBLIC cxx_std_17)
if(MSVC)
set_target_properties(${target} PROPERTIES CXX_STANDARD 17 CXX_STANDARD_REQUIRED ON)
else()
target_compile_features(${target} PUBLIC cxx_std_17)
endif()
set_target_properties(${target} PROPERTIES C_EXTENSIONS OFF CXX_EXTENSIONS OFF)
if(RMLUI_COMPILER_OPTIONS)

View File

@@ -1,4 +1,4 @@
#include <RmlUi/Core.h>
#include <RmlUi/Core.h>
#include <RmlUi/Core/TransformPrimitive.h>
#include <RmlUi/Debugger.h>
#include <RmlUi_Backend.h>

View File

@@ -1,4 +1,4 @@
#include <RmlUi/Core.h>
#include <RmlUi/Core.h>
#include <RmlUi/Debugger.h>
#include <RmlUi_Backend.h>
#include <Shell.h>

View File

@@ -1,4 +1,4 @@
#include <RmlUi/Core.h>
#include <RmlUi/Core.h>
#include <RmlUi/Debugger.h>
#include <RmlUi_Backend.h>
#include <Shell.h>

View File

@@ -1,4 +1,4 @@
#include "DemoEventListener.h"
#include "DemoEventListener.h"
#include "DemoWindow.h"
#include <RmlUi/Core/ElementDocument.h>
#include <RmlUi/Core/Factory.h>

View File

@@ -1,4 +1,4 @@
#include <RmlUi/Core.h>
#include <RmlUi/Core.h>
#include <RmlUi/Debugger.h>
#include <RmlUi_Backend.h>
#include <Shell.h>

View File

@@ -1,4 +1,4 @@
#include "FontEngineInterfaceHarfBuzz.h"
#include "FontEngineInterfaceHarfBuzz.h"
#include <RmlUi/Core.h>
#include <RmlUi/Debugger.h>
#include <RmlUi_Backend.h>

View File

@@ -1,4 +1,4 @@
#include <RmlUi/Core/Platform.h>
#include <RmlUi/Core/Platform.h>
#if !defined RMLUI_IME_SAMPLE_USE_NOTO_FONTS
#include "SystemFontWin32.h"
#endif

View File

@@ -34,7 +34,10 @@ EventDispatcher::~EventDispatcher()
{
// Detach from all event dispatchers
for (const auto& event : listeners)
event.listener->OnDetach(element);
{
if (event.listener)
event.listener->OnDetach(element);
}
}
void EventDispatcher::AttachEvent(const EventId id, EventListener* listener, const bool in_capture_phase)
@@ -64,7 +67,10 @@ void EventDispatcher::DetachEvent(const EventId id, EventListener* listener, con
void EventDispatcher::DetachAllEvents()
{
for (const auto& event : listeners)
event.listener->OnDetach(element);
{
if (event.listener)
event.listener->OnDetach(element);
}
listeners.clear();
@@ -198,26 +204,32 @@ void EventDispatcher::CollectListeners(int dom_distance_from_target, const Event
const bool in_target_phase = (dom_distance_from_target == 0);
if (in_target_phase)
{
// Listeners always attach to target phase, but make sure the event can actually execute in target phase.
if ((int)event_executes_in_phases & (int)EventPhase::Target)
if (in_target_phase)
{
// Listeners always attach to target phase, but make sure the event can actually execute in target phase.
if ((int)event_executes_in_phases & (int)EventPhase::Target)
{
for (auto it = begin; it != end; ++it)
{
if (auto* listener = it->listener.get())
collect_listeners.emplace_back(element, listener, dom_distance_from_target, false);
}
}
}
else
{
// Iterate through all the listeners and collect those matching the event execution phase.
for (auto it = begin; it != end; ++it)
collect_listeners.emplace_back(element, it->listener, dom_distance_from_target, false);
{
// Listeners will either attach to capture or bubble phase, make sure the event can execute in the same phase.
const EventPhase listener_executes_in_phase = (it->in_capture_phase ? EventPhase::Capture : EventPhase::Bubble);
if ((int)event_executes_in_phases & (int)listener_executes_in_phase)
{
if (auto* listener = it->listener.get())
collect_listeners.emplace_back(element, listener, dom_distance_from_target, it->in_capture_phase);
}
}
}
}
else
{
// Iterate through all the listeners and collect those matching the event execution phase.
for (auto it = begin; it != end; ++it)
{
// Listeners will either attach to capture or bubble phase, make sure the event can execute in the same phase.
const EventPhase listener_executes_in_phase = (it->in_capture_phase ? EventPhase::Capture : EventPhase::Bubble);
if ((int)event_executes_in_phases & (int)listener_executes_in_phase)
collect_listeners.emplace_back(element, it->listener, dom_distance_from_target, it->in_capture_phase);
}
}
}
String EventDispatcher::ToString() const

View File

@@ -1,6 +1,7 @@
#pragma once
#include "../../Include/RmlUi/Core/Event.h"
#include "../../Include/RmlUi/Core/EventListener.h"
#include "../../Include/RmlUi/Core/Types.h"
namespace Rml {
@@ -11,12 +12,12 @@ struct CollectedListener;
struct EventListenerEntry {
EventListenerEntry(const EventId id, EventListener* listener, const bool in_capture_phase) :
id(id), in_capture_phase(in_capture_phase), listener(listener)
id(id), in_capture_phase(in_capture_phase), listener(listener ? listener->GetObserverPtr() : ObserverPtr<EventListener>())
{}
EventId id;
bool in_capture_phase;
EventListener* listener;
ObserverPtr<EventListener> listener;
};
/**

View File

@@ -412,10 +412,6 @@ bool Factory::InstanceElementText(Element* parent, const String& in_text)
text_element->SetText(text);
// Store original untranslated text for runtime re-translation support.
if (in_text.size() > 2 && in_text[0] == '[')
element->SetAttribute("data-rml-source", in_text);
// Add to active node.
parent->AppendChild(std::move(element));
}

View File

@@ -1,4 +1,4 @@
#include "../Common/TestsShell.h"
#include "../Common/TestsShell.h"
#include <RmlUi/Core/Context.h>
#include <RmlUi/Core/Element.h>
#include <RmlUi/Core/ElementDocument.h>

View File

@@ -1,4 +1,4 @@
#include "../Common/TestsInterface.h"
#include "../Common/TestsInterface.h"
#include "../Common/TestsShell.h"
#include <RmlUi/Core/Context.h>
#include <RmlUi/Core/Core.h>
@@ -302,7 +302,7 @@ TEST_CASE("core.release_resources")
CHECK(counters.generate_texture == counter_generate_before);
// However, when we display a non-ASCII character not part of the initial cache, the font texture needs to be regenerated.
element->SetInnerRML(reinterpret_cast<const char*>(u8"π"));
element->SetInnerRML(reinterpret_cast<const char*>(u8"p"));
TestsShell::RenderLoop();
CHECK(counters.generate_texture == counter_generate_before + 1);
CHECK(counters.release_texture == counter_release_before + 1);

View File

@@ -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"