merge from main
This commit is contained in:
+1
-1
@@ -62,7 +62,7 @@ namespace AZ
|
||||
bool m_enableShadow = false;
|
||||
ShadowmapSize m_shadowmapMaxSize = ShadowmapSize::Size256;
|
||||
ShadowFilterMethod m_shadowFilterMethod = ShadowFilterMethod::None;
|
||||
PcfMethod m_pcfMethod = PcfMethod::BoundarySearch;
|
||||
PcfMethod m_pcfMethod = PcfMethod::Bicubic;
|
||||
float m_boundaryWidthInDegrees = 0.25f;
|
||||
uint16_t m_predictionSampleCount = 4;
|
||||
uint16_t m_filteringSampleCount = 12;
|
||||
|
||||
+2
-2
@@ -61,7 +61,7 @@ namespace AZ
|
||||
float m_shadowFarClipDistance = 100.f;
|
||||
|
||||
//! Width/Height of shadowmap images.
|
||||
ShadowmapSize m_shadowmapSize = MaxShadowmapImageSize;
|
||||
ShadowmapSize m_shadowmapSize = ShadowmapSize::Size1024;
|
||||
|
||||
//! Number of cascades.
|
||||
uint32_t m_cascadeCount = 4;
|
||||
@@ -117,7 +117,7 @@ namespace AZ
|
||||
//! It is used only when the pixel is predicted as on the boundary.
|
||||
uint16_t m_filteringSampleCount = 32;
|
||||
|
||||
PcfMethod m_pcfMethod = PcfMethod::BoundarySearch;
|
||||
PcfMethod m_pcfMethod = PcfMethod::Bicubic;
|
||||
|
||||
bool IsSplitManual() const;
|
||||
bool IsSplitAutomatic() const;
|
||||
|
||||
+1
-1
@@ -51,4 +51,4 @@ namespace AZ
|
||||
using GridComponentNotificationBus = EBus<GridComponentNotifications>;
|
||||
|
||||
} // namespace Render
|
||||
} // namespace AZ
|
||||
} // namespace AZ
|
||||
|
||||
+1
-1
@@ -39,4 +39,4 @@ namespace AZ
|
||||
AZ::Color m_secondaryColor = AZ::Color(0.5f, 0.5f, 0.5f, 1.0f);
|
||||
};
|
||||
} // namespace Render
|
||||
} // namespace AZ
|
||||
} // namespace AZ
|
||||
|
||||
+1
-1
@@ -19,4 +19,4 @@ namespace AZ
|
||||
static constexpr const char* const GridComponentTypeId = "{27ACB2B3-C889-4DA5-BD27-E8C45CFBCFD6}";
|
||||
static constexpr const char* const EditorGridComponentTypeId = "{DF2D071A-EC31-428A-9FD0-2B8A59945417}";
|
||||
} // namespace Render
|
||||
} // namespace AZ
|
||||
} // namespace AZ
|
||||
|
||||
+1
-1
@@ -19,4 +19,4 @@ namespace AZ
|
||||
static constexpr const char* const ImageBasedLightComponentTypeId = "{33A1302F-A769-4D06-820A-096A4836A7E9}";
|
||||
static constexpr const char* const EditorImageBasedLightComponentTypeId = "{6202F16C-DDF9-4026-9479-F5BDC621D372}";
|
||||
} // namespace Render
|
||||
} // namespace AZ
|
||||
} // namespace AZ
|
||||
|
||||
+1
-1
@@ -19,4 +19,4 @@ namespace AZ
|
||||
static constexpr const char* const MaterialComponentTypeId = "{E5A56D7F-C63E-4080-BF62-01326AC60982}";
|
||||
static constexpr const char* const EditorMaterialComponentTypeId = "{02B60E9D-470B-447D-A6EE-7D635B154183}";
|
||||
} // namespace Render
|
||||
} // namespace AZ
|
||||
} // namespace AZ
|
||||
|
||||
+7
-4
@@ -27,7 +27,7 @@ namespace AZ
|
||||
{
|
||||
public:
|
||||
virtual void SetModelAsset(Data::Asset<RPI::ModelAsset> modelAsset) = 0;
|
||||
virtual const Data::Asset<RPI::ModelAsset>& GetModelAsset() const = 0;
|
||||
virtual Data::Asset<const RPI::ModelAsset> GetModelAsset() const = 0;
|
||||
|
||||
virtual void SetModelAssetId(Data::AssetId modelAssetId) = 0;
|
||||
virtual Data::AssetId GetModelAssetId() const = 0;
|
||||
@@ -35,7 +35,7 @@ namespace AZ
|
||||
virtual void SetModelAssetPath(const AZStd::string& path) = 0;
|
||||
virtual AZStd::string GetModelAssetPath() const = 0;
|
||||
|
||||
virtual const Data::Instance<RPI::Model> GetModel() const = 0;
|
||||
virtual Data::Instance<RPI::Model> GetModel() const = 0;
|
||||
|
||||
virtual void SetSortKey(RHI::DrawItemSortKey sortKey) = 0;
|
||||
virtual RHI::DrawItemSortKey GetSortKey() const = 0;
|
||||
@@ -78,12 +78,15 @@ namespace AZ
|
||||
{
|
||||
AZ::EBusConnectionPolicy<Bus>::Connect(busPtr, context, handler, connectLock, id);
|
||||
|
||||
Data::Asset<RPI::ModelAsset> modelAsset;
|
||||
MeshComponentRequestBus::EventResult(modelAsset, id, &MeshComponentRequestBus::Events::GetModelAsset);
|
||||
Data::Instance<RPI::Model> model;
|
||||
MeshComponentRequestBus::EventResult(model, id, &MeshComponentRequestBus::Events::GetModel);
|
||||
|
||||
if (model &&
|
||||
model->GetModelAsset().GetStatus() == AZ::Data::AssetData::AssetStatus::Ready)
|
||||
modelAsset.GetStatus() == AZ::Data::AssetData::AssetStatus::Ready)
|
||||
{
|
||||
handler->OnModelReady(model->GetModelAsset(), model);
|
||||
handler->OnModelReady(modelAsset, model);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
+1
-1
@@ -19,4 +19,4 @@ namespace AZ
|
||||
static constexpr const char* const MeshComponentTypeId = "{C7801FA8-3E82-4D40-B039-4854F1892FDE}";
|
||||
static constexpr const char* const EditorMeshComponentTypeId = "{DCE68F6E-2E16-4CB4-A834-B6C2F900A7E9}";
|
||||
} // namespace Render
|
||||
} // namespace AZ
|
||||
} // namespace AZ
|
||||
|
||||
+1
-1
@@ -33,4 +33,4 @@ namespace AZ
|
||||
|
||||
using EditorReflectionProbeBus = AZ::EBus<EditorReflectionProbeInterface>;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,4 +9,4 @@
|
||||
</g>
|
||||
<path d="M22,20.8342395 C22,18.1069667 22,17.2661779 22,11.7433304 C22,6.22048287 22,5.379694 22,2.65242127 C22,-0.0748514543 12,6.28878491 12,11.7433304 C12,17.1978758 22,23.5615122 22,20.8342395 Z" id="Path" fill="#FFFFFF" fill-rule="nonzero" transform="translate(17.000000, 11.743330) scale(-1, 1) translate(-17.000000, -11.743330) "></path>
|
||||
</g>
|
||||
</svg>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
@@ -0,0 +1,355 @@
|
||||
/*
|
||||
* 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 "AttachmentComponent.h"
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/RTTI/BehaviorContext.h>
|
||||
#include <AzCore/Component/Entity.h>
|
||||
#include <MathConversion.h>
|
||||
#include <LmbrCentral/Rendering/MeshAsset.h>
|
||||
#include <LmbrCentral/Animation/AttachmentComponentBus.h>
|
||||
#include <LmbrCentral/Animation/SkeletalHierarchyRequestBus.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace Render
|
||||
{
|
||||
/// Behavior Context handler for AttachmentComponentNotificationBus
|
||||
class BehaviorAttachmentComponentNotificationBusHandler : public LmbrCentral::AttachmentComponentNotificationBus::Handler,
|
||||
public AZ::BehaviorEBusHandler
|
||||
{
|
||||
public:
|
||||
AZ_EBUS_BEHAVIOR_BINDER(
|
||||
BehaviorAttachmentComponentNotificationBusHandler, "{636B95A0-5C7D-4EE7-8645-955665315451}", AZ::SystemAllocator,
|
||||
OnAttached, OnDetached);
|
||||
|
||||
void OnAttached(AZ::EntityId id) override
|
||||
{
|
||||
Call(FN_OnAttached, id);
|
||||
}
|
||||
|
||||
void OnDetached(AZ::EntityId id) override
|
||||
{
|
||||
Call(FN_OnDetached, id);
|
||||
}
|
||||
};
|
||||
|
||||
void AttachmentConfiguration::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
|
||||
if (serializeContext)
|
||||
{
|
||||
serializeContext->Class<AttachmentConfiguration>()
|
||||
->Version(1)
|
||||
->Field("Target ID", &AttachmentConfiguration::m_targetId)
|
||||
->Field("Target Bone Name", &AttachmentConfiguration::m_targetBoneName)
|
||||
->Field("Target Offset", &AttachmentConfiguration::m_targetOffset)
|
||||
->Field("Attached Initially", &AttachmentConfiguration::m_attachedInitially)
|
||||
->Field("Scale Source", &AttachmentConfiguration::m_scaleSource);
|
||||
}
|
||||
AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context);
|
||||
if (behaviorContext)
|
||||
{
|
||||
behaviorContext->EBus<LmbrCentral::AttachmentComponentRequestBus>("AttachmentComponentRequestBus")
|
||||
->Event("Attach", &LmbrCentral::AttachmentComponentRequestBus::Events::Attach)
|
||||
->Event("Detach", &LmbrCentral::AttachmentComponentRequestBus::Events::Detach)
|
||||
->Event("SetAttachmentOffset", &LmbrCentral::AttachmentComponentRequestBus::Events::SetAttachmentOffset);
|
||||
|
||||
behaviorContext->EBus<LmbrCentral::AttachmentComponentNotificationBus>("AttachmentComponentNotificationBus")
|
||||
->Handler<BehaviorAttachmentComponentNotificationBusHandler>();
|
||||
}
|
||||
}
|
||||
|
||||
void AttachmentComponent::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
AttachmentConfiguration::Reflect(context);
|
||||
|
||||
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
|
||||
if (serializeContext)
|
||||
{
|
||||
serializeContext->Class<AttachmentComponent, AZ::Component>()->Version(1)->Field(
|
||||
"Configuration", &AttachmentComponent::m_initialConfiguration);
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
// BoneFollower
|
||||
//=========================================================================
|
||||
|
||||
void BoneFollower::Activate(AZ::Entity* owner, const AttachmentConfiguration& configuration, bool targetCanAnimate)
|
||||
{
|
||||
AZ_Assert(owner, "owner is required");
|
||||
AZ_Assert(!m_ownerId.IsValid(), "BoneFollower is already Activated");
|
||||
|
||||
m_ownerId = owner->GetId();
|
||||
m_targetCanAnimate = targetCanAnimate;
|
||||
m_isUpdatingOwnerTransform = false;
|
||||
m_scaleSource = configuration.m_scaleSource;
|
||||
|
||||
m_cachedOwnerTransform = AZ::Transform::CreateIdentity();
|
||||
EBUS_EVENT_ID_RESULT(m_cachedOwnerTransform, m_ownerId, AZ::TransformBus, GetWorldTM);
|
||||
|
||||
if (configuration.m_attachedInitially)
|
||||
{
|
||||
Attach(configuration.m_targetId, configuration.m_targetBoneName.c_str(), configuration.m_targetOffset);
|
||||
}
|
||||
|
||||
LmbrCentral::AttachmentComponentRequestBus::Handler::BusConnect(m_ownerId);
|
||||
}
|
||||
|
||||
void BoneFollower::Deactivate()
|
||||
{
|
||||
AZ_Assert(m_ownerId.IsValid(), "BoneFollower was never Activated");
|
||||
|
||||
LmbrCentral::AttachmentComponentRequestBus::Handler::BusDisconnect();
|
||||
Detach();
|
||||
m_ownerId.SetInvalid();
|
||||
}
|
||||
|
||||
AZ::EntityId BoneFollower::GetTargetEntityId()
|
||||
{
|
||||
return m_targetId;
|
||||
}
|
||||
|
||||
AZ::Transform BoneFollower::GetOffset()
|
||||
{
|
||||
return m_targetOffset;
|
||||
}
|
||||
|
||||
void BoneFollower::Attach(AZ::EntityId targetId, const char* targetBoneName, const AZ::Transform& offset)
|
||||
{
|
||||
AZ_Assert(m_ownerId.IsValid(), "BoneFollower must be Activated to use.")
|
||||
|
||||
// safe to try and detach, even if we weren't attached
|
||||
Detach();
|
||||
|
||||
if (!targetId.IsValid())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (targetId == m_ownerId)
|
||||
{
|
||||
AZ_Error("Attachment Component", false, "AttachmentComponent cannot target itself");
|
||||
return;
|
||||
}
|
||||
|
||||
// Note: the target entity may not be activated yet. That's ok.
|
||||
// When mesh is ready we are notified via MeshComponentEvents::OnModelReady
|
||||
// When transform is ready we are notified via TransformNotificationBus::OnTransformChanged
|
||||
|
||||
m_targetId = targetId;
|
||||
m_targetBoneName = targetBoneName;
|
||||
m_targetOffset = offset;
|
||||
|
||||
BindTargetBone();
|
||||
|
||||
m_targetBoneTransform = AZ::Transform::Identity();
|
||||
|
||||
m_isTargetEntityTransformKnown = false; // target's transform may not be available yet
|
||||
|
||||
AZ::TransformBus::EventResult(
|
||||
m_cachedOwnerTransform, m_ownerId, &AZ::TransformBus::Events::GetWorldTM); // owner query will always succeed
|
||||
|
||||
MeshComponentNotificationBus::Handler::BusConnect(m_targetId); // fires OnModelReady if asset is already ready
|
||||
AZ::TransformNotificationBus::Handler::BusConnect(m_targetId);
|
||||
if (m_targetCanAnimate)
|
||||
{
|
||||
// Only register for per-frame updates when target can animate
|
||||
AZ::TickBus::Handler::BusConnect();
|
||||
}
|
||||
|
||||
// update owner's transform
|
||||
UpdateOwnerTransformIfNecessary();
|
||||
|
||||
// alert others that we've attached
|
||||
LmbrCentral::AttachmentComponentNotificationBus::Event(m_targetId, &LmbrCentral::AttachmentComponentNotificationBus::Events::OnAttached, m_ownerId);
|
||||
}
|
||||
|
||||
void BoneFollower::Detach()
|
||||
{
|
||||
AZ_Assert(m_ownerId.IsValid(), "BoneFollower must be Activated to use.");
|
||||
|
||||
if (m_targetId.IsValid())
|
||||
{
|
||||
// alert others that we're detaching
|
||||
EBUS_EVENT_ID(m_targetId, LmbrCentral::AttachmentComponentNotificationBus, OnDetached, m_ownerId);
|
||||
|
||||
MeshComponentNotificationBus::Handler::BusDisconnect();
|
||||
AZ::TransformNotificationBus::Handler::BusDisconnect(m_targetId);
|
||||
AZ::TickBus::Handler::BusDisconnect();
|
||||
|
||||
m_targetId.SetInvalid();
|
||||
}
|
||||
}
|
||||
|
||||
const char* BoneFollower::GetJointName()
|
||||
{
|
||||
return m_targetBoneName.c_str();
|
||||
}
|
||||
|
||||
void BoneFollower::SetAttachmentOffset(const AZ::Transform& offset)
|
||||
{
|
||||
AZ_Assert(m_ownerId.IsValid(), "BoneFollower must be Activated to use.");
|
||||
|
||||
if (m_targetId.IsValid())
|
||||
{
|
||||
m_targetOffset = offset;
|
||||
UpdateOwnerTransformIfNecessary();
|
||||
}
|
||||
}
|
||||
|
||||
void BoneFollower::OnModelReady([[maybe_unused]] const AZ::Data::Asset<AZ::RPI::ModelAsset>& modelAsset, [[maybe_unused]] const AZ::Data::Instance<AZ::RPI::Model>& model)
|
||||
{
|
||||
// reset character values
|
||||
BindTargetBone();
|
||||
m_targetBoneTransform = QueryBoneTransform();
|
||||
|
||||
// move owner if necessary
|
||||
UpdateOwnerTransformIfNecessary();
|
||||
}
|
||||
|
||||
void BoneFollower::BindTargetBone()
|
||||
{
|
||||
m_targetBoneId = -1;
|
||||
LmbrCentral::SkeletalHierarchyRequestBus::EventResult(
|
||||
m_targetBoneId, m_targetId, &LmbrCentral::SkeletalHierarchyRequests::GetJointIndexByName, m_targetBoneName.c_str());
|
||||
}
|
||||
|
||||
void BoneFollower::UpdateOwnerTransformIfNecessary()
|
||||
{
|
||||
// Can't update until target entity's transform is known
|
||||
if (!m_isTargetEntityTransformKnown)
|
||||
{
|
||||
if (AZ::TransformBus::GetNumOfEventHandlers(m_targetId) == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AZ::TransformBus::EventResult(m_targetEntityTransform, m_targetId, &AZ::TransformBus::Events::GetWorldTM);
|
||||
m_isTargetEntityTransformKnown = true;
|
||||
}
|
||||
|
||||
AZ::Transform finalTransform;
|
||||
if (m_scaleSource == AttachmentConfiguration::ScaleSource::WorldScale)
|
||||
{
|
||||
// apply offset in world-space
|
||||
finalTransform = m_targetEntityTransform * m_targetBoneTransform;
|
||||
finalTransform.SetScale(AZ::Vector3::CreateOne());
|
||||
finalTransform *= m_targetOffset;
|
||||
}
|
||||
else if (m_scaleSource == AttachmentConfiguration::ScaleSource::TargetEntityScale)
|
||||
{
|
||||
// apply offset in target-entity-space (ignoring bone scale)
|
||||
AZ::Transform boneNoScale = m_targetBoneTransform;
|
||||
boneNoScale.SetScale(AZ::Vector3::CreateOne());
|
||||
|
||||
finalTransform = m_targetEntityTransform * boneNoScale * m_targetOffset;
|
||||
}
|
||||
else // AttachmentConfiguration::ScaleSource::TargetEntityScale
|
||||
{
|
||||
// apply offset in target-bone-space
|
||||
finalTransform = m_targetEntityTransform * m_targetBoneTransform * m_targetOffset;
|
||||
}
|
||||
|
||||
if (m_cachedOwnerTransform != finalTransform)
|
||||
{
|
||||
AZ_Warning(
|
||||
"Attachment Component", !m_isUpdatingOwnerTransform,
|
||||
"AttachmentComponent detected a cycle when updating transform, do not target child entities.");
|
||||
if (!m_isUpdatingOwnerTransform)
|
||||
{
|
||||
m_cachedOwnerTransform = finalTransform;
|
||||
m_isUpdatingOwnerTransform = true;
|
||||
EBUS_EVENT_ID(m_ownerId, AZ::TransformBus, SetWorldTM, finalTransform);
|
||||
m_isUpdatingOwnerTransform = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AZ::Transform BoneFollower::QueryBoneTransform() const
|
||||
{
|
||||
AZ::Transform boneTransform = AZ::Transform::CreateIdentity();
|
||||
|
||||
if (m_targetBoneId >= 0)
|
||||
{
|
||||
LmbrCentral::SkeletalHierarchyRequestBus::EventResult(
|
||||
boneTransform, m_targetId, &LmbrCentral::SkeletalHierarchyRequests::GetJointTransformCharacterRelative, m_targetBoneId);
|
||||
}
|
||||
|
||||
return boneTransform;
|
||||
}
|
||||
|
||||
// fires when target's transform changes
|
||||
void BoneFollower::OnTransformChanged(const AZ::Transform& /*local*/, const AZ::Transform& world)
|
||||
{
|
||||
m_targetEntityTransform = world;
|
||||
m_isTargetEntityTransformKnown = true;
|
||||
UpdateOwnerTransformIfNecessary();
|
||||
}
|
||||
|
||||
void BoneFollower::OnTick(float /*deltaTime*/, AZ::ScriptTimePoint /*time*/)
|
||||
{
|
||||
m_targetBoneTransform = QueryBoneTransform();
|
||||
UpdateOwnerTransformIfNecessary();
|
||||
}
|
||||
|
||||
int BoneFollower::GetTickOrder()
|
||||
{
|
||||
return AZ::TICK_ATTACHMENT;
|
||||
}
|
||||
|
||||
void BoneFollower::Reattach(bool detachFirst)
|
||||
{
|
||||
#ifdef AZ_ENABLE_TRACING
|
||||
AZ::Entity* ownerEntity = nullptr;
|
||||
AZ::Entity* targetEntity = nullptr;
|
||||
AZ::ComponentApplicationBus::BroadcastResult(ownerEntity, &AZ::ComponentApplicationBus::Events::FindEntity, m_ownerId);
|
||||
AZ::ComponentApplicationBus::BroadcastResult(targetEntity, &AZ::ComponentApplicationBus::Events::FindEntity, m_targetId);
|
||||
AZ_TracePrintf(
|
||||
"BoneFollower", "Reattaching entity '%s' to entity '%s'", ownerEntity ? ownerEntity->GetName().c_str() : "",
|
||||
targetEntity ? targetEntity->GetName().c_str() : "");
|
||||
#endif
|
||||
|
||||
if (m_targetId.IsValid() && detachFirst)
|
||||
{
|
||||
LmbrCentral::AttachmentComponentNotificationBus::Event(m_targetId, &LmbrCentral::AttachmentComponentNotificationBus::Events::OnDetached, m_ownerId);
|
||||
}
|
||||
|
||||
if (m_targetId != m_ownerId)
|
||||
{
|
||||
LmbrCentral::AttachmentComponentNotificationBus::Event(m_targetId, &LmbrCentral::AttachmentComponentNotificationBus::Events::OnAttached, m_ownerId);
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
// AttachmentComponent
|
||||
//=========================================================================
|
||||
|
||||
void AttachmentComponent::Activate()
|
||||
{
|
||||
#ifdef AZ_ENABLE_TRACING
|
||||
bool isStaticTransform = false;
|
||||
AZ::TransformBus::EventResult(isStaticTransform, GetEntityId(), &AZ::TransformBus::Events::IsStaticTransform);
|
||||
AZ_Warning(
|
||||
"Attachment Component", !isStaticTransform, "Attachment needs to move, but entity '%s' %s has a static transform.",
|
||||
GetEntity()->GetName().c_str(), GetEntityId().ToString().c_str());
|
||||
#endif
|
||||
|
||||
m_boneFollower.Activate(GetEntity(), m_initialConfiguration, true);
|
||||
}
|
||||
|
||||
void AttachmentComponent::Deactivate()
|
||||
{
|
||||
m_boneFollower.Deactivate();
|
||||
}
|
||||
} // namespace Render
|
||||
} // namespace AZ
|
||||
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
* 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 <LmbrCentral/Animation/AttachmentComponentBus.h>
|
||||
#include <AtomLyIntegration/CommonFeatures/Mesh/MeshComponentBus.h>
|
||||
#include <AzCore/Component/Component.h>
|
||||
#include <AzCore/Component/TransformBus.h>
|
||||
#include <AzCore/Component/TickBus.h>
|
||||
#include <AzCore/Math/Transform.h>
|
||||
|
||||
struct ISkeletonPose;
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace Render
|
||||
{
|
||||
/*!
|
||||
* Configuration data for AttachmentComponent.
|
||||
*/
|
||||
struct AttachmentConfiguration
|
||||
{
|
||||
AZ_TYPE_INFO(AttachmentConfiguration, "{74B5DC69-DE44-4640-836A-55339E116795}");
|
||||
|
||||
virtual ~AttachmentConfiguration() = default;
|
||||
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
//! Attach to this entity.
|
||||
AZ::EntityId m_targetId;
|
||||
|
||||
//! Attach to this bone on target entity.
|
||||
AZStd::string m_targetBoneName;
|
||||
|
||||
//! Offset from target.
|
||||
AZ::Transform m_targetOffset = AZ::Transform::Identity();
|
||||
|
||||
//! Whether to attach to target upon activation.
|
||||
//! If false, the entity remains detached until Attach() is called.
|
||||
bool m_attachedInitially = true;
|
||||
|
||||
//! Source from which to retrieve scale information.
|
||||
enum class ScaleSource : AZ::u8
|
||||
{
|
||||
WorldScale, // Scaled in world space.
|
||||
TargetEntityScale, // Adopt scaling of attachment target entity.
|
||||
TargetBoneScale, // Adopt scaling of attachment target entity/joint.
|
||||
};
|
||||
ScaleSource m_scaleSource = ScaleSource::WorldScale;
|
||||
};
|
||||
|
||||
/*
|
||||
* Common functionality for game and editor attachment components.
|
||||
* The BoneFollower tracks movement of the target's bone and
|
||||
* updates the owning entity's TransformComponent to follow.
|
||||
* This class should be a member within the attachment component
|
||||
* and be activated/deactivated along with the component.
|
||||
* \ref AttachmentComponent
|
||||
*/
|
||||
class BoneFollower
|
||||
: public LmbrCentral::AttachmentComponentRequestBus::Handler
|
||||
, public AZ::TransformNotificationBus::Handler
|
||||
, public AZ::Render::MeshComponentNotificationBus::Handler
|
||||
, public AZ::Data::AssetBus::Handler
|
||||
, public AZ::TickBus::Handler
|
||||
{
|
||||
public:
|
||||
void Activate(AZ::Entity* owner, const AttachmentConfiguration& initialConfiguration, bool targetCanAnimate);
|
||||
void Deactivate();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// AttachmentComponentRequests
|
||||
void Reattach(bool detachFirst);
|
||||
void Attach(AZ::EntityId targetId, const char* targetBoneName, const AZ::Transform& offset) override;
|
||||
void Detach() override;
|
||||
void SetAttachmentOffset(const AZ::Transform& offset) override;
|
||||
const char* GetJointName() override;
|
||||
AZ::EntityId GetTargetEntityId() override;
|
||||
AZ::Transform GetOffset() override;
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// AZ::TickBus
|
||||
//! Check target bone transform every frame.
|
||||
void OnTick(float deltaTime, AZ::ScriptTimePoint time) override;
|
||||
//! Make sure target bone transform updates after animation update.
|
||||
int GetTickOrder() override;
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// AZ::TransformNotificationBus
|
||||
//! When target's transform changes
|
||||
void OnTransformChanged(const AZ::Transform& local, const AZ::Transform& world) override;
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// MeshComponentEvents
|
||||
//! When target's mesh changes
|
||||
void OnModelReady(const AZ::Data::Asset<AZ::RPI::ModelAsset>& modelAsset, const AZ::Data::Instance<AZ::RPI::Model>& model) override;
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void BindTargetBone();
|
||||
|
||||
AZ::Transform QueryBoneTransform() const;
|
||||
|
||||
void UpdateOwnerTransformIfNecessary();
|
||||
|
||||
//! Entity which which is being attached.
|
||||
AZ::EntityId m_ownerId;
|
||||
|
||||
//! Whether to query bone position per-frame (false while in editor)
|
||||
bool m_targetCanAnimate = false;
|
||||
|
||||
AZ::EntityId m_targetId;
|
||||
AZStd::string m_targetBoneName;
|
||||
AZ::Transform m_targetOffset; //!< local transform
|
||||
AZ::Transform m_targetBoneTransform; //!< local transform of bone
|
||||
AZ::Transform m_targetEntityTransform; //!< world transform of target
|
||||
bool m_isTargetEntityTransformKnown = false;
|
||||
|
||||
//! Cached value, so we don't update owner's position unnecessarily.
|
||||
AZ::Transform m_cachedOwnerTransform;
|
||||
bool m_isUpdatingOwnerTransform = false; //!< detect infinite loops when updating owner's transform
|
||||
|
||||
// Cached character values to avoid repeated lookup.
|
||||
// These are set by calling ResetCharacter()
|
||||
int m_targetBoneId; //!< negative when bone not found
|
||||
|
||||
AttachmentConfiguration::ScaleSource m_scaleSource;
|
||||
};
|
||||
|
||||
/*!
|
||||
* The AttachmentComponent lets an entity stick to a particular bone on
|
||||
* a target entity. This is achieved by tracking movement of the target's
|
||||
* bone and updating the entity's TransformComponent accordingly.
|
||||
*/
|
||||
class AttachmentComponent
|
||||
: public AZ::Component
|
||||
{
|
||||
public:
|
||||
AZ_COMPONENT(AttachmentComponent, "{2D17A64A-7AC5-4C02-AC36-C5E8141FFDDF}");
|
||||
|
||||
friend class EditorAttachmentComponent;
|
||||
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
|
||||
{
|
||||
provided.push_back(AZ_CRC("AttachmentService", 0x5aaa7b63));
|
||||
}
|
||||
|
||||
static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
|
||||
{
|
||||
incompatible.push_back(AZ_CRC("AttachmentService", 0x5aaa7b63));
|
||||
incompatible.push_back(AZ_CRC_CE("NonUniformScaleService"));
|
||||
}
|
||||
|
||||
static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required)
|
||||
{
|
||||
required.push_back(AZ_CRC("TransformService", 0x8ee22c50));
|
||||
}
|
||||
|
||||
~AttachmentComponent() override = default;
|
||||
|
||||
private:
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// AZ::Component
|
||||
void Activate() override;
|
||||
void Deactivate() override;
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//! Initial configuration for m_attachment
|
||||
AttachmentConfiguration m_initialConfiguration;
|
||||
|
||||
//! Implements actual attachment functionality
|
||||
BoneFollower m_boneFollower;
|
||||
};
|
||||
} // namespace Render
|
||||
} // namespace AZ
|
||||
+242
@@ -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 "EditorAttachmentComponent.h"
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
#include <AzCore/Math/Quaternion.h>
|
||||
#include <AzCore/Math/Transform.h>
|
||||
#include <LmbrCentral/Animation/SkeletalHierarchyRequestBus.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace Render
|
||||
{
|
||||
void EditorAttachmentComponent::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
|
||||
if (serializeContext)
|
||||
{
|
||||
serializeContext->Class<EditorAttachmentComponent, EditorComponentBase>()
|
||||
->Version(1)
|
||||
->Field("Target ID", &EditorAttachmentComponent::m_targetId)
|
||||
->Field("Target Bone Name", &EditorAttachmentComponent::m_targetBoneName)
|
||||
->Field("Position Offset", &EditorAttachmentComponent::m_positionOffset)
|
||||
->Field("Rotation Offset", &EditorAttachmentComponent::m_rotationOffset)
|
||||
->Field("Scale Offset", &EditorAttachmentComponent::m_scaleOffset)
|
||||
->Field("Attached Initially", &EditorAttachmentComponent::m_attachedInitially)
|
||||
->Field("Scale Source", &EditorAttachmentComponent::m_scaleSource);
|
||||
|
||||
AZ::EditContext* editContext = serializeContext->GetEditContext();
|
||||
if (editContext)
|
||||
{
|
||||
editContext
|
||||
->Class<EditorAttachmentComponent>(
|
||||
"Attachment", "The Attachment component lets an entity attach to a bone on the skeleton of another entity")
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::Category, "Animation")
|
||||
->Attribute(AZ::Edit::Attributes::Icon, "Icons/Components/Attachment.svg")
|
||||
->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/Attachment.png")
|
||||
->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c))
|
||||
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
||||
->Attribute(
|
||||
AZ::Edit::Attributes::HelpPageURL,
|
||||
"https://docs.aws.amazon.com/lumberyard/latest/userguide/component-attachment.html")
|
||||
->DataElement(0, &EditorAttachmentComponent::m_targetId, "Target entity", "Attach to this entity.")
|
||||
->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorAttachmentComponent::OnTargetIdChanged)
|
||||
->DataElement(
|
||||
AZ::Edit::UIHandlers::ComboBox, &EditorAttachmentComponent::m_targetBoneName, "Joint name",
|
||||
"Attach to this joint on target entity.")
|
||||
->Attribute(AZ::Edit::Attributes::StringList, &EditorAttachmentComponent::GetTargetBoneOptions)
|
||||
->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorAttachmentComponent::OnTargetBoneChanged)
|
||||
->DataElement(
|
||||
0, &EditorAttachmentComponent::m_positionOffset, "Position offset", "Local position offset from target bone")
|
||||
->Attribute(AZ::Edit::Attributes::Suffix, "m")
|
||||
->Attribute(AZ::Edit::Attributes::Step, 0.01f)
|
||||
->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorAttachmentComponent::OnTargetOffsetChanged)
|
||||
->DataElement(
|
||||
0, &EditorAttachmentComponent::m_rotationOffset, "Rotation offset", "Local rotation offset from target bone")
|
||||
->Attribute(AZ::Edit::Attributes::Suffix, "deg")
|
||||
->Attribute(AZ::Edit::Attributes::Step, 0.01f)
|
||||
->Attribute(AZ::Edit::Attributes::Min, -AZ::RadToDeg(AZ::Constants::TwoPi))
|
||||
->Attribute(AZ::Edit::Attributes::Max, AZ::RadToDeg(AZ::Constants::TwoPi))
|
||||
->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorAttachmentComponent::OnTargetOffsetChanged)
|
||||
->DataElement(0, &EditorAttachmentComponent::m_scaleOffset, "Scale offset", "Local scale offset from target entity")
|
||||
->Attribute(AZ::Edit::Attributes::Step, 0.1f)
|
||||
->Attribute(AZ::Edit::Attributes::Min, 0.001f)
|
||||
->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorAttachmentComponent::OnTargetOffsetChanged)
|
||||
->DataElement(
|
||||
0, &EditorAttachmentComponent::m_attachedInitially, "Attached initially",
|
||||
"Whether to attach to target upon activation.")
|
||||
->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorAttachmentComponent::OnAttachedInitiallyChanged)
|
||||
->DataElement(
|
||||
AZ::Edit::UIHandlers::ComboBox, &EditorAttachmentComponent::m_scaleSource, "Scaling",
|
||||
"How object scale should be determined. "
|
||||
"Use world scale = Attached object is scaled in world space, Use target entity scale = Attached object adopts "
|
||||
"scale of target entity., Use target bone scale = Attached object adopts scale of target entity/joint.")
|
||||
->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorAttachmentComponent::OnScaleSourceChanged)
|
||||
->EnumAttribute(AttachmentConfiguration::ScaleSource::WorldScale, "Use world scale")
|
||||
->EnumAttribute(AttachmentConfiguration::ScaleSource::TargetEntityScale, "Use target entity scale")
|
||||
->EnumAttribute(AttachmentConfiguration::ScaleSource::TargetBoneScale, "Use target bone scale");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EditorAttachmentComponent::Activate()
|
||||
{
|
||||
Base::Activate();
|
||||
m_boneFollower.Activate(GetEntity(), CreateAttachmentConfiguration(),
|
||||
false); // Entity's don't animate in Editor
|
||||
}
|
||||
|
||||
void EditorAttachmentComponent::Deactivate()
|
||||
{
|
||||
m_boneFollower.Deactivate();
|
||||
Base::Deactivate();
|
||||
}
|
||||
|
||||
void EditorAttachmentComponent::BuildGameEntity(AZ::Entity* gameEntity)
|
||||
{
|
||||
AttachmentComponent* component = gameEntity->CreateComponent<AttachmentComponent>();
|
||||
if (component)
|
||||
{
|
||||
component->m_initialConfiguration = CreateAttachmentConfiguration();
|
||||
}
|
||||
}
|
||||
|
||||
AttachmentConfiguration EditorAttachmentComponent::CreateAttachmentConfiguration() const
|
||||
{
|
||||
AttachmentConfiguration configuration;
|
||||
configuration.m_targetId = m_targetId;
|
||||
configuration.m_targetBoneName = m_targetBoneName;
|
||||
configuration.m_targetOffset = GetTargetOffset();
|
||||
configuration.m_attachedInitially = m_attachedInitially;
|
||||
configuration.m_scaleSource = m_scaleSource;
|
||||
return configuration;
|
||||
}
|
||||
|
||||
AZ::Transform EditorAttachmentComponent::GetTargetOffset() const
|
||||
{
|
||||
AZ::Transform offset = AZ::ConvertEulerDegreesToTransform(m_rotationOffset);
|
||||
offset.SetTranslation(m_positionOffset);
|
||||
offset.MultiplyByScale(m_scaleOffset);
|
||||
return offset;
|
||||
}
|
||||
|
||||
AZStd::vector<AZStd::string> EditorAttachmentComponent::GetTargetBoneOptions() const
|
||||
{
|
||||
AZStd::vector<AZStd::string> names;
|
||||
|
||||
// insert blank entry, so user may choose to bind to NO bone.
|
||||
names.push_back("");
|
||||
|
||||
// track whether currently-set bone is found
|
||||
bool currentTargetBoneFound = false;
|
||||
|
||||
// Get character and iterate over bones
|
||||
AZ::u32 jointCount = 0;
|
||||
LmbrCentral::SkeletalHierarchyRequestBus::EventResult(jointCount, m_targetId, &LmbrCentral::SkeletalHierarchyRequests::GetJointCount);
|
||||
for (AZ::u32 jointIndex = 0; jointIndex < jointCount; ++jointIndex)
|
||||
{
|
||||
const char* name = nullptr;
|
||||
LmbrCentral::SkeletalHierarchyRequestBus::EventResult(name, m_targetId, &LmbrCentral::SkeletalHierarchyRequests::GetJointNameByIndex, jointIndex);
|
||||
if (name)
|
||||
{
|
||||
names.push_back(name);
|
||||
|
||||
if (!currentTargetBoneFound)
|
||||
{
|
||||
currentTargetBoneFound = (m_targetBoneName == names.back());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we never found currently-set bone name,
|
||||
// stick it at top of list, just in case user wants to keep it anyway
|
||||
if (!currentTargetBoneFound && !m_targetBoneName.empty())
|
||||
{
|
||||
names.insert(names.begin(), m_targetBoneName);
|
||||
}
|
||||
|
||||
return names;
|
||||
}
|
||||
|
||||
AZ::u32 EditorAttachmentComponent::OnTargetIdChanged()
|
||||
{
|
||||
// Warn about bad setups (it won't crash, but it's nice to handle this early)
|
||||
if (m_targetId == GetEntityId())
|
||||
{
|
||||
AZ_Warning(GetEntity()->GetName().c_str(), false, "AttachmentComponent cannot target self.") m_targetId.SetInvalid();
|
||||
}
|
||||
|
||||
// Warn about children attaching to a parent
|
||||
AZ::EntityId parentOfTarget;
|
||||
AZ::TransformBus::EventResult(parentOfTarget, m_targetId, &AZ::TransformBus::Events::GetParentId);
|
||||
while (parentOfTarget.IsValid())
|
||||
{
|
||||
if (parentOfTarget == GetEntityId())
|
||||
{
|
||||
AZ_Warning(
|
||||
GetEntity()->GetName().c_str(), parentOfTarget != GetEntityId(), "AttachmentComponent cannot target child entity");
|
||||
m_targetId.SetInvalid();
|
||||
break;
|
||||
}
|
||||
|
||||
AZ::EntityId currentParentId = parentOfTarget;
|
||||
parentOfTarget.SetInvalid();
|
||||
AZ::TransformBus::EventResult(parentOfTarget, currentParentId, &AZ::TransformBus::Events::GetParentId);
|
||||
}
|
||||
|
||||
AttachOrDetachAsNecessary();
|
||||
|
||||
return AZ::Edit::PropertyRefreshLevels::AttributesAndValues; // refresh bone options
|
||||
}
|
||||
|
||||
AZ::u32 EditorAttachmentComponent::OnTargetBoneChanged()
|
||||
{
|
||||
AttachOrDetachAsNecessary();
|
||||
return AZ::Edit::PropertyRefreshLevels::None;
|
||||
}
|
||||
|
||||
AZ::u32 EditorAttachmentComponent::OnTargetOffsetChanged()
|
||||
{
|
||||
EBUS_EVENT_ID(GetEntityId(), LmbrCentral::AttachmentComponentRequestBus, SetAttachmentOffset, GetTargetOffset());
|
||||
return AZ::Edit::PropertyRefreshLevels::None;
|
||||
}
|
||||
|
||||
AZ::u32 EditorAttachmentComponent::OnAttachedInitiallyChanged()
|
||||
{
|
||||
AttachOrDetachAsNecessary();
|
||||
return AZ::Edit::PropertyRefreshLevels::None;
|
||||
}
|
||||
|
||||
AZ::u32 EditorAttachmentComponent::OnScaleSourceChanged()
|
||||
{
|
||||
m_boneFollower.Deactivate();
|
||||
m_boneFollower.Activate(GetEntity(), CreateAttachmentConfiguration(), false);
|
||||
return AZ::Edit::PropertyRefreshLevels::None;
|
||||
}
|
||||
|
||||
void EditorAttachmentComponent::AttachOrDetachAsNecessary()
|
||||
{
|
||||
if (m_attachedInitially && m_targetId.IsValid())
|
||||
{
|
||||
EBUS_EVENT_ID(
|
||||
GetEntityId(), LmbrCentral::AttachmentComponentRequestBus, Attach, m_targetId, m_targetBoneName.c_str(), GetTargetOffset());
|
||||
}
|
||||
else
|
||||
{
|
||||
EBUS_EVENT_ID(GetEntityId(), LmbrCentral::AttachmentComponentRequestBus, Detach);
|
||||
}
|
||||
}
|
||||
} // namespace Render
|
||||
} // namespace AZ
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* 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 <AzToolsFramework/ToolsComponents/EditorComponentBase.h>
|
||||
#include "AttachmentComponent.h"
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace Render
|
||||
{
|
||||
/*!
|
||||
* In-editor attachment component.
|
||||
* \ref AttachmentComponent
|
||||
*/
|
||||
class EditorAttachmentComponent
|
||||
: public AzToolsFramework::Components::EditorComponentBase
|
||||
{
|
||||
private:
|
||||
using Base = AzToolsFramework::Components::EditorComponentBase;
|
||||
public:
|
||||
AZ_COMPONENT(EditorAttachmentComponent, "{DA6072FD-E696-47D8-81D9-1F77D3464200}", Base);
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
|
||||
{
|
||||
AttachmentComponent::GetProvidedServices(provided);
|
||||
}
|
||||
|
||||
static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
|
||||
{
|
||||
AttachmentComponent::GetIncompatibleServices(incompatible);
|
||||
}
|
||||
|
||||
static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required)
|
||||
{
|
||||
AttachmentComponent::GetRequiredServices(required);
|
||||
}
|
||||
|
||||
~EditorAttachmentComponent() override = default;
|
||||
void BuildGameEntity(AZ::Entity* gameEntity) override;
|
||||
|
||||
protected:
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// AZ::Component interface implementation
|
||||
void Activate() override;
|
||||
void Deactivate() override;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AZ::u32 OnTargetIdChanged();
|
||||
AZ::u32 OnTargetBoneChanged();
|
||||
AZ::u32 OnTargetOffsetChanged();
|
||||
AZ::u32 OnAttachedInitiallyChanged();
|
||||
AZ::u32 OnScaleSourceChanged();
|
||||
|
||||
//! Invoked when an attachment property changes
|
||||
void AttachOrDetachAsNecessary();
|
||||
|
||||
//! For populating ComboBox
|
||||
AZStd::vector<AZStd::string> GetTargetBoneOptions() const;
|
||||
|
||||
//! Create runtime configuration from editor configuration
|
||||
AttachmentConfiguration CreateAttachmentConfiguration() const;
|
||||
|
||||
//! Create AZ::Transform from position and rotation
|
||||
AZ::Transform GetTargetOffset() const;
|
||||
|
||||
//! Attach to this entity.
|
||||
AZ::EntityId m_targetId;
|
||||
|
||||
//! Attach to this bone on target entity.
|
||||
AZStd::string m_targetBoneName;
|
||||
|
||||
//! Offset from target bone's position.
|
||||
AZ::Vector3 m_positionOffset = AZ::Vector3::CreateZero();
|
||||
|
||||
//! Offset from target bone's rotation.
|
||||
AZ::Vector3 m_rotationOffset = AZ::Vector3::CreateZero();
|
||||
|
||||
//! Offset from target entity's scale.
|
||||
AZ::Vector3 m_scaleOffset = AZ::Vector3::CreateOne();
|
||||
|
||||
//! Observe scale information from the specified source.
|
||||
AttachmentConfiguration::ScaleSource m_scaleSource = AttachmentConfiguration::ScaleSource::WorldScale;
|
||||
|
||||
//! Whether to attach to target upon activation.
|
||||
//! If false, the entity remains detached until Attach() is called.
|
||||
bool m_attachedInitially = true;
|
||||
|
||||
//! Implements actual attachment functionality
|
||||
AZ::Render::BoneFollower m_boneFollower;
|
||||
};
|
||||
} // namespace Render
|
||||
} // namespace AZ
|
||||
+1
-1
@@ -112,7 +112,7 @@ namespace AZ
|
||||
|
||||
bool AreaLightComponentConfig::SupportsShadows() const
|
||||
{
|
||||
return m_shapeType == AZ_CRC_CE("DiskShape");
|
||||
return m_lightType == LightType::SpotDisk || m_lightType == LightType::Sphere;
|
||||
}
|
||||
|
||||
bool AreaLightComponentConfig::ShadowsDisabled() const
|
||||
|
||||
+1
@@ -121,6 +121,7 @@ namespace AZ
|
||||
void DirectionalLightComponentController::GetIncompatibleServices(ComponentDescriptor::DependencyArrayType& incompatible)
|
||||
{
|
||||
incompatible.push_back(AZ_CRC("DirectionalLightService", 0x5270619f));
|
||||
incompatible.push_back(AZ_CRC_CE("NonUniformScaleComponent"));
|
||||
}
|
||||
|
||||
void DirectionalLightComponentController::GetProvidedServices(ComponentDescriptor::DependencyArrayType& provided)
|
||||
|
||||
+17
-10
@@ -93,7 +93,7 @@ namespace AZ::Render
|
||||
else
|
||||
{
|
||||
debugDisplay.DrawWireDisk(Vector3::CreateZero(), Vector3::CreateAxisZ(), radius);
|
||||
debugDisplay.DrawArc(Vector3::CreateZero(), radius, 90.0f, 180.0f, -3.0f, 0);
|
||||
debugDisplay.DrawArc(Vector3::CreateZero(), radius, 270.0f, 180.0f, 3.0f, 0);
|
||||
debugDisplay.DrawArc(Vector3::CreateZero(), radius, 0.0f, 180.0f, 3.0f, 1);
|
||||
}
|
||||
debugDisplay.PopMatrix();
|
||||
@@ -103,12 +103,15 @@ namespace AZ::Render
|
||||
void DiskLightDelegate::SetEnableShutters(bool enabled)
|
||||
{
|
||||
Base::SetEnableShutters(enabled);
|
||||
GetFeatureProcessor()->SetConstrainToConeLight(GetLightHandle(), true);
|
||||
if (GetLightHandle().IsValid())
|
||||
{
|
||||
GetFeatureProcessor()->SetConstrainToConeLight(GetLightHandle(), true);
|
||||
}
|
||||
}
|
||||
|
||||
void DiskLightDelegate::SetShutterAngles(float innerAngleDegrees, float outerAngleDegrees)
|
||||
{
|
||||
if (GetShuttersEnabled())
|
||||
if (GetShuttersEnabled() && GetLightHandle().IsValid())
|
||||
{
|
||||
GetFeatureProcessor()->SetConeAngles(GetLightHandle(), DegToRad(innerAngleDegrees), DegToRad(outerAngleDegrees));
|
||||
}
|
||||
@@ -117,12 +120,16 @@ namespace AZ::Render
|
||||
void DiskLightDelegate::SetEnableShadow(bool enabled)
|
||||
{
|
||||
Base::SetEnableShadow(enabled);
|
||||
GetFeatureProcessor()->SetShadowsEnabled(GetLightHandle(), enabled);
|
||||
|
||||
if (GetLightHandle().IsValid())
|
||||
{
|
||||
GetFeatureProcessor()->SetShadowsEnabled(GetLightHandle(), enabled);
|
||||
}
|
||||
}
|
||||
|
||||
void DiskLightDelegate::SetShadowmapMaxSize(ShadowmapSize size)
|
||||
{
|
||||
if (GetShadowsEnabled())
|
||||
if (GetShadowsEnabled() && GetLightHandle().IsValid())
|
||||
{
|
||||
GetFeatureProcessor()->SetShadowmapMaxResolution(GetLightHandle(), size);
|
||||
}
|
||||
@@ -130,7 +137,7 @@ namespace AZ::Render
|
||||
|
||||
void DiskLightDelegate::SetShadowFilterMethod(ShadowFilterMethod method)
|
||||
{
|
||||
if (GetShadowsEnabled())
|
||||
if (GetShadowsEnabled() && GetLightHandle().IsValid())
|
||||
{
|
||||
GetFeatureProcessor()->SetShadowFilterMethod(GetLightHandle(), method);
|
||||
}
|
||||
@@ -138,7 +145,7 @@ namespace AZ::Render
|
||||
|
||||
void DiskLightDelegate::SetSofteningBoundaryWidthAngle(float widthInDegrees)
|
||||
{
|
||||
if (GetShadowsEnabled())
|
||||
if (GetShadowsEnabled() && GetLightHandle().IsValid())
|
||||
{
|
||||
GetFeatureProcessor()->SetSofteningBoundaryWidthAngle(GetLightHandle(), DegToRad(widthInDegrees));
|
||||
}
|
||||
@@ -146,7 +153,7 @@ namespace AZ::Render
|
||||
|
||||
void DiskLightDelegate::SetPredictionSampleCount(uint32_t count)
|
||||
{
|
||||
if (GetShadowsEnabled())
|
||||
if (GetShadowsEnabled() && GetLightHandle().IsValid())
|
||||
{
|
||||
GetFeatureProcessor()->SetPredictionSampleCount(GetLightHandle(), count);
|
||||
}
|
||||
@@ -154,7 +161,7 @@ namespace AZ::Render
|
||||
|
||||
void DiskLightDelegate::SetFilteringSampleCount(uint32_t count)
|
||||
{
|
||||
if (GetShadowsEnabled())
|
||||
if (GetShadowsEnabled() && GetLightHandle().IsValid())
|
||||
{
|
||||
GetFeatureProcessor()->SetFilteringSampleCount(GetLightHandle(), count);
|
||||
}
|
||||
@@ -162,7 +169,7 @@ namespace AZ::Render
|
||||
|
||||
void DiskLightDelegate::SetPcfMethod(PcfMethod method)
|
||||
{
|
||||
if (GetShadowsEnabled())
|
||||
if (GetShadowsEnabled() && GetLightHandle().IsValid())
|
||||
{
|
||||
GetFeatureProcessor()->SetPcfMethod(GetLightHandle(), method);
|
||||
}
|
||||
|
||||
+6
-5
@@ -49,8 +49,8 @@ namespace AZ
|
||||
"Light", "A light which emits from a point or goemetric shape.")
|
||||
->ClassElement(Edit::ClassElements::EditorData, "")
|
||||
->Attribute(Edit::Attributes::Category, "Atom")
|
||||
->Attribute(Edit::Attributes::Icon, "Editor/Icons/Components/Component_Placeholder.svg")
|
||||
->Attribute(Edit::Attributes::ViewportIcon, "editor/icons/components/viewport/component_placeholder.png")
|
||||
->Attribute(Edit::Attributes::Icon, "Icons/Components/Component_Placeholder.svg")
|
||||
->Attribute(Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/Component_Placeholder.png")
|
||||
->Attribute(Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c))
|
||||
->Attribute(Edit::Attributes::AutoExpand, true)
|
||||
->Attribute(Edit::Attributes::HelpPageURL, "https://docs.aws.amazon.com/lumberyard/latest/userguide/component-light.html")
|
||||
@@ -173,10 +173,10 @@ namespace AZ
|
||||
->DataElement(
|
||||
Edit::UIHandlers::ComboBox, &AreaLightComponentConfig::m_pcfMethod, "Pcf method",
|
||||
"Type of PCF to use.\n"
|
||||
" Boundary search: do several taps to first determine if we are on a shadow boundary\n"
|
||||
" Bicubic: a smooth, fixed-size kernel \n")
|
||||
->EnumAttribute(PcfMethod::BoundarySearch, "Boundary search")
|
||||
" Bicubic: a smooth, fixed-size kernel \n"
|
||||
" Boundary search: do several taps to first determine if we are on a shadow boundary\n")
|
||||
->EnumAttribute(PcfMethod::Bicubic, "Bicubic")
|
||||
->EnumAttribute(PcfMethod::BoundarySearch, "Boundary search")
|
||||
->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly)
|
||||
->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShadows)
|
||||
->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::IsShadowPcfDisabled);
|
||||
@@ -336,6 +336,7 @@ namespace AZ
|
||||
bool needsFullRefresh = HandleLightTypeChange();
|
||||
|
||||
LmbrCentral::EditorShapeComponentRequestsBus::Event(GetEntityId(), &LmbrCentral::EditorShapeComponentRequests::SetShapeColor, m_controller.m_configuration.m_color);
|
||||
LmbrCentral::EditorShapeComponentRequestsBus::Event(GetEntityId(), &LmbrCentral::EditorShapeComponentRequests::SetShapeWireframeColor, m_controller.m_configuration.m_color);
|
||||
|
||||
// If photometric unit changes, convert the intensities so the actual intensity doesn't change.
|
||||
m_controller.ConvertToIntensityMode(m_controller.m_configuration.m_intensityMode);
|
||||
|
||||
+5
-5
@@ -44,8 +44,8 @@ namespace AZ
|
||||
"Directional Light", "A directional light to cast a shadow of meshes onto meshes.")
|
||||
->ClassElement(Edit::ClassElements::EditorData, "")
|
||||
->Attribute(Edit::Attributes::Category, "Atom")
|
||||
->Attribute(AZ::Edit::Attributes::Icon, "Editor/Icons/Components/Component_Placeholder.svg") // [GFX TODO][ATOM-1998] create icons.
|
||||
->Attribute(AZ::Edit::Attributes::ViewportIcon, "editor/icons/components/viewport/component_placeholder.png") // [GFX TODO][ATOM-1998] create icons.
|
||||
->Attribute(AZ::Edit::Attributes::Icon, "Icons/Components/Component_Placeholder.svg") // [GFX TODO][ATOM-1998] create icons.
|
||||
->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/Component_Placeholder.png") // [GFX TODO][ATOM-1998] create icons.
|
||||
->Attribute(Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c))
|
||||
->Attribute(Edit::Attributes::AutoExpand, true)
|
||||
->Attribute(Edit::Attributes::HelpPageURL, "https://") // [GFX TODO][ATOM-1998] create page
|
||||
@@ -163,10 +163,10 @@ namespace AZ
|
||||
->DataElement(
|
||||
Edit::UIHandlers::ComboBox, &DirectionalLightComponentConfig::m_pcfMethod, "Pcf Method",
|
||||
"Type of Pcf to use.\n"
|
||||
" Boundary search: do several taps to first determine if we are on a shadow boundary\n"
|
||||
" Bicubic: a smooth, fixed-size kernel \n")
|
||||
->EnumAttribute(PcfMethod::BoundarySearch, "Boundary Search")
|
||||
" Bicubic: a smooth, fixed-size kernel \n"
|
||||
" Boundary search: do several taps to first determine if we are on a shadow boundary\n")
|
||||
->EnumAttribute(PcfMethod::Bicubic, "Bicubic")
|
||||
->EnumAttribute(PcfMethod::BoundarySearch, "Boundary Search")
|
||||
->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly)
|
||||
->Attribute(Edit::Attributes::ReadOnly, &DirectionalLightComponentConfig::IsShadowPcfDisabled);
|
||||
;
|
||||
|
||||
@@ -101,6 +101,7 @@ namespace AZ
|
||||
template <typename FeatureProcessorType>
|
||||
void LightDelegateBase<FeatureProcessorType>::OnShapeChanged(ShapeChangeReasons changeReason)
|
||||
{
|
||||
AZ_Assert(m_shapeBus, "OnShapeChanged called without a shape bus present.");
|
||||
if (changeReason == ShapeChangeReasons::TransformChanged)
|
||||
{
|
||||
AZ::Aabb aabb; // unused, but required for GetTransformAndLocalBounds()
|
||||
@@ -133,7 +134,11 @@ namespace AZ
|
||||
{
|
||||
// now visible, acquire light handle and update values.
|
||||
m_lightHandle = m_featureProcessor->AcquireLight();
|
||||
OnShapeChanged(ShapeChangeReasons::TransformChanged);
|
||||
if (m_shapeBus)
|
||||
{
|
||||
// For lights that get their transform from the shape bus, force an OnShapeChanged to update the transform.
|
||||
OnShapeChanged(ShapeChangeReasons::TransformChanged);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+8
-2
@@ -23,7 +23,10 @@ namespace AZ
|
||||
: LightDelegateBase<SimplePointLightFeatureProcessorInterface>(entityId, isVisible)
|
||||
{
|
||||
InitBase(entityId);
|
||||
GetFeatureProcessor()->SetPosition(GetLightHandle(), GetTransform().GetTranslation());
|
||||
if (GetLightHandle().IsValid())
|
||||
{
|
||||
GetFeatureProcessor()->SetPosition(GetLightHandle(), GetTransform().GetTranslation());
|
||||
}
|
||||
}
|
||||
float SimplePointLightDelegate::CalculateAttenuationRadius(float lightThreshold) const
|
||||
{
|
||||
@@ -39,7 +42,10 @@ namespace AZ
|
||||
|
||||
void SimplePointLightDelegate::HandleShapeChanged()
|
||||
{
|
||||
GetFeatureProcessor()->SetPosition(GetLightHandle(), GetTransform().GetTranslation());
|
||||
if (GetLightHandle().IsValid())
|
||||
{
|
||||
GetFeatureProcessor()->SetPosition(GetLightHandle(), GetTransform().GetTranslation());
|
||||
}
|
||||
}
|
||||
|
||||
void SimplePointLightDelegate::DrawDebugDisplay(const Transform& transform, const Color& color, AzFramework::DebugDisplayRequests& debugDisplay, bool isSelected) const
|
||||
|
||||
+9
-3
@@ -24,8 +24,11 @@ namespace AZ::Render
|
||||
|
||||
void SimpleSpotLightDelegate::HandleShapeChanged()
|
||||
{
|
||||
GetFeatureProcessor()->SetPosition(GetLightHandle(), GetTransform().GetTranslation());
|
||||
GetFeatureProcessor()->SetDirection(GetLightHandle(), GetTransform().GetBasisZ());
|
||||
if (GetLightHandle().IsValid())
|
||||
{
|
||||
GetFeatureProcessor()->SetPosition(GetLightHandle(), GetTransform().GetTranslation());
|
||||
GetFeatureProcessor()->SetDirection(GetLightHandle(), GetTransform().GetBasisZ());
|
||||
}
|
||||
}
|
||||
|
||||
float SimpleSpotLightDelegate::CalculateAttenuationRadius(float lightThreshold) const
|
||||
@@ -42,7 +45,10 @@ namespace AZ::Render
|
||||
|
||||
void SimpleSpotLightDelegate::SetShutterAngles(float innerAngleDegrees, float outerAngleDegrees)
|
||||
{
|
||||
GetFeatureProcessor()->SetConeAngles(GetLightHandle(), DegToRad(innerAngleDegrees), DegToRad(outerAngleDegrees));
|
||||
if (GetLightHandle().IsValid())
|
||||
{
|
||||
GetFeatureProcessor()->SetConeAngles(GetLightHandle(), DegToRad(innerAngleDegrees), DegToRad(outerAngleDegrees));
|
||||
}
|
||||
}
|
||||
|
||||
void SimpleSpotLightDelegate::DrawDebugDisplay(const Transform& transform, const Color& /*color*/, AzFramework::DebugDisplayRequests& debugDisplay, bool isSelected) const
|
||||
|
||||
@@ -63,5 +63,64 @@ namespace AZ
|
||||
debugDisplay.DrawWireSphere(transform.GetTranslation(), CalculateAttenuationRadius(AreaLightComponentConfig::CutoffIntensity));
|
||||
}
|
||||
}
|
||||
|
||||
void SphereLightDelegate::SetEnableShadow(bool enabled)
|
||||
{
|
||||
Base::SetEnableShadow(enabled);
|
||||
|
||||
if (GetLightHandle().IsValid())
|
||||
{
|
||||
GetFeatureProcessor()->SetShadowsEnabled(GetLightHandle(), enabled);
|
||||
}
|
||||
}
|
||||
|
||||
void SphereLightDelegate::SetShadowmapMaxSize(ShadowmapSize size)
|
||||
{
|
||||
if (GetShadowsEnabled() && GetLightHandle().IsValid())
|
||||
{
|
||||
GetFeatureProcessor()->SetShadowmapMaxResolution(GetLightHandle(), size);
|
||||
}
|
||||
}
|
||||
|
||||
void SphereLightDelegate::SetShadowFilterMethod(ShadowFilterMethod method)
|
||||
{
|
||||
if (GetShadowsEnabled() && GetLightHandle().IsValid())
|
||||
{
|
||||
GetFeatureProcessor()->SetShadowFilterMethod(GetLightHandle(), method);
|
||||
}
|
||||
}
|
||||
|
||||
void SphereLightDelegate::SetSofteningBoundaryWidthAngle(float widthInDegrees)
|
||||
{
|
||||
if (GetShadowsEnabled() && GetLightHandle().IsValid())
|
||||
{
|
||||
GetFeatureProcessor()->SetSofteningBoundaryWidthAngle(GetLightHandle(), DegToRad(widthInDegrees));
|
||||
}
|
||||
}
|
||||
|
||||
void SphereLightDelegate::SetPredictionSampleCount(uint32_t count)
|
||||
{
|
||||
if (GetShadowsEnabled() && GetLightHandle().IsValid())
|
||||
{
|
||||
GetFeatureProcessor()->SetPredictionSampleCount(GetLightHandle(), count);
|
||||
}
|
||||
}
|
||||
|
||||
void SphereLightDelegate::SetFilteringSampleCount(uint32_t count)
|
||||
{
|
||||
if (GetShadowsEnabled() && GetLightHandle().IsValid())
|
||||
{
|
||||
GetFeatureProcessor()->SetFilteringSampleCount(GetLightHandle(), count);
|
||||
}
|
||||
}
|
||||
|
||||
void SphereLightDelegate::SetPcfMethod(PcfMethod method)
|
||||
{
|
||||
if (GetShadowsEnabled() && GetLightHandle().IsValid())
|
||||
{
|
||||
GetFeatureProcessor()->SetPcfMethod(GetLightHandle(), method);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Render
|
||||
} // namespace AZ
|
||||
|
||||
@@ -24,6 +24,8 @@ namespace AZ
|
||||
class SphereLightDelegate final
|
||||
: public LightDelegateBase<PointLightFeatureProcessorInterface>
|
||||
{
|
||||
using Base = LightDelegateBase<PointLightFeatureProcessorInterface>;
|
||||
|
||||
public:
|
||||
SphereLightDelegate(LmbrCentral::SphereShapeComponentRequests* shapeBus, EntityId entityId, bool isVisible);
|
||||
|
||||
@@ -32,6 +34,13 @@ namespace AZ
|
||||
void DrawDebugDisplay(const Transform& transform, const Color& color, AzFramework::DebugDisplayRequests& debugDisplay, bool isSelected) const override;
|
||||
float GetSurfaceArea() const override;
|
||||
float GetEffectiveSolidAngle() const override { return PhotometricValue::OmnidirectionalSteradians; }
|
||||
void SetEnableShadow(bool enabled) override;
|
||||
void SetShadowmapMaxSize(ShadowmapSize size) override;
|
||||
void SetShadowFilterMethod(ShadowFilterMethod method) override;
|
||||
void SetSofteningBoundaryWidthAngle(float widthInDegrees) override;
|
||||
void SetPredictionSampleCount(uint32_t count) override;
|
||||
void SetFilteringSampleCount(uint32_t count) override;
|
||||
void SetPcfMethod(PcfMethod method) override;
|
||||
|
||||
private:
|
||||
|
||||
|
||||
+24
-1
@@ -75,6 +75,12 @@ namespace AZ
|
||||
incompatible.push_back(AZ_CRC_CE("DecalService"));
|
||||
}
|
||||
|
||||
void DecalComponentController::GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent)
|
||||
{
|
||||
dependent.push_back(AZ_CRC_CE("TransformService"));
|
||||
dependent.push_back(AZ_CRC_CE("NonUniformScaleService"));
|
||||
}
|
||||
|
||||
DecalComponentController::DecalComponentController(const DecalComponentConfig& config)
|
||||
: m_configuration(config)
|
||||
{
|
||||
@@ -90,6 +96,11 @@ namespace AZ
|
||||
m_handle = m_featureProcessor->AcquireDecal();
|
||||
}
|
||||
|
||||
m_cachedNonUniformScale = AZ::Vector3::CreateOne();
|
||||
AZ::NonUniformScaleRequestBus::EventResult(m_cachedNonUniformScale, m_entityId, &AZ::NonUniformScaleRequests::GetScale);
|
||||
AZ::NonUniformScaleRequestBus::Event(m_entityId, &AZ::NonUniformScaleRequests::RegisterScaleChangedEvent,
|
||||
m_nonUniformScaleChangedHandler);
|
||||
|
||||
AZ::Transform local, world;
|
||||
AZ::TransformBus::Event(entityId, &AZ::TransformBus::Events::GetLocalAndWorld, local, world);
|
||||
OnTransformChanged(local, world);
|
||||
@@ -103,6 +114,7 @@ namespace AZ
|
||||
{
|
||||
DecalRequestBus::Handler::BusDisconnect(m_entityId);
|
||||
TransformNotificationBus::Handler::BusDisconnect(m_entityId);
|
||||
m_nonUniformScaleChangedHandler.Disconnect();
|
||||
if (m_featureProcessor)
|
||||
{
|
||||
m_featureProcessor->ReleaseDecal(m_handle);
|
||||
@@ -125,7 +137,18 @@ namespace AZ
|
||||
{
|
||||
if (m_featureProcessor)
|
||||
{
|
||||
m_featureProcessor->SetDecalTransform(m_handle, world);
|
||||
m_featureProcessor->SetDecalTransform(m_handle, world, m_cachedNonUniformScale);
|
||||
}
|
||||
}
|
||||
|
||||
void DecalComponentController::HandleNonUniformScaleChange(const AZ::Vector3& nonUniformScale)
|
||||
{
|
||||
m_cachedNonUniformScale = nonUniformScale;
|
||||
if (m_featureProcessor)
|
||||
{
|
||||
AZ::Transform world = AZ::Transform::CreateIdentity();
|
||||
AZ::TransformBus::EventResult(world, m_entityId, &AZ::TransformBus::Events::GetWorldTM);
|
||||
m_featureProcessor->SetDecalTransform(m_handle, world, nonUniformScale);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
#include <AzCore/Component/Component.h>
|
||||
#include <AzCore/Component/TransformBus.h>
|
||||
#include <AzCore/Component/NonUniformScaleBus.h>
|
||||
#include <AtomLyIntegration/CommonFeatures/Decals/DecalBus.h>
|
||||
#include <AtomLyIntegration/CommonFeatures/Decals/DecalComponentConfig.h>
|
||||
#include <Atom/Feature/Decals/DecalFeatureProcessorInterface.h>
|
||||
@@ -33,6 +34,7 @@ namespace AZ
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided);
|
||||
static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible);
|
||||
static void GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent);
|
||||
|
||||
DecalComponentController() = default;
|
||||
DecalComponentController(const DecalComponentConfig& config);
|
||||
@@ -64,11 +66,18 @@ namespace AZ
|
||||
void OpacityChanged();
|
||||
void SortKeyChanged();
|
||||
void MaterialChanged();
|
||||
void HandleNonUniformScaleChange(const AZ::Vector3& nonUniformScale);
|
||||
|
||||
DecalComponentConfig m_configuration;
|
||||
DecalFeatureProcessorInterface* m_featureProcessor = nullptr;
|
||||
DecalFeatureProcessorInterface::DecalHandle m_handle;
|
||||
EntityId m_entityId;
|
||||
AZ::Vector3 m_cachedNonUniformScale = AZ::Vector3::CreateOne();
|
||||
|
||||
AZ::NonUniformScaleChangedEvent::Handler m_nonUniformScaleChangedHandler
|
||||
{
|
||||
[&](const AZ::Vector3& nonUniformScale) { HandleNonUniformScaleChange(nonUniformScale); }
|
||||
};
|
||||
};
|
||||
} // namespace Render
|
||||
} // AZ namespace
|
||||
|
||||
@@ -39,8 +39,8 @@ namespace AZ
|
||||
"Decal (Atom)", "The Decal component allows an entity to project a texture or material onto a mesh")
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::Category, "Atom")
|
||||
->Attribute(AZ::Edit::Attributes::Icon, "Editor/Icons/Components/Component_Placeholder.svg")
|
||||
->Attribute(AZ::Edit::Attributes::ViewportIcon, "editor/icons/components/viewport/component_placeholder.png")
|
||||
->Attribute(AZ::Edit::Attributes::Icon, "Icons/Components/Component_Placeholder.svg")
|
||||
->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/Component_Placeholder.png")
|
||||
->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC_CE("Game"))
|
||||
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
||||
->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://docs.aws.amazon.com/lumberyard/latest/userguide/component-decal.html")
|
||||
|
||||
+2
-1
@@ -25,7 +25,7 @@
|
||||
#include <AzFramework/Entity/EntityContextBus.h>
|
||||
#include <AzFramework/Entity/EntityContext.h>
|
||||
#include <AzFramework/Scene/Scene.h>
|
||||
#include <AzFramework/Scene/SceneSystemBus.h>
|
||||
#include <AzFramework/Scene/SceneSystemInterface.h>
|
||||
|
||||
#include <AzCore/RTTI/BehaviorContext.h>
|
||||
|
||||
@@ -73,6 +73,7 @@ namespace AZ
|
||||
void DiffuseProbeGridComponentController::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
|
||||
{
|
||||
incompatible.push_back(AZ_CRC("DiffuseProbeGridService", 0x63d32042));
|
||||
incompatible.push_back(AZ_CRC_CE("NonUniformScaleService"));
|
||||
}
|
||||
|
||||
void DiffuseProbeGridComponentController::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required)
|
||||
|
||||
+2
-2
@@ -43,8 +43,8 @@ namespace AZ
|
||||
"Diffuse Probe Grid", "The DiffuseProbeGrid component generates a grid of diffuse light probes for global illumination")
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::Category, "Atom")
|
||||
->Attribute(AZ::Edit::Attributes::Icon, "Editor/Icons/Components/Component_Placeholder.svg")
|
||||
->Attribute(AZ::Edit::Attributes::ViewportIcon, "editor/icons/components/viewport/component_placeholder.png")
|
||||
->Attribute(AZ::Edit::Attributes::Icon, "Icons/Components/Component_Placeholder.svg")
|
||||
->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/Component_Placeholder.png")
|
||||
->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c))
|
||||
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
||||
->Attribute(AZ::Edit::Attributes::PrimaryAssetType, AZ::AzTypeInfo<RPI::ModelAsset>::Uuid())
|
||||
|
||||
@@ -34,8 +34,8 @@ namespace AZ
|
||||
"Grid", "Adds grid to the scene")
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::Category, "Atom")
|
||||
->Attribute(AZ::Edit::Attributes::Icon, "Editor/Icons/Components/Component_Placeholder.svg")
|
||||
->Attribute(AZ::Edit::Attributes::ViewportIcon, "editor/icons/components/viewport/component_placeholder.png")
|
||||
->Attribute(AZ::Edit::Attributes::Icon, "Icons/Components/Component_Placeholder.svg")
|
||||
->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/Component_Placeholder.png")
|
||||
->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c))
|
||||
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
||||
->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://docs.aws.amazon.com/lumberyard/latest/userguide/component-grid.html")
|
||||
|
||||
+2
-2
@@ -34,8 +34,8 @@ namespace AZ
|
||||
"Global Skylight (IBL)", "Adds image based illumination to the scene")
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::Category, "Atom")
|
||||
->Attribute(AZ::Edit::Attributes::Icon, "Editor/Icons/Components/Component_Placeholder.svg")
|
||||
->Attribute(AZ::Edit::Attributes::ViewportIcon, "editor/icons/components/viewport/component_placeholder.png")
|
||||
->Attribute(AZ::Edit::Attributes::Icon, "Icons/Components/Component_Placeholder.svg")
|
||||
->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/Component_Placeholder.png")
|
||||
->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c))
|
||||
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
||||
->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://docs.aws.amazon.com/lumberyard/latest/userguide/component-imagebasedlight.html")
|
||||
|
||||
+2
-2
@@ -137,8 +137,8 @@ namespace AZ
|
||||
"Material", "The material component specifies the material to use for this entity")
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::Category, "Atom")
|
||||
->Attribute(AZ::Edit::Attributes::Icon, "Editor/Icons/Components/Component_Placeholder.svg")
|
||||
->Attribute(AZ::Edit::Attributes::ViewportIcon, "editor/icons/components/viewport/component_placeholder.png")
|
||||
->Attribute(AZ::Edit::Attributes::Icon, "Icons/Components/Component_Placeholder.svg")
|
||||
->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/Component_Placeholder.png")
|
||||
->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c))
|
||||
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
||||
->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://docs.aws.amazon.com/lumberyard/latest/userguide/component-material.html")
|
||||
|
||||
+17
-3
@@ -203,6 +203,7 @@ namespace AZ
|
||||
propertyConfig.m_id = AZ::RPI::MaterialPropertyId(groupNameId, shaderInputStr).GetCStr();
|
||||
propertyConfig.m_nameId = shaderInputStr;
|
||||
propertyConfig.m_displayName = shaderInputStr;
|
||||
propertyConfig.m_groupName = groupDisplayName;
|
||||
propertyConfig.m_description = shaderInputStr;
|
||||
propertyConfig.m_defaultValue = uvName;
|
||||
propertyConfig.m_originalValue = uvName;
|
||||
@@ -212,7 +213,11 @@ namespace AZ
|
||||
}
|
||||
|
||||
// Passing in same group as main and comparison instance to enable custom value comparison for highlighting modified properties
|
||||
auto propertyGroupWidget = new AtomToolsFramework::InspectorPropertyGroupWidget(&group, &group, group.TYPEINFO_Uuid(), this, this,
|
||||
const AZ::Crc32 saveStateKey(AZStd::string::format(
|
||||
"MaterialPropertyInspector::PropertyGroup::%s::%s", m_materialAssetId.ToString<AZStd::string>().c_str(),
|
||||
groupNameId.c_str()));
|
||||
auto propertyGroupWidget = new AtomToolsFramework::InspectorPropertyGroupWidget(
|
||||
&group, &group, group.TYPEINFO_Uuid(), this, this, saveStateKey,
|
||||
[this](const AzToolsFramework::InstanceDataNode* source, const AzToolsFramework::InstanceDataNode* target) {
|
||||
AZ_UNUSED(source);
|
||||
const AtomToolsFramework::DynamicProperty* property = AtomToolsFramework::FindDynamicPropertyForInstanceDataNode(target);
|
||||
@@ -244,10 +249,15 @@ namespace AZ
|
||||
for (const auto& propertyDefinition : propertyListItr->second)
|
||||
{
|
||||
AtomToolsFramework::DynamicPropertyConfig propertyConfig;
|
||||
|
||||
// Assign id before conversion so it can be used in dynamic description
|
||||
propertyConfig.m_id = AZ::RPI::MaterialPropertyId(groupNameId, propertyDefinition.m_nameId).GetFullName();
|
||||
|
||||
AtomToolsFramework::ConvertToPropertyConfig(propertyConfig, propertyDefinition);
|
||||
|
||||
propertyConfig.m_id = AZ::RPI::MaterialPropertyId(groupNameId, propertyDefinition.m_nameId).GetFullName();
|
||||
propertyConfig.m_groupName = groupDisplayName;
|
||||
const auto& propertyIndex = m_editData.m_materialAsset->GetMaterialPropertiesLayout()->FindPropertyIndex(propertyConfig.m_id);
|
||||
propertyConfig.m_showThumbnail = true;
|
||||
propertyConfig.m_defaultValue = AtomToolsFramework::ConvertToEditableType(m_editData.m_materialTypeAsset->GetDefaultPropertyValues()[propertyIndex.GetIndex()]);
|
||||
propertyConfig.m_parentValue = AtomToolsFramework::ConvertToEditableType(m_editData.m_materialTypeAsset->GetDefaultPropertyValues()[propertyIndex.GetIndex()]);
|
||||
propertyConfig.m_originalValue = AtomToolsFramework::ConvertToEditableType(m_editData.m_materialAsset->GetPropertyValues()[propertyIndex.GetIndex()]);
|
||||
@@ -256,7 +266,11 @@ namespace AZ
|
||||
}
|
||||
|
||||
// Passing in same group as main and comparison instance to enable custom value comparison for highlighting modified properties
|
||||
auto propertyGroupWidget = new AtomToolsFramework::InspectorPropertyGroupWidget(&group, &group, group.TYPEINFO_Uuid(), this, this,
|
||||
const AZ::Crc32 saveStateKey(AZStd::string::format(
|
||||
"MaterialPropertyInspector::PropertyGroup::%s::%s", m_materialAssetId.ToString<AZStd::string>().c_str(),
|
||||
groupNameId.c_str()));
|
||||
auto propertyGroupWidget = new AtomToolsFramework::InspectorPropertyGroupWidget(
|
||||
&group, &group, group.TYPEINFO_Uuid(), this, this, saveStateKey,
|
||||
[this](const AzToolsFramework::InstanceDataNode* source, const AzToolsFramework::InstanceDataNode* target) {
|
||||
AZ_UNUSED(source);
|
||||
const AtomToolsFramework::DynamicProperty* property = AtomToolsFramework::FindDynamicPropertyForInstanceDataNode(target);
|
||||
|
||||
+3
-2
@@ -98,7 +98,7 @@ namespace AZ
|
||||
->Attribute(AZ::Edit::Attributes::DefaultAsset, &EditorMaterialComponentSlot::GetDefaultAssetId)
|
||||
->Attribute(AZ::Edit::Attributes::NameLabelOverride, &EditorMaterialComponentSlot::GetLabel)
|
||||
->Attribute(AZ::Edit::Attributes::ShowProductAssetFileName, true)
|
||||
->Attribute("ThumbnailWithDropDown", &EditorMaterialComponentSlot::OpenPopupMenu)
|
||||
->Attribute("ThumbnailCallback", &EditorMaterialComponentSlot::OpenPopupMenu)
|
||||
;
|
||||
}
|
||||
}
|
||||
@@ -269,7 +269,8 @@ namespace AZ
|
||||
|
||||
QAction* action = nullptr;
|
||||
|
||||
menu.addAction("Open Material Editor", [this]() { EditorMaterialSystemComponentRequestBus::Broadcast(&EditorMaterialSystemComponentRequestBus::Events::OpenInMaterialEditor, ""); });
|
||||
action = menu.addAction("Open Material Editor...", [this]() { EditorMaterialSystemComponentRequestBus::Broadcast(&EditorMaterialSystemComponentRequestBus::Events::OpenInMaterialEditor, ""); });
|
||||
action->setVisible(!m_materialAsset.GetId().IsValid());
|
||||
|
||||
action = menu.addAction("Clear", [this]() { Clear(); });
|
||||
action->setEnabled(m_materialAsset.GetId().IsValid() || !m_propertyOverrides.empty() || !m_matModUvOverrides.empty());
|
||||
|
||||
+14
-28
@@ -23,6 +23,8 @@
|
||||
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
|
||||
#include <AzToolsFramework/Thumbnails/ThumbnailContext.h>
|
||||
|
||||
#include <Atom/RHI/Factory.h>
|
||||
|
||||
#include <AtomToolsFramework/Util/Util.h>
|
||||
|
||||
#include <Material/MaterialThumbnail.h>
|
||||
@@ -93,7 +95,6 @@ namespace AZ
|
||||
|
||||
void EditorMaterialSystemComponent::Activate()
|
||||
{
|
||||
AzFramework::TargetManagerClient::Bus::Handler::BusConnect();
|
||||
EditorMaterialSystemComponentRequestBus::Handler::BusConnect();
|
||||
AzFramework::ApplicationLifecycleEvents::Bus::Handler::BusConnect();
|
||||
AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler::BusConnect();
|
||||
@@ -105,7 +106,6 @@ namespace AZ
|
||||
|
||||
void EditorMaterialSystemComponent::Deactivate()
|
||||
{
|
||||
AzFramework::TargetManagerClient::Bus::Handler::BusDisconnect();
|
||||
EditorMaterialSystemComponentRequestBus::Handler::BusDisconnect();
|
||||
AzFramework::ApplicationLifecycleEvents::Bus::Handler::BusDisconnect();
|
||||
AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler::BusDisconnect();
|
||||
@@ -123,36 +123,19 @@ namespace AZ
|
||||
|
||||
void EditorMaterialSystemComponent::OpenInMaterialEditor(const AZStd::string& sourcePath)
|
||||
{
|
||||
if (m_materialEditorTarget.IsValid())
|
||||
{
|
||||
AzFramework::TmMsg openDocumentMsg(AZ_CRC("OpenInMaterialEditor", 0x9f92aac8));
|
||||
openDocumentMsg.AddCustomBlob(sourcePath.c_str(), sourcePath.size() + 1);
|
||||
AzFramework::TargetManager::Bus::Broadcast(&AzFramework::TargetManager::SendTmMessage, m_materialEditorTarget, openDocumentMsg);
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_TracePrintf("MaterialComponent", "Launching Material Editor");
|
||||
AZ_TracePrintf("MaterialComponent", "Launching Material Editor");
|
||||
|
||||
QStringList arguments;
|
||||
arguments.append(sourcePath.c_str());
|
||||
AtomToolsFramework::LaunchTool("MaterialEditor", ".exe", arguments);
|
||||
}
|
||||
}
|
||||
QStringList arguments;
|
||||
arguments.append(sourcePath.c_str());
|
||||
|
||||
void EditorMaterialSystemComponent::TargetJoinedNetwork(AzFramework::TargetInfo info)
|
||||
{
|
||||
if (AZ::StringFunc::Equal(info.GetDisplayName(), "MaterialEditor"))
|
||||
// Use the same RHI as the main editor
|
||||
AZ::Name apiName = AZ::RHI::Factory::Get().GetName();
|
||||
if (!apiName.IsEmpty())
|
||||
{
|
||||
m_materialEditorTarget = info;
|
||||
arguments.append(QString("--rhi=%1").arg(apiName.GetCStr()));
|
||||
}
|
||||
}
|
||||
|
||||
void EditorMaterialSystemComponent::TargetLeftNetwork(AzFramework::TargetInfo info)
|
||||
{
|
||||
if (AZ::StringFunc::Equal(info.GetDisplayName(), "MaterialEditor"))
|
||||
{
|
||||
m_materialEditorTarget = {};
|
||||
}
|
||||
AtomToolsFramework::LaunchTool("MaterialEditor", ".exe", arguments);
|
||||
}
|
||||
|
||||
void EditorMaterialSystemComponent::OnApplicationAboutToStop()
|
||||
@@ -166,7 +149,10 @@ namespace AZ
|
||||
{
|
||||
m_openMaterialEditorAction = new QAction("Material Editor");
|
||||
m_openMaterialEditorAction->setShortcut(QKeySequence(Qt::Key_M));
|
||||
QObject::connect(m_openMaterialEditorAction, &QAction::triggered, m_openMaterialEditorAction, [this]()
|
||||
m_openMaterialEditorAction->setCheckable(false);
|
||||
m_openMaterialEditorAction->setChecked(false);
|
||||
QObject::connect(
|
||||
m_openMaterialEditorAction, &QAction::triggered, m_openMaterialEditorAction, [this]()
|
||||
{
|
||||
OpenInMaterialEditor("");
|
||||
}
|
||||
|
||||
-9
@@ -14,7 +14,6 @@
|
||||
#include <AzCore/Component/Component.h>
|
||||
|
||||
#include <AzFramework/Application/Application.h>
|
||||
#include <AzFramework/TargetManagement/TargetManagementAPI.h>
|
||||
|
||||
#include <AzToolsFramework/Thumbnails/Thumbnail.h>
|
||||
#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
|
||||
@@ -32,7 +31,6 @@ namespace AZ
|
||||
class EditorMaterialSystemComponent
|
||||
: public AZ::Component
|
||||
, private EditorMaterialSystemComponentRequestBus::Handler
|
||||
, private AzFramework::TargetManagerClient::Bus::Handler
|
||||
, private AzFramework::ApplicationLifecycleEvents::Bus::Handler
|
||||
, public AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler
|
||||
, public AzToolsFramework::EditorMenuNotificationBus::Handler
|
||||
@@ -57,10 +55,6 @@ namespace AZ
|
||||
//! EditorMaterialSystemComponentRequestBus::Handler overrides...
|
||||
void OpenInMaterialEditor(const AZStd::string& sourcePath) override;
|
||||
|
||||
//! AzFramework::TargetManagerClient::Bus::Handler overrides...
|
||||
void TargetJoinedNetwork(AzFramework::TargetInfo info) override;
|
||||
void TargetLeftNetwork(AzFramework::TargetInfo info) override;
|
||||
|
||||
// AzFramework::ApplicationLifecycleEvents overrides...
|
||||
void OnApplicationAboutToStop() override;
|
||||
|
||||
@@ -74,9 +68,6 @@ namespace AZ
|
||||
void SetupThumbnails();
|
||||
void TeardownThumbnails();
|
||||
|
||||
// Material Editor target for interprocess communication with MaterialEditor
|
||||
AzFramework::TargetInfo m_materialEditorTarget;
|
||||
|
||||
QAction* m_openMaterialEditorAction = nullptr;
|
||||
|
||||
AZStd::unique_ptr<MaterialBrowserInteractions> m_materialBrowserInteractions;
|
||||
|
||||
@@ -21,13 +21,13 @@ namespace AZ
|
||||
{
|
||||
namespace Thumbnails
|
||||
{
|
||||
const int MaterialThumbnailSize = 200;
|
||||
static constexpr const int MaterialThumbnailSize = 512; // 512 is the default size in render to texture pass
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// MaterialThumbnail
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
MaterialThumbnail::MaterialThumbnail(AzToolsFramework::Thumbnailer::SharedThumbnailKey key, int thumbnailSize)
|
||||
: Thumbnail(key, thumbnailSize)
|
||||
MaterialThumbnail::MaterialThumbnail(AzToolsFramework::Thumbnailer::SharedThumbnailKey key)
|
||||
: Thumbnail(key)
|
||||
{
|
||||
m_assetId = GetAssetId(key, RPI::MaterialAsset::RTTI_Type());
|
||||
if (!m_assetId.IsValid())
|
||||
@@ -47,7 +47,7 @@ namespace AZ
|
||||
RPI::MaterialAsset::RTTI_Type(),
|
||||
&AzToolsFramework::Thumbnailer::ThumbnailerRendererRequests::RenderThumbnail,
|
||||
m_key,
|
||||
m_thumbnailSize);
|
||||
MaterialThumbnailSize);
|
||||
// wait for response from thumbnail renderer
|
||||
m_renderWait.acquire();
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace AZ
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
MaterialThumbnail(AzToolsFramework::Thumbnailer::SharedThumbnailKey key, int thumbnailSize);
|
||||
MaterialThumbnail(AzToolsFramework::Thumbnailer::SharedThumbnailKey key);
|
||||
~MaterialThumbnail() override;
|
||||
|
||||
//! AzToolsFramework::ThumbnailerRendererNotificationBus::Handler overrides...
|
||||
|
||||
@@ -44,8 +44,8 @@ namespace AZ
|
||||
"Mesh", "The mesh component is the primary method of adding visual geometry to entities")
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::Category, "Atom")
|
||||
->Attribute(AZ::Edit::Attributes::Icon, "Editor/Icons/Components/Component_Placeholder.svg")
|
||||
->Attribute(AZ::Edit::Attributes::ViewportIcon, "editor/icons/components/viewport/component_placeholder.png")
|
||||
->Attribute(AZ::Edit::Attributes::Icon, "Icons/Components/Component_Placeholder.svg")
|
||||
->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/Component_Placeholder.png")
|
||||
->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c))
|
||||
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
||||
->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://docs.aws.amazon.com/lumberyard/latest/userguide/component-mesh.html")
|
||||
|
||||
+31
-10
@@ -27,7 +27,7 @@
|
||||
#include <AzFramework/Entity/EntityContextBus.h>
|
||||
#include <AzFramework/Entity/EntityContext.h>
|
||||
#include <AzFramework/Scene/Scene.h>
|
||||
#include <AzFramework/Scene/SceneSystemBus.h>
|
||||
#include <AzFramework/Scene/SceneSystemInterface.h>
|
||||
|
||||
#include <AzCore/RTTI/BehaviorContext.h>
|
||||
|
||||
@@ -131,6 +131,7 @@ namespace AZ
|
||||
void MeshComponentController::GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent)
|
||||
{
|
||||
dependent.push_back(AZ_CRC("TransformService", 0x8ee22c50));
|
||||
dependent.push_back(AZ_CRC_CE("NonUniformScaleService"));
|
||||
}
|
||||
|
||||
void MeshComponentController::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
|
||||
@@ -268,15 +269,34 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
bool MeshComponentController::RequiresCloning(const Data::Asset<RPI::ModelAsset>& modelAsset)
|
||||
{
|
||||
// Is the model asset containing a cloth buffer? If yes, we need to clone the model asset for instancing.
|
||||
const AZStd::array_view<AZ::Data::Asset<AZ::RPI::ModelLodAsset>> lodAssets = modelAsset->GetLodAssets();
|
||||
for (const AZ::Data::Asset<AZ::RPI::ModelLodAsset>& lodAsset : lodAssets)
|
||||
{
|
||||
const AZStd::array_view<AZ::RPI::ModelLodAsset::Mesh> meshes = lodAsset->GetMeshes();
|
||||
for (const AZ::RPI::ModelLodAsset::Mesh& mesh : meshes)
|
||||
{
|
||||
if (mesh.GetSemanticBufferAssetView(AZ::Name("CLOTH_DATA")) != nullptr)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void MeshComponentController::HandleModelChange(Data::Instance<RPI::Model> model)
|
||||
{
|
||||
if (model)
|
||||
Data::Asset<RPI::ModelAsset> modelAsset = m_meshFeatureProcessor->GetModelAsset(m_meshHandle);
|
||||
if (model && modelAsset)
|
||||
{
|
||||
m_configuration.m_modelAsset = model->GetModelAsset();
|
||||
MeshComponentNotificationBus::Event(m_entityId, &MeshComponentNotificationBus::Events::OnModelReady, model->GetModelAsset(), model);
|
||||
m_configuration.m_modelAsset = modelAsset;
|
||||
MeshComponentNotificationBus::Event(m_entityId, &MeshComponentNotificationBus::Events::OnModelReady, m_configuration.m_modelAsset, model);
|
||||
MaterialReceiverNotificationBus::Event(m_entityId, &MaterialReceiverNotificationBus::Events::OnMaterialAssignmentsChanged);
|
||||
AzFramework::EntityBoundsUnionRequestBus::Broadcast(
|
||||
&AzFramework::EntityBoundsUnionRequestBus::Events::RefreshEntityLocalBoundsUnion, m_entityId);
|
||||
AZ::Interface<AzFramework::IEntityBoundsUnion>::Get()->RefreshEntityLocalBoundsUnion(m_entityId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -288,7 +308,8 @@ namespace AZ
|
||||
MaterialComponentRequestBus::EventResult(materials, m_entityId, &MaterialComponentRequests::GetMaterialOverrides);
|
||||
|
||||
m_meshFeatureProcessor->ReleaseMesh(m_meshHandle);
|
||||
m_meshHandle = m_meshFeatureProcessor->AcquireMesh(m_configuration.m_modelAsset, materials);
|
||||
m_meshHandle = m_meshFeatureProcessor->AcquireMesh(m_configuration.m_modelAsset, materials,
|
||||
/*skinnedMeshWithMotion=*/false, /*rayTracingEnabled=*/true, RequiresCloning);
|
||||
m_meshFeatureProcessor->ConnectModelChangeEventHandler(m_meshHandle, m_changeEventHandler);
|
||||
|
||||
const AZ::Transform& transform = m_transformInterface ? m_transformInterface->GetWorldTM() : AZ::Transform::CreateIdentity();
|
||||
@@ -345,9 +366,9 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
const Data::Asset<RPI::ModelAsset>& MeshComponentController::GetModelAsset() const
|
||||
Data::Asset<const RPI::ModelAsset> MeshComponentController::GetModelAsset() const
|
||||
{
|
||||
return GetModel() ? GetModel()->GetModelAsset() : m_configuration.m_modelAsset;
|
||||
return m_configuration.m_modelAsset;
|
||||
}
|
||||
|
||||
Data::AssetId MeshComponentController::GetModelAssetId() const
|
||||
@@ -369,7 +390,7 @@ namespace AZ
|
||||
return assetPathString;
|
||||
}
|
||||
|
||||
const Data::Instance<RPI::Model> MeshComponentController::GetModel() const
|
||||
Data::Instance<RPI::Model> MeshComponentController::GetModel() const
|
||||
{
|
||||
return m_meshFeatureProcessor ? m_meshFeatureProcessor->GetModel(m_meshHandle) : Data::Instance<RPI::Model>();
|
||||
}
|
||||
|
||||
@@ -83,17 +83,16 @@ namespace AZ
|
||||
const MeshComponentConfig& GetConfiguration() const;
|
||||
|
||||
private:
|
||||
|
||||
AZ_DISABLE_COPY(MeshComponentController);
|
||||
|
||||
// MeshComponentRequestBus::Handler overrides ...
|
||||
void SetModelAsset(Data::Asset<RPI::ModelAsset> modelAsset) override;
|
||||
const Data::Asset<RPI::ModelAsset>& GetModelAsset() const override;
|
||||
Data::Asset<const RPI::ModelAsset> GetModelAsset() const override;
|
||||
void SetModelAssetId(Data::AssetId modelAssetId) override;
|
||||
Data::AssetId GetModelAssetId() const override;
|
||||
void SetModelAssetPath(const AZStd::string& modelAssetPath) override;
|
||||
AZStd::string GetModelAssetPath() const override;
|
||||
const AZ::Data::Instance<RPI::Model> GetModel() const override;
|
||||
AZ::Data::Instance<RPI::Model> GetModel() const override;
|
||||
|
||||
void SetSortKey(RHI::DrawItemSortKey sortKey) override;
|
||||
RHI::DrawItemSortKey GetSortKey() const override;
|
||||
@@ -118,6 +117,13 @@ namespace AZ
|
||||
// MaterialComponentNotificationBus::Handler overrides ...
|
||||
void OnMaterialsUpdated(const MaterialAssignmentMap& materials) override;
|
||||
|
||||
//! Check if the model asset requires to be cloned (e.g. cloth) for unique model instances.
|
||||
//! @param modelAsset The model asset to check.
|
||||
//! @result True in case the model asset needs to be cloned before creating the model. False if there is a 1:1 relationship between
|
||||
//! the model asset and the model and it is static and shared. In the second case the m_originalModelAsset of the mesh handle is
|
||||
//! equal to the model asset that the model is linked to.
|
||||
static bool RequiresCloning(const Data::Asset<RPI::ModelAsset>& modelAsset);
|
||||
|
||||
void HandleModelChange(Data::Instance<RPI::Model> model);
|
||||
void RegisterModel();
|
||||
void UnregisterModel();
|
||||
|
||||
@@ -22,13 +22,13 @@ namespace AZ
|
||||
{
|
||||
namespace Thumbnails
|
||||
{
|
||||
const int MeshThumbnailSize = 200;
|
||||
static constexpr const int MeshThumbnailSize = 512; // 512 is the default size in render to texture pass
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// MeshThumbnail
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
MeshThumbnail::MeshThumbnail(AzToolsFramework::Thumbnailer::SharedThumbnailKey key, int thumbnailSize)
|
||||
: Thumbnail(key, thumbnailSize)
|
||||
MeshThumbnail::MeshThumbnail(AzToolsFramework::Thumbnailer::SharedThumbnailKey key)
|
||||
: Thumbnail(key)
|
||||
{
|
||||
m_assetId = GetAssetId(key, RPI::ModelAsset::RTTI_Type());
|
||||
if (!m_assetId.IsValid())
|
||||
@@ -48,7 +48,7 @@ namespace AZ
|
||||
RPI::ModelAsset::RTTI_Type(),
|
||||
&AzToolsFramework::Thumbnailer::ThumbnailerRendererRequests::RenderThumbnail,
|
||||
m_key,
|
||||
m_thumbnailSize);
|
||||
MeshThumbnailSize);
|
||||
// wait for response from thumbnail renderer
|
||||
m_renderWait.acquire();
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace AZ
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
MeshThumbnail(AzToolsFramework::Thumbnailer::SharedThumbnailKey key, int thumbnailSize);
|
||||
MeshThumbnail(AzToolsFramework::Thumbnailer::SharedThumbnailKey key);
|
||||
~MeshThumbnail() override;
|
||||
|
||||
//! AzToolsFramework::ThumbnailerRendererNotificationBus::Handler overrides...
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#include <SkyBox/PhysicalSkyComponent.h>
|
||||
#include <Scripting/EntityReferenceComponent.h>
|
||||
#include <SurfaceData/SurfaceDataMeshComponent.h>
|
||||
#include <Animation/AttachmentComponent.h>
|
||||
|
||||
#ifdef ATOMLYINTEGRATION_FEATURE_COMMON_EDITOR
|
||||
#include <EditorCommonFeaturesSystemComponent.h>
|
||||
@@ -69,6 +70,7 @@
|
||||
#include <SkyBox/EditorPhysicalSkyComponent.h>
|
||||
#include <Scripting/EditorEntityReferenceComponent.h>
|
||||
#include <SurfaceData/EditorSurfaceDataMeshComponent.h>
|
||||
#include <Animation/EditorAttachmentComponent.h>
|
||||
#endif
|
||||
|
||||
namespace AZ
|
||||
@@ -111,6 +113,7 @@ namespace AZ
|
||||
DiffuseProbeGridComponent::CreateDescriptor(),
|
||||
DeferredFogComponent::CreateDescriptor(),
|
||||
SurfaceData::SurfaceDataMeshComponent::CreateDescriptor(),
|
||||
AttachmentComponent::CreateDescriptor(),
|
||||
|
||||
#ifdef ATOMLYINTEGRATION_FEATURE_COMMON_EDITOR
|
||||
EditorAreaLightComponent::CreateDescriptor(),
|
||||
@@ -141,6 +144,7 @@ namespace AZ
|
||||
EditorDiffuseProbeGridComponent::CreateDescriptor(),
|
||||
EditorDeferredFogComponent::CreateDescriptor(),
|
||||
SurfaceData::EditorSurfaceDataMeshComponent::CreateDescriptor(),
|
||||
EditorAttachmentComponent::CreateDescriptor(),
|
||||
#endif
|
||||
});
|
||||
}
|
||||
|
||||
+2
-2
@@ -32,8 +32,8 @@ namespace AZ
|
||||
"Bloom", "Controls the Bloom")
|
||||
->ClassElement(Edit::ClassElements::EditorData, "")
|
||||
->Attribute(Edit::Attributes::Category, "Atom")
|
||||
->Attribute(AZ::Edit::Attributes::Icon, "Editor/Icons/Components/Component_Placeholder.svg") // [GFX TODO ATOM-2672][PostFX] need to create icons for PostProcessing.
|
||||
->Attribute(AZ::Edit::Attributes::ViewportIcon, "editor/icons/components/viewport/component_placeholder.png") // [GFX TODO ATOM-2672][PostFX] need to create icons for PostProcessing.
|
||||
->Attribute(AZ::Edit::Attributes::Icon, "Icons/Components/Component_Placeholder.svg") // [GFX TODO ATOM-2672][PostFX] need to create icons for PostProcessing.
|
||||
->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/Component_Placeholder.png") // [GFX TODO ATOM-2672][PostFX] need to create icons for PostProcessing.
|
||||
->Attribute(Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c))
|
||||
->Attribute(Edit::Attributes::AutoExpand, true)
|
||||
->Attribute(Edit::Attributes::HelpPageURL, "https://") // [TODO ATOM-2672][PostFX] need create page for PostProcessing.
|
||||
|
||||
+2
-2
@@ -32,8 +32,8 @@ namespace AZ
|
||||
"DepthOfField", "Controls the Depth of Field.")
|
||||
->ClassElement(Edit::ClassElements::EditorData, "")
|
||||
->Attribute(Edit::Attributes::Category, "Atom")
|
||||
->Attribute(AZ::Edit::Attributes::Icon, "Editor/Icons/Components/Component_Placeholder.svg") // [GFX TODO ATOM-2672][PostFX] need to create icons for PostProcessing.
|
||||
->Attribute(AZ::Edit::Attributes::ViewportIcon, "editor/icons/components/viewport/component_placeholder.png") // [GFX TODO ATOM-2672][PostFX] need to create icons for PostProcessing.y
|
||||
->Attribute(AZ::Edit::Attributes::Icon, "Icons/Components/Component_Placeholder.svg") // [GFX TODO ATOM-2672][PostFX] need to create icons for PostProcessing.
|
||||
->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/Component_Placeholder.png") // [GFX TODO ATOM-2672][PostFX] need to create icons for PostProcessing.y
|
||||
->Attribute(Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c))
|
||||
->Attribute(Edit::Attributes::AutoExpand, true)
|
||||
->Attribute(Edit::Attributes::HelpPageURL, "https://") // [GFX TODO][ATOM-2672][PostFX] need create page for PostProcessing.
|
||||
|
||||
+2
-2
@@ -32,8 +32,8 @@ namespace AZ
|
||||
"Display Mapper", "The display mapper applying on the look modification process.")
|
||||
->ClassElement(Edit::ClassElements::EditorData, "")
|
||||
->Attribute(Edit::Attributes::Category, "Atom")
|
||||
->Attribute(AZ::Edit::Attributes::Icon, "Editor/Icons/Components/Component_Placeholder.svg") // [GFX TODO][ATOM-2672][PostFX] need to create icons for PostProcessing.
|
||||
->Attribute(AZ::Edit::Attributes::ViewportIcon, "editor/icons/components/viewport/component_placeholder.png") // [GFX TODO][ATOM-2672][PostFX] need to create icons for PostProcessing.
|
||||
->Attribute(AZ::Edit::Attributes::Icon, "Icons/Components/Component_Placeholder.svg") // [GFX TODO][ATOM-2672][PostFX] need to create icons for PostProcessing.
|
||||
->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/Component_Placeholder.png") // [GFX TODO][ATOM-2672][PostFX] need to create icons for PostProcessing.
|
||||
->Attribute(Edit::Attributes::AppearsInAddComponentMenu, AZStd::vector<AZ::Crc32>({ AZ_CRC("Level", 0x9aeacc13), AZ_CRC("Game", 0x232b318c) }))
|
||||
->Attribute(Edit::Attributes::AutoExpand, true)
|
||||
->Attribute(Edit::Attributes::HelpPageURL, "https://") // [GFX TODO][ATOM-2672][PostFX] need to create page for PostProcessing.
|
||||
|
||||
+2
-2
@@ -32,8 +32,8 @@ namespace AZ
|
||||
"PostFX Layer", "This component enables the entity to specify post process settings")
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::Category, "Atom")
|
||||
->Attribute(AZ::Edit::Attributes::Icon, "Editor/Icons/Components/Component_Placeholder.svg")
|
||||
->Attribute(AZ::Edit::Attributes::ViewportIcon, "editor/icons/components/viewport/component_placeholder.png")
|
||||
->Attribute(AZ::Edit::Attributes::Icon, "Icons/Components/Component_Placeholder.svg")
|
||||
->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/Component_Placeholder.png")
|
||||
->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c))
|
||||
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
||||
->Attribute(AZ::Edit::Attributes::HelpPageURL, "")
|
||||
|
||||
+2
-2
@@ -32,8 +32,8 @@ namespace AZ
|
||||
"Exposure Control", "Exposure component control exposure value for rendered scene.")
|
||||
->ClassElement(Edit::ClassElements::EditorData, "")
|
||||
->Attribute(Edit::Attributes::Category, "Atom")
|
||||
->Attribute(AZ::Edit::Attributes::Icon, "Editor/Icons/Components/Component_Placeholder.svg") // [GFX TODO ATOM-2672][PostFX] need to create icons for PostProcessing.
|
||||
->Attribute(AZ::Edit::Attributes::ViewportIcon, "editor/icons/components/viewport/component_placeholder.png") // [GFX TODO ATOM-2672][PostFX] need to create icons for PostProcessing.
|
||||
->Attribute(AZ::Edit::Attributes::Icon, "Icons/Components/Component_Placeholder.svg") // [GFX TODO ATOM-2672][PostFX] need to create icons for PostProcessing.
|
||||
->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/Component_Placeholder.png") // [GFX TODO ATOM-2672][PostFX] need to create icons for PostProcessing.
|
||||
->Attribute(Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c))
|
||||
->Attribute(Edit::Attributes::AutoExpand, true)
|
||||
->Attribute(Edit::Attributes::HelpPageURL, "https://") // [TODO ATOM-2672][PostFX] need create page for PostProcessing.
|
||||
|
||||
+3
@@ -88,6 +88,9 @@ namespace AZ
|
||||
{
|
||||
ExposureControlRequestBus::Handler::BusDisconnect(m_entityId);
|
||||
|
||||
m_configuration.SetHeatmapEnabled(false);
|
||||
OnConfigChanged();
|
||||
|
||||
if (m_postProcessInterface)
|
||||
{
|
||||
m_postProcessInterface->RemoveExposureControlSettingsInterface();
|
||||
|
||||
+2
-2
@@ -32,8 +32,8 @@ namespace AZ
|
||||
"PostFX Gradient Weight Modifier", "Modifies PostFX override factor based on a gradient signal sampled from an entity")
|
||||
->ClassElement(Edit::ClassElements::EditorData, "")
|
||||
->Attribute(Edit::Attributes::Category, "Atom")
|
||||
->Attribute(AZ::Edit::Attributes::Icon, "Editor/Icons/Components/Component_Placeholder.svg")
|
||||
->Attribute(AZ::Edit::Attributes::ViewportIcon, "editor/icons/components/viewport/component_placeholder.png")
|
||||
->Attribute(AZ::Edit::Attributes::Icon, "Icons/Components/Component_Placeholder.svg")
|
||||
->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/Component_Placeholder.png")
|
||||
->Attribute(Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c))
|
||||
->Attribute(Edit::Attributes::AutoExpand, true)
|
||||
->Attribute(Edit::Attributes::HelpPageURL, "")
|
||||
|
||||
+2
-2
@@ -32,8 +32,8 @@ namespace AZ
|
||||
"Look Modification", "The look modification process.")
|
||||
->ClassElement(Edit::ClassElements::EditorData, "")
|
||||
->Attribute(Edit::Attributes::Category, "Atom")
|
||||
->Attribute(AZ::Edit::Attributes::Icon, "Editor/Icons/Components/Component_Placeholder.svg") // [GFX TODO ATOM-2672][PostFX] need to create icons for PostProcessing.
|
||||
->Attribute(AZ::Edit::Attributes::ViewportIcon, "editor/icons/components/viewport/component_placeholder.png") // [GFX TODO ATOM-2672][PostFX] need to create icons for PostProcessing.
|
||||
->Attribute(AZ::Edit::Attributes::Icon, "Icons/Components/Component_Placeholder.svg") // [GFX TODO ATOM-2672][PostFX] need to create icons for PostProcessing.
|
||||
->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/Component_Placeholder.png") // [GFX TODO ATOM-2672][PostFX] need to create icons for PostProcessing.
|
||||
->Attribute(Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c))
|
||||
->Attribute(Edit::Attributes::AutoExpand, true)
|
||||
->Attribute(Edit::Attributes::HelpPageURL, "https://") // [TODO ATOM-2672][PostFX] need to create page for PostProcessing.
|
||||
|
||||
+2
-2
@@ -32,8 +32,8 @@ namespace AZ
|
||||
"Radius Weight Modifier", "Modifies PostFX override factor based on proximity of an influencer against this entity's bounding sphere")
|
||||
->ClassElement(Edit::ClassElements::EditorData, "")
|
||||
->Attribute(Edit::Attributes::Category, "Atom")
|
||||
->Attribute(AZ::Edit::Attributes::Icon, "Editor/Icons/Components/Component_Placeholder.svg")
|
||||
->Attribute(AZ::Edit::Attributes::ViewportIcon, "editor/icons/components/viewport/component_placeholder.png")
|
||||
->Attribute(AZ::Edit::Attributes::Icon, "Icons/Components/Component_Placeholder.svg")
|
||||
->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/Component_Placeholder.png")
|
||||
->Attribute(Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c))
|
||||
->Attribute(Edit::Attributes::AutoExpand, true)
|
||||
->Attribute(Edit::Attributes::HelpPageURL, "")
|
||||
|
||||
+2
-2
@@ -32,8 +32,8 @@ namespace AZ
|
||||
"PostFX Shape Weight Modifier", "Modifies PostFX override factor based on proximity of an influencer against this entity's bounding sphere")
|
||||
->ClassElement(Edit::ClassElements::EditorData, "")
|
||||
->Attribute(Edit::Attributes::Category, "Atom")
|
||||
->Attribute(AZ::Edit::Attributes::Icon, "Editor/Icons/Components/Component_Placeholder.svg")
|
||||
->Attribute(AZ::Edit::Attributes::ViewportIcon, "editor/icons/components/viewport/component_placeholder.png")
|
||||
->Attribute(AZ::Edit::Attributes::Icon, "Icons/Components/Component_Placeholder.svg")
|
||||
->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/Component_Placeholder.png")
|
||||
->Attribute(Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c))
|
||||
->Attribute(Edit::Attributes::AutoExpand, true)
|
||||
->Attribute(Edit::Attributes::HelpPageURL, "")
|
||||
|
||||
+2
-2
@@ -32,8 +32,8 @@ namespace AZ
|
||||
"SSAO", "Controls SSAO.")
|
||||
->ClassElement(Edit::ClassElements::EditorData, "")
|
||||
->Attribute(Edit::Attributes::Category, "Atom")
|
||||
->Attribute(AZ::Edit::Attributes::Icon, "Editor/Icons/Components/Component_Placeholder.svg") // [GFX TODO ATOM-2672][PostFX] need to create icons for PostProcessing.
|
||||
->Attribute(AZ::Edit::Attributes::ViewportIcon, "editor/icons/components/viewport/component_placeholder.png") // [GFX TODO ATOM-2672][PostFX] need to create icons for PostProcessing.
|
||||
->Attribute(AZ::Edit::Attributes::Icon, "Icons/Components/Component_Placeholder.svg") // [GFX TODO ATOM-2672][PostFX] need to create icons for PostProcessing.
|
||||
->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/Component_Placeholder.png") // [GFX TODO ATOM-2672][PostFX] need to create icons for PostProcessing.
|
||||
->Attribute(Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC_CE("Game"))
|
||||
->Attribute(Edit::Attributes::AutoExpand, true)
|
||||
->Attribute(Edit::Attributes::HelpPageURL, "https://") // [GFX TODO][ATOM-2672][PostFX] need create page for PostProcessing.
|
||||
|
||||
+144
-115
@@ -49,20 +49,24 @@ namespace AZ
|
||||
"Reflection Probe", "The ReflectionProbe component captures an IBL specular reflection at a specific position in the level")
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::Category, "Atom")
|
||||
->Attribute(AZ::Edit::Attributes::Icon, "Editor/Icons/Components/Component_Placeholder.svg")
|
||||
->Attribute(AZ::Edit::Attributes::ViewportIcon, "editor/icons/components/viewport/component_placeholder.png")
|
||||
->Attribute(AZ::Edit::Attributes::Icon, "Icons/Components/Component_Placeholder.svg")
|
||||
->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/Component_Placeholder.png")
|
||||
->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c))
|
||||
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
||||
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
|
||||
->Attribute(AZ::Edit::Attributes::PrimaryAssetType, AZ::AzTypeInfo<RPI::ModelAsset>::Uuid())
|
||||
->ClassElement(AZ::Edit::ClassElements::Group, "Cubemap")
|
||||
->ClassElement(AZ::Edit::ClassElements::Group, "Cubemap Bake")
|
||||
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &EditorReflectionProbeComponent::m_useBakedCubemap, "Use Baked Cubemap", "Selects between a cubemap that captures the environment at location in the scene or a preauthored cubemap")
|
||||
->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorReflectionProbeComponent::OnUseBakedCubemapChanged)
|
||||
->UIElement(AZ::Edit::UIHandlers::Button, "Bake Reflection Probe", "Bake Reflection Probe")
|
||||
->Attribute(AZ::Edit::Attributes::NameLabelOverride, "")
|
||||
->Attribute(AZ::Edit::Attributes::ButtonText, "Bake Reflection Probe")
|
||||
->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorReflectionProbeComponent::BakeReflectionProbe)
|
||||
->Attribute(AZ::Edit::Attributes::Visibility, &EditorReflectionProbeComponent::GetBakedCubemapVisibilitySetting)
|
||||
->ClassElement(AZ::Edit::ClassElements::Group, "Cubemap")
|
||||
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &EditorReflectionProbeComponent::m_useBakedCubemap, "Use Baked Cubemap", "Selects between a cubemap that captures the environment at location in the scene or a preauthored cubemap")
|
||||
->Attribute(AZ::Edit::Attributes::ChangeValidate, &EditorReflectionProbeComponent::OnUseBakedCubemapValidate)
|
||||
->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorReflectionProbeComponent::OnUseBakedCubemapChanged)
|
||||
->DataElement(AZ::Edit::UIHandlers::MultiLineEdit, &EditorReflectionProbeComponent::m_bakedCubeMapRelativePath, "Baked Cubemap Path", "Baked Cubemap Path")
|
||||
->Attribute(AZ::Edit::Attributes::ReadOnly, true)
|
||||
->Attribute(AZ::Edit::Attributes::Visibility, &EditorReflectionProbeComponent::GetBakedCubemapVisibilitySetting)
|
||||
@@ -129,23 +133,14 @@ namespace AZ
|
||||
AzFramework::EntityDebugDisplayEventBus::Handler::BusConnect(GetEntityId());
|
||||
AzToolsFramework::EditorComponentSelectionRequestsBus::Handler::BusConnect(GetEntityId());
|
||||
EditorReflectionProbeBus::Handler::BusConnect(GetEntityId());
|
||||
AZ::TickBus::Handler::BusConnect();
|
||||
|
||||
ReflectionProbeComponentConfig& configuration = m_controller.m_configuration;
|
||||
|
||||
// special handling is required if this component is being cloned in the editor:
|
||||
// if the entityId in the configuration does not match this component's entityId it is being cloned
|
||||
AZ::u64 entityId = (AZ::u64)GetEntityId();
|
||||
if (configuration.m_entityId != EntityId::InvalidEntityId
|
||||
&& configuration.m_entityId != entityId)
|
||||
{
|
||||
// clear the cubeMapRelativePath to prevent the newly cloned reflection probe
|
||||
// from using the same cubemap path as the original reflection probe
|
||||
configuration.m_bakedCubeMapRelativePath = "";
|
||||
}
|
||||
|
||||
// update UI cubemap path display
|
||||
m_bakedCubeMapRelativePath = configuration.m_bakedCubeMapRelativePath;
|
||||
|
||||
AZ::u64 entityId = (AZ::u64)GetEntityId();
|
||||
configuration.m_entityId = entityId;
|
||||
}
|
||||
|
||||
@@ -154,9 +149,55 @@ namespace AZ
|
||||
EditorReflectionProbeBus::Handler::BusDisconnect(GetEntityId());
|
||||
AzToolsFramework::EditorComponentSelectionRequestsBus::Handler::BusDisconnect();
|
||||
AzFramework::EntityDebugDisplayEventBus::Handler::BusDisconnect();
|
||||
AZ::TickBus::Handler::BusDisconnect();
|
||||
BaseClass::Deactivate();
|
||||
}
|
||||
|
||||
void EditorReflectionProbeComponent::OnTick([[maybe_unused]] float deltaTime, [[maybe_unused]] AZ::ScriptTimePoint time)
|
||||
{
|
||||
if (!m_controller.m_featureProcessor)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_controller.m_configuration.m_useBakedCubemap)
|
||||
{
|
||||
AZStd::string cubeMapRelativePath = m_controller.m_configuration.m_bakedCubeMapRelativePath + ".streamingimage";
|
||||
Data::Asset<RPI::StreamingImageAsset> cubeMapAsset;
|
||||
CubeMapAssetNotificationType notificationType = CubeMapAssetNotificationType::None;
|
||||
if (m_controller.m_featureProcessor->CheckCubeMapAssetNotification(cubeMapRelativePath, cubeMapAsset, notificationType))
|
||||
{
|
||||
// a cubemap bake is in progress for this entity component
|
||||
if (notificationType == CubeMapAssetNotificationType::Ready)
|
||||
{
|
||||
// bake is complete, update configuration with the new baked cubemap asset
|
||||
m_controller.m_configuration.m_bakedCubeMapAsset = { cubeMapAsset.GetAs<RPI::StreamingImageAsset>(), AZ::Data::AssetLoadBehavior::PreLoad };
|
||||
|
||||
// refresh the currently rendered cubemap
|
||||
m_controller.UpdateCubeMap();
|
||||
|
||||
// update the UI
|
||||
AzToolsFramework::PropertyEditorGUIMessages::Bus::Broadcast(&AzToolsFramework::PropertyEditorGUIMessages::RequestRefresh, AzToolsFramework::PropertyModificationRefreshLevel::Refresh_AttributesAndValues);
|
||||
}
|
||||
else if (notificationType == CubeMapAssetNotificationType::Error)
|
||||
{
|
||||
// cubemap bake failed
|
||||
QMessageBox::information(
|
||||
QApplication::activeWindow(),
|
||||
"Reflection Probe",
|
||||
"Reflection Probe cubemap failed to bake, please check the Asset Processor for more information.",
|
||||
QMessageBox::Ok);
|
||||
|
||||
// clear relative path, this will allow the user to retry
|
||||
m_controller.m_configuration.m_bakedCubeMapRelativePath.clear();
|
||||
|
||||
// update the UI
|
||||
AzToolsFramework::PropertyEditorGUIMessages::Bus::Broadcast(&AzToolsFramework::PropertyEditorGUIMessages::RequestRefresh, AzToolsFramework::PropertyModificationRefreshLevel::Refresh_AttributesAndValues);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EditorReflectionProbeComponent::DisplayEntityViewport([[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay)
|
||||
{
|
||||
// only draw the bounds if selected
|
||||
@@ -168,13 +209,19 @@ namespace AZ
|
||||
AZ::Vector3 position = AZ::Vector3::CreateZero();
|
||||
AZ::TransformBus::EventResult(position, GetEntityId(), &AZ::TransformBus::Events::GetWorldTranslation);
|
||||
|
||||
AZ::Vector3 scale = AZ::Vector3::CreateOne();
|
||||
AZ::TransformBus::EventResult(scale, GetEntityId(), &AZ::TransformBus::Events::GetLocalScale);
|
||||
|
||||
// draw AABB at probe position using the inner dimensions
|
||||
Color color(0.0f, 0.0f, 1.0f, 1.0f);
|
||||
debugDisplay.SetColor(color);
|
||||
|
||||
ReflectionProbeComponentConfig& configuration = m_controller.m_configuration;
|
||||
AZ::Vector3 innerMin(position.GetX() - configuration.m_innerWidth / 2, position.GetY() - configuration.m_innerLength / 2, position.GetZ() - configuration.m_innerHeight / 2);
|
||||
AZ::Vector3 innerMax(position.GetX() + configuration.m_innerWidth / 2, position.GetY() + configuration.m_innerLength / 2, position.GetZ() + configuration.m_innerHeight / 2);
|
||||
AZ::Vector3 innerExtents(configuration.m_innerWidth, configuration.m_innerLength, configuration.m_innerHeight);
|
||||
innerExtents *= scale;
|
||||
|
||||
AZ::Vector3 innerMin(position.GetX() - innerExtents.GetX() / 2, position.GetY() - innerExtents.GetY() / 2, position.GetZ() - innerExtents.GetZ() / 2);
|
||||
AZ::Vector3 innerMax(position.GetX() + innerExtents.GetX() / 2, position.GetY() + innerExtents.GetY() / 2, position.GetZ() + innerExtents.GetZ() / 2);
|
||||
debugDisplay.DrawWireBox(innerMin, innerMax);
|
||||
}
|
||||
|
||||
@@ -188,6 +235,16 @@ namespace AZ
|
||||
return false;
|
||||
}
|
||||
|
||||
AZ::Outcome<void, AZStd::string> EditorReflectionProbeComponent::OnUseBakedCubemapValidate([[maybe_unused]] void* newValue, [[maybe_unused]] const AZ::Uuid& valueType)
|
||||
{
|
||||
if (!m_controller.m_featureProcessor)
|
||||
{
|
||||
return AZ::Failure(AZStd::string("This Reflection Probe entity is hidden, it must be visible in order to change the cubemap type."));
|
||||
}
|
||||
|
||||
return AZ::Success();
|
||||
}
|
||||
|
||||
AZ::u32 EditorReflectionProbeComponent::OnUseBakedCubemapChanged()
|
||||
{
|
||||
// save setting to the configuration
|
||||
@@ -256,122 +313,94 @@ namespace AZ
|
||||
return AZ::Edit::PropertyRefreshLevels::None;
|
||||
}
|
||||
|
||||
// callback from the EnvironmentCubeMapPass when the cubemap render is complete
|
||||
BuildCubeMapCallback buildCubeMapCallback = [this](uint8_t* const* cubeMapFaceTextureData, const RHI::Format cubeMapTextureFormat)
|
||||
char projectPath[AZ_MAX_PATH_LEN];
|
||||
AZ::IO::FileIOBase::GetInstance()->ResolvePath("@devassets@", projectPath, AZ_MAX_PATH_LEN);
|
||||
|
||||
// retrieve the source cubemap path from the configuration
|
||||
// we need to make sure to use the same source cubemap for each bake
|
||||
AZStd::string cubeMapRelativePath = m_controller.m_configuration.m_bakedCubeMapRelativePath;
|
||||
AZStd::string cubeMapFullPath;
|
||||
|
||||
if (!cubeMapRelativePath.empty())
|
||||
{
|
||||
if (!m_bakeInProgress)
|
||||
// test to see if the cubemap file is actually there, if it was removed we need to
|
||||
// generate a new filename, otherwise it will cause an error in the asset system
|
||||
AzFramework::StringFunc::Path::Join(projectPath, cubeMapRelativePath.c_str(), cubeMapFullPath, true, true);
|
||||
|
||||
if (!AZ::IO::FileIOBase::GetInstance()->Exists(cubeMapFullPath.c_str()))
|
||||
{
|
||||
// user canceled the bake
|
||||
return;
|
||||
// clear it to force the generation of a new filename
|
||||
cubeMapRelativePath.clear();
|
||||
}
|
||||
}
|
||||
|
||||
char projectPath[AZ_MAX_PATH_LEN];
|
||||
AZ::IO::FileIOBase::GetInstance()->ResolvePath("@devassets@", projectPath, AZ_MAX_PATH_LEN);
|
||||
// build a new cubemap path if necessary
|
||||
if (cubeMapRelativePath.empty())
|
||||
{
|
||||
// the file name is a combination of the entity name, a UUID, and the filemask
|
||||
Entity* entity = GetEntity();
|
||||
AZ_Assert(entity, "ReflectionProbe entity is null");
|
||||
|
||||
// retrieve the source cubemap path from the configuration
|
||||
// we need to make sure to use the same source cubemap for each bake
|
||||
AZStd::string cubeMapRelativePath = m_controller.m_configuration.m_bakedCubeMapRelativePath;
|
||||
AZStd::string cubeMapFullPath;
|
||||
AZ::Uuid uuid = AZ::Uuid::CreateRandom();
|
||||
AZStd::string uuidString;
|
||||
uuid.ToString(uuidString);
|
||||
|
||||
if (!cubeMapRelativePath.empty())
|
||||
cubeMapRelativePath = "ReflectionProbes/" + entity->GetName() + "_" + uuidString + "_iblspecularcm.dds";
|
||||
|
||||
// replace any invalid filename characters
|
||||
auto invalidCharacters = [](char letter)
|
||||
{
|
||||
// test to see if the cubemap file is actually there, if it was removed we need to
|
||||
// generate a new filename, otherwise it will cause an error in the asset system
|
||||
AzFramework::StringFunc::Path::Join(projectPath, cubeMapRelativePath.c_str(), cubeMapFullPath, true, true);
|
||||
return
|
||||
letter == ':' || letter == '"' || letter == '\'' ||
|
||||
letter == '{' || letter == '}' ||
|
||||
letter == '<' || letter == '>';
|
||||
};
|
||||
AZStd::replace_if(cubeMapRelativePath.begin(), cubeMapRelativePath.end(), invalidCharacters, '_');
|
||||
|
||||
if (!AZ::IO::FileIOBase::GetInstance()->Exists(cubeMapFullPath.c_str()))
|
||||
{
|
||||
// clear it to force the generation of a new filename
|
||||
cubeMapRelativePath.clear();
|
||||
}
|
||||
}
|
||||
// build the full source path
|
||||
AzFramework::StringFunc::Path::Join(projectPath, cubeMapRelativePath.c_str(), cubeMapFullPath, true, true);
|
||||
}
|
||||
|
||||
// build a new cubemap path if necessary
|
||||
if (cubeMapRelativePath.empty())
|
||||
{
|
||||
// the file name is a combination of the entity name, a UUID, and the filemask
|
||||
Entity* entity = GetEntity();
|
||||
AZ_Assert(entity, "ReflectionProbe entity is null");
|
||||
// make sure the folder is created
|
||||
AZStd::string reflectionProbeFolder;
|
||||
AzFramework::StringFunc::Path::GetFolderPath(cubeMapFullPath.data(), reflectionProbeFolder);
|
||||
AZ::IO::SystemFile::CreateDir(reflectionProbeFolder.c_str());
|
||||
|
||||
AZ::Uuid uuid = AZ::Uuid::CreateRandom();
|
||||
AZStd::string uuidString;
|
||||
uuid.ToString(uuidString);
|
||||
// check out the file in source control
|
||||
bool checkedOutSuccessfully = false;
|
||||
using ApplicationBus = AzToolsFramework::ToolsApplicationRequestBus;
|
||||
ApplicationBus::BroadcastResult(
|
||||
checkedOutSuccessfully,
|
||||
&ApplicationBus::Events::RequestEditForFileBlocking,
|
||||
cubeMapFullPath.c_str(),
|
||||
"Checking out for edit...",
|
||||
ApplicationBus::Events::RequestEditProgressCallback());
|
||||
|
||||
cubeMapRelativePath = "ReflectionProbes/" + entity->GetName() + "_" + uuidString + "_iblspecularcm.dds";
|
||||
if (!checkedOutSuccessfully)
|
||||
{
|
||||
AZ_Error("ReflectionProbe", false, "Failed to write \"%s\", source control checkout failed", cubeMapFullPath.c_str());
|
||||
}
|
||||
|
||||
// replace any invalid filename characters
|
||||
auto invalidCharacters = [](char letter)
|
||||
{
|
||||
return
|
||||
letter == ':' || letter == '"' || letter == '\'' ||
|
||||
letter == '{' || letter == '}' ||
|
||||
letter == '<' || letter == '>';
|
||||
};
|
||||
AZStd::replace_if(cubeMapRelativePath.begin(), cubeMapRelativePath.end(), invalidCharacters, '_');
|
||||
// save the relative source path in the configuration
|
||||
AzToolsFramework::ScopedUndoBatch undoBatch("Cubemap path changed.");
|
||||
m_controller.m_configuration.m_bakedCubeMapRelativePath = cubeMapRelativePath;
|
||||
SetDirty();
|
||||
|
||||
// build the full source path
|
||||
AzFramework::StringFunc::Path::Join(projectPath, cubeMapRelativePath.c_str(), cubeMapFullPath, true, true);
|
||||
}
|
||||
|
||||
// make sure the folder is created
|
||||
AZStd::string reflectionProbeFolder;
|
||||
AzFramework::StringFunc::Path::GetFolderPath(cubeMapFullPath.data(), reflectionProbeFolder);
|
||||
AZ::IO::SystemFile::CreateDir(reflectionProbeFolder.c_str());
|
||||
|
||||
// check out the file in source control
|
||||
bool checkedOutSuccessfully = false;
|
||||
using ApplicationBus = AzToolsFramework::ToolsApplicationRequestBus;
|
||||
ApplicationBus::BroadcastResult(
|
||||
checkedOutSuccessfully,
|
||||
&ApplicationBus::Events::RequestEditForFileBlocking,
|
||||
cubeMapFullPath.c_str(),
|
||||
"Checking out for edit...",
|
||||
ApplicationBus::Events::RequestEditProgressCallback());
|
||||
|
||||
if (!checkedOutSuccessfully)
|
||||
{
|
||||
AZ_Error("ReflectionProbe", false, "Failed to write \"%s\", source control checkout failed", cubeMapFullPath.c_str());
|
||||
}
|
||||
// update UI cubemap path display
|
||||
m_bakedCubeMapRelativePath = cubeMapRelativePath;
|
||||
|
||||
// callback from the EnvironmentCubeMapPass when the cubemap render is complete
|
||||
BuildCubeMapCallback buildCubeMapCallback = [=](uint8_t* const* cubeMapFaceTextureData, const RHI::Format cubeMapTextureFormat)
|
||||
{
|
||||
// write the cubemap data to the .dds file
|
||||
WriteOutputFile(cubeMapFullPath.c_str(), cubeMapFaceTextureData, cubeMapTextureFormat);
|
||||
|
||||
// save the relative source path in the configuration
|
||||
AzToolsFramework::ScopedUndoBatch undoBatch("Cubemap path changed.");
|
||||
m_controller.m_configuration.m_bakedCubeMapRelativePath = cubeMapRelativePath;
|
||||
SetDirty();
|
||||
|
||||
// update UI cubemap path display
|
||||
m_bakedCubeMapRelativePath = cubeMapRelativePath;
|
||||
|
||||
// call the feature processor to notify when the asset is created and ready
|
||||
NotifyCubeMapAssetReadyCallback notifyCubeMapAssetReadyCallback = [this](const Data::Asset<RPI::StreamingImageAsset>& cubeMapAsset, CubeMapAssetNotificationType notificationType)
|
||||
{
|
||||
// we only need to store the cubemap asset and update the cubemap image on the first bake of the probe,
|
||||
// otherwise it is a hot-reload of an existing cubemap asset which is handled by the RPI
|
||||
if (notificationType == CubeMapAssetNotificationType::Ready)
|
||||
{
|
||||
// update configuration with the new baked cubemap asset
|
||||
m_controller.m_configuration.m_bakedCubeMapAsset = { cubeMapAsset.GetAs<RPI::StreamingImageAsset>(), AZ::Data::AssetLoadBehavior::PreLoad };
|
||||
|
||||
// refresh the currently rendered cubemap
|
||||
m_controller.UpdateCubeMap();
|
||||
|
||||
// update the UI
|
||||
AzToolsFramework::PropertyEditorGUIMessages::Bus::Broadcast(&AzToolsFramework::PropertyEditorGUIMessages::RequestRefresh, AzToolsFramework::PropertyModificationRefreshLevel::Refresh_AttributesAndValues);
|
||||
}
|
||||
|
||||
// signal completion
|
||||
m_bakeInProgress = false;
|
||||
};
|
||||
|
||||
AZStd::string cubeMapRelativeAssetPath = cubeMapRelativePath + ".streamingimage";
|
||||
m_controller.m_featureProcessor->NotifyCubeMapAssetReady(cubeMapRelativeAssetPath, notifyCubeMapAssetReadyCallback);
|
||||
m_bakeInProgress = false;
|
||||
};
|
||||
|
||||
// initiate the cubemap bake
|
||||
// initiate the cubemap bake, this will invoke the buildCubeMapCallback when the cubemap data is ready
|
||||
m_bakeInProgress = true;
|
||||
m_controller.BakeReflectionProbe(buildCubeMapCallback);
|
||||
AZStd::string cubeMapRelativeAssetPath = cubeMapRelativePath + ".streamingimage";
|
||||
m_controller.BakeReflectionProbe(buildCubeMapCallback, cubeMapRelativeAssetPath);
|
||||
|
||||
// show a dialog box letting the user know the probe is baking
|
||||
QProgressDialog bakeDialog;
|
||||
|
||||
+9
@@ -13,6 +13,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/std/parallel/atomic.h>
|
||||
#include <AzCore/Component/TickBus.h>
|
||||
#include <AzFramework/Entity/EntityDebugDisplayBus.h>
|
||||
#include <AzToolsFramework/API/ComponentEntitySelectionBus.h>
|
||||
#include <ReflectionProbe/ReflectionProbeComponent.h>
|
||||
@@ -29,6 +30,7 @@ namespace AZ
|
||||
, public EditorReflectionProbeBus::Handler
|
||||
, private AzToolsFramework::EditorComponentSelectionRequestsBus::Handler
|
||||
, private AzFramework::EntityDebugDisplayEventBus::Handler
|
||||
, private AZ::TickBus::Handler
|
||||
{
|
||||
public:
|
||||
using BaseClass = EditorRenderComponentAdapter<ReflectionProbeComponentController, ReflectionProbeComponent, ReflectionProbeComponentConfig>;
|
||||
@@ -45,8 +47,15 @@ namespace AZ
|
||||
|
||||
// AzFramework::EntityDebugDisplayEventBus::Handler overrides
|
||||
void DisplayEntityViewport(const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay) override;
|
||||
|
||||
private:
|
||||
|
||||
// AZ::TickBus overrides
|
||||
void OnTick(float deltaTime, AZ::ScriptTimePoint time) override;
|
||||
|
||||
// validation
|
||||
AZ::Outcome<void, AZStd::string> OnUseBakedCubemapValidate(void* newValue, const AZ::Uuid& valueType);
|
||||
|
||||
// change notifications
|
||||
AZ::u32 OnUseBakedCubemapChanged();
|
||||
AZ::u32 OnAuthoredCubemapChanged();
|
||||
|
||||
+30
-8
@@ -25,7 +25,7 @@
|
||||
#include <AzFramework/Entity/EntityContextBus.h>
|
||||
#include <AzFramework/Entity/EntityContext.h>
|
||||
#include <AzFramework/Scene/Scene.h>
|
||||
#include <AzFramework/Scene/SceneSystemBus.h>
|
||||
#include <AzFramework/Scene/SceneSystemInterface.h>
|
||||
|
||||
#include <AzCore/RTTI/BehaviorContext.h>
|
||||
|
||||
@@ -80,6 +80,7 @@ namespace AZ
|
||||
void ReflectionProbeComponentController::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
|
||||
{
|
||||
incompatible.push_back(AZ_CRC("ReflectionProbeService", 0xa5b919ce));
|
||||
incompatible.push_back(AZ_CRC_CE("NonUniformScaleService"));
|
||||
}
|
||||
|
||||
void ReflectionProbeComponentController::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required)
|
||||
@@ -111,6 +112,18 @@ namespace AZ
|
||||
m_boxShapeInterface = LmbrCentral::BoxShapeComponentRequestsBus::FindFirstHandler(m_entityId);
|
||||
AZ_Assert(m_boxShapeInterface, "ReflectionProbeComponentController was unable to find box shape component");
|
||||
|
||||
// special handling is required if this component is being cloned in the editor:
|
||||
// if this probe is using a baked cubemap, check to see if it is already referenced by another probe
|
||||
if (m_configuration.m_useBakedCubemap)
|
||||
{
|
||||
if (m_featureProcessor->IsCubeMapReferenced(m_configuration.m_bakedCubeMapRelativePath))
|
||||
{
|
||||
// clear the cubeMapRelativePath to prevent the newly cloned reflection probe
|
||||
// from using the same cubemap path as the original reflection probe
|
||||
m_configuration.m_bakedCubeMapRelativePath = "";
|
||||
}
|
||||
}
|
||||
|
||||
// add this reflection probe to the feature processor
|
||||
const AZ::Transform& transform = m_transformInterface->GetWorldTM();
|
||||
m_handle = m_featureProcessor->AddProbe(transform, m_configuration.m_useParallaxCorrection);
|
||||
@@ -130,12 +143,15 @@ namespace AZ
|
||||
m_configuration.m_useBakedCubemap ? m_configuration.m_bakedCubeMapAsset : m_configuration.m_authoredCubeMapAsset;
|
||||
Data::AssetBus::MultiHandler::BusConnect(cubeMapAsset.GetId());
|
||||
|
||||
const AZStd::string& relativePath =
|
||||
m_configuration.m_useBakedCubemap ? m_configuration.m_bakedCubeMapRelativePath : m_configuration.m_authoredCubeMapAsset.GetHint();
|
||||
|
||||
if (cubeMapAsset.GetId().IsValid())
|
||||
{
|
||||
if (cubeMapAsset.IsReady())
|
||||
{
|
||||
Data::Instance<RPI::Image> image = RPI::StreamingImage::FindOrCreate(cubeMapAsset);
|
||||
m_featureProcessor->SetProbeCubeMap(m_handle, image);
|
||||
m_featureProcessor->SetProbeCubeMap(m_handle, image, relativePath);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -149,6 +165,7 @@ namespace AZ
|
||||
if (m_featureProcessor)
|
||||
{
|
||||
m_featureProcessor->RemoveProbe(m_handle);
|
||||
m_handle = nullptr;
|
||||
}
|
||||
|
||||
LmbrCentral::ShapeComponentNotificationsBus::Handler::BusDisconnect();
|
||||
@@ -169,8 +186,11 @@ namespace AZ
|
||||
return;
|
||||
}
|
||||
|
||||
const AZStd::string& relativePath =
|
||||
m_configuration.m_useBakedCubemap ? m_configuration.m_bakedCubeMapRelativePath : m_configuration.m_authoredCubeMapAsset.GetHint();
|
||||
|
||||
Data::Instance<RPI::Image> image = RPI::StreamingImage::FindOrCreate(asset);
|
||||
m_featureProcessor->SetProbeCubeMap(m_handle, image);
|
||||
m_featureProcessor->SetProbeCubeMap(m_handle, image, relativePath);
|
||||
}
|
||||
|
||||
void ReflectionProbeComponentController::SetConfiguration(const ReflectionProbeComponentConfig& config)
|
||||
@@ -188,8 +208,11 @@ namespace AZ
|
||||
Data::Asset<RPI::StreamingImageAsset>& cubeMapAsset =
|
||||
m_configuration.m_useBakedCubemap ? m_configuration.m_bakedCubeMapAsset : m_configuration.m_authoredCubeMapAsset;
|
||||
|
||||
const AZStd::string& relativePath =
|
||||
m_configuration.m_useBakedCubemap ? m_configuration.m_bakedCubeMapRelativePath : m_configuration.m_authoredCubeMapAsset.GetHint();
|
||||
|
||||
Data::Instance<RPI::Image> image = RPI::StreamingImage::FindOrCreate(cubeMapAsset);
|
||||
m_featureProcessor->SetProbeCubeMap(m_handle, image);
|
||||
m_featureProcessor->SetProbeCubeMap(m_handle, image, relativePath);
|
||||
}
|
||||
|
||||
void ReflectionProbeComponentController::OnTransformChanged([[maybe_unused]] const AZ::Transform& local, const AZ::Transform& world)
|
||||
@@ -231,8 +254,7 @@ namespace AZ
|
||||
m_configuration.m_outerLength = dimensions.GetY();
|
||||
m_configuration.m_outerHeight = dimensions.GetZ();
|
||||
|
||||
AzFramework::EntityBoundsUnionRequestBus::Broadcast(
|
||||
&AzFramework::EntityBoundsUnionRequestBus::Events::RefreshEntityLocalBoundsUnion, m_entityId);
|
||||
AZ::Interface<AzFramework::IEntityBoundsUnion>::Get()->RefreshEntityLocalBoundsUnion(m_entityId);
|
||||
|
||||
// clamp the inner extents to the outer extents
|
||||
m_configuration.m_innerWidth = AZStd::min(m_configuration.m_innerWidth, m_configuration.m_outerWidth);
|
||||
@@ -240,14 +262,14 @@ namespace AZ
|
||||
m_configuration.m_innerHeight = AZStd::min(m_configuration.m_innerHeight, m_configuration.m_outerHeight);
|
||||
}
|
||||
|
||||
void ReflectionProbeComponentController::BakeReflectionProbe(BuildCubeMapCallback callback)
|
||||
void ReflectionProbeComponentController::BakeReflectionProbe(BuildCubeMapCallback callback, const AZStd::string& relativePath)
|
||||
{
|
||||
if (!m_featureProcessor)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_featureProcessor->BakeProbe(m_handle, callback);
|
||||
m_featureProcessor->BakeProbe(m_handle, callback, relativePath);
|
||||
}
|
||||
|
||||
AZ::Aabb ReflectionProbeComponentController::GetAabb() const
|
||||
|
||||
+1
-1
@@ -79,7 +79,7 @@ namespace AZ
|
||||
AZ::Aabb GetAabb() const;
|
||||
|
||||
// initiate the reflection probe bake, invokes callback when complete
|
||||
void BakeReflectionProbe(BuildCubeMapCallback callback);
|
||||
void BakeReflectionProbe(BuildCubeMapCallback callback, const AZStd::string& relativePath);
|
||||
|
||||
// update the currently rendering cubemap asset for this probe
|
||||
void UpdateCubeMap();
|
||||
|
||||
+2
-2
@@ -32,8 +32,8 @@ namespace AZ
|
||||
"Deferred Fog", "Controls the Deferred Fog")
|
||||
->ClassElement(Edit::ClassElements::EditorData, "")
|
||||
->Attribute(Edit::Attributes::Category, "Atom")
|
||||
->Attribute(AZ::Edit::Attributes::Icon, "Editor/Icons/Components/Component_Placeholder.svg") // [GFX TODO ATOM-2672][PostFX] need to create icons for PostProcessing.
|
||||
->Attribute(AZ::Edit::Attributes::ViewportIcon, "editor/icons/components/viewport/component_placeholder.png") // [GFX TODO ATOM-2672][PostFX] need to create icons for PostProcessing.
|
||||
->Attribute(AZ::Edit::Attributes::Icon, "Icons/Components/Component_Placeholder.svg") // [GFX TODO ATOM-2672][PostFX] need to create icons for PostProcessing.
|
||||
->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/Component_Placeholder.png") // [GFX TODO ATOM-2672][PostFX] need to create icons for PostProcessing.
|
||||
->Attribute(Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c))
|
||||
->Attribute(Edit::Attributes::AutoExpand, true)
|
||||
->Attribute(Edit::Attributes::HelpPageURL, "https://") // [TODO][ATOM-13427] Create Wiki for Deferred Fog
|
||||
|
||||
+2
-2
@@ -31,8 +31,8 @@ namespace AZ
|
||||
"Entity Reference", "Contains a reference list to other entities")
|
||||
->ClassElement(Edit::ClassElements::EditorData, "")
|
||||
->Attribute(Edit::Attributes::Category, "Atom")
|
||||
->Attribute(AZ::Edit::Attributes::Icon, "Editor/Icons/Components/Component_Placeholder.svg")
|
||||
->Attribute(AZ::Edit::Attributes::ViewportIcon, "editor/icons/components/viewport/component_placeholder.png")
|
||||
->Attribute(AZ::Edit::Attributes::Icon, "Icons/Components/Component_Placeholder.svg")
|
||||
->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/Component_Placeholder.png")
|
||||
->Attribute(Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c))
|
||||
->Attribute(Edit::Attributes::AutoExpand, true)
|
||||
->Attribute(Edit::Attributes::HelpPageURL, "")
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
#include <SkinnedMesh/SkinnedMeshDebugDisplay.h>
|
||||
#include <Atom/Feature/SkinnedMesh/SkinnedMeshStatsBus.h>
|
||||
#include <Atom/RPI.Public/Scene.h>
|
||||
#include <AzFramework/Scene/SceneSystemBus.h>
|
||||
#include <AzFramework/Scene/SceneSystemInterface.h>
|
||||
|
||||
#include <AzToolsFramework/Entity/EditorEntityContextBus.h>
|
||||
|
||||
|
||||
+2
-2
@@ -32,8 +32,8 @@ namespace AZ
|
||||
"HDRi Skybox", "SkyBox component render the background of your scene with cubemap")
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::Category, "Atom")
|
||||
->Attribute(AZ::Edit::Attributes::Icon, "Editor/Icons/Components/Component_Placeholder.svg")
|
||||
->Attribute(AZ::Edit::Attributes::ViewportIcon, "editor/icons/components/viewport/component_placeholder.png")
|
||||
->Attribute(AZ::Edit::Attributes::Icon, "Icons/Components/Component_Placeholder.svg")
|
||||
->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/Component_Placeholder.png")
|
||||
->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c))
|
||||
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
||||
->Attribute(AZ::Edit::Attributes::HelpPageURL, "")
|
||||
|
||||
+2
-2
@@ -32,8 +32,8 @@ namespace AZ
|
||||
"Physical Sky", "Physical Sky render the background of your scene with physical simulation")
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::Category, "Atom")
|
||||
->Attribute(AZ::Edit::Attributes::Icon, "Editor/Icons/Components/Component_Placeholder.svg")
|
||||
->Attribute(AZ::Edit::Attributes::ViewportIcon, "editor/icons/components/viewport/component_placeholder.png")
|
||||
->Attribute(AZ::Edit::Attributes::Icon, "Icons/Components/Component_Placeholder.svg")
|
||||
->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/Component_Placeholder.png")
|
||||
->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c))
|
||||
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
||||
->Attribute(AZ::Edit::Attributes::HelpPageURL, "")
|
||||
|
||||
+1
@@ -51,6 +51,7 @@ namespace AZ
|
||||
void HDRiSkyboxComponentController::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
|
||||
{
|
||||
incompatible.push_back(AZ_CRC("SkyBoxService", 0x8169a709));
|
||||
incompatible.push_back(AZ_CRC_CE("NonUniformScaleService"));
|
||||
}
|
||||
|
||||
void HDRiSkyboxComponentController::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required)
|
||||
|
||||
+1
@@ -58,6 +58,7 @@ namespace AZ
|
||||
void PhysicalSkyComponentController::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
|
||||
{
|
||||
incompatible.push_back(AZ_CRC("SkyBoxService", 0x8169a709));
|
||||
incompatible.push_back(AZ_CRC_CE("NonUniformScaleService"));
|
||||
}
|
||||
|
||||
void PhysicalSkyComponentController::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required)
|
||||
|
||||
+2
-1
@@ -82,8 +82,9 @@ namespace AZ
|
||||
return m_data;
|
||||
}
|
||||
|
||||
void CommonThumbnailRenderer::RenderThumbnail(AzToolsFramework::Thumbnailer::SharedThumbnailKey thumbnailKey, [[maybe_unused]] int thumbnailSize)
|
||||
void CommonThumbnailRenderer::RenderThumbnail(AzToolsFramework::Thumbnailer::SharedThumbnailKey thumbnailKey, int thumbnailSize)
|
||||
{
|
||||
m_data->m_thumbnailSize = thumbnailSize;
|
||||
m_data->m_thumbnailQueue.push(thumbnailKey);
|
||||
if (m_currentStep == Step::None)
|
||||
{
|
||||
|
||||
+2
-1
@@ -42,7 +42,7 @@ namespace AZ
|
||||
RPI::ScenePtr m_scene;
|
||||
AZStd::string m_sceneName = "Material Thumbnail Scene";
|
||||
AZStd::string m_pipelineName = "Material Thumbnail Pipeline";
|
||||
AzFramework::Scene* m_frameworkScene = nullptr;
|
||||
AZStd::shared_ptr<AzFramework::Scene> m_frameworkScene;
|
||||
RPI::RenderPipelinePtr m_renderPipeline;
|
||||
AZStd::unique_ptr<AzFramework::EntityContext> m_entityContext;
|
||||
AZStd::vector<AZStd::string> m_passHierarchy;
|
||||
@@ -52,6 +52,7 @@ namespace AZ
|
||||
|
||||
double m_simulateTime = 0.0f;
|
||||
float m_deltaTime = 0.0f;
|
||||
int m_thumbnailSize = 512;
|
||||
|
||||
//! Incoming thumbnail requests are appended to this queue and processed one at a time in OnTick function.
|
||||
AZStd::queue<AzToolsFramework::Thumbnailer::SharedThumbnailKey> m_thumbnailQueue;
|
||||
|
||||
+9
@@ -37,6 +37,15 @@ namespace AZ
|
||||
|
||||
void CaptureStep::Start()
|
||||
{
|
||||
if (!m_context->GetData()->m_materialAsset ||
|
||||
!m_context->GetData()->m_modelAsset)
|
||||
{
|
||||
AzToolsFramework::Thumbnailer::ThumbnailerRendererNotificationBus::Event(
|
||||
m_context->GetData()->m_thumbnailKeyRendered,
|
||||
&AzToolsFramework::Thumbnailer::ThumbnailerRendererNotifications::ThumbnailFailedToRender);
|
||||
m_context->SetStep(Step::FindThumbnailToRender);
|
||||
return;
|
||||
}
|
||||
Render::MaterialComponentRequestBus::Event(
|
||||
m_context->GetData()->m_modelEntity->GetId(),
|
||||
&Render::MaterialComponentRequestBus::Events::SetDefaultMaterialOverride,
|
||||
|
||||
+9
-16
@@ -100,24 +100,15 @@ namespace AZ
|
||||
data->m_scene->SetShaderResourceGroupCallback(callback);
|
||||
|
||||
// Bind m_defaultScene to the GameEntityContext's AzFramework::Scene
|
||||
Outcome<AzFramework::Scene*, AZStd::string> createSceneOutcome;
|
||||
AzFramework::SceneSystemRequestBus::BroadcastResult(
|
||||
createSceneOutcome,
|
||||
&AzFramework::SceneSystemRequests::CreateScene,
|
||||
data->m_sceneName);
|
||||
auto* sceneSystem = AzFramework::SceneSystemInterface::Get();
|
||||
AZ_Assert(sceneSystem, "Thumbnail system failed to get scene system implementation.");
|
||||
Outcome<AZStd::shared_ptr<AzFramework::Scene>, AZStd::string> createSceneOutcome =
|
||||
sceneSystem->CreateScene(data->m_sceneName);
|
||||
AZ_Assert(createSceneOutcome, createSceneOutcome.GetError().c_str()); // This should never happen unless scene creation has changed.
|
||||
createSceneOutcome.GetValue()->SetSubsystem(data->m_scene.get());
|
||||
data->m_frameworkScene = createSceneOutcome.GetValue();
|
||||
data->m_frameworkScene->SetSubsystem(data->m_scene.get());
|
||||
|
||||
bool success = false;
|
||||
AzFramework::SceneSystemRequestBus::BroadcastResult(
|
||||
success,
|
||||
&AzFramework::SceneSystemRequests::SetSceneForEntityContextId,
|
||||
data->m_entityContext->GetContextId(),
|
||||
data->m_frameworkScene);
|
||||
AZ_Assert(success, "Unable to set entity context on AzFramework::Scene: %s", data->m_sceneName.c_str());
|
||||
data->m_frameworkScene = createSceneOutcome.TakeValue();
|
||||
data->m_frameworkScene->SetSubsystem(data->m_scene);
|
||||
|
||||
data->m_frameworkScene->SetSubsystem(data->m_entityContext.get());
|
||||
// Create a render pipeline from the specified asset for the window context and add the pipeline to the scene
|
||||
RPI::RenderPipelineDescriptor pipelineDesc;
|
||||
pipelineDesc.m_mainViewTagName = "MainCamera";
|
||||
@@ -198,6 +189,7 @@ namespace AZ
|
||||
m_context->GetData()->DefaultModelPath,
|
||||
RPI::ModelAsset::RTTI_Type(),
|
||||
false);
|
||||
AZ_Error("ThumbnailRenderer", defaultModelAssetId.IsValid(), "Default model asset is invalid. Verify the asset %s exists.", m_context->GetData()->DefaultModelPath);
|
||||
if (m_context->GetData()->m_assetsToLoad.emplace(defaultModelAssetId).second)
|
||||
{
|
||||
data->m_defaultModelAsset.Create(defaultModelAssetId);
|
||||
@@ -212,6 +204,7 @@ namespace AZ
|
||||
m_context->GetData()->DefaultMaterialPath,
|
||||
RPI::MaterialAsset::RTTI_Type(),
|
||||
false);
|
||||
AZ_Error("ThumbnailRenderer", defaultMaterialAssetId.IsValid(), "Default material asset is invalid. Verify the asset %s exists.", m_context->GetData()->DefaultMaterialPath);
|
||||
if (m_context->GetData()->m_assetsToLoad.emplace(defaultMaterialAssetId).second)
|
||||
{
|
||||
data->m_defaultMaterialAsset.Create(defaultMaterialAssetId);
|
||||
|
||||
+8
-6
@@ -14,7 +14,7 @@
|
||||
#include <Atom/RPI.Public/RPISystemInterface.h>
|
||||
#include <Atom/RPI.Public/Scene.h>
|
||||
#include <AzFramework/Scene/Scene.h>
|
||||
#include <AzFramework/Scene/SceneSystemBus.h>
|
||||
#include <AzFramework/Scene/SceneSystemInterface.h>
|
||||
#include <Thumbnails/Rendering/ThumbnailRendererContext.h>
|
||||
#include <Thumbnails/Rendering/ThumbnailRendererData.h>
|
||||
#include <Thumbnails/Rendering/ThumbnailRendererSteps/ReleaseResourcesStep.h>
|
||||
@@ -49,11 +49,13 @@ namespace AZ
|
||||
m_context->GetData()->m_scene->Deactivate();
|
||||
m_context->GetData()->m_scene->RemoveRenderPipeline(m_context->GetData()->m_renderPipeline->GetId());
|
||||
RPI::RPISystemInterface::Get()->UnregisterScene(m_context->GetData()->m_scene);
|
||||
bool sceneRemovedSuccessfully = false;
|
||||
AzFramework::SceneSystemRequestBus::BroadcastResult(
|
||||
sceneRemovedSuccessfully,
|
||||
&AzFramework::SceneSystemRequests::RemoveScene,
|
||||
m_context->GetData()->m_sceneName);
|
||||
|
||||
auto sceneSystem = AzFramework::SceneSystemInterface::Get();
|
||||
AZ_Assert(sceneSystem, "Thumbnail system failed to get scene system implementation.");
|
||||
[[maybe_unused]] bool sceneRemovedSuccessfully = sceneSystem->RemoveScene(m_context->GetData()->m_sceneName);
|
||||
AZ_Assert(
|
||||
sceneRemovedSuccessfully, "Thumbnail system was unable to remove scene '%s' from the scene system.",
|
||||
m_context->GetData()->m_sceneName.c_str());
|
||||
m_context->GetData()->m_scene = nullptr;
|
||||
m_context->GetData()->m_renderPipeline = nullptr;
|
||||
}
|
||||
|
||||
+3
-1
@@ -11,6 +11,8 @@
|
||||
|
||||
set(FILES
|
||||
Source/Module.cpp
|
||||
Source/Animation/EditorAttachmentComponent.h
|
||||
Source/Animation/EditorAttachmentComponent.cpp
|
||||
Include/AtomLyIntegration/CommonFeatures/Material/EditorMaterialSystemComponentRequestBus.h
|
||||
Include/AtomLyIntegration/CommonFeatures/ReflectionProbe/EditorReflectionProbeBus.h
|
||||
Source/EditorCommonFeaturesSystemComponent.h
|
||||
@@ -112,4 +114,4 @@ set(FILES
|
||||
Source/SurfaceData/EditorSurfaceDataMeshComponent.cpp
|
||||
Source/SurfaceData/EditorSurfaceDataMeshComponent.h
|
||||
Resources/AtomLyIntegrationResources.qrc
|
||||
)
|
||||
)
|
||||
|
||||
+2
@@ -10,6 +10,8 @@
|
||||
#
|
||||
|
||||
set(FILES
|
||||
Source/Animation/AttachmentComponent.h
|
||||
Source/Animation/AttachmentComponent.cpp
|
||||
Source/CoreLights/AreaLightComponent.h
|
||||
Source/CoreLights/AreaLightComponent.cpp
|
||||
Source/CoreLights/AreaLightComponentConfig.cpp
|
||||
|
||||
Reference in New Issue
Block a user