You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
374 lines
14 KiB
C++
374 lines
14 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 <AzCore/Serialization/EditContext.h>
|
|
#include <AzCore/Component/ComponentApplicationBus.h>
|
|
#include <AzCore/Component/ComponentExport.h>
|
|
#include <AzCore/Slice/SliceComponent.h>
|
|
#include <AzCore/Serialization/SerializeContext.h>
|
|
#include <AzCore/Serialization/EditContext.h>
|
|
#include <AzFramework/Components/EditorEntityEvents.h>
|
|
#include <AzToolsFramework/ToolsComponents/GenericComponentWrapper.h>
|
|
#include <AzToolsFramework/Entity/EditorEntityHelpers.h>
|
|
|
|
|
|
namespace AzToolsFramework
|
|
{
|
|
namespace Components
|
|
{
|
|
/**
|
|
* Custom export callback for GenericComponentWrapper, invoked by the slice compiler.
|
|
* The Wrapper component simply exports the inner template, which is the runtime/non-editor component.
|
|
*/
|
|
AZ::ExportedComponent ExportTemplateComponent(AZ::Component* thisComponent, const AZ::PlatformTagSet& /*platformTags*/)
|
|
{
|
|
GenericComponentWrapper* wrapper = static_cast<GenericComponentWrapper*>(thisComponent);
|
|
return AZ::ExportedComponent(wrapper->GetTemplate(), false);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// GenericComponentWrapper
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
void GenericComponentWrapper::Reflect(AZ::ReflectContext* context)
|
|
{
|
|
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
|
|
if (serializeContext)
|
|
{
|
|
serializeContext->Class<GenericComponentWrapper, EditorComponentBase>()
|
|
->Field("m_template", &GenericComponentWrapper::m_template);
|
|
|
|
AZ::EditContext* editContext = serializeContext->GetEditContext();
|
|
if (editContext)
|
|
{
|
|
editContext->Class<GenericComponentWrapper>("GenericComponentWrapper", "This should be hidden!")
|
|
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
|
->Attribute(AZ::Edit::Attributes::NameLabelOverride, &GenericComponentWrapper::GetDisplayName)
|
|
->Attribute(AZ::Edit::Attributes::DescriptionTextOverride, &GenericComponentWrapper::GetDisplayDescription)
|
|
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
|
->Attribute(AZ::Edit::Attributes::RuntimeExportCallback, &ExportTemplateComponent)
|
|
->DataElement("", &GenericComponentWrapper::m_template, "m_template", "")
|
|
->Attribute(AZ::Edit::Attributes::Visibility, AZ_CRC("PropertyVisibility_ShowChildrenOnly", 0xef428f20));
|
|
}
|
|
}
|
|
}
|
|
|
|
GenericComponentWrapper::GenericComponentWrapper()
|
|
{
|
|
}
|
|
|
|
GenericComponentWrapper::GenericComponentWrapper(const AZ::SerializeContext::ClassData* templateClassData)
|
|
{
|
|
EBUS_EVENT_ID_RESULT(m_template, templateClassData->m_typeId, AZ::ComponentDescriptorBus, CreateComponent);
|
|
}
|
|
|
|
GenericComponentWrapper::GenericComponentWrapper(AZ::Component* templateClassInstance)
|
|
{
|
|
if (templateClassInstance)
|
|
{
|
|
if (templateClassInstance->GetEntity())
|
|
{
|
|
AZ_Error("GenericComponentWrapper", false, "Component must be detached from entity before placing inside GenericComponentWrapper.");
|
|
}
|
|
else
|
|
{
|
|
m_id = templateClassInstance->GetId();
|
|
m_template = templateClassInstance;
|
|
}
|
|
}
|
|
}
|
|
|
|
GenericComponentWrapper::~GenericComponentWrapper()
|
|
{
|
|
if (m_template)
|
|
{
|
|
delete m_template;
|
|
}
|
|
}
|
|
|
|
GenericComponentWrapper::GenericComponentWrapper(const GenericComponentWrapper& RHS)
|
|
: m_displayName(RHS.m_displayName)
|
|
, m_displayDescription(RHS.m_displayDescription)
|
|
{
|
|
if (GetEntity())
|
|
{
|
|
AZ_Assert(GetEntity()->GetState() <= AZ::Entity::State::Init, "Entity should not be activated when copying components");
|
|
}
|
|
|
|
AZ::SerializeContext* context = nullptr;
|
|
AZ::ComponentApplicationBus::BroadcastResult(context, &AZ::ComponentApplicationBus::Events::GetSerializeContext);
|
|
m_template = context->CloneObject<AZ::Component>(RHS.m_template);
|
|
|
|
m_templateEvents = azrtti_cast<AzFramework::EditorEntityEvents*>(m_template);
|
|
}
|
|
|
|
GenericComponentWrapper::GenericComponentWrapper(GenericComponentWrapper&& RHS)
|
|
: m_displayName(AZStd::move(RHS.m_displayName))
|
|
, m_displayDescription(AZStd::move(RHS.m_displayDescription))
|
|
{
|
|
if (GetEntity())
|
|
{
|
|
AZ_Assert(GetEntity()->GetState() <= AZ::Entity::State::Init, "Entity should not be activated when copying components");
|
|
}
|
|
|
|
m_template = AZStd::move(RHS.m_template);
|
|
RHS.m_template = nullptr;
|
|
|
|
m_templateEvents = azrtti_cast<AzFramework::EditorEntityEvents*>(m_template);
|
|
}
|
|
|
|
GenericComponentWrapper& GenericComponentWrapper::operator=(const GenericComponentWrapper& RHS)
|
|
{
|
|
if (GetEntity())
|
|
{
|
|
AZ_Assert(GetEntity()->GetState() <= AZ::Entity::State::Init, "Entity should not be activated when copying components");
|
|
}
|
|
|
|
AZ::SerializeContext* context = nullptr;
|
|
AZ::ComponentApplicationBus::BroadcastResult(context, &AZ::ComponentApplicationBus::Events::GetSerializeContext);
|
|
m_template = context->CloneObject<AZ::Component>(RHS.m_template);
|
|
|
|
m_templateEvents = azrtti_cast<AzFramework::EditorEntityEvents*>(m_template);
|
|
|
|
m_displayName = RHS.m_displayName;
|
|
m_displayDescription = RHS.m_displayDescription;
|
|
|
|
return *this;
|
|
}
|
|
|
|
GenericComponentWrapper& GenericComponentWrapper::operator=(GenericComponentWrapper&& RHS)
|
|
{
|
|
if (GetEntity())
|
|
{
|
|
AZ_Assert(GetEntity()->GetState() <= AZ::Entity::State::Init, "Entity should not be activated when copying components");
|
|
}
|
|
|
|
m_template = AZStd::move(RHS.m_template);
|
|
RHS.m_template = nullptr;
|
|
|
|
m_templateEvents = azrtti_cast<AzFramework::EditorEntityEvents*>(m_template);
|
|
|
|
m_displayName = AZStd::move(RHS.m_displayName);
|
|
m_displayDescription = AZStd::move(RHS.m_displayDescription);
|
|
|
|
return *this;
|
|
}
|
|
|
|
const char* GenericComponentWrapper::GetDisplayName()
|
|
{
|
|
if (m_displayName.empty())
|
|
{
|
|
if (m_template)
|
|
{
|
|
m_displayName = GetFriendlyComponentName(m_template);
|
|
}
|
|
}
|
|
return m_displayName.c_str();
|
|
}
|
|
|
|
const char* GenericComponentWrapper::GetDisplayDescription()
|
|
{
|
|
if (m_displayDescription.empty())
|
|
{
|
|
if (m_template)
|
|
{
|
|
m_displayDescription = GetFriendlyComponentDescription(m_template);
|
|
}
|
|
}
|
|
return m_displayDescription.c_str();
|
|
}
|
|
|
|
void GenericComponentWrapper::Init()
|
|
{
|
|
EditorComponentBase::Init();
|
|
|
|
if (m_template)
|
|
{
|
|
m_displayName = GetFriendlyComponentName(m_template);
|
|
m_displayDescription = GetFriendlyComponentDescription(m_template);
|
|
if (m_displayDescription.empty())
|
|
{
|
|
m_displayDescription = m_displayName;
|
|
}
|
|
|
|
m_templateEvents = azrtti_cast<AzFramework::EditorEntityEvents*>(m_template);
|
|
if (m_templateEvents)
|
|
{
|
|
m_templateEvents->EditorInit(GetEntityId());
|
|
}
|
|
}
|
|
}
|
|
|
|
void GenericComponentWrapper::Activate()
|
|
{
|
|
EditorComponentBase::Activate();
|
|
|
|
if (m_templateEvents)
|
|
{
|
|
m_templateEvents->EditorActivate(GetEntityId());
|
|
AzFramework::EntityDebugDisplayEventBus::Handler::BusConnect(GetEntityId());
|
|
}
|
|
}
|
|
|
|
void GenericComponentWrapper::Deactivate()
|
|
{
|
|
EditorComponentBase::Deactivate();
|
|
|
|
if (m_templateEvents)
|
|
{
|
|
AzFramework::EntityDebugDisplayEventBus::Handler::BusDisconnect();
|
|
m_templateEvents->EditorDeactivate(GetEntityId());
|
|
}
|
|
}
|
|
|
|
const AZ::TypeId& GenericComponentWrapper::GetUnderlyingComponentType() const
|
|
{
|
|
if (m_template)
|
|
{
|
|
return m_template->RTTI_GetType();
|
|
}
|
|
|
|
return RTTI_GetType();
|
|
}
|
|
|
|
void GenericComponentWrapper::BuildGameEntity(AZ::Entity* gameEntity)
|
|
{
|
|
if (m_template)
|
|
{
|
|
AZ::SerializeContext* context = nullptr;
|
|
AZ::ComponentApplicationBus::BroadcastResult(context, &AZ::ComponentApplicationBus::Events::GetSerializeContext);
|
|
if (!context)
|
|
{
|
|
AZ_Error("GenericComponentWrapper", false, "Can't get serialize context from component application.");
|
|
return;
|
|
}
|
|
|
|
gameEntity->AddComponent(context->CloneObject(m_template));
|
|
}
|
|
}
|
|
|
|
AZ::ComponentValidationResult GenericComponentWrapper::ValidateComponentRequirements(
|
|
const AZ::ImmutableEntityVector& sliceEntities, const AZStd::unordered_set<AZ::Crc32>& platformTags) const
|
|
{
|
|
AZ::ComponentValidationResult baseClassResult = EditorComponentBase::ValidateComponentRequirements(sliceEntities, platformTags);
|
|
if (!baseClassResult.IsSuccess())
|
|
{
|
|
return baseClassResult;
|
|
}
|
|
|
|
if (m_template)
|
|
{
|
|
return m_template->ValidateComponentRequirements(sliceEntities, platformTags);
|
|
}
|
|
|
|
return AZ::Success();
|
|
}
|
|
|
|
void GenericComponentWrapper::DisplayEntityViewport(
|
|
const AzFramework::ViewportInfo& /*viewportInfo*/,
|
|
AzFramework::DebugDisplayRequests& debugDisplay)
|
|
{
|
|
if (m_templateEvents)
|
|
{
|
|
m_templateEvents->EditorDisplay(GetEntityId(), debugDisplay, GetWorldTM());
|
|
}
|
|
}
|
|
|
|
void GenericComponentWrapper::SetPrimaryAsset(const AZ::Data::AssetId& assetId)
|
|
{
|
|
if (m_templateEvents)
|
|
{
|
|
m_templateEvents->EditorSetPrimaryAsset(assetId);
|
|
}
|
|
}
|
|
|
|
AZ::Component* GenericComponentWrapper::ReleaseTemplate()
|
|
{
|
|
AZ::Component* component = m_template;
|
|
m_template = nullptr;
|
|
return component;
|
|
}
|
|
|
|
class GenericComponentWrapperDescriptor
|
|
: public AZ::ComponentDescriptorHelper<GenericComponentWrapper>
|
|
{
|
|
public:
|
|
AZ_CLASS_ALLOCATOR(GenericComponentWrapperDescriptor, AZ::SystemAllocator, 0);
|
|
AZ_TYPE_INFO(GenericComponentWrapperDescriptor, "{3326B218-282B-4985-AEDE-39A77D48AD57}");
|
|
|
|
AZ::ComponentDescriptor* GetTemplateDescriptor(const AZ::Component* instance) const
|
|
{
|
|
AZ::ComponentDescriptor* templateDescriptor = nullptr;
|
|
|
|
const GenericComponentWrapper* wrapper = azrtti_cast<const GenericComponentWrapper*>(instance);
|
|
if (wrapper && wrapper->GetTemplate())
|
|
{
|
|
EBUS_EVENT_ID_RESULT(
|
|
templateDescriptor, wrapper->GetTemplate()->RTTI_GetType(),
|
|
AZ::ComponentDescriptorBus, GetDescriptor);
|
|
}
|
|
|
|
return templateDescriptor;
|
|
}
|
|
|
|
void Reflect(AZ::ReflectContext* reflection) const override
|
|
{
|
|
GenericComponentWrapper::Reflect(reflection);
|
|
}
|
|
|
|
void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided, const AZ::Component* instance) const override
|
|
{
|
|
const AZ::ComponentDescriptor* templateDescriptor = GetTemplateDescriptor(instance);
|
|
if (templateDescriptor)
|
|
{
|
|
templateDescriptor->GetProvidedServices(provided, instance);
|
|
}
|
|
}
|
|
|
|
void GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent, const AZ::Component* instance) const override
|
|
{
|
|
const AZ::ComponentDescriptor* templateDescriptor = GetTemplateDescriptor(instance);
|
|
if (templateDescriptor)
|
|
{
|
|
templateDescriptor->GetDependentServices(dependent, instance);
|
|
}
|
|
}
|
|
|
|
void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required, const AZ::Component* instance) const override
|
|
{
|
|
const AZ::ComponentDescriptor* templateDescriptor = GetTemplateDescriptor(instance);
|
|
if (templateDescriptor)
|
|
{
|
|
templateDescriptor->GetRequiredServices(required, instance);
|
|
}
|
|
}
|
|
|
|
void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible, const AZ::Component* instance) const override
|
|
{
|
|
const AZ::ComponentDescriptor* templateDescriptor = GetTemplateDescriptor(instance);
|
|
if (templateDescriptor)
|
|
{
|
|
templateDescriptor->GetIncompatibleServices(incompatible, instance);
|
|
}
|
|
}
|
|
};
|
|
|
|
AZ::ComponentDescriptor* GenericComponentWrapper::CreateDescriptor()
|
|
{
|
|
AZ::ComponentDescriptor* descriptor = nullptr;
|
|
EBUS_EVENT_ID_RESULT(descriptor, GenericComponentWrapper::RTTI_Type(), AZ::ComponentDescriptorBus, GetDescriptor);
|
|
|
|
return descriptor ? descriptor : aznew GenericComponentWrapperDescriptor();
|
|
}
|
|
} // namespace Components
|
|
|
|
const AZ::Uuid& GetUnderlyingComponentType(const AZ::Component& component)
|
|
{
|
|
return component.GetUnderlyingComponentType();
|
|
}
|
|
} // namespace AzToolsFramework
|