Merge pull request #277 from aws-lumberyard-dev/nvsickle/MoreMainFixes

Cherry-pick several 1.0 viewport fixes to main
This commit is contained in:
Nicholas Van Sickle
2021-04-23 09:50:07 -07:00
committed by GitHub
14 changed files with 147 additions and 23 deletions
+8 -3
View File
@@ -1218,13 +1218,18 @@ void EditorViewportWidget::SetViewportId(int id)
CViewport::SetViewportId(id);
// Now that we have an ID, we can initialize our viewport.
m_renderViewport = new AtomToolsFramework::RenderViewportWidget(id, this);
m_defaultViewportContextName = m_renderViewport->GetViewportContext()->GetName();
m_renderViewport = new AtomToolsFramework::RenderViewportWidget(this, false);
if (!m_renderViewport->InitializeViewportContext(id))
{
AZ_Warning("EditorViewportWidget", false, "Failed to initialize RenderViewportWidget's ViewportContext");
return;
}
auto viewportContext = m_renderViewport->GetViewportContext();
m_defaultViewportContextName = viewportContext->GetName();
QBoxLayout* layout = new QBoxLayout(QBoxLayout::Direction::TopToBottom, this);
layout->setContentsMargins(QMargins());
layout->addWidget(m_renderViewport);
auto viewportContext = m_renderViewport->GetViewportContext();
viewportContext->ConnectViewMatrixChangedHandler(m_cameraViewMatrixChangeHandler);
viewportContext->ConnectProjectionMatrixChangedHandler(m_cameraProjectionMatrixChangeHandler);
@@ -118,6 +118,12 @@ namespace AZ
//! Update View's SRG values and compile. This should only be called once per frame before execute command lists.
void UpdateSrg();
using MatrixChangedEvent = AZ::Event<const AZ::Matrix4x4&>;
//! Notifies consumers when the world to view matrix has changed.
void ConnectWorldToViewMatrixChangedHandler(MatrixChangedEvent::Handler& handler);
//! Notifies consumers when the world to clip matrix has changed.
void ConnectWorldToClipMatrixChangedHandler(MatrixChangedEvent::Handler& handler);
private:
View() = delete;
View(const AZ::Name& name, UsageFlags usage);
@@ -182,6 +188,9 @@ namespace AZ
// view class doesn't contain subroutines called at the end of each frame
bool m_worldToClipMatrixChanged = true;
bool m_worldToClipPrevMatrixNeedsUpdate = false;
MatrixChangedEvent m_onWorldToClipMatrixChange;
MatrixChangedEvent m_onWorldToViewMatrixChange;
};
AZ_DEFINE_ENUM_BITWISE_OPERATORS(View::UsageFlags);
@@ -125,7 +125,9 @@ namespace AZ
AzFramework::WindowSize m_viewportSize;
SizeChangedEvent m_sizeChangedEvent;
MatrixChangedEvent m_viewMatrixChangedEvent;
MatrixChangedEvent::Handler m_onViewMatrixChangedHandler;
MatrixChangedEvent m_projectionMatrixChangedEvent;
MatrixChangedEvent::Handler m_onProjectionMatrixChangedHandler;
SceneChangedEvent m_sceneChangedEvent;
ViewportContextManager* m_manager;
RenderPipelinePtr m_currentPipeline;
@@ -104,6 +104,9 @@ namespace AZ
m_worldToClipMatrix = m_viewToClipMatrix * m_worldToViewMatrix;
m_worldToClipMatrixChanged = true;
m_onWorldToViewMatrixChange.Signal(m_worldToViewMatrix);
m_onWorldToClipMatrixChange.Signal(m_worldToClipMatrix);
InvalidateSrg();
}
@@ -132,6 +135,9 @@ namespace AZ
m_clipToWorldMatrix = m_viewToWorldMatrix * m_clipToViewMatrix;
m_worldToClipMatrixChanged = true;
m_onWorldToViewMatrixChange.Signal(m_worldToViewMatrix);
m_onWorldToClipMatrixChange.Signal(m_worldToClipMatrix);
InvalidateSrg();
}
@@ -166,6 +172,8 @@ namespace AZ
m_unprojectionConstants.SetZ(float(-tanHalfFovX));
m_unprojectionConstants.SetW(float(tanHalfFovY));
m_onWorldToClipMatrixChange.Signal(m_worldToClipMatrix);
InvalidateSrg();
}
@@ -225,6 +233,16 @@ namespace AZ
passWithDrawListTag->SortDrawList(drawList);
}
void View::ConnectWorldToViewMatrixChangedHandler(View::MatrixChangedEvent::Handler& handler)
{
handler.Connect(m_onWorldToViewMatrixChange);
}
void View::ConnectWorldToClipMatrixChangedHandler(View::MatrixChangedEvent::Handler& handler)
{
handler.Connect(m_onWorldToClipMatrixChange);
}
// [GFX TODO] This function needs unit tests and might need to be reworked
RHI::DrawItemSortKey View::GetSortKeyForPosition(const Vector3& positionInWorld) const
{
@@ -34,6 +34,15 @@ namespace AZ
&AzFramework::WindowRequestBus::Events::GetClientAreaSize);
AzFramework::WindowNotificationBus::Handler::BusConnect(nativeWindow);
m_onProjectionMatrixChangedHandler = ViewportContext::MatrixChangedEvent::Handler([this](const AZ::Matrix4x4& matrix)
{
m_projectionMatrixChangedEvent.Signal(matrix);
});
m_onViewMatrixChangedHandler = ViewportContext::MatrixChangedEvent::Handler([this](const AZ::Matrix4x4& matrix)
{
m_projectionMatrixChangedEvent.Signal(matrix);
});
SetRenderScene(renderScene);
}
@@ -175,7 +184,6 @@ namespace AZ
void ViewportContext::SetCameraProjectionMatrix(const AZ::Matrix4x4& matrix)
{
GetDefaultView()->SetViewToClipMatrix(matrix);
m_projectionMatrixChangedEvent.Signal(matrix);
}
AZ::Transform ViewportContext::GetCameraTransform() const
@@ -192,18 +200,23 @@ namespace AZ
{
const auto view = GetDefaultView();
view->SetCameraTransform(AZ::Matrix3x4::CreateFromTransform(transform.GetOrthogonalized()));
m_viewMatrixChangedEvent.Signal(view->GetWorldToViewMatrix());
}
void ViewportContext::SetDefaultView(ViewPtr view)
{
if (m_defaultView != view)
{
m_onProjectionMatrixChangedHandler.Disconnect();
m_onViewMatrixChangedHandler.Disconnect();
m_defaultView = view;
UpdatePipelineView();
m_viewMatrixChangedEvent.Signal(view->GetWorldToViewMatrix());
m_projectionMatrixChangedEvent.Signal(view->GetViewToClipMatrix());
view->ConnectWorldToViewMatrixChangedHandler(m_onViewMatrixChangedHandler);
view->ConnectWorldToClipMatrixChangedHandler(m_onProjectionMatrixChangedHandler);
}
}
@@ -43,9 +43,16 @@ namespace AtomToolsFramework
//! Creates a RenderViewportWidget.
//! Requires the Atom RPI to be initialized in order
//! to internally construct an RPI::ViewportContext.
explicit RenderViewportWidget(AzFramework::ViewportId id = AzFramework::InvalidViewportId, QWidget* parent = nullptr);
//! If initializeViewportContext is set to false, nothing will be displayed on-screen until InitiliazeViewportContext is called.
explicit RenderViewportWidget(QWidget* parent = nullptr, bool shouldInitializeViewportContext = true);
~RenderViewportWidget();
//! Initializes the underlying ViewportContext, if it hasn't already been.
//! If id is specified, the target ViewportContext will be overridden.
//! NOTE: ViewportContext IDs must be unique.
//! Returns true if the ViewportContext is available
//! (i.e. GetViewportContext will return a valid pointer).
bool InitializeViewportContext(AzFramework::ViewportId id = AzFramework::InvalidViewportId);
//! Gets the name associated with this viewport's ViewportContext.
//! This context name can be used to adjust the current Camera
//! independently of the underlying viewport.
@@ -31,12 +31,35 @@
namespace AtomToolsFramework
{
RenderViewportWidget::RenderViewportWidget(AzFramework::ViewportId id, QWidget* parent)
RenderViewportWidget::RenderViewportWidget(QWidget* parent, bool shouldInitializeViewportContext)
: QWidget(parent)
, AzFramework::InputChannelEventListener(AzFramework::InputChannelEventListener::GetPriorityDefault())
{
if (shouldInitializeViewportContext)
{
InitializeViewportContext();
}
setUpdatesEnabled(false);
setFocusPolicy(Qt::FocusPolicy::WheelFocus);
setMouseTracking(true);
}
bool RenderViewportWidget::InitializeViewportContext(AzFramework::ViewportId id)
{
if (m_viewportContext != nullptr)
{
AZ_Assert(id == AzFramework::InvalidViewportId || m_viewportContext->GetId() == id, "Attempted to reinitialize RenderViewportWidget with a different ID");
return true;
}
auto viewportContextManager = AZ::Interface<AZ::RPI::ViewportContextRequestsInterface>::Get();
AZ_Assert(viewportContextManager, "Attempted to construct RenderViewportWidget without ViewportContextManager");
AZ_Assert(viewportContextManager, "Attempted to initialize RenderViewportWidget without ViewportContextManager");
if (viewportContextManager == nullptr)
{
return false;
}
// Before we do anything else, we must create a ViewportContext which will give us a ViewportId if we didn't manually specify one.
AZ::RPI::ViewportContextRequestsInterface::CreationParameters params;
@@ -46,6 +69,11 @@ namespace AtomToolsFramework
AzFramework::WindowRequestBus::Handler::BusConnect(params.windowHandle);
m_viewportContext = viewportContextManager->CreateViewportContext(AZ::Name(), params);
if (m_viewportContext == nullptr)
{
return false;
}
SetControllerList(AZStd::make_shared<AzFramework::ViewportControllerList>());
AZ::Name cameraName = AZ::Name(AZStd::string::format("Viewport %i Default Camera", m_viewportContext->GetId()));
@@ -58,9 +86,7 @@ namespace AtomToolsFramework
AZ::TickBus::Handler::BusConnect();
AzFramework::WindowRequestBus::Handler::BusConnect(params.windowHandle);
setUpdatesEnabled(false);
setFocusPolicy(Qt::FocusPolicy::WheelFocus);
setMouseTracking(true);
return true;
}
RenderViewportWidget::~RenderViewportWidget()
@@ -38,7 +38,7 @@ namespace MaterialEditor
{
MaterialViewportWidget::MaterialViewportWidget(QWidget* parent)
: AtomToolsFramework::RenderViewportWidget(AzFramework::InvalidViewportId, parent)
: AtomToolsFramework::RenderViewportWidget(parent)
, m_ui(new Ui::MaterialViewportWidget)
{
m_ui->setupUi(this);
@@ -59,14 +59,8 @@ namespace AZ
const AZ::Name contextName = atomViewportRequests->GetDefaultViewportContextName();
AZ::RPI::ViewportContextNotificationBus::Handler::BusConnect(contextName);
#if defined(IMGUI_ENABLED)
ImGui::ImGuiManagerListenerBus::Broadcast(&ImGui::IImGuiManagerListener::SetResolutionMode, ImGui::ImGuiResolutionMode::LockToResolution);
auto defaultViewportContext = atomViewportRequests->GetDefaultViewportContext();
if (defaultViewportContext)
{
OnViewportSizeChanged(defaultViewportContext->GetViewportSize());
}
#endif
m_initialized = false;
InitializeViewportSizeIfNeeded();
}
void ImguiAtomSystemComponent::Deactivate()
@@ -75,6 +69,23 @@ namespace AZ
AZ::RPI::ViewportContextNotificationBus::Handler::BusDisconnect();
}
void ImguiAtomSystemComponent::InitializeViewportSizeIfNeeded()
{
#if defined(IMGUI_ENABLED)
if (m_initialized)
{
return;
}
auto atomViewportRequests = AZ::Interface<AZ::RPI::ViewportContextRequestsInterface>::Get();
auto defaultViewportContext = atomViewportRequests->GetDefaultViewportContext();
if (defaultViewportContext)
{
// If this succeeds, m_initialized will be set to true.
OnViewportSizeChanged(defaultViewportContext->GetViewportSize());
}
#endif
}
void ImguiAtomSystemComponent::RenderImGuiBuffers(const ImDrawData& drawData)
{
Render::ImGuiSystemRequestBus::Broadcast(&Render::ImGuiSystemRequests::RenderImGuiBuffersToCurrentViewport, drawData);
@@ -83,6 +94,7 @@ namespace AZ
void ImguiAtomSystemComponent::OnRenderTick()
{
#if defined(IMGUI_ENABLED)
InitializeViewportSizeIfNeeded();
ImGui::ImGuiManagerListenerBus::Broadcast(&ImGui::IImGuiManagerListener::Render);
#endif
}
@@ -90,7 +102,17 @@ namespace AZ
void ImguiAtomSystemComponent::OnViewportSizeChanged(AzFramework::WindowSize size)
{
#if defined(IMGUI_ENABLED)
ImGui::ImGuiManagerListenerBus::Broadcast(&ImGui::IImGuiManagerListener::SetImGuiRenderResolution, ImVec2{aznumeric_cast<float>(size.m_width), aznumeric_cast<float>(size.m_height)});
ImGui::ImGuiManagerListenerBus::Broadcast([this, size](ImGui::ImGuiManagerListenerBus::Events* imgui)
{
imgui->OverrideRenderWindowSize(size.m_width, size.m_height);
// ImGuiManagerListenerBus may not have been connected when this system component is activated
// as ImGuiManager is not part of a system component we can require and instead just listens for ESYSTEM_EVENT_GAME_POST_INIT.
// Let our ImguiAtomSystemComponent know once we successfully connect and update the viewport size.
if (!m_initialized)
{
m_initialized = true;
}
});
#endif
}
}
@@ -48,6 +48,7 @@ namespace AZ
void Deactivate() override;
private:
void InitializeViewportSizeIfNeeded();
// OtherActiveImGuiRequestBus overrides ...
void RenderImGuiBuffers(const ImDrawData& drawData) override;
@@ -57,6 +58,7 @@ namespace AZ
void OnViewportSizeChanged(AzFramework::WindowSize size) override;
DebugConsole m_debugConsole;
bool m_initialized = false;
};
} // namespace LYIntegration
} // namespace AZ
+2
View File
@@ -90,6 +90,8 @@ namespace ImGui
virtual void SetResolutionMode(ImGuiResolutionMode state) = 0;
virtual const ImVec2& GetImGuiRenderResolution() const = 0;
virtual void SetImGuiRenderResolution(const ImVec2& res) = 0;
virtual void OverrideRenderWindowSize(uint32_t width, uint32_t height) = 0;
virtual void RestoreRenderWindowSizeToDefault() = 0;
virtual void Render() = 0;
};
typedef AZ::EBus<IImGuiManagerListener> ImGuiManagerListenerBus;
+16 -1
View File
@@ -262,6 +262,21 @@ void ImGuiManager::Shutdown()
ImGui::DestroyContext(m_imguiContext);
}
void ImGui::ImGuiManager::OverrideRenderWindowSize(uint32_t width, uint32_t height)
{
m_windowSize.m_width = width;
m_windowSize.m_height = height;
m_overridingWindowSize = true;
// Don't listen for window updates if our window size is being overridden
AzFramework::WindowNotificationBus::Handler::BusDisconnect();
}
void ImGui::ImGuiManager::RestoreRenderWindowSizeToDefault()
{
m_overridingWindowSize = false;
InitWindowSize();
}
void ImGuiManager::Render()
{
if (m_clientMenuBarState == DisplayState::Hidden && m_editorWindowState == DisplayState::Hidden)
@@ -757,7 +772,7 @@ void ImGuiManager::InitWindowSize()
{
// We only need to initialize the window size by querying the window the first time.
// After that we will get OnWindowResize notifications
if (!AzFramework::WindowNotificationBus::Handler::BusIsConnected())
if (!m_overridingWindowSize && !AzFramework::WindowNotificationBus::Handler::BusIsConnected())
{
AzFramework::NativeWindowHandle windowHandle = nullptr;
AzFramework::WindowSystemRequestBus::BroadcastResult(windowHandle, &AzFramework::WindowSystemRequestBus::Events::GetDefaultWindowHandle);
+3
View File
@@ -60,6 +60,8 @@ namespace ImGui
void SetResolutionMode(ImGuiResolutionMode mode) override { m_resolutionMode = mode; }
const ImVec2& GetImGuiRenderResolution() const override { return m_renderResolution; }
void SetImGuiRenderResolution(const ImVec2& res) override { m_renderResolution = res; }
void OverrideRenderWindowSize(uint32_t width, uint32_t height) override;
void RestoreRenderWindowSizeToDefault() override;
void Render() override;
// -- ImGuiManagerListenerBus Interface -------------------------------------------------------------------
@@ -89,6 +91,7 @@ namespace ImGui
ImVec2 m_renderResolution = ImVec2(1920.0f, 1080.0f);
ImVec2 m_lastRenderResolution;
AzFramework::WindowSize m_windowSize = AzFramework::WindowSize(1920, 1080);
bool m_overridingWindowSize = false;
// Rendering buffers
std::vector<SVF_P3F_C4B_T2F> m_vertBuffer;
+1 -1
View File
@@ -204,7 +204,7 @@ namespace
} // anonymous namespace.
ViewportWidget::ViewportWidget(EditorWindow* parent)
: AtomToolsFramework::RenderViewportWidget(AzFramework::InvalidViewportId, parent)
: AtomToolsFramework::RenderViewportWidget(parent)
, m_editorWindow(parent)
, m_viewportInteraction(new ViewportInteraction(m_editorWindow))
, m_viewportAnchor(new ViewportAnchor())