Merge remote-tracking branch 'origin' into MultiplayerComponents
This commit is contained in:
@@ -13,7 +13,6 @@
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzCore/Module/Module.h>
|
||||
#include <AtomBridgeModule.h>
|
||||
#include <BuilderComponent.h>
|
||||
|
||||
#include "./Editor/AssetCollectionAsyncLoaderTestComponent.h"
|
||||
|
||||
@@ -33,7 +32,6 @@ namespace AZ
|
||||
{
|
||||
// Push results of [MyComponent]::CreateDescriptor() into m_descriptors here.
|
||||
m_descriptors.insert(m_descriptors.end(), {
|
||||
BuilderComponent::CreateDescriptor(),
|
||||
AssetCollectionAsyncLoaderTestComponent::CreateDescriptor(),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -62,12 +62,10 @@ namespace AZ
|
||||
|
||||
AtomBridgeSystemComponent::AtomBridgeSystemComponent()
|
||||
{
|
||||
AZ::Interface<AzFramework::AtomActiveInterface>::Register(this);
|
||||
}
|
||||
|
||||
AtomBridgeSystemComponent::~AtomBridgeSystemComponent()
|
||||
{
|
||||
AZ::Interface<AzFramework::AtomActiveInterface>::Unregister(this);
|
||||
}
|
||||
|
||||
void AtomBridgeSystemComponent::GetProvidedServices(ComponentDescriptor::DependencyArrayType& provided)
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
|
||||
#include <AzCore/Component/Component.h>
|
||||
|
||||
#include <AzFramework/API/AtomActiveInterface.h>
|
||||
#include <AzFramework/Render/RenderSystemBus.h>
|
||||
#include <AzFramework/Components/DeprecatedComponentsBus.h>
|
||||
|
||||
@@ -37,7 +36,6 @@ namespace AZ
|
||||
|
||||
class AtomBridgeSystemComponent
|
||||
: public Component
|
||||
, public AzFramework::AtomActiveInterface
|
||||
, public AzFramework::Render::RenderSystemRequestBus::Handler
|
||||
, public AzFramework::Components::DeprecatedComponentsRequestBus::Handler
|
||||
, public Render::Bootstrap::NotificationBus::Handler
|
||||
|
||||
+43
-12
@@ -244,9 +244,6 @@ namespace AZ::AtomBridge
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Partial implementation of the DebugDisplayRequestBus on Atom.
|
||||
// Commented out function prototypes are waiting to be implemented.
|
||||
// work tracked in [ATOM-3459]
|
||||
AtomDebugDisplayViewportInterface::AtomDebugDisplayViewportInterface(AZ::RPI::ViewportContextPtr viewportContextPtr)
|
||||
{
|
||||
ResetRenderState();
|
||||
@@ -272,9 +269,8 @@ namespace AZ::AtomBridge
|
||||
InitInternal(scene, nullptr);
|
||||
}
|
||||
|
||||
void AtomDebugDisplayViewportInterface::InitInternal(RPI::Scene* scene, AZ::RPI::ViewportContextPtr viewportContextPtr)
|
||||
void AtomDebugDisplayViewportInterface::UpdateAuxGeom(RPI::Scene* scene, AZ::RPI::View* view)
|
||||
{
|
||||
AzFramework::DebugDisplayRequestBus::Handler::BusDisconnect(m_viewportId);
|
||||
if (!scene)
|
||||
{
|
||||
m_auxGeomPtr = nullptr;
|
||||
@@ -286,20 +282,46 @@ namespace AZ::AtomBridge
|
||||
m_auxGeomPtr = nullptr;
|
||||
return;
|
||||
}
|
||||
if (m_defaultInstance)
|
||||
// default instance draws to all viewports in the default scene
|
||||
if (m_defaultInstance || !view)
|
||||
{
|
||||
m_auxGeomPtr = auxGeomFP->GetDrawQueue();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_auxGeomPtr = auxGeomFP->GetOrCreateDrawQueueForView(viewportContextPtr->GetDefaultView().get());
|
||||
// cache the aux geom draw interface for the current view (aka camera)
|
||||
m_auxGeomPtr = auxGeomFP->GetOrCreateDrawQueueForView(view);
|
||||
}
|
||||
}
|
||||
|
||||
void AtomDebugDisplayViewportInterface::InitInternal(RPI::Scene* scene, AZ::RPI::ViewportContextPtr viewportContextPtr)
|
||||
{
|
||||
AzFramework::DebugDisplayRequestBus::Handler::BusDisconnect(m_viewportId);
|
||||
UpdateAuxGeom(scene, viewportContextPtr ? viewportContextPtr->GetDefaultView().get() : nullptr);
|
||||
AzFramework::DebugDisplayRequestBus::Handler::BusConnect(m_viewportId);
|
||||
if (!m_defaultInstance) // only the per viewport instances need to listen for viewport changes
|
||||
{
|
||||
AZ::RPI::ViewportContextIdNotificationBus::Handler::BusConnect(viewportContextPtr->GetId());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void AtomDebugDisplayViewportInterface::OnViewportDefaultViewChanged(AZ::RPI::ViewPtr view)
|
||||
{
|
||||
ResetRenderState();
|
||||
if (!m_defaultInstance)
|
||||
{
|
||||
// handle viewport update (view change, scene change, etc
|
||||
auto viewportContextManager = AZ::Interface<AZ::RPI::ViewportContextRequestsInterface>::Get();
|
||||
AZ::RPI::ViewportContextPtr viewportContextPtr = viewportContextManager->GetViewportContextById(m_viewportId);
|
||||
UpdateAuxGeom(viewportContextPtr->GetRenderScene().get(), viewportContextPtr->GetDefaultView().get());
|
||||
}
|
||||
}
|
||||
|
||||
AtomDebugDisplayViewportInterface::~AtomDebugDisplayViewportInterface()
|
||||
{
|
||||
AzFramework::DebugDisplayRequestBus::Handler::BusDisconnect(m_viewportId);
|
||||
AZ::RPI::ViewportContextIdNotificationBus::Handler::BusDisconnect();
|
||||
m_viewportId = AzFramework::InvalidViewportId;
|
||||
m_auxGeomPtr = nullptr;
|
||||
}
|
||||
@@ -1234,8 +1256,15 @@ namespace AZ::AtomBridge
|
||||
int srcOffsetX [[maybe_unused]],
|
||||
int srcOffsetY [[maybe_unused]])
|
||||
{
|
||||
// abort draw if draw is invalid or font query interface is missing.
|
||||
if (!text || size == 0.0f || !AZ::Interface<AzFramework::FontQueryInterface>::Get())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AzFramework::FontDrawInterface* fontDrawInterface = AZ::Interface<AzFramework::FontQueryInterface>::Get()->GetDefaultFontDrawInterface();
|
||||
if (!fontDrawInterface || !text || size == 0.0f)
|
||||
// abort draw if font draw interface is missing
|
||||
if (!fontDrawInterface)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -1263,13 +1292,15 @@ namespace AZ::AtomBridge
|
||||
const char* text,
|
||||
bool center)
|
||||
{
|
||||
auto fontQueryInterface = AZ::Interface<AzFramework::FontQueryInterface>::Get();
|
||||
if (!fontQueryInterface)
|
||||
// abort draw if draw is invalid or font query interface is missing.
|
||||
if (!text || size == 0.0f || !AZ::Interface<AzFramework::FontQueryInterface>::Get())
|
||||
{
|
||||
return;
|
||||
}
|
||||
AzFramework::FontDrawInterface* fontDrawInterface = fontQueryInterface->GetDefaultFontDrawInterface();
|
||||
if (!fontDrawInterface || !text || size == 0.0f)
|
||||
|
||||
AzFramework::FontDrawInterface* fontDrawInterface = AZ::Interface<AzFramework::FontQueryInterface>::Get()->GetDefaultFontDrawInterface();
|
||||
// abort draw if font draw interface is missing
|
||||
if (!fontDrawInterface)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <Atom/RPI.Public/RPISystemInterface.h>
|
||||
#include <Atom/RPI.Public/AuxGeom/AuxGeomDraw.h>
|
||||
#include <Atom/RPI.Public/ViewportContext.h>
|
||||
#include <Atom/RPI.Public/ViewportContextBus.h>
|
||||
|
||||
namespace AZ::AtomBridge
|
||||
{
|
||||
@@ -121,6 +122,7 @@ namespace AZ::AtomBridge
|
||||
|
||||
class AtomDebugDisplayViewportInterface final
|
||||
: public AzFramework::DebugDisplayRequestBus::Handler
|
||||
, public AZ::RPI::ViewportContextIdNotificationBus::Handler
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(AtomDebugDisplayViewportInterface, "{09AF6A46-0100-4FBF-8F94-E6B221322D14}", AzFramework::DebugDisplayRequestBus::Handler);
|
||||
@@ -198,6 +200,12 @@ namespace AZ::AtomBridge
|
||||
void PopMatrix() override;
|
||||
|
||||
private:
|
||||
|
||||
// ViewportContextIdNotificationBus handlers
|
||||
void OnViewportDefaultViewChanged(AZ::RPI::ViewPtr view) override;
|
||||
|
||||
|
||||
// internal helper functions
|
||||
using LineSegmentFilterFunc = AZStd::function<bool(const AZ::Vector3& lineStart, const AZ::Vector3& lineEnd, int segmentIndex)>;
|
||||
enum CircleAxis
|
||||
{
|
||||
@@ -245,6 +253,7 @@ namespace AZ::AtomBridge
|
||||
|
||||
const AZ::Matrix3x4& GetCurrentTransform() const;
|
||||
|
||||
void UpdateAuxGeom(RPI::Scene* scene, AZ::RPI::View* view);
|
||||
void InitInternal(RPI::Scene* scene, AZ::RPI::ViewportContextPtr viewportContextPtr);
|
||||
|
||||
AZ::RPI::ViewportContextPtr GetViewportContext() const;
|
||||
@@ -254,10 +263,12 @@ namespace AZ::AtomBridge
|
||||
RenderState m_rendState;
|
||||
|
||||
AZ::RPI::AuxGeomDrawPtr m_auxGeomPtr;
|
||||
bool m_defaultInstance = false; // only true for drawing to a particular viewport. What would 2D drawing mean in a scene with several windows?
|
||||
|
||||
// m_defaultInstance is true for the instance that multicasts the debug draws to all viewports
|
||||
// (with an AuxGeom render pass) in the default scene.
|
||||
bool m_defaultInstance = false;
|
||||
AzFramework::ViewportId m_viewportId = AzFramework::InvalidViewportId; // Address this instance answers on.
|
||||
AZ::RPI::ViewportContext::SceneChangedEvent::Handler
|
||||
m_sceneChangeHandler;
|
||||
AZ::RPI::ViewportContext::SceneChangedEvent::Handler m_sceneChangeHandler;
|
||||
};
|
||||
|
||||
// this is duplicated from Cry_Math.h, GetBasisVectors.
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzCore/Component/Entity.h>
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/Interface/Interface.h>
|
||||
|
||||
#include <BuilderComponent.h>
|
||||
|
||||
#include <AssetBuilderSDK/AssetBuilderSDK.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace AtomBridge
|
||||
{
|
||||
void BuilderComponent::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (auto* serialize = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serialize->Class<BuilderComponent, AZ::Component>()
|
||||
->Version(0)
|
||||
->Attribute(AZ::Edit::Attributes::SystemComponentTags, AZStd::vector<AZ::Crc32>({ AssetBuilderSDK::ComponentTags::AssetBuilder }))
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
BuilderComponent::BuilderComponent()
|
||||
{
|
||||
AZ::Interface<AzFramework::AtomActiveInterface>::Register(this);
|
||||
}
|
||||
|
||||
BuilderComponent::~BuilderComponent()
|
||||
{
|
||||
AZ::Interface<AzFramework::AtomActiveInterface>::Unregister(this);
|
||||
}
|
||||
|
||||
void BuilderComponent::Activate()
|
||||
{
|
||||
}
|
||||
|
||||
void BuilderComponent::Deactivate()
|
||||
{
|
||||
}
|
||||
} // namespace RPI
|
||||
} // namespace AZ
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Component/Component.h>
|
||||
#include <AzFramework/API/AtomActiveInterface.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace AtomBridge
|
||||
{
|
||||
class BuilderComponent final
|
||||
: public AZ::Component
|
||||
, public AzFramework::AtomActiveInterface
|
||||
{
|
||||
public:
|
||||
AZ_COMPONENT(BuilderComponent, "{D1FE015B-8431-4155-8FD0-8197F246901A}");
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
BuilderComponent();
|
||||
~BuilderComponent() override;
|
||||
|
||||
// AZ::Component overrides...
|
||||
void Activate() override;
|
||||
void Deactivate() override;
|
||||
};
|
||||
} // namespace RPI
|
||||
} // namespace AZ
|
||||
@@ -13,8 +13,6 @@ set(FILES
|
||||
Source/AtomBridgeEditorModule.cpp
|
||||
Source/AtomBridgeModule.cpp
|
||||
Source/AtomBridgeModule.h
|
||||
Source/BuilderComponent.cpp
|
||||
Source/BuilderComponent.h
|
||||
Source/Editor/AssetCollectionAsyncLoaderTestComponent.cpp
|
||||
Source/Editor/AssetCollectionAsyncLoaderTestComponent.h
|
||||
)
|
||||
|
||||
@@ -226,7 +226,7 @@ namespace AZ
|
||||
|
||||
private:
|
||||
virtual ~FFont();
|
||||
bool InitFont();
|
||||
bool InitFont(AZ::RPI::Scene* renderScene);
|
||||
bool InitTexture();
|
||||
bool InitCache();
|
||||
|
||||
|
||||
@@ -99,7 +99,7 @@ AZ::RPI::WindowContextSharedPtr AZ::FFont::GetDefaultWindowContext() const
|
||||
return {};
|
||||
}
|
||||
|
||||
bool AZ::FFont::InitFont()
|
||||
bool AZ::FFont::InitFont(AZ::RPI::Scene* renderScene)
|
||||
{
|
||||
auto initializationState = InitializationState::Uninitialized;
|
||||
// Do an atomic transition to Initializing if we're in the Uninitialized state.
|
||||
@@ -111,8 +111,13 @@ bool AZ::FFont::InitFont()
|
||||
return initializationState == InitializationState::Initialized;
|
||||
}
|
||||
|
||||
if (!renderScene)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create and initialize DynamicDrawContext for font draw
|
||||
AZ::RPI::Ptr<AZ::RPI::DynamicDrawContext> dynamicDraw = m_atomFont->GetOrCreateDynamicDrawForScene(GetDefaultViewportContext()->GetRenderScene().get());
|
||||
AZ::RPI::Ptr<AZ::RPI::DynamicDrawContext> dynamicDraw = m_atomFont->GetOrCreateDynamicDrawForScene(renderScene);
|
||||
|
||||
// Save draw srg input indices for later use
|
||||
Data::Instance<RPI::ShaderResourceGroup> drawSrg = dynamicDraw->NewDrawSrg();
|
||||
@@ -299,7 +304,7 @@ void AZ::FFont::DrawStringUInternal(
|
||||
const TextDrawContext& ctx)
|
||||
{
|
||||
// Lazily ensure we're initialized before attempting to render.
|
||||
if (!InitFont())
|
||||
if (!viewportContext || !InitFont(viewportContext->GetRenderScene().get()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -1623,7 +1628,7 @@ void AZ::FFont::ScaleCoord(const RHI::Viewport& viewport, float& x, float& y) co
|
||||
|
||||
void AZ::FFont::OnBootstrapSceneReady([[maybe_unused]] AZ::RPI::Scene* bootstrapScene)
|
||||
{
|
||||
InitFont();
|
||||
InitFont(bootstrapScene);
|
||||
}
|
||||
|
||||
static void SetCommonContextFlags(AZ::TextDrawContext& ctx, const AzFramework::TextDrawParameters& params)
|
||||
|
||||
+1
@@ -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);
|
||||
|
||||
+14
-1
@@ -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>
|
||||
@@ -125,6 +127,14 @@ namespace AZ
|
||||
|
||||
QStringList arguments;
|
||||
arguments.append(sourcePath.c_str());
|
||||
|
||||
// Use the same RHI as the main editor
|
||||
AZ::Name apiName = AZ::RHI::Factory::Get().GetName();
|
||||
if (!apiName.IsEmpty())
|
||||
{
|
||||
arguments.append(QString("--rhi=%1").arg(apiName.GetCStr()));
|
||||
}
|
||||
|
||||
AtomToolsFramework::LaunchTool("MaterialEditor", ".exe", arguments);
|
||||
}
|
||||
|
||||
@@ -139,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("");
|
||||
}
|
||||
|
||||
+117
-108
@@ -133,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;
|
||||
}
|
||||
|
||||
@@ -158,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
|
||||
@@ -276,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;
|
||||
|
||||
+6
@@ -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,12 @@ 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);
|
||||
|
||||
|
||||
+26
-5
@@ -111,6 +111,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 +142,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
|
||||
{
|
||||
@@ -169,8 +184,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 +206,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)
|
||||
@@ -239,14 +260,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();
|
||||
|
||||
Reference in New Issue
Block a user