aboutsummaryrefslogtreecommitdiff
path: root/Minecraft.Client/Common/UI
diff options
context:
space:
mode:
Diffstat (limited to 'Minecraft.Client/Common/UI')
-rw-r--r--Minecraft.Client/Common/UI/IUIScene_AbstractContainerMenu.cpp20
-rw-r--r--Minecraft.Client/Common/UI/IUIScene_AbstractContainerMenu.h1
-rw-r--r--Minecraft.Client/Common/UI/UIBitmapFont.cpp96
-rw-r--r--Minecraft.Client/Common/UI/UIComponent_Chat.cpp23
-rw-r--r--Minecraft.Client/Common/UI/UIComponent_MenuBackground.cpp23
-rw-r--r--Minecraft.Client/Common/UI/UIComponent_Panorama.cpp57
-rw-r--r--Minecraft.Client/Common/UI/UIComponent_Tooltips.cpp23
-rw-r--r--Minecraft.Client/Common/UI/UIController.cpp149
-rw-r--r--Minecraft.Client/Common/UI/UIController.h1
-rw-r--r--Minecraft.Client/Common/UI/UIScene.cpp82
-rw-r--r--Minecraft.Client/Common/UI/UIScene_AbstractContainerMenu.cpp35
-rw-r--r--Minecraft.Client/Common/UI/UIScene_AbstractContainerMenu.h1
-rw-r--r--Minecraft.Client/Common/UI/UIScene_HUD.cpp50
-rw-r--r--Minecraft.Client/Common/UI/UIScene_HUD.h2
-rw-r--r--Minecraft.Client/Common/UI/UIScene_Keyboard.cpp64
-rw-r--r--Minecraft.Client/Common/UI/UIScene_Keyboard.h1
-rw-r--r--Minecraft.Client/Common/UI/UISplitScreenHelpers.h114
17 files changed, 512 insertions, 230 deletions
diff --git a/Minecraft.Client/Common/UI/IUIScene_AbstractContainerMenu.cpp b/Minecraft.Client/Common/UI/IUIScene_AbstractContainerMenu.cpp
index e55f207d..ce247728 100644
--- a/Minecraft.Client/Common/UI/IUIScene_AbstractContainerMenu.cpp
+++ b/Minecraft.Client/Common/UI/IUIScene_AbstractContainerMenu.cpp
@@ -481,25 +481,15 @@ void IUIScene_AbstractContainerMenu::onMouseTick()
#endif
#ifdef _WINDOWS64
- if (!g_KBMInput.IsMouseGrabbed() && g_KBMInput.IsKBMActive())
+ if (iPad == 0 && !g_KBMInput.IsMouseGrabbed() && g_KBMInput.IsKBMActive())
{
int deltaX = g_KBMInput.GetMouseDeltaX();
int deltaY = g_KBMInput.GetMouseDeltaY();
- extern HWND g_hWnd;
- RECT rc;
- GetClientRect(g_hWnd, &rc);
- int winW = rc.right - rc.left;
- int winH = rc.bottom - rc.top;
-
- if (winW > 0 && winH > 0)
- {
- float scaleX = (float)getMovieWidth() / (float)winW;
- float scaleY = (float)getMovieHeight() / (float)winH;
-
- vPointerPos.x += (float)deltaX * scaleX;
- vPointerPos.y += (float)deltaY * scaleY;
- }
+ float scaleX, scaleY;
+ getMouseToSWFScale(scaleX, scaleY);
+ vPointerPos.x += (float)deltaX * scaleX;
+ vPointerPos.y += (float)deltaY * scaleY;
if (deltaX != 0 || deltaY != 0)
{
diff --git a/Minecraft.Client/Common/UI/IUIScene_AbstractContainerMenu.h b/Minecraft.Client/Common/UI/IUIScene_AbstractContainerMenu.h
index 4877cfce..718a2d44 100644
--- a/Minecraft.Client/Common/UI/IUIScene_AbstractContainerMenu.h
+++ b/Minecraft.Client/Common/UI/IUIScene_AbstractContainerMenu.h
@@ -277,4 +277,5 @@ public:
virtual int getPad() = 0;
virtual int getMovieWidth() = 0;
virtual int getMovieHeight() = 0;
+ virtual void getMouseToSWFScale(float &scaleX, float &scaleY) = 0;
};
diff --git a/Minecraft.Client/Common/UI/UIBitmapFont.cpp b/Minecraft.Client/Common/UI/UIBitmapFont.cpp
index afc2b139..31eef281 100644
--- a/Minecraft.Client/Common/UI/UIBitmapFont.cpp
+++ b/Minecraft.Client/Common/UI/UIBitmapFont.cpp
@@ -250,15 +250,22 @@ rrbool UIBitmapFont::GetGlyphBitmap(S32 glyph,F32 pixel_scale,IggyBitmapCharacte
// Choose a reasonable glyph scale.
float glyphScale = 1.0f, truePixelScale = 1.0f / m_cFontData->getFontData()->m_fAdvPerPixel;
- F32 targetPixelScale = pixel_scale;
- //if(!RenderManager.IsWidescreen())
- //{
- // // Fix for different scales in 480
- // targetPixelScale = pixel_scale*2/3;
- //}
- while ( (0.5f + glyphScale) * truePixelScale < targetPixelScale)
+ while ( (0.5f + glyphScale) * truePixelScale < pixel_scale)
glyphScale++;
+ // Debug: log each unique (font, pixel_scale) pair
+ {
+ static std::unordered_set<int> s_loggedScaleKeys;
+ // Encode font pointer + quantized scale into a key to log each combo once
+ int scaleKey = (int)(pixel_scale * 100.0f) ^ (int)(uintptr_t)m_cFontData;
+ if (s_loggedScaleKeys.find(scaleKey) == s_loggedScaleKeys.end() && s_loggedScaleKeys.size() < 50) {
+ s_loggedScaleKeys.insert(scaleKey);
+ float tps = truePixelScale;
+ app.DebugPrintf("[FONT-DBG] GetGlyphBitmap: font=%s glyph=%d pixel_scale=%.3f truePixelScale=%.1f glyphScale=%.0f\n",
+ m_cFontData->getFontName().c_str(), glyph, pixel_scale, tps, glyphScale);
+ }
+ }
+
// 4J-JEV: Debug code to check which font sizes are being used.
#if (!defined _CONTENT_PACKAGE) && (VERBOSE_FONT_OUTPUT > 0)
@@ -303,9 +310,6 @@ rrbool UIBitmapFont::GetGlyphBitmap(S32 glyph,F32 pixel_scale,IggyBitmapCharacte
}
#endif
- //app.DebugPrintf("Request glyph_%d (U+%.4X) at %f, converted to %f (%f)\n",
- // glyph, GetUnicode(glyph), pixel_scale, targetPixelScale, glyphScale);
-
// It is not necessary to shrink the glyph width here
// as its already been done in 'GetGlyphMetrics' by:
// > metrics->x1 = m_kerningTable[glyph] * ratio;
@@ -324,27 +328,57 @@ rrbool UIBitmapFont::GetGlyphBitmap(S32 glyph,F32 pixel_scale,IggyBitmapCharacte
bitmap->top_left_y = -((S32) m_cFontData->getFontData()->m_uiGlyphHeight) * m_cFontData->getFontData()->m_fAscent;
bitmap->oversample = 0;
- bitmap->point_sample = true;
-
- // 4J-JEV:
- // pixel_scale == font size chosen in flash.
- // bitmap->pixel_scale_correct = (float) m_glyphHeight; // Scales the glyph to desired size.
- // bitmap->pixel_scale_correct = pixel_scale; // Always the same size (not desired size).
- // bitmap->pixel_scale_correct = pixel_scale * 0.5; // Doubles original size.
- // bitmap->pixel_scale_correct = pixel_scale * 2; // Halves original size.
-
- // Actual scale, and possible range of scales.
- bitmap->pixel_scale_correct = pixel_scale / glyphScale;
- bitmap->pixel_scale_max = 99.0f;
- bitmap->pixel_scale_min = 0.0f;
-
- /* 4J-JEV: Some of Sean's code.
- int glyphScaleMin = 1;
- int glyphScaleMax = 3;
- float actualScale = pixel_scale / glyphScale;
- bitmap->pixel_scale_correct = actualScale;
- bitmap->pixel_scale_min = actualScale * glyphScaleMin * 0.999f;
- bitmap->pixel_scale_max = actualScale * glyphScaleMax * 1.001f; */
+
+#ifdef _WINDOWS64
+ // On Windows64 the window can be any size, producing fractional
+ // pixel_scale values that don't align to integer multiples of
+ // truePixelScale. The original console code cached glyphs with a
+ // broad [truePixelScale, 99] range in the "normal" branch, which
+ // works on consoles (fixed 1080p — font sizes are exact multiples)
+ // but causes cache pollution on Windows: the first glyph cached in
+ // that range sets pixel_scale_correct for ALL subsequent requests,
+ // so different font sizes get scaled by wrong ratios, producing
+ // mixed letter sizes on screen.
+ //
+ // Fix: always use pixel_scale_correct = truePixelScale so every
+ // cache entry is consistent. Two ranges: downscale (bilinear for
+ // smooth reduction) and upscale (point_sample for crisp pixel-art).
+ bitmap->pixel_scale_correct = truePixelScale;
+ if (pixel_scale < truePixelScale)
+ {
+ bitmap->pixel_scale_min = 0.0f;
+ bitmap->pixel_scale_max = truePixelScale;
+ bitmap->point_sample = false;
+ }
+ else
+ {
+ bitmap->pixel_scale_min = truePixelScale;
+ bitmap->pixel_scale_max = 99.0f;
+ bitmap->point_sample = true;
+ }
+#else
+ if (glyphScale <= 1 && pixel_scale < truePixelScale)
+ {
+ // Small display: pixel_scale is less than the native glyph size.
+ // Report the bitmap at its true native scale so Iggy downscales it
+ // to match the layout metrics (bilinear for smooth downscaling).
+ bitmap->pixel_scale_correct = truePixelScale;
+ bitmap->pixel_scale_min = 0.0f;
+ bitmap->pixel_scale_max = truePixelScale * 1.001f;
+ bitmap->point_sample = false;
+ }
+ else
+ {
+ // Normal/upscale case: integer-multiple scaling for pixel-art look.
+ // Console-only — fixed resolution means pixel_scale values are exact
+ // integer multiples of truePixelScale, so cache sharing is safe.
+ float actualScale = pixel_scale / glyphScale;
+ bitmap->pixel_scale_correct = actualScale;
+ bitmap->pixel_scale_min = truePixelScale;
+ bitmap->pixel_scale_max = 99.0f;
+ bitmap->point_sample = true;
+ }
+#endif
// 4J-JEV: Nothing to do with glyph placement,
// entirely to do with cropping your glyph out of an archive.
diff --git a/Minecraft.Client/Common/UI/UIComponent_Chat.cpp b/Minecraft.Client/Common/UI/UIComponent_Chat.cpp
index 901b5a77..1d2f3cb0 100644
--- a/Minecraft.Client/Common/UI/UIComponent_Chat.cpp
+++ b/Minecraft.Client/Common/UI/UIComponent_Chat.cpp
@@ -1,6 +1,7 @@
#include "stdafx.h"
#include "UI.h"
#include "UIComponent_Chat.h"
+#include "UISplitScreenHelpers.h"
#include "..\..\Minecraft.h"
#include "..\..\Gui.h"
@@ -120,6 +121,7 @@ void UIComponent_Chat::render(S32 width, S32 height, C4JRender::eViewportType vi
S32 tileWidth = width;
S32 tileHeight = height;
+ bool needsYTile = false;
switch( viewport )
{
case C4JRender::VIEWPORT_TYPE_SPLIT_LEFT:
@@ -127,25 +129,30 @@ void UIComponent_Chat::render(S32 width, S32 height, C4JRender::eViewportType vi
tileHeight = (S32)(ui.getScreenHeight());
break;
case C4JRender::VIEWPORT_TYPE_SPLIT_TOP:
- tileWidth = (S32)(ui.getScreenWidth());
- tileYStart = (S32)(m_movieHeight / 2);
- break;
case C4JRender::VIEWPORT_TYPE_SPLIT_BOTTOM:
tileWidth = (S32)(ui.getScreenWidth());
- tileYStart = (S32)(m_movieHeight / 2);
+ needsYTile = true;
break;
case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_LEFT:
case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_RIGHT:
case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_LEFT:
case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_RIGHT:
- tileYStart = (S32)(m_movieHeight / 2);
+ needsYTile = true;
break;
}
- IggyPlayerSetDisplaySize( getMovie(), m_movieWidth, m_movieHeight );
+ F32 scale;
+ ComputeTileScale(tileWidth, tileHeight, m_movieWidth, m_movieHeight, needsYTile, scale, tileYStart);
+ IggyPlayerSetDisplaySize( getMovie(), (S32)(m_movieWidth * scale), (S32)(m_movieHeight * scale) );
+
+ S32 contentOffX, contentOffY;
+ ComputeSplitContentOffset(viewport, m_movieWidth, m_movieHeight, scale, tileWidth, tileHeight, tileYStart, contentOffX, contentOffY);
+ xPos += contentOffX;
+ yPos += contentOffY;
+ ui.setupRenderPosition(xPos, yPos);
IggyPlayerDrawTilesStart ( getMovie() );
-
+
m_renderWidth = tileWidth;
m_renderHeight = tileHeight;
IggyPlayerDrawTile ( getMovie() ,
@@ -153,7 +160,7 @@ void UIComponent_Chat::render(S32 width, S32 height, C4JRender::eViewportType vi
tileYStart ,
tileXStart + tileWidth ,
tileYStart + tileHeight ,
- 0 );
+ 0 );
IggyPlayerDrawTilesEnd ( getMovie() );
}
else
diff --git a/Minecraft.Client/Common/UI/UIComponent_MenuBackground.cpp b/Minecraft.Client/Common/UI/UIComponent_MenuBackground.cpp
index d3a4c4c0..60b4a95c 100644
--- a/Minecraft.Client/Common/UI/UIComponent_MenuBackground.cpp
+++ b/Minecraft.Client/Common/UI/UIComponent_MenuBackground.cpp
@@ -68,24 +68,29 @@ void UIComponent_MenuBackground::render(S32 width, S32 height, C4JRender::eViewp
break;
case C4JRender::VIEWPORT_TYPE_SPLIT_TOP:
tileWidth = (S32)(ui.getScreenWidth());
- tileYStart = (S32)(m_movieHeight / 2);
+ tileYStart = (S32)(ui.getScreenHeight() / 2);
break;
case C4JRender::VIEWPORT_TYPE_SPLIT_BOTTOM:
tileWidth = (S32)(ui.getScreenWidth());
- tileYStart = (S32)(m_movieHeight / 2);
+ tileYStart = (S32)(ui.getScreenHeight() / 2);
break;
case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_LEFT:
case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_RIGHT:
case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_LEFT:
case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_RIGHT:
- tileYStart = (S32)(m_movieHeight / 2);
+ tileYStart = (S32)(ui.getScreenHeight() / 2);
break;
}
- IggyPlayerSetDisplaySize( getMovie(), m_movieWidth, m_movieHeight );
+ F32 scaleW = (F32)(tileXStart + tileWidth) / (F32)m_movieWidth;
+ F32 scaleH = (F32)(tileYStart + tileHeight) / (F32)m_movieHeight;
+ F32 scale = (scaleW > scaleH) ? scaleW : scaleH;
+ if(scale < 1.0f) scale = 1.0f;
+
+ IggyPlayerSetDisplaySize( getMovie(), (S32)(m_movieWidth * scale), (S32)(m_movieHeight * scale) );
IggyPlayerDrawTilesStart ( getMovie() );
-
+
m_renderWidth = tileWidth;
m_renderHeight = tileHeight;
IggyPlayerDrawTile ( getMovie() ,
@@ -93,11 +98,15 @@ void UIComponent_MenuBackground::render(S32 width, S32 height, C4JRender::eViewp
tileYStart ,
tileXStart + tileWidth ,
tileYStart + tileHeight ,
- 0 );
+ 0 );
IggyPlayerDrawTilesEnd ( getMovie() );
}
else
{
- UIScene::render(width, height, viewport);
+ if(m_bIsReloading) return;
+ if(!m_hasTickedOnce || !getMovie()) return;
+ ui.setupRenderPosition(0, 0);
+ IggyPlayerSetDisplaySize( getMovie(), (S32)ui.getScreenWidth(), (S32)ui.getScreenHeight() );
+ IggyPlayerDraw( getMovie() );
}
} \ No newline at end of file
diff --git a/Minecraft.Client/Common/UI/UIComponent_Panorama.cpp b/Minecraft.Client/Common/UI/UIComponent_Panorama.cpp
index a52ebd72..bd3df101 100644
--- a/Minecraft.Client/Common/UI/UIComponent_Panorama.cpp
+++ b/Minecraft.Client/Common/UI/UIComponent_Panorama.cpp
@@ -93,38 +93,47 @@ void UIComponent_Panorama::render(S32 width, S32 height, C4JRender::eViewportTyp
}
ui.setupRenderPosition(xPos, yPos);
- if((viewport == C4JRender::VIEWPORT_TYPE_SPLIT_LEFT) || (viewport == C4JRender::VIEWPORT_TYPE_SPLIT_RIGHT))
+ S32 tileXStart = 0;
+ S32 tileYStart = 0;
+ S32 tileWidth = width;
+ S32 tileHeight = height;
+
+ if((viewport == C4JRender::VIEWPORT_TYPE_SPLIT_LEFT) || (viewport == C4JRender::VIEWPORT_TYPE_SPLIT_RIGHT))
{
- // Need to render at full height, but only the left side of the scene
- S32 tileXStart = 0;
- S32 tileYStart = 0;
- S32 tileWidth = width;
- S32 tileHeight = (S32)(ui.getScreenHeight());
-
- IggyPlayerSetDisplaySize( getMovie(), m_movieWidth, m_movieHeight );
-
- IggyPlayerDrawTilesStart ( getMovie() );
-
- m_renderWidth = tileWidth;
- m_renderHeight = tileHeight;
- IggyPlayerDrawTile ( getMovie() ,
- tileXStart ,
- tileYStart ,
- tileXStart + tileWidth ,
- tileYStart + tileHeight ,
- 0 );
- IggyPlayerDrawTilesEnd ( getMovie() );
+ tileHeight = (S32)(ui.getScreenHeight());
}
else
{
- // Need to render at full height, and full width. But compressed into the viewport
- IggyPlayerSetDisplaySize( getMovie(), ui.getScreenWidth(), ui.getScreenHeight()/2 );
- IggyPlayerDraw( getMovie() );
+ tileWidth = (S32)(ui.getScreenWidth());
+ tileYStart = (S32)(ui.getScreenHeight() / 2);
}
+
+ F32 scaleW = (F32)(tileXStart + tileWidth) / (F32)m_movieWidth;
+ F32 scaleH = (F32)(tileYStart + tileHeight) / (F32)m_movieHeight;
+ F32 scale = (scaleW > scaleH) ? scaleW : scaleH;
+ if(scale < 1.0f) scale = 1.0f;
+
+ IggyPlayerSetDisplaySize( getMovie(), (S32)(m_movieWidth * scale), (S32)(m_movieHeight * scale) );
+
+ IggyPlayerDrawTilesStart ( getMovie() );
+
+ m_renderWidth = tileWidth;
+ m_renderHeight = tileHeight;
+ IggyPlayerDrawTile ( getMovie() ,
+ tileXStart ,
+ tileYStart ,
+ tileXStart + tileWidth ,
+ tileYStart + tileHeight ,
+ 0 );
+ IggyPlayerDrawTilesEnd ( getMovie() );
}
else
{
- UIScene::render(width, height, viewport);
+ if(m_bIsReloading) return;
+ if(!m_hasTickedOnce || !getMovie()) return;
+ ui.setupRenderPosition(0, 0);
+ IggyPlayerSetDisplaySize( getMovie(), (S32)ui.getScreenWidth(), (S32)ui.getScreenHeight() );
+ IggyPlayerDraw( getMovie() );
}
}
diff --git a/Minecraft.Client/Common/UI/UIComponent_Tooltips.cpp b/Minecraft.Client/Common/UI/UIComponent_Tooltips.cpp
index 255740c9..844e928a 100644
--- a/Minecraft.Client/Common/UI/UIComponent_Tooltips.cpp
+++ b/Minecraft.Client/Common/UI/UIComponent_Tooltips.cpp
@@ -1,6 +1,7 @@
#include "stdafx.h"
#include "UI.h"
#include "UIComponent_Tooltips.h"
+#include "UISplitScreenHelpers.h"
UIComponent_Tooltips::UIComponent_Tooltips(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer)
{
@@ -224,6 +225,7 @@ void UIComponent_Tooltips::render(S32 width, S32 height, C4JRender::eViewportTyp
S32 tileWidth = width;
S32 tileHeight = height;
+ bool needsYTile = false;
switch( viewport )
{
case C4JRender::VIEWPORT_TYPE_SPLIT_LEFT:
@@ -231,25 +233,30 @@ void UIComponent_Tooltips::render(S32 width, S32 height, C4JRender::eViewportTyp
tileHeight = (S32)(ui.getScreenHeight());
break;
case C4JRender::VIEWPORT_TYPE_SPLIT_TOP:
- tileWidth = (S32)(ui.getScreenWidth());
- tileYStart = (S32)(m_movieHeight / 2);
- break;
case C4JRender::VIEWPORT_TYPE_SPLIT_BOTTOM:
tileWidth = (S32)(ui.getScreenWidth());
- tileYStart = (S32)(m_movieHeight / 2);
+ needsYTile = true;
break;
case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_LEFT:
case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_RIGHT:
case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_LEFT:
case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_RIGHT:
- tileYStart = (S32)(m_movieHeight / 2);
+ needsYTile = true;
break;
}
- IggyPlayerSetDisplaySize( getMovie(), m_movieWidth, m_movieHeight );
+ F32 scale;
+ ComputeTileScale(tileWidth, tileHeight, m_movieWidth, m_movieHeight, needsYTile, scale, tileYStart);
+ IggyPlayerSetDisplaySize( getMovie(), (S32)(m_movieWidth * scale), (S32)(m_movieHeight * scale) );
+
+ S32 contentOffX, contentOffY;
+ ComputeSplitContentOffset(viewport, m_movieWidth, m_movieHeight, scale, tileWidth, tileHeight, tileYStart, contentOffX, contentOffY);
+ xPos += contentOffX;
+ yPos += contentOffY;
+ ui.setupRenderPosition(xPos, yPos);
IggyPlayerDrawTilesStart ( getMovie() );
-
+
m_renderWidth = tileWidth;
m_renderHeight = tileHeight;
IggyPlayerDrawTile ( getMovie() ,
@@ -257,7 +264,7 @@ void UIComponent_Tooltips::render(S32 width, S32 height, C4JRender::eViewportTyp
tileYStart ,
tileXStart + tileWidth ,
tileYStart + tileHeight ,
- 0 );
+ 0 );
IggyPlayerDrawTilesEnd ( getMovie() );
}
else
diff --git a/Minecraft.Client/Common/UI/UIController.cpp b/Minecraft.Client/Common/UI/UIController.cpp
index 840ed389..b0bd7dd3 100644
--- a/Minecraft.Client/Common/UI/UIController.cpp
+++ b/Minecraft.Client/Common/UI/UIController.cpp
@@ -13,6 +13,7 @@
#include "..\..\EnderDragonRenderer.h"
#include "..\..\MultiPlayerLocalPlayer.h"
#include "UIFontData.h"
+#include "UISplitScreenHelpers.h"
#ifdef _WINDOWS64
#include "..\..\Windows64\KeyboardMouseInput.h"
#endif
@@ -57,6 +58,8 @@ bool UIController::ms_bReloadSkinCSInitialised = false;
DWORD UIController::m_dwTrialTimerLimitSecs=DYNAMIC_CONFIG_DEFAULT_TRIAL_TIME;
+// GetViewportRect and Fit16x9 are now in UISplitScreenHelpers.h
+
#ifdef _WINDOWS64
static UIControl_Slider *FindSliderById(UIScene *pScene, int sliderId)
{
@@ -806,13 +809,16 @@ void UIController::tickInput()
eUILayer_Fullscreen,
eUILayer_Scene,
};
- for (int l = 0; l < _countof(mouseLayers) && !pScene; ++l)
+ // Only check the fullscreen group and the primary (KBM) player's group.
+ // Other splitscreen players use controllers — mouse must not affect them.
+ const int mouseGroups[] = { (int)eUIGroup_Fullscreen, ProfileManager.GetPrimaryPad() + 1 };
+ for (int l = 0; l < _countof(mouseLayers) && !pScene; ++l)
+ {
+ for (int g = 0; g < _countof(mouseGroups) && !pScene; ++g)
{
- for (int grp = 0; grp < eUIGroup_COUNT && !pScene; ++grp)
- {
- pScene = m_groups[grp]->GetTopScene(mouseLayers[l]);
- }
+ pScene = m_groups[mouseGroups[g]]->GetTopScene(mouseLayers[l]);
}
+ }
if (pScene && pScene->getMovie())
{
int rawMouseX = g_KBMInput.GetMouseX();
@@ -825,7 +831,12 @@ void UIController::tickInput()
m_lastHoverMouseX = rawMouseX;
m_lastHoverMouseY = rawMouseY;
- // Convert mouse to scene/movie coordinates
+ // Convert mouse window-pixel coords to Flash/SWF authoring coords.
+ // In split-screen the scene is rendered at a tile-origin offset
+ // and at a smaller display size, so we must:
+ // 1. Map window pixels -> UIController screen space
+ // 2. Subtract the viewport tile origin
+ // 3. Scale from display dimensions to SWF authoring dimensions
F32 sceneMouseX = (F32)rawMouseX;
F32 sceneMouseY = (F32)rawMouseY;
{
@@ -837,8 +848,30 @@ void UIController::tickInput()
int winH = rc.bottom - rc.top;
if (winW > 0 && winH > 0)
{
- sceneMouseX = sceneMouseX * ((F32)pScene->getRenderWidth() / (F32)winW);
- sceneMouseY = sceneMouseY * ((F32)pScene->getRenderHeight() / (F32)winH);
+ // Step 1: window pixels -> screen space
+ F32 screenX = sceneMouseX * (getScreenWidth() / (F32)winW);
+ F32 screenY = sceneMouseY * (getScreenHeight() / (F32)winH);
+
+ // Step 2 & 3: account for split-screen viewport
+ C4JRender::eViewportType vp = pScene->GetParentLayer()->getViewport();
+ S32 displayW = 0, displayH = 0;
+ getRenderDimensions(vp, displayW, displayH);
+
+ F32 vpOriginX, vpOriginY, vpW, vpH;
+ GetViewportRect(getScreenWidth(), getScreenHeight(), vp, vpOriginX, vpOriginY, vpW, vpH);
+ // All viewports use Fit16x9 for menu scenes
+ S32 fitW, fitH, fitOffsetX, fitOffsetY;
+ Fit16x9(vpW, vpH, fitW, fitH, fitOffsetX, fitOffsetY);
+ S32 originX = (S32)vpOriginX + fitOffsetX;
+ S32 originY = (S32)vpOriginY + fitOffsetY;
+ displayW = fitW;
+ displayH = fitH;
+
+ if (displayW > 0 && displayH > 0)
+ {
+ sceneMouseX = (screenX - originX) * ((F32)pScene->getRenderWidth() / (F32)displayW);
+ sceneMouseY = (screenY - originY) * ((F32)pScene->getRenderHeight() / (F32)displayH);
+ }
}
}
}
@@ -1566,73 +1599,48 @@ void UIController::renderScenes()
void UIController::getRenderDimensions(C4JRender::eViewportType viewport, S32 &width, S32 &height)
{
- switch( viewport )
+ F32 originX, originY, viewW, viewH;
+ GetViewportRect(getScreenWidth(), getScreenHeight(), viewport, originX, originY, viewW, viewH);
+
+ if(viewport == C4JRender::VIEWPORT_TYPE_FULLSCREEN)
{
- case C4JRender::VIEWPORT_TYPE_FULLSCREEN:
- width = (S32)(getScreenWidth());
- height = (S32)(getScreenHeight());
- break;
- case C4JRender::VIEWPORT_TYPE_SPLIT_TOP:
- case C4JRender::VIEWPORT_TYPE_SPLIT_BOTTOM:
- width = (S32)(getScreenWidth() / 2);
- height = (S32)(getScreenHeight() / 2);
- break;
- case C4JRender::VIEWPORT_TYPE_SPLIT_LEFT:
- case C4JRender::VIEWPORT_TYPE_SPLIT_RIGHT:
- width = (S32)(getScreenWidth() / 2);
- height = (S32)(getScreenHeight() / 2);
- break;
- case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_LEFT:
- case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_RIGHT:
- case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_LEFT:
- case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_RIGHT:
- width = (S32)(getScreenWidth() / 2);
- height = (S32)(getScreenHeight() / 2);
- break;
+ S32 offsetX, offsetY;
+ Fit16x9(viewW, viewH, width, height, offsetX, offsetY);
+ }
+ else
+ {
+ // Split-screen: use raw viewport dims — the SWF tiling code handles non-16:9
+ width = (S32)viewW;
+ height = (S32)viewH;
}
}
void UIController::setupRenderPosition(C4JRender::eViewportType viewport)
{
- if(m_bCustomRenderPosition || m_currentRenderViewport != viewport)
+ m_currentRenderViewport = viewport;
+ m_bCustomRenderPosition = false;
+
+ F32 vpOriginX, vpOriginY, vpW, vpH;
+ GetViewportRect(getScreenWidth(), getScreenHeight(), viewport, vpOriginX, vpOriginY, vpW, vpH);
+
+ S32 xPos, yPos;
+ if(viewport == C4JRender::VIEWPORT_TYPE_FULLSCREEN)
{
- m_currentRenderViewport = viewport;
- m_bCustomRenderPosition = false;
- S32 xPos = 0;
- S32 yPos = 0;
- switch( viewport )
- {
- case C4JRender::VIEWPORT_TYPE_SPLIT_TOP:
- xPos = (S32)(getScreenWidth() / 4);
- break;
- case C4JRender::VIEWPORT_TYPE_SPLIT_BOTTOM:
- xPos = (S32)(getScreenWidth() / 4);
- yPos = (S32)(getScreenHeight() / 2);
- break;
- case C4JRender::VIEWPORT_TYPE_SPLIT_LEFT:
- yPos = (S32)(getScreenHeight() / 4);
- break;
- case C4JRender::VIEWPORT_TYPE_SPLIT_RIGHT:
- xPos = (S32)(getScreenWidth() / 2);
- yPos = (S32)(getScreenHeight() / 4);
- break;
- case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_LEFT:
- break;
- case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_RIGHT:
- xPos = (S32)(getScreenWidth() / 2);
- break;
- case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_LEFT:
- yPos = (S32)(getScreenHeight() / 2);
- break;
- case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_RIGHT:
- xPos = (S32)(getScreenWidth() / 2);
- yPos = (S32)(getScreenHeight() / 2);
- break;
- }
- m_tileOriginX = xPos;
- m_tileOriginY = yPos;
- setTileOrigin(xPos, yPos);
+ S32 fitW, fitH, fitOffsetX, fitOffsetY;
+ Fit16x9(vpW, vpH, fitW, fitH, fitOffsetX, fitOffsetY);
+ xPos = (S32)vpOriginX + fitOffsetX;
+ yPos = (S32)vpOriginY + fitOffsetY;
+ }
+ else
+ {
+ // Split-screen: position at viewport origin, no 16:9 fitting
+ xPos = (S32)vpOriginX;
+ yPos = (S32)vpOriginY;
}
+
+ m_tileOriginX = xPos;
+ m_tileOriginY = yPos;
+ setTileOrigin(xPos, yPos);
}
void UIController::setupRenderPosition(S32 xOrigin, S32 yOrigin)
@@ -1840,8 +1848,11 @@ void RADLINK UIController::TextureSubstitutionDestroyCallback ( void * user_call
ui.destroySubstitutionTexture(user_callback_data, handle);
- Textures *t = Minecraft::GetInstance()->textures;
- t->releaseTexture( id );
+ Minecraft* mc = Minecraft::GetInstance();
+ if (mc && mc->textures)
+ {
+ mc->textures->releaseTexture( id );
+ }
}
void UIController::registerSubstitutionTexture(const wstring &textureName, PBYTE pbData, DWORD dwLength)
diff --git a/Minecraft.Client/Common/UI/UIController.h b/Minecraft.Client/Common/UI/UIController.h
index 5b897b13..63ae5a19 100644
--- a/Minecraft.Client/Common/UI/UIController.h
+++ b/Minecraft.Client/Common/UI/UIController.h
@@ -257,6 +257,7 @@ public:
// RENDERING
float getScreenWidth() { return m_fScreenWidth; }
float getScreenHeight() { return m_fScreenHeight; }
+ void updateScreenSize(S32 w, S32 h) { m_fScreenWidth = (float)w; m_fScreenHeight = (float)h; app.DebugPrintf("[UI-INIT] updateScreenSize: %d x %d\n", w, h); }
virtual void render() = 0;
void getRenderDimensions(C4JRender::eViewportType viewport, S32 &width, S32 &height);
diff --git a/Minecraft.Client/Common/UI/UIScene.cpp b/Minecraft.Client/Common/UI/UIScene.cpp
index d01585cb..391a0502 100644
--- a/Minecraft.Client/Common/UI/UIScene.cpp
+++ b/Minecraft.Client/Common/UI/UIScene.cpp
@@ -1,6 +1,7 @@
#include "stdafx.h"
#include "UI.h"
#include "UIScene.h"
+#include "UISplitScreenHelpers.h"
#include "..\..\Lighting.h"
#include "..\..\LocalPlayer.h"
@@ -285,26 +286,8 @@ void UIScene::loadMovie()
moviePath.append(L"Vita.swf");
m_loadedResolution = eSceneResolution_Vita;
#elif defined _WINDOWS64
- if(ui.getScreenHeight() == 720)
- {
- moviePath.append(L"720.swf");
- m_loadedResolution = eSceneResolution_720;
- }
- else if(ui.getScreenHeight() == 480)
- {
- moviePath.append(L"480.swf");
- m_loadedResolution = eSceneResolution_480;
- }
- else if(ui.getScreenHeight() < 720)
- {
- moviePath.append(L"Vita.swf");
- m_loadedResolution = eSceneResolution_Vita;
- }
- else
- {
- moviePath.append(L"1080.swf");
- m_loadedResolution = eSceneResolution_1080;
- }
+ moviePath.append(L"1080.swf");
+ m_loadedResolution = eSceneResolution_1080;
#else
moviePath.append(L"1080.swf");
m_loadedResolution = eSceneResolution_1080;
@@ -332,8 +315,6 @@ void UIScene::loadMovie()
int64_t beforeLoad = ui.iggyAllocCount;
swf = IggyPlayerCreateFromMemory ( baFile.data , baFile.length, NULL);
int64_t afterLoad = ui.iggyAllocCount;
- IggyPlayerInitializeAndTickRS ( swf );
- int64_t afterTick = ui.iggyAllocCount;
if(!swf)
{
@@ -343,17 +324,44 @@ void UIScene::loadMovie()
#endif
app.FatalLoadError();
}
- app.DebugPrintf( app.USER_SR, "Loaded iggy movie %ls\n", moviePath.c_str() );
+
+ // Read movie dimensions from the SWF header (available immediately after
+ // CreateFromMemory, no init tick needed).
IggyProperties *properties = IggyPlayerProperties ( swf );
m_movieHeight = properties->movie_height_in_pixels;
m_movieWidth = properties->movie_width_in_pixels;
-
m_renderWidth = m_movieWidth;
m_renderHeight = m_movieHeight;
- S32 width, height;
- m_parentLayer->getRenderDimensions(width, height);
- IggyPlayerSetDisplaySize( swf, width, height );
+ // Set display size BEFORE the init tick to match what render() will use.
+ // InitializeAndTickRS runs ActionScript that creates text fields. If the
+ // display size here differs from what render() passes to SetDisplaySize,
+ // Iggy can cache glyph rasterizations at one scale during init and then
+ // reuse them at a different scale during draw, producing mixed glyph sizes.
+#ifdef _WINDOWS64
+ {
+ S32 fitW, fitH, fitOffX, fitOffY;
+ Fit16x9(ui.getScreenWidth(), ui.getScreenHeight(), fitW, fitH, fitOffX, fitOffY);
+ IggyPlayerSetDisplaySize( swf, fitW, fitH );
+ }
+#else
+ IggyPlayerSetDisplaySize( swf, m_movieWidth, m_movieHeight );
+#endif
+
+ IggyPlayerInitializeAndTickRS ( swf );
+ int64_t afterTick = ui.iggyAllocCount;
+
+#ifdef _WINDOWS64
+ // Flush Iggy's internal font caches so all glyphs get rasterized fresh
+ // at the current display scale on the first Draw. Without this, stale
+ // cache entries from a previous scene (loaded at a different display size)
+ // cause mixed glyph sizes. ResizeD3D already calls this, which is why
+ // fonts look correct after a resize but break when a scene reloads
+ // without one.
+ IggyFlushInstalledFonts();
+#endif
+
+ app.DebugPrintf( app.USER_SR, "Loaded iggy movie %ls\n", moviePath.c_str() );
IggyPlayerSetUserdata(swf,this);
@@ -685,9 +693,23 @@ void UIScene::render(S32 width, S32 height, C4JRender::eViewportType viewport)
{
if(m_bIsReloading) return;
if(!m_hasTickedOnce || !swf) return;
- ui.setupRenderPosition(viewport);
- IggyPlayerSetDisplaySize( swf, width, height );
- IggyPlayerDraw( swf );
+
+ if(viewport != C4JRender::VIEWPORT_TYPE_FULLSCREEN)
+ {
+ F32 originX, originY, viewW, viewH;
+ GetViewportRect(ui.getScreenWidth(), ui.getScreenHeight(), viewport, originX, originY, viewW, viewH);
+ S32 fitW, fitH, offsetX, offsetY;
+ Fit16x9(viewW, viewH, fitW, fitH, offsetX, offsetY);
+ ui.setupRenderPosition((S32)originX + offsetX, (S32)originY + offsetY);
+ IggyPlayerSetDisplaySize( swf, fitW, fitH );
+ IggyPlayerDraw( swf );
+ }
+ else
+ {
+ ui.setupRenderPosition(viewport);
+ IggyPlayerSetDisplaySize( swf, width, height );
+ IggyPlayerDraw( swf );
+ }
}
void UIScene::setOpacity(float percent)
diff --git a/Minecraft.Client/Common/UI/UIScene_AbstractContainerMenu.cpp b/Minecraft.Client/Common/UI/UIScene_AbstractContainerMenu.cpp
index 6b196c1b..7001ab81 100644
--- a/Minecraft.Client/Common/UI/UIScene_AbstractContainerMenu.cpp
+++ b/Minecraft.Client/Common/UI/UIScene_AbstractContainerMenu.cpp
@@ -1,6 +1,7 @@
#include "stdafx.h"
#include "UI.h"
#include "UIScene_AbstractContainerMenu.h"
+#include "UISplitScreenHelpers.h"
#include "..\..\..\Minecraft.World\net.minecraft.world.inventory.h"
#include "..\..\..\Minecraft.World\net.minecraft.world.item.h"
@@ -187,14 +188,19 @@ void UIScene_AbstractContainerMenu::PlatformInitialize(int iPad, int startIndex)
IggyEvent mouseEvent;
S32 width, height;
m_parentLayer->getRenderDimensions(width, height);
+
+ C4JRender::eViewportType vp = m_parentLayer->getViewport();
+ if(vp != C4JRender::VIEWPORT_TYPE_FULLSCREEN)
+ Fit16x9(width, height);
+
S32 x = m_pointerPos.x*((float)width/m_movieWidth);
- S32 y = m_pointerPos.y*((float)height/m_movieHeight);
+ S32 y = m_pointerPos.y*((float)height/m_movieHeight);
IggyMakeEventMouseMove( &mouseEvent, x, y);
IggyEventResult result;
IggyPlayerDispatchEventRS ( getMovie() , &mouseEvent , &result );
-#ifdef USE_POINTER_ACCEL
+#ifdef USE_POINTER_ACCEL
m_fPointerVelX = 0.0f;
m_fPointerVelY = 0.0f;
m_fPointerAccelX = 0.0f;
@@ -212,6 +218,10 @@ void UIScene_AbstractContainerMenu::tick()
S32 width, height;
m_parentLayer->getRenderDimensions(width, height);
+ C4JRender::eViewportType vp = m_parentLayer->getViewport();
+ if(vp != C4JRender::VIEWPORT_TYPE_FULLSCREEN)
+ Fit16x9(width, height);
+
S32 x = (S32)(m_pointerPos.x * ((float)width / m_movieWidth));
S32 y = (S32)(m_pointerPos.y * ((float)height / m_movieHeight));
@@ -251,6 +261,27 @@ void UIScene_AbstractContainerMenu::render(S32 width, S32 height, C4JRender::eVi
m_needsCacheRendered = false;
}
+void UIScene_AbstractContainerMenu::getMouseToSWFScale(float &scaleX, float &scaleY)
+{
+ extern HWND g_hWnd;
+ RECT rc;
+ GetClientRect(g_hWnd, &rc);
+ int winW = rc.right - rc.left;
+ int winH = rc.bottom - rc.top;
+ if(winW <= 0 || winH <= 0) { scaleX = 1.0f; scaleY = 1.0f; return; }
+
+ S32 renderW, renderH;
+ C4JRender::eViewportType vp = GetParentLayer()->getViewport();
+ ui.getRenderDimensions(vp, renderW, renderH);
+ if(vp != C4JRender::VIEWPORT_TYPE_FULLSCREEN)
+ Fit16x9(renderW, renderH);
+
+ float screenW = (float)ui.getScreenWidth();
+ float screenH = (float)ui.getScreenHeight();
+ scaleX = (float)m_movieWidth * screenW / ((float)renderW * (float)winW);
+ scaleY = (float)m_movieHeight * screenH / ((float)renderH * (float)winH);
+}
+
void UIScene_AbstractContainerMenu::customDraw(IggyCustomDrawCallbackRegion *region)
{
Minecraft *pMinecraft = Minecraft::GetInstance();
diff --git a/Minecraft.Client/Common/UI/UIScene_AbstractContainerMenu.h b/Minecraft.Client/Common/UI/UIScene_AbstractContainerMenu.h
index 605f5dbd..1a2bfff4 100644
--- a/Minecraft.Client/Common/UI/UIScene_AbstractContainerMenu.h
+++ b/Minecraft.Client/Common/UI/UIScene_AbstractContainerMenu.h
@@ -38,6 +38,7 @@ public:
int getPad() { return m_iPad; }
int getMovieWidth() { return m_movieWidth; }
int getMovieHeight() { return m_movieHeight; }
+ void getMouseToSWFScale(float &scaleX, float &scaleY);
bool getIgnoreInput() { return m_bIgnoreInput; }
void setIgnoreInput(bool bVal) { m_bIgnoreInput=bVal; }
diff --git a/Minecraft.Client/Common/UI/UIScene_HUD.cpp b/Minecraft.Client/Common/UI/UIScene_HUD.cpp
index 5f401c39..a5bd61a4 100644
--- a/Minecraft.Client/Common/UI/UIScene_HUD.cpp
+++ b/Minecraft.Client/Common/UI/UIScene_HUD.cpp
@@ -1,6 +1,7 @@
#include "stdafx.h"
#include "UI.h"
#include "UIScene_HUD.h"
+#include "UISplitScreenHelpers.h"
#include "BossMobGuiInfo.h"
#include "..\..\Minecraft.h"
#include "..\..\MultiplayerLocalPlayer.h"
@@ -266,8 +267,6 @@ void UIScene_HUD::handleReload()
SetDisplayName(ProfileManager.GetDisplayName(m_iPad));
- repositionHud();
-
SetTooltipsEnabled(((ui.GetMenuDisplayed(ProfileManager.GetPrimaryPad())) || (app.GetGameSettings(ProfileManager.GetPrimaryPad(),eGameSetting_Tooltips) != 0)));
}
@@ -697,6 +696,7 @@ void UIScene_HUD::render(S32 width, S32 height, C4JRender::eViewportType viewpor
S32 tileWidth = width;
S32 tileHeight = height;
+ bool needsYTile = false;
switch( viewport )
{
case C4JRender::VIEWPORT_TYPE_SPLIT_LEFT:
@@ -704,23 +704,25 @@ void UIScene_HUD::render(S32 width, S32 height, C4JRender::eViewportType viewpor
tileHeight = (S32)(ui.getScreenHeight());
break;
case C4JRender::VIEWPORT_TYPE_SPLIT_TOP:
- tileWidth = (S32)(ui.getScreenWidth());
- tileYStart = (S32)(m_movieHeight / 2);
- break;
case C4JRender::VIEWPORT_TYPE_SPLIT_BOTTOM:
tileWidth = (S32)(ui.getScreenWidth());
- tileYStart = (S32)(m_movieHeight / 2);
+ needsYTile = true;
break;
case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_LEFT:
case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_RIGHT:
case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_LEFT:
case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_RIGHT:
- tileYStart = (S32)(m_movieHeight / 2);
+ needsYTile = true;
break;
}
- IggyPlayerSetDisplaySize( getMovie(), m_movieWidth, m_movieHeight );
-
+ F32 scale;
+ ComputeTileScale(tileWidth, tileHeight, m_movieWidth, m_movieHeight, needsYTile, scale, tileYStart);
+
+ IggyPlayerSetDisplaySize( getMovie(), (S32)(m_movieWidth * scale), (S32)(m_movieHeight * scale) );
+
+ repositionHud(tileWidth, tileHeight, scale);
+
m_renderWidth = tileWidth;
m_renderHeight = tileHeight;
@@ -730,7 +732,7 @@ void UIScene_HUD::render(S32 width, S32 height, C4JRender::eViewportType viewpor
tileYStart ,
tileXStart + tileWidth ,
tileYStart + tileHeight ,
- 0 );
+ 0 );
IggyPlayerDrawTilesEnd ( getMovie() );
}
else
@@ -790,34 +792,24 @@ void UIScene_HUD::handleTimerComplete(int id)
//setVisible(anyVisible);
}
-void UIScene_HUD::repositionHud()
+void UIScene_HUD::repositionHud(S32 tileWidth, S32 tileHeight, F32 scale)
{
if(!m_bSplitscreen) return;
- S32 width = 0;
- S32 height = 0;
- m_parentLayer->getRenderDimensions( width, height );
-
- switch( m_parentLayer->getViewport() )
- {
- case C4JRender::VIEWPORT_TYPE_SPLIT_LEFT:
- case C4JRender::VIEWPORT_TYPE_SPLIT_RIGHT:
- height = (S32)(ui.getScreenHeight());
- break;
- case C4JRender::VIEWPORT_TYPE_SPLIT_TOP:
- case C4JRender::VIEWPORT_TYPE_SPLIT_BOTTOM:
- width = (S32)(ui.getScreenWidth());
- break;
- }
+ // Pass the visible tile area in SWF coordinates so ActionScript
+ // positions elements (crosshair, hotbar, etc.) centered in the
+ // actually visible region, not the raw viewport.
+ S32 visibleW = (S32)(tileWidth / scale);
+ S32 visibleH = (S32)(tileHeight / scale);
- app.DebugPrintf(app.USER_SR, "Reposition HUD with dims %d, %d\n", width, height );
+ app.DebugPrintf(app.USER_SR, "Reposition HUD: tile %dx%d, scale %.3f, visible SWF %dx%d\n", tileWidth, tileHeight, scale, visibleW, visibleH );
IggyDataValue result;
IggyDataValue value[2];
value[0].type = IGGY_DATATYPE_number;
- value[0].number = width;
+ value[0].number = visibleW;
value[1].type = IGGY_DATATYPE_number;
- value[1].number = height;
+ value[1].number = visibleH;
IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcRepositionHud , 2 , value );
}
diff --git a/Minecraft.Client/Common/UI/UIScene_HUD.h b/Minecraft.Client/Common/UI/UIScene_HUD.h
index 9d58ba4b..569b5234 100644
--- a/Minecraft.Client/Common/UI/UIScene_HUD.h
+++ b/Minecraft.Client/Common/UI/UIScene_HUD.h
@@ -176,5 +176,5 @@ protected:
#endif
private:
- void repositionHud();
+ void repositionHud(S32 tileWidth, S32 tileHeight, F32 scale);
};
diff --git a/Minecraft.Client/Common/UI/UIScene_Keyboard.cpp b/Minecraft.Client/Common/UI/UIScene_Keyboard.cpp
index 0af343bb..f9d558a0 100644
--- a/Minecraft.Client/Common/UI/UIScene_Keyboard.cpp
+++ b/Minecraft.Client/Common/UI/UIScene_Keyboard.cpp
@@ -38,6 +38,7 @@ UIScene_Keyboard::UIScene_Keyboard(int iPad, void *initData, UILayer *parentLaye
}
m_win64TextBuffer = defaultText;
+ m_iCursorPos = (int)m_win64TextBuffer.length();
m_EnterTextLabel.init(titleText);
m_KeyboardTextInput.init(defaultText, -1);
@@ -111,6 +112,9 @@ UIScene_Keyboard::UIScene_Keyboard(int iPad, void *initData, UILayer *parentLaye
if (IggyValuePathMakeNameRef(&keyPath, root, s_keyNames[i]))
IggyValueSetBooleanRS(&keyPath, nameVisible, NULL, false);
}
+
+ m_KeyboardTextInput.setCaretVisible(true);
+ m_KeyboardTextInput.setCaretIndex(m_iCursorPos);
}
#endif
@@ -165,9 +169,13 @@ void UIScene_Keyboard::tick()
// Sync our buffer from Flash so we pick up changes made via controller/on-screen buttons.
// Without this, switching between controller and keyboard would use stale text.
- const wchar_t* flashText = m_KeyboardTextInput.getLabel();
- if (flashText)
- m_win64TextBuffer = flashText;
+ // In PC mode we own the buffer — skip sync to preserve cursor position.
+ if (!m_bPCMode)
+ {
+ const wchar_t* flashText = m_KeyboardTextInput.getLabel();
+ if (flashText)
+ m_win64TextBuffer = flashText;
+ }
// Accumulate physical keyboard chars into our own buffer, then push to Flash via setLabel.
// This bypasses Iggy's focus system (char events only route to the focused element).
@@ -178,7 +186,16 @@ void UIScene_Keyboard::tick()
{
if (ch == 0x08) // backspace
{
- if (!m_win64TextBuffer.empty())
+ if (m_bPCMode)
+ {
+ if (m_iCursorPos > 0)
+ {
+ m_win64TextBuffer.erase(m_iCursorPos - 1, 1);
+ m_iCursorPos--;
+ changed = true;
+ }
+ }
+ else if (!m_win64TextBuffer.empty())
{
m_win64TextBuffer.pop_back();
changed = true;
@@ -194,13 +211,45 @@ void UIScene_Keyboard::tick()
}
else if ((int)m_win64TextBuffer.length() < m_win64MaxChars)
{
- m_win64TextBuffer += ch;
+ if (m_bPCMode)
+ {
+ m_win64TextBuffer.insert(m_iCursorPos, 1, ch);
+ m_iCursorPos++;
+ }
+ else
+ {
+ m_win64TextBuffer += ch;
+ }
+ changed = true;
+ }
+ }
+
+ if (m_bPCMode)
+ {
+ // Arrow keys, Home, End, Delete for cursor movement
+ if (g_KBMInput.IsKeyPressed(VK_LEFT) && m_iCursorPos > 0)
+ m_iCursorPos--;
+ if (g_KBMInput.IsKeyPressed(VK_RIGHT) && m_iCursorPos < (int)m_win64TextBuffer.length())
+ m_iCursorPos++;
+ if (g_KBMInput.IsKeyPressed(VK_HOME))
+ m_iCursorPos = 0;
+ if (g_KBMInput.IsKeyPressed(VK_END))
+ m_iCursorPos = (int)m_win64TextBuffer.length();
+ if (g_KBMInput.IsKeyPressed(VK_DELETE) && m_iCursorPos < (int)m_win64TextBuffer.length())
+ {
+ m_win64TextBuffer.erase(m_iCursorPos, 1);
changed = true;
}
}
if (changed)
m_KeyboardTextInput.setLabel(m_win64TextBuffer.c_str(), true /*instant*/);
+
+ if (m_bPCMode)
+ {
+ m_KeyboardTextInput.setCaretVisible(true);
+ m_KeyboardTextInput.setCaretIndex(m_iCursorPos);
+ }
}
#endif
@@ -286,7 +335,10 @@ void UIScene_Keyboard::handleInput(int iPad, int key, bool repeat, bool pressed,
case ACTION_MENU_RIGHT:
case ACTION_MENU_UP:
case ACTION_MENU_DOWN:
- sendInputToMovie(key, repeat, pressed, released);
+#ifdef _WINDOWS64
+ if (!m_bPCMode)
+#endif
+ sendInputToMovie(key, repeat, pressed, released);
handled = true;
break;
}
diff --git a/Minecraft.Client/Common/UI/UIScene_Keyboard.h b/Minecraft.Client/Common/UI/UIScene_Keyboard.h
index 054322f2..146934c1 100644
--- a/Minecraft.Client/Common/UI/UIScene_Keyboard.h
+++ b/Minecraft.Client/Common/UI/UIScene_Keyboard.h
@@ -13,6 +13,7 @@ private:
wstring m_win64TextBuffer;
int m_win64MaxChars;
bool m_bPCMode; // Hides on-screen keyboard buttons; physical keyboard only
+ int m_iCursorPos;
#endif
protected:
diff --git a/Minecraft.Client/Common/UI/UISplitScreenHelpers.h b/Minecraft.Client/Common/UI/UISplitScreenHelpers.h
new file mode 100644
index 00000000..e451b3f2
--- /dev/null
+++ b/Minecraft.Client/Common/UI/UISplitScreenHelpers.h
@@ -0,0 +1,114 @@
+#pragma once
+
+// Shared split-screen UI helpers to avoid duplicating viewport math
+// across HUD, Chat, Tooltips, and container menus.
+
+// Compute the raw viewport rectangle for a given viewport type.
+inline void GetViewportRect(F32 screenW, F32 screenH, C4JRender::eViewportType viewport,
+ F32 &originX, F32 &originY, F32 &viewW, F32 &viewH)
+{
+ originX = originY = 0;
+ viewW = screenW;
+ viewH = screenH;
+ switch(viewport)
+ {
+ case C4JRender::VIEWPORT_TYPE_SPLIT_TOP:
+ viewH = screenH * 0.5f; break;
+ case C4JRender::VIEWPORT_TYPE_SPLIT_BOTTOM:
+ originY = screenH * 0.5f; viewH = screenH * 0.5f; break;
+ case C4JRender::VIEWPORT_TYPE_SPLIT_LEFT:
+ viewW = screenW * 0.5f; break;
+ case C4JRender::VIEWPORT_TYPE_SPLIT_RIGHT:
+ originX = screenW * 0.5f; viewW = screenW * 0.5f; break;
+ case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_LEFT:
+ viewW = screenW * 0.5f; viewH = screenH * 0.5f; break;
+ case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_RIGHT:
+ originX = screenW * 0.5f; viewW = screenW * 0.5f; viewH = screenH * 0.5f; break;
+ case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_LEFT:
+ originY = screenH * 0.5f; viewW = screenW * 0.5f; viewH = screenH * 0.5f; break;
+ case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_RIGHT:
+ originX = screenW * 0.5f; originY = screenH * 0.5f;
+ viewW = screenW * 0.5f; viewH = screenH * 0.5f; break;
+ default: break;
+ }
+}
+
+// Fit a 16:9 rectangle inside the given dimensions.
+inline void Fit16x9(F32 viewW, F32 viewH, S32 &fitW, S32 &fitH, S32 &offsetX, S32 &offsetY)
+{
+ const F32 kAspect = 16.0f / 9.0f;
+ if(viewW / viewH > kAspect)
+ {
+ fitH = (S32)viewH;
+ fitW = (S32)(viewH * kAspect);
+ }
+ else
+ {
+ fitW = (S32)viewW;
+ fitH = (S32)(viewW / kAspect);
+ }
+ offsetX = (S32)((viewW - fitW) * 0.5f);
+ offsetY = (S32)((viewH - fitH) * 0.5f);
+}
+
+// Convenience: just fit 16:9 dimensions, ignore offsets.
+inline void Fit16x9(S32 &width, S32 &height)
+{
+ S32 offX, offY;
+ Fit16x9((F32)width, (F32)height, width, height, offX, offY);
+}
+
+// Compute the uniform scale and tileYStart for split-screen tile rendering.
+// Used by HUD, Chat, and Tooltips to scale the SWF movie to cover the viewport tile.
+inline void ComputeTileScale(S32 tileWidth, S32 tileHeight, S32 movieWidth, S32 movieHeight,
+ bool needsYTile, F32 &outScale, S32 &outTileYStart)
+{
+ F32 scaleW = (F32)tileWidth / (F32)movieWidth;
+ F32 scaleH = (F32)tileHeight / (F32)movieHeight;
+ F32 scale = (scaleW > scaleH) ? scaleW : scaleH;
+ if(scale < 1.0f) scale = 1.0f;
+
+ outTileYStart = 0;
+ if(needsYTile)
+ {
+ S32 dispH = (S32)(movieHeight * scale);
+ outTileYStart = dispH - tileHeight;
+ if(outTileYStart < 0) outTileYStart = 0;
+ scaleH = (F32)(outTileYStart + tileHeight) / (F32)movieHeight;
+ scale = (scaleW > scaleH) ? scaleW : scaleH;
+ if(scale < 1.0f) scale = 1.0f;
+ }
+
+ outScale = scale;
+}
+
+// Compute the render offset to center split-screen SWF content in the viewport.
+// Used by Chat and Tooltips (HUD uses repositionHud instead).
+inline void ComputeSplitContentOffset(C4JRender::eViewportType viewport, S32 movieWidth, S32 movieHeight,
+ F32 scale, S32 tileWidth, S32 tileHeight, S32 tileYStart,
+ S32 &outXOffset, S32 &outYOffset)
+{
+ S32 contentCenterX, contentCenterY;
+ if(viewport == C4JRender::VIEWPORT_TYPE_SPLIT_LEFT || viewport == C4JRender::VIEWPORT_TYPE_SPLIT_RIGHT)
+ {
+ contentCenterX = (S32)(movieWidth * scale / 4);
+ contentCenterY = (S32)(movieHeight * scale / 2);
+ }
+ else if(viewport == C4JRender::VIEWPORT_TYPE_SPLIT_TOP || viewport == C4JRender::VIEWPORT_TYPE_SPLIT_BOTTOM)
+ {
+ contentCenterX = (S32)(movieWidth * scale / 2);
+ contentCenterY = (S32)(movieHeight * scale * 3 / 4);
+ }
+ else
+ {
+ contentCenterX = (S32)(movieWidth * scale / 4);
+ contentCenterY = (S32)(movieHeight * scale * 3 / 4);
+ }
+
+ outXOffset = 0;
+ outYOffset = 0;
+ if(viewport == C4JRender::VIEWPORT_TYPE_SPLIT_LEFT || viewport == C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_LEFT || viewport == C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_LEFT)
+ outXOffset = -(tileWidth / 2 - contentCenterX);
+ if(viewport == C4JRender::VIEWPORT_TYPE_SPLIT_TOP || viewport == C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_LEFT || viewport == C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_RIGHT)
+ outYOffset = -(tileHeight / 2 - (contentCenterY - tileYStart));
+}