Initial commit

This commit is contained in:
alexpete
2021-03-05 11:26:34 -08:00
commit a10351f38d
27091 changed files with 5521199 additions and 0 deletions
@@ -0,0 +1,79 @@
/*
* 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 "DebugOutput.h"
namespace AZ::SceneAPI::Utilities
{
void DebugOutput::Write(const char* name, const char* data)
{
m_output += AZStd::string::format("\t%s: %s\n", name, data);
}
void DebugOutput::Write(const char* name, const AZStd::string& data)
{
Write(name, data.c_str());
}
void DebugOutput::Write(const char* name, double data)
{
m_output += AZStd::string::format("\t%s: %f\n", name, data);
}
void DebugOutput::Write(const char* name, uint64_t data)
{
m_output += AZStd::string::format("\t%s: %" PRIu64 "\n", name, data);
}
void DebugOutput::Write(const char* name, int64_t data)
{
m_output += AZStd::string::format("\t%s: %" PRId64 "\n", name, data);
}
void DebugOutput::Write(const char* name, const DataTypes::MatrixType& data)
{
AZ::Vector3 basisX{};
AZ::Vector3 basisY{};
AZ::Vector3 basisZ{};
AZ::Vector3 translation{};
data.GetBasisAndTranslation(&basisX, &basisY, &basisZ, &translation);
m_output += AZStd::string::format("\t%s:\n", name);
m_output += "\t";
Write("BasisX", basisX);
m_output += "\t";
Write("BasisY", basisY);
m_output += "\t";
Write("BasisZ", basisZ);
m_output += "\t";
Write("Transl", translation);
}
void DebugOutput::Write(const char* name, bool data)
{
m_output += AZStd::string::format("\t%s: %s\n", name, data ? "true" : "false");
}
void DebugOutput::Write(const char* name, Vector3 data)
{
m_output += AZStd::string::format("\t%s: <% f, % f, % f>\n", name, data.GetX(), data.GetY(), data.GetZ());
}
const AZStd::string& DebugOutput::GetOutput() const
{
return m_output;
}
}
@@ -0,0 +1,47 @@
/*
* 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.
*
*/
#pragma once
#include <SceneAPI/SceneCore/SceneCoreConfiguration.h>
#include <SceneAPI/SceneCore/DataTypes/MatrixType.h>
#include <SceneAPI/SceneCore/Utilities/HashHelper.h>
#include <cinttypes>
namespace AZ::SceneAPI::Utilities
{
class DebugOutput
{
public:
template<typename T>
void Write(const char* name, const AZStd::vector<T>& data);
template<typename T>
void Write(const char* name, const AZStd::vector<AZStd::vector<T>>& data);
SCENE_CORE_API void Write(const char* name, const char* data);
SCENE_CORE_API void Write(const char* name, const AZStd::string& data);
SCENE_CORE_API void Write(const char* name, double data);
SCENE_CORE_API void Write(const char* name, uint64_t data);
SCENE_CORE_API void Write(const char* name, int64_t data);
SCENE_CORE_API void Write(const char* name, const DataTypes::MatrixType& data);
SCENE_CORE_API void Write(const char* name, bool data);
SCENE_CORE_API void Write(const char* name, Vector3 data);
SCENE_CORE_API const AZStd::string& GetOutput() const;
protected:
AZStd::string m_output;
};
}
#include "DebugOutput.inl"
@@ -0,0 +1,35 @@
/*
* 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.
*
*/
#pragma once
namespace AZ::SceneAPI::Utilities
{
template <typename T>
void DebugOutput::Write(const char* name, const AZStd::vector<T>& data)
{
m_output += AZStd::string::format("\t%s: Count %zu. Hash: %zu\n", name, data.size(), AZStd::hash_range(data.begin(), data.end()));
}
template <typename T>
void DebugOutput::Write(const char* name, const AZStd::vector<AZStd::vector<T>>& data)
{
size_t hash = 0;
for (auto&& vector : data)
{
AZStd::hash_combine(hash, AZStd::hash_range(vector.begin(), vector.end()));
}
m_output += AZStd::string::format("\t%s: Count %zu. Hash: %zu\n", name, data.size(), hash);
}
}
@@ -0,0 +1,67 @@
/*
* 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 <AzCore/IO/SystemFile.h>
#include <AzFramework/StringFunc/StringFunc.h>
#include <AzFramework/API/ApplicationAPI.h>
#include <SceneAPI/SceneCore/Utilities/FileUtilities.h>
namespace AZ
{
namespace SceneAPI
{
namespace Utilities
{
AZStd::string FileUtilities::CreateOutputFileName(const AZStd::string& groupName, const AZStd::string& outputDirectory, const AZStd::string& extension)
{
AZStd::string result;
if (!AzFramework::StringFunc::Path::ConstructFull(outputDirectory.c_str(), groupName.c_str(), extension.c_str(), result, true))
{
return "";
}
return result;
}
bool FileUtilities::EnsureTargetFolderExists(const AZStd::string& path)
{
AZStd::string folder;
if (!AzFramework::StringFunc::Path::GetFullPath(path.c_str(), folder))
{
return false;
}
if (!IO::SystemFile::Exists(folder.c_str()))
{
if (!IO::SystemFile::CreateDir(folder.c_str()))
{
return false;
}
}
return true;
}
AZStd::string FileUtilities::GetRelativePath(const AZStd::string& path, const AZStd::string& rootPath)
{
AZStd::string outputPath(path);
EBUS_EVENT(AzFramework::ApplicationRequests::Bus, NormalizePath, outputPath);
if (outputPath.compare(0, rootPath.size(), rootPath) == 0)
{
size_t offset = rootPath[rootPath.length() - 1] == '/' ? 1 : 0;
AzFramework::StringFunc::RKeep(outputPath, rootPath.size() - offset);
}
return outputPath;
}
}
}
}
@@ -0,0 +1,33 @@
#pragma once
/*
* 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 <AzCore/std/string/string.h>
#include <SceneAPI/SceneCore/SceneCoreConfiguration.h>
namespace AZ
{
namespace SceneAPI
{
namespace Utilities
{
class FileUtilities
{
public:
SCENE_CORE_API static AZStd::string CreateOutputFileName(const AZStd::string& groupName, const AZStd::string& outputDirectory, const AZStd::string& extension);
SCENE_CORE_API static bool EnsureTargetFolderExists(const AZStd::string& path);
SCENE_CORE_API static AZStd::string GetRelativePath(const AZStd::string& path, const AZStd::string& rootPath);
};
}
}
}
@@ -0,0 +1,97 @@
/*
* 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.
*
*/
#pragma once
#include <AzCore/Math/Vector2.h>
#include <AzCore/Math/Vector3.h>
#include <AzCore/Math/Vector4.h>
#include <AzCore/Math/Matrix3x4.h>
namespace AZStd
{
template<>
struct hash<AZ::Vector2>
{
using result_type = AZStd::size_t;
result_type operator()(const AZ::Vector2& value) const
{
result_type hash = 0;
hash_combine(hash, value.GetX());
hash_combine(hash, value.GetY());
return hash;
}
};
template<>
struct hash<AZ::Vector3>
{
using result_type = AZStd::size_t;
result_type operator()(const AZ::Vector3& value) const
{
result_type hash = 0;
hash_combine(hash, value.GetX());
hash_combine(hash, value.GetY());
hash_combine(hash, value.GetZ());
return hash;
}
};
template<>
struct hash<AZ::Vector4>
{
using result_type = AZStd::size_t;
result_type operator()(const AZ::Vector4& value) const
{
result_type hash = 0;
hash_combine(hash, value.GetX());
hash_combine(hash, value.GetY());
hash_combine(hash, value.GetZ());
hash_combine(hash, value.GetW());
return hash;
}
};
template<>
struct hash<AZ::Matrix3x4>
{
using result_type = AZStd::size_t;
result_type operator()(const AZ::Matrix3x4& value) const
{
result_type hash = 0;
AZ::Vector3 basisX;
AZ::Vector3 basisY;
AZ::Vector3 basisZ;
AZ::Vector3 translation;
value.GetBasisAndTranslation(&basisX, &basisY, &basisZ, &translation);
hash_combine(hash, basisX);
hash_combine(hash, basisY);
hash_combine(hash, basisZ);
hash_combine(hash, translation);
return hash;
}
};
}
@@ -0,0 +1,177 @@
/*
* 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 <AzCore/Serialization/SerializeContext.h>
#include <AzCore/Serialization/EditContext.h>
#include <AzCore/std/string/regex.h>
#include <AzFramework/StringFunc/StringFunc.h>
#include <SceneAPI/SceneCore/Utilities/Reporting.h>
#include <SceneAPI/SceneCore/Utilities/PatternMatcher.h>
namespace AZ
{
namespace SceneAPI
{
namespace SceneCore
{
PatternMatcher::PatternMatcher(const char* pattern, MatchApproach matcher)
: m_pattern(pattern)
, m_matcher(matcher)
{
}
PatternMatcher::PatternMatcher(const AZStd::string& pattern, MatchApproach matcher)
: m_pattern(pattern)
, m_matcher(matcher)
{
}
PatternMatcher::PatternMatcher(AZStd::string&& pattern, MatchApproach matcher)
: m_pattern(AZStd::move(pattern))
, m_matcher(matcher)
{
}
PatternMatcher::PatternMatcher(PatternMatcher&& rhs)
: m_pattern(AZStd::move(rhs.m_pattern))
, m_matcher(rhs.m_matcher)
{
}
PatternMatcher& PatternMatcher::operator=(PatternMatcher&& rhs)
{
m_pattern = AZStd::move(rhs.m_pattern);
m_matcher = rhs.m_matcher;
return *this;
}
bool PatternMatcher::LoadFromJson(rapidjson::Document::ConstMemberIterator member)
{
if (!member->value.HasMember("PatternMatcher"))
{
AZ_TracePrintf(Utilities::WarningWindow, "Missing element 'PatternMatcher'.");
return false;
}
if (!member->value.HasMember("Pattern"))
{
AZ_TracePrintf(Utilities::WarningWindow, "Missing element 'Pattern'.");
return false;
}
const auto& patternMatcherValue = member->value["PatternMatcher"];
if (!patternMatcherValue.IsString())
{
AZ_TracePrintf(Utilities::WarningWindow, "Element 'PatternMatcher' is not a string.");
return false;
}
const auto& patternValue = member->value["Pattern"];
if (!patternValue.IsString())
{
AZ_TracePrintf(Utilities::WarningWindow, "Element 'Pattern' is not a string.");
return false;
}
if (AzFramework::StringFunc::Equal(patternMatcherValue.GetString(), "postfix"))
{
m_matcher = MatchApproach::PostFix;
}
else if (AzFramework::StringFunc::Equal(patternMatcherValue.GetString(), "prefix"))
{
m_matcher = MatchApproach::PreFix;
}
else if (AzFramework::StringFunc::Equal(patternMatcherValue.GetString(), "regex"))
{
m_matcher = MatchApproach::Regex;
}
else
{
AZ_TracePrintf(Utilities::WarningWindow,
"Element 'PatternMatcher' is no one of the available options postfix, prefix or regex.");
return false;
}
m_pattern = patternValue.GetString();
return true;
}
bool PatternMatcher::MatchesPattern(const char* name, size_t nameLength) const
{
switch (m_matcher)
{
case MatchApproach::PreFix:
return AzFramework::StringFunc::Equal(name, m_pattern.c_str(), false, m_pattern.size());
case MatchApproach::PostFix:
{
if (m_pattern.size() > nameLength)
{
return false;
}
size_t offset = nameLength - m_pattern.size();
return AzFramework::StringFunc::Equal(name + offset, m_pattern.c_str());
}
case MatchApproach::Regex:
{
AZStd::regex comparer(m_pattern, AZStd::regex::extended);
AZStd::smatch match;
return AZStd::regex_match(name, match, comparer);
}
default:
AZ_Assert(false, "Unknown option '%i' for pattern matcher.", m_matcher);
return false;
}
}
bool PatternMatcher::MatchesPattern(const AZStd::string& name) const
{
return MatchesPattern(name.c_str(), name.length());
}
const AZStd::string& PatternMatcher::GetPattern() const
{
return m_pattern;
}
PatternMatcher::MatchApproach PatternMatcher::GetMatchApproach() const
{
return m_matcher;
}
void PatternMatcher::Reflect(ReflectContext* context)
{
SerializeContext* serializeContext = azrtti_cast<SerializeContext*>(context);
if (serializeContext)
{
serializeContext->Class<PatternMatcher>()
->Version(1)
->Field("pattern", &PatternMatcher::m_pattern)
->Field("matcher", &PatternMatcher::m_matcher);
EditContext* editContext = serializeContext->GetEditContext();
if (editContext)
{
editContext->Class<PatternMatcher>("Pattern matcher", "")
->ClassElement(Edit::ClassElements::EditorData, "")
->Attribute(Edit::Attributes::AutoExpand, true)
->DataElement(Edit::UIHandlers::Default, &PatternMatcher::m_pattern, "Pattern", "The pattern the matcher will check against.")
->DataElement(Edit::UIHandlers::ComboBox, &PatternMatcher::m_matcher, "Matcher", "The used approach for matching.")
->EnumAttribute(MatchApproach::PreFix, "PreFix")
->EnumAttribute(MatchApproach::PostFix, "PostFix")
->EnumAttribute(MatchApproach::Regex, "Regex");
}
}
}
} // SceneCore
} // SceneAPI
} // AZ
@@ -0,0 +1,72 @@
#pragma once
/*
* 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 <AzCore/RTTI/RTTI.h>
#include <AzCore/std/string/string.h>
#include <AzCore/JSON/document.h>
#include <SceneAPI/SceneCore/SceneCoreConfiguration.h>
namespace AZ
{
class ReflectContext;
namespace SceneAPI
{
namespace SceneCore
{
// PatternMatcher stores a pattern and a matching approach for later use.
// Strings can then be checked against the stored pattern.
// The supported approaches are:
// Prefix - Matches if the string starts with the stored pattern.
// Postfix - Matches if the string ends with the stored pattern.
// Regex - Matches if the string matches the given regular expression.
class PatternMatcher
{
public:
AZ_RTTI(PatternMatcher, "{F043EC4E-FA29-4A5E-BEF6-13C661048FC4}");
virtual ~PatternMatcher() = default;
enum class MatchApproach
{
PreFix,
PostFix,
Regex
};
PatternMatcher() = default;
SCENE_CORE_API PatternMatcher(const char* pattern, MatchApproach matcher);
SCENE_CORE_API PatternMatcher(const AZStd::string& pattern, MatchApproach matcher);
SCENE_CORE_API PatternMatcher(AZStd::string&& pattern, MatchApproach matcher);
SCENE_CORE_API PatternMatcher(const PatternMatcher& rhs) = default;
SCENE_CORE_API PatternMatcher(PatternMatcher&& rhs);
SCENE_CORE_API PatternMatcher& operator=(const PatternMatcher& rhs) = default;
SCENE_CORE_API PatternMatcher& operator=(PatternMatcher&& rhs);
SCENE_CORE_API bool LoadFromJson(rapidjson::Document::ConstMemberIterator member);
SCENE_CORE_API bool MatchesPattern(const char* name, size_t nameLength) const;
SCENE_CORE_API bool MatchesPattern(const AZStd::string& name) const;
SCENE_CORE_API const AZStd::string& GetPattern() const;
SCENE_CORE_API MatchApproach GetMatchApproach() const;
static void Reflect(AZ::ReflectContext* context);
private:
AZStd::string m_pattern;
MatchApproach m_matcher = MatchApproach::PostFix;
};
} // SceneCore
} // SceneAPI
} // AZ
@@ -0,0 +1,32 @@
#pragma once
/*
* 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.
*
*/
namespace AZ
{
namespace SceneAPI
{
namespace Utilities
{
// Window name used for reporting errors through AZ_TracePrintf.
const char* const ErrorWindow = "Error";
// Window name used for reporting warnings through AZ_TracePrintf.
const char* const WarningWindow = "Warning";
// Window name used for reporting success events through AZ_TracePrintf.
const char* const SuccessWindow = "Success";
// Window name used for logging through AZ_TracePrintf.
const char* const LogWindow = "SceneAPI";
} // Utilities
} // SceneAPI
} // AZ
@@ -0,0 +1,251 @@
/*
* 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 <SceneAPI/SceneCore/Containers/Views/SceneGraphDownwardsIterator.h>
#include <SceneAPI/SceneCore/Containers/Views/PairIterator.h>
#include <SceneAPI/SceneCore/Utilities/SceneGraphSelector.h>
#include <AzCore/std/containers/set.h>
#include <AzCore/Math/Transform.h>
#include <SceneAPI/SceneCore/DataTypes/ManifestBase/ISceneNodeSelectionList.h>
#include <SceneAPI/SceneCore/DataTypes/GraphData/IMeshData.h>
namespace AZ
{
namespace SceneAPI
{
namespace Utilities
{
bool SceneGraphSelector::IsTreeViewType(const Containers::SceneGraph& graph, Containers::SceneGraph::NodeIndex& index)
{
if (index == graph.GetRoot())
{
return false;
}
return !graph.IsNodeEndPoint(index);
}
bool SceneGraphSelector::IsMesh(const Containers::SceneGraph& graph, Containers::SceneGraph::NodeIndex& index)
{
AZStd::shared_ptr<const DataTypes::IGraphObject> object = graph.GetNodeContent(index);
return SceneGraphSelector::IsMeshObject(object);
}
bool SceneGraphSelector::IsMeshObject(const AZStd::shared_ptr<const DataTypes::IGraphObject>& object)
{
return object && object->RTTI_IsTypeOf(DataTypes::IMeshData::TYPEINFO_Uuid());
}
AZStd::vector<AZStd::string> SceneGraphSelector::GenerateTargetNodes(const Containers::SceneGraph& graph, const DataTypes::ISceneNodeSelectionList& list, NodeFilterFunction nodeFilter)
{
AZStd::vector<AZStd::string> targetNodes;
AZStd::set<AZStd::string> selectedNodesSet;
AZStd::set<AZStd::string> unselectedNodesSet;
CopySelectionToSet(selectedNodesSet, unselectedNodesSet, list);
CorrectRootNode(graph, selectedNodesSet, unselectedNodesSet);
auto nodeIterator = graph.ConvertToHierarchyIterator(graph.GetRoot());
auto view = Containers::Views::MakeSceneGraphDownwardsView<Containers::Views::BreadthFirst>(graph, nodeIterator, graph.GetContentStorage().cbegin(), true);
if (view.begin() == view.end())
{
return targetNodes;
}
for (auto it = ++view.begin(); it != view.end(); ++it)
{
Containers::SceneGraph::NodeIndex index = graph.ConvertToNodeIndex(it.GetHierarchyIterator());
AZStd::string currentNodeName = graph.GetNodeName(index).GetPath();
if (unselectedNodesSet.find(currentNodeName) != unselectedNodesSet.end())
{
continue;
}
if (selectedNodesSet.find(currentNodeName) != selectedNodesSet.end())
{
if (nodeFilter(graph, index))
{
targetNodes.push_back(currentNodeName);
}
continue;
}
Containers::SceneGraph::NodeIndex parentIndex = graph.GetNodeParent(index);
if (parentIndex.IsValid())
{
AZStd::string parentNodeName = graph.GetNodeName(parentIndex).GetPath();
if (unselectedNodesSet.find(parentNodeName) != unselectedNodesSet.end())
{
unselectedNodesSet.insert(currentNodeName);
}
else if (selectedNodesSet.find(parentNodeName) != selectedNodesSet.end())
{
selectedNodesSet.insert(currentNodeName);
if (nodeFilter(graph, index))
{
targetNodes.push_back(currentNodeName);
}
}
else
{
AZ_Assert(false, "SceneGraphSelector does a breadth first iteration so parent should be processed, "
"but '%s' wasn't found in either selected or unselected list.", currentNodeName.c_str());
}
}
}
return targetNodes;
}
void SceneGraphSelector::SelectAll(const Containers::SceneGraph& graph, DataTypes::ISceneNodeSelectionList& list)
{
list.ClearSelectedNodes();
list.ClearUnselectedNodes();
auto hierarchyStorage = graph.GetHierarchyStorage();
auto nameStorage = graph.GetNameStorage();
auto range = Containers::Views::MakePairView(hierarchyStorage, nameStorage);
for (auto it : range)
{
if (!it.first.IsEndPoint())
{
list.AddSelectedNode(it.second.GetPath());
}
}
}
void SceneGraphSelector::UnselectAll(const Containers::SceneGraph& graph, DataTypes::ISceneNodeSelectionList& list)
{
list.ClearSelectedNodes();
list.ClearUnselectedNodes();
auto hierarchyStorage = graph.GetHierarchyStorage();
auto nameStorage = graph.GetNameStorage();
auto range = Containers::Views::MakePairView(hierarchyStorage, nameStorage);
for (auto it : range)
{
if (!it.first.IsEndPoint())
{
list.RemoveSelectedNode(it.second.GetPath());
}
}
}
void SceneGraphSelector::UpdateNodeSelection(const Containers::SceneGraph& graph, DataTypes::ISceneNodeSelectionList& list)
{
AZStd::set<AZStd::string> selectedNodesSet;
AZStd::set<AZStd::string> unselectedNodesSet;
CopySelectionToSet(selectedNodesSet, unselectedNodesSet, list);
CorrectRootNode(graph, selectedNodesSet, unselectedNodesSet);
list.ClearSelectedNodes();
list.ClearUnselectedNodes();
auto nameStorage = graph.GetNameStorage();
auto contentStorage = graph.GetContentStorage();
auto keyValueView = Containers::Views::MakePairView(nameStorage, contentStorage);
auto nodeIterator = graph.ConvertToHierarchyIterator(graph.GetRoot());
auto view = Containers::Views::MakeSceneGraphDownwardsView<Containers::Views::BreadthFirst>(graph, nodeIterator, keyValueView.cbegin(), true);
if (view.begin() == view.end())
{
return;
}
for (auto it = ++view.begin(); it != view.end(); ++it)
{
Containers::SceneGraph::NodeIndex index = graph.ConvertToNodeIndex(it.GetHierarchyIterator());
AZStd::string currentNodeName = it->first.GetPath();
// Check if item is already registered and if so add it to the appropriate list.
if (unselectedNodesSet.find(currentNodeName) != unselectedNodesSet.end())
{
list.RemoveSelectedNode(AZStd::move(currentNodeName));
continue;
}
if (selectedNodesSet.find(currentNodeName) != selectedNodesSet.end())
{
list.AddSelectedNode(AZStd::move(currentNodeName));
continue;
}
// If not already registered, look at the parent and determine what container it's in
// and add the unregistered node to that list.
Containers::SceneGraph::NodeIndex parentIndex = graph.GetNodeParent(index);
if (parentIndex.IsValid())
{
AZStd::string parentNodeName = graph.GetNodeName(parentIndex).GetPath();
if (unselectedNodesSet.find(parentNodeName) != unselectedNodesSet.end())
{
unselectedNodesSet.insert(currentNodeName);
list.RemoveSelectedNode(AZStd::move(currentNodeName));
}
else
{
selectedNodesSet.insert(currentNodeName);
list.AddSelectedNode(AZStd::move(currentNodeName));
}
}
}
}
void SceneGraphSelector::UpdateTargetNodes(const Containers::SceneGraph& graph, DataTypes::ISceneNodeSelectionList& list, const AZStd::unordered_set<AZStd::string>& targetNodes,
NodeFilterFunction nodeFilter)
{
list.ClearSelectedNodes();
list.ClearUnselectedNodes();
auto nameStorage = graph.GetNameStorage();
auto contentStorage = graph.GetContentStorage();
auto view = Containers::Views::MakePairView(nameStorage, contentStorage);
if (view.begin() == view.end())
{
return;
}
for (auto it = ++view.begin(); it != view.end(); ++it)
{
Containers::SceneGraph::NodeIndex index = graph.ConvertToNodeIndex(it.GetSecondIterator());
AZStd::string currentNodeName = it->first.GetPath();
if (nodeFilter(graph, index))
{
if (targetNodes.find(currentNodeName) != targetNodes.end())
{
list.AddSelectedNode(currentNodeName);
}
else
{
list.RemoveSelectedNode(currentNodeName);
}
}
}
}
void SceneGraphSelector::CopySelectionToSet(AZStd::set<AZStd::string>& selected, AZStd::set<AZStd::string>& unselected, const DataTypes::ISceneNodeSelectionList& list)
{
for (size_t i = 0; i < list.GetSelectedNodeCount(); ++i)
{
selected.insert(list.GetSelectedNode(i));
}
for (size_t i = 0; i < list.GetUnselectedNodeCount(); ++i)
{
unselected.insert(list.GetUnselectedNode(i));
}
}
void SceneGraphSelector::CorrectRootNode(const Containers::SceneGraph& graph,
AZStd::set<AZStd::string>& selected, AZStd::set<AZStd::string>& unselected)
{
AZStd::string rootNodeName = graph.GetNodeName(graph.GetRoot()).GetPath();
if (selected.find(rootNodeName) == selected.end())
{
selected.insert(rootNodeName);
}
auto root = unselected.find(rootNodeName);
if (root != unselected.end())
{
unselected.erase(root);
}
}
}
}
}
@@ -0,0 +1,56 @@
#pragma once
/*
* 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 <AzCore/std/functional.h>
#include <AzCore/std/string/string.h>
#include <AzCore/std/containers/set.h>
#include <AzCore/std/containers/unordered_set.h>
#include <SceneAPI/SceneCore/Containers/SceneGraph.h>
namespace AZ
{
namespace SceneAPI
{
namespace DataTypes
{
class ISceneNodeSelectionList;
}
namespace Utilities
{
// SceneGraphSelector provides utilities including converting selected and unselected node lists
// in the MeshGroup into the final target node list.
class SceneGraphSelector
{
public:
using NodeFilterFunction = AZStd::function<bool(const Containers::SceneGraph& graph, Containers::SceneGraph::NodeIndex& index)>;
SCENE_CORE_API static AZStd::vector<AZStd::string> GenerateTargetNodes(const Containers::SceneGraph& graph, const DataTypes::ISceneNodeSelectionList& list,
NodeFilterFunction nodeFilter);
SCENE_CORE_API static void SelectAll(const Containers::SceneGraph& graph, DataTypes::ISceneNodeSelectionList& list);
SCENE_CORE_API static void UnselectAll(const Containers::SceneGraph& graph, DataTypes::ISceneNodeSelectionList& list);
SCENE_CORE_API static void UpdateNodeSelection(const Containers::SceneGraph& graph, DataTypes::ISceneNodeSelectionList& list);
SCENE_CORE_API static void UpdateTargetNodes(const Containers::SceneGraph& graph, DataTypes::ISceneNodeSelectionList& list,
const AZStd::unordered_set<AZStd::string>& targetNodes, NodeFilterFunction nodeFilter);
SCENE_CORE_API static bool IsTreeViewType(const Containers::SceneGraph& graph, Containers::SceneGraph::NodeIndex& index);
SCENE_CORE_API static bool IsMesh(const Containers::SceneGraph& graph, Containers::SceneGraph::NodeIndex& index);
SCENE_CORE_API static bool IsMeshObject(const AZStd::shared_ptr<const DataTypes::IGraphObject>& object);
private:
static void CopySelectionToSet(AZStd::set<AZStd::string>& selected, AZStd::set<AZStd::string>& unselected, const DataTypes::ISceneNodeSelectionList& list);
static void CorrectRootNode(const Containers::SceneGraph& graph, AZStd::set<AZStd::string>& selected, AZStd::set<AZStd::string>& unselected);
};
}
}
}