1 // Copyright 2001-2018 Crytek GmbH / Crytek Group. All rights reserved.
4 #include "DependencyTracker.h"
5 #include "AssetManager.h"
7 namespace Private_DependencyTracker
12 bool operator()(const std::pair
<string
, SAssetDependencyInfo
>& a
, const string
& b
)
14 return stricmp(a
.first
.c_str(), b
.c_str()) < 0;
17 bool operator()(const string
& a
, const std::pair
<string
, SAssetDependencyInfo
>& b
)
19 return stricmp(a
.c_str(), b
.first
.c_str()) < 0;
25 bool operator()(const std::pair
<string
, SAssetDependencyInfo
>& a
, const string
& b
)
27 return stricmp(a
.second
.path
.c_str(), b
.c_str()) < 0;
30 bool operator()(const string
& a
, const std::pair
<string
, SAssetDependencyInfo
>& b
)
32 return stricmp(a
.c_str(), b
.second
.path
.c_str()) < 0;
39 CDependencyTracker::CDependencyTracker()
41 CAssetManager
* pAssetManager
= CAssetManager::GetInstance();
43 pAssetManager
->signalAfterAssetsInserted
.Connect([this](const std::vector
<CAsset
*>&)
48 pAssetManager
->signalAfterAssetsUpdated
.Connect([this]()
53 pAssetManager
->signalAssetChanged
.Connect([this](CAsset
&)
58 pAssetManager
->signalAfterAssetsRemoved
.Connect([this]()
64 CDependencyTracker::~CDependencyTracker()
66 CAssetManager
* pAssetManager
= CAssetManager::GetInstance();
67 pAssetManager
->signalAfterAssetsInserted
.DisconnectById((uintptr_t)this);
68 pAssetManager
->signalAfterAssetsUpdated
.DisconnectById((uintptr_t)this);
69 pAssetManager
->signalAssetChanged
.DisconnectById((uintptr_t)this);
70 pAssetManager
->signalAfterAssetsRemoved
.DisconnectById((uintptr_t)this);
73 std::vector
<SAssetDependencyInfo
> CDependencyTracker::GetReverseDependencies(const char* szAssetPath
) const
75 const auto range
= GetRange(szAssetPath
);
77 std::vector
<SAssetDependencyInfo
> dependencies
;
78 dependencies
.reserve(3); // just an empirical expectation.
80 std::transform(range
.first
, range
.second
, std::back_inserter(dependencies
), [](const auto& x
)
88 std::pair
<bool, int> CDependencyTracker::IsAssetUsedBy(const char* szAssetPath
, const char* szAnotherAssetPath
) const
90 using namespace Private_DependencyTracker
;
92 const auto range
= GetRange(szAssetPath
);
93 if (range
.first
== range
.second
)
98 const string value
= PathUtil::ToUnixPath(szAnotherAssetPath
);
99 const auto lowerBound
= std::lower_bound(range
.first
, range
.second
, value
, SLessValue());
100 if (lowerBound
!= range
.second
&& (*lowerBound
).second
.path
.CompareNoCase(value
) == 0)
102 return { true, (*lowerBound
).second
.usageCount
};
108 void CDependencyTracker::CreateIndex()
110 // Do nothing if the future has already referred to the deffered request.
111 if (m_future
.valid() && m_future
.wait_for(std::chrono::seconds(0)) != std::future_status::ready
)
116 m_future
= std::async(std::launch::deferred
, [this]()
119 CAssetManager
* pAssetManager
= CAssetManager::GetInstance();
120 pAssetManager
->ForeachAsset([this](CAsset
* pAsset
)
122 MAKE_SURE(pAsset
->GetFilesCount(), return);
124 const std::vector
<SAssetDependencyInfo
>& dependencies
= pAsset
->GetDependencies();
125 for (const auto& item
: dependencies
)
127 m_index
.emplace_back(item
.path
, SAssetDependencyInfo( pAsset
->GetFile(0), item
.usageCount
));
131 std::sort(m_index
.begin(), m_index
.end(), [](const auto& a
, const auto& b
)
133 const int first
= stricmp(a
.first
.c_str(), b
.first
.c_str());
139 return stricmp(a
.second
.path
.c_str(), b
.second
.path
.c_str()) < 0;
144 std::pair
<CDependencyTracker::IndexIterator
, CDependencyTracker::IndexIterator
> CDependencyTracker::GetRange(const char* szAssetPath
) const
146 using namespace Private_DependencyTracker
;
148 if (m_future
.valid())
153 const string key
= PathUtil::ToUnixPath(szAssetPath
);
154 const auto lowerBound
= std::lower_bound(m_index
.cbegin(), m_index
.cend(), key
, SLessKey());
155 const auto upperBound
= std::upper_bound(lowerBound
, m_index
.cend(), key
, SLessKey());
156 return { lowerBound
, upperBound
};