Files
GabsPuNs-Project_Zenith_Main/Minecraft.Client/RmlManager.cpp
2026-06-11 22:07:34 -04:00

193 lines
5.0 KiB
C++

#include "RmlManager.h"
extern ID3D11Device* g_pd3dDevice;
extern ID3D11DeviceContext* g_pImmediateContext;
extern ID3D11RenderTargetView* g_pRenderTargetView;
RmlManager& RmlManager::Get()
{
static RmlManager instance;
return instance;
}
RmlManager::RmlManager()
: m_initialised(false)
, m_context(nullptr)
{
}
RmlManager::~RmlManager()
{
Shutdown();
}
bool RmlManager::Init(int viewport_width, int viewport_height)
{
if (m_initialised)
return true;
m_file_interface = std::make_unique<FileInterface_Game>();
m_system_interface = std::make_unique<SystemInterface_Win64>();
m_renderer = std::make_unique<RenderInterface_D3D11>(g_pd3dDevice, g_pImmediateContext);
if (!m_renderer->IsInitialised())
{
app.DebugPrintf("[RmlManager] Renderer failed to initialise\n");
return false;
}
// Set asset path for RmlUi files (relative to exe directory)
Rml::String assetPath = utils.GetExeDir().string() + "/Assets/UI";
m_file_interface->SetAssetPath(assetPath);
Rml::SetRenderInterface(m_renderer.get());
Rml::SetSystemInterface(m_system_interface.get());
Rml::SetFileInterface(m_file_interface.get());
if (!Rml::Initialise())
{
app.DebugPrintf("[RmlManager] RmlUi Core failed to initialise\n");
return false;
}
// GabsPuN: Hardcoded. Is this really needed?
/*
// Load default fonts
Rml::LoadFontFace("C:/Windows/Fonts/segoeui.ttf", false);
Rml::LoadFontFace("C:/Windows/Fonts/segoeuib.ttf", false);
Rml::LoadFontFace("C:/Windows/Fonts/segoeuii.ttf", false);
Rml::LoadFontFace("C:/Windows/Fonts/segoeuiz.ttf", false);
*/
// Minecraft's UI fonts (from tryashtar/minecraft-ttf)
if (!Rml::LoadFontFace(assetPath + "/fonts/Mojangles.ttf", "Minecraft Default", Rml::Style::FontStyle::Normal, Rml::Style::FontWeight::Normal, false))
app.DebugPrintf("[RmlManager] FAILED loading Mojangles.ttf\n");
if (!Rml::LoadFontFace(assetPath + "/fonts/MinecraftTen.ttf", "Minecraft Default", Rml::Style::FontStyle::Normal, Rml::Style::FontWeight::Bold, true))
app.DebugPrintf("[RmlManager] FAILED loading MinecraftTen.ttf\n");
m_context = Rml::CreateContext("main", Rml::Vector2i(viewport_width, viewport_height));
if (!m_context)
{
app.DebugPrintf("[RmlManager] Failed to create RmlUi context\n");
Rml::Shutdown();
return false;
}
app.DebugPrintf("[RmlManager] Context created (%dx%d)\n", viewport_width, viewport_height);
m_renderer->SetViewport(viewport_width, viewport_height);
m_initialised = true;
app.DebugPrintf("[RmlManager] Initialised (%dx%d)\n", viewport_width, viewport_height);
UpdateDpRatio();
return true;
}
void RmlManager::Shutdown()
{
if (!m_initialised)
return;
if (m_context)
{
m_context->UnloadAllDocuments();
Rml::RemoveContext(m_context->GetName());
m_context = nullptr;
}
Rml::Shutdown();
m_renderer.reset();
m_system_interface.reset();
m_file_interface.reset();
m_initialised = false;
app.DebugPrintf("[RmlManager] Shutdown\n");
}
void RmlManager::Update()
{
if (!m_initialised || !m_context)
return;
m_context->Update();
}
void RmlManager::Render()
{
if (!m_initialised || !m_context)
return;
// Ensure we render to the backbuffer (gamma post-process may have restored a
// different RTV). Use the singleton backbuffer RTV that the rest of the engine
// binds at frame start.
if (g_pRenderTargetView)
{
ID3D11DepthStencilView* nullDSV = nullptr;
g_pImmediateContext->OMSetRenderTargets(1, &g_pRenderTargetView, nullDSV);
}
// Clear any SRV still bound from gamma post-process so it doesn't
// interfere with RmlUi's own texture binding.
ID3D11ShaderResourceView* nullSRV[1] = { nullptr };
g_pImmediateContext->PSSetShaderResources(0, 1, nullSRV);
m_renderer->BeginFrame();
//GabsPuN: This DebugPrintf is called each frame when RMLUI is not used.
/*
int docCount = 0;
for (int i = 0; i < m_context->GetNumDocuments(); i++)
{
auto* doc = m_context->GetDocument(i);
if (doc && doc->IsVisible())
docCount++;
}
if (docCount == 0)
app.DebugPrintf("[RmlManager] WARNING: No visible documents in context\n");
*/
m_context->Render();
m_renderer->EndFrame();
}
void RmlManager::OnResize(int width, int height)
{
if (!m_initialised || !m_context)
return;
m_context->SetDimensions(Rml::Vector2i(width, height));
m_renderer->SetViewport(width, height);
}
// GabsPuN: Taken from the Quake port as something temporary
void RmlManager::UpdateDpRatio()
{
if (!m_context)
return;
int width = GetSystemMetrics(SM_CXSCREEN);
int height = GetSystemMetrics(SM_CYSCREEN);
float scale_x = static_cast<float>(width) / 1920;
float scale_y = static_cast<float>(height) / 1080;
float base_ratio = (scale_x < scale_y) ? scale_x : scale_y;
float blend = (base_ratio > 1.0f) ? std::min(base_ratio - 1.0f, 1.0f) : 0.0f;
float effective_dpi = (1.0f - blend) + blend;
float auto_dp = base_ratio * effective_dpi;
float viewport_cap = 0.88f * static_cast<float>(height) / 850.0f;
if (auto_dp > viewport_cap)
auto_dp = viewport_cap;
float dp_ratio = auto_dp;
if (dp_ratio < 0.5f)
dp_ratio = 0.5f;
if (dp_ratio > 3.0f)
dp_ratio = 3.0f;
m_context->SetDensityIndependentPixelRatio(dp_ratio);
}