Files
o3de/Gems/GradientSignal/Code/Include/GradientSignal/Editor/EditorGradientComponentBase.inl
T
Steve Pham 38261d0800 Shorten copyright headers by splitting into 2 lines (#2213)
* Updated all copyright headers to split the longer original copyright line into 2 shorter lines

Signed-off-by: Steve Pham <spham@amazon.com>
2021-07-16 15:25:48 -07:00

274 lines
13 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
*
*/
#pragma once
namespace GradientSignal
{
template <typename TComponent, typename TConfiguration>
bool EditorGradientComponentBase<TComponent, TConfiguration>::VersionConverter(AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement)
{
// Changed EditorGradientComponentBase to inherit from EditorWrappedComponentBase
if (classElement.GetVersion() < 1)
{
TConfiguration configData;
AzToolsFramework::Components::EditorComponentBase editorComponentBaseData;
classElement.FindSubElementAndGetData(AZ_CRC("Configuration", 0xa5e2a5d7), configData);
classElement.FindSubElementAndGetData(AZ_CRC("BaseClass1", 0xd4925735), editorComponentBaseData);
classElement.RemoveElementByName(AZ_CRC("Configuration", 0xa5e2a5d7));
classElement.RemoveElementByName(AZ_CRC("BaseClass1", 0xd4925735));
BaseClassType wrappedComponentBaseInstance;
int baseIndex = classElement.AddElementWithData(context, "BaseClass1", wrappedComponentBaseInstance);
auto& wrappedComponentBaseElement = classElement.GetSubElement(baseIndex);
auto* editorComponentBaseElement = wrappedComponentBaseElement.FindSubElement(AZ_CRC("BaseClass1", 0xd4925735));
auto* configurationElement = wrappedComponentBaseElement.FindSubElement(AZ_CRC("Configuration", 0xa5e2a5d7));
editorComponentBaseElement->SetData(context, editorComponentBaseData);
configurationElement->SetData(context, configData);
return true;
}
return true;
}
template <typename TComponent, typename TConfiguration>
void EditorGradientComponentBase<TComponent, TConfiguration>::Reflect(AZ::ReflectContext* context)
{
BaseClassType::Reflect(context);
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<EditorGradientComponentBase, BaseClassType>()
->Version(1, &EditorGradientComponentBase::VersionConverter)
->Field("PreviewEntity", &EditorGradientComponentBase::m_previewEntityId)
->Field("PreviewPosition", &EditorGradientComponentBase::m_previewPosition)
->Field("PreviewSize", &EditorGradientComponentBase::m_previewSize)
->Field("ConstrainToShape", &EditorGradientComponentBase::m_constrainToShape);
if (auto editContext = serializeContext->GetEditContext())
{
editContext->Class<EditorGradientComponentBase>("GradientComponentBase", "")
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
->ClassElement(AZ::Edit::ClassElements::Group, "Preview")
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::Show)
->UIElement(AZ_CRC("GradientPreviewer", 0x1dbbba45), "Previewer")
->Attribute(AZ::Edit::Attributes::NameLabelOverride, "")
->Attribute(AZ_CRC("GradientEntity", 0xe8531817), &EditorGradientComponentBase::GetGradientEntityId)
->ClassElement(AZ::Edit::ClassElements::Group, "Preview Settings")
->DataElement(0, &EditorGradientComponentBase::m_previewEntityId, "Pin Preview to Shape", "The entity whose shape represents the bounds to render the gradient preview")
->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorGradientComponentBase::PreviewSettingsAndSettingsVisibilityChanged)
->DataElement(0, &EditorGradientComponentBase::m_previewPosition, "Preview Position", "Center of the preview bounds")
->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorGradientComponentBase::UpdatePreviewSettings)
->Attribute(AZ::Edit::Attributes::Visibility, &EditorGradientComponentBase::GetPreviewPositionVisibility)
->DataElement(0, &EditorGradientComponentBase::m_previewSize, "Preview Size", "Size of the preview bounds")
->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorGradientComponentBase::UpdatePreviewSettings)
->Attribute(AZ::Edit::Attributes::Visibility, &EditorGradientComponentBase::GetPreviewSizeVisibility)
->DataElement(0, &EditorGradientComponentBase::m_constrainToShape, "Constrain to Shape", "If checked, only renders the parts of the gradient inside the component's shape and not its entire bounding box")
->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorGradientComponentBase::UpdatePreviewSettings)
->Attribute(AZ::Edit::Attributes::Visibility, &EditorGradientComponentBase::GetPreviewConstrainToShapeVisibility)
;
}
}
}
template <typename TComponent, typename TConfiguration>
void EditorGradientComponentBase<TComponent, TConfiguration>::Activate()
{
m_gradientEntityId = GetEntityId();
LmbrCentral::DependencyNotificationBus::Handler::BusConnect(GetEntityId());
AzToolsFramework::EntitySelectionEvents::Bus::Handler::BusConnect(GetEntityId());
GradientPreviewContextRequestBus::Handler::BusConnect(GetEntityId());
SetSamplerOwnerEntity(m_configuration, GetEntityId());
// Validation needs to happen after the ownerEntity is set in case the validation needs that data
if (!ValidateGradientEntityIds(m_configuration))
{
SetDirty();
}
BaseClassType::Activate();
if (!m_previewEntityId.IsValid())
{
// Default our preview entity to this entity
m_previewEntityId = GetEntityId();
SetDirty();
}
UpdatePreviewSettings();
}
template <typename TComponent, typename TConfiguration>
void EditorGradientComponentBase<TComponent, TConfiguration>::Deactivate()
{
// If the preview shouldn't be active, use an invalid entityId
m_gradientEntityId = AZ::EntityId();
AzToolsFramework::EntitySelectionEvents::Bus::Handler::BusDisconnect();
GradientPreviewContextRequestBus::Handler::BusDisconnect();
AzToolsFramework::Components::EditorComponentBase::Deactivate();
LmbrCentral::DependencyNotificationBus::Handler::BusDisconnect();
BaseClassType::Deactivate();
}
template<typename TComponent, typename TConfiguration>
void GradientSignal::EditorGradientComponentBase<TComponent, TConfiguration>::OnCompositionChanged()
{
UpdatePreviewSettings();
}
template <typename TComponent, typename TConfiguration>
AZ::u32 EditorGradientComponentBase<TComponent, TConfiguration>::ConfigurationChanged()
{
// Cancel any pending preview refreshes before locking, to help ensure the preview itself isn't holding the lock
auto entityIds = CancelPreviewRendering();
// block anyone from accessing the buses while the editor deactivates and re-activates the contained component.
auto& surfaceDataSystemRequestBusContext = SurfaceData::SurfaceDataSystemRequestBus::GetOrCreateContext(false);
auto& gradientRequestBusContextContext = GradientRequestBus::GetOrCreateContext(false);
AZStd::scoped_lock< decltype(surfaceDataSystemRequestBusContext.m_contextMutex),
decltype(gradientRequestBusContextContext.m_contextMutex)
>
scopeLock( surfaceDataSystemRequestBusContext.m_contextMutex,
gradientRequestBusContextContext.m_contextMutex);
auto refreshResult = BaseClassType::ConfigurationChanged();
// Refresh any of the previews that we cancelled that were still in progress so they can be completed
for (auto entityId : entityIds)
{
GradientSignal::GradientPreviewRequestBus::Event(entityId, &GradientSignal::GradientPreviewRequestBus::Events::Refresh);
}
// This OnCompositionChanged notification will refresh our own preview so we don't need to call UpdatePreviewSettings explicitly
LmbrCentral::DependencyNotificationBus::Event(GetEntityId(), &LmbrCentral::DependencyNotificationBus::Events::OnCompositionChanged);
return refreshResult;
}
template <typename TComponent, typename TConfiguration>
AZ::EntityId EditorGradientComponentBase<TComponent, TConfiguration>::GetPreviewEntity() const
{
return m_previewEntityId;
}
template <typename TComponent, typename TConfiguration>
AZ::Aabb EditorGradientComponentBase<TComponent, TConfiguration>::GetPreviewBounds() const
{
AZ::Vector3 position = m_previewPosition;
//if a shape entity was supplied, attempt to use its shape bounds or position
if (m_previewEntityId.IsValid())
{
AZ::Aabb bounds = AZ::Aabb::CreateNull();
LmbrCentral::ShapeComponentRequestsBus::EventResult(bounds, m_previewEntityId, &LmbrCentral::ShapeComponentRequestsBus::Events::GetEncompassingAabb);
if (bounds.IsValid())
{
return bounds;
}
AZ::TransformBus::EventResult(position, m_previewEntityId, &AZ::TransformBus::Events::GetWorldTranslation);
}
return AZ::Aabb::CreateCenterHalfExtents(position, m_previewSize / 2.0f);
}
template <typename TComponent, typename TConfiguration>
bool EditorGradientComponentBase<TComponent, TConfiguration>::GetConstrainToShape() const
{
return m_constrainToShape && m_previewEntityId.IsValid();
}
template <typename TComponent, typename TConfiguration>
void EditorGradientComponentBase<TComponent, TConfiguration>::OnSelected()
{
UpdatePreviewSettings();
}
template <typename TComponent, typename TConfiguration>
void EditorGradientComponentBase<TComponent, TConfiguration>::OnDeselected()
{
UpdatePreviewSettings();
}
template <typename TComponent, typename TConfiguration>
AZ::u32 EditorGradientComponentBase<TComponent, TConfiguration>::GetPreviewPositionVisibility() const
{
return m_previewEntityId.IsValid() ? AZ::Edit::PropertyVisibility::Hide : AZ::Edit::PropertyVisibility::Show;
}
template <typename TComponent, typename TConfiguration>
AZ::u32 EditorGradientComponentBase<TComponent, TConfiguration>::GetPreviewSizeVisibility() const
{
if (m_previewEntityId.IsValid())
{
AZ::Aabb bounds = AZ::Aabb::CreateNull();
LmbrCentral::ShapeComponentRequestsBus::EventResult(bounds, m_previewEntityId, &LmbrCentral::ShapeComponentRequestsBus::Events::GetEncompassingAabb);
if (bounds.IsValid())
{
return AZ::Edit::PropertyVisibility::Hide;
}
}
return AZ::Edit::PropertyVisibility::Show;
}
template <typename TComponent, typename TConfiguration>
AZ::u32 EditorGradientComponentBase<TComponent, TConfiguration>::GetPreviewConstrainToShapeVisibility() const
{
return m_previewEntityId.IsValid() ? AZ::Edit::PropertyVisibility::Show : AZ::Edit::PropertyVisibility::Hide;
}
template <typename TComponent, typename TConfiguration>
AZ::u32 EditorGradientComponentBase<TComponent, TConfiguration>::PreviewSettingsAndSettingsVisibilityChanged() const
{
UpdatePreviewSettings();
// We've changed the visibility of one or more properties, so refresh the entire component.
return AZ::Edit::PropertyRefreshLevels::EntireTree;
}
template <typename TComponent, typename TConfiguration>
void EditorGradientComponentBase<TComponent, TConfiguration>::UpdatePreviewSettings() const
{
// Trigger an update just for our specific preview (this means there was a preview-specific change, not an actual configuration change)
GradientSignal::GradientPreviewRequestBus::Event(m_gradientEntityId, &GradientSignal::GradientPreviewRequestBus::Events::Refresh);
}
template <typename TComponent, typename TConfiguration>
AzToolsFramework::EntityIdList EditorGradientComponentBase<TComponent, TConfiguration>::CancelPreviewRendering() const
{
AzToolsFramework::EntityIdList entityIds;
AZ::EBusAggregateResults<AZ::EntityId> cancelledPreviews;
GradientSignal::GradientPreviewRequestBus::BroadcastResult(cancelledPreviews, &GradientSignal::GradientPreviewRequestBus::Events::CancelRefresh);
// Gather up the EntityIds for any previews that were in progress when we cancelled them
for (auto entityId : cancelledPreviews.values)
{
if (entityId.IsValid())
{
entityIds.push_back(entityId);
}
}
return entityIds;
}
template <typename TComponent, typename TConfiguration>
AZ::EntityId EditorGradientComponentBase<TComponent, TConfiguration>::GetGradientEntityId() const
{
return m_gradientEntityId;
}
}