diff --git a/DataSpec/DNACommon/SAVWCommon.hpp b/DataSpec/DNACommon/SAVWCommon.hpp index 8325ec372..a4601453c 100644 --- a/DataSpec/DNACommon/SAVWCommon.hpp +++ b/DataSpec/DNACommon/SAVWCommon.hpp @@ -13,7 +13,8 @@ enum class EScanCategory Data, Lore, Creature, - Research + Research, + Artifact }; struct Header : BigYAML diff --git a/DataSpec/DNACommon/Tweaks/ITweakGui.hpp b/DataSpec/DNACommon/Tweaks/ITweakGui.hpp index 0f8297352..e8ad396a1 100644 --- a/DataSpec/DNACommon/Tweaks/ITweakGui.hpp +++ b/DataSpec/DNACommon/Tweaks/ITweakGui.hpp @@ -105,6 +105,7 @@ struct ITweakGui : ITweak virtual float GetScanSidesStartTime() const=0; virtual float GetScanSidesEndTime() const=0; virtual float GetScanSidesPositionStart() const=0; + virtual bool GetLatchArticleText() const=0; virtual float GetWorldTransManagerCharsPerSfx() const=0; virtual atUint32 GetXRayFogMode() const=0; virtual float GetXRayFogNearZ() const=0; diff --git a/DataSpec/DNAMP1/Tweaks/CTweakGui.hpp b/DataSpec/DNAMP1/Tweaks/CTweakGui.hpp index c0ff31683..845acec4f 100644 --- a/DataSpec/DNAMP1/Tweaks/CTweakGui.hpp +++ b/DataSpec/DNAMP1/Tweaks/CTweakGui.hpp @@ -149,7 +149,7 @@ struct CTweakGui : ITweakGui Value x26c_; Value x270_scanSidesPositionStart; Value x274_; - bool x275_ = true; + bool x275_latchArticleText = true; Value x278_wtMgrCharsPerSfx; Value x27c_xrayFogMode; Value x280_xrayFogNearZ; @@ -266,6 +266,7 @@ struct CTweakGui : ITweakGui float GetScanSidesStartTime() const { return x224_scanSidesStartTime; } float GetScanSidesEndTime() const { return x228_scanSidesEndTime; } float GetScanSidesPositionStart() const { return x270_scanSidesPositionStart; } + bool GetLatchArticleText() const { return x275_latchArticleText; } float GetWorldTransManagerCharsPerSfx() const { return x278_wtMgrCharsPerSfx; } atUint32 GetXRayFogMode() const { return x27c_xrayFogMode; } float GetXRayFogNearZ() const { return x280_xrayFogNearZ; } diff --git a/Runtime/CMemoryCardSys.cpp b/Runtime/CMemoryCardSys.cpp index 42b8d6f97..6db603077 100644 --- a/Runtime/CMemoryCardSys.cpp +++ b/Runtime/CMemoryCardSys.cpp @@ -106,6 +106,8 @@ CMemoryCardSys::CMemoryCardSys() x1c_worldInter->emplace_back(mlvl.second, -1); } } + + x30_scanCategoryCounts.resize(6); } bool CMemoryCardSys::InitializePump() @@ -154,7 +156,10 @@ bool CMemoryCardSys::InitializePump() std::find_if(x20_scanStates.begin(), x20_scanStates.end(), [&](const auto& test) { return test.first == scan.x0_id && test.second == scan.x4_category; }); if (existingSearch == x20_scanStates.end()) + { x20_scanStates.emplace_back(scan.x0_id, scan.x4_category); + ++x30_scanCategoryCounts[int(scan.x4_category)]; + } } wldMemOut.x3c_saveWorld = std::move(world.x34_saveWorld); diff --git a/Runtime/CMemoryCardSys.hpp b/Runtime/CMemoryCardSys.hpp index 344583b02..6ce055a65 100644 --- a/Runtime/CMemoryCardSys.hpp +++ b/Runtime/CMemoryCardSys.hpp @@ -64,6 +64,7 @@ class CMemoryCardSys std::vector> xc_memoryWorlds; /* MLVL as key */ std::experimental::optional> x1c_worldInter; /* used to be auto_ptr of vector */ std::vector> x20_scanStates; + rstl::reserved_vector x30_scanCategoryCounts; public: static kabufuda::SystemString ResolveDolphinCardPath(kabufuda::ECardSlot slot); @@ -91,6 +92,7 @@ public: const std::vector& GetHints() const { return x0_hints->GetHints(); } const std::vector>& GetMemoryWorlds() const { return xc_memoryWorlds; } const std::vector>& GetScanStates() const { return x20_scanStates; } + u32 GetScanCategoryCount(CSaveWorld::EScanCategory cat) const { return x30_scanCategoryCounts[int(cat)]; } bool HasSaveWorldMemory(ResId wldId) const; const CSaveWorldMemory& GetSaveWorldMemory(ResId wldId) const; diff --git a/Runtime/GuiSys/CAuiImagePane.cpp b/Runtime/GuiSys/CAuiImagePane.cpp index 18d074ec8..25289d13a 100644 --- a/Runtime/GuiSys/CAuiImagePane.cpp +++ b/Runtime/GuiSys/CAuiImagePane.cpp @@ -1,14 +1,17 @@ #include "CAuiImagePane.hpp" +#include "CSimplePool.hpp" namespace urde { -CAuiImagePane::CAuiImagePane(const CGuiWidgetParms& parms, CSimplePool* sp, ResId, ResId, +CAuiImagePane::CAuiImagePane(const CGuiWidgetParms& parms, CSimplePool* sp, ResId tex0, ResId tex1, rstl::reserved_vector&& coords, - rstl::reserved_vector&& uvs, bool) -: CGuiWidget(parms) + rstl::reserved_vector&& uvs, bool initTex) +: CGuiWidget(parms), xc8_tex0(tex0), xcc_tex1(tex1), xe0_coords(std::move(coords)), + x114_uvs(std::move(uvs)) { - + if (initTex) + SetTextureID0(tex0, sp); } std::shared_ptr CAuiImagePane::Create(CGuiFrame* frame, CInputStream& in, CSimplePool* sp) @@ -31,4 +34,23 @@ std::shared_ptr CAuiImagePane::Create(CGuiFrame* frame, CInputStream return ret; } +void CAuiImagePane::SetTextureID0(ResId tex, CSimplePool* sp) +{ + xc8_tex0 = tex; + if (!sp) + return; + if (xc8_tex0 != -1) + xb8_tex0Tok = sp->GetObj({FOURCC('TXTR'), xc8_tex0}); + else + xb8_tex0Tok = TLockedToken(); +} + +void CAuiImagePane::SetAnimationParms(const zeus::CVector2f& vec, float interval, float duration) +{ + x138_ = vec; + x140_interval = interval; + x144_ = 0.f; + x148_duration = duration; +} + } diff --git a/Runtime/GuiSys/CAuiImagePane.hpp b/Runtime/GuiSys/CAuiImagePane.hpp index 50fd74952..581bd7ab5 100644 --- a/Runtime/GuiSys/CAuiImagePane.hpp +++ b/Runtime/GuiSys/CAuiImagePane.hpp @@ -2,19 +2,39 @@ #define __URDE_CAUIIMAGEPANE_HPP__ #include "CGuiWidget.hpp" +#include "CToken.hpp" namespace urde { class CSimplePool; +class CTexture; class CAuiImagePane : public CGuiWidget { + TLockedToken xb8_tex0Tok; // Used to be optional + ResId xc8_tex0; + ResId xcc_tex1; + zeus::CVector2f xd0_; + zeus::CVector2f xd8_; + rstl::reserved_vector xe0_coords; + rstl::reserved_vector x114_uvs; + zeus::CVector2f x138_; + float x140_interval = 0.f; + float x144_ = 0.f; + float x148_duration = 0.f; + float x14c_invAlpha = 0.f; + float x150_interp = 0.f; public: CAuiImagePane(const CGuiWidgetParms& parms, CSimplePool* sp, ResId, ResId, rstl::reserved_vector&& coords, - rstl::reserved_vector&& uvs, bool); + rstl::reserved_vector&& uvs, bool initTex); FourCC GetWidgetTypeID() const { return FOURCC('IMGP'); } static std::shared_ptr Create(CGuiFrame* frame, CInputStream& in, CSimplePool* sp); + + void SetTextureID0(ResId tex, CSimplePool* sp); + void SetAnimationParms(const zeus::CVector2f& vec, float interval, float duration); + void SetInverseAlpha(float a) { x14c_invAlpha = a; } + void ResetInterp() { x150_interp = 0.f; } }; } diff --git a/Runtime/GuiSys/CStringTable.hpp b/Runtime/GuiSys/CStringTable.hpp index 753d0b742..d817a36c9 100644 --- a/Runtime/GuiSys/CStringTable.hpp +++ b/Runtime/GuiSys/CStringTable.hpp @@ -18,6 +18,7 @@ public: void LoadStringTable(CInputStream& in); const char16_t* GetString(s32) const; + u32 GetStringCount() const { return x0_stringCount; } static void SetLanguage(s32); }; diff --git a/Runtime/MP1/CArtifactDoll.cpp b/Runtime/MP1/CArtifactDoll.cpp index 1109c9453..72332783a 100644 --- a/Runtime/MP1/CArtifactDoll.cpp +++ b/Runtime/MP1/CArtifactDoll.cpp @@ -95,6 +95,7 @@ void CArtifactDoll::Draw(float alpha, const CStateManager& mgr, if (!IsLoaded()) return; + alpha *= x24_fader; g_Renderer->SetPerspective(55.f, g_Viewport.x8_width, g_Viewport.xc_height, 0.2f, 4096.f); CGraphics::SetViewPointMatrix(zeus::CTransform::Translate(0.f, -10.f, 0.f)); @@ -139,6 +140,8 @@ void CArtifactDoll::Draw(float alpha, const CStateManager& mgr, x20_actorLights->ActivateLights(model->GetInstance()); model->Draw(flags); + flags.x4_color = color; + flags.x4_color.a *= alpha; flags.m_extendedShader = EExtendedShader::ForcedAdditive; model->Draw(flags); } diff --git a/Runtime/MP1/CInventoryScreen.cpp b/Runtime/MP1/CInventoryScreen.cpp index 319fc77cf..d124bbe9e 100644 --- a/Runtime/MP1/CInventoryScreen.cpp +++ b/Runtime/MP1/CInventoryScreen.cpp @@ -290,7 +290,7 @@ void CInventoryScreen::UpdateTextBody() x174_textpane_body->TextSupport()->SetPage(0); } -void CInventoryScreen::ChangedMode() +void CInventoryScreen::ChangedMode(EMode oldMode) { if (x10_mode == EMode::TextScroll) { diff --git a/Runtime/MP1/CInventoryScreen.hpp b/Runtime/MP1/CInventoryScreen.hpp index 62712a3d5..f6bb22318 100644 --- a/Runtime/MP1/CInventoryScreen.hpp +++ b/Runtime/MP1/CInventoryScreen.hpp @@ -40,7 +40,7 @@ public: bool VReady() const; void VActivate(); void RightTableSelectionChanged(int selBegin, int selEnd); - void ChangedMode(); + void ChangedMode(EMode oldMode); void UpdateRightTable(); bool ShouldLeftTableAdvance() const; bool ShouldRightTableAdvance() const; diff --git a/Runtime/MP1/CLogBookScreen.cpp b/Runtime/MP1/CLogBookScreen.cpp index 903bfa523..93dd15ed2 100644 --- a/Runtime/MP1/CLogBookScreen.cpp +++ b/Runtime/MP1/CLogBookScreen.cpp @@ -1,6 +1,8 @@ #include "CLogBookScreen.hpp" #include "GuiSys/CGuiModel.hpp" #include "GuiSys/CGuiTableGroup.hpp" +#include "GuiSys/CGuiTextPane.hpp" +#include "GuiSys/CAuiImagePane.hpp" #include "MP1.hpp" namespace urde @@ -12,6 +14,8 @@ CLogBookScreen::CLogBookScreen(const CStateManager& mgr, CGuiFrame& frame, const CStringTable& pauseStrg) : CPauseScreenBase(mgr, frame, pauseStrg) { + x19c_scanCompletes.resize(5); + x200_viewScans.resize(5); x258_artifactDoll = std::make_unique(); CMain::EnsureWorldPaksReady(); InitializeLogBook(); @@ -25,9 +29,255 @@ CLogBookScreen::~CLogBookScreen() CMain::EnsureWorldPakReady(g_GameState->CurrentWorldAssetId()); } +bool CLogBookScreen::IsScanComplete(CSaveWorld::EScanCategory category, ResId scan, + const CPlayerState& playerState) +{ + float time = playerState.GetScanTime(scan); + if (category == CSaveWorld::EScanCategory::Artifact) + return time >= 0.5f; + else + return time >= 1.f; +} + void CLogBookScreen::InitializeLogBook() { + for (int i=0 ; i<5 ; ++i) + x19c_scanCompletes[i].reserve(g_MemoryCardSys->GetScanCategoryCount(CSaveWorld::EScanCategory(i + 1))); + CPlayerState& playerState = *x4_mgr.GetPlayerState(); + for (const std::pair& scanState : g_MemoryCardSys->GetScanStates()) + { + if (scanState.second == CSaveWorld::EScanCategory::None) + continue; + bool complete = IsScanComplete(scanState.second, scanState.first, playerState); + x19c_scanCompletes[int(scanState.second) - 1].push_back(std::make_pair(scanState.first, complete)); + } + + std::sort(x19c_scanCompletes[4].begin(), x19c_scanCompletes[4].end(), + [](const std::pair& a, std::pair& b) + { + return CArtifactDoll::GetArtifactHeadScanIndex(a.first) < + CArtifactDoll::GetArtifactHeadScanIndex(b.first); + }); + + auto viewIt = x200_viewScans.begin(); + for (std::vector>& category : x19c_scanCompletes) + { + std::vector, + TLockedToken>>& viewScans = *viewIt++; + size_t viewScanCount = std::min(category.size(), size_t(5)); + viewScans.reserve(viewScanCount); + for (size_t i=0 ; iGetObj({FOURCC('SCAN'), category[i].first}), + TLockedToken{})); + } +} + +void CLogBookScreen::UpdateRightTitles() +{ + std::vector>& category = + x19c_scanCompletes[x70_tablegroup_leftlog->GetUserSelection()]; + for (int i=0 ; xd8_textpane_titles.size() ; ++i) + { + std::u16string string; + size_t scanIndex = x18_firstViewRightSel + i; + if (scanIndex < x1f0_curViewScans.size()) + { + std::pair, + TCachedToken>& scan = x1f0_curViewScans[scanIndex]; + if (scan.second && scan.second.IsLoaded()) + { + if (category[scanIndex].second) + { + if (scan.second->GetStringCount() > 1) + string = scan.second->GetString(1); + else + string = u"No Title!"; + } + else + { + string = u"??????"; + } + } + + if (string.empty()) + string = u"........"; + } + xd8_textpane_titles[i]->TextSupport()->SetText(string); + } + + int rightSelMod = x18_firstViewRightSel % 5; + int rightSelRem = 5 - rightSelMod; + for (int i=0 ; i= rightSelMod) ? rightSelRem - 5 : rightSelRem) * x38_highlightPitch; + x144_model_titles[i]->SetLocalTransform( + zeus::CTransform::Translate(0.f, 0.f, zOff) * x144_model_titles[i]->GetTransform()); + } +} + +void CLogBookScreen::PumpArticleLoad() +{ + x260_24_loaded = true; + for (std::vector, + TLockedToken>>& category : x200_viewScans) + { + for (std::pair, + TLockedToken>& scan : category) + { + if (scan.first.IsLoaded()) + { + if (!scan.second) + { + scan.second = g_SimplePool->GetObj({FOURCC('STRG'), scan.first->GetStringTableId()}); + x260_24_loaded = false; + } + } + else + { + x260_24_loaded = false; + } + } + } + + int rem = 6; + for (std::pair, + TCachedToken>& scan : x1f0_curViewScans) + { + if (scan.first.IsLoaded()) + { + if (!scan.second) + { + scan.second = g_SimplePool->GetObj({FOURCC('STRG'), scan.first->GetStringTableId()}); + scan.second.Lock(); + } + } + if (--rem == 0) + break; + } + + if (x1f0_curViewScans.size()) + { + int articleIdx = x18_firstViewRightSel; + while (rem > 0) + { + x1f0_curViewScans[articleIdx].first.Lock(); + articleIdx = NextSurroundingArticleIndex(articleIdx); + --rem; + } + } + + for (std::pair, + TCachedToken>& scan : x1f0_curViewScans) + { + if (scan.first.IsLoaded()) + { + if (scan.second && scan.second.IsLoaded()) + { + UpdateRightTitles(); + UpdateBodyText(); + } + } + } +} + +bool CLogBookScreen::IsScanCategoryReady(CSaveWorld::EScanCategory category) const +{ + CPlayerState& playerState = *x4_mgr.GetPlayerState(); + for (const std::pair& scanState : g_MemoryCardSys->GetScanStates()) + { + if (scanState.second != category) + continue; + if (IsScanComplete(scanState.second, scanState.first, playerState)) + return true; + } + return false; +} + +void CLogBookScreen::UpdateBodyText() +{ + if (x10_mode != EMode::TextScroll) + { + x174_textpane_body->TextSupport()->SetText(u""); + return; + } + + TCachedToken& str = x1f0_curViewScans[x1c_rightSel].second; + if (str && str.IsLoaded()) + { + std::u16string accumStr = str->GetString(0); + if (str->GetStringCount() > 2) + { + accumStr += u"\n\n"; + accumStr += str->GetString(2); + } + + if (IsArtifactCategorySelected()) + { + int headIdx = GetSelectedArtifactHeadScanIndex(); + if (headIdx >= 0 && g_GameState->GetPlayerState()->HasPowerUp(CPlayerState::EItemType(headIdx + 29))) + accumStr = std::u16string(u"\n\n\n\n\n\n") + g_MainStringTable->GetString(105); + } + + x174_textpane_body->TextSupport()->SetText(accumStr, true); + } +} + +void CLogBookScreen::UpdateBodyImagesAndText() +{ + const CScannableObjectInfo* scan = x1f0_curViewScans[x1c_rightSel].first.GetObj(); + for (CAuiImagePane* pane : xf0_imagePanes) + { + pane->SetTextureID0(-1, g_SimplePool); + pane->SetAnimationParms(zeus::CVector2f::skZero, 0.f, 0.f); + } + + for (int i=0 ; i<4 ; ++i) + { + const CScannableObjectInfo::SBucket& bucket = scan->GetBucket(i); + if (bucket.x8_imagePos == -1) + continue; + CAuiImagePane* pane = xf0_imagePanes[bucket.x8_imagePos]; + if (bucket.x14_interval > 0.f) + { + pane->SetAnimationParms(zeus::CVector2f(bucket.xc_size.x, bucket.xc_size.y), + bucket.x14_interval, bucket.x18_fadeDuration); + } + pane->SetTextureID0(bucket.x0_texture, g_SimplePool); + pane->ResetInterp(); + } + + x260_26_exitTextScroll = false; + UpdateBodyText(); +} + +int CLogBookScreen::NextSurroundingArticleIndex(int cur) const +{ + if (cur < x18_firstViewRightSel) + { + int tmp = x18_firstViewRightSel + (x18_firstViewRightSel - cur + 6); + if (tmp >= x1f0_curViewScans.size()) + return cur - 1; + else + return tmp; + } + + if (cur < x18_firstViewRightSel + 6) + { + if (cur + 1 < x1f0_curViewScans.size()) + return cur + 1; + if (x18_firstViewRightSel == 0) + return -1; + return x18_firstViewRightSel - 1; + } + + int tmp = x18_firstViewRightSel - (cur - (x18_firstViewRightSel + 5)); + if (tmp >= 0) + return tmp; + + if (cur >= x1f0_curViewScans.size() - 1) + return -1; + return cur + 1; } bool CLogBookScreen::IsArtifactCategorySelected() const @@ -35,6 +285,122 @@ bool CLogBookScreen::IsArtifactCategorySelected() const return x70_tablegroup_leftlog->GetUserSelection() == 4; } +int CLogBookScreen::GetSelectedArtifactHeadScanIndex() const +{ + auto& category = x19c_scanCompletes[x70_tablegroup_leftlog->GetUserSelection()]; + if (x1c_rightSel < category.size()) + return CArtifactDoll::GetArtifactHeadScanIndex(category[x1c_rightSel].first); + return -1; +} + +bool CLogBookScreen::InputDisabled() const +{ + return x25c_leavePauseState == ELeavePauseState::LeavingPause; +} + +void CLogBookScreen::TransitioningAway() +{ + x25c_leavePauseState = ELeavePauseState::LeavingPause; +} + +void CLogBookScreen::Update(float dt, CRandom16& rand, CArchitectureQueue& archQueue) +{ + CPauseScreenBase::Update(dt, rand, archQueue); + x258_artifactDoll->Update(dt, x4_mgr); + PumpArticleLoad(); + + if (x10_mode == EMode::TextScroll) + { + if (x260_25_inTextScroll) + x254_viewInterp = std::min(x254_viewInterp + 4.f * dt, 1.f); + else + x254_viewInterp = std::max(0.f, x254_viewInterp - 4.f * dt); + + zeus::CColor color(1.f, x254_viewInterp); + x74_basewidget_leftguages->SetColor(color); + x88_basewidget_rightguages->SetColor(color); + + zeus::CColor invColor(1.f, 1.f - x254_viewInterp); + x70_tablegroup_leftlog->SetColor(invColor); + x84_tablegroup_rightlog->SetColor(invColor); + x17c_model_textalpha->SetColor(invColor); + x174_textpane_body->SetColor(invColor); + + for (CAuiImagePane* pane : xf0_imagePanes) + pane->SetInverseAlpha(1.f - x254_viewInterp); + + if (x254_viewInterp == 0.f && x25c_leavePauseState == ELeavePauseState::InPause) + ChangeMode(EMode::RightTable); + } + + if (x25c_leavePauseState == ELeavePauseState::LeavingPause && x254_viewInterp == 0.f) + x25c_leavePauseState = ELeavePauseState::LeftPause; +} + +void CLogBookScreen::Touch() +{ + CPauseScreenBase::Touch(); + x258_artifactDoll->Touch(); +} + +void CLogBookScreen::ProcessControllerInput(const CFinalInput& input) +{ + x260_25_inTextScroll = false; + if (x25c_leavePauseState == ELeavePauseState::LeftPause) + return; + + if (x10_mode == EMode::TextScroll) + { + int oldPage = x174_textpane_body->TextSupport()->GetPageCounter(); + int newPage = oldPage; + int pageCount = x174_textpane_body->TextSupport()->GetTotalPageCount(); + bool lastPage = (pageCount - 1) == oldPage; + if (pageCount != -1) + { + if (input.PLAUp()) + newPage = std::max(oldPage - 1, 0); + else if (input.PLADown() || (input.PA() && !lastPage)) + newPage = std::min(oldPage + 1, pageCount - 1); + x174_textpane_body->TextSupport()->SetPage(newPage); + if (oldPage != newPage) + CSfxManager::SfxStart(1444, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + x198_28_pulseTextArrowTop = newPage > 1; + x198_29_pulseTextArrowBottom = !lastPage; + } + else + { + x198_29_pulseTextArrowBottom = false; + x198_28_pulseTextArrowTop = false; + } + + if (!x260_26_exitTextScroll) + x260_26_exitTextScroll = input.PB() || (input.PA() && lastPage); + + if (g_tweakGui->GetLatchArticleText()) + x260_25_inTextScroll = !x260_26_exitTextScroll; + else + x260_25_inTextScroll = input.DA(); + } + else + { + x198_29_pulseTextArrowBottom = false; + x198_28_pulseTextArrowTop = false; + } + + if (x25c_leavePauseState == ELeavePauseState::LeavingPause) + x260_25_inTextScroll = false; + + CPauseScreenBase::ProcessControllerInput(input); +} + +void CLogBookScreen::Draw(float transInterp, float totalAlpha, float yOff) +{ + CPauseScreenBase::Draw(transInterp, totalAlpha, yOff); + bool artifactSel = x10_mode == EMode::RightTable && IsArtifactCategorySelected(); + x258_artifactDoll->Draw(transInterp * (1.f - x254_viewInterp), x4_mgr, artifactSel, + GetSelectedArtifactHeadScanIndex()); +} + bool CLogBookScreen::VReady() const { return true; @@ -42,12 +408,79 @@ bool CLogBookScreen::VReady() const void CLogBookScreen::VActivate() { + for (int i=0 ; i<5 ; ++i) + { + if (IsScanCategoryReady(CSaveWorld::EScanCategory(i + 1))) + { + xa8_textpane_categories[i]->TextSupport()->SetText(xc_pauseStrg.GetString(i + 1)); + } + else + { + xa8_textpane_categories[i]->TextSupport()->SetText(u"??????"); + x70_tablegroup_leftlog->GetWorkerWidget(i)->SetIsSelectable(false); + } + } + x178_textpane_title->TextSupport()->SetText(xc_pauseStrg.GetString(0)); + + for (int i=0 ; i<5 ; ++i) + x70_tablegroup_leftlog->GetWorkerWidget(i)->SetIsSelectable(false); +} + +void CLogBookScreen::RightTableSelectionChanged(int selBegin, int selEnd) +{ + UpdateRightTitles(); +} + +void CLogBookScreen::ChangedMode(EMode oldMode) +{ + if (oldMode == EMode::TextScroll) + { + x74_basewidget_leftguages->SetVisibility(false, ETraversalMode::Children); + x88_basewidget_rightguages->SetVisibility(false, ETraversalMode::Children); + UpdateBodyText(); + x174_textpane_body->TextSupport()->SetPage(0); + } + else if (x10_mode == EMode::TextScroll) + { + x74_basewidget_leftguages->SetVisibility(true, ETraversalMode::Children); + x88_basewidget_rightguages->SetVisibility(true, ETraversalMode::Children); + x260_25_inTextScroll = true; + UpdateBodyImagesAndText(); + } +} + +void CLogBookScreen::UpdateRightTable() +{ + CPauseScreenBase::UpdateRightTable(); + x1f0_curViewScans.clear(); + std::vector>& category = x19c_scanCompletes[x70_tablegroup_leftlog->GetUserSelection()]; + x1f0_curViewScans.reserve(category.size()); + for (std::pair& scan : category) + x1f0_curViewScans.push_back(std::make_pair(g_SimplePool->GetObj({FOURCC('SCAN'), scan.first}), + TLockedToken{})); + + PumpArticleLoad(); + UpdateRightTitles(); +} + +bool CLogBookScreen::ShouldLeftTableAdvance() const +{ + if (!x260_24_loaded || x1f0_curViewScans.empty()) + return false; + return IsScanCategoryReady(CSaveWorld::EScanCategory(x70_tablegroup_leftlog->GetUserSelection() + 1)); +} + +bool CLogBookScreen::ShouldRightTableAdvance() const +{ + const std::pair, + TLockedToken>& scan = x1f0_curViewScans[x1c_rightSel]; + return scan.first.IsLoaded() && scan.second.IsLoaded(); } u32 CLogBookScreen::GetRightTableCount() const { - return 0; + return x1f0_curViewScans.size(); } } diff --git a/Runtime/MP1/CLogBookScreen.hpp b/Runtime/MP1/CLogBookScreen.hpp index f814068b2..7ae0bf4d5 100644 --- a/Runtime/MP1/CLogBookScreen.hpp +++ b/Runtime/MP1/CLogBookScreen.hpp @@ -12,33 +12,62 @@ namespace MP1 class CLogBookScreen : public CPauseScreenBase { - rstl::reserved_vector, 5> x19c_; - std::vector x1f0_; - rstl::reserved_vector, 5> x200_; - float x254_ = 0.f; + rstl::reserved_vector>, 5> x19c_scanCompletes; + std::vector, + TCachedToken>> x1f0_curViewScans; + rstl::reserved_vector, + TLockedToken>>, 5> x200_viewScans; + float x254_viewInterp = 0.f; std::unique_ptr x258_artifactDoll; - u32 x25c_ = 0; + + enum class ELeavePauseState + { + InPause = 0, + LeavingPause = 1, + LeftPause = 2 + }; + + ELeavePauseState x25c_leavePauseState = ELeavePauseState::InPause; union { struct { - bool x260_24_ : 1; - bool x260_25_ : 1; - bool x260_26_ : 1; + bool x260_24_loaded : 1; + bool x260_25_inTextScroll : 1; + bool x260_26_exitTextScroll : 1; }; s32 _dummy = 0; }; void InitializeLogBook(); + void UpdateRightTitles(); + void PumpArticleLoad(); + bool IsScanCategoryReady(CSaveWorld::EScanCategory category) const; + void UpdateBodyText(); + void UpdateBodyImagesAndText(); + int NextSurroundingArticleIndex(int cur) const; + bool IsArtifactCategorySelected() const; + int GetSelectedArtifactHeadScanIndex() const; + static bool IsScanComplete(CSaveWorld::EScanCategory category, ResId scan, const CPlayerState& playerState); public: CLogBookScreen(const CStateManager& mgr, CGuiFrame& frame, const CStringTable& pauseStrg); ~CLogBookScreen(); - bool IsArtifactCategorySelected() const; + bool InputDisabled() const; + void TransitioningAway(); + void Update(float dt, CRandom16& rand, CArchitectureQueue& archQueue); + void Touch(); + void ProcessControllerInput(const CFinalInput& input); + void Draw(float transInterp, float totalAlpha, float yOff); bool VReady() const; void VActivate(); + void RightTableSelectionChanged(int selBegin, int selEnd); + void ChangedMode(EMode oldMode); + void UpdateRightTable(); + bool ShouldLeftTableAdvance() const; + bool ShouldRightTableAdvance() const; u32 GetRightTableCount() const; }; diff --git a/Runtime/MP1/COptionsScreen.cpp b/Runtime/MP1/COptionsScreen.cpp index 23ad2c464..ae003cc06 100644 --- a/Runtime/MP1/COptionsScreen.cpp +++ b/Runtime/MP1/COptionsScreen.cpp @@ -232,7 +232,7 @@ void COptionsScreen::RightTableSelectionChanged(int selBegin, int selEnd) UpdateOptionView(); } -void COptionsScreen::ChangedMode() +void COptionsScreen::ChangedMode(EMode oldMode) { if (x10_mode == EMode::RightTable) { diff --git a/Runtime/MP1/COptionsScreen.hpp b/Runtime/MP1/COptionsScreen.hpp index 459fdf06d..dc5ad4fef 100644 --- a/Runtime/MP1/COptionsScreen.hpp +++ b/Runtime/MP1/COptionsScreen.hpp @@ -37,7 +37,7 @@ public: bool VReady() const; void VActivate(); void RightTableSelectionChanged(int selBegin, int selEnd); - void ChangedMode(); + void ChangedMode(EMode oldMode); void UpdateRightTable(); bool ShouldLeftTableAdvance() const; bool ShouldRightTableAdvance() const; diff --git a/Runtime/MP1/CPauseScreenBase.cpp b/Runtime/MP1/CPauseScreenBase.cpp index 9d9ca9b03..81b73ba9c 100644 --- a/Runtime/MP1/CPauseScreenBase.cpp +++ b/Runtime/MP1/CPauseScreenBase.cpp @@ -211,7 +211,7 @@ void CPauseScreenBase::ChangeMode(EMode mode) default: break; } - ChangedMode(); + ChangedMode(oldMode); } void CPauseScreenBase::UpdateSideTable(CGuiTableGroup* table) diff --git a/Runtime/MP1/CPauseScreenBase.hpp b/Runtime/MP1/CPauseScreenBase.hpp index d67f2933e..357e08850 100644 --- a/Runtime/MP1/CPauseScreenBase.hpp +++ b/Runtime/MP1/CPauseScreenBase.hpp @@ -122,7 +122,7 @@ public: virtual bool VReady() const=0; virtual void VActivate()=0; virtual void RightTableSelectionChanged(int selBegin, int selEnd) {} - virtual void ChangedMode() {} + virtual void ChangedMode(EMode oldMode) {} virtual void UpdateRightTable(); virtual bool ShouldLeftTableAdvance() const { return true; } virtual bool ShouldRightTableAdvance() const { return true; }