aboutsummaryrefslogtreecommitdiff
path: root/Minecraft.Client/Common/XUI/XUI_Scene_AbstractContainer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Minecraft.Client/Common/XUI/XUI_Scene_AbstractContainer.cpp')
-rw-r--r--Minecraft.Client/Common/XUI/XUI_Scene_AbstractContainer.cpp475
1 files changed, 475 insertions, 0 deletions
diff --git a/Minecraft.Client/Common/XUI/XUI_Scene_AbstractContainer.cpp b/Minecraft.Client/Common/XUI/XUI_Scene_AbstractContainer.cpp
new file mode 100644
index 00000000..10369d5e
--- /dev/null
+++ b/Minecraft.Client/Common/XUI/XUI_Scene_AbstractContainer.cpp
@@ -0,0 +1,475 @@
+#include "stdafx.h"
+#include <xuiresource.h>
+#include <xuiapp.h>
+#include <assert.h>
+
+#include "..\..\..\Minecraft.World\Player.h"
+#include "..\..\..\Minecraft.Client\LocalPlayer.h"
+#include "..\..\..\Minecraft.Client\Minecraft.h"
+#include "..\..\..\Minecraft.Client\GameMode.h"
+#include "..\..\..\Minecraft.World\AbstractContainerMenu.h"
+#include "..\..\..\Minecraft.World\net.minecraft.world.inventory.h"
+#include "..\..\..\Minecraft.World\net.minecraft.world.item.h"
+#include "..\..\..\Minecraft.World\Tile.h"
+#include "..\..\..\Minecraft.World\FurnaceRecipes.h"
+#include "..\..\..\Minecraft.World\Recipy.h"
+#include "..\..\..\Minecraft.World\Recipes.h"
+#include "..\..\..\Minecraft.World\ArmorRecipes.h"
+#include "..\..\..\Minecraft.World\StringHelpers.h"
+
+#include "..\..\Common\Tutorial\Tutorial.h"
+#include "..\..\Common\Tutorial\TutorialMode.h"
+
+#include "XUI_Ctrl_SlotList.h"
+#include "XUI_Ctrl_SlotItem.h"
+#include "XUI_Ctrl_SlotItemListItem.h"
+#include "XUI_Scene_AbstractContainer.h"
+#ifdef _DEBUG_MENUS_ENABLED
+#include "XUI_DebugItemEditor.h"
+#endif
+
+#define IGNORE_KEYPRESS_TIMERID 11
+#define IGNORE_KEYPRESS_TIME 100
+
+void CXuiSceneAbstractContainer::PlatformInitialize(int iPad, int startIndex)
+{
+ m_bIgnoreKeyPresses=true;
+ m_iPad = iPad;
+
+ XuiControlSetText(m_InventoryText,app.GetString(IDS_INVENTORY));
+
+ // Determine min and max extents for pointer, it needs to be able to move off the container to drop items.
+ float fPanelWidth, fPanelHeight;
+ float fPointerWidth, fPointerHeight;
+
+ // We may have varying depths of controls here, so base off the pointers parent
+ HXUIOBJ parent;
+ XuiElementGetBounds( m_pointerControl->m_hObj, &fPointerWidth, &fPointerHeight );
+ XuiElementGetParent( m_pointerControl->m_hObj, &parent );
+ m_pointerControl->SetShow(TRUE);
+ XuiElementGetBounds( parent, &fPanelWidth, &fPanelHeight );
+ // Get size of pointer
+ m_fPointerImageOffsetX = floor(fPointerWidth/2.0f);
+ m_fPointerImageOffsetY = floor(fPointerHeight/2.0f);
+
+ m_fPanelMinX = 0.0f;
+ m_fPanelMaxX = fPanelWidth;
+ m_fPanelMinY = 0.0f;
+ m_fPanelMaxY = fPanelHeight;
+
+ // 4J-PB - need to limit this in splitscreen
+ if(app.GetLocalPlayerCount()>1)
+ {
+ // don't let the pointer go into someone's screen
+ m_fPointerMinY = floor(fPointerHeight/2.0f);
+ }
+ else
+ {
+ m_fPointerMinY = -fPointerHeight;
+ }
+ m_fPointerMinX = -fPointerWidth;
+ m_fPointerMaxX = fPanelWidth + fPointerWidth;
+ m_fPointerMaxY = fPanelHeight + (fPointerHeight/2);
+
+// m_hPointerText=NULL;
+// m_hPointerTextBkg=NULL;
+
+ UIVec2D itemPos;
+ UIVec2D itemSize;
+ GetItemScreenData( m_eCurrSection, 0, &( itemPos ), &( itemSize ) );
+
+ UIVec2D sectionPos;
+ GetPositionOfSection( m_eCurrSection, &( sectionPos ) );
+
+ UIVec2D vPointerPos = sectionPos;
+ vPointerPos += itemPos;
+ vPointerPos.x += ( itemSize.x / 2.0f );
+ vPointerPos.y += ( itemSize.y / 2.0f );
+
+ vPointerPos.x -= m_fPointerImageOffsetX;
+ vPointerPos.y -= m_fPointerImageOffsetY;
+
+ D3DXVECTOR3 newPointerPos;
+ newPointerPos.x = vPointerPos.x;
+ newPointerPos.y = vPointerPos.y;
+ newPointerPos.z = 0.0f;
+ m_pointerControl->SetPosition( &newPointerPos );
+ m_pointerPos.x = newPointerPos.x;
+ m_pointerPos.y = newPointerPos.y;
+
+#ifdef USE_POINTER_ACCEL
+ m_fPointerVelX = 0.0f;
+ m_fPointerVelY = 0.0f;
+ m_fPointerAccelX = 0.0f;
+ m_fPointerAccelY = 0.0f;
+#endif
+
+ // Add timer to poll controller stick input at 60Hz
+ HRESULT timerResult = SetTimer( POINTER_INPUT_TIMER_ID, ( 1000 / 60 ) );
+ assert( timerResult == S_OK );
+
+ XuiSetTimer(m_hObj,IGNORE_KEYPRESS_TIMERID,IGNORE_KEYPRESS_TIME);
+
+ // Disable the default navigation behaviour for all slot lsit items (prevent old style cursor navigation).
+ for ( int iSection = m_eFirstSection; iSection < m_eMaxSection; ++iSection )
+ {
+ ESceneSection eSection = ( ESceneSection )( iSection );
+
+ if(!IsSectionSlotList(eSection)) continue;
+
+ // Get dimensions of this section.
+ int iNumRows;
+ int iNumColumns;
+ int iNumItems = GetSectionDimensions( eSection, &( iNumColumns ), &( iNumRows ) );
+
+ for ( int iItem = 0; iItem < iNumItems; ++iItem )
+ {
+ CXuiCtrlSlotItemListItem* pCXuiCtrlSlotItem;
+ GetSectionSlotList( eSection )->GetCXuiCtrlSlotItem( iItem, &( pCXuiCtrlSlotItem ) );
+ pCXuiCtrlSlotItem->SetSkipsDefaultNavigation( TRUE );
+ }
+ }
+}
+
+// 4J Stu - Added to support auto-save. Need to re-associate on a navigate back
+void CXuiSceneAbstractContainer::InitDataAssociations(int iPad, AbstractContainerMenu *menu, int startIndex /*= 0*/)
+{
+ // TODO Inventory dimensions need defined as constants
+ m_inventoryControl->SetData( iPad, menu, 3, 9, startIndex, startIndex + 3*9 );
+
+ // TODO Inventory dimensions need defined as constants
+ m_useRowControl->SetData( iPad, menu, 1, 9, startIndex + 3*9, startIndex + 4*9 );
+
+ m_pointerControl->SetUserIndex(m_pointerControl->m_hObj, iPad);
+}
+
+int CXuiSceneAbstractContainer::getSectionColumns(ESceneSection eSection)
+{
+ return GetSectionSlotList( eSection )->GetColumns();
+}
+
+int CXuiSceneAbstractContainer::getSectionRows(ESceneSection eSection)
+{
+ return GetSectionSlotList( eSection )->GetRows();
+}
+
+// Adding this so we can turn off the pointer text background, since it flickers on then off at the start of a scene where a tutorial popup is
+HRESULT CXuiSceneAbstractContainer::OnTransitionStart( XUIMessageTransition *pTransition, BOOL& bHandled )
+{
+ if(pTransition->dwTransAction==XUI_TRANSITION_ACTION_DESTROY ) return S_OK;
+
+ if(pTransition->dwTransType == XUI_TRANSITION_TO || pTransition->dwTransType == XUI_TRANSITION_BACKTO)
+ {
+ // 4J Stu - Added to support auto-save. Need to re-associate on a navigate back
+ if(pTransition->dwTransType == XUI_TRANSITION_BACKTO)
+ {
+ // Add timer to poll controller stick input at 60Hz
+ HRESULT timerResult = SetTimer( POINTER_INPUT_TIMER_ID, ( 1000 / 60 ) );
+ assert( timerResult == S_OK );
+
+ InitDataAssociations(m_iPad, m_menu);
+ }
+
+ HXUIOBJ hObj=NULL;
+ HRESULT hr=XuiControlGetVisual(m_pointerControl->m_hObj,&hObj);
+ hr=XuiElementGetChildById(hObj,L"text_measurer",&m_hPointerTextMeasurer);
+ hr=XuiElementGetChildById(hObj,L"text_name",&m_hPointerText);
+ hr=XuiElementGetChildById(hObj,L"text_panel",&m_hPointerTextBkg);
+ hr=XuiElementGetChildById(hObj,L"pointer_image",&m_hPointerImg);
+ XuiElementSetShow(m_hPointerText,FALSE);
+ XuiElementSetShow(m_hPointerTextBkg,FALSE);
+ }
+
+ return S_OK;
+}
+
+
+D3DXVECTOR3 CXuiSceneAbstractContainer::GetCursorScreenPosition()
+{
+ return app.GetElementScreenPosition(m_pointerControl->m_hObj);
+}
+
+HRESULT CXuiSceneAbstractContainer::OnKeyDown(XUIMessageInput *pInputData, BOOL& bHandled)
+{
+ if(m_bIgnoreKeyPresses) return S_OK;
+
+ bHandled = handleKeyDown(pInputData->UserIndex, mapVKToAction(pInputData->dwKeyCode), (pInputData->dwFlags & XUI_INPUT_FLAG_REPEAT) != 0);
+
+ return S_OK;
+}
+
+int CXuiSceneAbstractContainer::mapVKToAction(int vk)
+{
+ int action = MINECRAFT_ACTION_MAX;
+ switch(vk)
+ {
+ case VK_PAD_A:
+ action = ACTION_MENU_A;
+ break;
+ case VK_PAD_B:
+ case VK_PAD_START:
+ action = ACTION_MENU_B;
+ break;
+ case VK_PAD_X:
+ action = ACTION_MENU_X;
+ break;
+ case VK_PAD_Y:
+ action = ACTION_MENU_Y;
+ break;
+ case VK_PAD_DPAD_LEFT:
+ action = ACTION_MENU_LEFT;
+ break;
+ case VK_PAD_DPAD_RIGHT:
+ action = ACTION_MENU_RIGHT;
+ break;
+ case VK_PAD_DPAD_UP:
+ action = ACTION_MENU_UP;
+ break;
+ case VK_PAD_DPAD_DOWN:
+ action = ACTION_MENU_DOWN;
+ break;
+ case VK_PAD_LTRIGGER:
+ action = ACTION_MENU_PAGEUP;
+ break;
+ case VK_PAD_RTRIGGER:
+ action = ACTION_MENU_PAGEDOWN;
+ break;
+ case VK_PAD_LSHOULDER:
+ action = ACTION_MENU_LEFT_SCROLL;
+ break;
+ case VK_PAD_RSHOULDER:
+ action = ACTION_MENU_RIGHT_SCROLL;
+ break;
+ case VK_PAD_RTHUMB_UP:
+ action = ACTION_MENU_OTHER_STICK_UP;
+ break;
+ case VK_PAD_RTHUMB_DOWN:
+ action = ACTION_MENU_OTHER_STICK_DOWN;
+ break;
+ case VK_PAD_RTHUMB_RIGHT:
+ action = ACTION_MENU_OTHER_STICK_RIGHT;
+ break;
+ case VK_PAD_RTHUMB_LEFT:
+ action = ACTION_MENU_OTHER_STICK_LEFT;
+ break;
+ };
+
+ return action;
+}
+
+void CXuiSceneAbstractContainer::handleSectionClick(ESceneSection eSection)
+{
+ CXuiCtrlSlotList *slotList = GetSectionSlotList( eSection );
+ slotList->Clicked();
+}
+
+HRESULT CXuiSceneAbstractContainer::handleCustomTimer( XUIMessageTimer *pTimer, BOOL& bHandled )
+{
+ return S_OK;
+}
+
+// Returns XUI position of given scene section.
+void CXuiSceneAbstractContainer::GetPositionOfSection( ESceneSection eSection, UIVec2D* pPosition )
+{
+ D3DXVECTOR3 xuiPos;
+ GetSectionControl( eSection )->GetPosition( &xuiPos );
+ pPosition->x = xuiPos.x;
+ pPosition->y = xuiPos.y;
+}
+
+void CXuiSceneAbstractContainer::GetItemScreenData( ESceneSection eSection, int iItemIndex, UIVec2D* pPosition, UIVec2D* pSize )
+{
+ D3DXVECTOR3 xuiPos;
+ if(IsSectionSlotList(eSection))
+ {
+ // Get slot item.
+ CXuiCtrlSlotItemListItem* pCXuiCtrlSlotItem;
+ GetSectionSlotList( eSection )->GetCXuiCtrlSlotItem( iItemIndex, &( pCXuiCtrlSlotItem ) );
+
+ // Get size of slot.
+ pCXuiCtrlSlotItem->GetBounds( &( pSize->x ), &( pSize->y ) );
+
+ // Get position of slot.
+ pCXuiCtrlSlotItem->GetPosition( &xuiPos );
+ pPosition->x = xuiPos.x;
+ pPosition->y = xuiPos.y;
+ }
+ else
+ {
+ // Get size of control
+ GetSectionControl( eSection )->GetBounds( &( pSize->x ), &( pSize->y ) );
+
+ // Get position of control
+ GetSectionControl( eSection )->GetPosition( &xuiPos );
+ pPosition->x = xuiPos.x;
+ pPosition->y = xuiPos.y;
+ }
+}
+
+shared_ptr<ItemInstance> CXuiSceneAbstractContainer::getSlotItem(ESceneSection eSection, int iSlot)
+{
+ CXuiCtrlSlotItemListItem* pCXuiCtrlSlotItem;
+ GetSectionSlotList( eSection )->GetCXuiCtrlSlotItem( iSlot, &( pCXuiCtrlSlotItem ) );
+ return pCXuiCtrlSlotItem->getItemInstance( pCXuiCtrlSlotItem->m_hObj );
+}
+
+bool CXuiSceneAbstractContainer::isSlotEmpty(ESceneSection eSection, int iSlot)
+{
+ CXuiCtrlSlotItemListItem* pCXuiCtrlSlotItem;
+ GetSectionSlotList( eSection )->GetCXuiCtrlSlotItem( iSlot, &( pCXuiCtrlSlotItem ) );
+ return pCXuiCtrlSlotItem->isEmpty( pCXuiCtrlSlotItem->m_hObj );
+}
+
+HRESULT CXuiSceneAbstractContainer::OnTimer( XUIMessageTimer *pTimer, BOOL& bHandled )
+{
+ HRESULT hr = S_OK;
+
+ // Update pointer from stick input on timer.
+ if ( pTimer->nId == POINTER_INPUT_TIMER_ID )
+ {
+
+ onMouseTick();
+ D3DXVECTOR3 pointerPos;
+ pointerPos.x = m_pointerPos.x;
+ pointerPos.y = m_pointerPos.y;
+ pointerPos.z = 0.0f;
+ m_pointerControl->SetPosition( &pointerPos );
+ // This message has been dealt with, don't pass it on further.
+ bHandled = TRUE;
+ }
+ else if ( pTimer->nId == IGNORE_KEYPRESS_TIMERID)
+ {
+ KillTimer(IGNORE_KEYPRESS_TIMERID);
+ m_bIgnoreKeyPresses=false;
+ }
+ else
+ {
+ // Some scenes may have their own timers for other events, so handle them here
+ hr = handleCustomTimer( pTimer, bHandled );
+ }
+ return hr;
+}
+
+HRESULT CXuiSceneAbstractContainer::OnCustomMessage_Splitscreenplayer(bool bJoining, BOOL& bHandled)
+{
+ bHandled=true;
+ return app.AdjustSplitscreenScene_PlayerChanged(m_hObj,&m_OriginalPosition,m_iPad,bJoining);
+}
+
+bool CXuiSceneAbstractContainer::doesSectionTreeHaveFocus(ESceneSection eSection)
+{
+ return GetSectionControl( eSection )->TreeHasFocus();
+}
+
+void CXuiSceneAbstractContainer::setSectionFocus(ESceneSection eSection, int iPad)
+{
+ HRESULT focusResult = GetSectionControl( eSection )->SetFocus( iPad );
+ assert( focusResult == S_OK );
+}
+
+void CXuiSceneAbstractContainer::setSectionSelectedSlot(ESceneSection eSection, int x, int y)
+{
+ GetSectionSlotList( eSection )->SetCurrentSlot(y,x);
+}
+
+void CXuiSceneAbstractContainer::setFocusToPointer(int iPad)
+{
+ m_pointerControl->SetFocus( iPad );
+}
+
+void CXuiSceneAbstractContainer::SetPointerText(const wstring &description, vector<wstring> &unformattedStrings, bool newSlot)
+{
+ if(description.empty())
+ {
+ m_pointerControl->SetText(L"");
+ XuiElementSetShow(m_hPointerText,FALSE);
+ XuiElementSetShow(m_hPointerTextBkg,FALSE);
+ return;
+ }
+
+ bool smallPointer = m_bSplitscreen || (!RenderManager.IsHiDef() && !RenderManager.IsWidescreen());
+ wstring desc = L"<font size=\"" + _toString<int>(smallPointer ? 12 :14) + L"\">" + description + L"</font>";
+
+ XUIRect tempXuiRect, xuiRect;
+ HRESULT hr;
+ xuiRect.right = 0;
+
+ for(AUTO_VAR(it, unformattedStrings.begin()); it != unformattedStrings.end(); ++it)
+ {
+ XuiTextPresenterMeasureText(m_hPointerTextMeasurer, parseXMLSpecials((*it)).c_str(), &tempXuiRect);
+ if(tempXuiRect.right > xuiRect.right) xuiRect = tempXuiRect;
+ }
+
+ // Set size with the new width so that the HTML height check is correct
+ XuiElementSetBounds(m_hPointerTextBkg,xuiRect.right+4.0f+4.0f+4.0f,xuiRect.bottom); // edge graphics are 8 pixels, with 4 for the border, extra 4 for the background is fudge
+ XuiElementSetBounds(m_hPointerText,xuiRect.right+4.0f+4.0f,xuiRect.bottom); // edge graphics are 8 pixels, text is centred
+
+ XuiHtmlSetText(m_hPointerText, desc.c_str() );
+
+ // Check if we need to resize the box
+ XUIContentDims contentDims;
+ XuiHtmlGetContentDims(m_hPointerText,&contentDims);
+ xuiRect.bottom = contentDims.nContentHeight;
+
+ // get the size of the button, and apply the change in size due to the text to the whole button
+ float fImgWidth,fImgHeight;
+ XuiElementGetBounds(m_hPointerImg,&fImgWidth, &fImgHeight);
+ // 4J-PB - changing to calculate values
+ D3DXVECTOR3 vPosText, vPosTextBkg,vPosImg;
+
+ XuiElementGetPosition(m_hPointerImg,&vPosImg);
+ XuiElementGetPosition(m_hPointerText,&vPosText);
+ XuiElementGetPosition(m_hPointerTextBkg,&vPosTextBkg);
+
+ // Set the new height
+ XuiElementSetBounds(m_hPointerTextBkg,xuiRect.right+4.0f+4.0f+4.0f,xuiRect.bottom+4.0f+4.0f); // edge graphics are 8 pixels, with 4 for the border, extra 4 for the background is fudge
+ XuiElementSetBounds(m_hPointerText,xuiRect.right+4.0f+4.0f,xuiRect.bottom+4.0f+4.0f); // edge graphics are 8 pixels, text is centred
+
+ // position the text and panel relative to the pointer image
+ vPosTextBkg.x=vPosImg.x+fImgWidth*0.6f;
+ vPosText.x=vPosTextBkg.x + 4;
+ vPosTextBkg.y=vPosImg.y-(xuiRect.bottom+4.0f+4.0f)+fImgWidth*0.4f;
+ vPosText.y=vPosTextBkg.y + 4;
+
+ XuiElementSetPosition(m_hPointerText,&vPosText);
+ XuiElementSetPosition(m_hPointerTextBkg,&vPosTextBkg);
+
+ XuiElementSetShow(m_hPointerTextBkg,TRUE);
+ XuiElementSetShow(m_hPointerText,TRUE);
+}
+
+void CXuiSceneAbstractContainer::adjustPointerForSafeZone()
+{
+ D3DXVECTOR2 baseSceneOrigin;
+ float baseWidth, baseHeight;
+ if(CXuiSceneBase::GetBaseSceneSafeZone( m_iPad, baseSceneOrigin, baseWidth, baseHeight))
+ {
+ D3DXMATRIX pointerBackgroundMatrix;
+ XuiElementGetFullXForm( m_hPointerTextBkg, &pointerBackgroundMatrix);
+
+ float width, height;
+ XuiElementGetBounds( m_hPointerTextBkg, &width, &height );
+
+ if( ( (pointerBackgroundMatrix._41 / pointerBackgroundMatrix._11) + width) > (baseSceneOrigin.x + baseWidth) )
+ {
+ //app.DebugPrintf("Pointer is outside the safe zone for this base scene\n");
+
+ // get the size of the button, and apply the change in size due to the text to the whole button
+ float fImgWidth,fImgHeight;
+ XuiElementGetBounds(m_hPointerImg,&fImgWidth, &fImgHeight);
+ // 4J-PB - changing to calculate values
+ D3DXVECTOR3 vPosText, vPosTextBkg,vPosImg;
+
+ XuiElementGetPosition(m_hPointerImg,&vPosImg);
+ XuiElementGetPosition(m_hPointerText,&vPosText);
+ XuiElementGetPosition(m_hPointerTextBkg,&vPosTextBkg);
+
+ // position the text and panel relative to the pointer image
+ vPosTextBkg.x= (vPosImg.x+fImgWidth*0.4f) - width;
+ vPosText.x=vPosTextBkg.x + 4;
+
+ XuiElementSetPosition(m_hPointerText,&vPosText);
+ XuiElementSetPosition(m_hPointerTextBkg,&vPosTextBkg);
+ }
+ }
+} \ No newline at end of file