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,55 @@
#
# 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.
#
if (NOT PAL_TRAIT_BUILD_HOST_TOOLS)
return()
endif()
ly_add_target(
NAME SceneCore SHARED
NAMESPACE AZ
FILES_CMAKE
scenecore_files.cmake
COMPILE_DEFINITIONS
PRIVATE
SCENE_CORE_EXPORTS
INCLUDE_DIRECTORIES
PUBLIC
../..
BUILD_DEPENDENCIES
PRIVATE
AZ::AzCore
AZ::AzFramework
AZ::AzToolsFramework
AZ::GFxFramework
)
if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
ly_add_target(
NAME SceneCore.Tests ${PAL_TRAIT_TEST_TARGET_TYPE}
NAMESPACE AZ
FILES_CMAKE
scenecore_testing_files.cmake
INCLUDE_DIRECTORIES
PRIVATE
Tests
BUILD_DEPENDENCIES
PRIVATE
AZ::AzTest
AZ::SceneCore
AZ::AzFramework
AZ::AzToolsFramework
AZ::GFxFramework
)
ly_add_googletest(
NAME AZ::SceneCore.Tests
)
endif()
@@ -0,0 +1,40 @@
/*
* 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 <SceneAPI/SceneCore/Components/BehaviorComponent.h>
namespace AZ
{
namespace SceneAPI
{
namespace SceneCore
{
void BehaviorComponent::Activate()
{
}
void BehaviorComponent::Deactivate()
{
}
void BehaviorComponent::Reflect(ReflectContext* context)
{
SerializeContext* serializeContext = azrtti_cast<SerializeContext*>(context);
if (serializeContext)
{
serializeContext->Class<BehaviorComponent, AZ::Component>()->Version(1);
}
}
} // namespace SceneCore
} // namespace SceneAPI
} // namespace AZ
@@ -0,0 +1,44 @@
/*
* 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/Component/Component.h>
#include <SceneAPI/SceneCore/SceneCoreConfiguration.h>
namespace AZ
{
namespace SceneAPI
{
namespace SceneCore
{
// Behavior components are small logic units that exist as long as the SceneAPI is
// initialized and active. These components can react to various events that
// happen to a scene and make appropriate changes, additions or removals. These
// components are also responsible to register their associated data with the
// reflect context.
class SCENE_CORE_CLASS BehaviorComponent
: public AZ::Component
{
public:
AZ_COMPONENT(BehaviorComponent, "{DA66AE07-9ECF-4108-9CCC-9BFF618DD4AD}");
~BehaviorComponent() override = default;
SCENE_CORE_API void Activate() override;
SCENE_CORE_API void Deactivate() override;
static void Reflect(ReflectContext* context);
};
} // namespace SceneCore
} // namespace SceneAPI
} // namespace AZ
@@ -0,0 +1,42 @@
/*
* 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 <SceneAPI/SceneCore/Components/ExportingComponent.h>
namespace AZ
{
namespace SceneAPI
{
namespace SceneCore
{
void ExportingComponent::Activate()
{
ActivateBindings();
}
void ExportingComponent::Deactivate()
{
DeactivateBindings();
}
void ExportingComponent::Reflect(ReflectContext* context)
{
SerializeContext* serializeContext = azrtti_cast<SerializeContext*>(context);
if (serializeContext)
{
serializeContext->Class<ExportingComponent, AZ::Component>()->Version(2);
}
}
} // namespace SceneCore
} // namespace SceneAPI
} // namespace AZ
@@ -0,0 +1,48 @@
/*
* 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/Component/Component.h>
#include <SceneAPI/SceneCore/SceneCoreConfiguration.h>
#include <SceneAPI/SceneCore/Events/CallProcessorBinder.h>
namespace AZ
{
namespace SceneAPI
{
namespace SceneCore
{
// Exporting components are small logic units that exist only during exporting. Each of
// these components take care of a small piece of the exporting process, allowing
// multiple components to use the same graph and manifest to collect data.
// Use the BindToCall from the CallProcessorBinder to be able to react to specific
// loading contexts/events.
class SCENE_CORE_CLASS ExportingComponent
: public AZ::Component
, public Events::CallProcessorBinder
{
public:
AZ_COMPONENT(ExportingComponent, "{0CB2327A-EAB7-4F16-8204-861530C3A077}", Events::CallProcessorBinder);
ExportingComponent() = default;
~ExportingComponent() override = default;
SCENE_CORE_API void Activate() override;
SCENE_CORE_API void Deactivate() override;
static void Reflect(ReflectContext* context);
};
} // namespace SceneCore
} // namespace SceneAPI
} // namespace AZ
@@ -0,0 +1,36 @@
/*
* 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 <SceneAPI/SceneCore/Components/GenerationComponent.h>
namespace AZ::SceneAPI::SceneCore
{
void GenerationComponent::Activate()
{
ActivateBindings();
}
void GenerationComponent::Deactivate()
{
DeactivateBindings();
}
void GenerationComponent::Reflect(ReflectContext* context)
{
SerializeContext* serializeContext = azrtti_cast<SerializeContext*>(context);
if (serializeContext)
{
serializeContext->Class<GenerationComponent, AZ::Component, Events::CallProcessorBinder>()->Version(1);
}
}
} // namespace AZ::SceneAPI::SceneCore
@@ -0,0 +1,38 @@
/*
* 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/Component/Component.h>
#include <SceneAPI/SceneCore/SceneCoreConfiguration.h>
#include <SceneAPI/SceneCore/Events/CallProcessorBinder.h>
namespace AZ::SceneAPI::SceneCore
{
// Generation components are small logic units that exist only during scene generation. Each of
// these components take care of a piece of the generation process, allowing
// multiple components to do runtime creation of scene graph objects.
// Use the BindToCall from the CallProcessorBinder to be able to react to specific
// loading contexts/events.
class SCENE_CORE_CLASS GenerationComponent
: public AZ::Component
, public Events::CallProcessorBinder
{
public:
AZ_COMPONENT(GenerationComponent, "{3DBA42C1-894E-4437-B046-BC399E34366B}", Events::CallProcessorBinder);
SCENE_CORE_API void Activate() override;
SCENE_CORE_API void Deactivate() override;
static void Reflect(ReflectContext* context);
};
} // namespace AZ::SceneAPI::SceneCore
@@ -0,0 +1,42 @@
/*
* 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 <SceneAPI/SceneCore/Components/LoadingComponent.h>
namespace AZ
{
namespace SceneAPI
{
namespace SceneCore
{
void LoadingComponent::Activate()
{
ActivateBindings();
}
void LoadingComponent::Deactivate()
{
DeactivateBindings();
}
void LoadingComponent::Reflect(ReflectContext* context)
{
SerializeContext* serializeContext = azrtti_cast<SerializeContext*>(context);
if (serializeContext)
{
serializeContext->Class<LoadingComponent, AZ::Component>()->Version(2);
}
}
} // namespace SceneCore
} // namespace SceneAPI
} // namespace AZ
@@ -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 <AzCore/Component/Component.h>
#include <SceneAPI/SceneCore/SceneCoreConfiguration.h>
#include <SceneAPI/SceneCore/Events/CallProcessorBinder.h>
namespace AZ
{
namespace SceneAPI
{
namespace SceneCore
{
// Loading components are small logic units that exist only during loading. Each of
// these components take care of a small piece of the loading process, allowing
// multiple components to use the same sources to collect data.
// Use the BindToCall from the CallProcessorBinder to be able to react to specific
// loading contexts/events.
class SCENE_CORE_CLASS LoadingComponent
: public AZ::Component
, public Events::CallProcessorBinder
{
public:
AZ_COMPONENT(LoadingComponent, "{335A696D-38DA-4A4F-B3F3-DBAD1FE86888}", Events::CallProcessorBinder);
LoadingComponent() = default;
~LoadingComponent() override = default;
SCENE_CORE_API void Activate() override;
SCENE_CORE_API void Deactivate() override;
static void Reflect(ReflectContext* context);
};
} // namespace SceneCore
} // namespace SceneAPI
} // namespace AZ
@@ -0,0 +1,42 @@
/*
* 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 <SceneAPI/SceneCore/Components/RCExportingComponent.h>
namespace AZ
{
namespace SceneAPI
{
namespace SceneCore
{
void RCExportingComponent::Activate()
{
ActivateBindings();
}
void RCExportingComponent::Deactivate()
{
DeactivateBindings();
}
void RCExportingComponent::Reflect(ReflectContext* context)
{
SerializeContext* serializeContext = azrtti_cast<SerializeContext*>(context);
if (serializeContext)
{
serializeContext->Class<RCExportingComponent, AZ::Component>()->Version(2);
}
}
} // namespace SceneCore
} // namespace SceneAPI
} // namespace AZ
@@ -0,0 +1,45 @@
/*
* 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/Component/Component.h>
#include <SceneAPI/SceneCore/SceneCoreConfiguration.h>
#include <SceneAPI/SceneCore/Events/CallProcessorBinder.h>
namespace AZ
{
namespace SceneAPI
{
namespace SceneCore
{
// Component used to support legacy systems. Use ExportingComponent for any new
// development.
class SCENE_CORE_CLASS RCExportingComponent
: public AZ::Component
, public Events::CallProcessorBinder
{
public:
AZ_COMPONENT(RCExportingComponent, "{128286A3-41EF-4910-8C62-E9EECA43C4EF}", Events::CallProcessorBinder);
RCExportingComponent() = default;
~RCExportingComponent() override = default;
SCENE_CORE_API void Activate() override;
SCENE_CORE_API void Deactivate() override;
static void Reflect(ReflectContext* context);
};
} // namespace SceneCore
} // namespace SceneAPI
} // namespace AZ
@@ -0,0 +1,40 @@
/*
* 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 <SceneAPI/SceneCore/Components/SceneSystemComponent.h>
namespace AZ
{
namespace SceneAPI
{
namespace SceneCore
{
void SceneSystemComponent::Activate()
{
}
void SceneSystemComponent::Deactivate()
{
}
void SceneSystemComponent::Reflect(ReflectContext* context)
{
SerializeContext* serializeContext = azrtti_cast<SerializeContext*>(context);
if (serializeContext)
{
serializeContext->Class<SceneSystemComponent, AZ::Component>()->Version(1);
}
}
} // namespace SceneCore
} // namespace SceneAPI
} // namespace AZ
@@ -0,0 +1,43 @@
/*
* 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/Component/Component.h>
#include <SceneAPI/SceneCore/SceneCoreConfiguration.h>
namespace AZ
{
namespace SceneAPI
{
namespace SceneCore
{
// Scene system components are components that can be used to create system components
// in situations where the full initialization and/or construction of regular
// system components don't apply such as in the Project Configurator's advanced
// settings and the ResourceCompilerScene.
class SCENE_CORE_CLASS SceneSystemComponent
: public AZ::Component
{
public:
AZ_COMPONENT(SceneSystemComponent, "{480FE393-A6BE-4AB9-AF91-11468AAFDB36}");
~SceneSystemComponent() override = default;
SCENE_CORE_API void Activate() override;
SCENE_CORE_API void Deactivate() override;
static void Reflect(ReflectContext* context);
};
} // namespace SceneCore
} // namespace SceneAPI
} // namespace AZ
@@ -0,0 +1,106 @@
/*
* 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/Component/ComponentApplication.h>
#include <AzCore/Component/ComponentApplicationBus.h>
#include <AzCore/Component/Entity.h>
#include <AzCore/IO/FileIO.h>
#include <AzCore/Module/ModuleManager.h>
#include <AzCore/RTTI/RTTI.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/Serialization/ObjectStream.h>
#include <SceneAPI/SceneCore/Components/SceneSystemComponent.h>
#include <SceneAPI/SceneCore/Components/Utilities/EntityConstructor.h>
#include <SceneAPI/SceneCore/Utilities/Reporting.h>
namespace AZ
{
namespace SceneAPI
{
namespace SceneCore
{
namespace EntityConstructor
{
EntityPointer BuildEntity(const char* entityName, const AZ::Uuid& baseComponentType)
{
return EntityPointer(BuildEntityRaw(entityName, baseComponentType), [](AZ::Entity* entity)
{
entity->Deactivate();
delete entity;
});
}
Entity* BuildEntityRaw(const char* entityName, const AZ::Uuid& baseComponentType)
{
SerializeContext* context = nullptr;
ComponentApplicationBus::BroadcastResult(context, &ComponentApplicationBus::Events::GetSerializeContext);
Entity* entity = aznew AZ::Entity(entityName);
if (context)
{
context->EnumerateDerived(
[entity](const AZ::SerializeContext::ClassData* data, const AZ::Uuid& /*typeId*/) -> bool
{
entity->CreateComponent(data->m_typeId);
return true;
}, baseComponentType, baseComponentType);
}
entity->Init();
entity->Activate();
return entity;
}
Entity* BuildSceneSystemEntity()
{
SerializeContext* context = nullptr;
ComponentApplicationBus::BroadcastResult(context, &ComponentApplicationBus::Events::GetSerializeContext);
if (!context)
{
AZ_TracePrintf(SceneAPI::Utilities::ErrorWindow, "Unable to retrieve serialize context.");
return nullptr;
}
// Starting all system components would be too expensive for a builder/ResourceCompiler, so only the system components needed
// for the SceneAPI will be created.
AZStd::unique_ptr<Entity> entity(aznew AZ::Entity("Scene System"));
const Uuid sceneSystemComponentType = azrtti_typeid<AZ::SceneAPI::SceneCore::SceneSystemComponent>();
context->EnumerateDerived(
[&entity](const AZ::SerializeContext::ClassData* data, const AZ::Uuid& typeId) -> bool
{
AZ_UNUSED(typeId);
// Before adding a new instance of a SceneSystemComponent, first check if the entity already has
// a component of the same type. Just like regular system components, there should only ever be
// a single instance of a SceneSystemComponent.
bool alreadyAdded = false;
for (const Component* component : entity->GetComponents())
{
if (component->RTTI_GetType() == data->m_typeId)
{
alreadyAdded = true;
break;
}
}
if (!alreadyAdded)
{
entity->CreateComponent(data->m_typeId);
}
return true;
}, sceneSystemComponentType, sceneSystemComponentType);
return entity.release();
}
} // namespace EntityConstructor
} // namespace SceneCore
} // namespace SceneAPI
} // namespace AZ
@@ -0,0 +1,37 @@
/*
* 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/std/smart_ptr/unique_ptr.h>
#include <SceneAPI/SceneCore/SceneCoreConfiguration.h>
namespace AZ
{
class Entity;
struct Uuid;
namespace SceneAPI
{
namespace SceneCore
{
namespace EntityConstructor
{
using EntityPointer = AZStd::unique_ptr<AZ::Entity, void(*)(AZ::Entity*)>;
SCENE_CORE_API EntityPointer BuildEntity(const char* entityName, const AZ::Uuid& baseComponentType);
SCENE_CORE_API Entity* BuildEntityRaw(const char* entityName, const AZ::Uuid& baseComponentType);
SCENE_CORE_API Entity* BuildSceneSystemEntity();
} // namespace EntityConstructor
} // namespace SceneCore
} // namespace SceneAPI
} // namespace AZ
@@ -0,0 +1,227 @@
/*
* 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/GraphObjectProxy.h>
#include <AzCore/Casting/numeric_cast.h>
#include <AzCore/RTTI/BehaviorContext.h>
namespace AZ
{
namespace SceneAPI
{
namespace Containers
{
void GraphObjectProxy::Reflect(AZ::ReflectContext* context)
{
AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context);
if (behaviorContext)
{
behaviorContext->Class<GraphObjectProxy>()
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
->Attribute(AZ::Script::Attributes::Module, "scene.graph")
->Method("CastWithTypeName", &GraphObjectProxy::CastWithTypeName)
->Method("Invoke", &GraphObjectProxy::Invoke)
;
}
}
GraphObjectProxy::GraphObjectProxy(AZStd::shared_ptr<const DataTypes::IGraphObject> graphObject)
{
m_graphObject = graphObject;
}
GraphObjectProxy::~GraphObjectProxy()
{
m_graphObject.reset();
m_behaviorClass = nullptr;
}
bool GraphObjectProxy::CastWithTypeName(const AZStd::string& classTypeName)
{
const AZ::BehaviorClass* behaviorClass = BehaviorContextHelper::GetClass(classTypeName);
if (behaviorClass)
{
const void* baseClass = behaviorClass->m_azRtti->Cast(m_graphObject.get(), behaviorClass->m_azRtti->GetTypeId());
if (baseClass)
{
m_behaviorClass = behaviorClass;
}
return true;
}
return false;
}
AZStd::any GraphObjectProxy::Invoke(AZStd::string_view method, AZStd::vector<AZStd::any> argList)
{
AZ::SerializeContext* serializeContext = nullptr;
AZ::ComponentApplicationBus::BroadcastResult(serializeContext, &AZ::ComponentApplicationRequests::GetSerializeContext);
if (!serializeContext)
{
AZ_Error("SceneAPI", false, "AZ::SerializeContext should be prepared.");
return AZStd::any(false);
}
if (!m_behaviorClass)
{
AZ_Warning("SceneAPI", false, "Use the CastWithTypeName() to assign the concrete type of IGraphObject to Invoke().");
return AZStd::any(false);
}
auto entry = m_behaviorClass->m_methods.find(method);
if (m_behaviorClass->m_methods.end() == entry)
{
AZ_Warning("SceneAPI", false, "Missing method %.*s from class %s",
aznumeric_cast<int>(method.size()),
method.data(),
m_behaviorClass->m_name.c_str());
return AZStd::any(false);
}
AZ::BehaviorMethod* behaviorMethod = entry->second;
constexpr size_t behaviorParamListSize = 8;
if (behaviorMethod->GetNumArguments() > behaviorParamListSize)
{
AZ_Error("SceneAPI", false, "Unsupported behavior method; supports max %zu but %s has %zu argument slots",
behaviorParamListSize,
behaviorMethod->m_name.c_str(),
behaviorMethod->GetNumArguments());
return AZStd::any(false);
}
AZ::BehaviorValueParameter behaviorParamList[behaviorParamListSize];
// detect if the method passes in a "this" pointer which can be true if the method is a member function
// or if the first argument is the same as the behavior class such as from a lambda function
bool hasSelfPointer = behaviorMethod->IsMember();
if (!hasSelfPointer)
{
hasSelfPointer = behaviorMethod->GetArgument(0)->m_typeId == m_behaviorClass->m_typeId;
}
// record the "this" pointer's metadata like its RTTI so that it can be
// down casted to a parent class type if needed to invoke a parent method
if (const AZ::BehaviorParameter* thisInfo = behaviorMethod->GetArgument(0); hasSelfPointer)
{
// avoiding the "Special handling for the generic object holder." since it assumes
// the BehaviorObject.m_value is a pointer; the reference version is already dereferenced
AZ::BehaviorValueParameter theThisPointer;
const void* self = reinterpret_cast<const void*>(m_graphObject.get());
if ((thisInfo->m_traits & AZ::BehaviorParameter::TR_POINTER) == AZ::BehaviorParameter::TR_POINTER)
{
theThisPointer.m_value = &self;
}
else
{
theThisPointer.m_value = const_cast<void*>(self);
}
theThisPointer.Set(*thisInfo);
behaviorParamList[0].Set(theThisPointer);
}
int paramCount = 0;
for (; paramCount < argList.size() && paramCount < behaviorMethod->GetNumArguments(); ++paramCount)
{
size_t behaviorArgIndex = hasSelfPointer ? paramCount + 1 : paramCount;
const AZ::BehaviorParameter* argBehaviorInfo = behaviorMethod->GetArgument(behaviorArgIndex);
if (!Convert(argList[paramCount], argBehaviorInfo, behaviorParamList[behaviorArgIndex]))
{
AZ_Error("SceneAPI", false, "Could not convert from %s to %s at index %zu",
argBehaviorInfo->m_typeId.ToString<AZStd::string>().c_str(),
behaviorParamList[behaviorArgIndex].m_typeId.ToString<AZStd::string>().c_str(),
paramCount);
return AZStd::any(false);
}
}
if (hasSelfPointer)
{
++paramCount;
}
AZ::BehaviorValueParameter returnBehaviorValue;
if (behaviorMethod->HasResult())
{
returnBehaviorValue.Set(*behaviorMethod->GetResult());
returnBehaviorValue.m_value =
returnBehaviorValue.m_tempData.allocate(returnBehaviorValue.m_azRtti->GetTypeSize(), 16);
}
if (!entry->second->Call(behaviorParamList, paramCount, &returnBehaviorValue))
{
return AZStd::any(false);
}
if (!behaviorMethod->HasResult())
{
return AZStd::any(true);
}
// Create temporary any to get its type info to construct a new AZStd::any with new data
AZStd::any tempAny = serializeContext->CreateAny(returnBehaviorValue.m_typeId);
return AZStd::move(AZStd::any(returnBehaviorValue.m_value, tempAny.get_type_info()));
}
template <typename FROM, typename TO>
bool ConvertFromTo(AZStd::any& input, const AZ::BehaviorParameter* argBehaviorInfo, AZ::BehaviorValueParameter& behaviorParam)
{
if (input.get_type_info().m_id != azrtti_typeid<FROM>())
{
return false;
}
if (argBehaviorInfo->m_typeId != azrtti_typeid<TO>())
{
return false;
}
TO* storage = reinterpret_cast<TO*>(behaviorParam.m_tempData.allocate(argBehaviorInfo->m_azRtti->GetTypeSize(), 16));
*storage = aznumeric_cast<TO>(*AZStd::any_cast<FROM>(&input));
behaviorParam.m_typeId = azrtti_typeid<TO>();
behaviorParam.m_value = storage;
return true;
}
bool GraphObjectProxy::Convert(AZStd::any& input, const AZ::BehaviorParameter* argBehaviorInfo, AZ::BehaviorValueParameter& behaviorParam)
{
if (input.get_type_info().m_id == argBehaviorInfo->m_typeId)
{
behaviorParam.m_typeId = input.get_type_info().m_id;
behaviorParam.m_value = AZStd::any_cast<void>(&input);
return true;
}
#define CONVERT_ANY_NUMERIC(TYPE) ( \
ConvertFromTo<TYPE, double>(input, argBehaviorInfo, behaviorParam) || \
ConvertFromTo<TYPE, float>(input, argBehaviorInfo, behaviorParam) || \
ConvertFromTo<TYPE, AZ::s8>(input, argBehaviorInfo, behaviorParam) || \
ConvertFromTo<TYPE, AZ::u8>(input, argBehaviorInfo, behaviorParam) || \
ConvertFromTo<TYPE, AZ::s16>(input, argBehaviorInfo, behaviorParam) || \
ConvertFromTo<TYPE, AZ::u16>(input, argBehaviorInfo, behaviorParam) || \
ConvertFromTo<TYPE, AZ::s32>(input, argBehaviorInfo, behaviorParam) || \
ConvertFromTo<TYPE, AZ::u32>(input, argBehaviorInfo, behaviorParam) || \
ConvertFromTo<TYPE, AZ::s64>(input, argBehaviorInfo, behaviorParam) || \
ConvertFromTo<TYPE, AZ::u64>(input, argBehaviorInfo, behaviorParam) )
if (CONVERT_ANY_NUMERIC(double) || CONVERT_ANY_NUMERIC(float) ||
CONVERT_ANY_NUMERIC(AZ::s8) || CONVERT_ANY_NUMERIC(AZ::u8) ||
CONVERT_ANY_NUMERIC(AZ::s16) || CONVERT_ANY_NUMERIC(AZ::u16) ||
CONVERT_ANY_NUMERIC(AZ::s32) || CONVERT_ANY_NUMERIC(AZ::u32) ||
CONVERT_ANY_NUMERIC(AZ::s64) || CONVERT_ANY_NUMERIC(AZ::u64) )
{
return true;
}
#undef CONVERT_ANY_NUMERIC
return false;
}
} // Containers
} // SceneAPI
} // AZ
@@ -0,0 +1,51 @@
/*
* 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/Serialization/SerializeContext.h>
#include <SceneAPI/SceneCore/DataTypes/IGraphObject.h>
namespace AZ
{
namespace SceneAPI
{
namespace Containers
{
//
// GraphObjectProxy wraps the smart pointer to IGraphObject privately
// so that scripts can access the "graph node content" inside the SceneGraph
//
class GraphObjectProxy final
{
public:
AZ_RTTI(GraphObjectProxy, "{3EF0DDEC-C734-4804-BE99-82058FEBDA71}");
AZ_CLASS_ALLOCATOR(GraphObjectProxy, AZ::SystemAllocator, 0);
static void Reflect(AZ::ReflectContext* context);
GraphObjectProxy(AZStd::shared_ptr<const DataTypes::IGraphObject> graphObject);
~GraphObjectProxy();
bool CastWithTypeName(const AZStd::string& classTypeName);
AZStd::any Invoke(AZStd::string_view method, AZStd::vector<AZStd::any> argList);
protected:
bool Convert(AZStd::any& input, const AZ::BehaviorParameter* argBehaviorInfo, AZ::BehaviorValueParameter& behaviorParam);
private:
AZStd::shared_ptr<const DataTypes::IGraphObject> m_graphObject;
const AZ::BehaviorClass* m_behaviorClass = nullptr;
};
} // Containers
} // SceneAPI
} // AZ
@@ -0,0 +1,159 @@
/*
* 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/ReflectContext.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/Serialization/EditContext.h>
#include <SceneAPI/SceneCore/Utilities/Reporting.h>
#include <SceneAPI/SceneCore/Containers/RuleContainer.h>
namespace AZ
{
namespace SceneAPI
{
namespace Containers
{
size_t RuleContainer::GetRuleCount() const
{
return m_rules.size();
}
AZStd::shared_ptr<DataTypes::IRule> RuleContainer::GetRule(size_t index) const
{
AZ_Assert(index < m_rules.size(), "Cannot get rule. Index %i is out of range.", index);
if (index >= m_rules.size())
{
return nullptr;
}
return m_rules[index];
}
void RuleContainer::AddRule(const AZStd::shared_ptr<DataTypes::IRule>& rule)
{
AZ_Assert(AZStd::find(m_rules.begin(), m_rules.end(), rule) == m_rules.end(), "Unable to add rule as it's already been added.");
m_rules.push_back(rule);
}
void RuleContainer::AddRule(AZStd::shared_ptr<DataTypes::IRule>&& rule)
{
AZ_Assert(AZStd::find(m_rules.begin(), m_rules.end(), rule) == m_rules.end(), "Unable to add rule as it's already been added.");
m_rules.push_back(rule);
}
void RuleContainer::RemoveRule(size_t index)
{
if (index < m_rules.size())
{
m_rules.erase(m_rules.begin() + index);
}
}
void RuleContainer::RemoveRule(const AZStd::shared_ptr<DataTypes::IRule>& rule)
{
auto it = AZStd::find(m_rules.begin(), m_rules.end(), rule);
if (it != m_rules.end())
{
m_rules.erase(it);
}
}
void RuleContainer::Reflect(ReflectContext* context)
{
SerializeContext* serializeContext = azrtti_cast<SerializeContext*>(context);
if (!serializeContext)
{
return;
}
serializeContext->Class<RuleContainer>()
->Version(1)
->Field("rules", &RuleContainer::m_rules);
EditContext* editContext = serializeContext->GetEditContext();
if (editContext)
{
editContext->Class<RuleContainer>("Rule Container", "Description.")
->DataElement(AZ_CRC("ManifestVector", 0x895aa9aa), &RuleContainer::m_rules, "", "Add or remove entries to fine-tune source file processing.")
->Attribute(AZ::Edit::Attributes::ContainerCanBeModified, false)
->Attribute(AZ_CRC("CollectionName", 0xbbc1c898), "Modifiers")
->Attribute(AZ_CRC("ObjectTypeName", 0x6559e0c0), "Modifier")
->ElementAttribute(AZ::Edit::Attributes::Visibility, AZ_CRC("PropertyVisibility_Hide", 0x32ab90f7));
}
}
// Previously, groups stored the vector of shared pointers of rules. We moved the vector of shared pointers of rules to the RuleContainer and
// groups now have a RuleContainer as a member. This version converter converts from groups holding the vector
bool RuleContainer::VectorToRuleContainerConverter(SerializeContext& context, SerializeContext::DataElementNode& classElement)
{
int elementIndex = classElement.FindElement(AZ_CRC("rules", 0x899a993c));
if (elementIndex >= 0)
{
AZ::SerializeContext::DataElementNode& rulesElement = classElement.GetSubElement(elementIndex);
// Clone the rule elements.
AZStd::vector<AZ::SerializeContext::DataElementNode> rules;
const int numSubElements = rulesElement.GetNumSubElements();
rules.reserve(numSubElements);
for (int i = 0; i < numSubElements; i++)
{
AZ::SerializeContext::DataElementNode& sharedPtrElement = rulesElement.GetSubElement(i);
if (sharedPtrElement.GetNumSubElements() > 0)
{
AZ::SerializeContext::DataElementNode& ruleElement = sharedPtrElement.GetSubElement(0);
rules.push_back(ruleElement);
}
}
// Remove the original rule vector element.
classElement.RemoveElement(elementIndex);
// Add a new rule container element.
const int ruleContainerIndex = classElement.AddElement<RuleContainer>(context, "rules");
if (ruleContainerIndex >= 0)
{
AZ::SerializeContext::DataElementNode& ruleContainerElement = classElement.GetSubElement(ruleContainerIndex);
// Create a rule vector element.
const int rulesVectorIndex = ruleContainerElement.AddElement<AZStd::vector<AZStd::shared_ptr<DataTypes::IRule>>>(context, "rules");
AZ::SerializeContext::DataElementNode& ruleVectorElement = ruleContainerElement.GetSubElement(rulesVectorIndex);
// Add the copied rules to the rule vector element.
for (SerializeContext::DataElementNode& rule : rules)
{
int valueIndex = ruleVectorElement.AddElement<AZStd::shared_ptr<DataTypes::IRule>>(context, "element");
SerializeContext::DataElementNode& pointerNode = ruleVectorElement.GetSubElement(valueIndex);
pointerNode.AddElement(rule);
}
}
}
return true;
}
} // Containers
} // SceneAPI
} // AZ
@@ -0,0 +1,71 @@
/*
* 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/Serialization/SerializeContext.h>
#include <AzCore/std/containers/vector.h>
#include <AzCore/std/smart_ptr/shared_ptr.h>
#include <SceneAPI/SceneCore/DataTypes/Rules/IRule.h>
#include <SceneAPI/SceneCore/SceneCoreConfiguration.h>
namespace AZ
{
class ReflectContext;
namespace SceneAPI
{
namespace Containers
{
class RuleContainer
{
public:
AZ_RTTI(RuleContainer, "{2C20D3DF-57FF-4A31-8680-A4D45302B9CF}");
virtual ~RuleContainer() {}
SCENE_CORE_API size_t GetRuleCount() const;
SCENE_CORE_API AZStd::shared_ptr<DataTypes::IRule> GetRule(size_t index) const;
/**
* Find the first rule of the template type.
* @result The first rule of the template type. nullptr if not found.
*/
template<typename T>
AZStd::shared_ptr<T> FindFirstByType() const;
/**
* Check if there is a rule of the given template type.
* @result True in case a rule of the given template type got found, false if not.
*/
template<typename T>
bool ContainsRuleOfType() const;
SCENE_CORE_API void AddRule(const AZStd::shared_ptr<DataTypes::IRule>& rule);
SCENE_CORE_API void AddRule(AZStd::shared_ptr<DataTypes::IRule>&& rule);
SCENE_CORE_API void RemoveRule(size_t index);
SCENE_CORE_API void RemoveRule(const AZStd::shared_ptr<DataTypes::IRule>& rule);
static void Reflect(ReflectContext* context);
static SCENE_CORE_API bool VectorToRuleContainerConverter(AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement);
private:
AZStd::vector<AZStd::shared_ptr<DataTypes::IRule>> m_rules;
};
} // Containers
} // SceneAPI
} // AZ
#include <SceneAPI/SceneCore/Containers/RuleContainer.inl>
@@ -0,0 +1,58 @@
/*
* 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/RuleContainer.h>
namespace AZ
{
namespace SceneAPI
{
namespace Containers
{
template<typename T>
AZStd::shared_ptr<T> RuleContainer::FindFirstByType() const
{
static_assert(AZStd::is_base_of<DataTypes::IRule, T>::value, "Specified type T is not derived from IRule.");
for (const AZStd::shared_ptr<DataTypes::IRule>& rule : m_rules)
{
if (rule && rule->RTTI_IsTypeOf(T::TYPEINFO_Uuid()))
{
return AZStd::static_pointer_cast<T>(rule);
}
}
return AZStd::shared_ptr<T>();
}
template<typename T>
bool RuleContainer::ContainsRuleOfType() const
{
static_assert(AZStd::is_base_of<DataTypes::IRule, T>::value, "Specified type T is not derived from IRule.");
for (const AZStd::shared_ptr<DataTypes::IRule>& rule : m_rules)
{
if (rule && rule->RTTI_IsTypeOf(T::TYPEINFO_Uuid()))
{
return true;
}
}
return false;
}
} // Containers
} // SceneAPI
} // AZ
@@ -0,0 +1,134 @@
/*
* 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/Scene.h>
#include <AzCore/RTTI/BehaviorContext.h>
namespace AZ
{
namespace SceneAPI
{
namespace Containers
{
Scene::Scene(const AZStd::string& name)
: m_name(name)
{
}
Scene::Scene(AZStd::string&& name)
: m_name(AZStd::move(name))
{
}
void Scene::SetSource(const AZStd::string& filename, const Uuid& guid)
{
m_sourceFilename = filename;
m_sourceGuid = guid;
}
void Scene::SetSource(AZStd::string&& filename, const Uuid& guid)
{
m_sourceFilename = AZStd::move(filename);
m_sourceGuid = guid;
}
const AZStd::string& Scene::GetSourceFilename() const
{
return m_sourceFilename;
}
const Uuid& Scene::GetSourceGuid() const
{
return m_sourceGuid;
}
void Scene::SetManifestFilename(const AZStd::string& name)
{
m_manifestFilename = name;
}
void Scene::SetManifestFilename(AZStd::string&& name)
{
m_manifestFilename = AZStd::move(name);
}
const AZStd::string& Scene::GetManifestFilename() const
{
return m_manifestFilename;
}
SceneGraph& Scene::GetGraph()
{
return m_graph;
}
const SceneGraph& Scene::GetGraph() const
{
return m_graph;
}
SceneManifest& Scene::GetManifest()
{
return m_manifest;
}
const SceneManifest& Scene::GetManifest() const
{
return m_manifest;
}
const AZStd::string& Scene::GetName() const
{
return m_name;
}
void Scene::SetOriginalSceneOrientation(SceneOrientation orientation)
{
m_originalOrientation = orientation;
}
Scene::SceneOrientation Scene::GetOriginalSceneOrientation() const
{
return m_originalOrientation;
}
void Scene::Reflect(ReflectContext* context)
{
AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context);
if (behaviorContext)
{
behaviorContext->Class<Scene>()
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
->Attribute(AZ::Script::Attributes::Module, "scene")
->Property("name", BehaviorValueGetter(&Scene::m_name), nullptr)
->Property("manifestFilename", BehaviorValueGetter(&Scene::m_manifestFilename), nullptr)
->Property("sourceFilename", BehaviorValueGetter(&Scene::m_sourceFilename), nullptr)
->Property("sourceGuid", BehaviorValueGetter(&Scene::m_sourceGuid), nullptr)
->Property("graph", BehaviorValueGetter(&Scene::m_graph), nullptr)
->Property("manifest", BehaviorValueGetter(&Scene::m_manifest), nullptr)
->Constant("SceneOrientation_YUp", BehaviorConstant(SceneOrientation::YUp))
->Constant("SceneOrientation_ZUp", BehaviorConstant(SceneOrientation::ZUp))
->Constant("SceneOrientation_XUp", BehaviorConstant(SceneOrientation::XUp))
->Constant("SceneOrientation_NegXUp", BehaviorConstant(SceneOrientation::NegXUp))
->Constant("SceneOrientation_NegYUp", BehaviorConstant(SceneOrientation::NegYUp))
->Constant("SceneOrientation_NegZUp", BehaviorConstant(SceneOrientation::NegZUp))
->Method("GetOriginalSceneOrientation", [](Scene* self) -> int
{
return aznumeric_cast<int>(self->GetOriginalSceneOrientation());
})
;
}
}
} // Containers
} // SceneAPI
} // AZ
@@ -0,0 +1,74 @@
#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/Containers/SceneGraph.h>
#include <SceneAPI/SceneCore/Containers/SceneManifest.h>
#include <SceneAPI/SceneCore/SceneCoreConfiguration.h>
namespace AZ
{
namespace SceneAPI
{
namespace Containers
{
// Scenes are used to store the scene's graph the hierarchy and the manifest for meta data as well
// as a history of the files used to construct both.
class SCENE_CORE_API Scene
{
public:
AZ_TYPE_INFO(Scene, "{1F2E6142-B0D8-42C6-A6E5-CD726DAA9EF0}");
explicit Scene(const AZStd::string& name);
explicit Scene(AZStd::string&& name);
void SetSource(const AZStd::string& filename, const Uuid& guid);
void SetSource(AZStd::string&& filename, const Uuid& guid);
const AZStd::string& GetSourceFilename() const;
const Uuid& GetSourceGuid() const;
void SetManifestFilename(const AZStd::string& name);
void SetManifestFilename(AZStd::string&& name);
const AZStd::string& GetManifestFilename() const;
SceneGraph& GetGraph();
const SceneGraph& GetGraph() const;
SceneManifest& GetManifest();
const SceneManifest& GetManifest() const;
const AZStd::string& GetName() const;
enum class SceneOrientation {YUp, ZUp, XUp, NegYUp, NegZUp, NegXUp};
void SetOriginalSceneOrientation(SceneOrientation orientation);
SceneOrientation GetOriginalSceneOrientation() const;
static void Reflect(ReflectContext* context);
private:
// Disabling export warnings for private methods, clients wont have access to them
AZ_PUSH_DISABLE_WARNING(4251, "-Wunknown-warning-option")
AZStd::string m_name;
AZStd::string m_manifestFilename;
AZStd::string m_sourceFilename;
Uuid m_sourceGuid;
SceneGraph m_graph;
SceneManifest m_manifest;
SceneOrientation m_originalOrientation = SceneOrientation::YUp;
AZ_POP_DISABLE_OVERRIDE_WARNING
};
} // Containers
} // SceneAPI
} // AZ
@@ -0,0 +1,369 @@
/*
* 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/Casting/numeric_cast.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzFramework/StringFunc/StringFunc.h>
#include <SceneAPI/SceneCore/Containers/SceneGraph.h>
#include <SceneAPI/SceneCore/Containers/GraphObjectProxy.h>
namespace AZ
{
namespace SceneAPI
{
namespace Containers
{
const SceneGraph::NodeIndex::IndexType SceneGraph::NodeIndex::INVALID_INDEX;
static_assert(sizeof(SceneGraph::NodeIndex::IndexType) >= ((SceneGraph::NodeHeader::INDEX_BIT_COUNT / 8) + 1),
"SceneGraph::NodeIndex is not big enough to store the parent index of a SceneGraph::NodeHeader");
//
// SceneGraph
//
SceneGraph::SceneGraph()
{
AddDefaultRoot();
}
void SceneGraph::Reflect(AZ::ReflectContext* context)
{
GraphObjectProxy::Reflect(context);
AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context);
if (behaviorContext)
{
behaviorContext->Class<SceneGraph>()
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
->Attribute(AZ::Script::Attributes::Module, "scene.graph")
// static methods
->Method("IsValidName", [](const char* name) { return SceneGraph::IsValidName(name); })
->Method("GetNodeSeperationCharacter", &SceneGraph::GetNodeSeperationCharacter)
// instance methods
->Method("GetNodeName", &SceneGraph::GetNodeName)
->Method("GetRoot", &SceneGraph::GetRoot)
->Method("HasNodeContent", &SceneGraph::HasNodeContent)
->Method("HasNodeSibling", &SceneGraph::HasNodeSibling)
->Method("HasNodeChild", &SceneGraph::HasNodeChild)
->Method("HasNodeParent", &SceneGraph::HasNodeParent)
->Method("IsNodeEndPoint", &SceneGraph::IsNodeEndPoint)
->Method("GetNodeParent", [](const SceneGraph& self, NodeIndex node) { return self.GetNodeParent(node); })
->Method("GetNodeSibling", [](const SceneGraph& self, NodeIndex node) { return self.GetNodeSibling(node); })
->Method("GetNodeChild", [](const SceneGraph& self, NodeIndex node) { return self.GetNodeChild(node); })
->Method("GetNodeCount", &SceneGraph::GetNodeCount)
->Method("FindWithPath", [](const SceneGraph& self, const AZStd::string& path)
{
return self.Find(path);
})
->Method("FindWithRootAndPath", [](const SceneGraph& self, NodeIndex root, const AZStd::string& path)
{
return self.Find(root, path);
})
->Method("GetNodeContent", [](const SceneGraph& self, NodeIndex node) -> GraphObjectProxy*
{
auto graphObject = self.GetNodeContent(node);
if (graphObject)
{
GraphObjectProxy* proxy = aznew GraphObjectProxy(graphObject);
return proxy;
}
return nullptr;
})
;
behaviorContext->Class<SceneGraph::NodeIndex>()
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
->Attribute(AZ::Script::Attributes::Module, "scene.graph")
->Method("AsNumber", &SceneGraph::NodeIndex::AsNumber)
->Method("Distance", &SceneGraph::NodeIndex::Distance)
->Method("IsValid", &SceneGraph::NodeIndex::IsValid)
->Method("Equal", &SceneGraph::NodeIndex::operator==)
->Attribute(AZ::Script::Attributes::Operator, AZ::Script::Attributes::OperatorType::Equal)
;
behaviorContext->Class<SceneGraph::Name>()
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
->Attribute(AZ::Script::Attributes::Module, "scene.graph")
->Method("GetPath", &SceneGraph::Name::GetPath)
->Method("GetName", &SceneGraph::Name::GetName)
;
}
}
SceneGraph::NodeIndex SceneGraph::Find(const char* path) const
{
auto location = FindNameLookupIterator(path);
return NodeIndex(location != m_nameLookup.end() ? (*location).second : NodeIndex::INVALID_INDEX);
}
SceneGraph::NodeIndex SceneGraph::Find(NodeIndex root, const char* name) const
{
if (root.m_value < m_names.size())
{
AZStd::string fullname = CombineName(m_names[root.m_value].GetPath(), name);
return Find(fullname);
}
return NodeIndex();
}
const SceneGraph::Name& SceneGraph::GetNodeName(NodeIndex node) const
{
if (node.m_value < m_names.size())
{
return m_names[node.m_value];
}
else
{
static Name invalidNodeName(AZStd::string("<Invalid>"), 0);
return invalidNodeName;
}
}
SceneGraph::NodeIndex SceneGraph::AddChild(NodeIndex parent, const char* name)
{
return AddChild(parent, name, AZStd::shared_ptr<DataTypes::IGraphObject>(nullptr));
}
SceneGraph::NodeIndex SceneGraph::AddChild(NodeIndex parent, const char* name, const AZStd::shared_ptr<DataTypes::IGraphObject>& content)
{
return AddChild(parent, name, AZStd::shared_ptr<DataTypes::IGraphObject>(content));
}
SceneGraph::NodeIndex SceneGraph::AddChild(NodeIndex parent, const char* name, AZStd::shared_ptr<DataTypes::IGraphObject>&& content)
{
if (parent.m_value < m_hierarchy.size())
{
NodeHeader& parentNode = m_hierarchy[parent.m_value];
if (parentNode.HasChild())
{
return AddSibling(NodeIndex(parentNode.m_childIndex), name, AZStd::move(content));
}
else
{
return NodeIndex(AppendChild(parent.m_value, name, AZStd::move(content)));
}
}
return NodeIndex();
}
SceneGraph::NodeIndex SceneGraph::AddSibling(NodeIndex sibling, const char* name)
{
return AddSibling(sibling, name, AZStd::shared_ptr<DataTypes::IGraphObject>(nullptr));
}
SceneGraph::NodeIndex SceneGraph::AddSibling(NodeIndex sibling, const char* name, const AZStd::shared_ptr<DataTypes::IGraphObject>& content)
{
return AddSibling(sibling, name, AZStd::shared_ptr<DataTypes::IGraphObject>(content));
}
SceneGraph::NodeIndex SceneGraph::AddSibling(NodeIndex sibling, const char* name, AZStd::shared_ptr<DataTypes::IGraphObject>&& content)
{
if (sibling.m_value < m_hierarchy.size())
{
NodeIndex::IndexType siblingIndex = sibling.m_value;
while (m_hierarchy[siblingIndex].HasSibling())
{
siblingIndex = m_hierarchy[siblingIndex].m_siblingIndex;
}
return NodeIndex(AppendSibling(siblingIndex, name, AZStd::move(content)));
}
return NodeIndex();
}
bool SceneGraph::SetContent(NodeIndex node, const AZStd::shared_ptr<DataTypes::IGraphObject>& content)
{
if (node.m_value < m_content.size())
{
m_content[node.m_value] = content;
return true;
}
return false;
}
bool SceneGraph::SetContent(NodeIndex node, AZStd::shared_ptr<DataTypes::IGraphObject>&& content)
{
if (node.m_value < m_content.size())
{
m_content[node.m_value] = AZStd::move(content);
return true;
}
return false;
}
bool SceneGraph::MakeEndPoint(NodeIndex node)
{
if (node.m_value < m_hierarchy.size())
{
m_hierarchy[node.m_value].m_isEndPoint = 1;
return true;
}
return false;
}
void SceneGraph::Clear()
{
m_nameLookup.clear();
m_hierarchy.clear();
m_names.clear();
m_content.clear();
AddDefaultRoot();
}
bool SceneGraph::IsValidName(const char* name)
{
if (!name)
{
return false;
}
if (name[0] == 0)
{
return false;
}
const char* current = name;
while (*current)
{
if (*current++ == s_nodeSeperationCharacter)
{
return false;
}
}
return true;
}
char SceneGraph::GetNodeSeperationCharacter()
{
return s_nodeSeperationCharacter;
}
SceneGraph::NodeIndex::IndexType SceneGraph::AppendChild(NodeIndex::IndexType parent, const char* name, AZStd::shared_ptr<DataTypes::IGraphObject>&& content)
{
if (parent < m_hierarchy.size())
{
NodeHeader parentNode = m_hierarchy[parent];
AZ_Assert(!parentNode.HasChild(), "Child '%s' couldn't be added as the target parent already contains a child.", name);
AZ_Assert(!parentNode.IsEndPoint(), "Attempting to add a child '%s' to node which is marked as an end point.", name);
if (!parentNode.HasChild() && !parentNode.IsEndPoint())
{
NodeIndex::IndexType nodeIndex = AppendNode(parent, name, AZStd::move(content));
m_hierarchy[parent].m_childIndex = nodeIndex;
return nodeIndex;
}
}
return NodeIndex::INVALID_INDEX;
}
SceneGraph::NodeIndex::IndexType SceneGraph::AppendSibling(NodeIndex::IndexType sibling, const char* name, AZStd::shared_ptr<DataTypes::IGraphObject>&& content)
{
if (sibling < m_hierarchy.size())
{
NodeHeader siblingNode = m_hierarchy[sibling];
AZ_Assert(!siblingNode.HasSibling(), "Sibling '%s' couldn't be added as the target node already contains a sibling.", name);
if (!siblingNode.HasSibling())
{
NodeIndex::IndexType nodeIndex = AppendNode(siblingNode.m_parentIndex, name, AZStd::move(content));
m_hierarchy[sibling].m_siblingIndex = nodeIndex;
return nodeIndex;
}
}
return NodeIndex::INVALID_INDEX;
}
SceneGraph::NodeIndex::IndexType SceneGraph::AppendNode(NodeIndex::IndexType parentIndex, const char* name, AZStd::shared_ptr<DataTypes::IGraphObject>&& content)
{
NodeIndex::IndexType nodeIndex = aznumeric_caster(m_hierarchy.size());
NodeHeader node;
node.m_parentIndex = parentIndex;
m_hierarchy.push_back(node);
AZ_Assert(IsValidName(name), "Name '%s' for SceneGraph sibling contains invalid characters", name);
AZStd::string fullName;
size_t nameOffset;
if (parentIndex != NodeHeader::INVALID_INDEX)
{
const Name& parentName = m_names[parentIndex];
fullName = CombineName(parentName.GetPath(), name);
nameOffset = parentName.GetPathLength() + (parentName.GetPathLength() != 0 ? 1 : 0);
}
else
{
fullName = name;
nameOffset = 0;
}
StringHash fullNameHash = StringHasher()(fullName);
AZ_Assert(FindNameLookupIterator(fullNameHash, fullName.c_str()) == m_nameLookup.end(), "Duplicate name found in SceneGraph: %s", fullName.c_str());
m_nameLookup.insert(NameLookup::value_type(fullNameHash, nodeIndex));
m_names.emplace_back(AZStd::move(fullName), nameOffset);
AZ_Assert(m_hierarchy.size() == m_names.size(),
"Hierarchy and name lists in SceneGraph have gone out of sync. (%i vs. %i)", m_hierarchy.size(), m_names.size());
m_content.push_back(AZStd::move(content));
AZ_Assert(m_hierarchy.size() == m_content.size(),
"Hierarchy and data lists in SceneGraph have gone out of sync. (%i vs. %i)", m_hierarchy.size(), m_content.size());
return nodeIndex;
}
SceneGraph::NameLookup::const_iterator SceneGraph::FindNameLookupIterator(const char* name) const
{
StringHash hash = StringHasher()(name);
return FindNameLookupIterator(hash, name);
}
SceneGraph::NameLookup::const_iterator SceneGraph::FindNameLookupIterator(StringHash hash, const char* name) const
{
auto range = m_nameLookup.equal_range(hash);
// Always check the name, even if there's only one entry as the hash can be a clash with
// the single entry.
for (auto it = range.first; it != range.second; ++it)
{
if (AzFramework::StringFunc::Equal(m_names[it->second].GetPath(), name, true))
{
return it;
}
}
return m_nameLookup.end();
}
AZStd::string SceneGraph::CombineName(const char* path, const char* name) const
{
AZStd::string result = path;
if (result.length() > 0)
{
result += s_nodeSeperationCharacter;
}
result += name;
return result;
}
void SceneGraph::AddDefaultRoot()
{
AZ_Assert(m_hierarchy.size() == 0, "Adding a default root node to a SceneGraph with content.");
m_hierarchy.push_back(NodeHeader());
m_nameLookup.insert(NameLookup::value_type(StringHasher()(""), 0));
m_names.emplace_back("", 0);
m_content.emplace_back(nullptr);
}
} // Containers
} // SceneAPI
} // AZ
@@ -0,0 +1,289 @@
#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 <stdint.h>
#include <AzCore/std/hash.h>
#include <AzCore/std/containers/vector.h>
#include <AzCore/std/containers/unordered_map.h>
#include <AzCore/std/smart_ptr/shared_ptr.h>
#include <AzCore/std/string/string.h>
#include <AzCore/RTTI/TypeInfo.h>
#include <AzCore/RTTI/ReflectContext.h>
#include <SceneAPI/SceneCore/SceneCoreConfiguration.h>
#include <SceneAPI/SceneCore/Containers/Views/View.h>
#include <SceneAPI/SceneCore/Containers/Views/ConvertIterator.h>
namespace AZ
{
namespace SceneAPI
{
namespace DataTypes
{
class IGraphObject;
}
namespace FbxSceneBuilder
{
struct QueueNode;
struct ImportContext;
}
namespace Containers
{
// The SceneGraph allows for hierarchical storage of arbitrary data in a tree like fashion.
// The internal storage is based on child-sibling representation: https://en.wikipedia.org/wiki/Left-child_right-sibling_binary_tree
//
// The SceneGraph uses a naming convention where the name of a node is concatenated with it's parent and separate by a dot ('.')
// such that child node B of parent node A will have the name "A.B". Note that by default the scene graph has a nameless root node.
//
// There are 2 approaches to manipulating the SceneGraph. The first is direct manipulation by using NodeIndex. This supports
// navigating the graph, manipulating the graph hierarchy and manipulating the stored values. This approach is the most
// flexible and allows for the most control, but requires a lot of code support. This approach is best use while constructing
// the graph for a scene.
// The second option is by combining views. This allows for navigating the graph and manipulating stored values, but not
// for manipulating the graph hierarchy. Views use iterators and can therefore be used in most STL(-like) algorithms as well
// as ranged based loops, but have restrictions in what they can do. This approach is best used while inspecting or exporting
// the graph for a scene.
class SceneGraph
{
public:
// Index for a node.
// Instead of using just a plain int, this is it's own type to reduce the
// risk of invalid indices being passed.
class NodeIndex
{
friend class SceneGraph;
friend struct FbxSceneBuilder::QueueNode;
friend struct FbxSceneBuilder::ImportContext;
public:
// Type needs to be able to store an index in a NodeHeader (currently 21-bits).
using IndexType = uint32_t;
NodeIndex(const NodeIndex& rhs) = default;
NodeIndex& operator=(const NodeIndex& rhs) = default;
// Returns whether or not the node index is valid.
// Note that this function reports explicit invalid nodes, such as the invalid node that's returned when a name can't be found, and
// whether it's valid before any changes are made. If changes to the SceneGraph are made it will not be able to detect that a
// previously valid index has become invalid.
inline bool IsValid() const;
inline bool operator==(NodeIndex rhs) const;
inline bool operator!=(NodeIndex rhs) const;
inline IndexType AsNumber() const;
inline s32 Distance(NodeIndex rhs) const;
private:
static const IndexType INVALID_INDEX = static_cast<IndexType>(-1);
inline NodeIndex();
inline explicit NodeIndex(IndexType value);
IndexType m_value;
};
// NodeHeader contains the relationship a node has with its surrounding nodes and additional information about a node.
// Note that this is always passed by value, so direct access to the member variables doesn't risk unwanted changes.
struct NodeHeader
{
// Number of bits used for storing an index into the stored data. Currently 21 bits, which will support about 2 million nodes.
static const uint32_t INDEX_BIT_COUNT = 21;
static const uint64_t INVALID_INDEX = (1 << INDEX_BIT_COUNT) - 1; // Largest possible value for the index bit count.
// End point nodes are nodes that are not allowed to have children.
uint64_t m_isEndPoint : 1;
uint64_t m_parentIndex: INDEX_BIT_COUNT;
uint64_t m_siblingIndex: INDEX_BIT_COUNT;
uint64_t m_childIndex: INDEX_BIT_COUNT;
inline bool HasParent() const;
inline bool HasSibling() const;
inline bool HasChild() const;
inline bool IsEndPoint() const;
inline NodeIndex GetParentIndex() const;
inline NodeIndex GetSiblingIndex() const;
inline NodeIndex GetChildIndex() const;
inline NodeHeader();
NodeHeader(const NodeHeader& rhs) = default;
NodeHeader& operator=(const NodeHeader& rhs) = default;
};
class Name
{
friend class SceneGraph;
public:
inline Name();
Name(const Name& rhs) = default;
inline Name(Name&& rhs);
inline Name(AZStd::string&& pathName, size_t nameOffset);
Name& operator=(const Name& rhs) = default;
inline Name& operator=(Name&& rhs);
inline bool operator==(const Name& rhs) const;
inline bool operator!=(const Name& rhs) const;
// Returns the full unique path for the SceneGraph node.
inline const char* GetPath() const;
// Returns the name for the SceneGraph Node.
inline const char* GetName() const;
inline size_t GetPathLength() const;
inline size_t GetNameLength() const;
private:
AZStd::string m_path;
size_t m_nameOffset;
};
inline static AZStd::shared_ptr<const DataTypes::IGraphObject> ConstDataConverter(const AZStd::shared_ptr<DataTypes::IGraphObject>& value);
using StringHasher = AZStd::hash<AZStd::string>;
using StringHash = size_t;
using NameLookup = AZStd::unordered_multimap<StringHash, uint32_t>;
using HierarchyStorageType = NodeHeader;
using HierarchyStorage = AZStd::vector<HierarchyStorageType>;
using HierarchyStorageConstIterator = HierarchyStorage::const_iterator;
using HierarchyStorageConstData = Views::View<HierarchyStorageConstIterator>;
using NameStorageType = Name;
using NameStorage = AZStd::vector<NameStorageType>;
using NameStorageConstData = Views::View<NameStorage::const_iterator>;
using ContentStorageType = AZStd::shared_ptr<DataTypes::IGraphObject>;
using ContentStorage = AZStd::vector<ContentStorageType>;
using ContentStorageData = Views::View<ContentStorage::const_iterator>;
using ContentStorageConstDataIteratorWrapper = Views::ConvertIterator<ContentStorage::const_iterator,
decltype(ConstDataConverter(nullptr))>;
using ContentStorageConstData = Views::View<ContentStorageConstDataIteratorWrapper>;
SCENE_CORE_API SceneGraph();
inline NodeIndex GetRoot() const;
SCENE_CORE_API NodeIndex Find(const char* path) const;
SCENE_CORE_API NodeIndex Find(NodeIndex root, const char* name) const;
inline NodeIndex Find(const Name& name);
inline NodeIndex Find(const AZStd::string& path) const;
inline NodeIndex Find(NodeIndex root, const AZStd::string& name) const;
inline bool HasNodeContent(NodeIndex node) const;
inline bool HasNodeSibling(NodeIndex node) const;
inline bool HasNodeChild(NodeIndex node) const;
inline bool HasNodeParent(NodeIndex node) const;
inline bool IsNodeEndPoint(NodeIndex node) const;
SCENE_CORE_API const Name& GetNodeName(NodeIndex node) const;
inline AZStd::shared_ptr<DataTypes::IGraphObject> GetNodeContent(NodeIndex node);
inline AZStd::shared_ptr<const DataTypes::IGraphObject> GetNodeContent(NodeIndex node) const;
inline NodeIndex GetNodeParent(NodeIndex node) const;
inline NodeIndex GetNodeParent(NodeHeader node) const;
inline NodeIndex GetNodeSibling(NodeIndex node) const;
inline NodeIndex GetNodeSibling(NodeHeader node) const;
inline NodeIndex GetNodeChild(NodeIndex node) const;
inline NodeIndex GetNodeChild(NodeHeader node) const;
inline size_t GetNodeCount() const;
// Used when switching from index based navigation to iterator based.
inline HierarchyStorageConstData::iterator ConvertToHierarchyIterator(NodeIndex node) const;
inline NameStorageConstData::iterator ConvertToNameIterator(NodeIndex node) const;
inline ContentStorageData::iterator ConvertToStorageIterator(NodeIndex node);
inline ContentStorageConstData::iterator ConvertToStorageIterator(NodeIndex node) const;
// Used when switching from iterator based navigation to index based.
// Note that any changes made to the SceneGraph using the node index will invalidate
// the original iterator.
inline NodeIndex ConvertToNodeIndex(HierarchyStorageConstData::iterator iterator) const;
inline NodeIndex ConvertToNodeIndex(NameStorageConstData::iterator iterator) const;
inline NodeIndex ConvertToNodeIndex(ContentStorageData::iterator iterator) const;
inline NodeIndex ConvertToNodeIndex(ContentStorageConstData::iterator iterator) const;
// Adds a child node to the given parent. If the parent already had a child, AddChild will search the sibling
// chain for an available spot.
SCENE_CORE_API NodeIndex AddChild(NodeIndex parent, const char* name);
SCENE_CORE_API NodeIndex AddChild(NodeIndex parent, const char* name, const AZStd::shared_ptr<DataTypes::IGraphObject>& content);
SCENE_CORE_API NodeIndex AddChild(NodeIndex parent, const char* name, AZStd::shared_ptr<DataTypes::IGraphObject>&& content);
// Adds a sibling to given sibling. If the given sibling already has a sibling, the sibling chain is searched
// for an available spot. If the parent node is known AddChild can be used to achieve the same effect,
// however if index of the (last) added node is available this function can be used to reduce or skip
// the search within the sibling chain. This function can therefore be used as an optimization for AddChild,
// when more than 1 child is being added.
SCENE_CORE_API NodeIndex AddSibling(NodeIndex sibling, const char* name);
SCENE_CORE_API NodeIndex AddSibling(NodeIndex sibling, const char* name, const AZStd::shared_ptr<DataTypes::IGraphObject>& content);
SCENE_CORE_API NodeIndex AddSibling(NodeIndex sibling, const char* name, AZStd::shared_ptr<DataTypes::IGraphObject>&& content);
SCENE_CORE_API bool SetContent(NodeIndex node, const AZStd::shared_ptr<DataTypes::IGraphObject>& content);
SCENE_CORE_API bool SetContent(NodeIndex node, AZStd::shared_ptr<DataTypes::IGraphObject>&& content);
// Marks a function to no longer accept child nodes.
SCENE_CORE_API bool MakeEndPoint(NodeIndex node);
inline HierarchyStorageConstData GetHierarchyStorage() const;
inline NameStorageConstData GetNameStorage() const;
inline ContentStorageData GetContentStorage();
inline ContentStorageConstData GetContentStorage() const;
// Clears all data stored inside and reads the default root node.
SCENE_CORE_API void Clear();
// Checks if the given name can be used as a valid name for a node. This only checks the name validity, not if it's
// already in use. Use Find(...) to check if a name is already in use.
SCENE_CORE_API static bool IsValidName(const char* name);
// Checks if the given name can be used as a valid name for a node. This only checks the name validity, not if it's
// already in use. Use Find(...) to check if a name is already in use.
inline static bool IsValidName(const AZStd::string& name);
SCENE_CORE_API static char GetNodeSeperationCharacter();
static void Reflect(AZ::ReflectContext* context);
private:
// Adds a child node to the given parent. AppendChild assumes that checks have already be done to guarantee the given parent
// doesn't already have a child.
NodeIndex::IndexType AppendChild(NodeIndex::IndexType parent, const char* name, AZStd::shared_ptr<DataTypes::IGraphObject>&& content);
// Add a sibling after the given sibling. AppendSibling assumes that the correct insertion point was found before calling
// and the given sibling is the last in line with no siblings following.
NodeIndex::IndexType AppendSibling(NodeIndex::IndexType sibling, const char* name, AZStd::shared_ptr<DataTypes::IGraphObject>&& content);
// Appends a new node to the graph and configures its heritage according to the given parent. Connections to the new node
// as identified by the returned index are assumed to be setup by either the calling function such as AppendChild or
// AppendSibling.
NodeIndex::IndexType AppendNode(NodeIndex::IndexType parentIndex, const char* name, AZStd::shared_ptr<DataTypes::IGraphObject>&& content);
NameLookup::const_iterator FindNameLookupIterator(const char* name) const;
NameLookup::const_iterator FindNameLookupIterator(StringHash hash, const char* name) const;
AZStd::string CombineName(const char* path, const char* name) const;
void AddDefaultRoot();
static const char s_nodeSeperationCharacter = '.';
NameLookup m_nameLookup;
HierarchyStorage m_hierarchy;
NameStorage m_names;
ContentStorage m_content;
};
} // Containers
} // SceneAPI
AZ_TYPE_INFO_SPECIALIZE(AZ::SceneAPI::Containers::SceneGraph, "{CAC6556D-D5FE-4D0E-BCCD-8940357C1D35}");
AZ_TYPE_INFO_SPECIALIZE(AZ::SceneAPI::Containers::SceneGraph::NodeHeader, "{888C32BB-FEE3-4FA1-ADA4-09A58B03562A}");
AZ_TYPE_INFO_SPECIALIZE(AZ::SceneAPI::Containers::SceneGraph::NodeIndex, "{4AD18037-E629-480D-8165-997A137327FD}");
AZ_TYPE_INFO_SPECIALIZE(AZ::SceneAPI::Containers::SceneGraph::Name, "{4077AC3C-B301-4F5A-BEA7-54D6511AEC2E}");
} // AZ
#include <SceneAPI/SceneCore/Containers/SceneGraph.inl>
@@ -0,0 +1,341 @@
/*
* 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/iterator.h>
#include <AzCore/Casting/numeric_cast.h>
namespace AZ
{
namespace SceneAPI
{
namespace Containers
{
//
// NodeIndex
//
SceneGraph::NodeIndex::NodeIndex()
: m_value(NodeIndex::INVALID_INDEX)
{
}
bool SceneGraph::NodeIndex::IsValid() const
{
return m_value != NodeIndex::INVALID_INDEX;
}
bool SceneGraph::NodeIndex::operator==(NodeIndex rhs) const
{
return m_value == rhs.m_value;
}
bool SceneGraph::NodeIndex::operator!=(NodeIndex rhs) const
{
return m_value != rhs.m_value;
}
SceneGraph::NodeIndex::IndexType SceneGraph::NodeIndex::AsNumber() const
{
return m_value;
}
s32 SceneGraph::NodeIndex::Distance(NodeIndex rhs) const
{
return static_cast<s32>(rhs.m_value) - static_cast<s32>(m_value);
}
SceneGraph::NodeIndex::NodeIndex(IndexType value)
: m_value(value)
{
}
//
// SceneGraph NodeHeader
//
SceneGraph::NodeHeader::NodeHeader()
: m_isEndPoint(0)
, m_parentIndex(NodeHeader::INVALID_INDEX)
, m_siblingIndex(NodeHeader::INVALID_INDEX)
, m_childIndex(NodeHeader::INVALID_INDEX)
{
}
bool SceneGraph::NodeHeader::HasParent() const
{
return m_parentIndex != NodeHeader::INVALID_INDEX;
}
bool SceneGraph::NodeHeader::HasSibling() const
{
return m_siblingIndex != NodeHeader::INVALID_INDEX;
}
bool SceneGraph::NodeHeader::HasChild() const
{
return m_childIndex != NodeHeader::INVALID_INDEX;
}
bool SceneGraph::NodeHeader::IsEndPoint() const
{
return m_isEndPoint;
}
SceneGraph::NodeIndex SceneGraph::NodeHeader::GetParentIndex() const
{
return NodeIndex(m_parentIndex);
}
SceneGraph::NodeIndex SceneGraph::NodeHeader::GetSiblingIndex() const
{
return NodeIndex(m_siblingIndex);
}
SceneGraph::NodeIndex SceneGraph::NodeHeader::GetChildIndex() const
{
return NodeIndex(m_childIndex);
}
//
// Name
//
SceneGraph::Name::Name()
: m_nameOffset(0)
{
}
SceneGraph::Name::Name(Name&& rhs)
: m_path(AZStd::move(rhs.m_path))
, m_nameOffset(rhs.m_nameOffset)
{
}
SceneGraph::Name::Name(AZStd::string&& pathName, size_t nameOffset)
: m_path(AZStd::move(pathName))
, m_nameOffset(nameOffset)
{
if (m_nameOffset >= m_path.size())
{
m_nameOffset = m_path.size();
}
}
SceneGraph::Name& SceneGraph::Name::operator=(Name&& rhs)
{
m_path = AZStd::move(rhs.m_path);
m_nameOffset = rhs.m_nameOffset;
return *this;
}
bool SceneGraph::Name::operator==(const Name& rhs) const
{
return m_nameOffset == rhs.m_nameOffset && m_path == rhs.m_path;
}
bool SceneGraph::Name::operator!=(const Name& rhs) const
{
return m_nameOffset != rhs.m_nameOffset || m_path != rhs.m_path;
}
const char* SceneGraph::Name::GetPath() const
{
return m_path.c_str();
}
const char* SceneGraph::Name::GetName() const
{
AZ_Assert(m_nameOffset <= m_path.length(), "Offset to name in SceneGraph path is invalid.");
return m_path.c_str() + m_nameOffset;
}
size_t SceneGraph::Name::GetPathLength() const
{
return m_path.length();
}
size_t SceneGraph::Name::GetNameLength() const
{
AZ_Assert(m_nameOffset <= m_path.length(), "Offset to name in SceneGraph path is invalid.");
return m_path.length() - m_nameOffset;
}
//
// SceneGraph
//
AZStd::shared_ptr<const DataTypes::IGraphObject> SceneGraph::ConstDataConverter(const AZStd::shared_ptr<DataTypes::IGraphObject>& value)
{
return AZStd::shared_ptr<const DataTypes::IGraphObject>(value);
}
SceneGraph::NodeIndex SceneGraph::GetRoot() const
{
return NodeIndex(0);
}
SceneGraph::NodeIndex SceneGraph::Find(const AZStd::string& path) const
{
return Find(path.c_str());
}
SceneGraph::NodeIndex SceneGraph::Find(const Name& name)
{
return Find(name.GetPath());
}
SceneGraph::NodeIndex SceneGraph::Find(NodeIndex root, const AZStd::string& name) const
{
return Find(root, name.c_str());
}
bool SceneGraph::HasNodeContent(NodeIndex node) const
{
return node.m_value < m_content.size() ? m_content[node.m_value] != nullptr : false;
}
bool SceneGraph::HasNodeSibling(NodeIndex node) const
{
return node.m_value < m_hierarchy.size() ? m_hierarchy[node.m_value].HasSibling() : false;
}
bool SceneGraph::HasNodeChild(NodeIndex node) const
{
return node.m_value < m_hierarchy.size() ? m_hierarchy[node.m_value].HasChild() : false;
}
bool SceneGraph::HasNodeParent(NodeIndex node) const
{
return node.m_value < m_hierarchy.size() ? m_hierarchy[node.m_value].HasParent() : false;
}
bool SceneGraph::IsNodeEndPoint(NodeIndex node) const
{
return node.m_value < m_hierarchy.size() ? m_hierarchy[node.m_value].IsEndPoint() : true;
}
AZStd::shared_ptr<DataTypes::IGraphObject> SceneGraph::GetNodeContent(NodeIndex node)
{
return node.m_value < m_content.size() ? m_content[node.m_value] : nullptr;
}
AZStd::shared_ptr<const DataTypes::IGraphObject> SceneGraph::GetNodeContent(NodeIndex node) const
{
return node.m_value < m_content.size() ? m_content[node.m_value] : nullptr;
}
SceneGraph::NodeIndex SceneGraph::GetNodeParent(NodeIndex node) const
{
return node.m_value < m_hierarchy.size() ? GetNodeParent(m_hierarchy[node.m_value]) : NodeIndex();
}
SceneGraph::NodeIndex SceneGraph::GetNodeParent(NodeHeader node) const
{
return NodeIndex(node.m_parentIndex != NodeHeader::INVALID_INDEX ? static_cast<uint32_t>(node.m_parentIndex) : NodeIndex::INVALID_INDEX);
}
SceneGraph::NodeIndex SceneGraph::GetNodeSibling(NodeIndex node) const
{
return node.m_value < m_hierarchy.size() ? GetNodeSibling(m_hierarchy[node.m_value]) : NodeIndex();
}
SceneGraph::NodeIndex SceneGraph::GetNodeSibling(NodeHeader node) const
{
return NodeIndex(node.m_siblingIndex != NodeHeader::INVALID_INDEX ? static_cast<uint32_t>(node.m_siblingIndex) : NodeIndex::INVALID_INDEX);
}
SceneGraph::NodeIndex SceneGraph::GetNodeChild(NodeIndex node) const
{
return node.m_value < m_hierarchy.size() ? GetNodeChild(m_hierarchy[node.m_value]) : NodeIndex();
}
SceneGraph::NodeIndex SceneGraph::GetNodeChild(NodeHeader node) const
{
return NodeIndex(node.m_childIndex != NodeHeader::INVALID_INDEX ? static_cast<uint32_t>(node.m_childIndex) : NodeIndex::INVALID_INDEX);
}
size_t SceneGraph::GetNodeCount() const
{
return m_hierarchy.size();
}
SceneGraph::HierarchyStorageConstData::iterator SceneGraph::ConvertToHierarchyIterator(NodeIndex node) const
{
return node.m_value < m_hierarchy.size() ? m_hierarchy.cbegin() + node.m_value : m_hierarchy.cend();
}
SceneGraph::NameStorageConstData::iterator SceneGraph::ConvertToNameIterator(NodeIndex node) const
{
return node.m_value < m_names.size() ? m_names.cbegin() + node.m_value : m_names.cend();
}
SceneGraph::ContentStorageData::iterator SceneGraph::ConvertToStorageIterator(NodeIndex node)
{
return node.m_value < m_content.size() ? m_content.cbegin() + node.m_value : m_content.cend();
}
SceneGraph::ContentStorageConstData::iterator SceneGraph::ConvertToStorageIterator(NodeIndex node) const
{
return node.m_value < m_content.size() ?
Views::MakeConvertIterator(m_content.cbegin() + node.m_value, ConstDataConverter) :
Views::MakeConvertIterator(m_content.cend(), ConstDataConverter);
}
SceneGraph::NodeIndex SceneGraph::ConvertToNodeIndex(HierarchyStorageConstData::iterator iterator) const
{
return NodeIndex(iterator != m_hierarchy.cend() ? static_cast<uint32_t>(std::distance(m_hierarchy.cbegin(), iterator)) : NodeIndex::INVALID_INDEX);
}
SceneGraph::NodeIndex SceneGraph::ConvertToNodeIndex(NameStorageConstData::iterator iterator) const
{
return NodeIndex(iterator != m_names.cend() ? static_cast<uint32_t>(std::distance(m_names.cbegin(), iterator)) : NodeIndex::INVALID_INDEX);
}
SceneGraph::NodeIndex SceneGraph::ConvertToNodeIndex(ContentStorageData::iterator iterator) const
{
return NodeIndex(iterator != m_content.end() ? static_cast<uint32_t>(std::distance(m_content.begin(), iterator)) : NodeIndex::INVALID_INDEX);
}
SceneGraph::NodeIndex SceneGraph::ConvertToNodeIndex(ContentStorageConstData::iterator iterator) const
{
return NodeIndex(
iterator.GetBaseIterator() != m_content.cend() ?
aznumeric_caster(AZStd::distance(m_content.cbegin(), iterator.GetBaseIterator())) :
NodeIndex::INVALID_INDEX);
}
SceneGraph::HierarchyStorageConstData SceneGraph::GetHierarchyStorage() const
{
return HierarchyStorageConstData(m_hierarchy.begin(), m_hierarchy.end());
}
SceneGraph::NameStorageConstData SceneGraph::GetNameStorage() const
{
return NameStorageConstData(m_names.begin(), m_names.end());
}
SceneGraph::ContentStorageData SceneGraph::GetContentStorage()
{
return ContentStorageData(m_content.begin(), m_content.end());
}
SceneGraph::ContentStorageConstData SceneGraph::GetContentStorage() const
{
return ContentStorageConstData(
Views::MakeConvertIterator(m_content.cbegin(), ConstDataConverter),
Views::MakeConvertIterator(m_content.cend(), ConstDataConverter));
}
bool SceneGraph::IsValidName(const AZStd::string& name)
{
return name.size() > 0 ? IsValidName(name.c_str()) : false;
}
} // Containers
} // SceneAPI
} // AZ
@@ -0,0 +1,374 @@
/*
* 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/SceneManifest.h>
#include <AzCore/Casting/numeric_cast.h>
#include <AzCore/Component/ComponentApplicationBus.h>
#include <AzCore/Debug/Trace.h>
#include <AzCore/IO/GenericStreams.h>
#include <AzCore/IO/Path/Path.h>
#include <AzCore/IO/SystemFile.h>
#include <AzCore/JSON/rapidjson.h>
#include <AzCore/JSON/document.h>
#include <AzCore/JSON/prettywriter.h>
#include <AzCore/Memory/SystemAllocator.h>
#include <AzCore/Serialization/Json/RegistrationContext.h>
#include <AzCore/Serialization/Json/JsonSerialization.h>
#include <AzCore/Serialization/Json/JsonSerializationResult.h>
#include <AzCore/Serialization/Utils.h>
#include <AzCore/std/algorithm.h>
#include <AzCore/Utils/Utils.h>
#include <AzFramework/FileFunc/FileFunc.h>
#include <AzFramework/StringFunc/StringFunc.h>
#include <AzToolsFramework/Debug/TraceContext.h>
#include <SceneAPI/SceneCore/Utilities/Reporting.h>
namespace AZ
{
namespace SceneAPI
{
namespace Containers
{
//! Protects from allocating too much memory. The choice of a 5MB threshold is arbitrary.
const size_t MaxSceneManifestFileSizeInBytes = 5 * 1024 * 1024;
const char ErrorWindowName[] = "SceneManifest";
AZ_CLASS_ALLOCATOR_IMPL(SceneManifest, AZ::SystemAllocator, 0)
SceneManifest::~SceneManifest()
{
}
void SceneManifest::Clear()
{
m_storageLookup.clear();
m_values.clear();
}
bool SceneManifest::AddEntry(AZStd::shared_ptr<DataTypes::IManifestObject>&& value)
{
auto itValue = m_storageLookup.find(value.get());
if (itValue != m_storageLookup.end())
{
AZ_TracePrintf(Utilities::WarningWindow, "Manifest Object has already been registered with the manifest.");
return false;
}
Index index = aznumeric_caster(m_values.size());
m_storageLookup[value.get()] = index;
m_values.push_back(AZStd::move(value));
AZ_Assert(m_values.size() == m_storageLookup.size(),
"SceneManifest values and storage-lookup tables have gone out of lockstep (%i vs %i)",
m_values.size(), m_storageLookup.size());
return true;
}
bool SceneManifest::RemoveEntry(const DataTypes::IManifestObject* const value)
{
auto storageLookupIt = m_storageLookup.find(value);
if (storageLookupIt == m_storageLookup.end())
{
AZ_Assert(false, "Value not registered in SceneManifest.");
return false;
}
size_t index = storageLookupIt->second;
m_values.erase(m_values.begin() + index);
m_storageLookup.erase(storageLookupIt);
for (auto& entry : m_storageLookup)
{
if (entry.second > index)
{
entry.second--;
}
}
return true;
}
SceneManifest::Index SceneManifest::FindIndex(const DataTypes::IManifestObject* const value) const
{
auto it = m_storageLookup.find(value);
return it != m_storageLookup.end() ? (*it).second : s_invalidIndex;
}
bool SceneManifest::LoadFromFile(const AZStd::string& absoluteFilePath, SerializeContext* context)
{
if (absoluteFilePath.empty())
{
AZ_Error(ErrorWindowName, false, "Unable to load Scene Manifest: no file path was provided.");
return false;
}
auto readFileOutcome = Utils::ReadFile(absoluteFilePath, MaxSceneManifestFileSizeInBytes);
if (!readFileOutcome.IsSuccess())
{
AZ_Error(ErrorWindowName, false, readFileOutcome.GetError().c_str());
return false;
}
AZStd::string fileContents(readFileOutcome.TakeValue());
// Attempt to read the file as JSON
auto loadJsonOutcome = LoadFromString(fileContents, context);
if (loadJsonOutcome.IsSuccess())
{
return true;
}
// If JSON parsing failed, try to deserialize with XML
auto loadXmlOutcome = LoadFromString(fileContents, context, nullptr, true);
AZStd::string fileName;
AzFramework::StringFunc::Path::GetFileName(absoluteFilePath.c_str(), fileName);
if (loadXmlOutcome.IsSuccess())
{
AZ_TracePrintf(ErrorWindowName, "Scene Manifest ( %s ) is using the deprecated XML file format. It will be upgraded to JSON the next time it is modified.\n", fileName.c_str());
return true;
}
// If both failed, throw an error
AZ_Error(ErrorWindowName, false,
"Unable to deserialize ( %s ) using JSON or XML. \nJSON reported error: %s\nXML reported error: %s",
fileName.c_str(), loadJsonOutcome.GetError().c_str(), loadXmlOutcome.GetError().c_str());
return false;
}
bool SceneManifest::SaveToFile(const AZStd::string& absoluteFilePath, SerializeContext* context)
{
AZ_TraceContext(ErrorWindowName, absoluteFilePath);
if (absoluteFilePath.empty())
{
AZ_Error(ErrorWindowName, false, "Unable to save Scene Manifest: no file path was provided.");
return false;
}
AZStd::string errorMsg = AZStd::string::format("Unable to save Scene Manifest to ( %s ):\n", absoluteFilePath.c_str());
AZ::Outcome<rapidjson::Document, AZStd::string> saveToJsonOutcome = SaveToJsonDocument(context);
if (!saveToJsonOutcome.IsSuccess())
{
AZ_Error(ErrorWindowName, false, "%s%s", errorMsg.c_str(), saveToJsonOutcome.GetError().c_str());
return false;
}
AZ::IO::Path fileIoPath(absoluteFilePath);
auto saveToFileOutcome = AzFramework::FileFunc::WriteJsonFile(saveToJsonOutcome.GetValue(), fileIoPath);
if (!saveToFileOutcome.IsSuccess())
{
AZ_Error(ErrorWindowName, false, "%s%s", errorMsg.c_str(), saveToFileOutcome.GetError().c_str());
return false;
}
return true;
}
AZStd::shared_ptr<const DataTypes::IManifestObject> SceneManifest::SceneManifestConstDataConverter(
const AZStd::shared_ptr<DataTypes::IManifestObject>& value)
{
return AZStd::shared_ptr<const DataTypes::IManifestObject>(value);
}
void SceneManifest::Reflect(ReflectContext* context)
{
SerializeContext* serializeContext = azrtti_cast<SerializeContext*>(context);
if (serializeContext)
{
serializeContext->Class<SceneManifest>()
->Version(1, &SceneManifest::VersionConverter)
->Field("values", &SceneManifest::m_values);
}
BehaviorContext* behaviorContext = azrtti_cast<BehaviorContext*>(context);
if (behaviorContext)
{
behaviorContext->Class<SceneManifest>()
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
->Attribute(AZ::Script::Attributes::Module, "scene")
->Method("ImportFromJson", [](SceneManifest& self, AZStd::string_view jsonBuffer) -> bool
{
auto outcome = self.LoadFromString(jsonBuffer);
if (outcome.IsSuccess())
{
return true;
}
AZ_Warning(ErrorWindowName, false, "LoadFromString outcome failure (%s)", outcome.GetError().c_str());
return true;
})
->Method("ExportToJson", [](SceneManifest& self) -> AZStd::string
{
auto outcome = self.SaveToJsonDocument();
if (outcome.IsSuccess())
{
// write the manifest to a UTF-8 string buffer and move return the string
rapidjson::StringBuffer sb;
rapidjson::Writer<rapidjson::StringBuffer, rapidjson::UTF8<>> writer(sb);
rapidjson::Document& document = outcome.GetValue();
document.Accept(writer);
return AZStd::move(AZStd::string(sb.GetString()));
}
AZ_Warning(ErrorWindowName, false, "SaveToJsonDocument outcome failure (%s)", outcome.GetError().c_str());
return {};
});
}
}
bool SceneManifest::VersionConverter(SerializeContext& context, SerializeContext::DataElementNode& node)
{
if (node.GetVersion() != 0)
{
AZ_TracePrintf(ErrorWindowName, "Unable to upgrade SceneManifest from version %i.", node.GetVersion());
return false;
}
// Copy out the original values.
AZStd::vector<SerializeContext::DataElementNode> values;
values.reserve(node.GetNumSubElements());
for (int i = 0; i < node.GetNumSubElements(); ++i)
{
// The old format stored AZStd::pair<AZStd::string, AZStd::shared_ptr<IManifestObjets>>. All this
// data is still used, but needs to be move to the new location. The shared ptr needs to be
// moved into the new container, while the name needs to be moved to the group name.
SerializeContext::DataElementNode& pairNode = node.GetSubElement(i);
// This is the original content of the shared ptr. Using the shared pointer directly caused
// registration issues so it's extracting the data the shared ptr was storing instead.
SerializeContext::DataElementNode& elementNode = pairNode.GetSubElement(1).GetSubElement(0);
SerializeContext::DataElementNode& nameNode = pairNode.GetSubElement(0);
AZStd::string name;
if (nameNode.GetData(name))
{
elementNode.AddElementWithData<AZStd::string>(context, "name", name);
}
// It's better not to set a default name here as the default behaviors will take care of that
// will have more information to work with.
values.push_back(elementNode);
}
// Delete old values
for (int i = 0; i < node.GetNumSubElements(); ++i)
{
node.RemoveElement(i);
}
// Put stored values back
int vectorIndex = node.AddElement<ValueStorage>(context, "values");
SerializeContext::DataElementNode& vectorNode = node.GetSubElement(vectorIndex);
for (SerializeContext::DataElementNode& value : values)
{
value.SetName("element");
// Put in a blank shared ptr to be filled with a value stored from "values".
int valueIndex = vectorNode.AddElement<ValueStorageType>(context, "element");
SerializeContext::DataElementNode& pointerNode = vectorNode.GetSubElement(valueIndex);
// Type doesn't matter as it will be overwritten by the stored value.
pointerNode.AddElement<int>(context, "element");
pointerNode.GetSubElement(0) = value;
}
AZ_TracePrintf(Utilities::WarningWindow,
"The SceneManifest has been updated from version %i. It's recommended to save the updated file.", node.GetVersion());
return true;
}
AZ::Outcome<void, AZStd::string> SceneManifest::LoadFromString(const AZStd::string& fileContents, SerializeContext* context, JsonRegistrationContext* registrationContext, bool loadXml)
{
Clear();
AZStd::string failureMessage;
if (loadXml)
{
// Attempt to read the stream as XML (old format)
// Gems can be removed, causing the setting for manifest objects in the the Gem to not be registered. Instead of failing
// to load the entire manifest, just ignore those values.
ObjectStream::FilterDescriptor loadFilter(&AZ::Data::AssetFilterNoAssetLoading, ObjectStream::FILTERFLAG_IGNORE_UNKNOWN_CLASSES);
if (Utils::LoadObjectFromBufferInPlace<SceneManifest>(fileContents.data(), fileContents.size(), *this, context, loadFilter))
{
Init();
return AZ::Success();
}
failureMessage = "Unable to load Scene Manifest as XML";
}
else
{
// Attempt to read the stream as JSON
auto readJsonOutcome = AzFramework::FileFunc::ReadJsonFromString(fileContents);
AZStd::string errorMsg;
if (!readJsonOutcome.IsSuccess())
{
return AZ::Failure(readJsonOutcome.TakeError());
}
rapidjson::Document document = readJsonOutcome.TakeValue();
AZ::JsonDeserializerSettings settings;
settings.m_serializeContext = context;
settings.m_registrationContext = registrationContext;
AZ::JsonSerializationResult::ResultCode jsonResult = AZ::JsonSerialization::Load(*this, document, settings);
if (jsonResult.GetProcessing() != AZ::JsonSerializationResult::Processing::Halted)
{
Init();
return AZ::Success();
}
failureMessage = jsonResult.ToString("");
}
return AZ::Failure(failureMessage);
}
AZ::Outcome<rapidjson::Document, AZStd::string> SceneManifest::SaveToJsonDocument(SerializeContext* context, JsonRegistrationContext* registrationContext)
{
AZ::JsonSerializerSettings settings;
settings.m_serializeContext = context;
settings.m_registrationContext = registrationContext;
rapidjson::Document jsonDocument;
auto jsonResult = JsonSerialization::Store(jsonDocument, jsonDocument.GetAllocator(), *this, settings);
if (jsonResult.GetProcessing() == AZ::JsonSerializationResult::Processing::Halted)
{
return AZ::Failure(AZStd::string::format("JSON serialization failed: %s", jsonResult.ToString("").c_str()));
}
return AZ::Success(AZStd::move(jsonDocument));
}
void SceneManifest::Init()
{
auto end = AZStd::remove_if(m_values.begin(), m_values.end(),
[](const ValueStorageType& entry) -> bool
{
return !entry;
});
m_values.erase(end, m_values.end());
for (size_t i = 0; i < m_values.size(); ++i)
{
Index index = aznumeric_caster(i);
m_storageLookup[m_values[i].get()] = index;
}
}
} // Containers
} // SceneAPI
} // AZ
@@ -0,0 +1,119 @@
#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 <stdint.h>
#include <AzCore/JSON/rapidjson.h>
#include <AzCore/JSON/document.h>
#include <AzCore/Memory/Memory.h>
#include <AzCore/Outcome/Outcome.h>
#include <AzCore/std/containers/vector.h>
#include <AzCore/std/containers/unordered_map.h>
#include <AzCore/std/smart_ptr/shared_ptr.h>
#include <AzCore/std/utils.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <SceneAPI/SceneCore/SceneCoreConfiguration.h>
#include <SceneAPI/SceneCore/Containers/Views/View.h>
#include <SceneAPI/SceneCore/Containers/Views/ConvertIterator.h>
#include <SceneAPI/SceneCore/DataTypes/IManifestObject.h>
namespace AZ
{
class JsonRegistrationContext;
namespace SceneAPI
{
namespace Containers
{
// Scene manifests hold arbitrary meta data about a scene in a dictionary-like fashion.
// This can include data such as export groups.
class SCENE_CORE_API SceneManifest
{
friend class SceneManifestContainer;
public:
AZ_CLASS_ALLOCATOR_DECL
AZ_RTTI(SceneManifest, "{9274AD17-3212-4651-9F3B-7DCCB080E467}");
virtual ~SceneManifest();
static AZStd::shared_ptr<const DataTypes::IManifestObject> SceneManifestConstDataConverter(
const AZStd::shared_ptr<DataTypes::IManifestObject>& value);
using Index = size_t;
static const Index s_invalidIndex = static_cast<Index>(-1);
using StorageHash = const DataTypes::IManifestObject *;
using StorageLookup = AZStd::unordered_map<StorageHash, Index>;
using ValueStorageType = AZStd::shared_ptr<DataTypes::IManifestObject>;
using ValueStorage = AZStd::vector<ValueStorageType>;
using ValueStorageData = Views::View<ValueStorage::const_iterator>;
using ValueStorageConstDataIteratorWrapper = Views::ConvertIterator<ValueStorage::const_iterator,
decltype(SceneManifestConstDataConverter(AZStd::shared_ptr<DataTypes::IManifestObject>()))>;
using ValueStorageConstData = Views::View<ValueStorageConstDataIteratorWrapper>;
void Clear();
inline bool IsEmpty() const;
inline bool AddEntry(const AZStd::shared_ptr<DataTypes::IManifestObject>& value);
bool AddEntry(AZStd::shared_ptr<DataTypes::IManifestObject>&& value);
inline bool RemoveEntry(const AZStd::shared_ptr<DataTypes::IManifestObject>& value);
bool RemoveEntry(const DataTypes::IManifestObject* const value);
inline size_t GetEntryCount() const;
inline AZStd::shared_ptr<DataTypes::IManifestObject> GetValue(Index index);
inline AZStd::shared_ptr<const DataTypes::IManifestObject> GetValue(Index index) const;
// Finds the index of the given manifest object. A nullptr or invalid object will return s_invalidIndex.
inline Index FindIndex(const AZStd::shared_ptr<DataTypes::IManifestObject>& value) const;
// Finds the index of the given manifest object. A nullptr or invalid object will return s_invalidIndex.
Index FindIndex(const DataTypes::IManifestObject* const value) const;
inline ValueStorageData GetValueStorage();
inline ValueStorageConstData GetValueStorage() const;
bool LoadFromFile(const AZStd::string& absoluteFilePath, SerializeContext* context = nullptr);
/**
* Save manifest to file. Overwrites the file in case it already exists and creates a new file if not.
* @param absoluteFilePath the absolute path of the file you want to save to.
* @param context If no serialize context was specified, it will get the serialize context from the application component bus.
* @result True in case saving went all fine, false if an error occured.
*/
bool SaveToFile(const AZStd::string& absoluteFilePath, SerializeContext* context = nullptr);
AZ::Outcome<void, AZStd::string> LoadFromString(
const AZStd::string& fileContents, SerializeContext* context = nullptr,
JsonRegistrationContext* registrationContext = nullptr, bool loadXml = false);
static void Reflect(ReflectContext* context);
static bool VersionConverter(SerializeContext& context, SerializeContext::DataElementNode& node);
protected:
AZ::Outcome<rapidjson::Document, AZStd::string> SaveToJsonDocument(SerializeContext* context = nullptr, JsonRegistrationContext* registrationContext = nullptr);
private:
void Init();
AZ_PUSH_DISABLE_WARNING(4251, "-Wunknown-warning-option")
StorageLookup m_storageLookup;
ValueStorage m_values;
AZ_POP_DISABLE_OVERRIDE_WARNING
};
} // Containers
} // SceneAPI
} // AZ
#include <SceneAPI/SceneCore/Containers/SceneManifest.inl>
@@ -0,0 +1,75 @@
/*
* 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/Debug/Trace.h>
namespace AZ
{
namespace SceneAPI
{
namespace Containers
{
bool SceneManifest::IsEmpty() const
{
// Any of the containers would do as they should be in-sync with each other, so pick one arbitrarily.
AZ_Assert(m_values.empty() == m_storageLookup.empty(), "SceneManifest values and storage-lookup tables have gone out of lockstep.");
return m_values.empty();
}
bool SceneManifest::AddEntry(const AZStd::shared_ptr<DataTypes::IManifestObject>& value)
{
return AddEntry(AZStd::shared_ptr<DataTypes::IManifestObject>(value));
}
bool SceneManifest::RemoveEntry(const AZStd::shared_ptr<DataTypes::IManifestObject>& value)
{
return RemoveEntry(value.get());
}
size_t SceneManifest::GetEntryCount() const
{
// Any of the containers would do as they should be in-sync with each other, so pick one randomly.
AZ_Assert(m_values.size() == m_storageLookup.size(),
"SceneManifest values and storage-lookup tables have gone out of lockstep. (%i vs. %i)",
m_values.size(), m_storageLookup.size());
return m_values.size();
}
AZStd::shared_ptr<DataTypes::IManifestObject> SceneManifest::GetValue(Index index)
{
return index < m_values.size() ? m_values[index] : AZStd::shared_ptr<DataTypes::IManifestObject>();
}
AZStd::shared_ptr<const DataTypes::IManifestObject> SceneManifest::GetValue(Index index) const
{
return index < m_values.size() ? m_values[index] : AZStd::shared_ptr<const DataTypes::IManifestObject>();
}
SceneManifest::Index SceneManifest::FindIndex(const AZStd::shared_ptr<DataTypes::IManifestObject>& value) const
{
return FindIndex(value.get());
}
SceneManifest::ValueStorageData SceneManifest::GetValueStorage()
{
return ValueStorageData(m_values.begin(), m_values.end());
}
SceneManifest::ValueStorageConstData SceneManifest::GetValueStorage() const
{
return ValueStorageConstData(
Views::MakeConvertIterator(m_values.cbegin(), SceneManifestConstDataConverter),
Views::MakeConvertIterator(m_values.cend(), SceneManifestConstDataConverter));
}
} // Containers
} // SceneAPI
} // AZ
@@ -0,0 +1,142 @@
#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/smart_ptr/shared_ptr.h>
#include <AzCore/std/typetraits/is_base_of.h>
#include <AzCore/std/typetraits/conditional.h>
#include <AzCore/std/utils.h>
#include <SceneAPI/SceneCore/DataTypes/IManifestObject.h>
#include <SceneAPI/SceneCore/DataTypes/IGraphObject.h>
#include <SceneAPI/SceneCore/Containers/Views/FilterIterator.h>
#include <SceneAPI/SceneCore/Containers/Views/ConvertIterator.h>
namespace AZ
{
namespace SceneAPI
{
namespace Containers
{
// Utility classes to construct common filters for scenes. These can be used in
// algorithms such as find_if or the FilterIterator.
// Example:
// auto result = AZStd::find_if(view.begin(), view.end(), DerivedTypeFilter<IMeshData>());
namespace Internal
{
template<typename T, typename ObjectType, bool ExactType>
struct TypeFilter
{
bool operator()(const ObjectType& object) const;
bool operator()(const ObjectType* const object) const;
bool operator()(const AZStd::shared_ptr<const ObjectType>& object) const;
bool operator()(const AZStd::shared_ptr<ObjectType>& object) const;
template<typename T1>
bool operator()(const AZStd::pair<T1, AZStd::shared_ptr<const ObjectType>>& object) const;
template<typename T1>
bool operator()(const AZStd::pair<T1, AZStd::shared_ptr<ObjectType>>& object) const;
template<typename T1>
bool operator()(const AZStd::pair<T1, const AZStd::shared_ptr<const ObjectType>&>& object) const;
template<typename T1>
bool operator()(const AZStd::pair<T1, const AZStd::shared_ptr<ObjectType>&>& object) const;
template<typename T2>
bool operator()(const AZStd::pair<AZStd::shared_ptr<const ObjectType>, T2>& object) const;
template<typename T2>
bool operator()(const AZStd::pair<AZStd::shared_ptr<ObjectType>, T2>& object) const;
template<typename T2>
bool operator()(const AZStd::pair<const AZStd::shared_ptr<const ObjectType>&, T2>& object) const;
template<typename T2>
bool operator()(const AZStd::pair<const AZStd::shared_ptr<ObjectType>&, T2>& object) const;
};
template<typename T>
struct TypeFilterBaseType
{
static const bool s_isManifestObject = AZStd::is_base_of<DataTypes::IManifestObject, T>::value;
static const bool s_isGraphObject = AZStd::is_base_of<DataTypes::IGraphObject, T>::value;
static_assert(s_isManifestObject || s_isGraphObject, "Target type is not derived from IManifestObject or IGraphObject.");
using type = typename AZStd::conditional<s_isManifestObject, DataTypes::IManifestObject, DataTypes::IGraphObject>::type;
};
template<typename T> struct IsConstPayload { static const bool value = AZStd::is_const<T>::value; };
template<typename T> struct IsConstPayload<AZStd::shared_ptr<T>> { static const bool value = false; };
template<typename T> struct IsConstPayload<AZStd::unique_ptr<T>> { static const bool value = false; };
template<typename T> struct IsConstPayload<AZStd::shared_ptr<const T>> { static const bool value = true; };
template<typename T> struct IsConstPayload<AZStd::unique_ptr<const T>> { static const bool value = true; };
template<typename T, typename ViewType>
struct ConversionType
{
using type = typename AZStd::conditional<
IsConstPayload<typename AZStd::iterator_traits<typename ViewType::iterator>::value_type>::value,
const T, T>::type;
};
}
// Filter object for any type derived from the given type or the type itself. The given type must
// itself derive from either IManifestObject or IGraphObject.
// Example:
// auto result = AZStd::find_if(view.begin(), view.end(), DerivedTypeFilter<IMeshData>());
template<typename T>
struct DerivedTypeFilter
: public Internal::TypeFilter<T, typename Internal::TypeFilterBaseType<T>::type, false>
{
};
// Filter object for the given type. The given type must derive from either IManifestObject or
// IGraphObject.
// Example:
// auto view = Views::MakeFilterView(graph.GetContentStorage, ExactTypeFilter<MeshData>());
template<typename T>
struct ExactTypeFilter
: public Internal::TypeFilter<T, typename Internal::TypeFilterBaseType<T>::type, true>
{
};
// Compound view that returns all instances of the requested type and any types deriving from it.
// The given type must derive from either IManifestObject or IGraphObject.
// Example:
// auto view = MakeDerivedFilterView<IMeshData>(graph.GetContentStorage());
// for (IMeshData& mesh : view)
// {
// ...
// }
template<typename T, typename ViewType>
Views::View<Views::ConvertIterator<typename Views::FilterIterator<typename ViewType::iterator>,
typename Internal::ConversionType<T, ViewType>::type&>> MakeDerivedFilterView(ViewType& view);
template<typename T, typename ViewType>
Views::View<Views::ConvertIterator<typename Views::FilterIterator<typename ViewType::const_iterator>, const T&>> MakeDerivedFilterView(const ViewType& view);
// Compound view that returns all instances of the requested type.
// The given type must derive from either IManifestObject or IGraphObject.
// Example:
// auto view = MakeExactFilterView<MeshData>(graph.GetContentStorage());
// for (MeshData& mesh : view)
// {
// ...
// }
template<typename T, typename ViewType>
Views::View<Views::ConvertIterator<typename Views::FilterIterator<typename ViewType::iterator>,
typename Internal::ConversionType<T, ViewType>::type&>> MakeExactFilterView(ViewType& view);
template<typename T, typename ViewType>
Views::View<Views::ConvertIterator<typename Views::FilterIterator<typename ViewType::const_iterator>, const T&>> MakeExactFilterView(const ViewType& view);
} // Containers
} // SceneAPI
} // AZ
#include <SceneAPI/SceneCore/Containers/Utilities/Filters.inl>
@@ -0,0 +1,253 @@
/*
* 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 Containers
{
namespace Internal
{
template<typename T, typename ObjectType, bool ExactType>
bool TypeFilter<T, ObjectType, ExactType>::operator()(const ObjectType& object) const
{
if (ExactType)
{
return object.RTTI_GetType() == T::TYPEINFO_Uuid();
}
else
{
return object.RTTI_IsTypeOf(T::TYPEINFO_Uuid());
}
}
template<typename T, typename ObjectType, bool ExactType>
bool TypeFilter<T, ObjectType, ExactType>::operator()(const ObjectType* const object) const
{
if (ExactType)
{
return object && object->RTTI_GetType() == T::TYPEINFO_Uuid();
}
else
{
return object && object->RTTI_IsTypeOf(T::TYPEINFO_Uuid());
}
}
template<typename T, typename ObjectType, bool ExactType>
bool TypeFilter<T, ObjectType, ExactType>::operator()(const AZStd::shared_ptr<const ObjectType>& object) const
{
if (ExactType)
{
return object && object->RTTI_GetType() == T::TYPEINFO_Uuid();
}
else
{
return object && object->RTTI_IsTypeOf(T::TYPEINFO_Uuid());
}
}
template<typename T, typename ObjectType, bool ExactType>
bool TypeFilter<T, ObjectType, ExactType>::operator()(const AZStd::shared_ptr<ObjectType>& object) const
{
if (ExactType)
{
return object && object->RTTI_GetType() == T::TYPEINFO_Uuid();
}
else
{
return object && object->RTTI_IsTypeOf(T::TYPEINFO_Uuid());
}
}
template<typename T, typename ObjectType, bool ExactType> template<typename T1>
bool TypeFilter<T, ObjectType, ExactType>::operator()(const AZStd::pair<T1, AZStd::shared_ptr<const ObjectType>>& object) const
{
if (ExactType)
{
return object.second && object.second->RTTI_GetType() == T::TYPEINFO_Uuid();
}
else
{
return object.second && object.second->RTTI_IsTypeOf(T::TYPEINFO_Uuid());
}
}
template<typename T, typename ObjectType, bool ExactType> template<typename T1>
bool TypeFilter<T, ObjectType, ExactType>::operator()(const AZStd::pair<T1, AZStd::shared_ptr<ObjectType>>& object) const
{
if (ExactType)
{
return object.second && object.second->RTTI_GetType() == T::TYPEINFO_Uuid();
}
else
{
return object.second && object.second->RTTI_IsTypeOf(T::TYPEINFO_Uuid());
}
}
template<typename T, typename ObjectType, bool ExactType> template<typename T1>
bool TypeFilter<T, ObjectType, ExactType>::operator()(const AZStd::pair<T1, const AZStd::shared_ptr<const ObjectType>&>& object) const
{
if (ExactType)
{
return object.second && object.second->RTTI_GetType() == T::TYPEINFO_Uuid();
}
else
{
return object.second && object.second->RTTI_IsTypeOf(T::TYPEINFO_Uuid());
}
}
template<typename T, typename ObjectType, bool ExactType> template<typename T1>
bool TypeFilter<T, ObjectType, ExactType>::operator()(const AZStd::pair<T1, const AZStd::shared_ptr<ObjectType>&>& object) const
{
if (ExactType)
{
return object.second && object.second->RTTI_GetType() == T::TYPEINFO_Uuid();
}
else
{
return object.second && object.second->RTTI_IsTypeOf(T::TYPEINFO_Uuid());
}
}
template<typename T, typename ObjectType, bool ExactType> template<typename T2>
bool TypeFilter<T, ObjectType, ExactType>::operator()(const AZStd::pair<AZStd::shared_ptr<const ObjectType>, T2>& object) const
{
if (ExactType)
{
return object.first && object.first->RTTI_GetType() == T::TYPEINFO_Uuid();
}
else
{
return object.first && object.first->RTTI_IsTypeOf(T::TYPEINFO_Uuid());
}
}
template<typename T, typename ObjectType, bool ExactType> template<typename T2>
bool TypeFilter<T, ObjectType, ExactType>::operator()(const AZStd::pair<AZStd::shared_ptr<ObjectType>, T2>& object) const
{
if (ExactType)
{
return object.first && object.first->RTTI_GetType() == T::TYPEINFO_Uuid();
}
else
{
return object.first && object.first->RTTI_IsTypeOf(T::TYPEINFO_Uuid());
}
}
template<typename T, typename ObjectType, bool ExactType> template<typename T2>
bool TypeFilter<T, ObjectType, ExactType>::operator()(const AZStd::pair<const AZStd::shared_ptr<const ObjectType>&, T2>& object) const
{
if (ExactType)
{
return object.first && object.first->RTTI_GetType() == T::TYPEINFO_Uuid();
}
else
{
return object.first && object.first->RTTI_IsTypeOf(T::TYPEINFO_Uuid());
}
}
template<typename T, typename ObjectType, bool ExactType> template<typename T2>
bool TypeFilter<T, ObjectType, ExactType>::operator()(const AZStd::pair<const AZStd::shared_ptr<ObjectType>&, T2>& object) const
{
if (ExactType)
{
return object.first && object.first->RTTI_GetType() == T::TYPEINFO_Uuid();
}
else
{
return object.first && object.first->RTTI_IsTypeOf(T::TYPEINFO_Uuid());
}
}
} // Internal
template<typename T, typename ViewType>
Views::View<Views::ConvertIterator<typename Views::FilterIterator<typename ViewType::iterator>,
typename Internal::ConversionType<T, ViewType>::type&>> MakeDerivedFilterView(ViewType& view)
{
auto filterView = Views::MakeFilterView(view, DerivedTypeFilter<T>());
auto convertView = Views::MakeConvertView(filterView,
// Note that by default begin() returns a reference to the value, so the argument will
// already be by-reference so an extra reference doesn't need to be added and this
// function isn't being called by value.
[](decltype(*filterView.begin()) instance) -> typename Internal::ConversionType<T, ViewType>::type&
{
AZ_Assert(instance.get(), "Null pointer encountered.");
typename Internal::ConversionType<T, ViewType>::type* result =
azrtti_cast<typename Internal::ConversionType<T, ViewType>::type*>(instance.get());
AZ_Assert(result, "Unable to cast to target type.");
return *result;
}
);
return convertView;
}
template<typename T, typename ViewType>
Views::View<Views::ConvertIterator<typename Views::FilterIterator<typename ViewType::const_iterator>, const T&>> MakeDerivedFilterView(const ViewType& view)
{
auto filterView = Views::MakeFilterView(view, DerivedTypeFilter<T>());
auto convertView = Views::MakeConvertView(filterView,
// Note that by default begin() returns a reference to the value, so the argument will
// already be by-reference so an extra reference doesn't need to be added and this
// function isn't being called by value.
[](decltype(*filterView.begin()) instance) -> const T&
{
AZ_Assert(instance.get(), "Null pointer encountered.");
const T* result = azrtti_cast<const T*>(instance.get());
AZ_Assert(result, "Unable to cast to target type.");
return *result;
}
);
return convertView;
}
template<typename T, typename ViewType>
Views::View<Views::ConvertIterator<typename Views::FilterIterator<typename ViewType::iterator>,
typename Internal::ConversionType<T, ViewType>::type&>> MakeExactFilterView(ViewType& view)
{
auto filterView = Views::MakeFilterView(view, ExactTypeFilter<T>());
auto convertView = Views::MakeConvertView(filterView,
[](decltype(*filterView.begin()) instance) -> typename Internal::ConversionType<T, ViewType>::type&
{
AZ_Assert(instance.get(), "Null pointer encountered.");
typename Internal::ConversionType<T, ViewType>::type* result =
azrtti_cast<typename Internal::ConversionType<T, ViewType>::type*>(instance.get());
AZ_Assert(result, "Unable to cast to target type.");
return *result;
}
);
return convertView;
}
template<typename T, typename ViewType>
Views::View<Views::ConvertIterator<typename Views::FilterIterator<typename ViewType::const_iterator>, const T&>> MakeExactFilterView(const ViewType& view)
{
auto filterView = Views::MakeFilterView(view, ExactTypeFilter<T>());
auto convertView = Views::MakeConvertView(filterView,
[](decltype(*filterView.begin())& instance) -> const T&
{
AZ_Assert(instance.get(), "Null pointer encountered.");
const T* result = azrtti_cast<const T*>(instance.get());
AZ_Assert(result, "Unable to cast to target type.");
return *result;
}
);
return convertView;
}
} // Containers
} // SceneAPI
} // AZ
@@ -0,0 +1,53 @@
#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 Containers
{
// Utility class that stores (or references if possible) the given value
// but otherwise acts as a pointer. This can be useful for functions
// that require returning a pointer but don't store a local copy to
// return.
template<typename Type>
class ProxyPointer
{
public:
ProxyPointer(const Type& value);
Type& operator*();
Type* operator->();
private:
Type m_value;
};
template<typename Type>
class ProxyPointer<Type&>
{
public:
ProxyPointer(Type& value);
Type& operator*();
Type* operator->();
private:
Type& m_value;
};
} // Containers
} // SceneAPI
} // AZ
#include <SceneAPI/SceneCore/Containers/Utilities/ProxyPointer.inl>
@@ -0,0 +1,56 @@
/*
* 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 Containers
{
template<typename Type>
ProxyPointer<Type>::ProxyPointer(const Type& value)
: m_value(value)
{
}
template<typename Type>
Type& ProxyPointer<Type>::operator*()
{
return m_value;
}
template<typename Type>
Type* ProxyPointer<Type>::operator->()
{
return &m_value;
}
template<typename Type>
ProxyPointer<Type&>::ProxyPointer(Type& value)
: m_value(value)
{
}
template<typename Type>
Type& ProxyPointer<Type&>::operator*()
{
return m_value;
}
template<typename Type>
Type* ProxyPointer<Type&>::operator->()
{
return &m_value;
}
} // Containers
} // SceneAPI
} // AZ
@@ -0,0 +1,69 @@
/*
* 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/Math/Matrix3x4.h>
#include <AzCore/std/algorithm.h>
#include <AzCore/std/typetraits/is_base_of.h>
#include <SceneAPI/SceneCore/Containers/Scene.h>
#include <SceneAPI/SceneCore/Containers/SceneGraph.h>
#include <SceneAPI/SceneCore/Containers/Views/FilterIterator.h>
#include <SceneAPI/SceneCore/Containers/Utilities/Filters.h>
#include <SceneAPI/SceneCore/Containers/Utilities/SceneGraphUtilities.h>
#include <SceneAPI/SceneCore/Containers/Views/SceneGraphChildIterator.h>
#include <SceneAPI/SceneCore/DataTypes/GraphData/ITransform.h>
#include <SceneAPI/SceneCore/Events/GraphMetaInfoBus.h>
namespace AZ
{
namespace SceneAPI
{
namespace Utilities
{
DataTypes::MatrixType BuildWorldTransform(const Containers::SceneGraph& graph, Containers::SceneGraph::NodeIndex nodeIndex)
{
DataTypes::MatrixType outTransform = DataTypes::MatrixType::Identity();
while (nodeIndex.IsValid())
{
auto view = Containers::Views::MakeSceneGraphChildView<Containers::Views::AcceptEndPointsOnly>(graph, nodeIndex,
graph.GetContentStorage().begin(), true);
auto result = AZStd::find_if(view.begin(), view.end(), Containers::DerivedTypeFilter<DataTypes::ITransform>());
if (result != view.end())
{
// Check if the node has any child transform node
const DataTypes::MatrixType& azTransform = azrtti_cast<const DataTypes::ITransform*>(result->get())->GetMatrix();
outTransform = azTransform * outTransform;
}
else
{
// Check if the node itself is a transform node.
AZStd::shared_ptr<const DataTypes::ITransform> transformData = azrtti_cast<const DataTypes::ITransform*>(graph.GetNodeContent(nodeIndex));
if (transformData)
{
outTransform = transformData->GetMatrix() * outTransform;
}
}
if (graph.HasNodeParent(nodeIndex))
{
nodeIndex = graph.GetNodeParent(nodeIndex);
}
else
{
break;
}
}
return outTransform;
}
} // Utilities
} // SceneAPI
} // AZ
@@ -0,0 +1,38 @@
#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 <SceneAPI/SceneCore/Containers/SceneGraph.h>
#include <SceneAPI/SceneCore/DataTypes/MatrixType.h>
namespace AZ
{
namespace SceneAPI
{
namespace Containers
{
class Scene;
}
namespace Utilities
{
// Searches for any entries in the scene graph that are derived or match the given type.
// If "checkVirtualTypes" is true, a matching entry is also checked if it's not a
// virtual type.
template<typename T>
bool DoesSceneGraphContainDataLike(const Containers::Scene& scene, bool checkVirtualTypes);
SCENE_CORE_API DataTypes::MatrixType BuildWorldTransform(const Containers::SceneGraph& graph, Containers::SceneGraph::NodeIndex nodeIndex);
} // Utilities
} // SceneAPI
} // AZ
#include <SceneAPI/SceneCore/Containers/Utilities/SceneGraphUtilities.inl>
@@ -0,0 +1,58 @@
/*
* 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/algorithm.h>
#include <AzCore/std/typetraits/is_base_of.h>
#include <SceneAPI/SceneCore/Containers/Scene.h>
#include <SceneAPI/SceneCore/Containers/SceneGraph.h>
#include <SceneAPI/SceneCore/Containers/Views/FilterIterator.h>
#include <SceneAPI/SceneCore/Containers/Utilities/Filters.h>
#include <SceneAPI/SceneCore/Events/GraphMetaInfoBus.h>
namespace AZ
{
namespace SceneAPI
{
namespace Utilities
{
template<typename T>
bool DoesSceneGraphContainDataLike(const Containers::Scene& scene, bool checkVirtualTypes)
{
static_assert(AZStd::is_base_of<DataTypes::IGraphObject, T>::value, "Specified type T is not derived from IGraphObject.");
const Containers::SceneGraph& graph = scene.GetGraph();
if (checkVirtualTypes)
{
auto contentStorage = graph.GetContentStorage();
auto view = Containers::Views::MakeFilterView(contentStorage, Containers::DerivedTypeFilter<T>());
for (auto it = view.begin(); it != view.end(); ++it)
{
AZStd::set<Crc32> types;
EBUS_EVENT(Events::GraphMetaInfoBus, GetVirtualTypes, types, scene, graph.ConvertToNodeIndex(it.GetBaseIterator()));
// Check if the type is not a virtual type. If it is, this isn't a valid type for T.
if (types.empty())
{
return true;
}
}
return false;
}
else
{
Containers::SceneGraph::ContentStorageConstData graphContent = graph.GetContentStorage();
auto data = AZStd::find_if(graphContent.begin(), graphContent.end(), Containers::DerivedTypeFilter<T>());
return data != graphContent.end();
}
}
} // Utilities
} // SceneAPI
} // AZ
@@ -0,0 +1,234 @@
#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/iterator.h>
#include <AzCore/std/typetraits/is_pointer.h>
#include <AzCore/std/typetraits/is_reference.h>
#include <AzCore/std/typetraits/remove_reference.h>
#include <AzCore/std/utils.h>
#include <SceneAPI/SceneCore/Containers/Views/View.h>
#include <SceneAPI/SceneCore/Containers/Utilities/ProxyPointer.h>
namespace AZ
{
namespace SceneAPI
{
namespace Containers
{
namespace Views
{
// Transform allows the value of the given iterator to be converted to the assigned TransformType when dereferencing.
// A typical use case would be to change a "const shared_ptr<type>" to "const shared<const type>" for read-only
// iteration of a vector<shared_ptr<type>>.
// template argument Iterator: the base iterator which will be used as the given iterator.
// template argument TransformType: the target type the value of base iterator will be converted to.
// This requires the type stored in iterator to have conversion to this type.
// template argument Category: the iterator classification. ConvertIterator will automatically derive this
// from the given iterator and match its behavior.
// Example:
// ConvertIterator<Vector<shared_ptr<Object>>::iterator, shared_ptr<const Object>>;
//
// WARNING
// Types used for conversion that are not convertible through a reference and pointer will return their result
// by-value instead of by-reference. This may cause some unexpected behavior the user should be aware of.
template<typename Iterator>
struct ConvertIteratorArgumentHelper
{
using ArgumentType = typename AZStd::conditional<AZStd::is_pointer<
typename AZStd::iterator_traits<Iterator>::value_type>::value,
typename AZStd::iterator_traits<Iterator>::value_type,
typename AZStd::iterator_traits<Iterator>::reference>::type;
};
template<typename Iterator, typename Function>
struct ConvertIteratorFunctionHelper
{
using ArgumentType = typename ConvertIteratorArgumentHelper<Iterator>::ArgumentType;
using ReturnType = AZStd::invoke_result_t<Function, ArgumentType>;
};
template<typename Iterator, typename ReturnType>
struct ConvertIteratorTypeHelper
{
using ArgumentType = typename ConvertIteratorArgumentHelper<Iterator>::ArgumentType;
using Function = ReturnType(*)(ArgumentType);
using PointerConditionType = typename AZStd::is_reference<ReturnType>::type;
using reference = ReturnType;
using pointer = typename AZStd::conditional<AZStd::is_reference<ReturnType>::value,
typename AZStd::remove_reference<ReturnType>::type*, ProxyPointer<ReturnType> >::type;
using value_type = typename AZStd::remove_reference<ReturnType>::type;
};
template<typename Iterator, typename ReturnType, typename Category = typename AZStd::iterator_traits<Iterator>::iterator_category>
class ConvertIterator
{
};
//
// Base iterator
//
template<typename Iterator, typename ReturnType>
class ConvertIterator<Iterator, ReturnType, void>
{
public:
using value_type = typename ConvertIteratorTypeHelper<Iterator, ReturnType>::value_type;
using difference_type = typename AZStd::iterator_traits<Iterator>::difference_type;
using pointer = typename ConvertIteratorTypeHelper<Iterator, ReturnType>::pointer;
using reference = typename ConvertIteratorTypeHelper<Iterator, ReturnType>::reference;
using iterator_category = typename AZStd::iterator_traits<Iterator>::iterator_category;
using Function = typename ConvertIteratorTypeHelper<Iterator, ReturnType>::Function;
using RootIterator = ConvertIterator<Iterator, ReturnType, iterator_category>;
ConvertIterator(Iterator iterator, Function converter);
ConvertIterator(const ConvertIterator&) = default;
ConvertIterator& operator=(const ConvertIterator&) = default;
RootIterator& operator++();
RootIterator operator++(int);
const Iterator& GetBaseIterator();
protected:
Iterator m_iterator;
Function m_converter;
};
//
// input_iterator_tag
//
template<typename Iterator, typename ReturnType>
class ConvertIterator<Iterator, ReturnType, AZStd::input_iterator_tag>
: public ConvertIterator<Iterator, ReturnType, void>
{
public:
using super = ConvertIterator<Iterator, ReturnType, void>;
ConvertIterator(Iterator iterator, typename super::Function converter);
ConvertIterator(const ConvertIterator&) = default;
typename super::reference operator*() const;
typename super::pointer operator->() const;
bool operator==(const typename super::RootIterator& rhs) const;
bool operator!=(const typename super::RootIterator& rhs) const;
protected:
// Used for pointer casts that don't require an intermediate value.
typename super::pointer GetPointer(AZStd::true_type castablePointer) const;
// Used for pointer casts that require an intermediate proxy object.
typename super::pointer GetPointer(AZStd::false_type intermediateValue) const;
};
//
// forward_iterator_tag
//
template<typename Iterator, typename ReturnType>
class ConvertIterator<Iterator, ReturnType, AZStd::forward_iterator_tag>
: public ConvertIterator<Iterator, ReturnType, AZStd::input_iterator_tag>
{
public:
using super = ConvertIterator<Iterator, ReturnType, AZStd::input_iterator_tag>;
ConvertIterator(Iterator iterator, typename super::Function converter);
ConvertIterator(const ConvertIterator&) = default;
ConvertIterator();
};
//
// bidirectional_iterator_tag
//
template<typename Iterator, typename ReturnType>
class ConvertIterator<Iterator, ReturnType, AZStd::bidirectional_iterator_tag>
: public ConvertIterator<Iterator, ReturnType, AZStd::forward_iterator_tag>
{
public:
using super = ConvertIterator<Iterator, ReturnType, AZStd::forward_iterator_tag>;
ConvertIterator(Iterator iterator, typename super::Function converter);
ConvertIterator(const ConvertIterator&) = default;
ConvertIterator();
typename super::RootIterator& operator--();
typename super::RootIterator operator--(int);
};
//
// random_access_iterator_tag
//
template<typename Iterator, typename ReturnType>
class ConvertIterator<Iterator, ReturnType, AZStd::random_access_iterator_tag>
: public ConvertIterator<Iterator, ReturnType, AZStd::bidirectional_iterator_tag>
{
public:
using super = ConvertIterator<Iterator, ReturnType, AZStd::bidirectional_iterator_tag>;
ConvertIterator(Iterator iterator, typename super::Function converter);
ConvertIterator(const ConvertIterator&) = default;
ConvertIterator();
typename super::reference operator[](size_t index);
bool operator<(const typename super::RootIterator& rhs) const;
bool operator>(const typename super::RootIterator& rhs) const;
bool operator<=(const typename super::RootIterator& rhs) const;
bool operator>=(const typename super::RootIterator& rhs) const;
typename super::RootIterator operator+(size_t n) const;
typename super::RootIterator operator-(size_t n) const;
typename super::difference_type operator-(const typename super::RootIterator& rhs) const;
typename super::RootIterator& operator+=(size_t n);
typename super::RootIterator& operator-=(size_t n);
};
// contiguous_iterator_tag
template<typename Iterator, typename ReturnType>
class ConvertIterator<Iterator, ReturnType, AZStd::contiguous_iterator_tag>
: public ConvertIterator<Iterator, ReturnType, AZStd::random_access_iterator_tag>
{
public:
using super = ConvertIterator<Iterator, ReturnType, AZStd::random_access_iterator_tag>;
ConvertIterator(Iterator iterator, typename super::Function converter);
ConvertIterator(const ConvertIterator&) = default;
ConvertIterator();
};
// Utility functions
template<typename Iterator, typename Function>
ConvertIterator<Iterator, typename ConvertIteratorFunctionHelper<Iterator, Function>::ReturnType>
MakeConvertIterator(Iterator iterator, Function converter);
template<typename Iterator, typename Function>
View<ConvertIterator<Iterator, typename ConvertIteratorFunctionHelper<Iterator, Function>::ReturnType>>
MakeConvertView(Iterator begin, Iterator end, Function converter);
template<typename ViewType, typename Function>
View<ConvertIterator<typename ViewType::iterator, typename ConvertIteratorFunctionHelper<typename ViewType::iterator, Function>::ReturnType>>
MakeConvertView(ViewType& view, Function converter);
template<typename ViewType, typename Function>
View<ConvertIterator<typename ViewType::const_iterator, typename ConvertIteratorFunctionHelper<typename ViewType::const_iterator, Function>::ReturnType>>
MakeConvertView(const ViewType& view, Function converter);
} // Views
} // Containers
} // SceneAPI
} // AZ
#include <SceneAPI/SceneCore/Containers/Views/ConvertIterator.inl>
@@ -0,0 +1,277 @@
/*
* 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/Debug/Trace.h>
namespace AZ
{
namespace SceneAPI
{
namespace Containers
{
namespace Views
{
//
// Base iterator
//
template<typename Iterator, typename ReturnType>
ConvertIterator<Iterator, ReturnType, void>::ConvertIterator(Iterator iterator, Function converter)
: m_iterator(iterator)
, m_converter(converter)
{
}
template<typename Iterator, typename ReturnType>
auto ConvertIterator<Iterator, ReturnType, void>::operator++()->RootIterator &
{
++m_iterator;
return *static_cast<RootIterator*>(this);
}
template<typename Iterator, typename ReturnType>
auto ConvertIterator<Iterator, ReturnType, void>::operator++(int)->RootIterator
{
RootIterator result = *static_cast<RootIterator*>(this);
++m_iterator;
return result;
}
template<typename Iterator, typename ReturnType>
const Iterator& ConvertIterator<Iterator, ReturnType, void>::GetBaseIterator()
{
return m_iterator;
}
//
// input_iterator_tag
//
template<typename Iterator, typename ReturnType>
ConvertIterator<Iterator, ReturnType, AZStd::input_iterator_tag>::ConvertIterator(Iterator iterator, typename super::Function converter)
: super(iterator, converter)
{
}
template<typename Iterator, typename ReturnType>
auto ConvertIterator<Iterator, ReturnType, AZStd::input_iterator_tag>::operator*() const->typename super::reference
{
AZ_Assert(super::m_converter, "No valid conversion function set for ConvertIterator.");
return super::m_converter(*super::m_iterator);
}
template<typename Iterator, typename ReturnType>
auto ConvertIterator<Iterator, ReturnType, AZStd::input_iterator_tag>::GetPointer(
[[maybe_unused]] AZStd::true_type castablePointer) const->typename super::pointer
{
AZ_Assert(super::m_converter, "No valid conversion function set for ConvertIterator.");
return &(super::m_converter(*super::m_iterator));
}
template<typename Iterator, typename ReturnType>
auto ConvertIterator<Iterator, ReturnType, AZStd::input_iterator_tag>::GetPointer(
[[maybe_unused]] AZStd::false_type intermediateValue) const->typename super::pointer
{
AZ_Assert(super::m_converter, "No valid conversion function set for ConvertIterator.");
return typename super::pointer(super::m_converter(*super::m_iterator));
}
template<typename Iterator, typename ReturnType>
auto ConvertIterator<Iterator, ReturnType, AZStd::input_iterator_tag>::operator->() const->typename super::pointer
{
return GetPointer(typename ConvertIteratorTypeHelper<Iterator, ReturnType>::PointerConditionType());
}
template<typename Iterator, typename ReturnType>
bool ConvertIterator<Iterator, ReturnType, AZStd::input_iterator_tag>::operator==(const typename super::RootIterator& rhs) const
{
return super::m_iterator == rhs.m_iterator;
}
template<typename Iterator, typename ReturnType>
bool ConvertIterator<Iterator, ReturnType, AZStd::input_iterator_tag>::operator!=(const typename super::RootIterator& rhs) const
{
return super::m_iterator != rhs.m_iterator;
}
//
// forward_iterator_tag
//
template<typename Iterator, typename ReturnType>
ConvertIterator<Iterator, ReturnType, AZStd::forward_iterator_tag>::ConvertIterator(Iterator iterator, typename super::Function converter)
: super(iterator, converter)
{
}
template<typename Iterator, typename ReturnType>
ConvertIterator<Iterator, ReturnType, AZStd::forward_iterator_tag>::ConvertIterator()
: super(Iterator(), nullptr)
{
}
//
// bidirectional_iterator_tag
//
template<typename Iterator, typename ReturnType>
ConvertIterator<Iterator, ReturnType, AZStd::bidirectional_iterator_tag>::ConvertIterator(Iterator iterator, typename super::Function converter)
: super(iterator, converter)
{
}
template<typename Iterator, typename ReturnType>
ConvertIterator<Iterator, ReturnType, AZStd::bidirectional_iterator_tag>::ConvertIterator()
: super()
{
}
template<typename Iterator, typename ReturnType>
auto ConvertIterator<Iterator, ReturnType, AZStd::bidirectional_iterator_tag>::operator--()->typename super::RootIterator &
{
--super::m_iterator;
return *static_cast<typename super::RootIterator*>(this);
}
template<typename Iterator, typename ReturnType>
auto ConvertIterator<Iterator, ReturnType, AZStd::bidirectional_iterator_tag>::operator--(int)->typename super::RootIterator
{
typename super::RootIterator result = *static_cast<typename super::RootIterator*>(this);
--super::m_iterator;
return result;
}
//
// random_access_iterator_tag
//
template<typename Iterator, typename ReturnType>
ConvertIterator<Iterator, ReturnType, AZStd::random_access_iterator_tag>::ConvertIterator(Iterator iterator, typename super::Function converter)
: super(iterator, converter)
{
}
template<typename Iterator, typename ReturnType>
ConvertIterator<Iterator, ReturnType, AZStd::random_access_iterator_tag>::ConvertIterator()
: super()
{
}
template<typename Iterator, typename ReturnType>
auto ConvertIterator<Iterator, ReturnType, AZStd::random_access_iterator_tag>::operator[](size_t index)->typename super::reference
{
AZ_Assert(super::m_converter, "No valid conversion function set for ConvertIterator.");
return super::m_converter(super::m_iterator[index]);
}
template<typename Iterator, typename ReturnType>
bool ConvertIterator<Iterator, ReturnType, AZStd::random_access_iterator_tag>::operator<(const typename super::RootIterator& rhs) const
{
return super::m_iterator < rhs.m_iterator;
}
template<typename Iterator, typename ReturnType>
bool ConvertIterator<Iterator, ReturnType, AZStd::random_access_iterator_tag>::operator>(const typename super::RootIterator& rhs) const
{
return super::m_iterator > rhs.m_iterator;
}
template<typename Iterator, typename ReturnType>
bool ConvertIterator<Iterator, ReturnType, AZStd::random_access_iterator_tag>::operator<=(const typename super::RootIterator& rhs) const
{
return super::m_iterator <= rhs.m_iterator;
}
template<typename Iterator, typename ReturnType>
bool ConvertIterator<Iterator, ReturnType, AZStd::random_access_iterator_tag>::operator>=(const typename super::RootIterator& rhs) const
{
return super::m_iterator >= rhs.m_iterator;
}
template<typename Iterator, typename ReturnType>
auto ConvertIterator<Iterator, ReturnType, AZStd::random_access_iterator_tag>::operator+(size_t n) const->typename super::RootIterator
{
typename super::RootIterator result = *static_cast<const typename super::RootIterator*>(this);
result.m_iterator += n;
return result;
}
template<typename Iterator, typename ReturnType>
auto ConvertIterator<Iterator, ReturnType, AZStd::random_access_iterator_tag>::operator-(size_t n) const->typename super::RootIterator
{
typename super::RootIterator result = *static_cast<const typename super::RootIterator*>(this);
result.m_iterator -= n;
return result;
}
template<typename Iterator, typename ReturnType>
auto ConvertIterator<Iterator, ReturnType, AZStd::random_access_iterator_tag>::operator-(const typename super::RootIterator& rhs) const->typename super::difference_type
{
return super::m_iterator - rhs.m_iterator;
}
template<typename Iterator, typename ReturnType>
auto ConvertIterator<Iterator, ReturnType, AZStd::random_access_iterator_tag>::operator+=(size_t n)->typename super::RootIterator &
{
super::m_iterator += n;
return *static_cast<typename super::RootIterator*>(this);
}
template<typename Iterator, typename ReturnType>
auto ConvertIterator<Iterator, ReturnType, AZStd::random_access_iterator_tag>::operator-=(size_t n)->typename super::RootIterator &
{
super::m_iterator -= n;
return *static_cast<typename super::RootIterator*>(this);
}
//
// contiguous_iterator_tag
//
template<typename Iterator, typename ReturnType>
ConvertIterator<Iterator, ReturnType, AZStd::contiguous_iterator_tag>::ConvertIterator(Iterator iterator, typename super::Function converter)
: super(iterator, converter)
{
}
template<typename Iterator, typename ReturnType>
ConvertIterator<Iterator, ReturnType, AZStd::contiguous_iterator_tag>::ConvertIterator()
: super()
{
}
// Utility functions
template<typename Iterator, typename Function>
ConvertIterator<Iterator, typename ConvertIteratorFunctionHelper<Iterator, Function>::ReturnType>
MakeConvertIterator(Iterator iterator, Function converter)
{
using ReturnType = typename ConvertIteratorFunctionHelper<Iterator, Function>::ReturnType;
return ConvertIterator<Iterator, ReturnType>(iterator, converter);
}
template<typename Iterator, typename Function>
View<ConvertIterator<Iterator, typename ConvertIteratorFunctionHelper<Iterator, Function>::ReturnType>>
MakeConvertView(Iterator begin, Iterator end, Function converter)
{
using ReturnType = typename ConvertIteratorFunctionHelper<Iterator, Function>::ReturnType;
return View<ConvertIterator<Iterator, ReturnType>>(
MakeConvertIterator(begin, converter),
MakeConvertIterator(end, converter));
}
template<typename ViewType, typename Function>
View<ConvertIterator<typename ViewType::iterator, typename ConvertIteratorFunctionHelper<typename ViewType::iterator, Function>::ReturnType>>
MakeConvertView(ViewType& view, Function converter)
{
return MakeConvertView(view.begin(), view.end(), converter);
}
template<typename ViewType, typename Function>
View<ConvertIterator<typename ViewType::const_iterator, typename ConvertIteratorFunctionHelper<typename ViewType::const_iterator, Function>::ReturnType>>
MakeConvertView(const ViewType& view, Function converter)
{
return MakeConvertView(view.begin(), view.end(), converter);
}
} // Views
} // Containers
} // SceneAPI
} // AZ
@@ -0,0 +1,244 @@
#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/utils.h>
#include <AzCore/std/iterator.h>
#include <AzCore/std/functional.h>
#include <AzCore/std/typetraits/is_base_of.h>
#include <SceneAPI/SceneCore/Containers/Views/View.h>
namespace AZ
{
namespace SceneAPI
{
namespace Containers
{
namespace Views
{
// Skips values in the iterator it wraps based on a given function's result.
// The predicate function takes the reference of the value of iterator as its
// argument and must return a boolean, where true means to accept the given
// iterator value and false if FilterIterator needs to skip to the next value.
// For complex iterators it's often easier to use decltype to derive the argument
// to the predicate function instead of fully specifying it. (See example below)
// Note:
// Because skipping happens while iterating, random access iterators will degrade
// to bidirectional iterators.
// Example:
// vector<int> list = { 10, 20, 30, 40, 50 };
// auto view = MakeFilterView(list.begin(), list.end(),
// [](int value) -> bool
// {
// return value >= 25;
// });
// for (auto it : view)
// {
// printf( "%i ", it );
// }
// result: 30 40 50
// Example:
// vector<int> list = { 10, 20, 30, 40, 50 };
// auto convertView = MakeConvertView<uint64_t>(list.begin(), list.end());
// auto filteredView = MakeFilterView(convertView,
// // Easier to read and automatically reflects any changes made in the view stack.
// [](const decltype(*convertView.begin())& object) -> bool
// {
// return value >= 25;
// });
template<typename Iterator, typename Category = typename AZStd::iterator_traits<Iterator>::iterator_category>
class FilterIterator
{
};
//
// Base iterator
//
template<typename Iterator>
class FilterIterator<Iterator, void>
{
public:
using value_type = typename AZStd::iterator_traits<Iterator>::value_type;
using difference_type = typename AZStd::iterator_traits<Iterator>::difference_type;
using pointer = typename AZStd::iterator_traits<Iterator>::pointer;
using reference = typename AZStd::iterator_traits<Iterator>::reference;
using iterator_category = typename AZStd::iterator_traits<Iterator>::iterator_category;
using RootIterator = FilterIterator<Iterator, iterator_category>;
using Predicate = AZStd::function<bool(const reference)>;
FilterIterator(Iterator iterator, Iterator end, const Predicate& predicate);
FilterIterator(const FilterIterator&) = default;
FilterIterator& operator=(const FilterIterator&) = default;
RootIterator& operator++();
RootIterator operator++(int);
const Iterator& GetBaseIterator();
protected:
// Pseudo default constructor.
// This is used because default constructing later on would trigger a predicate
// on an default constructed iterator, causing a crash when either using the
// predicate or dereferencing the iterator when trying to move forward.
explicit FilterIterator(Iterator defaultIterator);
void MoveToNext();
Iterator m_iterator;
Iterator m_end;
Predicate m_predicate;
};
//
// Input iterator
//
template<typename Iterator>
class FilterIterator<Iterator, AZStd::input_iterator_tag>
: public FilterIterator<Iterator, void>
{
public:
using super = FilterIterator<Iterator, void>;
FilterIterator(Iterator iterator, Iterator end, const typename super::Predicate& predicate);
FilterIterator(const FilterIterator& rhs) = default;
bool operator==(const typename super::RootIterator& rhs) const;
bool operator!=(const typename super::RootIterator& rhs) const;
typename super::reference operator*() const;
typename super::pointer operator->() const;
protected:
// Used when iterator is raw pointer
typename super::pointer GetPointer(AZStd::true_type) const;
// Used when iterator is an object
typename super::pointer GetPointer(AZStd::false_type) const;
// Pseudo default constructor.
explicit FilterIterator(Iterator defaultIterator);
};
//
// Forward iterator
//
template<typename Iterator>
class FilterIterator<Iterator, AZStd::forward_iterator_tag>
: public FilterIterator<Iterator, AZStd::input_iterator_tag>
{
public:
using super = FilterIterator<Iterator, AZStd::input_iterator_tag>;
FilterIterator(Iterator iterator, Iterator end, const typename super::Predicate& predicate);
FilterIterator(const FilterIterator& rhs) = default;
FilterIterator();
};
//
// Bidirectional iterator
//
template<typename Iterator>
class FilterIterator<Iterator, AZStd::bidirectional_iterator_tag>
: public FilterIterator<Iterator, AZStd::forward_iterator_tag>
{
public:
using super = FilterIterator<Iterator, AZStd::forward_iterator_tag>;
FilterIterator(Iterator iterator, Iterator end, const typename super::Predicate& predicate);
FilterIterator(Iterator iterator, Iterator begin, Iterator end, const typename super::Predicate& predicate);
FilterIterator(const FilterIterator& rhs) = default;
FilterIterator();
typename super::RootIterator& operator--();
typename super::RootIterator operator--(int);
protected:
void MoveToPrevious();
Iterator m_begin;
};
//
// Random Access iterator
// Because individual elements have to be inspected to know if they should be accepted, treat the random access iterator
// as a bidirectional iterator to force algorithms to inspect individual elements.
//
template<typename Iterator>
class FilterIterator<Iterator, AZStd::random_access_iterator_tag>
: public FilterIterator<Iterator, AZStd::bidirectional_iterator_tag>
{
public:
using super = FilterIterator<Iterator, AZStd::bidirectional_iterator_tag>;
using iterator_category = AZStd::bidirectional_iterator_tag;
FilterIterator(Iterator iterator, Iterator end, const typename super::Predicate& predicate);
FilterIterator(Iterator iterator, Iterator begin, Iterator end, const typename super::Predicate& predicate);
FilterIterator(const FilterIterator& rhs) = default;
FilterIterator();
};
//
// Contiguous Random Access iterator
// See Random Access iterator
//
template<typename Iterator>
class FilterIterator<Iterator, AZStd::contiguous_iterator_tag>
: public FilterIterator<Iterator, AZStd::bidirectional_iterator_tag>
{
public:
using super = FilterIterator<Iterator, AZStd::bidirectional_iterator_tag>;
using iterator_category = AZStd::bidirectional_iterator_tag;
FilterIterator(Iterator iterator, Iterator end, const typename super::Predicate& predicate);
FilterIterator(Iterator iterator, Iterator begin, Iterator end, const typename super::Predicate& predicate);
FilterIterator(const FilterIterator& rhs) = default;
FilterIterator();
};
//
// Utility functions
//
namespace Internal
{
template<typename Iterator>
struct FilterIteratorNeedsFullRange
{
// True if the Iterator can move backwards, which requires an end and a begin iterator, otherwise false and only
// an end iterator is needed.
static const bool value = AZStd::is_base_of<AZStd::bidirectional_iterator_tag, typename Iterator::iterator_category>::value;
};
}
template<typename Iterator>
FilterIterator<Iterator> MakeFilterIterator(Iterator current, Iterator end, const typename FilterIterator<Iterator, void>::Predicate& predicate);
template<typename Iterator, typename AZStd::enable_if<Internal::FilterIteratorNeedsFullRange<Iterator>::value>::type>
FilterIterator<Iterator> MakeFilterIterator(Iterator current, Iterator begin, Iterator end, const typename FilterIterator<Iterator, void>::Predicate& predicate);
template<typename Iterator>
View<FilterIterator<Iterator> > MakeFilterView(Iterator current, Iterator end, const typename FilterIterator<Iterator, void>::Predicate& predicate);
template<typename Iterator, typename AZStd::enable_if<Internal::FilterIteratorNeedsFullRange<Iterator>::value>::type>
View<FilterIterator<Iterator> > MakeFilterView(Iterator current, Iterator begin, Iterator end, const typename FilterIterator<Iterator>::Predicate& predicate);
template<typename ViewType>
View<FilterIterator<typename ViewType::iterator> > MakeFilterView(ViewType& view, const typename FilterIterator<typename ViewType::iterator>::Predicate& predicate);
template<typename ViewType>
const View<FilterIterator<typename ViewType::const_iterator> > MakeFilterView(const ViewType& view, const typename FilterIterator<typename ViewType::const_iterator>::Predicate& predicate);
} // Views
} // Containers
} // SceneAPI
} // AZ
#include <SceneAPI/SceneCore/Containers/Views/FilterIterator.inl>
@@ -0,0 +1,316 @@
/*
* 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/typetraits/is_pointer.h>
namespace AZ
{
namespace SceneAPI
{
namespace Containers
{
namespace Views
{
//
// Base iterator
//
template<typename Iterator>
FilterIterator<Iterator, void>::FilterIterator(Iterator iterator, Iterator end, const Predicate& predicate)
: m_iterator(iterator)
, m_end(end)
, m_predicate(predicate)
{
while (m_iterator != m_end && !m_predicate(*m_iterator))
{
AZStd::advance(m_iterator, 1);
}
}
template<typename Iterator>
FilterIterator<Iterator, void>::FilterIterator(Iterator defaultIterator)
: m_iterator(defaultIterator)
, m_end(defaultIterator)
, m_predicate()
{
}
template<typename Iterator>
auto FilterIterator<Iterator, void>::operator++()->RootIterator &
{
MoveToNext();
return *static_cast<RootIterator*>(this);
}
template<typename Iterator>
auto FilterIterator<Iterator, void>::operator++(int)->RootIterator
{
RootIterator result = *static_cast<RootIterator*>(this);
MoveToNext();
return result;
}
template<typename Iterator>
auto FilterIterator<Iterator, void>::GetBaseIterator()->const Iterator&
{
return m_iterator;
}
template<typename Iterator>
void FilterIterator<Iterator, void>::MoveToNext()
{
if (m_iterator != m_end)
{
AZStd::advance(m_iterator, 1);
}
while (m_iterator != m_end && !m_predicate(*m_iterator))
{
AZStd::advance(m_iterator, 1);
}
}
//
// Input iterator
//
template<typename Iterator>
FilterIterator<Iterator, AZStd::input_iterator_tag>::FilterIterator(Iterator iterator, Iterator end, const typename super::Predicate& predicate)
: super(iterator, end, predicate)
{
}
template<typename Iterator>
FilterIterator<Iterator, AZStd::input_iterator_tag>::FilterIterator(Iterator defaultIterator)
: super(defaultIterator)
{
}
template<typename Iterator>
bool FilterIterator<Iterator, AZStd::input_iterator_tag>::operator==(const typename super::RootIterator& rhs) const
{
return super::m_iterator == rhs.m_iterator;
}
template<typename Iterator>
bool FilterIterator<Iterator, AZStd::input_iterator_tag>::operator!=(const typename super::RootIterator& rhs) const
{
return super::m_iterator != rhs.m_iterator;
}
template<typename Iterator>
auto FilterIterator<Iterator, AZStd::input_iterator_tag>::operator*() const->typename super::reference
{
return static_cast<typename super::reference>(*super::m_iterator);
}
// Used when iterator is raw pointer
template<typename Iterator>
auto FilterIterator<Iterator, AZStd::input_iterator_tag>::GetPointer(AZStd::true_type) const->typename super::pointer
{
return super::m_iterator;
}
// Used when iterator is an object
template<typename Iterator>
auto FilterIterator<Iterator, AZStd::input_iterator_tag>::GetPointer(AZStd::false_type) const->typename super::pointer
{
return super::m_iterator.operator->();
}
template<typename Iterator>
auto FilterIterator<Iterator, AZStd::input_iterator_tag>::operator->() const->typename super::pointer
{
return GetPointer(typename AZStd::is_pointer<Iterator>::type());
}
//
// Forward iterator
//
template<typename Iterator>
FilterIterator<Iterator, AZStd::forward_iterator_tag>::FilterIterator(Iterator iterator, Iterator end, const typename super::Predicate& predicate)
: super(iterator, end, predicate)
{
}
template<typename Iterator>
FilterIterator<Iterator, AZStd::forward_iterator_tag>::FilterIterator()
: super(Iterator())
{
}
//
// Bidirectional iterator
//
template<typename Iterator>
FilterIterator<Iterator, AZStd::bidirectional_iterator_tag>::FilterIterator(Iterator iterator, Iterator end, const typename super::Predicate& predicate)
: super(iterator, end, predicate)
{
// Matches the iterator that's been moved forward to the first element that passes the predicate.
m_begin = super::m_iterator;
}
template<typename Iterator>
FilterIterator<Iterator, AZStd::bidirectional_iterator_tag>::FilterIterator(Iterator iterator, Iterator begin, Iterator end, const typename super::Predicate& predicate)
: super(iterator, end, predicate)
, m_begin(begin)
{
while (m_begin != super::m_end && !super::m_predicate(*m_begin))
{
AZStd::advance(m_begin, 1);
}
}
template<typename Iterator>
FilterIterator<Iterator, AZStd::bidirectional_iterator_tag>::FilterIterator()
: super()
{
}
template<typename Iterator>
auto FilterIterator<Iterator, AZStd::bidirectional_iterator_tag>::operator--()->typename super::RootIterator &
{
MoveToPrevious();
return *static_cast<typename super::RootIterator*>(this);
}
template<typename Iterator>
auto FilterIterator<Iterator, AZStd::bidirectional_iterator_tag>::operator--(int)->typename super::RootIterator
{
typename super::RootIterator result = *static_cast<typename super::RootIterator*>(this);
MoveToPrevious();
return result;
}
template<typename Iterator>
void FilterIterator<Iterator, AZStd::bidirectional_iterator_tag>::MoveToPrevious()
{
if (super::m_iterator != m_begin)
{
AZStd::advance(super::m_iterator, -1);
}
while (super::m_iterator != m_begin && !super::m_predicate(*super::m_iterator))
{
AZStd::advance(super::m_iterator, -1);
}
}
//
// Random Access iterator
//
template<typename Iterator>
FilterIterator<Iterator, AZStd::random_access_iterator_tag>::FilterIterator(Iterator iterator, Iterator end, const typename super::Predicate& predicate)
: super(iterator, end, predicate)
{
}
template<typename Iterator>
FilterIterator<Iterator, AZStd::random_access_iterator_tag>::FilterIterator(Iterator iterator, Iterator begin, Iterator end, const typename super::Predicate& predicate)
: super(iterator, begin, end, predicate)
{
}
template<typename Iterator>
FilterIterator<Iterator, AZStd::random_access_iterator_tag>::FilterIterator()
: super()
{
}
//
// Continuous Random Access iterator
//
template<typename Iterator>
FilterIterator<Iterator, AZStd::contiguous_iterator_tag>::FilterIterator(
Iterator iterator, Iterator end, const typename super::Predicate& predicate)
: super(iterator, end, predicate)
{
}
template<typename Iterator>
FilterIterator<Iterator, AZStd::contiguous_iterator_tag>::FilterIterator(
Iterator iterator, Iterator begin, Iterator end, const typename super::Predicate& predicate)
: super(iterator, begin, end, predicate)
{
}
template<typename Iterator>
FilterIterator<Iterator, AZStd::contiguous_iterator_tag>::FilterIterator()
: super()
{
}
//
// Utility functions
//
namespace Internal
{
template<typename Iterator>
View<FilterIterator<Iterator> > MakeFilterView(Iterator current, Iterator end,
const typename FilterIterator<Iterator>::Predicate& predicate, AZStd::false_type)
{
return View<FilterIterator<Iterator> >(
FilterIterator<Iterator>(current, end, predicate),
FilterIterator<Iterator>(end, end, predicate));
}
template<typename Iterator>
View<FilterIterator<Iterator> > MakeFilterView(Iterator current, Iterator end,
const typename FilterIterator<Iterator>::Predicate& predicate, AZStd::true_type)
{
return View<FilterIterator<Iterator> >(
FilterIterator<Iterator>(current, current, end, predicate),
FilterIterator<Iterator>(end, current, end, predicate));
}
}
template<typename Iterator>
FilterIterator<Iterator> MakeFilterIterator(Iterator current, Iterator end, const typename FilterIterator<Iterator, void>::Predicate& predicate)
{
return FilterIterator<Iterator>(current, end, predicate);
}
template<typename Iterator, typename AZStd::enable_if<Internal::FilterIteratorNeedsFullRange<Iterator>::value>::type>
FilterIterator<Iterator> MakeFilterIterator(Iterator current, Iterator begin, Iterator end, const typename FilterIterator<Iterator, void>::Predicate& predicate)
{
return FilterIterator<Iterator>(current, begin, end, predicate);
}
template<typename Iterator>
View<FilterIterator<Iterator> > MakeFilterView(Iterator current, Iterator end, const typename FilterIterator<Iterator, void>::Predicate& predicate)
{
return Internal::MakeFilterView(current, end, predicate,
typename AZStd::is_base_of<AZStd::bidirectional_iterator_tag, typename AZStd::iterator_traits<Iterator>::iterator_category>::type());
}
template<typename Iterator, typename AZStd::enable_if<Internal::FilterIteratorNeedsFullRange<Iterator>::value>::type>
View<FilterIterator<Iterator> > MakeFilterView(Iterator current, Iterator begin, Iterator end, const typename FilterIterator<Iterator>::Predicate& predicate)
{
return View<FilterIterator<Iterator> >(
FilterIterator<Iterator>(current, begin, end, predicate),
FilterIterator<Iterator>(end, begin, end, predicate));
}
template<typename ViewType>
View<FilterIterator<typename ViewType::iterator> > MakeFilterView(ViewType& view, const typename FilterIterator<typename ViewType::iterator>::Predicate& predicate)
{
return MakeFilterView(view.begin(), view.end(), predicate);
}
template<typename ViewType>
const View<FilterIterator<typename ViewType::const_iterator> > MakeFilterView(const ViewType& view, const typename FilterIterator<typename ViewType::const_iterator>::Predicate& predicate)
{
return MakeFilterView(view.begin(), view.end(), predicate);
}
} // Views
} // Containers
} // SceneAPI
} // AZ
@@ -0,0 +1,249 @@
#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 <utility>
#include <AzCore/std/utils.h>
#include <AzCore/std/typetraits/is_same.h>
#include <AzCore/std/typetraits/is_base_of.h>
#include <AzCore/std/iterator.h>
#include <SceneAPI/SceneCore/Containers/Views/View.h>
#include <SceneAPI/SceneCore/Containers/Utilities/ProxyPointer.h>
namespace AZ
{
namespace SceneAPI
{
namespace Containers
{
namespace Views
{
// Merges two iterators together that have a pair relation.
// Both iterators must point to the same relative entry and must contain
// the same amount of remaining increments (and decrements if appropriate).
// If the categories of the given iterators differ the PairIterator
// will only support functionality shared between them. The categories
// must be implementations of or be related to the categories defined by
// the C++ standard.
// Example:
// vector<string> names;
// vector<int> values;
// auto view = MakePairView(names.begin(), names.end(), values.begin(), values.end());
// for(auto it : view)
// {
// printf("%s has value %i\n", it.first.c_str(), it.second);
// }
namespace Internal
{
template<typename FirstIterator, typename SecondIterator>
struct PairIteratorCategory
{
static const bool s_sameCategory = AZStd::is_same<
typename AZStd::iterator_traits<FirstIterator>::iterator_category,
typename AZStd::iterator_traits<SecondIterator>::iterator_category>::value;
// True if both categories are the same.
// True if FirstIterator has the lower category in the hierarchy
// False if ValueItator has the lower category or is unrelated.
static const bool s_firstIteratorCategoryIsBaseOfSecondIterator = AZStd::is_base_of<
typename AZStd::iterator_traits<FirstIterator>::iterator_category,
typename AZStd::iterator_traits<SecondIterator>::iterator_category>::value;
// True if both categories are the same.
// True if SecondIterator has the lower category in the hierarchy
// False if FirstItator has the lower category or is unrelated.
static const bool s_SecondIteratorCategoryIsBaseOfFirstIterator = AZStd::is_base_of<
typename AZStd::iterator_traits<SecondIterator>::iterator_category,
typename AZStd::iterator_traits<FirstIterator>::iterator_category>::value;
static_assert(s_sameCategory || (s_firstIteratorCategoryIsBaseOfSecondIterator != s_SecondIteratorCategoryIsBaseOfFirstIterator),
"The iterator categories for the first and second in the PairIterator are unrelated categories.");
using Category = typename AZStd::conditional<s_firstIteratorCategoryIsBaseOfSecondIterator,
typename AZStd::iterator_traits<FirstIterator>::iterator_category,
typename AZStd::iterator_traits<SecondIterator>::iterator_category>::type;
};
}
template<typename FirstIterator, typename SecondIterator,
typename Category = typename Internal::PairIteratorCategory<FirstIterator, SecondIterator>::Category>
class PairIterator
{
};
//
// Base iterator
//
template<typename FirstIterator, typename SecondIterator>
class PairIterator<FirstIterator, SecondIterator, void>
{
public:
using value_type = AZStd::pair<typename AZStd::iterator_traits<FirstIterator>::value_type, typename AZStd::iterator_traits<SecondIterator>::value_type>;
using difference_type = AZStd::ptrdiff_t;
using reference = AZStd::pair<typename AZStd::iterator_traits<FirstIterator>::reference, typename AZStd::iterator_traits<SecondIterator>::reference>;
using pointer = ProxyPointer<reference>;
using iterator_category = typename Internal::PairIteratorCategory<FirstIterator, SecondIterator>::Category;
using RootIterator = PairIterator<FirstIterator, SecondIterator, iterator_category>;
PairIterator(FirstIterator First, SecondIterator second);
PairIterator(const PairIterator&) = default;
PairIterator& operator=(const PairIterator&) = default;
RootIterator& operator++();
RootIterator operator++(int);
const FirstIterator& GetFirstIterator();
const SecondIterator& GetSecondIterator();
protected:
FirstIterator m_first;
SecondIterator m_second;
};
//
// Input iterator
//
template<typename FirstIterator, typename SecondIterator>
class PairIterator<FirstIterator, SecondIterator, AZStd::input_iterator_tag>
: public PairIterator<FirstIterator, SecondIterator, void>
{
public:
using super = PairIterator<FirstIterator, SecondIterator, void>;
PairIterator(FirstIterator first, SecondIterator second);
PairIterator(const PairIterator& rhs) = default;
bool operator==(const typename super::RootIterator& rhs) const;
bool operator!=(const typename super::RootIterator& rhs) const;
typename super::reference operator*() const;
typename super::pointer operator->() const;
};
//
// Forward iterator
//
template<typename FirstIterator, typename SecondIterator>
class PairIterator<FirstIterator, SecondIterator, AZStd::forward_iterator_tag>
: public PairIterator<FirstIterator, SecondIterator, AZStd::input_iterator_tag>
{
public:
using super = PairIterator<FirstIterator, SecondIterator, AZStd::input_iterator_tag>;
PairIterator(FirstIterator first, SecondIterator second);
PairIterator(const PairIterator& rhs) = default;
PairIterator();
};
//
// Bidirectional iterator
//
template<typename FirstIterator, typename SecondIterator>
class PairIterator<FirstIterator, SecondIterator, AZStd::bidirectional_iterator_tag>
: public PairIterator<FirstIterator, SecondIterator, AZStd::forward_iterator_tag>
{
public:
using super = PairIterator<FirstIterator, SecondIterator, AZStd::forward_iterator_tag>;
PairIterator(FirstIterator first, SecondIterator second);
PairIterator(const PairIterator& rhs) = default;
PairIterator();
typename super::RootIterator& operator--();
typename super::RootIterator operator--(int);
};
//
// Random Access iterator
//
template<typename FirstIterator, typename SecondIterator>
class PairIterator<FirstIterator, SecondIterator, AZStd::random_access_iterator_tag>
: public PairIterator<FirstIterator, SecondIterator, AZStd::bidirectional_iterator_tag>
{
public:
using super = PairIterator<FirstIterator, SecondIterator, AZStd::bidirectional_iterator_tag>;
PairIterator(FirstIterator first, SecondIterator second);
PairIterator(const PairIterator& rhs) = default;
PairIterator();
typename super::reference operator[](size_t index);
bool operator<(const typename super::RootIterator& rhs) const;
bool operator>(const typename super::RootIterator& rhs) const;
bool operator<=(const typename super::RootIterator& rhs) const;
bool operator>=(const typename super::RootIterator& rhs) const;
typename super::RootIterator operator+(size_t n) const;
typename super::RootIterator operator-(size_t n) const;
typename super::difference_type operator-(const typename super::RootIterator& rhs) const;
typename super::RootIterator& operator+=(size_t n);
typename super::RootIterator& operator-=(size_t n);
};
//
// Contiguous Random Access iterator
//
template<typename FirstIterator, typename SecondIterator>
class PairIterator<FirstIterator, SecondIterator, AZStd::contiguous_iterator_tag>
: public PairIterator<FirstIterator, SecondIterator, AZStd::random_access_iterator_tag>
{
public:
using super = PairIterator<FirstIterator, SecondIterator, AZStd::random_access_iterator_tag>;
PairIterator(FirstIterator first, SecondIterator second);
PairIterator(const PairIterator& rhs) = default;
PairIterator();
};
//
// Utility functions
//
template<typename FirstIterator, typename SecondIterator>
PairIterator<FirstIterator, SecondIterator> MakePairIterator(FirstIterator first, SecondIterator second);
template<typename FirstIterator, typename SecondIterator>
View<PairIterator<FirstIterator, SecondIterator>>
MakePairView(FirstIterator firstBegin, FirstIterator firstEnd, SecondIterator secondBegin, SecondIterator secondEnd);
template<typename FirstView, typename SecondView>
View<PairIterator<typename FirstView::iterator, typename SecondView::iterator>>
MakePairView(FirstView& firstView, SecondView& secondView);
template<typename FirstView, typename SecondView>
View<PairIterator<typename FirstView::const_iterator, typename SecondView::iterator>>
MakePairView(const FirstView& firstView, SecondView& secondView);
template<typename FirstView, typename SecondView>
View<PairIterator<typename FirstView::iterator, typename SecondView::const_iterator>>
MakePairView(FirstView& firstView, const SecondView& secondView);
template<typename FirstView, typename SecondView>
View<PairIterator<typename FirstView::const_iterator, typename SecondView::const_iterator>>
MakePairView(const FirstView& firstView, const SecondView& secondView);
} // Views
} // Containers
} // SceneAPI
} // AZ
namespace AZStd
{
// iterator swap
template<typename First, typename Second>
void iter_swap(AZ::SceneAPI::Containers::Views::PairIterator<First, Second> lhs, AZ::SceneAPI::Containers::Views::PairIterator<First, Second> rhs);
}
#include <SceneAPI/SceneCore/Containers/Views/PairIterator.inl>
@@ -0,0 +1,318 @@
/*
* 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/Debug/Trace.h>
#include <AzCore/std/typetraits/remove_pointer.h>
#include <AzCore/std/typetraits/remove_reference.h>
namespace AZ
{
namespace SceneAPI
{
namespace Containers
{
namespace Views
{
//
// Base iterator
//
template<typename FirstIterator, typename SecondIterator>
PairIterator<FirstIterator, SecondIterator, void>::PairIterator(FirstIterator first, SecondIterator second)
: m_first(first)
, m_second(second)
{
}
template<typename FirstIterator, typename SecondIterator>
auto PairIterator<FirstIterator, SecondIterator, void>::operator++()->RootIterator &
{
++m_first;
++m_second;
return *static_cast<RootIterator*>(this);
}
template<typename FirstIterator, typename SecondIterator>
auto PairIterator<FirstIterator, SecondIterator, void>::operator++(int)->RootIterator
{
RootIterator result = *static_cast<RootIterator*>(this);
++m_first;
++m_second;
return result;
}
template<typename FirstIterator, typename SecondIterator>
auto PairIterator<FirstIterator, SecondIterator, void>::GetFirstIterator()->const FirstIterator&
{
return m_first;
}
template<typename FirstIterator, typename SecondIterator>
auto PairIterator<FirstIterator, SecondIterator, void>::GetSecondIterator()->const SecondIterator&
{
return m_second;
}
//
// Input iterator
//
template<typename FirstIterator, typename SecondIterator>
PairIterator<FirstIterator, SecondIterator, AZStd::input_iterator_tag>::PairIterator(FirstIterator first, SecondIterator second)
: super(first, second)
{
}
template<typename FirstIterator, typename SecondIterator>
bool PairIterator<FirstIterator, SecondIterator, AZStd::input_iterator_tag>::operator==(const typename super::RootIterator& rhs) const
{
return super::m_first == rhs.m_first && super::m_second == rhs.m_second;
}
template<typename FirstIterator, typename SecondIterator>
bool PairIterator<FirstIterator, SecondIterator, AZStd::input_iterator_tag>::operator!=(const typename super::RootIterator& rhs) const
{
return super::m_first != rhs.m_first || super::m_second != rhs.m_second;
}
template<typename FirstIterator, typename SecondIterator>
auto PairIterator<FirstIterator, SecondIterator, AZStd::input_iterator_tag>::operator*() const ->typename super::reference
{
return typename super::reference(*super::m_first, *super::m_second);
}
template<typename FirstIterator, typename SecondIterator>
auto PairIterator<FirstIterator, SecondIterator, AZStd::input_iterator_tag>::operator->() const ->typename super::pointer
{
return typename super::pointer(operator*());
}
//
// Forward iterator
//
template<typename FirstIterator, typename SecondIterator>
PairIterator<FirstIterator, SecondIterator, AZStd::forward_iterator_tag>::PairIterator(FirstIterator first, SecondIterator second)
: super(first, second)
{
}
template<typename FirstIterator, typename SecondIterator>
PairIterator<FirstIterator, SecondIterator, AZStd::forward_iterator_tag>::PairIterator()
: super(FirstIterator(), SecondIterator())
{
}
//
// Bidirectional iterator
//
template<typename FirstIterator, typename SecondIterator>
PairIterator<FirstIterator, SecondIterator, AZStd::bidirectional_iterator_tag>::PairIterator(FirstIterator first, SecondIterator second)
: super(first, second)
{
}
template<typename FirstIterator, typename SecondIterator>
PairIterator<FirstIterator, SecondIterator, AZStd::bidirectional_iterator_tag>::PairIterator()
: super()
{
}
template<typename FirstIterator, typename SecondIterator>
auto PairIterator<FirstIterator, SecondIterator, AZStd::bidirectional_iterator_tag>::operator--()->typename super::RootIterator &
{
--super::m_first;
--super::m_second;
return *static_cast<typename super::RootIterator*>(this);
}
template<typename FirstIterator, typename SecondIterator>
auto PairIterator<FirstIterator, SecondIterator, AZStd::bidirectional_iterator_tag>::operator--(int)->typename super::RootIterator
{
typename super::RootIterator result = *static_cast<typename super::RootIterator*>(this);
--super::m_first;
--super::m_second;
return result;
}
//
// Random Access iterator
//
template<typename FirstIterator, typename SecondIterator>
PairIterator<FirstIterator, SecondIterator, AZStd::random_access_iterator_tag>::PairIterator(FirstIterator first, SecondIterator second)
: super(first, second)
{
}
template<typename FirstIterator, typename SecondIterator>
PairIterator<FirstIterator, SecondIterator, AZStd::random_access_iterator_tag>::PairIterator()
: super()
{
}
template<typename FirstIterator, typename SecondIterator>
auto PairIterator<FirstIterator, SecondIterator, AZStd::random_access_iterator_tag>::operator[](size_t index)->typename super::reference
{
return typename super::reference(super::m_first[index], super::m_second[index]);
}
template<typename FirstIterator, typename SecondIterator>
bool IsSmaller(const FirstIterator& lhsFirst, const FirstIterator& lhsSecond, const SecondIterator& rhsFirst, const SecondIterator& rhsSecond)
{
return (lhsFirst < rhsFirst || (!(rhsFirst < lhsFirst) && lhsSecond < rhsSecond));
}
template<typename FirstIterator, typename SecondIterator>
bool PairIterator<FirstIterator, SecondIterator, AZStd::random_access_iterator_tag>::operator<(const typename super::RootIterator& rhs) const
{
return IsSmaller(super::m_first, super::m_second, rhs.m_first, rhs.m_second);
}
template<typename FirstIterator, typename SecondIterator>
bool PairIterator<FirstIterator, SecondIterator, AZStd::random_access_iterator_tag>::operator>(const typename super::RootIterator& rhs) const
{
return IsSmaller(rhs.m_first, rhs.m_second, super::m_first, super::m_second);
}
template<typename FirstIterator, typename SecondIterator>
bool PairIterator<FirstIterator, SecondIterator, AZStd::random_access_iterator_tag>::operator<=(const typename super::RootIterator& rhs) const
{
return !IsSmaller(rhs.m_first, rhs.m_second, super::m_first, super::m_second);
}
template<typename FirstIterator, typename SecondIterator>
bool PairIterator<FirstIterator, SecondIterator, AZStd::random_access_iterator_tag>::operator>=(const typename super::RootIterator& rhs) const
{
return !IsSmaller(super::m_first, super::m_second, rhs.m_first, rhs.m_second);
}
template<typename FirstIterator, typename SecondIterator>
auto PairIterator<FirstIterator, SecondIterator, AZStd::random_access_iterator_tag>::operator+(size_t n) const->typename super::RootIterator
{
typename super::RootIterator result = *static_cast<const typename super::RootIterator*>(this);
result.m_first += n;
result.m_second += n;
return result;
}
template<typename FirstIterator, typename SecondIterator>
auto PairIterator<FirstIterator, SecondIterator, AZStd::random_access_iterator_tag>::operator-(size_t n) const->typename super::RootIterator
{
typename super::RootIterator result = *static_cast<const typename super::RootIterator*>(this);
result.m_first -= n;
result.m_second -= n;
return result;
}
template<typename FirstIterator, typename SecondIterator>
auto PairIterator<FirstIterator, SecondIterator, AZStd::random_access_iterator_tag>::operator-(const typename super::RootIterator& rhs) const->typename super::difference_type
{
typename super::difference_type result = super::m_first - rhs.m_first;
AZ_Assert((super::m_second - rhs.m_second) == result, "First and second in PairIterator have gone out of lockstep.");
return result;
}
template<typename FirstIterator, typename SecondIterator>
auto PairIterator<FirstIterator, SecondIterator, AZStd::random_access_iterator_tag>::operator+=(size_t n)->typename super::RootIterator &
{
super::m_first += n;
super::m_second += n;
return *static_cast<typename super::RootIterator*>(this);
}
template<typename FirstIterator, typename SecondIterator>
auto PairIterator<FirstIterator, SecondIterator, AZStd::random_access_iterator_tag>::operator-=(size_t n)->typename super::RootIterator &
{
super::m_first -= n;
super::m_second -= n;
return *static_cast<typename super::RootIterator*>(this);
}
//
// Contiguous Random Access iterator
//
template<typename FirstIterator, typename SecondIterator>
PairIterator<FirstIterator, SecondIterator, AZStd::contiguous_iterator_tag>::PairIterator(
FirstIterator first, SecondIterator second)
: super(first, second)
{
}
template<typename FirstIterator, typename SecondIterator>
PairIterator<FirstIterator, SecondIterator, AZStd::contiguous_iterator_tag>::PairIterator()
: super()
{
}
//
// Utility functions
//
template<typename FirstIterator, typename SecondIterator>
PairIterator<FirstIterator, SecondIterator> MakePairIterator(FirstIterator first, SecondIterator second)
{
return PairIterator<FirstIterator, SecondIterator>(first, second);
}
template<typename FirstIterator, typename SecondIterator>
View<PairIterator<FirstIterator, SecondIterator>>
MakePairView(FirstIterator firstBegin, FirstIterator firstEnd, SecondIterator secondBegin, SecondIterator secondEnd)
{
return View<PairIterator<FirstIterator, SecondIterator>>(
PairIterator<FirstIterator, SecondIterator>(firstBegin, secondBegin),
PairIterator<FirstIterator, SecondIterator>(firstEnd, secondEnd));
}
template<typename FirstView, typename SecondView>
View<PairIterator<typename FirstView::iterator, typename SecondView::iterator>>
MakePairView(FirstView& firstView, SecondView& secondView)
{
return MakePairView(firstView.begin(), firstView.end(), secondView.begin(), secondView.end());
}
template<typename FirstView, typename SecondView>
View<PairIterator<typename FirstView::const_iterator, typename SecondView::iterator>>
MakePairView(const FirstView& firstView, SecondView& secondView)
{
return MakePairView(firstView.begin(), firstView.end(), secondView.begin(), secondView.end());
}
template<typename FirstView, typename SecondView>
View<PairIterator<typename FirstView::iterator, typename SecondView::const_iterator>>
MakePairView(FirstView& firstView, const SecondView& secondView)
{
return MakePairView(firstView.begin(), firstView.end(), secondView.begin(), secondView.end());
}
template<typename FirstView, typename SecondView>
View<PairIterator<typename FirstView::const_iterator, typename SecondView::const_iterator>>
MakePairView(const FirstView& firstView, const SecondView& secondView)
{
return MakePairView(firstView.begin(), firstView.end(), secondView.begin(), secondView.end());
}
} // Views
} // Containers
} // SceneAPI
} // AZ
namespace AZStd
{
// iterator swap
template<typename First, typename Second>
void iter_swap(AZ::SceneAPI::Containers::Views::PairIterator<First, Second> lhs, AZ::SceneAPI::Containers::Views::PairIterator<First, Second> rhs)
{
typename remove_pointer<typename remove_reference<First>::type>::type tmpFirst = (*lhs).first;
typename remove_pointer<typename remove_reference<Second>::type>::type tmpSecond = (*lhs).second;
(*lhs).first = (*rhs).first;
(*lhs).second = (*rhs).second;
(*rhs).first = tmpFirst;
(*rhs).second = tmpSecond;
}
}
@@ -0,0 +1,156 @@
#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 <iterator>
#include <type_traits>
#include <AzCore/std/iterator.h>
#include <AzCore/std/typetraits/is_base_of.h>
#include <SceneAPI/SceneCore/Containers/Views/View.h>
#include <SceneAPI/SceneCore/Containers/SceneGraph.h>
namespace AZ
{
namespace SceneAPI
{
namespace Containers
{
namespace Views
{
struct FilterAcceptanceTag {};
// Filter tag to only show regular nodes.
struct AcceptNodesOnly : public FilterAcceptanceTag {};
// Filter tag to only show end points.
struct AcceptEndPointsOnly : public FilterAcceptanceTag {};
// Filter tag to show all nodes.
struct AcceptAll : public FilterAcceptanceTag {};
// Iterator to traverse a SceneGraph from a given node by listing all the direct children. The given node will not be included in the
// iteration. By default all children are listed, but optionally only regular nodes or only end points can be returned by
// specifying the appropriate tag (see example below).
// Example:
// auto view = MakeSceneGraphChildView(graph, graph.ConvertToHierarchyIterator(nodeIndex), graph.GetNameStorage().begin(), true);
// for (auto& it : view)
// {
// printf("Node: %s\n", it.c_str());
// }
//
// Example:
// auto view = MakeSceneGraphChildView<AcceptEndPointsOnly>(graph, nodeIndex, graph.GetNameStorage().begin(), true);
// for (auto& it : view)
// {
// printf("End point: %s\n", it.c_str());
// }
template<typename Iterator, typename Filter = AcceptAll>
class SceneGraphChildIterator
{
static_assert(AZStd::is_base_of<FilterAcceptanceTag, Filter>::value,
"Filter for SceneGraphChildIterator is not a valid tag. Use AcceptNodesOnly, AcceptEndPointsOnly, AcceptAll or leave blank.");
static_assert(AZStd::is_base_of<AZStd::bidirectional_iterator_tag, typename AZStd::iterator_traits<Iterator>::iterator_category>::value,
"SceneGraphChildIterator needs at least a bidirectional iterator for its data iterator.");
public:
using value_type = typename AZStd::iterator_traits<Iterator>::value_type;
using difference_type = AZStd::ptrdiff_t;
using pointer = typename AZStd::iterator_traits<Iterator>::pointer;
using reference = typename AZStd::iterator_traits<Iterator>::reference;
using iterator_category = AZStd::forward_iterator_tag;
// Creates an iterator at a specified node in the hierarchy.
// graph: SceneGraph that will traversed.
// graphIterator: The node to start traversing from.
// iterator: The data iterator to be dereferenced from.
// rootIterator: If true the data iterator will be the first iterator from the data and
// this iterator will be moved forward to match the graph iterator. If false
// the graph iterator and the data iterator should be pointing to the same relative
// element.
SceneGraphChildIterator(const SceneGraph& graph, SceneGraph::HierarchyStorageConstIterator graphIterator, Iterator iterator, bool rootIterator);
SceneGraphChildIterator(const SceneGraphChildIterator&) = default;
SceneGraphChildIterator();
SceneGraphChildIterator& operator=(const SceneGraphChildIterator&) = default;
SceneGraphChildIterator& operator++();
SceneGraphChildIterator operator++(int);
bool operator==(const SceneGraphChildIterator& rhs) const;
bool operator!=(const SceneGraphChildIterator& rhs) const;
reference operator*() const;
pointer operator->() const;
SceneGraph::HierarchyStorageConstIterator GetHierarchyIterator() const;
private:
// For iterators that are raw pointers.
pointer GetPointer(AZStd::true_type) const;
// For all other types of iterator.
pointer GetPointer(AZStd::false_type) const;
void MoveToNext();
bool ShouldAcceptNode(AcceptNodesOnly) const;
bool ShouldAcceptNode(AcceptEndPointsOnly) const;
bool ShouldAcceptNode(AcceptAll) const;
const SceneGraph* m_graph;
Iterator m_iterator;
int32_t m_index;
};
//
// Iterator construction
//
template<typename Filter, typename Iterator>
SceneGraphChildIterator<Iterator, Filter> MakeSceneGraphChildIterator(
const SceneGraph& graph, SceneGraph::HierarchyStorageConstIterator graphIterator, Iterator iterator, bool rootIterator);
template<typename Filter, typename Iterator>
SceneGraphChildIterator<Iterator, Filter> MakeSceneGraphChildIterator(
const SceneGraph& graph, SceneGraph::NodeIndex node, Iterator iterator, bool rootIterator);
template<typename Iterator>
SceneGraphChildIterator<Iterator> MakeSceneGraphChildIterator(
const SceneGraph& graph, SceneGraph::HierarchyStorageConstIterator graphIterator, Iterator iterator, bool rootIterator);
template<typename Iterator>
SceneGraphChildIterator<Iterator> MakeSceneGraphChildIterator(
const SceneGraph& graph, SceneGraph::NodeIndex node, Iterator iterator, bool rootIterator);
//
// View construction
//
template<typename Filter, typename Iterator>
View<SceneGraphChildIterator<Iterator, Filter> > MakeSceneGraphChildView(
const SceneGraph& graph, SceneGraph::HierarchyStorageConstIterator graphIterator, Iterator iterator, bool rootIterator);
template<typename Filter, typename Iterator>
View<SceneGraphChildIterator<Iterator, Filter> > MakeSceneGraphChildView(
const SceneGraph& graph, SceneGraph::NodeIndex node, Iterator iterator, bool rootIterator);
template<typename Iterator>
View<SceneGraphChildIterator<Iterator> > MakeSceneGraphChildView(
const SceneGraph& graph, SceneGraph::HierarchyStorageConstIterator graphIterator, Iterator iterator, bool rootIterator);
template<typename Iterator>
View<SceneGraphChildIterator<Iterator> > MakeSceneGraphChildView(
const SceneGraph& graph, SceneGraph::NodeIndex node, Iterator iterator, bool rootIterator);
} // Views
} // Containers
} // SceneAPI
} // AZ
#include <SceneAPI/SceneCore/Containers/Views/SceneGraphChildIterator.inl>
@@ -0,0 +1,222 @@
/*
* 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 Containers
{
namespace Views
{
template<typename Iterator, typename Filter>
SceneGraphChildIterator<Iterator, Filter>::SceneGraphChildIterator(
const SceneGraph& graph, SceneGraph::HierarchyStorageConstIterator graphIterator, Iterator iterator, bool rootIterator)
: m_index(-1)
, m_graph(nullptr)
{
if (graph.GetHierarchyStorage().end() != graphIterator)
{
if (graphIterator->HasChild())
{
m_graph = &graph;
m_index = graphIterator->m_childIndex;
s32 delta = rootIterator ? static_cast<s32>(m_index) : graph.ConvertToNodeIndex(graphIterator).Distance(graphIterator->GetChildIndex());
m_iterator = AZStd::next(iterator, delta);
if (!ShouldAcceptNode(Filter()))
{
MoveToNext();
}
}
}
}
template<typename Iterator, typename Filter>
SceneGraphChildIterator<Iterator, Filter>::SceneGraphChildIterator()
: m_graph(nullptr)
, m_index(-1)
{
}
template<typename Iterator, typename Filter>
auto SceneGraphChildIterator<Iterator, Filter>::operator++()->SceneGraphChildIterator &
{
MoveToNext();
return *this;
}
template<typename Iterator, typename Filter>
auto SceneGraphChildIterator<Iterator, Filter>::operator++(int)->SceneGraphChildIterator
{
SceneGraphChildIterator result = *this;
MoveToNext();
return result;
}
template<typename Iterator, typename Filter>
bool SceneGraphChildIterator<Iterator, Filter>::operator==(const SceneGraphChildIterator& rhs) const
{
return m_graph == rhs.m_graph && m_index == rhs.m_index;
}
template<typename Iterator, typename Filter>
bool SceneGraphChildIterator<Iterator, Filter>::operator!=(const SceneGraphChildIterator& rhs) const
{
return m_graph != rhs.m_graph || m_index != rhs.m_index;
}
template<typename Iterator, typename Filter>
auto SceneGraphChildIterator<Iterator, Filter>::operator*() const->reference
{
return *m_iterator;
}
template<typename Iterator, typename Filter>
auto SceneGraphChildIterator<Iterator, Filter>::GetPointer(AZStd::true_type) const->pointer
{
return m_iterator;
}
template<typename Iterator, typename Filter>
auto SceneGraphChildIterator<Iterator, Filter>::GetPointer(AZStd::false_type) const->pointer
{
return m_iterator.operator->();
}
template<typename Iterator, typename Filter>
auto SceneGraphChildIterator<Iterator, Filter>::operator->() const->pointer
{
return GetPointer(typename AZStd::is_pointer<Iterator>::type());
}
template<typename Iterator, typename Filter>
SceneGraph::HierarchyStorageConstIterator SceneGraphChildIterator<Iterator, Filter>::GetHierarchyIterator() const
{
if (m_index >= 0)
{
return AZStd::next(m_graph->GetHierarchyStorage().begin(), m_index);
}
else
{
return SceneGraph::HierarchyStorageConstIterator();
}
}
template<typename Iterator, typename Filter>
void SceneGraphChildIterator<Iterator, Filter>::MoveToNext()
{
do
{
SceneGraph::NodeHeader header = m_graph->GetHierarchyStorage().begin()[m_index];
if (header.HasSibling())
{
AZStd::advance(m_iterator, header.m_siblingIndex - m_index);
m_index = header.m_siblingIndex;
}
else
{
m_index = -1;
m_graph = nullptr;
return;
}
} while (!ShouldAcceptNode(Filter()));
}
template<typename Iterator, typename Filter>
bool SceneGraphChildIterator<Iterator, Filter>::ShouldAcceptNode(AcceptNodesOnly) const
{
SceneGraph::NodeHeader header = m_graph->GetHierarchyStorage().begin()[m_index];
return !header.IsEndPoint();
}
template<typename Iterator, typename Filter>
bool SceneGraphChildIterator<Iterator, Filter>::ShouldAcceptNode(AcceptEndPointsOnly) const
{
SceneGraph::NodeHeader header = m_graph->GetHierarchyStorage().begin()[m_index];
return header.IsEndPoint();
}
template<typename Iterator, typename Filter>
bool SceneGraphChildIterator<Iterator, Filter>::ShouldAcceptNode(AcceptAll) const
{
return true;
}
template<typename Filter, typename Iterator>
SceneGraphChildIterator<Iterator, Filter> MakeSceneGraphChildIterator(
const SceneGraph& graph, SceneGraph::HierarchyStorageConstIterator graphIterator, Iterator iterator, bool rootIterator)
{
return SceneGraphChildIterator<Iterator, Filter>(graph, graphIterator, iterator, rootIterator);
}
template<typename Filter, typename Iterator>
SceneGraphChildIterator<Iterator, Filter> MakeSceneGraphChildIterator(
const SceneGraph& graph, SceneGraph::NodeIndex node, Iterator iterator, bool rootIterator)
{
return SceneGraphChildIterator<Iterator, Filter>(graph, graph.ConvertToHierarchyIterator(node), iterator, rootIterator);
}
template<typename Iterator>
SceneGraphChildIterator<Iterator> MakeSceneGraphChildIterator(
const SceneGraph& graph, SceneGraph::HierarchyStorageConstIterator graphIterator, Iterator iterator, bool rootIterator)
{
return SceneGraphChildIterator<Iterator>(graph, graphIterator, iterator, rootIterator);
}
template<typename Iterator>
SceneGraphChildIterator<Iterator> MakeSceneGraphChildIterator(
const SceneGraph& graph, SceneGraph::NodeIndex node, Iterator iterator, bool rootIterator)
{
return SceneGraphChildIterator<Iterator>(graph, graph.ConvertToHierarchyIterator(node), iterator, rootIterator);
}
template<typename Filter, typename Iterator>
View<SceneGraphChildIterator<Iterator, Filter> > MakeSceneGraphChildView(
const SceneGraph& graph, SceneGraph::HierarchyStorageConstIterator graphIterator, Iterator iterator, bool rootIterator)
{
return View<SceneGraphChildIterator<Iterator, Filter> >(
SceneGraphChildIterator<Iterator, Filter>(graph, graphIterator, iterator, rootIterator),
SceneGraphChildIterator<Iterator, Filter>());
}
template<typename Filter, typename Iterator>
View<SceneGraphChildIterator<Iterator, Filter> > MakeSceneGraphChildView(
const SceneGraph& graph, SceneGraph::NodeIndex node, Iterator iterator, bool rootIterator)
{
return View<SceneGraphChildIterator<Iterator, Filter> >(
SceneGraphChildIterator<Iterator, Filter>(graph, graph.ConvertToHierarchyIterator(node), iterator, rootIterator),
SceneGraphChildIterator<Iterator, Filter>());
}
template<typename Iterator>
View<SceneGraphChildIterator<Iterator> > MakeSceneGraphChildView(
const SceneGraph& graph, SceneGraph::HierarchyStorageConstIterator graphIterator, Iterator iterator, bool rootIterator)
{
return View<SceneGraphChildIterator<Iterator> >(
SceneGraphChildIterator<Iterator>(graph, graphIterator, iterator, rootIterator),
SceneGraphChildIterator<Iterator>());
}
template<typename Iterator>
View<SceneGraphChildIterator<Iterator> > MakeSceneGraphChildView(
const SceneGraph& graph, SceneGraph::NodeIndex node, Iterator iterator, bool rootIterator)
{
return View<SceneGraphChildIterator<Iterator> >(
SceneGraphChildIterator<Iterator>(graph, graph.ConvertToHierarchyIterator(node), iterator, rootIterator),
SceneGraphChildIterator<Iterator>());
}
} // Views
} // Containers
} // SceneAPI
} // AZ
@@ -0,0 +1,135 @@
#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 <deque>
#include <iterator>
#include <type_traits>
#include <AzCore/std/iterator.h>
#include <SceneAPI/SceneCore/Containers/SceneGraph.h>
#include <SceneAPI/SceneCore/Containers/Views/View.h>
namespace AZ
{
namespace SceneAPI
{
namespace Containers
{
namespace Views
{
// Tag for depth-first traversal
struct DepthFirst {};
// Tag for breadth-first traversal
struct BreadthFirst {};
// Iterator to traverse a SceneGraph downwards from the root or a given hierarchy iterator either
// depth-first or breadth-first. If a hierarchy iterator is specified it will be the first
// entry returned, otherwise the root.
// Example:
// auto view = MakeSceneGraphDownwardsView<DepthFirst>(graph, graph.GetNameStorage().begin());
// for (auto it : view)
// {
// printf("Node: %s\n", it.c_str());
// }
// Example:
// SceneGraph::NodeIndex search = graph.Find("A.C");
// auto view = MakeSceneGraphDownwardsView<BreadthFirst>(graph, graph.ConvertToHierarchyIterator(search), graph.GetNameStorage().begin(), true);
// for (auto it : view)
// {
// printf("Node: %s\n", it.c_str());
// }
template<typename Iterator, typename Traversal>
class SceneGraphDownwardsIterator
{
static_assert(std::is_base_of<AZStd::bidirectional_iterator_tag, typename AZStd::iterator_traits<Iterator>::iterator_category>::value,
"SceneGraphDownwardsIterator needs at least a bidrectional iterator for its data iterator.");
public:
using value_type = typename AZStd::iterator_traits<Iterator>::value_type;
using difference_type = std::ptrdiff_t;
using pointer = typename AZStd::iterator_traits<Iterator>::pointer;
using reference = typename AZStd::iterator_traits<Iterator>::reference;
using iterator_category = AZStd::forward_iterator_tag;
// Creates an iterator at the root node in the hierarchy.
SceneGraphDownwardsIterator(const SceneGraph& graph, Iterator iterator);
// Creates an iterator at a specified node in the hierarchy.
// graph: SceneGraph that will traversed.
// graphIterator: The node to start traversing from.
// iterator: The data iterator to be dereferenced from.
// rootIterator: If true the data iterator will be the first iterator from the data and
// this iterator will be moved forward to match the graph iterator. If false
// the graph iterator and the data iterator should be pointing to the same relative
// element.
SceneGraphDownwardsIterator(const SceneGraph& graph, SceneGraph::HierarchyStorageConstIterator graphIterator, Iterator iterator, bool rootIterator);
SceneGraphDownwardsIterator(const SceneGraphDownwardsIterator&) = default;
SceneGraphDownwardsIterator();
SceneGraphDownwardsIterator& operator=(const SceneGraphDownwardsIterator&) = default;
SceneGraphDownwardsIterator& operator++();
SceneGraphDownwardsIterator operator++(int);
bool operator==(const SceneGraphDownwardsIterator& rhs) const;
bool operator!=(const SceneGraphDownwardsIterator& rhs) const;
reference operator*() const;
pointer operator->() const;
SceneGraph::HierarchyStorageConstIterator GetHierarchyIterator() const;
// Stops the iterator from descending into the children of the current node. Pending nodes and their children will be processed as normal.
// This call can be made multiple times for different nodes.
void IgnoreNodeDescendants();
private:
// For iterators that are raw pointers.
pointer GetPointer(AZStd::true_type) const;
// For all other types of iterator.
pointer GetPointer(AZStd::false_type) const;
void MoveToNext(DepthFirst);
void MoveToNext(BreadthFirst);
void JumpTo(int32_t index);
std::deque<int32_t> m_pending;
const SceneGraph* m_graph;
Iterator m_iterator;
int32_t m_index : 30;
int32_t m_firstNode : 1;
int32_t m_ignoreDescendants : 1;
};
template<typename Traversal, typename Iterator>
SceneGraphDownwardsIterator<Iterator, Traversal> MakeSceneGraphDownwardsIterator(const SceneGraph& graph, Iterator iterator);
template<typename Traversal, typename Iterator>
SceneGraphDownwardsIterator<Iterator, Traversal> MakeSceneGraphDownwardsIterator(
const SceneGraph& graph, SceneGraph::HierarchyStorageConstIterator graphIterator, Iterator iterator, bool rootIterator);
template<typename Traversal, typename Iterator>
SceneGraphDownwardsIterator<Iterator, Traversal> MakeSceneGraphDownwardsIterator(
const SceneGraph& graph, SceneGraph::NodeIndex node, Iterator iterator, bool rootIterator);
template<typename Traversal, typename Iterator>
View<SceneGraphDownwardsIterator<Iterator, Traversal> > MakeSceneGraphDownwardsView(const SceneGraph& graph, Iterator iterator);
template<typename Traversal, typename Iterator>
View<SceneGraphDownwardsIterator<Iterator, Traversal> > MakeSceneGraphDownwardsView(
const SceneGraph& graph, SceneGraph::HierarchyStorageConstIterator graphIterator, Iterator iterator, bool rootIterator);
template<typename Traversal, typename Iterator>
View<SceneGraphDownwardsIterator<Iterator, Traversal> > MakeSceneGraphDownwardsView(
const SceneGraph& graph, SceneGraph::NodeIndex node, Iterator iterator, bool rootIterator);
} // Views
} // Containers
} // SceneAPI
} // AZ
#include <SceneAPI/SceneCore/Containers/Views/SceneGraphDownwardsIterator.inl>
@@ -0,0 +1,242 @@
/*
* 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/typetraits/is_pointer.h>
namespace AZ
{
namespace SceneAPI
{
namespace Containers
{
namespace Views
{
template<typename Iterator, typename Traversal>
SceneGraphDownwardsIterator<Iterator, Traversal>::SceneGraphDownwardsIterator(const SceneGraph& graph, Iterator iterator)
: m_graph(&graph)
, m_iterator(iterator)
, m_index(0)
, m_ignoreDescendants(false)
, m_firstNode(true)
{
}
template<typename Iterator, typename Traversal>
SceneGraphDownwardsIterator<Iterator, Traversal>::SceneGraphDownwardsIterator(
const SceneGraph& graph, SceneGraph::HierarchyStorageConstIterator graphIterator, Iterator iterator, bool rootIterator)
: m_ignoreDescendants(false)
, m_firstNode(true)
{
if (graph.GetHierarchyStorage().end() == graphIterator)
{
m_index = -1;
m_graph = nullptr;
}
else
{
m_graph = &graph;
m_index = static_cast<int32_t>(AZStd::distance(graph.GetHierarchyStorage().begin(), graphIterator));
m_iterator = rootIterator ? AZStd::next(iterator, m_index) : iterator;
}
}
template<typename Iterator, typename Traversal>
SceneGraphDownwardsIterator<Iterator, Traversal>::SceneGraphDownwardsIterator()
: m_graph(nullptr)
, m_index(-1)
, m_ignoreDescendants(false)
, m_firstNode(false)
{
}
template<typename Iterator, typename Traversal>
auto SceneGraphDownwardsIterator<Iterator, Traversal>::operator++()->SceneGraphDownwardsIterator &
{
MoveToNext(Traversal());
return *this;
}
template<typename Iterator, typename Traversal>
auto SceneGraphDownwardsIterator<Iterator, Traversal>::operator++(int)->SceneGraphDownwardsIterator
{
SceneGraphDownwardsIterator result = *this;
MoveToNext(Traversal());
return result;
}
template<typename Iterator, typename Traversal>
bool SceneGraphDownwardsIterator<Iterator, Traversal>::operator==(const SceneGraphDownwardsIterator& rhs) const
{
return m_graph == rhs.m_graph && m_index == rhs.m_index && m_firstNode == rhs.m_firstNode;
}
template<typename Iterator, typename Traversal>
bool SceneGraphDownwardsIterator<Iterator, Traversal>::operator!=(const SceneGraphDownwardsIterator& rhs) const
{
return m_graph != rhs.m_graph || m_index != rhs.m_index || m_firstNode != rhs.m_firstNode;
}
template<typename Iterator, typename Traversal>
auto SceneGraphDownwardsIterator<Iterator, Traversal>::operator*() const->reference
{
return *m_iterator;
}
template<typename Iterator, typename Traversal>
auto SceneGraphDownwardsIterator<Iterator, Traversal>::GetPointer(AZStd::true_type) const->pointer
{
return m_iterator;
}
template<typename Iterator, typename Traversal>
auto SceneGraphDownwardsIterator<Iterator, Traversal>::GetPointer(AZStd::false_type) const->pointer
{
return m_iterator.operator->();
}
template<typename Iterator, typename Traversal>
auto SceneGraphDownwardsIterator<Iterator, Traversal>::operator->() const->pointer
{
return GetPointer(typename AZStd::is_pointer<Iterator>::type());
}
template<typename Iterator, typename Traversal>
SceneGraph::HierarchyStorageConstIterator SceneGraphDownwardsIterator<Iterator, Traversal>::GetHierarchyIterator() const
{
if (m_index >= 0)
{
return AZStd::next(m_graph->GetHierarchyStorage().begin(), m_index);
}
else
{
return SceneGraph::HierarchyStorageConstIterator();
}
}
template<typename Iterator, typename Traversal>
void SceneGraphDownwardsIterator<Iterator, Traversal>::IgnoreNodeDescendants()
{
m_ignoreDescendants = true;
}
template<typename Iterator, typename Traversal>
void SceneGraphDownwardsIterator<Iterator, Traversal>::MoveToNext(DepthFirst)
{
AZ_Assert(m_graph, "Invalid iterator or moved passed end of list.");
SceneGraph::NodeHeader header = m_graph->GetHierarchyStorage().begin()[m_index];
if (!m_firstNode && header.HasSibling())
{
m_pending.push_back(static_cast<int32_t>(header.m_siblingIndex));
}
if (!m_ignoreDescendants && header.HasChild())
{
JumpTo(header.m_childIndex);
}
else if (!m_pending.empty())
{
JumpTo(m_pending.back());
m_pending.pop_back();
}
else
{
m_index = -1;
m_graph = nullptr;
}
m_ignoreDescendants = false;
m_firstNode = false;
}
template<typename Iterator, typename Traversal>
void SceneGraphDownwardsIterator<Iterator, Traversal>::MoveToNext(BreadthFirst)
{
AZ_Assert(m_graph, "Invalid iterator or moved passed end of list.");
SceneGraph::NodeHeader header = m_graph->GetHierarchyStorage().begin()[m_index];
if (!m_ignoreDescendants && header.HasChild())
{
m_pending.push_back(static_cast<int32_t>(header.m_childIndex));
}
if (!m_firstNode && header.HasSibling())
{
JumpTo(header.m_siblingIndex);
}
else if (!m_pending.empty())
{
JumpTo(m_pending.front());
m_pending.pop_front();
}
else
{
m_index = -1;
m_graph = nullptr;
}
m_ignoreDescendants = false;
m_firstNode = false;
}
template<typename Iterator, typename Traversal>
void SceneGraphDownwardsIterator<Iterator, Traversal>::JumpTo(int32_t index)
{
AZStd::advance(m_iterator, index - m_index);
m_index = index;
}
template<typename Traversal, typename Iterator>
SceneGraphDownwardsIterator<Iterator, Traversal> MakeSceneGraphDownwardsIterator(const SceneGraph& graph, Iterator iterator)
{
return SceneGraphDownwardsIterator<Iterator, Traversal>(graph, iterator);
}
template<typename Traversal, typename Iterator>
SceneGraphDownwardsIterator<Iterator, Traversal> MakeSceneGraphDownwardsIterator(
const SceneGraph& graph, SceneGraph::HierarchyStorageConstIterator graphIterator, Iterator iterator, bool rootIterator)
{
return SceneGraphDownwardsIterator<Iterator, Traversal>(graph, graphIterator, iterator, rootIterator);
}
template<typename Traversal, typename Iterator>
SceneGraphDownwardsIterator<Iterator, Traversal> MakeSceneGraphDownwardsIterator(
const SceneGraph& graph, SceneGraph::NodeIndex node, Iterator iterator, bool rootIterator)
{
return SceneGraphDownwardsIterator<Iterator, Traversal>(graph, graph.ConvertToHierarchyIterator(node), iterator, rootIterator);
}
template<typename Traversal, typename Iterator>
View<SceneGraphDownwardsIterator<Iterator, Traversal> > MakeSceneGraphDownwardsView(const SceneGraph& graph, Iterator iterator)
{
return View<SceneGraphDownwardsIterator<Iterator, Traversal> >(
SceneGraphDownwardsIterator<Iterator, Traversal>(graph, iterator),
SceneGraphDownwardsIterator<Iterator, Traversal>());
}
template<typename Traversal, typename Iterator>
View<SceneGraphDownwardsIterator<Iterator, Traversal> > MakeSceneGraphDownwardsView(
const SceneGraph& graph, SceneGraph::HierarchyStorageConstIterator graphIterator, Iterator iterator, bool rootIterator)
{
return View<SceneGraphDownwardsIterator<Iterator, Traversal> >(
SceneGraphDownwardsIterator<Iterator, Traversal>(graph, graphIterator, iterator, rootIterator),
SceneGraphDownwardsIterator<Iterator, Traversal>());
}
template<typename Traversal, typename Iterator>
View<SceneGraphDownwardsIterator<Iterator, Traversal> > MakeSceneGraphDownwardsView(
const SceneGraph& graph, SceneGraph::NodeIndex node, Iterator iterator, bool rootIterator)
{
return View<SceneGraphDownwardsIterator<Iterator, Traversal> >(
SceneGraphDownwardsIterator<Iterator, Traversal>(graph, graph.ConvertToHierarchyIterator(node), iterator, rootIterator),
SceneGraphDownwardsIterator<Iterator, Traversal>());
}
} // Views
} // Containers
} // SceneAPI
} // AZ
@@ -0,0 +1,109 @@
#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 <stack>
#include <iterator>
#include <type_traits>
#include <AzCore/std/iterator.h>
#include <AzCore/std/typetraits/is_base_of.h>
#include <SceneAPI/SceneCore/Containers/Views/View.h>
#include <SceneAPI/SceneCore/Containers/SceneGraph.h>
namespace AZ
{
namespace SceneAPI
{
namespace Containers
{
namespace Views
{
// Iterator to traverse a SceneGraph from a given node upwards to the root.
// The given node will be included as the first returned value.
// Example:
// auto view = MakeSceneGraphUpwardsView(graph, graph.ConvertToHierarchyIterator(nodeIndex), graph.GetNameStorage().begin(), true);
// for (auto it : view)
// {
// printf("Node: %s\n", it.c_str());
// }
template<typename Iterator>
class SceneGraphUpwardsIterator
{
static_assert(AZStd::is_base_of<AZStd::bidirectional_iterator_tag, typename AZStd::iterator_traits<Iterator>::iterator_category>::value,
"SceneGraphUpwardsIterator needs at least a bidrectional iterator for its data iterator.");
public:
using value_type = typename AZStd::iterator_traits<Iterator>::value_type;
using difference_type = AZStd::ptrdiff_t;
using pointer = typename AZStd::iterator_traits<Iterator>::pointer;
using reference = typename AZStd::iterator_traits<Iterator>::reference;
using iterator_category = AZStd::forward_iterator_tag;
// Creates an iterator at a specified node in the hierarchy.
// graph: SceneGraph that will traversed.
// graphIterator: The node to start traversing from.
// iterator: The data iterator to be dereferenced from.
// rootIterator: If true the data iterator will be the first iterator from the data and
// this iterator will be moved forward to match the graph iterator. If false
// the graph iterator and the data iterator should be pointing to the same relative
// element.
SceneGraphUpwardsIterator(const SceneGraph& graph, SceneGraph::HierarchyStorageConstIterator graphIterator, Iterator iterator, bool rootIterator);
SceneGraphUpwardsIterator(const SceneGraphUpwardsIterator&) = default;
SceneGraphUpwardsIterator();
SceneGraphUpwardsIterator& operator=(const SceneGraphUpwardsIterator&) = default;
SceneGraphUpwardsIterator& operator++();
SceneGraphUpwardsIterator operator++(int);
bool operator==(const SceneGraphUpwardsIterator& rhs) const;
bool operator!=(const SceneGraphUpwardsIterator& rhs) const;
reference operator*() const;
pointer operator->() const;
SceneGraph::HierarchyStorageConstIterator GetHierarchyIterator() const;
private:
// For iterators that are raw pointers.
pointer GetPointer(AZStd::true_type) const;
// For all other types of iterator.
pointer GetPointer(AZStd::false_type) const;
void MoveToNext();
const SceneGraph* m_graph;
Iterator m_iterator;
int32_t m_index;
};
template<typename Iterator>
SceneGraphUpwardsIterator<Iterator> MakeSceneGraphUpwardsIterator(
const SceneGraph& graph, SceneGraph::HierarchyStorageConstIterator graphIterator, Iterator iterator, bool rootIterator);
template<typename Iterator>
SceneGraphUpwardsIterator<Iterator> MakeSceneGraphUpwardsIterator(
const SceneGraph& graph, SceneGraph::NodeIndex node, Iterator iterator, bool rootIterator);
template<typename Iterator>
View<SceneGraphUpwardsIterator<Iterator> > MakeSceneGraphUpwardsView(
const SceneGraph& graph, SceneGraph::HierarchyStorageConstIterator graphIterator, Iterator iterator, bool rootIterator);
template<typename Iterator>
View<SceneGraphUpwardsIterator<Iterator> > MakeSceneGraphUpwardsView(
const SceneGraph& graph, SceneGraph::NodeIndex node, Iterator iterator, bool rootIterator);
} // Views
} // Containers
} // SceneAPI
} // AZ
#include <SceneAPI/SceneCore/Containers/Views/SceneGraphUpwardsIterator.inl>
@@ -0,0 +1,153 @@
/*
* 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 Containers
{
namespace Views
{
template<typename Iterator>
SceneGraphUpwardsIterator<Iterator>::SceneGraphUpwardsIterator(
const SceneGraph& graph, SceneGraph::HierarchyStorageConstIterator graphIterator, Iterator iterator, bool rootIterator)
{
if (graph.GetHierarchyStorage().end() == graphIterator)
{
m_index = -1;
m_graph = nullptr;
}
else
{
m_graph = &graph;
m_index = static_cast<int32_t>(AZStd::distance(graph.GetHierarchyStorage().begin(), graphIterator));
m_iterator = rootIterator ? AZStd::next(iterator, m_index) : iterator;
}
}
template<typename Iterator>
SceneGraphUpwardsIterator<Iterator>::SceneGraphUpwardsIterator()
: m_graph(nullptr)
, m_index(-1)
{
}
template<typename Iterator>
auto SceneGraphUpwardsIterator<Iterator>::operator++()->SceneGraphUpwardsIterator &
{
MoveToNext();
return *this;
}
template<typename Iterator>
auto SceneGraphUpwardsIterator<Iterator>::operator++(int)->SceneGraphUpwardsIterator
{
SceneGraphUpwardsIterator result = *this;
MoveToNext();
return result;
}
template<typename Iterator>
bool SceneGraphUpwardsIterator<Iterator>::operator==(const SceneGraphUpwardsIterator& rhs) const
{
return m_graph == rhs.m_graph && m_index == rhs.m_index;
}
template<typename Iterator>
bool SceneGraphUpwardsIterator<Iterator>::operator!=(const SceneGraphUpwardsIterator& rhs) const
{
return m_graph != rhs.m_graph || m_index != rhs.m_index;
}
template<typename Iterator>
auto SceneGraphUpwardsIterator<Iterator>::operator*() const->reference
{
return *m_iterator;
}
template<typename Iterator>
auto SceneGraphUpwardsIterator<Iterator>::GetPointer(AZStd::true_type) const->pointer
{
return m_iterator;
}
template<typename Iterator>
auto SceneGraphUpwardsIterator<Iterator>::GetPointer(AZStd::false_type) const->pointer
{
return m_iterator.operator->();
}
template<typename Iterator>
auto SceneGraphUpwardsIterator<Iterator>::operator->() const->pointer
{
return GetPointer(typename AZStd::is_pointer<Iterator>::type());
}
template<typename Iterator>
SceneGraph::HierarchyStorageConstIterator SceneGraphUpwardsIterator<Iterator>::GetHierarchyIterator() const
{
return AZStd::next(m_graph->GetHierarchyStorage().begin(), m_index);
}
template<typename Iterator>
void SceneGraphUpwardsIterator<Iterator>::MoveToNext()
{
AZ_Assert(m_graph, "Invalid iterator or moved passed end of list.");
SceneGraph::NodeHeader header = m_graph->GetHierarchyStorage().begin()[m_index];
if (header.HasParent())
{
AZStd::advance(m_iterator, header.m_parentIndex - m_index);
m_index = header.m_parentIndex;
}
else
{
m_index = -1;
m_graph = nullptr;
}
}
template<typename Iterator>
SceneGraphUpwardsIterator<Iterator> MakeSceneGraphUpwardsIterator(
const SceneGraph& graph, SceneGraph::HierarchyStorageConstIterator graphIterator, Iterator iterator, bool rootIterator)
{
return SceneGraphUpwardsIterator<Iterator>(graph, graphIterator, iterator, rootIterator);
}
template<typename Iterator>
SceneGraphUpwardsIterator<Iterator> MakeSceneGraphUpwardsIterator(
const SceneGraph& graph, SceneGraph::NodeIndex node, Iterator iterator, bool rootIterator)
{
return SceneGraphUpwardsIterator<Iterator>(graph, graph.ConvertToHierarchyIterator(node), iterator, rootIterator);
}
template<typename Iterator>
View<SceneGraphUpwardsIterator<Iterator> > MakeSceneGraphUpwardsView(
const SceneGraph& graph, SceneGraph::HierarchyStorageConstIterator graphIterator, Iterator iterator, bool rootIterator)
{
return View<SceneGraphUpwardsIterator<Iterator> >(
SceneGraphUpwardsIterator<Iterator>(graph, graphIterator, iterator, rootIterator),
SceneGraphUpwardsIterator<Iterator>());
}
template<typename Iterator>
View<SceneGraphUpwardsIterator<Iterator> > MakeSceneGraphUpwardsView(
const SceneGraph& graph, SceneGraph::NodeIndex node, Iterator iterator, bool rootIterator)
{
return View<SceneGraphUpwardsIterator<Iterator> >(
SceneGraphUpwardsIterator<Iterator>(graph, graph.ConvertToHierarchyIterator(node), iterator, rootIterator),
SceneGraphUpwardsIterator<Iterator>());
}
} // Views
} // Containers
} // SceneAPI
} // AZ
@@ -0,0 +1,62 @@
#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 Containers
{
namespace Views
{
// View combines begin and end iterators together in a single object.
// This reduces the number of functions that are needed to pass
// iterators from functions and avoids problems with mismatched
// iterators. It also makes it easier to use in ranged-based
// for-loops.
// Note that const correctness is enforced by the type of
// iterator passed, so all versions of begin and end return
// the same value.
template<typename Iterator>
class View
{
public:
using iterator = Iterator;
using const_iterator = Iterator;
View(Iterator begin, Iterator end);
Iterator begin();
Iterator end();
Iterator begin() const;
Iterator end() const;
Iterator cbegin() const;
Iterator cend() const;
private:
Iterator m_begin;
Iterator m_end;
};
template<typename Iterator>
View<Iterator> MakeView(Iterator begin, Iterator end)
{
return View<Iterator>(begin, end);
}
} // Views
} // Containers
} // SceneAPI
} // AZ
#include <SceneAPI/SceneCore/Containers/Views/View.inl>
@@ -0,0 +1,68 @@
#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 Containers
{
namespace Views
{
template<typename Iterator>
View<Iterator>::View(Iterator begin, Iterator end)
: m_begin(begin)
, m_end(end)
{
}
template<typename Iterator>
Iterator View<Iterator>::begin()
{
return m_begin;
}
template<typename Iterator>
Iterator View<Iterator>::end()
{
return m_end;
}
template<typename Iterator>
Iterator View<Iterator>::begin() const
{
return m_begin;
}
template<typename Iterator>
Iterator View<Iterator>::end() const
{
return m_end;
}
template<typename Iterator>
Iterator View<Iterator>::cbegin() const
{
return m_begin;
}
template<typename Iterator>
Iterator View<Iterator>::cend() const
{
return m_end;
}
}; // Views
} // Containers
} // SceneAPI
} // AZ
@@ -0,0 +1,137 @@
/*
* 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 <AzFramework/StringFunc/StringFunc.h>
#include <SceneAPI/SceneCore/Containers/Scene.h>
#include <SceneAPI/SceneCore/Containers/SceneManifest.h>
#include <SceneAPI/SceneCore/DataTypes/Groups/IGroup.h>
#include <SceneAPI/SceneCore/DataTypes/DataTypeUtilities.h>
namespace AZ
{
namespace SceneAPI
{
namespace DataTypes
{
namespace Utilities
{
bool IsNameAvailable(const AZStd::string& name, const Containers::SceneManifest& manifest, const Uuid& type)
{
for (AZStd::shared_ptr<const IManifestObject> object : manifest.GetValueStorage())
{
if (object->RTTI_IsTypeOf(IGroup::TYPEINFO_Uuid()) && object->RTTI_IsTypeOf(type))
{
const IGroup* group = azrtti_cast<const IGroup*>(object.get());
if (AzFramework::StringFunc::Equal(group->GetName().c_str(), name.c_str()))
{
return false;
}
}
}
return true;
}
AZStd::string CreateUniqueName(const AZStd::string& baseName, const Containers::SceneManifest& manifest, const Uuid& type)
{
int highestIndex = -1;
for (AZStd::shared_ptr<const IManifestObject> object : manifest.GetValueStorage())
{
if (object->RTTI_IsTypeOf(IGroup::TYPEINFO_Uuid()) && object->RTTI_IsTypeOf(type))
{
const IGroup* group = azrtti_cast<const IGroup*>(object.get());
const AZStd::string& groupName = group->GetName();
if (groupName.length() < baseName.length())
{
continue;
}
if (AzFramework::StringFunc::Equal(groupName.c_str(), baseName.c_str(), false, baseName.length()))
{
if (groupName.length() == baseName.length())
{
highestIndex = AZStd::max(0, highestIndex);
}
else if (groupName[baseName.length()] == '-')
{
int index = 0;
if (AzFramework::StringFunc::LooksLikeInt(groupName.c_str() + baseName.length() + 1, &index))
{
highestIndex = AZStd::max(index, highestIndex);
}
}
}
}
}
AZStd::string result;
if (highestIndex == -1)
{
result = baseName;
}
else
{
result = AZStd::string::format("%s-%i", baseName.c_str(), highestIndex + 1);
}
// Replace any characters that are invalid as part of a file name.
const char* invalidCharactersBegin = AZ_FILESYSTEM_INVALID_CHARACTERS;
const char* invalidCharactersEnd = invalidCharactersBegin + AZ_ARRAY_SIZE(AZ_FILESYSTEM_INVALID_CHARACTERS);
for (size_t i = 0; i < result.length(); ++i)
{
if (result[i] == AZ_FILESYSTEM_DRIVE_SEPARATOR || result[i] == AZ_FILESYSTEM_WILDCARD ||
result[i] == AZ_CORRECT_FILESYSTEM_SEPARATOR || result[i] == AZ_WRONG_FILESYSTEM_SEPARATOR ||
AZStd::find(invalidCharactersBegin, invalidCharactersEnd, result[i]) != invalidCharactersEnd)
{
result[i] = '_';
}
}
return result;
}
AZStd::string CreateUniqueName(const AZStd::string& baseName, const AZStd::string& subName,
const Containers::SceneManifest& manifest, const Uuid& type)
{
return CreateUniqueName(AZStd::string::format("%s_%s", baseName.c_str(), subName.c_str()), manifest, type);
}
Uuid CreateStableUuid(const Containers::Scene& scene, const Uuid& typeId)
{
char guid[sizeof(Uuid) * 2];
memcpy(guid, scene.GetSourceGuid().data, sizeof(Uuid));
memcpy(guid + sizeof(Uuid), typeId.data, sizeof(Uuid));
return Uuid::CreateData(guid, sizeof(Uuid) * 2);
}
Uuid CreateStableUuid(const Containers::Scene& scene, const Uuid& typeId, const AZStd::string& subId)
{
AZStd::string guid;
guid += scene.GetSourceGuid().ToString<AZStd::string>();
guid += typeId.ToString<AZStd::string>();
guid += subId;
return Uuid::CreateData(guid.data(), guid.size() * sizeof(guid[0]));
}
Uuid CreateStableUuid(const Containers::Scene& scene, const Uuid& typeId, const char* subId)
{
AZStd::string guid;
guid += scene.GetSourceGuid().ToString<AZStd::string>();
guid += typeId.ToString<AZStd::string>();
guid += subId;
return Uuid::CreateData(guid.data(), guid.size() * sizeof(guid[0]));
}
} // namespace Utilities
} // namespace DataTypes
} // namespace SceneAPI
} // namespace AZ
@@ -0,0 +1,73 @@
#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 <AzCore/std/smart_ptr/shared_ptr.h>
#include <SceneAPI/SceneCore/SceneCoreConfiguration.h>
namespace AZ
{
namespace SceneAPI
{
namespace Containers
{
class Scene;
class SceneManifest;
}
namespace DataTypes
{
namespace Utilities
{
//! Checks if the given name is already in use by another manifest entry of a (derived) type.
template<typename T>
bool IsNameAvailable(const AZStd::string& name, const Containers::SceneManifest& manifest);
//! Checks if the given name is already in use by another manifest entry of a (derived) type.
SCENE_CORE_API bool IsNameAvailable(const AZStd::string& name, const Containers::SceneManifest& manifest, const Uuid& type);
//! Creates a unique name for given (derived) type starting with the given base name.
template<typename T>
inline AZStd::string CreateUniqueName(const AZStd::string& baseName, const Containers::SceneManifest& manifest);
//! Creates a unique name for given (derived) type starting with the given base name and specialized on the sub name.
template<typename T>
inline AZStd::string CreateUniqueName(const AZStd::string& baseName, const AZStd::string& subName, const Containers::SceneManifest& manifest);
//! Creates a unique name for given (derived) type starting with the given base name.
SCENE_CORE_API AZStd::string CreateUniqueName(const AZStd::string& baseName, const Containers::SceneManifest& manifest, const Uuid& type);
//! Creates a unique name for given (derived) type starting with the given base name and specialized on the sub name.
SCENE_CORE_API AZStd::string CreateUniqueName(const AZStd::string& baseName, const AZStd::string& subName,
const Containers::SceneManifest& manifest, const Uuid& type);
//! Creates a uuid that remains stable between runs. Use this to make sure that objects that are default generated get the same uuid
//! when generated again between runs. Use this version if this is the only or primary object. Do not use this function to create
//! a uuid for objects the user manually adds, which should use a random uuid.
SCENE_CORE_API Uuid CreateStableUuid(const Containers::Scene& scene, const Uuid& typeId);
//! Creates a uuid that remains stable between runs. Use this to make sure that objects that are default generated get the same uuid
//! when generated again between runs. Use this version if there are multiple objects of the same type automatically generated that
//! are not the primary object. For instance if there are multiple mesh groups, where some groups only have a single mesh and the remaining
//! meshes go in the default mesh group, the default mesh group would use the previous CreateStableUuid, and the additional mesh groups
//! can use this with the selected mesh as the sub id. Other alternatives might be all the selected nodes concatenated into a single string.
SCENE_CORE_API Uuid CreateStableUuid(const Containers::Scene& scene, const Uuid& typeId, const AZStd::string& subId);
//! Creates a uuid that remains stable between runs. Use this to make sure that objects that are default generated get the same uuid
//! when generated again between runs. Use this version if there are multiple objects of the same type automatically generated that
//! are not the primary object. For instance if there are multiple mesh groups, where some groups only have a single mesh and the remaining
//! meshes go in the default mesh group, the default mesh group would use the previous CreateStableUuid, and the additional mesh groups
//! can use this with the selected mesh as the sub id. Other alternatives might be all the selected nodes concatenated into a single string.
SCENE_CORE_API Uuid CreateStableUuid(const Containers::Scene& scene, const Uuid& typeId, const char* subId);
} // Utilities
} // DataTypes
} // SceneAPI
} // AZ
#include <SceneAPI/SceneCore/DataTypes/DataTypeUtilities.inl>
@@ -0,0 +1,50 @@
/*
* 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 <stdlib.h>
#include <AzFramework/StringFunc/StringFunc.h>
#include <SceneAPI/SceneCore/Containers/SceneManifest.h>
#include <SceneAPI/SceneCore/Containers/Views/FilterIterator.h>
#include <SceneAPI/SceneCore/Containers/Utilities/Filters.h>
namespace AZ
{
namespace SceneAPI
{
namespace DataTypes
{
namespace Utilities
{
template<typename T>
bool IsNameAvailable(const AZStd::string& name, const Containers::SceneManifest& manifest)
{
return IsNameAvailable(name, manifest, T::TYPEINFO_Uuid());
}
template<typename T>
AZStd::string CreateUniqueName(const AZStd::string& baseName, const Containers::SceneManifest& manifest)
{
return CreateUniqueName(baseName, manifest, T::TYPEINFO_Uuid());
}
template<typename T>
AZStd::string CreateUniqueName(const AZStd::string& baseName, const AZStd::string& subName, const Containers::SceneManifest& manifest)
{
return CreateUniqueName(baseName, subName, manifest, T::TYPEINFO_Uuid());
}
} // Utilities
} // DataTypes
} // SceneAPI
} // AZ
@@ -0,0 +1,53 @@
#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/Math/Vector3.h>
#include <SceneAPI/SceneCore/DataTypes/IGraphObject.h>
#include <SceneAPI/SceneCore/DataTypes/MatrixType.h>
namespace AZ
{
namespace SceneAPI
{
namespace DataTypes
{
class IAnimationData
: public IGraphObject
{
public:
AZ_RTTI(IAnimationData, "{62B0571C-6EFF-42FA-902A-85AC744E04F2}", IGraphObject);
virtual ~IAnimationData() override = default;
virtual size_t GetKeyFrameCount() const = 0;
virtual const MatrixType& GetKeyFrame(size_t index) const = 0;
virtual double GetTimeStepBetweenFrames() const = 0;
};
class IBlendShapeAnimationData
: public IGraphObject
{
public:
AZ_RTTI(IBlendShapeAnimationData, "{CD2004EB-8B88-42B2-A539-079A557C98C9}", IGraphObject);
virtual ~IBlendShapeAnimationData() override = default;
virtual const char* GetBlendShapeName() const = 0;
virtual size_t GetKeyFrameCount() const = 0;
virtual double GetKeyFrame(size_t index) const = 0;
virtual double GetTimeStepBetweenFrames() const = 0;
};
}
}
}
@@ -0,0 +1,83 @@
#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/Math/Vector3.h>
#include <AzCore/RTTI/RTTI.h>
#include <SceneAPI/SceneCore/DataTypes/IGraphObject.h>
namespace AZ
{
namespace SceneAPI
{
namespace DataTypes
{
class IBlendShapeData
: public IGraphObject
{
public:
AZ_RTTI(IBlendShapeData, "{55E7384D-9333-4C51-BC91-E90CAC2C30E2}", IGraphObject);
struct Face
{
unsigned int vertexIndex[3];
inline bool operator==(const Face& rhs) const
{
return (vertexIndex[0] == rhs.vertexIndex[0] && vertexIndex[1] == rhs.vertexIndex[1] &&
vertexIndex[2] == rhs.vertexIndex[2]);
}
inline bool operator!=(const Face& rhs) const
{
return (vertexIndex[0] != rhs.vertexIndex[0] || vertexIndex[1] != rhs.vertexIndex[1] ||
vertexIndex[2] != rhs.vertexIndex[2] );
}
};
virtual ~IBlendShapeData() override = default;
virtual size_t GetUsedControlPointCount() const = 0;
virtual int GetControlPointIndex(int vertexIndex) const = 0;
virtual int GetUsedPointIndexForControlPoint(int controlPointIndex) const = 0;
virtual unsigned int GetVertexCount() const = 0;
virtual unsigned int GetFaceCount() const = 0;
virtual const AZ::Vector3& GetPosition(unsigned int index) const = 0;
virtual const AZ::Vector3& GetNormal(unsigned int index) const = 0;
virtual unsigned int GetFaceVertexIndex(unsigned int face, unsigned int vertexIndex) const = 0;
};
} //namespace DataTypes
} //namespace SceneAPI
} //namespace AZ
namespace AZStd
{
template<>
struct hash<AZ::SceneAPI::DataTypes::IBlendShapeData::Face>
{
using result_type = AZStd::size_t;
result_type operator()(const AZ::SceneAPI::DataTypes::IBlendShapeData::Face& value) const
{
result_type hash = 0;
hash_combine(hash, value.vertexIndex[0]);
hash_combine(hash, value.vertexIndex[1]);
hash_combine(hash, value.vertexIndex[2]);
return hash;
}
};
}
@@ -0,0 +1,43 @@
#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 <SceneAPI/SceneCore/DataTypes/IGraphObject.h>
#include <SceneAPI/SceneCore/DataTypes/MatrixType.h>
namespace AZ
{
namespace SceneAPI
{
namespace DataTypes
{
class IBoneData
: public IGraphObject
{
public:
AZ_RTTI(IBoneData, "{9DC2BC55-BF0A-4849-9367-2138340768DE}", IGraphObject);
virtual ~IBoneData() override = default;
virtual const MatrixType& GetWorldTransform() const = 0;
void GetDebugOutput(AZ::SceneAPI::Utilities::DebugOutput& output) const override
{
output.Write("WorldTransform", GetWorldTransform());
}
};
} // DataTypes
} // SceneAPI
} // AZ
@@ -0,0 +1,73 @@
#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.
*
*/
#ifndef AZINCLUDE_TOOLS_SCENECORE_DATATYPES_IMATERIALDATA_H_
#define AZINCLUDE_TOOLS_SCENECORE_DATATYPES_IMATERIALDATA_H_
#include <AzCore/std/string/string.h>
#include <AzCore/RTTI/RTTI.h>
#include <AzCore/Math/Vector3.h>
#include <SceneAPI/SceneCore/DataTypes/IGraphObject.h>
namespace AZ
{
namespace SceneAPI
{
namespace DataTypes
{
class IMaterialData
: public IGraphObject
{
public:
AZ_RTTI(IMaterialData, "{4C0E818F-CEE8-48A0-AC3D-AC926811BFE4}", IGraphObject);
enum class TextureMapType
{
Diffuse,
Specular,
Bump,
Normal
};
~IMaterialData() override = default;
void GetDebugOutput(AZ::SceneAPI::Utilities::DebugOutput& output) const override
{
output.Write("MaterialName", GetMaterialName());
output.Write("UniqueId", GetUniqueId());
output.Write("IsNoDraw", IsNoDraw());
output.Write("DiffuseColor", GetDiffuseColor());
output.Write("SpecularColor", GetSpecularColor());
output.Write("EmissiveColor", GetEmissiveColor());
output.Write("Opacity", GetOpacity());
output.Write("Shininess", GetShininess());
}
virtual const AZStd::string& GetMaterialName() const = 0;
virtual const AZStd::string& GetTexture(TextureMapType mapType) const = 0;
virtual bool IsNoDraw() const = 0;
virtual const AZ::Vector3& GetDiffuseColor() const = 0;
virtual const AZ::Vector3& GetSpecularColor() const = 0;
virtual const AZ::Vector3& GetEmissiveColor() const = 0;
virtual float GetOpacity() const = 0;
virtual float GetShininess() const = 0;
virtual uint64_t GetUniqueId() const = 0;
};
} //namespace DataTypes
} //namespace SceneAPI
} //namespace AZ
#endif // AZINCLUDE_TOOLS_SCENECORE_DATATYPES_IMATERIALDATA_H_
@@ -0,0 +1,115 @@
#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.
*
*/
#ifndef AZINCLUDE_TOOLS_SCENECORE_DATATYPES_IMESHDATA_H_
#define AZINCLUDE_TOOLS_SCENECORE_DATATYPES_IMESHDATA_H_
#include <AzCore/RTTI/RTTI.h>
#include <AzCore/Math/Vector3.h>
#include <AzCore/Math/Vector2.h>
#include <SceneAPI/SceneCore/DataTypes/IGraphObject.h>
namespace AZ
{
namespace SceneAPI
{
namespace DataTypes
{
class IMeshData
: public IGraphObject
{
public:
AZ_RTTI(IMeshData, "{B94A59C0-F3A5-40A0-B541-7E36B6576C4A}", IGraphObject);
struct Face
{
unsigned int vertexIndex[3];
inline bool operator==(const Face& rhs) const
{
return (vertexIndex[0] == rhs.vertexIndex[0] && vertexIndex[1] == rhs.vertexIndex[1] &&
vertexIndex[2] == rhs.vertexIndex[2]);
}
inline bool operator!=(const Face& rhs) const
{
return (vertexIndex[0] != rhs.vertexIndex[0] || vertexIndex[1] != rhs.vertexIndex[1] ||
vertexIndex[2] != rhs.vertexIndex[2]);
}
};
virtual ~IMeshData() override = default;
virtual unsigned int GetVertexCount() const = 0;
virtual bool HasNormalData() const = 0;
//1 to 1 mapping from position to normal (each corner of triangle represented)
virtual const AZ::Vector3& GetPosition(unsigned int index) const = 0;
virtual const AZ::Vector3& GetNormal(unsigned int index) const = 0;
virtual unsigned int GetFaceCount() const = 0;
virtual const Face& GetFaceInfo(unsigned int index) const = 0;
virtual unsigned int GetFaceMaterialId(unsigned int index) const = 0;
// 0 <= vertexIndex < GetVertexCount().
virtual int GetControlPointIndex(int vertexIndex) const = 0;
// Returns number of unique control points used in the mesh. Here, "used"
// means it is actually referenced by some polygon in the mesh.
virtual size_t GetUsedControlPointCount() const = 0;
// If the control point index specified is indeed used by the mesh, returns a unique value
// in the range [0, GetUsedControlPointCount()). Otherwise, returns -1.
virtual int GetUsedPointIndexForControlPoint(int controlPointIndex) const = 0;
virtual unsigned int GetVertexIndex(int faceIndex, int vertexIndexInFace) const = 0;
static const int s_invalidMaterialId = 0;
// Set the unit size of the mesh, from the point of FBX SDK
void SetUnitSizeInMeters(float size) { m_unitSizeInMeters = size; }
float GetUnitSizeInMeters() const { return m_unitSizeInMeters; }
// Set the original unit size of the mesh, from the point of FBX SDK
void SetOriginalUnitSizeInMeters(float size) { m_originalUnitSizeInMeters = size; }
float GetOriginalUnitSizeInMeters() const { return m_originalUnitSizeInMeters; }
private:
float m_unitSizeInMeters = 1.f;
float m_originalUnitSizeInMeters = 1.f;
};
} //namespace DataTypes
} //namespace SceneAPI
} //namespace AZ
namespace AZStd
{
template<>
struct hash<AZ::SceneAPI::DataTypes::IMeshData::Face>
{
using result_type = AZStd::size_t;
result_type operator()(const AZ::SceneAPI::DataTypes::IMeshData::Face& value) const
{
result_type hash = 0;
hash_combine(hash, value.vertexIndex[0]);
hash_combine(hash, value.vertexIndex[1]);
hash_combine(hash, value.vertexIndex[2]);
return hash;
}
};
}
#endif // AZINCLUDE_TOOLS_SCENECORE_DATATYPES_IMESHDATA_H_
@@ -0,0 +1,50 @@
/*
* 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/RTTI/RTTI.h>
#include <SceneAPI/SceneCore/DataTypes/IGraphObject.h>
#include <SceneAPI/SceneCore/DataTypes/GraphData/IMeshVertexTangentData.h>
namespace AZ
{
class Vector3;
}
namespace AZ
{
namespace SceneAPI
{
namespace DataTypes
{
class IMeshVertexBitangentData
: public IGraphObject
{
public:
AZ_RTTI(IMeshVertexBitangentData, "{6C8F6109-B0BD-49D1-A998-4A4946557DF9}", IGraphObject);
virtual ~IMeshVertexBitangentData() override = default;
virtual size_t GetCount() const = 0;
virtual const AZ::Vector3& GetBitangent(size_t index) const = 0;
virtual void SetBitangent(size_t vertexIndex, const AZ::Vector3& bitangent) = 0;
virtual void SetBitangentSetIndex(size_t setIndex) = 0;
virtual size_t GetBitangentSetIndex() const = 0;
virtual TangentSpace GetTangentSpace() const = 0;
virtual void SetTangentSpace(TangentSpace space) = 0;
};
} // DataTypes
} // SceneAPI
} // AZ
@@ -0,0 +1,94 @@
#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 <SceneAPI/SceneCore/DataTypes/IGraphObject.h>
#include <AzCore/Name/Name.h>
namespace AZ
{
namespace SceneAPI
{
namespace DataTypes
{
enum class ColorChannel : AZ::u8
{
Red = 0,
Green,
Blue,
Alpha
};
struct Color
{
union
{
struct
{
float red;
float green;
float blue;
float alpha;
};
float m_channels[4];
};
Color(float r, float g, float b, float a)
: red(r), green(g), blue(b), alpha(a)
{
}
float GetChannel(ColorChannel channel) const
{
return m_channels[static_cast<AZ::u8>(channel)];
}
};
class IMeshVertexColorData
: public IGraphObject
{
public:
AZ_RTTI(IMeshVertexColorData, "{27659F76-1245-4549-87A6-AF4E8B94CD51}", IGraphObject);
virtual ~IMeshVertexColorData() override = default;
virtual const AZ::Name& GetCustomName() const = 0;
virtual size_t GetCount() const = 0;
virtual const Color& GetColor(size_t index) const = 0;
};
} // DataTypes
} // SceneAPI
} // AZ
namespace AZStd
{
template<>
struct hash<AZ::SceneAPI::DataTypes::Color>
{
using result_type = AZStd::size_t;
result_type operator()(const AZ::SceneAPI::DataTypes::Color& value) const
{
result_type hash = 0;
hash_combine(hash, value.red);
hash_combine(hash, value.green);
hash_combine(hash, value.blue);
hash_combine(hash, value.alpha);
return hash;
}
};
}
@@ -0,0 +1,60 @@
/*
* 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/RTTI/RTTI.h>
#include <SceneAPI/SceneCore/DataTypes/IGraphObject.h>
namespace AZ
{
class Vector4;
}
namespace AZ
{
namespace SceneAPI
{
namespace DataTypes
{
enum class TangentSpace
{
FromFbx = 0,
MikkT = 1,
EMotionFX = 2
};
enum class BitangentMethod
{
UseFromTangentSpace = 0,
Orthogonal = 1
};
class IMeshVertexTangentData
: public IGraphObject
{
public:
AZ_RTTI(IMeshVertexTangentData, "{B24084FF-09B1-4EE5-BA5B-2D392E92ECC1}", IGraphObject);
virtual ~IMeshVertexTangentData() override = default;
virtual size_t GetCount() const = 0;
virtual const AZ::Vector4& GetTangent(size_t index) const = 0;
virtual void SetTangent(size_t vertexIndex, const AZ::Vector4& tangent) = 0;
virtual void SetTangentSetIndex(size_t setIndex) = 0;
virtual size_t GetTangentSetIndex() const = 0;
virtual TangentSpace GetTangentSpace() const = 0;
virtual void SetTangentSpace(TangentSpace space) = 0;
};
} // DataTypes
} // SceneAPI
} // AZ
@@ -0,0 +1,46 @@
#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 <SceneAPI/SceneCore/DataTypes/IGraphObject.h>
#include <AzCore/Name/Name.h>
namespace AZ
{
class Vector2;
class Name;
}
namespace AZ
{
namespace SceneAPI
{
namespace DataTypes
{
class IMeshVertexUVData
: public IGraphObject
{
public:
AZ_RTTI(IMeshVertexUVData, "{C45B2027-5D0A-400A-9689-88C9A27EFE57}", IGraphObject);
virtual ~IMeshVertexUVData() override = default;
virtual const AZ::Name& GetCustomName() const = 0;
virtual size_t GetCount() const = 0;
virtual const AZ::Vector2& GetUV(size_t index) const = 0;
};
} // DataTypes
} // SceneAPI
} // AZ
@@ -0,0 +1,66 @@
#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 <SceneAPI/SceneCore/DataTypes/IGraphObject.h>
#include <AzCore/std/containers/vector.h>
namespace AZ
{
namespace SceneAPI
{
namespace DataTypes
{
class ISkinWeightData
: public IGraphObject
{
public:
AZ_RTTI(ISkinWeightData, "{F7A6CC37-5904-4D25-B1A9-B25C192A4C64}", IGraphObject);
struct Link
{
int boneId;
float weight;
};
virtual ~ISkinWeightData() override = default;
virtual size_t GetVertexCount() const = 0;
virtual size_t GetLinkCount(size_t vertexIndex) const = 0;
virtual const Link& GetLink(size_t vertexIndex, size_t linkIndex) const = 0;
virtual size_t GetBoneCount() const = 0;
virtual const AZStd::string& GetBoneName(int boneId) const = 0;
};
} // DataTypes
} // SceneAPI
} // AZ
namespace AZStd
{
template<>
struct hash<AZ::SceneAPI::DataTypes::ISkinWeightData::Link>
{
using result_type = AZStd::size_t;
result_type operator()(const AZ::SceneAPI::DataTypes::ISkinWeightData::Link& value) const
{
result_type hash = 0;
hash_combine(hash, value.boneId);
hash_combine(hash, value.weight);
return hash;
}
};
}
@@ -0,0 +1,42 @@
#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 <SceneAPI/SceneCore/DataTypes/IGraphObject.h>
#include <SceneAPI/SceneCore/DataTypes/MatrixType.h>
namespace AZ
{
namespace SceneAPI
{
namespace DataTypes
{
class ITransform
: public IGraphObject
{
public:
AZ_RTTI(ITransform, "{C1A24A14-EDD4-422F-AB62-9566D744AF1B}", IGraphObject);
virtual ~ITransform() override = default;
virtual MatrixType& GetMatrix() = 0;
virtual const MatrixType& GetMatrix() const = 0;
void GetDebugOutput(AZ::SceneAPI::Utilities::DebugOutput& output) const override
{
output.Write("Matrix", GetMatrix());
}
};
} // DataTypes
} // SceneAPI
} // AZ
@@ -0,0 +1,60 @@
#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 <SceneAPI/SceneCore/DataTypes/Groups/IGroup.h>
namespace AZ
{
class ReflectContext;
namespace SceneAPI
{
namespace DataTypes
{
class IAnimationGroup
: public IGroup
{
public:
AZ_RTTI(IAnimationGroup, "{B07FB380-6A1F-40BE-B3CE-41258985DF36}", IGroup);
struct PerBoneCompression
{
public:
AZ_TYPE_INFO(PerBoneCompression, "{23DC875D-42E8-40AF-AB0E-30BDBB6427D8}");
AZStd::string m_boneNamePattern = "*";
float m_compressionStrength = 0.1f;
static void Reflect(ReflectContext* context);
};
typedef AZStd::vector<PerBoneCompression> PerBoneCompressionList;
~IAnimationGroup() override = default;
virtual const AZStd::string& GetSelectedRootBone() const = 0;
virtual uint32_t GetStartFrame() const = 0;
virtual uint32_t GetEndFrame() const = 0;
virtual void SetSelectedRootBone(const AZStd::string& selectedRootBone) = 0;
virtual void SetStartFrame(uint32_t frame) = 0;
virtual void SetEndFrame(uint32_t frame) = 0;
virtual const float GetDefaultCompressionStrength() const = 0;
virtual const PerBoneCompressionList& GetPerBoneCompression() const = 0;
};
}
}
}
@@ -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 <AzCore/std/string/string.h>
#include <AzCore/std/smart_ptr/shared_ptr.h>
#include <AzCore/RTTI/RTTI.h>
#include <SceneAPI/SceneCore/Containers/RuleContainer.h>
#include <SceneAPI/SceneCore/DataTypes/IManifestObject.h>
namespace AZ
{
namespace SceneAPI
{
namespace DataTypes
{
class IRule;
class IGroup
: public IManifestObject
{
public:
AZ_RTTI(IGroup, "{DE008E67-790D-4672-A73A-5CA0F31EDD2D}", IManifestObject);
~IGroup() override = default;
virtual const AZStd::string& GetName() const = 0;
virtual const Uuid& GetId() const = 0;
virtual Containers::RuleContainer& GetRuleContainer() = 0;
virtual const Containers::RuleContainer& GetRuleContainerConst() const = 0;
};
} // DataTypes
} // SceneAPI
} // AZ
@@ -0,0 +1,41 @@
#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 <SceneAPI/SceneCore/DataTypes/Groups/ISceneNodeGroup.h>
#include <SceneAPI/SceneCore/DataTypes/ManifestBase/ISceneNodeSelectionList.h>
namespace AZ
{
namespace SceneAPI
{
namespace Containers
{
class DataObject;
}
namespace DataTypes
{
class IMeshGroup
: public ISceneNodeGroup
{
public:
AZ_RTTI(IMeshGroup, "{74D45E45-81EE-4AD4-83B5-F37EB98D847C}", ISceneNodeGroup);
~IMeshGroup() override = default;
virtual void SetName(AZStd::string&& name) = 0;
virtual void OverrideId(const Uuid& id) = 0;
};
} // DataTypes
} // SceneAPI
} // AZ
@@ -0,0 +1,44 @@
#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 <memory>
#include <AzCore/std/string/string.h>
#include <AzCore/RTTI/RTTI.h>
#include <SceneAPI/SceneCore/DataTypes/Groups/IGroup.h>
#include <SceneAPI/SceneCore/DataTypes/ManifestBase/ISceneNodeSelectionList.h>
namespace AZ
{
namespace SceneAPI
{
namespace Containers
{
class DataObject;
}
namespace DataTypes
{
class ISceneNodeGroup
: public IGroup
{
public:
AZ_RTTI(ISceneNodeGroup, "{1D20FA11-B184-429E-8C86-745852234845}", IGroup);
~ISceneNodeGroup() override = default;
virtual DataTypes::ISceneNodeSelectionList& GetSceneNodeSelectionList() = 0;
virtual const DataTypes::ISceneNodeSelectionList& GetSceneNodeSelectionList() const = 0;
};
} // DataTypes
} // SceneAPI
} // AZ
@@ -0,0 +1,37 @@
#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 <SceneAPI/SceneCore/DataTypes/Groups/IGroup.h>
#include <AzCore/std/string/string.h>
namespace AZ
{
namespace SceneAPI
{
namespace DataTypes
{
class ISkeletonGroup
: public IGroup
{
public:
AZ_RTTI(ISkeletonGroup, "{419ECE00-3CC5-4CAB-A451-453BF3FEA665}", IGroup);
~ISkeletonGroup() override = default;
virtual const AZStd::string& GetSelectedRootBone() const = 0;
virtual void SetSelectedRootBone(const AZStd::string& selectedRootBone) = 0;
};
}
}
}
@@ -0,0 +1,39 @@
#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 <SceneAPI/SceneCore/DataTypes/Groups/ISceneNodeGroup.h>
#include <SceneAPI/SceneCore/DataTypes/ManifestBase/ISceneNodeSelectionList.h>
namespace AZ
{
namespace SceneAPI
{
namespace Containers
{
class DataObject;
}
namespace DataTypes
{
class ISkinGroup
: public ISceneNodeGroup
{
public:
AZ_RTTI(ISkinGroup, "{D3FD3067-0291-4274-8C58-050B47095747}", ISceneNodeGroup);
~ISkinGroup() override = default;
};
} // DataTypes
} // SceneAPI
} // AZ
@@ -0,0 +1,40 @@
#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 <SceneAPI/SceneCore/Utilities/DebugOutput.h>
namespace AZ
{
namespace SceneAPI
{
namespace DataTypes
{
class IGraphObject
{
public:
AZ_RTTI(IGraphObject, "{9A72266A-B308-4A74-9500-EF5C7B60AD8A}");
virtual ~IGraphObject() = 0;
// When requested, the scene graph can be dumped to a file to help with debugging.
virtual void GetDebugOutput([[maybe_unused]] AZ::SceneAPI::Utilities::DebugOutput& output) const {}
};
inline IGraphObject::~IGraphObject()
{
}
} //namespace DataTypes
} //namespace SceneAPI
} //namespace AZ
@@ -0,0 +1,50 @@
#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/Serialization/SerializeContext.h>
namespace AZ
{
namespace SceneAPI
{
namespace DataTypes
{
class IManifestObject
{
public:
AZ_RTTI(IManifestObject, "{3B839407-1884-4FF4-ABEA-CA9D347E83F7}");
static void Reflect(AZ::ReflectContext* context);
virtual ~IManifestObject() = 0;
virtual void OnUserAdded() {};
virtual void OnUserRemoved() const {};
};
inline void IManifestObject::Reflect(AZ::ReflectContext* context)
{
if(AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<IManifestObject>()
->Version(0);
}
}
inline IManifestObject::~IManifestObject()
{
}
} //namespace DataTypes
} //namespace SceneAPI
} //namespace AZ
@@ -0,0 +1,55 @@
#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 <memory>
#include <AzCore/std/smart_ptr/unique_ptr.h>
#include <AzCore/std/string/string.h>
#include <AzCore/RTTI/RTTI.h>
#include <SceneAPI/SceneCore/DataTypes/IManifestObject.h>
namespace AZ
{
namespace SceneAPI
{
namespace Containers
{
class DataObject;
}
namespace DataTypes
{
class ISceneNodeSelectionList
{
public:
AZ_RTTI(ISceneNodeSelectionList, "{DC3F9996-E550-4780-A03B-80B0DDA1DA45}");
virtual ~ ISceneNodeSelectionList() = default;
virtual size_t GetSelectedNodeCount() const = 0;
virtual const AZStd::string& GetSelectedNode(size_t index) const = 0;
virtual size_t AddSelectedNode(const AZStd::string& name) = 0;
virtual size_t AddSelectedNode(AZStd::string&& name) = 0;
virtual void RemoveSelectedNode(size_t index) = 0;
virtual void RemoveSelectedNode(const AZStd::string& name) = 0;
virtual void ClearSelectedNodes() = 0;
virtual size_t GetUnselectedNodeCount() const = 0;
virtual const AZStd::string& GetUnselectedNode(size_t index) const = 0;
virtual void ClearUnselectedNodes() = 0;
virtual AZStd::unique_ptr<ISceneNodeSelectionList> Copy() const = 0;
virtual void CopyTo(ISceneNodeSelectionList& other) const = 0;
};
} // DataTypes
} // SceneAPI
} // AZ
@@ -0,0 +1,26 @@
/*
* 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/Matrix3x4.h>
namespace AZ
{
namespace SceneAPI
{
namespace DataTypes
{
using MatrixType = AZ::Matrix3x4;
} //namespace DataTypes
} //namespace SceneAPI
} //namespace AZ
@@ -0,0 +1,37 @@
#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 <SceneAPI/SceneCore/DataTypes/Rules/IRule.h>
#include <SceneAPI/SceneCore/DataTypes/ManifestBase/ISceneNodeSelectionList.h>
namespace AZ
{
namespace SceneAPI
{
namespace DataTypes
{
class IBlendShapeRule
: public IRule
{
public:
AZ_RTTI(IBlendShapeRule, "{C801EEE7-934B-4F5E-A20B-C394BEC992E2}", IRule);
~IBlendShapeRule() override = default;
virtual ISceneNodeSelectionList& GetSceneNodeSelectionList() = 0;
virtual const ISceneNodeSelectionList& GetSceneNodeSelectionList() const = 0;
};
} // DataTypes
} // SceneAPI
} // AZ
@@ -0,0 +1,84 @@
/*
* 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/Color.h>
#include <SceneAPI/SceneCore/DataTypes/Rules/IRule.h>
#include <SceneAPI/SceneCore/Containers/SceneGraph.h>
#include <SceneAPI/SceneCore/Containers/RuleContainer.h>
#include <SceneAPI/SceneCore/Utilities/Reporting.h>
namespace AZ
{
namespace SceneAPI
{
namespace DataTypes
{
/// This class is the interface for the cloth rule (aka cloth modifier).
/// It exposes functions to extract cloth data.
class IClothRule
: public IRule
{
public:
AZ_RTTI(IClothRule, "{5185510A-50BF-418A-ACB4-1A9E014C7E43}", IRule);
~IClothRule() override = default;
/// Returns the name of the mesh node inside the FBX that will be exported as cloth.
virtual const AZStd::string& GetMeshNodeName() const = 0;
/// Returns cloth data from the mesh node selected in the cloth rule.
virtual AZStd::vector<AZ::Color> ExtractClothData(const Containers::SceneGraph& graph, const size_t numVertices) const = 0;
/// Finds the cloth rule affecting a mesh node and extracts cloth data.
static AZStd::vector<AZ::Color> FindClothData(
const AZ::SceneAPI::Containers::SceneGraph& graph,
const AZ::SceneAPI::Containers::SceneGraph::NodeIndex& meshNodeIndex,
const size_t numVertices,
const AZ::SceneAPI::Containers::RuleContainer& rules)
{
AZStd::vector<AZ::Color> clothData;
const char* meshNodeName = graph.GetNodeName(meshNodeIndex).GetPath();
for (size_t ruleIndex = 0; ruleIndex < rules.GetRuleCount(); ++ruleIndex)
{
const IClothRule* clothRule = azrtti_cast<const IClothRule*>(rules.GetRule(ruleIndex).get());
if (!clothRule)
{
continue;
}
// Reached a cloth rule for this mesh node?
if (meshNodeName != clothRule->GetMeshNodeName())
{
continue;
}
// If there is already cloth data it means there is more than 1 cloth rule affecting the same mesh.
if (!clothData.empty())
{
AZ_TracePrintf(AZ::SceneAPI::Utilities::WarningWindow, "Different cloth rules chose the same mesh node, only using the first cloth rule.");
continue;
}
clothData = clothRule->ExtractClothData(graph, numVertices);
}
return clothData;
}
};
} //namespace DataTypes
} //namespace SceneAPI
} // namespace AZ
@@ -0,0 +1,37 @@
#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 <AzCore/RTTI/RTTI.h>
#include <SceneAPI/SceneCore/DataTypes/Rules/IRule.h>
namespace AZ
{
namespace SceneAPI
{
namespace DataTypes
{
class ICommentRule
: public IRule
{
public:
AZ_RTTI(ICommentRule, "{7CF18D33-C7AB-47F0-8084-A90351154293}", IRule);
virtual ~ICommentRule() override = default;
virtual const AZStd::string& GetComment() const = 0;
};
} // DataTypes
} // SceneAPI
} // AZ
@@ -0,0 +1,39 @@
#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 <SceneAPI/SceneCore/DataTypes/Rules/IRule.h>
#include <SceneAPI/SceneCore/DataTypes/ManifestBase/ISceneNodeSelectionList.h>
namespace AZ
{
namespace SceneAPI
{
namespace DataTypes
{
class ILodRule
: public IRule
{
public:
AZ_RTTI(ILodRule, "{D91C2CA1-B3F9-4819-8B58-AE2AEB98859A}", IRule);
virtual ~ILodRule() override = default;
virtual ISceneNodeSelectionList& GetSceneNodeSelectionList(size_t index) = 0;
virtual const ISceneNodeSelectionList& GetSceneNodeSelectionList(size_t index) const = 0;
virtual size_t GetLodCount() const = 0;
};
} // DataTypes
} // SceneAPI
} // AZ
@@ -0,0 +1,38 @@
#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 <SceneAPI/SceneCore/DataTypes/Rules/IRule.h>
namespace AZ
{
namespace SceneAPI
{
namespace DataTypes
{
class IMaterialRule
: public IRule
{
public:
AZ_RTTI(IMaterialRule, "{428C9752-6EDF-4FA2-9BDF-DBDFCEB4CC0F}", IRule);
~IMaterialRule() override = default;
virtual bool RemoveUnusedMaterials() const = 0;
virtual bool UpdateMaterials() const = 0;
};
} // DataTypes
} // SceneAPI
} // AZ
@@ -0,0 +1,44 @@
#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 <AzCore/RTTI/RTTI.h>
#include <SceneAPI/SceneCore/DataTypes/Rules/IRule.h>
namespace AZ
{
namespace SceneAPI
{
namespace DataTypes
{
const static AZStd::string s_advancedDisabledString = "Disabled";
class IMeshAdvancedRule
: public IRule
{
public:
AZ_RTTI(IMeshAdvancedRule, "{ADF04C44-5786-466A-AE69-63E5E3474D21}", IRule);
virtual ~IMeshAdvancedRule() override = default;
virtual bool Use32bitVertices() const = 0;
virtual bool MergeMeshes() const = 0;
virtual bool UseCustomNormals() const = 0;
virtual const AZStd::string& GetVertexColorStreamName() const = 0;
// Returns whether or not the vertex color stream was explicitly disabled by the user.
// This does guarantee a valid vertex color stream name if false.
virtual bool IsVertexColorStreamDisabled() const = 0;
};
} // DataTypes
} // SceneAPI
} // AZ
@@ -0,0 +1,44 @@
#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 <AzCore/RTTI/RTTI.h>
#include <SceneAPI/SceneCore/DataTypes/Rules/IRule.h>
namespace AZ
{
class Quaternion;
class Vector3;
namespace SceneAPI
{
namespace DataTypes
{
class IOriginRule
: public IRule
{
public:
AZ_RTTI(IOriginRule, "{9FB042DF-1C7F-4815-BC83-BF8D94F907C5}", IRule);
virtual ~IOriginRule() override = default;
virtual const AZStd::string& GetOriginNodeName() const = 0;
virtual bool UseRootAsOrigin() const = 0;
virtual const AZ::Quaternion& GetRotation() const = 0;
virtual const AZ::Vector3& GetTranslation() const = 0;
virtual float GetScale() const = 0;
};
} // DataTypes
} // SceneAPI
} // AZ
@@ -0,0 +1,36 @@
#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 <memory>
#include <AzCore/std/string/string.h>
#include <AzCore/RTTI/RTTI.h>
#include <SceneAPI/SceneCore/DataTypes/IManifestObject.h>
namespace AZ
{
namespace SceneAPI
{
namespace DataTypes
{
class IRule
: public IManifestObject
{
public:
AZ_RTTI(IRule, "{81267F8B-3963-423B-9FF7-D276D82CD110}", IManifestObject);
virtual ~IRule() override = default;
};
} // DataTypes
} // SceneAPI
} // AZ
@@ -0,0 +1,36 @@
/*
* 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/std/string/string.h>
#include <AzCore/RTTI/RTTI.h>
#include <SceneAPI/SceneCore/DataTypes/Rules/IRule.h>
namespace AZ
{
namespace SceneAPI
{
namespace DataTypes
{
class IScriptProcessorRule
: public IRule
{
public:
AZ_RTTI(IScriptProcessorRule, "{7D595C6C-55BD-44AC-84F9-7E3C74713D7D}", IRule);
virtual ~IScriptProcessorRule() override = default;
virtual const AZStd::string& GetScriptFilename() const = 0;
};
} // DataTypes
} // SceneAPI
} // AZ
@@ -0,0 +1,38 @@
#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 <SceneAPI/SceneCore/DataTypes/Rules/IRule.h>
#include <SceneAPI/SceneCore/DataTypes/ManifestBase/ISceneNodeSelectionList.h>
namespace AZ
{
namespace SceneAPI
{
namespace DataTypes
{
class ISkeletonProxyRule
: public IRule
{
public:
AZ_RTTI(ISkeletonProxyRule, "{0F1D03FA-E6A8-4E9D-8EF8-3AB426360C45}", IRule);
~ISkeletonProxyRule() override = default;
virtual size_t GetProxyGroupCount() const = 0;
};
} // DataTypes
} // SceneAPI
} // AZ
@@ -0,0 +1,92 @@
/*
* 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/RTTI/RTTI.h>
#include <SceneAPI/SceneCore/DataTypes/Rules/IRule.h>
#include <SceneAPI/SceneCore/DataTypes/ManifestBase/ISceneNodeSelectionList.h>
namespace AZ
{
namespace SceneAPI
{
namespace DataTypes
{
/*!
The author of the touch bendable asset will be able to define stiffness, damping and thickness
as attributes per bone. Adding those kind of attributes to a node is supported
by DCC tools and the FBX API (FbxProperty), but SceneAPI doesn't support parsing those attributes into the
Scene Nodes or IGraphObjects. In the meantime, and while parsing Extra Atrributes is not supported by SceneAPI, the
content author should manually set the values in this Modifier. The values will be applied to all bones.
The ShouldOverride*() methods are put in place so in the future the content author can override
all the attributes at once without re-exporting assets from the DCC tools.
This is more of a convenience.
If the original asset doesn't have any of these attributes in the bones, then the values
of this rule will be applied to the root bone. Children bones will copy the parents attributes
for all unspecified attributes.
*/
class ITouchBendingRule
: public IRule
{
public:
AZ_RTTI(ITouchBendingRule, "{2FE2B499-DB71-4D69-8944-6DE2396D6E78}", IRule);
~ITouchBendingRule() override = default;
virtual const AZStd::string& GetRootBoneName() const = 0;
/*!
The returned list contains only one mesh in 99.99% of the cases.
The mesh is supposed to be the proximity trigger mesh.
Most of the time the content author would want the proximity trigger mesh
to be as simple as possible for performance reasons. So, something like a simple
cube that covers the main render mesh is the ideal thing to do for collision detection.
The selected proximity mesh is stored in a list, because there can be extreme cases
where several meshes can define the proximity trigger volume. They will all be combined
into a single submesh into the exported CGF file, at the expense of performance when the
engine calculates if a vegetation mesh is being touched or not.
*/
virtual ISceneNodeSelectionList& GetSceneNodeSelectionList() = 0;
virtual const ISceneNodeSelectionList& GetSceneNodeSelectionList() const = 0;
///If true, The stifness parameter for all the bones
///in the tree will be set to GetOverrideStiffness(), replacing
///the value set by the Author of the asset.
virtual bool ShouldOverrideStiffness() const = 0;
///A value from 0.0f to 1.0f.
///0.0 means no stiffness, the tree will look like a sad willow.
///Segments (bones) of the tree would never return to its original pose
///after being pushed by a Collider.
virtual float GetOverrideStiffness() const = 0;
///If true, The Damping parameter for all the bones
///in the tree will be set to GetOverrideDamping(), replacing
///the value set by the Author of the asset.
virtual bool ShouldOverrideDamping() const = 0;
///A value from 0.0 to 1.0. 0.0 means no damping, lots of back and forth movement around its original pose.
///1.0 means maximum damping, the segment will quickly converge back to its original pose.
virtual float GetOverrideDamping() const = 0;
///If true, The thickness parameter for all the bones
///in the tree will be set to GetOverrideThickness(), replacing
///the value set by the Author of the asset.
virtual bool ShouldOverrideThickness() const = 0;
///If you imagine the Segment (or Bone) to be a cylinder, this is its radius in meters.
virtual float GetOverrideThickness() const = 0;
}; //class ITouchBendingRule
} //namespace DataTypes
} // namespace SceneAPI
} // namespace AZ
+346
View File
@@ -0,0 +1,346 @@
/*
* 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.
*
*/
#if !defined(AZ_MONOLITHIC_BUILD)
#include <AzCore/Component/EntityBus.h>
#include <AzCore/Component/Entity.h>
#include <AzCore/EBus/EBus.h>
#include <AzCore/Module/Environment.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <SceneAPI/SceneCore/Components/BehaviorComponent.h>
#include <SceneAPI/SceneCore/Components/LoadingComponent.h>
#include <SceneAPI/SceneCore/Components/GenerationComponent.h>
#include <SceneAPI/SceneCore/Components/ExportingComponent.h>
#include <SceneAPI/SceneCore/Components/Utilities/EntityConstructor.h>
#include <SceneAPI/SceneCore/Components/SceneSystemComponent.h>
#include <SceneAPI/SceneCore/Containers/RuleContainer.h>
#include <SceneAPI/SceneCore/Containers/SceneManifest.h>
#include <SceneAPI/SceneCore/DataTypes/IManifestObject.h>
#include <SceneAPI/SceneCore/DataTypes/IGraphObject.h>
#include <SceneAPI/SceneCore/DataTypes/Groups/IGroup.h>
#include <SceneAPI/SceneCore/DataTypes/Groups/IMeshGroup.h>
#include <SceneAPI/SceneCore/DataTypes/Groups/ISkeletonGroup.h>
#include <SceneAPI/SceneCore/DataTypes/Groups/ISkinGroup.h>
#include <SceneAPI/SceneCore/DataTypes/Groups/IAnimationGroup.h>
#include <SceneAPI/SceneCore/DataTypes/Rules/IRule.h>
#include <SceneAPI/SceneCore/DataTypes/Rules/IBlendShapeRule.h>
#include <SceneAPI/SceneCore/DataTypes/Rules/ICommentRule.h>
#include <SceneAPI/SceneCore/DataTypes/Rules/IMaterialRule.h>
#include <SceneAPI/SceneCore/DataTypes/Rules/IMeshAdvancedRule.h>
#include <SceneAPI/SceneCore/DataTypes/Rules/IOriginRule.h>
#include <SceneAPI/SceneCore/DataTypes/Rules/ILodRule.h>
#include <SceneAPI/SceneCore/DataTypes/Rules/ISkeletonProxyRule.h>
#include <SceneAPI/SceneCore/DataTypes/GraphData/IAnimationData.h>
#include <SceneAPI/SceneCore/DataTypes/GraphData/IBlendShapeData.h>
#include <SceneAPI/SceneCore/DataTypes/GraphData/IBoneData.h>
#include <SceneAPI/SceneCore/DataTypes/GraphData/IMaterialData.h>
#include <SceneAPI/SceneCore/DataTypes/GraphData/IMeshData.h>
#include <SceneAPI/SceneCore/DataTypes/GraphData/IMeshVertexColorData.h>
#include <SceneAPI/SceneCore/DataTypes/GraphData/IMeshVertexUVData.h>
#include <SceneAPI/SceneCore/DataTypes/GraphData/ISkinWeightData.h>
#include <SceneAPI/SceneCore/DataTypes/GraphData/ITransform.h>
#include <SceneAPI/SceneCore/DataTypes/ManifestBase/ISceneNodeSelectionList.h>
#include <SceneAPI/SceneCore/Export/MtlMaterialExporter.h>
#include <SceneAPI/SceneCore/Import/ManifestImportRequestHandler.h>
#include <SceneAPI/SceneCore/Utilities/PatternMatcher.h>
#include <SceneAPI/SceneCore/Utilities/Reporting.h>
namespace AZ
{
namespace SceneAPI
{
namespace SceneCore
{
static class EntityMonitor* g_entityMonitor = nullptr;
static AZ::Entity* g_behaviors = nullptr;
static AZ::EntityId g_behaviorsId;
static AZStd::vector<AZ::ComponentDescriptor*> g_componentDescriptors;
static AZ::SceneAPI::Import::ManifestImportRequestHandler* g_manifestImporter = nullptr;
class EntityMonitor
: public AZ::EntityBus::Handler
{
public:
AZ_CLASS_ALLOCATOR(EntityMonitor, AZ::SystemAllocator, 0);
EntityMonitor()
{
AZ::EntityBus::Handler::BusConnect(g_behaviorsId);
}
~EntityMonitor()
{
AZ::EntityBus::Handler::BusDisconnect(g_behaviorsId);
}
void OnEntityDestruction(const AZ::EntityId& entityId) override
{
if (entityId == g_behaviorsId)
{
// Another part of the code has claimed and deleted this entity already.
g_behaviors = nullptr;
AZ::EntityBus::Handler::BusDisconnect(g_behaviorsId);
g_behaviorsId.SetInvalid();
}
}
};
void Initialize()
{
// Explicitly creating this component early as this currently needs to be available to the
// RC before Gems are loaded in order to know the file extension.
if (!g_manifestImporter)
{
g_manifestImporter = aznew AZ::SceneAPI::Import::ManifestImportRequestHandler();
g_manifestImporter->Activate();
}
}
bool IMeshGroupConverter(AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement)
{
if (classElement.GetVersion() == 1)
{
// There have been 2 version of IMeshGroup, one that directly inherited from IGroup and one that
// inherited as IMeshGroup : ISceneNodeGroup (was IMeshBaseGroup) : IGroup. To fix this, check
// if {1D20FA11-B184-429E-8C86-745852234845} (ISceneNodeGroup) is present and if not add it.
AZ::SerializeContext::DataElementNode& baseClass = classElement.GetSubElement(0);
if (baseClass.GetId() != AZ::SceneAPI::DataTypes::ISceneNodeGroup::TYPEINFO_Uuid())
{
if (!baseClass.Convert<AZ::SceneAPI::DataTypes::ISceneNodeGroup>(context))
{
AZ_TracePrintf(AZ::SceneAPI::Utilities::ErrorWindow, "Failed to upgrade IMeshGroup from version 1.");
return false;
}
}
}
return true;
}
void ReflectTypes(AZ::SerializeContext* context)
{
if (!context)
{
AZ::ComponentApplicationBus::BroadcastResult(context, &AZ::ComponentApplicationBus::Events::GetSerializeContext);
}
// Check if this library hasn't already been reflected. This can happen as the ResourceCompilerScene needs
// to explicitly load and reflect the SceneAPI libraries to discover the available extension, while
// Gems with system components need to do the same in the Project Configurator.
if (context && (context->IsRemovingReflection() || !context->FindClassData(AZ::SceneAPI::DataTypes::IGroup::TYPEINFO_Uuid())))
{
AZ::SceneAPI::DataTypes::IManifestObject::Reflect(context);
// Register components
AZ::SceneAPI::SceneCore::BehaviorComponent::Reflect(context);
AZ::SceneAPI::SceneCore::LoadingComponent::Reflect(context);
AZ::SceneAPI::SceneCore::GenerationComponent::Reflect(context);
AZ::SceneAPI::SceneCore::ExportingComponent::Reflect(context);
AZ::SceneAPI::SceneCore::RCExportingComponent::Reflect(context);
AZ::SceneAPI::SceneCore::SceneSystemComponent::Reflect(context);
// Register group interfaces
context->Class<AZ::SceneAPI::DataTypes::IGroup, AZ::SceneAPI::DataTypes::IManifestObject>()->Version(1);
context->Class<AZ::SceneAPI::DataTypes::ISceneNodeGroup, AZ::SceneAPI::DataTypes::IGroup>()->Version(1);
context->Class<AZ::SceneAPI::DataTypes::IMeshGroup, AZ::SceneAPI::DataTypes::ISceneNodeGroup>()->Version(2, &IMeshGroupConverter);
context->Class<AZ::SceneAPI::DataTypes::ISkeletonGroup, AZ::SceneAPI::DataTypes::IGroup>()->Version(1);
context->Class<AZ::SceneAPI::DataTypes::ISkinGroup, AZ::SceneAPI::DataTypes::ISceneNodeGroup>()->Version(1);
context->Class<AZ::SceneAPI::DataTypes::IAnimationGroup, AZ::SceneAPI::DataTypes::IGroup>()->Version(1);
// Register rule interfaces
context->Class<AZ::SceneAPI::DataTypes::IRule, AZ::SceneAPI::DataTypes::IManifestObject>()->Version(1);
context->Class<AZ::SceneAPI::DataTypes::IBlendShapeRule, AZ::SceneAPI::DataTypes::IRule>()->Version(1);
context->Class<AZ::SceneAPI::DataTypes::ICommentRule, AZ::SceneAPI::DataTypes::IRule>()->Version(1);
context->Class<AZ::SceneAPI::DataTypes::IMaterialRule, AZ::SceneAPI::DataTypes::IRule>()->Version(1);
context->Class<AZ::SceneAPI::DataTypes::IMeshAdvancedRule, AZ::SceneAPI::DataTypes::IRule>()->Version(1);
context->Class<AZ::SceneAPI::DataTypes::IOriginRule, AZ::SceneAPI::DataTypes::IRule>()->Version(1);
context->Class<AZ::SceneAPI::DataTypes::ILodRule, AZ::SceneAPI::DataTypes::IRule>()->Version(1);
context->Class<AZ::SceneAPI::DataTypes::ISkeletonProxyRule, AZ::SceneAPI::DataTypes::IRule>()->Version(1);
// Register graph data interfaces
context->Class<AZ::SceneAPI::DataTypes::IAnimationData, AZ::SceneAPI::DataTypes::IGraphObject>()->Version(1);
context->Class<AZ::SceneAPI::DataTypes::IBlendShapeData, AZ::SceneAPI::DataTypes::IGraphObject>()->Version(1);
context->Class<AZ::SceneAPI::DataTypes::IBoneData, AZ::SceneAPI::DataTypes::IGraphObject>()->Version(1);
context->Class<AZ::SceneAPI::DataTypes::IMaterialData, AZ::SceneAPI::DataTypes::IGraphObject>()->Version(1);
context->Class<AZ::SceneAPI::DataTypes::IMeshData, AZ::SceneAPI::DataTypes::IGraphObject>()->Version(1);
context->Class<AZ::SceneAPI::DataTypes::IMeshVertexColorData, AZ::SceneAPI::DataTypes::IGraphObject>()->Version(1);
context->Class<AZ::SceneAPI::DataTypes::IMeshVertexUVData, AZ::SceneAPI::DataTypes::IGraphObject>()->Version(1);
context->Class<AZ::SceneAPI::DataTypes::ISkinWeightData, AZ::SceneAPI::DataTypes::IGraphObject>()->Version(1);
context->Class<AZ::SceneAPI::DataTypes::ITransform, AZ::SceneAPI::DataTypes::IGraphObject>()->Version(1);
// Register base manifest types
context->Class<AZ::SceneAPI::DataTypes::ISceneNodeSelectionList>()->Version(1);
// Register containers
AZ::SceneAPI::Containers::RuleContainer::Reflect(context);
AZ::SceneAPI::Containers::SceneManifest::Reflect(context);
// Register utilities
AZ::SceneAPI::SceneCore::PatternMatcher::Reflect(context);
}
}
void Reflect(AZ::SerializeContext* context)
{
ReflectTypes(context);
// Descriptor registration is done in Reflect instead of Initialize because the ResourceCompilerScene initializes the libraries before
// there's an application.
if (g_componentDescriptors.empty())
{
g_componentDescriptors.push_back(AZ::SceneAPI::Export::MaterialExporterComponent::CreateDescriptor());
g_componentDescriptors.push_back(AZ::SceneAPI::Export::RCMaterialExporterComponent::CreateDescriptor());
for (AZ::ComponentDescriptor* descriptor : g_componentDescriptors)
{
AZ::ComponentApplicationBus::Broadcast(&AZ::ComponentApplicationBus::Handler::RegisterComponentDescriptor, descriptor);
}
}
}
void ReflectBehavior(AZ::BehaviorContext* context)
{
AZ::SceneAPI::Containers::Scene::Reflect(context);
AZ::SceneAPI::Containers::SceneGraph::Reflect(context);
AZ::SceneAPI::Containers::SceneManifest::Reflect(context);
AZ::SceneAPI::Containers::RuleContainer::Reflect(context);
}
void Activate()
{
if (g_behaviors)
{
return;
}
g_behaviors = AZ::SceneAPI::SceneCore::EntityConstructor::BuildEntityRaw("Scene Behaviors",
AZ::SceneAPI::SceneCore::BehaviorComponent::TYPEINFO_Uuid());
g_behaviorsId = g_behaviors->GetId();
AZ_Error("SceneCore", !g_entityMonitor, "The EntityMonitor has not been deactivated properly, cannot complete activation");
if (!g_entityMonitor)
{
g_entityMonitor = aznew EntityMonitor();
}
}
void Deactivate()
{
if (g_entityMonitor)
{
delete g_entityMonitor;
g_entityMonitor = nullptr;
}
if (g_behaviors)
{
g_behaviors->Deactivate();
delete g_behaviors;
g_behaviors = nullptr;
g_behaviorsId.SetInvalid();
}
}
void Uninitialize()
{
AZ::SerializeContext* context = nullptr;
AZ::ComponentApplicationBus::BroadcastResult(context, &AZ::ComponentApplicationBus::Events::GetSerializeContext);
if (context)
{
context->EnableRemoveReflection();
Reflect(context);
context->DisableRemoveReflection();
context->CleanupModuleGenericClassInfo();
}
if (!g_componentDescriptors.empty())
{
for (AZ::ComponentDescriptor* descriptor : g_componentDescriptors)
{
descriptor->ReleaseDescriptor();
}
g_componentDescriptors.clear();
g_componentDescriptors.shrink_to_fit();
}
if (g_manifestImporter)
{
g_manifestImporter->Deactivate();
delete g_manifestImporter;
g_manifestImporter = nullptr;
}
}
} // namespace SceneCore
} // namespace SceneAPI
} // namespace AZ
extern "C" AZ_DLL_EXPORT void InitializeDynamicModule(void* env)
{
if (AZ::Environment::IsReady())
{
return;
}
AZ::Environment::Attach(static_cast<AZ::EnvironmentInstance>(env));
AZ::SceneAPI::SceneCore::Initialize();
}
extern "C" AZ_DLL_EXPORT void Reflect(AZ::SerializeContext* context)
{
AZ::SceneAPI::SceneCore::Reflect(context);
}
extern "C" AZ_DLL_EXPORT void ReflectBehavior(AZ::BehaviorContext * context)
{
AZ::SceneAPI::SceneCore::ReflectBehavior(context);
}
extern "C" AZ_DLL_EXPORT void ReflectTypes(AZ::SerializeContext * context)
{
AZ::SceneAPI::SceneCore::ReflectTypes(context);
}
extern "C" AZ_DLL_EXPORT void Activate()
{
AZ::SceneAPI::SceneCore::Activate();
}
extern "C" AZ_DLL_EXPORT void Deactivate()
{
AZ::SceneAPI::SceneCore::Deactivate();
}
extern "C" AZ_DLL_EXPORT void UninitializeDynamicModule()
{
if (!AZ::Environment::IsReady())
{
return;
}
AZ::SceneAPI::SceneCore::Uninitialize();
// This module does not own these allocators, but must clear its cached EnvironmentVariables
// because it is linked into other modules, and thus does not get unloaded from memory always
if (AZ::AllocatorInstance<AZ::SystemAllocator>::IsReady())
{
AZ::AllocatorInstance<AZ::SystemAllocator>::Destroy();
}
if (AZ::AllocatorInstance<AZ::OSAllocator>::IsReady())
{
AZ::AllocatorInstance<AZ::OSAllocator>::Destroy();
}
AZ::Environment::Detach();
}
#endif // !defined(AZ_MONOLITHIC_BUILD)
@@ -0,0 +1,184 @@
/*
* 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 <AzCore/std/smart_ptr/make_shared.h>
#include <AzFramework/StringFunc/StringFunc.h>
#include <AzToolsFramework/Debug/TraceContext.h>
#include <SceneAPI/SceneCore/Components/LoadingComponent.h>
#include <SceneAPI/SceneCore/Components/SceneSystemComponent.h>
#include <SceneAPI/SceneCore/Components/Utilities/EntityConstructor.h>
#include <SceneAPI/SceneCore/Containers/Scene.h>
#include <SceneAPI/SceneCore/Events/AssetImportRequest.h>
#include <SceneAPI/SceneCore/Events/SceneSerializationBus.h>
#include <SceneAPI/SceneCore/Utilities/Reporting.h>
namespace AZ
{
namespace SceneAPI
{
namespace Events
{
//
// Loading Result Combiner
//
LoadingResultCombiner::LoadingResultCombiner()
: m_manifestResult(ProcessingResult::Ignored)
, m_assetResult(ProcessingResult::Ignored)
{
}
void LoadingResultCombiner::operator=(LoadingResult rhs)
{
switch (rhs)
{
case LoadingResult::Ignored:
return;
case LoadingResult::AssetLoaded:
m_assetResult = m_assetResult != ProcessingResult::Failure ? ProcessingResult::Success : ProcessingResult::Failure;
return;
case LoadingResult::ManifestLoaded:
m_manifestResult = m_manifestResult != ProcessingResult::Failure ? ProcessingResult::Success : ProcessingResult::Failure;
return;
case LoadingResult::AssetFailure:
m_assetResult = ProcessingResult::Failure;
return;
case LoadingResult::ManifestFailure:
m_manifestResult = ProcessingResult::Failure;
return;
}
}
ProcessingResult LoadingResultCombiner::GetManifestResult() const
{
return m_manifestResult;
}
ProcessingResult LoadingResultCombiner::GetAssetResult() const
{
return m_assetResult;
}
//
// Asset Importer Request
//
void AssetImportRequest::GetManifestExtension(AZStd::string& /*result*/)
{
}
void AssetImportRequest::GetSupportedFileExtensions(AZStd::unordered_set<AZStd::string>& /*extensions*/)
{
}
ProcessingResult AssetImportRequest::PrepareForAssetLoading(Containers::Scene& /*scene*/, RequestingApplication /*requester*/)
{
return ProcessingResult::Ignored;
}
LoadingResult AssetImportRequest::LoadAsset(Containers::Scene& /*scene*/, const AZStd::string& /*path*/, const Uuid& /*guid*/,
RequestingApplication /*requester*/)
{
return LoadingResult::Ignored;
}
void AssetImportRequest::FinalizeAssetLoading(Containers::Scene& /*scene*/, RequestingApplication /*requester*/)
{
}
ProcessingResult AssetImportRequest::UpdateManifest(Containers::Scene& /*scene*/, ManifestAction /*action*/, RequestingApplication /*requester*/)
{
return ProcessingResult::Ignored;
}
void AssetImportRequest::AreCustomNormalsUsed(bool &value)
{
// Leave the SceneProcessingConfigSystemComponent do the job
AZ_UNUSED(value);
}
AZStd::shared_ptr<Containers::Scene> AssetImportRequest::LoadSceneFromVerifiedPath(const AZStd::string& assetFilePath, const Uuid& sourceGuid,
RequestingApplication requester)
{
AZStd::string sceneName;
AzFramework::StringFunc::Path::GetFileName(assetFilePath.c_str(), sceneName);
AZStd::shared_ptr<Containers::Scene> scene = AZStd::make_shared<Containers::Scene>(AZStd::move(sceneName));
AZ_Assert(scene, "Unable to create new scene for asset importing.");
// Unique pointer, will deactivate and clean up once going out of scope.
SceneCore::EntityConstructor::EntityPointer loaders =
SceneCore::EntityConstructor::BuildEntity("Scene Loading", SceneCore::LoadingComponent::TYPEINFO_Uuid());
ProcessingResultCombiner areAllPrepared;
AssetImportRequestBus::BroadcastResult(areAllPrepared, &AssetImportRequestBus::Events::PrepareForAssetLoading, *scene, requester);
if (areAllPrepared.GetResult() == ProcessingResult::Failure)
{
AZ_TracePrintf(Utilities::ErrorWindow, "Not all asset loaders could initialize.\n");
return nullptr;
}
LoadingResultCombiner filesLoaded;
AssetImportRequestBus::BroadcastResult(filesLoaded, &AssetImportRequestBus::Events::LoadAsset, *scene, assetFilePath, sourceGuid, requester);
AssetImportRequestBus::Broadcast(&AssetImportRequestBus::Events::FinalizeAssetLoading, *scene, requester);
if (filesLoaded.GetAssetResult() != ProcessingResult::Success)
{
AZ_TracePrintf(Utilities::ErrorWindow, "Failed to load requested scene file.\n");
return nullptr;
}
ManifestAction action = ManifestAction::Update;
// If the result for manifest is ignored it means no manifest was found.
if (filesLoaded.GetManifestResult() == ProcessingResult::Failure || filesLoaded.GetManifestResult() == ProcessingResult::Ignored)
{
scene->GetManifest().Clear();
action = ManifestAction::ConstructDefault;
}
ProcessingResultCombiner manifestUpdate;
AssetImportRequestBus::BroadcastResult(manifestUpdate, &AssetImportRequestBus::Events::UpdateManifest, *scene, action, requester);
if (manifestUpdate.GetResult() == ProcessingResult::Failure)
{
AZ_TracePrintf(Utilities::ErrorWindow, "Unable to %s manifest.\n", action == ManifestAction::ConstructDefault ? "create new" : "update");
return nullptr;
}
return scene;
}
bool AssetImportRequest::IsManifestExtension(const char* filePath)
{
AZStd::string manifestExtension;
AssetImportRequestBus::Broadcast(&AssetImportRequestBus::Events::GetManifestExtension, manifestExtension);
AZ_Assert(!manifestExtension.empty(), "Manifest extension was not declared.");
return AzFramework::StringFunc::Path::IsExtension(filePath, manifestExtension.c_str());
}
bool AssetImportRequest::IsSceneFileExtension(const char* filePath)
{
AZStd::unordered_set<AZStd::string> extensions;
AssetImportRequestBus::Broadcast(&AssetImportRequestBus::Events::GetSupportedFileExtensions, extensions);
AZ_Assert(!extensions.empty(), "No extensions found for source files.");
for (const AZStd::string& extension : extensions)
{
if (AzFramework::StringFunc::Path::IsExtension(filePath, extension.c_str()))
{
return true;
}
}
return false;
}
} // namespace Events
} // namespace SceneAPI
} // namespace AZ
@@ -0,0 +1,120 @@
/*
* 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/EBus/EBus.h>
#include <AzCore/Math/Uuid.h>
#include <AzCore/std/smart_ptr/shared_ptr.h>
#include <AzCore/std/string/string.h>
#include <AzCore/std/containers/unordered_set.h>
#include <SceneAPI/SceneCore/SceneCoreConfiguration.h>
#include <SceneAPI/SceneCore/Events/ProcessingResult.h>
namespace AZ
{
namespace SceneAPI
{
namespace Containers
{
class Scene;
}
namespace Events
{
enum class LoadingResult
{
Ignored,
AssetLoaded,
ManifestLoaded,
AssetFailure,
ManifestFailure
};
class SCENE_CORE_API LoadingResultCombiner
{
public:
LoadingResultCombiner();
void operator= (LoadingResult rhs);
ProcessingResult GetManifestResult() const;
ProcessingResult GetAssetResult() const;
private:
ProcessingResult m_manifestResult;
ProcessingResult m_assetResult;
};
class SCENE_CORE_API AssetImportRequest
: public AZ::EBusTraits
{
public:
enum RequestingApplication
{
Generic,
Editor,
AssetProcessor
};
enum ManifestAction
{
Update,
ConstructDefault
};
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple;
using MutexType = AZStd::recursive_mutex;
virtual ~AssetImportRequest() = 0;
//! Fills the given list with all available file extensions, excluding the extension for the manifest.
virtual void GetSupportedFileExtensions(AZStd::unordered_set<AZStd::string>& extensions);
//! Gets the file extension for the manifest.
virtual void GetManifestExtension(AZStd::string& result);
//! Before asset loading starts this is called to allow for any required initialization.
virtual ProcessingResult PrepareForAssetLoading(Containers::Scene& scene, RequestingApplication requester);
//! Starts the loading of the asset at the given path in the given scene. Loading optimizations can be applied based on
//! the calling application.
virtual LoadingResult LoadAsset(Containers::Scene& scene, const AZStd::string& path, const Uuid& guid, RequestingApplication requester);
//! FinalizeAssetLoading can be used to do any work to complete loading, such as complete asynchronous loading
//! or adjust the loaded content in the the SceneGraph. While manifest changes can be done here as well, it's
//! recommended to wait for the UpdateManifest call.
virtual void FinalizeAssetLoading(Containers::Scene& scene, RequestingApplication requester);
//! After all loading has completed, this call can be used to make adjustments to the manifest. Based on the given
//! action this can mean constructing a new manifest or updating an existing manifest. This call is intended
//! to deal with any default behavior of the manifest.
virtual ProcessingResult UpdateManifest(Containers::Scene& scene, ManifestAction action,
RequestingApplication requester);
// Get scene processing project setting: UseCustomNormal
virtual void AreCustomNormalsUsed(bool & value);
//! Utility function to load an asset and manifest from file by using the EBus functions above.
//! @param assetFilePath The absolute path to the source file (not the manifest).
//! @param sourceGuid The guid assigned to the source file (not the manifest).
//! @param requester The application making the request to load the file. This can be used to optimize the type and amount of data
//! to load.
static AZStd::shared_ptr<Containers::Scene> LoadSceneFromVerifiedPath(const AZStd::string& assetFilePath,
const Uuid&sourceGuid, RequestingApplication requester);
//! Utility function to determine if a given file path points to a scene manifest file (.assetinfo).
//! @param filePath A relative or absolute path to the file to check.
static bool IsManifestExtension(const char* filePath);
//! Utility function to determine if a given file path points to a scene file (for instance .fbx).
//! @param filePath A relative or absolute path to the file to check.
static bool IsSceneFileExtension(const char* filePath);
};
using AssetImportRequestBus = AZ::EBus<AssetImportRequest>;
inline AssetImportRequest::~AssetImportRequest() = default;
} // namespace Events
} // namespace SceneAPI
} // namespace AZ
@@ -0,0 +1,53 @@
/*
* 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/Events/CallProcessorBinder.h>
namespace AZ
{
namespace SceneAPI
{
namespace Events
{
CallProcessorBinder::~CallProcessorBinder()
{
BusDisconnect();
}
ProcessingResult CallProcessorBinder::Process(ICallContext* context)
{
ProcessingResultCombiner result;
for (auto& it : m_bindings)
{
result += it->Process(this, context);
}
return result.GetResult();
}
void CallProcessorBinder::ActivateBindings()
{
CallProcessorBus::Handler::BusConnect();
}
void CallProcessorBinder::DeactivateBindings()
{
CallProcessorBus::Handler::BusDisconnect();
}
void CallProcessorBinder::ClearBindings()
{
m_bindings.clear();
}
} // namespace Events
} // namespace SceneAPI
} // namespace AZ
@@ -0,0 +1,136 @@
/*
* 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/std/containers/vector.h>
#include <AzCore/std/smart_ptr/unique_ptr.h>
#include <SceneAPI/SceneCore/SceneCoreConfiguration.h>
#include <SceneAPI/SceneCore/Events/ProcessingResult.h>
#include <SceneAPI/SceneCore/Events/CallProcessorBus.h>
namespace AZ
{
namespace SceneAPI
{
namespace Events
{
// CallProcessorBinder automatically registers to the CallProcessorBus to
// handle process calls on behave to the parent class by filtering
// and forwarding calls to the appropriate functions.
// To use, derive from CallProcessorBinder and call "BindToCall"
// one or more times to register functions with that accept a
// processor context with the signature "ProcessingResult(X& context) const" or
// "ProcessingResult(X& context)", where X is any class derived from ICallContext.
//
// Example:
// Example inherits from CallProcessorBinder and has the following
// function: ProcessingResult ProcessContext(ExampleContext& context);
// In Example's constructor call:
// BindToCall(&Example::ProcessContext);
// If an processor call with the ExampleContext is send,
// Example::ProcessContext will automatically be called.
class SCENE_CORE_CLASS CallProcessorBinder :
public CallProcessorBus::Handler
{
public:
enum class TypeMatch
{
Exact,
Derived
};
AZ_RTTI(CallProcessorBinder, "{887A50B4-3FC4-4695-A88E-CA7BE931A73E}");
SCENE_CORE_API ProcessingResult Process(ICallContext* context) override final;
CallProcessorBinder() = default;
SCENE_CORE_API virtual ~CallProcessorBinder();
protected:
CallProcessorBinder(const CallProcessorBinder&) = delete;
template<typename Class, typename ContextType>
inline void BindToCall(ProcessingResult(Class::*Func)(ContextType& context) const, TypeMatch typeMatch = TypeMatch::Exact);
template<typename Class, typename ContextType>
inline void BindToCall(ProcessingResult(Class::*Func)(ContextType& context), TypeMatch typeMatch = TypeMatch::Exact);
SCENE_CORE_API void ActivateBindings();
SCENE_CORE_API void DeactivateBindings();
SCENE_CORE_API void ClearBindings();
private:
class FunctionBinding
{
public:
virtual ~FunctionBinding() = default;
virtual ProcessingResult Process(CallProcessorBinder* thisPtr, ICallContext* context) = 0;
protected:
template<typename Class, typename ContextType, typename Function>
ProcessingResult Call(CallProcessorBinder* thisPtr, ICallContext* context, Function function);
};
template<typename Class, typename ContextType>
class ConstFunctionBindingTemplate : public FunctionBinding
{
public:
using Function = ProcessingResult(Class::*)(ContextType&) const;
explicit ConstFunctionBindingTemplate(Function function);
~ConstFunctionBindingTemplate() override = default;
ProcessingResult Process(CallProcessorBinder* thisPtr, ICallContext* context) override;
private:
Function m_function;
};
template<typename Class, typename ContextType>
class FunctionBindingTemplate : public FunctionBinding
{
public:
using Function = ProcessingResult(Class::*)(ContextType&);
explicit FunctionBindingTemplate(Function function);
~FunctionBindingTemplate() override = default;
ProcessingResult Process(CallProcessorBinder* thisPtr, ICallContext* context) override;
private:
Function m_function;
};
template<typename Class, typename ContextType>
class ConstDerivedFunctionBindingTemplate : public FunctionBinding
{
public:
using Function = ProcessingResult(Class::*)(ContextType&) const;
explicit ConstDerivedFunctionBindingTemplate(Function function);
~ConstDerivedFunctionBindingTemplate() override = default;
ProcessingResult Process(CallProcessorBinder* thisPtr, ICallContext* context) override;
private:
Function m_function;
};
template<typename Class, typename ContextType>
class DerivedFunctionBindingTemplate : public FunctionBinding
{
public:
using Function = ProcessingResult(Class::*)(ContextType&);
explicit DerivedFunctionBindingTemplate(Function function);
~DerivedFunctionBindingTemplate() override = default;
ProcessingResult Process(CallProcessorBinder* thisPtr, ICallContext* context) override;
private:
Function m_function;
};
AZStd::vector<AZStd::unique_ptr<FunctionBinding>> m_bindings;
};
} // namespace Events
} // namespace SceneAPI
} // namespace AZ
#include <SceneAPI/SceneCore/Events/CallProcessorBinder.inl>
@@ -0,0 +1,155 @@
/*
* 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/typetraits/is_base_of.h>
namespace AZ
{
namespace SceneAPI
{
namespace Events
{
template<typename Class, typename ContextType>
void CallProcessorBinder::BindToCall(ProcessingResult(Class::*Func)(ContextType& context) const, TypeMatch typeMatch)
{
static_assert((AZStd::is_base_of<CallProcessorBinder, Class>::value),
"CallProcessorBinder can only bind to classes derived from it.");
static_assert((AZStd::is_base_of<ICallContext, ContextType>::value),
"Only arguments derived from ICallContext are accepted by CallProcessorBinder");
if (typeMatch == TypeMatch::Exact)
{
using Binder = ConstFunctionBindingTemplate<Class, ContextType>;
m_bindings.emplace_back(AZStd::make_unique<Binder>(Func));
}
else
{
using Binder = ConstDerivedFunctionBindingTemplate<Class, ContextType>;
m_bindings.emplace_back(AZStd::make_unique<Binder>(Func));
}
}
template<typename Class, typename ContextType>
void CallProcessorBinder::BindToCall(ProcessingResult(Class::*Func)(ContextType& context), TypeMatch typeMatch)
{
static_assert((AZStd::is_base_of<CallProcessorBinder, Class>::value),
"CallProcessorBinder can only bind to classes derived from it.");
static_assert((AZStd::is_base_of<ICallContext, ContextType>::value),
"Only arguments derived from ICallContext are accepted by CallProcessorBinder");
if (typeMatch == TypeMatch::Exact)
{
using Binder = FunctionBindingTemplate<Class, ContextType>;
m_bindings.emplace_back(AZStd::make_unique<Binder>(Func));
}
else
{
using Binder = DerivedFunctionBindingTemplate<Class, ContextType>;
m_bindings.emplace_back(AZStd::make_unique<Binder>(Func));
}
}
// FunctionBinding
template<typename Class, typename ContextType, typename Function>
ProcessingResult CallProcessorBinder::FunctionBinding::Call(CallProcessorBinder* thisPtr, ICallContext* context, Function function)
{
ContextType* arg = azrtti_cast<ContextType*>(context);
if (arg)
{
// As the compiler can't "see" the target Class for conversion the safety checks in azrtti_cast
// throw a false positive. Instead of using azrtti_cast directly, so address look up here
// and use a standard reinterpret_cast.
void* address = thisPtr->RTTI_AddressOf(Class::TYPEINFO_Uuid());
AZ_Assert(address, "Unable to case CallProcessorBinder to %s.", Class::TYPEINFO_Name());
return (reinterpret_cast<Class*>(address)->*(function))(*arg);
}
else
{
AZ_Assert(arg, "CallProcessorBinder failed to cast context for unknown reasons.");
return ProcessingResult::Failure;
}
}
// ConstFunctionBindingTemplate
template<typename Class, typename ContextType>
CallProcessorBinder::ConstFunctionBindingTemplate<Class, ContextType>::ConstFunctionBindingTemplate(Function function)
: m_function(function)
{
}
template<typename Class, typename ContextType>
ProcessingResult CallProcessorBinder::ConstFunctionBindingTemplate<Class, ContextType>::Process(
CallProcessorBinder* thisPtr, ICallContext* context)
{
if (context && context->RTTI_GetType() == ContextType::TYPEINFO_Uuid())
{
return Call<Class, ContextType, Function>(thisPtr, context, m_function);
}
return ProcessingResult::Ignored;
}
//FunctionBindingTemplate
template<typename Class, typename ContextType>
CallProcessorBinder::FunctionBindingTemplate<Class, ContextType>::FunctionBindingTemplate(Function function)
: m_function(function)
{
}
template<typename Class, typename ContextType>
ProcessingResult CallProcessorBinder::FunctionBindingTemplate<Class, ContextType>::Process(
CallProcessorBinder* thisPtr, ICallContext* context)
{
if (context && context->RTTI_GetType() == ContextType::TYPEINFO_Uuid())
{
return Call<Class, ContextType, Function>(thisPtr, context, m_function);
}
return ProcessingResult::Ignored;
}
// ConstDerivedFunctionBindingTemplate
template<typename Class, typename ContextType>
CallProcessorBinder::ConstDerivedFunctionBindingTemplate<Class, ContextType>::ConstDerivedFunctionBindingTemplate(Function function)
: m_function(function)
{
}
template<typename Class, typename ContextType>
ProcessingResult CallProcessorBinder::ConstDerivedFunctionBindingTemplate<Class, ContextType>::Process(
CallProcessorBinder* thisPtr, ICallContext* context)
{
if (context && context->RTTI_IsTypeOf(ContextType::TYPEINFO_Uuid()))
{
return Call<Class, ContextType, Function>(thisPtr, context, m_function);
}
return ProcessingResult::Ignored;
}
//DerivedFunctionBindingTemplate
template<typename Class, typename ContextType>
CallProcessorBinder::DerivedFunctionBindingTemplate<Class, ContextType>::DerivedFunctionBindingTemplate(Function function)
: m_function(function)
{
}
template<typename Class, typename ContextType>
ProcessingResult CallProcessorBinder::DerivedFunctionBindingTemplate<Class, ContextType>::Process(
CallProcessorBinder* thisPtr, ICallContext* context)
{
if (context && context->RTTI_IsTypeOf(ContextType::TYPEINFO_Uuid()))
{
return Call<Class, ContextType, Function>(thisPtr, context, m_function);
}
return ProcessingResult::Ignored;
}
} // namespace Events
} // namespace SceneAPI
} // namespace AZ
@@ -0,0 +1,40 @@
/*
* 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/Events/CallProcessorBus.h>
namespace AZ
{
namespace SceneAPI
{
namespace Events
{
uint8_t CallProcessor::GetPriority() const
{
return CallProcessor::NormalProcessing;
}
bool CallProcessor::Compare(const CallProcessor* rhs) const
{
AZ_Assert(rhs, "Invalid argument for ProcessingEvents::Compare.");
return GetPriority() < rhs->GetPriority();
}
ProcessingResult Process(ICallContext& context)
{
ProcessingResultCombiner result;
CallProcessorBus::BroadcastResult(result, &CallProcessorBus::Events::Process, &context);
return result.GetResult();
}
} // namespace Events
} // namespace SceneAPI
} // namespace AZ
@@ -0,0 +1,86 @@
/*
* 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/std/containers/vector.h>
#include <AzCore/RTTI/RTTI.h>
#include <AzCore/EBus/EBus.h>
#include <SceneAPI/SceneCore/SceneCoreConfiguration.h>
#include <SceneAPI/SceneCore/Events/ProcessingResult.h>
namespace AZ
{
namespace SceneAPI
{
namespace Events
{
class ICallContext
{
public:
AZ_RTTI(ICallContext, "{525ED64B-9425-4F88-8E6B-D02FF61429B7}");
virtual ~ICallContext() = 0;
};
class SCENE_CORE_CLASS CallProcessor
: public AZ::EBusTraits
{
public:
enum ProcessingPriority : uint8_t
{
EarliestProcessing = 0,
EarlyProcessing = 64,
NormalProcessing = 128,
LateProcessing = 192,
LatestProcessing = 255
};
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::MultipleAndOrdered;
using MutexType = AZStd::recursive_mutex;
virtual ~CallProcessor() = 0;
// Request to process the event for the given context.
virtual ProcessingResult Process(ICallContext* context) = 0;
// The order of the calling processors is undetermined, but sometimes a context needs to be
// processed before another. In these situations the priority of a processor can be
// reduced or increased to make sure it gets called before or after normal processing
// has happened. Note that if two or more processors are raised to the same priority
// there will still not be a guarantee which will gets to do work first.
SCENE_CORE_API virtual uint8_t GetPriority() const;
SCENE_CORE_API bool Compare(const CallProcessor* rhs) const;
};
using CallProcessorBus = AZ::EBus<CallProcessor>;
// Utility function to call the CallProcessor EBus.
SCENE_CORE_API ProcessingResult Process(ICallContext& context);
// Utility function to all the CallProcessor EBus.
// Usage:
// Process<Context>(ContextArg1, ContextArg2, ContextArg3);
template<typename Context, typename... Args>
ProcessingResult Process(Args&&... args);
inline ICallContext::~ICallContext()
{
}
inline CallProcessor::~CallProcessor()
{
}
} // namespace Events
} // namespace SceneAPI
} // namespace AZ
#include <SceneAPI/SceneCore/Events/CallProcessorBus.inl>
@@ -0,0 +1,29 @@
/*
* 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/utils.h>
namespace AZ
{
namespace SceneAPI
{
namespace Events
{
template<typename Context, typename... Args>
ProcessingResult Process(Args&&... args)
{
Context context(std::forward<Args>(args)...);
return Process(context);
}
} // Events
} // SceneAPI
} // AZ
@@ -0,0 +1,150 @@
/*
* 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/Events/ExportEventContext.h>
namespace AZ
{
namespace SceneAPI
{
namespace Events
{
/////////////
// PreExportEventContext
/////////////
PreExportEventContext::PreExportEventContext(ExportProductList& productList, const AZStd::string& outputDirectory, const Containers::Scene& scene, const char* platformIdentifier)
: m_outputDirectory(outputDirectory)
, m_productList(productList)
, m_scene(scene)
, m_platformIdentifier(platformIdentifier)
{
}
PreExportEventContext::PreExportEventContext(ExportProductList& productList, AZStd::string&& outputDirectory, const Containers::Scene& scene, const char* platformIdentifier)
: m_outputDirectory(AZStd::move(outputDirectory))
, m_productList(productList)
, m_scene(scene)
, m_platformIdentifier(platformIdentifier)
{
}
const AZStd::string& PreExportEventContext::GetOutputDirectory() const
{
return m_outputDirectory;
}
ExportProductList& PreExportEventContext::GetProductList()
{
return m_productList;
}
const ExportProductList& PreExportEventContext::GetProductList() const
{
return m_productList;
}
const Containers::Scene& PreExportEventContext::GetScene() const
{
return m_scene;
}
const char* PreExportEventContext::GetPlatformIdentifier() const
{
return m_platformIdentifier;
}
/////////////
// ExportEventContext
/////////////
ExportEventContext::ExportEventContext(ExportProductList& productList, const AZStd::string& outputDirectory, const Containers::Scene& scene, const char* platformIdentifier)
: m_outputDirectory(outputDirectory)
, m_productList(productList)
, m_scene(scene)
, m_platformIdentifier(platformIdentifier)
{
}
ExportEventContext::ExportEventContext(ExportProductList& productList, AZStd::string&& outputDirectory, const Containers::Scene& scene, const char* platformIdentifier)
: m_outputDirectory(AZStd::move(outputDirectory))
, m_productList(productList)
, m_scene(scene)
, m_platformIdentifier(platformIdentifier)
{
}
const AZStd::string& ExportEventContext::GetOutputDirectory() const
{
return m_outputDirectory;
}
ExportProductList& ExportEventContext::GetProductList()
{
return m_productList;
}
const ExportProductList& ExportEventContext::GetProductList() const
{
return m_productList;
}
const Containers::Scene& ExportEventContext::GetScene() const
{
return m_scene;
}
const char* ExportEventContext::GetPlatformIdentifier() const
{
return m_platformIdentifier;
}
/////////////
// PostExportEventContext
/////////////
PostExportEventContext::PostExportEventContext(ExportProductList& productList, const AZStd::string& outputDirectory, const char* platformIdentifier)
: m_outputDirectory(outputDirectory)
, m_productList(productList)
, m_platformIdentifier(platformIdentifier)
{
}
PostExportEventContext::PostExportEventContext(ExportProductList& productList, AZStd::string&& outputDirectory, const char* platformIdentifier)
: m_outputDirectory(AZStd::move(outputDirectory))
, m_platformIdentifier(platformIdentifier)
, m_productList(productList)
{
}
const AZStd::string PostExportEventContext::GetOutputDirectory() const
{
return m_outputDirectory;
}
ExportProductList& PostExportEventContext::GetProductList()
{
return m_productList;
}
const ExportProductList& PostExportEventContext::GetProductList() const
{
return m_productList;
}
const char* PostExportEventContext::GetPlatformIdentifier() const
{
return m_platformIdentifier;
}
} // Events
} // SceneAPI
} // AZ
@@ -0,0 +1,126 @@
#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 <SceneAPI/SceneCore/Events/CallProcessorBus.h>
#include <SceneAPI/SceneCore/SceneCoreConfiguration.h>
namespace AZ
{
namespace SceneAPI
{
namespace Containers
{
class Scene;
}
namespace DataTypes
{
class IGroup;
}
namespace Events
{
class ExportProductList;
// Signals an export of the contained scene is about to happen.
class PreExportEventContext
: public ICallContext
{
public:
AZ_RTTI(PreExportEventContext, "{6B303E35-8BF0-43DD-9AD7-7D7F24F18F37}", ICallContext);
~PreExportEventContext() override = default;
SCENE_CORE_API PreExportEventContext(ExportProductList& productList, const AZStd::string& outputDirectory, const Containers::Scene& scene, const char* platformIdentifier);
SCENE_CORE_API PreExportEventContext(ExportProductList& productList, AZStd::string&& outputDirectory, const Containers::Scene& scene, const char* platformIdentifier);
SCENE_CORE_API const AZStd::string& GetOutputDirectory() const;
SCENE_CORE_API ExportProductList& GetProductList();
SCENE_CORE_API const ExportProductList& GetProductList() const;
SCENE_CORE_API const Containers::Scene& GetScene() const;
SCENE_CORE_API const char* GetPlatformIdentifier() const;
private:
AZStd::string m_outputDirectory;
ExportProductList& m_productList;
const Containers::Scene& m_scene;
/**
* The platform identifier is configured in the AssetProcessorPlatformConfig.ini and is data driven
* it is generally a value like "pc" or "ios" or such.
* this const char* points at memory owned by the caller but it will always survive for the duration of the call.
*/
const char* m_platformIdentifier = nullptr;
};
// Signals the scene that the contained scene needs to be exported to the specified directory.
class ExportEventContext
: public ICallContext
{
public:
AZ_RTTI(ExportEventContext, "{ECE4A3BD-CE48-4B17-9609-6D97F8A887D3}", ICallContext);
~ExportEventContext() override = default;
SCENE_CORE_API ExportEventContext(ExportProductList& productList, const AZStd::string& outputDirectory, const Containers::Scene& scene, const char* platformIdentifier);
SCENE_CORE_API ExportEventContext(ExportProductList& productList, AZStd::string&& outputDirectory, const Containers::Scene& scene, const char* platformIdentifier);
SCENE_CORE_API const AZStd::string& GetOutputDirectory() const;
SCENE_CORE_API ExportProductList& GetProductList();
SCENE_CORE_API const ExportProductList& GetProductList() const;
SCENE_CORE_API const Containers::Scene& GetScene() const;
SCENE_CORE_API const char* GetPlatformIdentifier() const;
private:
AZStd::string m_outputDirectory;
ExportProductList& m_productList;
const Containers::Scene& m_scene;
/**
* The platform identifier is configured in the AssetProcessorPlatformConfig.ini and is data driven
* it is generally a value like "pc" or "ios" or such.
* this const char* points at memory owned by the caller but it will always survive for the duration of the call.
*/
const char* m_platformIdentifier = nullptr;
};
// Signals that an export has completed and written (if successful) to the specified directory.
class PostExportEventContext
: public ICallContext
{
public:
AZ_RTTI(PostExportEventContext, "{92E0AD59-62CA-45E3-BB73-5659D10FF0DE}", ICallContext);
~PostExportEventContext() override = default;
SCENE_CORE_API PostExportEventContext(ExportProductList& productList, const AZStd::string& outputDirectory, const char* platformIdentifier);
SCENE_CORE_API PostExportEventContext(ExportProductList& productList, AZStd::string&& outputDirectory, const char* platformIdentifier);
SCENE_CORE_API const AZStd::string GetOutputDirectory() const;
SCENE_CORE_API ExportProductList& GetProductList();
SCENE_CORE_API const ExportProductList& GetProductList() const;
SCENE_CORE_API const char* GetPlatformIdentifier() const;
private:
AZStd::string m_outputDirectory;
/**
* The platform identifier is configured in the AssetProcessorPlatformConfig.ini and is data driven
* it is generally a value like "pc" or "ios" or such.
* this const char* points at memory owned by the caller but it will always survive for the duration of the call.
*/
const char* m_platformIdentifier = nullptr;
ExportProductList& m_productList;
};
} // namespace Events
} // namespace SceneAPI
} // namespace AZ
@@ -0,0 +1,94 @@
/*
* 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/Events/ExportProductList.h>
namespace AZ
{
namespace SceneAPI
{
namespace Events
{
ExportProduct::ExportProduct(const AZStd::string& filename, Uuid id, Data::AssetType assetType, AZStd::optional<u8> lod, AZStd::optional<u32> subId,
Data::ProductDependencyInfo::ProductDependencyFlags dependencyFlags)
:ExportProduct(AZStd::string(filename), id, assetType, lod, subId, dependencyFlags)
{
}
ExportProduct::ExportProduct(AZStd::string&& filename, Uuid id, Data::AssetType assetType, AZStd::optional<u8> lod, AZStd::optional<u32> subId,
Data::ProductDependencyInfo::ProductDependencyFlags dependencyFlags)
: m_filename(AZStd::move(filename))
, m_id(id)
, m_assetType(assetType)
, m_lod(lod)
, m_subId(subId)
, m_dependencyFlags(dependencyFlags)
{
}
ExportProduct::ExportProduct(ExportProduct&& rhs)
{
*this = AZStd::move(rhs);
}
ExportProduct& ExportProduct::operator=(ExportProduct&& rhs)
{
m_legacyFileNames = AZStd::move(rhs.m_legacyFileNames);
m_filename = AZStd::move(rhs.m_filename);
m_id = rhs.m_id;
m_assetType = rhs.m_assetType;
m_lod = rhs.m_lod;
m_subId = rhs.m_subId;
m_dependencyFlags = rhs.m_dependencyFlags;
m_legacyPathDependencies = rhs.m_legacyPathDependencies;
m_productDependencies = rhs.m_productDependencies;
return *this;
}
ExportProduct& ExportProductList::AddProduct(const AZStd::string& filename, Uuid id, Data::AssetType assetType, AZStd::optional<u8> lod, AZStd::optional<u32> subId,
Data::ProductDependencyInfo::ProductDependencyFlags dependencyFlags)
{
return AddProduct(AZStd::string(filename), id, assetType, lod, subId, dependencyFlags);
}
ExportProduct& ExportProductList::AddProduct(AZStd::string&& filename, Uuid id, Data::AssetType assetType, AZStd::optional<u8> lod, AZStd::optional<u32> subId,
Data::ProductDependencyInfo::ProductDependencyFlags dependencyFlags)
{
AZ_Assert(!filename.empty(), "A filename is required to register a product.");
AZ_Assert(!id.IsNull(), "Provided guid is not valid");
AZ_Assert(!lod.has_value() || lod < 16, "Lod value has to be between 0 and 15 or disabled.");
size_t index = m_products.size();
m_products.emplace_back(AZStd::move(filename), id, assetType, lod, subId, dependencyFlags);
return m_products[index];
}
const AZStd::vector<ExportProduct>& ExportProductList::GetProducts() const
{
return m_products;
}
void ExportProductList::AddDependencyToProduct(const AZStd::string& productName, ExportProduct& dependency)
{
for (ExportProduct& product : m_products)
{
if (product.m_filename == productName)
{
product.m_productDependencies.push_back(dependency);
break;
}
}
}
} // namespace Events
} // namespace SceneAPI
} // namespace AZ
@@ -0,0 +1,76 @@
/*
* 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/base.h>
#include <AzCore/Asset/AssetCommon.h>
#include <AzCore/Math/Uuid.h>
#include <SceneAPI/SceneCore/SceneCoreConfiguration.h>
namespace AZ
{
namespace SceneAPI
{
namespace Events
{
struct ExportProduct
{
SCENE_CORE_API ExportProduct(const AZStd::string& filename, Uuid id, Data::AssetType assetType, AZStd::optional<u8> lod, AZStd::optional<u32> subId,
Data::ProductDependencyInfo::ProductDependencyFlags dependencyFlags = Data::ProductDependencyInfo::CreateFlags(Data::AssetLoadBehavior::NoLoad));
SCENE_CORE_API ExportProduct(AZStd::string&& filename, Uuid id, Data::AssetType assetType, AZStd::optional<u8> lod, AZStd::optional<u32> subId,
Data::ProductDependencyInfo::ProductDependencyFlags dependencyFlags = Data::ProductDependencyInfo::CreateFlags(Data::AssetLoadBehavior::NoLoad));
ExportProduct(const ExportProduct& rhs) = default;
SCENE_CORE_API ExportProduct(ExportProduct&& rhs);
ExportProduct& operator=(const ExportProduct& rhs) = default;
SCENE_CORE_API ExportProduct& operator=(ExportProduct&& rhs);
//! Other names the product file may be known as in the past. This is only backwards compatibility in ResourceCompilerScene.
AZStd::vector<AZStd::string> m_legacyFileNames;
//! Relative or absolute path of the product file.
AZStd::string m_filename;
//! Unique id for the product file. This is usually based on the group id and is used to generate the
//! the sub id.
Uuid m_id;
//! Type of the product file.
Data::AssetType m_assetType;
AZStd::optional<u32> m_subId;
//! If the product makes use of level of detail, the level is encoded in the sub id. Otherwise the entire sub id number will be used for the product id.
AZStd::optional<u8> m_lod;
//! Save off any product dependency flags that are detected for any serialized dependencies.
Data::ProductDependencyInfo::ProductDependencyFlags m_dependencyFlags;
//! Relative path dependencies for autogenerated FBX materials
AZStd::vector<AZStd::string> m_legacyPathDependencies;
//! In the case of CGFs, we will have LOD export products that are dependencies of the base LOD
AZStd::vector<ExportProduct> m_productDependencies;
};
class ExportProductList
{
public:
SCENE_CORE_API ExportProduct& AddProduct(const AZStd::string& filename, Uuid id, Data::AssetType assetType, AZStd::optional<u8> lod, AZStd::optional<u32> subId,
Data::ProductDependencyInfo::ProductDependencyFlags dependencyFlags = Data::ProductDependencyInfo::CreateFlags(Data::AssetLoadBehavior::NoLoad));
SCENE_CORE_API ExportProduct& AddProduct(AZStd::string&& filename, Uuid id, Data::AssetType assetType, AZStd::optional<u8> lod, AZStd::optional<u32> subId,
Data::ProductDependencyInfo::ProductDependencyFlags dependencyFlags = Data::ProductDependencyInfo::CreateFlags(Data::AssetLoadBehavior::NoLoad));
SCENE_CORE_API const AZStd::vector<ExportProduct>& GetProducts() const;
SCENE_CORE_API void AddDependencyToProduct(const AZStd::string& productName, ExportProduct& dependency);
private:
AZStd::vector<ExportProduct> m_products;
};
} // namespace Events
} // namespace SceneAPI
} // namespace AZ
@@ -0,0 +1,76 @@
/*
* 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/Events/GenerateEventContext.h>
namespace AZ::SceneAPI::Events
{
/////////////
// PreGenerateEventContext
/////////////
PreGenerateEventContext::PreGenerateEventContext(Containers::Scene& scene, const char* platformIdentifier)
: m_scene(scene)
, m_platformIdentifier(platformIdentifier)
{
}
Containers::Scene& PreGenerateEventContext::GetScene() const
{
return m_scene;
}
const char* PreGenerateEventContext::GetPlatformIdentifier() const
{
return m_platformIdentifier;
}
/////////////
// GenerateEventContext
/////////////
GenerateEventContext::GenerateEventContext(Containers::Scene& scene, const char* platformIdentifier)
: m_scene(scene)
, m_platformIdentifier(platformIdentifier)
{
}
Containers::Scene& GenerateEventContext::GetScene() const
{
return m_scene;
}
const char* GenerateEventContext::GetPlatformIdentifier() const
{
return m_platformIdentifier;
}
/////////////
// PostGenerateEventContext
/////////////
PostGenerateEventContext::PostGenerateEventContext(Containers::Scene& scene, const char* platformIdentifier)
: m_scene(scene)
, m_platformIdentifier(platformIdentifier)
{
}
Containers::Scene& PostGenerateEventContext::GetScene() const
{
return m_scene;
}
const char* PostGenerateEventContext::GetPlatformIdentifier() const
{
return m_platformIdentifier;
}
} // namespace AZ::SceneAPI::Events
@@ -0,0 +1,94 @@
/*
* 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/RTTI/RTTI.h>
#include <AzCore/std/string/string.h>
#include <SceneAPI/SceneCore/Events/CallProcessorBus.h>
#include <SceneAPI/SceneCore/SceneCoreConfiguration.h>
namespace AZ::SceneAPI::Containers { class Scene; }
namespace AZ::SceneAPI::DataTypes { class IGroup; }
namespace AZ::SceneAPI::Events
{
class ExportProductList;
// Signals the scene generation step is about to happen
class PreGenerateEventContext
: public ICallContext
{
public:
AZ_RTTI(PreGenerateEventContext, "{0D1AB113-D35E-4C35-9820-E7B22F37D90C}", ICallContext)
SCENE_CORE_API PreGenerateEventContext(Containers::Scene& scene, const char* platformIdentifier);
SCENE_CORE_API Containers::Scene& GetScene() const;
SCENE_CORE_API const char* GetPlatformIdentifier() const;
private:
Containers::Scene& m_scene;
/**
* The platform identifier is configured in the AssetProcessorPlatformConfig.ini and is data driven
* it is generally a value like "pc" or "ios" or such.
* this const char* points at memory owned by the caller but it will always survive for the duration of the call.
*/
const char* m_platformIdentifier = nullptr;
};
// Signals that all appropriate objects should be generated into the Scene
class GenerateEventContext
: public ICallContext
{
public:
AZ_RTTI(GenerateEventContext, "{B53CCBBF-965A-4709-AD33-AFD5F3AE8580}", ICallContext)
SCENE_CORE_API GenerateEventContext(Containers::Scene& scene, const char* platformIdentifier);
SCENE_CORE_API Containers::Scene& GetScene() const;
SCENE_CORE_API const char* GetPlatformIdentifier() const;
private:
Containers::Scene& m_scene;
/**
* The platform identifier is configured in the AssetProcessorPlatformConfig.ini and is data driven
* it is generally a value like "pc" or "ios" or such.
* this const char* points at memory owned by the caller but it will always survive for the duration of the call.
*/
const char* m_platformIdentifier = nullptr;
};
// Signals that the generation step is complete
class PostGenerateEventContext
: public ICallContext
{
public:
AZ_RTTI(PostGenerateEventContext, "{3EE65CBF-6C0E-425A-9ECC-3CC8FC4372F7}", ICallContext)
SCENE_CORE_API PostGenerateEventContext(Containers::Scene& scene, const char* platformIdentifier);
SCENE_CORE_API Containers::Scene& GetScene() const;
SCENE_CORE_API const char* GetPlatformIdentifier() const;
private:
Containers::Scene& m_scene;
/**
* The platform identifier is configured in the AssetProcessorPlatformConfig.ini and is data driven
* it is generally a value like "pc" or "ios" or such.
* this const char* points at memory owned by the caller but it will always survive for the duration of the call.
*/
const char* m_platformIdentifier = nullptr;
};
} // namespace AZ::SceneAPI::Events
@@ -0,0 +1,79 @@
#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/EBus/EBus.h>
#include <AzCore/Math/Crc.h>
#include <AzCore/std/string/string.h>
#include <AzCore/std/containers/set.h>
#include <SceneAPI/SceneCore/Containers/SceneGraph.h>
#include <SceneAPI/SceneCore/SceneCoreConfiguration.h>
namespace AZ
{
namespace SceneAPI
{
namespace Containers
{
class Scene;
}
namespace DataTypes
{
class IGraphObject;
}
namespace Events
{
#if defined(AZ_PLATFORM_LINUX)
class SCENE_CORE_API GraphMetaInfo
#else
class GraphMetaInfo
#endif
: public AZ::EBusTraits
{
public:
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple;
inline static Crc32 GetIgnoreVirtualType()
{
static Crc32 s_ignoreVirtualType = AZ_CRC("Ignore", 0x0d88d6e2);
return s_ignoreVirtualType;
}
SCENE_CORE_API GraphMetaInfo() = default;
virtual ~GraphMetaInfo() = default;
// Gets the path to the icon associated with the given object.
SCENE_CORE_API virtual void GetIconPath([[maybe_unused]] AZStd::string& iconPath, [[maybe_unused]] const DataTypes::IGraphObject* target) {}
// Provides a short description of the type.
SCENE_CORE_API virtual void GetToolTip([[maybe_unused]] AZStd::string& toolTip, [[maybe_unused]] const DataTypes::IGraphObject* target) {}
// Provides a list of string CRCs that indicate the virtual type the given node can act as.
// Virtual types are none custom types that are different interpretations of existing types based on
// their name or attributes.
SCENE_CORE_API virtual void GetVirtualTypes([[maybe_unused]] AZStd::set<Crc32>& types,
[[maybe_unused]] const Containers::Scene& scene,
[[maybe_unused]] Containers::SceneGraph::NodeIndex node) {}
// Provides a list of string CRCs that indicate all available virtual types.
SCENE_CORE_API virtual void GetAllVirtualTypes([[maybe_unused]] AZStd::set<Crc32>& types) {}
// Converts the virtual type hashed name into a readable name.
SCENE_CORE_API virtual void GetVirtualTypeName([[maybe_unused]] AZStd::string& name, [[maybe_unused]] Crc32 type) {}
};
using GraphMetaInfoBus = AZ::EBus<GraphMetaInfo>;
} // Events
} // SceneAPI
} // AZ

Some files were not shown because too many files have changed in this diff Show More