4jcraft/Minecraft.Client/Platform/Common/UI/UIGroup.cpp
Nikita Edel a006cc5aa0 uninitialized vptr
the vptr to isSolidRender() is not known before contruction of the Tile. Its true by default. if false, need to pass false. that is what i did. i verfied what isSolidRender() is in every file. and did exactly what isSolidRender() would return
2026-03-10 23:22:34 +01:00

423 lines
11 KiB
C++

#include "../../Minecraft.World/Platform/stdafx.h"
#include "UIGroup.h"
UIGroup::UIGroup(EUIGroup group, int iPad)
{
m_group = group;
m_iPad = iPad;
m_bMenuDisplayed = false;
m_bPauseMenuDisplayed = false;
m_bContainerMenuDisplayed = false;
m_bIgnoreAutosaveMenuDisplayed = false;
m_bIgnorePlayerJoinMenuDisplayed = false;
// 4jcraft, moved this to the top
// uninitialized memory was read.
m_viewportType = C4JRender::VIEWPORT_TYPE_FULLSCREEN;
m_updateFocusStateCountdown = 0;
for(unsigned int i = 0; i < eUILayer_COUNT; ++i)
{
m_layers[i] = new UILayer(this);
#ifdef __PSVITA__
m_layers[i]->m_iLayer=(EUILayer)i;
#endif
}
m_tooltips = (UIComponent_Tooltips *)m_layers[(int)eUILayer_Tooltips]->addComponent(0, eUIComponent_Tooltips);
m_tutorialPopup = NULL;
m_hud = NULL;
m_pressStartToPlay = NULL;
if(m_group != eUIGroup_Fullscreen)
{
m_tutorialPopup = (UIComponent_TutorialPopup *)m_layers[(int)eUILayer_Popup]->addComponent(m_iPad, eUIComponent_TutorialPopup);
m_hud = (UIScene_HUD *)m_layers[(int)eUILayer_HUD]->addComponent(m_iPad, eUIScene_HUD);
//m_layers[(int)eUILayer_Chat]->addComponent(m_iPad, eUIComponent_Chat);
}
else
{
m_pressStartToPlay = (UIComponent_PressStartToPlay *)m_layers[(int)eUILayer_Tooltips]->addComponent(0, eUIComponent_PressStartToPlay);
}
// 4J Stu - Pre-allocate this for cached rendering in scenes. It's horribly slow to do dynamically, but we should only need one
// per group as we will only be displaying one of these types of scenes at a time
m_commandBufferList = MemoryTracker::genLists(1);
}
void UIGroup::DestroyAll()
{
for(unsigned int i = 0; i < eUILayer_COUNT; ++i)
{
m_layers[i]->DestroyAll();
}
}
void UIGroup::ReloadAll()
{
// We only need to reload things when they are likely to be rendered
int highestRenderable = 0;
for(; highestRenderable < eUILayer_COUNT; ++highestRenderable)
{
if(m_layers[highestRenderable]->hidesLowerScenes()) break;
}
if(highestRenderable < eUILayer_Fullscreen) highestRenderable = eUILayer_Fullscreen;
for(; highestRenderable >= 0; --highestRenderable)
{
if(highestRenderable < eUILayer_COUNT) m_layers[highestRenderable]->ReloadAll(highestRenderable != (int)eUILayer_Fullscreen);
}
}
void UIGroup::tick()
{
// Ignore this group if the player isn't signed in
if(m_iPad >= 0 && !ProfileManager.IsSignedIn(m_iPad)) return;
for(unsigned int i = 0; i < eUILayer_COUNT; ++i)
{
m_layers[i]->tick();
// TODO: May wish to ignore ticking other layers here based on current layer
}
// Handle deferred update focus
if (m_updateFocusStateCountdown > 0)
{
m_updateFocusStateCountdown--;
if (m_updateFocusStateCountdown == 0)_UpdateFocusState();
}
}
void UIGroup::render()
{
// Ignore this group if the player isn't signed in
if(m_iPad >= 0 && !ProfileManager.IsSignedIn(m_iPad)) return;
S32 width = 0;
S32 height = 0;
ui.getRenderDimensions(m_viewportType, width, height);
int highestRenderable = 0;
for(; highestRenderable < eUILayer_COUNT; ++highestRenderable)
{
if(m_layers[highestRenderable]->hidesLowerScenes()) break;
}
for(; highestRenderable >= 0; --highestRenderable)
{
if(highestRenderable < eUILayer_COUNT) m_layers[highestRenderable]->render(width, height,m_viewportType);
}
}
bool UIGroup::hidesLowerScenes()
{
// Ignore this group if the player isn't signed in
if(m_iPad >= 0 && !ProfileManager.IsSignedIn(m_iPad)) return false;
bool hidesScenes = false;
for(int i = eUILayer_COUNT - 1; i >= 0; --i)
{
hidesScenes = m_layers[i]->hidesLowerScenes();
if(hidesScenes) break;
}
return hidesScenes;
}
void UIGroup::getRenderDimensions(S32 &width, S32 &height)
{
ui.getRenderDimensions(m_viewportType, width, height);
}
// NAVIGATION
bool UIGroup::NavigateToScene(int iPad, EUIScene scene, void *initData, EUILayer layer)
{
bool succeeded = m_layers[(int)layer]->NavigateToScene(iPad, scene, initData);
updateStackStates();
return succeeded;
}
bool UIGroup::NavigateBack(int iPad, EUIScene eScene, EUILayer eLayer)
{
// Keep navigating back on every layer until we hit the target scene
bool foundTarget = false;
for(unsigned int i = 0; i < eUILayer_COUNT; ++i)
{
if(eLayer < eUILayer_COUNT && eLayer != i) continue;
foundTarget = m_layers[i]->NavigateBack(iPad, eScene);
if(foundTarget) break;
}
updateStackStates();
return foundTarget;
}
void UIGroup::closeAllScenes()
{
Minecraft *pMinecraft = Minecraft::GetInstance();
if( m_iPad >= 0 )
{
if(pMinecraft != NULL && pMinecraft->localgameModes[m_iPad] != NULL )
{
TutorialMode *gameMode = (TutorialMode *)pMinecraft->localgameModes[m_iPad];
// This just allows it to be shown
gameMode->getTutorial()->showTutorialPopup(true);
}
}
for(unsigned int i = 0; i < eUILayer_COUNT; ++i)
{
// Ignore the error layer
if(i != (int)eUILayer_Error) m_layers[i]->closeAllScenes();
}
updateStackStates();
}
UIScene *UIGroup::GetTopScene(EUILayer layer)
{
return m_layers[(int)layer]->GetTopScene();
}
bool UIGroup::GetMenuDisplayed()
{
return m_bMenuDisplayed;
}
bool UIGroup::IsSceneInStack(EUIScene scene)
{
bool found = false;
for(unsigned int i = 0; i < eUILayer_COUNT; ++i)
{
found = m_layers[i]->IsSceneInStack(scene);
if(found) break;
}
return found;
}
bool UIGroup::HasFocus(int iPad)
{
bool hasFocus = false;
for(unsigned int i = 0; i < eUILayer_COUNT; ++i)
{
if( m_layers[i]->m_hasFocus)
{
if(m_layers[i]->HasFocus(iPad))
{
hasFocus = true;
}
break;
}
}
return hasFocus;
}
#ifdef __PSVITA__
UIScene *UIGroup::getCurrentScene()
{
UIScene *pScene;
for(unsigned int i = 0; i < eUILayer_COUNT; ++i)
{
pScene=m_layers[i]->getCurrentScene();
if(pScene!=NULL) return pScene;
}
return NULL;
}
#endif
// INPUT
void UIGroup::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled)
{
// Ignore this group if the player isn't signed in
if(m_iPad >= 0 && !ProfileManager.IsSignedIn(m_iPad)) return;
for(unsigned int i = 0; i < eUILayer_COUNT; ++i)
{
m_layers[i]->handleInput(iPad, key, repeat, pressed, released, handled);
if(handled) break;
}
}
// FOCUS
// Check that a layer may recieve focus, specifically that there is no infocus layer above
bool UIGroup::RequestFocus(UILayer* layerPtr)
{
// Find the layer
unsigned int layerIndex = GetLayerIndex(layerPtr);
// Top layer is always allowed focus
if (layerIndex == 0) return true;
// Check layers above to see if any of them have focus
for (int i = layerIndex-1; i >= 0; i--)
{
if (m_layers[i]->m_hasFocus) return false;
}
return true;
}
void UIGroup::showComponent(int iPad, EUIScene scene, EUILayer layer, bool show)
{
m_layers[layer]->showComponent(iPad, scene, show);
}
UIScene *UIGroup::addComponent(int iPad, EUIScene scene, EUILayer layer)
{
return m_layers[layer]->addComponent(iPad, scene);
}
void UIGroup::removeComponent(EUIScene scene, EUILayer layer)
{
m_layers[layer]->removeComponent(scene);
}
void UIGroup::SetViewportType(C4JRender::eViewportType type)
{
if(m_viewportType != type)
{
m_viewportType = type;
for(unsigned int i = 0; i < eUILayer_COUNT; ++i)
{
m_layers[i]->ReloadAll(true);
}
}
}
C4JRender::eViewportType UIGroup::GetViewportType()
{
return m_viewportType;
}
void UIGroup::HandleDLCMountingComplete()
{
// Ignore this group if the player isn't signed in
if(m_iPad >= 0 && !ProfileManager.IsSignedIn(m_iPad)) return;
for(unsigned int i = 0; i < eUILayer_COUNT; ++i)
{
app.DebugPrintf("UIGroup::HandleDLCMountingComplete - m_layers[%d]\n",i);
m_layers[i]->HandleDLCMountingComplete();
}
}
void UIGroup::HandleDLCInstalled()
{
// Ignore this group if the player isn't signed in
if(m_iPad >= 0 && !ProfileManager.IsSignedIn(m_iPad)) return;
for(unsigned int i = 0; i < eUILayer_COUNT; ++i)
{
m_layers[i]->HandleDLCInstalled();
}
}
#ifdef _XBOX_ONE
void UIGroup::HandleDLCLicenseChange()
{
// Ignore this group if the player isn't signed in
if(m_iPad >= 0 && !ProfileManager.IsSignedIn(m_iPad)) return;
for(unsigned int i = 0; i < eUILayer_COUNT; ++i)
{
m_layers[i]->HandleDLCLicenseChange();
}
}
#endif
bool UIGroup::IsFullscreenGroup()
{
return m_group == eUIGroup_Fullscreen;
}
void UIGroup::handleUnlockFullVersion()
{
for(unsigned int i = 0; i < eUILayer_COUNT; ++i)
{
m_layers[i]->handleUnlockFullVersion();
}
}
void UIGroup::updateStackStates()
{
m_bMenuDisplayed = false;
m_bPauseMenuDisplayed = false;
m_bContainerMenuDisplayed = false;
m_bIgnoreAutosaveMenuDisplayed = false;
m_bIgnorePlayerJoinMenuDisplayed = false;
for(unsigned int i = 0; i < eUILayer_COUNT; ++i)
{
m_bMenuDisplayed = m_bMenuDisplayed || m_layers[i]->m_bMenuDisplayed;
m_bPauseMenuDisplayed = m_bPauseMenuDisplayed || m_layers[i]->m_bPauseMenuDisplayed;
m_bContainerMenuDisplayed = m_bContainerMenuDisplayed || m_layers[i]->m_bContainerMenuDisplayed;
m_bIgnoreAutosaveMenuDisplayed = m_bIgnoreAutosaveMenuDisplayed || m_layers[i]->m_bIgnoreAutosaveMenuDisplayed;
m_bIgnorePlayerJoinMenuDisplayed = m_bIgnorePlayerJoinMenuDisplayed || m_layers[i]->m_bIgnorePlayerJoinMenuDisplayed;
}
}
// Defer update focus till for 10 UI ticks
void UIGroup::UpdateFocusState()
{
m_updateFocusStateCountdown = 10;
}
// Pass focus to uppermost layer that accepts focus
void UIGroup::_UpdateFocusState()
{
bool groupFocusSet = false;
for(unsigned int i = 0; i < eUILayer_COUNT; ++i)
{
groupFocusSet = m_layers[i]->updateFocusState(true);
if (groupFocusSet) break;
}
}
// Get the index of the layer
unsigned int UIGroup::GetLayerIndex(UILayer* layerPtr)
{
for(unsigned int i = 0; i < eUILayer_COUNT; ++i)
{
if (m_layers[i] == layerPtr) return i;
}
// can't get here...
return 0;
}
void UIGroup::PrintTotalMemoryUsage(__int64 &totalStatic, __int64 &totalDynamic)
{
__int64 groupStatic = 0;
__int64 groupDynamic = 0;
app.DebugPrintf(app.USER_SR, "-- BEGIN GROUP %d\n",m_group);
for(unsigned int i = 0; i < eUILayer_COUNT; ++i)
{
app.DebugPrintf(app.USER_SR, " \\- BEGIN LAYER %d\n",i);
m_layers[i]->PrintTotalMemoryUsage(groupStatic, groupDynamic);
app.DebugPrintf(app.USER_SR, " \\- END LAYER %d\n",i);
}
app.DebugPrintf(app.USER_SR, "-- Group static: %d, Group dynamic: %d\n", groupStatic, groupDynamic);
totalStatic += groupStatic;
totalDynamic += groupDynamic;
app.DebugPrintf(app.USER_SR, "-- END GROUP %d\n",m_group);
}
int UIGroup::getCommandBufferList()
{
return m_commandBufferList;
}
// Returns the first scene of given type if it exists, NULL otherwise
UIScene *UIGroup::FindScene(EUIScene sceneType)
{
UIScene *pScene = NULL;
for (int i = 0; i < eUILayer_COUNT; i++)
{
pScene = m_layers[i]->FindScene(sceneType);
#ifdef __PS3__
if (pScene != NULL) return pScene;
#else
if (pScene != nullptr) return pScene;
#endif
}
return pScene;
}