|
@@ -0,0 +1,137 @@
|
|
|
+/*
|
|
|
+ * 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 <SceneAPI/SceneBuilder/Importers/AssImpCustomPropertyImporter.h>
|
|
|
+#include <SceneAPI/SceneBuilder/Importers/AssImpImporterUtilities.h>
|
|
|
+
|
|
|
+#include <AzCore/std/smart_ptr/make_shared.h>
|
|
|
+#include <AzCore/Serialization/SerializeContext.h>
|
|
|
+#include <AzToolsFramework/Debug/TraceContext.h>
|
|
|
+#include <SceneAPI/SceneBuilder/SceneSystem.h>
|
|
|
+#include <SceneAPI/SceneBuilder/Importers/ImporterUtilities.h>
|
|
|
+#include <SceneAPI/SceneBuilder/Importers/Utilities/RenamedNodesMap.h>
|
|
|
+#include <SceneAPI/SceneCore/Utilities/Reporting.h>
|
|
|
+#include <SceneAPI/SceneData/GraphData/CustomPropertyData.h>
|
|
|
+#include <SceneAPI/SDKWrapper/AssImpTypeConverter.h>
|
|
|
+#include <SceneAPI/SDKWrapper/AssImpNodeWrapper.h>
|
|
|
+#include <SceneAPI/SDKWrapper/AssImpSceneWrapper.h>
|
|
|
+#include <assimp/scene.h>
|
|
|
+
|
|
|
+namespace AZ::SceneAPI::SceneBuilder
|
|
|
+{
|
|
|
+ const char* s_customPropertiesNodeName = "custom_properties";
|
|
|
+
|
|
|
+ AssImpCustomPropertyImporter::AssImpCustomPropertyImporter()
|
|
|
+ {
|
|
|
+ BindToCall(&AssImpCustomPropertyImporter::ImportCustomProperty);
|
|
|
+ }
|
|
|
+
|
|
|
+ void AssImpCustomPropertyImporter::Reflect(ReflectContext* context)
|
|
|
+ {
|
|
|
+ SerializeContext* serializeContext = azrtti_cast<SerializeContext*>(context);
|
|
|
+ if (serializeContext)
|
|
|
+ {
|
|
|
+ serializeContext->Class<AssImpCustomPropertyImporter, SceneCore::LoadingComponent>()->Version(1);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ Events::ProcessingResult AssImpCustomPropertyImporter::ImportCustomProperty(AssImpSceneNodeAppendedContext& context)
|
|
|
+ {
|
|
|
+ AZ_TraceContext("Importer", "customProperty");
|
|
|
+ const aiNode* currentNode = context.m_sourceNode.GetAssImpNode();
|
|
|
+
|
|
|
+ if (!currentNode->mMetaData || currentNode->mMetaData->mNumProperties == 0)
|
|
|
+ {
|
|
|
+ return Events::ProcessingResult::Ignored;
|
|
|
+ }
|
|
|
+
|
|
|
+ AZ::SceneData::GraphData::CustomPropertyData::PropertyMap propertyMap;
|
|
|
+
|
|
|
+ for (size_t index = 0; index < currentNode->mMetaData->mNumProperties; ++index)
|
|
|
+ {
|
|
|
+ const aiString* key;
|
|
|
+ const aiMetadataEntry* data;
|
|
|
+ currentNode->mMetaData->Get(index, key, data);
|
|
|
+
|
|
|
+ AZStd::string_view currentNodeName(currentNode->mName.C_Str(), currentNode->mName.length);
|
|
|
+ AZStd::string_view keyName(key->C_Str(), key->length);
|
|
|
+
|
|
|
+ if (data->mType == AI_AISTRING)
|
|
|
+ {
|
|
|
+ const aiString* value = reinterpret_cast<const aiString*>(data->mData);
|
|
|
+ propertyMap[keyName] = AZStd::make_any<AZStd::string>(value->C_Str(), value->length);
|
|
|
+ }
|
|
|
+ else if (data->mType == AI_BOOL)
|
|
|
+ {
|
|
|
+ const bool* value = reinterpret_cast<const bool*>(data->mData);
|
|
|
+ propertyMap[keyName] = AZStd::make_any<bool>(aznumeric_cast<bool>(*value));
|
|
|
+ }
|
|
|
+ else if (data->mType == AI_INT32)
|
|
|
+ {
|
|
|
+ const int32_t* value = reinterpret_cast<const int32_t*>(data->mData);
|
|
|
+ propertyMap[keyName] = AZStd::make_any<AZ::s32>(aznumeric_cast<AZ::s32>(*value));
|
|
|
+ }
|
|
|
+ else if (data->mType == AI_UINT64)
|
|
|
+ {
|
|
|
+ const uint64_t* value = reinterpret_cast<const uint64_t*>(data->mData);
|
|
|
+ propertyMap[keyName] = AZStd::make_any<AZ::u64>(aznumeric_cast<AZ::u64>(*value));
|
|
|
+ }
|
|
|
+ else if (data->mType == AI_FLOAT)
|
|
|
+ {
|
|
|
+ const float* value = reinterpret_cast<const float*>(data->mData);
|
|
|
+ propertyMap[keyName] = AZStd::make_any<float>(aznumeric_cast<float>(*value));
|
|
|
+ }
|
|
|
+ else if (data->mType == AI_DOUBLE)
|
|
|
+ {
|
|
|
+ const double* value = reinterpret_cast<const double*>(data->mData);
|
|
|
+ propertyMap[keyName] = AZStd::make_any<double>(aznumeric_cast<double>(*value));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ auto customPropertyMapData = AZStd::make_shared<SceneData::GraphData::CustomPropertyData>(propertyMap);
|
|
|
+ if (!customPropertyMapData)
|
|
|
+ {
|
|
|
+ return Events::ProcessingResult::Failure;
|
|
|
+ }
|
|
|
+
|
|
|
+ // If it is non-endpoint data populated node, add a custom property node attribute
|
|
|
+ if (context.m_scene.GetGraph().HasNodeContent(context.m_currentGraphPosition))
|
|
|
+ {
|
|
|
+ if (!context.m_scene.GetGraph().IsNodeEndPoint(context.m_currentGraphPosition))
|
|
|
+ {
|
|
|
+ AZStd::string nodeName{ s_customPropertiesNodeName };
|
|
|
+ RenamedNodesMap::SanitizeNodeName(nodeName, context.m_scene.GetGraph(), context.m_currentGraphPosition);
|
|
|
+
|
|
|
+ auto newIndex = context.m_scene.GetGraph().AddChild(context.m_currentGraphPosition, nodeName.c_str());
|
|
|
+ AZ_Error(SceneAPI::Utilities::ErrorWindow, newIndex.IsValid(), "Failed to create SceneGraph node for attribute.");
|
|
|
+ if (!newIndex.IsValid())
|
|
|
+ {
|
|
|
+ return Events::ProcessingResult::Failure;
|
|
|
+ }
|
|
|
+
|
|
|
+ Events::ProcessingResult attributeResult;
|
|
|
+ AssImpSceneAttributeDataPopulatedContext dataPopulated(context, customPropertyMapData, newIndex, nodeName);
|
|
|
+ attributeResult = Events::Process(dataPopulated);
|
|
|
+
|
|
|
+ if (attributeResult != Events::ProcessingResult::Failure)
|
|
|
+ {
|
|
|
+ attributeResult = AddAttributeDataNodeWithContexts(dataPopulated);
|
|
|
+ }
|
|
|
+
|
|
|
+ return attributeResult;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ bool addedData = context.m_scene.GetGraph().SetContent(context.m_currentGraphPosition, customPropertyMapData);
|
|
|
+ AZ_Error(SceneAPI::Utilities::ErrorWindow, addedData, "Failed to add node data");
|
|
|
+ return addedData ? Events::ProcessingResult::Success : Events::ProcessingResult::Failure;
|
|
|
+ }
|
|
|
+
|
|
|
+ return Events::ProcessingResult::Ignored;
|
|
|
+ }
|
|
|
+}
|