AssImpCustomPropertyImporter.cpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  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 <SceneAPI/SceneBuilder/Importers/AssImpCustomPropertyImporter.h>
  9. #include <SceneAPI/SceneBuilder/Importers/AssImpImporterUtilities.h>
  10. #include <AzCore/std/smart_ptr/make_shared.h>
  11. #include <AzCore/Serialization/SerializeContext.h>
  12. #include <AzToolsFramework/Debug/TraceContext.h>
  13. #include <SceneAPI/SceneBuilder/SceneSystem.h>
  14. #include <SceneAPI/SceneBuilder/Importers/ImporterUtilities.h>
  15. #include <SceneAPI/SceneBuilder/Importers/Utilities/RenamedNodesMap.h>
  16. #include <SceneAPI/SceneCore/Utilities/Reporting.h>
  17. #include <SceneAPI/SceneData/GraphData/CustomPropertyData.h>
  18. #include <SceneAPI/SDKWrapper/AssImpTypeConverter.h>
  19. #include <SceneAPI/SDKWrapper/AssImpNodeWrapper.h>
  20. #include <SceneAPI/SDKWrapper/AssImpSceneWrapper.h>
  21. #include <assimp/scene.h>
  22. namespace AZ::SceneAPI::SceneBuilder
  23. {
  24. const char* s_customPropertiesNodeName = "custom_properties";
  25. AssImpCustomPropertyImporter::AssImpCustomPropertyImporter()
  26. {
  27. BindToCall(&AssImpCustomPropertyImporter::ImportCustomProperty);
  28. }
  29. void AssImpCustomPropertyImporter::Reflect(ReflectContext* context)
  30. {
  31. SerializeContext* serializeContext = azrtti_cast<SerializeContext*>(context);
  32. if (serializeContext)
  33. {
  34. serializeContext->Class<AssImpCustomPropertyImporter, SceneCore::LoadingComponent>()->Version(1);
  35. }
  36. }
  37. Events::ProcessingResult AssImpCustomPropertyImporter::ImportCustomProperty(AssImpSceneNodeAppendedContext& context)
  38. {
  39. AZ_TraceContext("Importer", "customProperty");
  40. const aiNode* currentNode = context.m_sourceNode.GetAssImpNode();
  41. if (!currentNode->mMetaData || currentNode->mMetaData->mNumProperties == 0)
  42. {
  43. return Events::ProcessingResult::Ignored;
  44. }
  45. AZ::SceneData::GraphData::CustomPropertyData::PropertyMap propertyMap;
  46. for (size_t index = 0; index < currentNode->mMetaData->mNumProperties; ++index)
  47. {
  48. const aiString* key;
  49. const aiMetadataEntry* data;
  50. currentNode->mMetaData->Get(index, key, data);
  51. AZStd::string_view currentNodeName(currentNode->mName.C_Str(), currentNode->mName.length);
  52. AZStd::string_view keyName(key->C_Str(), key->length);
  53. if (data->mType == AI_AISTRING)
  54. {
  55. const aiString* value = reinterpret_cast<const aiString*>(data->mData);
  56. propertyMap[keyName] = AZStd::make_any<AZStd::string>(value->C_Str(), value->length);
  57. }
  58. else if (data->mType == AI_BOOL)
  59. {
  60. const bool* value = reinterpret_cast<const bool*>(data->mData);
  61. propertyMap[keyName] = AZStd::make_any<bool>(aznumeric_cast<bool>(*value));
  62. }
  63. else if (data->mType == AI_INT32)
  64. {
  65. const int32_t* value = reinterpret_cast<const int32_t*>(data->mData);
  66. propertyMap[keyName] = AZStd::make_any<AZ::s32>(aznumeric_cast<AZ::s32>(*value));
  67. }
  68. else if (data->mType == AI_UINT64)
  69. {
  70. const uint64_t* value = reinterpret_cast<const uint64_t*>(data->mData);
  71. propertyMap[keyName] = AZStd::make_any<AZ::u64>(aznumeric_cast<AZ::u64>(*value));
  72. }
  73. else if (data->mType == AI_FLOAT)
  74. {
  75. const float* value = reinterpret_cast<const float*>(data->mData);
  76. propertyMap[keyName] = AZStd::make_any<float>(aznumeric_cast<float>(*value));
  77. }
  78. else if (data->mType == AI_DOUBLE)
  79. {
  80. const double* value = reinterpret_cast<const double*>(data->mData);
  81. propertyMap[keyName] = AZStd::make_any<double>(aznumeric_cast<double>(*value));
  82. }
  83. }
  84. auto customPropertyMapData = AZStd::make_shared<SceneData::GraphData::CustomPropertyData>(propertyMap);
  85. if (!customPropertyMapData)
  86. {
  87. return Events::ProcessingResult::Failure;
  88. }
  89. // If it is non-endpoint data populated node, add a custom property node attribute
  90. if (context.m_scene.GetGraph().HasNodeContent(context.m_currentGraphPosition))
  91. {
  92. if (!context.m_scene.GetGraph().IsNodeEndPoint(context.m_currentGraphPosition))
  93. {
  94. AZStd::string nodeName{ s_customPropertiesNodeName };
  95. RenamedNodesMap::SanitizeNodeName(nodeName, context.m_scene.GetGraph(), context.m_currentGraphPosition);
  96. auto newIndex = context.m_scene.GetGraph().AddChild(context.m_currentGraphPosition, nodeName.c_str());
  97. AZ_Error(SceneAPI::Utilities::ErrorWindow, newIndex.IsValid(), "Failed to create SceneGraph node for attribute.");
  98. if (!newIndex.IsValid())
  99. {
  100. return Events::ProcessingResult::Failure;
  101. }
  102. Events::ProcessingResult attributeResult;
  103. AssImpSceneAttributeDataPopulatedContext dataPopulated(context, customPropertyMapData, newIndex, nodeName);
  104. attributeResult = Events::Process(dataPopulated);
  105. if (attributeResult != Events::ProcessingResult::Failure)
  106. {
  107. attributeResult = AddAttributeDataNodeWithContexts(dataPopulated);
  108. }
  109. return attributeResult;
  110. }
  111. }
  112. else
  113. {
  114. bool addedData = context.m_scene.GetGraph().SetContent(context.m_currentGraphPosition, customPropertyMapData);
  115. AZ_Error(SceneAPI::Utilities::ErrorWindow, addedData, "Failed to add node data");
  116. return addedData ? Events::ProcessingResult::Success : Events::ProcessingResult::Failure;
  117. }
  118. return Events::ProcessingResult::Ignored;
  119. }
  120. }