/* * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or * its licensors. * * For complete copyright and license terms please see the LICENSE at the root of this * distribution (the "License"). All use of this software is governed by the License, * or, if provided, by the license below or the license accompanying this file. Do not * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace AZ { namespace SceneAPI { namespace Behaviors { void MeshAdvancedRule::Activate() { Events::ManifestMetaInfoBus::Handler::BusConnect(); Events::AssetImportRequestBus::Handler::BusConnect(); } void MeshAdvancedRule::Deactivate() { Events::AssetImportRequestBus::Handler::BusDisconnect(); Events::ManifestMetaInfoBus::Handler::BusDisconnect(); } void MeshAdvancedRule::Reflect(ReflectContext* context) { SerializeContext* serializeContext = azrtti_cast(context); if (serializeContext) { serializeContext->Class()->Version(1); } } void MeshAdvancedRule::InitializeObject(const Containers::Scene& scene, DataTypes::IManifestObject& target) { AZStd::string firstVertexColorStream = GetFirstVertexColorStream(scene); if (target.RTTI_IsTypeOf(DataTypes::ISceneNodeGroup::TYPEINFO_Uuid())) { if (!firstVertexColorStream.empty()) { if (target.RTTI_IsTypeOf(DataTypes::ISkinGroup::TYPEINFO_Uuid())) { AZStd::shared_ptr rule = AZStd::make_shared(); rule->SetVertexColorStreamName(firstVertexColorStream.empty() ? DataTypes::s_advancedDisabledString : AZStd::move(firstVertexColorStream)); DataTypes::ISceneNodeGroup* sceneNodeGroup = azrtti_cast(&target); sceneNodeGroup->GetRuleContainer().AddRule(AZStd::move(rule)); } else if (target.RTTI_IsTypeOf(DataTypes::IMeshGroup::TYPEINFO_Uuid())) { AZStd::shared_ptr rule = AZStd::make_shared(); rule->SetVertexColorStreamName(firstVertexColorStream.empty() ? DataTypes::s_advancedDisabledString : AZStd::move(firstVertexColorStream)); DataTypes::ISceneNodeGroup* sceneNodeGroup = azrtti_cast(&target); sceneNodeGroup->GetRuleContainer().AddRule(AZStd::move(rule)); } } } else if (target.RTTI_IsTypeOf(SceneData::StaticMeshAdvancedRule::TYPEINFO_Uuid())) { SceneData::StaticMeshAdvancedRule* rule = azrtti_cast(&target); rule->SetVertexColorStreamName(firstVertexColorStream.empty() ? DataTypes::s_advancedDisabledString : AZStd::move(firstVertexColorStream)); } else if (target.RTTI_IsTypeOf(SceneData::SkinMeshAdvancedRule::TYPEINFO_Uuid())) { SceneData::SkinMeshAdvancedRule* rule = azrtti_cast(&target); rule->SetVertexColorStreamName(firstVertexColorStream.empty() ? DataTypes::s_advancedDisabledString : AZStd::move(firstVertexColorStream)); } } Events::ProcessingResult MeshAdvancedRule::UpdateManifest(Containers::Scene& scene, ManifestAction action, RequestingApplication requester) { AZ_UNUSED(requester); if (action == ManifestAction::Update) { UpdateMeshAdvancedRules(scene); return Events::ProcessingResult::Success; } else { return Events::ProcessingResult::Ignored; } } void MeshAdvancedRule::UpdateMeshAdvancedRules(Containers::Scene& scene) const { Containers::SceneManifest& manifest = scene.GetManifest(); auto valueStorage = manifest.GetValueStorage(); auto view = Containers::MakeDerivedFilterView(valueStorage); for (DataTypes::ISceneNodeGroup& group : view) { AZ_TraceContext("Scene node group", group.GetName()); Containers::RuleContainer& rules = group.GetRuleContainer(); const size_t ruleCount = rules.GetRuleCount(); // The Mesh Advanced Rules were previously invalidly applied to any group containing a vertex color stream, and should be cleaned up if unnecessarily added to existing data. // We use a list to track indices of rules to remove in a separate pass since the RuleContainer does not have direct iterator access. bool isValidGroupType = group.RTTI_IsTypeOf(DataTypes::IMeshGroup::TYPEINFO_Uuid()) || group.RTTI_IsTypeOf(DataTypes::ISkinGroup::TYPEINFO_Uuid()); AZStd::vector rulesToRemove; for (size_t index = 0; index < ruleCount; ++index) { DataTypes::IMeshAdvancedRule* rule = azrtti_cast(rules.GetRule(index).get()); if (rule) { if (isValidGroupType) { UpdateMeshAdvancedRule(scene, rule); } else { rulesToRemove.push_back(index); } } } // Remove in reversed order, as otherwise the indices will be wrong. For example if we remove index 3, then index 6 would really be 5 afterwards. // By doing this in reversed order we remove items at the end of the list first so it won't impact the indices of previous ones. for (AZStd::vector::reverse_iterator it = rulesToRemove.rbegin(); it != rulesToRemove.rend(); ++it) { rules.RemoveRule(*it); } } } void MeshAdvancedRule::UpdateMeshAdvancedRule(Containers::Scene& scene, DataTypes::IMeshAdvancedRule* rule) const { if (!rule) { return; } SceneData::SkinMeshAdvancedRule* skinRule = azrtti_cast(rule); SceneData::StaticMeshAdvancedRule* meshRule = azrtti_cast(rule); if (!(skinRule || meshRule)) { return; } const AZStd::string& vertexColorStreamName = rule->GetVertexColorStreamName(); bool foundColorStream = vertexColorStreamName == DataTypes::s_advancedDisabledString; const Containers::SceneGraph& graph = scene.GetGraph(); Containers::SceneGraph::NameStorageConstData graphNames = graph.GetNameStorage(); for (auto it = graphNames.begin(); it != graphNames.end(); ++it) { if (foundColorStream) { break; } const char* nodeName = it->GetName(); if (!foundColorStream && vertexColorStreamName == nodeName) { foundColorStream = true; } } if (!foundColorStream) { AZStd::string newColorStreamName = GetFirstVertexColorStream(scene); AZ_TracePrintf(Utilities::WarningWindow, "Old vertex color stream name not found so renamed from '%s' to '%s'.", vertexColorStreamName.c_str(), newColorStreamName.c_str()); if (skinRule) { skinRule->SetVertexColorStreamName(newColorStreamName.empty() ? DataTypes::s_advancedDisabledString : AZStd::move(newColorStreamName)); } else if (meshRule) { meshRule->SetVertexColorStreamName(newColorStreamName.empty() ? DataTypes::s_advancedDisabledString : AZStd::move(newColorStreamName)); } } } AZStd::string MeshAdvancedRule::GetFirstVertexColorStream(const Containers::Scene& scene) const { const Containers::SceneGraph& graph = scene.GetGraph(); Containers::SceneGraph::ContentStorageConstData graphContent = graph.GetContentStorage(); auto vertexColorData = AZStd::find_if(graphContent.begin(), graphContent.end(), Containers::DerivedTypeFilter()); if (vertexColorData != graphContent.end()) { return graph.GetNodeName(graph.ConvertToNodeIndex(vertexColorData)).GetName(); } else { return AZStd::string(); } } } // namespace Behaviors } // namespace SceneAPI } // namespace AZ