mirror of
https://github.com/LCEMP/LCEMP.git
synced 2026-04-23 15:33:58 +00:00
wired up keyboard and mouse input for menu navigation, inventory cursor, crafting, and general UI interaction. added WASD movement, mouse look, left ctrl sprint, left shift sneak, and all the keybinds for gameplay. also fixed the sound engine crashing when it cant find a sound asset, and set up the x64 build with proper post-build steps for dlls and redist
1683 lines
46 KiB
C++
1683 lines
46 KiB
C++
#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 <pad.h>
|
|
#endif
|
|
|
|
#ifdef _WINDOWS64
|
|
#include "..\..\KeyboardMouseInput.h"
|
|
#include "UI.h"
|
|
|
|
SavedInventoryCursorPos g_savedInventoryCursorPos = { 0.0f, 0.0f, false };
|
|
#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<XUSER_MAX_COUNT;i++)
|
|
// {
|
|
// m_bFirstTouchStored[i]=false;
|
|
// }
|
|
|
|
#ifdef __ORBIS__
|
|
for(int i=0;i<XUSER_MAX_COUNT;i++)
|
|
{
|
|
m_bFirstTouchStored[i]=false;
|
|
}
|
|
#endif
|
|
|
|
PlatformInitialize(iPad,startIndex);
|
|
}
|
|
|
|
int IUIScene_AbstractContainerMenu::GetSectionDimensions( ESceneSection eSection, int* piNumColumns, int* piNumRows )
|
|
{
|
|
if(IsSectionSlotList(eSection))
|
|
{
|
|
*piNumRows = getSectionRows( eSection );
|
|
*piNumColumns = getSectionColumns( eSection );
|
|
}
|
|
else
|
|
{
|
|
*piNumRows = 0;
|
|
*piNumColumns = 0;
|
|
}
|
|
return( ( *piNumRows ) * ( *piNumColumns ) );
|
|
}
|
|
|
|
void IUIScene_AbstractContainerMenu::updateSlotPosition( ESceneSection eSection, ESceneSection newSection, ETapState eTapDirection, int *piTargetX, int *piTargetY, int xOffset )
|
|
{
|
|
// Update the target slot based on the size of the current section
|
|
int columns, rows;
|
|
|
|
// The return value of this function is unused, but the output params are required.
|
|
//int iItemsNum = GetSectionDimensions( newSection, &columns, &rows );
|
|
GetSectionDimensions( newSection, &columns, &rows );
|
|
|
|
if( newSection != eSection )
|
|
{
|
|
// Update Y
|
|
if(eTapDirection == eTapStateUp)
|
|
{
|
|
(*piTargetY) = rows - 1;
|
|
}
|
|
else if(eTapDirection == eTapStateDown)
|
|
{
|
|
(*piTargetY) = 0;
|
|
}
|
|
if( (*piTargetY) < 0 )
|
|
{
|
|
(*piTargetY) = 0;
|
|
}
|
|
|
|
// Update X
|
|
int offsetX = (*piTargetX) - xOffset;
|
|
if( offsetX < 0 )
|
|
{
|
|
*piTargetX = 0;
|
|
}
|
|
else if (offsetX >= 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
|
|
|
|
#ifdef _WINDOWS64
|
|
if (!g_KBMInput.IsMouseGrabbed())
|
|
{
|
|
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;
|
|
}
|
|
|
|
if (deltaX != 0 || deltaY != 0)
|
|
{
|
|
bStickInput = true;
|
|
}
|
|
}
|
|
#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!
|
|
#ifdef _WINDOWS64
|
|
if(g_KBMInput.IsMouseGrabbed() && CanHaveFocus(eSectionUnderPointer))
|
|
#else
|
|
if(CanHaveFocus(eSectionUnderPointer))
|
|
#endif
|
|
{
|
|
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<LocalPlayer> player = Minecraft::GetInstance()->localplayers[getPad()];
|
|
shared_ptr<ItemInstance> carriedItem = nullptr;
|
|
if(player != NULL) carriedItem = player->inventory->getCarried();
|
|
|
|
shared_ptr<ItemInstance> 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<ArmorItem *>(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<wstring> unformattedStrings;
|
|
wstring desc = GetItemDescription( slot, unformattedStrings );
|
|
SetPointerText(desc, unformattedStrings, slot != m_lastPointerLabelSlot);
|
|
m_lastPointerLabelSlot = slot;
|
|
}
|
|
else
|
|
{
|
|
vector<wstring> 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<ItemInstance> 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<ItemInstance> 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<ItemInstance> 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<ItemInstance> 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<ItemInstance> 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<ItemInstance> 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<ItemInstance> 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<ItemInstance> 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<ItemInstance> 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.
|
|
#ifdef _WINDOWS64
|
|
if (g_KBMInput.IsMouseGrabbed())
|
|
{
|
|
#endif
|
|
vPointerPos.x -= m_fPointerImageOffsetX;
|
|
vPointerPos.y -= m_fPointerImageOffsetY;
|
|
#ifdef _WINDOWS64
|
|
}
|
|
#endif
|
|
|
|
// 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<ItemInstance> 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<ItemInstance> itemA, shared_ptr<ItemInstance> 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<ItemInstance> 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<wstring> &unformattedStrings)
|
|
{
|
|
if(slot == NULL) return L"";
|
|
|
|
wstring desc = L"";
|
|
vector<wstring> *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"<br />" );
|
|
}
|
|
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"<font color=\"#%08x\">%ls</font>",colour,thisString.c_str());
|
|
thisString = formatted;
|
|
}
|
|
desc.append( thisString );
|
|
}
|
|
strings->clear();
|
|
delete strings;
|
|
return desc;
|
|
}
|