Add initial AnyAspectRatio support

This commit is contained in:
Fayaz Shaikh 2026-03-03 15:51:00 -05:00
parent 384b9f4445
commit 158881800c
12 changed files with 249 additions and 18 deletions

View file

@ -181,7 +181,9 @@ UIController::UIController()
// 4J Stu - This is a bit of a hack until we change the Minecraft initialisation to store the proper screen size for other platforms // 4J Stu - This is a bit of a hack until we change the Minecraft initialisation to store the proper screen size for other platforms
#if defined _WINDOWS64 || defined _DURANGO || defined __ORBIS__ #if defined _WINDOWS64 || defined _DURANGO || defined __ORBIS__
m_fScreenWidth = 1920.0f; m_fScreenWidth = 1920.0f;
m_fScreenHeight = 1080.0f; m_fScreenHeight = 1080.0f;\
aar_Width = 1920.0f;
aar_Height = 1080.0f;
m_bScreenWidthSetup = false; m_bScreenWidthSetup = false;
#else #else
m_fScreenWidth = 1280.0f; m_fScreenWidth = 1280.0f;
@ -1209,10 +1211,37 @@ void UIController::getRenderDimensions(C4JRender::eViewportType viewport, S32 &w
{ {
switch( viewport ) switch( viewport )
{ {
case C4JRender::VIEWPORT_TYPE_FULLSCREEN: case C4JRender::VIEWPORT_TYPE_FULLSCREEN:
width = (S32)(getScreenWidth()); {
height = (S32)(getScreenHeight()); // AnyAspectRatio support by Fayaz
break; // We must clamp the render dimensions to 16:9 so Iggy doesn't stretch content.
float targetAspect = 16.0f / 9.0f;
float currentAspect = aar_Width / aar_Height;
if (currentAspect > targetAspect)
{
// Screen is Ultrawide (Wider than 16:9):
// Lock height to screen, calculate width based on 16:9 ratio
width = (S32)(aar_Height * targetAspect);
height = (S32)aar_Height;
}
else if (currentAspect < targetAspect)
{
// Screen is Tall (Taller than 16:9, e.g. 4:3, 16:10, Steam Deck):
// Lock width to screen, calculate height based on 16:9 ratio
width = (S32)aar_Width;
// Height = Width / 1.777
height = (S32)(aar_Width / targetAspect);
}
else
{
// Standard 16:9: Use actual screen dimensions
width = (S32)aar_Width;
height = (S32)aar_Height;
}
}
break;
case C4JRender::VIEWPORT_TYPE_SPLIT_TOP: case C4JRender::VIEWPORT_TYPE_SPLIT_TOP:
case C4JRender::VIEWPORT_TYPE_SPLIT_BOTTOM: case C4JRender::VIEWPORT_TYPE_SPLIT_BOTTOM:
width = (S32)(getScreenWidth() / 2); width = (S32)(getScreenWidth() / 2);
@ -1233,16 +1262,81 @@ void UIController::getRenderDimensions(C4JRender::eViewportType viewport, S32 &w
} }
} }
// AAR - Handle window resizing by updating the width and height variables
// AAR - Handle window resizing by updating the width and height variables
// AAR - Handle window resizing by updating the width and height variables
void UIController::resize(S32 width, S32 height)
{
// Store the new dimensions
aar_Width = (float)width;
aar_Height = (float)height;
m_fScreenWidth = (float)width;
m_fScreenHeight = (float)height;
// Notify all UIGroups about the resize
for (unsigned int i = 0; i < eUIGroup_COUNT; ++i)
{
if (m_groups[i])
{
m_groups[i]->OnResize(width, height);
}
}
// Force a render position update on next render
m_currentRenderViewport = (C4JRender::eViewportType)-1; // Force recalculation
// Update the Iggy global display if needed
// (Some Iggy versions need global display size updates)
}
void UIController::setupRenderPosition(C4JRender::eViewportType viewport) void UIController::setupRenderPosition(C4JRender::eViewportType viewport)
{ {
if(m_bCustomRenderPosition || m_currentRenderViewport != viewport) // AAR - Force update for fullscreen to ensure offsets are calculated (fix for constructor init issue)
if(m_bCustomRenderPosition || m_currentRenderViewport != viewport || viewport == C4JRender::VIEWPORT_TYPE_FULLSCREEN)
{ {
m_currentRenderViewport = viewport; m_currentRenderViewport = viewport;
m_bCustomRenderPosition = false; m_bCustomRenderPosition = false;
S32 xPos = 0; S32 xPos = 0;
S32 yPos = 0; S32 yPos = 0;
switch( viewport ) switch( viewport )
{ {
case C4JRender::VIEWPORT_TYPE_FULLSCREEN:
{
// AnyAspectRatio support by Fayaz (related code has AAR prefix)
// Calculate target 16:9 width based on current height
float targetAspect = 16.0f / 9.0f;
float currentAspect = aar_Width / aar_Height;
// Screen is wider than 16:9 (Ultrawide)
if (currentAspect > targetAspect)
{
// find what the width of 16/9 would be at this height
S32 width169 = (S32)(aar_Height * targetAspect);
// Center the UI by setting the width to have the difference of 16/9 width and current width
xPos = (S32)(aar_Width - width169) * 0.5;
yPos = 0;
}
// Screen is taller than 16:9 (like 4:3 or Steam Deck)
else if (currentAspect < targetAspect)
{
// find what the height of 16/9 would be at this width
S32 height169 = (S32)(aar_Width / targetAspect);
// Center the UI by setting the height to have the difference of 16/9 height and current height
xPos = 0;
yPos = (S32)(aar_Height - height169) * -0.5; // 0, 0 is top left, so we need to negate the yPos
}
// Otherwise, assume current aspect ratio is 16:9
else
{
// 16:9 - Fill screen normally (starts at 0,0)
xPos = 0;
yPos = 0;
}
}
break;
case C4JRender::VIEWPORT_TYPE_SPLIT_TOP: case C4JRender::VIEWPORT_TYPE_SPLIT_TOP:
xPos = (S32)(getScreenWidth() / 4); xPos = (S32)(getScreenWidth() / 4);
break; break;
@ -1317,7 +1411,7 @@ void UIController::setupCustomDrawGameState()
PIXBeginNamedEvent(0,"Final setup"); PIXBeginNamedEvent(0,"Final setup");
glMatrixMode(GL_PROJECTION); glMatrixMode(GL_PROJECTION);
glLoadIdentity(); glLoadIdentity();
glOrtho(0, m_fScreenWidth, m_fScreenHeight, 0, 1000, 3000); glOrtho(0, aar_Width, aar_Height, 0, 1000, 3000); // AAR - Changed to allow resizing
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
glEnable(GL_ALPHA_TEST); glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER, 0.1f); glAlphaFunc(GL_GREATER, 0.1f);
@ -1365,16 +1459,21 @@ void UIController::setupCustomDrawMatrices(UIScene *scene, CustomDrawData *custo
{ {
m_fScreenWidth=(float)pMinecraft->width_phys; m_fScreenWidth=(float)pMinecraft->width_phys;
m_fScreenHeight=(float)pMinecraft->height_phys; m_fScreenHeight=(float)pMinecraft->height_phys;
aar_Width = (float)pMinecraft->width_phys;
aar_Height = (float)pMinecraft->height_phys;
m_bScreenWidthSetup = true; m_bScreenWidthSetup = true;
} }
} }
glLoadIdentity(); glLoadIdentity();
glTranslatef(0, 0, -2000); glTranslatef(0, 0, -2000);
// Fayaz - Apply the calculated tile origin
glTranslatef((float)m_tileOriginX, (float)m_tileOriginY, 0.0f);
// Iggy translations are based on a double-size target, with the origin in the centre // Iggy translations are based on a double-size target, with the origin in the centre
glTranslatef((m_fScreenWidth + customDrawRegion->mat[(0*4)+3]*m_fScreenWidth)/2,(m_fScreenHeight - customDrawRegion->mat[(1*4)+3]*m_fScreenHeight)/2,0); glTranslatef((aar_Width + customDrawRegion->mat[(0 * 4) + 3] * aar_Width) / 2, (aar_Height - customDrawRegion->mat[(1 * 4) + 3] * aar_Height) / 2, 0);
// Iggy scales are based on a double-size target // Iggy scales are based on a double-size target
glScalef( (m_fScreenWidth * customDrawRegion->mat[0])/2,(m_fScreenHeight * -customDrawRegion->mat[(1*4) + 1])/2,1.0f); glScalef((aar_Width * customDrawRegion->mat[0]) / 2, (aar_Height * -customDrawRegion->mat[(1 * 4) + 1]) / 2, 1.0f);
} }
void UIController::setupCustomDrawGameStateAndMatrices(UIScene *scene, CustomDrawData *customDrawRegion) void UIController::setupCustomDrawGameStateAndMatrices(UIScene *scene, CustomDrawData *customDrawRegion)

View file

@ -34,6 +34,8 @@ private:
float m_fScreenWidth; float m_fScreenWidth;
float m_fScreenHeight; float m_fScreenHeight;
float aar_Width;
float aar_Height;
bool m_bScreenWidthSetup; bool m_bScreenWidthSetup;
S32 m_tileOriginX, m_tileOriginY; S32 m_tileOriginX, m_tileOriginY;
@ -172,6 +174,7 @@ private:
public: public:
UIController(); UIController();
void resize(S32 width, S32 height);
#ifdef __PSVITA__ #ifdef __PSVITA__
void TouchBoxAdd(UIControl *pControl,UIScene *pUIScene); void TouchBoxAdd(UIControl *pControl,UIScene *pUIScene);
bool TouchBoxHit(UIScene *pUIScene,S32 x, S32 y); bool TouchBoxHit(UIScene *pUIScene,S32 x, S32 y);

View file

@ -333,6 +333,41 @@ bool UIGroup::IsFullscreenGroup()
return m_group == eUIGroup_Fullscreen; return m_group == eUIGroup_Fullscreen;
} }
void UIGroup::OnResize(S32 width, S32 height)
{
// Update all layers in this group
for (int layer = 0; layer < LAYER_COUNT; ++layer)
{
if (m_layers[layer])
{
m_layers[layer]->OnResize();
}
}
//// Update HUD if it exists
//if (m_hud)
//{
// m_hud->OnResize();
//}
//// Update tooltips if they exist
//if (m_tooltips)
//{
// m_tooltips->OnResize();
//}
//// Update tutorial popup if it exists
//if (m_tutorialPopup)
//{
// m_tutorialPopup->OnResize();
//}
//// Update press start to play if it exists
//if (m_pressStartToPlay)
//{
// m_pressStartToPlay->OnResize();
//}
}
void UIGroup::handleUnlockFullVersion() void UIGroup::handleUnlockFullVersion()
{ {

View file

@ -101,6 +101,10 @@ public:
bool IsFullscreenGroup(); bool IsFullscreenGroup();
void handleUnlockFullVersion(); void handleUnlockFullVersion();
void OnResize(S32 width, S32 height);
static const int LAYER_COUNT = eUILayer_COUNT;
void PrintTotalMemoryUsage(__int64 &totalStatic, __int64 &totalDynamic); void PrintTotalMemoryUsage(__int64 &totalStatic, __int64 &totalDynamic);

View file

@ -872,6 +872,35 @@ C4JRender::eViewportType UILayer::getViewport()
return m_parentGroup->GetViewportType(); return m_parentGroup->GetViewportType();
} }
void UILayer::OnResize()
{
// Update all components
for (auto component : m_components)
{
if (component)
{
component->OnResize();
}
}
// Update all scenes in the stack
for (auto scene : m_sceneStack)
{
if (scene)
{
scene->OnResize();
}
}
// Update any scenes pending deletion
for (auto scene : m_scenesToDelete)
{
if (scene)
{
scene->OnResize();
}
}
}
void UILayer::handleUnlockFullVersion() void UILayer::handleUnlockFullVersion()
{ {

View file

@ -34,7 +34,7 @@ public:
UIGroup *m_parentGroup; UIGroup *m_parentGroup;
public: public:
UILayer(UIGroup *parent); UILayer(UIGroup *parent);
void UILayer::OnResize();
void tick(); void tick();
void render(S32 width, S32 height, C4JRender::eViewportType viewport); void render(S32 width, S32 height, C4JRender::eViewportType viewport);
void getRenderDimensions(S32 &width, S32 &height); void getRenderDimensions(S32 &width, S32 &height);

View file

@ -1199,6 +1199,46 @@ void UIScene::_handleFocusChange(F64 controlId, F64 childId)
ui.PlayUISFX(eSFX_Focus); ui.PlayUISFX(eSFX_Focus);
} }
void UIScene::OnResize()
{
if (!swf)
{
return;
}
// Update the Iggy player with new display size
S32 width, height;
m_parentLayer->getRenderDimensions(width, height);
IggyPlayerSetDisplaySize(swf, width, height);
// Update safe zone
updateSafeZone();
// Notify the Flash movie about resize (if it has a resize handler)
IggyDataValue result;
IggyResult out = IggyPlayerCallMethodRS(getMovie(), &result,
IggyPlayerRootPath(getMovie()),
registerFastName(L"OnResize"),
0, NULL);
// Force a redraw of cached content
m_needsCacheRendered = true;
}
void UIScene::UpdateDisplaySize()
{
if (!swf)
{
return;
}
S32 width, height;
m_parentLayer->getRenderDimensions(width, height);
IggyPlayerSetDisplaySize(swf, width, height);
updateSafeZone();
}
void UIScene::_handleInitFocus(F64 controlId, F64 childId) void UIScene::_handleInitFocus(F64 controlId, F64 childId)
{ {
m_iFocusControl = (int)controlId; m_iFocusControl = (int)controlId;

View file

@ -122,6 +122,8 @@ protected:
virtual bool mapElementsAndNames(); virtual bool mapElementsAndNames();
void initialiseMovie(); void initialiseMovie();
void loadMovie(); void loadMovie();
virtual void OnResize();
virtual void UpdateDisplaySize();
private: private:
void getDebugMemoryUseRecursive(const wstring &moviePath, IggyMemoryUseInfo &memoryInfo); void getDebugMemoryUseRecursive(const wstring &moviePath, IggyMemoryUseInfo &memoryInfo);

View file

@ -973,6 +973,9 @@ void gdraw_D3D1X_(SetRendertargetSize)(S32 w, S32 h)
void gdraw_D3D1X_(SetTileOrigin)(ID3D1X(RenderTargetView) *main_rt, ID3D1X(DepthStencilView) *main_ds, ID3D1X(ShaderResourceView) *non_msaa_rt, S32 x, S32 y) void gdraw_D3D1X_(SetTileOrigin)(ID3D1X(RenderTargetView) *main_rt, ID3D1X(DepthStencilView) *main_ds, ID3D1X(ShaderResourceView) *non_msaa_rt, S32 x, S32 y)
{ {
if (!gdraw) return; // AAR - saftey check because windows calls resize early
D3D1X_(RENDER_TARGET_VIEW_DESC) desc; D3D1X_(RENDER_TARGET_VIEW_DESC) desc;
if (gdraw->frame_done) { if (gdraw->frame_done) {

View file

@ -85,13 +85,24 @@ BOOL g_bWidescreen = TRUE;
int g_iScreenWidth = 1920; int g_iScreenWidth = 1920;
int g_iScreenHeight = 1080; int g_iScreenHeight = 1080;
UINT g_ScreenWidth = 1920; float g_iAspectRatio = (float)g_iScreenWidth / (float)g_iScreenHeight;
UINT g_ScreenHeight = 1080;
// Fullscreen toggle state // Fullscreen toggle state
static bool g_isFullscreen = false; static bool g_isFullscreen = false;
static WINDOWPLACEMENT g_wpPrev = { sizeof(g_wpPrev) }; static WINDOWPLACEMENT g_wpPrev = { sizeof(g_wpPrev) };
//--------------------------------------------------------------------------------------
// Update the Aspect Ratio to support Any Aspect Ratio
//--------------------------------------------------------------------------------------
void UpdateAspectRatio(int width, int height)
{
g_iAspectRatio = (float)width / (float)height;
// printf("Window resized to: %d x %d, aspect ratio: %.2f\n", width, height, g_iAspectRatio);
// Update the UI components as well
ui.resize(width, height);
}
void DefineActions(void) void DefineActions(void)
{ {
// The app needs to define the actions required, and the possible mappings for these // The app needs to define the actions required, and the possible mappings for these
@ -320,6 +331,7 @@ ID3D11Texture2D* g_pDepthStencilBuffer = NULL;
// WM_COMMAND - process the application menu // WM_COMMAND - process the application menu
// WM_PAINT - Paint the main window // WM_PAINT - Paint the main window
// WM_DESTROY - post a quit message and return // WM_DESTROY - post a quit message and return
// WM_SIZE - handle resizing logic to support Any Aspect Ratio
// //
// //
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
@ -429,6 +441,11 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
return TRUE; return TRUE;
} }
return DefWindowProc(hWnd, message, wParam, lParam); return DefWindowProc(hWnd, message, wParam, lParam);
case WM_SIZE:
{
UpdateAspectRatio(LOWORD(lParam), HIWORD(lParam));
}
break;
default: default:
return DefWindowProc(hWnd, message, wParam, lParam); return DefWindowProc(hWnd, message, wParam, lParam);
} }
@ -563,7 +580,7 @@ HRESULT InitDevice()
//app.DebugPrintf("width: %d, height: %d\n", width, height); //app.DebugPrintf("width: %d, height: %d\n", width, height);
width = g_iScreenWidth; width = g_iScreenWidth;
height = g_iScreenHeight; height = g_iScreenHeight;
app.DebugPrintf("width: %d, height: %d\n", width, height); //app.DebugPrintf("width: %d, height: %d\n", width, height);
UINT createDeviceFlags = 0; UINT createDeviceFlags = 0;
#ifdef _DEBUG #ifdef _DEBUG

View file

@ -9,6 +9,7 @@
ConsoleUIController ui; ConsoleUIController ui;
void ConsoleUIController::init(ID3D11Device *dev, ID3D11DeviceContext *ctx, ID3D11RenderTargetView* pRenderTargetView, ID3D11DepthStencilView* pDepthStencilView, S32 w, S32 h) void ConsoleUIController::init(ID3D11Device *dev, ID3D11DeviceContext *ctx, ID3D11RenderTargetView* pRenderTargetView, ID3D11DepthStencilView* pDepthStencilView, S32 w, S32 h)
{ {
#ifdef _ENABLEIGGY #ifdef _ENABLEIGGY

View file

@ -48,13 +48,11 @@ void glLoadIdentity()
RenderManager.MatrixSetIdentity(); RenderManager.MatrixSetIdentity();
} }
extern int g_iScreenWidth; // AAR - Use calculated aspect ratio to support dynamic resizing
extern int g_iScreenHeight; extern float g_iAspectRatio;
void gluPerspective(float fovy, float aspect, float zNear, float zFar) void gluPerspective(float fovy, float aspect, float zNear, float zFar)
{ {
float dynamicAspect = (float)g_iScreenWidth / (float)g_iScreenHeight; RenderManager.MatrixPerspective(fovy, g_iAspectRatio, zNear, zFar);
RenderManager.MatrixPerspective(fovy, dynamicAspect, zNear, zFar);
} }
void glOrtho(float left,float right,float bottom,float top,float zNear,float zFar) void glOrtho(float left,float right,float bottom,float top,float zNear,float zFar)