From b691c43c44ff180d10e7d4a9afc83b98551ff586 Mon Sep 17 00:00:00 2001 From: daoge_cmd <3523206925@qq.com> Date: Sun, 1 Mar 2026 12:16:08 +0800 Subject: Initial commit --- .../Common/UI/IUIScene_AbstractContainerMenu.cpp | 1635 ++++++++++++++++++++ 1 file changed, 1635 insertions(+) create mode 100644 Minecraft.Client/Common/UI/IUIScene_AbstractContainerMenu.cpp (limited to 'Minecraft.Client/Common/UI/IUIScene_AbstractContainerMenu.cpp') diff --git a/Minecraft.Client/Common/UI/IUIScene_AbstractContainerMenu.cpp b/Minecraft.Client/Common/UI/IUIScene_AbstractContainerMenu.cpp new file mode 100644 index 00000000..29ddcf71 --- /dev/null +++ b/Minecraft.Client/Common/UI/IUIScene_AbstractContainerMenu.cpp @@ -0,0 +1,1635 @@ +#include "stdafx.h" + +#include "IUIScene_AbstractContainerMenu.h" + +#include "..\..\..\Minecraft.World\net.minecraft.world.inventory.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.item.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.item.crafting.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.level.tile.entity.h" +#include "..\..\MultiplayerLocalPlayer.h" +#include "..\..\Minecraft.h" + +#ifdef __ORBIS__ +#include +#endif + +IUIScene_AbstractContainerMenu::IUIScene_AbstractContainerMenu() +{ + m_menu = NULL; + m_autoDeleteMenu = false; + m_lastPointerLabelSlot = NULL; + + m_pointerPos.x = 0.0f; + m_pointerPos.y = 0.0f; + +} + +IUIScene_AbstractContainerMenu::~IUIScene_AbstractContainerMenu() +{ + // Delete associated menu if we were requested to on initialisation. Most menus are + // created just before calling CXuiSceneAbstractContainer::Initialize, but the player's inventorymenu + // is also passed directly and we don't want to go deleting that + if( m_autoDeleteMenu ) delete m_menu; +} + +void IUIScene_AbstractContainerMenu::Initialize(int iPad, AbstractContainerMenu* menu, bool autoDeleteMenu, int startIndex,ESceneSection firstSection,ESceneSection maxSection, bool bNavigateBack) +{ + assert( menu != NULL ); + + m_menu = menu; + m_autoDeleteMenu = autoDeleteMenu; + + Minecraft::GetInstance()->localplayers[iPad]->containerMenu = menu; + + // 4J WESTY - New tool tips to support pointer prototype. + //UpdateTooltips(); + // Default tooltips. + for ( int i = 0; i < eToolTipNumButtons; ++i ) + { + m_aeToolTipSettings[ i ] = eToolTipNone; + } + // 4J-PB - don't set the eToolTipPickupPlace_OLD here - let the timer do it. + /*SetToolTip( eToolTipButtonA, eToolTipPickupPlace_OLD );*/ + SetToolTip( eToolTipButtonB, eToolTipExit ); + SetToolTip( eToolTipButtonA, eToolTipNone ); + SetToolTip( eToolTipButtonX, eToolTipNone ); + SetToolTip( eToolTipButtonY, eToolTipNone ); + + // 4J WESTY : To indicate if pointer has left menu window area. + m_bPointerOutsideMenu = false; + + // 4J Stu - Store the enum range for the current scene + m_eFirstSection = firstSection; + m_eMaxSection = maxSection; + + m_iConsectiveInputTicks = 0; + + m_bNavigateBack = bNavigateBack; + + // Put the pointer over first item in use row to start with. +#ifdef TAP_DETECTION + m_eCurrSection = firstSection; + m_eCurrTapState = eTapStateNoInput; + m_iCurrSlotX = 0; + m_iCurrSlotY = 0; +#endif // TAP_DETECTION + // + // for(int i=0;i= columns) + { + *piTargetX = columns - 1; + } + else + { + *piTargetX = offsetX; + } + } + else + { + // Update X + int offsetX = (*piTargetX) - xOffset; + if( offsetX < 0 ) + { + *piTargetX = columns - 1; + } + else if (offsetX >= columns) + { + *piTargetX = 0; + } + else + { + *piTargetX = offsetX; + } + } +} + +#ifdef TAP_DETECTION +IUIScene_AbstractContainerMenu::ETapState IUIScene_AbstractContainerMenu::GetTapInputType( float fInputX, float fInputY ) +{ + if ( ( fabs( fInputX ) < 0.3f ) && ( fabs( fInputY ) < 0.3f ) ) + { + return eTapStateNoInput; + } + else if ( ( fInputX < -0.3f ) && ( fabs( fInputY ) < 0.3f ) ) + { + return eTapStateLeft; + } + else if ( ( fInputX > 0.3f ) && ( fabs( fInputY ) < 0.3f ) ) + { + return eTapStateRight; + } + else if ( ( fInputY < -0.3f ) && ( fabs( fInputX ) < 0.3f ) ) + { + return eTapStateDown; + } + else if ( ( fInputY > 0.3f ) && ( fabs( fInputX ) < 0.3f ) ) + { + return eTapStateUp; + } + else + { + return eTapNone; + } +} +#endif // TAP_DETECTION + +void IUIScene_AbstractContainerMenu::SetToolTip( EToolTipButton eButton, EToolTipItem eItem ) +{ + if ( m_aeToolTipSettings[ eButton ] != eItem ) + { + m_aeToolTipSettings[ eButton ] = eItem; + UpdateTooltips(); + } +} + +void IUIScene_AbstractContainerMenu::UpdateTooltips() +{ + // Table gives us text id for tooltip. + static const DWORD kaToolTipextIds[ eNumToolTips ] = + { + IDS_TOOLTIPS_PICKUPPLACE, //eToolTipPickupPlace_OLD + IDS_TOOLTIPS_EXIT, // eToolTipExit + IDS_TOOLTIPS_PICKUP_GENERIC, // eToolTipPickUpGeneric + IDS_TOOLTIPS_PICKUP_ALL, // eToolTipPickUpAll + IDS_TOOLTIPS_PICKUP_HALF, // eToolTipPickUpHalf + IDS_TOOLTIPS_PLACE_GENERIC, // eToolTipPlaceGeneric + IDS_TOOLTIPS_PLACE_ONE, // eToolTipPlaceOne + IDS_TOOLTIPS_PLACE_ALL, // eToolTipPlaceAll + IDS_TOOLTIPS_DROP_GENERIC, // eToolTipDropGeneric + IDS_TOOLTIPS_DROP_ONE, // eToolTipDropOne + IDS_TOOLTIPS_DROP_ALL, // eToolTipDropAll + IDS_TOOLTIPS_SWAP, // eToolTipSwap + IDS_TOOLTIPS_QUICK_MOVE, // eToolTipQuickMove + IDS_TOOLTIPS_QUICK_MOVE_INGREDIENT, // eToolTipQuickMoveIngredient + IDS_TOOLTIPS_QUICK_MOVE_FUEL, // eToolTipQuickMoveTool + IDS_TOOLTIPS_WHAT_IS_THIS, // eToolTipWhatIsThis + IDS_TOOLTIPS_EQUIP, // eToolTipEquip + IDS_TOOLTIPS_CLEAR_QUICK_SELECT, // eToolTipClearQuickSelect + IDS_TOOLTIPS_QUICK_MOVE_TOOL, // eToolTipQuickMoveTool + IDS_TOOLTIPS_QUICK_MOVE_ARMOR, // eToolTipQuickMoveTool + IDS_TOOLTIPS_QUICK_MOVE_WEAPON, // eToolTipQuickMoveTool + IDS_TOOLTIPS_DYE, // eToolTipDye + IDS_TOOLTIPS_REPAIR, // eToolTipRepair + }; + + BYTE focusUser = getPad(); + + for ( int i = 0; i < eToolTipNumButtons; ++i ) + { + if ( m_aeToolTipSettings[ i ] == eToolTipNone ) + { + ui.ShowTooltip( focusUser, i, FALSE ); + } + else + { + ui.SetTooltipText( focusUser, i, kaToolTipextIds[ m_aeToolTipSettings[ i ] ] ); + ui.ShowTooltip( focusUser, i, TRUE ); + } + } +} + +void IUIScene_AbstractContainerMenu::onMouseTick() +{ + Minecraft *pMinecraft = Minecraft::GetInstance(); + if( pMinecraft->localgameModes[getPad()] != NULL) + { + Tutorial *tutorial = pMinecraft->localgameModes[getPad()]->getTutorial(); + if(tutorial != NULL) + { + if(ui.IsTutorialVisible(getPad()) && !tutorial->isInputAllowed(ACTION_MENU_UP)) + { + return; + } + } + } + + // Offset to display carried item attached to pointer. + // static const float kfCarriedItemOffsetX = -5.0f; + // static const float kfCarriedItemOffsetY = -5.0f; + float fInputDirX=0.0f; + float fInputDirY=0.0f; + + // Get current pointer position. + UIVec2D vPointerPos = m_pointerPos; + + // Offset to image centre. + vPointerPos.x += m_fPointerImageOffsetX; + vPointerPos.y += m_fPointerImageOffsetY; + + // Get stick input. + int iPad = getPad(); + + bool bStickInput = false; + float fInputX = InputManager.GetJoypadStick_LX( iPad, false )*((float)app.GetGameSettings(iPad,eGameSetting_Sensitivity_InMenu)/100.0f); // apply the sensitivity + float fInputY = InputManager.GetJoypadStick_LY( iPad, false )*((float)app.GetGameSettings(iPad,eGameSetting_Sensitivity_InMenu)/100.0f); // apply the sensitivity + +#ifdef __ORBIS__ + // should have sensitivity for the touchpad + //(float)app.GetGameSettings(iPad,eGameSetting_Sensitivity_TouchPadInMenu)/100.0f + + // get the touchpad input and treat it as a map to the window + ScePadTouchData *pTouchPadData=InputManager.GetTouchPadData(iPad); + + // make sure the touchpad button isn't down (it's the pausemenu) + + if((!InputManager.ButtonDown(iPad, ACTION_MENU_TOUCHPAD_PRESS)) && (pTouchPadData->touchNum>0)) + { + if(m_bFirstTouchStored[iPad]==false) + { + m_oldvTouchPos.x=(float)pTouchPadData->touch[0].x; + m_oldvTouchPos.y=(float)pTouchPadData->touch[0].y; + m_oldvPointerPos.x=vPointerPos.x; + m_oldvPointerPos.y=vPointerPos.y; + m_bFirstTouchStored[iPad]=true; + } + + // should take the average of multiple touch points + + float fNewX=(((float)pTouchPadData->touch[0].x)-m_oldvTouchPos.x) * m_fTouchPadMulX; + float fNewY=(((float)pTouchPadData->touch[0].y)-m_oldvTouchPos.y) * m_fTouchPadMulY; + // relative positions - needs a deadzone + + if(fNewX>m_fTouchPadDeadZoneX) + { + vPointerPos.x=m_oldvPointerPos.x+((fNewX-m_fTouchPadDeadZoneX)*((float)app.GetGameSettings(iPad,eGameSetting_Sensitivity_InMenu)/100.0f)); + } + else if(fNewX<-m_fTouchPadDeadZoneX) + { + vPointerPos.x=m_oldvPointerPos.x+((fNewX+m_fTouchPadDeadZoneX)*((float)app.GetGameSettings(iPad,eGameSetting_Sensitivity_InMenu)/100.0f)); + } + + if(fNewY>m_fTouchPadDeadZoneY) + { + vPointerPos.y=m_oldvPointerPos.y+((fNewY-m_fTouchPadDeadZoneY)*((float)app.GetGameSettings(iPad,eGameSetting_Sensitivity_InMenu)/100.0f)); + } + else if(fNewY<-m_fTouchPadDeadZoneY) + { + vPointerPos.y=m_oldvPointerPos.y+((fNewY+m_fTouchPadDeadZoneY)*((float)app.GetGameSettings(iPad,eGameSetting_Sensitivity_InMenu)/100.0f)); + } + + // Clamp to pointer extents. + if ( vPointerPos.x < m_fPointerMinX ) vPointerPos.x = m_fPointerMinX; + else if ( vPointerPos.x > m_fPointerMaxX ) vPointerPos.x = m_fPointerMaxX; + if ( vPointerPos.y < m_fPointerMinY ) vPointerPos.y = m_fPointerMinY; + else if ( vPointerPos.y > m_fPointerMaxY ) vPointerPos.y = m_fPointerMaxY; + + bStickInput = true; + m_eCurrTapState=eTapStateNoInput; + } + else + { + // reset the touch flag + m_bFirstTouchStored[iPad]=false; + +#endif + + + + // If there is any input on sticks, move the pointer. + if ( ( fabs( fInputX ) >= 0.01f ) || ( fabs( fInputY ) >= 0.01f ) ) + { + fInputDirX = ( fInputX > 0.0f ) ? 1.0f : ( fInputX < 0.0f )?-1.0f : 0.0f; + fInputDirY = ( fInputY > 0.0f ) ? 1.0f : ( fInputY < 0.0f )?-1.0f : 0.0f; + +#ifdef TAP_DETECTION + // Check for potential tap input to jump slot. + ETapState eNewTapInput = GetTapInputType( fInputX, fInputY ); + + switch( m_eCurrTapState ) + { + case eTapStateNoInput: + m_eCurrTapState = eNewTapInput; + break; + + case eTapStateUp: + case eTapStateDown: + case eTapStateLeft: + case eTapStateRight: + if ( ( eNewTapInput != m_eCurrTapState ) && ( eNewTapInput != eTapStateNoInput ) ) + { + // Input is no longer suitable for tap. + m_eCurrTapState = eTapNone; + } + break; + + case eTapNone: + /// Nothing to do, input is not a tap. + break; + } +#endif // TAP_DETECTION + + // Square it so we get more precision for small inputs. + fInputX = fInputX * fInputX * fInputDirX * POINTER_SPEED_FACTOR; + fInputY = fInputY * fInputY * fInputDirY * POINTER_SPEED_FACTOR; + //fInputX = fInputX * POINTER_SPEED_FACTOR; + //fInputY = fInputY * POINTER_SPEED_FACTOR; + float fInputScale = 1.0f; + + // Ramp up input from zero when new input is recieved over INPUT_TICKS_FOR_SCALING ticks. This is to try to improve tapping stick to move 1 box. + if ( m_iConsectiveInputTicks < MAX_INPUT_TICKS_FOR_SCALING ) + { + ++m_iConsectiveInputTicks; + fInputScale = ( (float)( m_iConsectiveInputTicks) / (float)(MAX_INPUT_TICKS_FOR_SCALING) ); + } +#ifdef TAP_DETECTION + else if ( m_iConsectiveInputTicks < MAX_INPUT_TICKS_FOR_TAPPING ) + { + ++m_iConsectiveInputTicks; + } + else + { + m_eCurrTapState = eTapNone; + } +#endif + // 4J Stu - The cursor moves too fast in SD mode + // The SD/splitscreen scenes are approximately 0.6 times the size of the fullscreen on + if(!RenderManager.IsHiDef() || app.GetLocalPlayerCount() > 1) fInputScale *= 0.6f; + + fInputX *= fInputScale; + fInputY *= fInputScale; + +#ifdef USE_POINTER_ACCEL + m_fPointerAccelX += fInputX / 50.0f; + m_fPointerAccelY += fInputY / 50.0f; + + if ( fabsf( fInputX ) > fabsf( m_fPointerVelX + m_fPointerAccelX ) ) + { + m_fPointerVelX += m_fPointerAccelX; + } + else + { + m_fPointerAccelX = fInputX - m_fPointerVelX; + m_fPointerVelX = fInputX; + } + + if ( fabsf( fInputY ) > fabsf( m_fPointerVelY + m_fPointerAccelY ) ) + { + m_fPointerVelY += m_fPointerAccelY; + } + else + { + m_fPointerAccelY = fInputY - m_fPointerVelY; + m_fPointerVelY = fInputY; + } + //printf( "IN %.2f VEL %.2f ACC %.2f\n", fInputY, m_fPointerVelY, m_fPointerAccelY ); + + vPointerPos.x += m_fPointerVelX; + vPointerPos.y -= m_fPointerVelY; +#else + // Add input to pointer position. + vPointerPos.x += fInputX; + vPointerPos.y -= fInputY; +#endif + // Clamp to pointer extents. + if ( vPointerPos.x < m_fPointerMinX ) vPointerPos.x = m_fPointerMinX; + else if ( vPointerPos.x > m_fPointerMaxX ) vPointerPos.x = m_fPointerMaxX; + if ( vPointerPos.y < m_fPointerMinY ) vPointerPos.y = m_fPointerMinY; + else if ( vPointerPos.y > m_fPointerMaxY ) vPointerPos.y = m_fPointerMaxY; + + bStickInput = true; + } + else + { + m_iConsectiveInputTicks = 0; +#ifdef USE_POINTER_ACCEL + m_fPointerVelX = 0.0f; + m_fPointerVelY = 0.0f; + m_fPointerAccelX = 0.0f; + m_fPointerAccelY = 0.0f; +#endif + } + +#ifdef __ORBIS__ + } +#endif + + // Determine which slot the pointer is currently over. + ESceneSection eSectionUnderPointer = eSectionNone; + int iNewSlotX = -1; + int iNewSlotY = -1; + int iNewSlotIndex = -1; + bool bPointerIsOverSlot = false; + + // Centre position of item under pointer, use this to snap pointer to item. + D3DXVECTOR3 vSnapPos; + + for ( int iSection = m_eFirstSection; iSection < m_eMaxSection; ++iSection ) + { + // Do not check any further if we have already found the item under the pointer. + if(m_eCurrTapState == eTapStateJump) + { + eSectionUnderPointer = m_eCurrSection; + } + else if ( eSectionUnderPointer == eSectionNone ) + { + ESceneSection eSection = ( ESceneSection )( iSection ); + + // Get position of this section. + UIVec2D sectionPos; + GetPositionOfSection( eSection, &( sectionPos ) ); + + if(!IsSectionSlotList(eSection)) + { + UIVec2D itemPos; + UIVec2D itemSize; + GetItemScreenData( eSection, 0, &( itemPos ), &( itemSize ) ); + + UIVec2D itemMax = itemSize; + itemMax += itemPos; + + if ( ( vPointerPos.x >= sectionPos.x ) && ( vPointerPos.x <= itemMax.x ) && + ( vPointerPos.y >= sectionPos.y ) && ( vPointerPos.y <= itemMax.y ) ) + { + // Pointer is over this control! + eSectionUnderPointer = eSection; + + vSnapPos.x = itemPos.x + ( itemSize.x / 2.0f ); + vSnapPos.y = itemPos.y + ( itemSize.y / 2.0f ); + + // Does this section already have focus. + if ( !doesSectionTreeHaveFocus( eSection ) ) + { + // Give focus to this section. + setSectionFocus(eSection, getPad()); + } + + bPointerIsOverSlot = false; + + // Have we actually changed slot? If so, input cannot be a tap. + if ( ( eSectionUnderPointer != m_eCurrSection ) || ( iNewSlotX != m_iCurrSlotX ) || ( iNewSlotY != m_iCurrSlotY ) ) + { + m_eCurrTapState = eTapNone; + } + + // Store what is currently under the pointer. + m_eCurrSection = eSectionUnderPointer; + } + } + else + { + + // Get dimensions of this section. + int iNumRows; + int iNumColumns; + int iNumItems = GetSectionDimensions( eSection, &( iNumColumns ), &( iNumRows ) ); + + // Check each item to see if pointer is over it. + for ( int iItem = 0; iItem < iNumItems; ++iItem ) + { + UIVec2D itemPos; + UIVec2D itemSize; + GetItemScreenData( eSection, iItem, &( itemPos ), &( itemSize ) ); + + itemPos += sectionPos; + + UIVec2D itemMax = itemSize; + itemMax += itemPos; + + if ( ( vPointerPos.x >= itemPos.x ) && ( vPointerPos.x <= itemMax.x ) && + ( vPointerPos.y >= itemPos.y ) && ( vPointerPos.y <= itemMax.y ) ) + { + // Pointer is over this slot! + eSectionUnderPointer = eSection; + iNewSlotIndex = iItem; + iNewSlotX = iNewSlotIndex % iNumColumns; + iNewSlotY = iNewSlotIndex / iNumColumns; + + vSnapPos.x = itemPos.x + ( itemSize.x / 2.0f ); + vSnapPos.y = itemPos.y + ( itemSize.y / 2.0f ); + + // Does this section already have focus. + if ( !doesSectionTreeHaveFocus( eSection ) ) + { + // Give focus to this section. + setSectionFocus(eSection, getPad()); + } + + // Set the highlight marker. + setSectionSelectedSlot(eSection, iNewSlotX, iNewSlotY ); + + bPointerIsOverSlot = true; + +#ifdef TAP_DETECTION + // Have we actually changed slot? If so, input cannot be a tap. + if ( ( eSectionUnderPointer != m_eCurrSection ) || ( iNewSlotX != m_iCurrSlotX ) || ( iNewSlotY != m_iCurrSlotY ) ) + { + m_eCurrTapState = eTapNone; + } + + // Store what is currently under the pointer. + m_eCurrSection = eSectionUnderPointer; + m_iCurrSlotX = iNewSlotX; + m_iCurrSlotY = iNewSlotY; +#endif // TAP_DETECTION + // No need to check any further slots, the pointer can only ever be over one. + break; + } + } + } + } + } + + // If we are not over any slot, set focus elsewhere. + if ( eSectionUnderPointer == eSectionNone ) + { + setFocusToPointer( getPad() ); +#ifdef TAP_DETECTION + // Input cannot be a tap. + m_eCurrTapState = eTapNone; + + // Store what is currently under the pointer. + m_eCurrSection = eSectionNone; + m_iCurrSlotX = -1; + m_iCurrSlotY = -1; +#endif // TAP_DETECTION + } + else + { + if ( !bStickInput ) + { + // Did we get a tap input? + int iDesiredSlotX = -1; + int iDesiredSlotY = -1; + + switch( m_eCurrTapState ) + { + case eTapStateUp: + iDesiredSlotX = m_iCurrSlotX; + iDesiredSlotY = m_iCurrSlotY - 1; + break; + case eTapStateDown: + iDesiredSlotX = m_iCurrSlotX; + iDesiredSlotY = m_iCurrSlotY + 1; + break; + case eTapStateLeft: + iDesiredSlotX = m_iCurrSlotX - 1; + iDesiredSlotY = m_iCurrSlotY; + break; + case eTapStateRight: + iDesiredSlotX = m_iCurrSlotX + 1; + iDesiredSlotY = m_iCurrSlotY; + break; + case eTapStateJump: + iDesiredSlotX = m_iCurrSlotX; + iDesiredSlotY = m_iCurrSlotY; + break; + } + + int iNumRows; + int iNumColumns; + int iNumItems = GetSectionDimensions( eSectionUnderPointer, &( iNumColumns ), &( iNumRows ) ); + + + if ( (m_eCurrTapState != eTapNone && m_eCurrTapState != eTapStateNoInput) && + ( !IsSectionSlotList(eSectionUnderPointer) || + ( ( iDesiredSlotX < 0 ) || ( iDesiredSlotX >= iNumColumns ) || ( iDesiredSlotY < 0 ) || ( iDesiredSlotY >= iNumRows ) ) + )) + { + + eSectionUnderPointer = GetSectionAndSlotInDirection( eSectionUnderPointer, m_eCurrTapState, &iDesiredSlotX, &iDesiredSlotY ); + + if(!IsSectionSlotList(eSectionUnderPointer)) bPointerIsOverSlot = false; + + // Get the details for the new section + iNumItems = GetSectionDimensions( eSectionUnderPointer, &( iNumColumns ), &( iNumRows ) ); + } + + if ( !IsSectionSlotList(eSectionUnderPointer) || ( ( iDesiredSlotX >= 0 ) && ( iDesiredSlotX < iNumColumns ) && ( iDesiredSlotY >= 0 ) && ( iDesiredSlotY < iNumRows ) ) ) + { + // Desired slot after tap input is valid, so make the jump to this slot. + UIVec2D sectionPos; + GetPositionOfSection( eSectionUnderPointer, &( sectionPos ) ); + + iNewSlotIndex = ( iDesiredSlotY * iNumColumns ) + iDesiredSlotX; + + UIVec2D itemPos; + UIVec2D itemSize; + GetItemScreenData( eSectionUnderPointer, iNewSlotIndex, &( itemPos ), &( itemSize ) ); + + if(IsSectionSlotList(eSectionUnderPointer)) itemPos += sectionPos; + + vSnapPos.x = itemPos.x + ( itemSize.x / 2.0f); + vSnapPos.y = itemPos.y + ( itemSize.y / 2.0f); + + m_eCurrSection = eSectionUnderPointer; + m_iCurrSlotX = iDesiredSlotX; + m_iCurrSlotY = iDesiredSlotY; + } + + m_eCurrTapState = eTapStateNoInput; + + // If there is no stick input, and we are over a slot, then snap pointer to slot centre. + // 4J - TomK - only if this particular component allows so! + if(CanHaveFocus(eSectionUnderPointer)) + { + vPointerPos.x = vSnapPos.x; + vPointerPos.y = vSnapPos.y; + } + } + } + + // Clamp to pointer extents. + if ( vPointerPos.x < m_fPointerMinX ) vPointerPos.x = m_fPointerMinX; + else if ( vPointerPos.x > m_fPointerMaxX ) vPointerPos.x = m_fPointerMaxX; + if ( vPointerPos.y < m_fPointerMinY ) vPointerPos.y = m_fPointerMinY; + else if ( vPointerPos.y > m_fPointerMaxY ) vPointerPos.y = m_fPointerMaxY; + + // Check if the pointer is outside of the panel. + bool bPointerIsOutsidePanel = false; + if ( ( vPointerPos.x < m_fPanelMinX ) || ( vPointerPos.x > m_fPanelMaxX ) || ( vPointerPos.y < m_fPanelMinY ) || ( vPointerPos.y > m_fPanelMaxY ) ) + { + bPointerIsOutsidePanel = true; + } + + // Determine appropriate context sensitive tool tips, based on what is carried on the pointer and what is under the pointer. + + // What are we carrying on pointer. + shared_ptr player = Minecraft::GetInstance()->localplayers[getPad()]; + shared_ptr carriedItem = nullptr; + if(player != NULL) carriedItem = player->inventory->getCarried(); + + shared_ptr slotItem = nullptr; + Slot *slot = NULL; + int slotIndex = 0; + if(bPointerIsOverSlot) + { + slotIndex = iNewSlotIndex + getSectionStartOffset( eSectionUnderPointer ); + slot = m_menu->getSlot(slotIndex); + } + bool bIsItemCarried = carriedItem != NULL; + int iCarriedCount = 0; + bool bCarriedIsSameAsSlot = false; // Indicates if same item is carried on pointer as is in slot under pointer. + if ( bIsItemCarried ) + { + iCarriedCount = carriedItem->count; + } + + // What is in the slot that we are over. + bool bSlotHasItem = false; + bool bMayPlace = false; + bool bCanPlaceOne = false; + bool bCanPlaceAll = false; + bool bCanCombine = false; + bool bCanDye = false; + int iSlotCount = 0; + int iSlotStackSizeRemaining = 0; // How many more items can be stacked on this slot. + if ( bPointerIsOverSlot ) + { + slotItem = slot->getItem(); + bSlotHasItem = slotItem != NULL; + if ( bSlotHasItem ) + { + iSlotCount = slotItem->GetCount(); + + if ( bIsItemCarried ) + { + bCarriedIsSameAsSlot = IsSameItemAs(carriedItem, slotItem); + bCanCombine = m_menu->mayCombine(slot,carriedItem); + bCanDye = bCanCombine && dynamic_cast(slot->getItem()->getItem()); + + if ( bCarriedIsSameAsSlot ) + { + iSlotStackSizeRemaining = GetEmptyStackSpace( m_menu->getSlot(slotIndex) ); + } + } + } + + if( bIsItemCarried) + { + bMayPlace = slot->mayPlace(carriedItem); + + if ( bSlotHasItem ) iSlotStackSizeRemaining = GetEmptyStackSpace( slot ); + else iSlotStackSizeRemaining = slot->getMaxStackSize(); + + if(bMayPlace && iSlotStackSizeRemaining > 0) bCanPlaceOne = true; + if(bMayPlace && iSlotStackSizeRemaining > 1 && carriedItem->count > 1) bCanPlaceAll = true; + } + } + + if( bPointerIsOverSlot && bSlotHasItem ) + { + vector unformattedStrings; + wstring desc = GetItemDescription( slot, unformattedStrings ); + SetPointerText(desc, unformattedStrings, slot != m_lastPointerLabelSlot); + m_lastPointerLabelSlot = slot; + } + else + { + vector unformattedStrings; + SetPointerText(L"", unformattedStrings, false); + m_lastPointerLabelSlot = NULL; + } + + EToolTipItem buttonA, buttonX, buttonY, buttonRT; + buttonA = buttonX = buttonY = buttonRT = eToolTipNone; + if ( bPointerIsOverSlot ) + { + SetPointerOutsideMenu( false ); + if ( bIsItemCarried ) + { + if ( bSlotHasItem ) + { + // Item in hand and item in slot ... is item in slot the same as in out hand? If so, can we stack on to it? + if ( bCarriedIsSameAsSlot ) + { + // Can we stack more into this slot? + if ( iSlotStackSizeRemaining == 0 ) + { + // Cannot stack any more. + buttonRT = eToolTipWhatIsThis; + } + else if ( iSlotStackSizeRemaining == 1 ) + { + // Can only put 1 more on the stack. + buttonA = eToolTipPlaceGeneric; + buttonRT = eToolTipWhatIsThis; + } + else // can put 1 or all. + { + if(bCanPlaceAll) + { + // Multiple items in hand. + buttonA = eToolTipPlaceAll; + buttonX = eToolTipPlaceOne; + } + else if(bCanPlaceOne) + { + if(iCarriedCount > 1) buttonA = eToolTipPlaceOne; + else buttonA = eToolTipPlaceGeneric; + } + buttonRT = eToolTipWhatIsThis; + } + } + else // items are different, click here will swap them. + { + + if(bMayPlace) buttonA = eToolTipSwap; + buttonRT = eToolTipWhatIsThis; + } + if(bCanDye) + { + buttonX = eToolTipDye; + } + else if(bCanCombine) + { + buttonX = eToolTipRepair; + } + } + else // slot empty. + { + // Item in hand, slot is empty. + if ( iCarriedCount == 1 ) + { + // Only one item in hand. + buttonA = eToolTipPlaceGeneric; + } + else + { + if(bCanPlaceAll) + { + // Multiple items in hand. + buttonA = eToolTipPlaceAll; + buttonX = eToolTipPlaceOne; + } + else if(bCanPlaceOne) + { + buttonA = eToolTipPlaceOne; + } + } + } + } + else // no object in hand + { + if ( bSlotHasItem ) + { + if ( iSlotCount == 1 ) + { + buttonA = eToolTipPickUpGeneric; + buttonRT = eToolTipWhatIsThis; + } + else + { + // Multiple items in slot. + buttonA = eToolTipPickUpAll; + buttonX = eToolTipPickUpHalf; + buttonRT = eToolTipWhatIsThis; + } + } + else + { + // Nothing in slot and nothing in hand. + } + } + + if ( bSlotHasItem ) + { + // Item in slot + + // 4J-PB - show tooltips for quick use of armour + + if((eSectionUnderPointer==eSectionInventoryUsing)||(eSectionUnderPointer==eSectionInventoryInventory)) + { + shared_ptr item = getSlotItem(eSectionUnderPointer, iNewSlotIndex); + ArmorRecipes::_eArmorType eArmourType=ArmorRecipes::GetArmorType(item->id); + + if(eArmourType==ArmorRecipes::eArmorType_None) + { + buttonY = eToolTipQuickMove; + } + else + { + // check that the slot required is empty + switch(eArmourType) + { + case ArmorRecipes::eArmorType_Helmet: + if(isSlotEmpty(eSectionInventoryArmor,0)) + { + buttonY = eToolTipEquip; + } + else + { + buttonY = eToolTipQuickMove; + } + break; + case ArmorRecipes::eArmorType_Chestplate: + if(isSlotEmpty(eSectionInventoryArmor,1)) + { + buttonY = eToolTipEquip; + } + else + { + buttonY = eToolTipQuickMove; + } + break; + case ArmorRecipes::eArmorType_Leggings: + if(isSlotEmpty(eSectionInventoryArmor,2)) + { + buttonY = eToolTipEquip; + } + else + { + buttonY = eToolTipQuickMove; + } + break; + case ArmorRecipes::eArmorType_Boots: + if(isSlotEmpty(eSectionInventoryArmor,3)) + { + buttonY = eToolTipEquip; + } + else + { + buttonY = eToolTipQuickMove; + } + break; + default: + buttonY = eToolTipQuickMove; + break; + } + + } + } + // 4J-PB - show tooltips for quick use of fuel or ingredient + else if((eSectionUnderPointer==eSectionFurnaceUsing)||(eSectionUnderPointer==eSectionFurnaceInventory)) + { + // Get the info on this item. + shared_ptr item = getSlotItem(eSectionUnderPointer, iNewSlotIndex); + bool bValidFuel = FurnaceTileEntity::isFuel(item); + bool bValidIngredient = FurnaceRecipes::getInstance()->getResult(item->getItem()->id) != NULL; + + if(bValidIngredient) + { + // is there already something in the ingredient slot? + if(!isSlotEmpty(eSectionFurnaceIngredient,0)) + { + // is it the same as this item + shared_ptr IngredientItem = getSlotItem(eSectionFurnaceIngredient,0); + if(IngredientItem->id == item->id) + { + buttonY = eToolTipQuickMoveIngredient; + } + else + { + if(FurnaceRecipes::getInstance()->getResult(item->id)==NULL) + { + buttonY = eToolTipQuickMove; + } + else + { + buttonY = eToolTipQuickMoveIngredient; + } + } + } + else + { + // ingredient slot empty + buttonY = eToolTipQuickMoveIngredient; + } + } + else if(bValidFuel) + { + // Is there already something in the fuel slot? + if(!isSlotEmpty(eSectionFurnaceFuel,0)) + { + // is it the same as this item + shared_ptr fuelItem = getSlotItem(eSectionFurnaceFuel,0); + if(fuelItem->id == item->id) + { + buttonY = eToolTipQuickMoveFuel; + } + else if(bValidIngredient) + { + // check if the ingredient slot is empty, or the same as this + if(!isSlotEmpty(eSectionFurnaceIngredient,0)) + { + // is it the same as this item + shared_ptr IngredientItem = getSlotItem(eSectionFurnaceIngredient,0); + if(IngredientItem->id == item->id) + { + buttonY = eToolTipQuickMoveIngredient; + } + else + { + if(FurnaceRecipes::getInstance()->getResult(item->id)==NULL) + { + buttonY = eToolTipQuickMove; + } + else + { + buttonY = eToolTipQuickMoveIngredient; + } + } + } + else + { + // ingredient slot empty + buttonY = eToolTipQuickMoveIngredient; + } + } + else + { + buttonY = eToolTipQuickMove; + } + } + else + { + buttonY = eToolTipQuickMoveFuel; + } + } + else + { + buttonY = eToolTipQuickMove; + } + } + // 4J-PB - show tooltips for quick use of ingredients in brewing + else if((eSectionUnderPointer==eSectionBrewingUsing)||(eSectionUnderPointer==eSectionBrewingInventory)) + { + // Get the info on this item. + shared_ptr item = getSlotItem(eSectionUnderPointer, iNewSlotIndex); + int iId=item->id; + + // valid ingredient? + bool bValidIngredient=false; + //bool bValidIngredientBottom=false; + + if(Item::items[iId]->hasPotionBrewingFormula() || (iId == Item::netherStalkSeeds_Id)) + { + bValidIngredient=true; + } + + if(bValidIngredient) + { + // is there already something in the ingredient slot? + if(!isSlotEmpty(eSectionBrewingIngredient,0)) + { + // is it the same as this item + shared_ptr IngredientItem = getSlotItem(eSectionBrewingIngredient,0); + if(IngredientItem->id == item->id) + { + buttonY = eToolTipQuickMoveIngredient; + } + else + { + buttonY=eToolTipQuickMove; + } + } + else + { + // ingredient slot empty + buttonY = eToolTipQuickMoveIngredient; + } + } + else + { + // valid potion? Glass bottle with water in it is a 'potion' too. + if(iId==Item::potion_Id) + { + // space available? + if(isSlotEmpty(eSectionBrewingBottle1,0) || + isSlotEmpty(eSectionBrewingBottle2,0) || + isSlotEmpty(eSectionBrewingBottle3,0)) + { + buttonY = eToolTipQuickMoveIngredient; + } + else + { + buttonY=eToolTipNone; + } + } + else + { + buttonY=eToolTipQuickMove; + } + } + } + else if((eSectionUnderPointer==eSectionEnchantUsing)||(eSectionUnderPointer==eSectionEnchantInventory)) + { + // Get the info on this item. + shared_ptr item = getSlotItem(eSectionUnderPointer, iNewSlotIndex); + int iId=item->id; + + // valid enchantable tool? + if(Item::items[iId]->isEnchantable(item)) + { + // is there already something in the ingredient slot? + if(isSlotEmpty(eSectionEnchantSlot,0)) + { + // tool slot empty + switch(iId) + { + case Item::bow_Id: + case Item::sword_wood_Id: + case Item::sword_stone_Id: + case Item::sword_iron_Id: + case Item::sword_diamond_Id: + buttonY=eToolTipQuickMoveWeapon; + break; + + case Item::helmet_cloth_Id: + case Item::chestplate_cloth_Id: + case Item::leggings_cloth_Id: + case Item::boots_cloth_Id: + + case Item::helmet_chain_Id: + case Item::chestplate_chain_Id: + case Item::leggings_chain_Id: + case Item::boots_chain_Id: + + case Item::helmet_iron_Id: + case Item::chestplate_iron_Id: + case Item::leggings_iron_Id: + case Item::boots_iron_Id: + + case Item::helmet_diamond_Id: + case Item::chestplate_diamond_Id: + case Item::leggings_diamond_Id: + case Item::boots_diamond_Id: + + case Item::helmet_gold_Id: + case Item::chestplate_gold_Id: + case Item::leggings_gold_Id: + case Item::boots_gold_Id: + buttonY=eToolTipQuickMoveArmor; + + break; + case Item::book_Id: + buttonY = eToolTipQuickMove; + break; + default: + buttonY=eToolTipQuickMoveTool; + break; + } + } + else + { + buttonY = eToolTipQuickMove; + } + } + else + { + buttonY=eToolTipQuickMove; + } + } + else + { + buttonY = eToolTipQuickMove; + } + } + } + + if ( bPointerIsOutsidePanel ) + { + SetPointerOutsideMenu( true ); + // Outside window, we dropping items. + if ( bIsItemCarried ) + { + //int iCount = m_pointerControl->GetObjectCount( m_pointerControl->m_hObj ); + if ( iCarriedCount > 1 ) + { + buttonA = eToolTipDropAll; + buttonX = eToolTipDropOne; + } + else + { + buttonA = eToolTipDropGeneric; + } + } + } + else // pointer is just over dead space ... can't really do anything. + { + SetPointerOutsideMenu( false ); + } + + shared_ptr item = nullptr; + if(bPointerIsOverSlot && bSlotHasItem) item = getSlotItem(eSectionUnderPointer, iNewSlotIndex); + overrideTooltips(eSectionUnderPointer, item, bIsItemCarried, bSlotHasItem, bCarriedIsSameAsSlot, iSlotStackSizeRemaining, buttonA, buttonX, buttonY, buttonRT); + + SetToolTip( eToolTipButtonA, buttonA ); + SetToolTip( eToolTipButtonX, buttonX ); + SetToolTip( eToolTipButtonY, buttonY ); + SetToolTip( eToolTipButtonRT, buttonRT ); + + + // Offset back to image top left. + vPointerPos.x -= m_fPointerImageOffsetX; + vPointerPos.y -= m_fPointerImageOffsetY; + + // Update pointer position. + // 4J-PB - do not allow sub pixel positions or we get broken lines in box edges + + // problem here when sensitivity is low - we'll be moving a sub pixel size, so it'll clamp, and we'll never move. In that case, move 1 pixel + if(fInputDirX!=0.0f) + { + if(fInputDirX==1.0f) + { + vPointerPos.x+=0.999999f; + } + else + { + vPointerPos.x-=0.999999f; + } + } + + if(fInputDirY!=0.0f) + { + if(fInputDirY==1.0f) + { + vPointerPos.y+=0.999999f; + } + else + { + vPointerPos.y-=0.999999f; + } + } + + vPointerPos.x = floor(vPointerPos.x); + vPointerPos.x += ( (int)vPointerPos.x%2); + vPointerPos.y = floor(vPointerPos.y); + vPointerPos.y += ( (int)vPointerPos.y%2); + m_pointerPos = vPointerPos; + + adjustPointerForSafeZone(); +} + +bool IUIScene_AbstractContainerMenu::handleKeyDown(int iPad, int iAction, bool bRepeat) +{ + bool bHandled = false; + + Minecraft *pMinecraft = Minecraft::GetInstance(); + if( pMinecraft->localgameModes[getPad()] != NULL ) + { + Tutorial *tutorial = pMinecraft->localgameModes[getPad()]->getTutorial(); + if(tutorial != NULL) + { + tutorial->handleUIInput(iAction); + if(ui.IsTutorialVisible(getPad()) && !tutorial->isInputAllowed(iAction)) + { + return S_OK; + } + } + } + +#ifdef _XBOX + ui.AnimateKeyPress(iPad, iAction); +#else + ui.AnimateKeyPress(iPad, iAction, bRepeat, true, false); +#endif + + int buttonNum=0; // 0 = LeftMouse, 1 = RightMouse + BOOL quickKeyHeld=FALSE; // Represents shift key on PC + + BOOL validKeyPress = FALSE; + //BOOL itemEditorKeyPress = FALSE; + + // Ignore input from other players + //if(pMinecraft->player->GetXboxPad()!=pInputData->UserIndex) return S_OK; + + switch(iAction) + { +#ifdef _DEBUG_MENUS_ENABLED +#if TO_BE_IMPLEMENTED + case VK_PAD_RTHUMB_PRESS: + itemEditorKeyPress = TRUE; + break; +#endif +#endif + case ACTION_MENU_A: +#ifdef __ORBIS__ + case ACTION_MENU_TOUCHPAD_PRESS: +#endif + if(!bRepeat) + { + validKeyPress = TRUE; + + // Standard left click + buttonNum = 0; + quickKeyHeld = FALSE; + ui.PlayUISFX(eSFX_Press); + } + break; + case ACTION_MENU_X: + if(!bRepeat) + { + validKeyPress = TRUE; + + // Standard right click + buttonNum = 1; + quickKeyHeld = FALSE; + ui.PlayUISFX(eSFX_Press); + } + break; + case ACTION_MENU_Y: + if(!bRepeat) + { + //bool bIsItemCarried = !m_pointerControl->isEmpty( m_pointerControl->m_hObj ); + + // 4J Stu - TU8: Remove this fix, and fix the tooltip display instead as customers liked the feature + + // Fix for #58583 - TU6: Content: UI: The Quick Move button prompt disappears even though it still works + // No quick move tooltip is shown if something is carried, so disable the action as well + //if(!bIsItemCarried) + { + validKeyPress = TRUE; + + // Shift and left click + buttonNum = 0; + quickKeyHeld = TRUE; + ui.PlayUISFX(eSFX_Press); + } + } + break; + // 4J Stu - Also enable start to exit the scene. This key is also not constrained by the tutorials. + case ACTION_MENU_PAUSEMENU: + case ACTION_MENU_B: + { + + ui.SetTooltips(iPad, -1); + + // 4J Stu - Fix for #11302 - TCR 001: Network Connectivity: Host crashed after being killed by the client while accessing a chest during burst packet loss. + // We need to make sure that we call closeContainer() anytime this menu is closed, even if it is forced to close by some other reason (like the player dying) + // Therefore I have moved this call to the OnDestroy() method to make sure that it always happens. + //Minecraft::GetInstance()->localplayers[pInputData->UserIndex]->closeContainer(); + + // Return to the game. We should really callback to the app here as well + // to let it know that we have closed the ui incase we need to do things when that happens + + if(m_bNavigateBack) + { + ui.NavigateBack(iPad); + } + else + { + ui.CloseUIScenes(iPad); + } + + bHandled = true; + return S_OK; + } + break; + case ACTION_MENU_LEFT: + { + //ui.PlayUISFX(eSFX_Focus); + m_eCurrTapState = eTapStateLeft; + } + break; + case ACTION_MENU_RIGHT: + { + //ui.PlayUISFX(eSFX_Focus); + m_eCurrTapState = eTapStateRight; + } + break; + case ACTION_MENU_UP: + { + //ui.PlayUISFX(eSFX_Focus); + m_eCurrTapState = eTapStateUp; + } + break; + case ACTION_MENU_DOWN: + { + //ui.PlayUISFX(eSFX_Focus); + m_eCurrTapState = eTapStateDown; + } + break; + case ACTION_MENU_PAGEUP: + { + // 4J Stu - Do nothing except stop this being passed anywhere else + bHandled = true; + } + break; +#ifdef __PSVITA__ + //CD - Vita uses select for What's this - key 40 + case MINECRAFT_ACTION_GAME_INFO: +#else + case ACTION_MENU_PAGEDOWN: +#endif + + { + if( IsSectionSlotList( m_eCurrSection ) ) + { + int currentIndex = getCurrentIndex( m_eCurrSection ) - getSectionStartOffset(m_eCurrSection); + + bool bSlotHasItem = !isSlotEmpty(m_eCurrSection, currentIndex); + if ( bSlotHasItem ) + { + shared_ptr item = getSlotItem(m_eCurrSection, currentIndex); + if( Minecraft::GetInstance()->localgameModes[iPad] != NULL ) + { + Tutorial::PopupMessageDetails *message = new Tutorial::PopupMessageDetails; + message->m_messageId = item->getUseDescriptionId(); + + if(Item::items[item->id] != NULL) message->m_titleString = Item::items[item->id]->getHoverName(item); + message->m_titleId = item->getDescriptionId(); + + message->m_icon = item->id; + message->m_iAuxVal = item->getAuxValue(); + message->m_forceDisplay = true; + + TutorialMode *gameMode = (TutorialMode *)Minecraft::GetInstance()->localgameModes[iPad]; + gameMode->getTutorial()->setMessage(NULL, message); + ui.PlayUISFX(eSFX_Press); + } + } + } + bHandled = TRUE; + } + break; + }; + + if( validKeyPress == TRUE ) + { + if(handleValidKeyPress(iPad,buttonNum,quickKeyHeld)) + { + // Used to allow overriding certain keypresses, so do nothing here + } + else + { + if( IsSectionSlotList( m_eCurrSection ) ) + { + handleSlotListClicked(m_eCurrSection,buttonNum,quickKeyHeld); + } + else + { + // TODO Clicked something else, like for example the craft result. Do something here + + // 4J WESTY : For pointer system we can legally drop items outside of the window panel here, or may press button while + // pointer is over empty panel space. + if ( m_bPointerOutsideMenu ) + { + handleOutsideClicked(iPad, buttonNum, quickKeyHeld); + } + else // + { + // over empty space or something else??? + handleOtherClicked(iPad,m_eCurrSection,buttonNum,quickKeyHeld?true:false); + //assert( FALSE ); + } + } + } + bHandled = true; + } +#ifdef _DEBUG_MENUS_ENABLED +#if TO_BE_IMPLEMENTED + else if(itemEditorKeyPress == TRUE) + { + HXUIOBJ hFocusObject = GetFocus(pInputData->UserIndex); + HXUIOBJ hFocusObjectParent; + XuiElementGetParent( hFocusObject, &hFocusObjectParent ); + + HXUICLASS hClassCXuiCtrlSlotList; + + // TODO Define values for these + hClassCXuiCtrlSlotList = XuiFindClass( L"CXuiCtrlSlotList" ); + + // If the press comes from a SlotList, cast it up then send a clicked call to it's menu + if( XuiIsInstanceOf( hFocusObjectParent, hClassCXuiCtrlSlotList ) ) + { + CXuiCtrlSlotList* slotList; + VOID *pObj; + XuiObjectFromHandle( hFocusObjectParent, &pObj ); + slotList = (CXuiCtrlSlotList *)pObj; + + int currentIndex = slotList->GetCurSel(); + + CXuiCtrlSlotItemListItem* pCXuiCtrlSlotItem; + slotList->GetCXuiCtrlSlotItem( currentIndex, &( pCXuiCtrlSlotItem ) ); + + //Minecraft *pMinecraft = Minecraft::GetInstance(); + + CScene_DebugItemEditor::ItemEditorInput *initData = new CScene_DebugItemEditor::ItemEditorInput(); + initData->iPad = m_iPad; + initData->slot = pCXuiCtrlSlotItem->getSlot( pCXuiCtrlSlotItem->m_hObj ); + initData->menu = m_menu; + + // Add timer to poll controller stick input at 60Hz + HRESULT timerResult = KillTimer( POINTER_INPUT_TIMER_ID ); + assert( timerResult == S_OK ); + + app.NavigateToScene(m_iPad,eUIScene_DebugItemEditor,(void *)initData,false,TRUE); + } + } +#endif +#endif + else + { + handleAdditionalKeyPress(iAction); + } + + UpdateTooltips(); + + return bHandled; +} + +bool IUIScene_AbstractContainerMenu::handleValidKeyPress(int iUserIndex, int buttonNum, BOOL quickKeyHeld) +{ + return false; +} + +void IUIScene_AbstractContainerMenu::handleOutsideClicked(int iPad, int buttonNum, BOOL quickKeyHeld) +{ + // Drop items. + + //pMinecraft->localgameModes[m_iPad]->handleInventoryMouseClick(menu->containerId, AbstractContainerMenu::CLICKED_OUTSIDE, buttonNum, quickKeyHeld?true:false, pMinecraft->localplayers[m_iPad] ); + slotClicked(AbstractContainerMenu::CLICKED_OUTSIDE, buttonNum, quickKeyHeld?true:false); +} + +void IUIScene_AbstractContainerMenu::handleOtherClicked(int iPad, ESceneSection eSection, int buttonNum, bool quickKey) +{ + // Do nothing +} + +void IUIScene_AbstractContainerMenu::handleAdditionalKeyPress(int iAction) +{ + // Do nothing +} + +void IUIScene_AbstractContainerMenu::handleSlotListClicked(ESceneSection eSection, int buttonNum, BOOL quickKeyHeld) +{ + int currentIndex = getCurrentIndex(eSection); + + //pMinecraft->localgameModes[m_iPad]->handleInventoryMouseClick(menu->containerId, currentIndex, buttonNum, quickKeyHeld?true:false, pMinecraft->localplayers[m_iPad] ); + slotClicked(currentIndex, buttonNum, quickKeyHeld?true:false); + + handleSectionClick(eSection); +} + +void IUIScene_AbstractContainerMenu::slotClicked(int slotId, int buttonNum, bool quickKey) +{ + // 4J Stu - Removed this line as unused + //if (slot != NULL) slotId = slot->index; + + Minecraft *pMinecraft = Minecraft::GetInstance(); + pMinecraft->localgameModes[getPad()]->handleInventoryMouseClick(m_menu->containerId, slotId, buttonNum, quickKey, pMinecraft->localplayers[getPad()] ); +} + +int IUIScene_AbstractContainerMenu::getCurrentIndex(ESceneSection eSection) +{ + int rows, columns; + GetSectionDimensions( eSection, &columns, &rows ); + int currentIndex = (m_iCurrSlotY * columns) + m_iCurrSlotX; + + return currentIndex + getSectionStartOffset(eSection); +} + +bool IUIScene_AbstractContainerMenu::IsSameItemAs(shared_ptr itemA, shared_ptr itemB) +{ + if(itemA == NULL || itemB == NULL) return false; + + bool bStackedByData = itemA->isStackedByData(); + return ( ( itemA->id == itemB->id ) && ( (bStackedByData && itemA->getAuxValue() == itemB->getAuxValue()) || !bStackedByData ) ); +} + +int IUIScene_AbstractContainerMenu::GetEmptyStackSpace(Slot *slot) +{ + int iResult = 0; + + if(slot != NULL && slot->hasItem()) + { + shared_ptr item = slot->getItem(); + if ( item->isStackable() ) + { + int iCount = item->GetCount(); + int iMaxStackSize = min(item->getMaxStackSize(), slot->getMaxStackSize() ); + + iResult = iMaxStackSize - iCount; + + if(iResult < 0 ) iResult = 0; + } + } + + return iResult; +} + +wstring IUIScene_AbstractContainerMenu::GetItemDescription(Slot *slot, vector &unformattedStrings) +{ + if(slot == NULL) return L""; + + wstring desc = L""; + vector *strings = slot->getItem()->getHoverText(nullptr, false, unformattedStrings); + bool firstLine = true; + for(AUTO_VAR(it, strings->begin()); it != strings->end(); ++it) + { + wstring thisString = *it; + if(!firstLine) + { + desc.append( L"
" ); + } + else + { + firstLine = false; + wchar_t formatted[256]; + eMinecraftColour rarityColour = slot->getItem()->getRarity()->color; + int colour = app.GetHTMLColour(rarityColour); + + if(slot->getItem()->hasCustomHoverName()) + { + colour = app.GetHTMLColour(eTextColor_RenamedItemTitle); + } + + swprintf(formatted, 256, L"%ls",colour,thisString.c_str()); + thisString = formatted; + } + desc.append( thisString ); + } + strings->clear(); + delete strings; + return desc; +} -- cgit v1.2.3