Files
o3de/Gems/LmbrCentral/Code/Source/Shape/SplineComponent.cpp
Esteban Papp 1f9b284de2 Merge branch 'development' into cmake/SPEC-7179
Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>

# Conflicts:
#	Code/Editor/Plugins/ComponentEntityEditorPlugin/ComponentEntityEditorPlugin_precompiled.h
#	Code/Editor/Plugins/EditorCommon/EditorCommon_precompiled.h
#	Code/Editor/Plugins/EditorCommon/stdafx.cpp
#	Code/Editor/Plugins/FFMPEGPlugin/FFMPEGPlugin_precompiled.h
#	Code/Editor/Plugins/PerforcePlugin/PerforcePlugin_precompiled.h
#	Code/Editor/Plugins/ProjectSettingsTool/ProjectSettingsTool_precompiled.h
#	Code/Framework/AzToolsFramework/AzToolsFramework/AzToolsFramework_precompiled.h
#	Code/Tools/AssetProcessor/native/precompiled.h
#	Code/Tools/Standalone/StandaloneTools_precompiled.h
#	Gems/AssetMemoryAnalyzer/Code/Source/AssetMemoryAnalyzer_precompiled.h
#	Gems/Atom/Asset/ImageProcessingAtom/Code/Source/ImageProcessing_precompiled.h
#	Gems/Atom/RHI/DX12/Code/Source/RHI/Atom_RHI_DX12_precompiled.h
#	Gems/Atom/RHI/Metal/Code/Include/Platform/Mac/Atom_RHI_Metal_precompiled_Platform.h
#	Gems/Atom/RHI/Metal/Code/Include/Platform/iOS/Atom_RHI_Metal_precompiled_Platform.h
#	Gems/Atom/RHI/Metal/Code/Source/Atom_RHI_Metal_precompiled.h
#	Gems/Atom/RHI/Metal/Code/atom_rhi_metal_common_files.cmake
#	Gems/Atom/RHI/Null/Code/Source/Atom_RHI_Null_precompiled.h
#	Gems/Atom/RHI/Null/Code/atom_rhi_null_common_files.cmake
#	Gems/Atom/RHI/Vulkan/Code/Include/Platform/Android/Atom_RHI_Vulkan_precompiled_Platform.h
#	Gems/Atom/RHI/Vulkan/Code/Include/Platform/Linux/Atom_RHI_Vulkan_precompiled_Platform.h
#	Gems/Atom/RHI/Vulkan/Code/Include/Platform/Mac/Atom_RHI_Vulkan_precompiled_Platform.h
#	Gems/Atom/RHI/Vulkan/Code/Include/Platform/Windows/Atom_RHI_Vulkan_precompiled_Platform.h
#	Gems/Atom/RHI/Vulkan/Code/Source/Atom_RHI_Vulkan_precompiled.h
#	Gems/Atom/RHI/Vulkan/Code/Source/RHI/SwapChain.cpp
#	Gems/Atom/RHI/Vulkan/Code/atom_rhi_vulkan_common_files.cmake
#	Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/AtomFont_precompiled.h
#	Gems/Blast/Code/Source/StdAfx.cpp
#	Gems/Camera/Code/Source/Camera_precompiled.h
#	Gems/EMotionFX/Code/Source/EMotionFX_precompiled.h
#	Gems/FastNoise/Code/Source/FastNoise_precompiled.h
#	Gems/Gestures/Code/Source/Gestures_precompiled.h
#	Gems/GradientSignal/Code/Source/GradientSignal_precompiled.h
#	Gems/GraphCanvas/Code/precompiled.h
#	Gems/ImGui/Code/Source/ImGui_precompiled.h
#	Gems/InAppPurchases/Code/Source/InAppPurchases_precompiled.h
#	Gems/LmbrCentral/Code/Source/LmbrCentral_precompiled.h
#	Gems/LmbrCentral/Code/Tests/ShapeGeometryUtilTest.cpp
#	Gems/LyShine/Code/Editor/UiCanvasEditor_precompiled.h
#	Gems/LyShine/Code/Source/Animation/LyShine_precompiled.h
#	Gems/LyShine/Code/Source/LyShine_precompiled.h
#	Gems/LyShineExamples/Code/Source/LyShineExamples_precompiled.h
#	Gems/Maestro/Code/Source/Cinematics/Maestro_precompiled.h
#	Gems/Maestro/Code/Source/Maestro_precompiled.h
#	Gems/MessagePopup/Code/Source/MessagePopup_precompiled.h
#	Gems/Metastream/Code/Source/Metastream_precompiled.h
#	Gems/Microphone/Code/Source/Microphone_precompiled.h
#	Gems/Multiplayer/Code/Source/Multiplayer_precompiled.h
#	Gems/PhysX/Code/NumericalMethods/Source/NumericalMethods_precompiled.h
#	Gems/PhysX/Code/Source/PhysXUnsupported_precompiled.h
#	Gems/PhysX/Code/Source/PhysX_precompiled.h
#	Gems/PhysX/Code/physx_unsupported_files.cmake
#	Gems/PhysXDebug/Code/Source/PhysXDebugUnsupported_precompiled.h
#	Gems/PhysXDebug/Code/Source/PhysXDebug_precompiled.h
#	Gems/ScriptCanvas/Code/Editor/precompiled.h
#	Gems/ScriptCanvas/Code/Source/precompiled.h
#	Gems/ScriptCanvasDeveloper/Code/Source/precompiled.h
#	Gems/ScriptCanvasPhysics/Code/Source/ScriptCanvasPhysics_precompiled.h
#	Gems/ScriptEvents/Code/Source/precompiled.h
#	Gems/ScriptEvents/Code/Tests/Editor/EditorTests.cpp
#	Gems/ScriptedEntityTweener/Code/Source/ScriptedEntityTweener_precompiled.h
#	Gems/SliceFavorites/Code/Source/SliceFavorites_precompiled.h
#	Gems/StartingPointCamera/Code/Source/StartingPointCamera_precompiled.h
#	Gems/StartingPointInput/Code/Source/StartingPointInput_precompiled.h
#	Gems/StartingPointMovement/Code/Source/StartingPointMovement_precompiled.h
#	Gems/SurfaceData/Code/Source/SurfaceData_precompiled.h
#	Gems/TextureAtlas/Code/Source/TextureAtlas_precompiled.h
#	Gems/TickBusOrderViewer/Code/Source/TickBusOrderViewer_precompiled.h
#	Gems/Twitch/Code/Source/Twitch_precompiled.h
#	Gems/VirtualGamepad/Code/Source/VirtualGamepad_precompiled.h
#	Gems/WhiteBox/Code/Source/WhiteBoxUnsupported_precompiled.h
#	Gems/WhiteBox/Code/Source/WhiteBox_precompiled.h
2021-07-16 15:42:37 -07:00

345 lines
12 KiB
C++

/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include "SplineComponent.h"
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/Serialization/EditContext.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/std/smart_ptr/make_shared.h>
namespace LmbrCentral
{
using SplineComboBoxVec = AZStd::vector<AZStd::pair<size_t, AZStd::string>>;
static SplineComboBoxVec PopulateSplineTypeList()
{
return SplineComboBoxVec
{
AZStd::make_pair(AZ::LinearSpline::RTTI_Type().GetHash(), "Linear"),
AZStd::make_pair(AZ::BezierSpline::RTTI_Type().GetHash(), "Bezier"),
AZStd::make_pair(AZ::CatmullRomSpline::RTTI_Type().GetHash(), "Catmull-Rom")
};
}
static AZ::SplinePtr MakeSplinePtr(AZ::u64 splineType)
{
if (splineType == AZ::LinearSpline::RTTI_Type().GetHash())
{
return AZStd::make_shared<AZ::LinearSpline>();
}
if (splineType == AZ::BezierSpline::RTTI_Type().GetHash())
{
return AZStd::make_shared<AZ::BezierSpline>();
}
if (splineType == AZ::CatmullRomSpline::RTTI_Type().GetHash())
{
return AZStd::make_shared<AZ::CatmullRomSpline>();
}
AZ_Assert(false, "Unhandled spline type %d in %s", splineType, __FUNCTION__);
return nullptr;
}
static AZ::SplinePtr CopySplinePtr(AZ::u64 splineType, const AZ::SplinePtr& spline)
{
if (splineType == AZ::LinearSpline::RTTI_Type().GetHash())
{
return AZStd::make_shared<AZ::LinearSpline>(*spline);
}
if (splineType == AZ::BezierSpline::RTTI_Type().GetHash())
{
return AZStd::make_shared<AZ::BezierSpline>(*spline);
}
if (splineType == AZ::CatmullRomSpline::RTTI_Type().GetHash())
{
return AZStd::make_shared<AZ::CatmullRomSpline>(*spline);
}
AZ_Assert(false, "Unhandled spline type %d in %s", splineType, __FUNCTION__);
return nullptr;
}
SplineCommon::SplineCommon()
{
m_spline = MakeSplinePtr(m_splineType);
}
void SplineCommon::Reflect(AZ::ReflectContext* context)
{
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<SplineCommon>()
->Version(1)
->Field("Spline Type", &SplineCommon::m_splineType)
->Field("Spline", &SplineCommon::m_spline);
if (AZ::EditContext* editContext = serializeContext->GetEditContext())
{
editContext->Class<SplineCommon>("Configuration", "Spline configuration parameters")
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
//->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly) // disabled - prevents ChangeNotify attribute firing correctly
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
->DataElement(AZ::Edit::UIHandlers::ComboBox, &SplineCommon::m_splineType, "Spline Type", "Interpolation type to use between vertices.")
->Attribute(AZ::Edit::Attributes::EnumValues, &PopulateSplineTypeList)
->Attribute(AZ::Edit::Attributes::ChangeNotify, &SplineCommon::OnChangeSplineType)
->DataElement(AZ::Edit::UIHandlers::Default, &SplineCommon::m_spline, "Spline", "Data representing the spline.")
//->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly) // disabled - prevents ChangeNotify attribute firing correctly
->Attribute(AZ::Edit::Attributes::ContainerCanBeModified, false)
->Attribute(AZ::Edit::Attributes::AutoExpand, true);
}
}
}
void SplineCommon::ChangeSplineType(AZ::u64 splineType)
{
m_splineType = splineType;
OnChangeSplineType();
}
void SplineCommon::SetCallbacks(
const AZ::IndexFunction& OnAddVertex, const AZ::IndexFunction& OnRemoveVertex,
const AZ::IndexFunction& OnUpdateVertex, const AZ::VoidFunction& OnSetVertices,
const AZ::VoidFunction& OnClearVertices, const AZ::VoidFunction& OnChangeType,
const AZ::BoolFunction& OnOpenClose)
{
m_onAddVertex = OnAddVertex;
m_onRemoveVertex = OnRemoveVertex;
m_onUpdateVertex = OnUpdateVertex;
m_onSetVertices = OnSetVertices;
m_onClearVertices = OnClearVertices;
m_onChangeType = OnChangeType;
m_onOpenCloseChange = OnOpenClose;
m_spline->SetCallbacks(
OnAddVertex, OnRemoveVertex,
OnUpdateVertex, OnSetVertices,
OnClearVertices, OnOpenClose);
}
AZ::u32 SplineCommon::OnChangeSplineType()
{
AZ::u32 ret = AZ::Edit::PropertyRefreshLevels::None;
if (m_spline->RTTI_GetType().GetHash() != m_splineType)
{
m_spline = CopySplinePtr(m_splineType, m_spline);
m_spline->SetCallbacks(
m_onAddVertex, m_onRemoveVertex, m_onUpdateVertex,
m_onSetVertices, m_onClearVertices, m_onOpenCloseChange);
ret = AZ::Edit::PropertyRefreshLevels::EntireTree;
if (m_onChangeType)
{
m_onChangeType();
}
}
return ret;
}
/// BehaviorContext forwarder for SplineComponentNotificationBus
class BehaviorSplineComponentNotificationBusHandler
: public SplineComponentNotificationBus::Handler
, public AZ::BehaviorEBusHandler
{
public:
AZ_EBUS_BEHAVIOR_BINDER(BehaviorSplineComponentNotificationBusHandler, "{05816EA4-A4F0-4FB4-A82B-D6537B215D25}", AZ::SystemAllocator, OnSplineChanged);
void OnSplineChanged() override
{
Call(FN_OnSplineChanged);
}
};
void SplineComponent::Reflect(AZ::ReflectContext* context)
{
SplineCommon::Reflect(context);
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<SplineComponent, AZ::Component>()
->Version(1)
->Field("Configuration", &SplineComponent::m_splineCommon);
}
if (auto behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
{
behaviorContext->EBus<SplineComponentNotificationBus>("SplineComponentNotificationBus")->
Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::All)->
Handler<BehaviorSplineComponentNotificationBusHandler>();
behaviorContext->EBus<SplineComponentRequestBus>("SplineComponentRequestBus")
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation)
->Attribute(AZ::Edit::Attributes::Category, "Shape")
->Attribute(AZ::Script::Attributes::Module, "shape")
->Event("GetSpline", &SplineComponentRequestBus::Events::GetSpline)
->Event("SetClosed", &SplineComponentRequestBus::Events::SetClosed)
->Event("AddVertex", &SplineComponentRequestBus::Events::AddVertex)
->Event("UpdateVertex", &SplineComponentRequestBus::Events::UpdateVertex)
->Event("InsertVertex", &SplineComponentRequestBus::Events::InsertVertex)
->Event("RemoveVertex", &SplineComponentRequestBus::Events::RemoveVertex)
->Event("ClearVertices", &SplineComponentRequestBus::Events::ClearVertices);
}
}
void SplineComponent::Activate()
{
m_currentTransform = AZ::Transform::CreateIdentity();
AZ::TransformBus::EventResult(m_currentTransform, GetEntityId(), &AZ::TransformBus::Events::GetWorldTM);
AZ::TransformNotificationBus::Handler::BusConnect(GetEntityId());
SplineComponentRequestBus::Handler::BusConnect(GetEntityId());
const auto splineChanged = [this]()
{
SplineComponentNotificationBus::Event(
GetEntityId(), &SplineComponentNotificationBus::Events::OnSplineChanged);
};
const auto vertexAdded = [this, splineChanged](size_t index)
{
SplineComponentNotificationBus::Event(
GetEntityId(), &SplineComponentNotificationBus::Events::OnVertexAdded, index);
splineChanged();
};
const auto vertexRemoved = [this, splineChanged](size_t index)
{
SplineComponentNotificationBus::Event(
GetEntityId(), &SplineComponentNotificationBus::Events::OnVertexRemoved, index);
splineChanged();
};
const auto vertexUpdated = [this, splineChanged](size_t index)
{
SplineComponentNotificationBus::Event(
GetEntityId(), &SplineComponentNotificationBus::Events::OnVertexUpdated, index);
splineChanged();
};
const auto verticesSet = [this, splineChanged]()
{
SplineComponentNotificationBus::Event(
GetEntityId(),
&SplineComponentNotificationBus::Events::OnVerticesSet,
m_splineCommon.m_spline->GetVertices()
);
splineChanged();
};
const auto verticesCleared = [this, splineChanged]()
{
SplineComponentNotificationBus::Event(
GetEntityId(), &SplineComponentNotificationBus::Events::OnVerticesCleared);
splineChanged();
};
const auto openCloseChanged = [this, splineChanged](const bool closed)
{
SplineComponentNotificationBus::Event(
GetEntityId(), &SplineComponentNotificationBus::Events::OnOpenCloseChanged, closed);
splineChanged();
};
m_splineCommon.SetCallbacks(
vertexAdded,
vertexRemoved,
vertexUpdated,
verticesSet,
verticesCleared,
splineChanged,
openCloseChanged);
}
void SplineComponent::Deactivate()
{
SplineComponentRequestBus::Handler::BusDisconnect();
AZ::TransformNotificationBus::Handler::BusDisconnect();
}
void SplineComponent::OnTransformChanged(const AZ::Transform& /*local*/, const AZ::Transform& world)
{
m_currentTransform = world;
}
AZ::SplinePtr SplineComponent::GetSpline()
{
return m_splineCommon.m_spline;
}
void SplineComponent::ChangeSplineType(AZ::u64 splineType)
{
m_splineCommon.ChangeSplineType(splineType);
}
bool SplineComponent::UpdateVertex(size_t index, const AZ::Vector3& vertex)
{
return m_splineCommon.m_spline->m_vertexContainer.UpdateVertex(index, vertex);
}
bool SplineComponent::GetVertex(size_t index, AZ::Vector3& vertex) const
{
return m_splineCommon.m_spline->m_vertexContainer.GetVertex(index, vertex);
}
void SplineComponent::AddVertex(const AZ::Vector3& vertex)
{
m_splineCommon.m_spline->m_vertexContainer.AddVertex(vertex);
}
bool SplineComponent::InsertVertex(size_t index, const AZ::Vector3& vertex)
{
return m_splineCommon.m_spline->m_vertexContainer.InsertVertex(index, vertex);
}
bool SplineComponent::RemoveVertex(size_t index)
{
return m_splineCommon.m_spline->m_vertexContainer.RemoveVertex(index);
}
void SplineComponent::SetVertices(const AZStd::vector<AZ::Vector3>& vertices)
{
m_splineCommon.m_spline->m_vertexContainer.SetVertices(vertices);
}
void SplineComponent::ClearVertices()
{
m_splineCommon.m_spline->m_vertexContainer.Clear();
}
bool SplineComponent::Empty() const
{
return m_splineCommon.m_spline->m_vertexContainer.Empty();
}
size_t SplineComponent::Size() const
{
return m_splineCommon.m_spline->m_vertexContainer.Size();
}
void SplineComponent::SetClosed(const bool closed)
{
// set closed callback calls OnSplineChanged
m_splineCommon.m_spline->SetClosed(closed);
}
} // namespace LmbrCentral