diff --git a/Minecraft.Client/Common/UI/UIController.cpp b/Minecraft.Client/Common/UI/UIController.cpp index 9e4a32024..2d11ff247 100644 --- a/Minecraft.Client/Common/UI/UIController.cpp +++ b/Minecraft.Client/Common/UI/UIController.cpp @@ -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 #if defined _WINDOWS64 || defined _DURANGO || defined __ORBIS__ m_fScreenWidth = 1920.0f; - m_fScreenHeight = 1080.0f; + m_fScreenHeight = 1080.0f;\ + aar_Width = 1920.0f; + aar_Height = 1080.0f; m_bScreenWidthSetup = false; #else m_fScreenWidth = 1280.0f; @@ -1209,10 +1211,37 @@ void UIController::getRenderDimensions(C4JRender::eViewportType viewport, S32 &w { switch( viewport ) { - case C4JRender::VIEWPORT_TYPE_FULLSCREEN: - width = (S32)(getScreenWidth()); - height = (S32)(getScreenHeight()); - break; + case C4JRender::VIEWPORT_TYPE_FULLSCREEN: + { + // AnyAspectRatio support by Fayaz + // 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_BOTTOM: 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) { - 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_bCustomRenderPosition = false; S32 xPos = 0; S32 yPos = 0; + 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: xPos = (S32)(getScreenWidth() / 4); break; @@ -1317,7 +1411,7 @@ void UIController::setupCustomDrawGameState() PIXBeginNamedEvent(0,"Final setup"); glMatrixMode(GL_PROJECTION); 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); glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GREATER, 0.1f); @@ -1365,16 +1459,21 @@ void UIController::setupCustomDrawMatrices(UIScene *scene, CustomDrawData *custo { m_fScreenWidth=(float)pMinecraft->width_phys; m_fScreenHeight=(float)pMinecraft->height_phys; + aar_Width = (float)pMinecraft->width_phys; + aar_Height = (float)pMinecraft->height_phys; m_bScreenWidthSetup = true; } } glLoadIdentity(); 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 - 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 - 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) diff --git a/Minecraft.Client/Common/UI/UIController.h b/Minecraft.Client/Common/UI/UIController.h index 49c780320..01ed79dbc 100644 --- a/Minecraft.Client/Common/UI/UIController.h +++ b/Minecraft.Client/Common/UI/UIController.h @@ -34,6 +34,8 @@ private: float m_fScreenWidth; float m_fScreenHeight; + float aar_Width; + float aar_Height; bool m_bScreenWidthSetup; S32 m_tileOriginX, m_tileOriginY; @@ -172,6 +174,7 @@ private: public: UIController(); + void resize(S32 width, S32 height); #ifdef __PSVITA__ void TouchBoxAdd(UIControl *pControl,UIScene *pUIScene); bool TouchBoxHit(UIScene *pUIScene,S32 x, S32 y); diff --git a/Minecraft.Client/Common/UI/UIGroup.cpp b/Minecraft.Client/Common/UI/UIGroup.cpp index e8bb9fe66..4db27cdb0 100644 --- a/Minecraft.Client/Common/UI/UIGroup.cpp +++ b/Minecraft.Client/Common/UI/UIGroup.cpp @@ -333,6 +333,41 @@ bool UIGroup::IsFullscreenGroup() 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() { diff --git a/Minecraft.Client/Common/UI/UIGroup.h b/Minecraft.Client/Common/UI/UIGroup.h index 0ffee0ca2..981fd0e68 100644 --- a/Minecraft.Client/Common/UI/UIGroup.h +++ b/Minecraft.Client/Common/UI/UIGroup.h @@ -101,6 +101,10 @@ public: bool IsFullscreenGroup(); void handleUnlockFullVersion(); + + void OnResize(S32 width, S32 height); + + static const int LAYER_COUNT = eUILayer_COUNT; void PrintTotalMemoryUsage(__int64 &totalStatic, __int64 &totalDynamic); diff --git a/Minecraft.Client/Common/UI/UILayer.cpp b/Minecraft.Client/Common/UI/UILayer.cpp index 13b26c845..7a8211d8a 100644 --- a/Minecraft.Client/Common/UI/UILayer.cpp +++ b/Minecraft.Client/Common/UI/UILayer.cpp @@ -872,6 +872,35 @@ C4JRender::eViewportType UILayer::getViewport() 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() { diff --git a/Minecraft.Client/Common/UI/UILayer.h b/Minecraft.Client/Common/UI/UILayer.h index 47c776ab7..4209a7e83 100644 --- a/Minecraft.Client/Common/UI/UILayer.h +++ b/Minecraft.Client/Common/UI/UILayer.h @@ -34,7 +34,7 @@ public: UIGroup *m_parentGroup; public: UILayer(UIGroup *parent); - + void UILayer::OnResize(); void tick(); void render(S32 width, S32 height, C4JRender::eViewportType viewport); void getRenderDimensions(S32 &width, S32 &height); diff --git a/Minecraft.Client/Common/UI/UIScene.cpp b/Minecraft.Client/Common/UI/UIScene.cpp index ba2536434..16c176ce2 100644 --- a/Minecraft.Client/Common/UI/UIScene.cpp +++ b/Minecraft.Client/Common/UI/UIScene.cpp @@ -1199,6 +1199,46 @@ void UIScene::_handleFocusChange(F64 controlId, F64 childId) 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) { m_iFocusControl = (int)controlId; diff --git a/Minecraft.Client/Common/UI/UIScene.h b/Minecraft.Client/Common/UI/UIScene.h index 8c20aaae3..1f4c37584 100644 --- a/Minecraft.Client/Common/UI/UIScene.h +++ b/Minecraft.Client/Common/UI/UIScene.h @@ -122,6 +122,8 @@ protected: virtual bool mapElementsAndNames(); void initialiseMovie(); void loadMovie(); + virtual void OnResize(); + virtual void UpdateDisplaySize(); private: void getDebugMemoryUseRecursive(const wstring &moviePath, IggyMemoryUseInfo &memoryInfo); diff --git a/Minecraft.Client/Windows64/Iggy/gdraw/gdraw_d3d1x_shared.inl b/Minecraft.Client/Windows64/Iggy/gdraw/gdraw_d3d1x_shared.inl index e827cd823..df42488c6 100644 --- a/Minecraft.Client/Windows64/Iggy/gdraw/gdraw_d3d1x_shared.inl +++ b/Minecraft.Client/Windows64/Iggy/gdraw/gdraw_d3d1x_shared.inl @@ -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) { + + if (!gdraw) return; // AAR - saftey check because windows calls resize early + D3D1X_(RENDER_TARGET_VIEW_DESC) desc; if (gdraw->frame_done) { diff --git a/Minecraft.Client/Windows64/Windows64_Minecraft.cpp b/Minecraft.Client/Windows64/Windows64_Minecraft.cpp index 78ab76fef..61002a619 100644 --- a/Minecraft.Client/Windows64/Windows64_Minecraft.cpp +++ b/Minecraft.Client/Windows64/Windows64_Minecraft.cpp @@ -85,13 +85,24 @@ BOOL g_bWidescreen = TRUE; int g_iScreenWidth = 1920; int g_iScreenHeight = 1080; -UINT g_ScreenWidth = 1920; -UINT g_ScreenHeight = 1080; +float g_iAspectRatio = (float)g_iScreenWidth / (float)g_iScreenHeight; // Fullscreen toggle state static bool g_isFullscreen = false; 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) { // 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_PAINT - Paint the main window // 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) @@ -429,6 +441,11 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) return TRUE; } return DefWindowProc(hWnd, message, wParam, lParam); + case WM_SIZE: + { + UpdateAspectRatio(LOWORD(lParam), HIWORD(lParam)); + } + break; default: return DefWindowProc(hWnd, message, wParam, lParam); } @@ -563,7 +580,7 @@ HRESULT InitDevice() //app.DebugPrintf("width: %d, height: %d\n", width, height); width = g_iScreenWidth; height = g_iScreenHeight; -app.DebugPrintf("width: %d, height: %d\n", width, height); +//app.DebugPrintf("width: %d, height: %d\n", width, height); UINT createDeviceFlags = 0; #ifdef _DEBUG diff --git a/Minecraft.Client/Windows64/Windows64_UIController.cpp b/Minecraft.Client/Windows64/Windows64_UIController.cpp index 10ae20aff..c4aa73f7a 100644 --- a/Minecraft.Client/Windows64/Windows64_UIController.cpp +++ b/Minecraft.Client/Windows64/Windows64_UIController.cpp @@ -9,6 +9,7 @@ ConsoleUIController ui; + void ConsoleUIController::init(ID3D11Device *dev, ID3D11DeviceContext *ctx, ID3D11RenderTargetView* pRenderTargetView, ID3D11DepthStencilView* pDepthStencilView, S32 w, S32 h) { #ifdef _ENABLEIGGY diff --git a/Minecraft.Client/glWrapper.cpp b/Minecraft.Client/glWrapper.cpp index 540271b91..a356e674c 100644 --- a/Minecraft.Client/glWrapper.cpp +++ b/Minecraft.Client/glWrapper.cpp @@ -48,13 +48,11 @@ void glLoadIdentity() RenderManager.MatrixSetIdentity(); } -extern int g_iScreenWidth; -extern int g_iScreenHeight; - +// AAR - Use calculated aspect ratio to support dynamic resizing +extern float g_iAspectRatio; void gluPerspective(float fovy, float aspect, float zNear, float zFar) { - float dynamicAspect = (float)g_iScreenWidth / (float)g_iScreenHeight; - RenderManager.MatrixPerspective(fovy, dynamicAspect, zNear, zFar); + RenderManager.MatrixPerspective(fovy, g_iAspectRatio, zNear, zFar); } void glOrtho(float left,float right,float bottom,float top,float zNear,float zFar)