Merge branch 'development' into LYN-3705-2

This commit is contained in:
sphrose
2021-07-22 10:39:14 +01:00
434 changed files with 3617 additions and 1486 deletions
+15 -1
View File
@@ -403,6 +403,19 @@ bool EditorViewportWidget::event(QEvent* event)
m_keyDown.clear();
break;
case QEvent::ShortcutOverride:
{
// Ensure we exit game mode on escape, even if something else would eat our escape key event.
if (static_cast<QKeyEvent*>(event)->key() == Qt::Key_Escape && GetIEditor()->IsInGameMode())
{
GetIEditor()->SetInGameMode(false);
event->accept();
return true;
}
break;
}
case QEvent::Shortcut:
// a shortcut should immediately clear us, otherwise the release event never gets sent
m_keyDown.clear();
@@ -456,7 +469,6 @@ void EditorViewportWidget::Update()
auto m = AZMatrix3x4ToLYMatrix3x4(matrix);
SetViewTM(m);
SetFOV(cameraState.m_fovOrZoom);
m_Camera.SetZRange(cameraState.m_nearClip, cameraState.m_farClip);
}
@@ -2601,6 +2613,8 @@ void EditorViewportWidget::DestroyRenderContext()
//////////////////////////////////////////////////////////////////////////
void EditorViewportWidget::SetDefaultCamera()
{
// Ensure the FOV matches our internally stored setting
SetFOV(GetFOV());
if (IsDefaultCamera())
{
return;
@@ -296,8 +296,8 @@ private:
AZStd::unordered_set<AZ::EntityId> m_unsavedEntities;
const AZStd::string m_defaultComponentIconLocation = "Icons/Components/Component_Placeholder.svg";
const AZStd::string m_defaultComponentViewportIconLocation = "Icons/Components/Viewport/Component_Placeholder.png";
const AZStd::string m_defaultEntityIconLocation = "Icons/Components/Viewport/Transform.png";
const AZStd::string m_defaultComponentViewportIconLocation = "Icons/Components/Viewport/Component_Placeholder.svg";
const AZStd::string m_defaultEntityIconLocation = "Icons/Components/Viewport/Transform.svg";
bool m_debugDisplayBusImplementationActive = false;
-1
View File
@@ -346,7 +346,6 @@ bool ShortcutDispatcher::eventFilter(QObject* obj, QEvent* ev)
case QEvent::Shortcut:
return shortcutFilter(obj, static_cast<QShortcutEvent*>(ev));
break;
case QEvent::MouseButtonPress:
if (!s_lastFocus || !IsAContainerForB(qobject_cast<QWidget*>(obj), s_lastFocus))
@@ -67,6 +67,17 @@ namespace AzPhysics
}
}
// class for exposing free functions to script
class SceneQueries
{
public:
AZ_TYPE_INFO(SceneQueries, "{4EFA3DA5-C0E3-4753-8C55-202228CA527E}");
AZ_CLASS_ALLOCATOR(SceneQueries, AZ::SystemAllocator, 0);
SceneQueries() = default;
~SceneQueries() = default;
};
/*static*/ void SceneQueryRequest::Reflect(AZ::ReflectContext* context)
{
if (auto* serializeContext = azdynamic_cast<AZ::SerializeContext*>(context))
@@ -96,6 +107,7 @@ namespace AzPhysics
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
->Attribute(AZ::Script::Attributes::Module, "physics")
->Attribute(AZ::Script::Attributes::Category, "PhysX")
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Property("Collision", BehaviorValueProperty(&SceneQueryRequest::m_collisionGroup))
// Until enum class support for behavior context is done, expose this as an int
->Property("QueryType", [](const SceneQueryRequest& self) { return static_cast<int>(self.m_queryType); },
@@ -134,11 +146,28 @@ namespace AzPhysics
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
->Attribute(AZ::Script::Attributes::Module, "physics")
->Attribute(AZ::Script::Attributes::Category, "PhysX")
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Property("Distance", BehaviorValueProperty(&RayCastRequest::m_distance))
->Property("Start", BehaviorValueProperty(&RayCastRequest::m_start))
->Property("Direction", BehaviorValueProperty(&RayCastRequest::m_direction))
->Property("ReportMultipleHits", BehaviorValueProperty(&RayCastRequest::m_reportMultipleHits))
;
behaviorContext->Class<SceneQueries>("SceneQueries")
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
->Attribute(AZ::Script::Attributes::Module, "physics")
->Attribute(AZ::Script::Attributes::Category, "PhysX")
->Method(
"CreateRayCastRequest",
[](const AZ::Vector3& start, const AZ::Vector3& direction, float distance, const AZStd::string& collisionGroup)
{
RayCastRequest request;
request.m_start = start;
request.m_direction = direction;
request.m_distance = distance;
request.m_collisionGroup = CollisionGroup(collisionGroup);
return request;
});
}
}
@@ -162,6 +191,7 @@ namespace AzPhysics
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
->Attribute(AZ::Script::Attributes::Module, "physics")
->Attribute(AZ::Script::Attributes::Category, "PhysX")
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Property("Distance", BehaviorValueProperty(&ShapeCastRequest::m_distance))
->Property("Start", BehaviorValueProperty(&ShapeCastRequest::m_start))
->Property("Direction", BehaviorValueProperty(&ShapeCastRequest::m_direction))
@@ -175,7 +205,6 @@ namespace AzPhysics
return ShapeCastRequestHelpers::CreateSphereCastRequest(
radius, startPose, direction, distance, queryType, collisionGroup, nullptr);
});
behaviorContext->Method(
"CreateBoxCastRequest",
[](const AZ::Vector3& boxDimensions, const AZ::Transform& startPose, const AZ::Vector3& direction, float distance,
@@ -184,7 +213,6 @@ namespace AzPhysics
return ShapeCastRequestHelpers::CreateBoxCastRequest(
boxDimensions, startPose, direction, distance, queryType, collisionGroup, nullptr);
});
behaviorContext->Method(
"CreateCapsuleCastRequest",
[](float capsuleRadius, float capsuleHeight, const AZ::Transform& startPose, const AZ::Vector3& direction, float distance,
@@ -267,6 +295,7 @@ namespace AzPhysics
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
->Attribute(AZ::Script::Attributes::Module, "physics")
->Attribute(AZ::Script::Attributes::Category, "PhysX")
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Property("Pose", BehaviorValueProperty(&OverlapRequest::m_pose))
;
@@ -349,6 +378,7 @@ namespace AzPhysics
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
->Attribute(AZ::Script::Attributes::Module, "physics")
->Attribute(AZ::Script::Attributes::Category, "PhysX")
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Property("Distance", BehaviorValueProperty(&SceneQueryHit::m_distance))
->Property("Position", BehaviorValueProperty(&SceneQueryHit::m_position))
->Property("Normal", BehaviorValueProperty(&SceneQueryHit::m_normal))
@@ -51,7 +51,10 @@ namespace AzPhysics
->Method("GetOnPostsimulateEvent", getOnPostsimulateEvent)
->Attribute(AZ::Script::Attributes::AzEventDescription, postsimulateEventDescription)
->Method("GetSceneHandle", &SystemInterface::GetSceneHandle)
->Method("GetScene", &SystemInterface::GetScene);
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Method("GetScene", &SystemInterface::GetScene)
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
;
behaviorContext->Method(
"GetPhysicsSystem",
@@ -303,4 +303,22 @@ namespace AzNetworking
return serializer.IsValid();
}
};
template <>
struct SerializeObjectHelper<AZ::Transform>
{
static bool SerializeObject(ISerializer& serializer, AZ::Transform& value)
{
AZ::Vector3 translation = value.GetTranslation();
AZ::Quaternion rotation = value.GetRotation();
float uniformScale = value.GetUniformScale();
serializer.Serialize(translation, "Translation");
serializer.Serialize(rotation, "Rotation");
serializer.Serialize(uniformScale, "Scale");
value.SetTranslation(translation);
value.SetRotation(rotation);
value.SetUniformScale(uniformScale);
return serializer.IsValid();
}
};
}
@@ -11,9 +11,9 @@
namespace AzNetworking
{
// This gives us a hash sensitivity of around 1/128th of a unit, and will detect errors within a range of -16,777,216 to +16,777,216
static const int32_t FloatHashMinValue = (INT_MIN >> 7);
static const int32_t FloatHashMaxValue = (INT_MAX >> 7);
// This gives us a hash sensitivity of around 1/512th of a unit, and will detect errors within a range of -4,194,304 to +4,194,304
static const int32_t FloatHashMinValue = (INT_MIN >> 9);
static const int32_t FloatHashMaxValue = (INT_MAX >> 9);
AZ::HashValue32 HashSerializer::GetHash() const
{
@@ -403,7 +403,7 @@ namespace AzToolsFramework
void RootAssetBrowserEntry::UpdateChildPaths(AssetBrowserEntry* child) const
{
child->m_relativePath = child->m_name;
child->m_fullPath = child->m_name;
child->m_fullPath = m_fullPath / child->m_name;
AssetBrowserEntry::UpdateChildPaths(child);
}
@@ -88,13 +88,15 @@ namespace AzToolsFramework
{
if (m_rootInstance)
{
AzToolsFramework::ToolsApplicationRequestBus::Broadcast(
&AzToolsFramework::ToolsApplicationRequestBus::Events::ClearDirtyEntities);
Prefab::TemplateId templateId = m_rootInstance->GetTemplateId();
m_rootInstance->Reset();
if (templateId != Prefab::InvalidTemplateId)
{
m_rootInstance->SetTemplateId(Prefab::InvalidTemplateId);
m_prefabSystemComponent->RemoveTemplate(templateId);
}
m_rootInstance->Reset();
m_rootInstance->SetContainerEntityName("Level");
}
@@ -82,16 +82,7 @@ namespace AzToolsFramework
return;
}
// If this instance's templateId is valid, we should be able to unregister this instance from
// Template to Instance mapping successfully.
if (m_templateId != InvalidTemplateId &&
!m_templateInstanceMapper->UnregisterInstance(*this))
{
AZ_Assert(false,
"Prefab - Attempted to Unregister Instance from Template with Id '%u'. "
"Instance may never have been registered or was unregistered early.",
m_templateId);
}
m_templateInstanceMapper->UnregisterInstance(*this);
m_templateId = templateId;
@@ -221,15 +212,7 @@ namespace AzToolsFramework
void Instance::Reset()
{
// Clean up Instance associations.
if (m_templateId != InvalidTemplateId && !m_templateInstanceMapper->UnregisterInstance(*this))
{
AZ_Assert(
false,
"Prefab - Attempted to unregister Instance from Template on file path '%s' with Id '%u'. "
"Instance may never have been registered or was unregistered early.",
m_templateSourcePath.c_str(), m_templateId);
}
m_templateInstanceMapper->UnregisterInstance(*this);
ClearEntities();
@@ -40,7 +40,7 @@ namespace AzToolsFramework
->Attribute(AZ::Edit::Attributes::FixedComponentListIndex, 1)
->Attribute(AZ::Edit::Attributes::RemoveableByUser, true)
->Attribute(AZ::Edit::Attributes::Icon, "Icons/Components/NonUniformScale.svg")
->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/NonUniformScale.svg")
->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/NonUniformScale.svg")
->DataElement(
AZ::Edit::UIHandlers::Default, &EditorNonUniformScaleComponent::m_scale, "Non-uniform Scale",
"Non-uniform scale for this entity only (does not propagate through hierarchy)")
@@ -1021,6 +1021,7 @@ namespace AzToolsFramework
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
->Attribute(AZ::Edit::Attributes::Category, "Scripting")
->Attribute(AZ::Edit::Attributes::Icon, "Icons/Components/LuaScript.svg")
->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/LuaScript.svg")
->Attribute(AZ::Edit::Attributes::PrimaryAssetType, AZ::AzTypeInfo<AZ::ScriptAsset>::Uuid())
->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/Script.png")
->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/lua-script/")
@@ -1182,7 +1182,7 @@ namespace AzToolsFramework
ClassElement(AZ::Edit::ClassElements::EditorData, "")->
Attribute(AZ::Edit::Attributes::FixedComponentListIndex, 0)->
Attribute(AZ::Edit::Attributes::Icon, "Icons/Components/Transform.svg")->
Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/Transform.png")->
Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/Transform.svg")->
Attribute(AZ::Edit::Attributes::AutoExpand, true)->
DataElement(AZ::Edit::UIHandlers::Default, &TransformComponent::m_parentEntityId, "Parent entity", "")->
Attribute(AZ::Edit::Attributes::ChangeValidate, &TransformComponent::ValidatePotentialParent)->
@@ -4965,21 +4965,29 @@ namespace AzToolsFramework
void EntityPropertyEditor::SetEditorUiEnabled(bool enable)
{
if (enable)
if (!m_selectedEntityIds.empty())
{
EnableComponentActions(this, m_entityComponentActions);
if (enable)
{
EnableComponentActions(this, m_entityComponentActions);
}
else
{
DisableComponentActions(this, m_entityComponentActions);
}
SetPropertyEditorState(m_gui, enable);
for (auto componentEditor : m_componentEditors)
{
AzQtComponents::SetWidgetInteractEnabled(componentEditor, enable);
}
}
else
{
DisableComponentActions(this, m_entityComponentActions);
AzQtComponents::SetWidgetInteractEnabled(m_gui->m_entityDetailsLabel, enable);
}
m_disabled = !enable;
SetPropertyEditorState(m_gui, enable);
for (auto componentEditor : m_componentEditors)
{
AzQtComponents::SetWidgetInteractEnabled(componentEditor, enable);
}
// record the selected state after entering/leaving component mode
SaveComponentEditorState();
}
@@ -6,7 +6,6 @@
*
*/
#include <AzToolsFramework/ViewportUi/Button.h>
namespace AzToolsFramework::ViewportUi::Internal
@@ -28,7 +28,7 @@ namespace AzToolsFramework::ViewportUi::Internal
AZStd::string m_icon; //!< The icon for this button, string path to an image.
AZStd::string m_name; //!< The name displayed as a label next to the button's icon.
State m_state = State::Deselected;
ButtonId m_buttonId;
State m_state = State::Deselected;
ButtonId m_buttonId;
};
} // namespace AzToolsFramework::ViewportUi::Internal
@@ -45,11 +45,11 @@ namespace AzToolsFramework::ViewportUi::Internal
if (name.empty())
{
m_buttons.insert({buttonId, AZStd::make_unique<Button>(icon, buttonId)});
m_buttons.insert({ buttonId, AZStd::make_unique<Button>(icon, buttonId) });
}
else
{
m_buttons.insert({buttonId, AZStd::make_unique<Button>(icon, name, buttonId)});
m_buttons.insert({ buttonId, AZStd::make_unique<Button>(icon, name, buttonId) });
}
return buttonId;
}
@@ -73,7 +73,8 @@ namespace AzToolsFramework::ViewportUi::Internal
return buttons;
}
void ButtonGroup::ConnectEventHandler(AZ::Event<ButtonId>::Handler& handler) {
void ButtonGroup::ConnectEventHandler(AZ::Event<ButtonId>::Handler& handler)
{
handler.Connect(m_buttonTriggeredEvent);
}
@@ -1,5 +1,3 @@
#pragma once
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
@@ -8,6 +6,8 @@
*
*/
#pragma once
#include <AzToolsFramework/ViewportUi/ViewportUiRequestBus.h>
namespace AzToolsFramework::ViewportUi::Internal
@@ -10,9 +10,7 @@
namespace AzToolsFramework::ViewportUi::Internal
{
TextField::TextField(
const AZStd::string& labelText, const AZStd::string& fieldText,
TextFieldValidationType validationType)
TextField::TextField(const AZStd::string& labelText, const AZStd::string& fieldText, TextFieldValidationType validationType)
: m_labelText(labelText)
, m_fieldText(fieldText)
, m_validationType(validationType)
@@ -19,16 +19,17 @@ namespace AzToolsFramework::ViewportUi::Internal
{
public:
TextField(
const AZStd::string& labelText = "", const AZStd::string& fieldText = "",
const AZStd::string& labelText = "",
const AZStd::string& fieldText = "",
TextFieldValidationType validationType = TextFieldValidationType::String);
~TextField() = default;
void ConnectEventHandler(AZ::Event<AZStd::string>::Handler& handler);
//! Default text for the text field. Will be cast to same type as m_validationType.
AZStd::string m_fieldText;
AZStd::string m_fieldText;
AZStd::string m_labelText;
TextFieldValidationType m_validationType; //<! The type of validator for this text edit.
TextFieldValidationType m_validationType; //!< The type of validator for this text edit.
TextFieldId m_textFieldId;
ViewportUiElementId m_viewportId;
AZ::Event<AZStd::string> m_textEditedEvent;
@@ -6,7 +6,6 @@
*
*/
#include <AzToolsFramework/ViewportUi/ButtonGroup.h>
#include <AzToolsFramework/ViewportUi/ViewportUiCluster.h>
@@ -14,13 +13,12 @@ namespace AzToolsFramework::ViewportUi::Internal
{
ViewportUiCluster::ViewportUiCluster(AZStd::shared_ptr<ButtonGroup> buttonGroup)
: QToolBar(nullptr)
, m_buttonGroup(buttonGroup)
, m_buttonGroup(AZStd::move(buttonGroup))
{
setOrientation(Qt::Orientation::Vertical);
setStyleSheet("background: black;");
const AZStd::vector<Button*> buttons = buttonGroup->GetButtons();
for (auto button : buttons)
for (auto button : m_buttonGroup->GetButtons())
{
RegisterButton(button);
}
@@ -34,10 +32,12 @@ namespace AzToolsFramework::ViewportUi::Internal
AddClusterAction(
action,
[this, button]() {
[this, button]()
{
m_buttonGroup->PressButton(button->m_buttonId);
},
[button](QAction* action) {
[button](QAction* action)
{
action->setChecked(button->m_state == Button::State::Selected);
});
@@ -46,8 +46,7 @@ namespace AzToolsFramework::ViewportUi::Internal
void ViewportUiCluster::RemoveButton(ButtonId buttonId)
{
if (auto actionEntry = m_buttonActionMap.find(buttonId);
actionEntry != m_buttonActionMap.end())
if (auto actionEntry = m_buttonActionMap.find(buttonId); actionEntry != m_buttonActionMap.end())
{
auto action = actionEntry->second;
RemoveClusterAction(action);
@@ -56,8 +55,7 @@ namespace AzToolsFramework::ViewportUi::Internal
}
void ViewportUiCluster::AddClusterAction(
QAction* action, const AZStd::function<void()>& callback,
const AZStd::function<void(QAction*)>& updateCallback)
QAction* action, const AZStd::function<void()>& callback, const AZStd::function<void(QAction*)>& updateCallback)
{
if (!action)
{
@@ -80,10 +78,12 @@ namespace AzToolsFramework::ViewportUi::Internal
}
// register the action
m_widgetCallbacks.AddWidget(action, [updateCallback](QPointer<QObject> object)
{
updateCallback(static_cast<QAction*>(object.data()));
});
m_widgetCallbacks.AddWidget(
action,
[updateCallback](QPointer<QObject> object)
{
updateCallback(static_cast<QAction*>(object.data()));
});
}
void ViewportUiCluster::RemoveClusterAction(QAction* action)
@@ -111,10 +111,13 @@ namespace AzToolsFramework::ViewportUi::Internal
if (m_lockedButtonId.has_value() && isLocked)
{
// find the button to extract the old icon (without overlay)
auto findLocked = [this](const Button* button) { return (button->m_buttonId == m_lockedButtonId); };
auto findLocked = [this](const Button* button)
{
return (button->m_buttonId == m_lockedButtonId);
};
if (auto lockedButtonIt = AZStd::find_if(buttons.begin(), buttons.end(), findLocked); lockedButtonIt != buttons.end())
{
// get the action corresponding to the lockedButtonId
// get the action corresponding to the lockedButtonId
if (auto actionEntry = m_buttonActionMap.find(m_lockedButtonId.value()); actionEntry != m_buttonActionMap.end())
{
// remove the overlay
@@ -124,14 +127,18 @@ namespace AzToolsFramework::ViewportUi::Internal
}
}
auto found = [buttonId](Button* button) { return (button->m_buttonId == buttonId); };
auto found = [buttonId](Button* button)
{
return (button->m_buttonId == buttonId);
};
if (auto buttonIt = AZStd::find_if(buttons.begin(), buttons.end(), found); buttonIt != buttons.end())
{
QIcon newIcon;
if (isLocked)
{
// overlay the locked icon ontop of the button's icon
// overlay the locked icon on top of the button's icon
QPixmap comboPixmap(24, 24);
comboPixmap.fill(Qt::transparent);
QPixmap firstImage(QString((*buttonIt)->m_icon.c_str()));
@@ -12,16 +12,16 @@
#include <AzCore/std/smart_ptr/shared_ptr.h>
#include <AzToolsFramework/ViewportUi/Button.h>
#include <AzToolsFramework/ViewportUi/ViewportUiWidgetCallbacks.h>
#include <QToolBar>
#include <QPainter>
#include <QToolBar>
namespace AzToolsFramework::ViewportUi::Internal
{
class ButtonGroup;
//! Helper class to make clusters (toolbars) for display in Viewport UI.
class ViewportUiCluster
: public QToolBar
class ViewportUiCluster : public QToolBar
{
Q_OBJECT
@@ -45,8 +45,7 @@ namespace AzToolsFramework::ViewportUi::Internal
private:
//! Adds an action to the Viewport UI Cluster.
void AddClusterAction(
QAction* action, const AZStd::function<void()>& callback = {},
const AZStd::function<void(QAction*)>& updateCallback = {});
QAction* action, const AZStd::function<void()>& callback = {}, const AZStd::function<void(QAction*)>& updateCallback = {});
//! Removes an action from the Viewport UI Cluster.
void RemoveClusterAction(QAction* action);
@@ -6,13 +6,12 @@
*
*/
#include <AzCore/std/smart_ptr/make_shared.h>
#include <AzFramework/Viewport/ViewportScreen.h>
#include <AzToolsFramework/Viewport/ViewportMessages.h>
#include <AzToolsFramework/ViewportSelection/EditorSelectionUtil.h>
#include <AzToolsFramework/ViewportUi/ViewportUiDisplay.h>
#include <AzToolsFramework/ViewportUi/ViewportUiCluster.h>
#include <AzToolsFramework/ViewportUi/ViewportUiDisplay.h>
#include <AzToolsFramework/ViewportUi/ViewportUiSwitcher.h>
#include <AzToolsFramework/ViewportUi/ViewportUiTextField.h>
#include <QWidget>
@@ -34,9 +33,9 @@ namespace AzToolsFramework::ViewportUi::Internal
}
}
static Qt::Alignment GetQtAlignment(Alignment align)
static Qt::Alignment GetQtAlignment(const Alignment alignment)
{
switch (align)
switch (alignment)
{
case Alignment::TopRight:
return Qt::AlignTop | Qt::AlignRight;
@@ -52,7 +51,7 @@ namespace AzToolsFramework::ViewportUi::Internal
return Qt::AlignBottom;
}
AZ_Assert(false, "ViewportUI", "Unhandled ViewportUI Alignment %d", static_cast<int>(align));
AZ_Assert(false, "ViewportUI", "Unhandled ViewportUI Alignment %d", static_cast<int>(alignment));
return Qt::AlignTop;
}
@@ -71,7 +70,7 @@ namespace AzToolsFramework::ViewportUi::Internal
UnparentWidgets(m_viewportUiElements);
}
void ViewportUiDisplay::AddCluster(AZStd::shared_ptr<ButtonGroup> buttonGroup, const Alignment align)
void ViewportUiDisplay::AddCluster(AZStd::shared_ptr<ButtonGroup> buttonGroup, const Alignment alignment)
{
if (!buttonGroup.get())
{
@@ -81,11 +80,10 @@ namespace AzToolsFramework::ViewportUi::Internal
auto viewportUiCluster = AZStd::make_shared<ViewportUiCluster>(buttonGroup);
auto id = AddViewportUiElement(viewportUiCluster);
buttonGroup->SetViewportUiElementId(id);
PositionViewportUiElementAnchored(id, GetQtAlignment(align));
PositionViewportUiElementAnchored(id, GetQtAlignment(alignment));
}
void ViewportUiDisplay::AddClusterButton(
const ViewportUiElementId clusterId, Button* button)
void ViewportUiDisplay::AddClusterButton(const ViewportUiElementId clusterId, Button* button)
{
if (auto viewportUiCluster = qobject_cast<ViewportUiCluster*>(GetViewportUiElement(clusterId).get()))
{
@@ -101,7 +99,8 @@ namespace AzToolsFramework::ViewportUi::Internal
}
}
void ViewportUiDisplay::SetClusterButtonTooltip(const ViewportUiElementId clusterId, const ButtonId buttonId, const AZStd::string& tooltip)
void ViewportUiDisplay::SetClusterButtonTooltip(
const ViewportUiElementId clusterId, const ButtonId buttonId, const AZStd::string& tooltip)
{
if (auto viewportUiCluster = qobject_cast<ViewportUiCluster*>(GetViewportUiElement(clusterId).get()))
{
@@ -125,7 +124,7 @@ namespace AzToolsFramework::ViewportUi::Internal
}
}
void ViewportUiDisplay::AddSwitcher(AZStd::shared_ptr<ButtonGroup> buttonGroup, const Alignment align)
void ViewportUiDisplay::AddSwitcher(AZStd::shared_ptr<ButtonGroup> buttonGroup, const Alignment alignment)
{
if (!buttonGroup.get())
{
@@ -135,7 +134,7 @@ namespace AzToolsFramework::ViewportUi::Internal
auto viewportUiSwitcher = AZStd::make_shared<ViewportUiSwitcher>(buttonGroup);
auto id = AddViewportUiElement(viewportUiSwitcher);
buttonGroup->SetViewportUiElementId(id);
PositionViewportUiElementAnchored(id, GetQtAlignment(align));
PositionViewportUiElementAnchored(id, GetQtAlignment(alignment));
}
void ViewportUiDisplay::AddSwitcherButton(const ViewportUiElementId clusterId, Button* button)
@@ -198,11 +197,12 @@ namespace AzToolsFramework::ViewportUi::Internal
const ViewportUiElementInfo& elementInfo = element.second;
if (!elementInfo.m_anchored)
{
const auto screenPoint = AzFramework::WorldToScreen(
elementInfo.m_worldPosition, AzToolsFramework::GetCameraState(m_viewportId));
const auto screenPoint =
AzFramework::WorldToScreen(elementInfo.m_worldPosition, AzToolsFramework::GetCameraState(m_viewportId));
elementInfo.m_widget->move(screenPoint.m_x, screenPoint.m_y);
}
}
PositionUiOverlayOverRenderViewport();
}
@@ -216,7 +216,6 @@ namespace AzToolsFramework::ViewportUi::Internal
ViewportUiElementId newId = ViewportUiElementId(++m_numViewportElements);
ViewportUiElementInfo newElement{ widget, newId, true };
m_viewportUiElements.insert({ newId, newElement });
SetUiOverlayContents(widget.get());
return newId;
}
@@ -233,8 +232,11 @@ namespace AzToolsFramework::ViewportUi::Internal
ViewportUiElementId ViewportUiDisplay::GetViewportUiElementId(QPointer<QWidget> widget)
{
if (auto element = AZStd::find_if(
m_viewportUiElements.begin(), m_viewportUiElements.end(),
[widget](const auto& it) { return it.second.m_widget.get() == widget; });
m_viewportUiElements.begin(), m_viewportUiElements.end(),
[widget](const auto& it)
{
return it.second.m_widget.get() == widget;
});
element != m_viewportUiElements.end())
{
return element->second.m_viewportUiElementId;
@@ -245,7 +247,8 @@ namespace AzToolsFramework::ViewportUi::Internal
void ViewportUiDisplay::RemoveViewportUiElement(ViewportUiElementId elementId)
{
AZ_Assert(elementId != AzToolsFramework::ViewportUi::InvalidViewportUiElementId,
AZ_Assert(
elementId != AzToolsFramework::ViewportUi::InvalidViewportUiElementId,
"Tried to remove a Viewport UI element using an invalid or removed ViewportUiElementId.");
auto viewportUiMapElement = m_viewportUiElements.find(elementId);
@@ -264,8 +267,7 @@ namespace AzToolsFramework::ViewportUi::Internal
void ViewportUiDisplay::ShowViewportUiElement(ViewportUiElementId elementId)
{
if (ViewportUiElementInfo element = GetViewportUiElementInfo(elementId);
element.m_widget)
if (ViewportUiElementInfo element = GetViewportUiElementInfo(elementId); element.m_widget)
{
element.m_widget->setVisible(true);
}
@@ -273,8 +275,7 @@ namespace AzToolsFramework::ViewportUi::Internal
void ViewportUiDisplay::HideViewportUiElement(ViewportUiElementId elementId)
{
if (ViewportUiElementInfo element = GetViewportUiElementInfo(elementId);
element.m_widget)
if (ViewportUiElementInfo element = GetViewportUiElementInfo(elementId); element.m_widget)
{
element.m_widget->setVisible(false);
}
@@ -282,8 +283,7 @@ namespace AzToolsFramework::ViewportUi::Internal
bool ViewportUiDisplay::IsViewportUiElementVisible(ViewportUiElementId elementId)
{
if (ViewportUiElementInfo element = GetViewportUiElementInfo(elementId);
element.m_widget)
if (ViewportUiElementInfo element = GetViewportUiElementInfo(elementId); element.m_widget)
{
return element.IsValid() && element.m_widget->isVisible();
}
@@ -293,12 +293,12 @@ namespace AzToolsFramework::ViewportUi::Internal
void ViewportUiDisplay::CreateComponentModeBorder(const AZStd::string& borderTitle)
{
AZStd::string styleSheet = AZStd::string::format(
"border: %dpx solid %s; border-top: %dpx solid %s;", HighlightBorderSize,
HighlightBorderColor, TopHighlightBorderSize, HighlightBorderColor);
"border: %dpx solid %s; border-top: %dpx solid %s;", HighlightBorderSize, HighlightBorderColor, TopHighlightBorderSize,
HighlightBorderColor);
m_uiOverlay.setStyleSheet(styleSheet.c_str());
m_uiOverlayLayout.setContentsMargins(HighlightBorderSize + ViewportUiOverlayMargin,
TopHighlightBorderSize + ViewportUiOverlayMargin, HighlightBorderSize + ViewportUiOverlayMargin,
HighlightBorderSize + ViewportUiOverlayMargin);
m_uiOverlayLayout.setContentsMargins(
HighlightBorderSize + ViewportUiOverlayMargin, TopHighlightBorderSize + ViewportUiOverlayMargin,
HighlightBorderSize + ViewportUiOverlayMargin, HighlightBorderSize + ViewportUiOverlayMargin);
m_componentModeBorderText.setVisible(true);
m_componentModeBorderText.setText(borderTitle.c_str());
}
@@ -314,8 +314,7 @@ namespace AzToolsFramework::ViewportUi::Internal
{
auto viewportUiMapElement = m_viewportUiElements.find(elementId);
if (viewportUiMapElement != m_viewportUiElements.end() &&
viewportUiMapElement->second.m_widget)
if (viewportUiMapElement != m_viewportUiElements.end() && viewportUiMapElement->second.m_widget)
{
viewportUiMapElement->second.m_anchored = false;
viewportUiMapElement->second.m_worldPosition = pos;
@@ -328,51 +327,28 @@ namespace AzToolsFramework::ViewportUi::Internal
{
auto viewportUiMapElement = m_viewportUiElements.find(elementId);
if (viewportUiMapElement != m_viewportUiElements.end() &&
viewportUiMapElement->second.m_widget)
if (viewportUiMapElement != m_viewportUiElements.end() && viewportUiMapElement->second.m_widget)
{
viewportUiMapElement->second.m_anchored = true;
SetUiOverlayContentsAnchored(viewportUiMapElement->second.m_widget.get(), alignment);
}
}
void ViewportUiDisplay::AddMaximumSizeViewportUiElement(QPointer<QWidget> widget)
{
if (widget)
{
return;
}
if (m_fullScreenWidget)
{
AZ_Warning(
"ViewportUi", false,
"Attaching a maximum size element when one already exists. Removing the previously attached element.");
RemoveViewportUiElement(GetViewportUiElementId(m_fullScreenWidget));
}
widget->setAttribute(Qt::WA_ShowWithoutActivating);
widget->setParent(&m_uiOverlay);
m_fullScreenWidget = widget;
m_fullScreenLayout.addWidget(m_fullScreenWidget, 0, 0, 1, 1);
m_renderOverlay->setFocus();
}
// disables system background for widget and gives a transparent background
static void ConfigureWidgetForViewportUi(QPointer<QWidget> widget)
static void ConfigureWindowForViewportUi(QPointer<QMainWindow> mainWindow)
{
// no background for the widget else each set of buttons/textfields/etc would have a black box around them
SetTransparentBackground(widget);
widget->setWindowFlags(Qt::Window | Qt::FramelessWindowHint);
// no background for the widget else each set of buttons/text-fields/etc would have a black box around them
SetTransparentBackground(mainWindow);
mainWindow->setWindowFlags(Qt::Window | Qt::FramelessWindowHint | Qt::WindowDoesNotAcceptFocus);
}
void ViewportUiDisplay::InitializeUiOverlay()
{
m_uiMainWindow.setObjectName(m_uiMainWindow.windowTitle());
ConfigureWidgetForViewportUi(&m_uiMainWindow);
m_uiMainWindow.setObjectName(QString("ViewportUiWindow"));
ConfigureWindowForViewportUi(&m_uiMainWindow);
m_uiMainWindow.setVisible(false);
m_uiOverlay.setObjectName(m_uiOverlay.windowTitle());
m_uiOverlay.setObjectName(QString("ViewportUiOverlay"));
m_uiMainWindow.setCentralWidget(&m_uiOverlay);
m_uiOverlay.setVisible(false);
@@ -382,8 +358,7 @@ namespace AzToolsFramework::ViewportUi::Internal
m_fullScreenLayout.addLayout(&m_uiOverlayLayout, 0, 0, 1, 1);
// format the label which will appear on top of the highlight border
AZStd::string styleSheet = AZStd::string::format(
"background-color: %s; border: none;", HighlightBorderColor);
AZStd::string styleSheet = AZStd::string::format("background-color: %s; border: none;", HighlightBorderColor);
m_componentModeBorderText.setStyleSheet(styleSheet.c_str());
m_componentModeBorderText.setFixedHeight(TopHighlightBorderSize);
m_componentModeBorderText.setVisible(false);
@@ -408,7 +383,7 @@ namespace AzToolsFramework::ViewportUi::Internal
m_renderOverlay->setFocus();
}
void ViewportUiDisplay::SetUiOverlayContentsAnchored(QPointer<QWidget> widget, Qt::Alignment alignment)
void ViewportUiDisplay::SetUiOverlayContentsAnchored(QPointer<QWidget> widget, const Qt::Alignment alignment)
{
if (!widget)
{
@@ -429,13 +404,8 @@ namespace AzToolsFramework::ViewportUi::Internal
// get the border region by taking the entire region and subtracting the non-border area
region += m_uiOverlay.rect();
region -= QRect(
QPoint(
m_uiOverlay.rect().left() + HighlightBorderSize,
m_uiOverlay.rect().top() + TopHighlightBorderSize),
QPoint(
m_uiOverlay.rect().right() - HighlightBorderSize,
m_uiOverlay.rect().bottom() - HighlightBorderSize)
);
QPoint(m_uiOverlay.rect().left() + HighlightBorderSize, m_uiOverlay.rect().top() + TopHighlightBorderSize),
QPoint(m_uiOverlay.rect().right() - HighlightBorderSize, m_uiOverlay.rect().bottom() - HighlightBorderSize));
}
// add all children widget regions
@@ -465,8 +435,7 @@ namespace AzToolsFramework::ViewportUi::Internal
ViewportUiElementInfo ViewportUiDisplay::GetViewportUiElementInfo(const ViewportUiElementId elementId)
{
if (auto element = m_viewportUiElements.find(elementId);
element != m_viewportUiElements.end())
if (auto element = m_viewportUiElements.find(elementId); element != m_viewportUiElements.end())
{
return element->second;
}
@@ -488,7 +457,7 @@ namespace AzToolsFramework::ViewportUi::Internal
return &m_uiOverlayLayout;
}
void SetTransparentBackground(QWidget * widget)
void SetTransparentBackground(QWidget* widget)
{
widget->setAttribute(Qt::WA_TranslucentBackground);
widget->setAutoFillBackground(false);
@@ -11,11 +11,12 @@
#include <AzToolsFramework/ViewportUi/Button.h>
#include <AzToolsFramework/ViewportUi/ButtonGroup.h>
#include <AzToolsFramework/ViewportUi/TextField.h>
#include <AzToolsFramework/ViewportUi/ViewportUiRequestBus.h>
#include <AzToolsFramework/ViewportUi/ViewportUiDisplayLayout.h>
#include <AzToolsFramework/ViewportUi/ViewportUiRequestBus.h>
#include <QLabel>
#include <QMainWindow>
#include <QPointer>
#include <QLabel>
AZ_PUSH_DISABLE_WARNING(4251, "-Wunknown-warning-option")
#include <QGridLayout>
@@ -28,10 +29,10 @@ namespace AzToolsFramework::ViewportUi::Internal
//! Used to track info for each widget in the Viewport UI.
struct ViewportUiElementInfo
{
AZStd::shared_ptr<QWidget> m_widget; //<! Reference to the widget.
ViewportUiElementId m_viewportUiElementId; //<! Corresponding ViewportUiElementId of the widget.
bool m_anchored = true; //<! Whether the widget is anchored to one position or moves with camera/entity.
AZ::Vector3 m_worldPosition; //<! If not anchored, use this to project widget position to screen space.
AZStd::shared_ptr<QWidget> m_widget; //!< Reference to the widget.
ViewportUiElementId m_viewportUiElementId; //!< Corresponding ViewportUiElementId of the widget.
bool m_anchored = true; //!< Whether the widget is anchored to one position or moves with camera/entity.
AZ::Vector3 m_worldPosition; //!< If not anchored, use this to project widget position to screen space.
bool IsValid() const
{
@@ -52,14 +53,14 @@ namespace AzToolsFramework::ViewportUi::Internal
ViewportUiDisplay(QWidget* parent, QWidget* renderOverlay);
~ViewportUiDisplay();
void AddCluster(AZStd::shared_ptr<ButtonGroup> buttonGroup, Alignment align);
void AddCluster(AZStd::shared_ptr<ButtonGroup> buttonGroup, Alignment alignment);
void AddClusterButton(ViewportUiElementId clusterId, Button* button);
void SetClusterButtonLocked(ViewportUiElementId clusterId, ButtonId buttonId, bool isLocked);
void SetClusterButtonTooltip(ViewportUiElementId clusterId, ButtonId buttonId, const AZStd::string& tooltip);
void RemoveClusterButton(ViewportUiElementId clusterId, ButtonId buttonId);
void UpdateCluster(const ViewportUiElementId clusterId);
void AddSwitcher(AZStd::shared_ptr<ButtonGroup> buttonGroup, Alignment align);
void AddSwitcher(AZStd::shared_ptr<ButtonGroup> buttonGroup, Alignment alignment);
void AddSwitcherButton(ViewportUiElementId switcherId, Button* button);
void RemoveSwitcherButton(ViewportUiElementId switcherId, ButtonId buttonId);
void UpdateSwitcher(ViewportUiElementId switcherId);
@@ -90,13 +91,12 @@ namespace AzToolsFramework::ViewportUi::Internal
void CreateComponentModeBorder(const AZStd::string& borderTitle);
void RemoveComponentModeBorder();
private:
void PrepareWidgetForViewportUi(QPointer<QWidget> widget);
ViewportUiElementId AddViewportUiElement(AZStd::shared_ptr<QWidget> widget);
ViewportUiElementId GetViewportUiElementId(QPointer<QWidget> widget);
void AddMaximumSizeViewportUiElement(QPointer<QWidget> widget);
void PositionViewportUiElementFromWorldSpace(ViewportUiElementId elementId, const AZ::Vector3& pos);
void PositionViewportUiElementAnchored(ViewportUiElementId elementId, const Qt::Alignment alignment);
@@ -109,16 +109,16 @@ namespace AzToolsFramework::ViewportUi::Internal
ViewportUiElementInfo GetViewportUiElementInfo(const ViewportUiElementId elementId);
QMainWindow m_uiMainWindow; //<! The window which contains the UI Overlay.
QWidget m_uiOverlay; //<! The UI Overlay which displays Viewport UI Elements.
QGridLayout m_fullScreenLayout; //<! The layout which extends across the full screen.
ViewportUiDisplayLayout m_uiOverlayLayout; //<! The layout used for optionally anchoring Viewport UI Elements.
QLabel m_componentModeBorderText; //<! The text used for the Component Mode border.
QMainWindow m_uiMainWindow; //!< The window which contains the UI Overlay.
QWidget m_uiOverlay; //!< The UI Overlay which displays Viewport UI Elements.
QGridLayout m_fullScreenLayout; //!< The layout which extends across the full screen.
ViewportUiDisplayLayout m_uiOverlayLayout; //!< The layout used for optionally anchoring Viewport UI Elements.
QLabel m_componentModeBorderText; //!< The text used for the Component Mode border.
QWidget* m_renderOverlay;
QPointer<QWidget> m_fullScreenWidget; //<! Reference to the widget attached to m_fullScreenLayout if any.
int m_viewportId;
int64_t m_numViewportElements = 0;
QPointer<QWidget> m_fullScreenWidget; //!< Reference to the widget attached to m_fullScreenLayout if any.
int64_t m_numViewportElements = 0;
int m_viewportId = 0;
ViewportUiElementIdInfoLookup m_viewportUiElements;
};
@@ -6,15 +6,19 @@
*
*/
#include <AzCore/Console/IConsole.h>
#include <AzToolsFramework/ViewportUi/ViewportUiDisplayLayout.h>
#include <QtWidgets/QWidget>
#include <QWidget>
namespace AzToolsFramework::ViewportUi::Internal
{
AZ_CVAR(
int, ViewportUiDisplayLayoutSpacing, 5, nullptr, AZ::ConsoleFunctorFlags::Null,
int,
ViewportUiDisplayLayoutSpacing,
5,
nullptr,
AZ::ConsoleFunctorFlags::Null,
"The spacing between elements attached to the Viewport UI Display Layout");
ViewportUiDisplayLayout::ViewportUiDisplayLayout(QWidget* parent)
@@ -27,7 +31,7 @@ namespace AzToolsFramework::ViewportUi::Internal
setSpacing(ViewportUiDisplayLayoutSpacing);
// create a 3x2 map of sub layouts which will stack widgets according to their mapped alignment
m_internalLayouts = AZStd::unordered_map<Qt::Alignment, QBoxLayout*> {
m_internalLayouts = AZStd::unordered_map<Qt::Alignment, QBoxLayout*>{
CreateSubLayout(new QVBoxLayout(), 0, 0, Qt::AlignTop | Qt::AlignLeft),
CreateSubLayout(new QVBoxLayout(), 1, 0, Qt::AlignBottom | Qt::AlignLeft),
CreateSubLayout(new QVBoxLayout(), 0, 1, Qt::AlignTop),
@@ -45,8 +49,7 @@ namespace AzToolsFramework::ViewportUi::Internal
}
// find the corresponding sub layout for the alignment and add the widget
if (auto layoutForAlignment = m_internalLayouts.find(alignment);
layoutForAlignment != m_internalLayouts.end())
if (auto layoutForAlignment = m_internalLayouts.find(alignment); layoutForAlignment != m_internalLayouts.end())
{
// place the widget before or after the invisible spacer
// depending on the layout alignment
@@ -97,7 +100,7 @@ namespace AzToolsFramework::ViewportUi::Internal
// without this, alignment and resizing within the sublayouts becomes difficult
layout->addStretch(1);
addLayout(layout, row, column, /*rowSpan=*/ 1, /*colSpan=*/ 1, alignment);
addLayout(layout, row, column, /*rowSpan=*/1, /*colSpan=*/1, alignment);
return { alignment, layout };
}
@@ -9,8 +9,9 @@
#pragma once
#include <AzCore/std/containers/unordered_map.h>
#include <QGridLayout>
#include <QBoxLayout>
#include <QGridLayout>
#include <QPointer>
namespace AzToolsFramework::ViewportUi::Internal
@@ -33,8 +34,7 @@ namespace AzToolsFramework::ViewportUi::Internal
private:
//! Create a sub-layout to add to the grid of layouts.
//! @return A pair of the new layout along with its alignment on the grid.
AZStd::pair<Qt::Alignment, QBoxLayout*> CreateSubLayout(
QBoxLayout* layout, int row, int column, Qt::Alignment alignment);
AZStd::pair<Qt::Alignment, QBoxLayout*> CreateSubLayout(QBoxLayout* layout, int row, int column, Qt::Alignment alignment);
//! A mapping of each sub-layout to its corresponding alignment on the grid.
AZStd::unordered_map<Qt::Alignment, QBoxLayout*> m_internalLayouts;
@@ -6,12 +6,11 @@
*
*/
#include <AzCore/std/smart_ptr/make_shared.h>
#include <AzToolsFramework/ViewportUi/Button.h>
#include <AzToolsFramework/ViewportUi/ButtonGroup.h>
#include <AzToolsFramework/ViewportUi/ViewportUiManager.h>
#include <AzToolsFramework/ViewportUi/ViewportUiDisplay.h>
#include <AzToolsFramework/ViewportUi/ViewportUiManager.h>
namespace AzToolsFramework::ViewportUi
{
@@ -114,7 +113,8 @@ namespace AzToolsFramework::ViewportUi
return ButtonId(0);
}
const ButtonId ViewportUiManager::CreateSwitcherButton(const SwitcherId switcherId, const AZStd::string& icon, const AZStd::string& name)
const ButtonId ViewportUiManager::CreateSwitcherButton(
const SwitcherId switcherId, const AZStd::string& icon, const AZStd::string& name)
{
if (auto switcherIt = m_switcherButtonGroups.find(switcherId); switcherIt != m_switcherButtonGroups.end())
{
@@ -146,8 +146,7 @@ namespace AzToolsFramework::ViewportUi
}
}
static void SetViewportUiElementVisible(
Internal::ViewportUiDisplay* ui, ViewportUiElementId id, bool visible)
static void SetViewportUiElementVisible(Internal::ViewportUiDisplay* ui, ViewportUiElementId id, bool visible)
{
if (visible)
{
@@ -186,11 +185,9 @@ namespace AzToolsFramework::ViewportUi
}
const TextFieldId ViewportUiManager::CreateTextField(
const AZStd::string& labelText, const AZStd::string& textFieldDefaultText,
TextFieldValidationType validationType)
const AZStd::string& labelText, const AZStd::string& textFieldDefaultText, TextFieldValidationType validationType)
{
auto textField = AZStd::make_shared<Internal::TextField>(
labelText, textFieldDefaultText, validationType);
auto textField = AZStd::make_shared<Internal::TextField>(labelText, textFieldDefaultText, validationType);
m_viewportUi->AddTextField(textField);
return RegisterNewTextField(textField);
@@ -206,8 +203,7 @@ namespace AzToolsFramework::ViewportUi
}
}
void ViewportUiManager::RegisterTextFieldCallback(
TextFieldId textFieldId, AZ::Event<AZStd::string>::Handler& handler)
void ViewportUiManager::RegisterTextFieldCallback(TextFieldId textFieldId, AZ::Event<AZStd::string>::Handler& handler)
{
if (auto textFieldIt = m_textFields.find(textFieldId); textFieldIt != m_textFields.end())
{
@@ -234,7 +230,6 @@ namespace AzToolsFramework::ViewportUi
}
}
void ViewportUiManager::CreateComponentModeBorder(const AZStd::string& borderTitle)
{
m_viewportUi->CreateComponentModeBorder(borderTitle);
@@ -248,8 +243,7 @@ namespace AzToolsFramework::ViewportUi
void ViewportUiManager::PressButton(ClusterId clusterId, ButtonId buttonId)
{
// Find cluster using ID and cluster map
if (auto clusterIt = m_clusterButtonGroups.find(clusterId);
clusterIt != m_clusterButtonGroups.end())
if (auto clusterIt = m_clusterButtonGroups.find(clusterId); clusterIt != m_clusterButtonGroups.end())
{
clusterIt->second->PressButton(buttonId);
}
@@ -305,7 +299,7 @@ namespace AzToolsFramework::ViewportUi
SwitcherId ViewportUiManager::RegisterNewSwitcher(AZStd::shared_ptr<Internal::ButtonGroup>& buttonGroup)
{
SwitcherId newId = SwitcherId(m_switcherButtonGroups.size() + 1);
m_switcherButtonGroups.insert({newId, buttonGroup});
m_switcherButtonGroups.insert({ newId, buttonGroup });
return newId;
}
@@ -18,7 +18,7 @@ namespace AzToolsFramework::ViewportUi
{
class ButtonGroup;
class ViewportUiDisplay;
}
} // namespace Internal
class ViewportUiManager : public ViewportUiRequestBus::Handler
{
@@ -65,8 +65,12 @@ namespace AzToolsFramework::ViewportUi::Internal
// resize to fit new action with minimum extra space
resize(minimumSizeHint());
const AZStd::function<void()>& callback = [this, button]() { m_buttonGroup->PressButton(button->m_buttonId); };
const AZStd::function<void(QAction*)>& updateCallback = [button](QAction* action) {
const AZStd::function<void()>& callback = [this, button]()
{
m_buttonGroup->PressButton(button->m_buttonId);
};
const AZStd::function<void(QAction*)>& updateCallback = [button](QAction* action)
{
action->setChecked(button->m_state == Button::State::Selected);
};
@@ -78,9 +82,13 @@ namespace AzToolsFramework::ViewportUi::Internal
// register the action
m_widgetCallbacks.AddWidget(
action, [updateCallback](QPointer<QObject> object) { updateCallback(static_cast<QAction*>(object.data())); });
action,
[updateCallback](QPointer<QObject> object)
{
updateCallback(static_cast<QAction*>(object.data()));
});
m_buttonActionMap.insert({button->m_buttonId, action});
m_buttonActionMap.insert({ button->m_buttonId, action });
}
void ViewportUiSwitcher::RemoveButton(ButtonId buttonId)
@@ -121,9 +129,12 @@ namespace AzToolsFramework::ViewportUi::Internal
// Check if it is the first active mode to be set
bool initialActiveMode = (m_activeButtonId == ButtonId(0));
// Change the toolbutton's name and icon to that button
// Change the tool button's name and icon to that button
const AZStd::vector<Button*> buttons = m_buttonGroup->GetButtons();
auto found = [buttonId](Button* button) { return (button->m_buttonId == buttonId); };
auto found = [buttonId](Button* button)
{
return (button->m_buttonId == buttonId);
};
if (auto buttonIt = AZStd::find_if(buttons.begin(), buttons.end(), found); buttonIt != buttons.end())
{
@@ -8,11 +8,11 @@
#pragma once
#include <AzToolsFramework/ViewportUi/Button.h>
#include <AzCore/std/containers/unordered_map.h>
#include <AzCore/std/smart_ptr/shared_ptr.h>
#include <AzToolsFramework/ViewportUi/Button.h>
#include <AzToolsFramework/ViewportUi/ViewportUiWidgetCallbacks.h>
#include <functional>
#include <QPointer>
#include <QToolBar>
#include <QToolButton>
@@ -6,7 +6,6 @@
*
*/
#include "ViewportUiTextField.h"
#include <AzCore/Console/IConsole.h>
@@ -16,7 +15,11 @@
namespace AzToolsFramework::ViewportUi::Internal
{
AZ_CVAR(
int, ViewportUiTextFieldLength, 35, nullptr, AZ::ConsoleFunctorFlags::Null,
int,
ViewportUiTextFieldLength,
35,
nullptr,
AZ::ConsoleFunctorFlags::Null,
"The pixel length of the text field part of a ViewportUiTextField");
ViewportUiTextField::ViewportUiTextField(AZStd::shared_ptr<TextField> textField)
@@ -56,11 +59,14 @@ namespace AzToolsFramework::ViewportUi::Internal
m_lineEdit.setValidator(m_validator);
connect(&m_lineEdit, &QLineEdit::textEdited, &m_lineEdit, [textField](QString text) {
// convert the text using toLocal8Bit().data() as recommended by Qt, then emit signal
textField->m_fieldText = text.toLocal8Bit().data();
textField->m_textEditedEvent.Signal(textField->m_fieldText);
});
connect(
&m_lineEdit, &QLineEdit::textEdited, &m_lineEdit,
[textField](QString text)
{
// convert the text using toLocal8Bit().data() as recommended by Qt, then emit signal
textField->m_fieldText = text.toLocal8Bit().data();
textField->m_textEditedEvent.Signal(textField->m_fieldText);
});
}
void ViewportUiTextField::Update()
@@ -7,7 +7,10 @@
*/
#pragma once
#include <AzCore/std/smart_ptr/shared_ptr.h>
#include <AzToolsFramework/ViewportUi/TextField.h>
#include <QLabel>
#include <QLineEdit>
#include <QWidget>
@@ -17,13 +20,10 @@ AZ_PUSH_DISABLE_WARNING(4251, "-Wunknown-warning-option")
#include <QVBoxLayout>
AZ_POP_DISABLE_WARNING
#include <AzCore/std/smart_ptr/shared_ptr.h>
namespace AzToolsFramework::ViewportUi::Internal
{
//! Helper class for a widget that holds and manages multiple LabelTextFields.
class ViewportUiTextField
: public QWidget
class ViewportUiTextField : public QWidget
{
Q_OBJECT
@@ -34,9 +34,9 @@ namespace AzToolsFramework::ViewportUi::Internal
void Update();
private:
QLabel m_label; //<! The text label.
QLineEdit m_lineEdit; //<! The editable text field.
QValidator* m_validator; //<! The validator for the line edit text.
AZStd::shared_ptr<TextField> m_textField; //<! Reference to the text field data struct.
QLabel m_label; //!< The text label.
QLineEdit m_lineEdit; //!< The editable text field.
QValidator* m_validator; //!< The validator for the line edit text.
AZStd::shared_ptr<TextField> m_textField; //!< Reference to the text field data struct.
};
} // namespace AzToolsFramework::ViewportUi::Internal
@@ -6,13 +6,11 @@
*
*/
#include "ViewportUiWidgetCallbacks.h"
namespace AzToolsFramework::ViewportUi::Internal
{
void ViewportUiWidgetCallbacks::AddWidget(
QPointer<QObject> widget, const AZStd::function<void(QPointer<QObject>)>& updateCallback)
void ViewportUiWidgetCallbacks::AddWidget(QPointer<QObject> widget, const AZStd::function<void(QPointer<QObject>)>& updateCallback)
{
if (widget.isNull())
{
@@ -40,7 +38,7 @@ namespace AzToolsFramework::ViewportUi::Internal
{
// if widget exists on the manager, register the callback
auto callBackWidget = AZStd::find(m_widgets.begin(), m_widgets.end(), widget);
AZ_Assert(callBackWidget != m_widgets.end(), "Unable to register a callback for an unregistered widget.")
AZ_Assert(callBackWidget != m_widgets.end(), "Unable to register a callback for an unregistered widget.");
if (callBackWidget != m_widgets.end())
{
@@ -58,8 +56,7 @@ namespace AzToolsFramework::ViewportUi::Internal
RemoveWidget(widget);
}
// check if the widget has not been deleted externally
else if (auto callback = m_updateCallbacks.find(widget);
callback != m_updateCallbacks.end())
else if (auto callback = m_updateCallbacks.find(widget); callback != m_updateCallbacks.end())
{
callback->second(widget);
}
@@ -9,12 +9,12 @@
#pragma once
#include <AzCore/Memory/Memory.h>
#include <AzCore/std/function/function_template.h>
#include <AzCore/std/containers/unordered_map.h>
#include <QPointer>
#include <QObject>
#include <QMetaMethod>
#include <AzCore/std/function/function_template.h>
#include <QMetaMethod>
#include <QObject>
#include <QPointer>
namespace AzToolsFramework::ViewportUi::Internal
{
@@ -30,7 +30,8 @@ namespace AzToolsFramework::ViewportUi::Internal
//! Must call ViewportUiWidgetCallbacks::Update to execute the callback.
void RegisterUpdateCallback(QPointer<QObject> widget, const AZStd::function<void(QPointer<QObject>)>& callback);
void Update();
const AZStd::vector<QPointer<QObject>> GetWidgets() const { return m_widgets; }
const AZStd::vector<QPointer<QObject>>& GetWidgets() const;
protected:
//! A map of all update callbacks and their respective widgets.
@@ -38,4 +39,9 @@ namespace AzToolsFramework::ViewportUi::Internal
AZStd::unordered_map<QObject*, AZStd::function<void(QPointer<QObject>)>> m_updateCallbacks;
AZStd::vector<QPointer<QObject>> m_widgets;
};
inline const AZStd::vector<QPointer<QObject>>& ViewportUiWidgetCallbacks::GetWidgets() const
{
return m_widgets;
}
} // namespace AzToolsFramework::ViewportUi::Internal
@@ -315,7 +315,7 @@ namespace AssetProcessor
}
}
for (const AZ::IO::Path& sourcePath : sourcePaths)
for (const AZ::IO::PathView& sourcePath : sourcePaths)
{
// Use JSON Pointer to append elements to the SourcePaths array
registry.Set(FixedValueString::format("%s/SourcePaths/%zu", PlaceholderGemKey.c_str(), pathIndex++),
@@ -25,8 +25,7 @@ namespace AZ
enum class TangentSpace
{
FromSourceScene = 0,
MikkT = 1,
EMotionFX = 2
MikkT = 1
};
enum class BitangentMethod
@@ -34,7 +34,6 @@ namespace AZ
->Method("GetBitangent", &MeshVertexBitangentData::GetBitangent)
->Method("GetBitangentSetIndex", &MeshVertexBitangentData::GetBitangentSetIndex)
->Method("GetTangentSpace", &MeshVertexBitangentData::GetTangentSpace)
->Enum<(int)SceneAPI::DataTypes::TangentSpace::EMotionFX>("EMotionFX")
->Enum<(int)SceneAPI::DataTypes::TangentSpace::FromSourceScene>("FromSourceScene")
->Enum<(int)SceneAPI::DataTypes::TangentSpace::MikkT>("MikkT");
}
@@ -34,7 +34,6 @@ namespace AZ
->Method("GetTangent", &MeshVertexTangentData::GetTangent)
->Method("GetTangentSetIndex", &MeshVertexTangentData::GetTangentSetIndex)
->Method("GetTangentSpace", &MeshVertexTangentData::GetTangentSpace)
->Enum<(int)SceneAPI::DataTypes::TangentSpace::EMotionFX>("EMotionFX")
->Enum<(int)SceneAPI::DataTypes::TangentSpace::FromSourceScene>("FromSourceScene")
->Enum<(int)SceneAPI::DataTypes::TangentSpace::MikkT>("MikkT");
}
@@ -23,6 +23,7 @@
#include <SceneAPI/SceneData/Rules/MaterialRule.h>
#include <SceneAPI/SceneData/Rules/StaticMeshAdvancedRule.h>
#include <SceneAPI/SceneData/Rules/SkeletonProxyRule.h>
#include <SceneAPI/SceneData/Rules/TangentsRule.h>
#include <SceneAPI/SceneData/Rules/SkinMeshAdvancedRule.h>
#include <SceneAPI/SceneData/Rules/SkinRule.h>
#include <SceneAPI/SceneData/Rules/CoordinateSystemRule.h>
@@ -82,6 +83,10 @@ namespace AZ
{
modifiers.push_back(azrtti_typeid<CoordinateSystemRule>());
}
if (existingRules.find(SceneData::TangentsRule::TYPEINFO_Uuid()) == existingRules.end())
{
modifiers.push_back(SceneData::TangentsRule::TYPEINFO_Uuid());
}
}
else if (target.RTTI_IsTypeOf(DataTypes::ISkinGroup::TYPEINFO_Uuid()))
{
@@ -27,114 +27,14 @@ namespace AZ
TangentsRule::TangentsRule()
: DataTypes::IRule()
, m_tangentSpace(AZ::SceneAPI::DataTypes::TangentSpace::MikkT)
, m_bitangentMethod(AZ::SceneAPI::DataTypes::BitangentMethod::Orthogonal)
, m_uvSetIndex(0)
, m_normalize(true)
{
}
AZ::SceneAPI::DataTypes::TangentSpace TangentsRule::GetTangentSpace() const
{
return m_tangentSpace;
}
AZ::SceneAPI::DataTypes::BitangentMethod TangentsRule::GetBitangentMethod() const
{
return m_bitangentMethod;
}
AZ::u64 TangentsRule::GetUVSetIndex() const
{
return m_uvSetIndex;
}
bool TangentsRule::GetNormalizeVectors() const
{
return m_normalize;
}
// Find UV data.
AZ::SceneAPI::DataTypes::IMeshVertexUVData* TangentsRule::FindUVData(AZ::SceneAPI::Containers::SceneGraph& graph, const AZ::SceneAPI::Containers::SceneGraph::NodeIndex& nodeIndex, AZ::u64 uvSet)
{
const auto nameContentView = AZ::SceneAPI::Containers::Views::MakePairView(graph.GetNameStorage(), graph.GetContentStorage());
AZ::u64 uvSetIndex = 0;
auto meshChildView = AZ::SceneAPI::Containers::Views::MakeSceneGraphChildView<AZ::SceneAPI::Containers::Views::AcceptEndPointsOnly>(graph, nodeIndex, nameContentView.begin(), true);
for (auto child = meshChildView.begin(); child != meshChildView.end(); ++child)
{
AZ::SceneAPI::DataTypes::IMeshVertexUVData* data = azrtti_cast<AZ::SceneAPI::DataTypes::IMeshVertexUVData*>(child->second.get());
if (data)
{
if (uvSetIndex == uvSet)
{
return data;
}
uvSetIndex++;
}
}
return nullptr;
}
// Find tangent data.
AZ::SceneAPI::DataTypes::IMeshVertexTangentData* TangentsRule::FindTangentData(AZ::SceneAPI::Containers::SceneGraph& graph, const AZ::SceneAPI::Containers::SceneGraph::NodeIndex& nodeIndex, AZ::u64 setIndex, AZ::SceneAPI::DataTypes::TangentSpace tangentSpace)
{
const auto nameContentView = AZ::SceneAPI::Containers::Views::MakePairView(graph.GetNameStorage(), graph.GetContentStorage());
auto meshChildView = AZ::SceneAPI::Containers::Views::MakeSceneGraphChildView<AZ::SceneAPI::Containers::Views::AcceptEndPointsOnly>(graph, nodeIndex, nameContentView.begin(), true);
for (auto child = meshChildView.begin(); child != meshChildView.end(); ++child)
{
AZ::SceneAPI::DataTypes::IMeshVertexTangentData* data = azrtti_cast<AZ::SceneAPI::DataTypes::IMeshVertexTangentData*>(child->second.get());
if (data)
{
if (setIndex == data->GetTangentSetIndex() && tangentSpace == data->GetTangentSpace())
{
return data;
}
}
}
return nullptr;
}
// Find bitangent data.
AZ::SceneAPI::DataTypes::IMeshVertexBitangentData* TangentsRule::FindBitangentData(AZ::SceneAPI::Containers::SceneGraph& graph, const AZ::SceneAPI::Containers::SceneGraph::NodeIndex& nodeIndex, AZ::u64 setIndex, AZ::SceneAPI::DataTypes::TangentSpace tangentSpace)
{
const auto nameContentView = AZ::SceneAPI::Containers::Views::MakePairView(graph.GetNameStorage(), graph.GetContentStorage());
auto meshChildView = AZ::SceneAPI::Containers::Views::MakeSceneGraphChildView<AZ::SceneAPI::Containers::Views::AcceptEndPointsOnly>(graph, nodeIndex, nameContentView.begin(), true);
for (auto child = meshChildView.begin(); child != meshChildView.end(); ++child)
{
AZ::SceneAPI::DataTypes::IMeshVertexBitangentData* data = azrtti_cast<AZ::SceneAPI::DataTypes::IMeshVertexBitangentData*>(child->second.get());
if (data)
{
if (setIndex == data->GetBitangentSetIndex() && tangentSpace == data->GetTangentSpace())
{
return data;
}
}
}
return nullptr;
}
AZ::Crc32 TangentsRule::GetNormalizeVisibility() const
{
return (m_tangentSpace == AZ::SceneAPI::DataTypes::TangentSpace::EMotionFX) ? AZ::Edit::PropertyVisibility::Hide : AZ::Edit::PropertyVisibility::Show;
}
AZ::Crc32 TangentsRule::GetOrthogonalVisibility() const
{
return (m_tangentSpace == AZ::SceneAPI::DataTypes::TangentSpace::EMotionFX) ? AZ::Edit::PropertyVisibility::Hide : AZ::Edit::PropertyVisibility::Show;
}
void TangentsRule::Reflect(AZ::ReflectContext* context)
{
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
@@ -143,11 +43,8 @@ namespace AZ
return;
}
serializeContext->Class<TangentsRule, DataTypes::IRule>()->Version(2)
->Field("tangentSpace", &TangentsRule::m_tangentSpace)
->Field("bitangentMethod", &TangentsRule::m_bitangentMethod)
->Field("normalize", &TangentsRule::m_normalize)
->Field("uvSetIndex", &TangentsRule::m_uvSetIndex);
serializeContext->Class<TangentsRule, DataTypes::IRule>()->Version(3)
->Field("tangentSpace", &TangentsRule::m_tangentSpace);
AZ::EditContext* editContext = serializeContext->GetEditContext();
if (editContext)
@@ -159,17 +56,7 @@ namespace AZ
->DataElement(AZ::Edit::UIHandlers::ComboBox, &AZ::SceneAPI::SceneData::TangentsRule::m_tangentSpace, "Tangent space", "Specify the tangent space used for normal map baking. Choose 'From Fbx' to extract the tangents and bitangents directly from the Fbx file. When there is no tangents rule or the Fbx has no tangents stored inside it, the 'MikkT' option will be used with orthogonal tangents of unit length, so with the normalize option enabled, using the first UV set.")
->EnumAttribute(AZ::SceneAPI::DataTypes::TangentSpace::FromSourceScene, "From Source Scene")
->EnumAttribute(AZ::SceneAPI::DataTypes::TangentSpace::MikkT, "MikkT")
->EnumAttribute(AZ::SceneAPI::DataTypes::TangentSpace::EMotionFX, "EMotion FX")
->Attribute(AZ::Edit::Attributes::ChangeNotify, AZ::Edit::PropertyRefreshLevels::EntireTree)
->DataElement(AZ::Edit::UIHandlers::ComboBox, &AZ::SceneAPI::SceneData::TangentsRule::m_bitangentMethod, "Bitangents", "Set to 'use from tangent space' to use the bitangents generated by the algorithm used or inside the fbx file. This can result in non-orthogonal tangents. Set to 'orthogonal' to skip storing the bitangents and let the engine calculate the bitangents in a way it will be perpendicular to both the normal and tangent.")
->EnumAttribute(AZ::SceneAPI::DataTypes::BitangentMethod::UseFromTangentSpace, "Use from tangent space")
->EnumAttribute(AZ::SceneAPI::DataTypes::BitangentMethod::Orthogonal, "Orthogonal")
->Attribute(AZ::Edit::Attributes::Visibility, &TangentsRule::GetOrthogonalVisibility)
->DataElement(AZ::Edit::UIHandlers::Default, &TangentsRule::m_uvSetIndex, "Uv set", "The UV set index to generate the tangents from. A value of 0 means the first uv set, while 1 means the second uv set.")
->Attribute(AZ::Edit::Attributes::Min, 0)
->Attribute(AZ::Edit::Attributes::Max, 1)
->DataElement(AZ::Edit::UIHandlers::Default, &TangentsRule::m_normalize, "Normalize", "Normalize the tangents and bitangents? When disabled the vectors might no be unit length, which can be useful for relief mapping.")
->Attribute(AZ::Edit::Attributes::Visibility, &TangentsRule::GetNormalizeVisibility)
;
}
}
@@ -46,24 +46,11 @@ namespace AZ
SCENE_DATA_API ~TangentsRule() override = default;
SCENE_DATA_API AZ::SceneAPI::DataTypes::TangentSpace GetTangentSpace() const;
SCENE_DATA_API AZ::SceneAPI::DataTypes::BitangentMethod GetBitangentMethod() const;
SCENE_DATA_API AZ::u64 GetUVSetIndex() const;
SCENE_DATA_API bool GetNormalizeVectors() const;
SCENE_DATA_API static AZ::SceneAPI::DataTypes::IMeshVertexUVData* FindUVData(AZ::SceneAPI::Containers::SceneGraph& graph, const AZ::SceneAPI::Containers::SceneGraph::NodeIndex& nodeIndex, AZ::u64 uvSet);
SCENE_DATA_API static AZ::SceneAPI::DataTypes::IMeshVertexTangentData* FindTangentData(AZ::SceneAPI::Containers::SceneGraph& graph, const AZ::SceneAPI::Containers::SceneGraph::NodeIndex& nodeIndex, AZ::u64 setIndex, AZ::SceneAPI::DataTypes::TangentSpace tangentSpace);
SCENE_DATA_API static AZ::SceneAPI::DataTypes::IMeshVertexBitangentData* FindBitangentData(AZ::SceneAPI::Containers::SceneGraph& graph, const AZ::SceneAPI::Containers::SceneGraph::NodeIndex& nodeIndex, AZ::u64 setIndex, AZ::SceneAPI::DataTypes::TangentSpace tangentSpace);
static void Reflect(ReflectContext* context);
protected:
AZ::Crc32 GetNormalizeVisibility() const;
AZ::Crc32 GetOrthogonalVisibility() const;
AZ::SceneAPI::DataTypes::TangentSpace m_tangentSpace; /**< Specifies how to handle tangents. Either generate them, or import them. */
AZ::SceneAPI::DataTypes::BitangentMethod m_bitangentMethod; /**< Grab the bitangents from the generator/source or use an orthogonal basis by always calculating them? */
AZ::u64 m_uvSetIndex; /**< Generate the tangents from this UV set. */
bool m_normalize; /**< Normalize the tangent and bitangents? */
AZ::SceneAPI::DataTypes::TangentSpace m_tangentSpace; /**< Specifies how to handle tangents. Either generate them, or import them. */
};
} // SceneData
} // SceneAPI
@@ -94,7 +94,7 @@ namespace AZ
tangentData->AppendTangent(AZ::Vector4{0.12f, 0.34f, 0.56f, 0.78f});
tangentData->AppendTangent(AZ::Vector4{0.18f, 0.28f, 0.19f, 0.29f});
tangentData->AppendTangent(AZ::Vector4{0.21f, 0.43f, 0.65f, 0.87f});
tangentData->SetTangentSpace(AZ::SceneAPI::DataTypes::TangentSpace::EMotionFX);
tangentData->SetTangentSpace(AZ::SceneAPI::DataTypes::TangentSpace::MikkT);
tangentData->SetTangentSetIndex(2);
return true;
}