#include "../../Minecraft.World/Platform/stdafx.h" #include "UI.h" #include "UIComponent_TutorialPopup.h" #include "../Tutorial/Tutorial.h" #include "../../Minecraft.World/Util/StringHelpers.h" #include "../../Minecraft.Client/Player/MultiPlayerLocalPlayer.h" #include "../../Minecraft.Client/Minecraft.h" #include "../../Minecraft.World/Headers/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 = nullptr; m_lastInteractSceneMoved = nullptr; m_lastSceneMovedLeft = false; m_bAllowFade = false; m_iconItem = nullptr; m_iconIsFoil = false; m_bContainerMenuVisible = false; m_bSplitscreenGamertagVisible = false; m_iconType = e_ICON_TYPE_IGGY; m_labelDescription.init(L""); // 4jcraft added m_tutorial = nullptr; } std::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); setupIconHolder(m_iconType); } void UIComponent_TutorialPopup::SetTutorialDescription( TutorialPopupInfo* info) { m_interactScene = info->interactScene; // 4jcraft added m_tutorial = info->tutorial; std::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 = nullptr; } } 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 std::wstring& desc, const std::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 = nullptr; 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) { std::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"",app.GetHTMLColour(eHTMLColor_White),m_textFontSize); swprintf(formatting, 40, L"", app.GetHTMLColour(eHTMLColor_White)); text = formatting + text; m_labelDescription.setLabel(text, true); } else { std::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"",app.GetHTMLColour(eHTMLColor_White),m_textFontSize); swprintf(formatting, 40, L"", 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); } } std::wstring UIComponent_TutorialPopup::_SetIcon(int icon, int iAuxVal, bool isFoil, const wchar_t* desc) { std::wstring temp(desc); bool isFixedIcon = false; m_iconIsFoil = isFoil; if (icon != TUTORIAL_NO_ICON) { m_iconIsFoil = false; m_iconItem = std::shared_ptr(new ItemInstance(icon, 1, iAuxVal)); } else { m_iconItem = nullptr; std::wstring openTag(L"{*ICON*}"); std::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()) { std::wstring id = temp.substr(iconStartPos, iconEndPos - iconStartPos); std::vector idAndAux = stringSplit(id, L':'); int iconId = _fromString(idAndAux[0]); if (idAndAux.size() > 1) { iAuxVal = _fromString(idAndAux[1]); } else { iAuxVal = 0; } m_iconItem = std::shared_ptr( new ItemInstance(iconId, 1, iAuxVal)); temp.replace(iconTagStartPos, iconEndPos - iconTagStartPos + closeTag.length(), L""); } } // remove any icon text else if (temp.find(L"{*CraftingTableIcon*}") != std::wstring::npos) { m_iconItem = std::shared_ptr( new ItemInstance(Tile::workBench_Id, 1, 0)); } else if (temp.find(L"{*SticksIcon*}") != std::wstring::npos) { m_iconItem = std::shared_ptr( new ItemInstance(Item::stick_Id, 1, 0)); } else if (temp.find(L"{*PlanksIcon*}") != std::wstring::npos) { m_iconItem = std::shared_ptr( new ItemInstance(Tile::wood_Id, 1, 0)); } else if (temp.find(L"{*WoodenShovelIcon*}") != std::wstring::npos) { m_iconItem = std::shared_ptr( new ItemInstance(Item::shovel_wood_Id, 1, 0)); } else if (temp.find(L"{*WoodenHatchetIcon*}") != std::wstring::npos) { m_iconItem = std::shared_ptr( new ItemInstance(Item::hatchet_wood_Id, 1, 0)); } else if (temp.find(L"{*WoodenPickaxeIcon*}") != std::wstring::npos) { m_iconItem = std::shared_ptr( new ItemInstance(Item::pickAxe_wood_Id, 1, 0)); } else if (temp.find(L"{*FurnaceIcon*}") != std::wstring::npos) { m_iconItem = std::shared_ptr( new ItemInstance(Tile::furnace_Id, 1, 0)); } else if (temp.find(L"{*WoodenDoorIcon*}") != std::wstring::npos) { m_iconItem = std::shared_ptr( new ItemInstance(Item::door_wood, 1, 0)); } else if (temp.find(L"{*TorchIcon*}") != std::wstring::npos) { m_iconItem = std::shared_ptr( new ItemInstance(Tile::torch_Id, 1, 0)); } else if (temp.find(L"{*BoatIcon*}") != std::wstring::npos) { m_iconItem = std::shared_ptr( new ItemInstance(Item::boat_Id, 1, 0)); } else if (temp.find(L"{*FishingRodIcon*}") != std::wstring::npos) { m_iconItem = std::shared_ptr( new ItemInstance(Item::fishingRod_Id, 1, 0)); } else if (temp.find(L"{*FishIcon*}") != std::wstring::npos) { m_iconItem = std::shared_ptr( new ItemInstance(Item::fish_raw_Id, 1, 0)); } else if (temp.find(L"{*MinecartIcon*}") != std::wstring::npos) { m_iconItem = std::shared_ptr( new ItemInstance(Item::minecart_Id, 1, 0)); } else if (temp.find(L"{*RailIcon*}") != std::wstring::npos) { m_iconItem = std::shared_ptr( new ItemInstance(Tile::rail_Id, 1, 0)); } else if (temp.find(L"{*PoweredRailIcon*}") != std::wstring::npos) { m_iconItem = std::shared_ptr( new ItemInstance(Tile::goldenRail_Id, 1, 0)); } else if (temp.find(L"{*StructuresIcon*}") != std::wstring::npos) { isFixedIcon = true; setupIconHolder(e_ICON_TYPE_STRUCTURES); } else if (temp.find(L"{*ToolsIcon*}") != std::wstring::npos) { isFixedIcon = true; setupIconHolder(e_ICON_TYPE_TOOLS); } else if (temp.find(L"{*StoneIcon*}") != std::wstring::npos) { m_iconItem = std::shared_ptr( new ItemInstance(Tile::stone_Id, 1, 0)); } else { m_iconItem = nullptr; } } if (!isFixedIcon && m_iconItem != nullptr) setupIconHolder(e_ICON_TYPE_IGGY); m_controlIconHolder.setVisible(isFixedIcon || m_iconItem != nullptr); return temp; } std::wstring UIComponent_TutorialPopup::_SetImage(std::wstring& desc) { // 4J Stu - Unused return desc; } std::wstring UIComponent_TutorialPopup::ParseDescription(int iPad, std::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 != std::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 == nullptr) 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); bool isTradingScene = (m_interactScene->getSceneType() == eUIScene_TradingMenu); 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 && !isTradingScene) { 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; default: 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; default: 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; default: 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 != nullptr) 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); m_iconType = icon; }