| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203 |
- /*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
- #include <AssetBuilderSDK/SerializationDependencies.h>
- #include <Common/AnyAssetBuilder.h>
- #include <AzCore/Component/ComponentApplicationBus.h>
- #include <AzCore/Serialization/Utils.h>
- #include <AzCore/std/smart_ptr/make_shared.h>
- #include <AzCore/std/algorithm.h>
- #include <AzFramework/IO/LocalFileIO.h>
- #include <AzFramework/StringFunc/StringFunc.h>
- #include <AzToolsFramework/API/EditorAssetSystemAPI.h>
- #include <AzCore/Serialization/Json/JsonUtils.h>
- #include <Atom/RPI.Edit/Common/ConvertibleSource.h>
- #include <Atom/RPI.Reflect/System/AnyAsset.h>
- namespace AZ
- {
- namespace RPI
- {
- namespace
- {
- [[maybe_unused]] const char* AnyAssetBuilderName = "AnyAssetBuilder";
- const char* AnyAssetBuilderJobKey = "Any Asset Builder";
- const char* AnyAssetBuilderDefaultExtension = "azasset";
- const char* AnyAssetSourceExtensions[] =
- {
- "azasset",
- "attimage",
- "azbuffer",
- };
- const uint32_t NumberOfSourceExtensions = AZ_ARRAY_SIZE(AnyAssetSourceExtensions);
- }
- void AnyAssetBuilder::RegisterBuilder()
- {
- // build source extension patterns
- AZStd::vector<AssetBuilderSDK::AssetBuilderPattern> patterns(NumberOfSourceExtensions);
- AZStd::for_each(patterns.begin(), patterns.end(), [&, index = 0](AssetBuilderSDK::AssetBuilderPattern& pattern) mutable
- {
- pattern = AssetBuilderSDK::AssetBuilderPattern(AZStd::string("*.") + AnyAssetSourceExtensions[index++], AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard);
- });
- // setup builder descriptor
- AssetBuilderSDK::AssetBuilderDesc builderDescriptor;
- builderDescriptor.m_name = AnyAssetBuilderJobKey;
- builderDescriptor.m_patterns.insert(builderDescriptor.m_patterns.end(), patterns.begin(), patterns.end());
- builderDescriptor.m_busId = azrtti_typeid<AnyAssetBuilder>();
- builderDescriptor.m_createJobFunction = AZStd::bind(&AnyAssetBuilder::CreateJobs, this,
- AZStd::placeholders::_1, AZStd::placeholders::_2);
- builderDescriptor.m_processJobFunction = AZStd::bind(&AnyAssetBuilder::ProcessJob, this,
- AZStd::placeholders::_1, AZStd::placeholders::_2);
- builderDescriptor.m_version = 10;
- BusConnect(builderDescriptor.m_busId);
- AssetBuilderSDK::AssetBuilderBus::Broadcast(&AssetBuilderSDK::AssetBuilderBusTraits::RegisterBuilderInformation, builderDescriptor);
- }
- AnyAssetBuilder::~AnyAssetBuilder()
- {
- BusDisconnect();
- }
-
- void AnyAssetBuilder::CreateJobs(const AssetBuilderSDK::CreateJobsRequest& request, AssetBuilderSDK::CreateJobsResponse& response)
- {
- if (m_isShuttingDown)
- {
- response.m_result = AssetBuilderSDK::CreateJobsResultCode::ShuttingDown;
- return;
- }
- for (const AssetBuilderSDK::PlatformInfo& platformInfo : request.m_enabledPlatforms)
- {
- AssetBuilderSDK::JobDescriptor descriptor;
- descriptor.m_jobKey = AnyAssetBuilderJobKey;
- descriptor.SetPlatformIdentifier(platformInfo.m_identifier.c_str());
- // [GFX TODO][ATOM-2830] Set 'm_critical' back to 'false' once proper fix for Atom startup issues are in
- descriptor.m_critical = true;
- response.m_createJobOutputs.push_back(descriptor);
- }
- response.m_result = AssetBuilderSDK::CreateJobsResultCode::Success;
- }
-
- void AnyAssetBuilder::ProcessJob(const AssetBuilderSDK::ProcessJobRequest& request, AssetBuilderSDK::ProcessJobResponse& response)
- {
- AssetBuilderSDK::JobCancelListener jobCancelListener(request.m_jobId);
- if (jobCancelListener.IsCancelled() || m_isShuttingDown)
- {
- response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Cancelled;
- return;
- }
- // Get serialization context
- SerializeContext* context = nullptr;
- ComponentApplicationBus::BroadcastResult(context, &ComponentApplicationBus::Events::GetSerializeContext);
- if (!context)
- {
- AZ_Assert(false, "No serialize context");
- return;
- }
- Outcome<AZStd::any, AZStd::string> loadResult = AZ::JsonSerializationUtils::LoadAnyObjectFromFile(request.m_fullPath);
-
- if (!loadResult.IsSuccess())
- {
- AZ_Error(AnyAssetBuilderName, false, "Failed to load file [%s] as an any asset", request.m_fullPath.c_str());
- AZ_Error(AnyAssetBuilderName, false, "Loading issues: %s", loadResult.GetError().data());
- response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Failed;
- return ;
- }
- AZStd::any loadedClass = loadResult.GetValue();
- auto loadedClassId = loadedClass.get_type_info().m_id;
- void* loadedInstance = AZStd::any_cast<void>(&loadedClass);
-
- // Apply converter if the source data class is a ConvertibleSource
- bool isConvertible = false;
- context->EnumerateBase(
- [&isConvertible](const AZ::SerializeContext::ClassData* classData, AZ::Uuid)
- {
- if (classData && classData->m_typeId == ConvertibleSource::TYPEINFO_Uuid())
- {
- isConvertible = true;
- }
- return true;
- },
- loadedClassId);
- AZStd::shared_ptr<void> convertedData;
- TypeId outputTypeId = loadedClassId;
- void* outputData = loadedInstance;
-
- if (isConvertible)
- {
- const ConvertibleSource* convertible = reinterpret_cast<const ConvertibleSource*>(loadedInstance);
- // convert and save the converted data to outputData and its type id to outputTypeId
- bool converted = convertible->Convert(outputTypeId, convertedData);
- if (!converted)
- {
- AZ_Error(AnyAssetBuilderName, false, "Failed to convert asset [%s]", request.m_fullPath.c_str());
- response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Failed;
- return;
- }
- outputData = convertedData.get();
- }
-
- // Get file name from source file path, then replace the extension to generate product file name
- // Note that we preserve the file extension since it is used during reflection
- AZStd::string destFileName;
- AzFramework::StringFunc::Path::GetFullFileName(request.m_fullPath.c_str(), destFileName);
- // Construct product full path
- AZStd::string destPath;
- AzFramework::StringFunc::Path::ConstructFull(request.m_tempDirPath.c_str(), destFileName.c_str(), destPath, true);
-
- // Save the asset to binary format for production
- bool result = Utils::SaveObjectToFile(destPath, DataStream::ST_BINARY, outputData, outputTypeId, context);
- if (result == false)
- {
- AZ_Error(AnyAssetBuilderName, false, "Failed to save asset to %s", destPath.c_str());
- response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Failed;
- return;
- }
-
- // Success. Save output product(s) to response.
- // Note that we use the classId we found in the source file, unless it's a standard .azasset
- AZStd::string sourceFileExtension;
- AzFramework::StringFunc::Path::GetExtension(request.m_fullPath.c_str(), sourceFileExtension, false);
- auto destClassId = (sourceFileExtension == AnyAssetBuilderDefaultExtension) ? AnyAsset::RTTI_Type() : loadedClassId;
- AssetBuilderSDK::JobProduct jobProduct(destPath, destClassId, 0);
- if (AssetBuilderSDK::OutputObject(outputData, outputTypeId, destPath, destClassId, 0, jobProduct))
- {
- response.m_outputProducts.push_back(jobProduct);
- response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Success;
- }
- }
- void AnyAssetBuilder::ShutDown()
- {
- m_isShuttingDown = true;
- }
- } // namespace RPI_Builder
- } // namespace AZ
|