diff options
| author | daoge_cmd <3523206925@qq.com> | 2026-03-01 12:16:08 +0800 |
|---|---|---|
| committer | daoge_cmd <3523206925@qq.com> | 2026-03-01 12:16:08 +0800 |
| commit | b691c43c44ff180d10e7d4a9afc83b98551ff586 (patch) | |
| tree | 3e9849222cbc6ba49f2f1fc6e5fe7179632c7390 /Minecraft.Client/Common/UI | |
| parent | def8cb415354ac390b7e89052a50605285f1aca9 (diff) | |
Initial commit
Diffstat (limited to 'Minecraft.Client/Common/UI')
226 files changed, 54496 insertions, 0 deletions
diff --git a/Minecraft.Client/Common/UI/IUIController.h b/Minecraft.Client/Common/UI/IUIController.h new file mode 100644 index 00000000..319185d8 --- /dev/null +++ b/Minecraft.Client/Common/UI/IUIController.h @@ -0,0 +1,77 @@ +#pragma once + +#include "UIEnums.h" + +// 4J Stu - An interface class that defines all the public functions that we use within the game code. This allows us to build the Xbox 360 version without +// using the base UIController class used by the other platforms +class IUIController +{ +public: + virtual void tick() = 0; + virtual void render() = 0; + virtual void StartReloadSkinThread() = 0; + virtual bool IsReloadingSkin() = 0; + virtual void CleanUpSkinReload() = 0; + virtual bool NavigateToScene(int iPad, EUIScene scene, void *initData = NULL, EUILayer layer = eUILayer_Scene, EUIGroup group = eUIGroup_PAD) = 0; + virtual bool NavigateBack(int iPad, bool forceUsePad = false, EUIScene eScene = eUIScene_COUNT, EUILayer eLayer = eUILayer_COUNT) = 0; + virtual void CloseUIScenes(int iPad, bool forceIPad = false) = 0; + virtual void CloseAllPlayersScenes() = 0; + + virtual bool IsPauseMenuDisplayed(int iPad) = 0; + virtual bool IsContainerMenuDisplayed(int iPad) = 0; + virtual bool IsIgnorePlayerJoinMenuDisplayed(int iPad) = 0; + virtual bool IsIgnoreAutosaveMenuDisplayed(int iPad) = 0; + virtual void SetIgnoreAutosaveMenuDisplayed(int iPad, bool displayed) = 0; + virtual bool IsSceneInStack(int iPad, EUIScene eScene) = 0; + virtual bool GetMenuDisplayed(int iPad) = 0; + virtual void CheckMenuDisplayed() = 0; + + virtual void SetTooltipText( unsigned int iPad, unsigned int tooltip, int iTextID ) = 0; + virtual void SetEnableTooltips( unsigned int iPad, BOOL bVal ) = 0; + virtual void ShowTooltip( unsigned int iPad, unsigned int tooltip, bool show ) = 0; + virtual void SetTooltips( unsigned int iPad, int iA, int iB=-1, int iX=-1, int iY=-1 , int iLT=-1, int iRT=-1, int iLB=-1, int iRB=-1, int iLS=-1, bool forceUpdate = false) = 0; + virtual void EnableTooltip( unsigned int iPad, unsigned int tooltip, bool enable ) = 0; + virtual void RefreshTooltips(unsigned int iPad) = 0; + + virtual void PlayUISFX(ESoundEffect eSound) = 0; + + virtual void ShowUIDebugConsole(bool show) {} + virtual void ShowUIDebugMarketingGuide(bool show) {} + + virtual void DisplayGamertag(unsigned int iPad, bool show) = 0; + virtual void SetSelectedItem(unsigned int iPad, const wstring &name) = 0; + virtual void UpdateSelectedItemPos(unsigned int iPad) = 0; + + virtual void HandleDLCMountingComplete() = 0; + virtual void HandleDLCInstalled(int iPad) = 0; +#ifdef _XBOX_ONE + virtual void HandleDLCLicenseChange() = 0; +#endif + virtual void HandleTMSDLCFileRetrieved(int iPad) = 0; + virtual void HandleTMSBanFileRetrieved(int iPad) = 0; + virtual void HandleInventoryUpdated(int iPad) = 0; + virtual void HandleGameTick() = 0; + + virtual void SetTutorialDescription(int iPad, TutorialPopupInfo *info) = 0; + virtual void SetTutorialVisible(int iPad, bool visible) = 0; + virtual bool IsTutorialVisible(int iPad) = 0; + + virtual void UpdatePlayerBasePositions() = 0; + virtual void SetEmptyQuadrantLogo(int iSection) = 0; + virtual void HideAllGameUIElements() = 0; + virtual void ShowOtherPlayersBaseScene(unsigned int iPad, bool show) = 0; + + virtual void ShowTrialTimer(bool show) = 0; + virtual void SetTrialTimerLimitSecs(unsigned int uiSeconds) = 0; + virtual void UpdateTrialTimer(unsigned int iPad) = 0; + virtual void ReduceTrialTimerValue() = 0; + + virtual void ShowAutosaveCountdownTimer(bool show) = 0; + virtual void UpdateAutosaveCountdownTimer(unsigned int uiSeconds) = 0; + virtual void ShowSavingMessage(unsigned int iPad, C4JStorage::ESavingMessage eVal) = 0; + + virtual bool PressStartPlaying(unsigned int iPad) = 0; + virtual void ShowPressStart(unsigned int iPad) = 0; + + virtual void SetWinUserIndex(unsigned int iPad) = 0; +}; 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 <pad.h> +#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 + + // 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<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. + 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<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; +} diff --git a/Minecraft.Client/Common/UI/IUIScene_AbstractContainerMenu.h b/Minecraft.Client/Common/UI/IUIScene_AbstractContainerMenu.h new file mode 100644 index 00000000..bdb8bb4c --- /dev/null +++ b/Minecraft.Client/Common/UI/IUIScene_AbstractContainerMenu.h @@ -0,0 +1,223 @@ +#pragma once + +// Uncomment to enable tap input detection to jump 1 slot. Doesn't work particularly well yet, and I feel the system does not need it. +// Would probably be required if we decide to slow down the pointer movement. +// 4J Stu - There was a request to be able to navigate the scenes with the dpad, so I have used much of the TAP_DETECTION +// code as it worked well for that situation. This #define should still stop the same things happening when using the +// stick though when not defined +#define TAP_DETECTION + +// Uncomment to enable acceleration on pointer input. +//#define USE_POINTER_ACCEL + +#define POINTER_INPUT_TIMER_ID (0) // Arbitrary timer ID. +#define POINTER_SPEED_FACTOR (13.0f) // Speed of pointer. +//#define POINTER_PANEL_OVER_REACH (42.0f) // Amount beyond edge of panel which pointer can go over to drop items. - comes from the pointer size in the scene + +#define MAX_INPUT_TICKS_FOR_SCALING (7) +#define MAX_INPUT_TICKS_FOR_TAPPING (15) + +class AbstractContainerMenu; +class Slot; + +class IUIScene_AbstractContainerMenu +{ +protected: + // Sections of this scene containing items selectable by the pointer. + // 4J Stu - Always make the Using section the first one + enum ESceneSection + { + eSectionNone = -1, + eSectionContainerUsing = 0, + eSectionContainerInventory, + eSectionContainerChest, + eSectionContainerMax, + + eSectionFurnaceUsing, + eSectionFurnaceInventory, + eSectionFurnaceIngredient, + eSectionFurnaceFuel, + eSectionFurnaceResult, + eSectionFurnaceMax, + + eSectionInventoryUsing, + eSectionInventoryInventory, + eSectionInventoryArmor, + eSectionInventoryMax, + + eSectionTrapUsing, + eSectionTrapInventory, + eSectionTrapTrap, + eSectionTrapMax, + + eSectionInventoryCreativeUsing, + eSectionInventoryCreativeSelector, +#ifndef _XBOX + eSectionInventoryCreativeTab_0, + eSectionInventoryCreativeTab_1, + eSectionInventoryCreativeTab_2, + eSectionInventoryCreativeTab_3, + eSectionInventoryCreativeTab_4, + eSectionInventoryCreativeTab_5, + eSectionInventoryCreativeTab_6, + eSectionInventoryCreativeTab_7, + eSectionInventoryCreativeSlider, +#endif + eSectionInventoryCreativeMax, + + eSectionEnchantUsing, + eSectionEnchantInventory, + eSectionEnchantSlot, + eSectionEnchantButton1, + eSectionEnchantButton2, + eSectionEnchantButton3, + eSectionEnchantMax, + + eSectionBrewingUsing, + eSectionBrewingInventory, + eSectionBrewingBottle1, + eSectionBrewingBottle2, + eSectionBrewingBottle3, + eSectionBrewingIngredient, + eSectionBrewingMax, + + eSectionAnvilUsing, + eSectionAnvilInventory, + eSectionAnvilItem1, + eSectionAnvilItem2, + eSectionAnvilResult, + eSectionAnvilName, + eSectionAnvilMax, + }; + + AbstractContainerMenu* m_menu; + bool m_autoDeleteMenu; + + eTutorial_State m_previousTutorialState; + + UIVec2D m_pointerPos; + + // Offset from pointer image top left to centre (we use the centre as the actual pointer). + float m_fPointerImageOffsetX; + float m_fPointerImageOffsetY; + + // Min and max extents for the pointer. + float m_fPointerMinX; + float m_fPointerMaxX; + float m_fPointerMinY; + float m_fPointerMaxY; + + // Min and max extents of the panel. + float m_fPanelMinX; + float m_fPanelMaxX; + float m_fPanelMinY; + float m_fPanelMaxY; + + int m_iConsectiveInputTicks; + + // Used for detecting quick "taps" in a direction, should jump cursor to next slot. + enum ETapState + { + eTapStateNoInput = 0, + eTapStateUp, + eTapStateDown, + eTapStateLeft, + eTapStateRight, + eTapStateJump, + eTapNone + }; + + ETapState m_eCurrTapState; + ESceneSection m_eCurrSection; + int m_iCurrSlotX; + int m_iCurrSlotY; + +#ifdef __ORBIS__ + bool m_bFirstTouchStored[XUSER_MAX_COUNT]; // monitor the first position of a touch, so we can use relative distances of movement + UIVec2D m_oldvPointerPos; + UIVec2D m_oldvTouchPos; + // store the multipliers to map the UI window to the touchpad window + float m_fTouchPadMulX; + float m_fTouchPadMulY; + float m_fTouchPadDeadZoneX; // usese the multipliers + float m_fTouchPadDeadZoneY; + + +#endif + + // ENum indexes of the first section for this scene, and 1+the last section + ESceneSection m_eFirstSection, m_eMaxSection; + + // 4J - WESTY - Added for pointer prototype. + // Current tooltip settings. + EToolTipItem m_aeToolTipSettings[ eToolTipNumButtons ]; + + // 4J - WESTY - Added for pointer prototype. + // Indicates if pointer is outside UI window (used to drop items). + bool m_bPointerOutsideMenu; + Slot *m_lastPointerLabelSlot; + + bool m_bSplitscreen; + bool m_bNavigateBack; // should we exit the xuiscenes or just navigate back on exit? + + virtual bool IsSectionSlotList( ESceneSection eSection ) { return eSection != eSectionNone; } + virtual bool CanHaveFocus( ESceneSection eSection ) { return true; } + int GetSectionDimensions( ESceneSection eSection, int* piNumColumns, int* piNumRows ); + virtual int getSectionColumns(ESceneSection eSection) = 0; + virtual int getSectionRows(ESceneSection eSection) = 0; + virtual ESceneSection GetSectionAndSlotInDirection( ESceneSection eSection, ETapState eTapDirection, int *piTargetX, int *piTargetY ) = 0; + virtual void GetPositionOfSection( ESceneSection eSection, UIVec2D* pPosition ) = 0; + virtual void GetItemScreenData( ESceneSection eSection, int iItemIndex, UIVec2D* pPosition, UIVec2D* pSize ) = 0; + void updateSlotPosition( ESceneSection eSection, ESceneSection newSection, ETapState eTapDirection, int *piTargetX, int *piTargetY, int xOffset ); + + #ifdef TAP_DETECTION + ETapState GetTapInputType( float fInputX, float fInputY ); + #endif + + // Current tooltip settings. + void SetToolTip( EToolTipButton eButton, EToolTipItem eItem ); + void UpdateTooltips(); + + // 4J - WESTY - Added for pointer prototype. + void SetPointerOutsideMenu( bool bOutside ) { m_bPointerOutsideMenu = bOutside; } + + void Initialize(int m_iPad, AbstractContainerMenu* menu, bool autoDeleteMenu, int startIndex,ESceneSection firstSection,ESceneSection maxSection, bool bNavigateBack=FALSE); + virtual void PlatformInitialize(int iPad, int startIndex) = 0; + virtual void InitDataAssociations(int iPad, AbstractContainerMenu *menu, int startIndex = 0) = 0; + + void onMouseTick(); + bool handleKeyDown(int iPad, int iAction, bool bRepeat); + virtual bool handleValidKeyPress(int iUserIndex, int buttonNum, BOOL quickKeyHeld); + virtual void handleOutsideClicked(int iPad, int buttonNum, BOOL quickKeyHeld); + virtual void handleOtherClicked(int iPad, ESceneSection eSection, int buttonNum, bool quickKey); + virtual void handleAdditionalKeyPress(int iAction); + virtual void handleSlotListClicked(ESceneSection eSection, int buttonNum, BOOL quickKeyHeld); + virtual void handleSectionClick(ESceneSection eSection) = 0; + void slotClicked(int slotId, int buttonNum, bool quickKey); + int getCurrentIndex(ESceneSection eSection); + virtual int getSectionStartOffset(ESceneSection eSection) = 0; + virtual bool doesSectionTreeHaveFocus(ESceneSection eSection) = 0; + virtual void setSectionFocus(ESceneSection eSection, int iPad) = 0; + virtual void setSectionSelectedSlot(ESceneSection eSection, int x, int y) = 0; + virtual void setFocusToPointer(int iPad) = 0; + virtual void SetPointerText(const wstring &description, vector<wstring> &unformattedStrings, bool newSlot) = 0; + virtual shared_ptr<ItemInstance> getSlotItem(ESceneSection eSection, int iSlot) = 0; + virtual bool isSlotEmpty(ESceneSection eSection, int iSlot) = 0; + virtual void adjustPointerForSafeZone() = 0; + + virtual bool overrideTooltips(ESceneSection sectionUnderPointer, shared_ptr<ItemInstance> itemUnderPointer, bool bIsItemCarried, bool bSlotHasItem, bool bCarriedIsSameAsSlot, int iSlotStackSizeRemaining, + EToolTipItem &buttonA, EToolTipItem &buttonX, EToolTipItem &buttonY, EToolTipItem &buttonRT) { return false; } + +private: + bool IsSameItemAs(shared_ptr<ItemInstance> itemA, shared_ptr<ItemInstance> itemB); + int GetEmptyStackSpace(Slot *slot); + wstring GetItemDescription(Slot *slot, vector<wstring> &unformattedStrings); + +protected: + + IUIScene_AbstractContainerMenu(); + virtual ~IUIScene_AbstractContainerMenu(); + +public: + virtual int getPad() = 0; +}; diff --git a/Minecraft.Client/Common/UI/IUIScene_AnvilMenu.cpp b/Minecraft.Client/Common/UI/IUIScene_AnvilMenu.cpp new file mode 100644 index 00000000..81451c7a --- /dev/null +++ b/Minecraft.Client/Common/UI/IUIScene_AnvilMenu.cpp @@ -0,0 +1,272 @@ +#include "stdafx.h" +#include "IUIScene_AnvilMenu.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.inventory.h" +#include "..\..\..\Minecraft.World\InputOutputStream.h" +#include "..\..\..\Minecraft.World\net.minecraft.network.packet.h" +#include "..\..\Minecraft.h" +#include "..\..\MultiPlayerLocalPlayer.h" +#include "..\..\ClientConnection.h" + +IUIScene_AnvilMenu::IUIScene_AnvilMenu() +{ + m_inventory = nullptr; + m_repairMenu = NULL; + m_itemName = L""; +} + +IUIScene_AbstractContainerMenu::ESceneSection IUIScene_AnvilMenu::GetSectionAndSlotInDirection( ESceneSection eSection, ETapState eTapDirection, int *piTargetX, int *piTargetY ) +{ + ESceneSection newSection = eSection; + int xOffset = 0; + + // Find the new section if there is one + switch( eSection ) + { + case eSectionAnvilItem1: + if(eTapDirection == eTapStateUp) + { + newSection = eSectionAnvilName; + } + else if(eTapDirection == eTapStateDown) + { + newSection = eSectionAnvilInventory; + xOffset = ANVIL_SCENE_ITEM1_SLOT_DOWN_OFFSET; + } + else if(eTapDirection == eTapStateLeft) + { + newSection = eSectionAnvilResult; + } + else if(eTapDirection == eTapStateRight) + { + newSection = eSectionAnvilItem2; + } + break; + case eSectionAnvilItem2: + if(eTapDirection == eTapStateUp) + { + newSection = eSectionAnvilName; + } + else if(eTapDirection == eTapStateDown) + { + newSection = eSectionAnvilInventory; + xOffset = ANVIL_SCENE_ITEM2_SLOT_DOWN_OFFSET; + } + else if(eTapDirection == eTapStateLeft) + { + newSection = eSectionAnvilItem1; + } + else if(eTapDirection == eTapStateRight) + { + newSection = eSectionAnvilResult; + } + break; + case eSectionAnvilResult: + if(eTapDirection == eTapStateUp) + { + newSection = eSectionAnvilName; + } + else if(eTapDirection == eTapStateDown) + { + newSection = eSectionAnvilInventory; + xOffset = ANVIL_SCENE_RESULT_SLOT_DOWN_OFFSET; + } + else if(eTapDirection == eTapStateLeft) + { + newSection = eSectionAnvilItem2; + } + else if(eTapDirection == eTapStateRight) + { + newSection = eSectionAnvilItem1; + } + break; + case eSectionAnvilName: + if(eTapDirection == eTapStateUp) + { + newSection = eSectionAnvilUsing; + xOffset = ANVIL_SCENE_ITEM2_SLOT_UP_OFFSET; + } + else if(eTapDirection == eTapStateDown) + { + newSection = eSectionAnvilItem2; + } + break; + case eSectionAnvilInventory: + if(eTapDirection == eTapStateDown) + { + newSection = eSectionAnvilUsing; + } + else if(eTapDirection == eTapStateUp) + { + if( *piTargetX <= ANVIL_SCENE_ITEM1_SLOT_UP_OFFSET) + { + newSection = eSectionAnvilItem1; + } + else if( *piTargetX <= ANVIL_SCENE_ITEM2_SLOT_UP_OFFSET) + { + newSection = eSectionAnvilItem2; + } + else if( *piTargetX >= ANVIL_SCENE_RESULT_SLOT_UP_OFFSET) + { + newSection = eSectionAnvilResult; + } + } + break; + case eSectionAnvilUsing: + if(eTapDirection == eTapStateUp) + { + newSection = eSectionAnvilInventory; + } + else if(eTapDirection == eTapStateDown) + { + if( *piTargetX <= ANVIL_SCENE_ITEM1_SLOT_UP_OFFSET) + { + newSection = eSectionAnvilItem1; + } + else if( *piTargetX <= ANVIL_SCENE_ITEM2_SLOT_UP_OFFSET) + { + newSection = eSectionAnvilName; + } + else if( *piTargetX >= ANVIL_SCENE_RESULT_SLOT_UP_OFFSET) + { + newSection = eSectionAnvilName; + } + } + break; + default: + assert( false ); + break; + } + + updateSlotPosition(eSection, newSection, eTapDirection, piTargetX, piTargetY, xOffset); + + return newSection; +} + +int IUIScene_AnvilMenu::getSectionStartOffset(ESceneSection eSection) +{ + int offset = 0; + switch( eSection ) + { + case eSectionAnvilItem1: + offset = MerchantMenu::PAYMENT1_SLOT; + break; + case eSectionAnvilItem2: + offset = MerchantMenu::PAYMENT2_SLOT; + break; + case eSectionAnvilResult: + offset = MerchantMenu::RESULT_SLOT; + break; + case eSectionAnvilInventory: + offset = MerchantMenu::INV_SLOT_START; + break; + case eSectionAnvilUsing: + offset = MerchantMenu::USE_ROW_SLOT_START; + break; + default: + assert( false ); + break; + } + return offset; +} + +void IUIScene_AnvilMenu::handleOtherClicked(int iPad, ESceneSection eSection, int buttonNum, bool quickKey) +{ + switch(eSection) + { + case eSectionAnvilName: + handleEditNamePressed(); + break; + }; +} + +bool IUIScene_AnvilMenu::IsSectionSlotList( ESceneSection eSection ) +{ + switch( eSection ) + { + case eSectionAnvilUsing: + case eSectionAnvilInventory: + case eSectionAnvilItem1: + case eSectionAnvilItem2: + case eSectionAnvilResult: + return true; + } + return false; +} + +void IUIScene_AnvilMenu::handleTick() +{ + Minecraft *pMinecraft = Minecraft::GetInstance(); + bool canAfford = true; + wstring m_costString = L""; + + if(m_repairMenu->cost > 0) + { + if(m_repairMenu->cost >= 40 && !pMinecraft->localplayers[getPad()]->abilities.instabuild) + { + m_costString = app.GetString(IDS_REPAIR_EXPENSIVE); + canAfford = false; + } + else if(!m_repairMenu->getSlot(RepairMenu::RESULT_SLOT)->hasItem()) + { + // Do nothing + } + else + { + LPCWSTR costString = app.GetString(IDS_REPAIR_COST); + wchar_t temp[256]; + swprintf(temp, 256, costString, m_repairMenu->cost); + m_costString = temp; + if(!m_repairMenu->getSlot(RepairMenu::RESULT_SLOT)->mayPickup(dynamic_pointer_cast<Player>(m_inventory->player->shared_from_this()))) + { + canAfford = false; + } + } + } + setCostLabel(m_costString, canAfford); + + bool crossVisible = (m_repairMenu->getSlot(RepairMenu::INPUT_SLOT)->hasItem() || m_repairMenu->getSlot(RepairMenu::ADDITIONAL_SLOT)->hasItem()) && !m_repairMenu->getSlot(RepairMenu::RESULT_SLOT)->hasItem(); + showCross(crossVisible); +} + +void IUIScene_AnvilMenu::updateItemName() +{ + Slot *slot = m_repairMenu->getSlot(RepairMenu::INPUT_SLOT); + if (slot != NULL && slot->hasItem()) + { + if (!slot->getItem()->hasCustomHoverName() && m_itemName.compare(slot->getItem()->getHoverName())==0) + { + m_itemName = L""; + } + } + + m_repairMenu->setItemName(m_itemName); + + // Convert to byteArray + ByteArrayOutputStream baos; + DataOutputStream dos(&baos); + dos.writeUTF(m_itemName); + Minecraft::GetInstance()->localplayers[getPad()]->connection->send(shared_ptr<CustomPayloadPacket>(new CustomPayloadPacket(CustomPayloadPacket::SET_ITEM_NAME_PACKET, baos.toByteArray()))); +} + +void IUIScene_AnvilMenu::refreshContainer(AbstractContainerMenu *container, vector<shared_ptr<ItemInstance> > *items) +{ + slotChanged(container, RepairMenu::INPUT_SLOT, container->getSlot(0)->getItem()); +} + +void IUIScene_AnvilMenu::slotChanged(AbstractContainerMenu *container, int slotIndex, shared_ptr<ItemInstance> item) +{ + if (slotIndex == RepairMenu::INPUT_SLOT) + { + m_itemName = item == NULL ? L"" : item->getHoverName(); + setEditNameValue(m_itemName); + setEditNameEditable(item != NULL); + if (item != NULL) + { + updateItemName(); + } + } +} + +void IUIScene_AnvilMenu::setContainerData(AbstractContainerMenu *container, int id, int value) +{ +}
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/IUIScene_AnvilMenu.h b/Minecraft.Client/Common/UI/IUIScene_AnvilMenu.h new file mode 100644 index 00000000..6c4348f2 --- /dev/null +++ b/Minecraft.Client/Common/UI/IUIScene_AnvilMenu.h @@ -0,0 +1,45 @@ +#pragma once +#include "IUIScene_AbstractContainerMenu.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.inventory.ContainerListener.h" + +// The 0-indexed slot in the inventory list that lines up with the result slot +#define ANVIL_SCENE_RESULT_SLOT_UP_OFFSET 5 +#define ANVIL_SCENE_RESULT_SLOT_DOWN_OFFSET 5 +#define ANVIL_SCENE_ITEM1_SLOT_UP_OFFSET 3 +#define ANVIL_SCENE_ITEM1_SLOT_DOWN_OFFSET 3 +#define ANVIL_SCENE_ITEM2_SLOT_UP_OFFSET 4 +#define ANVIL_SCENE_ITEM2_SLOT_DOWN_OFFSET 4 + +class Inventory; +class RepairMenu; + +class IUIScene_AnvilMenu : public virtual IUIScene_AbstractContainerMenu, public net_minecraft_world_inventory::ContainerListener +{ +protected: + shared_ptr<Inventory> m_inventory; + RepairMenu *m_repairMenu; + wstring m_itemName; + +protected: + IUIScene_AnvilMenu(); + + virtual ESceneSection GetSectionAndSlotInDirection( ESceneSection eSection, ETapState eTapDirection, int *piTargetX, int *piTargetY ); + int getSectionStartOffset(ESceneSection eSection); + virtual void handleOtherClicked(int iPad, ESceneSection eSection, int buttonNum, bool quickKey); + bool IsSectionSlotList( ESceneSection eSection ); + + void handleTick(); + + // Anvil only + virtual void handleEditNamePressed() = 0; + virtual void setEditNameValue(const wstring &name) = 0; + virtual void setEditNameEditable(bool enabled) = 0; + virtual void setCostLabel(const wstring &label, bool canAfford) = 0; + virtual void showCross(bool show) = 0; + void updateItemName(); + + // ContainerListenr + void refreshContainer(AbstractContainerMenu *container, vector<shared_ptr<ItemInstance> > *items); + void slotChanged(AbstractContainerMenu *container, int slotIndex, shared_ptr<ItemInstance> item); + void setContainerData(AbstractContainerMenu *container, int id, int value); +};
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/IUIScene_BrewingMenu.cpp b/Minecraft.Client/Common/UI/IUIScene_BrewingMenu.cpp new file mode 100644 index 00000000..44bbdc44 --- /dev/null +++ b/Minecraft.Client/Common/UI/IUIScene_BrewingMenu.cpp @@ -0,0 +1,151 @@ +#include "stdafx.h" + +#include "IUIScene_BrewingMenu.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.inventory.h" + +IUIScene_AbstractContainerMenu::ESceneSection IUIScene_BrewingMenu::GetSectionAndSlotInDirection( ESceneSection eSection, ETapState eTapDirection, int *piTargetX, int *piTargetY ) +{ + ESceneSection newSection = eSection; + int xOffset = 0; + + // Find the new section if there is one + switch( eSection ) + { + case eSectionBrewingBottle1: + if(eTapDirection == eTapStateUp) + { + newSection = eSectionBrewingIngredient; + } + else if(eTapDirection == eTapStateDown) + { + newSection = eSectionBrewingInventory; + xOffset = BREWING_SCENE_BOTTLE1_SLOT_DOWN_OFFSET; + } + else if(eTapDirection == eTapStateLeft) + { + newSection = eSectionBrewingBottle3; + } + else if(eTapDirection == eTapStateRight) + { + newSection = eSectionBrewingBottle2; + } + break; + case eSectionBrewingBottle2: + if(eTapDirection == eTapStateUp) + { + newSection = eSectionBrewingIngredient; + } + else if(eTapDirection == eTapStateDown) + { + newSection = eSectionBrewingInventory; + xOffset = BREWING_SCENE_BOTTLE2_SLOT_DOWN_OFFSET; + } + else if(eTapDirection == eTapStateLeft) + { + newSection = eSectionBrewingBottle1; + } + else if(eTapDirection == eTapStateRight) + { + newSection = eSectionBrewingBottle3; + } + break; + case eSectionBrewingBottle3: + if(eTapDirection == eTapStateUp) + { + newSection = eSectionBrewingIngredient; + } + else if(eTapDirection == eTapStateDown) + { + newSection = eSectionBrewingInventory; + xOffset = BREWING_SCENE_BOTTLE3_SLOT_DOWN_OFFSET; + } + else if(eTapDirection == eTapStateLeft) + { + newSection = eSectionBrewingBottle2; + } + else if(eTapDirection == eTapStateRight) + { + newSection = eSectionBrewingBottle1; + } + break; + case eSectionBrewingIngredient: + if(eTapDirection == eTapStateUp) + { + newSection = eSectionBrewingUsing; + xOffset = BREWING_SCENE_INGREDIENT_SLOT_DOWN_OFFSET; + } + else if(eTapDirection == eTapStateDown) + { + newSection = eSectionBrewingBottle2; + } + break; + case eSectionBrewingInventory: + if(eTapDirection == eTapStateDown) + { + newSection = eSectionBrewingUsing; + } + else if(eTapDirection == eTapStateUp) + { + if( *piTargetX <= BREWING_SCENE_BOTTLE1_SLOT_UP_OFFSET) + { + newSection = eSectionBrewingBottle1; + } + else if( *piTargetX <= BREWING_SCENE_BOTTLE2_SLOT_UP_OFFSET) + { + newSection = eSectionBrewingBottle2; + } + else if( *piTargetX >= BREWING_SCENE_BOTTLE3_SLOT_UP_OFFSET) + { + newSection = eSectionBrewingBottle3; + } + } + break; + case eSectionBrewingUsing: + if(eTapDirection == eTapStateUp) + { + newSection = eSectionBrewingInventory; + } + else if(eTapDirection == eTapStateDown) + { + newSection = eSectionBrewingIngredient; + } + break; + default: + assert( false ); + break; + } + + updateSlotPosition(eSection, newSection, eTapDirection, piTargetX, piTargetY, xOffset); + + return newSection; +} + +int IUIScene_BrewingMenu::getSectionStartOffset(ESceneSection eSection) +{ + int offset = 0; + switch( eSection ) + { + case eSectionBrewingBottle1: + offset = BrewingStandMenu::BOTTLE_SLOT_START; + break; + case eSectionBrewingBottle2: + offset = BrewingStandMenu::BOTTLE_SLOT_START + 1; + break; + case eSectionBrewingBottle3: + offset = BrewingStandMenu::BOTTLE_SLOT_START + 2; + break; + case eSectionBrewingIngredient: + offset = BrewingStandMenu::INGREDIENT_SLOT; + break; + case eSectionBrewingInventory: + offset = BrewingStandMenu::INV_SLOT_START; + break; + case eSectionBrewingUsing: + offset = BrewingStandMenu::INV_SLOT_START + 27; + break; + default: + assert( false ); + break; + } + return offset; +}
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/IUIScene_BrewingMenu.h b/Minecraft.Client/Common/UI/IUIScene_BrewingMenu.h new file mode 100644 index 00000000..2d5150bb --- /dev/null +++ b/Minecraft.Client/Common/UI/IUIScene_BrewingMenu.h @@ -0,0 +1,19 @@ +#pragma once +#include "IUIScene_AbstractContainerMenu.h" + +// The 0-indexed slot in the inventory list that lines up with the result slot +#define BREWING_SCENE_INGREDIENT_SLOT_UP_OFFSET 5 +#define BREWING_SCENE_INGREDIENT_SLOT_DOWN_OFFSET 5 +#define BREWING_SCENE_BOTTLE1_SLOT_UP_OFFSET 3 +#define BREWING_SCENE_BOTTLE1_SLOT_DOWN_OFFSET 3 +#define BREWING_SCENE_BOTTLE2_SLOT_UP_OFFSET 4 +#define BREWING_SCENE_BOTTLE2_SLOT_DOWN_OFFSET 4 +#define BREWING_SCENE_BOTTLE3_SLOT_UP_OFFSET 5 +#define BREWING_SCENE_BOTTLE3_SLOT_DOWN_OFFSET 5 + +class IUIScene_BrewingMenu : public virtual IUIScene_AbstractContainerMenu +{ +protected: + virtual ESceneSection GetSectionAndSlotInDirection( ESceneSection eSection, ETapState eTapDirection, int *piTargetX, int *piTargetY ); + int getSectionStartOffset(ESceneSection eSection); +};
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/IUIScene_ContainerMenu.cpp b/Minecraft.Client/Common/UI/IUIScene_ContainerMenu.cpp new file mode 100644 index 00000000..c6a4df00 --- /dev/null +++ b/Minecraft.Client/Common/UI/IUIScene_ContainerMenu.cpp @@ -0,0 +1,71 @@ +#include "stdafx.h" +#include "IUIScene_ContainerMenu.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.inventory.h" + +IUIScene_AbstractContainerMenu::ESceneSection IUIScene_ContainerMenu::GetSectionAndSlotInDirection( ESceneSection eSection, ETapState eTapDirection, int *piTargetX, int *piTargetY ) +{ + ESceneSection newSection = eSection; + + // Find the new section if there is one + switch( eSection ) + { + case eSectionContainerChest: + if(eTapDirection == eTapStateDown) + { + newSection = eSectionContainerInventory; + } + else if(eTapDirection == eTapStateUp) + { + newSection = eSectionContainerUsing; + } + break; + case eSectionContainerInventory: + if(eTapDirection == eTapStateDown) + { + newSection = eSectionContainerUsing; + } + else if(eTapDirection == eTapStateUp) + { + newSection = eSectionContainerChest; + } + break; + case eSectionContainerUsing: + if(eTapDirection == eTapStateDown) + { + newSection = eSectionContainerChest; + } + else if(eTapDirection == eTapStateUp) + { + newSection = eSectionContainerInventory; + } + break; + default: + assert( false ); + break; + } + + updateSlotPosition(eSection, newSection, eTapDirection, piTargetX, piTargetY, 0); + + return newSection; +} + +int IUIScene_ContainerMenu::getSectionStartOffset(ESceneSection eSection) +{ + int offset = 0; + switch( eSection ) + { + case eSectionContainerChest: + offset = 0; + break; + case eSectionContainerInventory: + offset = m_menu->getSize() - (27+9); + break; + case eSectionContainerUsing: + offset = m_menu->getSize() - 9; + break; + default: + assert( false ); + break; + } + return offset; +}
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/IUIScene_ContainerMenu.h b/Minecraft.Client/Common/UI/IUIScene_ContainerMenu.h new file mode 100644 index 00000000..e0408b39 --- /dev/null +++ b/Minecraft.Client/Common/UI/IUIScene_ContainerMenu.h @@ -0,0 +1,10 @@ +#pragma once + +#include "IUIScene_AbstractContainerMenu.h" + +class IUIScene_ContainerMenu : public virtual IUIScene_AbstractContainerMenu +{ +protected: + virtual ESceneSection GetSectionAndSlotInDirection( ESceneSection eSection, ETapState eTapDirection, int *piTargetX, int *piTargetY ); + int getSectionStartOffset(ESceneSection eSection); +};
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/IUIScene_CraftingMenu.cpp b/Minecraft.Client/Common/UI/IUIScene_CraftingMenu.cpp new file mode 100644 index 00000000..f158b174 --- /dev/null +++ b/Minecraft.Client/Common/UI/IUIScene_CraftingMenu.cpp @@ -0,0 +1,1400 @@ +#include "stdafx.h" + +#include "..\..\..\Minecraft.World\net.minecraft.world.item.crafting.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.level.tile.h" +#include "..\..\..\Minecraft.World\net.minecraft.stats.h" +#include "..\..\LocalPlayer.h" +#include "IUIScene_CraftingMenu.h" + +Recipy::_eGroupType IUIScene_CraftingMenu::m_GroupTypeMapping4GridA[IUIScene_CraftingMenu::m_iMaxGroup2x2]= +{ + Recipy::eGroupType_Structure, + Recipy::eGroupType_Tool, + Recipy::eGroupType_Food, + Recipy::eGroupType_Mechanism, + Recipy::eGroupType_Transport, + Recipy::eGroupType_Decoration, +}; + +Recipy::_eGroupType IUIScene_CraftingMenu::m_GroupTypeMapping9GridA[IUIScene_CraftingMenu::m_iMaxGroup3x3]= +{ + Recipy::eGroupType_Structure, + Recipy::eGroupType_Tool, + Recipy::eGroupType_Food, + Recipy::eGroupType_Armour, + Recipy::eGroupType_Mechanism, + Recipy::eGroupType_Transport, + Recipy::eGroupType_Decoration, +}; + + +LPCWSTR IUIScene_CraftingMenu::m_GroupIconNameA[m_iMaxGroup3x3]= +{ + L"Structures",//Recipy::eGroupType_Structure, + L"Tools",//Recipy::eGroupType_Tool, + L"Food",//Recipy::eGroupType_Food, + L"Armour",//Recipy::eGroupType_Armour, + L"Mechanisms",//Recipy::eGroupType_Mechanism, + L"Transport",//Recipy::eGroupType_Transport, + L"Decoration",//Recipy::eGroupType_Decoration, +}; + +IUIScene_CraftingMenu::_eGroupTab IUIScene_CraftingMenu::m_GroupTabBkgMapping2x2A[m_iMaxGroup2x2]= +{ + eGroupTab_Left, + eGroupTab_Middle, + eGroupTab_Middle, + eGroupTab_Middle, + eGroupTab_Middle, + eGroupTab_Right, +}; + +IUIScene_CraftingMenu::_eGroupTab IUIScene_CraftingMenu::m_GroupTabBkgMapping3x3A[m_iMaxGroup3x3]= +{ + eGroupTab_Left, + eGroupTab_Middle, + eGroupTab_Middle, + eGroupTab_Middle, + eGroupTab_Middle, + eGroupTab_Middle, + eGroupTab_Right, +}; + + +// mapping array to map the base objects to their description string +// This should map the enums +// enum +// { +// eBaseItemType_undefined=0, +// eBaseItemType_sword, +// eBaseItemType_shovel, +// eBaseItemType_pickaxe, +// eBaseItemType_hatchet, +// eBaseItemType_hoe, +// eBaseItemType_door, +// eBaseItemType_helmet, +// eBaseItemType_chestplate, +// eBaseItemType_leggings, +// eBaseItemType_boots, +// eBaseItemType_ingot, +// eBaseItemType_rail, +// eBaseItemType_block, +// eBaseItemType_pressureplate, +// eBaseItemType_stairs, +// eBaseItemType_cloth, +// eBaseItemType_dyepowder, +// eBaseItemType_structplanks +// eBaseItemType_structblock, +// eBaseItemType_slab, +// eBaseItemType_halfslab, +// eBaseItemType_torch, +// eBaseItemType_bow, +// eBaseItemType_pockettool, +// eBaseItemType_utensil, +// +// } +// eBaseItemType; + +IUIScene_CraftingMenu::IUIScene_CraftingMenu() +{ + m_iCurrentSlotHIndex=0; + m_iCurrentSlotVIndex=1; + + for(int i=0;i<m_iMaxHSlotC;i++) + { + CanBeMadeA[i].iCount=0; + CanBeMadeA[i].iItemBaseType=0; + } + memset(CanBeMadeA,0,sizeof(CANBEMADE)*m_iMaxHSlotC); + m_iRecipeC=0; + m_iGroupIndex=0; + + for(int i=0;i<m_iMaxDisplayedVSlotC;i++) + { + iVSlotIndexA[i]=i; // start with 0,1,2 + } + + m_iDisplayDescription=DISPLAY_INVENTORY; + m_iIngredientsC=0; +} + +LPCWSTR IUIScene_CraftingMenu::GetGroupNameText(int iGroupType) +{ + switch(iGroupType) + { + case ShapedRecipy::eGroupType_Tool: + return app.GetString( IDS_GROUPNAME_TOOLS ); + case ShapedRecipy::eGroupType_Food: + return app.GetString( IDS_GROUPNAME_FOOD); + case ShapedRecipy::eGroupType_Structure: + return app.GetString( IDS_GROUPNAME_STRUCTURES ); + case ShapedRecipy::eGroupType_Armour: + return app.GetString( IDS_GROUPNAME_ARMOUR ); + case ShapedRecipy::eGroupType_Mechanism: + return app.GetString( IDS_GROUPNAME_MECHANISMS ); + case ShapedRecipy::eGroupType_Transport: + return app.GetString( IDS_GROUPNAME_TRANSPORT ); + case ShapedRecipy::eGroupType_Decoration: + default: + return app.GetString( IDS_GROUPNAME_DECORATIONS ); + } +} + +bool IUIScene_CraftingMenu::handleKeyDown(int iPad, int iAction, bool bRepeat) +{ + bool bHandled = false; + + if(m_bIgnoreKeyPresses) return bHandled; + + // ignore key repeats of the X key - because it's X to open this menu, it can come through as a repeat on opening + if(bRepeat &&(iAction==ACTION_MENU_X)) + { + return S_OK; + } + + 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; + } + } + } + + + switch(iAction) + { + case ACTION_MENU_X: + + // change the display + m_iDisplayDescription++; + if(m_iDisplayDescription==DISPLAY_MAX) m_iDisplayDescription=DISPLAY_INVENTORY; + ui.PlayUISFX(eSFX_Focus); + UpdateMultiPanel(); + UpdateTooltips(); + break; + case ACTION_MENU_PAUSEMENU: + case ACTION_MENU_B: + ui.ShowTooltip( iPad, eToolTipButtonX, false ); + ui.ShowTooltip( iPad, eToolTipButtonB, false ); + ui.ShowTooltip( iPad, eToolTipButtonA, false ); + ui.ShowTooltip( iPad, eToolTipButtonRB, false ); + // kill the crafting xui + //ui.PlayUISFX(eSFX_Back); + ui.CloseUIScenes(iPad); + + bHandled = true; + break; + case ACTION_MENU_A: +#ifdef __ORBIS__ + case ACTION_MENU_TOUCHPAD_PRESS: +#endif + // Do some crafting! + if(m_pPlayer && m_pPlayer->inventory) + { + //RecipyList *recipes = ((Recipes *)Recipes::getInstance())->getRecipies(); + Recipy::INGREDIENTS_REQUIRED *pRecipeIngredientsRequired=Recipes::getInstance()->getRecipeIngredientsArray(); + // Force a make if the debug is on + if(app.DebugSettingsOn() && app.GetGameSettingsDebugMask(ProfileManager.GetPrimaryPad())&(1L<<eDebugSetting_CraftAnything)) + { + if(CanBeMadeA[m_iCurrentSlotHIndex].iCount!=0) + { + int iSlot=iVSlotIndexA[m_iCurrentSlotVIndex]; + + int iRecipe= CanBeMadeA[m_iCurrentSlotHIndex].iRecipeA[iSlot]; + shared_ptr<ItemInstance> pTempItemInst=pRecipeIngredientsRequired[iRecipe].pRecipy->assemble(nullptr); + //int iIcon=pTempItemInst->getItem()->getIcon(pTempItemInst->getAuxValue()); + + if( pMinecraft->localgameModes[iPad] != NULL) + { + Tutorial *tutorial = pMinecraft->localgameModes[iPad]->getTutorial(); + if(tutorial != NULL) + { + tutorial->onCrafted(pTempItemInst); + } + } + + pMinecraft->localgameModes[iPad]->handleCraftItem(iRecipe,m_pPlayer); + + if(m_pPlayer->inventory->add(pTempItemInst)==false) + { + // no room in inventory, so throw it down + m_pPlayer->drop(pTempItemInst); + } + // play a sound + //pMinecraft->soundEngine->playUI( L"random.pop", 1.0f, 1.0f); + ui.PlayUISFX(eSFX_Craft); + } + } + else if(CanBeMadeA[m_iCurrentSlotHIndex].iCount!=0) + { + int iSlot; + if(CanBeMadeA[m_iCurrentSlotHIndex].iCount>1) + { + iSlot=iVSlotIndexA[m_iCurrentSlotVIndex]; + } + else + { + iSlot=0; + } + int iRecipe= CanBeMadeA[m_iCurrentSlotHIndex].iRecipeA[iSlot]; + shared_ptr<ItemInstance> pTempItemInst=pRecipeIngredientsRequired[iRecipe].pRecipy->assemble(nullptr); + //int iIcon=pTempItemInst->getItem()->getIcon(pTempItemInst->getAuxValue()); + + if( pMinecraft->localgameModes[iPad] != NULL ) + { + Tutorial *tutorial = pMinecraft->localgameModes[iPad]->getTutorial(); + if(tutorial != NULL) + { + tutorial->createItemSelected(pTempItemInst, pRecipeIngredientsRequired[iRecipe].bCanMake[iPad]); + } + } + + if(pRecipeIngredientsRequired[iRecipe].bCanMake[iPad]) + { + pTempItemInst->onCraftedBy(m_pPlayer->level, dynamic_pointer_cast<Player>( m_pPlayer->shared_from_this() ), pTempItemInst->count ); + // TODO 4J Stu - handleCraftItem should do a lot more than what it does, loads of the "can we craft" code should also probably be + // shifted to the GameMode + pMinecraft->localgameModes[iPad]->handleCraftItem(iRecipe,m_pPlayer); + + // play a sound + //pMinecraft->soundEngine->playUI( L"random.pop", 1.0f, 1.0f); + ui.PlayUISFX(eSFX_Craft); + + // and remove those resources from your inventory + for(int i=0;i<pRecipeIngredientsRequired[iRecipe].iIngC;i++) + { + for(int j=0;j<pRecipeIngredientsRequired[iRecipe].iIngValA[i];j++) + { + shared_ptr<ItemInstance> ingItemInst = nullptr; + // do we need to remove a specific aux value? + if(pRecipeIngredientsRequired[iRecipe].iIngAuxValA[i]!=Recipes::ANY_AUX_VALUE) + { + ingItemInst = m_pPlayer->inventory->getResourceItem( pRecipeIngredientsRequired[iRecipe].iIngIDA[i],pRecipeIngredientsRequired[iRecipe].iIngAuxValA[i] ); + m_pPlayer->inventory->removeResource(pRecipeIngredientsRequired[iRecipe].iIngIDA[i],pRecipeIngredientsRequired[iRecipe].iIngAuxValA[i]); + } + else + { + ingItemInst = m_pPlayer->inventory->getResourceItem( pRecipeIngredientsRequired[iRecipe].iIngIDA[i] ); + m_pPlayer->inventory->removeResource(pRecipeIngredientsRequired[iRecipe].iIngIDA[i]); + } + + // 4J Stu - Fix for #13097 - Bug: Milk Buckets are removed when crafting Cake + if (ingItemInst != NULL) + { + if (ingItemInst->getItem()->hasCraftingRemainingItem()) + { + // replace item with remaining result + m_pPlayer->inventory->add( shared_ptr<ItemInstance>( new ItemInstance(ingItemInst->getItem()->getCraftingRemainingItem()) ) ); + } + + } + } + } + + // 4J Stu - Fix for #13119 - We should add the item after we remove the ingredients + if(m_pPlayer->inventory->add(pTempItemInst)==false ) + { + // no room in inventory, so throw it down + m_pPlayer->drop(pTempItemInst); + } + + //4J Gordon: Achievements + switch(pTempItemInst->id ) + { + case Tile::workBench_Id: m_pPlayer->awardStat(GenericStats::buildWorkbench(), GenericStats::param_buildWorkbench()); break; + case Item::pickAxe_wood_Id: m_pPlayer->awardStat(GenericStats::buildPickaxe(), GenericStats::param_buildPickaxe()); break; + case Tile::furnace_Id: m_pPlayer->awardStat(GenericStats::buildFurnace(), GenericStats::param_buildFurnace()); break; + case Item::hoe_wood_Id: m_pPlayer->awardStat(GenericStats::buildHoe(), GenericStats::param_buildHoe()); break; + case Item::bread_Id: m_pPlayer->awardStat(GenericStats::makeBread(), GenericStats::param_makeBread()); break; + case Item::cake_Id: m_pPlayer->awardStat(GenericStats::bakeCake(), GenericStats::param_bakeCake()); break; + case Item::pickAxe_stone_Id: m_pPlayer->awardStat(GenericStats::buildBetterPickaxe(), GenericStats::param_buildBetterPickaxe()); break; + case Item::sword_wood_Id: m_pPlayer->awardStat(GenericStats::buildSword(), GenericStats::param_buildSword()); break; + case Tile::dispenser_Id: m_pPlayer->awardStat(GenericStats::dispenseWithThis(), GenericStats::param_dispenseWithThis()); break; + case Tile::enchantTable_Id: m_pPlayer->awardStat(GenericStats::enchantments(), GenericStats::param_enchantments()); break; + case Tile::bookshelf_Id: m_pPlayer->awardStat(GenericStats::bookcase(), GenericStats::param_bookcase()); break; + } + + // We've used some ingredients from our inventory, so update the recipes we can make + CheckRecipesAvailable(); + // don't reset the vertical slots - we want to stay where we are + UpdateVerticalSlots(); + UpdateHighlight(); + } + else + { + //pMinecraft->soundEngine->playUI( L"btn.back", 1.0f, 1.0f); + ui.PlayUISFX(eSFX_CraftFail); + } + } + } + break; + + case ACTION_MENU_LEFT_SCROLL: + // turn off the old group tab + showTabHighlight(m_iGroupIndex,false); + + if(m_iGroupIndex==0) + { + if(m_iContainerType==RECIPE_TYPE_3x3) + { + m_iGroupIndex=m_iMaxGroup3x3-1; + } + else + { + m_iGroupIndex=m_iMaxGroup2x2-1; + } + } + else + { + m_iGroupIndex--; + } + // turn on the new group + showTabHighlight(m_iGroupIndex,true); + + m_iCurrentSlotHIndex=0; + m_iCurrentSlotVIndex=1; + + CheckRecipesAvailable(); + // reset the vertical slots + iVSlotIndexA[0]=CanBeMadeA[m_iCurrentSlotHIndex].iCount-1; + iVSlotIndexA[1]=0; + iVSlotIndexA[2]=1; + ui.PlayUISFX(eSFX_Focus); + UpdateVerticalSlots(); + UpdateHighlight(); + setGroupText(GetGroupNameText(m_pGroupA[m_iGroupIndex])); + + break; + case ACTION_MENU_RIGHT_SCROLL: + // turn off the old group tab + showTabHighlight(m_iGroupIndex,false); + + m_iGroupIndex++; + if(m_iContainerType==RECIPE_TYPE_3x3) + { + if(m_iGroupIndex==m_iMaxGroup3x3) m_iGroupIndex=0; + } + else + { + if(m_iGroupIndex==m_iMaxGroup2x2) m_iGroupIndex=0; + } + // turn on the new group + showTabHighlight(m_iGroupIndex,true); + + m_iCurrentSlotHIndex=0; + m_iCurrentSlotVIndex=1; + CheckRecipesAvailable(); + // reset the vertical slots + iVSlotIndexA[0]=CanBeMadeA[m_iCurrentSlotHIndex].iCount-1; + iVSlotIndexA[1]=0; + iVSlotIndexA[2]=1; + ui.PlayUISFX(eSFX_Focus); + UpdateVerticalSlots(); + UpdateHighlight(); + setGroupText(GetGroupNameText(m_pGroupA[m_iGroupIndex])); + break; + } + + // 4J-Tomk - check if we've only got one vertical scroll slot (480, splits & Vita) + bool bNoScrollSlots = false; + if(m_bSplitscreen ||(!RenderManager.IsHiDef() && !RenderManager.IsWidescreen())) + { + bNoScrollSlots = true; + } +#ifdef __PSVITA__ + bNoScrollSlots = true; +#endif + + // 4J Stu - We did used to swap the thumsticks based on Southpaw in this scene, but ONLY in this scene + switch(iAction) + { + case ACTION_MENU_OTHER_STICK_UP: + scrollDescriptionUp(); + break; + case ACTION_MENU_OTHER_STICK_DOWN: + scrollDescriptionDown(); + break; + case ACTION_MENU_RIGHT: + { + int iOldHSlot=m_iCurrentSlotHIndex; + + m_iCurrentSlotHIndex++; + if(m_iCurrentSlotHIndex>=m_iCraftablesMaxHSlotC) m_iCurrentSlotHIndex=0; + m_iCurrentSlotVIndex=1; + // clear the indices + iVSlotIndexA[0]=CanBeMadeA[m_iCurrentSlotHIndex].iCount-1; + iVSlotIndexA[1]=0; + iVSlotIndexA[2]=1; + + UpdateVerticalSlots(); + UpdateHighlight(); + // re-enable the old hslot + if(CanBeMadeA[iOldHSlot].iCount>0) + { + setShowCraftHSlot(iOldHSlot,true); + } + ui.PlayUISFX(eSFX_Focus); + bHandled = true; + } + break; + case ACTION_MENU_LEFT: + { + if(m_iCraftablesMaxHSlotC!=0) + { + int iOldHSlot=m_iCurrentSlotHIndex; + if(m_iCurrentSlotHIndex==0) m_iCurrentSlotHIndex=m_iCraftablesMaxHSlotC-1; + else m_iCurrentSlotHIndex--; + m_iCurrentSlotVIndex=1; + // clear the indices + iVSlotIndexA[0]=CanBeMadeA[m_iCurrentSlotHIndex].iCount-1; + iVSlotIndexA[1]=0; + iVSlotIndexA[2]=1; + + UpdateVerticalSlots(); + UpdateHighlight(); + // re-enable the old hslot + if(CanBeMadeA[iOldHSlot].iCount>0) + { + setShowCraftHSlot(iOldHSlot,true); + } + ui.PlayUISFX(eSFX_Focus); + } + bHandled = true; + } + break; + case ACTION_MENU_UP: + { + if(CanBeMadeA[m_iCurrentSlotHIndex].iCount>1) + { + if(bNoScrollSlots) + { + if(iVSlotIndexA[1]==0) + { + iVSlotIndexA[1]=CanBeMadeA[m_iCurrentSlotHIndex].iCount-1; + } + else + { + iVSlotIndexA[1]--; + } + ui.PlayUISFX(eSFX_Focus); + } + else + if(CanBeMadeA[m_iCurrentSlotHIndex].iCount>2) + { + { + if(m_iCurrentSlotVIndex!=0) + { + // just move the highlight + m_iCurrentSlotVIndex--; + ui.PlayUISFX(eSFX_Focus); + } + else + { + //move the slots + iVSlotIndexA[2]=iVSlotIndexA[1]; + iVSlotIndexA[1]=iVSlotIndexA[0]; + // on 0 and went up, so cycle the values + if(iVSlotIndexA[0]==0) + { + iVSlotIndexA[0]=CanBeMadeA[m_iCurrentSlotHIndex].iCount-1; + } + else + { + iVSlotIndexA[0]--; + } + ui.PlayUISFX(eSFX_Focus); + } + } + } + else + { + if(m_iCurrentSlotVIndex!=1) + { + // just move the highlight + m_iCurrentSlotVIndex--; + ui.PlayUISFX(eSFX_Focus); + } + } + UpdateVerticalSlots(); + UpdateHighlight(); + } + + } + break; + case ACTION_MENU_DOWN: + { + if(CanBeMadeA[m_iCurrentSlotHIndex].iCount>1) + { + if(bNoScrollSlots) + { + if(iVSlotIndexA[1]==(CanBeMadeA[m_iCurrentSlotHIndex].iCount-1)) + { + iVSlotIndexA[1]=0; + } + else + { + iVSlotIndexA[1]++; + } + ui.PlayUISFX(eSFX_Focus); + + } + else + if(CanBeMadeA[m_iCurrentSlotHIndex].iCount>2) + { + if(m_iCurrentSlotVIndex!=2) + { + m_iCurrentSlotVIndex++; + ui.PlayUISFX(eSFX_Focus); + } + else + { + iVSlotIndexA[0]=iVSlotIndexA[1]; + iVSlotIndexA[1]=iVSlotIndexA[2]; + if(iVSlotIndexA[m_iCurrentSlotVIndex]==(CanBeMadeA[m_iCurrentSlotHIndex].iCount-1)) + { + iVSlotIndexA[2]=0; + } + else + { + iVSlotIndexA[2]++; + } + ui.PlayUISFX(eSFX_Focus); + } + } + else + { + if(m_iCurrentSlotVIndex!=(CanBeMadeA[m_iCurrentSlotHIndex].iCount)) + { + m_iCurrentSlotVIndex++; + ui.PlayUISFX(eSFX_Focus); + } + } + UpdateVerticalSlots(); + UpdateHighlight(); + } + } + break; + } + + return bHandled; +} + +////////////////////////////////////////////////////////////////////////// +// +// CheckRecipesAvailable +// +////////////////////////////////////////////////////////////////////////// +void IUIScene_CraftingMenu::CheckRecipesAvailable() +{ + int iHSlotBrushControl=0; + + // clear the current list + memset(CanBeMadeA,0,sizeof(CANBEMADE)*m_iCraftablesMaxHSlotC); + + hideAllHSlots(); + + if(m_pPlayer && m_pPlayer->inventory) + { + // dump out the inventory + /* for (unsigned int k = 0; k < m_pPlayer->inventory->items.length; k++) + { + if (m_pPlayer->inventory->items[k] != NULL) + { + wstring itemstring=m_pPlayer->inventory->items[k]->toString(); + + //printf("--- Player has "); + OutputDebugStringW(itemstring.c_str()); + //printf(" with Aux val = %d, base type = %d, Material = %d\n",m_pPlayer->inventory->items[k]->getAuxValue(),m_pPlayer->inventory->items[k]->getItem()->getBaseItemType(),m_pPlayer->inventory->items[k]->getItem()->getMaterial()); + } + } + */ + RecipyList *recipes = ((Recipes *)Recipes::getInstance())->getRecipies(); + Recipy::INGREDIENTS_REQUIRED *pRecipeIngredientsRequired=Recipes::getInstance()->getRecipeIngredientsArray(); + int iRecipeC=(int)recipes->size(); + AUTO_VAR(itRecipe, recipes->begin()); + + // dump out the recipe products + + // for (int i = 0; i < iRecipeC; i++) + // { + // shared_ptr<ItemInstance> pTempItemInst=pRecipeIngredientsRequired[i].pRecipy->assemble(NULL); + // if (pTempItemInst != NULL) + // { + // wstring itemstring=pTempItemInst->toString(); + // + // printf("Recipe [%d] = ",i); + // OutputDebugStringW(itemstring.c_str()); + // if(pTempItemInst->id!=0) + // { + // if(pTempItemInst->id<256) + // { + // Tile *pTile=Tile::tiles[pTempItemInst->id]; + // printf("[TILE] ID\t%d\tAux val\t%d\tBase type\t%d\tMaterial\t%d\t Count=%d\n",pTempItemInst->id, pTempItemInst->getAuxValue(),pTile->getBaseItemType(),pTile->getMaterial(),pTempItemInst->GetCount()); + // } + // else + // { + // printf("ID\t%d\tAux val\t%d\tBase type\t%d\tMaterial\t%d Count=%d\n",pTempItemInst->id, pTempItemInst->getAuxValue(),pTempItemInst->getItem()->getBaseItemType(),pTempItemInst->getItem()->getMaterial(),pTempItemInst->GetCount()); + // } + // + // } + // } + // } + + for(int i=0;i<iRecipeC;i++) + { + + Recipy *r = *itRecipe; + + // If this recipe isn't in the current grouptype, skip it + if(r->getGroup()!=m_pGroupA[m_iGroupIndex]) + { + itRecipe++; + pRecipeIngredientsRequired[i].bCanMake[getPad()]=false; + continue; + } + // if we are in the inventory menu, then we have 2x2 crafting available only + if((m_iContainerType==RECIPE_TYPE_2x2) && (pRecipeIngredientsRequired[i].iType==RECIPE_TYPE_3x3)) + { + // need a crafting table for this recipe + itRecipe++; + pRecipeIngredientsRequired[i].bCanMake[getPad()]=false; + continue; + } + // clear the mask showing which ingredients are missing + pRecipeIngredientsRequired[i].usBitmaskMissingGridIngredients[getPad()]=0; + + //bool bCanMakeRecipe=true; + bool *bFoundA= new bool [pRecipeIngredientsRequired[i].iIngC]; + for(int j=0;j<pRecipeIngredientsRequired[i].iIngC;j++) + { + bFoundA[j]=false; + int iTotalCount=0; + + // Does the player have this ingredient? + for (unsigned int k = 0; k < m_pPlayer->inventory->items.length; k++) + { + if (m_pPlayer->inventory->items[k] != NULL) + { + // do they have the ingredient, and the aux value matches, and enough off it? + if((m_pPlayer->inventory->items[k]->id == pRecipeIngredientsRequired[i].iIngIDA[j]) && + // check if the ingredient required doesn't care about the aux value, or if it does, does the inventory item aux match it + ((pRecipeIngredientsRequired[i].iIngAuxValA[j]==Recipes::ANY_AUX_VALUE) || (pRecipeIngredientsRequired[i].iIngAuxValA[j]==m_pPlayer->inventory->items[k]->getAuxValue())) + ) + { + // do they have enough? We need to check the whole inventory, since they may have enough in different slots (milk isn't milkx3, but milk,milk,milk) + if(m_pPlayer->inventory->items[k]->GetCount()>=pRecipeIngredientsRequired[i].iIngValA[j]) + { + // they have enough with one slot + bFoundA[j]=true; + } + else + { + // look at the combined value from the whole inventory + + for(unsigned int l=0;l<m_pPlayer->inventory->items.length;l++) + { + if (m_pPlayer->inventory->items[l] != NULL) + { + if( + (m_pPlayer->inventory->items[l]->id == pRecipeIngredientsRequired[i].iIngIDA[j]) && + ( (pRecipeIngredientsRequired[i].iIngAuxValA[j]==Recipes::ANY_AUX_VALUE) || (pRecipeIngredientsRequired[i].iIngAuxValA[j]==m_pPlayer->inventory->items[l]->getAuxValue() )) + ) + { + iTotalCount+=m_pPlayer->inventory->items[l]->GetCount(); + } + } + } + + if(iTotalCount>=pRecipeIngredientsRequired[i].iIngValA[j]) + { + bFoundA[j]=true; + } + } + + // 4J Stu - TU-1 hotfix + // Fix for #13143 - Players are able to craft items they do not have enough ingredients for if they store the ingredients in multiple, smaller stacks + break; + } + } + } + // if bFoundA[j] is false, then we didn't have enough of the ingredient required by the recipe, so mark the grid items we're short of + if(bFoundA[j]==false) + { + int iMissing = pRecipeIngredientsRequired[i].iIngValA[j]-iTotalCount; + int iGridIndex=0; + while(iMissing!=0) + { + // need to check if there is an aux val and match that + if(((pRecipeIngredientsRequired[i].uiGridA[iGridIndex]&0x00FFFFFF)==pRecipeIngredientsRequired[i].iIngIDA[j]) && + ((pRecipeIngredientsRequired[i].iIngAuxValA[j]==Recipes::ANY_AUX_VALUE) ||(pRecipeIngredientsRequired[i].iIngAuxValA[j]== ((pRecipeIngredientsRequired[i].uiGridA[iGridIndex]&0xFF000000)>>24))) ) + { + // this grid entry is the ingredient we don't have enough of + pRecipeIngredientsRequired[i].usBitmaskMissingGridIngredients[getPad()]|=1<<iGridIndex; + iMissing--; + } + iGridIndex++; + } + } + } + + // so can we make it? + bool bCanMake=true; + for(int j=0;j<pRecipeIngredientsRequired[i].iIngC;j++) + { + if(bFoundA[j]==false) + { + bCanMake=false; + break; + } + } + + pRecipeIngredientsRequired[i].bCanMake[getPad()]=bCanMake; + + // Add the recipe to the CanBeMade list of lists + if(iHSlotBrushControl<=m_iCraftablesMaxHSlotC) + { + bool bFound=false; + shared_ptr<ItemInstance> pTempItemInst=pRecipeIngredientsRequired[i].pRecipy->assemble(nullptr); + //int iIcon=pTempItemInst->getItem()->getIcon(pTempItemInst->getAuxValue()); + int iID=pTempItemInst->getItem()->id; + int iBaseType; + + if(iID<256) // is it a tile? + { + iBaseType=Tile::tiles[iID]->getBaseItemType(); + } + else + { + iBaseType=pTempItemInst->getItem()->getBaseItemType(); + } + + // ignore for the misc base type - these have not been placed in a base type group + if(iBaseType!=Item::eBaseItemType_undefined) + { + for(int k=0;k<iHSlotBrushControl;k++) + { + // if the item base type is the same as one already in, then add it to that list + if(CanBeMadeA[k].iItemBaseType==iBaseType) + { + // base item type already in our list + bFound=true; + if(CanBeMadeA[k].iCount<m_iMaxVSlotC) + { + CanBeMadeA[k].iRecipeA[CanBeMadeA[k].iCount++]=i; + } + else + { + app.DebugPrintf("Need more V slots\n"); + } + break; + } + } + } + + if(!bFound) + { + if(iHSlotBrushControl<m_iCraftablesMaxHSlotC) + { + // add to the list + CanBeMadeA[iHSlotBrushControl].iItemBaseType=iBaseType; + CanBeMadeA[iHSlotBrushControl].iRecipeA[CanBeMadeA[iHSlotBrushControl].iCount++]=i; + iHSlotBrushControl++; + } + else + { + app.DebugPrintf("Need more H slots - "); +#ifndef _CONTENT_PACKAGE + OutputDebugStringW(app.GetString(pTempItemInst->getDescriptionId())); +#endif + app.DebugPrintf("\n"); + + } + } + } + else + { + app.DebugPrintf("Need more HSlots\n"); + } + + delete [] bFoundA; + itRecipe++; + } + } + + // run through the canbemade list and update the icons displayed + int iIndex=0; + //RecipyList *recipes = ((Recipes *)Recipes::getInstance())->getRecipies(); + Recipy::INGREDIENTS_REQUIRED *pRecipeIngredientsRequired=Recipes::getInstance()->getRecipeIngredientsArray(); + + while((iIndex<m_iCraftablesMaxHSlotC) && CanBeMadeA[iIndex].iCount!=0) + { + shared_ptr<ItemInstance> pTempItemInst=pRecipeIngredientsRequired[CanBeMadeA[iIndex].iRecipeA[0]].pRecipy->assemble(nullptr); + assert(pTempItemInst->id!=0); + unsigned int uiAlpha; + + if(app.DebugSettingsOn() && app.GetGameSettingsDebugMask(ProfileManager.GetPrimaryPad())&(1L<<eDebugSetting_CraftAnything)) + { + uiAlpha = 31; + } + else + { + if(pRecipeIngredientsRequired[CanBeMadeA[iIndex].iRecipeA[0]].bCanMake[getPad()]) + { + uiAlpha = 31; + } + else + { + uiAlpha= 16; + } + } + + // 4J Stu - For clocks and compasses we set the aux value to a special one that signals we should use a default texture + // rather than the dynamic one for the player + if( pTempItemInst->id == Item::clock_Id || pTempItemInst->id == Item::compass_Id ) + { + pTempItemInst->setAuxValue( 255 ); + } + setCraftHSlotItem(getPad(),iIndex,pTempItemInst,uiAlpha); + + iIndex++; + } + + // 4J-PB - Removed - UpdateTooltips will do this + // Update tooltips + /*if(CanBeMadeA[m_iCurrentSlotHIndex].iCount!=0) + { + ui.ShowTooltip( getPad(), eToolTipButtonA, true ); + // 4J-PB - not implemented ! + //ui.EnableTooltip( getPad(), eToolTipButtonA, true ); + } + else + { + ui.ShowTooltip( getPad(), eToolTipButtonA, false ); + }*/ +} + +////////////////////////////////////////////////////////////////////////// +// +// UpdateHighlight +// +////////////////////////////////////////////////////////////////////////// +void IUIScene_CraftingMenu::UpdateHighlight() +{ + updateHighlightAndScrollPositions(); + + bool bCanBeMade=CanBeMadeA[m_iCurrentSlotHIndex].iCount!=0; + if(bCanBeMade) + { + //RecipyList *recipes = ((Recipes *)Recipes::getInstance())->getRecipies(); + Recipy::INGREDIENTS_REQUIRED *pRecipeIngredientsRequired=Recipes::getInstance()->getRecipeIngredientsArray(); + int iSlot; + if(CanBeMadeA[m_iCurrentSlotHIndex].iCount>1) + { + iSlot=iVSlotIndexA[m_iCurrentSlotVIndex]; + } + else + { + iSlot=0; + } + shared_ptr<ItemInstance> pTempItemInstAdditional=pRecipeIngredientsRequired[CanBeMadeA[m_iCurrentSlotHIndex].iRecipeA[iSlot]].pRecipy->assemble(nullptr); + + // special case for the torch coal/charcoal + int id=pTempItemInstAdditional->getDescriptionId(); + LPCWSTR itemstring; + + switch(id) + { + case IDS_TILE_TORCH: + { + if(pRecipeIngredientsRequired[CanBeMadeA[m_iCurrentSlotHIndex].iRecipeA[iSlot]].iIngAuxValA[0]==1) + { + itemstring=app.GetString( IDS_TILE_TORCHCHARCOAL ); + } + else + { + itemstring=app.GetString( IDS_TILE_TORCHCOAL ); + } + } + break; + case IDS_ITEM_FIREBALL: + { + if(pRecipeIngredientsRequired[CanBeMadeA[m_iCurrentSlotHIndex].iRecipeA[iSlot]].iIngAuxValA[2]==1) + { + itemstring=app.GetString( IDS_ITEM_FIREBALLCHARCOAL ); + } + else + { + itemstring=app.GetString( IDS_ITEM_FIREBALLCOAL ); + } + } + break; + default: + itemstring=app.GetString(id ); + break; + } + + setItemText(itemstring); + } + else + { + setItemText(L""); + } + UpdateDescriptionText(bCanBeMade); + DisplayIngredients(); + + UpdateMultiPanel(); + + UpdateTooltips(); +} + +////////////////////////////////////////////////////////////////////////// +// +// UpdateVerticalSlots +// +////////////////////////////////////////////////////////////////////////// +void IUIScene_CraftingMenu::UpdateVerticalSlots() +{ + //RecipyList *recipes = ((Recipes *)Recipes::getInstance())->getRecipies(); + Recipy::INGREDIENTS_REQUIRED *pRecipeIngredientsRequired=Recipes::getInstance()->getRecipeIngredientsArray(); + + // update the vertical items for the current horizontal slot + hideAllVSlots(); + + // could have either 1 or 2 vertical slots, above and below the horizontal slot + if(CanBeMadeA[m_iCurrentSlotHIndex].iCount>1) + { + // turn off the horizontal one since we could be cycling through others + setShowCraftHSlot(m_iCurrentSlotHIndex,false); + int iSlots=(CanBeMadeA[m_iCurrentSlotHIndex].iCount>2)?3:2; + + // 4J-Tomk - check if we've only got one vertical scroll slot (480, splits & Vita) + bool bNoScrollSlots = false; + if(m_bSplitscreen ||(!RenderManager.IsHiDef() && !RenderManager.IsWidescreen())) + { + bNoScrollSlots = true; + } +#ifdef __PSVITA__ + bNoScrollSlots = true; +#endif + + for(int i=0;i<iSlots;i++) + { + // 4J this check determines if the crafting scene has only one vertical scroll slot + if(bNoScrollSlots) + { + if(i!=1) continue; + } + shared_ptr<ItemInstance> pTempItemInstAdditional=pRecipeIngredientsRequired[CanBeMadeA[m_iCurrentSlotHIndex].iRecipeA[iVSlotIndexA[i]]].pRecipy->assemble(nullptr); + + assert(pTempItemInstAdditional->id!=0); + unsigned int uiAlpha; + + if(app.DebugSettingsOn() && app.GetGameSettingsDebugMask(ProfileManager.GetPrimaryPad())&(1L<<eDebugSetting_CraftAnything)) + { + uiAlpha = 31; + } + else + { + if(pRecipeIngredientsRequired[CanBeMadeA[m_iCurrentSlotHIndex].iRecipeA[iVSlotIndexA[i]]].bCanMake[getPad()]) + { + uiAlpha = 31; + } + else + { + uiAlpha= 16; + } + } + + // 4J Stu - For clocks and compasses we set the aux value to a special one that signals we should use a default texture + // rather than the dynamic one for the player + if( pTempItemInstAdditional->id == Item::clock_Id || pTempItemInstAdditional->id == Item::compass_Id ) + { + pTempItemInstAdditional->setAuxValue( 255 ); + } + + setCraftVSlotItem(getPad(),i,pTempItemInstAdditional,uiAlpha); + + updateVSlotPositions(iSlots, i); + } + } +} + +////////////////////////////////////////////////////////////////////////// +// +// DisplayIngredients +// +////////////////////////////////////////////////////////////////////////// +void IUIScene_CraftingMenu::DisplayIngredients() +{ + //RecipyList *recipes = ((Recipes *)Recipes::getInstance())->getRecipies(); + Recipy::INGREDIENTS_REQUIRED *pRecipeIngredientsRequired=Recipes::getInstance()->getRecipeIngredientsArray(); + + // hide the previous ingredients + hideAllIngredientsSlots(); + + if(CanBeMadeA[m_iCurrentSlotHIndex].iCount!=0) + { + int iSlot,iRecipy; + if(CanBeMadeA[m_iCurrentSlotHIndex].iCount>1) + { + iSlot=iVSlotIndexA[m_iCurrentSlotVIndex]; + iRecipy=CanBeMadeA[m_iCurrentSlotHIndex].iRecipeA[iSlot]; + } + else + { + iSlot=0; + iRecipy=CanBeMadeA[m_iCurrentSlotHIndex].iRecipeA[0]; + } + + // show the 2x2 or 3x3 to make the current item + int iBoxWidth=(m_iContainerType==RECIPE_TYPE_2x2)?2:3; + int iRecipe=CanBeMadeA[m_iCurrentSlotHIndex].iRecipeA[iSlot]; + bool bCanMakeRecipe = pRecipeIngredientsRequired[iRecipe].bCanMake[getPad()]; + shared_ptr<ItemInstance> pTempItemInst=pRecipeIngredientsRequired[iRecipe].pRecipy->assemble(nullptr); + + m_iIngredientsC=pRecipeIngredientsRequired[iRecipe].iIngC; + + // update the ingredients required - these will all be hidden until cycled by the user + for(int i=0;i<pRecipeIngredientsRequired[iRecipe].iIngC;i++) + { + int id=pRecipeIngredientsRequired[iRecipe].iIngIDA[i]; + int iAuxVal=pRecipeIngredientsRequired[iRecipe].iIngAuxValA[i]; + Item *item = Item::items[id]; + if( (iAuxVal & 0xFF) == 0xFF) // 4J Stu - If the aux value is set to match any + iAuxVal = 0; + + // 4J Stu - For clocks and compasses we set the aux value to a special one that signals we should use a default texture + // rather than the dynamic one for the player + if( id == Item::clock_Id || id == Item::compass_Id ) + { + iAuxVal = 0xFF; + } + + shared_ptr<ItemInstance> itemInst= shared_ptr<ItemInstance>(new ItemInstance(item,pRecipeIngredientsRequired[iRecipe].iIngValA[i],iAuxVal)); + + setIngredientDescriptionItem(getPad(),i,itemInst); + setIngredientDescriptionRedBox(i,false); + + // 4J-PB - a very special case - the bed can use any kind of wool, so we can't use the item description + // and the same goes for the painting + int idescID; + + if( ((pTempItemInst->id==Item::bed_Id) &&(id==Tile::cloth_Id)) || + ((pTempItemInst->id==Item::painting_Id) &&(id==Tile::cloth_Id)) ) + { + idescID=IDS_ANY_WOOL; + } + else + { + idescID=itemInst->getDescriptionId(); + } + setIngredientDescriptionText(i,app.GetString(idescID)); + } + + // 4J Stu - For clocks and compasses we set the aux value to a special one that signals we should use a default texture + // rather than the dynamic one for the player + if( pTempItemInst->id == Item::clock_Id || pTempItemInst->id == Item::compass_Id ) + { + pTempItemInst->setAuxValue( 255 ); + } + + // don't grey out the output icon + setCraftingOutputSlotItem(getPad(), pTempItemInst); + + if(app.DebugSettingsOn() && app.GetGameSettingsDebugMask(ProfileManager.GetPrimaryPad())&(1L<<eDebugSetting_CraftAnything)) + { + setCraftingOutputSlotRedBox(false); + } + else + { + if(bCanMakeRecipe==false) + { + setCraftingOutputSlotRedBox(true); + } + else + { + setCraftingOutputSlotRedBox(false); + } + + } + for (int x = 0; x < iBoxWidth; x++) + { + for (int y = 0; y < iBoxWidth; y++) + { + int index = x+y*iBoxWidth; + if(pRecipeIngredientsRequired[iRecipy].uiGridA[x+y*3]!=0) + { + int id=pRecipeIngredientsRequired[iRecipy].uiGridA[x+y*3]&0x00FFFFFF; + assert(id!=0); + int iAuxVal=(pRecipeIngredientsRequired[iRecipy].uiGridA[x+y*3]&0xFF000000)>>24; + + // 4J Stu - For clocks and compasses we set the aux value to a special one that signals we should use a default texture + // rather than the dynamic one for the player + if( id == Item::clock_Id || id == Item::compass_Id ) + { + iAuxVal = 0xFF; + } + shared_ptr<ItemInstance> itemInst= shared_ptr<ItemInstance>(new ItemInstance(id,1,iAuxVal)); + setIngredientSlotItem(getPad(),index,itemInst); + // show the ingredients we don't have if we can't make the recipe + if(app.DebugSettingsOn() && app.GetGameSettingsDebugMask(ProfileManager.GetPrimaryPad())&(1L<<eDebugSetting_CraftAnything)) + { + setIngredientSlotRedBox(index, false); + } + else + { + if((pRecipeIngredientsRequired[iRecipy].usBitmaskMissingGridIngredients[getPad()]&(1<<(x+y*3)))!=0) + { + setIngredientSlotRedBox(index, true); + } + else + { + setIngredientSlotRedBox(index, false); + } + } + } + else + { + setIngredientSlotRedBox(index, false); + setIngredientSlotItem(getPad(),index,nullptr); + } + } + } + } + else + { + setCraftingOutputSlotItem(getPad(), nullptr); + setCraftingOutputSlotRedBox(false); + m_iIngredientsC=0; + int iIngredientsSlots; + // if it's a 2x2 , only clear the 4 m_pCraftingIngredientA slots + if(m_iContainerType==RECIPE_TYPE_2x2) + { + iIngredientsSlots=4; + } + else + { + iIngredientsSlots=m_iIngredients3x3SlotC; + } + + for(int i=0;i<iIngredientsSlots;i++) + { + setIngredientSlotRedBox(i, false); + setIngredientSlotItem(getPad(),i,nullptr); + } + } +} + + +////////////////////////////////////////////////////////////////////////// +// +// UpdateDescriptionText +// +////////////////////////////////////////////////////////////////////////// +void IUIScene_CraftingMenu::UpdateDescriptionText(bool bCanBeMade) +{ + int iIDSString=0; + //RecipyList *recipes = ((Recipes *)Recipes::getInstance())->getRecipies(); + Recipy::INGREDIENTS_REQUIRED *pRecipeIngredientsRequired=Recipes::getInstance()->getRecipeIngredientsArray(); + + if(bCanBeMade) + { + int iSlot;//,iRecipy; + if(CanBeMadeA[m_iCurrentSlotHIndex].iCount>1) + { + iSlot=iVSlotIndexA[m_iCurrentSlotVIndex]; + //iRecipy=CanBeMadeA[m_iCurrentSlotHIndex].iRecipeA[iSlot]; + } + else + { + iSlot=0; + //iRecipy=CanBeMadeA[m_iCurrentSlotHIndex].iRecipeA[0]; + } + + shared_ptr<ItemInstance> pTempItemInst=pRecipeIngredientsRequired[CanBeMadeA[m_iCurrentSlotHIndex].iRecipeA[iSlot]].pRecipy->assemble(nullptr); + int iID=pTempItemInst->getItem()->id; + int iAuxVal=pTempItemInst->getAuxValue(); + int iBaseType; + + if(iID<256) // is it a tile? + { + iBaseType=Tile::tiles[iID]->getBaseItemType(); + + iIDSString = Tile::tiles[iID]->getUseDescriptionId(); + } + else + { + iBaseType=pTempItemInst->getItem()->getBaseItemType(); + + iIDSString = pTempItemInst->getUseDescriptionId(); + } + + // A few special cases where the description required is specific to crafting, rather than the normal description + if(iBaseType!=Item::eBaseItemType_undefined) + { + switch(iBaseType) + { + case Item::eBaseItemType_cloth: + switch(iAuxVal) + { + case 0: + iIDSString=IDS_DESC_WOOLSTRING; + break; + } + break; + } + } + + // set the string mapped to by the base object mapping array + + if(iIDSString>=0) + { + // this is an html control now, so set the font size and colour + //wstring wsText=app.GetString(iIDSString); + wstring wsText=app.FormatHTMLString(getPad(),app.GetString(iIDSString)); + + // 12 for splitscreen, 14 for normal + EHTMLFontSize size = eHTMLSize_Normal; + if(m_bSplitscreen ||(!RenderManager.IsHiDef() && !RenderManager.IsWidescreen())) + { + size = eHTMLSize_Splitscreen; + } + wchar_t startTags[64]; + swprintf(startTags,64,L"<font color=\"#%08x\"><P ALIGN=LEFT>",app.GetHTMLColour(eHTMLColor_Black)); + wsText= startTags + wsText + L"</P>"; + + setDescriptionText(wsText.c_str()); + } + else + { + /// Missing string! +#ifdef _DEBUG + setDescriptionText(L"This is some placeholder description text about the craftable item."); +#else + setDescriptionText(L""); +#endif + } + } + else + { + setDescriptionText(L""); + } +} + +////////////////////////////////////////////////////////////////////////// +// +// UpdateTooltips +// +////////////////////////////////////////////////////////////////////////// +void IUIScene_CraftingMenu::UpdateTooltips() +{ + //RecipyList *recipes = ((Recipes *)Recipes::getInstance())->getRecipies(); + Recipy::INGREDIENTS_REQUIRED *pRecipeIngredientsRequired=Recipes::getInstance()->getRecipeIngredientsArray(); + // Update tooltips + + bool bDisplayCreate; + + if(CanBeMadeA[m_iCurrentSlotHIndex].iCount!=0) + { + int iSlot; + if(CanBeMadeA[m_iCurrentSlotHIndex].iCount>1) + { + iSlot=iVSlotIndexA[m_iCurrentSlotVIndex]; + } + else + { + iSlot=0; + } + + if(pRecipeIngredientsRequired[CanBeMadeA[m_iCurrentSlotHIndex].iRecipeA[iSlot]].bCanMake[getPad()]) + { + bDisplayCreate=true; + } + else + { + bDisplayCreate=false; + } + } + else + { + bDisplayCreate=false; + } + + + switch(m_iDisplayDescription) + { + case DISPLAY_INVENTORY: + ui.SetTooltips( getPad(), bDisplayCreate?IDS_TOOLTIPS_CREATE:-1,IDS_TOOLTIPS_EXIT, IDS_TOOLTIPS_SHOW_DESCRIPTION,-1,-1,-1,-2, IDS_TOOLTIPS_CHANGE_GROUP); + break; + case DISPLAY_DESCRIPTION: + ui.SetTooltips( getPad(), bDisplayCreate?IDS_TOOLTIPS_CREATE:-1,IDS_TOOLTIPS_EXIT, IDS_TOOLTIPS_SHOW_INGREDIENTS,-1,-1,-1,-2, IDS_TOOLTIPS_CHANGE_GROUP); + break; + case DISPLAY_INGREDIENTS: + ui.SetTooltips( getPad(), bDisplayCreate?IDS_TOOLTIPS_CREATE:-1,IDS_TOOLTIPS_EXIT, IDS_TOOLTIPS_SHOW_INVENTORY,-1,-1,-1,-2, IDS_TOOLTIPS_CHANGE_GROUP); + break; + } + + /*if(CanBeMadeA[m_iCurrentSlotHIndex].iCount!=0) + { + int iSlot; + if(CanBeMadeA[m_iCurrentSlotHIndex].iCount>1) + { + iSlot=iVSlotIndexA[m_iCurrentSlotVIndex]; + } + else + { + iSlot=0; + } + + if(pRecipeIngredientsRequired[CanBeMadeA[m_iCurrentSlotHIndex].iRecipeA[iSlot]].bCanMake[getPad()]) + { + ui.EnableTooltip( getPad(), eToolTipButtonA, true ); + } + else + { + ui.EnableTooltip( getPad(), eToolTipButtonA, false ); + } + } + else + { + ui.ShowTooltip( getPad(), eToolTipButtonA, false ); + }*/ +} + +bool IUIScene_CraftingMenu::isItemSelected(int itemId) +{ + bool isSelected = false; + if(m_pPlayer && m_pPlayer->inventory) + { + //RecipyList *recipes = ((Recipes *)Recipes::getInstance())->getRecipies(); + Recipy::INGREDIENTS_REQUIRED *pRecipeIngredientsRequired=Recipes::getInstance()->getRecipeIngredientsArray(); + + if(CanBeMadeA[m_iCurrentSlotHIndex].iCount!=0) + { + int iSlot; + if(CanBeMadeA[m_iCurrentSlotHIndex].iCount>1) + { + iSlot=iVSlotIndexA[m_iCurrentSlotVIndex]; + } + else + { + iSlot=0; + } + int iRecipe= CanBeMadeA[m_iCurrentSlotHIndex].iRecipeA[iSlot]; + ItemInstance *pTempItemInst = (ItemInstance *)pRecipeIngredientsRequired[iRecipe].pRecipy->getResultItem(); + + if(pTempItemInst->id == itemId) + { + isSelected = true; + } + } + } + return isSelected; +} diff --git a/Minecraft.Client/Common/UI/IUIScene_CraftingMenu.h b/Minecraft.Client/Common/UI/IUIScene_CraftingMenu.h new file mode 100644 index 00000000..05227fff --- /dev/null +++ b/Minecraft.Client/Common/UI/IUIScene_CraftingMenu.h @@ -0,0 +1,119 @@ +#pragma once +#include "..\..\..\Minecraft.World\Recipy.h" +#include "..\..\..\Minecraft.World\Item.h" + +class LocalPlayer; + +// 4J Stu - Crafting menu code that's shared across Iggy and XUI +class IUIScene_CraftingMenu +{ +protected: +#define DISPLAY_INVENTORY 0 +#define DISPLAY_DESCRIPTION 1 +#define DISPLAY_INGREDIENTS 2 +#define DISPLAY_MAX 3 + + enum _eGroupTab + { + eGroupTab_Left, + eGroupTab_Middle, + eGroupTab_Right + }; + + static const int m_iMaxHSlotC = 12; + static const int m_iMaxHCraftingSlotC = 10; + static const int m_iMaxVSlotC = 17; + static const int m_iMaxDisplayedVSlotC = 3; + static const int m_iIngredients3x3SlotC = 9; + static const int m_iIngredients2x2SlotC = 4; + + static const int m_iMaxHSlot3x3C = 12; + static const int m_iMaxHSlot2x2C = 10; + + static const int m_iMaxGroup3x3 = 7; + static const int m_iMaxGroup2x2 = 6; + + static int m_iBaseTypeMapA[Item::eBaseItemType_MAXTYPES]; + + typedef struct + { + int iCount; + int iItemBaseType; + int iRecipeA[m_iMaxVSlotC]; // tiers of item that can be made + } + CANBEMADE; + + CANBEMADE CanBeMadeA[m_iMaxHSlotC]; + + int m_iCurrentSlotHIndex; + int m_iCurrentSlotVIndex; + int m_iRecipeC; + int m_iContainerType; // 2x2 or 3x3 + shared_ptr<LocalPlayer> m_pPlayer; + int m_iGroupIndex; + + int iVSlotIndexA[3]; // index of the v slots currently displayed + + static LPCWSTR m_GroupIconNameA[m_iMaxGroup3x3]; + static Recipy::_eGroupType m_GroupTypeMapping4GridA[m_iMaxGroup2x2]; + static Recipy::_eGroupType m_GroupTypeMapping9GridA[m_iMaxGroup3x3]; + Recipy::_eGroupType *m_pGroupA; + + static LPCWSTR m_GroupTabNameA[3]; + static _eGroupTab m_GroupTabBkgMapping2x2A[m_iMaxGroup2x2]; + static _eGroupTab m_GroupTabBkgMapping3x3A[m_iMaxGroup3x3]; + _eGroupTab *m_pGroupTabA; + int m_iCraftablesMaxHSlotC; + int m_iIngredientsMaxSlotC; + int m_iDisplayDescription; + int m_iIngredientsC; + bool m_bIgnoreKeyPresses; + bool m_bSplitscreen; + + eTutorial_State m_previousTutorialState; + + bool handleKeyDown(int iPad, int iAction, bool bRepeat); + +public: + IUIScene_CraftingMenu(); + +protected: + LPCWSTR GetGroupNameText(int iGroupType); + + void CheckRecipesAvailable(); + void UpdateHighlight(); + void UpdateVerticalSlots(); + void DisplayIngredients(); + void UpdateTooltips(); + void UpdateDescriptionText(bool); + +public: + Recipy::_eGroupType getCurrentGroup() { return m_pGroupA[m_iGroupIndex]; } + bool isItemSelected(int itemId); + +protected: + virtual int getPad() = 0; + virtual void hideAllHSlots() = 0; + virtual void hideAllVSlots() = 0; + virtual void hideAllIngredientsSlots() = 0; + virtual void setCraftHSlotItem(int iPad, int iIndex, shared_ptr<ItemInstance> item, unsigned int uiAlpha) = 0; + virtual void setCraftVSlotItem(int iPad, int iIndex, shared_ptr<ItemInstance> item, unsigned int uiAlpha) = 0; + virtual void setCraftingOutputSlotItem(int iPad, shared_ptr<ItemInstance> item) = 0; + virtual void setCraftingOutputSlotRedBox(bool show) = 0; + virtual void setIngredientSlotItem(int iPad, int index, shared_ptr<ItemInstance> item) = 0; + virtual void setIngredientSlotRedBox(int index, bool show) = 0; + virtual void setIngredientDescriptionItem(int iPad, int index, shared_ptr<ItemInstance> item) = 0; + virtual void setIngredientDescriptionRedBox(int index, bool show) = 0; + virtual void setIngredientDescriptionText(int index, LPCWSTR text) = 0; + virtual void setShowCraftHSlot(int iIndex, bool show) = 0; + virtual void showTabHighlight(int iIndex, bool show) = 0; + virtual void setGroupText(LPCWSTR text) = 0; + virtual void setDescriptionText(LPCWSTR text) = 0; + virtual void setItemText(LPCWSTR text) = 0; + virtual void scrollDescriptionUp() = 0; + virtual void scrollDescriptionDown() = 0; + virtual void updateHighlightAndScrollPositions() = 0; + virtual void updateVSlotPositions(int iSlots, int i) = 0; + + virtual void UpdateMultiPanel() = 0; +};
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/IUIScene_CreativeMenu.cpp b/Minecraft.Client/Common/UI/IUIScene_CreativeMenu.cpp new file mode 100644 index 00000000..7ce33234 --- /dev/null +++ b/Minecraft.Client/Common/UI/IUIScene_CreativeMenu.cpp @@ -0,0 +1,1053 @@ +#include "stdafx.h" +#include "IUIScene_CreativeMenu.h" + +#include "..\..\Minecraft.h" +#include "..\..\MultiplayerLocalPlayer.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.inventory.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.level.tile.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.level.tile.entity.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.item.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.item.enchantment.h" + +// 4J JEV - Images for each tab. +IUIScene_CreativeMenu::TabSpec **IUIScene_CreativeMenu::specs = NULL; + +vector< shared_ptr<ItemInstance> > IUIScene_CreativeMenu::categoryGroups[eCreativeInventoryGroupsCount]; + +#define ITEM(id) list->push_back( shared_ptr<ItemInstance>(new ItemInstance(id, 1, 0)) ); +#define ITEM_AUX(id, aux) list->push_back( shared_ptr<ItemInstance>(new ItemInstance(id, 1, aux)) ); +#define DEF(index) list = &categoryGroups[index]; + + +void IUIScene_CreativeMenu::staticCtor() +{ + vector< shared_ptr<ItemInstance> > *list; + + + // Building Blocks + DEF(eCreativeInventory_BuildingBlocks) + ITEM(Tile::rock_Id) + ITEM(Tile::grass_Id) + ITEM(Tile::dirt_Id) + ITEM(Tile::stoneBrick_Id) + ITEM(Tile::sand_Id) + ITEM(Tile::sandStone_Id) + ITEM_AUX(Tile::sandStone_Id, SandStoneTile::TYPE_SMOOTHSIDE) + ITEM_AUX(Tile::sandStone_Id, SandStoneTile::TYPE_HEIROGLYPHS) + ITEM(Tile::goldBlock_Id) + ITEM(Tile::ironBlock_Id) + ITEM(Tile::lapisBlock_Id) + ITEM(Tile::diamondBlock_Id) + ITEM(Tile::emeraldBlock_Id) + ITEM_AUX(Tile::quartzBlock_Id,QuartzBlockTile::TYPE_DEFAULT) + ITEM(Tile::coalOre_Id) + ITEM(Tile::lapisOre_Id) + ITEM(Tile::diamondOre_Id) + ITEM(Tile::redStoneOre_Id) + ITEM(Tile::ironOre_Id) + ITEM(Tile::goldOre_Id) + ITEM(Tile::emeraldOre_Id) + ITEM(Tile::netherQuartz_Id) + ITEM(Tile::unbreakable_Id) + ITEM_AUX(Tile::wood_Id,0) + ITEM_AUX(Tile::wood_Id,TreeTile::DARK_TRUNK) + ITEM_AUX(Tile::wood_Id,TreeTile::BIRCH_TRUNK) + ITEM_AUX(Tile::wood_Id,TreeTile::JUNGLE_TRUNK) + ITEM_AUX(Tile::treeTrunk_Id, 0) + ITEM_AUX(Tile::treeTrunk_Id, TreeTile::DARK_TRUNK) + ITEM_AUX(Tile::treeTrunk_Id, TreeTile::BIRCH_TRUNK) + ITEM_AUX(Tile::treeTrunk_Id, TreeTile::JUNGLE_TRUNK) + ITEM(Tile::gravel_Id) + ITEM(Tile::redBrick_Id) + ITEM(Tile::mossStone_Id) + ITEM(Tile::obsidian_Id) + ITEM(Tile::clay) + ITEM(Tile::ice_Id) + ITEM(Tile::snow_Id) + ITEM(Tile::hellRock_Id) + ITEM(Tile::hellSand_Id) + ITEM(Tile::lightGem_Id) + ITEM_AUX(Tile::stoneBrickSmooth_Id,SmoothStoneBrickTile::TYPE_DEFAULT) + ITEM_AUX(Tile::stoneBrickSmooth_Id,SmoothStoneBrickTile::TYPE_MOSSY) + ITEM_AUX(Tile::stoneBrickSmooth_Id,SmoothStoneBrickTile::TYPE_CRACKED) + ITEM_AUX(Tile::stoneBrickSmooth_Id,SmoothStoneBrickTile::TYPE_DETAIL) + ITEM_AUX(Tile::monsterStoneEgg_Id,StoneMonsterTile::HOST_ROCK) + ITEM_AUX(Tile::monsterStoneEgg_Id,StoneMonsterTile::HOST_COBBLE) + ITEM_AUX(Tile::monsterStoneEgg_Id,StoneMonsterTile::HOST_STONEBRICK) + ITEM(Tile::mycel_Id) + ITEM(Tile::netherBrick_Id) + ITEM(Tile::whiteStone_Id) + ITEM_AUX(Tile::quartzBlock_Id,QuartzBlockTile::TYPE_CHISELED) + ITEM_AUX(Tile::quartzBlock_Id,QuartzBlockTile::TYPE_LINES_Y) + ITEM(Tile::trapdoor_Id) + ITEM(Tile::fenceGate_Id) + ITEM(Item::door_wood_Id) + ITEM(Item::door_iron_Id) + ITEM_AUX(Tile::stoneSlabHalf_Id,StoneSlabTile::STONE_SLAB) + ITEM_AUX(Tile::stoneSlabHalf_Id,StoneSlabTile::SAND_SLAB) + // AP - changed oak slab to be wood because it wouldn't burn +// ITEM_AUX(Tile::stoneSlabHalf_Id,StoneSlabTile::WOOD_SLAB) + ITEM_AUX(Tile::woodSlabHalf_Id,0) + ITEM_AUX(Tile::woodSlabHalf_Id,TreeTile::DARK_TRUNK) + ITEM_AUX(Tile::woodSlabHalf_Id,TreeTile::BIRCH_TRUNK) + ITEM_AUX(Tile::woodSlabHalf_Id,TreeTile::JUNGLE_TRUNK) + ITEM_AUX(Tile::stoneSlabHalf_Id,StoneSlabTile::COBBLESTONE_SLAB) + ITEM_AUX(Tile::stoneSlabHalf_Id,StoneSlabTile::BRICK_SLAB) + ITEM_AUX(Tile::stoneSlabHalf_Id,StoneSlabTile::SMOOTHBRICK_SLAB) + ITEM_AUX(Tile::stoneSlabHalf_Id,StoneSlabTile::NETHERBRICK_SLAB) + ITEM_AUX(Tile::stoneSlabHalf_Id,StoneSlabTile::QUARTZ_SLAB) + ITEM(Tile::stairs_wood_Id) + ITEM(Tile::stairs_birchwood_Id) + ITEM(Tile::stairs_sprucewood_Id) + ITEM(Tile::stairs_junglewood_Id) + ITEM(Tile::stairs_stone_Id) + ITEM(Tile::stairs_bricks_Id) + ITEM(Tile::stairs_stoneBrickSmooth_Id) + ITEM(Tile::stairs_netherBricks_Id) + ITEM(Tile::stairs_sandstone_Id) + ITEM(Tile::stairs_quartz_Id) + + + // Decoration + DEF(eCreativeInventory_Decoration) + ITEM_AUX(Item::skull_Id,SkullTileEntity::TYPE_SKELETON) + ITEM_AUX(Item::skull_Id,SkullTileEntity::TYPE_WITHER) + ITEM_AUX(Item::skull_Id,SkullTileEntity::TYPE_ZOMBIE) + ITEM_AUX(Item::skull_Id,SkullTileEntity::TYPE_CHAR) + ITEM_AUX(Item::skull_Id,SkullTileEntity::TYPE_CREEPER) + ITEM(Tile::sponge_Id) + ITEM(Tile::melon_Id) + ITEM(Tile::pumpkin_Id) + ITEM(Tile::litPumpkin_Id) + ITEM_AUX(Tile::sapling_Id, Sapling::TYPE_DEFAULT) + ITEM_AUX(Tile::sapling_Id, Sapling::TYPE_EVERGREEN) + ITEM_AUX(Tile::sapling_Id, Sapling::TYPE_BIRCH) + ITEM_AUX(Tile::sapling_Id, Sapling::TYPE_JUNGLE) + ITEM_AUX(Tile::leaves_Id, LeafTile::NORMAL_LEAF) + ITEM_AUX(Tile::leaves_Id, LeafTile::EVERGREEN_LEAF) + ITEM_AUX(Tile::leaves_Id, LeafTile::BIRCH_LEAF) + ITEM_AUX(Tile::leaves_Id, LeafTile::JUNGLE_LEAF) + ITEM(Tile::vine) + ITEM(Tile::waterLily_Id) + ITEM(Tile::torch_Id) + ITEM_AUX(Tile::tallgrass_Id, TallGrass::DEAD_SHRUB) + ITEM_AUX(Tile::tallgrass_Id, TallGrass::TALL_GRASS) + ITEM_AUX(Tile::tallgrass_Id, TallGrass::FERN) + ITEM(Tile::deadBush_Id) + ITEM(Tile::flower_Id) + ITEM(Tile::rose_Id) + ITEM(Tile::mushroom1_Id) + ITEM(Tile::mushroom2_Id) + ITEM(Tile::cactus_Id) + ITEM(Tile::topSnow_Id) + // 4J-PB - Already got sugar cane in Materials ITEM_11(Tile::reeds_Id) + ITEM(Tile::web_Id) + ITEM(Tile::thinGlass_Id) + ITEM(Tile::glass_Id) + ITEM(Item::painting_Id) + ITEM(Item::itemFrame_Id) + ITEM(Item::sign_Id) + ITEM(Tile::bookshelf_Id) + ITEM(Item::flowerPot_Id) + ITEM_AUX(Tile::cloth_Id,14) // Red + ITEM_AUX(Tile::cloth_Id,1) // Orange + ITEM_AUX(Tile::cloth_Id,4) // Yellow + ITEM_AUX(Tile::cloth_Id,5) // Lime + ITEM_AUX(Tile::cloth_Id,3) // Light Blue + ITEM_AUX(Tile::cloth_Id,9) // Cyan + ITEM_AUX(Tile::cloth_Id,11) // Blue + ITEM_AUX(Tile::cloth_Id,10) // Purple + ITEM_AUX(Tile::cloth_Id,2) // Magenta + ITEM_AUX(Tile::cloth_Id,6) // Pink + ITEM_AUX(Tile::cloth_Id,0) // White + ITEM_AUX(Tile::cloth_Id,8) // Light Gray + ITEM_AUX(Tile::cloth_Id,7) // Gray + ITEM_AUX(Tile::cloth_Id,15) // Black + ITEM_AUX(Tile::cloth_Id,13) // Green + ITEM_AUX(Tile::cloth_Id,12) // Brown + + ITEM_AUX(Tile::woolCarpet_Id,14) // Red + ITEM_AUX(Tile::woolCarpet_Id,1) // Orange + ITEM_AUX(Tile::woolCarpet_Id,4) // Yellow + ITEM_AUX(Tile::woolCarpet_Id,5) // Lime + ITEM_AUX(Tile::woolCarpet_Id,3) // Light Blue + ITEM_AUX(Tile::woolCarpet_Id,9) // Cyan + ITEM_AUX(Tile::woolCarpet_Id,11) // Blue + ITEM_AUX(Tile::woolCarpet_Id,10) // Purple + ITEM_AUX(Tile::woolCarpet_Id,2) // Magenta + ITEM_AUX(Tile::woolCarpet_Id,6) // Pink + ITEM_AUX(Tile::woolCarpet_Id,0) // White + ITEM_AUX(Tile::woolCarpet_Id,8) // Light Gray + ITEM_AUX(Tile::woolCarpet_Id,7) // Gray + ITEM_AUX(Tile::woolCarpet_Id,15) // Black + ITEM_AUX(Tile::woolCarpet_Id,13) // Green + ITEM_AUX(Tile::woolCarpet_Id,12) // Brown + + + // Redstone + DEF(eCreativeInventory_Redstone) + ITEM(Tile::dispenser_Id) + ITEM(Tile::musicBlock_Id) + ITEM(Tile::pistonBase_Id) + ITEM(Tile::pistonStickyBase_Id) + ITEM(Tile::tnt_Id) + ITEM(Tile::lever_Id) + ITEM(Tile::button_stone_Id) + ITEM(Tile::button_wood_Id) + ITEM(Tile::pressurePlate_stone_Id) + ITEM(Tile::pressurePlate_wood_Id) + ITEM(Item::redStone_Id) + ITEM(Tile::notGate_on_Id) + ITEM(Item::diode_Id) + ITEM(Tile::redstoneLight_Id) + ITEM(Tile::tripWireSource_Id) + + // Transport + DEF(eCreativeInventory_Transport) + ITEM(Tile::rail_Id) + ITEM(Tile::goldenRail_Id) + ITEM(Tile::detectorRail_Id) + ITEM(Tile::ladder_Id) + ITEM(Item::minecart_Id) + ITEM(Item::minecart_chest_Id) + ITEM(Item::minecart_furnace_Id) + ITEM(Item::saddle_Id) + ITEM(Item::boat_Id) + + // Miscellaneous + DEF(eCreativeInventory_Misc) + ITEM(Tile::chest_Id) + ITEM(Tile::enderChest_Id) + ITEM(Tile::workBench_Id) + ITEM(Tile::furnace_Id) + ITEM(Item::brewingStand_Id) + ITEM(Tile::enchantTable_Id) + ITEM(Tile::endPortalFrameTile_Id) + ITEM(Tile::recordPlayer_Id) + ITEM(Tile::anvil_Id); + ITEM(Tile::fence_Id) + ITEM(Tile::netherFence_Id) + ITEM(Tile::ironFence_Id) + ITEM_AUX(Tile::cobbleWall_Id, WallTile::TYPE_NORMAL) + ITEM_AUX(Tile::cobbleWall_Id, WallTile::TYPE_MOSSY) + ITEM(Item::bed_Id) + ITEM(Item::bucket_empty_Id) + ITEM(Item::bucket_lava_Id) + ITEM(Item::bucket_water_Id) + ITEM(Item::milk_Id) + ITEM(Item::cauldron_Id) + ITEM(Item::snowBall_Id) + ITEM(Item::paper_Id) + ITEM(Item::book_Id) + ITEM(Item::enderPearl_Id) + ITEM(Item::eyeOfEnder_Id) + ITEM(Item::record_01_Id) + ITEM(Item::record_02_Id) + ITEM(Item::record_03_Id) + ITEM(Item::record_04_Id) + ITEM(Item::record_05_Id) + ITEM(Item::record_06_Id) + ITEM(Item::record_07_Id) + ITEM(Item::record_08_Id) + ITEM(Item::record_09_Id) + ITEM(Item::record_10_Id) + ITEM(Item::record_11_Id) + ITEM(Item::record_12_Id) + ITEM_AUX(Item::monsterPlacer_Id, 50); // Creeper + ITEM_AUX(Item::monsterPlacer_Id, 51); // Skeleton + ITEM_AUX(Item::monsterPlacer_Id, 52); // Spider + ITEM_AUX(Item::monsterPlacer_Id, 54); // Zombie + ITEM_AUX(Item::monsterPlacer_Id, 55); // Slime + ITEM_AUX(Item::monsterPlacer_Id, 56); // Ghast + ITEM_AUX(Item::monsterPlacer_Id, 57); // Zombie Pigman + ITEM_AUX(Item::monsterPlacer_Id, 58); // Enderman + ITEM_AUX(Item::monsterPlacer_Id, 59); // Cave Spider + ITEM_AUX(Item::monsterPlacer_Id, 60); // Silverfish + ITEM_AUX(Item::monsterPlacer_Id, 61); // Blaze + ITEM_AUX(Item::monsterPlacer_Id, 62); // Magma Cube + ITEM_AUX(Item::monsterPlacer_Id, 90); // Pig + ITEM_AUX(Item::monsterPlacer_Id, 91); // Sheep + ITEM_AUX(Item::monsterPlacer_Id, 92); // Cow + ITEM_AUX(Item::monsterPlacer_Id, 93); // Chicken + ITEM_AUX(Item::monsterPlacer_Id, 94); // Squid + ITEM_AUX(Item::monsterPlacer_Id, 95); // Wolf + ITEM_AUX(Item::monsterPlacer_Id, 96); // Mooshroom + ITEM_AUX(Item::monsterPlacer_Id, 98); // Ozelot + ITEM_AUX(Item::monsterPlacer_Id, 120); // Villager + + // Food + DEF(eCreativeInventory_Food) + ITEM(Item::apple_Id) + ITEM(Item::apple_gold_Id) + ITEM_AUX(Item::apple_gold_Id,1) // Enchanted + ITEM(Item::melon_Id) + ITEM(Item::mushroomStew_Id) + ITEM(Item::bread_Id) + ITEM(Item::cake_Id) + ITEM(Item::cookie_Id) + ITEM(Item::fish_cooked_Id) + ITEM(Item::fish_raw_Id) + ITEM(Item::porkChop_cooked_Id) + ITEM(Item::porkChop_raw_Id) + ITEM(Item::beef_cooked_Id) + ITEM(Item::beef_raw_Id) + ITEM(Item::chicken_raw_Id) + ITEM(Item::chicken_cooked_Id) + ITEM(Item::rotten_flesh_Id) + ITEM(Item::spiderEye_Id) + ITEM(Item::potato_Id) + ITEM(Item::potatoBaked_Id) + ITEM(Item::potatoPoisonous_Id) + ITEM(Item::carrots_Id) + ITEM(Item::carrotGolden_Id) + ITEM(Item::pumpkinPie_Id) + + // Tools, Armour and Weapons (Complete) + DEF(eCreativeInventory_ToolsArmourWeapons) + ITEM(Item::compass_Id) + ITEM(Item::helmet_cloth_Id) + ITEM(Item::chestplate_cloth_Id) + ITEM(Item::leggings_cloth_Id) + ITEM(Item::boots_cloth_Id) + ITEM(Item::sword_wood_Id) + ITEM(Item::shovel_wood_Id) + ITEM(Item::pickAxe_wood_Id) + ITEM(Item::hatchet_wood_Id) + ITEM(Item::hoe_wood_Id) + + ITEM(Item::map_Id) + ITEM(Item::helmet_chain_Id) + ITEM(Item::chestplate_chain_Id) + ITEM(Item::leggings_chain_Id) + ITEM(Item::boots_chain_Id) + ITEM(Item::sword_stone_Id) + ITEM(Item::shovel_stone_Id) + ITEM(Item::pickAxe_stone_Id) + ITEM(Item::hatchet_stone_Id) + ITEM(Item::hoe_stone_Id) + + ITEM(Item::bow_Id) + ITEM(Item::helmet_iron_Id) + ITEM(Item::chestplate_iron_Id) + ITEM(Item::leggings_iron_Id) + ITEM(Item::boots_iron_Id) + ITEM(Item::sword_iron_Id) + ITEM(Item::shovel_iron_Id) + ITEM(Item::pickAxe_iron_Id) + ITEM(Item::hatchet_iron_Id) + ITEM(Item::hoe_iron_Id) + + ITEM(Item::arrow_Id) + ITEM(Item::helmet_gold_Id) + ITEM(Item::chestplate_gold_Id) + ITEM(Item::leggings_gold_Id) + ITEM(Item::boots_gold_Id) + ITEM(Item::sword_gold_Id) + ITEM(Item::shovel_gold_Id) + ITEM(Item::pickAxe_gold_Id) + ITEM(Item::hatchet_gold_Id) + ITEM(Item::hoe_gold_Id) + + ITEM(Item::flintAndSteel_Id) + ITEM(Item::helmet_diamond_Id) + ITEM(Item::chestplate_diamond_Id) + ITEM(Item::leggings_diamond_Id) + ITEM(Item::boots_diamond_Id) + ITEM(Item::sword_diamond_Id) + ITEM(Item::shovel_diamond_Id) + ITEM(Item::pickAxe_diamond_Id) + ITEM(Item::hatchet_diamond_Id) + ITEM(Item::hoe_diamond_Id) + + ITEM(Item::fireball_Id) + ITEM(Item::clock_Id) + ITEM(Item::shears_Id) + ITEM(Item::fishingRod_Id) + ITEM(Item::carrotOnAStick_Id) + + for(unsigned int i = 0; i < Enchantment::enchantments.length; ++i) + { + Enchantment *enchantment = Enchantment::enchantments[i]; + if (enchantment == NULL || enchantment->category == NULL) continue; + list->push_back(Item::enchantedBook->createForEnchantment(new EnchantmentInstance(enchantment, enchantment->getMaxLevel()))); + } + + // Materials + DEF(eCreativeInventory_Materials) + ITEM(Item::coal_Id) + ITEM_AUX(Item::coal_Id,1) + ITEM(Item::diamond_Id) + ITEM(Item::emerald_Id) + ITEM(Item::ironIngot_Id) + ITEM(Item::goldIngot_Id) + ITEM(Item::netherQuartz_Id) + ITEM(Item::brick_Id) + ITEM(Item::netherbrick_Id) + ITEM(Item::stick_Id) + ITEM(Item::bowl_Id) + ITEM(Item::bone_Id) + ITEM(Item::string_Id) + ITEM(Item::feather_Id) + ITEM(Item::flint_Id) + ITEM(Item::leather_Id) + ITEM(Item::sulphur_Id) + ITEM(Item::clay_Id) + ITEM(Item::yellowDust_Id) + ITEM(Item::seeds_wheat_Id) + ITEM(Item::seeds_melon_Id) + ITEM(Item::seeds_pumpkin_Id) + ITEM(Item::wheat_Id) + ITEM(Item::reeds_Id) + ITEM(Item::egg_Id) + ITEM(Item::sugar_Id) + ITEM(Item::slimeBall_Id) + ITEM(Item::blazeRod_Id) + ITEM(Item::goldNugget_Id) + ITEM(Item::netherStalkSeeds_Id) + ITEM_AUX(Item::dye_powder_Id,1) // Red + ITEM_AUX(Item::dye_powder_Id,14) // Orange + ITEM_AUX(Item::dye_powder_Id,11) // Yellow + ITEM_AUX(Item::dye_powder_Id,10) // Lime + ITEM_AUX(Item::dye_powder_Id,12) // Light Blue + ITEM_AUX(Item::dye_powder_Id,6) // Cyan + ITEM_AUX(Item::dye_powder_Id,4) // Blue + ITEM_AUX(Item::dye_powder_Id,5) // Purple + ITEM_AUX(Item::dye_powder_Id,13) // Magenta + ITEM_AUX(Item::dye_powder_Id,9) // Pink + ITEM_AUX(Item::dye_powder_Id,15) // Bone Meal + ITEM_AUX(Item::dye_powder_Id,7) // Light gray + ITEM_AUX(Item::dye_powder_Id,8) // Gray + ITEM_AUX(Item::dye_powder_Id,0) // black (ink sac) + ITEM_AUX(Item::dye_powder_Id,2) // Green + ITEM_AUX(Item::dye_powder_Id,3) // Brown + + // Brewing (TODO) + DEF(eCreativeInventory_Brewing) + ITEM(Item::expBottle_Id) + + // 4J Stu - Anything else added here also needs to be added to the key handler below + ITEM(Item::ghastTear_Id) + ITEM(Item::fermentedSpiderEye_Id) + ITEM(Item::blazePowder_Id) + ITEM(Item::magmaCream_Id) + ITEM(Item::speckledMelon_Id) + ITEM(Item::glassBottle_Id) + ITEM_AUX(Item::potion_Id,0) // Water bottle + //ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(0, 0, MASK_TYPE_AWKWARD)) // Awkward Potion + + + DEF(eCreativeInventory_Potions_Basic) + ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(0, 0, MASK_REGENERATION)) + ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(0, 0, MASK_SPEED)) + //ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(0, 0, MASK_FIRE_RESISTANCE)) + ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(0, 0, MASK_POISON)) + ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(0, 0, MASK_INSTANTHEALTH)) + //ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(0, 0, MASK_WEAKNESS)) + ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(0, 0, MASK_STRENGTH)) + //ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(0, 0, MASK_SLOWNESS)) + ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(0, 0, MASK_INSTANTDAMAGE)) + ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(MASK_SPLASH, 0, MASK_REGENERATION)) + ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(MASK_SPLASH, 0, MASK_SPEED)) + //ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(MASK_SPLASH, 0, MASK_FIRE_RESISTANCE)) + ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(MASK_SPLASH, 0, MASK_POISON)) + ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(MASK_SPLASH, 0, MASK_INSTANTHEALTH)) + //ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(MASK_SPLASH, 0, MASK_WEAKNESS)) + ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(MASK_SPLASH, 0, MASK_STRENGTH)) + //ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(MASK_SPLASH, 0, MASK_SLOWNESS)) + ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(MASK_SPLASH, 0, MASK_INSTANTDAMAGE)) + + DEF(eCreativeInventory_Potions_Level2) + ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(0, MASK_LEVEL2, MASK_REGENERATION)) + ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(0, MASK_LEVEL2, MASK_SPEED)) + ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(0, 0, MASK_FIRE_RESISTANCE)) + ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(0, MASK_LEVEL2, MASK_POISON)) + //ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(0, MASK_LEVEL2, MASK_INSTANTHEALTH)) + //ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(0, MASK_LEVEL2, MASK_NIGHTVISION)) + //ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(0, MASK_LEVEL2, MASK_INVISIBILITY)) + + ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(0, 0, MASK_WEAKNESS)) + ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(0, MASK_LEVEL2, MASK_STRENGTH)) + ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(0, 0, MASK_SLOWNESS)) + //ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(0, MASK_LEVEL2, MASK_INSTANTDAMAGE)) + ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(MASK_SPLASH, MASK_LEVEL2, MASK_REGENERATION)) + ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(MASK_SPLASH, MASK_LEVEL2, MASK_SPEED)) + ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(MASK_SPLASH, 0, MASK_FIRE_RESISTANCE)) + ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(MASK_SPLASH, MASK_LEVEL2, MASK_POISON)) + //ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(MASK_SPLASH, MASK_LEVEL2, MASK_INSTANTHEALTH)) + //ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(MASK_SPLASH, MASK_LEVEL2, MASK_NIGHTVISION)) + //ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(MASK_SPLASH, MASK_LEVEL2, MASK_INVISIBILITY)) + ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(MASK_SPLASH, 0, MASK_WEAKNESS)) + ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(MASK_SPLASH, MASK_LEVEL2, MASK_STRENGTH)) + ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(MASK_SPLASH, 0, MASK_SLOWNESS)) + //ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(MASK_SPLASH, MASK_LEVEL2, MASK_INSTANTDAMAGE)) + + DEF(eCreativeInventory_Potions_Extended) + ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(0, MASK_EXTENDED, MASK_REGENERATION)) + ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(0, MASK_EXTENDED, MASK_SPEED)) + //ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(0, MASK_EXTENDED, MASK_FIRE_RESISTANCE)) + ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(0, MASK_EXTENDED, MASK_POISON)) + //ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(0, MASK_LEVEL2, MASK_INSTANTHEALTH)) + ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(0, 0, MASK_NIGHTVISION)) // 4J- Moved here as there isn't a weak variant of this potion. + ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(0, 0, MASK_INVISIBILITY)) // 4J- Moved here as there isn't a weak variant of this potion. + //ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(0, MASK_EXTENDED, MASK_WEAKNESS)) + ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(0, MASK_EXTENDED, MASK_STRENGTH)) + //ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(0, MASK_EXTENDED, MASK_SLOWNESS)) + //ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(0, MASK_LEVEL2, MASK_INSTANTDAMAGE)) + ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(MASK_SPLASH, MASK_EXTENDED, MASK_REGENERATION)) + ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(MASK_SPLASH, MASK_EXTENDED, MASK_SPEED)) + //ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(MASK_SPLASH, MASK_EXTENDED, MASK_FIRE_RESISTANCE)) + ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(MASK_SPLASH, MASK_EXTENDED, MASK_POISON)) + //ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(MASK_SPLASH, MASK_LEVEL2, MASK_INSTANTHEALTH)) + ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(MASK_SPLASH, 0, MASK_NIGHTVISION)) // 4J- Moved here as there isn't a weak variant of this potion. + ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(MASK_SPLASH, 0, MASK_INVISIBILITY)) // 4J- Moved here as there isn't a weak variant of this potion. + //ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(MASK_SPLASH, MASK_EXTENDED, MASK_WEAKNESS)) + ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(MASK_SPLASH, MASK_EXTENDED, MASK_STRENGTH)) + //ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(MASK_SPLASH, MASK_EXTENDED, MASK_SLOWNESS)) + //ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(MASK_SPLASH, MASK_LEVEL2, MASK_INSTANTDAMAGE)) + + DEF(eCreativeInventory_Potions_Level2_Extended) + ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(0, MASK_LEVEL2EXTENDED, MASK_REGENERATION)) + ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(0, MASK_LEVEL2EXTENDED, MASK_SPEED)) + ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(0, MASK_EXTENDED, MASK_FIRE_RESISTANCE)) + ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(0, MASK_LEVEL2EXTENDED, MASK_POISON)) + ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(0, MASK_LEVEL2, MASK_INSTANTHEALTH)) + //ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(0, MASK_LEVEL2EXTENDED, MASK_NIGHTVISION)) + //ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(0, MASK_LEVEL2EXTENDED, MASK_INVISIBILITY)) + ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(0, MASK_EXTENDED, MASK_NIGHTVISION)) // 4J- Moved here as there isn't a weak variant of this potion. + ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(0, MASK_EXTENDED, MASK_INVISIBILITY)) // 4J- Moved here as there isn't a weak variant of this potion. + ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(0, MASK_EXTENDED, MASK_WEAKNESS)) + ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(0, MASK_LEVEL2EXTENDED, MASK_STRENGTH)) + ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(0, MASK_EXTENDED, MASK_SLOWNESS)) + ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(0, MASK_LEVEL2, MASK_INSTANTDAMAGE)) + ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(MASK_SPLASH, MASK_LEVEL2EXTENDED, MASK_REGENERATION)) + ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(MASK_SPLASH, MASK_LEVEL2EXTENDED, MASK_SPEED)) + ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(MASK_SPLASH, MASK_EXTENDED, MASK_FIRE_RESISTANCE)) + ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(MASK_SPLASH, MASK_LEVEL2EXTENDED, MASK_POISON)) + ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(MASK_SPLASH, MASK_LEVEL2, MASK_INSTANTHEALTH)) + //ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(MASK_SPLASH, MASK_LEVEL2EXTENDED, MASK_NIGHTVISION)) + //ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(MASK_SPLASH, MASK_LEVEL2EXTENDED, MASK_INVISIBILITY)) + ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(MASK_SPLASH, MASK_EXTENDED, MASK_NIGHTVISION)) // 4J- Moved here as there isn't a weak variant of this potion. + ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(MASK_SPLASH, MASK_EXTENDED, MASK_INVISIBILITY)) // 4J- Moved here as there isn't a weak variant of this potion. + ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(MASK_SPLASH, MASK_EXTENDED, MASK_WEAKNESS)) + ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(MASK_SPLASH, MASK_LEVEL2EXTENDED, MASK_STRENGTH)) + ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(MASK_SPLASH, MASK_EXTENDED, MASK_SLOWNESS)) + ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(MASK_SPLASH, MASK_LEVEL2, MASK_INSTANTDAMAGE)) + + + specs = new TabSpec*[eCreativeInventoryTab_COUNT]; + + // Top Row + ECreative_Inventory_Groups blocksGroup[] = {eCreativeInventory_BuildingBlocks}; + specs[eCreativeInventoryTab_BuildingBlocks] = new TabSpec(L"Structures", IDS_GROUPNAME_BUILDING_BLOCKS, 1, blocksGroup, 0, NULL); + + ECreative_Inventory_Groups decorationsGroup[] = {eCreativeInventory_Decoration}; + specs[eCreativeInventoryTab_Decorations] = new TabSpec(L"Decoration", IDS_GROUPNAME_DECORATIONS, 1, decorationsGroup, 0, NULL); + + ECreative_Inventory_Groups redAndTranGroup[] = {eCreativeInventory_Transport, eCreativeInventory_Redstone}; + specs[eCreativeInventoryTab_RedstoneAndTransport] = new TabSpec(L"RedstoneAndTransport", IDS_GROUPNAME_REDSTONE_AND_TRANSPORT, 2, redAndTranGroup, 0, NULL); + + ECreative_Inventory_Groups materialsGroup[] = {eCreativeInventory_Materials}; + specs[eCreativeInventoryTab_Materials] = new TabSpec(L"Materials", IDS_GROUPNAME_MATERIALS, 1, materialsGroup, 0, NULL); + + ECreative_Inventory_Groups foodGroup[] = {eCreativeInventory_Food}; + specs[eCreativeInventoryTab_Food] = new TabSpec(L"Food", IDS_GROUPNAME_FOOD, 1, foodGroup, 0, NULL); + + ECreative_Inventory_Groups toolsGroup[] = {eCreativeInventory_ToolsArmourWeapons}; + specs[eCreativeInventoryTab_ToolsWeaponsArmor] = new TabSpec(L"Tools", IDS_GROUPNAME_TOOLS_WEAPONS_ARMOR, 1, toolsGroup, 0, NULL); + + ECreative_Inventory_Groups brewingGroup[] = {eCreativeInventory_Brewing, eCreativeInventory_Potions_Level2_Extended, eCreativeInventory_Potions_Extended, eCreativeInventory_Potions_Level2, eCreativeInventory_Potions_Basic}; + + // Just use the text LT - the graphic doesn't fit in splitscreen either + // In 480p there's not enough room for the LT button, so use text instead + //if(!RenderManager.IsHiDef() && !RenderManager.IsWidescreen()) + { + specs[eCreativeInventoryTab_Brewing] = new TabSpec(L"Brewing", IDS_GROUPNAME_POTIONS_480, 5, brewingGroup, 0, NULL); + } + // else + // { + // specs[eCreativeInventoryTab_Brewing] = new TabSpec(L"icon_brewing.png", IDS_GROUPNAME_POTIONS, 1, brewingGroup, 4, potionsGroup); + // } + + ECreative_Inventory_Groups miscGroup[] = {eCreativeInventory_Misc}; + specs[eCreativeInventoryTab_Misc] = new TabSpec(L"Misc", IDS_GROUPNAME_MISCELLANEOUS, 1, miscGroup, 0, NULL); + +} + +IUIScene_CreativeMenu::IUIScene_CreativeMenu() +{ + m_bCarryingCreativeItem = false; + m_creativeSlotX = m_creativeSlotY = m_inventorySlotX = m_inventorySlotY = 0; + + // 4J JEV - Settup Tabs + for (int i = 0; i < eCreativeInventoryTab_COUNT; i++) + { + m_tabDynamicPos[i] = 0; + m_tabPage[i] = 0; + } +} + +/* 4J JEV - Switches between tabs. +*/ +void IUIScene_CreativeMenu::switchTab(ECreativeInventoryTabs tab) +{ + // Could just be changing page on the current tab + if(tab != m_curTab) updateTabHighlightAndText(tab); + + m_curTab = tab; + + updateScrollCurrentPage(m_tabPage[m_curTab] + 1, specs[m_curTab]->getPageCount()); + + specs[tab]->populateMenu(itemPickerMenu,m_tabDynamicPos[m_curTab], m_tabPage[m_curTab]); +} + +// 4J JEV - Tab Spec Struct + +IUIScene_CreativeMenu::TabSpec::TabSpec(LPCWSTR icon, int descriptionId, int staticGroupsCount, ECreative_Inventory_Groups *staticGroups, int dynamicGroupsCount, ECreative_Inventory_Groups *dynamicGroups) + : m_icon(icon), m_descriptionId(descriptionId), m_staticGroupsCount(staticGroupsCount), m_dynamicGroupsCount(dynamicGroupsCount) +{ + + m_pages = 0; + m_staticGroupsA = NULL; + + unsigned int dynamicItems = 0; + m_staticItems = 0; + + if(staticGroupsCount > 0) + { + m_staticGroupsA = new ECreative_Inventory_Groups[staticGroupsCount]; + for(int i = 0; i < staticGroupsCount; ++i) + { + m_staticGroupsA[i] = staticGroups[i]; + m_staticItems += categoryGroups[m_staticGroupsA[i]].size(); + } + } + + m_dynamicGroupsA = NULL; + if(dynamicGroupsCount > 0) + { + m_dynamicGroupsA = new ECreative_Inventory_Groups[dynamicGroupsCount]; + for(int i = 0; i < dynamicGroupsCount; ++i) + { + m_dynamicGroupsA[i] = dynamicGroups[i]; + dynamicItems += categoryGroups[m_dynamicGroupsA[i]].size(); + } + } + + m_staticPerPage = MAX_SIZE - dynamicItems; + m_pages = (int)ceil((float)m_staticItems / m_staticPerPage); +} + +IUIScene_CreativeMenu::TabSpec::~TabSpec() +{ + if(m_staticGroupsA != NULL) delete [] m_staticGroupsA; + if(m_dynamicGroupsA != NULL) delete [] m_dynamicGroupsA; +} + +void IUIScene_CreativeMenu::TabSpec::populateMenu(AbstractContainerMenu *menu, int dynamicIndex, unsigned int page) +{ + int lastSlotIndex = 0; + + // Fill the dynamic group + if(m_dynamicGroupsCount > 0 && m_dynamicGroupsA != NULL) + { + for(AUTO_VAR(it, categoryGroups[m_dynamicGroupsA[dynamicIndex]].rbegin()); it != categoryGroups[m_dynamicGroupsA[dynamicIndex]].rend() && lastSlotIndex < MAX_SIZE; ++it) + { + Slot *slot = menu->getSlot(++lastSlotIndex); + slot->set( *it ); + } + } + + // Fill from the static groups + unsigned int startIndex = page * m_staticPerPage; + int remainingItems = m_staticItems - startIndex; + + // Work out the first group with an item the want to display, and which item in that group + unsigned int currentIndex = 0; + unsigned int currentGroup = 0; + unsigned int currentItem = 0; + for(; currentGroup < m_staticGroupsCount; ++currentGroup) + { + int size = categoryGroups[m_staticGroupsA[currentGroup]].size(); + if( currentIndex + size < startIndex) + { + currentIndex += size; + continue; + } + currentItem = size - ((currentIndex + size) - startIndex); + break; + } + + for(; lastSlotIndex < MAX_SIZE;) + { + Slot *slot = menu->getSlot(lastSlotIndex++); + slot->set(categoryGroups[m_staticGroupsA[currentGroup]][currentItem]); + + ++currentItem; + if(currentItem >= categoryGroups[m_staticGroupsA[currentGroup]].size()) + { + currentItem = 0; + ++currentGroup; + if(currentGroup >= m_staticGroupsCount) + { + break; + } + } + } + + for(; lastSlotIndex < MAX_SIZE; ++lastSlotIndex) + { + Slot *slot = menu->getSlot(lastSlotIndex); + slot->remove(1); + } +} + +unsigned int IUIScene_CreativeMenu::TabSpec::getPageCount() +{ + return m_pages; +} + + +// 4J JEV - Item Picker Menu +IUIScene_CreativeMenu::ItemPickerMenu::ItemPickerMenu( shared_ptr<SimpleContainer> smp, shared_ptr<Inventory> inv ) : AbstractContainerMenu() +{ + inventory = inv; + creativeContainer = smp; + + //int startLength = slots->size(); + + Slot *slot = NULL; + for (int i = 0; i < TabSpec::MAX_SIZE; i++) + { + // 4J JEV - These values get set by addSlot anyway. + slot = new Slot( creativeContainer, i, -1, -1); + + ItemPickerMenu::addSlot( slot ); + } + + for (int i = 0; i < 9; i++) + { + slot = new Slot( inventory, i, -1, -1 ); + ItemPickerMenu::addSlot( slot ); + } + + // 4J Stu - Give the creative menu a unique container id + containerId = CONTAINER_ID_CREATIVE; +} + +bool IUIScene_CreativeMenu::ItemPickerMenu::stillValid(shared_ptr<Player> player) +{ + return true; +} + +bool IUIScene_CreativeMenu::ItemPickerMenu::isOverrideResultClick(int slotNum, int buttonNum) +{ + return slotNum >= 0 && slotNum < 9 && buttonNum == 0; +} + +IUIScene_AbstractContainerMenu::ESceneSection IUIScene_CreativeMenu::GetSectionAndSlotInDirection( ESceneSection eSection, ETapState eTapDirection, int *piTargetX, int *piTargetY ) +{ + ESceneSection newSection = eSection; + + // Find the new section if there is one + switch( eSection ) + { + case eSectionInventoryCreativeSelector: + if (eTapDirection == eTapStateDown || eTapDirection == eTapStateUp) + { + newSection = eSectionInventoryCreativeUsing; + } + break; + case eSectionInventoryCreativeUsing: + if (eTapDirection == eTapStateDown || eTapDirection == eTapStateUp) + { + newSection = eSectionInventoryCreativeSelector; + } + break; +#ifndef _XBOX + case eSectionInventoryCreativeTab_0: + case eSectionInventoryCreativeTab_1: + case eSectionInventoryCreativeTab_2: + case eSectionInventoryCreativeTab_3: + case eSectionInventoryCreativeTab_4: + case eSectionInventoryCreativeTab_5: + case eSectionInventoryCreativeTab_6: + case eSectionInventoryCreativeTab_7: + case eSectionInventoryCreativeSlider: + /* do nothing */ + break; +#endif + default: + assert( false ); + break; + } + + updateSlotPosition(eSection, newSection, eTapDirection, piTargetX, piTargetY, 0); + + return newSection; +} + +bool IUIScene_CreativeMenu::handleValidKeyPress(int iPad, int buttonNum, BOOL quickKeyHeld) +{ + // 4J Added - Make pressing the X button clear the hotbar + if(buttonNum == 1) + { + Minecraft *pMinecraft = Minecraft::GetInstance(); + for(unsigned int i = TabSpec::MAX_SIZE; i < TabSpec::MAX_SIZE + 9; ++i) + { + shared_ptr<ItemInstance> newItem = m_menu->getSlot(i)->getItem(); + + if(newItem != NULL) + { + m_menu->getSlot(i)->set(nullptr); + // call this function to synchronize multiplayer item bar + pMinecraft->localgameModes[iPad]->handleCreativeModeItemAdd(nullptr, i - (int)m_menu->slots->size() + 9 + InventoryMenu::USE_ROW_SLOT_START); + } + } + return true; + } + return false; +} + +void IUIScene_CreativeMenu::handleOutsideClicked(int iPad, int buttonNum, BOOL quickKeyHeld) +{ + // Drop items. + Minecraft *pMinecraft = Minecraft::GetInstance(); + + shared_ptr<Inventory> playerInventory = pMinecraft->localplayers[iPad]->inventory; + if (playerInventory->getCarried() != NULL) + { + if (buttonNum == 0) + { + pMinecraft->localgameModes[iPad]->handleCreativeModeItemDrop(playerInventory->getCarried()); + playerInventory->setCarried(nullptr); + } + if (buttonNum == 1) + { + shared_ptr<ItemInstance> removedItem = playerInventory->getCarried()->remove(1); + pMinecraft->localgameModes[iPad]->handleCreativeModeItemDrop(removedItem); + if (playerInventory->getCarried()->count == 0) playerInventory->setCarried(nullptr); + } + } + + //pMinecraft->localgameModes[m_iPad]->handleInventoryMouseClick(menu->containerId, AbstractContainerMenu::CLICKED_OUTSIDE, buttonNum, quickKeyHeld?true:false, pMinecraft->localplayers[m_iPad] ); +} + +void IUIScene_CreativeMenu::handleAdditionalKeyPress(int iAction) +{ + int dir = 1; + switch(iAction) + { + case ACTION_MENU_LEFT_SCROLL: + dir = -1; + // Fall through intentional + case ACTION_MENU_RIGHT_SCROLL: + { + ECreativeInventoryTabs tab = (ECreativeInventoryTabs)(m_curTab + dir); + if (tab < 0) tab = (ECreativeInventoryTabs)(eCreativeInventoryTab_COUNT - 1); + if (tab >= eCreativeInventoryTab_COUNT) tab = eCreativeInventoryTab_BuildingBlocks; + switchTab(tab); + ui.PlayUISFX(eSFX_Focus); + } + break; + case ACTION_MENU_PAGEUP: + // change the potion strength + { + ++m_tabDynamicPos[m_curTab]; + if(m_tabDynamicPos[m_curTab] >= specs[m_curTab]->m_dynamicGroupsCount) m_tabDynamicPos[m_curTab] = 0; + switchTab(m_curTab); + } + break; + case ACTION_MENU_OTHER_STICK_DOWN: + ++m_tabPage[m_curTab]; + if(m_tabPage[m_curTab] >= specs[m_curTab]->getPageCount()) + { + m_tabPage[m_curTab] = specs[m_curTab]->getPageCount() - 1; + } + else + { + switchTab(m_curTab); + } + break; + case ACTION_MENU_OTHER_STICK_UP: + --m_tabPage[m_curTab]; + if(m_tabPage[m_curTab] < 0) + { + m_tabPage[m_curTab] = 0; + } + else + { + switchTab(m_curTab); + } + break; + } +} + +void IUIScene_CreativeMenu::handleSlotListClicked(ESceneSection eSection, int buttonNum, BOOL quickKeyHeld) +{ + int currentIndex = getCurrentIndex(eSection); + + Minecraft *pMinecraft = Minecraft::GetInstance(); + + bool instantPlace = false; + if (eSection == eSectionInventoryCreativeSelector) + { + if (buttonNum == 0) + { + + shared_ptr<Inventory> playerInventory = pMinecraft->localplayers[getPad()]->inventory; + shared_ptr<ItemInstance> carried = playerInventory->getCarried(); + shared_ptr<ItemInstance> clicked = m_menu->getSlot(currentIndex)->getItem(); + if (clicked != NULL) + { + playerInventory->setCarried(ItemInstance::clone(clicked)); + carried = playerInventory->getCarried(); + if (quickKeyHeld == TRUE) + { + carried->count = carried->getMaxStackSize(); + } + m_creativeSlotX = m_iCurrSlotX; + m_creativeSlotY = m_iCurrSlotY; + m_eCurrSection = eSectionInventoryCreativeUsing; + m_eCurrTapState = eTapStateJump; + + instantPlace = getEmptyInventorySlot(carried, m_inventorySlotX); + m_iCurrSlotX = m_inventorySlotX; + m_iCurrSlotY = m_inventorySlotY; + + m_bCarryingCreativeItem = true; + } + } + } + if(instantPlace || eSection == eSectionInventoryCreativeUsing) + { + if(instantPlace) + { + setSectionSelectedSlot(eSectionInventoryCreativeUsing,m_iCurrSlotX,m_iCurrSlotY); + currentIndex = getCurrentIndex(eSectionInventoryCreativeUsing); + buttonNum = 0; + quickKeyHeld = FALSE; + } + m_menu->clicked(currentIndex, buttonNum, quickKeyHeld?AbstractContainerMenu::CLICK_QUICK_MOVE:AbstractContainerMenu::CLICK_PICKUP, pMinecraft->localplayers[getPad()]); + shared_ptr<ItemInstance> newItem = m_menu->getSlot(currentIndex)->getItem(); + // call this function to synchronize multiplayer item bar + pMinecraft->localgameModes[getPad()]->handleCreativeModeItemAdd(newItem, currentIndex - (int)m_menu->slots->size() + 9 + InventoryMenu::USE_ROW_SLOT_START); + + if(m_bCarryingCreativeItem) + { + m_inventorySlotX = m_iCurrSlotX; + m_inventorySlotY = m_iCurrSlotY; + m_eCurrSection = eSectionInventoryCreativeSelector; + m_eCurrTapState = eTapStateJump; + m_iCurrSlotX = m_creativeSlotX; + m_iCurrSlotY = m_creativeSlotY; + + shared_ptr<Inventory> playerInventory = pMinecraft->localplayers[getPad()]->inventory; + playerInventory->setCarried(nullptr); + m_bCarryingCreativeItem = false; + } + } +} + +bool IUIScene_CreativeMenu::IsSectionSlotList( ESceneSection eSection ) +{ + switch( eSection ) + { + case eSectionInventoryCreativeUsing: + case eSectionInventoryCreativeSelector: + return true; + } + return false; +} + +bool IUIScene_CreativeMenu::CanHaveFocus( ESceneSection eSection ) +{ + switch( eSection ) + { + case eSectionInventoryCreativeUsing: + case eSectionInventoryCreativeSelector: + return true; + } + return false; +} + +bool IUIScene_CreativeMenu::getEmptyInventorySlot(shared_ptr<ItemInstance> item, int &slotX) +{ + bool sameItemFound = false; + bool emptySlotFound = false; + // Jump to the slot with this item already on it, if we can stack more + for(unsigned int i = TabSpec::MAX_SIZE; i < TabSpec::MAX_SIZE + 9; ++i) + { + shared_ptr<ItemInstance> slotItem = m_menu->getSlot(i)->getItem(); + if( slotItem != NULL && slotItem->sameItem(item) && (slotItem->GetCount() + item->GetCount() <= item->getMaxStackSize() )) + { + sameItemFound = true; + slotX = i - TabSpec::MAX_SIZE; + break; + } + } + + if(!sameItemFound) + { + // Find an empty slot + for(unsigned int i = TabSpec::MAX_SIZE; i < TabSpec::MAX_SIZE + 9; ++i) + { + if( m_menu->getSlot(i)->getItem() == NULL ) + { + slotX = i - TabSpec::MAX_SIZE; + emptySlotFound = true; + break; + } + } + } + return sameItemFound || emptySlotFound; +} + +int IUIScene_CreativeMenu::getSectionStartOffset(ESceneSection eSection) +{ + int offset = 0; + switch( eSection ) + { + case eSectionInventoryCreativeSelector: + offset = 0; + break; + case eSectionInventoryCreativeUsing: + offset = TabSpec::MAX_SIZE; + break; + default: + assert( false ); + break; + } + return offset; +} + +bool IUIScene_CreativeMenu::overrideTooltips(ESceneSection sectionUnderPointer, shared_ptr<ItemInstance> itemUnderPointer, bool bIsItemCarried, bool bSlotHasItem, bool bCarriedIsSameAsSlot, int iSlotStackSizeRemaining, + EToolTipItem &buttonA, EToolTipItem &buttonX, EToolTipItem &buttonY, EToolTipItem &buttonRT) +{ + bool _override = false; + + if(sectionUnderPointer == eSectionInventoryCreativeSelector) + { + if(bSlotHasItem) + { + buttonA = eToolTipPickUpGeneric; + buttonRT = eToolTipWhatIsThis; + + if(itemUnderPointer->isStackable()) + { + buttonY = eToolTipPickUpAll; + } + else + { + buttonY = eToolTipNone; //eToolTipPickUpGeneric; + } + } + } + else if(sectionUnderPointer == eSectionInventoryCreativeUsing) + { + buttonY = eToolTipNone; + } + buttonX = eToolTipClearQuickSelect; + _override = true; + + return _override; +} diff --git a/Minecraft.Client/Common/UI/IUIScene_CreativeMenu.h b/Minecraft.Client/Common/UI/IUIScene_CreativeMenu.h new file mode 100644 index 00000000..7ab3ff7e --- /dev/null +++ b/Minecraft.Client/Common/UI/IUIScene_CreativeMenu.h @@ -0,0 +1,122 @@ +#pragma once +#include "IUIScene_AbstractContainerMenu.h" +#include "..\..\..\Minecraft.World\AbstractContainerMenu.h" +// 4J Stu - This class is for code that is common between XUI and Iggy + +class SimpleContainer; + +class IUIScene_CreativeMenu : public virtual IUIScene_AbstractContainerMenu +{ +public: + // 4J Stu - These map directly to the tabs seenon the screen + enum ECreativeInventoryTabs + { + eCreativeInventoryTab_BuildingBlocks = 0, + eCreativeInventoryTab_Decorations, + eCreativeInventoryTab_RedstoneAndTransport, + eCreativeInventoryTab_Materials, + eCreativeInventoryTab_Food, + eCreativeInventoryTab_ToolsWeaponsArmor, + eCreativeInventoryTab_Brewing, + eCreativeInventoryTab_Misc, + eCreativeInventoryTab_COUNT, + }; + + // 4J Stu - These are logical groupings of items, and be be combined for tabs on-screen + enum ECreative_Inventory_Groups + { + eCreativeInventory_BuildingBlocks, + eCreativeInventory_Decoration, + eCreativeInventory_Redstone, + eCreativeInventory_Transport, + eCreativeInventory_Materials, + eCreativeInventory_Food, + eCreativeInventory_ToolsArmourWeapons, + eCreativeInventory_Brewing, + eCreativeInventory_Potions_Basic, + eCreativeInventory_Potions_Level2, + eCreativeInventory_Potions_Extended, + eCreativeInventory_Potions_Level2_Extended, + eCreativeInventory_Misc, + eCreativeInventoryGroupsCount + }; + + // 4J JEV - Keeping all the tab specifications in one place. + struct TabSpec + { + public: + // 4J JEV - Layout + static const int rows = 5; + static const int columns = 10; + static const int MAX_SIZE = rows * columns; + + // 4J JEV - Images + const LPCWSTR m_icon; + const int m_descriptionId; + const int m_staticGroupsCount; + ECreative_Inventory_Groups *m_staticGroupsA; + const int m_dynamicGroupsCount; + ECreative_Inventory_Groups *m_dynamicGroupsA; + + private: + unsigned int m_pages; + unsigned int m_staticPerPage; + unsigned int m_staticItems; + + public: + TabSpec( LPCWSTR icon, int descriptionId, int staticGroupsCount, ECreative_Inventory_Groups *staticGroups, int dynamicGroupsCount, ECreative_Inventory_Groups *dynamicGroups ); + ~TabSpec(); + + void populateMenu(AbstractContainerMenu *menu, int dynamicIndex, unsigned int page); + unsigned int getPageCount(); + }; + + class ItemPickerMenu : public AbstractContainerMenu + { + protected: + shared_ptr<SimpleContainer> creativeContainer; + shared_ptr<Inventory> inventory; + + public: + ItemPickerMenu( shared_ptr<SimpleContainer> creativeContainer, shared_ptr<Inventory> inventory ); + + virtual bool stillValid(shared_ptr<Player> player); + bool isOverrideResultClick(int slotNum, int buttonNum); + protected: + // 4J Stu - Brought forward from 1.2 to fix infinite recursion bug in creative + virtual void loopClick(int slotIndex, int buttonNum, bool quickKeyHeld, shared_ptr<Player> player) { } // do nothing + } *itemPickerMenu; + +protected: + static vector< shared_ptr<ItemInstance> > categoryGroups[eCreativeInventoryGroupsCount]; + // 4J JEV - Tabs + static TabSpec **specs; + + bool m_bCarryingCreativeItem; + int m_creativeSlotX, m_creativeSlotY, m_inventorySlotX, m_inventorySlotY; + +public: + static void staticCtor(); + IUIScene_CreativeMenu(); + +protected: + ECreativeInventoryTabs m_curTab; + int m_tabDynamicPos[eCreativeInventoryTab_COUNT]; + int m_tabPage[eCreativeInventoryTab_COUNT]; + + void switchTab(ECreativeInventoryTabs tab); + virtual void updateTabHighlightAndText(ECreativeInventoryTabs tab) = 0; + virtual void updateScrollCurrentPage(int currentPage, int pageCount) = 0; + virtual ESceneSection GetSectionAndSlotInDirection( ESceneSection eSection, ETapState eTapDirection, int *piTargetX, int *piTargetY ); + virtual bool handleValidKeyPress(int iUserIndex, int buttonNum, BOOL quickKeyHeld); + virtual void handleOutsideClicked(int iPad, int buttonNum, BOOL quickKeyHeld); + virtual void handleAdditionalKeyPress(int iAction); + virtual void handleSlotListClicked(ESceneSection eSection, int buttonNum, BOOL quickKeyHeld); + bool getEmptyInventorySlot(shared_ptr<ItemInstance> item, int &slotX); + int getSectionStartOffset(ESceneSection eSection); + virtual bool IsSectionSlotList( ESceneSection eSection ); + virtual bool CanHaveFocus( ESceneSection eSection ); + + virtual bool overrideTooltips(ESceneSection sectionUnderPointer, shared_ptr<ItemInstance> itemUnderPointer, bool bIsItemCarried, bool bSlotHasItem, bool bCarriedIsSameAsSlot, int iSlotStackSizeRemaining, + EToolTipItem &buttonA, EToolTipItem &buttonX, EToolTipItem &buttonY, EToolTipItem &buttonRT); +};
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/IUIScene_DispenserMenu.cpp b/Minecraft.Client/Common/UI/IUIScene_DispenserMenu.cpp new file mode 100644 index 00000000..ec8a73c3 --- /dev/null +++ b/Minecraft.Client/Common/UI/IUIScene_DispenserMenu.cpp @@ -0,0 +1,77 @@ +#include "stdafx.h" + +#include "IUIScene_DispenserMenu.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.inventory.h" + +IUIScene_AbstractContainerMenu::ESceneSection IUIScene_DispenserMenu::GetSectionAndSlotInDirection( ESceneSection eSection, ETapState eTapDirection, int *piTargetX, int *piTargetY ) +{ + ESceneSection newSection = eSection; + int xOffset = 0; + + // Find the new section if there is one + switch( eSection ) + { + case eSectionTrapTrap: + if(eTapDirection == eTapStateDown) + { + newSection = eSectionTrapInventory; + xOffset = -TRAP_SCENE_TRAP_SLOT_OFFSET; + } + else if(eTapDirection == eTapStateUp) + { + newSection = eSectionTrapUsing; + xOffset = -TRAP_SCENE_TRAP_SLOT_OFFSET; + } + break; + case eSectionTrapInventory: + if(eTapDirection == eTapStateDown) + { + newSection = eSectionTrapUsing; + } + else if(eTapDirection == eTapStateUp) + { + newSection = eSectionTrapTrap; + xOffset = TRAP_SCENE_TRAP_SLOT_OFFSET; + } + break; + case eSectionTrapUsing: + if(eTapDirection == eTapStateDown) + { + newSection = eSectionTrapTrap; + xOffset = TRAP_SCENE_TRAP_SLOT_OFFSET; + } + else if(eTapDirection == eTapStateUp) + { + newSection = eSectionTrapInventory; + } + break; + default: + assert( false ); + break; + } + + updateSlotPosition(eSection, newSection, eTapDirection, piTargetX, piTargetY, xOffset); + + return newSection; +} + +int IUIScene_DispenserMenu::getSectionStartOffset(ESceneSection eSection) +{ + int offset = 0; + switch( eSection ) + { + case eSectionTrapTrap: + offset = 0; + break; + case eSectionTrapInventory: + offset = 9; + break; + case eSectionTrapUsing: + offset = 9 + 27; + break; + default: + assert( false ); + break; + } + return offset; +}
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/IUIScene_DispenserMenu.h b/Minecraft.Client/Common/UI/IUIScene_DispenserMenu.h new file mode 100644 index 00000000..e1826f95 --- /dev/null +++ b/Minecraft.Client/Common/UI/IUIScene_DispenserMenu.h @@ -0,0 +1,12 @@ +#pragma once +#include "IUIScene_AbstractContainerMenu.h" + +// The 0-indexed slot in the inventory list that lines up with the result slot +#define TRAP_SCENE_TRAP_SLOT_OFFSET 3 + +class IUIScene_DispenserMenu : public virtual IUIScene_AbstractContainerMenu +{ +protected: + virtual ESceneSection GetSectionAndSlotInDirection( ESceneSection eSection, ETapState eTapDirection, int *piTargetX, int *piTargetY ); + int getSectionStartOffset(ESceneSection eSection); +};
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/IUIScene_EnchantingMenu.cpp b/Minecraft.Client/Common/UI/IUIScene_EnchantingMenu.cpp new file mode 100644 index 00000000..c73f7dc5 --- /dev/null +++ b/Minecraft.Client/Common/UI/IUIScene_EnchantingMenu.cpp @@ -0,0 +1,185 @@ +#include "stdafx.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.inventory.h" +#include "..\..\Minecraft.h" +#include "..\..\MultiplayerLocalPlayer.h" +#include "IUIScene_EnchantingMenu.h" + +IUIScene_AbstractContainerMenu::ESceneSection IUIScene_EnchantingMenu::GetSectionAndSlotInDirection( IUIScene_AbstractContainerMenu::ESceneSection eSection, ETapState eTapDirection, int *piTargetX, int *piTargetY ) +{ + IUIScene_AbstractContainerMenu::ESceneSection newSection = eSection; + int xOffset = 0; + + // Find the new section if there is one + switch( eSection ) + { + case eSectionEnchantInventory: + if(eTapDirection == eTapStateDown) + { + newSection = eSectionEnchantUsing; + } + else if(eTapDirection == eTapStateUp) + { + if( *piTargetX >= ENCHANT_SCENE_ENCHANT_BUTTONS_UP_OFFSET) + { + newSection = eSectionEnchantButton3; + } + else + { + newSection = eSectionEnchantSlot; + } + } + break; + case eSectionEnchantUsing: + if(eTapDirection == eTapStateDown) + { + if( *piTargetX >= ENCHANT_SCENE_ENCHANT_BUTTONS_UP_OFFSET) + { + newSection = eSectionEnchantButton1; + } + else + { + newSection = eSectionEnchantSlot; + } + } + else if(eTapDirection == eTapStateUp) + { + newSection = eSectionEnchantInventory; + } + break; + case eSectionEnchantSlot: + if(eTapDirection == eTapStateDown) + { + newSection = eSectionEnchantInventory; + xOffset = ENCHANT_SCENE_INGREDIENT_SLOT_DOWN_OFFSET; + } + else if(eTapDirection == eTapStateUp) + { + newSection = eSectionEnchantUsing; + xOffset = ENCHANT_SCENE_INGREDIENT_SLOT_DOWN_OFFSET; + } + else if(eTapDirection == eTapStateLeft || eTapDirection == eTapStateRight) + { + newSection = eSectionEnchantButton1; + } + break; + case eSectionEnchantButton1: + if(eTapDirection == eTapStateDown) + { + newSection = eSectionEnchantButton2; + } + else if(eTapDirection == eTapStateUp) + { + newSection = eSectionEnchantUsing; + xOffset = ENCHANT_SCENE_ENCHANT_BUTTONS_DOWN_OFFSET; + } + else if(eTapDirection == eTapStateLeft || eTapDirection == eTapStateRight) + { + newSection = eSectionEnchantSlot; + } + break; + case eSectionEnchantButton2: + if(eTapDirection == eTapStateDown) + { + newSection = eSectionEnchantButton3; + } + else if(eTapDirection == eTapStateUp) + { + newSection = eSectionEnchantButton1; + } + else if(eTapDirection == eTapStateLeft || eTapDirection == eTapStateRight) + { + newSection = eSectionEnchantSlot; + } + break; + case eSectionEnchantButton3: + if(eTapDirection == eTapStateDown) + { + newSection = eSectionEnchantInventory; + xOffset = ENCHANT_SCENE_ENCHANT_BUTTONS_DOWN_OFFSET; + } + else if(eTapDirection == eTapStateUp) + { + newSection = eSectionEnchantButton2; + } + else if(eTapDirection == eTapStateLeft || eTapDirection == eTapStateRight) + { + newSection = eSectionEnchantSlot; + } + break; + default: + assert( false ); + break; + } + + updateSlotPosition(eSection, newSection, eTapDirection, piTargetX, piTargetY, xOffset); + + return newSection; +} + +void IUIScene_EnchantingMenu::handleOtherClicked(int iPad, ESceneSection eSection, int buttonNum, bool quickKey) +{ + int index = -1; + // Old xui code +#if 0 + HXUIOBJ hFocusObject = GetFocus(iPad); + if(hFocusObject == m_enchant1->m_hObj) index = 0; + else if(hFocusObject == m_enchant2->m_hObj) index = 1; + else if(hFocusObject == m_enchant3->m_hObj) index = 2; +#endif + + switch(eSection) + { + case eSectionEnchantButton1: + index = 0; + break; + case eSectionEnchantButton2: + index = 1; + break; + case eSectionEnchantButton3: + index = 2; + break; + }; + Minecraft *pMinecraft = Minecraft::GetInstance(); + if (index >= 0 && m_menu->clickMenuButton(dynamic_pointer_cast<Player>(pMinecraft->localplayers[iPad]), index)) + { + pMinecraft->localgameModes[iPad]->handleInventoryButtonClick(m_menu->containerId, index); + } +} + +int IUIScene_EnchantingMenu::getSectionStartOffset(ESceneSection eSection) +{ + int offset = 0; + switch( eSection ) + { + case eSectionEnchantSlot: + offset = 0; + break; + case eSectionEnchantInventory: + offset = 1; + break; + case eSectionEnchantUsing: + offset = 1 + 27; + break; + default: + assert( false ); + break; + }; + return offset; +} + +bool IUIScene_EnchantingMenu::IsSectionSlotList( ESceneSection eSection ) +{ + switch( eSection ) + { + case eSectionEnchantInventory: + case eSectionEnchantUsing: + case eSectionEnchantSlot: + return true; + } + return false; +} + +EnchantmentMenu *IUIScene_EnchantingMenu::getMenu() +{ + return (EnchantmentMenu *)m_menu; +}
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/IUIScene_EnchantingMenu.h b/Minecraft.Client/Common/UI/IUIScene_EnchantingMenu.h new file mode 100644 index 00000000..7867265a --- /dev/null +++ b/Minecraft.Client/Common/UI/IUIScene_EnchantingMenu.h @@ -0,0 +1,23 @@ +#pragma once + +#include "IUIScene_AbstractContainerMenu.h" + +// The 0-indexed slot in the inventory list that lines up with the result slot +#define ENCHANT_SCENE_ENCHANT_BUTTONS_UP_OFFSET 3 +#define ENCHANT_SCENE_ENCHANT_BUTTONS_DOWN_OFFSET -7 +#define ENCHANT_SCENE_INGREDIENT_SLOT_UP_OFFSET 0 +#define ENCHANT_SCENE_INGREDIENT_SLOT_DOWN_OFFSET 0 + +class EnchantmentMenu; + +class IUIScene_EnchantingMenu : public virtual IUIScene_AbstractContainerMenu +{ +protected: + virtual ESceneSection GetSectionAndSlotInDirection( ESceneSection eSection, ETapState eTapDirection, int *piTargetX, int *piTargetY ); + virtual void handleOtherClicked(int iPad, ESceneSection eSection, int buttonNum, bool quickKey); + int getSectionStartOffset(ESceneSection eSection); + virtual bool IsSectionSlotList( ESceneSection eSection ); + +public: + EnchantmentMenu *getMenu(); +};
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/IUIScene_FurnaceMenu.cpp b/Minecraft.Client/Common/UI/IUIScene_FurnaceMenu.cpp new file mode 100644 index 00000000..4a6c6762 --- /dev/null +++ b/Minecraft.Client/Common/UI/IUIScene_FurnaceMenu.cpp @@ -0,0 +1,141 @@ +#include "stdafx.h" + +#include "IUIScene_FurnaceMenu.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.inventory.h" + +IUIScene_AbstractContainerMenu::ESceneSection IUIScene_FurnaceMenu::GetSectionAndSlotInDirection( ESceneSection eSection, ETapState eTapDirection, int *piTargetX, int *piTargetY ) +{ + ESceneSection newSection = eSection; + int xOffset = 0; + + // Find the new section if there is one + switch( eSection ) + { + case eSectionFurnaceResult: + if(eTapDirection == eTapStateUp) + { + newSection = eSectionFurnaceUsing; + xOffset = FURNACE_SCENE_RESULT_SLOT_DOWN_OFFSET; + } + else if(eTapDirection == eTapStateDown) + { + newSection = eSectionFurnaceInventory; + xOffset = FURNACE_SCENE_RESULT_SLOT_DOWN_OFFSET; + } + else if(eTapDirection == eTapStateLeft) + { + newSection = eSectionFurnaceIngredient; + } + else if(eTapDirection == eTapStateRight) + { + newSection = eSectionFurnaceIngredient; + } + break; + case eSectionFurnaceIngredient: + if(eTapDirection == eTapStateUp) + { + newSection = eSectionFurnaceUsing; + xOffset = FURNACE_SCENE_FUEL_SLOT_DOWN_OFFSET; + } + else if(eTapDirection == eTapStateDown) + { + newSection = eSectionFurnaceFuel; + } + else if(eTapDirection == eTapStateLeft) + { + newSection = eSectionFurnaceResult; + } + else if(eTapDirection == eTapStateRight) + { + newSection = eSectionFurnaceResult; + } + break; + case eSectionFurnaceFuel: + if(eTapDirection == eTapStateDown) + { + newSection = eSectionFurnaceInventory; + xOffset = FURNACE_SCENE_FUEL_SLOT_DOWN_OFFSET; + } + else if(eTapDirection == eTapStateUp) + { + newSection = eSectionFurnaceIngredient; + } + else if(eTapDirection == eTapStateLeft) + { + newSection = eSectionFurnaceResult; + } + else if(eTapDirection == eTapStateRight) + { + newSection = eSectionFurnaceResult; + } + break; + case eSectionFurnaceInventory: + if(eTapDirection == eTapStateDown) + { + newSection = eSectionFurnaceUsing; + } + else if(eTapDirection == eTapStateUp) + { + if( *piTargetX >= FURNACE_SCENE_RESULT_SLOT_UP_OFFSET) + { + newSection = eSectionFurnaceResult; + } + else + { + newSection = eSectionFurnaceFuel; + } + } + break; + case eSectionFurnaceUsing: + if(eTapDirection == eTapStateUp) + { + newSection = eSectionFurnaceInventory; + } + else if(eTapDirection == eTapStateDown) + { + if( *piTargetX >= FURNACE_SCENE_RESULT_SLOT_UP_OFFSET) + { + newSection = eSectionFurnaceResult; + } + else + { + newSection = eSectionFurnaceIngredient; + } + } + break; + default: + assert( false ); + break; + } + + updateSlotPosition(eSection, newSection, eTapDirection, piTargetX, piTargetY, xOffset); + + return newSection; +} + +int IUIScene_FurnaceMenu::getSectionStartOffset(ESceneSection eSection) +{ + int offset = 0; + switch( eSection ) + { + case eSectionFurnaceResult: + offset = FurnaceMenu::RESULT_SLOT; + break; + case eSectionFurnaceFuel: + offset = FurnaceMenu::FUEL_SLOT; + break; + case eSectionFurnaceIngredient: + offset = FurnaceMenu::INGREDIENT_SLOT; + break; + case eSectionFurnaceInventory: + offset = FurnaceMenu::INV_SLOT_START; + break; + case eSectionFurnaceUsing: + offset = FurnaceMenu::INV_SLOT_START + 27; + break; + default: + assert( false ); + break; + } + return offset; +}
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/IUIScene_FurnaceMenu.h b/Minecraft.Client/Common/UI/IUIScene_FurnaceMenu.h new file mode 100644 index 00000000..1e3b3ba1 --- /dev/null +++ b/Minecraft.Client/Common/UI/IUIScene_FurnaceMenu.h @@ -0,0 +1,15 @@ +#pragma once +#include "IUIScene_AbstractContainerMenu.h" + +// The 0-indexed slot in the inventory list that lines up with the result slot +#define FURNACE_SCENE_RESULT_SLOT_UP_OFFSET 6 +#define FURNACE_SCENE_RESULT_SLOT_DOWN_OFFSET -7 +#define FURNACE_SCENE_FUEL_SLOT_UP_OFFSET 0 +#define FURNACE_SCENE_FUEL_SLOT_DOWN_OFFSET -3 + +class IUIScene_FurnaceMenu : public virtual IUIScene_AbstractContainerMenu +{ +protected: + virtual ESceneSection GetSectionAndSlotInDirection( ESceneSection eSection, ETapState eTapDirection, int *piTargetX, int *piTargetY ); + int getSectionStartOffset(ESceneSection eSection); +};
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/IUIScene_InventoryMenu.cpp b/Minecraft.Client/Common/UI/IUIScene_InventoryMenu.cpp new file mode 100644 index 00000000..7bed406a --- /dev/null +++ b/Minecraft.Client/Common/UI/IUIScene_InventoryMenu.cpp @@ -0,0 +1,72 @@ +#include "stdafx.h" + +#include "IUIScene_InventoryMenu.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.inventory.h" + +IUIScene_AbstractContainerMenu::ESceneSection IUIScene_InventoryMenu::GetSectionAndSlotInDirection( ESceneSection eSection, ETapState eTapDirection, int *piTargetX, int *piTargetY ) +{ + ESceneSection newSection = eSection; + + // Find the new section if there is one + switch( eSection ) + { + case eSectionInventoryArmor: + if(eTapDirection == eTapStateDown) + { + newSection = eSectionInventoryInventory; + } + else if(eTapDirection == eTapStateUp) + { + newSection = eSectionInventoryUsing; + } + break; + case eSectionInventoryInventory: + if(eTapDirection == eTapStateDown) + { + newSection = eSectionInventoryUsing; + } + else if(eTapDirection == eTapStateUp) + { + newSection = eSectionInventoryArmor; + } + break; + case eSectionInventoryUsing: + if(eTapDirection == eTapStateDown) + { + newSection = eSectionInventoryArmor; + } + else if(eTapDirection == eTapStateUp) + { + newSection = eSectionInventoryInventory; + } + break; + default: + assert( false ); + break; + } + + updateSlotPosition(eSection, newSection, eTapDirection, piTargetX, piTargetY, 0); + + return newSection; +} + +int IUIScene_InventoryMenu::getSectionStartOffset(ESceneSection eSection) +{ + int offset = 0; + switch( eSection ) + { + case eSectionInventoryArmor: + offset = InventoryMenu::ARMOR_SLOT_START; + break; + case eSectionInventoryInventory: + offset = InventoryMenu::INV_SLOT_START; + break; + case eSectionInventoryUsing: + offset = InventoryMenu::INV_SLOT_START + 27; + break; + default: + assert( false ); + break; + } + return offset; +}
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/IUIScene_InventoryMenu.h b/Minecraft.Client/Common/UI/IUIScene_InventoryMenu.h new file mode 100644 index 00000000..30887f8a --- /dev/null +++ b/Minecraft.Client/Common/UI/IUIScene_InventoryMenu.h @@ -0,0 +1,10 @@ +#pragma once + +#include "IUIScene_AbstractContainerMenu.h" + +class IUIScene_InventoryMenu : public virtual IUIScene_AbstractContainerMenu +{ +protected: + virtual ESceneSection GetSectionAndSlotInDirection( ESceneSection eSection, ETapState eTapDirection, int *piTargetX, int *piTargetY ); + int getSectionStartOffset(ESceneSection eSection); +};
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/IUIScene_PauseMenu.cpp b/Minecraft.Client/Common/UI/IUIScene_PauseMenu.cpp new file mode 100644 index 00000000..79203e7c --- /dev/null +++ b/Minecraft.Client/Common/UI/IUIScene_PauseMenu.cpp @@ -0,0 +1,691 @@ +#include "stdafx.h" +#include "IUIScene_PauseMenu.h" +#include "..\..\Minecraft.h" +#include "..\..\MinecraftServer.h" +#include "..\..\MultiPlayerLevel.h" +#include "..\..\ProgressRenderer.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.level.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.phys.h" +#include "..\..\TexturePackRepository.h" +#include "..\..\TexturePack.h" +#include "..\..\DLCTexturePack.h" +#include "..\..\..\Minecraft.World\StringHelpers.h" + + +int IUIScene_PauseMenu::ExitGameDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result) +{ + IUIScene_PauseMenu *scene = (IUIScene_PauseMenu *)pParam; + + // Results switched for this dialog + if(result==C4JStorage::EMessage_ResultDecline) + { + scene->SetIgnoreInput(true); + app.SetAction(iPad,eAppAction_ExitWorld); + } + return 0; +} + + +int IUIScene_PauseMenu::ExitGameSaveDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result) +{ + IUIScene_PauseMenu *scene = (IUIScene_PauseMenu *)pParam; + + // Exit with or without saving + // Decline means save in this dialog + if(result==C4JStorage::EMessage_ResultDecline || result==C4JStorage::EMessage_ResultThirdOption) + { + if( result==C4JStorage::EMessage_ResultDecline ) // Save + { + // 4J-PB - Is the player trying to save but they are using a trial texturepack ? + if(!Minecraft::GetInstance()->skins->isUsingDefaultSkin()) + { + TexturePack *tPack = Minecraft::GetInstance()->skins->getSelected(); + DLCTexturePack *pDLCTexPack=(DLCTexturePack *)tPack; + + DLCPack *pDLCPack=pDLCTexPack->getDLCInfoParentPack();//tPack->getDLCPack(); + if(!pDLCPack->hasPurchasedFile( DLCManager::e_DLCType_Texture, L"" )) + { +#ifdef _XBOX + // upsell + ULONGLONG ullOfferID_Full; + // get the dlc texture pack + DLCTexturePack *pDLCTexPack=(DLCTexturePack *)tPack; + + app.GetDLCFullOfferIDForPackID(pDLCTexPack->getDLCParentPackId(),&ullOfferID_Full); + + // tell sentient about the upsell of the full version of the skin pack + TelemetryManager->RecordUpsellPresented(iPad, eSet_UpsellID_Texture_DLC, ullOfferID_Full & 0xFFFFFFFF); +#endif + + UINT uiIDA[2]; + uiIDA[0]=IDS_CONFIRM_OK; + uiIDA[1]=IDS_CONFIRM_CANCEL; + + // Give the player a warning about the trial version of the texture pack + ui.RequestMessageBox(IDS_WARNING_DLC_TRIALTEXTUREPACK_TITLE, IDS_WARNING_DLC_TRIALTEXTUREPACK_TEXT, uiIDA, 2, ProfileManager.GetPrimaryPad() , &IUIScene_PauseMenu::WarningTrialTexturePackReturned, scene,app.GetStringTable(), NULL, 0, false); + + return S_OK; + } + } + + // does the save exist? + bool bSaveExists; + StorageManager.DoesSaveExist(&bSaveExists); + // 4J-PB - we check if the save exists inside the libs + // we need to ask if they are sure they want to overwrite the existing game + if(bSaveExists) + { + UINT uiIDA[2]; + uiIDA[0]=IDS_CONFIRM_CANCEL; + uiIDA[1]=IDS_CONFIRM_OK; + ui.RequestMessageBox(IDS_TITLE_SAVE_GAME, IDS_CONFIRM_SAVE_GAME, uiIDA, 2, ProfileManager.GetPrimaryPad(), &IUIScene_PauseMenu::ExitGameAndSaveReturned, scene, app.GetStringTable(), NULL, 0, false); + return 0; + } + else + { +#if defined(_XBOX_ONE) || defined(__ORBIS__) + StorageManager.SetSaveDisabled(false); +#endif + MinecraftServer::getInstance()->setSaveOnExit( true ); + } + } + else + { + // been a few requests for a confirm on exit without saving + UINT uiIDA[2]; + uiIDA[0]=IDS_CONFIRM_CANCEL; + uiIDA[1]=IDS_CONFIRM_OK; + ui.RequestMessageBox(IDS_TITLE_DECLINE_SAVE_GAME, IDS_CONFIRM_DECLINE_SAVE_GAME, uiIDA, 2, ProfileManager.GetPrimaryPad(), &IUIScene_PauseMenu::ExitGameDeclineSaveReturned, scene, app.GetStringTable(), NULL, 0, false); + return 0; + } + + scene->SetIgnoreInput(true); + + app.SetAction(iPad,eAppAction_ExitWorld); + } + return 0; +} + + +int IUIScene_PauseMenu::ExitGameAndSaveReturned(void *pParam,int iPad,C4JStorage::EMessageResult result) +{ + // 4J-PB - we won't come in here if we have a trial texture pack + IUIScene_PauseMenu *scene = (IUIScene_PauseMenu *)pParam; + + // results switched for this dialog + if(result==C4JStorage::EMessage_ResultDecline) + { + //INT saveOrCheckpointId = 0; + //bool validSave = StorageManager.GetSaveUniqueNumber(&saveOrCheckpointId); + //SentientManager.RecordLevelSaveOrCheckpoint(ProfileManager.GetPrimaryPad(), saveOrCheckpointId); +#if defined(_XBOX_ONE) || defined(__ORBIS__) + StorageManager.SetSaveDisabled(false); +#endif + scene->SetIgnoreInput(true); + MinecraftServer::getInstance()->setSaveOnExit( true ); + // flag a app action of exit game + app.SetAction(iPad,eAppAction_ExitWorld); + } + else + { + // has someone disconnected the ethernet here, causing the pause menu to shut? + if(ui.IsPauseMenuDisplayed(ProfileManager.GetPrimaryPad())) + { + UINT uiIDA[3]; + // you cancelled the save on exit after choosing exit and save? You go back to the Exit choices then. + uiIDA[0]=IDS_CONFIRM_CANCEL; + uiIDA[1]=IDS_EXIT_GAME_SAVE; + uiIDA[2]=IDS_EXIT_GAME_NO_SAVE; + + if(g_NetworkManager.GetPlayerCount()>1) + { + ui.RequestMessageBox(IDS_EXIT_GAME, IDS_CONFIRM_EXIT_GAME_CONFIRM_DISCONNECT_SAVE, uiIDA, 3, ProfileManager.GetPrimaryPad(), &IUIScene_PauseMenu::ExitGameSaveDialogReturned, scene, app.GetStringTable(), NULL, 0, false); + } + else + { + ui.RequestMessageBox(IDS_EXIT_GAME, IDS_CONFIRM_EXIT_GAME, uiIDA, 3, ProfileManager.GetPrimaryPad(), &IUIScene_PauseMenu::ExitGameSaveDialogReturned, scene, app.GetStringTable(), NULL, 0, false); + } + } + } + return 0; +} + + + +int IUIScene_PauseMenu::ExitGameDeclineSaveReturned(void *pParam,int iPad,C4JStorage::EMessageResult result) +{ + IUIScene_PauseMenu *scene = (IUIScene_PauseMenu *)pParam; + + // results switched for this dialog + if(result==C4JStorage::EMessage_ResultDecline) + { +#if defined(_XBOX_ONE) || defined(__ORBIS__) + // Don't do this here, as it will still try and save some things even though it shouldn't! + //StorageManager.SetSaveDisabled(false); +#endif + scene->SetIgnoreInput(true); + MinecraftServer::getInstance()->setSaveOnExit( false ); + // flag a app action of exit game + app.SetAction(iPad,eAppAction_ExitWorld); + } + else + { + // has someone disconnected the ethernet here, causing the pause menu to shut? + if(ui.IsPauseMenuDisplayed(ProfileManager.GetPrimaryPad())) + { + UINT uiIDA[3]; + // you cancelled the save on exit after choosing exit and save? You go back to the Exit choices then. + uiIDA[0]=IDS_CONFIRM_CANCEL; + uiIDA[1]=IDS_EXIT_GAME_SAVE; + uiIDA[2]=IDS_EXIT_GAME_NO_SAVE; + + if(g_NetworkManager.GetPlayerCount()>1) + { + ui.RequestMessageBox(IDS_EXIT_GAME, IDS_CONFIRM_EXIT_GAME_CONFIRM_DISCONNECT_SAVE, uiIDA, 3, ProfileManager.GetPrimaryPad(),&IUIScene_PauseMenu::ExitGameSaveDialogReturned, scene, app.GetStringTable(), NULL, 0, false); + } + else + { + ui.RequestMessageBox(IDS_EXIT_GAME, IDS_CONFIRM_EXIT_GAME, uiIDA, 3, ProfileManager.GetPrimaryPad(),&IUIScene_PauseMenu::ExitGameSaveDialogReturned, scene, app.GetStringTable(), NULL, 0, false); + } + } + + } + return 0; +} + + + +int IUIScene_PauseMenu::WarningTrialTexturePackReturned(void *pParam,int iPad,C4JStorage::EMessageResult result) +{ +#if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__) + if(result==C4JStorage::EMessage_ResultAccept) + { + if(!ProfileManager.IsSignedInLive(iPad)) + { + // you're not signed in to PSN! + + } + else + { + // 4J-PB - need to check this user can access the store + bool bContentRestricted; + ProfileManager.GetChatAndContentRestrictions(iPad,true,NULL,&bContentRestricted,NULL); + if(bContentRestricted) + { + UINT uiIDA[1]; + uiIDA[0]=IDS_CONFIRM_OK; + ui.RequestMessageBox(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, iPad,NULL,&app, app.GetStringTable(), NULL, 0, false); + } + else + { + // need to get info on the pack to see if the user has already downloaded it + TexturePack *tPack = Minecraft::GetInstance()->skins->getSelected(); + DLCTexturePack *pDLCTexPack=(DLCTexturePack *)tPack; + + // retrieve the store name for the skin pack + DLCPack *pDLCPack=pDLCTexPack->getDLCInfoParentPack();//tPack->getDLCPack(); + const char *pchPackName=wstringtofilename(pDLCPack->getName()); + app.DebugPrintf("Texture Pack - %s\n",pchPackName); + SONYDLC *pSONYDLCInfo=app.GetSONYDLCInfo((char *)pchPackName); + + if(pSONYDLCInfo!=NULL) + { + char chName[42]; + char chSkuID[SCE_NP_COMMERCE2_SKU_ID_LEN]; + + memset(chSkuID,0,SCE_NP_COMMERCE2_SKU_ID_LEN); + // find the info on the skin pack + // we have to retrieve the skuid from the store info, it can't be hardcoded since Sony may change it. + // So we assume the first sku for the product is the one we want +#ifdef __ORBIS__ + sprintf(chName,"%s",pSONYDLCInfo->chDLCKeyname); +#else + sprintf(chName,"%s-%s",app.GetCommerceCategory(),pSONYDLCInfo->chDLCKeyname); +#endif + app.GetDLCSkuIDFromProductList(chName,chSkuID); + // 4J-PB - need to check for an empty store +#if defined __ORBIS__ || defined __PSVITA__ || defined __PS3__ + if(app.CheckForEmptyStore(iPad)==false) +#endif + { + if(app.DLCAlreadyPurchased(chSkuID)) + { + app.DownloadAlreadyPurchased(chSkuID); + } + else + { + app.Checkout(chSkuID); + } + } + } + } + } + } +#endif // + +#ifdef _XBOX_ONE + IUIScene_PauseMenu* pScene = (IUIScene_PauseMenu*)pParam; + + if(result==C4JStorage::EMessage_ResultAccept) + { + if(ProfileManager.IsSignedIn(iPad)) + { + if (ProfileManager.IsSignedInLive(iPad)) + { + TexturePack *tPack = Minecraft::GetInstance()->skins->getSelected(); + // get the dlc texture pack + DLCTexturePack *pDLCTexPack=(DLCTexturePack *)tPack; + + DLCPack *pDLCPack=pDLCTexPack->getDLCInfoParentPack(); + + DLC_INFO *pDLCInfo=app.GetDLCInfoForProductName((WCHAR *)pDLCPack->getName().c_str()); + + StorageManager.InstallOffer(1,(WCHAR *)pDLCInfo->wsProductId.c_str(),NULL,NULL); + + // the license change coming in when the offer has been installed will cause this scene to refresh + } + else + { + // 4J-JEV: Fix for XB1: #165863 - XR-074: Compliance: With no active network connection user is unable to convert from Trial to Full texture pack and is not messaged why. + UINT uiIDA[1] = { IDS_CONFIRM_OK }; + ui.RequestMessageBox(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_XBOXLIVE_NOTIFICATION, uiIDA, 1, iPad, NULL, NULL, app.GetStringTable()); + } + } + } + +#endif + +#ifdef _XBOX + IUIScene_PauseMenu* pScene = (IUIScene_PauseMenu*)pParam; + + //pScene->m_bIgnoreInput = false; + pScene->ShowScene( true ); + if(result==C4JStorage::EMessage_ResultAccept) + { + if(ProfileManager.IsSignedIn(iPad)) + { + ULONGLONG ullIndexA[1]; + + TexturePack *tPack = Minecraft::GetInstance()->skins->getSelected(); + // get the dlc texture pack + DLCTexturePack *pDLCTexPack=(DLCTexturePack *)tPack; + + // Need to get the parent packs id, since this may be one of many child packs with their own ids + app.GetDLCFullOfferIDForPackID(pDLCTexPack->getDLCParentPackId(),&ullIndexA[0]); + + // need to allow downloads here, or the player would need to quit the game to let the download of a texture pack happen. This might affect the network traffic, since the download could take all the bandwidth... + XBackgroundDownloadSetMode(XBACKGROUND_DOWNLOAD_MODE_ALWAYS_ALLOW); + + StorageManager.InstallOffer(1,ullIndexA,NULL,NULL); + } + } + else + { + TelemetryManager->RecordUpsellResponded(iPad, eSet_UpsellID_Texture_DLC, ( pScene->m_pDLCPack->getPurchaseOfferId() & 0xFFFFFFFF ), eSen_UpsellOutcome_Declined); + } +#endif + + + return 0; +} + + +int IUIScene_PauseMenu::SaveWorldThreadProc( LPVOID lpParameter ) +{ + bool bAutosave=(bool)lpParameter; + if(bAutosave) + { + app.SetXuiServerAction(ProfileManager.GetPrimaryPad(),eXuiServerAction_AutoSaveGame); + } + else + { + app.SetXuiServerAction(ProfileManager.GetPrimaryPad(),eXuiServerAction_SaveGame); + } + + // Share AABB & Vec3 pools with default (main thread) - should be ok as long as we don't tick the main thread whilst this thread is running + AABB::UseDefaultThreadStorage(); + Vec3::UseDefaultThreadStorage(); + Compression::UseDefaultThreadStorage(); + + Minecraft *pMinecraft=Minecraft::GetInstance(); + + //wprintf(L"Loading world on thread\n"); + + if(ProfileManager.IsFullVersion()) + { + app.SetGameStarted(false); + + while( app.GetXuiServerAction(ProfileManager.GetPrimaryPad() ) != eXuiServerAction_Idle && !MinecraftServer::serverHalted() ) + { + Sleep(10); + } + + if(!MinecraftServer::serverHalted() && !app.GetChangingSessionType() ) app.SetGameStarted(true); + +#if defined(_XBOX_ONE) || defined(__ORBIS__) + if(app.GetGameHostOption(eGameHostOption_DisableSaving)) StorageManager.SetSaveDisabled(true); +#endif + } + + HRESULT hr = S_OK; + if(app.GetChangingSessionType()) + { + // 4J Stu - This causes the fullscreenprogress scene to ignore the action it was given + hr = ERROR_CANCELLED; + } + return hr; +} + +int IUIScene_PauseMenu::ExitWorldThreadProc( void* lpParameter ) +{ + // Share AABB & Vec3 pools with default (main thread) - should be ok as long as we don't tick the main thread whilst this thread is running + AABB::UseDefaultThreadStorage(); + Vec3::UseDefaultThreadStorage(); + Compression::UseDefaultThreadStorage(); + + //app.SetGameStarted(false); + + _ExitWorld(lpParameter); + + return S_OK; +} + +// This function performs the meat of exiting from a level. It should be called from a thread other than the main thread. +void IUIScene_PauseMenu::_ExitWorld(LPVOID lpParameter) +{ + Minecraft *pMinecraft=Minecraft::GetInstance(); + + int exitReasonStringId = pMinecraft->progressRenderer->getCurrentTitle(); + int exitReasonTitleId = IDS_CONNECTION_LOST; + + bool saveStats = true; + if (pMinecraft->isClientSide() || g_NetworkManager.IsInSession()) + { + if(lpParameter != NULL ) + { + // 4J-PB - check if we have lost connection to Live + if(ProfileManager.GetLiveConnectionStatus()!=XONLINE_S_LOGON_CONNECTION_ESTABLISHED ) + { + exitReasonStringId = IDS_CONNECTION_LOST_LIVE; + } + else + { + switch( app.GetDisconnectReason() ) + { + case DisconnectPacket::eDisconnect_Kicked: + exitReasonStringId = IDS_DISCONNECTED_KICKED; + break; + case DisconnectPacket::eDisconnect_NoUGC_AllLocal: + exitReasonStringId = IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_ALL_LOCAL; + exitReasonTitleId = IDS_CONNECTION_FAILED; + break; + case DisconnectPacket::eDisconnect_NoUGC_Single_Local: + exitReasonStringId = IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_SINGLE_LOCAL; + exitReasonTitleId = IDS_CONNECTION_FAILED; + break; +#if defined(__PS3__) || defined(__ORBIS__) + case DisconnectPacket::eDisconnect_ContentRestricted_AllLocal: + exitReasonStringId = IDS_CONTENT_RESTRICTION_MULTIPLAYER; + exitReasonTitleId = IDS_CONNECTION_FAILED; + break; + case DisconnectPacket::eDisconnect_ContentRestricted_Single_Local: + exitReasonStringId = IDS_CONTENT_RESTRICTION; + exitReasonTitleId = IDS_CONNECTION_FAILED; + break; +#endif +#ifdef _XBOX + case DisconnectPacket::eDisconnect_NoUGC_Remote: + exitReasonStringId = IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_REMOTE; + exitReasonTitleId = IDS_CONNECTION_FAILED; + break; +#endif + case DisconnectPacket::eDisconnect_NoFlying: + exitReasonStringId = IDS_DISCONNECTED_FLYING; + break; + case DisconnectPacket::eDisconnect_Quitting: + exitReasonStringId = IDS_DISCONNECTED_SERVER_QUIT; + break; +#ifdef __ORBIS__ + case DisconnectPacket::eDisconnect_NetworkError: + exitReasonStringId = IDS_ERROR_NETWORK_EXIT; + exitReasonTitleId = IDS_ERROR_NETWORK_TITLE; + break; +#endif + case DisconnectPacket::eDisconnect_NoFriendsInGame: + exitReasonStringId = IDS_DISCONNECTED_NO_FRIENDS_IN_GAME; + exitReasonTitleId = IDS_CANTJOIN_TITLE; + break; + case DisconnectPacket::eDisconnect_Banned: + exitReasonStringId = IDS_DISCONNECTED_BANNED; + exitReasonTitleId = IDS_CANTJOIN_TITLE; + break; + case DisconnectPacket::eDisconnect_NotFriendsWithHost: + exitReasonStringId = IDS_NOTALLOWED_FRIENDSOFFRIENDS; + exitReasonTitleId = IDS_CANTJOIN_TITLE; + break; + case DisconnectPacket::eDisconnect_OutdatedServer: + exitReasonStringId = IDS_DISCONNECTED_SERVER_OLD; + exitReasonTitleId = IDS_CANTJOIN_TITLE; + break; + case DisconnectPacket::eDisconnect_OutdatedClient: + exitReasonStringId = IDS_DISCONNECTED_CLIENT_OLD; + exitReasonTitleId = IDS_CANTJOIN_TITLE; + break; + case DisconnectPacket::eDisconnect_ServerFull: + exitReasonStringId = IDS_DISCONNECTED_SERVER_FULL; + exitReasonTitleId = IDS_CANTJOIN_TITLE; + break; +#ifdef _XBOX_ONE + case DisconnectPacket::eDisconnect_ExitedGame: + exitReasonTitleId = IDS_EXIT_GAME; + exitReasonStringId = IDS_DISCONNECTED_EXITED_GAME; + break; +#endif + +#if defined __ORBIS__ || defined __PS3__ || defined __PSVITA__ + case DisconnectPacket::eDisconnect_NATMismatch: + exitReasonStringId = IDS_DISCONNECTED_NAT_TYPE_MISMATCH; + exitReasonTitleId = IDS_CONNECTION_FAILED; + break; +#endif + default: + exitReasonStringId = IDS_CONNECTION_LOST_SERVER; + } + } + //pMinecraft->progressRenderer->progressStartNoAbort( exitReasonStringId ); + + UINT uiIDA[1]; + uiIDA[0]=IDS_CONFIRM_OK; + // 4J Stu - Fix for #48669 - TU5: Code: Compliance: TCR #15: Incorrect/misleading messages after signing out a profile during online game session. + // If the primary player is signed out, then that is most likely the cause of the disconnection so don't display a message box. This will allow the message box requested by the libraries to be brought up + if( ProfileManager.IsSignedIn(ProfileManager.GetPrimaryPad())) ui.RequestMessageBox( exitReasonTitleId, exitReasonStringId, uiIDA,1,ProfileManager.GetPrimaryPad(),NULL,NULL, app.GetStringTable()); + exitReasonStringId = -1; + + // 4J - Force a disconnection, this handles the situation that the server has already disconnected + if( pMinecraft->levels[0] != NULL ) pMinecraft->levels[0]->disconnect(false); + if( pMinecraft->levels[1] != NULL ) pMinecraft->levels[1]->disconnect(false); + if( pMinecraft->levels[2] != NULL ) pMinecraft->levels[2]->disconnect(false); + } + else + { + exitReasonStringId = IDS_EXITING_GAME; + pMinecraft->progressRenderer->progressStartNoAbort( IDS_EXITING_GAME ); + if( pMinecraft->levels[0] != NULL ) pMinecraft->levels[0]->disconnect(); + if( pMinecraft->levels[1] != NULL ) pMinecraft->levels[1]->disconnect(); + if( pMinecraft->levels[2] != NULL ) pMinecraft->levels[2]->disconnect(); + } + + // 4J Stu - This only does something if we actually have a server, so don't need to do any other checks + MinecraftServer::HaltServer(); + + // We need to call the stats & leaderboards save before we exit the session + // 4J We need to do this in a QNet callback where it is safe + //pMinecraft->forceStatsSave(); + saveStats = false; + + // 4J Stu - Leave the session once the disconnect packet has been sent + g_NetworkManager.LeaveGame(FALSE); + } + else + { + if(lpParameter != NULL && ProfileManager.IsSignedIn(ProfileManager.GetPrimaryPad()) ) + { + switch( app.GetDisconnectReason() ) + { + case DisconnectPacket::eDisconnect_Kicked: + exitReasonStringId = IDS_DISCONNECTED_KICKED; + break; + case DisconnectPacket::eDisconnect_NoUGC_AllLocal: + exitReasonStringId = IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_ALL_LOCAL; + exitReasonTitleId = IDS_CONNECTION_FAILED; + break; + case DisconnectPacket::eDisconnect_NoUGC_Single_Local: + exitReasonStringId = IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_SINGLE_LOCAL; + exitReasonTitleId = IDS_CONNECTION_FAILED; + break; +#if defined(__PS3__) || defined(__ORBIS__) + case DisconnectPacket::eDisconnect_ContentRestricted_AllLocal: + exitReasonStringId = IDS_CONTENT_RESTRICTION_MULTIPLAYER; + exitReasonTitleId = IDS_CONNECTION_FAILED; + break; + case DisconnectPacket::eDisconnect_ContentRestricted_Single_Local: + exitReasonStringId = IDS_CONTENT_RESTRICTION; + exitReasonTitleId = IDS_CONNECTION_FAILED; + break; +#endif +#ifdef _XBOX + case DisconnectPacket::eDisconnect_NoUGC_Remote: + exitReasonStringId = IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_REMOTE; + exitReasonTitleId = IDS_CONNECTION_FAILED; + break; +#endif + case DisconnectPacket::eDisconnect_Quitting: + exitReasonStringId = IDS_DISCONNECTED_SERVER_QUIT; + break; +#ifdef __ORBIS__ + case DisconnectPacket::eDisconnect_NetworkError: + exitReasonStringId = IDS_ERROR_NETWORK_EXIT; + exitReasonTitleId = IDS_ERROR_NETWORK_TITLE; + break; +#endif + case DisconnectPacket::eDisconnect_NoMultiplayerPrivilegesJoin: + exitReasonStringId = IDS_NO_MULTIPLAYER_PRIVILEGE_JOIN_TEXT; + break; + case DisconnectPacket::eDisconnect_OutdatedServer: + exitReasonStringId = IDS_DISCONNECTED_SERVER_OLD; + exitReasonTitleId = IDS_CANTJOIN_TITLE; + break; + case DisconnectPacket::eDisconnect_OutdatedClient: + exitReasonStringId = IDS_DISCONNECTED_CLIENT_OLD; + exitReasonTitleId = IDS_CANTJOIN_TITLE; + break; + case DisconnectPacket::eDisconnect_ServerFull: + exitReasonStringId = IDS_DISCONNECTED_SERVER_FULL; + exitReasonTitleId = IDS_CANTJOIN_TITLE; + break; +#if defined __ORBIS__ || defined __PS3__ || defined __PSVITA__ + case DisconnectPacket::eDisconnect_NATMismatch: + exitReasonStringId = IDS_DISCONNECTED_NAT_TYPE_MISMATCH; + exitReasonTitleId = IDS_CONNECTION_FAILED; + break; +#endif + default: + exitReasonStringId = IDS_DISCONNECTED; + } + //pMinecraft->progressRenderer->progressStartNoAbort( exitReasonStringId ); + + UINT uiIDA[1]; + uiIDA[0]=IDS_CONFIRM_OK; + ui.RequestMessageBox( exitReasonTitleId, exitReasonStringId, uiIDA,1,ProfileManager.GetPrimaryPad(),NULL,NULL, app.GetStringTable()); + exitReasonStringId = -1; + } + } + // Fix for #93148 - TCR 001: BAS Game Stability: Title will crash for the multiplayer client if host of the game will exit during the clients loading to created world. + while( g_NetworkManager.IsNetworkThreadRunning() ) + { + Sleep(1); + } + pMinecraft->setLevel(NULL,exitReasonStringId,nullptr,saveStats); + + TelemetryManager->Flush(); + + app.m_gameRules.unloadCurrentGameRules(); + //app.m_Audio.unloadCurrentAudioDetails(); + + MinecraftServer::resetFlags(); + + // Fix for #48385 - BLACK OPS :TU5: Functional: Client becomes pseudo soft-locked when returned to the main menu after a remote disconnect + // Make sure there is text explaining why the player is waiting + pMinecraft->progressRenderer->progressStart(IDS_EXITING_GAME); + + // Fix for #13259 - CRASH: Gameplay: loading process is halted when player loads saved data + // We can't start/join a new game until the session is destroyed, so wait for it to be idle again + while( g_NetworkManager.IsInSession() ) + { + Sleep(1); + } + + app.SetChangingSessionType(false); + app.SetReallyChangingSessionType(false); + +#if defined(_XBOX_ONE) || defined(__ORBIS__) + // Make sure we don't think saving is disabled in the menus + StorageManager.SetSaveDisabled(false); +#endif +} + + +int IUIScene_PauseMenu::SaveGameDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result) +{ + // results switched for this dialog + if(result==C4JStorage::EMessage_ResultDecline) + { +#if defined(_XBOX_ONE) || defined(__ORBIS__) + UINT uiIDA[2]; + uiIDA[0]=IDS_CONFIRM_CANCEL; + uiIDA[1]=IDS_CONFIRM_OK; + ui.RequestMessageBox(IDS_TITLE_ENABLE_AUTOSAVE, IDS_CONFIRM_ENABLE_AUTOSAVE, uiIDA, 2, iPad,&IUIScene_PauseMenu::EnableAutosaveDialogReturned,pParam, app.GetStringTable(), NULL, 0, false); +#else + // flag a app action of save game + app.SetAction(iPad,eAppAction_SaveGame); +#endif + } + return 0; +} + +int IUIScene_PauseMenu::EnableAutosaveDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result) +{ + // results switched for this dialog + if(result==C4JStorage::EMessage_ResultDecline) + { + // Set the global flag, so that we don't disable saving again once the save is complete + app.SetGameHostOption(eGameHostOption_DisableSaving, 0); + } + else + { + // Set the global flag, so that we do disable saving again once the save is complete + // We need to set this on as we may have only disabled it due to having a trial texture pack + app.SetGameHostOption(eGameHostOption_DisableSaving, 1); + } + // Re-enable saving temporarily + StorageManager.SetSaveDisabled(false); + + // flag a app action of save game + app.SetAction(iPad,eAppAction_SaveGame); + return 0; +} + +int IUIScene_PauseMenu::DisableAutosaveDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result) +{ + // results switched for this dialog + if(result==C4JStorage::EMessage_ResultDecline) + { + // Set the global flag, so that we disable saving again once the save is complete + app.SetGameHostOption(eGameHostOption_DisableSaving, 1); + StorageManager.SetSaveDisabled(false); + + // flag a app action of save game + app.SetAction(iPad,eAppAction_SaveGame); + } + return 0; +}
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/IUIScene_PauseMenu.h b/Minecraft.Client/Common/UI/IUIScene_PauseMenu.h new file mode 100644 index 00000000..7233df3a --- /dev/null +++ b/Minecraft.Client/Common/UI/IUIScene_PauseMenu.h @@ -0,0 +1,25 @@ +#pragma once + +class IUIScene_PauseMenu +{ +protected: + DLCPack *m_pDLCPack; + +public: + static int ExitGameDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result); + static int ExitGameSaveDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result); + static int ExitGameAndSaveReturned(void *pParam,int iPad,C4JStorage::EMessageResult result); + static int ExitGameDeclineSaveReturned(void *pParam,int iPad,C4JStorage::EMessageResult result); + static int WarningTrialTexturePackReturned(void *pParam,int iPad,C4JStorage::EMessageResult result); + static int SaveGameDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result); + static int EnableAutosaveDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result); + static int DisableAutosaveDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result); + + static int SaveWorldThreadProc( void* lpParameter ); + static int ExitWorldThreadProc( void* lpParameter ); + static void _ExitWorld(LPVOID lpParameter); // Call only from a thread + +protected: + virtual void ShowScene(bool show) = 0; + virtual void SetIgnoreInput(bool ignoreInput) = 0; +};
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/IUIScene_StartGame.cpp b/Minecraft.Client/Common/UI/IUIScene_StartGame.cpp new file mode 100644 index 00000000..be611778 --- /dev/null +++ b/Minecraft.Client/Common/UI/IUIScene_StartGame.cpp @@ -0,0 +1,379 @@ +#include "stdafx.h" +#include "UI.h" +#include "TexturePack.h" +#include "TexturePackRepository.h" +#include "Minecraft.h" +#include "IUIScene_StartGame.h" + +IUIScene_StartGame::IUIScene_StartGame(int iPad, UILayer *parentLayer) : UIScene(iPad, parentLayer) +{ + m_bIgnoreInput = false; + m_iTexturePacksNotInstalled=0; + m_texturePackDescDisplayed = false; + m_bShowTexturePackDescription = false; + m_iSetTexturePackDescription = -1; + + Minecraft *pMinecraft = Minecraft::GetInstance(); + m_currentTexturePackIndex = pMinecraft->skins->getTexturePackIndex(0); +} + +void IUIScene_StartGame::HandleDLCMountingComplete() +{ + Minecraft *pMinecraft = Minecraft::GetInstance(); + // clear out the current texture pack list + m_texturePackList.clearSlots(); + + int texturePacksCount = pMinecraft->skins->getTexturePackCount(); + + for(unsigned int i = 0; i < texturePacksCount; ++i) + { + TexturePack *tp = pMinecraft->skins->getTexturePackByIndex(i); + + DWORD dwImageBytes; + PBYTE pbImageData = tp->getPackIcon(dwImageBytes); + + if(dwImageBytes > 0 && pbImageData) + { + wchar_t imageName[64]; + swprintf(imageName,64,L"tpack%08x",tp->getId()); + registerSubstitutionTexture(imageName, pbImageData, dwImageBytes); + m_texturePackList.addPack(i,imageName); + } + } + + m_iTexturePacksNotInstalled=0; + + // 4J-PB - there may be texture packs we don't have, so use the info from TMS for this + // REMOVE UNTIL WORKING + DLC_INFO *pDLCInfo=NULL; + + // first pass - look to see if there are any that are not in the list + bool bTexturePackAlreadyListed; + bool bNeedToGetTPD=false; + + for(unsigned int i = 0; i < app.GetDLCInfoTexturesOffersCount(); ++i) + { + bTexturePackAlreadyListed=false; +#if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__) + char *pchName=app.GetDLCInfoTextures(i); + pDLCInfo=app.GetDLCInfo(pchName); +#elif defined _XBOX_ONE + pDLCInfo=app.GetDLCInfoForFullOfferID((WCHAR *)app.GetDLCInfoTexturesFullOffer(i).c_str()); +#else + ULONGLONG ull=app.GetDLCInfoTexturesFullOffer(i); + pDLCInfo=app.GetDLCInfoForFullOfferID(ull); +#endif + for(unsigned int i = 0; i < texturePacksCount; ++i) + { + TexturePack *tp = pMinecraft->skins->getTexturePackByIndex(i); + if(pDLCInfo->iConfig==tp->getDLCParentPackId()) + { + bTexturePackAlreadyListed=true; + } + } + if(bTexturePackAlreadyListed==false) + { + // some missing + bNeedToGetTPD=true; + + m_iTexturePacksNotInstalled++; + } + } + +#if TO_BE_IMPLEMENTED + if(bNeedToGetTPD==true) + { + // add a TMS request for them + app.DebugPrintf("+++ Adding TMSPP request for texture pack data\n"); + app.AddTMSPPFileTypeRequest(e_DLC_TexturePackData); + if(m_iConfigA!=NULL) + { + delete m_iConfigA; + } + m_iConfigA= new int [m_iTexturePacksNotInstalled]; + m_iTexturePacksNotInstalled=0; + + for(unsigned int i = 0; i < app.GetDLCInfoTexturesOffersCount(); ++i) + { + bTexturePackAlreadyListed=false; + ULONGLONG ull=app.GetDLCInfoTexturesFullOffer(i); + pDLCInfo=app.GetDLCInfoForFullOfferID(ull); + for(unsigned int i = 0; i < texturePacksCount; ++i) + { + TexturePack *tp = pMinecraft->skins->getTexturePackByIndex(i); + if(pDLCInfo->iConfig==tp->getDLCParentPackId()) + { + bTexturePackAlreadyListed=true; + } + } + if(bTexturePackAlreadyListed==false) + { + m_iConfigA[m_iTexturePacksNotInstalled++]=pDLCInfo->iConfig; + } + } + } +#endif + m_currentTexturePackIndex = pMinecraft->skins->getTexturePackIndex(0); + UpdateTexturePackDescription(m_currentTexturePackIndex); + + m_texturePackList.selectSlot(m_currentTexturePackIndex); + m_bIgnoreInput=false; + app.m_dlcManager.checkForCorruptDLCAndAlert(); +} + +void IUIScene_StartGame::handleSelectionChanged(F64 selectedId) +{ + m_iSetTexturePackDescription = (int)selectedId; + + if(!m_texturePackDescDisplayed) + { + m_bShowTexturePackDescription = true; + } +} + +void IUIScene_StartGame::UpdateTexturePackDescription(int index) +{ + TexturePack *tp = Minecraft::GetInstance()->skins->getTexturePackByIndex(index); + + if(tp==NULL) + { +#if TO_BE_IMPLEMENTED + // this is probably a texture pack icon added from TMS + + DWORD dwBytes=0,dwFileBytes=0; + PBYTE pbData=NULL,pbFileData=NULL; + + CXuiCtrl4JList::LIST_ITEM_INFO ListItem; + // get the current index of the list, and then get the data + ListItem=m_pTexturePacksList->GetData(index); + + app.GetTPD(ListItem.iData,&pbData,&dwBytes); + + app.GetFileFromTPD(eTPDFileType_Loc,pbData,dwBytes,&pbFileData,&dwFileBytes ); + if(dwFileBytes > 0 && pbFileData) + { + StringTable *pStringTable = new StringTable(pbFileData, dwFileBytes); + m_texturePackTitle.SetText(pStringTable->getString(L"IDS_DISPLAY_NAME")); + m_texturePackDescription.SetText(pStringTable->getString(L"IDS_TP_DESCRIPTION")); + } + + app.GetFileFromTPD(eTPDFileType_Icon,pbData,dwBytes,&pbFileData,&dwFileBytes ); + if(dwFileBytes >= 0 && pbFileData) + { + XuiCreateTextureBrushFromMemory(pbFileData,dwFileBytes,&m_hTexturePackIconBrush); + m_texturePackIcon->UseBrush(m_hTexturePackIconBrush); + } + app.GetFileFromTPD(eTPDFileType_Comparison,pbData,dwBytes,&pbFileData,&dwFileBytes ); + if(dwFileBytes >= 0 && pbFileData) + { + XuiCreateTextureBrushFromMemory(pbFileData,dwFileBytes,&m_hTexturePackComparisonBrush); + m_texturePackComparison->UseBrush(m_hTexturePackComparisonBrush); + } + else + { + m_texturePackComparison->UseBrush(NULL); + } +#endif + } + else + { + m_labelTexturePackName.setLabel(tp->getName()); + m_labelTexturePackDescription.setLabel(tp->getDesc1()); + + DWORD dwImageBytes; + PBYTE pbImageData = tp->getPackIcon(dwImageBytes); + + //if(dwImageBytes > 0 && pbImageData) + //{ + // registerSubstitutionTexture(L"texturePackIcon", pbImageData, dwImageBytes); + // m_bitmapTexturePackIcon.setTextureName(L"texturePackIcon"); + //} + + wchar_t imageName[64]; + swprintf(imageName,64,L"tpack%08x",tp->getId()); + m_bitmapTexturePackIcon.setTextureName(imageName); + + pbImageData = tp->getPackComparison(dwImageBytes); + + if(dwImageBytes > 0 && pbImageData) + { + swprintf(imageName,64,L"texturePackComparison%08x",tp->getId()); + registerSubstitutionTexture(imageName, pbImageData, dwImageBytes); + m_bitmapComparison.setTextureName(imageName); + } + else + { + m_bitmapComparison.setTextureName(L""); + } + } +} + +void IUIScene_StartGame::UpdateCurrentTexturePack(int iSlot) +{ + m_currentTexturePackIndex = iSlot; + TexturePack *tp = Minecraft::GetInstance()->skins->getTexturePackByIndex(m_currentTexturePackIndex); + + // if the texture pack is null, you don't have it yet + if(tp==NULL) + { +#if TO_BE_IMPLEMENTED + // Upsell + + CXuiCtrl4JList::LIST_ITEM_INFO ListItem; + // get the current index of the list, and then get the data + ListItem=m_pTexturePacksList->GetData(m_currentTexturePackIndex); + + + // upsell the texture pack + // tell sentient about the upsell of the full version of the skin pack + ULONGLONG ullOfferID_Full; + app.GetDLCFullOfferIDForPackID(ListItem.iData,&ullOfferID_Full); + + TelemetryManager->RecordUpsellPresented(ProfileManager.GetPrimaryPad(), eSet_UpsellID_Texture_DLC, ullOfferID_Full & 0xFFFFFFFF); + + UINT uiIDA[3]; + + uiIDA[0]=IDS_TEXTUREPACK_FULLVERSION; + uiIDA[1]=IDS_TEXTURE_PACK_TRIALVERSION; + uiIDA[2]=IDS_CONFIRM_CANCEL; + + + // Give the player a warning about the texture pack missing + ui.RequestMessageBox(IDS_DLC_TEXTUREPACK_NOT_PRESENT_TITLE, IDS_DLC_TEXTUREPACK_NOT_PRESENT, uiIDA, 3, ProfileManager.GetPrimaryPad(),&:TexturePackDialogReturned,this,app.GetStringTable()); + + // do set the texture pack id, and on the user pressing create world, check they have it + m_MoreOptionsParams.dwTexturePack = ListItem.iData; + return ; +#endif + } + else + { + m_MoreOptionsParams.dwTexturePack = tp->getId(); + } +} + +int IUIScene_StartGame::TrialTexturePackWarningReturned(void *pParam,int iPad,C4JStorage::EMessageResult result) +{ + IUIScene_StartGame* pScene = (IUIScene_StartGame*)pParam; + + if(result==C4JStorage::EMessage_ResultAccept) + { + pScene->checkStateAndStartGame(); + } + else + { + pScene->m_bIgnoreInput=false; + } + return 0; +} + +int IUIScene_StartGame::UnlockTexturePackReturned(void *pParam,int iPad,C4JStorage::EMessageResult result) +{ + IUIScene_StartGame* pScene = (IUIScene_StartGame*)pParam; + + if(result==C4JStorage::EMessage_ResultAccept) + { + if(ProfileManager.IsSignedIn(iPad)) + { +#if defined _XBOX //|| defined _XBOX_ONE + ULONGLONG ullIndexA[1]; + DLC_INFO *pDLCInfo = app.GetDLCInfoForTrialOfferID(pScene->m_pDLCPack->getPurchaseOfferId()); + + if(pDLCInfo!=NULL) + { + ullIndexA[0]=pDLCInfo->ullOfferID_Full; + } + else + { + ullIndexA[0]=pScene->m_pDLCPack->getPurchaseOfferId(); + } + + + StorageManager.InstallOffer(1,ullIndexA,NULL,NULL); +#elif defined _XBOX_ONE + //StorageManager.InstallOffer(1,StorageManager.GetOffer(iIndex).wszProductID,NULL,NULL); +#endif + + // the license change coming in when the offer has been installed will cause this scene to refresh + } + } + else + { +#if defined _XBOX + TelemetryManager->RecordUpsellResponded(iPad, eSet_UpsellID_Texture_DLC, ( pScene->m_pDLCPack->getPurchaseOfferId() & 0xFFFFFFFF ), eSen_UpsellOutcome_Declined); +#endif + } + + pScene->m_bIgnoreInput = false; + + return 0; +} + +int IUIScene_StartGame::TexturePackDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result) +{ + IUIScene_StartGame *pClass = (IUIScene_StartGame *)pParam; + + +#ifdef _XBOX + // Exit with or without saving + // Decline means install full version of the texture pack in this dialog + if(result==C4JStorage::EMessage_ResultDecline || result==C4JStorage::EMessage_ResultAccept) + { + // we need to enable background downloading for the DLC + XBackgroundDownloadSetMode(XBACKGROUND_DOWNLOAD_MODE_ALWAYS_ALLOW); + + ULONGLONG ullOfferID_Full; + ULONGLONG ullIndexA[1]; + CXuiCtrl4JList::LIST_ITEM_INFO ListItem; + // get the current index of the list, and then get the data + ListItem=pClass->m_pTexturePacksList->GetData(pClass->m_currentTexturePackIndex); + app.GetDLCFullOfferIDForPackID(ListItem.iData,&ullOfferID_Full); + + if( result==C4JStorage::EMessage_ResultAccept ) // Full version + { + ullIndexA[0]=ullOfferID_Full; + StorageManager.InstallOffer(1,ullIndexA,NULL,NULL); + + } + else // trial version + { + // if there is no trial version, this is a Cancel + DLC_INFO *pDLCInfo=app.GetDLCInfoForFullOfferID(ullOfferID_Full); + if(pDLCInfo->ullOfferID_Trial!=0LL) + { + + ullIndexA[0]=pDLCInfo->ullOfferID_Trial; + StorageManager.InstallOffer(1,ullIndexA,NULL,NULL); + } + } + } +#elif defined _XBOX_ONE + // Get the product id from the texture pack id + if(result==C4JStorage::EMessage_ResultAccept) + { + + if(ProfileManager.IsSignedIn(iPad)) + { + if (ProfileManager.IsSignedInLive(iPad)) + { + wstring ProductId; + app.GetDLCFullOfferIDForPackID(pClass->m_MoreOptionsParams.dwTexturePack,ProductId); + + + StorageManager.InstallOffer(1,(WCHAR *)ProductId.c_str(),NULL,NULL); + + // the license change coming in when the offer has been installed will cause this scene to refresh + } + else + { + // 4J-JEV: Fix for XB1: #165863 - XR-074: Compliance: With no active network connection user is unable to convert from Trial to Full texture pack and is not messaged why. + UINT uiIDA[1] = { IDS_CONFIRM_OK }; + ui.RequestMessageBox(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_XBOXLIVE_NOTIFICATION, uiIDA, 1, iPad, NULL, NULL, app.GetStringTable()); + } + } + } + +#endif + pClass->m_bIgnoreInput=false; + return 0; +}
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/IUIScene_StartGame.h b/Minecraft.Client/Common/UI/IUIScene_StartGame.h new file mode 100644 index 00000000..a3361011 --- /dev/null +++ b/Minecraft.Client/Common/UI/IUIScene_StartGame.h @@ -0,0 +1,48 @@ +#pragma once + +#include "UIScene.h" + +// Shared functions between CreteWorld, Load and Join +class IUIScene_StartGame : public UIScene +{ +protected: + UIControl_TexturePackList m_texturePackList; + + UIControl m_controlTexturePackPanel; + UIControl_Label m_labelTexturePackName, m_labelTexturePackDescription; + UIControl_BitmapIcon m_bitmapTexturePackIcon, m_bitmapComparison; + + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) + UI_MAP_ELEMENT( m_controlTexturePackPanel, "TexturePackPanel" ) + UI_BEGIN_MAP_CHILD_ELEMENTS( m_controlTexturePackPanel ) + UI_MAP_ELEMENT( m_labelTexturePackName, "TexturePackName") + UI_MAP_ELEMENT( m_labelTexturePackDescription, "TexturePackDescription") + UI_MAP_ELEMENT( m_bitmapTexturePackIcon, "Icon") + UI_MAP_ELEMENT( m_bitmapComparison, "ComparisonPic") + UI_END_MAP_CHILD_ELEMENTS() + UI_END_MAP_ELEMENTS_AND_NAMES() + + LaunchMoreOptionsMenuInitData m_MoreOptionsParams; + bool m_bIgnoreInput; + + int m_iTexturePacksNotInstalled; + unsigned int m_currentTexturePackIndex; + bool m_bShowTexturePackDescription; + bool m_texturePackDescDisplayed; + int m_iSetTexturePackDescription; + + IUIScene_StartGame(int iPad, UILayer *parentLayer); + + virtual void checkStateAndStartGame() = 0; + + virtual void handleSelectionChanged(F64 selectedId); + + virtual void HandleDLCMountingComplete(); + + void UpdateTexturePackDescription(int index); + void UpdateCurrentTexturePack(int iSlot); + + static int TrialTexturePackWarningReturned(void *pParam,int iPad,C4JStorage::EMessageResult result); + static int UnlockTexturePackReturned(void *pParam,int iPad,C4JStorage::EMessageResult result); + static int TexturePackDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result); +};
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/IUIScene_TradingMenu.cpp b/Minecraft.Client/Common/UI/IUIScene_TradingMenu.cpp new file mode 100644 index 00000000..658bcdfb --- /dev/null +++ b/Minecraft.Client/Common/UI/IUIScene_TradingMenu.cpp @@ -0,0 +1,387 @@ +#include "stdafx.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.item.trading.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.inventory.h" +#include "..\..\..\Minecraft.World\net.minecraft.network.packet.h" +#include "..\..\Minecraft.h" +#include "..\..\MultiPlayerLocalPlayer.h" +#include "..\..\ClientConnection.h" +#include "IUIScene_TradingMenu.h" + +IUIScene_TradingMenu::IUIScene_TradingMenu() +{ + m_validOffersCount = 0; + m_selectedSlot = 0; + m_offersStartIndex = 0; + m_menu = NULL; + m_bHasUpdatedOnce = false; +} + +shared_ptr<Merchant> IUIScene_TradingMenu::getMerchant() +{ + return m_merchant; +} + +bool IUIScene_TradingMenu::handleKeyDown(int iPad, int iAction, bool bRepeat) +{ + bool handled = false; + //MerchantRecipeList *offers = m_merchant->getOffers(Minecraft::GetInstance()->localplayers[getPad()]); + + bool changed = 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; + } + } + } + + + switch(iAction) + { + case ACTION_MENU_B: + ui.ShowTooltip( iPad, eToolTipButtonX, false ); + ui.ShowTooltip( iPad, eToolTipButtonB, false ); + ui.ShowTooltip( iPad, eToolTipButtonA, false ); + ui.ShowTooltip( iPad, eToolTipButtonRB, false ); + // kill the crafting xui + //ui.PlayUISFX(eSFX_Back); + ui.CloseUIScenes(iPad); + + handled = true; + break; + case ACTION_MENU_A: +#ifdef __ORBIS__ + case ACTION_MENU_TOUCHPAD_PRESS: +#endif + if(!m_activeOffers.empty()) + { + int selectedShopItem = (m_selectedSlot + m_offersStartIndex); + if( selectedShopItem < m_activeOffers.size() ) + { + MerchantRecipe *activeRecipe = m_activeOffers.at(selectedShopItem).first; + if(!activeRecipe->isDeprecated()) + { + // Do we have the ingredients? + shared_ptr<ItemInstance> buyAItem = activeRecipe->getBuyAItem(); + shared_ptr<ItemInstance> buyBItem = activeRecipe->getBuyBItem(); + shared_ptr<MultiplayerLocalPlayer> player = Minecraft::GetInstance()->localplayers[getPad()]; + int buyAMatches = player->inventory->countMatches(buyAItem); + int buyBMatches = player->inventory->countMatches(buyBItem); + if( (buyAItem != NULL && buyAMatches >= buyAItem->count) && (buyBItem == NULL || buyBMatches >= buyBItem->count) ) + { + m_merchant->notifyTrade(activeRecipe); + + // Remove the items we are purchasing with + player->inventory->removeResources(buyAItem); + player->inventory->removeResources(buyBItem); + + // Add the item we have purchased + shared_ptr<ItemInstance> result = activeRecipe->getSellItem()->copy(); + if(!player->inventory->add( result ) ) + { + player->drop(result); + } + + // Send a packet to the server + int actualShopItem = m_activeOffers.at(selectedShopItem).second; + player->connection->send( shared_ptr<TradeItemPacket>( new TradeItemPacket(m_menu->containerId, actualShopItem) ) ); + + updateDisplay(); + } + } + } + } + handled = true; + break; + case ACTION_MENU_LEFT: + handled = true; + if(m_selectedSlot == 0) + { + if(m_offersStartIndex > 0) + { + --m_offersStartIndex; + changed = true; + } + } + else + { + --m_selectedSlot; + changed = true; + moveSelector(false); + } + break; + case ACTION_MENU_RIGHT: + handled = true; + if(m_selectedSlot == (DISPLAY_TRADES_COUNT - 1)) + { + if((m_offersStartIndex + DISPLAY_TRADES_COUNT) < m_activeOffers.size()) + { + ++m_offersStartIndex; + changed = true; + } + } + else + { + ++m_selectedSlot; + changed = true; + moveSelector(true); + } + break; + } + if (changed) + { + updateDisplay(); + + int selectedShopItem = (m_selectedSlot + m_offersStartIndex); + if( selectedShopItem < m_activeOffers.size() ) + { + int actualShopItem = m_activeOffers.at(selectedShopItem).second; + m_menu->setSelectionHint(actualShopItem); + + ByteArrayOutputStream rawOutput; + DataOutputStream output(&rawOutput); + output.writeInt(actualShopItem); + Minecraft::GetInstance()->getConnection(getPad())->send(shared_ptr<CustomPayloadPacket>( new CustomPayloadPacket(CustomPayloadPacket::TRADER_SELECTION_PACKET, rawOutput.toByteArray()))); + } + } + return handled; +} + +void IUIScene_TradingMenu::handleTick() +{ + int offerCount = 0; + MerchantRecipeList *offers = m_merchant->getOffers(Minecraft::GetInstance()->localplayers[getPad()]); + if (offers != NULL) + { + offerCount = offers->size(); + + if(!m_bHasUpdatedOnce) + { + updateDisplay(); + } + } + + showScrollRightArrow( (m_offersStartIndex + DISPLAY_TRADES_COUNT) < m_activeOffers.size()); + showScrollLeftArrow(m_offersStartIndex > 0); +} + +void IUIScene_TradingMenu::updateDisplay() +{ + int iA = -1; + + MerchantRecipeList *unfilteredOffers = m_merchant->getOffers(Minecraft::GetInstance()->localplayers[getPad()]); + if (unfilteredOffers != NULL) + { + m_activeOffers.clear(); + int unfilteredIndex = 0; + int firstValidTrade = INT_MAX; + for(AUTO_VAR(it, unfilteredOffers->begin()); it != unfilteredOffers->end(); ++it) + { + MerchantRecipe *recipe = *it; + if(!recipe->isDeprecated()) + { + m_activeOffers.push_back( pair<MerchantRecipe *,int>(recipe,unfilteredIndex)); + firstValidTrade = min(firstValidTrade,unfilteredIndex); + } + ++unfilteredIndex; + } + + if(!m_bHasUpdatedOnce) + { + if(firstValidTrade != 0 && firstValidTrade < unfilteredOffers->size()) + { + m_menu->setSelectionHint(firstValidTrade); + + ByteArrayOutputStream rawOutput; + DataOutputStream output(&rawOutput); + output.writeInt(firstValidTrade); + Minecraft::GetInstance()->getConnection(getPad())->send(shared_ptr<CustomPayloadPacket>( new CustomPayloadPacket(CustomPayloadPacket::TRADER_SELECTION_PACKET, rawOutput.toByteArray()))); + } + } + + if( (m_offersStartIndex + DISPLAY_TRADES_COUNT) > m_activeOffers.size()) + { + m_offersStartIndex = m_activeOffers.size() - DISPLAY_TRADES_COUNT; + if(m_offersStartIndex < 0) m_offersStartIndex = 0; + } + + for(unsigned int i = 0; i < DISPLAY_TRADES_COUNT; ++i) + { + int offerIndex = i + m_offersStartIndex; + bool showRedBox = false; + if(offerIndex < m_activeOffers.size()) + { + showRedBox = !canMake(m_activeOffers.at(offerIndex).first); + setTradeItem(i, m_activeOffers.at(offerIndex).first->getSellItem() ); + } + else + { + setTradeItem(i, nullptr); + } + setTradeRedBox( i, showRedBox); + } + + int selectedShopItem = (m_selectedSlot + m_offersStartIndex); + if( selectedShopItem < m_activeOffers.size() ) + { + MerchantRecipe *activeRecipe = m_activeOffers.at(selectedShopItem).first; + + wstring wsTemp; + + // 4J-PB - need to get the villager type here + wsTemp = app.GetString(IDS_VILLAGER_OFFERS_ITEM); + wsTemp = replaceAll(wsTemp,L"{*VILLAGER_TYPE*}",app.GetString(m_merchant->getDisplayName())); + int iPos=wsTemp.find(L"%s"); + wsTemp.replace(iPos,2,activeRecipe->getSellItem()->getHoverName()); + + setTitle(wsTemp.c_str()); + + vector<wstring> unformattedStrings; + wstring offerDescription = GetItemDescription(activeRecipe->getSellItem(), unformattedStrings); + setOfferDescription(offerDescription, unformattedStrings); + + shared_ptr<ItemInstance> buyAItem = activeRecipe->getBuyAItem(); + shared_ptr<ItemInstance> buyBItem = activeRecipe->getBuyBItem(); + + setRequest1Item(buyAItem); + setRequest2Item(buyBItem); + + if(buyAItem != NULL) setRequest1Name(buyAItem->getHoverName()); + else setRequest1Name(L""); + + if(buyBItem != NULL) setRequest2Name(buyBItem->getHoverName()); + else setRequest2Name(L""); + + bool canMake = true; + + shared_ptr<MultiplayerLocalPlayer> player = Minecraft::GetInstance()->localplayers[getPad()]; + int buyAMatches = player->inventory->countMatches(buyAItem); + if(buyAMatches > 0) + { + setRequest1RedBox(buyAMatches < buyAItem->count); + canMake = buyAMatches > buyAItem->count; + } + else + { + setRequest1RedBox(true); + canMake = false; + } + + int buyBMatches = player->inventory->countMatches(buyBItem); + if(buyBMatches > 0) + { + setRequest2RedBox(buyBMatches < buyBItem->count); + canMake = canMake && buyBMatches > buyBItem->count; + } + else + { + if(buyBItem!=NULL) + { + setRequest2RedBox(true); + canMake = false; + } + else + { + setRequest2RedBox(buyBItem != NULL); + canMake = canMake && buyBItem == NULL; + } + } + + if(canMake) iA = IDS_TOOLTIPS_TRADE; + } + else + { + setTitle(app.GetString(m_merchant->getDisplayName())); + setRequest1Name(L""); + setRequest2Name(L""); + setRequest1RedBox(false); + setRequest2RedBox(false); + setRequest1Item(nullptr); + setRequest2Item(nullptr); + } + + m_bHasUpdatedOnce = true; + } + + ui.SetTooltips(getPad(), iA, IDS_TOOLTIPS_EXIT); +} + +bool IUIScene_TradingMenu::canMake(MerchantRecipe *recipe) +{ + bool canMake = false; + if (recipe != NULL) + { + if(recipe->isDeprecated()) return false; + + shared_ptr<ItemInstance> buyAItem = recipe->getBuyAItem(); + shared_ptr<ItemInstance> buyBItem = recipe->getBuyBItem(); + + shared_ptr<MultiplayerLocalPlayer> player = Minecraft::GetInstance()->localplayers[getPad()]; + int buyAMatches = player->inventory->countMatches(buyAItem); + if(buyAMatches > 0) + { + canMake = buyAMatches >= buyAItem->count; + } + else + { + canMake = buyAItem == NULL; + } + + int buyBMatches = player->inventory->countMatches(buyBItem); + if(buyBMatches > 0) + { + canMake = canMake && buyBMatches >= buyBItem->count; + } + else + { + canMake = canMake && buyBItem == NULL; + } + } + return canMake; +} + + +void IUIScene_TradingMenu::setRequest1Item(shared_ptr<ItemInstance> item) +{ +} + +void IUIScene_TradingMenu::setRequest2Item(shared_ptr<ItemInstance> item) +{ +} + +void IUIScene_TradingMenu::setTradeItem(int index, shared_ptr<ItemInstance> item) +{ +} + +wstring IUIScene_TradingMenu::GetItemDescription(shared_ptr<ItemInstance> item, vector<wstring> &unformattedStrings) +{ + if(item == NULL) return L""; + + wstring desc = L""; + vector<wstring> *strings = item->getHoverTextOnly(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; + } + desc.append( thisString ); + } + strings->clear(); + delete strings; + return desc; +} diff --git a/Minecraft.Client/Common/UI/IUIScene_TradingMenu.h b/Minecraft.Client/Common/UI/IUIScene_TradingMenu.h new file mode 100644 index 00000000..c8edda67 --- /dev/null +++ b/Minecraft.Client/Common/UI/IUIScene_TradingMenu.h @@ -0,0 +1,58 @@ +#pragma once +#include "..\Minecraft.World\MerchantMenu.h" + +class MerchantRecipe; + +class IUIScene_TradingMenu +{ +protected: + MerchantMenu *m_menu; + shared_ptr<Merchant> m_merchant; + vector< pair<MerchantRecipe *,int> > m_activeOffers; + + int m_validOffersCount; + int m_selectedSlot; + int m_offersStartIndex; + bool m_bHasUpdatedOnce; + + eTutorial_State m_previousTutorialState; + + static const int DISPLAY_TRADES_COUNT = 7; + + static const int BUY_A = MerchantMenu::USE_ROW_SLOT_END; + static const int BUY_B = BUY_A + 1; + static const int TRADES_START = BUY_B + 1; + +protected: + IUIScene_TradingMenu(); + + bool handleKeyDown(int iPad, int iAction, bool bRepeat); + void handleTick(); + + virtual void showScrollRightArrow(bool show) = 0; + virtual void showScrollLeftArrow(bool show) = 0; + virtual void moveSelector(bool right) = 0; + virtual void setRequest1Name(const wstring &name) = 0; + virtual void setRequest2Name(const wstring &name) = 0; + virtual void setTitle(const wstring &name) = 0; + + virtual void setRequest1RedBox(bool show) = 0; + virtual void setRequest2RedBox(bool show) = 0; + virtual void setTradeRedBox(int index, bool show) = 0; + + virtual void setOfferDescription(const wstring &name, vector<wstring> &unformattedStrings) = 0; + + virtual void setRequest1Item(shared_ptr<ItemInstance> item); + virtual void setRequest2Item(shared_ptr<ItemInstance> item); + virtual void setTradeItem(int index, shared_ptr<ItemInstance> item); + +private: + void updateDisplay(); + bool canMake(MerchantRecipe *recipe); + wstring GetItemDescription(shared_ptr<ItemInstance> item, vector<wstring> &unformattedStrings); + +public: + shared_ptr<Merchant> getMerchant(); + + virtual int getPad() = 0; +};
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UI.h b/Minecraft.Client/Common/UI/UI.h new file mode 100644 index 00000000..622ccf84 --- /dev/null +++ b/Minecraft.Client/Common/UI/UI.h @@ -0,0 +1,118 @@ +#pragma once + +#include "UIEnums.h" +#include "UIStructs.h" + +#include "UIBitmapFont.h" +#include "UITTFFont.h" + +#include "UIScene.h" +#include "UILayer.h" +#include "UIGroup.h" +#include "UIController.h" + +#include "UIControl.h" +#include "UIControl_Base.h" +#include "UIControl_Button.h" +#include "UIControl_CheckBox.h" +#include "UIControl_Slider.h" +#include "UIControl_Label.h" +#include "UIControl_TextInput.h" +#include "UIControl_SlotList.h" +#include "UIControl_Cursor.h" +#include "UIControl_ButtonList.h" +#include "UIControl_Progress.h" +#include "UIControl_TexturePackList.h" +#include "UIControl_LeaderboardList.h" +#include "UIControl_SaveList.h" +#include "UIControl_PlayerList.h" +#include "UIControl_BitmapIcon.h" +#include "UIControl_DLCList.h" +#include "UIControl_HTMLLabel.h" +#include "UIControl_DynamicLabel.h" +#include "UIControl_MinecraftPlayer.h" +#include "UIControl_PlayerSkinPreview.h" +#include "UIControl_EnchantmentButton.h" +#include "UIControl_EnchantmentBook.h" +#include "UIControl_SpaceIndicatorBar.h" + +#ifdef __PSVITA__ +#include "UIControl_Touch.h" +#endif + +#include "UIScene_HUD.h" +#include "UIComponent_Panorama.h" +#include "UIComponent_Logo.h" +#include "UIComponent_Tooltips.h" +#include "UIComponent_TutorialPopup.h" +#include "UIComponent_Chat.h" +#include "UIComponent_PressStartToPlay.h" +#include "UIComponent_MenuBackground.h" + +#include "UIScene_QuadrantSignin.h" +#include "UIScene_MessageBox.h" +#include "UIScene_Timer.h" +#include "UIScene_Keyboard.h" + +#include "UIScene_DebugOverlay.h" +#include "UIScene_DebugOptions.h" +#include "UIComponent_DebugUIConsole.h" +#include "UIComponent_DebugUIMarketingGuide.h" +#include "UIScene_DebugSetCamera.h" +#include "UIScene_DebugCreateSchematic.h" + +#include "UIScene_TrialExitUpsell.h" +#include "UIScene_Intro.h" +#include "UIScene_SaveMessage.h" +#include "UIScene_MainMenu.h" +#include "UIScene_LoadMenu.h" +#include "UIScene_JoinMenu.h" +#include "UIScene_LoadOrJoinMenu.h" +#include "UIScene_CreateWorldMenu.h" +#include "UIScene_LaunchMoreOptionsMenu.h" +#include "UIScene_FullscreenProgress.h" +#include "UIScene_LeaderboardsMenu.h" +#include "UIScene_DLCMainMenu.h" +#include "UIScene_DLCOffersMenu.h" +#include "UIScene_ReinstallMenu.h" + +#include "UIScene_HelpAndOptionsMenu.h" +#include "UIScene_SettingsMenu.h" +#include "UIScene_SettingsOptionsMenu.h" +#include "UIScene_SettingsAudioMenu.h" +#include "UIScene_SettingsControlMenu.h" +#include "UIScene_SettingsGraphicsMenu.h" +#include "UIScene_SettingsUIMenu.h" +#include "UIScene_SkinSelectMenu.h" +#include "UIScene_HowToPlayMenu.h" +#include "UIScene_HowToPlay.h" +#include "UIScene_ControlsMenu.h" +#include "UIScene_Credits.h" + +#include "UIScene_PauseMenu.h" + +#include "UIScene_AbstractContainerMenu.h" +#include "UIScene_BrewingStandMenu.h" +#include "UIScene_ContainerMenu.h" +#include "UIScene_DispenserMenu.h" +#include "UIScene_EnchantingMenu.h" +#include "UIScene_InventoryMenu.h" +#include "UIScene_FurnaceMenu.h" +#include "UIScene_CreativeMenu.h" +#include "UIScene_TradingMenu.h" +#include "UIScene_AnvilMenu.h" + +#include "UIScene_CraftingMenu.h" +#include "UIScene_SignEntryMenu.h" + +#include "UIScene_ConnectingProgress.h" +#include "UIScene_DeathMenu.h" +#include "UIScene_InGameInfoMenu.h" +#include "UIScene_InGameHostOptionsMenu.h" +#include "UIScene_InGamePlayerOptionsMenu.h" +#if defined(_XBOX_ONE) || defined(__ORBIS__) +#include "UIScene_InGameSaveManagementMenu.h" +#endif +#include "UIScene_TeleportMenu.h" +#include "UIScene_EndPoem.h" +#include "UIScene_EULA.h" diff --git a/Minecraft.Client/Common/UI/UIBitmapFont.cpp b/Minecraft.Client/Common/UI/UIBitmapFont.cpp new file mode 100644 index 00000000..ec49eea3 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIBitmapFont.cpp @@ -0,0 +1,364 @@ +#include "stdafx.h" + +#include "BufferedImage.h" +#include "UIFontData.h" + +#include <unordered_set> + +#include "UIBitmapFont.h" + + +///////////////////////////// +// UI Abstract Bitmap Font // +///////////////////////////// + +UIAbstractBitmapFont::~UIAbstractBitmapFont() +{ + if (m_registered) IggyFontRemoveUTF8( m_fontname.c_str(),-1,IGGY_FONTFLAG_none ); + delete m_bitmapFontProvider; +} + + +UIAbstractBitmapFont::UIAbstractBitmapFont(const string &fontname) +{ + m_fontname = fontname; + + m_registered = false; + + m_bitmapFontProvider = new IggyBitmapFontProvider(); + m_bitmapFontProvider->get_font_metrics = &UIAbstractBitmapFont::GetFontMetrics_Callback; + m_bitmapFontProvider->get_glyph_for_codepoint = &UIAbstractBitmapFont::GetCodepointGlyph_Callback; + m_bitmapFontProvider->get_glyph_metrics = &UIAbstractBitmapFont::GetGlyphMetrics_Callback; + m_bitmapFontProvider->is_empty = &UIAbstractBitmapFont::IsGlyphEmpty_Callback; + m_bitmapFontProvider->get_kerning = &UIAbstractBitmapFont::GetKerningForGlyphPair_Callback; + m_bitmapFontProvider->can_bitmap = &UIAbstractBitmapFont::CanProvideBitmap_Callback; + m_bitmapFontProvider->get_bitmap = &UIAbstractBitmapFont::GetGlyphBitmap_Callback; + m_bitmapFontProvider->free_bitmap = &UIAbstractBitmapFont::FreeGlyphBitmap_Callback; + m_bitmapFontProvider->userdata = this; +} + +void UIAbstractBitmapFont::registerFont() +{ + if(m_registered) + { + return; + } + + m_bitmapFontProvider->num_glyphs = m_numGlyphs; + + IggyFontInstallBitmapUTF8( m_bitmapFontProvider,m_fontname.c_str(),-1,IGGY_FONTFLAG_none ); + IggyFontSetIndirectUTF8( m_fontname.c_str(),-1 ,IGGY_FONTFLAG_all ,m_fontname.c_str() ,-1 ,IGGY_FONTFLAG_none ); + m_registered = true; +} + +IggyFontMetrics * RADLINK UIAbstractBitmapFont::GetFontMetrics_Callback(void *user_context,IggyFontMetrics *metrics) +{ + return ((UIAbstractBitmapFont *) user_context)->GetFontMetrics(metrics); +} + +S32 RADLINK UIAbstractBitmapFont::GetCodepointGlyph_Callback(void *user_context,U32 codepoint) +{ + return ((UIAbstractBitmapFont *) user_context)->GetCodepointGlyph(codepoint); +} + +IggyGlyphMetrics * RADLINK UIAbstractBitmapFont::GetGlyphMetrics_Callback(void *user_context,S32 glyph,IggyGlyphMetrics *metrics) +{ + return ((UIAbstractBitmapFont *) user_context)->GetGlyphMetrics(glyph,metrics); +} + +rrbool RADLINK UIAbstractBitmapFont::IsGlyphEmpty_Callback(void *user_context,S32 glyph) +{ + return ((UIAbstractBitmapFont *) user_context)->IsGlyphEmpty(glyph); +} + +F32 RADLINK UIAbstractBitmapFont::GetKerningForGlyphPair_Callback(void *user_context,S32 first_glyph,S32 second_glyph) +{ + return ((UIAbstractBitmapFont *) user_context)->GetKerningForGlyphPair(first_glyph,second_glyph); +} + +rrbool RADLINK UIAbstractBitmapFont::CanProvideBitmap_Callback(void *user_context,S32 glyph,F32 pixel_scale) +{ + return ((UIAbstractBitmapFont *) user_context)->CanProvideBitmap(glyph,pixel_scale); +} + +rrbool RADLINK UIAbstractBitmapFont::GetGlyphBitmap_Callback(void *user_context,S32 glyph,F32 pixel_scale,IggyBitmapCharacter *bitmap) +{ + return ((UIAbstractBitmapFont *) user_context)->GetGlyphBitmap(glyph,pixel_scale,bitmap); +} + +void RADLINK UIAbstractBitmapFont::FreeGlyphBitmap_Callback(void *user_context,S32 glyph,F32 pixel_scale,IggyBitmapCharacter *bitmap) +{ + return ((UIAbstractBitmapFont *) user_context)->FreeGlyphBitmap(glyph,pixel_scale,bitmap); +} + +UIBitmapFont::UIBitmapFont( SFontData &sfontdata ) + : UIAbstractBitmapFont( sfontdata.m_strFontName ) +{ + m_numGlyphs = sfontdata.m_uiGlyphCount; + + BufferedImage bimg(sfontdata.m_wstrFilename); + int *bimgData = bimg.getData(); + + m_cFontData = new CFontData(sfontdata, bimgData); + + //delete [] bimgData; +} + +UIBitmapFont::~UIBitmapFont() +{ + m_cFontData->release(); +} + +//Callback function type for returning vertical font metrics +IggyFontMetrics *UIBitmapFont::GetFontMetrics(IggyFontMetrics *metrics) +{ + //Description + // Vertical metrics for a font + //Members + // ascent - extent of characters above baseline (positive) + // descent - extent of characters below baseline (positive) + // line_gap - spacing between one row's descent and the next line's ascent + // average_glyph_width_for_tab_stops - spacing of "average" character for computing default tab stops + // largest_glyph_bbox_y1 - lowest point below baseline of any character in the font + + metrics->ascent = m_cFontData->getFontData()->m_fAscent; + metrics->descent = m_cFontData->getFontData()->m_fDescent; + + metrics->average_glyph_width_for_tab_stops = 8.0f; + + // This is my best guess, there's no reference to a specific glyph here + // so aren't these just exactly the same. + metrics->largest_glyph_bbox_y1 = metrics->descent; + + // metrics->line_gap; // 4J-JEV: Sean said this does nothing. + + return metrics; +} + +//Callback function type for mapping 32-bit unicode code point to internal font glyph number; use IGGY_GLYPH_INVALID to mean "invalid character" +S32 UIBitmapFont::GetCodepointGlyph(U32 codepoint) +{ + // 4J-JEV: Change "right single quotation marks" to apostrophies. + if (codepoint == 0x2019) codepoint = 0x27; + + return m_cFontData->getGlyphId(codepoint); +} + +//Callback function type for returning horizontal metrics for each glyph +IggyGlyphMetrics * UIBitmapFont::GetGlyphMetrics(S32 glyph,IggyGlyphMetrics *metrics) +{ + // 4J-JEV: Information about 'Glyph Metrics'. + // http://freetype.sourceforge.net/freetype2/docs/glyphs/glyphs-3.html - Overview. + // http://en.wikipedia.org/wiki/Kerning#Kerning_values - 'Font Units' + + //Description + // Horizontal metrics for a glyph + //Members + // x0 y0 x1 y1 - bounding box + // advance - horizontal distance to move character origin after drawing this glyph + + + /* 4J-JEV: *IMPORTANT* + * + * I believe these are measured wrt the scale mentioned in GetGlyphBitmap + * i.e. 1.0f == pixel_scale, + * + * However we do not have that information here, then all these values need to be + * the same for every scale in this font. + * + * We have 2 scales of bitmap glyph, and we can only scale these up by powers of 2 + * otherwise the fonts will become blurry. The appropriate glyph is chosen in + * 'GetGlyphBitmap' however we need to set the horizontal sizes here. + */ + + float glyphAdvance = m_cFontData->getAdvance(glyph); + + // 4J-JEV: Anything outside this measurement will be + // cut off if it's at the start or end of the row. + metrics->x0 = 0.0f; + + if ( m_cFontData->glyphIsWhitespace(glyph) ) + metrics->x1 = 0.0f; + else + metrics->x1 = glyphAdvance; + + // The next Glyph just starts right after this one. + metrics->advance = glyphAdvance; + + //app.DebugPrintf("[UIBitmapFont] GetGlyphMetrics:\n\tmetrics->advance == %f,\n", metrics->advance); + + // These don't do anything either. + metrics->y0 = 0.0f; metrics->y1 = 1.0f; + + return metrics; +} + +//Callback function type that should return true iff the glyph has no visible elements +rrbool UIBitmapFont::IsGlyphEmpty (S32 glyph) +{ + if (m_cFontData->glyphIsWhitespace(glyph)) return true; + return false;//app.DebugPrintf("Is glyph %d empty? %s\n",glyph,isEmpty?"TRUE":"FALSE"); +} + +//Callback function type for returning the kerning amount for a given pair of glyphs +F32 UIBitmapFont::GetKerningForGlyphPair(S32 first_glyph,S32 second_glyph) +{ + //UIBitmapFont *uiFont = (UIBitmapFont *) user_context; + //app.DebugPrintf("Get kerning for glyph pair %d,%d\n",first_glyph,second_glyph); + + // 4J-JEV: Yet another field that doesn't do anything. + // Only set out of paranoia. + return 0.0f; +} + +//Callback function type used for reporting whether a bitmap supports a given glyph at the given scale +rrbool UIBitmapFont::CanProvideBitmap(S32 glyph,F32 pixel_scale) +{ + //app.DebugPrintf("Can provide bitmap for glyph %d at scale %f? %s\n",glyph,pixel_scale,canProvideBitmap?"TRUE":"FALSE"); + return true; +} + +// Description +// Callback function type used for getting the bitmap for a given glyph +// Parameters +// glyph The glyph to compute/get the bitmap for +// pixel_scale The scale factor (pseudo point size) requested by the textfield,adjusted for display resolution +// bitmap The structure to store the bitmap into +rrbool UIBitmapFont::GetGlyphBitmap(S32 glyph,F32 pixel_scale,IggyBitmapCharacter *bitmap) +{ + //Description + // Data structure used to return to Iggy the bitmap to use for a glyph + //Members + // pixels_one_per_byte - pixels startin with the top-left-most; 0 is transparent and 255 is opaque + // width_in_pixels - this is the width of the bitmap data + // height_in_pixels - this is the height of the bitmap data + // stride_in_bytes - the distance from one row to the next + // oversample - this is the amount of oversampling (0 or 1 = not oversample,2 = 2x oversampled,4 = 4x oversampled) + // point_sample - if true,the bitmap will be drawn with point sampling; if false,it will be drawn with bilinear + // top_left_x - the offset of the top left corner from the character origin + // top_left_y - the offset of the top left corner from the character origin + // pixel_scale_correct - the pixel_scale at which this character should be displayed at displayed_width_in_pixels + // pixel_scale_min - the smallest pixel_scale to allow using this character (scaled down) + // pixel_scale_max - the largest pixels cale to allow using this character (scaled up) + // user_context_for_free - you can use this to store data to access on the corresponding free call + + int row = 0,col = 0; + m_cFontData->getPos(glyph,row,col); + + // Skip to glyph start. + bitmap->pixels_one_per_byte = m_cFontData->topLeftPixel(row,col); + + // Choose a reasonable glyph scale. + float glyphScale = 1.0f, truePixelScale = 1.0f / m_cFontData->getFontData()->m_fAdvPerPixel; + F32 targetPixelScale = pixel_scale; + //if(!RenderManager.IsWidescreen()) + //{ + // // Fix for different scales in 480 + // targetPixelScale = pixel_scale*2/3; + //} + while ( (0.5f + glyphScale) * truePixelScale < targetPixelScale) + glyphScale++; + + // 4J-JEV: Debug code to check which font sizes are being used. +#if (!defined _CONTENT_PACKAGE) && (VERBOSE_FONT_OUTPUT > 0) + + struct DebugData + { + string name; + long scale; + long mul; + + bool operator==(const DebugData& dd) const + { + if ( name.compare(dd.name) != 0 ) return false; + else if (scale != dd.scale) return false; + else if (mul != dd.mul) return false; + else return true; + } + }; + + static long long lastPrint = System::currentTimeMillis(); + static unordered_set<DebugData> debug_fontSizesRequested; + + { + DebugData dData = { m_cFontData->getFontName(), (long) pixel_scale, (long) glyphScale }; + debug_fontSizesRequested.insert(dData); + + if ( (lastPrint - System::currentTimeMillis()) > VERBOSE_FONT_OUTPUT ) + { + app.DebugPrintf("<UIBitmapFont> Requested font/sizes:\n"); + + unordered_set<DebugData>::iterator itr; + for ( itr = debug_fontSizesRequested.begin(); + itr != debug_fontSizesRequested.end(); + itr++ + ) + { + app.DebugPrintf("<UIBitmapFont>\t- %s:%i\t(x%i)\n", itr->name.c_str(), itr->scale, itr->mul); + } + + lastPrint = System::currentTimeMillis(); + debug_fontSizesRequested.clear(); + } + } +#endif + + //app.DebugPrintf("Request glyph_%d (U+%.4X) at %f, converted to %f (%f)\n", + // glyph, GetUnicode(glyph), pixel_scale, targetPixelScale, glyphScale); + + // It is not necessary to shrink the glyph width here + // as its already been done in 'GetGlyphMetrics' by: + // > metrics->x1 = m_kerningTable[glyph] * ratio; + bitmap->width_in_pixels = m_cFontData->getFontData()->m_uiGlyphWidth; + bitmap->height_in_pixels = m_cFontData->getFontData()->m_uiGlyphHeight; + + /* 4J-JEV: This is to do with glyph placement, + * and not the position in the archive. + * I don't know why the 0.65 is needed, or what it represents, + * although it doesn't look like its the baseline. + */ + bitmap->top_left_x = 0; + + // 4J-PB - this was chopping off the top of the characters, so accented ones were losing a couple of pixels at the top + // DaveK has reduced the height of the accented capitalised characters, and we've dropped this from 0.65 to 0.64 + bitmap->top_left_y = -((S32) m_cFontData->getFontData()->m_uiGlyphHeight) * m_cFontData->getFontData()->m_fAscent; + + bitmap->oversample = 0; + bitmap->point_sample = true; + + // 4J-JEV: + // pixel_scale == font size chosen in flash. + // bitmap->pixel_scale_correct = (float) m_glyphHeight; // Scales the glyph to desired size. + // bitmap->pixel_scale_correct = pixel_scale; // Always the same size (not desired size). + // bitmap->pixel_scale_correct = pixel_scale * 0.5; // Doubles original size. + // bitmap->pixel_scale_correct = pixel_scale * 2; // Halves original size. + + // Actual scale, and possible range of scales. + bitmap->pixel_scale_correct = pixel_scale / glyphScale; + bitmap->pixel_scale_max = 99.0f; + bitmap->pixel_scale_min = 0.0f; + + /* 4J-JEV: Some of Sean's code. + int glyphScaleMin = 1; + int glyphScaleMax = 3; + float actualScale = pixel_scale / glyphScale; + bitmap->pixel_scale_correct = actualScale; + bitmap->pixel_scale_min = actualScale * glyphScaleMin * 0.999f; + bitmap->pixel_scale_max = actualScale * glyphScaleMax * 1.001f; */ + + // 4J-JEV: Nothing to do with glyph placement, + // entirely to do with cropping your glyph out of an archive. + bitmap->stride_in_bytes = m_cFontData->getFontData()->m_uiGlyphMapX; + + // 4J-JEV: Additional information needed to release memory afterwards. + bitmap->user_context_for_free = NULL; + + return true; +} + +//Callback function type for freeing a bitmap shape returned by GetGlyphBitmap +void RADLINK UIBitmapFont::FreeGlyphBitmap(S32 glyph,F32 pixel_scale,IggyBitmapCharacter *bitmap) +{ + // We don't need to free anything,it just comes from the archive. + //app.DebugPrintf("Free bitmap for glyph %d at scale %f\n",glyph,pixel_scale); +} diff --git a/Minecraft.Client/Common/UI/UIBitmapFont.h b/Minecraft.Client/Common/UI/UIBitmapFont.h new file mode 100644 index 00000000..62b708fb --- /dev/null +++ b/Minecraft.Client/Common/UI/UIBitmapFont.h @@ -0,0 +1,75 @@ +#pragma once + +struct SFontData; +class CFontData; + +#define VERBOSE_FONT_OUTPUT 0 + +// const int BITMAP_FONT_LANGUAGES = XC_LANGUAGE_ENGLISH +// | XC_LANGUAGE_GERMAN +// | XC_LANGUAGE_FRENCH +// | XC_LANGUAGE_SPANISH +// | XC_LANGUAGE_ITALIAN +// | XC_LANGUAGE_PORTUGUESE +// | XC_LANGUAGE_BRAZILIAN; + +using namespace std; + +class UIAbstractBitmapFont +{ +protected: + string m_fontname; + + IggyBitmapFontProvider *m_bitmapFontProvider; + + bool m_registered; + + unsigned int m_numGlyphs; + +public: + UIAbstractBitmapFont(const string &fontname); + ~UIAbstractBitmapFont(); + + void registerFont(); + + // Virtual Functions. + virtual IggyFontMetrics *GetFontMetrics(IggyFontMetrics *metrics) = 0; + virtual S32 GetCodepointGlyph(U32 codepoint) = 0; + virtual IggyGlyphMetrics *GetGlyphMetrics(S32 glyph, IggyGlyphMetrics *metrics) = 0; + virtual rrbool IsGlyphEmpty(S32 glyph) = 0; + virtual F32 GetKerningForGlyphPair(S32 first_glyph, S32 second_glyph) = 0; + virtual rrbool CanProvideBitmap(S32 glyph, F32 pixel_scale) = 0; + virtual rrbool GetGlyphBitmap(S32 glyph, F32 pixel_scale, IggyBitmapCharacter *bitmap) = 0; + virtual void FreeGlyphBitmap(S32 glyph, F32 pixel_scale, IggyBitmapCharacter *bitmap) = 0; + + // Static Callbacks + // Just wrappers for the virtual functions. + static IggyFontMetrics * RADLINK GetFontMetrics_Callback(void *user_context, IggyFontMetrics *metrics); + static S32 RADLINK GetCodepointGlyph_Callback(void *user_context, U32 codepoint); + static IggyGlyphMetrics * RADLINK GetGlyphMetrics_Callback(void *user_context, S32 glyph, IggyGlyphMetrics *metrics); + static rrbool RADLINK IsGlyphEmpty_Callback(void *user_context, S32 glyph); + static F32 RADLINK GetKerningForGlyphPair_Callback(void *user_context, S32 first_glyph, S32 second_glyph); + static rrbool RADLINK CanProvideBitmap_Callback(void *user_context, S32 glyph, F32 pixel_scale); + static rrbool RADLINK GetGlyphBitmap_Callback(void *user_context, S32 glyph, F32 pixel_scale, IggyBitmapCharacter *bitmap); + static void RADLINK FreeGlyphBitmap_Callback(void *user_context, S32 glyph, F32 pixel_scale, IggyBitmapCharacter *bitmap); +}; + +class UIBitmapFont : public UIAbstractBitmapFont +{ +protected: + CFontData *m_cFontData; + +public: + UIBitmapFont(SFontData &sfontdata); + + ~UIBitmapFont(); + + virtual IggyFontMetrics * GetFontMetrics(IggyFontMetrics *metrics); + virtual S32 GetCodepointGlyph(U32 codepoint); + virtual IggyGlyphMetrics * GetGlyphMetrics(S32 glyph, IggyGlyphMetrics *metrics); + virtual rrbool IsGlyphEmpty(S32 glyph); + virtual F32 GetKerningForGlyphPair(S32 first_glyph, S32 second_glyph); + virtual rrbool CanProvideBitmap(S32 glyph, F32 pixel_scale); + virtual rrbool GetGlyphBitmap(S32 glyph, F32 pixel_scale, IggyBitmapCharacter *bitmap); + virtual void FreeGlyphBitmap(S32 glyph, F32 pixel_scale, IggyBitmapCharacter *bitmap); +};
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIComponent_Chat.cpp b/Minecraft.Client/Common/UI/UIComponent_Chat.cpp new file mode 100644 index 00000000..98b4f165 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIComponent_Chat.cpp @@ -0,0 +1,157 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIComponent_Chat.h" +#include "..\..\Minecraft.h" +#include "..\..\Gui.h" + +UIComponent_Chat::UIComponent_Chat(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) +{ + // Setup all the Iggy references we need for this scene + initialiseMovie(); + + for(unsigned int i = 0; i < CHAT_LINES_COUNT; ++i) + { + m_labelChatText[i].init(L""); + } + m_labelJukebox.init(L""); + + addTimer(0, 100); +} + +wstring UIComponent_Chat::getMoviePath() +{ + switch( m_parentLayer->getViewport() ) + { + case C4JRender::VIEWPORT_TYPE_SPLIT_TOP: + case C4JRender::VIEWPORT_TYPE_SPLIT_BOTTOM: + case C4JRender::VIEWPORT_TYPE_SPLIT_LEFT: + case C4JRender::VIEWPORT_TYPE_SPLIT_RIGHT: + case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_LEFT: + case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_RIGHT: + case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_LEFT: + case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_RIGHT: + m_bSplitscreen = true; + return L"ComponentChatSplit"; + break; + case C4JRender::VIEWPORT_TYPE_FULLSCREEN: + default: + m_bSplitscreen = false; + return L"ComponentChat"; + break; + } +} + +void UIComponent_Chat::handleTimerComplete(int id) +{ + Minecraft *pMinecraft = Minecraft::GetInstance(); + + bool anyVisible = false; + if(pMinecraft->localplayers[m_iPad]!= NULL) + { + Gui *pGui = pMinecraft->gui; + //DWORD messagesToDisplay = min( CHAT_LINES_COUNT, pGui->getMessagesCount(m_iPad) ); + for( unsigned int i = 0; i < CHAT_LINES_COUNT; ++i ) + { + float opacity = pGui->getOpacity(m_iPad, i); + if( opacity > 0 ) + { + m_controlLabelBackground[i].setOpacity(opacity); + m_labelChatText[i].setOpacity(opacity); + m_labelChatText[i].setLabel( pGui->getMessage(m_iPad,i) ); + + anyVisible = true; + } + else + { + m_controlLabelBackground[i].setOpacity(0); + m_labelChatText[i].setOpacity(0); + m_labelChatText[i].setLabel(L""); + } + } + if(pGui->getJukeboxOpacity(m_iPad) > 0) anyVisible = true; + m_labelJukebox.setOpacity( pGui->getJukeboxOpacity(m_iPad) ); + m_labelJukebox.setLabel( pGui->getJukeboxMessage(m_iPad) ); + } + else + { + for( unsigned int i = 0; i < CHAT_LINES_COUNT; ++i ) + { + m_controlLabelBackground[i].setOpacity(0); + m_labelChatText[i].setOpacity(0); + m_labelChatText[i].setLabel(L""); + } + m_labelJukebox.setOpacity( 0 ); + } + + setVisible(anyVisible); +} + +void UIComponent_Chat::render(S32 width, S32 height, C4JRender::eViewportType viewport) +{ + if(m_bSplitscreen) + { + S32 xPos = 0; + S32 yPos = 0; + switch( viewport ) + { + case C4JRender::VIEWPORT_TYPE_SPLIT_BOTTOM: + case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_LEFT: + yPos = (S32)(ui.getScreenHeight() / 2); + break; + case C4JRender::VIEWPORT_TYPE_SPLIT_RIGHT: + case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_RIGHT: + xPos = (S32)(ui.getScreenWidth() / 2); + break; + case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_RIGHT: + xPos = (S32)(ui.getScreenWidth() / 2); + yPos = (S32)(ui.getScreenHeight() / 2); + break; + } + ui.setupRenderPosition(xPos, yPos); + + S32 tileXStart = 0; + S32 tileYStart = 0; + S32 tileWidth = width; + S32 tileHeight = height; + + switch( viewport ) + { + case C4JRender::VIEWPORT_TYPE_SPLIT_LEFT: + case C4JRender::VIEWPORT_TYPE_SPLIT_RIGHT: + tileHeight = (S32)(ui.getScreenHeight()); + break; + case C4JRender::VIEWPORT_TYPE_SPLIT_TOP: + tileWidth = (S32)(ui.getScreenWidth()); + tileYStart = (S32)(m_movieHeight / 2); + break; + case C4JRender::VIEWPORT_TYPE_SPLIT_BOTTOM: + tileWidth = (S32)(ui.getScreenWidth()); + tileYStart = (S32)(m_movieHeight / 2); + break; + case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_LEFT: + case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_RIGHT: + case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_LEFT: + case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_RIGHT: + tileYStart = (S32)(m_movieHeight / 2); + break; + } + + IggyPlayerSetDisplaySize( getMovie(), m_movieWidth, m_movieHeight ); + + IggyPlayerDrawTilesStart ( getMovie() ); + + m_renderWidth = tileWidth; + m_renderHeight = tileHeight; + IggyPlayerDrawTile ( getMovie() , + tileXStart , + tileYStart , + tileXStart + tileWidth , + tileYStart + tileHeight , + 0 ); + IggyPlayerDrawTilesEnd ( getMovie() ); + } + else + { + UIScene::render(width, height, viewport); + } +}
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIComponent_Chat.h b/Minecraft.Client/Common/UI/UIComponent_Chat.h new file mode 100644 index 00000000..d18352cc --- /dev/null +++ b/Minecraft.Client/Common/UI/UIComponent_Chat.h @@ -0,0 +1,66 @@ +#pragma once + +#include "UIScene.h" + +#define CHAT_LINES_COUNT 10 + +class UIComponent_Chat : public UIScene +{ +private: + bool m_bSplitscreen; + +protected: + UIControl_Label m_labelChatText[CHAT_LINES_COUNT]; + UIControl_Label m_labelJukebox; + UIControl m_controlLabelBackground[CHAT_LINES_COUNT]; + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) + UI_MAP_ELEMENT(m_labelChatText[0],"Label1") + UI_MAP_ELEMENT(m_labelChatText[1],"Label2") + UI_MAP_ELEMENT(m_labelChatText[2],"Label3") + UI_MAP_ELEMENT(m_labelChatText[3],"Label4") + UI_MAP_ELEMENT(m_labelChatText[4],"Label5") + UI_MAP_ELEMENT(m_labelChatText[5],"Label6") + UI_MAP_ELEMENT(m_labelChatText[6],"Label7") + UI_MAP_ELEMENT(m_labelChatText[7],"Label8") + UI_MAP_ELEMENT(m_labelChatText[8],"Label9") + UI_MAP_ELEMENT(m_labelChatText[9],"Label10") + + UI_MAP_ELEMENT(m_controlLabelBackground[0],"Label1Background") + UI_MAP_ELEMENT(m_controlLabelBackground[1],"Label2Background") + UI_MAP_ELEMENT(m_controlLabelBackground[2],"Label3Background") + UI_MAP_ELEMENT(m_controlLabelBackground[3],"Label4Background") + UI_MAP_ELEMENT(m_controlLabelBackground[4],"Label5Background") + UI_MAP_ELEMENT(m_controlLabelBackground[5],"Label6Background") + UI_MAP_ELEMENT(m_controlLabelBackground[6],"Label7Background") + UI_MAP_ELEMENT(m_controlLabelBackground[7],"Label8Background") + UI_MAP_ELEMENT(m_controlLabelBackground[8],"Label9Background") + UI_MAP_ELEMENT(m_controlLabelBackground[9],"Label10Background") + + UI_MAP_ELEMENT(m_labelJukebox,"Jukebox") + UI_END_MAP_ELEMENTS_AND_NAMES() + +public: + UIComponent_Chat(int iPad, void *initData, UILayer *parentLayer); + +protected: + // TODO: This should be pure virtual in this class + virtual wstring getMoviePath(); + +public: + virtual EUIScene getSceneType() { return eUIComponent_Chat;} + + // Returns true if this scene handles input + virtual bool stealsFocus() { return false; } + + // Returns true if this scene has focus for the pad passed in + virtual bool hasFocus(int iPad) { return false; } + + // Returns true if lower scenes in this scenes layer, or in any layer below this scenes layers should be hidden + virtual bool hidesLowerScenes() { return false; } + + // RENDERING + virtual void render(S32 width, S32 height, C4JRender::eViewportType viewport); + +protected: + void handleTimerComplete(int id); +};
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIComponent_DebugUIConsole.cpp b/Minecraft.Client/Common/UI/UIComponent_DebugUIConsole.cpp new file mode 100644 index 00000000..7436d796 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIComponent_DebugUIConsole.cpp @@ -0,0 +1,39 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIComponent_DebugUIConsole.h" + +UIComponent_DebugUIConsole::UIComponent_DebugUIConsole(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) +{ + // Setup all the Iggy references we need for this scene + initialiseMovie(); + + m_bTextChanged = false; +} + +wstring UIComponent_DebugUIConsole::getMoviePath() +{ + return L"DebugUIConsoleComponent"; +} + +void UIComponent_DebugUIConsole::tick() +{ + UIScene::tick(); + if(m_bTextChanged) + { + m_bTextChanged = false; + for(unsigned int i = 0; i < 10 && i < m_textList.size(); ++i) + { + m_labels[i].setLabel(m_textList[i]); + } + } +} + +void UIComponent_DebugUIConsole::addText(const string &text) +{ + if(!text.empty() && text.compare("\n") != 0) + { + if(m_textList.size() >= 10) m_textList.pop_front(); + m_textList.push_back(text); + m_bTextChanged = true; + } +}
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIComponent_DebugUIConsole.h b/Minecraft.Client/Common/UI/UIComponent_DebugUIConsole.h new file mode 100644 index 00000000..177754f5 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIComponent_DebugUIConsole.h @@ -0,0 +1,49 @@ +#pragma once + +#include "UIScene.h" +#include "UIControl_Label.h" + +class UIComponent_DebugUIConsole : public UIScene +{ +private: + UIControl_Label m_labels[10]; + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) + UI_MAP_ELEMENT( m_labels[0], "consoleLine1") + UI_MAP_ELEMENT( m_labels[1], "consoleLine2") + UI_MAP_ELEMENT( m_labels[2], "consoleLine3") + UI_MAP_ELEMENT( m_labels[3], "consoleLine4") + UI_MAP_ELEMENT( m_labels[4], "consoleLine5") + UI_MAP_ELEMENT( m_labels[5], "consoleLine6") + UI_MAP_ELEMENT( m_labels[6], "consoleLine7") + UI_MAP_ELEMENT( m_labels[7], "consoleLine8") + UI_MAP_ELEMENT( m_labels[8], "consoleLine9") + UI_MAP_ELEMENT( m_labels[9], "consoleLine10") + UI_END_MAP_ELEMENTS_AND_NAMES() + + deque<string> m_textList; + + bool m_bTextChanged; + +public: + UIComponent_DebugUIConsole(int iPad, void *initData, UILayer *parentLayer); + + virtual void tick(); + +protected: + // TODO: This should be pure virtual in this class + virtual wstring getMoviePath(); + +public: + virtual EUIScene getSceneType() { return eUIComponent_DebugUIConsole;} + + // Returns true if this scene handles input + virtual bool stealsFocus() { return false; } + + // Returns true if this scene has focus for the pad passed in + virtual bool hasFocus(int iPad) { return false; } + + // Returns true if lower scenes in this scenes layer, or in any layer below this scenes layers should be hidden + virtual bool hidesLowerScenes() { return false; } + + void addText(const string &text); +};
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIComponent_DebugUIMarketingGuide.cpp b/Minecraft.Client/Common/UI/UIComponent_DebugUIMarketingGuide.cpp new file mode 100644 index 00000000..240429bc --- /dev/null +++ b/Minecraft.Client/Common/UI/UIComponent_DebugUIMarketingGuide.cpp @@ -0,0 +1,33 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIComponent_DebugUIMarketingGuide.h" + +UIComponent_DebugUIMarketingGuide::UIComponent_DebugUIMarketingGuide(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) +{ + // Setup all the Iggy references we need for this scene + initialiseMovie(); + + IggyDataValue result; + IggyDataValue value[1]; + value[0].type = IGGY_DATATYPE_number; + value[0].number = (F64)0; // WIN64 +#if defined _XBOX + value[0].number = (F64)1; +#elif defined _DURANGO + value[0].number = (F64)2; +#elif defined __PS3__ + value[0].number = (F64)3; +#elif defined __ORBIS__ + value[0].number = (F64)4; +#elif defined __PSVITA__ + value[0].number = (F64)5; +#elif defined _WINDOWS64 + value[0].number = (F64)0; +#endif + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcSetPlatform , 1 , value ); +} + +wstring UIComponent_DebugUIMarketingGuide::getMoviePath() +{ + return L"DebugUIMarketingGuide"; +}
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIComponent_DebugUIMarketingGuide.h b/Minecraft.Client/Common/UI/UIComponent_DebugUIMarketingGuide.h new file mode 100644 index 00000000..2c651173 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIComponent_DebugUIMarketingGuide.h @@ -0,0 +1,34 @@ +#pragma once + +#include "UIScene.h" +#include "UIControl_Label.h" + +class UIComponent_DebugUIMarketingGuide : public UIScene +{ +private: + IggyName m_funcSetPlatform; + + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) + UI_MAP_NAME( m_funcSetPlatform, L"SetPlatform") + UI_END_MAP_ELEMENTS_AND_NAMES() + + +public: + UIComponent_DebugUIMarketingGuide(int iPad, void *initData, UILayer *parentLayer); + +protected: + // TODO: This should be pure virtual in this class + virtual wstring getMoviePath(); + +public: + virtual EUIScene getSceneType() { return eUIComponent_DebugUIMarketingGuide;} + + // Returns true if this scene handles input + virtual bool stealsFocus() { return false; } + + // Returns true if this scene has focus for the pad passed in + virtual bool hasFocus(int iPad) { return false; } + + // Returns true if lower scenes in this scenes layer, or in any layer below this scenes layers should be hidden + virtual bool hidesLowerScenes() { return false; } +};
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIComponent_Logo.cpp b/Minecraft.Client/Common/UI/UIComponent_Logo.cpp new file mode 100644 index 00000000..2f5c82bd --- /dev/null +++ b/Minecraft.Client/Common/UI/UIComponent_Logo.cpp @@ -0,0 +1,30 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIComponent_Logo.h" + +UIComponent_Logo::UIComponent_Logo(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) +{ + // Setup all the Iggy references we need for this scene + initialiseMovie(); +} + +wstring UIComponent_Logo::getMoviePath() +{ + switch( m_parentLayer->getViewport() ) + { + case C4JRender::VIEWPORT_TYPE_SPLIT_TOP: + case C4JRender::VIEWPORT_TYPE_SPLIT_BOTTOM: + case C4JRender::VIEWPORT_TYPE_SPLIT_LEFT: + case C4JRender::VIEWPORT_TYPE_SPLIT_RIGHT: + case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_LEFT: + case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_RIGHT: + case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_LEFT: + case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_RIGHT: + return L"ComponentLogoSplit"; + break; + case C4JRender::VIEWPORT_TYPE_FULLSCREEN: + default: + return L"ComponentLogo"; + break; + } +}
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIComponent_Logo.h b/Minecraft.Client/Common/UI/UIComponent_Logo.h new file mode 100644 index 00000000..1a8cf819 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIComponent_Logo.h @@ -0,0 +1,25 @@ +#pragma once + +#include "UIScene.h" + +class UIComponent_Logo : public UIScene +{ +public: + UIComponent_Logo(int iPad, void *initData, UILayer *parentLayer); + +protected: + // TODO: This should be pure virtual in this class + virtual wstring getMoviePath(); + +public: + virtual EUIScene getSceneType() { return eUIComponent_Logo;} + + // Returns true if this scene handles input + virtual bool stealsFocus() { return false; } + + // Returns true if this scene has focus for the pad passed in + virtual bool hasFocus(int iPad) { return false; } + + // Returns true if lower scenes in this scenes layer, or in any layer below this scenes layers should be hidden + virtual bool hidesLowerScenes() { return false; } +};
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIComponent_MenuBackground.cpp b/Minecraft.Client/Common/UI/UIComponent_MenuBackground.cpp new file mode 100644 index 00000000..d3a4c4c0 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIComponent_MenuBackground.cpp @@ -0,0 +1,103 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIComponent_MenuBackground.h" + +UIComponent_MenuBackground::UIComponent_MenuBackground(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) +{ + m_bSplitscreen = false; + // Setup all the Iggy references we need for this scene + initialiseMovie(); +} + +wstring UIComponent_MenuBackground::getMoviePath() +{ switch( m_parentLayer->getViewport() ) + { + case C4JRender::VIEWPORT_TYPE_SPLIT_TOP: + case C4JRender::VIEWPORT_TYPE_SPLIT_BOTTOM: + case C4JRender::VIEWPORT_TYPE_SPLIT_LEFT: + case C4JRender::VIEWPORT_TYPE_SPLIT_RIGHT: + case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_LEFT: + case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_RIGHT: + case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_LEFT: + case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_RIGHT: + m_bSplitscreen = true; + break; + case C4JRender::VIEWPORT_TYPE_FULLSCREEN: + default: + m_bSplitscreen = false; + break; + } + + // We use the fullscreen one even in splitscreen, just draw different parts of it + return L"MenuBackground"; +} + +void UIComponent_MenuBackground::render(S32 width, S32 height, C4JRender::eViewportType viewport) +{ + if(m_bSplitscreen) + { + S32 xPos = 0; + S32 yPos = 0; + switch( viewport ) + { + case C4JRender::VIEWPORT_TYPE_SPLIT_BOTTOM: + case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_LEFT: + yPos = (S32)(ui.getScreenHeight() / 2); + break; + case C4JRender::VIEWPORT_TYPE_SPLIT_RIGHT: + case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_RIGHT: + xPos = (S32)(ui.getScreenWidth() / 2); + break; + case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_RIGHT: + xPos = (S32)(ui.getScreenWidth() / 2); + yPos = (S32)(ui.getScreenHeight() / 2); + break; + } + ui.setupRenderPosition(xPos, yPos); + + S32 tileXStart = 0; + S32 tileYStart = 0; + S32 tileWidth = width; + S32 tileHeight = height; + + switch( viewport ) + { + case C4JRender::VIEWPORT_TYPE_SPLIT_LEFT: + case C4JRender::VIEWPORT_TYPE_SPLIT_RIGHT: + tileHeight = (S32)(ui.getScreenHeight()); + break; + case C4JRender::VIEWPORT_TYPE_SPLIT_TOP: + tileWidth = (S32)(ui.getScreenWidth()); + tileYStart = (S32)(m_movieHeight / 2); + break; + case C4JRender::VIEWPORT_TYPE_SPLIT_BOTTOM: + tileWidth = (S32)(ui.getScreenWidth()); + tileYStart = (S32)(m_movieHeight / 2); + break; + case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_LEFT: + case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_RIGHT: + case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_LEFT: + case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_RIGHT: + tileYStart = (S32)(m_movieHeight / 2); + break; + } + + IggyPlayerSetDisplaySize( getMovie(), m_movieWidth, m_movieHeight ); + + IggyPlayerDrawTilesStart ( getMovie() ); + + m_renderWidth = tileWidth; + m_renderHeight = tileHeight; + IggyPlayerDrawTile ( getMovie() , + tileXStart , + tileYStart , + tileXStart + tileWidth , + tileYStart + tileHeight , + 0 ); + IggyPlayerDrawTilesEnd ( getMovie() ); + } + else + { + UIScene::render(width, height, viewport); + } +}
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIComponent_MenuBackground.h b/Minecraft.Client/Common/UI/UIComponent_MenuBackground.h new file mode 100644 index 00000000..ac0b9d2f --- /dev/null +++ b/Minecraft.Client/Common/UI/UIComponent_MenuBackground.h @@ -0,0 +1,30 @@ +#pragma once + +#include "UIScene.h" + +class UIComponent_MenuBackground : public UIScene +{ +private: + bool m_bSplitscreen; +public: + UIComponent_MenuBackground(int iPad, void *initData, UILayer *parentLayer); + +protected: + // TODO: This should be pure virtual in this class + virtual wstring getMoviePath(); + +public: + virtual EUIScene getSceneType() { return eUIComponent_MenuBackground;} + + // Returns true if this scene handles input + virtual bool stealsFocus() { return false; } + + // Returns true if this scene has focus for the pad passed in + virtual bool hasFocus(int iPad) { return false; } + + // Returns true if lower scenes in this scenes layer, or in any layer below this scenes layers should be hidden + virtual bool hidesLowerScenes() { return false; } + + // RENDERING + virtual void render(S32 width, S32 height, C4JRender::eViewportType viewport); +};
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIComponent_Panorama.cpp b/Minecraft.Client/Common/UI/UIComponent_Panorama.cpp new file mode 100644 index 00000000..a418fcda --- /dev/null +++ b/Minecraft.Client/Common/UI/UIComponent_Panorama.cpp @@ -0,0 +1,144 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIComponent_Panorama.h" +#include "Minecraft.h" +#include "MultiPlayerLevel.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.level.dimension.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.level.storage.h" + +UIComponent_Panorama::UIComponent_Panorama(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) +{ + // Setup all the Iggy references we need for this scene + initialiseMovie(); + + m_bShowingDay = true; + + while(!m_hasTickedOnce) tick(); +} + +wstring UIComponent_Panorama::getMoviePath() +{ + switch( m_parentLayer->getViewport() ) + { + case C4JRender::VIEWPORT_TYPE_SPLIT_TOP: + case C4JRender::VIEWPORT_TYPE_SPLIT_BOTTOM: + case C4JRender::VIEWPORT_TYPE_SPLIT_LEFT: + case C4JRender::VIEWPORT_TYPE_SPLIT_RIGHT: + case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_LEFT: + case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_RIGHT: + case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_LEFT: + case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_RIGHT: + m_bSplitscreen = true; + return L"PanoramaSplit"; + break; + case C4JRender::VIEWPORT_TYPE_FULLSCREEN: + default: + m_bSplitscreen = false; + return L"Panorama"; + break; + } +} + +void UIComponent_Panorama::tick() +{ + if(!hasMovie()) return; + + Minecraft *pMinecraft = Minecraft::GetInstance(); + EnterCriticalSection(&pMinecraft->m_setLevelCS); + if(pMinecraft->level!=NULL) + { + __int64 i64TimeOfDay =0; + // are we in the Nether? - Leave the time as 0 if we are, so we show daylight + if(pMinecraft->level->dimension->id==0) + { + i64TimeOfDay = pMinecraft->level->getLevelData()->getTime() % 24000; + } + + if(i64TimeOfDay>14000) + { + setPanorama(false); + } + else + { + setPanorama(true); + } + } + else + { + setPanorama(true); + } + LeaveCriticalSection(&pMinecraft->m_setLevelCS); + + UIScene::tick(); +} + +void UIComponent_Panorama::render(S32 width, S32 height, C4JRender::eViewportType viewport) +{ + bool specialViewport = (viewport == C4JRender::VIEWPORT_TYPE_SPLIT_TOP) || + (viewport == C4JRender::VIEWPORT_TYPE_SPLIT_BOTTOM) || + (viewport == C4JRender::VIEWPORT_TYPE_SPLIT_LEFT) || + (viewport == C4JRender::VIEWPORT_TYPE_SPLIT_RIGHT); + if(m_bSplitscreen && specialViewport) + { + S32 xPos = 0; + S32 yPos = 0; + switch( viewport ) + { + case C4JRender::VIEWPORT_TYPE_SPLIT_BOTTOM: + yPos = (S32)(ui.getScreenHeight() / 2); + break; + case C4JRender::VIEWPORT_TYPE_SPLIT_RIGHT: + xPos = (S32)(ui.getScreenWidth() / 2); + break; + } + ui.setupRenderPosition(xPos, yPos); + + if((viewport == C4JRender::VIEWPORT_TYPE_SPLIT_LEFT) || (viewport == C4JRender::VIEWPORT_TYPE_SPLIT_RIGHT)) + { + // Need to render at full height, but only the left side of the scene + S32 tileXStart = 0; + S32 tileYStart = 0; + S32 tileWidth = width; + S32 tileHeight = (S32)(ui.getScreenHeight()); + + IggyPlayerSetDisplaySize( getMovie(), m_movieWidth, m_movieHeight ); + + IggyPlayerDrawTilesStart ( getMovie() ); + + m_renderWidth = tileWidth; + m_renderHeight = tileHeight; + IggyPlayerDrawTile ( getMovie() , + tileXStart , + tileYStart , + tileXStart + tileWidth , + tileYStart + tileHeight , + 0 ); + IggyPlayerDrawTilesEnd ( getMovie() ); + } + else + { + // Need to render at full height, and full width. But compressed into the viewport + IggyPlayerSetDisplaySize( getMovie(), ui.getScreenWidth(), ui.getScreenHeight()/2 ); + IggyPlayerDraw( getMovie() ); + } + } + else + { + UIScene::render(width, height, viewport); + } +} + +void UIComponent_Panorama::setPanorama(bool isDay) +{ + if(isDay != m_bShowingDay) + { + m_bShowingDay = isDay; + + IggyDataValue result; + IggyDataValue value[1]; + value[0].type = IGGY_DATATYPE_boolean; + value[0].boolval = isDay; + + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcShowPanoramaDay , 1 , value ); + } +} diff --git a/Minecraft.Client/Common/UI/UIComponent_Panorama.h b/Minecraft.Client/Common/UI/UIComponent_Panorama.h new file mode 100644 index 00000000..99dc115c --- /dev/null +++ b/Minecraft.Client/Common/UI/UIComponent_Panorama.h @@ -0,0 +1,40 @@ +#pragma once + +#include "UIScene.h" + +class UIComponent_Panorama : public UIScene +{ +private: + bool m_bSplitscreen; + bool m_bShowingDay; + +protected: + IggyName m_funcShowPanoramaDay; + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) + UI_MAP_NAME(m_funcShowPanoramaDay, L"ShowPanoramaDay"); + UI_END_MAP_ELEMENTS_AND_NAMES() + +public: + UIComponent_Panorama(int iPad, void *initData, UILayer *parentLayer); + +protected: + // TODO: This should be pure virtual in this class + virtual wstring getMoviePath(); + +public: + virtual EUIScene getSceneType() { return eUIComponent_Panorama;} + + // Returns true if this scene handles input + virtual bool stealsFocus() { return false; } + + // Returns true if this scene has focus for the pad passed in + virtual bool hasFocus(int iPad) { return false; } + + virtual void tick(); + + // RENDERING + virtual void render(S32 width, S32 height, C4JRender::eViewportType viewport); + +private: + void setPanorama(bool isDay); +}; diff --git a/Minecraft.Client/Common/UI/UIComponent_PressStartToPlay.cpp b/Minecraft.Client/Common/UI/UIComponent_PressStartToPlay.cpp new file mode 100644 index 00000000..2feb94c1 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIComponent_PressStartToPlay.cpp @@ -0,0 +1,167 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIComponent_PressStartToPlay.h" +#include "..\..\..\Minecraft.World\StringHelpers.h" + +UIComponent_PressStartToPlay::UIComponent_PressStartToPlay(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) +{ + // Setup all the Iggy references we need for this scene + initialiseMovie(); + + m_showingSaveIcon = false; + m_showingAutosaveTimer = false; + m_showingTrialTimer = false; + for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i) + { + m_showingPressStart[i] = false; + } + m_trialTimer = L""; + m_autosaveTimer = L""; + + m_labelTrialTimer.init(L""); + m_labelTrialTimer.setVisible(false); + +#ifdef __ORBIS__ + wstring text = app.GetString(IDS_PRESS_X_TO_JOIN); + text = replaceAll(text, L"{*CONTROLLER_VK_A*}", app.GetVKReplacement(VK_PAD_A) ); + + m_labelPressStart.init(text.c_str()); +#elif defined _XBOX_ONE + wstring text = app.GetString(IDS_PRESS_START_TO_JOIN); + text = replaceAll(text, L"{*CONTROLLER_VK_START*}", app.GetVKReplacement(VK_PAD_START) ); + m_labelPressStart.init(text.c_str()); +#else + m_labelPressStart.init(app.GetString(IDS_PRESS_START_TO_JOIN)); +#endif + m_controlSaveIcon.setVisible(false); + m_controlPressStartPanel.setVisible(false); + m_playerDisplayName.setVisible(false); +} + +wstring UIComponent_PressStartToPlay::getMoviePath() +{ + return L"PressStartToPlay"; +} + +void UIComponent_PressStartToPlay::handleReload() +{ + // 4J Stu - It's possible these could change during the reload, so can't use the normal controls refresh of it's state + m_controlSaveIcon.setVisible(m_showingSaveIcon); + m_labelTrialTimer.setVisible(m_showingAutosaveTimer); + m_labelTrialTimer.setLabel(m_autosaveTimer); + m_labelTrialTimer.setVisible(m_showingTrialTimer); + m_labelTrialTimer.setLabel(m_trialTimer); + + bool showPressStart = false; + for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i) + { + bool show = m_showingPressStart[i]; + showPressStart |= show; + + if(show) + { + addTimer(0,3000); + + IggyDataValue result; + IggyDataValue value[1]; + value[0].type = IGGY_DATATYPE_number; + value[0].number = i; + + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcShowController , 1 , value ); + } + } + m_controlPressStartPanel.setVisible(showPressStart); +} + +void UIComponent_PressStartToPlay::handleTimerComplete(int id) +{ + m_controlPressStartPanel.setVisible(false); + for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i) + { + m_showingPressStart[i] = false; + } + ui.ClearPressStart(); +} + +void UIComponent_PressStartToPlay::showPressStart(int iPad, bool show) +{ + m_showingPressStart[iPad] = show; + if(!ui.IsExpectingOrReloadingSkin() && hasMovie()) + { + m_controlPressStartPanel.setVisible(show); + + if(show) + { + addTimer(0,3000); + + IggyDataValue result; + IggyDataValue value[1]; + value[0].type = IGGY_DATATYPE_number; + value[0].number = iPad; + + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcShowController , 1 , value ); + } + } +} + +void UIComponent_PressStartToPlay::setTrialTimer(const wstring &label) +{ + m_trialTimer = label; + if(!ui.IsExpectingOrReloadingSkin() && hasMovie()) + { + m_labelTrialTimer.setLabel(label); + } +} + +void UIComponent_PressStartToPlay::showTrialTimer(bool show) +{ + m_showingTrialTimer = show; + if(!ui.IsExpectingOrReloadingSkin() && hasMovie()) + { + m_labelTrialTimer.setVisible(show); + } +} + +void UIComponent_PressStartToPlay::setAutosaveTimer(const wstring &label) +{ + m_autosaveTimer = label; + if(!ui.IsExpectingOrReloadingSkin() && hasMovie()) + { + m_labelTrialTimer.setLabel(label); + } +} + +void UIComponent_PressStartToPlay::showAutosaveTimer(bool show) +{ + m_showingAutosaveTimer = show; + if(!ui.IsExpectingOrReloadingSkin() && hasMovie()) + { + m_labelTrialTimer.setVisible(show); + } +} + +void UIComponent_PressStartToPlay::showSaveIcon(bool show) +{ + m_showingSaveIcon = show; + if(!ui.IsExpectingOrReloadingSkin() && hasMovie()) + { + m_controlSaveIcon.setVisible(show); + } + else + { + if(show) app.DebugPrintf("Tried to show save icon while texture pack reload was in progress\n"); + } +} + +void UIComponent_PressStartToPlay::showPlayerDisplayName(bool show) +{ +#ifdef _XBOX_ONE + if(show) + { + m_playerDisplayName.setLabel(ProfileManager.GetDisplayName(ProfileManager.GetPrimaryPad())); + } + m_playerDisplayName.setVisible(show); +#else + m_playerDisplayName.setVisible(false); +#endif +}
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIComponent_PressStartToPlay.h b/Minecraft.Client/Common/UI/UIComponent_PressStartToPlay.h new file mode 100644 index 00000000..a29b6016 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIComponent_PressStartToPlay.h @@ -0,0 +1,60 @@ +#pragma once + +#include "UIScene.h" + +class UIComponent_PressStartToPlay : public UIScene +{ +private: + bool m_showingSaveIcon; + bool m_showingAutosaveTimer; + bool m_showingTrialTimer; + bool m_showingPressStart[XUSER_MAX_COUNT]; + wstring m_trialTimer; + wstring m_autosaveTimer; + +protected: + UIControl_Label m_labelTrialTimer, m_labelPressStart, m_playerDisplayName; + UIControl m_controlSaveIcon, m_controlPressStartPanel; + IggyName m_funcShowController; + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) + UI_MAP_ELEMENT(m_labelTrialTimer, "TrialTimer") + UI_MAP_ELEMENT(m_controlSaveIcon, "SaveIcon") + UI_MAP_ELEMENT(m_playerDisplayName, "PlayerName") + UI_MAP_ELEMENT(m_controlPressStartPanel, "MainPanel") + UI_BEGIN_MAP_CHILD_ELEMENTS(m_controlPressStartPanel) + UI_MAP_ELEMENT(m_labelPressStart, "PressStartLabel" ) + UI_END_MAP_CHILD_ELEMENTS() + + UI_MAP_NAME(m_funcShowController, L"ShowController"); + UI_END_MAP_ELEMENTS_AND_NAMES() + +public: + UIComponent_PressStartToPlay(int iPad, void *initData, UILayer *parentLayer); + +protected: + // TODO: This should be pure virtual in this class + virtual wstring getMoviePath(); + +public: + virtual EUIScene getSceneType() { return eUIComponent_PressStartToPlay;} + + // Returns true if this scene handles input + virtual bool stealsFocus() { return false; } + + // Returns true if this scene has focus for the pad passed in + virtual bool hasFocus(int iPad) { return false; } + + // Returns true if lower scenes in this scenes layer, or in any layer below this scenes layers should be hidden + virtual bool hidesLowerScenes() { return false; } + + virtual void handleReload(); + virtual void handleTimerComplete(int id); + + void showPressStart(int iPad, bool show); + void setTrialTimer(const wstring &label); + void showTrialTimer(bool show); + void setAutosaveTimer(const wstring &label); + void showAutosaveTimer(bool show); + void showSaveIcon(bool show); + void showPlayerDisplayName(bool show); +};
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIComponent_Tooltips.cpp b/Minecraft.Client/Common/UI/UIComponent_Tooltips.cpp new file mode 100644 index 00000000..63eba1a5 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIComponent_Tooltips.cpp @@ -0,0 +1,501 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIComponent_Tooltips.h" + +UIComponent_Tooltips::UIComponent_Tooltips(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) +{ + for(int i=0;i<XUSER_MAX_COUNT;i++) + { + for(int j=0;j<ACTION_MAX_MENU;j++) + { + m_overrideSFX[i][j]=false; + } + } + // Setup all the Iggy references we need for this scene + initialiseMovie(); + +#ifdef __PSVITA__ + // initialise vita touch controls with ids + for(unsigned int i = 0; i < ETouchInput_Count; ++i) + { + m_TouchController[i].init(i); + } +#endif + +#if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__) + if(InputManager.IsCircleCrossSwapped()) + { + IggyDataValue result; + IggyDataValue value[1]; + value[0].type = IGGY_DATATYPE_boolean; + value[0].boolval = true; + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcSetABSwap , 1 , value ); + } +#endif +} + +wstring UIComponent_Tooltips::getMoviePath() +{ + switch( m_parentLayer->getViewport() ) + { + case C4JRender::VIEWPORT_TYPE_SPLIT_TOP: + case C4JRender::VIEWPORT_TYPE_SPLIT_BOTTOM: + case C4JRender::VIEWPORT_TYPE_SPLIT_LEFT: + case C4JRender::VIEWPORT_TYPE_SPLIT_RIGHT: + case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_LEFT: + case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_RIGHT: + case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_LEFT: + case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_RIGHT: + m_bSplitscreen = true; + return L"ToolTipsSplit"; + break; + case C4JRender::VIEWPORT_TYPE_FULLSCREEN: + default: + m_bSplitscreen = false; + return L"ToolTips"; + break; + } +} + +F64 UIComponent_Tooltips::getSafeZoneHalfWidth() +{ + float width = ui.getScreenWidth(); + + float safeWidth = 0.0f; + +#ifndef __PSVITA__ + // 85% safezone for tooltips in either SD mode + if( !RenderManager.IsHiDef() ) + { + // 85% safezone + safeWidth = m_movieWidth * (0.15f / 2); + } + else + { + // 90% safezone + safeWidth = width * (0.1f / 2); + } +#endif + return safeWidth; +} + +void UIComponent_Tooltips::updateSafeZone() +{ + // Distance from edge + F64 safeTop = 0.0; + F64 safeBottom = 0.0; + F64 safeLeft = 0.0; + F64 safeRight = 0.0; + + switch( m_parentLayer->getViewport() ) + { + case C4JRender::VIEWPORT_TYPE_SPLIT_TOP: + safeTop = getSafeZoneHalfHeight(); + safeLeft = getSafeZoneHalfWidth(); + break; + case C4JRender::VIEWPORT_TYPE_SPLIT_BOTTOM: + safeBottom = getSafeZoneHalfHeight(); + safeLeft = getSafeZoneHalfWidth(); + break; + case C4JRender::VIEWPORT_TYPE_SPLIT_LEFT: + safeLeft = getSafeZoneHalfWidth(); + safeBottom = getSafeZoneHalfHeight(); + break; + case C4JRender::VIEWPORT_TYPE_SPLIT_RIGHT: + safeRight = getSafeZoneHalfWidth(); + safeBottom = getSafeZoneHalfHeight(); + break; + case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_LEFT: + safeTop = getSafeZoneHalfHeight(); + safeLeft = getSafeZoneHalfWidth(); + break; + case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_RIGHT: + safeTop = getSafeZoneHalfHeight(); + safeRight = getSafeZoneHalfWidth(); + break; + case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_LEFT: + safeBottom = getSafeZoneHalfHeight(); + safeLeft = getSafeZoneHalfWidth(); + break; + case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_RIGHT: + safeBottom = getSafeZoneHalfHeight(); + safeRight = getSafeZoneHalfWidth(); + break; + case C4JRender::VIEWPORT_TYPE_FULLSCREEN: + default: + safeTop = getSafeZoneHalfHeight(); + safeBottom = getSafeZoneHalfHeight(); + safeLeft = getSafeZoneHalfWidth(); + safeRight = getSafeZoneHalfWidth(); + break; + } + setSafeZone(safeTop, safeBottom, safeLeft, safeRight); +} + +void UIComponent_Tooltips::tick() +{ + UIScene::tick(); + + // set the opacity of the tooltip items + unsigned char ucAlpha=app.GetGameSettings(ProfileManager.GetPrimaryPad(),eGameSetting_InterfaceOpacity); + float fVal; + + if(ucAlpha<80) + { + // if we are in a menu, set the minimum opacity for tooltips to 15% + if(ui.GetMenuDisplayed(m_iPad) && (ucAlpha<15)) + { + ucAlpha=15; + } + + // check if we have the timer running for the opacity + unsigned int uiOpacityTimer=app.GetOpacityTimer(m_iPad); + if(uiOpacityTimer!=0) + { + if(uiOpacityTimer<10) + { + float fStep=(80.0f-(float)ucAlpha)/10.0f; + fVal=0.01f*(80.0f-((10.0f-(float)uiOpacityTimer)*fStep)); + } + else + { + fVal=0.01f*80.0f; + } + } + else + { + fVal=0.01f*(float)ucAlpha; + } + } + else + { + // if we are in a menu, set the minimum opacity for tooltips to 15% + if(ui.GetMenuDisplayed(m_iPad) && (ucAlpha<15)) + { + ucAlpha=15; + } + fVal=0.01f*(float)ucAlpha; + } + setOpacity(fVal); +} + +void UIComponent_Tooltips::render(S32 width, S32 height, C4JRender::eViewportType viewport) +{ + if((ProfileManager.GetLockedProfile()!=-1) && !ui.GetMenuDisplayed(m_iPad) && (app.GetGameSettings(m_iPad,eGameSetting_Tooltips)==0 || app.GetGameSettings(m_iPad,eGameSetting_DisplayHUD)==0)) + { + return; + } + + if(m_bSplitscreen) + { + S32 xPos = 0; + S32 yPos = 0; + switch( viewport ) + { + case C4JRender::VIEWPORT_TYPE_SPLIT_BOTTOM: + case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_LEFT: + yPos = (S32)(ui.getScreenHeight() / 2); + break; + case C4JRender::VIEWPORT_TYPE_SPLIT_RIGHT: + case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_RIGHT: + xPos = (S32)(ui.getScreenWidth() / 2); + break; + case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_RIGHT: + xPos = (S32)(ui.getScreenWidth() / 2); + yPos = (S32)(ui.getScreenHeight() / 2); + break; + } + ui.setupRenderPosition(xPos, yPos); + + S32 tileXStart = 0; + S32 tileYStart = 0; + S32 tileWidth = width; + S32 tileHeight = height; + + switch( viewport ) + { + case C4JRender::VIEWPORT_TYPE_SPLIT_LEFT: + case C4JRender::VIEWPORT_TYPE_SPLIT_RIGHT: + tileHeight = (S32)(ui.getScreenHeight()); + break; + case C4JRender::VIEWPORT_TYPE_SPLIT_TOP: + tileWidth = (S32)(ui.getScreenWidth()); + tileYStart = (S32)(m_movieHeight / 2); + break; + case C4JRender::VIEWPORT_TYPE_SPLIT_BOTTOM: + tileWidth = (S32)(ui.getScreenWidth()); + tileYStart = (S32)(m_movieHeight / 2); + break; + case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_LEFT: + case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_RIGHT: + case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_LEFT: + case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_RIGHT: + tileYStart = (S32)(m_movieHeight / 2); + break; + } + + IggyPlayerSetDisplaySize( getMovie(), m_movieWidth, m_movieHeight ); + + IggyPlayerDrawTilesStart ( getMovie() ); + + m_renderWidth = tileWidth; + m_renderHeight = tileHeight; + IggyPlayerDrawTile ( getMovie() , + tileXStart , + tileYStart , + tileXStart + tileWidth , + tileYStart + tileHeight , + 0 ); + IggyPlayerDrawTilesEnd ( getMovie() ); + } + else + { + UIScene::render(width, height, viewport); + } +} + +void UIComponent_Tooltips::SetTooltipText( unsigned int tooltip, int iTextID ) +{ + if( _SetTooltip(tooltip, iTextID) ) _Relayout(); +} + +void UIComponent_Tooltips::SetEnableTooltips( bool bVal ) +{ +} + +void UIComponent_Tooltips::ShowTooltip( unsigned int tooltip, bool show ) +{ + if(show != m_tooltipValues[tooltip].show) + { + _SetTooltip(tooltip, L"", show); + _Relayout(); + } +} + +void UIComponent_Tooltips::SetTooltips( int iA, int iB, int iX, int iY , int iLT, int iRT, int iLB, int iRB, int iLS, bool forceUpdate) +{ + bool needsRelayout = false; + needsRelayout = _SetTooltip( eToolTipButtonA, iA ) || needsRelayout; + needsRelayout = _SetTooltip( eToolTipButtonB, iB ) || needsRelayout; + needsRelayout = _SetTooltip( eToolTipButtonX, iX ) || needsRelayout; + needsRelayout = _SetTooltip( eToolTipButtonY, iY ) || needsRelayout; + needsRelayout = _SetTooltip( eToolTipButtonLT, iLT ) || needsRelayout; + needsRelayout = _SetTooltip( eToolTipButtonRT, iRT ) || needsRelayout; + needsRelayout = _SetTooltip( eToolTipButtonLB, iLB ) || needsRelayout; + needsRelayout = _SetTooltip( eToolTipButtonRB, iRB ) || needsRelayout; + needsRelayout = _SetTooltip( eToolTipButtonLS, iLS ) || needsRelayout; + + if(needsRelayout)_Relayout(); +} + +void UIComponent_Tooltips::EnableTooltip( unsigned int tooltip, bool enable ) +{ +} + +bool UIComponent_Tooltips::_SetTooltip(unsigned int iToolTip, int iTextID) +{ + bool changed = false; + if(iTextID != m_tooltipValues[iToolTip].iString || (iTextID > -1 && !m_tooltipValues[iToolTip].show)) + { + m_tooltipValues[iToolTip].iString = iTextID; + changed = true; + if(iTextID > -1) _SetTooltip(iToolTip, app.GetString(iTextID), true); + else if(iTextID == -2) _SetTooltip(iToolTip, L"", true); + else _SetTooltip(iToolTip, L"", false); + } + return changed; +} + +void UIComponent_Tooltips::_SetTooltip(unsigned int iToolTipId, const wstring &label, bool show, bool force) +{ + if(!force && !show && !m_tooltipValues[iToolTipId].show) + { + return; + } + m_tooltipValues[iToolTipId].show = show; + + IggyDataValue result; + IggyDataValue value[3]; + value[0].type = IGGY_DATATYPE_number; + value[0].number = iToolTipId; + + value[1].type = IGGY_DATATYPE_string_UTF16; + IggyStringUTF16 stringVal; + + stringVal.string = (IggyUTF16*)label.c_str(); + stringVal.length = label.length(); + value[1].string16 = stringVal; + + value[2].type = IGGY_DATATYPE_boolean; + value[2].boolval = show; + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcSetTooltip , 3 , value ); + + app.DebugPrintf("Actual tooltip update!\n"); +} + +void UIComponent_Tooltips::_Relayout() +{ + IggyDataValue result; + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcUpdateLayout, 0 , NULL ); + +#ifdef __PSVITA__ + // rebuild touchboxes + ui.TouchBoxRebuild(this); +#endif +} + +#ifdef __PSVITA__ +void UIComponent_Tooltips::handleTouchInput(unsigned int iPad, S32 x, S32 y, int iId, bool bPressed, bool bRepeat, bool bReleased) +{ + //app.DebugPrintf("ToolTip Touch ID = %i\n", iId); + bool handled = false; + + // perform action on release + if(bReleased) + { + switch(iId) + { + case ETouchInput_Touch_A: + app.DebugPrintf("ToolTip Map Touch to _PSV_JOY_BUTTON_X\n", iId); + InputManager.MapTouchInput(iPad, _PSV_JOY_BUTTON_X); + break; + case ETouchInput_Touch_B: + app.DebugPrintf("ToolTip Map Touch to _PSV_JOY_BUTTON_O\n", iId); + InputManager.MapTouchInput(iPad, _PSV_JOY_BUTTON_O); + break; + case ETouchInput_Touch_X: + app.DebugPrintf("ToolTip Map Touch to _PSV_JOY_BUTTON_SQUARE\n", iId); + InputManager.MapTouchInput(iPad, _PSV_JOY_BUTTON_SQUARE); + break; + case ETouchInput_Touch_Y: + app.DebugPrintf("ToolTip Map Touch to _PSV_JOY_BUTTON_TRIANGLE\n", iId); + InputManager.MapTouchInput(iPad, _PSV_JOY_BUTTON_TRIANGLE); + break; + case ETouchInput_Touch_LT: + /* not in use on vita */ + app.DebugPrintf("ToolTip no action\n", iId); + break; + case ETouchInput_Touch_RightTrigger: + app.DebugPrintf("ToolTip Map Touch to _PSV_JOY_BUTTON_SELECT\n", iId); + InputManager.MapTouchInput(iPad, _PSV_JOY_BUTTON_SELECT); + break; + case ETouchInput_Touch_LeftBumper: + app.DebugPrintf("ToolTip Map Touch to _PSV_JOY_BUTTON_L1\n", iId); + InputManager.MapTouchInput(iPad, _PSV_JOY_BUTTON_L1); + break; + case ETouchInput_Touch_RightBumper: + app.DebugPrintf("ToolTip Map Touch to _PSV_JOY_BUTTON_R1\n", iId); + InputManager.MapTouchInput(iPad, _PSV_JOY_BUTTON_R1); + break; + case ETouchInput_Touch_LeftStick: + app.DebugPrintf("ToolTip no action\n", iId); + /* no action */ + break; + } + } +} +#endif + +void UIComponent_Tooltips::handleReload() +{ + app.DebugPrintf("UIComponent_Tooltips::handleReload\n"); + +#if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__) + if(InputManager.IsCircleCrossSwapped()) + { + IggyDataValue result; + IggyDataValue value[1]; + value[0].type = IGGY_DATATYPE_boolean; + value[0].boolval = true; + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcSetABSwap , 1 , value ); + } +#endif + + for(unsigned int i = 0; i < eToolTipNumButtons; ++i) + { + _SetTooltip(i,app.GetString(m_tooltipValues[i].iString), m_tooltipValues[i].show, true); + } + _Relayout(); +} + +void UIComponent_Tooltips::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled) +{ + if(m_overrideSFX[iPad][key]) + { + // don't play a sound for this action + switch(key) + { + case ACTION_MENU_A: + case ACTION_MENU_OK: + case ACTION_MENU_PAGEUP: + case ACTION_MENU_PAGEDOWN: + case ACTION_MENU_X: + case ACTION_MENU_Y: + case ACTION_MENU_B: + case ACTION_MENU_CANCEL: + case ACTION_MENU_LEFT_SCROLL: + case ACTION_MENU_RIGHT_SCROLL: + case ACTION_MENU_LEFT: + case ACTION_MENU_RIGHT: + case ACTION_MENU_UP: + case ACTION_MENU_DOWN: + sendInputToMovie(key, repeat, pressed, released); + break; + } + } + else + { + switch(key) + { + case ACTION_MENU_OK: + case ACTION_MENU_CANCEL: + // 4J-PB - We get both A and OK, and B and Cancel, so only play a sound on one of them. + sendInputToMovie(key, repeat, pressed, released); + break; + case ACTION_MENU_A: + case ACTION_MENU_X: + case ACTION_MENU_Y: + // 4J-PB - play a Press sound + //CD - Removed, causes a sound on all presses + /*if(pressed) + { + ui.PlayUISFX(eSFX_Press); + }*/ + sendInputToMovie(key, repeat, pressed, released); + break; + + case ACTION_MENU_B: + // 4J-PB - play a Press sound + //CD - Removed, causes a sound on all presses + /*if(pressed) + { + ui.PlayUISFX(eSFX_Back); + }*/ + sendInputToMovie(key, repeat, pressed, released); + break; + + case ACTION_MENU_LEFT_SCROLL: + case ACTION_MENU_RIGHT_SCROLL: + //CD - Removed, causes a sound on all presses + /*if(pressed) + { + ui.PlayUISFX(eSFX_Scroll); + }*/ + sendInputToMovie(key, repeat, pressed, released); + break; + case ACTION_MENU_PAGEUP: + case ACTION_MENU_PAGEDOWN: + case ACTION_MENU_LEFT: + case ACTION_MENU_RIGHT: + case ACTION_MENU_UP: + case ACTION_MENU_DOWN: + sendInputToMovie(key, repeat, pressed, released); + break; + } + } +} + +void UIComponent_Tooltips::overrideSFX(int iPad, int key, bool bVal) +{ + m_overrideSFX[iPad][key]=bVal; +} diff --git a/Minecraft.Client/Common/UI/UIComponent_Tooltips.h b/Minecraft.Client/Common/UI/UIComponent_Tooltips.h new file mode 100644 index 00000000..4b4c8268 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIComponent_Tooltips.h @@ -0,0 +1,110 @@ +#pragma once + +#include "UIScene.h" + +class UIComponent_Tooltips : public UIScene +{ +private: + bool m_bSplitscreen; + +protected: + typedef struct _TooltipValues + { + bool show; + int iString; + + _TooltipValues() + { + show = false; + iString = -1; + } + } TooltipValues; + + TooltipValues m_tooltipValues[eToolTipNumButtons]; + + IggyName m_funcSetTooltip, m_funcSetOpacity, m_funcSetABSwap, m_funcUpdateLayout; + +#ifdef __PSVITA__ + enum ETouchInput + { + ETouchInput_Touch_A, + ETouchInput_Touch_B, + ETouchInput_Touch_X, + ETouchInput_Touch_Y, + ETouchInput_Touch_LT, + ETouchInput_Touch_RightTrigger, + ETouchInput_Touch_LeftBumper, + ETouchInput_Touch_RightBumper, + ETouchInput_Touch_LeftStick, + + ETouchInput_Count, + }; + UIControl_Touch m_TouchController[ETouchInput_Count]; +#endif + + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) +#ifdef __PSVITA__ + UI_MAP_ELEMENT( m_TouchController[ETouchInput_Touch_A], "Touch_A") + UI_MAP_ELEMENT( m_TouchController[ETouchInput_Touch_B], "Touch_B") + UI_MAP_ELEMENT( m_TouchController[ETouchInput_Touch_X], "Touch_X") + UI_MAP_ELEMENT( m_TouchController[ETouchInput_Touch_Y], "Touch_Y") + UI_MAP_ELEMENT( m_TouchController[ETouchInput_Touch_LT], "Touch_LT") + UI_MAP_ELEMENT( m_TouchController[ETouchInput_Touch_RightTrigger], "Touch_RightTrigger") + UI_MAP_ELEMENT( m_TouchController[ETouchInput_Touch_LeftBumper], "Touch_LeftBumper") + UI_MAP_ELEMENT( m_TouchController[ETouchInput_Touch_RightBumper], "Touch_RightBumper") + UI_MAP_ELEMENT( m_TouchController[ETouchInput_Touch_LeftStick], "Touch_LeftStick") +#endif + UI_MAP_NAME( m_funcSetTooltip, L"SetToolTip") + UI_MAP_NAME( m_funcSetOpacity, L"SetOpacity") + UI_MAP_NAME( m_funcSetABSwap, L"SetABSwap") + UI_MAP_NAME( m_funcUpdateLayout, L"UpdateLayout") + UI_END_MAP_ELEMENTS_AND_NAMES() + + virtual wstring getMoviePath(); + + virtual F64 getSafeZoneHalfWidth(); + +public: + UIComponent_Tooltips(int iPad, void *initData, UILayer *parentLayer); + + virtual EUIScene getSceneType() { return eUIComponent_Tooltips;} + + // Returns true if this scene handles input + virtual bool stealsFocus() { return false; } + + // Returns true if this scene has focus for the pad passed in + virtual bool hasFocus(int iPad) { return false; } + + // Returns true if lower scenes in this scenes layer, or in any layer below this scenes layers should be hidden + virtual bool hidesLowerScenes() { return false; } + + virtual void updateSafeZone(); + + virtual void tick(); + + // RENDERING + virtual void render(S32 width, S32 height, C4JRender::eViewportType viewport); + + virtual void SetTooltipText( unsigned int tooltip, int iTextID ); + virtual void SetEnableTooltips( bool bVal ); + virtual void ShowTooltip( unsigned int tooltip, bool show ); + virtual void SetTooltips( int iA, int iB=-1, int iX=-1, int iY=-1 , int iLT=-1, int iRT=-1, int iLB=-1, int iRB=-1, int iLS=-1, bool forceUpdate = false); + virtual void EnableTooltip( unsigned int tooltip, bool enable ); + + virtual void handleReload(); + virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled); + + void overrideSFX(int iPad, int key, bool bVal); + + +private: + bool _SetTooltip(unsigned int iToolTip, int iTextID); + void _SetTooltip(unsigned int iToolTipId, const wstring &label, bool show, bool force = false); + void _Relayout(); + + bool m_overrideSFX[XUSER_MAX_COUNT][ACTION_MAX_MENU]; + +#ifdef __PSVITA__ + virtual void handleTouchInput(unsigned int iPad, S32 x, S32 y, int iId, bool bPressed, bool bRepeat, bool bReleased); +#endif +};
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIComponent_TutorialPopup.cpp b/Minecraft.Client/Common/UI/UIComponent_TutorialPopup.cpp new file mode 100644 index 00000000..858a8b43 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIComponent_TutorialPopup.cpp @@ -0,0 +1,539 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIComponent_TutorialPopup.h" +#include "..\..\Common\Tutorial\Tutorial.h" +#include "..\..\..\Minecraft.World\StringHelpers.h" +#include "..\..\MultiplayerLocalPlayer.h" +#include "..\..\Minecraft.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.level.tile.h" + +UIComponent_TutorialPopup::UIComponent_TutorialPopup(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) +{ + // Setup all the Iggy references we need for this scene + initialiseMovie(); + + m_interactScene = NULL; + m_lastInteractSceneMoved = NULL; + m_lastSceneMovedLeft = false; + m_bAllowFade = false; + m_iconItem = nullptr; + m_iconIsFoil = false; + + m_bContainerMenuVisible = false; + m_bSplitscreenGamertagVisible = false; + + m_labelDescription.init(L""); +} + +wstring UIComponent_TutorialPopup::getMoviePath() +{ + switch( m_parentLayer->getViewport() ) + { + case C4JRender::VIEWPORT_TYPE_SPLIT_TOP: + case C4JRender::VIEWPORT_TYPE_SPLIT_BOTTOM: + case C4JRender::VIEWPORT_TYPE_SPLIT_LEFT: + case C4JRender::VIEWPORT_TYPE_SPLIT_RIGHT: + case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_LEFT: + case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_RIGHT: + case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_LEFT: + case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_RIGHT: + return L"TutorialPopupSplit"; + break; + case C4JRender::VIEWPORT_TYPE_FULLSCREEN: + default: + return L"TutorialPopup"; + break; + } +} + +void UIComponent_TutorialPopup::UpdateTutorialPopup() +{ + // has the Splitscreen Gamertag visibility been changed? Re-Adjust Layout to prevent overlaps! + if(m_bSplitscreenGamertagVisible != (bool)(app.GetGameSettings(ProfileManager.GetPrimaryPad(),eGameSetting_DisplaySplitscreenGamertags) != 0)) + { + m_bSplitscreenGamertagVisible = (bool)(app.GetGameSettings(ProfileManager.GetPrimaryPad(),eGameSetting_DisplaySplitscreenGamertags) != 0); + handleReload(); + } +} + +void UIComponent_TutorialPopup::handleReload() +{ + IggyDataValue result; + IggyDataValue value[1]; + value[0].type = IGGY_DATATYPE_boolean; + value[0].boolval = (bool)((app.GetGameSettings(ProfileManager.GetPrimaryPad(),eGameSetting_DisplaySplitscreenGamertags)!=0) && !m_bContainerMenuVisible); // 4J - TomK - Offset for splitscreen gamertag? + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcAdjustLayout, 1 , value ); +} + +void UIComponent_TutorialPopup::SetTutorialDescription(TutorialPopupInfo *info) +{ + m_interactScene = info->interactScene; + + wstring parsed = _SetIcon(info->icon, info->iAuxVal, info->isFoil, info->desc); + parsed = _SetImage( parsed ); + parsed = ParseDescription(m_iPad, parsed); + + if(parsed.empty()) + { + _SetDescription( info->interactScene, L"", L"", info->allowFade, info->isReminder ); + } + else + { + _SetDescription( info->interactScene, parsed, info->title, info->allowFade, info->isReminder ); + } +} + +void UIComponent_TutorialPopup::RemoveInteractSceneReference(UIScene *scene) +{ + if( m_interactScene == scene ) + { + m_interactScene = NULL; + } +} + +void UIComponent_TutorialPopup::SetVisible(bool visible) +{ + m_parentLayer->showComponent(0,eUIComponent_TutorialPopup,visible); + + if( visible && m_bAllowFade ) + { + //Initialise a timer to fade us out again + app.DebugPrintf("UIComponent_TutorialPopup::SetVisible: setting TUTORIAL_POPUP_FADE_TIMER_ID to %d\n",m_tutorial->GetTutorialDisplayMessageTime()); + addTimer(TUTORIAL_POPUP_FADE_TIMER_ID,m_tutorial->GetTutorialDisplayMessageTime()); + } +} + +bool UIComponent_TutorialPopup::IsVisible() +{ + return m_parentLayer->isComponentVisible(eUIComponent_TutorialPopup); +} + +void UIComponent_TutorialPopup::handleTimerComplete(int id) +{ + switch(id) + { + case TUTORIAL_POPUP_FADE_TIMER_ID: + SetVisible(false); + killTimer(id); + app.DebugPrintf("handleTimerComplete: setting TUTORIAL_POPUP_MOVE_SCENE_TIMER_ID\n"); + addTimer(TUTORIAL_POPUP_MOVE_SCENE_TIMER_ID,TUTORIAL_POPUP_MOVE_SCENE_TIME); + break; + case TUTORIAL_POPUP_MOVE_SCENE_TIMER_ID: + UpdateInteractScenePosition(IsVisible()); + killTimer(id); + break; + } +} + +void UIComponent_TutorialPopup::_SetDescription(UIScene *interactScene, const wstring &desc, const wstring &title, bool allowFade, bool isReminder) +{ + m_interactScene = interactScene; + app.DebugPrintf("Setting m_interactScene to %08x\n", m_interactScene); + if( interactScene != m_lastInteractSceneMoved ) m_lastInteractSceneMoved = NULL; + if(desc.empty()) + { + SetVisible( false ); + app.DebugPrintf("_SetDescription1: setting TUTORIAL_POPUP_MOVE_SCENE_TIMER_ID\n"); + addTimer(TUTORIAL_POPUP_MOVE_SCENE_TIMER_ID,TUTORIAL_POPUP_MOVE_SCENE_TIME); + killTimer(TUTORIAL_POPUP_FADE_TIMER_ID); + } + else + { + SetVisible( true ); + app.DebugPrintf("_SetDescription2: setting TUTORIAL_POPUP_MOVE_SCENE_TIMER_ID\n"); + addTimer(TUTORIAL_POPUP_MOVE_SCENE_TIMER_ID,TUTORIAL_POPUP_MOVE_SCENE_TIME); + + if( allowFade ) + { + //Initialise a timer to fade us out again + app.DebugPrintf("_SetDescription: setting TUTORIAL_POPUP_FADE_TIMER_ID\n"); + addTimer(TUTORIAL_POPUP_FADE_TIMER_ID,m_tutorial->GetTutorialDisplayMessageTime()); + } + else + { + app.DebugPrintf("_SetDescription: killing TUTORIAL_POPUP_FADE_TIMER_ID\n"); + killTimer(TUTORIAL_POPUP_FADE_TIMER_ID); + } + m_bAllowFade = allowFade; + + if(isReminder) + { + wstring text(app.GetString( IDS_TUTORIAL_REMINDER )); + text.append( desc ); + stripWhitespaceForHtml( text ); + // set the text colour + wchar_t formatting[40]; + // 4J Stu - Don't set HTML font size, that's set at design time in flash + //swprintf(formatting, 40, L"<font color=\"#%08x\" size=\"%d\">",app.GetHTMLColour(eHTMLColor_White),m_textFontSize); + swprintf(formatting, 40, L"<font color=\"#%08x\">",app.GetHTMLColour(eHTMLColor_White)); + text = formatting + text; + + m_labelDescription.setLabel( text, true ); + } + else + { + wstring text(desc); + stripWhitespaceForHtml( text ); + // set the text colour + wchar_t formatting[40]; + // 4J Stu - Don't set HTML font size, that's set at design time in flash + //swprintf(formatting, 40, L"<font color=\"#%08x\" size=\"%d\">",app.GetHTMLColour(eHTMLColor_White),m_textFontSize); + swprintf(formatting, 40, L"<font color=\"#%08x\">",app.GetHTMLColour(eHTMLColor_White)); + text = formatting + text; + + m_labelDescription.setLabel( text, true ); + + } + + m_labelTitle.setLabel( title, true ); + m_labelTitle.setVisible(!title.empty()); + + + // read host setting if gamertag is visible or not and pass on to Adjust Layout function (so we can offset it to stay clear of the gamertag) + m_bSplitscreenGamertagVisible = (bool)(app.GetGameSettings(ProfileManager.GetPrimaryPad(),eGameSetting_DisplaySplitscreenGamertags)!=0); + IggyDataValue result; + IggyDataValue value[1]; + value[0].type = IGGY_DATATYPE_boolean; + value[0].boolval = (m_bSplitscreenGamertagVisible && !m_bContainerMenuVisible); // 4J - TomK - Offset for splitscreen gamertag? + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcAdjustLayout, 1 , value ); + } +} + +wstring UIComponent_TutorialPopup::_SetIcon(int icon, int iAuxVal, bool isFoil, LPCWSTR desc) +{ + wstring temp(desc); + + bool isFixedIcon = false; + + m_iconIsFoil = isFoil; + if( icon != TUTORIAL_NO_ICON ) + { + m_iconIsFoil = false; + m_iconItem = shared_ptr<ItemInstance>(new ItemInstance(icon,1,iAuxVal)); + } + else + { + m_iconItem = nullptr; + wstring openTag(L"{*ICON*}"); + wstring closeTag(L"{*/ICON*}"); + int iconTagStartPos = (int)temp.find(openTag); + int iconStartPos = iconTagStartPos + (int)openTag.length(); + if( iconTagStartPos > 0 && iconStartPos < (int)temp.length() ) + { + int iconEndPos = (int)temp.find( closeTag, iconStartPos ); + + if(iconEndPos > iconStartPos && iconEndPos < (int)temp.length() ) + { + wstring id = temp.substr(iconStartPos, iconEndPos - iconStartPos); + + vector<wstring> idAndAux = stringSplit(id,L':'); + + int iconId = _fromString<int>(idAndAux[0]); + + if(idAndAux.size() > 1) + { + iAuxVal = _fromString<int>(idAndAux[1]); + } + else + { + iAuxVal = 0; + } + m_iconItem = shared_ptr<ItemInstance>(new ItemInstance(iconId,1,iAuxVal)); + + temp.replace(iconTagStartPos, iconEndPos - iconTagStartPos + closeTag.length(), L""); + } + } + + // remove any icon text + else if(temp.find(L"{*CraftingTableIcon*}")!=wstring::npos) + { + m_iconItem = shared_ptr<ItemInstance>(new ItemInstance(Tile::workBench_Id,1,0)); + } + else if(temp.find(L"{*SticksIcon*}")!=wstring::npos) + { + m_iconItem = shared_ptr<ItemInstance>(new ItemInstance(Item::stick_Id,1,0)); + } + else if(temp.find(L"{*PlanksIcon*}")!=wstring::npos) + { + m_iconItem = shared_ptr<ItemInstance>(new ItemInstance(Tile::wood_Id,1,0)); + } + else if(temp.find(L"{*WoodenShovelIcon*}")!=wstring::npos) + { + m_iconItem = shared_ptr<ItemInstance>(new ItemInstance(Item::shovel_wood_Id,1,0)); + } + else if(temp.find(L"{*WoodenHatchetIcon*}")!=wstring::npos) + { + m_iconItem = shared_ptr<ItemInstance>(new ItemInstance(Item::hatchet_wood_Id,1,0)); + } + else if(temp.find(L"{*WoodenPickaxeIcon*}")!=wstring::npos) + { + m_iconItem = shared_ptr<ItemInstance>(new ItemInstance(Item::pickAxe_wood_Id,1,0)); + } + else if(temp.find(L"{*FurnaceIcon*}")!=wstring::npos) + { + m_iconItem = shared_ptr<ItemInstance>(new ItemInstance(Tile::furnace_Id,1,0)); + } + else if(temp.find(L"{*WoodenDoorIcon*}")!=wstring::npos) + { + m_iconItem = shared_ptr<ItemInstance>(new ItemInstance(Item::door_wood,1,0)); + } + else if(temp.find(L"{*TorchIcon*}")!=wstring::npos) + { + m_iconItem = shared_ptr<ItemInstance>(new ItemInstance(Tile::torch_Id,1,0)); + } + else if(temp.find(L"{*BoatIcon*}")!=wstring::npos) + { + m_iconItem = shared_ptr<ItemInstance>(new ItemInstance(Item::boat_Id,1,0)); + } + else if(temp.find(L"{*FishingRodIcon*}")!=wstring::npos) + { + m_iconItem = shared_ptr<ItemInstance>(new ItemInstance(Item::fishingRod_Id,1,0)); + } + else if(temp.find(L"{*FishIcon*}")!=wstring::npos) + { + m_iconItem = shared_ptr<ItemInstance>(new ItemInstance(Item::fish_raw_Id,1,0)); + } + else if(temp.find(L"{*MinecartIcon*}")!=wstring::npos) + { + m_iconItem = shared_ptr<ItemInstance>(new ItemInstance(Item::minecart_Id,1,0)); + } + else if(temp.find(L"{*RailIcon*}")!=wstring::npos) + { + m_iconItem = shared_ptr<ItemInstance>(new ItemInstance(Tile::rail_Id,1,0)); + } + else if(temp.find(L"{*PoweredRailIcon*}")!=wstring::npos) + { + m_iconItem = shared_ptr<ItemInstance>(new ItemInstance(Tile::goldenRail_Id,1,0)); + } + else if(temp.find(L"{*StructuresIcon*}")!=wstring::npos) + { + isFixedIcon = true; + setupIconHolder(e_ICON_TYPE_STRUCTURES); + } + else if(temp.find(L"{*ToolsIcon*}")!=wstring::npos) + { + isFixedIcon = true; + setupIconHolder(e_ICON_TYPE_TOOLS); + } + else if(temp.find(L"{*StoneIcon*}")!=wstring::npos) + { + m_iconItem = shared_ptr<ItemInstance>(new ItemInstance(Tile::rock_Id,1,0)); + } + else + { + m_iconItem = nullptr; + } + } + if(!isFixedIcon && m_iconItem != NULL) setupIconHolder(e_ICON_TYPE_IGGY); + m_controlIconHolder.setVisible( isFixedIcon || m_iconItem != NULL); + + return temp; +} + +wstring UIComponent_TutorialPopup::_SetImage(wstring &desc) +{ + // 4J Stu - Unused +#if 0 + BOOL imageShowAtStart = m_image.IsShown(); + + wstring openTag(L"{*IMAGE*}"); + wstring closeTag(L"{*/IMAGE*}"); + int imageTagStartPos = (int)desc.find(openTag); + int imageStartPos = imageTagStartPos + (int)openTag.length(); + if( imageTagStartPos > 0 && imageStartPos < (int)desc.length() ) + { + int imageEndPos = (int)desc.find( closeTag, imageStartPos ); + + if(imageEndPos > imageStartPos && imageEndPos < (int)desc.length() ) + { + wstring id = desc.substr(imageStartPos, imageEndPos - imageStartPos); + m_image.SetImagePath( id.c_str() ); + m_image.SetShow( TRUE ); + + desc.replace(imageTagStartPos, imageEndPos - imageTagStartPos + closeTag.length(), L""); + } + } + else + { + // hide the icon slot + m_image.SetShow( FALSE ); + } + + BOOL imageShowAtEnd = m_image.IsShown(); + if(imageShowAtStart != imageShowAtEnd) + { + float fHeight, fWidth, fIconHeight, fDescHeight, fDescWidth; + m_image.GetBounds(&fWidth,&fIconHeight); + GetBounds(&fWidth,&fHeight); + + + // 4J Stu - For some reason when we resize the scene it resets the size of the HTML control + // We don't want that to happen, so get it's size before and set it back after + m_description.GetBounds(&fDescWidth,&fDescHeight); + if(imageShowAtEnd) + { + SetBounds(fWidth, fHeight + fIconHeight); + } + else + { + SetBounds(fWidth, fHeight - fIconHeight); + } + m_description.SetBounds(fDescWidth, fDescHeight); + } +#endif + return desc; +} + + +wstring UIComponent_TutorialPopup::ParseDescription(int iPad, wstring &text) +{ + text = replaceAll(text, L"{*CraftingTableIcon*}", L""); + text = replaceAll(text, L"{*SticksIcon*}", L""); + text = replaceAll(text, L"{*PlanksIcon*}", L""); + text = replaceAll(text, L"{*WoodenShovelIcon*}", L""); + text = replaceAll(text, L"{*WoodenHatchetIcon*}", L""); + text = replaceAll(text, L"{*WoodenPickaxeIcon*}", L""); + text = replaceAll(text, L"{*FurnaceIcon*}", L""); + text = replaceAll(text, L"{*WoodenDoorIcon*}", L""); + text = replaceAll(text, L"{*TorchIcon*}", L""); + text = replaceAll(text, L"{*MinecartIcon*}", L""); + text = replaceAll(text, L"{*BoatIcon*}", L""); + text = replaceAll(text, L"{*FishingRodIcon*}", L""); + text = replaceAll(text, L"{*FishIcon*}", L""); + text = replaceAll(text, L"{*RailIcon*}", L""); + text = replaceAll(text, L"{*PoweredRailIcon*}", L""); + text = replaceAll(text, L"{*StructuresIcon*}", L""); + text = replaceAll(text, L"{*ToolsIcon*}", L""); + text = replaceAll(text, L"{*StoneIcon*}", L""); + + bool exitScreenshot = false; + size_t pos = text.find(L"{*EXIT_PICTURE*}"); + if(pos != wstring::npos) exitScreenshot = true; + text = replaceAll(text, L"{*EXIT_PICTURE*}", L""); + m_controlExitScreenshot.setVisible(exitScreenshot); + /* +#define MINECRAFT_ACTION_RENDER_DEBUG ACTION_INGAME_13 +#define MINECRAFT_ACTION_PAUSEMENU ACTION_INGAME_15 +#define MINECRAFT_ACTION_SNEAK_TOGGLE ACTION_INGAME_17 + */ + + return app.FormatHTMLString(iPad,text); +} + +void UIComponent_TutorialPopup::UpdateInteractScenePosition(bool visible) +{ + if( m_interactScene == NULL ) return; + + // 4J-PB - check this players screen section to see if we should allow the animation + bool bAllowAnim=false; + bool isCraftingScene = (m_interactScene->getSceneType() == eUIScene_Crafting2x2Menu) || (m_interactScene->getSceneType() == eUIScene_Crafting3x3Menu); + bool isCreativeScene = (m_interactScene->getSceneType() == eUIScene_CreativeMenu); + switch(Minecraft::GetInstance()->localplayers[m_iPad]->m_iScreenSection) + { + case C4JRender::VIEWPORT_TYPE_FULLSCREEN: + case C4JRender::VIEWPORT_TYPE_SPLIT_TOP: + case C4JRender::VIEWPORT_TYPE_SPLIT_BOTTOM: + bAllowAnim=true; + break; + default: + // anim allowed for everything except the crafting 2x2 and 3x3, and the creative menu + if(!isCraftingScene && !isCreativeScene) + { + bAllowAnim=true; + } + break; + } + + if(bAllowAnim) + { + bool movingLeft = visible; + + if( (m_lastInteractSceneMoved != m_interactScene && movingLeft) || ( m_lastInteractSceneMoved == m_interactScene && m_lastSceneMovedLeft != movingLeft ) ) + { + if(movingLeft) + { + m_interactScene->slideLeft(); + } + else + { + m_interactScene->slideRight(); + } + + m_lastInteractSceneMoved = m_interactScene; + m_lastSceneMovedLeft = movingLeft; + } + } + +} + +void UIComponent_TutorialPopup::render(S32 width, S32 height, C4JRender::eViewportType viewport) +{ + if(viewport != C4JRender::VIEWPORT_TYPE_FULLSCREEN) + { + S32 xPos = 0; + S32 yPos = 0; + switch( viewport ) + { + case C4JRender::VIEWPORT_TYPE_SPLIT_BOTTOM: + xPos = (S32)(ui.getScreenWidth() / 2); + yPos = (S32)(ui.getScreenHeight() / 2); + break; + case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_LEFT: + yPos = (S32)(ui.getScreenHeight() / 2); + break; + case C4JRender::VIEWPORT_TYPE_SPLIT_TOP: + case C4JRender::VIEWPORT_TYPE_SPLIT_RIGHT: + case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_RIGHT: + xPos = (S32)(ui.getScreenWidth() / 2); + break; + case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_RIGHT: + xPos = (S32)(ui.getScreenWidth() / 2); + yPos = (S32)(ui.getScreenHeight() / 2); + break; + } + //Adjust for safezone + switch( viewport ) + { + case C4JRender::VIEWPORT_TYPE_SPLIT_TOP: + case C4JRender::VIEWPORT_TYPE_SPLIT_LEFT: + case C4JRender::VIEWPORT_TYPE_SPLIT_RIGHT: + case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_LEFT: + case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_RIGHT: + yPos += getSafeZoneHalfHeight(); + break; + } + switch( viewport ) + { + case C4JRender::VIEWPORT_TYPE_SPLIT_TOP: + case C4JRender::VIEWPORT_TYPE_SPLIT_BOTTOM: + case C4JRender::VIEWPORT_TYPE_SPLIT_RIGHT: + case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_RIGHT: + case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_RIGHT: + xPos -= getSafeZoneHalfWidth(); + break; + } + ui.setupRenderPosition(xPos, yPos); + + IggyPlayerSetDisplaySize( getMovie(), width, height ); + IggyPlayerDraw( getMovie() ); + } + else + { + UIScene::render(width, height, viewport); + } +} + +void UIComponent_TutorialPopup::customDraw(IggyCustomDrawCallbackRegion *region) +{ + if(m_iconItem != NULL) customDrawSlotControl(region,m_iPad,m_iconItem,1.0f,m_iconItem->isFoil() || m_iconIsFoil,false); +} + +void UIComponent_TutorialPopup::setupIconHolder(EIcons icon) +{ + app.DebugPrintf("Setting icon holder to %d\n", icon); + IggyDataValue result; + IggyDataValue value[1]; + value[0].type = IGGY_DATATYPE_number; + value[0].number = (F64)icon; + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcSetupIconHolder , 1 , value ); +} diff --git a/Minecraft.Client/Common/UI/UIComponent_TutorialPopup.h b/Minecraft.Client/Common/UI/UIComponent_TutorialPopup.h new file mode 100644 index 00000000..36f78300 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIComponent_TutorialPopup.h @@ -0,0 +1,101 @@ +#pragma once + +#include "UIScene.h" + +#define TUTORIAL_POPUP_FADE_TIMER_ID 0 +#define TUTORIAL_POPUP_MOVE_SCENE_TIMER_ID 1 +#define TUTORIAL_POPUP_MOVE_SCENE_TIME 500 + + +class UIComponent_TutorialPopup : public UIScene +{ +private: + // A scene that may be displayed behind the popup that the player is using, that will need shifted so we can see it clearly. + UIScene *m_interactScene, *m_lastInteractSceneMoved; + bool m_lastSceneMovedLeft; + bool m_bAllowFade; + Tutorial *m_tutorial; + shared_ptr<ItemInstance> m_iconItem; + bool m_iconIsFoil; + //int m_iLocalPlayerC; + + bool m_bContainerMenuVisible; + bool m_bSplitscreenGamertagVisible; + + // Maps to values in AS + enum EIcons + { + e_ICON_TYPE_IGGY = 0, + e_ICON_TYPE_ARMOUR = 1, + e_ICON_TYPE_BREWING = 2, + e_ICON_TYPE_DECORATION = 3, + e_ICON_TYPE_FOOD = 4, + e_ICON_TYPE_MATERIALS = 5, + e_ICON_TYPE_MECHANISMS = 6, + e_ICON_TYPE_MISC = 7, + e_ICON_TYPE_REDSTONE_AND_TRANSPORT = 8, + e_ICON_TYPE_STRUCTURES = 9, + e_ICON_TYPE_TOOLS = 10, + e_ICON_TYPE_TRANSPORT = 11, + }; + +public: + UIComponent_TutorialPopup(int iPad, void *initData, UILayer *parentLayer); + +protected: + UIControl_Label m_labelDescription, m_labelTitle; + UIControl m_controlIconHolder; + UIControl m_controlExitScreenshot; + IggyName m_funcAdjustLayout, m_funcSetupIconHolder; + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) + UI_MAP_ELEMENT( m_labelTitle, "Title") + UI_MAP_ELEMENT( m_labelDescription, "Description") + UI_MAP_ELEMENT( m_controlIconHolder, "IconHolder") + UI_MAP_ELEMENT( m_controlExitScreenshot, "ExitScreenShot") + + UI_MAP_NAME( m_funcAdjustLayout, L"AdjustLayout") + UI_MAP_NAME( m_funcSetupIconHolder, L"SetupIconHolder") + UI_END_MAP_ELEMENTS_AND_NAMES() + + virtual wstring getMoviePath(); + +public: + virtual EUIScene getSceneType() { return eUIComponent_TutorialPopup;} + + // Returns true if this scene handles input + virtual bool stealsFocus() { return false; } + + // Returns true if this scene has focus for the pad passed in + virtual bool hasFocus(int iPad) { return false; } + + // Returns true if lower scenes in this scenes layer, or in any layer below this scenes layers should be hidden + virtual bool hidesLowerScenes() { return false; } + + virtual void handleReload(); + + void SetContainerMenuVisible(bool bContainerMenuVisible) { m_bContainerMenuVisible = bContainerMenuVisible; } + void UpdateTutorialPopup(); + + void SetTutorial( Tutorial *tutorial ) { m_tutorial = tutorial; } + void SetTutorialDescription(TutorialPopupInfo *info); + void RemoveInteractSceneReference(UIScene *scene); + void SetVisible(bool visible); + bool IsVisible(); + + // RENDERING + virtual void render(S32 width, S32 height, C4JRender::eViewportType viewport); + + virtual void customDraw(IggyCustomDrawCallbackRegion *region); + +protected: + void handleTimerComplete(int id); + +private: + void _SetDescription(UIScene *interactScene, const wstring &desc, const wstring &title, bool allowFade, bool isReminder); + wstring _SetIcon(int icon, int iAuxVal, bool isFoil, LPCWSTR desc); + wstring _SetImage(wstring &desc); + wstring ParseDescription(int iPad, wstring &text); + void UpdateInteractScenePosition(bool visible); + + void setupIconHolder(EIcons icon); +}; diff --git a/Minecraft.Client/Common/UI/UIControl.cpp b/Minecraft.Client/Common/UI/UIControl.cpp new file mode 100644 index 00000000..ec2e13d8 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIControl.cpp @@ -0,0 +1,153 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIControl.h" +#include "..\..\..\Minecraft.World\StringHelpers.h" +#include "..\..\..\Minecraft.World\JavaMath.h" + +UIControl::UIControl() +{ + m_parentScene = NULL; + m_lastOpacity = 1.0f; + m_controlName = ""; + m_isVisible = true; + m_bHidden = false; + m_eControlType = eNoControl; +} + +bool UIControl::setupControl(UIScene *scene, IggyValuePath *parent, const string &controlName) +{ + m_parentScene = scene; + m_controlName = controlName; + + rrbool res = IggyValuePathMakeNameRef ( &m_iggyPath , parent , controlName.c_str() ); + + m_nameXPos = registerFastName(L"x"); + m_nameYPos = registerFastName(L"y"); + m_nameWidth = registerFastName(L"width"); + m_nameHeight = registerFastName(L"height"); + m_funcSetAlpha = registerFastName(L"SetControlAlpha"); + m_nameVisible = registerFastName(L"visible"); + + F64 fx, fy, fwidth, fheight; + IggyValueGetF64RS( getIggyValuePath() , m_nameXPos , NULL , &fx ); + IggyValueGetF64RS( getIggyValuePath() , m_nameYPos , NULL , &fy ); + IggyValueGetF64RS( getIggyValuePath() , m_nameWidth , NULL , &fwidth ); + IggyValueGetF64RS( getIggyValuePath() , m_nameHeight , NULL , &fheight ); + + m_x = (S32)fx; + m_y = (S32)fy; + m_width = (S32)Math::round(fwidth); + m_height = (S32)Math::round(fheight); + + return res; +} + +#ifdef __PSVITA__ +void UIControl::UpdateControl() +{ + F64 fx, fy, fwidth, fheight; + IggyValueGetF64RS( getIggyValuePath() , m_nameXPos , NULL , &fx ); + IggyValueGetF64RS( getIggyValuePath() , m_nameYPos , NULL , &fy ); + IggyValueGetF64RS( getIggyValuePath() , m_nameWidth , NULL , &fwidth ); + IggyValueGetF64RS( getIggyValuePath() , m_nameHeight , NULL , &fheight ); + m_x = (S32)fx; + m_y = (S32)fy; + m_width = (S32)Math::round(fwidth); + m_height = (S32)Math::round(fheight); +} +#endif // __PSVITA__ + +void UIControl::ReInit() +{ + if(m_lastOpacity != 1.0f) + { + IggyDataValue result; + IggyDataValue value[2]; + IggyStringUTF8 stringVal; + + stringVal.string = (char *)m_controlName.c_str(); + stringVal.length = m_controlName.length(); + value[0].type = IGGY_DATATYPE_string_UTF8; + value[0].string8 = stringVal; + + value[1].type = IGGY_DATATYPE_number; + value[1].number = m_lastOpacity; + + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, m_parentScene->m_rootPath , m_funcSetAlpha , 2 , value ); + } + + IggyValueSetBooleanRS( getIggyValuePath(), m_nameVisible, NULL, m_isVisible ); +} + +IggyValuePath *UIControl::getIggyValuePath() +{ + return &m_iggyPath; +} + +S32 UIControl::getXPos() +{ + return m_x; +} + +S32 UIControl::getYPos() +{ + return m_y; +} + +S32 UIControl::getWidth() +{ + return m_width; +} + +S32 UIControl::getHeight() +{ + return m_height; +} + +void UIControl::setOpacity(float percent) +{ + if(percent != m_lastOpacity) + { + m_lastOpacity = percent; + + IggyDataValue result; + IggyDataValue value[2]; + IggyStringUTF8 stringVal; + + stringVal.string = (char *)m_controlName.c_str(); + stringVal.length = m_controlName.length(); + value[0].type = IGGY_DATATYPE_string_UTF8; + value[0].string8 = stringVal; + + value[1].type = IGGY_DATATYPE_number; + value[1].number = m_lastOpacity; + + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, m_parentScene->m_rootPath , m_funcSetAlpha , 2 , value ); + } +} + +void UIControl::setVisible(bool visible) +{ + if(visible != m_isVisible) + { + rrbool succ = IggyValueSetBooleanRS( getIggyValuePath(), m_nameVisible, NULL, visible ); + if(succ) m_isVisible = visible; + else app.DebugPrintf("Failed to set visibility for control\n"); + } +} + +bool UIControl::getVisible() +{ + rrbool bVisible = false; + + IggyResult result = IggyValueGetBooleanRS ( getIggyValuePath() , m_nameVisible, NULL, &bVisible ); + + m_isVisible = bVisible; + + return bVisible; +} + +IggyName UIControl::registerFastName(const wstring &name) +{ + return m_parentScene->registerFastName(name); +} diff --git a/Minecraft.Client/Common/UI/UIControl.h b/Minecraft.Client/Common/UI/UIControl.h new file mode 100644 index 00000000..3b4ef050 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIControl.h @@ -0,0 +1,92 @@ +#pragma once + +// This class for any name object in the flash scene +class UIControl +{ + +public: + enum eUIControlType + { + eNoControl, + eButton, + eButtonList, + eCheckBox, + eCursor, + eDLCList, + eDynamicLabel, + eEnchantmentBook, + eEnchantmentButton, + eHTMLLabel, + eLabel, + eLeaderboardList, + eMinecraftPlayer, + ePlayerList, + ePlayerSkinPreview, + eProgress, + eSaveList, + eSlider, + eSlotList, + eTextInput, + eTexturePackList, + eBitmapIcon, + eTouchControl, + }; +protected: + eUIControlType m_eControlType; + int m_id; + bool m_bHidden; // set by the Remove call + +public: + + void setControlType(eUIControlType eType) {m_eControlType=eType;} + eUIControlType getControlType() {return m_eControlType;} + void setId(int iID) { m_id=iID; } + int getId() { return m_id; } + UIScene * getParentScene() {return m_parentScene;} + +protected: + IggyValuePath m_iggyPath; + UIScene *m_parentScene; + string m_controlName; + + IggyName m_nameXPos, m_nameYPos, m_nameWidth, m_nameHeight; + IggyName m_funcSetAlpha, m_nameVisible; + + S32 m_x,m_y,m_width,m_height; + float m_lastOpacity; + bool m_isVisible; + +public: + UIControl(); + + virtual bool setupControl(UIScene *scene, IggyValuePath *parent, const string &controlName); +#ifdef __PSVITA__ + void UpdateControl(); + void setHidden(bool bHidden) {m_bHidden=bHidden;} + bool getHidden(void) {return m_bHidden;} +#endif + + IggyValuePath *getIggyValuePath(); + + string getControlName() { return m_controlName; } + + virtual void tick() {} + virtual void ReInit(); + + virtual void setFocus(bool focus) {} + + S32 getXPos(); + S32 getYPos(); + S32 getWidth(); + S32 getHeight(); + + void setOpacity(float percent); + void setVisible(bool visible); + bool getVisible(); + bool isVisible() { return m_isVisible; } + + virtual bool hasFocus() { return false; } + +protected: + IggyName registerFastName(const wstring &name); +}; diff --git a/Minecraft.Client/Common/UI/UIControl_Base.cpp b/Minecraft.Client/Common/UI/UIControl_Base.cpp new file mode 100644 index 00000000..18af2f63 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIControl_Base.cpp @@ -0,0 +1,112 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIControl.h" +#include "..\..\..\Minecraft.World\StringHelpers.h" +#include "..\..\..\Minecraft.World\JavaMath.h" + +UIControl_Base::UIControl_Base() +{ + m_bLabelChanged = false; + m_label = L""; + m_id = 0; +} + +bool UIControl_Base::setupControl(UIScene *scene, IggyValuePath *parent, const string &controlName) +{ + bool success = UIControl::setupControl(scene,parent,controlName); + + m_setLabelFunc = registerFastName(L"SetLabel"); + m_initFunc = registerFastName(L"Init"); + m_funcGetLabel = registerFastName(L"GetLabel"); + m_funcCheckLabelWidths = registerFastName(L"CheckLabelWidths"); + + return success; +} + +void UIControl_Base::tick() +{ + UIControl::tick(); + + if(m_bLabelChanged) + { + //app.DebugPrintf("Calling SetLabel - '%ls'\n", m_label.c_str()); + m_bLabelChanged = false; + + IggyDataValue result; + IggyDataValue value[1]; + value[0].type = IGGY_DATATYPE_string_UTF16; + IggyStringUTF16 stringVal; + + stringVal.string = (IggyUTF16*)m_label.c_str(); + stringVal.length = m_label.length(); + value[0].string16 = stringVal; + + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath() , m_setLabelFunc , 1 , value ); + } +} + +void UIControl_Base::setLabel(const wstring &label, bool instant, bool force) +{ + if( force || ((!m_label.empty() || !label.empty()) && m_label.compare(label) != 0) ) m_bLabelChanged = true; + m_label = label; + + if(m_bLabelChanged && instant) + { + m_bLabelChanged = false; + + IggyDataValue result; + IggyDataValue value[1]; + value[0].type = IGGY_DATATYPE_string_UTF16; + IggyStringUTF16 stringVal; + + stringVal.string = (IggyUTF16*)m_label.c_str(); + stringVal.length = m_label.length(); + value[0].string16 = stringVal; + + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath() , m_setLabelFunc , 1 , value ); + } +} + +void UIControl_Base::setLabel(const string &label) +{ + wstring wlabel = convStringToWstring(label); + setLabel(wlabel); +} + +const wchar_t* UIControl_Base::getLabel() +{ + IggyDataValue result; + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath() , m_funcGetLabel , 0 , NULL ); + + if(result.type == IGGY_DATATYPE_string_UTF16) + { + m_label = wstring( (wchar_t *)result.string16.string, result.string16.length); + } + + return m_label.c_str(); +} + +void UIControl_Base::setAllPossibleLabels(int labelCount, wchar_t labels[][256]) +{ + IggyDataValue result; + IggyDataValue *value = new IggyDataValue[labelCount]; + IggyStringUTF16 * stringVal = new IggyStringUTF16[labelCount]; + + for(unsigned int i = 0; i < labelCount; ++i) + { + stringVal[i].string = (IggyUTF16 *)labels[i]; + stringVal[i].length = wcslen(labels[i]); + value[i].type = IGGY_DATATYPE_string_UTF16; + value[i].string16 = stringVal[i]; + } + + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath() , m_funcCheckLabelWidths , labelCount , value ); + + delete [] value; + delete [] stringVal; +} + +bool UIControl_Base::hasFocus() +{ + return m_parentScene->controlHasFocus( this ); +} diff --git a/Minecraft.Client/Common/UI/UIControl_Base.h b/Minecraft.Client/Common/UI/UIControl_Base.h new file mode 100644 index 00000000..e70997c3 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIControl_Base.h @@ -0,0 +1,30 @@ +#pragma once + +#include "UIControl.h" + +// This class maps to the FJ_Base class in actionscript +class UIControl_Base : public UIControl +{ +protected: + IggyName m_initFunc; + IggyName m_setLabelFunc; + IggyName m_funcGetLabel; + IggyName m_funcCheckLabelWidths; + + bool m_bLabelChanged; + wstring m_label; +public: + UIControl_Base(); + + virtual bool setupControl(UIScene *scene, IggyValuePath *parent, const string &controlName); + + virtual void tick(); + + virtual void setLabel(const wstring &label, bool instant = false, bool force = false); + virtual void setLabel(const string &label); + const wchar_t* getLabel(); + virtual void setAllPossibleLabels(int labelCount, wchar_t labels[][256]); + int getId() { return m_id; } + + virtual bool hasFocus(); +}; diff --git a/Minecraft.Client/Common/UI/UIControl_BitmapIcon.cpp b/Minecraft.Client/Common/UI/UIControl_BitmapIcon.cpp new file mode 100644 index 00000000..49561906 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIControl_BitmapIcon.cpp @@ -0,0 +1,27 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIControl_BitmapIcon.h" + +bool UIControl_BitmapIcon::setupControl(UIScene *scene, IggyValuePath *parent, const string &controlName) +{ + UIControl::setControlType(UIControl::eBitmapIcon); + bool success = UIControl::setupControl(scene,parent,controlName); + + //SlotList specific initialisers + m_funcSetTextureName = registerFastName(L"SetTextureName"); + + return success; +} + +void UIControl_BitmapIcon::setTextureName(const wstring &iconName) +{ + IggyDataValue result; + IggyDataValue value[1]; + + IggyStringUTF16 stringVal; + stringVal.string = (IggyUTF16*)iconName.c_str(); + stringVal.length = iconName.length(); + value[0].type = IGGY_DATATYPE_string_UTF16; + value[0].string16 = stringVal; + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath(), m_funcSetTextureName , 1 , value ); +} diff --git a/Minecraft.Client/Common/UI/UIControl_BitmapIcon.h b/Minecraft.Client/Common/UI/UIControl_BitmapIcon.h new file mode 100644 index 00000000..9b2fe0a8 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIControl_BitmapIcon.h @@ -0,0 +1,14 @@ +#pragma once + +#include "UIControl.h" + +class UIControl_BitmapIcon : public UIControl +{ +private: + IggyName m_funcSetTextureName; + +public: + virtual bool setupControl(UIScene *scene, IggyValuePath *parent, const string &controlName); + + void setTextureName(const wstring &iconName); +};
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIControl_Button.cpp b/Minecraft.Client/Common/UI/UIControl_Button.cpp new file mode 100644 index 00000000..96ddb8eb --- /dev/null +++ b/Minecraft.Client/Common/UI/UIControl_Button.cpp @@ -0,0 +1,68 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIControl_Button.h" + +UIControl_Button::UIControl_Button() +{ +} + +bool UIControl_Button::setupControl(UIScene *scene, IggyValuePath *parent, const string &controlName) +{ + UIControl::setControlType(UIControl::eButton); + bool success = UIControl_Base::setupControl(scene,parent,controlName); + + //Button specific initialisers + m_funcEnableButton = registerFastName(L"EnableButton"); + + return success; +} + +void UIControl_Button::init(const wstring &label, int id) +{ + m_label = label; + m_id = id; + + IggyDataValue result; + IggyDataValue value[2]; + value[0].type = IGGY_DATATYPE_string_UTF16; + IggyStringUTF16 stringVal; + + stringVal.string = (IggyUTF16*)label.c_str(); + stringVal.length = label.length(); + value[0].string16 = stringVal; + + value[1].type = IGGY_DATATYPE_number; + value[1].number = id; + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath() , m_initFunc , 2 , value ); + +#ifdef __PSVITA__ + // 4J-PB - add this button to the vita touch box list + + switch(m_parentScene->GetParentLayer()->m_iLayer) + { + case eUILayer_Error: + case eUILayer_Fullscreen: + case eUILayer_Scene: + case eUILayer_HUD: + ui.TouchBoxAdd(this,m_parentScene); + break; + } +#endif +} + +void UIControl_Button::ReInit() +{ + UIControl_Base::ReInit(); + + init(m_label, m_id); +} + +void UIControl_Button::setEnable(bool enable) +{ + IggyDataValue result; + IggyDataValue value[1]; + + value[0].type = IGGY_DATATYPE_boolean; + value[0].boolval = enable; + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath() , m_funcEnableButton , 1 , value ); +} diff --git a/Minecraft.Client/Common/UI/UIControl_Button.h b/Minecraft.Client/Common/UI/UIControl_Button.h new file mode 100644 index 00000000..367a48d7 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIControl_Button.h @@ -0,0 +1,19 @@ +#pragma once + +#include "UIControl_Base.h" + +class UIControl_Button : public UIControl_Base +{ +private: + IggyName m_funcEnableButton; + +public: + UIControl_Button(); + + virtual bool setupControl(UIScene *scene, IggyValuePath *parent, const string &controlName); + + void init(const wstring &label, int id); + virtual void ReInit(); + + void setEnable(bool enable); +};
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIControl_ButtonList.cpp b/Minecraft.Client/Common/UI/UIControl_ButtonList.cpp new file mode 100644 index 00000000..32db4843 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIControl_ButtonList.cpp @@ -0,0 +1,197 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIControl_ButtonList.h" + +UIControl_ButtonList::UIControl_ButtonList() +{ + m_itemCount = 0; + m_iCurrentSelection = 0; +} + +bool UIControl_ButtonList::setupControl(UIScene *scene, IggyValuePath *parent, const string &controlName) +{ + UIControl::setControlType(UIControl::eButtonList); + bool success = UIControl_Base::setupControl(scene,parent,controlName); + + //SlotList specific initialisers + m_addNewItemFunc = registerFastName(L"addNewItem"); + m_removeAllItemsFunc = registerFastName(L"removeAllItems"); + m_funcHighlightItem = registerFastName(L"HighlightItem"); + m_funcRemoveItem = registerFastName(L"RemoveItem"); + m_funcSetButtonLabel = registerFastName(L"SetButtonLabel"); + m_funcSetTouchFocus = registerFastName(L"SetTouchFocus"); + m_funcCanTouchTrigger = registerFastName(L"CanTouchTrigger"); + + return success; +} + +void UIControl_ButtonList::init(int id) +{ + m_id = id; + + IggyDataValue result; + IggyDataValue value[1]; + value[0].type = IGGY_DATATYPE_number; + value[0].number = id; + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath() , m_initFunc , 1 , value ); + + #ifdef __PSVITA__ + // 4J-PB - add this buttonlist to the vita touch box list + + switch(m_parentScene->GetParentLayer()->m_iLayer) + { + case eUILayer_Fullscreen: + case eUILayer_Scene: + case eUILayer_HUD: + ui.TouchBoxAdd(this,m_parentScene); + break; +} + #endif +} + +void UIControl_ButtonList::ReInit() +{ + UIControl_Base::ReInit(); + init(m_id); + m_itemCount = 0; + m_iCurrentSelection = 0; +} + +void UIControl_ButtonList::clearList() +{ + IggyDataValue result; + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath(), m_removeAllItemsFunc , 0 , NULL ); + + m_itemCount = 0; +} + +void UIControl_ButtonList::addItem(const string &label) +{ + addItem(label, m_itemCount); +} + +void UIControl_ButtonList::addItem(const wstring &label) +{ + addItem(label, m_itemCount); +} + +void UIControl_ButtonList::addItem(const string &label, int data) +{ + IggyDataValue result; + IggyDataValue value[2]; + + IggyStringUTF8 stringVal; + stringVal.string = (char*)label.c_str(); + stringVal.length = (S32)label.length(); + value[0].type = IGGY_DATATYPE_string_UTF8; + value[0].string8 = stringVal; + + value[1].type = IGGY_DATATYPE_number; + value[1].number = data; + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath(), m_addNewItemFunc , 2 , value ); + + ++m_itemCount; +} + +void UIControl_ButtonList::addItem(const wstring &label, int data) +{ + IggyDataValue result; + IggyDataValue value[2]; + + IggyStringUTF16 stringVal; + stringVal.string = (IggyUTF16*)label.c_str(); + stringVal.length = label.length(); + value[0].type = IGGY_DATATYPE_string_UTF16; + value[0].string16 = stringVal; + + value[1].type = IGGY_DATATYPE_number; + value[1].number = data; + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath(), m_addNewItemFunc , 2 , value ); + + ++m_itemCount; +} + +void UIControl_ButtonList::removeItem(int index) +{ + IggyDataValue result; + IggyDataValue value[1]; + + value[0].type = IGGY_DATATYPE_number; + value[0].number = index; + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath(), m_funcRemoveItem , 1 , value ); + + --m_itemCount; +} + +void UIControl_ButtonList::setCurrentSelection(int iSelection) +{ + IggyDataValue result; + IggyDataValue value[1]; + + value[0].type = IGGY_DATATYPE_number; + value[0].number = iSelection; + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath(), m_funcHighlightItem , 1 , value ); +} + +int UIControl_ButtonList::getCurrentSelection() +{ + return m_iCurrentSelection; +} + +void UIControl_ButtonList::updateChildFocus(int iChild) +{ + m_iCurrentSelection = iChild; +} + +void UIControl_ButtonList::setButtonLabel(int iButtonId, const wstring &label) +{ + IggyDataValue result; + IggyDataValue value[2]; + + value[0].type = IGGY_DATATYPE_number; + value[0].number = iButtonId; + + IggyStringUTF16 stringVal; + stringVal.string = (IggyUTF16*)label.c_str(); + stringVal.length = label.length(); + value[1].type = IGGY_DATATYPE_string_UTF16; + value[1].string16 = stringVal; + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie(), &result, getIggyValuePath(), m_funcSetButtonLabel, 2 , value ); +} + +#ifdef __PSVITA__ +void UIControl_ButtonList::SetTouchFocus(S32 iX, S32 iY, bool bRepeat) +{ + IggyDataValue result; + IggyDataValue value[3]; + + value[0].type = IGGY_DATATYPE_number; + value[0].number = iX; + value[1].type = IGGY_DATATYPE_number; + value[1].number = iY; + value[2].type = IGGY_DATATYPE_boolean; + value[2].boolval = bRepeat; + + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie(), &result, getIggyValuePath(), m_funcSetTouchFocus, 3 , value ); +} + +bool UIControl_ButtonList::CanTouchTrigger(S32 iX, S32 iY) +{ + IggyDataValue result; + IggyDataValue value[2]; + + value[0].type = IGGY_DATATYPE_number; + value[0].number = iX; + value[1].type = IGGY_DATATYPE_number; + value[1].number = iY; + + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie(), &result, getIggyValuePath(), m_funcCanTouchTrigger, 2 , value ); + + S32 bCanTouchTrigger = false; + if(result.type == IGGY_DATATYPE_boolean) + { + bCanTouchTrigger = (bool)result.boolval; + } + return bCanTouchTrigger; +} +#endif diff --git a/Minecraft.Client/Common/UI/UIControl_ButtonList.h b/Minecraft.Client/Common/UI/UIControl_ButtonList.h new file mode 100644 index 00000000..a3c5da3a --- /dev/null +++ b/Minecraft.Client/Common/UI/UIControl_ButtonList.h @@ -0,0 +1,44 @@ +#pragma once + +#include "UIControl_Base.h" + +class UIControl_ButtonList : public UIControl_Base +{ +protected: + IggyName m_addNewItemFunc, m_removeAllItemsFunc, m_funcHighlightItem, m_funcRemoveItem, m_funcSetButtonLabel, m_funcSetTouchFocus, m_funcCanTouchTrigger; + + int m_itemCount; + int m_iCurrentSelection; + +public: + UIControl_ButtonList(); + + virtual bool setupControl(UIScene *scene, IggyValuePath *parent, const string &controlName); + + void init(int id); + virtual void ReInit(); + + void clearList(); + + void addItem(const wstring &label); + void addItem(const string &label); + + void addItem(const wstring &label, int data); + void addItem(const string &label, int data); + + void removeItem(int index); + + int getItemCount() { return m_itemCount; } + + void setCurrentSelection(int iSelection); + int getCurrentSelection(); + + void updateChildFocus(int iChild); + + void setButtonLabel(int iButtonId, const wstring &label); + +#ifdef __PSVITA__ + void SetTouchFocus(S32 iX, S32 iY, bool bRepeat); + bool CanTouchTrigger(S32 iX, S32 iY); +#endif +}; diff --git a/Minecraft.Client/Common/UI/UIControl_CheckBox.cpp b/Minecraft.Client/Common/UI/UIControl_CheckBox.cpp new file mode 100644 index 00000000..d3bdf758 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIControl_CheckBox.cpp @@ -0,0 +1,109 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIControl_CheckBox.h" + +UIControl_CheckBox::UIControl_CheckBox() +{ +} + +bool UIControl_CheckBox::setupControl(UIScene *scene, IggyValuePath *parent, const string &controlName) +{ + UIControl::setControlType(UIControl::eCheckBox); + bool success = UIControl_Base::setupControl(scene,parent,controlName); + + //CheckBox specific initialisers + m_checkedProp = registerFastName(L"Checked"); + m_funcEnable = registerFastName(L"EnableCheckBox"); + m_funcSetCheckBox = registerFastName(L"SetCheckBox"); + + m_bEnabled = true; + + return success; +} + +void UIControl_CheckBox::init(const wstring &label, int id, bool checked) +{ + m_label = label; + m_id = id; + m_bChecked = checked; + + IggyDataValue result; + IggyDataValue value[3]; + value[0].type = IGGY_DATATYPE_string_UTF16; + IggyStringUTF16 stringVal; + + stringVal.string = (IggyUTF16*)label.c_str(); + stringVal.length = label.length(); + value[0].string16 = stringVal; + + value[1].type = IGGY_DATATYPE_number; + value[1].number = (int)id; + + value[2].type = IGGY_DATATYPE_boolean; + value[2].boolval = checked; + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath() , m_initFunc , 3 , value ); + +#ifdef __PSVITA__ + // 4J-TomK - add checkbox to the vita touch box list + + switch(m_parentScene->GetParentLayer()->m_iLayer) + { + case eUILayer_Fullscreen: + case eUILayer_Scene: + case eUILayer_HUD: + ui.TouchBoxAdd(this,m_parentScene); + break; +} +#endif +} + +bool UIControl_CheckBox::IsChecked() +{ + rrbool checked = false; + IggyResult result = IggyValueGetBooleanRS ( &m_iggyPath , m_checkedProp, NULL, &checked ); + m_bChecked = checked; + return checked; +} + +bool UIControl_CheckBox::IsEnabled() +{ + return m_bEnabled; +} + +void UIControl_CheckBox::SetEnable(bool enable) +{ + m_bEnabled = enable; + + IggyDataValue result; + IggyDataValue value[1]; + value[0].type = IGGY_DATATYPE_boolean; + value[0].boolval = enable; + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath() , m_funcEnable , 1 , value ); +} + +// 4J HEG - this is only ever used when required, most of this should happen in the flash +void UIControl_CheckBox::setChecked(bool checked) +{ + IggyDataValue result; + IggyDataValue value[1]; + value[0].type = IGGY_DATATYPE_boolean; + value[0].boolval = checked; + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath() , m_funcSetCheckBox , 1 , value ); +} + +// 4J-TomK we need to trigger this one via function instead of key down event because of how it works +void UIControl_CheckBox::TouchSetCheckbox(bool checked) +{ + IggyDataValue result; + IggyDataValue value[1]; + value[0].type = IGGY_DATATYPE_boolean; + value[0].boolval = checked; + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath() , m_funcSetCheckBox , 1 , value ); +} + +void UIControl_CheckBox::ReInit() +{ + UIControl_Base::ReInit(); + + init(m_label, m_id, m_bChecked); +} diff --git a/Minecraft.Client/Common/UI/UIControl_CheckBox.h b/Minecraft.Client/Common/UI/UIControl_CheckBox.h new file mode 100644 index 00000000..924e9c68 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIControl_CheckBox.h @@ -0,0 +1,27 @@ +#pragma once + +#include "UIControl_Base.h" + +class UIControl_CheckBox : public UIControl_Base +{ +private: + IggyName m_checkedProp, m_funcEnable, m_funcSetCheckBox; + + bool m_bChecked, m_bEnabled; + +public: + UIControl_CheckBox(); + + virtual bool setupControl(UIScene *scene, IggyValuePath *parent, const string &controlName); + + void init(const wstring &label, int id, bool checked); + + bool IsChecked(); + bool IsEnabled(); + void SetEnable(bool enable); + void setChecked(bool checked); + void TouchSetCheckbox(bool checked); + + virtual void ReInit(); + +}; diff --git a/Minecraft.Client/Common/UI/UIControl_Cursor.cpp b/Minecraft.Client/Common/UI/UIControl_Cursor.cpp new file mode 100644 index 00000000..2ac5ce8a --- /dev/null +++ b/Minecraft.Client/Common/UI/UIControl_Cursor.cpp @@ -0,0 +1,17 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIControl_Cursor.h" + +UIControl_Cursor::UIControl_Cursor() +{ +} + +bool UIControl_Cursor::setupControl(UIScene *scene, IggyValuePath *parent, const string &controlName) +{ + UIControl::setControlType(UIControl::eCursor); + bool success = UIControl_Base::setupControl(scene,parent,controlName); + + //Label specific initialisers + + return success; +} diff --git a/Minecraft.Client/Common/UI/UIControl_Cursor.h b/Minecraft.Client/Common/UI/UIControl_Cursor.h new file mode 100644 index 00000000..cc7705d4 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIControl_Cursor.h @@ -0,0 +1,11 @@ +#pragma once + +#include "UIControl_Base.h" + +class UIControl_Cursor : public UIControl_Base +{ +public: + UIControl_Cursor(); + + virtual bool setupControl(UIScene *scene, IggyValuePath *parent, const string &controlName); +};
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIControl_DLCList.cpp b/Minecraft.Client/Common/UI/UIControl_DLCList.cpp new file mode 100644 index 00000000..35e6b08a --- /dev/null +++ b/Minecraft.Client/Common/UI/UIControl_DLCList.cpp @@ -0,0 +1,69 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIControl_DLCList.h" + +bool UIControl_DLCList::setupControl(UIScene *scene, IggyValuePath *parent, const string &controlName) +{ + UIControl::setControlType(UIControl::eDLCList); + bool success = UIControl_ButtonList::setupControl(scene,parent,controlName); + + //SlotList specific initialisers + m_funcShowTick = registerFastName(L"ShowTick"); + + return success; +} + +void UIControl_DLCList::addItem(const string &label, bool showTick, int iId) +{ + IggyDataValue result; + IggyDataValue value[3]; + + IggyStringUTF8 stringVal; + stringVal.string = (char*)label.c_str(); + stringVal.length = (S32)label.length(); + value[0].type = IGGY_DATATYPE_string_UTF8; + value[0].string8 = stringVal; + + value[1].type = IGGY_DATATYPE_number; + value[1].number = iId; + + value[2].type = IGGY_DATATYPE_boolean; + value[2].boolval = showTick; + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath(), m_addNewItemFunc , 3 , value ); + + ++m_itemCount; +} + +void UIControl_DLCList::addItem(const wstring &label, bool showTick, int iId) +{ + IggyDataValue result; + IggyDataValue value[3]; + + IggyStringUTF16 stringVal; + stringVal.string = (IggyUTF16 *)label.c_str(); + stringVal.length = (S32)label.length(); + value[0].type = IGGY_DATATYPE_string_UTF16; + value[0].string16 = stringVal; + + value[1].type = IGGY_DATATYPE_number; + value[1].number = iId; + + value[2].type = IGGY_DATATYPE_boolean; + value[2].boolval = showTick; + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath(), m_addNewItemFunc , 3 , value ); + + ++m_itemCount; +} + +void UIControl_DLCList::showTick(int iId, bool showTick) +{ + IggyDataValue result; + IggyDataValue value[2]; + + value[0].type = IGGY_DATATYPE_number; + value[0].number = iId; + + value[1].type = IGGY_DATATYPE_boolean; + value[1].boolval = showTick; + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath(), m_funcShowTick , 2 , value ); +} diff --git a/Minecraft.Client/Common/UI/UIControl_DLCList.h b/Minecraft.Client/Common/UI/UIControl_DLCList.h new file mode 100644 index 00000000..9c917cbf --- /dev/null +++ b/Minecraft.Client/Common/UI/UIControl_DLCList.h @@ -0,0 +1,17 @@ +#pragma once + +#include "UIControl_ButtonList.h" + +class UIControl_DLCList : public UIControl_ButtonList +{ +private: + IggyName m_funcShowTick; + +public: + virtual bool setupControl(UIScene *scene, IggyValuePath *parent, const string &controlName); + + using UIControl_ButtonList::addItem; + void addItem(const string &label, bool showTick, int iId); + void addItem(const wstring &label, bool showTick, int iId); + void showTick(int iId, bool showTick); +}; diff --git a/Minecraft.Client/Common/UI/UIControl_DynamicLabel.cpp b/Minecraft.Client/Common/UI/UIControl_DynamicLabel.cpp new file mode 100644 index 00000000..fa29a137 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIControl_DynamicLabel.cpp @@ -0,0 +1,98 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIControl_DynamicLabel.h" + +UIControl_DynamicLabel::UIControl_DynamicLabel() +{ +} + +bool UIControl_DynamicLabel::setupControl(UIScene *scene, IggyValuePath *parent, const string &controlName) +{ + UIControl::setControlType(UIControl::eDynamicLabel); + bool success = UIControl_Base::setupControl(scene,parent,controlName); + + //Label specific initialisers + m_funcAddText = registerFastName(L"AddText"); + m_funcTouchScroll = registerFastName(L"TouchScroll"); + m_funcGetRealWidth = registerFastName(L"GetRealWidth"); + m_funcGetRealHeight = registerFastName(L"GetRealHeight"); + + return success; +} + +void UIControl_DynamicLabel::addText(const wstring &text, bool bLastEntry) +{ + IggyDataValue result; + IggyDataValue value[2]; + + IggyStringUTF16 stringVal; + stringVal.string = (IggyUTF16*)text.c_str(); + stringVal.length = text.length(); + value[0].type = IGGY_DATATYPE_string_UTF16; + value[0].string16 = stringVal; + + value[1].type = IGGY_DATATYPE_boolean; + value[1].boolval = bLastEntry; + + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath() , m_funcAddText , 2 , value ); +} + +void UIControl_DynamicLabel::ReInit() +{ + UIControl_Base::ReInit(); +} + +void UIControl_DynamicLabel::SetupTouch() +{ + #ifdef __PSVITA__ + // 4J-TomK - add this dynamic label to the vita touch box list + + switch(m_parentScene->GetParentLayer()->m_iLayer) + { + case eUILayer_Fullscreen: + case eUILayer_Scene: + case eUILayer_HUD: + ui.TouchBoxAdd(this,m_parentScene); + break; + } + #endif +} + +void UIControl_DynamicLabel::TouchScroll(S32 iY, bool bActive) +{ + IggyDataValue result; + IggyDataValue value[2]; + + value[0].type = IGGY_DATATYPE_number; + value[0].number = iY; + value[1].type = IGGY_DATATYPE_boolean; + value[1].boolval = bActive; + + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie(), &result, getIggyValuePath(), m_funcTouchScroll, 2 , value ); +} + +S32 UIControl_DynamicLabel::GetRealWidth() +{ + IggyDataValue result; + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath() , m_funcGetRealWidth, 0 , NULL ); + + S32 iRealWidth = m_width; + if(result.type == IGGY_DATATYPE_number) + { + iRealWidth = (S32)result.number; + } + return iRealWidth; +} + +S32 UIControl_DynamicLabel::GetRealHeight() +{ + IggyDataValue result; + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath() , m_funcGetRealHeight, 0 , NULL ); + + S32 iRealHeight = m_height; + if(result.type == IGGY_DATATYPE_number) + { + iRealHeight = (S32)result.number; + } + return iRealHeight; +}
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIControl_DynamicLabel.h b/Minecraft.Client/Common/UI/UIControl_DynamicLabel.h new file mode 100644 index 00000000..902c706d --- /dev/null +++ b/Minecraft.Client/Common/UI/UIControl_DynamicLabel.h @@ -0,0 +1,25 @@ +#pragma once + +#include "UIControl_Base.h" + +class UIControl_DynamicLabel : public UIControl_Label +{ +private: + IggyName m_funcAddText, m_funcTouchScroll, m_funcGetRealWidth, m_funcGetRealHeight; + +public: + UIControl_DynamicLabel(); + + virtual bool setupControl(UIScene *scene, IggyValuePath *parent, const string &controlName); + + virtual void addText(const wstring &text, bool bLastEntry); + + virtual void ReInit(); + + virtual void SetupTouch(); + + virtual void TouchScroll(S32 iY, bool bActive); + + S32 GetRealWidth(); + S32 GetRealHeight(); +}; diff --git a/Minecraft.Client/Common/UI/UIControl_EnchantmentBook.cpp b/Minecraft.Client/Common/UI/UIControl_EnchantmentBook.cpp new file mode 100644 index 00000000..ef7c0e94 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIControl_EnchantmentBook.cpp @@ -0,0 +1,140 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIControl_EnchantmentBook.h" +#include "..\..\Minecraft.h" +#include "..\..\TileEntityRenderDispatcher.h" +#include "..\..\EnchantTableRenderer.h" +#include "..\..\Lighting.h" +#include "..\..\BookModel.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.level.tile.entity.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.inventory.h" + +UIControl_EnchantmentBook::UIControl_EnchantmentBook() +{ + UIControl::setControlType(UIControl::eEnchantmentBook); + model = NULL; + last = nullptr; + + time = 0; + flip = oFlip = flipT = flipA = 0.0f; + open = oOpen = 0.0f; +} + +void UIControl_EnchantmentBook::render(IggyCustomDrawCallbackRegion *region) +{ + glPushMatrix(); + float width = region->x1 - region->x0; + float height = region->y1 - region->y0; + + // Revert the scale from the setup + float ssX = width/m_width; + float ssY = height/m_height; + glScalef(ssX, ssY,1.0f); + + glTranslatef(m_width/2, m_height/2, 50.0f); + + // Add a uniform scale + glScalef(1/ssX, 1/ssX, 1.0f); + + glScalef(50.0f,50.0f,1.0f); + + glRotatef(45 + 90, 0, 1, 0); + Lighting::turnOn(); + glRotatef(-45 - 90, 0, 1, 0); + + //float sss = 4; + + //glTranslatef(0, 3.3f, -16); + //glScalef(sss, sss, sss); + + Minecraft *pMinecraft = Minecraft::GetInstance(); + int tex = pMinecraft->textures->loadTexture(TN_ITEM_BOOK); // 4J was L"/1_2_2/item/book.png" + pMinecraft->textures->bind(tex); + + glRotatef(20, 1, 0, 0); + + float a = 1; + float o = oOpen + (open - oOpen) * a; + glTranslatef((1 - o) * 0.2f, (1 - o) * 0.1f, (1 - o) * 0.25f); + glRotatef(-(1 - o) * 90 - 90, 0, 1, 0); + glRotatef(180, 1, 0, 0); + + float ff1 = oFlip + (flip - oFlip) * a + 0.25f; + float ff2 = oFlip + (flip - oFlip) * a + 0.75f; + ff1 = (ff1 - floor(ff1)) * 1.6f - 0.3f; + ff2 = (ff2 - floor(ff2)) * 1.6f - 0.3f; + + if (ff1 < 0) ff1 = 0; + if (ff2 < 0) ff2 = 0; + if (ff1 > 1) ff1 = 1; + if (ff2 > 1) ff2 = 1; + + glEnable(GL_CULL_FACE); + + if(model == NULL) + { + // Share the model the the EnchantTableRenderer + + EnchantTableRenderer *etr = (EnchantTableRenderer*)TileEntityRenderDispatcher::instance->getRenderer(eTYPE_ENCHANTMENTTABLEENTITY); + if(etr != NULL) + { + model = etr->bookModel; + } + else + { + model = new BookModel(); + } + } + + model->render(nullptr, 0, ff1, ff2, o, 0, 1 / 16.0f,true); + glDisable(GL_CULL_FACE); + + glPopMatrix(); + Lighting::turnOff(); + glDisable(GL_RESCALE_NORMAL); + + tickBook(); +} + +void UIControl_EnchantmentBook::tickBook() +{ + UIScene_EnchantingMenu *m_containerScene = (UIScene_EnchantingMenu *)m_parentScene; + EnchantmentMenu *menu = m_containerScene->getMenu(); + shared_ptr<ItemInstance> current = menu->getSlot(0)->getItem(); + if (!ItemInstance::matches(current, last)) + { + last = current; + + do + { + flipT += random.nextInt(4) - random.nextInt(4); + } while (flip <= flipT + 1 && flip >= flipT - 1); + } + + time++; + oFlip = flip; + oOpen = open; + + bool shouldBeOpen = false; + for (int i = 0; i < 3; i++) + { + if (menu->costs[i] != 0) + { + shouldBeOpen = true; + } + } + + if (shouldBeOpen) open += 0.2f; + else open -= 0.2f; + if (open < 0) open = 0; + if (open > 1) open = 1; + + + float diff = (flipT - flip) * 0.4f; + float max = 0.2f; + if (diff < -max) diff = -max; + if (diff > +max) diff = +max; + flipA += (diff - flipA) * 0.9f; + + flip = flip + flipA; +} diff --git a/Minecraft.Client/Common/UI/UIControl_EnchantmentBook.h b/Minecraft.Client/Common/UI/UIControl_EnchantmentBook.h new file mode 100644 index 00000000..cbe2cf2b --- /dev/null +++ b/Minecraft.Client/Common/UI/UIControl_EnchantmentBook.h @@ -0,0 +1,33 @@ +#pragma once + +#include "UIControl.h" + +class UIScene_EnchantingMenu; +class BookModel; + +class UIControl_EnchantmentBook : public UIControl +{ +private: + BookModel *model; + Random random; + + // 4J JEV: Book animation variables. + int time; + float flip, oFlip, flipT, flipA; + float open, oOpen; + + //BOOL m_bDirty; + //float m_fScale,m_fAlpha; + //int m_iPad; + shared_ptr<ItemInstance> last; + + //float m_fScreenWidth,m_fScreenHeight; + //float m_fRawWidth,m_fRawHeight; + + void tickBook(); + +public: + UIControl_EnchantmentBook(); + + void render(IggyCustomDrawCallbackRegion *region); +}; diff --git a/Minecraft.Client/Common/UI/UIControl_EnchantmentButton.cpp b/Minecraft.Client/Common/UI/UIControl_EnchantmentButton.cpp new file mode 100644 index 00000000..e1490e0b --- /dev/null +++ b/Minecraft.Client/Common/UI/UIControl_EnchantmentButton.cpp @@ -0,0 +1,205 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIControl_EnchantmentButton.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.inventory.h" +#include "..\..\Minecraft.h" +#include "..\..\MultiplayerLocalPlayer.h" +#include "..\..\..\Minecraft.World\StringHelpers.h" + +UIControl_EnchantmentButton::UIControl_EnchantmentButton() +{ + m_index = 0; + m_lastState = eState_Inactive; + m_lastCost = 0; + m_enchantmentString = L""; + m_bHasFocus = false; + + m_textColour = app.GetHTMLColour(eTextColor_Enchant); + m_textFocusColour = app.GetHTMLColour(eTextColor_EnchantFocus); + m_textDisabledColour = app.GetHTMLColour(eTextColor_EnchantDisabled); +} + +bool UIControl_EnchantmentButton::setupControl(UIScene *scene, IggyValuePath *parent, const string &controlName) +{ + UIControl::setControlType(UIControl::eEnchantmentButton); + bool success = UIControl_Button::setupControl(scene,parent,controlName); + + //Button specific initialisers + m_funcChangeState = registerFastName(L"ChangeState"); + + return success; +} + +void UIControl_EnchantmentButton::init(int index) +{ + m_index = index; +} + +void UIControl_EnchantmentButton::tick() +{ + updateState(); + UIControl_Button::tick(); +} + +void UIControl_EnchantmentButton::render(IggyCustomDrawCallbackRegion *region) +{ + UIScene_EnchantingMenu *enchantingScene = (UIScene_EnchantingMenu *)m_parentScene; + EnchantmentMenu *menu = enchantingScene->getMenu(); + + float width = region->x1 - region->x0; + float height = region->y1 - region->y0; + float xo = width/2; + float yo = height; + //glTranslatef(xo, yo, 50.0f); + + // Revert the scale from the setup + float ssX = width/m_width; + float ssY = height/m_height; + glScalef(ssX, ssY,1.0f); + + float ss = 1.0f; + +#if TO_BE_IMPLEMENTED + if(!enchantingScene->m_bSplitscreen) +#endif + { + switch(enchantingScene->getSceneResolution()) + { + case UIScene::eSceneResolution_1080: + ss = 3.0f; + break; + default: + ss = 2.0f; + break; + } + } + + glScalef(ss, ss, ss); + + int cost = menu->costs[m_index]; + + //if(cost != m_lastCost) + //{ + // updateState(); + //} + + glColor4f(1, 1, 1, 1); + if (cost != 0) + { + glEnable(GL_ALPHA_TEST); + glAlphaFunc(GL_GREATER, 0.1f); + Minecraft *pMinecraft = Minecraft::GetInstance(); + wstring line = _toString<int>(cost); + Font *font = pMinecraft->altFont; + //int col = 0x685E4A; + unsigned int col = m_textColour; + if (pMinecraft->localplayers[enchantingScene->getPad()]->experienceLevel < cost && !pMinecraft->localplayers[enchantingScene->getPad()]->abilities.instabuild) + { + col = m_textDisabledColour; + font->drawWordWrap(m_enchantmentString, 0, 0, (float)m_width/ss, col, (float)m_height/ss); + font = pMinecraft->font; + //col = (0x80ff20 & 0xfefefe) >> 1; + //font->drawShadow(line, (bwidth - font->width(line))/ss, 7, col); + } + else + { + if (m_bHasFocus) + { + //col = 0xffff80; + col = m_textFocusColour; + } + font->drawWordWrap(m_enchantmentString, 0, 0, (float)m_width/ss, col, (float)m_height/ss); + font = pMinecraft->font; + //col = 0x80ff20; + //font->drawShadow(line, (bwidth - font->width(line))/ss, 7, col); + } + glDisable(GL_ALPHA_TEST); + } + else + { + } + + //Lighting::turnOff(); + glDisable(GL_RESCALE_NORMAL); +} + +void UIControl_EnchantmentButton::updateState() +{ + UIScene_EnchantingMenu *enchantingScene = (UIScene_EnchantingMenu *)m_parentScene; + EnchantmentMenu *menu = enchantingScene->getMenu(); + + EState state = eState_Inactive; + + int cost = menu->costs[m_index]; + + Minecraft *pMinecraft = Minecraft::GetInstance(); + if(cost > pMinecraft->localplayers[enchantingScene->getPad()]->experienceLevel && !pMinecraft->localplayers[enchantingScene->getPad()]->abilities.instabuild) + { + // Dark background + state = eState_Inactive; + } + else + { + // Light background and focus background + if(m_bHasFocus) + { + state = eState_Selected; + } + else + { + state = eState_Active; + } + } + + if(cost != m_lastCost) + { + setLabel( _toString<int>(cost) ); + m_lastCost = cost; + m_enchantmentString = EnchantmentNames::instance.getRandomName(); + } + if(cost == 0) + { + // Dark background + state = eState_Inactive; + setLabel(L""); + } + + if(state != m_lastState) + { + IggyDataValue result; + IggyDataValue value[1]; + + value[0].type = IGGY_DATATYPE_number; + value[0].number = (int)state; + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath() , m_funcChangeState , 1 , value ); + + if(out == IGGY_RESULT_SUCCESS) m_lastState = state; + } +} + +void UIControl_EnchantmentButton::setFocus(bool focus) +{ + m_bHasFocus = focus; + updateState(); +} + +UIControl_EnchantmentButton::EnchantmentNames UIControl_EnchantmentButton::EnchantmentNames::instance; + +UIControl_EnchantmentButton::EnchantmentNames::EnchantmentNames() +{ + wstring allWords = L"the elder scrolls klaatu berata niktu xyzzy bless curse light darkness fire air earth water hot dry cold wet ignite snuff embiggen twist shorten stretch fiddle destroy imbue galvanize enchant free limited range of towards inside sphere cube self other ball mental physical grow shrink demon elemental spirit animal creature beast humanoid undead fresh stale "; + std::wistringstream iss(allWords); + std::copy(std::istream_iterator< std::wstring, wchar_t, std::char_traits<wchar_t> >(iss), std::istream_iterator< std::wstring, wchar_t, std::char_traits<wchar_t> >(),std::back_inserter(words)); +} + +wstring UIControl_EnchantmentButton::EnchantmentNames::getRandomName() +{ + int wordCount = random.nextInt(2) + 3; + wstring word = L""; + for (int i = 0; i < wordCount; i++) + { + if (i > 0) word += L" "; + word += words[random.nextInt(words.size())]; + } + return word; +} diff --git a/Minecraft.Client/Common/UI/UIControl_EnchantmentButton.h b/Minecraft.Client/Common/UI/UIControl_EnchantmentButton.h new file mode 100644 index 00000000..9b8a3c8f --- /dev/null +++ b/Minecraft.Client/Common/UI/UIControl_EnchantmentButton.h @@ -0,0 +1,55 @@ +#pragma once + +#include "UIControl_Button.h" + +class UIControl_EnchantmentButton : public UIControl_Button +{ +private: + // Maps to values in AS + enum EState + { + eState_Inactive = 0, + eState_Active = 1, + eState_Selected = 2, + }; + + EState m_lastState; + int m_lastCost; + int m_index; + wstring m_enchantmentString; + bool m_bHasFocus; + + IggyName m_funcChangeState; + + unsigned int m_textColour, m_textFocusColour, m_textDisabledColour; + + class EnchantmentNames + { + public: + static EnchantmentNames instance; + + private: + Random random; + vector<wstring> words; + + EnchantmentNames(); + + public: + wstring getRandomName(); + }; + +public: + UIControl_EnchantmentButton(); + + virtual bool setupControl(UIScene *scene, IggyValuePath *parent, const string &controlName); + + virtual void tick(); + + void init(int index); + + void render(IggyCustomDrawCallbackRegion *region); + + void updateState(); + + virtual void setFocus(bool focus); +};
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIControl_HTMLLabel.cpp b/Minecraft.Client/Common/UI/UIControl_HTMLLabel.cpp new file mode 100644 index 00000000..8b7eb9a1 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIControl_HTMLLabel.cpp @@ -0,0 +1,103 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIControl_HTMLLabel.h" + +UIControl_HTMLLabel::UIControl_HTMLLabel() +{ +} + +bool UIControl_HTMLLabel::setupControl(UIScene *scene, IggyValuePath *parent, const string &controlName) +{ + UIControl::setControlType(UIControl::eHTMLLabel); + bool success = UIControl_Base::setupControl(scene,parent,controlName); + + //Label specific initialisers + m_funcStartAutoScroll = registerFastName(L"StartAutoScroll"); + m_funcTouchScroll = registerFastName(L"TouchScroll"); + m_funcGetRealWidth = registerFastName(L"GetRealWidth"); + m_funcGetRealHeight = registerFastName(L"GetRealHeight"); + + return success; +} + +void UIControl_HTMLLabel::startAutoScroll() +{ + IggyDataValue result; + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath() , m_funcStartAutoScroll , 0 , NULL ); +} + +void UIControl_HTMLLabel::ReInit() +{ + UIControl_Base::ReInit(); + // Don't set the label, HTML sizes will have changed. Let the scene update us. + init(L""); +} + +void UIControl_HTMLLabel::setLabel(const string &label) +{ + IggyDataValue result; + IggyDataValue value[1]; + value[0].type = IGGY_DATATYPE_string_UTF8; + IggyStringUTF8 stringVal; + + stringVal.string = (char *) label.c_str(); + stringVal.length = label.length(); + value[0].string8 = stringVal; + + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath() , m_setLabelFunc , 1 , value ); +} + +void UIControl_HTMLLabel::SetupTouch() +{ + #ifdef __PSVITA__ + // 4J-TomK - add this dynamic label to the vita touch box list + + switch(m_parentScene->GetParentLayer()->m_iLayer) + { + case eUILayer_Fullscreen: + case eUILayer_Scene: + case eUILayer_HUD: + ui.TouchBoxAdd(this,m_parentScene); + break; + } + #endif +} + +void UIControl_HTMLLabel::TouchScroll(S32 iY, bool bActive) +{ + IggyDataValue result; + IggyDataValue value[2]; + + value[0].type = IGGY_DATATYPE_number; + value[0].number = iY; + value[1].type = IGGY_DATATYPE_boolean; + value[1].boolval = bActive; + + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie(), &result, getIggyValuePath(), m_funcTouchScroll, 2 , value ); +} + +S32 UIControl_HTMLLabel::GetRealWidth() +{ + IggyDataValue result; + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath() , m_funcGetRealWidth, 0 , NULL ); + + S32 iRealWidth = m_width; + if(result.type == IGGY_DATATYPE_number) + { + iRealWidth = (S32)result.number; + } + return iRealWidth; +} + +S32 UIControl_HTMLLabel::GetRealHeight() +{ + IggyDataValue result; + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath() , m_funcGetRealHeight, 0 , NULL ); + + S32 iRealHeight = m_height; + if(result.type == IGGY_DATATYPE_number) + { + iRealHeight = (S32)result.number; + } + return iRealHeight; +}
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIControl_HTMLLabel.h b/Minecraft.Client/Common/UI/UIControl_HTMLLabel.h new file mode 100644 index 00000000..17e7cfb4 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIControl_HTMLLabel.h @@ -0,0 +1,27 @@ +#pragma once + +#include "UIControl_Base.h" + +class UIControl_HTMLLabel : public UIControl_Label +{ +private: + IggyName m_funcStartAutoScroll, m_funcTouchScroll, m_funcGetRealWidth, m_funcGetRealHeight; + +public: + UIControl_HTMLLabel(); + + virtual bool setupControl(UIScene *scene, IggyValuePath *parent, const string &controlName); + + void startAutoScroll(); + virtual void ReInit(); + + using UIControl_Base::setLabel; + void setLabel(const string &label); + + virtual void SetupTouch(); + + virtual void TouchScroll(S32 iY, bool bActive); + + S32 GetRealWidth(); + S32 GetRealHeight(); +};
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIControl_Label.cpp b/Minecraft.Client/Common/UI/UIControl_Label.cpp new file mode 100644 index 00000000..1481fea1 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIControl_Label.cpp @@ -0,0 +1,53 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIControl_Label.h" +#include "..\..\..\Minecraft.World\StringHelpers.h" + +UIControl_Label::UIControl_Label() +{ +} + +bool UIControl_Label::setupControl(UIScene *scene, IggyValuePath *parent, const string &controlName) +{ + UIControl::setControlType(UIControl::eLabel); + bool success = UIControl_Base::setupControl(scene,parent,controlName); + + //Label specific initialisers + + return success; +} + +void UIControl_Label::init(const wstring &label) +{ + m_label = label; + + IggyDataValue result; + IggyDataValue value[1]; + value[0].type = IGGY_DATATYPE_string_UTF16; + IggyStringUTF16 stringVal; + + stringVal.string = (IggyUTF16*)label.c_str(); + stringVal.length = label.length(); + value[0].string16 = stringVal; + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath() , m_initFunc , 1 , value ); +} + +void UIControl_Label::init(const string &label) +{ + m_label = convStringToWstring(label); + IggyDataValue result; + IggyDataValue value[1]; + value[0].type = IGGY_DATATYPE_string_UTF8; + IggyStringUTF8 stringVal; + + stringVal.string = (char *)label.c_str(); + stringVal.length = label.length(); + value[0].string8 = stringVal; + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath() , m_initFunc , 1 , value ); +} + +void UIControl_Label::ReInit() +{ + UIControl_Base::ReInit(); + init(m_label); +} diff --git a/Minecraft.Client/Common/UI/UIControl_Label.h b/Minecraft.Client/Common/UI/UIControl_Label.h new file mode 100644 index 00000000..aa0f3f14 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIControl_Label.h @@ -0,0 +1,15 @@ +#pragma once + +#include "UIControl_Base.h" + +class UIControl_Label : public UIControl_Base +{ +public: + UIControl_Label(); + + virtual bool setupControl(UIScene *scene, IggyValuePath *parent, const string &controlName); + + void init(const wstring &label); + void init(const string &label); + virtual void ReInit(); +};
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIControl_LeaderboardList.cpp b/Minecraft.Client/Common/UI/UIControl_LeaderboardList.cpp new file mode 100644 index 00000000..c34b5e87 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIControl_LeaderboardList.cpp @@ -0,0 +1,238 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIControl_LeaderboardList.h" + +UIControl_LeaderboardList::UIControl_LeaderboardList() +{ +} + +bool UIControl_LeaderboardList::setupControl(UIScene *scene, IggyValuePath *parent, const string &controlName) +{ + UIControl::setControlType(UIControl::eLeaderboardList); + bool success = UIControl_Base::setupControl(scene,parent,controlName); + + //UIControl_LeaderboardList specific initialisers + m_funcInitLeaderboard = registerFastName(L"InitLeaderboard"); + m_funcAddDataSet = registerFastName(L"AddDataSet"); + m_funcResetLeaderboard = registerFastName(L"ResetLeaderboard"); + m_funcSetupTitles = registerFastName(L"SetupTitles"); + m_funcSetColumnIcon = registerFastName(L"SetColumnIcon"); +#ifdef __PSVITA__ + m_funcSetTouchFocus = registerFastName(L"SetTouchFocus"); + m_bTouchInitialised = false; +#endif + + return success; +} + +void UIControl_LeaderboardList::init(int id) +{ + m_id = id; + + IggyDataValue result; + IggyDataValue value[1]; + value[0].type = IGGY_DATATYPE_number; + value[0].number = id; + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath() , m_initFunc , 1 , value ); +} + +void UIControl_LeaderboardList::ReInit() +{ + UIControl_Base::ReInit(); + init(m_id); +} + +void UIControl_LeaderboardList::clearList() +{ + IggyDataValue result; + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath(), m_funcResetLeaderboard , 0 , NULL ); +} + +void UIControl_LeaderboardList::setupTitles(const wstring &rank, const wstring &gamertag) +{ + IggyDataValue result; + IggyDataValue value[2]; + + IggyStringUTF16 stringVal0; + stringVal0.string = (IggyUTF16*)rank.c_str(); + stringVal0.length = rank.length(); + value[0].type = IGGY_DATATYPE_string_UTF16; + value[0].string16 = stringVal0; + + IggyStringUTF16 stringVal1; + stringVal1.string = (IggyUTF16*)gamertag.c_str(); + stringVal1.length = gamertag.length(); + value[1].type = IGGY_DATATYPE_string_UTF16; + value[1].string16 = stringVal1; + + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath(), m_funcSetupTitles , 2 , value ); +} + +void UIControl_LeaderboardList::initLeaderboard(int iFirstFocus, int iTotalEntries, int iNumColumns) +{ + IggyDataValue result; + IggyDataValue value[3]; + value[0].type = IGGY_DATATYPE_number; + value[0].number = iFirstFocus; + + value[1].type = IGGY_DATATYPE_number; + value[1].number = iTotalEntries; + + value[2].type = IGGY_DATATYPE_number; + value[2].number = iNumColumns; + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath(), m_funcInitLeaderboard , 3 , value ); + +#ifdef __PSVITA__ + // 4J-PB - add this button to the vita touch box list + if(!m_bTouchInitialised) + { + switch(m_parentScene->GetParentLayer()->m_iLayer) + { + case eUILayer_Fullscreen: + case eUILayer_Scene: + ui.TouchBoxAdd(this,m_parentScene); + break; + } + m_bTouchInitialised = true; + } +#endif +} + +void UIControl_LeaderboardList::setColumnIcon(int iColumn, int iType) +{ + IggyDataValue result; + IggyDataValue value[2]; + value[0].type = IGGY_DATATYPE_number; + value[0].number = iColumn; + + value[1].type = IGGY_DATATYPE_number; + value[1].number = (iType<=32000)?0:(iType-32000); + + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath(), m_funcSetColumnIcon , 2 , value ); +} + +void UIControl_LeaderboardList::addDataSet(bool bLast, int iId, int iRank, const wstring &gamertag, bool bDisplayMessage, const wstring &col0, const wstring &col1, const wstring &col2, const wstring &col3, const wstring &col4, const wstring &col5, const wstring &col6) +{ + IggyDataValue result; + IggyDataValue value[12]; + + value[0].type = IGGY_DATATYPE_boolean; + value[0].boolval = bLast; + + value[1].type = IGGY_DATATYPE_number; + value[1].number = iId; + + value[2].type = IGGY_DATATYPE_number; + value[2].number = iRank; + + IggyStringUTF16 stringVal0; + stringVal0.string = (IggyUTF16*)gamertag.c_str(); + stringVal0.length = gamertag.length(); + value[3].type = IGGY_DATATYPE_string_UTF16; + value[3].string16 = stringVal0; + + value[4].type = IGGY_DATATYPE_boolean; + value[4].boolval = bDisplayMessage; + + IggyStringUTF16 stringVal1; + stringVal1.string = (IggyUTF16*)col0.c_str(); + stringVal1.length = col0.length(); + value[5].type = IGGY_DATATYPE_string_UTF16; + value[5].string16 = stringVal1; + + if(col1.empty()) + { + value[6].type = IGGY_DATATYPE_null; + } + else + { + IggyStringUTF16 stringVal2; + stringVal2.string = (IggyUTF16*)col1.c_str(); + stringVal2.length = col1.length(); + value[6].type = IGGY_DATATYPE_string_UTF16; + value[6].string16 = stringVal2; + } + + if(col2.empty()) + { + value[7].type = IGGY_DATATYPE_null; + } + else + { + IggyStringUTF16 stringVal3; + stringVal3.string = (IggyUTF16*)col2.c_str(); + stringVal3.length = col2.length(); + value[7].type = IGGY_DATATYPE_string_UTF16; + value[7].string16 = stringVal3; + } + + if(col3.empty()) + { + value[8].type = IGGY_DATATYPE_null; + } + else + { + IggyStringUTF16 stringVal4; + stringVal4.string = (IggyUTF16*)col3.c_str(); + stringVal4.length = col3.length(); + value[8].type = IGGY_DATATYPE_string_UTF16; + value[8].string16 = stringVal4; + } + + if(col4.empty()) + { + value[9].type = IGGY_DATATYPE_null; + } + else + { + IggyStringUTF16 stringVal5; + stringVal5.string = (IggyUTF16*)col4.c_str(); + stringVal5.length = col4.length(); + value[9].type = IGGY_DATATYPE_string_UTF16; + value[9].string16 = stringVal5; + } + + if(col5.empty()) + { + value[10].type = IGGY_DATATYPE_null; + } + else + { + IggyStringUTF16 stringVal6; + stringVal6.string = (IggyUTF16*)col5.c_str(); + stringVal6.length = col5.length(); + value[10].type = IGGY_DATATYPE_string_UTF16; + value[10].string16 = stringVal6; + } + + if(col6.empty()) + { + value[11].type = IGGY_DATATYPE_null; + } + else + { + IggyStringUTF16 stringVal7; + stringVal7.string = (IggyUTF16*)col6.c_str(); + stringVal7.length = col6.length(); + value[11].type = IGGY_DATATYPE_string_UTF16; + value[11].string16 = stringVal7; + } + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath(), m_funcAddDataSet , 12 , value ); +} + +#ifdef __PSVITA__ +void UIControl_LeaderboardList::SetTouchFocus(S32 iX, S32 iY, bool bRepeat) +{ + IggyDataValue result; + IggyDataValue value[3]; + + value[0].type = IGGY_DATATYPE_number; + value[0].number = iX; + value[1].type = IGGY_DATATYPE_number; + value[1].number = iY; + value[2].type = IGGY_DATATYPE_boolean; + value[2].boolval = bRepeat; + + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie(), &result, getIggyValuePath(), m_funcSetTouchFocus, 3 , value ); +} +#endif
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIControl_LeaderboardList.h b/Minecraft.Client/Common/UI/UIControl_LeaderboardList.h new file mode 100644 index 00000000..e102ddd7 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIControl_LeaderboardList.h @@ -0,0 +1,50 @@ +#pragma once + +#include "UIControl_Base.h" + +class UIControl_LeaderboardList : public UIControl_Base +{ +private: + IggyName m_funcInitLeaderboard, m_funcAddDataSet; + IggyName m_funcResetLeaderboard; + IggyName m_funcSetupTitles, m_funcSetColumnIcon; +#ifdef __PSVITA__ + IggyName m_funcSetTouchFocus; + bool m_bTouchInitialised; +#endif +public: + enum ELeaderboardIcons + { + e_ICON_TYPE_IGGY = 0, + e_ICON_TYPE_CLIMBED = 32001, + e_ICON_TYPE_FALLEN = 32002, + e_ICON_TYPE_WALKED = 32003, + e_ICON_TYPE_SWAM = 32004, + e_ICON_TYPE_ZOMBIE = 32005, + e_ICON_TYPE_ZOMBIEPIGMAN = 32006, + e_ICON_TYPE_GHAST = 32007, + e_ICON_TYPE_CREEPER = 32008, + e_ICON_TYPE_SKELETON = 32009, + e_ICON_TYPE_SPIDER = 32010, + e_ICON_TYPE_SPIDERJOKEY = 32011, + e_ICON_TYPE_SLIME = 32012, + e_ICON_TYPE_PORTAL = 32013, + }; + UIControl_LeaderboardList(); + + virtual bool setupControl(UIScene *scene, IggyValuePath *parent, const string &controlName); + + void init(int id); + virtual void ReInit(); + + void clearList(); + + void setupTitles(const wstring &rank, const wstring &gamertag); + void initLeaderboard(int iFirstFocus, int iTotalEntries, int iNumColumns); + void setColumnIcon(int iColumn, int iType); + void addDataSet(bool bLast, int iId, int iRank, const wstring &gamertag, bool bDisplayMessage, const wstring &col0, const wstring &col1, const wstring &col2, const wstring &col3, const wstring &col4, const wstring &col5, const wstring &col6); + +#ifdef __PSVITA__ + void SetTouchFocus(S32 iX, S32 iY, bool bRepeat); +#endif +};
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIControl_MinecraftPlayer.cpp b/Minecraft.Client/Common/UI/UIControl_MinecraftPlayer.cpp new file mode 100644 index 00000000..3a18ed53 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIControl_MinecraftPlayer.cpp @@ -0,0 +1,93 @@ +#include "stdafx.h" +#include "..\..\Minecraft.h" +#include "..\..\ScreenSizeCalculator.h" +#include "..\..\EntityRenderDispatcher.h" +#include "..\..\PlayerRenderer.h" +#include "..\..\HumanoidModel.h" +#include "..\..\Lighting.h" +#include "..\..\ModelPart.h" +#include "..\..\Options.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.entity.player.h" +#include "..\..\MultiplayerLocalPlayer.h" +#include "UI.h" +#include "UIControl_MinecraftPlayer.h" + +UIControl_MinecraftPlayer::UIControl_MinecraftPlayer() +{ + UIControl::setControlType(UIControl::eMinecraftPlayer); + + Minecraft *pMinecraft=Minecraft::GetInstance(); + + ScreenSizeCalculator ssc(pMinecraft->options, pMinecraft->width_phys, pMinecraft->height_phys); + m_fScreenWidth=(float)pMinecraft->width_phys; + m_fRawWidth=(float)ssc.rawWidth; + m_fScreenHeight=(float)pMinecraft->height_phys; + m_fRawHeight=(float)ssc.rawHeight; +} + +void UIControl_MinecraftPlayer::render(IggyCustomDrawCallbackRegion *region) +{ + Minecraft *pMinecraft = Minecraft::GetInstance(); + glEnable(GL_RESCALE_NORMAL); + glEnable(GL_COLOR_MATERIAL); + glPushMatrix(); + + float width = region->x1 - region->x0; + float height = region->y1 - region->y0; + float xo = width/2; + float yo = height; + + glTranslatef(xo, yo - 7.0f, 50.0f); + + float ss; + + // Base scale on height of this control + // Potentially we might want separate x & y scales here + ss = width / (m_fScreenWidth / m_fScreenHeight); + + glScalef(-ss, ss, ss); + glRotatef(180, 0, 0, 1); + + UIScene_InventoryMenu *containerMenu = (UIScene_InventoryMenu *)m_parentScene; + + float oybr = pMinecraft->localplayers[containerMenu->getPad()]->yBodyRot; + float oyr = pMinecraft->localplayers[containerMenu->getPad()]->yRot; + float oxr = pMinecraft->localplayers[containerMenu->getPad()]->xRot; + float oyhr = pMinecraft->localplayers[containerMenu->getPad()]->yHeadRot; + + //float xd = ( matrix._41 + ( (bwidth*matrix._11)/2) ) - m_pointerPos.x; + float xd = (m_x + m_width/2) - containerMenu->m_pointerPos.x; + + // Need to base Y on head position, not centre of mass + //float yd = ( matrix._42 + ( (bheight*matrix._22) / 2) - 40 ) - m_pointerPos.y; + float yd = (m_y + m_height/2 - 40) - containerMenu->m_pointerPos.y; + + glRotatef(45 + 90, 0, 1, 0); + Lighting::turnOn(); + glRotatef(-45 - 90, 0, 1, 0); + + glRotatef(-(float) atan(yd / 40.0f) * 20, 1, 0, 0); + + pMinecraft->localplayers[containerMenu->getPad()]->yBodyRot = (float) atan(xd / 40.0f) * 20; + pMinecraft->localplayers[containerMenu->getPad()]->yRot = (float) atan(xd / 40.0f) * 40; + pMinecraft->localplayers[containerMenu->getPad()]->xRot = -(float) atan(yd / 40.0f) * 20; + pMinecraft->localplayers[containerMenu->getPad()]->yHeadRot = pMinecraft->localplayers[containerMenu->getPad()]->yRot; + //pMinecraft->localplayers[m_iPad]->glow = 1; + glTranslatef(0, pMinecraft->localplayers[containerMenu->getPad()]->heightOffset, 0); + EntityRenderDispatcher::instance->playerRotY = 180; + + // 4J Stu - Turning on hideGui while we do this stops the name rendering in split-screen + bool wasHidingGui = pMinecraft->options->hideGui; + pMinecraft->options->hideGui = true; + EntityRenderDispatcher::instance->render(pMinecraft->localplayers[containerMenu->getPad()], 0, 0, 0, 0, 1, false, false); + pMinecraft->options->hideGui = wasHidingGui; + //pMinecraft->localplayers[m_iPad]->glow = 0; + + pMinecraft->localplayers[containerMenu->getPad()]->yBodyRot = oybr; + pMinecraft->localplayers[containerMenu->getPad()]->yRot = oyr; + pMinecraft->localplayers[containerMenu->getPad()]->xRot = oxr; + pMinecraft->localplayers[containerMenu->getPad()]->yHeadRot = oyhr; + glPopMatrix(); + Lighting::turnOff(); + glDisable(GL_RESCALE_NORMAL); +} diff --git a/Minecraft.Client/Common/UI/UIControl_MinecraftPlayer.h b/Minecraft.Client/Common/UI/UIControl_MinecraftPlayer.h new file mode 100644 index 00000000..3b032f76 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIControl_MinecraftPlayer.h @@ -0,0 +1,15 @@ +#pragma once + +#include "UIControl.h" + +class UIControl_MinecraftPlayer : public UIControl +{ +private: + float m_fScreenWidth,m_fScreenHeight; + float m_fRawWidth,m_fRawHeight; + +public: + UIControl_MinecraftPlayer(); + + void render(IggyCustomDrawCallbackRegion *region); +};
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIControl_PlayerList.cpp b/Minecraft.Client/Common/UI/UIControl_PlayerList.cpp new file mode 100644 index 00000000..41534dc2 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIControl_PlayerList.cpp @@ -0,0 +1,65 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIControl_PlayerList.h" + +bool UIControl_PlayerList::setupControl(UIScene *scene, IggyValuePath *parent, const string &controlName) +{ + UIControl::setControlType(UIControl::ePlayerList); + bool success = UIControl_ButtonList::setupControl(scene,parent,controlName); + + //SlotList specific initialisers + m_funcSetPlayerIcon = registerFastName(L"SetPlayerIcon"); + m_funcSetVOIPIcon = registerFastName(L"SetVOIPIcon"); + + return success; +} + +void UIControl_PlayerList::addItem(const wstring &label, int iPlayerIcon, int iVOIPIcon) +{ + IggyDataValue result; + IggyDataValue value[4]; + + IggyStringUTF16 stringVal; + stringVal.string = (IggyUTF16*)label.c_str(); + stringVal.length = (S32)label.length(); + value[0].type = IGGY_DATATYPE_string_UTF16; + value[0].string16 = stringVal; + + value[1].type = IGGY_DATATYPE_number; + value[1].number = m_itemCount; + + value[2].type = IGGY_DATATYPE_number; + value[2].number = iPlayerIcon + 1; + + value[3].type = IGGY_DATATYPE_number; + value[3].number = iVOIPIcon + 1; + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath(), m_addNewItemFunc , 4 , value ); + + ++m_itemCount; +} + +void UIControl_PlayerList::setPlayerIcon(int iId, int iPlayerIcon) +{ + IggyDataValue result; + IggyDataValue value[2]; + + value[0].type = IGGY_DATATYPE_number; + value[0].number = iId; + + value[1].type = IGGY_DATATYPE_number; + value[1].number = iPlayerIcon + 1; + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath(), m_funcSetPlayerIcon , 2 , value ); +} + +void UIControl_PlayerList::setVOIPIcon(int iId, int iVOIPIcon) +{ + IggyDataValue result; + IggyDataValue value[2]; + + value[0].type = IGGY_DATATYPE_number; + value[0].number = iId; + + value[1].type = IGGY_DATATYPE_number; + value[1].number = iVOIPIcon + 1; + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath(), m_funcSetVOIPIcon , 2 , value ); +} diff --git a/Minecraft.Client/Common/UI/UIControl_PlayerList.h b/Minecraft.Client/Common/UI/UIControl_PlayerList.h new file mode 100644 index 00000000..8647d950 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIControl_PlayerList.h @@ -0,0 +1,17 @@ +#pragma once + +#include "UIControl_ButtonList.h" + +class UIControl_PlayerList : public UIControl_ButtonList +{ +private: + IggyName m_funcSetPlayerIcon, m_funcSetVOIPIcon; + +public: + virtual bool setupControl(UIScene *scene, IggyValuePath *parent, const string &controlName); + + using UIControl_ButtonList::addItem; + void addItem(const wstring &label, int iPlayerIcon, int iVOIPIcon); + void setPlayerIcon(int iId, int iPlayerIcon); + void setVOIPIcon(int iId, int iVOIPIcon); +};
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIControl_PlayerSkinPreview.cpp b/Minecraft.Client/Common/UI/UIControl_PlayerSkinPreview.cpp new file mode 100644 index 00000000..544b4da1 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIControl_PlayerSkinPreview.cpp @@ -0,0 +1,514 @@ +#include "stdafx.h" +#include "..\..\Minecraft.h" +#include "..\..\ScreenSizeCalculator.h" +#include "..\..\EntityRenderDispatcher.h" +#include "..\..\PlayerRenderer.h" +#include "..\..\HumanoidModel.h" +#include "..\..\Lighting.h" +#include "..\..\ModelPart.h" +#include "..\..\Options.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.entity.player.h" +#include "UIControl_PlayerSkinPreview.h" + +//#define SKIN_PREVIEW_BOB_ANIM +#define SKIN_PREVIEW_WALKING_ANIM + +UIControl_PlayerSkinPreview::UIControl_PlayerSkinPreview() +{ + UIControl::setControlType(UIControl::ePlayerSkinPreview); + m_bDirty = FALSE; + m_fScale = 1.0f; + m_fAlpha = 1.0f; + + Minecraft *pMinecraft=Minecraft::GetInstance(); + + ScreenSizeCalculator ssc(pMinecraft->options, pMinecraft->width_phys, pMinecraft->height_phys); + m_fScreenWidth=(float)pMinecraft->width_phys; + m_fRawWidth=(float)ssc.rawWidth; + m_fScreenHeight=(float)pMinecraft->height_phys; + m_fRawHeight=(float)ssc.rawHeight; + + m_customTextureUrl = L"default"; + m_backupTexture = TN_MOB_CHAR; + m_capeTextureUrl = L""; + + m_yRot = 0; + m_xRot = 0; + + m_swingTime = 0.0f; + m_bobTick = 0.0f; + m_walkAnimSpeedO = 0.0f; + m_walkAnimSpeed = 0.0f; + m_walkAnimPos = 0.0f; + + m_bAutoRotate = false; + m_bRotatingLeft = false; + + m_incXRot = false; + m_decXRot = false; + m_incYRot = false; + m_decYRot = false; + + m_currentAnimation = e_SkinPreviewAnimation_Walking; + + m_fTargetRotation = 0.0f; + m_fOriginalRotation = 0.0f; + m_framesAnimatingRotation = 0; + m_bAnimatingToFacing = false; + m_pvAdditionalModelParts=NULL; + m_uiAnimOverrideBitmask=0L; +} + +void UIControl_PlayerSkinPreview::tick() +{ + UIControl::tick(); + + if( m_bAnimatingToFacing ) + { + ++m_framesAnimatingRotation; + m_yRot = m_fOriginalRotation + m_framesAnimatingRotation * ( (m_fTargetRotation - m_fOriginalRotation) / CHANGING_SKIN_FRAMES ); + + //if(m_framesAnimatingRotation == CHANGING_SKIN_FRAMES) m_bAnimatingToFacing = false; + } + else + { + if( m_incXRot ) IncrementXRotation(); + if( m_decXRot ) DecrementXRotation(); + if( m_incYRot ) IncrementYRotation(); + if( m_decYRot ) DecrementYRotation(); + + if(m_bAutoRotate) + { + ++m_rotateTick; + + if(m_rotateTick%4==0) + { + if(m_yRot >= LOOK_LEFT_EXTENT) + { + m_bRotatingLeft = false; + } + else if(m_yRot <= LOOK_RIGHT_EXTENT) + { + m_bRotatingLeft = true; + } + + if(m_bRotatingLeft) + { + IncrementYRotation(); + } + else + { + DecrementYRotation(); + } + } + } + } +} + +void UIControl_PlayerSkinPreview::SetTexture(const wstring &url, TEXTURE_NAME backupTexture) +{ + m_customTextureUrl = url; + m_backupTexture = backupTexture; + + unsigned int uiAnimOverrideBitmask = Player::getSkinAnimOverrideBitmask( app.getSkinIdFromPath(m_customTextureUrl) ); + + if(app.GetGameSettings(eGameSetting_CustomSkinAnim)==0 ) + { + // We have a force animation for some skins (claptrap) + // 4J-PB - treat all the eAnim_Disable flags as a force anim + + if((uiAnimOverrideBitmask & HumanoidModel::m_staticBitmaskIgnorePlayerCustomAnimSetting)!=0) + { + m_uiAnimOverrideBitmask=uiAnimOverrideBitmask; + } + else + { + m_uiAnimOverrideBitmask=0; + } + } + else + { + m_uiAnimOverrideBitmask = uiAnimOverrideBitmask; + } + + m_pvAdditionalModelParts=app.GetAdditionalModelParts(app.getSkinIdFromPath(m_customTextureUrl)); +} + +void UIControl_PlayerSkinPreview::SetFacing(ESkinPreviewFacing facing, bool bAnimate /*= false*/) +{ + switch(facing) + { + case e_SkinPreviewFacing_Forward: + m_fTargetRotation = 0; + m_bRotatingLeft = true; + break; + case e_SkinPreviewFacing_Left: + m_fTargetRotation = LOOK_LEFT_EXTENT; + m_bRotatingLeft = false; + break; + case e_SkinPreviewFacing_Right: + m_fTargetRotation = LOOK_RIGHT_EXTENT; + m_bRotatingLeft = true; + break; + } + + if(!bAnimate) + { + m_yRot = m_fTargetRotation; + m_bAnimatingToFacing = false; + } + else + { + m_fOriginalRotation = m_yRot; + m_bAnimatingToFacing = true; + m_framesAnimatingRotation = 0; + } +} + +void UIControl_PlayerSkinPreview::CycleNextAnimation() +{ + m_currentAnimation = (ESkinPreviewAnimations)(m_currentAnimation + 1); + if(m_currentAnimation >= e_SkinPreviewAnimation_Count) m_currentAnimation = e_SkinPreviewAnimation_Walking; + + m_swingTime = 0.0f; +} + +void UIControl_PlayerSkinPreview::CyclePreviousAnimation() +{ + m_currentAnimation = (ESkinPreviewAnimations)(m_currentAnimation - 1); + if(m_currentAnimation < e_SkinPreviewAnimation_Walking) m_currentAnimation = (ESkinPreviewAnimations)(e_SkinPreviewAnimation_Count - 1); + + m_swingTime = 0.0f; +} + +void UIControl_PlayerSkinPreview::render(IggyCustomDrawCallbackRegion *region) +{ + Minecraft *pMinecraft=Minecraft::GetInstance(); + + glEnable(GL_RESCALE_NORMAL); + glEnable(GL_COLOR_MATERIAL); + glPushMatrix(); + + float width = region->x1 - region->x0; + float height = region->y1 - region->y0; + float xo = width/2; + float yo = height; + + glTranslatef(xo, yo - 3.5f, 50.0f); + //glTranslatef(120.0f, 294, 0.0f); + + float ss; + + // Base scale on height of this control + // Potentially we might want separate x & y scales here + ss = width / (m_fScreenWidth / m_fScreenHeight); + + glScalef(-ss, ss, ss); + glRotatef(180, 0, 0, 1); + + //glRotatef(45 + 90, 0, 1, 0); + Lighting::turnOn(); + //glRotatef(-45 - 90, 0, 1, 0); + + glRotatef(-(float)m_xRot, 1, 0, 0); + + // 4J Stu - Turning on hideGui while we do this stops the name rendering in split-screen + bool wasHidingGui = pMinecraft->options->hideGui; + pMinecraft->options->hideGui = true; + + //EntityRenderDispatcher::instance->render(pMinecraft->localplayers[0], 0, 0, 0, 0, 1); + EntityRenderer *renderer = EntityRenderDispatcher::instance->getRenderer(eTYPE_PLAYER); + if (renderer != NULL) + { + // 4J-PB - any additional parts to turn on for this player (skin dependent) + //vector<ModelPart *> *pAdditionalModelParts=mob->GetAdditionalModelParts(); + + if(m_pvAdditionalModelParts && m_pvAdditionalModelParts->size()!=0) + { + for(AUTO_VAR(it, m_pvAdditionalModelParts->begin()); it != m_pvAdditionalModelParts->end(); ++it) + { + ModelPart *pModelPart=*it; + + pModelPart->visible=true; + } + } + + render(renderer,0,0,0,0,1); + //renderer->postRender(entity, x, y, z, rot, a); + + // hide the additional parts + if(m_pvAdditionalModelParts && m_pvAdditionalModelParts->size()!=0) + { + for(AUTO_VAR(it, m_pvAdditionalModelParts->begin()); it != m_pvAdditionalModelParts->end(); ++it) + { + ModelPart *pModelPart=*it; + + pModelPart->visible=false; + } + } + } + + pMinecraft->options->hideGui = wasHidingGui; + + glPopMatrix(); + Lighting::turnOff(); + glDisable(GL_RESCALE_NORMAL); +} + +// 4J Stu - Modified version of MobRenderer::render that does not require an actual entity +void UIControl_PlayerSkinPreview::render(EntityRenderer *renderer, double x, double y, double z, float rot, float a) +{ + glPushMatrix(); + glDisable(GL_CULL_FACE); + + HumanoidModel *model = (HumanoidModel *)renderer->getModel(); + + //getAttackAnim(mob, a); + //if (armor != NULL) armor->attackTime = model->attackTime; + //model->riding = mob->isRiding(); + //if (armor != NULL) armor->riding = model->riding; + + // 4J Stu - Remember to reset these values once the rendering is done if you add another one + model->attackTime = 0; + model->sneaking = false; + model->holdingRightHand = false; + model->holdingLeftHand = false; + model->idle = false; + model->eating = false; + model->eating_swing = 0; + model->eating_t = 0; + model->young = false; + model->riding = false; + + model->m_uiAnimOverrideBitmask = m_uiAnimOverrideBitmask; + + if( !m_bAnimatingToFacing ) + { + switch( m_currentAnimation ) + { + case e_SkinPreviewAnimation_Sneaking: + model->sneaking = true; + break; + case e_SkinPreviewAnimation_Attacking: + model->holdingRightHand = true; + m_swingTime++; + if (m_swingTime >= (Player::SWING_DURATION * 3) ) + { + m_swingTime = 0; + } + model->attackTime = m_swingTime / (float) (Player::SWING_DURATION * 3); + break; + default: + break; + }; + } + + + float bodyRot = m_yRot; //(mob->yBodyRotO + (mob->yBodyRot - mob->yBodyRotO) * a); + float headRot = m_yRot; //(mob->yRotO + (mob->yRot - mob->yRotO) * a); + float headRotx = 0; //(mob->xRotO + (mob->xRot - mob->xRotO) * a); + + //setupPosition(mob, x, y, z); + // is equivalent to + glTranslatef((float) x, (float) y, (float) z); + + //float bob = getBob(mob, a); +#ifdef SKIN_PREVIEW_BOB_ANIM + float bob = (m_bobTick + a)/2; + + ++m_bobTick; + if(m_bobTick>=360*2) m_bobTick = 0; +#else + float bob = 0.0f; +#endif + + //setupRotations(mob, bob, bodyRot, a); + // is equivalent to + glRotatef(180 - bodyRot, 0, 1, 0); + + float _scale = 1 / 16.0f; + glEnable(GL_RESCALE_NORMAL); + glScalef(-1, -1, 1); + + //scale(mob, a); + // is equivalent to + float s = 15 / 16.0f; + glScalef(s, s, s); + + glTranslatef(0, -24 * _scale - 0.125f / 16.0f, 0); + +#ifdef SKIN_PREVIEW_WALKING_ANIM + m_walkAnimSpeedO = m_walkAnimSpeed; + m_walkAnimSpeed += (0.1f - m_walkAnimSpeed) * 0.4f; + m_walkAnimPos += m_walkAnimSpeed; + float ws = m_walkAnimSpeedO + (m_walkAnimSpeed - m_walkAnimSpeedO) * a; + float wp = m_walkAnimPos - m_walkAnimSpeed * (1 - a); +#else + float ws = 0; + float wp = 0; +#endif + + if (ws > 1) ws = 1; + + MemSect(31); + bindTexture(m_customTextureUrl, m_backupTexture); + MemSect(0); + glEnable(GL_ALPHA_TEST); + + //model->prepareMobModel(mob, wp, ws, a); + model->render(nullptr, wp, ws, bob, headRot - bodyRot, headRotx, _scale, true); + /*for (int i = 0; i < MAX_ARMOR_LAYERS; i++) + { + if (prepareArmor(mob, i, a)) + { + armor->render(wp, ws, bob, headRot - bodyRot, headRotx, _scale, true); + glDisable(GL_BLEND); + glEnable(GL_ALPHA_TEST); + } + }*/ + + //additionalRendering(mob, a); + if (bindTexture(m_capeTextureUrl, L"" )) + { + glPushMatrix(); + glTranslatef(0, 0, 2 / 16.0f); + + double xd = 0;//(mob->xCloakO + (mob->xCloak - mob->xCloakO) * a) - (mob->xo + (mob->x - mob->xo) * a); + double yd = 0;//(mob->yCloakO + (mob->yCloak - mob->yCloakO) * a) - (mob->yo + (mob->y - mob->yo) * a); + double zd = 0;//(mob->zCloakO + (mob->zCloak - mob->zCloakO) * a) - (mob->zo + (mob->z - mob->zo) * a); + + float yr = 1;//mob->yBodyRotO + (mob->yBodyRot - mob->yBodyRotO) * a; + + double xa = sin(yr * PI / 180); + double za = -cos(yr * PI / 180); + + float flap = (float) yd * 10; + if (flap < -6) flap = -6; + if (flap > 32) flap = 32; + float lean = (float) (xd * xa + zd * za) * 100; + float lean2 = (float) (xd * za - zd * xa) * 100; + if (lean < 0) lean = 0; + + //float pow = 1;//mob->oBob + (bob - mob->oBob) * a; + + flap += 1;//sin((mob->walkDistO + (mob->walkDist - mob->walkDistO) * a) * 6) * 32 * pow; + if (model->sneaking) + { + flap += 25; + } + + glRotatef(6.0f + lean / 2 + flap, 1, 0, 0); + glRotatef(lean2 / 2, 0, 0, 1); + glRotatef(-lean2 / 2, 0, 1, 0); + glRotatef(180, 0, 1, 0); + model->renderCloak(1 / 16.0f,true); + glPopMatrix(); + } + /* + float br = mob->getBrightness(a); + int overlayColor = getOverlayColor(mob, br, a); + + if (((overlayColor >> 24) & 0xff) > 0 || mob->hurtTime > 0 || mob->deathTime > 0) + { + glDisable(GL_TEXTURE_2D); + glDisable(GL_ALPHA_TEST); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glDepthFunc(GL_EQUAL); + + // 4J - changed these renders to not use the compiled version of their models, because otherwise the render states set + // about (in particular the depth & alpha test) don't work with our command buffer versions + if (mob->hurtTime > 0 || mob->deathTime > 0) + { + glColor4f(br, 0, 0, 0.4f); + model->render(wp, ws, bob, headRot - bodyRot, headRotx, _scale, false); + for (int i = 0; i < MAX_ARMOR_LAYERS; i++) + { + if (prepareArmorOverlay(mob, i, a)) + { + glColor4f(br, 0, 0, 0.4f); + armor->render(wp, ws, bob, headRot - bodyRot, headRotx, _scale, false); + } + } + } + + if (((overlayColor >> 24) & 0xff) > 0) + { + float r = ((overlayColor >> 16) & 0xff) / 255.0f; + float g = ((overlayColor >> 8) & 0xff) / 255.0f; + float b = ((overlayColor) & 0xff) / 255.0f; + float aa = ((overlayColor >> 24) & 0xff) / 255.0f; + glColor4f(r, g, b, aa); + model->render(wp, ws, bob, headRot - bodyRot, headRotx, _scale, false); + for (int i = 0; i < MAX_ARMOR_LAYERS; i++) + { + if (prepareArmorOverlay(mob, i, a)) + { + glColor4f(r, g, b, aa); + armor->render(wp, ws, bob, headRot - bodyRot, headRotx, _scale, false); + } + } + } + + glDepthFunc(GL_LEQUAL); + glDisable(GL_BLEND); + glEnable(GL_ALPHA_TEST); + glEnable(GL_TEXTURE_2D); + } + */ + glDisable(GL_RESCALE_NORMAL); + + glEnable(GL_CULL_FACE); + + glPopMatrix(); + + MemSect(31); + //renderName(mob, x, y, z); + MemSect(0); + + // Reset the model values to stop the changes we made here affecting anything in game (like the player hand render) + model->attackTime = 0; + model->sneaking = false; + model->holdingRightHand = false; + model->holdingLeftHand = false; +} + +bool UIControl_PlayerSkinPreview::bindTexture(const wstring& urlTexture, int backupTexture) +{ + Textures *t = Minecraft::GetInstance()->textures; + + // 4J-PB - no http textures on the xbox, mem textures instead + + //int id = t->loadHttpTexture(urlTexture, backupTexture); + int id = t->loadMemTexture(urlTexture, backupTexture); + + if (id >= 0) + { + t->bind(id); + return true; + } + else + { + return false; + } +} + +bool UIControl_PlayerSkinPreview::bindTexture(const wstring& urlTexture, const wstring& backupTexture) +{ + Textures *t = Minecraft::GetInstance()->textures; + + // 4J-PB - no http textures on the xbox, mem textures instead + + //int id = t->loadHttpTexture(urlTexture, backupTexture); + int id = t->loadMemTexture(urlTexture, backupTexture); + + if (id >= 0) + { + t->bind(id); + return true; + } + else + { + return false; + } +} diff --git a/Minecraft.Client/Common/UI/UIControl_PlayerSkinPreview.h b/Minecraft.Client/Common/UI/UIControl_PlayerSkinPreview.h new file mode 100644 index 00000000..a7c3126e --- /dev/null +++ b/Minecraft.Client/Common/UI/UIControl_PlayerSkinPreview.h @@ -0,0 +1,90 @@ +#pragma once + +#include "UIControl.h" +#include "..\..\Textures.h" + +class ModelPart; +class EntityRenderer; + +class UIControl_PlayerSkinPreview : public UIControl +{ +private: + static const int LOOK_LEFT_EXTENT = 45; + static const int LOOK_RIGHT_EXTENT = -45; + + static const int CHANGING_SKIN_FRAMES = 15; + + enum ESkinPreviewAnimations + { + e_SkinPreviewAnimation_Walking, + e_SkinPreviewAnimation_Sneaking, + e_SkinPreviewAnimation_Attacking, + + e_SkinPreviewAnimation_Count, + }; + + BOOL m_bDirty; + float m_fScale,m_fAlpha; + + wstring m_customTextureUrl; + TEXTURE_NAME m_backupTexture; + wstring m_capeTextureUrl; + unsigned int m_uiAnimOverrideBitmask; + + float m_fScreenWidth,m_fScreenHeight; + float m_fRawWidth,m_fRawHeight; + + int m_yRot,m_xRot; + + float m_bobTick; + + float m_walkAnimSpeedO; + float m_walkAnimSpeed; + float m_walkAnimPos; + + bool m_bAutoRotate, m_bRotatingLeft; + BYTE m_rotateTick; + float m_fTargetRotation, m_fOriginalRotation; + int m_framesAnimatingRotation; + bool m_bAnimatingToFacing; + + float m_swingTime; + + ESkinPreviewAnimations m_currentAnimation; + //vector<Model::SKIN_BOX *> *m_pvAdditionalBoxes; + vector<ModelPart *> *m_pvAdditionalModelParts; +public: + enum ESkinPreviewFacing + { + e_SkinPreviewFacing_Forward, + e_SkinPreviewFacing_Left, + e_SkinPreviewFacing_Right, + }; + + UIControl_PlayerSkinPreview(); + + virtual void tick(); + + void render(IggyCustomDrawCallbackRegion *region); + + void SetTexture(const wstring &url, TEXTURE_NAME backupTexture = TN_MOB_CHAR); + void SetCapeTexture(const wstring &url) { m_capeTextureUrl = url; } + void ResetRotation() { m_xRot = 0; m_yRot = 0; } + void IncrementYRotation() { m_yRot = (m_yRot+4); if(m_yRot >= 180) m_yRot = -180; } + void DecrementYRotation() { m_yRot = (m_yRot-4); if(m_yRot <= -180) m_yRot = 180; } + void IncrementXRotation() { m_xRot = (m_xRot+2); if(m_xRot > 22) m_xRot = 22; } + void DecrementXRotation() { m_xRot = (m_xRot-2); if(m_xRot < -22) m_xRot = -22; } + void SetAutoRotate(bool autoRotate) { m_bAutoRotate = autoRotate; } + void SetFacing(ESkinPreviewFacing facing, bool bAnimate = false); + + void CycleNextAnimation(); + void CyclePreviousAnimation(); + + bool m_incXRot, m_decXRot; + bool m_incYRot, m_decYRot; + +private: + void render(EntityRenderer *renderer, double x, double y, double z, float rot, float a); + bool bindTexture(const wstring& urlTexture, int backupTexture); + bool bindTexture(const wstring& urlTexture, const wstring& backupTexture); +};
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIControl_Progress.cpp b/Minecraft.Client/Common/UI/UIControl_Progress.cpp new file mode 100644 index 00000000..e2ab817d --- /dev/null +++ b/Minecraft.Client/Common/UI/UIControl_Progress.cpp @@ -0,0 +1,84 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIControl_Progress.h" + +UIControl_Progress::UIControl_Progress() +{ + m_min = 0; + m_max = 100; + m_current = 0; + m_lastPercent = 0.0f; + m_showingBar = true; +} + +bool UIControl_Progress::setupControl(UIScene *scene, IggyValuePath *parent, const string &controlName) +{ + UIControl::setControlType(UIControl::eProgress); + bool success = UIControl_Base::setupControl(scene,parent,controlName); + + //Progress specific initialisers + m_setProgressFunc = registerFastName(L"setProgress"); + m_showBarFunc = registerFastName(L"ShowBar"); + + return success; +} + +void UIControl_Progress::init(const wstring &label, int id, int min, int max, int current) +{ + m_label = label; + m_id = id; + m_min = min; + m_max = max; + m_current = current; + + IggyDataValue result; + IggyDataValue value[1]; + value[0].type = IGGY_DATATYPE_string_UTF16; + IggyStringUTF16 stringVal; + + stringVal.string = (IggyUTF16*)label.c_str(); + stringVal.length = label.length(); + value[0].string16 = stringVal; + + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath() , m_initFunc , 1 , value ); +} + +void UIControl_Progress::ReInit() +{ + UIControl_Base::ReInit(); + init(m_label, m_id, m_min, m_max, m_current); +} + +void UIControl_Progress::setProgress(int current) +{ + m_current = current; + + float percent = (float)((m_current-m_min))/(m_max-m_min); + + if(percent != m_lastPercent) + { + m_lastPercent = percent; + //app.DebugPrintf("Setting progress value to %d/%f\n", m_current, percent); + + IggyDataValue result; + IggyDataValue value[1]; + value[0].type = IGGY_DATATYPE_number; + value[0].number = percent; + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath() , m_setProgressFunc , 1 , value ); + } +} + +void UIControl_Progress::showBar(bool show) +{ + if(show != m_showingBar) + { + m_showingBar = show; + //app.DebugPrintf("Setting progress value to %d/%f\n", m_current, percent); + + IggyDataValue result; + IggyDataValue value[1]; + value[0].type = IGGY_DATATYPE_boolean; + value[0].boolval = show; + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath() , m_showBarFunc , 1 , value ); + } +}
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIControl_Progress.h b/Minecraft.Client/Common/UI/UIControl_Progress.h new file mode 100644 index 00000000..8398a188 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIControl_Progress.h @@ -0,0 +1,25 @@ +#pragma once + +#include "UIControl_Base.h" + +class UIControl_Progress : public UIControl_Base +{ +private: + IggyName m_setProgressFunc, m_showBarFunc; + int m_min; + int m_max; + int m_current; + float m_lastPercent; + bool m_showingBar; + +public: + UIControl_Progress(); + + virtual bool setupControl(UIScene *scene, IggyValuePath *parent, const string &controlName); + + void init(const wstring &label, int id, int min, int max, int current); + virtual void ReInit(); + + void setProgress(int current); + void showBar(bool show); +};
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIControl_SaveList.cpp b/Minecraft.Client/Common/UI/UIControl_SaveList.cpp new file mode 100644 index 00000000..f83454d7 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIControl_SaveList.cpp @@ -0,0 +1,106 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIControl_SaveList.h" + +bool UIControl_SaveList::setupControl(UIScene *scene, IggyValuePath *parent, const string &controlName) +{ + UIControl::setControlType(UIControl::eSaveList); + bool success = UIControl_ButtonList::setupControl(scene,parent,controlName); + + //SlotList specific initialisers + m_funcSetTextureName = registerFastName(L"SetTextureName"); + + return success; +} + +void UIControl_SaveList::addItem(const wstring &label) +{ + addItem(label, L""); +} + +void UIControl_SaveList::addItem(const string &label) +{ + addItem(label, L""); +} + +void UIControl_SaveList::addItem(const wstring &label, int data) +{ + addItem(label, L"", data); +} + +void UIControl_SaveList::addItem(const string &label, int data) +{ + addItem(label, L"", data); +} + +void UIControl_SaveList::addItem(const string &label, const wstring &iconName) +{ + addItem(label, iconName, m_itemCount); + ++m_itemCount; +} + +void UIControl_SaveList::addItem(const wstring &label, const wstring &iconName) +{ + addItem(label, iconName, m_itemCount); + ++m_itemCount; +} + +void UIControl_SaveList::addItem(const string &label, const wstring &iconName, int data) +{ + IggyDataValue result; + IggyDataValue value[3]; + + IggyStringUTF8 stringVal; + stringVal.string = (char*)label.c_str(); + stringVal.length = (S32)label.length(); + value[0].type = IGGY_DATATYPE_string_UTF8; + value[0].string8 = stringVal; + + value[1].type = IGGY_DATATYPE_number; + value[1].number = m_itemCount; + + IggyStringUTF16 stringVal2; + stringVal2.string = (IggyUTF16*)iconName.c_str(); + stringVal2.length = iconName.length(); + value[2].type = IGGY_DATATYPE_string_UTF16; + value[2].string16 = stringVal2; + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath(), m_addNewItemFunc , 3 , value ); +} + +void UIControl_SaveList::addItem(const wstring &label, const wstring &iconName, int data) +{ + IggyDataValue result; + IggyDataValue value[3]; + + IggyStringUTF16 stringVal; + stringVal.string = (IggyUTF16*)label.c_str(); + stringVal.length = (S32)label.length(); + value[0].type = IGGY_DATATYPE_string_UTF16; + value[0].string16 = stringVal; + + value[1].type = IGGY_DATATYPE_number; + value[1].number = m_itemCount; + + IggyStringUTF16 stringVal2; + stringVal2.string = (IggyUTF16*)iconName.c_str(); + stringVal2.length = iconName.length(); + value[2].type = IGGY_DATATYPE_string_UTF16; + value[2].string16 = stringVal2; + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath(), m_addNewItemFunc , 3 , value ); +} + +void UIControl_SaveList::setTextureName(int iId, const wstring &iconName) +{ + IggyDataValue result; + IggyDataValue value[2]; + + value[0].type = IGGY_DATATYPE_number; + value[0].number = iId; + + IggyStringUTF16 stringVal; + stringVal.string = (IggyUTF16*)iconName.c_str(); + stringVal.length = iconName.length(); + value[1].type = IGGY_DATATYPE_string_UTF16; + value[1].string16 = stringVal; + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath(), m_funcSetTextureName , 2 , value ); +} diff --git a/Minecraft.Client/Common/UI/UIControl_SaveList.h b/Minecraft.Client/Common/UI/UIControl_SaveList.h new file mode 100644 index 00000000..7c72fea9 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIControl_SaveList.h @@ -0,0 +1,29 @@ +#pragma once + +#include "UIControl_ButtonList.h" + +class UIControl_SaveList : public UIControl_ButtonList +{ +private: + IggyName m_funcSetTextureName; + +public: + virtual bool setupControl(UIScene *scene, IggyValuePath *parent, const string &controlName); + + using UIControl_ButtonList::addItem; + + void addItem(const wstring &label); + void addItem(const string &label); + + void addItem(const wstring &label, int data); + void addItem(const string &label, int data); + + void addItem(const string &label, const wstring &iconName); + void addItem(const wstring &label, const wstring &iconName); + void setTextureName(int iId, const wstring &iconName); + +private: + void addItem(const string &label, const wstring &iconName, int data); + void addItem(const wstring &label, const wstring &iconName, int data); + +};
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIControl_Slider.cpp b/Minecraft.Client/Common/UI/UIControl_Slider.cpp new file mode 100644 index 00000000..bd3b1ada --- /dev/null +++ b/Minecraft.Client/Common/UI/UIControl_Slider.cpp @@ -0,0 +1,119 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIControl_Slider.h" + +UIControl_Slider::UIControl_Slider() +{ + m_id = 0; + m_min = 0; + m_max = 100; + m_current = 0; +} + +bool UIControl_Slider::setupControl(UIScene *scene, IggyValuePath *parent, const string &controlName) +{ + UIControl::setControlType(UIControl::eSlider); + bool success = UIControl_Base::setupControl(scene,parent,controlName); + + //Slider specific initialisers + m_funcSetRelativeSliderPos = registerFastName(L"SetRelativeSliderPos"); + m_funcGetRealWidth = registerFastName(L"GetRealWidth"); + + return success; +} + +void UIControl_Slider::init(const wstring &label, int id, int min, int max, int current) +{ + m_label = label; + m_id = id; + m_min = min; + m_max = max; + m_current = current; + + IggyDataValue result; + IggyDataValue value[5]; + value[0].type = IGGY_DATATYPE_string_UTF16; + IggyStringUTF16 stringVal; + + stringVal.string = (IggyUTF16*)label.c_str(); + stringVal.length = label.length(); + value[0].string16 = stringVal; + + value[1].type = IGGY_DATATYPE_number; + value[1].number = (int)id; + + value[2].type = IGGY_DATATYPE_number; + value[2].number = (int)min; + + value[3].type = IGGY_DATATYPE_number; + value[3].number = (int)max; + + value[4].type = IGGY_DATATYPE_number; + value[4].number = (int)current; + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath() , m_initFunc , 5 , value ); + +#ifdef __PSVITA__ + // 4J-TomK - add slider to the vita touch box list + + switch(m_parentScene->GetParentLayer()->m_iLayer) + { + case eUILayer_Fullscreen: + case eUILayer_Scene: + case eUILayer_HUD: + ui.TouchBoxAdd(this,m_parentScene); + break; + } +#endif +} + +void UIControl_Slider::handleSliderMove(int newValue) +{ + if (m_current!=newValue) + { + ui.PlayUISFX(eSFX_Scroll); + m_current = newValue; + + if(newValue < m_allPossibleLabels.size()) + { + setLabel(m_allPossibleLabels[newValue]); + } + } +} + +void UIControl_Slider::SetSliderTouchPos(float fTouchPos) +{ + IggyDataValue result; + IggyDataValue value[1]; + value[0].type = IGGY_DATATYPE_number; + value[0].number = fTouchPos; + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath() , m_funcSetRelativeSliderPos , 1 , value ); + } + +S32 UIControl_Slider::GetRealWidth() +{ + IggyDataValue result; + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath() , m_funcGetRealWidth , 0 , NULL ); + + S32 iRealWidth = m_width; + if(result.type == IGGY_DATATYPE_number) + { + iRealWidth = (S32)result.number; + } + return iRealWidth; +} + +void UIControl_Slider::setAllPossibleLabels(int labelCount, wchar_t labels[][256]) +{ + for(unsigned int i = 0; i < labelCount; ++i) + { + m_allPossibleLabels.push_back(labels[i]); + } + UIControl_Base::setAllPossibleLabels(labelCount, labels); +} + +void UIControl_Slider::ReInit() +{ + UIControl_Base::ReInit(); + + init(m_label, m_id, m_min, m_max, m_current); +} diff --git a/Minecraft.Client/Common/UI/UIControl_Slider.h b/Minecraft.Client/Common/UI/UIControl_Slider.h new file mode 100644 index 00000000..0b57c2f1 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIControl_Slider.h @@ -0,0 +1,32 @@ +#pragma once + +#include "UIControl_Base.h" + +class UIControl_Slider : public UIControl_Base +{ +private: + //int m_id; // 4J-TomK this is part of class UIControl and doesn't need to be here! + int m_min; + int m_max; + int m_current; + + vector<wstring> m_allPossibleLabels; + + // 4J-TomK - function for setting slider position on touch + IggyName m_funcSetRelativeSliderPos; + IggyName m_funcGetRealWidth; + +public: + UIControl_Slider(); + + virtual bool setupControl(UIScene *scene, IggyValuePath *parent, const string &controlName); + + void init(const wstring &label, int id, int min, int max, int current); + + void handleSliderMove(int newValue); + void SetSliderTouchPos(float fTouchPos); + virtual void setAllPossibleLabels(int labelCount, wchar_t labels[][256]); + + S32 GetRealWidth(); + virtual void ReInit(); +}; diff --git a/Minecraft.Client/Common/UI/UIControl_SlotList.cpp b/Minecraft.Client/Common/UI/UIControl_SlotList.cpp new file mode 100644 index 00000000..e2130431 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIControl_SlotList.cpp @@ -0,0 +1,93 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIControl_SlotList.h" + +UIControl_SlotList::UIControl_SlotList() +{ + m_lastHighlighted = -1; +} + +bool UIControl_SlotList::setupControl(UIScene *scene, IggyValuePath *parent, const string &controlName) +{ + UIControl::setControlType(UIControl::eSlotList); + bool success = UIControl_Base::setupControl(scene,parent,controlName); + + //SlotList specific initialisers + m_addSlotFunc = registerFastName(L"addSlot"); + m_setRedBoxFunc = registerFastName(L"SetSlotRedBox"); + m_setHighlightFunc = registerFastName(L"SetSlotHighlight"); + + m_lastHighlighted = 0; + + return success; +} + +void UIControl_SlotList::addSlot(int id) +{ + IggyDataValue result; + IggyDataValue value[3]; + value[0].type = IGGY_DATATYPE_number; + value[0].number = id; + + value[1].type = IGGY_DATATYPE_boolean; + value[1].boolval = false; + value[2].type = IGGY_DATATYPE_boolean; + value[2].boolval = false; + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath(), m_addSlotFunc ,3 , value ); +} + +void UIControl_SlotList::addSlots(int iStartValue, int iCount) +{ + for(unsigned int i = iStartValue; i < iStartValue + iCount; ++i) + { + addSlot(i); + } +} + + +void UIControl_SlotList::setHighlightSlot(int index) +{ + if(index != m_lastHighlighted) + { + if(m_lastHighlighted != -1) + { + setSlotHighlighted(m_lastHighlighted, false); + } + setSlotHighlighted(index, true); + m_lastHighlighted = index; + } +} + +void UIControl_SlotList::setSlotHighlighted(int index, bool highlight) +{ + IggyDataValue result; + IggyDataValue value[2]; + value[0].type = IGGY_DATATYPE_number; + value[0].number = index; + + value[1].type = IGGY_DATATYPE_boolean; + value[1].boolval = highlight; + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath(), m_setHighlightFunc , 2 , value ); +} + +void UIControl_SlotList::showSlotRedBox(int index, bool show) +{ + //app.DebugPrintf("Setting red box at index %d to %s\n", index, show?"on":"off"); + IggyDataValue result; + IggyDataValue value[2]; + value[0].type = IGGY_DATATYPE_number; + value[0].number = index; + + value[1].type = IGGY_DATATYPE_boolean; + value[1].boolval = show; + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath(), m_setRedBoxFunc , 2, value ); +} + +void UIControl_SlotList::setFocus(bool focus) +{ + if(m_lastHighlighted != -1) + { + if(focus) setSlotHighlighted(m_lastHighlighted, true); + else setSlotHighlighted(m_lastHighlighted, false); + } +} diff --git a/Minecraft.Client/Common/UI/UIControl_SlotList.h b/Minecraft.Client/Common/UI/UIControl_SlotList.h new file mode 100644 index 00000000..ee741c4d --- /dev/null +++ b/Minecraft.Client/Common/UI/UIControl_SlotList.h @@ -0,0 +1,28 @@ +#pragma once + +#include "UIControl_Base.h" + +class UIControl_SlotList : public UIControl_Base +{ +private: + //IggyName m_addSlotFunc, m_getSlotFunc, m_setRedBoxFunc, m_setHighlightFunc; + IggyName m_addSlotFunc, m_setRedBoxFunc, m_setHighlightFunc; + + int m_lastHighlighted; + +public: + UIControl_SlotList(); + + virtual bool setupControl(UIScene *scene, IggyValuePath *parent, const string &controlName); + + void addSlot(int id); + void addSlots(int iStartValue, int iCount); + + void setHighlightSlot(int index); + void showSlotRedBox(int index, bool show); + + virtual void setFocus(bool focus); + +private: + void setSlotHighlighted(int index, bool highlight); +}; diff --git a/Minecraft.Client/Common/UI/UIControl_SpaceIndicatorBar.cpp b/Minecraft.Client/Common/UI/UIControl_SpaceIndicatorBar.cpp new file mode 100644 index 00000000..dfdea93e --- /dev/null +++ b/Minecraft.Client/Common/UI/UIControl_SpaceIndicatorBar.cpp @@ -0,0 +1,122 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIControl_SpaceIndicatorBar.h" + +UIControl_SpaceIndicatorBar::UIControl_SpaceIndicatorBar() +{ + m_min = 0; + m_max = 100; + m_currentSave = 0; + m_currentTotal = 0; + m_currentOffset = 0.0f; +} + +bool UIControl_SpaceIndicatorBar::setupControl(UIScene *scene, IggyValuePath *parent, const string &controlName) +{ + UIControl::setControlType(UIControl::eProgress); + bool success = UIControl_Base::setupControl(scene,parent,controlName); + + //Progress specific initialisers + m_setSaveSizeFunc = registerFastName(L"setSaveGameSize"); + m_setTotalSizeFunc = registerFastName(L"setTotalSize"); + m_setSaveGameOffsetFunc = registerFastName(L"setSaveGameOffset"); + + return success; +} + +void UIControl_SpaceIndicatorBar::init(const wstring &label, int id, __int64 min, __int64 max) +{ + m_label = label; + m_id = id; + m_min = min; + m_max = max; + + IggyDataValue result; + IggyDataValue value[1]; + value[0].type = IGGY_DATATYPE_string_UTF16; + IggyStringUTF16 stringVal; + + stringVal.string = (IggyUTF16*)label.c_str(); + stringVal.length = label.length(); + value[0].string16 = stringVal; + + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath() , m_initFunc , 1 , value ); +} + +void UIControl_SpaceIndicatorBar::ReInit() +{ + UIControl_Base::ReInit(); + init(m_label, m_id, m_min, m_max); + setSaveSize(m_currentSave); + setTotalSize(m_currentTotal); + setSaveGameOffset(m_currentOffset); +} + +void UIControl_SpaceIndicatorBar::reset() +{ + m_sizeAndOffsets.clear(); + m_currentTotal = 0; + setTotalSize(0); + setSaveSize(0); + setSaveGameOffset(0.0f); +} + +void UIControl_SpaceIndicatorBar::addSave(__int64 size) +{ + float startPercent = (float)((m_currentTotal-m_min))/(m_max-m_min); + + m_sizeAndOffsets.push_back( pair<__int64, float>(size, startPercent) ); + + m_currentTotal += size; + setTotalSize(m_currentTotal); +} + +void UIControl_SpaceIndicatorBar::selectSave(int index) +{ + if(index >= 0 && index < m_sizeAndOffsets.size()) + { + pair<__int64,float> values = m_sizeAndOffsets[index]; + setSaveSize(values.first); + setSaveGameOffset(values.second); + } + else + { + setSaveSize(0); + setSaveGameOffset(0); + } +} + +void UIControl_SpaceIndicatorBar::setSaveSize(__int64 size) +{ + m_currentSave = size; + + float percent = (float)((m_currentSave-m_min))/(m_max-m_min); + + IggyDataValue result; + IggyDataValue value[1]; + value[0].type = IGGY_DATATYPE_number; + value[0].number = percent; + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath() , m_setSaveSizeFunc , 1 , value ); +} + +void UIControl_SpaceIndicatorBar::setTotalSize(__int64 size) +{ + float percent = (float)((m_currentTotal-m_min))/(m_max-m_min); + + IggyDataValue result; + IggyDataValue value[1]; + value[0].type = IGGY_DATATYPE_number; + value[0].number = percent; + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath() , m_setTotalSizeFunc , 1 , value ); +} + +void UIControl_SpaceIndicatorBar::setSaveGameOffset(float offset) +{ + m_currentOffset = offset; + + IggyDataValue result; + IggyDataValue value[1]; + value[0].type = IGGY_DATATYPE_number; + value[0].number = m_currentOffset; + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath() , m_setSaveGameOffsetFunc , 1 , value ); +}
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIControl_SpaceIndicatorBar.h b/Minecraft.Client/Common/UI/UIControl_SpaceIndicatorBar.h new file mode 100644 index 00000000..39f9a746 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIControl_SpaceIndicatorBar.h @@ -0,0 +1,33 @@ +#pragma once + +#include "UIControl_Base.h" + +class UIControl_SpaceIndicatorBar : public UIControl_Base +{ +private: + IggyName m_setSaveSizeFunc, m_setTotalSizeFunc, m_setSaveGameOffsetFunc; + __int64 m_min; + __int64 m_max; + __int64 m_currentSave, m_currentTotal; + float m_currentOffset; + + vector<pair<__int64,float> > m_sizeAndOffsets; + +public: + UIControl_SpaceIndicatorBar(); + + virtual bool setupControl(UIScene *scene, IggyValuePath *parent, const string &controlName); + + void init(const wstring &label, int id, __int64 min, __int64 max); + virtual void ReInit(); + void reset(); + + void addSave(__int64 size); + void selectSave(int index); + + +private: + void setSaveSize(__int64 size); + void setTotalSize(__int64 totalSize); + void setSaveGameOffset(float offset); +};
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIControl_TextInput.cpp b/Minecraft.Client/Common/UI/UIControl_TextInput.cpp new file mode 100644 index 00000000..4cb78d50 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIControl_TextInput.cpp @@ -0,0 +1,83 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIControl_TextInput.h" + +UIControl_TextInput::UIControl_TextInput() +{ + m_bHasFocus = false; +} + +bool UIControl_TextInput::setupControl(UIScene *scene, IggyValuePath *parent, const string &controlName) +{ + UIControl::setControlType(UIControl::eTextInput); + bool success = UIControl_Base::setupControl(scene,parent,controlName); + + //TextInput specific initialisers + m_textName = registerFastName(L"text"); + m_funcChangeState = registerFastName(L"ChangeState"); + m_funcSetCharLimit = registerFastName(L"SetCharLimit"); + + return success; +} + +void UIControl_TextInput::init(const wstring &label, int id) +{ + m_label = label; + m_id = id; + + IggyDataValue result; + IggyDataValue value[2]; + value[0].type = IGGY_DATATYPE_string_UTF16; + IggyStringUTF16 stringVal; + + stringVal.string = (IggyUTF16*)label.c_str(); + stringVal.length = label.length(); + value[0].string16 = stringVal; + + value[1].type = IGGY_DATATYPE_number; + value[1].number = id; + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath() , m_initFunc , 2 , value ); + + #ifdef __PSVITA__ + // 4J-TomK - add this buttonlist to the vita touch box list + + switch(m_parentScene->GetParentLayer()->m_iLayer) + { + case eUILayer_Fullscreen: + case eUILayer_Scene: + case eUILayer_HUD: + ui.TouchBoxAdd(this,m_parentScene); + break; + } + #endif +} + +void UIControl_TextInput::ReInit() +{ + UIControl_Base::ReInit(); + + init(m_label, m_id); +} + +void UIControl_TextInput::setFocus(bool focus) +{ + if(m_bHasFocus != focus) + { + m_bHasFocus = focus; + + IggyDataValue result; + IggyDataValue value[1]; + value[0].type = IGGY_DATATYPE_number; + value[0].number = focus?0:1; + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath() , m_funcChangeState , 1 , value ); + } +} + +void UIControl_TextInput::SetCharLimit(int iLimit) +{ + IggyDataValue result; + IggyDataValue value[1]; + value[0].type = IGGY_DATATYPE_number; + value[0].number = iLimit; + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath() , m_funcSetCharLimit , 1 , value ); +} diff --git a/Minecraft.Client/Common/UI/UIControl_TextInput.h b/Minecraft.Client/Common/UI/UIControl_TextInput.h new file mode 100644 index 00000000..d4023884 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIControl_TextInput.h @@ -0,0 +1,22 @@ +#pragma once + +#include "UIControl_Base.h" + +class UIControl_TextInput : public UIControl_Base +{ +private: + IggyName m_textName, m_funcChangeState, m_funcSetCharLimit; + bool m_bHasFocus; + +public: + UIControl_TextInput(); + + virtual bool setupControl(UIScene *scene, IggyValuePath *parent, const string &controlName); + + void init(const wstring &label, int id); + void ReInit(); + + virtual void setFocus(bool focus); + + void SetCharLimit(int iLimit); +};
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIControl_TexturePackList.cpp b/Minecraft.Client/Common/UI/UIControl_TexturePackList.cpp new file mode 100644 index 00000000..02336e00 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIControl_TexturePackList.cpp @@ -0,0 +1,145 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIControl_TexturePackList.h" + +UIControl_TexturePackList::UIControl_TexturePackList() +{ +} + +bool UIControl_TexturePackList::setupControl(UIScene *scene, IggyValuePath *parent, const string &controlName) +{ + UIControl::setControlType(UIControl::eTexturePackList); + bool success = UIControl_Base::setupControl(scene,parent,controlName); + + //SlotList specific initialisers + m_addPackFunc = registerFastName(L"addPack"); + m_clearSlotsFunc = registerFastName(L"removeAllItems"); + m_funcSelectSlot = registerFastName(L"SelectSlot"); + m_funcEnableSelector = registerFastName(L"EnableSelector"); + m_funcSetTouchFocus = registerFastName(L"SetTouchFocus"); + m_funcCanTouchTrigger = registerFastName(L"CanTouchTrigger"); + m_funcGetRealHeight = registerFastName(L"GetRealHeight"); + + return success; +} + +void UIControl_TexturePackList::init(const wstring &label, int id) +{ + m_label = label; + m_id = id; + + IggyDataValue result; + IggyDataValue value[2]; + value[0].type = IGGY_DATATYPE_string_UTF16; + IggyStringUTF16 stringVal; + + stringVal.string = (IggyUTF16*)label.c_str(); + stringVal.length = label.length(); + value[0].string16 = stringVal; + + value[1].type = IGGY_DATATYPE_number; + value[1].number = id; + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath() , m_initFunc , 2 , value ); + +#ifdef __PSVITA__ + // 4J-TomK - add this texturepack list to the vita touch box list + + switch(m_parentScene->GetParentLayer()->m_iLayer) + { + case eUILayer_Fullscreen: + case eUILayer_Scene: + case eUILayer_HUD: + ui.TouchBoxAdd(this,m_parentScene); + break; + } +#endif +} + +void UIControl_TexturePackList::addPack(int id, const wstring &textureName) +{ + IggyDataValue result; + IggyDataValue value[2]; + value[0].type = IGGY_DATATYPE_number; + value[0].number = id; + + value[1].type = IGGY_DATATYPE_string_UTF16; + IggyStringUTF16 stringVal; + + stringVal.string = (IggyUTF16*)textureName.c_str(); + stringVal.length = textureName.length(); + value[1].string16 = stringVal; + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath(), m_addPackFunc ,2 , value ); +} + +void UIControl_TexturePackList::selectSlot(int id) +{ + IggyDataValue result; + IggyDataValue value[1]; + value[0].type = IGGY_DATATYPE_number; + value[0].number = id; + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath(), m_funcSelectSlot ,1 , value ); +} + +void UIControl_TexturePackList::clearSlots() +{ + IggyDataValue result; + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath(), m_clearSlotsFunc ,0 , NULL ); +} + +void UIControl_TexturePackList::setEnabled(bool enable) +{ + IggyDataValue result; + IggyDataValue value[1]; + value[0].type = IGGY_DATATYPE_boolean; + value[0].number = enable; + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath(), m_funcEnableSelector ,1 , value ); +} + +void UIControl_TexturePackList::SetTouchFocus(S32 iX, S32 iY, bool bRepeat) +{ + IggyDataValue result; + IggyDataValue value[3]; + + value[0].type = IGGY_DATATYPE_number; + value[0].number = iX; + value[1].type = IGGY_DATATYPE_number; + value[1].number = iY; + value[2].type = IGGY_DATATYPE_boolean; + value[2].boolval = bRepeat; + + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie(), &result, getIggyValuePath(), m_funcSetTouchFocus, 3 , value ); +} + +bool UIControl_TexturePackList::CanTouchTrigger(S32 iX, S32 iY) +{ + IggyDataValue result; + IggyDataValue value[2]; + + value[0].type = IGGY_DATATYPE_number; + value[0].number = iX; + value[1].type = IGGY_DATATYPE_number; + value[1].number = iY; + + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie(), &result, getIggyValuePath(), m_funcCanTouchTrigger, 2 , value ); + + S32 bCanTouchTrigger = false; + if(result.type == IGGY_DATATYPE_boolean) + { + bCanTouchTrigger = (bool)result.boolval; + } + return bCanTouchTrigger; +} + +S32 UIControl_TexturePackList::GetRealHeight() +{ + IggyDataValue result; + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath() , m_funcGetRealHeight, 0 , NULL ); + + S32 iRealHeight = m_height; + if(result.type == IGGY_DATATYPE_number) + { + iRealHeight = (S32)result.number; + } + return iRealHeight; +} + diff --git a/Minecraft.Client/Common/UI/UIControl_TexturePackList.h b/Minecraft.Client/Common/UI/UIControl_TexturePackList.h new file mode 100644 index 00000000..ce476fb1 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIControl_TexturePackList.h @@ -0,0 +1,27 @@ +#pragma once + +#include "UIControl_Base.h" + +class UIControl_TexturePackList : public UIControl_Base +{ +private: + IggyName m_addPackFunc, m_funcSelectSlot, m_funcSetTouchFocus, m_funcCanTouchTrigger, m_funcGetRealHeight,m_clearSlotsFunc; + IggyName m_funcEnableSelector; + +public: + UIControl_TexturePackList(); + + virtual bool setupControl(UIScene *scene, IggyValuePath *parent, const string &controlName); + + void init(const wstring &label, int id); + + void addPack(int id, const wstring &textureName); + void selectSlot(int id); + void clearSlots(); + + virtual void setEnabled(bool enable); + + void SetTouchFocus(S32 iX, S32 iY, bool bRepeat); + bool CanTouchTrigger(S32 iX, S32 iY); + S32 GetRealHeight(); +}; diff --git a/Minecraft.Client/Common/UI/UIControl_Touch.cpp b/Minecraft.Client/Common/UI/UIControl_Touch.cpp new file mode 100644 index 00000000..bd57882f --- /dev/null +++ b/Minecraft.Client/Common/UI/UIControl_Touch.cpp @@ -0,0 +1,38 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIControl_Touch.h" + +UIControl_Touch::UIControl_Touch() +{ +} + +bool UIControl_Touch::setupControl(UIScene *scene, IggyValuePath *parent, const string &controlName) +{ + UIControl::setControlType(UIControl::eTouchControl); + bool success = UIControl_Base::setupControl(scene,parent,controlName); + + return success; +} + +void UIControl_Touch::init(int iId) +{ + m_id = iId; + + // 4J-TomK - add this touch control to the vita touch box list + switch(m_parentScene->GetParentLayer()->m_iLayer) + { + case eUILayer_Error: + case eUILayer_Fullscreen: + case eUILayer_Scene: + case eUILayer_HUD: + ui.TouchBoxAdd(this,m_parentScene); + break; + } +} + +void UIControl_Touch::ReInit() +{ + UIControl_Base::ReInit(); + + init(m_id); +}
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIControl_Touch.h b/Minecraft.Client/Common/UI/UIControl_Touch.h new file mode 100644 index 00000000..8ae799a0 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIControl_Touch.h @@ -0,0 +1,16 @@ +#pragma once + +#include "UIControl_Base.h" + +class UIControl_Touch : public UIControl_Base +{ +private: + +public: + UIControl_Touch(); + + virtual bool setupControl(UIScene *scene, IggyValuePath *parent, const string &controlName); + + void init(int id); + virtual void ReInit(); +};
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIController.cpp b/Minecraft.Client/Common/UI/UIController.cpp new file mode 100644 index 00000000..7493ff06 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIController.cpp @@ -0,0 +1,3015 @@ +#include "stdafx.h" +#include "UIController.h" +#include "UI.h" +#include "UIScene.h" +#include "..\..\..\Minecraft.World\StringHelpers.h" +#include "..\..\LocalPlayer.h" +#include "..\..\DLCTexturePack.h" +#include "..\..\TexturePackRepository.h" +#include "..\..\Minecraft.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.entity.boss.enderdragon.h" +#include "..\..\EnderDragonRenderer.h" +#include "..\..\MultiPlayerLocalPlayer.h" +#include "UIFontData.h" +#ifdef __PSVITA__ +#include <message_dialog.h> +#endif + +// 4J Stu - Enable this to override the Iggy Allocator +//#define ENABLE_IGGY_ALLOCATOR +//#define EXCLUDE_IGGY_ALLOCATIONS_FROM_HEAP_INSPECTOR + +//#define ENABLE_IGGY_EXPLORER +#ifdef ENABLE_IGGY_EXPLORER +#include "Windows64\Iggy\include\iggyexpruntime.h" +#endif + +//#define ENABLE_IGGY_PERFMON +#ifdef ENABLE_IGGY_PERFMON + +#define PM_ORIGIN_X 24 +#define PM_ORIGIN_Y 34 + +#ifdef __ORBIS__ +#include "Orbis\Iggy\include\iggyperfmon.h" +#include "Orbis\Iggy\include\iggyperfmon_orbis.h" +#elif defined _DURANGO +#include "Durango\Iggy\include\iggyperfmon.h" +#elif defined __PS3__ +#include "PS3\Iggy\include\iggyperfmon.h" +#include "PS3\Iggy\include\iggyperfmon_ps3.h" +#elif defined __PSVITA__ +#include "PSVita\Iggy\include\iggyperfmon.h" +#include "PSVita\Iggy\include\iggyperfmon_psp2.h" +#elif defined __WINDOWS64 +#include "Windows64\Iggy\include\iggyperfmon.h" +#endif + +#endif + +CRITICAL_SECTION UIController::ms_reloadSkinCS; +bool UIController::ms_bReloadSkinCSInitialised = false; + +DWORD UIController::m_dwTrialTimerLimitSecs=DYNAMIC_CONFIG_DEFAULT_TRIAL_TIME; + +static void RADLINK WarningCallback(void *user_callback_data, Iggy *player, IggyResult code, const char *message) +{ + //enum IggyResult{ IGGY_RESULT_SUCCESS = 0, IGGY_RESULT_Warning_None = 0, + // IGGY_RESULT_Warning_Misc = 100, IGGY_RESULT_Warning_GDraw = 101, + // IGGY_RESULT_Warning_ProgramFlow = 102, + // IGGY_RESULT_Warning_Actionscript = 103, + // IGGY_RESULT_Warning_Graphics = 104, IGGY_RESULT_Warning_Font = 105, + // IGGY_RESULT_Warning_Timeline = 106, IGGY_RESULT_Warning_Library = 107, + // IGGY_RESULT_Warning_CannotSustainFrameRate = 201, + // IGGY_RESULT_Warning_ThrewException = 202, + // IGGY_RESULT_Error_Threshhold = 400, IGGY_RESULT_Error_Misc = 400, + // IGGY_RESULT_Error_GDraw = 401, IGGY_RESULT_Error_ProgramFlow = 402, + // IGGY_RESULT_Error_Actionscript = 403, IGGY_RESULT_Error_Graphics = 404, + // IGGY_RESULT_Error_Font = 405, IGGY_RESULT_Error_Create = 406, + // IGGY_RESULT_Error_Library = 407, IGGY_RESULT_Error_ValuePath = 408, + // IGGY_RESULT_Error_Audio = 409, IGGY_RESULT_Error_Internal = 499, + // IGGY_RESULT_Error_InvalidIggy = 501, + // IGGY_RESULT_Error_InvalidArgument = 502, + // IGGY_RESULT_Error_InvalidEntity = 503, + // IGGY_RESULT_Error_UndefinedEntity = 504, + // IGGY_RESULT_Error_OutOfMemory = 1001,}; + + switch(code) + { + case IGGY_RESULT_Warning_CannotSustainFrameRate: + // Ignore warning + break; + default: + /* Normally, we'd want to issue this warning to some kind of + logging system or error reporting system, but since this is a + tutorial app, we just use Win32's default error stream. Since + ActionScript 3 exceptions are routed through this warning + callback, it's definitely a good idea to make sure these + warnings get printed somewhere that's easy for you to read and + use for debugging, otherwise debugging errors in the + ActionScript 3 code in your Flash content will be very + difficult! */ + app.DebugPrintf(app.USER_SR, message); + app.DebugPrintf(app.USER_SR, "\n"); + break; + }; +} + + +/* Flash provides a way for ActionScript 3 code to print debug output +using a function called "trace". It's very useful for debugging +Flash programs, so ideally, when using Iggy, we'd like to see any +trace output alongside our own debugging output. To facilitate +this, Iggy allows us to install a callback that will be called +any time ActionScript code calls trace. */ +static void RADLINK TraceCallback(void *user_callback_data, Iggy *player, char const *utf8_string, S32 length_in_bytes) +{ + app.DebugPrintf(app.USER_UI, (char *)utf8_string); +} + +#ifdef ENABLE_IGGY_PERFMON +static void *RADLINK perf_malloc(void *handle, U32 size) +{ + return malloc(size); +} + +static void RADLINK perf_free(void *handle, void *ptr) +{ + return free(ptr); +} +#endif + +#ifdef EXCLUDE_IGGY_ALLOCATIONS_FROM_HEAP_INSPECTOR +extern "C" void *__real_malloc(size_t t); +extern "C" void __real_free(void *t); +#endif + +__int64 UIController::iggyAllocCount = 0; +static unordered_map<void *,size_t> allocations; +static void * RADLINK AllocateFunction ( void * alloc_callback_user_data , size_t size_requested , size_t * size_returned ) +{ + UIController *controller = (UIController *)alloc_callback_user_data; + EnterCriticalSection(&controller->m_Allocatorlock); +#ifdef EXCLUDE_IGGY_ALLOCATIONS_FROM_HEAP_INSPECTOR + void *alloc = __real_malloc(size_requested); +#else + void *alloc = malloc(size_requested); +#endif + *size_returned = size_requested; + UIController::iggyAllocCount += size_requested; + allocations[alloc] = size_requested; + app.DebugPrintf(app.USER_SR, "Allocating %d, new total: %d\n", size_requested, UIController::iggyAllocCount); + LeaveCriticalSection(&controller->m_Allocatorlock); + return alloc; +} + +static void RADLINK DeallocateFunction ( void * alloc_callback_user_data , void * ptr ) +{ + UIController *controller = (UIController *)alloc_callback_user_data; + EnterCriticalSection(&controller->m_Allocatorlock); + size_t size = allocations[ptr]; + UIController::iggyAllocCount -= size; + allocations.erase(ptr); + app.DebugPrintf(app.USER_SR, "Freeing %d, new total %d\n", size, UIController::iggyAllocCount); +#ifdef EXCLUDE_IGGY_ALLOCATIONS_FROM_HEAP_INSPECTOR + __real_free(ptr); +#else + free(ptr); +#endif + LeaveCriticalSection(&controller->m_Allocatorlock); +} + +UIController::UIController() +{ + m_uiDebugConsole = NULL; + m_reloadSkinThread = NULL; + m_navigateToHomeOnReload = false; + m_mcTTFFont= NULL; + m_moj7 = NULL; + m_moj11 = NULL; + +#ifdef ENABLE_IGGY_ALLOCATOR + InitializeCriticalSection(&m_Allocatorlock); +#endif + + // 4J Stu - This is a bit of a hack until we change the Minecraft initialisation to store the proper screen size for other platforms +#if defined _WINDOWS64 || defined _DURANGO || defined __ORBIS__ + m_fScreenWidth = 1920.0f; + m_fScreenHeight = 1080.0f; + m_bScreenWidthSetup = true; +#else + m_fScreenWidth = 1280.0f; + m_fScreenHeight = 720.0f; + m_bScreenWidthSetup = false; +#endif + + for(unsigned int i = 0; i < eLibrary_Count; ++i) + { + m_iggyLibraries[i] = IGGY_INVALID_LIBRARY; + } + + for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i) + { + m_bMenuDisplayed[i] = false; + m_iCountDown[i]=0; + m_bMenuToBeClosed[i]=false; + + for(unsigned int key = 0; key <= ACTION_MAX_MENU; ++key) + { + m_actionRepeatTimer[i][key] = 0; + } + } + + for(unsigned int i = 0; i < eUIGroup_COUNT; ++i) + { + m_bCloseAllScenes[i] = false; + } + + m_iPressStartQuadrantsMask = 0; + + m_currentRenderViewport = C4JRender::VIEWPORT_TYPE_FULLSCREEN; + m_bCustomRenderPosition = false; + m_winUserIndex = 0; + m_accumulatedTicks = 0; + + InitializeCriticalSection(&m_navigationLock); + InitializeCriticalSection(&m_registeredCallbackScenesCS); + //m_bSysUIShowing=false; + m_bSystemUIShowing=false; +#ifdef __PSVITA__ + m_bTouchscreenPressed=false; +#endif + + if(!ms_bReloadSkinCSInitialised) + { + // MGH - added to prevent crash loading Iggy movies while the skins were being reloaded + InitializeCriticalSection(&ms_reloadSkinCS); + ms_bReloadSkinCSInitialised = true; + } +} + +void UIController::SetSysUIShowing(bool bVal) +{ + if(bVal) app.DebugPrintf("System UI showing\n"); + else app.DebugPrintf("System UI stopped showing\n"); + m_bSystemUIShowing=bVal; +} + +void UIController::SetSystemUIShowing(LPVOID lpParam,bool bVal) +{ + UIController *pClass=(UIController *)lpParam; + pClass->SetSysUIShowing(bVal); +} + +// SETUP +void UIController::preInit(S32 width, S32 height) +{ + m_fScreenWidth = width; + m_fScreenHeight = height; + m_bScreenWidthSetup = true; + +#ifdef ENABLE_IGGY_ALLOCATOR + IggyAllocator allocator; + allocator.user_callback_data = this; + allocator.mem_alloc = &AllocateFunction; + allocator.mem_free = &DeallocateFunction; + IggyInit(&allocator); +#else + IggyInit(0); +#endif + + IggySetWarningCallback(WarningCallback, 0); + IggySetTraceCallbackUTF8(TraceCallback, 0); + + setFontCachingCalculationBuffer(-1); +} + +void UIController::postInit() +{ + // set up a custom rendering callback + IggySetCustomDrawCallback(&UIController::CustomDrawCallback, this); + IggySetAS3ExternalFunctionCallbackUTF16 ( &UIController::ExternalFunctionCallback, this ); + IggySetTextureSubstitutionCallbacks ( &UIController::TextureSubstitutionCreateCallback , &UIController::TextureSubstitutionDestroyCallback, this ); + + SetupFont(); + // + loadSkins(); + + for(unsigned int i = 0; i < eUIGroup_COUNT; ++i) + { + m_groups[i] = new UIGroup((EUIGroup)i,i-1); + } + + +#ifdef ENABLE_IGGY_EXPLORER + iggy_explorer = IggyExpCreate("127.0.0.1", 9190, malloc(IGGYEXP_MIN_STORAGE), IGGYEXP_MIN_STORAGE); + if ( iggy_explorer == NULL ) + { + // not normally an error, just an error for this demo! + app.DebugPrintf( "Couldn't connect to Iggy Explorer, did you run it first?" ); + } + else + { + IggyUseExplorer( m_groups[1]->getHUD()->getMovie(), iggy_explorer); + } +#endif + +#ifdef ENABLE_IGGY_PERFMON + m_iggyPerfmonEnabled = false; + iggy_perfmon = IggyPerfmonCreate(perf_malloc, perf_free, NULL); + IggyInstallPerfmon(iggy_perfmon); +#endif + + NavigateToScene(0, eUIScene_Intro); +} + +void UIController::SetupFont() +{ + bool bBitmapFont=false; + + if(m_mcTTFFont!=NULL) + { + delete m_mcTTFFont; + } + + switch(XGetLanguage()) + { +#if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__) + case XC_LANGUAGE_JAPANESE: + m_mcTTFFont = new UITTFFont("Common/Media/font/JPN/DF-DotDotGothic16.ttf", 0x203B); // JPN + break; + case XC_LANGUAGE_SCHINESE: //TODO + case XC_LANGUAGE_TCHINESE: + m_mcTTFFont = new UITTFFont("Common/Media/font/CHT/DFTT_R5.TTC", 0x203B); // CHT + break; + case XC_LANGUAGE_KOREAN: + m_mcTTFFont = new UITTFFont("Common/Media/font/KOR/candadite2.ttf", 0x203B); // KOR + break; + // 4J-JEV, Cyrillic characters have been added to this font now, (4/July/14) + //case XC_LANGUAGE_RUSSIAN: + //case XC_LANGUAGE_GREEK: +#else + case XC_LANGUAGE_JAPANESE: + m_mcTTFFont = new UITTFFont("Common/Media/font/JPN/DFGMaruGothic-Md.ttf", 0x2022); // JPN + break; + case XC_LANGUAGE_SCHINESE: //TODO + case XC_LANGUAGE_TCHINESE: + m_mcTTFFont = new UITTFFont("Common/Media/font/CHT/DFHeiMedium-B5.ttf", 0x2022); // CHT + break; + case XC_LANGUAGE_KOREAN: + m_mcTTFFont = new UITTFFont("Common/Media/font/KOR/BOKMSD.ttf", 0x2022); // KOR + break; +#endif + default: + bBitmapFont=true; + // m_mcTTFFont = new UITTFFont("Common/Media/font/Mojangles.ttf", 0x2022); // 4J-JEV: Shouldn't be using this. + break; + } + + if(bBitmapFont) + { + // these may have been set up by a previous language being chosen + if(m_moj7==NULL) + { + m_moj7 = new UIBitmapFont(SFontData::Mojangles_7); + m_moj7->registerFont(); + } + if(m_moj11==NULL) + { + m_moj11 = new UIBitmapFont(SFontData::Mojangles_11); + m_moj11->registerFont(); + } + } + else + { + app.DebugPrintf("IggyFontSetIndirectUTF8\n"); + IggyFontSetIndirectUTF8( "Mojangles7", -1, IGGY_FONTFLAG_all, "Mojangles_TTF",-1 ,IGGY_FONTFLAG_none ); + IggyFontSetIndirectUTF8( "Mojangles11", -1, IGGY_FONTFLAG_all, "Mojangles_TTF",-1 ,IGGY_FONTFLAG_none ); + } +} + +// TICKING +void UIController::tick() +{ + if(m_navigateToHomeOnReload && !ui.IsReloadingSkin()) + { + ui.CleanUpSkinReload(); + m_navigateToHomeOnReload = false; + ui.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_MainMenu); + } + + for(unsigned int i = 0; i < eUIGroup_COUNT; ++i) + { + if(m_bCloseAllScenes[i]) + { + m_groups[i]->closeAllScenes(); + m_groups[i]->getTooltips()->SetTooltips(-1); + m_bCloseAllScenes[i] = false; + } + } + + if(m_accumulatedTicks == 0) tickInput(); + m_accumulatedTicks = 0; + + for(unsigned int i = 0; i < eUIGroup_COUNT; ++i) + { + m_groups[i]->tick(); + + // TODO: May wish to skip ticking other groups here + } + + // Fix for HUD ticks so that they all tick before this reference is cleared + EnderDragonRenderer::bossInstance = nullptr; + + // Clear out the cached movie file data + __int64 currentTime = System::currentTimeMillis(); + for(AUTO_VAR(it, m_cachedMovieData.begin()); it != m_cachedMovieData.end();) + { + if(it->second.m_expiry < currentTime) + { + delete [] it->second.m_ba.data; + it = m_cachedMovieData.erase(it); + } + else + { + ++it; + } + } +} + +void UIController::loadSkins() +{ + wstring platformSkinPath = L""; + +#ifdef __PS3__ + platformSkinPath = L"skinPS3.swf"; +#elif defined __PSVITA__ + platformSkinPath = L"skinVita.swf"; +#elif defined _WINDOWS64 + if(m_fScreenHeight==1080.0f) + { + platformSkinPath = L"skinHDWin.swf"; + } + else + { + platformSkinPath = L"skinWin.swf"; + } +#elif defined _DURANGO + if(m_fScreenHeight==1080.0f) + { + platformSkinPath = L"skinHDDurango.swf"; + } + else + { + platformSkinPath = L"skinDurango.swf"; + } +#elif defined __ORBIS__ + if(m_fScreenHeight==1080.0f) + { + platformSkinPath = L"skinHDOrbis.swf"; + } + else + { + platformSkinPath = L"skinOrbis.swf"; + } + +#endif + // Every platform has one of these, so nothing shared + if(m_fScreenHeight==1080.0f) + { + m_iggyLibraries[eLibrary_Platform] = loadSkin(platformSkinPath, L"platformskinHD.swf"); + } + else + { + m_iggyLibraries[eLibrary_Platform] = loadSkin(platformSkinPath, L"platformskin.swf"); + } + +#if defined(__PS3__) || defined(__PSVITA__) + m_iggyLibraries[eLibrary_GraphicsDefault] = loadSkin(L"skinGraphics.swf", L"skinGraphics.swf"); + m_iggyLibraries[eLibrary_GraphicsHUD] = loadSkin(L"skinGraphicsHud.swf", L"skinGraphicsHud.swf"); + m_iggyLibraries[eLibrary_GraphicsInGame] = loadSkin(L"skinGraphicsInGame.swf", L"skinGraphicsInGame.swf"); + m_iggyLibraries[eLibrary_GraphicsTooltips] = loadSkin(L"skinGraphicsTooltips.swf", L"skinGraphicsTooltips.swf"); + m_iggyLibraries[eLibrary_GraphicsLabels] = loadSkin(L"skinGraphicsLabels.swf", L"skinGraphicsLabels.swf"); + m_iggyLibraries[eLibrary_Labels] = loadSkin(L"skinLabels.swf", L"skinLabels.swf"); + m_iggyLibraries[eLibrary_InGame] = loadSkin(L"skinInGame.swf", L"skinInGame.swf"); + m_iggyLibraries[eLibrary_HUD] = loadSkin(L"skinHud.swf", L"skinHud.swf"); + m_iggyLibraries[eLibrary_Tooltips] = loadSkin(L"skinTooltips.swf", L"skinTooltips.swf"); + m_iggyLibraries[eLibrary_Default] = loadSkin(L"skin.swf", L"skin.swf"); +#endif + +#if ( defined(_WINDOWS64) || defined(_DURANGO) || defined(__ORBIS__) ) + +#if defined(_WINDOWS64) + // 4J Stu - Load the 720/480 skins so that we have something to fallback on during development +#ifndef _FINAL_BUILD + m_iggyLibraries[eLibraryFallback_GraphicsDefault] = loadSkin(L"skinGraphics.swf", L"skinGraphics.swf"); + m_iggyLibraries[eLibraryFallback_GraphicsHUD] = loadSkin(L"skinGraphicsHud.swf", L"skinGraphicsHud.swf"); + m_iggyLibraries[eLibraryFallback_GraphicsInGame] = loadSkin(L"skinGraphicsInGame.swf", L"skinGraphicsInGame.swf"); + m_iggyLibraries[eLibraryFallback_GraphicsTooltips] = loadSkin(L"skinGraphicsTooltips.swf", L"skinGraphicsTooltips.swf"); + m_iggyLibraries[eLibraryFallback_GraphicsLabels] = loadSkin(L"skinGraphicsLabels.swf", L"skinGraphicsLabels.swf"); + m_iggyLibraries[eLibraryFallback_Labels] = loadSkin(L"skinLabels.swf", L"skinLabels.swf"); + m_iggyLibraries[eLibraryFallback_InGame] = loadSkin(L"skinInGame.swf", L"skinInGame.swf"); + m_iggyLibraries[eLibraryFallback_HUD] = loadSkin(L"skinHud.swf", L"skinHud.swf"); + m_iggyLibraries[eLibraryFallback_Tooltips] = loadSkin(L"skinTooltips.swf", L"skinTooltips.swf"); + m_iggyLibraries[eLibraryFallback_Default] = loadSkin(L"skin.swf", L"skin.swf"); +#endif +#endif + + m_iggyLibraries[eLibrary_GraphicsDefault] = loadSkin(L"skinHDGraphics.swf", L"skinHDGraphics.swf"); + m_iggyLibraries[eLibrary_GraphicsHUD] = loadSkin(L"skinHDGraphicsHud.swf", L"skinHDGraphicsHud.swf"); + m_iggyLibraries[eLibrary_GraphicsInGame] = loadSkin(L"skinHDGraphicsInGame.swf", L"skinHDGraphicsInGame.swf"); + m_iggyLibraries[eLibrary_GraphicsTooltips] = loadSkin(L"skinHDGraphicsTooltips.swf", L"skinHDGraphicsTooltips.swf"); + m_iggyLibraries[eLibrary_GraphicsLabels] = loadSkin(L"skinHDGraphicsLabels.swf", L"skinHDGraphicsLabels.swf"); + m_iggyLibraries[eLibrary_Labels] = loadSkin(L"skinHDLabels.swf", L"skinHDLabels.swf"); + m_iggyLibraries[eLibrary_InGame] = loadSkin(L"skinHDInGame.swf", L"skinHDInGame.swf"); + m_iggyLibraries[eLibrary_HUD] = loadSkin(L"skinHDHud.swf", L"skinHDHud.swf"); + m_iggyLibraries[eLibrary_Tooltips] = loadSkin(L"skinHDTooltips.swf", L"skinHDTooltips.swf"); + m_iggyLibraries[eLibrary_Default] = loadSkin(L"skinHD.swf", L"skinHD.swf"); +#endif // HD platforms +} + +IggyLibrary UIController::loadSkin(const wstring &skinPath, const wstring &skinName) +{ + IggyLibrary lib = IGGY_INVALID_LIBRARY; + // 4J Stu - We need to load the platformskin before the normal skin, as the normal skin requires some elements from the platform skin + if(!skinPath.empty() && app.hasArchiveFile(skinPath)) + { + byteArray baFile = app.getArchiveFile(skinPath); + lib = IggyLibraryCreateFromMemoryUTF16( (IggyUTF16 *)skinName.c_str() , (void *)baFile.data, baFile.length, NULL ); + + delete[] baFile.data; +#ifdef _DEBUG + IggyMemoryUseInfo memoryInfo; + rrbool res; + int iteration = 0; + __int64 totalStatic = 0; + while(res = IggyDebugGetMemoryUseInfo ( NULL , + lib , + "" , + 0 , + iteration , + &memoryInfo )) + { + totalStatic += memoryInfo.static_allocation_bytes; + app.DebugPrintf(app.USER_SR, "%ls - %.*s, static: %dB, dynamic: %dB\n", skinPath.c_str(), memoryInfo.subcategory_stringlen, memoryInfo.subcategory, memoryInfo.static_allocation_bytes, memoryInfo.dynamic_allocation_bytes); + ++iteration; + } + + app.DebugPrintf(app.USER_SR, "%ls - Total static: %dB (%dKB)\n", skinPath.c_str(), totalStatic, totalStatic/1024); +#endif + } + return lib; +} + +void UIController::ReloadSkin() +{ + // Destroy all scene swf + for(unsigned int i = 0; i < eUIGroup_COUNT; ++i) + { + //m_bCloseAllScenes[i] = true; + m_groups[i]->DestroyAll(); + } + + // Unload the current libraries + // Some libraries reference others, so we destroy in reverse order + for(int i = eLibrary_Count - 1; i >= 0; --i) + { + if(m_iggyLibraries[i] != IGGY_INVALID_LIBRARY) IggyLibraryDestroy(m_iggyLibraries[i]); + m_iggyLibraries[i] = IGGY_INVALID_LIBRARY; + } + +#ifdef _WINDOWS64 + // 4J Stu - Don't load on a thread on windows. I haven't investigated this in detail, so a quick fix + reloadSkinThreadProc(this); +#else + // Navigate to the timer scene so that we can display something while the loading is happening + ui.NavigateToScene(0,eUIScene_Timer,(void *)1,eUILayer_Tooltips,eUIGroup_Fullscreen); + + m_reloadSkinThread = new C4JThread(reloadSkinThreadProc, (void*)this, "Reload skin thread"); + m_reloadSkinThread->SetProcessor(CPU_CORE_UI_SCENE); + //m_reloadSkinThread->Run(); + + //// Load new skin + //loadSkins(); + + //// Reload all scene swf + //for(int i = eUIGroup_Player1; i <= eUIGroup_Player4; ++i) + //{ + // m_groups[i]->ReloadAll(); + //} + + //// Always reload the fullscreen group + //m_groups[eUIGroup_Fullscreen]->ReloadAll(); +#endif +} + +void UIController::StartReloadSkinThread() +{ + if(m_reloadSkinThread) m_reloadSkinThread->Run(); +} + +int UIController::reloadSkinThreadProc(void* lpParam) +{ + EnterCriticalSection(&ms_reloadSkinCS); // MGH - added to prevent crash loading Iggy movies while the skins were being reloaded + UIController *controller = (UIController *)lpParam; + // Load new skin + controller->loadSkins(); + + // Reload all scene swf + for(int i = eUIGroup_Player1; i < eUIGroup_COUNT; ++i) + { + controller->m_groups[i]->ReloadAll(); + } + + // Always reload the fullscreen group + controller->m_groups[eUIGroup_Fullscreen]->ReloadAll(); + + // 4J Stu - Don't do this on windows, as we never navigated forwards to start with +#ifndef _WINDOW64 + controller->NavigateBack(0, false, eUIScene_COUNT, eUILayer_Tooltips); +#endif + LeaveCriticalSection(&ms_reloadSkinCS); + + return 0; +} + +bool UIController::IsReloadingSkin() +{ + return m_reloadSkinThread && (!m_reloadSkinThread->hasStarted() || m_reloadSkinThread->isRunning()); +} + +bool UIController::IsExpectingOrReloadingSkin() +{ + return Minecraft::GetInstance()->skins->getSelected()->isLoadingData() || Minecraft::GetInstance()->skins->needsUIUpdate() || IsReloadingSkin(); +} + +void UIController::CleanUpSkinReload() +{ + delete m_reloadSkinThread; + m_reloadSkinThread = NULL; + + if(!Minecraft::GetInstance()->skins->isUsingDefaultSkin()) + { + if(!Minecraft::GetInstance()->skins->getSelected()->hasAudio()) + { +#ifdef _DURANGO + DWORD result = StorageManager.UnmountInstalledDLC(L"TPACK"); +#else + DWORD result = StorageManager.UnmountInstalledDLC("TPACK"); +#endif + } + } + + for(AUTO_VAR(it,m_queuedMessageBoxData.begin()); it != m_queuedMessageBoxData.end(); ++it) + { + QueuedMessageBoxData *queuedData = *it; + ui.NavigateToScene(queuedData->iPad, eUIScene_MessageBox, &queuedData->info, queuedData->layer, eUIGroup_Fullscreen); + delete queuedData->info.uiOptionA; + delete queuedData; + } + m_queuedMessageBoxData.clear(); +} + +byteArray UIController::getMovieData(const wstring &filename) +{ + // Cache everything we load in the current tick + __int64 targetTime = System::currentTimeMillis() + (1000LL * 60); + AUTO_VAR(it,m_cachedMovieData.find(filename)); + if(it == m_cachedMovieData.end() ) + { + byteArray baFile = app.getArchiveFile(filename); + CachedMovieData cmd; + cmd.m_ba = baFile; + cmd.m_expiry = targetTime; + m_cachedMovieData[filename] = cmd; + return baFile; + } + else + { + it->second.m_expiry = targetTime; + return it->second.m_ba; + } +} + +// INPUT +void UIController::tickInput() +{ + // If system/commerce UI up, don't handle input + //if(!m_bSysUIShowing && !m_bSystemUIShowing) + if(!m_bSystemUIShowing) + { +#ifdef ENABLE_IGGY_PERFMON + if (m_iggyPerfmonEnabled) + { + if(InputManager.ButtonPressed(ProfileManager.GetPrimaryPad(), ACTION_MENU_STICK_PRESS)) m_iggyPerfmonEnabled = !m_iggyPerfmonEnabled; + } + else +#endif + { + handleInput(); + ++m_accumulatedTicks; + } + } +} + +void UIController::handleInput() +{ + // For each user, loop over each key type and send messages based on the state + for(unsigned int iPad = 0; iPad < XUSER_MAX_COUNT; ++iPad) + { +#ifdef _DURANGO + // 4J-JEV: Added exception for primary play who migh've uttered speech commands. + if(iPad != ProfileManager.GetPrimaryPad() + && (!InputManager.IsPadConnected(iPad) || !InputManager.IsPadLocked(iPad)) ) continue; +#endif + for(unsigned int key = 0; key <= ACTION_MAX_MENU; ++key) + { + handleKeyPress(iPad, key); + } + +#ifdef __PSVITA__ + //CD - Vita requires key press 40 - select [MINECRAFT_ACTION_GAME_INFO] + handleKeyPress(iPad, MINECRAFT_ACTION_GAME_INFO); +#endif + } + +#ifdef _DURANGO + if(!app.GetGameStarted()) + { + bool repeat = false; + int firstUnfocussedUnhandledPad = -1; + + // For durango, check for unmapped controllers + for(unsigned int iPad = XUSER_MAX_COUNT; iPad < (XUSER_MAX_COUNT + InputManager.MAX_GAMEPADS); ++iPad) + { + if(InputManager.IsPadLocked(iPad) || !InputManager.IsPadConnected(iPad) ) continue; + + for(unsigned int key = 0; key <= ACTION_MAX_MENU; ++key) + { + + bool pressed = InputManager.ButtonPressed(iPad,key); // Toggle + bool released = InputManager.ButtonReleased(iPad,key); // Toggle + + if(pressed || released) + { + bool handled = false; + + // Send the key to the fullscreen group first + m_groups[(int)eUIGroup_Fullscreen]->handleInput(iPad, key, repeat, pressed, released, handled); + + if(firstUnfocussedUnhandledPad < 0 && !m_groups[(int)eUIGroup_Fullscreen]->HasFocus(iPad)) + { + firstUnfocussedUnhandledPad = iPad; + } + } + } + } + + if(ProfileManager.GetLockedProfile() >= 0 && !InputManager.IsPadLocked( ProfileManager.GetLockedProfile() ) && firstUnfocussedUnhandledPad >= 0) + { + ProfileManager.RequestSignInUI(false, false, false, false, true, NULL, NULL, firstUnfocussedUnhandledPad ); + } + } +#endif +} + +void UIController::handleKeyPress(unsigned int iPad, unsigned int key) +{ + + bool down = false; + bool pressed = false; // Toggle + bool released = false; // Toggle + bool repeat = false; + +#ifdef __PSVITA__ + if(key==ACTION_MENU_OK) + { + bool bTouchScreenInput=false; + + // check the touchscreen + + // 4J-PB - use the touchscreen for quickselect + SceTouchData* pTouchData = InputManager.GetTouchPadData(iPad,false); + + if((m_bTouchscreenPressed==false) && pTouchData->reportNum==1) + { + // no active touch? clear active and highlighted touch UI elements + m_ActiveUIElement = NULL; + m_HighlightedUIElement = NULL; + + // fullscreen first + UIScene *pScene=m_groups[(int)eUIGroup_Fullscreen]->getCurrentScene(); + // also check tooltip scene if we're not touching anything in the main scene + UIScene *pToolTips=m_groups[(int)eUIGroup_Fullscreen]->getTooltips(); + if(pScene) + { + // scene touch check + if(TouchBoxHit(pScene,pTouchData->report[0].x,pTouchData->report[0].y)) + { + down=pressed=m_bTouchscreenPressed=true; + bTouchScreenInput=true; + } + // tooltip touch check + else if(TouchBoxHit(pToolTips,pTouchData->report[0].x,pTouchData->report[0].y)) + { + down=pressed=m_bTouchscreenPressed=true; + bTouchScreenInput=true; + } + } + else + { + pScene=m_groups[(EUIGroup)(iPad+1)]->getCurrentScene(); + pToolTips=m_groups[(int)iPad+1]->getTooltips(); + if(pScene) + { + // scene touch check + if(TouchBoxHit(pScene,pTouchData->report[0].x,pTouchData->report[0].y)) + { + down=pressed=m_bTouchscreenPressed=true; + bTouchScreenInput=true; + } + // tooltip touch check (if scene exists but not component has been touched) + else if(TouchBoxHit(pToolTips,pTouchData->report[0].x,pTouchData->report[0].y)) + { + down=pressed=m_bTouchscreenPressed=true; + bTouchScreenInput=true; + } + } + else if(pToolTips) + { + // tooltip touch check (if scene does not exist) + if(TouchBoxHit(pToolTips,pTouchData->report[0].x,pTouchData->report[0].y)) + { + down=pressed=m_bTouchscreenPressed=true; + bTouchScreenInput=true; + } + } + } + } + else if(m_bTouchscreenPressed && pTouchData->reportNum==1) + { + // fullscreen first + UIScene *pScene=m_groups[(int)eUIGroup_Fullscreen]->getCurrentScene(); + // also check tooltip scene if we're not touching anything in the main scene + UIScene *pToolTips=m_groups[(int)eUIGroup_Fullscreen]->getTooltips(); + if(pScene) + { + // scene touch check + if(TouchBoxHit(pScene,pTouchData->report[0].x,pTouchData->report[0].y)) + { + down=true; + bTouchScreenInput=true; + } + // tooltip touch check (if scene exists but not component has been touched) + else if(TouchBoxHit(pToolTips,pTouchData->report[0].x,pTouchData->report[0].y)) + { + down=true; + bTouchScreenInput=true; + } + } + else + { + pScene=m_groups[(EUIGroup)(iPad+1)]->getCurrentScene(); + pToolTips=m_groups[(int)iPad+1]->getTooltips(); + if(pScene) + { + // scene touch check + if(TouchBoxHit(pScene,pTouchData->report[0].x,pTouchData->report[0].y)) + { + down=true; + bTouchScreenInput=true; + } + // tooltip touch check (if scene exists but not component has been touched) + else if(TouchBoxHit(pToolTips,pTouchData->report[0].x,pTouchData->report[0].y)) + { + down=true; + bTouchScreenInput=true; + } + } + else if(pToolTips) + { + // tooltip touch check (if scene does not exist) + if(TouchBoxHit(pToolTips,pTouchData->report[0].x,pTouchData->report[0].y)) + { + down=true; + bTouchScreenInput=true; + } + } + } + } + else if(m_bTouchscreenPressed && pTouchData->reportNum==0) + { + // released + bTouchScreenInput=true; + m_bTouchscreenPressed=false; + released=true; + } + + if(pressed) + { + // Start repeat timer + m_actionRepeatTimer[iPad][key] = GetTickCount() + UI_REPEAT_KEY_DELAY_MS; + } + else if (released) + { + // Stop repeat timer + m_actionRepeatTimer[iPad][key] = 0; + } + else if (down) + { + // Check is enough time has elapsed to be a repeat key + DWORD currentTime = GetTickCount(); + if(m_actionRepeatTimer[iPad][key] > 0 && currentTime > m_actionRepeatTimer[iPad][key]) + { + repeat = true; + pressed = true; + m_actionRepeatTimer[iPad][key] = currentTime + UI_REPEAT_KEY_REPEAT_RATE_MS; + } + } + + // handle touch input + HandleTouchInput(iPad, key, pressed, repeat, released); + + // ignore any other presses if the touchscreen has been used + if(bTouchScreenInput) return; + } +#endif + + down = InputManager.ButtonDown(iPad,key); + pressed = InputManager.ButtonPressed(iPad,key); // Toggle + released = InputManager.ButtonReleased(iPad,key); // Toggle + + if(pressed) app.DebugPrintf("Pressed %d\n",key); + if(released) app.DebugPrintf("Released %d\n",key); + // Repeat handling + if(pressed) + { + // Start repeat timer + m_actionRepeatTimer[iPad][key] = GetTickCount() + UI_REPEAT_KEY_DELAY_MS; + } + else if (released) + { + // Stop repeat timer + m_actionRepeatTimer[iPad][key] = 0; + } + else if (down) + { + // Check is enough time has elapsed to be a repeat key + DWORD currentTime = GetTickCount(); + if(m_actionRepeatTimer[iPad][key] > 0 && currentTime > m_actionRepeatTimer[iPad][key]) + { + repeat = true; + pressed = true; + m_actionRepeatTimer[iPad][key] = currentTime + UI_REPEAT_KEY_REPEAT_RATE_MS; + } + } + +#ifndef _CONTENT_PACKAGE + +#ifdef ENABLE_IGGY_PERFMON + if ( pressed && !repeat && key == ACTION_MENU_STICK_PRESS) + { + m_iggyPerfmonEnabled = !m_iggyPerfmonEnabled; + } +#endif + + // 4J Stu - Removed this function +#if 0 +#ifdef __PS3__ + //if ( pressed && + // !repeat && + // //app.GetGameSettingsDebugMask(ProfileManager.GetPrimaryPad())&(1L<<eDebugSetting_ToggleFont) && + // key == ACTION_MENU_STICK_PRESS) + //{ + // static bool whichFont = true; + // if (whichFont) + // { + // IggyFontSetIndirectUTF8( "Mojangles_7", -1, IGGY_FONTFLAG_all, "Mojangles_TTF",-1 ,IGGY_FONTFLAG_none ); + // IggyFontSetIndirectUTF8( "Mojangles_11", -1, IGGY_FONTFLAG_all, "Mojangles_TTF",-1 ,IGGY_FONTFLAG_none ); + // whichFont = false; + // } + // else + // { + // IggyFontSetIndirectUTF8( "Mojangles_7", -1, IGGY_FONTFLAG_all, "Mojangles_7",-1 ,IGGY_FONTFLAG_none ); + // IggyFontSetIndirectUTF8( "Mojangles_11", -1, IGGY_FONTFLAG_all, "Mojangles_11",-1 ,IGGY_FONTFLAG_none ); + // whichFont = true; + // } + //} + //else + if ( pressed && + !repeat && + //!(app.GetGameSettingsDebugMask(ProfileManager.GetPrimaryPad())&(1L<<eDebugSetting_ToggleFont)) && + key == ACTION_MENU_STICK_PRESS) + { + __int64 totalStatic = 0; + __int64 totalDynamic = 0; + app.DebugPrintf(app.USER_SR, "********************************\n"); + app.DebugPrintf(app.USER_SR, "BEGIN TOTAL SWF MEMORY USAGE\n\n"); + for(unsigned int i = 0; i < eUIGroup_COUNT; ++i) + { + m_groups[i]->PrintTotalMemoryUsage(totalStatic, totalDynamic); + } + for(unsigned int i = 0; i < eLibrary_Count; ++i) + { + __int64 libraryStatic = 0; + __int64 libraryDynamic = 0; + + if(m_iggyLibraries[i] != IGGY_INVALID_LIBRARY) + { + + IggyMemoryUseInfo memoryInfo; + rrbool res; + int iteration = 0; + while(res = IggyDebugGetMemoryUseInfo ( NULL , + m_iggyLibraries[i] , + "" , + 0 , + iteration , + &memoryInfo )) + { + libraryStatic += memoryInfo.static_allocation_bytes; + libraryDynamic += memoryInfo.dynamic_allocation_bytes; + totalStatic += memoryInfo.static_allocation_bytes; + totalDynamic += memoryInfo.dynamic_allocation_bytes; + ++iteration; + } + } + + app.DebugPrintf(app.USER_SR, "Library static: %dB , Library dynamic: %d, ID: %d\n", libraryStatic, libraryDynamic, i); + } + app.DebugPrintf(app.USER_SR, "Total static: %d , Total dynamic: %d\n", totalStatic, totalDynamic); + app.DebugPrintf(app.USER_SR, "\n\nEND TOTAL SWF MEMORY USAGE\n"); + app.DebugPrintf(app.USER_SR, "********************************\n\n"); + } + else +#endif +#endif +#endif + //#endif + if(repeat || pressed || released) + { + bool handled = false; + + // Send the key to the fullscreen group first + m_groups[(int)eUIGroup_Fullscreen]->handleInput(iPad, key, repeat, pressed, released, handled); + if(!handled) + { + // If it's not been handled yet, then pass the event onto the players specific group + m_groups[(iPad+1)]->handleInput(iPad, key, repeat, pressed, released, handled); + } + } +} + +rrbool RADLINK UIController::ExternalFunctionCallback( void * user_callback_data , Iggy * player , IggyExternalFunctionCallUTF16 * call) +{ + UIScene *scene = (UIScene *)IggyPlayerGetUserdata(player); + + if(scene != NULL) + { + scene->externalCallback(call); + } + + return true; +} + +// RENDERING +void UIController::renderScenes() +{ + PIXBeginNamedEvent(0, "Rendering Iggy scenes"); + // Only render player scenes if the game is started + if(app.GetGameStarted() && !m_groups[eUIGroup_Fullscreen]->hidesLowerScenes()) + { + for(int i = eUIGroup_Player1; i < eUIGroup_COUNT; ++i) + { + PIXBeginNamedEvent(0, "Rendering layer %d scenes", i); + m_groups[i]->render(); + PIXEndNamedEvent(); + } + } + + // Always render the fullscreen group + PIXBeginNamedEvent(0, "Rendering fullscreen scenes"); + m_groups[eUIGroup_Fullscreen]->render(); + PIXEndNamedEvent(); + + PIXEndNamedEvent(); + +#ifdef ENABLE_IGGY_PERFMON + if (m_iggyPerfmonEnabled) + { + IggyPerfmonPad pm_pad; + + pm_pad.bits = 0; + pm_pad.field.dpad_up = InputManager.ButtonPressed(ProfileManager.GetPrimaryPad(),ACTION_MENU_UP); + pm_pad.field.dpad_down = InputManager.ButtonPressed(ProfileManager.GetPrimaryPad(),ACTION_MENU_DOWN); + pm_pad.field.dpad_left = InputManager.ButtonPressed(ProfileManager.GetPrimaryPad(),ACTION_MENU_LEFT); + pm_pad.field.dpad_right = InputManager.ButtonPressed(ProfileManager.GetPrimaryPad(),ACTION_MENU_RIGHT); + pm_pad.field.button_up = InputManager.ButtonPressed(ProfileManager.GetPrimaryPad(),ACTION_MENU_Y); + pm_pad.field.button_down = InputManager.ButtonPressed(ProfileManager.GetPrimaryPad(),ACTION_MENU_A); + pm_pad.field.button_left = InputManager.ButtonPressed(ProfileManager.GetPrimaryPad(),ACTION_MENU_X); + pm_pad.field.button_right = InputManager.ButtonPressed(ProfileManager.GetPrimaryPad(),ACTION_MENU_B); + pm_pad.field.shoulder_left_hi = InputManager.ButtonPressed(ProfileManager.GetPrimaryPad(),ACTION_MENU_LEFT_SCROLL); + pm_pad.field.shoulder_right_hi = InputManager.ButtonPressed(ProfileManager.GetPrimaryPad(),ACTION_MENU_RIGHT_SCROLL); + pm_pad.field.trigger_left_low = InputManager.ButtonPressed(ProfileManager.GetPrimaryPad(),ACTION_MENU_PAGEUP); + pm_pad.field.trigger_right_low = InputManager.ButtonPressed(ProfileManager.GetPrimaryPad(),ACTION_MENU_PAGEDOWN); + //IggyPerfmonPadFromXInputStatePointer(pm_pad, &xi_pad); + + //gdraw_D3D_SetTileOrigin( fb, + // zb, + // PM_ORIGIN_X, + // PM_ORIGIN_Y ); + IggyPerfmonTickAndDraw(iggy_perfmon, gdraw_funcs, &pm_pad, + PM_ORIGIN_X, PM_ORIGIN_Y, getScreenWidth(), getScreenHeight()); // perfmon draw area in window coords + } +#endif +} + +void UIController::getRenderDimensions(C4JRender::eViewportType viewport, S32 &width, S32 &height) +{ + switch( viewport ) + { + case C4JRender::VIEWPORT_TYPE_FULLSCREEN: + width = (S32)(getScreenWidth()); + height = (S32)(getScreenHeight()); + break; + case C4JRender::VIEWPORT_TYPE_SPLIT_TOP: + case C4JRender::VIEWPORT_TYPE_SPLIT_BOTTOM: + width = (S32)(getScreenWidth() / 2); + height = (S32)(getScreenHeight() / 2); + break; + case C4JRender::VIEWPORT_TYPE_SPLIT_LEFT: + case C4JRender::VIEWPORT_TYPE_SPLIT_RIGHT: + width = (S32)(getScreenWidth() / 2); + height = (S32)(getScreenHeight() / 2); + break; + case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_LEFT: + case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_RIGHT: + case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_LEFT: + case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_RIGHT: + width = (S32)(getScreenWidth() / 2); + height = (S32)(getScreenHeight() / 2); + break; + } +} + +void UIController::setupRenderPosition(C4JRender::eViewportType viewport) +{ + if(m_bCustomRenderPosition || m_currentRenderViewport != viewport) + { + m_currentRenderViewport = viewport; + m_bCustomRenderPosition = false; + S32 xPos = 0; + S32 yPos = 0; + switch( viewport ) + { + case C4JRender::VIEWPORT_TYPE_SPLIT_TOP: + xPos = (S32)(getScreenWidth() / 4); + break; + case C4JRender::VIEWPORT_TYPE_SPLIT_BOTTOM: + xPos = (S32)(getScreenWidth() / 4); + yPos = (S32)(getScreenHeight() / 2); + break; + case C4JRender::VIEWPORT_TYPE_SPLIT_LEFT: + yPos = (S32)(getScreenHeight() / 4); + break; + case C4JRender::VIEWPORT_TYPE_SPLIT_RIGHT: + xPos = (S32)(getScreenWidth() / 2); + yPos = (S32)(getScreenHeight() / 4); + break; + case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_LEFT: + break; + case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_RIGHT: + xPos = (S32)(getScreenWidth() / 2); + break; + case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_LEFT: + yPos = (S32)(getScreenHeight() / 2); + break; + case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_RIGHT: + xPos = (S32)(getScreenWidth() / 2); + yPos = (S32)(getScreenHeight() / 2); + break; + } + m_tileOriginX = xPos; + m_tileOriginY = yPos; + setTileOrigin(xPos, yPos); + } +} + +void UIController::setupRenderPosition(S32 xOrigin, S32 yOrigin) +{ + m_bCustomRenderPosition = true; + m_tileOriginX = xOrigin; + m_tileOriginY = yOrigin; + setTileOrigin(xOrigin, yOrigin); +} + +void UIController::setupCustomDrawGameState() +{ + // Rest the clear rect + m_customRenderingClearRect.left = LONG_MAX; + m_customRenderingClearRect.right = LONG_MIN; + m_customRenderingClearRect.top = LONG_MAX; + m_customRenderingClearRect.bottom = LONG_MIN; + +#if defined _WINDOWS64 || _DURANGO + PIXBeginNamedEvent(0,"StartFrame"); + RenderManager.StartFrame(); + PIXEndNamedEvent(); + gdraw_D3D11_setViewport_4J(); +#elif defined __PS3__ + RenderManager.StartFrame(); +#elif defined __PSVITA__ + RenderManager.StartFrame(); +#elif defined __ORBIS__ + RenderManager.StartFrame(false); + // Set up a viewport for the render that matches Iggy's own viewport, apart form using an opengl-style z-range (Iggy uses a DX-style range on PS4), so + // that the renderer orthographic projection will work + gdraw_orbis_setViewport_4J(); +#endif + RenderManager.Set_matrixDirty(); + + // 4J Stu - We don't need to clear this here as iggy hasn't written anything to the depth buffer. + // We DO however clear after we render which is why we still setup the rectangle here + //RenderManager.Clear(GL_DEPTH_BUFFER_BIT, &m_customRenderingClearRect); + //glClear(GL_DEPTH_BUFFER_BIT); + + PIXBeginNamedEvent(0,"Final setup"); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0, m_fScreenWidth, m_fScreenHeight, 0, 1000, 3000); + glMatrixMode(GL_MODELVIEW); + glEnable(GL_ALPHA_TEST); + glAlphaFunc(GL_GREATER, 0.1f); + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LEQUAL); + glDepthMask(true); + PIXEndNamedEvent(); +} + +void UIController::setupCustomDrawMatrices(UIScene *scene, CustomDrawData *customDrawRegion) +{ + Minecraft *pMinecraft=Minecraft::GetInstance(); + + // Clear just the region required for this control. + float sceneWidth = (float)scene->getRenderWidth(); + float sceneHeight = (float)scene->getRenderHeight(); + + LONG left, right, top, bottom; +#ifdef __PS3__ + if(!RenderManager.IsHiDef() && !RenderManager.IsWidescreen()) + { + // 4J Stu - Our SD target on PS3 is double width + left = m_tileOriginX + (sceneWidth + customDrawRegion->mat[(0*4)+3]*sceneWidth); + right = left + ( (sceneWidth * customDrawRegion->mat[0]) ) * customDrawRegion->x1; + } + else +#endif + { + left = m_tileOriginX + (sceneWidth + customDrawRegion->mat[(0*4)+3]*sceneWidth)/2; + right = left + ( (sceneWidth * customDrawRegion->mat[0])/2 ) * customDrawRegion->x1; + } + + top = m_tileOriginY + (sceneHeight - customDrawRegion->mat[(1*4)+3]*sceneHeight)/2; + bottom = top + (sceneHeight * -customDrawRegion->mat[(1*4) + 1])/2 * customDrawRegion->y1; + + m_customRenderingClearRect.left = min(m_customRenderingClearRect.left, left); + m_customRenderingClearRect.right = max(m_customRenderingClearRect.right, right);; + m_customRenderingClearRect.top = min(m_customRenderingClearRect.top, top); + m_customRenderingClearRect.bottom = max(m_customRenderingClearRect.bottom, bottom); + + if(!m_bScreenWidthSetup) + { + Minecraft *pMinecraft=Minecraft::GetInstance(); + if(pMinecraft != NULL) + { + m_fScreenWidth=(float)pMinecraft->width_phys; + m_fScreenHeight=(float)pMinecraft->height_phys; + m_bScreenWidthSetup = true; + } + } + + glLoadIdentity(); + glTranslatef(0, 0, -2000); + // Iggy translations are based on a double-size target, with the origin in the centre + glTranslatef((m_fScreenWidth + customDrawRegion->mat[(0*4)+3]*m_fScreenWidth)/2,(m_fScreenHeight - customDrawRegion->mat[(1*4)+3]*m_fScreenHeight)/2,0); + // Iggy scales are based on a double-size target + glScalef( (m_fScreenWidth * customDrawRegion->mat[0])/2,(m_fScreenHeight * -customDrawRegion->mat[(1*4) + 1])/2,1.0f); +} + +void UIController::setupCustomDrawGameStateAndMatrices(UIScene *scene, CustomDrawData *customDrawRegion) +{ + setupCustomDrawGameState(); + setupCustomDrawMatrices(scene, customDrawRegion); +} + +void UIController::endCustomDrawGameState() +{ +#ifdef __ORBIS__ + // TO BE IMPLEMENTED + RenderManager.Clear(GL_DEPTH_BUFFER_BIT); +#else + RenderManager.Clear(GL_DEPTH_BUFFER_BIT, &m_customRenderingClearRect); +#endif + //glClear(GL_DEPTH_BUFFER_BIT); + glDepthMask(false); + glDisable(GL_ALPHA_TEST); +} + +void UIController::endCustomDrawMatrices() +{ +} + +void UIController::endCustomDrawGameStateAndMatrices() +{ + endCustomDrawMatrices(); + endCustomDrawGameState(); +} + +void RADLINK UIController::CustomDrawCallback(void *user_callback_data, Iggy *player, IggyCustomDrawCallbackRegion *region) +{ + UIScene *scene = (UIScene *)IggyPlayerGetUserdata(player); + + if(scene != NULL) + { + scene->customDraw(region); + } +} + +//Description +//Callback to create a user-defined texture to replace SWF-defined textures. +//Parameters +//width - Input value: optional number of pixels wide specified from AS3, or -1 if not defined. Output value: the number of pixels wide to pretend to Iggy that the bitmap is. SWF and AS3 scales bitmaps based on their pixel dimensions, so you can use this to substitute a texture that is higher or lower resolution that ActionScript thinks it is. +//height - Input value: optional number of pixels high specified from AS3, or -1 if not defined. Output value: the number of pixels high to pretend to Iggy that the bitmap is. SWF and AS3 scales bitmaps based on their pixel dimensions, so you can use this to substitute a texture that is higher or lower resolution that ActionScript thinks it is. +//destroy_callback_data - Optional additional output value you can set; the value will be passed along to the corresponding Iggy_TextureSubstitutionDestroyCallback (e.g. you can store the pointer to your own internal structure here). +//return - A platform-independent wrapped texture handle provided by GDraw, or NULL (NULL with throw an ActionScript 3 ArgumentError that the Flash developer can catch) Use by calling IggySetTextureSubstitutionCallbacks. +// +//Discussion +// +//If your texture includes an alpha channel, you must use a premultiplied alpha (where the R,G, and B channels have been multiplied by the alpha value); all Iggy shaders assume premultiplied alpha (and it looks better anyway). +GDrawTexture * RADLINK UIController::TextureSubstitutionCreateCallback ( void * user_callback_data , IggyUTF16 * texture_name , S32 * width , S32 * height , void * * destroy_callback_data ) +{ + UIController *uiController = (UIController *)user_callback_data; + AUTO_VAR(it,uiController->m_substitutionTextures.find((wchar_t *)texture_name)); + + if(it != uiController->m_substitutionTextures.end()) + { + app.DebugPrintf("Found substitution texture %ls, with %d bytes\n", (wchar_t *)texture_name,it->second.length); + + BufferedImage image(it->second.data, it->second.length); + if( image.getData() != NULL ) + { + image.preMultiplyAlpha(); + Textures *t = Minecraft::GetInstance()->textures; + int id = t->getTexture(&image,C4JRender::TEXTURE_FORMAT_RxGyBzAw,false); + + // 4J Stu - All our flash controls that allow replacing textures use a special 64x64 symbol + // Force this size here so that our images don't get scaled wildly + #if (defined __ORBIS__ || defined _DURANGO ) + *width = 96; + *height = 96; + #else + *width = 64; + *height = 64; + + #endif + *destroy_callback_data = (void *)id; + + app.DebugPrintf("Found substitution texture %ls (%d) - %dx%d\n", (wchar_t *)texture_name, id, image.getWidth(), image.getHeight()); + return ui.getSubstitutionTexture(id); + } + else + { + return NULL; + } + } + else + { + app.DebugPrintf("Could not find substitution texture %ls\n", (wchar_t *)texture_name); + return NULL; + } +} + +//Description +//Callback received from Iggy when it stops using a user-defined texture. +void RADLINK UIController::TextureSubstitutionDestroyCallback ( void * user_callback_data , void * destroy_callback_data , GDrawTexture * handle ) +{ + // Orbis complains about casting a pointer to an int + LONGLONG llVal=(LONGLONG)destroy_callback_data; + int id=(int)llVal; + app.DebugPrintf("Destroying iggy texture %d\n", id); + + ui.destroySubstitutionTexture(user_callback_data, handle); + + Textures *t = Minecraft::GetInstance()->textures; + t->releaseTexture( id ); +} + +void UIController::registerSubstitutionTexture(const wstring &textureName, PBYTE pbData, DWORD dwLength) +{ + // Remove it if it already exists + unregisterSubstitutionTexture(textureName,false); + + m_substitutionTextures[textureName] = byteArray(pbData, dwLength); +} + +void UIController::unregisterSubstitutionTexture(const wstring &textureName, bool deleteData) +{ + AUTO_VAR(it,m_substitutionTextures.find(textureName)); + + if(it != m_substitutionTextures.end()) + { + if(deleteData) delete [] it->second.data; + m_substitutionTextures.erase(it); + } +} + +// NAVIGATION +bool UIController::NavigateToScene(int iPad, EUIScene scene, void *initData, EUILayer layer, EUIGroup group) +{ + // if you're trying to navigate to the inventory,the crafting, pause or game info or any of the trigger scenes and there's already a menu up (because you were pressing a few buttons at the same time) then ignore the navigate + if(GetMenuDisplayed(iPad)) + { + switch(scene) + { + case eUIScene_PauseMenu: + case eUIScene_Crafting2x2Menu: + case eUIScene_Crafting3x3Menu: + case eUIScene_FurnaceMenu: + case eUIScene_ContainerMenu: + case eUIScene_LargeContainerMenu: + case eUIScene_InventoryMenu: + case eUIScene_CreativeMenu: + case eUIScene_DispenserMenu: + case eUIScene_SignEntryMenu: + case eUIScene_InGameInfoMenu: + case eUIScene_EnchantingMenu: + case eUIScene_BrewingStandMenu: + case eUIScene_AnvilMenu: + case eUIScene_TradingMenu: + app.DebugPrintf("IGNORING NAVIGATE - we're trying to navigate to a user selected scene when there's already a scene up: pad:%d, scene:%d\n", iPad, scene); + return false; + break; + } + } + + switch(scene) + { + case eUIScene_FullscreenProgress: + { + // 4J Stu - The fullscreen progress scene should not interfere with any other scene stack, so should be placed in it's own group/layer + layer = eUILayer_Fullscreen; + group = eUIGroup_Fullscreen; + } + break; + case eUIScene_ConnectingProgress: + { + // The connecting progress scene shouldn't interfere with other scenes + layer = eUILayer_Fullscreen; + } + break; + case eUIScene_EndPoem: + { + // The end poem scene shouldn't interfere with other scenes, but will be underneath the autosave progress + group = eUIGroup_Fullscreen; + layer = eUILayer_Scene; + } + break; + }; + int menuDisplayedPad = XUSER_INDEX_ANY; + if(group == eUIGroup_PAD) + { + if( app.GetGameStarted() ) + { + // If the game isn't running treat as user 0, otherwise map index directly from pad + if( ( iPad != 255 ) && ( iPad >= 0 ) ) + { + menuDisplayedPad = iPad; + group = (EUIGroup)(iPad+1); + } + else group = eUIGroup_Fullscreen; + } + else + { + layer = eUILayer_Fullscreen; + group = eUIGroup_Fullscreen; + } + } + + PerformanceTimer timer; + + EnterCriticalSection(&m_navigationLock); + SetMenuDisplayed(menuDisplayedPad,true); + bool success = m_groups[(int)group]->NavigateToScene(iPad, scene, initData, layer); + if(success && group == eUIGroup_Fullscreen) setFullscreenMenuDisplayed(true); + LeaveCriticalSection(&m_navigationLock); + + timer.PrintElapsedTime(L"Navigate to scene"); + + return success; + //return true; +} + +bool UIController::NavigateBack(int iPad, bool forceUsePad, EUIScene eScene, EUILayer eLayer) +{ + bool navComplete = false; + if( app.GetGameStarted() ) + { + bool navComplete = m_groups[(int)eUIGroup_Fullscreen]->NavigateBack(iPad, eScene, eLayer); + + if(!navComplete && ( iPad != 255 ) && ( iPad >= 0 ) ) + { + EUIGroup group = (EUIGroup)(iPad+1); + navComplete = m_groups[(int)group]->NavigateBack(iPad, eScene, eLayer); + if(!m_groups[(int)group]->GetMenuDisplayed())SetMenuDisplayed(iPad,false); + } + // 4J-PB - autosave in fullscreen doesn't clear the menuDisplayed flag + else + { + if(!m_groups[(int)eUIGroup_Fullscreen]->GetMenuDisplayed()) + { + setFullscreenMenuDisplayed(false); + for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i) + { + SetMenuDisplayed(i,m_groups[i+1]->GetMenuDisplayed()); + } + } + } + } + else + { + navComplete = m_groups[(int)eUIGroup_Fullscreen]->NavigateBack(iPad, eScene, eLayer); + if(!m_groups[(int)eUIGroup_Fullscreen]->GetMenuDisplayed()) SetMenuDisplayed(XUSER_INDEX_ANY,false); + } + return navComplete; +} + +void UIController::NavigateToHomeMenu() +{ + ui.CloseAllPlayersScenes(); + + // Alert the app the we no longer want to be informed of ethernet connections + app.SetLiveLinkRequired( false ); + + Minecraft *pMinecraft = Minecraft::GetInstance(); + + // 4J-PB - just about to switched to the default texture pack , so clean up anything texture pack related here + + // unload any texture pack audio + // if there is audio in use, clear out the audio, and unmount the pack + TexturePack *pTexPack=Minecraft::GetInstance()->skins->getSelected(); + + + DLCTexturePack *pDLCTexPack=NULL; + if(pTexPack->hasAudio()) + { + // get the dlc texture pack, and store it + pDLCTexPack=(DLCTexturePack *)pTexPack; + } + + // change to the default texture pack + pMinecraft->skins->selectTexturePackById(TexturePackRepository::DEFAULT_TEXTURE_PACK_ID); + + + if(pTexPack->hasAudio()) + { + // need to stop the streaming audio - by playing streaming audio from the default texture pack now + // reset the streaming sounds back to the normal ones + pMinecraft->soundEngine->SetStreamingSounds(eStream_Overworld_Calm1,eStream_Overworld_piano3, + eStream_Nether1,eStream_Nether4, + eStream_end_dragon,eStream_end_end, + eStream_CD_1); + pMinecraft->soundEngine->playStreaming(L"", 0, 0, 0, 1, 1); + + // if(pDLCTexPack->m_pStreamedWaveBank!=NULL) + // { + // pDLCTexPack->m_pStreamedWaveBank->Destroy(); + // } + // if(pDLCTexPack->m_pSoundBank!=NULL) + // { + // pDLCTexPack->m_pSoundBank->Destroy(); + // } +#ifdef _XBOX_ONE + DWORD result = StorageManager.UnmountInstalledDLC(L"TPACK"); +#else + DWORD result = StorageManager.UnmountInstalledDLC("TPACK"); +#endif + + app.DebugPrintf("Unmount result is %d\n",result); + } + + g_NetworkManager.ForceFriendsSessionRefresh(); + + if(pMinecraft->skins->needsUIUpdate()) + { + m_navigateToHomeOnReload = true; + } + else + { + ui.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_MainMenu); + } +} + +UIScene *UIController::GetTopScene(int iPad, EUILayer layer, EUIGroup group) +{ + if(group == eUIGroup_PAD) + { + if( app.GetGameStarted() ) + { + // If the game isn't running treat as user 0, otherwise map index directly from pad + if( ( iPad != 255 ) && ( iPad >= 0 ) ) + { + group = (EUIGroup)(iPad+1); + } + else group = eUIGroup_Fullscreen; + } + else + { + layer = eUILayer_Fullscreen; + group = eUIGroup_Fullscreen; + } + } + return m_groups[(int)group]->GetTopScene(layer); +} + +size_t UIController::RegisterForCallbackId(UIScene *scene) +{ + EnterCriticalSection(&m_registeredCallbackScenesCS); + size_t newId = GetTickCount(); + newId &= 0xFFFFFF; // Chop off the top byte, we don't need any more accuracy than that + newId |= (scene->getSceneType() << 24); // Add in the scene's type to help keep this unique + m_registeredCallbackScenes[newId] = scene; + LeaveCriticalSection(&m_registeredCallbackScenesCS); + return newId; +} + +void UIController::UnregisterCallbackId(size_t id) +{ + EnterCriticalSection(&m_registeredCallbackScenesCS); + AUTO_VAR(it, m_registeredCallbackScenes.find(id) ); + if(it != m_registeredCallbackScenes.end() ) + { + m_registeredCallbackScenes.erase(it); + } + LeaveCriticalSection(&m_registeredCallbackScenesCS); +} + +UIScene *UIController::GetSceneFromCallbackId(size_t id) +{ + UIScene *scene = NULL; + AUTO_VAR(it, m_registeredCallbackScenes.find(id) ); + if(it != m_registeredCallbackScenes.end() ) + { + scene = it->second; + } + return scene; +} + +void UIController::EnterCallbackIdCriticalSection() +{ + EnterCriticalSection(&m_registeredCallbackScenesCS); +} + +void UIController::LeaveCallbackIdCriticalSection() +{ + LeaveCriticalSection(&m_registeredCallbackScenesCS); +} + +void UIController::CloseAllPlayersScenes() +{ + m_groups[(int)eUIGroup_Fullscreen]->getTooltips()->SetTooltips(-1); + for(unsigned int i = 0; i < eUIGroup_COUNT; ++i) + { + //m_bCloseAllScenes[i] = true; + m_groups[i]->closeAllScenes(); + m_groups[i]->getTooltips()->SetTooltips(-1); + } + + if (!m_groups[eUIGroup_Fullscreen]->GetMenuDisplayed()) { + for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i) + { + SetMenuDisplayed(i,false); + } + } + setFullscreenMenuDisplayed(false); +} + +void UIController::CloseUIScenes(int iPad, bool forceIPad) +{ + EUIGroup group; + if( app.GetGameStarted() || forceIPad ) + { + // If the game isn't running treat as user 0, otherwise map index directly from pad + if( ( iPad != 255 ) && ( iPad >= 0 ) ) group = (EUIGroup)(iPad+1); + else group = eUIGroup_Fullscreen; + } + else + { + group = eUIGroup_Fullscreen; + } + + m_groups[(int)group]->closeAllScenes(); + m_groups[(int)group]->getTooltips()->SetTooltips(-1); + + // This should cause the popup to dissappear + TutorialPopupInfo popupInfo; + if(m_groups[(int)group]->getTutorialPopup()) m_groups[(int)group]->getTutorialPopup()->SetTutorialDescription(&popupInfo); + + if(group==eUIGroup_Fullscreen) setFullscreenMenuDisplayed(false); + + SetMenuDisplayed((group == eUIGroup_Fullscreen ? XUSER_INDEX_ANY : iPad), m_groups[(int)group]->GetMenuDisplayed()); +} + +void UIController::setFullscreenMenuDisplayed(bool displayed) +{ + // Show/hide the tooltips for the fullscreen group + m_groups[(int)eUIGroup_Fullscreen]->showComponent(ProfileManager.GetPrimaryPad(),eUIComponent_Tooltips,eUILayer_Tooltips,displayed); + + // Show/hide tooltips for the other layers + for(unsigned int i = (eUIGroup_Fullscreen+1); i < eUIGroup_COUNT; ++i) + { + m_groups[i]->showComponent(i,eUIComponent_Tooltips,eUILayer_Tooltips,!displayed); + } +} + +bool UIController::IsPauseMenuDisplayed(int iPad) +{ + EUIGroup group; + if( app.GetGameStarted() ) + { + // If the game isn't running treat as user 0, otherwise map index directly from pad + if( ( iPad != 255 ) && ( iPad >= 0 ) ) group = (EUIGroup)(iPad+1); + else group = eUIGroup_Fullscreen; + } + else + { + group = eUIGroup_Fullscreen; + } + return m_groups[(int)group]->IsPauseMenuDisplayed(); +} + +bool UIController::IsContainerMenuDisplayed(int iPad) +{ + EUIGroup group; + if( app.GetGameStarted() ) + { + // If the game isn't running treat as user 0, otherwise map index directly from pad + if( ( iPad != 255 ) && ( iPad >= 0 ) ) group = (EUIGroup)(iPad+1); + else group = eUIGroup_Fullscreen; + } + else + { + group = eUIGroup_Fullscreen; + } + return m_groups[(int)group]->IsContainerMenuDisplayed(); +} + +bool UIController::IsIgnorePlayerJoinMenuDisplayed(int iPad) +{ + EUIGroup group; + if( app.GetGameStarted() ) + { + // If the game isn't running treat as user 0, otherwise map index directly from pad + if( ( iPad != 255 ) && ( iPad >= 0 ) ) group = (EUIGroup)(iPad+1); + else group = eUIGroup_Fullscreen; + } + else + { + group = eUIGroup_Fullscreen; + } + return m_groups[(int)group]->IsIgnorePlayerJoinMenuDisplayed(); +} + +bool UIController::IsIgnoreAutosaveMenuDisplayed(int iPad) +{ + EUIGroup group; + if( app.GetGameStarted() ) + { + // If the game isn't running treat as user 0, otherwise map index directly from pad + if( ( iPad != 255 ) && ( iPad >= 0 ) ) group = (EUIGroup)(iPad+1); + else group = eUIGroup_Fullscreen; + } + else + { + group = eUIGroup_Fullscreen; + } + return m_groups[(int)eUIGroup_Fullscreen]->IsIgnoreAutosaveMenuDisplayed() || (group != eUIGroup_Fullscreen && m_groups[(int)group]->IsIgnoreAutosaveMenuDisplayed()); +} + +void UIController::SetIgnoreAutosaveMenuDisplayed(int iPad, bool displayed) +{ + app.DebugPrintf(app.USER_SR, "UIController::SetIgnoreAutosaveMenuDisplayed is not implemented\n"); +} + +bool UIController::IsSceneInStack(int iPad, EUIScene eScene) +{ + EUIGroup group; + if( app.GetGameStarted() ) + { + // If the game isn't running treat as user 0, otherwise map index directly from pad + if( ( iPad != 255 ) && ( iPad >= 0 ) ) group = (EUIGroup)(iPad+1); + else group = eUIGroup_Fullscreen; + } + else + { + group = eUIGroup_Fullscreen; + } + return m_groups[(int)group]->IsSceneInStack(eScene); +} + +bool UIController::GetMenuDisplayed(int iPad) +{ + return m_bMenuDisplayed[iPad]; +} + +void UIController::SetMenuDisplayed(int iPad,bool bVal) +{ + if(bVal) + { + if(iPad==XUSER_INDEX_ANY) + { + for(int i=0;i<XUSER_MAX_COUNT;i++) + { + InputManager.SetMenuDisplayed(i,true); + m_bMenuDisplayed[i]=true; + // 4J Stu - Fix for #11018 - Functional: When the controller is unplugged during active gameplay and plugged back in at the resulting pause menu, it will demonstrate dual-functionality. + m_bMenuToBeClosed[i]=false; + } + } + else + { + InputManager.SetMenuDisplayed(iPad,true); + m_bMenuDisplayed[iPad]=true; + // 4J Stu - Fix for #11018 - Functional: When the controller is unplugged during active gameplay and plugged back in at the resulting pause menu, it will demonstrate dual-functionality. + m_bMenuToBeClosed[iPad]=false; + } + } + else + { + if(iPad==XUSER_INDEX_ANY) + { + for(int i=0;i<XUSER_MAX_COUNT;i++) + { + m_bMenuToBeClosed[i]=true; + m_iCountDown[i]=10; + } + } + else + { + m_bMenuToBeClosed[iPad]=true; + m_iCountDown[iPad]=10; + +#ifdef _DURANGO + // 4J-JEV: When in-game, allow player to toggle the 'Pause' and 'IngameInfo' menus via Kinnect. + if (Minecraft::GetInstance()->running) + InputManager.SetEnabledGtcButtons(_360_GTC_MENU | _360_GTC_PAUSE | _360_GTC_VIEW); +#endif + } + } +} + +void UIController::CheckMenuDisplayed() +{ + for(int iPad=0;iPad<XUSER_MAX_COUNT;iPad++) + { + if(m_bMenuToBeClosed[iPad]) + { + if(m_iCountDown[iPad]!=0) + { + m_iCountDown[iPad]--; + } + else + { + m_bMenuToBeClosed[iPad]=false; + m_bMenuDisplayed[iPad]=false; + InputManager.SetMenuDisplayed(iPad,false); + } + + } + } +} + +void UIController::SetTooltipText( unsigned int iPad, unsigned int tooltip, int iTextID ) +{ + EUIGroup group; + if( app.GetGameStarted() ) + { + // If the game isn't running treat as user 0, otherwise map index directly from pad + if( ( iPad != 255 ) ) group = (EUIGroup)(iPad+1); + else group = eUIGroup_Fullscreen; + } + else + { + group = eUIGroup_Fullscreen; + } + if(m_groups[(int)group]->getTooltips()) m_groups[(int)group]->getTooltips()->SetTooltipText(tooltip, iTextID); +} + +void UIController::SetEnableTooltips( unsigned int iPad, BOOL bVal ) +{ + EUIGroup group; + if( app.GetGameStarted() ) + { + // If the game isn't running treat as user 0, otherwise map index directly from pad + if( ( iPad != 255 ) ) group = (EUIGroup)(iPad+1); + else group = eUIGroup_Fullscreen; + } + else + { + group = eUIGroup_Fullscreen; + } + if(m_groups[(int)group]->getTooltips()) m_groups[(int)group]->getTooltips()->SetEnableTooltips(bVal); +} + +void UIController::ShowTooltip( unsigned int iPad, unsigned int tooltip, bool show ) +{ + EUIGroup group; + if( app.GetGameStarted() ) + { + // If the game isn't running treat as user 0, otherwise map index directly from pad + if( ( iPad != 255 ) ) group = (EUIGroup)(iPad+1); + else group = eUIGroup_Fullscreen; + } + else + { + group = eUIGroup_Fullscreen; + } + if(m_groups[(int)group]->getTooltips()) m_groups[(int)group]->getTooltips()->ShowTooltip(tooltip,show); +} + +void UIController::SetTooltips( unsigned int iPad, int iA, int iB, int iX, int iY, int iLT, int iRT, int iLB, int iRB, int iLS, bool forceUpdate) +{ + EUIGroup group; + + // 4J-PB - strip out any that are not applicable on the platform +#ifndef _XBOX + if(iX==IDS_TOOLTIPS_SELECTDEVICE) iX=-1; + if(iX==IDS_TOOLTIPS_CHANGEDEVICE) iX=-1; + +#if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__) + if(iY==IDS_TOOLTIPS_VIEW_GAMERCARD) iY=-1; + if(iY==IDS_TOOLTIPS_VIEW_GAMERPROFILE) iY=-1; + +#endif +#endif + + if( app.GetGameStarted() ) + { + // If the game isn't running treat as user 0, otherwise map index directly from pad + if( ( iPad != 255 ) ) group = (EUIGroup)(iPad+1); + else group = eUIGroup_Fullscreen; + } + else + { + group = eUIGroup_Fullscreen; + } + if(m_groups[(int)group]->getTooltips()) m_groups[(int)group]->getTooltips()->SetTooltips(iA, iB, iX, iY, iLT, iRT, iLB, iRB, iLS, forceUpdate); +} + +void UIController::EnableTooltip( unsigned int iPad, unsigned int tooltip, bool enable ) +{ + EUIGroup group; + if( app.GetGameStarted() ) + { + // If the game isn't running treat as user 0, otherwise map index directly from pad + if( ( iPad != 255 ) ) group = (EUIGroup)(iPad+1); + else group = eUIGroup_Fullscreen; + } + else + { + group = eUIGroup_Fullscreen; + } + if(m_groups[(int)group]->getTooltips()) m_groups[(int)group]->getTooltips()->EnableTooltip(tooltip,enable); +} + +void UIController::RefreshTooltips(unsigned int iPad) +{ + app.DebugPrintf(app.USER_SR, "UIController::RefreshTooltips is not implemented\n"); +} + +void UIController::AnimateKeyPress(int iPad, int iAction, bool bRepeat, bool bPressed, bool bReleased) +{ + EUIGroup group; + if(bPressed==false) + { + // only animating button press + return; + } + if( app.GetGameStarted() ) + { + // If the game isn't running treat as user 0, otherwise map index directly from pad + if( ( iPad != 255 ) && ( iPad >= 0 ) ) group = (EUIGroup)(iPad+1); + else group = eUIGroup_Fullscreen; + } + else + { + group = eUIGroup_Fullscreen; + } + bool handled = false; + if(m_groups[(int)group]->getTooltips()) m_groups[(int)group]->getTooltips()->handleInput(iPad, iAction, bRepeat, bPressed, bReleased, handled); +} + +void UIController::OverrideSFX(int iPad, int iAction,bool bVal) +{ + EUIGroup group; + + if( app.GetGameStarted() ) + { + // If the game isn't running treat as user 0, otherwise map index directly from pad + if( ( iPad != 255 ) && ( iPad >= 0 ) ) group = (EUIGroup)(iPad+1); + else group = eUIGroup_Fullscreen; + } + else + { + group = eUIGroup_Fullscreen; + } + bool handled = false; + if(m_groups[(int)group]->getTooltips()) m_groups[(int)group]->getTooltips()->overrideSFX(iPad, iAction,bVal); +} + +void UIController::PlayUISFX(ESoundEffect eSound) +{ + Minecraft::GetInstance()->soundEngine->playUI(eSound,1.0f,1.0f); +} + +void UIController::DisplayGamertag(unsigned int iPad, bool show) +{ + // The host decides whether these are on or off + if( app.GetGameSettings(ProfileManager.GetPrimaryPad(),eGameSetting_DisplaySplitscreenGamertags) == 0) + { + show = false; + } + EUIGroup group = (EUIGroup)(iPad+1); + if(m_groups[(int)group]->getHUD()) m_groups[(int)group]->getHUD()->ShowDisplayName(show); + + // Update TutorialPopup in Splitscreen if no container is displayed (to make sure the Popup does not overlap with the Gamertag!) + if(app.GetLocalPlayerCount() > 1 && m_groups[(int)group]->getTutorialPopup() && !m_groups[(int)group]->IsContainerMenuDisplayed()) + { + m_groups[(int)group]->getTutorialPopup()->UpdateTutorialPopup(); + } +} + +void UIController::SetSelectedItem(unsigned int iPad, const wstring &name) +{ + EUIGroup group; + + if( app.GetGameStarted() ) + { + // If the game isn't running treat as user 0, otherwise map index directly from pad + if( ( iPad != 255 ) && ( iPad >= 0 ) ) group = (EUIGroup)(iPad+1); + else group = eUIGroup_Fullscreen; + } + else + { + group = eUIGroup_Fullscreen; + } + bool handled = false; + if(m_groups[(int)group]->getHUD()) m_groups[(int)group]->getHUD()->SetSelectedLabel(name); +} + +void UIController::UpdateSelectedItemPos(unsigned int iPad) +{ + app.DebugPrintf(app.USER_SR, "UIController::UpdateSelectedItemPos not implemented\n"); +} + +void UIController::HandleDLCMountingComplete() +{ + for(unsigned int i = 0; i < eUIGroup_COUNT; ++i) + { + app.DebugPrintf("UIController::HandleDLCMountingComplete - m_groups[%d]\n",i); + m_groups[i]->HandleDLCMountingComplete(); + } +} + +void UIController::HandleDLCInstalled(int iPad) +{ + //app.DebugPrintf(app.USER_SR, "UIController::HandleDLCInstalled not implemented\n"); + for(unsigned int i = 0; i < eUIGroup_COUNT; ++i) + { + m_groups[i]->HandleDLCInstalled(); + } +} + + +#ifdef _XBOX_ONE +void UIController::HandleDLCLicenseChange() +{ + for(unsigned int i = 0; i < eUIGroup_COUNT; ++i) + { + app.DebugPrintf("UIController::HandleDLCLicenseChange - m_groups[%d]\n",i); + m_groups[i]->HandleDLCLicenseChange(); + } +} +#endif + +void UIController::HandleTMSDLCFileRetrieved(int iPad) +{ + app.DebugPrintf(app.USER_SR, "UIController::HandleTMSDLCFileRetrieved not implemented\n"); +} + +void UIController::HandleTMSBanFileRetrieved(int iPad) +{ + app.DebugPrintf(app.USER_SR, "UIController::HandleTMSBanFileRetrieved not implemented\n"); +} + +void UIController::HandleInventoryUpdated(int iPad) +{ + app.DebugPrintf(app.USER_SR, "UIController::HandleInventoryUpdated not implemented\n"); +} + +void UIController::HandleGameTick() +{ + tickInput(); + + for(unsigned int i = 0; i < eUIGroup_COUNT; ++i) + { + if(m_groups[i]->getHUD()) m_groups[i]->getHUD()->handleGameTick(); + } +} + +void UIController::SetTutorial(int iPad, Tutorial *tutorial) +{ + EUIGroup group; + if( app.GetGameStarted() ) + { + // If the game isn't running treat as user 0, otherwise map index directly from pad + if( ( iPad != 255 ) && ( iPad >= 0 ) ) group = (EUIGroup)(iPad+1); + else group = eUIGroup_Fullscreen; + } + else + { + group = eUIGroup_Fullscreen; + } + if(m_groups[(int)group]->getTutorialPopup()) m_groups[(int)group]->getTutorialPopup()->SetTutorial(tutorial); +} + +void UIController::SetTutorialDescription(int iPad, TutorialPopupInfo *info) +{ + EUIGroup group; + if( app.GetGameStarted() ) + { + // If the game isn't running treat as user 0, otherwise map index directly from pad + if( ( iPad != 255 ) && ( iPad >= 0 ) ) group = (EUIGroup)(iPad+1); + else group = eUIGroup_Fullscreen; + } + else + { + group = eUIGroup_Fullscreen; + } + + if(m_groups[(int)group]->getTutorialPopup()) + { + // tutorial popup needs to know if a container menu is being displayed + m_groups[(int)group]->getTutorialPopup()->SetContainerMenuVisible(m_groups[(int)group]->IsContainerMenuDisplayed()); + m_groups[(int)group]->getTutorialPopup()->SetTutorialDescription(info); + } +} + +#ifndef _XBOX +void UIController::RemoveInteractSceneReference(int iPad, UIScene *scene) +{ + EUIGroup group; + if( app.GetGameStarted() ) + { + // If the game isn't running treat as user 0, otherwise map index directly from pad + if( ( iPad != 255 ) && ( iPad >= 0 ) ) group = (EUIGroup)(iPad+1); + else group = eUIGroup_Fullscreen; + } + else + { + group = eUIGroup_Fullscreen; + } + if(m_groups[(int)group]->getTutorialPopup()) m_groups[(int)group]->getTutorialPopup()->RemoveInteractSceneReference(scene); +} +#endif + +void UIController::SetTutorialVisible(int iPad, bool visible) +{ + EUIGroup group; + if( app.GetGameStarted() ) + { + // If the game isn't running treat as user 0, otherwise map index directly from pad + if( ( iPad != 255 ) && ( iPad >= 0 ) ) group = (EUIGroup)(iPad+1); + else group = eUIGroup_Fullscreen; + } + else + { + group = eUIGroup_Fullscreen; + } + if(m_groups[(int)group]->getTutorialPopup()) m_groups[(int)group]->getTutorialPopup()->SetVisible(visible); +} + +bool UIController::IsTutorialVisible(int iPad) +{ + EUIGroup group; + if( app.GetGameStarted() ) + { + // If the game isn't running treat as user 0, otherwise map index directly from pad + if( ( iPad != 255 ) && ( iPad >= 0 ) ) group = (EUIGroup)(iPad+1); + else group = eUIGroup_Fullscreen; + } + else + { + group = eUIGroup_Fullscreen; + } + bool visible = false; + if(m_groups[(int)group]->getTutorialPopup()) visible = m_groups[(int)group]->getTutorialPopup()->IsVisible(); + return visible; +} + +void UIController::UpdatePlayerBasePositions() +{ + Minecraft *pMinecraft = Minecraft::GetInstance(); + + for( BYTE idx = 0; idx < XUSER_MAX_COUNT; ++idx) + { + if(pMinecraft->localplayers[idx] != NULL) + { + if(pMinecraft->localplayers[idx]->m_iScreenSection==C4JRender::VIEWPORT_TYPE_FULLSCREEN) + { + DisplayGamertag(idx,false); + } + else + { + DisplayGamertag(idx,true); + } + m_groups[idx+1]->SetViewportType((C4JRender::eViewportType)pMinecraft->localplayers[idx]->m_iScreenSection); + } + else + { + // 4J Stu - This is a legacy thing from our XUI implementation that we don't need + // Changing the viewport to fullscreen for users that no longer exist is SLOW + // This should probably be on all platforms, but I don't have time to test them all just now! +#ifndef __ORBIS__ + m_groups[idx+1]->SetViewportType(C4JRender::VIEWPORT_TYPE_FULLSCREEN); +#endif + DisplayGamertag(idx,false); + } + } +} + +void UIController::SetEmptyQuadrantLogo(int iSection) +{ + // 4J Stu - We shouldn't need to implement this +} + +void UIController::HideAllGameUIElements() +{ + // 4J Stu - We might not need to implement this + app.DebugPrintf(app.USER_SR, "UIController::HideAllGameUIElements not implemented\n"); +} + +void UIController::ShowOtherPlayersBaseScene(unsigned int iPad, bool show) +{ + // 4J Stu - We shouldn't need to implement this +} + +void UIController::ShowTrialTimer(bool show) +{ + if(m_groups[(int)eUIGroup_Fullscreen]->getPressStartToPlay()) m_groups[(int)eUIGroup_Fullscreen]->getPressStartToPlay()->showTrialTimer(show); +} + +void UIController::SetTrialTimerLimitSecs(unsigned int uiSeconds) +{ + UIController::m_dwTrialTimerLimitSecs = uiSeconds; +} + +void UIController::UpdateTrialTimer(unsigned int iPad) +{ + WCHAR wcTime[20]; + + DWORD dwTimeTicks=(DWORD)app.getTrialTimer(); + + if(dwTimeTicks>m_dwTrialTimerLimitSecs) + { + dwTimeTicks=m_dwTrialTimerLimitSecs; + } + + dwTimeTicks=m_dwTrialTimerLimitSecs-dwTimeTicks; + +#ifndef _CONTENT_PACKAGE + if(true) +#else + // display the time - only if there's less than 3 minutes + if(dwTimeTicks<180) +#endif + { + int iMins=dwTimeTicks/60; + int iSeconds=dwTimeTicks%60; + swprintf( wcTime, 20, L"%d:%02d",iMins,iSeconds); + if(m_groups[(int)eUIGroup_Fullscreen]->getPressStartToPlay()) m_groups[(int)eUIGroup_Fullscreen]->getPressStartToPlay()->setTrialTimer(wcTime); + } + else + { + if(m_groups[(int)eUIGroup_Fullscreen]->getPressStartToPlay()) m_groups[(int)eUIGroup_Fullscreen]->getPressStartToPlay()->setTrialTimer(L""); + } + + // are we out of time? + if((dwTimeTicks==0)) + { + // Trial over + // bring up the pause menu to stop the trial over message box being called again? + if(!ui.GetMenuDisplayed( iPad ) ) + { + ui.NavigateToScene(iPad, eUIScene_PauseMenu, NULL, eUILayer_Scene); + + app.SetAction(iPad,eAppAction_TrialOver); + } + } +} + +void UIController::ReduceTrialTimerValue() +{ + DWORD dwTimeTicks=(int)app.getTrialTimer(); + + if(dwTimeTicks>m_dwTrialTimerLimitSecs) + { + dwTimeTicks=m_dwTrialTimerLimitSecs; + } + + m_dwTrialTimerLimitSecs-=dwTimeTicks; +} + +void UIController::ShowAutosaveCountdownTimer(bool show) +{ + if(m_groups[(int)eUIGroup_Fullscreen]->getPressStartToPlay()) m_groups[(int)eUIGroup_Fullscreen]->getPressStartToPlay()->showTrialTimer(show); +} + +void UIController::UpdateAutosaveCountdownTimer(unsigned int uiSeconds) +{ +#if !(defined(_XBOX_ONE) || defined(__ORBIS__)) + WCHAR wcAutosaveCountdown[100]; + swprintf( wcAutosaveCountdown, 100, app.GetString(IDS_AUTOSAVE_COUNTDOWN),uiSeconds); + if(m_groups[(int)eUIGroup_Fullscreen]->getPressStartToPlay()) m_groups[(int)eUIGroup_Fullscreen]->getPressStartToPlay()->setTrialTimer(wcAutosaveCountdown); +#endif +} + +void UIController::ShowSavingMessage(unsigned int iPad, C4JStorage::ESavingMessage eVal) +{ + bool show = false; + switch(eVal) + { + case C4JStorage::ESavingMessage_None: + show = false; + break; + case C4JStorage::ESavingMessage_Short: + case C4JStorage::ESavingMessage_Long: + show = true; + break; + } + if(m_groups[(int)eUIGroup_Fullscreen]->getPressStartToPlay()) m_groups[(int)eUIGroup_Fullscreen]->getPressStartToPlay()->showSaveIcon(show); +} + +void UIController::ShowPlayerDisplayname(bool show) +{ + if(m_groups[(int)eUIGroup_Fullscreen]->getPressStartToPlay()) m_groups[(int)eUIGroup_Fullscreen]->getPressStartToPlay()->showPlayerDisplayName(show); +} + +void UIController::SetWinUserIndex(unsigned int iPad) +{ + m_winUserIndex = iPad; +} + +unsigned int UIController::GetWinUserIndex() +{ + return m_winUserIndex; +} + +void UIController::ShowUIDebugConsole(bool show) +{ +#ifndef _CONTENT_PACKAGE + + if(show) + { + m_uiDebugConsole = (UIComponent_DebugUIConsole *)m_groups[eUIGroup_Fullscreen]->addComponent(0, eUIComponent_DebugUIConsole, eUILayer_Debug); + } + else + { + m_groups[eUIGroup_Fullscreen]->removeComponent(eUIComponent_DebugUIConsole, eUILayer_Debug); + m_uiDebugConsole = NULL; + } +#endif +} + +void UIController::ShowUIDebugMarketingGuide(bool show) +{ +#ifndef _CONTENT_PACKAGE + + if(show) + { + m_uiDebugMarketingGuide = (UIComponent_DebugUIMarketingGuide *)m_groups[eUIGroup_Fullscreen]->addComponent(0, eUIComponent_DebugUIMarketingGuide, eUILayer_Debug); + } + else + { + m_groups[eUIGroup_Fullscreen]->removeComponent(eUIComponent_DebugUIMarketingGuide, eUILayer_Debug); + m_uiDebugMarketingGuide = NULL; + } +#endif +} + +void UIController::logDebugString(const string &text) +{ + if(m_uiDebugConsole) m_uiDebugConsole->addText(text); +} + +bool UIController::PressStartPlaying(unsigned int iPad) +{ + return m_iPressStartQuadrantsMask&(1<<iPad)?true:false; +} + +void UIController::ShowPressStart(unsigned int iPad) +{ + m_iPressStartQuadrantsMask|=1<<iPad; + if(m_groups[(int)eUIGroup_Fullscreen]->getPressStartToPlay()) m_groups[(int)eUIGroup_Fullscreen]->getPressStartToPlay()->showPressStart(iPad, true); +} + +void UIController::HidePressStart() +{ + ClearPressStart(); + if(m_groups[(int)eUIGroup_Fullscreen]->getPressStartToPlay()) m_groups[(int)eUIGroup_Fullscreen]->getPressStartToPlay()->showPressStart(0, false); +} + +void UIController::ClearPressStart() +{ + m_iPressStartQuadrantsMask = 0; +} + +// 4J Stu - For the different StringTable classes. Should really fix the libraries. +#ifndef __PS3__ +C4JStorage::EMessageResult UIController::RequestMessageBox(UINT uiTitle, UINT uiText, UINT *uiOptionA,UINT uiOptionC, DWORD dwPad, + int( *Func)(LPVOID,int,const C4JStorage::EMessageResult),LPVOID lpParam, C4JStringTable *pStringTable, WCHAR *pwchFormatString,DWORD dwFocusButton, bool bIsError) +#else +C4JStorage::EMessageResult UIController::RequestMessageBox(UINT uiTitle, UINT uiText, UINT *uiOptionA,UINT uiOptionC, DWORD dwPad, + int( *Func)(LPVOID,int,const C4JStorage::EMessageResult),LPVOID lpParam, StringTable *pStringTable, WCHAR *pwchFormatString,DWORD dwFocusButton, bool bIsError) +#endif +{ + MessageBoxInfo param; + param.uiTitle = uiTitle; + param.uiText = uiText; + param.uiOptionA = uiOptionA; + param.uiOptionC = uiOptionC; + param.dwPad = dwPad; + param.Func = Func;\ + param.lpParam = lpParam; + param.pwchFormatString = pwchFormatString; + param.dwFocusButton = dwFocusButton; + + EUILayer layer = bIsError?eUILayer_Error:eUILayer_Alert; + + bool completed = false; + if(ui.IsReloadingSkin()) + { + // Queue this message box + QueuedMessageBoxData *queuedData = new QueuedMessageBoxData(); + queuedData->info = param; + queuedData->info.uiOptionA = new UINT[param.uiOptionC]; + memcpy(queuedData->info.uiOptionA, param.uiOptionA, param.uiOptionC * sizeof(UINT)); + queuedData->iPad = dwPad; + queuedData->layer = eUILayer_Error; // Ensures that these don't get wiped out by a CloseAllScenes call + m_queuedMessageBoxData.push_back(queuedData); + } + else + { + completed = ui.NavigateToScene(dwPad, eUIScene_MessageBox, ¶m, layer, eUIGroup_Fullscreen); + } + + if( completed ) + { + // This may happen if we had to queue the message box, or there was already a message box displaying and so the NavigateToScene returned false; + return C4JStorage::EMessage_Pending; + } + else + { + return C4JStorage::EMessage_Busy; + } +} + +C4JStorage::EMessageResult UIController::RequestUGCMessageBox(UINT title/* = -1 */, UINT message/* = -1 */, int iPad/* = -1*/, int( *Func)(LPVOID,int,const C4JStorage::EMessageResult)/* = NULL*/, LPVOID lpParam/* = NULL*/) +{ + // Default title / messages + if (title == -1) + { + title = IDS_FAILED_TO_CREATE_GAME_TITLE; + } + + if (message == -1) + { + message = IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_CREATE; + } + + // Default pad to primary player + if (iPad == -1) iPad = ProfileManager.GetPrimaryPad(); + +#ifdef __ORBIS__ + // Show the vague UGC system message in addition to our message + ProfileManager.DisplaySystemMessage( SCE_MSG_DIALOG_SYSMSG_TYPE_TRC_PSN_UGC_RESTRICTION, iPad ); + return C4JStorage::EMessage_ResultAccept; +#elif defined(__PSVITA__) + ProfileManager.ShowSystemMessage( SCE_MSG_DIALOG_SYSMSG_TYPE_TRC_PSN_CHAT_RESTRICTION, iPad ); + UINT uiIDA[1]; + uiIDA[0]=IDS_CONFIRM_OK; + return ui.RequestMessageBox( title, IDS_CHAT_RESTRICTION_UGC, uiIDA, 1, iPad, Func, lpParam, app.GetStringTable(), NULL, 0, false); +#else + UINT uiIDA[1]; + uiIDA[0]=IDS_CONFIRM_OK; + return ui.RequestMessageBox( title, message, uiIDA, 1, iPad, Func, lpParam, app.GetStringTable(), NULL, 0, false); +#endif +} + +C4JStorage::EMessageResult UIController::RequestContentRestrictedMessageBox(UINT title/* = -1 */, UINT message/* = -1 */, int iPad/* = -1*/, int( *Func)(LPVOID,int,const C4JStorage::EMessageResult)/* = NULL*/, LPVOID lpParam/* = NULL*/) +{ + // Default title / messages + if (title == -1) + { + title = IDS_FAILED_TO_CREATE_GAME_TITLE; + } + + if (message == -1) + { +#if defined(_XBOX_ONE) || defined(_WINDOWS64) + // IDS_CONTENT_RESTRICTION doesn't exist on XB1 + message = IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_CREATE; +#else + message = IDS_CONTENT_RESTRICTION; +#endif + } + + // Default pad to primary player + if (iPad == -1) iPad = ProfileManager.GetPrimaryPad(); + +#ifdef __ORBIS__ + // Show the vague UGC system message in addition to our message + ProfileManager.DisplaySystemMessage( SCE_MSG_DIALOG_SYSMSG_TYPE_TRC_PSN_UGC_RESTRICTION, iPad ); + return C4JStorage::EMessage_ResultAccept; +#elif defined(__PSVITA__) + ProfileManager.ShowSystemMessage( SCE_MSG_DIALOG_SYSMSG_TYPE_TRC_PSN_AGE_RESTRICTION, iPad ); + return C4JStorage::EMessage_ResultAccept; +#else + UINT uiIDA[1]; + uiIDA[0]=IDS_CONFIRM_OK; + return ui.RequestMessageBox( title, message, uiIDA, 1, iPad, Func, lpParam, app.GetStringTable(), NULL, 0, false); +#endif +} + +void UIController::setFontCachingCalculationBuffer(int length) +{ + /* 4J-JEV: As described in an email from Sean. + If your `optional_temp_buffer` is NULL, Iggy will allocate the temp + buffer on the stack during Iggy draw calls. The size of the buffer it + will allocate is 16 bytes times `max_chars` in 32-bit, and 24 bytes + times `max_chars` in 64-bit. If the stack of the thread making the + draw call is not large enough, Iggy will crash or otherwise behave + incorrectly. + */ +#if defined __ORBIS__ || defined _DURANGO || defined _WIN64 + static const int CHAR_SIZE = 24; +#else + static const int CHAR_SIZE = 16; +#endif + + if (m_tempBuffer != NULL) delete [] m_tempBuffer; + if (length<0) + { + if (m_defaultBuffer == NULL) m_defaultBuffer = new char[CHAR_SIZE*5000]; + IggySetFontCachingCalculationBuffer(5000, m_defaultBuffer, CHAR_SIZE*5000); + } + else + { + m_tempBuffer = new char[CHAR_SIZE*length]; + IggySetFontCachingCalculationBuffer(length, m_tempBuffer, CHAR_SIZE*length); + } +} + +// Returns the first scene of given type if it exists, NULL otherwise +UIScene *UIController::FindScene(EUIScene sceneType) +{ + UIScene *pScene = NULL; + + for (int i = 0; i < eUIGroup_COUNT; i++) + { + pScene = m_groups[i]->FindScene(sceneType); +#ifdef __PS3__ + if (pScene != NULL) return pScene; +#else + if (pScene != nullptr) return pScene; +#endif + } + + return pScene; +} + +#ifdef __PSVITA__ + +void UIController::TouchBoxAdd(UIControl *pControl,UIScene *pUIScene) +{ + EUIGroup eUIGroup=pUIScene->GetParentLayerGroup(); + EUILayer eUILayer=pUIScene->GetParentLayer()->m_iLayer; + EUIScene eUIscene=pUIScene->getSceneType(); + + TouchBoxAdd(pControl,eUIGroup,eUILayer,eUIscene, pUIScene->GetMainPanel()); +} + +void UIController::TouchBoxAdd(UIControl *pControl,EUIGroup eUIGroup,EUILayer eUILayer,EUIScene eUIscene, UIControl *pMainPanelControl) +{ + UIELEMENT *puiElement = new UIELEMENT; + puiElement->pControl = pControl; + + S32 iControlWidth = pControl->getWidth(); + S32 iControlHeight = pControl->getHeight(); + S32 iMainPanelOffsetX = 0; + S32 iMainPanelOffsetY= 0; + + // 4J-TomK add main panel offset if controls do not live in the root scene + if(pMainPanelControl) + { + iMainPanelOffsetX = pMainPanelControl->getXPos(); + iMainPanelOffsetY = pMainPanelControl->getYPos(); + } + + // 4J-TomK override control width / height where needed + if(puiElement->pControl->getControlType() == UIControl::eSlider) + { + // Sliders are never scaled but masked, so we have to get the real width from AS + UIControl_Slider *pSlider = (UIControl_Slider *)puiElement->pControl; + iControlWidth = pSlider->GetRealWidth(); + } + else if(puiElement->pControl->getControlType() == UIControl::eTexturePackList) + { + // The origin of the TexturePackList is NOT in the top left corner but where the slot area starts. therefore we need the height of the slot area itself. + UIControl_TexturePackList *pTexturePackList = (UIControl_TexturePackList *)puiElement->pControl; + iControlHeight = pTexturePackList->GetRealHeight(); + } + else if(puiElement->pControl->getControlType() == UIControl::eDynamicLabel) + { + // The height and width of this control changes per how to play page + UIControl_DynamicLabel *pDynamicLabel = (UIControl_DynamicLabel *)puiElement->pControl; + iControlWidth = pDynamicLabel->GetRealWidth(); + iControlHeight = pDynamicLabel->GetRealHeight(); + } + else if(puiElement->pControl->getControlType() == UIControl::eHTMLLabel) + { + // The height and width of this control changes per how to play page + UIControl_HTMLLabel *pHtmlLabel = (UIControl_HTMLLabel *)puiElement->pControl; + iControlWidth = pHtmlLabel->GetRealWidth(); + iControlHeight = pHtmlLabel->GetRealHeight(); + } + + puiElement->x1=(S32)((float)pControl->getXPos() + (float)iMainPanelOffsetX); + puiElement->y1=(S32)((float)pControl->getYPos() + (float)iMainPanelOffsetY); + puiElement->x2=(S32)(((float)pControl->getXPos() + (float)iControlWidth + (float)iMainPanelOffsetX)); + puiElement->y2=(S32)(((float)pControl->getYPos() + (float)iControlHeight + (float)iMainPanelOffsetY)); + + if(puiElement->pControl->getControlType() == UIControl::eNoControl) + { + app.DebugPrintf("NO CONTROL!"); + } + + if(puiElement->x1 == puiElement->x2 || puiElement->y1 == puiElement->y2) + { + app.DebugPrintf("NOT adding touchbox %d,%d,%d,%d\n",puiElement->x1,puiElement->y1,puiElement->x2,puiElement->y2); + } + else + { + app.DebugPrintf("Adding touchbox %d,%d,%d,%d\n",puiElement->x1,puiElement->y1,puiElement->x2,puiElement->y2); + m_TouchBoxes[eUIGroup][eUILayer][eUIscene].push_back(puiElement); + } +} + +void UIController::TouchBoxRebuild(UIScene *pUIScene) +{ + EUIGroup eUIGroup=pUIScene->GetParentLayerGroup(); + EUILayer eUILayer=pUIScene->GetParentLayer()->m_iLayer; + EUIScene eUIscene=pUIScene->getSceneType(); + + // if we delete an element, it's possible that the scene has re-arranged all the elements, so we need to rebuild the boxes + ui.TouchBoxesClear(pUIScene); + + // rebuild boxes + AUTO_VAR(itEnd, pUIScene->GetControls()->end()); + for (AUTO_VAR(it, pUIScene->GetControls()->begin()); it != itEnd; it++) + { + UIControl *control=(UIControl *)*it; + + if(control->getControlType() == UIControl::eButton || + control->getControlType() == UIControl::eSlider || + control->getControlType() == UIControl::eCheckBox || + control->getControlType() == UIControl::eTexturePackList || + control->getControlType() == UIControl::eButtonList || + control->getControlType() == UIControl::eTextInput || + control->getControlType() == UIControl::eDynamicLabel || + control->getControlType() == UIControl::eHTMLLabel || + control->getControlType() == UIControl::eLeaderboardList || + control->getControlType() == UIControl::eTouchControl) + { + // 4J-TomK update the control (it might have been moved by flash / AS) + control->UpdateControl(); + + ui.TouchBoxAdd(control,eUIGroup,eUILayer,eUIscene, pUIScene->GetMainPanel()); + } + } +} + +void UIController::TouchBoxesClear(UIScene *pUIScene) +{ + EUIGroup eUIGroup=pUIScene->GetParentLayerGroup(); + EUILayer eUILayer=pUIScene->GetParentLayer()->m_iLayer; + EUIScene eUIscene=pUIScene->getSceneType(); + + AUTO_VAR(itEnd, m_TouchBoxes[eUIGroup][eUILayer][eUIscene].end()); + for (AUTO_VAR(it, m_TouchBoxes[eUIGroup][eUILayer][eUIscene].begin()); it != itEnd; it++) + { + UIELEMENT *element=(UIELEMENT *)*it; + delete element; + } + m_TouchBoxes[eUIGroup][eUILayer][eUIscene].clear(); +} + +bool UIController::TouchBoxHit(UIScene *pUIScene,S32 x, S32 y) +{ + EUIGroup eUIGroup=pUIScene->GetParentLayerGroup(); + EUILayer eUILayer=pUIScene->GetParentLayer()->m_iLayer; + EUIScene eUIscene=pUIScene->getSceneType(); + + // 4J-TomK let's do the transformation from touch resolution to screen resolution here, so our touchbox values always are in screen resolution! + x *= (m_fScreenWidth/1920.0f); + y *= (m_fScreenHeight/1080.0f); + + if(m_TouchBoxes[eUIGroup][eUILayer][eUIscene].size()>0) + { + AUTO_VAR(itEnd, m_TouchBoxes[eUIGroup][eUILayer][eUIscene].end()); + for (AUTO_VAR(it, m_TouchBoxes[eUIGroup][eUILayer][eUIscene].begin()); it != itEnd; it++) + { + UIELEMENT *element=(UIELEMENT *)*it; + if(element->pControl->getHidden() == false && element->pControl->getVisible()) // ignore removed controls + { + if((x>=element->x1) &&(x<=element->x2) && (y>=element->y1) && (y<=element->y2)) + { + if(!m_bTouchscreenPressed) + { + app.DebugPrintf("SET m_ActiveUIElement (Layer: %i) at x = %i y = %i\n", (int)eUILayer, (int)x, (int)y); + m_ActiveUIElement = element; + } + // remember the currently highlighted element + m_HighlightedUIElement = element; + + return true; + } + } + } + } + + //app.DebugPrintf("MISS at x = %i y = %i\n", (int)x, (int)y); + m_HighlightedUIElement = NULL; + return false; +} + +// +// Handle Touch Input +// +void UIController::HandleTouchInput(unsigned int iPad, unsigned int key, bool bPressed, bool bRepeat, bool bReleased) +{ + // no input? no handling! + if(!bPressed && !bRepeat && !bReleased) + { + // override for instand repeat without delay! + if(m_bTouchscreenPressed && m_ActiveUIElement && ( + m_ActiveUIElement->pControl->getControlType() == UIControl::eSlider || + m_ActiveUIElement->pControl->getControlType() == UIControl::eButtonList || + m_ActiveUIElement->pControl->getControlType() == UIControl::eTexturePackList || + m_ActiveUIElement->pControl->getControlType() == UIControl::eDynamicLabel || + m_ActiveUIElement->pControl->getControlType() == UIControl::eHTMLLabel || + m_ActiveUIElement->pControl->getControlType() == UIControl::eLeaderboardList || + m_ActiveUIElement->pControl->getControlType() == UIControl::eTouchControl)) + bRepeat = true; // the above controls need to be controllable without having the finger over them + else + return; + } + + SceTouchData* pTouchData = InputManager.GetTouchPadData(iPad,false); + S32 x = pTouchData->report[0].x * (m_fScreenWidth/1920.0f); + S32 y = pTouchData->report[0].y * (m_fScreenHeight/1080.0f); + + if(bPressed && !bRepeat && !bReleased) // PRESSED HANDLING + { + app.DebugPrintf("touch input pressed\n"); + switch(m_ActiveUIElement->pControl->getControlType()) + { + case UIControl::eButton: + // set focus + UIControl_Button *pButton=(UIControl_Button *)m_ActiveUIElement->pControl; + pButton->getParentScene()->SetFocusToElement(m_ActiveUIElement->pControl->getId()); + // override bPressed to false. we only want the button to trigger on touch release! + bPressed = false; + break; + case UIControl::eSlider: + // set focus + UIControl_Slider *pSlider=(UIControl_Slider *)m_ActiveUIElement->pControl; + pSlider->getParentScene()->SetFocusToElement(m_ActiveUIElement->pControl->getId()); + break; + case UIControl::eCheckBox: + // set focus + UIControl_CheckBox *pCheckbox=(UIControl_CheckBox *)m_ActiveUIElement->pControl; + pCheckbox->getParentScene()->SetFocusToElement(m_ActiveUIElement->pControl->getId()); + // override bPressed. we only want the checkbox to trigger on touch release! + bPressed = false; + break; + case UIControl::eButtonList: + // set focus to list + UIControl_ButtonList *pButtonList=(UIControl_ButtonList *)m_ActiveUIElement->pControl; + //pButtonList->getParentScene()->SetFocusToElement(m_ActiveUIElement->pControl->getId()); + // tell list where we tapped it so it can set focus to the correct button + pButtonList->SetTouchFocus((float)x, (float)y, false); + // override bPressed. we only want the ButtonList to trigger on touch release! + bPressed = false; + break; + case UIControl::eTexturePackList: + // set focus to list + UIControl_TexturePackList *pTexturePackList=(UIControl_TexturePackList *)m_ActiveUIElement->pControl; + pTexturePackList->getParentScene()->SetFocusToElement(m_ActiveUIElement->pControl->getId()); + // tell list where we tapped it so it can set focus to the correct texture pack + pTexturePackList->SetTouchFocus((float)x - (float)m_ActiveUIElement->x1, (float)y - (float)m_ActiveUIElement->y1, false); + // override bPressed. we only want the TexturePack List to trigger on touch release! + bPressed = false; + break; + case UIControl::eTextInput: + // set focus + UIControl_TextInput *pTextInput=(UIControl_TextInput *)m_ActiveUIElement->pControl; + pTextInput->getParentScene()->SetFocusToElement(m_ActiveUIElement->pControl->getId()); + // override bPressed to false. we only want the textinput to trigger on touch release! + bPressed = false; + break; + case UIControl::eDynamicLabel: + // handle dynamic label scrolling + UIControl_DynamicLabel *pDynamicLabel=(UIControl_DynamicLabel *)m_ActiveUIElement->pControl; + pDynamicLabel->TouchScroll(y, true); + // override bPressed to false + bPressed = false; + break; + case UIControl::eHTMLLabel: + // handle dynamic label scrolling + UIControl_HTMLLabel *pHtmlLabel=(UIControl_HTMLLabel *)m_ActiveUIElement->pControl; + pHtmlLabel->TouchScroll(y, true); + // override bPressed to false + bPressed = false; + break; + case UIControl::eLeaderboardList: + // set focus to list + UIControl_LeaderboardList *pLeaderboardList=(UIControl_LeaderboardList *)m_ActiveUIElement->pControl; + // tell list where we tapped it so it can set focus to the correct button + pLeaderboardList->SetTouchFocus((float)x, (float)y, false); + // override bPressed. we only want the ButtonList to trigger on touch release! + bPressed = false; + break; + case UIControl::eTouchControl: + // pass on touch input to relevant parent scene so we can handle it there! + m_ActiveUIElement->pControl->getParentScene()->handleTouchInput(iPad, x, y, m_ActiveUIElement->pControl->getId(), bPressed, bRepeat, bReleased); + // override bPressed to false + bPressed = false; + break; + default: + app.DebugPrintf("PRESSED - UNHANDLED UI ELEMENT\n"); + break; + } + } + else if(bRepeat) // REPEAT HANDLING + { + switch(m_ActiveUIElement->pControl->getControlType()) + { + case UIControl::eButton: + /* no action */ + break; + case UIControl::eSlider: + // handle slider movement + UIControl_Slider *pSlider=(UIControl_Slider *)m_ActiveUIElement->pControl; + float fNewSliderPos = ((float)x - (float)m_ActiveUIElement->x1) / (float)pSlider->GetRealWidth(); + pSlider->SetSliderTouchPos(fNewSliderPos); + break; + case UIControl::eCheckBox: + /* no action */ + bRepeat = false; + bPressed = false; + break; + case UIControl::eButtonList: + // handle button list scrolling + UIControl_ButtonList *pButtonList=(UIControl_ButtonList *)m_ActiveUIElement->pControl; + pButtonList->SetTouchFocus((float)x, (float)y, true); + break; + case UIControl::eTexturePackList: + // handle texturepack list scrolling + UIControl_TexturePackList *pTexturePackList=(UIControl_TexturePackList *)m_ActiveUIElement->pControl; + pTexturePackList->SetTouchFocus((float)x - (float)m_ActiveUIElement->x1, (float)y - (float)m_ActiveUIElement->y1, true); + break; + case UIControl::eTextInput: + /* no action */ + bRepeat = false; + bPressed = false; + break; + case UIControl::eDynamicLabel: + // handle dynamic label scrolling + UIControl_DynamicLabel *pDynamicLabel=(UIControl_DynamicLabel *)m_ActiveUIElement->pControl; + pDynamicLabel->TouchScroll(y, true); + // override bPressed & bRepeat to false + bPressed = false; + bRepeat = false; + break; + case UIControl::eHTMLLabel: + // handle dynamic label scrolling + UIControl_HTMLLabel *pHtmlLabel=(UIControl_HTMLLabel *)m_ActiveUIElement->pControl; + pHtmlLabel->TouchScroll(y, true); + // override bPressed & bRepeat to false + bPressed = false; + bRepeat = false; + break; + case UIControl::eLeaderboardList: + // handle button list scrolling + UIControl_LeaderboardList *pLeaderboardList=(UIControl_LeaderboardList *)m_ActiveUIElement->pControl; + pLeaderboardList->SetTouchFocus((float)x, (float)y, true); + break; + case UIControl::eTouchControl: + // override bPressed to false + bPressed = false; + // pass on touch input to relevant parent scene so we can handle it there! + m_ActiveUIElement->pControl->getParentScene()->handleTouchInput(iPad, x, y, m_ActiveUIElement->pControl->getId(), bPressed, bRepeat, bReleased); + // override bRepeat to false + bRepeat = false; + break; + default: + app.DebugPrintf("REPEAT - UNHANDLED UI ELEMENT\n"); + break; + } + } + if(bReleased) // RELEASED HANDLING + { + app.DebugPrintf("touch input released\n"); + switch(m_ActiveUIElement->pControl->getControlType()) + { + case UIControl::eButton: + // trigger button on release (ONLY if the finger is still on it!) + if(m_HighlightedUIElement && m_ActiveUIElement->pControl == m_HighlightedUIElement->pControl) + bPressed = true; + break; + case UIControl::eSlider: + /* no action */ + break; + case UIControl::eCheckBox: + // trigger checkbox on release (ONLY if the finger is still on it!) + if(m_HighlightedUIElement && m_ActiveUIElement->pControl == m_HighlightedUIElement->pControl) + { + UIControl_CheckBox *pCheckbox=(UIControl_CheckBox *)m_ActiveUIElement->pControl; + pCheckbox->TouchSetCheckbox(!pCheckbox->IsChecked()); + } + bReleased = false; + break; + case UIControl::eButtonList: + // trigger buttonlist on release (ONLY if the finger is still on it!) + if(m_HighlightedUIElement && m_ActiveUIElement->pControl == m_HighlightedUIElement->pControl) + { + UIControl_ButtonList *pButtonList=(UIControl_ButtonList *)m_ActiveUIElement->pControl; + if(pButtonList->CanTouchTrigger(x,y)) + bPressed = true; + } + break; + case UIControl::eTexturePackList: + // trigger texturepack list on release (ONLY if the finger is still on it!) + if(m_HighlightedUIElement && m_ActiveUIElement->pControl == m_HighlightedUIElement->pControl) + { + UIControl_TexturePackList *pTexturePackList=(UIControl_TexturePackList *)m_ActiveUIElement->pControl; + if(pTexturePackList->CanTouchTrigger((float)x - (float)m_ActiveUIElement->x1, (float)y - (float)m_ActiveUIElement->y1)) + bPressed = true; + } + break; + case UIControl::eTextInput: + // trigger TextInput on release (ONLY if the finger is still on it!) + if(m_HighlightedUIElement && m_ActiveUIElement->pControl == m_HighlightedUIElement->pControl) + bPressed = true; + break; + case UIControl::eDynamicLabel: + // handle dynamic label scrolling + UIControl_DynamicLabel *pDynamicLabel=(UIControl_DynamicLabel *)m_ActiveUIElement->pControl; + pDynamicLabel->TouchScroll(y, false); + break; + case UIControl::eHTMLLabel: + // handle dynamic label scrolling + UIControl_HTMLLabel *pHtmlLabel=(UIControl_HTMLLabel *)m_ActiveUIElement->pControl; + pHtmlLabel->TouchScroll(y, false); + break; + case UIControl::eLeaderboardList: + /* no action */ + break; + case UIControl::eTouchControl: + // trigger only if touch is released over the same component! + if(m_HighlightedUIElement && m_ActiveUIElement->pControl == m_HighlightedUIElement->pControl) + { + // pass on touch input to relevant parent scene so we can handle it there! + m_ActiveUIElement->pControl->getParentScene()->handleTouchInput(iPad, x, y, m_ActiveUIElement->pControl->getId(), bPressed, bRepeat, bReleased); + } + // override bReleased to false + bReleased = false; + break; + default: + app.DebugPrintf("RELEASED - UNHANDLED UI ELEMENT\n"); + break; + } + } + + // only proceed if there's input to be handled + if(bPressed || bRepeat || bReleased) + { + SendTouchInput(iPad, key, bPressed, bRepeat, bReleased); + } +} + +void UIController::SendTouchInput(unsigned int iPad, unsigned int key, bool bPressed, bool bRepeat, bool bReleased) +{ + bool handled = false; + + // Send the key to the fullscreen group first + m_groups[(int)eUIGroup_Fullscreen]->handleInput(iPad, key, bRepeat, bPressed, bReleased, handled); + if(!handled) + { + // If it's not been handled yet, then pass the event onto the players specific group + m_groups[(iPad+1)]->handleInput(iPad, key, bRepeat, bPressed, bReleased, handled); + } +} + + +#endif
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIController.h b/Minecraft.Client/Common/UI/UIController.h new file mode 100644 index 00000000..ef064f80 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIController.h @@ -0,0 +1,369 @@ +#pragma once +using namespace std; +#include "IUIController.h" +#include "UIEnums.h" +#include "UIGroup.h" + +class UIAbstractBitmapFont; +class UIBitmapFont; +class UITTFFont; +class UIComponent_DebugUIConsole; +class UIComponent_DebugUIMarketingGuide; +class UIControl; + +// Base class for all shared functions between UIControllers +class UIController : public IUIController +{ +public: + static __int64 iggyAllocCount; + + // MGH - added to prevent crash loading Iggy movies while the skins were being reloaded + static CRITICAL_SECTION ms_reloadSkinCS; + static bool ms_bReloadSkinCSInitialised; + +protected: + UIComponent_DebugUIConsole *m_uiDebugConsole; + UIComponent_DebugUIMarketingGuide *m_uiDebugMarketingGuide; + +private: + CRITICAL_SECTION m_navigationLock; + + static const int UI_REPEAT_KEY_DELAY_MS = 300; // How long from press until the first repeat + static const int UI_REPEAT_KEY_REPEAT_RATE_MS = 100; // How long in between repeats + DWORD m_actionRepeatTimer[XUSER_MAX_COUNT][ACTION_MAX_MENU+1]; + + float m_fScreenWidth; + float m_fScreenHeight; + bool m_bScreenWidthSetup; + + S32 m_tileOriginX, m_tileOriginY; + + UIAbstractBitmapFont *m_mcBitmapFont; + UITTFFont *m_mcTTFFont; + UIBitmapFont *m_moj7, *m_moj11; + + // 4J-PB - ui element type for PSVita touch control +#ifdef __PSVITA__ + + typedef struct + { + UIControl *pControl; + S32 x1,y1,x2,y2; + } + UIELEMENT; + // E3 - Fine for now, but we need to make this better! + vector<UIELEMENT *> m_TouchBoxes[eUIGroup_COUNT][eUILayer_COUNT][eUIScene_COUNT]; + bool m_bTouchscreenPressed; +#endif + // 4J Stu - These should be in the order that they reference each other (i.e. they can only reference one with a lower value in the enum) + enum ELibraries + { + eLibrary_Platform, + eLibrary_GraphicsDefault, + eLibrary_GraphicsHUD, + eLibrary_GraphicsInGame, + eLibrary_GraphicsTooltips, + eLibrary_GraphicsLabels, + eLibrary_Labels, + eLibrary_InGame, + eLibrary_HUD, + eLibrary_Tooltips, + eLibrary_Default, + +#if ( defined(_WINDOWS64) ) + // 4J Stu - Load the 720/480 skins so that we have something to fallback on during development +#ifndef _FINAL_BUILD + eLibraryFallback_Platform, + eLibraryFallback_GraphicsDefault, + eLibraryFallback_GraphicsHUD, + eLibraryFallback_GraphicsInGame, + eLibraryFallback_GraphicsTooltips, + eLibraryFallback_GraphicsLabels, + eLibraryFallback_Labels, + eLibraryFallback_InGame, + eLibraryFallback_HUD, + eLibraryFallback_Tooltips, + eLibraryFallback_Default, +#endif +#endif + + eLibrary_Count, + }; + + IggyLibrary m_iggyLibraries[eLibrary_Count]; + +protected: + GDrawFunctions *gdraw_funcs; + +private: + HIGGYEXP iggy_explorer; + HIGGYPERFMON iggy_perfmon; + bool m_iggyPerfmonEnabled; + + bool m_bMenuDisplayed[XUSER_MAX_COUNT]; // track each players menu displayed + bool m_bMenuToBeClosed[XUSER_MAX_COUNT]; // actioned at the end of the game loop + int m_iCountDown[XUSER_MAX_COUNT]; // ticks to block input + + bool m_bCloseAllScenes[eUIGroup_COUNT]; + + int m_iPressStartQuadrantsMask; + + C4JRender::eViewportType m_currentRenderViewport; + bool m_bCustomRenderPosition; + + static DWORD m_dwTrialTimerLimitSecs; + + unordered_map<wstring, byteArray> m_substitutionTextures; + + typedef struct _CachedMovieData + { + byteArray m_ba; + __int64 m_expiry; + } CachedMovieData; + unordered_map<wstring, CachedMovieData> m_cachedMovieData; + + typedef struct _QueuedMessageBoxData + { + MessageBoxInfo info; + int iPad; + EUILayer layer; + } QueuedMessageBoxData; + vector<QueuedMessageBoxData *> m_queuedMessageBoxData; + + unsigned int m_winUserIndex; + //bool m_bSysUIShowing; + bool m_bSystemUIShowing; + C4JThread *m_reloadSkinThread; + bool m_navigateToHomeOnReload; + int m_accumulatedTicks; + + D3D11_RECT m_customRenderingClearRect; + + unordered_map<size_t, UIScene *> m_registeredCallbackScenes; // A collection of scenes and unique id's that are used in async callbacks so we can safely handle when they get destroyed + CRITICAL_SECTION m_registeredCallbackScenesCS;; + +public: + UIController(); +#ifdef __PSVITA__ + void TouchBoxAdd(UIControl *pControl,UIScene *pUIScene); + bool TouchBoxHit(UIScene *pUIScene,S32 x, S32 y); + void TouchBoxesClear(UIScene *pUIScene); + void TouchBoxRebuild(UIScene *pUIScene); + + void HandleTouchInput(unsigned int iPad, unsigned int key, bool bPressed, bool bRepeat, bool bReleased); + void SendTouchInput(unsigned int iPad, unsigned int key, bool bPressed, bool bRepeat, bool bReleased); + + private: + void TouchBoxAdd(UIControl *pControl,EUIGroup eUIGroup,EUILayer eUILayer,EUIScene eUIscene, UIControl *pMainPanelControl); + UIELEMENT *m_ActiveUIElement; + UIELEMENT *m_HighlightedUIElement; +#endif + +protected: + UIGroup *m_groups[eUIGroup_COUNT]; + +public: + void showComponent(int iPad, EUIScene scene, EUILayer layer, EUIGroup group, bool show) + { + m_groups[group]->showComponent(iPad, scene, layer, show); + } + + void removeComponent(EUIScene scene, EUILayer layer, EUIGroup group) + { + m_groups[group]->removeComponent(scene, layer); + } + +protected: + // Should be called from the platforms init function + void preInit(S32 width, S32 height); + void postInit(); + + +public: + CRITICAL_SECTION m_Allocatorlock; + void SetupFont(); +public: + // TICKING + virtual void tick(); + +private: + void loadSkins(); + IggyLibrary loadSkin(const wstring &skinPath, const wstring &skinName); + +public: + void ReloadSkin(); + virtual void StartReloadSkinThread(); + virtual bool IsReloadingSkin(); + virtual bool IsExpectingOrReloadingSkin(); + virtual void CleanUpSkinReload(); + +private: + static int reloadSkinThreadProc(void* lpParam); + +public: + byteArray getMovieData(const wstring &filename); + + // INPUT +private: + void tickInput(); + void handleInput(); + void handleKeyPress(unsigned int iPad, unsigned int key); + +protected: + static rrbool RADLINK ExternalFunctionCallback( void * user_callback_data , Iggy * player , IggyExternalFunctionCallUTF16 * call ); + +public: + // RENDERING + float getScreenWidth() { return m_fScreenWidth; } + float getScreenHeight() { return m_fScreenHeight; } + + virtual void render() = 0; + void getRenderDimensions(C4JRender::eViewportType viewport, S32 &width, S32 &height); + void setupRenderPosition(C4JRender::eViewportType viewport); + void setupRenderPosition(S32 xOrigin, S32 yOrigin); + + void SetSysUIShowing(bool bVal); + static void SetSystemUIShowing(LPVOID lpParam,bool bVal); + +protected: + virtual void setTileOrigin(S32 xPos, S32 yPos) = 0; + +public: + + virtual CustomDrawData *setupCustomDraw(UIScene *scene, IggyCustomDrawCallbackRegion *region) = 0; + virtual CustomDrawData *calculateCustomDraw(IggyCustomDrawCallbackRegion *region) = 0; + virtual void endCustomDraw(IggyCustomDrawCallbackRegion *region) = 0; +protected: + // Should be called from the platforms render function + void renderScenes(); + +public: + virtual void beginIggyCustomDraw4J(IggyCustomDrawCallbackRegion *region, CustomDrawData *customDrawRegion) = 0; + void setupCustomDrawGameState(); + void endCustomDrawGameState(); + void setupCustomDrawMatrices(UIScene *scene, CustomDrawData *customDrawRegion); + void setupCustomDrawGameStateAndMatrices(UIScene *scene, CustomDrawData *customDrawRegion); + void endCustomDrawMatrices(); + void endCustomDrawGameStateAndMatrices(); + +protected: + + static void RADLINK CustomDrawCallback(void *user_callback_data, Iggy *player, IggyCustomDrawCallbackRegion *Region); + static GDrawTexture * RADLINK TextureSubstitutionCreateCallback( void * user_callback_data , IggyUTF16 * texture_name , S32 * width , S32 * height , void **destroy_callback_data ); + static void RADLINK TextureSubstitutionDestroyCallback( void * user_callback_data , void * destroy_callback_data , GDrawTexture * handle ); + + virtual GDrawTexture *getSubstitutionTexture(int textureId) { return NULL; } + virtual void destroySubstitutionTexture(void *destroyCallBackData, GDrawTexture *handle) {} + +public: + void registerSubstitutionTexture(const wstring &textureName, PBYTE pbData, DWORD dwLength); + void unregisterSubstitutionTexture(const wstring &textureName, bool deleteData); + +public: + // NAVIGATION + bool NavigateToScene(int iPad, EUIScene scene, void *initData = NULL, EUILayer layer = eUILayer_Scene, EUIGroup group = eUIGroup_PAD); + bool NavigateBack(int iPad, bool forceUsePad = false, EUIScene eScene = eUIScene_COUNT, EUILayer eLayer = eUILayer_COUNT); + void NavigateToHomeMenu(); + UIScene *GetTopScene(int iPad, EUILayer layer = eUILayer_Scene, EUIGroup group = eUIGroup_PAD); + + size_t RegisterForCallbackId(UIScene *scene); + void UnregisterCallbackId(size_t id); + UIScene *GetSceneFromCallbackId(size_t id); + void EnterCallbackIdCriticalSection(); + void LeaveCallbackIdCriticalSection(); + +private: + void setFullscreenMenuDisplayed(bool displayed); + +public: + void CloseAllPlayersScenes(); + void CloseUIScenes(int iPad, bool forceIPad = false); + + virtual bool IsPauseMenuDisplayed(int iPad); + virtual bool IsContainerMenuDisplayed(int iPad); + virtual bool IsIgnorePlayerJoinMenuDisplayed(int iPad); + virtual bool IsIgnoreAutosaveMenuDisplayed(int iPad); + virtual void SetIgnoreAutosaveMenuDisplayed(int iPad, bool displayed); + virtual bool IsSceneInStack(int iPad, EUIScene eScene); + bool GetMenuDisplayed(int iPad); + void SetMenuDisplayed(int iPad,bool bVal); + virtual void CheckMenuDisplayed(); + void AnimateKeyPress(int iPad, int iAction, bool bRepeat, bool bPressed, bool bReleased); + void OverrideSFX(int iPad, int iAction,bool bVal); + + // TOOLTIPS + virtual void SetTooltipText( unsigned int iPad, unsigned int tooltip, int iTextID ); + virtual void SetEnableTooltips( unsigned int iPad, BOOL bVal ); + virtual void ShowTooltip( unsigned int iPad, unsigned int tooltip, bool show ); + virtual void SetTooltips( unsigned int iPad, int iA, int iB=-1, int iX=-1, int iY=-1 , int iLT=-1, int iRT=-1, int iLB=-1, int iRB=-1, int iLS=-1, bool forceUpdate = false); + virtual void EnableTooltip( unsigned int iPad, unsigned int tooltip, bool enable ); + virtual void RefreshTooltips(unsigned int iPad); + + virtual void PlayUISFX(ESoundEffect eSound); + + virtual void DisplayGamertag(unsigned int iPad, bool show); + virtual void SetSelectedItem(unsigned int iPad, const wstring &name); + virtual void UpdateSelectedItemPos(unsigned int iPad); + + virtual void HandleDLCMountingComplete(); + virtual void HandleDLCInstalled(int iPad); +#ifdef _XBOX_ONE + virtual void HandleDLCLicenseChange(); +#endif + virtual void HandleTMSDLCFileRetrieved(int iPad); + virtual void HandleTMSBanFileRetrieved(int iPad); + virtual void HandleInventoryUpdated(int iPad); + virtual void HandleGameTick(); + + virtual void SetTutorial(int iPad, Tutorial *tutorial); + virtual void SetTutorialDescription(int iPad, TutorialPopupInfo *info); + virtual void RemoveInteractSceneReference(int iPad, UIScene *scene); + virtual void SetTutorialVisible(int iPad, bool visible); + virtual bool IsTutorialVisible(int iPad); + + virtual void UpdatePlayerBasePositions(); + virtual void SetEmptyQuadrantLogo(int iSection); + virtual void HideAllGameUIElements(); + virtual void ShowOtherPlayersBaseScene(unsigned int iPad, bool show); + + virtual void ShowTrialTimer(bool show); + virtual void SetTrialTimerLimitSecs(unsigned int uiSeconds); + virtual void UpdateTrialTimer(unsigned int iPad); + virtual void ReduceTrialTimerValue(); + + virtual void ShowAutosaveCountdownTimer(bool show); + virtual void UpdateAutosaveCountdownTimer(unsigned int uiSeconds); + virtual void ShowSavingMessage(unsigned int iPad, C4JStorage::ESavingMessage eVal); + + virtual void ShowPlayerDisplayname(bool show); + virtual bool PressStartPlaying(unsigned int iPad); + virtual void ShowPressStart(unsigned int iPad); + virtual void HidePressStart(); + void ClearPressStart(); + + // 4J Stu - Only because of the different StringTable type, should really fix the libraries +#ifndef __PS3__ + virtual C4JStorage::EMessageResult RequestMessageBox(UINT uiTitle, UINT uiText, UINT *uiOptionA,UINT uiOptionC, DWORD dwPad=XUSER_INDEX_ANY, + int( *Func)(LPVOID,int,const C4JStorage::EMessageResult)=NULL,LPVOID lpParam=NULL, C4JStringTable *pStringTable=NULL, WCHAR *pwchFormatString=NULL,DWORD dwFocusButton=0, bool bIsError = true); +#else + virtual C4JStorage::EMessageResult RequestMessageBox(UINT uiTitle, UINT uiText, UINT *uiOptionA,UINT uiOptionC, DWORD dwPad=XUSER_INDEX_ANY, + int( *Func)(LPVOID,int,const C4JStorage::EMessageResult)=NULL,LPVOID lpParam=NULL, StringTable *pStringTable=NULL, WCHAR *pwchFormatString=NULL,DWORD dwFocusButton=0, bool bIsError = true); +#endif + + C4JStorage::EMessageResult RequestUGCMessageBox(UINT title = -1, UINT message = -1, int iPad = -1, int( *Func)(LPVOID,int,const C4JStorage::EMessageResult) = NULL, LPVOID lpParam = NULL); + C4JStorage::EMessageResult RequestContentRestrictedMessageBox(UINT title = -1, UINT message = -1, int iPad = -1, int( *Func)(LPVOID,int,const C4JStorage::EMessageResult) = NULL, LPVOID lpParam = NULL); + + virtual void SetWinUserIndex(unsigned int iPad); + unsigned int GetWinUserIndex(); + + virtual void ShowUIDebugConsole(bool show); + virtual void ShowUIDebugMarketingGuide(bool show); + void logDebugString(const string &text); + UIScene* FindScene(EUIScene sceneType); + +public: + char *m_defaultBuffer, *m_tempBuffer; + void setFontCachingCalculationBuffer(int length); + + +}; diff --git a/Minecraft.Client/Common/UI/UIEnums.h b/Minecraft.Client/Common/UI/UIEnums.h new file mode 100644 index 00000000..c68b6740 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIEnums.h @@ -0,0 +1,234 @@ +#pragma once + +// Defines the fixed groups for UI (lower numbers ticked first, rendered last (ie on top)) +enum EUIGroup +{ + eUIGroup_Fullscreen, + eUIGroup_Player1, +#ifndef __PSVITA__ + eUIGroup_Player2, + eUIGroup_Player3, + eUIGroup_Player4, +#endif + + eUIGroup_COUNT, + + eUIGroup_PAD, // Special case to determine the group from the pad (default) +}; + +// Defines the layers in a UI group (lower numbers ticked first, rendered last (ie on top)) +enum EUILayer +{ +#ifndef _CONTENT_PACKAGE + eUILayer_Debug, +#endif + eUILayer_Tooltips, + eUILayer_Error, + eUILayer_Alert, + eUILayer_Fullscreen, // Note: Fullscreen in this context doesn't necessarily mean fill the whole screen, but fill the whole viewport for this group. Enables processes that don't interefere with normal scene stack + eUILayer_Popup, + eUILayer_Scene, + //eUILayer_Chat, + eUILayer_HUD, + + eUILayer_COUNT, +}; + +// Defines the scenes and components that can be added to a layer +// If you add to the enums below, you need to add the scene name in the right place in CConsoleMinecraftApp::wchSceneA +enum EUIScene +{ + eUIScene_PartnernetPassword = 0, + eUIScene_Intro, + eUIScene_SaveMessage, + eUIScene_MainMenu, + eUIScene_FullscreenProgress, + eUIScene_PauseMenu, + eUIScene_Crafting2x2Menu, + eUIScene_Crafting3x3Menu, + eUIScene_FurnaceMenu, + eUIScene_ContainerMenu, + eUIScene_LargeContainerMenu,// for splitscreen + eUIScene_InventoryMenu, + eUIScene_DispenserMenu, + eUIScene_DebugOptions, + eUIScene_DebugTips, + eUIScene_HelpAndOptionsMenu, + eUIScene_HowToPlay, + eUIScene_HowToPlayMenu, + eUIScene_ControlsMenu, + eUIScene_SettingsOptionsMenu, + eUIScene_SettingsAudioMenu, + eUIScene_SettingsControlMenu, + eUIScene_SettingsGraphicsMenu, + eUIScene_SettingsUIMenu, + eUIScene_SettingsMenu, + eUIScene_LeaderboardsMenu, + eUIScene_Credits, + eUIScene_DeathMenu, + eUIComponent_TutorialPopup, + eUIScene_CreateWorldMenu, + eUIScene_LoadOrJoinMenu, + eUIScene_JoinMenu, + eUIScene_SignEntryMenu, + eUIScene_InGameInfoMenu, + eUIScene_ConnectingProgress, + eUIScene_DLCOffersMenu, + eUIScene_SocialPost, + eUIScene_TrialExitUpsell, + eUIScene_LoadMenu, + eUIComponent_Chat, + eUIScene_ReinstallMenu, + eUIScene_SkinSelectMenu, + eUIScene_TextEntry, + eUIScene_InGameHostOptionsMenu, + eUIScene_InGamePlayerOptionsMenu, + eUIScene_CreativeMenu, + eUIScene_LaunchMoreOptionsMenu, + eUIScene_DLCMainMenu, + eUIScene_NewUpdateMessage, + eUIScene_EnchantingMenu, + eUIScene_BrewingStandMenu, + eUIScene_EndPoem, + eUIScene_HUD, + eUIScene_TradingMenu, + eUIScene_AnvilMenu, + eUIScene_TeleportMenu, + +#ifdef _XBOX +// eUIScene_TransferToXboxOne, +#endif + + // When adding new scenes here, you must also update the switches in CConsoleMinecraftApp::NavigateToScene + // There are quite a few so you need to check them all + +#ifndef _XBOX + // Anything non-xbox should be added here. The ordering of scenes above is required for sentient reporting on xbox 360 to continue to be accurate + eUIComponent_Panorama, + eUIComponent_Logo, + eUIComponent_DebugUIConsole, + eUIComponent_DebugUIMarketingGuide, + eUIComponent_Tooltips, + eUIComponent_PressStartToPlay, + eUIComponent_MenuBackground, + eUIScene_Keyboard, + eUIScene_QuadrantSignin, + eUIScene_MessageBox, + eUIScene_Timer, + eUIScene_EULA, + eUIScene_InGameSaveManagementMenu, +#endif // ndef _XBOX + +#ifdef _DEBUG_MENUS_ENABLED + eUIScene_DebugOverlay, + eUIScene_DebugItemEditor, +#endif +#ifndef _CONTENT_PACKAGE + eUIScene_DebugCreateSchematic, + eUIScene_DebugSetCamera, +#endif + + eUIScene_COUNT, +}; + +// Used by the fullscreen progress scene to decide what to do when a thread finishes +enum ProgressionCompletionType +{ + e_ProgressCompletion_NoAction, + e_ProgressCompletion_NavigateBack, + e_ProgressCompletion_CloseUIScenes, + e_ProgressCompletion_CloseAllPlayersUIScenes, + e_ProgressCompletion_NavigateToHomeMenu, + e_ProgressCompletion_AutosaveNavigateBack, + e_ProgressCompletion_NavigateBackToScene, +}; + +enum EToolTipButton +{ + eToolTipButtonA = 0, + eToolTipButtonB, + eToolTipButtonX, + eToolTipButtonY, + eToolTipButtonLT, + eToolTipButtonRT, + eToolTipButtonLB, + eToolTipButtonRB, + eToolTipButtonLS, + eToolTipNumButtons +}; + +enum EToolTipItem +{ + eToolTipNone = -1, + eToolTipPickupPlace_OLD = 0, // To support existing menus. + eToolTipExit, + eToolTipPickUpGeneric, + eToolTipPickUpAll, + eToolTipPickUpHalf, + eToolTipPlaceGeneric, + eToolTipPlaceOne, + eToolTipPlaceAll, + eToolTipDropGeneric, + eToolTipDropOne, + eToolTipDropAll, + eToolTipSwap, + eToolTipQuickMove, + eToolTipQuickMoveIngredient, + eToolTipQuickMoveFuel, + eToolTipWhatIsThis, + eToolTipEquip, + eToolTipClearQuickSelect, + eToolTipQuickMoveTool, + eToolTipQuickMoveArmor, + eToolTipQuickMoveWeapon, + eToolTipDye, + eToolTipRepair, + eNumToolTips +}; + +enum EHowToPlayPage +{ + eHowToPlay_WhatsNew = 0, + eHowToPlay_Basics, + eHowToPlay_Multiplayer, + eHowToPlay_HUD, + eHowToPlay_Creative, + eHowToPlay_Inventory, + eHowToPlay_Chest, + eHowToPlay_LargeChest, + eHowToPlay_Enderchest, + eHowToPlay_InventoryCrafting, + eHowToPlay_CraftTable, + eHowToPlay_Furnace, + eHowToPlay_Dispenser, + + eHowToPlay_Brewing, + eHowToPlay_Enchantment, + eHowToPlay_Anvil, + eHowToPlay_FarmingAnimals, + eHowToPlay_Breeding, + eHowToPlay_Trading, + + eHowToPlay_NetherPortal, + eHowToPlay_TheEnd, +#ifdef _XBOX + eHowToPlay_SocialMedia, + eHowToPlay_BanList, +#endif + eHowToPlay_HostOptions, + eHowToPlay_NumPages +}; + +// Credits +enum ECreditTextTypes +{ + eExtraLargeText = 0, + eLargeText, + eMediumText, + eSmallText, + eNumTextTypes +}; + +#define NO_TRANSLATED_STRING ( -1 ) // String ID used to indicate that we are using non localised string. + +#define CONNECTING_PROGRESS_CHECK_TIME 500 diff --git a/Minecraft.Client/Common/UI/UIFontData.cpp b/Minecraft.Client/Common/UI/UIFontData.cpp new file mode 100644 index 00000000..c5ad46ef --- /dev/null +++ b/Minecraft.Client/Common/UI/UIFontData.cpp @@ -0,0 +1,341 @@ +#include "stdafx.h" +#include "UIFontData.h" + + ///////////////////////////////////////////////////// + // --- -- --- THIS FILE IS IN UNICODE --- -- --- // + ///////////////////////////////////////////////////// + +SFontData SFontData::Mojangles_7 + = { + + /* Font Name */ "Mojangles7", + +#ifdef _XBOX + /* filename */ L"/font/Mojangles_7.png", +#else + /* Filename */ L"/TitleUpdate/res/font/Mojangles_7.png", +#endif + + /* Glyph count */ FONTSIZE, + /* Codepoints */ SFontData::Codepoints, + + /*img wdth,hght*/ 190, 264, + /*img cols,rows*/ FONTCOLS, FONTROWS, + + + /*glyph dim x,y*/ 8,13, + + /*ascent/descent*/ 7.f/13.f, 8.f/13.f, + + /*advance*/ 1.f/10.f, + + /*whitespace*/ 5, + + }; + + +SFontData SFontData::Mojangles_11 + = { + + /* Font Name */ "Mojangles11", + +#ifdef _XBOX + /* filename */ L"/font/Mojangles_11.png", +#else + /* Filename */ L"/TitleUpdate/res/font/Mojangles_11.png", +#endif + + /* Glyph count */ FONTSIZE, + /* Codepoints */ SFontData::Codepoints, + + /*img wdth,hght*/ 305, 348, + /*img cols,rows*/ FONTCOLS, FONTROWS, + + /*glyph dim x,y*/ 13,17, + + /*ascent/descent*/ 11.f/17.f, 6.f/17.f, + + /*advance*/ 1.f/13.f, + + /*whitespace*/ 7 + + }; + + + // ----------------------------------------------------------------------------- + // 4J-JEV: Glyph -> Unicode Maps, + // Unicode search tool: http://www.fileformat.info/info/unicode/char/search.htm + //------------------------------------------------------------------------------ + + +// Originally interpretted from 'Chars.txt', required many alterations to work correctly. (New Characters have been also added) +unsigned short SFontData::Codepoints[FONTSIZE] = +{ + // NOTE: When adding characters here, you may also want to add them to the ignore list 'Mojangles\Dev\Tools\Mojangles.txt' so we know not to panic when localisation uses them. + +/* ż Å» ź Ź ć Ć Å„ Ń */ + 0x0001, 0x017C, 0x017B, 0x017A, 0x0179, 0x0107, 0x0106, 0x0144, 0x0143, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, + +/* ! " # $ % & ' ( ) * + , - */ + 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, 0x0020, 0x0000, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, + +/* . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D */ + 0x002E, 0x002F, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, + +/* E F G H I J K L M N O P Q R S T U V W X Y Z [ */ + 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x005B, + +/* \ ] ^ _ ` a b c d e f g h i j k l m n o p q r */ + 0x005C, 0x005D, 0x005E, 0x005F, 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, 0x0070, 0x0071, 0x0072, + +/* s t u v w x y z { | } ~ */ + 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F, 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, + +/* */ + 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F, 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F, 0x00A0, + +/* ¡ ¢ £ ¤ Â¥ ¦ § ¨ © ª « ¬  ® ¯ ° ± ² ³ ´ µ ¶ · */ + 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, + +/* ¸ ¹ º » ¼ ½ ¾ ¿ À à Â Ã Ä Ã… Æ Ç È É Ê Ë ÃŒ à Î */ + 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, + +/* à à Ñ Ã’ Ó Ô Õ Ö × Ø Ù Ú Û Ü à Þ ß à á â ã ä Ã¥ */ + 0x00CF, 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF, 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, + +/* æ ç è é ê ë ì à î ï ð ñ ò ó ô õ ö ÷ ø ù ú û ü */ + 0x00E6, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, + +/* ý þ ÿ Å’ Å“ Å Å¡ Ÿ Ž ž Æ’ Ë£ âž„ – — ’ ‚ “ †„ †‡ • */ + 0x00FD, 0x00FE, 0x00FF, 0x0152, 0x0153, 0x0160, 0x0161, 0x0178, 0x017D, 0x017E, 0x0192, 0x02E3, 0x2784, 0x2013, 0x2014, 0x2019, 0x201A, 0x201C, 0x201D, 0x201E, 0x2020, 0x2021, 0x2022, + +/* … ‰ ‹ › € â„¢ Í Åž İ Äž ÅŸ ı ÄŸ Ä™ Ę ó Ó Ä… Ä„ Å› Åš Å‚ Å */ + 0x2026, 0x2030, 0x2039, 0x203A, 0x20AC, 0x2122, 0x035D, 0x015E, 0x0130, 0x011E, 0x015F, 0x0131, 0x011F, 0x0119, 0x0118, 0x00F3, 0x00D3, 0x0105, 0x0104, 0x015B, 0x015A, 0x0142, 0x0141, + +/* РРБ Ð’ Г Д Е Ж З И Й К Л М РО П РС Т У Ф Ð¥ */ + 0x0401, 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, + +/* Ц Ч Ш Щ Ъ Ы Ь РЮ Я а б в г д е ж з и й к л м */ + 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F, 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, + +/* н о п Ñ€ Ñ Ñ‚ у Ñ„ Ñ… ц ч ш щ ÑŠ Ñ‹ ÑŒ Ñ ÑŽ Ñ Ñ‘ χ ψ ω */ + 0x043D, 0x043E, 0x043F, 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F, 0x0451, 0x03C7, 0x03C8, 0x03C9, + +/* ÄŒ ÄŽ Äš Ĺ Ľ Ň ŠŘ Ť Å® Ű Ä Ä Ä› ĺ ľ ň Å‘ Å™ Å¥ ů ű */ + 0x010C, 0x010E, 0x011A, 0x0139, 0x013D, 0x0147, 0x0150, 0x0158, 0x0164, 0x016E, 0x0170, 0x010D, 0x010F, 0x011B, 0x013A, 0x013E, 0x0148, 0x0151, 0x0159, 0x0165, 0x016F, 0x0171, 0x0020, + +/* Α Î’ Γ Δ Ε Ζ Η Θ Ι Κ Λ Μ ΠΞ Ο ΠΡ Σ Τ Î¥ Φ Χ Ψ */ + 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, 0x03A0, 0x03A1, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, + +/* Ω α β γ δ ε ζ η θ ι κ λ μ ν ξ ο Ï€ Ï Ï‚ σ Ï„ Ï… φ */ + 0x03A9, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, 0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, + +/* Ά Έ Ή Ί ÎŒ ÎŽ ΠΠά Πή ί ÏŠ ÏŒ Ï ÏŽ Å• ΄ ‘ */ + 0x0386, 0x0388, 0x0389, 0x038A, 0x038C, 0x038E, 0x038F, 0x0390, 0x03AC, 0x03AD, 0x03AE, 0x03AF, 0x03CA, 0x03CC, 0x03CD, 0x03CE, 0x0155, 0x0384, 0x2018, 0x0000, 0x0000, 0x0000, 0x0000, +}; + + + + + /////////////////////// + // --- CFontData --- // + /////////////////////// + +CFontData::CFontData() +{ + m_unicodeMap = unordered_map<unsigned int, unsigned short>(); + + m_sFontData = NULL; + m_kerningTable = NULL; + m_pbRawImage = NULL; +} + +CFontData::CFontData(SFontData &sFontData, int *pbRawImage) + : m_unicodeMap( sFontData.m_uiGlyphCount + 2 ) +{ + this->m_sFontData = &sFontData; + + // INITIALISE ALPHA CHANNEL // + + // Glyph Archive (1Byte per pixel). + unsigned int archiveSize = sFontData.m_uiGlyphMapX * sFontData.m_uiGlyphMapY; + + this->m_pbRawImage = new unsigned char[archiveSize]; + + // 4J-JEV: Take the alpha channel from each pixel. + for (unsigned int i = 0; i < archiveSize; i++) + { + this->m_pbRawImage[i] = (pbRawImage[i] & 0xFF000000) >> 24; + } + + // CREATE UNICODE MAP // + for (unsigned int i = 0; i < sFontData.m_uiGlyphCount; i++) + { + unordered_map<unsigned int, unsigned short>::value_type pair(sFontData.Codepoints[i], i); + m_unicodeMap.insert( pair ); + } + + // CREATE KERNING TABLE // + m_kerningTable = new unsigned short[sFontData.m_uiGlyphCount]; + for (unsigned short glyph = 0; glyph < sFontData.m_uiGlyphCount; glyph++) + { + int row,column; + getPos(glyph,row,column); + + short xMax = 0, _x=0, _y=0; + + // Find the position of the topLeft corner. + unsigned char *topLeft = m_pbRawImage, *cursor; + moveCursor( topLeft, column * sFontData.m_uiGlyphWidth, row * sFontData.m_uiGlyphHeight); + + assert( ((column+1)*sFontData.m_uiGlyphWidth) < sFontData.m_uiGlyphMapX ); + assert( ((row+1)*sFontData.m_uiGlyphHeight) < sFontData.m_uiGlyphMapY ); + + static int XX = 79; + // Find the furthest filled pixel to the right. + for (short y = 0; y < sFontData.m_uiGlyphHeight; y++) + { + for (short x = 0; x < sFontData.m_uiGlyphWidth; x++) + { + cursor = topLeft; + moveCursor(cursor, x, y); + + assert( (cursor-m_pbRawImage) < archiveSize ); + + if ( *cursor > 0 ) + { + if (x > xMax) xMax = x; + _x = x; + _y = y; + } + } + } + +#if _DEBUG_BLOCK_CHARS + for (short y = 0; y < sFontData.m_uiGlyphHeight; y++) + { + for (short x = 0; x < sFontData.m_uiGlyphWidth; x++) + { + cursor = topLeft; + moveCursor(cursor, x, y); + + if (x==0) *cursor = 0x00; + else if (x<=xMax) *cursor = 0xFF; + else *cursor = 0x00; + } + } +#endif + + // 4J-JEV: Empty glyphs are considered to be whitespace. + if (xMax == 0) m_kerningTable[glyph] = sFontData.m_uiWhitespaceWidth; + else m_kerningTable[glyph] = xMax + 1; + } + + // CACHE GLYPH ADVANCES // + m_pfAdvanceTable = new float[sFontData.m_uiGlyphCount]; + for (unsigned short glyph = 0; glyph < sFontData.m_uiGlyphCount; glyph++) + { + m_pfAdvanceTable[glyph] = m_kerningTable[glyph] * m_sFontData->m_fAdvPerPixel; + } + + // DEBUG // +#ifndef _CONTENT_PACKAGE + for (int i = 0; i < sFontData.m_uiGlyphCount; i++) + { + int unicode = getUnicode(i), unicodeChar = 32, row, col; + if ( 32 < unicode && unicode < 127 && unicode != 0x0025 ) + { + unicodeChar = unicode; + } + + getPos(i, row, col); + + string state = "ok"; + if (i != getGlyphId(unicode)) + { + state = "MISSMATCHED!"; + + app.DebugPrintf( "<GLYPH_%03i> %i\t%c\tU+%.4X, kerning=%i, (%2i,%2i). %s\n", + i, getGlyphId(unicode), unicodeChar, unicode, m_kerningTable[i], row, col, state.c_str() ); + } + } +#endif +} + +void CFontData::release() +{ + delete [] m_kerningTable; + delete [] m_pfAdvanceTable; + delete [] m_pbRawImage; +} + +const string CFontData::getFontName() +{ + return m_sFontData->m_strFontName; +} + +SFontData *CFontData::getFontData() +{ + return m_sFontData; +} + +unsigned short CFontData::getGlyphId(unsigned int unicodepoint) +{ + unordered_map<unsigned int, unsigned short>::iterator out = m_unicodeMap.find(unicodepoint); + if (out != m_unicodeMap.end()) + return out->second; + return 0; +} + +unsigned int CFontData::getUnicode(unsigned short glyphId) +{ + return m_sFontData->Codepoints[glyphId]; +} + +unsigned char *CFontData::topLeftPixel(int row, int col) +{ + unsigned char *out = m_pbRawImage; + moveCursor(out, col * m_sFontData->m_uiGlyphWidth, row* m_sFontData->m_uiGlyphHeight); + return out; +} + +void CFontData::getPos(unsigned short glyphId, int &rowOut, int &colOut) +{ + rowOut = glyphId / m_sFontData->m_uiGlyphMapCols; + colOut = glyphId % m_sFontData->m_uiGlyphMapCols; +} + +float CFontData::getAdvance(unsigned short glyphId) +{ + return m_pfAdvanceTable[glyphId]; +} + +int CFontData::getWidth(unsigned short glyphId) +{ + return m_kerningTable[glyphId]; +} + +bool CFontData::glyphIsWhitespace(unsigned short glyphId) +{ + return unicodeIsWhitespace( getUnicode(glyphId) ); +} + +bool CFontData::unicodeIsWhitespace(unsigned int unicode) +{ + static const unsigned int MAX_WHITESPACE = 1; + static const unsigned int whitespace[MAX_WHITESPACE] = { + 0x0020 + }; + + for (int i=0; i<MAX_WHITESPACE; i++) + { + if (unicode == whitespace[i]) return true; + } + + return false; +} + +void CFontData::moveCursor(unsigned char *&cursor, unsigned int dx, unsigned int dy) +{ + cursor += (dy * m_sFontData->m_uiGlyphMapX) + dx; +} diff --git a/Minecraft.Client/Common/UI/UIFontData.h b/Minecraft.Client/Common/UI/UIFontData.h new file mode 100644 index 00000000..b7e38ffa --- /dev/null +++ b/Minecraft.Client/Common/UI/UIFontData.h @@ -0,0 +1,133 @@ +#pragma once + +#include <unordered_map> + +using namespace std; + +#define _DEBUG_BLOCK_CHARS 0 + +// For hardcoded font data. +struct SFontData +{ +public: + static const unsigned short FONTCOLS = 23; + static const unsigned short FONTROWS = 20; + + static const unsigned short FONTSIZE = FONTCOLS * FONTROWS; + +public: + // Font name. + string m_strFontName; + + // Filename of the glyph archive. + wstring m_wstrFilename; + + // Number of glyphs in the archive. + unsigned int m_uiGlyphCount; + + // Unicode values of each glyph. + unsigned short *m_arrCodepoints; + + // X resolution of glyph archive. + unsigned int m_uiGlyphMapX; + + // Y resolution of glyph archive. + unsigned int m_uiGlyphMapY; + + // Number of columns in the glyph archive. + unsigned int m_uiGlyphMapCols; + + // Number of rows in the glyph archive. + unsigned int m_uiGlyphMapRows; + + // Width of each glyph. + unsigned int m_uiGlyphWidth; + + // Height of each glyph. + unsigned int m_uiGlyphHeight; + + // Ascent of each glyph above the baseline (units?). + float m_fAscent; + + // Descent of each glyph below the baseline (units?). + float m_fDescent; + + // How much to advance for each pixel wide the glyph is. + float m_fAdvPerPixel; + + // How many pixels wide any whitespace characters are. + unsigned int m_uiWhitespaceWidth; + +public: + static unsigned short Codepoints[FONTSIZE]; + static SFontData Mojangles_7; + static SFontData Mojangles_11; +}; + +// Provides a common interface for dealing with font data. +class CFontData +{ +public: + CFontData(); + + // pbRawImage consumed by constructor. + CFontData(SFontData &sFontData, int *pbRawImage); + + // Release memory. + void release(); + +protected: + + // Hardcoded font data. + SFontData *m_sFontData; + + // Map Unicodepoints to glyph ids. + unordered_map<unsigned int, unsigned short> m_unicodeMap; + + // Kerning value for each glyph. + unsigned short *m_kerningTable; + + // Binary blob of the archive image. + unsigned char *m_pbRawImage; + + // Total advance of each character. + float *m_pfAdvanceTable; + +public: + + // Accessor for the font name in the internal SFontData. + const string getFontName(); + + // Accessor for the hardcoded internal font data. + SFontData *getFontData(); + + // Get the glyph id corresponding to a unicode point. + unsigned short getGlyphId(unsigned int unicodepoint); + + // Get the unicodepoint corresponding to a glyph id. + unsigned int getUnicode(unsigned short glyphId); + + // Get a pointer to the top left pixel of a row/column in the raw image. + unsigned char *topLeftPixel(int row, int col); + + // Get the row and column where a glyph appears in the archive. + void getPos(unsigned short gyphId, int &row, int &col); + + // Get the advance of this character (units?). + float getAdvance(unsigned short glyphId); + + // Get the width (in pixels) of a given character. + int getWidth(unsigned short glyphId); + + // Returns true if this glyph is whitespace. + bool glyphIsWhitespace(unsigned short glyphId); + + // Returns true if this unicodepoint is whitespace + bool unicodeIsWhitespace(unsigned int unicodepoint); + +private: + + // Move a pointer in an image dx pixels right and dy pixels down, wrap around in either dimension leads to unknown behaviour. + void moveCursor(unsigned char *&cursor, unsigned int dx, unsigned int dy); +}; + diff --git a/Minecraft.Client/Common/UI/UIGroup.cpp b/Minecraft.Client/Common/UI/UIGroup.cpp new file mode 100644 index 00000000..1899d05b --- /dev/null +++ b/Minecraft.Client/Common/UI/UIGroup.cpp @@ -0,0 +1,421 @@ +#include "stdafx.h" +#include "UIGroup.h" + +UIGroup::UIGroup(EUIGroup group, int iPad) +{ + m_group = group; + m_iPad = iPad; + m_bMenuDisplayed = false; + m_bPauseMenuDisplayed = false; + m_bContainerMenuDisplayed = false; + m_bIgnoreAutosaveMenuDisplayed = false; + m_bIgnorePlayerJoinMenuDisplayed = false; + + m_updateFocusStateCountdown = 0; + + for(unsigned int i = 0; i < eUILayer_COUNT; ++i) + { + m_layers[i] = new UILayer(this); +#ifdef __PSVITA__ + m_layers[i]->m_iLayer=(EUILayer)i; +#endif + } + + m_tooltips = (UIComponent_Tooltips *)m_layers[(int)eUILayer_Tooltips]->addComponent(0, eUIComponent_Tooltips); + + m_tutorialPopup = NULL; + m_hud = NULL; + m_pressStartToPlay = NULL; + if(m_group != eUIGroup_Fullscreen) + { + m_tutorialPopup = (UIComponent_TutorialPopup *)m_layers[(int)eUILayer_Popup]->addComponent(m_iPad, eUIComponent_TutorialPopup); + + m_hud = (UIScene_HUD *)m_layers[(int)eUILayer_HUD]->addComponent(m_iPad, eUIScene_HUD); + + //m_layers[(int)eUILayer_Chat]->addComponent(m_iPad, eUIComponent_Chat); + } + else + { + m_pressStartToPlay = (UIComponent_PressStartToPlay *)m_layers[(int)eUILayer_Tooltips]->addComponent(0, eUIComponent_PressStartToPlay); + } + + m_viewportType = C4JRender::VIEWPORT_TYPE_FULLSCREEN; + + // 4J Stu - Pre-allocate this for cached rendering in scenes. It's horribly slow to do dynamically, but we should only need one + // per group as we will only be displaying one of these types of scenes at a time + m_commandBufferList = MemoryTracker::genLists(1); +} + +void UIGroup::DestroyAll() +{ + for(unsigned int i = 0; i < eUILayer_COUNT; ++i) + { + m_layers[i]->DestroyAll(); + } +} + +void UIGroup::ReloadAll() +{ + // We only need to reload things when they are likely to be rendered + int highestRenderable = 0; + for(; highestRenderable < eUILayer_COUNT; ++highestRenderable) + { + if(m_layers[highestRenderable]->hidesLowerScenes()) break; + } + if(highestRenderable < eUILayer_Fullscreen) highestRenderable = eUILayer_Fullscreen; + for(; highestRenderable >= 0; --highestRenderable) + { + if(highestRenderable < eUILayer_COUNT) m_layers[highestRenderable]->ReloadAll(highestRenderable != (int)eUILayer_Fullscreen); + } +} + +void UIGroup::tick() +{ + // Ignore this group if the player isn't signed in + if(m_iPad >= 0 && !ProfileManager.IsSignedIn(m_iPad)) return; + for(unsigned int i = 0; i < eUILayer_COUNT; ++i) + { + m_layers[i]->tick(); + + // TODO: May wish to ignore ticking other layers here based on current layer + } + + // Handle deferred update focus + if (m_updateFocusStateCountdown > 0) + { + m_updateFocusStateCountdown--; + if (m_updateFocusStateCountdown == 0)_UpdateFocusState(); +} +} + +void UIGroup::render() +{ + // Ignore this group if the player isn't signed in + if(m_iPad >= 0 && !ProfileManager.IsSignedIn(m_iPad)) return; + S32 width = 0; + S32 height = 0; + ui.getRenderDimensions(m_viewportType, width, height); + int highestRenderable = 0; + for(; highestRenderable < eUILayer_COUNT; ++highestRenderable) + { + if(m_layers[highestRenderable]->hidesLowerScenes()) break; + } + for(; highestRenderable >= 0; --highestRenderable) + { + if(highestRenderable < eUILayer_COUNT) m_layers[highestRenderable]->render(width, height,m_viewportType); + } +} + +bool UIGroup::hidesLowerScenes() +{ + // Ignore this group if the player isn't signed in + if(m_iPad >= 0 && !ProfileManager.IsSignedIn(m_iPad)) return false; + bool hidesScenes = false; + for(int i = eUILayer_COUNT - 1; i >= 0; --i) + { + hidesScenes = m_layers[i]->hidesLowerScenes(); + if(hidesScenes) break; + } + return hidesScenes; +} + +void UIGroup::getRenderDimensions(S32 &width, S32 &height) +{ + ui.getRenderDimensions(m_viewportType, width, height); +} + +// NAVIGATION +bool UIGroup::NavigateToScene(int iPad, EUIScene scene, void *initData, EUILayer layer) +{ + bool succeeded = m_layers[(int)layer]->NavigateToScene(iPad, scene, initData); + updateStackStates(); + return succeeded; +} + +bool UIGroup::NavigateBack(int iPad, EUIScene eScene, EUILayer eLayer) +{ + // Keep navigating back on every layer until we hit the target scene + bool foundTarget = false; + for(unsigned int i = 0; i < eUILayer_COUNT; ++i) + { + if(eLayer < eUILayer_COUNT && eLayer != i) continue; + foundTarget = m_layers[i]->NavigateBack(iPad, eScene); + if(foundTarget) break; + } + updateStackStates(); + return foundTarget; +} + +void UIGroup::closeAllScenes() +{ + Minecraft *pMinecraft = Minecraft::GetInstance(); + if( m_iPad >= 0 ) + { + if(pMinecraft != NULL && pMinecraft->localgameModes[m_iPad] != NULL ) + { + TutorialMode *gameMode = (TutorialMode *)pMinecraft->localgameModes[m_iPad]; + + // This just allows it to be shown + gameMode->getTutorial()->showTutorialPopup(true); + } + } + + for(unsigned int i = 0; i < eUILayer_COUNT; ++i) + { + // Ignore the error layer + if(i != (int)eUILayer_Error) m_layers[i]->closeAllScenes(); + } + updateStackStates(); +} + +UIScene *UIGroup::GetTopScene(EUILayer layer) +{ + return m_layers[(int)layer]->GetTopScene(); +} + +bool UIGroup::GetMenuDisplayed() +{ + return m_bMenuDisplayed; +} + +bool UIGroup::IsSceneInStack(EUIScene scene) +{ + bool found = false; + for(unsigned int i = 0; i < eUILayer_COUNT; ++i) + { + found = m_layers[i]->IsSceneInStack(scene); + if(found) break; + } + return found; +} + +bool UIGroup::HasFocus(int iPad) +{ + bool hasFocus = false; + for(unsigned int i = 0; i < eUILayer_COUNT; ++i) + { + if( m_layers[i]->m_hasFocus) + { + if(m_layers[i]->HasFocus(iPad)) + { + hasFocus = true; + } + break; + } + } + return hasFocus; +} + +#ifdef __PSVITA__ +UIScene *UIGroup::getCurrentScene() +{ + UIScene *pScene; + for(unsigned int i = 0; i < eUILayer_COUNT; ++i) + { + pScene=m_layers[i]->getCurrentScene(); + + if(pScene!=NULL) return pScene; + } + + return NULL; +} +#endif + +// INPUT +void UIGroup::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled) +{ + // Ignore this group if the player isn't signed in + if(m_iPad >= 0 && !ProfileManager.IsSignedIn(m_iPad)) return; + for(unsigned int i = 0; i < eUILayer_COUNT; ++i) + { + m_layers[i]->handleInput(iPad, key, repeat, pressed, released, handled); + if(handled) break; + } +} + +// FOCUS + +// Check that a layer may recieve focus, specifically that there is no infocus layer above +bool UIGroup::RequestFocus(UILayer* layerPtr) +{ + // Find the layer + unsigned int layerIndex = GetLayerIndex(layerPtr); + + // Top layer is always allowed focus + if (layerIndex == 0) return true; + + // Check layers above to see if any of them have focus + for (int i = layerIndex-1; i >= 0; i--) + { + if (m_layers[i]->m_hasFocus) return false; + } + + return true; +} + +void UIGroup::showComponent(int iPad, EUIScene scene, EUILayer layer, bool show) +{ + m_layers[layer]->showComponent(iPad, scene, show); +} + +UIScene *UIGroup::addComponent(int iPad, EUIScene scene, EUILayer layer) +{ + return m_layers[layer]->addComponent(iPad, scene); +} + +void UIGroup::removeComponent(EUIScene scene, EUILayer layer) +{ + m_layers[layer]->removeComponent(scene); +} + +void UIGroup::SetViewportType(C4JRender::eViewportType type) +{ + if(m_viewportType != type) + { + m_viewportType = type; + for(unsigned int i = 0; i < eUILayer_COUNT; ++i) + { + m_layers[i]->ReloadAll(true); + } + } +} + +C4JRender::eViewportType UIGroup::GetViewportType() +{ + return m_viewportType; +} + +void UIGroup::HandleDLCMountingComplete() +{ + // Ignore this group if the player isn't signed in + if(m_iPad >= 0 && !ProfileManager.IsSignedIn(m_iPad)) return; + for(unsigned int i = 0; i < eUILayer_COUNT; ++i) + { + app.DebugPrintf("UIGroup::HandleDLCMountingComplete - m_layers[%d]\n",i); + m_layers[i]->HandleDLCMountingComplete(); + } +} + +void UIGroup::HandleDLCInstalled() +{ + // Ignore this group if the player isn't signed in + if(m_iPad >= 0 && !ProfileManager.IsSignedIn(m_iPad)) return; + for(unsigned int i = 0; i < eUILayer_COUNT; ++i) + { + m_layers[i]->HandleDLCInstalled(); + } +} + +#ifdef _XBOX_ONE +void UIGroup::HandleDLCLicenseChange() +{ + // Ignore this group if the player isn't signed in + if(m_iPad >= 0 && !ProfileManager.IsSignedIn(m_iPad)) return; + for(unsigned int i = 0; i < eUILayer_COUNT; ++i) + { + m_layers[i]->HandleDLCLicenseChange(); + } +} +#endif + +bool UIGroup::IsFullscreenGroup() +{ + return m_group == eUIGroup_Fullscreen; +} + + +void UIGroup::handleUnlockFullVersion() +{ + for(unsigned int i = 0; i < eUILayer_COUNT; ++i) + { + m_layers[i]->handleUnlockFullVersion(); + } +} + +void UIGroup::updateStackStates() +{ + m_bMenuDisplayed = false; + m_bPauseMenuDisplayed = false; + m_bContainerMenuDisplayed = false; + m_bIgnoreAutosaveMenuDisplayed = false; + m_bIgnorePlayerJoinMenuDisplayed = false; + + for(unsigned int i = 0; i < eUILayer_COUNT; ++i) + { + m_bMenuDisplayed = m_bMenuDisplayed || m_layers[i]->m_bMenuDisplayed; + m_bPauseMenuDisplayed = m_bPauseMenuDisplayed || m_layers[i]->m_bPauseMenuDisplayed; + m_bContainerMenuDisplayed = m_bContainerMenuDisplayed || m_layers[i]->m_bContainerMenuDisplayed; + m_bIgnoreAutosaveMenuDisplayed = m_bIgnoreAutosaveMenuDisplayed || m_layers[i]->m_bIgnoreAutosaveMenuDisplayed; + m_bIgnorePlayerJoinMenuDisplayed = m_bIgnorePlayerJoinMenuDisplayed || m_layers[i]->m_bIgnorePlayerJoinMenuDisplayed; + } +} + +// Defer update focus till for 10 UI ticks +void UIGroup::UpdateFocusState() +{ + m_updateFocusStateCountdown = 10; +} + +// Pass focus to uppermost layer that accepts focus +void UIGroup::_UpdateFocusState() +{ + bool groupFocusSet = false; + + for(unsigned int i = 0; i < eUILayer_COUNT; ++i) + { + groupFocusSet = m_layers[i]->updateFocusState(true); + if (groupFocusSet) break; + } +} + +// Get the index of the layer +unsigned int UIGroup::GetLayerIndex(UILayer* layerPtr) +{ + for(unsigned int i = 0; i < eUILayer_COUNT; ++i) + { + if (m_layers[i] == layerPtr) return i; + } + + // can't get here... + return 0; +} + +void UIGroup::PrintTotalMemoryUsage(__int64 &totalStatic, __int64 &totalDynamic) +{ + __int64 groupStatic = 0; + __int64 groupDynamic = 0; + app.DebugPrintf(app.USER_SR, "-- BEGIN GROUP %d\n",m_group); + for(unsigned int i = 0; i < eUILayer_COUNT; ++i) + { + app.DebugPrintf(app.USER_SR, " \\- BEGIN LAYER %d\n",i); + m_layers[i]->PrintTotalMemoryUsage(groupStatic, groupDynamic); + app.DebugPrintf(app.USER_SR, " \\- END LAYER %d\n",i); + } + app.DebugPrintf(app.USER_SR, "-- Group static: %d, Group dynamic: %d\n", groupStatic, groupDynamic); + totalStatic += groupStatic; + totalDynamic += groupDynamic; + app.DebugPrintf(app.USER_SR, "-- END GROUP %d\n",m_group); +} + +int UIGroup::getCommandBufferList() +{ + return m_commandBufferList; +} + +// Returns the first scene of given type if it exists, NULL otherwise +UIScene *UIGroup::FindScene(EUIScene sceneType) +{ + UIScene *pScene = NULL; + + for (int i = 0; i < eUILayer_COUNT; i++) + { + pScene = m_layers[i]->FindScene(sceneType); +#ifdef __PS3__ + if (pScene != NULL) return pScene; +#else + if (pScene != nullptr) return pScene; +#endif + } + + return pScene; +} diff --git a/Minecraft.Client/Common/UI/UIGroup.h b/Minecraft.Client/Common/UI/UIGroup.h new file mode 100644 index 00000000..e20fbb02 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIGroup.h @@ -0,0 +1,113 @@ +#pragma once +#include "UILayer.h" +#include "UIEnums.h" + +class UIComponent_Tooltips; +class UIComponent_TutorialPopup; +class UIScene_HUD; +class UIComponent_PressStartToPlay; + +// A group contains a collection of layers for a specific context (e.g. each player has 1 group) +class UIGroup +{ +private: + UILayer *m_layers[eUILayer_COUNT]; + + UIComponent_Tooltips *m_tooltips; + UIComponent_TutorialPopup *m_tutorialPopup; + UIComponent_PressStartToPlay *m_pressStartToPlay; + UIScene_HUD *m_hud; + + C4JRender::eViewportType m_viewportType; + + EUIGroup m_group; + int m_iPad; + + bool m_bMenuDisplayed; + bool m_bPauseMenuDisplayed; + bool m_bContainerMenuDisplayed; + bool m_bIgnoreAutosaveMenuDisplayed; + bool m_bIgnorePlayerJoinMenuDisplayed; + + // Countdown in ticks to update focus state + int m_updateFocusStateCountdown; + + int m_commandBufferList; + +public: + UIGroup(EUIGroup group, int iPad); + +#ifdef __PSVITA__ + EUIGroup GetGroup() {return m_group;} +#endif + UIComponent_Tooltips *getTooltips() { return m_tooltips; } + UIComponent_TutorialPopup *getTutorialPopup() { return m_tutorialPopup; } + UIScene_HUD *getHUD() { return m_hud; } + UIComponent_PressStartToPlay *getPressStartToPlay() { return m_pressStartToPlay; } + + void DestroyAll(); + void ReloadAll(); + + void tick(); + void render(); + bool hidesLowerScenes(); + void getRenderDimensions(S32 &width, S32 &height); + + // NAVIGATION + bool NavigateToScene(int iPad, EUIScene scene, void *initData, EUILayer layer); + bool NavigateBack(int iPad, EUIScene eScene, EUILayer eLayer = eUILayer_COUNT); + void closeAllScenes(); + UIScene *GetTopScene(EUILayer layer); + + bool IsSceneInStack(EUIScene scene); + bool HasFocus(int iPad); + + bool RequestFocus(UILayer* layerPtr); + void UpdateFocusState(); + + bool GetMenuDisplayed(); + bool IsPauseMenuDisplayed() { return m_bPauseMenuDisplayed; } + bool IsContainerMenuDisplayed() { return m_bContainerMenuDisplayed; } + bool IsIgnoreAutosaveMenuDisplayed() { return m_bIgnoreAutosaveMenuDisplayed; } + bool IsIgnorePlayerJoinMenuDisplayed() { return m_bIgnorePlayerJoinMenuDisplayed; } + + // INPUT + void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled); + +#ifdef __PSVITA__ + // Current active scene + UIScene *getCurrentScene(); +#endif + + // FOCUS + bool getFocusState(); + + // A component is an element on a layer that displays BELOW other scenes in this layer, but does not engage in any navigation + // E.g. you can keep a component active while performing navigation with other scenes on this layer + void showComponent(int iPad, EUIScene scene, EUILayer layer, bool show); + UIScene *addComponent(int iPad, EUIScene scene, EUILayer layer); + void removeComponent(EUIScene scene, EUILayer layer); + + void SetViewportType(C4JRender::eViewportType type); + C4JRender::eViewportType GetViewportType(); + + virtual void HandleDLCMountingComplete(); + virtual void HandleDLCInstalled(); +#ifdef _XBOX_ONE + virtual void HandleDLCLicenseChange(); +#endif + bool IsFullscreenGroup(); + + void handleUnlockFullVersion(); + + void PrintTotalMemoryUsage(__int64 &totalStatic, __int64 &totalDynamic); + + unsigned int GetLayerIndex(UILayer* layerPtr); + + int getCommandBufferList(); + UIScene *FindScene(EUIScene sceneType); + +private: + void _UpdateFocusState(); + void updateStackStates(); +}; diff --git a/Minecraft.Client/Common/UI/UILayer.cpp b/Minecraft.Client/Common/UI/UILayer.cpp new file mode 100644 index 00000000..e6f87f81 --- /dev/null +++ b/Minecraft.Client/Common/UI/UILayer.cpp @@ -0,0 +1,870 @@ +#include "stdafx.h" +#include "UI.h" +#include "UILayer.h" +#include "UIScene.h" + +UILayer::UILayer(UIGroup *parent) +{ + m_parentGroup = parent; + m_hasFocus = false; + m_bMenuDisplayed = false; + m_bPauseMenuDisplayed = false; + m_bContainerMenuDisplayed = false; + m_bIgnoreAutosaveMenuDisplayed = false; + m_bIgnorePlayerJoinMenuDisplayed = false; +} + +void UILayer::tick() +{ + // Delete old scenes - deleting a scene can cause a new scene to be deleted, so we need to make a copy of the scenes that we are going to try and destroy this tick + vector<UIScene *>scenesToDeleteCopy; + for( AUTO_VAR(it,m_scenesToDelete.begin()); it != m_scenesToDelete.end(); it++) + { + UIScene *scene = (*it); + scenesToDeleteCopy.push_back(scene); + } + m_scenesToDelete.clear(); + + // Delete the scenes in our copy if they are ready to delete, otherwise add back to the ones that are still to be deleted. Actually deleting a scene might also add something back into m_scenesToDelete. + for( AUTO_VAR(it,scenesToDeleteCopy.begin()); it != scenesToDeleteCopy.end(); it++) + { + UIScene *scene = (*it); + if( scene->isReadyToDelete()) + { + delete scene; + } + else + { + m_scenesToDelete.push_back(scene); + } + } + + while (!m_scenesToDestroy.empty()) + { + UIScene *scene = m_scenesToDestroy.back(); + m_scenesToDestroy.pop_back(); + scene->destroyMovie(); + } + m_scenesToDestroy.clear(); + + for(AUTO_VAR(it,m_components.begin()); it != m_components.end(); ++it) + { + (*it)->tick(); + } + // Note: reverse iterator, the last element is the top of the stack + int sceneIndex = m_sceneStack.size() - 1; + //for(AUTO_VAR(it,m_sceneStack.rbegin()); it != m_sceneStack.rend(); ++it) + while( sceneIndex >= 0 && sceneIndex < m_sceneStack.size() ) + { + //(*it)->tick(); + UIScene *scene = m_sceneStack[sceneIndex]; + scene->tick(); + --sceneIndex; + // TODO: We may wish to ignore ticking the rest of the stack based on this scene + } +} + +void UILayer::render(S32 width, S32 height, C4JRender::eViewportType viewport) +{ + if(!ui.IsExpectingOrReloadingSkin()) + { + for(AUTO_VAR(it,m_components.begin()); it != m_components.end(); ++it) + { + AUTO_VAR(itRef,m_componentRefCount.find((*it)->getSceneType())); + if(itRef != m_componentRefCount.end() && itRef->second.second) + { + if((*it)->isVisible() ) + { + PIXBeginNamedEvent(0, "Rendering component %d", (*it)->getSceneType() ); + (*it)->render(width, height,viewport); + PIXEndNamedEvent(); + } + } + } + } + if(!m_sceneStack.empty()) + { + int lowestRenderable = m_sceneStack.size() - 1; + for(;lowestRenderable >= 0; --lowestRenderable) + { + if(m_sceneStack[lowestRenderable]->hidesLowerScenes()) break; + } + if(lowestRenderable < 0) lowestRenderable = 0; + for(;lowestRenderable < m_sceneStack.size(); ++lowestRenderable) + { + if(m_sceneStack[lowestRenderable]->isVisible() && (!ui.IsExpectingOrReloadingSkin() || m_sceneStack[lowestRenderable]->getSceneType()==eUIScene_Timer)) + { + PIXBeginNamedEvent(0, "Rendering scene %d", m_sceneStack[lowestRenderable]->getSceneType() ); + m_sceneStack[lowestRenderable]->render(width, height,viewport); + PIXEndNamedEvent(); + } + } + } +} + +bool UILayer::IsSceneInStack(EUIScene scene) +{ + bool inStack = false; + for(int i = m_sceneStack.size() - 1;i >= 0; --i) + { + if(m_sceneStack[i]->getSceneType() == scene) + { + inStack = true; + break; + } + } + return inStack; +} + +bool UILayer::HasFocus(int iPad) +{ + bool hasFocus = false; + if(m_hasFocus) + { + for(int i = m_sceneStack.size() - 1;i >= 0; --i) + { + if(m_sceneStack[i]->stealsFocus() ) + { + if(m_sceneStack[i]->hasFocus(iPad)) + { + hasFocus = true; + } + break; + } + } + } + return hasFocus; +} + +bool UILayer::hidesLowerScenes() +{ + bool hidesScenes = false; + for(AUTO_VAR(it,m_components.begin()); it != m_components.end(); ++it) + { + if((*it)->hidesLowerScenes()) + { + hidesScenes = true; + break; + } + } + if(!hidesScenes && !m_sceneStack.empty()) + { + for(int i = m_sceneStack.size() - 1;i >= 0; --i) + { + if(m_sceneStack[i]->hidesLowerScenes()) + { + hidesScenes = true; + break; + } + } + } + return hidesScenes; +} + +void UILayer::getRenderDimensions(S32 &width, S32 &height) +{ + m_parentGroup->getRenderDimensions(width, height); +} + +void UILayer::DestroyAll() +{ + for(AUTO_VAR(it,m_components.begin()); it != m_components.end(); ++it) + { + (*it)->destroyMovie(); + } + for(AUTO_VAR(it, m_sceneStack.begin()); it != m_sceneStack.end(); ++it) + { + (*it)->destroyMovie(); + } +} + +void UILayer::ReloadAll(bool force) +{ + for(AUTO_VAR(it,m_components.begin()); it != m_components.end(); ++it) + { + (*it)->reloadMovie(force); + } + if(!m_sceneStack.empty()) + { + int lowestRenderable = 0; + for(;lowestRenderable < m_sceneStack.size(); ++lowestRenderable) + { + m_sceneStack[lowestRenderable]->reloadMovie(); + } + } +} + +bool UILayer::GetMenuDisplayed() +{ + return m_bMenuDisplayed; +} + +bool UILayer::NavigateToScene(int iPad, EUIScene scene, void *initData) +{ + UIScene *newScene = NULL; + switch(scene) + { + // Debug +#ifdef _DEBUG_MENUS_ENABLED + case eUIScene_DebugOverlay: + newScene = new UIScene_DebugOverlay(iPad, initData, this); + break; + case eUIScene_DebugSetCamera: + newScene = new UIScene_DebugSetCamera(iPad, initData, this); + break; + case eUIScene_DebugCreateSchematic: + newScene = new UIScene_DebugCreateSchematic(iPad, initData, this); + break; +#endif + case eUIScene_DebugOptions: + newScene = new UIScene_DebugOptionsMenu(iPad, initData, this); + break; + + // Containers + case eUIScene_InventoryMenu: + newScene = new UIScene_InventoryMenu(iPad, initData, this); + break; + case eUIScene_CreativeMenu: + newScene = new UIScene_CreativeMenu(iPad, initData, this); + break; + case eUIScene_ContainerMenu: + case eUIScene_LargeContainerMenu: + newScene = new UIScene_ContainerMenu(iPad, initData, this); + break; + case eUIScene_BrewingStandMenu: + newScene = new UIScene_BrewingStandMenu(iPad, initData, this); + break; + case eUIScene_DispenserMenu: + newScene = new UIScene_DispenserMenu(iPad, initData, this); + break; + case eUIScene_EnchantingMenu: + newScene = new UIScene_EnchantingMenu(iPad, initData, this); + break; + case eUIScene_FurnaceMenu: + newScene = new UIScene_FurnaceMenu(iPad, initData, this); + break; + case eUIScene_Crafting2x2Menu: + case eUIScene_Crafting3x3Menu: + newScene = new UIScene_CraftingMenu(iPad, initData, this); + break; + case eUIScene_TradingMenu: + newScene = new UIScene_TradingMenu(iPad, initData, this); + break; + case eUIScene_AnvilMenu: + newScene = new UIScene_AnvilMenu(iPad, initData, this); + break; + + // Help and Options + case eUIScene_HelpAndOptionsMenu: + newScene = new UIScene_HelpAndOptionsMenu(iPad, initData, this); + break; + case eUIScene_SettingsMenu: + newScene = new UIScene_SettingsMenu(iPad, initData, this); + break; + case eUIScene_SettingsOptionsMenu: + newScene = new UIScene_SettingsOptionsMenu(iPad, initData, this); + break; + case eUIScene_SettingsAudioMenu: + newScene = new UIScene_SettingsAudioMenu(iPad, initData, this); + break; + case eUIScene_SettingsControlMenu: + newScene = new UIScene_SettingsControlMenu(iPad, initData, this); + break; + case eUIScene_SettingsGraphicsMenu: + newScene = new UIScene_SettingsGraphicsMenu(iPad, initData, this); + break; + case eUIScene_SettingsUIMenu: + newScene = new UIScene_SettingsUIMenu(iPad, initData, this); + break; + case eUIScene_SkinSelectMenu: + newScene = new UIScene_SkinSelectMenu(iPad, initData, this); + break; + case eUIScene_HowToPlayMenu: + newScene = new UIScene_HowToPlayMenu(iPad, initData, this); + break; + case eUIScene_HowToPlay: + newScene = new UIScene_HowToPlay(iPad, initData, this); + break; + case eUIScene_ControlsMenu: + newScene = new UIScene_ControlsMenu(iPad, initData, this); + break; + case eUIScene_ReinstallMenu: + newScene = new UIScene_ReinstallMenu(iPad, initData, this); + break; + case eUIScene_Credits: + newScene = new UIScene_Credits(iPad, initData, this); + break; + + + // Other in-game + case eUIScene_PauseMenu: + newScene = new UIScene_PauseMenu(iPad, initData, this); + break; + case eUIScene_DeathMenu: + newScene = new UIScene_DeathMenu(iPad, initData, this); + break; + case eUIScene_ConnectingProgress: + newScene = new UIScene_ConnectingProgress(iPad, initData, this); + break; + case eUIScene_SignEntryMenu: + newScene = new UIScene_SignEntryMenu(iPad, initData, this); + break; + case eUIScene_InGameInfoMenu: + newScene = new UIScene_InGameInfoMenu(iPad, initData, this); + break; + case eUIScene_InGameHostOptionsMenu: + newScene = new UIScene_InGameHostOptionsMenu(iPad, initData, this); + break; + case eUIScene_InGamePlayerOptionsMenu: + newScene = new UIScene_InGamePlayerOptionsMenu(iPad, initData, this); + break; +#if defined(_XBOX_ONE) || defined(__ORBIS__) + case eUIScene_InGameSaveManagementMenu: + newScene = new UIScene_InGameSaveManagementMenu(iPad, initData, this); + break; +#endif + case eUIScene_TeleportMenu: + newScene = new UIScene_TeleportMenu(iPad, initData, this); + break; + case eUIScene_EndPoem: + if(IsSceneInStack(eUIScene_EndPoem)) + { + app.DebugPrintf("Skipped EndPoem as one was already showing\n"); + return false; + } + else + { + newScene = new UIScene_EndPoem(iPad, initData, this); + } + break; + + + // Frontend + case eUIScene_TrialExitUpsell: + newScene = new UIScene_TrialExitUpsell(iPad, initData, this); + break; + case eUIScene_Intro: + newScene = new UIScene_Intro(iPad, initData, this); + break; + case eUIScene_SaveMessage: + newScene = new UIScene_SaveMessage(iPad, initData, this); + break; + case eUIScene_MainMenu: + newScene = new UIScene_MainMenu(iPad, initData, this); + break; + case eUIScene_LoadOrJoinMenu: + newScene = new UIScene_LoadOrJoinMenu(iPad, initData, this); + break; + case eUIScene_LoadMenu: + newScene = new UIScene_LoadMenu(iPad, initData, this); + break; + case eUIScene_JoinMenu: + newScene = new UIScene_JoinMenu(iPad, initData, this); + break; + case eUIScene_CreateWorldMenu: + newScene = new UIScene_CreateWorldMenu(iPad, initData, this); + break; + case eUIScene_LaunchMoreOptionsMenu: + newScene = new UIScene_LaunchMoreOptionsMenu(iPad, initData, this); + break; + case eUIScene_FullscreenProgress: + newScene = new UIScene_FullscreenProgress(iPad, initData, this); + break; + case eUIScene_LeaderboardsMenu: + newScene = new UIScene_LeaderboardsMenu(iPad, initData, this); + break; + case eUIScene_DLCMainMenu: + newScene = new UIScene_DLCMainMenu(iPad, initData, this); + break; + case eUIScene_DLCOffersMenu: + newScene = new UIScene_DLCOffersMenu(iPad, initData, this); + break; + case eUIScene_EULA: + newScene = new UIScene_EULA(iPad, initData, this); + break; + + // Other + case eUIScene_Keyboard: + newScene = new UIScene_Keyboard(iPad, initData, this); + break; + case eUIScene_QuadrantSignin: + newScene = new UIScene_QuadrantSignin(iPad, initData, this); + break; + case eUIScene_MessageBox: + if(IsSceneInStack(eUIScene_MessageBox)) + { + app.DebugPrintf("Skipped MessageBox as one was already showing\n"); + return false; + } + else + { + newScene = new UIScene_MessageBox(iPad, initData, this); + } + break; + case eUIScene_Timer: + newScene = new UIScene_Timer(iPad, initData, this); + break; + }; + + if(newScene == NULL) + { + app.DebugPrintf("WARNING: Scene %d was not created. Add it to UILayer::NavigateToScene\n", scene); + return false; + } + + if(m_sceneStack.size() > 0) + { + newScene->setBackScene(m_sceneStack[m_sceneStack.size()-1]); + } + + m_sceneStack.push_back(newScene); + + updateFocusState(); + + newScene->tick(); + + return true; +} + +bool UILayer::NavigateBack(int iPad, EUIScene eScene) +{ + if(m_sceneStack.size() == 0) return false; + + bool navigated = false; + if(eScene < eUIScene_COUNT) + { + UIScene *scene = NULL; + do + { + scene = m_sceneStack.back(); + if(scene->getSceneType() == eScene) + { + navigated = true; + break; + } + else + { + if(scene->hasFocus(iPad)) + { + removeScene(scene); + } + else + { + // No focus on the top scene, so this use shouldn't be navigating! + break; + } + } + } while(m_sceneStack.size() > 0); + + } + else + { + UIScene *scene = m_sceneStack.back(); + if(scene->hasFocus(iPad)) + { + removeScene(scene); + navigated = true; + } + } + return navigated; +} + +void UILayer::showComponent(int iPad, EUIScene scene, bool show) +{ + AUTO_VAR(it,m_componentRefCount.find(scene)); + if(it != m_componentRefCount.end()) + { + it->second.second = show; + return; + } + if(show) addComponent(iPad,scene); +} + +bool UILayer::isComponentVisible(EUIScene scene) +{ + bool visible = false; + AUTO_VAR(it,m_componentRefCount.find(scene)); + if(it != m_componentRefCount.end()) + { + visible = it->second.second; + } + return visible; +} + +UIScene *UILayer::addComponent(int iPad, EUIScene scene, void *initData) +{ + AUTO_VAR(it,m_componentRefCount.find(scene)); + if(it != m_componentRefCount.end()) + { + ++it->second.first; + + for(AUTO_VAR(itComp,m_components.begin()); itComp != m_components.end(); ++itComp) + { + if( (*itComp)->getSceneType() == scene ) + { + return *itComp; + } + } + return NULL; + } + UIScene *newScene = NULL; + + switch(scene) + { + case eUIComponent_Panorama: + newScene = new UIComponent_Panorama(iPad, initData, this); + m_componentRefCount[scene] = pair<int,bool>(1,true); + break; + case eUIComponent_DebugUIConsole: + newScene = new UIComponent_DebugUIConsole(iPad, initData, this); + m_componentRefCount[scene] = pair<int,bool>(1,true); + break; + case eUIComponent_DebugUIMarketingGuide: + newScene = new UIComponent_DebugUIMarketingGuide(iPad, initData, this); + m_componentRefCount[scene] = pair<int,bool>(1,true); + break; + case eUIComponent_Logo: + newScene = new UIComponent_Logo(iPad, initData, this); + m_componentRefCount[scene] = pair<int,bool>(1,true); + break; + case eUIComponent_Tooltips: + newScene = new UIComponent_Tooltips(iPad, initData, this); + m_componentRefCount[scene] = pair<int,bool>(1,true); + break; + case eUIComponent_TutorialPopup: + newScene = new UIComponent_TutorialPopup(iPad, initData, this); + // Start hidden + m_componentRefCount[scene] = pair<int,bool>(1,false); + break; + case eUIScene_HUD: + newScene = new UIScene_HUD(iPad, initData, this); + // Start hidden + m_componentRefCount[scene] = pair<int,bool>(1,false); + break; + case eUIComponent_Chat: + newScene = new UIComponent_Chat(iPad, initData, this); + m_componentRefCount[scene] = pair<int,bool>(1,true); + break; + case eUIComponent_PressStartToPlay: + newScene = new UIComponent_PressStartToPlay(iPad, initData, this); + m_componentRefCount[scene] = pair<int,bool>(1,true); + break; + case eUIComponent_MenuBackground: + newScene = new UIComponent_MenuBackground(iPad, initData, this); + m_componentRefCount[scene] = pair<int,bool>(1,true); + break; + }; + + if(newScene == NULL) return NULL; + + m_components.push_back(newScene); + + return newScene; +} + +void UILayer::removeComponent(EUIScene scene) +{ + AUTO_VAR(it,m_componentRefCount.find(scene)); + if(it != m_componentRefCount.end()) + { + --it->second.first; + + if(it->second.first <= 0) + { + m_componentRefCount.erase(it); + for(AUTO_VAR(compIt, m_components.begin()) ; compIt != m_components.end(); ) + { + if( (*compIt)->getSceneType() == scene) + { +#ifdef __PSVITA__ + // remove any touchboxes + ui.TouchBoxesClear((*compIt)); +#endif + m_scenesToDelete.push_back((*compIt)); + (*compIt)->handleDestroy(); // For anything that might require the pointer be valid + compIt = m_components.erase(compIt); + } + else + { + ++compIt; + } + } + } + } +} + +void UILayer::removeScene(UIScene *scene) +{ +#ifdef __PSVITA__ + // remove any touchboxes + ui.TouchBoxesClear(scene); +#endif + + AUTO_VAR(newEnd, std::remove(m_sceneStack.begin(), m_sceneStack.end(), scene) ); + m_sceneStack.erase(newEnd, m_sceneStack.end()); + + m_scenesToDelete.push_back(scene); + + scene->handleDestroy(); // For anything that might require the pointer be valid + + bool hadFocus = m_hasFocus; + updateFocusState(); + + // If this layer has focus, pass it on + if (m_hasFocus || hadFocus) + { + m_hasFocus = false; + m_parentGroup->UpdateFocusState(); + } +} + +void UILayer::closeAllScenes() +{ + vector<UIScene *> temp; + temp.insert(temp.end(), m_sceneStack.begin(), m_sceneStack.end()); + m_sceneStack.clear(); + for(AUTO_VAR(it, temp.begin()); it != temp.end(); ++it) + { +#ifdef __PSVITA__ + // remove any touchboxes + ui.TouchBoxesClear(*it); +#endif + m_scenesToDelete.push_back(*it); + (*it)->handleDestroy(); // For anything that might require the pointer be valid + } + + updateFocusState(); + + // If this layer has focus, pass it on + if (m_hasFocus) + { + m_hasFocus = false; + m_parentGroup->UpdateFocusState(); + } +} + +// Get top scene on stack (or NULL if stack is empty) +UIScene *UILayer::GetTopScene() +{ + if(m_sceneStack.size() == 0) + { + return NULL; + } + else + { + return m_sceneStack[m_sceneStack.size()-1]; + } +} + +// Updates layer focus state if no error message is present (unless this is the error layer) +bool UILayer::updateFocusState(bool allowedFocus /* = false */) +{ + // If haveFocus is false, request it + if (!allowedFocus) + { + // To update focus in this layer we need to request focus from group + // Focus will be denied if there's an upper layer that needs focus + allowedFocus = m_parentGroup->RequestFocus(this); + } + + m_bMenuDisplayed = false; + m_bPauseMenuDisplayed = false; + m_bContainerMenuDisplayed = false; + m_bIgnoreAutosaveMenuDisplayed = false; + m_bIgnorePlayerJoinMenuDisplayed = false; + + bool layerFocusSet = false; + for(AUTO_VAR(it,m_sceneStack.rbegin()); it != m_sceneStack.rend(); ++it) + { + UIScene *scene = *it; + + // UPDATE FOCUS STATES + if(!layerFocusSet && allowedFocus && scene->stealsFocus()) + { + scene->gainFocus(); + layerFocusSet = true; + } + else + { + scene->loseFocus(); + if(allowedFocus && app.GetGameStarted()) + { + // 4J Stu - This is a memory optimisation so we don't keep scenes loaded in memory all the time + // This is required for PS3 (and likely Vita), but I'm removing it on XboxOne so that we can avoid + // the scene creation time (which can be >0.5s) since we have the memory to spare +#ifndef _XBOX_ONE + m_scenesToDestroy.push_back(scene); +#endif + } + } + + /// UPDATE STACK STATES + + // 4J-PB - this should just be true + m_bMenuDisplayed=true; + + EUIScene sceneType = scene->getSceneType(); + switch(sceneType) + { + case eUIScene_PauseMenu: + m_bPauseMenuDisplayed = true; + break; + case eUIScene_Crafting2x2Menu: + case eUIScene_Crafting3x3Menu: + case eUIScene_FurnaceMenu: + case eUIScene_ContainerMenu: + case eUIScene_LargeContainerMenu: + case eUIScene_InventoryMenu: + case eUIScene_CreativeMenu: + case eUIScene_DispenserMenu: + case eUIScene_BrewingStandMenu: + case eUIScene_EnchantingMenu: + m_bContainerMenuDisplayed=true; + + // Intentional fall-through + case eUIScene_DeathMenu: + case eUIScene_FullscreenProgress: + case eUIScene_SignEntryMenu: + case eUIScene_EndPoem: + m_bIgnoreAutosaveMenuDisplayed = true; + break; + } + + switch(sceneType) + { + case eUIScene_FullscreenProgress: + case eUIScene_EndPoem: + case eUIScene_Credits: + case eUIScene_LeaderboardsMenu: + m_bIgnorePlayerJoinMenuDisplayed = true; + break; + } + } + m_hasFocus = layerFocusSet; + + return m_hasFocus; +} + +#ifdef __PSVITA__ +UIScene *UILayer::getCurrentScene() +{ + // Note: reverse iterator, the last element is the top of the stack + for(AUTO_VAR(it,m_sceneStack.rbegin()); it != m_sceneStack.rend(); ++it) + { + UIScene *scene = *it; + // 4J-PB - only used on Vita, so iPad 0 is fine + if(scene->hasFocus(0) && scene->canHandleInput()) + { + return scene; + } +} + + return NULL; +} +#endif + +void UILayer::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled) +{ + // Note: reverse iterator, the last element is the top of the stack + for(AUTO_VAR(it,m_sceneStack.rbegin()); it != m_sceneStack.rend(); ++it) + { + UIScene *scene = *it; + if(scene->hasFocus(iPad) && scene->canHandleInput()) + { + // 4J-PB - ignore repeats of action ABXY buttons + // fix for PS3 213 - [MAIN MENU] Holding down buttons will continue to activate every prompt. + // 4J Stu - Changed this slightly to add the allowRepeat function so we can allow repeats in the crafting menu + if(repeat && !scene->allowRepeat(key) ) + { + return; + } + scene->handleInput(iPad, key, repeat, pressed, released, handled); + } + + // Fix for PS3 #444 - [IN GAME] If the user keeps pressing CROSS while on the 'Save Game' screen the title will crash. + handled = handled || scene->hidesLowerScenes(); + if(handled ) break; + } + + // Components can't take input or focus +} + +void UILayer::HandleDLCMountingComplete() +{ + for(AUTO_VAR(it,m_sceneStack.rbegin()); it != m_sceneStack.rend(); ++it) + { + UIScene *topScene = *it; + app.DebugPrintf("UILayer::HandleDLCMountingComplete - topScene\n"); + topScene->HandleDLCMountingComplete(); + } +} + +void UILayer::HandleDLCInstalled() +{ + for(AUTO_VAR(it,m_sceneStack.rbegin()); it != m_sceneStack.rend(); ++it) + { + UIScene *topScene = *it; + topScene->HandleDLCInstalled(); + } +} + +#ifdef _XBOX_ONE +void UILayer::HandleDLCLicenseChange() +{ + for(AUTO_VAR(it,m_sceneStack.rbegin()); it != m_sceneStack.rend(); ++it) + { + UIScene *topScene = *it; + topScene->HandleDLCLicenseChange(); + } +} +#endif + +bool UILayer::IsFullscreenGroup() +{ + return m_parentGroup->IsFullscreenGroup(); +} + +C4JRender::eViewportType UILayer::getViewport() +{ + return m_parentGroup->GetViewportType(); +} + + +void UILayer::handleUnlockFullVersion() +{ + for(AUTO_VAR(it, m_sceneStack.begin()); it != m_sceneStack.end(); ++it) + { + (*it)->handleUnlockFullVersion(); + } +} + +void UILayer::PrintTotalMemoryUsage(__int64 &totalStatic, __int64 &totalDynamic) +{ + __int64 layerStatic = 0; + __int64 layerDynamic = 0; + for(AUTO_VAR(it,m_components.begin()); it != m_components.end(); ++it) + { + (*it)->PrintTotalMemoryUsage(layerStatic, layerDynamic); + } + for(AUTO_VAR(it, m_sceneStack.begin()); it != m_sceneStack.end(); ++it) + { + (*it)->PrintTotalMemoryUsage(layerStatic, layerDynamic); + } + app.DebugPrintf(app.USER_SR, " \\- Layer static: %d , Layer dynamic: %d\n", layerStatic, layerDynamic); + totalStatic += layerStatic; + totalDynamic += layerDynamic; +} + +// Returns the first scene of given type if it exists, NULL otherwise +UIScene *UILayer::FindScene(EUIScene sceneType) +{ + for (int i = 0; i < m_sceneStack.size(); i++) + { + if (m_sceneStack[i]->getSceneType() == sceneType) + { + return m_sceneStack[i]; + } + } + + return NULL; +}
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UILayer.h b/Minecraft.Client/Common/UI/UILayer.h new file mode 100644 index 00000000..2840f23f --- /dev/null +++ b/Minecraft.Client/Common/UI/UILayer.h @@ -0,0 +1,91 @@ +#pragma once +#include "UIEnums.h" +using namespace std; +class UIScene; +class UIGroup; + +// A layer include a collection of scenes and other components +class UILayer +{ +private: + vector<UIScene *> m_sceneStack; // Operates as a stack mainly, but we may wish to iterate over all elements + vector<UIScene *> m_components; // Other componenents in this scene that to do not conform the the user nav stack, and cannot take focus + vector<UIScene *> m_scenesToDelete; // A list of scenes to delete + vector<UIScene *> m_scenesToDestroy; // A list of scenes where we want to dump the swf + +#ifdef __ORBIS__ + unordered_map<EUIScene,std::pair<int,bool>,std::hash<int>> m_componentRefCount; +#else + unordered_map<EUIScene,pair<int,bool> > m_componentRefCount; +#endif + +public: + bool m_hasFocus; // True if the layer "has focus", should be the only layer in the group + bool m_bMenuDisplayed; + bool m_bPauseMenuDisplayed; + bool m_bContainerMenuDisplayed; + bool m_bIgnoreAutosaveMenuDisplayed; + bool m_bIgnorePlayerJoinMenuDisplayed; + +#ifdef __PSVITA__ + EUILayer m_iLayer; +#endif + + UIGroup *m_parentGroup; +public: + UILayer(UIGroup *parent); + + void tick(); + void render(S32 width, S32 height, C4JRender::eViewportType viewport); + void getRenderDimensions(S32 &width, S32 &height); + + void DestroyAll(); + void ReloadAll(bool force = false); + + // NAVIGATION + bool NavigateToScene(int iPad, EUIScene scene, void *initData); + bool NavigateBack(int iPad, EUIScene eScene); + void removeScene(UIScene *scene); + void closeAllScenes(); + UIScene *GetTopScene(); + + bool GetMenuDisplayed(); + bool IsPauseMenuDisplayed() { return m_bPauseMenuDisplayed; } + + bool IsSceneInStack(EUIScene scene); + bool HasFocus(int iPad); + + bool hidesLowerScenes(); + + // A component is an element on a layer that displays BELOW other scenes in this layer, but does not engage in any navigation + // E.g. you can keep a component active while performing navigation with other scenes on this layer + void showComponent(int iPad, EUIScene scene, bool show); + bool isComponentVisible(EUIScene scene); + UIScene *addComponent(int iPad, EUIScene scene, void *initData = NULL); + void removeComponent(EUIScene scene); + + // INPUT + void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled); +#ifdef __PSVITA__ + // Current active scene + UIScene *getCurrentScene(); +#endif + // FOCUS + + bool updateFocusState(bool allowedFocus = false); + +public: + bool IsFullscreenGroup(); + C4JRender::eViewportType getViewport(); + + virtual void HandleDLCMountingComplete(); + virtual void HandleDLCInstalled(); +#ifdef _XBOX_ONE + virtual void HandleDLCLicenseChange(); +#endif + void handleUnlockFullVersion(); + UIScene *FindScene(EUIScene sceneType); + + void PrintTotalMemoryUsage(__int64 &totalStatic, __int64 &totalDynamic); + +}; diff --git a/Minecraft.Client/Common/UI/UIScene.cpp b/Minecraft.Client/Common/UI/UIScene.cpp new file mode 100644 index 00000000..e7d907ec --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene.cpp @@ -0,0 +1,1248 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIScene.h" + +#include "..\..\Lighting.h" +#include "..\..\LocalPlayer.h" +#include "..\..\ItemRenderer.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.item.h" + +UIScene::UIScene(int iPad, UILayer *parentLayer) +{ + m_parentLayer = parentLayer; + m_iPad = iPad; + swf = NULL; + m_pItemRenderer = NULL; + + bHasFocus = false; + m_hasTickedOnce = false; + m_bFocussedOnce = false; + m_bVisible = true; + m_bCanHandleInput = false; + m_bIsReloading = false; + + m_iFocusControl = -1; + m_iFocusChild = 0; + m_lastOpacity = 1.0f; + m_bUpdateOpacity = false; + + m_backScene = NULL; + + m_cacheSlotRenders = false; + m_needsCacheRendered = true; + m_expectedCachedSlotCount = 0; + m_callbackUniqueId = 0; +} + +UIScene::~UIScene() +{ + /* Destroy the Iggy player. */ + IggyPlayerDestroy( swf ); + + for(AUTO_VAR(it,m_registeredTextures.begin()); it != m_registeredTextures.end(); ++it) + { + ui.unregisterSubstitutionTexture( it->first, it->second ); + } + + if(m_callbackUniqueId != 0) + { + ui.UnregisterCallbackId(m_callbackUniqueId); + } + + if(m_pItemRenderer != NULL) delete m_pItemRenderer; +} + +void UIScene::destroyMovie() +{ + /* Destroy the Iggy player. */ + IggyPlayerDestroy( swf ); + swf = NULL; + + // Clear out the controls collection (doesn't delete the controls, and they get re-setup later) + m_controls.clear(); + + // Clear out all the fast names for the current movie + m_fastNames.clear(); +} + +void UIScene::reloadMovie(bool force) +{ + if(!force && (stealsFocus() && (getSceneType() != eUIScene_FullscreenProgress && !bHasFocus))) return; + + m_bIsReloading = true; + if(swf) + { + /* Destroy the Iggy player. */ + IggyPlayerDestroy( swf ); + + // Clear out the controls collection (doesn't delete the controls, and they get re-setup later) + m_controls.clear(); + + // Clear out all the fast names for the current movie + m_fastNames.clear(); + } + + // Reload everything + initialiseMovie(); + + handlePreReload(); + + // Reload controls + for(AUTO_VAR(it, m_controls.begin()); it != m_controls.end(); ++it) + { + (*it)->ReInit(); + } + + handleReload(); + + IggyDataValue result; + IggyDataValue value[1]; + + value[0].type = IGGY_DATATYPE_number; + value[0].number = m_iFocusControl; + + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcSetFocus , 1 , value ); + + m_needsCacheRendered = true; + m_bIsReloading = false; +} + +bool UIScene::needsReloaded() +{ + return !swf && (!stealsFocus() || bHasFocus); +} + +bool UIScene::hasMovie() +{ + return swf != NULL; +} + +F64 UIScene::getSafeZoneHalfHeight() +{ + float height = ui.getScreenHeight(); + + float safeHeight = 0.0f; + +#ifndef __PSVITA__ + if( !RenderManager.IsHiDef() && RenderManager.IsWidescreen() ) + { + // 90% safezone + safeHeight = height * (0.15f / 2); + } + else + { + // 90% safezone + safeHeight = height * (0.1f / 2); + } +#endif + return safeHeight; +} + +F64 UIScene::getSafeZoneHalfWidth() +{ + float width = ui.getScreenWidth(); + + float safeWidth = 0.0f; +#ifndef __PSVITA__ + if( !RenderManager.IsHiDef() && RenderManager.IsWidescreen() ) + { + // 85% safezone + safeWidth = width * (0.15f / 2); + } + else + { + // 90% safezone + safeWidth = width * (0.1f / 2); + } +#endif + return safeWidth; +} + +void UIScene::updateSafeZone() +{ + // Distance from edge + F64 safeTop = 0.0; + F64 safeBottom = 0.0; + F64 safeLeft = 0.0; + F64 safeRight = 0.0; + + switch( m_parentLayer->getViewport() ) + { + case C4JRender::VIEWPORT_TYPE_SPLIT_TOP: + safeTop = getSafeZoneHalfHeight(); + break; + case C4JRender::VIEWPORT_TYPE_SPLIT_BOTTOM: + safeBottom = getSafeZoneHalfHeight(); + break; + case C4JRender::VIEWPORT_TYPE_SPLIT_LEFT: + safeLeft = getSafeZoneHalfWidth(); + break; + case C4JRender::VIEWPORT_TYPE_SPLIT_RIGHT: + safeRight = getSafeZoneHalfWidth(); + break; + case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_LEFT: + safeTop = getSafeZoneHalfHeight(); + safeLeft = getSafeZoneHalfWidth(); + break; + case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_RIGHT: + safeTop = getSafeZoneHalfHeight(); + safeRight = getSafeZoneHalfWidth(); + break; + case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_LEFT: + safeBottom = getSafeZoneHalfHeight(); + safeLeft = getSafeZoneHalfWidth(); + break; + case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_RIGHT: + safeBottom = getSafeZoneHalfHeight(); + safeRight = getSafeZoneHalfWidth(); + break; + case C4JRender::VIEWPORT_TYPE_FULLSCREEN: + default: + safeTop = getSafeZoneHalfHeight(); + safeBottom = getSafeZoneHalfHeight(); + safeLeft = getSafeZoneHalfWidth(); + safeRight = getSafeZoneHalfWidth(); + break; + } + setSafeZone(safeTop, safeBottom, safeLeft, safeRight); +} + +void UIScene::setSafeZone(S32 safeTop, S32 safeBottom, S32 safeLeft, S32 safeRight) +{ + IggyDataValue result; + IggyDataValue value[4]; + + value[0].type = IGGY_DATATYPE_number; + value[0].number = safeTop; + value[1].type = IGGY_DATATYPE_number; + value[1].number = safeBottom; + value[2].type = IGGY_DATATYPE_number; + value[2].number = safeLeft; + value[3].type = IGGY_DATATYPE_number; + value[3].number = safeRight; + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcSetSafeZone , 4 , value ); +} + +void UIScene::initialiseMovie() +{ + loadMovie(); + mapElementsAndNames(); + + updateSafeZone(); + + m_bUpdateOpacity = true; +} + +#ifdef __PSVITA__ +void UIScene::SetFocusToElement(int iID) +{ + IggyDataValue result; + IggyDataValue value[1]; + + value[0].type = IGGY_DATATYPE_number; + value[0].number = iID; + + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcSetFocus , 1 , value ); + + // also trigger handle focus change (just in case if anything else in relation needs updating!) + _handleFocusChange(iID, 0); +} +#endif + +bool UIScene::mapElementsAndNames() +{ + m_rootPath = IggyPlayerRootPath( swf ); + + m_funcRemoveObject = registerFastName( L"RemoveObject" ); + m_funcSlideLeft = registerFastName( L"SlideLeft" ); + m_funcSlideRight = registerFastName( L"SlideRight" ); + m_funcSetSafeZone = registerFastName( L"SetSafeZone" ); + m_funcSetAlpha = registerFastName( L"SetAlpha" ); + m_funcSetFocus = registerFastName( L"SetFocus" ); + m_funcHorizontalResizeCheck = registerFastName( L"DoHorizontalResizeCheck"); + return true; +} + +extern CRITICAL_SECTION s_loadSkinCS; +void UIScene::loadMovie() +{ + EnterCriticalSection(&UIController::ms_reloadSkinCS); // MGH - added to prevent crash loading Iggy movies while the skins were being reloaded + wstring moviePath = getMoviePath(); + +#ifdef __PS3__ + if(RenderManager.IsWidescreen()) + { + moviePath.append(L"720.swf"); + m_loadedResolution = eSceneResolution_720; + } + else + { + moviePath.append(L"480.swf"); + m_loadedResolution = eSceneResolution_480; + } +#elif defined __PSVITA__ + moviePath.append(L"Vita.swf"); + m_loadedResolution = eSceneResolution_Vita; +#elif defined _WINDOWS64 + if(ui.getScreenHeight() == 720) + { + moviePath.append(L"720.swf"); + m_loadedResolution = eSceneResolution_720; + } + else if(ui.getScreenHeight() == 480) + { + moviePath.append(L"480.swf"); + m_loadedResolution = eSceneResolution_480; + } + else if(ui.getScreenHeight() < 720) + { + moviePath.append(L"Vita.swf"); + m_loadedResolution = eSceneResolution_Vita; + } + else + { + moviePath.append(L"1080.swf"); + m_loadedResolution = eSceneResolution_1080; + } +#else + moviePath.append(L"1080.swf"); + m_loadedResolution = eSceneResolution_1080; +#endif + + if(!app.hasArchiveFile(moviePath)) + { + app.DebugPrintf("WARNING: Could not find iggy movie %ls, falling back on 720\n", moviePath.c_str()); + + moviePath = getMoviePath(); + moviePath.append(L"720.swf"); + m_loadedResolution = eSceneResolution_720; + + if(!app.hasArchiveFile(moviePath)) + { + app.DebugPrintf("ERROR: Could not find any iggy movie for %ls!\n", moviePath.c_str()); +#ifndef _CONTENT_PACKAGE + __debugbreak(); +#endif + app.FatalLoadError(); + } + } + + byteArray baFile = ui.getMovieData(moviePath.c_str()); + __int64 beforeLoad = ui.iggyAllocCount; + swf = IggyPlayerCreateFromMemory ( baFile.data , baFile.length, NULL); + __int64 afterLoad = ui.iggyAllocCount; + IggyPlayerInitializeAndTickRS ( swf ); + __int64 afterTick = ui.iggyAllocCount; + + if(!swf) + { + app.DebugPrintf("ERROR: Failed to load iggy scene!\n"); +#ifndef _CONTENT_PACKAGE + __debugbreak(); +#endif + app.FatalLoadError(); + } + app.DebugPrintf( app.USER_SR, "Loaded iggy movie %ls\n", moviePath.c_str() ); + IggyProperties *properties = IggyPlayerProperties ( swf ); + m_movieHeight = properties->movie_height_in_pixels; + m_movieWidth = properties->movie_width_in_pixels; + + m_renderWidth = m_movieWidth; + m_renderHeight = m_movieHeight; + + S32 width, height; + m_parentLayer->getRenderDimensions(width, height); + IggyPlayerSetDisplaySize( swf, width, height ); + + IggyPlayerSetUserdata(swf,this); + +//#ifdef _DEBUG +#if 0 + IggyMemoryUseInfo memoryInfo; + rrbool res; + int iteration = 0; + __int64 totalStatic = 0; + __int64 totalDynamic = 0; + while(res = IggyDebugGetMemoryUseInfo ( swf , + NULL , + 0 , + 0 , + iteration , + &memoryInfo )) + { + totalStatic += memoryInfo.static_allocation_bytes; + totalDynamic += memoryInfo.dynamic_allocation_bytes; + app.DebugPrintf(app.USER_SR, "%ls - %.*s static: %d ( %d ) dynamic: %d ( %d )\n", moviePath.c_str(), memoryInfo.subcategory_stringlen, memoryInfo.subcategory, + memoryInfo.static_allocation_bytes, memoryInfo.static_allocation_count, memoryInfo.dynamic_allocation_bytes, memoryInfo.dynamic_allocation_count); + ++iteration; + //if(memoryInfo.static_allocation_bytes > 0) getDebugMemoryUseRecursive(moviePath, memoryInfo); + + } + + app.DebugPrintf(app.USER_SR, "%ls - Total: %d, Expected: %d, Diff: %d\n", moviePath.c_str(), totalStatic + totalDynamic, afterTick - beforeLoad, (afterTick - beforeLoad) - (totalStatic + totalDynamic)); + +#endif + LeaveCriticalSection(&UIController::ms_reloadSkinCS); + +} + +void UIScene::getDebugMemoryUseRecursive(const wstring &moviePath, IggyMemoryUseInfo &memoryInfo) +{ + rrbool res; + IggyMemoryUseInfo internalMemoryInfo; + int internalIteration = 0; + while(res = IggyDebugGetMemoryUseInfo ( swf , + NULL , + memoryInfo.subcategory , + memoryInfo.subcategory_stringlen , + internalIteration , + &internalMemoryInfo )) + { + app.DebugPrintf(app.USER_SR, "%ls - %.*s static: %d ( %d ) dynamic: %d ( %d )\n", moviePath.c_str(), internalMemoryInfo.subcategory_stringlen, internalMemoryInfo.subcategory, + internalMemoryInfo.static_allocation_bytes, internalMemoryInfo.static_allocation_count, internalMemoryInfo.dynamic_allocation_bytes, internalMemoryInfo.dynamic_allocation_count); + ++internalIteration; + if(internalMemoryInfo.subcategory_stringlen > memoryInfo.subcategory_stringlen) getDebugMemoryUseRecursive(moviePath, internalMemoryInfo); + } +} + +void UIScene::PrintTotalMemoryUsage(__int64 &totalStatic, __int64 &totalDynamic) +{ + if(!swf) return; + + IggyMemoryUseInfo memoryInfo; + rrbool res; + int iteration = 0; + __int64 sceneStatic = 0; + __int64 sceneDynamic = 0; + while(res = IggyDebugGetMemoryUseInfo ( swf , + NULL , + "" , + 0 , + iteration , + &memoryInfo )) + { + sceneStatic += memoryInfo.static_allocation_bytes; + sceneDynamic += memoryInfo.dynamic_allocation_bytes; + totalStatic += memoryInfo.static_allocation_bytes; + totalDynamic += memoryInfo.dynamic_allocation_bytes; + ++iteration; + + } + + app.DebugPrintf(app.USER_SR, " \\- Scene static: %d , Scene dynamic: %d , Total: %d - %ls\n", sceneStatic, sceneDynamic, sceneStatic + sceneDynamic, getMoviePath().c_str()); +} + +void UIScene::tick() +{ + if(m_bIsReloading) return; + if(m_hasTickedOnce) m_bCanHandleInput = true; + while(IggyPlayerReadyToTick( swf )) + { + tickTimers(); + for(AUTO_VAR(it, m_controls.begin()); it != m_controls.end(); ++it) + { + (*it)->tick(); + } + IggyPlayerTickRS( swf ); + m_hasTickedOnce = true; + } +} + +UIControl* UIScene::GetMainPanel() +{ + return NULL; +} + + +void UIScene::addTimer(int id, int ms) +{ + int currentTime = System::currentTimeMillis(); + + TimerInfo info; + info.running = true; + info.duration = ms; + info.targetTime = currentTime + ms; + m_timers[id] = info; +} + +void UIScene::killTimer(int id) +{ + AUTO_VAR(it, m_timers.find(id)); + if(it != m_timers.end()) + { + it->second.running = false; + } +} + +void UIScene::tickTimers() +{ + int currentTime = System::currentTimeMillis(); + for(AUTO_VAR(it, m_timers.begin()); it != m_timers.end();) + { + if(!it->second.running) + { + it = m_timers.erase(it); + } + else + { + if(currentTime > it->second.targetTime) + { + handleTimerComplete(it->first); + + // Auto-restart + it->second.targetTime = it->second.duration + currentTime; + } + ++it; + } + } +} + +IggyName UIScene::registerFastName(const wstring &name) +{ + IggyName var; + AUTO_VAR(it,m_fastNames.find(name)); + if(it != m_fastNames.end()) + { + var = it->second; + } + else + { + var = IggyPlayerCreateFastName ( getMovie() , (IggyUTF16 *)name.c_str() , -1 ); + m_fastNames[name] = var; + } + return var; +} + +void UIScene::removeControl( UIControl_Base *control, bool centreScene) +{ + IggyDataValue result; + IggyDataValue value[2]; + + string name = control->getControlName(); + IggyStringUTF8 stringVal; + stringVal.string = (char*)name.c_str(); + stringVal.length = name.length(); + value[0].type = IGGY_DATATYPE_string_UTF8; + value[0].string8 = stringVal; + + value[1].type = IGGY_DATATYPE_boolean; + value[1].boolval = centreScene; + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcRemoveObject , 2 , value ); + +#ifdef __PSVITA__ + // update the button positions since they may have changed + UpdateSceneControls(); + + // mark the button as removed + control->setHidden(true); + // remove it from the touchboxes + ui.TouchBoxRebuild(control->getParentScene()); +#endif + +} + +void UIScene::slideLeft() +{ + IggyDataValue result; + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcSlideLeft , 0 , NULL ); +} + +void UIScene::slideRight() +{ + IggyDataValue result; + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcSlideRight , 0 , NULL ); +} + +void UIScene::doHorizontalResizeCheck() +{ + IggyDataValue result; + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcHorizontalResizeCheck , 0 , NULL ); +} + +void UIScene::render(S32 width, S32 height, C4JRender::eViewportType viewport) +{ + if(m_bIsReloading) return; + if(!m_hasTickedOnce || !swf) return; + ui.setupRenderPosition(viewport); + IggyPlayerSetDisplaySize( swf, width, height ); + IggyPlayerDraw( swf ); +} + +void UIScene::setOpacity(float percent) +{ + if(percent != m_lastOpacity || (m_bUpdateOpacity && getMovie())) + { + m_lastOpacity = percent; + + // 4J-TomK once a scene has been freshly loaded or re-loaded we force update opacity via initialiseMovie + if(m_bUpdateOpacity) + m_bUpdateOpacity = false; + + IggyDataValue result; + IggyDataValue value[1]; + value[0].type = IGGY_DATATYPE_number; + value[0].number = percent; + + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcSetAlpha , 1 , value ); + } +} + +void UIScene::setVisible(bool visible) +{ + m_bVisible = visible; +} + +void UIScene::customDraw(IggyCustomDrawCallbackRegion *region) +{ + app.DebugPrintf("Handling custom draw for scene with no override!\n"); +} + +void UIScene::customDrawSlotControl(IggyCustomDrawCallbackRegion *region, int iPad, shared_ptr<ItemInstance> item, float fAlpha, bool isFoil, bool bDecorations) +{ + if (item!= NULL) + { + if(m_cacheSlotRenders) + { + if( (m_cachedSlotDraw.size() + 1) == m_expectedCachedSlotCount) + { + //Make sure that pMinecraft->player is the correct player so that player specific rendering + // eg clock and compass, are rendered correctly + Minecraft *pMinecraft=Minecraft::GetInstance(); + shared_ptr<MultiplayerLocalPlayer> oldPlayer = pMinecraft->player; + if( iPad >= 0 && iPad < XUSER_MAX_COUNT ) pMinecraft->player = pMinecraft->localplayers[iPad]; + + // Setup GDraw, normal game render states and matrices + //CustomDrawData *customDrawRegion = ui.setupCustomDraw(this,region); + PIXBeginNamedEvent(0,"Starting Iggy custom draw\n"); + CustomDrawData *customDrawRegion = ui.calculateCustomDraw(region); + ui.beginIggyCustomDraw4J(region, customDrawRegion); + ui.setupCustomDrawGameState(); + + int list = m_parentLayer->m_parentGroup->getCommandBufferList(); + + bool useCommandBuffers = false; +#ifdef _XBOX_ONE + useCommandBuffers = true; + + // 4J Stu - Temporary until we fix the glint animation which needs updated if we are just replaying a command buffer + m_needsCacheRendered = true; +#endif + + if(!useCommandBuffers || m_needsCacheRendered) + { +#if (!defined __PS3__) && (!defined __PSVITA__) + if(useCommandBuffers) RenderManager.CBuffStart(list, true); +#endif + PIXBeginNamedEvent(0,"Draw uncached"); + ui.setupCustomDrawMatrices(this, customDrawRegion); + _customDrawSlotControl(customDrawRegion, iPad, item, fAlpha, isFoil, bDecorations, useCommandBuffers); + delete customDrawRegion; + PIXEndNamedEvent(); + + PIXBeginNamedEvent(0,"Draw all cache"); + // Draw all the cached slots + for(AUTO_VAR(it, m_cachedSlotDraw.begin()); it != m_cachedSlotDraw.end(); ++it) + { + CachedSlotDrawData *drawData = *it; + ui.setupCustomDrawMatrices(this, drawData->customDrawRegion); + _customDrawSlotControl(drawData->customDrawRegion, iPad, drawData->item, drawData->fAlpha, drawData->isFoil, drawData->bDecorations, useCommandBuffers); + delete drawData->customDrawRegion; + delete drawData; + } + PIXEndNamedEvent(); +#ifndef __PS3__ + if(useCommandBuffers) RenderManager.CBuffEnd(); +#endif + } + m_cachedSlotDraw.clear(); + +#ifndef __PS3__ + if(useCommandBuffers) RenderManager.CBuffCall(list); +#endif + + // Finish GDraw and anything else that needs to be finalised + ui.endCustomDraw(region); + + pMinecraft->player = oldPlayer; + } + else + { + PIXBeginNamedEvent(0,"Caching region"); + CachedSlotDrawData *drawData = new CachedSlotDrawData(); + drawData->item = item; + drawData->fAlpha = fAlpha; + drawData->isFoil = isFoil; + drawData->bDecorations = bDecorations; + drawData->customDrawRegion = ui.calculateCustomDraw(region); + + m_cachedSlotDraw.push_back(drawData); + PIXEndNamedEvent(); + } + } + else + { + // Setup GDraw, normal game render states and matrices + CustomDrawData *customDrawRegion = ui.setupCustomDraw(this,region); + + Minecraft *pMinecraft=Minecraft::GetInstance(); + + //Make sure that pMinecraft->player is the correct player so that player specific rendering + // eg clock and compass, are rendered correctly + shared_ptr<MultiplayerLocalPlayer> oldPlayer = pMinecraft->player; + if( iPad >= 0 && iPad < XUSER_MAX_COUNT ) pMinecraft->player = pMinecraft->localplayers[iPad]; + + _customDrawSlotControl(customDrawRegion, iPad, item, fAlpha, isFoil, bDecorations, false); + delete customDrawRegion; + pMinecraft->player = oldPlayer; + + // Finish GDraw and anything else that needs to be finalised + ui.endCustomDraw(region); + } + } +} + +void UIScene::_customDrawSlotControl(CustomDrawData *region, int iPad, shared_ptr<ItemInstance> item, float fAlpha, bool isFoil, bool bDecorations, bool usingCommandBuffer) +{ + Minecraft *pMinecraft=Minecraft::GetInstance(); + + float bwidth,bheight; + bwidth = region->x1 - region->x0; + bheight = region->y1 - region->y0; + + float x = region->x0; + float y = region->y0; + + // Base scale on height of this control, compared to height of what the item renderer normally renders (16 pixels high). Potentially + // we might want separate x & y scales here + + float scaleX = bwidth / 16.0f; + float scaleY = bheight / 16.0f; + + glEnable(GL_RESCALE_NORMAL); + glPushMatrix(); + glRotatef(120, 1, 0, 0); + Lighting::turnOn(); + glPopMatrix(); + + float pop = item->popTime; + if (pop > 0) + { + glPushMatrix(); + float squeeze = 1 + pop / (float) Inventory::POP_TIME_DURATION; + float sx = x; + float sy = y; + float sxoffs = 8 * scaleX; + float syoffs = 12 * scaleY; + glTranslatef((float)(sx + sxoffs), (float)(sy + syoffs), 0); + glScalef(1 / squeeze, (squeeze + 1) / 2, 1); + glTranslatef((float)-(sx + sxoffs), (float)-(sy + syoffs), 0); + } + + PIXBeginNamedEvent(0,"Render and decorate"); + if(m_pItemRenderer == NULL) m_pItemRenderer = new ItemRenderer(); + m_pItemRenderer->renderAndDecorateItem(pMinecraft->font, pMinecraft->textures, item, x, y,scaleX,scaleY,fAlpha,isFoil,false, !usingCommandBuffer); + PIXEndNamedEvent(); + + if (pop > 0) + { + glPopMatrix(); + } + + if(bDecorations) + { + if((scaleX!=1.0f) ||(scaleY!=1.0f)) + { + glPushMatrix(); + glScalef(scaleX, scaleY, 1.0f); + int iX= (int)(0.5f+((float)x)/scaleX); + int iY= (int)(0.5f+((float)y)/scaleY); + + m_pItemRenderer->renderGuiItemDecorations(pMinecraft->font, pMinecraft->textures, item, iX, iY, fAlpha); + glPopMatrix(); + } + else + { + m_pItemRenderer->renderGuiItemDecorations(pMinecraft->font, pMinecraft->textures, item, (int)x, (int)y, fAlpha); + } + } + + Lighting::turnOff(); + glDisable(GL_RESCALE_NORMAL); +} + +// 4J Stu - Not threadsafe +//void UIScene::navigateForward(int iPad, EUIScene scene, void *initData) +//{ +// if(m_parentLayer == NULL) +// { +// app.DebugPrintf("A scene is trying to navigate forwards, but it's parent layer is NULL!\n"); +//#ifndef _CONTENT_PACKAGE +// __debugbreak(); +//#endif +// } +// else +// { +// m_parentLayer->NavigateToScene(iPad,scene,initData); +// } +//} + +void UIScene::navigateBack() +{ + //CD - Added for audio + ui.PlayUISFX(eSFX_Back); + + ui.NavigateBack(m_iPad); + + if(m_parentLayer == NULL) + { +// app.DebugPrintf("A scene is trying to navigate back, but it's parent layer is NULL!\n"); +#ifndef _CONTENT_PACKAGE +// __debugbreak(); +#endif + } + else + { +// m_parentLayer->removeScene(this); + +#ifdef _DURANGO + if (ui.GetTopScene(0)) + InputManager.SetEnabledGtcButtons( ui.GetTopScene(0)->getDefaultGtcButtons() ); +#endif + } + +} + +void UIScene::gainFocus() +{ + if( !bHasFocus && stealsFocus() ) + { + // 4J Stu - Don't do this + /* + IggyEvent event; + IggyMakeEventFocusGained( &event , 0); + + IggyEventResult result; + IggyPlayerDispatchEventRS( getMovie() , &event , &result ); + + app.DebugPrintf("Sent gain focus event to scene\n"); + */ + bHasFocus = true; + if(app.GetGameStarted() && needsReloaded()) + { + reloadMovie(); + } + + updateTooltips(); + updateComponents(); + + if(!m_bFocussedOnce) + { + IggyDataValue result; + IggyDataValue value[1]; + + value[0].type = IGGY_DATATYPE_number; + value[0].number = -1; + + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcSetFocus , 1 , value ); + } + + handleGainFocus(m_bFocussedOnce); + if(bHasFocus) m_bFocussedOnce = true; + } + else if(bHasFocus && stealsFocus()) + { + updateTooltips(); + } +} + +void UIScene::loseFocus() +{ + if(bHasFocus) + { + // 4J Stu - Don't do this + /* + IggyEvent event; + IggyMakeEventFocusLost( &event ); + IggyEventResult result; + IggyPlayerDispatchEventRS ( getMovie() , &event , &result ); + */ + + app.DebugPrintf("Sent lose focus event to scene\n"); + bHasFocus = false; + handleLoseFocus(); + } +} + +void UIScene::handleGainFocus(bool navBack) +{ +#ifdef _DURANGO + InputManager.SetEnabledGtcButtons( this->getDefaultGtcButtons() ); +#endif +} + +void UIScene::updateTooltips() +{ + ui.SetTooltips(m_iPad, -1); +} + +void UIScene::sendInputToMovie(int key, bool repeat, bool pressed, bool released) +{ + if(!swf) return; + + int iggyKeyCode = convertGameActionToIggyKeycode(key); + + if(iggyKeyCode < 0) + { + app.DebugPrintf("UI WARNING: Ignoring input as game action does not translate to an Iggy keycode\n"); + return; + } + IggyEvent keyEvent; + // 4J Stu - Keyloc is always standard as we don't care about shift/alt + IggyMakeEventKey( &keyEvent, pressed?IGGY_KEYEVENT_Down:IGGY_KEYEVENT_Up, (IggyKeycode)iggyKeyCode, IGGY_KEYLOC_Standard ); + + IggyEventResult result; + IggyPlayerDispatchEventRS ( swf , &keyEvent , &result ); +} + +int UIScene::convertGameActionToIggyKeycode(int action) +{ + int keycode = -1; + switch(action) + { +#ifdef __ORBIS__ + case ACTION_MENU_TOUCHPAD_PRESS: +#endif + case ACTION_MENU_A: + keycode = IGGY_KEYCODE_ENTER; + break; + case ACTION_MENU_B: + keycode = IGGY_KEYCODE_ESCAPE; + break; + case ACTION_MENU_X: + keycode = IGGY_KEYCODE_F1; + break; + case ACTION_MENU_Y: + keycode = IGGY_KEYCODE_F2; + break; + case ACTION_MENU_OK: + keycode = IGGY_KEYCODE_ENTER; + break; + case ACTION_MENU_CANCEL: + keycode = IGGY_KEYCODE_ESCAPE; + break; + case ACTION_MENU_UP: + keycode = IGGY_KEYCODE_UP; + break; + case ACTION_MENU_DOWN: + keycode = IGGY_KEYCODE_DOWN; + break; + case ACTION_MENU_RIGHT: + keycode = IGGY_KEYCODE_RIGHT; + break; + case ACTION_MENU_LEFT: + keycode = IGGY_KEYCODE_LEFT; + break; + case ACTION_MENU_PAGEUP: + keycode = IGGY_KEYCODE_PAGE_UP; + break; + case ACTION_MENU_PAGEDOWN: + keycode = IGGY_KEYCODE_PAGE_DOWN; + break; + case ACTION_MENU_RIGHT_SCROLL: + keycode = IGGY_KEYCODE_F3; + break; + case ACTION_MENU_LEFT_SCROLL: + keycode = IGGY_KEYCODE_F4; + break; + case ACTION_MENU_STICK_PRESS: + break; + case ACTION_MENU_OTHER_STICK_PRESS: + break; + case ACTION_MENU_OTHER_STICK_UP: + keycode = IGGY_KEYCODE_F11; + break; + case ACTION_MENU_OTHER_STICK_DOWN: + keycode = IGGY_KEYCODE_F12; + break; + case ACTION_MENU_OTHER_STICK_LEFT: + break; + case ACTION_MENU_OTHER_STICK_RIGHT: + break; + }; + + return keycode; +} + +bool UIScene::allowRepeat(int key) +{ + // 4J-PB - ignore repeats of action ABXY buttons + // fix for PS3 213 - [MAIN MENU] Holding down buttons will continue to activate every prompt. + switch(key) + { + case ACTION_MENU_OK: + case ACTION_MENU_CANCEL: + case ACTION_MENU_A: + case ACTION_MENU_B: + case ACTION_MENU_X: + case ACTION_MENU_Y: + return false; + } + return true; +} + +void UIScene::externalCallback(IggyExternalFunctionCallUTF16 * call) +{ + if(wcscmp((wchar_t *)call->function_name.string,L"handlePress")==0) + { + if(call->num_arguments != 2) + { + app.DebugPrintf("Callback for handlePress did not have the correct number of arguments\n"); +#ifndef _CONTENT_PACKAGE + __debugbreak(); +#endif + return; + } + if(call->arguments[0].type != IGGY_DATATYPE_number || call->arguments[1].type != IGGY_DATATYPE_number) + { + app.DebugPrintf("Arguments for handlePress were not of the correct type\n"); +#ifndef _CONTENT_PACKAGE + __debugbreak(); +#endif + return; + } + handlePress(call->arguments[0].number, call->arguments[1].number); + } + else if(wcscmp((wchar_t *)call->function_name.string,L"handleFocusChange")==0) + { + if(call->num_arguments != 2) + { + app.DebugPrintf("Callback for handleFocusChange did not have the correct number of arguments\n"); +#ifndef _CONTENT_PACKAGE + __debugbreak(); +#endif + return; + } + if(call->arguments[0].type != IGGY_DATATYPE_number || call->arguments[1].type != IGGY_DATATYPE_number) + { + app.DebugPrintf("Arguments for handleFocusChange were not of the correct type\n"); +#ifndef _CONTENT_PACKAGE + __debugbreak(); +#endif + return; + } + _handleFocusChange(call->arguments[0].number, call->arguments[1].number); + } + else if(wcscmp((wchar_t *)call->function_name.string,L"handleInitFocus")==0) + { + if(call->num_arguments != 2) + { + app.DebugPrintf("Callback for handleInitFocus did not have the correct number of arguments\n"); +#ifndef _CONTENT_PACKAGE + __debugbreak(); +#endif + return; + } + if(call->arguments[0].type != IGGY_DATATYPE_number || call->arguments[1].type != IGGY_DATATYPE_number) + { + app.DebugPrintf("Arguments for handleInitFocus were not of the correct type\n"); +#ifndef _CONTENT_PACKAGE + __debugbreak(); +#endif + return; + } + _handleInitFocus(call->arguments[0].number, call->arguments[1].number); + } + else if(wcscmp((wchar_t *)call->function_name.string,L"handleCheckboxToggled")==0) + { + if(call->num_arguments != 2) + { + app.DebugPrintf("Callback for handleCheckboxToggled did not have the correct number of arguments\n"); +#ifndef _CONTENT_PACKAGE + __debugbreak(); +#endif + return; + } + if(call->arguments[0].type != IGGY_DATATYPE_number || call->arguments[1].type != IGGY_DATATYPE_boolean) + { + app.DebugPrintf("Arguments for handleCheckboxToggled were not of the correct type\n"); +#ifndef _CONTENT_PACKAGE + __debugbreak(); +#endif + return; + } + handleCheckboxToggled(call->arguments[0].number, call->arguments[1].boolval); + } + else if(wcscmp((wchar_t *)call->function_name.string,L"handleSliderMove")==0) + { + if(call->num_arguments != 2) + { + app.DebugPrintf("Callback for handleSliderMove did not have the correct number of arguments\n"); +#ifndef _CONTENT_PACKAGE + __debugbreak(); +#endif + return; + } + if(call->arguments[0].type != IGGY_DATATYPE_number || call->arguments[1].type != IGGY_DATATYPE_number) + { + app.DebugPrintf("Arguments for handleSliderMove were not of the correct type\n"); +#ifndef _CONTENT_PACKAGE + __debugbreak(); +#endif + return; + } + handleSliderMove(call->arguments[0].number, call->arguments[1].number); + } + else if(wcscmp((wchar_t *)call->function_name.string,L"handleAnimationEnd")==0) + { + if(call->num_arguments != 0) + { + app.DebugPrintf("Callback for handleAnimationEnd did not have the correct number of arguments\n"); +#ifndef _CONTENT_PACKAGE + __debugbreak(); +#endif + return; + } + handleAnimationEnd(); + } + else if(wcscmp((wchar_t *)call->function_name.string,L"handleSelectionChanged")==0) + { + if(call->num_arguments != 1) + { + app.DebugPrintf("Callback for handleSelectionChanged did not have the correct number of arguments\n"); +#ifndef _CONTENT_PACKAGE + __debugbreak(); +#endif + return; + } + if(call->arguments[0].type != IGGY_DATATYPE_number) + { + app.DebugPrintf("Arguments for handleSelectionChanged were not of the correct type\n"); +#ifndef _CONTENT_PACKAGE + __debugbreak(); +#endif + return; + } + handleSelectionChanged(call->arguments[0].number); + } + else if(wcscmp((wchar_t *)call->function_name.string,L"handleRequestMoreData")==0) + { + if(call->num_arguments == 0) + { + handleRequestMoreData(0,false); + } + else + { + if(call->num_arguments != 2) + { + app.DebugPrintf("Callback for handleRequestMoreData did not have the correct number of arguments\n"); +#ifndef _CONTENT_PACKAGE + __debugbreak(); +#endif + return; + } + if(call->arguments[0].type != IGGY_DATATYPE_number || call->arguments[1].type != IGGY_DATATYPE_boolean) + { + app.DebugPrintf("Arguments for handleRequestMoreData were not of the correct type\n"); +#ifndef _CONTENT_PACKAGE + __debugbreak(); +#endif + return; + } + handleRequestMoreData(call->arguments[0].number, call->arguments[1].boolval); + } + } + else if(wcscmp((wchar_t *)call->function_name.string,L"handleTouchBoxRebuild")==0) + { + handleTouchBoxRebuild(); + } + else + { + app.DebugPrintf("Unhandled callback: %s\n", call->function_name.string); + } +} + +void UIScene::registerSubstitutionTexture(const wstring &textureName, PBYTE pbData, DWORD dwLength, bool deleteData) +{ + m_registeredTextures[textureName] = deleteData;; + ui.registerSubstitutionTexture(textureName, pbData, dwLength); +} + +bool UIScene::hasRegisteredSubstitutionTexture(const wstring &textureName) +{ + AUTO_VAR(it, m_registeredTextures.find( textureName ) ); + + return it != m_registeredTextures.end(); +} + +void UIScene::_handleFocusChange(F64 controlId, F64 childId) +{ + m_iFocusControl = (int)controlId; + m_iFocusChild = (int)childId; + + handleFocusChange(controlId, childId); + ui.PlayUISFX(eSFX_Focus); +} + +void UIScene::_handleInitFocus(F64 controlId, F64 childId) +{ + m_iFocusControl = (int)controlId; + m_iFocusChild = (int)childId; + + //handleInitFocus(controlId, childId); + handleFocusChange(controlId, childId); +} + +bool UIScene::controlHasFocus(int iControlId) +{ + return m_iFocusControl == iControlId; +} + +bool UIScene::controlHasFocus(UIControl_Base *control) +{ + return controlHasFocus( control->getId() ); +} + +int UIScene::getControlChildFocus() +{ + return m_iFocusChild; +} + +int UIScene::getControlFocus() +{ + return m_iFocusControl; +} + +void UIScene::setBackScene(UIScene *scene) +{ + m_backScene = scene; +} + +UIScene *UIScene::getBackScene() +{ + return m_backScene; +} +#ifdef __PSVITA__ +void UIScene::UpdateSceneControls() +{ + AUTO_VAR(itEnd, GetControls()->end()); + for (AUTO_VAR(it, GetControls()->begin()); it != itEnd; it++) + { + UIControl *control=(UIControl *)*it; + control->UpdateControl(); + } +} +#endif + +size_t UIScene::GetCallbackUniqueId() +{ + if( m_callbackUniqueId == 0) + { + m_callbackUniqueId = ui.RegisterForCallbackId(this); + } + return m_callbackUniqueId; +} + +bool UIScene::isReadyToDelete() +{ + return true; +}
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIScene.h b/Minecraft.Client/Common/UI/UIScene.h new file mode 100644 index 00000000..823c510c --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene.h @@ -0,0 +1,270 @@ +#pragma once +// 4J-PB - remove the inherits via dominance warnings +#pragma warning( disable : 4250 ) +using namespace std; +// A scene map directly to an Iggy movie (or more accurately a collection of different sized movies) + +#include "UIEnums.h" +#include "UIControl_Base.h" + +class ItemRenderer; +class UILayer; + +// 4J Stu - Setup some defines for quickly mapping elements in the scene + +#define UI_BEGIN_MAP_ELEMENTS_AND_NAMES(parentClass) \ + virtual bool mapElementsAndNames() \ + { \ + parentClass::mapElementsAndNames(); \ + IggyValuePath *currentRoot = IggyPlayerRootPath ( getMovie() ); + +#define UI_END_MAP_ELEMENTS_AND_NAMES() \ + return true; \ + } + +#define UI_MAP_ELEMENT( var, name) \ + { var.setupControl(this, currentRoot , name ); m_controls.push_back(&var); } + +#define UI_BEGIN_MAP_CHILD_ELEMENTS( parent ) \ + { \ + IggyValuePath *lastRoot = currentRoot; \ + currentRoot = parent.getIggyValuePath(); + +#define UI_END_MAP_CHILD_ELEMENTS() \ + currentRoot = lastRoot; \ + } + +#define UI_MAP_NAME( var, name ) \ + { var = registerFastName(name); } + +class UIScene +{ + friend class UILayer; +public: + IggyValuePath *m_rootPath; + +private: + Iggy *swf; + IggyName m_funcRemoveObject, m_funcSlideLeft, m_funcSlideRight, m_funcSetSafeZone, m_funcSetFocus, m_funcHorizontalResizeCheck; + IggyName m_funcSetAlpha; + + ItemRenderer *m_pItemRenderer; + unordered_map<wstring, IggyName> m_fastNames; + unordered_map<wstring, bool> m_registeredTextures; + + typedef struct _TimerInfo + { + int duration; + int targetTime; + bool running; + } TimerInfo; + unordered_map<int,TimerInfo> m_timers; + + int m_iFocusControl, m_iFocusChild; + float m_lastOpacity; + bool m_bUpdateOpacity; + bool m_bVisible; + bool m_bCanHandleInput; + UIScene *m_backScene; + + size_t m_callbackUniqueId; + +public: + enum ESceneResolution + { + eSceneResolution_1080, + eSceneResolution_720, + eSceneResolution_480, + eSceneResolution_Vita, + }; + +protected: + ESceneResolution m_loadedResolution; + + bool m_bIsReloading; + bool m_bFocussedOnce; + + int m_movieWidth, m_movieHeight; + int m_renderWidth, m_renderHeight; + vector<UIControl *> m_controls; + +protected: + UILayer *m_parentLayer; + bool bHasFocus; + int m_iPad; + bool m_hasTickedOnce; + +public: + virtual Iggy *getMovie() { return swf; } + + void destroyMovie(); + virtual void reloadMovie(bool force = false); + virtual bool needsReloaded(); + virtual bool hasMovie(); + virtual void updateSafeZone(); + + int getRenderWidth() { return m_renderWidth; } + int getRenderHeight() { return m_renderHeight; } + +#ifdef __PSVITA__ + UILayer *GetParentLayer() {return m_parentLayer;} + EUIGroup GetParentLayerGroup() {return m_parentLayer->m_parentGroup->GetGroup();} + vector<UIControl *> *GetControls() {return &m_controls;} +#endif + +protected: + virtual F64 getSafeZoneHalfHeight(); + virtual F64 getSafeZoneHalfWidth(); + void setSafeZone(S32 top, S32 bottom, S32 left, S32 right); + void doHorizontalResizeCheck(); + virtual wstring getMoviePath() = 0; + + virtual bool mapElementsAndNames(); + void initialiseMovie(); + void loadMovie(); + +private: + void getDebugMemoryUseRecursive(const wstring &moviePath, IggyMemoryUseInfo &memoryInfo); + +public: + void PrintTotalMemoryUsage(__int64 &totalStatic, __int64 &totalDynamic); + +public: + UIScene(int iPad, UILayer *parentLayer); + virtual ~UIScene(); + + virtual EUIScene getSceneType() = 0; + ESceneResolution getSceneResolution() { return m_loadedResolution; } + + virtual void tick(); + + IggyName registerFastName(const wstring &name); +#ifdef __PSVITA__ + void SetFocusToElement(int iID); + void UpdateSceneControls(); +#endif +protected: + void addTimer(int id, int ms); + void killTimer(int id); + void tickTimers(); + TimerInfo* getTimer(int id) { return &m_timers[id]; } + virtual void handleTimerComplete(int id) {} + +public: + // FOCUS + // Returns true if this scene handles input + virtual bool stealsFocus() { return true; } + + // Returns true if this scene has focus for the pad passed in + virtual bool hasFocus(int iPad) { return bHasFocus && iPad == m_iPad; } + + void gainFocus(); + void loseFocus(); + + virtual void updateTooltips(); + virtual void updateComponents() {} + virtual void handleGainFocus(bool navBack); + virtual void handleLoseFocus() {} + + // Returns true if lower scenes in this scenes layer, or in any layer below this scenes layers should be hidden + virtual bool hidesLowerScenes() { return m_hasTickedOnce; } + + // returns main panel if controls are not living in the root + virtual UIControl* GetMainPanel(); + + void removeControl( UIControl_Base *control, bool centreScene); + void slideLeft(); + void slideRight(); + + // RENDERING + virtual void render(S32 width, S32 height, C4JRender::eViewportType viewpBort); + + virtual void customDraw(IggyCustomDrawCallbackRegion *region); + + void setOpacity(float percent); + void setVisible(bool visible); + bool isVisible() { return m_bVisible; } + +protected: + //void customDrawSlotControl(IggyCustomDrawCallbackRegion *region, int iPad, int iID, int iCount, int iAuxVal, float fAlpha, bool isFoil, bool bDecorations); + void customDrawSlotControl(IggyCustomDrawCallbackRegion *region, int iPad, shared_ptr<ItemInstance> item, float fAlpha, bool isFoil, bool bDecorations); + + bool m_cacheSlotRenders; + bool m_needsCacheRendered; + int m_expectedCachedSlotCount; +private: + typedef struct _CachedSlotDrawData + { + CustomDrawData *customDrawRegion; + shared_ptr<ItemInstance> item; + float fAlpha; + bool isFoil; + bool bDecorations; + } CachedSlotDrawData; + vector<CachedSlotDrawData *> m_cachedSlotDraw; + + void _customDrawSlotControl(CustomDrawData *region, int iPad, shared_ptr<ItemInstance> item, float fAlpha, bool isFoil, bool bDecorations, bool usingCommandBuffer); + +public: + // INPUT + bool canHandleInput() { return m_bCanHandleInput; } + virtual bool allowRepeat(int key); + virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled) {} + void externalCallback(IggyExternalFunctionCallUTF16 * call); + + virtual void handleDestroy() {} +protected: + void sendInputToMovie(int key, bool repeat, bool pressed, bool released); + virtual void handlePreReload() {} + virtual void handleReload() {} + virtual void handlePress(F64 controlId, F64 childId) {} + virtual void handleFocusChange(F64 controlId, F64 childId) {} + virtual void handleInitFocus(F64 controlId, F64 childId) {} + virtual void handleCheckboxToggled(F64 controlId, bool selected) {} + virtual void handleSliderMove(F64 sliderId, F64 currentValue) {} + virtual void handleAnimationEnd() {} + virtual void handleSelectionChanged(F64 selectedId) {} + virtual void handleRequestMoreData(F64 startIndex, bool up) {} + virtual void handleTouchBoxRebuild() {} +private: + void _handleFocusChange(F64 controlId, F64 childId); + void _handleInitFocus(F64 controlId, F64 childId); + + int convertGameActionToIggyKeycode(int action); + +public: + bool controlHasFocus(int iControlId); + bool controlHasFocus(UIControl_Base *control); + int getControlFocus(); + int getControlChildFocus(); + + // NAVIGATION +protected: + //void navigateForward(int iPad, EUIScene scene, void *initData = NULL); + void navigateBack(); + +public: + void setBackScene(UIScene *scene); + UIScene *getBackScene(); + virtual void HandleDLCMountingComplete() {} + virtual void HandleDLCInstalled() {} +#ifdef _XBOX_ONE + virtual void HandleDLCLicenseChange() {} +#endif + void registerSubstitutionTexture(const wstring &textureName, PBYTE pbData, DWORD dwLength, bool deleteData = false); + bool hasRegisteredSubstitutionTexture(const wstring &textureName); + + virtual void handleUnlockFullVersion() {} + + virtual void handleTouchInput(unsigned int iPad, S32 x, S32 y, int iId, bool bPressed, bool bRepeat, bool bReleased) {} + + +protected: +#ifdef _DURANGO + virtual long long getDefaultGtcButtons() { return _360_GTC_BACK; } +#endif + + size_t GetCallbackUniqueId(); + + virtual bool isReadyToDelete(); +}; diff --git a/Minecraft.Client/Common/UI/UIScene_AbstractContainerMenu.cpp b/Minecraft.Client/Common/UI/UIScene_AbstractContainerMenu.cpp new file mode 100644 index 00000000..a1bd8270 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_AbstractContainerMenu.cpp @@ -0,0 +1,307 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIScene_AbstractContainerMenu.h" + +#include "..\..\..\Minecraft.World\net.minecraft.world.inventory.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.item.h" +#include "..\..\MultiplayerLocalPlayer.h" + +UIScene_AbstractContainerMenu::UIScene_AbstractContainerMenu(int iPad, UILayer *parentLayer) : UIScene(iPad, parentLayer) +{ + m_focusSection = eSectionNone; + // in this scene, we override the press sound with our own for crafting success or fail + ui.OverrideSFX(m_iPad,ACTION_MENU_A,true); + ui.OverrideSFX(m_iPad,ACTION_MENU_OK,true); +#ifdef __ORBIS__ + ui.OverrideSFX(m_iPad,ACTION_MENU_TOUCHPAD_PRESS,true); +#endif + ui.OverrideSFX(m_iPad,ACTION_MENU_X,true); + ui.OverrideSFX(m_iPad,ACTION_MENU_Y,true); + ui.OverrideSFX(m_iPad,ACTION_MENU_LEFT_SCROLL,true); + ui.OverrideSFX(m_iPad,ACTION_MENU_RIGHT_SCROLL,true); + ui.OverrideSFX(m_iPad,ACTION_MENU_LEFT,true); + ui.OverrideSFX(m_iPad,ACTION_MENU_RIGHT,true); + ui.OverrideSFX(m_iPad,ACTION_MENU_UP,true); + ui.OverrideSFX(m_iPad,ACTION_MENU_DOWN,true); + + m_bIgnoreInput=false; +} + +UIScene_AbstractContainerMenu::~UIScene_AbstractContainerMenu() +{ + app.DebugPrintf("UIScene_AbstractContainerMenu::~UIScene_AbstractContainerMenu\n"); +} + +void UIScene_AbstractContainerMenu::handleDestroy() +{ + app.DebugPrintf("UIScene_AbstractContainerMenu::handleDestroy\n"); + Minecraft *pMinecraft = Minecraft::GetInstance(); + if( pMinecraft->localgameModes[m_iPad] != NULL ) + { + TutorialMode *gameMode = (TutorialMode *)pMinecraft->localgameModes[m_iPad]; + if(gameMode != NULL) gameMode->getTutorial()->changeTutorialState(m_previousTutorialState); + } + + // 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) + if(pMinecraft->localplayers[m_iPad] != NULL) pMinecraft->localplayers[m_iPad]->closeContainer(); + + ui.OverrideSFX(m_iPad,ACTION_MENU_A,false); + ui.OverrideSFX(m_iPad,ACTION_MENU_OK,false); +#ifdef __ORBIS__ + ui.OverrideSFX(m_iPad,ACTION_MENU_TOUCHPAD_PRESS,false); +#endif + ui.OverrideSFX(m_iPad,ACTION_MENU_X,false); + ui.OverrideSFX(m_iPad,ACTION_MENU_Y,false); + ui.OverrideSFX(m_iPad,ACTION_MENU_LEFT_SCROLL,false); + ui.OverrideSFX(m_iPad,ACTION_MENU_RIGHT_SCROLL,false); + ui.OverrideSFX(m_iPad,ACTION_MENU_LEFT,false); + ui.OverrideSFX(m_iPad,ACTION_MENU_RIGHT,false); + ui.OverrideSFX(m_iPad,ACTION_MENU_UP,false); + ui.OverrideSFX(m_iPad,ACTION_MENU_DOWN,false); +} + +void UIScene_AbstractContainerMenu::InitDataAssociations(int iPad, AbstractContainerMenu *menu, int startIndex) +{ +} + +void UIScene_AbstractContainerMenu::PlatformInitialize(int iPad, int startIndex) +{ + + m_labelInventory.init( app.GetString(IDS_INVENTORY) ); + + if(startIndex >= 0) + { + m_slotListInventory.addSlots(startIndex, 27); + m_slotListHotbar.addSlots(startIndex + 27, 9); + } + + // Determine min and max extents for pointer, it needs to be able to move off the container to drop items. + float fPanelWidth, fPanelHeight; + float fPanelX, fPanelY; + float fPointerWidth, fPointerHeight; + + // We may have varying depths of controls here, so base off the pointers parent +#if TO_BE_IMPLEMENTED + HXUIOBJ parent; + XuiElementGetBounds( m_pointerControl->m_hObj, &fPointerWidth, &fPointerHeight ); +#else + fPointerWidth = 50; + fPointerHeight = 50; +#endif + + fPanelWidth = m_controlBackgroundPanel.getWidth(); + fPanelHeight = m_controlBackgroundPanel.getHeight(); + fPanelX = m_controlBackgroundPanel.getXPos(); + fPanelY = m_controlBackgroundPanel.getYPos(); + // Get size of pointer + m_fPointerImageOffsetX = 0; //floor(fPointerWidth/2.0f); + m_fPointerImageOffsetY = 0; //floor(fPointerHeight/2.0f); + + m_fPanelMinX = fPanelX; + m_fPanelMaxX = fPanelX + fPanelWidth; + m_fPanelMinY = fPanelY; + m_fPanelMaxY = fPanelY + fPanelHeight; + +#ifdef __ORBIS__ + // we need to map the touchpad rectangle to the UI rectangle. While it works great for the creative menu, it is much too sensitive for the smaller menus. + //X coordinate of the touch point (0 to 1919) + //Y coordinate of the touch point (0 to 941: DUALSHOCK®4 wireless controllers and the CUH-ZCT1J/CAP-ZCT1J/CAP-ZCT1U controllers for the PlayStation®4 development tool, + //0 to 753: JDX-1000x series controllers for the PlayStation®4 development tool,) + m_fTouchPadMulX=fPanelWidth/1919.0f; + m_fTouchPadMulY=fPanelHeight/941.0f; + m_fTouchPadDeadZoneX=15.0f*m_fTouchPadMulX; + m_fTouchPadDeadZoneY=15.0f*m_fTouchPadMulY; + +#endif + + // 4J-PB - need to limit this in splitscreen + if(app.GetLocalPlayerCount()>1) + { + // don't let the pointer go into someone's screen + m_fPointerMinY = floor(fPointerHeight/2.0f); + } + else + { + m_fPointerMinY = fPanelY -fPointerHeight; + } + m_fPointerMinX = fPanelX - fPointerWidth; + m_fPointerMaxX = m_fPanelMaxX + fPointerWidth; + m_fPointerMaxY = m_fPanelMaxY + (fPointerHeight/2); + +// m_hPointerText=NULL; +// m_hPointerTextBkg=NULL; + + // Put the pointer over first item in use row to start with. + UIVec2D itemPos; + UIVec2D itemSize; + GetItemScreenData( m_eCurrSection, 0, &( itemPos ), &( itemSize ) ); + + UIVec2D sectionPos; + GetPositionOfSection( m_eCurrSection, &( sectionPos ) ); + + UIVec2D vPointerPos = sectionPos; + vPointerPos += itemPos; + vPointerPos.x += ( itemSize.x / 2.0f ); + vPointerPos.y += ( itemSize.y / 2.0f ); + + vPointerPos.x -= m_fPointerImageOffsetX; + vPointerPos.y -= m_fPointerImageOffsetY; + + //m_pointerControl->SetPosition( &vPointerPos ); + m_pointerPos = vPointerPos; + + IggyEvent mouseEvent; + S32 width, height; + m_parentLayer->getRenderDimensions(width, height); + S32 x = m_pointerPos.x*((float)width/m_movieWidth); + S32 y = m_pointerPos.y*((float)height/m_movieHeight); + IggyMakeEventMouseMove( &mouseEvent, x, y); + + IggyEventResult result; + IggyPlayerDispatchEventRS ( getMovie() , &mouseEvent , &result ); + +#ifdef USE_POINTER_ACCEL + m_fPointerVelX = 0.0f; + m_fPointerVelY = 0.0f; + m_fPointerAccelX = 0.0f; + m_fPointerAccelY = 0.0f; +#endif +} + +void UIScene_AbstractContainerMenu::tick() +{ + UIScene::tick(); + + onMouseTick(); + + IggyEvent mouseEvent; + S32 width, height; + m_parentLayer->getRenderDimensions(width, height); + S32 x = m_pointerPos.x*((float)width/m_movieWidth); + S32 y = m_pointerPos.y*((float)height/m_movieHeight); + IggyMakeEventMouseMove( &mouseEvent, x, y); + + // 4J Stu - This seems to be broken on Durango, so do it ourself +#ifdef _DURANGO + //mouseEvent.x = x; + //mouseEvent.y = y; +#endif + + IggyEventResult result; + IggyPlayerDispatchEventRS ( getMovie() , &mouseEvent , &result ); +} + +void UIScene_AbstractContainerMenu::render(S32 width, S32 height, C4JRender::eViewportType viewpBort) +{ + m_cacheSlotRenders = true; + + m_needsCacheRendered = m_needsCacheRendered || m_menu->needsRendered(); + + if(m_needsCacheRendered) + { + m_expectedCachedSlotCount = 0; + unsigned int count = m_menu->getSize(); + for(unsigned int i = 0; i < count; ++i) + { + if(m_menu->getSlot(i)->hasItem()) + { + ++m_expectedCachedSlotCount; + } + } + } + + UIScene::render(width, height, viewpBort); + + m_needsCacheRendered = false; +} + +void UIScene_AbstractContainerMenu::customDraw(IggyCustomDrawCallbackRegion *region) +{ + Minecraft *pMinecraft = Minecraft::GetInstance(); + if(pMinecraft->localplayers[m_iPad] == NULL || pMinecraft->localgameModes[m_iPad] == NULL) return; + + shared_ptr<ItemInstance> item = nullptr; + if(wcscmp((wchar_t *)region->name,L"pointerIcon")==0) + { + m_cacheSlotRenders = false; + item = pMinecraft->localplayers[m_iPad]->inventory->getCarried(); + } + else + { + int slotId = -1; + swscanf((wchar_t*)region->name,L"slot_%d",&slotId); + if (slotId == -1) + { + app.DebugPrintf("This is not the control we are looking for\n"); + } + else + { + m_cacheSlotRenders = true; + Slot *slot = m_menu->getSlot(slotId); + item = slot->getItem(); + } + } + + if(item != NULL) customDrawSlotControl(region,m_iPad,item,1.0f,item->isFoil(),true); +} + +void UIScene_AbstractContainerMenu::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled) +{ + if(m_bIgnoreInput) return; + + //app.DebugPrintf("UIScene_InventoryMenu handling input for pad %d, key %d, down- %s, pressed- %s, released- %s\n", iPad, key, down?"TRUE":"FALSE", pressed?"TRUE":"FALSE", released?"TRUE":"FALSE"); + ui.AnimateKeyPress(m_iPad, key, repeat, pressed, released); + + if(pressed) + { + handled = handleKeyDown(m_iPad, key, repeat); + } +} + +void UIScene_AbstractContainerMenu::SetPointerText(const wstring &description, vector<wstring> &unformattedStrings, bool newSlot) +{ + //app.DebugPrintf("Setting pointer text\n"); + m_cursorPath.setLabel(description,false,newSlot); +} + +void UIScene_AbstractContainerMenu::setSectionFocus(ESceneSection eSection, int iPad) +{ + if(m_focusSection != eSectionNone) + { + UIControl *currentFocus = getSection(m_focusSection); + if(currentFocus) currentFocus->setFocus(false); + } + UIControl *newFocus = getSection(eSection); + if(newFocus) newFocus->setFocus(true); + m_focusSection = eSection; +} + +void UIScene_AbstractContainerMenu::setFocusToPointer(int iPad) +{ + if(m_focusSection != eSectionNone) + { + UIControl *currentFocus = getSection(m_focusSection); + if(currentFocus) currentFocus->setFocus(false); + } + m_focusSection = eSectionNone; +} + +shared_ptr<ItemInstance> UIScene_AbstractContainerMenu::getSlotItem(ESceneSection eSection, int iSlot) +{ + Slot *slot = m_menu->getSlot( getSectionStartOffset(eSection) + iSlot ); + if(slot) return slot->getItem(); + else return nullptr; +} + +bool UIScene_AbstractContainerMenu::isSlotEmpty(ESceneSection eSection, int iSlot) +{ + Slot *slot = m_menu->getSlot( getSectionStartOffset(eSection) + iSlot ); + if(slot) return !slot->hasItem(); + else return false; +} + +void UIScene_AbstractContainerMenu::adjustPointerForSafeZone() +{ + // Handled by AS +} diff --git a/Minecraft.Client/Common/UI/UIScene_AbstractContainerMenu.h b/Minecraft.Client/Common/UI/UIScene_AbstractContainerMenu.h new file mode 100644 index 00000000..b98b3763 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_AbstractContainerMenu.h @@ -0,0 +1,63 @@ +#pragma once + +#include "UIScene.h" +#include "IUIScene_AbstractContainerMenu.h" + +class AbstractContainerMenu; + +class UIScene_AbstractContainerMenu : public UIScene, public virtual IUIScene_AbstractContainerMenu +{ +private: + ESceneSection m_focusSection; + bool m_bIgnoreInput; + +protected: + UIControl m_controlMainPanel; + UIControl_SlotList m_slotListHotbar, m_slotListInventory; + UIControl_Cursor m_cursorPath; + UIControl_Label m_labelInventory, m_labelBrewingStand; + UIControl m_controlBackgroundPanel; + + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) + UI_MAP_ELEMENT( m_controlMainPanel, "MainPanel" ) + UI_BEGIN_MAP_CHILD_ELEMENTS( m_controlMainPanel ) + UI_MAP_ELEMENT( m_controlBackgroundPanel, "BackgroundPanel" ) + UI_MAP_ELEMENT( m_slotListHotbar, "hotbarList") + UI_MAP_ELEMENT( m_slotListInventory, "inventoryList") + UI_MAP_ELEMENT( m_cursorPath, "cursor") + UI_MAP_ELEMENT( m_labelInventory, "inventoryLabel") + UI_END_MAP_CHILD_ELEMENTS() + UI_END_MAP_ELEMENTS_AND_NAMES() + +public: + UIScene_AbstractContainerMenu(int iPad, UILayer *parentLayer); + ~UIScene_AbstractContainerMenu(); + + virtual void handleDestroy(); + + int getPad() { return m_iPad; } + bool getIgnoreInput() { return m_bIgnoreInput; } + void setIgnoreInput(bool bVal) { m_bIgnoreInput=bVal; } + +protected: + virtual void PlatformInitialize(int iPad, int startIndex); + virtual void InitDataAssociations(int iPad, AbstractContainerMenu *menu, int startIndex = 0); + virtual bool doesSectionTreeHaveFocus(ESceneSection eSection) { return false; } + virtual void setSectionFocus(ESceneSection eSection, int iPad); + void setFocusToPointer(int iPad); + void SetPointerText(const wstring &description, vector<wstring> &unformattedStrings, bool newSlot); + virtual shared_ptr<ItemInstance> getSlotItem(ESceneSection eSection, int iSlot); + virtual bool isSlotEmpty(ESceneSection eSection, int iSlot); + virtual void adjustPointerForSafeZone(); + + virtual UIControl *getSection(ESceneSection eSection) { return NULL; } + +public: + virtual void tick(); + + virtual void render(S32 width, S32 height, C4JRender::eViewportType viewpBort); + virtual void customDraw(IggyCustomDrawCallbackRegion *region); + + // INPUT + virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled); +}; diff --git a/Minecraft.Client/Common/UI/UIScene_AnvilMenu.cpp b/Minecraft.Client/Common/UI/UIScene_AnvilMenu.cpp new file mode 100644 index 00000000..7b9886bc --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_AnvilMenu.cpp @@ -0,0 +1,400 @@ +#include "stdafx.h" +#include "UI.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.inventory.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.level.tile.entity.h" +#include "MultiPlayerLocalPlayer.h" +#include "..\..\Minecraft.h" +#include "UIScene_AnvilMenu.h" + +UIScene_AnvilMenu::UIScene_AnvilMenu(int iPad, void *_initData, UILayer *parentLayer) : UIScene_AbstractContainerMenu(iPad, parentLayer) +{ + // Setup all the Iggy references we need for this scene + initialiseMovie(); + + m_showingCross = false; + m_textInputAnvil.init(m_itemName,eControl_TextInput); + + m_labelAnvil.init( app.GetString(IDS_REPAIR_AND_NAME) ); + + AnvilScreenInput *initData = (AnvilScreenInput *)_initData; + m_inventory = initData->inventory; + + Minecraft *pMinecraft = Minecraft::GetInstance(); + if( pMinecraft->localgameModes[iPad] != NULL ) + { + TutorialMode *gameMode = (TutorialMode *)pMinecraft->localgameModes[iPad]; + m_previousTutorialState = gameMode->getTutorial()->getCurrentState(); + gameMode->getTutorial()->changeTutorialState(e_Tutorial_State_Anvil_Menu, this); + } + + m_repairMenu = new RepairMenu( initData->inventory, initData->level, initData->x, initData->y, initData->z, pMinecraft->localplayers[iPad] ); + m_repairMenu->addSlotListener(this); + + Initialize( iPad, m_repairMenu, true, RepairMenu::INV_SLOT_START, eSectionAnvilUsing, eSectionAnvilMax ); + + m_slotListItem1.addSlots(RepairMenu::INPUT_SLOT, 1); + m_slotListItem2.addSlots(RepairMenu::ADDITIONAL_SLOT, 1); + m_slotListResult.addSlots(RepairMenu::RESULT_SLOT, 1); + + bool expensive = false; + wstring m_costString = L""; + + if(m_repairMenu->cost > 0) + { + if(m_repairMenu->cost >= 40 && !pMinecraft->localplayers[iPad]->abilities.instabuild) + { + m_costString = app.GetString(IDS_REPAIR_EXPENSIVE); + expensive = true; + } + else if(!m_repairMenu->getSlot(RepairMenu::RESULT_SLOT)->hasItem()) + { + // Do nothing + } + else + { + LPCWSTR costString = app.GetString(IDS_REPAIR_COST); + wchar_t temp[256]; + swprintf(temp, 256, costString, m_repairMenu->cost); + m_costString = temp; + if(!m_repairMenu->getSlot(RepairMenu::RESULT_SLOT)->mayPickup(dynamic_pointer_cast<Player>(m_inventory->player->shared_from_this()))) + { + expensive = true; + } + } + } + setCostLabel(m_costString, expensive); + + if(initData) delete initData; + + setIgnoreInput(false); + + app.SetRichPresenceContext(iPad, CONTEXT_GAME_STATE_ANVIL); +} + +wstring UIScene_AnvilMenu::getMoviePath() +{ + if(app.GetLocalPlayerCount() > 1) + { + return L"AnvilMenuSplit"; + } + else + { + return L"AnvilMenu"; + } +} + +void UIScene_AnvilMenu::handleReload() +{ + Initialize( m_iPad, m_menu, true, RepairMenu::INV_SLOT_START, eSectionAnvilUsing, eSectionAnvilMax ); + + m_slotListItem1.addSlots(RepairMenu::INPUT_SLOT, 1); + m_slotListItem2.addSlots(RepairMenu::ADDITIONAL_SLOT, 1); + m_slotListResult.addSlots(RepairMenu::RESULT_SLOT, 1); +} + +void UIScene_AnvilMenu::tick() +{ + UIScene_AbstractContainerMenu::tick(); + + handleTick(); +} + +int UIScene_AnvilMenu::getSectionColumns(ESceneSection eSection) +{ + int cols = 0; + switch( eSection ) + { + case eSectionAnvilItem1: + cols = 1; + break; + case eSectionAnvilItem2: + cols = 1; + break; + case eSectionAnvilResult: + cols = 1; + break; + case eSectionAnvilInventory: + cols = 9; + break; + case eSectionAnvilUsing: + cols = 9; + break; + default: + assert( false ); + break; + } + return cols; +} + +int UIScene_AnvilMenu::getSectionRows(ESceneSection eSection) +{ + int rows = 0; + switch( eSection ) + { + case eSectionAnvilItem1: + rows = 1; + break; + case eSectionAnvilItem2: + rows = 1; + break; + case eSectionAnvilResult: + rows = 1; + break; + case eSectionAnvilInventory: + rows = 3; + break; + case eSectionAnvilUsing: + rows = 1; + break; + default: + assert( false ); + break; + } + return rows; +} + +void UIScene_AnvilMenu::GetPositionOfSection( ESceneSection eSection, UIVec2D* pPosition ) +{ + switch( eSection ) + { + case eSectionAnvilItem1: + pPosition->x = m_slotListItem1.getXPos(); + pPosition->y = m_slotListItem1.getYPos(); + break; + case eSectionAnvilItem2: + pPosition->x = m_slotListItem2.getXPos(); + pPosition->y = m_slotListItem2.getYPos(); + break; + case eSectionAnvilResult: + pPosition->x = m_slotListResult.getXPos(); + pPosition->y = m_slotListResult.getYPos(); + break; + case eSectionAnvilName: + pPosition->x = m_textInputAnvil.getXPos(); + pPosition->y = m_textInputAnvil.getYPos(); + break; + case eSectionAnvilInventory: + pPosition->x = m_slotListInventory.getXPos(); + pPosition->y = m_slotListInventory.getYPos(); + break; + case eSectionAnvilUsing: + pPosition->x = m_slotListHotbar.getXPos(); + pPosition->y = m_slotListHotbar.getYPos(); + break; + default: + assert( false ); + break; + } +} + +void UIScene_AnvilMenu::GetItemScreenData( ESceneSection eSection, int iItemIndex, UIVec2D* pPosition, UIVec2D* pSize ) +{ + UIVec2D sectionSize; + + switch( eSection ) + { + case eSectionAnvilItem1: + sectionSize.x = m_slotListItem1.getWidth(); + sectionSize.y = m_slotListItem1.getHeight(); + break; + case eSectionAnvilItem2: + sectionSize.x = m_slotListItem2.getWidth(); + sectionSize.y = m_slotListItem2.getHeight(); + break; + case eSectionAnvilResult: + sectionSize.x = m_slotListResult.getWidth(); + sectionSize.y = m_slotListResult.getHeight(); + break; + case eSectionAnvilName: + sectionSize.x = m_textInputAnvil.getWidth(); + sectionSize.y = m_textInputAnvil.getHeight(); + break; + case eSectionAnvilInventory: + sectionSize.x = m_slotListInventory.getWidth(); + sectionSize.y = m_slotListInventory.getHeight(); + break; + case eSectionAnvilUsing: + sectionSize.x = m_slotListHotbar.getWidth(); + sectionSize.y = m_slotListHotbar.getHeight(); + break; + default: + assert( false ); + break; + } + + if(IsSectionSlotList(eSection)) + { + int rows = getSectionRows(eSection); + int cols = getSectionColumns(eSection); + + pSize->x = sectionSize.x/cols; + pSize->y = sectionSize.y/rows; + + int itemCol = iItemIndex % cols; + int itemRow = iItemIndex/cols; + + pPosition->x = itemCol * pSize->x; + pPosition->y = itemRow * pSize->y; + } + else + { + GetPositionOfSection(eSection, pPosition); + pSize->x = sectionSize.x; + pSize->y = sectionSize.y; + } +} + +void UIScene_AnvilMenu::setSectionSelectedSlot(ESceneSection eSection, int x, int y) +{ + int cols = getSectionColumns(eSection); + + int index = (y * cols) + x; + + UIControl_SlotList *slotList = NULL; + switch( eSection ) + { + case eSectionAnvilItem1: + slotList = &m_slotListItem1; + break; + case eSectionAnvilItem2: + slotList = &m_slotListItem2; + break; + case eSectionAnvilResult: + slotList = &m_slotListResult; + break; + case eSectionAnvilInventory: + slotList = &m_slotListInventory; + break; + case eSectionAnvilUsing: + slotList = &m_slotListHotbar; + break; + default: + assert( false ); + break; + } + + slotList->setHighlightSlot(index); +} + +UIControl *UIScene_AnvilMenu::getSection(ESceneSection eSection) +{ + UIControl *control = NULL; + switch( eSection ) + { + case eSectionAnvilItem1: + control = &m_slotListItem1; + break; + case eSectionAnvilItem2: + control = &m_slotListItem2; + break; + case eSectionAnvilResult: + control = &m_slotListResult; + break; + case eSectionAnvilName: + control = &m_textInputAnvil; + break; + case eSectionAnvilInventory: + control = &m_slotListInventory; + break; + case eSectionAnvilUsing: + control = &m_slotListHotbar; + break; + default: + assert( false ); + break; + } + return control; +} + +int UIScene_AnvilMenu::KeyboardCompleteCallback(LPVOID lpParam,bool bRes) +{ + // 4J HEG - No reason to set value if keyboard was cancelled + UIScene_AnvilMenu *pClass=(UIScene_AnvilMenu *)lpParam; + pClass->setIgnoreInput(false); + + if (bRes) + { + uint16_t pchText[128]; + ZeroMemory(pchText, 128 * sizeof(uint16_t) ); + InputManager.GetText(pchText); + pClass->setEditNameValue((wchar_t *)pchText); + pClass->m_itemName = (wchar_t *)pchText; + pClass->updateItemName(); + } + return 0; +} + +void UIScene_AnvilMenu::handleEditNamePressed() +{ + setIgnoreInput(true); +#if defined(__PS3__) || defined(__ORBIS__) || defined __PSVITA__ + int language = XGetLanguage(); + switch(language) + { + case XC_LANGUAGE_JAPANESE: + case XC_LANGUAGE_KOREAN: + case XC_LANGUAGE_TCHINESE: + InputManager.RequestKeyboard(app.GetString(IDS_TITLE_RENAME),m_textInputAnvil.getLabel(),(DWORD)m_iPad,30,&UIScene_AnvilMenu::KeyboardCompleteCallback,this,C_4JInput::EKeyboardMode_Default); + break; + default: + // 4J Stu - Use a different keyboard for non-asian languages so we don't have prediction on + InputManager.RequestKeyboard(app.GetString(IDS_TITLE_RENAME),m_textInputAnvil.getLabel(),(DWORD)m_iPad,30,&UIScene_AnvilMenu::KeyboardCompleteCallback,this,C_4JInput::EKeyboardMode_Alphabet_Extended); + break; + } +#else + InputManager.RequestKeyboard(app.GetString(IDS_TITLE_RENAME),m_textInputAnvil.getLabel(),(DWORD)m_iPad,30,&UIScene_AnvilMenu::KeyboardCompleteCallback,this,C_4JInput::EKeyboardMode_Default); +#endif +} + +void UIScene_AnvilMenu::setEditNameValue(const wstring &name) +{ + m_textInputAnvil.setLabel(name); +} + +void UIScene_AnvilMenu::setEditNameEditable(bool enabled) +{ +} + +void UIScene_AnvilMenu::setCostLabel(const wstring &label, bool canAfford) +{ + IggyDataValue result; + IggyDataValue value[2]; + + IggyStringUTF16 stringVal; + stringVal.string = (IggyUTF16*)label.c_str(); + stringVal.length = label.length(); + value[0].type = IGGY_DATATYPE_string_UTF16; + value[0].string16 = stringVal; + + value[1].type = IGGY_DATATYPE_boolean; + value[1].boolval = canAfford; + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcSetCostLabel , 2 , value ); +} + +void UIScene_AnvilMenu::showCross(bool show) +{ + if(m_showingCross != show) + { + IggyDataValue result; + IggyDataValue value[1]; + + value[0].type = IGGY_DATATYPE_boolean; + value[0].boolval = show; + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcShowRedCross , 1 , value ); + + m_showingCross = show; + } +} + +void UIScene_AnvilMenu::handleDestroy() +{ +#ifdef __PSVITA__ + app.DebugPrintf("missing InputManager.DestroyKeyboard on Vita !!!!!!\n"); +#endif + + // another player destroyed the anvil, so shut down the keyboard if it is displayed +#if ( defined __PS3__ || defined __ORBIS__ || defined _DURANGO) + InputManager.DestroyKeyboard(); +#endif + UIScene_AbstractContainerMenu::handleDestroy(); +} diff --git a/Minecraft.Client/Common/UI/UIScene_AnvilMenu.h b/Minecraft.Client/Common/UI/UIScene_AnvilMenu.h new file mode 100644 index 00000000..3afc6333 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_AnvilMenu.h @@ -0,0 +1,66 @@ +#pragma once + +#include "UIScene_AbstractContainerMenu.h" +#include "IUIScene_AnvilMenu.h" +#include "..\Minecraft.World\MerchantMenu.h" + +class InventoryMenu; + +class UIScene_AnvilMenu : public UIScene_AbstractContainerMenu, public IUIScene_AnvilMenu +{ +private: + bool m_showingCross; + + enum EControls + { + eControl_TextInput, + }; + +public: + UIScene_AnvilMenu(int iPad, void *initData, UILayer *parentLayer); + + virtual EUIScene getSceneType() { return eUIScene_AnvilMenu;} + +protected: + UIControl_SlotList m_slotListItem1, m_slotListItem2, m_slotListResult; + UIControl_Label m_labelAnvil; + UIControl_TextInput m_textInputAnvil; + + IggyName m_funcShowRedCross, m_funcSetCostLabel; + + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene_AbstractContainerMenu) + UI_BEGIN_MAP_CHILD_ELEMENTS( m_controlMainPanel ) + UI_MAP_ELEMENT( m_slotListItem1, "Ingredient") + UI_MAP_ELEMENT( m_slotListItem2, "Ingredient2") + UI_MAP_ELEMENT( m_slotListResult, "Result") + UI_MAP_ELEMENT( m_labelAnvil, "AnvilText") + UI_MAP_ELEMENT( m_textInputAnvil, "AnvilTextInput") + UI_END_MAP_CHILD_ELEMENTS() + + UI_MAP_NAME(m_funcShowRedCross, L"ShowRedCross") + UI_MAP_NAME(m_funcSetCostLabel, L"SetCostLabel") + UI_END_MAP_ELEMENTS_AND_NAMES() + + virtual wstring getMoviePath(); + virtual void handleReload(); + + virtual void tick(); + + virtual int getSectionColumns(ESceneSection eSection); + virtual int getSectionRows(ESceneSection eSection); + virtual void GetPositionOfSection( ESceneSection eSection, UIVec2D* pPosition ); + virtual void GetItemScreenData( ESceneSection eSection, int iItemIndex, UIVec2D* pPosition, UIVec2D* pSize ); + virtual void handleSectionClick(ESceneSection eSection) {} + virtual void setSectionSelectedSlot(ESceneSection eSection, int x, int y); + + virtual UIControl *getSection(ESceneSection eSection); + + static int KeyboardCompleteCallback(LPVOID lpParam,bool bRes); + virtual void handleEditNamePressed(); + virtual void setEditNameValue(const wstring &name); + virtual void setEditNameEditable(bool enabled); + virtual void handleDestroy(); + + void setCostLabel(const wstring &label, bool canAfford); + void showCross(bool show); +};
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIScene_BrewingStandMenu.cpp b/Minecraft.Client/Common/UI/UIScene_BrewingStandMenu.cpp new file mode 100644 index 00000000..cd56bd84 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_BrewingStandMenu.cpp @@ -0,0 +1,309 @@ +#include "stdafx.h" +#include "UI.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.inventory.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.item.alchemy.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.level.tile.entity.h" +#include "..\..\Minecraft.h" +#include "UIScene_BrewingStandMenu.h" + +UIScene_BrewingStandMenu::UIScene_BrewingStandMenu(int iPad, void *_initData, UILayer *parentLayer) : UIScene_AbstractContainerMenu(iPad, parentLayer) +{ + // Setup all the Iggy references we need for this scene + initialiseMovie(); + + m_progressBrewingArrow.init(L"",0,0,PotionBrewing::BREWING_TIME_SECONDS * SharedConstants::TICKS_PER_SECOND,0); + m_progressBrewingBubbles.init(L"",0,0,30,0); + + m_labelBrewingStand.init( app.GetString(IDS_BREWING_STAND) ); + + BrewingScreenInput *initData = (BrewingScreenInput *)_initData; + m_brewingStand = initData->brewingStand; + + Minecraft *pMinecraft = Minecraft::GetInstance(); + if( pMinecraft->localgameModes[initData->iPad] != NULL ) + { + TutorialMode *gameMode = (TutorialMode *)pMinecraft->localgameModes[initData->iPad]; + m_previousTutorialState = gameMode->getTutorial()->getCurrentState(); + gameMode->getTutorial()->changeTutorialState(e_Tutorial_State_Brewing_Menu, this); + } + + BrewingStandMenu* menu = new BrewingStandMenu( initData->inventory, initData->brewingStand ); + + Initialize( initData->iPad, menu, true, BrewingStandMenu::INV_SLOT_START, eSectionBrewingUsing, eSectionBrewingMax ); + + m_slotListIngredient.addSlots(BrewingStandMenu::INGREDIENT_SLOT, 1); + + for(unsigned int i = 0; i < 3; ++i) + { + m_slotListBottles[i].addSlots(BrewingStandMenu::BOTTLE_SLOT_START + i, 1); + } + + if(initData) delete initData; + + app.SetRichPresenceContext(iPad, CONTEXT_GAME_STATE_BREWING); +} + +wstring UIScene_BrewingStandMenu::getMoviePath() +{ + if(app.GetLocalPlayerCount() > 1) + { + return L"BrewingStandMenuSplit"; + } + else + { + return L"BrewingStandMenu"; + } +} + +void UIScene_BrewingStandMenu::handleReload() +{ + Initialize( m_iPad, m_menu, true, BrewingStandMenu::INV_SLOT_START, eSectionBrewingUsing, eSectionBrewingMax ); + + m_slotListIngredient.addSlots(BrewingStandMenu::INGREDIENT_SLOT, 1); + + for(unsigned int i = 0; i < 3; ++i) + { + m_slotListBottles[i].addSlots(BrewingStandMenu::BOTTLE_SLOT_START + i, 1); + } +} + +void UIScene_BrewingStandMenu::tick() +{ + m_progressBrewingArrow.setProgress( m_brewingStand->getBrewTime() ); + + int value = 0; + int bubbleStep = (m_brewingStand->getBrewTime() / 2) % 7; + switch (bubbleStep) + { + case 0: + value = 0; + break; + case 6: + value = 5; + break; + case 5: + value = 10; + break; + case 4: + value = 15; + break; + case 3: + value = 20; + break; + case 2: + value = 25; + break; + case 1: + value = 30; + break; + } + m_progressBrewingBubbles.setProgress( value); + UIScene_AbstractContainerMenu::tick(); +} + +int UIScene_BrewingStandMenu::getSectionColumns(ESceneSection eSection) +{ + int cols = 0; + switch( eSection ) + { + case eSectionBrewingBottle1: + cols = 1; + break; + case eSectionBrewingBottle2: + cols = 1; + break; + case eSectionBrewingBottle3: + cols = 1; + break; + case eSectionBrewingIngredient: + cols = 1; + break; + case eSectionBrewingInventory: + cols = 9; + break; + case eSectionBrewingUsing: + cols = 9; + break; + default: + assert( false ); + break; + } + return cols; +} + +int UIScene_BrewingStandMenu::getSectionRows(ESceneSection eSection) +{ + int rows = 0; + switch( eSection ) + { + case eSectionBrewingBottle1: + rows = 1; + break; + case eSectionBrewingBottle2: + rows = 1; + break; + case eSectionBrewingBottle3: + rows = 1; + break; + case eSectionBrewingIngredient: + rows = 1; + break; + case eSectionBrewingInventory: + rows = 3; + break; + case eSectionBrewingUsing: + rows = 1; + break; + default: + assert( false ); + break; + } + return rows; +} + +void UIScene_BrewingStandMenu::GetPositionOfSection( ESceneSection eSection, UIVec2D* pPosition ) +{ + switch( eSection ) + { + case eSectionBrewingBottle1: + pPosition->x = m_slotListBottles[0].getXPos(); + pPosition->y = m_slotListBottles[0].getYPos(); + break; + case eSectionBrewingBottle2: + pPosition->x = m_slotListBottles[1].getXPos(); + pPosition->y = m_slotListBottles[1].getYPos(); + break; + case eSectionBrewingBottle3: + pPosition->x = m_slotListBottles[2].getXPos(); + pPosition->y = m_slotListBottles[2].getYPos(); + break; + case eSectionBrewingIngredient: + pPosition->x = m_slotListIngredient.getXPos(); + pPosition->y = m_slotListIngredient.getYPos(); + break; + case eSectionBrewingInventory: + pPosition->x = m_slotListInventory.getXPos(); + pPosition->y = m_slotListInventory.getYPos(); + break; + case eSectionBrewingUsing: + pPosition->x = m_slotListHotbar.getXPos(); + pPosition->y = m_slotListHotbar.getYPos(); + break; + default: + assert( false ); + break; + } +} + +void UIScene_BrewingStandMenu::GetItemScreenData( ESceneSection eSection, int iItemIndex, UIVec2D* pPosition, UIVec2D* pSize ) +{ + UIVec2D sectionSize; + + switch( eSection ) + { + case eSectionBrewingBottle1: + sectionSize.x = m_slotListBottles[0].getWidth(); + sectionSize.y = m_slotListBottles[0].getHeight(); + break; + case eSectionBrewingBottle2: + sectionSize.x = m_slotListBottles[1].getWidth(); + sectionSize.y = m_slotListBottles[1].getHeight(); + break; + case eSectionBrewingBottle3: + sectionSize.x = m_slotListBottles[2].getWidth(); + sectionSize.y = m_slotListBottles[2].getHeight(); + break; + case eSectionBrewingIngredient: + sectionSize.x = m_slotListIngredient.getWidth(); + sectionSize.y = m_slotListIngredient.getHeight(); + break; + case eSectionBrewingInventory: + sectionSize.x = m_slotListInventory.getWidth(); + sectionSize.y = m_slotListInventory.getHeight(); + break; + case eSectionBrewingUsing: + sectionSize.x = m_slotListHotbar.getWidth(); + sectionSize.y = m_slotListHotbar.getHeight(); + break; + default: + assert( false ); + break; + } + + int rows = getSectionRows(eSection); + int cols = getSectionColumns(eSection); + + pSize->x = sectionSize.x/cols; + pSize->y = sectionSize.y/rows; + + int itemCol = iItemIndex % cols; + int itemRow = iItemIndex/cols; + + pPosition->x = itemCol * pSize->x; + pPosition->y = itemRow * pSize->y; +} + +void UIScene_BrewingStandMenu::setSectionSelectedSlot(ESceneSection eSection, int x, int y) +{ + int cols = getSectionColumns(eSection); + + int index = (y * cols) + x; + + UIControl_SlotList *slotList = NULL; + switch( eSection ) + { + case eSectionBrewingBottle1: + slotList = &m_slotListBottles[0]; + break; + case eSectionBrewingBottle2: + slotList = &m_slotListBottles[1]; + break; + case eSectionBrewingBottle3: + slotList = &m_slotListBottles[2]; + break; + case eSectionBrewingIngredient: + slotList = &m_slotListIngredient; + break; + case eSectionBrewingInventory: + slotList = &m_slotListInventory; + break; + case eSectionBrewingUsing: + slotList = &m_slotListHotbar; + break; + default: + assert( false ); + break; + } + + slotList->setHighlightSlot(index); +} + +UIControl *UIScene_BrewingStandMenu::getSection(ESceneSection eSection) +{ + UIControl *control = NULL; + switch( eSection ) + { + case eSectionBrewingBottle1: + control = &m_slotListBottles[0]; + break; + case eSectionBrewingBottle2: + control = &m_slotListBottles[1]; + break; + case eSectionBrewingBottle3: + control = &m_slotListBottles[2]; + break; + case eSectionBrewingIngredient: + control = &m_slotListIngredient; + break; + case eSectionBrewingInventory: + control = &m_slotListInventory; + break; + case eSectionBrewingUsing: + control = &m_slotListHotbar; + break; + default: + assert( false ); + break; + } + return control; +} diff --git a/Minecraft.Client/Common/UI/UIScene_BrewingStandMenu.h b/Minecraft.Client/Common/UI/UIScene_BrewingStandMenu.h new file mode 100644 index 00000000..5441a1ac --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_BrewingStandMenu.h @@ -0,0 +1,49 @@ +#pragma once + +#include "UIScene_AbstractContainerMenu.h" +#include "IUIScene_BrewingMenu.h" + +class InventoryMenu; + +class UIScene_BrewingStandMenu : public UIScene_AbstractContainerMenu, public IUIScene_BrewingMenu +{ +private: + shared_ptr<BrewingStandTileEntity> m_brewingStand; + +public: + UIScene_BrewingStandMenu(int iPad, void *initData, UILayer *parentLayer); + + virtual EUIScene getSceneType() { return eUIScene_BrewingStandMenu;} + +protected: + UIControl_SlotList m_slotListBottles[3], m_slotListIngredient; + UIControl_Label m_labelBrewingStand; + UIControl_Progress m_progressBrewingArrow, m_progressBrewingBubbles; + + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene_AbstractContainerMenu) + UI_BEGIN_MAP_CHILD_ELEMENTS( m_controlMainPanel ) + UI_MAP_ELEMENT( m_slotListBottles[0], "Bottle1") + UI_MAP_ELEMENT( m_slotListBottles[1], "Bottle2") + UI_MAP_ELEMENT( m_slotListBottles[2], "Bottle3") + UI_MAP_ELEMENT( m_slotListIngredient, "Ingredient") + UI_MAP_ELEMENT( m_labelBrewingStand, "BrewingStandText") + + UI_MAP_ELEMENT( m_progressBrewingArrow, "BrewingArrow") + UI_MAP_ELEMENT( m_progressBrewingBubbles, "BrewingBubbles") + UI_END_MAP_CHILD_ELEMENTS() + UI_END_MAP_ELEMENTS_AND_NAMES() + + virtual wstring getMoviePath(); + virtual void handleReload(); + + virtual void tick(); + + virtual int getSectionColumns(ESceneSection eSection); + virtual int getSectionRows(ESceneSection eSection); + virtual void GetPositionOfSection( ESceneSection eSection, UIVec2D* pPosition ); + virtual void GetItemScreenData( ESceneSection eSection, int iItemIndex, UIVec2D* pPosition, UIVec2D* pSize ); + virtual void handleSectionClick(ESceneSection eSection) {} + virtual void setSectionSelectedSlot(ESceneSection eSection, int x, int y); + + virtual UIControl *getSection(ESceneSection eSection); +};
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIScene_ConnectingProgress.cpp b/Minecraft.Client/Common/UI/UIScene_ConnectingProgress.cpp new file mode 100644 index 00000000..0ea99a36 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_ConnectingProgress.cpp @@ -0,0 +1,267 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIScene_ConnectingProgress.h" +#include "..\..\Minecraft.h" + +UIScene_ConnectingProgress::UIScene_ConnectingProgress(int iPad, void *_initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) +{ + // Setup all the Iggy references we need for this scene + initialiseMovie(); + + parentLayer->addComponent(iPad,eUIComponent_Panorama); + parentLayer->addComponent(iPad,eUIComponent_Logo); + + m_progressBar.showBar(false); + m_progressBar.setVisible( false ); + m_labelTip.setVisible( false ); + + ConnectionProgressParams *param = (ConnectionProgressParams *)_initData; + + if( param->stringId >= 0 ) + { + m_labelTitle.init( app.GetString( param->stringId ) ); + } + else + { + m_labelTitle.init( L"" ); + } + m_progressBar.init(L"",0,0,100,0); + m_buttonConfirm.init( app.GetString( IDS_CONFIRM_OK ), eControl_Confirm ); + m_buttonConfirm.setVisible(false); + +#if 0 + if(app.GetLocalPlayerCount()>1) + { + app.AdjustSplitscreenScene(m_hObj,&m_OriginalPosition,m_iPad,false); + } +#endif + + m_showTooltips = param->showTooltips; + m_runFailTimer = param->setFailTimer; + m_timerTime = param->timerTime; + m_cancelFunc = param->cancelFunc; + m_cancelFuncParam = param->cancelFuncParam; + m_removeLocalPlayer = false; + m_showingButton = false; +} + +UIScene_ConnectingProgress::~UIScene_ConnectingProgress() +{ + m_parentLayer->removeComponent(eUIComponent_Panorama); + m_parentLayer->removeComponent(eUIComponent_Logo); +} + +void UIScene_ConnectingProgress::updateTooltips() +{ + // 4J-PB - removing the option of cancel join, since it didn't work anyway + //ui.SetTooltips( m_iPad, -1, m_showTooltips?IDS_TOOLTIPS_CANCEL_JOIN:-1); + ui.SetTooltips( m_iPad, -1, -1); +} + +void UIScene_ConnectingProgress::tick() +{ + UIScene::tick(); + + if( m_removeLocalPlayer ) + { + m_removeLocalPlayer = false; + + Minecraft *pMinecraft = Minecraft::GetInstance(); + pMinecraft->removeLocalPlayerIdx(m_iPad); +#ifdef _XBOX_ONE + ProfileManager.RemoveGamepadFromGame(m_iPad); +#endif + } +} + +wstring UIScene_ConnectingProgress::getMoviePath() +{ + if(app.GetLocalPlayerCount() > 1 && !m_parentLayer->IsFullscreenGroup()) + { + return L"FullscreenProgressSplit"; + } + else + { + return L"FullscreenProgress"; + } +} + +void UIScene_ConnectingProgress::handleGainFocus(bool navBack) +{ + UIScene::handleGainFocus(navBack); + if(!navBack && m_runFailTimer) addTimer(0,m_timerTime); +} + +void UIScene_ConnectingProgress::handleLoseFocus() +{ + int millisecsLeft = getTimer(0)->targetTime - System::currentTimeMillis(); + int millisecsTaken = getTimer(0)->duration - millisecsLeft; + app.DebugPrintf("\n"); + app.DebugPrintf("---------------------------------------------------------\n"); + app.DebugPrintf("---------------------------------------------------------\n"); + app.DebugPrintf("UIScene_ConnectingProgress time taken = %d millisecs\n", millisecsTaken); + app.DebugPrintf("---------------------------------------------------------\n"); + app.DebugPrintf("---------------------------------------------------------\n"); + app.DebugPrintf("\n"); + + + killTimer(0); +} + +void UIScene_ConnectingProgress::handleTimerComplete(int id) +{ + // Check if the connection failed + Minecraft *pMinecraft = Minecraft::GetInstance(); + + if( pMinecraft->m_connectionFailed[m_iPad] || !g_NetworkManager.IsInSession() ) + { + +#if 0 + app.RemoveBackScene(m_iPad); +#endif + + int exitReasonStringId; + switch(pMinecraft->m_connectionFailedReason[m_iPad]) + { + case DisconnectPacket::eDisconnect_LoginTooLong: + exitReasonStringId = IDS_DISCONNECTED_LOGIN_TOO_LONG; + break; + case DisconnectPacket::eDisconnect_ServerFull: + exitReasonStringId = IDS_DISCONNECTED_SERVER_FULL; + break; + case DisconnectPacket::eDisconnect_Kicked: + exitReasonStringId = IDS_DISCONNECTED_KICKED; + break; + case DisconnectPacket::eDisconnect_NoUGC_AllLocal: + exitReasonStringId = IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_ALL_LOCAL; + break; + case DisconnectPacket::eDisconnect_NoUGC_Single_Local: + exitReasonStringId = IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_SINGLE_LOCAL; + break; +#if defined(__PS3__) || defined(__ORBIS__) + case DisconnectPacket::eDisconnect_ContentRestricted_AllLocal: + exitReasonStringId = IDS_CONTENT_RESTRICTION_MULTIPLAYER; + break; + case DisconnectPacket::eDisconnect_ContentRestricted_Single_Local: + exitReasonStringId = IDS_CONTENT_RESTRICTION; + break; +#endif +#ifdef _XBOX + case DisconnectPacket::eDisconnect_NoUGC_Remote: + exitReasonStringId = IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_REMOTE; + break; +#endif + case DisconnectPacket::eDisconnect_NoFlying: + exitReasonStringId = IDS_DISCONNECTED_FLYING; + break; + case DisconnectPacket::eDisconnect_Quitting: + exitReasonStringId = IDS_DISCONNECTED_SERVER_QUIT; + break; + case DisconnectPacket::eDisconnect_OutdatedServer: + exitReasonStringId = IDS_DISCONNECTED_SERVER_OLD; + break; + case DisconnectPacket::eDisconnect_OutdatedClient: + exitReasonStringId = IDS_DISCONNECTED_CLIENT_OLD; + break; +#if defined __ORBIS__ || defined __PS3__ || defined __PSVITA__ + case DisconnectPacket::eDisconnect_NATMismatch: + exitReasonStringId = IDS_DISCONNECTED_NAT_TYPE_MISMATCH; + break; +#endif + default: + exitReasonStringId = IDS_CONNECTION_LOST_SERVER; + break; + } + + if( m_iPad != ProfileManager.GetPrimaryPad() && g_NetworkManager.IsInSession() ) + { + m_buttonConfirm.setVisible(true); + m_showingButton = true; + + // Set text + m_labelTitle.setLabel( app.GetString( IDS_CONNECTION_FAILED ) ); + m_progressBar.setLabel( app.GetString( exitReasonStringId ) ); + m_progressBar.setVisible( true ); + m_controlTimer.setVisible( false ); + } + else + { + UINT uiIDA[1]; + uiIDA[0]=IDS_CONFIRM_OK; + ui.RequestMessageBox( IDS_CONNECTION_FAILED, exitReasonStringId, uiIDA,1,ProfileManager.GetPrimaryPad(),NULL,NULL, app.GetStringTable()); + exitReasonStringId = -1; + + //app.NavigateToHomeMenu(); + app.SetAction(ProfileManager.GetPrimaryPad(),eAppAction_ExitWorld,(void *)TRUE); + } + } +} + +void UIScene_ConnectingProgress::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled) +{ + //app.DebugPrintf("UIScene_DebugOverlay handling input for pad %d, key %d, down- %s, pressed- %s, released- %s\n", iPad, key, down?"TRUE":"FALSE", pressed?"TRUE":"FALSE", released?"TRUE":"FALSE"); + + if( m_showTooltips ) + { + ui.AnimateKeyPress(m_iPad, key, repeat, pressed, released); + + switch(key) + { +// 4J-PB - Removed the option to cancel join - it didn't work anyway +// case ACTION_MENU_CANCEL: +// { +// if(m_cancelFunc != NULL) +// { +// m_cancelFunc(m_cancelFuncParam); +// } +// else +// { +// // Cancel the join +// Minecraft *pMinecraft = Minecraft::GetInstance(); +// pMinecraft->removeLocalPlayerIdx(m_iPad); +// } +// handled = true; +// } +// break; + case ACTION_MENU_OK: +#ifdef __ORBIS__ + case ACTION_MENU_TOUCHPAD_PRESS: +#endif + if(pressed) + { + sendInputToMovie(key, repeat, pressed, released); + } + break; + case ACTION_MENU_UP: + case ACTION_MENU_DOWN: + if(pressed) + { + sendInputToMovie(key, repeat, pressed, released); + } + break; + } + } +} + +void UIScene_ConnectingProgress::handlePress(F64 controlId, F64 childId) +{ + switch((int)controlId) + { + case eControl_Confirm: + if(m_showingButton) + { + if( m_iPad != ProfileManager.GetPrimaryPad() && g_NetworkManager.IsInSession() ) + { + // The connection failed if we see the button, so the temp player should be removed and the viewports updated again + // This is actually done in the tick as we can't pull down the scene we are currently in from here + m_removeLocalPlayer = true; + } + else + { + ui.NavigateToHomeMenu(); + //app.NavigateBack( ProfileManager.GetPrimaryPad() ); + } + } + break; + } +} diff --git a/Minecraft.Client/Common/UI/UIScene_ConnectingProgress.h b/Minecraft.Client/Common/UI/UIScene_ConnectingProgress.h new file mode 100644 index 00000000..2c52284c --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_ConnectingProgress.h @@ -0,0 +1,61 @@ +#pragma once + +#include "UIScene.h" + +class UIScene_ConnectingProgress : public UIScene +{ +private: + bool m_runFailTimer; + int m_timerTime; + bool m_showTooltips; + bool m_removeLocalPlayer; + bool m_showingButton; + void (*m_cancelFunc)(LPVOID param); + LPVOID m_cancelFuncParam; + + enum EControls + { + eControl_Confirm + }; + +protected: + UIControl_Progress m_progressBar; + UIControl_Label m_labelTitle, m_labelTip; + UIControl_Button m_buttonConfirm; + UIControl m_controlTimer; + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) + UI_MAP_ELEMENT( m_progressBar, "ProgressBar") + UI_MAP_ELEMENT( m_labelTitle, "Title") + UI_MAP_ELEMENT( m_labelTip, "Tip") + UI_MAP_ELEMENT( m_buttonConfirm, "Confirm") + UI_MAP_ELEMENT( m_controlTimer, "Timer") + UI_END_MAP_ELEMENTS_AND_NAMES() +public: + UIScene_ConnectingProgress(int iPad, void *initData, UILayer *parentLayer); + virtual ~UIScene_ConnectingProgress(); + + virtual void tick(); + + virtual EUIScene getSceneType() { return eUIScene_ConnectingProgress;} + + virtual void updateTooltips(); + virtual void handleGainFocus(bool navBack); + virtual void handleLoseFocus(); + + void handleTimerComplete(int id); + +protected: + // TODO: This should be pure virtual in this class + virtual wstring getMoviePath(); + +#ifdef _DURANGO + virtual long long getDefaultGtcButtons() { return 0; } +#endif + +public: + // INPUT + virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled); + +protected: + void handlePress(F64 controlId, F64 childId); +}; diff --git a/Minecraft.Client/Common/UI/UIScene_ContainerMenu.cpp b/Minecraft.Client/Common/UI/UIScene_ContainerMenu.cpp new file mode 100644 index 00000000..a0b25d18 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_ContainerMenu.cpp @@ -0,0 +1,223 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIScene_ContainerMenu.h" + +#include "..\..\..\Minecraft.World\net.minecraft.world.inventory.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.item.h" +#include "..\..\..\Minecraft.World\net.minecraft.stats.h" +#include "..\..\LocalPlayer.h" +#include "..\..\Minecraft.h" +#include "..\Tutorial\Tutorial.h" +#include "..\Tutorial\TutorialMode.h" +#include "..\Tutorial\TutorialEnum.h" + +UIScene_ContainerMenu::UIScene_ContainerMenu(int iPad, void *_initData, UILayer *parentLayer) : UIScene_AbstractContainerMenu(iPad, parentLayer) +{ + ContainerScreenInput *initData = (ContainerScreenInput *)_initData; + m_bLargeChest = (initData->container->getContainerSize() > 3*9)?true:false; + + // Setup all the Iggy references we need for this scene + initialiseMovie(); + + m_labelChest.init(app.GetString(initData->container->getName())); + + ContainerMenu* menu = new ContainerMenu( initData->inventory, initData->container ); + + Minecraft *pMinecraft = Minecraft::GetInstance(); + if( pMinecraft->localgameModes[iPad] != NULL ) + { + TutorialMode *gameMode = (TutorialMode *)pMinecraft->localgameModes[initData->iPad]; + m_previousTutorialState = gameMode->getTutorial()->getCurrentState(); + gameMode->getTutorial()->changeTutorialState(e_Tutorial_State_Container_Menu, this); + } + + int containerSize = menu->getSize() - (27 + 9); + + Initialize( initData->iPad, menu, true, containerSize, eSectionContainerUsing, eSectionContainerMax); + + m_slotListContainer.addSlots(0, containerSize); + + if(initData) delete initData; +} + +wstring UIScene_ContainerMenu::getMoviePath() +{ + if(m_bLargeChest) + { + if(app.GetLocalPlayerCount() > 1) + { + return L"ChestLargeMenuSplit"; + } + else + { + return L"ChestLargeMenu"; + } + } + else + { + if(app.GetLocalPlayerCount() > 1) + { + return L"ChestMenuSplit"; + } + else + { + return L"ChestMenu"; + } + } +} + +void UIScene_ContainerMenu::handleReload() +{ + int containerSize = m_menu->getSize() - (27 + 9); + + Initialize( m_iPad, m_menu, true, containerSize, eSectionContainerUsing, eSectionContainerMax ); + + m_slotListContainer.addSlots(0, containerSize); +} + +int UIScene_ContainerMenu::getSectionColumns(ESceneSection eSection) +{ + int cols = 0; + switch( eSection ) + { + case eSectionContainerChest: + cols = 9; + break; + case eSectionContainerInventory: + cols = 9; + break; + case eSectionContainerUsing: + cols = 9; + break; + default: + assert( false ); + break; + } + return cols; +} + +int UIScene_ContainerMenu::getSectionRows(ESceneSection eSection) +{ + int rows = 0; + switch( eSection ) + { + case eSectionContainerChest: + rows = (m_menu->getSize() - (27 + 9)) / 9; + break; + case eSectionContainerInventory: + rows = 3; + break; + case eSectionContainerUsing: + rows = 1; + break; + default: + assert( false ); + break; + } + return rows; +} + +void UIScene_ContainerMenu::GetPositionOfSection( ESceneSection eSection, UIVec2D* pPosition ) +{ + switch( eSection ) + { + case eSectionContainerChest: + pPosition->x = m_slotListContainer.getXPos(); + pPosition->y = m_slotListContainer.getYPos(); + break; + case eSectionContainerInventory: + pPosition->x = m_slotListInventory.getXPos(); + pPosition->y = m_slotListInventory.getYPos(); + break; + case eSectionContainerUsing: + pPosition->x = m_slotListHotbar.getXPos(); + pPosition->y = m_slotListHotbar.getYPos(); + break; + default: + assert( false ); + break; + } +} + +void UIScene_ContainerMenu::GetItemScreenData( ESceneSection eSection, int iItemIndex, UIVec2D* pPosition, UIVec2D* pSize ) +{ + UIVec2D sectionSize; + + switch( eSection ) + { + case eSectionContainerChest: + sectionSize.x = m_slotListContainer.getWidth(); + sectionSize.y = m_slotListContainer.getHeight(); + break; + case eSectionContainerInventory: + sectionSize.x = m_slotListInventory.getWidth(); + sectionSize.y = m_slotListInventory.getHeight(); + break; + case eSectionContainerUsing: + sectionSize.x = m_slotListHotbar.getWidth(); + sectionSize.y = m_slotListHotbar.getHeight(); + break; + default: + assert( false ); + break; + } + + int rows = getSectionRows(eSection); + int cols = getSectionColumns(eSection); + + pSize->x = sectionSize.x/cols; + pSize->y = sectionSize.y/rows; + + int itemCol = iItemIndex % cols; + int itemRow = iItemIndex/cols; + + pPosition->x = itemCol * pSize->x; + pPosition->y = itemRow * pSize->y; +} + +void UIScene_ContainerMenu::setSectionSelectedSlot(ESceneSection eSection, int x, int y) +{ + int cols = getSectionColumns(eSection); + + int index = (y * cols) + x; + + UIControl_SlotList *slotList = NULL; + switch( eSection ) + { + case eSectionContainerChest: + slotList = &m_slotListContainer; + break; + case eSectionContainerInventory: + slotList = &m_slotListInventory; + break; + case eSectionContainerUsing: + slotList = &m_slotListHotbar; + break; + default: + assert( false ); + break; + } + + slotList->setHighlightSlot(index); +} + +UIControl *UIScene_ContainerMenu::getSection(ESceneSection eSection) +{ + UIControl *control = NULL; + switch( eSection ) + { + case eSectionContainerChest: + control = &m_slotListContainer; + break; + case eSectionContainerInventory: + control = &m_slotListInventory; + break; + case eSectionContainerUsing: + control = &m_slotListHotbar; + break; + default: + assert( false ); + break; + } + return control; +}
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIScene_ContainerMenu.h b/Minecraft.Client/Common/UI/UIScene_ContainerMenu.h new file mode 100644 index 00000000..f2ad743c --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_ContainerMenu.h @@ -0,0 +1,40 @@ +#pragma once + +#include "UIScene_AbstractContainerMenu.h" +#include "IUIScene_ContainerMenu.h" + +class InventoryMenu; + +class UIScene_ContainerMenu : public UIScene_AbstractContainerMenu, public IUIScene_ContainerMenu +{ +private: + bool m_bLargeChest; + +public: + UIScene_ContainerMenu(int iPad, void *initData, UILayer *parentLayer); + + virtual EUIScene getSceneType() { return eUIScene_ContainerMenu;} + +protected: + UIControl_SlotList m_slotListContainer; + UIControl_Label m_labelChest; + + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene_AbstractContainerMenu) + UI_BEGIN_MAP_CHILD_ELEMENTS( m_controlMainPanel ) + UI_MAP_ELEMENT( m_slotListContainer, "containerList") + UI_MAP_ELEMENT( m_labelChest, "chestLabel") + UI_END_MAP_CHILD_ELEMENTS() + UI_END_MAP_ELEMENTS_AND_NAMES() + + virtual wstring getMoviePath(); + virtual void handleReload(); + + virtual int getSectionColumns(ESceneSection eSection); + virtual int getSectionRows(ESceneSection eSection); + virtual void GetPositionOfSection( ESceneSection eSection, UIVec2D* pPosition ); + virtual void GetItemScreenData( ESceneSection eSection, int iItemIndex, UIVec2D* pPosition, UIVec2D* pSize ); + virtual void handleSectionClick(ESceneSection eSection) {} + virtual void setSectionSelectedSlot(ESceneSection eSection, int x, int y); + + virtual UIControl *getSection(ESceneSection eSection); +};
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIScene_ControlsMenu.cpp b/Minecraft.Client/Common/UI/UIScene_ControlsMenu.cpp new file mode 100644 index 00000000..c05b502e --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_ControlsMenu.cpp @@ -0,0 +1,336 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIScene_ControlsMenu.h" +#include "..\..\Minecraft.h" +#include "..\..\MultiplayerLocalPlayer.h" + +UIScene_ControlsMenu::UIScene_ControlsMenu(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) +{ + // Setup all the Iggy references we need for this scene + initialiseMovie(); + + IggyDataValue result; + IggyDataValue value[1]; + value[0].type = IGGY_DATATYPE_number; +#if defined(_XBOX) || defined(_WIN64) + value[0].number = (F64)0; +#elif defined(_DURANGO) + value[0].number = (F64)1; +#elif defined(__PS3__) + value[0].number = (F64)2; +#elif defined(__ORBIS__) + value[0].number = (F64)3; +#elif defined(__PSVITA__) + value[0].number = (F64)4; +#endif + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcSetPlatform , 1 , value ); + + bool bNotInGame=(Minecraft::GetInstance()->level==NULL); + + if(bNotInGame) + { + LPWSTR layoutString = new wchar_t[ 128 ]; + swprintf( layoutString, 128, L"%ls", VER_PRODUCTVERSION_STR_W); + m_labelVersion.init(layoutString); + delete [] layoutString; + } + // 4J-PB - stop the label showing in the in-game controls menu + else + { + m_labelVersion.init(" "); + } + m_bCreativeMode = !bNotInGame && Minecraft::GetInstance()->localplayers[m_iPad] && Minecraft::GetInstance()->localplayers[m_iPad]->abilities.mayfly; + +#ifndef __PSVITA__ +#ifdef __ORBIS__ + // no buttons to initialise if we're running this on PS4 remote play + if(!InputManager.UsingRemoteVita()) +#endif + { + m_buttonLayouts[0].init(L"1", eControl_Button0); + m_buttonLayouts[1].init(L"2", eControl_Button1); + m_buttonLayouts[2].init(L"3", eControl_Button2); + } +#endif + + m_checkboxInvert.init(app.GetString(IDS_INVERT_LOOK), eControl_InvertLook, app.GetGameSettings(m_iPad,eGameSetting_ControlInvertLook)); + m_checkboxSouthpaw.init(app.GetString(IDS_SOUTHPAW), eControl_Southpaw, app.GetGameSettings(m_iPad,eGameSetting_ControlSouthPaw)); + + m_iSchemeTextA[0]=IDS_CONTROLS_SCHEME0; + m_iSchemeTextA[1]=IDS_CONTROLS_SCHEME1; + m_iSchemeTextA[2]=IDS_CONTROLS_SCHEME2; + + int iSelected=app.GetGameSettings(m_iPad,eGameSetting_ControlScheme); + +#ifndef __PSVITA__ + LPWSTR layoutString = new wchar_t[ 128 ]; + swprintf( layoutString, 128, L"%ls : %ls", app.GetString( IDS_CURRENT_LAYOUT ),app.GetString(m_iSchemeTextA[iSelected])); +#ifdef __ORBIS__ + if (!InputManager.UsingRemoteVita()) +#endif + { + m_labelCurrentLayout.init(layoutString); + } +#endif + + m_iCurrentNavigatedControlsLayout = iSelected; + + +#ifdef __ORBIS__ + // don't set controller layout if we're entering the PS4 remote play scene + if(!InputManager.UsingRemoteVita()) +#endif + { + IggyDataValue result; + IggyDataValue value[1]; + value[0].type = IGGY_DATATYPE_number; + value[0].number = (F64)m_iCurrentNavigatedControlsLayout; + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcSetControllerLayout , 1 , value ); + } + +#ifdef __ORBIS__ + // Set mapping to Vita mapping + if (InputManager.UsingRemoteVita()) m_iCurrentNavigatedControlsLayout = 3; +#elif defined __PSVITA__ + // Set mapping to Vita mapping + if (InputManager.IsVitaTV()) m_iCurrentNavigatedControlsLayout = 1; +#endif + + for(unsigned int i = 0; i < e_PadCOUNT; ++i) + { + m_labelsPad[i].init(L""); + m_controlLines[i].setVisible(false); + } + m_bLayoutChanged = false; + + + PositionAllText(m_iPad); +} + +wstring UIScene_ControlsMenu::getMoviePath() +{ +#ifdef __ORBIS__ + if(InputManager.UsingRemoteVita()) + { + return L"ControlsRemotePlay"; + } + else +#endif +#ifdef __PSVITA__ + if(InputManager.IsVitaTV()) + { + return L"ControlsTV"; + } + else +#endif + if(app.GetLocalPlayerCount() > 1) + { + return L"ControlsSplit"; + } + else + { + return L"Controls"; + } +} + +void UIScene_ControlsMenu::updateTooltips() +{ + ui.SetTooltips( m_iPad, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK); +} + +void UIScene_ControlsMenu::tick() +{ + if(m_bLayoutChanged) PositionAllText(m_iPad); + UIScene::tick(); +} + +void UIScene_ControlsMenu::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled) +{ + //app.DebugPrintf("UIScene_DebugOverlay handling input for pad %d, key %d, down- %s, pressed- %s, released- %s\n", iPad, key, down?"TRUE":"FALSE", pressed?"TRUE":"FALSE", released?"TRUE":"FALSE"); + ui.AnimateKeyPress(m_iPad, key, repeat, pressed, released); + + switch(key) + { + case ACTION_MENU_CANCEL: + if(pressed) + { + app.CheckGameSettingsChanged(true,iPad); + navigateBack(); + } + break; + case ACTION_MENU_OK: +#ifdef __ORBIS__ + case ACTION_MENU_TOUCHPAD_PRESS: +#endif + if( pressed ) + { + //CD - Added for audio + ui.PlayUISFX(eSFX_Press); + } + sendInputToMovie(key, repeat, pressed, released); + break; + case ACTION_MENU_UP: + case ACTION_MENU_DOWN: + case ACTION_MENU_LEFT: + case ACTION_MENU_RIGHT: + sendInputToMovie(key, repeat, pressed, released); + break; + } +} + +void UIScene_ControlsMenu::handleCheckboxToggled(F64 controlId, bool selected) +{ + switch((int)controlId) + { + case eControl_InvertLook: + app.SetGameSettings(m_iPad,eGameSetting_ControlInvertLook,(unsigned char)( selected ) ); + break; + case eControl_Southpaw: + app.SetGameSettings(m_iPad,eGameSetting_ControlSouthPaw,(unsigned char)( selected ) ); + PositionAllText(m_iPad); + break; + }; +} + +void UIScene_ControlsMenu::handlePress(F64 controlId, F64 childId) +{ + int control = (int)controlId; + switch(control) + { + case eControl_Button0: + case eControl_Button1: + case eControl_Button2: + app.SetGameSettings(m_iPad,eGameSetting_ControlScheme,(unsigned char)control); + LPWSTR layoutString = new wchar_t[ 128 ]; + swprintf( layoutString, 128, L"%ls : %ls", app.GetString( IDS_CURRENT_LAYOUT ),app.GetString(m_iSchemeTextA[control])); +#ifdef __ORBIS__ + if (!InputManager.UsingRemoteVita()) +#endif + { + m_labelCurrentLayout.setLabel(layoutString); + } + + break; + }; +} + +void UIScene_ControlsMenu::handleFocusChange(F64 controlId, F64 childId) +{ + int control = (int)controlId; + switch(control) + { + case eControl_Button0: + case eControl_Button1: + case eControl_Button2: + m_iCurrentNavigatedControlsLayout=control; + m_bLayoutChanged = true; + break; + }; +} + +void UIScene_ControlsMenu::PositionAllText(int iPad) +{ + for(unsigned int i = 0; i < e_PadCOUNT; ++i) + { + m_labelsPad[i].setLabel(L""); + m_controlLines[i].setVisible(false); + } + + if(m_bCreativeMode) + { + PositionText(iPad,IDS_CONTROLS_JUMPFLY,MINECRAFT_ACTION_JUMP); + } + else + { + PositionText(iPad,IDS_CONTROLS_JUMP,MINECRAFT_ACTION_JUMP); + } + PositionText(iPad,IDS_CONTROLS_INVENTORY,MINECRAFT_ACTION_INVENTORY); + PositionText(iPad,IDS_CONTROLS_PAUSE,MINECRAFT_ACTION_PAUSEMENU); + if(m_bCreativeMode) + { + PositionText(iPad,IDS_CONTROLS_SNEAKFLY,MINECRAFT_ACTION_SNEAK_TOGGLE); + } + else + { + PositionText(iPad,IDS_CONTROLS_SNEAK,MINECRAFT_ACTION_SNEAK_TOGGLE); + } + PositionText(iPad,IDS_CONTROLS_USE,MINECRAFT_ACTION_USE); + PositionText(iPad,IDS_CONTROLS_ACTION,MINECRAFT_ACTION_ACTION); + PositionText(iPad,IDS_CONTROLS_HELDITEM,MINECRAFT_ACTION_RIGHT_SCROLL); + PositionText(iPad,IDS_CONTROLS_HELDITEM,MINECRAFT_ACTION_LEFT_SCROLL); + PositionText(iPad,IDS_CONTROLS_DROP,MINECRAFT_ACTION_DROP); + PositionText(iPad,IDS_CONTROLS_CRAFTING,MINECRAFT_ACTION_CRAFTING); + PositionText(iPad,IDS_CONTROLS_THIRDPERSON,MINECRAFT_ACTION_RENDER_THIRD_PERSON); + PositionText(iPad,IDS_CONTROLS_PLAYERS,MINECRAFT_ACTION_GAME_INFO); + + // Swap for southpaw. + if ( app.GetGameSettings(m_iPad,eGameSetting_ControlSouthPaw) ) + { + // Move + PositionText(iPad,IDS_CONTROLS_LOOK,MINECRAFT_ACTION_RIGHT); + // Look + PositionText(iPad,IDS_CONTROLS_MOVE,MINECRAFT_ACTION_LOOK_RIGHT); + } + else // Normal right handed. + { + // Move + PositionText(iPad,IDS_CONTROLS_MOVE,MINECRAFT_ACTION_RIGHT); + // Look + PositionText(iPad,IDS_CONTROLS_LOOK,MINECRAFT_ACTION_LOOK_RIGHT); + } + + bool layoutHasDpadFly; +#ifdef __PSVITA__ + layoutHasDpadFly = m_iCurrentNavigatedControlsLayout == 1; +#else + layoutHasDpadFly = m_iCurrentNavigatedControlsLayout == 0; +#endif + + // If we're in controls mode 1, and creative mode show the dpad for Creative Mode + if(m_bCreativeMode && layoutHasDpadFly) + { + PositionText(iPad,IDS_CONTROLS_DPAD,MINECRAFT_ACTION_DPAD_LEFT); + } + m_bLayoutChanged = false; +} + +void UIScene_ControlsMenu::PositionText(int iPad,int iTextID, unsigned char ucAction) +{ + unsigned int uiVal = InputManager.GetGameJoypadMaps(m_iCurrentNavigatedControlsLayout, ucAction); + + if (uiVal & _360_JOY_BUTTON_A) PositionTextDirect(iPad, iTextID, e_PadA, true); + if (uiVal & _360_JOY_BUTTON_B) PositionTextDirect(iPad, iTextID, e_PadB, true); + if (uiVal & _360_JOY_BUTTON_X) PositionTextDirect(iPad, iTextID, e_PadX, true); + if (uiVal & _360_JOY_BUTTON_Y) PositionTextDirect(iPad, iTextID, e_PadY, true); + if (uiVal & _360_JOY_BUTTON_BACK) + { +#ifdef __ORBIS__ + PositionTextDirect(iPad, iTextID, (InputManager.UsingRemoteVita() ? e_PadTouch : e_PadBack), true); +#else + PositionTextDirect(iPad, iTextID, e_PadBack, true); +#endif + } + if (uiVal & _360_JOY_BUTTON_START) PositionTextDirect(iPad, iTextID, e_PadStart, true); + if (uiVal & _360_JOY_BUTTON_RB) PositionTextDirect(iPad, iTextID, e_PadRB, true); + if (uiVal & _360_JOY_BUTTON_LB) PositionTextDirect(iPad, iTextID, e_PadLB, true); + if (uiVal & _360_JOY_BUTTON_RTHUMB) PositionTextDirect(iPad, iTextID, e_PadRS_1, true); + if (uiVal & _360_JOY_BUTTON_LTHUMB) PositionTextDirect(iPad, iTextID, e_PadLS_1, true); + // Look + if (uiVal & _360_JOY_BUTTON_RSTICK_RIGHT) PositionTextDirect(iPad, iTextID, e_PadRS_2, true); + // Move + if (uiVal & _360_JOY_BUTTON_LSTICK_RIGHT) PositionTextDirect(iPad, iTextID, e_PadLS_2, true); + if (uiVal & _360_JOY_BUTTON_RT) PositionTextDirect(iPad, iTextID, e_PadRT, true); + if (uiVal & _360_JOY_BUTTON_LT) PositionTextDirect(iPad, iTextID, e_PadLT, true); + if (uiVal & _360_JOY_BUTTON_DPAD_RIGHT) PositionTextDirect(iPad, iTextID, e_PadDPadRight, true); + if (uiVal & _360_JOY_BUTTON_DPAD_LEFT) PositionTextDirect(iPad, iTextID, e_PadDPadLeft, true); + if (uiVal & _360_JOY_BUTTON_DPAD_UP) PositionTextDirect(iPad, iTextID, e_PadDPadUp, true); + if (uiVal & _360_JOY_BUTTON_DPAD_DOWN) PositionTextDirect(iPad, iTextID, e_PadDPadDown, true); + } + +void UIScene_ControlsMenu::PositionTextDirect(int iPad,int iTextID, int iControlDetailsIndex, bool bShow) +{ + LPCWSTR text = app.GetString(iTextID); + + m_labelsPad[iControlDetailsIndex].setLabel(text); + m_controlLines[iControlDetailsIndex].setVisible(bShow); +}
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIScene_ControlsMenu.h b/Minecraft.Client/Common/UI/UIScene_ControlsMenu.h new file mode 100644 index 00000000..538207fe --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_ControlsMenu.h @@ -0,0 +1,141 @@ +#pragma once + +#include "UIScene.h" + +class UIScene_ControlsMenu : public UIScene +{ +private: + enum EControl + { + // Buttons must be first three controls here + eControl_Button0, + eControl_Button1, + eControl_Button2, + eControl_InvertLook, + eControl_Southpaw, + }; + + enum EPadButtons + { + e_PadBack=0, + e_PadLT, + e_PadLB, + e_PadDPadLeft, + e_PadDPadRight, + e_PadDPadUp, + e_PadDPadDown, + e_PadLS_1, + e_PadLS_2, + e_PadStart, + e_PadRT, + e_PadRB, + e_PadY, + e_PadB, + e_PadA, + e_PadX, + e_PadRS_1, + e_PadRS_2, + e_PadTouch, + + e_PadCOUNT, + }; + + int m_iSchemeTextA[3]; + int m_iCurrentNavigatedControlsLayout; + bool m_bCreativeMode; + bool m_bLayoutChanged; + + UIControl_Label m_labelCurrentLayout; + UIControl_Label m_labelVersion; + UIControl_Label m_labelsPad[e_PadCOUNT]; + UIControl m_controlLines[e_PadCOUNT]; + UIControl_Button m_buttonLayouts[3]; + UIControl_CheckBox m_checkboxInvert, m_checkboxSouthpaw; + IggyName m_funcSetPlatform, m_funcSetControllerLayout; + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) + +#ifndef __PSVITA__ +#ifdef __ORBIS__ + if (!InputManager.UsingRemoteVita()) +#endif + { + UI_MAP_ELEMENT( m_labelCurrentLayout, "CurrentLayout") + + UI_MAP_ELEMENT( m_buttonLayouts[0], "Button1") + UI_MAP_ELEMENT( m_buttonLayouts[1], "Button2") + UI_MAP_ELEMENT( m_buttonLayouts[2], "Button3") + } +#endif + + UI_MAP_ELEMENT( m_labelsPad[e_PadBack], "LabelBack") + UI_MAP_ELEMENT( m_labelsPad[e_PadLT], "LabelLT") + UI_MAP_ELEMENT( m_labelsPad[e_PadLB], "LabelLB") + UI_MAP_ELEMENT( m_labelsPad[e_PadDPadLeft], "LabelDPadLeft") + UI_MAP_ELEMENT( m_labelsPad[e_PadDPadRight], "LabelDPadRight") + UI_MAP_ELEMENT( m_labelsPad[e_PadDPadUp], "LabelDPadUp") + UI_MAP_ELEMENT( m_labelsPad[e_PadDPadDown], "LabelDPadDown") + UI_MAP_ELEMENT( m_labelsPad[e_PadLS_1], "LabelLS_1") + UI_MAP_ELEMENT( m_labelsPad[e_PadLS_2], "LabelLS_2") + UI_MAP_ELEMENT( m_labelsPad[e_PadStart], "LabelStart") + UI_MAP_ELEMENT( m_labelsPad[e_PadRT], "LabelRT") + UI_MAP_ELEMENT( m_labelsPad[e_PadRB], "LabelRB") + UI_MAP_ELEMENT( m_labelsPad[e_PadY], "LabelY") + UI_MAP_ELEMENT( m_labelsPad[e_PadB], "LabelB") + UI_MAP_ELEMENT( m_labelsPad[e_PadA], "LabelA") + UI_MAP_ELEMENT( m_labelsPad[e_PadX], "LabelX") + UI_MAP_ELEMENT( m_labelsPad[e_PadRS_1], "LabelRS_1") + UI_MAP_ELEMENT( m_labelsPad[e_PadRS_2], "LabelRS_2") + UI_MAP_ELEMENT( m_labelsPad[e_PadTouch], "LabelTouch") + + UI_MAP_ELEMENT( m_controlLines[e_PadBack], "LineBack") + UI_MAP_ELEMENT( m_controlLines[e_PadLT], "LineLT") + UI_MAP_ELEMENT( m_controlLines[e_PadLB], "LineLB") + UI_MAP_ELEMENT( m_controlLines[e_PadDPadLeft], "LineDpadLeft") + UI_MAP_ELEMENT( m_controlLines[e_PadDPadRight], "LineDpadRight") + UI_MAP_ELEMENT( m_controlLines[e_PadDPadUp], "LineDpadUp") + UI_MAP_ELEMENT( m_controlLines[e_PadDPadDown], "LineDpadDown") + UI_MAP_ELEMENT( m_controlLines[e_PadLS_1], "LineL3") + UI_MAP_ELEMENT( m_controlLines[e_PadLS_2], "LineLeftStick") + UI_MAP_ELEMENT( m_controlLines[e_PadStart], "LineStart") + UI_MAP_ELEMENT( m_controlLines[e_PadRT], "LineRT") + UI_MAP_ELEMENT( m_controlLines[e_PadRB], "LineRB") + UI_MAP_ELEMENT( m_controlLines[e_PadY], "LineY") + UI_MAP_ELEMENT( m_controlLines[e_PadB], "LineB") + UI_MAP_ELEMENT( m_controlLines[e_PadA], "LineA") + UI_MAP_ELEMENT( m_controlLines[e_PadX], "LineX") + UI_MAP_ELEMENT( m_controlLines[e_PadRS_1], "LineR3") + UI_MAP_ELEMENT( m_controlLines[e_PadRS_2], "LineRightStick") + UI_MAP_ELEMENT( m_controlLines[e_PadTouch], "LineTouch") + + UI_MAP_ELEMENT( m_checkboxInvert, "InvertLook") + UI_MAP_ELEMENT( m_checkboxSouthpaw, "SouthPaw") + + UI_MAP_NAME( m_funcSetPlatform, L"SetPlatform") + UI_MAP_NAME( m_funcSetControllerLayout, L"SetControllerLayout") + UI_MAP_ELEMENT( m_labelVersion, "Version") + UI_END_MAP_ELEMENTS_AND_NAMES() +public: + UIScene_ControlsMenu(int iPad, void *initData, UILayer *parentLayer); + + virtual EUIScene getSceneType() { return eUIScene_ControlsMenu;} + + virtual void updateTooltips(); + virtual void tick(); + +protected: + // TODO: This should be pure virtual in this class + virtual wstring getMoviePath(); + +public: + // INPUT + virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled); + + virtual void handleCheckboxToggled(F64 controlId, bool selected); + virtual void handlePress(F64 controlId, F64 childId); + virtual void handleFocusChange(F64 controlId, F64 childId); + +private: + void PositionText(int iPad,int iTextID, unsigned char ucAction); + void PositionTextDirect(int iPad,int iTextID, int iControlDetailsIndex, bool bShow); + void PositionAllText(int iPad); +};
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIScene_CraftingMenu.cpp b/Minecraft.Client/Common/UI/UIScene_CraftingMenu.cpp new file mode 100644 index 00000000..5b729069 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_CraftingMenu.cpp @@ -0,0 +1,769 @@ +#include "stdafx.h" +#include "UI.h" +#include "..\..\Minecraft.h" +#include "..\..\MultiplayerLocalPlayer.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.inventory.h" +#include "UIScene_CraftingMenu.h" + +#ifdef __PSVITA__ +#define GAME_CRAFTING_TOUCHUPDATE_TIMER_ID 0 +#define GAME_CRAFTING_TOUCHUPDATE_TIMER_TIME 100 +#endif + +UIScene_CraftingMenu::UIScene_CraftingMenu(int iPad, void *_initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) +{ + m_bIgnoreKeyPresses = false; + + CraftingPanelScreenInput* initData = (CraftingPanelScreenInput*)_initData; + m_iContainerType=initData->iContainerType; + m_pPlayer=initData->player; + m_bSplitscreen=initData->bSplitscreen; + + // Setup all the Iggy references we need for this scene + initialiseMovie(); + + for(unsigned int i = 0; i < 4; ++i) m_labelIngredientsDesc[i].init(L""); + m_labelDescription.init(L""); + m_labelGroupName.init(L""); + m_labelItemName.init(L""); + m_labelInventory.init( app.GetString(IDS_INVENTORY) ); + m_labelIngredients.init( app.GetString(IDS_INGREDIENTS) ); + + if(m_iContainerType==RECIPE_TYPE_2x2) + { + m_menu = m_pPlayer->inventoryMenu; + m_iMenuInventoryStart = InventoryMenu::INV_SLOT_START; + m_iMenuHotBarStart = InventoryMenu::USE_ROW_SLOT_START; + } + else + { + CraftingMenu *menu = new CraftingMenu(m_pPlayer->inventory, m_pPlayer->level, initData->x, initData->y, initData->z); + Minecraft::GetInstance()->localplayers[m_iPad]->containerMenu = menu; + + m_menu = menu; + m_iMenuInventoryStart = CraftingMenu::INV_SLOT_START; + m_iMenuHotBarStart = CraftingMenu::USE_ROW_SLOT_START; + } + m_slotListInventory.addSlots(CRAFTING_INVENTORY_SLOT_START,CRAFTING_INVENTORY_SLOT_END - CRAFTING_INVENTORY_SLOT_START); + m_slotListHotBar.addSlots(CRAFTING_HOTBAR_SLOT_START, CRAFTING_HOTBAR_SLOT_END - CRAFTING_HOTBAR_SLOT_START); + +#if TO_BE_IMPLEMENTED + // if we are in splitscreen, then we need to figure out if we want to move this scene + if(m_bSplitscreen) + { + app.AdjustSplitscreenScene(m_hObj,&m_OriginalPosition,m_iPad); + } + + XuiElementSetShow(m_hGrid,TRUE); + XuiElementSetShow(m_hPanel,TRUE); +#endif + + if(m_iContainerType==RECIPE_TYPE_3x3) + { + m_iIngredientsMaxSlotC = m_iIngredients3x3SlotC; + m_pGroupA=(Recipy::_eGroupType *)&m_GroupTypeMapping9GridA; + m_pGroupTabA=(_eGroupTab *)&m_GroupTabBkgMapping3x3A; + m_iCraftablesMaxHSlotC=m_iMaxHSlot3x3C; + } + else + { + m_iIngredientsMaxSlotC = m_iIngredients2x2SlotC; + m_pGroupA=(Recipy::_eGroupType *)&m_GroupTypeMapping4GridA; + m_pGroupTabA=(_eGroupTab *)&m_GroupTabBkgMapping2x2A; + m_iCraftablesMaxHSlotC=m_iMaxHSlot2x2C; + } + +#if TO_BE_IMPLEMENTED + + + // display the first group tab + m_hTabGroupA[m_iGroupIndex].SetShow(TRUE); + + // store the slot 0 position + m_pHSlotsBrushImageControl[0]->GetPosition(&m_vSlot0Pos); + m_pHSlotsBrushImageControl[1]->GetPosition(&vec); + m_fSlotSize=vec.x-m_vSlot0Pos.x; + + // store the slot 0 highlight position + m_hHighlight.GetPosition(&m_vSlot0HighlightPos); + // Store the V slot position + m_hScrollBar2.GetPosition(&m_vSlot0V2ScrollPos); + m_hScrollBar3.GetPosition(&m_vSlot0V3ScrollPos); + + // get the position of the slot from the xui, and apply any offset needed + for(int i=0;i<m_iCraftablesMaxHSlotC;i++) + { + m_pHSlotsBrushImageControl[i]->SetShow(FALSE); + } + + XuiElementSetShow(m_hGridInventory,FALSE); + + m_hScrollBar2.SetShow(FALSE); + m_hScrollBar3.SetShow(FALSE); + +#endif + + app.SetRichPresenceContext(m_iPad,CONTEXT_GAME_STATE_CRAFTING); + setGroupText(GetGroupNameText(m_pGroupA[m_iGroupIndex])); + + // Update the tutorial state + Minecraft *pMinecraft = Minecraft::GetInstance(); + + if( pMinecraft->localgameModes[m_iPad] != NULL ) + { + TutorialMode *gameMode = (TutorialMode *)pMinecraft->localgameModes[m_iPad]; + m_previousTutorialState = gameMode->getTutorial()->getCurrentState(); + if(m_iContainerType==RECIPE_TYPE_2x2) + { + gameMode->getTutorial()->changeTutorialState(e_Tutorial_State_2x2Crafting_Menu, this); + } + else + { + gameMode->getTutorial()->changeTutorialState(e_Tutorial_State_3x3Crafting_Menu, this); + } + } + +#ifdef _TO_BE_IMPLEMENTED + XuiSetTimer(m_hObj,IGNORE_KEYPRESS_TIMERID,IGNORE_KEYPRESS_TIME); +#endif + + for(unsigned int i = 0; i < 4; ++i) + { + m_slotListIngredients[i].addSlot(CRAFTING_INGREDIENTS_DESCRIPTION_START + i); + } + m_slotListCraftingOutput.addSlot(CRAFTING_OUTPUT_SLOT_START); + m_slotListIngredientsLayout.addSlots(CRAFTING_INGREDIENTS_LAYOUT_START, m_iIngredientsMaxSlotC); + + // 3 Slot vertical scroll + m_slotListCrafting3VSlots[0].addSlot(CRAFTING_V_SLOT_START + 0); + m_slotListCrafting3VSlots[1].addSlot(CRAFTING_V_SLOT_START + 1); + m_slotListCrafting3VSlots[2].addSlot(CRAFTING_V_SLOT_START + 2); + + // 2 Slot vertical scroll + // 2 slot scroll has swapped order + m_slotListCrafting2VSlots[0].addSlot(CRAFTING_V_SLOT_START + 1); + m_slotListCrafting2VSlots[1].addSlot(CRAFTING_V_SLOT_START + 0); + + // 1 Slot scroll (for 480 mainly) + m_slotListCrafting1VSlots.addSlot(CRAFTING_V_SLOT_START); + + m_slotListCraftingHSlots.addSlots(CRAFTING_H_SLOT_START,m_iCraftablesMaxHSlotC); + + // Check which recipes are available with the resources we have + CheckRecipesAvailable(); + // reset the vertical slots + iVSlotIndexA[0]=CanBeMadeA[m_iCurrentSlotHIndex].iCount-1; + iVSlotIndexA[1]=0; + iVSlotIndexA[2]=1; + UpdateVerticalSlots(); + UpdateHighlight(); + + if(initData) delete initData; + + // in this scene, we override the press sound with our own for crafting success or fail + ui.OverrideSFX(m_iPad,ACTION_MENU_A,true); + ui.OverrideSFX(m_iPad,ACTION_MENU_OK,true); +#ifdef __ORBIS__ + ui.OverrideSFX(m_iPad,ACTION_MENU_TOUCHPAD_PRESS,true); +#endif + ui.OverrideSFX(m_iPad,ACTION_MENU_LEFT_SCROLL,true); + ui.OverrideSFX(m_iPad,ACTION_MENU_RIGHT_SCROLL,true); + ui.OverrideSFX(m_iPad,ACTION_MENU_LEFT,true); + ui.OverrideSFX(m_iPad,ACTION_MENU_RIGHT,true); + ui.OverrideSFX(m_iPad,ACTION_MENU_UP,true); + ui.OverrideSFX(m_iPad,ACTION_MENU_DOWN,true); + + // 4J-PB - Must be after the CanBeMade list has been set up with CheckRecipesAvailable + UpdateTooltips(); + +#ifdef __PSVITA__ + // initialise vita touch controls with ids + for(unsigned int i = 0; i < ETouchInput_Count; ++i) + { + m_TouchInput[i].init(i); + } + ui.TouchBoxRebuild(this); +#endif +} + +void UIScene_CraftingMenu::handleDestroy() +{ + Minecraft *pMinecraft = Minecraft::GetInstance(); + + if( pMinecraft->localgameModes[m_iPad] != NULL ) + { + TutorialMode *gameMode = (TutorialMode *)pMinecraft->localgameModes[m_iPad]; + if(gameMode != NULL) gameMode->getTutorial()->changeTutorialState(m_previousTutorialState); + } + + // 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) + if(Minecraft::GetInstance()->localplayers[m_iPad] != NULL) Minecraft::GetInstance()->localplayers[m_iPad]->closeContainer(); + + ui.OverrideSFX(m_iPad,ACTION_MENU_A,false); + ui.OverrideSFX(m_iPad,ACTION_MENU_OK,false); +#ifdef __ORBIS__ + ui.OverrideSFX(m_iPad,ACTION_MENU_TOUCHPAD_PRESS,false); +#endif + ui.OverrideSFX(m_iPad,ACTION_MENU_LEFT_SCROLL,false); + ui.OverrideSFX(m_iPad,ACTION_MENU_RIGHT_SCROLL,false); + ui.OverrideSFX(m_iPad,ACTION_MENU_LEFT,false); + ui.OverrideSFX(m_iPad,ACTION_MENU_RIGHT,false); + ui.OverrideSFX(m_iPad,ACTION_MENU_UP,false); + ui.OverrideSFX(m_iPad,ACTION_MENU_DOWN,false); +} + +EUIScene UIScene_CraftingMenu::getSceneType() +{ + if(m_iContainerType==RECIPE_TYPE_3x3) + { + return eUIScene_Crafting3x3Menu; + } + else + { + return eUIScene_Crafting2x2Menu; + } +} + +wstring UIScene_CraftingMenu::getMoviePath() +{ + if(app.GetLocalPlayerCount() > 1) + { + m_bSplitscreen = true; + if(m_iContainerType==RECIPE_TYPE_3x3) + { + return L"Crafting3x3MenuSplit"; + } + else + { + return L"Crafting2x2MenuSplit"; + } + } + else + { + if(m_iContainerType==RECIPE_TYPE_3x3) + { + return L"Crafting3x3Menu"; + } + else + { + return L"Crafting2x2Menu"; + } + } +} + +#ifdef __PSVITA__ +UIControl* UIScene_CraftingMenu::GetMainPanel() +{ + return &m_controlMainPanel; +} + +void UIScene_CraftingMenu::handleTouchInput(unsigned int iPad, S32 x, S32 y, int iId, bool bPressed, bool bRepeat, bool bReleased) +{ + // perform action on release + if(bPressed) + { + if(iId == ETouchInput_CraftingHSlots) + { + m_iCraftingSlotTouchStartY = y; + } + } + else if(bRepeat) + { + if(iId == ETouchInput_CraftingHSlots) + { + if(y >= m_iCraftingSlotTouchStartY + m_TouchInput[ETouchInput_CraftingHSlots].getHeight()) // scroll list down + { + if(iVSlotIndexA[1]==(CanBeMadeA[m_iCurrentSlotHIndex].iCount-1)) + { + iVSlotIndexA[1]=0; + } + else + { + iVSlotIndexA[1]++; + } + ui.PlayUISFX(eSFX_Focus); + + UpdateVerticalSlots(); + UpdateHighlight(); + + m_iCraftingSlotTouchStartY = y; + } + else if(y <= m_iCraftingSlotTouchStartY - m_TouchInput[ETouchInput_CraftingHSlots].getHeight()) // scroll list up + { + if(iVSlotIndexA[1]==0) + { + iVSlotIndexA[1]=CanBeMadeA[m_iCurrentSlotHIndex].iCount-1; + } + else + { + iVSlotIndexA[1]--; + } + ui.PlayUISFX(eSFX_Focus); + + UpdateVerticalSlots(); + UpdateHighlight(); + + m_iCraftingSlotTouchStartY = y; + } + } + } + else if(bReleased) + { + if(iId >= ETouchInput_TouchPanel_0 && iId <= ETouchInput_TouchPanel_6) // Touch Change Group + { + m_iGroupIndex = iId; + // turn on the new group + showTabHighlight(m_iGroupIndex,true); + + m_iCurrentSlotHIndex=0; + m_iCurrentSlotVIndex=1; + CheckRecipesAvailable(); + // reset the vertical slots + iVSlotIndexA[0]=CanBeMadeA[m_iCurrentSlotHIndex].iCount-1; + iVSlotIndexA[1]=0; + iVSlotIndexA[2]=1; + ui.PlayUISFX(eSFX_Focus); + UpdateVerticalSlots(); + UpdateHighlight(); + setGroupText(GetGroupNameText(m_pGroupA[m_iGroupIndex])); + } + else if(iId == ETouchInput_CraftingHSlots) // Touch Change Slot + { + int iMaxHSlots = 0; + if(m_iContainerType==RECIPE_TYPE_3x3) + { + iMaxHSlots = m_iMaxHSlot3x3C; + } + else + { + iMaxHSlots = m_iMaxHSlot2x2C; + } + + int iNewSlot = (x - m_TouchInput[ETouchInput_CraftingHSlots].getXPos() - m_controlMainPanel.getXPos()) / m_TouchInput[ETouchInput_CraftingHSlots].getHeight(); + + int iOldHSlot=m_iCurrentSlotHIndex; + + m_iCurrentSlotHIndex = iNewSlot; + if(m_iCurrentSlotHIndex>=m_iCraftablesMaxHSlotC) m_iCurrentSlotHIndex=0; + m_iCurrentSlotVIndex=1; + // clear the indices + iVSlotIndexA[0]=CanBeMadeA[m_iCurrentSlotHIndex].iCount-1; + iVSlotIndexA[1]=0; + iVSlotIndexA[2]=1; + + UpdateVerticalSlots(); + UpdateHighlight(); + // re-enable the old hslot + if(CanBeMadeA[iOldHSlot].iCount>0) + { + setShowCraftHSlot(iOldHSlot,true); + } + ui.PlayUISFX(eSFX_Focus); + } + } +} + +void UIScene_CraftingMenu::handleTouchBoxRebuild() +{ + addTimer(GAME_CRAFTING_TOUCHUPDATE_TIMER_ID,GAME_CRAFTING_TOUCHUPDATE_TIMER_TIME); +} + +void UIScene_CraftingMenu::handleTimerComplete(int id) +{ + if(id == GAME_CRAFTING_TOUCHUPDATE_TIMER_ID) + { + // we cannot rebuild touch boxes in an iggy callback because it requires further iggy calls + GetMainPanel()->UpdateControl(); + ui.TouchBoxRebuild(this); + killTimer(GAME_CRAFTING_TOUCHUPDATE_TIMER_ID); + } +} +#endif + +void UIScene_CraftingMenu::handleReload() +{ + m_slotListInventory.addSlots(CRAFTING_INVENTORY_SLOT_START,CRAFTING_INVENTORY_SLOT_END - CRAFTING_INVENTORY_SLOT_START); + m_slotListHotBar.addSlots(CRAFTING_HOTBAR_SLOT_START, CRAFTING_HOTBAR_SLOT_END - CRAFTING_HOTBAR_SLOT_START); + + for(unsigned int i = 0; i < 4; ++i) + { + m_slotListIngredients[i].addSlot(CRAFTING_INGREDIENTS_DESCRIPTION_START + i); + } + m_slotListCraftingOutput.addSlot(CRAFTING_OUTPUT_SLOT_START); + m_slotListIngredientsLayout.addSlots(CRAFTING_INGREDIENTS_LAYOUT_START, m_iIngredientsMaxSlotC); + + // 3 Slot vertical scroll + m_slotListCrafting3VSlots[0].addSlot(CRAFTING_V_SLOT_START + 0); + m_slotListCrafting3VSlots[1].addSlot(CRAFTING_V_SLOT_START + 1); + m_slotListCrafting3VSlots[2].addSlot(CRAFTING_V_SLOT_START + 2); + + // 2 Slot vertical scroll + // 2 slot scroll has swapped order + m_slotListCrafting2VSlots[0].addSlot(CRAFTING_V_SLOT_START + 1); + m_slotListCrafting2VSlots[1].addSlot(CRAFTING_V_SLOT_START + 0); + + // 1 Slot scroll (for 480 mainly) + m_slotListCrafting1VSlots.addSlot(CRAFTING_V_SLOT_START); + + m_slotListCraftingHSlots.addSlots(CRAFTING_H_SLOT_START,m_iCraftablesMaxHSlotC); + + app.DebugPrintf(app.USER_SR,"Reloading MultiPanel\n"); + int temp = m_iDisplayDescription; + m_iDisplayDescription = m_iDisplayDescription==0?1:0; + UpdateMultiPanel(); + m_iDisplayDescription = temp; + UpdateMultiPanel(); + + app.DebugPrintf(app.USER_SR,"Reloading Highlight and scroll\n"); + + // reset the vertical slots + m_iCurrentSlotHIndex = 0; + m_iCurrentSlotVIndex = 1; + iVSlotIndexA[0]=CanBeMadeA[m_iCurrentSlotHIndex].iCount-1; + iVSlotIndexA[1]=0; + iVSlotIndexA[2]=1; + UpdateVerticalSlots(); + UpdateHighlight(); + + app.DebugPrintf(app.USER_SR,"Reloading tabs\n"); + showTabHighlight(0,false); + showTabHighlight(m_iGroupIndex,true); +} + +void UIScene_CraftingMenu::customDraw(IggyCustomDrawCallbackRegion *region) +{ + Minecraft *pMinecraft = Minecraft::GetInstance(); + if(pMinecraft->localplayers[m_iPad] == NULL || pMinecraft->localgameModes[m_iPad] == NULL) return; + + shared_ptr<ItemInstance> item = nullptr; + int slotId = -1; + float alpha = 1.0f; + bool decorations = true; + bool inventoryItem = false; + swscanf((wchar_t*)region->name,L"slot_%d",&slotId); + if (slotId == -1) + { + app.DebugPrintf("This is not the control we are looking for\n"); + } + else if(slotId >= CRAFTING_INVENTORY_SLOT_START && slotId < CRAFTING_INVENTORY_SLOT_END) + { + int iIndex = slotId - CRAFTING_INVENTORY_SLOT_START; + iIndex += m_iMenuInventoryStart; + Slot *slot = m_menu->getSlot(iIndex); + item = slot->getItem(); + inventoryItem = true; + } + else if(slotId >= CRAFTING_HOTBAR_SLOT_START && slotId < CRAFTING_HOTBAR_SLOT_END) + { + int iIndex = slotId - CRAFTING_HOTBAR_SLOT_START; + iIndex += m_iMenuHotBarStart; + Slot *slot = m_menu->getSlot(iIndex); + item = slot->getItem(); + inventoryItem = true; + } + else if(slotId >= CRAFTING_V_SLOT_START && slotId < CRAFTING_V_SLOT_END ) + { + decorations = false; + int iIndex = slotId - CRAFTING_V_SLOT_START; + if(m_vSlotsInfo[iIndex].show) + { + item = m_vSlotsInfo[iIndex].item; + alpha = ((float)m_vSlotsInfo[iIndex].alpha)/31.0f; + } + } + else if(slotId >= CRAFTING_H_SLOT_START && slotId < (CRAFTING_H_SLOT_START + m_iCraftablesMaxHSlotC) ) + { + decorations = false; + int iIndex = slotId - CRAFTING_H_SLOT_START; + if(m_hSlotsInfo[iIndex].show) + { + item = m_hSlotsInfo[iIndex].item; + alpha = ((float)m_hSlotsInfo[iIndex].alpha)/31.0f; + } + } + else if(slotId >= CRAFTING_INGREDIENTS_LAYOUT_START && slotId < (CRAFTING_INGREDIENTS_LAYOUT_START + m_iIngredientsMaxSlotC) ) + { + int iIndex = slotId - CRAFTING_INGREDIENTS_LAYOUT_START; + if(m_ingredientsSlotsInfo[iIndex].show) + { + item = m_ingredientsSlotsInfo[iIndex].item; + alpha = ((float)m_ingredientsSlotsInfo[iIndex].alpha)/31.0f; + } + } + else if(slotId >= CRAFTING_INGREDIENTS_DESCRIPTION_START && slotId < (CRAFTING_INGREDIENTS_DESCRIPTION_START + 4) ) + { + int iIndex = slotId - CRAFTING_INGREDIENTS_DESCRIPTION_START; + if(m_ingredientsInfo[iIndex].show) + { + item = m_ingredientsInfo[iIndex].item; + alpha = ((float)m_ingredientsInfo[iIndex].alpha)/31.0f; + } + } + else if(slotId == CRAFTING_OUTPUT_SLOT_START ) + { + if(m_craftingOutputSlotInfo.show) + { + item = m_craftingOutputSlotInfo.item; + alpha = ((float)m_craftingOutputSlotInfo.alpha)/31.0f; + } + } + + if(item != NULL) + { + if(!inventoryItem) + { + if( item->id == Item::clock_Id || item->id == Item::compass_Id ) + { + // 4J Stu - For clocks and compasses we set the aux value to a special one that signals we should use a default texture + // rather than the dynamic one for the player + item->setAuxValue(0xFF); + } + else if( (item->getAuxValue() & 0xFF) == 0xFF) + { + // 4J Stu - If the aux value is set to match any + item->setAuxValue(0); + } + } + customDrawSlotControl(region,m_iPad,item,alpha,item->isFoil(),decorations); + } +} + +int UIScene_CraftingMenu::getPad() +{ + return m_iPad; +} + +bool UIScene_CraftingMenu::allowRepeat(int key) +{ + switch(key) + { + // X is used to open this menu, so don't let it repeat + case ACTION_MENU_X: + return false; + } + return true; +} + +void UIScene_CraftingMenu::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled) +{ + //app.DebugPrintf("UIScene_InventoryMenu handling input for pad %d, key %d, down- %s, pressed- %s, released- %s\n", iPad, key, down?"TRUE":"FALSE", pressed?"TRUE":"FALSE", released?"TRUE":"FALSE"); + ui.AnimateKeyPress(m_iPad, key, repeat, pressed, released); + + switch(key) + { + case ACTION_MENU_OTHER_STICK_UP: + case ACTION_MENU_OTHER_STICK_DOWN: + sendInputToMovie(key,repeat,pressed,released); + break; + default: + if(pressed) + { + handled = handleKeyDown(m_iPad, key, repeat); + } + break; + }; +} + +void UIScene_CraftingMenu::hideAllHSlots() +{ + for(unsigned int iIndex = 0; iIndex < m_iMaxHSlotC; ++iIndex) + { + m_hSlotsInfo[iIndex].item = nullptr; + m_hSlotsInfo[iIndex].alpha = 31; + m_hSlotsInfo[iIndex].show = false; + } +} + +void UIScene_CraftingMenu::hideAllVSlots() +{ + for(unsigned int iIndex = 0; iIndex < m_iMaxDisplayedVSlotC; ++iIndex) + { + m_vSlotsInfo[iIndex].item = nullptr; + m_vSlotsInfo[iIndex].alpha = 31; + m_vSlotsInfo[iIndex].show = false; + } +} + +void UIScene_CraftingMenu::hideAllIngredientsSlots() +{ + for(int i=0;i<m_iIngredientsC;i++) + { + m_ingredientsInfo[i].item = nullptr; + m_ingredientsInfo[i].alpha = 31; + m_ingredientsInfo[i].show = false; + + m_labelIngredientsDesc[i].setLabel(L""); + + IggyDataValue result; + IggyDataValue value[2]; + + value[0].type = IGGY_DATATYPE_number; + value[0].number = i; + + value[1].type = IGGY_DATATYPE_boolean; + value[1].boolval = false; + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ) , m_funcShowIngredientSlot , 2 , value ); + } +} + +void UIScene_CraftingMenu::setCraftHSlotItem(int iPad, int iIndex, shared_ptr<ItemInstance> item, unsigned int uiAlpha) +{ + m_hSlotsInfo[iIndex].item = item; + m_hSlotsInfo[iIndex].alpha = uiAlpha; + m_hSlotsInfo[iIndex].show = true; +} + +void UIScene_CraftingMenu::setCraftVSlotItem(int iPad, int iIndex, shared_ptr<ItemInstance> item, unsigned int uiAlpha) +{ + m_vSlotsInfo[iIndex].item = item; + m_vSlotsInfo[iIndex].alpha = uiAlpha; + m_vSlotsInfo[iIndex].show = true; +} + +void UIScene_CraftingMenu::setCraftingOutputSlotItem(int iPad, shared_ptr<ItemInstance> item) +{ + m_craftingOutputSlotInfo.item = item; + m_craftingOutputSlotInfo.alpha = 31; + m_craftingOutputSlotInfo.show = item != NULL; +} + +void UIScene_CraftingMenu::setCraftingOutputSlotRedBox(bool show) +{ + m_slotListCraftingOutput.showSlotRedBox(0,show); +} + +void UIScene_CraftingMenu::setIngredientSlotItem(int iPad, int index, shared_ptr<ItemInstance> item) +{ + m_ingredientsSlotsInfo[index].item = item; + m_ingredientsSlotsInfo[index].alpha = 31; + m_ingredientsSlotsInfo[index].show = item != NULL; +} + +void UIScene_CraftingMenu::setIngredientSlotRedBox(int index, bool show) +{ + m_slotListIngredientsLayout.showSlotRedBox(index,show); +} + +void UIScene_CraftingMenu::setIngredientDescriptionItem(int iPad, int index, shared_ptr<ItemInstance> item) +{ + m_ingredientsInfo[index].item = item; + m_ingredientsInfo[index].alpha = 31; + m_ingredientsInfo[index].show = item != NULL; + + IggyDataValue result; + IggyDataValue value[2]; + + value[0].type = IGGY_DATATYPE_number; + value[0].number = index; + + value[1].type = IGGY_DATATYPE_boolean; + value[1].boolval = m_ingredientsInfo[index].show; + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ) , m_funcShowIngredientSlot , 2 , value ); +} + +void UIScene_CraftingMenu::setIngredientDescriptionRedBox(int index, bool show) +{ + m_slotListIngredients[index].showSlotRedBox(0,show); +} + +void UIScene_CraftingMenu::setIngredientDescriptionText(int index, LPCWSTR text) +{ + m_labelIngredientsDesc[index].setLabel(text); +} + + +void UIScene_CraftingMenu::setShowCraftHSlot(int iIndex, bool show) +{ + m_hSlotsInfo[iIndex].show = show; +} + +void UIScene_CraftingMenu::showTabHighlight(int iIndex, bool show) +{ + if(show) + { + IggyDataValue result; + IggyDataValue value[1]; + + value[0].type = IGGY_DATATYPE_number; + value[0].number = iIndex; + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ) , m_funcSetActiveTab , 1 , value ); + } +} + +void UIScene_CraftingMenu::setGroupText(LPCWSTR text) +{ + m_labelGroupName.setLabel(text); +} + +void UIScene_CraftingMenu::setDescriptionText(LPCWSTR text) +{ + m_labelDescription.setLabel(text); +} + +void UIScene_CraftingMenu::setItemText(LPCWSTR text) +{ + m_labelItemName.setLabel(text); +} + +void UIScene_CraftingMenu::UpdateMultiPanel() +{ + // Call Iggy function to show the current panel + IggyDataValue result; + IggyDataValue value[1]; + + value[0].type = IGGY_DATATYPE_number; + value[0].number = m_iDisplayDescription; + + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ) , m_funcShowPanelDisplay , 1 , value ); +} + +void UIScene_CraftingMenu::scrollDescriptionUp() +{ + // handled differently +} + +void UIScene_CraftingMenu::scrollDescriptionDown() +{ + // handled differently +} + +void UIScene_CraftingMenu::updateHighlightAndScrollPositions() +{ + { + IggyDataValue result; + IggyDataValue value[2]; + + value[0].type = IGGY_DATATYPE_number; + value[0].number = m_iCurrentSlotHIndex; + + int selectorType = 0; + if(CanBeMadeA[m_iCurrentSlotHIndex].iCount == 2) + { + selectorType = 1; + } + else if( CanBeMadeA[m_iCurrentSlotHIndex].iCount > 2) + { + selectorType = 2; + } + + value[1].type = IGGY_DATATYPE_number; + value[1].number = selectorType; + + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ) , m_funcMoveSelector , 2 , value ); + } + + { + IggyDataValue result; + IggyDataValue value[1]; + + value[0].type = IGGY_DATATYPE_number; + value[0].number = m_iCurrentSlotVIndex; + + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ) , m_funcSelectVerticalItem , 1 , value ); + } +} + +void UIScene_CraftingMenu::updateVSlotPositions(int iSlots, int i) +{ + // Not needed +} diff --git a/Minecraft.Client/Common/UI/UIScene_CraftingMenu.h b/Minecraft.Client/Common/UI/UIScene_CraftingMenu.h new file mode 100644 index 00000000..44a39d61 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_CraftingMenu.h @@ -0,0 +1,205 @@ +#pragma once + +#include "UIScene.h" +#include "UIControl_SlotList.h" +#include "UIControl_Label.h" +#include "IUIScene_CraftingMenu.h" + +#define CRAFTING_INVENTORY_SLOT_START 0 +#define CRAFTING_INVENTORY_SLOT_END (CRAFTING_INVENTORY_SLOT_START + 27) + +#define CRAFTING_HOTBAR_SLOT_START CRAFTING_INVENTORY_SLOT_END +#define CRAFTING_HOTBAR_SLOT_END (CRAFTING_HOTBAR_SLOT_START + 9) + +// Ingredients etc should go here +#define CRAFTING_INGREDIENTS_DESCRIPTION_START CRAFTING_HOTBAR_SLOT_END +#define CRAFTING_INGREDEINTS_DESCRIPTION_END (CRAFTING_INGREDIENTS_DESCRIPTION_START + 4) + +#define CRAFTING_OUTPUT_SLOT_START CRAFTING_INGREDEINTS_DESCRIPTION_END +#define CRAFTING_OUTPUT_SLOT_END (CRAFTING_OUTPUT_SLOT_START + 1) + +#define CRAFTING_INGREDIENTS_LAYOUT_START CRAFTING_OUTPUT_SLOT_END +#define CRAFTING_INGREDIENTS_LAYOUT_END (CRAFTING_INGREDIENTS_LAYOUT_START+9) + +#define CRAFTING_V_SLOT_START CRAFTING_INGREDIENTS_LAYOUT_END +#define CRAFTING_V_SLOT_END (CRAFTING_V_SLOT_START+3) + +// H slots should go last in the count as it's dependent on which size of crafting panel we have +#define CRAFTING_H_SLOT_START CRAFTING_V_SLOT_END + +class UIScene_CraftingMenu : public UIScene, public IUIScene_CraftingMenu +{ +private: + typedef struct _SlotInfo + { + shared_ptr<ItemInstance> item; + unsigned int alpha; + bool show; + + _SlotInfo() + { + item = nullptr; + alpha = 31; + show = true; + } + } SlotInfo; + + SlotInfo m_hSlotsInfo[m_iMaxHSlotC]; + SlotInfo m_vSlotsInfo[m_iMaxDisplayedVSlotC]; + SlotInfo m_ingredientsSlotsInfo[m_iIngredients3x3SlotC]; + SlotInfo m_craftingOutputSlotInfo; + SlotInfo m_ingredientsInfo[4]; + + AbstractContainerMenu *m_menu; + + int m_iMenuInventoryStart; + int m_iMenuHotBarStart; + +public: + UIScene_CraftingMenu(int iPad, void *initData, UILayer *parentLayer); + + virtual void handleDestroy(); + + virtual EUIScene getSceneType(); + + virtual void customDraw(IggyCustomDrawCallbackRegion *region); + +#ifdef __PSVITA__ + virtual void handleTouchInput(unsigned int iPad, S32 x, S32 y, int iId, bool bPressed, bool bRepeat, bool bReleased); + virtual UIControl* GetMainPanel(); + virtual void handleTouchBoxRebuild(); + virtual void handleTimerComplete(int id); +#endif + +protected: + UIControl m_controlMainPanel; + UIControl m_control1Selector, m_control2Selector, m_control3Selector; + UIControl_SlotList m_slotListCraftingHSlots; + UIControl_SlotList m_slotListCrafting1VSlots, m_slotListCrafting2VSlots[2], m_slotListCrafting3VSlots[3]; + UIControl_SlotList m_slotListIngredientsLayout, m_slotListCraftingOutput; + UIControl_SlotList m_slotListIngredients[4]; + UIControl_SlotList m_slotListInventory, m_slotListHotBar; + UIControl_Label m_labelIngredientsDesc[4]; + UIControl_HTMLLabel m_labelDescription; + UIControl_Label m_labelGroupName, m_labelItemName, m_labelInventory, m_labelIngredients; + + IggyName m_funcMoveSelector, m_funcSelectVerticalItem, m_funcSetActiveTab; + IggyName m_funcShowPanelDisplay, m_funcShowIngredientSlot; + +#ifdef __PSVITA__ + enum ETouchInput + { + ETouchInput_TouchPanel_0, + ETouchInput_TouchPanel_1, + ETouchInput_TouchPanel_2, + ETouchInput_TouchPanel_3, + ETouchInput_TouchPanel_4, + ETouchInput_TouchPanel_5, + ETouchInput_TouchPanel_6, + ETouchInput_CraftingHSlots, + + ETouchInput_Count, + }; + UIControl_Touch m_TouchInput[ETouchInput_Count]; + S32 m_iCraftingSlotTouchStartY; +#endif + + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) + UI_MAP_ELEMENT( m_controlMainPanel, "MainPanel" ) + UI_BEGIN_MAP_CHILD_ELEMENTS( m_controlMainPanel ) + UI_MAP_ELEMENT( m_slotListCraftingHSlots, "CraftingHSlots") + + UI_MAP_ELEMENT( m_control3Selector, "SlotSelector3" ) + UI_BEGIN_MAP_CHILD_ELEMENTS( m_control3Selector) + UI_MAP_ELEMENT( m_slotListCrafting3VSlots[0], "Crafting3VSlot1") + UI_MAP_ELEMENT( m_slotListCrafting3VSlots[1], "Crafting3VSlot2") + UI_MAP_ELEMENT( m_slotListCrafting3VSlots[2], "Crafting3VSlot3") + UI_END_MAP_CHILD_ELEMENTS() + + UI_MAP_ELEMENT( m_control2Selector, "SlotSelector2" ) + UI_BEGIN_MAP_CHILD_ELEMENTS( m_control2Selector) + UI_MAP_ELEMENT( m_slotListCrafting2VSlots[0], "Crafting2VSlot1") + UI_MAP_ELEMENT( m_slotListCrafting2VSlots[1], "Crafting2VSlot2") + UI_END_MAP_CHILD_ELEMENTS() + + UI_MAP_ELEMENT( m_control1Selector, "CraftingSelector" ) + UI_BEGIN_MAP_CHILD_ELEMENTS( m_control1Selector) + UI_MAP_ELEMENT( m_slotListCrafting1VSlots, "Crafting1VSlot1") + UI_END_MAP_CHILD_ELEMENTS() + + UI_MAP_ELEMENT( m_slotListIngredientsLayout, "IngredientsLayout") + UI_MAP_ELEMENT( m_slotListCraftingOutput, "CraftingOutput") + + UI_MAP_ELEMENT( m_slotListIngredients[0], "Ingredient1") + UI_MAP_ELEMENT( m_slotListIngredients[1], "Ingredient2") + UI_MAP_ELEMENT( m_slotListIngredients[2], "Ingredient3") + UI_MAP_ELEMENT( m_slotListIngredients[3], "Ingredient4") + + UI_MAP_ELEMENT( m_labelIngredientsDesc[0], "Ingredient1Desc") + UI_MAP_ELEMENT( m_labelIngredientsDesc[1], "Ingredient2Desc") + UI_MAP_ELEMENT( m_labelIngredientsDesc[2], "Ingredient3Desc") + UI_MAP_ELEMENT( m_labelIngredientsDesc[3], "Ingredient4Desc") + + UI_MAP_ELEMENT( m_labelIngredients, "IngredientsLabel") + + UI_MAP_ELEMENT( m_labelDescription, "DescriptionText") + + UI_MAP_ELEMENT( m_slotListInventory, "Inventory") + UI_MAP_ELEMENT( m_slotListHotBar, "HotBar") + + UI_MAP_ELEMENT( m_labelGroupName, "GroupName") + UI_MAP_ELEMENT( m_labelItemName, "ItemName") + UI_MAP_ELEMENT( m_labelInventory, "InventoryLabel") + + UI_MAP_NAME( m_funcMoveSelector, L"MoveSelector") + UI_MAP_NAME( m_funcSelectVerticalItem, L"SelectVerticalItem") + UI_MAP_NAME( m_funcSetActiveTab, L"SetActiveTab") + UI_MAP_NAME( m_funcShowPanelDisplay, L"showPanelDisplay") + UI_MAP_NAME( m_funcShowIngredientSlot, L"ShowIngredient") + +#ifdef __PSVITA__ + UI_MAP_ELEMENT( m_TouchInput[ETouchInput_TouchPanel_0], "TouchPanel_0" ) + UI_MAP_ELEMENT( m_TouchInput[ETouchInput_TouchPanel_1], "TouchPanel_1" ) + UI_MAP_ELEMENT( m_TouchInput[ETouchInput_TouchPanel_2], "TouchPanel_2" ) + UI_MAP_ELEMENT( m_TouchInput[ETouchInput_TouchPanel_3], "TouchPanel_3" ) + UI_MAP_ELEMENT( m_TouchInput[ETouchInput_TouchPanel_4], "TouchPanel_4" ) + UI_MAP_ELEMENT( m_TouchInput[ETouchInput_TouchPanel_5], "TouchPanel_5" ) + UI_MAP_ELEMENT( m_TouchInput[ETouchInput_TouchPanel_6], "TouchPanel_6" ) + UI_MAP_ELEMENT( m_TouchInput[ETouchInput_CraftingHSlots], "TouchPanel_CraftingHSlots" ) +#endif + + UI_END_MAP_CHILD_ELEMENTS() + UI_END_MAP_ELEMENTS_AND_NAMES() + + virtual wstring getMoviePath(); + virtual void handleReload(); + + virtual bool allowRepeat(int key); + void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled); + +protected: + virtual int getPad(); + virtual void hideAllHSlots(); + virtual void hideAllVSlots(); + virtual void hideAllIngredientsSlots(); + virtual void setCraftHSlotItem(int iPad, int iIndex, shared_ptr<ItemInstance> item, unsigned int uiAlpha); + virtual void setCraftVSlotItem(int iPad, int iIndex, shared_ptr<ItemInstance> item, unsigned int uiAlpha); + virtual void setCraftingOutputSlotItem(int iPad, shared_ptr<ItemInstance> item); + virtual void setCraftingOutputSlotRedBox(bool show); + virtual void setIngredientSlotItem(int iPad, int index, shared_ptr<ItemInstance> item); + virtual void setIngredientSlotRedBox(int index, bool show); + virtual void setIngredientDescriptionItem(int iPad, int index, shared_ptr<ItemInstance> item); + virtual void setIngredientDescriptionRedBox(int index, bool show); + virtual void setIngredientDescriptionText(int index, LPCWSTR text); + virtual void setShowCraftHSlot(int iIndex, bool show); + virtual void showTabHighlight(int iIndex, bool show); + virtual void setGroupText(LPCWSTR text); + virtual void setDescriptionText(LPCWSTR text); + virtual void setItemText(LPCWSTR text); + virtual void scrollDescriptionUp(); + virtual void scrollDescriptionDown(); + virtual void updateHighlightAndScrollPositions(); + virtual void updateVSlotPositions(int iSlots, int i); + + virtual void UpdateMultiPanel(); +}; diff --git a/Minecraft.Client/Common/UI/UIScene_CreateWorldMenu.cpp b/Minecraft.Client/Common/UI/UIScene_CreateWorldMenu.cpp new file mode 100644 index 00000000..fa41909d --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_CreateWorldMenu.cpp @@ -0,0 +1,1457 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIScene_CreateWorldMenu.h" +#include "..\..\MinecraftServer.h" +#include "..\..\Minecraft.h" +#include "..\..\Options.h" +#include "..\..\TexturePackRepository.h" +#include "..\..\TexturePack.h" +#include "..\..\..\Minecraft.World\LevelSettings.h" +#include "..\..\..\Minecraft.World\StringHelpers.h" +#include "..\..\..\Minecraft.World\BiomeSource.h" +#include "..\..\..\Minecraft.World\IntCache.h" +#include "..\..\..\Minecraft.World\LevelType.h" +#include "..\..\DLCTexturePack.h" + +#ifdef __PSVITA__ +#include "PSVita\Network\SQRNetworkManager_AdHoc_Vita.h" +#endif + +#ifdef _WINDOWS64 + +#include <windows.h> +#include "Xbox\Resource.h" +#endif + +#define GAME_CREATE_ONLINE_TIMER_ID 0 +#define GAME_CREATE_ONLINE_TIMER_TIME 100 + +int UIScene_CreateWorldMenu::m_iDifficultyTitleSettingA[4]= +{ + IDS_DIFFICULTY_TITLE_PEACEFUL, + IDS_DIFFICULTY_TITLE_EASY, + IDS_DIFFICULTY_TITLE_NORMAL, + IDS_DIFFICULTY_TITLE_HARD +}; + +UIScene_CreateWorldMenu::UIScene_CreateWorldMenu(int iPad, void *initData, UILayer *parentLayer) : IUIScene_StartGame(iPad, parentLayer) +{ + // Setup all the Iggy references we need for this scene + initialiseMovie(); + + m_worldName = app.GetString(IDS_DEFAULT_WORLD_NAME); + m_seed = L""; + + m_iPad=iPad; + + m_labelWorldName.init(app.GetString(IDS_WORLD_NAME)); + m_labelSeed.init(app.GetString(IDS_CREATE_NEW_WORLD_SEED)); + m_labelRandomSeed.init(app.GetString(IDS_CREATE_NEW_WORLD_RANDOM_SEED)); + + m_editWorldName.init(m_worldName, eControl_EditWorldName); + m_editSeed.init(L"", eControl_EditSeed); + + m_buttonGamemode.init(app.GetString(IDS_GAMEMODE_SURVIVAL),eControl_GameModeToggle); + m_buttonMoreOptions.init(app.GetString(IDS_MORE_OPTIONS),eControl_MoreOptions); + m_buttonCreateWorld.init(app.GetString(IDS_CREATE_NEW_WORLD),eControl_NewWorld); + + m_texturePackList.init(app.GetString(IDS_DLC_MENU_TEXTUREPACKS), eControl_TexturePackList); + + m_labelTexturePackName.init(L""); + m_labelTexturePackDescription.init(L""); + + WCHAR TempString[256]; + swprintf( (WCHAR *)TempString, 256, L"%ls: %ls", app.GetString( IDS_SLIDER_DIFFICULTY ),app.GetString(m_iDifficultyTitleSettingA[app.GetGameSettings(m_iPad,eGameSetting_Difficulty)])); + m_sliderDifficulty.init(TempString,eControl_Difficulty,0,3,app.GetGameSettings(m_iPad,eGameSetting_Difficulty)); + + m_MoreOptionsParams.bGenerateOptions=TRUE; + m_MoreOptionsParams.bStructures=TRUE; + m_MoreOptionsParams.bFlatWorld=FALSE; + m_MoreOptionsParams.bBonusChest=FALSE; + m_MoreOptionsParams.bPVP = TRUE; + m_MoreOptionsParams.bTrust = TRUE; + m_MoreOptionsParams.bFireSpreads = TRUE; + m_MoreOptionsParams.bHostPrivileges = FALSE; + m_MoreOptionsParams.bTNT = TRUE; + m_MoreOptionsParams.iPad = iPad; + + m_bGameModeSurvival=true; + m_pDLCPack = NULL; + m_bRebuildTouchBoxes = false; + + m_bMultiplayerAllowed = ProfileManager.IsSignedInLive( m_iPad ) && ProfileManager.AllowedToPlayMultiplayer(m_iPad); + // 4J-PB - read the settings for the online flag. We'll only save this setting if the user changed it. + bool bGameSetting_Online=(app.GetGameSettings(m_iPad,eGameSetting_Online)!=0); + m_MoreOptionsParams.bOnlineSettingChangedBySystem=false; + + // 4J-PB - Removing this so that we can attempt to create an online game on PS3 when we are a restricted child account + // It'll fail when we choose create, but this matches the behaviour of load game, and lets the player know why they can't play online, + // instead of just greying out the online setting in the More Options + // #ifdef __PS3__ + // if(ProfileManager.IsSignedInLive( m_iPad )) + // { + // ProfileManager.GetChatAndContentRestrictions(m_iPad,true,&bChatRestricted,&bContentRestricted,NULL); + // } + // #endif + + // Set the text for friends of friends, and default to on + if( m_bMultiplayerAllowed ) + { + m_MoreOptionsParams.bOnlineGame = bGameSetting_Online?TRUE:FALSE; + if(bGameSetting_Online) + { + m_MoreOptionsParams.bInviteOnly = (app.GetGameSettings(m_iPad,eGameSetting_InviteOnly)!=0)?TRUE:FALSE; + m_MoreOptionsParams.bAllowFriendsOfFriends = (app.GetGameSettings(m_iPad,eGameSetting_FriendsOfFriends)!=0)?TRUE:FALSE; + } + else + { + m_MoreOptionsParams.bInviteOnly = FALSE; + m_MoreOptionsParams.bAllowFriendsOfFriends = FALSE; + } + } + else + { + m_MoreOptionsParams.bOnlineGame = FALSE; + m_MoreOptionsParams.bInviteOnly = FALSE; + m_MoreOptionsParams.bAllowFriendsOfFriends = FALSE; + if(bGameSetting_Online) + { + // The profile settings say Online, but either the player is offline, or they are not allowed to play online + m_MoreOptionsParams.bOnlineSettingChangedBySystem=true; + } + } + +#if defined _XBOX_ONE || defined __ORBIS__ || defined _WINDOWS64 + if(getSceneResolution() == eSceneResolution_1080) + { + // Set up online game checkbox + bool bOnlineGame = m_MoreOptionsParams.bOnlineGame; + m_checkboxOnline.SetEnable(true); + + // 4J-PB - to stop an offline game being able to select the online flag + if(ProfileManager.IsSignedInLive(m_iPad) == false) + { + m_checkboxOnline.SetEnable(false); + } + + if(m_MoreOptionsParams.bOnlineSettingChangedBySystem) + { + m_checkboxOnline.SetEnable(false); + bOnlineGame = false; + } + + m_checkboxOnline.init(app.GetString(IDS_ONLINE_GAME), eControl_OnlineGame, bOnlineGame); + } +#endif + + addTimer( GAME_CREATE_ONLINE_TIMER_ID,GAME_CREATE_ONLINE_TIMER_TIME ); +#if TO_BE_IMPLEMENTED + XuiSetTimer(m_hObj,CHECKFORAVAILABLETEXTUREPACKS_TIMER_ID,CHECKFORAVAILABLETEXTUREPACKS_TIMER_TIME); +#endif + + TelemetryManager->RecordMenuShown(m_iPad, eUIScene_CreateWorldMenu, 0); + + // block input if we're waiting for DLC to install, and wipe the saves list. The end of dlc mounting custom message will fill the list again + if(app.StartInstallDLCProcess(m_iPad)==true) + { + // not doing a mount, so enable input + m_bIgnoreInput=true; + } + else + { + m_bIgnoreInput = false; + + Minecraft *pMinecraft = Minecraft::GetInstance(); + int texturePacksCount = pMinecraft->skins->getTexturePackCount(); + for(unsigned int i = 0; i < texturePacksCount; ++i) + { + TexturePack *tp = pMinecraft->skins->getTexturePackByIndex(i); + + DWORD dwImageBytes; + PBYTE pbImageData = tp->getPackIcon(dwImageBytes); + + if(dwImageBytes > 0 && pbImageData) + { + wchar_t imageName[64]; + swprintf(imageName,64,L"tpack%08x",tp->getId()); + registerSubstitutionTexture(imageName, pbImageData, dwImageBytes); + m_texturePackList.addPack(i,imageName); + } + } + +#if TO_BE_IMPLEMENTED + // 4J-PB - there may be texture packs we don't have, so use the info from TMS for this + + DLC_INFO *pDLCInfo=NULL; + + // first pass - look to see if there are any that are not in the list + bool bTexturePackAlreadyListed; + bool bNeedToGetTPD=false; + + for(unsigned int i = 0; i < app.GetDLCInfoTexturesOffersCount(); ++i) + { + bTexturePackAlreadyListed=false; + ULONGLONG ull=app.GetDLCInfoTexturesFullOffer(i); + pDLCInfo=app.GetDLCInfoForFullOfferID(ull); + for(unsigned int i = 0; i < texturePacksCount; ++i) + { + TexturePack *tp = pMinecraft->skins->getTexturePackByIndex(i); + if(pDLCInfo->iConfig==tp->getDLCParentPackId()) + { + bTexturePackAlreadyListed=true; + } + } + if(bTexturePackAlreadyListed==false) + { + // some missing + bNeedToGetTPD=true; + + m_iTexturePacksNotInstalled++; + } + } + + if(bNeedToGetTPD==true) + { + // add a TMS request for them + app.DebugPrintf("+++ Adding TMSPP request for texture pack data\n"); + app.AddTMSPPFileTypeRequest(e_DLC_TexturePackData); + m_iConfigA= new int [m_iTexturePacksNotInstalled]; + m_iTexturePacksNotInstalled=0; + + for(unsigned int i = 0; i < app.GetDLCInfoTexturesOffersCount(); ++i) + { + bTexturePackAlreadyListed=false; + ULONGLONG ull=app.GetDLCInfoTexturesFullOffer(i); + pDLCInfo=app.GetDLCInfoForFullOfferID(ull); + for(unsigned int i = 0; i < texturePacksCount; ++i) + { + TexturePack *tp = pMinecraft->skins->getTexturePackByIndex(i); + if(pDLCInfo->iConfig==tp->getDLCParentPackId()) + { + bTexturePackAlreadyListed=true; + } + } + if(bTexturePackAlreadyListed==false) + { + m_iConfigA[m_iTexturePacksNotInstalled++]=pDLCInfo->iConfig; + } + } + } +#endif + + UpdateTexturePackDescription(m_currentTexturePackIndex); + + + m_texturePackList.selectSlot(m_currentTexturePackIndex); + } +} + +UIScene_CreateWorldMenu::~UIScene_CreateWorldMenu() +{ +} + +void UIScene_CreateWorldMenu::updateTooltips() +{ + ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK); +} + +void UIScene_CreateWorldMenu::updateComponents() +{ + m_parentLayer->showComponent(m_iPad,eUIComponent_Panorama,true); + m_parentLayer->showComponent(m_iPad,eUIComponent_Logo,false); +} + +wstring UIScene_CreateWorldMenu::getMoviePath() +{ + return L"CreateWorldMenu"; +} + +UIControl* UIScene_CreateWorldMenu::GetMainPanel() +{ + return &m_controlMainPanel; +} + +void UIScene_CreateWorldMenu::handleDestroy() +{ +#ifdef __PSVITA__ + app.DebugPrintf("missing InputManager.DestroyKeyboard on Vita !!!!!!\n"); +#endif + + // shut down the keyboard if it is displayed +#if ( defined __PS3__ || defined __ORBIS__ || defined _DURANGO) + InputManager.DestroyKeyboard(); +#endif +} + +void UIScene_CreateWorldMenu::tick() +{ + UIScene::tick(); + + if(m_iSetTexturePackDescription >= 0 ) + { + UpdateTexturePackDescription( m_iSetTexturePackDescription ); + m_iSetTexturePackDescription = -1; + } + if(m_bShowTexturePackDescription) + { + slideLeft(); + m_texturePackDescDisplayed = true; + + m_bShowTexturePackDescription = false; + } + +#ifdef __ORBIS__ + // check the status of the PSPlus common dialog + switch (sceNpCommerceDialogUpdateStatus()) + { + case SCE_COMMON_DIALOG_STATUS_FINISHED: + { + SceNpCommerceDialogResult Result; + sceNpCommerceDialogGetResult(&Result); + sceNpCommerceDialogTerminate(); + + if(Result.authorized) + { + ProfileManager.PsPlusUpdate(ProfileManager.GetPrimaryPad(), &Result); + // they just became a PSPlus member + checkStateAndStartGame(); + } + else + { + // continue offline? + UINT uiIDA[1]; + uiIDA[0]=IDS_PRO_NOTONLINE_DECLINE; + + // Give the player a warning about the texture pack missing + ui.RequestMessageBox(IDS_PLAY_OFFLINE,IDS_NO_PLAYSTATIONPLUS, uiIDA, 1, ProfileManager.GetPrimaryPad(),&UIScene_CreateWorldMenu::ContinueOffline,dynamic_cast<UIScene_CreateWorldMenu*>(this),app.GetStringTable(), 0, 0, false); + } + } + break; + default: + break; + } +#endif +} + +#ifdef __ORBIS__ +int UIScene_CreateWorldMenu::ContinueOffline(void *pParam,int iPad,C4JStorage::EMessageResult result) +{ + UIScene_CreateWorldMenu* pClass = (UIScene_CreateWorldMenu*)pParam; + + // results switched for this dialog + if(result==C4JStorage::EMessage_ResultAccept) + { + pClass->m_MoreOptionsParams.bOnlineGame=false; + pClass->checkStateAndStartGame(); + } + return 0; +} + +#endif + +void UIScene_CreateWorldMenu::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled) +{ + if(m_bIgnoreInput) return; + + ui.AnimateKeyPress(m_iPad, key, repeat, pressed, released); + + switch(key) + { + case ACTION_MENU_CANCEL: + if(pressed) + { + navigateBack(); + handled = true; + } + break; + case ACTION_MENU_OK: +#ifdef __ORBIS__ + case ACTION_MENU_TOUCHPAD_PRESS: +#endif + + // 4J-JEV: Inform user why their game must be offline. +#if defined _XBOX_ONE + if ( pressed && controlHasFocus(m_checkboxOnline.getId()) && !m_checkboxOnline.IsEnabled() ) + { + UINT uiIDA[1] = { IDS_CONFIRM_OK }; + ui.RequestMessageBox(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_XBOXLIVE_NOTIFICATION, uiIDA, 1, iPad, NULL, NULL, app.GetStringTable()); + } +#endif + + case ACTION_MENU_UP: + case ACTION_MENU_DOWN: + case ACTION_MENU_LEFT: + case ACTION_MENU_RIGHT: + case ACTION_MENU_OTHER_STICK_UP: + case ACTION_MENU_OTHER_STICK_DOWN: + sendInputToMovie(key, repeat, pressed, released); + +#if defined _XBOX_ONE || defined __ORBIS__ || defined _WINDOWS64 + if(getSceneResolution() == eSceneResolution_1080) + { + bool bOnlineGame = m_checkboxOnline.IsChecked(); + if (m_MoreOptionsParams.bOnlineGame != bOnlineGame) + { + m_MoreOptionsParams.bOnlineGame = bOnlineGame; + + if (!m_MoreOptionsParams.bOnlineGame) + { + m_MoreOptionsParams.bInviteOnly = false; + m_MoreOptionsParams.bAllowFriendsOfFriends = false; + } + } + } +#endif + + handled = true; + break; + } +} + +void UIScene_CreateWorldMenu::handlePress(F64 controlId, F64 childId) +{ + if(m_bIgnoreInput) return; + + //CD - Added for audio + ui.PlayUISFX(eSFX_Press); + + switch((int)controlId) + { + case eControl_EditWorldName: + { + m_bIgnoreInput=true; + InputManager.RequestKeyboard(app.GetString(IDS_CREATE_NEW_WORLD),m_editWorldName.getLabel(),(DWORD)0,25,&UIScene_CreateWorldMenu::KeyboardCompleteWorldNameCallback,this,C_4JInput::EKeyboardMode_Default); + } + break; + case eControl_EditSeed: + { + m_bIgnoreInput=true; +#ifdef __PS3__ + int language = XGetLanguage(); + switch(language) + { + case XC_LANGUAGE_JAPANESE: + case XC_LANGUAGE_KOREAN: + case XC_LANGUAGE_TCHINESE: + InputManager.RequestKeyboard(app.GetString(IDS_CREATE_NEW_WORLD_SEED),m_editSeed.getLabel(),(DWORD)0,60,&UIScene_CreateWorldMenu::KeyboardCompleteSeedCallback,this,C_4JInput::EKeyboardMode_Default); + break; + default: + // 4J Stu - Use a different keyboard for non-asian languages so we don't have prediction on + InputManager.RequestKeyboard(app.GetString(IDS_CREATE_NEW_WORLD_SEED),m_editSeed.getLabel(),(DWORD)0,60,&UIScene_CreateWorldMenu::KeyboardCompleteSeedCallback,this,C_4JInput::EKeyboardMode_Alphabet_Extended); + break; + } +#else + InputManager.RequestKeyboard(app.GetString(IDS_CREATE_NEW_WORLD_SEED),m_editSeed.getLabel(),(DWORD)0,60,&UIScene_CreateWorldMenu::KeyboardCompleteSeedCallback,this,C_4JInput::EKeyboardMode_Default); +#endif + } + break; + case eControl_GameModeToggle: + if(m_bGameModeSurvival) + { + m_buttonGamemode.setLabel(app.GetString(IDS_GAMEMODE_CREATIVE)); + m_bGameModeSurvival=false; + } + else + { + m_buttonGamemode.setLabel(app.GetString(IDS_GAMEMODE_SURVIVAL)); + m_bGameModeSurvival=true; + } + break; + case eControl_MoreOptions: + ui.NavigateToScene(m_iPad, eUIScene_LaunchMoreOptionsMenu, &m_MoreOptionsParams); + break; + case eControl_TexturePackList: + { + UpdateCurrentTexturePack((int)childId); + } + break; + case eControl_NewWorld: + { +#ifdef _DURANGO + if(m_MoreOptionsParams.bOnlineGame) + { + m_bIgnoreInput = true; + ProfileManager.CheckMultiplayerPrivileges(m_iPad, true, &checkPrivilegeCallback, this); + } + else +#endif + { + StartSharedLaunchFlow(); + } + break; + } + } +} + +#ifdef _DURANGO +void UIScene_CreateWorldMenu::checkPrivilegeCallback(LPVOID lpParam, bool hasPrivilege, int iPad) +{ + UIScene_CreateWorldMenu* pClass = (UIScene_CreateWorldMenu*)lpParam; + + if(hasPrivilege) + { + pClass->StartSharedLaunchFlow(); + } + else + { + pClass->m_bIgnoreInput = false; + } +} +#endif + +void UIScene_CreateWorldMenu::StartSharedLaunchFlow() +{ + Minecraft *pMinecraft=Minecraft::GetInstance(); + // Check if we need to upsell the texture pack + if(m_MoreOptionsParams.dwTexturePack!=0) + { + // texture pack hasn't been set yet, so check what it will be + TexturePack *pTexturePack = pMinecraft->skins->getTexturePackById(m_MoreOptionsParams.dwTexturePack); + + if(pTexturePack==NULL) + { +#if TO_BE_IMPLEMENTED + // They've selected a texture pack they don't have yet + // upsell + CXuiCtrl4JList::LIST_ITEM_INFO ListItem; + // get the current index of the list, and then get the data + ListItem=m_pTexturePacksList->GetData(m_currentTexturePackIndex); + + + // upsell the texture pack + // tell sentient about the upsell of the full version of the skin pack + ULONGLONG ullOfferID_Full; + app.GetDLCFullOfferIDForPackID(m_MoreOptionsParams.dwTexturePack,&ullOfferID_Full); + + TelemetryManager->RecordUpsellPresented(ProfileManager.GetPrimaryPad(), eSet_UpsellID_Texture_DLC, ullOfferID_Full & 0xFFFFFFFF); +#endif + + UINT uiIDA[2]; + + uiIDA[0]=IDS_TEXTUREPACK_FULLVERSION; + //uiIDA[1]=IDS_TEXTURE_PACK_TRIALVERSION; + uiIDA[1]=IDS_CONFIRM_CANCEL; + + // Give the player a warning about the texture pack missing + ui.RequestMessageBox(IDS_DLC_TEXTUREPACK_NOT_PRESENT_TITLE, IDS_DLC_TEXTUREPACK_NOT_PRESENT, uiIDA, 2, ProfileManager.GetPrimaryPad(),&TexturePackDialogReturned,this,app.GetStringTable(),NULL,0,false); + return; + } + } + m_bIgnoreInput = true; + + // if the profile data has been changed, then force a profile write (we save the online/invite/friends of friends settings) + // It seems we're allowed to break the 5 minute rule if it's the result of a user action + // check the checkboxes + + // Only save the online setting if the user changed it - we may change it because we're offline, but don't want that saved + if(!m_MoreOptionsParams.bOnlineSettingChangedBySystem) + { + app.SetGameSettings(m_iPad,eGameSetting_Online,m_MoreOptionsParams.bOnlineGame?1:0); + } + app.SetGameSettings(m_iPad,eGameSetting_InviteOnly,m_MoreOptionsParams.bInviteOnly?1:0); + app.SetGameSettings(m_iPad,eGameSetting_FriendsOfFriends,m_MoreOptionsParams.bAllowFriendsOfFriends?1:0); + + app.CheckGameSettingsChanged(true,m_iPad); + + // Check that we have the rights to use a texture pack we have selected. + if(m_MoreOptionsParams.dwTexturePack!=0) + { + // texture pack hasn't been set yet, so check what it will be + TexturePack *pTexturePack = pMinecraft->skins->getTexturePackById(m_MoreOptionsParams.dwTexturePack); + DLCTexturePack *pDLCTexPack=(DLCTexturePack *)pTexturePack; + m_pDLCPack=pDLCTexPack->getDLCInfoParentPack(); + + // do we have a license? + if(m_pDLCPack && !m_pDLCPack->hasPurchasedFile( DLCManager::e_DLCType_Texture, L"" )) + { + // no + + // We need to allow people to use a trial texture pack if they are offline - we only need them online if they want to buy it. + + /* + UINT uiIDA[1]; + uiIDA[0]=IDS_OK; + + if(!ProfileManager.IsSignedInLive(m_iPad)) + { + // need to be signed in to live + ui.RequestMessageBox(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_XBOXLIVE_NOTIFICATION, uiIDA, 1); + m_bIgnoreInput = false; + return; + } + else */ + { + // upsell +#ifdef _XBOX + DLC_INFO *pDLCInfo = app.GetDLCInfoForTrialOfferID(m_pDLCPack->getPurchaseOfferId()); + ULONGLONG ullOfferID_Full; + + if(pDLCInfo!=NULL) + { + ullOfferID_Full=pDLCInfo->ullOfferID_Full; + } + else + { + ullOfferID_Full=pTexturePack->getDLCPack()->getPurchaseOfferId(); + } + + // tell sentient about the upsell of the full version of the texture pack + TelemetryManager->RecordUpsellPresented(m_iPad, eSet_UpsellID_Texture_DLC, ullOfferID_Full & 0xFFFFFFFF); +#endif + +#if defined(_DURANGO) || defined(_WINDOWS64) + // trial pack warning + UINT uiIDA[1]; + uiIDA[0]=IDS_CONFIRM_OK; + ui.RequestMessageBox(IDS_WARNING_DLC_TRIALTEXTUREPACK_TITLE, IDS_USING_TRIAL_TEXUREPACK_WARNING, uiIDA, 1, m_iPad,&TrialTexturePackWarningReturned,this,app.GetStringTable(),NULL,0,false); +#elif defined __PS3__ || defined __ORBIS__ || defined(__PSVITA__) + // trial pack warning + UINT uiIDA[2]; + uiIDA[0]=IDS_CONFIRM_OK; + uiIDA[1]=IDS_CONFIRM_CANCEL; + ui.RequestMessageBox(IDS_WARNING_DLC_TRIALTEXTUREPACK_TITLE, IDS_USING_TRIAL_TEXUREPACK_WARNING, uiIDA, 2, m_iPad,&TrialTexturePackWarningReturned,this,app.GetStringTable(),NULL,0,false); +#endif + +#if defined _XBOX_ONE || defined __ORBIS__ + StorageManager.SetSaveDisabled(true); +#endif + return; + } + } + } +#if defined _XBOX_ONE || defined __ORBIS__ + app.SetGameHostOption(eGameHostOption_DisableSaving, m_MoreOptionsParams.bDisableSaving?1:0); + StorageManager.SetSaveDisabled(m_MoreOptionsParams.bDisableSaving); +#endif + checkStateAndStartGame(); +} + +void UIScene_CreateWorldMenu::handleSliderMove(F64 sliderId, F64 currentValue) +{ + WCHAR TempString[256]; + int value = (int)currentValue; + switch((int)sliderId) + { + case eControl_Difficulty: + m_sliderDifficulty.handleSliderMove(value); + + app.SetGameSettings(m_iPad,eGameSetting_Difficulty,value); + swprintf( (WCHAR *)TempString, 256, L"%ls: %ls", app.GetString( IDS_SLIDER_DIFFICULTY ),app.GetString(m_iDifficultyTitleSettingA[value])); + m_sliderDifficulty.setLabel(TempString); + break; + } +} + +void UIScene_CreateWorldMenu::handleTimerComplete(int id) +{ +#ifdef __PSVITA__ + // we cannot rebuild touch boxes in an iggy callback because it requires further iggy calls + if(m_bRebuildTouchBoxes) + { + GetMainPanel()->UpdateControl(); + ui.TouchBoxRebuild(this); + m_bRebuildTouchBoxes = false; + } +#endif + + switch(id) + { + case GAME_CREATE_ONLINE_TIMER_ID: + { + bool bMultiplayerAllowed = ProfileManager.IsSignedInLive( m_iPad ) && ProfileManager.AllowedToPlayMultiplayer(m_iPad); + + if(bMultiplayerAllowed != m_bMultiplayerAllowed) + { + if( bMultiplayerAllowed ) + { + bool bGameSetting_Online=(app.GetGameSettings(m_iPad,eGameSetting_Online)!=0); + m_MoreOptionsParams.bOnlineGame = bGameSetting_Online?TRUE:FALSE; + if(bGameSetting_Online) + { + m_MoreOptionsParams.bInviteOnly = (app.GetGameSettings(m_iPad,eGameSetting_InviteOnly)!=0)?TRUE:FALSE; + m_MoreOptionsParams.bAllowFriendsOfFriends = (app.GetGameSettings(m_iPad,eGameSetting_FriendsOfFriends)!=0)?TRUE:FALSE; + } + else + { + m_MoreOptionsParams.bInviteOnly = FALSE; + m_MoreOptionsParams.bAllowFriendsOfFriends = FALSE; + } + } + else + { + m_MoreOptionsParams.bOnlineGame = FALSE; + m_MoreOptionsParams.bInviteOnly = FALSE; + m_MoreOptionsParams.bAllowFriendsOfFriends = FALSE; + } + +#if defined _XBOX_ONE || defined __ORBIS__ || defined _WINDOWS64 + if(getSceneResolution() == eSceneResolution_1080) + { + m_checkboxOnline.SetEnable(bMultiplayerAllowed); + m_checkboxOnline.setChecked(m_MoreOptionsParams.bOnlineGame); + } +#endif + m_bMultiplayerAllowed = bMultiplayerAllowed; + } + } + break; + // 4J-PB - Only Xbox will not have trial DLC patched into the game +#ifdef _XBOX + case CHECKFORAVAILABLETEXTUREPACKS_TIMER_ID: + { + // also check for any new texture packs info being available + // for each item in the mem list, check it's in the data list + + CXuiCtrl4JList::LIST_ITEM_INFO ListInfo; + // for each iConfig, check if the data is available, and add it to the List, then remove it from the viConfig + for(int i=0;i<m_iTexturePacksNotInstalled;i++) + { + if(m_iConfigA[i]!=-1) + { + DWORD dwBytes=0; + PBYTE pbData=NULL; + //app.DebugPrintf("Retrieving iConfig %d from TPD\n",m_iConfigA[i]); + + app.GetTPD(m_iConfigA[i],&pbData,&dwBytes); + + ZeroMemory(&ListInfo,sizeof(CXuiCtrl4JList::LIST_ITEM_INFO)); + if(dwBytes > 0 && pbData) + { + DWORD dwImageBytes=0; + PBYTE pbImageData=NULL; + + app.GetFileFromTPD(eTPDFileType_Icon,pbData,dwBytes,&pbImageData,&dwImageBytes ); + ListInfo.fEnabled = TRUE; + ListInfo.iData = m_iConfigA[i]; + HRESULT hr=XuiCreateTextureBrushFromMemory(pbImageData,dwImageBytes,&ListInfo.hXuiBrush); + app.DebugPrintf("Adding texturepack %d from TPD\n",m_iConfigA[i]); + + m_pTexturePacksList->AddData(ListInfo); + + m_iConfigA[i]=-1; + } + } + } + } + break; +#endif + }; +} + +void UIScene_CreateWorldMenu::handleGainFocus(bool navBack) +{ + if(navBack) + { +#if defined _XBOX_ONE || defined __ORBIS__ || defined _WINDOWS64 + if(getSceneResolution() == eSceneResolution_1080) + { + m_checkboxOnline.setChecked(m_MoreOptionsParams.bOnlineGame); + } + m_editSeed.setLabel(m_MoreOptionsParams.seed); +#endif + } +} + +int UIScene_CreateWorldMenu::KeyboardCompleteWorldNameCallback(LPVOID lpParam,bool bRes) +{ + UIScene_CreateWorldMenu *pClass=(UIScene_CreateWorldMenu *)lpParam; + pClass->m_bIgnoreInput=false; + // 4J HEG - No reason to set value if keyboard was cancelled + if (bRes) + { + uint16_t pchText[128]; + ZeroMemory(pchText, 128 * sizeof(uint16_t) ); + InputManager.GetText(pchText); + + if(pchText[0]!=0) + { + pClass->m_editWorldName.setLabel((wchar_t *)pchText); + pClass->m_worldName = (wchar_t *)pchText; + } + + pClass->m_buttonCreateWorld.setEnable( !pClass->m_worldName.empty() ); + } + return 0; +} + +int UIScene_CreateWorldMenu::KeyboardCompleteSeedCallback(LPVOID lpParam,bool bRes) +{ + UIScene_CreateWorldMenu *pClass=(UIScene_CreateWorldMenu *)lpParam; + pClass->m_bIgnoreInput=false; + // 4J HEG - No reason to set value if keyboard was cancelled + if (bRes) + { +#ifdef __PSVITA__ + //CD - Changed to 2048 [SCE_IME_MAX_TEXT_LENGTH] + uint16_t pchText[2048]; + ZeroMemory(pchText, 2048 * sizeof(uint16_t) ); +#else + uint16_t pchText[128]; + ZeroMemory(pchText, 128 * sizeof(uint16_t) ); +#endif + InputManager.GetText(pchText); + pClass->m_editSeed.setLabel((wchar_t *)pchText); + pClass->m_MoreOptionsParams.seed = (wchar_t *)pchText; + } + return 0; +} + +void UIScene_CreateWorldMenu::checkStateAndStartGame() +{ + int primaryPad = ProfileManager.GetPrimaryPad(); + bool isSignedInLive = true; + bool isOnlineGame = m_MoreOptionsParams.bOnlineGame; + int iPadNotSignedInLive = -1; + bool isLocalMultiplayerAvailable = app.IsLocalMultiplayerAvailable(); + + for(unsigned int i = 0; i < XUSER_MAX_COUNT; i++) + { + if (ProfileManager.IsSignedIn(i) && (i == primaryPad || isLocalMultiplayerAvailable)) + { + if (isSignedInLive && !ProfileManager.IsSignedInLive(i)) + { + // Record the first non signed in live pad + iPadNotSignedInLive = i; + } + + isSignedInLive = isSignedInLive && ProfileManager.IsSignedInLive(i); + } + } + + // If this is an online game but not all players are signed in to Live, stop! + if (isOnlineGame && !isSignedInLive) + { +#ifdef __ORBIS__ + assert(iPadNotSignedInLive != -1); + + // Check if PSN is unavailable because of age restriction + int npAvailability = ProfileManager.getNPAvailability(iPadNotSignedInLive); + if (npAvailability == SCE_NP_ERROR_AGE_RESTRICTION) + { + m_bIgnoreInput = false; + // 4J Stu - This is a bit messy and is due to the library incorrectly returning false for IsSignedInLive if the npAvailability isn't SCE_OK + UINT uiIDA[1]; + uiIDA[0]=IDS_OK; + ui.RequestMessageBox(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, iPadNotSignedInLive, NULL, NULL, app.GetStringTable()); + } + else + { + m_bIgnoreInput = true; + UINT uiIDA[2]; + uiIDA[0] = IDS_PRO_NOTONLINE_ACCEPT; + uiIDA[1] = IDS_CANCEL; + ui.RequestMessageBox( IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 2, iPadNotSignedInLive, &UIScene_CreateWorldMenu::MustSignInReturnedPSN, this, app.GetStringTable(), NULL, 0, false); + } + return; +/* 4J-PB - Add this after release +#elif defined __PSVITA__ + m_bIgnoreInput=false; + // Determine why they're not "signed in live" + if (ProfileManager.IsSignedInPSN(ProfileManager.GetPrimaryPad())) + { + // Signed in to PSN but not connected (no internet access) + UINT uiIDA[1]; + uiIDA[0] = IDS_CONFIRM_OK; + ui.RequestMessageBox(IDS_PRO_CURRENTLY_NOT_ONLINE_TITLE, IDS_PRO_PSNOFFLINE_TEXT, uiIDA, 1, ProfileManager.GetPrimaryPad(), NULL,NULL, app.GetStringTable()); + } + else + { + // Not signed in to PSN + UINT uiIDA[1]; + uiIDA[0] = IDS_CONFIRM_OK; + ui.RequestMessageBox(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 1, ProfileManager.GetPrimaryPad(), NULL,NULL, app.GetStringTable()); + return; + }*/ +#else + m_bIgnoreInput=false; + UINT uiIDA[1]; + uiIDA[0]=IDS_CONFIRM_OK; + ui.RequestMessageBox( IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA,1,ProfileManager.GetPrimaryPad(),NULL,NULL, app.GetStringTable(),NULL,0,false); + return; +#endif + } + +#ifdef __ORBIS__ + + bool bPlayStationPlus = true; + int iPadWithNoPlaystationPlus=0; + if(isOnlineGame && isSignedInLive) + { + for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i) + { + if(ProfileManager.IsSignedIn(i) && (i == primaryPad || isLocalMultiplayerAvailable)) + { + if(ProfileManager.HasPlayStationPlus(i)==false) + { + bPlayStationPlus=false; + iPadWithNoPlaystationPlus=i; + break; + } + } + } + + if(bPlayStationPlus==false) + { + m_bIgnoreInput=false; + + // 4J-PB - we're not allowed to show the text Playstation Plus - have to call the upsell all the time! + // upsell psplus + int32_t iResult=sceNpCommerceDialogInitialize(); + + SceNpCommerceDialogParam param; + sceNpCommerceDialogParamInitialize(¶m); + param.mode=SCE_NP_COMMERCE_DIALOG_MODE_PLUS; + param.features = SCE_NP_PLUS_FEATURE_REALTIME_MULTIPLAY; + param.userId = ProfileManager.getUserID(iPadWithNoPlaystationPlus); + + iResult=sceNpCommerceDialogOpen(¶m); + +// UINT uiIDA[2]; +// uiIDA[0]=IDS_PLAY_OFFLINE; +// uiIDA[1]=IDS_PLAYSTATIONPLUS_SIGNUP; +// ui.RequestMessageBox( IDS_FAILED_TO_CREATE_GAME_TITLE, IDS_NO_PLAYSTATIONPLUS, uiIDA,2,ProfileManager.GetPrimaryPad(),&UIScene_CreateWorldMenu::PSPlusReturned,this, app.GetStringTable(),NULL,0,false); + return; + } + } +#endif + + if(m_bGameModeSurvival != true || m_MoreOptionsParams.bHostPrivileges == TRUE) + { + UINT uiIDA[2]; + uiIDA[0]=IDS_CONFIRM_OK; + uiIDA[1]=IDS_CONFIRM_CANCEL; + if(m_bGameModeSurvival != true) + { + ui.RequestMessageBox(IDS_TITLE_START_GAME, IDS_CONFIRM_START_CREATIVE, uiIDA, 2, m_iPad,&UIScene_CreateWorldMenu::ConfirmCreateReturned,this,app.GetStringTable(),NULL,0,false); + } + else + { + ui.RequestMessageBox(IDS_TITLE_START_GAME, IDS_CONFIRM_START_HOST_PRIVILEGES, uiIDA, 2, m_iPad,&UIScene_CreateWorldMenu::ConfirmCreateReturned,this,app.GetStringTable(),NULL,0,false); + } + } + else + { + // 4J Stu - If we only have one controller connected, then don't show the sign-in UI again + DWORD connectedControllers = 0; + for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i) + { + if( InputManager.IsPadConnected(i) || ProfileManager.IsSignedIn(i) ) ++connectedControllers; + } + + // Check if user-created content is allowed, as we cannot play multiplayer if it's not + //bool isClientSide = ProfileManager.IsSignedInLive(ProfileManager.GetPrimaryPad()) && m_MoreOptionsParams.bOnlineGame; + bool noUGC = false; + BOOL pccAllowed = TRUE; + BOOL pccFriendsAllowed = TRUE; + bool bContentRestricted = false; + + ProfileManager.AllowedPlayerCreatedContent(ProfileManager.GetPrimaryPad(),false,&pccAllowed,&pccFriendsAllowed); +#if defined(__PS3__) || defined(__PSVITA__) + if(isOnlineGame && isSignedInLive) + { + ProfileManager.GetChatAndContentRestrictions(ProfileManager.GetPrimaryPad(),false,NULL,&bContentRestricted,NULL); + } +#endif + + noUGC = !pccAllowed && !pccFriendsAllowed; + + if(isOnlineGame && isSignedInLive && app.IsLocalMultiplayerAvailable()) + { + // 4J-PB not sure why we aren't checking the content restriction for the main player here when multiple controllers are connected - adding now + if(noUGC ) + { + m_bIgnoreInput=false; + ui.RequestUGCMessageBox(); + } + else if(bContentRestricted ) + { + m_bIgnoreInput=false; + ui.RequestContentRestrictedMessageBox(); + } +#ifdef __ORBIS__ + else if(bPlayStationPlus==false) + { + m_bIgnoreInput=false; + + // 4J-PB - we're not allowed to show the text Playstation Plus - have to call the upsell all the time! + // upsell psplus + int32_t iResult=sceNpCommerceDialogInitialize(); + + SceNpCommerceDialogParam param; + sceNpCommerceDialogParamInitialize(¶m); + param.mode=SCE_NP_COMMERCE_DIALOG_MODE_PLUS; + param.features = SCE_NP_PLUS_FEATURE_REALTIME_MULTIPLAY; + param.userId = ProfileManager.getUserID(iPadWithNoPlaystationPlus); + + iResult=sceNpCommerceDialogOpen(¶m); +// UINT uiIDA[2]; +// uiIDA[0]=IDS_PLAY_OFFLINE; +// uiIDA[1]=IDS_PLAYSTATIONPLUS_SIGNUP; +// ui.RequestMessageBox( IDS_FAILED_TO_CREATE_GAME_TITLE, IDS_NO_PLAYSTATIONPLUS, uiIDA,2,ProfileManager.GetPrimaryPad(),&UIScene_CreateWorldMenu::PSPlusReturned,this, app.GetStringTable(),NULL,0,false); + } + +#endif + else + { + //ProfileManager.RequestSignInUI(false, false, false, true, false,&CScene_MultiGameCreate::StartGame_SignInReturned, this,ProfileManager.GetPrimaryPad()); + SignInInfo info; + info.Func = &UIScene_CreateWorldMenu::StartGame_SignInReturned; + info.lpParam = this; + info.requireOnline = m_MoreOptionsParams.bOnlineGame; + ui.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_QuadrantSignin,&info); + } + } + else + { + if(!pccAllowed && !pccFriendsAllowed) noUGC = true; + + if(isOnlineGame && isSignedInLive && noUGC ) + { + m_bIgnoreInput=false; + ui.RequestUGCMessageBox(); + } + else if(isOnlineGame && isSignedInLive && bContentRestricted ) + { + m_bIgnoreInput=false; + ui.RequestContentRestrictedMessageBox(); + } +#ifdef __ORBIS__ + else if(isOnlineGame && isSignedInLive && (bPlayStationPlus==false)) + { + m_bIgnoreInput=false; + setVisible( true ); + + // 4J-PB - we're not allowed to show the text Playstation Plus - have to call the upsell all the time! + // upsell psplus + int32_t iResult=sceNpCommerceDialogInitialize(); + + SceNpCommerceDialogParam param; + sceNpCommerceDialogParamInitialize(¶m); + param.mode=SCE_NP_COMMERCE_DIALOG_MODE_PLUS; + param.features = SCE_NP_PLUS_FEATURE_REALTIME_MULTIPLAY; + param.userId = ProfileManager.getUserID(iPadWithNoPlaystationPlus); + + iResult=sceNpCommerceDialogOpen(¶m); + +// UINT uiIDA[2]; +// uiIDA[0]=IDS_PLAY_OFFLINE; +// uiIDA[1]=IDS_PLAYSTATIONPLUS_SIGNUP; +// ui.RequestMessageBox( IDS_FAILED_TO_CREATE_GAME_TITLE, IDS_NO_PLAYSTATIONPLUS, uiIDA,2,ProfileManager.GetPrimaryPad(),&UIScene_CreateWorldMenu::PSPlusReturned,this, app.GetStringTable(),NULL,0,false); + } + +#endif + else + { +#if defined(__ORBIS__) || defined(__PSVITA__) + if(isOnlineGame) + { + bool chatRestricted = false; + ProfileManager.GetChatAndContentRestrictions(ProfileManager.GetPrimaryPad(),false,&chatRestricted,NULL,NULL); + if(chatRestricted) + { + ProfileManager.DisplaySystemMessage( SCE_MSG_DIALOG_SYSMSG_TYPE_TRC_PSN_CHAT_RESTRICTION, ProfileManager.GetPrimaryPad() ); + } + } +#endif + CreateGame(this, 0); + } + } + } + +} + +// 4J Stu - Shared functionality that is the same whether we needed a quadrant sign-in or not +void UIScene_CreateWorldMenu::CreateGame(UIScene_CreateWorldMenu* pClass, DWORD dwLocalUsersMask) +{ +#if TO_BE_IMPLEMENTED + // stop the timer running that causes a check for new texture packs in TMS but not installed, since this will run all through the create game, and will crash if it tries to create an hbrush + XuiKillTimer(pClass->m_hObj,CHECKFORAVAILABLETEXTUREPACKS_TIMER_ID); +#endif + + bool isClientSide = ProfileManager.IsSignedInLive(ProfileManager.GetPrimaryPad()) && pClass->m_MoreOptionsParams.bOnlineGame; +#ifdef __PSVITA__ + if(CGameNetworkManager::usingAdhocMode()) + { + if(SQRNetworkManager_AdHoc_Vita::GetAdhocStatus())// && pClass->m_MoreOptionsParams.bOnlineGame) + isClientSide = true; + } +#endif // __PSVITA__ + + bool isPrivate = pClass->m_MoreOptionsParams.bInviteOnly?true:false; + + // clear out the app's terrain features list + app.ClearTerrainFeaturePosition(); + + // create the world and launch + wstring wWorldName = pClass->m_worldName; + + StorageManager.ResetSaveData(); + // Make our next save default to the name of the level + StorageManager.SetSaveTitle((wchar_t *)wWorldName.c_str()); + + wstring wSeed; + if(!pClass->m_MoreOptionsParams.seed.empty() ) + { + wSeed=pClass->m_MoreOptionsParams.seed; + } + else + { + // random + wSeed=L""; + } + + // start the game + bool isFlat = (pClass->m_MoreOptionsParams.bFlatWorld==TRUE); + __int64 seedValue = 0; + + NetworkGameInitData *param = new NetworkGameInitData(); + + if (wSeed.length() != 0) + { + __int64 value = 0; + unsigned int len = (unsigned int)wSeed.length(); + + //Check if the input string contains a numerical value + bool isNumber = true; + for( unsigned int i = 0 ; i < len ; ++i ) + { + if( wSeed.at(i) < L'0' || wSeed.at(i) > L'9' ) + { + if( !(i==0 && wSeed.at(i) == L'-' ) ) + { + isNumber = false; + break; + } + } + } + + //If the input string is a numerical value, convert it to a number + if( isNumber ) + value = _fromString<__int64>(wSeed); + + //If the value is not 0 use it, otherwise use the algorithm from the java String.hashCode() function to hash it + if( value != 0 ) + seedValue = value; + else + { + int hashValue = 0; + for( unsigned int i = 0 ; i < len ; ++i ) + hashValue = 31 * hashValue + wSeed.at(i); + seedValue = hashValue; + } + } + else + { + param->findSeed = true; // 4J - java code sets the seed to was (new Random())->nextLong() here - we used to at this point find a suitable seed, but now just set a flag so this is performed in Minecraft::Server::initServer. + } + + + param->seed = seedValue; + param->saveData = NULL; + param->texturePackId = pClass->m_MoreOptionsParams.dwTexturePack; + + Minecraft *pMinecraft = Minecraft::GetInstance(); + pMinecraft->skins->selectTexturePackById(pClass->m_MoreOptionsParams.dwTexturePack); + + app.SetGameHostOption(eGameHostOption_Difficulty,Minecraft::GetInstance()->options->difficulty); + app.SetGameHostOption(eGameHostOption_FriendsOfFriends,pClass->m_MoreOptionsParams.bAllowFriendsOfFriends); + app.SetGameHostOption(eGameHostOption_Gamertags,app.GetGameSettings(pClass->m_iPad,eGameSetting_GamertagsVisible)?1:0); + + app.SetGameHostOption(eGameHostOption_BedrockFog,app.GetGameSettings(pClass->m_iPad,eGameSetting_BedrockFog)?1:0); + + app.SetGameHostOption(eGameHostOption_GameType,pClass->m_bGameModeSurvival?GameType::SURVIVAL->getId():GameType::CREATIVE->getId() ); + app.SetGameHostOption(eGameHostOption_LevelType,pClass->m_MoreOptionsParams.bFlatWorld ); + app.SetGameHostOption(eGameHostOption_Structures,pClass->m_MoreOptionsParams.bStructures ); + app.SetGameHostOption(eGameHostOption_BonusChest,pClass->m_MoreOptionsParams.bBonusChest ); + + app.SetGameHostOption(eGameHostOption_PvP,pClass->m_MoreOptionsParams.bPVP); + app.SetGameHostOption(eGameHostOption_TrustPlayers,pClass->m_MoreOptionsParams.bTrust ); + app.SetGameHostOption(eGameHostOption_FireSpreads,pClass->m_MoreOptionsParams.bFireSpreads ); + app.SetGameHostOption(eGameHostOption_TNT,pClass->m_MoreOptionsParams.bTNT ); + app.SetGameHostOption(eGameHostOption_HostCanFly,pClass->m_MoreOptionsParams.bHostPrivileges); + app.SetGameHostOption(eGameHostOption_HostCanChangeHunger,pClass->m_MoreOptionsParams.bHostPrivileges); + app.SetGameHostOption(eGameHostOption_HostCanBeInvisible,pClass->m_MoreOptionsParams.bHostPrivileges ); + + g_NetworkManager.HostGame(dwLocalUsersMask,isClientSide,isPrivate,MINECRAFT_NET_MAX_PLAYERS,0); + + param->settings = app.GetGameHostOption( eGameHostOption_All ); + +#ifdef _LARGE_WORLDS + switch(pClass->m_MoreOptionsParams.worldSize) + { + case 0: + // Classic + param->xzSize = 1 * 54; + param->hellScale = 3; + break; + case 1: + // Small + param->xzSize = 1 * 64; + param->hellScale = 3; + break; + case 2: + // Medium + param->xzSize = 3 * 64; + param->hellScale = 6; + break; + case 3: + //param->xzSize = 5 * 64; + //param->hellScale = 8; + + // Large + param->xzSize = LEVEL_MAX_WIDTH; + param->hellScale = HELL_LEVEL_MAX_SCALE; + break; + }; +#else + param->xzSize = LEVEL_MAX_WIDTH; + param->hellScale = HELL_LEVEL_MAX_SCALE; +#endif + +#ifndef _XBOX + g_NetworkManager.FakeLocalPlayerJoined(); +#endif + + LoadingInputParams *loadingParams = new LoadingInputParams(); + loadingParams->func = &CGameNetworkManager::RunNetworkGameThreadProc; + loadingParams->lpParam = (LPVOID)param; + + // Reset the autosave time + app.SetAutosaveTimerTime(); + + UIFullscreenProgressCompletionData *completionData = new UIFullscreenProgressCompletionData(); + completionData->bShowBackground=TRUE; + completionData->bShowLogo=TRUE; + completionData->type = e_ProgressCompletion_CloseAllPlayersUIScenes; + completionData->iPad = DEFAULT_XUI_MENU_USER; + loadingParams->completionData = completionData; + + ui.NavigateToScene(pClass->m_iPad,eUIScene_FullscreenProgress, loadingParams); +} + + +int UIScene_CreateWorldMenu::StartGame_SignInReturned(void *pParam,bool bContinue, int iPad) +{ + UIScene_CreateWorldMenu* pClass = (UIScene_CreateWorldMenu*)pParam; + + if(bContinue==true) + { + // It's possible that the player has not signed in - they can back out + if(ProfileManager.IsSignedIn(pClass->m_iPad)) + { + bool isOnlineGame = ProfileManager.IsSignedInLive(ProfileManager.GetPrimaryPad()) && pClass->m_MoreOptionsParams.bOnlineGame; + // bool isOnlineGame = pClass->m_MoreOptionsParams.bOnlineGame; + int primaryPad = ProfileManager.GetPrimaryPad(); + bool noPrivileges = false; + DWORD dwLocalUsersMask = 0; + bool isSignedInLive = ProfileManager.IsSignedInLive(primaryPad); + int iPadNotSignedInLive = -1; + bool isLocalMultiplayerAvailable = app.IsLocalMultiplayerAvailable(); + + for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i) + { + if (ProfileManager.IsSignedIn(i) && ((i == primaryPad) || isLocalMultiplayerAvailable)) + { + if (isSignedInLive && !ProfileManager.IsSignedInLive(i)) + { + // Record the first non signed in live pad + iPadNotSignedInLive = i; + } + + if( !ProfileManager.AllowedToPlayMultiplayer(i) ) noPrivileges = true; + dwLocalUsersMask |= CGameNetworkManager::GetLocalPlayerMask(i); + isSignedInLive = isSignedInLive && ProfileManager.IsSignedInLive(i); + } + } + + // If this is an online game but not all players are signed in to Live, stop! + if (isOnlineGame && !isSignedInLive) + { +#ifdef __ORBIS__ + assert(iPadNotSignedInLive != -1); + + // Check if PSN is unavailable because of age restriction + int npAvailability = ProfileManager.getNPAvailability(iPadNotSignedInLive); + if (npAvailability == SCE_NP_ERROR_AGE_RESTRICTION) + { + pClass->m_bIgnoreInput = false; + // 4J Stu - This is a bit messy and is due to the library incorrectly returning false for IsSignedInLive if the npAvailability isn't SCE_OK + UINT uiIDA[1]; + uiIDA[0]=IDS_OK; + ui.RequestMessageBox(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, iPadNotSignedInLive, NULL, NULL, app.GetStringTable()); + } + else + { + pClass->m_bIgnoreInput=true; + UINT uiIDA[2]; + uiIDA[0] = IDS_PRO_NOTONLINE_ACCEPT; + uiIDA[1] = IDS_CANCEL; + ui.RequestMessageBox( IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 2, iPadNotSignedInLive, &UIScene_CreateWorldMenu::MustSignInReturnedPSN, pClass, app.GetStringTable(), NULL, 0, false); + } + return 0; +#else + pClass->m_bIgnoreInput=false; + UINT uiIDA[1]; + uiIDA[0]=IDS_CONFIRM_OK; + ui.RequestMessageBox( IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA,1,ProfileManager.GetPrimaryPad(),NULL,NULL, app.GetStringTable(),NULL,0,false); + return 0; +#endif + } + + // Check if user-created content is allowed, as we cannot play multiplayer if it's not + bool noUGC = false; + BOOL pccAllowed = TRUE; + BOOL pccFriendsAllowed = TRUE; + + ProfileManager.AllowedPlayerCreatedContent(ProfileManager.GetPrimaryPad(),false,&pccAllowed,&pccFriendsAllowed); + if(!pccAllowed && !pccFriendsAllowed) noUGC = true; + + if(isOnlineGame && (noPrivileges || noUGC) ) + { + if( noUGC ) + { + pClass->m_bIgnoreInput = false; + UINT uiIDA[1]; + uiIDA[0]=IDS_CONFIRM_OK; + ui.RequestMessageBox( IDS_FAILED_TO_CREATE_GAME_TITLE, IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_CREATE, uiIDA,1,ProfileManager.GetPrimaryPad(),NULL,NULL, app.GetStringTable(),NULL,0,false); + } + else + { + pClass->m_bIgnoreInput = false; + UINT uiIDA[1]; + uiIDA[0]=IDS_CONFIRM_OK; + ui.RequestMessageBox( IDS_NO_MULTIPLAYER_PRIVILEGE_TITLE, IDS_NO_MULTIPLAYER_PRIVILEGE_HOST_TEXT, uiIDA,1,ProfileManager.GetPrimaryPad(),NULL,NULL, app.GetStringTable(),NULL,0,false); + } + } + else + { + // This is NOT called from a storage manager thread, and is in fact called from the main thread in the Profile library tick. Therefore we use the main threads IntCache. + CreateGame(pClass, dwLocalUsersMask); + } + } + } + else + { + pClass->m_bIgnoreInput = false; + } + return 0; +} + + +int UIScene_CreateWorldMenu::ConfirmCreateReturned(void *pParam,int iPad,C4JStorage::EMessageResult result) +{ + UIScene_CreateWorldMenu* pClass = (UIScene_CreateWorldMenu*)pParam; + + if(result==C4JStorage::EMessage_ResultAccept) + { + bool isClientSide = ProfileManager.IsSignedInLive(ProfileManager.GetPrimaryPad()) && pClass->m_MoreOptionsParams.bOnlineGame; + + // 4J Stu - If we only have one controller connected, then don't show the sign-in UI again + DWORD connectedControllers = 0; + for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i) + { + if( InputManager.IsPadConnected(i) || ProfileManager.IsSignedIn(i) ) ++connectedControllers; + } + + if(isClientSide && app.IsLocalMultiplayerAvailable()) + { + //ProfileManager.RequestSignInUI(false, false, false, true, false,&UIScene_CreateWorldMenu::StartGame_SignInReturned, pClass,ProfileManager.GetPrimaryPad()); + SignInInfo info; + info.Func = &UIScene_CreateWorldMenu::StartGame_SignInReturned; + info.lpParam = pClass; + info.requireOnline = pClass->m_MoreOptionsParams.bOnlineGame; + ui.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_QuadrantSignin,&info); + } + else + { + // Check if user-created content is allowed, as we cannot play multiplayer if it's not + bool isClientSide = ProfileManager.IsSignedInLive(ProfileManager.GetPrimaryPad()) && pClass->m_MoreOptionsParams.bOnlineGame; + bool noUGC = false; + BOOL pccAllowed = TRUE; + BOOL pccFriendsAllowed = TRUE; + + ProfileManager.AllowedPlayerCreatedContent(ProfileManager.GetPrimaryPad(),false,&pccAllowed,&pccFriendsAllowed); + if(!pccAllowed && !pccFriendsAllowed) noUGC = true; + + if(isClientSide && noUGC ) + { + pClass->m_bIgnoreInput = false; + UINT uiIDA[1]; + uiIDA[0]=IDS_CONFIRM_OK; + ui.RequestMessageBox( IDS_FAILED_TO_CREATE_GAME_TITLE, IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_CREATE, uiIDA,1,ProfileManager.GetPrimaryPad(),NULL,NULL, app.GetStringTable(),NULL,0,false); + } + else + { +#if defined( __ORBIS__) || defined(__PSVITA__) + bool isOnlineGame = ProfileManager.IsSignedInLive(ProfileManager.GetPrimaryPad()) && pClass->m_MoreOptionsParams.bOnlineGame; + if(isOnlineGame) + { + bool chatRestricted = false; + ProfileManager.GetChatAndContentRestrictions(ProfileManager.GetPrimaryPad(),false,&chatRestricted,NULL,NULL); + if(chatRestricted) + { + ProfileManager.DisplaySystemMessage( SCE_MSG_DIALOG_SYSMSG_TYPE_TRC_PSN_CHAT_RESTRICTION, ProfileManager.GetPrimaryPad() ); + } + } +#endif + CreateGame(pClass, 0); + } + } + } + else + { + pClass->m_bIgnoreInput = false; + } + return 0; +} + +#ifdef __ORBIS__ +int UIScene_CreateWorldMenu::MustSignInReturnedPSN(void *pParam,int iPad,C4JStorage::EMessageResult result) +{ + UIScene_CreateWorldMenu* pClass = (UIScene_CreateWorldMenu *)pParam; + pClass->m_bIgnoreInput = false; + + if(result==C4JStorage::EMessage_ResultAccept) + { + SQRNetworkManager_Orbis::AttemptPSNSignIn(&UIScene_CreateWorldMenu::StartGame_SignInReturned, pClass, false, iPad); + } + + return 0; +} + +// int UIScene_CreateWorldMenu::PSPlusReturned(void *pParam,int iPad,C4JStorage::EMessageResult result) +// { +// int32_t iResult; +// UIScene_CreateWorldMenu *pClass = (UIScene_CreateWorldMenu *)pParam; +// +// // continue offline, or upsell PS Plus? +// if(result==C4JStorage::EMessage_ResultDecline) +// { +// // upsell psplus +// int32_t iResult=sceNpCommerceDialogInitialize(); +// +// SceNpCommerceDialogParam param; +// sceNpCommerceDialogParamInitialize(¶m); +// param.mode=SCE_NP_COMMERCE_DIALOG_MODE_PLUS; +// param.features = SCE_NP_PLUS_FEATURE_REALTIME_MULTIPLAY; +// param.userId = ProfileManager.getUserID(pClass->m_iPad); +// +// iResult=sceNpCommerceDialogOpen(¶m); +// } +// else if(result==C4JStorage::EMessage_ResultAccept) +// { +// // continue offline +// pClass->m_MoreOptionsParams.bOnlineGame=false; +// pClass->checkStateAndStartGame(); +// } +// +// pClass->m_bIgnoreInput=false; +// return 0; +// } +#endif + + +void UIScene_CreateWorldMenu::handleTouchBoxRebuild() +{ + m_bRebuildTouchBoxes = true; +} diff --git a/Minecraft.Client/Common/UI/UIScene_CreateWorldMenu.h b/Minecraft.Client/Common/UI/UIScene_CreateWorldMenu.h new file mode 100644 index 00000000..ebb383e8 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_CreateWorldMenu.h @@ -0,0 +1,115 @@ +#pragma once + +#include "IUIScene_StartGame.h" + +class UIScene_CreateWorldMenu : public IUIScene_StartGame +{ +private: + enum EControls + { + eControl_EditWorldName, + eControl_EditSeed, + eControl_TexturePackList, + eControl_GameModeToggle, + eControl_Difficulty, + eControl_MoreOptions, + eControl_NewWorld, + eControl_OnlineGame, + }; + + static int m_iDifficultyTitleSettingA[4]; + + + wstring m_worldName; + wstring m_seed; + + UIControl m_controlMainPanel; + UIControl_Label m_labelWorldName, m_labelSeed, m_labelRandomSeed; + UIControl_Button m_buttonGamemode, m_buttonMoreOptions, m_buttonCreateWorld; + UIControl_TextInput m_editWorldName, m_editSeed; + UIControl_Slider m_sliderDifficulty; + +#if defined _XBOX_ONE || defined __ORBIS__ || defined _WINDOWS64 + UIControl_CheckBox m_checkboxOnline; +#endif + + UIControl_BitmapIcon m_bitmapIcon, m_bitmapComparison; + + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(IUIScene_StartGame) + UI_MAP_ELEMENT( m_controlMainPanel, "MainPanel" ) + UI_BEGIN_MAP_CHILD_ELEMENTS( m_controlMainPanel ) + UI_MAP_ELEMENT( m_labelWorldName, "WorldName") + UI_MAP_ELEMENT( m_editWorldName, "EditWorldName") + UI_MAP_ELEMENT( m_labelSeed, "Seed") + UI_MAP_ELEMENT( m_editSeed, "EditSeed") + UI_MAP_ELEMENT( m_labelRandomSeed, "RandomSeed") + UI_MAP_ELEMENT( m_texturePackList, "TexturePackSelector") + UI_MAP_ELEMENT( m_buttonGamemode, "GameModeToggle") + +#if defined _XBOX_ONE || defined __ORBIS__ || defined _WINDOWS64 + UI_MAP_ELEMENT( m_checkboxOnline, "CheckboxOnline") +#endif + UI_MAP_ELEMENT( m_buttonMoreOptions, "MoreOptions") + UI_MAP_ELEMENT( m_buttonCreateWorld, "NewWorld") + UI_MAP_ELEMENT( m_sliderDifficulty, "Difficulty") + UI_END_MAP_CHILD_ELEMENTS() + UI_END_MAP_ELEMENTS_AND_NAMES() + + bool m_bGameModeSurvival; + bool m_bMultiplayerAllowed; + DLCPack * m_pDLCPack; + bool m_bRebuildTouchBoxes; + +public: + UIScene_CreateWorldMenu(int iPad, void *initData, UILayer *parentLayer); + virtual ~UIScene_CreateWorldMenu(); + + virtual void updateTooltips(); + virtual void updateComponents(); + + virtual EUIScene getSceneType() { return eUIScene_CreateWorldMenu;} + + virtual void handleDestroy(); + virtual void tick(); + + virtual UIControl* GetMainPanel(); + + virtual void handleTouchBoxRebuild(); + +protected: + // TODO: This should be pure virtual in this class + virtual wstring getMoviePath(); + + virtual void handleTimerComplete(int id); + virtual void handleGainFocus(bool navBack); + +public: + // INPUT + virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled); + +private: + void StartSharedLaunchFlow(); + bool IsLocalMultiplayerAvailable(); + +#ifdef _DURANGO + static void checkPrivilegeCallback(LPVOID lpParam, bool hasPrivilege, int iPad); +#endif + +protected: + static int KeyboardCompleteWorldNameCallback(LPVOID lpParam,const bool bRes); + static int KeyboardCompleteSeedCallback(LPVOID lpParam,const bool bRes); + void handlePress(F64 controlId, F64 childId); + void handleSliderMove(F64 sliderId, F64 currentValue); + + static void CreateGame(UIScene_CreateWorldMenu* pClass, DWORD dwLocalUsersMask); + static int ConfirmCreateReturned(void *pParam,int iPad,C4JStorage::EMessageResult result); + static int StartGame_SignInReturned(void *pParam,bool bContinue, int iPad); + static int MustSignInReturnedPSN(void *pParam,int iPad,C4JStorage::EMessageResult result); + +#ifdef __ORBIS__ + //static int PSPlusReturned(void *pParam,int iPad,C4JStorage::EMessageResult result); + static int ContinueOffline(void *pParam,int iPad,C4JStorage::EMessageResult result); +#endif + + virtual void checkStateAndStartGame(); +};
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIScene_CreativeMenu.cpp b/Minecraft.Client/Common/UI/UIScene_CreativeMenu.cpp new file mode 100644 index 00000000..569cc8ba --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_CreativeMenu.cpp @@ -0,0 +1,493 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIScene_CreativeMenu.h" + +#include "..\Minecraft.World\JavaMath.h" +#include "..\..\LocalPlayer.h" +#include "..\Tutorial\Tutorial.h" +#include "..\Tutorial\TutorialMode.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.inventory.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.item.h" + +#ifdef __PSVITA__ +#define GAME_CREATIVE_TOUCHUPDATE_TIMER_ID 0 +#define GAME_CREATIVE_TOUCHUPDATE_TIMER_TIME 100 +#endif + +UIScene_CreativeMenu::UIScene_CreativeMenu(int iPad, void *_initData, UILayer *parentLayer) : UIScene_AbstractContainerMenu(iPad, parentLayer) +{ + // Setup all the Iggy references we need for this scene + initialiseMovie(); + + InventoryScreenInput *initData = (InventoryScreenInput *)_initData; + + shared_ptr<SimpleContainer> creativeContainer = shared_ptr<SimpleContainer>(new SimpleContainer( 0, TabSpec::MAX_SIZE )); + itemPickerMenu = new ItemPickerMenu(creativeContainer, initData->player->inventory); + + Initialize( initData->iPad, itemPickerMenu, false, -1, eSectionInventoryCreativeUsing, eSectionInventoryCreativeMax, initData->bNavigateBack); + + m_labelInventory.setLabel( L"" ); + m_bFirstCall=true; + + //m_slotListContainer.addSlots(0,TabSpec::MAX_SIZE); + //m_slotListHotbar.addSlots(TabSpec::MAX_SIZE,TabSpec::MAX_SIZE + 9); + for(unsigned int i = 0; i < TabSpec::MAX_SIZE; ++i) + { + m_slotListContainer.addSlot(i); + } + + for(unsigned int i = TabSpec::MAX_SIZE; i < TabSpec::MAX_SIZE + 9; ++i) + { + m_slotListHotbar.addSlot(i); + } + + Minecraft *pMinecraft = Minecraft::GetInstance(); + if( pMinecraft->localgameModes[initData->iPad] != NULL ) + { + TutorialMode *gameMode = (TutorialMode *)pMinecraft->localgameModes[initData->iPad]; + m_previousTutorialState = gameMode->getTutorial()->getCurrentState(); + gameMode->getTutorial()->changeTutorialState(e_Tutorial_State_Creative_Inventory_Menu, this); + } + + if(initData) delete initData; + + m_curTab = eCreativeInventoryTab_COUNT; + switchTab(eCreativeInventoryTab_BuildingBlocks); + +#ifdef __PSVITA__ + // initialise vita touch controls with ids + for(unsigned int i = 0; i < ETouchInput_Count; ++i) + { + m_TouchInput[i].init(i); + } +#endif +} + +wstring UIScene_CreativeMenu::getMoviePath() +{ + if(app.GetLocalPlayerCount() > 1) + { + return L"CreativeMenuSplit"; + } + else + { + return L"CreativeMenu"; + } +} + +#ifdef __PSVITA__ +UIControl* UIScene_CreativeMenu::GetMainPanel() +{ + return &m_controlMainPanel; +} + +void UIScene_CreativeMenu::handleTouchInput(unsigned int iPad, S32 x, S32 y, int iId, bool bPressed, bool bRepeat, bool bReleased) +{ + // perform action on release + if(bReleased) + { + if(iId >= eCreativeInventoryTab_BuildingBlocks && iId <= eCreativeInventoryTab_Misc) + { + switchTab((ECreativeInventoryTabs)iId); + ui.PlayUISFX(eSFX_Focus); + } + } + if(bRepeat && iId == ETouchInput_TouchSlider && specs[m_curTab]->getPageCount() > 1) + { + // calculate relative touch position on slider + float fPosition = ((float)y - (float)m_TouchInput[ETouchInput_TouchSlider].getYPos() - m_controlMainPanel.getYPos()) / (float)m_TouchInput[ETouchInput_TouchSlider].getHeight(); + + // clamp + if(fPosition > 1) + fPosition = 1.0f; + else if(fPosition < 0) + fPosition = 0.0f; + + // calculate page position according to page count + int iCurrentPage = Math::round(fPosition * (specs[m_curTab]->getPageCount() - 1)); + + // set tab page + m_tabPage[m_curTab] = iCurrentPage; + + // update tab + switchTab(m_curTab); + } +} + +void UIScene_CreativeMenu::handleTouchBoxRebuild() +{ + addTimer(GAME_CREATIVE_TOUCHUPDATE_TIMER_ID,GAME_CREATIVE_TOUCHUPDATE_TIMER_TIME); +} + +void UIScene_CreativeMenu::handleTimerComplete(int id) +{ + if(id == GAME_CREATIVE_TOUCHUPDATE_TIMER_ID) + { + // we cannot rebuild touch boxes in an iggy callback because it requires further iggy calls + GetMainPanel()->UpdateControl(); + ui.TouchBoxRebuild(this); + killTimer(GAME_CREATIVE_TOUCHUPDATE_TIMER_ID); + } +} +#endif + +void UIScene_CreativeMenu::handleOtherClicked(int iPad, ESceneSection eSection, int buttonNum, bool quickKey) +{ + switch(eSection) + { + case eSectionInventoryCreativeTab_0: + case eSectionInventoryCreativeTab_1: + case eSectionInventoryCreativeTab_2: + case eSectionInventoryCreativeTab_3: + case eSectionInventoryCreativeTab_4: + case eSectionInventoryCreativeTab_5: + case eSectionInventoryCreativeTab_6: + case eSectionInventoryCreativeTab_7: + { + ECreativeInventoryTabs tab = (ECreativeInventoryTabs)((int)eCreativeInventoryTab_BuildingBlocks + (int)eSection - (int)eSectionInventoryCreativeTab_0); + if(tab != m_curTab) + { + switchTab(tab); + ui.PlayUISFX(eSFX_Focus); + } + } + break; + case eSectionInventoryCreativeSlider: + ScrollBar(this->m_pointerPos); + break; + } +} + +void UIScene_CreativeMenu::ScrollBar(UIVec2D pointerPos) +{ + float fPosition = ((float)pointerPos.y - (float)m_TouchInput[ETouchInput_TouchSlider].getYPos()) / (float)m_TouchInput[ETouchInput_TouchSlider].getHeight(); + + // clamp + if(fPosition > 1) + fPosition = 1.0f; + else if(fPosition < 0) + fPosition = 0.0f; + + // calculate page position according to page count + int iCurrentPage = Math::round(fPosition * (specs[m_curTab]->getPageCount() - 1)); + + // set tab page + m_tabPage[m_curTab] = iCurrentPage; + + // update tab + switchTab(m_curTab); +} + +void UIScene_CreativeMenu::handleReload() +{ + Initialize( m_iPad, m_menu, false, -1, eSectionInventoryCreativeUsing, eSectionInventoryCreativeMax, m_bNavigateBack ); + + for(unsigned int i = 0; i < TabSpec::MAX_SIZE; ++i) + { + m_slotListContainer.addSlot(i); + } + + for(unsigned int i = TabSpec::MAX_SIZE; i < TabSpec::MAX_SIZE + 9; ++i) + { + m_slotListHotbar.addSlot(i); + } +} + +void UIScene_CreativeMenu::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled) +{ + // 4J-PB - going to ignore repeats on this scene + if(repeat) return; + + //app.DebugPrintf("UIScene_CreativeMenu handling input for pad %d, key %d, down- %s, pressed- %s, released- %s\n", iPad, key, down?"TRUE":"FALSE", pressed?"TRUE":"FALSE", released?"TRUE":"FALSE"); + ui.AnimateKeyPress(m_iPad, key, repeat, pressed, released); + + int dir = 1; + switch(key) + { + case VK_PAD_LSHOULDER: + dir = -1; + // Fall through intentional + case VK_PAD_RSHOULDER: + { + ECreativeInventoryTabs tab = (ECreativeInventoryTabs)(m_curTab + dir); + if (tab < 0) tab = (ECreativeInventoryTabs)(eCreativeInventoryTab_COUNT - 1); + if (tab >= eCreativeInventoryTab_COUNT) tab = eCreativeInventoryTab_BuildingBlocks; + switchTab(tab); + ui.PlayUISFX(eSFX_Focus); + } + break; + case VK_PAD_LTRIGGER: + // change the potion strength + { + ++m_tabDynamicPos[m_curTab]; + if(m_tabDynamicPos[m_curTab] >= specs[m_curTab]->m_dynamicGroupsCount) m_tabDynamicPos[m_curTab] = 0; + switchTab(m_curTab); + } + break; + default: + UIScene_AbstractContainerMenu::handleInput(iPad,key,repeat,pressed,released,handled); + break; + } +} + +void UIScene_CreativeMenu::updateTabHighlightAndText(ECreativeInventoryTabs tab) +{ + IggyDataValue result; + IggyDataValue value[1]; + + value[0].type = IGGY_DATATYPE_number; + value[0].number = (F64)tab; + + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ) , m_funcSetActiveTab , 1 , value ); + + m_labelInventory.setLabel(app.GetString(specs[tab]->m_descriptionId)); +} + +int UIScene_CreativeMenu::getSectionColumns(ESceneSection eSection) +{ + int cols = 0; + switch( eSection ) + { + case eSectionInventoryCreativeSelector: + cols = 10; + break; + case eSectionInventoryCreativeUsing: + cols = 9; + break; + default: + assert( false ); + break; + } + return cols; +} + +int UIScene_CreativeMenu::getSectionRows(ESceneSection eSection) +{ + int rows = 0; + switch( eSection ) + { + case eSectionInventoryCreativeSelector: + rows = 5; + break; + case eSectionInventoryCreativeUsing: + rows = 1; + break; + default: + assert( false ); + break; + } + return rows; +} + +void UIScene_CreativeMenu::GetPositionOfSection( ESceneSection eSection, UIVec2D* pPosition ) +{ + switch( eSection ) + { + case eSectionInventoryCreativeSelector: + pPosition->x = m_slotListContainer.getXPos(); + pPosition->y = m_slotListContainer.getYPos(); + break; + case eSectionInventoryCreativeUsing: + pPosition->x = m_slotListHotbar.getXPos(); + pPosition->y = m_slotListHotbar.getYPos(); + break; + case eSectionInventoryCreativeTab_0: + pPosition->x = m_TouchInput[ETouchInput_TouchPanel_0].getXPos(); + pPosition->y = m_TouchInput[ETouchInput_TouchPanel_0].getYPos(); + break; + case eSectionInventoryCreativeTab_1: + pPosition->x = m_TouchInput[ETouchInput_TouchPanel_1].getXPos(); + pPosition->y = m_TouchInput[ETouchInput_TouchPanel_1].getYPos(); + break; + case eSectionInventoryCreativeTab_2: + pPosition->x = m_TouchInput[ETouchInput_TouchPanel_2].getXPos(); + pPosition->y = m_TouchInput[ETouchInput_TouchPanel_2].getYPos(); + break; + case eSectionInventoryCreativeTab_3: + pPosition->x = m_TouchInput[ETouchInput_TouchPanel_3].getXPos(); + pPosition->y = m_TouchInput[ETouchInput_TouchPanel_3].getYPos(); + break; + case eSectionInventoryCreativeTab_4: + pPosition->x = m_TouchInput[ETouchInput_TouchPanel_4].getXPos(); + pPosition->y = m_TouchInput[ETouchInput_TouchPanel_4].getYPos(); + break; + case eSectionInventoryCreativeTab_5: + pPosition->x = m_TouchInput[ETouchInput_TouchPanel_5].getXPos(); + pPosition->y = m_TouchInput[ETouchInput_TouchPanel_5].getYPos(); + break; + case eSectionInventoryCreativeTab_6: + pPosition->x = m_TouchInput[ETouchInput_TouchPanel_6].getXPos(); + pPosition->y = m_TouchInput[ETouchInput_TouchPanel_6].getYPos(); + break; + case eSectionInventoryCreativeTab_7: + pPosition->x = m_TouchInput[ETouchInput_TouchPanel_7].getXPos(); + pPosition->y = m_TouchInput[ETouchInput_TouchPanel_7].getYPos(); + break; + case eSectionInventoryCreativeSlider: + pPosition->x = m_TouchInput[ETouchInput_TouchSlider].getXPos(); + pPosition->y = m_TouchInput[ETouchInput_TouchSlider].getYPos(); + break; + default: + assert( false ); + break; + } +} + +void UIScene_CreativeMenu::GetItemScreenData( ESceneSection eSection, int iItemIndex, UIVec2D* pPosition, UIVec2D* pSize ) +{ + UIVec2D sectionSize; + + switch( eSection ) + { + case eSectionInventoryCreativeSelector: + sectionSize.x = m_slotListContainer.getWidth(); + sectionSize.y = m_slotListContainer.getHeight(); + break; + case eSectionInventoryCreativeUsing: + sectionSize.x = m_slotListHotbar.getWidth(); + sectionSize.y = m_slotListHotbar.getHeight(); + break; + case eSectionInventoryCreativeTab_0: + sectionSize.x = m_TouchInput[ETouchInput_TouchPanel_0].getWidth(); + sectionSize.y = m_TouchInput[ETouchInput_TouchPanel_0].getHeight(); + break; + case eSectionInventoryCreativeTab_1: + sectionSize.x = m_TouchInput[ETouchInput_TouchPanel_1].getWidth(); + sectionSize.y = m_TouchInput[ETouchInput_TouchPanel_1].getHeight(); + break; + case eSectionInventoryCreativeTab_2: + sectionSize.x = m_TouchInput[ETouchInput_TouchPanel_2].getWidth(); + sectionSize.y = m_TouchInput[ETouchInput_TouchPanel_2].getHeight(); + break; + case eSectionInventoryCreativeTab_3: + sectionSize.x = m_TouchInput[ETouchInput_TouchPanel_3].getWidth(); + sectionSize.y = m_TouchInput[ETouchInput_TouchPanel_3].getHeight(); + break; + case eSectionInventoryCreativeTab_4: + sectionSize.x = m_TouchInput[ETouchInput_TouchPanel_4].getWidth(); + sectionSize.y = m_TouchInput[ETouchInput_TouchPanel_4].getHeight(); + break; + case eSectionInventoryCreativeTab_5: + sectionSize.x = m_TouchInput[ETouchInput_TouchPanel_5].getWidth(); + sectionSize.y = m_TouchInput[ETouchInput_TouchPanel_5].getHeight(); + break; + case eSectionInventoryCreativeTab_6: + sectionSize.x = m_TouchInput[ETouchInput_TouchPanel_6].getWidth(); + sectionSize.y = m_TouchInput[ETouchInput_TouchPanel_6].getHeight(); + break; + case eSectionInventoryCreativeTab_7: + sectionSize.x = m_TouchInput[ETouchInput_TouchPanel_7].getWidth(); + sectionSize.y = m_TouchInput[ETouchInput_TouchPanel_7].getHeight(); + break; + case eSectionInventoryCreativeSlider: + sectionSize.x = m_TouchInput[ETouchInput_TouchSlider].getWidth(); + sectionSize.y = m_TouchInput[ETouchInput_TouchSlider].getHeight(); + break; + default: + assert( false ); + break; + } + + if(IsSectionSlotList(eSection)) + { + int rows = getSectionRows(eSection); + int cols = getSectionColumns(eSection); + + pSize->x = sectionSize.x/cols; + pSize->y = sectionSize.y/rows; + + int itemCol = iItemIndex % cols; + int itemRow = iItemIndex/cols; + + pPosition->x = itemCol * pSize->x; + pPosition->y = itemRow * pSize->y; + } + else + { + GetPositionOfSection(eSection, pPosition); + pSize->x = sectionSize.x; + pSize->y = sectionSize.y; + } +} + +void UIScene_CreativeMenu::setSectionSelectedSlot(ESceneSection eSection, int x, int y) +{ + int cols = getSectionColumns(eSection); + + int index = (y * cols) + x; + + UIControl_SlotList *slotList = NULL; + switch( eSection ) + { + case eSectionInventoryCreativeSelector: + slotList = &m_slotListContainer; + break; + case eSectionInventoryCreativeUsing: + slotList = &m_slotListHotbar; + break; + default: + assert( false ); + break; + } + + slotList->setHighlightSlot(index); +} + +UIControl *UIScene_CreativeMenu::getSection(ESceneSection eSection) +{ + UIControl *control = NULL; + switch( eSection ) + { + case eSectionInventoryCreativeSelector: + control = &m_slotListContainer; + break; + case eSectionInventoryCreativeUsing: + control = &m_slotListHotbar; + break; + case eSectionInventoryCreativeTab_0: + control = &m_TouchInput[ETouchInput_TouchPanel_0]; + break; + case eSectionInventoryCreativeTab_1: + control = &m_TouchInput[ETouchInput_TouchPanel_1]; + break; + case eSectionInventoryCreativeTab_2: + control = &m_TouchInput[ETouchInput_TouchPanel_2]; + break; + case eSectionInventoryCreativeTab_3: + control = &m_TouchInput[ETouchInput_TouchPanel_3]; + break; + case eSectionInventoryCreativeTab_4: + control = &m_TouchInput[ETouchInput_TouchPanel_4]; + break; + case eSectionInventoryCreativeTab_5: + control = &m_TouchInput[ETouchInput_TouchPanel_5]; + break; + case eSectionInventoryCreativeTab_6: + control = &m_TouchInput[ETouchInput_TouchPanel_6]; + break; + case eSectionInventoryCreativeTab_7: + control = &m_TouchInput[ETouchInput_TouchPanel_7]; + break; + case eSectionInventoryCreativeSlider: + control = &m_TouchInput[ETouchInput_TouchSlider]; + break; + default: + assert( false ); + break; + } + return control; +} + +void UIScene_CreativeMenu::updateScrollCurrentPage(int currentPage, int pageCount) +{ + IggyDataValue result; + IggyDataValue value[2]; + + value[0].type = IGGY_DATATYPE_number; + value[0].number = (F64)pageCount; + + value[1].type = IGGY_DATATYPE_number; + value[1].number = (F64)currentPage - 1; + + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ) , m_funcSetScrollBar , 2 , value ); +}
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIScene_CreativeMenu.h b/Minecraft.Client/Common/UI/UIScene_CreativeMenu.h new file mode 100644 index 00000000..6fbec2ba --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_CreativeMenu.h @@ -0,0 +1,90 @@ +#pragma once + +#include "UIScene_AbstractContainerMenu.h" +#include "IUIScene_CreativeMenu.h" + +class UIScene_CreativeMenu : public UIScene_AbstractContainerMenu, public IUIScene_CreativeMenu +{ +public: + UIScene_CreativeMenu(int iPad, void *initData, UILayer *parentLayer); + + virtual EUIScene getSceneType() { return eUIScene_CreativeMenu;} + +protected: + UIControl_SlotList m_slotListContainer; + IggyName m_funcSetActiveTab, m_funcSetScrollBar; + + enum ETouchInput + { + ETouchInput_TouchPanel_0, + ETouchInput_TouchPanel_1, + ETouchInput_TouchPanel_2, + ETouchInput_TouchPanel_3, + ETouchInput_TouchPanel_4, + ETouchInput_TouchPanel_5, + ETouchInput_TouchPanel_6, + ETouchInput_TouchPanel_7, + ETouchInput_TouchSlider, + + ETouchInput_Count, + }; + +#ifdef __PSVITA__ + // 4J - TomK - this only needs to be a touch component on vita! + UIControl_Touch m_TouchInput[ETouchInput_Count]; +#else + UIControl_Base m_TouchInput[ETouchInput_Count]; +#endif + + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene_AbstractContainerMenu) + UI_BEGIN_MAP_CHILD_ELEMENTS( m_controlMainPanel ) + + UI_MAP_ELEMENT( m_TouchInput[ETouchInput_TouchPanel_0], "TouchPanel_0" ) + UI_MAP_ELEMENT( m_TouchInput[ETouchInput_TouchPanel_1], "TouchPanel_1" ) + UI_MAP_ELEMENT( m_TouchInput[ETouchInput_TouchPanel_2], "TouchPanel_2" ) + UI_MAP_ELEMENT( m_TouchInput[ETouchInput_TouchPanel_3], "TouchPanel_3" ) + UI_MAP_ELEMENT( m_TouchInput[ETouchInput_TouchPanel_4], "TouchPanel_4" ) + UI_MAP_ELEMENT( m_TouchInput[ETouchInput_TouchPanel_5], "TouchPanel_5" ) + UI_MAP_ELEMENT( m_TouchInput[ETouchInput_TouchPanel_6], "TouchPanel_6" ) + UI_MAP_ELEMENT( m_TouchInput[ETouchInput_TouchPanel_7], "TouchPanel_7" ) + UI_MAP_ELEMENT( m_TouchInput[ETouchInput_TouchSlider], "TouchPanel_Slider" ) + + UI_MAP_ELEMENT( m_slotListContainer, "containerList") + UI_END_MAP_CHILD_ELEMENTS() + + UI_MAP_NAME(m_funcSetActiveTab, L"SetActiveTab") + UI_MAP_NAME(m_funcSetScrollBar, L"SetScrollBar") + UI_END_MAP_ELEMENTS_AND_NAMES() + + virtual wstring getMoviePath(); + virtual void handleReload(); + + virtual int getSectionColumns(ESceneSection eSection); + virtual int getSectionRows(ESceneSection eSection); + virtual void GetPositionOfSection( ESceneSection eSection, UIVec2D* pPosition ); + virtual void GetItemScreenData( ESceneSection eSection, int iItemIndex, UIVec2D* pPosition, UIVec2D* pSize ); + virtual void handleSectionClick(ESceneSection eSection) {} + virtual void setSectionSelectedSlot(ESceneSection eSection, int x, int y); + + virtual UIControl *getSection(ESceneSection eSection); + + virtual void handleOtherClicked(int iPad, ESceneSection eSection, int buttonNum, bool quickKey); + +public: + // INPUT + virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled); + +#ifdef __PSVITA__ + virtual void handleTouchInput(unsigned int iPad, S32 x, S32 y, int iId, bool bPressed, bool bRepeat, bool bReleased); + virtual UIControl* GetMainPanel(); + virtual void handleTouchBoxRebuild(); + virtual void handleTimerComplete(int id); +#endif + virtual void ScrollBar(UIVec2D pointerPos); + +private: + // IUIScene_CreativeMenu + void updateTabHighlightAndText(ECreativeInventoryTabs tab); + void updateScrollCurrentPage(int currentPage, int pageCount); + bool m_bFirstCall; +};
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIScene_Credits.cpp b/Minecraft.Client/Common/UI/UIScene_Credits.cpp new file mode 100644 index 00000000..11558598 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_Credits.cpp @@ -0,0 +1,677 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIScene_Credits.h" + +#define CREDIT_ICON -2 + +SCreditTextItemDef UIScene_Credits::gs_aCreditDefs[MAX_CREDIT_STRINGS] = +{ + { L"MOJANG", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eExtraLargeText }, + { L"", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, // extra blank line + { L"%ls", IDS_CREDITS_ORIGINALDESIGN, NO_TRANSLATED_STRING,eLargeText }, + { L"Markus Persson", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, // extra blank line + { L"%ls", IDS_CREDITS_PMPROD, NO_TRANSLATED_STRING,eLargeText }, + { L"Daniel Kaplan", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, // extra blank line + { L"%ls", IDS_CREDITS_RESTOFMOJANG, NO_TRANSLATED_STRING,eMediumText }, + { L"%ls", IDS_CREDITS_LEADPC, NO_TRANSLATED_STRING,eLargeText }, + { L"Jens Bergensten", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"%ls", IDS_CREDITS_JON_KAGSTROM, NO_TRANSLATED_STRING,eSmallText }, + { L"%ls", IDS_CREDITS_CEO, NO_TRANSLATED_STRING,eLargeText }, + { L"Carl Manneh", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"%ls", IDS_CREDITS_DOF, NO_TRANSLATED_STRING,eLargeText }, + { L"Lydia Winters", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"%ls", IDS_CREDITS_WCW, NO_TRANSLATED_STRING,eLargeText }, + { L"Karin Severinsson", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"%ls", IDS_CREDITS_CUSTOMERSUPPORT, NO_TRANSLATED_STRING,eLargeText }, + { L"Marc Watson", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, // extra blank line + { L"%ls", IDS_CREDITS_DESPROG, NO_TRANSLATED_STRING,eLargeText }, + { L"Aron Nieminen", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, // extra blank line + { L"%ls", IDS_CREDITS_CHIEFARCHITECT, NO_TRANSLATED_STRING,eLargeText }, + { L"Daniel Frisk", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"%ls", IDS_CREDITS_CODENINJA, NO_TRANSLATED_STRING,eLargeText }, + { L"%ls", IDS_CREDITS_TOBIAS_MOLLSTAM, NO_TRANSLATED_STRING,eSmallText }, + { L"%ls", IDS_CREDITS_OFFICEDJ, NO_TRANSLATED_STRING,eLargeText }, + { L"Kristoffer Jelbring", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"%ls", IDS_CREDITS_DEVELOPER, NO_TRANSLATED_STRING,eLargeText }, + { L"Leonard Axelsson", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"%ls", IDS_CREDITS_BULLYCOORD, NO_TRANSLATED_STRING,eLargeText }, + { L"Jakob Porser", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"%ls", IDS_CREDITS_ARTDEVELOPER, NO_TRANSLATED_STRING,eLargeText }, + { L"Junkboy", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"%ls", IDS_CREDITS_EXPLODANIM, NO_TRANSLATED_STRING,eLargeText }, + { L"Mattis Grahm", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"%ls", IDS_CREDITS_CONCEPTART, NO_TRANSLATED_STRING,eLargeText }, + { L"Henrik Petterson", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"%ls", IDS_CREDITS_CRUNCHER, NO_TRANSLATED_STRING,eLargeText }, + { L"Patrick Geuder", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"%ls", IDS_CREDITS_MUSICANDSOUNDS, NO_TRANSLATED_STRING,eLargeText }, + { L"Daniel Rosenfeld (C418)", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, // extra blank line + { L"4J Studios", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eExtraLargeText }, + { L"%ls", IDS_CREDITS_PROGRAMMING, NO_TRANSLATED_STRING,eLargeText }, + { L"Paddy Burns", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Richard Reavy", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Stuart Ross", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"James Vaughan", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Mark Hughes", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Harry Gordon", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Thomas Kronberg", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, +#ifdef _XBOX + { L"Ian le Bruce", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Andy West", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Gordon McLean", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, +#endif + +#ifdef __PSVITA__ +// 4J-PB - Aaron didn't want to be in the credits { L"Aaron Puzey", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Chris Dawson", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, +#endif + + { L"%ls", IDS_CREDITS_ART, NO_TRANSLATED_STRING,eLargeText }, + { L"David Keningale", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, +#ifdef _XBOX + { L"Pat McGovern", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, +#endif + { L"Alan Redmond", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, +#ifdef _XBOX + { L"Julian Laing", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + + { L"Caitlin Goodale", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Scott Sutherland", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, +#endif + { L"Chris Reeves", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Kate Wright", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Michael Hansen", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, +#ifdef _XBOX + { L"Kate Flavell", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, +#endif + { L"Donald Robertson", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Jamie Keddie", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Thomas Naylor", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Brian Lindsay", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Hannah Watts", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Rebecca O'Neil", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + + { L"%ls", IDS_CREDITS_QA, NO_TRANSLATED_STRING,eLargeText }, + { L"Steven Gary Woodward", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, +#ifdef _XBOX + { L"Richard Black", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, +#endif + { L"George Vaughan", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, // extra blank line + { L"%ls", IDS_CREDITS_SPECIALTHANKS, NO_TRANSLATED_STRING,eLargeText }, + { L"Chris van der Kuyl", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Roni Percy", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Anne Clarke", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Anthony Kent", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, +#ifdef _XBOX + // credits are in the XUI file +#elif defined(__PS3__) +// font credits + { L"", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, // extra blank line + { L"%ls", IDS_DYNAFONT, NO_TRANSLATED_STRING,eLargeText }, + +#elif defined(__ORBIS__) +// font credits + { L"", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, // extra blank line + { L"%ls", IDS_DYNAFONT, NO_TRANSLATED_STRING,eLargeText }, + +#elif defined(_DURANGO) + { L"", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, // extra blank line + { L"", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, // extra blank line + { L"Xbox LIVE Arcade Team", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eExtraLargeText }, + { L"", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, // extra blank line + { L"%s", IDS_CREDITS_LEADPRODUCER, NO_TRANSLATED_STRING,eLargeText }, + { L"Roger Carpenter", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"%s", IDS_CREDITS_PRODUCER, NO_TRANSLATED_STRING,eLargeText }, + { L"Stuart Platt", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Riccardo Lenzi", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"%s", IDS_CREDITS_LEADTESTER, NO_TRANSLATED_STRING,eLargeText }, + { L"Bill Brown (Insight Global)", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Brandon McCurry (Insight Global)", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Hakim Ronaque, Joe Dunavant", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Paul Loynd, Jeffery Stephens", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Rial Lerum (Xtreme Consulting Group Inc)", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"%s", IDS_CREDITS_DESIGNTEAM, NO_TRANSLATED_STRING,eLargeText }, + { L"Craig Leigh", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"%s", IDS_CREDITS_DEVELOPMENTTEAM, NO_TRANSLATED_STRING,eLargeText }, + { L"Scott Guest", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Jeff \"Dextor\" Blazier", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Yukie Yamaguchi", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Jason Hewitt", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"%s", IDS_CREDITS_RELEASEMANAGEMENT, NO_TRANSLATED_STRING,eLargeText }, + { L"Isaac Aubrey", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Jordan Forbes", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Josh Mulanax", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Shogo Ishii (TekSystems)", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Tyler Keenan (Xtreme Consulting Group Inc)", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Joshua Bullard (TekSystems)", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"GTO-E Compliance", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eLargeText }, + { L"Dominic Gara", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"James Small", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + + { L"%s", IDS_CREDITS_EXECPRODUCER, NO_TRANSLATED_STRING,eLargeText }, + { L"Mark Coates", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Avi Ben-Menahem", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Earnest Yuen", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + + + { L"%s", IDS_CREDITS_XBLADIRECTOR, NO_TRANSLATED_STRING,eLargeText }, + { L"Ted Woolsey", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"%s", IDS_CREDITS_BIZDEV, NO_TRANSLATED_STRING,eLargeText }, + { L"Cherie Lutz", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Peter Zetterberg", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"%s", IDS_CREDITS_PORTFOLIODIRECTOR, NO_TRANSLATED_STRING,eLargeText }, + { L"Chris Charla", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"%s", IDS_CREDITS_PRODUCTMANAGER, NO_TRANSLATED_STRING,eLargeText }, + { L"Daniel McConnell", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"%s", IDS_CREDITS_MARKETING, NO_TRANSLATED_STRING,eLargeText }, + { L"Brandon Wells", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Michael Wolf", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"John Dongelmans", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"%s", IDS_CREDITS_COMMUNITYMANAGER, NO_TRANSLATED_STRING,eLargeText }, + { L"Alex Hebert", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"%s", IDS_CREDITS_REDMONDLOC, NO_TRANSLATED_STRING,eLargeText }, + { L"Zeb Wedell", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Gabriella Mittiga (Pactera)", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Scott Fielding (Global Studio Consulting)", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Yong Zhao (Hisoft Envisage Inc)", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Shogo Ishii (Insight Global)", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"%s", IDS_CREDITS_EUROPELOC, NO_TRANSLATED_STRING,eLargeText }, + { L"Gerard Dunne", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Ricardo Cordoba", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Magali Lucchini", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Malika Kherfi", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Lizzy Untermann", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Ian Walsh", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Alfonsina Mossello (Keywords International Ltd)", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Marika Mauri (Keywords International Ltd)", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Nobuhiro Izumisawa (Keywords International Ltd)", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Sebastien Faucon (Keywords International Ltd)", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Jose Manuel Martinez (Keywords International Ltd)", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Montse Garcia (Keywords International Ltd)", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"%s", IDS_CREDITS_ASIALOC, NO_TRANSLATED_STRING,eLargeText }, + { L"Takashi Sasaki", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Changseon Ha", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Shinya Muto (Zip Global Corporation)", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Hiroshi Hosoda (Zip Global Corporation)", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Natsuko Kudo (Zip Global Corporation)", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Yong-Hong Park (Zip Global Corporation)", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Yuko Yoshida (Zip Global Corporation)", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"%s", IDS_CREDITS_USERRESEARCH, NO_TRANSLATED_STRING,eLargeText }, + { L"", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, // extra blank line + { L"User Research Lead", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eLargeText }, + { L"Tim Nichols", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, // extra blank line + { L"User Research Engineer", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eLargeText }, + { L"Michael Medlock", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Kristie Fisher", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, // extra blank line + { L"%s", IDS_CREDITS_MGSCENTRAL, NO_TRANSLATED_STRING,eLargeText }, + { L"", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, // extra blank line + { L"Test Team Lead", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eLargeText }, + { L"Dan Smith", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"%s", IDS_CREDITS_MILESTONEACCEPT, NO_TRANSLATED_STRING,eLargeText }, + { L"Justin Davis (VMC)", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Microsoft Studios Sentient Development Team", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eLargeText }, + { L"Ellery Charlson", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Frank Klier", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Jason Ronald", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Cullen Waters", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Steve Jackson", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Barath Vasudevan", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Derek Mantey", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Henry Sterchi", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Scott Fintel", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Soren Hannibal Nielsen", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Meetali Goel (Aditi)", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Uladzimir Sadouski (Volt)", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"%s", IDS_CREDITS_SPECIALTHANKS, NO_TRANSLATED_STRING,eLargeText }, + + { L"Allan Murphy", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Allison Bokone", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Alvin Chen", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Arthur Yung", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Brian Tyler", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Daniel Taylor", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Dave Reed", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Duoc Nguyen", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Eric Voreis", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Evelyn Thomas", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Jeff Braunstein", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Jolynn Carpenter", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Justin Brown", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Kareem Choudhry", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Kevin Cogger", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Kevin La Chapelle", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Luc Rancourt", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Matt Bronder", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Michael Siebert", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Mike Harsh", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Mike Sterling", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Nick Rapp", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Orr Keshet", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Paul Hellyar", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Peter Giffin", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Richard Moe", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Scott Selfon", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Stephane St-Michel", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Steve Spiller", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Steven Trombetta", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Theo Michel", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Tina Lemire", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Tom Miller", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Travis St. Onge", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + + { L"Brianna Witherspoon (Nytec Inc)", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Jim Pekola (Xtreme Consulting Group Inc)", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Greg Hjertager", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Masha Reutovski (Nytec Inc)", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Chris Henry", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Matt Golz", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Chris Gaffney (Volt)", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Jared Barnhill (Aditi)", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Laura Hawkins", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"2nd Cavalry", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"GTO Bug Bash Team", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Oliver Miyashita", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Kevin Salcedo", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Nick Bodenham", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Chris Giggins", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Ben Board", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Peter Choi", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Andy Su (CompuCom Systems Inc.)", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"David Boker ", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Josh Bliggenstorfer", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Paul Amer", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Louise Smith", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Karin Behland (Aquent LLC)", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"John Bruno", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Phil Spencer", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"John Smith", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Christi Davisson", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Jacob Farley (Aditi)", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Chad Stringer (Collabera)", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Rick Rispoli (Collabera)", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Test by Experis", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eExtraLargeText }, + { L"%s", IDS_CREDITS_TESTMANAGER, NO_TRANSLATED_STRING,eLargeText }, + { L"Matt Brown", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Gavin Kennedy", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"%s", IDS_CREDITS_SRTESTLEAD, NO_TRANSLATED_STRING,eLargeText }, + { L"Lloyd Bell", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Tim Attuquayefio", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"%s", IDS_CREDITS_TESTLEAD, NO_TRANSLATED_STRING,eLargeText }, + { L"Byron R. Monzon", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Marta Alombro", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"%s", IDS_CREDITS_SDET, NO_TRANSLATED_STRING,eLargeText }, + { L"Valeriy Novytskyy", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"%s", IDS_CREDITS_PROJECT, NO_TRANSLATED_STRING,eLargeText }, + { L"Allyson Burk", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"David Scott", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"John Shearer", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"%s", IDS_CREDITS_ADDITIONALSTE, NO_TRANSLATED_STRING,eLargeText }, + { L"Chris Merritt", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Kimberlee Lyles", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Eric Ranz", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Russ Allen", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"%s", IDS_CREDITS_TESTASSOCIATES, NO_TRANSLATED_STRING,eLargeText }, + { L"Michael Arvat", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Josh Breese", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"April Culberson", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Jason Fox", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Clayton K. Hopper", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Matthew Howells", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Alan Hume", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Jacob Martin", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Kevin Lourigan", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Tyler Lovemark", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"%s", IDS_CREDITS_RISE_LUGO, NO_TRANSLATED_STRING,eSmallText }, + { L"Ryan Naegeli", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Isaac Price", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Masha Reutovski", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Brad Shockey", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Jonathan Tote", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Marc Williams", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Gillian Williams", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Jeffrey Woito", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Tyler Young", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Jae Yslas", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Amanda Swalling", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Ben Dienes", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Chris Kent", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Dustin Lukas", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Emily Lovering", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Nick Fowler", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + // EVEN MORE CREDITS + { L"Test by Lionbridge", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eExtraLargeText }, + { L"", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, // extra blank line + { L"%s", IDS_CREDITS_TESTMANAGER, NO_TRANSLATED_STRING,eLargeText }, + { L"Blazej Zawadzki", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"%s", IDS_CREDITS_TESTLEAD, NO_TRANSLATED_STRING,eLargeText }, + { L"Jakub Garwacki", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Kamil Lahti", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Mariusz Gelnicki", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Karol Falak", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Lukasz Watroba", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + + { L"%s", IDS_CREDITS_PROJECT, NO_TRANSLATED_STRING,eLargeText }, + { L"Artur Grochowski", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Grzegorz Kohorewicz", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Lukasz Derewonko", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Michal Celej", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + + { L"Senior Test Engineers", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eLargeText }, + { L"Jakub Rybacki", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Mateusz Szymanski", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Arkadiusz Szczytowski", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Rafal Rawski", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + + { L"%s", IDS_CREDITS_TESTASSOCIATES, NO_TRANSLATED_STRING,eLargeText }, + { L"Adrian Klepacki", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Aleksander Pietraszak", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + + { L"Arkadiusz Kala", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Arkadiusz Sykula", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Bartlomiej Kmita", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Jakub Malinowski", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Jan Prejs", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Jedrzej Kucharek", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Kamil Dabrowski", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Maciej Urlo", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Maciej Wygoda", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Marcin Piasecki", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Marcin Piotrowski", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Marek Latacz", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Michal Biernat", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Michal Krupinski", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Michal Warchal", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Michal Wascinski", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Michal Zbrzezniak", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Milosz Maciejewicz", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Pawel Kumanowski", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Przemyslaw Malinowski", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Tomasz Dabrowicz", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Tomasz Trzebiatowski", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Wojciech Kujawa", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + + { L"Blazej Kohorewicz", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Damian Mielnik", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Dariusz Nowakowski", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Dominik Rzeznicki", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Jacek Piotrowski", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Jakub Rybacki", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Jakub Wozniakowski", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Jaroslaw Radzio", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Kamil Kaczor", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Karolina Szymanska", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Konrad Mady", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Krzysztof Galazka", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Ludwik Miszta", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Lukasz Kwiatkowski", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Marcin Krzysiak", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Mateusz Szymanski", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Michal Maslany", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Michal Nyszka", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Norbert Jankowski", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Piotr Daszewski", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Radoslaw Kozlowski", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Tomasz Kalowski", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"%s", IDS_CREDITS_SPECIALTHANKS, NO_TRANSLATED_STRING,eLargeText }, + { L"David Hickey", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Sean Kellogg", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Adam Keating", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Jerzy Tyminski", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Paulina Sliwinska", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + + + { L"Test by Shield", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eExtraLargeText }, + { L"", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, // extra blank line + { L"GTO Shared Service Test Manager", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eLargeText }, + { L"Natahri Felton", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Shield Test Lead", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eLargeText }, + { L"Matt Giddings", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Shield IT Support", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eLargeText }, + { L"David Grant (Compucom Systems Inc)", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Primary Team", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eLargeText }, + { L"Alex Chen (CompuCom Systems Inc)", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Alex Hunte (CompuCom Systems Inc)", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Brian Boye (CompuCom Systems Inc)", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Bridgette Cummins (CompuCom Systems Inc)", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Chris Carleson (Volt)", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Christopher Hermey (CompuCom Systems Inc)", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"David Hendrickson (CompuCom Systems Inc)", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Ioana Preda (CompuCom Systems Inc)", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Jessica Jenkins (CompuCom Systems Inc)", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Johnathan Ochs (CompuCom Systems Inc)", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Michael Upham (CompuCom Systems Inc)", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Nicholas Johansson (CompuCom Systems Inc)", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Nicholas Starner (CompuCom Systems Inc)", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Torr Vickers (Volt)", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + { L"Victoria Bruder (CompuCom Systems Inc)", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, + +#elif defined(_WIN64) +#elif defined(__PSVITA__) +// font credits + { L"", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, // extra blank line + { L"%ls", IDS_DYNAFONT, NO_TRANSLATED_STRING,eLargeText }, + +#endif + +#ifndef _XBOX +// Miles & Iggy credits + { L"", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, // extra blank line + { L"", CREDIT_ICON, eCreditIcon_Iggy,eSmallText }, // extra blank line + { L"Uses Iggy.", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, // extra blank line +#ifdef __PS3__ + { L"Copyright (C) 2009-2013 by RAD Game Tools, Inc.", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, // extra blank line +#else + { L"Copyright (C) 2009-2014 by RAD Game Tools, Inc.", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, // extra blank line +#endif + { L"", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, // extra blank line + { L"", CREDIT_ICON, eCreditIcon_Miles,eSmallText }, // extra blank line + { L"Uses Miles Sound System.", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, // extra blank line +#ifdef __PS3__ + { L"Copyright (C) 1991-2013 by RAD Game Tools, Inc.", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, // extra blank line +#else + { L"Copyright (C) 1991-2014 by RAD Game Tools, Inc.", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, // extra blank line +#endif +#ifdef __PS3__ + { L"", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, // extra blank line + { L"", CREDIT_ICON, eCreditIcon_Dolby,eSmallText }, // extra blank line + { L"Dolby and the double-D symbol", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, // extra blank line + { L"are trademarks of Dolby Laboratories.", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, // extra blank line +#endif +#endif +}; + +UIScene_Credits::UIScene_Credits(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) +{ + // Setup all the Iggy references we need for this scene + initialiseMovie(); + + m_bAddNextLabel = false; + + // How many lines of text are in the credits? + m_iNumTextDefs = MAX_CREDIT_STRINGS; + + // Are there any additional lines needed for the DLC credits? + m_iNumTextDefs+=app.GetDLCCreditsCount(); + + m_iCurrDefIndex = -1; + + // Add the first 20 Flash can cope with + for(unsigned int i = 0; i < 20; ++i) + { + ++m_iCurrDefIndex; + + // Set up the new text element. + if ( gs_aCreditDefs[i].m_iStringID[0] == NO_TRANSLATED_STRING ) + { + setNextLabel(gs_aCreditDefs[i].m_Text,gs_aCreditDefs[i].m_eType); + } + else // using additional translated string. + { + LPWSTR creditsString = new wchar_t[ 128 ]; + if(gs_aCreditDefs[i].m_iStringID[1]!=NO_TRANSLATED_STRING) + { + swprintf( creditsString, 128, gs_aCreditDefs[i].m_Text, app.GetString( gs_aCreditDefs[i].m_iStringID[0] ), app.GetString( gs_aCreditDefs[i].m_iStringID[1] ) ); + } + else + { + swprintf( creditsString, 128, gs_aCreditDefs[i].m_Text, app.GetString( gs_aCreditDefs[i].m_iStringID[0] ) ); + } + setNextLabel(creditsString,gs_aCreditDefs[i].m_eType); + delete [] creditsString; + } + } +} + +wstring UIScene_Credits::getMoviePath() +{ + return L"Credits"; +} + +void UIScene_Credits::updateTooltips() +{ + ui.SetTooltips( m_iPad, -1, IDS_TOOLTIPS_BACK); +} + +void UIScene_Credits::updateComponents() +{ + m_parentLayer->showComponent(m_iPad,eUIComponent_Logo,true); +} + +void UIScene_Credits::handleReload() +{ + // We don't allow this in splitscreen, so just go back + navigateBack(); +} + +void UIScene_Credits::tick() +{ + UIScene::tick(); + + if(m_bAddNextLabel) + { + m_bAddNextLabel = false; + + const SCreditTextItemDef* pDef; + + // Time to create next text item. + ++m_iCurrDefIndex; + + // Wrap back to start. + if ( m_iCurrDefIndex >= m_iNumTextDefs ) + { + m_iCurrDefIndex = 0; + } + + if(m_iCurrDefIndex >= MAX_CREDIT_STRINGS) + { + app.DebugPrintf("DLC credit %d\n",m_iCurrDefIndex-MAX_CREDIT_STRINGS); + // DLC credit + pDef = app.GetDLCCredits(m_iCurrDefIndex-MAX_CREDIT_STRINGS); + } + else + { + // Get text def for this item. + pDef = &( gs_aCreditDefs[ m_iCurrDefIndex ] ); + } + + // Set up the new text element. + if(pDef->m_Text!=NULL) // 4J-PB - think the RAD logo ones aren't set up yet and are coming is as null + { + + if ( pDef->m_iStringID[0] == CREDIT_ICON ) + { + addImage((ECreditIcons)pDef->m_iStringID[1]); + } + else if ( pDef->m_iStringID[0] == NO_TRANSLATED_STRING ) + { + setNextLabel(pDef->m_Text,pDef->m_eType); + } + else // using additional translated string. + { + LPWSTR creditsString = new wchar_t[ 128 ]; + if(pDef->m_iStringID[1]!=NO_TRANSLATED_STRING) + { + swprintf( creditsString, 128, pDef->m_Text, app.GetString( pDef->m_iStringID[0] ), app.GetString( pDef->m_iStringID[1] ) ); + } + else + { + swprintf( creditsString, 128, pDef->m_Text, app.GetString( pDef->m_iStringID[0] ) ); + } + setNextLabel(creditsString,pDef->m_eType); + delete [] creditsString; + } + } + } +} + +void UIScene_Credits::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled) +{ + //app.DebugPrintf("UIScene_DebugOverlay handling input for pad %d, key %d, down- %ls, pressed- %ls, released- %ls\n", iPad, key, down?"TRUE":"FALSE", pressed?"TRUE":"FALSE", released?"TRUE":"FALSE"); + + ui.AnimateKeyPress(m_iPad, key, repeat, pressed, released); + + switch(key) + { + case ACTION_MENU_CANCEL: + if(pressed && !repeat) + { + navigateBack(); + } + break; + case ACTION_MENU_OK: +#ifdef __ORBIS__ + case ACTION_MENU_TOUCHPAD_PRESS: +#endif + case ACTION_MENU_UP: + case ACTION_MENU_DOWN: + sendInputToMovie(key, repeat, pressed, released); + break; + } +} + +void UIScene_Credits::setNextLabel(const wstring &label, ECreditTextTypes size) +{ + IggyDataValue result; + IggyDataValue value[3]; + + IggyStringUTF16 stringVal; + stringVal.string = (IggyUTF16*)label.c_str(); + stringVal.length = label.length(); + value[0].type = IGGY_DATATYPE_string_UTF16; + value[0].string16 = stringVal; + + value[1].type = IGGY_DATATYPE_number; + value[1].number = (int)size; + + value[2].type = IGGY_DATATYPE_boolean; + value[2].boolval = (m_iCurrDefIndex == (m_iNumTextDefs - 1)); + + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcSetNextLabel , 3 , value ); +} + +void UIScene_Credits::addImage(ECreditIcons icon) +{ + IggyDataValue result; + IggyDataValue value[2]; + + value[0].type = IGGY_DATATYPE_number; + value[0].number = (int)icon; + + value[1].type = IGGY_DATATYPE_boolean; + value[1].boolval = (m_iCurrDefIndex == (m_iNumTextDefs - 1)); + + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcAddImage , 2 , value ); +} + +void UIScene_Credits::handleRequestMoreData(F64 startIndex, bool up) +{ + m_bAddNextLabel = true; +} diff --git a/Minecraft.Client/Common/UI/UIScene_Credits.h b/Minecraft.Client/Common/UI/UIScene_Credits.h new file mode 100644 index 00000000..4116628d --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_Credits.h @@ -0,0 +1,71 @@ +#pragma once + +#include "UIScene.h" + +#define PS3_CREDITS_COUNT 75 +#define PSVITA_CREDITS_COUNT 77 +#define PS4_CREDITS_COUNT 75 +#define XBOXONE_CREDITS_COUNT (75+318) +#define MILES_AND_IGGY_CREDITS_COUNT 8 +#define DYNAMODE_FONT_CREDITS_COUNT 2 +#define PS3_DOLBY_CREDIT 4 + + +#ifdef __PS3__ +#define MAX_CREDIT_STRINGS (PS3_CREDITS_COUNT + MILES_AND_IGGY_CREDITS_COUNT + DYNAMODE_FONT_CREDITS_COUNT + PS3_DOLBY_CREDIT) +#elif defined(__ORBIS__) +#define MAX_CREDIT_STRINGS (PS4_CREDITS_COUNT + MILES_AND_IGGY_CREDITS_COUNT + DYNAMODE_FONT_CREDITS_COUNT) +#elif defined(_DURANGO) || defined _WIN64 +#define MAX_CREDIT_STRINGS (XBOXONE_CREDITS_COUNT + MILES_AND_IGGY_CREDITS_COUNT) +#elif defined(__PSVITA__) +#define MAX_CREDIT_STRINGS (PSVITA_CREDITS_COUNT + MILES_AND_IGGY_CREDITS_COUNT + DYNAMODE_FONT_CREDITS_COUNT) +#endif + +class UIScene_Credits : public UIScene +{ +private: + enum ECreditIcons + { + eCreditIcon_Iggy, + eCreditIcon_Miles, + eCreditIcon_Dolby, + }; + + static SCreditTextItemDef gs_aCreditDefs[MAX_CREDIT_STRINGS]; + + int m_iCurrDefIndex; // Index of last created text def. + int m_iNumTextDefs; // Total number of text defs in the credits. + + bool m_bAddNextLabel; + + IggyName m_funcSetNextLabel, m_funcAddImage; + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) + UI_MAP_NAME(m_funcSetNextLabel, L"SetNextLabel") + UI_MAP_NAME(m_funcAddImage, L"AddImage") + UI_END_MAP_ELEMENTS_AND_NAMES() +public: + UIScene_Credits(int iPad, void *initData, UILayer *parentLayer); + + virtual EUIScene getSceneType() { return eUIScene_Credits;} + + virtual void updateTooltips(); + virtual void updateComponents(); + + void handleReload(); + + virtual void tick(); + +protected: + // TODO: This should be pure virtual in this class + virtual wstring getMoviePath(); + +public: + // INPUT + virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled); + + virtual void handleRequestMoreData(F64 startIndex, bool up); + +private: + void setNextLabel(const wstring &label, ECreditTextTypes size); + void addImage(ECreditIcons icon); +}; diff --git a/Minecraft.Client/Common/UI/UIScene_DLCMainMenu.cpp b/Minecraft.Client/Common/UI/UIScene_DLCMainMenu.cpp new file mode 100644 index 00000000..0d36dcdf --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_DLCMainMenu.cpp @@ -0,0 +1,243 @@ +#include "stdafx.h" +#include "UI.h" +#if defined(__PS3__) || defined(__ORBIS__) +#include "Common\Network\Sony\SonyCommerce.h" +#endif +#include "UIScene_DLCMainMenu.h" + +#define PLAYER_ONLINE_TIMER_ID 0 +#define PLAYER_ONLINE_TIMER_TIME 100 + +UIScene_DLCMainMenu::UIScene_DLCMainMenu(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) +{ + // Setup all the Iggy references we need for this scene + initialiseMovie(); + // Alert the app the we want to be informed of ethernet connections + app.SetLiveLinkRequired( true ); + + m_labelOffers.init(app.GetString(IDS_DOWNLOADABLE_CONTENT_OFFERS)); + m_buttonListOffers.init(eControl_OffersList); + +#if defined _XBOX_ONE || defined __ORBIS__ + // load any local DLC images + app.LoadLocalDLCImages(); +#endif + +#if defined(__PS3__) || defined(__ORBIS__) || defined (__PSVITA__) + // show a timer on this menu + m_Timer.setVisible(true); + + m_bCategoriesShown=false; +#endif + + if(m_loadedResolution == eSceneResolution_1080) + { +#ifdef _DURANGO + m_labelXboxStore.init( app.GetString(IDS_XBOX_STORE) ); +#else + m_labelXboxStore.init( L"" ); +#endif + } + +#if defined(_DURANGO) + m_Timer.setVisible(false); + + m_buttonListOffers.addItem(app.GetString(IDS_DLC_MENU_SKINPACKS),e_DLC_SkinPack); + m_buttonListOffers.addItem(app.GetString(IDS_DLC_MENU_TEXTUREPACKS),e_DLC_TexturePacks); + m_buttonListOffers.addItem(app.GetString(IDS_DLC_MENU_MASHUPPACKS),e_DLC_MashupPacks); + + app.AddDLCRequest(e_Marketplace_Content); // content is skin packs, texture packs and mash-up packs + // we also need to mount the local DLC so we can tell what's been purchased + app.StartInstallDLCProcess(iPad); +#endif + + TelemetryManager->RecordMenuShown(iPad, eUIScene_DLCMainMenu, 0); + +#ifdef __ORBIS__ + sceNpCommerceShowPsStoreIcon(SCE_NP_COMMERCE_PS_STORE_ICON_RIGHT); +#elif defined __PSVITA__ + sceNpCommerce2ShowPsStoreIcon(SCE_NP_COMMERCE2_ICON_DISP_RIGHT); +#endif + +#if ( defined __PS3__ || defined __ORBIS__ || defined __PSVITA__ ) + addTimer( PLAYER_ONLINE_TIMER_ID, PLAYER_ONLINE_TIMER_TIME ); +#endif +} + +UIScene_DLCMainMenu::~UIScene_DLCMainMenu() +{ + // Alert the app the we no longer want to be informed of ethernet connections + app.SetLiveLinkRequired( false ); +#if defined _XBOX_ONE || defined __ORBIS__ + app.FreeLocalDLCImages(); +#endif +} + +wstring UIScene_DLCMainMenu::getMoviePath() +{ + return L"DLCMainMenu"; +} + +void UIScene_DLCMainMenu::updateTooltips() +{ + ui.SetTooltips( m_iPad, IDS_TOOLTIPS_SELECT, IDS_TOOLTIPS_BACK ); +} + +void UIScene_DLCMainMenu::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled) +{ + //app.DebugPrintf("UIScene_DebugOverlay handling input for pad %d, key %d, down- %s, pressed- %s, released- %s\n", iPad, key, down?"TRUE":"FALSE", pressed?"TRUE":"FALSE", released?"TRUE":"FALSE"); + ui.AnimateKeyPress(m_iPad, key, repeat, pressed, released); + + switch(key) + { + case ACTION_MENU_CANCEL: + if(pressed) + { +#ifdef __ORBIS__ + sceNpCommerceHidePsStoreIcon(); +#elif defined __PSVITA__ + sceNpCommerce2HidePsStoreIcon(); +#endif + navigateBack(); + } + break; + case ACTION_MENU_OK: +#ifdef __ORBIS__ + case ACTION_MENU_TOUCHPAD_PRESS: +#endif + sendInputToMovie(key, repeat, pressed, released); + break; + case ACTION_MENU_UP: + case ACTION_MENU_DOWN: + case ACTION_MENU_LEFT: + case ACTION_MENU_RIGHT: + case ACTION_MENU_PAGEUP: + case ACTION_MENU_PAGEDOWN: + sendInputToMovie(key, repeat, pressed, released); + break; + } +} + +void UIScene_DLCMainMenu::handlePress(F64 controlId, F64 childId) +{ + switch((int)controlId) + { + case eControl_OffersList: + { + int iIndex = (int)childId; + DLCOffersParam *param = new DLCOffersParam(); + param->iPad = m_iPad; + + param->iType = iIndex; + // promote the DLC content request type + + // Xbox One will have requested the marketplace content - there is only that type +#ifndef _XBOX_ONE + app.AddDLCRequest((eDLCMarketplaceType)iIndex, true); +#endif + killTimer(PLAYER_ONLINE_TIMER_ID); + ui.NavigateToScene(m_iPad, eUIScene_DLCOffersMenu, param); + break; + } + }; +} + +void UIScene_DLCMainMenu::handleTimerComplete(int id) +{ +#if ( defined __PS3__ || defined __ORBIS__ || defined __PSVITA__) + switch(id) + { + case PLAYER_ONLINE_TIMER_ID: +#ifndef _WINDOWS64 + if(ProfileManager.IsSignedInLive(ProfileManager.GetPrimaryPad())==false) + { + // check the player hasn't gone offline + // If they have, bring up the PSN warning and exit from the leaderboards + unsigned int uiIDA[1]; + uiIDA[0]=IDS_OK; + C4JStorage::EMessageResult result = ui.RequestMessageBox( IDS_CONNECTION_LOST, g_NetworkManager.CorrectErrorIDS(IDS_CONNECTION_LOST_LIVE_NO_EXIT), uiIDA,1,ProfileManager.GetPrimaryPad(),UIScene_DLCMainMenu::ExitDLCMainMenu,this, app.GetStringTable()); + } +#endif + break; + } +#endif +} + +int UIScene_DLCMainMenu::ExitDLCMainMenu(void *pParam,int iPad,C4JStorage::EMessageResult result) +{ + UIScene_DLCMainMenu* pClass = (UIScene_DLCMainMenu*)pParam; + +#ifdef __ORBIS__ + sceNpCommerceHidePsStoreIcon(); +#elif defined __PSVITA__ + sceNpCommerce2HidePsStoreIcon(); +#endif + pClass->navigateBack(); + + return 0; +} + +void UIScene_DLCMainMenu::handleGainFocus(bool navBack) +{ + UIScene::handleGainFocus(navBack); + + updateTooltips(); + + if(navBack) + { + // add the timer back in +#if ( defined __PS3__ || defined __ORBIS__ || defined __PSVITA__ ) + addTimer( PLAYER_ONLINE_TIMER_ID, PLAYER_ONLINE_TIMER_TIME ); +#endif + } +} + +void UIScene_DLCMainMenu::tick() +{ + UIScene::tick(); + +#if defined(__PS3__) || defined(__ORBIS__) || defined (__PSVITA__) + if((m_bCategoriesShown==false) && (app.GetCommerceCategoriesRetrieved())) + { + // disable the timer display on this menu + m_Timer.setVisible(false); + m_bCategoriesShown=true; + + // add the categories to the list box + SonyCommerce::CategoryInfo *pCategories=app.GetCategoryInfo(); + std::list<SonyCommerce::CategoryInfoSub>::iterator iter = pCategories->subCategories.begin(); + SonyCommerce::CategoryInfoSub category; + for(int i=0;i<pCategories->countOfSubCategories;i++) + { + // add a button in with the subcategory + category = (SonyCommerce::CategoryInfoSub)(*iter); + + string teststring=category.categoryName; + m_buttonListOffers.addItem(teststring,i); + + iter++; + } + + // set the focus to the first thing in the categories if there are any + if(pCategories->countOfSubCategories>0) + { + m_buttonListOffers.setFocus(true); + } + else + { +#if defined __ORBIS__ || defined __PSVITA__ || defined __PS3__ + app.CheckForEmptyStore(ProfileManager.GetPrimaryPad()); +#endif + // need to display text to say no downloadable content available yet + m_labelOffers.setLabel(app.GetString(IDS_NO_DLCCATEGORIES)); + +#ifdef __ORBIS__ + // 4J-JEV: TRC Requirement (R4055), need to display this system message. + ProfileManager.DisplaySystemMessage( SCE_MSG_DIALOG_SYSMSG_TYPE_TRC_EMPTY_STORE, ProfileManager.GetPrimaryPad() ); +#endif + } + + } +#endif +} + diff --git a/Minecraft.Client/Common/UI/UIScene_DLCMainMenu.h b/Minecraft.Client/Common/UI/UIScene_DLCMainMenu.h new file mode 100644 index 00000000..15272fe1 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_DLCMainMenu.h @@ -0,0 +1,50 @@ +#pragma once + +#include "UIScene.h" + +class UIScene_DLCMainMenu : public UIScene +{ +private: + enum EControls + { + eControl_OffersList, + }; + + UIControl_ButtonList m_buttonListOffers; + UIControl_Label m_labelOffers, m_labelXboxStore; + UIControl m_Timer; + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) + UI_MAP_ELEMENT( m_buttonListOffers, "OffersList") + UI_MAP_ELEMENT( m_labelOffers, "OffersList_Title") + UI_MAP_ELEMENT( m_Timer, "Timer") + if(m_loadedResolution == eSceneResolution_1080) + { + UI_MAP_ELEMENT( m_labelXboxStore, "XboxLabel" ) + } + UI_END_MAP_ELEMENTS_AND_NAMES() + + static int ExitDLCMainMenu(void *pParam,int iPad,C4JStorage::EMessageResult result); + +#if defined(__PS3__) || defined(__ORBIS__) || defined (__PSVITA__) + bool m_bCategoriesShown; +#endif + +public: + UIScene_DLCMainMenu(int iPad, void *initData, UILayer *parentLayer); + ~UIScene_DLCMainMenu(); + virtual void handleTimerComplete(int id); + virtual void handleGainFocus(bool navBack); + + virtual EUIScene getSceneType() { return eUIScene_DLCMainMenu;} + virtual void tick(); + virtual void updateTooltips(); + +protected: + // TODO: This should be pure virtual in this class + virtual wstring getMoviePath(); + +public: + // INPUT + virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled); + virtual void handlePress(F64 controlId, F64 childId); +}; diff --git a/Minecraft.Client/Common/UI/UIScene_DLCOffersMenu.cpp b/Minecraft.Client/Common/UI/UIScene_DLCOffersMenu.cpp new file mode 100644 index 00000000..9dbdc3d4 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_DLCOffersMenu.cpp @@ -0,0 +1,923 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIScene_DLCOffersMenu.h" +#include "..\..\..\Minecraft.World\StringHelpers.h" +#if defined(__PS3__) || defined(__ORBIS__) || defined (__PSVITA__) +#include "Common\Network\Sony\SonyHttp.h" +#endif + +#ifdef __PSVITA__ +#include "PSVita\Network\SonyCommerce_Vita.h" +#endif + +#define PLAYER_ONLINE_TIMER_ID 0 +#define PLAYER_ONLINE_TIMER_TIME 100 + +UIScene_DLCOffersMenu::UIScene_DLCOffersMenu(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) +{ + m_bProductInfoShown=false; + DLCOffersParam *param=(DLCOffersParam *)initData; + m_iProductInfoIndex=param->iType; + m_iCurrentDLC=0; + m_iTotalDLC=0; +#if defined(__PS3__) || defined(__ORBIS__) || defined (__PSVITA__) + m_pvProductInfo=NULL; +#endif + m_bAddAllDLCButtons=true; + + // Setup all the Iggy references we need for this scene + initialiseMovie(); + // Alert the app the we want to be informed of ethernet connections + app.SetLiveLinkRequired( true ); + + m_bIsSD=!RenderManager.IsHiDef() && !RenderManager.IsWidescreen(); + + m_labelOffers.init(app.GetString(IDS_DOWNLOADABLE_CONTENT_OFFERS)); + m_buttonListOffers.init(eControl_OffersList); + m_labelHTMLSellText.init(" "); + m_labelPriceTag.init(" "); + TelemetryManager->RecordMenuShown(m_iPad, eUIScene_DLCOffersMenu, 0); + + m_bHasPurchased = false; + m_bIsSelected = false; + + if(m_loadedResolution == eSceneResolution_1080) + { +#ifdef _DURANGO + m_labelXboxStore.init( app.GetString(IDS_XBOX_STORE) ); +#else + m_labelXboxStore.init( L"" ); +#endif + } + +#ifdef _DURANGO + m_pNoImageFor_DLC = NULL; + // If we don't yet have this DLC, we need to display a timer + m_bDLCRequiredIsRetrieved=false; + m_bIgnorePress=true; + m_bSelectionChanged=true; + // display a timer + m_Timer.setVisible(true); + +#endif + +#ifdef __ORBIS__ + //sceNpCommerceShowPsStoreIcon(SCE_NP_COMMERCE_PS_STORE_ICON_CENTER); +#endif + +#if ( defined __PS3__ || defined __ORBIS__ || defined __PSVITA__ ) + addTimer( PLAYER_ONLINE_TIMER_ID, PLAYER_ONLINE_TIMER_TIME ); +#endif + +#ifdef __PSVITA__ + ui.TouchBoxRebuild(this); +#endif +} + +UIScene_DLCOffersMenu::~UIScene_DLCOffersMenu() +{ + // Alert the app the we no longer want to be informed of ethernet connections + app.SetLiveLinkRequired( false ); +} + +void UIScene_DLCOffersMenu::handleTimerComplete(int id) +{ +#if ( defined __PS3__ || defined __ORBIS__ || defined __PSVITA__) + switch(id) + { + case PLAYER_ONLINE_TIMER_ID: +#ifndef _WINDOWS64 + if(ProfileManager.IsSignedInLive(ProfileManager.GetPrimaryPad())==false) + { + // check the player hasn't gone offline + // If they have, bring up the PSN warning and exit from the DLC menu + unsigned int uiIDA[1]; + uiIDA[0]=IDS_OK; + C4JStorage::EMessageResult result = ui.RequestMessageBox( IDS_CONNECTION_LOST, g_NetworkManager.CorrectErrorIDS(IDS_CONNECTION_LOST_LIVE_NO_EXIT), uiIDA,1,ProfileManager.GetPrimaryPad(),UIScene_DLCOffersMenu::ExitDLCOffersMenu,this, app.GetStringTable()); + } +#endif + break; + } +#endif +} + +int UIScene_DLCOffersMenu::ExitDLCOffersMenu(void *pParam,int iPad,C4JStorage::EMessageResult result) +{ + UIScene_DLCOffersMenu* pClass = (UIScene_DLCOffersMenu*)pParam; + +#ifdef __ORBIS__ + sceNpCommerceHidePsStoreIcon(); +#elif defined __PSVITA__ + sceNpCommerce2HidePsStoreIcon(); +#endif + ui.NavigateToHomeMenu();//iPad,eUIScene_MainMenu); + + return 0; +} + +wstring UIScene_DLCOffersMenu::getMoviePath() +{ + return L"DLCOffersMenu"; +} + +void UIScene_DLCOffersMenu::updateTooltips() +{ + int iA = -1; + if(m_bIsSelected) + { + if( !m_bHasPurchased ) + { + iA = IDS_TOOLTIPS_INSTALL; + } + else + { + iA = IDS_TOOLTIPS_REINSTALL; + } + } + ui.SetTooltips( m_iPad, iA,IDS_TOOLTIPS_BACK); +} + +void UIScene_DLCOffersMenu::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled) +{ + //app.DebugPrintf("UIScene_DebugOverlay handling input for pad %d, key %d, down- %s, pressed- %s, released- %s\n", iPad, key, down?"TRUE":"FALSE", pressed?"TRUE":"FALSE", released?"TRUE":"FALSE"); + ui.AnimateKeyPress(m_iPad, key, repeat, pressed, released); + + switch(key) + { + case ACTION_MENU_CANCEL: + if(pressed) + { + navigateBack(); + } + break; + case ACTION_MENU_OK: +#ifdef __ORBIS__ + case ACTION_MENU_TOUCHPAD_PRESS: +#endif + sendInputToMovie(key, repeat, pressed, released); + break; + case ACTION_MENU_UP: + if(pressed) + { + // 4J - TomK don't proceed if there is no DLC to navigate through + if(m_iTotalDLC > 0) + { + if(m_iCurrentDLC > 0) + m_iCurrentDLC--; + + m_bProductInfoShown = false; + } + } + sendInputToMovie(key, repeat, pressed, released); + break; + + case ACTION_MENU_DOWN: + if(pressed) + { + // 4J - TomK don't proceed if there is no DLC to navigate through + if(m_iTotalDLC > 0) + { + if(m_iCurrentDLC < (m_iTotalDLC - 1)) + m_iCurrentDLC++; + + m_bProductInfoShown = false; + } + } + sendInputToMovie(key, repeat, pressed, released); + break; + + case ACTION_MENU_LEFT: + /* +#ifdef _DEBUG + static int iTextC=0; + switch(iTextC) + { + case 0: + m_labelHTMLSellText.init("Voici un fantastique mini-pack de 24 apparences pour personnaliser votre personnage Minecraft et vous mettre dans l'ambiance des fêtes de fin d'année.<br><br>1-4 joueurs<br>2-8 joueurs en réseau<br><br> Cet article fait l’objet d’une licence ou d’une sous-licence de Sony Computer Entertainment America, et est soumis aux conditions générales du service du réseau, au contrat d’utilisateur, aux restrictions d’utilisation de cet article et aux autres conditions applicables, disponibles sur le site www.us.playstation.com/support/useragreements. Si vous ne souhaitez pas accepter ces conditions, ne téléchargez pas ce produit. Cet article peut être utilisé avec un maximum de deux systèmes PlayStation®3 activés associés à ce compte Sony Entertainment Network. <br><br>'Minecraft' est une marque commerciale de Notch Development AB."); + break; + case 1: + m_labelHTMLSellText.init("Un fabuloso minipack de 24 aspectos para personalizar tu personaje de Minecraft y ponerte a tono con las fiestas.<br><br>1-4 jugadores<br>2-8 jugadores en red<br><br> Sony Computer Entertainment America le concede la licencia o sublicencia de este artículo, que está sujeto a los términos de servicio y al acuerdo de usuario de la red. Las restricciones de uso de este artículo, así como otros términos aplicables, se encuentran en www.us.playstation.com/support/useragreements. Si no desea aceptar todos estos términos, no descargue este artículo. Este artículo puede usarse en hasta dos sistemas PlayStation®3 activados asociados con esta cuenta de Sony Entertainment Network. <br><br>'Minecraft' es una marca comercial de Notch Development AB."); + break; + case 2: + m_labelHTMLSellText.init("Este é um incrível pacote com 24 capas para personalizar seu personagem no Minecraft e entrar no clima de final de ano.<br><br>1-4 Jogadores<br>Jogadores em rede 2-8<br><br> Este item está sendo licenciado ou sublicenciado para você pela Sony Computer Entertainment America e está sujeito aos Termos de Serviço da Rede e Acordo do Usuário, as restrições de uso deste item e outros termos aplicáveis estão localizados em www.us.playstation.com/support/useragreements. Caso não queira aceitar todos esses termos, não baixe este item. Este item pode ser usado com até 2 sistemas PlayStation®3 ativados associados a esta Conta de Rede Sony Entertainment. <br><br>'Minecraft' é uma marca registrada da Notch Development AB"); + break; + } + iTextC++; + if(iTextC>2) iTextC=0; +#endif + */ + case ACTION_MENU_RIGHT: + case ACTION_MENU_OTHER_STICK_DOWN: + case ACTION_MENU_OTHER_STICK_UP: + // don't pass down PageUp or PageDown because this will cause conflicts between the buttonlist and scrollable html text component + //case ACTION_MENU_PAGEUP: + //case ACTION_MENU_PAGEDOWN: + sendInputToMovie(key, repeat, pressed, released); + break; + } +} + +void UIScene_DLCOffersMenu::handlePress(F64 controlId, F64 childId) +{ + switch((int)controlId) + { + case eControl_OffersList: + { +#if defined(__PS3__) || defined(__ORBIS__) || defined (__PSVITA__) + // buy the DLC + + vector<SonyCommerce::ProductInfo >::iterator it = m_pvProductInfo->begin(); + string teststring; + for(int i=0;i<childId;i++) + { + it++; + } + + SonyCommerce::ProductInfo info = *it; + +#ifdef __PS3__ + // is the item purchasable? + if(info.purchasabilityFlag==1) + { + // can be bought + app.Checkout(info.skuId); + } + else + { + if((info.annotation & (SCE_NP_COMMERCE2_SKU_ANN_PURCHASED_CANNOT_PURCHASE_AGAIN | SCE_NP_COMMERCE2_SKU_ANN_PURCHASED_CAN_PURCHASE_AGAIN))!=0) + { + app.DownloadAlreadyPurchased(info.skuId); + } + } +#else // __ORBIS__ + // is the item purchasable? + if(info.purchasabilityFlag==SCE_TOOLKIT_NP_COMMERCE_NOT_PURCHASED) + { + // can be bought + app.Checkout(info.skuId); + } + else + { + app.DownloadAlreadyPurchased(info.skuId); + } +#endif // __PS3__ +#elif defined _XBOX_ONE + int iIndex = (int)childId; + StorageManager.InstallOffer(1,StorageManager.GetOffer(iIndex).wszProductID,NULL,NULL); +#else + int iIndex = (int)childId; + + ULONGLONG ullIndexA[1]; + ullIndexA[0]=StorageManager.GetOffer(iIndex).qwOfferID; + StorageManager.InstallOffer(1,ullIndexA,NULL,NULL); +#endif + } + break; + } +} + +void UIScene_DLCOffersMenu::handleSelectionChanged(F64 selectedId) +{ + +} + +void UIScene_DLCOffersMenu::handleFocusChange(F64 controlId, F64 childId) +{ + app.DebugPrintf("UIScene_DLCOffersMenu::handleFocusChange\n"); + +#ifdef __PSVITA__ + // set this here on Vita, in case we've came from a touch screen press. Fixes bug #5794 + if((int)controlId == eControl_OffersList) + { + m_bProductInfoShown = false; + m_iCurrentDLC = (int)childId; + } +#endif + +#ifdef _DURANGO + m_bSelectionChanged=true; // to tell the tick to update the display + // 4J-PB can't call settexturename from a callback + /*if(m_buttonListOffers.hasFocus() && (childId>-1)) + { + int iIndex = (int)childId; + MARKETPLACE_CONTENTOFFER_INFO xOffer = StorageManager.GetOffer(iIndex); + UpdateDisplay(xOffer); + }*/ +#endif + +#if defined __PSVITA__ || defined __ORBIS__ + if(m_pvProductInfo) + { + m_bIsSelected = true; + vector<SonyCommerce::ProductInfo >::iterator it = m_pvProductInfo->begin(); + string teststring; + for(int i=0;i<childId;i++) + { + it++; + } + + SonyCommerce::ProductInfo info = *it; + if(info.purchasabilityFlag==SCE_TOOLKIT_NP_COMMERCE_NOT_PURCHASED) + { + m_bHasPurchased=false; + } + else + { + m_bHasPurchased=true; + } + + updateTooltips(); + } +#endif +} + +void UIScene_DLCOffersMenu::tick() +{ + UIScene::tick(); + +#if defined(__PS3__) || defined(__ORBIS__) || defined (__PSVITA__) + + if(m_bAddAllDLCButtons) + { + // need to fill out all the dlc buttons + + if((m_bProductInfoShown==false) && app.GetCommerceProductListRetrieved() && app.GetCommerceProductListInfoRetrieved()) + { + m_bAddAllDLCButtons=false; + // add the categories to the list box + if(m_pvProductInfo==NULL) + { + m_pvProductInfo=app.GetProductList(m_iProductInfoIndex); + if(m_pvProductInfo==NULL) + { + m_iTotalDLC=0; + // need to display text to say no downloadable content available yet + m_labelOffers.setLabel(app.GetString(IDS_NO_DLCCATEGORIES)); + + m_bProductInfoShown=true; + return; + } + else m_iTotalDLC=m_pvProductInfo->size(); + } + + vector<SonyCommerce::ProductInfo >::iterator it = m_pvProductInfo->begin(); + string teststring; + bool bFirstItemSet=false; + for(int i=0;i<m_iTotalDLC;i++) + { + SonyCommerce::ProductInfo info = *it; + + if(strncmp(info.productName,"Minecraft ",10)==0) + { + teststring=&info.productName[10]; + + } + else + { + teststring=info.productName; + } + + bool bDLCIsAvailable=false; + +#ifdef __PS3__ + // is the item purchasable? + if(info.purchasabilityFlag==1) + { + // can be bought + app.DebugPrintf("Adding DLC (%s) - not bought\n",teststring.c_str()); + m_buttonListOffers.addItem(teststring,false,i); + bDLCIsAvailable=true; + } + else + { + if((info.annotation & (SCE_NP_COMMERCE2_SKU_ANN_PURCHASED_CANNOT_PURCHASE_AGAIN | SCE_NP_COMMERCE2_SKU_ANN_PURCHASED_CAN_PURCHASE_AGAIN))!=0) + { + app.DebugPrintf("Adding DLC (%s) - bought\n",teststring.c_str()); + m_buttonListOffers.addItem(teststring,true,i); + bDLCIsAvailable=true; + } + } +#else // __ORBIS__ + // is the item purchasable? + if(info.purchasabilityFlag==SCE_TOOLKIT_NP_COMMERCE_NOT_PURCHASED) + { + // can be bought + m_buttonListOffers.addItem(teststring,false,i); + bDLCIsAvailable=true; + } + else + { + m_buttonListOffers.addItem(teststring,true,i); + bDLCIsAvailable=true; + } +#endif // __PS3__ + + // set the other details for the first item + if(bDLCIsAvailable && (bFirstItemSet==false)) + { + bFirstItemSet=true; + + // 4J-PB - info.longDescription isn't null terminated + char chLongDescription[SCE_NP_COMMERCE2_PRODUCT_LONG_DESCRIPTION_LEN+1]; + memcpy(chLongDescription,info.longDescription,SCE_NP_COMMERCE2_PRODUCT_LONG_DESCRIPTION_LEN); + chLongDescription[SCE_NP_COMMERCE2_PRODUCT_LONG_DESCRIPTION_LEN]=0; + m_labelHTMLSellText.setLabel(chLongDescription); + + if(info.ui32Price==0) + { + m_labelPriceTag.setLabel(app.GetString(IDS_DLC_PRICE_FREE)); + } + else + { + teststring=info.price; + m_labelPriceTag.setLabel(teststring); + } + + // get the image - if we haven't already + wstring textureName = filenametowstring(info.imageUrl); + + if(hasRegisteredSubstitutionTexture(textureName)==false) + { + PBYTE pbImageData; + int iImageDataBytes=0; + bool bDeleteData; +#ifdef __ORBIS__ + // check the local files first + SONYDLC *pSONYDLCInfo=app.GetSONYDLCInfoFromKeyname(info.productId); + + // does the DLC info have an image? + if(pSONYDLCInfo->dwImageBytes!=0) + { + pbImageData=pSONYDLCInfo->pbImageData; + iImageDataBytes=pSONYDLCInfo->dwImageBytes; + bDeleteData=false; // we'll clean up the local LDC images + } + else +#endif + if(info.imageUrl[0]!=0) + { + SonyHttp::getDataFromURL(info.imageUrl,(void **)&pbImageData,&iImageDataBytes); + bDeleteData=true; + } + + if(iImageDataBytes!=0) + { + // set the image + registerSubstitutionTexture(textureName,pbImageData,iImageDataBytes,bDeleteData); + m_bitmapIconOfferImage.setTextureName(textureName); + // 4J Stu - Don't delete this + //delete [] pbImageData; + } + else + { + m_bitmapIconOfferImage.setTextureName(L""); + } + } + else + { + m_bitmapIconOfferImage.setTextureName(textureName); + } + } + it++; + } + + if(bFirstItemSet==false) + { + // we were not able to add any items to the list + m_labelOffers.setLabel(app.GetString(IDS_NO_DLCCATEGORIES)); + } + else + { + // set the focus to the first thing in the categories if there are any + if(m_pvProductInfo->size()>0) + { + m_buttonListOffers.setFocus(true); + } + else + { + // need to display text to say no downloadable content available yet + m_labelOffers.setLabel(app.GetString(IDS_NO_DLCCATEGORIES)); + } + } + + m_Timer.setVisible(false); + m_bProductInfoShown=true; + } + } + else + { +#ifdef __PSVITA__ + // MGH - fixes bug 5768 on Vita - should be extended properly to work for other platforms + if((SonyCommerce_Vita::getPurchasabilityUpdated()) && app.GetCommerceProductListRetrieved()&& app.GetCommerceProductListInfoRetrieved() && m_iTotalDLC > 0) + { + + { + vector<SonyCommerce::ProductInfo >::iterator it = m_pvProductInfo->begin(); + for(int i=0;i<m_iTotalDLC;i++) + { + SonyCommerce::ProductInfo info = *it; + // is the item purchasable? + if(info.purchasabilityFlag==SCE_TOOLKIT_NP_COMMERCE_NOT_PURCHASED) + { + // can be bought + m_buttonListOffers.showTick(i, false); + } + else + { + m_buttonListOffers.showTick(i, true); + } + it++; + } + } + } +#endif + + + // just update the details based on what the current selection is / TomK-4J - don't proceed if total DLC is 0 (bug 4757) + if((m_bProductInfoShown==false) && app.GetCommerceProductListRetrieved()&& app.GetCommerceProductListInfoRetrieved() && m_iTotalDLC > 0) + { + + + vector<SonyCommerce::ProductInfo >::iterator it = m_pvProductInfo->begin(); + string teststring; + for(int i=0;i<m_iCurrentDLC;i++) + { + it++; + } + + SonyCommerce::ProductInfo info = *it; + + // 4J-PB - info.longDescription isn't null terminated + char chLongDescription[SCE_NP_COMMERCE2_PRODUCT_LONG_DESCRIPTION_LEN+1]; + memcpy(chLongDescription,info.longDescription,SCE_NP_COMMERCE2_PRODUCT_LONG_DESCRIPTION_LEN); + chLongDescription[SCE_NP_COMMERCE2_PRODUCT_LONG_DESCRIPTION_LEN]=0; + m_labelHTMLSellText.setLabel(chLongDescription); + + if(info.ui32Price==0) + { + m_labelPriceTag.setLabel(app.GetString(IDS_DLC_PRICE_FREE)); + } + else + { + teststring=info.price; + m_labelPriceTag.setLabel(teststring); + } + + // get the image + + // then retrieve from the web + wstring textureName = filenametowstring(info.imageUrl); + + if(hasRegisteredSubstitutionTexture(textureName)==false) + { + PBYTE pbImageData; + int iImageDataBytes=0; + bool bDeleteData; +#ifdef __ORBIS__ + // check the local files first + SONYDLC *pSONYDLCInfo=app.GetSONYDLCInfoFromKeyname(info.productId); + + // does the DLC info have an image? + if(pSONYDLCInfo->dwImageBytes!=0) + { + pbImageData=pSONYDLCInfo->pbImageData; + iImageDataBytes=pSONYDLCInfo->dwImageBytes; + bDeleteData=false; // we'll clean up the local LDC images + } + else +#endif + { + SonyHttp::getDataFromURL(info.imageUrl,(void **)&pbImageData,&iImageDataBytes); + bDeleteData=true; + } + + if(iImageDataBytes!=0) + { + // set the image + registerSubstitutionTexture(textureName,pbImageData,iImageDataBytes, bDeleteData); + m_bitmapIconOfferImage.setTextureName(textureName); + + // 4J Stu - Don't delete this + //delete [] pbImageData; + } + else + { + m_bitmapIconOfferImage.setTextureName(L""); + } + } + else + { + m_bitmapIconOfferImage.setTextureName(textureName); + } + m_bProductInfoShown=true; + m_Timer.setVisible(false); + } + + } +#elif defined _XBOX_ONE + if(m_bAddAllDLCButtons) + { + // Is the DLC we're looking for available? + if(!m_bDLCRequiredIsRetrieved) + { + // DLCContentRetrieved is to see if the type of content has been retrieved - and on Durango there is only type 0 - XMARKETPLACE_OFFERING_TYPE_CONTENT + if(app.DLCContentRetrieved(e_Marketplace_Content)) + { + m_bDLCRequiredIsRetrieved=true; + + // Retrieve the info + GetDLCInfo(app.GetDLCOffersCount(), false); + m_bIgnorePress=false; + m_bAddAllDLCButtons=false; + + // hide the timer + m_Timer.setVisible(false); + } + } + } + + // have to wait until we have the offers + if(m_bSelectionChanged && m_bDLCRequiredIsRetrieved) + { + // need to update text and icon + if(m_buttonListOffers.hasFocus() && (getControlChildFocus()>-1)) + { + int iIndex = getControlChildFocus(); + MARKETPLACE_CONTENTOFFER_INFO xOffer = StorageManager.GetOffer(iIndex); + + if(UpdateDisplay(xOffer)) + { + // image was available + m_bSelectionChanged=false; + } + } + } + +// if(m_bBitmapOfferIconDisplayed==false) +// { +// // do we have it yet? +// if +// } + // retrieve the icons for the DLC +// if(m_vIconRetrieval.size()>0) +// { +// // for each icon, request it, and remove it from the list +// // the callback for the retrieval will update the display if needed +// +// AUTO_VAR(itEnd, m_vIconRetrieval.end()); +// for (AUTO_VAR(it, m_vIconRetrieval.begin()); it != itEnd; it++) +// { +// +// } +// +// } +#endif +} + +#if defined _XBOX_ONE +void UIScene_DLCOffersMenu::GetDLCInfo( int iOfferC, bool bUpdateOnly ) +{ + MARKETPLACE_CONTENTOFFER_INFO xOffer; + int iCount=0; + bool bNoDLCToDisplay = true; + unsigned int uiDLCCount=0; + + + if(bUpdateOnly) // Just update the info on the current list + { + + } + else + { + // clear out the list + m_buttonListOffers.clearList(); + + // need to reorder the DLC display according to dlc uiSortIndex + SORTINDEXSTRUCT *OrderA = new SORTINDEXSTRUCT [iOfferC]; + + for(int i = 0; i < iOfferC; i++) + { + xOffer = StorageManager.GetOffer(i); + // Check that this is in the list of known DLC + DLC_INFO *pDLC=app.GetDLCInfoForFullOfferID(xOffer.wszProductID); + + if(pDLC!=NULL) + { + OrderA[uiDLCCount].uiContentIndex=i; + OrderA[uiDLCCount++].uiSortIndex=pDLC->uiSortIndex; + } + else + { + app.DebugPrintf("Unknown offer - %ls\n",xOffer.wszOfferName); + } + } + + qsort( OrderA, uiDLCCount, sizeof(SORTINDEXSTRUCT), OrderSortFunction ); + + for(int i = 0; i < uiDLCCount; i++) + { + xOffer = StorageManager.GetOffer(OrderA[i].uiContentIndex); + + // Check that this is in the list of known DLC + DLC_INFO *pDLC=app.GetDLCInfoForFullOfferID(xOffer.wszProductID); + + if(pDLC==NULL) + { + // skip this one + app.DebugPrintf("Unknown offer - %ls\n",xOffer.wszOfferName); + continue; + } + + if(pDLC->eDLCType==(eDLCContentType)m_iProductInfoIndex) + { + wstring wstrTemp=xOffer.wszOfferName; + + // 4J-PB - Rog requested we remove the Minecraft at the start of the name. It's required for the Bing search, but gets in the way here + app.DebugPrintf("Adding %ls at %d\n",wstrTemp.c_str(), i); + + if(wcsncmp(L"Minecraft ",wstrTemp.c_str(),10)==0) + { + app.DebugPrintf("Removing Minecraft from name\n"); + WCHAR *pwchNewName=(WCHAR *)wstrTemp.c_str(); + wstrTemp=&pwchNewName[10]; + } + +#ifdef _XBOX_ONE + // 4J-PB - the hasPurchased comes from the local installed package info + // find the DLC in the installed packages + XCONTENT_DATA *pContentData=StorageManager.GetInstalledDLC(xOffer.wszProductID); + + if(pContentData!=NULL) + { + m_buttonListOffers.addItem(wstrTemp,!pContentData->bTrialLicense,OrderA[i].uiContentIndex); + } + else + { + m_buttonListOffers.addItem(wstrTemp,false,OrderA[i].uiContentIndex); + } +#else + m_buttonListOffers.addItem(wstrTemp,xOffer.fUserHasPurchased,OrderA[i].uiContentIndex); +#endif + + // add the required image to the retrieval queue + m_vIconRetrieval.push_back(pDLC->wchBanner); + + /** 4J JEV: + * We've filtered results out from the list, need to keep track + * of the 'actual' list index. + */ + iCount++; + } + } + + + // Check if there is nothing to display, and display the default "nothing available at this time" + if(iCount>0) + { + bNoDLCToDisplay=false; + xOffer = StorageManager.GetOffer(OrderA[0].uiContentIndex); + //m_buttonListOffers.setCurrentSelection(0); + + UpdateDisplay(xOffer); + } + delete OrderA; + } + + // turn off the timer display + //m_Timer.SetShow(FALSE); + if(bNoDLCToDisplay) + { + // set the default text + + wchar_t formatting[40]; + wstring wstrTemp = app.GetString(IDS_NO_DLCOFFERS); +// swprintf(formatting, 40, L"<font size=\"%d\">", m_bIsSD?12:14); +// wstrTemp = formatting + wstrTemp; + + m_labelHTMLSellText.setLabel(wstrTemp); + m_labelPriceTag.setVisible(false); + } +} + +int UIScene_DLCOffersMenu::OrderSortFunction(const void* a, const void* b) +{ + return ((SORTINDEXSTRUCT*)b)->uiSortIndex - ((SORTINDEXSTRUCT*)a)->uiSortIndex; +} + +void UIScene_DLCOffersMenu::UpdateTooltips(MARKETPLACE_CONTENTOFFER_INFO& xOffer) +{ + m_bHasPurchased = xOffer.fUserHasPurchased; + m_bIsSelected = true; + updateTooltips(); +} + +bool UIScene_DLCOffersMenu::UpdateDisplay(MARKETPLACE_CONTENTOFFER_INFO& xOffer) +{ + bool bImageAvailable=false; +#ifdef _XBOX_ONE + DLC_INFO *dlc = app.GetDLCInfoForFullOfferID(xOffer.wszProductID); +#else + DLC_INFO *dlc = app.GetDLCInfoForFullOfferID(xOffer.wszOfferName); +#endif + + if (dlc != NULL) + { + WCHAR *cString = dlc->wchBanner; + + + // is the file in the local DLC images? + // is the file in the TMS XZP? + //int iIndex = app.GetLocalTMSFileIndex(cString, true); + + if(dlc->dwImageBytes!=0) + { + //app.LoadLocalTMSFile(cString); + + // set the image - no delete + registerSubstitutionTexture(cString,dlc->pbImageData,dlc->dwImageBytes,false); + m_bitmapIconOfferImage.setTextureName(cString); + bImageAvailable=true; + } + else + { + bool bPresent = app.IsFileInMemoryTextures(cString); + if (!bPresent) + { + // Image has not come in yet + // Set the item monitored in the timer, so we can set the image when it comes in + m_pNoImageFor_DLC=dlc; + + app.AddTMSPPFileTypeRequest(dlc->eDLCType,true); + bImageAvailable=false; + //m_bitmapIconOfferImage.setTextureName(L""); + } + else + { + if(hasRegisteredSubstitutionTexture(cString)==false) + { + BYTE *pData=NULL; + DWORD dwSize=0; + app.GetMemFileDetails(cString,&pData,&dwSize); + // set the image +#ifdef _XBOX_ONE + registerSubstitutionTexture(cString,pData,dwSize); +#else + registerSubstitutionTexture(cString,pData,dwSize,true); +#endif + m_bitmapIconOfferImage.setTextureName(cString); + } + else + { + m_bitmapIconOfferImage.setTextureName(cString); + } + bImageAvailable=true; + } + } + + m_labelHTMLSellText.setLabel(xOffer.wszSellText); + + // set the price info + m_labelPriceTag.setVisible(true); + m_labelPriceTag.setLabel(xOffer.wszCurrencyPrice); + + UpdateTooltips(xOffer); + } + else + { + wchar_t formatting[40]; + wstring wstrTemp = app.GetString(IDS_NO_DLCOFFERS); + m_labelHTMLSellText.setLabel(wstrTemp.c_str()); + m_labelPriceTag.setVisible(false); + } + + return bImageAvailable; +} +#endif + +#ifdef _XBOX_ONE +void UIScene_DLCOffersMenu::HandleDLCLicenseChange() +{ + // flag an update of the display + int iOfferC=app.GetDLCOffersCount(); + + GetDLCInfo(iOfferC,false); +} +#endif // _XBOX_ONE + +#ifdef __PS3__ +void UIScene_DLCOffersMenu::HandleDLCInstalled() +{ + app.DebugPrintf(4,"UIScene_DLCOffersMenu::HandleDLCInstalled\n"); + +// m_buttonListOffers.clearList(); +// m_bAddAllDLCButtons=true; +// m_bProductInfoShown=false; +} + +// void UIScene_DLCOffersMenu::HandleDLCMountingComplete() +// { +// app.DebugPrintf(4,"UIScene_SkinSelectMenu::HandleDLCMountingComplete\n"); +//} + + +#endif
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIScene_DLCOffersMenu.h b/Minecraft.Client/Common/UI/UIScene_DLCOffersMenu.h new file mode 100644 index 00000000..c5fcac7e --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_DLCOffersMenu.h @@ -0,0 +1,96 @@ +#pragma once + +#include "UIScene.h" + +class UIScene_DLCOffersMenu : public UIScene +{ +private: + enum EControls + { + eControl_OffersList, + }; + + bool m_bIsSD; + bool m_bHasPurchased; + bool m_bIsSelected; + + UIControl_DLCList m_buttonListOffers; + UIControl_Label m_labelOffers, m_labelPriceTag, m_labelXboxStore; + UIControl_HTMLLabel m_labelHTMLSellText; + UIControl_BitmapIcon m_bitmapIconOfferImage; + UIControl m_Timer; + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) + UI_MAP_ELEMENT( m_buttonListOffers, "OffersList") + UI_MAP_ELEMENT( m_labelOffers, "OffersList_Title") + UI_MAP_ELEMENT( m_labelPriceTag, "PriceTag") + UI_MAP_ELEMENT( m_labelHTMLSellText, "HTMLSellText") + UI_MAP_ELEMENT( m_bitmapIconOfferImage, "DLCIcon" ) + UI_MAP_ELEMENT( m_Timer, "Timer") + + if(m_loadedResolution == eSceneResolution_1080) + { + UI_MAP_ELEMENT( m_labelXboxStore, "XboxLabel" ) + } + UI_END_MAP_ELEMENTS_AND_NAMES() +public: + UIScene_DLCOffersMenu(int iPad, void *initData, UILayer *parentLayer); + ~UIScene_DLCOffersMenu(); + static int ExitDLCOffersMenu(void *pParam,int iPad,C4JStorage::EMessageResult result); + + virtual EUIScene getSceneType() { return eUIScene_DLCOffersMenu;} + virtual void tick(); + virtual void updateTooltips(); + +protected: + // TODO: This should be pure virtual in this class + virtual wstring getMoviePath(); + +public: + // INPUT + virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled); + + virtual void handlePress(F64 controlId, F64 childId); + virtual void handleSelectionChanged(F64 selectedId); + virtual void handleFocusChange(F64 controlId, F64 childId); + virtual void handleTimerComplete(int id); +#ifdef __PS3__ + virtual void HandleDLCInstalled(); +#endif + +#ifdef _XBOX_ONE + virtual void HandleDLCLicenseChange(); +#endif + +private: +#ifdef _DURANGO + void GetDLCInfo( int iOfferC, bool bUpdateOnly=false ); + void UpdateTooltips(MARKETPLACE_CONTENTOFFER_INFO& xOffer); + bool UpdateDisplay(MARKETPLACE_CONTENTOFFER_INFO& xOffer); + + static int OrderSortFunction(const void* a, const void* b); + + bool m_bIgnorePress; + bool m_bDLCRequiredIsRetrieved; + DLC_INFO *m_pNoImageFor_DLC; + + typedef struct + { + unsigned int uiContentIndex; + unsigned int uiSortIndex; + } + SORTINDEXSTRUCT; + + vector <wstring>m_vIconRetrieval; + bool m_bSelectionChanged; + +#endif + + bool m_bProductInfoShown; + int m_iProductInfoIndex; + int m_iCurrentDLC; + int m_iTotalDLC; + bool m_bAddAllDLCButtons; +#if defined(__PS3__) || defined(__ORBIS__) || defined (__PSVITA__) + std::vector<SonyCommerce::ProductInfo>*m_pvProductInfo; +#endif +}; diff --git a/Minecraft.Client/Common/UI/UIScene_DeathMenu.cpp b/Minecraft.Client/Common/UI/UIScene_DeathMenu.cpp new file mode 100644 index 00000000..2026bfca --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_DeathMenu.cpp @@ -0,0 +1,191 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIScene_DeathMenu.h" +#include "IUIScene_PauseMenu.h" +#include "..\..\Minecraft.h" +#include "..\..\MultiplayerLocalPlayer.h" + +UIScene_DeathMenu::UIScene_DeathMenu(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) +{ + // Setup all the Iggy references we need for this scene + initialiseMovie(); + + m_buttonRespawn.init(app.GetString(IDS_RESPAWN),eControl_Respawn); + m_buttonExitGame.init(app.GetString(IDS_EXIT_GAME),eControl_ExitGame); + + m_labelTitle.setLabel(app.GetString(IDS_YOU_DIED)); + + m_bIgnoreInput = false; + + Minecraft *pMinecraft = Minecraft::GetInstance(); + if(pMinecraft != NULL && pMinecraft->localgameModes[iPad] != NULL ) + { + TutorialMode *gameMode = (TutorialMode *)pMinecraft->localgameModes[iPad]; + + // This just allows it to be shown + gameMode->getTutorial()->showTutorialPopup(false); + } +} + +UIScene_DeathMenu::~UIScene_DeathMenu() +{ + Minecraft *pMinecraft = Minecraft::GetInstance(); + if(pMinecraft != NULL && pMinecraft->localgameModes[m_iPad] != NULL ) + { + TutorialMode *gameMode = (TutorialMode *)pMinecraft->localgameModes[m_iPad]; + + // This just allows it to be shown + gameMode->getTutorial()->showTutorialPopup(true); + } +} + +wstring UIScene_DeathMenu::getMoviePath() +{ + if(app.GetLocalPlayerCount() > 1) + { + return L"DeathMenuSplit"; + } + else + { + return L"DeathMenu"; + } +} + +void UIScene_DeathMenu::updateTooltips() +{ + ui.SetTooltips( m_iPad, IDS_TOOLTIPS_SELECT); +} + +void UIScene_DeathMenu::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled) +{ + if(m_bIgnoreInput) return; + + ui.AnimateKeyPress(m_iPad, key, repeat, pressed, released); + + switch(key) + { + case ACTION_MENU_CANCEL: + handled = true; + break; + case ACTION_MENU_OK: +#ifdef __ORBIS__ + case ACTION_MENU_TOUCHPAD_PRESS: +#endif + case ACTION_MENU_UP: + case ACTION_MENU_DOWN: + sendInputToMovie(key, repeat, pressed, released); + handled = true; + break; + } +} + +void UIScene_DeathMenu::handlePress(F64 controlId, F64 childId) +{ + switch((int)controlId) + { + case eControl_Respawn: + m_bIgnoreInput = true; + app.SetAction(m_iPad,eAppAction_Respawn); +#ifdef _DURANGO + //InputManager.SetEnabledGtcButtons(_360_GTC_MENU|_360_GTC_PAUSE|_360_GTC_VIEW); +#endif + break; + case eControl_ExitGame: + { + Minecraft *pMinecraft=Minecraft::GetInstance(); + // 4J-PB - fix for #8333 - BLOCKER: If player decides to exit game, then cancels the exit player becomes stuck at game over screen + //m_bIgnoreInput = true; + // Check if it's the trial version + if(ProfileManager.IsFullVersion()) + { + + // is it the primary player exiting? + if(m_iPad==ProfileManager.GetPrimaryPad()) + { + UINT uiIDA[3]; + int playTime = -1; + if( pMinecraft->localplayers[m_iPad] != NULL ) + { + playTime = (int)pMinecraft->localplayers[m_iPad]->getSessionTimer(); + } + TelemetryManager->RecordLevelExit(m_iPad, eSen_LevelExitStatus_Failed); + +#if defined (_XBOX_ONE) || defined(__ORBIS__) + if(g_NetworkManager.IsHost() && StorageManager.GetSaveDisabled()) + { + uiIDA[0]=IDS_CONFIRM_CANCEL; + uiIDA[1]=IDS_EXIT_GAME_SAVE; + uiIDA[2]=IDS_EXIT_GAME_NO_SAVE; + + ui.RequestMessageBox(IDS_EXIT_GAME, IDS_CONFIRM_EXIT_GAME, uiIDA, 3, m_iPad,&IUIScene_PauseMenu::ExitGameSaveDialogReturned,this, app.GetStringTable(), 0, 0, false); + } + else + { + uiIDA[0]=IDS_CONFIRM_CANCEL; + uiIDA[1]=IDS_CONFIRM_OK; + ui.RequestMessageBox(IDS_EXIT_GAME, IDS_CONFIRM_EXIT_GAME, uiIDA, 2, m_iPad,&IUIScene_PauseMenu::ExitGameDialogReturned,this, app.GetStringTable(), 0, 0, false); + } + +#else + if(StorageManager.GetSaveDisabled()) + { + uiIDA[0]=IDS_CONFIRM_CANCEL; + uiIDA[1]=IDS_CONFIRM_OK; + ui.RequestMessageBox(IDS_EXIT_GAME, IDS_CONFIRM_EXIT_GAME_PROGRESS_LOST, uiIDA, 2, m_iPad,&IUIScene_PauseMenu::ExitGameDialogReturned,this, app.GetStringTable(), 0, 0, false); + } + else + { + if( g_NetworkManager.IsHost() ) + { + uiIDA[0]=IDS_CONFIRM_CANCEL; + uiIDA[1]=IDS_EXIT_GAME_SAVE; + uiIDA[2]=IDS_EXIT_GAME_NO_SAVE; + + ui.RequestMessageBox(IDS_EXIT_GAME, IDS_CONFIRM_EXIT_GAME, uiIDA, 3, m_iPad,&IUIScene_PauseMenu::ExitGameSaveDialogReturned,this, app.GetStringTable(), 0, 0, false); + } + else + { + uiIDA[0]=IDS_CONFIRM_CANCEL; + uiIDA[1]=IDS_CONFIRM_OK; + + ui.RequestMessageBox(IDS_EXIT_GAME, IDS_CONFIRM_EXIT_GAME, uiIDA, 2, m_iPad,&IUIScene_PauseMenu::ExitGameDialogReturned,this, app.GetStringTable(), 0, 0, false); + } + } +#endif + } + else + { + TelemetryManager->RecordLevelExit(m_iPad, eSen_LevelExitStatus_Failed); + + // just exit the player + app.SetAction(m_iPad,eAppAction_ExitPlayer); + } + } + else + { + // is it the primary player exiting? + if(m_iPad==ProfileManager.GetPrimaryPad()) + { + TelemetryManager->RecordLevelExit(m_iPad, eSen_LevelExitStatus_Failed); + + // adjust the trial time played + ui.ReduceTrialTimerValue(); + + // exit the level + UINT uiIDA[2]; + uiIDA[0]=IDS_CONFIRM_CANCEL; + uiIDA[1]=IDS_CONFIRM_OK; + ui.RequestMessageBox(IDS_EXIT_GAME, IDS_CONFIRM_EXIT_GAME_PROGRESS_LOST, uiIDA, 2, m_iPad,&IUIScene_PauseMenu::ExitGameDialogReturned,this, app.GetStringTable(), 0, 0, false); + } + else + { + TelemetryManager->RecordLevelExit(m_iPad, eSen_LevelExitStatus_Failed); + + // just exit the player + app.SetAction(m_iPad,eAppAction_ExitPlayer); + } + } + } + break; + } +}
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIScene_DeathMenu.h b/Minecraft.Client/Common/UI/UIScene_DeathMenu.h new file mode 100644 index 00000000..7285e413 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_DeathMenu.h @@ -0,0 +1,44 @@ +#pragma once + +#include "UIScene.h" + +class UIScene_DeathMenu : public UIScene +{ +private: + enum EControls + { + eControl_Respawn, + eControl_ExitGame + }; + + bool m_bIgnoreInput; + + UIControl_Button m_buttonRespawn, m_buttonExitGame; + UIControl_Label m_labelTitle; + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) + UI_MAP_ELEMENT( m_buttonRespawn, "Respawn") + UI_MAP_ELEMENT( m_buttonExitGame, "ExitGame") + UI_MAP_ELEMENT( m_labelTitle, "Title") + UI_END_MAP_ELEMENTS_AND_NAMES() +public: + UIScene_DeathMenu(int iPad, void *initData, UILayer *parentLayer); + virtual ~UIScene_DeathMenu(); + + virtual EUIScene getSceneType() { return eUIScene_DeathMenu;} + virtual void updateTooltips(); + +protected: + // TODO: This should be pure virtual in this class + virtual wstring getMoviePath(); + +public: + // INPUT + virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled); + +protected: + void handlePress(F64 controlId, F64 childId); + +#ifdef _DURANGO + virtual long long getDefaultGtcButtons() { return 0; } +#endif +}; diff --git a/Minecraft.Client/Common/UI/UIScene_DebugCreateSchematic.cpp b/Minecraft.Client/Common/UI/UIScene_DebugCreateSchematic.cpp new file mode 100644 index 00000000..2a8ac9f8 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_DebugCreateSchematic.cpp @@ -0,0 +1,216 @@ +#include "stdafx.h" + +#ifdef _DEBUG_MENUS_ENABLED +#include "UI.h" +#include "UIScene_DebugCreateSchematic.h" +#include "Minecraft.h" +#include "..\..\..\Minecraft.World\StringHelpers.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.level.h" + +UIScene_DebugCreateSchematic::UIScene_DebugCreateSchematic(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) +{ + // Setup all the Iggy references we need for this scene + initialiseMovie(); + + m_labelTitle.init(L"Name"); + m_labelStartX.init(L"StartX"); + m_labelStartY.init(L"StartY"); + m_labelStartZ.init(L"StartZ"); + m_labelEndX.init(L"EndX"); + m_labelEndY.init(L"EndY"); + m_labelEndZ.init(L"EndZ"); + + m_textInputStartX.init(L"",eControl_StartX); + m_textInputStartY.init(L"",eControl_StartY); + m_textInputStartZ.init(L"",eControl_StartZ); + m_textInputEndX.init(L"",eControl_EndX); + m_textInputEndY.init(L"",eControl_EndY); + m_textInputEndZ.init(L"",eControl_EndZ); + m_textInputName.init(L"",eControl_Name); + + m_checkboxSaveMobs.init(L"Save Mobs", eControl_SaveMobs,false); + m_checkboxUseCompression.init(L"Use Compression", eControl_UseCompression, false); + + m_buttonCreate.init(L"Create",eControl_Create); + + m_data = new ConsoleSchematicFile::XboxSchematicInitParam(); +} + +wstring UIScene_DebugCreateSchematic::getMoviePath() +{ + return L"DebugCreateSchematic"; +} + +void UIScene_DebugCreateSchematic::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled) +{ + ui.AnimateKeyPress(iPad, key, repeat, pressed, released); + + switch(key) + { + case ACTION_MENU_CANCEL: + if(pressed) + { + navigateBack(); + } + break; + case ACTION_MENU_OK: + case ACTION_MENU_UP: + case ACTION_MENU_DOWN: + case ACTION_MENU_PAGEUP: + case ACTION_MENU_PAGEDOWN: + case ACTION_MENU_LEFT: + case ACTION_MENU_RIGHT: + sendInputToMovie(key, repeat, pressed, released); + break; + } +} + +void UIScene_DebugCreateSchematic::handlePress(F64 controlId, F64 childId) +{ + switch((int)controlId) + { + case eControl_Create: + { + // We want the start to be even + if(m_data->startX > 0 && m_data->startX%2 != 0) + m_data->startX-=1; + else if(m_data->startX < 0 && m_data->startX%2 !=0) + m_data->startX-=1; + if(m_data->startY < 0) m_data->startY = 0; + else if(m_data->startY > 0 && m_data->startY%2 != 0) + m_data->startY-=1; + if(m_data->startZ > 0 && m_data->startZ%2 != 0) + m_data->startZ-=1; + else if(m_data->startZ < 0 && m_data->startZ%2 !=0) + m_data->startZ-=1; + + // We want the end to be odd to have a total size that is even + if(m_data->endX > 0 && m_data->endX%2 == 0) + m_data->endX+=1; + else if(m_data->endX < 0 && m_data->endX%2 ==0) + m_data->endX+=1; + if(m_data->endY > Level::maxBuildHeight) + m_data->endY = Level::maxBuildHeight; + else if(m_data->endY > 0 && m_data->endY%2 == 0) + m_data->endY+=1; + else if(m_data->endY < 0 && m_data->endY%2 ==0) + m_data->endY+=1; + if(m_data->endZ > 0 && m_data->endZ%2 == 0) + m_data->endZ+=1; + else if(m_data->endZ < 0 && m_data->endZ%2 ==0) + m_data->endZ+=1; + + app.SetXuiServerAction(ProfileManager.GetPrimaryPad(), eXuiServerAction_ExportSchematic, (void *)m_data); + + navigateBack(); + } + break; + case eControl_Name: + case eControl_StartX: + case eControl_StartY: + case eControl_StartZ: + case eControl_EndX: + case eControl_EndY: + case eControl_EndZ: + m_keyboardCallbackControl = (eControls)((int)controlId); + InputManager.RequestKeyboard(L"Enter something",L"",(DWORD)0,25,&UIScene_DebugCreateSchematic::KeyboardCompleteCallback,this,C_4JInput::EKeyboardMode_Default); + break; + }; +} + +void UIScene_DebugCreateSchematic::handleCheckboxToggled(F64 controlId, bool selected) +{ + switch((int)controlId) + { + case eControl_SaveMobs: + m_data->bSaveMobs = selected; + break; + case eControl_UseCompression: + if (selected) + m_data->compressionType = APPROPRIATE_COMPRESSION_TYPE; + else + m_data->compressionType = Compression::eCompressionType_RLE; + break; + } +} + +int UIScene_DebugCreateSchematic::KeyboardCompleteCallback(LPVOID lpParam,bool bRes) +{ + UIScene_DebugCreateSchematic *pClass=(UIScene_DebugCreateSchematic *)lpParam; + + uint16_t pchText[128]; + ZeroMemory(pchText, 128 * sizeof(uint16_t) ); + InputManager.GetText(pchText); + + if(pchText[0]!=0) + { + wstring value = (wchar_t *)pchText; + int iVal = 0; + if(!value.empty()) iVal = _fromString<int>( value ); + switch(pClass->m_keyboardCallbackControl) + { + case eControl_Name: + pClass->m_textInputName.setLabel(value); + if(!value.empty()) + { + swprintf(pClass->m_data->name,64,L"%ls", value.c_str()); + } + else + { + swprintf(pClass->m_data->name,64,L"schematic"); + } + break; + case eControl_StartX: + pClass->m_textInputStartX.setLabel(value); + + if( iVal >= (LEVEL_MAX_WIDTH * -16) || iVal < (LEVEL_MAX_WIDTH * 16)) + { + pClass->m_data->startX = iVal; + } + break; + case eControl_StartY: + pClass->m_textInputStartY.setLabel(value); + + if( iVal >= (LEVEL_MAX_WIDTH * -16) || iVal < (LEVEL_MAX_WIDTH * 16)) + { + pClass->m_data->startY = iVal; + } + break; + case eControl_StartZ: + pClass->m_textInputStartZ.setLabel(value); + + if( iVal >= (LEVEL_MAX_WIDTH * -16) || iVal < (LEVEL_MAX_WIDTH * 16)) + { + pClass->m_data->startZ = iVal; + } + break; + case eControl_EndX: + pClass->m_textInputEndX.setLabel(value); + + if( iVal >= (LEVEL_MAX_WIDTH * -16) || iVal < (LEVEL_MAX_WIDTH * 16)) + { + pClass->m_data->endX = iVal; + } + break; + case eControl_EndY: + pClass->m_textInputEndY.setLabel(value); + + if( iVal >= (LEVEL_MAX_WIDTH * -16) || iVal < (LEVEL_MAX_WIDTH * 16)) + { + pClass->m_data->endY = iVal; + } + break; + case eControl_EndZ: + pClass->m_textInputEndZ.setLabel(value); + + if( iVal >= (LEVEL_MAX_WIDTH * -16) || iVal < (LEVEL_MAX_WIDTH * 16)) + { + pClass->m_data->endZ = iVal; + } + break; + } + } + + return 0; +} +#endif
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIScene_DebugCreateSchematic.h b/Minecraft.Client/Common/UI/UIScene_DebugCreateSchematic.h new file mode 100644 index 00000000..cbfe785d --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_DebugCreateSchematic.h @@ -0,0 +1,73 @@ +#pragma once +#ifdef _DEBUG_MENUS_ENABLED +#include "UIScene.h" +#include "..\..\Common\GameRules\ConsoleSchematicFile.h" + +class UIScene_DebugCreateSchematic : public UIScene +{ +private: + enum eControls + { + eControl_Name, + eControl_StartX, + eControl_StartY, + eControl_StartZ, + eControl_EndX, + eControl_EndY, + eControl_EndZ, + eControl_SaveMobs, + eControl_UseCompression, + eControl_Create, + }; + + eControls m_keyboardCallbackControl; + + ConsoleSchematicFile::XboxSchematicInitParam *m_data; + +public: + UIScene_DebugCreateSchematic(int iPad, void *initData, UILayer *parentLayer); + + virtual EUIScene getSceneType() { return eUIScene_DebugCreateSchematic;} + +protected: + UIControl_TextInput m_textInputStartX, m_textInputStartY, m_textInputStartZ, m_textInputEndX, m_textInputEndY, m_textInputEndZ, m_textInputName; + UIControl_CheckBox m_checkboxSaveMobs, m_checkboxUseCompression; + UIControl_Button m_buttonCreate; + UIControl_Label m_labelStartX, m_labelStartY, m_labelStartZ, m_labelEndX, m_labelEndY, m_labelEndZ, m_labelTitle; + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) + UI_MAP_ELEMENT( m_textInputStartX, "StartX") + UI_MAP_ELEMENT( m_textInputStartY, "StartY") + UI_MAP_ELEMENT( m_textInputStartZ, "StartZ") + UI_MAP_ELEMENT( m_textInputEndX, "EndX") + UI_MAP_ELEMENT( m_textInputEndY, "EndY") + UI_MAP_ELEMENT( m_textInputEndZ, "EndZ") + UI_MAP_ELEMENT( m_textInputName, "Name") + + UI_MAP_ELEMENT( m_checkboxSaveMobs, "SaveMobs") + UI_MAP_ELEMENT( m_checkboxUseCompression, "UseCompression") + + UI_MAP_ELEMENT( m_buttonCreate, "Create") + + UI_MAP_ELEMENT( m_labelStartX, "LabelStartX") + UI_MAP_ELEMENT( m_labelStartY, "LabelStartY") + UI_MAP_ELEMENT( m_labelStartZ, "LabelStartZ") + UI_MAP_ELEMENT( m_labelEndX, "LabelEndX") + UI_MAP_ELEMENT( m_labelEndY, "LabelEndY") + UI_MAP_ELEMENT( m_labelEndZ, "LabelEndZ") + UI_MAP_ELEMENT( m_labelTitle, "LabelTitle") + UI_END_MAP_ELEMENTS_AND_NAMES() + + virtual wstring getMoviePath(); + +public: + // INPUT + virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled); + +protected: + void handlePress(F64 controlId, F64 childId); + virtual void handleCheckboxToggled(F64 controlId, bool selected); + +private: + static int KeyboardCompleteCallback(LPVOID lpParam,const bool bRes); +}; +#endif
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIScene_DebugOptions.cpp b/Minecraft.Client/Common/UI/UIScene_DebugOptions.cpp new file mode 100644 index 00000000..658a8517 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_DebugOptions.cpp @@ -0,0 +1,96 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIScene_DebugOptions.h" + +LPCWSTR UIScene_DebugOptionsMenu::m_DebugCheckboxTextA[eDebugSetting_Max+1]= +{ + L"Load Saves From Local Folder Mode", + L"Write Saves To Local Folder Mode", + L"Freeze Players", //L"Not Used", + L"Display Safe Area", + L"Mobs don't attack", + L"Freeze Time", + L"Disable Weather", + L"Craft Anything", + L"Use DPad for debug", + L"Mobs don't tick", + L"Instant Mine", + L"Show UI Console", + L"Distributable Save", + L"Debug Leaderboards", + L"Height-Water-Biome Maps", + L"Superflat Nether", + //L"Light/Dark background", + L"More lightning when thundering", + L"Go To Nether", + //L"Go To End", + L"Go To Overworld", + L"Unlock All DLC", //L"Toggle Font", + L"Show Marketing Guide", +}; + +UIScene_DebugOptionsMenu::UIScene_DebugOptionsMenu(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) +{ + // Setup all the Iggy references we need for this scene + initialiseMovie(); + + unsigned int uiDebugBitmask=app.GetGameSettingsDebugMask(iPad); + + IggyValuePath *root = IggyPlayerRootPath ( getMovie() ); + for(m_iTotalCheckboxElements = 0; m_iTotalCheckboxElements < eDebugSetting_Max && m_iTotalCheckboxElements < 21; ++m_iTotalCheckboxElements) + { + wstring label(m_DebugCheckboxTextA[m_iTotalCheckboxElements]); + m_checkboxes[m_iTotalCheckboxElements].init(label,m_iTotalCheckboxElements,(uiDebugBitmask&(1<<m_iTotalCheckboxElements)) ? true : false); + } +} + +wstring UIScene_DebugOptionsMenu::getMoviePath() +{ + return L"DebugOptionsMenu"; +} + +void UIScene_DebugOptionsMenu::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled) +{ + //app.DebugPrintf("UIScene_DebugOptionsMenu handling input for pad %d, key %d, repeat- %s, pressed- %s, released- %s\n", iPad, key, repeat?"TRUE":"FALSE", pressed?"TRUE":"FALSE", released?"TRUE":"FALSE"); + + switch(key) + { + case ACTION_MENU_CANCEL: + if(pressed) + { + int iCurrentBitmaskIndex=0; + unsigned int uiDebugBitmask=0L; + for(int i=0;i<m_iTotalCheckboxElements;i++) + { + uiDebugBitmask|=m_checkboxes[i].IsChecked()?(1<<iCurrentBitmaskIndex):0; + iCurrentBitmaskIndex++; + } + + if(uiDebugBitmask!=app.GetGameSettingsDebugMask(iPad)) + { + app.SetGameSettingsDebugMask(iPad,uiDebugBitmask); + if(app.DebugSettingsOn()) + { + app.ActionDebugMask(iPad); + } + else + { + // force debug mask off + app.ActionDebugMask(iPad,true); + } + + app.CheckGameSettingsChanged(true,iPad); + } + + navigateBack(); + } + break; + case ACTION_MENU_OK: + case ACTION_MENU_UP: + case ACTION_MENU_DOWN: + case ACTION_MENU_PAGEUP: + case ACTION_MENU_PAGEDOWN: + sendInputToMovie(key, repeat, pressed, released); + break; + } +} diff --git a/Minecraft.Client/Common/UI/UIScene_DebugOptions.h b/Minecraft.Client/Common/UI/UIScene_DebugOptions.h new file mode 100644 index 00000000..bb85bda0 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_DebugOptions.h @@ -0,0 +1,49 @@ +#pragma once + +#include "UIScene.h" +#include "UIControl_CheckBox.h" + +class UIScene_DebugOptionsMenu : public UIScene +{ +private: + static LPCWSTR m_DebugCheckboxTextA[eDebugSetting_Max+1]; + + int m_iTotalCheckboxElements; + +public: + UIScene_DebugOptionsMenu(int iPad, void *initData, UILayer *parentLayer); + + virtual EUIScene getSceneType() { return eUIScene_DebugOptions;} + +protected: + UIControl_CheckBox m_checkboxes[21]; + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) + UI_MAP_ELEMENT( m_checkboxes[0], "checkbox1") + UI_MAP_ELEMENT( m_checkboxes[1], "checkbox2") + UI_MAP_ELEMENT( m_checkboxes[2], "checkbox3") + UI_MAP_ELEMENT( m_checkboxes[3], "checkbox4") + UI_MAP_ELEMENT( m_checkboxes[4], "checkbox5") + UI_MAP_ELEMENT( m_checkboxes[5], "checkbox6") + UI_MAP_ELEMENT( m_checkboxes[6], "checkbox7") + UI_MAP_ELEMENT( m_checkboxes[7], "checkbox8") + UI_MAP_ELEMENT( m_checkboxes[8], "checkbox9") + UI_MAP_ELEMENT( m_checkboxes[9], "checkbox10") + UI_MAP_ELEMENT( m_checkboxes[10], "checkbox11") + UI_MAP_ELEMENT( m_checkboxes[11], "checkbox12") + UI_MAP_ELEMENT( m_checkboxes[12], "checkbox13") + UI_MAP_ELEMENT( m_checkboxes[13], "checkbox14") + UI_MAP_ELEMENT( m_checkboxes[14], "checkbox15") + UI_MAP_ELEMENT( m_checkboxes[15], "checkbox16") + UI_MAP_ELEMENT( m_checkboxes[16], "checkbox17") + UI_MAP_ELEMENT( m_checkboxes[17], "checkbox18") + UI_MAP_ELEMENT( m_checkboxes[18], "checkbox19") + UI_MAP_ELEMENT( m_checkboxes[19], "checkbox20") + UI_MAP_ELEMENT( m_checkboxes[20], "checkbox21") + UI_END_MAP_ELEMENTS_AND_NAMES() + + virtual wstring getMoviePath(); + +public: + // INPUT + virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled); +}; diff --git a/Minecraft.Client/Common/UI/UIScene_DebugOverlay.cpp b/Minecraft.Client/Common/UI/UIScene_DebugOverlay.cpp new file mode 100644 index 00000000..44a7e6c5 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_DebugOverlay.cpp @@ -0,0 +1,265 @@ +#include "stdafx.h" + +#ifdef _DEBUG_MENUS_ENABLED +#include "UI.h" +#include "UIScene_DebugOverlay.h" +#include "..\..\Minecraft.h" +#include "..\..\MinecraftServer.h" +#include "..\..\GameRenderer.h" +#include "..\..\MultiPlayerLevel.h" +#include "ClientConnection.h" +#include "MultiPlayerLocalPlayer.h" +#include "..\..\..\Minecraft.World\StringHelpers.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.item.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.level.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.level.storage.h" +#include "..\..\..\Minecraft.World\net.minecraft.commands.common.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.item.enchantment.h" + +UIScene_DebugOverlay::UIScene_DebugOverlay(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) +{ + // Setup all the Iggy references we need for this scene + initialiseMovie(); + + Minecraft *pMinecraft = Minecraft::GetInstance(); + WCHAR TempString[256]; + swprintf( (WCHAR *)TempString, 256, L"Set fov (%d)", (int)pMinecraft->gameRenderer->GetFovVal()); + m_sliderFov.init(TempString,eControl_FOV,0,100,(int)pMinecraft->gameRenderer->GetFovVal()); + + float currentTime = pMinecraft->level->getLevelData()->getTime() % 24000; + swprintf( (WCHAR *)TempString, 256, L"Set time (unsafe) (%d)", (int)currentTime); + m_sliderTime.init(TempString,eControl_Time,0,240,currentTime/100); + + m_buttonRain.init(L"Toggle Rain",eControl_Rain); + m_buttonThunder.init(L"Toggle Thunder",eControl_Thunder); + m_buttonSchematic.init(L"Create Schematic",eControl_Schematic); + m_buttonResetTutorial.init(L"Reset profile tutorial progress",eControl_ResetTutorial); + m_buttonSetCamera.init(L"Set camera",eControl_SetCamera); + m_buttonSetDay.init(L"Set Day", eControl_SetDay); + m_buttonSetNight.init(L"Set Night", eControl_SetNight); + + m_buttonListItems.init(eControl_Items); + + int listId = 0; + for(unsigned int i = 0; i < Item::items.length; ++i) + { + if(Item::items[i] != NULL) + { + m_itemIds.push_back(i); + m_buttonListItems.addItem(app.GetString(Item::items[i]->getDescriptionId()), listId); + ++listId; + } + } + + m_buttonListEnchantments.init(eControl_Enchantments); + + for(unsigned int i = 0; i < Enchantment::validEnchantments.size(); ++i ) + { + Enchantment *ench = Enchantment::validEnchantments.at(i); + + for(unsigned int level = ench->getMinLevel(); level <= ench->getMaxLevel(); ++level) + { + m_enchantmentIdAndLevels.push_back(pair<int,int>(ench->id,level)); + m_buttonListEnchantments.addItem(app.GetString( ench->getDescriptionId() ) + _toString<int>(level) ); + } + } + + m_buttonListMobs.init(eControl_Mobs); + m_buttonListMobs.addItem( L"Chicken" ); + m_mobFactories.push_back(eTYPE_CHICKEN); + m_buttonListMobs.addItem( L"Cow" ); + m_mobFactories.push_back(eTYPE_COW); + m_buttonListMobs.addItem( L"Pig" ); + m_mobFactories.push_back(eTYPE_PIG); + m_buttonListMobs.addItem( L"Sheep" ); + m_mobFactories.push_back(eTYPE_SHEEP); + m_buttonListMobs.addItem( L"Squid" ); + m_mobFactories.push_back(eTYPE_SQUID); + m_buttonListMobs.addItem( L"Wolf" ); + m_mobFactories.push_back(eTYPE_WOLF); + m_buttonListMobs.addItem( L"Creeper" ); + m_mobFactories.push_back(eTYPE_CREEPER); + m_buttonListMobs.addItem( L"Ghast" ); + m_mobFactories.push_back(eTYPE_GHAST); + m_buttonListMobs.addItem( L"Pig Zombie" ); + m_mobFactories.push_back(eTYPE_PIGZOMBIE); + m_buttonListMobs.addItem( L"Skeleton" ); + m_mobFactories.push_back(eTYPE_SKELETON); + m_buttonListMobs.addItem( L"Slime" ); + m_mobFactories.push_back(eTYPE_SLIME); + m_buttonListMobs.addItem( L"Spider" ); + m_mobFactories.push_back(eTYPE_SPIDER); + m_buttonListMobs.addItem( L"Zombie" ); + m_mobFactories.push_back(eTYPE_ZOMBIE); + m_buttonListMobs.addItem( L"Enderman" ); + m_mobFactories.push_back(eTYPE_ENDERMAN); + m_buttonListMobs.addItem( L"Silverfish" ); + m_mobFactories.push_back(eTYPE_SILVERFISH); + m_buttonListMobs.addItem( L"Cave Spider" ); + m_mobFactories.push_back(eTYPE_CAVESPIDER); + m_buttonListMobs.addItem( L"Mooshroom" ); + m_mobFactories.push_back(eTYPE_MUSHROOMCOW); + m_buttonListMobs.addItem( L"Snow Golem" ); + m_mobFactories.push_back(eTYPE_SNOWMAN); + m_buttonListMobs.addItem( L"Ender Dragon" ); + m_mobFactories.push_back(eTYPE_ENDERDRAGON); + m_buttonListMobs.addItem( L"Blaze" ); + m_mobFactories.push_back(eTYPE_BLAZE); + m_buttonListMobs.addItem( L"Magma Cube" ); + m_mobFactories.push_back(eTYPE_LAVASLIME); +} + +wstring UIScene_DebugOverlay::getMoviePath() +{ + return L"DebugMenu"; +} + +void UIScene_DebugOverlay::customDraw(IggyCustomDrawCallbackRegion *region) +{ + Minecraft *pMinecraft = Minecraft::GetInstance(); + if(pMinecraft->localplayers[m_iPad] == NULL || pMinecraft->localgameModes[m_iPad] == NULL) return; + + int itemId = -1; + swscanf((wchar_t*)region->name,L"item_%d",&itemId); + if (itemId == -1 || itemId > Item::ITEM_NUM_COUNT || Item::items[itemId] == NULL) + { + app.DebugPrintf("This is not the control we are looking for\n"); + } + else + { + shared_ptr<ItemInstance> item = shared_ptr<ItemInstance>( new ItemInstance(itemId,1,0) ); + if(item != NULL) customDrawSlotControl(region,m_iPad,item,1.0f,false,false); + } +} + +void UIScene_DebugOverlay::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled) +{ + ui.AnimateKeyPress(iPad, key, repeat, pressed, released); + + switch(key) + { + case ACTION_MENU_CANCEL: + if(pressed) + { + navigateBack(); + } + break; + case ACTION_MENU_OK: + case ACTION_MENU_UP: + case ACTION_MENU_DOWN: + case ACTION_MENU_PAGEUP: + case ACTION_MENU_PAGEDOWN: + case ACTION_MENU_LEFT: + case ACTION_MENU_RIGHT: + if(pressed) + { + sendInputToMovie(key, repeat, pressed, released); + } + break; + } +} + +void UIScene_DebugOverlay::handlePress(F64 controlId, F64 childId) +{ + switch((int)controlId) + { + case eControl_Items: + { + app.DebugPrintf("UIScene_DebugOverlay::handlePress for itemsList: %f\n", childId); + int id = childId; + //app.SetXuiServerAction(m_iPad, eXuiServerAction_DropItem, (void *)m_itemIds[id]); + ClientConnection *conn = Minecraft::GetInstance()->getConnection(ProfileManager.GetPrimaryPad()); + conn->send( GiveItemCommand::preparePacket(dynamic_pointer_cast<Player>(Minecraft::GetInstance()->localplayers[ProfileManager.GetPrimaryPad()]), m_itemIds[id]) ); + } + break; + case eControl_Mobs: + { + int id = childId; + if(id<m_mobFactories.size()) + { + app.SetXuiServerAction(ProfileManager.GetPrimaryPad(),eXuiServerAction_SpawnMob,(void *)m_mobFactories[id]); + } + } + break; + case eControl_Enchantments: + { + int id = childId; + ClientConnection *conn = Minecraft::GetInstance()->getConnection(ProfileManager.GetPrimaryPad()); + conn->send( EnchantItemCommand::preparePacket(dynamic_pointer_cast<Player>(Minecraft::GetInstance()->localplayers[ProfileManager.GetPrimaryPad()]), m_enchantmentIdAndLevels[id].first, m_enchantmentIdAndLevels[id].second) ); + } + break; + case eControl_Schematic: + { +#ifndef _CONTENT_PACKAGE + ui.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_DebugCreateSchematic,NULL,eUILayer_Debug); +#endif + } + break; + case eControl_SetCamera: + { +#ifndef _CONTENT_PACKAGE + ui.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_DebugSetCamera,NULL,eUILayer_Debug); +#endif + } + break; + case eControl_Rain: + { + //app.SetXuiServerAction(ProfileManager.GetPrimaryPad(),eXuiServerAction_ToggleRain); + ClientConnection *conn = Minecraft::GetInstance()->getConnection(ProfileManager.GetPrimaryPad()); + conn->send( ToggleDownfallCommand::preparePacket() ); + } + break; + case eControl_Thunder: + app.SetXuiServerAction(ProfileManager.GetPrimaryPad(),eXuiServerAction_ToggleThunder); + break; + case eControl_ResetTutorial: + Tutorial::debugResetPlayerSavedProgress( ProfileManager.GetPrimaryPad() ); + break; + case eControl_SetDay: + { + ClientConnection *conn = Minecraft::GetInstance()->getConnection(ProfileManager.GetPrimaryPad()); + conn->send( TimeCommand::preparePacket(false) ); + } + break; + case eControl_SetNight: + { + ClientConnection *conn = Minecraft::GetInstance()->getConnection(ProfileManager.GetPrimaryPad()); + conn->send( TimeCommand::preparePacket(true) ); + } + break; + }; +} + +void UIScene_DebugOverlay::handleSliderMove(F64 sliderId, F64 currentValue) +{ + switch((int)sliderId) + { + case eControl_Time: + { + Minecraft *pMinecraft = Minecraft::GetInstance(); + + // Need to set the time on both levels to stop the flickering as the local level + // tries to predict the time + // Only works if we are on the host machine, but shouldn't break if not + MinecraftServer::SetTime(currentValue * 100); + pMinecraft->level->getLevelData()->setTime(currentValue * 100); + + WCHAR TempString[256]; + float currentTime = currentValue * 100; + swprintf( (WCHAR *)TempString, 256, L"Set time (unsafe) (%d)", (int)currentTime); + m_sliderTime.setLabel(TempString); + } + break; + case eControl_FOV: + { + Minecraft *pMinecraft = Minecraft::GetInstance(); + pMinecraft->gameRenderer->SetFovVal((float)currentValue); + + WCHAR TempString[256]; + swprintf( (WCHAR *)TempString, 256, L"Set fov (%d)", (int)currentValue); + m_sliderFov.setLabel(TempString); + } + break; + }; +} +#endif diff --git a/Minecraft.Client/Common/UI/UIScene_DebugOverlay.h b/Minecraft.Client/Common/UI/UIScene_DebugOverlay.h new file mode 100644 index 00000000..9a0e1cd8 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_DebugOverlay.h @@ -0,0 +1,65 @@ +#pragma once +#ifdef _DEBUG_MENUS_ENABLED +#include "UIScene.h" +#include "UIControl_ButtonList.h" + +class UIScene_DebugOverlay : public UIScene +{ +private: + enum eControls + { + eControl_SetCamera, + eControl_ResetTutorial, + eControl_Schematic, + eControl_Thunder, + eControl_Rain, + eControl_FOV, + eControl_SetDay, + eControl_SetNight, + eControl_Time, + eControl_Mobs, + eControl_Enchantments, + eControl_Items, + }; + + vector<int> m_itemIds; + vector<eINSTANCEOF> m_mobFactories; + vector< pair<int,int> > m_enchantmentIdAndLevels; +public: + UIScene_DebugOverlay(int iPad, void *initData, UILayer *parentLayer); + + virtual EUIScene getSceneType() { return eUIScene_DebugOverlay;} + +protected: + UIControl_ButtonList m_buttonListItems, m_buttonListMobs, m_buttonListEnchantments; + UIControl_Slider m_sliderFov, m_sliderTime; + UIControl_Button m_buttonRain, m_buttonThunder, m_buttonSchematic, m_buttonResetTutorial, m_buttonSetCamera, m_buttonSetDay, m_buttonSetNight; + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) + UI_MAP_ELEMENT( m_buttonListItems, "itemsList") + UI_MAP_ELEMENT( m_buttonListEnchantments, "enchantmentsList") + UI_MAP_ELEMENT( m_buttonListMobs, "mobList") + UI_MAP_ELEMENT( m_sliderFov, "fov") + UI_MAP_ELEMENT( m_sliderTime, "time") + UI_MAP_ELEMENT( m_buttonSetDay, "setDay") + UI_MAP_ELEMENT( m_buttonSetNight, "setNight") + UI_MAP_ELEMENT( m_buttonRain, "rain") + UI_MAP_ELEMENT( m_buttonThunder, "thunder") + UI_MAP_ELEMENT( m_buttonSchematic, "schematic") + UI_MAP_ELEMENT( m_buttonResetTutorial, "resetTutorial") + UI_MAP_ELEMENT( m_buttonSetCamera, "setCamera") + UI_END_MAP_ELEMENTS_AND_NAMES() + + virtual wstring getMoviePath(); + +public: + virtual void customDraw(IggyCustomDrawCallbackRegion *region); + +public: + // INPUT + virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled); + +protected: + void handlePress(F64 controlId, F64 childId); + virtual void handleSliderMove(F64 sliderId, F64 currentValue); +}; +#endif
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIScene_DebugSetCamera.cpp b/Minecraft.Client/Common/UI/UIScene_DebugSetCamera.cpp new file mode 100644 index 00000000..dd5a429f --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_DebugSetCamera.cpp @@ -0,0 +1,158 @@ +#include "stdafx.h" + +#ifdef _DEBUG_MENUS_ENABLED +#include "UI.h" +#include "UIScene_DebugSetCamera.h" +#include "Minecraft.h" +#include "MultiPlayerLocalPlayer.h" +#include "..\..\..\Minecraft.World\StringHelpers.h" + +UIScene_DebugSetCamera::UIScene_DebugSetCamera(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) +{ + // Setup all the Iggy references we need for this scene + initialiseMovie(); + + int playerNo = 0; + currentPosition = new DebugSetCameraPosition(); + currentPosition->player = playerNo; + + Minecraft *pMinecraft = Minecraft::GetInstance(); + if (pMinecraft != NULL) + { + Vec3 *vec = pMinecraft->localplayers[playerNo]->getPos(1.0); + + currentPosition->m_camX = vec->x; + currentPosition->m_camY = vec->y - 1.62;// pMinecraft->localplayers[playerNo]->getHeadHeight(); + currentPosition->m_camZ = vec->z; + + currentPosition->m_yRot = pMinecraft->localplayers[playerNo]->yRot; + currentPosition->m_elev = pMinecraft->localplayers[playerNo]->xRot; + } + + WCHAR TempString[256]; + + swprintf( (WCHAR *)TempString, 256, L"%f", currentPosition->m_camX); + m_textInputX.init(TempString, eControl_CamX); + + swprintf( (WCHAR *)TempString, 256, L"%f", currentPosition->m_camY); + m_textInputY.init(TempString, eControl_CamY); + + swprintf( (WCHAR *)TempString, 256, L"%f", currentPosition->m_camZ); + m_textInputZ.init(TempString, eControl_CamZ); + + swprintf( (WCHAR *)TempString, 256, L"%f", currentPosition->m_yRot); + m_textInputYRot.init(TempString, eControl_YRot); + + swprintf( (WCHAR *)TempString, 256, L"%f", currentPosition->m_elev); + m_textInputElevation.init(TempString, eControl_Elevation); + + m_checkboxLockPlayer.init(L"Lock Player", eControl_LockPlayer, app.GetFreezePlayers()); + + m_buttonTeleport.init(L"Teleport", eControl_Teleport); + + m_labelTitle.init(L"Set Camera Position"); + m_labelCamX.init(L"CamX"); + m_labelCamY.init(L"CamY"); + m_labelCamZ.init(L"CamZ"); + m_labelYRotElev.init(L"Y-Rot & Elevation (Degs)"); +} + +wstring UIScene_DebugSetCamera::getMoviePath() +{ + return L"DebugSetCamera"; +} + +void UIScene_DebugSetCamera::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled) +{ + ui.AnimateKeyPress(iPad, key, repeat, pressed, released); + + switch(key) + { + case ACTION_MENU_CANCEL: + if(pressed) + { + navigateBack(); + } + break; + case ACTION_MENU_OK: + case ACTION_MENU_UP: + case ACTION_MENU_DOWN: + case ACTION_MENU_PAGEUP: + case ACTION_MENU_PAGEDOWN: + case ACTION_MENU_LEFT: + case ACTION_MENU_RIGHT: + sendInputToMovie(key, repeat, pressed, released); + break; + } +} + +void UIScene_DebugSetCamera::handlePress(F64 controlId, F64 childId) +{ + switch((int)controlId) + { + case eControl_Teleport: + app.SetXuiServerAction( ProfileManager.GetPrimaryPad(), + eXuiServerAction_SetCameraLocation, + (void *)currentPosition); + break; + case eControl_CamX: + case eControl_CamY: + case eControl_CamZ: + case eControl_YRot: + case eControl_Elevation: + m_keyboardCallbackControl = (eControls)((int)controlId); + InputManager.RequestKeyboard(L"Enter something",L"",(DWORD)0,25,&UIScene_DebugSetCamera::KeyboardCompleteCallback,this,C_4JInput::EKeyboardMode_Default); + break; + }; +} + +void UIScene_DebugSetCamera::handleCheckboxToggled(F64 controlId, bool selected) +{ + switch((int)controlId) + { + case eControl_LockPlayer: + app.SetFreezePlayers(selected); + break; + } +} + +int UIScene_DebugSetCamera::KeyboardCompleteCallback(LPVOID lpParam,bool bRes) +{ + UIScene_DebugSetCamera *pClass=(UIScene_DebugSetCamera *)lpParam; + uint16_t pchText[2048];//[128]; + ZeroMemory(pchText, 2048/*128*/ * sizeof(uint16_t) ); + InputManager.GetText(pchText); + + if(pchText[0]!=0) + { + wstring value = (wchar_t *)pchText; + double val = 0; + if(!value.empty()) val = _fromString<double>( value ); + switch(pClass->m_keyboardCallbackControl) + { + case eControl_CamX: + pClass->m_textInputX.setLabel(value); + pClass->currentPosition->m_camX = val; + break; + case eControl_CamY: + pClass->m_textInputY.setLabel(value); + pClass->currentPosition->m_camY = val; + break; + case eControl_CamZ: + pClass->m_textInputZ.setLabel(value); + pClass->currentPosition->m_camZ = val; + break; + case eControl_YRot: + pClass->m_textInputYRot.setLabel(value); + pClass->currentPosition->m_yRot = val; + break; + case eControl_Elevation: + pClass->m_textInputElevation.setLabel(value); + pClass->currentPosition->m_elev = val; + break; + } + } + + return 0; +} +#endif diff --git a/Minecraft.Client/Common/UI/UIScene_DebugSetCamera.h b/Minecraft.Client/Common/UI/UIScene_DebugSetCamera.h new file mode 100644 index 00000000..38db1258 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_DebugSetCamera.h @@ -0,0 +1,69 @@ +#pragma once +#ifdef _DEBUG_MENUS_ENABLED +#include "UIScene.h" + +class UIScene_DebugSetCamera : public UIScene +{ +private: + enum eControls + { + eControl_CamX, + eControl_CamY, + eControl_CamZ, + eControl_YRot, + eControl_Elevation, + eControl_LockPlayer, + eControl_Teleport, + }; + + typedef struct _FreezePlayerParam + { + int player; + bool freeze; + } FreezePlayerParam; + + DebugSetCameraPosition *currentPosition; + FreezePlayerParam *fpp; + + eControls m_keyboardCallbackControl; + +public: + UIScene_DebugSetCamera(int iPad, void *initData, UILayer *parentLayer); + + virtual EUIScene getSceneType() { return eUIScene_DebugSetCamera;} + +protected: + UIControl_TextInput m_textInputX, m_textInputY, m_textInputZ, m_textInputYRot, m_textInputElevation; + UIControl_CheckBox m_checkboxLockPlayer; + UIControl_Button m_buttonTeleport; + UIControl_Label m_labelTitle, m_labelCamX, m_labelCamY, m_labelCamZ, m_labelYRotElev; + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) + UI_MAP_ELEMENT( m_textInputX, "CamX") + UI_MAP_ELEMENT( m_textInputY, "CamY") + UI_MAP_ELEMENT( m_textInputZ, "CamZ") + UI_MAP_ELEMENT( m_textInputYRot, "YRot") + UI_MAP_ELEMENT( m_textInputElevation, "Elevation") + UI_MAP_ELEMENT( m_checkboxLockPlayer, "LockPlayer") + UI_MAP_ELEMENT( m_buttonTeleport, "Teleport") + + UI_MAP_ELEMENT( m_labelTitle, "LabelTitle") + UI_MAP_ELEMENT( m_labelCamX, "LabelCamX") + UI_MAP_ELEMENT( m_labelCamY, "LabelCamY") + UI_MAP_ELEMENT( m_labelCamZ, "LabelCamZ") + UI_MAP_ELEMENT( m_labelYRotElev, "LabelYRotElev") + UI_END_MAP_ELEMENTS_AND_NAMES() + + virtual wstring getMoviePath(); + +public: + // INPUT + virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled); + +protected: + void handlePress(F64 controlId, F64 childId); + virtual void handleCheckboxToggled(F64 controlId, bool selected); + +private: + static int KeyboardCompleteCallback(LPVOID lpParam,const bool bRes); +}; +#endif
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIScene_DispenserMenu.cpp b/Minecraft.Client/Common/UI/UIScene_DispenserMenu.cpp new file mode 100644 index 00000000..1eda1660 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_DispenserMenu.cpp @@ -0,0 +1,197 @@ +#include "stdafx.h" +#include "UI.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.level.tile.entity.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.inventory.h" +#include "..\..\Minecraft.h" +#include "UIScene_DispenserMenu.h" + +UIScene_DispenserMenu::UIScene_DispenserMenu(int iPad, void *_initData, UILayer *parentLayer) : UIScene_AbstractContainerMenu(iPad, parentLayer) +{ + // Setup all the Iggy references we need for this scene + initialiseMovie(); + + m_labelDispenser.init(app.GetString(IDS_DISPENSER)); + + TrapScreenInput *initData = (TrapScreenInput *)_initData; + + Minecraft *pMinecraft = Minecraft::GetInstance(); + if( pMinecraft->localgameModes[initData->iPad] != NULL ) + { + TutorialMode *gameMode = (TutorialMode *)pMinecraft->localgameModes[initData->iPad]; + m_previousTutorialState = gameMode->getTutorial()->getCurrentState(); + gameMode->getTutorial()->changeTutorialState(e_Tutorial_State_Trap_Menu, this); + } + + TrapMenu* menu = new TrapMenu( initData->inventory, initData->trap ); + + m_containerSize = initData->trap->getContainerSize(); + Initialize( initData->iPad, menu, true, m_containerSize, eSectionTrapUsing, eSectionTrapMax ); + + m_slotListTrap.addSlots(0, 9); + + delete initData; +} + +wstring UIScene_DispenserMenu::getMoviePath() +{ + if(app.GetLocalPlayerCount() > 1) + { + return L"DispenserMenuSplit"; + } + else + { + return L"DispenserMenu"; + } +} + +void UIScene_DispenserMenu::handleReload() +{ + Initialize( m_iPad, m_menu, true, m_containerSize, eSectionTrapUsing, eSectionTrapMax ); + + m_slotListTrap.addSlots(0, 9); +} + +int UIScene_DispenserMenu::getSectionColumns(ESceneSection eSection) +{ + int cols = 0; + switch( eSection ) + { + case eSectionTrapTrap: + cols = 3; + break; + case eSectionTrapInventory: + cols = 9; + break; + case eSectionTrapUsing: + cols = 9; + break; + default: + assert( false ); + break; + } + return cols; +} + +int UIScene_DispenserMenu::getSectionRows(ESceneSection eSection) +{ + int rows = 0; + switch( eSection ) + { + case eSectionTrapTrap: + rows = 3; + break; + case eSectionTrapInventory: + rows = 3; + break; + case eSectionTrapUsing: + rows = 1; + break; + default: + assert( false ); + break; + } + return rows; +} + +void UIScene_DispenserMenu::GetPositionOfSection( ESceneSection eSection, UIVec2D* pPosition ) +{ + switch( eSection ) + { + case eSectionTrapTrap: + pPosition->x = m_slotListTrap.getXPos(); + pPosition->y = m_slotListTrap.getYPos(); + break; + case eSectionTrapInventory: + pPosition->x = m_slotListInventory.getXPos(); + pPosition->y = m_slotListInventory.getYPos(); + break; + case eSectionTrapUsing: + pPosition->x = m_slotListHotbar.getXPos(); + pPosition->y = m_slotListHotbar.getYPos(); + break; + default: + assert( false ); + break; + } +} + +void UIScene_DispenserMenu::GetItemScreenData( ESceneSection eSection, int iItemIndex, UIVec2D* pPosition, UIVec2D* pSize ) +{ + UIVec2D sectionSize; + switch( eSection ) + { + case eSectionTrapTrap: + sectionSize.x = m_slotListTrap.getWidth(); + sectionSize.y = m_slotListTrap.getHeight(); + break; + case eSectionTrapInventory: + sectionSize.x = m_slotListInventory.getWidth(); + sectionSize.y = m_slotListInventory.getHeight(); + break; + case eSectionTrapUsing: + sectionSize.x = m_slotListHotbar.getWidth(); + sectionSize.y = m_slotListHotbar.getHeight(); + break; + default: + assert( false ); + break; + } + + int rows = getSectionRows(eSection); + int cols = getSectionColumns(eSection); + + pSize->x = sectionSize.x/cols; + pSize->y = sectionSize.y/rows; + + int itemCol = iItemIndex % cols; + int itemRow = iItemIndex/cols; + + pPosition->x = itemCol * pSize->x; + pPosition->y = itemRow * pSize->y; +} + +void UIScene_DispenserMenu::setSectionSelectedSlot(ESceneSection eSection, int x, int y) +{ + int cols = getSectionColumns(eSection); + + int index = (y * cols) + x; + + UIControl_SlotList *slotList = NULL; + switch( eSection ) + { + case eSectionTrapTrap: + slotList = &m_slotListTrap; + break; + case eSectionTrapInventory: + slotList = &m_slotListInventory; + break; + case eSectionTrapUsing: + slotList = &m_slotListHotbar; + break; + default: + assert( false ); + break; + } + slotList->setHighlightSlot(index); +} + +UIControl *UIScene_DispenserMenu::getSection(ESceneSection eSection) +{ + UIControl *control = NULL; + switch( eSection ) + { + case eSectionTrapTrap: + control = &m_slotListTrap; + break; + case eSectionTrapInventory: + control = &m_slotListInventory; + break; + case eSectionTrapUsing: + control = &m_slotListHotbar; + break; + default: + assert( false ); + break; + } + return control; +}
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIScene_DispenserMenu.h b/Minecraft.Client/Common/UI/UIScene_DispenserMenu.h new file mode 100644 index 00000000..6661c7a1 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_DispenserMenu.h @@ -0,0 +1,40 @@ +#pragma once + +#include "UIScene_AbstractContainerMenu.h" +#include "IUIScene_DispenserMenu.h" + +class InventoryMenu; + +class UIScene_DispenserMenu : public UIScene_AbstractContainerMenu, public IUIScene_DispenserMenu +{ +private: + int m_containerSize; + +public: + UIScene_DispenserMenu(int iPad, void *initData, UILayer *parentLayer); + + virtual EUIScene getSceneType() { return eUIScene_DispenserMenu;} + +protected: + UIControl_SlotList m_slotListTrap; + UIControl_Label m_labelDispenser; + + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene_AbstractContainerMenu) + UI_BEGIN_MAP_CHILD_ELEMENTS( m_controlMainPanel ) + UI_MAP_ELEMENT( m_slotListTrap, "Trap") + UI_MAP_ELEMENT( m_labelDispenser, "dispenserLabel") + UI_END_MAP_CHILD_ELEMENTS() + UI_END_MAP_ELEMENTS_AND_NAMES() + + virtual wstring getMoviePath(); + virtual void handleReload(); + + virtual int getSectionColumns(ESceneSection eSection); + virtual int getSectionRows(ESceneSection eSection); + virtual void GetPositionOfSection( ESceneSection eSection, UIVec2D* pPosition ); + virtual void GetItemScreenData( ESceneSection eSection, int iItemIndex, UIVec2D* pPosition, UIVec2D* pSize ); + virtual void handleSectionClick(ESceneSection eSection) {} + virtual void setSectionSelectedSlot(ESceneSection eSection, int x, int y); + + virtual UIControl *getSection(ESceneSection eSection); +};
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIScene_EULA.cpp b/Minecraft.Client/Common/UI/UIScene_EULA.cpp new file mode 100644 index 00000000..3177344d --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_EULA.cpp @@ -0,0 +1,145 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIScene_EULA.h" +#include "..\..\..\Minecraft.World\StringHelpers.h" + +UIScene_EULA::UIScene_EULA(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) +{ + // Setup all the Iggy references we need for this scene + initialiseMovie(); + + parentLayer->addComponent(iPad,eUIComponent_Panorama); + parentLayer->addComponent(iPad,eUIComponent_Logo); + + m_buttonConfirm.init(app.GetString(IDS_TOOLTIPS_ACCEPT),eControl_Confirm); + +#if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__) + wstring EULA = app.GetString(IDS_EULA); + EULA.append(L"\r\n"); + +#if defined(__PS3__) + if(app.IsEuropeanSKU()) + { + EULA.append(app.GetString(IDS_EULA_SCEE)); + // if it's the BD build + if(StorageManager.GetBootTypeDisc()) + { + EULA.append(app.GetString(IDS_EULA_SCEE_BD)); + } + } + else if(app.IsAmericanSKU()) + { + EULA.append(app.GetString(IDS_EULA_SCEA)); + } +#elif defined __ORBIS__ + if(app.IsEuropeanSKU()) + { + EULA.append(app.GetString(IDS_EULA_SCEE)); + // 4J-PB - we can't tell if it's a disc or digital version, so let's show this anyway + EULA.append(app.GetString(IDS_EULA_SCEE_BD)); + } + else if(app.IsAmericanSKU()) + { + EULA.append(app.GetString(IDS_EULA_SCEA)); + } +#endif +#else + wstring EULA = L""; +#endif + + vector<wstring> paragraphs; + int lastIndex = 0; + for ( int index = EULA.find(L"\r\n", lastIndex, 2); + index != wstring::npos; + index = EULA.find(L"\r\n", lastIndex, 2) + ) + { + paragraphs.push_back( EULA.substr(lastIndex, index-lastIndex) + L" " ); + lastIndex = index + 2; + } + paragraphs.push_back( EULA.substr( lastIndex, EULA.length() - lastIndex ) ); + + for(unsigned int i = 0; i < paragraphs.size(); ++i) + { + m_labelDescription.addText(paragraphs[i],i == (paragraphs.size() - 1) ); + } + + // 4J-PB - If we have a signed in user connected, let's get the DLC now + for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i) + { + if( (InputManager.IsPadConnected(i) || ProfileManager.IsSignedIn(i)) ) + { + if(!app.DLCInstallProcessCompleted() && !app.DLCInstallPending()) + { + app.StartInstallDLCProcess(i); + break; + } + } + } + + m_bIgnoreInput=false; + + //ui.setFontCachingCalculationBuffer(20000); + +#ifdef __PSVITA__ + ui.TouchBoxRebuild(this); +#endif +} + +UIScene_EULA::~UIScene_EULA() +{ + m_parentLayer->removeComponent(eUIComponent_Panorama); + m_parentLayer->removeComponent(eUIComponent_Logo); +} + +wstring UIScene_EULA::getMoviePath() +{ + return L"EULA"; +} + +void UIScene_EULA::updateTooltips() +{ + ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT ); +} + +void UIScene_EULA::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled) +{ + if(m_bIgnoreInput) return; + +#ifdef __ORBIS__ + // ignore all players except player 0 - it's their profile that is currently being used + if(iPad!=0) return; +#endif + + ui.AnimateKeyPress(m_iPad, key, repeat, pressed, released); + + switch(key) + { +#ifdef __ORBIS__ + case ACTION_MENU_TOUCHPAD_PRESS: +#endif + case ACTION_MENU_OK: + case ACTION_MENU_DOWN: + case ACTION_MENU_UP: + case ACTION_MENU_PAGEUP: + case ACTION_MENU_PAGEDOWN: + case ACTION_MENU_OTHER_STICK_DOWN: + case ACTION_MENU_OTHER_STICK_UP: + sendInputToMovie(key, repeat, pressed, released); + break; + } +} + +void UIScene_EULA::handlePress(F64 controlId, F64 childId) +{ + switch((int)controlId) + { + case eControl_Confirm: + //CD - Added for audio + ui.PlayUISFX(eSFX_Press); + app.SetGameSettings(0,eGameSetting_PS3_EULA_Read,1); + ui.NavigateToScene(0,eUIScene_SaveMessage); + ui.setFontCachingCalculationBuffer(-1); + break; + }; +} diff --git a/Minecraft.Client/Common/UI/UIScene_EULA.h b/Minecraft.Client/Common/UI/UIScene_EULA.h new file mode 100644 index 00000000..4715b112 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_EULA.h @@ -0,0 +1,45 @@ +#pragma once + +#include "UIScene.h" + +class UIScene_EULA : public UIScene +{ +private: + enum EControls + { + eControl_Confirm, + }; + + bool m_bIgnoreInput; + + UIControl_Button m_buttonConfirm; + UIControl_DynamicLabel m_labelDescription; + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) + UI_MAP_ELEMENT(m_buttonConfirm, "AcceptButton") + UI_MAP_ELEMENT(m_labelDescription, "EULAtext") + UI_END_MAP_ELEMENTS_AND_NAMES() + +public: + UIScene_EULA(int iPad, void *initData, UILayer *parentLayer); + ~UIScene_EULA(); + + virtual EUIScene getSceneType() { return eUIScene_EULA;} + + // Returns true if this scene has focus for the pad passed in +#ifndef __PS3__ + virtual bool hasFocus(int iPad) { return bHasFocus; } +#endif + virtual void updateTooltips(); + +protected: + virtual wstring getMoviePath(); + +public: + // INPUT + virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled); + +protected: + void handlePress(F64 controlId, F64 childId); + + virtual long long getDefaultGtcButtons() { return 0; } +}; diff --git a/Minecraft.Client/Common/UI/UIScene_EnchantingMenu.cpp b/Minecraft.Client/Common/UI/UIScene_EnchantingMenu.cpp new file mode 100644 index 00000000..8a4f1c6d --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_EnchantingMenu.cpp @@ -0,0 +1,284 @@ +#include "stdafx.h" +#include "UI.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.level.tile.entity.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.inventory.h" +#include "..\..\Minecraft.h" +#include "UIScene_EnchantingMenu.h" + +UIScene_EnchantingMenu::UIScene_EnchantingMenu(int iPad, void *_initData, UILayer *parentLayer) : UIScene_AbstractContainerMenu(iPad, parentLayer) +{ + // Setup all the Iggy references we need for this scene + initialiseMovie(); + + m_labelEnchant.init(app.GetString(IDS_ENCHANT)); + + m_enchantButton[0].init(0); + m_enchantButton[1].init(1); + m_enchantButton[2].init(2); + + EnchantingScreenInput *initData = (EnchantingScreenInput *)_initData; + + Minecraft *pMinecraft = Minecraft::GetInstance(); + if( pMinecraft->localgameModes[initData->iPad] != NULL ) + { + TutorialMode *gameMode = (TutorialMode *)pMinecraft->localgameModes[initData->iPad]; + m_previousTutorialState = gameMode->getTutorial()->getCurrentState(); + gameMode->getTutorial()->changeTutorialState(e_Tutorial_State_Enchanting_Menu, this); + } + + EnchantmentMenu *menu = new EnchantmentMenu(initData->inventory, initData->level, initData->x, initData->y, initData->z); + + Initialize( initData->iPad, menu, true, EnchantmentMenu::INV_SLOT_START, eSectionEnchantUsing, eSectionEnchantMax ); + + m_slotListIngredient.addSlots(EnchantmentMenu::INGREDIENT_SLOT, 1); + + app.SetRichPresenceContext(m_iPad,CONTEXT_GAME_STATE_ENCHANTING); + + delete initData; +} + +wstring UIScene_EnchantingMenu::getMoviePath() +{ + if(app.GetLocalPlayerCount() > 1) + { + return L"EnchantingMenuSplit"; + } + else + { + return L"EnchantingMenu"; + } +} + +void UIScene_EnchantingMenu::handleReload() +{ + Initialize( m_iPad, m_menu, true, EnchantmentMenu::INV_SLOT_START, eSectionEnchantUsing, eSectionEnchantMax ); + + m_slotListIngredient.addSlots(EnchantmentMenu::INGREDIENT_SLOT, 1); +} + +int UIScene_EnchantingMenu::getSectionColumns(ESceneSection eSection) +{ + int cols = 0; + switch( eSection ) + { + case eSectionEnchantSlot: + cols = 1; + break; + case eSectionEnchantInventory: + cols = 9; + break; + case eSectionEnchantUsing: + cols = 9; + break; + default: + assert( false ); + break; + }; + return cols; +} + +int UIScene_EnchantingMenu::getSectionRows(ESceneSection eSection) +{ + int rows = 0; + switch( eSection ) + { + case eSectionEnchantSlot: + rows = 1; + break; + case eSectionEnchantInventory: + rows = 3; + break; + case eSectionEnchantUsing: + rows = 1; + break; + default: + assert( false ); + break; + }; + return rows; +} + +void UIScene_EnchantingMenu::GetPositionOfSection( ESceneSection eSection, UIVec2D* pPosition ) +{ + switch( eSection ) + { + case eSectionEnchantSlot: + pPosition->x = m_slotListIngredient.getXPos(); + pPosition->y = m_slotListIngredient.getYPos(); + break; + case eSectionEnchantInventory: + pPosition->x = m_slotListInventory.getXPos(); + pPosition->y = m_slotListInventory.getYPos(); + break; + case eSectionEnchantUsing: + pPosition->x = m_slotListHotbar.getXPos(); + pPosition->y = m_slotListHotbar.getYPos(); + break; + case eSectionEnchantButton1: + pPosition->x = m_enchantButton[0].getXPos(); + pPosition->y = m_enchantButton[0].getYPos(); + break; + case eSectionEnchantButton2: + pPosition->x = m_enchantButton[1].getXPos(); + pPosition->y = m_enchantButton[1].getYPos(); + break; + case eSectionEnchantButton3: + pPosition->x = m_enchantButton[2].getXPos(); + pPosition->y = m_enchantButton[2].getYPos(); + break; + default: + assert( false ); + break; + }; +} + +void UIScene_EnchantingMenu::GetItemScreenData( ESceneSection eSection, int iItemIndex, UIVec2D* pPosition, UIVec2D* pSize ) +{ + UIVec2D sectionSize; + switch( eSection ) + { + case eSectionEnchantSlot: + sectionSize.x = m_slotListIngredient.getWidth(); + sectionSize.y = m_slotListIngredient.getHeight(); + break; + case eSectionEnchantInventory: + sectionSize.x = m_slotListInventory.getWidth(); + sectionSize.y = m_slotListInventory.getHeight(); + break; + case eSectionEnchantUsing: + sectionSize.x = m_slotListHotbar.getWidth(); + sectionSize.y = m_slotListHotbar.getHeight(); + break; + case eSectionEnchantButton1: + sectionSize.x = m_enchantButton[0].getWidth(); + sectionSize.y = m_enchantButton[0].getHeight(); + break; + case eSectionEnchantButton2: + sectionSize.x = m_enchantButton[1].getWidth(); + sectionSize.y = m_enchantButton[1].getHeight(); + break; + case eSectionEnchantButton3: + sectionSize.x = m_enchantButton[2].getWidth(); + sectionSize.y = m_enchantButton[2].getHeight(); + break; + default: + assert( false ); + break; + }; + + if(IsSectionSlotList(eSection)) + { + int rows = getSectionRows(eSection); + int cols = getSectionColumns(eSection); + + pSize->x = sectionSize.x/cols; + pSize->y = sectionSize.y/rows; + + int itemCol = iItemIndex % cols; + int itemRow = iItemIndex/cols; + + pPosition->x = itemCol * pSize->x; + pPosition->y = itemRow * pSize->y; + } + else + { + GetPositionOfSection(eSection, pPosition); + pSize->x = sectionSize.x; + pSize->y = sectionSize.y; + } +} + +void UIScene_EnchantingMenu::setSectionSelectedSlot(ESceneSection eSection, int x, int y) +{ + int cols = getSectionColumns(eSection); + + int index = (y * cols) + x; + + UIControl_SlotList *slotList = NULL; + switch( eSection ) + { + case eSectionEnchantSlot: + slotList = &m_slotListIngredient; + break; + case eSectionEnchantInventory: + slotList = &m_slotListInventory; + break; + case eSectionEnchantUsing: + slotList = &m_slotListHotbar; + break; + default: + assert( false ); + break; + }; + + slotList->setHighlightSlot(index); +} + +UIControl *UIScene_EnchantingMenu::getSection(ESceneSection eSection) +{ + UIControl *control = NULL; + switch( eSection ) + { + case eSectionEnchantSlot: + control = &m_slotListIngredient; + break; + case eSectionEnchantInventory: + control = &m_slotListInventory; + break; + case eSectionEnchantUsing: + control = &m_slotListHotbar; + break; + case eSectionEnchantButton1: + control = &m_enchantButton[0]; + break; + case eSectionEnchantButton2: + control = &m_enchantButton[1]; + break; + case eSectionEnchantButton3: + control = &m_enchantButton[2]; + break; + default: + assert( false ); + break; + }; + return control; +} + +void UIScene_EnchantingMenu::customDraw(IggyCustomDrawCallbackRegion *region) +{ + Minecraft *pMinecraft = Minecraft::GetInstance(); + if(pMinecraft->localplayers[m_iPad] == NULL || pMinecraft->localgameModes[m_iPad] == NULL) return; + + + if(wcscmp((wchar_t *)region->name,L"EnchantmentBook")==0) + { + // Setup GDraw, normal game render states and matrices + CustomDrawData *customDrawRegion = ui.setupCustomDraw(this,region); + delete customDrawRegion; + + m_enchantBook.render(region); + + // Finish GDraw and anything else that needs to be finalised + ui.endCustomDraw(region); + } + else + { + int slotId = -1; + swscanf((wchar_t*)region->name,L"slot_Button%d",&slotId); + if(slotId >= 0) + { + // Setup GDraw, normal game render states and matrices + CustomDrawData *customDrawRegion = ui.setupCustomDraw(this,region); + delete customDrawRegion; + + m_enchantButton[slotId-1].render(region); + + // Finish GDraw and anything else that needs to be finalised + ui.endCustomDraw(region); + } + else + { + UIScene_AbstractContainerMenu::customDraw(region); + } + } +} diff --git a/Minecraft.Client/Common/UI/UIScene_EnchantingMenu.h b/Minecraft.Client/Common/UI/UIScene_EnchantingMenu.h new file mode 100644 index 00000000..89ccd120 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_EnchantingMenu.h @@ -0,0 +1,54 @@ +#pragma once + +#include "UIScene_AbstractContainerMenu.h" +#include "IUIScene_EnchantingMenu.h" + +class InventoryMenu; + +class UIScene_EnchantingMenu : public UIScene_AbstractContainerMenu, public IUIScene_EnchantingMenu +{ +private: + enum EControls + { + eControl_UNKNOWN, + eControl_Button1, + eControl_Button2, + eControl_Button3, + }; +public: + UIScene_EnchantingMenu(int iPad, void *initData, UILayer *parentLayer); + + virtual EUIScene getSceneType() { return eUIScene_EnchantingMenu;} + +protected: + UIControl_SlotList m_slotListIngredient; + UIControl_Label m_labelEnchant; + UIControl_EnchantmentButton m_enchantButton[3]; + UIControl_EnchantmentBook m_enchantBook; + + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene_AbstractContainerMenu) + UI_BEGIN_MAP_CHILD_ELEMENTS( m_controlMainPanel ) + UI_MAP_ELEMENT( m_slotListIngredient, "ingredient") + UI_MAP_ELEMENT( m_enchantButton[0], "Button1") + UI_MAP_ELEMENT( m_enchantButton[1], "Button2") + UI_MAP_ELEMENT( m_enchantButton[2], "Button3") + UI_MAP_ELEMENT( m_labelEnchant, "enchantLabel") + + UI_MAP_ELEMENT( m_enchantBook, "iggy_EnchantmentBook") + UI_END_MAP_CHILD_ELEMENTS() + UI_END_MAP_ELEMENTS_AND_NAMES() + + virtual wstring getMoviePath(); + virtual void handleReload(); + + virtual int getSectionColumns(ESceneSection eSection); + virtual int getSectionRows(ESceneSection eSection); + virtual void GetPositionOfSection( ESceneSection eSection, UIVec2D* pPosition ); + virtual void GetItemScreenData( ESceneSection eSection, int iItemIndex, UIVec2D* pPosition, UIVec2D* pSize ); + virtual void handleSectionClick(ESceneSection eSection) {} + virtual void setSectionSelectedSlot(ESceneSection eSection, int x, int y); + + virtual UIControl *getSection(ESceneSection eSection); + + virtual void customDraw(IggyCustomDrawCallbackRegion *region); +};
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIScene_EndPoem.cpp b/Minecraft.Client/Common/UI/UIScene_EndPoem.cpp new file mode 100644 index 00000000..f825efd0 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_EndPoem.cpp @@ -0,0 +1,271 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIScene_EndPoem.h" +#include "UIBitmapFont.h" +#include "..\..\Minecraft.h" +#include "..\..\MultiplayerLocalPlayer.h" +#include "..\..\..\Minecraft.World\StringHelpers.h" + +UIScene_EndPoem::UIScene_EndPoem(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) +{ + + //ui.setFontCachingCalculationBuffer(20000); + + // Setup all the Iggy references we need for this scene + initialiseMovie(); + + m_bIgnoreInput = false; + + // 4J Stu - Don't need these, the AS handles the scrolling and makes it look nice +#if 0 + wstring halfScreenLineBreaks; + + if(RenderManager.IsHiDef()) + { + // HD - 17 line page + halfScreenLineBreaks = L"<br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br />"; + } + else + { + // 480 - 14 line page + halfScreenLineBreaks = L"<br /><br /><br /><br /><br /><br /><br /><br />"; + } +#endif + + //wchar_t startTags[64]; + //swprintf(startTags,64,L"<font size=\"%d\">",app.GetHTMLFontSize(eHTMLSize_EndPoem)); + //noNoiseString.append(halfScreenLineBreaks); + //noNoiseString.append(halfScreenLineBreaks); + noNoiseString.append( app.GetString(IDS_WIN_TEXT) ); + noNoiseString.append( app.GetString(IDS_WIN_TEXT_PART_2) ); + noNoiseString.append( app.GetString(IDS_WIN_TEXT_PART_3) ); + + //noNoiseString.append(halfScreenLineBreaks); + + // 4J Stu - Iggy seems to strip our trailing linebreaks, so added a space to made sure it scrolls this far + noNoiseString.append( L" " ); + + noNoiseString = app.FormatHTMLString(m_iPad, noNoiseString, 0xff000000); + + Minecraft *pMinecraft = Minecraft::GetInstance(); + + wstring playerName = L""; + if(pMinecraft->localplayers[ui.GetWinUserIndex()] != NULL) + { + playerName = escapeXML( pMinecraft->localplayers[ui.GetWinUserIndex()]->getDisplayName() ); + } + else + { + playerName = escapeXML( pMinecraft->localplayers[ProfileManager.GetPrimaryPad()]->getDisplayName() ); + } + noNoiseString = replaceAll(noNoiseString,L"{*PLAYER*}",playerName); + + Random random(8124371); + int found=(int)noNoiseString.find(L"{*NOISE*}"); + int length; + while (found!=string::npos) + { + length = random.nextInt(4) + 3; + m_noiseLengths.push_back(length); + found=(int)noNoiseString.find(L"{*NOISE*}",found+1); + } + + updateNoise(); + + + // 4J-JEV: Find paragraph start and end points. + m_paragraphs = vector<wstring>(); + int lastIndex = 0; + for ( int index = 0; + index != wstring::npos; + index = noiseString.find(L"<br /><br />", index+12, 12) + ) + { + m_paragraphs.push_back( noiseString.substr(lastIndex, index-lastIndex) ); + lastIndex = index; + } + //lastIndex += 12; + m_paragraphs.push_back( noiseString.substr( lastIndex, noiseString.length() - lastIndex ) ); + + //m_htmlPoem.init(noiseString.c_str()); + //m_htmlPoem.startAutoScroll(); + + //wstring result = m_htmlControl.GetText(); + + //wcout << result.c_str(); + +#if TO_BE_IMPLEMENTED + m_scrollDir = 1; + HRESULT hr = XuiHtmlControlSetSmoothScroll(m_htmlControl.m_hObj, XUI_SMOOTHSCROLL_VERTICAL,TRUE,AUTO_SCROLL_SPEED,1.0f,AUTO_SCROLL_SPEED); + XuiHtmlControlVScrollBy(m_htmlControl.m_hObj,m_scrollDir * 1000); + + SetTimer(0,200); +#endif + + m_requestedLabel = 0; +} + +wstring UIScene_EndPoem::getMoviePath() +{ + return L"EndPoem"; +} + +void UIScene_EndPoem::updateTooltips() +{ + ui.SetTooltips( XUSER_INDEX_ANY, -1, m_bIgnoreInput?-1:IDS_TOOLTIPS_CONTINUE); +} + +void UIScene_EndPoem::tick() +{ + UIScene::tick(); + + if( m_requestedLabel >= 0 && m_requestedLabel < m_paragraphs.size()) + { + wstring label = m_paragraphs[m_requestedLabel]; + + IggyDataValue result; + IggyDataValue value[3]; + + IggyStringUTF16 stringVal; + stringVal.string = (IggyUTF16*)label.c_str(); + stringVal.length = label.length(); + value[0].type = IGGY_DATATYPE_string_UTF16; + value[0].string16 = stringVal; + + value[1].type = IGGY_DATATYPE_number; + value[1].number = m_requestedLabel; + + value[2].type = IGGY_DATATYPE_boolean; + value[2].boolval = (m_requestedLabel == (m_paragraphs.size() - 1)); + + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcSetNextLabel , 3 , value ); + + m_requestedLabel = -1; + } +} + +void UIScene_EndPoem::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled) +{ + if(m_bIgnoreInput) return; + + if(pressed) ui.AnimateKeyPress(iPad, key, repeat, pressed, released); + + switch(key) + { + case ACTION_MENU_CANCEL: + if(pressed) + { + m_bIgnoreInput = true; + Minecraft *pMinecraft = Minecraft::GetInstance(); + for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i) + { + if(pMinecraft->localplayers[i] != NULL) + { + app.SetAction(i,eAppAction_Respawn); + } + } + + // This just allows it to be shown + if(pMinecraft->localgameModes[ProfileManager.GetPrimaryPad()] != NULL) pMinecraft->localgameModes[ProfileManager.GetPrimaryPad()]->getTutorial()->showTutorialPopup(true); + + updateTooltips(); + navigateBack(); + + handled = true; + } + break; + case ACTION_MENU_DOWN: + case ACTION_MENU_UP: + case ACTION_MENU_OTHER_STICK_DOWN: + case ACTION_MENU_OTHER_STICK_UP: + sendInputToMovie(key, repeat, pressed, released); + break; + } +} + +void UIScene_EndPoem::handleDestroy() +{ + + //ui.setFontCachingCalculationBuffer(-1); +} + +void UIScene_EndPoem::handleRequestMoreData(F64 startIndex, bool up) +{ + m_requestedLabel = (int)startIndex; +} + +void UIScene_EndPoem::updateNoise() +{ + Minecraft *pMinecraft = Minecraft::GetInstance(); + noiseString = noNoiseString; + + int length = 0; + wchar_t replacements[64]; + wstring replaceString = L""; + wchar_t randomChar = L'a'; + Random *random = pMinecraft->font->random; + + bool darken = false; + + wstring tag = L"{*NOISE*}"; + + AUTO_VAR(it, m_noiseLengths.begin()); + int found=(int)noiseString.find(tag); + while (found!=string::npos && it != m_noiseLengths.end() ) + { + length = *it; + ++it; + + replaceString = L""; + for(int i = 0; i < length; ++i) + { + randomChar = SharedConstants::acceptableLetters[random->nextInt((int)SharedConstants::acceptableLetters.length())]; + + wstring randomCharStr = L""; + randomCharStr.push_back(randomChar); + if(randomChar == L'<') + { + randomCharStr = L"<"; + } + else if (randomChar == L'>' ) + { + randomCharStr = L">"; + } + else if(randomChar == L'"') + { + randomCharStr = L"""; + } + else if(randomChar == L'&') + { + randomCharStr = L"&"; + } + else if(randomChar == L'\\') + { + randomCharStr = L"\\\\"; + } + else if(randomChar == L'{') + { + randomCharStr = L"}"; + } + + int randomVal = random->nextInt(2); + eMinecraftColour colour = eHTMLColor_8; + if(randomVal == 1) colour = eHTMLColor_9; + else if(randomVal == 2) colour = eHTMLColor_a; + ZeroMemory(replacements,64*sizeof(wchar_t)); + swprintf(replacements,64,L"<font color=\"#%08x\" shadowcolor=\"#80000000\">%ls</font>",app.GetHTMLColour(colour),randomCharStr.c_str()); + replaceString.append(replacements); + } + + noiseString.replace( found, tag.length(), replaceString ); + + //int pos = 0; + //do { + // pos = random->nextInt(SharedConstants::acceptableLetters.length()); + //} while (pMinecraft->font->charWidths[ch + 32] != pMinecraft->font->charWidths[pos + 32]); + //ib.put(listPos + 256 + random->nextInt(2) + 8 + (darken ? 16 : 0)); + //ib.put(listPos + pos + 32); + + found=(int)noiseString.find(tag,found+1); + } +}
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIScene_EndPoem.h b/Minecraft.Client/Common/UI/UIScene_EndPoem.h new file mode 100644 index 00000000..75024f68 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_EndPoem.h @@ -0,0 +1,41 @@ +#pragma once + +#include "UIScene.h" + +class UIScene_EndPoem : public UIScene +{ +private: + wstring noNoiseString; + wstring noiseString; + vector<int> m_noiseLengths; + bool m_bIgnoreInput; + int m_requestedLabel; + + vector<wstring> m_paragraphs; + + IggyName m_funcSetNextLabel; + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) + UI_MAP_NAME(m_funcSetNextLabel, L"SetNextLabel") + UI_END_MAP_ELEMENTS_AND_NAMES() + +public: + UIScene_EndPoem(int iPad, void *initData, UILayer *parentLayer); + + virtual EUIScene getSceneType() { return eUIScene_EndPoem;} + virtual void updateTooltips(); + +protected: + virtual wstring getMoviePath(); + +public: + virtual void tick(); + + // INPUT + virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled); + virtual void handleDestroy(); + + virtual void handleRequestMoreData(F64 startIndex, bool up); + +private: + void updateNoise(); +};
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIScene_FullscreenProgress.cpp b/Minecraft.Client/Common/UI/UIScene_FullscreenProgress.cpp new file mode 100644 index 00000000..ed31cfaf --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_FullscreenProgress.cpp @@ -0,0 +1,374 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIScene_FullscreenProgress.h" +#include "..\..\Minecraft.h" +#include "..\..\ProgressRenderer.h" + + +UIScene_FullscreenProgress::UIScene_FullscreenProgress(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) +{ + // Setup all the Iggy references we need for this scene + initialiseMovie(); + + parentLayer->addComponent(iPad,eUIComponent_Panorama); + parentLayer->addComponent(iPad,eUIComponent_Logo); + parentLayer->showComponent(iPad,eUIComponent_Logo,true); + parentLayer->showComponent(iPad,eUIComponent_MenuBackground,false); + + m_controlTimer.setVisible( false ); + + m_titleText = L""; + m_statusText = L""; + + m_lastTitle = -1; + m_lastStatus = -1; + m_lastProgress = 0; + + m_buttonConfirm.init( app.GetString( IDS_CONFIRM_OK ), eControl_Confirm ); + m_buttonConfirm.setVisible(false); + + LoadingInputParams *params = (LoadingInputParams *)initData; + + m_CompletionData = params->completionData; + m_iPad=params->completionData->iPad; + m_cancelFunc = params->cancelFunc; + m_cancelFuncParam = params->m_cancelFuncParam; + m_completeFunc = params->completeFunc; + m_completeFuncParam = params->m_completeFuncParam; + + m_cancelText = params->cancelText; + m_bWasCancelled=false; + m_bWaitForThreadToDelete = params->waitForThreadToDelete; + + // Clear the progress text + Minecraft *pMinecraft=Minecraft::GetInstance(); + pMinecraft->progressRenderer->progressStart(-1); + pMinecraft->progressRenderer->progressStage(-1); + m_progressBar.init(L"",0,0,100,0); + + // set the tip + wstring wsText= app.FormatHTMLString(m_iPad,app.GetString(app.GetNextTip())); + + wchar_t startTags[64]; + swprintf(startTags,64,L"<font color=\"#%08x\"><p align=center>",app.GetHTMLColour(eHTMLColor_White)); + wsText= startTags + wsText + L"</p>"; + m_labelTip.init(wsText); + + addTimer(TIMER_FULLSCREEN_TIPS, TIMER_FULLSCREEN_TIPS_TIME); + + m_labelTitle.init(L""); + + m_labelTip.setVisible( m_CompletionData->bShowTips ); + + thread = new C4JThread(params->func, params->lpParam, "FullscreenProgress"); + thread->SetProcessor(CPU_CORE_UI_SCENE); // TODO 4J Stu - Make sure this is a good thread/core to use + + m_threadCompleted = false; + thread->Run(); + threadStarted = true; + +#ifdef __PSVITA__ + ui.TouchBoxRebuild(this); +#endif + +#ifdef _XBOX_ONE + ui.ShowPlayerDisplayname(false); +#endif +} + +UIScene_FullscreenProgress::~UIScene_FullscreenProgress() +{ + m_parentLayer->removeComponent(eUIComponent_Panorama); + m_parentLayer->removeComponent(eUIComponent_Logo); + + delete thread; + + delete m_CompletionData; +} + +wstring UIScene_FullscreenProgress::getMoviePath() +{ + return L"FullscreenProgress"; +} + +void UIScene_FullscreenProgress::updateTooltips() +{ + ui.SetTooltips( m_parentLayer->IsFullscreenGroup()?XUSER_INDEX_ANY:m_iPad, m_threadCompleted?IDS_TOOLTIPS_SELECT:-1, m_threadCompleted?-1:m_cancelText, -1, -1 ); +} + +void UIScene_FullscreenProgress::handleDestroy() +{ + int code = thread->GetExitCode(); + DWORD exitcode = *((DWORD *)&code); + + // If we're active, have a cancel func, and haven't already cancelled, call cancel func + if( exitcode == STILL_ACTIVE && m_cancelFunc != NULL && !m_bWasCancelled) + { + m_bWasCancelled = true; + m_cancelFunc(m_cancelFuncParam); + } +} + +void UIScene_FullscreenProgress::tick() +{ + UIScene::tick(); + + Minecraft *pMinecraft=Minecraft::GetInstance(); + + int currentProgress = pMinecraft->progressRenderer->getCurrentPercent(); + if(currentProgress < 0) currentProgress = 0; + if(currentProgress != m_lastProgress) + { + m_lastProgress = currentProgress; + m_progressBar.setProgress(currentProgress); + //app.DebugPrintf("Updated progress value\n"); + } + + int title = pMinecraft->progressRenderer->getCurrentTitle(); + if(title >= 0 && title != m_lastTitle) + { + m_lastTitle = title; + m_titleText = app.GetString( title ); + m_labelTitle.setLabel(m_titleText); + } + + ProgressRenderer::eProgressStringType eProgressType=pMinecraft->progressRenderer->getType(); + + if(eProgressType==ProgressRenderer::eProgressStringType_ID) + { + int status = pMinecraft->progressRenderer->getCurrentStatus(); + if(status >= 0 && status != m_lastStatus) + { + m_lastStatus = status; + m_statusText = app.GetString( status ); + m_progressBar.setLabel(m_statusText.c_str()); + } + } + else + { + wstring& wstrText = pMinecraft->progressRenderer->getProgressString(); + m_progressBar.setLabel(wstrText.c_str()); + } + + + int code = thread->GetExitCode(); + DWORD exitcode = *((DWORD *)&code); + + //app.DebugPrintf("CScene_FullscreenProgress Timer %d\n",pTimer->nId); + + if( exitcode != STILL_ACTIVE ) + { + // If we failed (currently used by network connection thread), navigate back + if( exitcode != S_OK ) + { + if( exitcode == ERROR_CANCELLED ) + { + // Current thread cancelled for whatever reason + // Currently used only for the CConsoleMinecraftApp::RemoteSaveThreadProc thread + // Assume to just ignore this thread as something else is now running that will + // cause another action + } + else + { + /*m_threadCompleted = true; + m_buttonConfirm.SetShow( TRUE ); + m_buttonConfirm.SetFocus( m_CompletionData->iPad ); + m_CompletionData->type = e_ProgressCompletion_NavigateToHomeMenu; + + int exitReasonStringId; + switch( app.GetDisconnectReason() ) + { + default: + exitReasonStringId = IDS_CONNECTION_FAILED; + } + Minecraft *pMinecraft=Minecraft::GetInstance(); + pMinecraft->progressRenderer->progressStartNoAbort( exitReasonStringId );*/ + //app.NavigateBack(m_CompletionData->iPad); + + UINT uiIDA[1]; + uiIDA[0]=IDS_CONFIRM_OK; + ui.RequestMessageBox( g_NetworkManager.CorrectErrorIDS(IDS_CONNECTION_FAILED), g_NetworkManager.CorrectErrorIDS(IDS_CONNECTION_LOST_SERVER), uiIDA,1, XUSER_INDEX_ANY,NULL,NULL, app.GetStringTable()); + + ui.NavigateToHomeMenu(); + ui.UpdatePlayerBasePositions(); + } + } + else + { + if(( m_CompletionData->bRequiresUserAction == TRUE ) && (!m_bWasCancelled)) + { + m_threadCompleted = true; + m_buttonConfirm.setVisible( true ); + updateTooltips(); + } + else + { + if(m_bWasCancelled) + { + m_threadCompleted = true; + } + app.DebugPrintf("FullScreenProgress complete with action: "); + switch(m_CompletionData->type) + { + case e_ProgressCompletion_AutosaveNavigateBack: + app.DebugPrintf("e_ProgressCompletion_AutosaveNavigateBack\n"); + { + // 4J Stu - Fix for #65437 - Customer Encountered: Code: Settings: Autosave option doesn't work when the Host goes into idle state during gameplay. + // Autosave obviously cannot occur if an ignore autosave menu is displayed, so even if we navigate back to a scene and not empty + // then we still want to reset this flag which was set true by the navigate to the fullscreen progress + ui.SetIgnoreAutosaveMenuDisplayed(m_iPad, false); + + // This just allows it to be shown + Minecraft *pMinecraft = Minecraft::GetInstance(); + if(pMinecraft->localgameModes[ProfileManager.GetPrimaryPad()] != NULL) pMinecraft->localgameModes[ProfileManager.GetPrimaryPad()]->getTutorial()->showTutorialPopup(true); + ui.UpdatePlayerBasePositions(); + navigateBack(); + } + break; + + case e_ProgressCompletion_NavigateBack: + app.DebugPrintf("e_ProgressCompletion_NavigateBack\n"); + { + ui.UpdatePlayerBasePositions(); + navigateBack(); + } + break; + case e_ProgressCompletion_NavigateBackToScene: + app.DebugPrintf("e_ProgressCompletion_NavigateBackToScene\n"); + ui.UpdatePlayerBasePositions(); + // 4J Stu - If used correctly this scene will not have interfered with any other scene at all, so just navigate back + navigateBack(); + break; + case e_ProgressCompletion_CloseUIScenes: + app.DebugPrintf("e_ProgressCompletion_CloseUIScenes\n"); + ui.CloseUIScenes(m_CompletionData->iPad); + ui.UpdatePlayerBasePositions(); + break; + case e_ProgressCompletion_CloseAllPlayersUIScenes: + app.DebugPrintf("e_ProgressCompletion_CloseAllPlayersUIScenes\n"); + ui.CloseAllPlayersScenes(); + ui.UpdatePlayerBasePositions(); + break; + case e_ProgressCompletion_NavigateToHomeMenu: + app.DebugPrintf("e_ProgressCompletion_NavigateToHomeMenu\n"); + ui.NavigateToHomeMenu(); + ui.UpdatePlayerBasePositions(); + break; + default: + app.DebugPrintf("Default\n"); + break; + } + } + } + } +} + +void UIScene_FullscreenProgress::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled) +{ + //if( m_showTooltips ) + { + //ui.AnimateKeyPress(m_iPad, key, repeat, pressed, released); + + switch(key) + { + case ACTION_MENU_OK: +#ifdef __ORBIS__ + case ACTION_MENU_TOUCHPAD_PRESS: +#endif + if(pressed) + { + sendInputToMovie(key, repeat, pressed, released); + } + break; + case ACTION_MENU_B: + case ACTION_MENU_CANCEL: + if( pressed && m_cancelFunc != NULL && !m_bWasCancelled ) + { + m_bWasCancelled = true; + m_cancelFunc( m_cancelFuncParam ); + } + break; + } + } +} + +void UIScene_FullscreenProgress::handlePress(F64 controlId, F64 childId) +{ + if(m_threadCompleted && (int)controlId == eControl_Confirm) + { + // This assumes all buttons can only be pressed with the A button + ui.AnimateKeyPress(m_iPad, ACTION_MENU_A, false, true, false); + + // if there's a complete function, call it + if(m_completeFunc) + { + m_completeFunc(m_completeFuncParam); + } + + switch(m_CompletionData->type) + { + case e_ProgressCompletion_NavigateBack: + app.DebugPrintf("e_ProgressCompletion_NavigateBack\n"); + { + ui.UpdatePlayerBasePositions(); + navigateBack(); + } + break; + case e_ProgressCompletion_NavigateBackToScene: + app.DebugPrintf("e_ProgressCompletion_NavigateBackToScene\n"); + ui.UpdatePlayerBasePositions(); + // 4J Stu - If used correctly this scene will not have interfered with any other scene at all, so just navigate back + navigateBack(); + break; + case e_ProgressCompletion_CloseUIScenes: + app.DebugPrintf("e_ProgressCompletion_CloseUIScenes\n"); + ui.CloseUIScenes(m_CompletionData->iPad); + ui.UpdatePlayerBasePositions(); + break; + case e_ProgressCompletion_CloseAllPlayersUIScenes: + app.DebugPrintf("e_ProgressCompletion_CloseAllPlayersUIScenes\n"); + ui.CloseAllPlayersScenes(); + ui.UpdatePlayerBasePositions(); + break; + case e_ProgressCompletion_NavigateToHomeMenu: + app.DebugPrintf("e_ProgressCompletion_NavigateToHomeMenu\n"); + ui.NavigateToHomeMenu(); + ui.UpdatePlayerBasePositions(); + break; + } + } +} + +void UIScene_FullscreenProgress::handleTimerComplete(int id) +{ + switch(id) + { + case TIMER_FULLSCREEN_TIPS: + { + // display the next tip + wstring wsText=app.FormatHTMLString(m_iPad,app.GetString(app.GetNextTip())); + wchar_t startTags[64]; + swprintf(startTags,64,L"<font color=\"#%08x\"><p align=center>",app.GetHTMLColour(eHTMLColor_White)); + wsText= startTags + wsText + L"</p>"; + m_labelTip.setLabel(wsText); + } + break; + } +} + +void UIScene_FullscreenProgress::SetWasCancelled(bool wasCancelled) +{ + m_bWasCancelled = wasCancelled; +} + +bool UIScene_FullscreenProgress::isReadyToDelete() +{ + if( m_bWaitForThreadToDelete ) + { + return !thread->isRunning(); + } + else + { + return true; + } +}
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIScene_FullscreenProgress.h b/Minecraft.Client/Common/UI/UIScene_FullscreenProgress.h new file mode 100644 index 00000000..aeb428c3 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_FullscreenProgress.h @@ -0,0 +1,69 @@ +#pragma once + +#include "UIScene.h" + +class UIScene_FullscreenProgress : public UIScene +{ +private: + enum EControl + { + eControl_Confirm, + }; + + static const int TIMER_FULLSCREEN_TIPS = 1; + static const int TIMER_FULLSCREEN_TIPS_TIME = 7000; + + C4JThread* thread; + bool threadStarted; + UIFullscreenProgressCompletionData *m_CompletionData; + bool m_threadCompleted; + int m_iPad; + void (*m_cancelFunc)(LPVOID param); + void (*m_completeFunc)(LPVOID param); + LPVOID m_cancelFuncParam; + LPVOID m_completeFuncParam; + bool m_bWaitForThreadToDelete; + + wstring m_titleText, m_statusText; + int m_lastTitle, m_lastStatus, m_lastProgress; + int m_cancelText; + bool m_bWasCancelled; + + UIControl_Progress m_progressBar; + UIControl_Label m_labelTitle, m_labelTip; + UIControl_Button m_buttonConfirm; + UIControl m_controlTimer; + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) + UI_MAP_ELEMENT( m_progressBar, "ProgressBar") + UI_MAP_ELEMENT( m_labelTitle, "Title") + UI_MAP_ELEMENT( m_labelTip, "Tip") + UI_MAP_ELEMENT( m_buttonConfirm, "Confirm") + UI_MAP_ELEMENT( m_controlTimer, "Timer") + UI_END_MAP_ELEMENTS_AND_NAMES() +public: + UIScene_FullscreenProgress(int iPad, void *initData, UILayer *parentLayer); + virtual ~UIScene_FullscreenProgress(); + + virtual EUIScene getSceneType() { return eUIScene_FullscreenProgress;} + virtual void updateTooltips(); + virtual void handleDestroy(); + + void tick(); + +protected: + // TODO: This should be pure virtual in this class + virtual wstring getMoviePath(); + + virtual long long getDefaultGtcButtons() { return 0; } + +public: + // INPUT + virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled); + void handlePress(F64 controlId, F64 childId); + + virtual void handleTimerComplete(int id); + + void SetWasCancelled(bool wasCancelled); + + virtual bool isReadyToDelete(); +}; diff --git a/Minecraft.Client/Common/UI/UIScene_FurnaceMenu.cpp b/Minecraft.Client/Common/UI/UIScene_FurnaceMenu.cpp new file mode 100644 index 00000000..1ba4053d --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_FurnaceMenu.cpp @@ -0,0 +1,256 @@ +#include "stdafx.h" +#include "UI.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.level.tile.entity.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.inventory.h" +#include "..\..\Minecraft.h" +#include "UIScene_FurnaceMenu.h" + +UIScene_FurnaceMenu::UIScene_FurnaceMenu(int iPad, void *_initData, UILayer *parentLayer) : UIScene_AbstractContainerMenu(iPad, parentLayer) +{ + // Setup all the Iggy references we need for this scene + initialiseMovie(); + + m_labelFurnace.init(app.GetString(IDS_FURNACE)); + m_labelIngredient.init(app.GetString(IDS_INGREDIENT)); + m_labelFuel.init(app.GetString(IDS_FUEL)); + + m_progressFurnaceFire.init(L"",0,0,12,0); + m_progressFurnaceArrow.init(L"",0,0,24,0); + + FurnaceScreenInput *initData = (FurnaceScreenInput *)_initData; + m_furnace = initData->furnace; + + Minecraft *pMinecraft = Minecraft::GetInstance(); + if( pMinecraft->localgameModes[initData->iPad] != NULL ) + { + TutorialMode *gameMode = (TutorialMode *)pMinecraft->localgameModes[initData->iPad]; + m_previousTutorialState = gameMode->getTutorial()->getCurrentState(); + gameMode->getTutorial()->changeTutorialState(e_Tutorial_State_Furnace_Menu, this); + } + + FurnaceMenu* menu = new FurnaceMenu( initData->inventory, initData->furnace ); + + Initialize( initData->iPad, menu, true, FurnaceMenu::INV_SLOT_START, eSectionFurnaceUsing, eSectionFurnaceMax ); + + m_slotListFuel.addSlots(FurnaceMenu::FUEL_SLOT, 1); + m_slotListIngredient.addSlots(FurnaceMenu::INGREDIENT_SLOT, 1); + m_slotListResult.addSlots(FurnaceMenu::RESULT_SLOT, 1); + + app.SetRichPresenceContext(m_iPad,CONTEXT_GAME_STATE_FORGING); + + delete initData; +} + +wstring UIScene_FurnaceMenu::getMoviePath() +{ + if(app.GetLocalPlayerCount() > 1) + { + return L"FurnaceMenuSplit"; + } + else + { + return L"FurnaceMenu"; + } +} + +void UIScene_FurnaceMenu::handleReload() +{ + Initialize( m_iPad, m_menu, true, FurnaceMenu::INV_SLOT_START, eSectionFurnaceUsing, eSectionFurnaceMax ); + + m_slotListFuel.addSlots(FurnaceMenu::FUEL_SLOT, 1); + m_slotListIngredient.addSlots(FurnaceMenu::INGREDIENT_SLOT, 1); + m_slotListResult.addSlots(FurnaceMenu::RESULT_SLOT, 1); +} + +void UIScene_FurnaceMenu::tick() +{ + m_progressFurnaceFire.setProgress( m_furnace->getLitProgress( 12 ) ); + m_progressFurnaceArrow.setProgress( m_furnace->getBurnProgress( 24 ) ); + UIScene_AbstractContainerMenu::tick(); +} + +int UIScene_FurnaceMenu::getSectionColumns(ESceneSection eSection) +{ + int cols = 0; + switch( eSection ) + { + case eSectionFurnaceResult: + cols = 1; + break; + case eSectionFurnaceFuel: + cols = 1; + break; + case eSectionFurnaceIngredient: + cols = 1; + break; + case eSectionFurnaceInventory: + cols = 9; + break; + case eSectionFurnaceUsing: + cols = 9; + break; + default: + assert( false ); + break; + } + return cols; +} + +int UIScene_FurnaceMenu::getSectionRows(ESceneSection eSection) +{ + int rows = 0; + switch( eSection ) + { + case eSectionFurnaceResult: + rows = 1; + break; + case eSectionFurnaceFuel: + rows = 1; + break; + case eSectionFurnaceIngredient: + rows = 1; + break; + case eSectionFurnaceInventory: + rows = 3; + break; + case eSectionFurnaceUsing: + rows = 1; + break; + default: + assert( false ); + break; + } + return rows; +} + +void UIScene_FurnaceMenu::GetPositionOfSection( ESceneSection eSection, UIVec2D* pPosition ) +{ + switch( eSection ) + { + case eSectionFurnaceResult: + pPosition->x = m_slotListResult.getXPos(); + pPosition->y = m_slotListResult.getYPos(); + break; + case eSectionFurnaceFuel: + pPosition->x = m_slotListFuel.getXPos(); + pPosition->y = m_slotListFuel.getYPos(); + break; + case eSectionFurnaceIngredient: + pPosition->x = m_slotListIngredient.getXPos(); + pPosition->y = m_slotListIngredient.getYPos(); + break; + case eSectionFurnaceInventory: + pPosition->x = m_slotListInventory.getXPos(); + pPosition->y = m_slotListInventory.getYPos(); + break; + case eSectionFurnaceUsing: + pPosition->x = m_slotListHotbar.getXPos(); + pPosition->y = m_slotListHotbar.getYPos(); + break; + default: + assert( false ); + break; + } +} + +void UIScene_FurnaceMenu::GetItemScreenData( ESceneSection eSection, int iItemIndex, UIVec2D* pPosition, UIVec2D* pSize ) +{ + UIVec2D sectionSize; + switch( eSection ) + { + case eSectionFurnaceResult: + sectionSize.x = m_slotListResult.getWidth(); + sectionSize.y = m_slotListResult.getHeight(); + break; + case eSectionFurnaceFuel: + sectionSize.x = m_slotListFuel.getWidth(); + sectionSize.y = m_slotListFuel.getHeight(); + break; + case eSectionFurnaceIngredient: + sectionSize.x = m_slotListIngredient.getWidth(); + sectionSize.y = m_slotListIngredient.getHeight(); + break; + case eSectionFurnaceInventory: + sectionSize.x = m_slotListInventory.getWidth(); + sectionSize.y = m_slotListInventory.getHeight(); + break; + case eSectionFurnaceUsing: + sectionSize.x = m_slotListHotbar.getWidth(); + sectionSize.y = m_slotListHotbar.getHeight(); + break; + default: + assert( false ); + break; + } + + int rows = getSectionRows(eSection); + int cols = getSectionColumns(eSection); + + pSize->x = sectionSize.x/cols; + pSize->y = sectionSize.y/rows; + + int itemCol = iItemIndex % cols; + int itemRow = iItemIndex/cols; + + pPosition->x = itemCol * pSize->x; + pPosition->y = itemRow * pSize->y; +} + +void UIScene_FurnaceMenu::setSectionSelectedSlot(ESceneSection eSection, int x, int y) +{ + int cols = getSectionColumns(eSection); + + int index = (y * cols) + x; + + UIControl_SlotList *slotList = NULL; + switch( eSection ) + { + case eSectionFurnaceResult: + slotList = &m_slotListResult; + break; + case eSectionFurnaceFuel: + slotList = &m_slotListFuel; + break; + case eSectionFurnaceIngredient: + slotList = &m_slotListIngredient; + break; + case eSectionFurnaceInventory: + slotList = &m_slotListInventory; + break; + case eSectionFurnaceUsing: + slotList = &m_slotListHotbar; + break; + default: + assert( false ); + break; + } + + slotList->setHighlightSlot(index); +} + +UIControl *UIScene_FurnaceMenu::getSection(ESceneSection eSection) +{ + UIControl *control = NULL; + switch( eSection ) + { + case eSectionFurnaceResult: + control = &m_slotListResult; + break; + case eSectionFurnaceFuel: + control = &m_slotListFuel; + break; + case eSectionFurnaceIngredient: + control = &m_slotListIngredient; + break; + case eSectionFurnaceInventory: + control = &m_slotListInventory; + break; + case eSectionFurnaceUsing: + control = &m_slotListHotbar; + break; + default: + assert( false ); + break; + } + return control; +} diff --git a/Minecraft.Client/Common/UI/UIScene_FurnaceMenu.h b/Minecraft.Client/Common/UI/UIScene_FurnaceMenu.h new file mode 100644 index 00000000..dcea967e --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_FurnaceMenu.h @@ -0,0 +1,50 @@ +#pragma once + +#include "UIScene_AbstractContainerMenu.h" +#include "IUIScene_FurnaceMenu.h" + +class InventoryMenu; + +class UIScene_FurnaceMenu : public UIScene_AbstractContainerMenu, public IUIScene_FurnaceMenu +{ +private: + shared_ptr<FurnaceTileEntity> m_furnace; + +public: + UIScene_FurnaceMenu(int iPad, void *initData, UILayer *parentLayer); + + virtual EUIScene getSceneType() { return eUIScene_FurnaceMenu;} + +protected: + UIControl_SlotList m_slotListFuel, m_slotListIngredient, m_slotListResult; + UIControl_Label m_labelFurnace, m_labelIngredient, m_labelFuel; + UIControl_Progress m_progressFurnaceFire, m_progressFurnaceArrow; + + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene_AbstractContainerMenu) + UI_BEGIN_MAP_CHILD_ELEMENTS( m_controlMainPanel ) + UI_MAP_ELEMENT( m_slotListIngredient, "Ingredient") + UI_MAP_ELEMENT( m_slotListFuel, "Fuel") + UI_MAP_ELEMENT( m_slotListResult, "Result") + UI_MAP_ELEMENT( m_labelFurnace, "Furnace_text") + UI_MAP_ELEMENT( m_labelIngredient, "Ingredient_Label") + UI_MAP_ELEMENT( m_labelFuel, "Fuel_Label") + + UI_MAP_ELEMENT( m_progressFurnaceFire, "FurnaceFire") + UI_MAP_ELEMENT( m_progressFurnaceArrow, "FurnaceArrow") + UI_END_MAP_CHILD_ELEMENTS() + UI_END_MAP_ELEMENTS_AND_NAMES() + + virtual wstring getMoviePath(); + virtual void handleReload(); + + virtual void tick(); + + virtual int getSectionColumns(ESceneSection eSection); + virtual int getSectionRows(ESceneSection eSection); + virtual void GetPositionOfSection( ESceneSection eSection, UIVec2D* pPosition ); + virtual void GetItemScreenData( ESceneSection eSection, int iItemIndex, UIVec2D* pPosition, UIVec2D* pSize ); + virtual void handleSectionClick(ESceneSection eSection) {} + virtual void setSectionSelectedSlot(ESceneSection eSection, int x, int y); + + virtual UIControl *getSection(ESceneSection eSection); +};
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIScene_HUD.cpp b/Minecraft.Client/Common/UI/UIScene_HUD.cpp new file mode 100644 index 00000000..27eeb76b --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_HUD.cpp @@ -0,0 +1,997 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIScene_HUD.h" +#include "..\..\Minecraft.h" +#include "..\..\MultiplayerLocalPlayer.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.entity.boss.enderdragon.h" +#include "..\..\EnderDragonRenderer.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.inventory.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.item.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.effect.h" +#include "..\..\..\Minecraft.World\StringHelpers.h" + +UIScene_HUD::UIScene_HUD(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) +{ + m_bSplitscreen = false; + + // Setup all the Iggy references we need for this scene + initialiseMovie(); + + m_lastActiveSlot = 0; + m_lastScale = 1; + m_bToolTipsVisible = true; + m_lastExpProgress = 0.0f; + m_lastExpLevel = 0; + m_lastMaxHealth = 20; + m_lastHealthBlink = false; + m_lastHealthPoison = false; + m_lastMaxFood = 20; + m_lastFoodPoison = false; + m_lastAir = 10; + m_lastArmour = 0; + m_showHealth = true; + m_showFood = true; + m_showAir = true; + m_showArmour = true; + m_showExpBar = true; + m_lastRegenEffect = false; + m_lastSaturation = 0; + m_lastDragonHealth = 0.0f; + m_showDragonHealth = false; + m_ticksWithNoBoss = 0; + m_uiSelectedItemOpacityCountDown = 0; + m_displayName = L""; + m_lastShowDisplayName = true; + + SetDragonLabel( app.GetString( IDS_BOSS_ENDERDRAGON_HEALTH ) ); + SetSelectedLabel(L""); + + for(unsigned int i = 0; i < CHAT_LINES_COUNT; ++i) + { + m_labelChatText[i].init(L""); + } + m_labelJukebox.init(L""); + + addTimer(0, 100); +} + +wstring UIScene_HUD::getMoviePath() +{ + switch( m_parentLayer->getViewport() ) + { + case C4JRender::VIEWPORT_TYPE_SPLIT_TOP: + case C4JRender::VIEWPORT_TYPE_SPLIT_BOTTOM: + case C4JRender::VIEWPORT_TYPE_SPLIT_LEFT: + case C4JRender::VIEWPORT_TYPE_SPLIT_RIGHT: + case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_LEFT: + case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_RIGHT: + case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_LEFT: + case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_RIGHT: + m_bSplitscreen = true; + return L"HUDSplit"; + break; + case C4JRender::VIEWPORT_TYPE_FULLSCREEN: + default: + m_bSplitscreen = false; + return L"HUD"; + break; + } +} + +void UIScene_HUD::updateSafeZone() +{ + // Distance from edge + F64 safeTop = 0.0; + F64 safeBottom = 0.0; + F64 safeLeft = 0.0; + F64 safeRight = 0.0; + + switch( m_parentLayer->getViewport() ) + { + case C4JRender::VIEWPORT_TYPE_SPLIT_TOP: + safeTop = getSafeZoneHalfHeight(); + safeLeft = getSafeZoneHalfWidth(); + safeRight = getSafeZoneHalfWidth(); + break; + case C4JRender::VIEWPORT_TYPE_SPLIT_BOTTOM: + safeBottom = getSafeZoneHalfHeight(); + safeLeft = getSafeZoneHalfWidth(); + safeRight = getSafeZoneHalfWidth(); + break; + case C4JRender::VIEWPORT_TYPE_SPLIT_LEFT: + safeLeft = getSafeZoneHalfWidth(); + safeTop = getSafeZoneHalfHeight(); + safeBottom = getSafeZoneHalfHeight(); + break; + case C4JRender::VIEWPORT_TYPE_SPLIT_RIGHT: + safeRight = getSafeZoneHalfWidth(); + safeTop = getSafeZoneHalfHeight(); + safeBottom = getSafeZoneHalfHeight(); + break; + case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_LEFT: + safeTop = getSafeZoneHalfHeight(); + safeLeft = getSafeZoneHalfWidth(); + break; + case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_RIGHT: + safeTop = getSafeZoneHalfHeight(); + safeRight = getSafeZoneHalfWidth(); + break; + case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_LEFT: + safeBottom = getSafeZoneHalfHeight(); + safeLeft = getSafeZoneHalfWidth(); + break; + case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_RIGHT: + safeBottom = getSafeZoneHalfHeight(); + safeRight = getSafeZoneHalfWidth(); + break; + case C4JRender::VIEWPORT_TYPE_FULLSCREEN: + default: + safeTop = getSafeZoneHalfHeight(); + safeBottom = getSafeZoneHalfHeight(); + safeLeft = getSafeZoneHalfWidth(); + safeRight = getSafeZoneHalfWidth(); + break; + } + setSafeZone(safeTop, safeBottom, safeLeft, safeRight); +} + +void UIScene_HUD::tick() +{ + UIScene::tick(); + if(getMovie() && app.GetGameStarted()) + { + Minecraft *pMinecraft = Minecraft::GetInstance(); + if(pMinecraft->localplayers[m_iPad] == NULL || pMinecraft->localgameModes[m_iPad] == NULL) + { + return; + } + + if(pMinecraft->localplayers[m_iPad]->dimension == 1) + { + if (EnderDragonRenderer::bossInstance == NULL) + { + if(m_ticksWithNoBoss<=20) + { + ++m_ticksWithNoBoss; + } + if( m_ticksWithNoBoss > 20 ) + { + ShowDragonHealth(false); + } + } + else + { + shared_ptr<EnderDragon> boss = EnderDragonRenderer::bossInstance; + // 4J Stu - Don't clear this here as it's wiped for other players + //EnderDragonRenderer::bossInstance = nullptr; + m_ticksWithNoBoss = 0; + + ShowDragonHealth(true); + SetDragonHealth( (float)boss->getSynchedHealth()/boss->getMaxHealth()); + } + } + else + { + ShowDragonHealth(false); + } + } +} + +void UIScene_HUD::customDraw(IggyCustomDrawCallbackRegion *region) +{ + Minecraft *pMinecraft = Minecraft::GetInstance(); + if(pMinecraft->localplayers[m_iPad] == NULL || pMinecraft->localgameModes[m_iPad] == NULL) return; + + int slot = -1; + swscanf((wchar_t*)region->name,L"slot_%d",&slot); + if (slot == -1) + { + app.DebugPrintf("This is not the control we are looking for\n"); + } + else + { + Slot *invSlot = pMinecraft->localplayers[m_iPad]->inventoryMenu->getSlot(InventoryMenu::USE_ROW_SLOT_START + slot); + shared_ptr<ItemInstance> item = invSlot->getItem(); + if(item != NULL) + { + unsigned char ucAlpha=app.GetGameSettings(ProfileManager.GetPrimaryPad(),eGameSetting_InterfaceOpacity); + float fVal; + + if(ucAlpha<80) + { + // check if we have the timer running for the opacity + unsigned int uiOpacityTimer=app.GetOpacityTimer(m_iPad); + if(uiOpacityTimer!=0) + { + if(uiOpacityTimer<10) + { + float fStep=(80.0f-(float)ucAlpha)/10.0f; + fVal=0.01f*(80.0f-((10.0f-(float)uiOpacityTimer)*fStep)); + } + else + { + fVal=0.01f*80.0f; + } + } + else + { + fVal=0.01f*(float)ucAlpha; + } + } + else + { + fVal=0.01f*(float)ucAlpha; + } + customDrawSlotControl(region,m_iPad,item,fVal,item->isFoil(),true); + } + } +} + +void UIScene_HUD::handleReload() +{ + m_lastActiveSlot = 0; + m_lastScale = 1; + m_bToolTipsVisible = true; + m_lastExpProgress = 0.0f; + m_lastExpLevel = 0; + m_lastMaxHealth = 20; + m_lastHealthBlink = false; + m_lastHealthPoison = false; + m_lastMaxFood = 20; + m_lastFoodPoison = false; + m_lastAir = 10; + m_lastArmour = 0; + m_showHealth = true; + m_showFood = true; + m_showAir = true; + m_showArmour = true; + m_showExpBar = true; + m_lastRegenEffect = false; + m_lastSaturation = 0; + m_lastDragonHealth = 0.0f; + m_showDragonHealth = false; + m_ticksWithNoBoss = 0; + m_uiSelectedItemOpacityCountDown = 0; + m_displayName = L""; + + m_labelDisplayName.setVisible(m_lastShowDisplayName); + + SetDragonLabel( app.GetString( IDS_BOSS_ENDERDRAGON_HEALTH ) ); + SetSelectedLabel(L""); + + for(unsigned int i = 0; i < CHAT_LINES_COUNT; ++i) + { + m_labelChatText[i].init(L""); + } + m_labelJukebox.init(L""); + + int iGuiScale; + Minecraft *pMinecraft = Minecraft::GetInstance(); + if(pMinecraft->localplayers[m_iPad] == NULL || pMinecraft->localplayers[m_iPad]->m_iScreenSection == C4JRender::VIEWPORT_TYPE_FULLSCREEN) + { + iGuiScale=app.GetGameSettings(m_iPad,eGameSetting_UISize); + } + else + { + iGuiScale=app.GetGameSettings(m_iPad,eGameSetting_UISizeSplitscreen); + } + SetHudSize(iGuiScale); + + SetDisplayName(ProfileManager.GetDisplayName(m_iPad)); + + repositionHud(); + + SetTooltipsEnabled(((ui.GetMenuDisplayed(ProfileManager.GetPrimaryPad())) || (app.GetGameSettings(ProfileManager.GetPrimaryPad(),eGameSetting_Tooltips) != 0))); +} + +void UIScene_HUD::SetHudSize(int scale) +{ + if(scale != m_lastScale) + { + m_lastScale = scale; + + IggyDataValue result; + IggyDataValue value[1]; + value[0].type = IGGY_DATATYPE_number; + value[0].number = scale; + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcLoadHud , 1 , value ); + } +} + +void UIScene_HUD::SetExpBarProgress(float progress) +{ + if(progress != m_lastExpProgress) + { + m_lastExpProgress = progress; + + IggyDataValue result; + IggyDataValue value[1]; + value[0].type = IGGY_DATATYPE_number; + value[0].number = progress; + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcSetExpBarProgress , 1 , value ); + } +} + +void UIScene_HUD::SetExpLevel(int level) +{ + if(level != m_lastExpLevel) + { + m_lastExpLevel = level; + + IggyDataValue result; + IggyDataValue value[1]; + value[0].type = IGGY_DATATYPE_number; + value[0].number = level; + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcSetPlayerLevel , 1 , value ); + } +} + +void UIScene_HUD::SetActiveSlot(int slot) +{ + if(slot != m_lastActiveSlot) + { + m_lastActiveSlot = slot; + + IggyDataValue result; + IggyDataValue value[1]; + value[0].type = IGGY_DATATYPE_number; + value[0].number = slot; + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcSetActiveSlot , 1 , value ); + } +} + +void UIScene_HUD::SetHealth(int iHealth, int iLastHealth, bool bBlink, bool bPoison) +{ + int maxHealth = max(iHealth, iLastHealth); + if(maxHealth != m_lastMaxHealth || bBlink != m_lastHealthBlink || bPoison != m_lastHealthPoison) + { + m_lastMaxHealth = maxHealth; + m_lastHealthBlink = bBlink; + m_lastHealthPoison = bPoison; + + IggyDataValue result; + IggyDataValue value[3]; + value[0].type = IGGY_DATATYPE_number; + value[0].number = maxHealth; + value[1].type = IGGY_DATATYPE_boolean; + value[1].boolval = bBlink; + value[2].type = IGGY_DATATYPE_boolean; + value[2].boolval = bPoison; + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcSetHealth , 3 , value ); + } +} + +void UIScene_HUD::SetFood(int iFood, int iLastFood, bool bPoison) +{ + // Ignore iLastFood as food doesn't flash + int maxFood = iFood; //, iLastFood); + if(maxFood != m_lastMaxFood || bPoison != m_lastFoodPoison) + { + m_lastMaxFood = maxFood; + m_lastFoodPoison = bPoison; + + IggyDataValue result; + IggyDataValue value[2]; + value[0].type = IGGY_DATATYPE_number; + value[0].number = maxFood; + value[1].type = IGGY_DATATYPE_boolean; + value[1].boolval = bPoison; + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcSetFood , 2 , value ); + } +} + +void UIScene_HUD::SetAir(int iAir) +{ + if(iAir != m_lastAir) + { + app.DebugPrintf("SetAir to %d\n", iAir); + m_lastAir = iAir; + + IggyDataValue result; + IggyDataValue value[1]; + value[0].type = IGGY_DATATYPE_number; + value[0].number = iAir; + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcSetAir , 1 , value ); + } +} + +void UIScene_HUD::SetArmour(int iArmour) +{ + if(iArmour != m_lastArmour) + { + app.DebugPrintf("SetArmour to %d\n", iArmour); + m_lastArmour = iArmour; + + IggyDataValue result; + IggyDataValue value[1]; + value[0].type = IGGY_DATATYPE_number; + value[0].number = iArmour; + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcSetArmour , 1 , value ); + } +} + +void UIScene_HUD::ShowHealth(bool show) +{ + if(show != m_showHealth) + { + app.DebugPrintf("ShowHealth to %s\n", show?"TRUE":"FALSE"); + m_showHealth = show; + + IggyDataValue result; + IggyDataValue value[1]; + value[0].type = IGGY_DATATYPE_boolean; + value[0].boolval = show; + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcShowHealth , 1 , value ); + } +} + +void UIScene_HUD::ShowFood(bool show) +{ + if(show != m_showFood) + { + app.DebugPrintf("ShowFood to %s\n", show?"TRUE":"FALSE"); + m_showFood = show; + + IggyDataValue result; + IggyDataValue value[1]; + value[0].type = IGGY_DATATYPE_boolean; + value[0].boolval = show; + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcShowFood , 1 , value ); + } +} + +void UIScene_HUD::ShowAir(bool show) +{ + if(show != m_showAir) + { + app.DebugPrintf("ShowAir to %s\n", show?"TRUE":"FALSE"); + m_showAir = show; + + IggyDataValue result; + IggyDataValue value[1]; + value[0].type = IGGY_DATATYPE_boolean; + value[0].boolval = show; + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcShowAir , 1 , value ); + } +} + +void UIScene_HUD::ShowArmour(bool show) +{ + if(show != m_showArmour) + { + app.DebugPrintf("ShowArmour to %s\n", show?"TRUE":"FALSE"); + m_showArmour = show; + + IggyDataValue result; + IggyDataValue value[1]; + value[0].type = IGGY_DATATYPE_boolean; + value[0].boolval = show; + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcShowArmour , 1 , value ); + } +} + +void UIScene_HUD::ShowExpBar(bool show) +{ + if(show != m_showExpBar) + { + app.DebugPrintf("ShowExpBar to %s\n", show?"TRUE":"FALSE"); + m_showExpBar = show; + + IggyDataValue result; + IggyDataValue value[1]; + value[0].type = IGGY_DATATYPE_boolean; + value[0].boolval = show; + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcShowExpbar , 1 , value ); + } +} + +void UIScene_HUD::SetRegenerationEffect(bool bEnabled) +{ + if(bEnabled != m_lastRegenEffect) + { + app.DebugPrintf("SetRegenerationEffect to %s\n", bEnabled?"TRUE":"FALSE"); + m_lastRegenEffect = bEnabled; + + IggyDataValue result; + IggyDataValue value[1]; + value[0].type = IGGY_DATATYPE_boolean; + value[0].boolval = bEnabled; + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcSetRegenerationEffect , 1 , value ); + } +} + +void UIScene_HUD::SetFoodSaturationLevel(int iSaturation) +{ + if(iSaturation != m_lastSaturation) + { + app.DebugPrintf("Set saturation to %d\n", iSaturation); + m_lastSaturation = iSaturation; + + IggyDataValue result; + IggyDataValue value[1]; + value[0].type = IGGY_DATATYPE_number; + value[0].number = iSaturation; + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcSetFoodSaturationLevel , 1 , value ); + } +} + +void UIScene_HUD::SetDragonHealth(float health) +{ + if(health != m_lastDragonHealth) + { + app.DebugPrintf("Set dragon health to %f\n", health); + m_lastDragonHealth = health; + + IggyDataValue result; + IggyDataValue value[1]; + value[0].type = IGGY_DATATYPE_number; + value[0].number = health; + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcSetDragonHealth , 1 , value ); + } +} + +void UIScene_HUD::SetDragonLabel(const wstring &label) +{ + IggyDataValue result; + IggyDataValue value[1]; + IggyStringUTF16 stringVal; + stringVal.string = (IggyUTF16*)label.c_str(); + stringVal.length = label.length(); + value[0].type = IGGY_DATATYPE_string_UTF16; + value[0].string16 = stringVal; + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcSetDragonLabel , 1 , value ); +} + +void UIScene_HUD::ShowDragonHealth(bool show) +{ + if(show != m_showDragonHealth) + { + app.DebugPrintf("ShowDragonHealth to %s\n", show?"TRUE":"FALSE"); + m_showDragonHealth = show; + + IggyDataValue result; + IggyDataValue value[1]; + value[0].type = IGGY_DATATYPE_boolean; + value[0].boolval = show; + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcShowDragonHealth , 1 , value ); + } +} + +void UIScene_HUD::SetSelectedLabel(const wstring &label) +{ + // 4J Stu - Timing here is kept the same as on Xbox360, even though we do it differently now and do the fade out in Flash rather than directly setting opacity + if(!label.empty()) m_uiSelectedItemOpacityCountDown = SharedConstants::TICKS_PER_SECOND * 3; + + IggyDataValue result; + IggyDataValue value[1]; + IggyStringUTF16 stringVal; + stringVal.string = (IggyUTF16*)label.c_str(); + stringVal.length = label.length(); + value[0].type = IGGY_DATATYPE_string_UTF16; + value[0].string16 = stringVal; + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcSetSelectedLabel , 1 , value ); +} + +void UIScene_HUD::HideSelectedLabel() +{ + IggyDataValue result; + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcHideSelectedLabel , 0 , NULL ); +} + +void UIScene_HUD::render(S32 width, S32 height, C4JRender::eViewportType viewport) +{ + if(m_bSplitscreen) + { + S32 xPos = 0; + S32 yPos = 0; + switch( viewport ) + { + case C4JRender::VIEWPORT_TYPE_SPLIT_BOTTOM: + case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_LEFT: + yPos = (S32)(ui.getScreenHeight() / 2); + break; + case C4JRender::VIEWPORT_TYPE_SPLIT_RIGHT: + case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_RIGHT: + xPos = (S32)(ui.getScreenWidth() / 2); + break; + case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_RIGHT: + xPos = (S32)(ui.getScreenWidth() / 2); + yPos = (S32)(ui.getScreenHeight() / 2); + break; + } + ui.setupRenderPosition(xPos, yPos); + + S32 tileXStart = 0; + S32 tileYStart = 0; + S32 tileWidth = width; + S32 tileHeight = height; + + switch( viewport ) + { + case C4JRender::VIEWPORT_TYPE_SPLIT_LEFT: + case C4JRender::VIEWPORT_TYPE_SPLIT_RIGHT: + tileHeight = (S32)(ui.getScreenHeight()); + break; + case C4JRender::VIEWPORT_TYPE_SPLIT_TOP: + tileWidth = (S32)(ui.getScreenWidth()); + tileYStart = (S32)(m_movieHeight / 2); + break; + case C4JRender::VIEWPORT_TYPE_SPLIT_BOTTOM: + tileWidth = (S32)(ui.getScreenWidth()); + tileYStart = (S32)(m_movieHeight / 2); + break; + case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_LEFT: + case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_RIGHT: + case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_LEFT: + case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_RIGHT: + tileYStart = (S32)(m_movieHeight / 2); + break; + } + + IggyPlayerSetDisplaySize( getMovie(), m_movieWidth, m_movieHeight ); + + m_renderWidth = tileWidth; + m_renderHeight = tileHeight; + + IggyPlayerDrawTilesStart ( getMovie() ); + IggyPlayerDrawTile ( getMovie() , + tileXStart , + tileYStart , + tileXStart + tileWidth , + tileYStart + tileHeight , + 0 ); + IggyPlayerDrawTilesEnd ( getMovie() ); + } + else + { + UIScene::render(width, height, viewport); + } +} + +void UIScene_HUD::handleTimerComplete(int id) +{ + Minecraft *pMinecraft = Minecraft::GetInstance(); + + bool anyVisible = false; + if(pMinecraft->localplayers[m_iPad]!= NULL) + { + Gui *pGui = pMinecraft->gui; + //DWORD messagesToDisplay = min( CHAT_LINES_COUNT, pGui->getMessagesCount(m_iPad) ); + for( unsigned int i = 0; i < CHAT_LINES_COUNT; ++i ) + { + float opacity = pGui->getOpacity(m_iPad, i); + if( opacity > 0 ) + { + m_controlLabelBackground[i].setOpacity(opacity); + m_labelChatText[i].setOpacity(opacity); + m_labelChatText[i].setLabel( pGui->getMessagesCount(m_iPad) ? pGui->getMessage(m_iPad,i) : L"" ); + + anyVisible = true; + } + else + { + m_controlLabelBackground[i].setOpacity(0); + m_labelChatText[i].setOpacity(0); + m_labelChatText[i].setLabel(L""); + } + } + if(pGui->getJukeboxOpacity(m_iPad) > 0) anyVisible = true; + m_labelJukebox.setOpacity( pGui->getJukeboxOpacity(m_iPad) ); + m_labelJukebox.setLabel( pGui->getJukeboxMessage(m_iPad) ); + } + else + { + for( unsigned int i = 0; i < CHAT_LINES_COUNT; ++i ) + { + m_controlLabelBackground[i].setOpacity(0); + m_labelChatText[i].setOpacity(0); + m_labelChatText[i].setLabel(L""); + } + m_labelJukebox.setOpacity( 0 ); + } + + //setVisible(anyVisible); +} + +void UIScene_HUD::repositionHud() +{ + if(!m_bSplitscreen) return; + + S32 width = 0; + S32 height = 0; + m_parentLayer->getRenderDimensions( width, height ); + + switch( m_parentLayer->getViewport() ) + { + case C4JRender::VIEWPORT_TYPE_SPLIT_LEFT: + case C4JRender::VIEWPORT_TYPE_SPLIT_RIGHT: + height = (S32)(ui.getScreenHeight()); + break; + case C4JRender::VIEWPORT_TYPE_SPLIT_TOP: + case C4JRender::VIEWPORT_TYPE_SPLIT_BOTTOM: + width = (S32)(ui.getScreenWidth()); + break; + } + + app.DebugPrintf(app.USER_SR, "Reposition HUD with dims %d, %d\n", width, height ); + + IggyDataValue result; + IggyDataValue value[2]; + value[0].type = IGGY_DATATYPE_number; + value[0].number = width; + value[1].type = IGGY_DATATYPE_number; + value[1].number = height; + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcRepositionHud , 2 , value ); +} + +void UIScene_HUD::ShowDisplayName(bool show) +{ + m_lastShowDisplayName = show; + m_labelDisplayName.setVisible(show); +} + +void UIScene_HUD::SetDisplayName(const wstring &displayName) +{ + if(displayName.compare(m_displayName) != 0) + { + m_displayName = displayName; + + IggyDataValue result; + IggyDataValue value[1]; + IggyStringUTF16 stringVal; + stringVal.string = (IggyUTF16*)displayName.c_str(); + stringVal.length = displayName.length(); + value[0].type = IGGY_DATATYPE_string_UTF16; + value[0].string16 = stringVal; + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcSetDisplayName , 1 , value ); + + m_labelDisplayName.setVisible(m_lastShowDisplayName); + } +} + +void UIScene_HUD::SetTooltipsEnabled(bool bEnabled) +{ + if(m_bToolTipsVisible != bEnabled) + { + m_bToolTipsVisible = bEnabled; + + IggyDataValue result; + IggyDataValue value[1]; + value[0].type = IGGY_DATATYPE_boolean; + value[0].boolval = bEnabled; + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcSetTooltipsEnabled , 1 , value ); + } +} + +void UIScene_HUD::handleGameTick() +{ + if(getMovie() && app.GetGameStarted()) + { + Minecraft *pMinecraft = Minecraft::GetInstance(); + if(pMinecraft->localplayers[m_iPad] == NULL || pMinecraft->localgameModes[m_iPad] == NULL) + { + m_parentLayer->showComponent(m_iPad, eUIScene_HUD,false); + return; + } + m_parentLayer->showComponent(m_iPad, eUIScene_HUD,true); + + int iGuiScale; + + if(pMinecraft->localplayers[m_iPad]->m_iScreenSection == C4JRender::VIEWPORT_TYPE_FULLSCREEN) + { + iGuiScale=app.GetGameSettings(m_iPad,eGameSetting_UISize); + } + else + { + iGuiScale=app.GetGameSettings(m_iPad,eGameSetting_UISizeSplitscreen); + } + SetHudSize(iGuiScale); + + SetDisplayName(ProfileManager.GetDisplayName(m_iPad)); + + SetTooltipsEnabled(((ui.GetMenuDisplayed(ProfileManager.GetPrimaryPad())) || (app.GetGameSettings(ProfileManager.GetPrimaryPad(),eGameSetting_Tooltips) != 0))); + +#if TO_BE_IMPLEMENTED + // Move the whole hud group if we are not in fullscreen + if(pMinecraft->localplayers[m_iPad]->m_iScreenSection != C4JRender::VIEWPORT_TYPE_FULLSCREEN) + { + int iTooltipsYOffset = 0; + // if tooltips are off, set the y offset to zero + if(app.GetGameSettings(m_iPad,eGameSetting_Tooltips)==0) + { + switch(iGuiScale) + { + case 0: + iTooltipsYOffset=28;//screenHeight/10; + break; + case 2: + iTooltipsYOffset=28;//screenHeight/10; + break; + case 1: + default: + iTooltipsYOffset=28;//screenHeight/10; + break; + } + } + + float fHeight, fWidth; + GetBounds(&fWidth, &fHeight); + + int iSafezoneYHalf = 0; + switch(pMinecraft->localplayers[m_iPad]->m_iScreenSection) + { + case C4JRender::VIEWPORT_TYPE_SPLIT_TOP: + break; + case C4JRender::VIEWPORT_TYPE_SPLIT_BOTTOM: + iSafezoneYHalf = -fHeight/10;// 5% (need to treat the whole screen is 2x this screen) + break; + case C4JRender::VIEWPORT_TYPE_SPLIT_LEFT: + iSafezoneYHalf = (fHeight/2)-(fHeight/10);// 5% (need to treat the whole screen is 2x this screen) + break; + case C4JRender::VIEWPORT_TYPE_SPLIT_RIGHT: + iSafezoneYHalf = (fHeight/2)-(fHeight/10);// 5% (need to treat the whole screen is 2x this screen) + break; + case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_LEFT: + break; + case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_RIGHT: + break; + case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_LEFT: + iSafezoneYHalf = -fHeight/10; // 5% (the whole screen is 2x this screen) + break; + case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_RIGHT: + iSafezoneYHalf = -fHeight/10; // 5% (the whole screen is 2x this screen) + break; + }; + + D3DXVECTOR3 pos; + m_hudGroup.GetPosition(&pos); + pos.y = iTooltipsYOffset + iSafezoneYHalf; + m_hudGroup.SetPosition(&pos); + } +#endif + SetActiveSlot(pMinecraft->localplayers[m_iPad]->inventory->selected); + + // Update xp progress + if (pMinecraft->localgameModes[m_iPad]->canHurtPlayer()) + { + ShowExpBar(true); + int xpNeededForNextLevel = pMinecraft->localplayers[m_iPad]->getXpNeededForNextLevel(); + int progress = (int)(pMinecraft->localplayers[m_iPad]->experienceProgress *xpNeededForNextLevel); + SetExpBarProgress((float)progress/xpNeededForNextLevel); + } + else + { + ShowExpBar(false); + } + + // Update xp level + if (pMinecraft->localgameModes[m_iPad]->hasExperience() && pMinecraft->localplayers[m_iPad]->experienceLevel > 0) + { + SetExpLevel(pMinecraft->localplayers[m_iPad]->experienceLevel); + } + else + { + SetExpLevel(0); + } + + if (pMinecraft->localgameModes[m_iPad]->canHurtPlayer()) + { + ShowHealth(true); + ShowFood(true); + + SetRegenerationEffect(pMinecraft->localplayers[m_iPad]->hasEffect(MobEffect::regeneration)); + + // Update health + bool blink = pMinecraft->localplayers[m_iPad]->invulnerableTime / 3 % 2 == 1; + if (pMinecraft->localplayers[m_iPad]->invulnerableTime < 10) blink = false; + int iHealth = pMinecraft->localplayers[m_iPad]->getHealth(); + int iLastHealth = pMinecraft->localplayers[m_iPad]->lastHealth; + bool bHasPoison = pMinecraft->localplayers[m_iPad]->hasEffect(MobEffect::poison); + SetHealth(iHealth, iLastHealth, blink, bHasPoison); + + // Update food + //bool foodBlink = false; + FoodData *foodData = pMinecraft->localplayers[m_iPad]->getFoodData(); + int food = foodData->getFoodLevel(); + int oldFood = foodData->getLastFoodLevel(); + bool hasHungerEffect = pMinecraft->localplayers[m_iPad]->hasEffect(MobEffect::hunger); + int saturationLevel = pMinecraft->localplayers[m_iPad]->getFoodData()->getSaturationLevel(); + SetFood(food, oldFood, hasHungerEffect); + SetFoodSaturationLevel(saturationLevel); + + // Update armour + int armor = pMinecraft->localplayers[m_iPad]->getArmorValue(); + if(armor > 0) + { + ShowArmour(true); + SetArmour(armor); + } + else + { + ShowArmour(false); + } + + // Update air + if (pMinecraft->localplayers[m_iPad]->isUnderLiquid(Material::water)) + { + ShowAir(true); + int count = (int) ceil((pMinecraft->localplayers[m_iPad]->getAirSupply() - 2) * 10.0f / Player::TOTAL_AIR_SUPPLY); + SetAir(count); + } + else + { + ShowAir(false); + } + } + else + { + ShowHealth(false); + ShowFood(false); + ShowAir(false); + ShowArmour(false); + } + + if(m_uiSelectedItemOpacityCountDown>0) + { + --m_uiSelectedItemOpacityCountDown; + + // 4J Stu - Timing here is kept the same as on Xbox360, even though we do it differently now and do the fade out in Flash rather than directly setting opacity + if(m_uiSelectedItemOpacityCountDown < (SharedConstants::TICKS_PER_SECOND * 1) ) + { + HideSelectedLabel(); + m_uiSelectedItemOpacityCountDown = 0; + } + } + + unsigned char ucAlpha=app.GetGameSettings(ProfileManager.GetPrimaryPad(),eGameSetting_InterfaceOpacity); + float fVal; + + if(ucAlpha<80) + { + // if we are in a menu, set the minimum opacity for tooltips to 15% + if(ui.GetMenuDisplayed(m_iPad) && (ucAlpha<15)) + { + ucAlpha=15; + } + + // check if we have the timer running for the opacity + unsigned int uiOpacityTimer=app.GetOpacityTimer(m_iPad); + if(uiOpacityTimer!=0) + { + if(uiOpacityTimer<10) + { + float fStep=(80.0f-(float)ucAlpha)/10.0f; + fVal=0.01f*(80.0f-((10.0f-(float)uiOpacityTimer)*fStep)); + } + else + { + fVal=0.01f*80.0f; + } + } + else + { + fVal=0.01f*(float)ucAlpha; + } + } + else + { + // if we are in a menu, set the minimum opacity for tooltips to 15% + if(ui.GetMenuDisplayed(m_iPad) && (ucAlpha<15)) + { + ucAlpha=15; + } + fVal=0.01f*(float)ucAlpha; + } + setOpacity(fVal); + + bool bDisplayGui=app.GetGameStarted() && !ui.GetMenuDisplayed(m_iPad) && !(app.GetXuiAction(m_iPad)==eAppAction_AutosaveSaveGameCapturedThumbnail) && app.GetGameSettings(m_iPad,eGameSetting_DisplayHUD)!=0; + if(bDisplayGui && pMinecraft->localplayers[m_iPad] != NULL) + { + setVisible(true); + } + else + { + setVisible(false); + } + } +} diff --git a/Minecraft.Client/Common/UI/UIScene_HUD.h b/Minecraft.Client/Common/UI/UIScene_HUD.h new file mode 100644 index 00000000..cd0d8806 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_HUD.h @@ -0,0 +1,183 @@ +#pragma once + +#include "UIScene.h" + +#define CHAT_LINES_COUNT 10 + +class UIScene_HUD : public UIScene +{ +private: + bool m_bSplitscreen; + + int m_lastActiveSlot; + int m_lastScale; + bool m_bToolTipsVisible; + float m_lastExpProgress; + int m_lastExpLevel; + int m_lastMaxHealth; + bool m_lastHealthBlink, m_lastHealthPoison; + int m_lastMaxFood; + bool m_lastFoodPoison; + int m_lastAir; + int m_lastArmour; + float m_lastDragonHealth; + bool m_showDragonHealth; + int m_ticksWithNoBoss; + bool m_lastShowDisplayName; + + bool m_showHealth, m_showFood, m_showAir, m_showArmour, m_showExpBar; + bool m_lastRegenEffect; + int m_lastSaturation; + + unsigned int m_uiSelectedItemOpacityCountDown; + + wstring m_displayName; + +protected: + UIControl_Label m_labelChatText[CHAT_LINES_COUNT]; + UIControl_Label m_labelJukebox; + UIControl m_controlLabelBackground[CHAT_LINES_COUNT]; + UIControl_Label m_labelDisplayName; + + IggyName m_funcLoadHud, m_funcSetExpBarProgress, m_funcSetPlayerLevel, m_funcSetActiveSlot; + IggyName m_funcSetHealth, m_funcSetFood, m_funcSetAir, m_funcSetArmour; + IggyName m_funcShowHealth, m_funcShowFood, m_funcShowAir, m_funcShowArmour, m_funcShowExpbar; + IggyName m_funcSetRegenerationEffect, m_funcSetFoodSaturationLevel; + IggyName m_funcSetDragonHealth, m_funcSetDragonLabel, m_funcShowDragonHealth; + IggyName m_funcSetSelectedLabel, m_funcHideSelectedLabel; + IggyName m_funcRepositionHud, m_funcSetDisplayName, m_funcSetTooltipsEnabled; + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) + UI_MAP_ELEMENT(m_labelChatText[0],"Label1") + UI_MAP_ELEMENT(m_labelChatText[1],"Label2") + UI_MAP_ELEMENT(m_labelChatText[2],"Label3") + UI_MAP_ELEMENT(m_labelChatText[3],"Label4") + UI_MAP_ELEMENT(m_labelChatText[4],"Label5") + UI_MAP_ELEMENT(m_labelChatText[5],"Label6") + UI_MAP_ELEMENT(m_labelChatText[6],"Label7") + UI_MAP_ELEMENT(m_labelChatText[7],"Label8") + UI_MAP_ELEMENT(m_labelChatText[8],"Label9") + UI_MAP_ELEMENT(m_labelChatText[9],"Label10") + + UI_MAP_ELEMENT(m_controlLabelBackground[0],"Label1Background") + UI_MAP_ELEMENT(m_controlLabelBackground[1],"Label2Background") + UI_MAP_ELEMENT(m_controlLabelBackground[2],"Label3Background") + UI_MAP_ELEMENT(m_controlLabelBackground[3],"Label4Background") + UI_MAP_ELEMENT(m_controlLabelBackground[4],"Label5Background") + UI_MAP_ELEMENT(m_controlLabelBackground[5],"Label6Background") + UI_MAP_ELEMENT(m_controlLabelBackground[6],"Label7Background") + UI_MAP_ELEMENT(m_controlLabelBackground[7],"Label8Background") + UI_MAP_ELEMENT(m_controlLabelBackground[8],"Label9Background") + UI_MAP_ELEMENT(m_controlLabelBackground[9],"Label10Background") + + UI_MAP_ELEMENT(m_labelJukebox,"Jukebox") + + UI_MAP_ELEMENT(m_labelDisplayName,"LabelGamertag") + + UI_MAP_NAME(m_funcLoadHud, L"LoadHud") + UI_MAP_NAME(m_funcSetExpBarProgress, L"SetExpBarProgress") + UI_MAP_NAME(m_funcSetPlayerLevel, L"SetPlayerLevel") + UI_MAP_NAME(m_funcSetActiveSlot, L"SetActiveSlot") + + UI_MAP_NAME(m_funcSetHealth, L"SetHealth") + UI_MAP_NAME(m_funcSetFood, L"SetFood") + UI_MAP_NAME(m_funcSetAir, L"SetAir") + UI_MAP_NAME(m_funcSetArmour, L"SetArmour") + + UI_MAP_NAME(m_funcShowHealth, L"ShowHealth") + UI_MAP_NAME(m_funcShowFood, L"ShowFood") + UI_MAP_NAME(m_funcShowAir, L"ShowAir") + UI_MAP_NAME(m_funcShowArmour, L"ShowArmour") + UI_MAP_NAME(m_funcShowExpbar, L"ShowExpBar") + + UI_MAP_NAME(m_funcSetRegenerationEffect, L"SetRegenerationEffect") + UI_MAP_NAME(m_funcSetFoodSaturationLevel, L"SetFoodSaturationLevel") + + UI_MAP_NAME(m_funcSetDragonHealth, L"SetDragonHealth") + UI_MAP_NAME(m_funcSetDragonLabel, L"SetDragonLabel") + UI_MAP_NAME(m_funcShowDragonHealth, L"ShowDragonHealthBar") + + UI_MAP_NAME(m_funcSetSelectedLabel, L"SetSelectedLabel") + UI_MAP_NAME(m_funcHideSelectedLabel, L"HideSelectedLabel") + + UI_MAP_NAME(m_funcRepositionHud, L"RepositionHud") + UI_MAP_NAME(m_funcSetDisplayName, L"SetGamertag") + + UI_MAP_NAME(m_funcSetTooltipsEnabled, L"SetTooltipsEnabled") + UI_END_MAP_ELEMENTS_AND_NAMES() + +public: + UIScene_HUD(int iPad, void *initData, UILayer *parentLayer); + + virtual void tick(); + + virtual void updateSafeZone(); + +protected: + // TODO: This should be pure virtual in this class + virtual wstring getMoviePath(); + +public: + virtual EUIScene getSceneType() { return eUIScene_HUD;} + + // Returns true if this scene handles input + virtual bool stealsFocus() { return false; } + + // Returns true if this scene has focus for the pad passed in + virtual bool hasFocus(int iPad) { return false; } + + // Returns true if lower scenes in this scenes layer, or in any layer below this scenes layers should be hidden + virtual bool hidesLowerScenes() { return false; } + + virtual void customDraw(IggyCustomDrawCallbackRegion *region); + + virtual void handleReload(); + +private: + void SetHudSize(int scale); + void SetExpBarProgress(float progress); + void SetExpLevel(int level); + void SetActiveSlot(int slot); + + void SetHealth(int iHealth, int iLastHealth, bool bBlink, bool bPoison); + void SetFood(int iFood, int iLastFood, bool bPoison); + void SetAir(int iAir); + void SetArmour(int iArmour); + + void ShowHealth(bool show); + void ShowFood(bool show); + void ShowAir(bool show); + void ShowArmour(bool show); + void ShowExpBar(bool show); + + void SetRegenerationEffect(bool bEnabled); + void SetFoodSaturationLevel(int iSaturation); + + void SetDragonHealth(float health); + void SetDragonLabel(const wstring &label); + void ShowDragonHealth(bool show); + + void HideSelectedLabel(); + + void SetDisplayName(const wstring &displayName); + + void SetTooltipsEnabled(bool bEnabled); + +public: + void SetSelectedLabel(const wstring &label); + void ShowDisplayName(bool show); + + void handleGameTick(); + + // RENDERING + virtual void render(S32 width, S32 height, C4JRender::eViewportType viewport); + +protected: + void handleTimerComplete(int id); + +#ifdef _DURANGO + virtual long long getDefaultGtcButtons() { return _360_GTC_PAUSE | _360_GTC_MENU | _360_GTC_VIEW; } +#endif + +private: + void repositionHud(); +}; diff --git a/Minecraft.Client/Common/UI/UIScene_HelpAndOptionsMenu.cpp b/Minecraft.Client/Common/UI/UIScene_HelpAndOptionsMenu.cpp new file mode 100644 index 00000000..3fe03325 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_HelpAndOptionsMenu.cpp @@ -0,0 +1,233 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIScene_HelpAndOptionsMenu.h" +#include "..\..\Minecraft.h" + +UIScene_HelpAndOptionsMenu::UIScene_HelpAndOptionsMenu(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) +{ + // Setup all the Iggy references we need for this scene + initialiseMovie(); + + m_bNotInGame=(Minecraft::GetInstance()->level==NULL); + + m_buttons[BUTTON_HAO_CHANGESKIN].init(app.GetString(IDS_CHANGE_SKIN),BUTTON_HAO_CHANGESKIN); + m_buttons[BUTTON_HAO_HOWTOPLAY].init(app.GetString(IDS_HOW_TO_PLAY),BUTTON_HAO_HOWTOPLAY); + m_buttons[BUTTON_HAO_CONTROLS].init(app.GetString(IDS_CONTROLS),BUTTON_HAO_CONTROLS); + m_buttons[BUTTON_HAO_SETTINGS].init(app.GetString(IDS_SETTINGS),BUTTON_HAO_SETTINGS); + m_buttons[BUTTON_HAO_CREDITS].init(app.GetString(IDS_CREDITS),BUTTON_HAO_CREDITS); + //m_buttons[BUTTON_HAO_REINSTALL].init(app.GetString(IDS_REINSTALL_CONTENT),BUTTON_HAO_REINSTALL); + m_buttons[BUTTON_HAO_DEBUG].init(app.GetString(IDS_DEBUG_SETTINGS),BUTTON_HAO_DEBUG); + + /* 4J-TomK - we should never remove a control before the other buttons controls are initialised! + (because vita touchboxes are rebuilt on remove since the remaining positions might change) */ + // We don't have a reinstall content, so remove the button + removeControl( &m_buttons[BUTTON_HAO_REINSTALL], false ); + + doHorizontalResizeCheck(); + +#ifdef _FINAL_BUILD + removeControl( &m_buttons[BUTTON_HAO_DEBUG], false); +#else + if(!app.DebugSettingsOn()) removeControl( &m_buttons[BUTTON_HAO_DEBUG], false); +#endif + +#ifdef _XBOX_ONE + // 4J-PB - in order to buy the skin packs, we need the signed offer ids for them, which we get in the availability info + // we need to retrieve this info though, so do it here + app.AddDLCRequest(e_Marketplace_Content); // content is skin packs, texture packs and mash-up packs + + // we also need to mount the local DLC so we can tell what's been purchased + app.StartInstallDLCProcess(iPad); +#endif + + + + // 4J-PB - do not need a storage device to see this menu - just need one when you choose to re-install them + bool bNotInGame=(Minecraft::GetInstance()->level==NULL); + + // any content to be re-installed? + if(m_iPad==ProfileManager.GetPrimaryPad() && bNotInGame) + { + // We should show the reinstall menu + app.DebugPrintf("Reinstall Menu required...\n"); + } + else + { + removeControl( &m_buttons[BUTTON_HAO_REINSTALL], false); + } + + if(app.GetLocalPlayerCount()>1) + { + // no credits in splitscreen + removeControl( &m_buttons[BUTTON_HAO_CREDITS], false); + +#if TO_BE_IMPLEMENTED + app.AdjustSplitscreenScene(m_hObj,&m_OriginalPosition,m_iPad,false); +#endif + if(ProfileManager.GetPrimaryPad()!=m_iPad) + { + removeControl( &m_buttons[BUTTON_HAO_REINSTALL], false); + } + } + + if(!ProfileManager.IsFullVersion() )//|| ProfileManager.IsGuest(m_iPad)) + { + removeControl( &m_buttons[BUTTON_HAO_CHANGESKIN], false); + } + + //StorageManager.TMSPP_GetUserQuotaInfo(C4JStorage::eGlobalStorage_TitleUser,iPad); + //StorageManager.WebServiceRequestGetFriends(iPad); +} + +UIScene_HelpAndOptionsMenu::~UIScene_HelpAndOptionsMenu() +{ +} + +wstring UIScene_HelpAndOptionsMenu::getMoviePath() +{ + if(app.GetLocalPlayerCount() > 1) + { + return L"HelpAndOptionsMenuSplit"; + } + else + { + return L"HelpAndOptionsMenu"; + } +} + +void UIScene_HelpAndOptionsMenu::updateTooltips() +{ + ui.SetTooltips( m_iPad, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK); +} + +void UIScene_HelpAndOptionsMenu::updateComponents() +{ + bool bNotInGame=(Minecraft::GetInstance()->level==NULL); + if(bNotInGame) + { + m_parentLayer->showComponent(m_iPad,eUIComponent_Panorama,true); + m_parentLayer->showComponent(m_iPad,eUIComponent_Logo,true); + } + else + { + m_parentLayer->showComponent(m_iPad,eUIComponent_Panorama,false); + + if( app.GetLocalPlayerCount() == 1 ) m_parentLayer->showComponent(m_iPad,eUIComponent_Logo,true); + else m_parentLayer->showComponent(m_iPad,eUIComponent_Logo,false); + + } +} + +void UIScene_HelpAndOptionsMenu::handleReload() +{ +#ifdef _FINAL_BUILD + removeControl( &m_buttons[BUTTON_HAO_DEBUG], false); +#else + if(!app.DebugSettingsOn()) removeControl( &m_buttons[BUTTON_HAO_DEBUG], false); +#endif + + // 4J-PB - do not need a storage device to see this menu - just need one when you choose to re-install them + bool bNotInGame=(Minecraft::GetInstance()->level==NULL); + + // any content to be re-installed? + if(m_iPad==ProfileManager.GetPrimaryPad() && bNotInGame) + { + // We should show the reinstall menu + app.DebugPrintf("Reinstall Menu required...\n"); + } + else + { + removeControl( &m_buttons[BUTTON_HAO_REINSTALL], false); + } + + if(app.GetLocalPlayerCount()>1) + { + // no credits in splitscreen + removeControl( &m_buttons[BUTTON_HAO_CREDITS], false); + +#if TO_BE_IMPLEMENTED + app.AdjustSplitscreenScene(m_hObj,&m_OriginalPosition,m_iPad,false); +#endif + if(ProfileManager.GetPrimaryPad()!=m_iPad) + { + removeControl( &m_buttons[BUTTON_HAO_REINSTALL], false); + } + } + + if(!ProfileManager.IsFullVersion() )//|| ProfileManager.IsGuest(m_iPad)) + { +#if TO_BE_IMPLEMENTED + m_Buttons[BUTTON_HAO_CHANGESKIN].SetEnable(FALSE); + m_Buttons[BUTTON_HAO_CHANGESKIN].EnableInput(FALSE); + // set the focus to the second button + + XuiElementSetUserFocus(m_Buttons[BUTTON_HAO_HOWTOPLAY].m_hObj, m_iPad); +#endif + } + + if(!ProfileManager.IsFullVersion() )//|| ProfileManager.IsGuest(m_iPad)) + { + removeControl( &m_buttons[BUTTON_HAO_CHANGESKIN], false); + } + + doHorizontalResizeCheck(); +} + +void UIScene_HelpAndOptionsMenu::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled) +{ + //app.DebugPrintf("UIScene_DebugOverlay handling input for pad %d, key %d, down- %s, pressed- %s, released- %s\n", iPad, key, down?"TRUE":"FALSE", pressed?"TRUE":"FALSE", released?"TRUE":"FALSE"); + + ui.AnimateKeyPress(m_iPad, key, repeat, pressed, released); + + switch(key) + { + case ACTION_MENU_CANCEL: + if(pressed && !repeat) + { + navigateBack(); + } + break; + case ACTION_MENU_OK: +#ifdef __ORBIS__ + case ACTION_MENU_TOUCHPAD_PRESS: +#endif + //CD - Added for audio + if(pressed) + { + ui.PlayUISFX(eSFX_Press); + } + + case ACTION_MENU_UP: + case ACTION_MENU_DOWN: + sendInputToMovie(key, repeat, pressed, released); + break; + } +} + +void UIScene_HelpAndOptionsMenu::handlePress(F64 controlId, F64 childId) +{ + switch((int)controlId) + { + case BUTTON_HAO_CHANGESKIN: + ui.NavigateToScene(m_iPad, eUIScene_SkinSelectMenu); + break; + case BUTTON_HAO_HOWTOPLAY: + ui.NavigateToScene(m_iPad, eUIScene_HowToPlayMenu); + break; + case BUTTON_HAO_CONTROLS: + ui.NavigateToScene(m_iPad, eUIScene_ControlsMenu); + break; + case BUTTON_HAO_SETTINGS: + ui.NavigateToScene(m_iPad, eUIScene_SettingsMenu); + break; + case BUTTON_HAO_CREDITS: + ui.NavigateToScene(m_iPad, eUIScene_Credits); + break; + case BUTTON_HAO_REINSTALL: + ui.NavigateToScene(m_iPad, eUIScene_ReinstallMenu); + break; + case BUTTON_HAO_DEBUG: + ui.NavigateToScene(m_iPad, eUIScene_DebugOptions); + break; + } +} diff --git a/Minecraft.Client/Common/UI/UIScene_HelpAndOptionsMenu.h b/Minecraft.Client/Common/UI/UIScene_HelpAndOptionsMenu.h new file mode 100644 index 00000000..203011d3 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_HelpAndOptionsMenu.h @@ -0,0 +1,50 @@ +#pragma once + +#include "UIScene.h" + +#define BUTTON_HAO_CHANGESKIN 0 +#define BUTTON_HAO_HOWTOPLAY 1 +#define BUTTON_HAO_CONTROLS 2 +#define BUTTON_HAO_SETTINGS 3 +#define BUTTON_HAO_CREDITS 4 +#define BUTTON_HAO_REINSTALL 5 +#define BUTTON_HAO_DEBUG 6 +#define BUTTONS_HAO_MAX BUTTON_HAO_DEBUG + 1 + +class UIScene_HelpAndOptionsMenu : public UIScene +{ +private: + UIControl_Button m_buttons[BUTTONS_HAO_MAX]; + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) + UI_MAP_ELEMENT( m_buttons[BUTTON_HAO_CHANGESKIN], "Button1") + UI_MAP_ELEMENT( m_buttons[BUTTON_HAO_HOWTOPLAY], "Button2") + UI_MAP_ELEMENT( m_buttons[BUTTON_HAO_CONTROLS], "Button3") + UI_MAP_ELEMENT( m_buttons[BUTTON_HAO_SETTINGS], "Button4") + UI_MAP_ELEMENT( m_buttons[BUTTON_HAO_CREDITS], "Button5") + UI_MAP_ELEMENT( m_buttons[BUTTON_HAO_REINSTALL], "Button6") + UI_MAP_ELEMENT( m_buttons[BUTTON_HAO_DEBUG], "Button7") + UI_END_MAP_ELEMENTS_AND_NAMES() + + bool m_bNotInGame; +public: + UIScene_HelpAndOptionsMenu(int iPad, void *initData, UILayer *parentLayer); + virtual ~UIScene_HelpAndOptionsMenu(); + + virtual EUIScene getSceneType() { return eUIScene_HelpAndOptionsMenu;} + + virtual void updateTooltips(); + virtual void updateComponents(); + +protected: + // TODO: This should be pure virtual in this class + virtual wstring getMoviePath(); + +public: + virtual void handleReload(); + + // INPUT + virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled); + +protected: + void handlePress(F64 controlId, F64 childId); +};
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIScene_HowToPlay.cpp b/Minecraft.Client/Common/UI/UIScene_HowToPlay.cpp new file mode 100644 index 00000000..68c7591f --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_HowToPlay.cpp @@ -0,0 +1,328 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIScene_HowToPlay.h" +#include "..\..\..\Minecraft.World\StringHelpers.h" + +static UIScene_HowToPlay::SHowToPlayPageDef gs_aPageDefs[ eHowToPlay_NumPages ] = +{ + { IDS_HOW_TO_PLAY_WHATSNEW, 0, 0}, // eHowToPlay_WhatsNew + { IDS_HOW_TO_PLAY_BASICS, 0, 0}, // eHowToPlay_Basics + { IDS_HOW_TO_PLAY_MULTIPLAYER, 0, 0}, // eHowToPlay_Multiplayer + { IDS_HOW_TO_PLAY_HUD, 0, 0}, // eHowToPlay_HUD + { IDS_HOW_TO_PLAY_CREATIVE, UIScene_HowToPlay::eHowToPlay_LabelCreativeInventory, 1}, // eHowToPlay_Creative + { IDS_HOW_TO_PLAY_INVENTORY, UIScene_HowToPlay::eHowToPlay_LabelIInventory, 1}, // eHowToPlay_Inventory + { IDS_HOW_TO_PLAY_CHEST, UIScene_HowToPlay::eHowToPlay_LabelSCInventory, 2}, // eHowToPlay_Chest + { IDS_HOW_TO_PLAY_LARGECHEST, UIScene_HowToPlay::eHowToPlay_LabelLCInventory, 2}, // eHowToPlay_LargeChest + { IDS_HOW_TO_PLAY_ENDERCHEST, 0, 0}, // eHowToPlay_EnderChest + { IDS_HOW_TO_PLAY_CRAFTING, UIScene_HowToPlay::eHowToPlay_LabelCItem, 3}, // eHowToPlay_InventoryCrafting + { IDS_HOW_TO_PLAY_CRAFT_TABLE, UIScene_HowToPlay::eHowToPlay_LabelCTItem, 3}, // eHowToPlay_CraftTable + { IDS_HOW_TO_PLAY_FURNACE, UIScene_HowToPlay::eHowToPlay_LabelFFuel, 4}, // eHowToPlay_Furnace + { IDS_HOW_TO_PLAY_DISPENSER, UIScene_HowToPlay::eHowToPlay_LabelDText, 2}, // eHowToPlay_Dispenser + { IDS_HOW_TO_PLAY_BREWING, UIScene_HowToPlay::eHowToPlay_LabelBBrew, 2}, // eHowToPlay_Brewing + { IDS_HOW_TO_PLAY_ENCHANTMENT, UIScene_HowToPlay::eHowToPlay_LabelEEnchant, 2}, // eHowToPlay_Enchantment + { IDS_HOW_TO_PLAY_ANVIL, UIScene_HowToPlay::eHowToPlay_LabelAnvil_Inventory, 3}, // eHowToPlay_Anvil + { IDS_HOW_TO_PLAY_FARMANIMALS, 0, 0}, // eHowToPlay_Breeding + { IDS_HOW_TO_PLAY_BREEDANIMALS, 0, 0}, // eHowToPlay_Breeding + { IDS_HOW_TO_PLAY_TRADING, UIScene_HowToPlay::eHowToPlay_LabelTrading_Inventory, 5}, // eHowToPlay_Trading + { IDS_HOW_TO_PLAY_NETHERPORTAL, 0, 0}, // eHowToPlay_NetherPortal + { IDS_HOW_TO_PLAY_THEEND, 0, 0}, // eHowToPlay_NetherPortal +#ifdef _XBOX + { IDS_HOW_TO_PLAY_SOCIALMEDIA, 0, 0}, // eHowToPlay_SocialMedia + { IDS_HOW_TO_PLAY_BANLIST, 0, 0}, // eHowToPlay_BanList +#endif + { IDS_HOW_TO_PLAY_HOSTOPTIONS, 0, 0}, // eHowToPlay_HostOptions +}; + +int gs_pageToFlashMapping[eHowToPlay_NumPages] = +{ + 0, //eHowToPlay_WhatsNew = 0, + 1, //eHowToPlay_Basics, + 2, //eHowToPlay_Multiplayer, + 3, //eHowToPlay_HUD, + 4, //eHowToPlay_Creative, + 5, //eHowToPlay_Inventory, + 6, //eHowToPlay_Chest, + 7, //eHowToPlay_LargeChest, + 23, //eHowToPlay_Enderchest, + 8, //eHowToPlay_InventoryCrafting, + 9, //eHowToPlay_CraftTable, + 10, //eHowToPlay_Furnace, + 11, //eHowToPlay_Dispenser, + + 12, //eHowToPlay_Brewing, + 13, //eHowToPlay_Enchantment, + 21, //eHowToPlay_Anvil, + 14, //eHowToPlay_FarmingAnimals, + 15, //eHowToPlay_Breeding, + 22, //eHowToPlay_Trading, + + 16, //eHowToPlay_NetherPortal, + 17, //eHowToPlay_TheEnd, +#ifdef _XBOX + 18, //eHowToPlay_SocialMedia, + 19, //eHowToPlay_BanList, +#endif + 20, //eHowToPlay_HostOptions, +}; + +UIScene_HowToPlay::UIScene_HowToPlay(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) +{ + // Setup all the Iggy references we need for this scene + initialiseMovie(); + + wstring inventoryString = app.GetString(IDS_INVENTORY); + m_labels[ eHowToPlay_LabelCTItem].init(app.GetString(IDS_ITEM_HATCHET_WOOD)); + m_labels[ eHowToPlay_LabelCTGroup].init(app.GetString(IDS_GROUPNAME_TOOLS)); + m_labels[ eHowToPlay_LabelCTInventory3x3].init(inventoryString); + m_labels[ eHowToPlay_LabelCItem].init(app.GetString(IDS_TILE_WORKBENCH)); + m_labels[ eHowToPlay_LabelCGroup].init(app.GetString(IDS_GROUPNAME_STRUCTURES)); + m_labels[ eHowToPlay_LabelCInventory2x2].init(inventoryString); + m_labels[ eHowToPlay_LabelFFuel].init(app.GetString(IDS_FUEL)); + m_labels[ eHowToPlay_LabelFInventory].init(inventoryString); + m_labels[ eHowToPlay_LabelFIngredient].init(app.GetString(IDS_INGREDIENT)); + m_labels[ eHowToPlay_LabelFChest].init(app.GetString(IDS_FURNACE)); + m_labels[ eHowToPlay_LabelLCInventory].init(inventoryString); + m_labels[ eHowToPlay_LabelCreativeInventory].init(app.GetString(IDS_GROUPNAME_BUILDING_BLOCKS)); + m_labels[ eHowToPlay_LabelLCChest].init(app.GetString(IDS_CHEST)); + m_labels[ eHowToPlay_LabelSCInventory].init(inventoryString); + m_labels[ eHowToPlay_LabelSCChest].init(app.GetString(IDS_CHEST)); + m_labels[ eHowToPlay_LabelIInventory].init(inventoryString); + m_labels[ eHowToPlay_LabelDInventory].init(inventoryString); + m_labels[ eHowToPlay_LabelDText].init(app.GetString(IDS_DISPENSER)); + m_labels[ eHowToPlay_LabelEEnchant].init(app.GetString(IDS_ENCHANT)); + m_labels[ eHowToPlay_LabelEInventory].init(inventoryString); + m_labels[ eHowToPlay_LabelBBrew].init(app.GetString(IDS_BREWING_STAND)); + m_labels[ eHowToPlay_LabelBInventory].init(inventoryString); + m_labels[ eHowToPlay_LabelAnvil_Inventory].init(inventoryString.c_str()); + + wstring wsTemp = app.GetString(IDS_REPAIR_COST); + wsTemp.replace( wsTemp.find(L"%d"), 2, wstring(L"8") ); + + m_labels[ eHowToPlay_LabelAnvil_Cost].init(wsTemp.c_str()); + m_labels[ eHowToPlay_LabelAnvil_ARepairAndName].init(app.GetString(IDS_REPAIR_AND_NAME)); + m_labels[ eHowToPlay_LabelTrading_Inventory].init(inventoryString.c_str()); + m_labels[ eHowToPlay_LabelTrading_Offer2].init(app.GetString(IDS_ITEM_EMERALD)); + m_labels[ eHowToPlay_LabelTrading_Offer1].init(app.GetString(IDS_ITEM_EMERALD)); + m_labels[ eHowToPlay_LabelTrading_NeededForTrade].init(app.GetString(IDS_REQUIRED_ITEMS_FOR_TRADE)); + + wsTemp = app.GetString(IDS_VILLAGER_OFFERS_ITEM); + wsTemp = replaceAll(wsTemp,L"{*VILLAGER_TYPE*}",app.GetString(IDS_VILLAGER_PRIEST)); + wsTemp.replace(wsTemp.find(L"%s"),2, app.GetString(IDS_TILE_LIGHT_GEM)); + m_labels[ eHowToPlay_LabelTrading_VillagerOffers].init(wsTemp.c_str()); + + // Extract pad and required page from init data. We just put the data into the pointer rather than using it as an address. + size_t uiInitData = ( size_t )( initData ); + + EHowToPlayPage eStartPage = ( EHowToPlayPage )( ( uiInitData >> 16 ) & 0xFFF ); // Ignores MSB which is set to 1! + + TelemetryManager->RecordMenuShown(m_iPad, eUIScene_HowToPlay, (ETelemetry_HowToPlay_SubMenuId)eStartPage); + + StartPage( eStartPage ); +} + +wstring UIScene_HowToPlay::getMoviePath() +{ + if(app.GetLocalPlayerCount() > 1) + { + return L"HowToPlaySplit"; + } + else + { + return L"HowToPlay"; + } +} + +void UIScene_HowToPlay::updateTooltips() +{ + // Tool tips. + int iPage = ( int )( m_eCurrPage ); + + int firstPage = eHowToPlay_WhatsNew; +#ifdef __PS3__ + // If it's the blu ray, or the first Japanese digital game, there's no What's New until the first patch, which will take this line out + if(StorageManager.GetBootTypeDisc() || (app.GetProductSKU()==e_sku_SCEJ)) + { + ++firstPage; + } +#elif defined(__ORBIS__) || defined(_DURANGO) || defined(__PSVITA__) + // No What's New for the first PS4 and Xbox One builds + if(true) + { + ++firstPage; + } +#endif + + int iA = -1; + int iX = -1; + if ( iPage == firstPage ) + { + // No previous page. + iA = IDS_HOW_TO_PLAY_NEXT; + } + else if ( ( iPage + 1 ) == eHowToPlay_NumPages ) + { + // No next page. + iX = IDS_HOW_TO_PLAY_PREV; + } + else + { + iA = IDS_HOW_TO_PLAY_NEXT; + iX = IDS_HOW_TO_PLAY_PREV; + } + ui.SetTooltips( m_iPad, iA, IDS_TOOLTIPS_BACK, iX ); +} + +void UIScene_HowToPlay::handleReload() +{ + StartPage( m_eCurrPage ); +} + +void UIScene_HowToPlay::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled) +{ + ui.AnimateKeyPress(m_iPad, key, repeat, pressed, released); + + switch(key) + { + case ACTION_MENU_CANCEL: + if(pressed) + { + navigateBack(); + handled = true; + } + break; + case ACTION_MENU_A: +#ifdef __ORBIS__ + case ACTION_MENU_TOUCHPAD_PRESS: +#endif + if(pressed) + { + // Next page + int iNextPage = ( int )( m_eCurrPage ) + 1; + if ( iNextPage != eHowToPlay_NumPages ) + { + StartPage( ( EHowToPlayPage )( iNextPage ) ); + ui.PlayUISFX(eSFX_Press); + } + handled = true; + } + break; + case ACTION_MENU_X: + if(pressed) + { + // Previous page + int iPrevPage = ( int )( m_eCurrPage ) - 1; + +#ifdef __PS3__ + // If it's the blu ray, or the first Japanese digital game, there's no What's New until the first patch, which will take this line out + if(StorageManager.GetBootTypeDisc() || (app.GetProductSKU()==e_sku_SCEJ)) + { + if ( iPrevPage >= 0 && !((iPrevPage==eHowToPlay_WhatsNew))) + { + StartPage( ( EHowToPlayPage )( iPrevPage ) ); + ui.PlayUISFX(eSFX_Press); + } + } + else +#elif defined(__ORBIS__) || defined(_DURANGO) || defined(__PSVITA__) + // No What's New for the first PS4 and Xbox One builds + if(true) + { + if ( iPrevPage >= 0 && !((iPrevPage==eHowToPlay_WhatsNew))) + { + StartPage( ( EHowToPlayPage )( iPrevPage ) ); + ui.PlayUISFX(eSFX_Press); + } + } + else +#endif + { + if ( iPrevPage >= 0 ) + { + StartPage( ( EHowToPlayPage )( iPrevPage ) ); + ui.PlayUISFX(eSFX_Press); + } + + } + handled = true; + } + break; + case ACTION_MENU_UP: + case ACTION_MENU_DOWN: + case ACTION_MENU_PAGEUP: + case ACTION_MENU_PAGEDOWN: + sendInputToMovie(key, repeat, pressed, released); + break; + } +} + +void UIScene_HowToPlay::StartPage( EHowToPlayPage ePage ) +{ + m_eCurrPage = ePage; + + // Turn on just what we need for this screen. + SHowToPlayPageDef* pDef = &( gs_aPageDefs[ m_eCurrPage ] ); + + // Replace button identifiers in the text with actual button images. + wstring replacedText = app.FormatHTMLString(m_iPad, app.GetString( pDef->m_iTextStringID )); + // 4J-PB - replace the title with the platform specific title, and the platform name +// replacedText = replaceAll(replacedText,L"{*TITLE_UPDATE_NAME*}",app.GetString(IDS_TITLE_UPDATE_NAME)); +#ifndef _WINDOWS64 + replacedText = replaceAll(replacedText,L"{*KICK_PLAYER_DESCRIPTION*}",app.GetString(IDS_KICK_PLAYER_DESCRIPTION)); +#endif +#ifdef _XBOX_ONE + replacedText = replaceAll(replacedText,L"{*PLATFORM_NAME*}",app.GetString(IDS_PLATFORM_NAME)); +#endif + replacedText = replaceAll(replacedText,L"{*BACK_BUTTON*}",app.GetString(IDS_BACK_BUTTON)); + replacedText = replaceAll(replacedText,L"{*DISABLES_ACHIEVEMENTS*}",app.GetString(IDS_HOST_OPTION_DISABLES_ACHIEVEMENTS)); + + // strip out any tab characters and repeated spaces + stripWhitespaceForHtml( replacedText, true ); + + // Set the text colour + wstring finalText(replacedText.c_str() ); + wchar_t startTags[64]; + swprintf(startTags,64,L"<font color=\"#%08x\">",app.GetHTMLColour(eHTMLColor_White)); + finalText = startTags + finalText; + + vector<wstring> paragraphs; + int lastIndex = 0; + for ( int index = finalText.find(L"\r\n", lastIndex, 2); + index != wstring::npos; + index = finalText.find(L"\r\n", lastIndex, 2) + ) + { + paragraphs.push_back( finalText.substr(lastIndex, index-lastIndex) + L" " ); + lastIndex = index + 2; + } + paragraphs.push_back( finalText.substr( lastIndex, finalText.length() - lastIndex ) ); + + // Set the text in the scene + IggyDataValue result; + + IggyDataValue *value = new IggyDataValue[paragraphs.size()+1]; + IggyStringUTF16 * stringVal = new IggyStringUTF16[paragraphs.size()]; + + value[0].type = IGGY_DATATYPE_number; + value[0].number = gs_pageToFlashMapping[(int)ePage]; + + for(unsigned int i = 0; i < paragraphs.size(); ++i) + { + stringVal[i].string = (IggyUTF16 *)paragraphs[i].c_str(); + stringVal[i].length = paragraphs[i].length(); + value[i+1].type = IGGY_DATATYPE_string_UTF16; + value[i+1].string16 = stringVal[i]; + } + + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcLoadPage , 1 + paragraphs.size(), value ); + + delete [] value; + delete [] stringVal; + + updateTooltips(); + + TelemetryManager->RecordMenuShown(m_iPad, eUIScene_HowToPlay, (ETelemetry_HowToPlay_SubMenuId)ePage); + +#ifdef __PSVITA__ + ui.TouchBoxRebuild(this); +#endif +} diff --git a/Minecraft.Client/Common/UI/UIScene_HowToPlay.h b/Minecraft.Client/Common/UI/UIScene_HowToPlay.h new file mode 100644 index 00000000..cff07256 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_HowToPlay.h @@ -0,0 +1,123 @@ +#pragma once + +#include "UIScene.h" + + +class UIScene_HowToPlay : public UIScene +{ +public: + enum EHowToPlayLabelControls + { + eHowToPlay_LabelNone = -1, + eHowToPlay_LabelIInventory =0, + eHowToPlay_LabelSCInventory , + eHowToPlay_LabelSCChest , + eHowToPlay_LabelLCInventory , + eHowToPlay_LabelLCChest , + eHowToPlay_LabelCItem , + eHowToPlay_LabelCGroup , + eHowToPlay_LabelCInventory2x2 , + eHowToPlay_LabelCTItem , + eHowToPlay_LabelCTGroup , + eHowToPlay_LabelCTInventory3x3 , + eHowToPlay_LabelFFuel , + eHowToPlay_LabelFInventory , + eHowToPlay_LabelFIngredient , + eHowToPlay_LabelFChest , + eHowToPlay_LabelDText , + eHowToPlay_LabelDInventory , + eHowToPlay_LabelCreativeInventory, + eHowToPlay_LabelEEnchant, + eHowToPlay_LabelEInventory, + eHowToPlay_LabelBBrew, + eHowToPlay_LabelBInventory, + eHowToPlay_LabelAnvil_Inventory, + eHowToPlay_LabelAnvil_Cost, + eHowToPlay_LabelAnvil_ARepairAndName, + eHowToPlay_LabelTrading_Inventory, + eHowToPlay_LabelTrading_Offer2, + eHowToPlay_LabelTrading_Offer1, + eHowToPlay_LabelTrading_NeededForTrade, + eHowToPlay_LabelTrading_VillagerOffers, + eHowToPlay_NumLabels + }; + + struct SHowToPlayPageDef + { + int m_iTextStringID; // -1 if not used. + int m_iLabelStartIndex; // index of the labels if there are any for the page + int m_iLabelCount; + }; + +private: + EHowToPlayPage m_eCurrPage; + + IggyName m_funcLoadPage; + UIControl_DynamicLabel m_DynamicLabel; + UIControl_Label m_labels[ eHowToPlay_NumLabels ]; + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) + UI_MAP_ELEMENT( m_DynamicLabel , "DynamicHtmlText" ) + + UI_MAP_ELEMENT( m_labels[ eHowToPlay_LabelCTGroup ] , "Label1_9" ) + UI_MAP_ELEMENT( m_labels[ eHowToPlay_LabelCTItem ] , "Label2_9") + UI_MAP_ELEMENT( m_labels[ eHowToPlay_LabelCTInventory3x3 ] , "Label3_9" ) + + UI_MAP_ELEMENT( m_labels[ eHowToPlay_LabelCGroup ] , "Label1_8" ) + UI_MAP_ELEMENT( m_labels[ eHowToPlay_LabelCItem ] , "Label2_8" ) + UI_MAP_ELEMENT( m_labels[ eHowToPlay_LabelCInventory2x2 ] , "Label3_8" ) + + UI_MAP_ELEMENT( m_labels[ eHowToPlay_LabelFChest ] , "Label1_10" ) + UI_MAP_ELEMENT( m_labels[ eHowToPlay_LabelFIngredient ] , "Label2_10" ) + UI_MAP_ELEMENT( m_labels[ eHowToPlay_LabelFFuel ] , "Label3_10" ) + UI_MAP_ELEMENT( m_labels[ eHowToPlay_LabelFInventory ] , "Label4_10" ) + + UI_MAP_ELEMENT( m_labels[ eHowToPlay_LabelLCChest ] , "Label1_7" ) + UI_MAP_ELEMENT( m_labels[ eHowToPlay_LabelLCInventory ] , "Label2_7" ) + + UI_MAP_ELEMENT( m_labels[ eHowToPlay_LabelCreativeInventory ] , "Label1_4" ) + + UI_MAP_ELEMENT( m_labels[ eHowToPlay_LabelSCChest ] , "Label1_6" ) + UI_MAP_ELEMENT( m_labels[ eHowToPlay_LabelSCInventory ] , "Label2_6" ) + + UI_MAP_ELEMENT( m_labels[ eHowToPlay_LabelIInventory ] , "Label1_5" ) + + UI_MAP_ELEMENT( m_labels[ eHowToPlay_LabelDText ] , "Label1_11" ) + UI_MAP_ELEMENT( m_labels[ eHowToPlay_LabelDInventory ] , "Label2_11" ) + + UI_MAP_ELEMENT( m_labels[ eHowToPlay_LabelEEnchant ] , "Label1_13" ) + UI_MAP_ELEMENT( m_labels[ eHowToPlay_LabelEInventory ] , "Label2_13" ) + + UI_MAP_ELEMENT( m_labels[ eHowToPlay_LabelBBrew ] , "Label1_12" ) + UI_MAP_ELEMENT( m_labels[ eHowToPlay_LabelBInventory ] , "Label2_12" ) + + UI_MAP_ELEMENT( m_labels[ eHowToPlay_LabelTrading_VillagerOffers ] , "Label1_22" ) + UI_MAP_ELEMENT( m_labels[ eHowToPlay_LabelTrading_NeededForTrade ] , "Label2_22" ) + UI_MAP_ELEMENT( m_labels[ eHowToPlay_LabelTrading_Inventory ] , "Label3_22" ) + UI_MAP_ELEMENT( m_labels[ eHowToPlay_LabelTrading_Offer1 ] , "Label4_22" ) + UI_MAP_ELEMENT( m_labels[ eHowToPlay_LabelTrading_Offer2 ] , "Label5_22" ) + + UI_MAP_ELEMENT( m_labels[ eHowToPlay_LabelAnvil_ARepairAndName ] , "Label1_21" ) + UI_MAP_ELEMENT( m_labels[ eHowToPlay_LabelAnvil_Cost ] , "Label2_21" ) + UI_MAP_ELEMENT( m_labels[ eHowToPlay_LabelAnvil_Inventory ] , "Label3_21" ) + + UI_MAP_NAME(m_funcLoadPage, L"LoadHowToPlayPage") + UI_END_MAP_ELEMENTS_AND_NAMES() +public: + UIScene_HowToPlay(int iPad, void *initData, UILayer *parentLayer); + + virtual EUIScene getSceneType() { return eUIScene_HowToPlay;} + virtual void updateTooltips(); + +protected: + // TODO: This should be pure virtual in this class + virtual wstring getMoviePath(); + +public: + virtual void handleReload(); + + // INPUT + virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled); + +private: + void StartPage( EHowToPlayPage ePage ); +}; diff --git a/Minecraft.Client/Common/UI/UIScene_HowToPlayMenu.cpp b/Minecraft.Client/Common/UI/UIScene_HowToPlayMenu.cpp new file mode 100644 index 00000000..5fc6e02b --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_HowToPlayMenu.cpp @@ -0,0 +1,205 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIScene_HowToPlayMenu.h" + +// strings for buttons in the list +unsigned int UIScene_HowToPlayMenu::m_uiHTPButtonNameA[]= +{ + IDS_HOW_TO_PLAY_MENU_WHATSNEW, // eHTPButton_WhatsNew + IDS_HOW_TO_PLAY_MENU_BASICS, // eHTPButton_Basics, + IDS_HOW_TO_PLAY_MENU_MULTIPLAYER, // eHTPButton_Multiplayer + IDS_HOW_TO_PLAY_MENU_HUD, // eHTPButton_Hud, + IDS_HOW_TO_PLAY_MENU_CREATIVE, // eHTPButton_Creative, + IDS_HOW_TO_PLAY_MENU_INVENTORY, // eHTPButton_Inventory, + IDS_HOW_TO_PLAY_MENU_CHESTS, // eHTPButton_Chest, + IDS_HOW_TO_PLAY_MENU_CRAFTING, // eHTPButton_Crafting, + IDS_HOW_TO_PLAY_MENU_FURNACE, // eHTPButton_Furnace, + IDS_HOW_TO_PLAY_MENU_DISPENSER, // eHTPButton_Dispenser, + + IDS_HOW_TO_PLAY_MENU_BREWING, // eHTPButton_Brewing, + IDS_HOW_TO_PLAY_MENU_ENCHANTMENT, // eHTPButton_Enchantment, + IDS_HOW_TO_PLAY_MENU_ANVIL, + IDS_HOW_TO_PLAY_MENU_FARMANIMALS, // eHTPButton_Breeding, + IDS_HOW_TO_PLAY_MENU_BREEDANIMALS, // eHTPButton_Breeding, + IDS_HOW_TO_PLAY_MENU_TRADING, + + IDS_HOW_TO_PLAY_MENU_NETHERPORTAL, // eHTPButton_NetherPortal, + IDS_HOW_TO_PLAY_MENU_THEEND, // eHTPButton_TheEnd, +#ifdef _XBOX + IDS_HOW_TO_PLAY_MENU_SOCIALMEDIA, // eHTPButton_SocialMedia, + IDS_HOW_TO_PLAY_MENU_BANLIST, // eHTPButton_BanningLevels, +#endif + IDS_HOW_TO_PLAY_MENU_HOSTOPTIONS, // eHTPButton_HostOptions, +}; + +// mapping the buttons to a scene value +unsigned int UIScene_HowToPlayMenu::m_uiHTPSceneA[]= +{ + eHowToPlay_WhatsNew, + eHowToPlay_Basics, + eHowToPlay_Multiplayer, + eHowToPlay_HUD, + eHowToPlay_Creative, + eHowToPlay_Inventory, + eHowToPlay_Chest, + eHowToPlay_InventoryCrafting, + eHowToPlay_Furnace, + eHowToPlay_Dispenser, + + eHowToPlay_Brewing, + eHowToPlay_Enchantment, + eHowToPlay_Anvil, + eHowToPlay_FarmingAnimals, + eHowToPlay_Breeding, + eHowToPlay_Trading, + + eHowToPlay_NetherPortal, + eHowToPlay_TheEnd, +#ifdef _XBOX + eHowToPlay_SocialMedia, + eHowToPlay_BanList, +#endif + eHowToPlay_HostOptions, +}; + +UIScene_HowToPlayMenu::UIScene_HowToPlayMenu(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) +{ + // Setup all the Iggy references we need for this scene + initialiseMovie(); + + m_buttonListHowTo.init(eControl_Buttons); + + for(unsigned int i = 0; i < eHTPButton_Max; ++i) + { +#ifdef __PS3__ + // If it's the blu ray, or the first Japanese digital game, there's no What's New until the first patch, which will take this line out + if(StorageManager.GetBootTypeDisc() || (app.GetProductSKU()==e_sku_SCEJ)) + { + if(!(i==eHTPButton_WhatsNew) ) + { + m_buttonListHowTo.addItem( app.GetString(m_uiHTPButtonNameA[i]) , i);//iCount++); + } + } + else +#elif defined(__ORBIS__) || defined(_DURANGO) || defined(__PSVITA__) + // No What's New for the first PS4 and Xbox One builds + if(true) + { + if(!(i==eHTPButton_WhatsNew) ) + { + m_buttonListHowTo.addItem( app.GetString(m_uiHTPButtonNameA[i]) , i);//iCount++); + } + } + else +#endif + { + m_buttonListHowTo.addItem( app.GetString(m_uiHTPButtonNameA[i]) , i);//iCount++); + } + } +} + +wstring UIScene_HowToPlayMenu::getMoviePath() +{ + if(app.GetLocalPlayerCount() > 1) + { + return L"HowToPlayMenuSplit"; + } + else + { + return L"HowToPlayMenu"; + } +} + +void UIScene_HowToPlayMenu::updateTooltips() +{ + ui.SetTooltips( m_iPad, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK); +} + +void UIScene_HowToPlayMenu::updateComponents() +{ + bool bNotInGame=(Minecraft::GetInstance()->level==NULL); + if(bNotInGame) + { + m_parentLayer->showComponent(m_iPad,eUIComponent_Panorama,true); + m_parentLayer->showComponent(m_iPad,eUIComponent_Logo,true); + } + else + { + m_parentLayer->showComponent(m_iPad,eUIComponent_Panorama,false); + + if( app.GetLocalPlayerCount() == 1 ) m_parentLayer->showComponent(m_iPad,eUIComponent_Logo,true); + else m_parentLayer->showComponent(m_iPad,eUIComponent_Logo,false); + } +} + +void UIScene_HowToPlayMenu::handleReload() +{ + for(unsigned int i = 0; i < eHTPButton_Max; ++i) + { +#ifdef __PS3__ + // If it's the blu ray, or the first Japanese digital game, there's no What's New until the first patch, which will take this line out + if(StorageManager.GetBootTypeDisc() || (app.GetProductSKU()==e_sku_SCEJ)) + { + if(!(i==eHTPButton_WhatsNew) ) + { + m_buttonListHowTo.addItem( app.GetString(m_uiHTPButtonNameA[i]) , i); + } + } + else +#elif defined(__ORBIS__) || defined(_DURANGO) || defined(__PSVITA__) + // No What's New for the first PS4 and Xbox One builds + if(true) + { + if(!(i==eHTPButton_WhatsNew) ) + { + m_buttonListHowTo.addItem( app.GetString(m_uiHTPButtonNameA[i]) , i); + } + } + else +#endif + { + m_buttonListHowTo.addItem( app.GetString(m_uiHTPButtonNameA[i]) , i); + } + } +} + +void UIScene_HowToPlayMenu::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled) +{ + //app.DebugPrintf("UIScene_DebugOverlay handling input for pad %d, key %d, down- %s, pressed- %s, released- %s\n", iPad, key, down?"TRUE":"FALSE", pressed?"TRUE":"FALSE", released?"TRUE":"FALSE"); + ui.AnimateKeyPress(m_iPad, key, repeat, pressed, released); + + switch(key) + { + case ACTION_MENU_CANCEL: + if(pressed) + { + navigateBack(); + } + break; + case ACTION_MENU_OK: +#ifdef __ORBIS__ + case ACTION_MENU_TOUCHPAD_PRESS: +#endif + sendInputToMovie(key, repeat, pressed, released); + break; + case ACTION_MENU_UP: + case ACTION_MENU_DOWN: + case ACTION_MENU_PAGEUP: + case ACTION_MENU_PAGEDOWN: + sendInputToMovie(key, repeat, pressed, released); + break; + } +} + +void UIScene_HowToPlayMenu::handlePress(F64 controlId, F64 childId) +{ + if( (int)controlId == eControl_Buttons) + { + //CD - Added for audio + ui.PlayUISFX(eSFX_Press); + + unsigned int uiInitData; + uiInitData = ( ( 1 << 31 ) | ( m_uiHTPSceneA[(int)childId] << 16 ) | ( short )( m_iPad ) ); + ui.NavigateToScene(m_iPad, eUIScene_HowToPlay, ( void* )( uiInitData ) ); + } +} diff --git a/Minecraft.Client/Common/UI/UIScene_HowToPlayMenu.h b/Minecraft.Client/Common/UI/UIScene_HowToPlayMenu.h new file mode 100644 index 00000000..5a60cdd0 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_HowToPlayMenu.h @@ -0,0 +1,68 @@ +#pragma once + +#include "UIScene.h" + +class UIScene_HowToPlayMenu : public UIScene +{ +private: + enum EControls + { + eControl_Buttons, + }; + + enum eHTPButton + { + eHTPButton_WhatsNew = 0, + eHTPButton_Basics, + eHTPButton_Multiplayer, + eHTPButton_Hud, + eHTPButton_Creative, + eHTPButton_Inventory, + eHTPButton_Chest, + eHTPButton_Crafting, + eHTPButton_Furnace, + eHTPButton_Dispenser, + eHTPButton_Brewing, + eHTPButton_Enchantment, + eHTPButton_Anvil, + eHTPButton_FarmingAnimals, + eHTPButton_Breeding, + eHTPButton_Trading, + eHTPButton_NetherPortal, + eHTPButton_TheEnd, +#ifdef _XBOX + eHTPButton_SocialMedia, + eHTPButton_BanningLevels, +#endif + eHTPButton_HostOptions, + eHTPButton_Max, + }; + + static unsigned int m_uiHTPButtonNameA[eHTPButton_Max]; + static unsigned int m_uiHTPSceneA[eHTPButton_Max]; + + UIControl_ButtonList m_buttonListHowTo; + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) + UI_MAP_ELEMENT( m_buttonListHowTo, "HowToList") + UI_END_MAP_ELEMENTS_AND_NAMES() + +public: + UIScene_HowToPlayMenu(int iPad, void *initData, UILayer *parentLayer); + + virtual EUIScene getSceneType() { return eUIScene_HowToPlayMenu;} + + virtual void updateTooltips(); + virtual void updateComponents(); + + virtual void handleReload(); +protected: + // TODO: This should be pure virtual in this class + virtual wstring getMoviePath(); + +public: + // INPUT + virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled); + +protected: + void handlePress(F64 controlId, F64 childId); +};
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIScene_InGameHostOptionsMenu.cpp b/Minecraft.Client/Common/UI/UIScene_InGameHostOptionsMenu.cpp new file mode 100644 index 00000000..de8af0ac --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_InGameHostOptionsMenu.cpp @@ -0,0 +1,104 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIScene_InGameHostOptionsMenu.h" +#include "..\..\Minecraft.h" +#include "..\..\MultiPlayerLocalPlayer.h" +#include "..\..\ClientConnection.h" +#include "..\..\..\Minecraft.World\net.minecraft.network.h" +#include "..\..\..\Minecraft.World\net.minecraft.network.packet.h" + +UIScene_InGameHostOptionsMenu::UIScene_InGameHostOptionsMenu(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) +{ + // Setup all the Iggy references we need for this scene + initialiseMovie(); + + m_checkboxFireSpreads.init(app.GetString(IDS_FIRE_SPREADS), eControl_FireSpreads, app.GetGameHostOption(eGameHostOption_FireSpreads)!=0); + m_checkboxTNT.init(app.GetString(IDS_TNT_EXPLODES), eControl_TNT, app.GetGameHostOption(eGameHostOption_TNT)!=0); + + INetworkPlayer *localPlayer = g_NetworkManager.GetLocalPlayerByUserIndex( m_iPad ); + unsigned int privs = app.GetPlayerPrivileges(localPlayer->GetSmallId()); + if(app.GetGameHostOption(eGameHostOption_CheatsEnabled) + && Player::getPlayerGamePrivilege(privs,Player::ePlayerGamePrivilege_CanTeleport) + && g_NetworkManager.GetPlayerCount() > 1) + { + m_buttonTeleportToPlayer.init(app.GetString(IDS_TELEPORT_TO_PLAYER), eControl_TeleportToPlayer); + m_buttonTeleportToMe.init(app.GetString(IDS_TELEPORT_TO_ME), eControl_TeleportToMe); + } + else + { + removeControl(&m_buttonTeleportToPlayer, true); + removeControl(&m_buttonTeleportToMe, true); + } +} + +wstring UIScene_InGameHostOptionsMenu::getMoviePath() +{ + if(app.GetLocalPlayerCount() > 1) + { + return L"InGameHostOptionsSplit"; + } + else + { + return L"InGameHostOptions"; + } +} + +void UIScene_InGameHostOptionsMenu::updateTooltips() +{ + ui.SetTooltips( m_iPad, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK); +} + +void UIScene_InGameHostOptionsMenu::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled) +{ + //app.DebugPrintf("UIScene_DebugOverlay handling input for pad %d, key %d, down- %s, pressed- %s, released- %s\n", iPad, key, down?"TRUE":"FALSE", pressed?"TRUE":"FALSE", released?"TRUE":"FALSE"); + + ui.AnimateKeyPress(iPad, key, repeat, pressed, released); + switch(key) + { + case ACTION_MENU_CANCEL: + if(pressed) + { + unsigned int hostOptions = app.GetGameHostOption(eGameHostOption_All); + app.SetGameHostOption(hostOptions,eGameHostOption_FireSpreads,m_checkboxFireSpreads.IsChecked()); + app.SetGameHostOption(hostOptions,eGameHostOption_TNT,m_checkboxTNT.IsChecked()); + + // Send update settings packet to server + if(hostOptions != app.GetGameHostOption(eGameHostOption_All) ) + { + Minecraft *pMinecraft = Minecraft::GetInstance(); + shared_ptr<MultiplayerLocalPlayer> player = pMinecraft->localplayers[m_iPad]; + if(player->connection) + { + player->connection->send( shared_ptr<ServerSettingsChangedPacket>( new ServerSettingsChangedPacket( ServerSettingsChangedPacket::HOST_IN_GAME_SETTINGS, hostOptions) ) ); + } + } + + navigateBack(); + + handled = true; + } + break; + case ACTION_MENU_OK: +#ifdef __ORBIS__ + case ACTION_MENU_TOUCHPAD_PRESS: +#endif + sendInputToMovie(key, repeat, pressed, released); + break; + case ACTION_MENU_UP: + case ACTION_MENU_DOWN: + sendInputToMovie(key, repeat, pressed, released); + break; + } +} + +void UIScene_InGameHostOptionsMenu::handlePress(F64 controlId, F64 childId) +{ + TeleportMenuInitData *initData = new TeleportMenuInitData(); + initData->iPad = m_iPad; + initData->teleportToPlayer = false; + if( (int)controlId == eControl_TeleportToPlayer ) + { + initData->teleportToPlayer = true; + } + ui.NavigateToScene(m_iPad,eUIScene_TeleportMenu,(void*)initData); +} diff --git a/Minecraft.Client/Common/UI/UIScene_InGameHostOptionsMenu.h b/Minecraft.Client/Common/UI/UIScene_InGameHostOptionsMenu.h new file mode 100644 index 00000000..24711412 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_InGameHostOptionsMenu.h @@ -0,0 +1,38 @@ +#pragma once + +#include "UIScene.h" + +class UIScene_InGameHostOptionsMenu : public UIScene +{ +private: + enum EControls + { + eControl_FireSpreads, + eControl_TNT, + eControl_TeleportToPlayer, + eControl_TeleportToMe, + }; + + UIControl_CheckBox m_checkboxFireSpreads, m_checkboxTNT; + UIControl_Button m_buttonTeleportToPlayer, m_buttonTeleportToMe; + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) + UI_MAP_ELEMENT( m_checkboxFireSpreads, "CheckboxFireSpreads") + UI_MAP_ELEMENT( m_checkboxTNT, "CheckboxTNT") + UI_MAP_ELEMENT( m_buttonTeleportToPlayer, "TeleportToPlayer") + UI_MAP_ELEMENT( m_buttonTeleportToMe, "TeleportPlayerToMe") + UI_END_MAP_ELEMENTS_AND_NAMES() +public: + UIScene_InGameHostOptionsMenu(int iPad, void *initData, UILayer *parentLayer); + + virtual EUIScene getSceneType() { return eUIScene_InGameHostOptionsMenu;} + virtual void updateTooltips(); + +protected: + // TODO: This should be pure virtual in this class + virtual wstring getMoviePath(); + +public: + // INPUT + virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled); + virtual void handlePress(F64 controlId, F64 childId); +};
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIScene_InGameInfoMenu.cpp b/Minecraft.Client/Common/UI/UIScene_InGameInfoMenu.cpp new file mode 100644 index 00000000..5c3f73f6 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_InGameInfoMenu.cpp @@ -0,0 +1,605 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIScene_InGameInfoMenu.h" +#include "..\..\MultiPlayerLocalPlayer.h" +#include "..\..\..\Minecraft.World\net.minecraft.network.packet.h" +#include "..\..\MultiPlayerLocalPlayer.h" +#include "..\..\ClientConnection.h" + +UIScene_InGameInfoMenu::UIScene_InGameInfoMenu(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) +{ + // Setup all the Iggy references we need for this scene + initialiseMovie(); + + m_buttonGameOptions.init(app.GetString(IDS_HOST_OPTIONS),eControl_GameOptions); + m_labelTitle.init(app.GetString(IDS_PLAYERS_INVITE)); + m_playerList.init(eControl_GamePlayers); + + for(unsigned int i = 0; i < MINECRAFT_NET_MAX_PLAYERS; ++i) + { + m_playerNames[i] = L""; + } + + DWORD playerCount = g_NetworkManager.GetPlayerCount(); + + m_playersCount = 0; + for(DWORD i = 0; i < playerCount; ++i) + { + INetworkPlayer *player = g_NetworkManager.GetPlayerByIndex( i ); + + if( player != NULL ) + { + m_players[i] = player->GetSmallId(); + ++m_playersCount; + + wstring playerName = L""; +#ifndef _CONTENT_PACKAGE + if(app.DebugSettingsOn() && (app.GetGameSettingsDebugMask()&(1L<<eDebugSetting_DebugLeaderboards))) + { + playerName = L"WWWWWWWWWWWWWWWW"; + } + else +#endif + { + playerName = player->GetDisplayName(); + } + + int voiceStatus = 0; + if(player != NULL && player->HasVoice() ) + { + if( player->IsMutedByLocalUser(m_iPad) ) + { + // Muted image + voiceStatus = 3; + } + else if( player->IsTalking() ) + { + // Talking image + voiceStatus = 2; + } + else + { + // Not talking image + voiceStatus = 1; + } + } + + m_playersVoiceState[i] = voiceStatus; + m_playersColourState[i] = app.GetPlayerColour( m_players[i] ); + m_playerNames[i] = playerName; + m_playerList.addItem( playerName, app.GetPlayerColour( m_players[i] ), voiceStatus); + } + } + + g_NetworkManager.RegisterPlayerChangedCallback(m_iPad, &UIScene_InGameInfoMenu::OnPlayerChanged, this); + + INetworkPlayer *thisPlayer = g_NetworkManager.GetLocalPlayerByUserIndex( m_iPad ); + m_isHostPlayer = false; + if(thisPlayer != NULL) m_isHostPlayer = thisPlayer->IsHost() == TRUE; + + Minecraft *pMinecraft = Minecraft::GetInstance(); + shared_ptr<MultiplayerLocalPlayer> localPlayer = pMinecraft->localplayers[m_iPad]; + if(!m_isHostPlayer && !localPlayer->isModerator() ) + { + removeControl( &m_buttonGameOptions, false ); + } + + updateTooltips(); + +#if TO_BE_IMPLEMENTED + SetTimer( TOOLTIP_TIMERID , INGAME_INFO_TOOLTIP_TIMER ); +#endif + + // get rid of the quadrant display if it's on + ui.HidePressStart(); + +#if TO_BE_IMPLEMENTED + SetTimer(IGNORE_KEYPRESS_TIMERID,IGNORE_KEYPRESS_TIME); +#endif +} + +wstring UIScene_InGameInfoMenu::getMoviePath() +{ + if(app.GetLocalPlayerCount() > 1) + { + return L"InGameInfoMenuSplit"; + } + else + { + return L"InGameInfoMenu"; + } +} + +void UIScene_InGameInfoMenu::updateTooltips() +{ + int keyX = IDS_TOOLTIPS_INVITE_FRIENDS; + int ikeyY = -1; + + XPARTY_USER_LIST partyList; + if((XPartyGetUserList( &partyList ) != XPARTY_E_NOT_IN_PARTY ) && (partyList.dwUserCount>1)) + { + keyX = IDS_TOOLTIPS_INVITE_PARTY; + } + + if(g_NetworkManager.IsLocalGame()) keyX = -1; +#ifdef __PSVITA__ + if(CGameNetworkManager::usingAdhocMode()) keyX = -1; +#endif + + + INetworkPlayer *selectedPlayer = g_NetworkManager.GetPlayerBySmallId( m_players[ m_playerList.getCurrentSelection() ] ); + + int keyA = -1; + Minecraft *pMinecraft = Minecraft::GetInstance(); + shared_ptr<MultiplayerLocalPlayer> localPlayer = pMinecraft->localplayers[m_iPad]; + + bool isOp = m_isHostPlayer || localPlayer->isModerator(); + bool cheats = app.GetGameHostOption(eGameHostOption_CheatsEnabled) != 0; + bool trust = app.GetGameHostOption(eGameHostOption_TrustPlayers) != 0; + + if( isOp ) + { + if(m_buttonGameOptions.hasFocus()) + { + keyA = IDS_TOOLTIPS_SELECT; + } + else if( selectedPlayer != NULL) + { + bool editingHost = selectedPlayer->IsHost(); + if( (cheats && (m_isHostPlayer || !editingHost ) ) || (!trust && (m_isHostPlayer || !editingHost)) +#if (!defined(_CONTENT_PACKAGE) && !defined(_FINAL_BUILD) && defined(_DEBUG_MENUS_ENABLED)) + || (m_isHostPlayer && editingHost) +#endif + ) + { + keyA = IDS_TOOLTIPS_PRIVILEGES; + } + else if(selectedPlayer->IsLocal() != TRUE && selectedPlayer->IsSameSystem(g_NetworkManager.GetHostPlayer()) != TRUE) + { + // Only ops will hit this, can kick anyone not local and not local to the host + keyA = IDS_TOOLTIPS_KICK; + } + } + } + +#if defined(__PS3__) || defined(__ORBIS__) + if(m_iPad == ProfileManager.GetPrimaryPad() ) ikeyY = IDS_TOOLTIPS_GAME_INVITES; +#else + if(!m_buttonGameOptions.hasFocus()) + { + // if the player is me, then view gamer profile + if(selectedPlayer != NULL && selectedPlayer->IsLocal() && selectedPlayer->GetUserIndex()==m_iPad) + { + ikeyY = IDS_TOOLTIPS_VIEW_GAMERPROFILE; + } + else + { + ikeyY = IDS_TOOLTIPS_VIEW_GAMERCARD; + } + } +#endif + ui.SetTooltips( m_iPad, keyA,IDS_TOOLTIPS_BACK,keyX,ikeyY); +} + +void UIScene_InGameInfoMenu::handleDestroy() +{ + g_NetworkManager.UnRegisterPlayerChangedCallback(m_iPad, &UIScene_InGameInfoMenu::OnPlayerChanged, this); + + m_parentLayer->removeComponent(eUIComponent_MenuBackground); +} + +void UIScene_InGameInfoMenu::handleGainFocus(bool navBack) +{ + UIScene::handleGainFocus(navBack); + if( navBack ) g_NetworkManager.RegisterPlayerChangedCallback(m_iPad, &UIScene_InGameInfoMenu::OnPlayerChanged, this); +} + +void UIScene_InGameInfoMenu::handleReload() +{ + DWORD playerCount = g_NetworkManager.GetPlayerCount(); + + m_playersCount = 0; + for(DWORD i = 0; i < playerCount; ++i) + { + INetworkPlayer *player = g_NetworkManager.GetPlayerByIndex( i ); + + if( player != NULL ) + { + m_players[i] = player->GetSmallId(); + ++m_playersCount; + + wstring playerName = L""; +#ifndef _CONTENT_PACKAGE + if(app.DebugSettingsOn() && (app.GetGameSettingsDebugMask()&(1L<<eDebugSetting_DebugLeaderboards))) + { + playerName = L"WWWWWWWWWWWWWWWW"; + } + else +#endif + { + playerName = player->GetDisplayName(); + } + + int voiceStatus = 0; + if(player != NULL && player->HasVoice() ) + { + if( player->IsMutedByLocalUser(m_iPad) ) + { + // Muted image + voiceStatus = 3; + } + else if( player->IsTalking() ) + { + // Talking image + voiceStatus = 2; + } + else + { + // Not talking image + voiceStatus = 1; + } + } + + m_playersVoiceState[i] = voiceStatus; + m_playersColourState[i] = app.GetPlayerColour( m_players[i] ); + m_playerNames[i] = playerName; + m_playerList.addItem( playerName, app.GetPlayerColour( m_players[i] ), voiceStatus); + } + } + + INetworkPlayer *thisPlayer = g_NetworkManager.GetLocalPlayerByUserIndex( m_iPad ); + m_isHostPlayer = false; + if(thisPlayer != NULL) m_isHostPlayer = thisPlayer->IsHost() == TRUE; + + Minecraft *pMinecraft = Minecraft::GetInstance(); + shared_ptr<MultiplayerLocalPlayer> localPlayer = pMinecraft->localplayers[m_iPad]; + if(!m_isHostPlayer && !localPlayer->isModerator() ) + { + removeControl( &m_buttonGameOptions, false ); + } + + updateTooltips(); + + if(controlHasFocus(eControl_GamePlayers)) + { + m_playerList.setCurrentSelection(getControlChildFocus()); + } +} + +void UIScene_InGameInfoMenu::tick() +{ + UIScene::tick(); + + for(DWORD i = 0; i < m_playersCount; ++i) + { + INetworkPlayer *player = g_NetworkManager.GetPlayerByIndex( i ); + + if( player != NULL ) + { + m_players[i] = player->GetSmallId(); + int voiceStatus = 0; + if(player != NULL && player->HasVoice() ) + { + if( player->IsMutedByLocalUser(m_iPad) ) + { + // Muted image + voiceStatus = 3; + } + else if( player->IsTalking() ) + { + // Talking image + voiceStatus = 2; + } + else + { + // Not talking image + voiceStatus = 1; + } + } + + if(voiceStatus != m_playersVoiceState[i]) + { + m_playersVoiceState[i] = voiceStatus; + m_playerList.setVOIPIcon( i, voiceStatus ); + } + + short icon = app.GetPlayerColour( m_players[i] ); + + if(icon != m_playersColourState[i]) + { + m_playersColourState[i] = icon; + m_playerList.setPlayerIcon( i, (int)app.GetPlayerColour( m_players[i] ) ); + } + + wstring playerName = L""; +#ifndef _CONTENT_PACKAGE + if(app.DebugSettingsOn() && (app.GetGameSettingsDebugMask()&(1L<<eDebugSetting_DebugLeaderboards))) + { + playerName = L"WWWWWWWWWWWWWWWW"; + } + else +#endif + { + playerName = player->GetDisplayName(); + } + if(playerName.compare( m_playerNames[i] ) != 0 ) + { + m_playerList.setButtonLabel(i, playerName); + m_playerNames[i] = playerName; + } + } + } +} + +void UIScene_InGameInfoMenu::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled) +{ + //app.DebugPrintf("UIScene_DebugOverlay handling input for pad %d, key %d, down- %s, pressed- %s, released- %s\n", iPad, key, down?"TRUE":"FALSE", pressed?"TRUE":"FALSE", released?"TRUE":"FALSE"); + ui.AnimateKeyPress(m_iPad, key, repeat, pressed, released); + + switch(key) + { + case ACTION_MENU_CANCEL: + if(pressed && !repeat) + { + ui.PlayUISFX(eSFX_Back); + navigateBack(); + } + break; + case ACTION_MENU_Y: +#if defined(__PS3__) || defined(__ORBIS__) + if(pressed && iPad == ProfileManager.GetPrimaryPad()) + { +#ifdef __PS3__ + // are we offline? + if(!ProfileManager.IsSignedInLive(iPad)) + { + // get them to sign in to online + UINT uiIDA[2]; + uiIDA[0]=IDS_PRO_NOTONLINE_ACCEPT; + uiIDA[1]=IDS_PRO_NOTONLINE_DECLINE; + ui.RequestMessageBox(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 2, ProfileManager.GetPrimaryPad(),&UIScene_InGameInfoMenu::MustSignInReturnedPSN,this, app.GetStringTable()); + } + else +#endif + { +#ifdef __ORBIS__ + SQRNetworkManager_Orbis::RecvInviteGUI(); +#else // __PS3__ + int ret = sceNpBasicRecvMessageCustom(SCE_NP_BASIC_MESSAGE_MAIN_TYPE_INVITE, SCE_NP_BASIC_RECV_MESSAGE_OPTIONS_INCLUDE_BOOTABLE, SYS_MEMORY_CONTAINER_ID_INVALID); + app.DebugPrintf("sceNpBasicRecvMessageCustom return %d ( %08x )\n", ret, ret); +#endif + } + } +#else + + + if(pressed && m_playerList.hasFocus() && (m_playerList.getItemCount() > 0) && (m_playerList.getCurrentSelection() < m_playersCount) ) + { + INetworkPlayer *player = g_NetworkManager.GetPlayerBySmallId(m_players[m_playerList.getCurrentSelection()]); + if( player != NULL ) + { + PlayerUID uid = player->GetUID(); + if( uid != INVALID_XUID ) + { +#ifdef __PSVITA__ + PSVITA_STUBBED; +#else + ProfileManager.ShowProfileCard(iPad,uid); +#endif + } + } + } + +#endif + break; + case ACTION_MENU_X: + + if(pressed && !repeat && !g_NetworkManager.IsLocalGame() ) + { +#ifdef __PSVITA__ + if(CGameNetworkManager::usingAdhocMode() == false) + g_NetworkManager.SendInviteGUI(iPad); +#else + g_NetworkManager.SendInviteGUI(iPad); +#endif + } + + break; + case ACTION_MENU_OK: +#ifdef __ORBIS__ + case ACTION_MENU_TOUCHPAD_PRESS: +#endif + case ACTION_MENU_UP: + case ACTION_MENU_DOWN: + case ACTION_MENU_PAGEUP: + case ACTION_MENU_PAGEDOWN: + sendInputToMovie(key, repeat, pressed, released); + break; + } +} + +void UIScene_InGameInfoMenu::handlePress(F64 controlId, F64 childId) +{ + app.DebugPrintf("Pressed = %d, %d\n", (int)controlId, (int)childId); + switch((int)controlId) + { + case eControl_GameOptions: + ui.NavigateToScene(m_iPad,eUIScene_InGameHostOptionsMenu); + break; + case eControl_GamePlayers: + int currentSelection = (int)childId; + INetworkPlayer *selectedPlayer = g_NetworkManager.GetPlayerBySmallId( m_players[ currentSelection ] ); + + Minecraft *pMinecraft = Minecraft::GetInstance(); + shared_ptr<MultiplayerLocalPlayer> localPlayer = pMinecraft->localplayers[m_iPad]; + + bool isOp = m_isHostPlayer || localPlayer->isModerator(); + bool cheats = app.GetGameHostOption(eGameHostOption_CheatsEnabled) != 0; + bool trust = app.GetGameHostOption(eGameHostOption_TrustPlayers) != 0; + + if( isOp && selectedPlayer != NULL) + { + bool editingHost = selectedPlayer->IsHost(); + if( (cheats && (m_isHostPlayer || !editingHost ) ) || (!trust && (m_isHostPlayer || !editingHost)) +#if (!defined(_CONTENT_PACKAGE) && !defined(_FINAL_BUILD) && defined(_DEBUG_MENUS_ENABLED)) + || (m_isHostPlayer && editingHost) +#endif + ) + { + InGamePlayerOptionsInitData *pInitData = new InGamePlayerOptionsInitData(); + pInitData->iPad = m_iPad; + pInitData->networkSmallId = m_players[ currentSelection ]; + pInitData->playerPrivileges = app.GetPlayerPrivileges(m_players[ currentSelection ] ); + ui.NavigateToScene(m_iPad,eUIScene_InGamePlayerOptionsMenu,pInitData); + } + else if(selectedPlayer->IsLocal() != TRUE && selectedPlayer->IsSameSystem(g_NetworkManager.GetHostPlayer()) != TRUE) + { + // Only ops will hit this, can kick anyone not local and not local to the host + BYTE *smallId = new BYTE(); + *smallId = m_players[currentSelection]; + UINT uiIDA[2]; + uiIDA[0]=IDS_CONFIRM_OK; + uiIDA[1]=IDS_CONFIRM_CANCEL; + + ui.RequestMessageBox(IDS_UNLOCK_KICK_PLAYER_TITLE, IDS_UNLOCK_KICK_PLAYER, uiIDA, 2, m_iPad,&UIScene_InGameInfoMenu::KickPlayerReturned,smallId,app.GetStringTable(),NULL,0,false); + } + } + break; + } +} + +void UIScene_InGameInfoMenu::handleFocusChange(F64 controlId, F64 childId) +{ + switch((int)controlId) + { + case eControl_GamePlayers: + m_playerList.updateChildFocus( (int) childId ); + }; + updateTooltips(); +} + +void UIScene_InGameInfoMenu::OnPlayerChanged(void *callbackParam, INetworkPlayer *pPlayer, bool leaving) +{ + UIScene_InGameInfoMenu *scene = (UIScene_InGameInfoMenu *)callbackParam; + bool playerFound = false; + int foundIndex = 0; + for(int i = 0; i < scene->m_playersCount; ++i) + { + if(!playerFound && scene->m_players[i] == pPlayer->GetSmallId() ) + { + if( scene->m_playerList.getCurrentSelection() == scene->m_playerList.getItemCount() - 1 ) + { + scene->m_playerList.setCurrentSelection( scene->m_playerList.getItemCount() - 2 ); + } + // Player removed + playerFound = true; + foundIndex = i; + } + } + + if( playerFound ) + { + --scene->m_playersCount; + scene->m_playersVoiceState[scene->m_playersCount] = 0; + scene->m_playersColourState[scene->m_playersCount] = 0; + scene->m_playerNames[scene->m_playersCount] = L""; + scene->m_playerList.removeItem(scene->m_playersCount); + } + + if( !playerFound ) + { + // Player added + scene->m_players[scene->m_playersCount] = pPlayer->GetSmallId(); + ++scene->m_playersCount; + + wstring playerName = L""; +#ifndef _CONTENT_PACKAGE + if(app.DebugSettingsOn() && (app.GetGameSettingsDebugMask()&(1L<<eDebugSetting_DebugLeaderboards))) + { + playerName = L"WWWWWWWWWWWWWWWW"; + } + else +#endif + { + playerName = pPlayer->GetDisplayName(); + } + + int voiceStatus = 0; + if(pPlayer != NULL && pPlayer->HasVoice() ) + { + if( pPlayer->IsMutedByLocalUser(scene->m_iPad) ) + { + // Muted image + voiceStatus = 3; + } + else if( pPlayer->IsTalking() ) + { + // Talking image + voiceStatus = 2; + } + else + { + // Not talking image + voiceStatus = 1; + } + } + + scene->m_playerList.addItem( playerName, app.GetPlayerColour( scene->m_players[scene->m_playersCount - 1] ), voiceStatus); + } +} + +int UIScene_InGameInfoMenu::KickPlayerReturned(void *pParam,int iPad,C4JStorage::EMessageResult result) +{ + BYTE smallId = *(BYTE *)pParam; + delete pParam; + + if(result==C4JStorage::EMessage_ResultAccept) + { + Minecraft *pMinecraft = Minecraft::GetInstance(); + shared_ptr<MultiplayerLocalPlayer> localPlayer = pMinecraft->localplayers[iPad]; + if(localPlayer->connection) + { + localPlayer->connection->send( shared_ptr<KickPlayerPacket>( new KickPlayerPacket(smallId) ) ); + } + } + + return 0; +} + +#if defined __PS3__ || defined __PSVITA__ +int UIScene_InGameInfoMenu::MustSignInReturnedPSN(void *pParam,int iPad,C4JStorage::EMessageResult result) +{ + UIScene_InGameInfoMenu* pClass = (UIScene_InGameInfoMenu*)pParam; + + if(result==C4JStorage::EMessage_ResultAccept) + { +#ifdef __PS3__ + SQRNetworkManager_PS3::AttemptPSNSignIn(&UIScene_InGameInfoMenu::ViewInvites_SignInReturned, pClass); +#else // __PSVITA__ + SQRNetworkManager_Vita::AttemptPSNSignIn(&UIScene_InGameInfoMenu::ViewInvites_SignInReturned, pClass); +#endif + } + + return 0; +} + +int UIScene_InGameInfoMenu::ViewInvites_SignInReturned(void *pParam,bool bContinue, int iPad) +{ + if(bContinue==true) + { + // Check if we're signed in to LIVE + if(ProfileManager.IsSignedInLive(iPad)) + { +#ifdef __ORBIS__ + SQRNetworkManager_Orbis::RecvInviteGUI(); +#elif defined(__PS3__) + int ret = sceNpBasicRecvMessageCustom(SCE_NP_BASIC_MESSAGE_MAIN_TYPE_INVITE, SCE_NP_BASIC_RECV_MESSAGE_OPTIONS_INCLUDE_BOOTABLE, SYS_MEMORY_CONTAINER_ID_INVALID); + app.DebugPrintf("sceNpBasicRecvMessageCustom return %d ( %08x )\n", ret, ret); +#else // __PSVITA__ + PSVITA_STUBBED; +#endif + } + } + return 0; +} +#endif diff --git a/Minecraft.Client/Common/UI/UIScene_InGameInfoMenu.h b/Minecraft.Client/Common/UI/UIScene_InGameInfoMenu.h new file mode 100644 index 00000000..94966fa3 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_InGameInfoMenu.h @@ -0,0 +1,62 @@ +#pragma once + +#include "UIScene.h" + +class UIScene_InGameInfoMenu : public UIScene +{ +private: + enum EControls + { + eControl_GameOptions, + eControl_GamePlayers, + }; + + bool m_isHostPlayer; + int m_playersCount; + BYTE m_players[MINECRAFT_NET_MAX_PLAYERS]; // An array of QNet small-id's + char m_playersVoiceState[MINECRAFT_NET_MAX_PLAYERS]; + short m_playersColourState[MINECRAFT_NET_MAX_PLAYERS]; + wstring m_playerNames[MINECRAFT_NET_MAX_PLAYERS]; + + UIControl_Button m_buttonGameOptions; + UIControl_PlayerList m_playerList; + UIControl_Label m_labelTitle; + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) + UI_MAP_ELEMENT( m_buttonGameOptions, "GameOptions") + UI_MAP_ELEMENT( m_playerList, "GamePlayers") + UI_MAP_ELEMENT( m_labelTitle, "Title") + UI_END_MAP_ELEMENTS_AND_NAMES() +public: + UIScene_InGameInfoMenu(int iPad, void *initData, UILayer *parentLayer); + + virtual EUIScene getSceneType() { return eUIScene_InGameInfoMenu;} + virtual void updateTooltips(); + + virtual void handleReload(); + + virtual void tick(); + +protected: + // TODO: This should be pure virtual in this class + virtual wstring getMoviePath(); + +public: + // INPUT + virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled); + +protected: + virtual void handleGainFocus(bool navBack); + void handlePress(F64 controlId, F64 childId); + virtual void handleDestroy(); + virtual void handleFocusChange(F64 controlId, F64 childId); + +public: + static int KickPlayerReturned(void *pParam,int iPad,C4JStorage::EMessageResult result); + static void OnPlayerChanged(void *callbackParam, INetworkPlayer *pPlayer, bool leaving); + +private: +#if defined(__PS3__) || defined (__PSVITA__) || defined(__ORBIS__) + static int MustSignInReturnedPSN(void *pParam,int iPad,C4JStorage::EMessageResult result); + static int ViewInvites_SignInReturned(void *pParam,bool bContinue, int iPad); +#endif +}; diff --git a/Minecraft.Client/Common/UI/UIScene_InGamePlayerOptionsMenu.cpp b/Minecraft.Client/Common/UI/UIScene_InGamePlayerOptionsMenu.cpp new file mode 100644 index 00000000..6eb22b09 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_InGamePlayerOptionsMenu.cpp @@ -0,0 +1,438 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIScene_InGamePlayerOptionsMenu.h" +#include "..\..\Minecraft.h" +#include "..\..\MultiPlayerLocalPlayer.h" +#include "..\..\ClientConnection.h" +#include "..\..\..\Minecraft.World\net.minecraft.network.packet.h" + + +#define CHECKBOXES_TIMER_ID 0 +#define CHECKBOXES_TIMER_TIME 100 + +UIScene_InGamePlayerOptionsMenu::UIScene_InGamePlayerOptionsMenu(int iPad, void *_initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) +{ + // Setup all the Iggy references we need for this scene + initialiseMovie(); + + m_bShouldNavBack = false; + + InGamePlayerOptionsInitData *initData = (InGamePlayerOptionsInitData *)_initData; + m_networkSmallId = initData->networkSmallId; + m_playerPrivileges = initData->playerPrivileges; + + INetworkPlayer *localPlayer = g_NetworkManager.GetLocalPlayerByUserIndex( m_iPad ); + INetworkPlayer *editingPlayer = g_NetworkManager.GetPlayerBySmallId(m_networkSmallId); + + if(editingPlayer != NULL) + { + m_labelGamertag.init(editingPlayer->GetDisplayName()); + } + + bool trustPlayers = app.GetGameHostOption(eGameHostOption_TrustPlayers) != 0; + bool cheats = app.GetGameHostOption(eGameHostOption_CheatsEnabled) != 0; + m_editingSelf = (localPlayer != NULL && localPlayer == editingPlayer); + + if( m_editingSelf || trustPlayers || editingPlayer->IsHost()) + { + removeControl( &m_checkboxes[eControl_BuildAndMine], true ); + removeControl( &m_checkboxes[eControl_UseDoorsAndSwitches], true ); + removeControl( &m_checkboxes[eControl_UseContainers], true ); + removeControl( &m_checkboxes[eControl_AttackPlayers], true ); + removeControl( &m_checkboxes[eControl_AttackAnimals], true ); + } + else + { + bool checked = (Player::getPlayerGamePrivilege(m_playerPrivileges, Player::ePlayerGamePrivilege_CannotMine)==0 && Player::getPlayerGamePrivilege(m_playerPrivileges, Player::ePlayerGamePrivilege_CannotBuild)==0); + m_checkboxes[eControl_BuildAndMine].init( app.GetString(IDS_CAN_BUILD_AND_MINE), eControl_BuildAndMine, checked); + + checked = (Player::getPlayerGamePrivilege(m_playerPrivileges, Player::ePlayerGamePrivilege_CanUseDoorsAndSwitches)!=0); + m_checkboxes[eControl_UseDoorsAndSwitches].init( app.GetString(IDS_CAN_USE_DOORS_AND_SWITCHES), eControl_UseDoorsAndSwitches, checked); + + checked = (Player::getPlayerGamePrivilege(m_playerPrivileges, Player::ePlayerGamePrivilege_CanUseContainers)!=0); + m_checkboxes[eControl_UseContainers].init( app.GetString(IDS_CAN_OPEN_CONTAINERS), eControl_UseContainers, checked); + + checked = Player::getPlayerGamePrivilege(m_playerPrivileges, Player::ePlayerGamePrivilege_CannotAttackPlayers)==0; + m_checkboxes[eControl_AttackPlayers].init( app.GetString(IDS_CAN_ATTACK_PLAYERS), eControl_AttackPlayers, checked); + + checked = Player::getPlayerGamePrivilege(m_playerPrivileges, Player::ePlayerGamePrivilege_CannotAttackAnimals)==0; + m_checkboxes[eControl_AttackAnimals].init( app.GetString(IDS_CAN_ATTACK_ANIMALS), eControl_AttackAnimals, checked); + } + + if(m_editingSelf) + { +#if (defined(_CONTENT_PACKAGE) || defined(_FINAL_BUILD) && !defined(_DEBUG_MENUS_ENABLED)) + removeControl( &m_checkboxes[eControl_Op], true ); +#else + m_checkboxes[eControl_Op].init(L"DEBUG: Creative",eControl_Op,Player::getPlayerGamePrivilege(m_playerPrivileges,Player::ePlayerGamePrivilege_CreativeMode)); +#endif + + removeControl( &m_buttonKick, true ); + removeControl( &m_checkboxes[eControl_CheatTeleport], true ); + + if(cheats) + { + bool canBeInvisible = Player::getPlayerGamePrivilege(m_playerPrivileges, Player::ePlayerGamePrivilege_CanToggleInvisible) != 0; + m_checkboxes[eControl_HostInvisible].SetEnable(canBeInvisible); + bool checked = canBeInvisible && (Player::getPlayerGamePrivilege(m_playerPrivileges, Player::ePlayerGamePrivilege_Invisible)!=0 && Player::getPlayerGamePrivilege(m_playerPrivileges, Player::ePlayerGamePrivilege_Invulnerable)!=0); + m_checkboxes[eControl_HostInvisible].init( app.GetString(IDS_INVISIBLE), eControl_HostInvisible, checked); + + bool inCreativeMode = Player::getPlayerGamePrivilege(m_playerPrivileges,Player::ePlayerGamePrivilege_CreativeMode) != 0; + if(inCreativeMode) + { + removeControl( &m_checkboxes[eControl_HostFly], true ); + removeControl( &m_checkboxes[eControl_HostHunger], true ); + } + else + { + bool canFly = Player::getPlayerGamePrivilege(m_playerPrivileges,Player::ePlayerGamePrivilege_CanToggleFly); + bool canChangeHunger = Player::getPlayerGamePrivilege(m_playerPrivileges,Player::ePlayerGamePrivilege_CanToggleClassicHunger); + + m_checkboxes[eControl_HostFly].SetEnable(canFly); + checked = canFly && Player::getPlayerGamePrivilege(m_playerPrivileges, Player::ePlayerGamePrivilege_CanFly)!=0; + m_checkboxes[eControl_HostFly].init( app.GetString(IDS_CAN_FLY), eControl_HostFly, checked); + + m_checkboxes[eControl_HostHunger].SetEnable(canChangeHunger); + checked = canChangeHunger && Player::getPlayerGamePrivilege(m_playerPrivileges, Player::ePlayerGamePrivilege_ClassicHunger)!=0; + m_checkboxes[eControl_HostHunger].init( app.GetString(IDS_DISABLE_EXHAUSTION), eControl_HostHunger, checked); + } + } + else + { + removeControl( &m_checkboxes[eControl_HostInvisible], true ); + removeControl( &m_checkboxes[eControl_HostFly], true ); + removeControl( &m_checkboxes[eControl_HostHunger], true ); + } + } + else + { + if(localPlayer->IsHost()) + { + // Only host can make people moderators, or enable teleporting for them + m_checkboxes[eControl_Op].init( app.GetString(IDS_MODERATOR), eControl_Op, Player::getPlayerGamePrivilege(m_playerPrivileges, Player::ePlayerGamePrivilege_Op)!=0); + } + else + { + removeControl( &m_checkboxes[eControl_Op], true ); + } + + /*if(localPlayer->IsHost() && cheats ) + { + m_checkboxes[eControl_HostInvisible].SetEnable(true); + bool checked = Player::getPlayerGamePrivilege(m_playerPrivileges, Player::ePlayerGamePrivilege_CanToggleInvisible)!=0; + m_checkboxes[eControl_HostInvisible].init( app.GetString(IDS_CAN_INVISIBLE), eControl_HostInvisible, checked); + + m_checkboxes[eControl_HostFly].SetEnable(true); + checked = Player::getPlayerGamePrivilege(m_playerPrivileges, Player::ePlayerGamePrivilege_CanToggleFly)!=0; + m_checkboxes[eControl_HostFly].init( app.GetString(IDS_CAN_FLY), eControl_HostFly, checked); + + m_checkboxes[eControl_HostHunger].SetEnable(true); + checked = Player::getPlayerGamePrivilege(m_playerPrivileges, Player::ePlayerGamePrivilege_CanToggleClassicHunger)!=0; + m_checkboxes[eControl_HostHunger].init( app.GetString(IDS_CAN_DISABLE_EXHAUSTION), eControl_HostHunger, checked); + + checked = Player::getPlayerGamePrivilege(m_playerPrivileges, Player::ePlayerGamePrivilege_CanTeleport)!=0; + m_checkboxes[eControl_CheatTeleport].init(app.GetString(IDS_ENABLE_TELEPORT),eControl_CheatTeleport,checked); + } + else + { + removeControl( &m_checkboxes[eControl_HostInvisible], true ); + removeControl( &m_checkboxes[eControl_HostFly], true ); + removeControl( &m_checkboxes[eControl_HostHunger], true ); + removeControl( &m_checkboxes[eControl_CheatTeleport], true ); + }*/ + + if(localPlayer->IsHost() && cheats ) + { + m_checkboxes[eControl_HostInvisible].SetEnable(true); + bool checked = Player::getPlayerGamePrivilege(m_playerPrivileges, Player::ePlayerGamePrivilege_CanToggleInvisible)!=0; + m_checkboxes[eControl_HostInvisible].init( app.GetString(IDS_CAN_INVISIBLE), eControl_HostInvisible, checked); + + + bool inCreativeMode = Player::getPlayerGamePrivilege(m_playerPrivileges,Player::ePlayerGamePrivilege_CreativeMode) != 0; + if(inCreativeMode) + { + removeControl( &m_checkboxes[eControl_HostFly], true ); + removeControl( &m_checkboxes[eControl_HostHunger], true ); + } + else + { + m_checkboxes[eControl_HostFly].SetEnable(true); + checked = Player::getPlayerGamePrivilege(m_playerPrivileges, Player::ePlayerGamePrivilege_CanToggleFly)!=0; + m_checkboxes[eControl_HostFly].init( app.GetString(IDS_CAN_FLY), eControl_HostFly, checked); + + m_checkboxes[eControl_HostHunger].SetEnable(true); + checked = Player::getPlayerGamePrivilege(m_playerPrivileges, Player::ePlayerGamePrivilege_CanToggleClassicHunger)!=0; + m_checkboxes[eControl_HostHunger].init( app.GetString(IDS_CAN_DISABLE_EXHAUSTION), eControl_HostHunger, checked); + } + + checked = Player::getPlayerGamePrivilege(m_playerPrivileges, Player::ePlayerGamePrivilege_CanTeleport)!=0; + m_checkboxes[eControl_CheatTeleport].init(app.GetString(IDS_ENABLE_TELEPORT),eControl_CheatTeleport,checked); + } + else + { + removeControl( &m_checkboxes[eControl_HostInvisible], true ); + removeControl( &m_checkboxes[eControl_HostFly], true ); + removeControl( &m_checkboxes[eControl_HostHunger], true ); + removeControl( &m_checkboxes[eControl_CheatTeleport], true ); + } + + + // Can only kick people if they are not local, and not local to the host + if(editingPlayer->IsLocal() != TRUE && editingPlayer->IsSameSystem(g_NetworkManager.GetHostPlayer()) != TRUE) + { + m_buttonKick.init( app.GetString(IDS_KICK_PLAYER), eControl_Kick); + } + else + { + removeControl( &m_buttonKick, true ); + } + } + + short colourIndex = app.GetPlayerColour( m_networkSmallId ); + IggyDataValue result; + IggyDataValue value[1]; + value[0].type = IGGY_DATATYPE_number; + value[0].number = colourIndex; + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcSetPlayerIcon , 1 , value ); + +#if TO_BE_IMPLEMENTED + if(app.GetLocalPlayerCount()>1) + { + app.AdjustSplitscreenScene(m_hObj,&m_OriginalPosition,m_iPad); + } +#endif + + m_bModeratorState = m_checkboxes[eControl_Op].IsChecked(); + + resetCheatCheckboxes(); + + addTimer(CHECKBOXES_TIMER_ID,CHECKBOXES_TIMER_TIME); + + g_NetworkManager.RegisterPlayerChangedCallback(m_iPad, &UIScene_InGamePlayerOptionsMenu::OnPlayerChanged, this); + +#ifdef __PSVITA__ + ui.TouchBoxRebuild(this); +#endif +} + +wstring UIScene_InGamePlayerOptionsMenu::getMoviePath() +{ + if(app.GetLocalPlayerCount() > 1) + { + return L"InGamePlayerOptionsSplit"; + } + else + { + return L"InGamePlayerOptions"; + } +} + +void UIScene_InGamePlayerOptionsMenu::updateTooltips() +{ + ui.SetTooltips( m_iPad, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK); +} + +void UIScene_InGamePlayerOptionsMenu::tick() +{ + UIScene::tick(); + + if(m_bShouldNavBack) + { + m_bShouldNavBack = false; + ui.NavigateBack(m_iPad); + } +} + +void UIScene_InGamePlayerOptionsMenu::handleDestroy() +{ + g_NetworkManager.UnRegisterPlayerChangedCallback(m_iPad, &UIScene_InGamePlayerOptionsMenu::OnPlayerChanged, this); +} + +void UIScene_InGamePlayerOptionsMenu::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled) +{ + //app.DebugPrintf("UIScene_DebugOverlay handling input for pad %d, key %d, down- %s, pressed- %s, released- %s\n", iPad, key, down?"TRUE":"FALSE", pressed?"TRUE":"FALSE", released?"TRUE":"FALSE"); + + ui.AnimateKeyPress(iPad, key, repeat, pressed, released); + switch(key) + { + case ACTION_MENU_CANCEL: + if(pressed) + { + bool trustPlayers = app.GetGameHostOption(eGameHostOption_TrustPlayers) != 0; + bool cheats = app.GetGameHostOption(eGameHostOption_CheatsEnabled) != 0; + if(m_editingSelf) + { +#if (defined(_CONTENT_PACKAGE) || defined(_FINAL_BUILD) && !defined(_DEBUG_MENUS_ENABLED)) +#else + Player::setPlayerGamePrivilege(m_playerPrivileges,Player::ePlayerGamePrivilege_CreativeMode,m_checkboxes[eControl_Op].IsChecked()); +#endif + if(cheats) + { + bool canBeInvisible = Player::getPlayerGamePrivilege(m_playerPrivileges, Player::ePlayerGamePrivilege_CanToggleInvisible) != 0; + if(canBeInvisible) Player::setPlayerGamePrivilege(m_playerPrivileges,Player::ePlayerGamePrivilege_Invisible,m_checkboxes[eControl_HostInvisible].IsChecked()); + if(canBeInvisible) Player::setPlayerGamePrivilege(m_playerPrivileges,Player::ePlayerGamePrivilege_Invulnerable,m_checkboxes[eControl_HostInvisible].IsChecked()); + + bool inCreativeMode = Player::getPlayerGamePrivilege(m_playerPrivileges,Player::ePlayerGamePrivilege_CreativeMode) != 0; + if(!inCreativeMode) + { + bool canFly = Player::getPlayerGamePrivilege(m_playerPrivileges,Player::ePlayerGamePrivilege_CanToggleFly); + bool canChangeHunger = Player::getPlayerGamePrivilege(m_playerPrivileges,Player::ePlayerGamePrivilege_CanToggleClassicHunger); + + if(canFly) Player::setPlayerGamePrivilege(m_playerPrivileges,Player::ePlayerGamePrivilege_CanFly,m_checkboxes[eControl_HostFly].IsChecked()); + if(canChangeHunger) Player::setPlayerGamePrivilege(m_playerPrivileges,Player::ePlayerGamePrivilege_ClassicHunger,m_checkboxes[eControl_HostHunger].IsChecked()); + } + } + } + else + { + INetworkPlayer *editingPlayer = g_NetworkManager.GetPlayerBySmallId(m_networkSmallId); + if(!trustPlayers && (editingPlayer != NULL && !editingPlayer->IsHost() ) ) + { + Player::setPlayerGamePrivilege(m_playerPrivileges,Player::ePlayerGamePrivilege_CannotMine,!m_checkboxes[eControl_BuildAndMine].IsChecked()); + Player::setPlayerGamePrivilege(m_playerPrivileges,Player::ePlayerGamePrivilege_CannotBuild,!m_checkboxes[eControl_BuildAndMine].IsChecked()); + Player::setPlayerGamePrivilege(m_playerPrivileges,Player::ePlayerGamePrivilege_CannotAttackPlayers,!m_checkboxes[eControl_AttackPlayers].IsChecked()); + Player::setPlayerGamePrivilege(m_playerPrivileges,Player::ePlayerGamePrivilege_CannotAttackAnimals, !m_checkboxes[eControl_AttackAnimals].IsChecked()); + Player::setPlayerGamePrivilege(m_playerPrivileges,Player::ePlayerGamePrivilege_CanUseDoorsAndSwitches, m_checkboxes[eControl_UseDoorsAndSwitches].IsChecked()); + Player::setPlayerGamePrivilege(m_playerPrivileges,Player::ePlayerGamePrivilege_CanUseContainers, m_checkboxes[eControl_UseContainers].IsChecked()); + } + + INetworkPlayer *localPlayer = g_NetworkManager.GetLocalPlayerByUserIndex( m_iPad ); + + if(localPlayer->IsHost()) + { + if(cheats) + { + Player::setPlayerGamePrivilege(m_playerPrivileges,Player::ePlayerGamePrivilege_CanToggleInvisible,m_checkboxes[eControl_HostInvisible].IsChecked()); + Player::setPlayerGamePrivilege(m_playerPrivileges,Player::ePlayerGamePrivilege_CanToggleFly,m_checkboxes[eControl_HostFly].IsChecked()); + Player::setPlayerGamePrivilege(m_playerPrivileges,Player::ePlayerGamePrivilege_CanToggleClassicHunger,m_checkboxes[eControl_HostHunger].IsChecked()); + Player::setPlayerGamePrivilege(m_playerPrivileges,Player::ePlayerGamePrivilege_CanTeleport,m_checkboxes[eControl_CheatTeleport].IsChecked()); + } + + Player::setPlayerGamePrivilege(m_playerPrivileges,Player::ePlayerGamePrivilege_Op,m_checkboxes[eControl_Op].IsChecked()); + } + } + unsigned int originalPrivileges = app.GetPlayerPrivileges(m_networkSmallId); + if(originalPrivileges != m_playerPrivileges) + { + // Send update settings packet to server + Minecraft *pMinecraft = Minecraft::GetInstance(); + shared_ptr<MultiplayerLocalPlayer> player = pMinecraft->localplayers[m_iPad]; + if(player->connection) + { + player->connection->send( shared_ptr<PlayerInfoPacket>( new PlayerInfoPacket( m_networkSmallId, -1, m_playerPrivileges) ) ); + } + } + navigateBack(); + + handled = true; + } + break; + case ACTION_MENU_OK: +#ifdef __ORBIS__ + case ACTION_MENU_TOUCHPAD_PRESS: +#endif + sendInputToMovie(key, repeat, pressed, released); + break; + case ACTION_MENU_UP: + case ACTION_MENU_DOWN: + sendInputToMovie(key, repeat, pressed, released); + break; + } +} + +void UIScene_InGamePlayerOptionsMenu::handlePress(F64 controlId, F64 childId) +{ + switch((int)controlId) + { + case eControl_Kick: + { + BYTE *smallId = new BYTE(); + *smallId = m_networkSmallId; + UINT uiIDA[2]; + uiIDA[0]=IDS_CONFIRM_OK; + uiIDA[1]=IDS_CONFIRM_CANCEL; + + ui.RequestMessageBox(IDS_UNLOCK_KICK_PLAYER_TITLE, IDS_UNLOCK_KICK_PLAYER, uiIDA, 2, m_iPad,&UIScene_InGamePlayerOptionsMenu::KickPlayerReturned,smallId,app.GetStringTable(),NULL,0,false); + } + break; + }; +} + +int UIScene_InGamePlayerOptionsMenu::KickPlayerReturned(void *pParam,int iPad,C4JStorage::EMessageResult result) +{ + BYTE smallId = *(BYTE *)pParam; + delete pParam; + + if(result==C4JStorage::EMessage_ResultAccept) + { + Minecraft *pMinecraft = Minecraft::GetInstance(); + shared_ptr<MultiplayerLocalPlayer> localPlayer = pMinecraft->localplayers[iPad]; + if(localPlayer->connection) + { + localPlayer->connection->send( shared_ptr<KickPlayerPacket>( new KickPlayerPacket(smallId) ) ); + } + + // Fix for #61494 - [CRASH]: TU7: Code: Multiplayer: Title may crash while kicking a player from an online game. + // We cannot do a navigate back here is this actually occurs on a thread other than the main thread. On rare occasions this can clash + // with the XUI render and causes a crash. The OnPlayerChanged event should perform the navigate back on the main thread + //app.NavigateBack(iPad); + } + + return 0; +} + +void UIScene_InGamePlayerOptionsMenu::OnPlayerChanged(void *callbackParam, INetworkPlayer *pPlayer, bool leaving) +{ + app.DebugPrintf("UIScene_InGamePlayerOptionsMenu::OnPlayerChanged"); + UIScene_InGamePlayerOptionsMenu *scene = (UIScene_InGamePlayerOptionsMenu *)callbackParam; + + UIScene_InGameInfoMenu *infoScene = (UIScene_InGameInfoMenu *)scene->getBackScene(); + if(infoScene != NULL) UIScene_InGameInfoMenu::OnPlayerChanged(infoScene,pPlayer,leaving); + + if(leaving && pPlayer != NULL && pPlayer->GetSmallId() == scene->m_networkSmallId) + { + scene->m_bShouldNavBack = true; + } +} + +void UIScene_InGamePlayerOptionsMenu::resetCheatCheckboxes() +{ + bool isModerator = m_checkboxes[eControl_Op].IsChecked(); + //bool cheatsEnabled = app.GetGameHostOption(eGameHostOption_CheatsEnabled) != 0; + + if (!m_editingSelf) + { + m_checkboxes[eControl_HostInvisible].SetEnable(isModerator); + m_checkboxes[eControl_HostFly].SetEnable(isModerator); + m_checkboxes[eControl_HostHunger].SetEnable(isModerator); + m_checkboxes[eControl_CheatTeleport].SetEnable(isModerator); + } +} + +void UIScene_InGamePlayerOptionsMenu::handleCheckboxToggled(F64 controlId, bool selected) +{ + switch((int)controlId) + { + case eControl_Op: + // flag that the moderator state has changed + //resetCheatCheckboxes(); + break; + } +} + +void UIScene_InGamePlayerOptionsMenu::handleTimerComplete(int id) +{ + switch(id) + { + case CHECKBOXES_TIMER_ID: + { + bool bIsModerator = m_checkboxes[eControl_Op].IsChecked(); + if(m_bModeratorState!=bIsModerator) + { + m_bModeratorState=bIsModerator; + resetCheatCheckboxes(); + } + } + break; + } +} diff --git a/Minecraft.Client/Common/UI/UIScene_InGamePlayerOptionsMenu.h b/Minecraft.Client/Common/UI/UIScene_InGamePlayerOptionsMenu.h new file mode 100644 index 00000000..78e30f6e --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_InGamePlayerOptionsMenu.h @@ -0,0 +1,90 @@ +#pragma once + +#include "UIScene.h" + +class UIScene_InGamePlayerOptionsMenu : public UIScene +{ +private: + enum EControls + { + // Checkboxes + eControl_BuildAndMine, + eControl_UseDoorsAndSwitches, + eControl_UseContainers, + eControl_AttackPlayers, + eControl_AttackAnimals, + eControl_Op, + eControl_CheatTeleport, + eControl_HostFly, + eControl_HostHunger, + eControl_HostInvisible, + + eControl_CHECKBOXES_COUNT, + + // Others + eControl_Kick = eControl_CHECKBOXES_COUNT, + }; + + bool m_bShouldNavBack; + bool m_editingSelf; + BYTE m_networkSmallId; + unsigned int m_playerPrivileges; + + UIControl_Label m_labelGamertag; + UIControl_CheckBox m_checkboxes[eControl_CHECKBOXES_COUNT]; + UIControl_Button m_buttonKick; + IggyName m_funcSetPlayerIcon; + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) + UI_MAP_ELEMENT( m_checkboxes[eControl_BuildAndMine], "CheckboxBuildAndMine") + UI_MAP_ELEMENT( m_checkboxes[eControl_UseDoorsAndSwitches], "CheckboxUseDoorsAndSwitches") + UI_MAP_ELEMENT( m_checkboxes[eControl_UseContainers], "CheckboxUseContainers") + UI_MAP_ELEMENT( m_checkboxes[eControl_AttackPlayers], "CheckboxAttackPlayers") + UI_MAP_ELEMENT( m_checkboxes[eControl_AttackAnimals], "CheckboxAttackAnimals") + UI_MAP_ELEMENT( m_checkboxes[eControl_Op], "CheckboxOp") + UI_MAP_ELEMENT( m_checkboxes[eControl_CheatTeleport], "CheckboxTeleport") + UI_MAP_ELEMENT( m_checkboxes[eControl_HostFly], "CheckboxHostFly") + UI_MAP_ELEMENT( m_checkboxes[eControl_HostHunger], "CheckboxHostHunger") + UI_MAP_ELEMENT( m_checkboxes[eControl_HostInvisible], "CheckboxHostInvisible") + + UI_MAP_ELEMENT( m_buttonKick, "ButtonKick") + + UI_MAP_ELEMENT( m_labelGamertag, "Gamertag") + + UI_MAP_NAME( m_funcSetPlayerIcon, L"SetPlayerIcon" ); + UI_END_MAP_ELEMENTS_AND_NAMES() + + bool m_bModeratorState; + + +public: + UIScene_InGamePlayerOptionsMenu(int iPad, void *initData, UILayer *parentLayer); + + virtual EUIScene getSceneType() { return eUIScene_InGamePlayerOptionsMenu;} + virtual void updateTooltips(); + +protected: + // TODO: This should be pure virtual in this class + virtual wstring getMoviePath(); + virtual void handleCheckboxToggled(F64 controlId, bool selected); + virtual void handleTimerComplete(int id); + +public: + virtual void tick(); + + // INPUT + virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled); + + virtual void handleDestroy(); + virtual void handlePress(F64 controlId, F64 childId); + + + static int KickPlayerReturned(void *pParam,int iPad,C4JStorage::EMessageResult result); + static void OnPlayerChanged(void *callbackParam, INetworkPlayer *pPlayer, bool leaving); + +private: + /** 4J-JEV: + For enabling/disabling 'Can Fly', 'Can Teleport', 'Can Disable Hunger' etc + used after changing the moderator checkbox. + */ + void resetCheatCheckboxes(); +};
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIScene_InGameSaveManagementMenu.cpp b/Minecraft.Client/Common/UI/UIScene_InGameSaveManagementMenu.cpp new file mode 100644 index 00000000..b0dbc59f --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_InGameSaveManagementMenu.cpp @@ -0,0 +1,497 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIScene_InGameSaveManagementMenu.h" + +#if defined(__ORBIS__) || defined(__PSVITA__) +#include <ces.h> +#endif + +int UIScene_InGameSaveManagementMenu::LoadSaveDataThumbnailReturned(LPVOID lpParam,PBYTE pbThumbnail,DWORD dwThumbnailBytes) +{ + UIScene_InGameSaveManagementMenu *pClass= (UIScene_InGameSaveManagementMenu *)lpParam; + + app.DebugPrintf("Received data for save thumbnail\n"); + + if(pbThumbnail && dwThumbnailBytes) + { + pClass->m_saveDetails[pClass->m_iRequestingThumbnailId].pbThumbnailData = new BYTE[dwThumbnailBytes]; + memcpy(pClass->m_saveDetails[pClass->m_iRequestingThumbnailId].pbThumbnailData, pbThumbnail, dwThumbnailBytes); + pClass->m_saveDetails[pClass->m_iRequestingThumbnailId].dwThumbnailSize = dwThumbnailBytes; + } + else + { + pClass->m_saveDetails[pClass->m_iRequestingThumbnailId].pbThumbnailData = NULL; + pClass->m_saveDetails[pClass->m_iRequestingThumbnailId].dwThumbnailSize = 0; + app.DebugPrintf("Save thumbnail data is NULL, or has size 0\n"); + } + pClass->m_bSaveThumbnailReady = true; + + return 0; +} + +UIScene_InGameSaveManagementMenu::UIScene_InGameSaveManagementMenu(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) +{ + // Setup all the Iggy references we need for this scene + initialiseMovie(); + + m_iRequestingThumbnailId = 0; + m_iSaveInfoC=0; + m_bIgnoreInput = false; + m_iState=e_SavesIdle; + //m_bRetrievingSaveInfo=false; + + m_buttonListSaves.init(eControl_SavesList); + + m_labelSavesListTitle.init( app.GetString(IDS_SAVE_INCOMPLETE_DELETE_SAVES) ); + m_controlSavesTimer.setVisible( true ); + + +#if defined(_XBOX_ONE) || defined(__ORBIS__) + m_spaceIndicatorSaves.init(L"",eControl_SpaceIndicator,0, (4LL *1024LL * 1024LL * 1024LL) ); +#endif + m_bUpdateSaveSize = false; + + m_bAllLoaded = false; + m_bRetrievingSaveThumbnails = false; + m_bSaveThumbnailReady = false; + m_bExitScene=false; + m_pSaveDetails=NULL; + m_bSavesDisplayed=false; + m_saveDetails = NULL; + m_iSaveDetailsCount = 0; + +#if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__) || defined(_DURANGO) + // Always clear the saves when we enter this menu + StorageManager.ClearSavesInfo(); +#endif + + // block input if we're waiting for DLC to install, and wipe the saves list. The end of dlc mounting custom message will fill the list again + if(app.StartInstallDLCProcess(m_iPad)==true || app.DLCInstallPending()) + { + // if we're waiting for DLC to mount, don't fill the save list. The custom message on end of dlc mounting will do that + m_bIgnoreInput = true; + } + else + { + Initialise(); + } + +#ifdef __PSVITA__ + if(CGameNetworkManager::usingAdhocMode() && SQRNetworkManager_AdHoc_Vita::GetAdhocStatus()) + { + g_NetworkManager.startAdhocMatching(); // create the client matching context and clear out the friends list + } + +#endif + + // If we're not ignoring input, then we aren't still waiting for the DLC to mount, and can now check for corrupt dlc. Otherwise this will happen when the dlc has finished mounting. + if( !m_bIgnoreInput) + { + app.m_dlcManager.checkForCorruptDLCAndAlert(); + } + + parentLayer->addComponent(iPad,eUIComponent_MenuBackground); +} + + +UIScene_InGameSaveManagementMenu::~UIScene_InGameSaveManagementMenu() +{ + m_parentLayer->removeComponent(eUIComponent_MenuBackground); + + if(m_saveDetails) + { + for(int i = 0; i < m_iSaveDetailsCount; ++i) + { + delete m_saveDetails[i].pbThumbnailData; + } + delete [] m_saveDetails; + } + app.LeaveSaveNotificationSection(); + StorageManager.SetSaveDisabled(false); + StorageManager.ContinueIncompleteOperation(); +} + +void UIScene_InGameSaveManagementMenu::updateTooltips() +{ + int iA = -1; + if( m_bSavesDisplayed && m_iSaveDetailsCount > 0) + { + iA = IDS_TOOLTIPS_DELETESAVE; + } + ui.SetTooltips( m_parentLayer->IsFullscreenGroup()?XUSER_INDEX_ANY:m_iPad, iA, IDS_SAVE_INCOMPLETE_RETRY_SAVING); +} + +// +void UIScene_InGameSaveManagementMenu::Initialise() +{ + m_iSaveListIndex = 0; + + // Check if we're in the trial version + if(ProfileManager.IsFullVersion()==false) + { + } + else if(StorageManager.GetSaveDisabled()) + { + GetSaveInfo(); + } + else + { + // 4J-PB - we need to check that there is enough space left to create a copy of the save (for a rename) + bool bCanRename = StorageManager.EnoughSpaceForAMinSaveGame(); + + GetSaveInfo(); + } + + m_bIgnoreInput=false; +} + +void UIScene_InGameSaveManagementMenu::handleReload() +{ + m_bIgnoreInput = false; + m_iRequestingThumbnailId = 0; + m_bAllLoaded=false; + m_bRetrievingSaveThumbnails=false; + m_bSavesDisplayed=false; + m_iSaveInfoC=0; +} + +void UIScene_InGameSaveManagementMenu::handleGainFocus(bool navBack) +{ + UIScene::handleGainFocus(navBack); + + updateTooltips(); + + if(navBack) + { + // re-enable button presses + m_bIgnoreInput=false; + } +} + +wstring UIScene_InGameSaveManagementMenu::getMoviePath() +{ + return L"SaveMenu"; +} + +void UIScene_InGameSaveManagementMenu::tick() +{ + UIScene::tick(); + + if(m_bExitScene) // navigate forward or back + { + if(!m_bRetrievingSaveThumbnails) + { + // need to wait for any callback retrieving thumbnail to complete + navigateBack(); + } + } + // Stop loading thumbnails if we navigate forwards + if(hasFocus(m_iPad)) + { + if(m_bUpdateSaveSize) + { + m_spaceIndicatorSaves.selectSave(m_iSaveListIndex); + m_bUpdateSaveSize = false; + } + + // Display the saves if we have them + if(!m_bSavesDisplayed) + { + m_pSaveDetails=StorageManager.ReturnSavesInfo(); + if(m_pSaveDetails!=NULL) + { + m_spaceIndicatorSaves.reset(); + + m_bSavesDisplayed=true; + + if(m_saveDetails!=NULL) + { + for(unsigned int i = 0; i < m_pSaveDetails->iSaveC; ++i) + { + if(m_saveDetails[i].pbThumbnailData!=NULL) + { + delete m_saveDetails[i].pbThumbnailData; + } + } + delete m_saveDetails; + } + m_saveDetails = new SaveListDetails[m_pSaveDetails->iSaveC]; + + m_iSaveDetailsCount = m_pSaveDetails->iSaveC; + for(unsigned int i = 0; i < m_pSaveDetails->iSaveC; ++i) + { +#if defined(_XBOX_ONE) + m_spaceIndicatorSaves.addSave( m_pSaveDetails->SaveInfoA[i].totalSize ); +#elif defined(__ORBIS__) + m_spaceIndicatorSaves.addSave( m_pSaveDetails->SaveInfoA[i].blocksUsed * (32 * 1024) ); +#endif +#ifdef _DURANGO + m_buttonListSaves.addItem(m_pSaveDetails->SaveInfoA[i].UTF16SaveTitle, L""); + + m_saveDetails[i].saveId = i; + memcpy(m_saveDetails[i].UTF16SaveName, m_pSaveDetails->SaveInfoA[i].UTF16SaveTitle, 128); + memcpy(m_saveDetails[i].UTF16SaveFilename, m_pSaveDetails->SaveInfoA[i].UTF16SaveFilename, MAX_SAVEFILENAME_LENGTH); +#else + m_buttonListSaves.addItem(m_pSaveDetails->SaveInfoA[i].UTF8SaveTitle, L""); + + m_saveDetails[i].saveId = i; + memcpy(m_saveDetails[i].UTF8SaveName, m_pSaveDetails->SaveInfoA[i].UTF8SaveTitle, 128); + memcpy(m_saveDetails[i].UTF8SaveFilename, m_pSaveDetails->SaveInfoA[i].UTF8SaveFilename, MAX_SAVEFILENAME_LENGTH); +#endif + } + m_controlSavesTimer.setVisible( false ); + + // set focus on the first button + + } + } + + if(!m_bExitScene && m_bSavesDisplayed && !m_bRetrievingSaveThumbnails && !m_bAllLoaded) + { + if( m_iRequestingThumbnailId < (m_buttonListSaves.getItemCount() )) + { + m_bRetrievingSaveThumbnails = true; + app.DebugPrintf("Requesting the first thumbnail\n"); + // set the save to load + PSAVE_DETAILS pSaveDetails=StorageManager.ReturnSavesInfo(); + C4JStorage::ESaveGameState eLoadStatus=StorageManager.LoadSaveDataThumbnail(&pSaveDetails->SaveInfoA[(int)m_iRequestingThumbnailId],&LoadSaveDataThumbnailReturned,this); + + if(eLoadStatus!=C4JStorage::ESaveGame_GetSaveThumbnail) + { + // something went wrong + m_bRetrievingSaveThumbnails=false; + m_bAllLoaded = true; + } + } + } + else if (m_bSavesDisplayed && m_bSaveThumbnailReady) + { + m_bSaveThumbnailReady = false; + + // check we're not waiting to exit the scene + if(!m_bExitScene) + { + // convert to utf16 + uint16_t u16Message[MAX_SAVEFILENAME_LENGTH]; +#ifdef _DURANGO + // Already utf16 on durango + memcpy(u16Message, m_saveDetails[m_iRequestingThumbnailId].UTF16SaveFilename, MAX_SAVEFILENAME_LENGTH); +#elif defined(_WINDOWS64) + int result = ::MultiByteToWideChar( + CP_UTF8, // convert from UTF-8 + MB_ERR_INVALID_CHARS, // error on invalid chars + m_saveDetails[m_iRequestingThumbnailId].UTF8SaveFilename, // source UTF-8 string + MAX_SAVEFILENAME_LENGTH, // total length of source UTF-8 string, + // in CHAR's (= bytes), including end-of-string \0 + (wchar_t *)u16Message, // destination buffer + MAX_SAVEFILENAME_LENGTH // size of destination buffer, in WCHAR's + ); +#else +#ifdef __PS3 + size_t srcmax,dstmax; +#else + uint32_t srcmax,dstmax; + uint32_t srclen,dstlen; +#endif + srcmax=MAX_SAVEFILENAME_LENGTH; + dstmax=MAX_SAVEFILENAME_LENGTH; + +#if defined(__PS3__) + L10nResult lres= UTF8stoUTF16s((uint8_t *)m_saveDetails[m_iRequestingThumbnailId].UTF8SaveFilename,&srcmax,u16Message,&dstmax); +#else + SceCesUcsContext context; + sceCesUcsContextInit(&context); + + sceCesUtf8StrToUtf16Str(&context, (uint8_t *)m_saveDetails[m_iRequestingThumbnailId].UTF8SaveFilename,srcmax,&srclen,u16Message,dstmax,&dstlen); +#endif +#endif + if( m_saveDetails[m_iRequestingThumbnailId].pbThumbnailData ) + { + registerSubstitutionTexture((wchar_t *)u16Message,m_saveDetails[m_iRequestingThumbnailId].pbThumbnailData,m_saveDetails[m_iRequestingThumbnailId].dwThumbnailSize); + } + m_buttonListSaves.setTextureName(m_iRequestingThumbnailId, (wchar_t *)u16Message); + + ++m_iRequestingThumbnailId; + if( m_iRequestingThumbnailId < (m_buttonListSaves.getItemCount() )) + { + app.DebugPrintf("Requesting another thumbnail\n"); + // set the save to load + PSAVE_DETAILS pSaveDetails=StorageManager.ReturnSavesInfo(); + C4JStorage::ESaveGameState eLoadStatus=StorageManager.LoadSaveDataThumbnail(&pSaveDetails->SaveInfoA[(int)m_iRequestingThumbnailId],&LoadSaveDataThumbnailReturned,this); + if(eLoadStatus!=C4JStorage::ESaveGame_GetSaveThumbnail) + { + // something went wrong + m_bRetrievingSaveThumbnails=false; + m_bAllLoaded = true; + } + } + else + { + m_bRetrievingSaveThumbnails = false; + m_bAllLoaded = true; + } + } + else + { + // stop retrieving thumbnails, and exit + m_bRetrievingSaveThumbnails = false; + } + } + } + + switch(m_iState) + { + case e_SavesIdle: + break; + case e_SavesRepopulateAfterDelete: + m_bIgnoreInput = false; + m_iRequestingThumbnailId = 0; + m_bAllLoaded=false; + m_bRetrievingSaveThumbnails=false; + m_bSavesDisplayed=false; + m_iSaveInfoC=0; + m_buttonListSaves.clearList(); + //StorageManager.ClearSavesInfo(); + //GetSaveInfo(); + m_iState=e_SavesIdle; + break; + } +} + +void UIScene_InGameSaveManagementMenu::GetSaveInfo( ) +{ + unsigned int uiSaveC=0; + + // This will return with the number retrieved in uiSaveC + + // clear the saves list + m_bSavesDisplayed = false; // we're blocking the exit from this scene until complete + m_buttonListSaves.clearList(); + m_iSaveInfoC=0; + m_controlSavesTimer.setVisible(true); + + m_pSaveDetails=StorageManager.ReturnSavesInfo(); + if(m_pSaveDetails==NULL) + { + C4JStorage::ESaveGameState eSGIStatus= StorageManager.GetSavesInfo(m_iPad,NULL,this,"save"); + } + + + return; +} + +void UIScene_InGameSaveManagementMenu::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled) +{ + if(m_bIgnoreInput) return; + + // if we're retrieving save info, ignore key presses + if(!m_bSavesDisplayed) return; + + ui.AnimateKeyPress(m_iPad, key, repeat, pressed, released); + + switch(key) + { + case ACTION_MENU_CANCEL: + if(pressed) + { +#if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__) + m_bExitScene=true; +#else + navigateBack(); +#endif + handled = true; + } + break; + case ACTION_MENU_OK: +#ifdef __ORBIS__ + case ACTION_MENU_TOUCHPAD_PRESS: +#endif + case ACTION_MENU_UP: + case ACTION_MENU_DOWN: + case ACTION_MENU_PAGEUP: + case ACTION_MENU_PAGEDOWN: + sendInputToMovie(key, repeat, pressed, released); + handled = true; + break; + } +} + +void UIScene_InGameSaveManagementMenu::handleInitFocus(F64 controlId, F64 childId) +{ + app.DebugPrintf(app.USER_SR, "UIScene_InGameSaveManagementMenu::handleInitFocus - %d , %d\n", (int)controlId, (int)childId); +} + +void UIScene_InGameSaveManagementMenu::handleFocusChange(F64 controlId, F64 childId) +{ + app.DebugPrintf(app.USER_SR, "UIScene_InGameSaveManagementMenu::handleFocusChange - %d , %d\n", (int)controlId, (int)childId); + m_iSaveListIndex = childId; + if(m_bSavesDisplayed) m_bUpdateSaveSize = true; + updateTooltips(); +} + +void UIScene_InGameSaveManagementMenu::handlePress(F64 controlId, F64 childId) +{ + switch((int)controlId) + { + case eControl_SavesList: + { + m_bIgnoreInput = true; + + // delete the save game + // Have to ask the player if they are sure they want to delete this game + UINT uiIDA[2]; + uiIDA[0]=IDS_CONFIRM_CANCEL; + uiIDA[1]=IDS_CONFIRM_OK; + ui.RequestMessageBox(IDS_TOOLTIPS_DELETESAVE, IDS_TEXT_DELETE_SAVE, uiIDA, 2,m_iPad,&UIScene_InGameSaveManagementMenu::DeleteSaveDialogReturned,this, app.GetStringTable(),NULL,0,true); + + ui.PlayUISFX(eSFX_Press); + break; + } + } +} + +int UIScene_InGameSaveManagementMenu::DeleteSaveDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result) +{ + UIScene_InGameSaveManagementMenu* pClass = (UIScene_InGameSaveManagementMenu*)pParam; + // results switched for this dialog + + if(result==C4JStorage::EMessage_ResultDecline) + { + if(app.DebugSettingsOn() && app.GetLoadSavesFromFolderEnabled()) + { + pClass->m_bIgnoreInput=false; + } + else + { + StorageManager.DeleteSaveData(&pClass->m_pSaveDetails->SaveInfoA[pClass->m_iSaveListIndex],UIScene_InGameSaveManagementMenu::DeleteSaveDataReturned,pClass); + pClass->m_controlSavesTimer.setVisible( true ); + } + } + else + { + pClass->m_bIgnoreInput=false; + } + + return 0; +} + +int UIScene_InGameSaveManagementMenu::DeleteSaveDataReturned(LPVOID lpParam,bool bRes) +{ + UIScene_InGameSaveManagementMenu* pClass = (UIScene_InGameSaveManagementMenu*)lpParam; + + if(bRes) + { + // wipe the list and repopulate it + pClass->m_iState=e_SavesRepopulateAfterDelete; + } + else pClass->m_bIgnoreInput=false; + + pClass->updateTooltips(); + + return 0; +} + +bool UIScene_InGameSaveManagementMenu::hasFocus(int iPad) +{ + return bHasFocus && (iPad == m_iPad || m_iPad == XUSER_INDEX_ANY); +}
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIScene_InGameSaveManagementMenu.h b/Minecraft.Client/Common/UI/UIScene_InGameSaveManagementMenu.h new file mode 100644 index 00000000..3f9ace3a --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_InGameSaveManagementMenu.h @@ -0,0 +1,104 @@ +#pragma once + +#include "UIScene.h" + +class UIScene_InGameSaveManagementMenu : public UIScene +{ +private: + enum EControls + { + eControl_SavesList, +#if defined(_XBOX_ONE) || defined(__ORBIS__) + eControl_SpaceIndicator, +#endif + }; + + enum EState + { + e_SavesIdle, + e_SavesRepopulate, + e_SavesRepopulateAfterDelete + }; + + static const int JOIN_LOAD_CREATE_BUTTON_INDEX = 0; + + SaveListDetails *m_saveDetails; + int m_iSaveDetailsCount; + +protected: + UIControl_SaveList m_buttonListSaves; + UIControl_Label m_labelSavesListTitle; + UIControl m_controlSavesTimer; +#if defined(_XBOX_ONE) || defined(__ORBIS__) + UIControl_SpaceIndicatorBar m_spaceIndicatorSaves; +#endif + +private: + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) + UI_MAP_ELEMENT( m_buttonListSaves, "SavesList") + + UI_MAP_ELEMENT( m_labelSavesListTitle, "SavesListTitle") + + UI_MAP_ELEMENT( m_controlSavesTimer, "SavesTimer") + +#if defined(_XBOX_ONE) || defined(__ORBIS__) + UI_MAP_ELEMENT( m_spaceIndicatorSaves, "SaveSizeBar") +#endif + UI_END_MAP_ELEMENTS_AND_NAMES() + + int m_iState; + + vector<File *> *m_saves; + + bool m_bIgnoreInput; + bool m_bAllLoaded; + bool m_bRetrievingSaveThumbnails; + bool m_bSaveThumbnailReady; + int m_iRequestingThumbnailId; + SAVE_DETAILS *m_pSaveDetails; + bool m_bSavesDisplayed; + bool m_bExitScene; + int m_iSaveInfoC; + int m_iSaveListIndex; + //int *m_iConfigA; // track the texture packs that we don't have installed + + bool m_bUpdateSaveSize; + +public: + UIScene_InGameSaveManagementMenu(int iPad, void *initData, UILayer *parentLayer); + virtual ~UIScene_InGameSaveManagementMenu(); + + virtual void updateTooltips(); + + virtual void handleReload(); + virtual void handleGainFocus(bool navBack); + // INPUT + virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled); + virtual void handleFocusChange(F64 controlId, F64 childId); + virtual void handleInitFocus(F64 controlId, F64 childId); + + virtual EUIScene getSceneType() { return eUIScene_LoadOrJoinMenu;} + + // Returns true if lower scenes in this scenes layer, or in any layer below this scenes layers should be hidden + virtual bool hidesLowerScenes() { return true; } + + virtual bool hasFocus(int iPad); + + virtual void tick(); + +private: + void Initialise(); + void GetSaveInfo(); + +protected: + // TODO: This should be pure virtual in this class + virtual wstring getMoviePath(); + +public: + + static int LoadSaveDataThumbnailReturned(LPVOID lpParam,PBYTE pbThumbnail,DWORD dwThumbnailBytes); + static int DeleteSaveDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result); + static int DeleteSaveDataReturned(LPVOID lpParam,bool bRes); +protected: + void handlePress(F64 controlId, F64 childId); +}; diff --git a/Minecraft.Client/Common/UI/UIScene_Intro.cpp b/Minecraft.Client/Common/UI/UIScene_Intro.cpp new file mode 100644 index 00000000..2c50612f --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_Intro.cpp @@ -0,0 +1,166 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIScene_Intro.h" + + +UIScene_Intro::UIScene_Intro(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) +{ + // Setup all the Iggy references we need for this scene + initialiseMovie(); + m_bIgnoreNavigate = false; + m_bAnimationEnded = false; + + bool bSkipESRB = false; +#if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__) + bSkipESRB = app.GetProductSKU() != e_sku_SCEA; +#elif defined(_XBOX) || defined(_DURANGO) + bSkipESRB = !ProfileManager.LocaleIsUSorCanada(); +#endif + + // 4J Stu - These map to values in the Actionscript +#ifdef _WINDOWS64 + int platformIdx = 0; +#elif defined(_XBOX) + int platformIdx = 1; +#elif defined(_DURANGO) + int platformIdx = 2; +#elif defined(__PS3__) + int platformIdx = 3; +#elif defined(__ORBIS__) + int platformIdx = 4; +#elif defined(__PSVITA__) + int platformIdx = 5; +#endif + + IggyDataValue result; + IggyDataValue value[2]; + value[0].type = IGGY_DATATYPE_number; + value[0].number = platformIdx; + + value[1].type = IGGY_DATATYPE_boolean; + value[1].boolval = bSkipESRB; + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcSetIntroPlatform , 2 , value ); + +#ifdef __PSVITA__ + // initialise vita touch controls with ids + m_TouchToSkip.init(0); +#endif +} + +wstring UIScene_Intro::getMoviePath() +{ + return L"Intro"; +} + +void UIScene_Intro::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled) +{ + ui.AnimateKeyPress(m_iPad, key, repeat, pressed, released); + + switch(key) + { + case ACTION_MENU_OK: +#ifdef __ORBIS__ + case ACTION_MENU_TOUCHPAD_PRESS: +#endif + if(!m_bIgnoreNavigate) + { + m_bIgnoreNavigate = true; + //ui.NavigateToHomeMenu(); +#if defined(__PS3__) || defined(__ORBIS__) || defined (__PSVITA__) + + // has the user seen the EULA already ? We need their options file loaded for this + C4JStorage::eOptionsCallback eStatus=app.GetOptionsCallbackStatus(0); + switch(eStatus) + { + case C4JStorage::eOptions_Callback_Read: + case C4JStorage::eOptions_Callback_Read_FileNotFound: + // we've either read it, or it wasn't found + if(app.GetGameSettings(0,eGameSetting_PS3_EULA_Read)==0) + { + ui.NavigateToScene(0,eUIScene_EULA); + } + else + { + ui.NavigateToScene(0,eUIScene_SaveMessage); + } + break; + default: + ui.NavigateToScene(0,eUIScene_EULA); + break; + } +#elif defined _XBOX_ONE + ui.NavigateToScene(0,eUIScene_MainMenu); +#else + ui.NavigateToScene(0,eUIScene_SaveMessage); +#endif + } + break; + } +} + +#ifdef __PSVITA__ +void UIScene_Intro::handleTouchInput(unsigned int iPad, S32 x, S32 y, int iId, bool bPressed, bool bRepeat, bool bReleased) +{ + if(bReleased) + { + bool handled = false; + handleInput(iPad, ACTION_MENU_OK, false, true, false, handled); + } +} +#endif + +void UIScene_Intro::handleAnimationEnd() +{ + if(!m_bIgnoreNavigate) + { + m_bIgnoreNavigate = true; + //ui.NavigateToHomeMenu(); +#if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__) + // has the user seen the EULA already ? We need their options file loaded for this + C4JStorage::eOptionsCallback eStatus=app.GetOptionsCallbackStatus(0); + switch(eStatus) + { + case C4JStorage::eOptions_Callback_Read: + case C4JStorage::eOptions_Callback_Read_FileNotFound: + // we've either read it, or it wasn't found + if(app.GetGameSettings(0,eGameSetting_PS3_EULA_Read)==0) + { + ui.NavigateToScene(0,eUIScene_EULA); + } + else + { + ui.NavigateToScene(0,eUIScene_SaveMessage); + } + break; + default: + ui.NavigateToScene(0,eUIScene_EULA); + break; + } + + +#elif defined _XBOX_ONE + // Don't navigate to the main menu if we don't have focus, as we could have the quadrant sign-in or a join game timer screen running, and then when Those finish they'll + // give the main menu focus which clears the signed in players and therefore breaks transitioning into the game + if( hasFocus( m_iPad ) ) + { + ui.NavigateToScene(0,eUIScene_MainMenu); + } + else + { + m_bAnimationEnded = true; + } +#else + ui.NavigateToScene(0,eUIScene_SaveMessage); +#endif + } +} + +void UIScene_Intro::handleGainFocus(bool navBack) +{ + // Only relevant on xbox one - if we didn't navigate to the main menu at animation end due to the timer or quadrant sign-in being up, then we'll need to + // do it now in case the user has cancelled or joining a game failed + if( m_bAnimationEnded ) + { + ui.NavigateToScene(0,eUIScene_MainMenu); + } +} diff --git a/Minecraft.Client/Common/UI/UIScene_Intro.h b/Minecraft.Client/Common/UI/UIScene_Intro.h new file mode 100644 index 00000000..8bdc030e --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_Intro.h @@ -0,0 +1,52 @@ +#pragma once + +#include "UIScene.h" + +class UIScene_Intro : public UIScene +{ +private: + bool m_bIgnoreNavigate; + bool m_bAnimationEnded; + + IggyName m_funcSetIntroPlatform; +#ifdef __PSVITA__ + UIControl_Touch m_TouchToSkip; +#endif + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) +#ifdef __PSVITA__ + UI_MAP_ELEMENT( m_TouchToSkip, "TouchToSkip" ) +#endif + UI_MAP_NAME( m_funcSetIntroPlatform, L"SetIntroPlatform") + UI_END_MAP_ELEMENTS_AND_NAMES() + +public: + UIScene_Intro(int iPad, void *initData, UILayer *parentLayer); + + virtual EUIScene getSceneType() { return eUIScene_Intro;} + + // Returns true if this scene has focus for the pad passed in +#ifndef __PS3__ + virtual bool hasFocus(int iPad) { return bHasFocus; } +#endif + +protected: + + + virtual wstring getMoviePath(); + +#ifdef _DURANGO + virtual long long getDefaultGtcButtons() { return 0; } +#endif + +public: + // INPUT + virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled); + + virtual void handleAnimationEnd(); + virtual void handleGainFocus(bool navBack); + +#ifdef __PSVITA__ + virtual void handleTouchInput(unsigned int iPad, S32 x, S32 y, int iId, bool bPressed, bool bRepeat, bool bReleased); +#endif + +}; diff --git a/Minecraft.Client/Common/UI/UIScene_InventoryMenu.cpp b/Minecraft.Client/Common/UI/UIScene_InventoryMenu.cpp new file mode 100644 index 00000000..723937d0 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_InventoryMenu.cpp @@ -0,0 +1,334 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIScene_InventoryMenu.h" + +#include "..\..\..\Minecraft.World\net.minecraft.world.inventory.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.item.h" +#include "..\..\..\Minecraft.World\net.minecraft.stats.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.effect.h" +#include "..\..\MultiplayerLocalPlayer.h" +#include "..\..\Minecraft.h" +#include "..\..\Options.h" +#include "..\..\EntityRenderDispatcher.h" +#include "..\..\Lighting.h" +#include "..\Tutorial\Tutorial.h" +#include "..\Tutorial\TutorialMode.h" +#include "..\Tutorial\TutorialEnum.h" + +#define INVENTORY_UPDATE_EFFECTS_TIMER_ID (10) +#define INVENTORY_UPDATE_EFFECTS_TIMER_TIME (1000) // 1 second + +UIScene_InventoryMenu::UIScene_InventoryMenu(int iPad, void *_initData, UILayer *parentLayer) : UIScene_AbstractContainerMenu(iPad, parentLayer) +{ + // Setup all the Iggy references we need for this scene + initialiseMovie(); + + InventoryScreenInput *initData = (InventoryScreenInput *)_initData; + + Minecraft *pMinecraft = Minecraft::GetInstance(); + if( pMinecraft->localgameModes[initData->iPad] != NULL ) + { + TutorialMode *gameMode = (TutorialMode *)pMinecraft->localgameModes[initData->iPad]; + m_previousTutorialState = gameMode->getTutorial()->getCurrentState(); + gameMode->getTutorial()->changeTutorialState(e_Tutorial_State_Inventory_Menu, this); + } + + InventoryMenu *menu = (InventoryMenu *)initData->player->inventoryMenu; + + initData->player->awardStat(GenericStats::openInventory(),GenericStats::param_openInventory()); + + Initialize( initData->iPad, menu, false, InventoryMenu::INV_SLOT_START, eSectionInventoryUsing, eSectionInventoryMax, initData->bNavigateBack ); + + m_slotListArmor.addSlots(InventoryMenu::ARMOR_SLOT_START, InventoryMenu::ARMOR_SLOT_END - InventoryMenu::ARMOR_SLOT_START); + + if(initData) delete initData; + + for(unsigned int i = 0; i < MobEffect::NUM_EFFECTS; ++i) + { + m_bEffectTime[i] = 0; + } + + updateEffectsDisplay(); + addTimer(INVENTORY_UPDATE_EFFECTS_TIMER_ID,INVENTORY_UPDATE_EFFECTS_TIMER_TIME); +} + +wstring UIScene_InventoryMenu::getMoviePath() +{ + if(app.GetLocalPlayerCount() > 1) + { + return L"InventoryMenuSplit"; + } + else + { + return L"InventoryMenu"; + } +} + +void UIScene_InventoryMenu::handleReload() +{ + Initialize( m_iPad, m_menu, false, InventoryMenu::INV_SLOT_START, eSectionInventoryUsing, eSectionInventoryMax, m_bNavigateBack ); + + m_slotListArmor.addSlots(InventoryMenu::ARMOR_SLOT_START, InventoryMenu::ARMOR_SLOT_END - InventoryMenu::ARMOR_SLOT_START); + + for(unsigned int i = 0; i < MobEffect::NUM_EFFECTS; ++i) + { + m_bEffectTime[i] = 0; + } +} + +int UIScene_InventoryMenu::getSectionColumns(ESceneSection eSection) +{ + int cols = 0; + switch( eSection ) + { + case eSectionInventoryArmor: + cols = 1; + break; + case eSectionInventoryInventory: + cols = 9; + break; + case eSectionInventoryUsing: + cols = 9; + break; + default: + assert( false ); + break; + } + return cols; +} + +int UIScene_InventoryMenu::getSectionRows(ESceneSection eSection) +{ + int rows = 0; + switch( eSection ) + { + case eSectionInventoryArmor: + rows = 4; + break; + case eSectionInventoryInventory: + rows = 3; + break; + case eSectionInventoryUsing: + rows = 1; + break; + default: + assert( false ); + break; + } + return rows; +} + +void UIScene_InventoryMenu::GetPositionOfSection( ESceneSection eSection, UIVec2D* pPosition ) +{ + switch( eSection ) + { + case eSectionInventoryArmor: + pPosition->x = m_slotListArmor.getXPos(); + pPosition->y = m_slotListArmor.getYPos(); + break; + case eSectionInventoryInventory: + pPosition->x = m_slotListInventory.getXPos(); + pPosition->y = m_slotListInventory.getYPos(); + break; + case eSectionInventoryUsing: + pPosition->x = m_slotListHotbar.getXPos(); + pPosition->y = m_slotListHotbar.getYPos(); + break; + default: + assert( false ); + break; + } +} + +void UIScene_InventoryMenu::GetItemScreenData( ESceneSection eSection, int iItemIndex, UIVec2D* pPosition, UIVec2D* pSize ) +{ + UIVec2D sectionSize; + + switch( eSection ) + { + case eSectionInventoryArmor: + sectionSize.x = m_slotListArmor.getWidth(); + sectionSize.y = m_slotListArmor.getHeight(); + break; + case eSectionInventoryInventory: + sectionSize.x = m_slotListInventory.getWidth(); + sectionSize.y = m_slotListInventory.getHeight(); + break; + case eSectionInventoryUsing: + sectionSize.x = m_slotListHotbar.getWidth(); + sectionSize.y = m_slotListHotbar.getHeight(); + break; + default: + assert( false ); + break; + } + + int rows = getSectionRows(eSection); + int cols = getSectionColumns(eSection); + + pSize->x = sectionSize.x/cols; + pSize->y = sectionSize.y/rows; + + int itemCol = iItemIndex % cols; + int itemRow = iItemIndex/cols; + + pPosition->x = itemCol * pSize->x; + pPosition->y = itemRow * pSize->y; +} + +void UIScene_InventoryMenu::setSectionSelectedSlot(ESceneSection eSection, int x, int y) +{ + int cols = getSectionColumns(eSection); + + int index = (y * cols) + x; + + UIControl_SlotList *slotList = NULL; + switch( eSection ) + { + case eSectionInventoryArmor: + slotList = &m_slotListArmor; + break; + case eSectionInventoryInventory: + slotList = &m_slotListInventory; + break; + case eSectionInventoryUsing: + slotList = &m_slotListHotbar; + break; + } + + slotList->setHighlightSlot(index); +} + +UIControl *UIScene_InventoryMenu::getSection(ESceneSection eSection) +{ + UIControl *control = NULL; + switch( eSection ) + { + case eSectionInventoryArmor: + control = &m_slotListArmor; + break; + case eSectionInventoryInventory: + control = &m_slotListInventory; + break; + case eSectionInventoryUsing: + control = &m_slotListHotbar; + break; + } + return control; +} + +void UIScene_InventoryMenu::customDraw(IggyCustomDrawCallbackRegion *region) +{ + Minecraft *pMinecraft = Minecraft::GetInstance(); + if(pMinecraft->localplayers[m_iPad] == NULL || pMinecraft->localgameModes[m_iPad] == NULL) return; + + if(wcscmp((wchar_t *)region->name,L"player")==0) + { + // Setup GDraw, normal game render states and matrices + CustomDrawData *customDrawRegion = ui.setupCustomDraw(this,region); + delete customDrawRegion; + + m_playerPreview.render(region); + + // Finish GDraw and anything else that needs to be finalised + ui.endCustomDraw(region); + } + else + { + UIScene_AbstractContainerMenu::customDraw(region); + } +} + +void UIScene_InventoryMenu::handleTimerComplete(int id) +{ + if(id == INVENTORY_UPDATE_EFFECTS_TIMER_ID) + { + updateEffectsDisplay(); + } +} + +void UIScene_InventoryMenu::updateEffectsDisplay() +{ + // Update with the current effects + Minecraft *pMinecraft = Minecraft::GetInstance(); + shared_ptr<MultiplayerLocalPlayer> player = pMinecraft->localplayers[m_iPad]; + + if(player == NULL) return; + + vector<MobEffectInstance *> *activeEffects = player->getActiveEffects(); + + // 4J - TomK setup time update value array size to update the active effects + int iValue = 0; + IggyDataValue *UpdateValue = new IggyDataValue[activeEffects->size()*2]; + + for(AUTO_VAR(it, activeEffects->begin()); it != activeEffects->end(); ++it) + { + MobEffectInstance *effect = *it; + + if(effect->getDuration() >= m_bEffectTime[effect->getId()]) + { + wstring effectString = app.GetString( effect->getDescriptionId() );//I18n.get(effect.getDescriptionId()).trim(); + if (effect->getAmplifier() > 0) + { + wstring potencyString = L""; + switch(effect->getAmplifier()) + { + case 1: + potencyString = L" "; + potencyString += app.GetString( IDS_POTION_POTENCY_1 ); + break; + case 2: + potencyString = L" "; + potencyString += app.GetString( IDS_POTION_POTENCY_2 ); + break; + case 3: + potencyString = L" "; + potencyString += app.GetString( IDS_POTION_POTENCY_3 ); + break; + default: + potencyString = app.GetString( IDS_POTION_POTENCY_0 ); + break; + } + effectString += potencyString; + } + int icon = 0; + MobEffect *mobEffect = MobEffect::effects[effect->getId()]; + if (mobEffect->hasIcon()) + { + icon = mobEffect->getIcon(); + } + IggyDataValue result; + IggyDataValue value[3]; + value[0].type = IGGY_DATATYPE_number; + value[0].number = icon; + + IggyStringUTF16 stringVal; + stringVal.string = (IggyUTF16*)effectString.c_str(); + stringVal.length = effectString.length(); + value[1].type = IGGY_DATATYPE_string_UTF16; + value[1].string16 = stringVal; + + int seconds = effect->getDuration() / SharedConstants::TICKS_PER_SECOND; + value[2].type = IGGY_DATATYPE_number; + value[2].number = seconds; + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcAddEffect , 3 , value ); + } + + if(MobEffect::effects[effect->getId()]->hasIcon()) + { + // 4J - TomK set ids and remaining duration so we can update the timers accurately in one call! (this prevents performance related timer sync issues, especially on PSVita) + UpdateValue[iValue].type = IGGY_DATATYPE_number; + UpdateValue[iValue].number = MobEffect::effects[effect->getId()]->getIcon(); + UpdateValue[iValue + 1].type = IGGY_DATATYPE_number; + UpdateValue[iValue + 1].number = (int)(effect->getDuration() / SharedConstants::TICKS_PER_SECOND); + iValue+=2; + } + + m_bEffectTime[effect->getId()] = effect->getDuration(); + } + + IggyDataValue result; + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcUpdateEffects , activeEffects->size()*2 , UpdateValue ); + + delete activeEffects; +} diff --git a/Minecraft.Client/Common/UI/UIScene_InventoryMenu.h b/Minecraft.Client/Common/UI/UIScene_InventoryMenu.h new file mode 100644 index 00000000..fb8d57a2 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_InventoryMenu.h @@ -0,0 +1,51 @@ +#pragma once + +#include "UIScene_AbstractContainerMenu.h" +#include "IUIScene_InventoryMenu.h" + +#include "..\..\..\Minecraft.World\MobEffect.h" + +class InventoryMenu; + +class UIScene_InventoryMenu : public UIScene_AbstractContainerMenu, public IUIScene_InventoryMenu +{ + friend class UIControl_MinecraftPlayer; +private: + int m_bEffectTime[MobEffect::NUM_EFFECTS]; +public: + UIScene_InventoryMenu(int iPad, void *initData, UILayer *parentLayer); + + virtual EUIScene getSceneType() { return eUIScene_InventoryMenu;} + +protected: + UIControl_SlotList m_slotListArmor; + UIControl_MinecraftPlayer m_playerPreview; + IggyName m_funcUpdateEffects, m_funcAddEffect; + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene_AbstractContainerMenu) + UI_BEGIN_MAP_CHILD_ELEMENTS( m_controlMainPanel ) + UI_MAP_ELEMENT( m_slotListArmor, "armorList") + UI_MAP_ELEMENT( m_playerPreview, "iggy_player") + + UI_MAP_NAME( m_funcUpdateEffects, L"UpdateEffects") + UI_MAP_NAME( m_funcAddEffect, L"AddEffect") + UI_END_MAP_CHILD_ELEMENTS() + UI_END_MAP_ELEMENTS_AND_NAMES() + + virtual wstring getMoviePath(); + virtual void handleReload(); + + virtual int getSectionColumns(ESceneSection eSection); + virtual int getSectionRows(ESceneSection eSection); + virtual void GetPositionOfSection( ESceneSection eSection, UIVec2D* pPosition ); + virtual void GetItemScreenData( ESceneSection eSection, int iItemIndex, UIVec2D* pPosition, UIVec2D* pSize ); + virtual void handleSectionClick(ESceneSection eSection) {} + virtual void setSectionSelectedSlot(ESceneSection eSection, int x, int y); + + virtual UIControl *getSection(ESceneSection eSection); + + virtual void customDraw(IggyCustomDrawCallbackRegion *region); + virtual void handleTimerComplete(int id); + +private: + void updateEffectsDisplay(); +};
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIScene_JoinMenu.cpp b/Minecraft.Client/Common/UI/UIScene_JoinMenu.cpp new file mode 100644 index 00000000..cad86dce --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_JoinMenu.cpp @@ -0,0 +1,586 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIScene_JoinMenu.h" +#include "..\..\Minecraft.h" +#include "..\..\TexturePackRepository.h" +#include "..\..\Options.h" +#include "..\..\MinecraftServer.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.level.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.h" + +#define UPDATE_PLAYERS_TIMER_ID 0 +#define UPDATE_PLAYERS_TIMER_TIME 30000 + +UIScene_JoinMenu::UIScene_JoinMenu(int iPad, void *_initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) +{ + // Setup all the Iggy references we need for this scene + initialiseMovie(); + + JoinMenuInitData *initData = (JoinMenuInitData *)_initData; + m_selectedSession = initData->selectedSession; + m_friendInfoUpdatedOK = false; + m_friendInfoUpdatedERROR = false; + m_friendInfoRequestIssued = false; +} + +void UIScene_JoinMenu::updateTooltips() +{ + int iA = -1; + int iY = -1; + if (getControlFocus() == eControl_GamePlayers) + { +#ifdef _DURANGO + iY = IDS_TOOLTIPS_VIEW_GAMERCARD; +#endif + } + else + { + iA = IDS_TOOLTIPS_SELECT; + } + + ui.SetTooltips( DEFAULT_XUI_MENU_USER, iA, IDS_TOOLTIPS_BACK, -1, iY ); + +} + +void UIScene_JoinMenu::tick() +{ + if( !m_friendInfoRequestIssued ) + { + ui.NavigateToScene(m_iPad, eUIScene_Timer); + g_NetworkManager.GetFullFriendSessionInfo(m_selectedSession, &friendSessionUpdated, this); + m_friendInfoRequestIssued = true; + } + + if( m_friendInfoUpdatedOK ) + { + m_friendInfoUpdatedOK = false; + + m_buttonJoinGame.init(app.GetString(IDS_JOIN_GAME),eControl_JoinGame); + + m_buttonListPlayers.init(eControl_GamePlayers); + +#if defined(__PS3__) || defined(__ORBIS__) || defined __PSVITA__ + for( int i = 0; i < MINECRAFT_NET_MAX_PLAYERS; i++ ) + { + if( m_selectedSession->data.players[i] != NULL ) + { + #ifndef _CONTENT_PACKAGE + if(app.DebugSettingsOn() && (app.GetGameSettingsDebugMask()&(1L<<eDebugSetting_DebugLeaderboards))) + { + m_buttonListPlayers.addItem(L"WWWWWWWWWWWWWWWW"); + } + else + #endif + { + string playerName(m_selectedSession->data.players[i].getOnlineID()); + + #ifndef __PSVITA__ + // Append guest number (any players in an online game not signed into PSN are guests) + if( m_selectedSession->data.players[i].isSignedIntoPSN() == false ) + { + char suffix[5]; + sprintf(suffix, " (%d)", m_selectedSession->data.players[i].getQuadrant() + 1); + playerName.append(suffix); + } + #endif + m_buttonListPlayers.addItem(playerName); + } + } + else + { + // Leave the loop when we hit the first NULL player + break; + } + } +#elif defined(_DURANGO) + for( int i = 0; i < MINECRAFT_NET_MAX_PLAYERS; i++ ) + { + if ( m_selectedSession->searchResult.m_playerNames[i].size() ) + { + m_buttonListPlayers.addItem(m_selectedSession->searchResult.m_playerNames[i]); + } + else + { + // Leave the loop when we hit the first empty player name + break; + } + } +#endif + + m_labelLabels[eLabel_Difficulty].init(app.GetString(IDS_LABEL_DIFFICULTY)); + m_labelLabels[eLabel_GameType].init(app.GetString(IDS_LABEL_GAME_TYPE)); + m_labelLabels[eLabel_GamertagsOn].init(app.GetString(IDS_LABEL_GAMERTAGS)); + m_labelLabels[eLabel_Structures].init(app.GetString(IDS_LABEL_STRUCTURES)); + m_labelLabels[eLabel_LevelType].init(app.GetString(IDS_LABEL_LEVEL_TYPE)); + m_labelLabels[eLabel_PVP].init(app.GetString(IDS_LABEL_PvP)); + m_labelLabels[eLabel_Trust].init(app.GetString(IDS_LABEL_TRUST)); + m_labelLabels[eLabel_TNTOn].init(app.GetString(IDS_LABEL_TNT)); + m_labelLabels[eLabel_FireOn].init(app.GetString(IDS_LABEL_FIRE_SPREADS)); + + unsigned int uiGameHostSettings = m_selectedSession->data.m_uiGameHostSettings; + switch(app.GetGameHostOption(uiGameHostSettings,eGameHostOption_Difficulty)) + { + case Difficulty::EASY: + m_labelValues[eLabel_Difficulty].init( app.GetString(IDS_DIFFICULTY_TITLE_EASY) ); + break; + case Difficulty::NORMAL: + m_labelValues[eLabel_Difficulty].init( app.GetString(IDS_DIFFICULTY_TITLE_NORMAL) ); + break; + case Difficulty::HARD: + m_labelValues[eLabel_Difficulty].init( app.GetString(IDS_DIFFICULTY_TITLE_HARD) ); + break; + case Difficulty::PEACEFUL: + default: + m_labelValues[eLabel_Difficulty].init( app.GetString(IDS_DIFFICULTY_TITLE_PEACEFUL) ); + break; + } + + int option = app.GetGameHostOption(uiGameHostSettings,eGameHostOption_GameType); + if(option == GameType::CREATIVE->getId()) + { + m_labelValues[eLabel_GameType].init( app.GetString(IDS_CREATIVE) ); + } + else + { + m_labelValues[eLabel_GameType].init( app.GetString(IDS_SURVIVAL) ); + } + + if(app.GetGameHostOption(uiGameHostSettings,eGameHostOption_Gamertags)) m_labelValues[eLabel_GamertagsOn].init( app.GetString(IDS_ON) ); + else m_labelValues[eLabel_GamertagsOn].init( app.GetString(IDS_OFF) ); + + if(app.GetGameHostOption(uiGameHostSettings,eGameHostOption_Structures)) m_labelValues[eLabel_Structures].init( app.GetString(IDS_ON) ); + else m_labelValues[eLabel_Structures].init( app.GetString(IDS_OFF) ); + + if(app.GetGameHostOption(uiGameHostSettings,eGameHostOption_LevelType)) m_labelValues[eLabel_LevelType].init( app.GetString(IDS_LEVELTYPE_SUPERFLAT) ); + else m_labelValues[eLabel_LevelType].init( app.GetString(IDS_LEVELTYPE_NORMAL) ); + + if(app.GetGameHostOption(uiGameHostSettings,eGameHostOption_PvP))m_labelValues[eLabel_PVP].init( app.GetString(IDS_ON) ); + else m_labelValues[eLabel_PVP].init( app.GetString(IDS_OFF) ); + + if(app.GetGameHostOption(uiGameHostSettings,eGameHostOption_TrustPlayers)) m_labelValues[eLabel_Trust].init( app.GetString(IDS_ON) ); + else m_labelValues[eLabel_Trust].init( app.GetString(IDS_OFF) ); + + if(app.GetGameHostOption(uiGameHostSettings,eGameHostOption_TNT)) m_labelValues[eLabel_TNTOn].init( app.GetString(IDS_ON) ); + else m_labelValues[eLabel_TNTOn].init( app.GetString(IDS_OFF) ); + + if(app.GetGameHostOption(uiGameHostSettings,eGameHostOption_FireSpreads)) m_labelValues[eLabel_FireOn].init( app.GetString(IDS_ON) ); + else m_labelValues[eLabel_FireOn].init( app.GetString(IDS_OFF) ); + + m_bIgnoreInput = false; + + // Alert the app the we want to be informed of ethernet connections + app.SetLiveLinkRequired( true ); + + TelemetryManager->RecordMenuShown(m_iPad, eUIScene_JoinMenu, 0); + + addTimer(UPDATE_PLAYERS_TIMER_ID,UPDATE_PLAYERS_TIMER_TIME); + } + + if( m_friendInfoUpdatedERROR ) + { + m_buttonJoinGame.init(app.GetString(IDS_JOIN_GAME),eControl_JoinGame); + + m_buttonListPlayers.init(eControl_GamePlayers); + + m_labelLabels[eLabel_Difficulty].init(app.GetString(IDS_LABEL_DIFFICULTY)); + m_labelLabels[eLabel_GameType].init(app.GetString(IDS_LABEL_GAME_TYPE)); + m_labelLabels[eLabel_GamertagsOn].init(app.GetString(IDS_LABEL_GAMERTAGS)); + m_labelLabels[eLabel_Structures].init(app.GetString(IDS_LABEL_STRUCTURES)); + m_labelLabels[eLabel_LevelType].init(app.GetString(IDS_LABEL_LEVEL_TYPE)); + m_labelLabels[eLabel_PVP].init(app.GetString(IDS_LABEL_PvP)); + m_labelLabels[eLabel_Trust].init(app.GetString(IDS_LABEL_TRUST)); + m_labelLabels[eLabel_TNTOn].init(app.GetString(IDS_LABEL_TNT)); + m_labelLabels[eLabel_FireOn].init(app.GetString(IDS_LABEL_FIRE_SPREADS)); + + m_labelValues[eLabel_Difficulty].init(app.GetString(IDS_DIFFICULTY_TITLE_PEACEFUL)); + m_labelValues[eLabel_GameType].init( app.GetString(IDS_CREATIVE) ); + m_labelValues[eLabel_GamertagsOn].init( app.GetString(IDS_OFF) ); + m_labelValues[eLabel_Structures].init( app.GetString(IDS_OFF) ); + m_labelValues[eLabel_LevelType].init( app.GetString(IDS_LEVELTYPE_NORMAL) ); + m_labelValues[eLabel_PVP].init( app.GetString(IDS_OFF) ); + m_labelValues[eLabel_Trust].init( app.GetString(IDS_OFF) ); + m_labelValues[eLabel_TNTOn].init( app.GetString(IDS_OFF) ); + m_labelValues[eLabel_FireOn].init( app.GetString(IDS_OFF) ); + + m_friendInfoUpdatedERROR = false; + + // Show a generic network error message, not always safe to assume the error was host quitting + // without bubbling more info up from the network manager so this is the best we can do + UINT uiIDA[1]; + uiIDA[0] = IDS_CONFIRM_OK; +#ifdef _XBOX_ONE + ui.RequestMessageBox( IDS_CONNECTION_FAILED, IDS_DISCONNECTED_SERVER_QUIT, uiIDA,1,m_iPad,ErrorDialogReturned,this, app.GetStringTable()); +#else + ui.RequestMessageBox( IDS_ERROR_NETWORK_TITLE, IDS_ERROR_NETWORK, uiIDA,1,m_iPad,ErrorDialogReturned,this, app.GetStringTable()); +#endif + } + + UIScene::tick(); +} + +void UIScene_JoinMenu::friendSessionUpdated(bool success, void *pParam) +{ + UIScene_JoinMenu *scene = (UIScene_JoinMenu *)pParam; + ui.NavigateBack(scene->m_iPad); + if( success ) + { + scene->m_friendInfoUpdatedOK = true; + } + else + { + scene->m_friendInfoUpdatedERROR = true; + } +} + +int UIScene_JoinMenu::ErrorDialogReturned(void *pParam, int iPad, const C4JStorage::EMessageResult) +{ + UIScene_JoinMenu *scene = (UIScene_JoinMenu *)pParam; + ui.NavigateBack(scene->m_iPad); + + return 0; +} + +void UIScene_JoinMenu::updateComponents() +{ + m_parentLayer->showComponent(m_iPad,eUIComponent_Panorama,true); + m_parentLayer->showComponent(m_iPad,eUIComponent_Logo,true); +} + +wstring UIScene_JoinMenu::getMoviePath() +{ + return L"JoinMenu"; +} + +void UIScene_JoinMenu::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled) +{ + if(m_bIgnoreInput) return; + + ui.AnimateKeyPress(m_iPad, key, repeat, pressed, released); + + switch(key) + { + case ACTION_MENU_CANCEL: + if(pressed) + { + navigateBack(); + handled = true; + } + break; +#ifdef _DURANGO + case ACTION_MENU_Y: + if(m_selectedSession != NULL && getControlFocus() == eControl_GamePlayers && m_buttonListPlayers.getItemCount() > 0) + { + PlayerUID uid = m_selectedSession->searchResult.m_playerXuids[m_buttonListPlayers.getCurrentSelection()]; + if( uid != INVALID_XUID ) ProfileManager.ShowProfileCard(ProfileManager.GetLockedProfile(),uid); + } + break; +#endif + case ACTION_MENU_OK: + if (getControlFocus() != eControl_GamePlayers) + { + sendInputToMovie(key, repeat, pressed, released); + } + handled = true; + break; +#ifdef __ORBIS__ + case ACTION_MENU_TOUCHPAD_PRESS: +#endif + case ACTION_MENU_UP: + case ACTION_MENU_DOWN: + case ACTION_MENU_PAGEUP: + case ACTION_MENU_PAGEDOWN: + sendInputToMovie(key, repeat, pressed, released); + handled = true; + break; + } +} + +void UIScene_JoinMenu::handlePress(F64 controlId, F64 childId) +{ + switch((int)controlId) + { + case eControl_JoinGame: + { + m_bIgnoreInput = true; + + //CD - Added for audio + ui.PlayUISFX(eSFX_Press); + +#ifdef _DURANGO + ProfileManager.CheckMultiplayerPrivileges(m_iPad, true, &checkPrivilegeCallback, this); +#else + StartSharedLaunchFlow(); +#endif + } + break; + case eControl_GamePlayers: + break; + }; +} + +void UIScene_JoinMenu::handleFocusChange(F64 controlId, F64 childId) +{ + switch((int)controlId) + { + case eControl_GamePlayers: + m_buttonListPlayers.updateChildFocus( (int) childId ); + }; + updateTooltips(); +} + +#ifdef _DURANGO +void UIScene_JoinMenu::checkPrivilegeCallback(LPVOID lpParam, bool hasPrivilege, int iPad) +{ + UIScene_JoinMenu* pClass = (UIScene_JoinMenu*)lpParam; + + if(hasPrivilege) + { + pClass->StartSharedLaunchFlow(); +} + else + { + pClass->m_bIgnoreInput = false; + } +} +#endif + +void UIScene_JoinMenu::StartSharedLaunchFlow() +{ + if(!app.IsLocalMultiplayerAvailable()) + { + JoinGame(this); + } + else + { + //ProfileManager.RequestSignInUI(false, false, false, true, false,&UIScene_JoinMenu::StartGame_SignInReturned, this,ProfileManager.GetPrimaryPad()); + SignInInfo info; + info.Func = &UIScene_JoinMenu::StartGame_SignInReturned; + info.lpParam = this; + info.requireOnline = true; + ui.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_QuadrantSignin,&info); + } +} + +int UIScene_JoinMenu::StartGame_SignInReturned(void *pParam,bool bContinue, int iPad) +{ + UIScene_JoinMenu* pClass = (UIScene_JoinMenu*)pParam; + + if(bContinue==true) + { + // It's possible that the player has not signed in - they can back out + if(ProfileManager.IsSignedIn(iPad)) + { + JoinGame(pClass); + } + else + { + pClass->m_bIgnoreInput=false; + } + } + else + { + pClass->m_bIgnoreInput=false; + } + return 0; +} + +// Shared function to join the game that is the same whether we used the sign-in UI or not +void UIScene_JoinMenu::JoinGame(UIScene_JoinMenu* pClass) +{ + DWORD dwSignedInUsers = 0; + bool noPrivileges = false; + DWORD dwLocalUsersMask = 0; + bool isSignedInLive = true; + int iPadNotSignedInLive = -1; + + ProfileManager.SetLockedProfile(0); // TEMP! + + // If we're in SD mode, then only the primary player gets to play + if (app.IsLocalMultiplayerAvailable()) + { + for(unsigned int index = 0; index < XUSER_MAX_COUNT; ++index) + { + if(ProfileManager.IsSignedIn(index)) + { + if (isSignedInLive && !ProfileManager.IsSignedInLive(index)) + { + // Record the first non signed in live pad + iPadNotSignedInLive = index; + } + + if( !ProfileManager.AllowedToPlayMultiplayer(index) ) noPrivileges = true; + dwLocalUsersMask |= CGameNetworkManager::GetLocalPlayerMask(index); + isSignedInLive = isSignedInLive && ProfileManager.IsSignedInLive(index); + } + } + } + else + { + if(ProfileManager.IsSignedIn(ProfileManager.GetPrimaryPad())) + { + if( !ProfileManager.AllowedToPlayMultiplayer(ProfileManager.GetPrimaryPad()) ) noPrivileges = true; + dwLocalUsersMask |= CGameNetworkManager::GetLocalPlayerMask(ProfileManager.GetPrimaryPad()); + + isSignedInLive = ProfileManager.IsSignedInLive(ProfileManager.GetPrimaryPad()); +#ifdef __PSVITA__ + if(CGameNetworkManager::usingAdhocMode() && SQRNetworkManager_AdHoc_Vita::GetAdhocStatus()) + isSignedInLive = true; +#endif + + } + } + + // If this is an online game but not all players are signed in to Live, stop! + if (!isSignedInLive) + { +#ifdef __ORBIS__ + // Check if PSN is unavailable because of age restriction + int npAvailability = ProfileManager.getNPAvailability(iPadNotSignedInLive); + if (npAvailability == SCE_NP_ERROR_AGE_RESTRICTION) + { + pClass->m_bIgnoreInput = false; + // 4J Stu - This is a bit messy and is due to the library incorrectly returning false for IsSignedInLive if the npAvailability isn't SCE_OK + UINT uiIDA[1]; + uiIDA[0]=IDS_OK; + ui.RequestMessageBox(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, iPadNotSignedInLive, NULL, NULL, app.GetStringTable()); + } + else +#endif + { + pClass->m_bIgnoreInput=false; + UINT uiIDA[1]; + uiIDA[0]=IDS_CONFIRM_OK; + ui.RequestMessageBox( IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA,1,ProfileManager.GetPrimaryPad(),NULL,NULL, app.GetStringTable()); + } + return; + } + + // Check if user-created content is allowed, as we cannot play multiplayer if it's not + bool noUGC = false; + BOOL pccAllowed = TRUE; + BOOL pccFriendsAllowed = TRUE; + +#if defined(__PS3__) || defined(__PSVITA__) + if(isSignedInLive) + { + ProfileManager.GetChatAndContentRestrictions(ProfileManager.GetPrimaryPad(),false,&noUGC,NULL,NULL); + } +#else + ProfileManager.AllowedPlayerCreatedContent(ProfileManager.GetPrimaryPad(),false,&pccAllowed,&pccFriendsAllowed); + if(!pccAllowed && !pccFriendsAllowed) noUGC = true; +#endif + + +#ifdef __PSVITA__ + if( CGameNetworkManager::usingAdhocMode() ) + { + noPrivileges = false; + noUGC = false; + } +#endif + + if(noUGC) + { + pClass->setVisible( true ); + pClass->m_bIgnoreInput=false; + + int messageText = IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_SINGLE_LOCAL; + if(dwSignedInUsers > 1) messageText = IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_ALL_LOCAL; + + ui.RequestUGCMessageBox(IDS_CONNECTION_FAILED, messageText); + } + else if(noPrivileges) + { + pClass->setVisible( true ); + pClass->m_bIgnoreInput=false; + UINT uiIDA[1]; + uiIDA[0]=IDS_CONFIRM_OK; + ui.RequestMessageBox( IDS_NO_MULTIPLAYER_PRIVILEGE_TITLE, IDS_NO_MULTIPLAYER_PRIVILEGE_JOIN_TEXT, uiIDA,1,ProfileManager.GetPrimaryPad(),NULL,NULL, app.GetStringTable()); + } + else + { +#if defined(__ORBIS__) || defined(__PSVITA__) + bool chatRestricted = false; + ProfileManager.GetChatAndContentRestrictions(ProfileManager.GetPrimaryPad(),false,&chatRestricted,NULL,NULL); + if(chatRestricted) + { + ProfileManager.DisplaySystemMessage( SCE_MSG_DIALOG_SYSMSG_TYPE_TRC_PSN_CHAT_RESTRICTION, ProfileManager.GetPrimaryPad() ); + } +#endif + CGameNetworkManager::eJoinGameResult result = g_NetworkManager.JoinGame( pClass->m_selectedSession, dwLocalUsersMask ); + + // Alert the app the we no longer want to be informed of ethernet connections + app.SetLiveLinkRequired( false ); + + if( result != CGameNetworkManager::JOINGAME_SUCCESS ) + { + int exitReasonStringId = -1; + switch(result) + { + case CGameNetworkManager::JOINGAME_FAIL_SERVER_FULL: + exitReasonStringId = IDS_DISCONNECTED_SERVER_FULL; + break; + } + + if( exitReasonStringId == -1 ) + { + ui.NavigateBack(pClass->m_iPad); + } + else + { + UINT uiIDA[1]; + uiIDA[0]=IDS_CONFIRM_OK; + ui.RequestMessageBox( IDS_CONNECTION_FAILED, exitReasonStringId, uiIDA,1,ProfileManager.GetPrimaryPad(),NULL,NULL, app.GetStringTable()); + exitReasonStringId = -1; + + ui.NavigateToHomeMenu(); + } + } + } +} + +void UIScene_JoinMenu::handleTimerComplete(int id) +{ + switch(id) + { + case UPDATE_PLAYERS_TIMER_ID: + { +#if TO_BE_IMPLEMENTED + PlayerUID selectedPlayerXUID = m_selectedSession->data.players[playersList.GetCurSel()]; + + bool success = g_NetworkManager.GetGameSessionInfo(m_iPad, m_selectedSession->sessionId,m_selectedSession); + + if( success ) + { + playersList.DeleteItems(0, playersList.GetItemCount()); + int selectedIndex = 0; + for(unsigned int i = 0; i < MINECRAFT_NET_MAX_PLAYERS; ++i) + { + if( m_selectedSession->data.players[i] != NULL ) + { + if(m_selectedSession->data.players[i] == selectedPlayerXUID) selectedIndex = i; + playersList.InsertItems(i,1); +#ifndef _CONTENT_PACKAGE + if(app.DebugSettingsOn() && (app.GetGameSettingsDebugMask()&(1L<<eDebugSetting_DebugLeaderboards))) + { + playersList.SetText(i, L"WWWWWWWWWWWWWWWW" ); + } + else +#endif + { + playersList.SetText(i, convStringToWstring( m_selectedSession->data.szPlayers[i] ).c_str() ); + } + } + else + { + // Leave the loop when we hit the first NULL player + break; + } + } + playersList.SetCurSel(selectedIndex); + } +#endif + } + break; + }; +}
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIScene_JoinMenu.h b/Minecraft.Client/Common/UI/UIScene_JoinMenu.h new file mode 100644 index 00000000..817360ef --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_JoinMenu.h @@ -0,0 +1,98 @@ +#pragma once + +#include "UIScene.h" + +class UIScene_JoinMenu : public UIScene +{ +private: + enum EControls + { + eControl_JoinGame, + eControl_GamePlayers + }; + + enum ELabels + { + eLabel_Difficulty, + eLabel_GameType, + eLabel_GamertagsOn, + eLabel_Structures, + eLabel_LevelType, + eLabel_PVP, + eLabel_Trust, + eLabel_TNTOn, + eLabel_FireOn, + + eLabel_COUNT + }; + + UIControl_Button m_buttonJoinGame; + UIControl_ButtonList m_buttonListPlayers; + + UIControl_Label m_labelLabels[eLabel_COUNT]; + UIControl_Label m_labelValues[eLabel_COUNT]; + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) + UI_MAP_ELEMENT( m_buttonJoinGame, "JoinGame") + UI_MAP_ELEMENT( m_buttonListPlayers, "GamePlayers") + + UI_MAP_ELEMENT( m_labelLabels[0], "Label0") + UI_MAP_ELEMENT( m_labelLabels[1], "Label1") + UI_MAP_ELEMENT( m_labelLabels[2], "Label2") + UI_MAP_ELEMENT( m_labelLabels[3], "Label3") + UI_MAP_ELEMENT( m_labelLabels[4], "Label4") + UI_MAP_ELEMENT( m_labelLabels[5], "Label5") + UI_MAP_ELEMENT( m_labelLabels[6], "Label6") + UI_MAP_ELEMENT( m_labelLabels[7], "Label7") + UI_MAP_ELEMENT( m_labelLabels[8], "Label8") + + UI_MAP_ELEMENT( m_labelValues[0], "Value0") + UI_MAP_ELEMENT( m_labelValues[1], "Value1") + UI_MAP_ELEMENT( m_labelValues[2], "Value2") + UI_MAP_ELEMENT( m_labelValues[3], "Value3") + UI_MAP_ELEMENT( m_labelValues[4], "Value4") + UI_MAP_ELEMENT( m_labelValues[5], "Value5") + UI_MAP_ELEMENT( m_labelValues[6], "Value6") + UI_MAP_ELEMENT( m_labelValues[7], "Value7") + UI_MAP_ELEMENT( m_labelValues[8], "Value8") + UI_END_MAP_ELEMENTS_AND_NAMES() + + FriendSessionInfo *m_selectedSession; + bool m_bIgnoreInput; + bool m_friendInfoRequestIssued; + bool m_friendInfoUpdatedOK; + bool m_friendInfoUpdatedERROR; + +public: + UIScene_JoinMenu(int iPad, void *initData, UILayer *parentLayer); + void tick(); + static void friendSessionUpdated(bool success, void *pParam); + static int ErrorDialogReturned(void *pParam, int iPad, const C4JStorage::EMessageResult); + + virtual void updateTooltips(); + virtual void updateComponents(); + + virtual EUIScene getSceneType() { return eUIScene_LoadMenu;} + +protected: + // TODO: This should be pure virtual in this class + virtual wstring getMoviePath(); + +public: + // INPUT + virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled); + virtual void handleFocusChange(F64 controlId, F64 childId); + virtual void handleTimerComplete(int id); + +protected: + void handlePress(F64 controlId, F64 childId); + + + void StartSharedLaunchFlow(); + +#ifdef _DURANGO + static void checkPrivilegeCallback(LPVOID lpParam, bool hasPrivilege, int iPad); +#endif + + static int StartGame_SignInReturned(void *pParam, bool, int); + static void JoinGame(UIScene_JoinMenu* pClass); +}; diff --git a/Minecraft.Client/Common/UI/UIScene_Keyboard.cpp b/Minecraft.Client/Common/UI/UIScene_Keyboard.cpp new file mode 100644 index 00000000..fb1cc301 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_Keyboard.cpp @@ -0,0 +1,181 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIScene_Keyboard.h" + +#define KEYBOARD_DONE_TIMER_ID 0 +#define KEYBOARD_DONE_TIMER_TIME 100 + +UIScene_Keyboard::UIScene_Keyboard(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) +{ + // Setup all the Iggy references we need for this scene + initialiseMovie(); + + m_EnterTextLabel.init(L"Enter Sign Text"); + + m_KeyboardTextInput.init(L"", -1); + m_KeyboardTextInput.SetCharLimit(15); + + m_ButtonSpace.init(L"Space", -1); + m_ButtonCursorLeft.init(L"Cursor Left", -1); + m_ButtonCursorRight.init(L"Cursor Right", -1); + m_ButtonCaps.init(L"Caps", -1); + m_ButtonDone.init(L"Done", 0); // only the done button needs an id, the others will never call back! + m_ButtonSymbols.init(L"Symbols", -1); + m_ButtonBackspace.init(L"Backspace", -1); + + // Initialise function keyboard Buttons and set alternative symbol button string + wstring label = L"Abc"; + IggyStringUTF16 stringVal; + stringVal.string = (IggyUTF16*)label.c_str(); + stringVal.length = label.length(); + + IggyDataValue result; + IggyDataValue value[1]; + value[0].type = IGGY_DATATYPE_string_UTF16; + value[0].string16 = stringVal; + + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcInitFunctionButtons , 1 , value ); + + m_bKeyboardDonePressed = false; + + parentLayer->addComponent(iPad,eUIComponent_MenuBackground); +} + +UIScene_Keyboard::~UIScene_Keyboard() +{ + m_parentLayer->removeComponent(eUIComponent_MenuBackground); +} + +wstring UIScene_Keyboard::getMoviePath() +{ + if(app.GetLocalPlayerCount() > 1 && !m_parentLayer->IsFullscreenGroup()) + { + return L"KeyboardSplit"; + } + else + { + return L"Keyboard"; + } +} + +void UIScene_Keyboard::updateTooltips() +{ + ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK, -1, -1); +} + +bool UIScene_Keyboard::allowRepeat(int key) +{ + // 4J - TomK - we want to allow X and Y repeats! + switch(key) + { + case ACTION_MENU_OK: + case ACTION_MENU_CANCEL: + case ACTION_MENU_A: + case ACTION_MENU_B: + case ACTION_MENU_PAUSEMENU: + //case ACTION_MENU_X: + //case ACTION_MENU_Y: + return false; + } + return true; +} + +void UIScene_Keyboard::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled) +{ + IggyDataValue result; + IggyResult out; + + if(repeat || pressed) + { + switch(key) + { + case ACTION_MENU_CANCEL: + navigateBack(); + handled = true; + break; + case ACTION_MENU_X: // X + out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcBackspaceButtonPressed, 0 , NULL ); + handled = true; + break; + case ACTION_MENU_PAGEUP: // LT + out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcSymbolButtonPressed, 0 , NULL ); + handled = true; + break; + case ACTION_MENU_Y: // Y + out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcSpaceButtonPressed, 0 , NULL ); + handled = true; + break; + case ACTION_MENU_STICK_PRESS: // LS + out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcCapsButtonPressed, 0 , NULL ); + handled = true; + break; + case ACTION_MENU_LEFT_SCROLL: // LB + out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcCursorLeftButtonPressed, 0 , NULL ); + handled = true; + break; + case ACTION_MENU_RIGHT_SCROLL: // RB + out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcCursorRightButtonPressed, 0 , NULL ); + handled = true; + break; + case ACTION_MENU_PAUSEMENU: // Start + if(!m_bKeyboardDonePressed) + { + out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcDoneButtonPressed, 0 , NULL ); + + // kick off done timer + addTimer(KEYBOARD_DONE_TIMER_ID,KEYBOARD_DONE_TIMER_TIME); + m_bKeyboardDonePressed = true; + } + handled = true; + break; + } + } + + switch(key) + { + case ACTION_MENU_OK: + case ACTION_MENU_LEFT: + case ACTION_MENU_RIGHT: + case ACTION_MENU_UP: + case ACTION_MENU_DOWN: + sendInputToMovie(key, repeat, pressed, released); + handled = true; + break; + } +} + +void UIScene_Keyboard::handlePress(F64 controlId, F64 childId) +{ + if((int)controlId == 0) + { + // Done has been pressed. At this point we can query for the input string and pass it on to wherever it is needed. + // we can not query for m_KeyboardTextInput.getLabel() here because we're in an iggy callback so we need to wait a frame. + if(!m_bKeyboardDonePressed) + { + // kick off done timer + addTimer(KEYBOARD_DONE_TIMER_ID,KEYBOARD_DONE_TIMER_TIME); + m_bKeyboardDonePressed = true; + } + } +} + +void UIScene_Keyboard::handleTimerComplete(int id) +{ + if(id == KEYBOARD_DONE_TIMER_ID) + { + // remove timer + killTimer(KEYBOARD_DONE_TIMER_ID); + + // we're done here! + KeyboardDonePressed(); + } +} + +void UIScene_Keyboard::KeyboardDonePressed() +{ + // Debug + app.DebugPrintf("UI Keyboard - DONE - [%ls]\n", m_KeyboardTextInput.getLabel()); + + // ToDo: Keyboard can now pass on its final string value and close itself down + navigateBack(); +}
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIScene_Keyboard.h b/Minecraft.Client/Common/UI/UIScene_Keyboard.h new file mode 100644 index 00000000..f4e4c899 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_Keyboard.h @@ -0,0 +1,79 @@ +#pragma once + +#include "UIScene.h" + +class UIScene_Keyboard : public UIScene +{ +private: + bool m_bKeyboardDonePressed; + +protected: + UIControl_Label m_EnterTextLabel; + UIControl_TextInput m_KeyboardTextInput; + UIControl_Button m_ButtonSpace, m_ButtonCursorLeft, m_ButtonCursorRight, m_ButtonCaps, m_ButtonDone, m_ButtonSymbols, m_ButtonBackspace; + + IggyName m_funcInitFunctionButtons; + IggyName m_funcCursorRightButtonPressed, m_funcCursorLeftButtonPressed, m_funcCapsButtonPressed, m_funcBackspaceButtonPressed; + IggyName m_funcSpaceButtonPressed, m_funcSymbolButtonPressed, m_funcDoneButtonPressed; + + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) + UI_MAP_ELEMENT(m_EnterTextLabel, "EnterTextLabel") + UI_MAP_ELEMENT(m_KeyboardTextInput, "KeyboardTextInput") + + UI_MAP_ELEMENT(m_ButtonSpace, "Button_space") + UI_MAP_ELEMENT(m_ButtonCursorLeft, "Button_CursorLeft") + UI_MAP_ELEMENT(m_ButtonCursorRight, "Button_CursorRight") + UI_MAP_ELEMENT(m_ButtonCaps, "Button_Caps") + UI_MAP_ELEMENT(m_ButtonDone, "Button_Done") + UI_MAP_ELEMENT(m_ButtonSymbols, "Button_symbols") + UI_MAP_ELEMENT(m_ButtonBackspace, "Button_bspace") + + UI_MAP_NAME(m_funcInitFunctionButtons, L"InitFunctionButtons"); + + UI_MAP_NAME(m_funcCursorRightButtonPressed, L"CursorRightButtonPressed"); + UI_MAP_NAME(m_funcCursorLeftButtonPressed, L"CursorLeftButtonPressed"); + UI_MAP_NAME(m_funcCapsButtonPressed, L"CapsButtonPressed"); + UI_MAP_NAME(m_funcBackspaceButtonPressed, L"BackspaceButtonPressed"); + UI_MAP_NAME(m_funcSpaceButtonPressed, L"SpaceButtonPressed"); + UI_MAP_NAME(m_funcSymbolButtonPressed, L"SymbolButtonPressed"); + UI_MAP_NAME(m_funcDoneButtonPressed, L"DoneButtonPressed"); + UI_END_MAP_ELEMENTS_AND_NAMES() + +public: + UIScene_Keyboard(int iPad, void *initData, UILayer *parentLayer); + ~UIScene_Keyboard(); + + virtual void updateTooltips(); + + virtual bool allowRepeat(int key); + // INPUT + virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled); + + virtual void handleTimerComplete(int id); + +protected: + void handlePress(F64 controlId, F64 childId); + +protected: + // TODO: This should be pure virtual in this class + virtual wstring getMoviePath(); + +private: + void KeyboardDonePressed(); + +public: + virtual EUIScene getSceneType() { return eUIScene_Keyboard;} + + // Returns true if this scene handles input + //virtual bool stealsFocus() { return false; } + + // Returns true if this scene has focus for the pad passed in + //virtual bool hasFocus(int iPad) { return false; } + // Returns true if this scene has focus for the pad passed in +#ifndef __PS3__ + virtual bool hasFocus(int iPad) { return bHasFocus; } +#endif + + // Returns true if lower scenes in this scenes layer, or in any layer below this scenes layers should be hidden + virtual bool hidesLowerScenes() { return false; } +};
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIScene_LaunchMoreOptionsMenu.cpp b/Minecraft.Client/Common/UI/UIScene_LaunchMoreOptionsMenu.cpp new file mode 100644 index 00000000..6d472b50 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_LaunchMoreOptionsMenu.cpp @@ -0,0 +1,462 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIScene_LaunchMoreOptionsMenu.h" + +#define GAME_CREATE_ONLINE_TIMER_ID 0 +#define GAME_CREATE_ONLINE_TIMER_TIME 100 + +#ifdef _LARGE_WORLDS +int m_iWorldSizeTitleA[4] = +{ + IDS_WORLD_SIZE_TITLE_CLASSIC, + IDS_WORLD_SIZE_TITLE_SMALL, + IDS_WORLD_SIZE_TITLE_MEDIUM, + IDS_WORLD_SIZE_TITLE_LARGE, +}; +#endif + +UIScene_LaunchMoreOptionsMenu::UIScene_LaunchMoreOptionsMenu(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) +{ + // Setup all the Iggy references we need for this scene + initialiseMovie(); + + m_params = (LaunchMoreOptionsMenuInitData *)initData; + + m_labelWorldOptions.init(app.GetString(IDS_WORLD_OPTIONS)); + + IggyDataValue result; + IggyDataValue value[1]; + value[0].type = IGGY_DATATYPE_number; + value[0].number = m_params->bGenerateOptions?0:1; + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcSetMenuType , 1 , value ); + + m_bMultiplayerAllowed = ProfileManager.IsSignedInLive( m_params->iPad ) && ProfileManager.AllowedToPlayMultiplayer(m_params->iPad); + + bool bOnlineGame, bInviteOnly, bAllowFriendsOfFriends; + bOnlineGame = m_params->bOnlineGame; + bInviteOnly = m_params->bInviteOnly; + bAllowFriendsOfFriends = m_params->bAllowFriendsOfFriends; + + // 4J-PB - to stop an offline game being able to select the online flag + if(ProfileManager.IsSignedInLive(m_params->iPad) == false) + { + m_checkboxes[eLaunchCheckbox_Online].SetEnable(false); + } + + if ( m_params->bOnlineSettingChangedBySystem && !m_bMultiplayerAllowed ) + { + // 4J-JEV: Disable and uncheck these boxes if they can't play multiplayer. + m_checkboxes[eLaunchCheckbox_Online].SetEnable(false); + m_checkboxes[eLaunchCheckbox_InviteOnly].SetEnable(false); + m_checkboxes[eLaunchCheckbox_AllowFoF].SetEnable(false); + + bOnlineGame = bInviteOnly = bAllowFriendsOfFriends = false; + } + else if(!m_params->bOnlineGame) + { + + m_checkboxes[eLaunchCheckbox_InviteOnly].SetEnable(false); + m_checkboxes[eLaunchCheckbox_AllowFoF].SetEnable(false); + } + + m_checkboxes[eLaunchCheckbox_Online].init(app.GetString(IDS_ONLINE_GAME),eLaunchCheckbox_Online,bOnlineGame); + m_checkboxes[eLaunchCheckbox_InviteOnly].init(app.GetString(IDS_INVITE_ONLY),eLaunchCheckbox_InviteOnly,bInviteOnly); + m_checkboxes[eLaunchCheckbox_AllowFoF].init(app.GetString(IDS_ALLOWFRIENDSOFFRIENDS),eLaunchCheckbox_AllowFoF,bAllowFriendsOfFriends); + m_checkboxes[eLaunchCheckbox_PVP].init(app.GetString(IDS_PLAYER_VS_PLAYER),eLaunchCheckbox_PVP,m_params->bPVP); + m_checkboxes[eLaunchCheckbox_TrustSystem].init(app.GetString(IDS_TRUST_PLAYERS),eLaunchCheckbox_TrustSystem,m_params->bTrust); + m_checkboxes[eLaunchCheckbox_FireSpreads].init(app.GetString(IDS_FIRE_SPREADS),eLaunchCheckbox_FireSpreads,m_params->bFireSpreads); + m_checkboxes[eLaunchCheckbox_TNT].init(app.GetString(IDS_TNT_EXPLODES),eLaunchCheckbox_TNT,m_params->bTNT); + m_checkboxes[eLaunchCheckbox_HostPrivileges].init(app.GetString(IDS_HOST_PRIVILEGES),eLaunchCheckbox_HostPrivileges,m_params->bHostPrivileges); + m_checkboxes[eLaunchCheckbox_ResetNether].init(app.GetString(IDS_RESET_NETHER),eLaunchCheckbox_ResetNether,m_params->bResetNether); + m_checkboxes[eLaunchCheckbox_Structures].init(app.GetString(IDS_GENERATE_STRUCTURES),eLaunchCheckbox_Structures,m_params->bStructures); + m_checkboxes[eLaunchCheckbox_FlatWorld].init(app.GetString(IDS_SUPERFLAT_WORLD),eLaunchCheckbox_FlatWorld,m_params->bFlatWorld); + m_checkboxes[eLaunchCheckbox_BonusChest].init(app.GetString(IDS_BONUS_CHEST),eLaunchCheckbox_BonusChest,m_params->bBonusChest); + + if(m_loadedResolution == eSceneResolution_1080) + { +#ifdef _LARGE_WORLDS + m_labelGameOptions.init( app.GetString(IDS_GAME_OPTIONS) ); + m_labelSeed.init(app.GetString(IDS_CREATE_NEW_WORLD_SEED)); + m_labelRandomSeed.init(app.GetString(IDS_CREATE_NEW_WORLD_RANDOM_SEED)); + m_editSeed.init(m_params->seed, eControl_EditSeed); + m_labelWorldSize.init(app.GetString(IDS_WORLD_SIZE)); + m_sliderWorldSize.init(app.GetString(m_iWorldSizeTitleA[m_params->worldSize]),eControl_WorldSize,0,3,m_params->worldSize); + + m_checkboxes[eLaunchCheckbox_DisableSaving].init( app.GetString(IDS_DISABLE_SAVING), eLaunchCheckbox_DisableSaving, m_params->bDisableSaving ); +#endif + } + + // Only the Xbox 360 needs a reset nether + // 4J-PB - PS3 needs it now + // #ifndef _XBOX + // if(!m_params->bGenerateOptions) removeControl( &m_checkboxes[eLaunchCheckbox_ResetNether], false ); + // #endif + + // set the default text +#ifdef _LARGE_WORLDS + wstring wsText=L""; + if(m_params->bGenerateOptions) + { + wsText = app.GetString(IDS_GAMEOPTION_SEED); + } + else + { + wsText = app.GetString(IDS_GAMEOPTION_ONLINE); + } +#else + wstring wsText=app.GetString(IDS_GAMEOPTION_ONLINE); +#endif + EHTMLFontSize size = eHTMLSize_Normal; + if(!RenderManager.IsHiDef() && !RenderManager.IsWidescreen()) + { + size = eHTMLSize_Splitscreen; + } + wchar_t startTags[64]; + swprintf(startTags,64,L"<font color=\"#%08x\">",app.GetHTMLColour(eHTMLColor_White)); + wsText= startTags + wsText; + m_labelDescription.init(wsText); + + addTimer(GAME_CREATE_ONLINE_TIMER_ID,GAME_CREATE_ONLINE_TIMER_TIME); + +#ifdef __PSVITA__ + ui.TouchBoxRebuild(this); +#endif + + m_bIgnoreInput = false; + m_tabIndex = 0; +} + +void UIScene_LaunchMoreOptionsMenu::updateTooltips() +{ + int changeTabTooltip = -1; + +#ifdef _LARGE_WORLDS + if (m_loadedResolution == eSceneResolution_1080 && m_params->bGenerateOptions) + { + // Set tooltip for change tab (only two tabs) + if (m_tabIndex == 0) + { + changeTabTooltip = IDS_GAME_OPTIONS; + } + else + { + changeTabTooltip = IDS_WORLD_OPTIONS; + } + } +#endif + + // If there's a change tab tooltip, left bumper symbol should show but not the text (-2) + int lb = changeTabTooltip == -1 ? -1 : -2; + + ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT, IDS_TOOLTIPS_BACK, -1, -1, -1, -1, lb, changeTabTooltip); +} + +void UIScene_LaunchMoreOptionsMenu::updateComponents() +{ + m_parentLayer->showComponent(m_iPad,eUIComponent_Panorama,true); +#ifdef _LARGE_WORLDS + m_parentLayer->showComponent(m_iPad,eUIComponent_Logo,true); +#else + m_parentLayer->showComponent(m_iPad,eUIComponent_Logo,false); +#endif +} + +wstring UIScene_LaunchMoreOptionsMenu::getMoviePath() +{ + return L"LaunchMoreOptionsMenu"; +} + +void UIScene_LaunchMoreOptionsMenu::tick() +{ + UIScene::tick(); + + bool bMultiplayerAllowed = ProfileManager.IsSignedInLive(m_params->iPad) && ProfileManager.AllowedToPlayMultiplayer(m_params->iPad); + + if (bMultiplayerAllowed != m_bMultiplayerAllowed) + { + m_checkboxes[ eLaunchCheckbox_Online].SetEnable(bMultiplayerAllowed); + m_checkboxes[eLaunchCheckbox_InviteOnly].SetEnable(bMultiplayerAllowed); + m_checkboxes[ eLaunchCheckbox_AllowFoF].SetEnable(bMultiplayerAllowed); + + if (bMultiplayerAllowed) + { + m_checkboxes[ eLaunchCheckbox_Online].setChecked(true); + m_checkboxes[eLaunchCheckbox_AllowFoF].setChecked(true); + } + + m_bMultiplayerAllowed = bMultiplayerAllowed; + } +} + +void UIScene_LaunchMoreOptionsMenu::handleDestroy() +{ +#ifdef __PSVITA__ + app.DebugPrintf("missing InputManager.DestroyKeyboard on Vita !!!!!!\n"); +#endif + + // so shut down the keyboard if it is displayed +#if ( defined __PS3__ || defined __ORBIS__ || defined _DURANGO) + InputManager.DestroyKeyboard(); +#endif +} + +void UIScene_LaunchMoreOptionsMenu::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled) +{ + if(m_bIgnoreInput) return; + + //app.DebugPrintf("UIScene_DebugOverlay handling input for pad %d, key %d, down- %s, pressed- %s, released- %s\n", iPad, key, down?"TRUE":"FALSE", pressed?"TRUE":"FALSE", released?"TRUE":"FALSE"); + ui.AnimateKeyPress(m_iPad, key, repeat, pressed, released); + + switch(key) + { + case ACTION_MENU_CANCEL: + if(pressed) + { + navigateBack(); + handled = true; + } + break; + case ACTION_MENU_OK: +#ifdef __ORBIS__ + case ACTION_MENU_TOUCHPAD_PRESS: +#endif + // 4J-JEV: Inform user why their game must be offline. +#if defined _XBOX_ONE + { + UIControl_CheckBox *checkboxOnline = &m_checkboxes[eLaunchCheckbox_Online]; + if ( pressed && controlHasFocus( checkboxOnline->getId()) && !checkboxOnline->IsEnabled() ) + { + UINT uiIDA[1] = { IDS_CONFIRM_OK }; + ui.RequestMessageBox(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_XBOXLIVE_NOTIFICATION, uiIDA, 1, iPad, NULL, NULL, app.GetStringTable()); + } + } +#endif + + case ACTION_MENU_UP: + case ACTION_MENU_DOWN: + case ACTION_MENU_LEFT: + case ACTION_MENU_RIGHT: + case ACTION_MENU_PAGEUP: + case ACTION_MENU_PAGEDOWN: + case ACTION_MENU_OTHER_STICK_UP: + case ACTION_MENU_OTHER_STICK_DOWN: + sendInputToMovie(key, repeat, pressed, released); + handled = true; + break; + case ACTION_MENU_LEFT_SCROLL: + case ACTION_MENU_RIGHT_SCROLL: + if(pressed && m_loadedResolution == eSceneResolution_1080) + { + // Toggle tab index + m_tabIndex = m_tabIndex == 0 ? 1 : 0; + updateTooltips(); + IggyDataValue result; + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcChangeTab , 0 , NULL ); + } + break; + } +} + +void UIScene_LaunchMoreOptionsMenu::handleCheckboxToggled(F64 controlId, bool selected) +{ + //CD - Added for audio + ui.PlayUISFX(eSFX_Press); + + switch((EControls)((int)controlId)) + { + case eLaunchCheckbox_Online: + m_params->bOnlineGame = selected; + break; + case eLaunchCheckbox_InviteOnly: + m_params->bInviteOnly = selected; + break; + case eLaunchCheckbox_AllowFoF: + m_params->bAllowFriendsOfFriends = selected; + break; + case eLaunchCheckbox_PVP: + m_params->bPVP = selected; + break; + case eLaunchCheckbox_TrustSystem: + m_params->bTrust = selected; + break; + case eLaunchCheckbox_FireSpreads: + m_params->bFireSpreads = selected; + break; + case eLaunchCheckbox_TNT: + m_params->bTNT = selected; + break; + case eLaunchCheckbox_HostPrivileges: + m_params->bHostPrivileges = selected; + break; + case eLaunchCheckbox_ResetNether: + m_params->bResetNether = selected; + break; + case eLaunchCheckbox_Structures: + m_params->bStructures = selected; + break; + case eLaunchCheckbox_FlatWorld: + m_params->bFlatWorld = selected; + break; + case eLaunchCheckbox_BonusChest: + m_params->bBonusChest = selected; + break; + case eLaunchCheckbox_DisableSaving: + m_params->bDisableSaving = selected; + break; + }; +} + +void UIScene_LaunchMoreOptionsMenu::handleFocusChange(F64 controlId, F64 childId) +{ + int stringId = 0; + switch((int)controlId) + { + case eLaunchCheckbox_Online: + stringId = IDS_GAMEOPTION_ONLINE; + break; + case eLaunchCheckbox_InviteOnly: + stringId = IDS_GAMEOPTION_INVITEONLY; + break; + case eLaunchCheckbox_AllowFoF: + stringId = IDS_GAMEOPTION_ALLOWFOF; + break; + case eLaunchCheckbox_PVP: + stringId = IDS_GAMEOPTION_PVP; + break; + case eLaunchCheckbox_TrustSystem: + stringId = IDS_GAMEOPTION_TRUST; + break; + case eLaunchCheckbox_FireSpreads: + stringId = IDS_GAMEOPTION_FIRE_SPREADS; + break; + case eLaunchCheckbox_TNT: + stringId = IDS_GAMEOPTION_TNT_EXPLODES; + break; + case eLaunchCheckbox_HostPrivileges: + stringId = IDS_GAMEOPTION_HOST_PRIVILEGES; + break; + case eLaunchCheckbox_ResetNether: + stringId = IDS_GAMEOPTION_RESET_NETHER; + break; + case eLaunchCheckbox_Structures: + stringId = IDS_GAMEOPTION_STRUCTURES; + break; + case eLaunchCheckbox_FlatWorld: + stringId = IDS_GAMEOPTION_SUPERFLAT; + break; + case eLaunchCheckbox_BonusChest: + stringId = IDS_GAMEOPTION_BONUS_CHEST; + break; +#ifdef _LARGE_WORLDS + case eControl_EditSeed: + stringId = IDS_GAMEOPTION_SEED; + break; + case eControl_WorldSize: + stringId = IDS_GAMEOPTION_WORLD_SIZE; + break; + case eLaunchCheckbox_DisableSaving: + stringId = IDS_GAMEOPTION_DISABLE_SAVING; + break; +#endif + }; + + wstring wsText=app.GetString(stringId); + EHTMLFontSize size = eHTMLSize_Normal; + if(!RenderManager.IsHiDef() && !RenderManager.IsWidescreen()) + { + size = eHTMLSize_Splitscreen; + } + wchar_t startTags[64]; + swprintf(startTags,64,L"<font color=\"#%08x\">",app.GetHTMLColour(eHTMLColor_White)); + wsText= startTags + wsText; + + m_labelDescription.setLabel(wsText); +} + +void UIScene_LaunchMoreOptionsMenu::handleTimerComplete(int id) +{ + /*switch(id) //4J-JEV: Moved this over to the tick. + { + case GAME_CREATE_ONLINE_TIMER_ID: + { + bool bMultiplayerAllowed + = ProfileManager.IsSignedInLive(m_params->iPad) + && ProfileManager.AllowedToPlayMultiplayer(m_params->iPad); + + if (bMultiplayerAllowed != m_bMultiplayerAllowed) + { + m_checkboxes[ eLaunchCheckbox_Online].SetEnable(bMultiplayerAllowed); + m_checkboxes[eLaunchCheckbox_InviteOnly].SetEnable(bMultiplayerAllowed); + m_checkboxes[ eLaunchCheckbox_AllowFoF].SetEnable(bMultiplayerAllowed); + + m_checkboxes[eLaunchCheckbox_Online].setChecked(bMultiplayerAllowed); + + m_bMultiplayerAllowed = bMultiplayerAllowed; + } + } + break; + };*/ +} + +int UIScene_LaunchMoreOptionsMenu::KeyboardCompleteSeedCallback(LPVOID lpParam,bool bRes) +{ + UIScene_LaunchMoreOptionsMenu *pClass=(UIScene_LaunchMoreOptionsMenu *)lpParam; + pClass->m_bIgnoreInput=false; + // 4J HEG - No reason to set value if keyboard was cancelled + if (bRes) + { + uint16_t pchText[128]; + ZeroMemory(pchText, 128 * sizeof(uint16_t) ); + InputManager.GetText(pchText); + pClass->m_editSeed.setLabel((wchar_t *)pchText); + pClass->m_params->seed = (wchar_t *)pchText; + } + return 0; +} + +void UIScene_LaunchMoreOptionsMenu::handlePress(F64 controlId, F64 childId) +{ + if(m_bIgnoreInput) return; + + switch((int)controlId) + { + case eControl_EditSeed: + { + m_bIgnoreInput=true; +#ifdef __PS3__ + int language = XGetLanguage(); + switch(language) + { + case XC_LANGUAGE_JAPANESE: + case XC_LANGUAGE_KOREAN: + case XC_LANGUAGE_TCHINESE: + InputManager.RequestKeyboard(app.GetString(IDS_CREATE_NEW_WORLD_SEED),m_editSeed.getLabel(),(DWORD)0,60,&UIScene_LaunchMoreOptionsMenu::KeyboardCompleteSeedCallback,this,C_4JInput::EKeyboardMode_Default); + break; + default: + // 4J Stu - Use a different keyboard for non-asian languages so we don't have prediction on + InputManager.RequestKeyboard(app.GetString(IDS_CREATE_NEW_WORLD_SEED),m_editSeed.getLabel(),(DWORD)0,60,&UIScene_LaunchMoreOptionsMenu::KeyboardCompleteSeedCallback,this,C_4JInput::EKeyboardMode_Alphabet_Extended); + break; + } +#else + InputManager.RequestKeyboard(app.GetString(IDS_CREATE_NEW_WORLD_SEED),m_editSeed.getLabel(),(DWORD)0,60,&UIScene_LaunchMoreOptionsMenu::KeyboardCompleteSeedCallback,this,C_4JInput::EKeyboardMode_Default); +#endif + } + break; + } +} + + +void UIScene_LaunchMoreOptionsMenu::handleSliderMove(F64 sliderId, F64 currentValue) +{ + int value = (int)currentValue; + switch((int)sliderId) + { + case eControl_WorldSize: +#ifdef _LARGE_WORLDS + m_sliderWorldSize.handleSliderMove(value); + m_params->worldSize = value; + m_sliderWorldSize.setLabel(app.GetString(m_iWorldSizeTitleA[value])); +#endif + break; + } +} diff --git a/Minecraft.Client/Common/UI/UIScene_LaunchMoreOptionsMenu.h b/Minecraft.Client/Common/UI/UIScene_LaunchMoreOptionsMenu.h new file mode 100644 index 00000000..62d75115 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_LaunchMoreOptionsMenu.h @@ -0,0 +1,125 @@ +#pragma once + +#include "UIScene.h" + +class UIScene_LaunchMoreOptionsMenu : public UIScene +{ +private: + enum EControls + { + // Add all checkboxes at the start as they also index into a checkboxes array + eLaunchCheckbox_Online, + eLaunchCheckbox_InviteOnly, + eLaunchCheckbox_AllowFoF, + eLaunchCheckbox_PVP, + eLaunchCheckbox_TrustSystem, + eLaunchCheckbox_FireSpreads, + eLaunchCheckbox_TNT, + eLaunchCheckbox_HostPrivileges, + eLaunchCheckbox_ResetNether, + eLaunchCheckbox_Structures, + eLaunchCheckbox_FlatWorld, + eLaunchCheckbox_BonusChest, + eLaunchCheckbox_DisableSaving, + + eLaunchCheckboxes_Count, + + eControl_EditSeed, + eControl_WorldSize, + }; + + UIControl m_gameOptions, m_worldOptions; + UIControl_CheckBox m_checkboxes[eLaunchCheckboxes_Count]; + UIControl_Label m_labelWorldOptions, m_labelGameOptions, m_labelDescription; + UIControl_Label m_labelSeed, m_labelRandomSeed, m_labelWorldSize; + UIControl_TextInput m_editSeed; + UIControl_Slider m_sliderWorldSize; + IggyName m_funcSetMenuType, m_funcChangeTab; + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) + if(m_loadedResolution == eSceneResolution_1080) + { + UI_MAP_ELEMENT( m_labelGameOptions, "LabelGame") + UI_MAP_ELEMENT( m_labelWorldOptions, "LabelWorld") + + UI_MAP_ELEMENT( m_gameOptions, "GameOptions") + UI_BEGIN_MAP_CHILD_ELEMENTS(m_gameOptions) + UI_MAP_ELEMENT( m_checkboxes[eLaunchCheckbox_Online], "CheckboxOnline") + UI_MAP_ELEMENT( m_checkboxes[eLaunchCheckbox_InviteOnly], "CheckboxInviteOnly") + UI_MAP_ELEMENT( m_checkboxes[eLaunchCheckbox_AllowFoF], "CheckboxAllowFoF") + UI_MAP_ELEMENT( m_checkboxes[eLaunchCheckbox_PVP], "CheckboxPVP") + UI_MAP_ELEMENT( m_checkboxes[eLaunchCheckbox_TrustSystem], "CheckboxTrustSystem") + UI_MAP_ELEMENT( m_checkboxes[eLaunchCheckbox_FireSpreads], "CheckboxFireSpreads") + UI_MAP_ELEMENT( m_checkboxes[eLaunchCheckbox_TNT], "CheckboxTNT") + UI_MAP_ELEMENT( m_checkboxes[eLaunchCheckbox_HostPrivileges], "CheckboxHostPrivileges") + UI_MAP_ELEMENT( m_checkboxes[eLaunchCheckbox_ResetNether], "CheckboxResetNether") + UI_MAP_ELEMENT( m_checkboxes[eLaunchCheckbox_DisableSaving], "CheckboxDisableSaving") + UI_END_MAP_CHILD_ELEMENTS() + + UI_MAP_ELEMENT(m_worldOptions, "WorldOptions") + UI_BEGIN_MAP_CHILD_ELEMENTS(m_worldOptions) + UI_MAP_ELEMENT( m_labelSeed, "Seed") + UI_MAP_ELEMENT( m_editSeed, "EditSeed") + UI_MAP_ELEMENT( m_labelRandomSeed, "RandomSeed") + UI_MAP_ELEMENT( m_labelWorldSize, "WorldSize") + UI_MAP_ELEMENT( m_sliderWorldSize, "WorldSizeSlider") + UI_MAP_ELEMENT( m_checkboxes[eLaunchCheckbox_Structures], "CheckboxStructures") + UI_MAP_ELEMENT( m_checkboxes[eLaunchCheckbox_BonusChest], "CheckboxBonusChest") + UI_MAP_ELEMENT( m_checkboxes[eLaunchCheckbox_FlatWorld], "CheckboxFlatWorld") + UI_END_MAP_CHILD_ELEMENTS() + + UI_MAP_NAME( m_funcChangeTab, L"ChangeTab") + } + else + { + UI_MAP_ELEMENT( m_checkboxes[eLaunchCheckbox_Online], "CheckboxOnline") + UI_MAP_ELEMENT( m_checkboxes[eLaunchCheckbox_InviteOnly], "CheckboxInviteOnly") + UI_MAP_ELEMENT( m_checkboxes[eLaunchCheckbox_AllowFoF], "CheckboxAllowFoF") + UI_MAP_ELEMENT( m_checkboxes[eLaunchCheckbox_PVP], "CheckboxPVP") + UI_MAP_ELEMENT( m_checkboxes[eLaunchCheckbox_TrustSystem], "CheckboxTrustSystem") + UI_MAP_ELEMENT( m_checkboxes[eLaunchCheckbox_FireSpreads], "CheckboxFireSpreads") + UI_MAP_ELEMENT( m_checkboxes[eLaunchCheckbox_TNT], "CheckboxTNT") + UI_MAP_ELEMENT( m_checkboxes[eLaunchCheckbox_HostPrivileges], "CheckboxHostPrivileges") + UI_MAP_ELEMENT( m_checkboxes[eLaunchCheckbox_ResetNether], "CheckboxResetNether") + + UI_MAP_ELEMENT( m_labelWorldOptions, "WorldOptions") + UI_MAP_ELEMENT( m_checkboxes[eLaunchCheckbox_Structures], "CheckboxStructures") + UI_MAP_ELEMENT( m_checkboxes[eLaunchCheckbox_FlatWorld], "CheckboxFlatWorld") + UI_MAP_ELEMENT( m_checkboxes[eLaunchCheckbox_BonusChest], "CheckboxBonusChest") + } + + UI_MAP_ELEMENT( m_labelDescription, "Description") + + UI_MAP_NAME( m_funcSetMenuType, L"SetMenuType") + UI_END_MAP_ELEMENTS_AND_NAMES() + + LaunchMoreOptionsMenuInitData *m_params; + bool m_bMultiplayerAllowed; + bool m_bIgnoreInput; + bool m_tabIndex; + +public: + UIScene_LaunchMoreOptionsMenu(int iPad, void *initData, UILayer *parentLayer); + + virtual void updateTooltips(); + virtual void updateComponents(); + + virtual EUIScene getSceneType() { return eUIScene_LaunchMoreOptionsMenu;} + +protected: + // TODO: This should be pure virtual in this class + virtual wstring getMoviePath(); + +public: + virtual void tick(); + virtual void handleDestroy(); + // INPUT + virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled); + virtual void handleFocusChange(F64 controlId, F64 childId); + virtual void handleTimerComplete(int id); + static int KeyboardCompleteSeedCallback(LPVOID lpParam,const bool bRes); + virtual void handlePress(F64 controlId, F64 childId); + virtual void handleSliderMove(F64 sliderId, F64 currentValue); + +protected: + void handleCheckboxToggled(F64 controlId, bool selected); +}; diff --git a/Minecraft.Client/Common/UI/UIScene_LeaderboardsMenu.cpp b/Minecraft.Client/Common/UI/UIScene_LeaderboardsMenu.cpp new file mode 100644 index 00000000..80db57f8 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_LeaderboardsMenu.cpp @@ -0,0 +1,1045 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIScene_LeaderboardsMenu.h" +#include "..\Leaderboards\LeaderboardManager.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.level.tile.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.item.h" + +#define PLAYER_ONLINE_TIMER_ID 0 +#define PLAYER_ONLINE_TIMER_TIME 100 + +// if the value is greater than 32000, it's an xzp icon that needs displayed, rather than the game icon +const int UIScene_LeaderboardsMenu::TitleIcons[UIScene_LeaderboardsMenu::NUM_LEADERBOARDS][7] = +{ + { UIControl_LeaderboardList::e_ICON_TYPE_WALKED, UIControl_LeaderboardList::e_ICON_TYPE_FALLEN, Item::minecart_Id, Item::boat_Id, NULL }, + { Tile::dirt_Id, Tile::stoneBrick_Id, Tile::sand_Id, Tile::rock_Id, Tile::gravel_Id, Tile::clay_Id, Tile::obsidian_Id }, + { Item::egg_Id, Item::wheat_Id, Tile::mushroom1_Id, Tile::reeds_Id, Item::milk_Id, Tile::pumpkin_Id, NULL }, + { UIControl_LeaderboardList::e_ICON_TYPE_ZOMBIE, UIControl_LeaderboardList::e_ICON_TYPE_SKELETON, UIControl_LeaderboardList::e_ICON_TYPE_CREEPER, UIControl_LeaderboardList::e_ICON_TYPE_SPIDER, UIControl_LeaderboardList::e_ICON_TYPE_SPIDERJOKEY, UIControl_LeaderboardList::e_ICON_TYPE_ZOMBIEPIGMAN, UIControl_LeaderboardList::e_ICON_TYPE_SLIME }, +}; +const UIScene_LeaderboardsMenu::LeaderboardDescriptor UIScene_LeaderboardsMenu::LEADERBOARD_DESCRIPTORS[UIScene_LeaderboardsMenu::NUM_LEADERBOARDS][4] = { + { + UIScene_LeaderboardsMenu::LeaderboardDescriptor( 4, true, IDS_LEADERBOARD_TRAVELLING_PEACEFUL), // Travelling Peaceful + UIScene_LeaderboardsMenu::LeaderboardDescriptor( 4, true, IDS_LEADERBOARD_TRAVELLING_EASY), // Travelling Easy + UIScene_LeaderboardsMenu::LeaderboardDescriptor( 4, true, IDS_LEADERBOARD_TRAVELLING_NORMAL), // Travelling Normal + UIScene_LeaderboardsMenu::LeaderboardDescriptor( 4, true, IDS_LEADERBOARD_TRAVELLING_HARD), // Travelling Hard + }, + { + UIScene_LeaderboardsMenu::LeaderboardDescriptor( 7, false, IDS_LEADERBOARD_MINING_BLOCKS_PEACEFUL), // Mining Peaceful + UIScene_LeaderboardsMenu::LeaderboardDescriptor( 7, false, IDS_LEADERBOARD_MINING_BLOCKS_EASY), // Mining Easy + UIScene_LeaderboardsMenu::LeaderboardDescriptor( 7, false, IDS_LEADERBOARD_MINING_BLOCKS_NORMAL), // Mining Normal + UIScene_LeaderboardsMenu::LeaderboardDescriptor( 7, false, IDS_LEADERBOARD_MINING_BLOCKS_HARD), // Mining Hard + }, + { + UIScene_LeaderboardsMenu::LeaderboardDescriptor( 6, false, IDS_LEADERBOARD_FARMING_PEACEFUL), // Farming Peaceful + UIScene_LeaderboardsMenu::LeaderboardDescriptor( 6, false, IDS_LEADERBOARD_FARMING_EASY), // Farming Easy + UIScene_LeaderboardsMenu::LeaderboardDescriptor( 6, false, IDS_LEADERBOARD_FARMING_NORMAL), // Farming Normal + UIScene_LeaderboardsMenu::LeaderboardDescriptor( 6, false, IDS_LEADERBOARD_FARMING_HARD), // Farming Hard + }, + { + UIScene_LeaderboardsMenu::LeaderboardDescriptor( 0, false, -1), // + UIScene_LeaderboardsMenu::LeaderboardDescriptor( 7, false, IDS_LEADERBOARD_KILLS_EASY), // Kills Easy + UIScene_LeaderboardsMenu::LeaderboardDescriptor( 7, false, IDS_LEADERBOARD_KILLS_NORMAL), // Kills Normal + UIScene_LeaderboardsMenu::LeaderboardDescriptor( 7, false, IDS_LEADERBOARD_KILLS_HARD), // Kills Hard + }, +}; + +UIScene_LeaderboardsMenu::UIScene_LeaderboardsMenu(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) +{ + // Setup all the Iggy references we need for this scene + initialiseMovie(); + + m_bReady=false; + + m_bPopulatedOnce = false; + + m_newTop = m_newSel = -1; + m_isProcessingStatsRead = false; + // Ignore input until we're retrieved stats, or functions will be called in here after we've backed out of the scene + m_bIgnoreInput=true; + + // Alert the app the we want to be informed of ethernet connections + app.SetLiveLinkRequired( true ); + + LeaderboardManager::Instance()->OpenSession(); + + //GetFriends(); + + m_currentLeaderboard = 0; + m_currentDifficulty = 2; + SetLeaderboardHeader(); + m_currentFilter = LeaderboardManager::eFM_Friends; + + wchar_t filterBuffer[40]; + swprintf(filterBuffer, 40, L"%ls%ls", app.GetString(IDS_LEADERBOARD_FILTER), app.GetString(IDS_LEADERBOARD_FILTER_FRIENDS)); + m_labelFilter.init(filterBuffer); + + wchar_t entriesBuffer[40]; + swprintf(entriesBuffer, 40, L"%ls%i", app.GetString(IDS_LEADERBOARD_ENTRIES), 0); + m_labelEntries.init(entriesBuffer); + + ReadStats(-1); + +#if ( defined __PS3__ || defined __ORBIS__ || defined __PSVITA__ ) + addTimer( PLAYER_ONLINE_TIMER_ID, PLAYER_ONLINE_TIMER_TIME ); +#endif +} + +UIScene_LeaderboardsMenu::~UIScene_LeaderboardsMenu() +{ + LeaderboardManager::Instance()->CancelOperation(); + LeaderboardManager::Instance()->CloseSession(); + + // Alert the app the we no longer want to be informed of ethernet connections + app.SetLiveLinkRequired( false ); +} + +void UIScene_LeaderboardsMenu::updateTooltips() +{ + int iTooltipFriendRequest=-1; + int iTooltipGamerCardOrProfile=-1; + +#ifdef _DURANGO + //if( m_leaderboard.m_entries.size() > 0 ) + if(m_leaderboard.m_totalEntryCount > 0) + { + unsigned int selection = m_newSel; + + // If the selected user is me, don't show Send Friend Request, and show the gamer profile, not the gamer card + + // Check that the index is actually within range of the data we've got before accessing the m_leaderboard.m_entries array + int idx = selection - GetEntryStartIndex(); + if( ( idx < 0 ) || ( idx >= m_leaderboard.m_entries.size() ) ) + { + return; + } + if(m_leaderboard.m_entries[idx].m_bPlayer) + { + iTooltipGamerCardOrProfile=IDS_TOOLTIPS_VIEW_GAMERPROFILE; + } + else + { + iTooltipGamerCardOrProfile=IDS_TOOLTIPS_VIEW_GAMERCARD; + +#ifdef _XBOX + // if we're on the friends filter, then don't show the Send Friend Request + if(!m_currentFilter == LeaderboardManager::eFM_Friends) +#endif + { + // check the entry we're on + if( m_leaderboard.m_entries.size() > 0 ) + { + if( selection >= GetEntryStartIndex() && + selection < (GetEntryStartIndex() + m_leaderboard.m_entries.size()) ) + { +#ifdef _XBOX + if( (m_leaderboard.m_entries[selection - (m_leaderboard.m_entryStartIndex-1)].m_bFriend==false) + && (m_leaderboard.m_entries[selection - (m_leaderboard.m_entryStartIndex-1)].m_bRequestedFriend==false)) +#endif + { + iTooltipFriendRequest=IDS_TOOLTIPS_SEND_FRIEND_REQUEST; + } + } + } + } + } + } +#endif + + ui.SetTooltips(m_iPad, iTooltipFriendRequest, IDS_TOOLTIPS_BACK, IDS_TOOLTIPS_CHANGE_FILTER, iTooltipGamerCardOrProfile); +} + +void UIScene_LeaderboardsMenu::updateComponents() +{ + m_parentLayer->showComponent(m_iPad,eUIComponent_Panorama,!app.GetGameStarted()); + m_parentLayer->showComponent(m_iPad,eUIComponent_Logo,false); +} + +wstring UIScene_LeaderboardsMenu::getMoviePath() +{ + return L"LeaderboardMenu"; +} + +void UIScene_LeaderboardsMenu::handleReload() +{ + // We don't allow this in splitscreen, so just go back + navigateBack(); +} + +void UIScene_LeaderboardsMenu::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled) +{ + if(m_bIgnoreInput && key != ACTION_MENU_CANCEL) return; + + ui.AnimateKeyPress(m_iPad, key, repeat, pressed, released); + + // If this is not a press, do not action + if (!pressed) return; + + + /*app.DebugPrintf( + " m_newSel = %i [bottomId] = %i [topId] = %i, [size] = %i\n", + m_newSel, + m_leaderboard.m_entries.size() == 0 ? 0 : m_leaderboard.m_entries[m_leaderboard.m_entries.size()-1].m_row, + GetEntryStartIndex(), + m_leaderboard.m_entries.size() + );*/ + + switch(key) + { + case ACTION_MENU_CANCEL: + if(pressed) + { + navigateBack(); + handled = true; + } + break; + case ACTION_MENU_UP: + --m_newSel; + if(m_newSel<0)m_newSel = 0; + sendInputToMovie(key, repeat, pressed, released); + break; + case ACTION_MENU_DOWN: + ++m_newSel; + if(m_newSel>=m_leaderboard.m_totalEntryCount) m_newSel = m_leaderboard.m_totalEntryCount - 1; + sendInputToMovie(key, repeat, pressed, released); + break; + case ACTION_MENU_LEFT_SCROLL: + case ACTION_MENU_RIGHT_SCROLL: + { + //Do nothing if a stats read is currently in progress, otherwise the system complains about to many read requests + if( pressed && m_bPopulatedOnce && LeaderboardManager::Instance()->isIdle() ) + { + //CD - Added for audio + ui.PlayUISFX(eSFX_Scroll); + + if( key == ACTION_MENU_RIGHT_SCROLL ) + { + ++m_currentDifficulty; + if( m_currentDifficulty == 4 ) + m_currentDifficulty = 0; + + if( m_currentLeaderboard == LEADERBOARD_KILLS_POSITION && m_currentDifficulty == 0 ) + m_currentDifficulty = 1; + } + else + { + if( m_currentDifficulty == 0 ) + m_currentDifficulty = 4; + --m_currentDifficulty; + + if( m_currentLeaderboard == LEADERBOARD_KILLS_POSITION && m_currentDifficulty == 0 ) + m_currentDifficulty = 3; + } + + SetLeaderboardHeader(); + + ReadStats(-1); + ui.PlayUISFX(eSFX_Press); + } + + handled = true; + } + break; + case ACTION_MENU_LEFT: + case ACTION_MENU_RIGHT: + { + //Do nothing if a stats read is currently in progress, otherwise the system complains about to many read requests + if ( pressed && m_bPopulatedOnce && LeaderboardManager::Instance()->isIdle() ) + { + //CD - Added for audio + ui.PlayUISFX(eSFX_Scroll); + + m_bReady=false; + if(key == ACTION_MENU_RIGHT) + { + ++m_currentLeaderboard; + if( m_currentLeaderboard == NUM_LEADERBOARDS ) + m_currentLeaderboard = 0; + } + else + { + if( m_currentLeaderboard == 0 ) + m_currentLeaderboard = NUM_LEADERBOARDS; + --m_currentLeaderboard; + } + + if( m_currentLeaderboard == LEADERBOARD_KILLS_POSITION && m_currentDifficulty == 0 ) + m_currentDifficulty = 1; + + SetLeaderboardHeader(); + + ReadStats(-1); + ui.PlayUISFX(eSFX_Press); + } + handled = true; + } + break; + case ACTION_MENU_PAGEUP: + case ACTION_MENU_PAGEDOWN: + { + //Do nothing if a stats read is currently in progress, otherwise the system complains about to many read requests + if( pressed && m_bPopulatedOnce && LeaderboardManager::Instance()->isIdle() ) + { + //CD - Added for audio + ui.PlayUISFX(eSFX_Scroll); + + if( m_leaderboard.m_totalEntryCount <= 10 ) + break; + + sendInputToMovie(key, repeat, pressed, released); + +#if 0 + if( key == ACTION_MENU_PAGEUP ) + { + m_newTop = m_listGamers.GetTopItem() - 10; + + if( m_newTop < 0 ) + m_newTop = 0; + + m_newSel = m_newTop; + } + else + { + + m_newTop = m_listGamers.GetTopItem() + 10; + + if( m_newTop+10 > (int)m_leaderboard.m_totalEntryCount ) + { + m_newTop = m_leaderboard.m_totalEntryCount - 10; + if( m_newTop < 0 ) + m_newTop = 0; + } + + m_newSel = m_newTop; + } +#endif + } + handled = true; + } + break; + case ACTION_MENU_X: + { + //Do nothing if a stats read is currently in progress, otherwise the system complains about to many read requests + if( pressed && m_bPopulatedOnce && LeaderboardManager::Instance()->isIdle() ) + { + //CD - Added for audio + ui.PlayUISFX(eSFX_Scroll); + + switch( m_currentFilter ) + { + case LeaderboardManager::eFM_Friends: + { + m_currentFilter = LeaderboardManager::eFM_MyScore; + wchar_t filterBuffer[40]; + swprintf(filterBuffer, 40, L"%ls%ls", app.GetString(IDS_LEADERBOARD_FILTER), app.GetString(IDS_LEADERBOARD_FILTER_MYSCORE)); + m_labelFilter.setLabel(filterBuffer); + } + break; + case LeaderboardManager::eFM_MyScore: + { + m_currentFilter = LeaderboardManager::eFM_TopRank; + wchar_t filterBuffer[40]; + swprintf(filterBuffer, 40, L"%ls%ls", app.GetString(IDS_LEADERBOARD_FILTER), app.GetString(IDS_LEADERBOARD_FILTER_OVERALL)); + m_labelFilter.setLabel(filterBuffer); + } + break; + case LeaderboardManager::eFM_TopRank: + { + m_currentFilter = LeaderboardManager::eFM_Friends; + wchar_t filterBuffer[40]; + swprintf(filterBuffer, 40, L"%ls%ls", app.GetString(IDS_LEADERBOARD_FILTER), app.GetString(IDS_LEADERBOARD_FILTER_FRIENDS)); + m_labelFilter.setLabel(filterBuffer); + } + break; + } + + ReadStats(-1); + ui.PlayUISFX(eSFX_Press); + } + handled = true; + } + break; + case ACTION_MENU_Y: + { +#ifdef _DURANGO + //Show gamercard + //if( m_leaderboard.m_entries.size() > 0 ) + if(m_leaderboard.m_totalEntryCount > 0) + { + unsigned int selection = m_newSel; + if( selection >= GetEntryStartIndex() && + selection < (GetEntryStartIndex() + m_leaderboard.m_entries.size()) ) + { + PlayerUID uid = m_leaderboard.m_entries[selection - GetEntryStartIndex()].m_xuid; + if( uid != INVALID_XUID ) + { + ProfileManager.ShowProfileCard(ProfileManager.GetLockedProfile(),uid); + ui.PlayUISFX(eSFX_Press); + } + } + } +#endif + handled = true; + } + break; + case ACTION_MENU_A: + { +#ifdef _DURANGO + //Send friend request if the filter mode is not friend, and they're not a friend or a pending friend +#ifdef _XBOX + if( m_currentFilter != LeaderboardManager::eFM_Friends ) +#endif + { + if( m_leaderboard.m_entries.size() > 0 ) + { + unsigned int selection = m_newSel; + if( selection >= GetEntryStartIndex() && + selection < (GetEntryStartIndex() + m_leaderboard.m_entries.size()) ) + { + //If not the player and neither currently a friend or requested to be a friend + if( !m_leaderboard.m_entries[selection - GetEntryStartIndex()].m_bPlayer +#ifdef _XBOX + && !m_leaderboard.m_entries[selection - (m_leaderboard.m_entryStartIndex-1) ].m_bFriend + && !m_leaderboard.m_entries[selection - (m_leaderboard.m_entryStartIndex-1) ].m_bRequestedFriend +#endif + ) + { + PlayerUID xuid = m_leaderboard.m_entries[selection - GetEntryStartIndex()].m_xuid; + if( xuid != INVALID_XUID ) + { + ProfileManager.ShowAddFriend(m_iPad,xuid); + ui.PlayUISFX(eSFX_Press); + } + } + } + } + } +#endif + handled = true; + } + break; + } +} + +void UIScene_LeaderboardsMenu::ReadStats(int startIndex) +{ + //If startIndex == -1, then use default values + if( startIndex == -1 ) + { + m_newEntryIndex = 1; + m_newReadSize = READ_SIZE; + + m_newEntriesCount = 0; + + m_leaderboard.m_totalEntryCount = 0; + + m_listEntries.clearList(); + } + else + { + m_newEntryIndex = (unsigned int)startIndex; + // m_newReadSize = min((int)READ_SIZE, (int)m_leaderboard.m_totalEntryCount-(startIndex-1)); + } + + //app.DebugPrintf("Requesting stats read %d - %d - %d\n", m_currentLeaderboard, startIndex == -1 ? m_currentFilter : LeaderboardManager::eFM_TopRank, m_currentDifficulty); + + LeaderboardManager::EFilterMode filtermode; + if ( m_currentFilter == LeaderboardManager::eFM_MyScore + || m_currentFilter == LeaderboardManager::eFM_TopRank ) + { + filtermode = (startIndex == -1 ? m_currentFilter : LeaderboardManager::eFM_TopRank); + } + else + { + // 4J-JEV: Friends filter shouldn't switch to toprank. + filtermode = m_currentFilter; + } + + switch (filtermode) + { + case LeaderboardManager::eFM_TopRank: + LeaderboardManager::Instance()->ReadStats_TopRank( this, + m_currentDifficulty, (LeaderboardManager::EStatsType) m_currentLeaderboard, + m_newEntryIndex, m_newReadSize + ); + break; + case LeaderboardManager::eFM_MyScore: + { + PlayerUID uid; + ProfileManager.GetXUID(ProfileManager.GetPrimaryPad(),&uid, true); + LeaderboardManager::Instance()->ReadStats_MyScore( this, + m_currentDifficulty, (LeaderboardManager::EStatsType) m_currentLeaderboard, + uid /*ignored on PS3*/, + m_newReadSize + ); + } + break; + case LeaderboardManager::eFM_Friends: + { + PlayerUID uid; + ProfileManager.GetXUID(ProfileManager.GetPrimaryPad(),&uid, true); + LeaderboardManager::Instance()->ReadStats_Friends( this, + m_currentDifficulty, (LeaderboardManager::EStatsType) m_currentLeaderboard, + uid /*ignored on PS3*/, + m_newEntryIndex, m_newReadSize + ); + } + break; + } + + //Show the loading message + m_labelInfo.setLabel(app.GetString(IDS_LEADERBOARD_LOADING)); + m_labelInfo.setVisible(true); +} + +bool UIScene_LeaderboardsMenu::OnStatsReadComplete(LeaderboardManager::eStatsReturn retIn, int numResults, LeaderboardManager::ViewOut results) +{ + //CScene_Leaderboards* scene = reinterpret_cast<CScene_Leaderboards*>(userdata); + + m_isProcessingStatsRead = true; + + //bool noResults = LeaderboardManager::Instance()->GetStatsState() != XboxLeaderboardManager::eStatsState_Ready; + bool ret; + + //app.DebugPrintf("Leaderboards read %d stats\n", numResults); + if (retIn == LeaderboardManager::eStatsReturn_Success) + { + m_numStats = numResults; + m_stats = results; + ret = RetrieveStats(); + } + else ret = true; + + //else LeaderboardManager::Instance()->SetStatsRetrieved(false); + + PopulateLeaderboard(retIn); + + updateTooltips(); + + m_isProcessingStatsRead = false; + + // allow user input now + m_bIgnoreInput=false; + + return ret; +} + +bool UIScene_LeaderboardsMenu::RetrieveStats() +{ + if(app.DebugSettingsOn() && (app.GetGameSettingsDebugMask()&(1L<<eDebugSetting_DebugLeaderboards))) + { + m_leaderboard.m_totalEntryCount = NUM_ENTRIES; + m_leaderboard.m_numColumns = LEADERBOARD_DESCRIPTORS[m_currentLeaderboard][m_currentDifficulty].m_columnCount; + + //For each entry in the leaderboard + for(unsigned int entryIndex=0; entryIndex < NUM_ENTRIES; entryIndex++) + { + m_leaderboard.m_entries.push_back(LeaderboardEntry()); + m_leaderboard.m_entries[entryIndex].m_xuid = INVALID_XUID; + + m_leaderboard.m_entries[entryIndex].m_row = entryIndex; + m_leaderboard.m_entries[entryIndex].m_rank = entryIndex+1; + swprintf(m_leaderboard.m_entries[entryIndex].m_wcRank, 12, L"12345678");//(int)m_leaderboard.m_entries[entryIndex].m_rank); + + swprintf(m_leaderboard.m_entries[entryIndex].m_gamerTag, 17, L"WWWWWWWWWWWWWWWW"); + + //m_leaderboard.m_entries[entryIndex].m_locale = (entryIndex % 37) + 1; + + bool isDistanceLeaderboard = LEADERBOARD_DESCRIPTORS[m_currentLeaderboard][m_currentDifficulty].m_isDistanceLeaderboard; + + for( unsigned int i=0 ; i<m_leaderboard.m_numColumns ; i++ ) + { + if( !isDistanceLeaderboard ) + { + m_leaderboard.m_entries[entryIndex].m_columns[i] = USHRT_MAX; + swprintf(m_leaderboard.m_entries[entryIndex].m_wcColumns[i], 12, L"%u", m_leaderboard.m_entries[entryIndex].m_columns[i]); + } + else + { + m_leaderboard.m_entries[entryIndex].m_columns[i] = UINT_MAX; + swprintf(m_leaderboard.m_entries[entryIndex].m_wcColumns[i], 12, L"%.1fkm", ((float)m_leaderboard.m_entries[entryIndex].m_columns[i])/100.f/1000.f); + } + } + + m_leaderboard.m_entries[entryIndex].m_bPlayer = (entryIndex == 0); + m_leaderboard.m_entries[entryIndex].m_bOnline = (entryIndex != 0); + m_leaderboard.m_entries[entryIndex].m_bFriend = (entryIndex != 0); + m_leaderboard.m_entries[entryIndex].m_bRequestedFriend = false; + } + + //LeaderboardManager::Instance()->SetStatsRetrieved(true); + + m_newEntryIndex = 0; + m_newEntriesCount = NUM_ENTRIES; + + return true; + } + + //assert( LeaderboardManager::Instance()->GetStats() != NULL ); + //PXUSER_STATS_READ_RESULTS stats = LeaderboardManager::Instance()->GetStats(); + //if( m_currentFilter == LeaderboardManager::eFM_Friends ) LeaderboardManager::Instance()->SortFriendStats(); + + bool isDistanceLeaderboard = LEADERBOARD_DESCRIPTORS[m_currentLeaderboard][m_currentDifficulty].m_isDistanceLeaderboard; + + m_newEntriesCount = m_stats.m_numQueries; + + // First read + if( m_leaderboard.m_totalEntryCount == 0 ) + { + m_leaderboard.m_entries.clear(); + +#if _DURANGO + m_leaderboard.m_totalEntryCount = m_numStats; +#else + m_leaderboard.m_totalEntryCount = (m_currentFilter == LeaderboardManager::eFM_Friends) ? m_newEntriesCount : m_numStats; +#endif + + if( m_leaderboard.m_totalEntryCount == 0 || m_newEntriesCount == 0 ) + { + //LeaderboardManager::Instance()->SetStatsRetrieved(false); + return false; + } + + m_leaderboard.m_numColumns = m_stats.m_queries[0].m_statsSize; + + for( unsigned int entryIndex=0 ; entryIndex < m_newEntriesCount; ++entryIndex ) + { + m_leaderboard.m_entries.push_back(LeaderboardEntry()); + CopyLeaderboardEntry(&(m_stats.m_queries[entryIndex]), entryIndex, isDistanceLeaderboard); + } + + m_newEntryIndex = 0; + + // Clear these values so that we know whether or not they are set in the next block + m_newTop = -1; + m_newSel = -1; + + // If the filter mode is "My Score" then centre the list around the entries and select the player's score + if( m_currentFilter == LeaderboardManager::eFM_MyScore) + { + //Centre the leaderboard list on the entries + m_newTop = GetEntryStartIndex(); + + //Select the player entry + for( unsigned int i = GetEntryStartIndex(); i< GetEntryStartIndex() + m_leaderboard.m_entries.size(); ++i ) + { + if( m_leaderboard.m_entries[i - GetEntryStartIndex()].m_bPlayer ) + { + m_newSel = i; // this might be off the screen! + // and reposition the top one + if(m_newSel-m_newTop>9) + { + m_newTop=m_newSel-9; + } + break; + } + } + } + + // If not set, default to start index + if (m_newSel < 0) m_newTop = m_newSel = GetEntryStartIndex(); + } + // Additional read + else + { + if(m_newEntryIndex < GetEntryStartIndex() && m_newEntryIndex == 1) + { + // If we're at the top the new entries count is incorrect, so amend + m_newEntriesCount = GetEntryStartIndex(); + } + + bool deleteFront = false; + bool deleteBack = false; + + bool trim = m_leaderboard.m_entries.size() + m_newEntriesCount >= NUM_ENTRIES; + + unsigned int insertPosition = 0; + + // If the first new entry is at a smaller index than the current first entry + if(m_newEntryIndex < GetEntryStartIndex()) + { + insertPosition = 0; + if (trim) deleteBack = true; + } + else + { + insertPosition = m_leaderboard.m_entries.size(); + if (trim) deleteFront = true; + } + + m_newEntryIndex = insertPosition; + + // Copy results to entries list + for( unsigned int i=0 ; i < m_newEntriesCount ; ++i ) + { + m_leaderboard.m_entries.insert(m_leaderboard.m_entries.begin() + insertPosition, LeaderboardEntry()); + CopyLeaderboardEntry(&(m_stats.m_queries[i]), insertPosition, isDistanceLeaderboard); + + insertPosition++; + } + + if (deleteFront) + { + // Delete front x entries + m_leaderboard.m_entries.erase(m_leaderboard.m_entries.begin(), m_leaderboard.m_entries.begin() + READ_SIZE); + m_newEntryIndex -= m_newReadSize; + } + else if (deleteBack) + { + // Delete back x entries + m_leaderboard.m_entries.erase(m_leaderboard.m_entries.end() - READ_SIZE, m_leaderboard.m_entries.end()); + } + } + + return true; +} + +void UIScene_LeaderboardsMenu::CopyLeaderboardEntry(LeaderboardManager::ReadScore *statsRow, int leaderboardEntryIndex, bool isDistanceLeaderboard) +{ + LeaderboardEntry* leaderboardEntry = &(m_leaderboard.m_entries[leaderboardEntryIndex]); + + ZeroMemory(leaderboardEntry, sizeof(LeaderboardEntry)); + leaderboardEntry->m_xuid = statsRow->m_uid; + + // Copy the rank + leaderboardEntry->m_rank = statsRow->m_rank; + DWORD displayRank = leaderboardEntry->m_rank; + if(displayRank > 9999999) displayRank = 9999999; + swprintf(leaderboardEntry->m_wcRank, 12, L"%u", displayRank); + + leaderboardEntry->m_idsErrorMessage = statsRow->m_idsErrorMessage; + + // Build a row ID + if (m_currentFilter == LeaderboardManager::eFM_Friends) + { + // If friends don't ID rows by rank + leaderboardEntry->m_row = leaderboardEntryIndex; + } + else + { + leaderboardEntry->m_row = statsRow->m_rank - 1; + if (leaderboardEntryIndex > 0) { + // Check this row ID (/rank) against the last one, it might be the same + // (this happens on PS3 when players have the same score, i.e. if they share 76th position there'll be two rank 76 + // and the following entry will be rank 78) + LeaderboardEntry* prevEntry = &(m_leaderboard.m_entries[leaderboardEntryIndex - 1]); + if (leaderboardEntry->m_row <= prevEntry->m_row) + { + leaderboardEntry->m_row = prevEntry->m_row + 1; + } + } + } + +#ifdef __PS3__ + // m_name can be unicode characters somehow for Japan - should use m_onlineID + wstring wstr=convStringToWstring(statsRow->m_uid.getOnlineID()); + swprintf(leaderboardEntry->m_gamerTag, XUSER_NAME_SIZE, L"%ls",wstr.c_str()); +#else + memcpy(leaderboardEntry->m_gamerTag, statsRow->m_name.data(), statsRow->m_name.size() * sizeof(wchar_t)); +#endif + + // Copy the other columns + for( unsigned int i=0 ; i<statsRow->m_statsSize ; i++ ) + { + leaderboardEntry->m_columns[i] = statsRow->m_statsData[i]; + ZeroMemory(leaderboardEntry->m_wcColumns[i],12*sizeof(WCHAR)); + if( !isDistanceLeaderboard ) + { + DWORD displayValue = leaderboardEntry->m_columns[i]; + if(displayValue > 99999) displayValue = 99999; + swprintf(leaderboardEntry->m_wcColumns[i], 12, L"%u",displayValue); +#ifdef _DEBUG + //app.DebugPrintf("Value - %d\n",leaderboardEntry->m_columns[i]); +#endif + } + else + { + // check how many digits we have + int iDigitC=0; + unsigned int uiVal=leaderboardEntry->m_columns[i]; +// uiVal=0xFFFFFFFF; +// leaderboardEntry->m_columns[i-1]=uiVal; + + while(uiVal!=0) + { + uiVal/=10; + iDigitC++; + } + +#ifdef _DEBUG + //app.DebugPrintf("Value - %d\n",leaderboardEntry->m_columns[i]); +#endif + if(iDigitC<4) + { + // m + swprintf(leaderboardEntry->m_wcColumns[i], 12, L"%um", leaderboardEntry->m_columns[i]); +#ifdef _DEBUG + //app.DebugPrintf("Display - %um\n", leaderboardEntry->m_columns[i]); +#endif + } + else if(iDigitC<8) + { + // km with a .X + swprintf(leaderboardEntry->m_wcColumns[i], 12, L"%.1fkm", ((float)leaderboardEntry->m_columns[i])/1000.f); +#ifdef _DEBUG + //app.DebugPrintf("Display - %.1fkm\n", ((float)leaderboardEntry->m_columns[i])/1000.f); +#endif + } + else + { + // bigger than that, so no decimal point + swprintf(leaderboardEntry->m_wcColumns[i], 12, L"%.0fkm", ((float)leaderboardEntry->m_columns[i])/1000.f); +#ifdef _DEBUG + //app.DebugPrintf("Display - %.0fkm\n", ((float)leaderboardEntry->m_columns[i])/1000.f); +#endif + } + } + } + +#ifdef _DURANGO + //Is the player + PlayerUID myXuid; + ProfileManager.GetXUID(ProfileManager.GetPrimaryPad(),&myXuid,true); + if( statsRow->m_uid == myXuid ) + { + leaderboardEntry->m_bPlayer = true; + leaderboardEntry->m_bOnline = false; + leaderboardEntry->m_bFriend = false; + leaderboardEntry->m_bRequestedFriend = false; + } + else + { + leaderboardEntry->m_bPlayer = false; + leaderboardEntry->m_bOnline = false; + leaderboardEntry->m_bFriend = false; + leaderboardEntry->m_bRequestedFriend = false; + +#ifdef _XBOX + //Check for friend status + for( unsigned int friendIndex=0 ; friendIndex<m_numFriends ; ++friendIndex ) + { + if( m_friends[friendIndex].xuid == statsRow->m_uid ) + { + if( ( m_friends[friendIndex].dwFriendState & ( XONLINE_FRIENDSTATE_FLAG_SENTREQUEST | XONLINE_FRIENDSTATE_FLAG_RECEIVEDREQUEST ) ) == 0 ) + { + //Is friend, might be online + leaderboardEntry->m_bFriend = true; + leaderboardEntry->m_bOnline = ( m_friends[friendIndex].dwFriendState & XONLINE_FRIENDSTATE_FLAG_ONLINE ); + leaderboardEntry->m_bRequestedFriend = false; + } + else + { + //Friend request sent but not accepted yet + leaderboardEntry->m_bOnline = false; + leaderboardEntry->m_bFriend = false; + leaderboardEntry->m_bRequestedFriend = true; + } + + break; + } + } +#endif + } +#endif +} + +void UIScene_LeaderboardsMenu::PopulateLeaderboard(LeaderboardManager::eStatsReturn ret) +{ + int iValidSlots=SetLeaderboardTitleIcons(); + if( ret == LeaderboardManager::eStatsReturn_Success && m_leaderboard.m_totalEntryCount > 0 ) + { + m_listEntries.setupTitles( app.GetString( IDS_LEADERBOARD_RANK ), app.GetString( IDS_LEADERBOARD_GAMERTAG ) ); + + //Update entries display + wchar_t entriesBuffer[40]; + if(app.DebugSettingsOn() && (app.GetGameSettingsDebugMask()&(1L<<eDebugSetting_DebugLeaderboards))) + { + swprintf(entriesBuffer, 40, L"%ls12345678", app.GetString(IDS_LEADERBOARD_ENTRIES)); + } + else + { + swprintf(entriesBuffer, 40, L"%ls%i", app.GetString(IDS_LEADERBOARD_ENTRIES), m_leaderboard.m_totalEntryCount); + } + + m_labelEntries.setLabel(entriesBuffer); + m_labelInfo.setLabel(L""); + m_labelInfo.setVisible( false ); + + m_listEntries.initLeaderboard(m_newSel, m_leaderboard.m_totalEntryCount, LEADERBOARD_DESCRIPTORS[m_currentLeaderboard][m_currentDifficulty].m_columnCount); + + int startIndex = m_newEntryIndex; + int entryCount = m_newEntriesCount; + + for(DWORD i = startIndex; i < (startIndex + entryCount); ++i) + { + bool isLast = i == ((startIndex + entryCount) - 1); + + int idsErrorMessage = m_leaderboard.m_entries[i].m_idsErrorMessage; + + if (idsErrorMessage > 0) + { + m_listEntries.addDataSet( + isLast, + m_leaderboard.m_entries[i].m_row, + m_leaderboard.m_entries[i].m_rank, + m_leaderboard.m_entries[i].m_gamerTag, + + true, // 4J-JEV: Has error message to display. + + app.GetString(idsErrorMessage), + L"", L"", L"", L"", L"", L"" + ); + } + else + { + m_listEntries.addDataSet( + isLast, + m_leaderboard.m_entries[i].m_row, + m_leaderboard.m_entries[i].m_rank, + m_leaderboard.m_entries[i].m_gamerTag, + + // 4J-TomK | The bDisplayMessage Flag defines if Leaderboard Data should be + // displayed (false) or if a specific message (true - when data is private for example) + // should be displayed. The message itself should be passed on in col0! + false, + + m_leaderboard.m_entries[i].m_wcColumns[0], + m_leaderboard.m_entries[i].m_wcColumns[1], + m_leaderboard.m_entries[i].m_wcColumns[2], + m_leaderboard.m_entries[i].m_wcColumns[3], + m_leaderboard.m_entries[i].m_wcColumns[4], + m_leaderboard.m_entries[i].m_wcColumns[5], + m_leaderboard.m_entries[i].m_wcColumns[6] + ); + } + } + } + else + { + m_listEntries.setupTitles( L"", L"" ); + + //Update entries display (to zero) + wchar_t entriesBuffer[40]; + swprintf(entriesBuffer, 40, L"%ls0", app.GetString(IDS_LEADERBOARD_ENTRIES)); + m_labelEntries.setLabel(entriesBuffer); + + //Show the no results message +#if !(defined(_XBOX) || defined(_WINDOWS64)) // 4J Stu - Temp to get the win build running, but so we check this for other platforms + if (ret == LeaderboardManager::eStatsReturn_NetworkError) + m_labelInfo.setLabel(app.GetString(IDS_ERROR_NETWORK)); + else +#endif + m_labelInfo.setLabel(app.GetString(IDS_LEADERBOARD_NORESULTS)); + m_labelInfo.setVisible(true); + } + m_bPopulatedOnce = true; +} + +void UIScene_LeaderboardsMenu::SetLeaderboardHeader() +{ + m_labelLeaderboard.setLabel(app.GetString(LEADERBOARD_DESCRIPTORS[m_currentLeaderboard][m_currentDifficulty].m_title)); +} + +int UIScene_LeaderboardsMenu::SetLeaderboardTitleIcons() +{ + int iValidIcons=0; + + for(int i=0;i<7;i++) + { + if(TitleIcons[m_currentLeaderboard][i]==0) + { + //m_pHTitleIconSlots[i]->SetShow(FALSE); + } + else + { + iValidIcons++; + m_listEntries.setColumnIcon(i,TitleIcons[m_currentLeaderboard][i]); + } + } + + return iValidIcons; +} + +void UIScene_LeaderboardsMenu::customDraw(IggyCustomDrawCallbackRegion *region) +{ + int slotId = -1; + swscanf((wchar_t*)region->name,L"slot_%d",&slotId); + if (slotId == -1) + { + //app.DebugPrintf("This is not the control we are looking for\n"); + } + else + { + shared_ptr<ItemInstance> item = shared_ptr<ItemInstance>( new ItemInstance(TitleIcons[m_currentLeaderboard][slotId], 1, 0) ); + customDrawSlotControl(region,m_iPad,item,1.0f,false,false); + } +} + +void UIScene_LeaderboardsMenu::handleSelectionChanged(F64 selectedId) +{ + ui.PlayUISFX(eSFX_Focus); + m_newSel = (int)selectedId; + updateTooltips(); +} + +// Handle a request from Iggy for more data +void UIScene_LeaderboardsMenu::handleRequestMoreData(F64 startIndex, bool up) +{ + unsigned int item = (int)startIndex; + + if( m_leaderboard.m_totalEntryCount > 0 && (item+1) < GetEntryStartIndex() ) + { + if( LeaderboardManager::Instance()->isIdle() ) + { + int readIndex = (GetEntryStartIndex() + 1) - READ_SIZE; + if( readIndex <= 0 ) + readIndex = 1; + assert( readIndex >= 1 && readIndex <= (int)m_leaderboard.m_totalEntryCount ); + ReadStats(readIndex); + } + } + else if( m_leaderboard.m_totalEntryCount > 0 && (item+1) >= (GetEntryStartIndex() + m_leaderboard.m_entries.size()) ) + { + if( LeaderboardManager::Instance()->isIdle() ) + { + int readIndex = (GetEntryStartIndex() + 1) + m_leaderboard.m_entries.size(); + assert( readIndex >= 1 && readIndex <= (int)m_leaderboard.m_totalEntryCount ); + ReadStats(readIndex); + } + } +} + +void UIScene_LeaderboardsMenu::handleTimerComplete(int id) +{ +#if ( defined __PS3__ || defined __ORBIS__ || defined __PSVITA__) + switch(id) + { + case PLAYER_ONLINE_TIMER_ID: +#ifndef _WINDOWS64 + if(ProfileManager.IsSignedInLive(ProfileManager.GetPrimaryPad())==false) + { + // check the player hasn't gone offline + // If they have, bring up the PSN warning and exit from the leaderboards + unsigned int uiIDA[1]; + uiIDA[0]=IDS_OK; + C4JStorage::EMessageResult result = ui.RequestMessageBox( IDS_CONNECTION_LOST, g_NetworkManager.CorrectErrorIDS(IDS_CONNECTION_LOST_LIVE_NO_EXIT), uiIDA,1,ProfileManager.GetPrimaryPad(),UIScene_LeaderboardsMenu::ExitLeaderboards,this, app.GetStringTable()); + } +#endif + break; + } +#endif +} + +int UIScene_LeaderboardsMenu::ExitLeaderboards(void *pParam,int iPad,C4JStorage::EMessageResult result) +{ + UIScene_LeaderboardsMenu* pClass = (UIScene_LeaderboardsMenu*)pParam; + + pClass->navigateBack(); + + return 0; +} + +// Get entry start size, if no entries returns 0 +int UIScene_LeaderboardsMenu::GetEntryStartIndex() +{ + return m_leaderboard.m_entries.size() == 0 ? 0 : m_leaderboard.m_entries[0].m_row; +} diff --git a/Minecraft.Client/Common/UI/UIScene_LeaderboardsMenu.h b/Minecraft.Client/Common/UI/UIScene_LeaderboardsMenu.h new file mode 100644 index 00000000..20bf0002 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_LeaderboardsMenu.h @@ -0,0 +1,143 @@ +#pragma once + +#include "UIScene.h" +#include "..\Leaderboards\LeaderboardManager.h" + +class UIScene_LeaderboardsMenu : public UIScene, public LeaderboardReadListener +{ +private: + // 4J Stu - Because the kills leaderboard doesn't a peaceful entry there are some special + // handling to make it skip that. We have re-arranged the order of the leaderboards so + // I am making this in case we do it again. + // 4J Stu - Made it a member of the class, rather than a #define + static const int LEADERBOARD_KILLS_POSITION = 3; + + static const int NUM_LEADERBOARDS = 4;//6; //Number of leaderboards + static const int NUM_ENTRIES = 101; //Cache up to this many entries + static const int READ_SIZE = 15; //Read this many entries at a time + + struct LeaderboardDescriptor { + unsigned int m_columnCount; + bool m_isDistanceLeaderboard; + unsigned int m_title; + + LeaderboardDescriptor(unsigned int columnCount, bool isDistanceLeaderboard, unsigned int title) + { + m_columnCount = columnCount; + m_isDistanceLeaderboard = isDistanceLeaderboard; + m_title = title; + } + }; + + static const LeaderboardDescriptor LEADERBOARD_DESCRIPTORS[NUM_LEADERBOARDS][4]; + static const int TitleIcons[NUM_LEADERBOARDS][7]; + + struct LeaderboardEntry { + PlayerUID m_xuid; + unsigned int m_row; // Row identifier for passing to Iggy as a unique identifier + DWORD m_rank; + WCHAR m_wcRank[12]; + WCHAR m_gamerTag[XUSER_NAME_SIZE+1]; + //int m_locale; + unsigned int m_columns[7]; + WCHAR m_wcColumns[7][12]; + bool m_bPlayer; //Is the player + bool m_bOnline; //Is online + bool m_bFriend; //Is friend + bool m_bRequestedFriend; //Friend request sent but not answered + int m_idsErrorMessage; // 4J-JEV: Non-zero if this entry has an error message instead of results. + }; + + struct Leaderboard { + DWORD m_totalEntryCount; //Either total number of entries in leaderboard, or total number of results for a friends query + vector<LeaderboardEntry> m_entries; + DWORD m_numColumns; + }; + + Leaderboard m_leaderboard; //All leaderboard data for the currently selected filter + + unsigned int m_currentLeaderboard; //The current leaderboard selected for view + LeaderboardManager::EFilterMode m_currentFilter; //The current filter selected + unsigned int m_currentDifficulty; //The current difficulty selected + + unsigned int m_newEntryIndex; //Index of the first entry being read + unsigned int m_newReadSize; //Number of entries in the current read operation + + unsigned int m_newEntriesCount; // Number of new entries in this update + + int m_newTop; //Index of the element that should be at the top of the list + int m_newSel; //Index of the element that should be selected in the list + + bool m_isProcessingStatsRead; + bool m_bPopulatedOnce; + bool m_bReady; + + UIControl_LeaderboardList m_listEntries; + UIControl_Label m_labelFilter, m_labelLeaderboard, m_labelEntries, m_labelInfo; + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) + UI_MAP_ELEMENT( m_listEntries, "Gamers") + + UI_MAP_ELEMENT( m_labelFilter, "Filter") + UI_MAP_ELEMENT( m_labelLeaderboard, "Leaderboard") + UI_MAP_ELEMENT( m_labelEntries, "Entries") + UI_MAP_ELEMENT( m_labelInfo, "Info") + UI_END_MAP_ELEMENTS_AND_NAMES() + + static int ExitLeaderboards(void *pParam,int iPad,C4JStorage::EMessageResult result); + +public: + UIScene_LeaderboardsMenu(int iPad, void *initData, UILayer *parentLayer); + ~UIScene_LeaderboardsMenu(); + + virtual void updateTooltips(); + virtual void updateComponents(); + + virtual EUIScene getSceneType() { return eUIScene_LeaderboardsMenu;} + + // Returns true if this scene has focus for the pad passed in + virtual bool hasFocus(int iPad) { return bHasFocus; } + virtual void handleTimerComplete(int id); + +private: + int GetEntryStartIndex(); + +protected: + virtual wstring getMoviePath(); + +public: + void handleReload(); + + // INPUT + virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled); + +private: + //Start a read request with the current parameters + void ReadStats(int startIndex); + + //Copy the stats from the raw m_stats structure into the m_leaderboards structure + int m_numStats; + LeaderboardManager::ViewOut m_stats; + bool RetrieveStats(); + + // Copy a leaderboard entry from the stats row + void CopyLeaderboardEntry(LeaderboardManager::ReadScore *statsRow, int leaderboardEntryIndex, bool isDistanceLeaderboard); + + //Populate the XUI leaderboard with the contents of m_leaderboards + void PopulateLeaderboard(LeaderboardManager::eStatsReturn ret); + + //Set the header text of the leaderboard + void SetLeaderboardHeader(); + + // Set the title icons + int SetLeaderboardTitleIcons(); + + //Callback function called when stats read completes, userdata contains pointer to instance of CScene_Leaderboards + virtual bool OnStatsReadComplete(LeaderboardManager::eStatsReturn ret, int numResults, LeaderboardManager::ViewOut results); + + virtual void customDraw(IggyCustomDrawCallbackRegion *region); + + virtual void handleSelectionChanged(F64 selectedId); + virtual void handleRequestMoreData(F64 startIndex, bool up); + + bool m_bIgnoreInput; +}; diff --git a/Minecraft.Client/Common/UI/UIScene_LoadMenu.cpp b/Minecraft.Client/Common/UI/UIScene_LoadMenu.cpp new file mode 100644 index 00000000..f08fc727 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_LoadMenu.cpp @@ -0,0 +1,1804 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIScene_LoadMenu.h" +#include "..\..\Minecraft.h" +#include "..\..\TexturePackRepository.h" +#include "..\..\Options.h" +#include "..\..\MinecraftServer.h" +#include "..\..\..\Minecraft.World\LevelSettings.h" +#include "..\..\..\Minecraft.World\StringHelpers.h" +#if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__) +#include "Common\Network\Sony\SonyHttp.h" +#endif +#include "..\..\DLCTexturePack.h" +#if defined(__ORBIS__) || defined(__PSVITA__) +#include <ces.h> +#endif + +#define GAME_CREATE_ONLINE_TIMER_ID 0 +#define GAME_CREATE_ONLINE_TIMER_TIME 100 +// 4J-PB - Only Xbox will not have trial DLC patched into the game +#ifdef _XBOX +#define CHECKFORAVAILABLETEXTUREPACKS_TIMER_ID 1 +#define CHECKFORAVAILABLETEXTUREPACKS_TIMER_TIME 50 +#endif + +int UIScene_LoadMenu::m_iDifficultyTitleSettingA[4]= +{ + IDS_DIFFICULTY_TITLE_PEACEFUL, + IDS_DIFFICULTY_TITLE_EASY, + IDS_DIFFICULTY_TITLE_NORMAL, + IDS_DIFFICULTY_TITLE_HARD +}; + +int UIScene_LoadMenu::LoadSaveDataThumbnailReturned(LPVOID lpParam,PBYTE pbThumbnail,DWORD dwThumbnailBytes) +{ + UIScene_LoadMenu *pClass= (UIScene_LoadMenu *)lpParam; + + app.DebugPrintf("Received data for a thumbnail\n"); + + if(pbThumbnail && dwThumbnailBytes) + { + pClass->registerSubstitutionTexture(pClass->m_thumbnailName,pbThumbnail,dwThumbnailBytes); + + pClass->m_pbThumbnailData = pbThumbnail; + pClass->m_uiThumbnailSize = dwThumbnailBytes; + pClass->m_bSaveThumbnailReady = true; + } + else + { + app.DebugPrintf("Thumbnail data is NULL, or has size 0\n"); + pClass->m_bThumbnailGetFailed = true; + } + pClass->m_bRetrievingSaveThumbnail = false; + + return 0; +} + +UIScene_LoadMenu::UIScene_LoadMenu(int iPad, void *initData, UILayer *parentLayer) : IUIScene_StartGame(iPad, parentLayer) +{ + // Setup all the Iggy references we need for this scene + initialiseMovie(); + + LoadMenuInitData *params = (LoadMenuInitData *)initData; + + //m_labelGameName.init(app.GetString(IDS_WORLD_NAME)); + m_labelSeed.init(L""); + m_labelCreatedMode.init(app.GetString(IDS_CREATED_IN_SURVIVAL)); + + m_buttonGamemode.init(app.GetString(IDS_GAMEMODE_SURVIVAL),eControl_GameMode); + m_buttonMoreOptions.init(app.GetString(IDS_MORE_OPTIONS),eControl_MoreOptions); + m_buttonLoadWorld.init(app.GetString(IDS_LOAD),eControl_LoadWorld); + m_texturePackList.init(app.GetString(IDS_DLC_MENU_TEXTUREPACKS), eControl_TexturePackList); + + m_labelTexturePackName.init(L""); + m_labelTexturePackDescription.init(L""); + + m_CurrentDifficulty=app.GetGameSettings(m_iPad,eGameSetting_Difficulty); + WCHAR TempString[256]; + swprintf( (WCHAR *)TempString, 256, L"%ls: %ls", app.GetString( IDS_SLIDER_DIFFICULTY ),app.GetString(m_iDifficultyTitleSettingA[app.GetGameSettings(m_iPad,eGameSetting_Difficulty)])); + m_sliderDifficulty.init(TempString,eControl_Difficulty,0,3,app.GetGameSettings(m_iPad,eGameSetting_Difficulty)); + + m_MoreOptionsParams.bGenerateOptions=FALSE; + m_MoreOptionsParams.bPVP = TRUE; + m_MoreOptionsParams.bTrust = TRUE; + m_MoreOptionsParams.bFireSpreads = TRUE; + m_MoreOptionsParams.bHostPrivileges = FALSE; + m_MoreOptionsParams.bTNT = TRUE; + m_MoreOptionsParams.iPad = iPad; + + m_iSaveGameInfoIndex=params->iSaveGameInfoIndex; + m_levelGen = params->levelGen; + + m_bGameModeSurvival=true; + m_bHasBeenInCreative = false; + + m_bSaveThumbnailReady = false; + m_bRetrievingSaveThumbnail = true; + m_bShowTimer = false; + m_pDLCPack = NULL; + m_bAvailableTexturePacksChecked=false; + m_bRequestQuadrantSignin = false; + m_iTexturePacksNotInstalled=0; + m_bRebuildTouchBoxes = false; + m_bThumbnailGetFailed = false; + m_seed = 0; + + m_bMultiplayerAllowed = ProfileManager.IsSignedInLive( m_iPad ) && ProfileManager.AllowedToPlayMultiplayer(m_iPad); + // 4J-PB - read the settings for the online flag. We'll only save this setting if the user changed it. + bool bGameSetting_Online=(app.GetGameSettings(m_iPad,eGameSetting_Online)!=0); + m_MoreOptionsParams.bOnlineSettingChangedBySystem=false; + + // Set the text for friends of friends, and default to on + if( m_bMultiplayerAllowed) + { + m_MoreOptionsParams.bOnlineGame = bGameSetting_Online?TRUE:FALSE; + if(bGameSetting_Online) + { + m_MoreOptionsParams.bInviteOnly = (app.GetGameSettings(m_iPad,eGameSetting_InviteOnly)!=0)?TRUE:FALSE; + m_MoreOptionsParams.bAllowFriendsOfFriends = (app.GetGameSettings(m_iPad,eGameSetting_FriendsOfFriends)!=0)?TRUE:FALSE; + } + else + { + m_MoreOptionsParams.bInviteOnly = FALSE; + m_MoreOptionsParams.bAllowFriendsOfFriends = FALSE; + } + } + else + { + m_MoreOptionsParams.bOnlineGame = FALSE; + m_MoreOptionsParams.bInviteOnly = FALSE; + m_MoreOptionsParams.bAllowFriendsOfFriends = FALSE; + if(bGameSetting_Online) + { + // The profile settings say Online, but either the player is offline, or they are not allowed to play online + m_MoreOptionsParams.bOnlineSettingChangedBySystem=true; + } + } + + +#if defined _XBOX_ONE || defined __ORBIS__ || defined _WINDOWS64 + if(getSceneResolution() == eSceneResolution_1080) + { + // Set up online game checkbox + bool bOnlineGame = m_MoreOptionsParams.bOnlineGame; + m_checkboxOnline.SetEnable(true); + + // 4J-PB - to stop an offline game being able to select the online flag + if(ProfileManager.IsSignedInLive(m_iPad) == false) + { + m_checkboxOnline.SetEnable(false); + } + + if(m_MoreOptionsParams.bOnlineSettingChangedBySystem) + { + m_checkboxOnline.SetEnable(false); + bOnlineGame = false; + } + + m_checkboxOnline.init(app.GetString(IDS_ONLINE_GAME), eControl_OnlineGame, bOnlineGame); + } +#endif + + // Level gen + if(m_levelGen) + { + m_labelGameName.init(m_levelGen->getDisplayName()); + if(m_levelGen->requiresTexturePack()) + { + m_MoreOptionsParams.dwTexturePack = m_levelGen->getRequiredTexturePackId(); + + m_texturePackList.setEnabled(false); + + + // retrieve the save icon from the texture pack, if there is one + TexturePack *tp = Minecraft::GetInstance()->skins->getTexturePackById(m_MoreOptionsParams.dwTexturePack); + DWORD dwImageBytes; + PBYTE pbImageData = tp->getPackIcon(dwImageBytes); + + if(dwImageBytes > 0 && pbImageData) + { + wchar_t textureName[64]; + swprintf(textureName,64,L"loadsave"); + registerSubstitutionTexture(textureName,pbImageData,dwImageBytes); + m_bitmapIcon.setTextureName( textureName ); + } + } + // Set this level as created in creative mode, so that people can't use the themed worlds as an easy way to get achievements + m_bHasBeenInCreative = true; + m_labelCreatedMode.setLabel( app.GetString(IDS_CREATED_IN_CREATIVE) ); + } + else + { + +#if defined(__PS3__) || defined(__ORBIS__)|| defined(_DURANGO) || defined (__PSVITA__) + // convert to utf16 + uint16_t u16Message[MAX_SAVEFILENAME_LENGTH]; + size_t srclen,dstlen; + srclen=MAX_SAVEFILENAME_LENGTH; + dstlen=MAX_SAVEFILENAME_LENGTH; +#ifdef __PS3__ + L10nResult lres= UTF8stoUTF16s((uint8_t *)params->saveDetails->UTF8SaveFilename,&srclen,u16Message,&dstlen); +#elif defined(_DURANGO) + // Already utf16 on durango + memcpy(u16Message,params->saveDetails->UTF16SaveFilename, MAX_SAVEFILENAME_LENGTH); +#else // __ORBIS__ + { + SceCesUcsContext Context; + sceCesUcsContextInit( &Context ); + uint32_t utf8Len, utf16Len; + sceCesUtf8StrToUtf16Str(&Context, (uint8_t *)params->saveDetails->UTF8SaveFilename, srclen, &utf8Len, u16Message, dstlen, &utf16Len); + } +#endif + m_thumbnailName = (wchar_t *)u16Message; + if(params->saveDetails->pbThumbnailData) + { + m_pbThumbnailData = params->saveDetails->pbThumbnailData; + m_uiThumbnailSize = params->saveDetails->dwThumbnailSize; + m_bSaveThumbnailReady = true; + } + else + { + app.DebugPrintf("Requesting the save thumbnail\n"); + // set the save to load + PSAVE_DETAILS pSaveDetails=StorageManager.ReturnSavesInfo(); +#ifdef _DURANGO + // On Durango, we have an extra flag possible with LoadSaveDataThumbnail, which if true will force the loading of this thumbnail even if the save data isn't sync'd from + // the cloud at this stage. This could mean that there could be a pretty large delay before the callback happens, in this case. + C4JStorage::ESaveGameState eLoadStatus=StorageManager.LoadSaveDataThumbnail(&pSaveDetails->SaveInfoA[(int)m_iSaveGameInfoIndex],&LoadSaveDataThumbnailReturned,this,true); +#else + C4JStorage::ESaveGameState eLoadStatus=StorageManager.LoadSaveDataThumbnail(&pSaveDetails->SaveInfoA[(int)m_iSaveGameInfoIndex],&LoadSaveDataThumbnailReturned,this); +#endif + m_bShowTimer = true; + } +#if defined(_DURANGO) + m_labelGameName.init(params->saveDetails->UTF16SaveName); +#else + + m_labelGameName.init(params->saveDetails->UTF8SaveName); +#endif +#endif + } + + TelemetryManager->RecordMenuShown(m_iPad, eUIScene_LoadMenu, 0); + m_iTexturePacksNotInstalled=0; + + // block input if we're waiting for DLC to install, and wipe the saves list. The end of dlc mounting custom message will fill the list again + if(app.StartInstallDLCProcess(m_iPad)==true) + { + // not doing a mount, so enable input + m_bIgnoreInput=true; + } + else + { + m_bIgnoreInput = false; + + Minecraft *pMinecraft = Minecraft::GetInstance(); + int texturePacksCount = pMinecraft->skins->getTexturePackCount(); + for(unsigned int i = 0; i < texturePacksCount; ++i) + { + TexturePack *tp = pMinecraft->skins->getTexturePackByIndex(i); + + DWORD dwImageBytes; + PBYTE pbImageData = tp->getPackIcon(dwImageBytes); + + if(dwImageBytes > 0 && pbImageData) + { + wchar_t imageName[64]; + swprintf(imageName,64,L"tpack%08x",tp->getId()); + registerSubstitutionTexture(imageName, pbImageData, dwImageBytes); + m_texturePackList.addPack(i,imageName); + } + } + m_currentTexturePackIndex = pMinecraft->skins->getTexturePackIndex(m_MoreOptionsParams.dwTexturePack); + UpdateTexturePackDescription(m_currentTexturePackIndex); + m_texturePackList.selectSlot(m_currentTexturePackIndex); + + // 4J-PB - Only Xbox will not have trial DLC patched into the game +#ifdef _XBOX + // 4J-PB - there may be texture packs we don't have, so use the info from TMS for this + + // 4J-PB - Any texture packs available that we don't have installed? +#if defined(__PS3__) || defined(__ORBIS__) + if(!m_bAvailableTexturePacksChecked && app.GetCommerceProductListRetrieved()&& app.GetCommerceProductListInfoRetrieved()) +#else + if(!m_bAvailableTexturePacksChecked) +#endif + { + DLC_INFO *pDLCInfo=NULL; + + // first pass - look to see if there are any that are not in the list + bool bTexturePackAlreadyListed; + bool bNeedToGetTPD=false; + + for(unsigned int i = 0; i < app.GetDLCInfoTexturesOffersCount(); ++i) + { + bTexturePackAlreadyListed=false; +#if defined(__PS3__) || defined(__ORBIS__) + char *pchName=app.GetDLCInfoTextures(i); + pDLCInfo=app.GetDLCInfo(pchName); +#else + ULONGLONG ull=app.GetDLCInfoTexturesFullOffer(i); + pDLCInfo=app.GetDLCInfoForFullOfferID(ull); +#endif + + for(unsigned int i = 0; i < texturePacksCount; ++i) + { + TexturePack *tp = pMinecraft->skins->getTexturePackByIndex(i); + if(pDLCInfo && pDLCInfo->iConfig==tp->getDLCParentPackId()) + { + bTexturePackAlreadyListed=true; + } + } + if(bTexturePackAlreadyListed==false) + { + // some missing + bNeedToGetTPD=true; + + m_iTexturePacksNotInstalled++; + } + } + + if(bNeedToGetTPD==true) + { + // add a TMS request for them + app.DebugPrintf("+++ Adding TMSPP request for texture pack data\n"); + app.AddTMSPPFileTypeRequest(e_DLC_TexturePackData); + m_iConfigA= new int [m_iTexturePacksNotInstalled]; + m_iTexturePacksNotInstalled=0; + + for(unsigned int i = 0; i < app.GetDLCInfoTexturesOffersCount(); ++i) + { + bTexturePackAlreadyListed=false; +#if defined(__PS3__) || defined(__ORBIS__) + char *pchName=app.GetDLCInfoTextures(i); + pDLCInfo=app.GetDLCInfo(pchName); +#else + ULONGLONG ull=app.GetDLCInfoTexturesFullOffer(i); + pDLCInfo=app.GetDLCInfoForFullOfferID(ull); +#endif + + if(pDLCInfo) + { + for(unsigned int i = 0; i < texturePacksCount; ++i) + { + TexturePack *tp = pMinecraft->skins->getTexturePackByIndex(i); + if(pDLCInfo && pDLCInfo->iConfig==tp->getDLCParentPackId()) + { + bTexturePackAlreadyListed=true; + } + } + if(bTexturePackAlreadyListed==false) + { + m_iConfigA[m_iTexturePacksNotInstalled++]=pDLCInfo->iConfig; + } + } + } + } + } +#endif + } + +#ifdef _XBOX + addTimer(CHECKFORAVAILABLETEXTUREPACKS_TIMER_ID,CHECKFORAVAILABLETEXTUREPACKS_TIMER_TIME); +#endif + + if(params) delete params; + addTimer(GAME_CREATE_ONLINE_TIMER_ID,GAME_CREATE_ONLINE_TIMER_TIME); +} + +void UIScene_LoadMenu::updateTooltips() +{ + ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK, -1, -1); +} + +void UIScene_LoadMenu::updateComponents() +{ + m_parentLayer->showComponent(m_iPad,eUIComponent_Panorama,true); + + if(RenderManager.IsWidescreen()) + { + m_parentLayer->showComponent(m_iPad,eUIComponent_Logo,true); + } + else + { + m_parentLayer->showComponent(m_iPad,eUIComponent_Logo,false); + } +} + +wstring UIScene_LoadMenu::getMoviePath() +{ + return L"LoadMenu"; +} + +UIControl* UIScene_LoadMenu::GetMainPanel() +{ + return &m_controlMainPanel; +} + +void UIScene_LoadMenu::tick() +{ + if(m_bShowTimer) + { + m_bShowTimer = false; + ui.NavigateToScene(m_iPad, eUIScene_Timer); + } + + if( m_bThumbnailGetFailed ) + { + // On Durango, this can happen if a save is still not been synchronised (user cancelled, or some error). Return back to give them a choice to pick another save. + ui.NavigateBack(m_iPad, false, eUIScene_LoadOrJoinMenu); + return; + } + + if( m_bSaveThumbnailReady ) + { + m_bSaveThumbnailReady = false; + + m_bitmapIcon.setTextureName( m_thumbnailName.c_str() ); + + // retrieve the seed value from the image metadata + bool bHostOptionsRead = false; + unsigned int uiHostOptions = 0; + + char szSeed[50]; + ZeroMemory(szSeed,50); + app.GetImageTextData(m_pbThumbnailData,m_uiThumbnailSize,(unsigned char *)&szSeed,uiHostOptions,bHostOptionsRead,m_MoreOptionsParams.dwTexturePack); + +#if defined(_XBOX_ONE) || defined(__ORBIS__) + sscanf_s(szSeed, "%I64d", &m_seed); +#endif + + // #ifdef _DEBUG + // // dump out the thumbnail + // HANDLE hThumbnail = CreateFile("GAME:\\thumbnail.png", GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_FLAG_RANDOM_ACCESS, NULL); + // DWORD dwBytes; + // WriteFile(hThumbnail,pbImageData,dwImageBytes,&dwBytes,NULL); + // XCloseHandle(hThumbnail); + // #endif + + if(szSeed[0]!=0) + { + WCHAR TempString[256]; + swprintf( (WCHAR *)TempString, 256, L"%ls: %hs", app.GetString( IDS_SEED ),szSeed); + m_labelSeed.setLabel(TempString); + } + else + { + m_labelSeed.setLabel(L""); + } + + // Setup all the text and checkboxes to match what the game was saved with on + if(bHostOptionsRead) + { + m_MoreOptionsParams.bPVP = app.GetGameHostOption(uiHostOptions,eGameHostOption_PvP)>0?TRUE:FALSE; + m_MoreOptionsParams.bTrust = app.GetGameHostOption(uiHostOptions,eGameHostOption_TrustPlayers)>0?TRUE:FALSE; + m_MoreOptionsParams.bFireSpreads = app.GetGameHostOption(uiHostOptions,eGameHostOption_FireSpreads)>0?TRUE:FALSE; + m_MoreOptionsParams.bTNT = app.GetGameHostOption(uiHostOptions,eGameHostOption_TNT)>0?TRUE:FALSE; + m_MoreOptionsParams.bHostPrivileges = app.GetGameHostOption(uiHostOptions,eGameHostOption_CheatsEnabled)>0?TRUE:FALSE; + m_MoreOptionsParams.bDisableSaving = app.GetGameHostOption(uiHostOptions,eGameHostOption_DisableSaving)>0?TRUE:FALSE; + + // turn off creative mode on the save + // #ifdef _DEBUG + // uiHostOptions&=~GAME_HOST_OPTION_BITMASK_BEENINCREATIVE; + // app.SetGameHostOption(eGameHostOption_HasBeenInCreative, 0); + // #endif + + m_bHasBeenInCreative = app.GetGameHostOption(uiHostOptions,eGameHostOption_HasBeenInCreative)>0; + if(app.GetGameHostOption(uiHostOptions,eGameHostOption_HasBeenInCreative)>0) + { + m_labelCreatedMode.setLabel( app.GetString(IDS_CREATED_IN_CREATIVE) ); + } + else + { + m_labelCreatedMode.setLabel( app.GetString(IDS_CREATED_IN_SURVIVAL) ); + } + + if(app.GetGameHostOption(uiHostOptions,eGameHostOption_GameType)>0) + { + m_buttonGamemode.setLabel(app.GetString(IDS_GAMEMODE_CREATIVE)); + m_bGameModeSurvival=false; + } + + bool bGameSetting_Online=(app.GetGameSettings(m_iPad,eGameSetting_Online)!=0); + if(app.GetGameHostOption(uiHostOptions,eGameHostOption_FriendsOfFriends) && !(m_bMultiplayerAllowed && bGameSetting_Online)) + { + m_MoreOptionsParams.bAllowFriendsOfFriends = TRUE; + } + } + + Minecraft *pMinecraft = Minecraft::GetInstance(); + m_currentTexturePackIndex = pMinecraft->skins->getTexturePackIndex(m_MoreOptionsParams.dwTexturePack); + + UpdateTexturePackDescription(m_currentTexturePackIndex); + + m_texturePackList.selectSlot(m_currentTexturePackIndex); + + //m_labelGameName.setLabel(m_XContentData.szDisplayName); + + ui.NavigateBack(m_iPad, false, getSceneType() ); + } + + if(m_iSetTexturePackDescription >= 0 ) + { + UpdateTexturePackDescription( m_iSetTexturePackDescription ); + m_iSetTexturePackDescription = -1; + } + if(m_bShowTexturePackDescription) + { + slideLeft(); + m_texturePackDescDisplayed = true; + + m_bShowTexturePackDescription = false; + } + + if(m_bRequestQuadrantSignin) + { + m_bRequestQuadrantSignin = false; + SignInInfo info; + info.Func = &UIScene_LoadMenu::StartGame_SignInReturned; + info.lpParam = this; + info.requireOnline = m_MoreOptionsParams.bOnlineGame; + ui.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_QuadrantSignin,&info); + } + +#ifdef __ORBIS__ + // check the status of the PSPlus common dialog + switch (sceNpCommerceDialogUpdateStatus()) + { + case SCE_COMMON_DIALOG_STATUS_FINISHED: + { + SceNpCommerceDialogResult Result; + sceNpCommerceDialogGetResult(&Result); + sceNpCommerceDialogTerminate(); + + if(Result.authorized) + { + ProfileManager.PsPlusUpdate(ProfileManager.GetPrimaryPad(), &Result); + // they just became a PSPlus member + LoadDataComplete(this); + } + else + { + // continue offline? + UINT uiIDA[1]; + uiIDA[0]=IDS_PRO_NOTONLINE_DECLINE; + + // Give the player a warning about the texture pack missing + ui.RequestMessageBox(IDS_PLAY_OFFLINE,IDS_NO_PLAYSTATIONPLUS, uiIDA, 1, ProfileManager.GetPrimaryPad(),&UIScene_LoadMenu::ContinueOffline,this,app.GetStringTable(), 0, 0, false); + } + } + break; + default: + break; + } +#endif + + UIScene::tick(); +} + +#ifdef __ORBIS__ +int UIScene_LoadMenu::ContinueOffline(void *pParam,int iPad,C4JStorage::EMessageResult result) +{ + UIScene_LoadMenu* pClass = (UIScene_LoadMenu*)pParam; + + // results switched for this dialog + if(result==C4JStorage::EMessage_ResultAccept) + { + pClass->m_MoreOptionsParams.bOnlineGame=false; + pClass->LoadDataComplete(pClass); + } + return 0; +} + +#endif + +void UIScene_LoadMenu::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled) +{ + if(m_bIgnoreInput) return; + + ui.AnimateKeyPress(m_iPad, key, repeat, pressed, released); + + switch(key) + { + case ACTION_MENU_CANCEL: + if(pressed) + { + app.SetCorruptSaveDeleted(false); + navigateBack(); + handled = true; + } + break; + case ACTION_MENU_OK: +#ifdef __ORBIS__ + case ACTION_MENU_TOUCHPAD_PRESS: +#endif + + // 4J-JEV: Inform user why their game must be offline. +#if defined _XBOX_ONE + if ( pressed && controlHasFocus(m_checkboxOnline.getId()) && !m_checkboxOnline.IsEnabled() ) + { + UINT uiIDA[1] = { IDS_CONFIRM_OK }; + ui.RequestMessageBox(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_XBOXLIVE_NOTIFICATION, uiIDA, 1, iPad, NULL, NULL, app.GetStringTable()); + } +#endif + + case ACTION_MENU_UP: + case ACTION_MENU_DOWN: + case ACTION_MENU_LEFT: + case ACTION_MENU_RIGHT: + case ACTION_MENU_OTHER_STICK_UP: + case ACTION_MENU_OTHER_STICK_DOWN: + sendInputToMovie(key, repeat, pressed, released); + +#if defined _XBOX_ONE || defined __ORBIS__ || defined _WINDOWS64 + if(getSceneResolution() == eSceneResolution_1080) + { + bool bOnlineGame = m_checkboxOnline.IsChecked(); + if (m_MoreOptionsParams.bOnlineGame != bOnlineGame) + { + m_MoreOptionsParams.bOnlineGame = bOnlineGame; + + if (!m_MoreOptionsParams.bOnlineGame) + { + m_MoreOptionsParams.bInviteOnly = false; + m_MoreOptionsParams.bAllowFriendsOfFriends = false; + } + } + } +#endif + handled = true; + break; + } +} + +void UIScene_LoadMenu::handlePress(F64 controlId, F64 childId) +{ + if(m_bIgnoreInput) return; + + //CD - Added for audio + ui.PlayUISFX(eSFX_Press); + + switch((int)controlId) + { + case eControl_GameMode: + if(m_bGameModeSurvival) + { + m_buttonGamemode.setLabel(app.GetString(IDS_GAMEMODE_CREATIVE)); + m_bGameModeSurvival=false; + } + else + { + m_buttonGamemode.setLabel(app.GetString(IDS_GAMEMODE_SURVIVAL)); + m_bGameModeSurvival=true; + } + break; + case eControl_MoreOptions: + ui.NavigateToScene(m_iPad, eUIScene_LaunchMoreOptionsMenu, &m_MoreOptionsParams); + break; + case eControl_TexturePackList: + { + UpdateCurrentTexturePack((int)childId); + } + break; + case eControl_LoadWorld: + { +#ifdef _DURANGO + if(m_MoreOptionsParams.bOnlineGame) + { + m_bIgnoreInput = true; + ProfileManager.CheckMultiplayerPrivileges(m_iPad, true, &checkPrivilegeCallback, this); + } + else +#endif + { + StartSharedLaunchFlow(); + } + } + break; + }; +} + +#ifdef _DURANGO +void UIScene_LoadMenu::checkPrivilegeCallback(LPVOID lpParam, bool hasPrivilege, int iPad) +{ + UIScene_LoadMenu* pClass = (UIScene_LoadMenu*)lpParam; + + if(hasPrivilege) + { + pClass->StartSharedLaunchFlow(); + } + else + { + pClass->m_bIgnoreInput = false; + } +} +#endif + +void UIScene_LoadMenu::StartSharedLaunchFlow() +{ + Minecraft *pMinecraft=Minecraft::GetInstance(); + // Check if we need to upsell the texture pack + if(m_MoreOptionsParams.dwTexturePack!=0) + { + // texture pack hasn't been set yet, so check what it will be + TexturePack *pTexturePack = pMinecraft->skins->getTexturePackById(m_MoreOptionsParams.dwTexturePack); + + if(pTexturePack==NULL) + { +#if TO_BE_IMPLEMENTED + // They've selected a texture pack they don't have yet + // upsell + CXuiCtrl4JList::LIST_ITEM_INFO ListItem; + // get the current index of the list, and then get the data + ListItem=m_pTexturePacksList->GetData(m_currentTexturePackIndex); + + + // upsell the texture pack + // tell sentient about the upsell of the full version of the skin pack + ULONGLONG ullOfferID_Full; + app.GetDLCFullOfferIDForPackID(m_MoreOptionsParams.dwTexturePack,&ullOfferID_Full); + + TelemetryManager->RecordUpsellPresented(ProfileManager.GetPrimaryPad(), eSet_UpsellID_Texture_DLC, ullOfferID_Full & 0xFFFFFFFF); +#endif + + UINT uiIDA[2]; + + uiIDA[0]=IDS_TEXTUREPACK_FULLVERSION; + //uiIDA[1]=IDS_TEXTURE_PACK_TRIALVERSION; + uiIDA[1]=IDS_CONFIRM_CANCEL; + + // Give the player a warning about the texture pack missing + ui.RequestMessageBox(IDS_DLC_TEXTUREPACK_NOT_PRESENT_TITLE, IDS_DLC_TEXTUREPACK_NOT_PRESENT, uiIDA, 2, ProfileManager.GetPrimaryPad(),&TexturePackDialogReturned,this,app.GetStringTable(),NULL,0,false); + return; + } + } + m_bIgnoreInput = true; + + // if the profile data has been changed, then force a profile write (we save the online/invite/friends of friends settings) + // It seems we're allowed to break the 5 minute rule if it's the result of a user action + // check the checkboxes + + // Only save the online setting if the user changed it - we may change it because we're offline, but don't want that saved + if(!m_MoreOptionsParams.bOnlineSettingChangedBySystem) + { + app.SetGameSettings(m_iPad,eGameSetting_Online,m_MoreOptionsParams.bOnlineGame?1:0); + } + app.SetGameSettings(m_iPad,eGameSetting_InviteOnly,m_MoreOptionsParams.bInviteOnly?1:0); + app.SetGameSettings(m_iPad,eGameSetting_FriendsOfFriends,m_MoreOptionsParams.bAllowFriendsOfFriends?1:0); + + app.CheckGameSettingsChanged(true,m_iPad); + + // Check that we have the rights to use a texture pack we have selected. + if(m_MoreOptionsParams.dwTexturePack!=0) + { + // texture pack hasn't been set yet, so check what it will be + TexturePack *pTexturePack = pMinecraft->skins->getTexturePackById(m_MoreOptionsParams.dwTexturePack); + DLCTexturePack *pDLCTexPack=(DLCTexturePack *)pTexturePack; + m_pDLCPack=pDLCTexPack->getDLCInfoParentPack(); + + // do we have a license? + if(m_pDLCPack && !m_pDLCPack->hasPurchasedFile( DLCManager::e_DLCType_Texture, L"" )) + { + // no + + // We need to allow people to use a trial texture pack if they are offline - we only need them online if they want to buy it. + + /* + UINT uiIDA[1]; + uiIDA[0]=IDS_OK; + + if(!ProfileManager.IsSignedInLive(m_iPad)) + { + // need to be signed in to live + ui.RequestMessageBox(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_XBOXLIVE_NOTIFICATION, uiIDA, 1); + m_bIgnoreInput = false; + return; + } + else */ + { + // upsell +#ifdef _XBOX + DLC_INFO *pDLCInfo = app.GetDLCInfoForTrialOfferID(m_pDLCPack->getPurchaseOfferId()); + ULONGLONG ullOfferID_Full; + + if(pDLCInfo!=NULL) + { + ullOfferID_Full=pDLCInfo->ullOfferID_Full; + } + else + { + ullOfferID_Full=pTexturePack->getDLCPack()->getPurchaseOfferId(); + } + + // tell sentient about the upsell of the full version of the texture pack + TelemetryManager->RecordUpsellPresented(m_iPad, eSet_UpsellID_Texture_DLC, ullOfferID_Full & 0xFFFFFFFF); +#endif + +#if defined(_WINDOWS64) || defined(_DURANGO) + // trial pack warning + UINT uiIDA[1]; + uiIDA[0]=IDS_CONFIRM_OK; + ui.RequestMessageBox(IDS_WARNING_DLC_TRIALTEXTUREPACK_TITLE, IDS_USING_TRIAL_TEXUREPACK_WARNING, uiIDA, 1, m_iPad,&TrialTexturePackWarningReturned,this,app.GetStringTable(),NULL,0,false); +#elif defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__) + // trial pack warning + UINT uiIDA[2]; + uiIDA[0]=IDS_CONFIRM_OK; + uiIDA[1]=IDS_CONFIRM_CANCEL; + ui.RequestMessageBox(IDS_WARNING_DLC_TRIALTEXTUREPACK_TITLE, IDS_USING_TRIAL_TEXUREPACK_WARNING, uiIDA, 2, m_iPad,&TrialTexturePackWarningReturned,this,app.GetStringTable(),NULL,0,false); +#endif + +#if defined _XBOX_ONE || defined __ORBIS__ + StorageManager.SetSaveDisabled(true); +#endif + return; + } + } + } + +#if defined _XBOX_ONE || defined __ORBIS__ + app.SetGameHostOption(eGameHostOption_DisableSaving, m_MoreOptionsParams.bDisableSaving?1:0); + + StorageManager.SetSaveDisabled(m_MoreOptionsParams.bDisableSaving); +#endif + +#if TO_BE_IMPLEMENTED + // Reset the background downloading, in case we changed it by attempting to download a texture pack + XBackgroundDownloadSetMode(XBACKGROUND_DOWNLOAD_MODE_AUTO); +#endif + + // Check if they have the Reset Nether flag set, and confirm they want to do this + if(m_MoreOptionsParams.bResetNether==TRUE) + { + UINT uiIDA[2]; + uiIDA[0]=IDS_DONT_RESET_NETHER; + uiIDA[1]=IDS_RESET_NETHER; + + ui.RequestMessageBox(IDS_RESETNETHER_TITLE, IDS_RESETNETHER_TEXT, uiIDA, 2, m_iPad,&UIScene_LoadMenu::CheckResetNetherReturned,this,app.GetStringTable(),NULL,0,false); + } + else + { + LaunchGame(); + } +} + +void UIScene_LoadMenu::handleSliderMove(F64 sliderId, F64 currentValue) +{ + WCHAR TempString[256]; + int value = (int)currentValue; + switch((int)sliderId) + { + case eControl_Difficulty: + m_sliderDifficulty.handleSliderMove(value); + + app.SetGameSettings(m_iPad,eGameSetting_Difficulty,value); + swprintf( (WCHAR *)TempString, 256, L"%ls: %ls", app.GetString( IDS_SLIDER_DIFFICULTY ),app.GetString(m_iDifficultyTitleSettingA[value])); + m_sliderDifficulty.setLabel(TempString); + break; + } +} + +void UIScene_LoadMenu::handleTouchBoxRebuild() +{ + m_bRebuildTouchBoxes = true; +} + + +void UIScene_LoadMenu::handleTimerComplete(int id) +{ +#ifdef __PSVITA__ + // we cannot rebuild touch boxes in an iggy callback because it requires further iggy calls + if(m_bRebuildTouchBoxes) + { + GetMainPanel()->UpdateControl(); + ui.TouchBoxRebuild(this); + m_bRebuildTouchBoxes = false; + } +#endif + + switch(id) + { + case GAME_CREATE_ONLINE_TIMER_ID: + { + bool bMultiplayerAllowed = ProfileManager.IsSignedInLive( m_iPad ) && ProfileManager.AllowedToPlayMultiplayer(m_iPad); + + if(bMultiplayerAllowed != m_bMultiplayerAllowed) + { + if( bMultiplayerAllowed ) + { + bool bGameSetting_Online=(app.GetGameSettings(m_iPad,eGameSetting_Online)!=0); + m_MoreOptionsParams.bOnlineGame = bGameSetting_Online?TRUE:FALSE; + if(bGameSetting_Online) + { + m_MoreOptionsParams.bInviteOnly = (app.GetGameSettings(m_iPad,eGameSetting_InviteOnly)!=0)?TRUE:FALSE; + m_MoreOptionsParams.bAllowFriendsOfFriends = (app.GetGameSettings(m_iPad,eGameSetting_FriendsOfFriends)!=0)?TRUE:FALSE; + } + else + { + m_MoreOptionsParams.bInviteOnly = FALSE; + m_MoreOptionsParams.bAllowFriendsOfFriends = FALSE; + } + } + else + { + m_MoreOptionsParams.bOnlineGame = FALSE; + m_MoreOptionsParams.bInviteOnly = FALSE; + m_MoreOptionsParams.bAllowFriendsOfFriends = FALSE; + } +#if defined _XBOX_ONE || defined __ORBIS__ || defined _WINDOWS64 + if(getSceneResolution() == eSceneResolution_1080) + { + m_checkboxOnline.SetEnable(bMultiplayerAllowed); + m_checkboxOnline.setChecked(m_MoreOptionsParams.bOnlineGame); + } +#endif + + m_bMultiplayerAllowed = bMultiplayerAllowed; + } + } + break; + // 4J-PB - Only Xbox will not have trial DLC patched into the game +#ifdef _XBOX + case CHECKFORAVAILABLETEXTUREPACKS_TIMER_ID: + { + +#if defined(__PS3__) || defined(__ORBIS__) + for(int i=0;i<m_iTexturePacksNotInstalled;i++) + { + if(m_iConfigA[i]!=-1) + { + DLC_INFO *pDLCInfo=app.GetDLCInfoFromTPackID(m_iConfigA[i]); + + if(pDLCInfo) + { + // retrieve the image - if we haven't already + wstring textureName = filenametowstring(pDLCInfo->chImageURL); + + if(hasRegisteredSubstitutionTexture(textureName)==false) + { + PBYTE pbImageData; + int iImageDataBytes=0; + SonyHttp::getDataFromURL(pDLCInfo->chImageURL,(void **)&pbImageData,&iImageDataBytes); + + if(iImageDataBytes!=0) + { + // set the image + registerSubstitutionTexture(textureName,pbImageData,iImageDataBytes,true); + // add an item in + m_texturePackList.addPack(m_iConfigA[i],textureName); + m_iConfigA[i]=-1; + } + } + else + { + // already have the image, so add an item in + m_texturePackList.addPack(m_iConfigA[i],textureName); + m_iConfigA[i]=-1; + } + } + } + } + + bool bAllDone=true; + for(int i=0;i<m_iTexturePacksNotInstalled;i++) + { + if(m_iConfigA[i]!=-1) + { + bAllDone = false; + } + } + + if(bAllDone) + { + // kill this timer + killTimer(CHECKFORAVAILABLETEXTUREPACKS_TIMER_ID); + } +#endif + + } + break; +#endif + } +} + +void UIScene_LoadMenu::LaunchGame(void) +{ + // stop the timer running that causes a check for new texture packs in TMS but not installed, since this will run all through the load game, and will crash if it tries to create an hbrush +#ifdef _XBOX + killTimer(CHECKFORAVAILABLETEXTUREPACKS_TIMER_ID); +#endif + + if( (m_bGameModeSurvival != true || m_bHasBeenInCreative) || m_MoreOptionsParams.bHostPrivileges == TRUE) + { + UINT uiIDA[2]; + uiIDA[0]=IDS_CONFIRM_OK; + uiIDA[1]=IDS_CONFIRM_CANCEL; + if(m_bGameModeSurvival != true || m_bHasBeenInCreative) + { + // 4J-PB - Need different text for Survival mode with a level that has been saved in Creative + if(m_bGameModeSurvival) + { + ui.RequestMessageBox(IDS_TITLE_START_GAME, IDS_CONFIRM_START_SAVEDINCREATIVE, uiIDA, 2, m_iPad,&UIScene_LoadMenu::ConfirmLoadReturned,this,app.GetStringTable(),NULL,0,false); + } + else // it's creative mode + { + // has it previously been saved in creative? + if(m_bHasBeenInCreative) + { + // 4J-PB - We don't really need to tell the user this will have achievements disabled, since they already saved it in creative + // and they got the warning then + // inform them that leaderboard writes and achievements will be disabled + //ui.RequestMessageBox(IDS_TITLE_START_GAME, IDS_CONFIRM_START_SAVEDINCREATIVE_CONTINUE, uiIDA, 1, m_iPad,&CScene_LoadGameSettings::ConfirmLoadReturned,this,app.GetStringTable()); + + if(m_levelGen != NULL) + { + LoadLevelGen(m_levelGen); + } + else + { + + // set the save to load + PSAVE_DETAILS pSaveDetails=StorageManager.ReturnSavesInfo(); +#ifndef _DURANGO + app.DebugPrintf("Loading save s [%s]\n",pSaveDetails->SaveInfoA[(int)m_iSaveGameInfoIndex].UTF8SaveTitle,pSaveDetails->SaveInfoA[(int)m_iSaveGameInfoIndex].UTF8SaveFilename); +#endif + C4JStorage::ESaveGameState eLoadStatus=StorageManager.LoadSaveData(&pSaveDetails->SaveInfoA[(int)m_iSaveGameInfoIndex],&LoadSaveDataReturned,this); + +#if TO_BE_IMPLEMENTED + if(eLoadStatus==C4JStorage::ELoadGame_DeviceRemoved) + { + // disable saving + StorageManager.SetSaveDisabled(true); + StorageManager.SetSaveDeviceSelected(m_iPad,false); + UINT uiIDA[1]; + uiIDA[0]=IDS_OK; + ui.RequestMessageBox(IDS_STORAGEDEVICEPROBLEM_TITLE, IDS_FAILED_TO_LOADSAVE_TEXT, uiIDA, 1, m_iPad,&CScene_LoadGameSettings::DeviceRemovedDialogReturned,this); + + } +#endif + } + } + else + { + // ask if they're sure they want to turn this into a creative map + ui.RequestMessageBox(IDS_TITLE_START_GAME, IDS_CONFIRM_START_CREATIVE, uiIDA, 2, m_iPad,&UIScene_LoadMenu::ConfirmLoadReturned,this,app.GetStringTable(),NULL,0,false); + } + } + } + else + { + ui.RequestMessageBox(IDS_TITLE_START_GAME, IDS_CONFIRM_START_HOST_PRIVILEGES, uiIDA, 2, m_iPad,&UIScene_LoadMenu::ConfirmLoadReturned,this,app.GetStringTable(),NULL,0,false); + } + } + else + { + if(m_levelGen != NULL) + { + LoadLevelGen(m_levelGen); + } + else + { + // set the save to load + PSAVE_DETAILS pSaveDetails=StorageManager.ReturnSavesInfo(); +#ifndef _DURANGO + app.DebugPrintf("Loading save %s [%s]\n",pSaveDetails->SaveInfoA[(int)m_iSaveGameInfoIndex].UTF8SaveTitle,pSaveDetails->SaveInfoA[(int)m_iSaveGameInfoIndex].UTF8SaveFilename); +#endif + C4JStorage::ESaveGameState eLoadStatus=StorageManager.LoadSaveData(&pSaveDetails->SaveInfoA[(int)m_iSaveGameInfoIndex],&LoadSaveDataReturned,this); + +#if TO_BE_IMPLEMENTED + if(eLoadStatus==C4JStorage::ELoadGame_DeviceRemoved) + { + // disable saving + StorageManager.SetSaveDisabled(true); + StorageManager.SetSaveDeviceSelected(m_iPad,false); + UINT uiIDA[1]; + uiIDA[0]=IDS_OK; + ui.RequestMessageBox(IDS_STORAGEDEVICEPROBLEM_TITLE, IDS_FAILED_TO_LOADSAVE_TEXT, uiIDA, 1, m_iPad,&CScene_LoadGameSettings::DeviceRemovedDialogReturned,this); + } +#endif + } + } + //return 0; +} + +int UIScene_LoadMenu::CheckResetNetherReturned(void *pParam,int iPad,C4JStorage::EMessageResult result) +{ + UIScene_LoadMenu* pClass = (UIScene_LoadMenu*)pParam; + + // results switched for this dialog + if(result==C4JStorage::EMessage_ResultDecline) + { + // continue and reset the nether + pClass->LaunchGame(); + } + else if(result==C4JStorage::EMessage_ResultAccept) + { + // turn off the reset nether and continue + pClass->m_MoreOptionsParams.bResetNether=FALSE; + pClass->LaunchGame(); + } + else + { + // else they chose cancel + pClass->m_bIgnoreInput=false; + } + return 0; +} + +int UIScene_LoadMenu::ConfirmLoadReturned(void *pParam,int iPad,C4JStorage::EMessageResult result) +{ + UIScene_LoadMenu* pClass = (UIScene_LoadMenu*)pParam; + + if(result==C4JStorage::EMessage_ResultAccept) + { + if(pClass->m_levelGen != NULL) + { + pClass->LoadLevelGen(pClass->m_levelGen); + } + else + { + // set the save to load + PSAVE_DETAILS pSaveDetails=StorageManager.ReturnSavesInfo(); +#ifndef _DURANGO + app.DebugPrintf("Loading save %s [%s]\n",pSaveDetails->SaveInfoA[(int)pClass->m_iSaveGameInfoIndex].UTF8SaveTitle,pSaveDetails->SaveInfoA[(int)pClass->m_iSaveGameInfoIndex].UTF8SaveFilename); +#endif + C4JStorage::ESaveGameState eLoadStatus=StorageManager.LoadSaveData(&pSaveDetails->SaveInfoA[(int)pClass->m_iSaveGameInfoIndex],&LoadSaveDataReturned,pClass); + +#if TO_BE_IMPLEMENTED + if(eLoadStatus==C4JStorage::ELoadGame_DeviceRemoved) + { + // disable saving + StorageManager.SetSaveDisabled(true); + StorageManager.SetSaveDeviceSelected(m_iPad,false); + UINT uiIDA[1]; + uiIDA[0]=IDS_OK; + ui.RequestMessageBox(IDS_STORAGEDEVICEPROBLEM_TITLE, IDS_FAILED_TO_LOADSAVE_TEXT, uiIDA, 1, m_iPad,&CScene_LoadGameSettings::DeviceRemovedDialogReturned,this); + } +#endif + } + } + else + { + pClass->m_bIgnoreInput=false; + } + return 0; +} + +int UIScene_LoadMenu::LoadDataComplete(void *pParam) +{ + UIScene_LoadMenu* pClass = (UIScene_LoadMenu*)pParam; + + if(!pClass->m_bIsCorrupt) + { + int iPrimaryPad = ProfileManager.GetPrimaryPad(); + bool isSignedInLive = true; + bool isOnlineGame = pClass->m_MoreOptionsParams.bOnlineGame; + int iPadNotSignedInLive = -1; + bool isLocalMultiplayerAvailable = app.IsLocalMultiplayerAvailable(); + + for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i) + { + if (ProfileManager.IsSignedIn(i) && ((i == iPrimaryPad) || isLocalMultiplayerAvailable)) + { + if (isSignedInLive && !ProfileManager.IsSignedInLive(i)) + { + // Record the first non signed in live pad + iPadNotSignedInLive = i; + } + + isSignedInLive = isSignedInLive && ProfileManager.IsSignedInLive(i); + } + } + + // If this is an online game but not all players are signed in to Live, stop! + if (isOnlineGame && !isSignedInLive) + { +#ifdef __ORBIS__ + assert(iPadNotSignedInLive != -1); + // Check if PSN is unavailable because of age restriction + int npAvailability = ProfileManager.getNPAvailability(iPadNotSignedInLive); + if (npAvailability == SCE_NP_ERROR_AGE_RESTRICTION) + { + pClass->m_bIgnoreInput = false; + // 4J Stu - This is a bit messy and is due to the library incorrectly returning false for IsSignedInLive if the npAvailability isn't SCE_OK + UINT uiIDA[1]; + uiIDA[0]=IDS_OK; + ui.RequestMessageBox(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, iPadNotSignedInLive, NULL, NULL, app.GetStringTable()); + } + else + { + pClass->m_bIgnoreInput=true; + UINT uiIDA[2]; + uiIDA[0] = IDS_PRO_NOTONLINE_ACCEPT; + uiIDA[1] = IDS_CANCEL; + ui.RequestMessageBox( IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 2, iPadNotSignedInLive, &UIScene_LoadMenu::MustSignInReturnedPSN, pClass, app.GetStringTable(), NULL, 0, false); + } + return 0; +#else + pClass->m_bIgnoreInput=false; + UINT uiIDA[1]; + uiIDA[0]=IDS_CONFIRM_OK; + ui.RequestMessageBox( IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA,1,ProfileManager.GetPrimaryPad(),NULL,NULL, app.GetStringTable(),NULL,0,false); + return 0; +#endif + } + + // Check if user-created content is allowed, as we cannot play multiplayer if it's not + bool noUGC = false; + BOOL pccAllowed = TRUE; + BOOL pccFriendsAllowed = TRUE; + bool bContentRestricted = false; + ProfileManager.AllowedPlayerCreatedContent(ProfileManager.GetPrimaryPad(),false,&pccAllowed,&pccFriendsAllowed); +#if defined(__PS3__) || defined(__PSVITA__) + if(isOnlineGame) + { + ProfileManager.GetChatAndContentRestrictions(ProfileManager.GetPrimaryPad(),false,NULL,&bContentRestricted,NULL); + } +#endif + +#ifdef __ORBIS__ + bool bPlayStationPlus=true; + int iPadWithNoPlaystationPlus=0; + for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i) + { + if(ProfileManager.IsSignedIn(i) && ((i == iPrimaryPad) || isLocalMultiplayerAvailable)) + { + if(!ProfileManager.HasPlayStationPlus(i)) + { + bPlayStationPlus=false; + iPadWithNoPlaystationPlus=i; + break; + } + } + } +#endif + noUGC = !pccAllowed && !pccFriendsAllowed; + + if(!isOnlineGame || !isLocalMultiplayerAvailable) + { + if(isOnlineGame && noUGC ) + { + pClass->setVisible( true ); + + ui.RequestUGCMessageBox(); + + pClass->m_bIgnoreInput=false; + } + else if(isOnlineGame && bContentRestricted ) + { + pClass->setVisible( true ); + + ui.RequestContentRestrictedMessageBox(); + pClass->m_bIgnoreInput=false; + } +#ifdef __ORBIS__ + else if(isOnlineGame && (bPlayStationPlus==false)) + { + pClass->setVisible( true ); + pClass->m_bIgnoreInput=false; + + // 4J-PB - we're not allowed to show the text Playstation Plus - have to call the upsell all the time! + // upsell psplus + int32_t iResult=sceNpCommerceDialogInitialize(); + + SceNpCommerceDialogParam param; + sceNpCommerceDialogParamInitialize(¶m); + param.mode=SCE_NP_COMMERCE_DIALOG_MODE_PLUS; + param.features = SCE_NP_PLUS_FEATURE_REALTIME_MULTIPLAY; + param.userId = ProfileManager.getUserID(iPadWithNoPlaystationPlus); + + iResult=sceNpCommerceDialogOpen(¶m); + +// UINT uiIDA[2]; +// uiIDA[0]=IDS_PLAY_OFFLINE; +// uiIDA[1]=IDS_PLAYSTATIONPLUS_SIGNUP; +// ui.RequestMessageBox( IDS_FAILED_TO_CREATE_GAME_TITLE, IDS_NO_PLAYSTATIONPLUS, uiIDA,2,ProfileManager.GetPrimaryPad(),&UIScene_LoadMenu::PSPlusReturned,pClass, app.GetStringTable(),NULL,0,false); + } + +#endif + else + { + +#if defined(__ORBIS__) || defined(__PSVITA__) + if(isOnlineGame) + { + bool chatRestricted = false; + ProfileManager.GetChatAndContentRestrictions(ProfileManager.GetPrimaryPad(),false,&chatRestricted,NULL,NULL); + if(chatRestricted) + { + ProfileManager.DisplaySystemMessage( SCE_MSG_DIALOG_SYSMSG_TYPE_TRC_PSN_CHAT_RESTRICTION, ProfileManager.GetPrimaryPad() ); + } + } +#endif + DWORD dwLocalUsersMask = CGameNetworkManager::GetLocalPlayerMask(ProfileManager.GetPrimaryPad()); + + // No guest problems so we don't need to force a sign-in of players here + StartGameFromSave(pClass, dwLocalUsersMask); + } + } + else + { + // 4J-PB not sure why we aren't checking the content restriction for the main player here when multiple controllers are connected - adding now + if(isOnlineGame && noUGC ) + { + pClass->setVisible( true ); + ui.RequestUGCMessageBox(); + pClass->m_bIgnoreInput=false; + } + else if(isOnlineGame && bContentRestricted ) + { + pClass->setVisible( true ); + ui.RequestContentRestrictedMessageBox(); + pClass->m_bIgnoreInput=false; + } +#ifdef __ORBIS__ + else if(bPlayStationPlus==false) + { + pClass->setVisible( true ); + pClass->m_bIgnoreInput=false; + + // 4J-PB - we're not allowed to show the text Playstation Plus - have to call the upsell all the time! + // upsell psplus + int32_t iResult=sceNpCommerceDialogInitialize(); + + SceNpCommerceDialogParam param; + sceNpCommerceDialogParamInitialize(¶m); + param.mode=SCE_NP_COMMERCE_DIALOG_MODE_PLUS; + param.features = SCE_NP_PLUS_FEATURE_REALTIME_MULTIPLAY; + param.userId = ProfileManager.getUserID(iPadWithNoPlaystationPlus); + + iResult=sceNpCommerceDialogOpen(¶m); + +// UINT uiIDA[2]; +// uiIDA[0]=IDS_PLAY_OFFLINE; +// uiIDA[1]=IDS_PLAYSTATIONPLUS_SIGNUP; +// ui.RequestMessageBox( IDS_FAILED_TO_CREATE_GAME_TITLE, IDS_NO_PLAYSTATIONPLUS, uiIDA,2,ProfileManager.GetPrimaryPad(),&UIScene_LoadMenu::PSPlusReturned,pClass, app.GetStringTable(),NULL,0,false); + } +#endif + else + { + pClass->m_bRequestQuadrantSignin = true; + } + } + } + else + { + // the save is corrupt! + pClass->m_bIgnoreInput=false; + + // give the option to delete the save + UINT uiIDA[2]; + uiIDA[0]=IDS_CONFIRM_CANCEL; + uiIDA[1]=IDS_CONFIRM_OK; + ui.RequestMessageBox(IDS_CORRUPT_OR_DAMAGED_SAVE_TITLE, IDS_CORRUPT_OR_DAMAGED_SAVE_TEXT, uiIDA, 2, pClass->m_iPad,&UIScene_LoadMenu::DeleteSaveDialogReturned,pClass, app.GetStringTable(),NULL,0,false); + + } + + return 0; +} + +int UIScene_LoadMenu::LoadSaveDataReturned(void *pParam,bool bIsCorrupt, bool bIsOwner) +{ + UIScene_LoadMenu* pClass = (UIScene_LoadMenu*)pParam; + + pClass->m_bIsCorrupt=bIsCorrupt; + if(bIsOwner) + { + LoadDataComplete(pClass); + } + else + { + // messagebox + pClass->m_bIgnoreInput=false; + +#if defined(__PS3__) || defined(__ORBIS__) || defined (__PSVITA__) + // show the message that trophies are disabled + UINT uiIDA[1]; + uiIDA[0]=IDS_CONFIRM_OK; + ui.RequestMessageBox(IDS_SAVEDATA_COPIED_TITLE, IDS_SAVEDATA_COPIED_TEXT, uiIDA, 1, + pClass->m_iPad,&UIScene_LoadMenu::TrophyDialogReturned,pClass, app.GetStringTable()); +#endif + } + + + return 0; +} + +int UIScene_LoadMenu::TrophyDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result) +{ + UIScene_LoadMenu* pClass = (UIScene_LoadMenu*)pParam; + return LoadDataComplete(pClass); +} + +int UIScene_LoadMenu::DeleteSaveDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result) +{ + UIScene_LoadMenu* pClass = (UIScene_LoadMenu*)pParam; + + // results switched for this dialog + if(result==C4JStorage::EMessage_ResultDecline) + { + PSAVE_DETAILS pSaveDetails=StorageManager.ReturnSavesInfo(); + StorageManager.DeleteSaveData(&pSaveDetails->SaveInfoA[(int)pClass->m_iSaveGameInfoIndex],UIScene_LoadMenu::DeleteSaveDataReturned,pClass); + } + else + { + pClass->m_bIgnoreInput=false; + } + return 0; +} + +int UIScene_LoadMenu::DeleteSaveDataReturned(void *pParam,bool bSuccess) +{ + UIScene_LoadMenu* pClass = (UIScene_LoadMenu*)pParam; + + app.SetCorruptSaveDeleted(true); + pClass->navigateBack(); + + return 0; +} + +// 4J Stu - Shared functionality that is the same whether we needed a quadrant sign-in or not +void UIScene_LoadMenu::StartGameFromSave(UIScene_LoadMenu* pClass, DWORD dwLocalUsersMask) +{ + INT saveOrCheckpointId = 0; + bool validSave = StorageManager.GetSaveUniqueNumber(&saveOrCheckpointId); + TelemetryManager->RecordLevelResume(pClass->m_iPad, eSen_FriendOrMatch_Playing_With_Invited_Friends, eSen_CompeteOrCoop_Coop_and_Competitive, app.GetGameSettings(pClass->m_iPad,eGameSetting_Difficulty), app.GetLocalPlayerCount(), g_NetworkManager.GetOnlinePlayerCount(), saveOrCheckpointId); + + bool isClientSide = ProfileManager.IsSignedInLive(ProfileManager.GetPrimaryPad()) && pClass->m_MoreOptionsParams.bOnlineGame; +#ifdef __PSVITA__ + if(CGameNetworkManager::usingAdhocMode()) + { + if(SQRNetworkManager_AdHoc_Vita::GetAdhocStatus())// && pClass->m_MoreOptionsParams.bOnlineGame) + isClientSide = true; + } +#endif // __PSVITA__ + + bool isPrivate = (app.GetGameSettings(pClass->m_iPad,eGameSetting_InviteOnly)>0)?true:false; + + PSAVE_DETAILS pSaveDetails=StorageManager.ReturnSavesInfo(); + + NetworkGameInitData *param = new NetworkGameInitData(); + param->seed = pClass->m_seed; + param->saveData = NULL; + param->texturePackId = pClass->m_MoreOptionsParams.dwTexturePack; + + Minecraft *pMinecraft = Minecraft::GetInstance(); + pMinecraft->skins->selectTexturePackById(pClass->m_MoreOptionsParams.dwTexturePack); + //pMinecraft->skins->updateUI(); + + app.SetGameHostOption(eGameHostOption_Difficulty,Minecraft::GetInstance()->options->difficulty); + app.SetGameHostOption(eGameHostOption_FriendsOfFriends,app.GetGameSettings(pClass->m_iPad,eGameSetting_FriendsOfFriends)); + app.SetGameHostOption(eGameHostOption_Gamertags,app.GetGameSettings(pClass->m_iPad,eGameSetting_GamertagsVisible)); + + app.SetGameHostOption(eGameHostOption_BedrockFog,app.GetGameSettings(pClass->m_iPad,eGameSetting_BedrockFog)?1:0); + + app.SetGameHostOption(eGameHostOption_PvP,pClass->m_MoreOptionsParams.bPVP); + app.SetGameHostOption(eGameHostOption_TrustPlayers,pClass->m_MoreOptionsParams.bTrust ); + app.SetGameHostOption(eGameHostOption_FireSpreads,pClass->m_MoreOptionsParams.bFireSpreads ); + app.SetGameHostOption(eGameHostOption_TNT,pClass->m_MoreOptionsParams.bTNT ); + app.SetGameHostOption(eGameHostOption_HostCanFly,pClass->m_MoreOptionsParams.bHostPrivileges); + app.SetGameHostOption(eGameHostOption_HostCanChangeHunger,pClass->m_MoreOptionsParams.bHostPrivileges); + app.SetGameHostOption(eGameHostOption_HostCanBeInvisible,pClass->m_MoreOptionsParams.bHostPrivileges ); + + // flag if the user wants to reset the Nether to force a Fortress with netherwart etc. + app.SetResetNether((pClass->m_MoreOptionsParams.bResetNether==TRUE)?true:false); + // clear out the app's terrain features list + app.ClearTerrainFeaturePosition(); + + app.SetGameHostOption(eGameHostOption_GameType,pClass->m_bGameModeSurvival?GameType::SURVIVAL->getId():GameType::CREATIVE->getId() ); + + g_NetworkManager.HostGame(dwLocalUsersMask,isClientSide,isPrivate,MINECRAFT_NET_MAX_PLAYERS,0); + + param->settings = app.GetGameHostOption( eGameHostOption_All ); + +#ifndef _XBOX + g_NetworkManager.FakeLocalPlayerJoined(); +#endif + + LoadingInputParams *loadingParams = new LoadingInputParams(); + loadingParams->func = &CGameNetworkManager::RunNetworkGameThreadProc; + loadingParams->lpParam = (LPVOID)param; + + // Reset the autosave time + app.SetAutosaveTimerTime(); + + UIFullscreenProgressCompletionData *completionData = new UIFullscreenProgressCompletionData(); + completionData->bShowBackground=TRUE; + completionData->bShowLogo=TRUE; + completionData->type = e_ProgressCompletion_CloseAllPlayersUIScenes; + completionData->iPad = DEFAULT_XUI_MENU_USER; + loadingParams->completionData = completionData; + + ui.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_FullscreenProgress, loadingParams); +} + +void UIScene_LoadMenu::checkStateAndStartGame() +{ + // Check if they have the Reset Nether flag set, and confirm they want to do this + if(m_MoreOptionsParams.bResetNether==TRUE) + { + UINT uiIDA[2]; + uiIDA[0]=IDS_DONT_RESET_NETHER; + uiIDA[1]=IDS_RESET_NETHER; + + ui.RequestMessageBox(IDS_RESETNETHER_TITLE, IDS_RESETNETHER_TEXT, uiIDA, 2, m_iPad,&UIScene_LoadMenu::CheckResetNetherReturned,this,app.GetStringTable(),NULL,0,false); + } + else + { + LaunchGame(); + } +} + +void UIScene_LoadMenu::LoadLevelGen(LevelGenerationOptions *levelGen) +{ + bool isClientSide = ProfileManager.IsSignedInLive(ProfileManager.GetPrimaryPad()) && m_MoreOptionsParams.bOnlineGame; + + // 4J Stu - If we only have one controller connected, then don't show the sign-in UI again + DWORD connectedControllers = 0; + for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i) + { + if( InputManager.IsPadConnected(i) || ProfileManager.IsSignedIn(i) ) ++connectedControllers; + } + + if(!isClientSide || connectedControllers == 1 || !RenderManager.IsHiDef()) + { + + // Check if user-created content is allowed, as we cannot play multiplayer if it's not + bool noUGC = false; + BOOL pccAllowed = TRUE; + BOOL pccFriendsAllowed = TRUE; + + ProfileManager.AllowedPlayerCreatedContent(ProfileManager.GetPrimaryPad(),false,&pccAllowed,&pccFriendsAllowed); + if(!pccAllowed && !pccFriendsAllowed) noUGC = true; + + if(isClientSide && noUGC ) + { + m_bIgnoreInput=false; + UINT uiIDA[1]; + uiIDA[0]=IDS_CONFIRM_OK; + ui.RequestMessageBox( IDS_FAILED_TO_CREATE_GAME_TITLE, IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_CREATE, uiIDA,1,ProfileManager.GetPrimaryPad(),NULL,NULL, app.GetStringTable(),NULL,0,false); + return; + } + + } + + DWORD dwLocalUsersMask = 0; + + dwLocalUsersMask |= CGameNetworkManager::GetLocalPlayerMask(ProfileManager.GetPrimaryPad()); + // Load data from disc + //File saveFile( L"Tutorial\\Tutorial" ); + //LoadSaveFromDisk(&saveFile); + + StorageManager.ResetSaveData(); + // Make our next save default to the name of the level + StorageManager.SetSaveTitle(levelGen->getDefaultSaveName().c_str()); + + bool isPrivate = (app.GetGameSettings(m_iPad,eGameSetting_InviteOnly)>0)?true:false; + + g_NetworkManager.HostGame(dwLocalUsersMask,isClientSide,isPrivate,MINECRAFT_NET_MAX_PLAYERS,0); + + NetworkGameInitData *param = new NetworkGameInitData(); + param->seed = 0; + param->saveData = NULL; + param->levelGen = levelGen; + + if(levelGen->requiresTexturePack()) + { + param->texturePackId = levelGen->getRequiredTexturePackId(); + + Minecraft *pMinecraft = Minecraft::GetInstance(); + pMinecraft->skins->selectTexturePackById(param->texturePackId); + //pMinecraft->skins->updateUI(); + } + + + app.SetGameHostOption(eGameHostOption_Difficulty,Minecraft::GetInstance()->options->difficulty); + app.SetGameHostOption(eGameHostOption_FriendsOfFriends,app.GetGameSettings(m_iPad,eGameSetting_FriendsOfFriends)); + app.SetGameHostOption(eGameHostOption_Gamertags,app.GetGameSettings(m_iPad,eGameSetting_GamertagsVisible)); + + app.SetGameHostOption(eGameHostOption_BedrockFog,app.GetGameSettings(m_iPad,eGameSetting_BedrockFog)?1:0); + + app.SetGameHostOption(eGameHostOption_PvP,m_MoreOptionsParams.bPVP); + app.SetGameHostOption(eGameHostOption_TrustPlayers,m_MoreOptionsParams.bTrust ); + app.SetGameHostOption(eGameHostOption_FireSpreads,m_MoreOptionsParams.bFireSpreads ); + app.SetGameHostOption(eGameHostOption_TNT,m_MoreOptionsParams.bTNT ); + app.SetGameHostOption(eGameHostOption_HostCanFly,m_MoreOptionsParams.bHostPrivileges); + app.SetGameHostOption(eGameHostOption_HostCanChangeHunger,m_MoreOptionsParams.bHostPrivileges); + app.SetGameHostOption(eGameHostOption_HostCanBeInvisible,m_MoreOptionsParams.bHostPrivileges ); + + // flag if the user wants to reset the Nether to force a Fortress with netherwart etc. + app.SetResetNether((m_MoreOptionsParams.bResetNether==TRUE)?true:false); + // clear out the app's terrain features list + app.ClearTerrainFeaturePosition(); + + app.SetGameHostOption(eGameHostOption_GameType,m_bGameModeSurvival?GameType::SURVIVAL->getId():GameType::CREATIVE->getId() ); + + param->settings = app.GetGameHostOption( eGameHostOption_All ); + +#ifndef _XBOX + g_NetworkManager.FakeLocalPlayerJoined(); +#endif + + LoadingInputParams *loadingParams = new LoadingInputParams(); + loadingParams->func = &CGameNetworkManager::RunNetworkGameThreadProc; + loadingParams->lpParam = (LPVOID)param; + + // Reset the autosave time + app.SetAutosaveTimerTime(); + + UIFullscreenProgressCompletionData *completionData = new UIFullscreenProgressCompletionData(); + completionData->bShowBackground=TRUE; + completionData->bShowLogo=TRUE; + completionData->type = e_ProgressCompletion_CloseAllPlayersUIScenes; + completionData->iPad = DEFAULT_XUI_MENU_USER; + loadingParams->completionData = completionData; + + ui.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_FullscreenProgress, loadingParams); +} + +int UIScene_LoadMenu::StartGame_SignInReturned(void *pParam,bool bContinue, int iPad) +{ + UIScene_LoadMenu* pClass = (UIScene_LoadMenu*)pParam; + + if(bContinue==true) + { + // It's possible that the player has not signed in - they can back out + if(ProfileManager.IsSignedIn(pClass->m_iPad)) + { + int primaryPad = ProfileManager.GetPrimaryPad(); + bool noPrivileges = false; + DWORD dwLocalUsersMask = 0; + bool isSignedInLive = ProfileManager.IsSignedInLive(primaryPad); + bool isOnlineGame = pClass->m_MoreOptionsParams.bOnlineGame; + int iPadNotSignedInLive = -1; + bool isLocalMultiplayerAvailable = app.IsLocalMultiplayerAvailable(); + + for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i) + { + if (ProfileManager.IsSignedIn(i) && ((i == primaryPad) || isLocalMultiplayerAvailable)) + { + if (isSignedInLive && !ProfileManager.IsSignedInLive(i)) + { + // Record the first non signed in live pad + iPadNotSignedInLive = i; + } + + if( !ProfileManager.AllowedToPlayMultiplayer(i) ) noPrivileges = true; + dwLocalUsersMask |= CGameNetworkManager::GetLocalPlayerMask(i); + isSignedInLive = isSignedInLive && ProfileManager.IsSignedInLive(i); + } + } + + // If this is an online game but not all players are signed in to Live, stop! + if (isOnlineGame && !isSignedInLive) + { +#ifdef __ORBIS__ + assert(iPadNotSignedInLive != -1); + + // Check if PSN is unavailable because of age restriction + int npAvailability = ProfileManager.getNPAvailability(iPadNotSignedInLive); + if (npAvailability == SCE_NP_ERROR_AGE_RESTRICTION) + { + pClass->m_bIgnoreInput = false; + // 4J Stu - This is a bit messy and is due to the library incorrectly returning false for IsSignedInLive if the npAvailability isn't SCE_OK + UINT uiIDA[1]; + uiIDA[0]=IDS_OK; + ui.RequestMessageBox(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, iPadNotSignedInLive, NULL, NULL, app.GetStringTable()); + } + else + { + pClass->m_bIgnoreInput=true; + UINT uiIDA[2]; + uiIDA[0] = IDS_PRO_NOTONLINE_ACCEPT; + uiIDA[1] = IDS_CANCEL; + ui.RequestMessageBox( IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 2, iPadNotSignedInLive, &UIScene_LoadMenu::MustSignInReturnedPSN, pClass, app.GetStringTable(), NULL, 0, false); + } + return 0; +#else + pClass->m_bIgnoreInput=false; + UINT uiIDA[1]; + uiIDA[0]=IDS_CONFIRM_OK; + ui.RequestMessageBox( IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA,1,ProfileManager.GetPrimaryPad(),NULL,NULL, app.GetStringTable(),NULL,0,false); + return 0; +#endif + } + + // Check if user-created content is allowed, as we cannot play multiplayer if it's not + bool noUGC = false; + BOOL pccAllowed = TRUE; + BOOL pccFriendsAllowed = TRUE; + + ProfileManager.AllowedPlayerCreatedContent(ProfileManager.GetPrimaryPad(),false,&pccAllowed,&pccFriendsAllowed); + if(!pccAllowed && !pccFriendsAllowed) noUGC = true; + + if(isSignedInLive && isOnlineGame && (noPrivileges || noUGC) ) + { + if( noUGC ) + { + pClass->m_bIgnoreInput = false; + pClass->setVisible( true ); + UINT uiIDA[1]; + uiIDA[0]=IDS_CONFIRM_OK; + ui.RequestMessageBox( IDS_FAILED_TO_CREATE_GAME_TITLE, IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_CREATE, uiIDA,1,ProfileManager.GetPrimaryPad(),NULL,NULL, app.GetStringTable(),NULL,0,false); + } + else + { + pClass->m_bIgnoreInput = false; + pClass->setVisible( true ); + UINT uiIDA[1]; + uiIDA[0]=IDS_CONFIRM_OK; + ui.RequestMessageBox( IDS_NO_MULTIPLAYER_PRIVILEGE_TITLE, IDS_NO_MULTIPLAYER_PRIVILEGE_HOST_TEXT, uiIDA,1,ProfileManager.GetPrimaryPad(),NULL,NULL, app.GetStringTable(),NULL,0,false); + } + } + else + { +#if defined( __ORBIS__) || defined(__PSVITA__) + if(isOnlineGame) + { + // show the chat restriction message for all users that it applies to + for(unsigned int i = 0; i < XUSER_MAX_COUNT; i++) + { + if(ProfileManager.IsSignedInLive(i)) + { + bool chatRestricted = false; + ProfileManager.GetChatAndContentRestrictions(i,false,&chatRestricted,NULL,NULL); + if(chatRestricted) + { + ProfileManager.DisplaySystemMessage( SCE_MSG_DIALOG_SYSMSG_TYPE_TRC_PSN_CHAT_RESTRICTION, i ); + } + } + } + } +#endif + // This is NOT called from a storage manager thread, and is in fact called from the main thread in the Profile library tick. Therefore we use the main threads IntCache. + StartGameFromSave(pClass, dwLocalUsersMask); + } + } + } + else + { + pClass->m_bIgnoreInput=false; + } + + return 0; +} + +void UIScene_LoadMenu::handleGainFocus(bool navBack) +{ + if(navBack) + { + +#if defined _XBOX_ONE || defined __ORBIS__ || defined _WINDOWS64 + if(getSceneResolution() == eSceneResolution_1080) + { + m_checkboxOnline.setChecked(m_MoreOptionsParams.bOnlineGame == TRUE); + } +#endif + } +} + +#ifdef __ORBIS__ +int UIScene_LoadMenu::MustSignInReturnedPSN(void *pParam,int iPad,C4JStorage::EMessageResult result) +{ + UIScene_LoadMenu* pClass = (UIScene_LoadMenu *)pParam; + pClass->m_bIgnoreInput = false; + + if(result==C4JStorage::EMessage_ResultAccept) + { + SQRNetworkManager_Orbis::AttemptPSNSignIn(&UIScene_LoadMenu::StartGame_SignInReturned, pClass, false, iPad); + } + + return 0; +} + +// int UIScene_LoadMenu::PSPlusReturned(void *pParam,int iPad,C4JStorage::EMessageResult result) +// { +// int32_t iResult; +// UIScene_LoadMenu *pClass = (UIScene_LoadMenu *)pParam; +// +// // continue offline, or upsell PS Plus? +// if(result==C4JStorage::EMessage_ResultDecline) +// { +// // upsell psplus +// iResult=sceNpCommerceDialogInitialize(); +// +// SceNpCommerceDialogParam param; +// sceNpCommerceDialogParamInitialize(¶m); +// param.mode=SCE_NP_COMMERCE_DIALOG_MODE_PLUS; +// param.features = SCE_NP_PLUS_FEATURE_REALTIME_MULTIPLAY; +// param.userId = ProfileManager.getUserID(pClass->m_iPad); +// +// +// iResult=sceNpCommerceDialogOpen(¶m); +// } +// else if(result==C4JStorage::EMessage_ResultAccept) +// { +// // continue offline +// pClass->m_MoreOptionsParams.bOnlineGame=false; +// pClass->LoadDataComplete(pClass); +// } +// +// pClass->m_bIgnoreInput=false; +// return 0; +// } +#endif
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIScene_LoadMenu.h b/Minecraft.Client/Common/UI/UIScene_LoadMenu.h new file mode 100644 index 00000000..e45fa09c --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_LoadMenu.h @@ -0,0 +1,131 @@ +#pragma once + +#include "IUIScene_StartGame.h" + +class UIScene_LoadMenu : public IUIScene_StartGame +{ +private: + enum EControls + { + eControl_GameMode, + eControl_Difficulty, + eControl_MoreOptions, + eControl_LoadWorld, + eControl_TexturePackList, + eControl_OnlineGame, + }; + + static int m_iDifficultyTitleSettingA[4]; + + UIControl m_controlMainPanel; + UIControl_Label m_labelGameName, m_labelSeed, m_labelCreatedMode; + UIControl_Button m_buttonGamemode, m_buttonMoreOptions, m_buttonLoadWorld; + UIControl_Slider m_sliderDifficulty; + UIControl_BitmapIcon m_bitmapIcon; + +#if defined _XBOX_ONE || defined __ORBIS__ || defined _WINDOWS64 + UIControl_CheckBox m_checkboxOnline; +#endif + + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(IUIScene_StartGame) + UI_MAP_ELEMENT( m_controlMainPanel, "MainPanel" ) + UI_BEGIN_MAP_CHILD_ELEMENTS( m_controlMainPanel ) + UI_MAP_ELEMENT( m_labelGameName, "GameName") + UI_MAP_ELEMENT( m_labelCreatedMode, "CreatedMode") + UI_MAP_ELEMENT( m_labelSeed, "Seed") + UI_MAP_ELEMENT( m_texturePackList, "TexturePackSelector") + UI_MAP_ELEMENT( m_buttonGamemode, "GameModeToggle") + +#if defined _XBOX_ONE || defined __ORBIS__ || defined _WINDOWS64 + UI_MAP_ELEMENT( m_checkboxOnline, "CheckboxOnline") +#endif + UI_MAP_ELEMENT( m_buttonMoreOptions, "MoreOptions") + UI_MAP_ELEMENT( m_buttonLoadWorld, "LoadSettings") + UI_MAP_ELEMENT( m_sliderDifficulty, "Difficulty") + UI_MAP_ELEMENT( m_bitmapIcon, "LevelIcon") + UI_END_MAP_CHILD_ELEMENTS() + UI_END_MAP_ELEMENTS_AND_NAMES() + + LevelGenerationOptions *m_levelGen; + DLCPack * m_pDLCPack; + + int m_iSaveGameInfoIndex; + int m_CurrentDifficulty; + bool m_bGameModeSurvival; + bool m_bHasBeenInCreative; + bool m_bRetrievingSaveThumbnail; + bool m_bSaveThumbnailReady; + bool m_bMultiplayerAllowed; + bool m_bShowTimer; + bool m_bAvailableTexturePacksChecked; + bool m_bRequestQuadrantSignin; + bool m_bIsCorrupt; + bool m_bThumbnailGetFailed; + __int64 m_seed; + +#ifdef __PS3__ + std::vector<SonyCommerce::ProductInfo>*m_pvProductInfo; +#endif + //int *m_iConfigA; // track the texture packs that we don't have installed + + PBYTE m_pbThumbnailData; + unsigned int m_uiThumbnailSize; + wstring m_thumbnailName; + + bool m_bRebuildTouchBoxes; +public: + UIScene_LoadMenu(int iPad, void *initData, UILayer *parentLayer); + + virtual void updateTooltips(); + virtual void updateComponents(); + + virtual EUIScene getSceneType() { return eUIScene_LoadMenu;} + + virtual void tick(); + + virtual UIControl* GetMainPanel(); + + virtual void handleTouchBoxRebuild(); + +protected: + // TODO: This should be pure virtual in this class + virtual wstring getMoviePath(); + +public: + // INPUT + virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled); + virtual void handleTimerComplete(int id); + +protected: + void handlePress(F64 controlId, F64 childId); + void handleSliderMove(F64 sliderId, F64 currentValue); + virtual void handleGainFocus(bool navBack); + +private: + void StartSharedLaunchFlow(); + virtual void checkStateAndStartGame(); + void LoadLevelGen(LevelGenerationOptions *levelGen); + void LaunchGame(void); + +#ifdef _DURANGO + static void checkPrivilegeCallback(LPVOID lpParam, bool hasPrivilege, int iPad); +#endif + + static int ConfirmLoadReturned(void *pParam,int iPad,C4JStorage::EMessageResult result); + static void StartGameFromSave(UIScene_LoadMenu* pClass, DWORD dwLocalUsersMask); + static int LoadSaveDataReturned(void *pParam,bool bIsCorrupt, bool bIsOwner); + static int TrophyDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result); + static int LoadDataComplete(void *pParam); + static int LoadSaveDataThumbnailReturned(LPVOID lpParam,PBYTE pbThumbnail,DWORD dwThumbnailBytes); + static int CheckResetNetherReturned(void *pParam,int iPad,C4JStorage::EMessageResult result); + static int DeleteSaveDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result); + static int DeleteSaveDataReturned(void *pParam,bool bSuccess); + static int MustSignInReturnedPSN(void *pParam,int iPad,C4JStorage::EMessageResult result); +#ifdef __ORBIS__ + //static int PSPlusReturned(void *pParam,int iPad,C4JStorage::EMessageResult result); + static int ContinueOffline(void *pParam,int iPad,C4JStorage::EMessageResult result); +#endif + +public: + static int StartGame_SignInReturned(LPVOID pParam, bool, int); +};
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIScene_LoadOrJoinMenu.cpp b/Minecraft.Client/Common/UI/UIScene_LoadOrJoinMenu.cpp new file mode 100644 index 00000000..1d90da77 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_LoadOrJoinMenu.cpp @@ -0,0 +1,3536 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIScene_LoadOrJoinMenu.h" + +#include "..\..\..\Minecraft.World\StringHelpers.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.item.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.level.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.level.chunk.storage.h" +#include "..\..\..\Minecraft.World\ConsoleSaveFile.h" +#include "..\..\..\Minecraft.World\ConsoleSaveFileOriginal.h" +#include "..\..\..\Minecraft.World\ConsoleSaveFileSplit.h" +#include "..\..\ProgressRenderer.h" +#include "..\..\MinecraftServer.h" +#include "..\..\TexturePackRepository.h" +#include "..\..\TexturePack.h" +#include "..\Network\SessionInfo.h" +#if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__) +#include "Common\Network\Sony\SonyHttp.h" +#include "Common\Network\Sony\SonyRemoteStorage.h" +#endif +#if defined(__ORBIS__) || defined(__PSVITA__) +#include <ces.h> +#endif +#ifdef __PSVITA__ +#include "message_dialog.h" +#endif + + +#ifdef SONY_REMOTE_STORAGE_DOWNLOAD +unsigned long UIScene_LoadOrJoinMenu::m_ulFileSize=0L; +wstring UIScene_LoadOrJoinMenu::m_wstrStageText=L""; +#endif + + +#define JOIN_LOAD_ONLINE_TIMER_ID 0 +#define JOIN_LOAD_ONLINE_TIMER_TIME 100 + +#ifdef _XBOX +#define CHECKFORAVAILABLETEXTUREPACKS_TIMER_ID 3 +#define CHECKFORAVAILABLETEXTUREPACKS_TIMER_TIME 50 +#endif + +#ifdef _XBOX_ONE +UIScene_LoadOrJoinMenu::ESaveTransferFiles UIScene_LoadOrJoinMenu::s_eSaveTransferFile; +unsigned long UIScene_LoadOrJoinMenu::s_ulFileSize=0L; +byteArray UIScene_LoadOrJoinMenu::s_transferData = byteArray(); +wstring UIScene_LoadOrJoinMenu::m_wstrStageText=L""; + +#ifdef _DEBUG_MENUS_ENABLED +C4JStorage::SAVETRANSFER_FILE_DETAILS UIScene_LoadOrJoinMenu::m_debugTransferDetails; +#endif +#endif + +int UIScene_LoadOrJoinMenu::LoadSaveDataThumbnailReturned(LPVOID lpParam,PBYTE pbThumbnail,DWORD dwThumbnailBytes) +{ + UIScene_LoadOrJoinMenu *pClass= (UIScene_LoadOrJoinMenu *)lpParam; + + app.DebugPrintf("Received data for save thumbnail\n"); + + if(pbThumbnail && dwThumbnailBytes) + { + pClass->m_saveDetails[pClass->m_iRequestingThumbnailId].pbThumbnailData = new BYTE[dwThumbnailBytes]; + memcpy(pClass->m_saveDetails[pClass->m_iRequestingThumbnailId].pbThumbnailData, pbThumbnail, dwThumbnailBytes); + pClass->m_saveDetails[pClass->m_iRequestingThumbnailId].dwThumbnailSize = dwThumbnailBytes; + } + else + { + pClass->m_saveDetails[pClass->m_iRequestingThumbnailId].pbThumbnailData = NULL; + pClass->m_saveDetails[pClass->m_iRequestingThumbnailId].dwThumbnailSize = 0; + app.DebugPrintf("Save thumbnail data is NULL, or has size 0\n"); + } + pClass->m_bSaveThumbnailReady = true; + + return 0; +} + +int UIScene_LoadOrJoinMenu::LoadSaveCallback(LPVOID lpParam,bool bRes) +{ + //UIScene_LoadOrJoinMenu *pClass= (UIScene_LoadOrJoinMenu *)lpParam; + // Get the save data now + if(bRes) + { + app.DebugPrintf("Loaded save OK\n"); + } + return 0; +} + +UIScene_LoadOrJoinMenu::UIScene_LoadOrJoinMenu(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) +{ + // Setup all the Iggy references we need for this scene + initialiseMovie(); + app.SetLiveLinkRequired( true ); + + m_iRequestingThumbnailId = 0; + m_iSaveInfoC=0; + m_bIgnoreInput = false; + m_bShowingPartyGamesOnly = false; + m_bInParty = false; + m_currentSessions = NULL; + m_iState=e_SavesIdle; + //m_bRetrievingSaveInfo=false; + + m_buttonListSaves.init(eControl_SavesList); + m_buttonListGames.init(eControl_GamesList); + + m_labelSavesListTitle.init( app.GetString(IDS_START_GAME) ); + m_labelJoinListTitle.init( app.GetString(IDS_JOIN_GAME) ); + m_labelNoGames.init( app.GetString(IDS_NO_GAMES_FOUND) ); + m_labelNoGames.setVisible( false ); + m_controlSavesTimer.setVisible( true ); + m_controlJoinTimer.setVisible( true ); + + +#if defined(_XBOX_ONE) || defined(__ORBIS__) + m_spaceIndicatorSaves.init(L"",eControl_SpaceIndicator,0, (4LL *1024LL * 1024LL * 1024LL) ); +#endif + m_bUpdateSaveSize = false; + + m_bAllLoaded = false; + m_bRetrievingSaveThumbnails = false; + m_bSaveThumbnailReady = false; + m_bExitScene=false; + m_pSaveDetails=NULL; + m_bSavesDisplayed=false; + m_saveDetails = NULL; + m_iSaveDetailsCount = 0; + m_iTexturePacksNotInstalled = 0; + m_bCopying = false; + m_bCopyingCancelled = false; + +#ifndef _XBOX_ONE + m_bSaveTransferCancelled=false; + m_bSaveTransferInProgress=false; +#endif + m_eAction = eAction_None; + + m_bMultiplayerAllowed = ProfileManager.IsSignedInLive( m_iPad ) && ProfileManager.AllowedToPlayMultiplayer(m_iPad); + +#ifdef _XBOX_ONE + // 4J-PB - in order to buy the skin packs & texture packs, we need the signed offer ids for them, which we get in the availability info + // we need to retrieve this info though, so do it here + app.AddDLCRequest(e_Marketplace_Content); // content is skin packs, texture packs and mash-up packs +#endif + + + int iLB = -1; + +#ifdef _XBOX + XPARTY_USER_LIST partyList; + + if((XPartyGetUserList( &partyList ) != XPARTY_E_NOT_IN_PARTY ) && (partyList.dwUserCount>1)) + { + m_bInParty=true; + } + else + { + m_bInParty=false; + } +#endif + +#if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__) || defined(_DURANGO) + // Always clear the saves when we enter this menu + StorageManager.ClearSavesInfo(); +#endif + + // block input if we're waiting for DLC to install, and wipe the saves list. The end of dlc mounting custom message will fill the list again + if(app.StartInstallDLCProcess(m_iPad)==true || app.DLCInstallPending()) + { + // if we're waiting for DLC to mount, don't fill the save list. The custom message on end of dlc mounting will do that + m_bIgnoreInput = true; + } + else + { + Initialise(); + } + +#ifdef __PSVITA__ + if(CGameNetworkManager::usingAdhocMode() && SQRNetworkManager_AdHoc_Vita::GetAdhocStatus()) + { + g_NetworkManager.startAdhocMatching(); // create the client matching context and clear out the friends list + } + +#endif + + UpdateGamesList(); + + g_NetworkManager.SetSessionsUpdatedCallback( &UpdateGamesListCallback, this ); + + m_initData= new JoinMenuInitData(); + + // 4J Stu - Fix for #12530 -TCR 001 BAS Game Stability: Title will crash if the player disconnects while starting a new world and then opts to play the tutorial once they have been returned to the Main Menu. + MinecraftServer::resetFlags(); + + // If we're not ignoring input, then we aren't still waiting for the DLC to mount, and can now check for corrupt dlc. Otherwise this will happen when the dlc has finished mounting. + if( !m_bIgnoreInput) + { + app.m_dlcManager.checkForCorruptDLCAndAlert(); + } + + // 4J-PB - Only Xbox will not have trial DLC patched into the game +#ifdef _XBOX + // 4J-PB - there may be texture packs we don't have, so use the info from TMS for this + + DLC_INFO *pDLCInfo=NULL; + + // first pass - look to see if there are any that are not in the list + bool bTexturePackAlreadyListed; + bool bNeedToGetTPD=false; + Minecraft *pMinecraft = Minecraft::GetInstance(); + int texturePacksCount = pMinecraft->skins->getTexturePackCount(); + + for(unsigned int i = 0; i < app.GetDLCInfoTexturesOffersCount(); ++i) + { + bTexturePackAlreadyListed=false; +#if defined(__PS3__) || defined(__ORBIS__) + char *pchDLCName=app.GetDLCInfoTextures(i); + pDLCInfo=app.GetDLCInfo(pchDLCName); +#else + ULONGLONG ull=app.GetDLCInfoTexturesFullOffer(i); + pDLCInfo=app.GetDLCInfoForFullOfferID(ull); +#endif + for(unsigned int i = 0; i < texturePacksCount; ++i) + { + TexturePack *tp = pMinecraft->skins->getTexturePackByIndex(i); + if(pDLCInfo && pDLCInfo->iConfig==tp->getDLCParentPackId()) + { + bTexturePackAlreadyListed=true; + } + } + if(bTexturePackAlreadyListed==false) + { + // some missing + bNeedToGetTPD=true; + + m_iTexturePacksNotInstalled++; + } + } + + if(bNeedToGetTPD==true) + { + // add a TMS request for them + app.DebugPrintf("+++ Adding TMSPP request for texture pack data\n"); + app.AddTMSPPFileTypeRequest(e_DLC_TexturePackData); + m_iConfigA= new int [m_iTexturePacksNotInstalled]; + m_iTexturePacksNotInstalled=0; + + for(unsigned int i = 0; i < app.GetDLCInfoTexturesOffersCount(); ++i) + { + bTexturePackAlreadyListed=false; +#if defined(__PS3__) || defined(__ORBIS__) + char *pchDLCName=app.GetDLCInfoTextures(i); + pDLCInfo=app.GetDLCInfo(pchDLCName); +#else + ULONGLONG ull=app.GetDLCInfoTexturesFullOffer(i); + pDLCInfo=app.GetDLCInfoForFullOfferID(ull); +#endif + for(unsigned int i = 0; i < texturePacksCount; ++i) + { + TexturePack *tp = pMinecraft->skins->getTexturePackByIndex(i); + if(pDLCInfo->iConfig==tp->getDLCParentPackId()) + { + bTexturePackAlreadyListed=true; + } + } + if(bTexturePackAlreadyListed==false) + { + m_iConfigA[m_iTexturePacksNotInstalled++]=pDLCInfo->iConfig; + } + } + } + + addTimer(CHECKFORAVAILABLETEXTUREPACKS_TIMER_ID,CHECKFORAVAILABLETEXTUREPACKS_TIMER_TIME); +#endif + +#ifdef SONY_REMOTE_STORAGE_DOWNLOAD + m_eSaveTransferState = eSaveTransfer_Idle; +#endif +} + + +UIScene_LoadOrJoinMenu::~UIScene_LoadOrJoinMenu() +{ + g_NetworkManager.SetSessionsUpdatedCallback( NULL, NULL ); + app.SetLiveLinkRequired( false ); + + if(m_currentSessions) + { + for(AUTO_VAR(it, m_currentSessions->begin()); it < m_currentSessions->end(); ++it) + { + delete (*it); + } + } + +#if TO_BE_IMPLEMENTED + // Reset the background downloading, in case we changed it by attempting to download a texture pack + XBackgroundDownloadSetMode(XBACKGROUND_DOWNLOAD_MODE_AUTO); +#endif + + if(m_saveDetails) + { + for(int i = 0; i < m_iSaveDetailsCount; ++i) + { + delete m_saveDetails[i].pbThumbnailData; + } + delete [] m_saveDetails; + } +} + +void UIScene_LoadOrJoinMenu::updateTooltips() +{ + // update the tooltips + // if the saves list has focus, then we should show the Delete Save tooltip + // if the games list has focus, then we should the the View Gamercard tooltip + int iRB=-1; + int iY = -1; + int iLB = -1; + int iX=-1; + if (DoesGamesListHaveFocus() && m_buttonListGames.getItemCount() > 0) + { + iY = IDS_TOOLTIPS_VIEW_GAMERCARD; + } + else if (DoesSavesListHaveFocus()) + { + if((m_iDefaultButtonsC > 0) && (m_iSaveListIndex >= m_iDefaultButtonsC)) + { + if(StorageManager.GetSaveDisabled()) + { + iRB=IDS_TOOLTIPS_DELETESAVE; + } + else + { + if(StorageManager.EnoughSpaceForAMinSaveGame()) + { + iRB=IDS_TOOLTIPS_SAVEOPTIONS; + } + else + { + iRB=IDS_TOOLTIPS_DELETESAVE; + } + } + } + } + else if(DoesMashUpWorldHaveFocus()) + { + // If it's a mash-up pack world, give the Hide option + iRB=IDS_TOOLTIPS_HIDE; + } + + if(m_bInParty) + { + if( m_bShowingPartyGamesOnly ) iLB = IDS_TOOLTIPS_ALL_GAMES; + else iLB = IDS_TOOLTIPS_PARTY_GAMES; + } + +#if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__) + if(m_iPad == ProfileManager.GetPrimaryPad() ) iY = IDS_TOOLTIPS_GAME_INVITES; +#endif + + if(ProfileManager.IsFullVersion()==false ) + { + iRB = -1; + } + else if(StorageManager.GetSaveDisabled()) + { +#ifdef _XBOX + iX = IDS_TOOLTIPS_SELECTDEVICE; +#endif + } + else + { +#if defined _XBOX_ONE + if(ProfileManager.IsSignedInLive( m_iPad )) + { + // Is there a save from 360 on TMS? + iX=IDS_TOOLTIPS_SAVETRANSFER_DOWNLOAD; + } +#elif defined SONY_REMOTE_STORAGE_DOWNLOAD + // Is there a save from PS3 or PSVita available? + // Sony asked that this be displayed at all times so users are aware of the functionality. We'll display some text when there's no save available + //if(app.getRemoteStorage()->saveIsAvailable()) + { + bool bSignedInLive = ProfileManager.IsSignedInLive(m_iPad); + if(bSignedInLive) + { + iX=IDS_TOOLTIPS_SAVETRANSFER_DOWNLOAD; + } + } +#else + iX = IDS_TOOLTIPS_CHANGEDEVICE; +#endif + } + + ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT, IDS_TOOLTIPS_BACK, iX, iY,-1,-1,iLB,iRB); +} + +// +void UIScene_LoadOrJoinMenu::Initialise() +{ + m_iSaveListIndex = 0; + m_iGameListIndex = 0; + + m_iDefaultButtonsC = 0; + m_iMashUpButtonsC=0; + + // Check if we're in the trial version + if(ProfileManager.IsFullVersion()==false) + { + + + AddDefaultButtons(); + +#if TO_BE_IMPLEMENTED + m_pSavesList->SetCurSelVisible(0); +#endif + } + else if(StorageManager.GetSaveDisabled()) + { +#if defined(__PS3__) || defined(__ORBIS__) || defined (__PSVITA__) + GetSaveInfo(); +#else + +#if TO_BE_IMPLEMENTED + if(StorageManager.GetSaveDeviceSelected(m_iPad)) +#endif + { + // saving is disabled, but we should still be able to load from a selected save device + + + + GetSaveInfo(); + } +#if TO_BE_IMPLEMENTED + else + { + AddDefaultButtons(); + m_controlSavesTimer.setVisible( false ); + } +#endif +#endif // __PS3__ || __ORBIS + } + else + { + // 4J-PB - we need to check that there is enough space left to create a copy of the save (for a rename) + bool bCanRename = StorageManager.EnoughSpaceForAMinSaveGame(); + + GetSaveInfo(); + } + + m_bIgnoreInput=false; + app.m_dlcManager.checkForCorruptDLCAndAlert(); +} + +void UIScene_LoadOrJoinMenu::updateComponents() +{ + m_parentLayer->showComponent(m_iPad,eUIComponent_Panorama,true); + m_parentLayer->showComponent(m_iPad,eUIComponent_Logo,true); +} + +void UIScene_LoadOrJoinMenu::handleDestroy() +{ +#ifdef __PSVITA__ + app.DebugPrintf("missing InputManager.DestroyKeyboard on Vita !!!!!!\n"); +#endif + + // shut down the keyboard if it is displayed +#if ( defined __PS3__ || defined __ORBIS__ || defined _DURANGO) + InputManager.DestroyKeyboard(); +#endif +} + +void UIScene_LoadOrJoinMenu::handleGainFocus(bool navBack) +{ + UIScene::handleGainFocus(navBack); + + updateTooltips(); + + // Add load online timer + addTimer(JOIN_LOAD_ONLINE_TIMER_ID,JOIN_LOAD_ONLINE_TIMER_TIME); + + if(navBack) + { + app.SetLiveLinkRequired( true ); + + m_bMultiplayerAllowed = ProfileManager.IsSignedInLive( m_iPad ) && ProfileManager.AllowedToPlayMultiplayer(m_iPad); + + // re-enable button presses + m_bIgnoreInput=false; + + // block input if we're waiting for DLC to install, and wipe the saves list. The end of dlc mounting custom message will fill the list again + if(app.StartInstallDLCProcess(m_iPad)==false) + { + // not doing a mount, so re-enable input + m_bIgnoreInput=false; + } + else + { + m_bIgnoreInput=true; + m_buttonListSaves.clearList(); + m_controlSavesTimer.setVisible(true); + } + + if( m_bMultiplayerAllowed ) + { +#if TO_BE_IMPLEMENTED + HXUICLASS hClassFullscreenProgress = XuiFindClass( L"CScene_FullscreenProgress" ); + HXUICLASS hClassConnectingProgress = XuiFindClass( L"CScene_ConnectingProgress" ); + + // If we are navigating back from a full screen progress scene, then that means a connection attempt failed + if( XuiIsInstanceOf( hSceneFrom, hClassFullscreenProgress ) || XuiIsInstanceOf( hSceneFrom, hClassConnectingProgress ) ) + { + UpdateGamesList(); + } +#endif + } + else + { + m_buttonListGames.clearList(); + m_controlJoinTimer.setVisible(true); + m_labelNoGames.setVisible(false); +#if TO_BE_IMPLEMENTED + m_SavesList.InitFocus(m_iPad); +#endif + } + + // are we back here because of a delete of a corrupt save? + + if(app.GetCorruptSaveDeleted()) + { + // wipe the list and repopulate it + m_iState=e_SavesRepopulateAfterDelete; + app.SetCorruptSaveDeleted(false); + } + } +} + +void UIScene_LoadOrJoinMenu::handleLoseFocus() +{ + // Kill load online timer + killTimer(JOIN_LOAD_ONLINE_TIMER_ID); +} + +wstring UIScene_LoadOrJoinMenu::getMoviePath() +{ + return L"LoadOrJoinMenu"; +} + +void UIScene_LoadOrJoinMenu::tick() +{ + UIScene::tick(); + +#if (defined __PS3__ || defined __ORBIS__ || defined _DURANGO || defined _WINDOWS64 || defined __PSVITA__) + if(m_bExitScene) // navigate forward or back + { + if(!m_bRetrievingSaveThumbnails) + { + // need to wait for any callback retrieving thumbnail to complete + navigateBack(); + } + } + // Stop loading thumbnails if we navigate forwards + if(hasFocus(m_iPad)) + { +#if defined(_XBOX_ONE) || defined(__ORBIS__) + if(m_bUpdateSaveSize) + { + if((m_iDefaultButtonsC > 0) && (m_iSaveListIndex >= m_iDefaultButtonsC)) + { + m_spaceIndicatorSaves.selectSave(m_iSaveListIndex-m_iDefaultButtonsC); + } + else + { + m_spaceIndicatorSaves.selectSave(-1); + } + m_bUpdateSaveSize = false; + } +#endif + // Display the saves if we have them + if(!m_bSavesDisplayed) + { + m_pSaveDetails=StorageManager.ReturnSavesInfo(); + if(m_pSaveDetails!=NULL) + { + //CD - Fix - Adding define for ORBIS/XBOXONE +#if defined(_XBOX_ONE) || defined(__ORBIS__) + m_spaceIndicatorSaves.reset(); +#endif + + AddDefaultButtons(); + m_bSavesDisplayed=true; + UpdateGamesList(); + + if(m_saveDetails!=NULL) + { + for(unsigned int i = 0; i < m_iSaveDetailsCount; ++i) + { + if(m_saveDetails[i].pbThumbnailData!=NULL) + { + delete m_saveDetails[i].pbThumbnailData; + } + } + delete m_saveDetails; + } + m_saveDetails = new SaveListDetails[m_pSaveDetails->iSaveC]; + + m_iSaveDetailsCount = m_pSaveDetails->iSaveC; + for(unsigned int i = 0; i < m_pSaveDetails->iSaveC; ++i) + { +#if defined(_XBOX_ONE) + m_spaceIndicatorSaves.addSave(m_pSaveDetails->SaveInfoA[i].totalSize); +#elif defined(__ORBIS__) + m_spaceIndicatorSaves.addSave(m_pSaveDetails->SaveInfoA[i].blocksUsed * (32 * 1024) ); +#endif +#ifdef _DURANGO + m_buttonListSaves.addItem(m_pSaveDetails->SaveInfoA[i].UTF16SaveTitle, L""); + + m_saveDetails[i].saveId = i; + memcpy(m_saveDetails[i].UTF16SaveName, m_pSaveDetails->SaveInfoA[i].UTF16SaveTitle, 128); + memcpy(m_saveDetails[i].UTF16SaveFilename, m_pSaveDetails->SaveInfoA[i].UTF16SaveFilename, MAX_SAVEFILENAME_LENGTH); +#else + m_buttonListSaves.addItem(m_pSaveDetails->SaveInfoA[i].UTF8SaveTitle, L""); + + m_saveDetails[i].saveId = i; + memcpy(m_saveDetails[i].UTF8SaveName, m_pSaveDetails->SaveInfoA[i].UTF8SaveTitle, 128); + memcpy(m_saveDetails[i].UTF8SaveFilename, m_pSaveDetails->SaveInfoA[i].UTF8SaveFilename, MAX_SAVEFILENAME_LENGTH); +#endif + } + m_controlSavesTimer.setVisible( false ); + + // set focus on the first button + + } + } + + if(!m_bExitScene && m_bSavesDisplayed && !m_bRetrievingSaveThumbnails && !m_bAllLoaded) + { + if( m_iRequestingThumbnailId < (m_buttonListSaves.getItemCount() - m_iDefaultButtonsC )) + { + m_bRetrievingSaveThumbnails = true; + app.DebugPrintf("Requesting the first thumbnail\n"); + // set the save to load + PSAVE_DETAILS pSaveDetails=StorageManager.ReturnSavesInfo(); + C4JStorage::ESaveGameState eLoadStatus=StorageManager.LoadSaveDataThumbnail(&pSaveDetails->SaveInfoA[(int)m_iRequestingThumbnailId],&LoadSaveDataThumbnailReturned,this); + + if(eLoadStatus!=C4JStorage::ESaveGame_GetSaveThumbnail) + { + // something went wrong + m_bRetrievingSaveThumbnails=false; + m_bAllLoaded = true; + } + } + } + else if (m_bSavesDisplayed && m_bSaveThumbnailReady) + { + m_bSaveThumbnailReady = false; + + // check we're not waiting to exit the scene + if(!m_bExitScene) + { + // convert to utf16 + uint16_t u16Message[MAX_SAVEFILENAME_LENGTH]; +#ifdef _DURANGO + // Already utf16 on durango + memcpy(u16Message, m_saveDetails[m_iRequestingThumbnailId].UTF16SaveFilename, MAX_SAVEFILENAME_LENGTH); +#elif defined(_WINDOWS64) + int result = ::MultiByteToWideChar( + CP_UTF8, // convert from UTF-8 + MB_ERR_INVALID_CHARS, // error on invalid chars + m_saveDetails[m_iRequestingThumbnailId].UTF8SaveFilename, // source UTF-8 string + MAX_SAVEFILENAME_LENGTH, // total length of source UTF-8 string, + // in CHAR's (= bytes), including end-of-string \0 + (wchar_t *)u16Message, // destination buffer + MAX_SAVEFILENAME_LENGTH // size of destination buffer, in WCHAR's + ); +#else +#ifdef __PS3 + size_t srcmax,dstmax; +#else + uint32_t srcmax,dstmax; + uint32_t srclen,dstlen; +#endif + srcmax=MAX_SAVEFILENAME_LENGTH; + dstmax=MAX_SAVEFILENAME_LENGTH; + +#if defined(__PS3__) + L10nResult lres= UTF8stoUTF16s((uint8_t *)m_saveDetails[m_iRequestingThumbnailId].UTF8SaveFilename,&srcmax,u16Message,&dstmax); +#else + SceCesUcsContext context; + sceCesUcsContextInit(&context); + + sceCesUtf8StrToUtf16Str(&context, (uint8_t *)m_saveDetails[m_iRequestingThumbnailId].UTF8SaveFilename,srcmax,&srclen,u16Message,dstmax,&dstlen); +#endif +#endif + if( m_saveDetails[m_iRequestingThumbnailId].pbThumbnailData ) + { + registerSubstitutionTexture((wchar_t *)u16Message,m_saveDetails[m_iRequestingThumbnailId].pbThumbnailData,m_saveDetails[m_iRequestingThumbnailId].dwThumbnailSize); + } + m_buttonListSaves.setTextureName(m_iRequestingThumbnailId + m_iDefaultButtonsC, (wchar_t *)u16Message); + + ++m_iRequestingThumbnailId; + if( m_iRequestingThumbnailId < (m_buttonListSaves.getItemCount() - m_iDefaultButtonsC )) + { + app.DebugPrintf("Requesting another thumbnail\n"); + // set the save to load + PSAVE_DETAILS pSaveDetails=StorageManager.ReturnSavesInfo(); + C4JStorage::ESaveGameState eLoadStatus=StorageManager.LoadSaveDataThumbnail(&pSaveDetails->SaveInfoA[(int)m_iRequestingThumbnailId],&LoadSaveDataThumbnailReturned,this); + if(eLoadStatus!=C4JStorage::ESaveGame_GetSaveThumbnail) + { + // something went wrong + m_bRetrievingSaveThumbnails=false; + m_bAllLoaded = true; + } + } + else + { + m_bRetrievingSaveThumbnails = false; + m_bAllLoaded = true; + } + } + else + { + // stop retrieving thumbnails, and exit + m_bRetrievingSaveThumbnails = false; + } + } + } + + switch(m_iState) + { + case e_SavesIdle: + break; + case e_SavesRepopulate: + m_bIgnoreInput = false; + m_iState=e_SavesIdle; + m_bAllLoaded=false; + m_bRetrievingSaveThumbnails=false; + m_iRequestingThumbnailId = 0; + GetSaveInfo(); + break; + case e_SavesRepopulateAfterMashupHide: + m_bIgnoreInput = false; + m_iRequestingThumbnailId = 0; + m_bAllLoaded=false; + m_bRetrievingSaveThumbnails=false; + m_bSavesDisplayed=false; + m_iSaveInfoC=0; + m_buttonListSaves.clearList(); + GetSaveInfo(); + m_iState=e_SavesIdle; + break; + case e_SavesRepopulateAfterDelete: + case e_SavesRepopulateAfterTransferDownload: + m_bIgnoreInput = false; + m_iRequestingThumbnailId = 0; + m_bAllLoaded=false; + m_bRetrievingSaveThumbnails=false; + m_bSavesDisplayed=false; + m_iSaveInfoC=0; + m_buttonListSaves.clearList(); + StorageManager.ClearSavesInfo(); + GetSaveInfo(); + m_iState=e_SavesIdle; + break; + } +#else + if(!m_bSavesDisplayed) + { + AddDefaultButtons(); + m_bSavesDisplayed=true; + m_controlSavesTimer.setVisible( false ); + } +#endif + +#ifdef _XBOX_ONE + if(g_NetworkManager.ShouldMessageForFullSession()) + { + UINT uiIDA[1]; + uiIDA[0]=IDS_CONFIRM_OK; + ui.RequestMessageBox( IDS_CONNECTION_FAILED, IDS_IN_PARTY_SESSION_FULL, uiIDA,1,ProfileManager.GetPrimaryPad(),NULL,NULL, app.GetStringTable()); + } +#endif + + // SAVE TRANSFERS +#ifdef __ORBIS__ + // check the status of the PSPlus common dialog + switch (sceNpCommerceDialogUpdateStatus()) + { + case SCE_COMMON_DIALOG_STATUS_FINISHED: + { + SceNpCommerceDialogResult Result; + sceNpCommerceDialogGetResult(&Result); + sceNpCommerceDialogTerminate(); + + if(Result.authorized) + { + // they just became a PSPlus member + ProfileManager.PsPlusUpdate(ProfileManager.GetPrimaryPad(), &Result); + + } + else + { + + } + + // 4J-JEV: Fix for PS4 #5148 - [ONLINE] If the user attempts to join a game when they do not have Playstation Plus, the title will lose all functionality. + m_bIgnoreInput = false; + } + break; + default: + break; + } +#endif + +} + +void UIScene_LoadOrJoinMenu::GetSaveInfo() +{ + unsigned int uiSaveC=0; + + // This will return with the number retrieved in uiSaveC + + if(app.DebugSettingsOn() && app.GetLoadSavesFromFolderEnabled()) + { +#ifdef __ORBIS__ + // We need to make sure this is non-null so that we have an idea of free space + m_pSaveDetails=StorageManager.ReturnSavesInfo(); + if(m_pSaveDetails==NULL) + { + C4JStorage::ESaveGameState eSGIStatus= StorageManager.GetSavesInfo(m_iPad,NULL,this,"save"); + } +#endif + + uiSaveC = 0; +#ifdef _XBOX + File savesDir(L"GAME:\\Saves"); +#else + File savesDir(L"Saves"); +#endif + if( savesDir.exists() ) + { + m_saves = savesDir.listFiles(); + uiSaveC = (unsigned int)m_saves->size(); + } + // add the New Game and Tutorial after the saves list is retrieved, if there are any saves + + // Add two for New Game and Tutorial + unsigned int listItems = uiSaveC; + + AddDefaultButtons(); + + for(unsigned int i=0;i<listItems;i++) + { + + wstring wName = m_saves->at(i)->getName(); + wchar_t *name = new wchar_t[wName.size()+1]; + for(unsigned int j = 0; j < wName.size(); ++j) + { + name[j] = wName[j]; + } + name[wName.size()] = 0; + m_buttonListSaves.addItem(name,L""); + } + m_bSavesDisplayed = true; + m_bAllLoaded = true; + m_bIgnoreInput = false; + } + else + { + // clear the saves list + m_bSavesDisplayed = false; // we're blocking the exit from this scene until complete + m_buttonListSaves.clearList(); + m_iSaveInfoC=0; + m_controlSavesTimer.setVisible(true); + + m_pSaveDetails=StorageManager.ReturnSavesInfo(); + if(m_pSaveDetails==NULL) + { + C4JStorage::ESaveGameState eSGIStatus= StorageManager.GetSavesInfo(m_iPad,NULL,this,"save"); + } + +#if TO_BE_IMPLEMENTED + if(eSGIStatus==C4JStorage::ESGIStatus_NoSaves) + { + uiSaveC=0; + m_controlSavesTimer.setVisible( false ); + m_SavesList.SetEnable(TRUE); + } +#endif + } + + return; +} + +void UIScene_LoadOrJoinMenu::AddDefaultButtons() +{ + m_iDefaultButtonsC = 0; + m_iMashUpButtonsC=0; + m_generators.clear(); + + m_buttonListSaves.addItem(app.GetString(IDS_CREATE_NEW_WORLD)); + m_iDefaultButtonsC++; + + int i = 0; + + for(AUTO_VAR(it, app.getLevelGenerators()->begin()); it != app.getLevelGenerators()->end(); ++it) + { + LevelGenerationOptions *levelGen = *it; + + // retrieve the save icon from the texture pack, if there is one + unsigned int uiTexturePackID=levelGen->getRequiredTexturePackId(); + + if(uiTexturePackID!=0) + { + unsigned int uiMashUpWorldsBitmask=app.GetMashupPackWorlds(m_iPad); + + if((uiMashUpWorldsBitmask & (1<<(uiTexturePackID-1024)))==0) + { + // this world is hidden, so skip + continue; + } + } + + m_generators.push_back(levelGen); + m_buttonListSaves.addItem(levelGen->getWorldName()); + + if(uiTexturePackID!=0) + { + // increment the count of the mash-up pack worlds in the save list + m_iMashUpButtonsC++; + TexturePack *tp = Minecraft::GetInstance()->skins->getTexturePackById(levelGen->getRequiredTexturePackId()); + DWORD dwImageBytes; + PBYTE pbImageData = tp->getPackIcon(dwImageBytes); + + if(dwImageBytes > 0 && pbImageData) + { + wchar_t imageName[64]; + swprintf(imageName,64,L"tpack%08x",tp->getId()); + registerSubstitutionTexture(imageName, pbImageData, dwImageBytes); + m_buttonListSaves.setTextureName( m_buttonListSaves.getItemCount() - 1, imageName ); + } + } + + ++i; + } + m_iDefaultButtonsC += i; +} + +void UIScene_LoadOrJoinMenu::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled) +{ + if(m_bIgnoreInput) return; + + // if we're retrieving save info, ignore key presses + if(!m_bSavesDisplayed) return; + + ui.AnimateKeyPress(m_iPad, key, repeat, pressed, released); + + switch(key) + { + case ACTION_MENU_CANCEL: + if(pressed) + { +#if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__) + m_bExitScene=true; +#else + navigateBack(); +#endif + handled = true; + } + break; + case ACTION_MENU_X: +#if TO_BE_IMPLEMENTED + // Change device + // Fix for #12531 - TCR 001: BAS Game Stability: When a player selects to change a storage + // device, and repeatedly backs out of the SD screen, disconnects from LIVE, and then selects a SD, the title crashes. + m_bIgnoreInput=true; + StorageManager.SetSaveDevice(&CScene_MultiGameJoinLoad::DeviceSelectReturned,this,true); + ui.PlayUISFX(eSFX_Press); +#endif + // Save Transfer +#ifdef _XBOX_ONE + if(ProfileManager.IsSignedInLive( m_iPad )) + { + UIScene_LoadOrJoinMenu::s_ulFileSize=0; + LaunchSaveTransfer(); + } +#endif +#ifdef SONY_REMOTE_STORAGE_DOWNLOAD + { + bool bSignedInLive = ProfileManager.IsSignedInLive(iPad); + if(bSignedInLive) + { + LaunchSaveTransfer(); + } + } +#endif + break; + case ACTION_MENU_Y: +#if defined(__PS3__) || defined(__PSVITA__) || defined(__ORBIS__) + m_eAction = eAction_ViewInvites; + if(pressed && iPad == ProfileManager.GetPrimaryPad()) + { +#ifdef __ORBIS__ + // Check if PSN is unavailable because of age restriction + int npAvailability = ProfileManager.getNPAvailability(iPad); + if (npAvailability == SCE_NP_ERROR_AGE_RESTRICTION) + { + UINT uiIDA[1]; + uiIDA[0] = IDS_OK; + ui.RequestMessageBox(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, iPad, NULL, NULL, app.GetStringTable()); + + break; + } +#endif + + // are we offline? + if(!ProfileManager.IsSignedInLive(iPad)) + { + // get them to sign in to online + UINT uiIDA[2]; + uiIDA[0]=IDS_PRO_NOTONLINE_ACCEPT; + uiIDA[1]=IDS_PRO_NOTONLINE_DECLINE; + ui.RequestMessageBox(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 2, ProfileManager.GetPrimaryPad(), &UIScene_LoadOrJoinMenu::MustSignInReturnedPSN, this, app.GetStringTable(),NULL,0,false); + } + else + { +#ifdef __ORBIS__ + SQRNetworkManager_Orbis::RecvInviteGUI(); +#elif defined __PSVITA__ + SQRNetworkManager_Vita::RecvInviteGUI(); +#else + int ret = sceNpBasicRecvMessageCustom(SCE_NP_BASIC_MESSAGE_MAIN_TYPE_INVITE, SCE_NP_BASIC_RECV_MESSAGE_OPTIONS_INCLUDE_BOOTABLE, SYS_MEMORY_CONTAINER_ID_INVALID); + app.DebugPrintf("sceNpBasicRecvMessageCustom return %d ( %08x )\n", ret, ret); +#endif + } + } +#elif defined(_DURANGO) + if(getControlFocus() == eControl_GamesList && m_buttonListGames.getItemCount() > 0) + { + DWORD nIndex = m_buttonListGames.getCurrentSelection(); + FriendSessionInfo *pSelectedSession = m_currentSessions->at( nIndex ); + + PlayerUID uid = pSelectedSession->searchResult.m_playerXuids[0]; + if( uid != INVALID_XUID ) ProfileManager.ShowProfileCard(ProfileManager.GetLockedProfile(),uid); + ui.PlayUISFX(eSFX_Press); + } +#endif // __PS3__ || __ORBIS__ + break; + + case ACTION_MENU_RIGHT_SCROLL: + if(DoesSavesListHaveFocus()) + { + // 4J-PB - check we are on a valid save + if((m_iDefaultButtonsC != 0) && (m_iSaveListIndex >= m_iDefaultButtonsC)) + { + m_bIgnoreInput = true; + + // Could be delete save or Save Options + if(StorageManager.GetSaveDisabled()) + { + // delete the save game + // Have to ask the player if they are sure they want to delete this game + UINT uiIDA[2]; + uiIDA[0]=IDS_CONFIRM_CANCEL; + uiIDA[1]=IDS_CONFIRM_OK; + ui.RequestMessageBox(IDS_TOOLTIPS_DELETESAVE, IDS_TEXT_DELETE_SAVE, uiIDA, 2, iPad,&UIScene_LoadOrJoinMenu::DeleteSaveDialogReturned,this, app.GetStringTable(),NULL,0,false); + } + else + { + if(StorageManager.EnoughSpaceForAMinSaveGame()) + { + UINT uiIDA[4]; + uiIDA[0]=IDS_CONFIRM_CANCEL; + uiIDA[1]=IDS_TITLE_RENAMESAVE; + uiIDA[2]=IDS_TOOLTIPS_DELETESAVE; + int numOptions = 3; +#ifdef SONY_REMOTE_STORAGE_UPLOAD + if(ProfileManager.IsSignedInLive(ProfileManager.GetPrimaryPad())) + { + numOptions = 4; + uiIDA[3]=IDS_TOOLTIPS_SAVETRANSFER_UPLOAD; + } +#endif +#if defined _XBOX_ONE || defined __ORBIS__ + numOptions = 4; + uiIDA[3]=IDS_COPYSAVE; +#endif + ui.RequestMessageBox(IDS_TOOLTIPS_SAVEOPTIONS, IDS_TEXT_SAVEOPTIONS, uiIDA, numOptions, iPad,&UIScene_LoadOrJoinMenu::SaveOptionsDialogReturned,this, app.GetStringTable(),NULL,0,false); + } + else + { + // delete the save game + // Have to ask the player if they are sure they want to delete this game + UINT uiIDA[2]; + uiIDA[0]=IDS_CONFIRM_CANCEL; + uiIDA[1]=IDS_CONFIRM_OK; + ui.RequestMessageBox(IDS_TOOLTIPS_DELETESAVE, IDS_TEXT_DELETE_SAVE, uiIDA, 2,iPad,&UIScene_LoadOrJoinMenu::DeleteSaveDialogReturned,this, app.GetStringTable(),NULL,0,false); + } + } + ui.PlayUISFX(eSFX_Press); + } + } + else if(DoesMashUpWorldHaveFocus()) + { + // hiding a mash-up world + if((m_iSaveListIndex != JOIN_LOAD_CREATE_BUTTON_INDEX)) + { + LevelGenerationOptions *levelGen = m_generators.at(m_iSaveListIndex - 1); + + if(!levelGen->isTutorial()) + { + if(levelGen->requiresTexturePack()) + { + unsigned int uiPackID=levelGen->getRequiredTexturePackId(); + + m_bIgnoreInput = true; + app.HideMashupPackWorld(m_iPad,uiPackID); + + // update the saves list + m_iState = e_SavesRepopulateAfterMashupHide; + } + } + } + ui.PlayUISFX(eSFX_Press); + + } + break; + case ACTION_MENU_LEFT_SCROLL: +#ifdef _XBOX + if( m_bInParty ) + { + m_bShowingPartyGamesOnly = !m_bShowingPartyGamesOnly; + UpdateGamesList(); + CXuiSceneBase::PlayUISFX(eSFX_Press); + } +#endif + break; + case ACTION_MENU_LEFT: + case ACTION_MENU_RIGHT: + { + // if we are on the saves menu, check there are games in the games list to move to + if(DoesSavesListHaveFocus()) + { + if( m_buttonListGames.getItemCount() > 0) + { + sendInputToMovie(key, repeat, pressed, released); + } + } + else + { + sendInputToMovie(key, repeat, pressed, released); + } + } + break; + + case ACTION_MENU_OK: +#ifdef __ORBIS__ + case ACTION_MENU_TOUCHPAD_PRESS: +#endif + case ACTION_MENU_UP: + case ACTION_MENU_DOWN: + case ACTION_MENU_PAGEUP: + case ACTION_MENU_PAGEDOWN: + sendInputToMovie(key, repeat, pressed, released); + handled = true; + break; + } +} + +int UIScene_LoadOrJoinMenu::KeyboardCompleteWorldNameCallback(LPVOID lpParam,bool bRes) +{ + // 4J HEG - No reason to set value if keyboard was cancelled + UIScene_LoadOrJoinMenu *pClass=(UIScene_LoadOrJoinMenu *)lpParam; + pClass->m_bIgnoreInput=false; + if (bRes) + { + uint16_t ui16Text[128]; + ZeroMemory(ui16Text, 128 * sizeof(uint16_t) ); + InputManager.GetText(ui16Text); + + // check the name is valid + if(ui16Text[0]!=0) + { +#if (defined __PS3__ || defined __ORBIS__ || defined _DURANGO || defined(__PSVITA__)) + // open the save and overwrite the metadata + StorageManager.RenameSaveData(pClass->m_iSaveListIndex - pClass->m_iDefaultButtonsC, ui16Text,&UIScene_LoadOrJoinMenu::RenameSaveDataReturned,pClass); +#endif + } + else + { + pClass->m_bIgnoreInput=false; + pClass->updateTooltips(); + } + } + else + { + pClass->m_bIgnoreInput=false; + pClass->updateTooltips(); + } + + + return 0; +} +void UIScene_LoadOrJoinMenu::handleInitFocus(F64 controlId, F64 childId) +{ + app.DebugPrintf(app.USER_SR, "UIScene_LoadOrJoinMenu::handleInitFocus - %d , %d\n", (int)controlId, (int)childId); +} + +void UIScene_LoadOrJoinMenu::handleFocusChange(F64 controlId, F64 childId) +{ + app.DebugPrintf(app.USER_SR, "UIScene_LoadOrJoinMenu::handleFocusChange - %d , %d\n", (int)controlId, (int)childId); + + switch((int)controlId) + { + case eControl_GamesList: + m_iGameListIndex = childId; + m_buttonListGames.updateChildFocus( (int) childId ); + break; + case eControl_SavesList: + m_iSaveListIndex = childId; + m_bUpdateSaveSize = true; + break; + }; + updateTooltips(); +} + + +#ifdef SONY_REMOTE_STORAGE_DOWNLOAD +void UIScene_LoadOrJoinMenu::remoteStorageGetSaveCallback(LPVOID lpParam, SonyRemoteStorage::Status s, int error_code) +{ + app.DebugPrintf("remoteStorageGetCallback err : 0x%08x\n", error_code); + assert(error_code == 0); + ((UIScene_LoadOrJoinMenu*)lpParam)->LoadSaveFromCloud(); +} +#endif + +void UIScene_LoadOrJoinMenu::handlePress(F64 controlId, F64 childId) +{ + switch((int)controlId) + { + case eControl_SavesList: + { + m_bIgnoreInput=true; + + int lGenID = (int)childId - 1; + + //CD - Added for audio + ui.PlayUISFX(eSFX_Press); + + if((int)childId == JOIN_LOAD_CREATE_BUTTON_INDEX) + { + app.SetTutorialMode( false ); + + m_controlJoinTimer.setVisible( false ); + + app.SetCorruptSaveDeleted(false); + + CreateWorldMenuInitData *params = new CreateWorldMenuInitData(); + params->iPad = m_iPad; + ui.NavigateToScene(m_iPad,eUIScene_CreateWorldMenu,(void *)params); + } + else if (lGenID < m_generators.size()) + { + LevelGenerationOptions *levelGen = m_generators.at(lGenID); + app.SetTutorialMode( levelGen->isTutorial() ); + // Reset the autosave time + app.SetAutosaveTimerTime(); + + if(levelGen->isTutorial()) + { + LoadLevelGen(levelGen); + } + else + { + LoadMenuInitData *params = new LoadMenuInitData(); + params->iPad = m_iPad; + // need to get the iIndex from the list item, since the position in the list doesn't correspond to the GetSaveGameInfo list because of sorting + params->iSaveGameInfoIndex=-1; + //params->pbSaveRenamed=&m_bSaveRenamed; + params->levelGen = levelGen; + params->saveDetails = NULL; + + // navigate to the settings scene + ui.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_LoadMenu, params); + } + } + else + { +#ifdef __ORBIS__ + // check if this is a damaged save + PSAVE_INFO pSaveInfo = &m_pSaveDetails->SaveInfoA[((int)childId)-m_iDefaultButtonsC]; + if(pSaveInfo->thumbnailData == NULL && pSaveInfo->modifiedTime == 0) // no thumbnail data and time of zero and zero blocks useset for corrupt files + { + // give the option to delete the save + UINT uiIDA[2]; + uiIDA[0]=IDS_CONFIRM_CANCEL; + uiIDA[1]=IDS_CONFIRM_OK; + ui.RequestMessageBox(IDS_CORRUPT_OR_DAMAGED_SAVE_TITLE, IDS_CORRUPT_OR_DAMAGED_SAVE_TEXT, uiIDA, 2, ProfileManager.GetPrimaryPad(),&UIScene_LoadOrJoinMenu::DeleteSaveDialogReturned,this, app.GetStringTable(),NULL,0,false); + + } + else +#endif + { + app.SetTutorialMode( false ); + + if(app.DebugSettingsOn() && app.GetLoadSavesFromFolderEnabled()) + { + LoadSaveFromDisk(m_saves->at((int)childId-m_iDefaultButtonsC)); + } + else + { + LoadMenuInitData *params = new LoadMenuInitData(); + params->iPad = m_iPad; + // need to get the iIndex from the list item, since the position in the list doesn't correspond to the GetSaveGameInfo list because of sorting + params->iSaveGameInfoIndex=((int)childId)-m_iDefaultButtonsC; + //params->pbSaveRenamed=&m_bSaveRenamed; + params->levelGen = NULL; + params->saveDetails = &m_saveDetails[ ((int)childId)-m_iDefaultButtonsC ]; + +#ifdef _XBOX_ONE + // On XB1, saves might need syncing, in which case inform the user so they can decide whether they want to wait for this to happen + if( m_pSaveDetails->SaveInfoA[params->iSaveGameInfoIndex].needsSync ) + { + unsigned int uiIDA[2]; + uiIDA[0]=IDS_CONFIRM_SYNC; + uiIDA[1]=IDS_CONFIRM_CANCEL; + + m_loadMenuInitData = params; + ui.RequestMessageBox(IDS_LOAD_SAVED_WORLD, IDS_CONFIRM_SYNC_REQUIRED, uiIDA, 2, ProfileManager.GetPrimaryPad(),&NeedSyncMessageReturned,this,app.GetStringTable(),NULL,0,false); + } + else +#endif + { + // navigate to the settings scene + ui.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_LoadMenu, params); + } + } + } + } + } + break; + case eControl_GamesList: + { + m_bIgnoreInput=true; + + m_eAction = eAction_JoinGame; + + //CD - Added for audio + ui.PlayUISFX(eSFX_Press); + + { + int nIndex = (int)childId; + m_iGameListIndex = nIndex; + CheckAndJoinGame(nIndex); + } + + break; + } + } +} + +void UIScene_LoadOrJoinMenu::CheckAndJoinGame(int gameIndex) +{ + if( m_buttonListGames.getItemCount() > 0 && gameIndex < m_currentSessions->size() ) + { +#if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__) + // 4J-PB - is the player allowed to join games? + bool noUGC=false; + bool bContentRestricted=false; + + // we're online, since we are joining a game + ProfileManager.GetChatAndContentRestrictions(m_iPad,true,&noUGC,&bContentRestricted,NULL); + +#ifdef __ORBIS__ + // 4J Stu - On PS4 we don't restrict playing multiplayer based on chat restriction, so remove this check + noUGC = false; + + bool bPlayStationPlus=true; + int iPadWithNoPlaystationPlus=0; + bool isSignedInLive = true; + int iPadNotSignedInLive = -1; + for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i) + { + if( InputManager.IsPadConnected(i) || ProfileManager.IsSignedIn(i) ) + { + if (isSignedInLive && !ProfileManager.IsSignedInLive(i)) + { + // Record the first non signed in live pad + iPadNotSignedInLive = i; + } + + isSignedInLive = isSignedInLive && ProfileManager.IsSignedInLive(i); + if(ProfileManager.HasPlayStationPlus(i)==false) + { + bPlayStationPlus=false; + break; + } + } + } +#endif +#ifdef __PSVITA__ + if( CGameNetworkManager::usingAdhocMode() ) + { + bContentRestricted = false; + noUGC = false; + } +#endif + + if(noUGC) + { + // not allowed to join +#ifndef __PSVITA__ + UINT uiIDA[1]; + uiIDA[0]=IDS_CONFIRM_OK; + // Not allowed to play online + ui.RequestMessageBox(IDS_ONLINE_GAME, IDS_CHAT_RESTRICTION_UGC, uiIDA, 1, m_iPad,NULL,this,app.GetStringTable(),NULL,0,false); +#else + // Not allowed to play online + ProfileManager.ShowSystemMessage( SCE_MSG_DIALOG_SYSMSG_TYPE_TRC_PSN_CHAT_RESTRICTION, 0 ); +#endif + + m_bIgnoreInput=false; + return; + } + else if(bContentRestricted) + { + ui.RequestContentRestrictedMessageBox(); + + m_bIgnoreInput=false; + return; + } +#ifdef __ORBIS__ + // If this is an online game but not all players are signed in to Live, stop! + else if (!isSignedInLive) + { + UINT uiIDA[1]; + uiIDA[0]=IDS_CONFIRM_OK; + + // Check if PSN is unavailable because of age restriction + int npAvailability = ProfileManager.getNPAvailability(iPadNotSignedInLive); + if (npAvailability == SCE_NP_ERROR_AGE_RESTRICTION) + { + m_bIgnoreInput = false; + // 4J Stu - This is a bit messy and is due to the library incorrectly returning false for IsSignedInLive if the npAvailability isn't SCE_OK + ui.RequestMessageBox(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, iPadNotSignedInLive, NULL, NULL, app.GetStringTable()); + } + else + { + ui.RequestMessageBox( IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA,1,iPadNotSignedInLive, &UIScene_LoadOrJoinMenu::MustSignInReturnedPSN, this, app.GetStringTable()); + } + return; + } + else if(bPlayStationPlus==false) + { + // PS Plus upsell + // 4J-PB - we're not allowed to show the text Playstation Plus - have to call the upsell all the time! + // upsell psplus + int32_t iResult=sceNpCommerceDialogInitialize(); + + SceNpCommerceDialogParam param; + sceNpCommerceDialogParamInitialize(¶m); + param.mode=SCE_NP_COMMERCE_DIALOG_MODE_PLUS; + param.features = SCE_NP_PLUS_FEATURE_REALTIME_MULTIPLAY; + param.userId = ProfileManager.getUserID(iPadWithNoPlaystationPlus); + + iResult=sceNpCommerceDialogOpen(¶m); + + // UINT uiIDA[2]; + // uiIDA[0]=IDS_CONFIRM_OK; + // uiIDA[1]=IDS_PLAYSTATIONPLUS_SIGNUP; + // ui.RequestMessageBox( IDS_FAILED_TO_CREATE_GAME_TITLE, IDS_NO_PLAYSTATIONPLUS, uiIDA,2,ProfileManager.GetPrimaryPad(),&UIScene_LoadOrJoinMenu::PSPlusReturned,this, app.GetStringTable(),NULL,0,false); + + m_bIgnoreInput=false; + return; + } + +#endif +#endif + + //CScene_MultiGameInfo::JoinMenuInitData *initData = new CScene_MultiGameInfo::JoinMenuInitData(); + m_initData->iPad = 0;; + m_initData->selectedSession = m_currentSessions->at( gameIndex ); + + // check that we have the texture pack available + // If it's not the default texture pack + if(m_initData->selectedSession->data.texturePackParentId!=0) + { + int texturePacksCount = Minecraft::GetInstance()->skins->getTexturePackCount(); + bool bHasTexturePackInstalled=false; + + for(int i=0;i<texturePacksCount;i++) + { + TexturePack *tp = Minecraft::GetInstance()->skins->getTexturePackByIndex(i); + if(tp->getDLCParentPackId()==m_initData->selectedSession->data.texturePackParentId) + { + bHasTexturePackInstalled=true; + break; + } + } + + if(bHasTexturePackInstalled==false) + { + // upsell the texture pack + // tell sentient about the upsell of the full version of the skin pack +#ifdef _XBOX + ULONGLONG ullOfferID_Full; + app.GetDLCFullOfferIDForPackID(m_initData->selectedSession->data.texturePackParentId,&ullOfferID_Full); + + TelemetryManager->RecordUpsellPresented(m_iPad, eSet_UpsellID_Texture_DLC, ullOfferID_Full & 0xFFFFFFFF); +#endif + UINT uiIDA[2]; + + uiIDA[0]=IDS_TEXTUREPACK_FULLVERSION; + //uiIDA[1]=IDS_TEXTURE_PACK_TRIALVERSION; + uiIDA[1]=IDS_CONFIRM_CANCEL; + + + // Give the player a warning about the texture pack missing + ui.RequestMessageBox(IDS_DLC_TEXTUREPACK_NOT_PRESENT_TITLE, IDS_DLC_TEXTUREPACK_NOT_PRESENT, uiIDA, 2, m_iPad,&UIScene_LoadOrJoinMenu::TexturePackDialogReturned,this,app.GetStringTable(),NULL,0,false); + + return; + } + } + m_controlJoinTimer.setVisible( false ); + +#ifdef _XBOX + // Reset the background downloading, in case we changed it by attempting to download a texture pack + XBackgroundDownloadSetMode(XBACKGROUND_DOWNLOAD_MODE_AUTO); +#endif + + m_bIgnoreInput=true; + ui.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_JoinMenu,m_initData); + } +} + +void UIScene_LoadOrJoinMenu::LoadLevelGen(LevelGenerationOptions *levelGen) +{ + // Load data from disc + //File saveFile( L"Tutorial\\Tutorial" ); + //LoadSaveFromDisk(&saveFile); + + // clear out the app's terrain features list + app.ClearTerrainFeaturePosition(); + + StorageManager.ResetSaveData(); + // Make our next save default to the name of the level + StorageManager.SetSaveTitle(levelGen->getDefaultSaveName().c_str()); + + bool isClientSide = false; + bool isPrivate = false; + // TODO int maxPlayers = MINECRAFT_NET_MAX_PLAYERS; + int maxPlayers = 8; + + if( app.GetTutorialMode() ) + { + isClientSide = false; + maxPlayers = 4; + } + + g_NetworkManager.HostGame(0,isClientSide,isPrivate,maxPlayers,0); + + NetworkGameInitData *param = new NetworkGameInitData(); + param->seed = 0; + param->saveData = NULL; + param->settings = app.GetGameHostOption( eGameHostOption_Tutorial ); + param->levelGen = levelGen; + + if(levelGen->requiresTexturePack()) + { + param->texturePackId = levelGen->getRequiredTexturePackId(); + + Minecraft *pMinecraft = Minecraft::GetInstance(); + pMinecraft->skins->selectTexturePackById(param->texturePackId); + //pMinecraft->skins->updateUI(); + } + +#ifndef _XBOX + g_NetworkManager.FakeLocalPlayerJoined(); +#endif + + LoadingInputParams *loadingParams = new LoadingInputParams(); + loadingParams->func = &CGameNetworkManager::RunNetworkGameThreadProc; + loadingParams->lpParam = (LPVOID)param; + + UIFullscreenProgressCompletionData *completionData = new UIFullscreenProgressCompletionData(); + completionData->bShowBackground=TRUE; + completionData->bShowLogo=TRUE; + completionData->type = e_ProgressCompletion_CloseAllPlayersUIScenes; + completionData->iPad = DEFAULT_XUI_MENU_USER; + loadingParams->completionData = completionData; + + ui.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_FullscreenProgress, loadingParams); +} + +void UIScene_LoadOrJoinMenu::UpdateGamesListCallback(LPVOID pParam) +{ + if(pParam != NULL) + { + UIScene_LoadOrJoinMenu *pScene = (UIScene_LoadOrJoinMenu *)pParam; + pScene->UpdateGamesList(); + } +} + +void UIScene_LoadOrJoinMenu::UpdateGamesList() +{ + // If we're ignoring input scene isn't active so do nothing + if (m_bIgnoreInput) return; + + // If a texture pack is loading, or will be loading, then ignore this ( we are going to be destroyed anyway) + if( Minecraft::GetInstance()->skins->getSelected()->isLoadingData() || (Minecraft::GetInstance()->skins->needsUIUpdate() || ui.IsReloadingSkin()) ) return; + + // if we're retrieving save info, don't show the list yet as we will be ignoring press events + if(!m_bSavesDisplayed) + { + return; + } + + + FriendSessionInfo *pSelectedSession = NULL; + if(DoesGamesListHaveFocus() && m_buttonListGames.getItemCount() > 0) + { + unsigned int nIndex = m_buttonListGames.getCurrentSelection(); + pSelectedSession = m_currentSessions->at( nIndex ); + } + + SessionID selectedSessionId; + ZeroMemory(&selectedSessionId,sizeof(SessionID)); + if( pSelectedSession != NULL )selectedSessionId = pSelectedSession->sessionId; + pSelectedSession = NULL; + + m_controlJoinTimer.setVisible( false ); + + // if the saves list has focus, then we should show the Delete Save tooltip + // if the games list has focus, then we should show the View Gamercard tooltip + int iRB=-1; + int iY = -1; + int iX=-1; + + delete m_currentSessions; + m_currentSessions = g_NetworkManager.GetSessionList( m_iPad, 1, m_bShowingPartyGamesOnly ); + + // Update the xui list displayed + unsigned int xuiListSize = m_buttonListGames.getItemCount(); + unsigned int filteredListSize = (unsigned int)m_currentSessions->size(); + + BOOL gamesListHasFocus = DoesGamesListHaveFocus(); + + if(filteredListSize > 0) + { +#if TO_BE_IMPLEMENTED + if( !m_pGamesList->IsEnabled() ) + { + m_pGamesList->SetEnable(TRUE); + m_pGamesList->SetCurSel( 0 ); + } +#endif + m_labelNoGames.setVisible( false ); + m_controlJoinTimer.setVisible( false ); + } + else + { +#if TO_BE_IMPLEMENTED + m_pGamesList->SetEnable(FALSE); +#endif + m_controlJoinTimer.setVisible( false ); + m_labelNoGames.setVisible( true ); + +#if TO_BE_IMPLEMENTED + if( gamesListHasFocus ) m_pGamesList->InitFocus(m_iPad); +#endif + } + + // clear out the games list and re-fill + m_buttonListGames.clearList(); + + if( filteredListSize > 0 ) + { + // Reset the focus to the selected session if it still exists + unsigned int sessionIndex = 0; + m_buttonListGames.setCurrentSelection(0); + + for( AUTO_VAR(it, m_currentSessions->begin()); it < m_currentSessions->end(); ++it) + { + FriendSessionInfo *sessionInfo = *it; + + wchar_t textureName[64] = L"\0"; + + // Is this a default game or a texture pack game? + if(sessionInfo->data.texturePackParentId!=0) + { + // Do we have the texture pack + Minecraft *pMinecraft = Minecraft::GetInstance(); + TexturePack *tp = pMinecraft->skins->getTexturePackById(sessionInfo->data.texturePackParentId); + HRESULT hr; + + DWORD dwImageBytes=0; + PBYTE pbImageData=NULL; + + if(tp==NULL) + { + DWORD dwBytes=0; + PBYTE pbData=NULL; + app.GetTPD(sessionInfo->data.texturePackParentId,&pbData,&dwBytes); + + // is it in the tpd data ? + app.GetFileFromTPD(eTPDFileType_Icon,pbData,dwBytes,&pbImageData,&dwImageBytes ); + if(dwImageBytes > 0 && pbImageData) + { + swprintf(textureName,64,L"%ls",sessionInfo->displayLabel); + registerSubstitutionTexture(textureName,pbImageData,dwImageBytes); + } + } + else + { + pbImageData = tp->getPackIcon(dwImageBytes); + if(dwImageBytes > 0 && pbImageData) + { + swprintf(textureName,64,L"%ls",sessionInfo->displayLabel); + registerSubstitutionTexture(textureName,pbImageData,dwImageBytes); + } + } + } + else + { + // default texture pack + Minecraft *pMinecraft = Minecraft::GetInstance(); + TexturePack *tp = pMinecraft->skins->getTexturePackByIndex(0); + + DWORD dwImageBytes; + PBYTE pbImageData = tp->getPackIcon(dwImageBytes); + + if(dwImageBytes > 0 && pbImageData) + { + swprintf(textureName,64,L"%ls",sessionInfo->displayLabel); + registerSubstitutionTexture(textureName,pbImageData,dwImageBytes); + } + } + + m_buttonListGames.addItem( sessionInfo->displayLabel, textureName ); + + if(memcmp( &selectedSessionId, &sessionInfo->sessionId, sizeof(SessionID) ) == 0) + { + m_buttonListGames.setCurrentSelection(sessionIndex); + break; + } + ++sessionIndex; + } + } + + updateTooltips(); +} + +void UIScene_LoadOrJoinMenu::HandleDLCMountingComplete() +{ + Initialise(); +} + +bool UIScene_LoadOrJoinMenu::DoesSavesListHaveFocus() +{ + if( m_buttonListSaves.hasFocus() ) + { + // check it's not the first or second element (new world or tutorial) + if(m_iSaveListIndex > (m_iDefaultButtonsC-1)) + { + return true; + } + } + return false; +} + +bool UIScene_LoadOrJoinMenu::DoesMashUpWorldHaveFocus() +{ + if(m_buttonListSaves.hasFocus()) + { + // check it's not the first or second element (new world or tutorial) + if(m_iSaveListIndex > (m_iDefaultButtonsC - 1)) + { + return false; + } + + if(m_iSaveListIndex > (m_iDefaultButtonsC - 1 - m_iMashUpButtonsC)) + { + return true; + } + else return false; + } + else return false; +} + +bool UIScene_LoadOrJoinMenu::DoesGamesListHaveFocus() +{ + return m_buttonListGames.hasFocus(); +} + +void UIScene_LoadOrJoinMenu::handleTimerComplete(int id) +{ + switch(id) + { + case JOIN_LOAD_ONLINE_TIMER_ID: + { +#ifdef _XBOX + XPARTY_USER_LIST partyList; + + if((XPartyGetUserList( &partyList ) != XPARTY_E_NOT_IN_PARTY ) && (partyList.dwUserCount>1)) + { + m_bInParty=true; + } + else + { + m_bInParty=false; + } +#endif + + bool bMultiplayerAllowed = ProfileManager.IsSignedInLive( m_iPad ) && ProfileManager.AllowedToPlayMultiplayer(m_iPad); + if(bMultiplayerAllowed != m_bMultiplayerAllowed) + { + if( bMultiplayerAllowed ) + { + // m_CheckboxOnline.SetEnable(TRUE); + // m_CheckboxPrivate.SetEnable(TRUE); + } + else + { + m_bInParty = false; + m_buttonListGames.clearList(); + m_controlJoinTimer.setVisible( true ); + m_labelNoGames.setVisible( false ); + } + + m_bMultiplayerAllowed = bMultiplayerAllowed; + } + } + break; + // 4J-PB - Only Xbox will not have trial DLC patched into the game +#ifdef _XBOX + case CHECKFORAVAILABLETEXTUREPACKS_TIMER_ID: + { + +#if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__) + for(int i=0;i<m_iTexturePacksNotInstalled;i++) + { + if(m_iConfigA[i]!=-1) + { + DLC_INFO *pDLCInfo=app.GetDLCInfoFromTPackID(m_iConfigA[i]); + + if(pDLCInfo) + { + // retrieve the image - if we haven't already + wstring textureName = filenametowstring(pDLCInfo->chImageURL); + + if(hasRegisteredSubstitutionTexture(textureName)==false) + { + PBYTE pbImageData; + int iImageDataBytes=0; + SonyHttp::getDataFromURL(pDLCInfo->chImageURL,(void **)&pbImageData,&iImageDataBytes); + + if(iImageDataBytes!=0) + { + // set the image + registerSubstitutionTexture(textureName,pbImageData,iImageDataBytes,true); + m_iConfigA[i]=-1; + } + + } + } + } + } + + bool bAllDone=true; + for(int i=0;i<m_iTexturePacksNotInstalled;i++) + { + if(m_iConfigA[i]!=-1) + { + bAllDone = false; + } + } + + if(bAllDone) + { + // kill this timer + killTimer(CHECKFORAVAILABLETEXTUREPACKS_TIMER_ID); + } +#endif + + } + break; +#endif + } + +} + +void UIScene_LoadOrJoinMenu::LoadSaveFromDisk(File *saveFile, ESavePlatform savePlatform /*= SAVE_FILE_PLATFORM_LOCAL*/) +{ + // we'll only be coming in here when the tutorial is loaded now + + StorageManager.ResetSaveData(); + + // Make our next save default to the name of the level + StorageManager.SetSaveTitle(saveFile->getName().c_str()); + + __int64 fileSize = saveFile->length(); + FileInputStream fis(*saveFile); + byteArray ba(fileSize); + fis.read(ba); + fis.close(); + + + + bool isClientSide = false; + bool isPrivate = false; + int maxPlayers = MINECRAFT_NET_MAX_PLAYERS; + + if( app.GetTutorialMode() ) + { + isClientSide = false; + maxPlayers = 4; + } + + app.SetGameHostOption(eGameHostOption_GameType,GameType::CREATIVE->getId() ); + + g_NetworkManager.HostGame(0,isClientSide,isPrivate,maxPlayers,0); + + LoadSaveDataThreadParam *saveData = new LoadSaveDataThreadParam(ba.data, ba.length, saveFile->getName()); + + NetworkGameInitData *param = new NetworkGameInitData(); + param->seed = 0; + param->saveData = saveData; + param->settings = app.GetGameHostOption( eGameHostOption_All ); + param->savePlatform = savePlatform; + +#ifndef _XBOX + g_NetworkManager.FakeLocalPlayerJoined(); +#endif + + LoadingInputParams *loadingParams = new LoadingInputParams(); + loadingParams->func = &CGameNetworkManager::RunNetworkGameThreadProc; + loadingParams->lpParam = (LPVOID)param; + + UIFullscreenProgressCompletionData *completionData = new UIFullscreenProgressCompletionData(); + completionData->bShowBackground=TRUE; + completionData->bShowLogo=TRUE; + completionData->type = e_ProgressCompletion_CloseAllPlayersUIScenes; + completionData->iPad = DEFAULT_XUI_MENU_USER; + loadingParams->completionData = completionData; + + ui.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_FullscreenProgress, loadingParams); +} + +#ifdef SONY_REMOTE_STORAGE_DOWNLOAD +void UIScene_LoadOrJoinMenu::LoadSaveFromCloud() +{ + + wchar_t wFileName[128]; + mbstowcs(wFileName, app.getRemoteStorage()->getLocalFilename(), strlen(app.getRemoteStorage()->getLocalFilename())+1); // plus null + File cloudFile(wFileName); + + + StorageManager.ResetSaveData(); + + // Make our next save default to the name of the level + wchar_t wSaveName[128]; + mbstowcs(wSaveName, app.getRemoteStorage()->getSaveNameUTF8(), strlen(app.getRemoteStorage()->getSaveNameUTF8())+1); // plus null + StorageManager.SetSaveTitle(wSaveName); + + __int64 fileSize = cloudFile.length(); + FileInputStream fis(cloudFile); + byteArray ba(fileSize); + fis.read(ba); + fis.close(); + + + + bool isClientSide = false; + bool isPrivate = false; + int maxPlayers = MINECRAFT_NET_MAX_PLAYERS; + + if( app.GetTutorialMode() ) + { + isClientSide = false; + maxPlayers = 4; + } + + app.SetGameHostOption(eGameHostOption_All, app.getRemoteStorage()->getSaveHostOptions() ); + + g_NetworkManager.HostGame(0,isClientSide,isPrivate,maxPlayers,0); + + LoadSaveDataThreadParam *saveData = new LoadSaveDataThreadParam(ba.data, ba.length, cloudFile.getName()); + + NetworkGameInitData *param = new NetworkGameInitData(); + param->seed = app.getRemoteStorage()->getSaveSeed(); + param->saveData = saveData; + param->settings = app.GetGameHostOption( eGameHostOption_All ); + param->savePlatform = app.getRemoteStorage()->getSavePlatform(); + param->texturePackId = app.getRemoteStorage()->getSaveTexturePack(); + +#ifndef _XBOX + g_NetworkManager.FakeLocalPlayerJoined(); +#endif + + LoadingInputParams *loadingParams = new LoadingInputParams(); + loadingParams->func = &CGameNetworkManager::RunNetworkGameThreadProc; + loadingParams->lpParam = (LPVOID)param; + + UIFullscreenProgressCompletionData *completionData = new UIFullscreenProgressCompletionData(); + completionData->bShowBackground=TRUE; + completionData->bShowLogo=TRUE; + completionData->type = e_ProgressCompletion_CloseAllPlayersUIScenes; + completionData->iPad = DEFAULT_XUI_MENU_USER; + loadingParams->completionData = completionData; + + ui.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_FullscreenProgress, loadingParams); +} + +#endif //SONY_REMOTE_STORAGE_DOWNLOAD + +int UIScene_LoadOrJoinMenu::DeleteSaveDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result) +{ + UIScene_LoadOrJoinMenu* pClass = (UIScene_LoadOrJoinMenu*)pParam; + // results switched for this dialog + + // Check that we have a valid save selected (can get a bad index if the save list has been refreshed) + bool validSelection= pClass->m_iDefaultButtonsC != 0 && pClass->m_iSaveListIndex >= pClass->m_iDefaultButtonsC; + + if(result==C4JStorage::EMessage_ResultDecline && validSelection) + { + if(app.DebugSettingsOn() && app.GetLoadSavesFromFolderEnabled()) + { + pClass->m_bIgnoreInput=false; + } + else + { + StorageManager.DeleteSaveData(&pClass->m_pSaveDetails->SaveInfoA[pClass->m_iSaveListIndex - pClass->m_iDefaultButtonsC], UIScene_LoadOrJoinMenu::DeleteSaveDataReturned, (LPVOID)pClass->GetCallbackUniqueId()); + pClass->m_controlSavesTimer.setVisible( true ); + } + } + else + { + pClass->m_bIgnoreInput=false; + } + + return 0; +} + +int UIScene_LoadOrJoinMenu::DeleteSaveDataReturned(LPVOID lpParam,bool bRes) +{ + ui.EnterCallbackIdCriticalSection(); + UIScene_LoadOrJoinMenu* pClass = (UIScene_LoadOrJoinMenu*)ui.GetSceneFromCallbackId((size_t)lpParam); + + if(pClass) + { + if(bRes) + { + // wipe the list and repopulate it + pClass->m_iState=e_SavesRepopulateAfterDelete; + } + else pClass->m_bIgnoreInput=false; + + pClass->updateTooltips(); + } + ui.LeaveCallbackIdCriticalSection(); + return 0; +} + + +int UIScene_LoadOrJoinMenu::RenameSaveDataReturned(LPVOID lpParam,bool bRes) +{ + UIScene_LoadOrJoinMenu* pClass = (UIScene_LoadOrJoinMenu*)lpParam; + + if(bRes) + { + pClass->m_iState=e_SavesRepopulate; + } + else pClass->m_bIgnoreInput=false; + + pClass->updateTooltips(); + + return 0; +} + +#ifdef __ORBIS__ + + +void UIScene_LoadOrJoinMenu::LoadRemoteFileFromDisk(char* remoteFilename) +{ + wchar_t wSaveName[128]; + mbstowcs(wSaveName, remoteFilename, strlen(remoteFilename)+1); // plus null + + // processConsoleSave(wSaveName, L"ProcessedSave.bin"); + + // File remoteFile(L"ProcessedSave.bin"); + File remoteFile(wSaveName); + LoadSaveFromDisk(&remoteFile, SAVE_FILE_PLATFORM_PS3); +} +#endif + + +int UIScene_LoadOrJoinMenu::SaveOptionsDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result) +{ + UIScene_LoadOrJoinMenu* pClass = (UIScene_LoadOrJoinMenu*)pParam; + + // results switched for this dialog + // EMessage_ResultAccept means cancel + switch(result) + { + case C4JStorage::EMessage_ResultDecline: // rename + { + pClass->m_bIgnoreInput=true; +#ifdef _DURANGO + // bring up a keyboard + InputManager.RequestKeyboard(app.GetString(IDS_RENAME_WORLD_TITLE), (pClass->m_saveDetails[pClass->m_iSaveListIndex-pClass->m_iDefaultButtonsC]).UTF16SaveName,(DWORD)0,25,&UIScene_LoadOrJoinMenu::KeyboardCompleteWorldNameCallback,pClass,C_4JInput::EKeyboardMode_Default); +#else + // bring up a keyboard + wchar_t wSaveName[128]; + //CD - Fix - We must memset the SaveName + ZeroMemory(wSaveName, 128 * sizeof(wchar_t) ); + mbstowcs(wSaveName, pClass->m_saveDetails[pClass->m_iSaveListIndex - pClass->m_iDefaultButtonsC].UTF8SaveName, strlen(pClass->m_saveDetails->UTF8SaveName)+1); // plus null + LPWSTR ptr = wSaveName; + InputManager.RequestKeyboard(app.GetString(IDS_RENAME_WORLD_TITLE),wSaveName,(DWORD)0,25,&UIScene_LoadOrJoinMenu::KeyboardCompleteWorldNameCallback,pClass,C_4JInput::EKeyboardMode_Default); +#endif + } + break; + + case C4JStorage::EMessage_ResultThirdOption: // delete - + { + // delete the save game + // Have to ask the player if they are sure they want to delete this game + UINT uiIDA[2]; + uiIDA[0]=IDS_CONFIRM_CANCEL; + uiIDA[1]=IDS_CONFIRM_OK; + ui.RequestMessageBox(IDS_TOOLTIPS_DELETESAVE, IDS_TEXT_DELETE_SAVE, uiIDA, 2, iPad,&UIScene_LoadOrJoinMenu::DeleteSaveDialogReturned,pClass, app.GetStringTable(),NULL,0,false); + } + break; + +#ifdef SONY_REMOTE_STORAGE_UPLOAD + case C4JStorage::EMessage_ResultFourthOption: // upload to cloud + { + UINT uiIDA[2]; + uiIDA[0]=IDS_CONFIRM_OK; + uiIDA[1]=IDS_CONFIRM_CANCEL; + + ui.RequestMessageBox(IDS_TOOLTIPS_SAVETRANSFER_UPLOAD, IDS_SAVE_TRANSFER_TEXT, uiIDA, 2, iPad,&UIScene_LoadOrJoinMenu::SaveTransferDialogReturned,pClass, app.GetStringTable(),NULL,0,false); + } + break; +#endif // SONY_REMOTE_STORAGE_UPLOAD +#if defined _XBOX_ONE || defined __ORBIS__ + case C4JStorage::EMessage_ResultFourthOption: // copy save + { + UINT uiIDA[2]; + uiIDA[0]=IDS_CONFIRM_OK; + uiIDA[1]=IDS_CONFIRM_CANCEL; + + ui.RequestMessageBox(IDS_COPYSAVE, IDS_TEXT_COPY_SAVE, uiIDA, 2, iPad,&UIScene_LoadOrJoinMenu::CopySaveDialogReturned,pClass, app.GetStringTable(),NULL,0,false); + } + break; +#endif + + case C4JStorage::EMessage_Cancelled: + default: + { + // reset the tooltips + pClass->updateTooltips(); + pClass->m_bIgnoreInput=false; + } + break; + } + return 0; +} + +int UIScene_LoadOrJoinMenu::TexturePackDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result) +{ + UIScene_LoadOrJoinMenu *pClass = (UIScene_LoadOrJoinMenu *)pParam; + + // Exit with or without saving + if(result==C4JStorage::EMessage_ResultAccept) + { + // we need to enable background downloading for the DLC + XBackgroundDownloadSetMode(XBACKGROUND_DOWNLOAD_MODE_ALWAYS_ALLOW); +#if TO_BE_IMPLEMENTED + ULONGLONG ullOfferID_Full; + ULONGLONG ullIndexA[1]; + app.GetDLCFullOfferIDForPackID(pClass->m_initData->selectedSession->data.texturePackParentId,&ullOfferID_Full); + + + if( result==C4JStorage::EMessage_ResultAccept ) // Full version + { + ullIndexA[0]=ullOfferID_Full; + StorageManager.InstallOffer(1,ullIndexA,NULL,NULL); + + } + else // trial version + { + DLC_INFO *pDLCInfo=app.GetDLCInfoForFullOfferID(ullOfferID_Full); + ullIndexA[0]=pDLCInfo->ullOfferID_Trial; + StorageManager.InstallOffer(1,ullIndexA,NULL,NULL); + } +#endif + + +#if defined _XBOX_ONE + if(ProfileManager.IsSignedIn(iPad)) + { + if (ProfileManager.IsSignedInLive(iPad)) + { + wstring ProductId; + app.GetDLCFullOfferIDForPackID(pClass->m_initData->selectedSession->data.texturePackParentId,ProductId); + + StorageManager.InstallOffer(1,(WCHAR *)ProductId.c_str(),NULL,NULL); + } + else + { + // 4J-JEV: Fix for XB1: #165863 - XR-074: Compliance: With no active network connection user is unable to convert from Trial to Full texture pack and is not messaged why. + UINT uiIDA[1] = { IDS_CONFIRM_OK }; + ui.RequestMessageBox(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_XBOXLIVE_NOTIFICATION, uiIDA, 1, iPad, NULL, NULL, app.GetStringTable()); + } + } +#endif + + } + pClass->m_bIgnoreInput=false; + return 0; +} + +#if defined __PS3__ || defined __PSVITA__ || defined __ORBIS__ +int UIScene_LoadOrJoinMenu::MustSignInReturnedPSN(void *pParam,int iPad,C4JStorage::EMessageResult result) +{ + UIScene_LoadOrJoinMenu* pClass = (UIScene_LoadOrJoinMenu*)pParam; + + if(result==C4JStorage::EMessage_ResultAccept) + { +#if defined(__PS3__) + SQRNetworkManager_PS3::AttemptPSNSignIn(&UIScene_LoadOrJoinMenu::PSN_SignInReturned, pClass); +#elif defined __PSVITA__ + SQRNetworkManager_Vita::AttemptPSNSignIn(&UIScene_LoadOrJoinMenu::PSN_SignInReturned, pClass); +#else + SQRNetworkManager_Orbis::AttemptPSNSignIn(&UIScene_LoadOrJoinMenu::PSN_SignInReturned, pClass, false, iPad); +#endif + } + else + { + pClass->m_bIgnoreInput = false; + } + + return 0; +} + +int UIScene_LoadOrJoinMenu::PSN_SignInReturned(void *pParam,bool bContinue, int iPad) +{ + UIScene_LoadOrJoinMenu* pClass = (UIScene_LoadOrJoinMenu*)pParam; + if(bContinue==true) + { + switch(pClass->m_eAction) + { + case eAction_ViewInvites: + // Check if we're signed in to LIVE + if(ProfileManager.IsSignedInLive(iPad)) + { +#if defined(__PS3__) + int ret = sceNpBasicRecvMessageCustom(SCE_NP_BASIC_MESSAGE_MAIN_TYPE_INVITE, SCE_NP_BASIC_RECV_MESSAGE_OPTIONS_INCLUDE_BOOTABLE, SYS_MEMORY_CONTAINER_ID_INVALID); + app.DebugPrintf("sceNpBasicRecvMessageCustom return %d ( %08x )\n", ret, ret); +#elif defined __PSVITA__ + // TO BE IMPLEMENTED FOR VITA + PSVITA_STUBBED; +#else + SQRNetworkManager_Orbis::RecvInviteGUI(); +#endif + } + break; + case eAction_JoinGame: + pClass->CheckAndJoinGame(pClass->m_iGameListIndex); + break; + } + } + else + { + pClass->m_bIgnoreInput = false; + } + return 0; +} +#endif + +#ifdef SONY_REMOTE_STORAGE_DOWNLOAD + +void UIScene_LoadOrJoinMenu::LaunchSaveTransfer() +{ + LoadingInputParams *loadingParams = new LoadingInputParams(); + loadingParams->func = &UIScene_LoadOrJoinMenu::DownloadSonyCrossSaveThreadProc; + loadingParams->lpParam = (LPVOID)this; + + UIFullscreenProgressCompletionData *completionData = new UIFullscreenProgressCompletionData(); + completionData->bShowBackground=TRUE; + completionData->bShowLogo=TRUE; + completionData->type = e_ProgressCompletion_NavigateBackToScene; + completionData->iPad = DEFAULT_XUI_MENU_USER; + loadingParams->completionData = completionData; + + loadingParams->cancelFunc=&UIScene_LoadOrJoinMenu::CancelSaveTransferCallback; + loadingParams->m_cancelFuncParam=this; + loadingParams->cancelText=IDS_TOOLTIPS_CANCEL; + + ui.NavigateToScene(m_iPad,eUIScene_FullscreenProgress, loadingParams); +} + + + + +int UIScene_LoadOrJoinMenu::CreateDummySaveDataCallback(LPVOID lpParam,bool bRes) +{ + UIScene_LoadOrJoinMenu* pClass = (UIScene_LoadOrJoinMenu *) lpParam; + if(bRes) + { + pClass->m_eSaveTransferState = eSaveTransfer_GetSavesInfo; + } + else + { + pClass->m_eSaveTransferState = eSaveTransfer_Error; + app.DebugPrintf("CreateDummySaveDataCallback failed\n"); + + } + return 0; +} + +int UIScene_LoadOrJoinMenu::CrossSaveGetSavesInfoCallback(LPVOID lpParam, SAVE_DETAILS *pSaveDetails, bool bRes) +{ + UIScene_LoadOrJoinMenu* pClass = (UIScene_LoadOrJoinMenu *) lpParam; + if(bRes) + { + pClass->m_eSaveTransferState = eSaveTransfer_GetFileData; + } + else + { + pClass->m_eSaveTransferState = eSaveTransfer_Error; + app.DebugPrintf("CrossSaveGetSavesInfoCallback failed\n"); + } + return 0; +} + +int UIScene_LoadOrJoinMenu::LoadCrossSaveDataCallback( void *pParam,bool bIsCorrupt, bool bIsOwner ) +{ + UIScene_LoadOrJoinMenu* pClass = (UIScene_LoadOrJoinMenu *) pParam; + if(bIsCorrupt == false && bIsOwner) + { + pClass->m_eSaveTransferState = eSaveTransfer_CreatingNewSave; + } + else + { + pClass->m_eSaveTransferState = eSaveTransfer_Error; + app.DebugPrintf("LoadCrossSaveDataCallback failed \n"); + + } + return 0; +} + +int UIScene_LoadOrJoinMenu::CrossSaveFinishedCallback(void *pParam,int iPad,C4JStorage::EMessageResult result) +{ + UIScene_LoadOrJoinMenu* pClass = (UIScene_LoadOrJoinMenu *) pParam; + pClass->m_eSaveTransferState = eSaveTransfer_Idle; + return 0; +} + + +int UIScene_LoadOrJoinMenu::CrossSaveDeleteOnErrorReturned(LPVOID lpParam,bool bRes) +{ + UIScene_LoadOrJoinMenu* pClass = (UIScene_LoadOrJoinMenu *) lpParam; + pClass->m_eSaveTransferState = eSaveTransfer_ErrorMesssage; + return 0; +} + +int UIScene_LoadOrJoinMenu::RemoteSaveNotFoundCallback(void *pParam,int iPad,C4JStorage::EMessageResult result) +{ + UIScene_LoadOrJoinMenu* pClass = (UIScene_LoadOrJoinMenu *) pParam; + pClass->m_eSaveTransferState = eSaveTransfer_Idle; + return 0; +} + +// MGH - added this global to force the delete of the previous data, for the remote storage saves +// need to speak to Chris why this is necessary +bool g_bForceVitaSaveWipe = false; + + +int UIScene_LoadOrJoinMenu::DownloadSonyCrossSaveThreadProc( LPVOID lpParameter ) +{ + Compression::UseDefaultThreadStorage(); + UIScene_LoadOrJoinMenu* pClass = (UIScene_LoadOrJoinMenu *) lpParameter; + pClass->m_saveTransferDownloadCancelled = false; + bool bAbortCalled = false; + Minecraft *pMinecraft=Minecraft::GetInstance(); + bool bSaveFileCreated = false; + wchar_t wSaveName[128]; + + // get the save file size + pMinecraft->progressRenderer->progressStagePercentage(0); + pMinecraft->progressRenderer->progressStart(IDS_TOOLTIPS_SAVETRANSFER_DOWNLOAD); + pMinecraft->progressRenderer->progressStage( IDS_TOOLTIPS_SAVETRANSFER_DOWNLOAD ); + + ConsoleSaveFile* pSave = NULL; + + pClass->m_eSaveTransferState = eSaveTransfer_GetRemoteSaveInfo; + + + while(pClass->m_eSaveTransferState!=eSaveTransfer_Idle) + { + switch(pClass->m_eSaveTransferState) + { + case eSaveTransfer_Idle: + break; + case eSaveTransfer_GetRemoteSaveInfo: + app.DebugPrintf("UIScene_LoadOrJoinMenu getSaveInfo\n"); + app.getRemoteStorage()->getSaveInfo(); + pClass->m_eSaveTransferState = eSaveTransfer_GettingRemoteSaveInfo; + break; + case eSaveTransfer_GettingRemoteSaveInfo: + if(pClass->m_saveTransferDownloadCancelled) + { + pClass->m_eSaveTransferState = eSaveTransfer_Error; + break; + } + if(app.getRemoteStorage()->waitingForSaveInfo() == false) + { + if(app.getRemoteStorage()->saveIsAvailable()) + { + pClass->m_eSaveTransferState = eSaveTransfer_CreateDummyFile; + } + else + { + // no save available, inform the user about the functionality + UINT uiIDA[1]; + uiIDA[0]=IDS_CONFIRM_OK; + ui.RequestMessageBox(IDS_TOOLTIPS_SAVETRANSFER_DOWNLOAD, IDS_SAVE_TRANSFER_NOT_AVAILABLE_TEXT, uiIDA, 1, ProfileManager.GetPrimaryPad(),RemoteSaveNotFoundCallback,pClass, app.GetStringTable(),NULL,0,false); + } + } + break; + case eSaveTransfer_CreateDummyFile: + { + StorageManager.ResetSaveData(); + byte *compData = (byte *)StorageManager.AllocateSaveData( app.getRemoteStorage()->getSaveFilesize() ); + // Make our next save default to the name of the level + const char* pNameUTF8 = app.getRemoteStorage()->getSaveNameUTF8(); + mbstowcs(wSaveName, pNameUTF8, strlen(pNameUTF8)+1); // plus null + StorageManager.SetSaveTitle(wSaveName); + PBYTE pbThumbnailData=NULL; + DWORD dwThumbnailDataSize=0; + + PBYTE pbDataSaveImage=NULL; + DWORD dwDataSizeSaveImage=0; + + StorageManager.GetDefaultSaveImage(&pbDataSaveImage, &dwDataSizeSaveImage); // Get the default save thumbnail (as set by SetDefaultImages) for use on saving games t + StorageManager.GetDefaultSaveThumbnail(&pbThumbnailData,&dwThumbnailDataSize); // Get the default save image (as set by SetDefaultImages) for use on saving games that + + BYTE bTextMetadata[88]; + ZeroMemory(bTextMetadata,88); + int iTextMetadataBytes = app.CreateImageTextData(bTextMetadata, app.getRemoteStorage()->getSaveSeed(), true, app.getRemoteStorage()->getSaveHostOptions(), app.getRemoteStorage()->getSaveTexturePack() ); + + // set the icon and save image + StorageManager.SetSaveImages(pbThumbnailData,dwThumbnailDataSize,pbDataSaveImage,dwDataSizeSaveImage,bTextMetadata,iTextMetadataBytes); + + app.getRemoteStorage()->waitForStorageManagerIdle(); + C4JStorage::ESaveGameState saveState = StorageManager.SaveSaveData( &UIScene_LoadOrJoinMenu::CreateDummySaveDataCallback, lpParameter ); + if(saveState == C4JStorage::ESaveGame_Save) + { + pClass->m_eSaveTransferState = eSaveTransfer_CreatingDummyFile; + } + else + { + app.DebugPrintf("Failed to create dummy save file\n"); + pClass->m_eSaveTransferState = eSaveTransfer_Error; + } + } + break; + case eSaveTransfer_CreatingDummyFile: + break; + case eSaveTransfer_GetSavesInfo: + { + // we can't cancel here, we need the saves info so we can delete the file + if(pClass->m_saveTransferDownloadCancelled) + { + WCHAR wcTemp[256]; + swprintf(wcTemp,256, app.GetString(IDS_CANCEL)); // MGH - should change this string to "cancelling download" + m_wstrStageText=wcTemp; + pMinecraft->progressRenderer->progressStage( m_wstrStageText ); + } + + app.getRemoteStorage()->waitForStorageManagerIdle(); + app.DebugPrintf("CALL GetSavesInfo B\n"); + C4JStorage::ESaveGameState eSGIStatus= StorageManager.GetSavesInfo(pClass->m_iPad,&UIScene_LoadOrJoinMenu::CrossSaveGetSavesInfoCallback,pClass,"save"); + pClass->m_eSaveTransferState = eSaveTransfer_GettingSavesInfo; + } + break; + case eSaveTransfer_GettingSavesInfo: + if(pClass->m_saveTransferDownloadCancelled) + { + WCHAR wcTemp[256]; + swprintf(wcTemp,256, app.GetString(IDS_CANCEL)); // MGH - should change this string to "cancelling download" + m_wstrStageText=wcTemp; + pMinecraft->progressRenderer->progressStage( m_wstrStageText ); + } + break; + + case eSaveTransfer_GetFileData: + { + bSaveFileCreated = true; + StorageManager.GetSaveUniqueFileDir(pClass->m_downloadedUniqueFilename); + + if(pClass->m_saveTransferDownloadCancelled) + { + pClass->m_eSaveTransferState = eSaveTransfer_Error; + break; + } + PSAVE_DETAILS pSaveDetails=StorageManager.ReturnSavesInfo(); + int idx = pClass->m_iSaveListIndex - pClass->m_iDefaultButtonsC; + app.getRemoteStorage()->waitForStorageManagerIdle(); + bool bGettingOK = app.getRemoteStorage()->getSaveData(pClass->m_downloadedUniqueFilename, SaveTransferReturned, pClass); + if(bGettingOK) + { + pClass->m_eSaveTransferState = eSaveTransfer_GettingFileData; + } + else + { + pClass->m_eSaveTransferState = eSaveTransfer_Error; + app.DebugPrintf("app.getRemoteStorage()->getSaveData failed\n"); + + } + } + + case eSaveTransfer_GettingFileData: + { + WCHAR wcTemp[256]; + + int dataProgress = app.getRemoteStorage()->getDataProgress(); + pMinecraft->progressRenderer->progressStagePercentage(dataProgress); + + //swprintf(wcTemp, 256, L"Downloading data : %d", dataProgress);//app.GetString(IDS_SAVETRANSFER_STAGE_GET_DATA),0,pClass->m_ulFileSize); + swprintf(wcTemp,256, app.GetString(IDS_SAVETRANSFER_STAGE_GET_DATA),dataProgress); + m_wstrStageText=wcTemp; + pMinecraft->progressRenderer->progressStage( m_wstrStageText ); + if(pClass->m_saveTransferDownloadCancelled && bAbortCalled == false) + { + app.getRemoteStorage()->abort(); + bAbortCalled = true; + } + } + break; + case eSaveTransfer_FileDataRetrieved: + pClass->m_eSaveTransferState = eSaveTransfer_LoadSaveFromDisc; + break; + case eSaveTransfer_LoadSaveFromDisc: + { + if(pClass->m_saveTransferDownloadCancelled) + { + pClass->m_eSaveTransferState = eSaveTransfer_Error; + break; + } + + PSAVE_DETAILS pSaveDetails=StorageManager.ReturnSavesInfo(); + int saveInfoIndex = -1; + for(int i=0;i<pSaveDetails->iSaveC;i++) + { + if(strcmp(pSaveDetails->SaveInfoA[i].UTF8SaveFilename, pClass->m_downloadedUniqueFilename) == 0) + { + //found it + saveInfoIndex = i; + } + } + if(saveInfoIndex == -1) + { + pClass->m_eSaveTransferState = eSaveTransfer_Error; + app.DebugPrintf("CrossSaveGetSavesInfoCallback failed - couldn't find save\n"); + } + else + { +#ifdef __PS3__ + // ignore the CRC on PS3 + C4JStorage::ESaveGameState eLoadStatus=StorageManager.LoadSaveData(&pSaveDetails->SaveInfoA[saveInfoIndex],&LoadCrossSaveDataCallback,pClass, true); +#else + C4JStorage::ESaveGameState eLoadStatus=StorageManager.LoadSaveData(&pSaveDetails->SaveInfoA[saveInfoIndex],&LoadCrossSaveDataCallback,pClass); +#endif + if(eLoadStatus == C4JStorage::ESaveGame_Load) + { + pClass->m_eSaveTransferState = eSaveTransfer_LoadingSaveFromDisc; + } + else + { + pClass->m_eSaveTransferState = eSaveTransfer_Error; + } + } + } + break; + case eSaveTransfer_LoadingSaveFromDisc: + + break; + case eSaveTransfer_CreatingNewSave: + { + unsigned int fileSize = StorageManager.GetSaveSize(); + byteArray ba(fileSize); + StorageManager.GetSaveData(ba.data, &fileSize); + assert(ba.length == fileSize); + + + StorageManager.ResetSaveData(); + { + PBYTE pbThumbnailData=NULL; + DWORD dwThumbnailDataSize=0; + + PBYTE pbDataSaveImage=NULL; + DWORD dwDataSizeSaveImage=0; + + StorageManager.GetDefaultSaveImage(&pbDataSaveImage, &dwDataSizeSaveImage); // Get the default save thumbnail (as set by SetDefaultImages) for use on saving games t + StorageManager.GetDefaultSaveThumbnail(&pbThumbnailData,&dwThumbnailDataSize); // Get the default save image (as set by SetDefaultImages) for use on saving games that + + BYTE bTextMetadata[88]; + ZeroMemory(bTextMetadata,88); + int iTextMetadataBytes = app.CreateImageTextData(bTextMetadata, app.getRemoteStorage()->getSaveSeed(), true, app.getRemoteStorage()->getSaveHostOptions(), app.getRemoteStorage()->getSaveTexturePack() ); + + // set the icon and save image + StorageManager.SetSaveImages(pbThumbnailData,dwThumbnailDataSize,pbDataSaveImage,dwDataSizeSaveImage,bTextMetadata,iTextMetadataBytes); + } + + +#ifdef SPLIT_SAVES + ConsoleSaveFileOriginal oldFormatSave( wSaveName, ba.data, ba.length, false, app.getRemoteStorage()->getSavePlatform() ); + pSave = new ConsoleSaveFileSplit( &oldFormatSave, false, pMinecraft->progressRenderer ); + + pMinecraft->progressRenderer->progressStage(IDS_SAVETRANSFER_STAGE_SAVING); + pSave->Flush(false,false); + pClass->m_eSaveTransferState = eSaveTransfer_Saving; +#else + pSave = new ConsoleSaveFileOriginal( wSaveName, ba.data, ba.length, false, app.getRemoteStorage()->getSavePlatform() ); + pClass->m_eSaveTransferState = eSaveTransfer_Converting; + pMinecraft->progressRenderer->progressStage(IDS_SAVETRANSFER_STAGE_CONVERTING); +#endif + delete ba.data; + } + break; + case eSaveTransfer_Converting: + { + pSave->ConvertToLocalPlatform(); // check if we need to convert this file from PS3->PS4 + pClass->m_eSaveTransferState = eSaveTransfer_Saving; + pMinecraft->progressRenderer->progressStage(IDS_SAVETRANSFER_STAGE_SAVING); + StorageManager.SetSaveTitle(wSaveName); + StorageManager.SetSaveUniqueFilename(pClass->m_downloadedUniqueFilename); + + app.getRemoteStorage()->waitForStorageManagerIdle(); // we need to wait for the save system to be idle here, as Flush doesn't check for it. + pSave->Flush(false, false); + } + break; + case eSaveTransfer_Saving: + { + // On Durango/Orbis, we need to wait for all the asynchronous saving processes to complete before destroying the levels, as that will ultimately delete + // the directory level storage & therefore the ConsoleSaveSplit instance, which needs to be around until all the sub files have completed saving. +#if defined(_DURANGO) || defined(__ORBIS__) + while(StorageManager.GetSaveState() != C4JStorage::ESaveGame_Idle ) + { + Sleep(10); + StorageManager.Tick(); + } +#endif + + delete pSave; + + + pMinecraft->progressRenderer->progressStage(IDS_PROGRESS_SAVING_TO_DISC); + pClass->m_eSaveTransferState = eSaveTransfer_Succeeded; + } + break; + + case eSaveTransfer_Succeeded: + { + // if we've arrived here, the save has been created successfully + pClass->m_iState=e_SavesRepopulate; + pClass->updateTooltips(); + UINT uiIDA[1]; + uiIDA[0]=IDS_CONFIRM_OK; + app.getRemoteStorage()->waitForStorageManagerIdle(); // wait for everything to complete before we hand control back to the player + ui.RequestMessageBox( IDS_TOOLTIPS_SAVETRANSFER_DOWNLOAD, IDS_SAVE_TRANSFER_DOWNLOADCOMPLETE, uiIDA,1,ProfileManager.GetPrimaryPad(),CrossSaveFinishedCallback,pClass, app.GetStringTable()); + pClass->m_eSaveTransferState = eSaveTransfer_Finished; + } + break; + + case eSaveTransfer_Cancelled: // this is no longer used + { + assert(0); //pClass->m_eSaveTransferState = eSaveTransfer_Idle; + } + break; + case eSaveTransfer_Error: + { + if(bSaveFileCreated) + { + if(pClass->m_saveTransferDownloadCancelled) + { + WCHAR wcTemp[256]; + swprintf(wcTemp,256, app.GetString(IDS_CANCEL)); // MGH - should change this string to "cancelling download" + m_wstrStageText=wcTemp; + pMinecraft->progressRenderer->progressStage( m_wstrStageText ); + pMinecraft->progressRenderer->progressStage( m_wstrStageText ); + } + // if the save file has already been created we have to delete it again if there's been an error + PSAVE_DETAILS pSaveDetails=StorageManager.ReturnSavesInfo(); + int saveInfoIndex = -1; + for(int i=0;i<pSaveDetails->iSaveC;i++) + { + if(strcmp(pSaveDetails->SaveInfoA[i].UTF8SaveFilename, pClass->m_downloadedUniqueFilename) == 0) + { + //found it + saveInfoIndex = i; + } + } + if(saveInfoIndex == -1) + { + app.DebugPrintf("eSaveTransfer_Error failed - couldn't find save\n"); + assert(0); + pClass->m_eSaveTransferState = eSaveTransfer_ErrorMesssage; + } + else + { + // delete the save file + app.getRemoteStorage()->waitForStorageManagerIdle(); + C4JStorage::ESaveGameState eDeleteStatus = StorageManager.DeleteSaveData(&pSaveDetails->SaveInfoA[saveInfoIndex],UIScene_LoadOrJoinMenu::CrossSaveDeleteOnErrorReturned,pClass); + if(eDeleteStatus == C4JStorage::ESaveGame_Delete) + { + pClass->m_eSaveTransferState = eSaveTransfer_ErrorDeletingSave; + } + else + { + app.DebugPrintf("StorageManager.DeleteSaveData failed!!\n"); + pClass->m_eSaveTransferState = eSaveTransfer_ErrorMesssage; + } + } + } + else + { + pClass->m_eSaveTransferState = eSaveTransfer_ErrorMesssage; + } + } + break; + + case eSaveTransfer_ErrorDeletingSave: + break; + case eSaveTransfer_ErrorMesssage: + { + app.getRemoteStorage()->waitForStorageManagerIdle(); // wait for everything to complete before we hand control back to the player + if(pClass->m_saveTransferDownloadCancelled) + { + pClass->m_eSaveTransferState = eSaveTransfer_Idle; + } + else + { + UINT uiIDA[1]; + uiIDA[0]=IDS_CONFIRM_OK; + ui.RequestMessageBox( IDS_TOOLTIPS_SAVETRANSFER_DOWNLOAD, IDS_SAVE_TRANSFER_DOWNLOADFAILED, uiIDA,1,ProfileManager.GetPrimaryPad(),CrossSaveFinishedCallback,pClass, app.GetStringTable()); + pClass->m_eSaveTransferState = eSaveTransfer_Finished; + } + if(bSaveFileCreated) // save file has been created, then deleted. + pClass->m_iState=e_SavesRepopulateAfterDelete; + else + pClass->m_iState=e_SavesRepopulate; + pClass->updateTooltips(); + } + break; + case eSaveTransfer_Finished: + { + + } + // waiting to dismiss the dialog + break; + } + Sleep(50); + } + + return 0; + +} + +void UIScene_LoadOrJoinMenu::SaveTransferReturned(LPVOID lpParam, SonyRemoteStorage::Status s, int error_code) +{ + UIScene_LoadOrJoinMenu* pClass = (UIScene_LoadOrJoinMenu *) lpParam; + + if(s == SonyRemoteStorage::e_getDataSucceeded) + { + pClass->m_eSaveTransferState = eSaveTransfer_FileDataRetrieved; + } + else + { + pClass->m_eSaveTransferState = eSaveTransfer_Error; + app.DebugPrintf("SaveTransferReturned failed with error code : 0x%08x\n", error_code); + } + +} +ConsoleSaveFile* UIScene_LoadOrJoinMenu::SonyCrossSaveConvert() +{ + return NULL; +} + +void UIScene_LoadOrJoinMenu::CancelSaveTransferCallback(LPVOID lpParam) +{ + UIScene_LoadOrJoinMenu* pClass = (UIScene_LoadOrJoinMenu *) lpParam; + pClass->m_saveTransferDownloadCancelled = true; + ui.SetTooltips( DEFAULT_XUI_MENU_USER, -1, -1, -1, -1,-1,-1,-1,-1); // MGH - added - remove the "cancel" tooltip, so the player knows it's underway (really needs a "cancelling" message) +} + +#endif + + + +#ifdef SONY_REMOTE_STORAGE_UPLOAD + +void UIScene_LoadOrJoinMenu::LaunchSaveUpload() +{ + LoadingInputParams *loadingParams = new LoadingInputParams(); + loadingParams->func = &UIScene_LoadOrJoinMenu::UploadSonyCrossSaveThreadProc; + loadingParams->lpParam = (LPVOID)this; + + UIFullscreenProgressCompletionData *completionData = new UIFullscreenProgressCompletionData(); + completionData->bShowBackground=TRUE; + completionData->bShowLogo=TRUE; + completionData->type = e_ProgressCompletion_NavigateBackToScene; + completionData->iPad = DEFAULT_XUI_MENU_USER; + loadingParams->completionData = completionData; + +// 4J-PB - Waiting for Sony to fix canceling a save upload + loadingParams->cancelFunc=&UIScene_LoadOrJoinMenu::CancelSaveUploadCallback; + loadingParams->m_cancelFuncParam = this; + loadingParams->cancelText=IDS_TOOLTIPS_CANCEL; + + ui.NavigateToScene(m_iPad,eUIScene_FullscreenProgress, loadingParams); + +} + +int UIScene_LoadOrJoinMenu::CrossSaveUploadFinishedCallback(void *pParam,int iPad,C4JStorage::EMessageResult result) +{ + UIScene_LoadOrJoinMenu* pClass = (UIScene_LoadOrJoinMenu *) pParam; + pClass->m_eSaveUploadState = eSaveUpload_Idle; + + return 0; +} + + +int UIScene_LoadOrJoinMenu::UploadSonyCrossSaveThreadProc( LPVOID lpParameter ) +{ + UIScene_LoadOrJoinMenu* pClass = (UIScene_LoadOrJoinMenu *) lpParameter; + pClass->m_saveTransferUploadCancelled = false; + bool bAbortCalled = false; + Minecraft *pMinecraft=Minecraft::GetInstance(); + + // get the save file size + pMinecraft->progressRenderer->progressStagePercentage(0); + pMinecraft->progressRenderer->progressStart(IDS_TOOLTIPS_SAVETRANSFER_UPLOAD); + pMinecraft->progressRenderer->progressStage( IDS_TOOLTIPS_SAVETRANSFER_UPLOAD ); + + PSAVE_DETAILS pSaveDetails=StorageManager.ReturnSavesInfo(); + int idx = pClass->m_iSaveListIndex - pClass->m_iDefaultButtonsC; + bool bSettingOK = app.getRemoteStorage()->setSaveData(&pSaveDetails->SaveInfoA[idx], SaveUploadReturned, pClass); + + if(bSettingOK) + { + pClass->m_eSaveUploadState = eSaveUpload_UploadingFileData; + pMinecraft->progressRenderer->progressStagePercentage(0); + } + else + { + pClass->m_eSaveUploadState = eSaveUpload_Error; + } + + while(pClass->m_eSaveUploadState!=eSaveUpload_Idle) + { + switch(pClass->m_eSaveUploadState) + { + case eSaveUpload_Idle: + break; + case eSaveUpload_UploadingFileData: + { + WCHAR wcTemp[256]; + int dataProgress = app.getRemoteStorage()->getDataProgress(); + pMinecraft->progressRenderer->progressStagePercentage(dataProgress); + + //swprintf(wcTemp, 256, L"Uploading data : %d", dataProgress);//app.GetString(IDS_SAVETRANSFER_STAGE_GET_DATA),0,pClass->m_ulFileSize); + swprintf(wcTemp,256, app.GetString(IDS_SAVETRANSFER_STAGE_PUT_DATA),dataProgress); + + m_wstrStageText=wcTemp; + pMinecraft->progressRenderer->progressStage( m_wstrStageText ); +// 4J-PB - Waiting for Sony to fix canceling a save upload + if(pClass->m_saveTransferUploadCancelled && bAbortCalled == false) + { + // we only really want to be able to cancel during the download of data, if it's taking a long time + app.getRemoteStorage()->abort(); + bAbortCalled = true; + } + } + break; + case eSaveUpload_FileDataUploaded: + { + UINT uiIDA[1]; + uiIDA[0]=IDS_CONFIRM_OK; + ui.RequestMessageBox( IDS_TOOLTIPS_SAVETRANSFER_UPLOAD, IDS_SAVE_TRANSFER_UPLOADCOMPLETE, uiIDA,1,ProfileManager.GetPrimaryPad(),CrossSaveUploadFinishedCallback,pClass, app.GetStringTable()); + pClass->m_eSaveUploadState = esaveUpload_Finished; + } + break; + case eSaveUpload_Cancelled: // this is no longer used + assert(0);// pClass->m_eSaveUploadState = eSaveUpload_Idle; + break; + case eSaveUpload_Error: + { + if(pClass->m_saveTransferUploadCancelled) + { + pClass->m_eSaveUploadState = eSaveUpload_Idle; + } + else + { + UINT uiIDA[1]; + uiIDA[0]=IDS_CONFIRM_OK; + ui.RequestMessageBox( IDS_TOOLTIPS_SAVETRANSFER_UPLOAD, IDS_SAVE_TRANSFER_UPLOADFAILED, uiIDA,1,ProfileManager.GetPrimaryPad(),CrossSaveUploadFinishedCallback,pClass, app.GetStringTable()); + pClass->m_eSaveUploadState = esaveUpload_Finished; + } + } + break; + case esaveUpload_Finished: + // waiting for dialog to be dismissed + break; + } + Sleep(50); + } + + return 0; + +} + +void UIScene_LoadOrJoinMenu::SaveUploadReturned(LPVOID lpParam, SonyRemoteStorage::Status s, int error_code) +{ + UIScene_LoadOrJoinMenu* pClass = (UIScene_LoadOrJoinMenu *) lpParam; + + if(pClass->m_saveTransferUploadCancelled) + { + UINT uiIDA[1] = { IDS_CONFIRM_OK }; + ui.RequestMessageBox( IDS_CANCEL_UPLOAD_TITLE, IDS_CANCEL_UPLOAD_TEXT, uiIDA, 1, ProfileManager.GetPrimaryPad(), CrossSaveUploadFinishedCallback, pClass, app.GetStringTable() ); + pClass->m_eSaveUploadState=esaveUpload_Finished; + } + else + { + if(s == SonyRemoteStorage::e_setDataSucceeded) + pClass->m_eSaveUploadState = eSaveUpload_FileDataUploaded; + else if ( !pClass->m_saveTransferUploadCancelled ) + pClass->m_eSaveUploadState = eSaveUpload_Error; + } +} + +void UIScene_LoadOrJoinMenu::CancelSaveUploadCallback(LPVOID lpParam) +{ + UIScene_LoadOrJoinMenu* pClass = (UIScene_LoadOrJoinMenu *) lpParam; + pClass->m_saveTransferUploadCancelled = true; + app.DebugPrintf("m_saveTransferUploadCancelled = true\n"); + ui.SetTooltips( DEFAULT_XUI_MENU_USER, -1, -1, -1, -1,-1,-1,-1,-1); // MGH - added - remove the "cancel" tooltip, so the player knows it's underway (really needs a "cancelling" message) + + pClass->m_bIgnoreInput = true; +} + +int UIScene_LoadOrJoinMenu::SaveTransferDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result) +{ + UIScene_LoadOrJoinMenu* pClass = (UIScene_LoadOrJoinMenu*)pParam; + // results switched for this dialog + if(result==C4JStorage::EMessage_ResultAccept) + { + // upload the save + pClass->LaunchSaveUpload(); + + pClass->m_bIgnoreInput=false; + } + else + { + pClass->m_bIgnoreInput=false; + } + return 0; +} +#endif // SONY_REMOTE_STORAGE_UPLOAD + + +#if defined _XBOX_ONE +void UIScene_LoadOrJoinMenu::LaunchSaveTransfer() +{ + SaveTransferStateContainer *stateContainer = new SaveTransferStateContainer(); + stateContainer->m_iProgress = 0; + stateContainer->m_bSaveTransferInProgress = false; + stateContainer->m_bSaveTransferCancelled = false; + stateContainer->m_iPad = m_iPad; + stateContainer->m_eSaveTransferState = C4JStorage::eSaveTransfer_Idle; + stateContainer->m_pClass = this; + + LoadingInputParams *loadingParams = new LoadingInputParams(); + loadingParams->func = &UIScene_LoadOrJoinMenu::DownloadXbox360SaveThreadProc; + loadingParams->lpParam = (LPVOID)stateContainer; + + UIFullscreenProgressCompletionData *completionData = new UIFullscreenProgressCompletionData(); + completionData->bShowBackground=TRUE; + completionData->bShowLogo=TRUE; + completionData->type = e_ProgressCompletion_NavigateBackToScene; + completionData->iPad = DEFAULT_XUI_MENU_USER; + completionData->bRequiresUserAction=TRUE; + loadingParams->completionData = completionData; + + loadingParams->cancelFunc=&UIScene_LoadOrJoinMenu::CancelSaveTransferCallback; + loadingParams->m_cancelFuncParam=stateContainer; + loadingParams->cancelText=IDS_TOOLTIPS_CANCEL; + + ui.NavigateToScene(m_iPad,eUIScene_FullscreenProgress, loadingParams); +} + + + +int UIScene_LoadOrJoinMenu::DownloadXbox360SaveThreadProc( LPVOID lpParameter ) +{ + Compression::UseDefaultThreadStorage(); + + SaveTransferStateContainer *pStateContainer = (SaveTransferStateContainer *) lpParameter; + Minecraft *pMinecraft=Minecraft::GetInstance(); + ConsoleSaveFile* pSave = NULL; + + while(StorageManager.SaveTransferClearState()!=C4JStorage::eSaveTransfer_Idle) + { + Sleep(5); + } + + pStateContainer->m_bSaveTransferInProgress=true; + + UIScene_LoadOrJoinMenu::s_eSaveTransferFile = eSaveTransferFile_Marker; + RequestFileSize( pStateContainer, L"completemarker" ); + + while((pStateContainer->m_eSaveTransferState!=C4JStorage::eSaveTransfer_Idle) && pStateContainer->m_bSaveTransferInProgress && !pStateContainer->m_bSaveTransferCancelled) + { + switch(pStateContainer->m_eSaveTransferState) + { + case C4JStorage::eSaveTransfer_Idle: + break; + case C4JStorage::eSaveTransfer_FileSizeRetrieved: + switch(UIScene_LoadOrJoinMenu::s_eSaveTransferFile) + { + case eSaveTransferFile_Marker: + if(UIScene_LoadOrJoinMenu::s_ulFileSize == 0) + { + pMinecraft->progressRenderer->progressStage(IDS_SAVETRANSFER_NONE_FOUND); + pStateContainer->m_eSaveTransferState=C4JStorage::eSaveTransfer_Idle; + } + else + { + RequestFileData( pStateContainer, L"completemarker" ); + } + break; + case eSaveTransferFile_Metadata: + RequestFileData( pStateContainer, L"metadata" ); + break; + case eSaveTransferFile_SaveData: + RequestFileData( pStateContainer, L"savedata" ); + break; + }; + break; + case C4JStorage::eSaveTransfer_GettingFileData: + + break; + case C4JStorage::eSaveTransfer_FileDataRetrieved: + switch(UIScene_LoadOrJoinMenu::s_eSaveTransferFile) + { + case eSaveTransferFile_Marker: + UIScene_LoadOrJoinMenu::s_eSaveTransferFile = eSaveTransferFile_Metadata; + RequestFileSize( pStateContainer, L"metadata" ); + break; + case eSaveTransferFile_Metadata: + { + ByteArrayInputStream bais(UIScene_LoadOrJoinMenu::s_transferData); + DataInputStream dis(&bais); + + wstring saveTitle = dis.readUTF(); + StorageManager.SetSaveTitle(saveTitle.c_str()); + + wstring saveUniqueName = dis.readUTF(); + + // 4J Stu - Don't set this any more. We added it so that we could share the ban list data for this save + // However if the player downloads the same save multiple times, it will overwrite the previous version + // with that filname, and they could have made changes to it. + //StorageManager.SetSaveUniqueFilename((wchar_t *)saveUniqueName.c_str()); + + int thumbnailSize = dis.readInt(); + if(thumbnailSize > 0) + { + byteArray ba(thumbnailSize); + dis.readFully(ba); + + StorageManager.SetSaveImages(ba.data, ba.length, NULL, 0, NULL, 0); + + delete ba.data; + } + + UIScene_LoadOrJoinMenu::s_transferData = byteArray(); + UIScene_LoadOrJoinMenu::s_eSaveTransferFile = eSaveTransferFile_SaveData; + RequestFileSize( pStateContainer, L"savedata" ); + } + break; + case eSaveTransferFile_SaveData: + { +#ifdef SPLIT_SAVES + if(!pStateContainer->m_bSaveTransferCancelled) + { + ConsoleSaveFileOriginal oldFormatSave( L"Temp name", UIScene_LoadOrJoinMenu::s_transferData.data, UIScene_LoadOrJoinMenu::s_transferData.length, false, SAVE_FILE_PLATFORM_X360 ); + pSave = new ConsoleSaveFileSplit( &oldFormatSave, false, pMinecraft->progressRenderer ); + + pMinecraft->progressRenderer->progressStage(IDS_SAVETRANSFER_STAGE_SAVING); + if(!pStateContainer->m_bSaveTransferCancelled) pSave->Flush(false,false); + } + pStateContainer->m_eSaveTransferState=C4JStorage::eSaveTransfer_Saving; + +#else + pSave = new ConsoleSaveFileOriginal( wSaveName, m_transferData.data, m_transferData.length, false, SAVE_FILE_PLATFORM_X360 ); + pStateContainer->m_eSaveTransferState=C4JStorage::eSaveTransfer_Converting; +#endif + delete UIScene_LoadOrJoinMenu::s_transferData.data; + UIScene_LoadOrJoinMenu::s_transferData = byteArray(); + } + break; + }; + + pStateContainer->m_iProgress=0; + break; + case C4JStorage::eSaveTransfer_Converting: +#if 0 + pSave->ConvertToLocalPlatform(); + + pMinecraft->progressRenderer->progressStage(IDS_SAVETRANSFER_STAGE_SAVING); + if(!pStateContainer->m_bSaveTransferCancelled) pSave->Flush(false,false); + + pStateContainer->m_iProgress+=1; + if(pStateContainer->m_iProgress==101) + { + pStateContainer->m_eSaveTransferState=C4JStorage::eSaveTransfer_Saving; + pStateContainer->m_iProgress=0; + break; + } + pMinecraft->progressRenderer->progressStagePercentage(pStateContainer->m_iProgress); +#endif + break; + case C4JStorage::eSaveTransfer_Saving: + // On Durango/Orbis, we need to wait for all the asynchronous saving processes to complete before destroying the levels, as that will ultimately delete + // the directory level storage & therefore the ConsoleSaveSplit instance, which needs to be around until all the sub files have completed saving. +#if defined(_DURANGO) || defined(__ORBIS__) + pMinecraft->progressRenderer->progressStage(IDS_PROGRESS_SAVING_TO_DISC); + + while(StorageManager.GetSaveState() != C4JStorage::ESaveGame_Idle ) + { + Sleep(10); + + // 4J Stu - DO NOT tick this here. The main thread should be the only place ticking the StorageManager. You WILL get crashes. + //StorageManager.Tick(); + } +#endif + + delete pSave; + +#ifdef _XBOX_ONE + pMinecraft->progressRenderer->progressStage(IDS_SAVE_TRANSFER_DOWNLOAD_AND_CONVERT_COMPLETE); +#endif + + pStateContainer->m_eSaveTransferState=C4JStorage::eSaveTransfer_Idle; + + // wipe the list and repopulate it + if(!pStateContainer->m_bSaveTransferCancelled) pStateContainer->m_pClass->m_iState=e_SavesRepopulateAfterTransferDownload; + + //pClass->m_iProgress+=1; + //if(pClass->m_iProgress==101) + //{ + // pClass->m_iProgress=0; + // pClass->m_eSaveTransferState=C4JStorage::eSaveTransfer_Idle; + // pMinecraft->progressRenderer->progressStage( IDS_SAVE_TRANSFER_DOWNLOAD_AND_CONVERT_COMPLETE ); + + // break; + //} + //pMinecraft->progressRenderer->progressStagePercentage(pClass->m_iProgress); + + break; + } + Sleep(50); + } + + if(pStateContainer->m_bSaveTransferCancelled) + { + WCHAR wcTemp[256]; + + pStateContainer->m_bSaveTransferCancelled=false; + swprintf(wcTemp,app.GetString(IDS_SAVE_TRANSFER_DOWNLOAD_CANCELLED)); + m_wstrStageText=wcTemp; + pMinecraft->progressRenderer->progressStage( m_wstrStageText ); + + } + + pStateContainer->m_eSaveTransferState=C4JStorage::eSaveTransfer_Idle; + pStateContainer->m_bSaveTransferInProgress=false; + + delete pStateContainer; + + return 0; +} + +void UIScene_LoadOrJoinMenu::RequestFileSize( SaveTransferStateContainer *pClass, wchar_t *filename ) +{ + Minecraft *pMinecraft=Minecraft::GetInstance(); + + // get the save file size + pMinecraft->progressRenderer->progressStart(IDS_SAVETRANSFER_TITLE_GET); + pMinecraft->progressRenderer->progressStage( IDS_SAVETRANSFER_STAGE_GET_DETAILS ); + +#ifdef _DEBUG_MENUS_ENABLED + if(app.GetLoadSavesFromFolderEnabled()) + { + ZeroMemory(&m_debugTransferDetails, sizeof(C4JStorage::SAVETRANSFER_FILE_DETAILS) ); + + File targetFile( wstring(L"FakeTMSPP\\").append(filename) ); + if(targetFile.exists()) m_debugTransferDetails.ulFileLen = targetFile.length(); + + SaveTransferReturned(pClass,&m_debugTransferDetails); + } + else +#endif + { + do + { + pMinecraft->progressRenderer->progressStart(IDS_SAVETRANSFER_TITLE_GET); + pMinecraft->progressRenderer->progressStage( IDS_SAVETRANSFER_STAGE_GET_DETAILS ); + Sleep(1); + pClass->m_eSaveTransferState=StorageManager.SaveTransferGetDetails(pClass->m_iPad,C4JStorage::eGlobalStorage_TitleUser,filename,&UIScene_LoadOrJoinMenu::SaveTransferReturned,pClass); + } + while(pClass->m_eSaveTransferState == C4JStorage::eSaveTransfer_Busy && !pClass->m_bSaveTransferCancelled ); + } +} + +void UIScene_LoadOrJoinMenu::RequestFileData( SaveTransferStateContainer *pClass, wchar_t *filename ) +{ + Minecraft *pMinecraft=Minecraft::GetInstance(); + WCHAR wcTemp[256]; + + pMinecraft->progressRenderer->progressStagePercentage(0); + + swprintf(wcTemp,app.GetString(IDS_SAVETRANSFER_STAGE_GET_DATA),0,UIScene_LoadOrJoinMenu::s_ulFileSize); + m_wstrStageText=wcTemp; + + pMinecraft->progressRenderer->progressStage( m_wstrStageText ); + +#ifdef _DEBUG_MENUS_ENABLED + if(app.GetLoadSavesFromFolderEnabled()) + { + File targetFile( wstring(L"FakeTMSPP\\").append(filename) ); + if(targetFile.exists()) + { + HANDLE hSaveFile = CreateFile( targetFile.getPath().c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, NULL); + + m_debugTransferDetails.pbData = new BYTE[m_debugTransferDetails.ulFileLen]; + + DWORD numberOfBytesRead = 0; + ReadFile( hSaveFile,m_debugTransferDetails.pbData,m_debugTransferDetails.ulFileLen,&numberOfBytesRead,NULL); + assert(numberOfBytesRead == m_debugTransferDetails.ulFileLen); + + CloseHandle(hSaveFile); + + SaveTransferReturned(pClass,&m_debugTransferDetails); + } + } + else +#endif + { + do + { + pMinecraft->progressRenderer->progressStart(IDS_SAVETRANSFER_TITLE_GET); + pMinecraft->progressRenderer->progressStage( -1 ); + Sleep(1); + pClass->m_eSaveTransferState=StorageManager.SaveTransferGetData(pClass->m_iPad,C4JStorage::eGlobalStorage_TitleUser,filename,&UIScene_LoadOrJoinMenu::SaveTransferReturned,&UIScene_LoadOrJoinMenu::SaveTransferUpdateProgress,pClass,pClass); + } + while(pClass->m_eSaveTransferState == C4JStorage::eSaveTransfer_Busy && !pClass->m_bSaveTransferCancelled ); + } +} + +int UIScene_LoadOrJoinMenu::SaveTransferReturned(LPVOID lpParam,C4JStorage::SAVETRANSFER_FILE_DETAILS *pSaveTransferDetails) +{ + SaveTransferStateContainer* pClass = (SaveTransferStateContainer *) lpParam; + app.DebugPrintf("Save Transfer - size is %d\n",pSaveTransferDetails->ulFileLen); + + // if the file data is null, then assume this is the file size retrieval + if(pSaveTransferDetails->pbData==NULL) + { + pClass->m_eSaveTransferState=C4JStorage::eSaveTransfer_FileSizeRetrieved; + UIScene_LoadOrJoinMenu::s_ulFileSize=pSaveTransferDetails->ulFileLen; + } + else + { + delete UIScene_LoadOrJoinMenu::s_transferData.data; + UIScene_LoadOrJoinMenu::s_transferData = byteArray(pSaveTransferDetails->pbData, UIScene_LoadOrJoinMenu::s_ulFileSize); + pClass->m_eSaveTransferState=C4JStorage::eSaveTransfer_FileDataRetrieved; + } + + return 0; +} + +int UIScene_LoadOrJoinMenu::SaveTransferUpdateProgress(LPVOID lpParam,unsigned long ulBytesReceived) +{ + WCHAR wcTemp[256]; + + SaveTransferStateContainer* pClass = (SaveTransferStateContainer *) lpParam; + Minecraft *pMinecraft=Minecraft::GetInstance(); + + if(pClass->m_bSaveTransferCancelled) // was cancelled + { + pMinecraft->progressRenderer->progressStage(IDS_SAVE_TRANSFER_DOWNLOAD_CANCELLING); + swprintf(wcTemp,app.GetString(IDS_SAVE_TRANSFER_DOWNLOAD_CANCELLING)); + m_wstrStageText=wcTemp; + pMinecraft->progressRenderer->progressStage( m_wstrStageText ); + } + else + { + unsigned int uiProgress=(unsigned int)(((float)ulBytesReceived/float(UIScene_LoadOrJoinMenu::s_ulFileSize))*100.0f); + + pMinecraft->progressRenderer->progressStagePercentage(uiProgress); + swprintf(wcTemp,app.GetString(IDS_SAVETRANSFER_STAGE_GET_DATA),((float)(ulBytesReceived))/1024000.0f,((float)UIScene_LoadOrJoinMenu::s_ulFileSize)/1024000.0f); + m_wstrStageText=wcTemp; + pMinecraft->progressRenderer->progressStage( m_wstrStageText ); + } + + return 0; +} + +void UIScene_LoadOrJoinMenu::CancelSaveTransferCallback(LPVOID lpParam) +{ + SaveTransferStateContainer* pClass = (SaveTransferStateContainer *) lpParam; + + if(!pClass->m_bSaveTransferCancelled) + { + StorageManager.CancelSaveTransfer(UIScene_LoadOrJoinMenu::CancelSaveTransferCompleteCallback,pClass); + + pClass->m_bSaveTransferCancelled=true; + } + //pClass->m_bSaveTransferInProgress=false; +} + +int UIScene_LoadOrJoinMenu::CancelSaveTransferCompleteCallback(LPVOID lpParam) +{ + SaveTransferStateContainer* pClass = (SaveTransferStateContainer *) lpParam; + // change the state to idle to get the download thread to terminate + pClass->m_eSaveTransferState=C4JStorage::eSaveTransfer_Idle; + return 0; +} + +int UIScene_LoadOrJoinMenu::NeedSyncMessageReturned(void *pParam,int iPad,C4JStorage::EMessageResult result) +{ + UIScene_LoadOrJoinMenu *pClass = (UIScene_LoadOrJoinMenu *)pParam; + LoadMenuInitData *params = (LoadMenuInitData *)pParam; + + if( result == C4JStorage::EMessage_ResultAccept ) + { + // navigate to the settings scene + ui.NavigateToScene(ProfileManager.GetPrimaryPad(), eUIScene_LoadMenu, pClass->m_loadMenuInitData); + } + else + { + delete pClass->m_loadMenuInitData; + pClass->m_bIgnoreInput = false; + } + + return 0; +} + + +#endif + + +#ifdef _XBOX_ONE +void UIScene_LoadOrJoinMenu::HandleDLCLicenseChange() +{ + // may have installed Halloween on this menu + app.StartInstallDLCProcess(m_iPad); +} +#endif + +#if defined _XBOX_ONE || defined __ORBIS__ +int UIScene_LoadOrJoinMenu::CopySaveDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result) +{ + UIScene_LoadOrJoinMenu* pClass = (UIScene_LoadOrJoinMenu*)pParam; + + if(result==C4JStorage::EMessage_ResultAccept) + { + + LoadingInputParams *loadingParams = new LoadingInputParams(); + void *uniqueId = (LPVOID)pClass->GetCallbackUniqueId(); + loadingParams->func = &UIScene_LoadOrJoinMenu::CopySaveThreadProc; + loadingParams->lpParam = uniqueId; + loadingParams->waitForThreadToDelete = true; + + UIFullscreenProgressCompletionData *completionData = new UIFullscreenProgressCompletionData(); + completionData->bShowBackground=TRUE; + completionData->bShowLogo=TRUE; + completionData->type = e_ProgressCompletion_NavigateBackToScene; + completionData->iPad = DEFAULT_XUI_MENU_USER; + loadingParams->completionData = completionData; + + loadingParams->cancelFunc=&UIScene_LoadOrJoinMenu::CancelCopySaveCallback; + loadingParams->m_cancelFuncParam=uniqueId; + loadingParams->cancelText=IDS_TOOLTIPS_CANCEL; + + ui.NavigateToScene(iPad,eUIScene_FullscreenProgress, loadingParams); + } + else + { + pClass->m_bIgnoreInput=false; + } + + return 0; +} + +int UIScene_LoadOrJoinMenu::CopySaveThreadProc( LPVOID lpParameter ) +{ + Minecraft *pMinecraft=Minecraft::GetInstance(); + pMinecraft->progressRenderer->progressStart(IDS_PROGRESS_COPYING_SAVE); + pMinecraft->progressRenderer->progressStage( -1 ); + + ui.EnterCallbackIdCriticalSection(); + UIScene_LoadOrJoinMenu* pClass = (UIScene_LoadOrJoinMenu*)ui.GetSceneFromCallbackId((size_t)lpParameter); + if( pClass ) + { + pClass->m_bCopying = true; + pClass->m_bCopyingCancelled = false; + ui.LeaveCallbackIdCriticalSection(); + // Copy save data takes two callbacks - one for completion, and one for progress. The progress callback also lets us cancel the operation, if we return false. + StorageManager.CopySaveData(&pClass->m_pSaveDetails->SaveInfoA[pClass->m_iSaveListIndex - pClass->m_iDefaultButtonsC],UIScene_LoadOrJoinMenu::CopySaveDataReturned,UIScene_LoadOrJoinMenu::CopySaveDataProgress,lpParameter); + + bool bContinue = true; + do + { + Sleep(100); + ui.EnterCallbackIdCriticalSection(); + pClass = (UIScene_LoadOrJoinMenu*)ui.GetSceneFromCallbackId((size_t)lpParameter); + if( pClass ) + { + bContinue = pClass->m_bCopying; + } + else + { + bContinue = false; + } + ui.LeaveCallbackIdCriticalSection(); + } while( bContinue ); + } + else + { + ui.LeaveCallbackIdCriticalSection(); + } + + return 0; +} + +int UIScene_LoadOrJoinMenu::CopySaveDataReturned(LPVOID lpParam, bool success, C4JStorage::ESaveGameState stat) +{ + ui.EnterCallbackIdCriticalSection(); + UIScene_LoadOrJoinMenu* pClass = (UIScene_LoadOrJoinMenu*)ui.GetSceneFromCallbackId((size_t)lpParam); + + if(pClass) + { + if(success) + { + pClass->m_bCopying = false; + // wipe the list and repopulate it + pClass->m_iState=e_SavesRepopulateAfterDelete; + ui.LeaveCallbackIdCriticalSection(); + } + else + { +#ifdef __ORBIS__ + UINT uiIDA[1]; + // you cancelled the save on exit after choosing exit and save? You go back to the Exit choices then. + uiIDA[0]=IDS_OK; + + if( stat == C4JStorage::ESaveGame_CopyCompleteFailLocalStorage ) + { + ui.LeaveCallbackIdCriticalSection(); + ui.RequestMessageBox(IDS_COPYSAVE_FAILED_TITLE, IDS_COPYSAVE_FAILED_LOCAL, uiIDA, 1, ProfileManager.GetPrimaryPad(), CopySaveErrorDialogFinishedCallback, lpParam, app.GetStringTable()); + } + else if( stat == C4JStorage::ESaveGame_CopyCompleteFailQuota ) + { + ui.LeaveCallbackIdCriticalSection(); + ui.RequestMessageBox(IDS_COPYSAVE_FAILED_TITLE, IDS_COPYSAVE_FAILED_QUOTA, uiIDA, 1, ProfileManager.GetPrimaryPad(), CopySaveErrorDialogFinishedCallback, lpParam, app.GetStringTable()); + } + else + { + pClass->m_bCopying = false; + ui.LeaveCallbackIdCriticalSection(); + } +#else + pClass->m_bCopying = false; + ui.LeaveCallbackIdCriticalSection(); +#endif + } + } + else + { + ui.LeaveCallbackIdCriticalSection(); + } + return 0; +} + +bool UIScene_LoadOrJoinMenu::CopySaveDataProgress(LPVOID lpParam, int percent) +{ + bool bContinue = false; + ui.EnterCallbackIdCriticalSection(); + UIScene_LoadOrJoinMenu* pClass = (UIScene_LoadOrJoinMenu*)ui.GetSceneFromCallbackId((size_t)lpParam); + if( pClass ) + { + bContinue = !pClass->m_bCopyingCancelled; + } + ui.LeaveCallbackIdCriticalSection(); + Minecraft *pMinecraft=Minecraft::GetInstance(); + pMinecraft->progressRenderer->progressStagePercentage(percent); + + return bContinue; +} + +void UIScene_LoadOrJoinMenu::CancelCopySaveCallback(LPVOID lpParam) +{ + ui.EnterCallbackIdCriticalSection(); + UIScene_LoadOrJoinMenu* pClass = (UIScene_LoadOrJoinMenu*)ui.GetSceneFromCallbackId((size_t)lpParam); + if( pClass ) + { + pClass->m_bCopyingCancelled = true; + } + ui.LeaveCallbackIdCriticalSection(); +} + +int UIScene_LoadOrJoinMenu::CopySaveErrorDialogFinishedCallback(void *pParam,int iPad,C4JStorage::EMessageResult result) +{ + ui.EnterCallbackIdCriticalSection(); + UIScene_LoadOrJoinMenu* pClass = (UIScene_LoadOrJoinMenu*)ui.GetSceneFromCallbackId((size_t)pParam); + if( pClass ) + { + pClass->m_bCopying = false; + } + ui.LeaveCallbackIdCriticalSection(); + + return 0; +} + +#endif // _XBOX_ONE diff --git a/Minecraft.Client/Common/UI/UIScene_LoadOrJoinMenu.h b/Minecraft.Client/Common/UI/UIScene_LoadOrJoinMenu.h new file mode 100644 index 00000000..01d94b05 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_LoadOrJoinMenu.h @@ -0,0 +1,300 @@ +#pragma once + +#include "UIScene.h" + +class LevelGenerationOptions; + + +#if defined __PS3__ || defined __ORBIS__ || defined(__PSVITA__) +#define SONY_REMOTE_STORAGE_DOWNLOAD +#endif +#if defined __PS3__ || __PSVITA__ +#define SONY_REMOTE_STORAGE_UPLOAD +#endif + + +class UIScene_LoadOrJoinMenu : public UIScene +{ +private: + enum EControls + { + eControl_SavesList, + eControl_GamesList, +#if defined(_XBOX_ONE) || defined(__ORBIS__) + eControl_SpaceIndicator, +#endif + }; + + enum EState + { + e_SavesIdle, + e_SavesRepopulate, + e_SavesRepopulateAfterMashupHide, + e_SavesRepopulateAfterDelete, + e_SavesRepopulateAfterTransferDownload, + }; + + enum eActions + { + eAction_None=0, + eAction_ViewInvites, + eAction_JoinGame, + }; + eActions m_eAction; + + static const int JOIN_LOAD_CREATE_BUTTON_INDEX = 0; + + SaveListDetails *m_saveDetails; + int m_iSaveDetailsCount; + +protected: + UIControl_SaveList m_buttonListSaves; + UIControl_SaveList m_buttonListGames; + UIControl_Label m_labelSavesListTitle, m_labelJoinListTitle, m_labelNoGames; + UIControl m_controlSavesTimer, m_controlJoinTimer; +#if defined(_XBOX_ONE) || defined(__ORBIS__) + UIControl_SpaceIndicatorBar m_spaceIndicatorSaves; +#endif + +private: + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) + UI_MAP_ELEMENT( m_buttonListSaves, "SavesList") + UI_MAP_ELEMENT( m_buttonListGames, "JoinList") + + UI_MAP_ELEMENT( m_labelSavesListTitle, "SavesListTitle") + UI_MAP_ELEMENT( m_labelJoinListTitle, "JoinListTitle") + UI_MAP_ELEMENT( m_labelNoGames, "NoGames") + + UI_MAP_ELEMENT( m_controlSavesTimer, "SavesTimer") + UI_MAP_ELEMENT( m_controlJoinTimer, "JoinTimer") + +#if defined(_XBOX_ONE) || defined(__ORBIS__) + UI_MAP_ELEMENT( m_spaceIndicatorSaves, "SaveSizeBar") +#endif + UI_END_MAP_ELEMENTS_AND_NAMES() + + int m_iDefaultButtonsC; + int m_iMashUpButtonsC; + int m_iState; + + vector<FriendSessionInfo *> *m_currentSessions; + vector<LevelGenerationOptions *> m_generators; + vector<File *> *m_saves; + + bool m_bIgnoreInput; + bool m_bAllLoaded; + bool m_bRetrievingSaveThumbnails; + bool m_bSaveThumbnailReady; + bool m_bShowingPartyGamesOnly; + bool m_bInParty; + JoinMenuInitData *m_initData; + bool m_bMultiplayerAllowed; + int m_iTexturePacksNotInstalled; + int m_iRequestingThumbnailId; + SAVE_DETAILS *m_pSaveDetails; + bool m_bSavesDisplayed; + bool m_bExitScene; + bool m_bCopying; + bool m_bCopyingCancelled; + int m_iSaveInfoC; + int m_iSaveListIndex; + int m_iGameListIndex; + //int *m_iConfigA; // track the texture packs that we don't have installed +#ifndef _XBOX_ONE + bool m_bSaveTransferInProgress; + bool m_bSaveTransferCancelled; +#endif + bool m_bUpdateSaveSize; + +public: + UIScene_LoadOrJoinMenu(int iPad, void *initData, UILayer *parentLayer); + virtual ~UIScene_LoadOrJoinMenu(); + + virtual void updateTooltips(); + virtual void updateComponents(); + + virtual void handleDestroy(); + virtual void handleLoseFocus(); + virtual void handleGainFocus(bool navBack); + virtual void handleTimerComplete(int id); + // INPUT + virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled); + virtual void handleFocusChange(F64 controlId, F64 childId); + virtual void handleInitFocus(F64 controlId, F64 childId); + + virtual EUIScene getSceneType() { return eUIScene_LoadOrJoinMenu;} + + static void UpdateGamesListCallback(LPVOID pParam); +#ifdef _XBOX_ONE + void HandleDLCLicenseChange(); +#endif + virtual void tick(); + +private: + void Initialise(); + void GetSaveInfo(); + void UpdateGamesList(); + void AddDefaultButtons(); + bool DoesSavesListHaveFocus(); + bool DoesMashUpWorldHaveFocus(); + bool DoesGamesListHaveFocus(); + +protected: + // TODO: This should be pure virtual in this class + virtual wstring getMoviePath(); + +public: + + static int LoadSaveDataThumbnailReturned(LPVOID lpParam,PBYTE pbThumbnail,DWORD dwThumbnailBytes); + static int LoadSaveCallback(LPVOID lpParam,bool bRes); + static int DeleteSaveDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result); + static int SaveOptionsDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result); + static int TexturePackDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result); + static int DeleteSaveDataReturned(LPVOID lpParam,bool bRes); + static int RenameSaveDataReturned(LPVOID lpParam,bool bRes); + static int KeyboardCompleteWorldNameCallback(LPVOID lpParam,bool bRes); +protected: + void handlePress(F64 controlId, F64 childId); + void LoadLevelGen(LevelGenerationOptions *levelGen); + void LoadSaveFromDisk(File *saveFile, ESavePlatform savePlatform = SAVE_FILE_PLATFORM_LOCAL); +#if defined(__PS3__) || defined(__PSVITA__) || defined(__ORBIS__) + void LoadSaveFromCloud(); +#endif +public: + virtual void HandleDLCMountingComplete(); + +#ifdef __ORBIS__ + void LoadRemoteFileFromDisk(char* remoteFilename); +#endif + +private: + void CheckAndJoinGame(int gameIndex); +#if defined(__PS3__) || defined(__PSVITA__) || defined(__ORBIS__) + static int MustSignInReturnedPSN(void *pParam,int iPad,C4JStorage::EMessageResult result); + static int PSN_SignInReturned(void *pParam,bool bContinue, int iPad); + static void remoteStorageGetSaveCallback(LPVOID lpParam, SonyRemoteStorage::Status s, int error_code); +#endif + +#ifdef __ORBIS__ + //static int PSPlusReturned(void *pParam,int iPad,C4JStorage::EMessageResult result); +#endif +#ifdef _XBOX_ONE + typedef struct _SaveTransferStateContainer + { + int m_iProgress; + bool m_bSaveTransferInProgress; + bool m_bSaveTransferCancelled; + int m_iPad; + C4JStorage::eSaveTransferState m_eSaveTransferState; + UIScene_LoadOrJoinMenu *m_pClass; + } SaveTransferStateContainer; + enum ESaveTransferFiles + { + eSaveTransferFile_Marker, + eSaveTransferFile_Metadata, + eSaveTransferFile_SaveData, + }; + static ESaveTransferFiles s_eSaveTransferFile; + static unsigned long s_ulFileSize; + static byteArray s_transferData; + static wstring m_wstrStageText; + LoadMenuInitData *m_loadMenuInitData; + +#ifdef _DEBUG_MENUS_ENABLED + static C4JStorage::SAVETRANSFER_FILE_DETAILS m_debugTransferDetails; +#endif + + void LaunchSaveTransfer(); + static int DownloadXbox360SaveThreadProc( LPVOID lpParameter ); + static void RequestFileSize( SaveTransferStateContainer *pClass, wchar_t *filename ); + static void RequestFileData( SaveTransferStateContainer *pClass, wchar_t *filename ); + static int SaveTransferReturned(LPVOID lpParam,C4JStorage::SAVETRANSFER_FILE_DETAILS *pSaveTransferDetails); + static int SaveTransferUpdateProgress(LPVOID lpParam,unsigned long ulBytesReceived); + static void CancelSaveTransferCallback(LPVOID lpParam); + static int NeedSyncMessageReturned(void *pParam,int iPad,C4JStorage::EMessageResult result); + static int CancelSaveTransferCompleteCallback(LPVOID lpParam); + +#endif + + + +#ifdef SONY_REMOTE_STORAGE_DOWNLOAD + enum eSaveTransferState + { + eSaveTransfer_Idle, + eSaveTransfer_Busy, + eSaveTransfer_GetRemoteSaveInfo, + eSaveTransfer_GettingRemoteSaveInfo, + eSaveTransfer_CreateDummyFile, + eSaveTransfer_CreatingDummyFile, + eSaveTransfer_GettingFileSize, + eSaveTransfer_FileSizeRetrieved, + eSaveTransfer_GetFileData, + eSaveTransfer_GettingFileData, + eSaveTransfer_FileDataRetrieved, + eSaveTransfer_GetSavesInfo, + eSaveTransfer_GettingSavesInfo, + eSaveTransfer_LoadSaveFromDisc, + eSaveTransfer_LoadingSaveFromDisc, + eSaveTransfer_CreatingNewSave, + eSaveTransfer_Converting, + eSaveTransfer_Saving, + eSaveTransfer_Succeeded, + eSaveTransfer_Cancelled, + eSaveTransfer_Error, + eSaveTransfer_ErrorDeletingSave, + eSaveTransfer_ErrorMesssage, + eSaveTransfer_Finished, + + }; + eSaveTransferState m_eSaveTransferState; + static unsigned long m_ulFileSize; + static wstring m_wstrStageText; + int m_iProgress; + char m_downloadedUniqueFilename[64];//SCE_SAVE_DATA_DIRNAME_DATA_MAXSIZE]; + bool m_saveTransferDownloadCancelled; + void LaunchSaveTransfer(); + static int CreateDummySaveDataCallback(LPVOID lpParam,bool bRes); + static int CrossSaveGetSavesInfoCallback(LPVOID lpParam, SAVE_DETAILS *pSaveDetails,bool bRes); + static int LoadCrossSaveDataCallback(void *pParam,bool bIsCorrupt, bool bIsOwner); + static int CrossSaveFinishedCallback(void *pParam,int iPad,C4JStorage::EMessageResult result); + static int CrossSaveDeleteOnErrorReturned(LPVOID lpParam,bool bRes); + static int RemoteSaveNotFoundCallback(void *pParam,int iPad,C4JStorage::EMessageResult result); + static int DownloadSonyCrossSaveThreadProc( LPVOID lpParameter ); + static void SaveTransferReturned(LPVOID lpParam, SonyRemoteStorage::Status s, int error_code); + static ConsoleSaveFile* SonyCrossSaveConvert(); + + static void CancelSaveTransferCallback(LPVOID lpParam); +#endif + +#ifdef SONY_REMOTE_STORAGE_UPLOAD + enum eSaveUploadState + { + eSaveUpload_Idle, + eSaveUpload_UploadingFileData, + eSaveUpload_FileDataUploaded, + eSaveUpload_Cancelled, + eSaveUpload_Error, + esaveUpload_Finished + }; + + eSaveUploadState m_eSaveUploadState; + bool m_saveTransferUploadCancelled; + + void LaunchSaveUpload(); + static int UploadSonyCrossSaveThreadProc( LPVOID lpParameter ); + static void SaveUploadReturned(LPVOID lpParam, SonyRemoteStorage::Status s, int error_code); + static void CancelSaveUploadCallback(LPVOID lpParam); + static int SaveTransferDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result); + static int CrossSaveUploadFinishedCallback(void *pParam,int iPad,C4JStorage::EMessageResult result); +#endif + +#if defined _XBOX_ONE || defined __ORBIS__ + static int CopySaveDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result); + static int CopySaveThreadProc( LPVOID lpParameter ); + static int CopySaveDataReturned( LPVOID lpParameter, bool success, C4JStorage::ESaveGameState state ); + static bool CopySaveDataProgress(LPVOID lpParam, int percent); + static void CancelCopySaveCallback(LPVOID lpParam); + static int CopySaveErrorDialogFinishedCallback(void *pParam,int iPad,C4JStorage::EMessageResult result); +#endif +}; diff --git a/Minecraft.Client/Common/UI/UIScene_MainMenu.cpp b/Minecraft.Client/Common/UI/UIScene_MainMenu.cpp new file mode 100644 index 00000000..7724aaaf --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_MainMenu.cpp @@ -0,0 +1,2043 @@ +#include "stdafx.h" +#include "..\..\..\Minecraft.World\Mth.h" +#include "..\..\..\Minecraft.World\StringHelpers.h" +#include "..\..\..\Minecraft.World\Random.h" +#include "..\..\User.h" +#include "..\..\MinecraftServer.h" +#include "UI.h" +#include "UIScene_MainMenu.h" +#ifdef __ORBIS__ +#include <error_dialog.h> +#endif + +Random *UIScene_MainMenu::random = new Random(); + +UIScene_MainMenu::UIScene_MainMenu(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) +{ +#ifdef __ORBIS + //m_ePatchCheckState=ePatchCheck_Idle; + m_bRunGameChosen=false; + m_bErrorDialogRunning=false; +#endif + + + // Setup all the Iggy references we need for this scene + initialiseMovie(); + + parentLayer->addComponent(iPad,eUIComponent_Panorama); + parentLayer->addComponent(iPad,eUIComponent_Logo); + + m_eAction=eAction_None; + m_bIgnorePress=false; + + + m_buttons[(int)eControl_PlayGame].init(app.GetString(IDS_PLAY_GAME),eControl_PlayGame); + +#ifdef _XBOX_ONE + if(!ProfileManager.IsFullVersion()) m_buttons[(int)eControl_PlayGame].setLabel(app.GetString(IDS_PLAY_TRIAL_GAME)); + app.SetReachedMainMenu(); +#endif + + m_buttons[(int)eControl_Leaderboards].init(app.GetString(IDS_LEADERBOARDS),eControl_Leaderboards); + m_buttons[(int)eControl_Achievements].init(app.GetString(IDS_ACHIEVEMENTS),eControl_Achievements); + m_buttons[(int)eControl_HelpAndOptions].init(app.GetString(IDS_HELP_AND_OPTIONS),eControl_HelpAndOptions); + if(ProfileManager.IsFullVersion()) + { + m_bTrialVersion=false; + m_buttons[(int)eControl_UnlockOrDLC].init(app.GetString(IDS_DOWNLOADABLECONTENT),eControl_UnlockOrDLC); + } + else + { + m_bTrialVersion=true; + m_buttons[(int)eControl_UnlockOrDLC].init(app.GetString(IDS_UNLOCK_FULL_GAME),eControl_UnlockOrDLC); + } + +#ifndef _DURANGO + m_buttons[(int)eControl_Exit].init(app.GetString(IDS_EXIT_GAME),eControl_Exit); +#else + m_buttons[(int)eControl_XboxHelp].init(app.GetString(IDS_XBOX_HELP_APP), eControl_XboxHelp); +#endif + +#if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__) + // Not allowed to exit from a PS3 game from the game - have to use the PS button + removeControl( &m_buttons[(int)eControl_Exit], false ); + // We don't have a way to display trophies/achievements, so remove the button + removeControl( &m_buttons[(int)eControl_Achievements], false ); + m_bLaunchFullVersionPurchase=false; +#endif +#ifdef _DURANGO + // Allowed to not have achievements in the menu + removeControl( &m_buttons[(int)eControl_Achievements], false ); + // Not allowed to exit from a Xbox One game from the game - have to use the Home button + //removeControl( &m_buttons[(int)eControl_Exit], false ); + m_bWaitingForDLCInfo=false; +#endif + + doHorizontalResizeCheck(); + + m_splash = L""; + + wstring filename = L"splashes.txt"; + if( app.hasArchiveFile(filename) ) + { + byteArray splashesArray = app.getArchiveFile(filename); + ByteArrayInputStream bais(splashesArray); + InputStreamReader isr( &bais ); + BufferedReader br( &isr ); + + wstring line = L""; + while ( !(line = br.readLine()).empty() ) + { + line = trimString( line ); + if (line.length() > 0) + { + m_splashes.push_back(line); + } + } + + br.close(); + } + + m_bIgnorePress=false; + m_bLoadTrialOnNetworkManagerReady = false; + + // 4J Stu - Clear out any loaded game rules + app.setLevelGenerationOptions(NULL); + + // 4J Stu - Reset the leaving game flag so that we correctly handle signouts while in the menus + g_NetworkManager.ResetLeavingGame(); + +#if TO_BE_IMPLEMENTED + // Fix for #45154 - Frontend: DLC: Content can only be downloaded from the frontend if you have not joined/exited multiplayer + XBackgroundDownloadSetMode(XBACKGROUND_DOWNLOAD_MODE_ALWAYS_ALLOW); +#endif +} + +UIScene_MainMenu::~UIScene_MainMenu() +{ + m_parentLayer->removeComponent(eUIComponent_Panorama); + m_parentLayer->removeComponent(eUIComponent_Logo); +} + +void UIScene_MainMenu::updateTooltips() +{ + int iX = -1; + int iA = -1; + if(!m_bIgnorePress) + { + iA = IDS_TOOLTIPS_SELECT; + +#ifdef _XBOX_ONE + iX = IDS_TOOLTIPS_CHOOSE_USER; +#elif defined __PSVITA__ + if(ProfileManager.IsFullVersion()) + { + iX = IDS_TOOLTIP_CHANGE_NETWORK_MODE; + } +#endif + } + ui.SetTooltips( DEFAULT_XUI_MENU_USER, iA, -1, iX); +} + +void UIScene_MainMenu::updateComponents() +{ + m_parentLayer->showComponent(m_iPad,eUIComponent_Panorama,true); + m_parentLayer->showComponent(m_iPad,eUIComponent_Logo,true); +} + +void UIScene_MainMenu::handleGainFocus(bool navBack) +{ + UIScene::handleGainFocus(navBack); + ui.ShowPlayerDisplayname(false); + m_bIgnorePress=false; + + // 4J-JEV: This needs to come before SetLockedProfile(-1) as it wipes the XbLive contexts. + if (!navBack) + { + for (int iPad = 0; iPad < MAX_LOCAL_PLAYERS; iPad++) + { + // For returning to menus after exiting a game. + if (ProfileManager.IsSignedIn(iPad) ) + { + ProfileManager.SetCurrentGameActivity(iPad, CONTEXT_PRESENCE_MENUS, false); + } + } + } + ProfileManager.SetLockedProfile(-1); + + m_bIgnorePress = false; + updateTooltips(); + +#ifdef _DURANGO + ProfileManager.ClearGameUsers(); +#endif + + if(navBack && ProfileManager.IsFullVersion()) + { + // Replace the Unlock Full Game with Downloadable Content + m_buttons[(int)eControl_UnlockOrDLC].setLabel(app.GetString(IDS_DOWNLOADABLECONTENT)); + } + +#if TO_BE_IMPLEMENTED + // Fix for #45154 - Frontend: DLC: Content can only be downloaded from the frontend if you have not joined/exited multiplayer + XBackgroundDownloadSetMode(XBACKGROUND_DOWNLOAD_MODE_ALWAYS_ALLOW); + m_Timer.SetShow(FALSE); +#endif + m_controlTimer.setVisible( false ); + + // 4J-PB - remove the "hobo humping" message legal say we can't have, and the 1080p one for Vita +#ifdef __PSVITA__ + int splashIndex = eSplashRandomStart + 2 + random->nextInt( (int)m_splashes.size() - (eSplashRandomStart + 2) ); +#else + int splashIndex = eSplashRandomStart + 1 + random->nextInt( (int)m_splashes.size() - (eSplashRandomStart + 1) ); +#endif + + // Override splash text on certain dates + SYSTEMTIME LocalSysTime; + GetLocalTime( &LocalSysTime ); + if (LocalSysTime.wMonth == 11 && LocalSysTime.wDay == 9) + { + splashIndex = eSplashHappyBirthdayEx; + } + else if (LocalSysTime.wMonth == 6 && LocalSysTime.wDay == 1) + { + splashIndex = eSplashHappyBirthdayNotch; + } + else if (LocalSysTime.wMonth == 12 && LocalSysTime.wDay == 24) // the Java game shows this on Christmas Eve, so we will too + { + splashIndex = eSplashMerryXmas; + } + else if (LocalSysTime.wMonth == 1 && LocalSysTime.wDay == 1) + { + splashIndex = eSplashHappyNewYear; + } + //splashIndex = 47; // Very short string + //splashIndex = 194; // Very long string + //splashIndex = 295; // Coloured + //splashIndex = 296; // Noise + m_splash = m_splashes.at( splashIndex ); +} + +wstring UIScene_MainMenu::getMoviePath() +{ + return L"MainMenu"; +} + +void UIScene_MainMenu::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled) +{ + //app.DebugPrintf("UIScene_DebugOverlay handling input for pad %d, key %d, down- %s, pressed- %s, released- %s\n", iPad, key, down?"TRUE":"FALSE", pressed?"TRUE":"FALSE", released?"TRUE":"FALSE"); + + if(m_bIgnorePress) return; + +#if defined (__ORBIS__) || defined (__PSVITA__) + // ignore all players except player 0 - it's their profile that is currently being used + if(iPad!=0) return; +#endif + + ui.AnimateKeyPress(m_iPad, key, repeat, pressed, released); + + switch(key) + { + case ACTION_MENU_OK: +#ifdef __ORBIS__ + case ACTION_MENU_TOUCHPAD_PRESS: +#endif + if(pressed) + { + ProfileManager.SetPrimaryPad(iPad); + ProfileManager.SetLockedProfile(-1); + sendInputToMovie(key, repeat, pressed, released); + } + break; +#ifdef _XBOX_ONE + case ACTION_MENU_X: + if(pressed) + { + m_bIgnorePress = true; + ProfileManager.RequestSignInUI(false, false, false, false, false, ChooseUser_SignInReturned, this, iPad); + } + break; +#endif +#ifdef __PSVITA__ + case ACTION_MENU_X: + if(pressed && ProfileManager.IsFullVersion()) + { + UINT uiIDA[2]; + uiIDA[0]=IDS__NETWORK_PSN; + uiIDA[1]=IDS_NETWORK_ADHOC; + ui.RequestMessageBox(IDS_SELECT_NETWORK_MODE_TITLE, IDS_SELECT_NETWORK_MODE_TEXT, uiIDA, 2, XUSER_INDEX_ANY, &UIScene_MainMenu::SelectNetworkModeReturned,this); + } + break; +#endif + + case ACTION_MENU_UP: + case ACTION_MENU_DOWN: + sendInputToMovie(key, repeat, pressed, released); + break; + } +} + +void UIScene_MainMenu::handlePress(F64 controlId, F64 childId) +{ + int primaryPad = ProfileManager.GetPrimaryPad(); + + int (*signInReturnedFunc) (LPVOID,const bool, const int iPad) = NULL; + + switch((int)controlId) + { + case eControl_PlayGame: +#ifdef __ORBIS__ + { + m_bIgnorePress=true; + + //CD - Added for audio + ui.PlayUISFX(eSFX_Press); + + ProfileManager.RefreshChatAndContentRestrictions(RefreshChatAndContentRestrictionsReturned_PlayGame, this); + } +#else + m_eAction=eAction_RunGame; + //CD - Added for audio + ui.PlayUISFX(eSFX_Press); + + signInReturnedFunc = &UIScene_MainMenu::CreateLoad_SignInReturned; +#endif + break; + case eControl_Leaderboards: + //CD - Added for audio + ui.PlayUISFX(eSFX_Press); +#ifdef __ORBIS__ + ProfileManager.RefreshChatAndContentRestrictions(RefreshChatAndContentRestrictionsReturned_Leaderboards, this); +#else + m_eAction=eAction_RunLeaderboards; + signInReturnedFunc = &UIScene_MainMenu::Leaderboards_SignInReturned; +#endif + break; + case eControl_Achievements: + //CD - Added for audio + ui.PlayUISFX(eSFX_Press); + + m_eAction=eAction_RunAchievements; + signInReturnedFunc = &UIScene_MainMenu::Achievements_SignInReturned; + break; + case eControl_HelpAndOptions: + //CD - Added for audio + ui.PlayUISFX(eSFX_Press); + + m_eAction=eAction_RunHelpAndOptions; + signInReturnedFunc = &UIScene_MainMenu::HelpAndOptions_SignInReturned; + break; + case eControl_UnlockOrDLC: + //CD - Added for audio + ui.PlayUISFX(eSFX_Press); + + m_eAction=eAction_RunUnlockOrDLC; + signInReturnedFunc = &UIScene_MainMenu::UnlockFullGame_SignInReturned; + break; +#if defined _XBOX + case eControl_Exit: + if( ProfileManager.IsFullVersion() ) + { + UINT uiIDA[2]; + uiIDA[0]=IDS_CANCEL; + uiIDA[1]=IDS_OK; + ui.RequestMessageBox(IDS_WARNING_ARCADE_TITLE, IDS_WARNING_ARCADE_TEXT, uiIDA, 2, XUSER_INDEX_ANY,&UIScene_MainMenu::ExitGameReturned,this); + } + else + { +#ifdef _XBOX_ONE + ui.ShowPlayerDisplayname(true); +#endif + ui.NavigateToScene(primaryPad,eUIScene_TrialExitUpsell); + } + break; +#endif + +#ifdef _DURANGO + case eControl_XboxHelp: + ui.PlayUISFX(eSFX_Press); + + m_eAction=eAction_RunXboxHelp; + signInReturnedFunc = &UIScene_MainMenu::XboxHelp_SignInReturned; + break; +#endif + + default: __debugbreak(); + } + + bool confirmUser = false; + + // Note: if no sign in returned func, assume this isn't required + if (signInReturnedFunc != NULL) + { + if(ProfileManager.IsSignedIn(primaryPad)) + { + if (confirmUser) + { + ProfileManager.RequestSignInUI(false, false, true, false, true, signInReturnedFunc, this, primaryPad); + } + else + { + RunAction(primaryPad); + } + } + else + { + // Ask user to sign in + UINT uiIDA[2]; + uiIDA[0]=IDS_CONFIRM_OK; + uiIDA[1]=IDS_CONFIRM_CANCEL; + ui.RequestMessageBox(IDS_MUST_SIGN_IN_TITLE, IDS_MUST_SIGN_IN_TEXT, uiIDA, 2, primaryPad, &UIScene_MainMenu::MustSignInReturned, this, app.GetStringTable()); + } + } +} + +// Run current action +void UIScene_MainMenu::RunAction(int iPad) +{ + switch(m_eAction) + { + case eAction_RunGame: + RunPlayGame(iPad); + break; + case eAction_RunLeaderboards: + RunLeaderboards(iPad); + break; + case eAction_RunAchievements: + RunAchievements(iPad); + break; + case eAction_RunHelpAndOptions: + RunHelpAndOptions(iPad); + break; + case eAction_RunUnlockOrDLC: + RunUnlockOrDLC(iPad); + break; +#ifdef _DURANGO + case eAction_RunXboxHelp: + // 4J: Launch the dummy xbox help application. + WXS::User^ user = ProfileManager.GetUser(ProfileManager.GetPrimaryPad()); + Windows::Xbox::ApplicationModel::Help::Show(user); + break; +#endif + } +} + +void UIScene_MainMenu::customDraw(IggyCustomDrawCallbackRegion *region) +{ + if(wcscmp((wchar_t *)region->name,L"Splash")==0) + { + PIXBeginNamedEvent(0,"Custom draw splash"); + customDrawSplash(region); + PIXEndNamedEvent(); + } +} + +void UIScene_MainMenu::customDrawSplash(IggyCustomDrawCallbackRegion *region) +{ + Minecraft *pMinecraft = Minecraft::GetInstance(); + + // 4J Stu - Move this to the ctor when the main menu is not the first scene we navigate to + ScreenSizeCalculator ssc(pMinecraft->options, pMinecraft->width_phys, pMinecraft->height_phys); + m_fScreenWidth=(float)pMinecraft->width_phys; + m_fRawWidth=(float)ssc.rawWidth; + m_fScreenHeight=(float)pMinecraft->height_phys; + m_fRawHeight=(float)ssc.rawHeight; + + + // Setup GDraw, normal game render states and matrices + CustomDrawData *customDrawRegion = ui.setupCustomDraw(this,region); + delete customDrawRegion; + + + Font *font = pMinecraft->font; + + // build and render with the game call + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + + glPushMatrix(); + + float width = region->x1 - region->x0; + float height = region->y1 - region->y0; + float xo = width/2; + float yo = height; + + glTranslatef(xo, yo, 0); + + glRotatef(-17, 0, 0, 1); + float sss = 1.8f - Mth::abs(Mth::sin(System::currentTimeMillis() % 1000 / 1000.0f * PI * 2) * 0.1f); + sss*=(m_fScreenWidth/m_fRawWidth); + + sss = sss * 100 / (font->width(m_splash) + 8 * 4); + glScalef(sss, sss, sss); + //drawCenteredString(font, splash, 0, -8, 0xffff00); + font->drawShadow(m_splash, 0 - (font->width(m_splash)) / 2, -8, 0xffff00); + glPopMatrix(); + + glDisable(GL_RESCALE_NORMAL); + + glEnable(GL_DEPTH_TEST); + + + // Finish GDraw and anything else that needs to be finalised + ui.endCustomDraw(region); +} + +int UIScene_MainMenu::MustSignInReturned(void *pParam, int iPad, C4JStorage::EMessageResult result) +{ + UIScene_MainMenu* pClass = (UIScene_MainMenu*)pParam; + + if(result==C4JStorage::EMessage_ResultAccept) + { + // we need to specify local game here to display local and LIVE profiles in the list + switch(pClass->m_eAction) + { + case eAction_RunGame: ProfileManager.RequestSignInUI(false, true, false, false, true, &UIScene_MainMenu::CreateLoad_SignInReturned, pClass, iPad ); break; + case eAction_RunHelpAndOptions: ProfileManager.RequestSignInUI(false, false, true, false, true, &UIScene_MainMenu::HelpAndOptions_SignInReturned, pClass, iPad ); break; + case eAction_RunLeaderboards: ProfileManager.RequestSignInUI(false, false, true, false, true, &UIScene_MainMenu::Leaderboards_SignInReturned, pClass, iPad ); break; + case eAction_RunAchievements: ProfileManager.RequestSignInUI(false, false, true, false, true, &UIScene_MainMenu::Achievements_SignInReturned, pClass, iPad ); break; + case eAction_RunUnlockOrDLC: ProfileManager.RequestSignInUI(false, false, true, false, true, &UIScene_MainMenu::UnlockFullGame_SignInReturned, pClass, iPad ); break; +#ifdef _DURANGO + case eAction_RunXboxHelp: ProfileManager.RequestSignInUI(false, false, true, false, true, &UIScene_MainMenu::XboxHelp_SignInReturned, pClass, iPad ); break; +#endif + } + } + else + { + pClass->m_bIgnorePress=false; + // unlock the profile + ProfileManager.SetLockedProfile(-1); + for(int i=0;i<XUSER_MAX_COUNT;i++) + { + // if the user is valid, we should set the presence + if(ProfileManager.IsSignedIn(i)) + { + ProfileManager.SetCurrentGameActivity(i, CONTEXT_PRESENCE_MENUS, false); + } + } + } + + return 0; +} + +#if defined(__PS3__) || defined(__PSVITA__) || defined(__ORBIS__) +int UIScene_MainMenu::MustSignInReturnedPSN(void *pParam,int iPad,C4JStorage::EMessageResult result) +{ + UIScene_MainMenu* pClass = (UIScene_MainMenu*)pParam; + + if(result==C4JStorage::EMessage_ResultAccept) + { +#ifdef __PS3__ + // we need to specify local game here to display local and LIVE profiles in the list + switch(pClass->m_eAction) + { + case eAction_RunLeaderboardsPSN: + SQRNetworkManager_PS3::AttemptPSNSignIn(&UIScene_MainMenu::Leaderboards_SignInReturned, pClass); + break; + case eAction_RunGamePSN: + SQRNetworkManager_PS3::AttemptPSNSignIn(&UIScene_MainMenu::CreateLoad_SignInReturned, pClass); + break; + case eAction_RunUnlockOrDLCPSN: + SQRNetworkManager_PS3::AttemptPSNSignIn(&UIScene_MainMenu::UnlockFullGame_SignInReturned, pClass); + break; + } +#elif defined __PSVITA__ + switch(pClass->m_eAction) + { + case eAction_RunLeaderboardsPSN: + //CD - Must force Ad-Hoc off if they want leaderboard PSN sign-in + //Save settings change + app.SetGameSettings(0, eGameSetting_PSVita_NetworkModeAdhoc, 0); + //Force off + CGameNetworkManager::setAdhocMode(false); + //Now Sign-in + SQRNetworkManager_Vita::AttemptPSNSignIn(&UIScene_MainMenu::Leaderboards_SignInReturned, pClass); + break; + case eAction_RunGamePSN: + SQRNetworkManager_Vita::AttemptPSNSignIn(&UIScene_MainMenu::CreateLoad_SignInReturned, pClass); + break; + case eAction_RunUnlockOrDLCPSN: + //CD - Must force Ad-Hoc off if they want commerce PSN sign-in + //Save settings change + app.SetGameSettings(0, eGameSetting_PSVita_NetworkModeAdhoc, 0); + //Force off + CGameNetworkManager::setAdhocMode(false); + //Now Sign-in + SQRNetworkManager_Vita::AttemptPSNSignIn(&UIScene_MainMenu::UnlockFullGame_SignInReturned, pClass); + break; + } +#else + switch(pClass->m_eAction) + { + case eAction_RunLeaderboardsPSN: + SQRNetworkManager_Orbis::AttemptPSNSignIn(&UIScene_MainMenu::Leaderboards_SignInReturned, pClass, true, iPad); + break; + case eAction_RunGamePSN: + SQRNetworkManager_Orbis::AttemptPSNSignIn(&UIScene_MainMenu::CreateLoad_SignInReturned, pClass, true, iPad); + break; + case eAction_RunUnlockOrDLCPSN: + SQRNetworkManager_Orbis::AttemptPSNSignIn(&UIScene_MainMenu::UnlockFullGame_SignInReturned, pClass, true, iPad); + break; + } + +#endif + } + else + { + if( pClass->m_eAction == eAction_RunGamePSN ) + { + if( result == C4JStorage::EMessage_Cancelled) + CreateLoad_SignInReturned(pClass, false, 0); + else + CreateLoad_SignInReturned(pClass, true, 0); + } + else + { + pClass->m_bIgnorePress=false; + } + } + + return 0; +} +#endif + +int UIScene_MainMenu::HelpAndOptions_SignInReturned(void *pParam,bool bContinue,int iPad) +{ + UIScene_MainMenu *pClass = (UIScene_MainMenu *)pParam; + + if(bContinue) + { + // 4J-JEV: Don't we only need to update rich-presence if the sign-in status changes. + ProfileManager.SetCurrentGameActivity(iPad, CONTEXT_PRESENCE_MENUS, false); + +#if TO_BE_IMPLEMENTED + if(app.GetTMSDLCInfoRead()) +#endif + { + ProfileManager.SetLockedProfile(ProfileManager.GetPrimaryPad()); +#ifdef _XBOX_ONE + ui.ShowPlayerDisplayname(true); +#endif + ui.NavigateToScene(iPad,eUIScene_HelpAndOptionsMenu); + } +#if TO_BE_IMPLEMENTED + else + { + // Changing to async TMS calls + app.SetTMSAction(iPad,eTMSAction_TMSPP_RetrieveFiles_HelpAndOptions); + + // block all input + pClass->m_bIgnorePress=true; + // We want to hide everything in this scene and display a timer until we get a completion for the TMS files + for(int i=0;i<BUTTONS_MAX;i++) + { + pClass->m_Buttons[i].SetShow(FALSE); + } + + pClass->updateTooltips(); + + pClass->m_Timer.SetShow(TRUE); + } +#endif + } + else + { + pClass->m_bIgnorePress=false; + // unlock the profile + ProfileManager.SetLockedProfile(-1); + for(int i=0;i<XUSER_MAX_COUNT;i++) + { + // if the user is valid, we should set the presence + if(ProfileManager.IsSignedIn(i)) + { + ProfileManager.SetCurrentGameActivity(i,CONTEXT_PRESENCE_MENUS,false); + } + } + } + + return 0; +} + +#ifdef _XBOX_ONE +int UIScene_MainMenu::ChooseUser_SignInReturned(void *pParam, bool bContinue, int iPad) +{ + UIScene_MainMenu* pClass = (UIScene_MainMenu*)pParam; + pClass->m_bIgnorePress = false; + + return 0; +} +#endif + +int UIScene_MainMenu::CreateLoad_SignInReturned(void *pParam, bool bContinue, int iPad) +{ + UIScene_MainMenu* pClass = (UIScene_MainMenu*)pParam; + + if(bContinue) + { + // 4J-JEV: We only need to update rich-presence if the sign-in status changes. + ProfileManager.SetCurrentGameActivity(iPad, CONTEXT_PRESENCE_MENUS, false); + + UINT uiIDA[1] = { IDS_OK }; + + if(ProfileManager.IsGuest(ProfileManager.GetPrimaryPad())) + { + pClass->m_bIgnorePress=false; + ui.RequestMessageBox(IDS_PRO_GUESTPROFILE_TITLE, IDS_PRO_GUESTPROFILE_TEXT, uiIDA, 1); + } + else + { + ProfileManager.SetLockedProfile(ProfileManager.GetPrimaryPad()); + + + // change the minecraft player name + Minecraft::GetInstance()->user->name = convStringToWstring( ProfileManager.GetGamertag(ProfileManager.GetPrimaryPad())); + + if(ProfileManager.IsFullVersion()) + { + bool bSignedInLive = ProfileManager.IsSignedInLive(iPad); +#ifdef __PSVITA__ + if(CGameNetworkManager::usingAdhocMode()) + { + if(SQRNetworkManager_AdHoc_Vita::GetAdhocStatus()) + { + bSignedInLive = true; + } + else + { + // adhoc mode, but we didn't make the connection, turn off adhoc mode, and just go with whatever the regular online status is + CGameNetworkManager::setAdhocMode(false); + bSignedInLive = ProfileManager.IsSignedInLive(iPad); + } + } +#endif + + // Check if we're signed in to LIVE + if(bSignedInLive) + { + // 4J-PB - Need to check for installed DLC + if(!app.DLCInstallProcessCompleted()) app.StartInstallDLCProcess(iPad); + + if(ProfileManager.IsGuest(iPad)) + { + pClass->m_bIgnorePress=false; + ui.RequestMessageBox(IDS_PRO_GUESTPROFILE_TITLE, IDS_PRO_GUESTPROFILE_TEXT, uiIDA, 1); + } + else + { + // 4J Stu - Not relevant to PS3 +#ifdef _XBOX_ONE +// if(app.GetTMSDLCInfoRead() && app.GetBanListRead(iPad)) + if(app.GetBanListRead(iPad)) + { + Minecraft *pMinecraft=Minecraft::GetInstance(); + pMinecraft->user->name = convStringToWstring( ProfileManager.GetGamertag(ProfileManager.GetPrimaryPad())); + + // ensure we've applied this player's settings + app.ApplyGameSettingsChanged(iPad); + +#ifdef _XBOX_ONE + ui.ShowPlayerDisplayname(true); +#endif + ui.NavigateToScene(ProfileManager.GetPrimaryPad(), eUIScene_LoadOrJoinMenu); + } + else + { + app.SetTMSAction(iPad,eTMSAction_TMSPP_RetrieveFiles_RunPlayGame); + + // block all input + pClass->m_bIgnorePress=true; + // We want to hide everything in this scene and display a timer until we get a completion for the TMS files + // for(int i=0;i<eControl_Count;i++) + // { + // m_buttons[i].set(false); + // } + + pClass->updateTooltips(); + + pClass->m_controlTimer.setVisible( true ); + } +#endif +#if TO_BE_IMPLEMENTED + // check if all the TMS files are loaded + if(app.GetTMSDLCInfoRead() && app.GetTMSXUIDsFileRead() && app.GetBanListRead(iPad)) + { + if(StorageManager.SetSaveDevice(&UIScene_MainMenu::DeviceSelectReturned,pClass)==true) + { + // save device already selected + + // ensure we've applied this player's settings + app.ApplyGameSettingsChanged(ProfileManager.GetPrimaryPad()); + // check for DLC + // start timer to track DLC check finished + pClass->m_Timer.SetShow(TRUE); + XuiSetTimer(pClass->m_hObj,DLC_INSTALLED_TIMER_ID,DLC_INSTALLED_TIMER_TIME); + //app.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_MultiGameJoinLoad); + } + } + else + { + // Changing to async TMS calls + app.SetTMSAction(iPad,eTMSAction_TMSPP_RetrieveFiles_RunPlayGame); + + // block all input + pClass->m_bIgnorePress=true; + // We want to hide everything in this scene and display a timer until we get a completion for the TMS files + for(int i=0;i<BUTTONS_MAX;i++) + { + pClass->m_Buttons[i].SetShow(FALSE); + } + + updateTooltips(); + + pClass->m_Timer.SetShow(TRUE); + } +#else + Minecraft *pMinecraft=Minecraft::GetInstance(); + pMinecraft->user->name = convStringToWstring( ProfileManager.GetGamertag(ProfileManager.GetPrimaryPad())); + + // ensure we've applied this player's settings + app.ApplyGameSettingsChanged(iPad); + +#ifdef _XBOX_ONE + ui.ShowPlayerDisplayname(true); +#endif + ui.NavigateToScene(ProfileManager.GetPrimaryPad(), eUIScene_LoadOrJoinMenu); +#endif + } + } + else + { +#if TO_BE_IMPLEMENTED + // offline + ProfileManager.DisplayOfflineProfile(&CScene_Main::CreateLoad_OfflineProfileReturned,pClass, ProfileManager.GetPrimaryPad() ); +#else + app.DebugPrintf("Offline Profile returned not implemented\n"); +#ifdef _XBOX_ONE + ui.ShowPlayerDisplayname(true); +#endif + ui.NavigateToScene(ProfileManager.GetPrimaryPad(), eUIScene_LoadOrJoinMenu); +#endif + } + } + else + { + // 4J-PB - if this is the trial game, we can't have any networking + // Can't apply the player's settings here - they haven't come back from the QuerySignInStatud call above yet. + // Need to let them action in the main loop when they come in + // ensure we've applied this player's settings + //app.ApplyGameSettingsChanged(iPad); + +#if defined(__PS3__) || defined(__ORBIS__) || defined( __PSVITA__) + // ensure we've applied this player's settings - we do have them on PS3 + app.ApplyGameSettingsChanged(iPad); +#endif + +#ifdef __ORBIS__ + if(!g_NetworkManager.IsReadyToPlayOrIdle()) + { + pClass->m_bLoadTrialOnNetworkManagerReady = true; + ui.NavigateToScene(iPad, eUIScene_Timer); + } + else +#endif + { + // go straight in to the trial level + LoadTrial(); + } + } + } + } + else + { + pClass->m_bIgnorePress=false; + + // unlock the profile + ProfileManager.SetLockedProfile(-1); + for(int i=0;i<XUSER_MAX_COUNT;i++) + { + // if the user is valid, we should set the presence + if(ProfileManager.IsSignedIn(i)) + { + ProfileManager.SetCurrentGameActivity(i,CONTEXT_PRESENCE_MENUS,false); + } + } + + } + return 0; +} + +int UIScene_MainMenu::Leaderboards_SignInReturned(void *pParam,bool bContinue,int iPad) +{ + UIScene_MainMenu *pClass = (UIScene_MainMenu *)pParam; + + if(bContinue) + { + // 4J-JEV: We only need to update rich-presence if the sign-in status changes. + ProfileManager.SetCurrentGameActivity(iPad, CONTEXT_PRESENCE_MENUS, false); + + UINT uiIDA[1] = { IDS_OK }; + + // guests can't look at leaderboards + if(ProfileManager.IsGuest(ProfileManager.GetPrimaryPad())) + { + pClass->m_bIgnorePress=false; + ui.RequestMessageBox(IDS_PRO_GUESTPROFILE_TITLE, IDS_PRO_GUESTPROFILE_TEXT, uiIDA, 1); + } + else if(!ProfileManager.IsSignedInLive(ProfileManager.GetPrimaryPad())) + { + pClass->m_bIgnorePress=false; + ui.RequestMessageBox(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_XBOXLIVE_NOTIFICATION, uiIDA, 1); + } + else + { + bool bContentRestricted=false; +#if defined(__PS3__) || defined(__PSVITA__) + ProfileManager.GetChatAndContentRestrictions(iPad,true,NULL,&bContentRestricted,NULL); +#endif + if(bContentRestricted) + { + pClass->m_bIgnorePress=false; +#if !(defined(_XBOX) || defined(_WIN64)) // 4J Stu - Temp to get the win build running, but so we check this for other platforms + // you can't see leaderboards + UINT uiIDA[1]; + uiIDA[0]=IDS_CONFIRM_OK; + ui.RequestMessageBox(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, ProfileManager.GetPrimaryPad(),NULL,NULL, app.GetStringTable()); +#endif + } + else + { + ProfileManager.SetLockedProfile(ProfileManager.GetPrimaryPad()); +#ifdef _XBOX_ONE + ui.ShowPlayerDisplayname(true); +#endif + ui.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_LeaderboardsMenu); + } + } + } + else + { + pClass->m_bIgnorePress=false; + // unlock the profile + ProfileManager.SetLockedProfile(-1); + for(int i=0;i<XUSER_MAX_COUNT;i++) + { + // if the user is valid, we should set the presence + if(ProfileManager.IsSignedIn(i)) + { + ProfileManager.SetCurrentGameActivity(i,CONTEXT_PRESENCE_MENUS,false); + } + } + + } + return 0; +} + +int UIScene_MainMenu::Achievements_SignInReturned(void *pParam,bool bContinue,int iPad) +{ + UIScene_MainMenu *pClass = (UIScene_MainMenu *)pParam; + + if (bContinue) + { + pClass->m_bIgnorePress=false; + // 4J-JEV: We only need to update rich-presence if the sign-in status changes. + ProfileManager.SetCurrentGameActivity(iPad, CONTEXT_PRESENCE_MENUS, false); + + XShowAchievementsUI( ProfileManager.GetPrimaryPad() ); + } + else + { + pClass->m_bIgnorePress=false; + // unlock the profile + ProfileManager.SetLockedProfile(-1); + for(int i=0;i<XUSER_MAX_COUNT;i++) + { + // if the user is valid, we should set the presence + if(ProfileManager.IsSignedIn(i)) + { + ProfileManager.SetCurrentGameActivity(i,CONTEXT_PRESENCE_MENUS,false); + } + } + + } + return 0; +} + +int UIScene_MainMenu::UnlockFullGame_SignInReturned(void *pParam,bool bContinue,int iPad) +{ + UIScene_MainMenu* pClass = (UIScene_MainMenu*)pParam; + + if (bContinue) + { + // 4J-JEV: We only need to update rich-presence if the sign-in status changes. + ProfileManager.SetCurrentGameActivity(iPad, CONTEXT_PRESENCE_MENUS, false); + + pClass->RunUnlockOrDLC(iPad); + } + else + { + pClass->m_bIgnorePress=false; + // unlock the profile + ProfileManager.SetLockedProfile(-1); + for(int i=0;i<XUSER_MAX_COUNT;i++) + { + // if the user is valid, we should set the presence + if(ProfileManager.IsSignedIn(i)) + { + ProfileManager.SetCurrentGameActivity(i,CONTEXT_PRESENCE_MENUS,false); + } + } + + } + + return 0; +} + +#ifdef _DURANGO +int UIScene_MainMenu::XboxHelp_SignInReturned(void *pParam, bool bContinue, int iPad) +{ + UIScene_MainMenu* pClass = (UIScene_MainMenu*)pParam; + + if (bContinue) + { + // 4J: Launch the dummy xbox help application. + WXS::User^ user = ProfileManager.GetUser(ProfileManager.GetPrimaryPad()); + Windows::Xbox::ApplicationModel::Help::Show(user); + } + else + { + // unlock the profile + ProfileManager.SetLockedProfile(-1); + for(int i=0;i<XUSER_MAX_COUNT;i++) + { + // if the user is valid, we should set the presence + if(ProfileManager.IsSignedIn(i)) + { + ProfileManager.SetCurrentGameActivity(i,CONTEXT_PRESENCE_MENUS,false); + } + } + } + + return 0; +} +#endif + +int UIScene_MainMenu::ExitGameReturned(void *pParam,int iPad,C4JStorage::EMessageResult result) +{ + //UIScene_MainMenu* pClass = (UIScene_MainMenu*)pParam; + + // buttons reversed on this + if(result==C4JStorage::EMessage_ResultDecline) + { + //XLaunchNewImage(XLAUNCH_KEYWORD_DASH_ARCADE, 0); + app.ExitGame(); + } + + return 0; +} + +#ifdef __ORBIS__ +void UIScene_MainMenu::RefreshChatAndContentRestrictionsReturned_PlayGame(void *pParam) +{ + int primaryPad = ProfileManager.GetPrimaryPad(); + + UIScene_MainMenu* pClass = (UIScene_MainMenu*)pParam; + + int (*signInReturnedFunc) (LPVOID,const bool, const int iPad) = NULL; + + // 4J-PB - Check if there is a patch for the game + pClass->m_errorCode = ProfileManager.getNPAvailability(ProfileManager.GetPrimaryPad()); + + bool bPatchAvailable; + switch(pClass->m_errorCode) + { + case SCE_NP_ERROR_LATEST_PATCH_PKG_EXIST: + case SCE_NP_ERROR_LATEST_PATCH_PKG_DOWNLOADED: + bPatchAvailable=true; + break; + default: + bPatchAvailable=false; + break; + } + + if(!bPatchAvailable) + { + pClass->m_eAction=eAction_RunGame; + signInReturnedFunc = &UIScene_MainMenu::CreateLoad_SignInReturned; + } + else + { + pClass->m_bRunGameChosen=true; + pClass->m_bErrorDialogRunning=true; + int32_t ret=sceErrorDialogInitialize(); + if ( ret==SCE_OK ) + { + SceErrorDialogParam param; + sceErrorDialogParamInitialize( ¶m ); + // 4J-PB - We want to display the option to get the patch now + param.errorCode = SCE_NP_ERROR_LATEST_PATCH_PKG_DOWNLOADED;//pClass->m_errorCode; + ret = sceUserServiceGetInitialUser( ¶m.userId ); + if ( ret == SCE_OK ) + { + ret=sceErrorDialogOpen( ¶m ); + } + return; + } + +// UINT uiIDA[1]; +// uiIDA[0]=IDS_OK; +// ui.RequestMessageBox(IDS_PATCH_AVAILABLE_TITLE, IDS_PATCH_AVAILABLE_TEXT, uiIDA, 1, XUSER_INDEX_ANY,NULL,pClass); + } + + // Check if PSN is unavailable because of age restriction + if (pClass->m_errorCode == SCE_NP_ERROR_AGE_RESTRICTION) + { + UINT uiIDA[1]; + uiIDA[0]=IDS_PRO_NOTONLINE_DECLINE; + ui.RequestMessageBox(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, ProfileManager.GetPrimaryPad(), &UIScene_MainMenu::PlayOfflineReturned, pClass, app.GetStringTable()); + + return; + } + + bool confirmUser = false; + + // Note: if no sign in returned func, assume this isn't required + if (signInReturnedFunc != NULL) + { + if(ProfileManager.IsSignedIn(primaryPad)) + { + if (confirmUser) + { + ProfileManager.RequestSignInUI(false, false, true, false, true, signInReturnedFunc, pClass, primaryPad); + } + else + { + pClass->RunAction(primaryPad); + } + } + else + { + // Ask user to sign in + UINT uiIDA[2]; + uiIDA[0]=IDS_CONFIRM_OK; + uiIDA[1]=IDS_CONFIRM_CANCEL; + ui.RequestMessageBox(IDS_MUST_SIGN_IN_TITLE, IDS_MUST_SIGN_IN_TEXT, uiIDA, 2, primaryPad, &UIScene_MainMenu::MustSignInReturned, pClass, app.GetStringTable()); + } + } +} + +void UIScene_MainMenu::RefreshChatAndContentRestrictionsReturned_Leaderboards(void *pParam) +{ + int primaryPad = ProfileManager.GetPrimaryPad(); + + UIScene_MainMenu* pClass = (UIScene_MainMenu*)pParam; + + int (*signInReturnedFunc) (LPVOID,const bool, const int iPad) = NULL; + + // 4J-PB - Check if there is a patch for the game + pClass->m_errorCode = ProfileManager.getNPAvailability(ProfileManager.GetPrimaryPad()); + + bool bPatchAvailable; + switch(pClass->m_errorCode) + { + case SCE_NP_ERROR_LATEST_PATCH_PKG_EXIST: + case SCE_NP_ERROR_LATEST_PATCH_PKG_DOWNLOADED: + bPatchAvailable=true; + break; + default: + bPatchAvailable=false; + break; + } + + if(!bPatchAvailable) + { + pClass->m_eAction=eAction_RunLeaderboards; + signInReturnedFunc = &UIScene_MainMenu::Leaderboards_SignInReturned; + } + else + { + int32_t ret=sceErrorDialogInitialize(); + pClass->m_bErrorDialogRunning=true; + if ( ret==SCE_OK ) + { + SceErrorDialogParam param; + sceErrorDialogParamInitialize( ¶m ); + // 4J-PB - We want to display the option to get the patch now + param.errorCode = SCE_NP_ERROR_LATEST_PATCH_PKG_DOWNLOADED;//pClass->m_errorCode; + ret = sceUserServiceGetInitialUser( ¶m.userId ); + if ( ret == SCE_OK ) + { + ret=sceErrorDialogOpen( ¶m ); + } + } + +// UINT uiIDA[1]; +// uiIDA[0]=IDS_OK; +// ui.RequestMessageBox(IDS_PATCH_AVAILABLE_TITLE, IDS_PATCH_AVAILABLE_TEXT, uiIDA, 1, XUSER_INDEX_ANY,NULL,pClass); + } + + bool confirmUser = false; + + // Update error code + pClass->m_errorCode = ProfileManager.getNPAvailability(ProfileManager.GetPrimaryPad()); + + // Check if PSN is unavailable because of age restriction + if (pClass->m_errorCode == SCE_NP_ERROR_AGE_RESTRICTION) + { + UINT uiIDA[1]; + uiIDA[0] = IDS_CONFIRM_OK; + ui.RequestMessageBox(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, ProfileManager.GetPrimaryPad(), nullptr, pClass, app.GetStringTable()); + + return; + } + + // Note: if no sign in returned func, assume this isn't required + if (signInReturnedFunc != NULL) + { + if(ProfileManager.IsSignedIn(primaryPad)) + { + if (confirmUser) + { + ProfileManager.RequestSignInUI(false, false, true, false, true, signInReturnedFunc, pClass, primaryPad); + } + else + { + pClass->RunAction(primaryPad); + } + } + else + { + // Ask user to sign in + UINT uiIDA[2]; + uiIDA[0]=IDS_CONFIRM_OK; + uiIDA[1]=IDS_CONFIRM_CANCEL; + ui.RequestMessageBox(IDS_MUST_SIGN_IN_TITLE, IDS_MUST_SIGN_IN_TEXT, uiIDA, 2, primaryPad, &UIScene_MainMenu::MustSignInReturned, pClass, app.GetStringTable()); + } + } +} + +int UIScene_MainMenu::PlayOfflineReturned(void *pParam, int iPad, C4JStorage::EMessageResult result) +{ + UIScene_MainMenu* pClass = (UIScene_MainMenu*)pParam; + + if(result==C4JStorage::EMessage_ResultAccept) + { + if (pClass->m_eAction == eAction_RunGame) + { + CreateLoad_SignInReturned(pClass, true, 0); + } + else + { + pClass->m_bIgnorePress=false; + } + } + else + { + pClass->m_bIgnorePress=false; + } + + return 0; +} +#endif + +void UIScene_MainMenu::RunPlayGame(int iPad) +{ + Minecraft *pMinecraft=Minecraft::GetInstance(); + + // clear the remembered signed in users so their profiles get read again + app.ClearSignInChangeUsersMask(); + + app.ReleaseSaveThumbnail(); + + if(ProfileManager.IsGuest(iPad)) + { + UINT uiIDA[1]; + uiIDA[0]=IDS_OK; + + m_bIgnorePress=false; + ui.RequestMessageBox(IDS_PRO_GUESTPROFILE_TITLE, IDS_PRO_GUESTPROFILE_TEXT, uiIDA, 1); + } + else + { + ProfileManager.SetLockedProfile(iPad); + + // If the player was signed in before selecting play, we'll not have read the profile yet, so query the sign-in status to get this to happen + ProfileManager.QuerySigninStatus(); + + // 4J-PB - Need to check for installed DLC + if(!app.DLCInstallProcessCompleted()) app.StartInstallDLCProcess(iPad); + + if(ProfileManager.IsFullVersion()) + { + // are we offline? + bool bSignedInLive = ProfileManager.IsSignedInLive(iPad); +#ifdef __PSVITA__ + if(app.GetGameSettings(ProfileManager.GetPrimaryPad(),eGameSetting_PSVita_NetworkModeAdhoc) == true) + { + CGameNetworkManager::setAdhocMode(true); + bSignedInLive = SQRNetworkManager_AdHoc_Vita::GetAdhocStatus(); + app.DebugPrintf("Adhoc mode signed in : %s\n", bSignedInLive ? "true" : "false"); + } + else + { + CGameNetworkManager::setAdhocMode(false); + app.DebugPrintf("PSN mode signed in : %s\n", bSignedInLive ? "true" : "false"); + } + +#endif //__PSVITA__ + + if(!bSignedInLive) + { +#if defined(__PS3__) || defined __PSVITA__ + // enable input again + m_bIgnorePress=false; + + // Not sure why 360 doesn't need this, but leaving as __PS3__ only for now until we see that it does. Without this, on a PS3 offline game, the primary player just gets the default Player1234 type name + pMinecraft->user->name = convStringToWstring( ProfileManager.GetGamertag(ProfileManager.GetPrimaryPad())); + + m_eAction=eAction_RunGamePSN; + // get them to sign in to online + UINT uiIDA[2]; + uiIDA[0]=IDS_PRO_NOTONLINE_ACCEPT; + uiIDA[1]=IDS_PRO_NOTONLINE_DECLINE; + +#ifdef __PSVITA__ + if(CGameNetworkManager::usingAdhocMode()) + { + uiIDA[0]=IDS_NETWORK_ADHOC; + // this should be "Connect to adhoc network" + ui.RequestMessageBox(IDS_PRO_NOTADHOCONLINE_TITLE, IDS_PRO_NOTADHOCONLINE_TEXT, uiIDA, 2, ProfileManager.GetPrimaryPad(),&UIScene_MainMenu::MustSignInReturnedPSN,this, app.GetStringTable()); + } + else + { + /* 4J-PB - Add this after release + // Determine why they're not "signed in live" + if (ProfileManager.IsSignedInPSN(iPad)) + { + m_eAction=eAction_RunGame; + // Signed in to PSN but not connected (no internet access) + + UINT uiIDA[1]; + uiIDA[0] = IDS_PRO_NOTONLINE_DECLINE; + ui.RequestMessageBox( IDS_ERROR_NETWORK_TITLE, IDS_ERROR_NETWORK, uiIDA, 1, iPad, UIScene_MainMenu::PlayOfflineReturned, this, app.GetStringTable()); + } + else + { + m_eAction=eAction_RunGamePSN; + // Not signed in to PSN + ui.RequestMessageBox( IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 2, iPad, &UIScene_MainMenu::MustSignInReturnedPSN, this, app.GetStringTable()); + return; + } */ + ui.RequestMessageBox(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 2, ProfileManager.GetPrimaryPad(),&UIScene_MainMenu::MustSignInReturnedPSN,this, app.GetStringTable()); + + } +#else + + ui.RequestMessageBox(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 2, iPad, &UIScene_MainMenu::MustSignInReturnedPSN, this, app.GetStringTable()); +#endif + +#elif defined __ORBIS__ + + // Determine why they're not "signed in live" + if (ProfileManager.isSignedInPSN(iPad)) + { + m_eAction=eAction_RunGame; + // Signed in to PSN but not connected (no internet access) + assert(!ProfileManager.isConnectedToPSN(iPad)); + + UINT uiIDA[1]; + uiIDA[0] = IDS_PRO_NOTONLINE_DECLINE; + ui.RequestMessageBox( IDS_ERROR_NETWORK_TITLE, IDS_ERROR_NETWORK, uiIDA, 1, iPad, UIScene_MainMenu::PlayOfflineReturned, this, app.GetStringTable()); + } + else + { + m_eAction=eAction_RunGamePSN; + // Not signed in to PSN + UINT uiIDA[2]; + uiIDA[0] = IDS_PRO_NOTONLINE_ACCEPT; + uiIDA[1] = IDS_PRO_NOTONLINE_DECLINE; + ui.RequestMessageBox( IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 2, iPad, &UIScene_MainMenu::MustSignInReturnedPSN, this, app.GetStringTable(), NULL, 0, false); + return; + } +#else + ProfileManager.SetLockedProfile(iPad); +#ifdef _XBOX_ONE + ui.ShowPlayerDisplayname(true); +#endif + ui.NavigateToScene(ProfileManager.GetPrimaryPad(), eUIScene_LoadOrJoinMenu); +#endif + } + else + { +#ifdef _XBOX_ONE + if(!app.GetBanListRead(iPad)) + { + app.SetTMSAction(iPad,eTMSAction_TMSPP_RetrieveFiles_RunPlayGame); + + // block all input + m_bIgnorePress=true; + // We want to hide everything in this scene and display a timer until we get a completion for the TMS files +// for(int i=0;i<eControl_Count;i++) +// { +// m_buttons[i].set(false); +// } + + updateTooltips(); + + m_controlTimer.setVisible( true ); + } +#endif +#if TO_BE_IMPLEMENTED + // Check if there is any new DLC + app.ClearNewDLCAvailable(); + StorageManager.GetAvailableDLCCount(iPad); + + // check if all the TMS files are loaded + if(app.GetTMSDLCInfoRead() && app.GetTMSXUIDsFileRead() && app.GetBanListRead(iPad)) + { + if(StorageManager.SetSaveDevice(&CScene_Main::DeviceSelectReturned,this)==true) + { + // change the minecraft player name + pMinecraft->user->name = convStringToWstring( ProfileManager.GetGamertag(ProfileManager.GetPrimaryPad())); + // save device already selected + + // ensure we've applied this player's settings + app.ApplyGameSettingsChanged(iPad); + // check for DLC + // start timer to track DLC check finished + m_Timer.SetShow(TRUE); + XuiSetTimer(m_hObj,DLC_INSTALLED_TIMER_ID,DLC_INSTALLED_TIMER_TIME); + //app.NavigateToScene(iPad,eUIScene_MultiGameJoinLoad); + } + } + else + { + // Changing to async TMS calls + app.SetTMSAction(iPad,eTMSAction_TMSPP_RetrieveFiles_RunPlayGame); + + // block all input + m_bIgnorePress=true; + // We want to hide everything in this scene and display a timer until we get a completion for the TMS files + for(int i=0;i<BUTTONS_MAX;i++) + { + m_Buttons[i].SetShow(FALSE); + } + + updateTooltips(); + + m_Timer.SetShow(TRUE); + } +#else + pMinecraft->user->name = convStringToWstring( ProfileManager.GetGamertag(ProfileManager.GetPrimaryPad())); + + // ensure we've applied this player's settings + app.ApplyGameSettingsChanged(iPad); + +#ifdef _XBOX_ONE + ui.ShowPlayerDisplayname(true); +#endif + ui.NavigateToScene(ProfileManager.GetPrimaryPad(), eUIScene_LoadOrJoinMenu); +#endif + } + } + else + { + // 4J-PB - if this is the trial game, we can't have any networking + // go straight in to the trial level + // change the minecraft player name + Minecraft::GetInstance()->user->name = convStringToWstring( ProfileManager.GetGamertag(ProfileManager.GetPrimaryPad())); + + // Can't apply the player's settings here - they haven't come back from the QuerySignInStatud call above yet. + // Need to let them action in the main loop when they come in + // ensure we've applied this player's settings + //app.ApplyGameSettingsChanged(iPad); + +#if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__) + // ensure we've applied this player's settings - we do have them on PS3 + app.ApplyGameSettingsChanged(iPad); +#endif + +#ifdef __ORBIS__ + if(!g_NetworkManager.IsReadyToPlayOrIdle()) + { + m_bLoadTrialOnNetworkManagerReady = true; + ui.NavigateToScene(iPad, eUIScene_Timer); + } + else +#endif + { + LoadTrial(); + } + } + } +} + +void UIScene_MainMenu::RunLeaderboards(int iPad) +{ + UINT uiIDA[1]; + uiIDA[0]=IDS_OK; + + // guests can't look at leaderboards + if(ProfileManager.IsGuest(iPad)) + { + ui.RequestMessageBox(IDS_PRO_GUESTPROFILE_TITLE, IDS_PRO_GUESTPROFILE_TEXT, uiIDA, 1); + } + else if(!ProfileManager.IsSignedInLive(iPad)) + { +#if defined __PS3__ || defined __PSVITA__ + m_eAction=eAction_RunLeaderboardsPSN; + // get them to sign in to online + UINT uiIDA[1]; + uiIDA[0]=IDS_PRO_NOTONLINE_ACCEPT; + ui.RequestMessageBox(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 1, ProfileManager.GetPrimaryPad(),&UIScene_MainMenu::MustSignInReturnedPSN,this, app.GetStringTable()); + +/* 4J-PB - Add this after release +#elif defined __PSVITA__ + m_eAction=eAction_RunLeaderboardsPSN; + // Determine why they're not "signed in live" + if (ProfileManager.IsSignedInPSN(iPad)) + { + // Signed in to PSN but not connected (no internet access) + UINT uiIDA[1]; + uiIDA[0] = IDS_PRO_NOTONLINE_ACCEPT; + ui.RequestMessageBox(IDS_PRO_CURRENTLY_NOT_ONLINE_TITLE, IDS_PRO_PSNOFFLINE_TEXT, uiIDA, 1, ProfileManager.GetPrimaryPad(), &UIScene_MainMenu::MustSignInReturnedPSN, this, app.GetStringTable()); + } + else + { + // Not signed in to PSN + UINT uiIDA[1]; + uiIDA[0] = IDS_PRO_NOTONLINE_ACCEPT; + ui.RequestMessageBox(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 1, ProfileManager.GetPrimaryPad(), &UIScene_MainMenu::MustSignInReturnedPSN, this, app.GetStringTable()); + return; + }*/ +#elif defined __ORBIS__ + m_eAction=eAction_RunLeaderboardsPSN; + // Determine why they're not "signed in live" + if (ProfileManager.isSignedInPSN(iPad)) + { + // Signed in to PSN but not connected (no internet access) + assert(!ProfileManager.isConnectedToPSN(iPad)); + + UINT uiIDA[1]; + uiIDA[0] = IDS_OK; + ui.RequestMessageBox( IDS_ERROR_NETWORK_TITLE, IDS_ERROR_NETWORK, uiIDA, 1, iPad, NULL, NULL, app.GetStringTable()); + } + else + { + // Not signed in to PSN + UINT uiIDA[1]; + uiIDA[0] = IDS_PRO_NOTONLINE_ACCEPT; + ui.RequestMessageBox(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 1, ProfileManager.GetPrimaryPad(), &UIScene_MainMenu::MustSignInReturnedPSN, this, app.GetStringTable()); + return; + } +#else + ui.RequestMessageBox(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_XBOXLIVE_NOTIFICATION, uiIDA, 1); +#endif + } + else + { + // we're supposed to check for parental control restrictions before showing leaderboards + // The title enforces the user's NP parental control setting for age-based content + //restriction in network communications. + // If age restrictions are in place and the user's age does not meet + // the age restriction of the title's online service content rating (CERO, ESRB, PEGI, etc.), then the title must + //display a message such as the following and disallow online service for this user. + + bool bContentRestricted=false; +#if defined(__PS3__) || defined(__PSVITA__) + ProfileManager.GetChatAndContentRestrictions(iPad,true,NULL,&bContentRestricted,NULL); +#endif + if(bContentRestricted) + { +#if !(defined(_XBOX) || defined(_WIN64)) // 4J Stu - Temp to get the win build running, but so we check this for other platforms + // you can't see leaderboards + UINT uiIDA[1]; + uiIDA[0]=IDS_CONFIRM_OK; + ui.RequestMessageBox(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, ProfileManager.GetPrimaryPad(),NULL,this, app.GetStringTable()); +#endif + } + else + { + ProfileManager.SetLockedProfile(iPad); + // If the player was signed in before selecting play, we'll not have read the profile yet, so query the sign-in status to get this to happen + ProfileManager.QuerySigninStatus(); + +#ifdef _XBOX_ONE + ui.ShowPlayerDisplayname(true); +#endif + ui.NavigateToScene(iPad, eUIScene_LeaderboardsMenu); + } + } +} +void UIScene_MainMenu::RunUnlockOrDLC(int iPad) +{ + UINT uiIDA[1]; + uiIDA[0]=IDS_OK; + + // Check if this means downloadable content + if(ProfileManager.IsFullVersion()) + { +#ifdef __ORBIS__ + // 4J-PB - Check if there is a patch for the game + m_errorCode = ProfileManager.getNPAvailability(ProfileManager.GetPrimaryPad()); + + bool bPatchAvailable; + switch(m_errorCode) + { + case SCE_NP_ERROR_LATEST_PATCH_PKG_EXIST: + case SCE_NP_ERROR_LATEST_PATCH_PKG_DOWNLOADED: + bPatchAvailable=true; + break; + default: + bPatchAvailable=false; + break; + } + + if(bPatchAvailable) + { + m_bIgnorePress=false; + + int32_t ret=sceErrorDialogInitialize(); + m_bErrorDialogRunning=true; + if ( ret==SCE_OK ) + { + SceErrorDialogParam param; + sceErrorDialogParamInitialize( ¶m ); + // 4J-PB - We want to display the option to get the patch now + param.errorCode = SCE_NP_ERROR_LATEST_PATCH_PKG_DOWNLOADED;//pClass->m_errorCode; + ret = sceUserServiceGetInitialUser( ¶m.userId ); + if ( ret == SCE_OK ) + { + ret=sceErrorDialogOpen( ¶m ); + } + } + +// UINT uiIDA[1]; +// uiIDA[0]=IDS_OK; +// ui.RequestMessageBox(IDS_PATCH_AVAILABLE_TITLE, IDS_PATCH_AVAILABLE_TEXT, uiIDA, 1, XUSER_INDEX_ANY,NULL,this); + return; + } + + // Check if PSN is unavailable because of age restriction + if (m_errorCode == SCE_NP_ERROR_AGE_RESTRICTION) + { + m_bIgnorePress=false; + UINT uiIDA[1]; + uiIDA[0] = IDS_OK; + ui.RequestMessageBox(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, ProfileManager.GetPrimaryPad(), nullptr, this, app.GetStringTable()); + + return; + } +#endif + // downloadable content + if(ProfileManager.IsSignedInLive(iPad)) + { + if(ProfileManager.IsGuest(iPad)) + { + m_bIgnorePress=false; + ui.RequestMessageBox(IDS_PRO_GUESTPROFILE_TITLE, IDS_PRO_GUESTPROFILE_TEXT, uiIDA, 1); + } + else + { + + // If the player was signed in before selecting play, we'll not have read the profile yet, so query the sign-in status to get this to happen + ProfileManager.QuerySigninStatus(); + +#if defined _XBOX_ONE + if(app.GetTMSDLCInfoRead()) +#endif + { + bool bContentRestricted=false; +#if defined(__PS3__) || defined(__PSVITA__) + ProfileManager.GetChatAndContentRestrictions(iPad,true,NULL,&bContentRestricted,NULL); +#endif + if(bContentRestricted) + { + m_bIgnorePress=false; +#if !(defined(_XBOX) || defined(_WIN64)) // 4J Stu - Temp to get the win build running, but so we check this for other platforms + // you can't see the store + UINT uiIDA[1]; + uiIDA[0]=IDS_CONFIRM_OK; + ui.RequestMessageBox(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, ProfileManager.GetPrimaryPad(),NULL,this, app.GetStringTable()); +#endif + } + else + { + ProfileManager.SetLockedProfile(iPad); +#ifdef _XBOX_ONE + ui.ShowPlayerDisplayname(true); +#endif + ui.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_DLCMainMenu); + } + } +#if defined _XBOX_ONE + else + { + // Changing to async TMS calls + app.SetTMSAction(iPad,eTMSAction_TMSPP_RetrieveFiles_DLCMain); + + // block all input + m_bIgnorePress=true; + // We want to hide everything in this scene and display a timer until we get a completion for the TMS files +// for(int i=0;i<BUTTONS_MAX;i++) +// { +// m_Buttons[i].SetShow(FALSE); +// } + + updateTooltips(); + + m_controlTimer.setVisible( true ); + m_bWaitingForDLCInfo=true; + } +#endif + + // read the DLC info from TMS + /*app.ReadDLCFileFromTMS(iPad);*/ + + // We want to navigate to the DLC scene, but block input until we get the DLC file in from TMS + // Don't navigate - we might have an uplink disconnect + //app.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_DLCMainMenu); + + } + } + else + { +#if defined(__PS3__) || defined(__PSVITA__) + m_eAction=eAction_RunUnlockOrDLCPSN; + // get them to sign in to online + UINT uiIDA[1]; + uiIDA[0]=IDS_PRO_NOTONLINE_ACCEPT; + //uiIDA[1]=IDS_PRO_NOTONLINE_DECLINE; + ui.RequestMessageBox(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 1, ProfileManager.GetPrimaryPad(),&UIScene_MainMenu::MustSignInReturnedPSN,this, app.GetStringTable()); +#elif defined __ORBIS__ + m_eAction=eAction_RunUnlockOrDLCPSN; + // Determine why they're not "signed in live" + if (ProfileManager.isSignedInPSN(iPad)) + { + m_bIgnorePress=false; + // Signed in to PSN but not connected (no internet access) + assert(!ProfileManager.isConnectedToPSN(iPad)); + + UINT uiIDA[1]; + uiIDA[0] = IDS_OK; + ui.RequestMessageBox( IDS_ERROR_NETWORK_TITLE, IDS_ERROR_NETWORK, uiIDA, 1, iPad, NULL, NULL, app.GetStringTable()); + } + else + { + // Not signed in to PSN + UINT uiIDA[1]; + uiIDA[0] = IDS_PRO_NOTONLINE_ACCEPT; + ui.RequestMessageBox(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 1, ProfileManager.GetPrimaryPad(), &UIScene_MainMenu::MustSignInReturnedPSN, this, app.GetStringTable()); + return; + } +#else + UINT uiIDA[1]; + uiIDA[0]=IDS_OK; + ui.RequestMessageBox(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_XBOXLIVE_NOTIFICATION, uiIDA, 1); +#endif + } + } + else + { + // guests can't buy the game + if(ProfileManager.IsGuest(iPad)) + { + m_bIgnorePress=false; + ui.RequestMessageBox(IDS_UNLOCK_TITLE, IDS_UNLOCK_GUEST_TEXT, uiIDA, 1,iPad); + } + else if(!ProfileManager.IsSignedInLive(iPad)) + { +#if defined(__PS3__) || defined(__PSVITA__) + m_eAction=eAction_RunUnlockOrDLCPSN; + // get them to sign in to online + UINT uiIDA[1]; + uiIDA[0] = IDS_PRO_NOTONLINE_ACCEPT; + ui.RequestMessageBox(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 1, ProfileManager.GetPrimaryPad(),&UIScene_MainMenu::MustSignInReturnedPSN,this, app.GetStringTable()); +#elif defined __ORBIS__ + m_eAction=eAction_RunUnlockOrDLCPSN; + // Determine why they're not "signed in live" + if (ProfileManager.isSignedInPSN(iPad)) + { + m_bIgnorePress=false; + // Signed in to PSN but not connected (no internet access) + assert(!ProfileManager.isConnectedToPSN(iPad)); + + UINT uiIDA[1]; + uiIDA[0] = IDS_OK; + ui.RequestMessageBox( IDS_ERROR_NETWORK_TITLE, IDS_ERROR_NETWORK, uiIDA, 1, iPad, NULL, NULL, app.GetStringTable()); + } + else + { + // Not signed in to PSN + UINT uiIDA[1]; + uiIDA[0] = IDS_PRO_NOTONLINE_ACCEPT; + ui.RequestMessageBox(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 1, ProfileManager.GetPrimaryPad(), &UIScene_MainMenu::MustSignInReturnedPSN, this, app.GetStringTable()); + return; + } +#else + UINT uiIDA[1]; + uiIDA[0]=IDS_OK; + ui.RequestMessageBox(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_XBOXLIVE_NOTIFICATION, uiIDA, 1); +#endif + + } + else + { + // If the player was signed in before selecting play, we'll not have read the profile yet, so query the sign-in status to get this to happen + ProfileManager.QuerySigninStatus(); + + // check that the commerce is in the right state to be able to display the full version purchase - if the user is fast with the trial version, it can still be retrieving the product list +#if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__) + m_bIgnorePress=true; + m_bLaunchFullVersionPurchase=true; + +#else + TelemetryManager->RecordUpsellPresented(iPad, eSen_UpsellID_Full_Version_Of_Game, app.m_dwOfferID); + ProfileManager.DisplayFullVersionPurchase(false,iPad,eSen_UpsellID_Full_Version_Of_Game); +#endif + } + } +} + +void UIScene_MainMenu::tick() +{ + UIScene::tick(); + +#if defined(__PS3__) || defined (__ORBIS__) || defined(__PSVITA__) + if(m_bLaunchFullVersionPurchase) + { + int iCommerceState=app.GetCommerceState(); + // 4J-PB - if there's a commerce error - store down, player can't access store - let the DisplayFullVersionPurchase show the error + if((iCommerceState==CConsoleMinecraftApp::eCommerce_State_Online) || (iCommerceState==CConsoleMinecraftApp::eCommerce_State_Error)) + { + m_bLaunchFullVersionPurchase=false; + m_bIgnorePress=false; + updateTooltips(); + + // 4J-PB - need to check this user can access the store + bool bContentRestricted=false; + ProfileManager.GetChatAndContentRestrictions(ProfileManager.GetPrimaryPad(),true,NULL,&bContentRestricted,NULL); + if(bContentRestricted) + { + UINT uiIDA[1]; + uiIDA[0]=IDS_CONFIRM_OK; + ui.RequestMessageBox(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, ProfileManager.GetPrimaryPad(),NULL,this, app.GetStringTable()); + } + else + { + TelemetryManager->RecordUpsellPresented(ProfileManager.GetPrimaryPad(), eSen_UpsellID_Full_Version_Of_Game, app.m_dwOfferID); + ProfileManager.DisplayFullVersionPurchase(false,ProfileManager.GetPrimaryPad(),eSen_UpsellID_Full_Version_Of_Game); + } + } + } + + // 4J-PB - check for a trial version changing to a full version + if(m_bTrialVersion) + { + if(ProfileManager.IsFullVersion()) + { + m_bTrialVersion=false; + m_buttons[(int)eControl_UnlockOrDLC].init(app.GetString(IDS_DOWNLOADABLECONTENT),eControl_UnlockOrDLC); + } + } +#endif + +#if defined _XBOX_ONE + if(m_bWaitingForDLCInfo) + { + if(app.GetTMSDLCInfoRead()) + { + m_bWaitingForDLCInfo=false; + ProfileManager.SetLockedProfile(m_iPad); + ui.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_DLCMainMenu); + } + } + + if(g_NetworkManager.ShouldMessageForFullSession()) + { + UINT uiIDA[1]; + uiIDA[0]=IDS_CONFIRM_OK; + ui.RequestMessageBox( IDS_CONNECTION_FAILED, IDS_IN_PARTY_SESSION_FULL, uiIDA,1,ProfileManager.GetPrimaryPad(),NULL,NULL, app.GetStringTable()); + } +#endif + +#ifdef __ORBIS__ + + // process the error dialog (for a patch being available) + // SQRNetworkManager_Orbis::tickErrorDialog also runs the error dialog, so wrap this so this doesn't terminate a signin dialog + if(m_bErrorDialogRunning) + { + SceErrorDialogStatus stat = sceErrorDialogUpdateStatus(); + if( stat == SCE_ERROR_DIALOG_STATUS_FINISHED ) + { + sceErrorDialogTerminate(); + // if m_bRunGameChosen is true, we're here after selecting play game, and we should let the user continue with an offline game + if(m_bRunGameChosen) + { + m_bRunGameChosen=false; + m_eAction = eAction_RunGame; + + // give the option of continuing offline + UINT uiIDA[1]; + uiIDA[0]=IDS_PRO_NOTONLINE_DECLINE; + ui.RequestMessageBox(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION_PATCH_AVAILABLE, uiIDA, 1, ProfileManager.GetPrimaryPad(), &UIScene_MainMenu::PlayOfflineReturned, this, app.GetStringTable()); + + } + m_bErrorDialogRunning=false; + } + } + + if(m_bLoadTrialOnNetworkManagerReady && g_NetworkManager.IsReadyToPlayOrIdle()) + { + m_bLoadTrialOnNetworkManagerReady = false; + LoadTrial(); + } + +#endif +} + +void UIScene_MainMenu::RunAchievements(int iPad) +{ +#if TO_BE_IMPLEMENTED + UINT uiIDA[1]; + uiIDA[0]=IDS_OK; + + // guests can't look at achievements + if(ProfileManager.IsGuest(iPad)) + { + ui.RequestMessageBox(IDS_PRO_GUESTPROFILE_TITLE, IDS_PRO_GUESTPROFILE_TEXT, uiIDA, 1); + } + else + { + XShowAchievementsUI( iPad ); + } +#endif +} + +void UIScene_MainMenu::RunHelpAndOptions(int iPad) +{ + if(ProfileManager.IsGuest(iPad)) + { + UINT uiIDA[1]; + uiIDA[0]=IDS_OK; + ui.RequestMessageBox(IDS_PRO_GUESTPROFILE_TITLE, IDS_PRO_GUESTPROFILE_TEXT, uiIDA, 1); + } + else + { + // If the player was signed in before selecting play, we'll not have read the profile yet, so query the sign-in status to get this to happen + ProfileManager.QuerySigninStatus(); + +#if TO_BE_IMPLEMENTED + // 4J-PB - You can be offline and still can go into help and options + if(app.GetTMSDLCInfoRead() || !ProfileManager.IsSignedInLive(iPad)) +#endif + { + ProfileManager.SetLockedProfile(iPad); +#ifdef _XBOX_ONE + ui.ShowPlayerDisplayname(true); +#endif + ui.NavigateToScene(iPad,eUIScene_HelpAndOptionsMenu); + } +#if TO_BE_IMPLEMENTED + else + { + // Changing to async TMS calls + app.SetTMSAction(iPad,eTMSAction_TMSPP_RetrieveFiles_HelpAndOptions); + + // block all input + m_bIgnorePress=true; + // We want to hide everything in this scene and display a timer until we get a completion for the TMS files + for(int i=0;i<BUTTONS_MAX;i++) + { + m_Buttons[i].SetShow(FALSE); + } + + updateTooltips(); + + m_Timer.SetShow(TRUE); + } +#endif + } +} + +void UIScene_MainMenu::LoadTrial(void) +{ + app.SetTutorialMode( true ); + + // clear out the app's terrain features list + app.ClearTerrainFeaturePosition(); + + StorageManager.ResetSaveData(); + + // Need to set the mode as trial + ProfileManager.StartTrialGame(); + + // No saving in the trial + StorageManager.SetSaveDisabled(true); + + // Set the global flag, so that we don't disable saving again once the save is complete + app.SetGameHostOption(eGameHostOption_DisableSaving, 1); + + StorageManager.SetSaveTitle(L"Tutorial"); + + // Reset the autosave time + app.SetAutosaveTimerTime(); + + // not online for the trial game + g_NetworkManager.HostGame(0,false,true,MINECRAFT_NET_MAX_PLAYERS,0); + +#ifndef _XBOX + g_NetworkManager.FakeLocalPlayerJoined(); +#endif + + NetworkGameInitData *param = new NetworkGameInitData(); + param->seed = 0; + param->saveData = NULL; + param->settings = app.GetGameHostOption( eGameHostOption_Tutorial ) | app.GetGameHostOption(eGameHostOption_DisableSaving); + + vector<LevelGenerationOptions *> *generators = app.getLevelGenerators(); + param->levelGen = generators->at(0); + + LoadingInputParams *loadingParams = new LoadingInputParams(); + loadingParams->func = &CGameNetworkManager::RunNetworkGameThreadProc; + loadingParams->lpParam = (LPVOID)param; + + UIFullscreenProgressCompletionData *completionData = new UIFullscreenProgressCompletionData(); + completionData->bShowBackground=TRUE; + completionData->bShowLogo=TRUE; + completionData->type = e_ProgressCompletion_CloseAllPlayersUIScenes; + completionData->iPad = ProfileManager.GetPrimaryPad(); + loadingParams->completionData = completionData; + + ui.ShowTrialTimer(true); + +#ifdef _XBOX_ONE + ui.ShowPlayerDisplayname(true); +#endif + ui.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_FullscreenProgress, loadingParams); +} + +void UIScene_MainMenu::handleUnlockFullVersion() +{ + m_buttons[(int)eControl_UnlockOrDLC].setLabel(app.GetString(IDS_DOWNLOADABLECONTENT),true); +} + + +#ifdef __PSVITA__ +int UIScene_MainMenu::SelectNetworkModeReturned(void *pParam,int iPad,C4JStorage::EMessageResult result) +{ + UIScene_MainMenu* pClass = (UIScene_MainMenu*)pParam; + + if(result==C4JStorage::EMessage_ResultAccept) + { + app.DebugPrintf("Setting network mode to PSN\n"); + app.SetGameSettings(0, eGameSetting_PSVita_NetworkModeAdhoc, 0); + } + else if(result==C4JStorage::EMessage_ResultDecline) + { + app.DebugPrintf("Setting network mode to Adhoc\n"); + app.SetGameSettings(0, eGameSetting_PSVita_NetworkModeAdhoc, 1); + } + pClass->updateTooltips(); + return 0; +} +#endif //__PSVITA__ diff --git a/Minecraft.Client/Common/UI/UIScene_MainMenu.h b/Minecraft.Client/Common/UI/UIScene_MainMenu.h new file mode 100644 index 00000000..f1b358da --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_MainMenu.h @@ -0,0 +1,175 @@ +#pragma once + +#include "UIScene.h" + +class UIScene_MainMenu : public UIScene +{ +private: + enum EControls + { + eControl_PlayGame, + eControl_Leaderboards, + eControl_Achievements, + eControl_HelpAndOptions, + eControl_UnlockOrDLC, +#ifndef _DURANGO + eControl_Exit, +#else + eControl_XboxHelp, +#endif + eControl_Count, + }; + +// #ifdef __ORBIS__ +// enum EPatchCheck +// { +// ePatchCheck_Idle, +// ePatchCheck_Init, +// ePatchCheck_Running, +// }; +// #endif + + UIControl_Button m_buttons[eControl_Count]; + UIControl m_controlTimer; + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) + UI_MAP_ELEMENT( m_buttons[(int)eControl_PlayGame], "Button1") + UI_MAP_ELEMENT( m_buttons[(int)eControl_Leaderboards], "Button2") + UI_MAP_ELEMENT( m_buttons[(int)eControl_Achievements], "Button3") + UI_MAP_ELEMENT( m_buttons[(int)eControl_HelpAndOptions], "Button4") + UI_MAP_ELEMENT( m_buttons[(int)eControl_UnlockOrDLC], "Button5") +#ifndef _DURANGO + UI_MAP_ELEMENT( m_buttons[(int)eControl_Exit], "Button6") +#else + UI_MAP_ELEMENT( m_buttons[(int)eControl_XboxHelp], "Button6") +#endif + UI_MAP_ELEMENT( m_controlTimer, "Timer") + UI_END_MAP_ELEMENTS_AND_NAMES() + + static Random *random; + bool m_bIgnorePress; + bool m_bTrialVersion; + bool m_bLoadTrialOnNetworkManagerReady; +#if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__) + bool m_bLaunchFullVersionPurchase; +#endif + +#ifdef _XBOX_ONE + bool m_bWaitingForDLCInfo; +#endif + + float m_fScreenWidth,m_fScreenHeight; + float m_fRawWidth,m_fRawHeight; + vector<wstring> m_splashes; + wstring m_splash; + enum eSplashIndexes + { + eSplashHappyBirthdayEx = 0, + eSplashHappyBirthdayNotch, + eSplashMerryXmas, + eSplashHappyNewYear, + + // The start index in the splashes vector from which we can select a random splash + eSplashRandomStart, + }; + + enum eActions + { + eAction_None=0, + eAction_RunGame, + eAction_RunLeaderboards, + eAction_RunAchievements, + eAction_RunHelpAndOptions, + eAction_RunUnlockOrDLC, +#if defined(__PS3__)|| defined(__PSVITA__) || defined(__ORBIS__) + eAction_RunLeaderboardsPSN, + eAction_RunGamePSN, + eAction_RunUnlockOrDLCPSN, +#elif defined _DURANGO + eAction_RunXboxHelp, +#endif + + }; + eActions m_eAction; +public: + UIScene_MainMenu(int iPad, void *initData, UILayer *parentLayer); + virtual ~UIScene_MainMenu(); + + // Returns true if this scene has focus for the pad passed in +#ifndef __PS3__ + virtual bool hasFocus(int iPad) { return bHasFocus; } +#endif + + virtual void updateTooltips(); + virtual void updateComponents(); + + virtual EUIScene getSceneType() { return eUIScene_MainMenu;} + + virtual void customDraw(IggyCustomDrawCallbackRegion *region); +protected: + void customDrawSplash(IggyCustomDrawCallbackRegion *region); + + + virtual wstring getMoviePath(); + +public: + virtual void tick(); + // INPUT + virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled); + + virtual void handleUnlockFullVersion(); + +protected: + void handlePress(F64 controlId, F64 childId); + + void handleGainFocus(bool navBack); + + virtual long long getDefaultGtcButtons() { return 0; } + +private: + void RunPlayGame(int iPad); + void RunLeaderboards(int iPad); + void RunUnlockOrDLC(int iPad); + void RunAchievements(int iPad); + void RunHelpAndOptions(int iPad); + + void RunAction(int iPad); + + static void LoadTrial(); + +#ifdef _XBOX_ONE + static int ChooseUser_SignInReturned(void *pParam,bool bContinue, int iPad); +#endif + static int CreateLoad_SignInReturned(void *pParam,bool bContinue, int iPad); + static int HelpAndOptions_SignInReturned(void *pParam,bool bContinue,int iPad); + static int Achievements_SignInReturned(void *pParam,bool bContinue,int iPad); + static int MustSignInReturned(void *pParam,int iPad,C4JStorage::EMessageResult result); + +#if defined(__PS3__) || defined(__PSVITA__) || defined(__ORBIS__) + static int MustSignInReturnedPSN(void *pParam,int iPad,C4JStorage::EMessageResult result); +#endif + static int Leaderboards_SignInReturned(void* pParam, bool bContinue, int iPad); + static int UnlockFullGame_SignInReturned(void *pParam,bool bContinue,int iPad); + static int ExitGameReturned(void *pParam,int iPad,C4JStorage::EMessageResult result); + +#ifdef __ORBIS__ + static void RefreshChatAndContentRestrictionsReturned_PlayGame(void *pParam); + static void RefreshChatAndContentRestrictionsReturned_Leaderboards(void *pParam); + + static int PlayOfflineReturned(void *pParam, int iPad, C4JStorage::EMessageResult result); +#endif + +#ifdef _DURANGO + static int XboxHelp_SignInReturned(void *pParam, bool bContinue, int iPad); +#endif + +#ifdef __PSVITA__ + static int SelectNetworkModeReturned(void *pParam,int iPad,C4JStorage::EMessageResult result); +#endif + +#ifdef __ORBIS__ + //EPatchCheck m_ePatchCheckState; + bool m_bRunGameChosen; + int32_t m_errorCode; + bool m_bErrorDialogRunning; +#endif +}; diff --git a/Minecraft.Client/Common/UI/UIScene_MessageBox.cpp b/Minecraft.Client/Common/UI/UIScene_MessageBox.cpp new file mode 100644 index 00000000..6b8dc552 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_MessageBox.cpp @@ -0,0 +1,161 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIScene_MessageBox.h" + +UIScene_MessageBox::UIScene_MessageBox(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) +{ + // Setup all the Iggy references we need for this scene + initialiseMovie(); + + MessageBoxInfo *param = (MessageBoxInfo *)initData; + + m_buttonCount = param->uiOptionC; + + IggyDataValue result; + IggyDataValue value[2]; + value[0].type = IGGY_DATATYPE_number; + value[0].number = param->uiOptionC; + + value[1].type = IGGY_DATATYPE_number; + value[1].number = param->dwFocusButton; + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcInit , 2 , value ); + + int buttonIndex = 0; + if(param->uiOptionC > 3) + { + m_buttonButtons[eControl_Button0].init(app.GetString(param->uiOptionA[buttonIndex]),buttonIndex); + ++buttonIndex; + } + if(param->uiOptionC > 2) + { + m_buttonButtons[eControl_Button1].init(app.GetString(param->uiOptionA[buttonIndex]),buttonIndex); + ++buttonIndex; + } + if(param->uiOptionC > 1) + { + m_buttonButtons[eControl_Button2].init(app.GetString(param->uiOptionA[buttonIndex]),buttonIndex); + ++buttonIndex; + } + m_buttonButtons[eControl_Button3].init(app.GetString(param->uiOptionA[buttonIndex]),buttonIndex); + + m_labelTitle.init(app.GetString(param->uiTitle)); + m_labelContent.init(app.GetString(param->uiText)); + + out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcAutoResize , 0 , NULL ); + + m_Func = param->Func; + m_lpParam = param->lpParam; + + parentLayer->addComponent(iPad,eUIComponent_MenuBackground); + + // 4J-TomK - rebuild touch after auto resize +#ifdef __PSVITA__ + ui.TouchBoxRebuild(this); +#endif +} + +UIScene_MessageBox::~UIScene_MessageBox() +{ + m_parentLayer->removeComponent(eUIComponent_MenuBackground); +} + +wstring UIScene_MessageBox::getMoviePath() +{ + if(app.GetLocalPlayerCount() > 1 && !m_parentLayer->IsFullscreenGroup()) + { + return L"MessageBoxSplit"; + } + else + { + return L"MessageBox"; + } +} + +void UIScene_MessageBox::updateTooltips() +{ + ui.SetTooltips( m_parentLayer->IsFullscreenGroup()?XUSER_INDEX_ANY:m_iPad, IDS_TOOLTIPS_SELECT, IDS_TOOLTIPS_CANCEL); +} + +void UIScene_MessageBox::handleReload() +{ + IggyDataValue result; + IggyDataValue value[2]; + value[0].type = IGGY_DATATYPE_number; + value[0].number = m_buttonCount; + + value[1].type = IGGY_DATATYPE_number; + value[1].number = (F64)getControlFocus(); + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcInit , 2 , value ); + + out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcAutoResize , 0 , NULL ); +} + +void UIScene_MessageBox::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled) +{ + //app.DebugPrintf("UIScene_DebugOverlay handling input for pad %d, key %d, down- %s, pressed- %s, released- %s\n", iPad, key, down?"TRUE":"FALSE", pressed?"TRUE":"FALSE", released?"TRUE":"FALSE"); + ui.AnimateKeyPress(m_iPad, key, repeat, pressed, released); + switch(key) + { + case ACTION_MENU_CANCEL: + if(pressed) + { + navigateBack(); + if(m_Func) m_Func(m_lpParam, iPad, C4JStorage::EMessage_Cancelled); + } + break; + case ACTION_MENU_OK: +#ifdef __ORBIS__ + case ACTION_MENU_TOUCHPAD_PRESS: +#endif + sendInputToMovie(key, repeat, pressed, released); + break; + case ACTION_MENU_UP: + case ACTION_MENU_DOWN: + sendInputToMovie(key, repeat, pressed, released); + break; + } + handled = true; +} + +void UIScene_MessageBox::handlePress(F64 controlId, F64 childId) +{ + C4JStorage::EMessageResult result = C4JStorage::EMessage_Cancelled; + switch((int)controlId) + { + case 0: + result = C4JStorage::EMessage_ResultAccept; + break; + case 1: + result = C4JStorage::EMessage_ResultDecline; + break; + case 2: + result = C4JStorage::EMessage_ResultThirdOption; + break; + case 3: + result = C4JStorage::EMessage_ResultFourthOption; + break; + } + + navigateBack(); + if(m_Func) m_Func(m_lpParam, m_iPad, result); +} + +bool UIScene_MessageBox::hasFocus(int iPad) +{ + // 4J-JEV: Fix for PS4 #5204 - [TRC][R4033] The application can be locked up by second user logging out of the system. + if (m_iPad == 255) + { + // Message box is for everyone + return bHasFocus; + } + else if (ProfileManager.IsSignedIn(m_iPad)) + { + // Owner is still present + return bHasFocus && (iPad == m_iPad); + } + else + { + // Original owner has left so let everyone interact + return bHasFocus; + } +}
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIScene_MessageBox.h b/Minecraft.Client/Common/UI/UIScene_MessageBox.h new file mode 100644 index 00000000..3c349dea --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_MessageBox.h @@ -0,0 +1,59 @@ +#pragma once + +#include "UIScene.h" + +class UIScene_MessageBox : public UIScene +{ +private: + enum EControls + { + eControl_Button0, + eControl_Button1, + eControl_Button2, + eControl_Button3, + + eControl_COUNT + }; + + int( *m_Func)(LPVOID,int,const C4JStorage::EMessageResult); + LPVOID m_lpParam; + int m_buttonCount; + + UIControl_Button m_buttonButtons[eControl_COUNT]; + UIControl_Label m_labelTitle, m_labelContent; + IggyName m_funcInit, m_funcAutoResize; + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) + UI_MAP_ELEMENT( m_buttonButtons[eControl_Button0], "Button0") + UI_MAP_ELEMENT( m_buttonButtons[eControl_Button1], "Button1") + UI_MAP_ELEMENT( m_buttonButtons[eControl_Button2], "Button2") + UI_MAP_ELEMENT( m_buttonButtons[eControl_Button3], "Button3") + + UI_MAP_ELEMENT( m_labelTitle, "Title") + UI_MAP_ELEMENT( m_labelContent, "Content") + + UI_MAP_NAME( m_funcInit, L"Init") + UI_MAP_NAME( m_funcAutoResize, L"AutoResize") + UI_END_MAP_ELEMENTS_AND_NAMES() +public: + UIScene_MessageBox(int iPad, void *initData, UILayer *parentLayer); + ~UIScene_MessageBox(); + + virtual EUIScene getSceneType() { return eUIScene_MessageBox;} + + // Returns true if lower scenes in this scenes layer, or in any layer below this scenes layers should be hidden + virtual bool hidesLowerScenes() { return false; } + +protected: + // TODO: This should be pure virtual in this class + virtual wstring getMoviePath(); + + virtual void updateTooltips(); + +public: + virtual void handleReload(); + virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled); + virtual bool hasFocus(int iPad); + +protected: + void handlePress(F64 controlId, F64 childId); +};
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIScene_PauseMenu.cpp b/Minecraft.Client/Common/UI/UIScene_PauseMenu.cpp new file mode 100644 index 00000000..d9569cc9 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_PauseMenu.cpp @@ -0,0 +1,1483 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIScene_PauseMenu.h" +#include "..\..\MinecraftServer.h" +#include "..\..\MultiplayerLocalPlayer.h" +#include "..\..\TexturePackRepository.h" +#include "..\..\TexturePack.h" +#include "..\..\DLCTexturePack.h" +#include "..\..\..\Minecraft.World\StringHelpers.h" +#ifdef __ORBIS__ +#include <error_dialog.h> +#endif + +#ifdef _DURANGO +#include "..\..\Durango\Leaderboards\DurangoStatsDebugger.h" +#endif + +#ifdef __PSVITA__ +#include "PSVita\Network\SonyCommerce_Vita.h" +#endif + +#if defined __PS3__ || defined __ORBIS__ +#define USE_SONY_REMOTE_STORAGE +#endif + +UIScene_PauseMenu::UIScene_PauseMenu(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) +{ + // Setup all the Iggy references we need for this scene + initialiseMovie(); + m_bIgnoreInput=false; + m_eAction=eAction_None; + + m_buttons[BUTTON_PAUSE_RESUMEGAME].init(app.GetString(IDS_RESUME_GAME),BUTTON_PAUSE_RESUMEGAME); + m_buttons[BUTTON_PAUSE_HELPANDOPTIONS].init(app.GetString(IDS_HELP_AND_OPTIONS),BUTTON_PAUSE_HELPANDOPTIONS); + m_buttons[BUTTON_PAUSE_LEADERBOARDS].init(app.GetString(IDS_LEADERBOARDS),BUTTON_PAUSE_LEADERBOARDS); +#ifdef _DURANGO + m_buttons[BUTTON_PAUSE_XBOXHELP].init(app.GetString(IDS_XBOX_HELP_APP), BUTTON_PAUSE_XBOXHELP); +#else + m_buttons[BUTTON_PAUSE_ACHIEVEMENTS].init(app.GetString(IDS_ACHIEVEMENTS),BUTTON_PAUSE_ACHIEVEMENTS); +#endif +#if defined(_XBOX_ONE) || defined(__ORBIS__) + m_bTrialTexturePack = false; + if(!Minecraft::GetInstance()->skins->isUsingDefaultSkin()) + { + TexturePack *tPack = Minecraft::GetInstance()->skins->getSelected(); + DLCTexturePack *pDLCTexPack=(DLCTexturePack *)tPack; + + m_pDLCPack=pDLCTexPack->getDLCInfoParentPack();//tPack->getDLCPack(); + + if(!m_pDLCPack->hasPurchasedFile( DLCManager::e_DLCType_Texture, L"" )) + { + m_bTrialTexturePack = true; + } + } + + // 4J-TomK - check for all possible labels being fed into BUTTON_PAUSE_SAVEGAME (Bug 163775) + // this has to be done before button initialisation! + wchar_t saveButtonLabels[2][256]; + swprintf( saveButtonLabels[0], 256, L"%ls", app.GetString( IDS_SAVE_GAME )); + swprintf( saveButtonLabels[1], 256, L"%ls", app.GetString( IDS_DISABLE_AUTOSAVE )); + m_buttons[BUTTON_PAUSE_SAVEGAME].setAllPossibleLabels(2,saveButtonLabels); + + if(app.GetGameHostOption(eGameHostOption_DisableSaving) || m_bTrialTexturePack) + { + m_savesDisabled = true; + m_buttons[BUTTON_PAUSE_SAVEGAME].init(app.GetString(IDS_SAVE_GAME),BUTTON_PAUSE_SAVEGAME); + } + else + { + m_savesDisabled = false; + m_buttons[BUTTON_PAUSE_SAVEGAME].init(app.GetString(IDS_DISABLE_AUTOSAVE),BUTTON_PAUSE_SAVEGAME); + } +#else + m_buttons[BUTTON_PAUSE_SAVEGAME].init(app.GetString(IDS_SAVE_GAME),BUTTON_PAUSE_SAVEGAME); +#endif + m_buttons[BUTTON_PAUSE_EXITGAME].init(app.GetString(IDS_EXIT_GAME),BUTTON_PAUSE_EXITGAME); + + if(!ProfileManager.IsFullVersion()) + { + // hide the trial timer + ui.ShowTrialTimer(false); + } + + updateControlsVisibility(); + + doHorizontalResizeCheck(); + + // get rid of the quadrant display if it's on + ui.HidePressStart(); + +#if TO_BE_IMPLEMENTED + XuiSetTimer(m_hObj,IGNORE_KEYPRESS_TIMERID,IGNORE_KEYPRESS_TIME); +#endif + + if( g_NetworkManager.IsLocalGame() && g_NetworkManager.GetPlayerCount() == 1 ) + { + app.SetXuiServerAction(ProfileManager.GetPrimaryPad(),eXuiServerAction_PauseServer,(void *)TRUE); + } + + TelemetryManager->RecordMenuShown(m_iPad, eUIScene_PauseMenu, 0); + TelemetryManager->RecordPauseOrInactive(m_iPad); + + Minecraft *pMinecraft = Minecraft::GetInstance(); + if(pMinecraft != NULL && pMinecraft->localgameModes[iPad] != NULL ) + { + TutorialMode *gameMode = (TutorialMode *)pMinecraft->localgameModes[iPad]; + + // This just allows it to be shown + gameMode->getTutorial()->showTutorialPopup(false); + } + m_bErrorDialogRunning = false; +} + +UIScene_PauseMenu::~UIScene_PauseMenu() +{ + Minecraft *pMinecraft = Minecraft::GetInstance(); + if(pMinecraft != NULL && pMinecraft->localgameModes[m_iPad] != NULL ) + { + TutorialMode *gameMode = (TutorialMode *)pMinecraft->localgameModes[m_iPad]; + + // This just allows it to be shown + gameMode->getTutorial()->showTutorialPopup(true); + } + + m_parentLayer->showComponent(m_iPad,eUIComponent_Panorama,false); + m_parentLayer->showComponent(m_iPad,eUIComponent_MenuBackground,false); + m_parentLayer->showComponent(m_iPad,eUIComponent_Logo,false); +} + +wstring UIScene_PauseMenu::getMoviePath() +{ + if(app.GetLocalPlayerCount() > 1) + { + return L"PauseMenuSplit"; + } + else + { + return L"PauseMenu"; + } +} + +void UIScene_PauseMenu::tick() +{ + UIScene::tick(); + +#ifdef __PSVITA__ + // 4J-MGH - Need to check for installed DLC here, as we delay the installation of the key file on Vita + if(!app.DLCInstallProcessCompleted()) app.StartInstallDLCProcess(0); +#endif + + +#if defined _XBOX_ONE || defined __ORBIS__ + if(!m_bTrialTexturePack && m_savesDisabled != (app.GetGameHostOption(eGameHostOption_DisableSaving) != 0) && ProfileManager.GetPrimaryPad() == m_iPad ) + { + // We show the save button if saves are disabled as this lets us show a prompt to enable them (via purchasing a texture pack) + if( app.GetGameHostOption(eGameHostOption_DisableSaving) ) + { + m_savesDisabled = true; + m_buttons[BUTTON_PAUSE_SAVEGAME].setLabel( app.GetString(IDS_SAVE_GAME) ); + } + else + { + m_savesDisabled = false; + m_buttons[BUTTON_PAUSE_SAVEGAME].setLabel( app.GetString(IDS_DISABLE_AUTOSAVE) ); + } + } +#endif + +#ifdef __ORBIS__ + // Process the error dialog (for a patch being available) + if(m_bErrorDialogRunning) + { + SceErrorDialogStatus stat = sceErrorDialogUpdateStatus(); + if( stat == SCE_ERROR_DIALOG_STATUS_FINISHED ) + { + sceErrorDialogTerminate(); + m_bErrorDialogRunning=false; + } + } +#endif +} + +void UIScene_PauseMenu::updateTooltips() +{ + bool bUserisClientSide = ProfileManager.IsSignedInLive(m_iPad); + bool bIsisPrimaryHost=g_NetworkManager.IsHost() && (ProfileManager.GetPrimaryPad()==m_iPad); + +#ifdef _XBOX_ONE + bool bDisplayBanTip = !g_NetworkManager.IsLocalGame() && !bIsisPrimaryHost && !ProfileManager.IsGuest(m_iPad); +#endif + + int iY = -1; +#if defined __PS3__ || defined __ORBIS__ + if(m_iPad == ProfileManager.GetPrimaryPad() ) iY = IDS_TOOLTIPS_GAME_INVITES; +#endif + int iRB = -1; + int iX = -1; + + if(ProfileManager.IsFullVersion()) + { + if(StorageManager.GetSaveDisabled()) + { + iX = bIsisPrimaryHost?IDS_TOOLTIPS_SELECTDEVICE:-1; +#ifdef _XBOX_ONE + iRB = bDisplayBanTip?IDS_TOOLTIPS_BANLEVEL:-1; +#endif + if( CSocialManager::Instance()->IsTitleAllowedToPostImages() && CSocialManager::Instance()->AreAllUsersAllowedToPostImages() && bUserisClientSide ) + { +#ifndef __PS3__ + iY = IDS_TOOLTIPS_SHARE; +#endif + } + } + else + { + iX = bIsisPrimaryHost?IDS_TOOLTIPS_CHANGEDEVICE:-1; +#ifdef _XBOX_ONE + iRB = bDisplayBanTip?IDS_TOOLTIPS_BANLEVEL:-1; +#endif + if( CSocialManager::Instance()->IsTitleAllowedToPostImages() && CSocialManager::Instance()->AreAllUsersAllowedToPostImages() && bUserisClientSide) + { +#ifndef __PS3__ + iY = IDS_TOOLTIPS_SHARE; +#endif + } + } + } + ui.SetTooltips( m_iPad, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK,iX,iY, -1,-1,-1,iRB); +} + +void UIScene_PauseMenu::updateComponents() +{ + m_parentLayer->showComponent(m_iPad,eUIComponent_Panorama,false); + m_parentLayer->showComponent(m_iPad,eUIComponent_MenuBackground,true); + + if( app.GetLocalPlayerCount() == 1 ) m_parentLayer->showComponent(m_iPad,eUIComponent_Logo,true); + else m_parentLayer->showComponent(m_iPad,eUIComponent_Logo,false); +} + +void UIScene_PauseMenu::handlePreReload() +{ +#if defined _XBOX_ONE || defined __ORBIS__ + if(ProfileManager.GetPrimaryPad() == m_iPad) + { + // 4J-TomK - check for all possible labels being fed into BUTTON_PAUSE_SAVEGAME (Bug 163775) + // this has to be done before button initialisation! + wchar_t saveButtonLabels[2][256]; + swprintf( saveButtonLabels[0], 256, L"%ls", app.GetString( IDS_SAVE_GAME )); + swprintf( saveButtonLabels[1], 256, L"%ls", app.GetString( IDS_DISABLE_AUTOSAVE )); + m_buttons[BUTTON_PAUSE_SAVEGAME].setAllPossibleLabels(2,saveButtonLabels); + } +#endif +} + +void UIScene_PauseMenu::handleReload() +{ + updateTooltips(); + updateControlsVisibility(); + +#if defined _XBOX_ONE || defined __ORBIS__ + if(ProfileManager.GetPrimaryPad() == m_iPad) + { + // We show the save button if saves are disabled as this lets us show a prompt to enable them (via purchasing a texture pack) + if( app.GetGameHostOption(eGameHostOption_DisableSaving) || m_bTrialTexturePack ) + { + m_savesDisabled = true; + m_buttons[BUTTON_PAUSE_SAVEGAME].setLabel( app.GetString(IDS_SAVE_GAME) ); + } + else + { + m_savesDisabled = false; + m_buttons[BUTTON_PAUSE_SAVEGAME].setLabel( app.GetString(IDS_DISABLE_AUTOSAVE) ); + } + } +#endif + + doHorizontalResizeCheck(); +} + +void UIScene_PauseMenu::updateControlsVisibility() +{ + // are we the primary player? + // 4J-PB - fix for 7844 & 7845 - + // TCR # 128: XLA Pause Menu: When in a multiplayer game as a client the Pause Menu does not have a Leaderboards option. + // TCR # 128: XLA Pause Menu: When in a multiplayer game as a client the Pause Menu does not have an Achievements option. + if(ProfileManager.GetPrimaryPad()==m_iPad) // && g_NetworkManager.IsHost()) + { + // are we in splitscreen? + // how many local players do we have? + if( app.GetLocalPlayerCount()>1 ) + { + // Hide the BUTTON_PAUSE_LEADERBOARDS and BUTTON_PAUSE_ACHIEVEMENTS + removeControl( &m_buttons[BUTTON_PAUSE_LEADERBOARDS], false ); +#ifndef _XBOX_ONE + removeControl( &m_buttons[BUTTON_PAUSE_ACHIEVEMENTS], false ); +#endif + } +#ifdef __PSVITA__ + // MGH added - remove leaderboards in adhoc + if(CGameNetworkManager::usingAdhocMode()) + { + removeControl( &m_buttons[BUTTON_PAUSE_LEADERBOARDS], false ); + } +#endif + + if( !g_NetworkManager.IsHost() ) + { + // Hide the BUTTON_PAUSE_SAVEGAME + removeControl( &m_buttons[BUTTON_PAUSE_SAVEGAME], false ); + } + } + else + { + // Hide the BUTTON_PAUSE_LEADERBOARDS, BUTTON_PAUSE_ACHIEVEMENTS and BUTTON_PAUSE_SAVEGAME + removeControl( &m_buttons[BUTTON_PAUSE_LEADERBOARDS], false ); +#ifndef _XBOX_ONE + removeControl( &m_buttons[BUTTON_PAUSE_ACHIEVEMENTS], false ); +#endif + removeControl( &m_buttons[BUTTON_PAUSE_SAVEGAME], false ); + } + + // is saving disabled? + if(StorageManager.GetSaveDisabled()) + { +#ifdef _XBOX + // disable save button + m_buttons[BUTTON_PAUSE_SAVEGAME].setEnable(false); +#endif + } + +#if defined(__PS3__) || defined (__PSVITA__) || defined(__ORBIS__) + // We don't have a way to display trophies/achievements, so remove the button, and we're allowed to not have it on Xbox One + removeControl( &m_buttons[BUTTON_PAUSE_ACHIEVEMENTS], false ); +#endif + +} + +void UIScene_PauseMenu::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled) +{ + if(m_bIgnoreInput) + { + return; + } + + //app.DebugPrintf("UIScene_DebugOverlay handling input for pad %d, key %d, down- %s, pressed- %s, released- %s\n", iPad, key, down?"TRUE":"FALSE", pressed?"TRUE":"FALSE", released?"TRUE":"FALSE"); + ui.AnimateKeyPress(iPad, key, repeat, pressed, released); + +#ifdef _XBOX_ONE + bool bIsisPrimaryHost=g_NetworkManager.IsHost() && (ProfileManager.GetPrimaryPad()==iPad); + bool bDisplayBanTip = !g_NetworkManager.IsLocalGame() && !bIsisPrimaryHost && !ProfileManager.IsGuest(iPad); +#endif + + switch(key) + { +#ifdef _DURANGO + case ACTION_MENU_GTC_RESUME: +#endif +#if defined(__PS3__) // not for Orbis - we want to use the pause menu (touchpad press) to select a menu item + case ACTION_MENU_PAUSEMENU: +#endif + case ACTION_MENU_CANCEL: + if(pressed) + { +#ifdef _DURANGO + //DurangoStatsDebugger::PrintStats(iPad); +#endif + + if( iPad == ProfileManager.GetPrimaryPad() && g_NetworkManager.IsLocalGame() ) + { + app.SetXuiServerAction(ProfileManager.GetPrimaryPad(),eXuiServerAction_PauseServer,(void *)FALSE); + } + + ui.PlayUISFX(eSFX_Back); + navigateBack(); + if(!ProfileManager.IsFullVersion()) + { + ui.ShowTrialTimer(true); + } + } + break; + case ACTION_MENU_OK: +#ifdef __ORBIS__ + case ACTION_MENU_TOUCHPAD_PRESS: +#endif + case ACTION_MENU_UP: + case ACTION_MENU_DOWN: + if(pressed) + { + sendInputToMovie(key, repeat, pressed, released); + } + break; + +#if TO_BE_IMPLEMENTED + case VK_PAD_X: + // Change device + if(bIsisPrimaryHost) + { + // we need a function to deal with the return from this - if it changes, we need to update the pause menu and tooltips + // Fix for #12531 - TCR 001: BAS Game Stability: When a player selects to change a storage + // device, and repeatedly backs out of the SD screen, disconnects from LIVE, and then selects a SD, the title crashes. + m_bIgnoreInput=true; + + StorageManager.SetSaveDevice(&UIScene_PauseMenu::DeviceSelectReturned,this,true); + } + rfHandled = TRUE; + break; +#endif + + case ACTION_MENU_Y: + { + +#if defined(__PS3__) || defined(__ORBIS__) + if(pressed && iPad == ProfileManager.GetPrimaryPad()) + { +#ifdef __ORBIS__ + // If a patch is available, can't view invites + if (CheckForPatch()) break; +#endif + + // Are we offline? + if(!ProfileManager.IsSignedInLive(iPad)) + { + m_eAction=eAction_ViewInvitesPSN; +#ifdef __ORBIS__ + int npAvailability = ProfileManager.getNPAvailability(iPad); + if (npAvailability == SCE_NP_ERROR_AGE_RESTRICTION) + { + // 4J Stu - This is a bit messy and is due to the library incorrectly returning false for IsSignedInLive is the npAvailability isn't SCE_OK + UINT uiIDA[1]; + uiIDA[0]=IDS_OK; + ui.RequestMessageBox(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, iPad, NULL, NULL, app.GetStringTable()); + } + else + // Determine why they're not "signed in live" + if (ProfileManager.isSignedInPSN(iPad)) + { + // Signed in to PSN but not connected (no internet access) + assert(!ProfileManager.isConnectedToPSN(iPad)); + + UINT uiIDA[1]; + uiIDA[0] = IDS_OK; + ui.RequestMessageBox( IDS_ERROR_NETWORK_TITLE, IDS_ERROR_NETWORK, uiIDA, 1, iPad, NULL, NULL, app.GetStringTable()); + } + else + { + // Not signed in to PSN + UINT uiIDA[1]; + uiIDA[0] = IDS_PRO_NOTONLINE_ACCEPT; + ui.RequestMessageBox( IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 1, iPad, &UIScene_PauseMenu::MustSignInReturnedPSN, this, app.GetStringTable(), NULL, 0, false); + } +#else // __PS3__ + // get them to sign in to online + UINT uiIDA[1]; + uiIDA[0]=IDS_PRO_NOTONLINE_ACCEPT; + ui.RequestMessageBox(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 1, iPad, &UIScene_PauseMenu::MustSignInReturnedPSN, this, app.GetStringTable(), NULL, 0, false); +#endif + } + else + { +#ifdef __ORBIS__ + SQRNetworkManager_Orbis::RecvInviteGUI(); +#else // __PS3__ + int ret = sceNpBasicRecvMessageCustom(SCE_NP_BASIC_MESSAGE_MAIN_TYPE_INVITE, SCE_NP_BASIC_RECV_MESSAGE_OPTIONS_INCLUDE_BOOTABLE, SYS_MEMORY_CONTAINER_ID_INVALID); + app.DebugPrintf("sceNpBasicRecvMessageCustom return %d ( %08x )\n", ret, ret); +#endif + } + } +#else +#if TO_BE_IMPLEMENTED + if(bUserisClientSide) + { + // 4J Stu - Added check in 1.8.2 bug fix (TU6) to stop repeat key presses + bool bCanScreenshot = true; + for(int j=0; j < XUSER_MAX_COUNT;++j) + { + if(app.GetXuiAction(j) == eAppAction_SocialPostScreenshot) + { + bCanScreenshot = false; + break; + } + } + if(bCanScreenshot) app.SetAction(pInputData->UserIndex,eAppAction_SocialPost); + } + rfHandled = TRUE; +#endif +#endif // __PS3__ + } + break; +#ifdef _XBOX_ONE + case ACTION_MENU_RIGHT_SCROLL: + if( bDisplayBanTip ) + { + UINT uiIDA[2]; + uiIDA[0]=IDS_CONFIRM_CANCEL; + uiIDA[1]=IDS_CONFIRM_OK; + ui.RequestMessageBox(IDS_ACTION_BAN_LEVEL_TITLE, IDS_ACTION_BAN_LEVEL_DESCRIPTION, uiIDA, 2, iPad,&UIScene_PauseMenu::BanGameDialogReturned,this, app.GetStringTable(), NULL, 0, false); + + //rfHandled = TRUE; + } + break; +#endif + } +} + +void UIScene_PauseMenu::handlePress(F64 controlId, F64 childId) +{ + if(m_bIgnoreInput) return; + + switch((int)controlId) + { + case BUTTON_PAUSE_RESUMEGAME: + if( m_iPad == ProfileManager.GetPrimaryPad() && g_NetworkManager.IsLocalGame() ) + { + app.SetXuiServerAction(ProfileManager.GetPrimaryPad(),eXuiServerAction_PauseServer,(void *)FALSE); + } + navigateBack(); + break; + case BUTTON_PAUSE_LEADERBOARDS: + { + UINT uiIDA[1]; + uiIDA[0]=IDS_OK; + + //4J Gordon: Being used for the leaderboards proper now + // guests can't look at leaderboards + if(ProfileManager.IsGuest(m_iPad)) + { + ui.RequestMessageBox(IDS_PRO_GUESTPROFILE_TITLE, IDS_PRO_GUESTPROFILE_TEXT, uiIDA, 1, ProfileManager.GetPrimaryPad(),NULL,NULL, app.GetStringTable(), NULL, 0, false); + } + else if(!ProfileManager.IsSignedInLive(m_iPad)) + { +#ifdef __ORBIS__ + // If a patch is available, can't show leaderboard + if (CheckForPatch()) break; + + // Check for content restricted user + // Update error code + int errorCode = ProfileManager.getNPAvailability(m_iPad); + + // Check if PSN is unavailable because of age restriction + if (errorCode == SCE_NP_ERROR_AGE_RESTRICTION) + { + UINT uiIDA[1]; + uiIDA[0] = IDS_CONFIRM_OK; + ui.RequestMessageBox(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, m_iPad, NULL, NULL, app.GetStringTable()); + + break;; + } + +#endif + +#if defined __PS3__ || __PSVITA__ + // get them to sign in to online + m_eAction=eAction_ViewLeaderboardsPSN; + UINT uiIDA[1]; + uiIDA[0]=IDS_PRO_NOTONLINE_ACCEPT; + ui.RequestMessageBox(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_XBOXLIVE_NOTIFICATION, uiIDA, 1, ProfileManager.GetPrimaryPad(),&UIScene_PauseMenu::MustSignInReturnedPSN,this, app.GetStringTable(), NULL, 0, false); +#elif defined(__ORBIS__) + m_eAction=eAction_ViewLeaderboardsPSN; + int npAvailability = ProfileManager.getNPAvailability(m_iPad); + if (npAvailability == SCE_NP_ERROR_AGE_RESTRICTION) + { + // 4J Stu - This is a bit messy and is due to the library incorrectly returning false for IsSignedInLive is the npAvailability isn't SCE_OK + UINT uiIDA[1]; + uiIDA[0]=IDS_OK; + ui.RequestMessageBox(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, m_iPad, NULL, NULL, app.GetStringTable()); + } + else + // Determine why they're not "signed in live" + if (ProfileManager.isSignedInPSN(m_iPad)) + { + // Signed in to PSN but not connected (no internet access) + + // Id + assert(!ProfileManager.isConnectedToPSN(m_iPad)); + + UINT uiIDA[1]; + uiIDA[0] = IDS_OK; + ui.RequestMessageBox( IDS_ERROR_NETWORK_TITLE, IDS_ERROR_NETWORK, uiIDA, 1, m_iPad, NULL, NULL, app.GetStringTable()); + } + else + { + // Not signed in to PSN + UINT uiIDA[1]; + uiIDA[0] = IDS_PRO_NOTONLINE_ACCEPT; + ui.RequestMessageBox( IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 1, m_iPad, &UIScene_PauseMenu::MustSignInReturnedPSN, this, app.GetStringTable(), NULL, 0, false); + } +#else + UINT uiIDA[1] = { IDS_OK }; + ui.RequestMessageBox(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_XBOXLIVE_NOTIFICATION, uiIDA, 1, m_iPad); +#endif + } + else + { + bool bContentRestricted=false; +#if defined(__PS3__) || defined(__PSVITA__) + ProfileManager.GetChatAndContentRestrictions(m_iPad,true,NULL,&bContentRestricted,NULL); +#endif + if(bContentRestricted) + { +#if !(defined(_XBOX) || defined(_WIN64)) // 4J Stu - Temp to get the win build running, but so we check this for other platforms + // you can't see leaderboards + UINT uiIDA[1]; + uiIDA[0]=IDS_CONFIRM_OK; + ui.RequestMessageBox(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, m_iPad,NULL,this, app.GetStringTable(), NULL, 0, false); +#endif + } + else + { + ui.NavigateToScene(m_iPad, eUIScene_LeaderboardsMenu); + } + } + } + break; +#ifdef _DURANGO + case BUTTON_PAUSE_XBOXHELP: + { + // 4J: Launch the crummy xbox help application. + WXS::User^ user = ProfileManager.GetUser(m_iPad); + Windows::Xbox::ApplicationModel::Help::Show(user); + } + break; +#elif TO_BE_IMPLEMENTED + case BUTTON_PAUSE_ACHIEVEMENTS: + + // guests can't look at achievements + if(ProfileManager.IsGuest(pNotifyPressData->UserIndex)) + { + UINT uiIDA[1]; + uiIDA[0]=IDS_OK; + ui.RequestMessageBox(IDS_PRO_GUESTPROFILE_TITLE, IDS_PRO_GUESTPROFILE_TEXT, uiIDA, 1, ProfileManager.GetPrimaryPad(),NULL,NULL, app.GetStringTable(), NULL, 0, false); + } + else + { + XShowAchievementsUI( pNotifyPressData->UserIndex ); + } + break; +#endif + + case BUTTON_PAUSE_HELPANDOPTIONS: + ui.NavigateToScene(m_iPad,eUIScene_HelpAndOptionsMenu); + break; + case BUTTON_PAUSE_SAVEGAME: + PerformActionSaveGame(); + break; + case BUTTON_PAUSE_EXITGAME: + { + Minecraft *pMinecraft = Minecraft::GetInstance(); + // Check if it's the trial version + if(ProfileManager.IsFullVersion()) + { + UINT uiIDA[3]; + + // is it the primary player exiting? + if(m_iPad==ProfileManager.GetPrimaryPad()) + { + int playTime = -1; + if( pMinecraft->localplayers[m_iPad] != NULL ) + { + playTime = (int)pMinecraft->localplayers[m_iPad]->getSessionTimer(); + } + +#if defined(_XBOX_ONE) || defined(__ORBIS__) + uiIDA[0]=IDS_CONFIRM_CANCEL; + uiIDA[1]=IDS_CONFIRM_OK; + + if(g_NetworkManager.IsHost() && StorageManager.GetSaveDisabled()) + { + uiIDA[0]=IDS_CONFIRM_CANCEL; + uiIDA[1]=IDS_EXIT_GAME_SAVE; + uiIDA[2]=IDS_EXIT_GAME_NO_SAVE; + + if(g_NetworkManager.GetPlayerCount()>1) + { + ui.RequestMessageBox(IDS_EXIT_GAME, IDS_CONFIRM_EXIT_GAME_CONFIRM_DISCONNECT_SAVE, uiIDA, 3, m_iPad,&UIScene_PauseMenu::ExitGameSaveDialogReturned,this, app.GetStringTable(), NULL, 0, false); + } + else + { + ui.RequestMessageBox(IDS_EXIT_GAME, IDS_CONFIRM_EXIT_GAME, uiIDA, 3, m_iPad,&UIScene_PauseMenu::ExitGameSaveDialogReturned,this, app.GetStringTable(), NULL, 0, false); + } + } + else if(g_NetworkManager.IsHost() && g_NetworkManager.GetPlayerCount()>1) + { + ui.RequestMessageBox(IDS_EXIT_GAME, IDS_CONFIRM_EXIT_GAME_CONFIRM_DISCONNECT, uiIDA, 2, m_iPad,&IUIScene_PauseMenu::ExitGameDialogReturned, dynamic_cast<IUIScene_PauseMenu*>(this), app.GetStringTable(), NULL, 0, false); + } + else + { + ui.RequestMessageBox(IDS_EXIT_GAME, IDS_CONFIRM_EXIT_GAME, uiIDA, 2, m_iPad,&IUIScene_PauseMenu::ExitGameDialogReturned, dynamic_cast<IUIScene_PauseMenu*>(this), app.GetStringTable(), NULL, 0, false); + } +#else + if(StorageManager.GetSaveDisabled()) + { + uiIDA[0]=IDS_CONFIRM_CANCEL; + uiIDA[1]=IDS_CONFIRM_OK; + ui.RequestMessageBox(IDS_EXIT_GAME, IDS_CONFIRM_EXIT_GAME_PROGRESS_LOST, uiIDA, 2, m_iPad,&IUIScene_PauseMenu::ExitGameDialogReturned,this, app.GetStringTable(), NULL, 0, false); + } + else + { + if( g_NetworkManager.IsHost() ) + { + uiIDA[0]=IDS_CONFIRM_CANCEL; + uiIDA[1]=IDS_EXIT_GAME_SAVE; + uiIDA[2]=IDS_EXIT_GAME_NO_SAVE; + + if(g_NetworkManager.GetPlayerCount()>1) + { + ui.RequestMessageBox(IDS_EXIT_GAME, IDS_CONFIRM_EXIT_GAME_CONFIRM_DISCONNECT_SAVE, uiIDA, 3, m_iPad,&UIScene_PauseMenu::ExitGameSaveDialogReturned,this, app.GetStringTable(), NULL, 0, false); + } + else + { + ui.RequestMessageBox(IDS_EXIT_GAME, IDS_CONFIRM_EXIT_GAME, uiIDA, 3, m_iPad,&UIScene_PauseMenu::ExitGameSaveDialogReturned,this, app.GetStringTable(), NULL, 0, false); + } + } + else + { + uiIDA[0]=IDS_CONFIRM_CANCEL; + uiIDA[1]=IDS_CONFIRM_OK; + + ui.RequestMessageBox(IDS_EXIT_GAME, IDS_CONFIRM_EXIT_GAME, uiIDA, 2, m_iPad,&IUIScene_PauseMenu::ExitGameDialogReturned,this, app.GetStringTable(), NULL, 0, false); + } + } +#endif + } + else + { + int playTime = -1; + if( pMinecraft->localplayers[m_iPad] != NULL ) + { + playTime = (int)pMinecraft->localplayers[m_iPad]->getSessionTimer(); + } + + TelemetryManager->RecordLevelExit(m_iPad, eSen_LevelExitStatus_Exited); + + + // just exit the player + app.SetAction(m_iPad,eAppAction_ExitPlayer); + } + } + else + { + // is it the primary player exiting? + if(m_iPad==ProfileManager.GetPrimaryPad()) + { + int playTime = -1; + if( pMinecraft->localplayers[m_iPad] != NULL ) + { + playTime = (int)pMinecraft->localplayers[m_iPad]->getSessionTimer(); + } + + // adjust the trial time played + ui.ReduceTrialTimerValue(); + + // exit the level + UINT uiIDA[2]; + uiIDA[0]=IDS_CONFIRM_CANCEL; + uiIDA[1]=IDS_CONFIRM_OK; + ui.RequestMessageBox(IDS_EXIT_GAME, IDS_CONFIRM_EXIT_GAME_PROGRESS_LOST, uiIDA, 2, m_iPad,&IUIScene_PauseMenu::ExitGameDialogReturned, dynamic_cast<IUIScene_PauseMenu*>(this), app.GetStringTable(), NULL, 0, false); + + } + else + { + int playTime = -1; + if( pMinecraft->localplayers[m_iPad] != NULL ) + { + playTime = (int)pMinecraft->localplayers[m_iPad]->getSessionTimer(); + } + + TelemetryManager->RecordLevelExit(m_iPad, eSen_LevelExitStatus_Exited); + + // just exit the player + app.SetAction(m_iPad,eAppAction_ExitPlayer); + } + } + } + break; + } +} + +void UIScene_PauseMenu::PerformActionSaveGame() +{ + // is the player trying to save in the trial version? + if(!ProfileManager.IsFullVersion()) + { +#ifdef __ORBIS__ + // If a patch is available, can't buy full game + if (CheckForPatch()) return; +#endif + + // Unlock the full version? + if(!ProfileManager.IsSignedInLive(m_iPad)) + { +#if defined(__PS3__) + m_eAction=eAction_SaveGamePSN; + UINT uiIDA[2]; + uiIDA[0]=IDS_PRO_NOTONLINE_ACCEPT; + uiIDA[1]=IDS_PRO_NOTONLINE_DECLINE; + ui.RequestMessageBox(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_XBOXLIVE_NOTIFICATION, uiIDA, 2, ProfileManager.GetPrimaryPad(),&UIScene_PauseMenu::MustSignInReturnedPSN,this, app.GetStringTable(), NULL, 0, false); +#elif defined(__ORBIS__) + m_eAction=eAction_SaveGamePSN; + int npAvailability = ProfileManager.getNPAvailability(m_iPad); + if (npAvailability == SCE_NP_ERROR_AGE_RESTRICTION) + { + // 4J Stu - This is a bit messy and is due to the library incorrectly returning false for IsSignedInLive is the npAvailability isn't SCE_OK + UINT uiIDA[1]; + uiIDA[0]=IDS_OK; + ui.RequestMessageBox(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, m_iPad, NULL, NULL, app.GetStringTable()); + } + else + // Determine why they're not "signed in live" + if (ProfileManager.isSignedInPSN(m_iPad)) + { + // Signed in to PSN but not connected (no internet access) + assert(!ProfileManager.isConnectedToPSN(m_iPad)); + + UINT uiIDA[1]; + uiIDA[0] = IDS_OK; + ui.RequestMessageBox( IDS_ERROR_NETWORK_TITLE, IDS_ERROR_NETWORK, uiIDA, 1, m_iPad, NULL, NULL, app.GetStringTable()); + } + else + { + // Not signed in to PSN + UINT uiIDA[1]; + uiIDA[0] = IDS_PRO_NOTONLINE_ACCEPT; + ui.RequestMessageBox( IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 1, m_iPad, &UIScene_PauseMenu::MustSignInReturnedPSN, this, app.GetStringTable(), NULL, 0, false); + } +#endif + } + else + { + UINT uiIDA[2]; + uiIDA[0]=IDS_CONFIRM_OK; + uiIDA[1]=IDS_CONFIRM_CANCEL; + ui.RequestMessageBox(IDS_UNLOCK_TITLE, IDS_UNLOCK_TOSAVE_TEXT, uiIDA, 2,m_iPad,&UIScene_PauseMenu::UnlockFullSaveReturned,this,app.GetStringTable(), NULL, 0, false); + } + + return; + } + + // 4J-PB - Is the player trying to save but they are using a trial texturepack ? + if(!Minecraft::GetInstance()->skins->isUsingDefaultSkin()) + { + TexturePack *tPack = Minecraft::GetInstance()->skins->getSelected(); + DLCTexturePack *pDLCTexPack=(DLCTexturePack *)tPack; + + m_pDLCPack=pDLCTexPack->getDLCInfoParentPack();//tPack->getDLCPack(); + + if(!m_pDLCPack->hasPurchasedFile( DLCManager::e_DLCType_Texture, L"" )) + { + // upsell +#ifdef _XBOX + ULONGLONG ullOfferID_Full; + // get the dlc texture pack + DLCTexturePack *pDLCTexPack=(DLCTexturePack *)tPack; + + app.GetDLCFullOfferIDForPackID(pDLCTexPack->getDLCParentPackId(),&ullOfferID_Full); + + // tell sentient about the upsell of the full version of the texture pack + TelemetryManager->RecordUpsellPresented(m_iPad, eSet_UpsellID_Texture_DLC, ullOfferID_Full & 0xFFFFFFFF); +#endif + UINT uiIDA[2]; + uiIDA[0]=IDS_CONFIRM_OK; + uiIDA[1]=IDS_CONFIRM_CANCEL; + + // Give the player a warning about the trial version of the texture pack +#ifdef __PSVITA__ + if(app.DLCInstallProcessCompleted() && !SonyCommerce_Vita::getDLCUpgradePending()) // MGH - devtrack #5861 On vita it can take a bit after the install has finished to register the purchase, so make sure we don't end up asking to purchase again +#endif + { + ui.RequestMessageBox(IDS_WARNING_DLC_TRIALTEXTUREPACK_TITLE, IDS_WARNING_DLC_TRIALTEXTUREPACK_TEXT, uiIDA, 2, m_iPad,&UIScene_PauseMenu::WarningTrialTexturePackReturned,this,app.GetStringTable(), NULL, 0, false); + } + + return; + } + else + { + m_bTrialTexturePack = false; + } + } + + // does the save exist? + bool bSaveExists; + C4JStorage::ESaveGameState result=StorageManager.DoesSaveExist(&bSaveExists); + +#ifdef _XBOX + if(result == C4JStorage::ELoadGame_DeviceRemoved) + { + // this will be a tester trying to be clever + UINT uiIDA[2]; + uiIDA[0]=IDS_SELECTANEWDEVICE; + uiIDA[1]=IDS_NODEVICE_DECLINE; + + ui.RequestMessageBox(IDS_STORAGEDEVICEPROBLEM_TITLE, IDS_FAILED_TO_LOADSAVE_TEXT, uiIDA, 2, m_iPad,&IUIScene_PauseMenu::DeviceRemovedDialogReturned,this, app.GetStringTable(), NULL, 0, false); + } + else +#endif + { +#if defined(_XBOX_ONE) || defined(__ORBIS__) + if(!m_savesDisabled) + { + UINT uiIDA[2]; + uiIDA[0]=IDS_CANCEL; + uiIDA[1]=IDS_CONFIRM_OK; + ui.RequestMessageBox(IDS_TITLE_DISABLE_AUTOSAVE, IDS_CONFIRM_DISABLE_AUTOSAVE, uiIDA, 2, m_iPad,&IUIScene_PauseMenu::DisableAutosaveDialogReturned,this, app.GetStringTable(), NULL, 0, false); + } + else +#endif + // we need to ask if they are sure they want to overwrite the existing game + if(bSaveExists) + { + UINT uiIDA[2]; + uiIDA[0]=IDS_CONFIRM_CANCEL; + uiIDA[1]=IDS_CONFIRM_OK; + ui.RequestMessageBox(IDS_TITLE_SAVE_GAME, IDS_CONFIRM_SAVE_GAME, uiIDA, 2, m_iPad,&IUIScene_PauseMenu::SaveGameDialogReturned,this, app.GetStringTable(), NULL, 0, false); + } + else + { +#if defined(_XBOX_ONE) || defined(__ORBIS__) + UINT uiIDA[2]; + uiIDA[0]=IDS_CONFIRM_CANCEL; + uiIDA[1]=IDS_CONFIRM_OK; + ui.RequestMessageBox(IDS_TITLE_ENABLE_AUTOSAVE, IDS_CONFIRM_ENABLE_AUTOSAVE, uiIDA, 2, m_iPad,&IUIScene_PauseMenu::EnableAutosaveDialogReturned,this, app.GetStringTable(), NULL, 0, false); +#else + // flag a app action of save game + app.SetAction(m_iPad,eAppAction_SaveGame); +#endif + } + } +} + +void UIScene_PauseMenu::ShowScene(bool show) +{ + app.DebugPrintf("UIScene_PauseMenu::ShowScene is not implemented\n"); +} + +void UIScene_PauseMenu::HandleDLCInstalled() +{ + // mounted DLC may have changed + if(app.StartInstallDLCProcess(m_iPad)==false) + { + // not doing a mount, so re-enable input + //m_bIgnoreInput=false; + app.DebugPrintf("UIScene_PauseMenu::HandleDLCInstalled - m_bIgnoreInput false\n"); + } + else + { + // 4J-PB - Somehow, on th edisc build, we get in here, but don't call HandleDLCMountingComplete, so input locks up + //m_bIgnoreInput=true; + app.DebugPrintf("UIScene_PauseMenu::HandleDLCInstalled - m_bIgnoreInput true\n"); + } + // this will send a CustomMessage_DLCMountingComplete when done +} + + +void UIScene_PauseMenu::HandleDLCMountingComplete() +{ + // check if we should display the save option + + //m_bIgnoreInput=false; + app.DebugPrintf("UIScene_PauseMenu::HandleDLCMountingComplete - m_bIgnoreInput false \n"); + + // if(ProfileManager.IsFullVersion()) + // { + // bool bIsisPrimaryHost=g_NetworkManager.IsHost() && (ProfileManager.GetPrimaryPad()==m_iPad); + // + // if(bIsisPrimaryHost) + // { + // m_buttons[BUTTON_PAUSE_SAVEGAME].setEnable(true); + // } + // } +} + +int UIScene_PauseMenu::UnlockFullSaveReturned(void *pParam,int iPad,C4JStorage::EMessageResult result) +{ + UIScene_PauseMenu* pClass = (UIScene_PauseMenu*)pParam; + Minecraft *pMinecraft=Minecraft::GetInstance(); + + if(result==C4JStorage::EMessage_ResultAccept) + { + if(ProfileManager.IsSignedInLive(pMinecraft->player->GetXboxPad())) + { + // 4J-PB - need to check this user can access the store +#if defined(__PS3__) || defined(__PSVITA__) + bool bContentRestricted; + ProfileManager.GetChatAndContentRestrictions(ProfileManager.GetPrimaryPad(),true,NULL,&bContentRestricted,NULL); + if(bContentRestricted) + { + UINT uiIDA[1]; + uiIDA[0]=IDS_CONFIRM_OK; + ui.RequestMessageBox(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, ProfileManager.GetPrimaryPad(),NULL,pClass, app.GetStringTable(), NULL, 0, false); + } + else +#endif + { + ProfileManager.DisplayFullVersionPurchase(false,pMinecraft->player->GetXboxPad(),eSen_UpsellID_Full_Version_Of_Game); + } + } + } + else + { + //SentientManager.RecordUpsellResponded(iPad, eSen_UpsellID_Full_Version_Of_Game, app.m_dwOfferID, eSen_UpsellOutcome_Declined); + } + + return 0; +} + +int UIScene_PauseMenu::SaveGame_SignInReturned(void *pParam,bool bContinue, int iPad) +{ + UIScene_PauseMenu* pClass = (UIScene_PauseMenu*)pParam; + + if(bContinue==true) + { + pClass->PerformActionSaveGame(); + } + + return 0; +} + +#ifdef _XBOX_ONE +int UIScene_PauseMenu::BanGameDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result) +{ + // results switched for this dialog + if(result==C4JStorage::EMessage_ResultDecline) + { + app.SetAction(iPad,eAppAction_BanLevel); + } + return 0; +} +#endif + +#if defined(__PS3__) || defined (__PSVITA__) || defined(__ORBIS__) +int UIScene_PauseMenu::MustSignInReturnedPSN(void *pParam,int iPad,C4JStorage::EMessageResult result) +{ + UIScene_PauseMenu* pClass = (UIScene_PauseMenu*)pParam; + + if(result==C4JStorage::EMessage_ResultAccept) + { +#ifdef __PS3__ + switch(pClass->m_eAction) + { + case eAction_ViewLeaderboardsPSN: + SQRNetworkManager_PS3::AttemptPSNSignIn(&UIScene_PauseMenu::ViewLeaderboards_SignInReturned, pClass); + break; + case eAction_ViewInvitesPSN: + SQRNetworkManager_PS3::AttemptPSNSignIn(&UIScene_PauseMenu::ViewInvites_SignInReturned, pClass); + break; + case eAction_SaveGamePSN: + SQRNetworkManager_PS3::AttemptPSNSignIn(&UIScene_PauseMenu::SaveGame_SignInReturned, pClass); + break; + case eAction_BuyTexturePackPSN: + SQRNetworkManager_PS3::AttemptPSNSignIn(&UIScene_PauseMenu::BuyTexturePack_SignInReturned, pClass); + break; + } +#elif defined __PSVITA__ + switch(pClass->m_eAction) + { + case eAction_ViewLeaderboardsPSN: + //CD - Must force Ad-Hoc off if they want leaderboard PSN sign-in + //Save settings change + app.SetGameSettings(0, eGameSetting_PSVita_NetworkModeAdhoc, 0); + //Force off + CGameNetworkManager::setAdhocMode(false); + //Now Sign-in + SQRNetworkManager_Vita::AttemptPSNSignIn(&UIScene_PauseMenu::ViewLeaderboards_SignInReturned, pClass); + break; + case eAction_ViewInvitesPSN: + SQRNetworkManager_Vita::AttemptPSNSignIn(&UIScene_PauseMenu::ViewInvites_SignInReturned, pClass); + break; + case eAction_SaveGamePSN: + SQRNetworkManager_Vita::AttemptPSNSignIn(&UIScene_PauseMenu::SaveGame_SignInReturned, pClass); + break; + case eAction_BuyTexturePackPSN: + SQRNetworkManager_Vita::AttemptPSNSignIn(&UIScene_PauseMenu::BuyTexturePack_SignInReturned, pClass); + break; + } +#else + switch(pClass->m_eAction) + { + case eAction_ViewLeaderboardsPSN: + SQRNetworkManager_Orbis::AttemptPSNSignIn(&UIScene_PauseMenu::ViewLeaderboards_SignInReturned, pClass, false, iPad); + break; + case eAction_ViewInvitesPSN: + SQRNetworkManager_Orbis::AttemptPSNSignIn(&UIScene_PauseMenu::ViewInvites_SignInReturned, pClass, false, iPad); + break; + case eAction_SaveGamePSN: + SQRNetworkManager_Orbis::AttemptPSNSignIn(&UIScene_PauseMenu::SaveGame_SignInReturned, pClass, false, iPad); + break; + case eAction_BuyTexturePackPSN: + SQRNetworkManager_Orbis::AttemptPSNSignIn(&UIScene_PauseMenu::BuyTexturePack_SignInReturned, pClass, false, iPad); + break; + } +#endif + } + + return 0; +} + +int UIScene_PauseMenu::ViewLeaderboards_SignInReturned(void *pParam,bool bContinue, int iPad) +{ + UIScene_PauseMenu* pClass = (UIScene_PauseMenu*)pParam; + + if(bContinue==true) + { + UINT uiIDA[1]; + uiIDA[0]=IDS_CONFIRM_OK; + + // guests can't look at leaderboards + if(ProfileManager.IsGuest(pClass->m_iPad)) + { + ui.RequestMessageBox(IDS_PRO_GUESTPROFILE_TITLE, IDS_PRO_GUESTPROFILE_TEXT, uiIDA, 1, ProfileManager.GetPrimaryPad(),NULL,NULL, app.GetStringTable(), NULL, 0, false); + } + else if(ProfileManager.IsSignedInLive(iPad)) + { +#ifndef __ORBIS__ + bool bContentRestricted=false; + ProfileManager.GetChatAndContentRestrictions(pClass->m_iPad,true,NULL,&bContentRestricted,NULL); + if(bContentRestricted) + { + // you can't see leaderboards + ui.RequestMessageBox(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, ProfileManager.GetPrimaryPad(),NULL,pClass, app.GetStringTable(), NULL, 0, false); + } + else +#endif + { + ui.NavigateToScene(pClass->m_iPad, eUIScene_LeaderboardsMenu); + } + } + } + + return 0; +} + +int UIScene_PauseMenu::WarningTrialTexturePackReturned(void *pParam,int iPad,C4JStorage::EMessageResult result) +{ + UIScene_PauseMenu* pClass = (UIScene_PauseMenu*)pParam; + +#ifdef __ORBIS__ + // If a patch is available, can't proceed + if (pClass->CheckForPatch()) return 0; +#endif + +#if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__) + if(result==C4JStorage::EMessage_ResultAccept) + { + if(!ProfileManager.IsSignedInLive(iPad)) + { + pClass->m_eAction=eAction_SaveGamePSN; +#ifdef __ORBIS__// Check if PSN is unavailable because of age restriction + int npAvailability = ProfileManager.getNPAvailability(iPad); + if (npAvailability == SCE_NP_ERROR_AGE_RESTRICTION) + { + // 4J Stu - This is a bit messy and is due to the library incorrectly returning false for IsSignedInLive is the npAvailability isn't SCE_OK + UINT uiIDA[1]; + uiIDA[0]=IDS_OK; + ui.RequestMessageBox(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, iPad, NULL, NULL, app.GetStringTable()); + } + else + // Determine why they're not "signed in live" + if (ProfileManager.isSignedInPSN(iPad)) + { + // Signed in to PSN but not connected (no internet access) + assert(!ProfileManager.isConnectedToPSN(iPad)); + + UINT uiIDA[1]; + uiIDA[0] = IDS_OK; + ui.RequestMessageBox( IDS_ERROR_NETWORK_TITLE, IDS_ERROR_NETWORK, uiIDA, 1, iPad, NULL, NULL, app.GetStringTable()); + } + else + { + UINT uiIDA[1]; + uiIDA[0] = IDS_PRO_NOTONLINE_ACCEPT; + ui.RequestMessageBox( IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 1, iPad, &UIScene_PauseMenu::MustSignInReturnedPSN, pClass, app.GetStringTable(), NULL, 0, false); + } +#else // __PS3__ + // You're not signed in to PSN! + UINT uiIDA[2]; + uiIDA[0]=IDS_PRO_NOTONLINE_ACCEPT; + uiIDA[1]=IDS_PRO_NOTONLINE_DECLINE; + ui.RequestMessageBox(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_XBOXLIVE_NOTIFICATION, uiIDA, 2, iPad,&UIScene_PauseMenu::MustSignInReturnedPSN,pClass, app.GetStringTable(), NULL, 0, false); +#endif + } + else + { +#ifndef __ORBIS__ + // 4J-PB - need to check this user can access the store + bool bContentRestricted=false; + ProfileManager.GetChatAndContentRestrictions(ProfileManager.GetPrimaryPad(),true,NULL,&bContentRestricted,NULL); + if(bContentRestricted) + { + UINT uiIDA[1]; + uiIDA[0]=IDS_CONFIRM_OK; + ui.RequestMessageBox(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, iPad,NULL,pClass, app.GetStringTable(), NULL, 0, false); + } + else +#endif + { + // need to get info on the pack to see if the user has already downloaded it + TexturePack *tPack = Minecraft::GetInstance()->skins->getSelected(); + DLCTexturePack *pDLCTexPack=(DLCTexturePack *)tPack; + + // retrieve the store name for the skin pack + DLCPack *pDLCPack=pDLCTexPack->getDLCInfoParentPack();//tPack->getDLCPack(); + const char *pchPackName=wstringtofilename(pDLCPack->getName()); + app.DebugPrintf("Texture Pack - %s\n",pchPackName); + SONYDLC *pSONYDLCInfo=app.GetSONYDLCInfo((char *)pchPackName); + + if(pSONYDLCInfo!=NULL) + { + char chName[42]; + char chKeyName[20]; + char chSkuID[SCE_NP_COMMERCE2_SKU_ID_LEN]; + + memset(chSkuID,0,SCE_NP_COMMERCE2_SKU_ID_LEN); + // find the info on the skin pack + // we have to retrieve the skuid from the store info, it can't be hardcoded since Sony may change it. + // So we assume the first sku for the product is the one we want + + // MGH - keyname in the DLC file is 16 chars long, but there's no space for a NULL terminating char + memset(chKeyName, 0, sizeof(chKeyName)); + strncpy(chKeyName, pSONYDLCInfo->chDLCKeyname, 16); + +#ifdef __ORBIS__ + strcpy(chName, chKeyName); +#else + sprintf(chName,"%s-%s",app.GetCommerceCategory(),chKeyName); +#endif + app.GetDLCSkuIDFromProductList(chName,chSkuID); + + // 4J-PB - need to check for an empty store +#if defined __ORBIS__ || defined __PSVITA__ || defined __PS3__ + if(app.CheckForEmptyStore(iPad)==false) +#endif + { + if(app.DLCAlreadyPurchased(chSkuID)) + { + app.DownloadAlreadyPurchased(chSkuID); + } + else + { + app.Checkout(chSkuID); + } + } + } + } + } + } +#endif // + + return 0; +} + +int UIScene_PauseMenu::BuyTexturePack_SignInReturned(void *pParam,bool bContinue, int iPad) +{ + UIScene_PauseMenu* pClass = (UIScene_PauseMenu*)pParam; + + if(bContinue==true) + { + // Check if we're signed in to LIVE + if(ProfileManager.IsSignedInLive(iPad)) + { +#if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__) + +#ifndef __ORBIS__ + // 4J-PB - need to check this user can access the store + bool bContentRestricted=false; + ProfileManager.GetChatAndContentRestrictions(iPad,true,NULL,&bContentRestricted,NULL); + if(bContentRestricted) + { + UINT uiIDA[1]; + uiIDA[0]=IDS_CONFIRM_OK; + ui.RequestMessageBox(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, iPad,NULL,pClass, app.GetStringTable(), NULL, 0, false); + } + else +#endif + { + // need to get info on the pack to see if the user has already downloaded it + TexturePack *tPack = Minecraft::GetInstance()->skins->getSelected(); + DLCTexturePack *pDLCTexPack=(DLCTexturePack *)tPack; + + // retrieve the store name for the skin pack + DLCPack *pDLCPack=pDLCTexPack->getDLCInfoParentPack();//tPack->getDLCPack(); + const char *pchPackName=wstringtofilename(pDLCPack->getName()); + app.DebugPrintf("Texture Pack - %s\n",pchPackName); + SONYDLC *pSONYDLCInfo=app.GetSONYDLCInfo((char *)pchPackName); + + if(pSONYDLCInfo!=NULL) + { + char chName[42]; + char chKeyName[20]; + char chSkuID[SCE_NP_COMMERCE2_SKU_ID_LEN]; + + memset(chSkuID,0,SCE_NP_COMMERCE2_SKU_ID_LEN); + // find the info on the skin pack + // we have to retrieve the skuid from the store info, it can't be hardcoded since Sony may change it. + // So we assume the first sku for the product is the one we want + + // MGH - keyname in the DLC file is 16 chars long, but there's no space for a NULL terminating char + memset(chKeyName, 0, sizeof(chKeyName)); + strncpy(chKeyName, pSONYDLCInfo->chDLCKeyname, 16); + +#ifdef __ORBIS__ + strcpy(chName, chKeyName); +#else + sprintf(chName,"%s-%s",app.GetCommerceCategory(),chKeyName); +#endif + app.GetDLCSkuIDFromProductList(chName,chSkuID); + + // 4J-PB - need to check for an empty store +#if defined __ORBIS__ || defined __PSVITA__ || defined __PS3__ + if(app.CheckForEmptyStore(iPad)==false) +#endif + { + if(app.DLCAlreadyPurchased(chSkuID)) + { + app.DownloadAlreadyPurchased(chSkuID); + } + else + { + app.Checkout(chSkuID); + } + } + } + } +#else + // TO BE IMPEMENTED FOR ORBIS +#endif + } + } + return 0; +} + +int UIScene_PauseMenu::ViewInvites_SignInReturned(void *pParam,bool bContinue, int iPad) +{ + if(bContinue==true) + { + // Check if we're signed in to LIVE + if(ProfileManager.IsSignedInLive(iPad)) + { +#ifdef __ORBIS__ + SQRNetworkManager_Orbis::RecvInviteGUI(); +#elif defined __PS3__ + int ret = sceNpBasicRecvMessageCustom(SCE_NP_BASIC_MESSAGE_MAIN_TYPE_INVITE, SCE_NP_BASIC_RECV_MESSAGE_OPTIONS_INCLUDE_BOOTABLE, SYS_MEMORY_CONTAINER_ID_INVALID); + app.DebugPrintf("sceNpBasicRecvMessageCustom return %d ( %08x )\n", ret, ret); +#else // __PSVITA__ + PSVITA_STUBBED; +#endif + } + } + return 0; +} + + +int UIScene_PauseMenu::ExitGameSaveDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result) +{ + UIScene_PauseMenu *pClass = (UIScene_PauseMenu *)pParam; + // Exit with or without saving + // Decline means save in this dialog + if(result==C4JStorage::EMessage_ResultDecline || result==C4JStorage::EMessage_ResultThirdOption) + { + if( result==C4JStorage::EMessage_ResultDecline ) // Save + { + // 4J-PB - Is the player trying to save but they are using a trial texturepack ? + if(!Minecraft::GetInstance()->skins->isUsingDefaultSkin()) + { + TexturePack *tPack = Minecraft::GetInstance()->skins->getSelected(); + DLCTexturePack *pDLCTexPack=(DLCTexturePack *)tPack; + + DLCPack *pDLCPack=pDLCTexPack->getDLCInfoParentPack();//tPack->getDLCPack(); + if(!pDLCPack->hasPurchasedFile( DLCManager::e_DLCType_Texture, L"" )) + { +#ifdef _XBOX + // upsell + ULONGLONG ullOfferID_Full; + // get the dlc texture pack + DLCTexturePack *pDLCTexPack=(DLCTexturePack *)tPack; + + app.GetDLCFullOfferIDForPackID(pDLCTexPack->getDLCParentPackId(),&ullOfferID_Full); + + // tell sentient about the upsell of the full version of the skin pack + TelemetryManager->RecordUpsellPresented(iPad, eSet_UpsellID_Texture_DLC, ullOfferID_Full & 0xFFFFFFFF); +#endif + + UINT uiIDA[2]; + uiIDA[0]=IDS_CONFIRM_OK; + uiIDA[1]=IDS_CONFIRM_CANCEL; + + // Give the player a warning about the trial version of the texture pack + ui.RequestMessageBox(IDS_WARNING_DLC_TRIALTEXTUREPACK_TITLE, IDS_WARNING_DLC_TRIALTEXTUREPACK_TEXT, uiIDA, 2, ProfileManager.GetPrimaryPad() ,&UIScene_PauseMenu::WarningTrialTexturePackReturned, dynamic_cast<IUIScene_PauseMenu*>(pClass),app.GetStringTable(), NULL, 0, false); + + return S_OK; + } + } + + // does the save exist? + bool bSaveExists; + StorageManager.DoesSaveExist(&bSaveExists); + // 4J-PB - we check if the save exists inside the libs + // we need to ask if they are sure they want to overwrite the existing game + if(bSaveExists) + { + UINT uiIDA[2]; + uiIDA[0]=IDS_CONFIRM_CANCEL; + uiIDA[1]=IDS_CONFIRM_OK; + ui.RequestMessageBox(IDS_TITLE_SAVE_GAME, IDS_CONFIRM_SAVE_GAME, uiIDA, 2, ProfileManager.GetPrimaryPad(),&IUIScene_PauseMenu::ExitGameAndSaveReturned, dynamic_cast<IUIScene_PauseMenu*>(pClass), app.GetStringTable(), NULL, 0, false); + return 0; + } + else + { +#if defined(_XBOX_ONE) || defined(__ORBIS__) + StorageManager.SetSaveDisabled(false); +#endif + MinecraftServer::getInstance()->setSaveOnExit( true ); + } + } + else + { + // been a few requests for a confirm on exit without saving + UINT uiIDA[2]; + uiIDA[0]=IDS_CONFIRM_CANCEL; + uiIDA[1]=IDS_CONFIRM_OK; + ui.RequestMessageBox(IDS_TITLE_DECLINE_SAVE_GAME, IDS_CONFIRM_DECLINE_SAVE_GAME, uiIDA, 2, ProfileManager.GetPrimaryPad(),&IUIScene_PauseMenu::ExitGameDeclineSaveReturned, dynamic_cast<IUIScene_PauseMenu*>(pClass), app.GetStringTable(), NULL, 0, false); + return 0; + } + + app.SetAction(iPad,eAppAction_ExitWorld); + } + return 0; +} + +#endif + +void UIScene_PauseMenu::SetIgnoreInput(bool ignoreInput) +{ + m_bIgnoreInput = ignoreInput; +} + +#ifdef _XBOX_ONE +void UIScene_PauseMenu::HandleDLCLicenseChange() +{ +} +#endif + +#ifdef __ORBIS__ +bool UIScene_PauseMenu::CheckForPatch() +{ + int npAvailability = ProfileManager.getNPAvailability(ProfileManager.GetPrimaryPad()); + + bool bPatchAvailable; + switch(npAvailability) + { + case SCE_NP_ERROR_LATEST_PATCH_PKG_EXIST: + case SCE_NP_ERROR_LATEST_PATCH_PKG_DOWNLOADED: + bPatchAvailable=true; + break; + default: + bPatchAvailable=false; + break; + } + + if(bPatchAvailable) + { + int32_t ret = sceErrorDialogInitialize(); + if ( ret==SCE_OK ) + { + m_bErrorDialogRunning = true; + + SceErrorDialogParam param; + sceErrorDialogParamInitialize( ¶m ); + // 4J-PB - We want to display the option to get the patch now + param.errorCode = SCE_NP_ERROR_LATEST_PATCH_PKG_DOWNLOADED;//pClass->m_errorCode; + ret = sceUserServiceGetInitialUser( ¶m.userId ); + if ( ret == SCE_OK ) + { + ret = sceErrorDialogOpen( ¶m ); + } + else + { + sceErrorDialogTerminate(); + } + } + } + + return bPatchAvailable; +} +#endif
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIScene_PauseMenu.h b/Minecraft.Client/Common/UI/UIScene_PauseMenu.h new file mode 100644 index 00000000..f1bd53aa --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_PauseMenu.h @@ -0,0 +1,112 @@ +#pragma once + +#include "UIScene.h" +#include "IUIScene_PauseMenu.h" + +#define BUTTON_PAUSE_RESUMEGAME 0 +#define BUTTON_PAUSE_HELPANDOPTIONS 1 +#define BUTTON_PAUSE_LEADERBOARDS 2 + +#ifdef _XBOX_ONE +#define BUTTON_PAUSE_XBOXHELP 3 +#else +#define BUTTON_PAUSE_ACHIEVEMENTS 3 +#endif + +#define BUTTON_PAUSE_SAVEGAME 4 +#define BUTTON_PAUSE_EXITGAME 5 +#define BUTTONS_PAUSE_MAX BUTTON_PAUSE_EXITGAME + 1 + +class UIScene_PauseMenu : public UIScene, public IUIScene_PauseMenu +{ +private: + bool m_savesDisabled; + bool m_bTrialTexturePack; + bool m_bErrorDialogRunning; + + enum eActions + { + eAction_None=0, +#if defined(__PS3__) || defined(__PSVITA__) || defined(__ORBIS__) + eAction_ViewLeaderboardsPSN, + eAction_ViewInvitesPSN, + eAction_SaveGamePSN, + eAction_BuyTexturePackPSN +#endif + + }; + eActions m_eAction; + + UIControl_Button m_buttons[BUTTONS_PAUSE_MAX]; + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) + UI_MAP_ELEMENT( m_buttons[BUTTON_PAUSE_RESUMEGAME], "Button1") + UI_MAP_ELEMENT( m_buttons[BUTTON_PAUSE_HELPANDOPTIONS], "Button2") + UI_MAP_ELEMENT( m_buttons[BUTTON_PAUSE_LEADERBOARDS], "Button3") +#ifdef _DURANGO + UI_MAP_ELEMENT( m_buttons[BUTTON_PAUSE_XBOXHELP], "Button4") +#else + UI_MAP_ELEMENT( m_buttons[BUTTON_PAUSE_ACHIEVEMENTS], "Button4") +#endif + UI_MAP_ELEMENT( m_buttons[BUTTON_PAUSE_SAVEGAME], "Button5") + UI_MAP_ELEMENT( m_buttons[BUTTON_PAUSE_EXITGAME], "Button6") + UI_END_MAP_ELEMENTS_AND_NAMES() + + virtual void HandleDLCMountingComplete(); + virtual void HandleDLCInstalled(); +#ifdef _XBOX_ONE + virtual void HandleDLCLicenseChange(); +#endif + static int UnlockFullSaveReturned(void *pParam,int iPad,C4JStorage::EMessageResult result); + static int SaveGame_SignInReturned(void *pParam,bool bContinue, int iPad); + +public: + UIScene_PauseMenu(int iPad, void *initData, UILayer *parentLayer); + virtual ~UIScene_PauseMenu(); + + virtual EUIScene getSceneType() { return eUIScene_PauseMenu;} + + virtual void tick(); + + virtual void updateTooltips(); + virtual void updateComponents(); + virtual void handlePreReload(); + virtual void handleReload(); + +protected: + void updateControlsVisibility(); + + // TODO: This should be pure virtual in this class + virtual wstring getMoviePath(); + +public: + // INPUT + virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled); + +protected: + void handlePress(F64 controlId, F64 childId); + virtual void ShowScene(bool show); + virtual void SetIgnoreInput(bool ignoreInput); + bool m_bIgnoreInput; + +private: + void PerformActionSaveGame(); + +#if defined(__PS3__) || defined(__PSVITA__) || defined(__ORBIS__) + static int MustSignInReturnedPSN(void *pParam,int iPad,C4JStorage::EMessageResult result); + static int ViewLeaderboards_SignInReturned(void *pParam,bool bContinue, int iPad); + static int ViewInvites_SignInReturned(void *pParam,bool bContinue, int iPad); + static int BuyTexturePack_SignInReturned(void *pParam,bool bContinue, int iPad); + static int WarningTrialTexturePackReturned(void *pParam,int iPad,C4JStorage::EMessageResult result); + static int ExitGameSaveDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result); +#endif + +protected: +#ifdef _XBOX_ONE + static int BanGameDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result); + virtual long long getDefaultGtcButtons() { return _360_GTC_BACK | _360_GTC_PLAY; } +#endif + +#ifdef __ORBIS__ + bool CheckForPatch(); +#endif +}; diff --git a/Minecraft.Client/Common/UI/UIScene_QuadrantSignin.cpp b/Minecraft.Client/Common/UI/UIScene_QuadrantSignin.cpp new file mode 100644 index 00000000..4f1b9742 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_QuadrantSignin.cpp @@ -0,0 +1,291 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIScene_QuadrantSignin.h" +#include "..\..\Minecraft.h" +#if defined(__ORBIS__) +#include "Common\Network\Sony\SonyHttp.h" +#endif + +UIScene_QuadrantSignin::UIScene_QuadrantSignin(int iPad, void *_initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) +{ + // Setup all the Iggy references we need for this scene + initialiseMovie(); + + m_signInInfo = *((SignInInfo *)_initData); + + m_bIgnoreInput = false; + + m_lastRequestedAvatar = -1; + for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i) + { + m_iconRequested[i] = false; + + m_labelPressToJoin[i].init(app.GetString(IDS_MUST_SIGN_IN_TITLE)); + m_labelConnectController[i].init(L""); + m_labelAccountType[i].init(L""); + + //wchar_t num[2]; + //swprintf(num,2,L"%d",i+1); + //m_labelPlayerNumber[i].init(num); + + m_controllerStatus[i] = eControllerStatus_ConnectController; + + if(ProfileManager.IsSignedIn(i)) + { + app.DebugPrintf("Index %d is signed in\n", i); + + setControllerState(i, eControllerStatus_PlayerDetails); + m_labelDisplayName[i].init(ProfileManager.GetDisplayName(i)); + } + else if(InputManager.IsPadConnected(i)) + { + app.DebugPrintf("Index %d is not signed in\n", i); + + setControllerState(i, eControllerStatus_PressToJoin); + m_labelDisplayName[i].init(L""); + } + else + { + app.DebugPrintf("Index %d is not connected\n", i); + + setControllerState(i, eControllerStatus_ConnectController); + } + } + +#if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__) + if(InputManager.IsCircleCrossSwapped()) + { + IggyDataValue result; + IggyDataValue value[1]; + value[0].type = IGGY_DATATYPE_boolean; + value[0].boolval = true; + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcSetABSwap , 1 , value ); + } +#endif + + parentLayer->addComponent(iPad,eUIComponent_MenuBackground); +} + +UIScene_QuadrantSignin::~UIScene_QuadrantSignin() +{ + m_parentLayer->removeComponent(eUIComponent_MenuBackground); +} + +wstring UIScene_QuadrantSignin::getMoviePath() +{ + return L"QuadrantSignin"; +} + +void UIScene_QuadrantSignin::updateTooltips() +{ + ui.SetTooltips(m_iPad, IDS_TOOLTIPS_CONTINUE, IDS_TOOLTIPS_CANCEL); +} + +// Returns true if this scene has focus for the pad passed in +bool UIScene_QuadrantSignin::hasFocus(int iPad) +{ + // Allow input from any controller + return bHasFocus; +} + +bool UIScene_QuadrantSignin::hidesLowerScenes() +{ + // This is a Modal dialog, so don't need to hide the scene behind + return false; +} + +void UIScene_QuadrantSignin::tick() +{ + UIScene::tick(); + + updateState(); +} + +void UIScene_QuadrantSignin::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled) +{ + app.DebugPrintf("UIScene_QuadrantSignin handling input for pad %d, key %d, repeat- %s, pressed- %s, released- %s\n", iPad, key, repeat?"TRUE":"FALSE", pressed?"TRUE":"FALSE", released?"TRUE":"FALSE"); + + if(!m_bIgnoreInput) + { + ui.AnimateKeyPress(m_iPad, key, repeat, pressed, released); + + switch(key) + { + case ACTION_MENU_CANCEL: + { + if(pressed) + { +#ifdef _DURANGO + if(InputManager.IsPadLocked(iPad)) + { + if(iPad != ProfileManager.GetPrimaryPad()) + { + ProfileManager.RemoveGamepadFromGame(iPad); + } + else +#endif + { + m_bIgnoreInput = true; + m_signInInfo.Func(m_signInInfo.lpParam,false,iPad); + ProfileManager.CancelProfileAvatarRequest(); + + navigateBack(); + } + } +#ifdef _DURANGO + } +#endif + } + break; + case ACTION_MENU_OK: +#ifdef __ORBIS__ + case ACTION_MENU_TOUCHPAD_PRESS: +#endif + if(pressed) + { + m_bIgnoreInput = true; + if(ProfileManager.IsSignedIn(iPad)) + { + app.DebugPrintf("Signed in pad pressed\n"); + ProfileManager.CancelProfileAvatarRequest(); + +#ifdef _DURANGO + // On Durango, if we don't navigate forward here, then when we are on the main menu, it (re)gains focus & that causes our users to get cleared + ui.NavigateToScene(m_iPad, eUIScene_Timer); +#endif + navigateBack(); + m_signInInfo.Func(m_signInInfo.lpParam,true,m_iPad); + } + else + { + app.DebugPrintf("Non-signed in pad pressed\n"); + ProfileManager.RequestSignInUI(false, false, false, true, true,&UIScene_QuadrantSignin::SignInReturned, this, iPad); + } + } + break; + case ACTION_MENU_UP: + case ACTION_MENU_DOWN: + if(pressed) + { + sendInputToMovie(key, repeat, pressed, released); + } + break; + } + } + + handled = true; +} + +int UIScene_QuadrantSignin::SignInReturned(void *pParam,bool bContinue, int iPad) +{ + app.DebugPrintf("SignInReturned for pad %d\n", iPad); + + UIScene_QuadrantSignin *pClass = (UIScene_QuadrantSignin *)pParam; + +#ifdef _DURANGO + if(bContinue && pClass->m_signInInfo.requireOnline && ProfileManager.IsSignedIn(iPad)) + { + ProfileManager.CheckMultiplayerPrivileges(iPad, true, &checkAllPrivilegesCallback, pClass); + } + else +#endif + { + pClass->m_bIgnoreInput = false; + pClass->updateState(); + } + + return 0; +} + +#ifdef _DURANGO +void UIScene_QuadrantSignin::checkAllPrivilegesCallback(LPVOID lpParam, bool hasPrivileges, int iPad) +{ + UIScene_QuadrantSignin* pClass = (UIScene_QuadrantSignin*)lpParam; + + if(!hasPrivileges) + { + ProfileManager.RemoveGamepadFromGame(iPad); + } + pClass->m_bIgnoreInput = false; + pClass->updateState(); +} +#endif + +void UIScene_QuadrantSignin::updateState() +{ + for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i) + { + if(ProfileManager.IsSignedIn(i) && InputManager.IsPadConnected(i)) + { + //app.DebugPrintf("Index %d is signed in, display name - '%s'\n", i, ProfileManager.GetDisplayName(i).data()); + + setControllerState(i, eControllerStatus_PlayerDetails); + m_labelDisplayName[i].setLabel(ProfileManager.GetDisplayName(i)); + //m_buttonControllers[i].setLabel(app.GetString(IDS_TOOLTIPS_CONTINUE),i); + + if(!m_iconRequested[i]) + { + app.DebugPrintf(app.USER_SR, "Requesting avatar for %d\n", i); + if(ProfileManager.GetProfileAvatar(i, &UIScene_QuadrantSignin::AvatarReturned, this)) + { + m_iconRequested[i] = true; + m_lastRequestedAvatar = i; + } + } + } + else if(InputManager.IsPadConnected(i)) + { + //app.DebugPrintf("Index %d is not signed in\n", i); + + setControllerState(i, eControllerStatus_PressToJoin); + m_labelDisplayName[i].setLabel(L""); + m_iconRequested[i] = false; + } + else + { + //app.DebugPrintf("Index %d is not connected\n", i); + + setControllerState(i, eControllerStatus_ConnectController); + m_iconRequested[i] = false; + } + } +} + +void UIScene_QuadrantSignin::setControllerState(int iPad, EControllerStatus state) +{ + if(m_controllerStatus[iPad] != state) + { + m_controllerStatus[iPad] = state; + + IggyDataValue result; + IggyDataValue value[2]; + value[0].type = IGGY_DATATYPE_number; + value[0].number = iPad; + + value[1].type = IGGY_DATATYPE_number; + value[1].number = (int)state; + + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcSetControllerStatus , 2 , value ); + } +} + +int UIScene_QuadrantSignin::AvatarReturned(LPVOID lpParam,PBYTE pbThumbnail,DWORD dwThumbnailBytes) +{ + UIScene_QuadrantSignin *pClass = (UIScene_QuadrantSignin *)lpParam; + app.DebugPrintf(app.USER_SR,"AvatarReturned callback\n"); + if(pbThumbnail != NULL) + { + // 4J-JEV - Added to ensure each new texture gets a unique name. + static unsigned int quadrantImageCount = 0; + + wchar_t iconName[32]; + swprintf(iconName,32,L"quadrantImage%05d",quadrantImageCount++); + + pClass->registerSubstitutionTexture(iconName,pbThumbnail,dwThumbnailBytes,true); + pClass->m_bitmapIcon[pClass->m_lastRequestedAvatar].setTextureName(iconName); + } + + pClass->m_lastRequestedAvatar = -1; + + return 0; +} diff --git a/Minecraft.Client/Common/UI/UIScene_QuadrantSignin.h b/Minecraft.Client/Common/UI/UIScene_QuadrantSignin.h new file mode 100644 index 00000000..b500fcc3 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_QuadrantSignin.h @@ -0,0 +1,110 @@ +#pragma once + +#include "UIScene.h" + +class UIScene_QuadrantSignin : public UIScene +{ +private: + enum EControllerStatus + { + eControllerStatus_ConnectController, + eControllerStatus_PressToJoin, + eControllerStatus_PlayerDetails + }; + + bool m_bIgnoreInput; + SignInInfo m_signInInfo; + + EControllerStatus m_controllerStatus[4]; + bool m_iconRequested[4]; + + int m_lastRequestedAvatar; + + UIControl m_controlPanels[4]; + UIControl_Label m_labelPressToJoin[4], m_labelDisplayName[4], m_labelAccountType[4], m_labelPlayerNumber[4], m_labelConnectController[4]; + UIControl_BitmapIcon m_bitmapIcon[4]; + IggyName m_funcJoinButtonPressed, m_funcSetControllerStatus, m_funcSetABSwap; + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) + UI_MAP_ELEMENT(m_controlPanels[0],"Controller1") + UI_BEGIN_MAP_CHILD_ELEMENTS(m_controlPanels[0]) + UI_MAP_ELEMENT(m_labelPressToJoin[0], "PressLabel") + + UI_MAP_ELEMENT(m_labelDisplayName[0], "GamerTag") + UI_MAP_ELEMENT(m_labelAccountType[0], "AccountType") + UI_MAP_ELEMENT(m_labelPlayerNumber[0], "PlayerNumber") + UI_MAP_ELEMENT(m_bitmapIcon[0], "PlayerPic") + + UI_MAP_ELEMENT(m_labelConnectController[0], "ConnectControllerLabel") + UI_END_MAP_CHILD_ELEMENTS() + + UI_MAP_ELEMENT(m_controlPanels[1],"Controller2") + UI_BEGIN_MAP_CHILD_ELEMENTS(m_controlPanels[1]) + UI_MAP_ELEMENT(m_labelPressToJoin[1], "PressLabel") + + UI_MAP_ELEMENT(m_labelDisplayName[1], "GamerTag") + UI_MAP_ELEMENT(m_labelAccountType[1], "AccountType") + UI_MAP_ELEMENT(m_labelPlayerNumber[1], "PlayerNumber") + UI_MAP_ELEMENT(m_bitmapIcon[1], "PlayerPic") + + UI_MAP_ELEMENT(m_labelConnectController[1], "ConnectControllerLabel") + UI_END_MAP_CHILD_ELEMENTS() + + UI_MAP_ELEMENT(m_controlPanels[2],"Controller3") + UI_BEGIN_MAP_CHILD_ELEMENTS(m_controlPanels[2]) + UI_MAP_ELEMENT(m_labelPressToJoin[2], "PressLabel") + + UI_MAP_ELEMENT(m_labelDisplayName[2], "GamerTag") + UI_MAP_ELEMENT(m_labelAccountType[2], "AccountType") + UI_MAP_ELEMENT(m_labelPlayerNumber[2], "PlayerNumber") + UI_MAP_ELEMENT(m_bitmapIcon[2], "PlayerPic") + + UI_MAP_ELEMENT(m_labelConnectController[2], "ConnectControllerLabel") + UI_END_MAP_CHILD_ELEMENTS() + + UI_MAP_ELEMENT(m_controlPanels[3],"Controller4") + UI_BEGIN_MAP_CHILD_ELEMENTS(m_controlPanels[3]) + UI_MAP_ELEMENT(m_labelPressToJoin[3], "PressLabel") + + UI_MAP_ELEMENT(m_labelDisplayName[3], "GamerTag") + UI_MAP_ELEMENT(m_labelAccountType[3], "AccountType") + UI_MAP_ELEMENT(m_labelPlayerNumber[3], "PlayerNumber") + UI_MAP_ELEMENT(m_bitmapIcon[3], "PlayerPic") + + UI_MAP_ELEMENT(m_labelConnectController[3], "ConnectControllerLabel") + UI_END_MAP_CHILD_ELEMENTS() + + UI_MAP_NAME(m_funcJoinButtonPressed, L"JoinButtonPressed") + UI_MAP_NAME(m_funcSetControllerStatus, L"SetControllerStatus") + UI_MAP_NAME(m_funcSetABSwap, L"SetABSwap") + UI_END_MAP_ELEMENTS_AND_NAMES() +public: + UIScene_QuadrantSignin(int iPad, void *initData, UILayer *parentLayer); + ~UIScene_QuadrantSignin(); + + virtual EUIScene getSceneType() { return eUIScene_QuadrantSignin;} + virtual void updateTooltips(); + + virtual bool hasFocus(int iPad); + virtual bool hidesLowerScenes(); + + void tick(); + +protected: + // TODO: This should be pure virtual in this class + virtual wstring getMoviePath(); + +public: + // INPUT + virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled); + +private: + static int SignInReturned(void *pParam,bool bContinue, int iPad); + static int AvatarReturned(LPVOID lpParam,PBYTE pbThumbnail,DWORD dwThumbnailBytes); + + void updateState(); + void setControllerState(int iPad, EControllerStatus state); + +#ifdef _DURANGO + static void checkAllPrivilegesCallback(LPVOID lpParam, bool hasPrivileges, int iPad); +#endif +}; diff --git a/Minecraft.Client/Common/UI/UIScene_ReinstallMenu.cpp b/Minecraft.Client/Common/UI/UIScene_ReinstallMenu.cpp new file mode 100644 index 00000000..3b67f79e --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_ReinstallMenu.cpp @@ -0,0 +1,110 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIScene_ReinstallMenu.h" + +UIScene_ReinstallMenu::UIScene_ReinstallMenu(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) +{ + // Setup all the Iggy references we need for this scene + initialiseMovie(); + +#if TO_BE_IMPLEMENTED + XuiControlSetText(m_Buttons[eControl_Theme],app.GetString(IDS_REINSTALL_THEME)); + XuiControlSetText(m_Buttons[eControl_Gamerpic1],app.GetString(IDS_REINSTALL_GAMERPIC_1)); + XuiControlSetText(m_Buttons[eControl_Gamerpic2],app.GetString(IDS_REINSTALL_GAMERPIC_2)); + XuiControlSetText(m_Buttons[eControl_Avatar1],app.GetString(IDS_REINSTALL_AVATAR_ITEM_1)); + XuiControlSetText(m_Buttons[eControl_Avatar2],app.GetString(IDS_REINSTALL_AVATAR_ITEM_2)); + XuiControlSetText(m_Buttons[eControl_Avatar3],app.GetString(IDS_REINSTALL_AVATAR_ITEM_3)); +#endif +} + +wstring UIScene_ReinstallMenu::getMoviePath() +{ + if(app.GetLocalPlayerCount() > 1) + { + return L"ReinstallSplit"; + } + else + { + return L"ReinstallMenu"; + } +} + +void UIScene_ReinstallMenu::updateTooltips() +{ + ui.SetTooltips( m_iPad, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK,IDS_TOOLTIPS_SELECTDEVICE); +} + +void UIScene_ReinstallMenu::updateComponents() +{ + bool bNotInGame=(Minecraft::GetInstance()->level==NULL); + if(bNotInGame) + { + m_parentLayer->showComponent(m_iPad,eUIComponent_Panorama,true); + m_parentLayer->showComponent(m_iPad,eUIComponent_Logo,true); + } + else + { + m_parentLayer->showComponent(m_iPad,eUIComponent_Panorama,false); + + // 4J Stu - Do we want to show the logo in-game? + //if( app.GetLocalPlayerCount() == 1 ) m_parentLayer->showComponent(m_iPad,eUIComponent_Logo,true); + //else m_parentLayer->showComponent(m_iPad,eUIComponent_Logo,false); + m_parentLayer->showComponent(m_iPad,eUIComponent_Logo,false); + + } +} + +void UIScene_ReinstallMenu::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled) +{ + //app.DebugPrintf("UIScene_DebugOverlay handling input for pad %d, key %d, down- %s, pressed- %s, released- %s\n", iPad, key, down?"TRUE":"FALSE", pressed?"TRUE":"FALSE", released?"TRUE":"FALSE"); + + ui.AnimateKeyPress(m_iPad, key, repeat, pressed, released); + + switch(key) + { + case ACTION_MENU_CANCEL: + if(pressed && !repeat) + { + navigateBack(); + } + break; + case ACTION_MENU_OK: +#ifdef __ORBIS__ + case ACTION_MENU_TOUCHPAD_PRESS: +#endif + case ACTION_MENU_UP: + case ACTION_MENU_DOWN: + sendInputToMovie(key, repeat, pressed, released); + break; + } +} + +void UIScene_ReinstallMenu::handlePress(F64 controlId, F64 childId) +{ +#if TO_BE_IMPLEMENTED + switch((int)controlId) + { + case BUTTON_HAO_CHANGESKIN: + ui.NavigateToScene(m_iPad, eUIScene_SkinSelectMenu); + break; + case BUTTON_HAO_HOWTOPLAY: + ui.NavigateToScene(m_iPad, eUIScene_HowToPlayMenu); + break; + case BUTTON_HAO_CONTROLS: + ui.NavigateToScene(m_iPad, eUIScene_ControlsMenu); + break; + case BUTTON_HAO_SETTINGS: + ui.NavigateToScene(m_iPad, eUIScene_SettingsMenu); + break; + case BUTTON_HAO_CREDITS: + ui.NavigateToScene(m_iPad, eUIScene_Credits); + break; + case BUTTON_HAO_REINSTALL: + ui.NavigateToScene(m_iPad, eUIScene_ReinstallMenu); + break; + case BUTTON_HAO_DEBUG: + ui.NavigateToScene(m_iPad, eUIScene_DebugOptions); + break; + } +#endif +} diff --git a/Minecraft.Client/Common/UI/UIScene_ReinstallMenu.h b/Minecraft.Client/Common/UI/UIScene_ReinstallMenu.h new file mode 100644 index 00000000..54c20a6e --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_ReinstallMenu.h @@ -0,0 +1,47 @@ +#pragma once + +#include "UIScene.h" + +class UIScene_ReinstallMenu : public UIScene +{ +private: + enum EControls + { + eControl_Theme, + eControl_Gamerpic1, + eControl_Gamerpic2, + eControl_Avatar1, + eControl_Avatar2, + eControl_Avatar3, + eControl_COUNT, + }; + UIControl_Button m_buttons[eControl_COUNT]; + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) + UI_MAP_ELEMENT( m_buttons[eControl_Theme], "Button1") + UI_MAP_ELEMENT( m_buttons[eControl_Gamerpic1], "Button2") + UI_MAP_ELEMENT( m_buttons[eControl_Gamerpic2], "Button3") + UI_MAP_ELEMENT( m_buttons[eControl_Avatar1], "Button4") + UI_MAP_ELEMENT( m_buttons[eControl_Avatar2], "Button5") + UI_MAP_ELEMENT( m_buttons[eControl_Avatar3], "Button6") + UI_END_MAP_ELEMENTS_AND_NAMES() + + //bool m_bNotInGame; +public: + UIScene_ReinstallMenu(int iPad, void *initData, UILayer *parentLayer); + + virtual EUIScene getSceneType() { return eUIScene_ReinstallMenu;} + + virtual void updateTooltips(); + virtual void updateComponents(); + +protected: + // TODO: This should be pure virtual in this class + virtual wstring getMoviePath(); + +public: + // INPUT + virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled); + +protected: + void handlePress(F64 controlId, F64 childId); +}; diff --git a/Minecraft.Client/Common/UI/UIScene_SaveMessage.cpp b/Minecraft.Client/Common/UI/UIScene_SaveMessage.cpp new file mode 100644 index 00000000..a91d5aa8 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_SaveMessage.cpp @@ -0,0 +1,182 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIScene_SaveMessage.h" + +#define PROFILE_LOADED_TIMER_ID 0 +#define PROFILE_LOADED_TIMER_TIME 50 + +UIScene_SaveMessage::UIScene_SaveMessage(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) +{ + // Setup all the Iggy references we need for this scene + initialiseMovie(); + + parentLayer->addComponent(iPad,eUIComponent_Panorama); + parentLayer->addComponent(iPad,eUIComponent_Logo); + + m_buttonConfirm.init(app.GetString(IDS_CONFIRM_OK),eControl_Confirm); + m_labelDescription.init(app.GetString(IDS_SAVE_ICON_MESSAGE)); + + IggyDataValue result; + + // Russian needs to resize the box + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcAutoResize , 0 , NULL ); + + // 4J-PB - If we have a signed in user connected, let's get the DLC now + for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i) + { + if( (InputManager.IsPadConnected(i) || ProfileManager.IsSignedIn(i)) ) + { + if(!app.DLCInstallProcessCompleted() && !app.DLCInstallPending()) + { + app.StartInstallDLCProcess(i); + break; + } + } + } + + m_bIgnoreInput=false; + + // 4J-TomK - rebuild touch after auto resize +#ifdef __PSVITA__ + ui.TouchBoxRebuild(this); +#endif +} + +UIScene_SaveMessage::~UIScene_SaveMessage() +{ + m_parentLayer->removeComponent(eUIComponent_Panorama); + m_parentLayer->removeComponent(eUIComponent_Logo); +} + +wstring UIScene_SaveMessage::getMoviePath() +{ + return L"SaveMessage"; +} + +void UIScene_SaveMessage::updateTooltips() +{ + ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT ); +} + +void UIScene_SaveMessage::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled) +{ + if(m_bIgnoreInput) return; +#if defined (__ORBIS__) || defined (__PSVITA__) + // ignore all players except player 0 - it's their profile that is currently being used + if(iPad!=0) return; +#endif + + ui.AnimateKeyPress(m_iPad, key, repeat, pressed, released); + + switch(key) + { + case ACTION_MENU_OK: +#ifdef __ORBIS__ + case ACTION_MENU_TOUCHPAD_PRESS: +#endif + sendInputToMovie(key, repeat, pressed, released); + break; + // #ifdef __PS3__ + // case ACTION_MENU_Y: + // if(pressed) + // { + // // language select - switch to Greek for now + // if(app.GetMinecraftLanguage(iPad)==MINECRAFT_LANGUAGE_DEFAULT) + // { + // app.SetMinecraftLanguage(iPad,MINECRAFT_LANGUAGE_GREEK); + // } + // else + // { + // app.SetMinecraftLanguage(iPad,MINECRAFT_LANGUAGE_DEFAULT); + // } + // // reload the string table + // ui.SetupFont(); + // app.loadStringTable(); + // handleReload(); + // } + // break; + // #endif + } +} + +void UIScene_SaveMessage::handlePress(F64 controlId, F64 childId) +{ + switch((int)controlId) + { + case eControl_Confirm: + + //CD - Added for audio + ui.PlayUISFX(eSFX_Press); + + m_bIgnoreInput=true; + +#if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__) + // wait for the profile to be read - this has been kicked off earlier, so should be read by now + addTimer(PROFILE_LOADED_TIMER_ID,PROFILE_LOADED_TIMER_TIME); +#else + ui.NavigateToHomeMenu(); +#endif + break; + }; +} + +void UIScene_SaveMessage::handleTimerComplete(int id) +{ + switch(id) + { + case PROFILE_LOADED_TIMER_ID: + { +#if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__) + C4JStorage::eOptionsCallback eStatus=app.GetOptionsCallbackStatus(0); + + switch(eStatus) + { + case C4JStorage::eOptions_Callback_Read: + case C4JStorage::eOptions_Callback_Read_FileNotFound: + case C4JStorage::eOptions_Callback_Read_Fail: +#ifdef __PSVITA__ + case C4JStorage::eOptions_Callback_Write_Fail: + case C4JStorage::eOptions_Callback_Write: +#endif + // set defaults - which has already been done + killTimer(PROFILE_LOADED_TIMER_ID); + ui.NavigateToHomeMenu(); + SQRNetworkManager::SafeToRespondToGameBootInvite(); + app.SetOptionsCallbackStatus(0,C4JStorage::eOptions_Callback_Idle); + break; + case C4JStorage::eOptions_Callback_Read_CorruptDeleted: + killTimer(PROFILE_LOADED_TIMER_ID); + ui.NavigateToHomeMenu(); + SQRNetworkManager::SafeToRespondToGameBootInvite(); + app.SetOptionsCallbackStatus(0,C4JStorage::eOptions_Callback_Idle); + break; + case C4JStorage::eOptions_Callback_Read_Corrupt: + // get the user to delete the options file + app.DebugPrintf("Corrupt options file\n"); + app.SetOptionsCallbackStatus(0,C4JStorage::eOptions_Callback_Read_CorruptDeletePending); + m_bIgnoreInput=false; + // give the option to delete the save + UINT uiIDA[1]; + uiIDA[0]=IDS_CONFIRM_OK; + ui.RequestMessageBox(IDS_CORRUPT_FILE, IDS_CORRUPT_OPTIONS, uiIDA, 1, + 0,&UIScene_SaveMessage::DeleteOptionsDialogReturned,this, app.GetStringTable()); + break; + } +#endif + } + + break; + } +} + +#if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__) +int UIScene_SaveMessage::DeleteOptionsDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result) +{ + //UIScene_SaveMessage* pClass = (UIScene_SaveMessage*)pParam; + + // kick off the delete + StorageManager.DeleteOptionsData(iPad); + + return 0; +} +#endif diff --git a/Minecraft.Client/Common/UI/UIScene_SaveMessage.h b/Minecraft.Client/Common/UI/UIScene_SaveMessage.h new file mode 100644 index 00000000..cedc8c8f --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_SaveMessage.h @@ -0,0 +1,51 @@ +#pragma once + +#include "UIScene.h" + +class UIScene_SaveMessage : public UIScene +{ +private: + enum EControls + { + eControl_Confirm, + }; + + bool m_bIgnoreInput; + + UIControl_Button m_buttonConfirm; + UIControl_Label m_labelDescription; + IggyName m_funcAutoResize; + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) + UI_MAP_ELEMENT(m_buttonConfirm, "Confirm") + UI_MAP_ELEMENT(m_labelDescription, "Description") + UI_MAP_NAME( m_funcAutoResize, L"AutoResize") + UI_END_MAP_ELEMENTS_AND_NAMES() + +#if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__) + static int DeleteOptionsDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result); +#endif + +public: + UIScene_SaveMessage(int iPad, void *initData, UILayer *parentLayer); + ~UIScene_SaveMessage(); + + virtual EUIScene getSceneType() { return eUIScene_SaveMessage;} + // Returns true if this scene has focus for the pad passed in +#ifndef __PS3__ + virtual bool hasFocus(int iPad) { return bHasFocus; } +#endif + virtual void updateTooltips(); + +protected: + virtual wstring getMoviePath(); + +public: + // INPUT + virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled); + virtual void handleTimerComplete(int id); + +protected: + void handlePress(F64 controlId, F64 childId); + + virtual long long getDefaultGtcButtons() { return 0; } +}; diff --git a/Minecraft.Client/Common/UI/UIScene_SettingsAudioMenu.cpp b/Minecraft.Client/Common/UI/UIScene_SettingsAudioMenu.cpp new file mode 100644 index 00000000..6d892d70 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_SettingsAudioMenu.cpp @@ -0,0 +1,116 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIScene_SettingsAudioMenu.h" + +UIScene_SettingsAudioMenu::UIScene_SettingsAudioMenu(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) +{ + // Setup all the Iggy references we need for this scene + initialiseMovie(); + + WCHAR TempString[256]; + swprintf( (WCHAR *)TempString, 256, L"%ls: %d%%", app.GetString( IDS_SLIDER_MUSIC ),app.GetGameSettings(m_iPad,eGameSetting_MusicVolume)); + m_sliderMusic.init(TempString,eControl_Music,0,100,app.GetGameSettings(m_iPad,eGameSetting_MusicVolume)); + + swprintf( (WCHAR *)TempString, 256, L"%ls: %d%%", app.GetString( IDS_SLIDER_SOUND ),app.GetGameSettings(m_iPad,eGameSetting_SoundFXVolume)); + m_sliderSound.init(TempString,eControl_Sound,0,100,app.GetGameSettings(m_iPad,eGameSetting_SoundFXVolume)); + + doHorizontalResizeCheck(); + + if(app.GetLocalPlayerCount()>1) + { +#if TO_BE_IMPLEMENTED + app.AdjustSplitscreenScene(m_hObj,&m_OriginalPosition,m_iPad); +#endif + } +} + +UIScene_SettingsAudioMenu::~UIScene_SettingsAudioMenu() +{ +} + +wstring UIScene_SettingsAudioMenu::getMoviePath() +{ + if(app.GetLocalPlayerCount() > 1) + { + return L"SettingsAudioMenuSplit"; + } + else + { + return L"SettingsAudioMenu"; + } +} + +void UIScene_SettingsAudioMenu::updateTooltips() +{ + ui.SetTooltips( m_iPad, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK); +} + +void UIScene_SettingsAudioMenu::updateComponents() +{ + bool bNotInGame=(Minecraft::GetInstance()->level==NULL); + if(bNotInGame) + { + m_parentLayer->showComponent(m_iPad,eUIComponent_Panorama,true); + m_parentLayer->showComponent(m_iPad,eUIComponent_Logo,true); + } + else + { + m_parentLayer->showComponent(m_iPad,eUIComponent_Panorama,false); + + if( app.GetLocalPlayerCount() == 1 ) m_parentLayer->showComponent(m_iPad,eUIComponent_Logo,true); + else m_parentLayer->showComponent(m_iPad,eUIComponent_Logo,false); + } +} + +void UIScene_SettingsAudioMenu::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled) +{ + //app.DebugPrintf("UIScene_DebugOverlay handling input for pad %d, key %d, down- %s, pressed- %s, released- %s\n", iPad, key, down?"TRUE":"FALSE", pressed?"TRUE":"FALSE", released?"TRUE":"FALSE"); + ui.AnimateKeyPress(m_iPad, key, repeat, pressed, released); + + switch(key) + { + case ACTION_MENU_CANCEL: + if(pressed) + { + navigateBack(); + } + break; + case ACTION_MENU_OK: +#ifdef __ORBIS__ + case ACTION_MENU_TOUCHPAD_PRESS: +#endif + sendInputToMovie(key, repeat, pressed, released); + break; + case ACTION_MENU_UP: + case ACTION_MENU_DOWN: + case ACTION_MENU_LEFT: + case ACTION_MENU_RIGHT: + sendInputToMovie(key, repeat, pressed, released); + break; + } +} + +void UIScene_SettingsAudioMenu::handleSliderMove(F64 sliderId, F64 currentValue) +{ + WCHAR TempString[256]; + int value = (int)currentValue; + switch((int)sliderId) + { + case eControl_Music: + m_sliderMusic.handleSliderMove(value); + + app.SetGameSettings(m_iPad,eGameSetting_MusicVolume,value); + swprintf( (WCHAR *)TempString, 256, L"%ls: %d%%", app.GetString( IDS_SLIDER_MUSIC ),value); + m_sliderMusic.setLabel(TempString); + + break; + case eControl_Sound: + m_sliderSound.handleSliderMove(value); + + app.SetGameSettings(m_iPad,eGameSetting_SoundFXVolume,value); + swprintf( (WCHAR *)TempString, 256, L"%ls: %d%%", app.GetString( IDS_SLIDER_SOUND ),value); + m_sliderSound.setLabel(TempString); + + break; + } +} diff --git a/Minecraft.Client/Common/UI/UIScene_SettingsAudioMenu.h b/Minecraft.Client/Common/UI/UIScene_SettingsAudioMenu.h new file mode 100644 index 00000000..6c48b22b --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_SettingsAudioMenu.h @@ -0,0 +1,38 @@ +#pragma once + +#include "UIScene.h" + +class UIScene_SettingsAudioMenu : public UIScene +{ +private: + enum EControls + { + eControl_Music, + eControl_Sound + }; + + UIControl_Slider m_sliderMusic, m_sliderSound; // Sliders + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) + UI_MAP_ELEMENT( m_sliderMusic, "Music") + UI_MAP_ELEMENT( m_sliderSound, "Sound") + UI_END_MAP_ELEMENTS_AND_NAMES() + +public: + UIScene_SettingsAudioMenu(int iPad, void *initData, UILayer *parentLayer); + virtual ~UIScene_SettingsAudioMenu(); + + virtual EUIScene getSceneType() { return eUIScene_SettingsAudioMenu;} + + virtual void updateTooltips(); + virtual void updateComponents(); + +protected: + // TODO: This should be pure virtual in this class + virtual wstring getMoviePath(); + +public: + // INPUT + virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled); + + virtual void handleSliderMove(F64 sliderId, F64 currentValue); +};
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIScene_SettingsControlMenu.cpp b/Minecraft.Client/Common/UI/UIScene_SettingsControlMenu.cpp new file mode 100644 index 00000000..d5447f77 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_SettingsControlMenu.cpp @@ -0,0 +1,116 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIScene_SettingsControlMenu.h" + +UIScene_SettingsControlMenu::UIScene_SettingsControlMenu(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) +{ + // Setup all the Iggy references we need for this scene + initialiseMovie(); + + WCHAR TempString[256]; + swprintf( (WCHAR *)TempString, 256, L"%ls: %d%%", app.GetString( IDS_SLIDER_SENSITIVITY_INGAME ),app.GetGameSettings(m_iPad,eGameSetting_Sensitivity_InGame)); + m_sliderSensitivityInGame.init(TempString,eControl_SensitivityInGame,0,200,app.GetGameSettings(m_iPad,eGameSetting_Sensitivity_InGame)); + + swprintf( (WCHAR *)TempString, 256, L"%ls: %d%%", app.GetString( IDS_SLIDER_SENSITIVITY_INMENU ),app.GetGameSettings(m_iPad,eGameSetting_Sensitivity_InMenu)); + m_sliderSensitivityInMenu.init(TempString,eControl_SensitivityInMenu,0,200,app.GetGameSettings(m_iPad,eGameSetting_Sensitivity_InMenu)); + + doHorizontalResizeCheck(); + + if(app.GetLocalPlayerCount()>1) + { +#if TO_BE_IMPLEMENTED + app.AdjustSplitscreenScene(m_hObj,&m_OriginalPosition,m_iPad,false); +#endif + } +} + +UIScene_SettingsControlMenu::~UIScene_SettingsControlMenu() +{ +} + +wstring UIScene_SettingsControlMenu::getMoviePath() +{ + if(app.GetLocalPlayerCount() > 1) + { + return L"SettingsControlMenuSplit"; + } + else + { + return L"SettingsControlMenu"; + } +} + +void UIScene_SettingsControlMenu::updateTooltips() +{ + ui.SetTooltips( m_iPad, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK); +} + +void UIScene_SettingsControlMenu::updateComponents() +{ + bool bNotInGame=(Minecraft::GetInstance()->level==NULL); + if(bNotInGame) + { + m_parentLayer->showComponent(m_iPad,eUIComponent_Panorama,true); + m_parentLayer->showComponent(m_iPad,eUIComponent_Logo,true); + } + else + { + m_parentLayer->showComponent(m_iPad,eUIComponent_Panorama,false); + + if( app.GetLocalPlayerCount() == 1 ) m_parentLayer->showComponent(m_iPad,eUIComponent_Logo,true); + else m_parentLayer->showComponent(m_iPad,eUIComponent_Logo,false); + } +} + +void UIScene_SettingsControlMenu::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled) +{ + ui.AnimateKeyPress(iPad, key, repeat, pressed, released); + + switch(key) + { + case ACTION_MENU_CANCEL: + if(pressed) + { + navigateBack(); + handled = true; + } + break; + case ACTION_MENU_OK: +#ifdef __ORBIS__ + case ACTION_MENU_TOUCHPAD_PRESS: +#endif + sendInputToMovie(key, repeat, pressed, released); + break; + case ACTION_MENU_UP: + case ACTION_MENU_DOWN: + case ACTION_MENU_LEFT: + case ACTION_MENU_RIGHT: + sendInputToMovie(key, repeat, pressed, released); + break; + } +} + +void UIScene_SettingsControlMenu::handleSliderMove(F64 sliderId, F64 currentValue) +{ + WCHAR TempString[256]; + int value = (int)currentValue; + switch((int)sliderId) + { + case eControl_SensitivityInGame: + m_sliderSensitivityInGame.handleSliderMove(value); + + app.SetGameSettings(m_iPad,eGameSetting_Sensitivity_InGame,value); + swprintf( (WCHAR *)TempString, 256, L"%ls: %d%%", app.GetString( IDS_SLIDER_SENSITIVITY_INGAME ),value); + m_sliderSensitivityInGame.setLabel(TempString); + + break; + case eControl_SensitivityInMenu: + m_sliderSensitivityInMenu.handleSliderMove(value); + + app.SetGameSettings(m_iPad,eGameSetting_Sensitivity_InMenu,value); + swprintf( (WCHAR *)TempString, 256, L"%ls: %d%%", app.GetString( IDS_SLIDER_SENSITIVITY_INMENU ),value); + m_sliderSensitivityInMenu.setLabel(TempString); + + break; + } +} diff --git a/Minecraft.Client/Common/UI/UIScene_SettingsControlMenu.h b/Minecraft.Client/Common/UI/UIScene_SettingsControlMenu.h new file mode 100644 index 00000000..6d3b864c --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_SettingsControlMenu.h @@ -0,0 +1,37 @@ +#pragma once + +#include "UIScene.h" + +class UIScene_SettingsControlMenu : public UIScene +{ +private: + enum EControls + { + eControl_SensitivityInGame, + eControl_SensitivityInMenu + }; + + UIControl_Slider m_sliderSensitivityInGame, m_sliderSensitivityInMenu; // Sliders + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) + UI_MAP_ELEMENT( m_sliderSensitivityInGame, "SensitivityInGame") + UI_MAP_ELEMENT( m_sliderSensitivityInMenu, "SensitivityInMenu") + UI_END_MAP_ELEMENTS_AND_NAMES() +public: + UIScene_SettingsControlMenu(int iPad, void *initData, UILayer *parentLayer); + virtual ~UIScene_SettingsControlMenu(); + + virtual EUIScene getSceneType() { return eUIScene_SettingsControlMenu;} + + virtual void updateTooltips(); + virtual void updateComponents(); + +protected: + // TODO: This should be pure virtual in this class + virtual wstring getMoviePath(); + +public: + // INPUT + virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled); + + virtual void handleSliderMove(F64 sliderId, F64 currentValue); +};
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIScene_SettingsGraphicsMenu.cpp b/Minecraft.Client/Common/UI/UIScene_SettingsGraphicsMenu.cpp new file mode 100644 index 00000000..1234121e --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_SettingsGraphicsMenu.cpp @@ -0,0 +1,153 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIScene_SettingsGraphicsMenu.h" + +UIScene_SettingsGraphicsMenu::UIScene_SettingsGraphicsMenu(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) +{ + // Setup all the Iggy references we need for this scene + initialiseMovie(); + + m_bNotInGame=(Minecraft::GetInstance()->level==NULL); + + m_checkboxClouds.init(app.GetString(IDS_CHECKBOX_RENDER_CLOUDS),eControl_Clouds,(app.GetGameSettings(m_iPad,eGameSetting_Clouds)!=0)); + m_checkboxBedrockFog.init(app.GetString(IDS_CHECKBOX_RENDER_BEDROCKFOG),eControl_BedrockFog,(app.GetGameSettings(m_iPad,eGameSetting_BedrockFog)!=0)); + m_checkboxCustomSkinAnim.init(app.GetString(IDS_CHECKBOX_CUSTOM_SKIN_ANIM),eControl_CustomSkinAnim,(app.GetGameSettings(m_iPad,eGameSetting_CustomSkinAnim)!=0)); + + + WCHAR TempString[256]; + + swprintf( (WCHAR *)TempString, 256, L"%ls: %d%%", app.GetString( IDS_SLIDER_GAMMA ),app.GetGameSettings(m_iPad,eGameSetting_Gamma)); + m_sliderGamma.init(TempString,eControl_Gamma,0,100,app.GetGameSettings(m_iPad,eGameSetting_Gamma)); + + swprintf( (WCHAR *)TempString, 256, L"%ls: %d%%", app.GetString( IDS_SLIDER_INTERFACEOPACITY ),app.GetGameSettings(m_iPad,eGameSetting_InterfaceOpacity)); + m_sliderInterfaceOpacity.init(TempString,eControl_InterfaceOpacity,0,100,app.GetGameSettings(m_iPad,eGameSetting_InterfaceOpacity)); + + doHorizontalResizeCheck(); + + bool bInGame=(Minecraft::GetInstance()->level!=NULL); + bool bIsPrimaryPad=(ProfileManager.GetPrimaryPad()==m_iPad); + // if we're not in the game, we need to use basescene 0 + if(bInGame) + { + // If the game has started, then you need to be the host to change the in-game gamertags + if(bIsPrimaryPad) + { + // we are the primary player on this machine, but not the game host + // are we the game host? If not, we need to remove the bedrockfog setting + if(!g_NetworkManager.IsHost()) + { + // hide the in-game bedrock fog setting + removeControl(&m_checkboxBedrockFog, true); + } + } + else + { + // We shouldn't have the bedrock fog option, or the m_CustomSkinAnim option + removeControl(&m_checkboxBedrockFog, true); + removeControl(&m_checkboxCustomSkinAnim, true); + } + } + + if(app.GetLocalPlayerCount()>1) + { +#if TO_BE_IMPLEMENTED + app.AdjustSplitscreenScene(m_hObj,&m_OriginalPosition,m_iPad); +#endif + } +} + +UIScene_SettingsGraphicsMenu::~UIScene_SettingsGraphicsMenu() +{ +} + +wstring UIScene_SettingsGraphicsMenu::getMoviePath() +{ + if(app.GetLocalPlayerCount() > 1) + { + return L"SettingsGraphicsMenuSplit"; + } + else + { + return L"SettingsGraphicsMenu"; + } +} + +void UIScene_SettingsGraphicsMenu::updateTooltips() +{ + ui.SetTooltips( m_iPad, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK); +} + +void UIScene_SettingsGraphicsMenu::updateComponents() +{ + bool bNotInGame=(Minecraft::GetInstance()->level==NULL); + if(bNotInGame) + { + m_parentLayer->showComponent(m_iPad,eUIComponent_Panorama,true); + m_parentLayer->showComponent(m_iPad,eUIComponent_Logo,true); + } + else + { + m_parentLayer->showComponent(m_iPad,eUIComponent_Panorama,false); + + if( app.GetLocalPlayerCount() == 1 ) m_parentLayer->showComponent(m_iPad,eUIComponent_Logo,true); + else m_parentLayer->showComponent(m_iPad,eUIComponent_Logo,false); + + } +} + +void UIScene_SettingsGraphicsMenu::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled) +{ + ui.AnimateKeyPress(iPad, key, repeat, pressed, released); + switch(key) + { + case ACTION_MENU_CANCEL: + if(pressed) + { + // check the checkboxes + app.SetGameSettings(m_iPad,eGameSetting_Clouds,m_checkboxClouds.IsChecked()?1:0); + app.SetGameSettings(m_iPad,eGameSetting_BedrockFog,m_checkboxBedrockFog.IsChecked()?1:0); + app.SetGameSettings(m_iPad,eGameSetting_CustomSkinAnim,m_checkboxCustomSkinAnim.IsChecked()?1:0); + + navigateBack(); + handled = true; + } + break; + case ACTION_MENU_OK: +#ifdef __ORBIS__ + case ACTION_MENU_TOUCHPAD_PRESS: +#endif + sendInputToMovie(key, repeat, pressed, released); + break; + case ACTION_MENU_UP: + case ACTION_MENU_DOWN: + case ACTION_MENU_LEFT: + case ACTION_MENU_RIGHT: + sendInputToMovie(key, repeat, pressed, released); + break; + } +} + +void UIScene_SettingsGraphicsMenu::handleSliderMove(F64 sliderId, F64 currentValue) +{ + WCHAR TempString[256]; + int value = (int)currentValue; + switch((int)sliderId) + { + case eControl_Gamma: + m_sliderGamma.handleSliderMove(value); + + app.SetGameSettings(m_iPad,eGameSetting_Gamma,value); + swprintf( (WCHAR *)TempString, 256, L"%ls: %d%%", app.GetString( IDS_SLIDER_GAMMA ),value); + m_sliderGamma.setLabel(TempString); + + break; + case eControl_InterfaceOpacity: + m_sliderInterfaceOpacity.handleSliderMove(value); + + app.SetGameSettings(m_iPad,eGameSetting_InterfaceOpacity,value); + swprintf( (WCHAR *)TempString, 256, L"%ls: %d%%", app.GetString( IDS_SLIDER_INTERFACEOPACITY ),value); + m_sliderInterfaceOpacity.setLabel(TempString); + + break; + } +} diff --git a/Minecraft.Client/Common/UI/UIScene_SettingsGraphicsMenu.h b/Minecraft.Client/Common/UI/UIScene_SettingsGraphicsMenu.h new file mode 100644 index 00000000..e9c4905c --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_SettingsGraphicsMenu.h @@ -0,0 +1,46 @@ +#pragma once + +#include "UIScene.h" + +class UIScene_SettingsGraphicsMenu : public UIScene +{ +private: + enum EControls + { + eControl_Clouds, + eControl_BedrockFog, + eControl_CustomSkinAnim, + eControl_Gamma, + eControl_InterfaceOpacity + }; + + UIControl_CheckBox m_checkboxClouds, m_checkboxBedrockFog, m_checkboxCustomSkinAnim; // Checkboxes + UIControl_Slider m_sliderGamma, m_sliderInterfaceOpacity; // Sliders + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) + UI_MAP_ELEMENT( m_checkboxClouds, "Clouds") + UI_MAP_ELEMENT( m_checkboxBedrockFog, "BedrockFog") + UI_MAP_ELEMENT( m_checkboxCustomSkinAnim, "CustomSkinAnim") + UI_MAP_ELEMENT( m_sliderGamma, "Gamma") + UI_MAP_ELEMENT( m_sliderInterfaceOpacity, "InterfaceOpacity") + UI_END_MAP_ELEMENTS_AND_NAMES() + + bool m_bNotInGame; +public: + UIScene_SettingsGraphicsMenu(int iPad, void *initData, UILayer *parentLayer); + virtual ~UIScene_SettingsGraphicsMenu(); + + virtual EUIScene getSceneType() { return eUIScene_SettingsGraphicsMenu;} + + virtual void updateTooltips(); + virtual void updateComponents(); + +protected: + // TODO: This should be pure virtual in this class + virtual wstring getMoviePath(); + +public: + // INPUT + virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled); + + virtual void handleSliderMove(F64 sliderId, F64 currentValue); +};
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIScene_SettingsMenu.cpp b/Minecraft.Client/Common/UI/UIScene_SettingsMenu.cpp new file mode 100644 index 00000000..4ef7eb5d --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_SettingsMenu.cpp @@ -0,0 +1,168 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIScene_SettingsMenu.h" +#include "..\..\Minecraft.h" + +UIScene_SettingsMenu::UIScene_SettingsMenu(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) +{ + // Setup all the Iggy references we need for this scene + initialiseMovie(); + + bool bNotInGame=(Minecraft::GetInstance()->level==NULL); + + m_buttons[BUTTON_ALL_OPTIONS].init(app.GetString(IDS_OPTIONS),BUTTON_ALL_OPTIONS); + m_buttons[BUTTON_ALL_AUDIO].init(app.GetString(IDS_AUDIO),BUTTON_ALL_AUDIO); + m_buttons[BUTTON_ALL_CONTROL].init(app.GetString(IDS_CONTROL),BUTTON_ALL_CONTROL); + m_buttons[BUTTON_ALL_GRAPHICS].init(app.GetString(IDS_GRAPHICS),BUTTON_ALL_GRAPHICS); + m_buttons[BUTTON_ALL_UI].init(app.GetString(IDS_USER_INTERFACE),BUTTON_ALL_UI); + m_buttons[BUTTON_ALL_RESETTODEFAULTS].init(app.GetString(IDS_RESET_TO_DEFAULTS),BUTTON_ALL_RESETTODEFAULTS); + + if(ProfileManager.GetPrimaryPad()!=m_iPad) + { + removeControl( &m_buttons[BUTTON_ALL_AUDIO], true); + removeControl( &m_buttons[BUTTON_ALL_GRAPHICS], true); + } + + doHorizontalResizeCheck(); + + if(app.GetLocalPlayerCount()>1) + { +#if TO_BE_IMPLEMENTED + app.AdjustSplitscreenScene(m_hObj,&m_OriginalPosition,m_iPad,false); +#endif + } +} + +UIScene_SettingsMenu::~UIScene_SettingsMenu() +{ +} + +wstring UIScene_SettingsMenu::getMoviePath() +{ + if(app.GetLocalPlayerCount() > 1) + { + return L"SettingsMenuSplit"; + } + else + { + return L"SettingsMenu"; + } +} + +void UIScene_SettingsMenu::handleReload() +{ + if(ProfileManager.GetPrimaryPad()!=m_iPad) + { + removeControl( &m_buttons[BUTTON_ALL_AUDIO], true); + removeControl( &m_buttons[BUTTON_ALL_GRAPHICS], true); + } + + doHorizontalResizeCheck(); +} + +void UIScene_SettingsMenu::updateTooltips() +{ + ui.SetTooltips( m_iPad, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK); +} + +void UIScene_SettingsMenu::updateComponents() +{ + bool bNotInGame=(Minecraft::GetInstance()->level==NULL); + if(bNotInGame) + { + m_parentLayer->showComponent(m_iPad,eUIComponent_Panorama,true); + m_parentLayer->showComponent(m_iPad,eUIComponent_Logo,true); + } + else + { + m_parentLayer->showComponent(m_iPad,eUIComponent_Panorama,false); + + if( app.GetLocalPlayerCount() == 1 ) m_parentLayer->showComponent(m_iPad,eUIComponent_Logo,true); + else m_parentLayer->showComponent(m_iPad,eUIComponent_Logo,false); + + } +} + +void UIScene_SettingsMenu::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled) +{ + //app.DebugPrintf("UIScene_DebugOverlay handling input for pad %d, key %d, down- %s, pressed- %s, released- %s\n", iPad, key, down?"TRUE":"FALSE", pressed?"TRUE":"FALSE", released?"TRUE":"FALSE"); + ui.AnimateKeyPress(m_iPad, key, repeat, pressed, released); + + switch(key) + { + case ACTION_MENU_CANCEL: + if(pressed) + { + // if the profile data has been changed, then force a profile write + // It seems we're allowed to break the 5 minute rule if it's the result of a user action + + app.CheckGameSettingsChanged(true,iPad); + navigateBack(); + } + break; + case ACTION_MENU_OK: +#ifdef __ORBIS__ + case ACTION_MENU_TOUCHPAD_PRESS: +#endif + sendInputToMovie(key, repeat, pressed, released); + break; + case ACTION_MENU_UP: + case ACTION_MENU_DOWN: + sendInputToMovie(key, repeat, pressed, released); + break; + } +} + +void UIScene_SettingsMenu::handlePress(F64 controlId, F64 childId) +{ + //CD - Added for audio + ui.PlayUISFX(eSFX_Press); + + switch((int)controlId) + { + case BUTTON_ALL_OPTIONS: + ui.NavigateToScene(m_iPad, eUIScene_SettingsOptionsMenu); + break; + case BUTTON_ALL_AUDIO: + ui.NavigateToScene(m_iPad, eUIScene_SettingsAudioMenu); + break; + case BUTTON_ALL_CONTROL: + ui.NavigateToScene(m_iPad, eUIScene_SettingsControlMenu); + break; + case BUTTON_ALL_GRAPHICS: + ui.NavigateToScene(m_iPad, eUIScene_SettingsGraphicsMenu); + break; + case BUTTON_ALL_UI: + ui.NavigateToScene(m_iPad, eUIScene_SettingsUIMenu); + break; + case BUTTON_ALL_RESETTODEFAULTS: + { + // check they really want to do this + UINT uiIDA[2]; + uiIDA[0]=IDS_CONFIRM_CANCEL; + uiIDA[1]=IDS_CONFIRM_OK; + + ui.RequestMessageBox(IDS_DEFAULTS_TITLE, IDS_DEFAULTS_TEXT, uiIDA, 2, m_iPad,&UIScene_SettingsMenu::ResetDefaultsDialogReturned,this, app.GetStringTable(), NULL, 0, false); + } + break; + } +} + +int UIScene_SettingsMenu::ResetDefaultsDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result) +{ + UIScene_SettingsMenu* pClass = (UIScene_SettingsMenu*)pParam; + + // results switched for this dialog + if(result==C4JStorage::EMessage_ResultDecline) + { +#if (defined __PS3__ || defined __ORBIS__ || defined _DURANGO || defined __PSVITA__) + app.SetDefaultOptions(StorageManager.GetDashboardProfileSettings(pClass->m_iPad),pClass->m_iPad); +#else + app.SetDefaultOptions(ProfileManager.GetDashboardProfileSettings(pClass->m_iPad),pClass->m_iPad); +#endif + // if the profile data has been changed, then force a profile write + // It seems we're allowed to break the 5 minute rule if it's the result of a user action + app.CheckGameSettingsChanged(true,iPad); + } + return 0; +} diff --git a/Minecraft.Client/Common/UI/UIScene_SettingsMenu.h b/Minecraft.Client/Common/UI/UIScene_SettingsMenu.h new file mode 100644 index 00000000..7f5fe169 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_SettingsMenu.h @@ -0,0 +1,47 @@ +#pragma once + +#include "UIScene.h" + +#define BUTTON_ALL_OPTIONS 0 +#define BUTTON_ALL_AUDIO 1 +#define BUTTON_ALL_CONTROL 2 +#define BUTTON_ALL_GRAPHICS 4 +#define BUTTON_ALL_UI 5 +#define BUTTON_ALL_RESETTODEFAULTS 6 +#define BUTTONS_ALL_MAX BUTTON_ALL_RESETTODEFAULTS + 1 + +class UIScene_SettingsMenu : public UIScene +{ +private: + UIControl_Button m_buttons[BUTTONS_ALL_MAX]; + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) + UI_MAP_ELEMENT( m_buttons[BUTTON_ALL_OPTIONS], "Button1") + UI_MAP_ELEMENT( m_buttons[BUTTON_ALL_AUDIO], "Button2") + UI_MAP_ELEMENT( m_buttons[BUTTON_ALL_CONTROL], "Button3") + UI_MAP_ELEMENT( m_buttons[BUTTON_ALL_GRAPHICS], "Button4") + UI_MAP_ELEMENT( m_buttons[BUTTON_ALL_UI], "Button5") + UI_MAP_ELEMENT( m_buttons[BUTTON_ALL_RESETTODEFAULTS], "Button6") + UI_END_MAP_ELEMENTS_AND_NAMES() +public: + UIScene_SettingsMenu(int iPad, void *initData, UILayer *parentLayer); + virtual ~UIScene_SettingsMenu(); + + virtual EUIScene getSceneType() { return eUIScene_SettingsMenu;} + + virtual void updateTooltips(); + virtual void updateComponents(); + virtual void handleReload(); + +protected: + // TODO: This should be pure virtual in this class + virtual wstring getMoviePath(); + +public: + // INPUT + virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled); + +protected: + void handlePress(F64 controlId, F64 childId); + + static int ResetDefaultsDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result); +};
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIScene_SettingsOptionsMenu.cpp b/Minecraft.Client/Common/UI/UIScene_SettingsOptionsMenu.cpp new file mode 100644 index 00000000..72576ded --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_SettingsOptionsMenu.cpp @@ -0,0 +1,253 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIScene_SettingsOptionsMenu.h" + +int UIScene_SettingsOptionsMenu::m_iDifficultySettingA[4]= +{ + IDS_DIFFICULTY_PEACEFUL, + IDS_DIFFICULTY_EASY, + IDS_DIFFICULTY_NORMAL, + IDS_DIFFICULTY_HARD +}; + +int UIScene_SettingsOptionsMenu::m_iDifficultyTitleSettingA[4]= +{ + IDS_DIFFICULTY_TITLE_PEACEFUL, + IDS_DIFFICULTY_TITLE_EASY, + IDS_DIFFICULTY_TITLE_NORMAL, + IDS_DIFFICULTY_TITLE_HARD +}; + +UIScene_SettingsOptionsMenu::UIScene_SettingsOptionsMenu(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) +{ + // Setup all the Iggy references we need for this scene + initialiseMovie(); + + m_bNotInGame=(Minecraft::GetInstance()->level==NULL); + + m_checkboxViewBob.init(app.GetString(IDS_VIEW_BOBBING),eControl_ViewBob,(app.GetGameSettings(m_iPad,eGameSetting_ViewBob)!=0)); + m_checkboxShowHints.init(app.GetString(IDS_HINTS),eControl_ShowHints,(app.GetGameSettings(m_iPad,eGameSetting_Hints)!=0)); + m_checkboxShowTooltips.init(app.GetString(IDS_IN_GAME_TOOLTIPS),eControl_ShowTooltips,(app.GetGameSettings(m_iPad,eGameSetting_Tooltips)!=0)); + m_checkboxInGameGamertags.init(app.GetString(IDS_IN_GAME_GAMERTAGS),eControl_InGameGamertags,(app.GetGameSettings(m_iPad,eGameSetting_GamertagsVisible)!=0)); + + // check if we should display the mash-up option + if(m_bNotInGame && app.GetMashupPackWorlds(m_iPad)!=0xFFFFFFFF) + { + // the mash-up option is needed + m_bMashUpWorldsUnhideOption=true; + m_checkboxMashupWorlds.init(app.GetString(IDS_UNHIDE_MASHUP_WORLDS),eControl_ShowMashUpWorlds,false); + } + else + { + //m_checkboxMashupWorlds.init(L"",eControl_ShowMashUpWorlds,false); + removeControl(&m_checkboxMashupWorlds, true); + m_bMashUpWorldsUnhideOption=false; + } + + unsigned char ucValue=app.GetGameSettings(m_iPad,eGameSetting_Autosave); + + wchar_t autosaveLabels[9][256]; + for(unsigned int i = 0; i < 9; ++i) + { + if(i==0) + { + swprintf( autosaveLabels[i], 256, L"%ls", app.GetString( IDS_SLIDER_AUTOSAVE_OFF )); + } + else + { + swprintf( autosaveLabels[i], 256, L"%ls: %d %ls", app.GetString( IDS_SLIDER_AUTOSAVE ),i*15, app.GetString( IDS_MINUTES )); + } + + } + m_sliderAutosave.setAllPossibleLabels(9,autosaveLabels); + m_sliderAutosave.init(autosaveLabels[ucValue],eControl_Autosave,0,8,ucValue); + +#if defined(_XBOX_ONE) || defined(__ORBIS__) + removeControl(&m_sliderAutosave,true); +#endif + + ucValue = app.GetGameSettings(m_iPad,eGameSetting_Difficulty); + wchar_t difficultyLabels[4][256]; + for(unsigned int i = 0; i < 4; ++i) + { + swprintf( difficultyLabels[i], 256, L"%ls: %ls", app.GetString( IDS_SLIDER_DIFFICULTY ),app.GetString(m_iDifficultyTitleSettingA[i])); + } + m_sliderDifficulty.setAllPossibleLabels(4,difficultyLabels); + m_sliderDifficulty.init(difficultyLabels[ucValue],eControl_Difficulty,0,3,ucValue); + + wstring wsText=app.GetString(m_iDifficultySettingA[app.GetGameSettings(m_iPad,eGameSetting_Difficulty)]); + EHTMLFontSize size = eHTMLSize_Normal; + if(!RenderManager.IsHiDef() && !RenderManager.IsWidescreen()) + { + size = eHTMLSize_Splitscreen; + } + wchar_t startTags[64]; + swprintf(startTags,64,L"<font color=\"#%08x\">",app.GetHTMLColour(eHTMLColor_White)); + wsText= startTags + wsText; + + m_labelDifficultyText.init(wsText); + + // If you are in-game, only the game host can change in-game gamertags, and you can't change difficulty + // only the primary player gets to change the autosave and difficulty settings + bool bRemoveDifficulty=false; + bool bRemoveAutosave=false; + bool bRemoveInGameGamertags=false; + float fRemoveHeight=0.0f,fWidth,fHeight; + + bool bNotInGame=(Minecraft::GetInstance()->level==NULL); + bool bPrimaryPlayer = ProfileManager.GetPrimaryPad()==m_iPad; + if(!bPrimaryPlayer) + { + bRemoveDifficulty=true; + bRemoveAutosave=true; + bRemoveInGameGamertags=true; + } + + if(!bNotInGame) // in the game + { + bRemoveDifficulty=true; + if(!g_NetworkManager.IsHost()) + { + bRemoveAutosave=true; + bRemoveInGameGamertags=true; + } + } + if(bRemoveDifficulty) + { + m_labelDifficultyText.setVisible( false ); + removeControl(&m_sliderDifficulty, true); + } + + if(bRemoveAutosave) + { + removeControl(&m_sliderAutosave, true); + } + + if(bRemoveInGameGamertags) + { + removeControl(&m_checkboxInGameGamertags, true); + } + + doHorizontalResizeCheck(); + + if(app.GetLocalPlayerCount()>1) + { +#if TO_BE_IMPLEMENTED + app.AdjustSplitscreenScene(m_hObj,&m_OriginalPosition,m_iPad); +#endif + } +} + +UIScene_SettingsOptionsMenu::~UIScene_SettingsOptionsMenu() +{ +} + +wstring UIScene_SettingsOptionsMenu::getMoviePath() +{ + if(app.GetLocalPlayerCount() > 1) + { + return L"SettingsOptionsMenuSplit"; + } + else + { + return L"SettingsOptionsMenu"; + } +} + +void UIScene_SettingsOptionsMenu::updateTooltips() +{ + ui.SetTooltips( m_iPad, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK); +} + +void UIScene_SettingsOptionsMenu::updateComponents() +{ + bool bNotInGame=(Minecraft::GetInstance()->level==NULL); + if(bNotInGame) + { + m_parentLayer->showComponent(m_iPad,eUIComponent_Panorama,true); + m_parentLayer->showComponent(m_iPad,eUIComponent_Logo,true); + } + else + { + m_parentLayer->showComponent(m_iPad,eUIComponent_Panorama,false); + + if( app.GetLocalPlayerCount() == 1 ) m_parentLayer->showComponent(m_iPad,eUIComponent_Logo,RenderManager.IsHiDef()); + else m_parentLayer->showComponent(m_iPad,eUIComponent_Logo,false); + + } +} + +void UIScene_SettingsOptionsMenu::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled) +{ + ui.AnimateKeyPress(iPad, key, repeat, pressed, released); + switch(key) + { + case ACTION_MENU_CANCEL: + if(pressed) + { + // check the checkboxes + app.SetGameSettings(m_iPad,eGameSetting_ViewBob,m_checkboxViewBob.IsChecked()?1:0); + app.SetGameSettings(m_iPad,eGameSetting_GamertagsVisible,m_checkboxInGameGamertags.IsChecked()?1:0); + app.SetGameSettings(m_iPad,eGameSetting_Hints,m_checkboxShowHints.IsChecked()?1:0); + app.SetGameSettings(m_iPad,eGameSetting_Tooltips,m_checkboxShowTooltips.IsChecked()?1:0); + + // the mashup option will only be shown if some worlds have been previously hidden + if(m_bMashUpWorldsUnhideOption && m_checkboxMashupWorlds.IsChecked()) + { + // unhide all worlds + app.EnableMashupPackWorlds(m_iPad); + } + + // 4J-PB - don't action changes here or we might write to the profile on backing out here and then get a change in the settings all, and write again on backing out there + //app.CheckGameSettingsChanged(true,pInputData->UserIndex); + + navigateBack(); + } + break; + case ACTION_MENU_OK: +#ifdef __ORBIS__ + case ACTION_MENU_TOUCHPAD_PRESS: +#endif + sendInputToMovie(key, repeat, pressed, released); + break; + case ACTION_MENU_UP: + case ACTION_MENU_DOWN: + case ACTION_MENU_LEFT: + case ACTION_MENU_RIGHT: + sendInputToMovie(key, repeat, pressed, released); + break; + } +} + +void UIScene_SettingsOptionsMenu::handleSliderMove(F64 sliderId, F64 currentValue) +{ + WCHAR TempString[256]; + int value = (int)currentValue; + switch((int)sliderId) + { + case eControl_Autosave: + m_sliderAutosave.handleSliderMove(value); + + app.SetGameSettings(m_iPad,eGameSetting_Autosave,value); + // Update the autosave timer + app.SetAutosaveTimerTime(); + + break; + case eControl_Difficulty: + m_sliderDifficulty.handleSliderMove(value); + + app.SetGameSettings(m_iPad,eGameSetting_Difficulty,value); + + wstring wsText=app.GetString(m_iDifficultySettingA[value]); + EHTMLFontSize size = eHTMLSize_Normal; + if(!RenderManager.IsHiDef() && !RenderManager.IsWidescreen()) + { + size = eHTMLSize_Splitscreen; + } + wchar_t startTags[64]; + swprintf(startTags,64,L"<font color=\"#%08x\">",app.GetHTMLColour(eHTMLColor_White)); + wsText= startTags + wsText; + m_labelDifficultyText.setLabel(wsText.c_str()); + break; + } +} diff --git a/Minecraft.Client/Common/UI/UIScene_SettingsOptionsMenu.h b/Minecraft.Client/Common/UI/UIScene_SettingsOptionsMenu.h new file mode 100644 index 00000000..265a0790 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_SettingsOptionsMenu.h @@ -0,0 +1,57 @@ +#pragma once + +#include "UIScene.h" + +class UIScene_SettingsOptionsMenu : public UIScene +{ +private: + enum EControls + { + eControl_ViewBob, + eControl_ShowHints, + eControl_ShowTooltips, + eControl_InGameGamertags, + eControl_ShowMashUpWorlds, + eControl_Autosave, + eControl_Difficulty + }; +protected: + static int m_iDifficultySettingA[4]; + static int m_iDifficultyTitleSettingA[4]; + +private: + UIControl_CheckBox m_checkboxViewBob, m_checkboxShowHints, m_checkboxShowTooltips, m_checkboxInGameGamertags, m_checkboxMashupWorlds; // Checkboxes + UIControl_Slider m_sliderAutosave, m_sliderDifficulty; // Sliders + UIControl_Label m_labelDifficultyText; //Text + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) + UI_MAP_ELEMENT( m_checkboxViewBob, "ViewBob") + UI_MAP_ELEMENT( m_checkboxShowHints, "ShowHints") + UI_MAP_ELEMENT( m_checkboxShowTooltips, "ShowTooltips") + UI_MAP_ELEMENT( m_checkboxInGameGamertags, "InGameGamertags") + UI_MAP_ELEMENT( m_checkboxMashupWorlds, "ShowMashUpWorlds") + UI_MAP_ELEMENT( m_sliderAutosave, "Autosave") + UI_MAP_ELEMENT( m_sliderDifficulty, "Difficulty") + UI_MAP_ELEMENT( m_labelDifficultyText, "DifficultyText") + UI_END_MAP_ELEMENTS_AND_NAMES() + + bool m_bNotInGame; + bool m_bMashUpWorldsUnhideOption; +public: + UIScene_SettingsOptionsMenu(int iPad, void *initData, UILayer *parentLayer); + virtual ~UIScene_SettingsOptionsMenu(); + + virtual EUIScene getSceneType() { return eUIScene_SettingsOptionsMenu;} + + virtual void updateTooltips(); + virtual void updateComponents(); + +protected: + // TODO: This should be pure virtual in this class + virtual wstring getMoviePath(); + +public: + // INPUT + virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled); + + virtual void handleSliderMove(F64 sliderId, F64 currentValue); +};
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIScene_SettingsUIMenu.cpp b/Minecraft.Client/Common/UI/UIScene_SettingsUIMenu.cpp new file mode 100644 index 00000000..917012d6 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_SettingsUIMenu.cpp @@ -0,0 +1,183 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIScene_SettingsUIMenu.h" + +UIScene_SettingsUIMenu::UIScene_SettingsUIMenu(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) +{ + // Setup all the Iggy references we need for this scene + initialiseMovie(); + + m_bNotInGame=(Minecraft::GetInstance()->level==NULL); + + m_checkboxDisplayHUD.init(app.GetString(IDS_CHECKBOX_DISPLAY_HUD),eControl_DisplayHUD,(app.GetGameSettings(m_iPad,eGameSetting_DisplayHUD)!=0)); + m_checkboxDisplayHand.init(app.GetString(IDS_CHECKBOX_DISPLAY_HAND),eControl_DisplayHand,(app.GetGameSettings(m_iPad,eGameSetting_DisplayHand)!=0)); + m_checkboxDisplayDeathMessages.init(app.GetString(IDS_CHECKBOX_DEATH_MESSAGES),eControl_DisplayDeathMessages,(app.GetGameSettings(m_iPad,eGameSetting_DeathMessages)!=0)); + m_checkboxDisplayAnimatedCharacter.init(app.GetString(IDS_CHECKBOX_ANIMATED_CHARACTER),eControl_DisplayAnimatedCharacter,(app.GetGameSettings(m_iPad,eGameSetting_AnimatedCharacter)!=0)); + m_checkboxSplitscreen.init(app.GetString(IDS_CHECKBOX_VERTICAL_SPLIT_SCREEN),eControl_Splitscreen,(app.GetGameSettings(m_iPad,eGameSetting_SplitScreenVertical)!=0)); + m_checkboxShowSplitscreenGamertags.init(app.GetString(IDS_CHECKBOX_DISPLAY_SPLITSCREENGAMERTAGS),eControl_ShowSplitscreenGamertags,(app.GetGameSettings(m_iPad,eGameSetting_DisplaySplitscreenGamertags)!=0)); + + WCHAR TempString[256]; + + swprintf( (WCHAR *)TempString, 256, L"%ls: %d", app.GetString( IDS_SLIDER_UISIZE ),app.GetGameSettings(m_iPad,eGameSetting_UISize)+1); + m_sliderUISize.init(TempString,eControl_UISize,1,3,app.GetGameSettings(m_iPad,eGameSetting_UISize)+1); + + swprintf( (WCHAR *)TempString, 256, L"%ls: %d", app.GetString( IDS_SLIDER_UISIZESPLITSCREEN ),app.GetGameSettings(m_iPad,eGameSetting_UISizeSplitscreen)+1); + m_sliderUISizeSplitscreen.init(TempString,eControl_UISizeSplitscreen,1,3,app.GetGameSettings(m_iPad,eGameSetting_UISizeSplitscreen)+1); + + doHorizontalResizeCheck(); + + bool bInGame=(Minecraft::GetInstance()->level!=NULL); + bool bPrimaryPlayer = ProfileManager.GetPrimaryPad()==m_iPad; + + // if we're not in the game, we need to use basescene 0 + if(bInGame) + { + // If the game has started, then you need to be the host to change the in-game gamertags + if(!bPrimaryPlayer) + { + // hide things we don't want the splitscreen player changing + removeControl(&m_checkboxSplitscreen, true); + removeControl(&m_checkboxShowSplitscreenGamertags, true); + } + } + + + if(app.GetLocalPlayerCount()>1) + { +#if TO_BE_IMPLEMENTED + app.AdjustSplitscreenScene(m_hObj,&m_OriginalPosition,m_iPad); +#endif + } +} + +void UIScene_SettingsUIMenu::updateTooltips() +{ + ui.SetTooltips( m_iPad, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK); +} + +void UIScene_SettingsUIMenu::updateComponents() +{ + bool bNotInGame=(Minecraft::GetInstance()->level==NULL); + if(bNotInGame) + { + m_parentLayer->showComponent(m_iPad,eUIComponent_Panorama,true); + m_parentLayer->showComponent(m_iPad,eUIComponent_Logo,true); + } + else + { + m_parentLayer->showComponent(m_iPad,eUIComponent_Panorama,false); + + if( app.GetLocalPlayerCount() == 1 ) m_parentLayer->showComponent(m_iPad,eUIComponent_Logo,true); + else m_parentLayer->showComponent(m_iPad,eUIComponent_Logo,false); + + } +} + +UIScene_SettingsUIMenu::~UIScene_SettingsUIMenu() +{ +} + +wstring UIScene_SettingsUIMenu::getMoviePath() +{ + if(app.GetLocalPlayerCount() > 1) + { + return L"SettingsUIMenuSplit"; + } + else + { + return L"SettingsUIMenu"; + } +} + +void UIScene_SettingsUIMenu::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled) +{ + ui.AnimateKeyPress(iPad, key, repeat, pressed, released); + + switch(key) + { + case ACTION_MENU_CANCEL: + if(pressed) + { + // check the checkboxes + app.SetGameSettings(m_iPad,eGameSetting_DisplayHUD,m_checkboxDisplayHUD.IsChecked()?1:0); + app.SetGameSettings(m_iPad,eGameSetting_DisplayHand,m_checkboxDisplayHand.IsChecked()?1:0); + app.SetGameSettings(m_iPad,eGameSetting_DisplaySplitscreenGamertags,m_checkboxShowSplitscreenGamertags.IsChecked()?1:0); + app.SetGameSettings(m_iPad,eGameSetting_DeathMessages,m_checkboxDisplayDeathMessages.IsChecked()?1:0); + app.SetGameSettings(m_iPad,eGameSetting_AnimatedCharacter,m_checkboxDisplayAnimatedCharacter.IsChecked()?1:0); + + // if the splitscreen vertical/horizontal has changed, need to update the scenes + if(app.GetGameSettings(m_iPad,eGameSetting_SplitScreenVertical)!=(m_checkboxSplitscreen.IsChecked()?1:0)) + { + // changed + app.SetGameSettings(m_iPad,eGameSetting_SplitScreenVertical,m_checkboxSplitscreen.IsChecked()?1:0); + + // close the xui scenes, so we don't have the navigate backed to menu at the wrong place + if(app.GetLocalPlayerCount()==2) + { + ui.CloseAllPlayersScenes(); + } + else + { + navigateBack(); + } + } + else + { + navigateBack(); + } + handled = true; + } + break; + case ACTION_MENU_OK: +#ifdef __ORBIS__ + case ACTION_MENU_TOUCHPAD_PRESS: +#endif + sendInputToMovie(key, repeat, pressed, released); + break; + case ACTION_MENU_UP: + case ACTION_MENU_DOWN: + case ACTION_MENU_LEFT: + case ACTION_MENU_RIGHT: + sendInputToMovie(key, repeat, pressed, released); + break; + } +} + +void UIScene_SettingsUIMenu::handleSliderMove(F64 sliderId, F64 currentValue) +{ + WCHAR TempString[256]; + int value = (int)currentValue; + switch((int)sliderId) + { + case eControl_UISize: + m_sliderUISize.handleSliderMove(value); + + swprintf( (WCHAR *)TempString, 256, L"%ls: %d", app.GetString( IDS_SLIDER_UISIZE ),value); + m_sliderUISize.setLabel(TempString); + + // is this different from the current value? + if(value != app.GetGameSettings(m_iPad,eGameSetting_UISize)+1) + { + app.SetGameSettings(m_iPad,eGameSetting_UISize,value-1); + // Apply the changes to the selected text position + ui.UpdateSelectedItemPos(m_iPad); + } + + break; + case eControl_UISizeSplitscreen: + m_sliderUISizeSplitscreen.handleSliderMove(value); + + swprintf( (WCHAR *)TempString, 256, L"%ls: %d", app.GetString( IDS_SLIDER_UISIZESPLITSCREEN ),value); + m_sliderUISizeSplitscreen.setLabel(TempString); + + if(value != app.GetGameSettings(m_iPad,eGameSetting_UISizeSplitscreen)+1) + { + // slider is 1 to 3 + app.SetGameSettings(m_iPad,eGameSetting_UISizeSplitscreen,value-1); + // Apply the changes to the selected text position + ui.UpdateSelectedItemPos(m_iPad); + } + + break; + } +} diff --git a/Minecraft.Client/Common/UI/UIScene_SettingsUIMenu.h b/Minecraft.Client/Common/UI/UIScene_SettingsUIMenu.h new file mode 100644 index 00000000..8968bbe7 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_SettingsUIMenu.h @@ -0,0 +1,53 @@ +#pragma once + +#include "UIScene.h" + +class UIScene_SettingsUIMenu : public UIScene +{ +private: + enum EControls + { + eControl_DisplayHUD, + eControl_DisplayHand, + eControl_DisplayDeathMessages, + eControl_DisplayAnimatedCharacter, + eControl_Splitscreen, + eControl_ShowSplitscreenGamertags, + eControl_UISize, + eControl_UISizeSplitscreen + }; + + UIControl_CheckBox m_checkboxDisplayHUD, m_checkboxDisplayHand, m_checkboxDisplayDeathMessages, m_checkboxDisplayAnimatedCharacter, m_checkboxSplitscreen, m_checkboxShowSplitscreenGamertags; // Checkboxes + UIControl_Slider m_sliderUISize, m_sliderUISizeSplitscreen; // Sliders + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) + UI_MAP_ELEMENT( m_checkboxDisplayHUD, "DisplayHUD") + UI_MAP_ELEMENT( m_checkboxDisplayHand, "DisplayHand") + UI_MAP_ELEMENT( m_checkboxDisplayDeathMessages, "DisplayDeathMessages") + UI_MAP_ELEMENT( m_checkboxDisplayAnimatedCharacter, "DisplayAnimatedCharacter") + UI_MAP_ELEMENT( m_checkboxSplitscreen, "Splitscreen") + UI_MAP_ELEMENT( m_checkboxShowSplitscreenGamertags, "ShowSplitscreenGamertags") + + UI_MAP_ELEMENT( m_sliderUISize, "UISize") + UI_MAP_ELEMENT( m_sliderUISizeSplitscreen, "UISizeSplitscreen") + UI_END_MAP_ELEMENTS_AND_NAMES() + + bool m_bNotInGame; +public: + UIScene_SettingsUIMenu(int iPad, void *initData, UILayer *parentLayer); + virtual ~UIScene_SettingsUIMenu(); + + virtual EUIScene getSceneType() { return eUIScene_SettingsUIMenu;} + + virtual void updateTooltips(); + virtual void updateComponents(); + +protected: + // TODO: This should be pure virtual in this class + virtual wstring getMoviePath(); + +public: + // INPUT + virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled); + + virtual void handleSliderMove(F64 sliderId, F64 currentValue); +};
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIScene_SignEntryMenu.cpp b/Minecraft.Client/Common/UI/UIScene_SignEntryMenu.cpp new file mode 100644 index 00000000..c29bac2d --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_SignEntryMenu.cpp @@ -0,0 +1,206 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIScene_SignEntryMenu.h" +#include "..\..\Minecraft.h" +#include "..\..\MultiPlayerLocalPlayer.h" +#include "..\..\MultiPlayerLevel.h" +#include "..\..\ClientConnection.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.level.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.level.tile.entity.h" + +UIScene_SignEntryMenu::UIScene_SignEntryMenu(int iPad, void *_initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) +{ + // Setup all the Iggy references we need for this scene + initialiseMovie(); + + SignEntryScreenInput* initData = (SignEntryScreenInput*)_initData; + m_sign = initData->sign; + + m_bConfirmed = false; + m_bIgnoreInput = false; + + m_buttonConfirm.init(app.GetString(IDS_DONE), eControl_Confirm); + m_labelMessage.init(app.GetString(IDS_EDIT_SIGN_MESSAGE)); + + for(unsigned int i = 0; i<4; ++i) + { +#if TO_BE_IMPLEMENTED + // Have to have the Latin alphabet here, since that's what we have on the sign in-game + // but because the JAP/KOR/CHN fonts don't have extended European characters, let's restrict those languages to not having the extended character set, since they can't see what they are typing + switch(XGetLanguage()) + { + case XC_LANGUAGE_JAPANESE: + case XC_LANGUAGE_TCHINESE: + case XC_LANGUAGE_KOREAN: + case XC_LANGUAGE_RUSSIAN: + m_signRows[i].SetKeyboardType(C_4JInput::EKeyboardMode_Alphabet); + break; + default: + m_signRows[i].SetKeyboardType(C_4JInput::EKeyboardMode_Full); + break; + } + + m_signRows[i].SetText( m_sign->GetMessage(i).c_str() ); + m_signRows[i].SetTextLimit(15); + // Set the title and desc for the edit keyboard popup + m_signRows[i].SetTitleAndText(IDS_SIGN_TITLE,IDS_SIGN_TITLE_TEXT); +#endif + m_textInputLines[i].init(m_sign->GetMessage(i).c_str(), i); + } + + parentLayer->addComponent(iPad,eUIComponent_MenuBackground); +} + +UIScene_SignEntryMenu::~UIScene_SignEntryMenu() +{ + m_parentLayer->removeComponent(eUIComponent_MenuBackground); +} + +wstring UIScene_SignEntryMenu::getMoviePath() +{ + if(app.GetLocalPlayerCount() > 1) + { + return L"SignEntryMenuSplit"; + } + else + { + return L"SignEntryMenu"; + } +} + +void UIScene_SignEntryMenu::updateTooltips() +{ + ui.SetTooltips( m_iPad, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK); +} + +void UIScene_SignEntryMenu::tick() +{ + UIScene::tick(); + + if(m_bConfirmed) + { + m_bConfirmed = false; + + // Set the sign text here so we on;y call the verify once it has been set, not while we're typing in to it + for(int i=0;i<4;i++) + { + wstring temp=m_textInputLines[i].getLabel(); + m_sign->SetMessage(i,temp); + } + + m_sign->setChanged(); + + Minecraft *pMinecraft=Minecraft::GetInstance(); + // need to send the new data + if (pMinecraft->level->isClientSide) + { + shared_ptr<MultiplayerLocalPlayer> player = pMinecraft->localplayers[m_iPad]; + if(player != NULL && player->connection && player->connection->isStarted()) + { + player->connection->send( shared_ptr<SignUpdatePacket>( new SignUpdatePacket(m_sign->x, m_sign->y, m_sign->z, m_sign->IsVerified(), m_sign->IsCensored(), m_sign->GetMessages()) ) ); + } + } + ui.CloseUIScenes(m_iPad); + } +} + +void UIScene_SignEntryMenu::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled) +{ + if(m_bConfirmed || m_bIgnoreInput) return; + + ui.AnimateKeyPress(iPad, key, repeat, pressed, released); + + switch(key) + { + case ACTION_MENU_CANCEL: + if(pressed) + { + // user backed out, so wipe the sign + wstring temp=L""; + + for(int i=0;i<4;i++) + { + m_sign->SetMessage(i,temp); + } + + navigateBack(); + ui.PlayUISFX(eSFX_Back); + handled = true; + } + break; + case ACTION_MENU_OK: +#ifdef __ORBIS__ + case ACTION_MENU_TOUCHPAD_PRESS: +#endif + case ACTION_MENU_UP: + case ACTION_MENU_DOWN: + sendInputToMovie(key, repeat, pressed, released); + handled = true; + break; + } +} + +int UIScene_SignEntryMenu::KeyboardCompleteCallback(LPVOID lpParam,bool bRes) +{ + // 4J HEG - No reason to set value if keyboard was cancelled + UIScene_SignEntryMenu *pClass=(UIScene_SignEntryMenu *)lpParam; + pClass->m_bIgnoreInput = false; + if (bRes) + { + uint16_t pchText[128]; + ZeroMemory(pchText, 128 * sizeof(uint16_t) ); + InputManager.GetText(pchText); + pClass->m_textInputLines[pClass->m_iEditingLine].setLabel((wchar_t *)pchText); + } + return 0; +} + +void UIScene_SignEntryMenu::handlePress(F64 controlId, F64 childId) +{ + switch((int)controlId) + { + case eControl_Confirm: + { + m_bConfirmed = true; + } + break; + case eControl_Line1: + case eControl_Line2: + case eControl_Line3: + case eControl_Line4: + { + m_iEditingLine = (int)controlId; + m_bIgnoreInput = true; +#ifdef _XBOX_ONE + // 4J-PB - Xbox One uses the Windows virtual keyboard, and doesn't have the Xbox 360 Latin keyboard type, so we can't restrict the input set to alphanumeric. The closest we get is the emailSmtpAddress type. + int language = XGetLanguage(); + switch(language) + { + case XC_LANGUAGE_JAPANESE: + case XC_LANGUAGE_KOREAN: + case XC_LANGUAGE_TCHINESE: + InputManager.RequestKeyboard(app.GetString(IDS_SIGN_TITLE),m_textInputLines[m_iEditingLine].getLabel(),(DWORD)m_iPad,15,&UIScene_SignEntryMenu::KeyboardCompleteCallback,this,C_4JInput::EKeyboardMode_Email); + break; + default: + InputManager.RequestKeyboard(app.GetString(IDS_SIGN_TITLE),m_textInputLines[m_iEditingLine].getLabel(),(DWORD)m_iPad,15,&UIScene_SignEntryMenu::KeyboardCompleteCallback,this,C_4JInput::EKeyboardMode_Alphabet); + break; + } +#else + InputManager.RequestKeyboard(app.GetString(IDS_SIGN_TITLE),m_textInputLines[m_iEditingLine].getLabel(),(DWORD)m_iPad,15,&UIScene_SignEntryMenu::KeyboardCompleteCallback,this,C_4JInput::EKeyboardMode_Alphabet); +#endif + } + break; + } +} + +void UIScene_SignEntryMenu::handleDestroy() +{ +#ifdef __PSVITA__ + app.DebugPrintf("missing InputManager.DestroyKeyboard on Vita !!!!!!\n"); +#endif + + // another player destroyed the anvil, so shut down the keyboard if it is displayed +#if ( defined __PS3__ || defined __ORBIS__ || defined _DURANGO) + InputManager.DestroyKeyboard(); +#endif +}
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIScene_SignEntryMenu.h b/Minecraft.Client/Common/UI/UIScene_SignEntryMenu.h new file mode 100644 index 00000000..28b37d53 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_SignEntryMenu.h @@ -0,0 +1,58 @@ +#pragma once + +#include "UIScene.h" + +class SignTileEntity; + +class UIScene_SignEntryMenu : public UIScene +{ +private: + enum EControls + { + // Lines should be 0-3 + eControl_Line1, + eControl_Line2, + eControl_Line3, + eControl_Line4, + eControl_Confirm + }; + + shared_ptr<SignTileEntity> m_sign; + int m_iEditingLine; + bool m_bConfirmed; + bool m_bIgnoreInput; + + UIControl_Button m_buttonConfirm; + UIControl_Label m_labelMessage; + UIControl_TextInput m_textInputLines[4]; + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) + UI_MAP_ELEMENT( m_buttonConfirm, "Confirm") + UI_MAP_ELEMENT( m_labelMessage, "Message") + + UI_MAP_ELEMENT( m_textInputLines[0], "Line1") + UI_MAP_ELEMENT( m_textInputLines[1], "Line2") + UI_MAP_ELEMENT( m_textInputLines[2], "Line3") + UI_MAP_ELEMENT( m_textInputLines[3], "Line4") + UI_END_MAP_ELEMENTS_AND_NAMES() +public: + UIScene_SignEntryMenu(int iPad, void *initData, UILayer *parentLayer); + virtual ~UIScene_SignEntryMenu(); + + virtual EUIScene getSceneType() { return eUIScene_SignEntryMenu;} + virtual void updateTooltips(); + + virtual void tick(); + +protected: + // TODO: This should be pure virtual in this class + virtual wstring getMoviePath(); + +public: + // INPUT + virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled); + +protected: + void handlePress(F64 controlId, F64 childId); + static int KeyboardCompleteCallback(LPVOID lpParam,const bool bRes); + virtual void handleDestroy(); +};
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIScene_SkinSelectMenu.cpp b/Minecraft.Client/Common/UI/UIScene_SkinSelectMenu.cpp new file mode 100644 index 00000000..6910dd65 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_SkinSelectMenu.cpp @@ -0,0 +1,1798 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIScene_SkinSelectMenu.h" +#include "..\..\..\Minecraft.World\StringHelpers.h" +#ifdef __ORBIS__ +#include <error_dialog.h> +#elif defined __PSVITA__ +#include <message_dialog.h> +#endif + +#define SKIN_SELECT_PACK_DEFAULT 0 +#define SKIN_SELECT_PACK_FAVORITES 1 +//#define SKIN_SELECT_PACK_PLAYER_CUSTOM 1 +#define SKIN_SELECT_MAX_DEFAULTS 2 + +WCHAR *UIScene_SkinSelectMenu::wchDefaultNamesA[]= +{ + L"USE LOCALISED VERSION", // Server selected + L"Steve", + L"Tennis Steve", + L"Tuxedo Steve", + L"Athlete Steve", + L"Scottish Steve", + L"Prisoner Steve", + L"Cyclist Steve", + L"Boxer Steve", +}; + +UIScene_SkinSelectMenu::UIScene_SkinSelectMenu(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) +{ + // Setup all the Iggy references we need for this scene + initialiseMovie(); + + m_labelSelected.init( app.GetString( IDS_SELECTED ) ); + +#ifdef __ORBIS__ + m_bErrorDialogRunning=false; +#endif + + m_bIgnoreInput=false; + m_bNoSkinsToShow = false; + + m_currentPack = NULL; + m_packIndex = SKIN_SELECT_PACK_DEFAULT; + m_skinIndex = 0; + + m_originalSkinId = app.GetPlayerSkinId(iPad); + m_currentSkinPath = app.GetPlayerSkinName(iPad); + m_selectedSkinPath = L""; + m_selectedCapePath = L""; + m_vAdditionalSkinBoxes = NULL; + + m_bSlidingSkins = false; + m_bAnimatingMove = false; + m_bSkinIndexChanged = false; + + m_currentNavigation = eSkinNavigation_Skin; + + m_currentPackCount = 0; + + m_characters[eCharacter_Current].SetFacing(UIControl_PlayerSkinPreview::e_SkinPreviewFacing_Forward); + + m_characters[eCharacter_Next1].SetFacing(UIControl_PlayerSkinPreview::e_SkinPreviewFacing_Left); + m_characters[eCharacter_Next2].SetFacing(UIControl_PlayerSkinPreview::e_SkinPreviewFacing_Left); + m_characters[eCharacter_Next3].SetFacing(UIControl_PlayerSkinPreview::e_SkinPreviewFacing_Left); + m_characters[eCharacter_Next4].SetFacing(UIControl_PlayerSkinPreview::e_SkinPreviewFacing_Left); + + m_characters[eCharacter_Previous1].SetFacing(UIControl_PlayerSkinPreview::e_SkinPreviewFacing_Right); + m_characters[eCharacter_Previous2].SetFacing(UIControl_PlayerSkinPreview::e_SkinPreviewFacing_Right); + m_characters[eCharacter_Previous3].SetFacing(UIControl_PlayerSkinPreview::e_SkinPreviewFacing_Right); + m_characters[eCharacter_Previous4].SetFacing(UIControl_PlayerSkinPreview::e_SkinPreviewFacing_Right); + + m_labelSkinName.init(L""); + m_labelSkinOrigin.init(L""); + + m_leftLabel = L""; + m_centreLabel = L""; + m_rightLabel = L""; + +#ifdef __PSVITA__ + // initialise vita tab controls with ids + m_TouchTabLeft.init(ETouchInput_TabLeft); + m_TouchTabRight.init(ETouchInput_TabRight); + m_TouchTabCenter.init(ETouchInput_TabCenter); + m_TouchIggyCharacters.init(ETouchInput_IggyCharacters); +#endif + + // block input if we're waiting for DLC to install. The end of dlc mounting custom message will fill the save list + if(app.StartInstallDLCProcess(m_iPad)) + { + // DLC mounting in progress, so disable input + m_bIgnoreInput=true; + + m_controlTimer.setVisible( true ); + m_controlIggyCharacters.setVisible( false ); + m_controlSkinNamePlate.setVisible( false ); + + setCharacterLocked(false); + setCharacterSelected(false); + } + else + { + m_controlTimer.setVisible( false ); + + if(app.m_dlcManager.getPackCount(DLCManager::e_DLCType_Skin)>0) + { + // Change to display the favorites if there are any. The current skin will be in there (probably) - need to check for it + m_currentPack = app.m_dlcManager.getPackContainingSkin(m_currentSkinPath); + bool bFound; + if(m_currentPack != NULL) + { + m_packIndex = app.m_dlcManager.getPackIndex(m_currentPack,bFound,DLCManager::e_DLCType_Skin) + SKIN_SELECT_MAX_DEFAULTS; + } + } + + // If we have any favourites, set this to the favourites + // first validate the favorite skins - we might have uninstalled the DLC needed for them + app.ValidateFavoriteSkins(m_iPad); + + if(app.GetPlayerFavoriteSkinsCount(m_iPad)>0) + { + m_packIndex = SKIN_SELECT_PACK_FAVORITES; + } + + handlePackIndexChanged(); + } + + // Display the tooltips + +#ifdef __PSVITA__ + InitializeCriticalSection(&m_DLCInstallCS); // to prevent a race condition between the install and the mounted callback +#endif + +} + +void UIScene_SkinSelectMenu::updateTooltips() +{ + ui.SetTooltips( m_iPad, m_bNoSkinsToShow?-1:IDS_TOOLTIPS_SELECT_SKIN,IDS_TOOLTIPS_CANCEL,-1,-1,-1,-1,-1,-1,IDS_TOOLTIPS_NAVIGATE); +} + +void UIScene_SkinSelectMenu::updateComponents() +{ + m_parentLayer->showComponent(m_iPad,eUIComponent_Logo,false); +} + +wstring UIScene_SkinSelectMenu::getMoviePath() +{ + if(app.GetLocalPlayerCount() > 1) + { + return L"SkinSelectMenuSplit"; + } + else + { + return L"SkinSelectMenu"; + } +} + +void UIScene_SkinSelectMenu::tick() +{ + UIScene::tick(); + + if(m_bSkinIndexChanged) + { + m_bSkinIndexChanged = false; + handleSkinIndexChanged(); + } + + // check for new DLC installed + + // check for the patch error dialog +#ifdef __ORBIS__ + + // process the error dialog (for a patch being available) + if(m_bErrorDialogRunning) + { + SceErrorDialogStatus stat = sceErrorDialogUpdateStatus(); + if( stat == SCE_ERROR_DIALOG_STATUS_FINISHED ) + { + sceErrorDialogTerminate(); + m_bErrorDialogRunning=false; + } + } + +#endif +} + +void UIScene_SkinSelectMenu::handleAnimationEnd() +{ + if(m_bSlidingSkins) + { + m_bSlidingSkins = false; + + m_characters[eCharacter_Current].SetFacing(UIControl_PlayerSkinPreview::e_SkinPreviewFacing_Forward, false); + m_characters[eCharacter_Next1].SetFacing(UIControl_PlayerSkinPreview::e_SkinPreviewFacing_Left, false); + m_characters[eCharacter_Previous1].SetFacing(UIControl_PlayerSkinPreview::e_SkinPreviewFacing_Right, false); + + m_bSkinIndexChanged = true; + //handleSkinIndexChanged(); + + m_bAnimatingMove = false; + } +} + +void UIScene_SkinSelectMenu::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled) +{ + if (m_bIgnoreInput) return; + //app.DebugPrintf("UIScene_DebugOverlay handling input for pad %d, key %d, down- %s, pressed- %s, released- %s\n", iPad, key, down?"TRUE":"FALSE", pressed?"TRUE":"FALSE", released?"TRUE":"FALSE"); + + switch(key) + { + case ACTION_MENU_CANCEL: + if(pressed) + { + ui.AnimateKeyPress(iPad, key, repeat, pressed, released); + app.CheckGameSettingsChanged(true,iPad); + navigateBack(); + } + break; + case ACTION_MENU_OK: +#ifdef __ORBIS__ + case ACTION_MENU_TOUCHPAD_PRESS: +#endif + if(pressed) + { + ui.AnimateKeyPress(iPad, key, repeat, pressed, released); + // if the profile data has been changed, then force a profile write + // It seems we're allowed to break the 5 minute rule if it's the result of a user action + switch(m_packIndex) + { + case SKIN_SELECT_PACK_DEFAULT: + app.SetPlayerSkin(iPad, m_skinIndex); + app.SetPlayerCape(iPad, 0); + m_currentSkinPath = app.GetPlayerSkinName(iPad); + m_originalSkinId = app.GetPlayerSkinId(iPad); + setCharacterSelected(true); + ui.PlayUISFX(eSFX_Press); + break; + case SKIN_SELECT_PACK_FAVORITES: + if(app.GetPlayerFavoriteSkinsCount(iPad)>0) + { + // get the pack number from the skin id + wchar_t chars[256]; + swprintf(chars, 256, L"dlcskin%08d.png", app.GetPlayerFavoriteSkin(iPad,m_skinIndex)); + + DLCPack *Pack=app.m_dlcManager.getPackContainingSkin(chars); + + if(Pack) + { + DLCSkinFile *skinFile = Pack->getSkinFile(chars); + app.SetPlayerSkin(iPad, skinFile->getPath()); + app.SetPlayerCape(iPad, skinFile->getParameterAsString(DLCManager::e_DLCParamType_Cape)); + setCharacterSelected(true); + m_currentSkinPath = app.GetPlayerSkinName(iPad); + m_originalSkinId = app.GetPlayerSkinId(iPad); + app.SetPlayerFavoriteSkinsPos(iPad,m_skinIndex); + } + } + break; + default: + if( m_currentPack != NULL ) + { + DLCSkinFile *skinFile = m_currentPack->getSkinFile(m_skinIndex); + + if ( !skinFile->getParameterAsBool( DLCManager::e_DLCParamType_Free ) // Is this a free skin? + && !m_currentPack->hasPurchasedFile( DLCManager::e_DLCType_Skin, skinFile->getPath() ) // do we have a license? + ) + { + // 4J-PB - check for a patch +#ifdef __ORBIS__ + // 4J-PB - Check if there is a patch for the game + int errorCode = ProfileManager.getNPAvailability(ProfileManager.GetPrimaryPad()); + + bool bPatchAvailable; + switch(errorCode) + { + case SCE_NP_ERROR_LATEST_PATCH_PKG_EXIST: + case SCE_NP_ERROR_LATEST_PATCH_PKG_DOWNLOADED: + bPatchAvailable=true; + break; + default: + bPatchAvailable=false; + break; + } + + if(bPatchAvailable) + { + int32_t ret=sceErrorDialogInitialize(); + m_bErrorDialogRunning=true; + if ( ret==SCE_OK ) + { + SceErrorDialogParam param; + sceErrorDialogParamInitialize( ¶m ); + // 4J-PB - We want to display the option to get the patch now + param.errorCode = SCE_NP_ERROR_LATEST_PATCH_PKG_DOWNLOADED;//pClass->m_errorCode; + ret = sceUserServiceGetInitialUser( ¶m.userId ); + if ( ret == SCE_OK ) + { + ret=sceErrorDialogOpen( ¶m ); + break; + } + } + } +#endif + + // no + UINT uiIDA[1] = { IDS_OK }; +#ifdef __ORBIS__ + // Check if PSN is unavailable because of age restriction + int npAvailability = ProfileManager.getNPAvailability(iPad); + if (npAvailability == SCE_NP_ERROR_AGE_RESTRICTION) + { + ui.RequestMessageBox(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, iPad, NULL, NULL, app.GetStringTable()); + } + else +#endif + // We need to upsell the full version + if(ProfileManager.IsGuest(iPad)) + { + // can't buy + ui.RequestMessageBox(IDS_PRO_GUESTPROFILE_TITLE, IDS_PRO_GUESTPROFILE_TEXT, uiIDA, 1,iPad,NULL,NULL,app.GetStringTable(),NULL,0,false); + } + // are we online? + else if(!ProfileManager.IsSignedInLive(iPad)) + { + showNotOnlineDialog(iPad); + } + else + { + // upsell +#ifdef _XBOX + DLC_INFO *pDLCInfo = app.GetDLCInfoForTrialOfferID(m_currentPack->getPurchaseOfferId()); + ULONGLONG ullOfferID_Full; + + if(pDLCInfo!=NULL) + { + ullOfferID_Full=pDLCInfo->ullOfferID_Full; + } + else + { + ullOfferID_Full=m_currentPack->getPurchaseOfferId(); + } + + // tell sentient about the upsell of the full version of the skin pack + TelemetryManager->RecordUpsellPresented(iPad, eSet_UpsellID_Skin_DLC, ullOfferID_Full & 0xFFFFFFFF); +#endif + bool bContentRestricted=false; +#if defined(__PS3__) || defined(__PSVITA__) + ProfileManager.GetChatAndContentRestrictions(m_iPad,true,NULL,&bContentRestricted,NULL); +#endif + if(bContentRestricted) + { +#if !(defined(_XBOX) || defined(_WIN64)) // 4J Stu - Temp to get the win build running, but so we check this for other platforms + // you can't see the store + UINT uiIDA[1] = { IDS_CONFIRM_OK }; + ui.RequestMessageBox(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, iPad,NULL,this, app.GetStringTable(),NULL,0,false); +#endif + } + else + { + // 4J-PB - need to check for an empty store +#if defined __ORBIS__ || defined __PSVITA__ || defined __PS3__ + if(app.CheckForEmptyStore(iPad)==false) +#endif + { + this->m_bIgnoreInput = true; + + UINT uiIDA[2] = { IDS_CONFIRM_OK, IDS_CONFIRM_CANCEL }; + ui.RequestMessageBox(IDS_UNLOCK_DLC_TITLE, IDS_UNLOCK_DLC_SKIN, uiIDA, 2, iPad,&UIScene_SkinSelectMenu::UnlockSkinReturned,this,app.GetStringTable(),NULL,0,false); + } + } + } + } + else + { + app.SetPlayerSkin(iPad, skinFile->getPath()); + app.SetPlayerCape(iPad, skinFile->getParameterAsString(DLCManager::e_DLCParamType_Cape)); + setCharacterSelected(true); + m_currentSkinPath = app.GetPlayerSkinName(iPad); + m_originalSkinId = app.GetPlayerSkinId(iPad); + + // push this onto the favorite list + AddFavoriteSkin(iPad,GET_DLC_SKIN_ID_FROM_BITMASK(m_originalSkinId)); + } + } + + ui.PlayUISFX(eSFX_Press); + break; + } + } + break; + case ACTION_MENU_UP: + case ACTION_MENU_DOWN: + if(pressed) + { + if(m_packIndex==SKIN_SELECT_PACK_FAVORITES) + { + if(app.GetPlayerFavoriteSkinsCount(iPad)==0) + { + // ignore this, since there are no skins being displayed + break; + } + } + + ui.AnimateKeyPress(iPad, key, repeat, pressed, released); + ui.PlayUISFX(eSFX_Scroll); + switch(m_currentNavigation) + { + case eSkinNavigation_Pack: + m_currentNavigation = eSkinNavigation_Skin; + break; + case eSkinNavigation_Skin: + m_currentNavigation = eSkinNavigation_Pack; + break; + }; + sendInputToMovie(key, repeat, pressed, released); + } + break; + case ACTION_MENU_LEFT: + if(pressed) + { + if( m_currentNavigation == eSkinNavigation_Skin ) + { + if(!m_bAnimatingMove) + { + ui.AnimateKeyPress(iPad, key, repeat, pressed, released); + ui.PlayUISFX(eSFX_Scroll); + + m_skinIndex = getPreviousSkinIndex(m_skinIndex); + //handleSkinIndexChanged(); + + m_bSlidingSkins = true; + m_bAnimatingMove = true; + + m_characters[eCharacter_Current].SetFacing(UIControl_PlayerSkinPreview::e_SkinPreviewFacing_Left, true); + m_characters[eCharacter_Previous1].SetFacing(UIControl_PlayerSkinPreview::e_SkinPreviewFacing_Forward, true); + + // 4J Stu - Swapped nav buttons + sendInputToMovie(ACTION_MENU_RIGHT, repeat, pressed, released); + } + } + else if( m_currentNavigation == eSkinNavigation_Pack ) + { + ui.AnimateKeyPress(iPad, key, repeat, pressed, released); + ui.PlayUISFX(eSFX_Scroll); + DWORD startingIndex = m_packIndex; + m_packIndex = getPreviousPackIndex(m_packIndex); + if(startingIndex != m_packIndex) + { + handlePackIndexChanged(); + } + } + } + break; + case ACTION_MENU_RIGHT: + if(pressed) + { + if( m_currentNavigation == eSkinNavigation_Skin ) + { + if(!m_bAnimatingMove) + { + ui.AnimateKeyPress(iPad, key, repeat, pressed, released); + ui.PlayUISFX(eSFX_Scroll); + m_skinIndex = getNextSkinIndex(m_skinIndex); + //handleSkinIndexChanged(); + + m_bSlidingSkins = true; + m_bAnimatingMove = true; + + m_characters[eCharacter_Current].SetFacing(UIControl_PlayerSkinPreview::e_SkinPreviewFacing_Right, true); + m_characters[eCharacter_Next1].SetFacing(UIControl_PlayerSkinPreview::e_SkinPreviewFacing_Forward, true); + + // 4J Stu - Swapped nav buttons + sendInputToMovie(ACTION_MENU_LEFT, repeat, pressed, released); + } + } + else if( m_currentNavigation == eSkinNavigation_Pack ) + { + ui.AnimateKeyPress(iPad, key, repeat, pressed, released); + ui.PlayUISFX(eSFX_Scroll); + DWORD startingIndex = m_packIndex; + m_packIndex = getNextPackIndex(m_packIndex); + if(startingIndex != m_packIndex) + { + handlePackIndexChanged(); + } + } + } + break; + case ACTION_MENU_OTHER_STICK_PRESS: + if(pressed) + { + ui.PlayUISFX(eSFX_Press); + if( m_currentNavigation == eSkinNavigation_Skin ) + { + m_characters[eCharacter_Current].ResetRotation(); + } + } + break; + case ACTION_MENU_OTHER_STICK_LEFT: + if(pressed) + { + if( m_currentNavigation == eSkinNavigation_Skin ) + { + m_characters[eCharacter_Current].m_incYRot = true; + } + else + { + ui.PlayUISFX(eSFX_Scroll); + } + } + else if(released) + { + m_characters[eCharacter_Current].m_incYRot = false; + } + break; + case ACTION_MENU_OTHER_STICK_RIGHT: + if(pressed) + { + if( m_currentNavigation == eSkinNavigation_Skin ) + { + m_characters[eCharacter_Current].m_decYRot = true; + } + else + { + ui.PlayUISFX(eSFX_Scroll); + } + } + else if(released) + { + m_characters[eCharacter_Current].m_decYRot = false; + } + break; + case ACTION_MENU_OTHER_STICK_UP: + if(pressed) + { + if( m_currentNavigation == eSkinNavigation_Skin ) + { + //m_previewControl->m_incXRot = true; + m_characters[eCharacter_Current].CyclePreviousAnimation(); + } + else + { + ui.PlayUISFX(eSFX_Scroll); + } + } + break; + case ACTION_MENU_OTHER_STICK_DOWN: + if(pressed) + { + if( m_currentNavigation == eSkinNavigation_Skin ) + { + //m_previewControl->m_decXRot = true; + m_characters[eCharacter_Current].CycleNextAnimation(); + } + else + { + ui.PlayUISFX(eSFX_Scroll); + } + } + break; + } +} + +void UIScene_SkinSelectMenu::InputActionOK(unsigned int iPad) +{ + ui.AnimateKeyPress(iPad, ACTION_MENU_OK, false, true, false); + + // if the profile data has been changed, then force a profile write + // It seems we're allowed to break the 5 minute rule if it's the result of a user action + switch(m_packIndex) + { + case SKIN_SELECT_PACK_DEFAULT: + app.SetPlayerSkin(iPad, m_skinIndex); + app.SetPlayerCape(iPad, 0); + m_currentSkinPath = app.GetPlayerSkinName(iPad); + m_originalSkinId = app.GetPlayerSkinId(iPad); + setCharacterSelected(true); + ui.PlayUISFX(eSFX_Press); + break; + case SKIN_SELECT_PACK_FAVORITES: + if(app.GetPlayerFavoriteSkinsCount(iPad)>0) + { + // get the pack number from the skin id + wchar_t chars[256]; + swprintf(chars, 256, L"dlcskin%08d.png", app.GetPlayerFavoriteSkin(iPad,m_skinIndex)); + + DLCPack *Pack=app.m_dlcManager.getPackContainingSkin(chars); + + if(Pack) + { + DLCSkinFile *skinFile = Pack->getSkinFile(chars); + app.SetPlayerSkin(iPad, skinFile->getPath()); + app.SetPlayerCape(iPad, skinFile->getParameterAsString(DLCManager::e_DLCParamType_Cape)); + setCharacterSelected(true); + m_currentSkinPath = app.GetPlayerSkinName(iPad); + m_originalSkinId = app.GetPlayerSkinId(iPad); + app.SetPlayerFavoriteSkinsPos(iPad,m_skinIndex); + } +} + break; + default: + if( m_currentPack != NULL ) + { + bool renableInputAfterOperation = true; + m_bIgnoreInput = true; + + DLCSkinFile *skinFile = m_currentPack->getSkinFile(m_skinIndex); + + // Is this a free skin? + + if(!skinFile->getParameterAsBool( DLCManager::e_DLCParamType_Free )) + { + // do we have a license? + //if(true) + if(!m_currentPack->hasPurchasedFile( DLCManager::e_DLCType_Skin, skinFile->getPath() )) + { + // no + UINT uiIDA[1]; + uiIDA[0]=IDS_OK; + + // We need to upsell the full version + if(ProfileManager.IsGuest(iPad)) + { + // can't buy + ui.RequestMessageBox(IDS_PRO_GUESTPROFILE_TITLE, IDS_PRO_GUESTPROFILE_TEXT, uiIDA, 1,iPad,NULL,NULL,app.GetStringTable(),NULL,0,false); + } +#if defined(__PS3__) || defined(__ORBIS__) + // are we online? + else if(!ProfileManager.IsSignedInLive(iPad)) + { + showNotOnlineDialog(iPad); + } +#endif + else + { + // upsell +#ifdef _XBOX + DLC_INFO *pDLCInfo = app.GetDLCInfoForTrialOfferID(m_currentPack->getPurchaseOfferId()); + ULONGLONG ullOfferID_Full; + + if(pDLCInfo!=NULL) + { + ullOfferID_Full=pDLCInfo->ullOfferID_Full; + } + else + { + ullOfferID_Full=m_currentPack->getPurchaseOfferId(); + } + + // tell sentient about the upsell of the full version of the skin pack + SentientManager.RecordUpsellPresented(iPad, eSet_UpsellID_Skin_DLC, ullOfferID_Full & 0xFFFFFFFF); +#endif + bool bContentRestricted=false; +#if defined(__PS3__) || defined(__PSVITA__) + ProfileManager.GetChatAndContentRestrictions(m_iPad,true,NULL,&bContentRestricted,NULL); +#endif + if(bContentRestricted) + { +#if !(defined(_XBOX) || defined(_WIN64)) // 4J Stu - Temp to get the win build running, but so we check this for other platforms + // you can't see the store + UINT uiIDA[1]; + uiIDA[0]=IDS_CONFIRM_OK; + ui.RequestMessageBox(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, ProfileManager.GetPrimaryPad(),NULL,this, app.GetStringTable(),NULL,0,false); +#endif + } + else + { + // 4J-PB - need to check for an empty store +#if defined __ORBIS__ || defined __PSVITA__ || defined __PS3__ + if(app.CheckForEmptyStore(iPad)==false) +#endif + { + m_bIgnoreInput = true; + renableInputAfterOperation = false; + + UINT uiIDA[2] = { IDS_CONFIRM_OK, IDS_CONFIRM_CANCEL }; + ui.RequestMessageBox(IDS_UNLOCK_DLC_TITLE, IDS_UNLOCK_DLC_SKIN, uiIDA, 2, iPad,&UIScene_SkinSelectMenu::UnlockSkinReturned,this,app.GetStringTable(),NULL,0,false); + } + } + } + } + else + { + app.SetPlayerSkin(iPad, skinFile->getPath()); + app.SetPlayerCape(iPad, skinFile->getParameterAsString(DLCManager::e_DLCParamType_Cape)); + setCharacterSelected(true); + m_currentSkinPath = app.GetPlayerSkinName(iPad); + m_originalSkinId = app.GetPlayerSkinId(iPad); + + // push this onto the favorite list + AddFavoriteSkin(m_iPad,GET_DLC_SKIN_ID_FROM_BITMASK(m_originalSkinId)); + } + } + else + { + app.SetPlayerSkin(iPad, skinFile->getPath()); + app.SetPlayerCape(iPad, skinFile->getParameterAsString(DLCManager::e_DLCParamType_Cape)); + setCharacterSelected(true); + m_currentSkinPath = app.GetPlayerSkinName(iPad); + m_originalSkinId = app.GetPlayerSkinId(iPad); + + // push this onto the favorite list + AddFavoriteSkin(iPad,GET_DLC_SKIN_ID_FROM_BITMASK(m_originalSkinId)); + } + + if (renableInputAfterOperation) m_bIgnoreInput = false; + } + + ui.PlayUISFX(eSFX_Press); + break; + } +} + +void UIScene_SkinSelectMenu::customDraw(IggyCustomDrawCallbackRegion *region) +{ + int characterId = -1; + swscanf((wchar_t*)region->name,L"Character%d",&characterId); + if (characterId == -1) + { + app.DebugPrintf("Invalid character to render found\n"); + } + else + { + // Setup GDraw, normal game render states and matrices + CustomDrawData *customDrawRegion = ui.setupCustomDraw(this,region); + delete customDrawRegion; + + //app.DebugPrintf("Scissor x0= %d, y0= %d, x1= %d, y1= %d\n", region->scissor_x0, region->scissor_y0, region->scissor_x1, region->scissor_y1); + //app.DebugPrintf("Stencil mask= %d, stencil ref= %d, stencil write= %d\n", region->stencil_func_mask, region->stencil_func_ref, region->stencil_write_mask); +#ifdef __PS3__ + if(region->stencil_func_ref != 0) RenderManager.StateSetStencil(GL_EQUAL,region->stencil_func_ref,region->stencil_func_mask); +#elif __PSVITA__ + // AP - make sure the skins are only drawn inside the smokey panel + if(region->stencil_func_ref != 0) RenderManager.StateSetStencil(SCE_GXM_STENCIL_FUNC_EQUAL,region->stencil_func_mask,region->stencil_write_mask); +#else + if(region->stencil_func_ref != 0) RenderManager.StateSetStencil(GL_EQUAL,region->stencil_func_ref, region->stencil_func_mask,region->stencil_write_mask); +#endif + m_characters[characterId].render(region); + + // Finish GDraw and anything else that needs to be finalised + ui.endCustomDraw(region); + } +} + +void UIScene_SkinSelectMenu::handleSkinIndexChanged() +{ + BOOL showPrevious = FALSE, showNext = FALSE; + DWORD previousIndex = 0, nextIndex = 0; + wstring skinName = L""; + wstring skinOrigin = L""; + bool bSkinIsFree=false; + bool bLicensed=false; + DLCSkinFile *skinFile=NULL; + DLCPack *Pack=NULL; + BYTE sidePreviewControlsL,sidePreviewControlsR; + m_bNoSkinsToShow=false; + + TEXTURE_NAME backupTexture = TN_MOB_CHAR; + + setCharacterSelected(false); + + m_controlSkinNamePlate.setVisible( false ); + + if( m_currentPack != NULL ) + { + skinFile = m_currentPack->getSkinFile(m_skinIndex); + m_selectedSkinPath = skinFile->getPath(); + m_selectedCapePath = skinFile->getParameterAsString(DLCManager::e_DLCParamType_Cape); + m_vAdditionalSkinBoxes = skinFile->getAdditionalBoxes(); + + skinName = skinFile->getParameterAsString( DLCManager::e_DLCParamType_DisplayName ); + skinOrigin = skinFile->getParameterAsString( DLCManager::e_DLCParamType_ThemeName ); + + if( m_selectedSkinPath.compare( m_currentSkinPath ) == 0 ) + { + setCharacterSelected(true); + } + + bSkinIsFree = skinFile->getParameterAsBool( DLCManager::e_DLCParamType_Free ); + bLicensed = m_currentPack->hasPurchasedFile( DLCManager::e_DLCType_Skin, m_selectedSkinPath ); + + setCharacterLocked(!(bSkinIsFree || bLicensed)); + + m_characters[eCharacter_Current].setVisible(true); + m_controlSkinNamePlate.setVisible( true ); + } + else + { + m_selectedSkinPath = L""; + m_selectedCapePath = L""; + m_vAdditionalSkinBoxes = NULL; + + switch(m_packIndex) + { + case SKIN_SELECT_PACK_DEFAULT: + backupTexture = getTextureId(m_skinIndex); + + if( m_skinIndex == eDefaultSkins_ServerSelected ) + { + skinName = app.GetString(IDS_DEFAULT_SKINS); + } + else + { + skinName = wchDefaultNamesA[m_skinIndex]; + } + + if( m_originalSkinId == m_skinIndex ) + { + setCharacterSelected(true); + } + setCharacterLocked(false); + setCharacterLocked(false); + + m_characters[eCharacter_Current].setVisible(true); + m_controlSkinNamePlate.setVisible( true ); + + break; + case SKIN_SELECT_PACK_FAVORITES: + + if(app.GetPlayerFavoriteSkinsCount(m_iPad)>0) + { + // get the pack number from the skin id + wchar_t chars[256]; + swprintf(chars, 256, L"dlcskin%08d.png", app.GetPlayerFavoriteSkin(m_iPad,m_skinIndex)); + + Pack=app.m_dlcManager.getPackContainingSkin(chars); + if(Pack) + { + skinFile = Pack->getSkinFile(chars); + + m_selectedSkinPath = skinFile->getPath(); + m_selectedCapePath = skinFile->getParameterAsString(DLCManager::e_DLCParamType_Cape); + m_vAdditionalSkinBoxes = skinFile->getAdditionalBoxes(); + + skinName = skinFile->getParameterAsString( DLCManager::e_DLCParamType_DisplayName ); + skinOrigin = skinFile->getParameterAsString( DLCManager::e_DLCParamType_ThemeName ); + + if( m_selectedSkinPath.compare( m_currentSkinPath ) == 0 ) + { + setCharacterSelected(true); + } + + bSkinIsFree = skinFile->getParameterAsBool( DLCManager::e_DLCParamType_Free ); + bLicensed = Pack->hasPurchasedFile( DLCManager::e_DLCType_Skin, m_selectedSkinPath ); + + setCharacterLocked(!(bSkinIsFree || bLicensed)); + m_controlSkinNamePlate.setVisible( true ); + } + else + { + setCharacterSelected(false); + setCharacterLocked(false); + } + } + else + { + //disable the display + m_characters[eCharacter_Current].setVisible(false); + + // change the tooltips + m_bNoSkinsToShow=true; + } + break; + } + } + + m_labelSkinName.setLabel(skinName); + m_labelSkinOrigin.setLabel(skinOrigin); + + + if(m_vAdditionalSkinBoxes && m_vAdditionalSkinBoxes->size()!=0) + { + // add the boxes to the humanoid model, but only if we've not done this already + + vector<ModelPart *> *pAdditionalModelParts = app.GetAdditionalModelParts(skinFile->getSkinID()); + if(pAdditionalModelParts==NULL) + { + pAdditionalModelParts = app.SetAdditionalSkinBoxes(skinFile->getSkinID(),m_vAdditionalSkinBoxes); + } + } + + if(skinFile!=NULL) + { + app.SetAnimOverrideBitmask(skinFile->getSkinID(),skinFile->getAnimOverrideBitmask()); + } + + m_characters[eCharacter_Current].SetTexture(m_selectedSkinPath, backupTexture); + m_characters[eCharacter_Current].SetCapeTexture(m_selectedCapePath); + + showNext = TRUE; + showPrevious = TRUE; + nextIndex = getNextSkinIndex(m_skinIndex); + previousIndex = getPreviousSkinIndex(m_skinIndex); + + wstring otherSkinPath = L""; + wstring otherCapePath = L""; + vector<SKIN_BOX *> *othervAdditionalSkinBoxes=NULL; + wchar_t chars[256]; + + // turn off all displays + for(unsigned int i = eCharacter_Current + 1; i < eCharacter_COUNT; ++i) + { + m_characters[i].setVisible(false); + } + + unsigned int uiCurrentFavoriteC=app.GetPlayerFavoriteSkinsCount(m_iPad); + + if(m_packIndex==SKIN_SELECT_PACK_FAVORITES) + { + // might not be enough to cycle through + if(uiCurrentFavoriteC<((sidePreviewControls*2)+1)) + { + if(uiCurrentFavoriteC==0) + { + sidePreviewControlsL=sidePreviewControlsR=0; + } + // might be an odd number + else if((uiCurrentFavoriteC-1)%2==1) + { + sidePreviewControlsL=1+(uiCurrentFavoriteC-1)/2; + sidePreviewControlsR=(uiCurrentFavoriteC-1)/2; + } + else + { + sidePreviewControlsL=sidePreviewControlsR=(uiCurrentFavoriteC-1)/2; + } + } + else + { + sidePreviewControlsL=sidePreviewControlsR=sidePreviewControls; + } + } + else + { + sidePreviewControlsL=sidePreviewControlsR=sidePreviewControls; + } + + for(BYTE i = 0; i < sidePreviewControlsR; ++i) + { + if(showNext) + { + skinFile=NULL; + + m_characters[eCharacter_Next1 + i].setVisible(true); + + if( m_currentPack != NULL ) + { + skinFile = m_currentPack->getSkinFile(nextIndex); + otherSkinPath = skinFile->getPath(); + otherCapePath = skinFile->getParameterAsString(DLCManager::e_DLCParamType_Cape); + othervAdditionalSkinBoxes = skinFile->getAdditionalBoxes(); + backupTexture = TN_MOB_CHAR; + } + else + { + otherSkinPath = L""; + otherCapePath = L""; + othervAdditionalSkinBoxes=NULL; + switch(m_packIndex) + { + case SKIN_SELECT_PACK_DEFAULT: + backupTexture = getTextureId(nextIndex); + break; + case SKIN_SELECT_PACK_FAVORITES: + if(uiCurrentFavoriteC>0) + { + // get the pack number from the skin id + swprintf(chars, 256, L"dlcskin%08d.png", app.GetPlayerFavoriteSkin(m_iPad,nextIndex)); + + Pack=app.m_dlcManager.getPackContainingSkin(chars); + if(Pack) + { + skinFile = Pack->getSkinFile(chars); + + otherSkinPath = skinFile->getPath(); + otherCapePath = skinFile->getParameterAsString(DLCManager::e_DLCParamType_Cape); + othervAdditionalSkinBoxes = skinFile->getAdditionalBoxes(); + backupTexture = TN_MOB_CHAR; + } + } + break; + default: + break; + } + + } + if(othervAdditionalSkinBoxes && othervAdditionalSkinBoxes->size()!=0) + { + vector<ModelPart *> *pAdditionalModelParts = app.GetAdditionalModelParts(skinFile->getSkinID()); + if(pAdditionalModelParts==NULL) + { + pAdditionalModelParts = app.SetAdditionalSkinBoxes(skinFile->getSkinID(),othervAdditionalSkinBoxes); + } + } + // 4J-PB - anim override needs set before SetTexture + if(skinFile!=NULL) + { + app.SetAnimOverrideBitmask(skinFile->getSkinID(),skinFile->getAnimOverrideBitmask()); + } + m_characters[eCharacter_Next1 + i].SetTexture(otherSkinPath, backupTexture); + m_characters[eCharacter_Next1 + i].SetCapeTexture(otherCapePath); + } + + nextIndex = getNextSkinIndex(nextIndex); + } + + + + for(BYTE i = 0; i < sidePreviewControlsL; ++i) + { + if(showPrevious) + { + skinFile=NULL; + + m_characters[eCharacter_Previous1 + i].setVisible(true); + + if( m_currentPack != NULL ) + { + skinFile = m_currentPack->getSkinFile(previousIndex); + otherSkinPath = skinFile->getPath(); + otherCapePath = skinFile->getParameterAsString(DLCManager::e_DLCParamType_Cape); + othervAdditionalSkinBoxes = skinFile->getAdditionalBoxes(); + backupTexture = TN_MOB_CHAR; + } + else + { + otherSkinPath = L""; + otherCapePath = L""; + othervAdditionalSkinBoxes=NULL; + switch(m_packIndex) + { + case SKIN_SELECT_PACK_DEFAULT: + backupTexture = getTextureId(previousIndex); + break; + case SKIN_SELECT_PACK_FAVORITES: + if(uiCurrentFavoriteC>0) + { + // get the pack number from the skin id + swprintf(chars, 256, L"dlcskin%08d.png", app.GetPlayerFavoriteSkin(m_iPad,previousIndex)); + + Pack=app.m_dlcManager.getPackContainingSkin(chars); + if(Pack) + { + skinFile = Pack->getSkinFile(chars); + + otherSkinPath = skinFile->getPath(); + otherCapePath = skinFile->getParameterAsString(DLCManager::e_DLCParamType_Cape); + othervAdditionalSkinBoxes = skinFile->getAdditionalBoxes(); + backupTexture = TN_MOB_CHAR; + } + } + + break; + default: + break; + } + } + if(othervAdditionalSkinBoxes && othervAdditionalSkinBoxes->size()!=0) + { + vector<ModelPart *> *pAdditionalModelParts = app.GetAdditionalModelParts(skinFile->getSkinID()); + if(pAdditionalModelParts==NULL) + { + pAdditionalModelParts = app.SetAdditionalSkinBoxes(skinFile->getSkinID(),othervAdditionalSkinBoxes); + } + } + // 4J-PB - anim override needs set before SetTexture + if(skinFile) + { + app.SetAnimOverrideBitmask(skinFile->getSkinID(),skinFile->getAnimOverrideBitmask()); + } + m_characters[eCharacter_Previous1 + i].SetTexture(otherSkinPath, backupTexture); + m_characters[eCharacter_Previous1 + i].SetCapeTexture(otherCapePath); + } + + previousIndex = getPreviousSkinIndex(previousIndex); + } + + updateTooltips(); +} + +TEXTURE_NAME UIScene_SkinSelectMenu::getTextureId(int skinIndex) +{ + TEXTURE_NAME texture = TN_MOB_CHAR; + switch(skinIndex) + { + case eDefaultSkins_ServerSelected: + case eDefaultSkins_Skin0: + texture = TN_MOB_CHAR; + break; + case eDefaultSkins_Skin1: + texture = TN_MOB_CHAR1; + break; + case eDefaultSkins_Skin2: + texture = TN_MOB_CHAR2; + break; + case eDefaultSkins_Skin3: + texture = TN_MOB_CHAR3; + break; + case eDefaultSkins_Skin4: + texture = TN_MOB_CHAR4; + break; + case eDefaultSkins_Skin5: + texture = TN_MOB_CHAR5; + break; + case eDefaultSkins_Skin6: + texture = TN_MOB_CHAR6; + break; + case eDefaultSkins_Skin7: + texture = TN_MOB_CHAR7; + break; + }; + + return texture; +} + +int UIScene_SkinSelectMenu::getNextSkinIndex(DWORD sourceIndex) +{ + int nextSkin = sourceIndex; + + // special case for favourites + switch(m_packIndex) + { + + case SKIN_SELECT_PACK_FAVORITES: + ++nextSkin; + if(nextSkin>=app.GetPlayerFavoriteSkinsCount(m_iPad)) + { + nextSkin=0; + } + + break; + default: + ++nextSkin; + + if(m_packIndex == SKIN_SELECT_PACK_DEFAULT && nextSkin >= eDefaultSkins_Count) + { + nextSkin = eDefaultSkins_ServerSelected; + } + else if(m_currentPack != NULL && nextSkin>=m_currentPack->getSkinCount()) + { + nextSkin = 0; + } + break; + } + + + return nextSkin; +} + +int UIScene_SkinSelectMenu::getPreviousSkinIndex(DWORD sourceIndex) +{ + int previousSkin = sourceIndex; + switch(m_packIndex) + { + + case SKIN_SELECT_PACK_FAVORITES: + if(previousSkin==0) + { + previousSkin = app.GetPlayerFavoriteSkinsCount(m_iPad) - 1; + } + else + { + --previousSkin; + } + break; + default: + if(previousSkin==0) + { + if(m_packIndex == SKIN_SELECT_PACK_DEFAULT) + { + previousSkin = eDefaultSkins_Count - 1; + } + else if(m_currentPack != NULL) + { + previousSkin = m_currentPack->getSkinCount()-1; + } + } + else + { + --previousSkin; + } + break; + } + + + return previousSkin; +} + +void UIScene_SkinSelectMenu::handlePackIndexChanged() +{ + if(m_packIndex >= SKIN_SELECT_MAX_DEFAULTS) + { + m_currentPack = app.m_dlcManager.getPack(m_packIndex - SKIN_SELECT_MAX_DEFAULTS, DLCManager::e_DLCType_Skin); + } + else + { + m_currentPack = NULL; + } + m_skinIndex = 0; + if(m_currentPack != NULL) + { + bool found; + DWORD currentSkinIndex = m_currentPack->getSkinIndexAt(m_currentSkinPath, found); + if(found) m_skinIndex = currentSkinIndex; + } + else + { + switch(m_packIndex) + { + case SKIN_SELECT_PACK_DEFAULT: + if( !GET_IS_DLC_SKIN_FROM_BITMASK(m_originalSkinId) ) + { + DWORD ugcSkinIndex = GET_UGC_SKIN_ID_FROM_BITMASK(m_originalSkinId); + DWORD defaultSkinIndex = GET_DEFAULT_SKIN_ID_FROM_BITMASK(m_originalSkinId); + if( ugcSkinIndex == 0 ) + { + m_skinIndex = (EDefaultSkins) defaultSkinIndex; + } + } + break; + case SKIN_SELECT_PACK_FAVORITES: + if(app.GetPlayerFavoriteSkinsCount(m_iPad)>0) + { + bool found; + wchar_t chars[256]; + // get the pack number from the skin id + swprintf(chars, 256, L"dlcskin%08d.png", app.GetPlayerFavoriteSkin(m_iPad,app.GetPlayerFavoriteSkinsPos(m_iPad))); + + DLCPack *Pack=app.m_dlcManager.getPackContainingSkin(chars); + if(Pack) + { + DWORD currentSkinIndex = Pack->getSkinIndexAt(m_currentSkinPath, found); + if(found) m_skinIndex = app.GetPlayerFavoriteSkinsPos(m_iPad); + } + } + break; + default: + break; + } + } + handleSkinIndexChanged(); + updatePackDisplay(); +} + +void UIScene_SkinSelectMenu::updatePackDisplay() +{ + m_currentPackCount = app.m_dlcManager.getPackCount(DLCManager::e_DLCType_Skin) + SKIN_SELECT_MAX_DEFAULTS; + + if(m_packIndex >= SKIN_SELECT_MAX_DEFAULTS) + { + DLCPack *thisPack = app.m_dlcManager.getPack(m_packIndex - SKIN_SELECT_MAX_DEFAULTS, DLCManager::e_DLCType_Skin); + setCentreLabel(thisPack->getName().c_str()); + } + else + { + switch(m_packIndex) + { + case SKIN_SELECT_PACK_DEFAULT: + setCentreLabel(app.GetString(IDS_NO_SKIN_PACK)); + break; + case SKIN_SELECT_PACK_FAVORITES: + setCentreLabel(app.GetString(IDS_FAVORITES_SKIN_PACK)); + break; + } + } + + int nextPackIndex = getNextPackIndex(m_packIndex); + if(nextPackIndex >= SKIN_SELECT_MAX_DEFAULTS) + { + DLCPack *thisPack = app.m_dlcManager.getPack(nextPackIndex - SKIN_SELECT_MAX_DEFAULTS, DLCManager::e_DLCType_Skin); + setRightLabel(thisPack->getName().c_str()); + } + else + { + switch(nextPackIndex) + { + case SKIN_SELECT_PACK_DEFAULT: + setRightLabel(app.GetString(IDS_NO_SKIN_PACK)); + break; + case SKIN_SELECT_PACK_FAVORITES: + setRightLabel(app.GetString(IDS_FAVORITES_SKIN_PACK)); + break; + } + } + + int previousPackIndex = getPreviousPackIndex(m_packIndex); + if(previousPackIndex >= SKIN_SELECT_MAX_DEFAULTS) + { + DLCPack *thisPack = app.m_dlcManager.getPack(previousPackIndex - SKIN_SELECT_MAX_DEFAULTS, DLCManager::e_DLCType_Skin); + setLeftLabel(thisPack->getName().c_str()); + } + else + { + switch(previousPackIndex) + { + case SKIN_SELECT_PACK_DEFAULT: + setLeftLabel(app.GetString(IDS_NO_SKIN_PACK)); + break; + case SKIN_SELECT_PACK_FAVORITES: + setLeftLabel(app.GetString(IDS_FAVORITES_SKIN_PACK)); + break; + } + } + +} + +int UIScene_SkinSelectMenu::getNextPackIndex(DWORD sourceIndex) +{ + int nextPack = sourceIndex; + ++nextPack; + if(nextPack > app.m_dlcManager.getPackCount(DLCManager::e_DLCType_Skin) - 1 + SKIN_SELECT_MAX_DEFAULTS) + { + nextPack = SKIN_SELECT_PACK_DEFAULT; + } + + return nextPack; +} + +int UIScene_SkinSelectMenu::getPreviousPackIndex(DWORD sourceIndex) +{ + int previousPack = sourceIndex; + if (previousPack == SKIN_SELECT_PACK_DEFAULT) + { + DWORD packCount = app.m_dlcManager.getPackCount(DLCManager::e_DLCType_Skin); + + if (packCount > 0) + { + previousPack = packCount + SKIN_SELECT_MAX_DEFAULTS - 1; + } + else + { + previousPack = SKIN_SELECT_MAX_DEFAULTS - 1; + } + } + else + { + --previousPack; + } + + return previousPack; +} + +void UIScene_SkinSelectMenu::setCharacterSelected(bool selected) +{ + IggyDataValue result; + IggyDataValue value[1]; + value[0].type = IGGY_DATATYPE_boolean; + value[0].boolval = selected; + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcSetPlayerCharacterSelected , 1 , value ); +} + +void UIScene_SkinSelectMenu::setCharacterLocked(bool locked) +{ + IggyDataValue result; + IggyDataValue value[1]; + value[0].type = IGGY_DATATYPE_boolean; + value[0].boolval = locked; + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcSetCharacterLocked , 1 , value ); +} + +void UIScene_SkinSelectMenu::setLeftLabel(const wstring &label) +{ + if(label.compare(m_leftLabel) != 0) + { + m_leftLabel = label; + + IggyDataValue result; + IggyDataValue value[1]; + + IggyStringUTF16 stringVal; + stringVal.string = (IggyUTF16*)label.c_str(); + stringVal.length = label.length(); + + value[0].type = IGGY_DATATYPE_string_UTF16; + value[0].string16 = stringVal; + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcSetLeftLabel , 1 , value ); + } +} + +void UIScene_SkinSelectMenu::setCentreLabel(const wstring &label) +{ + if(label.compare(m_centreLabel) != 0) + { + m_centreLabel = label; + + IggyDataValue result; + IggyDataValue value[1]; + + IggyStringUTF16 stringVal; + stringVal.string = (IggyUTF16*)label.c_str(); + stringVal.length = label.length(); + + value[0].type = IGGY_DATATYPE_string_UTF16; + value[0].string16 = stringVal; + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcSetCentreLabel , 1 , value ); + } +} + +void UIScene_SkinSelectMenu::setRightLabel(const wstring &label) +{ + if(label.compare(m_rightLabel) != 0) + { + m_rightLabel = label; + + IggyDataValue result; + IggyDataValue value[1]; + + IggyStringUTF16 stringVal; + stringVal.string = (IggyUTF16*)label.c_str(); + stringVal.length = label.length(); + + value[0].type = IGGY_DATATYPE_string_UTF16; + value[0].string16 = stringVal; + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcSetRightLabel , 1 , value ); + } +} + +#ifdef __PSVITA__ +void UIScene_SkinSelectMenu::handleTouchInput(unsigned int iPad, S32 x, S32 y, int iId, bool bPressed, bool bRepeat, bool bReleased) +{ + if(bPressed) + { + switch(iId) + { + case ETouchInput_TabLeft: + case ETouchInput_TabRight: + case ETouchInput_TabCenter: + // change to pack navigation if not already there! + if(m_currentNavigation != eSkinNavigation_Pack) + { + ui.PlayUISFX(eSFX_Scroll); + m_currentNavigation = eSkinNavigation_Pack; + sendInputToMovie(ACTION_MENU_UP, false, true, false); + } + break; + case ETouchInput_IggyCharacters: + if(m_packIndex == SKIN_SELECT_PACK_FAVORITES) + { + if(app.GetPlayerFavoriteSkinsCount(m_iPad)==0) + { + // ignore this, since there are no skins being displayed + break; + } + } + // change to skin navigation if not already there! + if(m_currentNavigation != eSkinNavigation_Skin) + { + ui.PlayUISFX(eSFX_Scroll); + m_currentNavigation = eSkinNavigation_Skin; + sendInputToMovie(ACTION_MENU_DOWN, false, true, false); + } + // remember touch x start + m_iTouchXStart = x; + m_bTouchScrolled = false; + break; + } + } + else if(bRepeat) + { + switch(iId) + { + case ETouchInput_TabLeft: + /* no action */ + break; + case ETouchInput_TabRight: + /* no action */ + break; + case ETouchInput_IggyCharacters: + if(m_currentNavigation != eSkinNavigation_Skin) + { + // not in skin select mode + break; + } + if(x < m_iTouchXStart - 50) + { + if(!m_bAnimatingMove && !m_bTouchScrolled) + { + ui.PlayUISFX(eSFX_Scroll); + m_skinIndex = getNextSkinIndex(m_skinIndex); + //handleSkinIndexChanged(); + + m_bSlidingSkins = true; + m_bAnimatingMove = true; + + m_characters[eCharacter_Current].SetFacing(UIControl_PlayerSkinPreview::e_SkinPreviewFacing_Right, true); + m_characters[eCharacter_Next1].SetFacing(UIControl_PlayerSkinPreview::e_SkinPreviewFacing_Forward, true); + + // 4J Stu - Swapped nav buttons + sendInputToMovie(ACTION_MENU_LEFT, false, true, false); + + m_bTouchScrolled = true; + } + } + else if(x > m_iTouchXStart + 50) + { + if(!m_bAnimatingMove && !m_bTouchScrolled) + { + ui.PlayUISFX(eSFX_Scroll); + + m_skinIndex = getPreviousSkinIndex(m_skinIndex); + //handleSkinIndexChanged(); + + m_bSlidingSkins = true; + m_bAnimatingMove = true; + + m_characters[eCharacter_Current].SetFacing(UIControl_PlayerSkinPreview::e_SkinPreviewFacing_Left, true); + m_characters[eCharacter_Previous1].SetFacing(UIControl_PlayerSkinPreview::e_SkinPreviewFacing_Forward, true); + + // 4J Stu - Swapped nav buttons + sendInputToMovie(ACTION_MENU_RIGHT, false, true, false); + + m_bTouchScrolled = true; + } + } + break; + } + } + else if(bReleased) + { + switch(iId) + { + case ETouchInput_TabLeft: + if( m_currentNavigation == eSkinNavigation_Pack ) + { + ui.PlayUISFX(eSFX_Scroll); + DWORD startingIndex = m_packIndex; + m_packIndex = getPreviousPackIndex(m_packIndex); + if(startingIndex != m_packIndex) + { + handlePackIndexChanged(); + } + } + break; + case ETouchInput_TabRight: + if( m_currentNavigation == eSkinNavigation_Pack ) + { + ui.PlayUISFX(eSFX_Scroll); + DWORD startingIndex = m_packIndex; + m_packIndex = getNextPackIndex(m_packIndex); + if(startingIndex != m_packIndex) + { + handlePackIndexChanged(); + } + } + break; + case ETouchInput_IggyCharacters: + if(!m_bTouchScrolled) + { + InputActionOK(iPad); + } + break; + } + } +} +#endif + +void UIScene_SkinSelectMenu::HandleDLCInstalled() +{ +#ifdef __PSVITA__ + EnterCriticalSection(&m_DLCInstallCS); // to prevent a race condition between the install and the mounted callback +#endif + + app.DebugPrintf(4,"UIScene_SkinSelectMenu::HandleDLCInstalled\n"); + // mounted DLC may have changed + if(app.StartInstallDLCProcess(m_iPad)==false) + { + // not doing a mount, so re-enable input + app.DebugPrintf(4,"UIScene_SkinSelectMenu::HandleDLCInstalled - not doing a mount, so re-enable input\n"); + m_bIgnoreInput=false; + } + else + { + m_bIgnoreInput=true; + m_controlTimer.setVisible( true ); + m_controlIggyCharacters.setVisible( false ); + m_controlSkinNamePlate.setVisible( false ); + } + + // this will send a CustomMessage_DLCMountingComplete when done + +#ifdef __PSVITA__ + LeaveCriticalSection(&m_DLCInstallCS); +#endif + +} + + +void UIScene_SkinSelectMenu::HandleDLCMountingComplete() +{ +#ifdef __PSVITA__ + EnterCriticalSection(&m_DLCInstallCS); // to prevent a race condition between the install and the mounted callback +#endif + app.DebugPrintf(4,"UIScene_SkinSelectMenu::HandleDLCMountingComplete\n"); + m_controlTimer.setVisible( false ); + m_controlIggyCharacters.setVisible( true ); + m_controlSkinNamePlate.setVisible( true ); + + m_packIndex = SKIN_SELECT_PACK_DEFAULT; + + if(app.m_dlcManager.getPackCount(DLCManager::e_DLCType_Skin)>0) + { + m_currentPack = app.m_dlcManager.getPackContainingSkin(m_currentSkinPath); + if(m_currentPack != NULL) + { + bool bFound = false; + m_packIndex = app.m_dlcManager.getPackIndex(m_currentPack,bFound,DLCManager::e_DLCType_Skin) + SKIN_SELECT_MAX_DEFAULTS; + } + } + + // If we have any favourites, set this to the favourites + // first validate the favorite skins - we might have uninstalled the DLC needed for them + app.ValidateFavoriteSkins(m_iPad); + + if(app.GetPlayerFavoriteSkinsCount(m_iPad)>0) + { + m_packIndex = SKIN_SELECT_PACK_FAVORITES; + } + + handlePackIndexChanged(); + + m_bIgnoreInput=false; + app.m_dlcManager.checkForCorruptDLCAndAlert(); + bool bInGame=(Minecraft::GetInstance()->level!=NULL); + +#if TO_BE_IMPLEMENTED + if(bInGame) XBackgroundDownloadSetMode(XBACKGROUND_DOWNLOAD_MODE_AUTO); +#endif +#ifdef __PSVITA__ + LeaveCriticalSection(&m_DLCInstallCS); +#endif +} + +void UIScene_SkinSelectMenu::showNotOnlineDialog(int iPad) +{ + // need to be signed in to live. get them to sign in to online +#if defined(__PS3__) + SQRNetworkManager_PS3::AttemptPSNSignIn(NULL, this); + +#elif defined(__PSVITA__) + SQRNetworkManager_Vita::AttemptPSNSignIn(NULL, this); + +#elif defined(__ORBIS__) + SQRNetworkManager_Orbis::AttemptPSNSignIn(NULL, this, false, iPad); + +#elif defined(_DURANGO) + + UINT uiIDA[1] = { IDS_CONFIRM_OK }; + ui.RequestMessageBox(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_XBOXLIVE_NOTIFICATION, uiIDA, 1, iPad, NULL, NULL, app.GetStringTable() ); + +#endif +} + +int UIScene_SkinSelectMenu::UnlockSkinReturned(void *pParam,int iPad,C4JStorage::EMessageResult result) +{ + UIScene_SkinSelectMenu* pScene = (UIScene_SkinSelectMenu*)pParam; + + if ( (result == C4JStorage::EMessage_ResultAccept) + && ProfileManager.IsSignedIn(iPad) + ) + { + if (ProfileManager.IsSignedInLive(iPad)) + { +#if defined(__PS3__) || defined(__ORBIS__) || defined __PSVITA__ + // need to get info on the pack to see if the user has already downloaded it + + // retrieve the store name for the skin pack + wstring wStrPackName=pScene->m_currentPack->getName(); + const char *pchPackName=wstringtofilename(wStrPackName); + SONYDLC *pSONYDLCInfo=app.GetSONYDLCInfo((char *)pchPackName); + + if (pSONYDLCInfo != NULL) + { + char chName[42]; + char chKeyName[20]; + char chSkuID[SCE_NP_COMMERCE2_SKU_ID_LEN]; + + memset(chSkuID,0,SCE_NP_COMMERCE2_SKU_ID_LEN); + // find the info on the skin pack + // we have to retrieve the skuid from the store info, it can't be hardcoded since Sony may change it. + // So we assume the first sku for the product is the one we want + + // while the store is screwed, hardcode the sku + //sprintf(chName,"%s-%s-%s",app.GetCommerceCategory(),pSONYDLCInfo->chDLCKeyname,"EURO"); + + // MGH - keyname in the DLC file is 16 chars long, but there's no space for a NULL terminating char + memset(chKeyName, 0, sizeof(chKeyName)); + strncpy(chKeyName, pSONYDLCInfo->chDLCKeyname, 16); + +#ifdef __ORBIS__ + strcpy(chName, chKeyName); +#else + sprintf(chName,"%s-%s",app.GetCommerceCategory(),chKeyName); +#endif + app.GetDLCSkuIDFromProductList(chName,chSkuID); + +#if defined __ORBIS__ || defined __PSVITA__ || defined __PS3__ + if (app.CheckForEmptyStore(iPad) == false) +#endif + { + if (app.DLCAlreadyPurchased(chSkuID)) + { + app.DebugPrintf("Already purchased this DLC - DownloadAlreadyPurchased \n"); + app.DownloadAlreadyPurchased(chSkuID); + } + else + { + app.DebugPrintf("Not yet purchased this DLC - Checkout \n"); + app.Checkout(chSkuID); + } + } + // need to re-enable input because the user can back out of the store purchase, and we'll be stuck + pScene->m_bIgnoreInput = false; + } +#elif defined _XBOX_ONE + StorageManager.InstallOffer(1,(WCHAR *)(pScene->m_currentPack->getPurchaseOfferId().c_str()), &RenableInput, pScene, NULL); +#endif + } + else // Is signed in, but not live. + { + pScene->showNotOnlineDialog(iPad); + pScene->m_bIgnoreInput = false; + } + } + else + { + pScene->m_bIgnoreInput = false; + } + + return 0; +} + +int UIScene_SkinSelectMenu::RenableInput(LPVOID lpVoid, int, int) +{ + ((UIScene_SkinSelectMenu*) lpVoid)->m_bIgnoreInput = false; + return 0; +} + +void UIScene_SkinSelectMenu::AddFavoriteSkin(int iPad,int iSkinID) +{ + // Is this favorite skin already in the array? + unsigned int uiCurrentFavoriteSkinsCount=app.GetPlayerFavoriteSkinsCount(iPad); + + for(int i=0;i<uiCurrentFavoriteSkinsCount;i++) + { + if(app.GetPlayerFavoriteSkin(m_iPad,i)==iSkinID) + { + app.SetPlayerFavoriteSkinsPos(m_iPad,i); + return; + } + } + + unsigned char ucPos=app.GetPlayerFavoriteSkinsPos(m_iPad); + if(ucPos==(MAX_FAVORITE_SKINS-1)) + { + ucPos=0; + } + else + { + if(uiCurrentFavoriteSkinsCount>0) + { + ucPos++; + } + else + { + ucPos=0; + } + } + + app.SetPlayerFavoriteSkin(iPad,(int)ucPos,iSkinID); + app.SetPlayerFavoriteSkinsPos(m_iPad,ucPos); +} + + +void UIScene_SkinSelectMenu::handleReload() +{ + // Reinitialise a few values to prevent problems on reload + m_bIgnoreInput=false; + + m_currentNavigation = eSkinNavigation_Skin; + m_currentPackCount = 0; + + m_labelSkinName.init(L""); + m_labelSkinOrigin.init(L""); + + m_leftLabel = L""; + m_centreLabel = L""; + m_rightLabel = L""; + + handlePackIndexChanged(); +} + +#ifdef _XBOX_ONE +void UIScene_SkinSelectMenu::HandleDLCLicenseChange() +{ + // update the lock flag + handleSkinIndexChanged(); +} +#endif
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIScene_SkinSelectMenu.h b/Minecraft.Client/Common/UI/UIScene_SkinSelectMenu.h new file mode 100644 index 00000000..c9ed6691 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_SkinSelectMenu.h @@ -0,0 +1,189 @@ +#pragma once +#include "..\..\..\Minecraft.World\Definitions.h" +#include "UIScene.h" +#include "UIControl_PlayerSkinPreview.h" + +class UIScene_SkinSelectMenu : public UIScene +{ +private: + static WCHAR *wchDefaultNamesA[eDefaultSkins_Count]; + + // 4J Stu - How many to show on each side of the main control + static const BYTE sidePreviewControls = 4; + +#ifdef __PSVITA__ + enum ETouchInput + { + ETouchInput_TabLeft = 10, + ETouchInput_TabRight, + ETouchInput_TabCenter, + ETouchInput_IggyCharacters, + + ETouchInput_Count, + }; +#endif + + enum ESkinSelectNavigation + { + eSkinNavigation_Pack, + eSkinNavigation_Skin, + + eSkinNavigation_Count, + }; + + enum ECharacters + { + eCharacter_Current, + eCharacter_Next1, + eCharacter_Next2, + eCharacter_Next3, + eCharacter_Next4, + eCharacter_Previous1, + eCharacter_Previous2, + eCharacter_Previous3, + eCharacter_Previous4, + + eCharacter_COUNT, + }; + + UIControl_PlayerSkinPreview m_characters[eCharacter_COUNT]; + UIControl_Label m_labelSkinName, m_labelSkinOrigin; + UIControl_Label m_labelSelected; + UIControl m_controlSkinNamePlate, m_controlSelectedPanel, m_controlIggyCharacters, m_controlTimer; +#ifdef __PSVITA__ + UIControl_Touch m_TouchTabLeft, m_TouchTabRight, m_TouchTabCenter, m_TouchIggyCharacters; +#endif + IggyName m_funcSetPlayerCharacterSelected, m_funcSetCharacterLocked; + IggyName m_funcSetLeftLabel, m_funcSetRightLabel, m_funcSetCentreLabel; + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) +#ifdef __PSVITA__ + UI_MAP_ELEMENT( m_TouchTabLeft, "TouchTabLeft" ) + UI_MAP_ELEMENT( m_TouchTabRight, "TouchTabRight" ) + UI_MAP_ELEMENT( m_TouchTabCenter, "TouchTabCenter" ) + UI_MAP_ELEMENT( m_TouchIggyCharacters, "TouchIggyCharacters" ) +#endif + UI_MAP_ELEMENT( m_controlSkinNamePlate, "SkinNamePlate") + UI_BEGIN_MAP_CHILD_ELEMENTS( m_controlSkinNamePlate ) + UI_MAP_ELEMENT( m_labelSkinName, "SkinTitle1") + UI_MAP_ELEMENT( m_labelSkinOrigin, "SkinTitle2") + UI_END_MAP_CHILD_ELEMENTS() + + UI_MAP_ELEMENT( m_controlSelectedPanel, "SelectedPanel" ) + UI_BEGIN_MAP_CHILD_ELEMENTS( m_controlSelectedPanel ) + UI_MAP_ELEMENT( m_labelSelected, "SelectedPanelLabel" ) + UI_END_MAP_CHILD_ELEMENTS() + + UI_MAP_ELEMENT( m_controlTimer, "Timer" ) + + // 4J Stu - These aren't really used a AS3 controls, but adding here means that they get ticked by the scene + UI_MAP_ELEMENT( m_controlIggyCharacters, "IggyCharacters" ) + UI_BEGIN_MAP_CHILD_ELEMENTS( m_controlIggyCharacters ) + UI_MAP_ELEMENT( m_characters[eCharacter_Current], "iggy_Character0" ) + + UI_MAP_ELEMENT( m_characters[eCharacter_Next1], "iggy_Character1" ) + UI_MAP_ELEMENT( m_characters[eCharacter_Next2], "iggy_Character2" ) + UI_MAP_ELEMENT( m_characters[eCharacter_Next3], "iggy_Character3" ) + UI_MAP_ELEMENT( m_characters[eCharacter_Next4], "iggy_Character4" ) + + UI_MAP_ELEMENT( m_characters[eCharacter_Previous1], "iggy_Character5" ) + UI_MAP_ELEMENT( m_characters[eCharacter_Previous2], "iggy_Character6" ) + UI_MAP_ELEMENT( m_characters[eCharacter_Previous3], "iggy_Character7" ) + UI_MAP_ELEMENT( m_characters[eCharacter_Previous4], "iggy_Character8" ) + UI_END_MAP_CHILD_ELEMENTS() + + UI_MAP_NAME( m_funcSetPlayerCharacterSelected, L"SetPlayerCharacterSelected" ) + UI_MAP_NAME( m_funcSetCharacterLocked, L"SetCharacterLocked" ) + + UI_MAP_NAME( m_funcSetLeftLabel, L"SetLeftLabel" ) + UI_MAP_NAME( m_funcSetCentreLabel, L"SetCenterLabel" ) + UI_MAP_NAME( m_funcSetRightLabel, L"SetRightLabel" ) + UI_END_MAP_ELEMENTS_AND_NAMES() + + DLCPack *m_currentPack; + DWORD m_packIndex, m_skinIndex; + DWORD m_originalSkinId; + wstring m_currentSkinPath, m_selectedSkinPath, m_selectedCapePath; + vector<SKIN_BOX *> *m_vAdditionalSkinBoxes; + + bool m_bSlidingSkins, m_bAnimatingMove; + ESkinSelectNavigation m_currentNavigation; + + bool m_bNoSkinsToShow; + DWORD m_currentPackCount; + bool m_bIgnoreInput; + bool m_bSkinIndexChanged; + wstring m_leftLabel, m_centreLabel, m_rightLabel; + + S32 m_iTouchXStart; + bool m_bTouchScrolled; +public: + UIScene_SkinSelectMenu(int iPad, void *initData, UILayer *parentLayer); +#ifdef __PSVITA__ + virtual ~UIScene_SkinSelectMenu() { DeleteCriticalSection(&m_DLCInstallCS); } +#endif + + virtual void tick(); + + virtual void updateTooltips(); + virtual void updateComponents(); + + virtual EUIScene getSceneType() { return eUIScene_SkinSelectMenu;} + + virtual void handleAnimationEnd(); + + +protected: + // TODO: This should be pure virtual in this class + virtual wstring getMoviePath(); + +public: + // INPUT + virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled); + + virtual void customDraw(IggyCustomDrawCallbackRegion *region); + +private: + void handleSkinIndexChanged(); + int getNextSkinIndex(DWORD sourceIndex); + int getPreviousSkinIndex(DWORD sourceIndex); + + TEXTURE_NAME getTextureId(int skinIndex); + + void handlePackIndexChanged(); + void updatePackDisplay(); + int getNextPackIndex(DWORD sourceIndex); + int getPreviousPackIndex(DWORD sourceIndex); + + void setCharacterSelected(bool selected); + void setCharacterLocked(bool locked); + + void setLeftLabel(const wstring &label); + void setCentreLabel(const wstring &label); + void setRightLabel(const wstring &label); + + virtual void HandleDLCMountingComplete(); + virtual void HandleDLCInstalled(); +#ifdef _XBOX_ONE + virtual void HandleDLCLicenseChange(); +#endif + + void showNotOnlineDialog(int iPad); + + static int UnlockSkinReturned(void *pParam,int iPad,C4JStorage::EMessageResult result); + static int RenableInput(LPVOID lpVoid, int, int); + void AddFavoriteSkin(int iPad,int iSkinID); + + void InputActionOK(unsigned int iPad); +#ifdef __PSVITA__ + virtual void handleTouchInput(unsigned int iPad, S32 x, S32 y, int iId, bool bPressed, bool bRepeat, bool bReleased); +#endif //__PSVITA__ + virtual void handleReload(); + +#ifdef __ORBIS__ + bool m_bErrorDialogRunning; +#endif + +#ifdef __PSVITA__ + CRITICAL_SECTION m_DLCInstallCS; // to prevent a race condition between the install and the mounted callback +#endif +}; diff --git a/Minecraft.Client/Common/UI/UIScene_TeleportMenu.cpp b/Minecraft.Client/Common/UI/UIScene_TeleportMenu.cpp new file mode 100644 index 00000000..f6916d13 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_TeleportMenu.cpp @@ -0,0 +1,344 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIScene_TeleportMenu.h" +#include "..\..\MultiPlayerLocalPlayer.h" +#include "..\..\..\Minecraft.World\net.minecraft.network.packet.h" +#include "..\..\MultiPlayerLocalPlayer.h" +#include "..\..\ClientConnection.h" +#include "TeleportCommand.h" + +UIScene_TeleportMenu::UIScene_TeleportMenu(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) +{ + // Setup all the Iggy references we need for this scene + initialiseMovie(); + + TeleportMenuInitData *initParam = (TeleportMenuInitData *)initData; + + m_teleportToPlayer = initParam->teleportToPlayer; + + delete initParam; + + if(m_teleportToPlayer) + { + m_labelTitle.init(app.GetString(IDS_TELEPORT_TO_PLAYER)); + } + else + { + m_labelTitle.init(app.GetString(IDS_TELEPORT_TO_ME)); + } + + m_playerList.init(eControl_GamePlayers); + + for(unsigned int i = 0; i < MINECRAFT_NET_MAX_PLAYERS; ++i) + { + m_playerNames[i] = L""; + } + + DWORD playerCount = g_NetworkManager.GetPlayerCount(); + + m_playersCount = 0; + for(DWORD i = 0; i < playerCount; ++i) + { + INetworkPlayer *player = g_NetworkManager.GetPlayerByIndex( i ); + + if( player != NULL && !(player->IsLocal() && player->GetUserIndex() == m_iPad) ) + { + m_players[m_playersCount] = player->GetSmallId(); + ++m_playersCount; + + wstring playerName = L""; +#ifndef _CONTENT_PACKAGE + if(app.DebugSettingsOn() && (app.GetGameSettingsDebugMask()&(1L<<eDebugSetting_DebugLeaderboards))) + { + playerName = L"WWWWWWWWWWWWWWWW"; + } + else +#endif + { + playerName = player->GetDisplayName(); + } + + int voiceStatus = 0; + if(player != NULL && player->HasVoice() ) + { + if( player->IsMutedByLocalUser(m_iPad) ) + { + // Muted image + voiceStatus = 3; + } + else if( player->IsTalking() ) + { + // Talking image + voiceStatus = 2; + } + else + { + // Not talking image + voiceStatus = 1; + } + } + + m_playersVoiceState[m_playersCount] = voiceStatus; + m_playersColourState[m_playersCount] = app.GetPlayerColour( m_players[m_playersCount] ); + m_playerNames[m_playersCount] = playerName; + m_playerList.addItem( playerName, app.GetPlayerColour( m_players[m_playersCount] ), voiceStatus); + } + } + + g_NetworkManager.RegisterPlayerChangedCallback(m_iPad, &UIScene_TeleportMenu::OnPlayerChanged, this); + + parentLayer->addComponent(iPad,eUIComponent_MenuBackground); + + // get rid of the quadrant display if it's on + ui.HidePressStart(); +} + +wstring UIScene_TeleportMenu::getMoviePath() +{ + if(app.GetLocalPlayerCount() > 1) + { + return L"InGameTeleportMenuSplit"; + } + else + { + return L"InGameTeleportMenu"; + } +} + +void UIScene_TeleportMenu::updateTooltips() +{ + ui.SetTooltips( m_iPad, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK); +} + +void UIScene_TeleportMenu::handleDestroy() +{ + g_NetworkManager.UnRegisterPlayerChangedCallback(m_iPad, &UIScene_TeleportMenu::OnPlayerChanged, this); + + m_parentLayer->removeComponent(eUIComponent_MenuBackground); +} + +void UIScene_TeleportMenu::handleGainFocus(bool navBack) +{ + if( navBack ) g_NetworkManager.RegisterPlayerChangedCallback(m_iPad, &UIScene_TeleportMenu::OnPlayerChanged, this); +} + +void UIScene_TeleportMenu::handleReload() +{ + DWORD playerCount = g_NetworkManager.GetPlayerCount(); + + m_playersCount = 0; + for(DWORD i = 0; i < playerCount; ++i) + { + INetworkPlayer *player = g_NetworkManager.GetPlayerByIndex( i ); + + if( player != NULL && !(player->IsLocal() && player->GetUserIndex() == m_iPad) ) + { + m_players[m_playersCount] = player->GetSmallId(); + ++m_playersCount; + + wstring playerName = L""; +#ifndef _CONTENT_PACKAGE + if(app.DebugSettingsOn() && (app.GetGameSettingsDebugMask()&(1L<<eDebugSetting_DebugLeaderboards))) + { + playerName = L"WWWWWWWWWWWWWWWW"; + } + else +#endif + { + playerName = player->GetDisplayName(); + } + + int voiceStatus = 0; + if(player != NULL && player->HasVoice() ) + { + if( player->IsMutedByLocalUser(m_iPad) ) + { + // Muted image + voiceStatus = 3; + } + else if( player->IsTalking() ) + { + // Talking image + voiceStatus = 2; + } + else + { + // Not talking image + voiceStatus = 1; + } + } + + m_playersVoiceState[m_playersCount] = voiceStatus; + m_playersColourState[m_playersCount] = app.GetPlayerColour( m_players[m_playersCount] ); + m_playerNames[m_playersCount] = playerName; + m_playerList.addItem( playerName, app.GetPlayerColour( m_players[m_playersCount] ), voiceStatus); + } + } + + if(controlHasFocus(eControl_GamePlayers)) + { + m_playerList.setCurrentSelection(getControlChildFocus()); + } +} + +void UIScene_TeleportMenu::tick() +{ + UIScene::tick(); + + for(DWORD i = 0; i < m_playersCount; ++i) + { + INetworkPlayer *player = g_NetworkManager.GetPlayerBySmallId( m_players[i] ); + + if( player != NULL ) + { + m_players[i] = player->GetSmallId(); + + short icon = app.GetPlayerColour( m_players[i] ); + + if(icon != m_playersColourState[i]) + { + m_playersColourState[i] = icon; + m_playerList.setPlayerIcon( i, (int)app.GetPlayerColour( m_players[i] ) ); + } + + wstring playerName = L""; +#ifndef _CONTENT_PACKAGE + if(app.DebugSettingsOn() && (app.GetGameSettingsDebugMask()&(1L<<eDebugSetting_DebugLeaderboards))) + { + playerName = L"WWWWWWWWWWWWWWWW"; + } + else +#endif + { + playerName = player->GetDisplayName(); + } + if(playerName.compare( m_playerNames[i] ) != 0 ) + { + m_playerList.setButtonLabel(i, playerName); + m_playerNames[i] = playerName; + } + } + } +} + +void UIScene_TeleportMenu::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled) +{ + //app.DebugPrintf("UIScene_DebugOverlay handling input for pad %d, key %d, down- %s, pressed- %s, released- %s\n", iPad, key, down?"TRUE":"FALSE", pressed?"TRUE":"FALSE", released?"TRUE":"FALSE"); + ui.AnimateKeyPress(m_iPad, key, repeat, pressed, released); + + switch(key) + { + case ACTION_MENU_CANCEL: + if(pressed && !repeat) + { + ui.PlayUISFX(eSFX_Back); + navigateBack(); + } + break; + case ACTION_MENU_OK: +#ifdef __ORBIS__ + case ACTION_MENU_TOUCHPAD_PRESS: +#endif + case ACTION_MENU_UP: + case ACTION_MENU_DOWN: + case ACTION_MENU_PAGEUP: + case ACTION_MENU_PAGEDOWN: + sendInputToMovie(key, repeat, pressed, released); + break; + } +} + +void UIScene_TeleportMenu::handlePress(F64 controlId, F64 childId) +{ + app.DebugPrintf("Pressed = %d, %d\n", (int)controlId, (int)childId); + switch((int)controlId) + { + case eControl_GamePlayers: + int currentSelection = (int)childId; + INetworkPlayer *selectedPlayer = g_NetworkManager.GetPlayerBySmallId( m_players[ currentSelection ] ); + INetworkPlayer *thisPlayer = g_NetworkManager.GetLocalPlayerByUserIndex(m_iPad); + + shared_ptr<GameCommandPacket> packet; + if(m_teleportToPlayer) + { + packet = TeleportCommand::preparePacket(thisPlayer->GetUID(),selectedPlayer->GetUID()); + } + else + { + packet = TeleportCommand::preparePacket(selectedPlayer->GetUID(),thisPlayer->GetUID()); + } + ClientConnection *conn = Minecraft::GetInstance()->getConnection(m_iPad); + conn->send( packet ); + break; + } +} + +void UIScene_TeleportMenu::OnPlayerChanged(void *callbackParam, INetworkPlayer *pPlayer, bool leaving) +{ + UIScene_TeleportMenu *scene = (UIScene_TeleportMenu *)callbackParam; + bool playerFound = false; + int foundIndex = 0; + for(int i = 0; i < scene->m_playersCount; ++i) + { + if(!playerFound && scene->m_players[i] == pPlayer->GetSmallId() ) + { + if( scene->m_playerList.getCurrentSelection() == scene->m_playerList.getItemCount() - 1 ) + { + scene->m_playerList.setCurrentSelection( scene->m_playerList.getItemCount() - 2 ); + } + // Player removed + playerFound = true; + foundIndex = i; + } + } + + if( playerFound ) + { + --scene->m_playersCount; + scene->m_playersVoiceState[scene->m_playersCount] = 0; + scene->m_playersColourState[scene->m_playersCount] = 0; + scene->m_playerNames[scene->m_playersCount] = L""; + scene->m_playerList.removeItem(scene->m_playersCount); + } + + if( !playerFound ) + { + // Player added + scene->m_players[scene->m_playersCount] = pPlayer->GetSmallId(); + ++scene->m_playersCount; + + wstring playerName = L""; +#ifndef _CONTENT_PACKAGE + if(app.DebugSettingsOn() && (app.GetGameSettingsDebugMask()&(1L<<eDebugSetting_DebugLeaderboards))) + { + playerName = L"WWWWWWWWWWWWWWWW"; + } + else +#endif + { + playerName = pPlayer->GetDisplayName(); + } + + int voiceStatus = 0; + if(pPlayer != NULL && pPlayer->HasVoice() ) + { + if( pPlayer->IsMutedByLocalUser(scene->m_iPad) ) + { + // Muted image + voiceStatus = 3; + } + else if( pPlayer->IsTalking() ) + { + // Talking image + voiceStatus = 2; + } + else + { + // Not talking image + voiceStatus = 1; + } + } + + scene->m_playerList.addItem( playerName, app.GetPlayerColour( scene->m_players[scene->m_playersCount - 1] ), voiceStatus); + } +} diff --git a/Minecraft.Client/Common/UI/UIScene_TeleportMenu.h b/Minecraft.Client/Common/UI/UIScene_TeleportMenu.h new file mode 100644 index 00000000..ebbaa2a0 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_TeleportMenu.h @@ -0,0 +1,51 @@ +#pragma once + +#include "UIScene.h" + +class UIScene_TeleportMenu : public UIScene +{ +private: + enum EControls + { + eControl_GamePlayers, + }; + + bool m_teleportToPlayer; + int m_playersCount; + BYTE m_players[MINECRAFT_NET_MAX_PLAYERS]; // An array of QNet small-id's + char m_playersVoiceState[MINECRAFT_NET_MAX_PLAYERS]; + short m_playersColourState[MINECRAFT_NET_MAX_PLAYERS]; + wstring m_playerNames[MINECRAFT_NET_MAX_PLAYERS]; + + UIControl_PlayerList m_playerList; + UIControl_Label m_labelTitle; + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) + UI_MAP_ELEMENT( m_playerList, "GamePlayers") + UI_MAP_ELEMENT( m_labelTitle, "Title") + UI_END_MAP_ELEMENTS_AND_NAMES() +public: + UIScene_TeleportMenu(int iPad, void *initData, UILayer *parentLayer); + + virtual EUIScene getSceneType() { return eUIScene_TeleportMenu;} + + virtual void updateTooltips(); + virtual void handleReload(); + + virtual void tick(); + +protected: + // TODO: This should be pure virtual in this class + virtual wstring getMoviePath(); + +public: + // INPUT + virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled); + +protected: + virtual void handleGainFocus(bool navBack); + void handlePress(F64 controlId, F64 childId); + virtual void handleDestroy(); + +public: + static void OnPlayerChanged(void *callbackParam, INetworkPlayer *pPlayer, bool leaving); +};
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIScene_Timer.cpp b/Minecraft.Client/Common/UI/UIScene_Timer.cpp new file mode 100644 index 00000000..61586e87 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_Timer.cpp @@ -0,0 +1,32 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIScene_Timer.h" + + +UIScene_Timer::UIScene_Timer(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) +{ + // Setup all the Iggy references we need for this scene + initialiseMovie(); + + // In normal usage, we want to hide the new background that's used during texture pack reloading + if(initData == 0) + { + m_controlBackground.setVisible(false); + } +} + +wstring UIScene_Timer::getMoviePath() +{ + return L"Timer"; +} + +void UIScene_Timer::reloadMovie() +{ + // Never needs reloaded +} + +bool UIScene_Timer::needsReloaded() +{ + // Never needs reloaded + return false; +}
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIScene_Timer.h b/Minecraft.Client/Common/UI/UIScene_Timer.h new file mode 100644 index 00000000..5a75103a --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_Timer.h @@ -0,0 +1,28 @@ +#pragma once + +#include "UIScene.h" + +class UIScene_Timer : public UIScene +{ +private: + UIControl m_controlBackground; + + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) + UI_MAP_ELEMENT(m_controlBackground,"Background") + UI_END_MAP_ELEMENTS_AND_NAMES() + +public: + using UIScene::reloadMovie; + + UIScene_Timer(int iPad, void *initData, UILayer *parentLayer); + + virtual EUIScene getSceneType() { return eUIScene_Timer;} + + // Returns true if lower scenes in this scenes layer, or in any layer below this scenes layers should be hidden + virtual bool hidesLowerScenes() { return true; } + virtual void reloadMovie(); + virtual bool needsReloaded(); + +protected: + virtual wstring getMoviePath(); +}; diff --git a/Minecraft.Client/Common/UI/UIScene_TradingMenu.cpp b/Minecraft.Client/Common/UI/UIScene_TradingMenu.cpp new file mode 100644 index 00000000..dc2bac48 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_TradingMenu.cpp @@ -0,0 +1,268 @@ +#include "stdafx.h" +#include "UI.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.inventory.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.item.trading.h" +#include "..\..\..\Minecraft.World\net.minecraft.world.level.tile.entity.h" +#include "MultiPlayerLocalPlayer.h" +#include "..\..\Minecraft.h" +#include "UIScene_TradingMenu.h" + +UIScene_TradingMenu::UIScene_TradingMenu(int iPad, void *_initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) +{ + // Setup all the Iggy references we need for this scene + initialiseMovie(); + + m_showingLeftArrow = true; + m_showingRightArrow = true; + + // 4J-PB - "Villager" appears for a short time on opening the trading menu + //m_labelTrading.init( app.GetString(IDS_VILLAGER) ); + m_labelTrading.init( L"" ); + m_labelInventory.init( app.GetString(IDS_INVENTORY) ); + m_labelRequired.init( app.GetString(IDS_REQUIRED_ITEMS_FOR_TRADE) ); + + m_labelRequest1.init(L""); + m_labelRequest2.init(L""); + + TradingScreenInput *initData = (TradingScreenInput *)_initData; + m_merchant = initData->trader; + + Minecraft *pMinecraft = Minecraft::GetInstance(); + if( pMinecraft->localgameModes[iPad] != NULL ) + { + TutorialMode *gameMode = (TutorialMode *)pMinecraft->localgameModes[iPad]; + m_previousTutorialState = gameMode->getTutorial()->getCurrentState(); + gameMode->getTutorial()->changeTutorialState(e_Tutorial_State_Trading_Menu, this); + } + + m_menu = new MerchantMenu( initData->inventory, initData->trader, initData->level ); + + Minecraft::GetInstance()->localplayers[iPad]->containerMenu = m_menu; + + m_slotListRequest1.addSlots(BUY_A,1); + m_slotListRequest2.addSlots(BUY_B,1); + + m_slotListTrades.addSlots(TRADES_START,DISPLAY_TRADES_COUNT); + + m_slotListInventory.addSlots(MerchantMenu::INV_SLOT_START, 27); + m_slotListHotbar.addSlots(MerchantMenu::USE_ROW_SLOT_START, 9); + + if(initData) delete initData; + + // in this scene, we override the press sound with our own for crafting success or fail + ui.OverrideSFX(m_iPad,ACTION_MENU_A,true); + ui.OverrideSFX(m_iPad,ACTION_MENU_OK,true); +#ifdef __ORBIS__ + ui.OverrideSFX(m_iPad,ACTION_MENU_TOUCHPAD_PRESS,true); +#endif + ui.OverrideSFX(m_iPad,ACTION_MENU_LEFT_SCROLL,true); + ui.OverrideSFX(m_iPad,ACTION_MENU_RIGHT_SCROLL,true); + ui.OverrideSFX(m_iPad,ACTION_MENU_LEFT,true); + ui.OverrideSFX(m_iPad,ACTION_MENU_RIGHT,true); + ui.OverrideSFX(m_iPad,ACTION_MENU_UP,true); + ui.OverrideSFX(m_iPad,ACTION_MENU_DOWN,true); + + app.SetRichPresenceContext(iPad, CONTEXT_GAME_STATE_TRADING); +} + +wstring UIScene_TradingMenu::getMoviePath() +{ + if(app.GetLocalPlayerCount() > 1) + { + return L"TradingMenuSplit"; + } + else + { + return L"TradingMenu"; + } +} + +void UIScene_TradingMenu::updateTooltips() +{ + ui.SetTooltips(m_iPad, IDS_TOOLTIPS_TRADE, IDS_TOOLTIPS_BACK); +} + +void UIScene_TradingMenu::handleDestroy() +{ + app.DebugPrintf("UIScene_TradingMenu::handleDestroy\n"); + Minecraft *pMinecraft = Minecraft::GetInstance(); + if( pMinecraft->localgameModes[m_iPad] != NULL ) + { + TutorialMode *gameMode = (TutorialMode *)pMinecraft->localgameModes[m_iPad]; + if(gameMode != NULL) gameMode->getTutorial()->changeTutorialState(m_previousTutorialState); + } + + // 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) + if(pMinecraft->localplayers[m_iPad] != NULL) pMinecraft->localplayers[m_iPad]->closeContainer(); + + ui.OverrideSFX(m_iPad,ACTION_MENU_A,false); + ui.OverrideSFX(m_iPad,ACTION_MENU_OK,false); +#ifdef __ORBIS__ + ui.OverrideSFX(m_iPad,ACTION_MENU_TOUCHPAD_PRESS,false); +#endif + ui.OverrideSFX(m_iPad,ACTION_MENU_LEFT_SCROLL,false); + ui.OverrideSFX(m_iPad,ACTION_MENU_RIGHT_SCROLL,false); + ui.OverrideSFX(m_iPad,ACTION_MENU_LEFT,false); + ui.OverrideSFX(m_iPad,ACTION_MENU_RIGHT,false); + ui.OverrideSFX(m_iPad,ACTION_MENU_UP,false); + ui.OverrideSFX(m_iPad,ACTION_MENU_DOWN,false); +} + +void UIScene_TradingMenu::handleReload() +{ + m_slotListRequest1.addSlots(BUY_A,1); + m_slotListRequest2.addSlots(BUY_B,1); + + m_slotListTrades.addSlots(TRADES_START,DISPLAY_TRADES_COUNT); + + m_slotListInventory.addSlots(MerchantMenu::INV_SLOT_START, 27); + m_slotListHotbar.addSlots(MerchantMenu::USE_ROW_SLOT_START, 9); +} + +void UIScene_TradingMenu::tick() +{ + UIScene::tick(); + handleTick(); +} + +void UIScene_TradingMenu::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled) +{ + //app.DebugPrintf("UIScene_InventoryMenu handling input for pad %d, key %d, down- %s, pressed- %s, released- %s\n", iPad, key, down?"TRUE":"FALSE", pressed?"TRUE":"FALSE", released?"TRUE":"FALSE"); + ui.AnimateKeyPress(m_iPad, key, repeat, pressed, released); + + switch(key) + { + default: + if(pressed) + { + handled = handleKeyDown(m_iPad, key, repeat); + } + break; + }; +} + +void UIScene_TradingMenu::customDraw(IggyCustomDrawCallbackRegion *region) +{ + Minecraft *pMinecraft = Minecraft::GetInstance(); + if(pMinecraft->localplayers[m_iPad] == NULL || pMinecraft->localgameModes[m_iPad] == NULL) return; + + shared_ptr<ItemInstance> item = nullptr; + int slotId = -1; + swscanf((wchar_t*)region->name,L"slot_%d",&slotId); + + if(slotId < MerchantMenu::USE_ROW_SLOT_END) + { + Slot *slot = m_menu->getSlot(slotId); + item = slot->getItem(); + } + else if(slotId >= TRADES_START) + { + int tradeId = (slotId - TRADES_START) + m_offersStartIndex; + if(tradeId < m_activeOffers.size()) + { + item = m_activeOffers.at(tradeId).first->getSellItem(); + } + } + else + { + int tradeId = m_selectedSlot + m_offersStartIndex; + if( tradeId < m_activeOffers.size() ) + { + switch(slotId) + { + case BUY_A: + item = m_activeOffers.at(tradeId).first->getBuyAItem(); + break; + case BUY_B: + item = m_activeOffers.at(tradeId).first->getBuyBItem(); + break; + }; + } + } + if(item != NULL) customDrawSlotControl(region,m_iPad,item,1.0f,item->isFoil(),true); +} + +void UIScene_TradingMenu::showScrollRightArrow(bool show) +{ + if(m_showingRightArrow != show) + { + IggyDataValue result; + IggyDataValue value[1]; + + value[0].type = IGGY_DATATYPE_boolean; + value[0].boolval = show; + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcShowScrollRightArrow , 1 , value ); + + m_showingRightArrow = show; + } +} + +void UIScene_TradingMenu::showScrollLeftArrow(bool show) +{ + if(m_showingLeftArrow != show) + { + IggyDataValue result; + IggyDataValue value[1]; + + value[0].type = IGGY_DATATYPE_boolean; + value[0].boolval = show; + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcShowScrollLeftArrow , 1 , value ); + + m_showingLeftArrow = show; + } +} + +void UIScene_TradingMenu::moveSelector(bool right) +{ + IggyDataValue result; + IggyDataValue value[1]; + + value[0].type = IGGY_DATATYPE_boolean; + value[0].boolval = right; + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcMoveSelector , 1 , value ); +} + +void UIScene_TradingMenu::setTitle(const wstring &name) +{ + m_labelTrading.setLabel(name); +} + +void UIScene_TradingMenu::setRequest1Name(const wstring &name) +{ + m_labelRequest1.setLabel(name); +} + +void UIScene_TradingMenu::setRequest2Name(const wstring &name) +{ + m_labelRequest2.setLabel(name); +} + +void UIScene_TradingMenu::setRequest1RedBox(bool show) +{ + m_slotListRequest1.showSlotRedBox(0,show); +} + +void UIScene_TradingMenu::setRequest2RedBox(bool show) +{ + m_slotListRequest2.showSlotRedBox(0,show); +} + +void UIScene_TradingMenu::setTradeRedBox(int index, bool show) +{ + m_slotListTrades.showSlotRedBox(index,show); +} + +void UIScene_TradingMenu::setOfferDescription(const wstring &name, vector<wstring> &unformattedStrings) +{ + IggyDataValue result; + IggyDataValue value[1]; + + IggyStringUTF16 stringVal; + stringVal.string = (IggyUTF16*)name.c_str(); + stringVal.length = name.length(); + value[0].type = IGGY_DATATYPE_string_UTF16; + value[0].string16 = stringVal; + + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcSetOfferDescription , 1 , value ); +} diff --git a/Minecraft.Client/Common/UI/UIScene_TradingMenu.h b/Minecraft.Client/Common/UI/UIScene_TradingMenu.h new file mode 100644 index 00000000..08263a1c --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_TradingMenu.h @@ -0,0 +1,78 @@ +#pragma once + +#include "IUIScene_TradingMenu.h" + +class InventoryMenu; + +class UIScene_TradingMenu : public UIScene, public IUIScene_TradingMenu +{ +private: + bool m_showingRightArrow, m_showingLeftArrow; + +public: + UIScene_TradingMenu(int iPad, void *initData, UILayer *parentLayer); + + virtual EUIScene getSceneType() { return eUIScene_TradingMenu;} + +protected: + UIControl m_controlMainPanel; + UIControl_SlotList m_slotListTrades; + UIControl_SlotList m_slotListRequest1, m_slotListRequest2; + UIControl_SlotList m_slotListHotbar, m_slotListInventory; + UIControl_Label m_labelInventory; + UIControl_Label m_labelTrading, m_labelRequired; + UIControl_Label m_labelRequest1, m_labelRequest2; + + IggyName m_funcMoveSelector, m_funcShowScrollRightArrow, m_funcShowScrollLeftArrow, m_funcSetOfferDescription; + + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) + UI_MAP_ELEMENT( m_controlMainPanel, "MainPanel" ) + UI_BEGIN_MAP_CHILD_ELEMENTS( m_controlMainPanel ) + UI_MAP_ELEMENT( m_slotListTrades, "TradingBar") + UI_MAP_ELEMENT( m_slotListRequest1, "Request1") + UI_MAP_ELEMENT( m_slotListRequest2, "Request2") + + UI_MAP_ELEMENT( m_labelTrading, "VillagerText") + UI_MAP_ELEMENT( m_labelRequired, "RequiredLabel") + + UI_MAP_ELEMENT( m_labelRequest1, "Request1Label") + UI_MAP_ELEMENT( m_labelRequest2, "Request2Label") + + UI_MAP_ELEMENT( m_slotListHotbar, "HotBar") + UI_MAP_ELEMENT( m_slotListInventory, "Inventory") + UI_MAP_ELEMENT( m_labelInventory, "InventoryLabel") + + UI_END_MAP_CHILD_ELEMENTS() + + UI_MAP_NAME(m_funcMoveSelector, L"MoveSelector") + UI_MAP_NAME(m_funcShowScrollRightArrow, L"ShowScrollRightArrow") + UI_MAP_NAME(m_funcShowScrollLeftArrow, L"ShowScrollLeftArrow") + UI_MAP_NAME(m_funcSetOfferDescription, L"SetOfferDescription") + UI_END_MAP_ELEMENTS_AND_NAMES() + + virtual wstring getMoviePath(); + virtual void updateTooltips(); + virtual void handleDestroy(); + virtual void handleReload(); + + virtual void tick(); + + void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled); + + void customDraw(IggyCustomDrawCallbackRegion *region); + + virtual void showScrollRightArrow(bool show); + virtual void showScrollLeftArrow(bool show); + virtual void moveSelector(bool right); + virtual void setTitle(const wstring &name); + virtual void setRequest1Name(const wstring &name); + virtual void setRequest2Name(const wstring &name); + + virtual void setRequest1RedBox(bool show); + virtual void setRequest2RedBox(bool show); + virtual void setTradeRedBox(int index, bool show); + + virtual void setOfferDescription(const wstring &name, vector<wstring> &unformattedStrings); + + int getPad() { return m_iPad; } +};
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIScene_TrialExitUpsell.cpp b/Minecraft.Client/Common/UI/UIScene_TrialExitUpsell.cpp new file mode 100644 index 00000000..b395bc4c --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_TrialExitUpsell.cpp @@ -0,0 +1,75 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIScene_TrialExitUpsell.h" + + +UIScene_TrialExitUpsell::UIScene_TrialExitUpsell(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) +{ + // Setup all the Iggy references we need for this scene + initialiseMovie(); +} + +wstring UIScene_TrialExitUpsell::getMoviePath() +{ + return L"TrialExitUpsell"; +} + +void UIScene_TrialExitUpsell::updateTooltips() +{ + ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_EXIT_GAME,IDS_TOOLTIPS_BACK, IDS_UNLOCK_TITLE); +} + +void UIScene_TrialExitUpsell::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled) +{ + //app.DebugPrintf("UIScene_DebugOverlay handling input for pad %d, key %d, down- %s, pressed- %s, released- %s\n", iPad, key, down?"TRUE":"FALSE", pressed?"TRUE":"FALSE", released?"TRUE":"FALSE"); + + ui.AnimateKeyPress(m_iPad, key, repeat, pressed, released); + + switch(key) + { + case ACTION_MENU_CANCEL: + navigateBack(); + break; + case ACTION_MENU_OK: +#ifdef __ORBIS__ + case ACTION_MENU_TOUCHPAD_PRESS: +#endif + if(pressed) + { + //CD - Added for audio + ui.PlayUISFX(eSFX_Press); + app.ExitGame(); + } + break; + case ACTION_MENU_X: + if(ProfileManager.IsSignedIn(iPad)) + { + //CD - Added for audio + ui.PlayUISFX(eSFX_Press); + + // 4J-PB - need to check this user can access the store +#if defined(__PS3__) || defined(__PSVITA__) + bool bContentRestricted; + ProfileManager.GetChatAndContentRestrictions(ProfileManager.GetPrimaryPad(),true,NULL,&bContentRestricted,NULL); + if(bContentRestricted) + { + UINT uiIDA[1]; + uiIDA[0]=IDS_CONFIRM_OK; + ui.RequestMessageBox(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, ProfileManager.GetPrimaryPad(),NULL,this, app.GetStringTable()); + } + else +#endif + { + TelemetryManager->RecordUpsellPresented(iPad, eSen_UpsellID_Full_Version_Of_Game, app.m_dwOfferID); + ProfileManager.DisplayFullVersionPurchase(false,iPad,eSen_UpsellID_Full_Version_Of_Game); + } + } + break; + } +} + +void UIScene_TrialExitUpsell::handleAnimationEnd() +{ + //ui.NavigateToHomeMenu(); + ui.NavigateToScene(0,eUIScene_SaveMessage); +} diff --git a/Minecraft.Client/Common/UI/UIScene_TrialExitUpsell.h b/Minecraft.Client/Common/UI/UIScene_TrialExitUpsell.h new file mode 100644 index 00000000..79e9edf5 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_TrialExitUpsell.h @@ -0,0 +1,31 @@ +#pragma once + +#include "UIScene.h" + +class UIScene_TrialExitUpsell : public UIScene +{ +private: + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) + UI_END_MAP_ELEMENTS_AND_NAMES() + +public: + UIScene_TrialExitUpsell(int iPad, void *initData, UILayer *parentLayer); + + virtual EUIScene getSceneType() { return eUIScene_TrialExitUpsell;} + + // Returns true if this scene has focus for the pad passed in +#ifndef __PS3__ + virtual bool hasFocus(int iPad) { return bHasFocus; } +#endif + virtual void updateTooltips(); + +protected: + virtual wstring getMoviePath(); + +public: + // INPUT + virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled); + + virtual void handleAnimationEnd(); + +};
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIStructs.h b/Minecraft.Client/Common/UI/UIStructs.h new file mode 100644 index 00000000..2dd03c8c --- /dev/null +++ b/Minecraft.Client/Common/UI/UIStructs.h @@ -0,0 +1,409 @@ +#pragma once + +#pragma message("UIStructs.h") + +#include "UIEnums.h" + +class Container; +class Inventory; +class BrewingStandTileEntity; +class DispenserTileEntity; +class FurnaceTileEntity; +class SignTileEntity; +class LevelGenerationOptions; +class LocalPlayer; +class Merchant; + +// 4J Stu - Structs shared by Iggy and Xui scenes. +typedef struct _UIVec2D +{ + float x; + float y; + + _UIVec2D& operator+=(const _UIVec2D &rhs) + { + x += rhs.x; + y += rhs.y; + return *this; + } +} UIVec2D; + +// Brewing +typedef struct _BrewingScreenInput +{ + shared_ptr<Inventory> inventory; + shared_ptr<BrewingStandTileEntity> brewingStand; + int iPad; + bool bSplitscreen; +} BrewingScreenInput; + +// Chest +typedef struct _ContainerScreenInput +{ + shared_ptr<Container> inventory; + shared_ptr<Container> container; + int iPad; + bool bSplitscreen; +} ContainerScreenInput; + +// Dispenser +typedef struct _TrapScreenInput +{ + shared_ptr<Container> inventory; + shared_ptr<DispenserTileEntity> trap; + int iPad; + bool bSplitscreen; +} TrapScreenInput; + +// Inventory and creative inventory +typedef struct _InventoryScreenInput +{ + shared_ptr<LocalPlayer> player; + bool bNavigateBack; // If we came here from the crafting screen, go back to it, rather than closing the xui menus + int iPad; + bool bSplitscreen; +} InventoryScreenInput; + +// Enchanting +typedef struct _EnchantingScreenInput +{ + shared_ptr<Inventory> inventory; + Level *level; + int x; + int y; + int z; + int iPad; + bool bSplitscreen; +} EnchantingScreenInput; + +// Furnace +typedef struct _FurnaceScreenInput +{ + shared_ptr<Inventory> inventory; + shared_ptr<FurnaceTileEntity> furnace; + int iPad; + bool bSplitscreen; +} FurnaceScreenInput; + +// Crafting +typedef struct _CraftingPanelScreenInput +{ + shared_ptr<LocalPlayer> player; + int iContainerType; // RECIPE_TYPE_2x2 or RECIPE_TYPE_3x3 + bool bSplitscreen; + int iPad; + int x; + int y; + int z; +} +CraftingPanelScreenInput; + +// Trading +typedef struct _TradingScreenInput +{ + shared_ptr<Inventory> inventory; + shared_ptr<Merchant> trader; + Level *level; + int iPad; + bool bSplitscreen; +} +TradingScreenInput; + +// Anvil +typedef struct _AnvilScreenInput +{ + shared_ptr<Inventory> inventory; + Level *level; + int x; + int y; + int z; + int iPad; + bool bSplitscreen; +} +AnvilScreenInput; + +// Sign +typedef struct _SignEntryScreenInput +{ + shared_ptr<SignTileEntity> sign; + int iPad; +} SignEntryScreenInput; + +// Connecting progress +typedef struct _ConnectionProgressParams +{ + int iPad; + int stringId; + bool showTooltips; + bool setFailTimer; + int timerTime; + void (*cancelFunc)(LPVOID param); + LPVOID cancelFuncParam; + + _ConnectionProgressParams() + { + iPad = 0; + stringId = -1; + showTooltips = false; + setFailTimer = false; + timerTime = 0; + cancelFunc = NULL; + cancelFuncParam = NULL; + } +} ConnectionProgressParams; + +// Fullscreen progress +typedef struct _UIFullscreenProgressCompletionData +{ + BOOL bRequiresUserAction; + BOOL bShowBackground; + BOOL bShowLogo; + BOOL bShowTips; + ProgressionCompletionType type; + int iPad; + EUIScene scene; + + _UIFullscreenProgressCompletionData() + { + bRequiresUserAction = FALSE; + bShowBackground = TRUE; + bShowLogo = TRUE; + bShowTips = TRUE; + type = e_ProgressCompletion_NoAction; + } +} UIFullscreenProgressCompletionData; + +// Create world +typedef struct _CreateWorldMenuInitData +{ + BOOL bOnline; + BOOL bIsPrivate; + int iPad; +} +CreateWorldMenuInitData; + +// Join/Load saves list +typedef struct _SaveListDetails +{ + int saveId; + PBYTE pbThumbnailData; + DWORD dwThumbnailSize; +#ifdef _DURANGO + wchar_t UTF16SaveName[128]; + wchar_t UTF16SaveFilename[MAX_SAVEFILENAME_LENGTH]; +#else + char UTF8SaveName[128]; +#ifndef _XBOX + char UTF8SaveFilename[MAX_SAVEFILENAME_LENGTH]; +#endif +#endif + + _SaveListDetails() + { + saveId = 0; + pbThumbnailData = NULL; + dwThumbnailSize = 0; +#ifdef _DURANGO + ZeroMemory(UTF16SaveName,sizeof(wchar_t)*128); + ZeroMemory(UTF16SaveFilename,sizeof(wchar_t)*MAX_SAVEFILENAME_LENGTH); +#else + ZeroMemory(UTF8SaveName,128); +#ifndef _XBOX + ZeroMemory(UTF8SaveFilename,MAX_SAVEFILENAME_LENGTH); +#endif +#endif + } + +} SaveListDetails; + +// Load world +typedef struct _LoadMenuInitData +{ + int iPad; + int iSaveGameInfoIndex; + LevelGenerationOptions *levelGen; + SaveListDetails *saveDetails; +} +LoadMenuInitData; + +// Join Games +typedef struct _JoinMenuInitData +{ + FriendSessionInfo *selectedSession; + int iPad; +} JoinMenuInitData; + +// More Options +typedef struct _LaunchMoreOptionsMenuInitData +{ + BOOL bOnlineGame; + BOOL bInviteOnly; + BOOL bAllowFriendsOfFriends; + + BOOL bGenerateOptions; + BOOL bStructures; + BOOL bFlatWorld; + BOOL bBonusChest; + + BOOL bPVP; + BOOL bTrust; + BOOL bFireSpreads; + BOOL bTNT; + + BOOL bHostPrivileges; + BOOL bResetNether; + + BOOL bOnlineSettingChangedBySystem; + + int iPad; + + DWORD dwTexturePack; + + wstring seed; + int worldSize; + bool bDisableSaving; + + _LaunchMoreOptionsMenuInitData() + { + memset(this,0,sizeof(_LaunchMoreOptionsMenuInitData)); + bOnlineGame = TRUE; + bAllowFriendsOfFriends = TRUE; + bPVP = TRUE; + bFireSpreads = TRUE; + bTNT = TRUE; + iPad = -1; + worldSize = 3; + seed = L""; + bDisableSaving = false; + } +} +LaunchMoreOptionsMenuInitData; + +typedef struct _LoadingInputParams +{ + C4JThreadStartFunc* func; + LPVOID lpParam; + UIFullscreenProgressCompletionData *completionData; + + int cancelText; + void (*cancelFunc)(LPVOID param); + void (*completeFunc)(LPVOID param); + LPVOID m_cancelFuncParam; + LPVOID m_completeFuncParam; + bool waitForThreadToDelete; + + _LoadingInputParams() + { + func = NULL; + lpParam = NULL; + completionData = NULL; + + cancelText = -1; + cancelFunc = NULL; + completeFunc = NULL; + m_cancelFuncParam = NULL; + m_completeFuncParam = NULL; + waitForThreadToDelete = false; + } +} LoadingInputParams; + +// Tutorial +#ifndef _XBOX +class UIScene; +#endif +class Tutorial; +typedef struct _TutorialPopupInfo +{ +#ifdef _XBOX + CXuiScene *interactScene; +#else + UIScene *interactScene; +#endif + LPCWSTR desc; + LPCWSTR title; + int icon; + int iAuxVal /* = 0 */; + bool isFoil /* = false */; + bool allowFade /* = true */; + bool isReminder /*= false*/; + Tutorial *tutorial; + + _TutorialPopupInfo() + { + interactScene = NULL; + desc = L""; + title = L""; + icon = -1; + iAuxVal = 0; + isFoil = false; + allowFade = true; + isReminder = false; + tutorial = NULL; + } + +} TutorialPopupInfo; + +// Quadrant sign in +typedef struct _SignInInfo +{ + int( *Func)(LPVOID,const bool, const int iPad); + LPVOID lpParam; + bool requireOnline; +} SignInInfo; + +// Credits +typedef struct +{ + LPCWSTR m_Text; // Should contain string, optionally with %s to add in translated string ... e.g. "Andy West - %s" + int m_iStringID[2]; // May be NO_TRANSLATED_STRING if we do not require to add any translated string. + ECreditTextTypes m_eType; +} +SCreditTextItemDef; + +// Message box +typedef struct _MessageBoxInfo +{ + UINT uiTitle; + UINT uiText; + UINT *uiOptionA; + UINT uiOptionC; + DWORD dwPad; + int( *Func)(LPVOID,int,const C4JStorage::EMessageResult); + LPVOID lpParam; + //C4JStringTable *pStringTable; // 4J Stu - We don't need this for our internal message boxes + WCHAR *pwchFormatString; + DWORD dwFocusButton; +} MessageBoxInfo; + +typedef struct _DLCOffersParam +{ + int iPad; + int iOfferC; + int iType; +} +DLCOffersParam; + +typedef struct _InGamePlayerOptionsInitData +{ + int iPad; + BYTE networkSmallId; + unsigned int playerPrivileges; +} InGamePlayerOptionsInitData; + +typedef struct _DebugSetCameraPosition +{ + int player; + double m_camX, m_camY, m_camZ, m_yRot, m_elev; +} DebugSetCameraPosition; + +typedef struct _TeleportMenuInitData +{ + int iPad; + bool teleportToPlayer; +} TeleportMenuInitData; + +typedef struct _CustomDrawData +{ + float x0, y0, x1, y1; // the bounding box of the original DisplayObject, in object space + float mat[16]; +} CustomDrawData; diff --git a/Minecraft.Client/Common/UI/UITTFFont.cpp b/Minecraft.Client/Common/UI/UITTFFont.cpp new file mode 100644 index 00000000..eb343382 --- /dev/null +++ b/Minecraft.Client/Common/UI/UITTFFont.cpp @@ -0,0 +1,51 @@ +#include "stdafx.h" +#include "UI.h" +#include "..\..\..\Minecraft.World\StringHelpers.h" +#include "..\..\..\Minecraft.World\File.h" +#include "UITTFFont.h" + +UITTFFont::UITTFFont(const string &path, S32 fallbackCharacter) +{ + app.DebugPrintf("UITTFFont opening %s\n",path.c_str()); + +#ifdef _UNICODE + wstring wPath = convStringToWstring(path); + HANDLE file = CreateFile(wPath.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); +#else + HANDLE file = CreateFile(path.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); +#endif + if( file == INVALID_HANDLE_VALUE ) + { + DWORD error = GetLastError(); + app.DebugPrintf("Failed to open TTF file with error code %d (%x)\n", error, error); + assert(false); + } + + DWORD dwHigh=0; + DWORD dwFileSize = GetFileSize(file,&dwHigh); + + if(dwFileSize!=0) + { + DWORD bytesRead; + + pbData = (PBYTE) new BYTE[dwFileSize]; + BOOL bSuccess = ReadFile(file,pbData,dwFileSize,&bytesRead,NULL); + if(bSuccess==FALSE) + { + app.FatalLoadError(); + } + CloseHandle(file); + + IggyFontInstallTruetypeUTF8 ( (void *)pbData, IGGY_TTC_INDEX_none, "Mojangles_TTF", -1, IGGY_FONTFLAG_none ); + + IggyFontInstallTruetypeFallbackCodepointUTF8( "Mojangles_TTF", -1, IGGY_FONTFLAG_none, fallbackCharacter ); + + // 4J Stu - These are so we can use the default flash controls + IggyFontInstallTruetypeUTF8 ( (void *)pbData, IGGY_TTC_INDEX_none, "Times New Roman", -1, IGGY_FONTFLAG_none ); + IggyFontInstallTruetypeUTF8 ( (void *)pbData, IGGY_TTC_INDEX_none, "Arial", -1, IGGY_FONTFLAG_none ); + } +} + +UITTFFont::~UITTFFont() +{ +}
\ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UITTFFont.h b/Minecraft.Client/Common/UI/UITTFFont.h new file mode 100644 index 00000000..0de7c4e0 --- /dev/null +++ b/Minecraft.Client/Common/UI/UITTFFont.h @@ -0,0 +1,12 @@ +#pragma once + +class UITTFFont +{ +private: + PBYTE pbData; + //DWORD dwDataSize; + +public: + UITTFFont(const string &path, S32 fallbackCharacter); + ~UITTFFont(); +}; |
