Make version explorer wait on AP for dependent assets

Signed-off-by: carlitosan <82187351+carlitosan@users.noreply.github.com>
main^2^2
carlitosan 4 years ago
parent d8e5315199
commit d284d908b9

@ -281,7 +281,8 @@ namespace ScriptCanvasBuilder
}
else
{
if (AzFramework::StringFunc::Find(fileNameOnly, s_unitTestParseErrorPrefix) != AZStd::string::npos)
if (!ScriptCanvas::Grammar::g_processingErrorsForUnitTestsEnabled
&& AzFramework::StringFunc::Find(fileNameOnly, s_unitTestParseErrorPrefix) != AZStd::string::npos)
{
response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Success;
}

@ -190,7 +190,7 @@ namespace ScriptCanvasEditor
{
scriptCanvasSlot = eventHandler->GetSlot(slotId);
int& index = (scriptCanvasSlot->IsData() && scriptCanvasSlot->IsInput()) ? paramIndex : outputIndex;
int& index = (scriptCanvasSlot && scriptCanvasSlot->IsData() && scriptCanvasSlot->IsInput()) ? paramIndex : outputIndex;
if (scriptCanvasSlot && scriptCanvasSlot->IsVisible())
{

@ -1880,10 +1880,6 @@ namespace ScriptCanvasEditor
void MainWindow::OnFileOpen()
{
AZ::SerializeContext* serializeContext = nullptr;
EBUS_EVENT_RESULT(serializeContext, AZ::ComponentApplicationBus, GetSerializeContext);
AZ_Assert(serializeContext, "Failed to acquire application serialize context.");
AZStd::string assetRoot;
{
AZStd::array<char, AZ::IO::MaxPathLength> assetRootChar;
@ -1892,21 +1888,9 @@ namespace ScriptCanvasEditor
}
AZStd::string assetPath = AZStd::string::format("%s/scriptcanvas", assetRoot.c_str());
AZ::EBusAggregateResults<AZStd::vector<AZStd::string>> fileFilters;
AssetRegistryRequestBus::BroadcastResult(fileFilters, &AssetRegistryRequests::GetAssetHandlerFileFilters);
QString filter;
AZStd::set<AZStd::string> filterSet;
auto aggregateFilters = fileFilters.values;
for (auto aggregateFilters2 : fileFilters.values)
{
for (const AZStd::string& fileFilter : aggregateFilters2)
{
filterSet.insert(fileFilter);
}
}
AZStd::set<AZStd::string> filterSet { ".scriptcanvas" };
QStringList nameFilters;

@ -189,6 +189,11 @@ namespace ScriptCanvasEditor
OnButtonPressUpgradeImplementation(info);
}
void Controller::OnUpgradeDependencyWaitInterval([[maybe_unused]] const SourceHandle& info)
{
AddLogEntries();
}
void Controller::OnUpgradeModificationBegin([[maybe_unused]] const ModifyConfiguration& config, const SourceHandle& info)
{
for (auto* item : FindTableItems(info))

@ -93,9 +93,10 @@ namespace ScriptCanvasEditor
( const ModifyConfiguration& config
, const AZStd::vector<SourceHandle>& assets
, const AZStd::vector<size_t>& sortedOrder) override;
void OnUpgradeDependencyWaitInterval(const SourceHandle& info) override;
void OnUpgradeModificationBegin(const ModifyConfiguration& config, const SourceHandle& info) override;
void OnUpgradeModificationEnd(const ModifyConfiguration& config, const SourceHandle& info, ModificationResult result) override;
void SetLoggingPreferences();
void SetSpinnerIsBusy(bool isBusy);
void SetRowBusy(int index);

@ -22,6 +22,7 @@ namespace ScriptCanvasEditor
SourceHandle modifySingleAsset;
bool backupGraphBeforeModification = false;
bool successfulDependencyUpgradeRequired = true;
AZ::s32 perDependencyWaitSecondsMax = 20;
};
struct ModificationResult
@ -98,6 +99,7 @@ namespace ScriptCanvasEditor
( const ModifyConfiguration& config
, const AZStd::vector<SourceHandle>& assets
, const AZStd::vector<size_t>& sortedOrder) = 0;
virtual void OnUpgradeDependencyWaitInterval(const SourceHandle& info) = 0;
virtual void OnUpgradeModificationBegin(const ModifyConfiguration& config, const SourceHandle& info) = 0;
virtual void OnUpgradeModificationEnd(const ModifyConfiguration& config, const SourceHandle& info, ModificationResult result) = 0;
};

@ -30,38 +30,141 @@ namespace ScriptCanvasEditor
AZ_Assert(m_config.modification, "No modification function provided");
ModelNotificationsBus::Broadcast(&ModelNotificationsTraits::OnUpgradeBegin, modification, m_assets);
AZ::SystemTickBus::Handler::BusConnect();
AzFramework::AssetSystemInfoBus::Handler::BusConnect();
AzFramework::AssetSystemInfoBus::Handler::BusConnect();
m_result.asset = m_assets[GetCurrentIndex()];
}
size_t Modifier::GetCurrentIndex() const
Modifier::~Modifier()
{
return m_state == State::GatheringDependencies
? m_assetIndex
: m_dependencyOrderedAssetIndicies[m_assetIndex];
AzFramework::AssetSystemInfoBus::Handler::BusDisconnect();
AzFramework::AssetSystemInfoBus::Handler::BusDisconnect();
}
bool Modifier::AllDependenciesCleared(const AZStd::unordered_set<size_t>& dependencies) const
{
for (auto index : dependencies)
{
SourceHandle dependency = m_assets[index];
CompleteDescriptionInPlace(dependency);
if (dependency.Id().IsNull() || !m_assetsCompletedByAP.contains(dependency.Id()))
{
return false;
}
}
return true;
}
AZStd::unordered_set<size_t>& Modifier::GetOrCreateDependencyIndexSet()
bool Modifier::AnyDependenciesFailed(const AZStd::unordered_set<size_t>& dependencies) const
{
auto iter = m_dependencies.find(m_assetIndex);
if (iter == m_dependencies.end())
for (auto index : dependencies)
{
iter = m_dependencies.insert_or_assign(m_assetIndex, AZStd::unordered_set<size_t>()).first;
SourceHandle dependency = m_assets[index];
CompleteDescriptionInPlace(dependency);
if (dependency.Id().IsNull() || m_assetsFailedByAP.contains(dependency.Id()))
{
return true;
}
}
return iter->second;
return false;
}
const ModificationResults& Modifier::GetResult() const
AZStd::sys_time_t Modifier::CalculateRemainingWaitTime(const AZStd::unordered_set<size_t>& dependencies) const
{
return m_results;
auto maxSeconds = AZStd::chrono::seconds(dependencies.size() * m_config.perDependencyWaitSecondsMax);
auto waitedSeconds = AZStd::chrono::seconds(AZStd::chrono::system_clock::now() - m_waitTimeStamp);
return (maxSeconds - waitedSeconds).count();
}
void Modifier::SourceFileChanged(AZStd::string relativePath, [[maybe_unused]] AZStd::string scanFolder, [[maybe_unused]] AZ::Uuid fileAssetId)
{
AZ_TracePrintf("SC", "received SourceFileChanged: %s", relativePath.c_str());
VE_LOG("received SourceFileChanged: %s", relativePath.c_str());
}
void Modifier::SourceFileFailed(AZStd::string relativePath, [[maybe_unused]] AZStd::string scanFolder, [[maybe_unused]] AZ::Uuid fileAssetId)
{
AZ_TracePrintf("SC", "received SourceFileFailed: %s", relativePath.c_str());
VE_LOG("received SourceFileFailed: %s", relativePath.c_str());
}
void Modifier::ProcessNotifications()
{
AZStd::lock_guard<AZStd::recursive_mutex> lock(m_mutex);
for (const auto& assetPath : m_successNotifications)
{
VE_LOG("received AssetCompilationSuccess: %s", assetPath.c_str());
SourceHandle sourceHandle(nullptr, {}, assetPath.c_str());
CompleteDescriptionInPlace(sourceHandle);
if (m_attemptedAssets.contains(sourceHandle.Id()))
{
m_assetsCompletedByAP.insert(sourceHandle.Id());
}
}
m_successNotifications.clear();
for (const auto& assetPath : m_failureNotifications)
{
VE_LOG("received AssetCompilationFailed: %s", assetPath.c_str());
SourceHandle sourceHandle(nullptr, {}, assetPath.c_str());
CompleteDescriptionInPlace(sourceHandle);
if (m_attemptedAssets.contains(sourceHandle.Id()))
{
m_assetsFailedByAP.insert(sourceHandle.Id());
}
}
m_failureNotifications.clear();
}
void Modifier::AssetCompilationSuccess([[maybe_unused]] const AZStd::string& assetPath)
{
AZStd::lock_guard<AZStd::recursive_mutex> lock(m_mutex);
// test failure path m_successNotifications.insert(assetPath);
m_failureNotifications.insert(assetPath);
}
void Modifier::AssetCompilationFailed(const AZStd::string& assetPath)
{
AZStd::lock_guard<AZStd::recursive_mutex> lock(m_mutex);
m_failureNotifications.insert(assetPath);
}
void Modifier::CheckDependencies()
{
ModelNotificationsBus::Broadcast(&ModelNotificationsTraits::OnUpgradeModificationBegin, m_config, m_result.asset);
if (auto dependencies = GetDependencies(GetCurrentIndex()); dependencies != nullptr && !dependencies->empty())
{
VE_LOG
( "dependencies found for %s, update will wait for the AP to finish processing them"
, m_result.asset.Path().c_str());
m_waitTimeStamp = AZStd::chrono::system_clock::now();
m_waitLogTimeStamp = AZStd::chrono::system_clock::time_point{};
m_modifyState = ModifyState::WaitingForDependencyProcessing;
}
else
{
m_modifyState = ModifyState::StartModification;
}
}
void Modifier::GatherDependencies()
{
AZ::SerializeContext* serializeContext{};
AZ::ComponentApplicationBus::BroadcastResult(serializeContext, &AZ::ComponentApplicationBus::Events::GetSerializeContext);
AZ_Assert(serializeContext, "SerializeContext is required to enumerate dependent assets in the ScriptCanvas file");
LoadAsset();
bool anyFailures = false;
if (m_result.asset.Get() && m_result.asset.Mod()->GetGraphData())
@ -101,7 +204,7 @@ namespace ScriptCanvasEditor
, nullptr))
{
anyFailures = true;
VE_LOG("Modifier: ERROR - Failed to gather dependencies from graph data: %s"
VE_LOG("Modifier: ERROR - Failed to gather dependencies from graph data: %s"
, m_result.asset.Path().c_str())
}
}
@ -111,16 +214,40 @@ namespace ScriptCanvasEditor
VE_LOG("Modifier: ERROR - Failed to load asset %s for modification, even though it scanned properly"
, m_result.asset.Path().c_str());
}
ModelNotificationsBus::Broadcast
( &ModelNotificationsTraits::OnUpgradeDependenciesGathered
, m_result.asset
, anyFailures ? Result::Failure : Result::Success);
}
ReleaseCurrentAsset();
size_t Modifier::GetCurrentIndex() const
{
return m_state == State::GatheringDependencies
? m_assetIndex
: m_dependencyOrderedAssetIndicies[m_assetIndex];
}
// Flush asset database events to ensure no asset references are held by closures queued on Ebuses.
AZ::Data::AssetManager::Instance().DispatchEvents();
const AZStd::unordered_set<size_t>* Modifier::GetDependencies(size_t index) const
{
auto iter = m_dependencies.find(index);
return iter != m_dependencies.end() ? &iter->second : nullptr;
}
AZStd::unordered_set<size_t>& Modifier::GetOrCreateDependencyIndexSet()
{
auto iter = m_dependencies.find(m_assetIndex);
if (iter == m_dependencies.end())
{
iter = m_dependencies.insert_or_assign(m_assetIndex, AZStd::unordered_set<size_t>()).first;
}
return iter->second;
}
const ModificationResults& Modifier::GetResult() const
{
return m_results;
}
void Modifier::LoadAsset()
@ -144,7 +271,7 @@ namespace ScriptCanvasEditor
}
else if (m_result.asset.Describe() != result.asset.Describe())
{
ReportModificationError("Received modifiction complete notification for different result");
ReportModificationError("Received modification complete notification for different result");
}
else
{
@ -154,9 +281,6 @@ namespace ScriptCanvasEditor
void Modifier::ModifyCurrentAsset()
{
m_result = {};
m_result.asset = m_assets[GetCurrentIndex()];
ModelNotificationsBus::Broadcast(&ModelNotificationsTraits::OnUpgradeModificationBegin, m_config, m_result.asset);
LoadAsset();
if (m_result.asset.IsGraphValid())
@ -171,34 +295,55 @@ namespace ScriptCanvasEditor
}
}
void Modifier::ModifyNextAsset()
void Modifier::InitializeResult()
{
ModelNotificationsBus::Broadcast
( &ModelNotificationsTraits::OnUpgradeModificationEnd, m_config, m_result.asset, m_result);
m_result = {};
if (m_assetIndex != m_assets.size())
{
m_result.asset = m_assets[GetCurrentIndex()];
CompleteDescriptionInPlace(m_result.asset);
m_attemptedAssets.insert(m_result.asset.Id());
}
}
void Modifier::NextAsset()
{
++m_assetIndex;
InitializeResult();
}
void Modifier::NextModification()
{
ModelNotificationsBus::Broadcast( &ModelNotificationsTraits::OnUpgradeModificationEnd, m_config, m_result.asset, m_result);
ModificationNotificationsBus::Handler::BusDisconnect();
NextAsset();
m_fileSaveResult = {};
m_modifyState = ModifyState::Idle;
ReleaseCurrentAsset();
++m_assetIndex;
m_result = {};
}
void Modifier::ReleaseCurrentAsset()
{
m_result.asset = m_result.asset.Describe();
// Flush asset database events to ensure no asset references are held by closures queued on Ebuses.
AZ::Data::AssetManager::Instance().DispatchEvents();
}
void Modifier::ReportModificationError(AZStd::string_view report)
{
m_result.errorMessage = report;
m_results.m_failures.push_back({ m_result.asset.Describe(), report });
ModifyNextAsset();
m_assetsFailedByAP.insert(m_result.asset.Id());
NextModification();
}
void Modifier::ReportModificationSuccess()
{
m_result.asset = m_result.asset.Describe();
// \note DO NOT put asset into the m_assetsCompletedByAP here. That can only be done when the message is received by the AP
m_results.m_successes.push_back({ m_result.asset.Describe(), {} });
ModifyNextAsset();
AzFramework::AssetSystemRequestBus::Broadcast(
&AzFramework::AssetSystem::AssetSystemRequests::EscalateAssetByUuid, m_result.asset.Id());
NextModification();
}
void Modifier::ReportSaveResult()
@ -214,9 +359,6 @@ namespace ScriptCanvasEditor
{
ReportModificationError(m_fileSaveResult.fileSaveError);
}
m_fileSaveResult = {};
m_modifyState = ModifyState::Idle;
}
void Modifier::OnFileSaveComplete(const FileSaveResult& result)
@ -316,49 +458,87 @@ namespace ScriptCanvasEditor
m_assetIndex = 0;
m_state = State::ModifyingGraphs;
InitializeResult();
}
else
{
GatherDependencies();
ReleaseCurrentAsset();
++m_assetIndex;
NextAsset();
}
}
void Modifier::TickUpdateGraph()
{
if (m_assetIndex == m_assets.size())
AZStd::lock_guard<AZStd::recursive_mutex> lock(m_mutex);
switch (m_modifyState)
{
VE_LOG("Modifier: Complete.");
AZ::SystemTickBus::Handler::BusDisconnect();
case ScriptCanvasEditor::VersionExplorer::Modifier::ModifyState::Idle:
if (m_assetIndex == m_assets.size())
{
VE_LOG("Modifier: Complete.");
AZ::SystemTickBus::Handler::BusDisconnect();
if (m_onComplete)
if (m_onComplete)
{
m_onComplete();
}
}
else
{
m_onComplete();
CheckDependencies();
}
break;
case ScriptCanvasEditor::VersionExplorer::Modifier::ModifyState::WaitingForDependencyProcessing:
WaitForDependencies();
break;
case ScriptCanvasEditor::VersionExplorer::Modifier::ModifyState::StartModification:
ModifyCurrentAsset();
break;
case ScriptCanvasEditor::VersionExplorer::Modifier::ModifyState::ReportResult:
ReportSaveResult();
break;
default:
break;
}
else
}
void Modifier::WaitForDependencies()
{
const AZ::s32 LogPeriodSeconds = 5;
ProcessNotifications();
auto dependencies = GetDependencies(GetCurrentIndex());
if (dependencies == nullptr || dependencies->empty() || AllDependenciesCleared(*dependencies))
{
m_modifyState = ModifyState::StartModification;
}
else if (AnyDependenciesFailed(*dependencies))
{
ReportModificationError("A required dependency failed to update, graph cannot update.");
}
else if (AZStd::chrono::seconds(CalculateRemainingWaitTime(*dependencies)).count() < 0)
{
ReportModificationError("Dependency update time has taken too long, aborting modification.");
}
else if (AZStd::chrono::seconds(AZStd::chrono::system_clock::now() - m_waitLogTimeStamp).count() > LogPeriodSeconds)
{
AZStd::lock_guard<AZStd::recursive_mutex> lock(m_mutex);
m_waitLogTimeStamp = AZStd::chrono::system_clock::now();
switch (m_modifyState)
{
case ScriptCanvasEditor::VersionExplorer::Modifier::ModifyState::Idle:
ModifyCurrentAsset();
break;
case ScriptCanvasEditor::VersionExplorer::Modifier::ModifyState::ReportResult:
ReportSaveResult();
break;
default:
break;
}
AZ_TracePrintf
( ScriptCanvas::k_VersionExplorerWindow.data()
, "Waiting for dependencies for %d more seconds: %s"
, AZStd::chrono::seconds(CalculateRemainingWaitTime(*dependencies)).count()
, m_result.asset.Path().c_str());
ModelNotificationsBus::Broadcast(&ModelNotificationsTraits::OnUpgradeDependencyWaitInterval, m_result.asset);
}
}
const AZStd::unordered_set<size_t>* Modifier::Sorter::GetDependencies(size_t index) const
{
auto iter = modifier->m_dependencies.find(index);
return iter != modifier->m_dependencies.end() ? &iter->second : nullptr;
return modifier->GetDependencies(index);
}
void Modifier::Sorter::Sort()
@ -379,7 +559,7 @@ namespace ScriptCanvasEditor
if (markedTemporary.contains(index))
{
AZ_Error
(ScriptCanvas::k_VersionExplorerWindow.data()
( ScriptCanvas::k_VersionExplorerWindow.data()
, false
, "Modifier: Dependency sort has failed during, circular dependency detected for Asset: %s"
, modifier->m_result.asset.Path().c_str());

@ -9,17 +9,23 @@
#pragma once
#include <AzCore/Component/TickBus.h>
#include <AzFramework/Asset/AssetSystemBus.h>
#include <Editor/View/Windows/Tools/UpgradeTool/FileSaver.h>
#include <Editor/View/Windows/Tools/UpgradeTool/ModelTraits.h>
#include <ScriptCanvas/Core/Core.h>
// probably not needed if using the asset system bus
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
namespace ScriptCanvasEditor
{
namespace VersionExplorer
{
class Modifier
: private AZ::SystemTickBus::Handler
, private ModificationNotificationsBus::Handler
class Modifier final
: public AZ::SystemTickBus::Handler
, public ModificationNotificationsBus::Handler
, public AzToolsFramework::AssetSystemBus::Handler
, public AzFramework::AssetSystemInfoBus::Handler
{
public:
AZ_CLASS_ALLOCATOR(Modifier, AZ::SystemAllocator, 0);
@ -29,6 +35,8 @@ namespace ScriptCanvasEditor
, AZStd::vector<SourceHandle>&& assets
, AZStd::function<void()> onComplete);
virtual ~Modifier();
const ModificationResults& GetResult() const;
ModificationResults&& TakeResult();
@ -56,6 +64,8 @@ namespace ScriptCanvasEditor
enum class ModifyState
{
Idle,
WaitingForDependencyProcessing,
StartModification,
InProgress,
Saving,
ReportResult
@ -82,13 +92,27 @@ namespace ScriptCanvasEditor
ModificationResults m_results;
AZStd::unique_ptr<FileSaver> m_fileSaver;
FileSaveResult m_fileSaveResult;
AZStd::unordered_set<AZ::Uuid> m_attemptedAssets;
AZStd::unordered_set<AZ::Uuid> m_assetsCompletedByAP;
AZStd::unordered_set<AZ::Uuid> m_assetsFailedByAP;
AZStd::chrono::system_clock::time_point m_waitLogTimeStamp;
AZStd::chrono::system_clock::time_point m_waitTimeStamp;
AZStd::unordered_set<AZStd::string> m_successNotifications;
AZStd::unordered_set<AZStd::string> m_failureNotifications;
size_t GetCurrentIndex() const;
bool AllDependenciesCleared(const AZStd::unordered_set<size_t>& dependencies) const;
bool AnyDependenciesFailed(const AZStd::unordered_set<size_t>& dependencies) const;
AZStd::sys_time_t CalculateRemainingWaitTime(const AZStd::unordered_set<size_t>& dependencies) const;
void CheckDependencies();
void GatherDependencies();
size_t GetCurrentIndex() const;
const AZStd::unordered_set<size_t>* GetDependencies(size_t index) const;
AZStd::unordered_set<size_t>& GetOrCreateDependencyIndexSet();
void InitializeResult();
void LoadAsset();
void ModifyCurrentAsset();
void ModifyNextAsset();
void NextAsset();
void NextModification();
void ModificationComplete(const ModificationResult& result) override;
void ReleaseCurrentAsset();
void ReportModificationError(AZStd::string_view report);
@ -96,10 +120,20 @@ namespace ScriptCanvasEditor
void ReportSaveResult();
void SaveModifiedGraph(const ModificationResult& result);
void SortGraphsByDependencies();
/// use all this to track the success of dependencies
void SourceFileChanged(AZStd::string relativePath, AZStd::string scanFolder, AZ::Uuid fileAssetId) override;
void SourceFileFailed(AZStd::string relativePath, AZStd::string scanFolder, AZ::Uuid fileAssetId) override;
void AssetCompilationSuccess(const AZStd::string& assetPath) override;
void AssetCompilationFailed(const AZStd::string& assetPath) override;
void ProcessNotifications();
void OnFileSaveComplete(const FileSaveResult& result);
void OnSystemTick() override;
void TickGatherDependencies();
void TickUpdateGraph();
void WaitForDependencies();
};
}
}

@ -81,7 +81,9 @@ namespace ScriptCanvasEditor
void Scanner::FilterAsset(SourceHandle asset)
{
if (m_config.filter && m_config.filter(asset) == ScanConfiguration::Filter::Exclude)
AZStd::string name = asset.Path().c_str();
if ((m_config.filter && m_config.filter(asset) == ScanConfiguration::Filter::Exclude) || !name.contains("LY_SC_UnitTest_FunctionContainer"))
{
VE_LOG("Scanner: Excluded: %s ", ModCurrentAsset().Path().c_str());
m_result.m_filteredAssets.push_back(ModCurrentAsset().Describe());

@ -15,6 +15,7 @@ namespace ScriptCanvas
AZ_CVAR(bool, g_disableParseOnGraphValidation, false, {}, AZ::ConsoleFunctorFlags::Null, "In case parsing the graph is interfering with opening a graph, disable parsing on validation");
AZ_CVAR(bool, g_printAbstractCodeModel, true, {}, AZ::ConsoleFunctorFlags::Null, "Print out the Abstract Code Model at the end of parsing for debug purposes.");
AZ_CVAR(bool, g_printAbstractCodeModelAtPrefabTime, false, {}, AZ::ConsoleFunctorFlags::Null, "Print out the Abstract Code Model at the end of parsing (at prefab time) for debug purposes.");
AZ_CVAR(bool, g_processingErrorsForUnitTestsEnabled, false, {}, AZ::ConsoleFunctorFlags::Null, "Enable AP processing errors on parse failure for unit tests.");
AZ_CVAR(bool, g_saveRawTranslationOuputToFile, true, {}, AZ::ConsoleFunctorFlags::Null, "Save out the raw result of translation for debug purposes.");
AZ_CVAR(bool, g_saveRawTranslationOuputToFileAtPrefabTime, false, {}, AZ::ConsoleFunctorFlags::Null, "Save out the raw result of translation (at prefab time) for debug purposes.");

@ -245,6 +245,7 @@ namespace ScriptCanvas
AZ_CVAR_EXTERNED(bool, g_disableParseOnGraphValidation);
AZ_CVAR_EXTERNED(bool, g_printAbstractCodeModel);
AZ_CVAR_EXTERNED(bool, g_printAbstractCodeModelAtPrefabTime);
AZ_CVAR_EXTERNED(bool, g_processingErrorsForUnitTestsEnabled);
AZ_CVAR_EXTERNED(bool, g_saveRawTranslationOuputToFile);
AZ_CVAR_EXTERNED(bool, g_saveRawTranslationOuputToFileAtPrefabTime);

Loading…
Cancel
Save