SceneSerializationHandler.cpp 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <AzCore/Debug/Profiler.h>
  9. #include <AzCore/IO/Path/Path.h>
  10. #include <AzCore/IO/SystemFile.h>
  11. #include <AzCore/std/algorithm.h>
  12. #include <AzCore/std/string/conversions.h>
  13. #include <AzCore/Settings/SettingsRegistryMergeUtils.h>
  14. #include <AzFramework/StringFunc/StringFunc.h>
  15. #include <AzToolsFramework/API/EditorAssetSystemAPI.h>
  16. #include <AzToolsFramework/Debug/TraceContext.h>
  17. #include <SceneAPI/SceneCore/Events/AssetImportRequest.h>
  18. #include <SceneAPI/SceneCore/Components/LoadingComponent.h>
  19. #include <SceneAPI/SceneCore/Utilities/Reporting.h>
  20. #include <SceneSerializationHandler.h>
  21. namespace AZ
  22. {
  23. SceneSerializationHandler::~SceneSerializationHandler()
  24. {
  25. Deactivate();
  26. }
  27. void SceneSerializationHandler::Activate()
  28. {
  29. BusConnect();
  30. }
  31. void SceneSerializationHandler::Deactivate()
  32. {
  33. BusDisconnect();
  34. }
  35. AZStd::shared_ptr<SceneAPI::Containers::Scene> SceneSerializationHandler::LoadScene(
  36. const AZStd::string& sceneFilePath,
  37. Uuid sceneSourceGuid,
  38. const AZStd::string& watchFolder)
  39. {
  40. AZ_PROFILE_FUNCTION(Editor);
  41. namespace Utilities = AZ::SceneAPI::Utilities;
  42. using AZ::SceneAPI::Events::AssetImportRequest;
  43. using namespace SceneAPI::SceneCore;
  44. CleanSceneMap();
  45. AZ_TraceContext("File", sceneFilePath.c_str());
  46. if (!IsValidExtension(sceneFilePath))
  47. {
  48. return nullptr;
  49. }
  50. AZ::IO::Path cleanPath(BuildCleanPathFromFilePath(sceneFilePath));
  51. auto sceneIt = m_scenes.find(cleanPath.Native());
  52. if (sceneIt != m_scenes.end())
  53. {
  54. AZStd::shared_ptr<SceneAPI::Containers::Scene> scene = sceneIt->second.lock();
  55. if (scene)
  56. {
  57. return scene;
  58. }
  59. // There's a small window in between which the scene was closed after searching for
  60. // it in the scene map. In this case continue and simply reload the scene.
  61. }
  62. if (!AZ::IO::SystemFile::Exists(cleanPath.c_str()))
  63. {
  64. AZ_TracePrintf(Utilities::ErrorWindow, "No file exists at given source path.");
  65. return nullptr;
  66. }
  67. if (sceneSourceGuid.IsNull())
  68. {
  69. bool result = false;
  70. AZ::Data::AssetInfo info;
  71. AZStd::string watchFolderFromDatabase;
  72. AzToolsFramework::AssetSystemRequestBus::BroadcastResult(result, &AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourcePath, cleanPath.c_str(), info, watchFolderFromDatabase);
  73. if (!result)
  74. {
  75. AZ_TracePrintf(Utilities::ErrorWindow, "Failed to retrieve file info needed to determine the uuid of the source file.");
  76. return nullptr;
  77. }
  78. sceneSourceGuid = info.m_assetId.m_guid;
  79. }
  80. AZStd::shared_ptr<SceneAPI::Containers::Scene> scene =
  81. AssetImportRequest::LoadSceneFromVerifiedPath(cleanPath.Native(), sceneSourceGuid, AssetImportRequest::RequestingApplication::Editor, LoadingComponent::TYPEINFO_Uuid(), watchFolder);
  82. if (!scene)
  83. {
  84. AZ_TracePrintf(Utilities::ErrorWindow, "Failed to load the requested scene.");
  85. return nullptr;
  86. }
  87. m_scenes.emplace(AZStd::move(cleanPath.Native()), scene);
  88. return scene;
  89. }
  90. bool SceneSerializationHandler::IsSceneCached(const AZStd::string& sceneFilePath)
  91. {
  92. if (!IsValidExtension(sceneFilePath))
  93. {
  94. return false;
  95. }
  96. AZ::IO::Path cleanPath(BuildCleanPathFromFilePath(sceneFilePath));
  97. CleanSceneMap();
  98. // There's a small window where all shared pointers might be released after cleaning the map
  99. // and before checking the list here, so this won't be 100% accurate, but it will still catch
  100. // cases where the scene is in use somewhere.
  101. return m_scenes.find(cleanPath.Native()) != m_scenes.end();
  102. }
  103. AZ::IO::Path SceneSerializationHandler::BuildCleanPathFromFilePath(const AZStd::string& filePath) const
  104. {
  105. AZ::IO::Path enginePath;
  106. if (auto* settingsRegistry = AZ::SettingsRegistry::Get())
  107. {
  108. settingsRegistry->Get(enginePath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_EngineRootFolder);
  109. }
  110. return((enginePath / filePath).LexicallyNormal());
  111. }
  112. bool SceneSerializationHandler::IsValidExtension(const AZStd::string& filePath) const
  113. {
  114. namespace Utilities = AZ::SceneAPI::Utilities;
  115. if (AZ::SceneAPI::Events::AssetImportRequest::IsManifestExtension(filePath.c_str()))
  116. {
  117. AZ_TracePrintf(Utilities::ErrorWindow, "Provided path contains the manifest path, not the path to the source file.");
  118. return false;
  119. }
  120. if (!AZ::SceneAPI::Events::AssetImportRequest::IsSceneFileExtension(filePath.c_str()))
  121. {
  122. AZ_TracePrintf(Utilities::ErrorWindow, "Provided path doesn't contain an extension supported by the SceneAPI.");
  123. return false;
  124. }
  125. return true;
  126. }
  127. void SceneSerializationHandler::CleanSceneMap()
  128. {
  129. for (auto it = m_scenes.begin(); it != m_scenes.end(); )
  130. {
  131. if (it->second.expired())
  132. {
  133. it = m_scenes.erase(it);
  134. }
  135. else
  136. {
  137. ++it;
  138. }
  139. }
  140. }
  141. } // namespace AZ