From 0502475fa654d8b6fa4e1fce627275b210d8ac94 Mon Sep 17 00:00:00 2001 From: Jose Date: Wed, 7 Jul 2021 13:59:26 -0500 Subject: [PATCH 001/160] Created a toggle switch to enable and disable groups through the EditContext Signed-off-by: Jose --- .../AzCore/AzCore/Serialization/EditContext.h | 59 +++++++++++ .../PropertyEditor/InstanceDataHierarchy.cpp | 6 +- .../UI/PropertyEditor/PropertyRowWidget.cpp | 38 +++++++ .../UI/PropertyEditor/PropertyRowWidget.hxx | 8 ++ .../ReflectedPropertyEditor.cpp | 100 ++++++++++++++---- .../ReflectedPropertyEditor.hxx | 3 + .../Code/Source/GradientSampler.cpp | 9 +- 7 files changed, 193 insertions(+), 30 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/Serialization/EditContext.h b/Code/Framework/AzCore/AzCore/Serialization/EditContext.h index 12ec84161b..ba93d19a3d 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/EditContext.h +++ b/Code/Framework/AzCore/AzCore/Serialization/EditContext.h @@ -235,6 +235,17 @@ namespace AZ */ ClassBuilder* ClassElement(Crc32 elementIdCrc, const char* description); + + /** + * Declare element with attributes that belong to the class SerializeContext::Class, this is a logical structure, you can have one or more ClassElements. + * \uiId is the logical element ID (for instance "Group" when you want to group certain elements this class. + * then in each DataElement you can attach the appropriate group attribute. + * \param memberVariable - reference to the member variable to we can bind to serializations data. + */ + template + ClassBuilder* ClassElement(Crc32 elementIdCrc, const char* description, T memberVariable); + + /** * Declare element with an associated UI handler that does not represent a specific class member variable. * \param uiId - name of a UI handler used to display the element @@ -514,6 +525,54 @@ namespace AZ return this; } + //========================================================================= + // ClassElement + //========================================================================= + template + inline EditContext::ClassBuilder* EditContext::ClassBuilder::ClassElement(Crc32 elementIdCrc, const char* description, T memberVariable) + { + if (IsValid()) + { + using ElementTypeInfo = typename SerializeInternal::ElementInfo; + AZ_Assert( + m_classData->m_typeId == AzTypeInfo::Uuid(), + "Data element (%s) belongs to a different class!", description); + + // Not really portable but works for the supported compilers + size_t offset = + reinterpret_cast(&(reinterpret_cast(0)->*memberVariable)); + // offset = or pass it to the function with offsetof(typename ElementTypeInfo::ClassType,memberVariable); + + SerializeContext::ClassElement* classElement = nullptr; + for (size_t i = 0; i < m_classData->m_elements.size(); ++i) + { + SerializeContext::ClassElement* element = &m_classData->m_elements[i]; + if (element->m_offset == offset) + { + classElement = element; + break; + } + } + // We cannot continue past this point, we must alert the user to fix their serialization config and crash + AZ_Assert( + classElement, + "Class element for editor data element reflection '%s' was NOT found in the serialize context! This member MUST be " + "serializable to be editable!", + description); + + m_classElement->m_elements.push_back(); + Edit::ElementData& ed = m_classElement->m_elements.back(); + + classElement->m_editData = &ed; + m_editElement = &ed; + ed.m_elementId = elementIdCrc; + ed.m_name = description; + ed.m_description = description; + ed.m_serializeClassElement = classElement; + } + return this; + } + //========================================================================= // UIElement //========================================================================= diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/InstanceDataHierarchy.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/InstanceDataHierarchy.cpp index f411c60625..d6054a7937 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/InstanceDataHierarchy.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/InstanceDataHierarchy.cpp @@ -546,7 +546,7 @@ namespace AzToolsFramework for (auto& element : nodeEditData->m_elements) { - if (element.IsClassElement() && element.m_elementId == AZ::Edit::ClassElements::Group) + if (element.m_elementId == AZ::Edit::ClassElements::Group) { groupData = (element.m_description && element.m_description[0]) ? &element : nullptr; continue; @@ -1112,13 +1112,13 @@ namespace AzToolsFramework const AZ::Edit::ElementData* groupData = nullptr; for (const AZ::Edit::ElementData& elementData : parentEditData->m_elements) { - if (node->m_elementEditData == &elementData) // this element matches this node + if ((node->m_elementEditData == &elementData) && (elementData.m_elementId != AZ::Edit::ClassElements::Group)) // this element matches this node { // Record the last found group data node->m_groupElementData = groupData; break; } - else if (elementData.IsClassElement() && elementData.m_elementId == AZ::Edit::ClassElements::Group) + else if (elementData.m_elementId == AZ::Edit::ClassElements::Group) { if (!elementData.m_description || !elementData.m_description[0]) { // close the group diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.cpp index d66ee34c3b..b85fb9cb2e 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.cpp @@ -12,6 +12,7 @@ #include #include +#include AZ_PUSH_DISABLE_WARNING(4244 4251 4800, "-Wunknown-warning-option") // 4244: conversion from 'int' to 'float', possible loss of data // 4251: class '...' needs to have dll-interface to be used by clients of class 'QInputEvent' @@ -141,6 +142,11 @@ namespace AzToolsFramework m_treeDepth = 0; delete m_dropDownArrow; + if (m_toggleSwitch) + { + m_handler->DestroyGUI(m_toggleSwitch); + m_toggleSwitch = nullptr; + } if (m_childWidget) { @@ -387,6 +393,13 @@ namespace AzToolsFramework setUpdatesEnabled(true); } + void PropertyRowWidget::InitializeToggleGroup(const char* groupName, PropertyRowWidget* pParent, int depth, InstanceDataNode* node, int labelWidth) + { + Initialize(groupName, pParent, depth, labelWidth); + ChangeSourceNode(node); + CreateGroupToggleSwitch(); + } + void PropertyRowWidget::Initialize(const char* groupName, PropertyRowWidget* pParent, int depth, int labelWidth) { Initialize(pParent, nullptr, depth, labelWidth); @@ -1102,6 +1115,19 @@ namespace AzToolsFramework } } + void PropertyRowWidget::CreateGroupToggleSwitch() + { + if (!m_toggleSwitch) + { + m_handlerName = AZ::Edit::UIHandlers::CheckBox; + EBUS_EVENT_RESULT(m_handler, PropertyTypeRegistrationMessages::Bus, ResolvePropertyHandler, m_handlerName, azrtti_typeid()); + m_toggleSwitch = m_handler->CreateGUI(this); + m_middleLayout->insertWidget(0, m_toggleSwitch, 1); + auto checkBoxCtrl = reinterpret_cast(m_toggleSwitch); + QObject::connect(checkBoxCtrl, &AzToolsFramework::PropertyCheckBoxCtrl::valueChanged, this, &PropertyRowWidget::OnClickedToggleButton); + } + } + void PropertyRowWidget::SetIndentSize(int w) { m_indent->changeSize(w, 1, QSizePolicy::Fixed, QSizePolicy::Fixed); @@ -1110,6 +1136,18 @@ namespace AzToolsFramework m_leftHandSideLayout->activate(); } + void PropertyRowWidget::OnClickedToggleButton(bool checked) + { + if ((m_expanded && !checked) || (!m_expanded && checked)) + { + DoExpandOrContract(!IsExpanded(), 0 != (QGuiApplication::keyboardModifiers() & Qt::ControlModifier)); + } + } + + void PropertyRowWidget::ChangeSourceNode(InstanceDataNode* node) + { + m_sourceNode = node; + } void PropertyRowWidget::SetExpanded(bool expanded) { diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.hxx b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.hxx index b23691ea44..c5618b1f47 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.hxx +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.hxx @@ -48,6 +48,7 @@ namespace AzToolsFramework virtual void Initialize(PropertyRowWidget* pParent, InstanceDataNode* dataNode, int depth, int labelWidth = 200); virtual void Initialize(const char* groupName, PropertyRowWidget* pParent, int depth, int labelWidth = 200); + virtual void InitializeToggleGroup(const char* groupName, PropertyRowWidget* pParent, int depth, InstanceDataNode* node, int labelWidth = 200); virtual void Clear(); // for pooling // --- NOT A UNIQUE IDENTIFIER --- @@ -141,11 +142,13 @@ namespace AzToolsFramework QVBoxLayout* GetLeftHandSideLayoutParent() { return m_leftHandSideLayoutParent; } QToolButton* GetIndicatorButton() { return m_indicatorButton; } QLabel* GetNameLabel() { return m_nameLabel; } + QWidget* GetToggle() { return m_toggleSwitch; } void SetIndentSize(int w); void SetAsCustom(bool custom) { m_custom = custom; } bool CanChildrenBeReordered() const; bool CanBeReordered() const; + protected: int CalculateLabelWidth() const; @@ -175,6 +178,8 @@ namespace AzToolsFramework QLabel* m_defaultLabel; // if there is no handler, we use a m_defaultLabel label InstanceDataNode* m_sourceNode; + QWidget* m_toggleSwitch = nullptr; + QString m_currentFilterString; struct ChangeNotification @@ -239,6 +244,8 @@ namespace AzToolsFramework void mouseDoubleClickEvent(QMouseEvent* event) override; void UpdateDropDownArrow(); + void CreateGroupToggleSwitch(); + void ChangeSourceNode(InstanceDataNode* node); void UpdateDefaultLabel(InstanceDataNode* node); void createContainerButtons(); @@ -257,6 +264,7 @@ namespace AzToolsFramework private slots: void OnClickedExpansionButton(); + void OnClickedToggleButton(bool checked); void OnClickedAddElementButton(); void OnClickedRemoveElementButton(); void OnClickedClearContainerButton(); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ReflectedPropertyEditor.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ReflectedPropertyEditor.cpp index 1e7b0395c8..a1f67489e9 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ReflectedPropertyEditor.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ReflectedPropertyEditor.cpp @@ -167,6 +167,8 @@ namespace AzToolsFramework InstanceDataHierarchyList m_instances; ///< List of instance sets to display, other one can aggregate other instances. InstanceDataHierarchy::ValueComparisonFunction m_valueComparisonFunction; ReflectedPropertyEditor::WidgetList m_widgets; + ReflectedPropertyEditor::SpecialGroupWidgetList m_specialGroupWidgets; + InstanceDataNode* groupSourceNode = nullptr; RowContainerType m_widgetsInDisplayOrder; UserWidgetToDataMap m_userWidgetsToData; VisibilityCallback m_visibilityCallback; @@ -507,7 +509,25 @@ namespace AzToolsFramework { widgetEntry = CreateOrPullFromPool(); widgetEntry->SetFilterString(m_editor->GetFilterString()); - widgetEntry->Initialize(groupName, parent, depth, m_propertyLabelWidth); + + // Initialized normally if the group does not have a member variable attached to it, + // otherwise initialize it as a group that will have a toggle switch. + if (groupElementData->IsClassElement()) + { + widgetEntry->Initialize(groupName, parent, depth, m_propertyLabelWidth); + } + else + { + widgetEntry->InitializeToggleGroup(groupName, parent, depth, groupSourceNode, m_propertyLabelWidth); + QWidget* toggleSwitch = widgetEntry->GetToggle(); + PropertyHandlerBase* pHandler = widgetEntry->GetHandler(); + m_userWidgetsToData[toggleSwitch] = groupSourceNode; + m_specialGroupWidgets[groupSourceNode] = widgetEntry; + pHandler->ConsumeAttributes_Internal(toggleSwitch, groupSourceNode); + pHandler->ReadValuesIntoGUI_Internal(toggleSwitch, groupSourceNode); + widgetEntry->OnValuesUpdated(); + } + widgetEntry->SetLeafIndentation(m_leafIndentation); widgetEntry->SetTreeIndentation(m_treeIndentation); widgetEntry->setObjectName(groupName); @@ -606,7 +626,7 @@ namespace AzToolsFramework // creates and populates the GUI to edit the property if not already created void ReflectedPropertyEditor::Impl::CreateEditorWidget(PropertyRowWidget* pWidget) { - if (!pWidget->HasChildWidgetAlready()) + if ((!pWidget->HasChildWidgetAlready()) && (!pWidget->GetToggle())) { PropertyHandlerBase* pHandler = pWidget->GetHandler(); if (pHandler) @@ -733,36 +753,44 @@ namespace AzToolsFramework } } } + if ((!node->GetElementEditMetadata()) || (node->GetElementEditMetadata()->m_elementId != AZ::Edit::ClassElements::Group)) + { + pWidget = CreateOrPullFromPool(); + pWidget->show(); - pWidget = CreateOrPullFromPool(); - pWidget->show(); + pWidget->SetFilterString(m_editor->GetFilterString()); + pWidget->Initialize(pParent, node, depth, m_propertyLabelWidth); - pWidget->SetFilterString(m_editor->GetFilterString()); - pWidget->Initialize(pParent, node, depth, m_propertyLabelWidth); + if (labelOverride != "") + { + pWidget->SetNameLabel(labelOverride.data()); + } - if (labelOverride != "") - { - pWidget->SetNameLabel(labelOverride.data()); - } + pWidget->setObjectName(pWidget->label()); + pWidget->SetSelectionEnabled(m_selectionEnabled); + pWidget->SetLeafIndentation(m_leafIndentation); + pWidget->SetTreeIndentation(m_treeIndentation); - pWidget->setObjectName(pWidget->label()); - pWidget->SetSelectionEnabled(m_selectionEnabled); - pWidget->SetLeafIndentation(m_leafIndentation); - pWidget->SetTreeIndentation(m_treeIndentation); + m_widgets[node] = pWidget; + m_widgetsInDisplayOrder.insert(widgetDisplayOrder, pWidget); - m_widgets[node] = pWidget; - m_widgetsInDisplayOrder.insert(widgetDisplayOrder, pWidget); + if (pParent) + { + pParent->AddedChild(pWidget); + } - if (pParent) - { - pParent->AddedChild(pWidget); + if (pParent || !m_hideRootProperties) + { + depth += 1; + } + pParent = pWidget; } - if (pParent || !m_hideRootProperties) + // Save the last InstanceDataNode that is a Group ClassElement so that we can use it as the source node for its widget. + if ((node->GetElementEditMetadata()) && (node->GetElementEditMetadata()->m_elementId == AZ::Edit::ClassElements::Group)) { - depth += 1; + groupSourceNode = node; } - pParent = pWidget; } } @@ -1000,6 +1028,26 @@ namespace AzToolsFramework pWidget->UpdateIndicator(m_impl->m_indicatorQueryFunction(pWidget->GetNode())); } } + + for (auto it = m_impl->m_specialGroupWidgets.begin(); it != m_impl->m_specialGroupWidgets.end(); ++it) + { + PropertyRowWidget* pWidget = it->second; + + QWidget* childWidget = pWidget->GetChildWidget(); + + if (pWidget->GetHandler() && childWidget) + { + pWidget->GetHandler()->ConsumeAttributes_Internal(childWidget, it->first); + pWidget->GetHandler()->ReadValuesIntoGUI_Internal(childWidget, it->first); + pWidget->OnValuesUpdated(); + } + pWidget->RefreshAttributesFromNode(false); + + if (m_impl->m_indicatorQueryFunction) + { + pWidget->UpdateIndicator(m_impl->m_indicatorQueryFunction(pWidget->GetNode())); + } + } } void ReflectedPropertyEditor::InvalidateValues() @@ -1356,8 +1404,14 @@ namespace AzToolsFramework // get the property editor auto rowWidget = m_widgets.find(it->second); - if (rowWidget != m_widgets.end()) + auto rowWidgetGroup = m_specialGroupWidgets.find(it->second); + if (rowWidget != m_widgets.end() || rowWidgetGroup != m_specialGroupWidgets.end()) { + if (rowWidget == m_widgets.end()) + { + rowWidget = rowWidgetGroup; + } + InstanceDataNode* node = rowWidget->first; PropertyRowWidget* widget = rowWidget->second; PropertyHandlerBase* handler = widget->GetHandler(); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ReflectedPropertyEditor.hxx b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ReflectedPropertyEditor.hxx index c27acaa374..42ca0b6d92 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ReflectedPropertyEditor.hxx +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ReflectedPropertyEditor.hxx @@ -50,6 +50,8 @@ namespace AzToolsFramework typedef AZStd::unordered_map WidgetList; + typedef AZStd::unordered_map SpecialGroupWidgetList; + ReflectedPropertyEditor(QWidget* pParent); virtual ~ReflectedPropertyEditor(); @@ -61,6 +63,7 @@ namespace AzToolsFramework bool AddInstance(void* instance, const AZ::Uuid& classId, void* aggregateInstance = nullptr, void* compareInstance = nullptr); void SetCompareInstance(void* instance, const AZ::Uuid& classId); void ClearInstances(); + void ReadValuesIntoGui(QWidget* widget, InstanceDataNode* node); template bool AddInstance(T* instance, void* aggregateInstance = nullptr, void* compareInstance = nullptr) { diff --git a/Gems/GradientSignal/Code/Source/GradientSampler.cpp b/Gems/GradientSignal/Code/Source/GradientSampler.cpp index 944eef2e42..a0a23ffe68 100644 --- a/Gems/GradientSignal/Code/Source/GradientSampler.cpp +++ b/Gems/GradientSignal/Code/Source/GradientSampler.cpp @@ -61,8 +61,9 @@ namespace GradientSignal ->DataElement(0, &GradientSampler::m_invertInput, "Invert Input", "") ->Attribute(AZ::Edit::Attributes::ChangeNotify, &GradientSampler::ChangeNotify) - ->DataElement(0, &GradientSampler::m_enableTransform, "Enable Transform", "") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &GradientSampler::ChangeNotify) + + ->ClassElement(AZ::Edit::ClassElements::Group, "Enable Transform", &GradientSampler::m_enableTransform) + ->Attribute(AZ::Edit::Attributes::AutoExpand, false) ->DataElement(0, &GradientSampler::m_translate, "Translate", "") ->Attribute(AZ::Edit::Attributes::ReadOnly, &GradientSampler::AreTransformSettingsDisabled) ->Attribute(AZ::Edit::Attributes::ChangeNotify, &GradientSampler::ChangeNotify) @@ -73,8 +74,8 @@ namespace GradientSignal ->Attribute(AZ::Edit::Attributes::ReadOnly, &GradientSampler::AreTransformSettingsDisabled) ->Attribute(AZ::Edit::Attributes::ChangeNotify, &GradientSampler::ChangeNotify) - ->DataElement(0, &GradientSampler::m_enableLevels, "Enable Levels", "") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &GradientSampler::ChangeNotify) + ->ClassElement(AZ::Edit::ClassElements::Group, "Enable Levels", &GradientSampler::m_enableLevels) + ->Attribute(AZ::Edit::Attributes::AutoExpand, false) ->DataElement(AZ::Edit::UIHandlers::Slider, &GradientSampler::m_inputMid, "Input Mid", "") ->Attribute(AZ::Edit::Attributes::Min, 0.0f) ->Attribute(AZ::Edit::Attributes::Max, 10.0f) From e18bcc63f2a2b294e87f4328ea2f787cc8e1b82e Mon Sep 17 00:00:00 2001 From: Jose Date: Wed, 7 Jul 2021 15:12:43 -0500 Subject: [PATCH 002/160] Fixed a bug in the ReflectedPropertyError that was preventing groups from opening correctly Signed-off-by: Jose --- .../ReflectedPropertyEditor.cpp | 20 ------------------- 1 file changed, 20 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ReflectedPropertyEditor.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ReflectedPropertyEditor.cpp index a1f67489e9..02048a1161 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ReflectedPropertyEditor.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ReflectedPropertyEditor.cpp @@ -1028,26 +1028,6 @@ namespace AzToolsFramework pWidget->UpdateIndicator(m_impl->m_indicatorQueryFunction(pWidget->GetNode())); } } - - for (auto it = m_impl->m_specialGroupWidgets.begin(); it != m_impl->m_specialGroupWidgets.end(); ++it) - { - PropertyRowWidget* pWidget = it->second; - - QWidget* childWidget = pWidget->GetChildWidget(); - - if (pWidget->GetHandler() && childWidget) - { - pWidget->GetHandler()->ConsumeAttributes_Internal(childWidget, it->first); - pWidget->GetHandler()->ReadValuesIntoGUI_Internal(childWidget, it->first); - pWidget->OnValuesUpdated(); - } - pWidget->RefreshAttributesFromNode(false); - - if (m_impl->m_indicatorQueryFunction) - { - pWidget->UpdateIndicator(m_impl->m_indicatorQueryFunction(pWidget->GetNode())); - } - } } void ReflectedPropertyEditor::InvalidateValues() From 11eb920e400b0252fda27b1f6b39cf1f6c0ea1d5 Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Mon, 12 Jul 2021 15:29:56 -0700 Subject: [PATCH 003/160] Removal of dead code and bug fixes for reflection Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com> --- .../Platform/Windows/AzCore/Debug/StackTracer_Windows.cpp | 2 +- .../Code/Source/Shape/PolygonPrismShapeComponent.cpp | 2 +- .../Include/ScriptCanvas/Data/BehaviorContextObject.h | 8 +++++++- .../Code/Source/Framework/ScriptCanvasTestFixture.h | 5 ----- .../Code/Source/Framework/ScriptCanvasTestUtilities.cpp | 8 -------- 5 files changed, 9 insertions(+), 16 deletions(-) diff --git a/Code/Framework/AzCore/Platform/Windows/AzCore/Debug/StackTracer_Windows.cpp b/Code/Framework/AzCore/Platform/Windows/AzCore/Debug/StackTracer_Windows.cpp index 39f6c02bde..a40dd2daac 100644 --- a/Code/Framework/AzCore/Platform/Windows/AzCore/Debug/StackTracer_Windows.cpp +++ b/Code/Framework/AzCore/Platform/Windows/AzCore/Debug/StackTracer_Windows.cpp @@ -38,7 +38,7 @@ namespace AZ { struct SymbolStorageDynamicallyLoadedModules { size_t m_size; - DynamicallyLoadedModuleInfo m_modules[256]; + DynamicallyLoadedModuleInfo m_modules[1028]; SymbolStorageDynamicallyLoadedModules() : m_size(0) diff --git a/Gems/LmbrCentral/Code/Source/Shape/PolygonPrismShapeComponent.cpp b/Gems/LmbrCentral/Code/Source/Shape/PolygonPrismShapeComponent.cpp index 22b0cbfb03..6bb4c1238c 100644 --- a/Gems/LmbrCentral/Code/Source/Shape/PolygonPrismShapeComponent.cpp +++ b/Gems/LmbrCentral/Code/Source/Shape/PolygonPrismShapeComponent.cpp @@ -98,7 +98,7 @@ namespace LmbrCentral if (AZ::BehaviorContext* behaviorContext = azrtti_cast(context)) { behaviorContext->EBus("PolygonPrismShapeComponentRequestBus") - ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation) + ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) ->Attribute(AZ::Edit::Attributes::Category, "Shape") ->Attribute(AZ::Script::Attributes::Module, "shape") ->Event("GetPolygonPrism", &PolygonPrismShapeComponentRequestBus::Events::GetPolygonPrism) diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Data/BehaviorContextObject.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Data/BehaviorContextObject.h index 29831e20f9..4980fdd37b 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Data/BehaviorContextObject.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Data/BehaviorContextObject.h @@ -115,7 +115,6 @@ namespace ScriptCanvas AZ_FORCE_INLINE BehaviorContextObject() = default; BehaviorContextObject& operator=(const BehaviorContextObject&) = delete; - BehaviorContextObject(const BehaviorContextObject&) = delete; // copy ctor AZ_FORCE_INLINE BehaviorContextObject(const void* source, const AnyTypeInfo& typeInfo, AZ::u32 flags); @@ -134,6 +133,13 @@ namespace ScriptCanvas AZ_FORCE_INLINE void add_ref(); void release(); + + public: + // no copying allowed, this is here to allow compile time compatibility with storage in of BehaviorContextObjectPtr AZStd::any, only + AZ_FORCE_INLINE BehaviorContextObject(const BehaviorContextObject&) + { + AZ_Assert(false, "no copying allowed, this is here to allow storage in of BehaviorContextObjectPtr AZStd::any, only"); + } }; AZ_FORCE_INLINE BehaviorContextObject::BehaviorContextObject(const void* value, const AnyTypeInfo& typeInfo, AZ::u32 flags) diff --git a/Gems/ScriptCanvasTesting/Code/Source/Framework/ScriptCanvasTestFixture.h b/Gems/ScriptCanvasTesting/Code/Source/Framework/ScriptCanvasTestFixture.h index 0a4408b689..403a1623d6 100644 --- a/Gems/ScriptCanvasTesting/Code/Source/Framework/ScriptCanvasTestFixture.h +++ b/Gems/ScriptCanvasTesting/Code/Source/Framework/ScriptCanvasTestFixture.h @@ -135,11 +135,6 @@ namespace ScriptCanvasTests // don't hang on to dangling assets AZ::Data::AssetManager::Instance().DispatchEvents(); - if (AZ::IO::FileIOBase* fileIO = AZ::IO::FileIOBase::GetInstance()) - { - fileIO->DestroyPath(k_tempCoreAssetDir); - } - if (s_application) { s_application->Stop(); diff --git a/Gems/ScriptCanvasTesting/Code/Source/Framework/ScriptCanvasTestUtilities.cpp b/Gems/ScriptCanvasTesting/Code/Source/Framework/ScriptCanvasTestUtilities.cpp index 03ecba29be..8b231d5fdc 100644 --- a/Gems/ScriptCanvasTesting/Code/Source/Framework/ScriptCanvasTestUtilities.cpp +++ b/Gems/ScriptCanvasTesting/Code/Source/Framework/ScriptCanvasTestUtilities.cpp @@ -33,14 +33,6 @@ namespace ScriptCanvasTests { using namespace ScriptCanvas; -#define SC_CORE_UNIT_TEST_DIR "@engroot@/LY_SC_UnitTest_ScriptCanvas_CoreCPP_Temporary" -#define SC_CORE_UNIT_TEST_NAME "serializationTest.scriptcanvas_compiled" - const char* k_tempCoreAssetDir = SC_CORE_UNIT_TEST_DIR; - const char* k_tempCoreAssetName = SC_CORE_UNIT_TEST_NAME; - const char* k_tempCoreAssetPath = SC_CORE_UNIT_TEST_DIR "/" SC_CORE_UNIT_TEST_NAME; -#undef SC_CORE_UNIT_TEST_DIR -#undef SC_CORE_UNIT_TEST_NAME - void ExpectParse(AZStd::string_view graphPath) { AZ_TEST_START_TRACE_SUPPRESSION; From bc9d0eb0e1c70843c097a88fe720a5bd4d5ca524 Mon Sep 17 00:00:00 2001 From: Jose Date: Tue, 13 Jul 2021 14:55:05 -0500 Subject: [PATCH 004/160] Added unit tests for groups and toggle groups, fixed comments and syntax Signed-off-by: Jose --- .../AzCore/AzCore/Serialization/EditContext.h | 53 +-- .../PropertyEditor/InstanceDataHierarchy.cpp | 3 +- .../UI/PropertyEditor/PropertyRowWidget.cpp | 6 +- .../UI/PropertyEditor/PropertyRowWidget.hxx | 1 + .../ReflectedPropertyEditor.cpp | 22 +- .../ReflectedPropertyEditor.hxx | 2 +- .../Framework/Tests/InstanceDataHierarchy.cpp | 335 ++++++++++++++++++ .../Code/Source/GradientSampler.cpp | 6 +- 8 files changed, 363 insertions(+), 65 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/Serialization/EditContext.h b/Code/Framework/AzCore/AzCore/Serialization/EditContext.h index ba93d19a3d..61c7df4471 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/EditContext.h +++ b/Code/Framework/AzCore/AzCore/Serialization/EditContext.h @@ -237,13 +237,13 @@ namespace AZ /** - * Declare element with attributes that belong to the class SerializeContext::Class, this is a logical structure, you can have one or more ClassElements. - * \uiId is the logical element ID (for instance "Group" when you want to group certain elements this class. - * then in each DataElement you can attach the appropriate group attribute. - * \param memberVariable - reference to the member variable to we can bind to serializations data. + * Declare element with attributes that belong to the class SerializeContext::Class, this is a logical structure, you can have one or more GroupElementToggles. + * T must be a boolean variable that will enable and disable each DataElement attached to this structure. + * \param description - Descriptive name of the field that will typically appear in a tooltip. + * \param memberVariable - reference to the member variable so we can bind to serialization data. */ template - ClassBuilder* ClassElement(Crc32 elementIdCrc, const char* description, T memberVariable); + ClassBuilder* GroupElementToggle(const char* description, T memberVariable); /** @@ -529,48 +529,9 @@ namespace AZ // ClassElement //========================================================================= template - inline EditContext::ClassBuilder* EditContext::ClassBuilder::ClassElement(Crc32 elementIdCrc, const char* description, T memberVariable) + inline EditContext::ClassBuilder* EditContext::ClassBuilder::GroupElementToggle(const char* name, T memberVariable) { - if (IsValid()) - { - using ElementTypeInfo = typename SerializeInternal::ElementInfo; - AZ_Assert( - m_classData->m_typeId == AzTypeInfo::Uuid(), - "Data element (%s) belongs to a different class!", description); - - // Not really portable but works for the supported compilers - size_t offset = - reinterpret_cast(&(reinterpret_cast(0)->*memberVariable)); - // offset = or pass it to the function with offsetof(typename ElementTypeInfo::ClassType,memberVariable); - - SerializeContext::ClassElement* classElement = nullptr; - for (size_t i = 0; i < m_classData->m_elements.size(); ++i) - { - SerializeContext::ClassElement* element = &m_classData->m_elements[i]; - if (element->m_offset == offset) - { - classElement = element; - break; - } - } - // We cannot continue past this point, we must alert the user to fix their serialization config and crash - AZ_Assert( - classElement, - "Class element for editor data element reflection '%s' was NOT found in the serialize context! This member MUST be " - "serializable to be editable!", - description); - - m_classElement->m_elements.push_back(); - Edit::ElementData& ed = m_classElement->m_elements.back(); - - classElement->m_editData = &ed; - m_editElement = &ed; - ed.m_elementId = elementIdCrc; - ed.m_name = description; - ed.m_description = description; - ed.m_serializeClassElement = classElement; - } - return this; + return DataElement(AZ::Edit::ClassElements::Group, memberVariable, name, name, ""); } //========================================================================= diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/InstanceDataHierarchy.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/InstanceDataHierarchy.cpp index d6054a7937..9b69701a27 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/InstanceDataHierarchy.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/InstanceDataHierarchy.cpp @@ -1112,7 +1112,8 @@ namespace AzToolsFramework const AZ::Edit::ElementData* groupData = nullptr; for (const AZ::Edit::ElementData& elementData : parentEditData->m_elements) { - if ((node->m_elementEditData == &elementData) && (elementData.m_elementId != AZ::Edit::ClassElements::Group)) // this element matches this node + // this element matches this node + if ((node->m_elementEditData == &elementData) && (elementData.m_elementId != AZ::Edit::ClassElements::Group)) { // Record the last found group data node->m_groupElementData = groupData; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.cpp index b85fb9cb2e..e6f2af6a52 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.cpp @@ -1120,10 +1120,10 @@ namespace AzToolsFramework if (!m_toggleSwitch) { m_handlerName = AZ::Edit::UIHandlers::CheckBox; - EBUS_EVENT_RESULT(m_handler, PropertyTypeRegistrationMessages::Bus, ResolvePropertyHandler, m_handlerName, azrtti_typeid()); + PropertyTypeRegistrationMessages::Bus::BroadcastResult(m_handler, &PropertyTypeRegistrationMessages::Bus::Events::ResolvePropertyHandler, m_handlerName, azrtti_typeid()); m_toggleSwitch = m_handler->CreateGUI(this); m_middleLayout->insertWidget(0, m_toggleSwitch, 1); - auto checkBoxCtrl = reinterpret_cast(m_toggleSwitch); + auto checkBoxCtrl = static_cast(m_toggleSwitch); QObject::connect(checkBoxCtrl, &AzToolsFramework::PropertyCheckBoxCtrl::valueChanged, this, &PropertyRowWidget::OnClickedToggleButton); } } @@ -1138,7 +1138,7 @@ namespace AzToolsFramework void PropertyRowWidget::OnClickedToggleButton(bool checked) { - if ((m_expanded && !checked) || (!m_expanded && checked)) + if (m_expanded != checked) { DoExpandOrContract(!IsExpanded(), 0 != (QGuiApplication::keyboardModifiers() & Qt::ControlModifier)); } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.hxx b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.hxx index c5618b1f47..93c1fc4d03 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.hxx +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.hxx @@ -143,6 +143,7 @@ namespace AzToolsFramework QToolButton* GetIndicatorButton() { return m_indicatorButton; } QLabel* GetNameLabel() { return m_nameLabel; } QWidget* GetToggle() { return m_toggleSwitch; } + const QWidget* GetToggle() const { return m_toggleSwitch; } void SetIndentSize(int w); void SetAsCustom(bool custom) { m_custom = custom; } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ReflectedPropertyEditor.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ReflectedPropertyEditor.cpp index 02048a1161..d16fbb2776 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ReflectedPropertyEditor.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ReflectedPropertyEditor.cpp @@ -167,7 +167,7 @@ namespace AzToolsFramework InstanceDataHierarchyList m_instances; ///< List of instance sets to display, other one can aggregate other instances. InstanceDataHierarchy::ValueComparisonFunction m_valueComparisonFunction; ReflectedPropertyEditor::WidgetList m_widgets; - ReflectedPropertyEditor::SpecialGroupWidgetList m_specialGroupWidgets; + ReflectedPropertyEditor::WidgetList m_specialGroupWidgets; InstanceDataNode* groupSourceNode = nullptr; RowContainerType m_widgetsInDisplayOrder; UserWidgetToDataMap m_userWidgetsToData; @@ -626,7 +626,7 @@ namespace AzToolsFramework // creates and populates the GUI to edit the property if not already created void ReflectedPropertyEditor::Impl::CreateEditorWidget(PropertyRowWidget* pWidget) { - if ((!pWidget->HasChildWidgetAlready()) && (!pWidget->GetToggle())) + if (!pWidget->HasChildWidgetAlready() && !pWidget->GetToggle()) { PropertyHandlerBase* pHandler = pWidget->GetHandler(); if (pHandler) @@ -753,7 +753,7 @@ namespace AzToolsFramework } } } - if ((!node->GetElementEditMetadata()) || (node->GetElementEditMetadata()->m_elementId != AZ::Edit::ClassElements::Group)) + if (!node->GetElementEditMetadata() || (node->GetElementEditMetadata()->m_elementId != AZ::Edit::ClassElements::Group)) { pWidget = CreateOrPullFromPool(); pWidget->show(); @@ -787,7 +787,7 @@ namespace AzToolsFramework } // Save the last InstanceDataNode that is a Group ClassElement so that we can use it as the source node for its widget. - if ((node->GetElementEditMetadata()) && (node->GetElementEditMetadata()->m_elementId == AZ::Edit::ClassElements::Group)) + if (node->GetElementEditMetadata() && (node->GetElementEditMetadata()->m_elementId == AZ::Edit::ClassElements::Group)) { groupSourceNode = node; } @@ -1382,16 +1382,14 @@ namespace AzToolsFramework return; } - // get the property editor + // Get the property editor from either the widget map or the special toggle group widgets auto rowWidget = m_widgets.find(it->second); - auto rowWidgetGroup = m_specialGroupWidgets.find(it->second); - if (rowWidget != m_widgets.end() || rowWidgetGroup != m_specialGroupWidgets.end()) + if (rowWidget == m_widgets.end()) + { + rowWidget = m_specialGroupWidgets.find(it->second); + } + if (rowWidget != m_widgets.end() || rowWidget != m_specialGroupWidgets.end()) { - if (rowWidget == m_widgets.end()) - { - rowWidget = rowWidgetGroup; - } - InstanceDataNode* node = rowWidget->first; PropertyRowWidget* widget = rowWidget->second; PropertyHandlerBase* handler = widget->GetHandler(); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ReflectedPropertyEditor.hxx b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ReflectedPropertyEditor.hxx index 42ca0b6d92..bd5a6ab891 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ReflectedPropertyEditor.hxx +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ReflectedPropertyEditor.hxx @@ -50,7 +50,7 @@ namespace AzToolsFramework typedef AZStd::unordered_map WidgetList; - typedef AZStd::unordered_map SpecialGroupWidgetList; + ReflectedPropertyEditor::WidgetList m_specialGroupWidgets; ReflectedPropertyEditor(QWidget* pParent); virtual ~ReflectedPropertyEditor(); diff --git a/Code/Framework/Tests/InstanceDataHierarchy.cpp b/Code/Framework/Tests/InstanceDataHierarchy.cpp index db0223c0cf..29cf42fb6b 100644 --- a/Code/Framework/Tests/InstanceDataHierarchy.cpp +++ b/Code/Framework/Tests/InstanceDataHierarchy.cpp @@ -20,6 +20,7 @@ #include #include #include +#include using namespace AZ; @@ -726,6 +727,101 @@ namespace UnitTest }; + class InstanceDataHierarchyGroupTestFixture + : public AllocatorsFixture + { + public: + InstanceDataHierarchyGroupTestFixture() = default; + }; + + class GroupTestComponent + : public AZ::Component + { + public: + AZ_COMPONENT(GroupTestComponent, "{C088C81D-D59D-43F1-85F8-B2E591BABA36}") + + GroupTestComponent() = default; + + struct SubData + { + AZ_TYPE_INFO(SubData, "{983316B5-17C0-476E-9CEB-CA749B3ABE5D}"); + AZ_CLASS_ALLOCATOR(SubData, AZ::SystemAllocator, 0); + + SubData() {} + SubData(int v) : m_int(v) {} + SubData(bool b) : m_bool(b) {} + SubData(float f) : m_float(f) {} + ~SubData() = default; + + float m_float = 0.f; + int m_int = 0; + bool m_bool = true; + }; + + static void Reflect(AZ::ReflectContext* context) + { + if (auto* serializeContext = azrtti_cast(context)) + { + serializeContext->Class() + ->Version(1) + ->Field("SubInt", &SubData::m_int) + ->Field("SubToggle", &SubData::m_bool) + ->Field("SubFloat", &SubData::m_float) + ; + + serializeContext->Class() + ->Version(1) + ->Field("Float", &GroupTestComponent::m_float) + ->Field("GroupToggle", &GroupTestComponent::m_groupToggle) + ->Field("GroupFloat", &GroupTestComponent::m_groupFloat) + ->Field("ToggleGroupInt", &GroupTestComponent::m_toggleGroupInt) + ->Field("SubDataNormal", &GroupTestComponent::m_subGroupForNormal) + ->Field("SubDataToggle", &GroupTestComponent::m_subGroupForToggle) + ; + + if (AZ::EditContext* edit = serializeContext->GetEditContext()) + { + edit->Class("Group Test Component", "Testing normal groups and toggle groups") + ->ClassElement(AZ::Edit::ClassElements::EditorData, "") + ->DataElement(0, &GroupTestComponent::m_float, "Float Field", "A float field") + ->ClassElement(AZ::Edit::ClassElements::Group, "Normal Group") + ->DataElement(0, &GroupTestComponent::m_groupFloat, "Float Field", "A float field") + ->DataElement(0, &GroupTestComponent::m_subGroupForNormal, "Struct Field", "A sub data type") + ->GroupElementToggle("Group Toggle", &GroupTestComponent::m_groupToggle) + ->DataElement(0, &GroupTestComponent::m_toggleGroupInt, "Normal Integer", "An Integer") + ->DataElement(0, &GroupTestComponent::m_subGroupForToggle, "Struct Field", "A sub data type") + ; + + edit->Class("SubGroup Test Component", "Testing nested normal groups and toggle groups") + ->ClassElement(AZ::Edit::ClassElements::EditorData, "") + ->ClassElement(AZ::Edit::ClassElements::Group, "Normal SubGroup") + ->DataElement(0, &SubData::m_int, "SubGroup Int Field", "An int") + ->GroupElementToggle("SubGroup Toggle", &SubData::m_bool) + ->DataElement(0, &SubData::m_float, "SubGroup Float Field", "An int") + ; + } + } + } + + void Activate() override + { + } + + void Deactivate() override + { + } + + float m_float = 0.f; + float m_groupFloat = 0.f; + int m_toggleGroupInt = 0; + AZStd::string m_string; + bool m_groupToggle = false; + + SubData m_subGroupForNormal; + SubData m_subGroupForToggle; + }; + + class InstanceDataHierarchyKeyedContainerTest : public AllocatorsFixture { @@ -1314,4 +1410,243 @@ namespace UnitTest run(); } + TEST_F(InstanceDataHierarchyGroupTestFixture, TestNormalGroups) + { + using namespace AzToolsFramework; + + // Setting up the data node hierarchy + AZ::SerializeContext serializeContext; + serializeContext.CreateEditContext(); + Entity::Reflect(&serializeContext); + GroupTestComponent::Reflect(&serializeContext); + + AZStd::unique_ptr testEntity1(new AZ::Entity()); + testEntity1->CreateComponent(); + + InstanceDataHierarchy instanceDataHierarchy; + instanceDataHierarchy.AddRootInstance(testEntity1.get()); + instanceDataHierarchy.Build(&serializeContext, 0); + + // Adding the nodes to a node stack + auto rootNode = instanceDataHierarchy.GetRootNode(); + AZStd::stack nodeStack; + nodeStack.push(rootNode); + InstanceDataNode* componentNode1 = nullptr; + while (!nodeStack.empty()) + { + InstanceDataNode* node = nodeStack.top(); + nodeStack.pop(); + if (node->GetClassMetadata()->m_typeId == AZ::AzTypeInfo::Uuid()) + { + componentNode1 = node; + break; + } + for (InstanceDataNode& child : node->GetChildren()) + { + nodeStack.push(&child); + } + } + // Iterating through the children in the instance data hierarchy to verify their properties + ASSERT_TRUE(componentNode1 != nullptr); + for (auto child : componentNode1->GetChildren()) + { + AZStd::string childName(child.GetElementMetadata()->m_name); + if (childName.compare("GroupFloat") == 0) + { + // False for any child node with serializable data + ASSERT_FALSE(child.GetElementEditMetadata()->IsClassElement()); + // Child node should never be a ClassElement::Group, unless it is the root node of a ToggleGroup + ASSERT_NE(child.GetElementEditMetadata()->m_elementId, AZ::Edit::ClassElements::Group); + // Ensuring that this node was assigned to the appropriate group + ASSERT_EQ(child.GetGroupElementMetadata()->m_description, "Normal Group"); + // Ensuring that this node has the correct parent + ASSERT_EQ(child.GetParent()->GetClassMetadata()->m_name, "GroupTestComponent"); + } + } + } + + TEST_F(InstanceDataHierarchyGroupTestFixture, TestToggleGroups) + { + using namespace AzToolsFramework; + + // Setting up the data node hierarchy + AZ::SerializeContext serializeContext; + serializeContext.CreateEditContext(); + Entity::Reflect(&serializeContext); + GroupTestComponent::Reflect(&serializeContext); + + AZStd::unique_ptr testEntity1(new AZ::Entity()); + testEntity1->CreateComponent(); + + InstanceDataHierarchy instanceDataHierarchy; + instanceDataHierarchy.AddRootInstance(testEntity1.get()); + instanceDataHierarchy.Build(&serializeContext, 0); + + // Adding the nodes to a node stack + auto rootNode = instanceDataHierarchy.GetRootNode(); + AZStd::stack nodeStack; + nodeStack.push(rootNode); + InstanceDataNode* componentNode1 = nullptr; + while (!nodeStack.empty()) + { + InstanceDataNode* node = nodeStack.top(); + nodeStack.pop(); + if (node->GetClassMetadata()->m_typeId == AZ::AzTypeInfo::Uuid()) + { + componentNode1 = node; + break; + } + for (InstanceDataNode& child : node->GetChildren()) + { + nodeStack.push(&child); + } + } + // Iterating through the children in the instance data hierarchy to verify their properties + ASSERT_TRUE(componentNode1 != nullptr); + for (auto child : componentNode1->GetChildren()) + { + AZStd::string childName(child.GetElementMetadata()->m_name); + if (childName.compare("GroupToggle") == 0) + { + // False for any child node with serializable data + ASSERT_FALSE(child.GetElementEditMetadata()->IsClassElement()); + // Child node is the root node of a ToggleGroup, so it should be a ClassElement::Group + ASSERT_EQ(child.GetElementEditMetadata()->m_elementId, AZ::Edit::ClassElements::Group); + // Ensuring that this node has the correct parent + ASSERT_EQ(child.GetParent()->GetClassMetadata()->m_name, "GroupTestComponent"); + } + if (childName.compare("ToggleGroupInt") == 0) + { + // False for any child node with serializable data + ASSERT_FALSE(child.GetElementEditMetadata()->IsClassElement()); + // Child node should never be a ClassElement::Group, unless it is the root node of a ToggleGroup + ASSERT_NE(child.GetElementEditMetadata()->m_elementId, AZ::Edit::ClassElements::Group); + // Ensuring that this node was assigned to the appropriate group + ASSERT_EQ(child.GetGroupElementMetadata()->m_description, "Group Toggle"); + // Ensuring that this node has the correct parent + ASSERT_EQ(child.GetParent()->GetClassMetadata()->m_name, "GroupTestComponent"); + } + } + } + + TEST_F(InstanceDataHierarchyGroupTestFixture, TestNestedGroups) + { + using namespace AzToolsFramework; + + // Setting up the data node hierarchy + AZ::SerializeContext serializeContext; + serializeContext.CreateEditContext(); + Entity::Reflect(&serializeContext); + GroupTestComponent::Reflect(&serializeContext); + + AZStd::unique_ptr testEntity1(new AZ::Entity()); + testEntity1->CreateComponent(); + + InstanceDataHierarchy instanceDataHierarchy; + instanceDataHierarchy.AddRootInstance(testEntity1.get()); + instanceDataHierarchy.Build(&serializeContext, 0); + + // Adding the nodes to a node stack + auto rootNode = instanceDataHierarchy.GetRootNode(); + AZStd::stack nodeStack; + nodeStack.push(rootNode); + InstanceDataNode* componentNode1 = nullptr; + while (!nodeStack.empty()) + { + InstanceDataNode* node = nodeStack.top(); + nodeStack.pop(); + if (node->GetClassMetadata()->m_typeId == AZ::AzTypeInfo::Uuid()) + { + componentNode1 = node; + break; + } + for (InstanceDataNode& child : node->GetChildren()) + { + nodeStack.push(&child); + } + } + // Iterating through the children in the instance data hierarchy to verify their properties + ASSERT_TRUE(componentNode1 != nullptr); + for (auto child : componentNode1->GetChildren()) + { + AZStd::string childName(child.GetElementMetadata()->m_name); + if (childName.compare("SubDataNormal") == 0) + { + for (InstanceDataNode& subChild : child.GetChildren()) + { + childName = subChild.GetElementMetadata()->m_name; + if (childName.compare("SubInt") == 0) + { + // False for any child node with serializable data + ASSERT_FALSE(subChild.GetElementEditMetadata()->IsClassElement()); + // Child node should never be a ClassElement::Group, unless it is the root node of a ToggleGroup + ASSERT_NE(subChild.GetElementEditMetadata()->m_elementId, AZ::Edit::ClassElements::Group); + // Ensuring that this node was assigned to the appropriate group + ASSERT_EQ(subChild.GetGroupElementMetadata()->m_description, "Normal SubGroup"); + // Ensuring that this node has the correct parent + ASSERT_EQ(subChild.GetParent()->GetClassMetadata()->m_name, "SubData"); + } + if (childName.compare("SubToggle") == 0) + { + // False for any child node with serializable data + ASSERT_FALSE(subChild.GetElementEditMetadata()->IsClassElement()); + // Child node is the root node of a ToggleGroup, so it should be a ClassElement::Group + ASSERT_EQ(subChild.GetElementEditMetadata()->m_elementId, AZ::Edit::ClassElements::Group); + // Ensuring that this node has the correct parent + ASSERT_EQ(subChild.GetParent()->GetClassMetadata()->m_name, "SubData"); + } + if (childName.compare("SubFloat") == 0) + { + // False for any child node with serializable data + ASSERT_FALSE(subChild.GetElementEditMetadata()->IsClassElement()); + // Child node should never be a ClassElement::Group, unless it is the root node of a ToggleGroup + ASSERT_NE(subChild.GetElementEditMetadata()->m_elementId, AZ::Edit::ClassElements::Group); + // Ensuring that this node was assigned to the appropriate group + ASSERT_EQ(subChild.GetGroupElementMetadata()->m_description, "SubGroup Toggle"); + // Ensuring that this node has the correct parent + ASSERT_EQ(subChild.GetParent()->GetClassMetadata()->m_name, "SubData"); + } + } + } + if (childName.compare("SubDataToggle") == 0) + { + for (InstanceDataNode& subChild : child.GetChildren()) + { + childName = subChild.GetElementMetadata()->m_name; + if (childName.compare("SubInt") == 0) + { + // False for any child node with serializable data + ASSERT_FALSE(subChild.GetElementEditMetadata()->IsClassElement()); + // Child node should never be a ClassElement::Group, unless it is the root node of a ToggleGroup + ASSERT_NE(subChild.GetElementEditMetadata()->m_elementId, AZ::Edit::ClassElements::Group); + // Ensuring that this node was assigned to the appropriate group + ASSERT_EQ(subChild.GetGroupElementMetadata()->m_description, "Normal SubGroup"); + // Ensuring that this node has the correct parent + ASSERT_EQ(subChild.GetParent()->GetClassMetadata()->m_name, "SubData"); + } + if (childName.compare("SubToggle") == 0) + { + // False for any child node with serializable data + ASSERT_FALSE(subChild.GetElementEditMetadata()->IsClassElement()); + // Child node is the root node of a ToggleGroup, so it should be a ClassElement::Group + ASSERT_EQ(subChild.GetElementEditMetadata()->m_elementId, AZ::Edit::ClassElements::Group); + // Ensuring that this node has the correct parent + ASSERT_EQ(subChild.GetParent()->GetClassMetadata()->m_name, "SubData"); + } + if (childName.compare("SubFloat") == 0) + { + // False for any child node with serializable data + ASSERT_FALSE(subChild.GetElementEditMetadata()->IsClassElement()); + // Child node should never be a ClassElement::Group, unless it is the root node of a ToggleGroup + ASSERT_NE(subChild.GetElementEditMetadata()->m_elementId, AZ::Edit::ClassElements::Group); + // Ensuring that this node was assigned to the appropriate group + ASSERT_EQ(subChild.GetGroupElementMetadata()->m_description, "SubGroup Toggle"); + // Ensuring that this node has the correct parent + ASSERT_EQ(subChild.GetParent()->GetClassMetadata()->m_name, "SubData"); + } + } + } + } + } + } // namespace UnitTest diff --git a/Gems/GradientSignal/Code/Source/GradientSampler.cpp b/Gems/GradientSignal/Code/Source/GradientSampler.cpp index a0a23ffe68..c89a63790a 100644 --- a/Gems/GradientSignal/Code/Source/GradientSampler.cpp +++ b/Gems/GradientSignal/Code/Source/GradientSampler.cpp @@ -62,8 +62,9 @@ namespace GradientSignal ->DataElement(0, &GradientSampler::m_invertInput, "Invert Input", "") ->Attribute(AZ::Edit::Attributes::ChangeNotify, &GradientSampler::ChangeNotify) - ->ClassElement(AZ::Edit::ClassElements::Group, "Enable Transform", &GradientSampler::m_enableTransform) + ->GroupElementToggle("Enable Transform", &GradientSampler::m_enableTransform) ->Attribute(AZ::Edit::Attributes::AutoExpand, false) + ->Attribute(AZ::Edit::Attributes::ChangeNotify, &GradientSampler::ChangeNotify) ->DataElement(0, &GradientSampler::m_translate, "Translate", "") ->Attribute(AZ::Edit::Attributes::ReadOnly, &GradientSampler::AreTransformSettingsDisabled) ->Attribute(AZ::Edit::Attributes::ChangeNotify, &GradientSampler::ChangeNotify) @@ -74,8 +75,9 @@ namespace GradientSignal ->Attribute(AZ::Edit::Attributes::ReadOnly, &GradientSampler::AreTransformSettingsDisabled) ->Attribute(AZ::Edit::Attributes::ChangeNotify, &GradientSampler::ChangeNotify) - ->ClassElement(AZ::Edit::ClassElements::Group, "Enable Levels", &GradientSampler::m_enableLevels) + ->GroupElementToggle("Enable Levels", &GradientSampler::m_enableLevels) ->Attribute(AZ::Edit::Attributes::AutoExpand, false) + ->Attribute(AZ::Edit::Attributes::ChangeNotify, &GradientSampler::ChangeNotify) ->DataElement(AZ::Edit::UIHandlers::Slider, &GradientSampler::m_inputMid, "Input Mid", "") ->Attribute(AZ::Edit::Attributes::Min, 0.0f) ->Attribute(AZ::Edit::Attributes::Max, 10.0f) From 63cbb69797791a1490e4ae35b9643cacc4c749e0 Mon Sep 17 00:00:00 2001 From: puvvadar Date: Tue, 13 Jul 2021 15:05:27 -0700 Subject: [PATCH 005/160] Update previous transform to prevent jitter from lerping Signed-off-by: puvvadar --- .../Code/Source/Components/NetworkTransformComponent.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.cpp b/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.cpp index e956245724..7305c1f94e 100644 --- a/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.cpp @@ -91,6 +91,7 @@ namespace Multiplayer blendTransform.SetTranslation(m_previousTransform.GetTranslation().Lerp(m_targetTransform.GetTranslation(), blendFactor)); blendTransform.SetUniformScale(AZ::Lerp(m_previousTransform.GetUniformScale(), m_targetTransform.GetUniformScale(), blendFactor)); GetTransformComponent()->SetWorldTM(blendTransform); + m_previousTransform = blendTransform; } } From fed37e8e6de37fc9f15700f2a2e33f5d000edef7 Mon Sep 17 00:00:00 2001 From: dtamkin1 Date: Tue, 13 Jul 2021 18:02:25 -0500 Subject: [PATCH 006/160] Removed the ChangeNotify event in each attribute Signed-off-by: dtamkin1 --- Gems/GradientSignal/Code/Source/GradientSampler.cpp | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/Gems/GradientSignal/Code/Source/GradientSampler.cpp b/Gems/GradientSignal/Code/Source/GradientSampler.cpp index c89a63790a..bf0260374b 100644 --- a/Gems/GradientSignal/Code/Source/GradientSampler.cpp +++ b/Gems/GradientSignal/Code/Source/GradientSampler.cpp @@ -64,45 +64,35 @@ namespace GradientSignal ->GroupElementToggle("Enable Transform", &GradientSampler::m_enableTransform) ->Attribute(AZ::Edit::Attributes::AutoExpand, false) - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &GradientSampler::ChangeNotify) ->DataElement(0, &GradientSampler::m_translate, "Translate", "") ->Attribute(AZ::Edit::Attributes::ReadOnly, &GradientSampler::AreTransformSettingsDisabled) - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &GradientSampler::ChangeNotify) ->DataElement(0, &GradientSampler::m_scale, "Scale", "") ->Attribute(AZ::Edit::Attributes::ReadOnly, &GradientSampler::AreTransformSettingsDisabled) - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &GradientSampler::ChangeNotify) ->DataElement(0, &GradientSampler::m_rotate, "Rotate", "Rotation in degrees.") ->Attribute(AZ::Edit::Attributes::ReadOnly, &GradientSampler::AreTransformSettingsDisabled) - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &GradientSampler::ChangeNotify) ->GroupElementToggle("Enable Levels", &GradientSampler::m_enableLevels) ->Attribute(AZ::Edit::Attributes::AutoExpand, false) - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &GradientSampler::ChangeNotify) ->DataElement(AZ::Edit::UIHandlers::Slider, &GradientSampler::m_inputMid, "Input Mid", "") ->Attribute(AZ::Edit::Attributes::Min, 0.0f) ->Attribute(AZ::Edit::Attributes::Max, 10.0f) ->Attribute(AZ::Edit::Attributes::ReadOnly, &GradientSampler::AreLevelSettingsDisabled) - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &GradientSampler::ChangeNotify) ->DataElement(AZ::Edit::UIHandlers::Slider, &GradientSampler::m_inputMin, "Input Min", "") ->Attribute(AZ::Edit::Attributes::Min, 0.0f) ->Attribute(AZ::Edit::Attributes::Max, 1.0f) ->Attribute(AZ::Edit::Attributes::ReadOnly, &GradientSampler::AreLevelSettingsDisabled) - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &GradientSampler::ChangeNotify) ->DataElement(AZ::Edit::UIHandlers::Slider, &GradientSampler::m_inputMax, "Input Max", "") ->Attribute(AZ::Edit::Attributes::Min, 0.0f) ->Attribute(AZ::Edit::Attributes::Max, 1.0f) ->Attribute(AZ::Edit::Attributes::ReadOnly, &GradientSampler::AreLevelSettingsDisabled) - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &GradientSampler::ChangeNotify) ->DataElement(AZ::Edit::UIHandlers::Slider, &GradientSampler::m_outputMin, "Output Min", "") ->Attribute(AZ::Edit::Attributes::Min, 0.0f) ->Attribute(AZ::Edit::Attributes::Max, 1.0f) ->Attribute(AZ::Edit::Attributes::ReadOnly, &GradientSampler::AreLevelSettingsDisabled) - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &GradientSampler::ChangeNotify) ->DataElement(AZ::Edit::UIHandlers::Slider, &GradientSampler::m_outputMax, "Output Max", "") ->Attribute(AZ::Edit::Attributes::Min, 0.0f) ->Attribute(AZ::Edit::Attributes::Max, 1.0f) ->Attribute(AZ::Edit::Attributes::ReadOnly, &GradientSampler::AreLevelSettingsDisabled) - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &GradientSampler::ChangeNotify) ->ClassElement(AZ::Edit::ClassElements::Group, "Preview (Inbound)") ->Attribute(AZ::Edit::Attributes::AutoExpand, false) From 539fb8200990a876a6ba921e6122c99e1ac26845 Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Tue, 13 Jul 2021 17:40:49 -0700 Subject: [PATCH 007/160] remove smoke tag from scriptcanvas tests Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com> --- Gems/ScriptCanvasTesting/Code/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/Gems/ScriptCanvasTesting/Code/CMakeLists.txt b/Gems/ScriptCanvasTesting/Code/CMakeLists.txt index 83a3456a1c..9b01064e31 100644 --- a/Gems/ScriptCanvasTesting/Code/CMakeLists.txt +++ b/Gems/ScriptCanvasTesting/Code/CMakeLists.txt @@ -112,7 +112,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) ) ly_add_googletest( NAME Gem::ScriptCanvasTesting.Editor.Tests - TEST_SUITE smoke ) endif() From 41dd7054b7a43c3a2c429fdb616746262716d9ea Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Tue, 13 Jul 2021 17:52:06 -0700 Subject: [PATCH 008/160] Restore BCO destructor delete Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com> --- .../ScriptCanvas/Data/BehaviorContextObject.h | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Data/BehaviorContextObject.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Data/BehaviorContextObject.h index 4980fdd37b..51d61f9934 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Data/BehaviorContextObject.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Data/BehaviorContextObject.h @@ -36,8 +36,7 @@ namespace ScriptCanvas static void Reflect(AZ::ReflectContext* reflection); static BehaviorContextObjectPtr Create(const AZ::BehaviorClass& behaviorClass, const void* value = nullptr); - static BehaviorContextObjectPtr CreateDeepCopy(const AZ::BehaviorClass& behaviorClass, const BehaviorContextObject* value = nullptr); - + template AZ_INLINE static BehaviorContextObjectPtr Create(const t_Value& value, const AZ::BehaviorClass& behaviorClass); @@ -116,6 +115,8 @@ namespace ScriptCanvas BehaviorContextObject& operator=(const BehaviorContextObject&) = delete; + BehaviorContextObject(const BehaviorContextObject&) = delete; + // copy ctor AZ_FORCE_INLINE BehaviorContextObject(const void* source, const AnyTypeInfo& typeInfo, AZ::u32 flags); @@ -133,13 +134,6 @@ namespace ScriptCanvas AZ_FORCE_INLINE void add_ref(); void release(); - - public: - // no copying allowed, this is here to allow compile time compatibility with storage in of BehaviorContextObjectPtr AZStd::any, only - AZ_FORCE_INLINE BehaviorContextObject(const BehaviorContextObject&) - { - AZ_Assert(false, "no copying allowed, this is here to allow storage in of BehaviorContextObjectPtr AZStd::any, only"); - } }; AZ_FORCE_INLINE BehaviorContextObject::BehaviorContextObject(const void* value, const AnyTypeInfo& typeInfo, AZ::u32 flags) From 7dcdd3cb465c09e71f1f5dc5d788a8d8b7849742 Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Tue, 13 Jul 2021 21:20:52 -0700 Subject: [PATCH 009/160] remove the deliberate failure test Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com> --- .../Code/Tests/ScriptCanvas_RuntimeInterpreted.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Gems/ScriptCanvasTesting/Code/Tests/ScriptCanvas_RuntimeInterpreted.cpp b/Gems/ScriptCanvasTesting/Code/Tests/ScriptCanvas_RuntimeInterpreted.cpp index db3d2223d6..fedb1fc4d1 100644 --- a/Gems/ScriptCanvasTesting/Code/Tests/ScriptCanvas_RuntimeInterpreted.cpp +++ b/Gems/ScriptCanvasTesting/Code/Tests/ScriptCanvas_RuntimeInterpreted.cpp @@ -83,11 +83,6 @@ public: } }; -TEST_F(ScriptCanvasTestFixture, ProveError) -{ - EXPECT_TRUE(false); -} - TEST_F(ScriptCanvasTestFixture, ParseErrorOnKnownNull) { ExpectParseError("LY_SC_UnitTest_ParseErrorOnKnownNull"); From c6f03cbb098a474a17a78cee4205f1248e7c7d9b Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Wed, 14 Jul 2021 12:50:15 -0700 Subject: [PATCH 010/160] Removed superflous translation asset registration Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com> --- Gems/GraphCanvas/Code/Source/GraphCanvas.cpp | 29 -------------------- Gems/GraphCanvas/Code/Source/GraphCanvas.h | 1 - 2 files changed, 30 deletions(-) diff --git a/Gems/GraphCanvas/Code/Source/GraphCanvas.cpp b/Gems/GraphCanvas/Code/Source/GraphCanvas.cpp index 011548ce5a..be44908cb8 100644 --- a/Gems/GraphCanvas/Code/Source/GraphCanvas.cpp +++ b/Gems/GraphCanvas/Code/Source/GraphCanvas.cpp @@ -190,7 +190,6 @@ namespace GraphCanvas void GraphCanvasSystemComponent::Activate() { - RegisterAssetHandler(); RegisterTranslationBuilder(); AzFramework::AssetCatalogEventBus::Handler::BusConnect(); @@ -385,34 +384,6 @@ namespace GraphCanvas AZ::Data::AssetCatalogRequestBus::Broadcast(&AZ::Data::AssetCatalogRequestBus::Events::EnumerateAssets, nullptr, collectAssetsCb, postEnumerateCb); } - void GraphCanvasSystemComponent::RegisterAssetHandler() - { - AZ::Data::AssetType assetType(azrtti_typeid()); - if (AZ::Data::AssetManager::Instance().GetHandler(assetType)) - { - return; // Asset Type already handled - } - - auto* catalogBus = AZ::Data::AssetCatalogRequestBus::FindFirstHandler(); - if (catalogBus) - { - // Register asset types the asset DB should query our catalog for. - catalogBus->AddAssetType(assetType); - - // Build the catalog (scan). - catalogBus->AddExtension(".names"); - } - - m_assetHandler = AZStd::make_unique(); - AZ::Data::AssetManager::Instance().RegisterHandler(m_assetHandler.get(), assetType); - - // Use AssetCatalog service to register ScriptEvent asset type and extension - AZ::Data::AssetCatalogRequestBus::Broadcast(&AZ::Data::AssetCatalogRequests::AddAssetType, assetType); - AZ::Data::AssetCatalogRequestBus::Broadcast(&AZ::Data::AssetCatalogRequests::EnableCatalogForAsset, assetType); - AZ::Data::AssetCatalogRequestBus::Broadcast(&AZ::Data::AssetCatalogRequests::AddExtension, TranslationAsset::GetFileFilter()); - - } - void GraphCanvasSystemComponent::UnregisterAssetHandler() { if (m_assetHandler) diff --git a/Gems/GraphCanvas/Code/Source/GraphCanvas.h b/Gems/GraphCanvas/Code/Source/GraphCanvas.h index ddb29b18c0..2e5b200a1b 100644 --- a/Gems/GraphCanvas/Code/Source/GraphCanvas.h +++ b/Gems/GraphCanvas/Code/Source/GraphCanvas.h @@ -82,7 +82,6 @@ namespace GraphCanvas void RegisterTranslationBuilder(); - void RegisterAssetHandler(); void UnregisterAssetHandler(); TranslationAssetWorker m_translationAssetWorker; AZStd::vector m_translationAssets; From e2c147762900cec9c59302f950d4088e4eee8770 Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Thu, 15 Jul 2021 09:46:51 -0700 Subject: [PATCH 011/160] fix for dependency job key on ScriptEvents from SC builder Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com> --- .../AzCore/Debug/StackTracer_Windows.cpp | 2 +- .../Builder/ScriptCanvasBuilderWorker.cpp | 29 ++++++++++++++----- .../ScriptCanvasBuilderWorkerUtility.cpp | 2 +- .../ScriptCanvas/Core/SubgraphInterface.cpp | 6 ---- .../ScriptCanvas/Core/SubgraphInterface.h | 2 -- .../ScriptCanvas/Grammar/Primitives.cpp | 4 +-- .../Grammar/PrimitivesDeclarations.h | 2 +- .../Builder/ScriptEventsBuilderWorker.cpp | 2 +- .../Include/ScriptEvents/ScriptEventsAsset.h | 2 ++ 9 files changed, 29 insertions(+), 22 deletions(-) diff --git a/Code/Framework/AzCore/Platform/Windows/AzCore/Debug/StackTracer_Windows.cpp b/Code/Framework/AzCore/Platform/Windows/AzCore/Debug/StackTracer_Windows.cpp index a40dd2daac..dcc55cfcf6 100644 --- a/Code/Framework/AzCore/Platform/Windows/AzCore/Debug/StackTracer_Windows.cpp +++ b/Code/Framework/AzCore/Platform/Windows/AzCore/Debug/StackTracer_Windows.cpp @@ -38,7 +38,7 @@ namespace AZ { struct SymbolStorageDynamicallyLoadedModules { size_t m_size; - DynamicallyLoadedModuleInfo m_modules[1028]; + DynamicallyLoadedModuleInfo m_modules[1024]; SymbolStorageDynamicallyLoadedModules() : m_size(0) diff --git a/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilderWorker.cpp b/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilderWorker.cpp index b9d1dd5a7c..3377cea0e8 100644 --- a/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilderWorker.cpp +++ b/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilderWorker.cpp @@ -82,23 +82,35 @@ namespace ScriptCanvasBuilder m_processEditorAssetDependencies.clear(); - auto assetFilter = [this, &response](const AZ::Data::AssetFilterInfo& filterInfo) + AZStd::unordered_multimap jobDependenciesByKey; + + auto assetFilter = [this, &jobDependenciesByKey](const AZ::Data::AssetFilterInfo& filterInfo) { // force load these before processing if (filterInfo.m_assetType == azrtti_typeid() - || filterInfo.m_assetType == azrtti_typeid()) + || filterInfo.m_assetType == azrtti_typeid()) { this->m_processEditorAssetDependencies.push_back(filterInfo); } // these trigger re-processing - if (filterInfo.m_assetType == azrtti_typeid() - || filterInfo.m_assetType == azrtti_typeid() - || filterInfo.m_assetType == azrtti_typeid()) + if (filterInfo.m_assetType == azrtti_typeid()) + { + AZ_Error("ScriptCanvas", false, "ScriptAsset Reference in a graph detected"); + } + + if (filterInfo.m_assetType == azrtti_typeid()) + { + AssetBuilderSDK::SourceFileDependency dependency; + dependency.m_sourceFileDependencyUUID = filterInfo.m_assetId.m_guid; + jobDependenciesByKey.insert({ ScriptEvents::k_builderJobKey, dependency }); + } + + if (filterInfo.m_assetType == azrtti_typeid()) { AssetBuilderSDK::SourceFileDependency dependency; dependency.m_sourceFileDependencyUUID = filterInfo.m_assetId.m_guid; - response.m_sourceFileDependencyList.push_back(dependency); + jobDependenciesByKey.insert({ s_scriptCanvasProcessJobKey, dependency }); } // Asset filter always returns false to prevent parsing dependencies, but makes note of the script canvas dependencies @@ -163,9 +175,10 @@ namespace ScriptCanvasBuilder jobDescriptor.m_additionalFingerprintInfo = AZStd::string(GetFingerprintString()).append("|").append(AZStd::to_string(static_cast(fingerprint))); // Graph process job needs to wait until its dependency asset job finished - for (const auto& processingDependency : response.m_sourceFileDependencyList) + for (const auto& processingDependency : jobDependenciesByKey) { - jobDescriptor.m_jobDependencyList.emplace_back(s_scriptCanvasProcessJobKey, info.m_identifier.c_str(), AssetBuilderSDK::JobDependencyType::Order, processingDependency); + response.m_sourceFileDependencyList.push_back(processingDependency.second); + jobDescriptor.m_jobDependencyList.emplace_back(processingDependency.first, info.m_identifier.c_str(), AssetBuilderSDK::JobDependencyType::Order, processingDependency.second); } response.m_createJobOutputs.push_back(jobDescriptor); diff --git a/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilderWorkerUtility.cpp b/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilderWorkerUtility.cpp index 7f6269a698..375c773e7d 100644 --- a/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilderWorkerUtility.cpp +++ b/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilderWorkerUtility.cpp @@ -97,7 +97,7 @@ namespace ScriptCanvasBuilder bool pathFound = false; AZStd::string relativePath; AzToolsFramework::AssetSystemRequestBus::BroadcastResult - (pathFound + ( pathFound , &AzToolsFramework::AssetSystem::AssetSystemRequest::GetRelativeProductPathFromFullSourceOrProductPath , fullPath.c_str(), relativePath); diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/SubgraphInterface.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/SubgraphInterface.cpp index a6959ae209..3b7ec9c77f 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/SubgraphInterface.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/SubgraphInterface.cpp @@ -802,12 +802,6 @@ namespace ScriptCanvas m_namespacePath = namespacePath; } - void SubgraphInterface::TakeNamespacePath(NamespacePath&& namespacePath) - { - m_namespacePath = AZStd::move(namespacePath); - } - - AZStd::string SubgraphInterface::ToExecutionString() const { AZStd::string result; diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/SubgraphInterface.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/SubgraphInterface.h index 19ff2e1d65..6dac3cf7a4 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/SubgraphInterface.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/SubgraphInterface.h @@ -235,8 +235,6 @@ namespace ScriptCanvas void SetNamespacePath(const NamespacePath& namespacePath); - void TakeNamespacePath(NamespacePath&& namespacePath); - AZStd::string ToExecutionString() const; private: diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/Primitives.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/Primitives.cpp index aa11d01fdf..dca4f41933 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/Primitives.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/Primitives.cpp @@ -234,7 +234,7 @@ namespace ScriptCanvas const VariableData Source::k_emptyVardata{}; Source::Source - (const Graph& graph + ( const Graph& graph , const AZ::Data::AssetId& id , const GraphData& graphData , const VariableData& variableData @@ -276,7 +276,7 @@ namespace ScriptCanvas AzFramework::StringFunc::Path::StripExtension(namespacePath); return AZ::Success(Source - (*request.graph + (*request.graph , request.scriptAssetId , *graphData , *sourceVariableData diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/PrimitivesDeclarations.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/PrimitivesDeclarations.h index 12f4199bc4..0c245de2a5 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/PrimitivesDeclarations.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/PrimitivesDeclarations.h @@ -289,7 +289,7 @@ namespace ScriptCanvas Source() = default; Source - (const Graph& graph + ( const Graph& graph , const AZ::Data::AssetId& id , const GraphData& graphData , const VariableData& variableData diff --git a/Gems/ScriptEvents/Code/Builder/ScriptEventsBuilderWorker.cpp b/Gems/ScriptEvents/Code/Builder/ScriptEventsBuilderWorker.cpp index 2357fb38a5..8465b28936 100644 --- a/Gems/ScriptEvents/Code/Builder/ScriptEventsBuilderWorker.cpp +++ b/Gems/ScriptEvents/Code/Builder/ScriptEventsBuilderWorker.cpp @@ -120,7 +120,7 @@ namespace ScriptEventsBuilder AssetBuilderSDK::JobDescriptor jobDescriptor; jobDescriptor.m_priority = 2; jobDescriptor.m_critical = true; - jobDescriptor.m_jobKey = "Script Events"; + jobDescriptor.m_jobKey = ScriptEvents::k_builderJobKey; jobDescriptor.SetPlatformIdentifier(info.m_identifier.data()); jobDescriptor.m_additionalFingerprintInfo = GetFingerprintString(); diff --git a/Gems/ScriptEvents/Code/Include/ScriptEvents/ScriptEventsAsset.h b/Gems/ScriptEvents/Code/Include/ScriptEvents/ScriptEventsAsset.h index cfa8253923..8178f1c9e0 100644 --- a/Gems/ScriptEvents/Code/Include/ScriptEvents/ScriptEventsAsset.h +++ b/Gems/ScriptEvents/Code/Include/ScriptEvents/ScriptEventsAsset.h @@ -21,6 +21,8 @@ namespace ScriptEvents { + constexpr const char* k_builderJobKey = "Script Events"; + class ScriptEventsAsset : public AZ::Data::AssetData { From ab6a98db44013f6d4182d051dc009570f24f9231 Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Thu, 15 Jul 2021 09:52:40 -0700 Subject: [PATCH 012/160] restoring smoke lable to SC unit tests pending Linux filename fix Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com> --- Gems/ScriptCanvasTesting/Code/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Gems/ScriptCanvasTesting/Code/CMakeLists.txt b/Gems/ScriptCanvasTesting/Code/CMakeLists.txt index 9b01064e31..83a3456a1c 100644 --- a/Gems/ScriptCanvasTesting/Code/CMakeLists.txt +++ b/Gems/ScriptCanvasTesting/Code/CMakeLists.txt @@ -112,6 +112,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) ) ly_add_googletest( NAME Gem::ScriptCanvasTesting.Editor.Tests + TEST_SUITE smoke ) endif() From 7950c2b54906b2976b44c097403eb8607042f3a6 Mon Sep 17 00:00:00 2001 From: puvvadar Date: Thu, 15 Jul 2021 13:45:49 -0700 Subject: [PATCH 013/160] Add target host frame ID tracking to network transform Signed-off-by: puvvadar --- .../Components/NetworkTransformComponent.h | 4 +++ .../Components/NetworkTransformComponent.cpp | 27 ++++++++++++++++--- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkTransformComponent.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkTransformComponent.h index 5575de9b0d..c37c28db62 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkTransformComponent.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkTransformComponent.h @@ -35,6 +35,8 @@ namespace Multiplayer void OnScaleChangedEvent(float scale); void OnResetCountChangedEvent(); + void UpdateTargetHostFrameId(); + AZ::Transform m_previousTransform = AZ::Transform::CreateIdentity(); AZ::Transform m_targetTransform = AZ::Transform::CreateIdentity(); @@ -44,6 +46,8 @@ namespace Multiplayer AZ::Event::Handler m_resetCountEventHandler; EntityPreRenderEvent::Handler m_entityPreRenderEventHandler; + + Multiplayer::HostFrameId m_targetHostFrameId = HostFrameId(0); }; class NetworkTransformComponentController diff --git a/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.cpp b/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.cpp index 7305c1f94e..54b24ccf10 100644 --- a/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.cpp @@ -60,18 +60,21 @@ namespace Multiplayer { m_previousTransform.SetRotation(m_targetTransform.GetRotation()); m_targetTransform.SetRotation(rotation); + UpdateTargetHostFrameId(); } void NetworkTransformComponent::OnTranslationChangedEvent(const AZ::Vector3& translation) { m_previousTransform.SetTranslation(m_targetTransform.GetTranslation()); m_targetTransform.SetTranslation(translation); + UpdateTargetHostFrameId(); } void NetworkTransformComponent::OnScaleChangedEvent(float scale) { m_previousTransform.SetUniformScale(m_targetTransform.GetUniformScale()); m_targetTransform.SetUniformScale(scale); + UpdateTargetHostFrameId(); } void NetworkTransformComponent::OnResetCountChangedEvent() @@ -82,16 +85,32 @@ namespace Multiplayer m_previousTransform = m_targetTransform; } + void NetworkTransformComponent::UpdateTargetHostFrameId() + { + HostFrameId currentHostFrameId = Multiplayer::GetNetworkTime()->GetHostFrameId(); + if (currentHostFrameId > m_targetHostFrameId) + { + m_targetHostFrameId = currentHostFrameId; + } + } + void NetworkTransformComponent::OnPreRender([[maybe_unused]] float deltaTime, float blendFactor) { if (!HasController()) { AZ::Transform blendTransform; - blendTransform.SetRotation(m_previousTransform.GetRotation().Slerp(m_targetTransform.GetRotation(), blendFactor)); - blendTransform.SetTranslation(m_previousTransform.GetTranslation().Lerp(m_targetTransform.GetTranslation(), blendFactor)); - blendTransform.SetUniformScale(AZ::Lerp(m_previousTransform.GetUniformScale(), m_targetTransform.GetUniformScale(), blendFactor)); + if (Multiplayer::GetNetworkTime() && Multiplayer::GetNetworkTime()->GetHostFrameId() > m_targetHostFrameId) + { + m_previousTransform = m_targetTransform; + blendTransform = m_targetTransform; + } + else + { + blendTransform.SetRotation(m_previousTransform.GetRotation().Slerp(m_targetTransform.GetRotation(), blendFactor)); + blendTransform.SetTranslation(m_previousTransform.GetTranslation().Lerp(m_targetTransform.GetTranslation(), blendFactor)); + blendTransform.SetUniformScale(AZ::Lerp(m_previousTransform.GetUniformScale(), m_targetTransform.GetUniformScale(), blendFactor)); + } GetTransformComponent()->SetWorldTM(blendTransform); - m_previousTransform = blendTransform; } } From e28ff0beea17a3a63e3804ad11c8e16c6c2a4edb Mon Sep 17 00:00:00 2001 From: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> Date: Fri, 16 Jul 2021 03:52:11 -0500 Subject: [PATCH 014/160] Adding rapidjson.natvis file to the AzCore project to Visualizers to VS By adding the natvis to a vcxproj Visual Studio automatically loads it when using the source engine Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> --- .../AzCore/Natvis/rapidjson.natvis | 38 +++++++++++++++++++ .../Windows/platform_windows_files.cmake | 1 + 2 files changed, 39 insertions(+) create mode 100644 Code/Framework/AzCore/Platform/Common/VisualStudio/AzCore/Natvis/rapidjson.natvis diff --git a/Code/Framework/AzCore/Platform/Common/VisualStudio/AzCore/Natvis/rapidjson.natvis b/Code/Framework/AzCore/Platform/Common/VisualStudio/AzCore/Natvis/rapidjson.natvis new file mode 100644 index 0000000000..5167714f20 --- /dev/null +++ b/Code/Framework/AzCore/Platform/Common/VisualStudio/AzCore/Natvis/rapidjson.natvis @@ -0,0 +1,38 @@ + + + + + null + true + false + {data_.ss.str} + {(const char*)((size_t)data_.s.str & 0x0000FFFFFFFFFFFF)} + {data_.n.i.i} + {data_.n.u.u} + {data_.n.i64} + {data_.n.u64} + {data_.n.d} + Object members={data_.o.size} + Array members={data_.a.size} + + data_.o.size + data_.o.capacity + + data_.o.size + + (rapidjson_ly::GenericMember<$T1,$T2>*)(((size_t)data_.o.members) & 0x0000FFFFFFFFFFFF) + + + data_.a.size + data_.a.capacity + + data_.a.size + + (rapidjson_ly::GenericValue<$T1,$T2>*)(((size_t)data_.a.elements) & 0x0000FFFFFFFFFFFF) + + + + + + + diff --git a/Code/Framework/AzCore/Platform/Windows/platform_windows_files.cmake b/Code/Framework/AzCore/Platform/Windows/platform_windows_files.cmake index 520c53f74c..97ab3c86d6 100644 --- a/Code/Framework/AzCore/Platform/Windows/platform_windows_files.cmake +++ b/Code/Framework/AzCore/Platform/Windows/platform_windows_files.cmake @@ -29,6 +29,7 @@ set(FILES ../Common/VisualStudio/AzCore/Natvis/azcore.natvis ../Common/VisualStudio/AzCore/Natvis/azcore.natstepfilter ../Common/VisualStudio/AzCore/Natvis/azcore.natjmc + ../Common/VisualStudio/AzCore/Natvis/rapidjson.natvis AzCore/Debug/StackTracer_Windows.cpp ../Common/WinAPI/AzCore/Debug/Trace_WinAPI.cpp ../Common/WinAPI/AzCore/IO/Streamer/StreamerContext_WinAPI.cpp From ebe326f6e9cbbd2cf49e6aa791494dcc86947a8e Mon Sep 17 00:00:00 2001 From: puvvadar Date: Tue, 20 Jul 2021 14:12:06 -0700 Subject: [PATCH 015/160] Add server side accounting for blend factor Signed-off-by: puvvadar --- .../Code/Include/Multiplayer/IMultiplayer.h | 2 ++ .../Multiplayer/NetworkInput/NetworkInput.h | 4 ++++ .../LocalPredictionPlayerInputComponent.cpp | 6 +++++- .../Code/Source/MultiplayerSystemComponent.cpp | 5 +++++ .../Code/Source/MultiplayerSystemComponent.h | 1 + .../Code/Source/NetworkInput/NetworkInput.cpp | 14 +++++++++++++- 6 files changed, 30 insertions(+), 2 deletions(-) diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/IMultiplayer.h b/Gems/Multiplayer/Code/Include/Multiplayer/IMultiplayer.h index 182173c464..35af0034e5 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/IMultiplayer.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/IMultiplayer.h @@ -121,6 +121,8 @@ namespace Multiplayer //! @return the current server time in milliseconds virtual AZ::TimeMs GetCurrentHostTimeMs() const = 0; + virtual float GetCurrentBlendFactor() const = 0; + //! Returns the network time instance bound to this multiplayer instance. //! @return pointer to the network time instance bound to this multiplayer instance virtual INetworkTime* GetNetworkTime() = 0; diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/NetworkInput/NetworkInput.h b/Gems/Multiplayer/Code/Include/Multiplayer/NetworkInput/NetworkInput.h index 5d57ea6343..874ccad789 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/NetworkInput/NetworkInput.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/NetworkInput/NetworkInput.h @@ -44,6 +44,9 @@ namespace Multiplayer AZ::TimeMs GetHostTimeMs() const; AZ::TimeMs& ModifyHostTimeMs(); + void SetHostBlendFactor(float hostBlendFactor); + float GetHostBlendFactor() const; + void AttachNetBindComponent(NetBindComponent* netBindComponent); bool Serialize(AzNetworking::ISerializer& serializer); @@ -72,6 +75,7 @@ namespace Multiplayer ClientInputId m_inputId = ClientInputId{ 0 }; HostFrameId m_hostFrameId = InvalidHostFrameId; AZ::TimeMs m_hostTimeMs = AZ::TimeMs{ 0 }; + float m_hostBlendFactor = 0.f; ConstNetworkEntityHandle m_owner; bool m_wasAttached = false; }; diff --git a/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp b/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp index 0b4fa99111..da299401d8 100644 --- a/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp @@ -154,9 +154,12 @@ namespace Multiplayer // Discard move input events, client may be speed hacking if (m_clientBankedTime < sv_MaxBankTimeWindowSec) { + // Client blends from previous frame to target so here we subtract blend factor to get to that state + const float adjustedBlendFactor = std::pow(0.2f, input.GetHostBlendFactor()); + const AZ::TimeMs blendMs = AZ::TimeMs(static_cast(static_cast(cl_InputRateMs)) * adjustedBlendFactor); m_clientBankedTime = AZStd::min(m_clientBankedTime + clientInputRateSec, (double)sv_MaxBankTimeWindowSec); // clamp to boundary { - ScopedAlterTime scopedTime(input.GetHostFrameId(), input.GetHostTimeMs(), invokingConnection->GetConnectionId()); + ScopedAlterTime scopedTime(input.GetHostFrameId(), input.GetHostTimeMs() - blendMs, invokingConnection->GetConnectionId()); GetNetBindComponent()->ProcessInput(input, static_cast(clientInputRateSec)); } @@ -498,6 +501,7 @@ namespace Multiplayer input.SetClientInputId(m_clientInputId); input.SetHostFrameId(networkTime->GetHostFrameId()); input.SetHostTimeMs(multiplayer->GetCurrentHostTimeMs()); + input.SetHostBlendFactor(multiplayer->GetCurrentBlendFactor()); // Allow components to form the input for this frame GetNetBindComponent()->CreateInput(input, inputRate); diff --git a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp index 0100cfe3d2..16acf45872 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp +++ b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp @@ -802,6 +802,11 @@ namespace Multiplayer } } + float MultiplayerSystemComponent::GetCurrentBlendFactor() const + { + return m_renderBlendFactor; + } + INetworkTime* MultiplayerSystemComponent::GetNetworkTime() { return &m_networkTime; diff --git a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h index 7977a39443..5aaa52a7bd 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h +++ b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h @@ -112,6 +112,7 @@ namespace Multiplayer void Terminate(AzNetworking::DisconnectReason reason) override; void SendReadyForEntityUpdates(bool readyForEntityUpdates) override; AZ::TimeMs GetCurrentHostTimeMs() const override; + float GetCurrentBlendFactor() const override; INetworkTime* GetNetworkTime() override; INetworkEntityManager* GetNetworkEntityManager() override; void SetFilterEntityManager(IFilterEntityManager* entityFilter) override; diff --git a/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInput.cpp b/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInput.cpp index 75889d9f83..33b5a535e0 100644 --- a/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInput.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInput.cpp @@ -75,6 +75,16 @@ namespace Multiplayer return m_hostTimeMs; } + void NetworkInput::SetHostBlendFactor(float hostBlendFactor) + { + m_hostBlendFactor = hostBlendFactor; + } + + float NetworkInput::GetHostBlendFactor() const + { + return m_hostBlendFactor; + } + void NetworkInput::AttachNetBindComponent(NetBindComponent* netBindComponent) { m_wasAttached = true; @@ -90,7 +100,8 @@ namespace Multiplayer { if (!serializer.Serialize(m_inputId, "InputId") || !serializer.Serialize(m_hostTimeMs, "HostTimeMs") - || !serializer.Serialize(m_hostFrameId, "HostFrameId")) + || !serializer.Serialize(m_hostFrameId, "HostFrameId") + || !serializer.Serialize(m_hostBlendFactor, "HostBlendFactor")) { return false; } @@ -163,6 +174,7 @@ namespace Multiplayer m_inputId = rhs.m_inputId; m_hostFrameId = rhs.m_hostFrameId; m_hostTimeMs = rhs.m_hostTimeMs; + m_hostBlendFactor = rhs.m_hostBlendFactor; m_componentInputs.resize(rhs.m_componentInputs.size()); for (int32_t i = 0; i < rhs.m_componentInputs.size(); ++i) { From 69d5f64bb7c209e8bcd3b680ec6f1dc371d3294b Mon Sep 17 00:00:00 2001 From: puvvadar Date: Tue, 20 Jul 2021 14:21:00 -0700 Subject: [PATCH 016/160] Add function documentation for GetCurrentBlendFactor Signed-off-by: puvvadar --- Gems/Multiplayer/Code/Include/Multiplayer/IMultiplayer.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/IMultiplayer.h b/Gems/Multiplayer/Code/Include/Multiplayer/IMultiplayer.h index 35af0034e5..23885e6c64 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/IMultiplayer.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/IMultiplayer.h @@ -121,6 +121,9 @@ namespace Multiplayer //! @return the current server time in milliseconds virtual AZ::TimeMs GetCurrentHostTimeMs() const = 0; + //! Returns the current blend factor for client side interpolation + //! This value is only relevant on the client and is used to smooth between host frames + //! @return the current blend factor virtual float GetCurrentBlendFactor() const = 0; //! Returns the network time instance bound to this multiplayer instance. From 002a4a4a2120687773e0cb8a6986109818dbf58a Mon Sep 17 00:00:00 2001 From: Dayo Lawal Date: Wed, 21 Jul 2021 14:50:23 -0500 Subject: [PATCH 017/160] AtomToolsApplication working with MatEditor Signed-off-by: Dayo Lawal --- .../Application/AtomToolsApplication.h | 92 ++++ .../Application/AtomToolsApplication.cpp | 428 ++++++++++++++++++ .../Code/atomtoolsframework_files.cmake | 2 + .../Code/Source/MaterialEditorApplication.cpp | 203 +-------- .../Code/Source/MaterialEditorApplication.h | 53 +-- .../ShaderManagementConsoleApplication.cpp | 170 +------ .../ShaderManagementConsoleApplication.h | 21 +- 7 files changed, 535 insertions(+), 434 deletions(-) create mode 100644 Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h create mode 100644 Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h new file mode 100644 index 0000000000..dc34ad9a0a --- /dev/null +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h @@ -0,0 +1,92 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace AtomToolsFramework +{ + class AtomToolsApplication + : public AzFramework::Application + , public AzQtComponents::AzQtApplication + , protected AzToolsFramework::AssetDatabase::AssetDatabaseRequestsBus::Handler + , protected AzFramework::AssetSystemStatusBus::Handler + , protected AzToolsFramework::EditorPythonConsoleNotificationBus::Handler + , protected AZ::Debug::TraceMessageBus::Handler + , protected AZ::UserSettingsOwnerRequestBus::Handler + { + public: + AZ_TYPE_INFO(AtomTools::AtomToolsApplication, "{30F90CA5-1253-49B5-8143-19CEE37E22BB}"); + + using Base = AzFramework::Application; + + AtomToolsApplication(int* argc, char*** argv); + + ////////////////////////////////////////////////////////////////////////// + // AzFramework::Application + void CreateReflectionManager() override; + void Reflect(AZ::ReflectContext* context) override; + void RegisterCoreComponents() override; + AZ::ComponentTypeList GetRequiredSystemComponents() const override; + void CreateStaticModules(AZStd::vector& outModules) override; + const char* GetCurrentConfigurationName() const override; + void StartCommon(AZ::Entity* systemEntity) override; + void Tick(float deltaOverride = -1.f) override; + void Stop() override; + + protected: + ////////////////////////////////////////////////////////////////////////// + // AssetDatabaseRequestsBus::Handler overrides... + bool GetAssetDatabaseLocation(AZStd::string& result) override; + ////////////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////////////////// + // AzFramework::Application overrides... + void Destroy() override; + ////////////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////////////////// + // AZ::ComponentApplication overrides... + void QueryApplicationType(AZ::ApplicationTypeQuery& appType) const override; + ////////////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////////////////// + // AZ::UserSettingsOwnerRequestBus::Handler overrides... + void SaveSettings() override; + ////////////////////////////////////////////////////////////////////////// + + virtual void LoadSettings(); + virtual void UnloadSettings(); + virtual void CompileCriticalAssets(); + virtual void ProcessCommandLine(const AZ::CommandLine& commandLine); + virtual bool LaunchDiscoveryService(); + virtual void StartInternal(); + + static void PyIdleWaitFrames(uint32_t frames); + + AzToolsFramework::TraceLogger m_traceLogger; + + //! Local user settings are used to store material browser tree expansion state + AZ::UserSettingsProvider m_localUserSettings; + + //! Are local settings loaded + bool m_activatedLocalUserSettings = false; + + QTimer m_timer; + + AtomToolsFramework::LocalSocket m_socket; + AtomToolsFramework::LocalServer m_server; + }; +} // namespace AtomToolsFramework diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp new file mode 100644 index 0000000000..35a151e95b --- /dev/null +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp @@ -0,0 +1,428 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of + * this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include + +#include + +AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT +#include +#include +AZ_POP_DISABLE_WARNING + +namespace AtomToolsFramework +{ + //! This function returns the build system target name of "AtomTools +// AZStd::string_view GetBuildTargetName() +// { +//#if !defined(LY_CMAKE_TARGET) +//#error "LY_CMAKE_TARGET must be defined in order to add this source file to a CMake executable target" +//#endif +// return AZStd::string_view{ LY_CMAKE_TARGET }; +// } + + const char* AtomToolsApplication::GetCurrentConfigurationName() const + { +#if defined(_RELEASE) + return "ReleaseAtomTools"; +#elif defined(_DEBUG) + return "DebugAtomTools"; +#else + return "ProfileAtomTools"; +#endif + } + + + AtomToolsApplication::AtomToolsApplication(int* argc, char*** argv) + : Application(argc, argv) + , AzQtApplication(*argc, *argv) + { + } + + void AtomToolsApplication::CreateReflectionManager() + { + Application::CreateReflectionManager(); + GetSerializeContext()->CreateEditContext(); + } + + void AtomToolsApplication::Reflect(AZ::ReflectContext* context) + { + Application::Reflect(context); + + AzToolsFramework::AssetBrowser::AssetBrowserEntry::Reflect(context); + AzToolsFramework::AssetBrowser::RootAssetBrowserEntry::Reflect(context); + AzToolsFramework::AssetBrowser::FolderAssetBrowserEntry::Reflect(context); + AzToolsFramework::AssetBrowser::SourceAssetBrowserEntry::Reflect(context); + AzToolsFramework::AssetBrowser::ProductAssetBrowserEntry::Reflect(context); + + AzToolsFramework::QTreeViewWithStateSaving::Reflect(context); + AzToolsFramework::QWidgetSavedState::Reflect(context); + + if (auto behaviorContext = azrtti_cast(context)) + { + // this will put these methods into the 'azlmbr.AtomTools.general' module + auto addGeneral = [](AZ::BehaviorContext::GlobalMethodBuilder methodBuilder) + { + methodBuilder->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation) + ->Attribute(AZ::Script::Attributes::Category, "Editor") + ->Attribute(AZ::Script::Attributes::Module, "AtomTools.general"); + }; + // The reflection here is based on patterns in CryEditPythonHandler::Reflect + addGeneral(behaviorContext->Method( + "idle_wait_frames", &AtomToolsApplication::PyIdleWaitFrames, nullptr, + "Waits idling for a frames. Primarily used for auto-testing.")); + } + } + + void AtomToolsApplication::RegisterCoreComponents() + { + Application::RegisterCoreComponents(); + RegisterComponentDescriptor(AzToolsFramework::AssetBrowser::AssetBrowserComponent::CreateDescriptor()); + RegisterComponentDescriptor(AzToolsFramework::Thumbnailer::ThumbnailerComponent::CreateDescriptor()); + RegisterComponentDescriptor(AzToolsFramework::Components::PropertyManagerComponent::CreateDescriptor()); + RegisterComponentDescriptor(AzToolsFramework::AssetSystem::AssetSystemComponent::CreateDescriptor()); + RegisterComponentDescriptor(AzToolsFramework::PerforceComponent::CreateDescriptor()); + } + + AZ::ComponentTypeList AtomToolsApplication::GetRequiredSystemComponents() const + { + AZ::ComponentTypeList components = Application::GetRequiredSystemComponents(); + + components.insert( + components.end(), + { + azrtti_typeid(), + azrtti_typeid(), + azrtti_typeid(), + azrtti_typeid(), + }); + + return components; + } + + void AtomToolsApplication::CreateStaticModules(AZStd::vector& outModules) + { + Application::CreateStaticModules(outModules); + outModules.push_back(aznew AzToolsFramework::AzToolsFrameworkModule); + } + + void AtomToolsApplication::StartCommon(AZ::Entity* systemEntity) + { + AzFramework::AssetSystemStatusBus::Handler::BusConnect(); + AzToolsFramework::EditorPythonConsoleNotificationBus::Handler::BusConnect(); + + AzFramework::Application::StartCommon(systemEntity); + + StartInternal(); + + m_timer.start(); + } + + void AtomToolsApplication::Destroy() + { + AzToolsFramework::EditorPythonConsoleNotificationBus::Handler::BusDisconnect(); + AzToolsFramework::AssetDatabase::AssetDatabaseRequestsBus::Handler::BusDisconnect(); + AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); + + m_logFile = {}; + m_startupLogSink = {}; + + AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::StartDisconnectingAssetProcessor); + Application::Destroy(); + } + + void AtomToolsApplication::CompileCriticalAssets() + { + AZ_TracePrintf("AtomTools", "Compiling critical assets.\n"); + + // List of common asset filters for things that need to be compiled to run the material editor + // Some of these things will not be necessary once we have proper support for queued asset loading and reloading + const AZStd::string assetFiltersArray[] = { + "passes/", + "config/", + }; + + QStringList failedAssets; + + // Forced asset processor to synchronously process all critical assets + // Note: with AssetManager's current implementation, a compiled asset won't be added in asset registry until next system tick. + // So the asset id won't be found right after CompileAssetSync call. + for (const AZStd::string& assetFilters : assetFiltersArray) + { + AZ_TracePrintf("AtomTools", "Compiling critical asset matching: %s.\n", assetFilters.c_str()); + + // Wait for the asset be compiled + AzFramework::AssetSystem::AssetStatus status = AzFramework::AssetSystem::AssetStatus_Unknown; + AzFramework::AssetSystemRequestBus::BroadcastResult( + status, &AzFramework::AssetSystemRequestBus::Events::CompileAssetSync, assetFilters); + if (status != AzFramework::AssetSystem::AssetStatus_Compiled) + { + failedAssets.append(assetFilters.c_str()); + } + } + + if (!failedAssets.empty()) + { + QMessageBox::critical( + activeWindow(), QString("Failed to compile critical assets"), + QString("Failed to compile the following critical assets:\n%1\n%2") + .arg(failedAssets.join(",\n")) + .arg("Make sure this is an Atom project.")); + ExitMainLoop(); + } + } + + void AtomToolsApplication::SaveSettings() + { + if (m_activatedLocalUserSettings) + { + AZ::SerializeContext* context = nullptr; + AZ::ComponentApplicationBus::BroadcastResult(context, &AZ::ComponentApplicationRequests::GetSerializeContext); + AZ_Assert(context, "No serialize context"); + + char resolvedPath[AZ_MAX_PATH_LEN] = ""; + AZ::IO::FileIOBase::GetInstance()->ResolvePath( + "@user@/MaterialEditorUserSettings.xml", resolvedPath, AZ_ARRAY_SIZE(resolvedPath)); + m_localUserSettings.Save(resolvedPath, context); + } + } + + + void AtomToolsApplication::LoadSettings() + { + AZ::SerializeContext* context = nullptr; + AZ::ComponentApplicationBus::BroadcastResult(context, &AZ::ComponentApplicationRequests::GetSerializeContext); + AZ_Assert(context, "No serialize context"); + + char resolvedPath[AZ_MAX_PATH_LEN] = ""; + AZ::IO::FileIOBase::GetInstance()->ResolvePath("@user@/EditorUserSettings.xml", resolvedPath, AZ_MAX_PATH_LEN); + + m_localUserSettings.Load(resolvedPath, context); + m_localUserSettings.Activate(AZ::UserSettings::CT_LOCAL); + AZ::UserSettingsOwnerRequestBus::Handler::BusConnect(AZ::UserSettings::CT_LOCAL); + m_activatedLocalUserSettings = true; + } + + void AtomToolsApplication::UnloadSettings() + { + if (m_activatedLocalUserSettings) + { + //SaveSettings(); + m_localUserSettings.Deactivate(); + AZ::UserSettingsOwnerRequestBus::Handler::BusDisconnect(); + m_activatedLocalUserSettings = false; + } + } + + void AtomToolsApplication::ProcessCommandLine(const AZ::CommandLine& commandLine) + { + const AZStd::string exitAfterCommandsSwitchName = "exitaftercommands"; + if (commandLine.HasSwitch(exitAfterCommandsSwitchName)) + { + ExitMainLoop(); + } + } + + bool AtomToolsApplication::LaunchDiscoveryService() + { + // Determine if this is the first launch of the tool by attempting to connect to a running server + if (m_socket.Connect(QApplication::applicationName())) + { + // If the server was located, the application is already running. + // Forward commandline options to other application instance. + QByteArray buffer; + buffer.append("ProcessCommandLine:"); + + // Add the command line options from this process to the message, skipping the executable path + for (int argi = 1; argi < m_argC; ++argi) + { + buffer.append(QString(m_argV[argi]).append("\n").toUtf8()); + } + + // Inject command line option to always bring the main window to the foreground + buffer.append("--activatewindow\n"); + + m_socket.Send(buffer); + m_socket.Disconnect(); + return false; + } + + // Setup server to handle basic commands + m_server.SetReadHandler( + [this](const QByteArray& buffer) + { + // Handle commmand line params from connected socket + if (buffer.startsWith("ProcessCommandLine:")) + { + // Remove header and parse commands + AZStd::string params(buffer.data(), buffer.size()); + params = params.substr(strlen("ProcessCommandLine:")); + + AZStd::vector tokens; + AZ::StringFunc::Tokenize(params, tokens, "\n"); + + if (!tokens.empty()) + { + AZ::CommandLine commandLine; + commandLine.Parse(tokens); + ProcessCommandLine(commandLine); + } + } + }); + + // Launch local server + if (!m_server.Connect(QApplication::applicationName())) + { + return false; + } + + return true; + } + + void AtomToolsApplication::StartInternal() + { + if (WasExitMainLoopRequested()) + { + return; + } + + m_traceLogger.WriteStartupLog("AtomTools.log"); + + if (!LaunchDiscoveryService()) + { + ExitMainLoop(); + return; + } + + AzToolsFramework::AssetDatabase::AssetDatabaseRequestsBus::Handler::BusConnect(); + AzToolsFramework::AssetBrowser::AssetDatabaseLocationNotificationBus::Broadcast( + &AzToolsFramework::AssetBrowser::AssetDatabaseLocationNotifications::OnDatabaseInitialized); + + AZ::Data::AssetCatalogRequestBus::Broadcast(&AZ::Data::AssetCatalogRequestBus::Events::LoadCatalog, "@assets@/assetcatalog.xml"); + + AZ::RPI::RPISystemInterface::Get()->InitializeSystemAssets(); + + LoadSettings(); + + auto editorPythonEventsInterface = AZ::Interface::Get(); + if (editorPythonEventsInterface) + { + // The PythonSystemComponent does not call StartPython to allow for lazy python initialization, so start it here + // The PythonSystemComponent will call StopPython when it deactivates, so we do not need our own corresponding call to + // StopPython + editorPythonEventsInterface->StartPython(); + } + + // Delay execution of commands and scripts post initialization + QTimer::singleShot( + 0, + [this]() + { + ProcessCommandLine(m_commandLine); + }); + } + + bool AtomToolsApplication::GetAssetDatabaseLocation(AZStd::string& result) + { + AZ::SettingsRegistryInterface* settingsRegistry = AZ::SettingsRegistry::Get(); + AZ::IO::FixedMaxPath assetDatabaseSqlitePath; + if (settingsRegistry && + settingsRegistry->Get(assetDatabaseSqlitePath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_CacheProjectRootFolder)) + { + assetDatabaseSqlitePath /= "assetdb.sqlite"; + result = AZStd::string_view(assetDatabaseSqlitePath.Native()); + return true; + } + + return false; + } + + void AtomToolsApplication::Tick(float deltaOverride) + { + TickSystem(); + Application::Tick(deltaOverride); + + if (WasExitMainLoopRequested()) + { + m_timer.disconnect(); + quit(); + } + } + + void AtomToolsApplication::Stop() + { + UnloadSettings(); + AzFramework::Application::Stop(); + } + + void AtomToolsApplication::QueryApplicationType(AZ::ApplicationTypeQuery& appType) const + { + appType.m_maskValue = AZ::ApplicationTypeQuery::Masks::Game; + } + + // Copied from PyIdleWaitFrames in CryEdit.cpp + void AtomToolsApplication::PyIdleWaitFrames(uint32_t frames) + { + struct Ticker : public AZ::TickBus::Handler + { + Ticker(QEventLoop* loop, uint32_t targetFrames) + : m_loop(loop) + , m_targetFrames(targetFrames) + { + AZ::TickBus::Handler::BusConnect(); + } + ~Ticker() + { + AZ::TickBus::Handler::BusDisconnect(); + } + + void OnTick(float deltaTime, AZ::ScriptTimePoint time) override + { + AZ_UNUSED(deltaTime); + AZ_UNUSED(time); + if (++m_elapsedFrames == m_targetFrames) + { + m_loop->quit(); + } + } + QEventLoop* m_loop = nullptr; + uint32_t m_elapsedFrames = 0; + uint32_t m_targetFrames = 0; + }; + + QEventLoop loop; + Ticker ticker(&loop, frames); + loop.exec(); + } + +} // namespace AtomToolsFramework diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake b/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake index 817840221a..63bdbcd2ab 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake @@ -6,6 +6,7 @@ # set(FILES + Include/AtomToolsFramework/Application/AtomToolsApplication.h Include/AtomToolsFramework/Communication/LocalServer.h Include/AtomToolsFramework/Communication/LocalSocket.h Include/AtomToolsFramework/Debug/TraceRecorder.h @@ -22,6 +23,7 @@ set(FILES Include/AtomToolsFramework/Viewport/RenderViewportWidget.h Include/AtomToolsFramework/Viewport/ModularViewportCameraController.h Include/AtomToolsFramework/Viewport/ModularViewportCameraControllerRequestBus.h + Source/Application/AtomToolsApplication.cpp Source/Communication/LocalServer.cpp Source/Communication/LocalSocket.cpp Source/Debug/TraceRecorder.cpp diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp index f880ad7680..324db34ee8 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp @@ -71,8 +71,8 @@ namespace MaterialEditor } MaterialEditorApplication::MaterialEditorApplication(int* argc, char*** argv) - : Application(argc, argv) - , AzQtApplication(*argc, *argv) + : AtomToolsApplication(argc, argv) + { QApplication::setApplicationName("O3DE Material Editor"); @@ -93,63 +93,6 @@ namespace MaterialEditor AzToolsFramework::EditorPythonConsoleNotificationBus::Handler::BusDisconnect(); } - void MaterialEditorApplication::CreateReflectionManager() - { - Application::CreateReflectionManager(); - GetSerializeContext()->CreateEditContext(); - } - - void MaterialEditorApplication::Reflect(AZ::ReflectContext* context) - { - Application::Reflect(context); - - AzToolsFramework::AssetBrowser::AssetBrowserEntry::Reflect(context); - AzToolsFramework::AssetBrowser::RootAssetBrowserEntry::Reflect(context); - AzToolsFramework::AssetBrowser::FolderAssetBrowserEntry::Reflect(context); - AzToolsFramework::AssetBrowser::SourceAssetBrowserEntry::Reflect(context); - AzToolsFramework::AssetBrowser::ProductAssetBrowserEntry::Reflect(context); - - AzToolsFramework::QTreeViewWithStateSaving::Reflect(context); - AzToolsFramework::QWidgetSavedState::Reflect(context); - - if (auto behaviorContext = azrtti_cast(context)) - { - // this will put these methods into the 'azlmbr.materialeditor.general' module - auto addGeneral = [](AZ::BehaviorContext::GlobalMethodBuilder methodBuilder) - { - methodBuilder->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation) - ->Attribute(AZ::Script::Attributes::Category, "Editor") - ->Attribute(AZ::Script::Attributes::Module, "materialeditor.general"); - }; - // The reflection here is based on patterns in CryEditPythonHandler::Reflect - addGeneral(behaviorContext->Method("idle_wait_frames", &MaterialEditorApplication::PyIdleWaitFrames, nullptr, "Waits idling for a frames. Primarily used for auto-testing.")); - } - } - - void MaterialEditorApplication::RegisterCoreComponents() - { - Application::RegisterCoreComponents(); - RegisterComponentDescriptor(AzToolsFramework::AssetBrowser::AssetBrowserComponent::CreateDescriptor()); - RegisterComponentDescriptor(AzToolsFramework::Thumbnailer::ThumbnailerComponent::CreateDescriptor()); - RegisterComponentDescriptor(AzToolsFramework::Components::PropertyManagerComponent::CreateDescriptor()); - RegisterComponentDescriptor(AzToolsFramework::AssetSystem::AssetSystemComponent::CreateDescriptor()); - RegisterComponentDescriptor(AzToolsFramework::PerforceComponent::CreateDescriptor()); - } - - AZ::ComponentTypeList MaterialEditorApplication::GetRequiredSystemComponents() const - { - AZ::ComponentTypeList components = Application::GetRequiredSystemComponents(); - - components.insert(components.end(), { - azrtti_typeid(), - azrtti_typeid(), - azrtti_typeid(), - azrtti_typeid(), - }); - - return components; - } - void MaterialEditorApplication::CreateStaticModules(AZStd::vector& outModules) { Application::CreateStaticModules(outModules); @@ -269,20 +212,6 @@ namespace MaterialEditor } } - void MaterialEditorApplication::SaveSettings() - { - if (m_activatedLocalUserSettings) - { - AZ::SerializeContext* context = nullptr; - AZ::ComponentApplicationBus::BroadcastResult(context, &AZ::ComponentApplicationRequests::GetSerializeContext); - AZ_Assert(context, "No serialize context"); - - char resolvedPath[AZ_MAX_PATH_LEN] = ""; - AZ::IO::FileIOBase::GetInstance()->ResolvePath("@user@/MaterialEditorUserSettings.xml", resolvedPath, AZ_ARRAY_SIZE(resolvedPath)); - m_localUserSettings.Save(resolvedPath, context); - } - } - bool MaterialEditorApplication::OnOutput(const char* window, const char* message) { // Suppress spam from the Source Control system @@ -355,86 +284,6 @@ namespace MaterialEditor } } - void MaterialEditorApplication::LoadSettings() - { - AZ::SerializeContext* context = nullptr; - AZ::ComponentApplicationBus::BroadcastResult(context, &AZ::ComponentApplicationRequests::GetSerializeContext); - AZ_Assert(context, "No serialize context"); - - char resolvedPath[AZ_MAX_PATH_LEN] = ""; - AZ::IO::FileIOBase::GetInstance()->ResolvePath("@user@/EditorUserSettings.xml", resolvedPath, AZ_MAX_PATH_LEN); - - m_localUserSettings.Load(resolvedPath, context); - m_localUserSettings.Activate(AZ::UserSettings::CT_LOCAL); - AZ::UserSettingsOwnerRequestBus::Handler::BusConnect(AZ::UserSettings::CT_LOCAL); - m_activatedLocalUserSettings = true; - } - - void MaterialEditorApplication::UnloadSettings() - { - if (m_activatedLocalUserSettings) - { - SaveSettings(); - m_localUserSettings.Deactivate(); - AZ::UserSettingsOwnerRequestBus::Handler::BusDisconnect(); - m_activatedLocalUserSettings = false; - } - } - - bool MaterialEditorApplication::LaunchDiscoveryService() - { - // Determine if this is the first launch of the tool by attempting to connect to a running server - if (m_socket.Connect(QApplication::applicationName())) - { - // If the server was located, the application is already running. - // Forward commandline options to other application instance. - QByteArray buffer; - buffer.append("ProcessCommandLine:"); - - // Add the command line options from this process to the message, skipping the executable path - for (int argi = 1; argi < m_argC; ++argi) - { - buffer.append(QString(m_argV[argi]).append("\n").toUtf8()); - } - - // Inject command line option to always bring the main window to the foreground - buffer.append("--activatewindow\n"); - - m_socket.Send(buffer); - m_socket.Disconnect(); - return false; - } - - // Setup server to handle basic commands - m_server.SetReadHandler([this](const QByteArray& buffer) { - // Handle commmand line params from connected socket - if (buffer.startsWith("ProcessCommandLine:")) - { - // Remove header and parse commands - AZStd::string params(buffer.data(), buffer.size()); - params = params.substr(strlen("ProcessCommandLine:")); - - AZStd::vector tokens; - AZ::StringFunc::Tokenize(params, tokens, "\n"); - - if (!tokens.empty()) - { - AZ::CommandLine commandLine; - commandLine.Parse(tokens); - ProcessCommandLine(commandLine); - } - } - }); - - // Launch local server - if (!m_server.Connect(QApplication::applicationName())) - { - return false; - } - - return true; - } - void MaterialEditorApplication::StartInternal() { if (WasExitMainLoopRequested()) @@ -476,20 +325,6 @@ namespace MaterialEditor QTimer::singleShot(0, [this]() { ProcessCommandLine(m_commandLine); }); } - bool MaterialEditorApplication::GetAssetDatabaseLocation(AZStd::string& result) - { - AZ::SettingsRegistryInterface* settingsRegistry = AZ::SettingsRegistry::Get(); - AZ::IO::FixedMaxPath assetDatabaseSqlitePath; - if (settingsRegistry && settingsRegistry->Get(assetDatabaseSqlitePath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_CacheProjectRootFolder)) - { - assetDatabaseSqlitePath /= "assetdb.sqlite"; - result = AZStd::string_view(assetDatabaseSqlitePath.Native()); - return true; - } - - return false; - } - void MaterialEditorApplication::Tick(float deltaOverride) { TickSystem(); @@ -545,38 +380,4 @@ namespace MaterialEditor { AZ_Error("MaterialEditor", false, "Python: " AZ_STRING_FORMAT, AZ_STRING_ARG(message)); } - - // Copied from PyIdleWaitFrames in CryEdit.cpp - void MaterialEditorApplication::PyIdleWaitFrames(uint32_t frames) - { - struct Ticker : public AZ::TickBus::Handler - { - Ticker(QEventLoop* loop, uint32_t targetFrames) : m_loop(loop), m_targetFrames(targetFrames) - { - AZ::TickBus::Handler::BusConnect(); - } - ~Ticker() - { - AZ::TickBus::Handler::BusDisconnect(); - } - - void OnTick(float deltaTime, AZ::ScriptTimePoint time) override - { - AZ_UNUSED(deltaTime); - AZ_UNUSED(time); - if (++m_elapsedFrames == m_targetFrames) - { - m_loop->quit(); - } - } - QEventLoop* m_loop = nullptr; - uint32_t m_elapsedFrames = 0; - uint32_t m_targetFrames = 0; - }; - - QEventLoop loop; - Ticker ticker(&loop, frames); - loop.exec(); - } - } // namespace MaterialEditor diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h index 284eddee93..86fce0c73b 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h @@ -22,6 +22,7 @@ #include #include #include +#include #include @@ -30,29 +31,19 @@ namespace MaterialEditor class MaterialThumbnailRenderer; class MaterialEditorApplication - : public AzFramework::Application - , public AzQtComponents::AzQtApplication - , private AzToolsFramework::AssetDatabase::AssetDatabaseRequestsBus::Handler + : public AtomToolsFramework::AtomToolsApplication , private MaterialEditorWindowNotificationBus::Handler - , private AzFramework::AssetSystemStatusBus::Handler - , private AZ::UserSettingsOwnerRequestBus::Handler - , private AZ::Debug::TraceMessageBus::Handler - , private AzToolsFramework::EditorPythonConsoleNotificationBus::Handler { public: AZ_TYPE_INFO(MaterialEditor::MaterialEditorApplication, "{30F90CA5-1253-49B5-8143-19CEE37E22BB}"); - using Base = AzFramework::Application; + using Base = AtomToolsFramework::AtomToolsApplication; MaterialEditorApplication(int* argc, char*** argv); virtual ~MaterialEditorApplication(); ////////////////////////////////////////////////////////////////////////// // AzFramework::Application - void CreateReflectionManager() override; - void Reflect(AZ::ReflectContext* context) override; - void RegisterCoreComponents() override; - AZ::ComponentTypeList GetRequiredSystemComponents() const override; void CreateStaticModules(AZStd::vector& outModules) override; const char* GetCurrentConfigurationName() const override; void StartCommon(AZ::Entity* systemEntity) override; @@ -60,11 +51,6 @@ namespace MaterialEditor void Stop() override; private: - ////////////////////////////////////////////////////////////////////////// - // AssetDatabaseRequestsBus::Handler overrides... - bool GetAssetDatabaseLocation(AZStd::string& result) override; - ////////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////// // MaterialEditorWindowNotificationBus::Handler overrides... void OnMaterialEditorWindowClosing() override; @@ -92,28 +78,14 @@ namespace MaterialEditor void AssetSystemAvailable() override; ////////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////// - // AZ::UserSettingsOwnerRequestBus::Handler overrides... - void SaveSettings() override; - ////////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////// // AZ::Debug::TraceMessageBus::Handler overrides... bool OnOutput(const char* window, const char* message) override; ////////////////////////////////////////////////////////////////////////// - void CompileCriticalAssets(); - - void ProcessCommandLine(const AZ::CommandLine& commandLine); - - void LoadSettings(); - void UnloadSettings(); - - bool LaunchDiscoveryService(); - - void StartInternal(); - - static void PyIdleWaitFrames(uint32_t frames); + void CompileCriticalAssets() override; + void ProcessCommandLine(const AZ::CommandLine& commandLine) override; + void StartInternal() override; struct LogMessage { @@ -123,18 +95,5 @@ namespace MaterialEditor AZStd::vector m_startupLogSink; AZStd::unique_ptr m_logFile; - - AzToolsFramework::TraceLogger m_traceLogger; - - //! Local user settings are used to store material browser tree expansion state - AZ::UserSettingsProvider m_localUserSettings; - - //! Are local settings loaded - bool m_activatedLocalUserSettings = false; - - QTimer m_timer; - - AtomToolsFramework::LocalSocket m_socket; - AtomToolsFramework::LocalServer m_server; }; } // namespace MaterialEditor diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp index d10893ff46..271a53d73c 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp @@ -67,77 +67,13 @@ namespace ShaderManagementConsole } ShaderManagementConsoleApplication::ShaderManagementConsoleApplication(int* argc, char*** argv) - : Application(argc, argv) - , AzQtApplication(*argc, *argv) + : AtomToolsApplication(argc, argv) { QApplication::setApplicationName("O3DE Shader Management Console"); // The settings registry has been created at this point, so add the CMake target AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddBuildSystemTargetSpecialization( *AZ::SettingsRegistry::Get(), GetBuildTargetName()); - - connect(&m_timer, &QTimer::timeout, this, [&]() - { - this->PumpSystemEventLoopUntilEmpty(); - this->Tick(); - }); - } - - void ShaderManagementConsoleApplication::CreateReflectionManager() - { - Application::CreateReflectionManager(); - GetSerializeContext()->CreateEditContext(); - } - - void ShaderManagementConsoleApplication::Reflect(AZ::ReflectContext* context) - { - Application::Reflect(context); - - AzToolsFramework::AssetBrowser::AssetBrowserEntry::Reflect(context); - AzToolsFramework::AssetBrowser::RootAssetBrowserEntry::Reflect(context); - AzToolsFramework::AssetBrowser::FolderAssetBrowserEntry::Reflect(context); - AzToolsFramework::AssetBrowser::SourceAssetBrowserEntry::Reflect(context); - AzToolsFramework::AssetBrowser::ProductAssetBrowserEntry::Reflect(context); - - AzToolsFramework::QTreeViewWithStateSaving::Reflect(context); - AzToolsFramework::QWidgetSavedState::Reflect(context); - - if (auto behaviorContext = azrtti_cast(context)) - { - // this will put these methods into the 'azlmbr.shadermanagementconsole.general' module - auto addGeneral = [](AZ::BehaviorContext::GlobalMethodBuilder methodBuilder) - { - methodBuilder->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation) - ->Attribute(AZ::Script::Attributes::Category, "Editor") - ->Attribute(AZ::Script::Attributes::Module, "shadermanagementconsole.general"); - }; - // The reflection here is based on patterns in CryEditPythonHandler::Reflect - addGeneral(behaviorContext->Method("idle_wait_frames", &ShaderManagementConsoleApplication::PyIdleWaitFrames, nullptr, "Waits idling for a frames. Primarily used for auto-testing.")); - } - } - - void ShaderManagementConsoleApplication::RegisterCoreComponents() - { - Application::RegisterCoreComponents(); - RegisterComponentDescriptor(AzToolsFramework::AssetBrowser::AssetBrowserComponent::CreateDescriptor()); - RegisterComponentDescriptor(AzToolsFramework::Thumbnailer::ThumbnailerComponent::CreateDescriptor()); - RegisterComponentDescriptor(AzToolsFramework::Components::PropertyManagerComponent::CreateDescriptor()); - RegisterComponentDescriptor(AzToolsFramework::AssetSystem::AssetSystemComponent::CreateDescriptor()); - RegisterComponentDescriptor(AzToolsFramework::PerforceComponent::CreateDescriptor()); - } - - AZ::ComponentTypeList ShaderManagementConsoleApplication::GetRequiredSystemComponents() const - { - AZ::ComponentTypeList components = Application::GetRequiredSystemComponents(); - - components.insert(components.end(), { - azrtti_typeid(), - azrtti_typeid(), - azrtti_typeid(), - azrtti_typeid(), - }); - - return components; } void ShaderManagementConsoleApplication::CreateStaticModules(AZStd::vector& outModules) @@ -148,18 +84,6 @@ namespace ShaderManagementConsole outModules.push_back(aznew ShaderManagementConsoleWindowModule); } - void ShaderManagementConsoleApplication::StartCommon(AZ::Entity* systemEntity) - { - AzFramework::AssetSystemStatusBus::Handler::BusConnect(); - AzToolsFramework::EditorPythonConsoleNotificationBus::Handler::BusConnect(); - - AzFramework::Application::StartCommon(systemEntity); - - StartInternal(); - - m_timer.start(); - } - void ShaderManagementConsoleApplication::OnShaderManagementConsoleWindowClosing() { ExitMainLoop(); @@ -174,6 +98,7 @@ namespace ShaderManagementConsole ShaderManagementConsoleWindowNotificationBus::Handler::BusDisconnect(); AzToolsFramework::AssetDatabase::AssetDatabaseRequestsBus::Handler::BusDisconnect(); + m_traceLogger.~TraceLogger(); AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::StartDisconnectingAssetProcessor); @@ -254,20 +179,6 @@ namespace ShaderManagementConsole } } - void ShaderManagementConsoleApplication::SaveSettings() - { - if (m_activatedLocalUserSettings) - { - AZ::SerializeContext* context = nullptr; - AZ::ComponentApplicationBus::BroadcastResult(context, &AZ::ComponentApplicationRequests::GetSerializeContext); - AZ_Assert(context, "No serialize context"); - - char resolvedPath[AZ_MAX_PATH_LEN] = ""; - AZ::IO::FileIOBase::GetInstance()->ResolvePath("@user@/EditorUserSettings.xml", resolvedPath, AZ_ARRAY_SIZE(resolvedPath)); - m_localUserSettings.Save(resolvedPath, context); - } - } - bool ShaderManagementConsoleApplication::OnPrintf(const char* window, const char* /*message*/) { // Suppress spam from the Source Control system @@ -303,32 +214,6 @@ namespace ShaderManagementConsole } } - void ShaderManagementConsoleApplication::LoadSettings() - { - AZ::SerializeContext* context = nullptr; - AZ::ComponentApplicationBus::BroadcastResult(context, &AZ::ComponentApplicationRequests::GetSerializeContext); - AZ_Assert(context, "No serialize context"); - - char resolvedPath[AZ_MAX_PATH_LEN] = ""; - AZ::IO::FileIOBase::GetInstance()->ResolvePath("@user@/EditorUserSettings.xml", resolvedPath, AZ_MAX_PATH_LEN); - - m_localUserSettings.Load(resolvedPath, context); - m_localUserSettings.Activate(AZ::UserSettings::CT_LOCAL); - AZ::UserSettingsOwnerRequestBus::Handler::BusConnect(AZ::UserSettings::CT_LOCAL); - m_activatedLocalUserSettings = true; - } - - void ShaderManagementConsoleApplication::UnloadSettings() - { - if (m_activatedLocalUserSettings) - { - SaveSettings(); - m_localUserSettings.Deactivate(); - AZ::UserSettingsOwnerRequestBus::Handler::BusDisconnect(); - m_activatedLocalUserSettings = false; - } - } - bool ShaderManagementConsoleApplication::LaunchDiscoveryService() { const QStringList arguments = { "-fail_silently" }; @@ -398,17 +283,6 @@ namespace ShaderManagementConsole } } - void ShaderManagementConsoleApplication::Stop() - { - UnloadSettings(); - AzFramework::Application::Stop(); - } - - void ShaderManagementConsoleApplication::QueryApplicationType(AZ::ApplicationTypeQuery& appType) const - { - appType.m_maskValue = AZ::ApplicationTypeQuery::Masks::Game; - } - void ShaderManagementConsoleApplication::OnTraceMessage([[maybe_unused]] AZStd::string_view message) { #if defined(AZ_ENABLE_TRACING) @@ -428,48 +302,8 @@ namespace ShaderManagementConsole #endif } - void ShaderManagementConsoleApplication::OnErrorMessage(AZStd::string_view message) - { - // Use AZ_TracePrintf instead of AZ_Error or AZ_Warning to avoid all the metadata noise - OnTraceMessage(message); - } - void ShaderManagementConsoleApplication::OnExceptionMessage([[maybe_unused]] AZStd::string_view message) { AZ_Error("Shader Management Console", false, "Python: " AZ_STRING_FORMAT, AZ_STRING_ARG(message)); } - - // Copied from PyIdleWaitFrames in CryEdit.cpp - void ShaderManagementConsoleApplication::PyIdleWaitFrames(uint32_t frames) - { - struct Ticker : public AZ::TickBus::Handler - { - Ticker(QEventLoop* loop, uint32_t targetFrames) : m_loop(loop), m_targetFrames(targetFrames) - { - AZ::TickBus::Handler::BusConnect(); - } - ~Ticker() - { - AZ::TickBus::Handler::BusDisconnect(); - } - - void OnTick(float deltaTime, AZ::ScriptTimePoint time) override - { - AZ_UNUSED(deltaTime); - AZ_UNUSED(time); - if (++m_elapsedFrames == m_targetFrames) - { - m_loop->quit(); - } - } - QEventLoop* m_loop = nullptr; - uint32_t m_elapsedFrames = 0; - uint32_t m_targetFrames = 0; - }; - - QEventLoop loop; - Ticker ticker(&loop, frames); - loop.exec(); - } - } // namespace ShaderManagementConsole diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h index e74458b2e7..f6dd2f12ea 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h @@ -23,19 +23,17 @@ #include #include +#include #include namespace ShaderManagementConsole { class ShaderManagementConsoleApplication - : public AzFramework::Application - , public AzQtComponents::AzQtApplication - , private AzToolsFramework::AssetDatabase::AssetDatabaseRequestsBus::Handler + : public AtomToolsFramework::AtomToolsApplication , private ShaderManagementConsoleWindowNotificationBus::Handler , private AzFramework::AssetSystemStatusBus::Handler - , private AZ::UserSettingsOwnerRequestBus::Handler - , private AZ::Debug::TraceMessageBus::Handler + , private AzToolsFramework::AssetDatabase::AssetDatabaseRequestsBus::Handler , private AzToolsFramework::EditorPythonConsoleNotificationBus::Handler { public: @@ -113,18 +111,5 @@ namespace ShaderManagementConsole void StartInternal(); static void PyIdleWaitFrames(uint32_t frames); - - AzToolsFramework::TraceLogger m_traceLogger; - - //! Local user settings are used to store asset browser tree expansion state - AZ::UserSettingsProvider m_localUserSettings; - - //! Are local settings loaded - bool m_activatedLocalUserSettings = false; - - QTimer m_timer; - - bool m_started = false; - bool m_closing = false; }; } // namespace ShaderManagementConsole From c1998d8d3c2ca5adb024e7db6da81749319e9ee1 Mon Sep 17 00:00:00 2001 From: Dayo Lawal Date: Wed, 21 Jul 2021 16:47:06 -0500 Subject: [PATCH 018/160] AtomToolsApplication working with SMC Signed-off-by: Dayo Lawal --- .../Application/AtomToolsApplication.cpp | 3 -- .../Code/Source/MaterialEditorApplication.cpp | 5 --- .../Code/Source/MaterialEditorApplication.h | 5 --- .../ShaderManagementConsoleApplication.cpp | 21 ++++++------ .../ShaderManagementConsoleApplication.h | 32 ++----------------- 5 files changed, 12 insertions(+), 54 deletions(-) diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp index 35a151e95b..464480ec53 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp @@ -154,9 +154,6 @@ namespace AtomToolsFramework AzToolsFramework::AssetDatabase::AssetDatabaseRequestsBus::Handler::BusDisconnect(); AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); - m_logFile = {}; - m_startupLogSink = {}; - AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::StartDisconnectingAssetProcessor); Application::Destroy(); } diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp index 324db34ee8..4b233b0212 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp @@ -346,11 +346,6 @@ namespace MaterialEditor AzFramework::Application::Stop(); } - void MaterialEditorApplication::QueryApplicationType(AZ::ApplicationTypeQuery& appType) const - { - appType.m_maskValue = AZ::ApplicationTypeQuery::Masks::Game; - } - void MaterialEditorApplication::OnTraceMessage([[maybe_unused]] AZStd::string_view message) { #if defined(AZ_ENABLE_TRACING) diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h index 86fce0c73b..d398f4406d 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h @@ -61,11 +61,6 @@ namespace MaterialEditor void Destroy() override; ////////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////// - // AZ::ComponentApplication overrides... - void QueryApplicationType(AZ::ApplicationTypeQuery& appType) const override; - ////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////// // EditorPythonConsoleNotificationBus::Handler overrides... void OnTraceMessage(AZStd::string_view message) override; diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp index 271a53d73c..4a3f5dd02d 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp @@ -98,7 +98,7 @@ namespace ShaderManagementConsole ShaderManagementConsoleWindowNotificationBus::Handler::BusDisconnect(); AzToolsFramework::AssetDatabase::AssetDatabaseRequestsBus::Handler::BusDisconnect(); - m_traceLogger.~TraceLogger(); + AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::StartDisconnectingAssetProcessor); @@ -175,7 +175,7 @@ namespace ShaderManagementConsole QString("Failed to compile the following critical assets:\n%1\n%2") .arg(failedAssets.join(",\n")) .arg("Make sure this is an Atom project.")); - m_closing = true; + ExitMainLoop(); } } @@ -214,16 +214,9 @@ namespace ShaderManagementConsole } } - bool ShaderManagementConsoleApplication::LaunchDiscoveryService() - { - const QStringList arguments = { "-fail_silently" }; - - return AtomToolsFramework::LaunchTool("GridHub", AZ_TRAIT_SHADER_MANAGEMENT_CONSOLE_EXT, arguments); - } - void ShaderManagementConsoleApplication::StartInternal() { - if (m_closing) + if (WasExitMainLoopRequested()) { return; } @@ -276,7 +269,7 @@ namespace ShaderManagementConsole TickSystem(); Application::Tick(deltaOverride); - if (m_closing) + if (WasExitMainLoopRequested()) { m_timer.disconnect(); quit(); @@ -302,6 +295,12 @@ namespace ShaderManagementConsole #endif } + void ShaderManagementConsoleApplication::OnErrorMessage(AZStd::string_view message) + { + // Use AZ_TracePrintf instead of AZ_Error or AZ_Warning to avoid all the metadata noise + OnTraceMessage(message); + } + void ShaderManagementConsoleApplication::OnExceptionMessage([[maybe_unused]] AZStd::string_view message) { AZ_Error("Shader Management Console", false, "Python: " AZ_STRING_FORMAT, AZ_STRING_ARG(message)); diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h index f6dd2f12ea..d99d814627 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h @@ -32,9 +32,6 @@ namespace ShaderManagementConsole class ShaderManagementConsoleApplication : public AtomToolsFramework::AtomToolsApplication , private ShaderManagementConsoleWindowNotificationBus::Handler - , private AzFramework::AssetSystemStatusBus::Handler - , private AzToolsFramework::AssetDatabase::AssetDatabaseRequestsBus::Handler - , private AzToolsFramework::EditorPythonConsoleNotificationBus::Handler { public: AZ_TYPE_INFO(ShaderManagementConsole::ShaderManagementConsoleApplication, "{30F90CA5-1253-49B5-8143-19CEE37E22BB}"); @@ -46,15 +43,9 @@ namespace ShaderManagementConsole ////////////////////////////////////////////////////////////////////////// // AzFramework::Application - void CreateReflectionManager() override; - void Reflect(AZ::ReflectContext* context) override; - void RegisterCoreComponents() override; - AZ::ComponentTypeList GetRequiredSystemComponents() const override; void CreateStaticModules(AZStd::vector& outModules) override; const char* GetCurrentConfigurationName() const override; - void StartCommon(AZ::Entity* systemEntity) override; void Tick(float deltaOverride = -1.f) override; - void Stop() override; private: ////////////////////////////////////////////////////////////////////////// @@ -72,11 +63,6 @@ namespace ShaderManagementConsole void Destroy() override; ////////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////// - // AzFramework::ApplicationRequests::Bus overrides... - void QueryApplicationType(AZ::ApplicationTypeQuery& appType) const override; - ////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////// // EditorPythonConsoleNotificationBus::Handler overrides... void OnTraceMessage(AZStd::string_view message) override; @@ -89,27 +75,13 @@ namespace ShaderManagementConsole void AssetSystemAvailable() override; ////////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////// - // AZ::UserSettingsOwnerRequestBus::Handler overrides... - void SaveSettings() override; - ////////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////// // AZ::Debug::TraceMessageBus::Handler overrides... bool OnPrintf(const char* window, const char* message) override; ////////////////////////////////////////////////////////////////////////// - void CompileCriticalAssets(); - + void CompileCriticalAssets() override; void ProcessCommandLine(); - - void LoadSettings(); - void UnloadSettings(); - - bool LaunchDiscoveryService(); - - void StartInternal(); - - static void PyIdleWaitFrames(uint32_t frames); + void StartInternal() override; }; } // namespace ShaderManagementConsole From ecc26a24a5e13d7f4083f6e50c034fb507f7ec82 Mon Sep 17 00:00:00 2001 From: Dayo Lawal Date: Thu, 22 Jul 2021 11:27:23 -0500 Subject: [PATCH 019/160] //! Comment added Signed-off-by: Dayo Lawal --- .../AtomToolsFramework/Application/AtomToolsApplication.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h index dc34ad9a0a..8d3c09385c 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h @@ -18,6 +18,7 @@ namespace AtomToolsFramework { + //!Base class for Atom tools to inherit from class AtomToolsApplication : public AzFramework::Application , public AzQtComponents::AzQtApplication From b55bad496d2e6516bac233bc148a269002774733 Mon Sep 17 00:00:00 2001 From: puvvadar Date: Thu, 22 Jul 2021 13:49:05 -0700 Subject: [PATCH 020/160] Adding rewindable mechanisms to support interpolation Signed-off-by: puvvadar --- .../Code/Include/Multiplayer/IMultiplayer.h | 4 +++- .../Include/Multiplayer/MultiplayerTypes.h | 3 +++ .../Multiplayer/NetworkTime/INetworkTime.h | 8 ++++++++ .../Multiplayer/NetworkTime/RewindableObject.h | 4 ++++ .../NetworkTime/RewindableObject.inl | 6 ++++++ .../LocalPredictionPlayerInputComponent.cpp | 11 ++++++----- .../Code/Source/NetworkTime/NetworkTime.cpp | 11 +++++++++++ .../Code/Source/NetworkTime/NetworkTime.h | 3 +++ .../Code/Tests/RewindableContainerTests.cpp | 8 ++++---- .../Code/Tests/RewindableObjectTests.cpp | 18 +++++++++--------- 10 files changed, 57 insertions(+), 19 deletions(-) diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/IMultiplayer.h b/Gems/Multiplayer/Code/Include/Multiplayer/IMultiplayer.h index 23885e6c64..17d2cffafd 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/IMultiplayer.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/IMultiplayer.h @@ -186,18 +186,20 @@ namespace Multiplayer class ScopedAlterTime final { public: - inline ScopedAlterTime(HostFrameId frameId, AZ::TimeMs timeMs, AzNetworking::ConnectionId connectionId) + inline ScopedAlterTime(HostFrameId frameId, AZ::TimeMs timeMs, float blendFactor, AzNetworking::ConnectionId connectionId) { INetworkTime* time = GetNetworkTime(); m_previousHostFrameId = time->GetHostFrameId(); m_previousHostTimeMs = time->GetHostTimeMs(); m_previousRewindConnectionId = time->GetRewindingConnectionId(); time->AlterTime(frameId, timeMs, connectionId); + time->AlterBlendFactor(blendFactor); } inline ~ScopedAlterTime() { INetworkTime* time = GetNetworkTime(); time->AlterTime(m_previousHostFrameId, m_previousHostTimeMs, m_previousRewindConnectionId); + time->AlterBlendFactor(DefaultBlendFactor); } private: HostFrameId m_previousHostFrameId = InvalidHostFrameId; diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/MultiplayerTypes.h b/Gems/Multiplayer/Code/Include/Multiplayer/MultiplayerTypes.h index 9f81ca97a9..4fdf428e37 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/MultiplayerTypes.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/MultiplayerTypes.h @@ -21,6 +21,9 @@ namespace Multiplayer //! The default number of rewindable samples for us to store. static constexpr uint32_t RewindHistorySize = 128; + //! The default blend factor for ScopedAlterTime + static constexpr float DefaultBlendFactor = 1.f; + AZ_TYPE_SAFE_INTEGRAL(HostId, uint32_t); static constexpr HostId InvalidHostId = static_cast(-1); diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/NetworkTime/INetworkTime.h b/Gems/Multiplayer/Code/Include/Multiplayer/NetworkTime/INetworkTime.h index c88c971636..5e5e7aab25 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/NetworkTime/INetworkTime.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/NetworkTime/INetworkTime.h @@ -42,6 +42,10 @@ namespace Multiplayer //! @return the hosts current timeMs virtual AZ::TimeMs GetHostTimeMs() const = 0; + //! Retrieves the hosts current blend factor (may be rewound on the server during backward reconciliation). + //! @return the hosts current blend factor + virtual float GetHostBlendFactor() const = 0; + //! Get the controlling connection that may be currently altering global game time. //! Note this abstraction is required at a relatively high level to allow for 'don't rewind the shooter' semantics //! @return the ConnectionId of the connection requesting the rewind operation @@ -59,6 +63,10 @@ namespace Multiplayer //! @param rewindConnectionId the rewinding ConnectionId virtual void AlterTime(HostFrameId frameId, AZ::TimeMs timeMs, AzNetworking::ConnectionId rewindConnectionId) = 0; + //! Alters the current Host blend factor. Used to drive interpolation in rewound states. + //! @param blendFactor the blend factor to use + virtual void AlterBlendFactor(float blendFactor) = 0; + //! Syncs all entities contained within a volume to the current rewind state. //! @param rewindVolume the volume to rewind entities within (needed for physics entities) virtual void SyncEntitiesToRewindState(const AZ::Aabb& rewindVolume) = 0; diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/NetworkTime/RewindableObject.h b/Gems/Multiplayer/Code/Include/Multiplayer/NetworkTime/RewindableObject.h index 796eec5412..2eff6d8bb0 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/NetworkTime/RewindableObject.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/NetworkTime/RewindableObject.h @@ -59,6 +59,10 @@ namespace Multiplayer //! @return value in const base type form const BASE_TYPE& Get() const; + //! Const base type retriever for one host frame behind Get(). + //! @return value in const base type form + const BASE_TYPE& GetPrevious() const; + //! Base type retriever. //! @return value in base type form BASE_TYPE& Modify(); diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/NetworkTime/RewindableObject.inl b/Gems/Multiplayer/Code/Include/Multiplayer/NetworkTime/RewindableObject.inl index dc8d98fb45..7027069b27 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/NetworkTime/RewindableObject.inl +++ b/Gems/Multiplayer/Code/Include/Multiplayer/NetworkTime/RewindableObject.inl @@ -65,6 +65,12 @@ namespace Multiplayer return GetValueForTime(GetCurrentTimeForProperty()); } + template + inline const BASE_TYPE& RewindableObject::GetPrevious() const + { + return GetValueForTime(GetCurrentTimeForProperty() - HostFrameId(1)); + } + template inline BASE_TYPE& RewindableObject::Modify() { diff --git a/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp b/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp index da299401d8..15945b12ff 100644 --- a/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp @@ -155,11 +155,12 @@ namespace Multiplayer if (m_clientBankedTime < sv_MaxBankTimeWindowSec) { // Client blends from previous frame to target so here we subtract blend factor to get to that state - const float adjustedBlendFactor = std::pow(0.2f, input.GetHostBlendFactor()); + const float blendFactor = AZStd::max(0.f, input.GetHostBlendFactor()); + const float adjustedBlendFactor = std::pow(0.2f, blendFactor); const AZ::TimeMs blendMs = AZ::TimeMs(static_cast(static_cast(cl_InputRateMs)) * adjustedBlendFactor); m_clientBankedTime = AZStd::min(m_clientBankedTime + clientInputRateSec, (double)sv_MaxBankTimeWindowSec); // clamp to boundary { - ScopedAlterTime scopedTime(input.GetHostFrameId(), input.GetHostTimeMs() - blendMs, invokingConnection->GetConnectionId()); + ScopedAlterTime scopedTime(input.GetHostFrameId(), input.GetHostTimeMs() - blendMs, input.GetHostBlendFactor(), invokingConnection->GetConnectionId()); GetNetBindComponent()->ProcessInput(input, static_cast(clientInputRateSec)); } @@ -313,7 +314,7 @@ namespace Multiplayer ++ModifyLastInputId(); input.SetClientInputId(GetLastInputId()); - ScopedAlterTime scopedTime(input.GetHostFrameId(), input.GetHostTimeMs(), invokingConnection->GetConnectionId()); + ScopedAlterTime scopedTime(input.GetHostFrameId(), input.GetHostTimeMs(), DefaultBlendFactor, invokingConnection->GetConnectionId()); GetNetBindComponent()->ProcessInput(input, clientInputRateSec); AZLOG @@ -393,7 +394,7 @@ namespace Multiplayer { // Reprocess the input for this frame NetworkInput& input = m_inputHistory[replayIndex]; - ScopedAlterTime scopedTime(input.GetHostFrameId(), input.GetHostTimeMs(), invokingConnection->GetConnectionId()); + ScopedAlterTime scopedTime(input.GetHostFrameId(), input.GetHostTimeMs(), DefaultBlendFactor, invokingConnection->GetConnectionId()); GetNetBindComponent()->ProcessInput(input, clientInputRateSec); AZLOG @@ -576,7 +577,7 @@ namespace Multiplayer NetworkInput& input = m_lastInputReceived[0]; { - ScopedAlterTime scopedTime(input.GetHostFrameId(), input.GetHostTimeMs(), AzNetworking::InvalidConnectionId); + ScopedAlterTime scopedTime(input.GetHostFrameId(), input.GetHostTimeMs(), DefaultBlendFactor, AzNetworking::InvalidConnectionId); GetNetBindComponent()->ProcessInput(input, inputRate); } diff --git a/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.cpp b/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.cpp index 88ffa0b5d7..b15125b5d2 100644 --- a/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.cpp @@ -54,6 +54,11 @@ namespace Multiplayer return m_hostTimeMs; } + float NetworkTime::GetHostBlendFactor() const + { + return m_hostBlendFactor; + } + AzNetworking::ConnectionId NetworkTime::GetRewindingConnectionId() const { return m_rewindingConnectionId; @@ -71,6 +76,11 @@ namespace Multiplayer m_rewindingConnectionId = rewindConnectionId; } + void NetworkTime::AlterBlendFactor(float blendFactor) + { + m_hostBlendFactor = blendFactor; + } + void NetworkTime::SyncEntitiesToRewindState(const AZ::Aabb& rewindVolume) { // Since the vis system doesn't support rewound queries, first query with an expanded volume to catch any fast moving entities @@ -94,6 +104,7 @@ namespace Multiplayer if (networkTransform != nullptr) { + // We're not presently factoring in interpolated position here const AZ::Vector3 rewindCenter = networkTransform->GetTranslation(); // Get the rewound position const AZ::Vector3 rewindOffset = rewindCenter - currentCenter; // Compute offset between rewound and current positions const AZ::Aabb rewoundAabb = currentBounds.GetTranslated(rewindOffset); // Apply offset to the entity aabb diff --git a/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.h b/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.h index 53c9540843..f6b2907c92 100644 --- a/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.h +++ b/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.h @@ -29,9 +29,11 @@ namespace Multiplayer HostFrameId GetUnalteredHostFrameId() const override; void IncrementHostFrameId() override; AZ::TimeMs GetHostTimeMs() const override; + float GetHostBlendFactor() const override; AzNetworking::ConnectionId GetRewindingConnectionId() const override; HostFrameId GetHostFrameIdForRewindingConnection(AzNetworking::ConnectionId rewindConnectionId) const override; void AlterTime(HostFrameId frameId, AZ::TimeMs timeMs, AzNetworking::ConnectionId rewindConnectionId) override; + void AlterBlendFactor(float blendFactor) override; void SyncEntitiesToRewindState(const AZ::Aabb& rewindVolume) override; void ClearRewoundEntities() override; //! @} @@ -43,6 +45,7 @@ namespace Multiplayer HostFrameId m_hostFrameId = HostFrameId{ 0 }; HostFrameId m_unalteredFrameId = HostFrameId{ 0 }; AZ::TimeMs m_hostTimeMs = AZ::TimeMs{ 0 }; + float m_hostBlendFactor = DefaultBlendFactor; AzNetworking::ConnectionId m_rewindingConnectionId = AzNetworking::InvalidConnectionId; }; } diff --git a/Gems/Multiplayer/Code/Tests/RewindableContainerTests.cpp b/Gems/Multiplayer/Code/Tests/RewindableContainerTests.cpp index 2e3a65a5e5..ae56fdcf39 100644 --- a/Gems/Multiplayer/Code/Tests/RewindableContainerTests.cpp +++ b/Gems/Multiplayer/Code/Tests/RewindableContainerTests.cpp @@ -42,7 +42,7 @@ namespace UnitTest // Test rewind for all pushed values and overall size for (uint32_t idx = 0; idx < RewindableContainerSize; ++idx) { - Multiplayer::ScopedAlterTime time(static_cast(idx), AZ::TimeMs{ 0 }, AzNetworking::InvalidConnectionId); + Multiplayer::ScopedAlterTime time(static_cast(idx), AZ::TimeMs{ 0 }, 1.f, AzNetworking::InvalidConnectionId); EXPECT_EQ(idx + 1, test.size()); EXPECT_EQ(idx, test.back()); } @@ -69,9 +69,9 @@ namespace UnitTest EXPECT_TRUE(test.empty()); // Test rewind for pop_back and clear - Multiplayer::ScopedAlterTime pop_time(static_cast(RewindableContainerSize), AZ::TimeMs{ 0 }, AzNetworking::InvalidConnectionId); + Multiplayer::ScopedAlterTime pop_time(static_cast(RewindableContainerSize), AZ::TimeMs{ 0 }, 1.f, AzNetworking::InvalidConnectionId); EXPECT_EQ(RewindableContainerSize - 1, test.size()); - Multiplayer::ScopedAlterTime clear_time(static_cast(RewindableContainerSize + 1), AZ::TimeMs{ 0 }, AzNetworking::InvalidConnectionId); + Multiplayer::ScopedAlterTime clear_time(static_cast(RewindableContainerSize + 1), AZ::TimeMs{ 0 }, 1.f, AzNetworking::InvalidConnectionId); EXPECT_EQ(0, test.size()); // Test copy_values and resize_no_construct @@ -99,7 +99,7 @@ namespace UnitTest // Test rewind for all values and overall size for (uint32_t idx = 1; idx <= RewindableContainerSize; ++idx) { - Multiplayer::ScopedAlterTime time(static_cast(idx), AZ::TimeMs{ 0 }, AzNetworking::InvalidConnectionId); + Multiplayer::ScopedAlterTime time(static_cast(idx), AZ::TimeMs{ 0 }, 1.f, AzNetworking::InvalidConnectionId); for (uint32_t testIdx = 0; testIdx < RewindableContainerSize; ++testIdx) { if (testIdx < idx) diff --git a/Gems/Multiplayer/Code/Tests/RewindableObjectTests.cpp b/Gems/Multiplayer/Code/Tests/RewindableObjectTests.cpp index 472a1ce148..e992eb6848 100644 --- a/Gems/Multiplayer/Code/Tests/RewindableObjectTests.cpp +++ b/Gems/Multiplayer/Code/Tests/RewindableObjectTests.cpp @@ -38,7 +38,7 @@ namespace UnitTest for (uint32_t i = 0; i < 16; ++i) { - Multiplayer::ScopedAlterTime time(static_cast(i), AZ::TimeMs{ 0 }, AzNetworking::InvalidConnectionId); + Multiplayer::ScopedAlterTime time(static_cast(i), AZ::TimeMs{ 0 }, 1.f, AzNetworking::InvalidConnectionId); EXPECT_EQ(i, test); } @@ -51,7 +51,7 @@ namespace UnitTest for (uint32_t i = 16; i < 48; ++i) { - Multiplayer::ScopedAlterTime time(static_cast(i), AZ::TimeMs{ 0 }, AzNetworking::InvalidConnectionId); + Multiplayer::ScopedAlterTime time(static_cast(i), AZ::TimeMs{ 0 }, 1.f, AzNetworking::InvalidConnectionId); EXPECT_EQ(i, test); } } @@ -69,7 +69,7 @@ namespace UnitTest { // Note that we didn't actually set any value for time rewindableBufferFrames, so we're testing fetching a value past the last time set - Multiplayer::ScopedAlterTime time(static_cast(RewindableBufferFrames), AZ::TimeMs{ 0 }, AzNetworking::InvalidConnectionId); + Multiplayer::ScopedAlterTime time(static_cast(RewindableBufferFrames), AZ::TimeMs{ 0 }, 1.f, AzNetworking::InvalidConnectionId); EXPECT_EQ(RewindableBufferFrames - 1, test); } } @@ -92,7 +92,7 @@ namespace UnitTest for (uint32_t i = 0; i < RewindableBufferFrames; ++i) { - Multiplayer::ScopedAlterTime time(static_cast(i), AZ::TimeMs{ 0 }, AzNetworking::InvalidConnectionId); + Multiplayer::ScopedAlterTime time(static_cast(i), AZ::TimeMs{ 0 }, 1.f, AzNetworking::InvalidConnectionId); const Object& value = test; EXPECT_EQ(value.value, i); } @@ -101,19 +101,19 @@ namespace UnitTest TEST_F(RewindableObjectTests, TestBackfillOnLargeTimestep) { Multiplayer::RewindableObject test(0); - Multiplayer::ScopedAlterTime time1(static_cast(0), AZ::TimeMs{ 0 }, AzNetworking::InvalidConnectionId); + Multiplayer::ScopedAlterTime time1(static_cast(0), AZ::TimeMs{ 0 }, 1.f, AzNetworking::InvalidConnectionId); test = 1; - Multiplayer::ScopedAlterTime time2(static_cast(31), AZ::TimeMs{ 0 }, AzNetworking::InvalidConnectionId); + Multiplayer::ScopedAlterTime time2(static_cast(31), AZ::TimeMs{ 0 }, 1.f, AzNetworking::InvalidConnectionId); test = 2; for (uint32_t i = 0; i < 31; ++i) { - Multiplayer::ScopedAlterTime time(static_cast(i), AZ::TimeMs{ 0 }, AzNetworking::InvalidConnectionId); + Multiplayer::ScopedAlterTime time(static_cast(i), AZ::TimeMs{ 0 }, 1.f, AzNetworking::InvalidConnectionId); EXPECT_EQ(1, test); } - Multiplayer::ScopedAlterTime time3(static_cast(31), AZ::TimeMs{ 0 }, AzNetworking::InvalidConnectionId); + Multiplayer::ScopedAlterTime time3(static_cast(31), AZ::TimeMs{ 0 }, 1.f, AzNetworking::InvalidConnectionId); EXPECT_EQ(2, test); } @@ -129,7 +129,7 @@ namespace UnitTest for (uint32_t i = 0; i < 1000; ++i) { - Multiplayer::ScopedAlterTime time(static_cast(1000 - i), AZ::TimeMs{ 0 }, AzNetworking::InvalidConnectionId); + Multiplayer::ScopedAlterTime time(static_cast(1000 - i), AZ::TimeMs{ 0 }, 1.f, AzNetworking::InvalidConnectionId); EXPECT_EQ(1000, test); } } From 5b148b1f40351098cfdabd89448caa33dfb00394 Mon Sep 17 00:00:00 2001 From: amzn-phist <52085794+amzn-phist@users.noreply.github.com> Date: Thu, 22 Jul 2021 17:37:44 -0500 Subject: [PATCH 021/160] Convert legacy XML handling to rapidxml Updates the Audio Controls Editor code to use rapidxml instead of legacy xml apis. Further makes improvements to path manipulations away from strings towards PathView apis and similar. Fixes some issues encountered with memory management when handling xml data that did not occur previously. Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com> --- .../Source/Editor/AudioSystemEditor_wwise.cpp | 207 +++++++--- .../Source/Editor/AudioSystemEditor_wwise.h | 4 +- .../Code/Source/Editor/AudioWwiseLoader.cpp | 21 +- .../Code/Include/Editor/ACETypes.h | 4 + .../Code/Include/Editor/IAudioSystemEditor.h | 8 +- .../Code/Include/Engine/ATLCommon.h | 1 + .../Code/Include/Engine/AudioFileUtils.h | 17 +- .../Code/Source/Editor/AudioControl.h | 53 ++- .../Editor/AudioControlsEditorWindow.cpp | 39 +- .../Source/Editor/AudioControlsLoader.cpp | 387 +++++++++--------- .../Code/Source/Editor/AudioControlsLoader.h | 11 +- .../Source/Editor/AudioControlsWriter.cpp | 183 ++++++--- .../Code/Source/Editor/AudioControlsWriter.h | 25 +- .../Source/Editor/QAudioControlEditorIcons.h | 4 +- .../Code/Source/Engine/ATLComponents.cpp | 8 +- 15 files changed, 571 insertions(+), 401 deletions(-) diff --git a/Gems/AudioEngineWwise/Code/Source/Editor/AudioSystemEditor_wwise.cpp b/Gems/AudioEngineWwise/Code/Source/Editor/AudioSystemEditor_wwise.cpp index 4dfafa132a..5bad3ecf1c 100644 --- a/Gems/AudioEngineWwise/Code/Source/Editor/AudioSystemEditor_wwise.cpp +++ b/Gems/AudioEngineWwise/Code/Source/Editor/AudioSystemEditor_wwise.cpp @@ -19,10 +19,7 @@ #include #include -#include -#include -#include -#include +#include void InitWwiseResources() { @@ -217,28 +214,34 @@ namespace AudioControls } //-------------------------------------------------------------------------------------------// - TConnectionPtr CAudioSystemEditor_wwise::CreateConnectionFromXMLNode(XmlNodeRef node, EACEControlType atlControlType) + TConnectionPtr CAudioSystemEditor_wwise::CreateConnectionFromXMLNode(AZ::rapidxml::xml_node* node, EACEControlType atlControlType) { if (node) { - const AZStd::string tag(node->getTag()); - TImplControlType type = TagToType(tag); + AZStd::string_view element(node->name()); + TImplControlType type = TagToType(element); if (type != AUDIO_IMPL_INVALID_TYPE) { - AZStd::string name(node->getAttr(Audio::WwiseXmlTags::WwiseNameAttribute)); - AZStd::string localized(node->getAttr(Audio::WwiseXmlTags::WwiseLocalizedAttribute)); + AZStd::string name; + AZStd::string_view localized; - // Legacy Preload support - if (localized.empty()) + if (auto nameAttr = node->first_attribute(Audio::WwiseXmlTags::WwiseNameAttribute, 0, false); + nameAttr != nullptr) { - localized = node->getAttr(Audio::WwiseXmlTags::Legacy::WwiseLocalizedAttribute); + name = nameAttr->value(); } - bool isLocalized = AZ::StringFunc::Equal(localized.c_str(), "true"); + if (auto localizedAttr = node->first_attribute(Audio::WwiseXmlTags::WwiseLocalizedAttribute, 0, false); + localizedAttr != nullptr) + { + localized = localizedAttr->value(); + } + + bool isLocalized = AZ::StringFunc::Equal(localized, "true"); - // If control not found, create a placeholder. - // We want to keep that connection even if it's not in the middleware. - // The user could be using the engine without the wwise project + // If the control wasn't found, create a placeholder. + // We want to see that connection even if it's not in the middleware. + // User could be viewing the editor without a middleware project. IAudioSystemControl* control = GetControlByName(name, isLocalized); if (!control) { @@ -250,27 +253,26 @@ namespace AudioControls } } - // If it's a switch we actually connect to one of the states within the switch + // If it's a switch we connect to one of the states within the switch if (type == eWCT_WWISE_SWITCH_GROUP || type == eWCT_WWISE_GAME_STATE_GROUP) { - if (node->getChildCount() == 1) + if (auto childNode = node->first_node(); + childNode != nullptr) { - node = node->getChild(0); - if (node) + AZStd::string childName; + if (auto childNameAttr = childNode->first_attribute(Audio::WwiseXmlTags::WwiseNameAttribute, 0, false); + childNameAttr != nullptr) { - AZStd::string childName(node->getAttr(Audio::WwiseXmlTags::WwiseNameAttribute)); + childName = childNameAttr->value(); + } - IAudioSystemControl* childControl = GetControlByName(childName, false, control); - if (!childControl) - { - childControl = CreateControl(SControlDef(childName, type == eWCT_WWISE_SWITCH_GROUP ? eWCT_WWISE_SWITCH : eWCT_WWISE_GAME_STATE, false, control)); - } - control = childControl; + IAudioSystemControl* childControl = GetControlByName(childName, false, control); + if (!childControl) + { + childControl = CreateControl(SControlDef( + childName, type == eWCT_WWISE_SWITCH_GROUP ? eWCT_WWISE_SWITCH : eWCT_WWISE_GAME_STATE, false, control)); } - } - else - { - CryWarning(VALIDATOR_MODULE_EDITOR, VALIDATOR_ERROR, "Audio Controls Editor (Wwise): Error reading connection to Wwise control %s", name.c_str()); + control = childControl; } } @@ -289,16 +291,19 @@ namespace AudioControls float mult = 1.0f; float shift = 0.0f; - if (node->haveAttr(Audio::WwiseXmlTags::WwiseMutiplierAttribute)) + + if (auto multAttr = node->first_attribute(Audio::WwiseXmlTags::WwiseMutiplierAttribute, 0, false); + multAttr != nullptr) { - const AZStd::string multProperty(node->getAttr(Audio::WwiseXmlTags::WwiseMutiplierAttribute)); - mult = AZStd::stof(multProperty); + mult = AZStd::stof(AZStd::string(multAttr->value())); } - if (node->haveAttr(Audio::WwiseXmlTags::WwiseShiftAttribute)) + + if (auto shiftAttr = node->first_attribute(Audio::WwiseXmlTags::WwiseShiftAttribute, 0, false); + shiftAttr != nullptr) { - const AZStd::string shiftProperty(node->getAttr(Audio::WwiseXmlTags::WwiseShiftAttribute)); - shift = AZStd::stof(shiftProperty); + shift = AZStd::stof(AZStd::string(shiftAttr->value())); } + connection->m_mult = mult; connection->m_shift = shift; return connection; @@ -308,11 +313,12 @@ namespace AudioControls TStateConnectionPtr connection = AZStd::make_shared(control->GetId()); float value = 0.0f; - if (node->haveAttr(Audio::WwiseXmlTags::WwiseValueAttribute)) + if (auto valueAttr = node->first_attribute(Audio::WwiseXmlTags::WwiseValueAttribute, 0, false); + valueAttr != nullptr) { - const AZStd::string valueProperty(node->getAttr(Audio::WwiseXmlTags::WwiseValueAttribute)); - value = AZStd::stof(valueProperty); + value = AZStd::stof(AZStd::string(valueAttr->value())); } + connection->m_value = value; return connection; } @@ -329,28 +335,50 @@ namespace AudioControls } //-------------------------------------------------------------------------------------------// - XmlNodeRef CAudioSystemEditor_wwise::CreateXMLNodeFromConnection(const TConnectionPtr connection, const EACEControlType atlControlType) + AZ::rapidxml::xml_node* CAudioSystemEditor_wwise::CreateXMLNodeFromConnection(const TConnectionPtr connection, const EACEControlType atlControlType) { const IAudioSystemControl* control = GetControl(connection->GetID()); if (control) { + XmlAllocator& xmlAllocator(AudioControls::s_xmlAllocator); + switch (control->GetType()) { case AudioControls::eWCT_WWISE_SWITCH: + [[fallthrough]]; case AudioControls::eWCT_WWISE_SWITCH_GROUP: + [[fallthrough]]; case AudioControls::eWCT_WWISE_GAME_STATE: + [[fallthrough]]; case AudioControls::eWCT_WWISE_GAME_STATE_GROUP: { const IAudioSystemControl* parent = control->GetParent(); if (parent) { - XmlNodeRef switchNode = GetISystem()->CreateXmlNode(TypeToTag(parent->GetType()).data()); - switchNode->setAttr(Audio::WwiseXmlTags::WwiseNameAttribute, parent->GetName().c_str()); - - XmlNodeRef stateNode = switchNode->createNode(Audio::WwiseXmlTags::WwiseValueTag); - stateNode->setAttr(Audio::WwiseXmlTags::WwiseNameAttribute, control->GetName().c_str()); - switchNode->addChild(stateNode); - + AZStd::string_view parentType = TypeToTag(parent->GetType()); + auto switchNode = xmlAllocator.allocate_node( + AZ::rapidxml::node_element, + xmlAllocator.allocate_string(parentType.data()) + ); + + auto switchNameAttr = xmlAllocator.allocate_attribute( + Audio::WwiseXmlTags::WwiseNameAttribute, + xmlAllocator.allocate_string(parent->GetName().c_str()) + ); + + auto stateNode = xmlAllocator.allocate_node( + AZ::rapidxml::node_element, + Audio::WwiseXmlTags::WwiseValueTag + ); + + auto stateNameAttr = xmlAllocator.allocate_attribute( + Audio::WwiseXmlTags::WwiseNameAttribute, + xmlAllocator.allocate_string(control->GetName().c_str()) + ); + + switchNode->append_attribute(switchNameAttr); + stateNode->append_attribute(stateNameAttr); + switchNode->append_node(stateNode); return switchNode; } break; @@ -358,51 +386,98 @@ namespace AudioControls case AudioControls::eWCT_WWISE_RTPC: { - XmlNodeRef connectionNode = GetISystem()->CreateXmlNode(TypeToTag(control->GetType()).data()); - connectionNode->setAttr(Audio::WwiseXmlTags::WwiseNameAttribute, control->GetName().c_str()); + auto connectionNode = xmlAllocator.allocate_node( + AZ::rapidxml::node_element, + xmlAllocator.allocate_string(TypeToTag(control->GetType()).data()) + ); + + auto nameAttr = xmlAllocator.allocate_attribute( + Audio::WwiseXmlTags::WwiseNameAttribute, + xmlAllocator.allocate_string(control->GetName().c_str()) + ); + + connectionNode->append_attribute(nameAttr); if (atlControlType == eACET_RTPC) { AZStd::shared_ptr rtpcConnection = AZStd::static_pointer_cast(connection); - if (rtpcConnection->m_mult != 1.0f) + if (rtpcConnection->m_mult != 1.f) { - connectionNode->setAttr(Audio::WwiseXmlTags::WwiseMutiplierAttribute, rtpcConnection->m_mult); + auto multAttr = xmlAllocator.allocate_attribute( + Audio::WwiseXmlTags::WwiseMutiplierAttribute, + xmlAllocator.allocate_string(AZStd::to_string(rtpcConnection->m_mult).c_str()) + ); + + connectionNode->append_attribute(multAttr); } - if (rtpcConnection->m_shift != 0.0f) + + if (rtpcConnection->m_shift != 0.f) { - connectionNode->setAttr(Audio::WwiseXmlTags::WwiseShiftAttribute, rtpcConnection->m_shift); + auto shiftAttr = xmlAllocator.allocate_attribute( + Audio::WwiseXmlTags::WwiseShiftAttribute, + xmlAllocator.allocate_string(AZStd::to_string(rtpcConnection->m_shift).c_str()) + ); + + connectionNode->append_attribute(shiftAttr); } } else if (atlControlType == eACET_SWITCH_STATE) { AZStd::shared_ptr stateConnection = AZStd::static_pointer_cast(connection); - connectionNode->setAttr(Audio::WwiseXmlTags::WwiseValueAttribute, stateConnection->m_value); + + auto valueAttr = xmlAllocator.allocate_attribute( + Audio::WwiseXmlTags::WwiseValueAttribute, + xmlAllocator.allocate_string(AZStd::to_string(stateConnection->m_value).c_str()) + ); + + connectionNode->append_attribute(valueAttr); } - return connectionNode; - } - case AudioControls::eWCT_WWISE_EVENT: - { - XmlNodeRef connectionNode = GetISystem()->CreateXmlNode(TypeToTag(control->GetType()).data()); - connectionNode->setAttr(Audio::WwiseXmlTags::WwiseNameAttribute, control->GetName().c_str()); return connectionNode; } + case AudioControls::eWCT_WWISE_EVENT: + [[fallthrough]]; case AudioControls::eWCT_WWISE_AUX_BUS: { - XmlNodeRef connectionNode = GetISystem()->CreateXmlNode(TypeToTag(control->GetType()).data()); - connectionNode->setAttr(Audio::WwiseXmlTags::WwiseNameAttribute, control->GetName().c_str()); + auto connectionNode = xmlAllocator.allocate_node( + AZ::rapidxml::node_element, + xmlAllocator.allocate_string(TypeToTag(control->GetType()).data()) + ); + + auto nameAttr = xmlAllocator.allocate_attribute( + Audio::WwiseXmlTags::WwiseNameAttribute, + xmlAllocator.allocate_string(control->GetName().c_str()) + ); + + connectionNode->append_attribute(nameAttr); return connectionNode; } case AudioControls::eWCT_WWISE_SOUND_BANK: { - XmlNodeRef connectionNode = GetISystem()->CreateXmlNode(TypeToTag(control->GetType()).data()); - connectionNode->setAttr(Audio::WwiseXmlTags::WwiseNameAttribute, control->GetName().c_str()); + auto connectionNode = xmlAllocator.allocate_node( + AZ::rapidxml::node_element, + xmlAllocator.allocate_string(TypeToTag(control->GetType()).data()) + ); + + auto nameAttr = xmlAllocator.allocate_attribute( + Audio::WwiseXmlTags::WwiseNameAttribute, + xmlAllocator.allocate_string(control->GetName().c_str()) + ); + + connectionNode->append_attribute(nameAttr); + if (control->IsLocalized()) { - connectionNode->setAttr(Audio::WwiseXmlTags::WwiseLocalizedAttribute, "true"); + auto locAttr = xmlAllocator.allocate_attribute( + Audio::WwiseXmlTags::WwiseLocalizedAttribute, + xmlAllocator.allocate_string("true") + ); + + connectionNode->append_attribute(locAttr); } + return connectionNode; } } diff --git a/Gems/AudioEngineWwise/Code/Source/Editor/AudioSystemEditor_wwise.h b/Gems/AudioEngineWwise/Code/Source/Editor/AudioSystemEditor_wwise.h index 14708a5816..25c621de76 100644 --- a/Gems/AudioEngineWwise/Code/Source/Editor/AudioSystemEditor_wwise.h +++ b/Gems/AudioEngineWwise/Code/Source/Editor/AudioSystemEditor_wwise.h @@ -77,8 +77,8 @@ namespace AudioControls EACEControlType ImplTypeToATLType(TImplControlType type) const override; TImplControlTypeMask GetCompatibleTypes(EACEControlType atlControlType) const override; TConnectionPtr CreateConnectionToControl(EACEControlType atlControlType, IAudioSystemControl* middlewareControl) override; - TConnectionPtr CreateConnectionFromXMLNode(XmlNodeRef node, EACEControlType atlControlType) override; - XmlNodeRef CreateXMLNodeFromConnection(const TConnectionPtr connection, const EACEControlType atlControlType) override; + TConnectionPtr CreateConnectionFromXMLNode(AZ::rapidxml::xml_node* node, EACEControlType atlControlType) override; + AZ::rapidxml::xml_node* CreateXMLNodeFromConnection(const TConnectionPtr connection, const EACEControlType atlControlType) override; const AZStd::string_view GetTypeIcon(TImplControlType type) const override; const AZStd::string_view GetTypeIconSelected(TImplControlType type) const override; AZStd::string GetName() const override; diff --git a/Gems/AudioEngineWwise/Code/Source/Editor/AudioWwiseLoader.cpp b/Gems/AudioEngineWwise/Code/Source/Editor/AudioWwiseLoader.cpp index 30320a567f..1a3ff121f8 100644 --- a/Gems/AudioEngineWwise/Code/Source/Editor/AudioWwiseLoader.cpp +++ b/Gems/AudioEngineWwise/Code/Source/Editor/AudioWwiseLoader.cpp @@ -17,12 +17,6 @@ #include #include -#include -#include -#include -#include - -using namespace PathUtil; namespace AudioControls { @@ -68,8 +62,7 @@ namespace AudioControls for (const auto& filePath : foundFiles) { AZ_Assert(AZ::IO::FileIOBase::GetInstance()->Exists(filePath.c_str()), "FindFiles found file '%s' but FileIO says it doesn't exist!", filePath.c_str()); - AZStd::string fileName; - AZ::StringFunc::Path::GetFullFileName(filePath.c_str(), fileName); + AZ::IO::PathView fileName = filePath.Filename(); if (AZ::IO::FileIOBase::GetInstance()->IsDirectory(filePath.c_str())) { @@ -79,15 +72,15 @@ namespace AudioControls // we load only one as all of them should have the // same content (in the future we want to have a // consistency report to highlight if this is not the case) - m_localizationFolder = fileName; + m_localizationFolder.assign(fileName.Native().data(), fileName.Native().size()); LoadSoundBanks(rootFolder, m_localizationFolder, true); isLocalizedLoaded = true; } } - else if (AZ::StringFunc::Find(fileName.c_str(), Audio::Wwise::BankExtension) != AZStd::string::npos - && !AZ::StringFunc::Equal(fileName.c_str(), Audio::Wwise::InitBank)) + else if (fileName.Extension() == Audio::Wwise::BankExtension && !AZ::StringFunc::Equal(fileName.Native(), Audio::Wwise::InitBank)) { - m_audioSystemImpl->CreateControl(SControlDef(fileName, eWCT_WWISE_SOUND_BANK, isLocalized, nullptr, subPath)); + m_audioSystemImpl->CreateControl( + SControlDef(AZStd::string{ fileName.Native() }, eWCT_WWISE_SOUND_BANK, isLocalized, nullptr, subPath)); } } } @@ -103,14 +96,14 @@ namespace AudioControls if (AZ::IO::FileIOBase::GetInstance()->IsDirectory(filePath.c_str())) { - LoadControlsInFolder(filePath); + LoadControlsInFolder(filePath.Native()); } else { // Open the file, read into an xmlDoc, and call LoadControls with the root xml node... AZ_TracePrintf("AudioWwiseLoader", "Loading Xml from '%s'", filePath.c_str()); - Audio::ScopedXmlLoader xmlFileLoader(filePath); + Audio::ScopedXmlLoader xmlFileLoader(filePath.Native()); if (!xmlFileLoader.HasError()) { LoadControl(xmlFileLoader.GetRootNode()); diff --git a/Gems/AudioSystem/Code/Include/Editor/ACETypes.h b/Gems/AudioSystem/Code/Include/Editor/ACETypes.h index cc1e35028c..0bfaa6640c 100644 --- a/Gems/AudioSystem/Code/Include/Editor/ACETypes.h +++ b/Gems/AudioSystem/Code/Include/Editor/ACETypes.h @@ -13,6 +13,7 @@ #include #include #include +#include namespace AudioControls { @@ -39,4 +40,7 @@ namespace AudioControls using FilepathSet = AZStd::set; + using XmlAllocator = AZ::rapidxml::memory_pool<>; + inline static XmlAllocator s_xmlAllocator; + } // namespace AudioControls diff --git a/Gems/AudioSystem/Code/Include/Editor/IAudioSystemEditor.h b/Gems/AudioSystem/Code/Include/Editor/IAudioSystemEditor.h index 5196e2f0bc..5a9c773a32 100644 --- a/Gems/AudioSystem/Code/Include/Editor/IAudioSystemEditor.h +++ b/Gems/AudioSystem/Code/Include/Editor/IAudioSystemEditor.h @@ -12,12 +12,10 @@ #include #include #include +#include #include -#include -#include - namespace AudioControls { class IAudioSystemEditor; @@ -117,14 +115,14 @@ namespace AudioControls //! @param node XML node where the connection is defined. //! @param atlControlType The type of the ATL control you are connecting to. //! @return A pointer to the newly created connection. - virtual TConnectionPtr CreateConnectionFromXMLNode(XmlNodeRef node, EACEControlType atlControlType) = 0; + virtual TConnectionPtr CreateConnectionFromXMLNode(AZ::rapidxml::xml_node* node, EACEControlType atlControlType) = 0; //! When serializing connections between controls this function will be called once per connection to serialize its properties. //! This function should be in sync with CreateConnectionToControl as whatever it's written here will have to be read there. //! @param connection Connection to serialize. //! @param atlControlType Type of the ATL control that has this connection. //! @return XML node with the connection serialized. - virtual XmlNodeRef CreateXMLNodeFromConnection(const TConnectionPtr connection, const EACEControlType atlControlType) = 0; + virtual AZ::rapidxml::xml_node* CreateXMLNodeFromConnection(const TConnectionPtr connection, const EACEControlType atlControlType) = 0; //! Whenever a connection is removed from an ATL control this function should be called. //! To keep the system informed of which controls have been connected and which ones haven't. diff --git a/Gems/AudioSystem/Code/Include/Engine/ATLCommon.h b/Gems/AudioSystem/Code/Include/Engine/ATLCommon.h index dae411fd00..45997b1262 100644 --- a/Gems/AudioSystem/Code/Include/Engine/ATLCommon.h +++ b/Gems/AudioSystem/Code/Include/Engine/ATLCommon.h @@ -47,6 +47,7 @@ namespace Audio static constexpr const char* ATLInternalNameAttribute = "atl_internal_name"; static constexpr const char* ATLTypeAttribute = "atl_type"; static constexpr const char* ATLConfigGroupAttribute = "atl_config_group_name"; + static constexpr const char* ATLPathAttribute = "path"; static constexpr const char* ATLDataLoadType = "AutoLoad"; diff --git a/Gems/AudioSystem/Code/Include/Engine/AudioFileUtils.h b/Gems/AudioSystem/Code/Include/Engine/AudioFileUtils.h index 5f071fef63..37952eaa1a 100644 --- a/Gems/AudioSystem/Code/Include/Engine/AudioFileUtils.h +++ b/Gems/AudioSystem/Code/Include/Engine/AudioFileUtils.h @@ -9,6 +9,7 @@ #pragma once #include +#include #include #include #include @@ -20,22 +21,26 @@ namespace Audio /*! * FindFilesInPath */ - static AZStd::vector FindFilesInPath(const AZStd::string_view folderPath, const char* filter) + static AZStd::vector FindFilesInPath(const AZStd::string_view folderPath, const char* filter) { - AZStd::vector foundFiles; + AZStd::vector foundFiles; AZ::IO::FileIOBase::FindFilesCallbackType findFilesCallback = [&foundFiles](const char* file) -> bool { - foundFiles.emplace_back(file); + foundFiles.emplace_back(AZ::IO::FixedMaxPath{ file }.LexicallyNormal()); return true; }; - auto fileIO = AZ::IO::FileIOBase::GetInstance(); - if (fileIO) + if (auto fileIO = AZ::IO::FileIOBase::GetInstance(); + fileIO != nullptr) { AZ::IO::Result result = fileIO->FindFiles(folderPath.data(), filter, findFilesCallback); + if (result == AZ::IO::ResultCode::Success) + { + return AZStd::move(foundFiles); + } } - return foundFiles; + return {}; } /*! diff --git a/Gems/AudioSystem/Code/Source/Editor/AudioControl.h b/Gems/AudioSystem/Code/Source/Editor/AudioControl.h index f7c856fb46..9335429fd4 100644 --- a/Gems/AudioSystem/Code/Source/Editor/AudioControl.h +++ b/Gems/AudioSystem/Code/Source/Editor/AudioControl.h @@ -11,13 +11,11 @@ #include #include +#include #include #include -#include -#include - namespace AudioControls { class CATLControlsModel; @@ -25,15 +23,52 @@ namespace AudioControls //-------------------------------------------------------------------------------------------// struct SRawConnectionData { - SRawConnectionData(XmlNodeRef node, bool isValid) - : m_xmlNode(node) - , m_isValid(isValid) - {} + SRawConnectionData(AZ::rapidxml::xml_node* node, bool isValid) + { + m_xmlNode = DeepCopyNode(node); + m_isValid = isValid; + } - XmlNodeRef m_xmlNode; + AZ::rapidxml::xml_node* m_xmlNode{ nullptr }; // indicates if the connection is valid for the currently loaded middleware - bool m_isValid; + bool m_isValid{ false }; + + // Rapid XML provides a 'copy_node' utility that will copy an entire node tree, + // but it only copies pointers of any strings in the node names and values. + // This causes problems with storing raw xml nodes as this class does because strings + // will be pointing into the memory pool of an xml document that has gone out of scope. + // This function is a rewritten version of 'copy_node' that does the deep copy of strings + // into the new destination tree. + static AZ::rapidxml::xml_node* DeepCopyNode(AZ::rapidxml::xml_node* srcNode) + { + AZ::rapidxml::xml_node* destNode = nullptr; + if (srcNode) + { + XmlAllocator& xmlAlloc(AudioControls::s_xmlAllocator); + destNode = xmlAlloc.allocate_node(srcNode->type()); + + destNode->name(xmlAlloc.allocate_string(srcNode->name(), srcNode->name_size()), srcNode->name_size()); + destNode->value(xmlAlloc.allocate_string(srcNode->value(), srcNode->value_size()), srcNode->value_size()); + + for (AZ::rapidxml::xml_node* child = srcNode->first_node(); child != nullptr; child = child->next_sibling()) + { + destNode->append_node(DeepCopyNode(child)); + } + + for (AZ::rapidxml::xml_attribute* attr = srcNode->first_attribute(); attr != nullptr; attr = attr->next_attribute()) + { + destNode->append_attribute(xmlAlloc.allocate_attribute( + xmlAlloc.allocate_string(attr->name(), attr->name_size()), + xmlAlloc.allocate_string(attr->value(), attr->value_size()), + attr->name_size(), + attr->value_size() + )); + } + } + + return destNode; + } }; using TXmlNodeList = AZStd::vector; diff --git a/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorWindow.cpp b/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorWindow.cpp index b352534510..d19cfe7adb 100644 --- a/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorWindow.cpp +++ b/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorWindow.cpp @@ -10,21 +10,31 @@ #include #include +#include + +#include + #include #include #include #include #include -#include -#include + + #include #include #include #include + + +#include +#include #include -#include #include +#include + + #include #include #include @@ -318,19 +328,24 @@ namespace AudioControls // once we can listen to delete messages from Asset system, this can be changed to an EBus handler. const char* controlsPath = nullptr; Audio::AudioSystemRequestBus::BroadcastResult(controlsPath, &Audio::AudioSystemRequestBus::Events::GetControlsPath); - AZStd::string sControlsPath(Path::GetEditingGameDataFolder()); - AZ::StringFunc::Path::Join(sControlsPath.c_str(), controlsPath, sControlsPath); - Audio::SAudioManagerRequestData oParseGlobalRequestData(sControlsPath.c_str(), Audio::eADS_GLOBAL); + + AZ::IO::FixedMaxPath controlsFolder{ controlsPath }; + + Audio::SAudioManagerRequestData oParseGlobalRequestData(controlsFolder.c_str(), Audio::eADS_GLOBAL); oConfigDataRequest.pData = &oParseGlobalRequestData; Audio::AudioSystemRequestBus::Broadcast(&Audio::AudioSystemRequestBus::Events::PushRequest, oConfigDataRequest); // parse the AudioSystem level-specific config data - AZStd::string levelName{ GetIEditor()->GetLevelName().toUtf8().data() }; - AZ::StringFunc::Path::Join(sControlsPath.c_str(), "levels", sControlsPath); - AZ::StringFunc::Path::Join(sControlsPath.c_str(), levelName.c_str(), sControlsPath); - Audio::SAudioManagerRequestData oParseLevelRequestData(sControlsPath.c_str(), Audio::eADS_LEVEL_SPECIFIC); - oConfigDataRequest.pData = &oParseLevelRequestData; - Audio::AudioSystemRequestBus::Broadcast(&Audio::AudioSystemRequestBus::Events::PushRequest, oConfigDataRequest); + AZStd::string levelName; + AzToolsFramework::EditorRequestBus::BroadcastResult(levelName, &AzToolsFramework::EditorRequests::GetLevelName); + if (!levelName.empty() && levelName != "Untitled") + { + controlsFolder /= "levels"; + controlsFolder /= levelName; + Audio::SAudioManagerRequestData oParseLevelRequestData(controlsFolder.c_str(), Audio::eADS_LEVEL_SPECIFIC); + oConfigDataRequest.pData = &oParseLevelRequestData; + Audio::AudioSystemRequestBus::Broadcast(&Audio::AudioSystemRequestBus::Events::PushRequest, oConfigDataRequest); + } // inform the middleware specific plugin that the data has been saved // to disk (in case it needs to update something) diff --git a/Gems/AudioSystem/Code/Source/Editor/AudioControlsLoader.cpp b/Gems/AudioSystem/Code/Source/Editor/AudioControlsLoader.cpp index c247abf855..e0eba868d6 100644 --- a/Gems/AudioSystem/Code/Source/Editor/AudioControlsLoader.cpp +++ b/Gems/AudioSystem/Code/Source/Editor/AudioControlsLoader.cpp @@ -11,26 +11,21 @@ #include #include +#include #include #include #include +#include #include #include #include #include -#include -#include -#include -#include -#include -#include +#include #include -using namespace PathUtil; - namespace AudioControls { //-------------------------------------------------------------------------------------------// @@ -91,100 +86,81 @@ namespace AudioControls { const CUndoSuspend suspendUndo; - // Get the partial path (relative under asset root) where the controls live. + // Get the relative path (under asset root) where the controls live. const char* controlsPath = nullptr; Audio::AudioSystemRequestBus::BroadcastResult(controlsPath, &Audio::AudioSystemRequestBus::Events::GetControlsPath); // Get the full path up to asset root. - AZStd::string controlsFullPath(Path::GetEditingGameDataFolder()); - AZ::StringFunc::Path::Join(controlsFullPath.c_str(), controlsPath, controlsFullPath); + AZ::IO::FixedMaxPath controlsFullPath = AZ::Utils::GetProjectPath(); + controlsFullPath /= controlsPath; // load the global controls - LoadAllLibrariesInFolder(controlsFullPath, ""); + LoadAllLibrariesInFolder(controlsFullPath.Native(), ""); + + AZ::IO::FixedMaxPath searchPath = controlsFullPath / LoaderStrings::LevelsSubFolder; - // load the level specific controls - auto cryPak = gEnv->pCryPak; + auto foundFiles = Audio::FindFilesInPath(searchPath.Native(), "*"); - AZStd::string searchMask; - AZ::StringFunc::Path::Join(controlsFullPath.c_str(), LoaderStrings::LevelsSubFolder, searchMask); - AZ::StringFunc::Path::Join(searchMask.c_str(), "*", searchMask, true, false); - AZ::IO::ArchiveFileIterator handle = cryPak->FindFirst(searchMask.c_str()); - if (handle) + for (const auto& file : foundFiles) { - do + if (AZ::IO::FileIOBase::GetInstance()->IsDirectory(file.c_str())) { - if ((handle.m_fileDesc.nAttrib & AZ::IO::FileDesc::Attribute::Subdirectory) == AZ::IO::FileDesc::Attribute::Subdirectory) + AZStd::string levelName{ file.Filename().Native() }; + LoadAllLibrariesInFolder(controlsFullPath.Native(), levelName); + + if (!m_atlControlsModel->ScopeExists(levelName)) { - AZStd::string_view name = handle.m_filename; - if (name != "." && name != "..") - { - LoadAllLibrariesInFolder(controlsFullPath, name); - if (!m_atlControlsModel->ScopeExists(name)) - { - // if the control doesn't exist it - // means it is not a real level in the - // project so it is flagged as LocalOnly - m_atlControlsModel->AddScope(name, true); - } - } + // If the scope doesn't exist it means it is not a real + // level in the project so it's flagged as LocalOnly + m_atlControlsModel->AddScope(levelName, true); } } - while (handle = cryPak->FindNext(handle)); - cryPak->FindClose(handle); } + CreateDefaultControls(); } //-------------------------------------------------------------------------------------------// void CAudioControlsLoader::LoadAllLibrariesInFolder(const AZStd::string_view folderPath, const AZStd::string_view level) { - AZStd::string path(folderPath); - if (path.back() != AZ_CORRECT_FILESYSTEM_SEPARATOR) - { - path.append(AZ_CORRECT_FILESYSTEM_SEPARATOR_STRING); - } + AZ::IO::FixedMaxPath searchPath{ folderPath }; if (!level.empty()) { - path.append(LoaderStrings::LevelsSubFolder); - path.append(GetSlash()); - path.append(level); - path.append(AZ_CORRECT_FILESYSTEM_SEPARATOR_STRING); + searchPath /= LoaderStrings::LevelsSubFolder; + searchPath /= level; } - AZStd::string searchPath = path + "*.xml"; - auto cryPak = gEnv->pCryPak; - AZ::IO::ArchiveFileIterator handle = cryPak->FindFirst(searchPath.c_str()); - if (handle) + auto foundFiles = Audio::FindFilesInPath(searchPath.Native(), "*.xml"); + + for (auto& file : foundFiles) { - do + Audio::ScopedXmlLoader xmlLoader(file.Native()); + if (xmlLoader.HasError()) { - AZStd::string filename = path + AZStd::string{ static_cast(handle.m_filename) }; - AZ::StringFunc::Path::Normalize(filename); - XmlNodeRef root = GetISystem()->LoadXmlFromFile(filename.c_str()); - if (root) + AZ_Warning("AudioControlsLoader", false, "Unable to load the xml file '%s'", file.c_str()); + continue; + } + + auto xmlRootNode = xmlLoader.GetRootNode(); + if (xmlRootNode && azstricmp(xmlRootNode->name(), Audio::ATLXmlTags::RootNodeTag) == 0) + { + AZ::IO::PathView fileName = file.Filename(); + + AZStd::to_lower(file.Native().begin(), file.Native().end()); + m_loadedFilenames.insert(file.c_str()); + + if (auto nameAttr = xmlRootNode->first_attribute(Audio::ATLXmlTags::ATLNameAttribute, 0, false); nameAttr != nullptr) { - AZStd::string tag = root->getTag(); - if (tag == Audio::ATLXmlTags::RootNodeTag) - { - AZStd::to_lower(filename.begin(), filename.end()); - m_loadedFilenames.insert(filename.c_str()); - AZStd::string file = static_cast(handle.m_filename); - if (root->haveAttr(Audio::ATLXmlTags::ATLNameAttribute)) - { - file = root->getAttr(Audio::ATLXmlTags::ATLNameAttribute); - } - AZ::StringFunc::Path::StripExtension(file); - LoadControlsLibrary(root, folderPath, level, file); - } + fileName = nameAttr->value(); } else { - CryWarning(VALIDATOR_MODULE_EDITOR, VALIDATOR_ERROR, "(Audio Controls Editor) Failed parsing ATL Library '%s'", filename.c_str()); + fileName = fileName.Stem(); } - } while (handle = cryPak->FindNext(handle)); - cryPak->FindClose(handle); + LoadControlsLibrary(xmlRootNode, folderPath, level, fileName.Native()); + } } } @@ -233,74 +209,93 @@ namespace AudioControls } //-------------------------------------------------------------------------------------------// - void CAudioControlsLoader::LoadControlsLibrary(XmlNodeRef rootNode, [[maybe_unused]] const AZStd::string_view filePath, const AZStd::string_view level, const AZStd::string_view fileName) + void CAudioControlsLoader::LoadControlsLibrary( + const AZ::rapidxml::xml_node* rootNode, + [[maybe_unused]] const AZStd::string_view filePath, + const AZStd::string_view level, + const AZStd::string_view fileName) { QStandardItem* rootFolderItem = AddUniqueFolderPath(m_layoutModel->invisibleRootItem(), QString(fileName.data())); if (rootFolderItem && rootNode) { - const int numControlTypes = rootNode->getChildCount(); - for (int i = 0; i < numControlTypes; ++i) + auto controlTypeNode = rootNode->first_node(); // e.g. "AudioTriggers", "AudioRtpcs", etc + while (controlTypeNode) { - XmlNodeRef node = rootNode->getChild(i); - const int numControls = node->getChildCount(); - for (int j = 0; j < numControls; ++j) + auto controlNode = controlTypeNode->first_node(); // e.g. "ATLTrigger", "ATLRtpc", etc + while (controlNode) { - LoadControl(node->getChild(j), rootFolderItem, level); + LoadControl(controlNode, rootFolderItem, level); + controlNode = controlNode->next_sibling(); } + controlTypeNode = controlTypeNode->next_sibling(); } } } //-------------------------------------------------------------------------------------------// - CATLControl* CAudioControlsLoader::LoadControl(XmlNodeRef node, QStandardItem* folderItem, const AZStd::string_view scope) + CATLControl* CAudioControlsLoader::LoadControl(AZ::rapidxml::xml_node* node, QStandardItem* folderItem, const AZStd::string_view scope) { CATLControl* control = nullptr; - if (node) + + AZStd::string controlPath; + if (auto controlPathAttr = node->first_attribute("path", 0, false); + controlPathAttr != nullptr) { - QStandardItem* parentItem = AddUniqueFolderPath(folderItem, QString(node->getAttr(LoaderStrings::PathAttribute))); - if (parentItem) + controlPath = controlPathAttr->value(); + } + + QStandardItem* parentItem = AddUniqueFolderPath(folderItem, QString(controlPath.c_str())); + if (parentItem) + { + AZStd::string name; + if (auto nameAttr = node->first_attribute(Audio::ATLXmlTags::ATLNameAttribute, 0, false); + nameAttr != nullptr) { - const AZStd::string name = node->getAttr(Audio::ATLXmlTags::ATLNameAttribute); - const EACEControlType controlType = TagToType(node->getTag()); + name = nameAttr->value(); + } + + const EACEControlType controlType = TagToType(node->name()); - control = m_atlControlsModel->CreateControl(name, controlType); - if (control) + control = m_atlControlsModel->CreateControl(name, controlType); + if (control) + { + QStandardItem* item = new QAudioControlItem(QString(control->GetName().c_str()), control); + if (item) { - QStandardItem* item = new QAudioControlItem(QString(control->GetName().c_str()), control); - if (item) - { - parentItem->appendRow(item); - } + parentItem->appendRow(item); + } - switch (controlType) + switch (controlType) + { + case eACET_SWITCH: { - case eACET_SWITCH: + auto switchStateNode = node->first_node(); + while (switchStateNode) { - const int numStates = node->getChildCount(); - for (int i = 0; i < numStates; ++i) + CATLControl* stateControl = LoadControl(switchStateNode, item, scope); + if (stateControl) { - CATLControl* stateControl = LoadControl(node->getChild(i), item, scope); - if (stateControl) - { - stateControl->SetParent(control); - control->AddChild(stateControl); - } + stateControl->SetParent(control); + control->AddChild(stateControl); } - break; - } - case eACET_PRELOAD: - { - LoadPreloadConnections(node, control); - break; - } - default: - { - LoadConnections(node, control); - break; + + switchStateNode = switchStateNode->next_sibling(); } + break; + } + case eACET_PRELOAD: + { + LoadPreloadConnections(node, control); + break; + } + default: + { + LoadConnections(node, control); + break; } - control->SetScope(scope); } + + control->SetScope(scope); } } @@ -310,44 +305,37 @@ namespace AudioControls //-------------------------------------------------------------------------------------------// void CAudioControlsLoader::LoadScopes() { - AZStd::string levelsFolderPath; - AZ::StringFunc::Path::Join(Path::GetEditingGameDataFolder().c_str(), LoaderStrings::LevelsSubFolder, levelsFolderPath); - LoadScopesImpl(levelsFolderPath); + AZ::IO::FixedMaxPath levelsFolderPath = AZ::Utils::GetProjectPath(); + levelsFolderPath /= "Levels"; + LoadScopesImpl(levelsFolderPath.Native()); } //-------------------------------------------------------------------------------------------// void CAudioControlsLoader::LoadScopesImpl(const AZStd::string_view levelsFolder) { - AZStd::string search; - AZ::StringFunc::Path::Join(levelsFolder.data(), "*", search, true, false); - auto cryPak = gEnv->pCryPak; - AZ::IO::ArchiveFileIterator handle = cryPak->FindFirst(search.c_str()); - if (handle) + auto fileIO = AZ::IO::FileIOBase::GetInstance(); + AZ::IO::FixedMaxPath searchPath{ levelsFolder }; + + auto foundFiles = Audio::FindFilesInPath(searchPath.Native(), "*"); + for (auto& file : foundFiles) { - do + AZ::IO::PathView filePath{ file }; + AZ::IO::PathView fileName = filePath.Filename(); + if (fileIO->IsDirectory(filePath.Native().data())) { - AZStd::string name = static_cast(handle.m_filename); - if (name != "." && name != ".." && !name.empty()) + LoadScopesImpl((searchPath / fileName).Native()); + } + else + { + AZ::IO::PathView fileExt = filePath.Extension(); + if (fileExt == ".ly" || fileExt == ".cry" || fileExt == ".prefab") { - if ((handle.m_fileDesc.nAttrib & AZ::IO::FileDesc::Attribute::Subdirectory) == AZ::IO::FileDesc::Attribute::Subdirectory) - { - AZ::StringFunc::Path::Join(levelsFolder.data(), name.c_str(), search); - LoadScopesImpl(search); - } - else - { - AZStd::string extension; - AZ::StringFunc::Path::GetExtension(name.c_str(), extension, false); - if (extension.compare("cry") == 0 || extension.compare("ly") == 0) - { - AZ::StringFunc::Path::StripExtension(name); - m_atlControlsModel->AddScope(name); - } - } + AZ::IO::PathView fileStem = filePath.Stem(); + // May need to verify that .prefabs are the actual "level" prefab + // i.e. that it matches levels//.prefab + m_atlControlsModel->AddScope(fileStem.Native()); } } - while (handle = cryPak->FindNext(handle)); - cryPak->FindClose(handle); } } @@ -475,100 +463,80 @@ namespace AudioControls } //-------------------------------------------------------------------------------------------// - void CAudioControlsLoader::LoadConnections(XmlNodeRef rootNode, CATLControl* control) + void CAudioControlsLoader::LoadConnections(AZ::rapidxml::xml_node* rootNode, CATLControl* control) { - if (!rootNode || !control) - { - return; - } - - const int numChildren = rootNode->getChildCount(); - for (int i = 0; i < numChildren; ++i) + if (control && rootNode && m_audioSystemImpl) { - XmlNodeRef node = rootNode->getChild(i); - const AZStd::string tag = node->getTag(); - if (m_audioSystemImpl) + auto childNode = rootNode->first_node(); + while (childNode) { - TConnectionPtr connection = m_audioSystemImpl->CreateConnectionFromXMLNode(node, control->GetType()); + TConnectionPtr connection = m_audioSystemImpl->CreateConnectionFromXMLNode(childNode, control->GetType()); if (connection) { control->AddConnection(connection); } - control->m_connectionNodes.push_back(SRawConnectionData(node, connection != nullptr)); + + control->m_connectionNodes.push_back(SRawConnectionData(childNode, connection != nullptr)); + + childNode = childNode->next_sibling(); } } } //-------------------------------------------------------------------------------------------// - void CAudioControlsLoader::LoadPreloadConnections(XmlNodeRef node, CATLControl* control) + void CAudioControlsLoader::LoadPreloadConnections(AZ::rapidxml::xml_node* node, CATLControl* control) { - if (!node || !control) + if (!control || !node || !m_audioSystemImpl) { return; } - AZStd::string type = node->getAttr(Audio::ATLXmlTags::ATLTypeAttribute); - if (type.compare(Audio::ATLXmlTags::ATLDataLoadType) == 0) + AZStd::string type; + if (auto typeAttr = node->first_attribute(Audio::ATLXmlTags::ATLTypeAttribute, 0, false); + typeAttr != nullptr) { - control->SetAutoLoad(true); - } - else - { - control->SetAutoLoad(false); + type = typeAttr->value(); } - // Legacy Preload XML parsing... - // Read all the platform definitions for this control - XmlNodeRef platformsGroupNode = node->findChild(Audio::ATLXmlTags::ATLPlatformsTag); - if (platformsGroupNode) + control->SetAutoLoad(type == Audio::ATLXmlTags::ATLDataLoadType); + + auto platformGroupNode = node->first_node(Audio::ATLXmlTags::ATLPlatformsTag, 0, false); + if (platformGroupNode) { + // Legacy preload parsing... // Don't parse the platform groups xml chunk anymore. // Read the connection information for all connected preloads... - const int numChildren = node->getChildCount(); - for (int i = 0; i < numChildren; ++i) + auto configGroupNode = node->first_node(Audio::ATLXmlTags::ATLConfigGroupTag, 0, false); + while (configGroupNode) { - XmlNodeRef groupNode = node->getChild(i); - const AZStd::string tag = groupNode->getTag(); - if (tag.compare(Audio::ATLXmlTags::ATLConfigGroupTag) != 0) - { - continue; - } - - const AZStd::string groupName = groupNode->getAttr(Audio::ATLXmlTags::ATLNameAttribute); - const int numConnections = groupNode->getChildCount(); - for (int j = 0; j < numConnections; ++j) + auto connectionNode = configGroupNode->first_node(); + while (connectionNode) { - XmlNodeRef connectionNode = groupNode->getChild(j); - if (connectionNode && m_audioSystemImpl) + TConnectionPtr connection = m_audioSystemImpl->CreateConnectionFromXMLNode(connectionNode, control->GetType()); + if (connection) { - TConnectionPtr connection = m_audioSystemImpl->CreateConnectionFromXMLNode(connectionNode, control->GetType()); - if (connection) - { - control->AddConnection(connection); - } - control->m_connectionNodes.push_back(SRawConnectionData(connectionNode, connection != nullptr)); + control->AddConnection(connection); } + control->m_connectionNodes.push_back(SRawConnectionData(connectionNode, connection != nullptr)); + connectionNode = connectionNode->next_sibling(); } + configGroupNode = configGroupNode->next_sibling(); } } else { - // New Preload XML parsing... - const int numChildren = node->getChildCount(); - for (int i = 0; i < numChildren; ++i) + // New format preload parsing... + auto connectionNode = node->first_node(); + while (connectionNode) { - XmlNodeRef connectionNode = node->getChild(i); - if (connectionNode && m_audioSystemImpl) + TConnectionPtr connection = m_audioSystemImpl->CreateConnectionFromXMLNode(connectionNode, control->GetType()); + if (connection) { - TConnectionPtr connection = m_audioSystemImpl->CreateConnectionFromXMLNode(connectionNode, control->GetType()); - if (connection) - { - control->AddConnection(connection); - } - - control->m_connectionNodes.push_back(SRawConnectionData(connectionNode, connection != nullptr)); + control->AddConnection(connection); } + control->m_connectionNodes.push_back(SRawConnectionData(connectionNode, connection != nullptr)); + connectionNode = connectionNode->next_sibling(); } } } @@ -586,15 +554,28 @@ namespace AudioControls } //-------------------------------------------------------------------------------------------// - CATLControl* CAudioControlsLoader::CreateInternalSwitchState(CATLControl* parentControl, const AZStd::string& switchName, const AZStd::string& stateName) + CATLControl* CAudioControlsLoader::CreateInternalSwitchState(CATLControl* parentControl, [[maybe_unused]] const AZStd::string& switchName, const AZStd::string& stateName) { CATLControl* childControl = m_atlControlsModel->CreateControl(stateName, eACET_SWITCH_STATE, parentControl); - XmlNodeRef requestNode = GetISystem()->CreateXmlNode(Audio::ATLXmlTags::ATLSwitchRequestTag); - requestNode->setAttr(Audio::ATLXmlTags::ATLNameAttribute, switchName.c_str()); - XmlNodeRef valueNode = requestNode->createNode(Audio::ATLXmlTags::ATLValueTag); - valueNode->setAttr(Audio::ATLXmlTags::ATLNameAttribute, stateName.c_str()); - requestNode->addChild(valueNode); + XmlAllocator& xmlAlloc(AudioControls::s_xmlAllocator); + AZ::rapidxml::xml_node* requestNode = + xmlAlloc.allocate_node(AZ::rapidxml::node_element, xmlAlloc.allocate_string(Audio::ATLXmlTags::ATLSwitchRequestTag)); + + AZ::rapidxml::xml_attribute* switchNameAttr = xmlAlloc.allocate_attribute( + xmlAlloc.allocate_string(Audio::ATLXmlTags::ATLNameAttribute), xmlAlloc.allocate_string(switchName.c_str())); + + requestNode->append_attribute(switchNameAttr); + + AZ::rapidxml::xml_node* valueNode = + xmlAlloc.allocate_node(AZ::rapidxml::node_element, xmlAlloc.allocate_string(Audio::ATLXmlTags::ATLValueTag)); + + AZ::rapidxml::xml_attribute* stateNameAttr = xmlAlloc.allocate_attribute( + xmlAlloc.allocate_string(Audio::ATLXmlTags::ATLNameAttribute), xmlAlloc.allocate_string(stateName.c_str())); + + valueNode->append_attribute(stateNameAttr); + + requestNode->append_node(valueNode); childControl->m_connectionNodes.push_back(SRawConnectionData(requestNode, false)); return childControl; diff --git a/Gems/AudioSystem/Code/Source/Editor/AudioControlsLoader.h b/Gems/AudioSystem/Code/Source/Editor/AudioControlsLoader.h index bee55289e3..290327b946 100644 --- a/Gems/AudioSystem/Code/Source/Editor/AudioControlsLoader.h +++ b/Gems/AudioSystem/Code/Source/Editor/AudioControlsLoader.h @@ -10,12 +10,11 @@ #pragma once #include +#include #include #include -#include - #include class QStandardItemModel; @@ -38,11 +37,11 @@ namespace AudioControls private: void LoadAllLibrariesInFolder(const AZStd::string_view folderPath, const AZStd::string_view level); - void LoadControlsLibrary(XmlNodeRef rootNode, const AZStd::string_view filePath, const AZStd::string_view level, const AZStd::string_view fileName); - CATLControl* LoadControl(XmlNodeRef node, QStandardItem* folderItem, const AZStd::string_view scope); + void LoadControlsLibrary(const AZ::rapidxml::xml_node* rootNode, const AZStd::string_view filePath, const AZStd::string_view level, const AZStd::string_view fileName); + CATLControl* LoadControl(AZ::rapidxml::xml_node* node, QStandardItem* folderItem, const AZStd::string_view scope); - void LoadPreloadConnections(XmlNodeRef node, CATLControl* control); - void LoadConnections(XmlNodeRef rootNode, CATLControl* control); + void LoadPreloadConnections(AZ::rapidxml::xml_node* node, CATLControl* control); + void LoadConnections(AZ::rapidxml::xml_node* rootNode, CATLControl* control); void CreateDefaultControls(); QStandardItem* AddControl(CATLControl* control, QStandardItem* folderItem); diff --git a/Gems/AudioSystem/Code/Source/Editor/AudioControlsWriter.cpp b/Gems/AudioSystem/Code/Source/Editor/AudioControlsWriter.cpp index bb7409e179..80f05804f1 100644 --- a/Gems/AudioSystem/Code/Source/Editor/AudioControlsWriter.cpp +++ b/Gems/AudioSystem/Code/Source/Editor/AudioControlsWriter.cpp @@ -9,29 +9,28 @@ #include +#include +#include #include #include +#include +#include #include #include -#include #include #include #include + #include #include #include -#include -#include -#include #include #include #include -using namespace PathUtil; - namespace AudioControls { namespace WriterStrings @@ -80,6 +79,18 @@ namespace AudioControls index = index.sibling(++i, 0); } + auto fileIO = AZ::IO::FileIOBase::GetInstance(); + AZStd::for_each( + m_foundLibraryPaths.begin(), m_foundLibraryPaths.end(), + [fileIO](AZStd::string& libraryPath) -> void + { + AZStd::optional newLength = fileIO->ConvertToAlias(libraryPath.data(), libraryPath.size()); + if (newLength) + { + libraryPath.resize_no_construct(*newLength); + } + AZStd::to_lower(libraryPath.begin(), libraryPath.end()); + }); // Delete libraries that don't exist anymore from disk FilepathSet librariesToDelete; @@ -103,7 +114,10 @@ namespace AudioControls //-------------------------------------------------------------------------------------------// void CAudioControlsWriter::WriteLibrary(const AZStd::string_view libraryName, QModelIndex root) { - if (root.isValid()) + const char* controlsPath = nullptr; + Audio::AudioSystemRequestBus::BroadcastResult(controlsPath, &Audio::AudioSystemRequestBus::Events::GetControlsPath); + + if (root.isValid() && controlsPath) { TLibraryStorage library; int i = 0; @@ -114,68 +128,63 @@ namespace AudioControls child = root.model()->index(++i, 0, root); } - const char* controlsPath = nullptr; - Audio::AudioSystemRequestBus::BroadcastResult(controlsPath, &Audio::AudioSystemRequestBus::Events::GetControlsPath); - for (auto& libraryPair : library) { - AZStd::string libraryPath; + AZ::IO::FixedMaxPath libraryPath{ controlsPath }; const AZStd::string& scope = libraryPair.first; if (scope.empty()) { // no scope, file at the root level - libraryPath.append(controlsPath); - AZ::StringFunc::Path::Join(libraryPath.c_str(), libraryName.data(), libraryPath); - libraryPath.append(WriterStrings::LibraryExtension); + libraryPath /= libraryName; + libraryPath.ReplaceExtension(WriterStrings::LibraryExtension); } else { // with scope, inside level folder - libraryPath.append(controlsPath); - libraryPath.append(WriterStrings::LevelsSubFolder); - AZ::StringFunc::Path::Join(libraryPath.c_str(), scope.c_str(), libraryPath); - AZ::StringFunc::Path::Join(libraryPath.c_str(), libraryName.data(), libraryPath); - libraryPath.append(WriterStrings::LibraryExtension); + libraryPath /= AZ::IO::FixedMaxPath{ WriterStrings::LevelsSubFolder } / scope / libraryName; + libraryPath.ReplaceExtension(WriterStrings::LibraryExtension); } - // should be able to change this back to GamePathToFullPath once a path normalization bug has been fixed: - AZStd::string fullFilePath; - AZ::StringFunc::Path::Join(Path::GetEditingGameDataFolder().c_str(), libraryPath.c_str(), fullFilePath); - AZStd::to_lower(fullFilePath.begin(), fullFilePath.end()); + AZ::IO::FixedMaxPath fullFilePath = AZ::Utils::GetProjectPath(); + fullFilePath /= libraryPath; m_foundLibraryPaths.insert(fullFilePath.c_str()); const SLibraryScope& libScope = libraryPair.second; if (libScope.m_isDirty) { - XmlNodeRef fileNode = GetISystem()->CreateXmlNode(Audio::ATLXmlTags::RootNodeTag); - fileNode->setAttr(Audio::ATLXmlTags::ATLNameAttribute, libraryName.data()); + XmlAllocator& xmlAlloc(AudioControls::s_xmlAllocator); + AZ::rapidxml::xml_node* fileNode = + xmlAlloc.allocate_node(AZ::rapidxml::node_element, xmlAlloc.allocate_string(Audio::ATLXmlTags::RootNodeTag)); + + AZ::rapidxml::xml_attribute* nameAttr = xmlAlloc.allocate_attribute( + xmlAlloc.allocate_string(Audio::ATLXmlTags::ATLNameAttribute), xmlAlloc.allocate_string(libraryName.data())); + + fileNode->append_attribute(nameAttr); for (int ii = 0; ii < eACET_NUM_TYPES; ++ii) { - if (ii != eACET_SWITCH_STATE) // switch_states are written inside the switches + if (libScope.m_nodes[ii] && libScope.m_nodes[ii]->first_node() != nullptr) { - if (libScope.m_nodes[ii]->getChildCount() > 0) - { - fileNode->addChild(libScope.m_nodes[ii]); - } + fileNode->append_node(libScope.m_nodes[ii]); } } - if (QFileInfo::exists(fullFilePath.c_str())) + if (auto fileInfo = QFileInfo(fullFilePath.c_str()); + fileInfo.exists()) { - const DWORD fileAttributes = GetFileAttributes(fullFilePath.c_str()); - if (fileAttributes & FILE_ATTRIBUTE_READONLY) + if (!fileInfo.isWritable()) { - // file is read-only - CheckOutFile(fullFilePath); + // file exists and is read-only + CheckOutFile(fullFilePath.Native()); } - fileNode->saveToFile(fullFilePath.c_str()); + + [[maybe_unused]] bool writeOk = WriteXmlToFile(fullFilePath.Native(), fileNode); } else { - // save the file, CheckOutFile will add it, since it's new - fileNode->saveToFile(fullFilePath.c_str()); - CheckOutFile(fullFilePath); + // since it's a new file, save the file first, CheckOutFile will add it + [[maybe_unused]] bool writeOk = WriteXmlToFile(fullFilePath.Native(), fileNode); + CheckOutFile(fullFilePath.Native()); } } } @@ -249,14 +258,63 @@ namespace AudioControls } //-------------------------------------------------------------------------------------------// - void CAudioControlsWriter::WriteControlToXml(XmlNodeRef node, CATLControl* control, const AZStd::string_view path) + bool CAudioControlsWriter::WriteXmlToFile(const AZStd::string_view filepath, AZ::rapidxml::xml_node* rootNode) { + if (!rootNode) + { + return false; + } + + using namespace AZ::IO; + AZStd::string docString; + ByteContainerStream stringStream(&docString); + + AZ::rapidxml::xml_document xmlDoc; + xmlDoc.append_node(rootNode); + + RapidXMLStreamWriter streamWriter(&stringStream); + AZ::rapidxml::print(streamWriter.Iterator(), xmlDoc); + streamWriter.FlushCache(); + + constexpr int openMode = + (SystemFile::SF_OPEN_WRITE_ONLY | SystemFile::SF_OPEN_CREATE | SystemFile::SF_OPEN_CREATE_PATH); + + if (SystemFile fileOut; + fileOut.Open(filepath.data(), openMode)) + { + auto bytesWritten = fileOut.Write(docString.data(), docString.size()); + return (bytesWritten == docString.size()); + } + return false; + } + + //-------------------------------------------------------------------------------------------// + void CAudioControlsWriter::WriteControlToXml(AZ::rapidxml::xml_node* node, CATLControl* control, const AZStd::string_view path) + { + if (!node || !control) + { + return; + } + + XmlAllocator& xmlAlloc(AudioControls::s_xmlAllocator); + const EACEControlType type = control->GetType(); - XmlNodeRef childNode = node->createNode(TypeToTag(type).data()); - childNode->setAttr(Audio::ATLXmlTags::ATLNameAttribute, control->GetName().c_str()); + AZStd::string_view typeName = TypeToTag(type); + + AZ::rapidxml::xml_node* childNode = + xmlAlloc.allocate_node(AZ::rapidxml::node_element, xmlAlloc.allocate_string(typeName.data())); + + AZ::rapidxml::xml_attribute* nameAttr = xmlAlloc.allocate_attribute( + xmlAlloc.allocate_string(Audio::ATLXmlTags::ATLNameAttribute), xmlAlloc.allocate_string(control->GetName().c_str())); + + childNode->append_attribute(nameAttr); + if (!path.empty()) { - childNode->setAttr("path", path.data()); + AZ::rapidxml::xml_attribute* pathAttr = xmlAlloc.allocate_attribute( + xmlAlloc.allocate_string(Audio::ATLXmlTags::ATLPathAttribute), xmlAlloc.allocate_string(path.data())); + + childNode->append_attribute(pathAttr); } if (type == eACET_SWITCH) @@ -271,7 +329,11 @@ namespace AudioControls { if (control->IsAutoLoad()) { - childNode->setAttr(Audio::ATLXmlTags::ATLTypeAttribute, Audio::ATLXmlTags::ATLDataLoadType); + AZ::rapidxml::xml_attribute* loadAttr = xmlAlloc.allocate_attribute( + xmlAlloc.allocate_string(Audio::ATLXmlTags::ATLTypeAttribute), + xmlAlloc.allocate_string(Audio::ATLXmlTags::ATLDataLoadType)); + + childNode->append_attribute(loadAttr); } // New Preloads XML... @@ -282,38 +344,39 @@ namespace AudioControls WriteConnectionsToXml(childNode, control); } - node->addChild(childNode); + node->append_node(childNode); } //-------------------------------------------------------------------------------------------// - void CAudioControlsWriter::WriteConnectionsToXml(XmlNodeRef node, CATLControl* control) + void CAudioControlsWriter::WriteConnectionsToXml(AZ::rapidxml::xml_node* node, CATLControl* control) { - if (control && m_audioSystemImpl) + if (node && control && m_audioSystemImpl) { TXmlNodeList otherNodes = control->m_connectionNodes; - auto end = AZStd::remove_if(otherNodes.begin(), otherNodes.end(), - [](const SRawConnectionData& node) + auto end = AZStd::remove_if( + otherNodes.begin(), otherNodes.end(), + [](const SRawConnectionData& connection) { - return node.m_isValid; + return connection.m_isValid; } ); otherNodes.erase(end, otherNodes.end()); for (auto& connectionNode : otherNodes) { - node->addChild(connectionNode.m_xmlNode); + node->append_node(SRawConnectionData::DeepCopyNode(connectionNode.m_xmlNode)); } const size_t size = control->ConnectionCount(); for (size_t i = 0; i < size; ++i) { - TConnectionPtr connection = control->GetConnectionAt(i); - if (connection) + if (TConnectionPtr connection = control->GetConnectionAt(i); + connection != nullptr) { - XmlNodeRef childNode = m_audioSystemImpl->CreateXMLNodeFromConnection(connection, control->GetType()); - if (childNode) + if (auto childNode = m_audioSystemImpl->CreateXMLNodeFromConnection(connection, control->GetType()); + childNode != nullptr) { - node->addChild(childNode); + node->append_node(childNode); control->m_connectionNodes.push_back(SRawConnectionData(childNode, true)); } } @@ -322,24 +385,24 @@ namespace AudioControls } //-------------------------------------------------------------------------------------------// - void CAudioControlsWriter::CheckOutFile(const AZStd::string& filepath) + void CAudioControlsWriter::CheckOutFile(const AZStd::string_view filepath) { IEditor* editor = GetIEditor(); IFileUtil* fileUtil = editor ? editor->GetFileUtil() : nullptr; if (fileUtil) { - fileUtil->CheckoutFile(filepath.c_str(), nullptr); + fileUtil->CheckoutFile(filepath.data(), nullptr); } } //-------------------------------------------------------------------------------------------// - void CAudioControlsWriter::DeleteLibraryFile(const AZStd::string& filepath) + void CAudioControlsWriter::DeleteLibraryFile(const AZStd::string_view filepath) { IEditor* editor = GetIEditor(); IFileUtil* fileUtil = editor ? editor->GetFileUtil() : nullptr; if (fileUtil) { - fileUtil->DeleteFromSourceControl(filepath.c_str(), nullptr); + fileUtil->DeleteFromSourceControl(filepath.data(), nullptr); } } diff --git a/Gems/AudioSystem/Code/Source/Editor/AudioControlsWriter.h b/Gems/AudioSystem/Code/Source/Editor/AudioControlsWriter.h index 9e3978b94b..1414f6725d 100644 --- a/Gems/AudioSystem/Code/Source/Editor/AudioControlsWriter.h +++ b/Gems/AudioSystem/Code/Source/Editor/AudioControlsWriter.h @@ -16,10 +16,9 @@ #include #include #include -#include + #include -#include class QStandardItemModel; @@ -33,15 +32,16 @@ namespace AudioControls { SLibraryScope() { - m_nodes[eACET_TRIGGER] = GetISystem()->CreateXmlNode(Audio::ATLXmlTags::TriggersNodeTag); - m_nodes[eACET_RTPC] = GetISystem()->CreateXmlNode(Audio::ATLXmlTags::RtpcsNodeTag); - m_nodes[eACET_SWITCH] = GetISystem()->CreateXmlNode(Audio::ATLXmlTags::SwitchesNodeTag); + XmlAllocator& xmlAlloc(AudioControls::s_xmlAllocator); + m_nodes[eACET_TRIGGER] = xmlAlloc.allocate_node(AZ::rapidxml::node_element, Audio::ATLXmlTags::TriggersNodeTag); + m_nodes[eACET_RTPC] = xmlAlloc.allocate_node(AZ::rapidxml::node_element, Audio::ATLXmlTags::RtpcsNodeTag); + m_nodes[eACET_SWITCH] = xmlAlloc.allocate_node(AZ::rapidxml::node_element, Audio::ATLXmlTags::SwitchesNodeTag); m_nodes[eACET_SWITCH_STATE] = nullptr; - m_nodes[eACET_ENVIRONMENT] = GetISystem()->CreateXmlNode(Audio::ATLXmlTags::EnvironmentsNodeTag); - m_nodes[eACET_PRELOAD] = GetISystem()->CreateXmlNode(Audio::ATLXmlTags::PreloadsNodeTag); + m_nodes[eACET_ENVIRONMENT] = xmlAlloc.allocate_node(AZ::rapidxml::node_element, Audio::ATLXmlTags::EnvironmentsNodeTag); + m_nodes[eACET_PRELOAD] = xmlAlloc.allocate_node(AZ::rapidxml::node_element, Audio::ATLXmlTags::PreloadsNodeTag); } - XmlNodeRef m_nodes[eACET_NUM_TYPES]; + AZ::rapidxml::xml_node* m_nodes[eACET_NUM_TYPES]; bool m_isDirty = false; }; @@ -56,12 +56,13 @@ namespace AudioControls private: void WriteLibrary(const AZStd::string_view libraryName, QModelIndex root); void WriteItem(QModelIndex index, const AZStd::string& path, TLibraryStorage& library, bool isParentModified); - void WriteControlToXml(XmlNodeRef node, CATLControl* control, const AZStd::string_view path); - void WriteConnectionsToXml(XmlNodeRef node, CATLControl* control); + void WriteControlToXml(AZ::rapidxml::xml_node* node, CATLControl* control, const AZStd::string_view path); + void WriteConnectionsToXml(AZ::rapidxml::xml_node* node, CATLControl* control); bool IsItemModified(QModelIndex index); - void CheckOutFile(const AZStd::string& filepath); - void DeleteLibraryFile(const AZStd::string& filepath); + bool WriteXmlToFile(const AZStd::string_view filepath, AZ::rapidxml::xml_node* rootNode); + void CheckOutFile(const AZStd::string_view filepath); + void DeleteLibraryFile(const AZStd::string_view filepath); CATLControlsModel* m_atlModel; QStandardItemModel* m_layoutModel; diff --git a/Gems/AudioSystem/Code/Source/Editor/QAudioControlEditorIcons.h b/Gems/AudioSystem/Code/Source/Editor/QAudioControlEditorIcons.h index ce77125443..4d322a49d9 100644 --- a/Gems/AudioSystem/Code/Source/Editor/QAudioControlEditorIcons.h +++ b/Gems/AudioSystem/Code/Source/Editor/QAudioControlEditorIcons.h @@ -31,7 +31,7 @@ namespace AudioControls iconFile = ":/Icons/Switch_Icon.svg"; break; case AudioControls::eACET_SWITCH_STATE: - iconFile = ":/Icons/Property_Icon.svg"; + iconFile = ":/Icons/Property_Icon.png"; break; case AudioControls::eACET_ENVIRONMENT: iconFile = ":/Icons/Environment_Icon.svg"; @@ -41,7 +41,7 @@ namespace AudioControls break; default: // should make a "default"/empty icon... - iconFile = ":/Icons/RTPC_Icon.svg"; + iconFile = ":/Icons/Unassigned.svg"; } QIcon icon(iconFile); diff --git a/Gems/AudioSystem/Code/Source/Engine/ATLComponents.cpp b/Gems/AudioSystem/Code/Source/Engine/ATLComponents.cpp index ca9cb214e2..7010012e87 100644 --- a/Gems/AudioSystem/Code/Source/Engine/ATLComponents.cpp +++ b/Gems/AudioSystem/Code/Source/Engine/ATLComponents.cpp @@ -1005,14 +1005,14 @@ namespace Audio AZStd::string searchPath; AZ::StringFunc::Path::Join(m_rootPath.c_str(), folderPath, searchPath); - AZStd::vector foundFiles = Audio::FindFilesInPath(searchPath, "*.xml"); + auto foundFiles = Audio::FindFilesInPath(searchPath, "*.xml"); for (const auto& file : foundFiles) { AZ_Assert(AZ::IO::FileIOBase::GetInstance()->Exists(file.c_str()), "FindFiles found file '%s' but FileIO says it doesn't exist!", file.c_str()); g_audioLogger.Log(eALT_ALWAYS, "Loading Audio Controls Library: '%s'", file.c_str()); - Audio::ScopedXmlLoader xmlFileLoader(file); + Audio::ScopedXmlLoader xmlFileLoader(file.Native()); if (xmlFileLoader.HasError()) { continue; @@ -1053,14 +1053,14 @@ namespace Audio AZStd::string searchPath; AZ::StringFunc::Path::Join(m_rootPath.c_str(), folderPath, searchPath); - AZStd::vector foundFiles = Audio::FindFilesInPath(searchPath, "*.xml"); + auto foundFiles = Audio::FindFilesInPath(searchPath, "*.xml"); for (const auto& file : foundFiles) { AZ_Assert(AZ::IO::FileIOBase::GetInstance()->Exists(file.c_str()), "FindFiles found file '%s' but FileIO says it doesn't exist!", file.c_str()); g_audioLogger.Log(eALT_ALWAYS, "Loading Audio Preloads Library: '%s'", file.c_str()); - Audio::ScopedXmlLoader xmlFileLoader(file); + Audio::ScopedXmlLoader xmlFileLoader(file.Native()); if (xmlFileLoader.HasError()) { continue; From 976272d9cf9d2e22dceb6eea011d2f993854d320 Mon Sep 17 00:00:00 2001 From: amzn-phist <52085794+amzn-phist@users.noreply.github.com> Date: Thu, 22 Jul 2021 21:06:04 -0500 Subject: [PATCH 022/160] Cleans up more legacy code from ACE Rewrote some code to replace gEnv->pCryPak and ISystem usage. One place was grabbing a Camera view from ISystem, replaced with simple identity matrix. Cleaned up include headers. Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com> --- .../Code/Source/Editor/ATLControlsModel.cpp | 1 - .../Code/Source/Editor/ATLControlsPanel.cpp | 5 --- .../Code/Source/Editor/AudioControl.cpp | 1 - .../Editor/AudioControlsEditorPlugin.cpp | 12 ++---- .../Editor/AudioControlsEditorWindow.cpp | 39 ++++++------------- .../Source/Editor/AudioControlsEditorWindow.h | 1 - .../Source/Editor/AudioControlsLoader.cpp | 1 - .../Source/Editor/AudioResourceSelectors.cpp | 1 - .../Code/Source/Editor/AudioSystemPanel.cpp | 3 -- .../Source/Editor/ImplementationManager.cpp | 2 - .../Source/Editor/ImplementationManager.h | 3 -- .../Code/Source/Editor/InspectorPanel.cpp | 1 - .../Code/Source/Editor/QConnectionsWidget.cpp | 1 - 13 files changed, 14 insertions(+), 57 deletions(-) diff --git a/Gems/AudioSystem/Code/Source/Editor/ATLControlsModel.cpp b/Gems/AudioSystem/Code/Source/Editor/ATLControlsModel.cpp index 4fbc2a72c4..7bcce84ea4 100644 --- a/Gems/AudioSystem/Code/Source/Editor/ATLControlsModel.cpp +++ b/Gems/AudioSystem/Code/Source/Editor/ATLControlsModel.cpp @@ -13,7 +13,6 @@ #include #include #include -#include namespace AudioControls { diff --git a/Gems/AudioSystem/Code/Source/Editor/ATLControlsPanel.cpp b/Gems/AudioSystem/Code/Source/Editor/ATLControlsPanel.cpp index 6503e83545..48a16e54e6 100644 --- a/Gems/AudioSystem/Code/Source/Editor/ATLControlsPanel.cpp +++ b/Gems/AudioSystem/Code/Source/Editor/ATLControlsPanel.cpp @@ -16,13 +16,8 @@ #include #include #include -#include -#include -#include -#include #include #include -#include #include #include diff --git a/Gems/AudioSystem/Code/Source/Editor/AudioControl.cpp b/Gems/AudioSystem/Code/Source/Editor/AudioControl.cpp index 40c1cd3c79..c0a8fb8dde 100644 --- a/Gems/AudioSystem/Code/Source/Editor/AudioControl.cpp +++ b/Gems/AudioSystem/Code/Source/Editor/AudioControl.cpp @@ -14,7 +14,6 @@ #include #include #include -#include #include namespace AudioControls diff --git a/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorPlugin.cpp b/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorPlugin.cpp index b8761c4d62..973cb836a0 100644 --- a/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorPlugin.cpp +++ b/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorPlugin.cpp @@ -14,9 +14,6 @@ #include #include -#include -#include -#include #include #include @@ -28,7 +25,6 @@ using namespace AudioControls; -using namespace PathUtil; CATLControlsModel CAudioControlsEditorPlugin::ms_ATLModel; QATLTreeModel CAudioControlsEditorPlugin::ms_layoutModel; @@ -152,20 +148,18 @@ void CAudioControlsEditorPlugin::ExecuteTrigger(const AZStd::string_view sTrigge Audio::AudioSystemRequestBus::BroadcastResult(ms_nAudioTriggerID, &Audio::AudioSystemRequestBus::Events::GetAudioTriggerID, sTriggerName.data()); if (ms_nAudioTriggerID != INVALID_AUDIO_CONTROL_ID) { - const CCamera& camera = GetIEditor()->GetSystem()->GetViewCamera(); - Audio::SAudioRequest request; request.nFlags = Audio::eARF_PRIORITY_NORMAL; - const AZ::Matrix3x4 cameraMatrix = LYTransformToAZMatrix3x4(camera.GetMatrix()); + const AZ::Matrix3x4 listenerTxfm = AZ::Matrix3x4::CreateIdentity(); - Audio::SAudioListenerRequestData requestData(cameraMatrix); + Audio::SAudioListenerRequestData requestData(listenerTxfm); requestData.oNewPosition.NormalizeForwardVec(); requestData.oNewPosition.NormalizeUpVec(); request.pData = &requestData; Audio::AudioSystemRequestBus::Broadcast(&Audio::AudioSystemRequestBus::Events::PushRequest, request); - ms_pIAudioProxy->SetPosition(cameraMatrix); + ms_pIAudioProxy->SetPosition(listenerTxfm); ms_pIAudioProxy->ExecuteTrigger(ms_nAudioTriggerID); } } diff --git a/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorWindow.cpp b/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorWindow.cpp index d19cfe7adb..54a8ce616d 100644 --- a/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorWindow.cpp +++ b/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorWindow.cpp @@ -9,7 +9,6 @@ #include -#include #include #include @@ -18,22 +17,14 @@ #include #include #include +#include #include - - -#include #include #include #include - - -#include -#include -#include -#include - #include +#include #include #include @@ -41,6 +32,7 @@ #include #include + void InitACEResources() { Q_INIT_RESOURCE(AudioControlsEditorUI); @@ -116,25 +108,16 @@ namespace AudioControls { m_fileSystemWatcher.addPath(folder.data()); - AZStd::string search; - AZ::StringFunc::Path::Join(folder.data(), "*", search, true, false); - auto pCryPak = gEnv->pCryPak; - AZ::IO::ArchiveFileIterator handle = pCryPak->FindFirst(search.c_str()); - if (handle) + auto fileIO = AZ::IO::FileIOBase::GetInstance(); + auto foundFiles = Audio::FindFilesInPath(folder, "*"); + for (auto& file : foundFiles) { - do + if (fileIO->IsDirectory(file.c_str())) { - AZStd::string sName = static_cast(handle.m_filename); - if (!sName.empty() && sName[0] != '.') - { - if ((handle.m_fileDesc.nAttrib & AZ::IO::FileDesc::Attribute::Subdirectory) == AZ::IO::FileDesc::Attribute::Subdirectory) - { - AZ::StringFunc::Path::Join(folder.data(), sName.c_str(), sName); - StartWatchingFolder(sName); - } - } - } while (handle = pCryPak->FindNext(handle)); - pCryPak->FindClose(handle); + AZ::IO::FixedMaxPath resolvedPath; + fileIO->ReplaceAlias(resolvedPath, file); + StartWatchingFolder(file.Native()); + } } } diff --git a/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorWindow.h b/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorWindow.h index bfa08828ac..761f0c1a8e 100644 --- a/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorWindow.h +++ b/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorWindow.h @@ -12,7 +12,6 @@ #if !defined(Q_MOC_RUN) #include #include -#include #include #include diff --git a/Gems/AudioSystem/Code/Source/Editor/AudioControlsLoader.cpp b/Gems/AudioSystem/Code/Source/Editor/AudioControlsLoader.cpp index e0eba868d6..8714fd21da 100644 --- a/Gems/AudioSystem/Code/Source/Editor/AudioControlsLoader.cpp +++ b/Gems/AudioSystem/Code/Source/Editor/AudioControlsLoader.cpp @@ -10,7 +10,6 @@ #include #include -#include #include #include diff --git a/Gems/AudioSystem/Code/Source/Editor/AudioResourceSelectors.cpp b/Gems/AudioSystem/Code/Source/Editor/AudioResourceSelectors.cpp index 90c50ac741..f0c9ebe3d1 100644 --- a/Gems/AudioSystem/Code/Source/Editor/AudioResourceSelectors.cpp +++ b/Gems/AudioSystem/Code/Source/Editor/AudioResourceSelectors.cpp @@ -9,7 +9,6 @@ #include #include -#include #include #include #include diff --git a/Gems/AudioSystem/Code/Source/Editor/AudioSystemPanel.cpp b/Gems/AudioSystem/Code/Source/Editor/AudioSystemPanel.cpp index 99f615d1fe..deccfc1364 100644 --- a/Gems/AudioSystem/Code/Source/Editor/AudioSystemPanel.cpp +++ b/Gems/AudioSystem/Code/Source/Editor/AudioSystemPanel.cpp @@ -12,10 +12,7 @@ #include #include #include -#include -#include #include -#include #include #include diff --git a/Gems/AudioSystem/Code/Source/Editor/ImplementationManager.cpp b/Gems/AudioSystem/Code/Source/Editor/ImplementationManager.cpp index fc146a109d..bee5c1dd51 100644 --- a/Gems/AudioSystem/Code/Source/Editor/ImplementationManager.cpp +++ b/Gems/AudioSystem/Code/Source/Editor/ImplementationManager.cpp @@ -14,8 +14,6 @@ #include #include #include -#include -#include //-----------------------------------------------------------------------------------------------// diff --git a/Gems/AudioSystem/Code/Source/Editor/ImplementationManager.h b/Gems/AudioSystem/Code/Source/Editor/ImplementationManager.h index dd6d61d310..70a99fcc0e 100644 --- a/Gems/AudioSystem/Code/Source/Editor/ImplementationManager.h +++ b/Gems/AudioSystem/Code/Source/Editor/ImplementationManager.h @@ -10,9 +10,6 @@ #pragma once #if !defined(Q_MOC_RUN) -#include -#include - #include #endif diff --git a/Gems/AudioSystem/Code/Source/Editor/InspectorPanel.cpp b/Gems/AudioSystem/Code/Source/Editor/InspectorPanel.cpp index a9e2046348..318aea211c 100644 --- a/Gems/AudioSystem/Code/Source/Editor/InspectorPanel.cpp +++ b/Gems/AudioSystem/Code/Source/Editor/InspectorPanel.cpp @@ -12,7 +12,6 @@ #include #include #include -#include #include #include diff --git a/Gems/AudioSystem/Code/Source/Editor/QConnectionsWidget.cpp b/Gems/AudioSystem/Code/Source/Editor/QConnectionsWidget.cpp index 8a6fece85c..b65e690f1b 100644 --- a/Gems/AudioSystem/Code/Source/Editor/QConnectionsWidget.cpp +++ b/Gems/AudioSystem/Code/Source/Editor/QConnectionsWidget.cpp @@ -14,7 +14,6 @@ #include #include #include -#include #include #include From 91dcbe7fed88592507dcf9f41e2102ee0990b8d8 Mon Sep 17 00:00:00 2001 From: amzn-phist <52085794+amzn-phist@users.noreply.github.com> Date: Thu, 22 Jul 2021 21:17:41 -0500 Subject: [PATCH 023/160] Fixes minor mistake in helper function desc Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com> --- Gems/AudioSystem/Code/Source/Editor/AudioControl.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gems/AudioSystem/Code/Source/Editor/AudioControl.h b/Gems/AudioSystem/Code/Source/Editor/AudioControl.h index 9335429fd4..494b0465bd 100644 --- a/Gems/AudioSystem/Code/Source/Editor/AudioControl.h +++ b/Gems/AudioSystem/Code/Source/Editor/AudioControl.h @@ -34,11 +34,11 @@ namespace AudioControls // indicates if the connection is valid for the currently loaded middleware bool m_isValid{ false }; - // Rapid XML provides a 'copy_node' utility that will copy an entire node tree, + // Rapid XML provides a 'clone_node' utility that will copy an entire node tree, // but it only copies pointers of any strings in the node names and values. // This causes problems with storing raw xml nodes as this class does because strings // will be pointing into the memory pool of an xml document that has gone out of scope. - // This function is a rewritten version of 'copy_node' that does the deep copy of strings + // This function is a rewritten version of 'clone_node' that does the deep copy of strings // into the new destination tree. static AZ::rapidxml::xml_node* DeepCopyNode(AZ::rapidxml::xml_node* srcNode) { From 53dd7a89aa7abd8bf09ee6986db8e6f6e998542d Mon Sep 17 00:00:00 2001 From: Ken Pruiksma Date: Thu, 22 Jul 2021 23:50:23 -0500 Subject: [PATCH 024/160] ATOM-16024 Point light shadows now affect specular like they should. Signed-off-by: Ken Pruiksma --- .../Assets/ShaderLib/Atom/Features/PBR/Lights/PointLight.azsli | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/PointLight.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/PointLight.azsli index 64d384b2a4..b88b6574a4 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/PointLight.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/PointLight.azsli @@ -116,7 +116,7 @@ void ApplyPointLight(ViewSrg::PointLight light, Surface surface, inout LightingD float sphereIntensityNormalization = GetIntensityAdjustedByRadiusAndRoughness(surface.roughnessA, light.m_bulbRadius, d2); // Specular contribution - lightingData.specularLighting += sphereIntensityNormalization * GetSpecularLighting(surface, lightingData, lightIntensity, normalize(posToLight)); + lightingData.specularLighting += sphereIntensityNormalization * GetSpecularLighting(surface, lightingData, lightIntensity, normalize(posToLight)) * litRatio; } } From d385f6ed99170d0c50c9f8e0543d4abee648c03f Mon Sep 17 00:00:00 2001 From: amzn-phist <52085794+amzn-phist@users.noreply.github.com> Date: Fri, 23 Jul 2021 11:29:47 -0500 Subject: [PATCH 025/160] Addresses feedback from PR review Change DeepCopyNode utility to return a unique_ptr, fix up some string/path usages to avoid temporaries, etc. Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com> --- .../Code/Source/Editor/AudioWwiseLoader.cpp | 4 +--- .../Code/Include/Editor/ACETypes.h | 2 +- .../Code/Include/Engine/AudioFileUtils.h | 2 +- .../Code/Source/Editor/AudioControl.cpp | 2 +- .../Code/Source/Editor/AudioControl.h | 12 +++++------ .../Source/Editor/AudioControlsWriter.cpp | 20 +++++++------------ 6 files changed, 17 insertions(+), 25 deletions(-) diff --git a/Gems/AudioEngineWwise/Code/Source/Editor/AudioWwiseLoader.cpp b/Gems/AudioEngineWwise/Code/Source/Editor/AudioWwiseLoader.cpp index 1a3ff121f8..616a30994c 100644 --- a/Gems/AudioEngineWwise/Code/Source/Editor/AudioWwiseLoader.cpp +++ b/Gems/AudioEngineWwise/Code/Source/Editor/AudioWwiseLoader.cpp @@ -9,8 +9,6 @@ #include -#include - #include #include #include @@ -77,7 +75,7 @@ namespace AudioControls isLocalizedLoaded = true; } } - else if (fileName.Extension() == Audio::Wwise::BankExtension && !AZ::StringFunc::Equal(fileName.Native(), Audio::Wwise::InitBank)) + else if (fileName.Extension() == Audio::Wwise::BankExtension && fileName != Audio::Wwise::InitBank) { m_audioSystemImpl->CreateControl( SControlDef(AZStd::string{ fileName.Native() }, eWCT_WWISE_SOUND_BANK, isLocalized, nullptr, subPath)); diff --git a/Gems/AudioSystem/Code/Include/Editor/ACETypes.h b/Gems/AudioSystem/Code/Include/Editor/ACETypes.h index 0bfaa6640c..1ff6112056 100644 --- a/Gems/AudioSystem/Code/Include/Editor/ACETypes.h +++ b/Gems/AudioSystem/Code/Include/Editor/ACETypes.h @@ -41,6 +41,6 @@ namespace AudioControls using FilepathSet = AZStd::set; using XmlAllocator = AZ::rapidxml::memory_pool<>; - inline static XmlAllocator s_xmlAllocator; + inline XmlAllocator s_xmlAllocator; } // namespace AudioControls diff --git a/Gems/AudioSystem/Code/Include/Engine/AudioFileUtils.h b/Gems/AudioSystem/Code/Include/Engine/AudioFileUtils.h index 37952eaa1a..65122662b1 100644 --- a/Gems/AudioSystem/Code/Include/Engine/AudioFileUtils.h +++ b/Gems/AudioSystem/Code/Include/Engine/AudioFileUtils.h @@ -26,7 +26,7 @@ namespace Audio AZStd::vector foundFiles; AZ::IO::FileIOBase::FindFilesCallbackType findFilesCallback = [&foundFiles](const char* file) -> bool { - foundFiles.emplace_back(AZ::IO::FixedMaxPath{ file }.LexicallyNormal()); + foundFiles.emplace_back(AZ::IO::PathView{ file }.LexicallyNormal()); return true; }; diff --git a/Gems/AudioSystem/Code/Source/Editor/AudioControl.cpp b/Gems/AudioSystem/Code/Source/Editor/AudioControl.cpp index c0a8fb8dde..ce268022a8 100644 --- a/Gems/AudioSystem/Code/Source/Editor/AudioControl.cpp +++ b/Gems/AudioSystem/Code/Source/Editor/AudioControl.cpp @@ -345,7 +345,7 @@ namespace AudioControls { for (auto& connectionNode : m_connectionNodes) { - if (TConnectionPtr connection = audioSystemImpl->CreateConnectionFromXMLNode(connectionNode.m_xmlNode, m_type)) + if (TConnectionPtr connection = audioSystemImpl->CreateConnectionFromXMLNode(connectionNode.m_xmlNode.get(), m_type)) { AddConnection(connection); connectionNode.m_isValid = true; diff --git a/Gems/AudioSystem/Code/Source/Editor/AudioControl.h b/Gems/AudioSystem/Code/Source/Editor/AudioControl.h index 494b0465bd..c53f4aa831 100644 --- a/Gems/AudioSystem/Code/Source/Editor/AudioControl.h +++ b/Gems/AudioSystem/Code/Source/Editor/AudioControl.h @@ -25,11 +25,11 @@ namespace AudioControls { SRawConnectionData(AZ::rapidxml::xml_node* node, bool isValid) { - m_xmlNode = DeepCopyNode(node); + m_xmlNode = AZStd::move(DeepCopyNode(node)); m_isValid = isValid; } - AZ::rapidxml::xml_node* m_xmlNode{ nullptr }; + AZStd::unique_ptr> m_xmlNode{}; // indicates if the connection is valid for the currently loaded middleware bool m_isValid{ false }; @@ -40,20 +40,20 @@ namespace AudioControls // will be pointing into the memory pool of an xml document that has gone out of scope. // This function is a rewritten version of 'clone_node' that does the deep copy of strings // into the new destination tree. - static AZ::rapidxml::xml_node* DeepCopyNode(AZ::rapidxml::xml_node* srcNode) + [[nodiscard]] static AZStd::unique_ptr> DeepCopyNode(AZ::rapidxml::xml_node* srcNode) { - AZ::rapidxml::xml_node* destNode = nullptr; + AZStd::unique_ptr> destNode{}; if (srcNode) { XmlAllocator& xmlAlloc(AudioControls::s_xmlAllocator); - destNode = xmlAlloc.allocate_node(srcNode->type()); + destNode.reset(xmlAlloc.allocate_node(srcNode->type())); destNode->name(xmlAlloc.allocate_string(srcNode->name(), srcNode->name_size()), srcNode->name_size()); destNode->value(xmlAlloc.allocate_string(srcNode->value(), srcNode->value_size()), srcNode->value_size()); for (AZ::rapidxml::xml_node* child = srcNode->first_node(); child != nullptr; child = child->next_sibling()) { - destNode->append_node(DeepCopyNode(child)); + destNode->append_node(DeepCopyNode(child).release()); } for (AZ::rapidxml::xml_attribute* attr = srcNode->first_attribute(); attr != nullptr; attr = attr->next_attribute()) diff --git a/Gems/AudioSystem/Code/Source/Editor/AudioControlsWriter.cpp b/Gems/AudioSystem/Code/Source/Editor/AudioControlsWriter.cpp index 80f05804f1..973da60c90 100644 --- a/Gems/AudioSystem/Code/Source/Editor/AudioControlsWriter.cpp +++ b/Gems/AudioSystem/Code/Source/Editor/AudioControlsWriter.cpp @@ -352,19 +352,13 @@ namespace AudioControls { if (node && control && m_audioSystemImpl) { - TXmlNodeList otherNodes = control->m_connectionNodes; - auto end = AZStd::remove_if( - otherNodes.begin(), otherNodes.end(), - [](const SRawConnectionData& connection) + for (auto& connectionNode : control->m_connectionNodes) + { + if (!connectionNode.m_isValid) { - return connection.m_isValid; + auto nodeCopy = SRawConnectionData::DeepCopyNode(connectionNode.m_xmlNode.get()); + node->append_node(nodeCopy.release()); } - ); - otherNodes.erase(end, otherNodes.end()); - - for (auto& connectionNode : otherNodes) - { - node->append_node(SRawConnectionData::DeepCopyNode(connectionNode.m_xmlNode)); } const size_t size = control->ConnectionCount(); @@ -391,7 +385,7 @@ namespace AudioControls IFileUtil* fileUtil = editor ? editor->GetFileUtil() : nullptr; if (fileUtil) { - fileUtil->CheckoutFile(filepath.data(), nullptr); + fileUtil->CheckoutFile(AZ::IO::FixedMaxPath{ filepath }.c_str(), nullptr); } } @@ -402,7 +396,7 @@ namespace AudioControls IFileUtil* fileUtil = editor ? editor->GetFileUtil() : nullptr; if (fileUtil) { - fileUtil->DeleteFromSourceControl(filepath.data(), nullptr); + fileUtil->DeleteFromSourceControl(AZ::IO::FixedMaxPath{ filepath }.c_str(), nullptr); } } From ce2fc6c1e6cfe31ac6ed2264c0930574c3305ebe Mon Sep 17 00:00:00 2001 From: amzn-phist <52085794+amzn-phist@users.noreply.github.com> Date: Fri, 23 Jul 2021 11:43:03 -0500 Subject: [PATCH 026/160] Addresses one more piece of feedback Updates a call to ConvertToAlias to use PathView. Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com> --- Gems/AudioSystem/Code/Source/Editor/AudioControlsWriter.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Gems/AudioSystem/Code/Source/Editor/AudioControlsWriter.cpp b/Gems/AudioSystem/Code/Source/Editor/AudioControlsWriter.cpp index 973da60c90..91f9aa5138 100644 --- a/Gems/AudioSystem/Code/Source/Editor/AudioControlsWriter.cpp +++ b/Gems/AudioSystem/Code/Source/Editor/AudioControlsWriter.cpp @@ -84,10 +84,10 @@ namespace AudioControls m_foundLibraryPaths.begin(), m_foundLibraryPaths.end(), [fileIO](AZStd::string& libraryPath) -> void { - AZStd::optional newLength = fileIO->ConvertToAlias(libraryPath.data(), libraryPath.size()); - if (newLength) + if (auto newPathOpt = fileIO->ConvertToAlias(AZ::IO::PathView{ libraryPath }); + newPathOpt.has_value()) { - libraryPath.resize_no_construct(*newLength); + libraryPath = newPathOpt.value().Native(); } AZStd::to_lower(libraryPath.begin(), libraryPath.end()); }); From dff425764ab95c58c62307c293f08db7a1f32dc2 Mon Sep 17 00:00:00 2001 From: amzn-phist <52085794+amzn-phist@users.noreply.github.com> Date: Fri, 23 Jul 2021 12:17:34 -0500 Subject: [PATCH 027/160] Fix some minor things Removes unnecessary things added during development. Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com> --- Gems/AudioSystem/Code/Source/Editor/AudioControl.h | 2 +- Gems/AudioSystem/Code/Source/Editor/AudioControlsLoader.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Gems/AudioSystem/Code/Source/Editor/AudioControl.h b/Gems/AudioSystem/Code/Source/Editor/AudioControl.h index c53f4aa831..37e67c815c 100644 --- a/Gems/AudioSystem/Code/Source/Editor/AudioControl.h +++ b/Gems/AudioSystem/Code/Source/Editor/AudioControl.h @@ -42,7 +42,7 @@ namespace AudioControls // into the new destination tree. [[nodiscard]] static AZStd::unique_ptr> DeepCopyNode(AZ::rapidxml::xml_node* srcNode) { - AZStd::unique_ptr> destNode{}; + AZStd::unique_ptr> destNode; if (srcNode) { XmlAllocator& xmlAlloc(AudioControls::s_xmlAllocator); diff --git a/Gems/AudioSystem/Code/Source/Editor/AudioControlsLoader.cpp b/Gems/AudioSystem/Code/Source/Editor/AudioControlsLoader.cpp index 8714fd21da..220cd32b5c 100644 --- a/Gems/AudioSystem/Code/Source/Editor/AudioControlsLoader.cpp +++ b/Gems/AudioSystem/Code/Source/Editor/AudioControlsLoader.cpp @@ -553,7 +553,7 @@ namespace AudioControls } //-------------------------------------------------------------------------------------------// - CATLControl* CAudioControlsLoader::CreateInternalSwitchState(CATLControl* parentControl, [[maybe_unused]] const AZStd::string& switchName, const AZStd::string& stateName) + CATLControl* CAudioControlsLoader::CreateInternalSwitchState(CATLControl* parentControl, const AZStd::string& switchName, const AZStd::string& stateName) { CATLControl* childControl = m_atlControlsModel->CreateControl(stateName, eACET_SWITCH_STATE, parentControl); From fcb2a0f95c76e3a55cc93b9b21aa34e88c07b63c Mon Sep 17 00:00:00 2001 From: dtamkin1 Date: Fri, 23 Jul 2021 16:21:07 -0500 Subject: [PATCH 028/160] Reformatted Unit tests to give more information and be more concise, also changed the position of the toggle switch Signed-off-by: dtamkin1 --- .../UI/PropertyEditor/PropertyRowWidget.cpp | 7 +- .../ReflectedPropertyEditor.cpp | 5 +- .../Framework/Tests/InstanceDataHierarchy.cpp | 345 +++++++----------- 3 files changed, 139 insertions(+), 218 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.cpp index e6f2af6a52..7e20642bb8 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.cpp @@ -142,7 +142,7 @@ namespace AzToolsFramework m_treeDepth = 0; delete m_dropDownArrow; - if (m_toggleSwitch) + if (m_toggleSwitch != nullptr) { m_handler->DestroyGUI(m_toggleSwitch); m_toggleSwitch = nullptr; @@ -1117,12 +1117,13 @@ namespace AzToolsFramework void PropertyRowWidget::CreateGroupToggleSwitch() { - if (!m_toggleSwitch) + if (m_toggleSwitch == nullptr) { m_handlerName = AZ::Edit::UIHandlers::CheckBox; PropertyTypeRegistrationMessages::Bus::BroadcastResult(m_handler, &PropertyTypeRegistrationMessages::Bus::Events::ResolvePropertyHandler, m_handlerName, azrtti_typeid()); m_toggleSwitch = m_handler->CreateGUI(this); - m_middleLayout->insertWidget(0, m_toggleSwitch, 1); + m_toggleSwitch->setFixedWidth(38); + m_middleLayout->addWidget(m_toggleSwitch, 1, Qt::AlignRight); auto checkBoxCtrl = static_cast(m_toggleSwitch); QObject::connect(checkBoxCtrl, &AzToolsFramework::PropertyCheckBoxCtrl::valueChanged, this, &PropertyRowWidget::OnClickedToggleButton); } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ReflectedPropertyEditor.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ReflectedPropertyEditor.cpp index d16fbb2776..f7c663747e 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ReflectedPropertyEditor.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ReflectedPropertyEditor.cpp @@ -501,6 +501,7 @@ namespace AzToolsFramework // if the node is in a group then create the widget for the group if (groupElementData) { + bool isToggleGroup = false; const char* groupName = groupElementData->m_description; PropertyRowWidget*& widgetEntry = m_groupWidgets[{parent, groupName}]; @@ -526,6 +527,7 @@ namespace AzToolsFramework pHandler->ConsumeAttributes_Internal(toggleSwitch, groupSourceNode); pHandler->ReadValuesIntoGUI_Internal(toggleSwitch, groupSourceNode); widgetEntry->OnValuesUpdated(); + isToggleGroup = true; } widgetEntry->SetLeafIndentation(m_leafIndentation); @@ -534,7 +536,8 @@ namespace AzToolsFramework for (const AZ::Edit::AttributePair& attribute : groupElementData->m_attributes) { - PropertyAttributeReader reader(node->GetParent()->FirstInstance(), attribute.second); + InstanceDataNode* readerNode = (isToggleGroup) ? groupSourceNode : node; + PropertyAttributeReader reader(readerNode->GetParent()->FirstInstance(), attribute.second); QString descriptionOut; bool foundDescription = false; widgetEntry->ConsumeAttribute(attribute.first, reader, true, &descriptionOut, &foundDescription); diff --git a/Code/Framework/Tests/InstanceDataHierarchy.cpp b/Code/Framework/Tests/InstanceDataHierarchy.cpp index 29cf42fb6b..312b057715 100644 --- a/Code/Framework/Tests/InstanceDataHierarchy.cpp +++ b/Code/Framework/Tests/InstanceDataHierarchy.cpp @@ -727,30 +727,22 @@ namespace UnitTest }; - class InstanceDataHierarchyGroupTestFixture - : public AllocatorsFixture - { - public: - InstanceDataHierarchyGroupTestFixture() = default; - }; - - class GroupTestComponent - : public AZ::Component + class GroupTestComponent : public AZ::Component { public: AZ_COMPONENT(GroupTestComponent, "{C088C81D-D59D-43F1-85F8-B2E591BABA36}") GroupTestComponent() = default; - struct SubData + struct SubData { AZ_TYPE_INFO(SubData, "{983316B5-17C0-476E-9CEB-CA749B3ABE5D}"); AZ_CLASS_ALLOCATOR(SubData, AZ::SystemAllocator, 0); SubData() {} - SubData(int v) : m_int(v) {} - SubData(bool b) : m_bool(b) {} - SubData(float f) : m_float(f) {} + explicit SubData(int v) : m_int(v) {} + explicit SubData(bool b) : m_bool(b) {} + explicit SubData(float f) : m_float(f) {} ~SubData() = default; float m_float = 0.f; @@ -803,7 +795,7 @@ namespace UnitTest } } - void Activate() override + void Activate() override { } @@ -821,6 +813,66 @@ namespace UnitTest SubData m_subGroupForToggle; }; + class InstanceDataHierarchyGroupTestFixture : public AllocatorsFixture + { + public: + InstanceDataHierarchyGroupTestFixture() = default; + + AZStd::unique_ptr m_serializeContext; + AZStd::unique_ptr testEntity1; + AzToolsFramework::InstanceDataHierarchy* instanceDataHierarchy; + AzToolsFramework::InstanceDataNode* componentNode1 = nullptr; + + void SetUp() override + { + AllocatorsFixture::SetUp(); + + using AzToolsFramework::InstanceDataHierarchy; + using AzToolsFramework::InstanceDataNode; + + AZ::AllocatorInstance::Create(); + + m_serializeContext.reset(aznew AZ::SerializeContext()); + m_serializeContext.get()->CreateEditContext(); + Entity::Reflect(m_serializeContext.get()); + GroupTestComponent::Reflect(m_serializeContext.get()); + + testEntity1.reset(new AZ::Entity()); + testEntity1->CreateComponent(); + + instanceDataHierarchy = aznew InstanceDataHierarchy(); + instanceDataHierarchy->AddRootInstance(testEntity1.get()); + instanceDataHierarchy->Build(m_serializeContext.get(), 0); + + // Adding the nodes to a node stack + auto rootNode = instanceDataHierarchy->GetRootNode(); + AZStd::stack nodeStack; + nodeStack.push(rootNode); + while (!nodeStack.empty()) + { + InstanceDataNode* node = nodeStack.top(); + nodeStack.pop(); + if (node->GetClassMetadata()->m_typeId == AZ::AzTypeInfo::Uuid()) + { + componentNode1 = node; + break; + } + for (InstanceDataNode& child : node->GetChildren()) + { + nodeStack.push(&child); + } + } + } + + void TearDown() override + { + m_serializeContext.reset(); + testEntity1.reset(); + delete instanceDataHierarchy; + AZ::AllocatorInstance::Destroy(); + AllocatorsFixture::TearDown(); + } + }; class InstanceDataHierarchyKeyedContainerTest : public AllocatorsFixture @@ -1410,243 +1462,108 @@ namespace UnitTest run(); } - TEST_F(InstanceDataHierarchyGroupTestFixture, TestNormalGroups) + // Test to validate that the only ClassElement::Group nodes are ToggleGroups + TEST_F(InstanceDataHierarchyGroupTestFixture, GroupToggleIsClassElementGroup) { - using namespace AzToolsFramework; - - // Setting up the data node hierarchy - AZ::SerializeContext serializeContext; - serializeContext.CreateEditContext(); - Entity::Reflect(&serializeContext); - GroupTestComponent::Reflect(&serializeContext); - - AZStd::unique_ptr testEntity1(new AZ::Entity()); - testEntity1->CreateComponent(); - - InstanceDataHierarchy instanceDataHierarchy; - instanceDataHierarchy.AddRootInstance(testEntity1.get()); - instanceDataHierarchy.Build(&serializeContext, 0); - - // Adding the nodes to a node stack - auto rootNode = instanceDataHierarchy.GetRootNode(); - AZStd::stack nodeStack; - nodeStack.push(rootNode); - InstanceDataNode* componentNode1 = nullptr; - while (!nodeStack.empty()) - { - InstanceDataNode* node = nodeStack.top(); - nodeStack.pop(); - if (node->GetClassMetadata()->m_typeId == AZ::AzTypeInfo::Uuid()) - { - componentNode1 = node; - break; - } - for (InstanceDataNode& child : node->GetChildren()) - { - nodeStack.push(&child); - } - } - // Iterating through the children in the instance data hierarchy to verify their properties - ASSERT_TRUE(componentNode1 != nullptr); - for (auto child : componentNode1->GetChildren()) - { - AZStd::string childName(child.GetElementMetadata()->m_name); - if (childName.compare("GroupFloat") == 0) - { - // False for any child node with serializable data - ASSERT_FALSE(child.GetElementEditMetadata()->IsClassElement()); - // Child node should never be a ClassElement::Group, unless it is the root node of a ToggleGroup - ASSERT_NE(child.GetElementEditMetadata()->m_elementId, AZ::Edit::ClassElements::Group); - // Ensuring that this node was assigned to the appropriate group - ASSERT_EQ(child.GetGroupElementMetadata()->m_description, "Normal Group"); - // Ensuring that this node has the correct parent - ASSERT_EQ(child.GetParent()->GetClassMetadata()->m_name, "GroupTestComponent"); - } - } - } + using AzToolsFramework::InstanceDataHierarchy; + using AzToolsFramework::InstanceDataNode; - TEST_F(InstanceDataHierarchyGroupTestFixture, TestToggleGroups) - { - using namespace AzToolsFramework; - - // Setting up the data node hierarchy - AZ::SerializeContext serializeContext; - serializeContext.CreateEditContext(); - Entity::Reflect(&serializeContext); - GroupTestComponent::Reflect(&serializeContext); - - AZStd::unique_ptr testEntity1(new AZ::Entity()); - testEntity1->CreateComponent(); - - InstanceDataHierarchy instanceDataHierarchy; - instanceDataHierarchy.AddRootInstance(testEntity1.get()); - instanceDataHierarchy.Build(&serializeContext, 0); - - // Adding the nodes to a node stack - auto rootNode = instanceDataHierarchy.GetRootNode(); - AZStd::stack nodeStack; - nodeStack.push(rootNode); - InstanceDataNode* componentNode1 = nullptr; - while (!nodeStack.empty()) - { - InstanceDataNode* node = nodeStack.top(); - nodeStack.pop(); - if (node->GetClassMetadata()->m_typeId == AZ::AzTypeInfo::Uuid()) - { - componentNode1 = node; - break; - } - for (InstanceDataNode& child : node->GetChildren()) - { - nodeStack.push(&child); - } - } - // Iterating through the children in the instance data hierarchy to verify their properties - ASSERT_TRUE(componentNode1 != nullptr); for (auto child : componentNode1->GetChildren()) { AZStd::string childName(child.GetElementMetadata()->m_name); if (childName.compare("GroupToggle") == 0) { - // False for any child node with serializable data - ASSERT_FALSE(child.GetElementEditMetadata()->IsClassElement()); - // Child node is the root node of a ToggleGroup, so it should be a ClassElement::Group - ASSERT_EQ(child.GetElementEditMetadata()->m_elementId, AZ::Edit::ClassElements::Group); - // Ensuring that this node has the correct parent - ASSERT_EQ(child.GetParent()->GetClassMetadata()->m_name, "GroupTestComponent"); + EXPECT_EQ(child.GetElementEditMetadata()->m_elementId, AZ::Edit::ClassElements::Group); } - if (childName.compare("ToggleGroupInt") == 0) + if ((childName.compare("SubDataNormal") == 0) || (childName.compare("SubDataToggle") == 0)) { - // False for any child node with serializable data - ASSERT_FALSE(child.GetElementEditMetadata()->IsClassElement()); - // Child node should never be a ClassElement::Group, unless it is the root node of a ToggleGroup - ASSERT_NE(child.GetElementEditMetadata()->m_elementId, AZ::Edit::ClassElements::Group); - // Ensuring that this node was assigned to the appropriate group - ASSERT_EQ(child.GetGroupElementMetadata()->m_description, "Group Toggle"); - // Ensuring that this node has the correct parent - ASSERT_EQ(child.GetParent()->GetClassMetadata()->m_name, "GroupTestComponent"); + for (auto subChild : child.GetChildren()) + { + childName = subChild.GetElementMetadata()->m_name; + if (childName.compare("SubToggle") == 0) + { + EXPECT_EQ(subChild.GetElementEditMetadata()->m_elementId, AZ::Edit::ClassElements::Group); + } + else + { + EXPECT_NE(subChild.GetElementEditMetadata()->m_elementId, AZ::Edit::ClassElements::Group); + } + } } } } - TEST_F(InstanceDataHierarchyGroupTestFixture, TestNestedGroups) + // Test to ensure that each node has been assigned under the proper group and the group hierarchy is structured correctly + TEST_F(InstanceDataHierarchyGroupTestFixture, ValidatingGroupAndSubGroupHierarchy) { - using namespace AzToolsFramework; - - // Setting up the data node hierarchy - AZ::SerializeContext serializeContext; - serializeContext.CreateEditContext(); - Entity::Reflect(&serializeContext); - GroupTestComponent::Reflect(&serializeContext); - - AZStd::unique_ptr testEntity1(new AZ::Entity()); - testEntity1->CreateComponent(); - - InstanceDataHierarchy instanceDataHierarchy; - instanceDataHierarchy.AddRootInstance(testEntity1.get()); - instanceDataHierarchy.Build(&serializeContext, 0); - - // Adding the nodes to a node stack - auto rootNode = instanceDataHierarchy.GetRootNode(); - AZStd::stack nodeStack; - nodeStack.push(rootNode); - InstanceDataNode* componentNode1 = nullptr; - while (!nodeStack.empty()) + using AzToolsFramework::InstanceDataHierarchy; + using AzToolsFramework::InstanceDataNode; + + for (auto child : componentNode1->GetChildren()) { - InstanceDataNode* node = nodeStack.top(); - nodeStack.pop(); - if (node->GetClassMetadata()->m_typeId == AZ::AzTypeInfo::Uuid()) + AZStd::string childName(child.GetElementMetadata()->m_name); + if (childName.compare("GroupFloat") == 0) { - componentNode1 = node; - break; + EXPECT_EQ(child.GetGroupElementMetadata()->m_description, "Normal Group"); } - for (InstanceDataNode& child : node->GetChildren()) + if (childName.compare("ToggleGroupInt") == 0) { - nodeStack.push(&child); + EXPECT_EQ(child.GetGroupElementMetadata()->m_description, "Group Toggle"); } - } - // Iterating through the children in the instance data hierarchy to verify their properties - ASSERT_TRUE(componentNode1 != nullptr); - for (auto child : componentNode1->GetChildren()) - { - AZStd::string childName(child.GetElementMetadata()->m_name); - if (childName.compare("SubDataNormal") == 0) + if ((childName.compare("SubDataNormal") == 0) || (childName.compare("SubDataToggle") == 0)) { - for (InstanceDataNode& subChild : child.GetChildren()) + for (auto subChild : child.GetChildren()) { childName = subChild.GetElementMetadata()->m_name; if (childName.compare("SubInt") == 0) { - // False for any child node with serializable data - ASSERT_FALSE(subChild.GetElementEditMetadata()->IsClassElement()); - // Child node should never be a ClassElement::Group, unless it is the root node of a ToggleGroup - ASSERT_NE(subChild.GetElementEditMetadata()->m_elementId, AZ::Edit::ClassElements::Group); - // Ensuring that this node was assigned to the appropriate group - ASSERT_EQ(subChild.GetGroupElementMetadata()->m_description, "Normal SubGroup"); - // Ensuring that this node has the correct parent - ASSERT_EQ(subChild.GetParent()->GetClassMetadata()->m_name, "SubData"); - } - if (childName.compare("SubToggle") == 0) - { - // False for any child node with serializable data - ASSERT_FALSE(subChild.GetElementEditMetadata()->IsClassElement()); - // Child node is the root node of a ToggleGroup, so it should be a ClassElement::Group - ASSERT_EQ(subChild.GetElementEditMetadata()->m_elementId, AZ::Edit::ClassElements::Group); - // Ensuring that this node has the correct parent - ASSERT_EQ(subChild.GetParent()->GetClassMetadata()->m_name, "SubData"); + EXPECT_EQ(subChild.GetGroupElementMetadata()->m_description, "Normal SubGroup"); } if (childName.compare("SubFloat") == 0) { - // False for any child node with serializable data - ASSERT_FALSE(subChild.GetElementEditMetadata()->IsClassElement()); - // Child node should never be a ClassElement::Group, unless it is the root node of a ToggleGroup - ASSERT_NE(subChild.GetElementEditMetadata()->m_elementId, AZ::Edit::ClassElements::Group); - // Ensuring that this node was assigned to the appropriate group - ASSERT_EQ(subChild.GetGroupElementMetadata()->m_description, "SubGroup Toggle"); - // Ensuring that this node has the correct parent - ASSERT_EQ(subChild.GetParent()->GetClassMetadata()->m_name, "SubData"); + EXPECT_EQ(subChild.GetGroupElementMetadata()->m_description, "SubGroup Toggle"); } } } - if (childName.compare("SubDataToggle") == 0) + } + } + + class InstanceDataHierarchyGroupTestFixtureParameterized + : public InstanceDataHierarchyGroupTestFixture + , public ::testing::WithParamInterface + { + }; + + INSTANTIATE_TEST_CASE_P( + InstanceDataHierarchyGroupTestFixture, + InstanceDataHierarchyGroupTestFixtureParameterized, + ::testing::Values("GroupFloat", "GroupToggle", "ToggleGroupInt", "SubInt", "SubToggle", "SubFloat")); + + // Test to validate that each node in a group and Subgroup has the correct parent + TEST_P(InstanceDataHierarchyGroupTestFixtureParameterized, ValidatingGroupAndSubGroupParents) + { + using AzToolsFramework::InstanceDataHierarchy; + using AzToolsFramework::InstanceDataNode; + + const char* paramName = GetParam(); + for (auto child : componentNode1->GetChildren()) + { + AZStd::string childName(child.GetElementMetadata()->m_name); + if (childName.compare(paramName) == 0) + { + EXPECT_EQ(child.GetParent()->GetClassMetadata()->m_name, "GroupTestComponent"); + } + if ((childName.compare("SubDataNormal") == 0) || (childName.compare("SubDataToggle") == 0)) { - for (InstanceDataNode& subChild : child.GetChildren()) + for (auto subChild : child.GetChildren()) { childName = subChild.GetElementMetadata()->m_name; - if (childName.compare("SubInt") == 0) - { - // False for any child node with serializable data - ASSERT_FALSE(subChild.GetElementEditMetadata()->IsClassElement()); - // Child node should never be a ClassElement::Group, unless it is the root node of a ToggleGroup - ASSERT_NE(subChild.GetElementEditMetadata()->m_elementId, AZ::Edit::ClassElements::Group); - // Ensuring that this node was assigned to the appropriate group - ASSERT_EQ(subChild.GetGroupElementMetadata()->m_description, "Normal SubGroup"); - // Ensuring that this node has the correct parent - ASSERT_EQ(subChild.GetParent()->GetClassMetadata()->m_name, "SubData"); - } - if (childName.compare("SubToggle") == 0) - { - // False for any child node with serializable data - ASSERT_FALSE(subChild.GetElementEditMetadata()->IsClassElement()); - // Child node is the root node of a ToggleGroup, so it should be a ClassElement::Group - ASSERT_EQ(subChild.GetElementEditMetadata()->m_elementId, AZ::Edit::ClassElements::Group); - // Ensuring that this node has the correct parent - ASSERT_EQ(subChild.GetParent()->GetClassMetadata()->m_name, "SubData"); - } - if (childName.compare("SubFloat") == 0) + if (childName.compare(paramName) == 0) { - // False for any child node with serializable data - ASSERT_FALSE(subChild.GetElementEditMetadata()->IsClassElement()); - // Child node should never be a ClassElement::Group, unless it is the root node of a ToggleGroup - ASSERT_NE(subChild.GetElementEditMetadata()->m_elementId, AZ::Edit::ClassElements::Group); - // Ensuring that this node was assigned to the appropriate group - ASSERT_EQ(subChild.GetGroupElementMetadata()->m_description, "SubGroup Toggle"); - // Ensuring that this node has the correct parent - ASSERT_EQ(subChild.GetParent()->GetClassMetadata()->m_name, "SubData"); + EXPECT_EQ(subChild.GetParent()->GetClassMetadata()->m_name, "SubData"); } } } } } - } // namespace UnitTest From b4e88010957cc0ce0c09b535402d9bd6c04b4949 Mon Sep 17 00:00:00 2001 From: puvvadar Date: Fri, 23 Jul 2021 14:51:53 -0700 Subject: [PATCH 029/160] Account for new blend factor calc and updated ScopedAlterTime usages Signed-off-by: puvvadar --- Gems/Multiplayer/Code/Include/Multiplayer/IMultiplayer.h | 4 +++- .../Code/Include/Multiplayer/NetworkTime/INetworkTime.h | 2 +- .../Components/LocalPredictionPlayerInputComponent.cpp | 9 ++++----- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/IMultiplayer.h b/Gems/Multiplayer/Code/Include/Multiplayer/IMultiplayer.h index cf15e8c9b7..4f714068db 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/IMultiplayer.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/IMultiplayer.h @@ -194,18 +194,20 @@ namespace Multiplayer m_previousHostTimeMs = time->GetHostTimeMs(); m_previousRewindConnectionId = time->GetRewindingConnectionId(); time->AlterTime(frameId, timeMs, connectionId); + m_previousBlendFactor = time->GetHostBlendFactor(); time->AlterBlendFactor(blendFactor); } inline ~ScopedAlterTime() { INetworkTime* time = GetNetworkTime(); time->AlterTime(m_previousHostFrameId, m_previousHostTimeMs, m_previousRewindConnectionId); - time->AlterBlendFactor(DefaultBlendFactor); + time->AlterBlendFactor(m_previousBlendFactor); } private: HostFrameId m_previousHostFrameId = InvalidHostFrameId; AZ::TimeMs m_previousHostTimeMs = AZ::TimeMs{ 0 }; AzNetworking::ConnectionId m_previousRewindConnectionId = AzNetworking::InvalidConnectionId; + float m_previousBlendFactor = DefaultBlendFactor; }; inline const char* GetEnumString(MultiplayerAgentType value) diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/NetworkTime/INetworkTime.h b/Gems/Multiplayer/Code/Include/Multiplayer/NetworkTime/INetworkTime.h index 54953b8e7e..43bcf5404e 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/NetworkTime/INetworkTime.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/NetworkTime/INetworkTime.h @@ -65,7 +65,7 @@ namespace Multiplayer virtual void AlterTime(HostFrameId frameId, AZ::TimeMs timeMs, AzNetworking::ConnectionId rewindConnectionId) = 0; //! Alters the current Host blend factor. Used to drive interpolation in rewound states. - //! @param blendFactor the blend factor to use + //! @param blendFactor the blend factor to use virtual void AlterBlendFactor(float blendFactor) = 0; //! Syncs all entities contained within a volume to the current rewind state. diff --git a/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp b/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp index 3c164713ea..a3a5a31eb2 100644 --- a/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp @@ -156,9 +156,8 @@ namespace Multiplayer if (m_clientBankedTime < sv_MaxBankTimeWindowSec) { // Client blends from previous frame to target so here we subtract blend factor to get to that state - const float blendFactor = AZStd::max(0.f, input.GetHostBlendFactor()); - const float adjustedBlendFactor = std::pow(0.2f, blendFactor); - const AZ::TimeMs blendMs = AZ::TimeMs(static_cast(static_cast(cl_InputRateMs)) * adjustedBlendFactor); + const float blendFactor = AZStd::min(AZStd::max(0.f, input.GetHostBlendFactor()), 1.f); + const AZ::TimeMs blendMs = AZ::TimeMs(static_cast(static_cast(cl_InputRateMs)) * blendFactor); m_clientBankedTime = AZStd::min(m_clientBankedTime + clientInputRateSec, (double)sv_MaxBankTimeWindowSec); // clamp to boundary { ScopedAlterTime scopedTime(input.GetHostFrameId(), input.GetHostTimeMs() - blendMs, input.GetHostBlendFactor(), invokingConnection->GetConnectionId()); @@ -315,7 +314,7 @@ namespace Multiplayer ++ModifyLastInputId(); input.SetClientInputId(GetLastInputId()); - ScopedAlterTime scopedTime(input.GetHostFrameId(), input.GetHostTimeMs(), DefaultBlendFactor, invokingConnection->GetConnectionId()); + ScopedAlterTime scopedTime(input.GetHostFrameId(), input.GetHostTimeMs(), input.GetHostBlendFactor(), invokingConnection->GetConnectionId()); GetNetBindComponent()->ProcessInput(input, clientInputRateSec); AZLOG @@ -395,7 +394,7 @@ namespace Multiplayer { // Reprocess the input for this frame NetworkInput& input = m_inputHistory[replayIndex]; - ScopedAlterTime scopedTime(input.GetHostFrameId(), input.GetHostTimeMs(), DefaultBlendFactor, invokingConnection->GetConnectionId()); + ScopedAlterTime scopedTime(input.GetHostFrameId(), input.GetHostTimeMs(), input.GetHostBlendFactor(), invokingConnection->GetConnectionId()); GetNetBindComponent()->ProcessInput(input, clientInputRateSec); AZLOG From a3e90b878c6a33780425e6b27eaff4dc8286c7f0 Mon Sep 17 00:00:00 2001 From: Benjamin Jillich Date: Mon, 26 Jul 2021 09:55:37 +0200 Subject: [PATCH 030/160] Removed legacy anim graph node parsers and legacy file format chunks Signed-off-by: Benjamin Jillich --- .../Source/Importer/AnimGraphFileFormat.cpp | 120 - .../Source/Importer/AnimGraphFileFormat.h | 231 - .../Importer/LegacyAnimGraphNodeParser.cpp | 4772 ----------------- .../Importer/LegacyAnimGraphNodeParser.h | 259 - .../Source/Importer/MotionSetFileFormat.h | 60 - 5 files changed, 5442 deletions(-) delete mode 100644 Gems/EMotionFX/Code/EMotionFX/Source/Importer/AnimGraphFileFormat.cpp delete mode 100644 Gems/EMotionFX/Code/EMotionFX/Source/Importer/AnimGraphFileFormat.h delete mode 100644 Gems/EMotionFX/Code/EMotionFX/Source/Importer/LegacyAnimGraphNodeParser.cpp delete mode 100644 Gems/EMotionFX/Code/EMotionFX/Source/Importer/LegacyAnimGraphNodeParser.h delete mode 100644 Gems/EMotionFX/Code/EMotionFX/Source/Importer/MotionSetFileFormat.h diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/AnimGraphFileFormat.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Importer/AnimGraphFileFormat.cpp deleted file mode 100644 index f79057dfa8..0000000000 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/AnimGraphFileFormat.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -#include "AnimGraphFileFormat.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace EMotionFX -{ - namespace FileFormat - { - AZ::TypeId GetParameterTypeIdForInterfaceType(uint32 interfaceType) - { - switch (interfaceType) - { - case MCore::ATTRIBUTE_INTERFACETYPE_FLOATSPINNER: - return azrtti_typeid(); - case MCore::ATTRIBUTE_INTERFACETYPE_FLOATSLIDER: - return azrtti_typeid(); - case MCore::ATTRIBUTE_INTERFACETYPE_INTSPINNER: - return azrtti_typeid(); - case MCore::ATTRIBUTE_INTERFACETYPE_INTSLIDER: - return azrtti_typeid(); - case MCore::ATTRIBUTE_INTERFACETYPE_CHECKBOX: - return azrtti_typeid(); - case MCore::ATTRIBUTE_INTERFACETYPE_VECTOR2: - return azrtti_typeid(); - case MCore::ATTRIBUTE_INTERFACETYPE_VECTOR3GIZMO: - return azrtti_typeid(); - case MCore::ATTRIBUTE_INTERFACETYPE_VECTOR4: - return azrtti_typeid(); - case MCore::ATTRIBUTE_INTERFACETYPE_COLOR: - return azrtti_typeid(); - case MCore::ATTRIBUTE_INTERFACETYPE_STRING: - return azrtti_typeid(); - case MCore::ATTRIBUTE_INTERFACETYPE_VECTOR3: - return azrtti_typeid(); - case MCore::ATTRIBUTE_INTERFACETYPE_TAG: - return azrtti_typeid(); - - case MCore::ATTRIBUTE_INTERFACETYPE_COMBOBOX: - case MCore::ATTRIBUTE_INTERFACETYPE_PROPERTYSET: - case MCore::ATTRIBUTE_INTERFACETYPE_DEFAULT: - default: - break; - } - return AZ::TypeId(); - } - - uint32 GetInterfaceTypeForParameterTypeId(const AZ::TypeId& parameterTypeId) - { - if (parameterTypeId == azrtti_typeid()) - { - return MCore::ATTRIBUTE_INTERFACETYPE_FLOATSPINNER; - } - else if (parameterTypeId == azrtti_typeid()) - { - return MCore::ATTRIBUTE_INTERFACETYPE_FLOATSLIDER; - } - else if (parameterTypeId == azrtti_typeid()) - { - return MCore::ATTRIBUTE_INTERFACETYPE_INTSPINNER; - } - else if (parameterTypeId == azrtti_typeid()) - { - return MCore::ATTRIBUTE_INTERFACETYPE_INTSLIDER; - } - else if (parameterTypeId == azrtti_typeid()) - { - return MCore::ATTRIBUTE_INTERFACETYPE_CHECKBOX; - } - else if (parameterTypeId == azrtti_typeid()) - { - return MCore::ATTRIBUTE_INTERFACETYPE_VECTOR2; - } - else if (parameterTypeId == azrtti_typeid()) - { - return MCore::ATTRIBUTE_INTERFACETYPE_VECTOR3GIZMO; - } - else if (parameterTypeId == azrtti_typeid()) - { - return MCore::ATTRIBUTE_INTERFACETYPE_VECTOR4; - } - else if (parameterTypeId == azrtti_typeid()) - { - return MCore::ATTRIBUTE_INTERFACETYPE_COLOR; - } - else if (parameterTypeId == azrtti_typeid()) - { - return MCore::ATTRIBUTE_INTERFACETYPE_STRING; - } - else if (parameterTypeId == azrtti_typeid()) - { - return MCore::ATTRIBUTE_INTERFACETYPE_VECTOR3; - } - else if (parameterTypeId == azrtti_typeid()) - { - return MCore::ATTRIBUTE_INTERFACETYPE_TAG; - } - return MCORE_INVALIDINDEX32; - } - } -} // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/AnimGraphFileFormat.h b/Gems/EMotionFX/Code/EMotionFX/Source/Importer/AnimGraphFileFormat.h deleted file mode 100644 index 3b88c3605f..0000000000 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/AnimGraphFileFormat.h +++ /dev/null @@ -1,231 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -#pragma once - -#include "SharedFileFormatStructs.h" -#include "AzCore/RTTI/TypeInfo.h" - -namespace EMotionFX -{ - namespace FileFormat // so now we are in the namespace EMotionFX::FileFormat - { - // collection of animGraph chunk IDs - enum - { - ANIMGRAPH_CHUNK_BLENDNODE = 400, - ANIMGRAPH_CHUNK_STATETRANSITIONS = 401, - ANIMGRAPH_CHUNK_NODECONNECTIONS = 402, - ANIMGRAPH_CHUNK_PARAMETERS = 403, - ANIMGRAPH_CHUNK_NODEGROUPS = 404, - ANIMGRAPH_CHUNK_GROUPPARAMETERS = 405, - ANIMGRAPH_CHUNK_GAMECONTROLLERSETTINGS = 406, - ANIMGRAPH_CHUNK_ADDITIONALINFO = 407, - ANIMGRAPH_FORCE_32BIT = 0xFFFFFFFF - }; - - enum - { - ANIMGRAPH_NODEFLAG_COLLAPSED = 1 << 0, - ANIMGRAPH_NODEFLAG_VISUALIZED = 1 << 1, - ANIMGRAPH_NODEFLAG_DISABLED = 1 << 2, - ANIMGRAPH_NODEFLAG_VIRTUALFINALOUTPUT = 1 << 3 - }; - - /* - AnimGraph_Header - - ANIMGRAPH_CHUNK_PARAMETERS: (global animgraph parameters) - uint32 numParameters - AnimGraph_ParamInfo[numParameters] - - ANIMGRAPH_CHUNK_BLENDNODE: - AnimGraph_NodeHeader - - ANIMGRAPH_CHUNK_NODECONNECTIONS: (for last loaded BLENDNODE) - uint32 numConnections - AnimGraph_NodeConnection[numConnections] - - ANIMGRAPH_CHUNK_STATETRANSITIONS: (for last loaded node, assumed to be a state machine) - uint32 numStateTransitions - uint32 blendNodeIndex (the state machine the transitions are for) - AnimGraph_StateTransition[numStateTransitions] - - ANIMGRAPH_CHUNK_NODEGROUPS: - uint32 numNodeGroups - AnimGraph_NodeGroup[numNodeGroups] - - ANIMGRAPH_CHUNK_GAMECONTROLLERSETTINGS: - uint32 activePresetIndex - uint32 numPresets - AnimGraph_GameControllerPreset[numPresets] - */ - - // AnimGraph file header - struct AnimGraph_Header - { - char mFourCC[4]; - uint8 mEndianType; - uint32 mFileVersion; - uint32 mNumNodes; - uint32 mNumStateTransitions; - uint32 mNumNodeConnections; - uint32 mNumParameters; - - // followed by: - // string mName; - // string mCopyright; - // string mDescription; - // string mCompany; - // string mEMFXVersion; - // string mEMStudioBuildDate; - }; - - // additional info - struct AnimGraph_AdditionalInfo - { - uint8 mUnitType; - }; - - - // the node header - struct AnimGraph_NodeHeader - { - uint32 mTypeID; - uint32 mParentIndex; - uint32 mVersion; - uint32 mNumCustomDataBytes; // number of bytes of node custom data to follow - uint32 mNumChildNodes; - uint32 mNumAttributes; - int32 mVisualPosX; - int32 mVisualPosY; - uint32 mVisualizeColor; - uint8 mFlags; - - // followed by: - // string mName; - // animGraphNode->Save(...) or animGraphNode->Load(...), writing or reading mNumBytes bytes - }; - - - struct AnimGraph_ParameterInfo - { - uint32 mNumComboValues; - uint32 mInterfaceType; - uint32 mAttributeType; - uint16 mFlags; - char mHasMinMax; - - // followed by: - // string mName - // string mInternalName - // string mDescription - // if (mHasMinMax == 1) - // { - // AnimGraph_Attribute mMinValue - // AnimGraph_Attribute mMaxValue - // } - // AnimGraph_Attribute mDefaultValue - // string mComboValues[mNumComboValues] - }; - - - // a node connection - struct AnimGraph_NodeConnection - { - uint32 mSourceNode; - uint32 mTargetNode; - uint16 mSourceNodePort; - uint16 mTargetNodePort; - }; - - - // a state transition - struct AnimGraph_StateTransition - { - uint32 mSourceNode; - uint32 mDestNode; - int32 mStartOffsetX; - int32 mStartOffsetY; - int32 mEndOffsetX; - int32 mEndOffsetY; - uint32 mNumConditions; - - // followed by: - // AnimGraph_NodeHeader (and its followed by data, EXCEPT THE NAME STRING, which is skipped) - // AnimGraph_NodeHeader[mConditions] (and its followed by data, EXCEPT THE NAME STRING, which is skipped) - }; - - - // a node group - struct AnimGraph_NodeGroup - { - FileColor mColor; - uint8 mIsVisible; - uint32 mNumNodes; - - // followed by: - // string mName - // uint32[mNumNodes] (node indices that belong to the group) - }; - - - // a group parameter - struct AnimGraph_GroupParameter - { - uint32 mNumParameters; - uint8 mCollapsed; - - // followed by: - // string mName - // uint32[mNumParameters] (parameter indices that belong to the group) - }; - - - // a game controller parameter info - struct AnimGraph_GameControllerParameterInfo - { - uint8 mAxis; - uint8 mMode; - uint8 mInvert; - - // followed by: - // string mName - }; - - - // a game controller button info - struct AnimGraph_GameControllerButtonInfo - { - uint8 mButtonIndex; - uint8 mMode; - - // followed by: - // string mString - }; - - - // a game controller preset - struct AnimGraph_GameControllerPreset - { - uint32 mNumParameterInfos; - uint32 mNumButtonInfos; - - // followed by: - // string mName - // AnimGraph_GameControllerParameterInfo[mNumParameterInfos] - // AnimGraph_GameControllerButtonInfo[mNumButtonInfos] - }; - - // Conversion functions to support attributes with the old serialization. - // Once we deprecate the old format we can remove these two functions. - AZ::TypeId GetParameterTypeIdForInterfaceType(uint32 interfaceType); - uint32 GetInterfaceTypeForParameterTypeId(const AZ::TypeId& parameterTypeId); - - } // namespace FileFormat -} // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/LegacyAnimGraphNodeParser.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Importer/LegacyAnimGraphNodeParser.cpp deleted file mode 100644 index db3db121dd..0000000000 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/LegacyAnimGraphNodeParser.cpp +++ /dev/null @@ -1,4772 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ -#include "LegacyAnimGraphNodeParser.h" -#include -#include -#include "../ConstraintTransformRotationAngles.h" -#include "ChunkProcessors.h" -#include "../AnimGraph.h" -#include "../AnimGraphStateMachine.h" -#include "../AnimGraphBindPoseNode.h" -#include "../AnimGraphHubNode.h" -#include "../AnimGraphParameterCondition.h" -#include "../AnimGraphVector2Condition.h" -#include "../AnimGraphMotionCondition.h" -#include "../AnimGraphStateCondition.h" -#include "../AnimGraphTimeCondition.h" -#include "../AnimGraphPlayTimeCondition.h" -#include "../AnimGraphTagCondition.h" -#include "../BlendTreeMotionFrameNode.h" -#include "../BlendTreeBlendNNode.h" -#include "../BlendTreeFloatConditionNode.h" -#include "../BlendTreeFloatSwitchNode.h" -#include "../BlendTreeBoolLogicNode.h" -#include "../AnimGraphMotionNode.h" -#include "../BlendTreeAccumTransformNode.h" -#include "../BlendTreeBlend2LegacyNode.h" -#include "../BlendTreeFloatConstantNode.h" -#include "../BlendTreeFloatMath1Node.h" -#include "../BlendTreeFloatMath2Node.h" -#include "../BlendTreeMorphTargetNode.h" -#include "../BlendTreeVector2ComposeNode.h" -#include "../BlendTreeVector3ComposeNode.h" -#include "../BlendTreeVector4ComposeNode.h" -#include "../BlendTreeVector3Math1Node.h" -#include "../BlendTreeVector3Math2Node.h" -#include "../BlendTreeSmoothingNode.h" -#include "../BlendTreeRangeRemapperNode.h" -#include "../BlendTreeTwoLinkIKNode.h" -#include "../BlendTreeLookAtNode.h" -#include "../BlendTreeTransformNode.h" -#include "../BlendTreeMaskLegacyNode.h" -#include "../BlendTreePoseSwitchNode.h" -#include "../BlendTreeVector2DecomposeNode.h" -#include "../BlendTreeVector3DecomposeNode.h" -#include "../BlendTreeVector4DecomposeNode.h" -#include "../BlendTreeDirectionToWeightNode.h" -#include "../BlendTreeMirrorPoseNode.h" -#include "../AnimGraphEntryNode.h" -#include "../AnimGraphExitNode.h" -#include "../BlendTreeParameterNode.h" -#include "../BlendSpace1DNode.h" -#include "../BlendSpace2DNode.h" -#include "../BlendTreeFinalNode.h" -#include "../BlendTree.h" -#include "../BlendSpaceNode.h" -#include "../AnimGraphStateTransition.h" -#include "../AnimGraphMotionCondition.h" -#include "../AnimGraphParameterCondition.h" -#include "../AnimGraphPlayTimeCondition.h" -#include "../AnimGraphStateCondition.h" -#include "../AnimGraphTagCondition.h" -#include "../AnimGraphTimeCondition.h" -#include "../AnimGraphVector2Condition.h" -#include "../BlendTreeFloatConstantNode.h" -#include "../BlendTreeMorphTargetNode.h" -#include "../BlendTreeVector2ComposeNode.h" -#include "../BlendTreeVector3ComposeNode.h" -#include "../BlendTreeVector4ComposeNode.h" -#include "../TwoStringEventData.h" - - -namespace EMotionFX -{ - const AZ::TypeId GetNewTypeIdByOldNodeTypeId(uint32 oldNodeTypeId) - { - switch (oldNodeTypeId) - { - case 0x00000017: return azrtti_typeid(); break; - case 0x00000005: return azrtti_typeid(); break; - case 0x00000002: return azrtti_typeid(); break; - case 0x38658581: return azrtti_typeid(); break; - case 0x32521069: return azrtti_typeid(); break; - case 0x38020071: return azrtti_typeid(); break; - case 0x00000006: return azrtti_typeid(); break; - case 0x00000001: return azrtti_typeid(); break; - case 0x00022100: return azrtti_typeid(); break; - case 0x00022200: return azrtti_typeid(); break; - case 0x00000004: return azrtti_typeid(); break; - case 0x00000013: return azrtti_typeid(); break; - case 0x00000007: return azrtti_typeid(); break; - case 0x00000008: return azrtti_typeid(); break; - case 0x00000009: return azrtti_typeid(); break; - case 0x00000010: return azrtti_typeid(); break; - case 0x00000148: return azrtti_typeid(); break; - case 0x00000012: return azrtti_typeid(); break; - case 0x00000011: return azrtti_typeid(); break; - case 0x00000014: return azrtti_typeid(); break; - case 0x00000016: return azrtti_typeid(); break; - case 0x00002445: return azrtti_typeid(); break; - case 0x00000018: return azrtti_typeid(); break; - case 0x00000020: return azrtti_typeid(); break; - case 0x00000021: return azrtti_typeid(); break; - case 0x00000126: return azrtti_typeid(); break; - case 0x00000227: return azrtti_typeid(); break; - case 0x00000129: return azrtti_typeid(); break; - case 0x00000228: return azrtti_typeid(); break; - case 0x00000128: return azrtti_typeid(); break; - case 0x00000229: return azrtti_typeid(); break; - case 0x00000456: return azrtti_typeid(); break; - case 0x02094017: return azrtti_typeid(); break; - case 0x38427080: return azrtti_typeid(); break; - case 0x00000214: return azrtti_typeid(); break; - case 0x00001286: return azrtti_typeid(); break; - case 0x00040360: return azrtti_typeid(); break; - case 0x00012345: return azrtti_typeid(); break; - case 0x00012346: return azrtti_typeid(); break; - case 0x00001000: return azrtti_typeid(); break; - case 0x00002000: return azrtti_typeid(); break; - case 0x00002123: return azrtti_typeid(); break; - case 0x00002001: return azrtti_typeid(); break; - case 0x09502005: return azrtti_typeid(); break; - case 0x00005210: return azrtti_typeid(); break; - case 0x00029610: return azrtti_typeid(); break; - case 0x00005321: return azrtti_typeid(); break; - default: return AZ::TypeId::CreateNull(); - }; - } - - class LegacyAttributeRotation - { - public: - LegacyAttributeRotation() - {} - - LegacyAttributeRotation(const LegacyAttributeRotation& src): - m_rotation(src.m_rotation), - m_degrees(src.m_degrees), - m_order(src.m_order) - {} - - LegacyAttributeRotation& operator=(const LegacyAttributeRotation& src) - { - m_rotation = src.m_rotation; - m_degrees = src.m_degrees; - m_order = src.m_order; - return *this; - } - - void SetRotation(const AZ::Quaternion& rotation) - { - m_rotation = rotation; - } - - void SetDegrees(const AZ::Vector3& degrees) - { - m_degrees = degrees; - } - - void SetOrder(LegacyERotationOrder order) - { - m_order = order; - } - - const AZ::Quaternion& GetRotation() const - { - return m_rotation; - } - - const AZ::Vector3& GetDegrees() const - { - return m_degrees; - } - - LegacyERotationOrder GetOrder() const - { - return m_order; - } - - private: - AZ::Quaternion m_rotation; /**< The unit quaternion rotation. */ - AZ::Vector3 m_degrees; /**< The rotation angles. As programmer you don't need to setup these values. They are only to display in the GUI. */ - LegacyERotationOrder m_order; /**< The rotation order, which defaults to ZYX. */ - }; - - class LegacyStateFilterLocal - { - public: - LegacyStateFilterLocal() { } - - LegacyStateFilterLocal(const LegacyStateFilterLocal& src) : - m_nodeNames(src.m_nodeNames), - m_groupNames(src.m_groupNames) - { } - - LegacyStateFilterLocal& operator=(const LegacyStateFilterLocal& src) - { - m_nodeNames = src.m_nodeNames; - m_groupNames = src.m_groupNames; - return *this; - } - - void SetNodeNmes(const AZStd::vector& nodeNames) - { - m_nodeNames = nodeNames; - } - - void SetGroupNames(const AZStd::vector& groupNames) - { - m_groupNames = groupNames; - } - - const AZStd::vector& GetNodeNames() const - { - return m_nodeNames; - } - - const AZStd::vector& GetGroupNames() const - { - return m_groupNames; - } - - private: - AZStd::vector m_nodeNames; - AZStd::vector m_groupNames; - }; - -bool LegacyAnimGraphNodeParser::Forward(MCore::File* stream, size_t numBytes) -{ - if(!stream->Forward(numBytes)) - { - AZ_Error("EMotionFX", false, "Unable to skip data in stream"); - return false; - } - return true; -} - -template<> -bool LegacyAttribute::Parse(MCore::File* stream, MCore::Endian::EEndianType endianType) -{ - // Skip the version (not used byt this legacy attribute) - if (!LegacyAnimGraphNodeParser::Forward(stream, sizeof(uint8))) - { - return false; - } - - AZStd::string motionId; - - AZ::u32 numCharacters; - if (stream->Read(&numCharacters, sizeof(AZ::u32)) != sizeof(AZ::u32)) - { - AZ_Error("EMotionFX", false, "Unable to read data in stream"); - return false; - } - MCore::Endian::ConvertUnsignedInt32(&numCharacters, endianType); - - if (numCharacters > 0) - { - motionId.resize(numCharacters); - if (stream->Read(motionId.data(), numCharacters) != numCharacters) - { - AZ_Error("EMotionFX", false, "Unable to read data in stream"); - return false; - } - } - - AZ::Vector2 position; - if (stream->Read(&position, MCore::AttributeVector2::sizeofVector2) != MCore::AttributeVector2::sizeofVector2) - { - AZ_Error("EMotionFX", false, "Unable to read data in stream"); - return false; - } - float x = position.GetX(); - float y = position.GetY(); - MCore::Endian::ConvertFloat(&x, endianType); - MCore::Endian::ConvertFloat(&y, endianType); - position.Set(x, y); - - - AZ::u8 streamTypeFlags; - if (stream->Read(&streamTypeFlags, sizeof(AZ::u8)) != sizeof(AZ::u8)) - { - AZ_Error("EMotionFX", false, "Unable to read data in stream"); - return false; - } - BlendSpaceNode::BlendSpaceMotion::TypeFlags typeFlags = static_cast(streamTypeFlags); - m_value.Set(motionId, position, typeFlags); - return true; -} - -template<> -bool LegacyAttribute>::Parse(MCore::File* stream, MCore::Endian::EEndianType endianType) -{ - // Skip the version (not used byt this legacy attribute) - if (!LegacyAnimGraphNodeParser::Forward(stream, sizeof(uint8))) - { - return false; - } - - // Read the number of entries - uint32 numEntries; - if (stream->Read(&numEntries, sizeof(uint32)) != sizeof(uint32)) - { - AZ_Error("EMotionFX", false, "Unable to read data in stream"); - return false; - } - MCore::Endian::ConvertUnsignedInt32(&numEntries, endianType); - - m_value.resize(numEntries); - for (uint32 i = 0; i < numEntries; ++i) - { - // Read the number of string bytes to follow - uint32 numStringBytes; - if (stream->Read(&numStringBytes, sizeof(uint32)) != sizeof(uint32)) - { - AZ_Error("EMotionFX", false, "LegacyParameterMask: unable to read data in stream"); - return false; - } - MCore::Endian::ConvertUnsignedInt32(&numStringBytes, endianType); - AZStd::string name; - if (numStringBytes > 0) - { - name.resize(numStringBytes); - // Read the string data - if (stream->Read(name.data(), numStringBytes) != numStringBytes) - { - AZ_Error("EMotionFX", false, "LegacyParameterMask: Unable to read data in stream"); - return false; - } - } - m_value[i] = name; - } - - return true; -} - -template<> -bool LegacyAttribute::Parse(MCore::File* stream, MCore::Endian::EEndianType endianType) -{ - // Skip the version (not used byt this legacy attribute) - if (!LegacyAnimGraphNodeParser::Forward(stream, sizeof(uint8))) - { - return false; - } - - // Read the value - AZ::Vector2 streamValue; - if (stream->Read(&streamValue, MCore::AttributeVector2::sizeofVector2) != MCore::AttributeVector2::sizeofVector2) - { - AZ_Error("EMotionFX", false, "Unable to read data in stream"); - return false; - } - - // Convert endian - MCore::Endian::ConvertVector2(&streamValue, endianType); - m_value = streamValue; - return true; -} - -template<> -bool LegacyAttribute::Parse(MCore::File* stream, MCore::Endian::EEndianType endianType) -{ - uint8 version; - if(stream->Read(&version, sizeof(uint8)) != sizeof(uint8)) - { - AZ_Error("EMotionFX", false, "Unable to read data in stream"); - return false; - } - switch (version) - { - case 1: - { - AZ::PackedVector3f streamValue; - if (stream->Read(&streamValue, sizeof(AZ::PackedVector3f)) != sizeof(AZ::PackedVector3f)) - { - return false; - } - - // Convert endian - AZ::Vector3 value(streamValue); - MCore::Endian::ConvertVector3(&value, endianType); - - // Read only the degrees, automatically calculate the quaternion - m_value.SetDegrees(value); - const AZ::Quaternion rotation = MCore::AzEulerAnglesToAzQuat(MCore::Math::DegreesToRadians(value.GetX()), MCore::Math::DegreesToRadians(value.GetY()), MCore::Math::DegreesToRadians(value.GetZ())); - m_value.SetRotation(rotation); - } - break; - case 2: - { - AZ::PackedVector3f streamValue; - if (stream->Read(&streamValue, sizeof(AZ::PackedVector3f)) != sizeof(AZ::PackedVector3f)) - { - return false; - } - - // Convert endian - AZ::Vector3 value(streamValue); - MCore::Endian::ConvertVector3(&value, endianType); - m_value.SetDegrees(value); - - AZ::Quaternion streamValueQ; - if (stream->Read(&streamValueQ, sizeof(AZ::Quaternion)) != sizeof(AZ::Quaternion)) - { - return false; - } - - // Convert endian - MCore::Endian::ConvertQuaternion(&streamValueQ, endianType); - m_value.SetRotation(streamValueQ); - } - break; - case 3: - { - // Read the value - AZ::PackedVector3f streamValue; - if (stream->Read(&streamValue, sizeof(AZ::PackedVector3f)) != sizeof(AZ::PackedVector3f)) - { - return false; - } - - // Convert endian - AZ::Vector3 value(streamValue); - MCore::Endian::ConvertVector3(&value, endianType); - m_value.SetDegrees(value); - - // Read the quaternion - AZ::Quaternion streamValueQ; - if (stream->Read(&streamValueQ, sizeof(AZ::Quaternion)) != sizeof(AZ::Quaternion)) - { - return false; - } - - // Convert endian - MCore::Endian::ConvertQuaternion(&streamValueQ, endianType); - m_value.SetRotation(streamValueQ); - - // Read the rotation order - uint8 order = 0; - if (stream->Read(&order, sizeof(uint8)) != sizeof(uint8)) - { - return false; - } - - m_value.SetOrder(static_cast(order)); - } - break; - default: - { - AZ_Error("EMotionFX", false, "Unknown version %u parsing legacy attribute rotation", version); - return false; - } - break; - } - - return true; -} - -template<> -bool LegacyAttribute::Parse(MCore::File* stream, MCore::Endian::EEndianType endianType) -{ - // Skip the version (not used byt this legacy attribute) - if (!LegacyAnimGraphNodeParser::Forward(stream, sizeof(uint8))) - { - AZ_Error("EMotionFX", false, "Unable to read data in stream"); - return false; - } - - // Read the value - AZ::PackedVector3f streamValue(0.0f); - if (stream->Read(&streamValue, sizeof(AZ::PackedVector3f)) != sizeof(AZ::PackedVector3f)) - { - AZ_Error("EMotionFX", false, "Unable to read data in stream"); - return false; - } - - // Convert endian - AZ::Vector3 value(streamValue); - MCore::Endian::ConvertVector3(&value, endianType); - - m_value = AZ::PackedVector3f(value.GetX(), value.GetY(), value.GetZ()); - return true; -} - -template<> -bool LegacyAttribute::Parse(MCore::File* stream, MCore::Endian::EEndianType endianType) -{ - AZ_UNUSED(endianType); - // Skip the version (not used byt this legacy attribute) - if (!LegacyAnimGraphNodeParser::Forward(stream, sizeof(uint8))) - { - return false; - } - - int8 streamValue; - if (stream->Read(&streamValue, sizeof(int8)) != sizeof(int8)) - { - AZ_Error("EMotionFX", false, "Unable to read data in stream"); - return false; - } - - m_value = (streamValue == 0) ? false : true; - return true; -} - -template<> -bool LegacyAttribute::Parse(MCore::File* stream, MCore::Endian::EEndianType endianType) -{ - // Skip the version (not used byt this legacy attribute) - if (!LegacyAnimGraphNodeParser::Forward(stream, sizeof(uint8))) - { - return false; - } - - // Read the number of characters - uint32 numCharacters; - if (stream->Read(&numCharacters, sizeof(uint32)) != sizeof(uint32)) - { - AZ_Error("EMotionFX", false, "Unable to read data in stream"); - return false; - } - - // Convert endian - MCore::Endian::ConvertUnsignedInt32(&numCharacters, endianType); - AZStd::string nodeName; - // Read the character data - if (numCharacters > 0) - { - nodeName.resize(numCharacters); - if (stream->Read( nodeName.data(), sizeof(char) * numCharacters) != (sizeof(char) * numCharacters)) - { - AZ_Error("EMotionFX", false, "Unable to read data in stream"); - return false; - } - } - - // Read the parent depth - uint32 parentDepth; - if (stream->Read(&parentDepth, sizeof(uint32)) != sizeof(uint32)) - { - AZ_Error("EMotionFX", false, "Unable to read data in stream"); - return false; - } - - // Convert endian - MCore::Endian::ConvertUnsignedInt32(&parentDepth, endianType); - m_value.first = nodeName; - m_value.second = parentDepth; - return true; -} - -template<> -bool LegacyAttribute::Parse(MCore::File* stream, MCore::Endian::EEndianType streamEndianType) -{ - // Skip the version (not used byt this legacy attribute) - if (!LegacyAnimGraphNodeParser::Forward(stream, sizeof(uint8))) - { - AZ_Error("EMotionFX", false, "Unable to skip version for legacy attribute State Filter"); - return false; - } - - // Read the number of group entries - uint32 numGroupEntries; - if (stream->Read(&numGroupEntries, sizeof(uint32)) != sizeof(uint32)) - { - AZ_Error("EMotionFX", false, "Unable to read num groups"); - return false; - } - MCore::Endian::ConvertUnsignedInt32(&numGroupEntries, streamEndianType); - - // Read the number of node entries - uint32 numNodeEntries; - if (stream->Read(&numNodeEntries, sizeof(uint32)) != sizeof(uint32)) - { - AZ_Error("EMotionFX", false, "Unable to read num nodes"); - return false; - } - MCore::Endian::ConvertUnsignedInt32(&numNodeEntries, streamEndianType); - - // Read the group entries - AZStd::string convTemp; - - AZStd::vector groupNames; - groupNames.resize(numGroupEntries); - - for (uint32 i = 0; i < numGroupEntries; ++i) - { - // Read the number of string bytes to follow - uint32 numStringBytes; - if (stream->Read(&numStringBytes, sizeof(uint32)) != sizeof(uint32)) - { - AZ_Error("EMotionFX", false, "Unable to read group name size"); - return false; - } - MCore::Endian::ConvertUnsignedInt32(&numStringBytes, streamEndianType); - - // Read the string data - if (numStringBytes > 0) - { - convTemp.resize(numStringBytes); - if (stream->Read(convTemp.data(), numStringBytes) != numStringBytes) - { - AZ_Error("EMotionFX", false, "Unable to read group name"); - return false; - } - } - else - { - convTemp.clear(); - } - - // Add the entry to the mask - groupNames[i] = convTemp; - } - - // Read the node entries - AZStd::vector nodeNames; - nodeNames.resize(numNodeEntries); - for (uint32 i = 0; i < numNodeEntries; ++i) - { - // Read the number of string bytes to follow - uint32 numStringBytes; - if (stream->Read(&numStringBytes, sizeof(uint32)) != sizeof(uint32)) - { - AZ_Error("EMotionFX", false, "Unable to read node name size"); - return false; - } - MCore::Endian::ConvertUnsignedInt32(&numStringBytes, streamEndianType); - - // Read the string data - if (numStringBytes > 0) - { - convTemp.resize(numStringBytes); - if (stream->Read(convTemp.data(), numStringBytes) != numStringBytes) - { - AZ_Error("EMotionFX", false, "Unable to read node name"); - return false; - } - } - else - { - convTemp.clear(); - } - - // Add the entry to the mask - nodeNames[i] = convTemp; - } - m_value.SetNodeNmes(nodeNames); - m_value.SetGroupNames(groupNames); - - return true; -} - -template<> -bool LegacyAttribute::Parse(MCore::File* stream, MCore::Endian::EEndianType endianType) -{ - // Skip the version (not used byt this legacy attribute) - if (!LegacyAnimGraphNodeParser::Forward(stream, sizeof(uint8))) - { - return false; - } - - int32 streamValue; - if (stream->Read(&streamValue, sizeof(int32)) != sizeof(int32)) - { - AZ_Error("EMotionFX", false, "Unable to read data in stream"); - return false; - } - - MCore::Endian::ConvertSignedInt32(&streamValue, endianType); - m_value = streamValue; - return true; -} - -template<> -bool LegacyAttribute>::Parse(MCore::File* stream, MCore::Endian::EEndianType endianType) -{ - // Skip the version (not used byt this legacy attribute) - if (!LegacyAnimGraphNodeParser::Forward(stream, sizeof(uint8))) - { - return false; - } - - // Read the number of entries - uint32 numEntries; - if (stream->Read(&numEntries, sizeof(uint32)) != sizeof(uint32)) - { - AZ_Error("EMotionFX", false, "Unable to read data in stream"); - return false; - } - MCore::Endian::ConvertUnsignedInt32(&numEntries, endianType); - m_value.resize(numEntries); - // Read the entries - for (uint32 i = 0; i < numEntries; ++i) - { - // Read the weight - float weight; - if (stream->Read(&weight, sizeof(float)) != sizeof(float)) - { - AZ_Error("EMotionFX", false, "Unable to read data in stream"); - return false; - } - MCore::Endian::ConvertFloat(&weight, endianType); - - // Read the number of string bytes to follow - uint32 numStringBytes; - if (stream->Read(&numStringBytes, sizeof(uint32)) != sizeof(uint32)) - { - AZ_Error("EMotionFX", false, "Unable to read data in stream"); - return false; - } - MCore::Endian::ConvertUnsignedInt32(&numStringBytes, endianType); - AZStd::string name; - - if (numStringBytes > 0) - { - name.resize(numStringBytes); - - // Read the string data - if (stream->Read(name.data(), numStringBytes) != numStringBytes) - { - AZ_Error("EMotionFX", false, "Unable to read data in stream"); - return false; - } - } - - // Add the entry to the mask - m_value[i].first = name; - m_value[i].second = weight; - } - - return true; -} - -template<> -bool LegacyAttribute::Parse(MCore::File* stream, MCore::Endian::EEndianType endianType) -{ - // Skip the version (not used byt this legacy attribute) - if (!LegacyAnimGraphNodeParser::Forward(stream, sizeof(uint8))) - { - return false; - } - - // Read the number of characters - uint32 numCharacters; - if (stream->Read(&numCharacters, sizeof(uint32)) != sizeof(uint32)) - { - AZ_Error("EMotionFX", false, "Unable to read data in stream"); - return false; - } - - // Convert endian - MCore::Endian::ConvertUnsignedInt32(&numCharacters, endianType); - if (numCharacters == 0) - { - m_value.clear(); - return true; - } - - m_value.resize(numCharacters); - if (stream->Read(m_value.data(), numCharacters) != numCharacters) - { - AZ_Error("EMotionFX", false, "Unable to read data in stream"); - return false; - } - return true; -} - -template<> -bool LegacyAttribute::Parse(MCore::File* stream, MCore::Endian::EEndianType endianType) -{ - // Skip the version (not used byt this legacy attribute) - if (!LegacyAnimGraphNodeParser::Forward(stream, sizeof(uint8))) - { - return false; - } - - float streamValue; - if (stream->Read(&streamValue, sizeof(float)) != sizeof(float)) - { - AZ_Error("EMotionFX", false, "Unable to read data in stream"); - return false; - } - - MCore::Endian::ConvertFloat(&streamValue, endianType); - - m_value = streamValue; - return true; -} - -template -const T& LegacyAttribute::GetValue() const -{ - return m_value; -} - -bool LegacyAnimGraphNodeParser::GetBlendSpaceNodeEvaluatorTypeId(uint32 legacyIndex, AZ::TypeId& value) -{ - bool result = true; - switch (legacyIndex) - { - case 0: - { - value = azrtti_typeid(); - } - break; - case 1: - { - value = azrtti_typeid(); - } - break; - case 2: - { - value = azrtti_typeid(); - } - break; - case 3: - { - value = azrtti_typeid(); - } - break; - case 4: - { - value = azrtti_typeid(); - } - break; - case 5: - { - value = azrtti_typeid(); - } - break; - case 6: - { - value = azrtti_typeid(); - } - break; - case 7: - { - value = azrtti_typeid(); - } - break; - case 8: - { - value = azrtti_typeid(); - } - break; - default: - { - result = false; - AZ_Error("EMotionFX", false, "LegacyAnimGraphNodeParser::GetBlendSpaceNodeEvaluatorTypeId: Unknown typeid index"); - } - break; - } - return result; -} - -bool LegacyAnimGraphNodeParser::InitializeNodeGeneralData(const char* nodeName, Importer::ImportParameters& importParams, FileFormat::AnimGraph_NodeHeader& nodeHeader, AnimGraphNode* node) -{ - AnimGraph* animGraph = importParams.mAnimGraph; - node->SetName(nodeName); - - node->SetVisualPos(nodeHeader.mVisualPosX, nodeHeader.mVisualPosY); - node->SetIsCollapsed(nodeHeader.mFlags & FileFormat::ANIMGRAPH_NODEFLAG_COLLAPSED); - - const AZ::Color color( - MCore::ExtractRed(nodeHeader.mVisualizeColor)/255.0f, - MCore::ExtractGreen(nodeHeader.mVisualizeColor)/255.0f, - MCore::ExtractBlue(nodeHeader.mVisualizeColor)/255.0f, - 1.0f); - node->SetVisualizeColor(color); - - if (importParams.mAnimGraphSettings->mDisableNodeVisualization == false) - { - node->SetVisualization((nodeHeader.mFlags & FileFormat::ANIMGRAPH_NODEFLAG_VISUALIZED) != 0); - } - else - { - node->SetVisualization(false); - } - - node->ReserveChildNodes(nodeHeader.mNumChildNodes); - - if (node->GetSupportsDisable()) - { - node->SetIsEnabled(!(nodeHeader.mFlags & FileFormat::ANIMGRAPH_NODEFLAG_DISABLED)); - } - - MCore::Array& blendNodes = SharedHelperData::GetBlendNodes(importParams.mSharedData); - - // Add the new node to the list of loaded nodes - blendNodes.Add(node); - - AZStd::map& entryNodeIndexToStateMachineIdLookupTable = SharedHelperData::GetEntryStateToStateMachineTable(importParams.mSharedData); - - // Add the node to the anim graph - if (nodeHeader.mParentIndex == MCORE_INVALIDINDEX32) - { - AZ_Assert(azrtti_typeid(node) == azrtti_typeid(), ""); - AnimGraphStateMachine* stateMachine = static_cast(node); - - // Set the root state machine - if (animGraph->GetRootStateMachine() == nullptr) - { - animGraph->SetRootStateMachine(stateMachine); - } - else - { - AZ_Warning("EMotionFX", false, "Anim graph already contains a root state machine. Skipping additional root state machines."); - } - } - else - { - blendNodes[nodeHeader.mParentIndex]->AddChildNode(node); - - AZStd::rbtree_const_iterator> tableIter = entryNodeIndexToStateMachineIdLookupTable.find(AZ::u64(blendNodes[nodeHeader.mParentIndex]->GetId())); - if (tableIter != entryNodeIndexToStateMachineIdLookupTable.end()) - { - AnimGraphNode* animGraphNode = animGraph->RecursiveFindNodeById(AnimGraphNodeId((*tableIter).first)); - // The type id check will remove the pointer - if (!animGraphNode) - { - AZ_Error("EMotionFX", false, "Unable to find expected State Machine that needs a registered entry state"); - AZ_Assert(false, "Unable to find expected State Machine that needs a registered entry state"); - return false; - } - if (azrtti_typeid(animGraphNode) != azrtti_typeid()) - { - AZ_Error("EMotionFX", false, "Unexpected parent node type"); - AZ_Assert(false, "Unexpected parent node type"); - return false; - } - AnimGraphStateMachine& parentStateMachine = *(static_cast(animGraphNode)); - uint32 entryStateChildNodeIndex = (*tableIter).second; - if (entryStateChildNodeIndex < parentStateMachine.GetNumChildNodes()) - { - parentStateMachine.SetEntryStateId(parentStateMachine.GetChildNode(entryStateChildNodeIndex)->GetId()); - entryNodeIndexToStateMachineIdLookupTable.erase(tableIter); - } - } - - // Set the final node - if (azrtti_typeid(node) == azrtti_typeid()) - { - AZ_Assert(azrtti_typeid(blendNodes[nodeHeader.mParentIndex]) == azrtti_typeid(), ""); - BlendTree* blendTree = static_cast(blendNodes[nodeHeader.mParentIndex]); - blendTree->SetFinalNodeId(node->GetId()); - } - - // Update the virtual final output node - if (nodeHeader.mFlags & FileFormat::ANIMGRAPH_NODEFLAG_VIRTUALFINALOUTPUT) - { - AZ_Assert(azrtti_typeid(blendNodes[nodeHeader.mParentIndex]) == azrtti_typeid(), ""); - BlendTree* blendTree = static_cast(blendNodes[nodeHeader.mParentIndex]); - blendTree->SetVirtualFinalNode(node); - } - return true; - } - return true; -} - -template<> -bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, - uint32 numAttributes, - MCore::Endian::EEndianType endianType, - Importer::ImportParameters& importParams, - AnimGraphObject& animGraphObject) -{ - AZ_UNUSED(stream); - AZ_UNUSED(numAttributes); - AZ_UNUSED(endianType); - AZ_UNUSED(importParams); - AZ_UNUSED(animGraphObject); - // Do nothing - return true; -} - -template<> -bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, - uint32 numAttributes, - MCore::Endian::EEndianType endianType, - Importer::ImportParameters& importParams, - AnimGraphObject& animGraphObject) -{ - AZ_UNUSED(stream); - AZ_UNUSED(numAttributes); - AZ_UNUSED(endianType); - AZ_UNUSED(importParams); - AZ_UNUSED(animGraphObject); - // Do nothing - return true; -} - -template<> -bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, - uint32 numAttributes, - MCore::Endian::EEndianType endianType, - Importer::ImportParameters& importParams, - AnimGraphObject& animGraphObject) -{ - AZ_UNUSED(stream); - AZ_UNUSED(numAttributes); - AZ_UNUSED(endianType); - AZ_UNUSED(importParams); - AZ_UNUSED(animGraphObject); - // Do nothing - return true; -} - - -template<> -bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, - uint32 numAttributes, - MCore::Endian::EEndianType endianType, - Importer::ImportParameters& importParams, - AnimGraphObject& animGraphObject) -{ - AZ_UNUSED(importParams); - BlendTreeMorphTargetNode& blendTreeMorphTargetNode = static_cast(animGraphObject); - // For all attributes - for (uint32 parsedAttributeCount = 0; parsedAttributeCount < numAttributes; ++parsedAttributeCount) - { - LegacyAttributeHeader legacyAttributeHeader; - if (!LegacyAttributeHeader::Parse(stream, endianType, legacyAttributeHeader)) - { - AZ_Error("EMotionFX", false, "Unable to parse attribute header"); - return false; - } - - if (legacyAttributeHeader.GetAttributeSize() > 0) - { - switch (parsedAttributeCount) - { - case 0: - { - LegacyAttributeArray legacyAttributeArrayStrings; - if (!legacyAttributeArrayStrings.Parse(stream, endianType)) - { - return false; - } - AZStd::vector morphTargetNames; - morphTargetNames.resize(legacyAttributeArrayStrings.GetValue().size()); - for (int i = 0; i < legacyAttributeArrayStrings.GetValue().size(); i++) - { - morphTargetNames[i] = legacyAttributeArrayStrings.GetValue()[i].GetValue(); - } - blendTreeMorphTargetNode.SetMorphTargetNames(morphTargetNames); - } - break; - default: - { - AZ_Error("EMotionFX", false, "LegacyAnimGraphNodeParser::ParseLegacyAttributes: Unexpected attribute count"); - return false; - } - break; - } - } - } - return true; -} - - - -template<> -bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, - uint32 numAttributes, - MCore::Endian::EEndianType endianType, - Importer::ImportParameters& importParams, - AnimGraphObject& animGraphObject) -{ - AZ_UNUSED(importParams); - BlendTreeFloatConstantNode& blendTreeFloatConstantNode = static_cast(animGraphObject); - // For all attributes - for (uint32 parsedAttributeCount = 0; parsedAttributeCount < numAttributes; ++parsedAttributeCount) - { - LegacyAttributeHeader legacyAttributeHeader; - if (!LegacyAttributeHeader::Parse(stream, endianType, legacyAttributeHeader)) - { - AZ_Error("EMotionFX", false, "Unable to parse attribute header"); - return false; - } - - if (legacyAttributeHeader.GetAttributeSize() > 0) - { - switch (parsedAttributeCount) - { - case 0: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - blendTreeFloatConstantNode.SetValue(floatValue); - } - break; - default: - { - AZ_Error("EMotionFX", false, "LegacyAnimGraphNodeParser::ParseLegacyAttributes: Unexpected attribute count"); - return false; - } - break; - } - } - } - return true; -} - -template<> -bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, - uint32 numAttributes, - MCore::Endian::EEndianType endianType, - Importer::ImportParameters& importParams, - AnimGraphObject& animGraphObject) -{ - AZ_UNUSED(importParams); - BlendTreeLookAtNode& blendTreeLookAtNode = static_cast(animGraphObject); - // For all attributes - for (uint32 parsedAttributeCount = 0; parsedAttributeCount < numAttributes; ++parsedAttributeCount) - { - LegacyAttributeHeader legacyAttributeHeader; - if (!LegacyAttributeHeader::Parse(stream, endianType, legacyAttributeHeader)) - { - AZ_Error("EMotionFX", false, "Unable to parse attribute header"); - return false; - } - - if (legacyAttributeHeader.GetAttributeSize() > 0) - { - switch (parsedAttributeCount) - { - case 0: - { - LegacyAttribute legacyAttribute; - if (!legacyAttribute.Parse(stream, endianType)) - { - return false; - } - blendTreeLookAtNode.SetTargetNodeName(legacyAttribute.GetValue()); - } - break; - case 1: - { - LegacyAttribute legacyAttribute; - if (!legacyAttribute.Parse(stream, endianType)) - { - return false; - } - blendTreeLookAtNode.SetLimitMin(legacyAttribute.GetValue()); - } - break; - case 2: - { - LegacyAttribute legacyAttribute; - if (!legacyAttribute.Parse(stream, endianType)) - { - return false; - } - blendTreeLookAtNode.SetLimitMax(legacyAttribute.GetValue()); - } - break; - case 3: - { - LegacyAttribute legacyAttribute; - if (!legacyAttribute.Parse(stream, endianType)) - { - return false; - } - - blendTreeLookAtNode.SetConstraintRotation(legacyAttribute.GetValue().GetRotation()); - } - break; - case 4: - { - LegacyAttribute legacyAttribute; - if (!legacyAttribute.Parse(stream, endianType)) - { - return false; - } - - blendTreeLookAtNode.SetPostRotation(legacyAttribute.GetValue().GetRotation()); - } - break; - case 5: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - blendTreeLookAtNode.SetFollowSpeed(floatValue); - } - break; - case 6: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - ConstraintTransformRotationAngles::EAxis axis = static_cast(static_cast(floatValue)); - blendTreeLookAtNode.SetTwistAxis(axis); - } - break; - case 7: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - bool limitsEnabled = LegacyAnimGraphNodeParser::ConvertFloatAttributeValueToBool(floatValue); - blendTreeLookAtNode.SetLimitsEnabled(limitsEnabled); - } - break; - default: - { - AZ_Error("EMotionFX", false, "Unexpected attribute count"); - return false; - } - break; - } - } - } - return true; -} - -template<> -bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, - uint32 numAttributes, - MCore::Endian::EEndianType endianType, - Importer::ImportParameters& importParams, - AnimGraphObject& animGraphObject) -{ - AZ_UNUSED(importParams); - BlendTreeTwoLinkIKNode& blendTreeTwoLinkIKNode = static_cast(animGraphObject); - // For all attributes - for (uint32 parsedAttributeCount = 0; parsedAttributeCount < numAttributes; ++parsedAttributeCount) - { - LegacyAttributeHeader legacyAttributeHeader; - if (!LegacyAttributeHeader::Parse(stream, endianType, legacyAttributeHeader)) - { - AZ_Error("EMotionFX", false, "Unable to parse attribute header"); - return false; - } - - if (legacyAttributeHeader.GetAttributeSize() > 0) - { - switch (parsedAttributeCount) - { - case 0: - { - LegacyAttribute legacyAttribute; - if (!legacyAttribute.Parse(stream, endianType)) - { - return false; - } - blendTreeTwoLinkIKNode.SetEndNodeName(legacyAttribute.GetValue()); - } - break; - case 1: - { - LegacyAttribute legacyAttribute; - if (!legacyAttribute.Parse(stream, endianType)) - { - return false; - } - blendTreeTwoLinkIKNode.SetEndEffectorNodeName(legacyAttribute.GetValue()); - } - break; - case 2: - { - LegacyAttribute legacyAttribute; - if (!legacyAttribute.Parse(stream, endianType)) - { - return false; - } - blendTreeTwoLinkIKNode.SetAlignToNode(legacyAttribute.GetValue()); - } - break; - case 3: - { - LegacyAttribute legacyAttribute; - if (!legacyAttribute.Parse(stream, endianType)) - { - return false; - } - blendTreeTwoLinkIKNode.SetBendDirNodeName(legacyAttribute.GetValue()); - } - break; - case 4: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - bool boolValue = LegacyAnimGraphNodeParser::ConvertFloatAttributeValueToBool(floatValue); - blendTreeTwoLinkIKNode.SetRotationEnabled(boolValue); - } - break; - case 5: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - bool boolValue = LegacyAnimGraphNodeParser::ConvertFloatAttributeValueToBool(floatValue); - blendTreeTwoLinkIKNode.SetRelativeBendDir(boolValue); - } - break; - case 6: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - bool boolValue = LegacyAnimGraphNodeParser::ConvertFloatAttributeValueToBool(floatValue); - blendTreeTwoLinkIKNode.SetExtractBendDir(boolValue); - } - break; - default: - { - AZ_Error("EMotionFX", false, "Unexpected attribute count"); - return false; - } - break; - } - } - } - return true; -} - - -template<> -bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, - uint32 numAttributes, - MCore::Endian::EEndianType endianType, - Importer::ImportParameters& importParams, - AnimGraphObject& animGraphObject) -{ - AZ_UNUSED(importParams); - BlendTreeFloatMath1Node& blendTreeFloatMath1Node = static_cast(animGraphObject); - // For all attributes - for (uint32 parsedAttributeCount = 0; parsedAttributeCount < numAttributes; ++parsedAttributeCount) - { - LegacyAttributeHeader legacyAttributeHeader; - if (!LegacyAttributeHeader::Parse(stream, endianType, legacyAttributeHeader)) - { - AZ_Error("EMotionFX", false, "Unable to parse attribute header"); - return false; - } - - if (legacyAttributeHeader.GetAttributeSize() > 0) - { - switch (parsedAttributeCount) - { - case 0: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - BlendTreeFloatMath1Node::EMathFunction eMathFunction = static_cast(static_cast(floatValue)); - blendTreeFloatMath1Node.SetMathFunction(eMathFunction); - } - break; - default: - { - AZ_Error("EMotionFX", false, "Unexpected attribute count"); - return false; - } - break; - } - } - } - return true; -} -template<> -bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, - uint32 numAttributes, - MCore::Endian::EEndianType endianType, - Importer::ImportParameters& importParams, - AnimGraphObject& animGraphObject) -{ - AnimGraphStateTransition& animGraphStateTransition = static_cast(animGraphObject); - // For all attributes - for (uint32 parsedAttributeCount = 0; parsedAttributeCount < numAttributes; ++parsedAttributeCount) - { - LegacyAttributeHeader legacyAttributeHeader; - if (!LegacyAttributeHeader::Parse(stream, endianType, legacyAttributeHeader)) - { - AZ_Error("EMotionFX", false, "Unable to parse attribute header"); - return false; - } - - if (legacyAttributeHeader.GetAttributeSize() > 0) - { - switch (parsedAttributeCount) - { - case 0:// ATTRIB_DISABLED - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - AZ_Error("EMotionFX", false, "Unable to parse ATTRIB_DISABLED"); - return false; - } - bool isDisabled = LegacyAnimGraphNodeParser::ConvertFloatAttributeValueToBool(floatValue); - animGraphStateTransition.SetIsDisabled(isDisabled); - } - break; - case 1:// ATTRIB_PRIORITY - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - AZ_Error("EMotionFX", false, "Unable to parse ATTRIB_PRIORITY"); - return false; - } - int32 intValue = static_cast(floatValue); - animGraphStateTransition.SetPriority(intValue); - } - break; - case 2:// ATTRIB_CANBEINTERRUPTED - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - AZ_Error("EMotionFX", false, "Unable to parse ATTRIB_CANBEINTERRUPTED"); - return false; - } - bool canBeInterrupted = LegacyAnimGraphNodeParser::ConvertFloatAttributeValueToBool(floatValue); - animGraphStateTransition.SetCanBeInterrupted(canBeInterrupted); - } - break; - case 3:// ATTRIB_CANINTERRUPTOTHERTRANSITIONS - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - AZ_Error("EMotionFX", false, "Unable to parse ATTRIB_CANINTERRUPTOTHERTRANSITIONS"); - return false; - } - bool canInterruptOtherTransitions = LegacyAnimGraphNodeParser::ConvertFloatAttributeValueToBool(floatValue); - animGraphStateTransition.SetCanInterruptOtherTransitions(canInterruptOtherTransitions); - } - break; - case 4:// ATTRIB_ALLOWSELFINTERRUPTION - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - AZ_Error("EMotionFX", false, "Unable to parse ATTRIB_ALLOWSELFINTERRUPTION"); - return false; - } - bool allowSelfInterruption = LegacyAnimGraphNodeParser::ConvertFloatAttributeValueToBool(floatValue); - animGraphStateTransition.SetCanInterruptItself(allowSelfInterruption); - } - break; - case 5:// ATTRIB_ALLOWEDSTATES - { - LegacyAttribute legacyAttribute; - if (!legacyAttribute.Parse(stream, endianType)) - { - AZ_Error("EMotionFX", false, "Unable to parse legacy attribute state filter"); - return false; - } - - animGraphStateTransition.SetGroups(legacyAttribute.GetValue().GetGroupNames()); - AZStd::vector nodeIDs; - nodeIDs.resize(legacyAttribute.GetValue().GetNodeNames().size()); - int index = 0; - for (int i = 0; i < legacyAttribute.GetValue().GetNodeNames().size(); i++) - { - AnimGraphNode* node = importParams.mAnimGraph->RecursiveFindNodeByName(legacyAttribute.GetValue().GetNodeNames()[i].c_str()); - if (!node) - { - AZ_Warning("EMotionFX", false, "Missing allowed wild card transition on node (%s): The state (%s) in the allowed source state list does not exist in the graph. Removing." - , animGraphStateTransition.GetTargetNode()->GetName(), legacyAttribute.GetValue().GetNodeNames()[i].c_str()); - } - else - { - nodeIDs[index++] = node->GetId(); - } - } - animGraphStateTransition.SetStateIds(nodeIDs); - } - break; - case 6:// ATTRIB_BLENDTIME - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - AZ_Error("EMotionFX", false, "Unable to parse ATTRIB_BLENDTIME"); - return false; - } - animGraphStateTransition.SetBlendTime(floatValue); - } - break; - case 7:// ATTRIB_SYNC - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - AZ_Error("EMotionFX", false, "Unable to parse ATTRIB_SYNC"); - return false; - } - AnimGraphStateTransition::ESyncMode eSyncMode = static_cast(static_cast(floatValue)); - animGraphStateTransition.SetSyncMode(eSyncMode); - } - break; - case 8:// ATTRIB_EVENTMODE - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - AZ_Error("EMotionFX", false, "Unable to parse ATTRIB_EVENTMODE"); - return false; - } - AnimGraphStateTransition::EEventMode eventMode = static_cast(static_cast(floatValue)); - animGraphStateTransition.SetEventFilterMode(eventMode); - } - break; - case 9:// ATTRIB_INTERPOLATIONTYPE - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - AZ_Error("EMotionFX", false, "Unable to parse ATTRIB_INTERPOLATIONTYPE"); - return false; - } - AnimGraphStateTransition::EInterpolationType interpolationType = static_cast(static_cast(floatValue)); - animGraphStateTransition.SetInterpolationType(interpolationType); - } - break; - case 10:// ATTRIB_EASEIN_SMOOTH - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - AZ_Error("EMotionFX", false, "Unable to parse ATTRIB_EASEIN_SMOOTH"); - return false; - } - animGraphStateTransition.SetEaseInSmoothness(floatValue); - } - break; - case 11:// ATTRIB_EASEOUT_SMOOTH - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - AZ_Error("EMotionFX", false, "Unable to parse ATTRIB_EASEOUT_SMOOTH"); - return false; - } - animGraphStateTransition.SetEaseOutSmoothness(floatValue); - } - break; - default: - { - AZ_Error("EMotionFX", false, "Unexpected attribute count parsing AnimGraphStateTransition"); - return false; - } - break; - } - } - } - return true; -} - -template<> -bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, - uint32 numAttributes, - MCore::Endian::EEndianType endianType, - Importer::ImportParameters& importParams, - AnimGraphObject& animGraphObject) -{ - AZ_UNUSED(importParams); - AnimGraphStateMachine& animGraphStateMachine = static_cast(animGraphObject); - // For all attributes - for (uint32 parsedAttributeCount = 0; parsedAttributeCount < numAttributes; ++parsedAttributeCount) - { - LegacyAttributeHeader legacyAttributeHeader; - if (!LegacyAttributeHeader::Parse(stream, endianType, legacyAttributeHeader)) - { - AZ_Error("EMotionFX", false, "Unable to parse attribute header"); - return false; - } - - if (legacyAttributeHeader.GetAttributeSize() > 0) - { - switch (parsedAttributeCount) - { - case 0: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - bool alwaysStartInEntryState = LegacyAnimGraphNodeParser::ConvertFloatAttributeValueToBool(floatValue); - animGraphStateMachine.SetAlwaysStartInEntryState(alwaysStartInEntryState); - } - break; - default: - { - AZ_Error("EMotionFX", false, "Unexpected attribute count"); - return false; - } - break; - } - } - } - return true; -} - -template<> -bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, - uint32 numAttributes, - MCore::Endian::EEndianType endianType, - Importer::ImportParameters& importParams, - AnimGraphObject& animGraphObject) -{ - AZ_UNUSED(importParams); - BlendTreeRangeRemapperNode& blendTreeRangeRemapperNode = static_cast(animGraphObject); - // For all attributes - for (uint32 parsedAttributeCount = 0; parsedAttributeCount < numAttributes; ++parsedAttributeCount) - { - LegacyAttributeHeader legacyAttributeHeader; - if (!LegacyAttributeHeader::Parse(stream, endianType, legacyAttributeHeader)) - { - AZ_Error("EMotionFX", false, "Unable to parse attribute header"); - return false; - } - - if (legacyAttributeHeader.GetAttributeSize() > 0) - { - switch (parsedAttributeCount) - { - case 0: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - blendTreeRangeRemapperNode.SetInputMin(floatValue); - } - break; - case 1: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - blendTreeRangeRemapperNode.SetInputMax(floatValue); - } - break; - case 2: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - blendTreeRangeRemapperNode.SetOutputMin(floatValue); - } - break; - case 3: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - blendTreeRangeRemapperNode.SetOutputMax(floatValue); - } - break; - default: - { - AZ_Error("EMotionFX", false, "Unexpected attribute count"); - return false; - } - break; - } - } - } - return true; -} - -template<> -bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, - uint32 numAttributes, - MCore::Endian::EEndianType endianType, - Importer::ImportParameters& importParams, - AnimGraphObject& animGraphObject) -{ - AZ_UNUSED(importParams); - BlendTreeSmoothingNode& blendTreeSmoothingNode = static_cast(animGraphObject); - // For all attributes - for (uint32 parsedAttributeCount = 0; parsedAttributeCount < numAttributes; ++parsedAttributeCount) - { - LegacyAttributeHeader legacyAttributeHeader; - if (!LegacyAttributeHeader::Parse(stream, endianType, legacyAttributeHeader)) - { - AZ_Error("EMotionFX", false, "Unable to parse attribute header"); - return false; - } - - if (legacyAttributeHeader.GetAttributeSize() > 0) - { - switch (parsedAttributeCount) - { - case 0: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - blendTreeSmoothingNode.SetInterpolationSpeed(floatValue); - } - break; - case 1: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - bool useStartValue = LegacyAnimGraphNodeParser::ConvertFloatAttributeValueToBool(floatValue); - blendTreeSmoothingNode.SetUseStartVAlue(useStartValue); - } - break; - case 2: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - blendTreeSmoothingNode.SetStartVAlue(floatValue); - } - break; - default: - { - AZ_Error("EMotionFX", false, "Unexpected attribute count"); - return false; - } - break; - } - } - } - return true; -} - -template<> -bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, - uint32 numAttributes, - MCore::Endian::EEndianType endianType, - Importer::ImportParameters& importParams, - AnimGraphObject& animGraphObject) -{ - AZ_UNUSED(importParams); - BlendTreeVector3Math2Node& blendTreeVector3Math2Node = static_cast(animGraphObject); - // For all attributes - for (uint32 parsedAttributeCount = 0; parsedAttributeCount < numAttributes; ++parsedAttributeCount) - { - LegacyAttributeHeader legacyAttributeHeader; - if (!LegacyAttributeHeader::Parse(stream, endianType, legacyAttributeHeader)) - { - AZ_Error("EMotionFX", false, "Unable to parse attribute header"); - return false; - } - - if (legacyAttributeHeader.GetAttributeSize() > 0) - { - switch (parsedAttributeCount) - { - case 0: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - BlendTreeVector3Math2Node::EMathFunction eMathFunction = static_cast(static_cast(floatValue)); - blendTreeVector3Math2Node.SetMathFunction(eMathFunction); - } - break; - case 1: - { - LegacyAttribute legacyAttribute; - if (!legacyAttribute.Parse(stream, endianType)) - { - return false; - } - blendTreeVector3Math2Node.SetDefaultValue(AZ::Vector3(legacyAttribute.GetValue())); - } - break; - default: - { - AZ_Error("EMotionFX", false, "Unexpected attribute count"); - return false; - } - break; - } - } - } - return true; -} - -template<> -bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, - uint32 numAttributes, - MCore::Endian::EEndianType endianType, - Importer::ImportParameters& importParams, - AnimGraphObject& animGraphObject) -{ - AZ_UNUSED(importParams); - BlendTreeVector3Math1Node& blendTreeVector3Math1Node = static_cast(animGraphObject); - // For all attributes - for (uint32 parsedAttributeCount = 0; parsedAttributeCount < numAttributes; ++parsedAttributeCount) - { - LegacyAttributeHeader legacyAttributeHeader; - if (!LegacyAttributeHeader::Parse(stream, endianType, legacyAttributeHeader)) - { - AZ_Error("EMotionFX", false, "Unable to parse attribute header"); - return false; - } - - if (legacyAttributeHeader.GetAttributeSize() > 0) - { - switch (parsedAttributeCount) - { - case 0: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - BlendTreeVector3Math1Node::EMathFunction eMathFunction = static_cast(static_cast(floatValue)); - blendTreeVector3Math1Node.SetMathFunction(eMathFunction); - } - break; - default: - { - AZ_Error("EMotionFX", false, "Unexpected attribute count"); - return false; - } - break; - } - } - } - return true; -} - -template<> -bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, - uint32 numAttributes, - MCore::Endian::EEndianType endianType, - Importer::ImportParameters& importParams, - AnimGraphObject& animGraphObject) -{ - AZ_UNUSED(importParams); - BlendTreeFloatMath2Node& blendTreeFloatMath2Node = static_cast(animGraphObject); - // For all attributes - for (uint32 parsedAttributeCount = 0; parsedAttributeCount < numAttributes; ++parsedAttributeCount) - { - LegacyAttributeHeader legacyAttributeHeader; - if (!LegacyAttributeHeader::Parse(stream, endianType, legacyAttributeHeader)) - { - AZ_Error("EMotionFX", false, "Unable to parse attribute header"); - return false; - } - - if (legacyAttributeHeader.GetAttributeSize() > 0) - { - switch (parsedAttributeCount) - { - case 0: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - BlendTreeFloatMath2Node::EMathFunction eMathFunction = static_cast(static_cast(floatValue)); - blendTreeFloatMath2Node.SetMathFunction(eMathFunction); - } - break; - case 1: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - blendTreeFloatMath2Node.SetDefaultValue(floatValue); - } - break; - default: - { - AZ_Error("EMotionFX", false, "Unexpected attribute count"); - return false; - } - break; - } - } - } - return true; -} - -template<> -bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, - uint32 numAttributes, - MCore::Endian::EEndianType endianType, - Importer::ImportParameters& importParams, - AnimGraphObject& animGraphObject) -{ - AZ_UNUSED(importParams); - BlendTreeBlend2LegacyNode& blendTreeBlend2Node = static_cast(animGraphObject); - // For all attributes - for (uint32 parsedAttributeCount = 0; parsedAttributeCount < numAttributes; ++parsedAttributeCount) - { - LegacyAttributeHeader legacyAttributeHeader; - if (!LegacyAttributeHeader::Parse(stream, endianType, legacyAttributeHeader)) - { - AZ_Error("EMotionFX", false, "Unable to parse attribute header"); - return false; - } - - if (legacyAttributeHeader.GetAttributeSize() > 0) - { - switch (parsedAttributeCount) - { - case 0: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - AnimGraphObject::ESyncMode syncMode = static_cast(static_cast(floatValue)); - blendTreeBlend2Node.SetSyncMode(syncMode); - } - break; - case 1: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - AnimGraphObject::EEventMode eventMode = static_cast(static_cast(floatValue)); - blendTreeBlend2Node.SetEventMode(eventMode); - } - break; - case 2: - { - LegacyAttribute> legacyAttributeNodeMask; - if (!legacyAttributeNodeMask.Parse(stream, endianType)) - { - return false; - } - blendTreeBlend2Node.SetWeightedNodeMask(legacyAttributeNodeMask.GetValue()); - } - break; - case 3: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - bool isAdditive = LegacyAnimGraphNodeParser::ConvertFloatAttributeValueToBool(floatValue); - blendTreeBlend2Node.SetAdditiveBlending(isAdditive); - } - break; - default: - { - AZ_Error("EMotionFX", false, "Unexpected attribute count"); - return false; - } - break; - - } - } - } - return true; -} - -bool LegacyAnimGraphNodeParser::ConvertFloatAttributeValueToBool(float value) -{ - return value > MCore::Math::epsilon; -} - -bool LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(MCore::File* stream - , MCore::Endian::EEndianType endianType - , const LegacyAttributeHeader& attributeHeader - , float& outputValue) -{ - bool result = true; - switch (attributeHeader.GetAttributeType()) - { - case EMotionFX::LegacyAttributeTypeId::ATTRIBUTE_BOOL_TYPE_ID: - { - LegacyAttribute legacyAttribute; - if (!legacyAttribute.Parse(stream, endianType)) - { - result = false; - } - else - { - outputValue = legacyAttribute.GetValue() ? 1.0f : 0.0f; - } - } - break; - case EMotionFX::LegacyAttributeTypeId::ATTRIBUTE_INT32_TYPE_ID: - { - LegacyAttribute legacyAttribute; - if (!legacyAttribute.Parse(stream, endianType)) - { - result = false; - } - else - { - outputValue = static_cast(legacyAttribute.GetValue()); - } - } - break; - case EMotionFX::LegacyAttributeTypeId::ATTRIBUTE_FLOAT_TYPE_ID: - { - LegacyAttribute legacyAttribute; - if (!legacyAttribute.Parse(stream, endianType)) - { - result = false; - } - outputValue = legacyAttribute.GetValue(); - } - break; - default: - { - AZ_Error("EMotionFX", false, "Unexpected attribute type"); - result = false; - } - break; - } - if (!result) - { - AZ_Error("EMotionFX", false, "LegacyAnimGraphNodeParser::TryGetFloatFromAttribute Unable to parse attribute value"); - } - return result; -} - -bool LegacyAttributeHeader::Parse(MCore::File* stream, MCore::Endian::EEndianType endianType, LegacyAttributeHeader& attributeHeader) -{ - AZStd::string name; - name.resize(32); - - // Read the attribute size - uint32 attribType; - if (stream->Read(&attribType, sizeof(uint32)) != sizeof(uint32)) - { - AZ_Error("EMotionFX", false, "Unable to read data in stream"); - return false; - } - MCore::Endian::ConvertUnsignedInt32(&attribType, endianType); - - // Read the attribute size - uint32 attributeSize; - if (stream->Read(&attributeSize, sizeof(uint32)) != sizeof(uint32)) - { - AZ_Error("EMotionFX", false, "Unable to read data in stream"); - return false; - } - MCore::Endian::ConvertUnsignedInt32(&attributeSize, endianType); - - // First read the number of characters - uint32 numCharacters; - if (stream->Read(&numCharacters, sizeof(uint32)) != sizeof(uint32)) - { - AZ_Error("EMotionFX", false, "Unable to read data in stream"); - return false; - } - MCore::Endian::ConvertUnsignedInt32(&numCharacters, endianType); - - // Read the string - if (numCharacters > 0) - { - name.resize(numCharacters); - if (stream->Read(name.data(), numCharacters) != numCharacters) - { - AZ_Error("EMotionFX", false, "Unable to read data in stream"); - return false; - } - } - - attributeHeader.m_attribType = attribType; - attributeHeader.m_attributeSize = attributeSize; - attributeHeader.m_name = name; - return true; -} - -template class LegacyAttribute> -bool LegacyAttributeArray::PopulateAttributeDynamicArray(MCore::File* stream, MCore::Endian::EEndianType endianType) -{ - // Read the number of values - uint32 numValues; - if (stream->Read(&numValues, sizeof(uint32)) != sizeof(uint32)) - { - return false; - } - MCore::Endian::ConvertUnsignedInt32(&numValues, endianType); - - for (uint32 i = 0; i < numValues; ++i) - { - LegacyAttribute legacyAttribute; - legacyAttribute.Parse(stream, endianType); - m_attributes.push_back(legacyAttribute); - } - return true; -} - -template class LegacyAttribute> -bool LegacyAttributeArray::Parse(MCore::File* stream, MCore::Endian::EEndianType endianType) -{ - // Write the version of the attribute settings format - uint8 version; - if (stream->Read(&version, sizeof(uint8)) != sizeof(uint8)) - { - AZ_Error("EMotionFX", false, "LegacyAttributeArray::Parse - Failed to read the attribute version."); - return false; - } - if (version == 2) - { - // Read the attribute type id - uint32 attribType; - if (stream->Read(&attribType, sizeof(uint32)) != sizeof(uint32)) - { - AZ_Error("EMotionFX", false, "AttributeArray::ReadData() - Failed to read the attribute type ID."); - return false; - } - MCore::Endian::ConvertUnsignedInt32(&attribType, endianType); - m_elementTypeId = attribType; - - if (!LegacyAttributeSettingsParser::Parse(stream, endianType)) - { - return false; - } - } - return PopulateAttributeDynamicArray(stream, endianType); -} - -template class LegacyAttribute> -const AZStd::vector< LegacyAttribute > & LegacyAttributeArray::GetValue() const -{ - return m_attributes; -} - -bool LegacyAttributeSettingsParser::Parse(MCore::File* stream, MCore::Endian::EEndianType endianType) -{ - // Write the version of the attribute settings format - uint8 version; - if (stream->Read(&version, sizeof(uint8)) != sizeof(uint8)) - { - AZ_Error("EMotionFX", false, "LegacyAttributeSettingsParser::Parse - Failed to read the attribute version."); - return false; - } - - if (version == 2) - { - // Read the flags (new in version 2) - uint16 flags = 0; - if (stream->Read(&flags, sizeof(uint16)) != sizeof(uint16)) - { - return false; - } - MCore::Endian::ConvertUnsignedInt16(&flags, endianType); - } - - // Read the internal name - uint32 numChars; - if (stream->Read(&numChars, sizeof(uint32)) != sizeof(uint32)) - { - return false; - } - MCore::Endian::ConvertUnsignedInt32(&numChars, endianType); - - AZStd::string tempString; - if (numChars > 0) - { - tempString.resize(numChars); - if (stream->Read(tempString.data(), numChars) != numChars) - { - return false; - } - } - - // Read the name - if (stream->Read(&numChars, sizeof(uint32)) != sizeof(uint32)) - { - return false; - } - MCore::Endian::ConvertUnsignedInt32(&numChars, endianType); - tempString.clear(); - if (numChars > 0) - { - tempString.resize(numChars); - if (stream->Read(tempString.data(), numChars) != numChars) - { - return false; - } - } - - // Read the description - if (stream->Read(&numChars, sizeof(uint32)) != sizeof(uint32)) - { - return false; - } - MCore::Endian::ConvertUnsignedInt32(&numChars, endianType); - tempString.clear(); - if (numChars > 0) - { - tempString.resize(numChars); - if (stream->Read(tempString.data(), numChars) != numChars) - { - return false; - } - } - - // Read the interface type - uint32 interfaceType; - if (stream->Read(&interfaceType, sizeof(uint32)) != sizeof(uint32)) - { - return false; - } - MCore::Endian::ConvertUnsignedInt32(&interfaceType, endianType); - - // Read the number of combobox values - uint32 numComboValues; - if (stream->Read(&numComboValues, sizeof(uint32)) != sizeof(uint32)) - { - return false; - } - MCore::Endian::ConvertUnsignedInt32(&numComboValues, endianType); - - // Read the combo strings - for (uint32 i = 0; i < numComboValues; ++i) - { - tempString.clear(); - if (stream->Read(&numChars, sizeof(uint32)) != sizeof(uint32)) - { - return false; - } - MCore::Endian::ConvertUnsignedInt32(&numChars, endianType); - if (numChars > 0) - { - tempString.resize(numChars); - if (stream->Read(tempString.data(), numChars) != numChars) - { - return false; - } - } - } - - for (int skipCounter = 0; skipCounter < 3; ++skipCounter) - { - // Skipping attribute type (default value of settings) - if (!LegacyAnimGraphNodeParser::Forward(stream, sizeof(uint32))) - { - return false; - } - - // Read the attribute size - uint32 attributeSize; - if (stream->Read(&attributeSize, sizeof(uint32)) != sizeof(uint32)) - { - return false; - } - MCore::Endian::ConvertUnsignedInt32(&attributeSize, endianType); - // Skipping attribute content (default value of settings) - if (!LegacyAnimGraphNodeParser::Forward(stream, attributeSize)) - { - return false; - } - } - - return true; -} - -template class LegacyAttribute; -template class LegacyAttribute; -template class LegacyAttribute; -template class LegacyAttribute; -template class LegacyAttribute; -template class LegacyAttribute>; -template class LegacyAttribute>; -template class LegacyAttribute; -template class LegacyAttribute; -template class LegacyAttribute; -template class LegacyAttribute; -template class LegacyAttribute; -template class LegacyAttributeArray; -template class LegacyAttributeArray; - - -bool LegacyAnimGraphNodeParser::ParseTransitionConditionChunk(MCore::File* file, - Importer::ImportParameters& importParams, - const FileFormat::AnimGraph_NodeHeader& nodeHeader, - AnimGraphTransitionCondition*& transitionCondition) -{ - const AZ::TypeId conditionType = GetNewTypeIdByOldNodeTypeId(nodeHeader.mTypeID); - if (conditionType.IsNull()) - { - AZ_Error("EMotionFX", false, "LegacyAnimGraphNodeParser: Cannot convert legacy transition condition id '0x%x' to uuid.", nodeHeader.mTypeID); - return false; - } - - if (conditionType == azrtti_typeid()) - { - if (!ParseAnimGraphTransitionCondition(file, importParams, nodeHeader, transitionCondition)) - { - AZ_Error("EMotionFX", false, "Unable to parse AnimGraphMotionCondition"); - return false; - } - } - else if (conditionType == azrtti_typeid()) - { - if (!ParseAnimGraphTransitionCondition(file, importParams, nodeHeader, transitionCondition)) - { - AZ_Error("EMotionFX", false, "Unable to parse AnimGraphParameterCondition"); - return false; - } - transitionCondition->SetAnimGraph(importParams.mAnimGraph); - } - else if (conditionType == azrtti_typeid()) - { - if (!ParseAnimGraphTransitionCondition(file, importParams, nodeHeader, transitionCondition)) - { - AZ_Error("EMotionFX", false, "Unable to parse AnimGraphPlayTimeCondition"); - return false; - } - } - else if (conditionType == azrtti_typeid()) - { - if (!ParseAnimGraphTransitionCondition(file, importParams, nodeHeader, transitionCondition)) - { - AZ_Error("EMotionFX", false, "Unable to parse AnimGraphStateCondition"); - return false; - } - } - else if (conditionType == azrtti_typeid()) - { - if (!ParseAnimGraphTransitionCondition(file, importParams, nodeHeader, transitionCondition)) - { - AZ_Error("EMotionFX", false, "Unable to parse AnimGraphTagCondition"); - return false; - } - } - else if (conditionType == azrtti_typeid()) - { - if (!ParseAnimGraphTransitionCondition(file, importParams, nodeHeader, transitionCondition)) - { - AZ_Error("EMotionFX", false, "Unable to parse AnimGraphTimeCondition"); - return false; - } - } - else if (conditionType == azrtti_typeid()) - { - if (!ParseAnimGraphTransitionCondition(file, importParams, nodeHeader, transitionCondition)) - { - AZ_Error("EMotionFX", false, "Unable to parse AnimGraphVector2Condition"); - return false; - } - } - else - { - AZ_Error("EMotionFX", false, "LegacyAnimGraphNodeParser: Cannot parse transition condition with uuid %s. No node parser available", conditionType.ToString().c_str()); - return false; - } - - return true; -} - - -bool LegacyAnimGraphNodeParser::ParseAnimGraphNodeChunk(MCore::File* file, - Importer::ImportParameters& importParams, - const char* nodeName, - FileFormat::AnimGraph_NodeHeader& nodeHeader, - AnimGraphNode*& node) -{ - const AZ::TypeId nodeType = GetNewTypeIdByOldNodeTypeId(nodeHeader.mTypeID); - if (nodeType.IsNull()) - { - AZ_Error("EMotionFX", false, "LegacyAnimGraphNodeParser: Cannot convert legacy node id '0x%x' to uuid.", nodeHeader.mTypeID); - return false; - } - - if (nodeType == azrtti_typeid()) - { - if (!LegacyAnimGraphNodeParser::ParseAnimGraphNode(file, importParams, nodeName, nodeHeader, node)) - { - AZ_Error("EMotionFX", false, "Unable to parse AnimGraphBindPoseNode"); - return false; - } - } - else if (nodeType == azrtti_typeid()) - { - if (!LegacyAnimGraphNodeParser::ParseAnimGraphNode(file, importParams, nodeName, nodeHeader, node)) - { - AZ_Error("EMotionFX", false, "Unable to parse BlendTree"); - return false; - } - } - else if (nodeType == azrtti_typeid()) - { - if (!LegacyAnimGraphNodeParser::ParseAnimGraphNode(file, importParams, nodeName, nodeHeader, node)) - { - AZ_Error("EMotionFX", false, "Unable to parse BlendTreeFinalNode"); - return false; - } - } - else if (nodeType == azrtti_typeid()) - { - if (!LegacyAnimGraphNodeParser::ParseAnimGraphNode(file, importParams, nodeName, nodeHeader, node)) - { - AZ_Error("EMotionFX", false, "Unable to parse BlendTreeMotionFrameNode"); - return false; - } - } - else if (nodeType == azrtti_typeid()) - { - if (!LegacyAnimGraphNodeParser::ParseAnimGraphNode(file, importParams, nodeName, nodeHeader, node)) - { - AZ_Error("EMotionFX", false, "Unable to parse BlendTreeBlendNNode"); - return false; - } - } - else if (nodeType == azrtti_typeid()) - { - if (!LegacyAnimGraphNodeParser::ParseAnimGraphNode(file, importParams, nodeName, nodeHeader, node)) - { - AZ_Error("EMotionFX", false, "Unable to parse BlendTreeFloatConditionNode"); - return false; - } - } - else if (nodeType == azrtti_typeid()) - { - if (!LegacyAnimGraphNodeParser::ParseAnimGraphNode(file, importParams, nodeName, nodeHeader, node)) - { - AZ_Error("EMotionFX", false, "Unable to parse BlendTreeFloatSwitchNode"); - return false; - } - } - else if (nodeType == azrtti_typeid()) - { - if (!LegacyAnimGraphNodeParser::ParseAnimGraphNode(file, importParams, nodeName, nodeHeader, node)) - { - AZ_Error("EMotionFX", false, "Unable to parse BlendTreeBoolLogicNode"); - return false; - } - } - else if (nodeType == azrtti_typeid()) - { - if (!LegacyAnimGraphNodeParser::ParseAnimGraphNode(file, importParams, nodeName, nodeHeader, node)) - { - AZ_Error("EMotionFX", false, "Unable to parse AnimGraphMotionNode"); - return false; - } - } - else if (nodeType == azrtti_typeid()) - { - if (!LegacyAnimGraphNodeParser::ParseAnimGraphNode(file, importParams, nodeName, nodeHeader, node)) - { - AZ_Error("EMotionFX", false, "Unable to parse BlendTreeAccumTransformNode"); - return false; - } - } - else if (nodeType == azrtti_typeid()) - { - if (!LegacyAnimGraphNodeParser::ParseAnimGraphNode(file, importParams, nodeName, nodeHeader, node)) - { - AZ_Error("EMotionFX", false, "Unable to parse BlendTreeBlend2Node"); - return false; - } - } - else if (nodeType == azrtti_typeid()) - { - if (!LegacyAnimGraphNodeParser::ParseAnimGraphNode(file, importParams, nodeName, nodeHeader, node)) - { - AZ_Error("EMotionFX", false, "Unable to parse BlendTreeFloatMath1Node"); - return false; - } - } - else if (nodeType == azrtti_typeid()) - { - if (!LegacyAnimGraphNodeParser::ParseAnimGraphNode(file, importParams, nodeName, nodeHeader, node)) - { - AZ_Error("EMotionFX", false, "Unable to parse BlendTreeFloatMath2Node"); - return false; - } - } - else if (nodeType == azrtti_typeid()) - { - if (!LegacyAnimGraphNodeParser::ParseAnimGraphNode(file, importParams, nodeName, nodeHeader, node)) - { - AZ_Error("EMotionFX", false, "Unable to parse BlendTreeVector3Math1Node"); - return false; - } - } - else if (nodeType == azrtti_typeid()) - { - if (!LegacyAnimGraphNodeParser::ParseAnimGraphNode(file, importParams, nodeName, nodeHeader, node)) - { - AZ_Error("EMotionFX", false, "Unable to parse BlendTreeVector3Math2Node"); - return false; - } - } - else if (nodeType == azrtti_typeid()) - { - if (!LegacyAnimGraphNodeParser::ParseAnimGraphNode(file, importParams, nodeName, nodeHeader, node)) - { - AZ_Error("EMotionFX", false, "Unable to parse BlendTreeSmoothingNode"); - return false; - } - } - else if (nodeType == azrtti_typeid()) - { - if (!LegacyAnimGraphNodeParser::ParseAnimGraphNode(file, importParams, nodeName, nodeHeader, node)) - { - AZ_Error("EMotionFX", false, "Unable to parse BlendTreeRangeRemapperNode"); - return false; - } - } - else if (nodeType == azrtti_typeid()) - { - if (!LegacyAnimGraphNodeParser::ParseAnimGraphNode(file, importParams, nodeName, nodeHeader, node)) - { - AZ_Error("EMotionFX", false, "Unable to parse AnimGraphStateMachine"); - return false; - } - - // Only for this node we need to read legacy Custom Data. - - // Read the entry state child node index - uint32 entryStateNodeIndex; - if (file->Read(&entryStateNodeIndex, sizeof(uint32)) != sizeof(uint32)) - { - return false; - } - - // Convert endian if needed - MCore::Endian::ConvertUnsignedInt32(&entryStateNodeIndex, importParams.mEndianType); - AZStd::map& entryNodeIndexToStateMachineIdLookupTable = SharedHelperData::GetEntryStateToStateMachineTable(importParams.mSharedData); - if (!entryNodeIndexToStateMachineIdLookupTable.insert(AZStd::pair(node->GetId(), entryStateNodeIndex)).second) - { - AZ_Assert(false, "Same entry state id for different state machines found"); - AZ_Error("EMotionFX", false, "Same entry state id for different state machines found"); - return false; - } - } - else if (nodeType == azrtti_typeid()) - { - if (!LegacyAnimGraphNodeParser::ParseAnimGraphNode(file, importParams, nodeName, nodeHeader, node)) - { - AZ_Error("EMotionFX", false, "Unable to parse BlendTreeTwoLinkIKNode"); - return false; - } - } - else if (nodeType == azrtti_typeid()) - { - if (!LegacyAnimGraphNodeParser::ParseAnimGraphNode(file, importParams, nodeName, nodeHeader, node)) - { - AZ_Error("EMotionFX", false, "Unable to parse BlendTreeLookAtNode"); - return false; - } - } - else if (nodeType == azrtti_typeid()) - { - if (!LegacyAnimGraphNodeParser::ParseAnimGraphNode(file, importParams, nodeName, nodeHeader, node)) - { - AZ_Error("EMotionFX", false, "Unable to parse BlendTreeTransformNode"); - return false; - } - } - else if (nodeType == azrtti_typeid()) - { - if (!LegacyAnimGraphNodeParser::ParseAnimGraphNode(file, importParams, nodeName, nodeHeader, node)) - { - AZ_Error("EMotionFX", false, "Unable to parse BlendTreeMaskLegacyNode"); - return false; - } - } - else if (nodeType == azrtti_typeid()) - { - if (!LegacyAnimGraphNodeParser::ParseAnimGraphNode(file, importParams, nodeName, nodeHeader, node)) - { - AZ_Error("EMotionFX", false, "Unable to parse BlendTreePoseSwitchNode"); - return false; - } - } - else if (nodeType == azrtti_typeid()) - { - if (!LegacyAnimGraphNodeParser::ParseAnimGraphNode(file, importParams, nodeName, nodeHeader, node)) - { - AZ_Error("EMotionFX", false, "Unable to parse BlendTreeVector2DecomposeNode"); - return false; - } - } - else if (nodeType == azrtti_typeid()) - { - if (!LegacyAnimGraphNodeParser::ParseAnimGraphNode(file, importParams, nodeName, nodeHeader, node)) - { - AZ_Error("EMotionFX", false, "Unable to parse BlendTreeVector3DecomposeNode"); - return false; - } - } - else if (nodeType == azrtti_typeid()) - { - if (!LegacyAnimGraphNodeParser::ParseAnimGraphNode(file, importParams, nodeName, nodeHeader, node)) - { - AZ_Error("EMotionFX", false, "Unable to parse BlendTreeVector4DecomposeNode"); - return false; - } - } - else if (nodeType == azrtti_typeid()) - { - if (!LegacyAnimGraphNodeParser::ParseAnimGraphNode(file, importParams, nodeName, nodeHeader, node)) - { - AZ_Error("EMotionFX", false, "Unable to parse BlendTreeVector2ComposeNode"); - return false; - } - } - else if (nodeType == azrtti_typeid()) - { - if (!LegacyAnimGraphNodeParser::ParseAnimGraphNode(file, importParams, nodeName, nodeHeader, node)) - { - AZ_Error("EMotionFX", false, "Unable to parse BlendTreeVector3ComposeNode"); - return false; - } - } - else if (nodeType == azrtti_typeid()) - { - if (!LegacyAnimGraphNodeParser::ParseAnimGraphNode(file, importParams, nodeName, nodeHeader, node)) - { - AZ_Error("EMotionFX", false, "Unable to parse BlendTreeVector4ComposeNode"); - return false; - } - } - else if (nodeType == azrtti_typeid()) - { - if (!LegacyAnimGraphNodeParser::ParseAnimGraphNode(file, importParams, nodeName, nodeHeader, node)) - { - AZ_Error("EMotionFX", false, "Unable to parse BlendTreeDirectionToWeightNode"); - return false; - } - } - else if (nodeType == azrtti_typeid()) - { - if (!LegacyAnimGraphNodeParser::ParseAnimGraphNode(file, importParams, nodeName, nodeHeader, node)) - { - AZ_Error("EMotionFX", false, "Unable to parse BlendTreeMirrorPoseNode"); - return false; - } - } - else if (nodeType == azrtti_typeid()) - { - if (!LegacyAnimGraphNodeParser::ParseAnimGraphNode(file, importParams, nodeName, nodeHeader, node)) - { - AZ_Error("EMotionFX", false, "Unable to parse AnimGraphEntryNode"); - return false; - } - } - else if (nodeType == azrtti_typeid()) - { - if (!LegacyAnimGraphNodeParser::ParseAnimGraphNode(file, importParams, nodeName, nodeHeader, node)) - { - AZ_Error("EMotionFX", false, "Unable to parse AnimGraphExitNode"); - return false; - } - } - else if (nodeType == azrtti_typeid()) - { - if (!LegacyAnimGraphNodeParser::ParseAnimGraphNode(file, importParams, nodeName, nodeHeader, node)) - { - AZ_Error("EMotionFX", false, "Unable to parse BlendTreeParameterNode"); - return false; - } - } - else if (nodeType == azrtti_typeid()) - { - if (!LegacyAnimGraphNodeParser::ParseAnimGraphNode(file, importParams, nodeName, nodeHeader, node)) - { - AZ_Error("EMotionFX", false, "Unable to parse BlendSpace1DNode"); - return false; - } - } - else if (nodeType == azrtti_typeid()) - { - if (!LegacyAnimGraphNodeParser::ParseAnimGraphNode(file, importParams, nodeName, nodeHeader, node)) - { - AZ_Error("EMotionFX", false, "Unable to parse BlendSpace2DNode"); - return false; - } - } - else if (nodeType == azrtti_typeid()) - { - if (!LegacyAnimGraphNodeParser::ParseAnimGraphNode(file, importParams, nodeName, nodeHeader, node)) - { - AZ_Error("EMotionFX", false, "Unable to parse BlendTreeMorphTargetNode"); - return false; - } - } - else if (nodeType == azrtti_typeid()) - { - if (!LegacyAnimGraphNodeParser::ParseAnimGraphNode(file, importParams, nodeName, nodeHeader, node)) - { - AZ_Error("EMotionFX", false, "Unable to parse BlendTreeFloatConstantNode"); - return false; - } - } - else - { - AZ_Error("EMotionFX", false, "LegacyAnimGraphNodeParser: Cannot parse node with uuid %s. No node parser available", nodeType.ToString().c_str()); - return false; - } - - return true; -} - -template<> -bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, - uint32 numAttributes, - MCore::Endian::EEndianType endianType, - Importer::ImportParameters& importParams, - AnimGraphObject& animGraphObject) -{ - AZ_UNUSED(importParams); - AnimGraphVector2Condition& animGraphVector2Condition = static_cast(animGraphObject); - // For all attributes - for (uint32 parsedAttributeCount = 0; parsedAttributeCount < numAttributes; ++parsedAttributeCount) - { - LegacyAttributeHeader legacyAttributeHeader; - if (!LegacyAttributeHeader::Parse(stream, endianType, legacyAttributeHeader)) - { - AZ_Error("EMotionFX", false, "Unable to parse attribute header"); - return false; - } - - if (legacyAttributeHeader.GetAttributeSize() > 0) - { - switch (parsedAttributeCount) - { - case 0: - { - LegacyAttribute legacyAttribute; - if (!legacyAttribute.Parse(stream, endianType)) - { - return false; - } - animGraphVector2Condition.SetParameterName(legacyAttribute.GetValue()); - } - break; - case 1: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - AnimGraphVector2Condition::EOperation operation = static_cast(static_cast(floatValue)); - animGraphVector2Condition.SetOperation(operation); - } - break; - case 2: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - AnimGraphParameterCondition::EFunction function = static_cast(static_cast(floatValue)); - animGraphVector2Condition.SetFunction(function); - } - break; - case 3: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - animGraphVector2Condition.SetTestValue(floatValue); - } - break; - case 4: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - animGraphVector2Condition.SetRangeValue(floatValue); - } - break; - default: - { - AZ_Error("EMotionFX", false, "LegacyAnimGraphNodeParser::ParseLegacyAttributes. Unexpected attribute count"); - return false; - } - break; - } - } - } - return true; -} - - -template<> -bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, - uint32 numAttributes, - MCore::Endian::EEndianType endianType, - Importer::ImportParameters& importParams, - AnimGraphObject& animGraphObject) -{ - AZ_UNUSED(importParams); - AnimGraphTimeCondition& animGraphTimeCondition = static_cast(animGraphObject); - // For all attributes - for (uint32 parsedAttributeCount = 0; parsedAttributeCount < numAttributes; ++parsedAttributeCount) - { - LegacyAttributeHeader legacyAttributeHeader; - if (!LegacyAttributeHeader::Parse(stream, endianType, legacyAttributeHeader)) - { - AZ_Error("EMotionFX", false, "Unable to parse attribute header"); - return false; - } - - if (legacyAttributeHeader.GetAttributeSize() > 0) - { - switch (parsedAttributeCount) - { - case 0: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - animGraphTimeCondition.SetCountDownTime(floatValue); - } - break; - case 1: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - const bool useRandomization = LegacyAnimGraphNodeParser::ConvertFloatAttributeValueToBool(floatValue); - animGraphTimeCondition.SetUseRandomization(useRandomization); - } - break; - case 2: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - animGraphTimeCondition.SetMinRandomTime(floatValue); - } - break; - case 3: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - animGraphTimeCondition.SetMaxRandomTime(floatValue); - } - break; - default: - { - AZ_Error("EMotionFX", false, "LegacyAnimGraphNodeParser::ParseLegacyAttributes. Unexpected attribute count"); - return false; - } - break; - } - } - } - return true; -} - -template<> -bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, - uint32 numAttributes, - MCore::Endian::EEndianType endianType, - Importer::ImportParameters& importParams, - AnimGraphObject& animGraphObject) -{ - AZ_UNUSED(importParams); - AnimGraphTagCondition& animGraphTagCondition = static_cast(animGraphObject); - // For all attributes - for (uint32 parsedAttributeCount = 0; parsedAttributeCount < numAttributes; ++parsedAttributeCount) - { - LegacyAttributeHeader legacyAttributeHeader; - if (!LegacyAttributeHeader::Parse(stream, endianType, legacyAttributeHeader)) - { - AZ_Error("EMotionFX", false, "Unable to parse attribute header"); - return false; - } - - if (legacyAttributeHeader.GetAttributeSize() > 0) - { - switch (parsedAttributeCount) - { - case 0: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - AnimGraphTagCondition::EFunction function = static_cast(static_cast(floatValue)); - animGraphTagCondition.SetFunction(function); - } - break; - case 1: - { - LegacyAttributeArray legacyAttributeArrayStrings; - if (!legacyAttributeArrayStrings.Parse(stream, endianType)) - { - return false; - } - AZStd::vector tags; - tags.resize(legacyAttributeArrayStrings.GetValue().size()); - for (int i = 0; i < legacyAttributeArrayStrings.GetValue().size(); i++) - { - tags[i] = legacyAttributeArrayStrings.GetValue()[i].GetValue(); - } - animGraphTagCondition.SetTags(tags); - } - break; - default: - { - AZ_Error("EMotionFX", false, "LegacyAnimGraphNodeParser::ParseLegacyAttributes. Unexpected attribute count"); - return false; - } - break; - } - } - } - return true; -} - -template<> -bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, - uint32 numAttributes, - MCore::Endian::EEndianType endianType, - Importer::ImportParameters& importParams, - AnimGraphObject& animGraphObject) -{ - AnimGraphStateCondition& animGraphStateCondition = static_cast(animGraphObject); - // For all attributes - for (uint32 parsedAttributeCount = 0; parsedAttributeCount < numAttributes; ++parsedAttributeCount) - { - LegacyAttributeHeader legacyAttributeHeader; - if (!LegacyAttributeHeader::Parse(stream, endianType, legacyAttributeHeader)) - { - AZ_Error("EMotionFX", false, "Unable to parse attribute header"); - return false; - } - - if (legacyAttributeHeader.GetAttributeSize() > 0) - { - switch (parsedAttributeCount) - { - case 0: - { - LegacyAttribute legacyAttribute; - if (!legacyAttribute.Parse(stream, endianType)) - { - return false; - } - AnimGraphNode* node = importParams.mAnimGraph->RecursiveFindNodeByName(legacyAttribute.GetValue().c_str()); - if (node) - { - animGraphStateCondition.SetStateId(node->GetId()); - } - } - break; - case 1: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - AnimGraphStateCondition::TestFunction testFunction = static_cast(static_cast(floatValue)); - animGraphStateCondition.SetTestFunction(testFunction); - } - break; - case 2: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - animGraphStateCondition.SetPlayTime(floatValue); - } - break; - default: - { - AZ_Error("EMotionFX", false, "LegacyAnimGraphNodeParser::ParseLegacyAttributes. Unexpected attribute count"); - return false; - } - break; - } - } - } - return true; -} - - - -template<> -bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, - uint32 numAttributes, - MCore::Endian::EEndianType endianType, - Importer::ImportParameters& importParams, - AnimGraphObject& animGraphObject) -{ - AnimGraphPlayTimeCondition& animGraphPlayTimeCondition = static_cast(animGraphObject); - // For all attributes - for (uint32 parsedAttributeCount = 0; parsedAttributeCount < numAttributes; ++parsedAttributeCount) - { - LegacyAttributeHeader legacyAttributeHeader; - if (!LegacyAttributeHeader::Parse(stream, endianType, legacyAttributeHeader)) - { - AZ_Error("EMotionFX", false, "Unable to parse attribute header"); - return false; - } - - if (legacyAttributeHeader.GetAttributeSize() > 0) - { - switch (parsedAttributeCount) - { - case 0: - { - LegacyAttribute legacyAttribute; - if (!legacyAttribute.Parse(stream, endianType)) - { - return false; - } - AnimGraphNode* node = importParams.mAnimGraph->RecursiveFindNodeByName(legacyAttribute.GetValue().c_str()); - if (node) - { - animGraphPlayTimeCondition.SetNodeId(node->GetId()); - } - } - break; - case 1: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - animGraphPlayTimeCondition.SetPlayTime(floatValue); - } - break; - case 2: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - AnimGraphPlayTimeCondition::Mode mode = static_cast(static_cast(floatValue)); - animGraphPlayTimeCondition.SetMode(mode); - } - break; - default: - { - AZ_Error("EMotionFX", false, "LegacyAnimGraphNodeParser::ParseLegacyAttributes. Unexpected attribute count"); - return false; - } - break; - } - } - } - return true; -} - -template<> -bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, - uint32 numAttributes, - MCore::Endian::EEndianType endianType, - Importer::ImportParameters& importParams, - AnimGraphObject& animGraphObject) -{ - AZ_UNUSED(importParams); - AnimGraphParameterCondition& animGraphParameterCondition = static_cast(animGraphObject); - // For all attributes - for (uint32 parsedAttributeCount = 0; parsedAttributeCount < numAttributes; ++parsedAttributeCount) - { - LegacyAttributeHeader legacyAttributeHeader; - if (!LegacyAttributeHeader::Parse(stream, endianType, legacyAttributeHeader)) - { - AZ_Error("EMotionFX", false, "Unable to parse attribute header"); - return false; - } - - if (legacyAttributeHeader.GetAttributeSize() > 0) - { - switch (parsedAttributeCount) - { - case 0: - { - LegacyAttribute legacyAttribute; - if (!legacyAttribute.Parse(stream, endianType)) - { - return false; - } - animGraphParameterCondition.SetParameterName(legacyAttribute.GetValue()); - } - break; - case 1: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - animGraphParameterCondition.SetTestValue(floatValue); - } - break; - case 2: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - animGraphParameterCondition.SetRangeValue(floatValue); - } - break; - case 3: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - AnimGraphParameterCondition::EFunction function = static_cast(static_cast(floatValue)); - animGraphParameterCondition.SetFunction(function); - } - break; - case 4: - { - LegacyAttribute legacyAttribute; - if (!legacyAttribute.Parse(stream, endianType)) - { - return false; - } - animGraphParameterCondition.SetTestString(legacyAttribute.GetValue()); - } - break; - case 5: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - AnimGraphParameterCondition::EStringFunction stringFunction = static_cast(static_cast(floatValue)); - animGraphParameterCondition.SetStringFunction(stringFunction); - } - break; - default: - { - AZ_Error("EMotionFX", false, "LegacyAnimGraphNodeParser::ParseLegacyAttributes. Unexpected attribute count"); - return false; - } - break; - } - } - } - return true; -} - - -template<> -bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, - uint32 numAttributes, - MCore::Endian::EEndianType endianType, - Importer::ImportParameters& importParams, - AnimGraphObject& animGraphObject) -{ - AnimGraphMotionCondition& animGraphMotionCondition = static_cast(animGraphObject); - - AZStd::string eventType; - AZStd::string eventParameter; - - // For all attributes - for (uint32 parsedAttributeCount = 0; parsedAttributeCount < numAttributes; ++parsedAttributeCount) - { - LegacyAttributeHeader legacyAttributeHeader; - if (!LegacyAttributeHeader::Parse(stream, endianType, legacyAttributeHeader)) - { - AZ_Error("EMotionFX", false, "Unable to parse attribute header"); - return false; - } - - if (legacyAttributeHeader.GetAttributeSize() > 0) - { - switch (parsedAttributeCount) - { - case 0: // ATTRIB_MOTIONNODE - { - LegacyAttribute legacyAttribute; - if (!legacyAttribute.Parse(stream, endianType)) - { - return false; - } - AnimGraphNode* motionNode = importParams.mAnimGraph->RecursiveFindNodeByName(legacyAttribute.GetValue().c_str()); - if (motionNode) - { - animGraphMotionCondition.SetMotionNodeId(motionNode->GetId()); - } - } - break; - case 1: // ATTRIB_FUNCTION - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - AnimGraphMotionCondition::TestFunction testFunction = static_cast(static_cast(floatValue)); - animGraphMotionCondition.SetTestFunction(testFunction); - } - break; - case 2: // ATTRIB_NUMLOOPS - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - AZ::u32 numLoops = static_cast(floatValue); - animGraphMotionCondition.SetNumLoops(numLoops); - } - break; - case 3: // ATTRIB_PLAYTIME - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - animGraphMotionCondition.SetPlayTime(floatValue); - } - break; - case 4: // ATTRIB_EVENTTYPE - { - LegacyAttribute legacyAttribute; - if (!legacyAttribute.Parse(stream, endianType)) - { - return false; - } - eventType = legacyAttribute.GetValue(); - } - break; - case 5: // ATTRIB_EVENTPARAMETER - { - LegacyAttribute legacyAttribute; - if (!legacyAttribute.Parse(stream, endianType)) - { - return false; - } - eventParameter = legacyAttribute.GetValue(); - } - break; - default: - { - AZ_Error("EMotionFX", false, "LegacyAnimGraphNodeParser::ParseLegacyAttributes. Unexpected attribute count"); - return false; - } - break; - } - } - } - - AZStd::shared_ptr eventData = EMotionFX::GetEventManager().FindOrCreateEventData(eventType, eventParameter); - animGraphMotionCondition.SetEventDatas({eventData}); - - return true; -} - -template<> -bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, - uint32 numAttributes, - MCore::Endian::EEndianType endianType, - Importer::ImportParameters& importParams, - AnimGraphObject& animGraphObject) -{ - AZ_UNUSED(importParams); - BlendTreeBlendNNode& blendTreeBlendNNode = static_cast(animGraphObject); - // For all attributes - for (uint32 parsedAttributeCount = 0; parsedAttributeCount < numAttributes; ++parsedAttributeCount) - { - LegacyAttributeHeader legacyAttributeHeader; - if (!LegacyAttributeHeader::Parse(stream, endianType, legacyAttributeHeader)) - { - AZ_Error("EMotionFX", false, "Unable to parse attribute header"); - return false; - } - - if (legacyAttributeHeader.GetAttributeSize() > 0) - { - switch (parsedAttributeCount) - { - case 0: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - const AnimGraphObject::ESyncMode syncMode = static_cast(static_cast(floatValue)); - blendTreeBlendNNode.SetSyncMode(syncMode); - } - break; - case 1: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - const AnimGraphObject::EEventMode eventMode = static_cast(static_cast(floatValue)); - blendTreeBlendNNode.SetEventMode(eventMode); - } - break; - default: - { - AZ_Error("EMotionFX", false, "LegacyAnimGraphNodeParser::ParseLegacyAttributes: unexpected attribute count"); - return false; - } - break; - } - } - } - return true; -} - -template<> -bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, - uint32 numAttributes, - MCore::Endian::EEndianType endianType, - Importer::ImportParameters& importParams, - AnimGraphObject& animGraphObject) -{ - AZ_UNUSED(importParams); - BlendTreeMaskLegacyNode& blendTreeMaskNode = static_cast(animGraphObject); - for (uint32 parsedAttributeCount = 0; parsedAttributeCount < numAttributes; ++parsedAttributeCount) - { - LegacyAttributeHeader legacyAttributeHeader; - if (!LegacyAttributeHeader::Parse(stream, endianType, legacyAttributeHeader)) - { - AZ_Error("EMotionFX", false, "Unable to parse attribute header"); - return false; - } - if (legacyAttributeHeader.GetAttributeSize() > 0) - { - switch (parsedAttributeCount) - { - case 0: - { - LegacyAttribute> legacyAttribute; - if (!legacyAttribute.Parse(stream, endianType)) - { - return false; - } - AZStd::vector maskStrings(legacyAttribute.GetValue().size()); - for(int i = 0; i < legacyAttribute.GetValue().size(); i++) - { - maskStrings[i] = legacyAttribute.GetValue()[i].first; - } - blendTreeMaskNode.SetMask0(maskStrings); - } - break; - case 1: - { - LegacyAttribute> legacyAttribute; - if (!legacyAttribute.Parse(stream, endianType)) - { - return false; - } - AZStd::vector maskStrings(legacyAttribute.GetValue().size()); - for (int i = 0; i < legacyAttribute.GetValue().size(); i++) - { - maskStrings[i] = legacyAttribute.GetValue()[i].first; - } - blendTreeMaskNode.SetMask1(maskStrings); - } - break; - case 2: - { - LegacyAttribute> legacyAttribute; - if (!legacyAttribute.Parse(stream, endianType)) - { - return false; - } - AZStd::vector maskStrings(legacyAttribute.GetValue().size()); - for (int i = 0; i < legacyAttribute.GetValue().size(); i++) - { - maskStrings[i] = legacyAttribute.GetValue()[i].first; - } - blendTreeMaskNode.SetMask2(maskStrings); - } - break; - case 3: - { - LegacyAttribute> legacyAttribute; - if (!legacyAttribute.Parse(stream, endianType)) - { - return false; - } - AZStd::vector maskStrings(legacyAttribute.GetValue().size()); - for (int i = 0; i < legacyAttribute.GetValue().size(); i++) - { - maskStrings[i] = legacyAttribute.GetValue()[i].first; - } - blendTreeMaskNode.SetMask3(maskStrings); - } - break; - case 4: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - bool eventFlag = LegacyAnimGraphNodeParser::ConvertFloatAttributeValueToBool(floatValue); - blendTreeMaskNode.SetOutputEvents0(eventFlag); - } - break; - case 5: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - bool eventFlag = LegacyAnimGraphNodeParser::ConvertFloatAttributeValueToBool(floatValue); - blendTreeMaskNode.SetOutputEvents1(eventFlag); - } - break; - case 6: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - bool eventFlag = LegacyAnimGraphNodeParser::ConvertFloatAttributeValueToBool(floatValue); - blendTreeMaskNode.SetOutputEvents2(eventFlag); - } - break; - case 7: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - bool eventFlag = LegacyAnimGraphNodeParser::ConvertFloatAttributeValueToBool(floatValue); - blendTreeMaskNode.SetOutputEvents3(eventFlag); - } - break; - default: - { - AZ_Error("EMotionFX", false, "Unexpected attribute count parsing BlendTreeTransformNode"); - return false; - } - break; - } - } - } - return true; -} - - -template<> -bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, - uint32 numAttributes, - MCore::Endian::EEndianType endianType, - Importer::ImportParameters& importParams, - AnimGraphObject& animGraphObject) -{ - AZ_UNUSED(importParams); - BlendTreeTransformNode& blendTreeTransformNode = static_cast(animGraphObject); - for (uint32 parsedAttributeCount = 0; parsedAttributeCount < numAttributes; ++parsedAttributeCount) - { - LegacyAttributeHeader legacyAttributeHeader; - if (!LegacyAttributeHeader::Parse(stream, endianType, legacyAttributeHeader)) - { - AZ_Error("EMotionFX", false, "Unable to parse attribute header"); - return false; - } - if (legacyAttributeHeader.GetAttributeSize() > 0) - { - switch (parsedAttributeCount) - { - case 0: - { - LegacyAttribute legacyAttribute; - if (!legacyAttribute.Parse(stream, endianType)) - { - return false; - } - blendTreeTransformNode.SetTargetNodeName(legacyAttribute.GetValue()); - } - break; - case 1: - { - LegacyAttribute legacyAttribute; - if (!legacyAttribute.Parse(stream, endianType)) - { - return false; - } - blendTreeTransformNode.SetMinTranslation(AZ::Vector3(legacyAttribute.GetValue())); - } - break; - case 2: - { - LegacyAttribute legacyAttribute; - if (!legacyAttribute.Parse(stream, endianType)) - { - return false; - } - blendTreeTransformNode.SetMaxTranslation(AZ::Vector3(legacyAttribute.GetValue())); - } - break; - case 3: - { - LegacyAttribute legacyAttribute; - if (!legacyAttribute.Parse(stream, endianType)) - { - return false; - } - blendTreeTransformNode.SetMinRotation(legacyAttribute.GetValue().GetDegrees()); - } - break; - case 4: - { - LegacyAttribute legacyAttribute; - if (!legacyAttribute.Parse(stream, endianType)) - { - return false; - } - blendTreeTransformNode.SetMaxRotation(legacyAttribute.GetValue().GetDegrees()); - } - break; - case 5: - { - LegacyAttribute legacyAttribute; - if (!legacyAttribute.Parse(stream, endianType)) - { - return false; - } - blendTreeTransformNode.SetMinScale(AZ::Vector3(legacyAttribute.GetValue())); - } - break; - case 6: - { - LegacyAttribute legacyAttribute; - if (!legacyAttribute.Parse(stream, endianType)) - { - return false; - } - blendTreeTransformNode.SetMaxScale(AZ::Vector3(legacyAttribute.GetValue())); - } - break; - default: - { - AZ_Error("EMotionFX", false, "Unexpected attribute count parsing BlendTreeTransformNode"); - return false; - } - break; - } - } - } - return true; -} - -template<> -bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, - uint32 numAttributes, - MCore::Endian::EEndianType endianType, - Importer::ImportParameters& importParams, - AnimGraphObject& animGraphObject) -{ - AZ_UNUSED(importParams); - BlendTreeAccumTransformNode& blendTreeAccumTransformNode = static_cast(animGraphObject); - for (uint32 parsedAttributeCount = 0; parsedAttributeCount < numAttributes; ++parsedAttributeCount) - { - LegacyAttributeHeader legacyAttributeHeader; - if (!LegacyAttributeHeader::Parse(stream, endianType, legacyAttributeHeader)) - { - AZ_Error("EMotionFX", false, "Unable to parse attribute header"); - return false; - } - if (legacyAttributeHeader.GetAttributeSize() > 0) - { - switch (parsedAttributeCount) - { - case 0: - { - LegacyAttribute legacyAttribute; - if (!legacyAttribute.Parse(stream, endianType)) - { - return false; - } - blendTreeAccumTransformNode.SetTargetNodeName(legacyAttribute.GetValue()); - } - break; - case 1: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - BlendTreeAccumTransformNode::Axis axis = static_cast(static_cast(floatValue)); - blendTreeAccumTransformNode.SetTranslationAxis(axis); - } - break; - case 2: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - BlendTreeAccumTransformNode::Axis axis = static_cast(static_cast(floatValue)); - blendTreeAccumTransformNode.SetRotationAxis(axis); - } - break; - case 3: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - BlendTreeAccumTransformNode::ScaleAxis axis = static_cast(static_cast(floatValue)); - blendTreeAccumTransformNode.SetScaleAxis(axis); - } - break; - case 4: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - blendTreeAccumTransformNode.SetTranslateSpeed(floatValue); - } - break; - case 5: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - blendTreeAccumTransformNode.SetRotateSpeed(floatValue); - } - break; - case 6: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - blendTreeAccumTransformNode.SetScaleSpeed(floatValue); - } - break; - case 7: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - bool translateInvert = LegacyAnimGraphNodeParser::ConvertFloatAttributeValueToBool(floatValue); - blendTreeAccumTransformNode.SetInvertTranslation(translateInvert); - } - break; - case 8: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - bool rotateInvert = LegacyAnimGraphNodeParser::ConvertFloatAttributeValueToBool(floatValue); - blendTreeAccumTransformNode.SetInvertRotation(rotateInvert); - } - break; - case 9: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - bool scaleInvert = LegacyAnimGraphNodeParser::ConvertFloatAttributeValueToBool(floatValue); - blendTreeAccumTransformNode.SetInvertScale(scaleInvert); - } - break; - default: - { - AZ_Error("EMotionFX", false, "LegacyAnimGraphNodeParser::ParseLegacyAttributes: unexpected attributes count"); - return false; - } - break; - } - } - } - - return true; -} - -template<> -bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, - uint32 numAttributes, - MCore::Endian::EEndianType endianType, - Importer::ImportParameters& importParams, - AnimGraphObject& animGraphObject) -{ - AZ_UNUSED(importParams); - AnimGraphMotionNode& animGraphMotionNode = static_cast(animGraphObject); - for (uint32 parsedAttributeCount = 0; parsedAttributeCount < numAttributes; ++parsedAttributeCount) - { - LegacyAttributeHeader legacyAttributeHeader; - if (!LegacyAttributeHeader::Parse(stream, endianType, legacyAttributeHeader)) - { - AZ_Error("EMotionFX", false, "Unable to parse attribute header"); - return false; - } - if (legacyAttributeHeader.GetAttributeSize() > 0) - { - switch (parsedAttributeCount) - { - case 0: - { - LegacyAttributeArray legacyAttributeArrayStrings; - if (!legacyAttributeArrayStrings.Parse(stream, endianType)) - { - return false; - } - const AZStd::vector > & stringAttributes = legacyAttributeArrayStrings.GetValue(); - AZStd::vector stringValues; - for (LegacyAttribute attrStr : stringAttributes) - { - stringValues.push_back(attrStr.GetValue()); - } - animGraphMotionNode.SetMotionIds(stringValues); - } - break; - case 1: - { - LegacyAttribute legacyAttributeFloat; - if (!legacyAttributeFloat.Parse(stream, endianType)) - { - return false; - } - bool loop = LegacyAnimGraphNodeParser::ConvertFloatAttributeValueToBool(legacyAttributeFloat.GetValue()); - animGraphMotionNode.SetLoop(loop); - } - break; - case 2: - { - LegacyAttribute legacyAttributeFloat; - if (!legacyAttributeFloat.Parse(stream, endianType)) - { - return false; - } - bool retarget = LegacyAnimGraphNodeParser::ConvertFloatAttributeValueToBool(legacyAttributeFloat.GetValue()); - animGraphMotionNode.SetRetarget(retarget); - } - break; - case 3: - { - LegacyAttribute legacyAttributeFloat; - if (!legacyAttributeFloat.Parse(stream, endianType)) - { - return false; - } - bool reverse = LegacyAnimGraphNodeParser::ConvertFloatAttributeValueToBool(legacyAttributeFloat.GetValue()); - animGraphMotionNode.SetReverse(reverse); - } - break; - case 4: - { - LegacyAttribute legacyAttributeFloat; - if (!legacyAttributeFloat.Parse(stream, endianType)) - { - return false; - } - bool emitEvents = LegacyAnimGraphNodeParser::ConvertFloatAttributeValueToBool(legacyAttributeFloat.GetValue()); - animGraphMotionNode.SetEmitEvents(emitEvents); - } - break; - case 5: - { - LegacyAttribute legacyAttributeFloat; - if (!legacyAttributeFloat.Parse(stream, endianType)) - { - return false; - } - bool mirror = LegacyAnimGraphNodeParser::ConvertFloatAttributeValueToBool(legacyAttributeFloat.GetValue()); - animGraphMotionNode.SetMirrorMotion(mirror); - } - break; - case 6: - { - LegacyAttribute legacyAttributeFloat; - if (!legacyAttributeFloat.Parse(stream, endianType)) - { - return false; - } - bool motionExtraction = LegacyAnimGraphNodeParser::ConvertFloatAttributeValueToBool(legacyAttributeFloat.GetValue()); - animGraphMotionNode.SetMotionExtraction(motionExtraction); - } - break; - case 7: - { - LegacyAttribute legacyAttributeFloat; - if (!legacyAttributeFloat.Parse(stream, endianType)) - { - return false; - } - animGraphMotionNode.SetMotionPlaySpeed(legacyAttributeFloat.GetValue()); - } - break; - case 8: - { - LegacyAttribute legacyAttributeFloat; - if (!legacyAttributeFloat.Parse(stream, endianType)) - { - return false; - } - AnimGraphMotionNode::EIndexMode eIndexMode = static_cast(static_cast(legacyAttributeFloat.GetValue())); - animGraphMotionNode.SetIndexMode(eIndexMode); - } - break; - case 9: - { - LegacyAttribute legacyAttributeFloat; - if (!legacyAttributeFloat.Parse(stream, endianType)) - { - return false; - } - bool nextMotionAfterLoop = LegacyAnimGraphNodeParser::ConvertFloatAttributeValueToBool(legacyAttributeFloat.GetValue()); - animGraphMotionNode.SetNextMotionAfterLoop(nextMotionAfterLoop); - } - break; - case 10: - { - LegacyAttribute legacyAttributeFloat; - if (!legacyAttributeFloat.Parse(stream, endianType)) - { - return false; - } - bool nextMotionAfterLoop = LegacyAnimGraphNodeParser::ConvertFloatAttributeValueToBool(legacyAttributeFloat.GetValue()); - animGraphMotionNode.SetNextMotionAfterLoop(nextMotionAfterLoop); - } - break; - default: - { - AZ_Error("EMotionFX", false, "LegacyAnimGraphNodeParser::ParseLegacyAttributes: unexpected attributes count"); - return false; - } - break; - } - } - } - return true; -} - -template<> -bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, - uint32 numAttributes, - MCore::Endian::EEndianType endianType, - Importer::ImportParameters& importParams, - AnimGraphObject& animGraphObject) -{ - AZ_UNUSED(stream); - AZ_UNUSED(numAttributes); - AZ_UNUSED(endianType); - AZ_UNUSED(importParams); - AZ_UNUSED(animGraphObject); - // Do nothing - return true; -} - -template<> -bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, - uint32 numAttributes, - MCore::Endian::EEndianType endianType, - Importer::ImportParameters& importParams, - AnimGraphObject& animGraphObject) -{ - AZ_UNUSED(stream); - AZ_UNUSED(numAttributes); - AZ_UNUSED(endianType); - AZ_UNUSED(importParams); - AZ_UNUSED(animGraphObject); - // Do nothing - return true; -} - -template<> -bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, - uint32 numAttributes, - MCore::Endian::EEndianType endianType, - Importer::ImportParameters& importParams, - AnimGraphObject& animGraphObject) -{ - AZ_UNUSED(stream); - AZ_UNUSED(numAttributes); - AZ_UNUSED(endianType); - AZ_UNUSED(importParams); - AZ_UNUSED(animGraphObject); - // Do nothing - return true; -} - -template<> -bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, - uint32 numAttributes, - MCore::Endian::EEndianType endianType, - Importer::ImportParameters& importParams, - AnimGraphObject& animGraphObject) -{ - AZ_UNUSED(stream); - AZ_UNUSED(numAttributes); - AZ_UNUSED(endianType); - AZ_UNUSED(importParams); - AZ_UNUSED(animGraphObject); - // Do nothing - return true; -} - -template<> -bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, - uint32 numAttributes, - MCore::Endian::EEndianType endianType, - Importer::ImportParameters& importParams, - AnimGraphObject& animGraphObject) -{ - AZ_UNUSED(stream); - AZ_UNUSED(numAttributes); - AZ_UNUSED(endianType); - AZ_UNUSED(importParams); - AZ_UNUSED(animGraphObject); - // Do nothing - return true; -} - -template<> -bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, - uint32 numAttributes, - MCore::Endian::EEndianType endianType, - Importer::ImportParameters& importParams, - AnimGraphObject& animGraphObject) -{ - AZ_UNUSED(importParams); - BlendSpace2DNode& blendSpace2DNode = static_cast(animGraphObject); - // For all attributes - for (uint32 parsedAttributeCount = 0; parsedAttributeCount < numAttributes; ++parsedAttributeCount) - { - LegacyAttributeHeader legacyAttributeHeader; - if (!LegacyAttributeHeader::Parse(stream, endianType, legacyAttributeHeader)) - { - AZ_Error("EMotionFX", false, "BlendSpace2DNode: Unable to parse attribute header"); - return false; - } - - if (legacyAttributeHeader.GetAttributeSize() > 0) - { - switch (parsedAttributeCount) - { - case 0: // ATTRIB_CALCULATION_METHOD_X - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return true; - } - BlendSpaceNode::ECalculationMethod calculationMethod = static_cast(static_cast(floatValue)); - blendSpace2DNode.SetCalculationMethodX(calculationMethod); - } - break; - case 1: // ATTRIB_EVALUATOR_X - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return true; - } - uint32 evaluatorIndex = static_cast(floatValue); - AZ::TypeId evaluatorId; - if (!GetBlendSpaceNodeEvaluatorTypeId(evaluatorIndex, evaluatorId)) - { - return false; - } - blendSpace2DNode.SetEvaluatorTypeX(evaluatorId); - } - break; - case 2: // ATTRIB_CALCULATION_METHOD_Y - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return true; - } - BlendSpaceNode::ECalculationMethod calculationMethod = static_cast(static_cast(floatValue)); - blendSpace2DNode.SetCalculationMethodY(calculationMethod); - } - break; - case 3: // ATTRIB_EVALUATOR_Y - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return true; - } - uint32 evaluatorIndex = static_cast(floatValue); - AZ::TypeId evaluatorId; - if (!GetBlendSpaceNodeEvaluatorTypeId(evaluatorIndex, evaluatorId)) - { - return false; - } - blendSpace2DNode.SetEvaluatorTypeY(evaluatorId); - } - break; - case 4: // ATTRIB_SYNC - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return true; - } - AnimGraphObject::ESyncMode syncMode = static_cast(static_cast(floatValue)); - blendSpace2DNode.SetSyncMode(syncMode); - } - break; - case 5: //ATTRIB_SYNC_LEADERMOTION - { - LegacyAttribute legacyAttribute; - if (!legacyAttribute.Parse(stream, endianType)) - { - return false; - } - blendSpace2DNode.SetSyncLeaderMotionId(legacyAttribute.GetValue()); - } - break; - case 6: //ATTRIB_EVENTMODE - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return true; - } - BlendSpaceNode::EBlendSpaceEventMode eventMode = static_cast(static_cast(floatValue)); - blendSpace2DNode.SetEventFilterMode(eventMode); - } - break; - case 7: // ATTRIB_MOTIONS - { - // Parsing an array of string attributes - LegacyAttributeArray legacyAttributeArray; - if (!legacyAttributeArray.Parse(stream, endianType)) - { - return false; - } - // Get the attribute array and process it - AZStd::vector blendSpaceMotions; - blendSpaceMotions.resize(legacyAttributeArray.GetValue().size()); - int newVectorIndex = 0; - for (LegacyAttribute legacyAttribute : legacyAttributeArray.GetValue()) - { - blendSpaceMotions[newVectorIndex++] = legacyAttribute.GetValue(); - } - blendSpace2DNode.SetMotions(blendSpaceMotions); - } - break; - default: - { - AZ_Error("EMotionFX", false, "LegacyAnimGraphNodeParser::ParseLegacyAttributes: Unexpected number of attributes"); - return false; - } - break; - } - } - } - return true; -} - -template<> -bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, - uint32 numAttributes, - MCore::Endian::EEndianType endianType, - Importer::ImportParameters& importParams, - AnimGraphObject& animGraphObject) -{ - AZ_UNUSED(importParams); - BlendSpace1DNode& blendSpace1DNode = static_cast(animGraphObject); - // For all attributes - for (uint32 parsedAttributeCount = 0; parsedAttributeCount < numAttributes; ++parsedAttributeCount) - { - LegacyAttributeHeader legacyAttributeHeader; - if (!LegacyAttributeHeader::Parse(stream, endianType, legacyAttributeHeader)) - { - AZ_Error("EMotionFX", false, "BlendSpace1DNode: Unable to parse attribute header"); - return false; - } - - if (legacyAttributeHeader.GetAttributeSize() > 0) - { - switch (parsedAttributeCount) - { - case 0: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - AZ_Error("EMotionFX", false, "BlendSpace1DNode: Unable to parse calculation method"); - return false; - } - BlendSpaceNode::ECalculationMethod eCalculationMethod = static_cast(static_cast(floatValue)); - blendSpace1DNode.SetCalculationMethod(eCalculationMethod); - } - break; - case 1: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - AZ_Error("EMotionFX", false, "BlendSpace1DNode: Unable to parse evaluator"); - return false; - } - uint32 evaluatorIndex = static_cast(floatValue); - AZ::TypeId evaluatorUUid; - if (!GetBlendSpaceNodeEvaluatorTypeId(evaluatorIndex, evaluatorUUid)) - { - return false; - } - blendSpace1DNode.SetEvaluatorType(evaluatorUUid); - } - break; - case 2: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - AnimGraphNode::ESyncMode eSyncMmode = static_cast(static_cast(floatValue)); - blendSpace1DNode.SetSyncMode(eSyncMmode); - } - break; - case 3: - { - LegacyAttribute legacyAttribute; - if (!legacyAttribute.Parse(stream, endianType)) - { - return false; - } - blendSpace1DNode.SetSyncLeaderMotionId(legacyAttribute.GetValue()); - } - break; - case 4: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - BlendSpaceNode::EBlendSpaceEventMode eventMode = static_cast(static_cast(floatValue)); - blendSpace1DNode.SetEventFilterMode(eventMode); - } - break; - case 5: - { - // Parsing an array of string attributes - LegacyAttributeArray legacyAttributeArray; - if (!legacyAttributeArray.Parse(stream, endianType)) - { - return false; - } - // Get the attribute array and process it - AZStd::vector blendSpaceMotions; - blendSpaceMotions.resize(legacyAttributeArray.GetValue().size()); - int newVectorIndex = 0; - for (LegacyAttribute legacyAttribute : legacyAttributeArray.GetValue()) - { - blendSpaceMotions[newVectorIndex++] = legacyAttribute.GetValue(); - } - blendSpace1DNode.SetMotions(blendSpaceMotions); - } - break; - default: - { - AZ_Error("EMotionFX", false, "LegacyAnimGraphNodeParser::ParseLegacyAttributes: Unexpected attribute count"); - return false; - } - break; - } - } - } - return true; -} - -template<> -bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, - uint32 numAttributes, - MCore::Endian::EEndianType endianType, - Importer::ImportParameters& importParams, - AnimGraphObject& animGraphObject) -{ - BlendTreeParameterNode& blendTreeParameterNode = static_cast(animGraphObject); - - // **************************************************************************************** - // Please Note: this is a fix to enable a safe destruction of the node if the parser fails - // **************************************************************************************** - blendTreeParameterNode.SetAnimGraph(importParams.mAnimGraph); - // **************************************************************************************** - - // For all attributes - for (uint32 parsedAttributeCount = 0; parsedAttributeCount < numAttributes; ++parsedAttributeCount) - { - LegacyAttributeHeader legacyAttributeHeader; - if (!LegacyAttributeHeader::Parse(stream, endianType, legacyAttributeHeader)) - { - // **************************************************************************************** - // Please Note: this is a fix to enable a safe destruction of the node if the parser fails - // **************************************************************************************** - blendTreeParameterNode.SetAnimGraph(nullptr); - // **************************************************************************************** - AZ_Error("EMotionFX", false, "Unable to parse attribute header"); - return false; - } - - if (legacyAttributeHeader.GetAttributeSize() > 0) - { - switch (parsedAttributeCount) - { - case 0: - { - LegacyAttribute> legacyAttribute; - if (!legacyAttribute.Parse(stream, endianType)) - { - // **************************************************************************************** - // Please Note: this is a fix to enable a safe destruction of the node if the parser fails - // **************************************************************************************** - blendTreeParameterNode.SetAnimGraph(nullptr); - // **************************************************************************************** - - return false; - } - const AZStd::vector& parameterNames = legacyAttribute.GetValue(); - blendTreeParameterNode.SetParameters(parameterNames); - } - break; - default: - { - // **************************************************************************************** - // Please Note: this is a fix to enable a safe destruction of the node if the parser fails - // **************************************************************************************** - blendTreeParameterNode.SetAnimGraph(nullptr); - // **************************************************************************************** - - AZ_Error("EMotionFX", false, "LegacyAnimGraphNodeParser::ParseLegacyAttributes: Unexpected attribute count"); - return false; - } - break; - } - } - } - - return true; -} - -template<> -bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, - uint32 numAttributes, - MCore::Endian::EEndianType endianType, - Importer::ImportParameters& importParams, - AnimGraphObject& animGraphObject) -{ - AZ_UNUSED(stream); - AZ_UNUSED(numAttributes); - AZ_UNUSED(endianType); - AZ_UNUSED(importParams); - AZ_UNUSED(animGraphObject); - // Do nothing - return true; -} - -template<> -bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, - uint32 numAttributes, - MCore::Endian::EEndianType endianType, - Importer::ImportParameters& importParams, - AnimGraphObject& animGraphObject) -{ - AZ_UNUSED(stream); - AZ_UNUSED(numAttributes); - AZ_UNUSED(endianType); - AZ_UNUSED(importParams); - AZ_UNUSED(animGraphObject); - // Do nothing - return true; -} - -template<> -bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, - uint32 numAttributes, - MCore::Endian::EEndianType endianType, - Importer::ImportParameters& importParams, - AnimGraphObject& animGraphObject) -{ - AZ_UNUSED(stream); - AZ_UNUSED(numAttributes); - AZ_UNUSED(endianType); - AZ_UNUSED(importParams); - AZ_UNUSED(animGraphObject); - // Do nothing - return true; -} - -template<> -bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, - uint32 numAttributes, - MCore::Endian::EEndianType endianType, - Importer::ImportParameters& importParams, - AnimGraphObject& animGraphObject) -{ - AZ_UNUSED(stream); - AZ_UNUSED(numAttributes); - AZ_UNUSED(endianType); - AZ_UNUSED(importParams); - AZ_UNUSED(animGraphObject); - // Do nothing - return true; -} - -template<> -bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, - uint32 numAttributes, - MCore::Endian::EEndianType endianType, - Importer::ImportParameters& importParams, - AnimGraphObject& animGraphObject) -{ - AZ_UNUSED(stream); - AZ_UNUSED(numAttributes); - AZ_UNUSED(endianType); - AZ_UNUSED(importParams); - AZ_UNUSED(animGraphObject); - // Do nothing - return true; -} - -template<> -bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, - uint32 numAttributes, - MCore::Endian::EEndianType endianType, - Importer::ImportParameters& importParams, - AnimGraphObject& animGraphObject) -{ - AZ_UNUSED(stream); - AZ_UNUSED(numAttributes); - AZ_UNUSED(endianType); - AZ_UNUSED(importParams); - AZ_UNUSED(animGraphObject); - // Do nothing - return true; -} - -template<> -bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, - uint32 numAttributes, - MCore::Endian::EEndianType endianType, - Importer::ImportParameters& importParams, - AnimGraphObject& animGraphObject) -{ - AZ_UNUSED(stream); - AZ_UNUSED(numAttributes); - AZ_UNUSED(endianType); - AZ_UNUSED(importParams); - AZ_UNUSED(animGraphObject); - // Do nothing - return true; -} - -template<> -bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, - uint32 numAttributes, - MCore::Endian::EEndianType endianType, - Importer::ImportParameters& importParams, - AnimGraphObject& animGraphObject) -{ - AZ_UNUSED(importParams); - BlendTreeMotionFrameNode& blendTreeFloatConditionNode = static_cast(animGraphObject); - for (uint32 parsedAttributeCount = 0; parsedAttributeCount < numAttributes; ++parsedAttributeCount) - { - LegacyAttributeHeader legacyAttributeHeader; - if (!LegacyAttributeHeader::Parse(stream, endianType, legacyAttributeHeader)) - { - AZ_Error("EMotionFX", false, "Unable to parse attribute header"); - return false; - } - - if (legacyAttributeHeader.GetAttributeSize() > 0) - { - // This node needs only one attribute, if any more are found inthe file they will be skipped - if (parsedAttributeCount == 0) - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - blendTreeFloatConditionNode.SetNormalizedTimeValue(floatValue); - } - else - { - AZ_Error("EMotionFX", false, "LegacyAnimGraphNodeParser::ParseLegacyAttributes : Unexpected attribute count"); - return false; - } - } - } - return true; -} - -template<> -bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, - uint32 numAttributes, - MCore::Endian::EEndianType endianType, - Importer::ImportParameters& importParams, - AnimGraphObject& animGraphObject) -{ - AZ_UNUSED(importParams); - BlendTreeFloatConditionNode& blendTreeFloatConditionNode = static_cast(animGraphObject); - // For all attributes - for (uint32 parsedAttributeCount = 0; parsedAttributeCount < numAttributes; ++parsedAttributeCount) - { - LegacyAttributeHeader legacyAttributeHeader; - if (!LegacyAttributeHeader::Parse(stream, endianType, legacyAttributeHeader)) - { - AZ_Error("EMotionFX", false, "Unable to parse attribute header"); - return false; - } - - if (legacyAttributeHeader.GetAttributeSize() > 0) - { - switch (parsedAttributeCount) - { - case 0: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - - BlendTreeFloatConditionNode::EFunction eFunction = (BlendTreeFloatConditionNode::EFunction)((uint32)floatValue); - blendTreeFloatConditionNode.SetFunction(eFunction); - break; - } - - case 1: - { - if (legacyAttributeHeader.GetAttributeType() == LegacyAttributeTypeId::ATTRIBUTE_FLOAT_TYPE_ID) - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - - blendTreeFloatConditionNode.SetDefaultValue(floatValue); - } - else - { - AZ_Error("EMotionFX", false, "Unexpected Attribute type in legacy data. Float expected found %u instead", legacyAttributeHeader.GetAttributeType()); - return false; - } - break; - } - - case 2: - { - if (legacyAttributeHeader.GetAttributeType() == LegacyAttributeTypeId::ATTRIBUTE_FLOAT_TYPE_ID) - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - blendTreeFloatConditionNode.SetTrueResult(floatValue); - } - else - { - AZ_Error("EMotionFX", false, "Unexpected Attribute type in legacy data. Float expected found %u instead", legacyAttributeHeader.GetAttributeType()); - return false; - } - break; - } - - case 3: - { - if (legacyAttributeHeader.GetAttributeType() == LegacyAttributeTypeId::ATTRIBUTE_FLOAT_TYPE_ID) - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - blendTreeFloatConditionNode.SetFalseResult(floatValue); - } - else - { - AZ_Error("EMotionFX", false, "Unexpected Attribute type in legacy data. Float expected found %u instead", legacyAttributeHeader.GetAttributeType()); - return false; - } - break; - } - - case 4: - { - if (legacyAttributeHeader.GetAttributeType() == LegacyAttributeTypeId::ATTRIBUTE_FLOAT_TYPE_ID) - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - BlendTreeFloatConditionNode::EReturnMode returnMode = static_cast(static_cast(floatValue)); - blendTreeFloatConditionNode.SetFalseReturnMode(returnMode); - } - else - { - AZ_Error("EMotionFX", false, "Unexpected Attribute type in legacy data. Float expected found %u instead", legacyAttributeHeader.GetAttributeType()); - return false; - } - break; - } - - case 5: - { - if (legacyAttributeHeader.GetAttributeType() == LegacyAttributeTypeId::ATTRIBUTE_FLOAT_TYPE_ID) - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - BlendTreeFloatConditionNode::EReturnMode returnMode = static_cast(static_cast(floatValue)); - blendTreeFloatConditionNode.SetTrueReturnMode(returnMode); - } - else - { - AZ_Error("EMotionFX", false, "Unexpected Attribute type in legacy data. Float expected found %u instead", legacyAttributeHeader.GetAttributeType()); - return false; - } - break; - } - - default: - { - AZ_Error("EMotionFX", false, "LegacyAnimGraphNodeParser::ParseLegacyAttributes: Unexpected State in Legacy Node parser"); - return false; - } - } - } - } - - return true; -} - -template<> -bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, - uint32 numAttributes, - MCore::Endian::EEndianType endianType, - Importer::ImportParameters& importParams, - AnimGraphObject& animGraphObject) -{ - AZ_UNUSED(importParams); - BlendTreeFloatSwitchNode& blendTreeFloatSwitchNode = static_cast(animGraphObject); - // For all attributes - for (uint32 parsedAttributeCount = 0; parsedAttributeCount < numAttributes; ++parsedAttributeCount) - { - LegacyAttributeHeader legacyAttributeHeader; - if (!LegacyAttributeHeader::Parse(stream, endianType, legacyAttributeHeader)) - { - AZ_Error("EMotionFX", false, "Unable to parse attribute header"); - return false; - } - - if (legacyAttributeHeader.GetAttributeSize() > 0) - { - switch (parsedAttributeCount) - { - case 0: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - blendTreeFloatSwitchNode.SetValue0(floatValue); - } - break; - case 1: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - blendTreeFloatSwitchNode.SetValue1(floatValue); - } - break; - case 2: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - blendTreeFloatSwitchNode.SetValue2(floatValue); - } - break; - case 3: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - blendTreeFloatSwitchNode.SetValue3(floatValue); - } - break; - case 4: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - blendTreeFloatSwitchNode.SetValue4(floatValue); - } - break; - default: - { - AZ_Error("EMotionFX", false, "Unexpected attribute count"); - return false; - } - break; - } - } - } - return true; -} - -template<> -bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, - uint32 numAttributes, - MCore::Endian::EEndianType endianType, - Importer::ImportParameters& importParams, - AnimGraphObject& animGraphObject) -{ - AZ_UNUSED(importParams); - BlendTreeBoolLogicNode& blendTreeBoolLogicNode = static_cast(animGraphObject); - // For all attributes - for (uint32 parsedAttributeCount = 0; parsedAttributeCount < numAttributes; ++parsedAttributeCount) - { - LegacyAttributeHeader legacyAttributeHeader; - if (!LegacyAttributeHeader::Parse(stream, endianType, legacyAttributeHeader)) - { - AZ_Error("EMotionFX", false, "Unable to parse attribute header"); - return false; - } - - if (legacyAttributeHeader.GetAttributeSize() > 0) - { - switch (parsedAttributeCount) - { - case 0: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - BlendTreeBoolLogicNode::EFunction function = static_cast(static_cast(floatValue)); - blendTreeBoolLogicNode.SetFunction(function); - } - break; - case 1: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - blendTreeBoolLogicNode.SetDefaultValue(floatValue > MCore::Math::epsilon); - } - break; - case 2: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - blendTreeBoolLogicNode.SetTrueResult(floatValue); - } - break; - case 3: - { - float floatValue; - if (!LegacyAnimGraphNodeParser::TryGetFloatFromAttribute(stream, endianType, legacyAttributeHeader, floatValue)) - { - return false; - } - blendTreeBoolLogicNode.SetFalseResult(floatValue); - } - break; - default: - { - AZ_Error("EMotionFX", false, "Unexpected attribute count"); - return false; - } - break; - } - } - } - return true; -} - -} diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/LegacyAnimGraphNodeParser.h b/Gems/EMotionFX/Code/EMotionFX/Source/Importer/LegacyAnimGraphNodeParser.h deleted file mode 100644 index 5207b0aa10..0000000000 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/LegacyAnimGraphNodeParser.h +++ /dev/null @@ -1,259 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ -#pragma once - -#include -#include -#include -#include -#include "Importer.h" -#include "AnimGraphFileFormat.h" -#include "../AnimGraphObject.h" -#include -#include -#include "../AnimGraphNode.h" - - -namespace EMotionFX -{ - class AnimGraphNode; - class AnimGraphStateMachine; - class AnimGraphStateTransition; - class AnimGraphTransitionCondition; - class BlendTreeVector4ComposeNode; - class BlendTreeVector3ComposeNode; - class BlendTreeVector2ComposeNode; - class BlendTreeMorphTargetNode; - class BlendTreeFloatConstantNode; - class BlendTreeLookAtNode; - class BlendTreeTwoLinkIKNode; - class BlendTreeFloatMath1Node; - class AnimGraphStateTransition; - class AnimGraphStateMachine; - class BlendTreeRangeRemapperNode; - class BlendTreeSmoothingNode; - class BlendTreeVector3Math2Node; - class BlendTreeVector3Math1Node; - class BlendTreeFloatMath2Node; - class BlendTreeBlend2LegacyNode; - class AnimGraphVector2Condition; - class AnimGraphTimeCondition; - class AnimGraphTagCondition; - class AnimGraphStateCondition; - class AnimGraphPlayTimeCondition; - class AnimGraphParameterCondition; - class AnimGraphMotionCondition; - class BlendTreeBlendNNode; - class BlendTreeMaskLegacyNode; - class BlendTreeTransformNode; - class BlendTreeAccumTransformNode; - class AnimGraphMotionNode; - class BlendTreeVector4DecomposeNode; - class BlendTreeVector3DecomposeNode; - class BlendTreeVector2DecomposeNode; - class BlendTree; - class BlendTreePoseSwitchNode; - class BlendSpace2DNode; - class BlendSpace1DNode; - class BlendTreeParameterNode; - class AnimGraphExitNode; - class AnimGraphEntryNode; - class BlendTreeMirrorPoseNode; - class BlendTreeDirectionToWeightNode; - class AnimGraphBindPoseNode; - class BlendTreeFinalNode; - class AnimGraphNode; - class BlendTreeMotionFrameNode; - class BlendTreeFloatConditionNode; - class BlendTreeFloatSwitchNode; - class BlendTreeBoolLogicNode; - - const AZ::TypeId GetNewTypeIdByOldNodeTypeId(uint32 oldNodeTypeId); - - enum LegacyAttributeTypeId - { - ATTRIBUTE_FLOAT_TYPE_ID = 0x00000001, - ATTRIBUTE_INT32_TYPE_ID = 0x00000002, - ATTRIBUTE_BOOL_TYPE_ID = 0x00000004 - }; - - enum LegacyERotationOrder - { - ROTATIONORDER_ZYX = 0, - ROTATIONORDER_ZXY = 1, - ROTATIONORDER_YZX = 2, - ROTATIONORDER_YXZ = 3, - ROTATIONORDER_XYZ = 4, - ROTATIONORDER_XZY = 5 - }; - - - class LegacyAttributeHeader - { - public: - LegacyAttributeHeader() { } - - AZ::u32 GetAttributeType() const - { - return m_attribType; - } - - AZ::u32 GetAttributeSize() const - { - return m_attributeSize; - } - - static bool Parse(MCore::File* stream, MCore::Endian::EEndianType endianType, LegacyAttributeHeader& attributeHeader); - private: - LegacyAttributeHeader(const LegacyAttributeHeader& src) : - m_attribType(src.m_attribType) - , m_attributeSize(src.m_attributeSize) - , m_name(src.m_name) - { } - - AZ::u32 m_attribType; - AZ::u32 m_attributeSize; - AZStd::string m_name; - }; - - template - class LegacyAttribute - { - public: - bool Parse(MCore::File* stream, MCore::Endian::EEndianType endianType); - const T& GetValue() const; - private: - T m_value; - }; - - class LegacyAnimGraphNodeParser - { - public: - static bool ParseAnimGraphNodeChunk(MCore::File* file, - Importer::ImportParameters& importParams, - const char* nodeName, - FileFormat::AnimGraph_NodeHeader& nodeHeader, - AnimGraphNode*& node); - - static bool ParseTransitionConditionChunk(MCore::File* file, - Importer::ImportParameters& importParams, - const FileFormat::AnimGraph_NodeHeader& nodeHeader, - AnimGraphTransitionCondition*& transitionCondition); - - template - static bool ParseLegacyAttributes(MCore::File* stream, uint32 numAttributes, MCore::Endian::EEndianType endianType, Importer::ImportParameters& importParams, AnimGraphObject& animGraphObject); - - static bool Forward(MCore::File* stream, size_t numBytes); - - private: - static bool InitializeNodeGeneralData(const char* nodeName, Importer::ImportParameters& importParams, FileFormat::AnimGraph_NodeHeader& nodeHeader, AnimGraphNode* node); - static bool GetBlendSpaceNodeEvaluatorTypeId(uint32 legacyIndex, AZ::TypeId& value); - static bool ConvertFloatAttributeValueToBool(float value); - static bool TryGetFloatFromAttribute(MCore::File* stream, MCore::Endian::EEndianType endianType, const LegacyAttributeHeader& attributeHeader, float& outputValue); - - template - static bool ParseAnimGraphNode(MCore::File* file, - Importer::ImportParameters& importParams, - const char* nodeName, - FileFormat::AnimGraph_NodeHeader& nodeHeader, - AnimGraphNode*& node) - { - node = aznew T(); - node->SetAnimGraph(importParams.mAnimGraph); - if (!InitializeNodeGeneralData(nodeName, importParams, nodeHeader, node)) - { - MCore::LogError("Error on initializing node general data"); - return false; - } - if (!ParseLegacyAttributes(file, nodeHeader.mNumAttributes, importParams.mEndianType, importParams, *node)) - { - MCore::LogError("Unable to parse node legacy attributes"); - return false; - } - return true; - } - - template - static bool ParseAnimGraphTransitionCondition(MCore::File* file, - Importer::ImportParameters& importParams, - const FileFormat::AnimGraph_NodeHeader& header, - AnimGraphTransitionCondition*& transitionCondition) - { - transitionCondition = aznew T(); - return ParseLegacyAttributes(file, header.mNumAttributes, importParams.mEndianType, importParams, *transitionCondition); - } - }; - - template class LegacyAttribute> - class LegacyAttributeArray - { - public: - bool Parse(MCore::File* stream, MCore::Endian::EEndianType endianType); - const AZStd::vector< LegacyAttribute >& GetValue() const; - private: - bool PopulateAttributeDynamicArray(MCore::File* stream, MCore::Endian::EEndianType endianType); - - AZStd::vector< LegacyAttribute > m_attributes; - // Used when reading version 2 attribute array - uint32 m_elementTypeId; - }; - - class LegacyAttributeSettingsParser - { - public: - static bool Parse(MCore::File* stream, MCore::Endian::EEndianType endianType); - }; - - template<> bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, uint32 numAttributes, MCore::Endian::EEndianType endianType, Importer::ImportParameters& importParams, AnimGraphObject& animGraphObject); - template<> bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, uint32 numAttributes, MCore::Endian::EEndianType endianType, Importer::ImportParameters& importParams, AnimGraphObject& animGraphObject); - template<> bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, uint32 numAttributes, MCore::Endian::EEndianType endianType, Importer::ImportParameters& importParams, AnimGraphObject& animGraphObject); - template<> bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, uint32 numAttributes, MCore::Endian::EEndianType endianType, Importer::ImportParameters& importParams, AnimGraphObject& animGraphObject); - template<> bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, uint32 numAttributes, MCore::Endian::EEndianType endianType, Importer::ImportParameters& importParams, AnimGraphObject& animGraphObject); - template<> bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, uint32 numAttributes, MCore::Endian::EEndianType endianType, Importer::ImportParameters& importParams, AnimGraphObject& animGraphObject); - template<> bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, uint32 numAttributes, MCore::Endian::EEndianType endianType, Importer::ImportParameters& importParams, AnimGraphObject& animGraphObject); - template<> bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, uint32 numAttributes, MCore::Endian::EEndianType endianType, Importer::ImportParameters& importParams, AnimGraphObject& animGraphObject); - template<> bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, uint32 numAttributes, MCore::Endian::EEndianType endianType, Importer::ImportParameters& importParams, AnimGraphObject& animGraphObject); - template<> bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, uint32 numAttributes, MCore::Endian::EEndianType endianType, Importer::ImportParameters& importParams, AnimGraphObject& animGraphObject); - template<> bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, uint32 numAttributes, MCore::Endian::EEndianType endianType, Importer::ImportParameters& importParams, AnimGraphObject& animGraphObject); - template<> bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, uint32 numAttributes, MCore::Endian::EEndianType endianType, Importer::ImportParameters& importParams, AnimGraphObject& animGraphObject); - template<> bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, uint32 numAttributes, MCore::Endian::EEndianType endianType, Importer::ImportParameters& importParams, AnimGraphObject& animGraphObject); - template<> bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, uint32 numAttributes, MCore::Endian::EEndianType endianType, Importer::ImportParameters& importParams, AnimGraphObject& animGraphObject); - template<> bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, uint32 numAttributes, MCore::Endian::EEndianType endianType, Importer::ImportParameters& importParams, AnimGraphObject& animGraphObject); - template<> bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, uint32 numAttributes, MCore::Endian::EEndianType endianType, Importer::ImportParameters& importParams, AnimGraphObject& animGraphObject); - template<> bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, uint32 numAttributes, MCore::Endian::EEndianType endianType, Importer::ImportParameters& importParams, AnimGraphObject& animGraphObject); - template<> bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, uint32 numAttributes, MCore::Endian::EEndianType endianType, Importer::ImportParameters& importParams, AnimGraphObject& animGraphObject); - template<> bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, uint32 numAttributes, MCore::Endian::EEndianType endianType, Importer::ImportParameters& importParams, AnimGraphObject& animGraphObject); - template<> bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, uint32 numAttributes, MCore::Endian::EEndianType endianType, Importer::ImportParameters& importParams, AnimGraphObject& animGraphObject); - template<> bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, uint32 numAttributes, MCore::Endian::EEndianType endianType, Importer::ImportParameters& importParams, AnimGraphObject& animGraphObject); - template<> bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, uint32 numAttributes, MCore::Endian::EEndianType endianType, Importer::ImportParameters& importParams, AnimGraphObject& animGraphObject); - template<> bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, uint32 numAttributes, MCore::Endian::EEndianType endianType, Importer::ImportParameters& importParams, AnimGraphObject& animGraphObject); - template<> bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, uint32 numAttributes, MCore::Endian::EEndianType endianType, Importer::ImportParameters& importParams, AnimGraphObject& animGraphObject); - template<> bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, uint32 numAttributes, MCore::Endian::EEndianType endianType, Importer::ImportParameters& importParams, AnimGraphObject& animGraphObject); - template<> bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, uint32 numAttributes, MCore::Endian::EEndianType endianType, Importer::ImportParameters& importParams, AnimGraphObject& animGraphObject); - template<> bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, uint32 numAttributes, MCore::Endian::EEndianType endianType, Importer::ImportParameters& importParams, AnimGraphObject& animGraphObject); - template<> bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, uint32 numAttributes, MCore::Endian::EEndianType endianType, Importer::ImportParameters& importParams, AnimGraphObject& animGraphObject); - template<> bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, uint32 numAttributes, MCore::Endian::EEndianType endianType, Importer::ImportParameters& importParams, AnimGraphObject& animGraphObject); - template<> bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, uint32 numAttributes, MCore::Endian::EEndianType endianType, Importer::ImportParameters& importParams, AnimGraphObject& animGraphObject); - template<> bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, uint32 numAttributes, MCore::Endian::EEndianType endianType, Importer::ImportParameters& importParams, AnimGraphObject& animGraphObject); - template<> bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, uint32 numAttributes, MCore::Endian::EEndianType endianType, Importer::ImportParameters& importParams, AnimGraphObject& animGraphObject); - template<> bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, uint32 numAttributes, MCore::Endian::EEndianType endianType, Importer::ImportParameters& importParams, AnimGraphObject& animGraphObject); - template<> bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, uint32 numAttributes, MCore::Endian::EEndianType endianType, Importer::ImportParameters& importParams, AnimGraphObject& animGraphObject); - template<> bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, uint32 numAttributes, MCore::Endian::EEndianType endianType, Importer::ImportParameters& importParams, AnimGraphObject& animGraphObject); - template<> bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, uint32 numAttributes, MCore::Endian::EEndianType endianType, Importer::ImportParameters& importParams, AnimGraphObject& animGraphObject); - template<> bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, uint32 numAttributes, MCore::Endian::EEndianType endianType, Importer::ImportParameters& importParams, AnimGraphObject& animGraphObject); - template<> bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, uint32 numAttributes, MCore::Endian::EEndianType endianType, Importer::ImportParameters& importParams, AnimGraphObject& animGraphObject); - template<> bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, uint32 numAttributes, MCore::Endian::EEndianType endianType, Importer::ImportParameters& importParams, AnimGraphObject& animGraphObject); - template<> bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, uint32 numAttributes, MCore::Endian::EEndianType endianType, Importer::ImportParameters& importParams, AnimGraphObject& animGraphObject); - template<> bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, uint32 numAttributes, MCore::Endian::EEndianType endianType, Importer::ImportParameters& importParams, AnimGraphObject& animGraphObject); - template<> bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, uint32 numAttributes, MCore::Endian::EEndianType endianType, Importer::ImportParameters& importParams, AnimGraphObject& animGraphObject); - template<> bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, uint32 numAttributes, MCore::Endian::EEndianType endianType, Importer::ImportParameters& importParams, AnimGraphObject& animGraphObject); - template<> bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, uint32 numAttributes, MCore::Endian::EEndianType endianType, Importer::ImportParameters& importParams, AnimGraphObject& animGraphObject); - template<> bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, uint32 numAttributes, MCore::Endian::EEndianType endianType, Importer::ImportParameters& importParams, AnimGraphObject& animGraphObject); - template<> bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, uint32 numAttributes, MCore::Endian::EEndianType endianType, Importer::ImportParameters& importParams, AnimGraphObject& animGraphObject); - template<> bool LegacyAnimGraphNodeParser::ParseLegacyAttributes(MCore::File* stream, uint32 numAttributes, MCore::Endian::EEndianType endianType, Importer::ImportParameters& importParams, AnimGraphObject& animGraphObject); -} // Namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/MotionSetFileFormat.h b/Gems/EMotionFX/Code/EMotionFX/Source/Importer/MotionSetFileFormat.h deleted file mode 100644 index 216188022e..0000000000 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/MotionSetFileFormat.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -#pragma once - -// include the shared structs -#include "SharedFileFormatStructs.h" - - -namespace EMotionFX -{ - namespace FileFormat - { - // the chunks - enum - { - CHUNK_MOTIONSET = 500 - }; - - - struct MotionSet_Header - { - uint8 mFourCC[4]; // must be "MOS " - uint8 mHiVersion; // high version (2 in case of v2.34) - uint8 mLoVersion; // low version (34 in case of v2.34) - uint8 mEndianType; // the endian in which the data is saved [0=little, 1=big] - }; - - - struct MotionSetsChunk - { - uint32 mNumSets; // the number of motion sets - - // followed by: - // motionSets[mNumSets] - }; - - - struct MotionSetChunk - { - uint32 mNumChildSets; // the number of child motion sets - uint32 mNumMotionEntries; // the number of motion entries - - // followed by: - // string : the name of the parent set - // string : the name of the motion set - // string : the filename and path information (e.g. "Root/Motions/Human_Male/" // obsolete, this got removed and is now just an empty string - // motionEntries[mNumMotionEntries]: motion entries - // MotionEntry: - // string : motion filename without path (e.g. "Walk.motion") - // string : motion set string id (e.g. "WALK") - }; - } // namespace FileFormat -} // namespace EMotionFX - From a287b67b43c69fe3979d93ab9bcb331daa7b6957 Mon Sep 17 00:00:00 2001 From: Benjamin Jillich Date: Mon, 26 Jul 2021 09:57:01 +0200 Subject: [PATCH 031/160] Removed ReadDataSize/ReadData() helpers for attributes Used only by legacy binary file format Signed-off-by: Benjamin Jillich --- .../Source/AnimGraphAttributeTypes.h | 6 ---- .../Source/Importer/SharedFileFormatStructs.h | 28 ++------------- .../EMotionFX/Code/MCore/Source/Attribute.cpp | 29 +-------------- Gems/EMotionFX/Code/MCore/Source/Attribute.h | 23 ------------ .../Code/MCore/Source/AttributeBool.h | 18 ---------- .../Code/MCore/Source/AttributeColor.h | 22 ------------ .../Code/MCore/Source/AttributeFloat.h | 18 ---------- .../Code/MCore/Source/AttributeInt32.h | 18 ---------- .../Code/MCore/Source/AttributePointer.h | 13 ------- .../Code/MCore/Source/AttributeQuaternion.h | 21 ----------- .../Code/MCore/Source/AttributeString.h | 35 ------------------- .../Code/MCore/Source/AttributeVector2.h | 22 ------------ .../Code/MCore/Source/AttributeVector3.h | 22 ------------ .../Code/MCore/Source/AttributeVector4.h | 22 ------------ 14 files changed, 3 insertions(+), 294 deletions(-) diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphAttributeTypes.h b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphAttributeTypes.h index 9514ffdb20..9f7b33a66d 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphAttributeTypes.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphAttributeTypes.h @@ -79,9 +79,6 @@ namespace EMotionFX AttributePose(AnimGraphPose* pose) : MCore::Attribute(TYPE_ID) { mValue = pose; } ~AttributePose() {} - - uint32 GetDataSize() const override { return 0; } - bool ReadData(MCore::Stream* stream, MCore::Endian::EEndianType streamEndianType, uint8 version) override { MCORE_UNUSED(stream); MCORE_UNUSED(streamEndianType); MCORE_UNUSED(version); return false; } // unsupported }; @@ -130,9 +127,6 @@ namespace EMotionFX AttributeMotionInstance(MotionInstance* motionInstance) : MCore::Attribute(TYPE_ID) { mValue = motionInstance; } ~AttributeMotionInstance() {} - - uint32 GetDataSize() const override { return 0; } - bool ReadData(MCore::Stream* stream, MCore::Endian::EEndianType streamEndianType, uint8 version) override { MCORE_UNUSED(stream); MCORE_UNUSED(streamEndianType); MCORE_UNUSED(version); return false; } // unsupported }; class AnimGraphPropertyUtils diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/SharedFileFormatStructs.h b/Gems/EMotionFX/Code/EMotionFX/Source/Importer/SharedFileFormatStructs.h index 2355e7923d..082bcbf0ef 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/SharedFileFormatStructs.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Importer/SharedFileFormatStructs.h @@ -7,6 +7,7 @@ */ #pragma once + #include namespace EMotionFX @@ -20,8 +21,6 @@ namespace EMotionFX SHARED_CHUNK_TIMESTAMP = 51 }; - - // a chunk struct FileChunk { uint32 mChunkID; // the chunk ID @@ -29,7 +28,6 @@ namespace EMotionFX uint32 mVersion; // the version of the chunk }; - // color [0..1] range struct FileColor { @@ -39,16 +37,12 @@ namespace EMotionFX float mA; // alpha }; - - // a 2D vector struct FileVector2 { float mX; float mY; }; - - // a 3D vector struct FileVector3 { float mX; // x+ = to the right @@ -56,7 +50,6 @@ namespace EMotionFX float mZ; // z+ = up }; - // a compressed 3D vector struct File16BitVector3 { @@ -65,7 +58,6 @@ namespace EMotionFX uint16 mZ; // z+ = up }; - // a compressed 3D vector struct File8BitVector3 { @@ -74,8 +66,6 @@ namespace EMotionFX uint8 mZ; // z+ = up }; - - // a quaternion struct FileQuaternion { float mX; @@ -84,7 +74,6 @@ namespace EMotionFX float mW; }; - // the 16 bit component quaternion struct File16BitQuaternion { @@ -94,7 +83,6 @@ namespace EMotionFX int16 mW; }; - // a time stamp chunk struct FileTime { @@ -105,17 +93,5 @@ namespace EMotionFX int8 mMinutes; int8 mSeconds; }; - - - // attribute - struct FileAttribute - { - uint32 mDataType; - uint32 mNumBytes; - uint32 mFlags; - - // followed by: - // uint8 mData[mNumBytes]; - }; } // namespace FileFormat -} // namespace EMotionFX +} // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/MCore/Source/Attribute.cpp b/Gems/EMotionFX/Code/MCore/Source/Attribute.cpp index e2b7e7164b..ed2bc1a535 100644 --- a/Gems/EMotionFX/Code/MCore/Source/Attribute.cpp +++ b/Gems/EMotionFX/Code/MCore/Source/Attribute.cpp @@ -6,7 +6,6 @@ * */ -// include required headers #include "Attribute.h" #include "AttributeFactory.h" #include "AttributeString.h" @@ -14,20 +13,15 @@ namespace MCore { - // constructor Attribute::Attribute(uint32 typeID) { mTypeID = typeID; } - - // destructor Attribute::~Attribute() { } - - // equal operator Attribute& Attribute::operator=(const Attribute& other) { if (&other != this) @@ -36,25 +30,4 @@ namespace MCore } return *this; } - - // read the attribute - bool Attribute::Read(Stream* stream, Endian::EEndianType sourceEndianType) - { - // read the version - uint8 version; - if (stream->Read(&version, sizeof(uint8)) == 0) - { - return false; - } - - // read the data - const bool result = ReadData(stream, sourceEndianType, version); - if (result == false) - { - return false; - } - - return true; - } - -} // namespace MCore +} // namespace MCore diff --git a/Gems/EMotionFX/Code/MCore/Source/Attribute.h b/Gems/EMotionFX/Code/MCore/Source/Attribute.h index 06de883a98..c245e7d778 100644 --- a/Gems/EMotionFX/Code/MCore/Source/Attribute.h +++ b/Gems/EMotionFX/Code/MCore/Source/Attribute.h @@ -8,7 +8,6 @@ #pragma once -// include the required headers #include "StandardHeaders.h" #include "MemoryManager.h" #include "Endian.h" @@ -28,7 +27,6 @@ namespace MCore // forward declarations class AttributeSettings; - // the attribute interface types enum : uint32 { @@ -49,12 +47,6 @@ namespace MCore ATTRIBUTE_INTERFACETYPE_DEFAULT = 0xFFFFFFFF// use the default attribute type that the specific attribute class defines as default }; - - /** - * - * - * - */ class MCORE_API Attribute { friend class AttributeFactory; @@ -70,10 +62,6 @@ namespace MCore virtual uint32 GetClassSize() const = 0; virtual uint32 GetDefaultInterfaceType() const = 0; - // These two members and ReadData can go away once we put the old-format parser - bool Read(Stream* stream, MCore::Endian::EEndianType sourceEndianType); - virtual uint32 GetDataSize() const = 0; // data only - Attribute& operator=(const Attribute& other); virtual void NetworkSerialize(EMotionFX::Network::AnimGraphSnapshotChunkSerializer&) {}; @@ -82,16 +70,5 @@ namespace MCore uint32 mTypeID; /**< The unique type ID of the attribute class. */ Attribute(uint32 typeID); - - /** - * Read the attribute info and data from a given stream. - * Please note that the endian information of the actual data is not being converted. You have to handle that yourself. - * The data endian conversion could be done with for example the static Attribute::ConvertDataEndian method. - * @param stream The stream to read the info and data from. - * @param endianType The endian type in which the data is stored in the stream. - * @param version The version of the attribute. - * @result Returns true when successful, or false when reading failed. - */ - virtual bool ReadData(MCore::Stream* stream, MCore::Endian::EEndianType streamEndianType, uint8 version) = 0; }; } // namespace MCore diff --git a/Gems/EMotionFX/Code/MCore/Source/AttributeBool.h b/Gems/EMotionFX/Code/MCore/Source/AttributeBool.h index 6ef66c28c2..9a923b5fda 100644 --- a/Gems/EMotionFX/Code/MCore/Source/AttributeBool.h +++ b/Gems/EMotionFX/Code/MCore/Source/AttributeBool.h @@ -63,23 +63,5 @@ namespace MCore : Attribute(TYPE_ID) , mValue(value) {} ~AttributeBool() {} - - uint32 GetDataSize() const override { return sizeof(int8); } - - // read from a stream - bool ReadData(MCore::Stream* stream, MCore::Endian::EEndianType streamEndianType, uint8 version) override - { - MCORE_UNUSED(version); - MCORE_UNUSED(streamEndianType); - int8 streamValue; - if (stream->Read(&streamValue, sizeof(int8)) == 0) - { - return false; - } - - mValue = (streamValue == 0) ? false : true; - return true; - } - }; } // namespace MCore diff --git a/Gems/EMotionFX/Code/MCore/Source/AttributeColor.h b/Gems/EMotionFX/Code/MCore/Source/AttributeColor.h index 4abddf90cd..6287239bf8 100644 --- a/Gems/EMotionFX/Code/MCore/Source/AttributeColor.h +++ b/Gems/EMotionFX/Code/MCore/Source/AttributeColor.h @@ -79,27 +79,5 @@ namespace MCore : Attribute(TYPE_ID) , mValue(value) { } ~AttributeColor() {} - - uint32 GetDataSize() const override { return sizeof(RGBAColor); } - - // read from a stream - bool ReadData(MCore::Stream* stream, MCore::Endian::EEndianType streamEndianType, uint8 version) override - { - MCORE_UNUSED(version); - - // read the value - RGBAColor streamValue; - if (stream->Read(&streamValue, sizeof(RGBAColor)) == 0) - { - return false; - } - - // convert endian - Endian::ConvertRGBAColor(&streamValue, streamEndianType); - mValue = streamValue; - - return true; - } - }; } // namespace MCore diff --git a/Gems/EMotionFX/Code/MCore/Source/AttributeFloat.h b/Gems/EMotionFX/Code/MCore/Source/AttributeFloat.h index 2c9f26e90f..ef650a1430 100644 --- a/Gems/EMotionFX/Code/MCore/Source/AttributeFloat.h +++ b/Gems/EMotionFX/Code/MCore/Source/AttributeFloat.h @@ -57,8 +57,6 @@ namespace MCore private: float mValue; /**< The float value. */ - uint32 GetDataSize() const override { return sizeof(float); } - AttributeFloat() : Attribute(TYPE_ID) , mValue(0.0f) {} @@ -66,21 +64,5 @@ namespace MCore : Attribute(TYPE_ID) , mValue(value) {} ~AttributeFloat() {} - - // read from a stream - bool ReadData(MCore::Stream* stream, MCore::Endian::EEndianType streamEndianType, uint8 version) override - { - MCORE_UNUSED(version); - - float streamValue; - if (stream->Read(&streamValue, sizeof(float)) == 0) - { - return false; - } - - Endian::ConvertFloat(&streamValue, streamEndianType); - mValue = streamValue; - return true; - } }; } // namespace MCore diff --git a/Gems/EMotionFX/Code/MCore/Source/AttributeInt32.h b/Gems/EMotionFX/Code/MCore/Source/AttributeInt32.h index 75e4f102e3..f13246d438 100644 --- a/Gems/EMotionFX/Code/MCore/Source/AttributeInt32.h +++ b/Gems/EMotionFX/Code/MCore/Source/AttributeInt32.h @@ -64,23 +64,5 @@ namespace MCore : Attribute(TYPE_ID) , mValue(value) {} ~AttributeInt32() {} - - uint32 GetDataSize() const override { return sizeof(int32); } - - // read from a stream - bool ReadData(MCore::Stream* stream, MCore::Endian::EEndianType streamEndianType, uint8 version) override - { - MCORE_UNUSED(version); - - int32 streamValue; - if (stream->Read(&streamValue, sizeof(int32)) == 0) - { - return false; - } - - Endian::ConvertSignedInt32(&streamValue, streamEndianType); - mValue = streamValue; - return true; - } }; } // namespace MCore diff --git a/Gems/EMotionFX/Code/MCore/Source/AttributePointer.h b/Gems/EMotionFX/Code/MCore/Source/AttributePointer.h index becb6030b7..8f7a6cbc65 100644 --- a/Gems/EMotionFX/Code/MCore/Source/AttributePointer.h +++ b/Gems/EMotionFX/Code/MCore/Source/AttributePointer.h @@ -66,18 +66,5 @@ namespace MCore : Attribute(TYPE_ID) , mValue(pointer) { } ~AttributePointer() {} - - uint32 GetDataSize() const override { return sizeof(void*); } - - // read from a stream - bool ReadData(MCore::Stream* stream, MCore::Endian::EEndianType streamEndianType, uint8 version) override - { - MCORE_UNUSED(stream); - MCORE_UNUSED(streamEndianType); - MCORE_UNUSED(version); - - MCore::LogWarning("MCore::AttributePointer::ReadData() - Pointer attributes cannot be read from disk."); - return false; - } }; } // namespace MCore diff --git a/Gems/EMotionFX/Code/MCore/Source/AttributeQuaternion.h b/Gems/EMotionFX/Code/MCore/Source/AttributeQuaternion.h index 4509c3a962..3380cac957 100644 --- a/Gems/EMotionFX/Code/MCore/Source/AttributeQuaternion.h +++ b/Gems/EMotionFX/Code/MCore/Source/AttributeQuaternion.h @@ -82,26 +82,5 @@ namespace MCore : Attribute(TYPE_ID) , mValue(value) {} ~AttributeQuaternion() { } - - uint32 GetDataSize() const override { return sizeof(AZ::Quaternion); } - - // read from a stream - bool ReadData(MCore::Stream* stream, MCore::Endian::EEndianType streamEndianType, uint8 version) override - { - MCORE_UNUSED(version); - - // read the value - AZ::Quaternion streamValue; - if (stream->Read(&streamValue, sizeof(AZ::Quaternion)) == 0) - { - return false; - } - - // convert endian - Endian::ConvertQuaternion(&streamValue, streamEndianType); - mValue = streamValue; - return true; - } - }; } // namespace MCore diff --git a/Gems/EMotionFX/Code/MCore/Source/AttributeString.h b/Gems/EMotionFX/Code/MCore/Source/AttributeString.h index 5e030baf54..4f3f8df6f9 100644 --- a/Gems/EMotionFX/Code/MCore/Source/AttributeString.h +++ b/Gems/EMotionFX/Code/MCore/Source/AttributeString.h @@ -72,40 +72,5 @@ namespace MCore : Attribute(TYPE_ID) , mValue(value) { } ~AttributeString() { mValue.clear(); } - - uint32 GetDataSize() const override - { - return sizeof(uint32) + static_cast(mValue.size()); - } - - // read from a stream - bool ReadData(MCore::Stream* stream, MCore::Endian::EEndianType streamEndianType, uint8 version) override - { - MCORE_UNUSED(version); - - // read the number of characters - uint32 numCharacters; - if (stream->Read(&numCharacters, sizeof(uint32)) == 0) - { - return false; - } - - // convert endian - Endian::ConvertUnsignedInt32(&numCharacters, streamEndianType); - if (numCharacters == 0) - { - mValue.clear(); - return true; - } - - mValue.resize(numCharacters); - if (stream->Read(mValue.data(), numCharacters) == 0) - { - return false; - } - - return true; - } - }; } // namespace MCore diff --git a/Gems/EMotionFX/Code/MCore/Source/AttributeVector2.h b/Gems/EMotionFX/Code/MCore/Source/AttributeVector2.h index b69fd5ebcf..b82c7778f7 100644 --- a/Gems/EMotionFX/Code/MCore/Source/AttributeVector2.h +++ b/Gems/EMotionFX/Code/MCore/Source/AttributeVector2.h @@ -78,27 +78,5 @@ namespace MCore : Attribute(TYPE_ID) , mValue(value) { } ~AttributeVector2() { } - - uint32 GetDataSize() const override { return sizeofVector2; } - - // read from a stream - bool ReadData(MCore::Stream* stream, MCore::Endian::EEndianType streamEndianType, uint8 version) override - { - MCORE_UNUSED(version); - - // read the value - AZ::Vector2 streamValue; - if (stream->Read(&streamValue, sizeofVector2) == 0) - { - return false; - } - - // convert endian - Endian::ConvertVector2(&streamValue, streamEndianType); - mValue = streamValue; - - return true; - } - }; } // namespace MCore diff --git a/Gems/EMotionFX/Code/MCore/Source/AttributeVector3.h b/Gems/EMotionFX/Code/MCore/Source/AttributeVector3.h index 0151de0d69..ea6b820944 100644 --- a/Gems/EMotionFX/Code/MCore/Source/AttributeVector3.h +++ b/Gems/EMotionFX/Code/MCore/Source/AttributeVector3.h @@ -79,27 +79,5 @@ namespace MCore : Attribute(TYPE_ID) , mValue(value) { } ~AttributeVector3() { } - - uint32 GetDataSize() const override { return sizeof(AZ::Vector3); } - - // read from a stream - bool ReadData(MCore::Stream* stream, MCore::Endian::EEndianType streamEndianType, uint8 version) override - { - MCORE_UNUSED(version); - - // read the value - AZ::PackedVector3f streamValue(0.0f); - if (stream->Read(&streamValue, sizeof(AZ::PackedVector3f)) == 0) - { - return false; - } - - // convert endian - mValue = AZ::Vector3(streamValue.GetX(), streamValue.GetY(), streamValue.GetZ()); - Endian::ConvertVector3(&mValue, streamEndianType); - - return true; - } - }; } // namespace MCore diff --git a/Gems/EMotionFX/Code/MCore/Source/AttributeVector4.h b/Gems/EMotionFX/Code/MCore/Source/AttributeVector4.h index 0df42b6676..93dc4a527b 100644 --- a/Gems/EMotionFX/Code/MCore/Source/AttributeVector4.h +++ b/Gems/EMotionFX/Code/MCore/Source/AttributeVector4.h @@ -75,27 +75,5 @@ namespace MCore : Attribute(TYPE_ID) , mValue(value) { } ~AttributeVector4() { } - - uint32 GetDataSize() const override { return sizeof(AZ::Vector4); } - - // read from a stream - bool ReadData(MCore::Stream* stream, MCore::Endian::EEndianType streamEndianType, uint8 version) override - { - MCORE_UNUSED(version); - - // read the value - AZ::Vector4 streamValue; - if (stream->Read(&streamValue, sizeof(AZ::Vector4)) == 0) - { - return false; - } - - // convert endian - Endian::ConvertVector4(&streamValue, streamEndianType); - mValue = streamValue; - - return true; - } - }; } // namespace MCore From c097d192150e1787ee0864dd0989bedc2bee6027 Mon Sep 17 00:00:00 2001 From: Benjamin Jillich Date: Mon, 26 Jul 2021 09:57:51 +0200 Subject: [PATCH 032/160] Removed legacy chunk processors for anim graphs and motion sets together with unused shared data Signed-off-by: Benjamin Jillich --- .../Source/Importer/ChunkProcessors.cpp | 935 +----------------- .../Source/Importer/ChunkProcessors.h | 50 - 2 files changed, 1 insertion(+), 984 deletions(-) diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/ChunkProcessors.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Importer/ChunkProcessors.cpp index 87ab61bf59..e1a3e0bbfa 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/ChunkProcessors.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Importer/ChunkProcessors.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -53,7 +54,6 @@ #include "../AnimGraphTransitionCondition.h" #include "../MCore/Source/Endian.h" #include "../NodeMap.h" -#include "LegacyAnimGraphNodeParser.h" #include #include @@ -245,14 +245,10 @@ namespace EMotionFX { mFileHighVersion = 1; mFileLowVersion = 0; - mIsUnicodeFile = true; // allocate the string buffer used for reading in variable sized strings mStringStorageSize = 256; mStringStorage = (char*)MCore::Allocate(mStringStorageSize, EMFX_MEMCATEGORY_IMPORTER); - mBlendNodes.SetMemoryCategory(EMFX_MEMCATEGORY_IMPORTER); - mBlendNodes.Reserve(1024); - //mConvertString.Reserve( 256 ); } @@ -281,57 +277,8 @@ namespace EMotionFX mStringStorage = nullptr; mStringStorageSize = 0; - //mConvertString.Clear(); - - // get rid of the blend nodes array - mBlendNodes.Clear(); - - m_entryNodeIndexToStateMachineIdLookupTable.clear(); - } - - - // check if the strings in the file are encoded using unicode or multi-byte - bool SharedHelperData::GetIsUnicodeFile(const char* dateString, MCore::Array* sharedData) - { - // find the helper data - SharedData* data = Importer::FindSharedData(sharedData, SharedHelperData::TYPE_ID); - SharedHelperData* helperData = static_cast(data); - - AZStd::vector dateParts; - AzFramework::StringFunc::Tokenize(dateString, dateParts, MCore::CharacterConstants::space, false /* keep empty strings */, true /* keep space strings */); - - // decode the month - int32 month = 0; - const AZStd::string& monthString = dateParts[0]; - const char* monthStrings[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; - for (int32 i = 0; i < 12; ++i) - { - if (monthString == monthStrings[i]) - { - month = i + 1; - break; - } - } - - //int32 day = dateParts[1].ToInt(); - int32 year; - if (!AzFramework::StringFunc::LooksLikeInt(dateParts[2].c_str(), &year)) - { - return false; - } - - // set if the file contains unicode strings or not based on the compilcation date - if (year < 2012 || (year == 2012 && month < 11)) - { - helperData->mIsUnicodeFile = false; - } - - //LogInfo( "String: '%s', Decoded: %i.%i.%i - isUnicode=%i", dateString, day, month, year, helperData->mIsUnicodeFile ); - - return helperData->mIsUnicodeFile; } - const char* SharedHelperData::ReadString(MCore::Stream* file, MCore::Array* sharedData, MCore::Endian::EEndianType endianType) { MCORE_ASSERT(file); @@ -366,25 +313,6 @@ namespace EMotionFX return helperData->mStringStorage; } - - // get the array of anim graph nodes - MCore::Array& SharedHelperData::GetBlendNodes(MCore::Array* sharedData) - { - // find the helper data - SharedData* data = Importer::FindSharedData(sharedData, SharedHelperData::TYPE_ID); - SharedHelperData* helperData = static_cast(data); - return helperData->mBlendNodes; - } - - // Get the table of entry state indices to state machines IDs - AZStd::map& SharedHelperData::GetEntryStateToStateMachineTable(MCore::Array* sharedData) - { - // Find the helper data - SharedData* data = Importer::FindSharedData(sharedData, SharedHelperData::TYPE_ID); - SharedHelperData* helperData = static_cast(data); - return helperData->m_entryNodeIndexToStateMachineIdLookupTable; - } - //----------------------------------------------------------------------------- // constructor @@ -1999,7 +1927,6 @@ namespace EMotionFX //---------------------------------------------------------------------------------------------------------- - // bool ChunkProcessorActorAttachmentNodes::Process(MCore::File* file, Importer::ImportParameters& importParams) { const MCore::Endian::EEndianType endianType = importParams.mEndianType; @@ -2055,866 +1982,6 @@ namespace EMotionFX return true; } - - //---------------------------------------------------------------------------------------------------------- - - // animGraph state transitions - bool ChunkProcessorAnimGraphStateTransitions::Process(MCore::File* file, Importer::ImportParameters& importParams) - { - // read the number of transitions to follow - uint32 numTransitions; - file->Read(&numTransitions, sizeof(uint32)); - MCore::Endian::ConvertUnsignedInt32(&numTransitions, importParams.mEndianType); - - // read the state machine index - uint32 stateMachineIndex; - file->Read(&stateMachineIndex, sizeof(uint32)); - MCore::Endian::ConvertUnsignedInt32(&stateMachineIndex, importParams.mEndianType); - - // get the loaded anim graph nodes - MCore::Array& blendNodes = SharedHelperData::GetBlendNodes(importParams.mSharedData); - if (stateMachineIndex >= blendNodes.GetLength()) - { - if (GetLogging()) - { - AZ_Error("EMotionFX", false, "State machine refers to invalid blend node, state machine index: %d, amount of blend node: %d", stateMachineIndex, blendNodes.GetLength()); - } - return false; - } - AZ_Assert(azrtti_typeid(blendNodes[stateMachineIndex]) == azrtti_typeid(), "ChunkProcessorAnimGraphStateTransitions::Process : Unexpected node type expected AnimGraphStateMachine. Found %u instead", azrtti_typeid(blendNodes[stateMachineIndex])); - AnimGraphStateMachine* stateMachine = static_cast(blendNodes[stateMachineIndex]); - - if (GetLogging()) - { - MCore::LogDetailedInfo("- Num transitions for state machine '%s' = %d", blendNodes[stateMachineIndex]->GetName(), numTransitions); - } - - stateMachine->ReserveTransitions(numTransitions); - - // read the transitions - FileFormat::AnimGraph_StateTransition transition; - for (uint32 i = 0; i < numTransitions; ++i) - { - // read the transition - file->Read(&transition, sizeof(FileFormat::AnimGraph_StateTransition)); - - // convert endian - MCore::Endian::ConvertUnsignedInt32(&transition.mSourceNode, importParams.mEndianType); - MCore::Endian::ConvertUnsignedInt32(&transition.mDestNode, importParams.mEndianType); - MCore::Endian::ConvertUnsignedInt32(&transition.mNumConditions, importParams.mEndianType); - MCore::Endian::ConvertSignedInt32(&transition.mStartOffsetX, importParams.mEndianType); - MCore::Endian::ConvertSignedInt32(&transition.mStartOffsetY, importParams.mEndianType); - MCore::Endian::ConvertSignedInt32(&transition.mEndOffsetX, importParams.mEndianType); - MCore::Endian::ConvertSignedInt32(&transition.mEndOffsetY, importParams.mEndianType); - - //---------------------------------------------- - // read the node header - FileFormat::AnimGraph_NodeHeader nodeHeader; - file->Read(&nodeHeader, sizeof(FileFormat::AnimGraph_NodeHeader)); - - // convert endian - MCore::Endian::ConvertUnsignedInt32(&nodeHeader.mTypeID, importParams.mEndianType); - MCore::Endian::ConvertUnsignedInt32(&nodeHeader.mParentIndex, importParams.mEndianType); - MCore::Endian::ConvertUnsignedInt32(&nodeHeader.mVersion, importParams.mEndianType); - MCore::Endian::ConvertUnsignedInt32(&nodeHeader.mNumCustomDataBytes, importParams.mEndianType); - MCore::Endian::ConvertUnsignedInt32(&nodeHeader.mNumChildNodes, importParams.mEndianType); - MCore::Endian::ConvertUnsignedInt32(&nodeHeader.mNumAttributes, importParams.mEndianType); - MCore::Endian::ConvertSignedInt32(&nodeHeader.mVisualPosX, importParams.mEndianType); - MCore::Endian::ConvertSignedInt32(&nodeHeader.mVisualPosY, importParams.mEndianType); - MCore::Endian::ConvertUnsignedInt32(&nodeHeader.mVisualizeColor, importParams.mEndianType); - - if (GetLogging()) - { - MCore::LogDetailedInfo("- State Transition Node:"); - MCore::LogDetailedInfo(" + Type = %d", nodeHeader.mTypeID); - MCore::LogDetailedInfo(" + Version = %d", nodeHeader.mVersion); - MCore::LogDetailedInfo(" + Num data bytes = %d", nodeHeader.mNumCustomDataBytes); - MCore::LogDetailedInfo(" + Num attributes = %d", nodeHeader.mNumAttributes); - MCore::LogDetailedInfo(" + Num conditions = %d", transition.mNumConditions); - MCore::LogDetailedInfo(" + Source node = %d", transition.mSourceNode); - MCore::LogDetailedInfo(" + Dest node = %d", transition.mDestNode); - } - - // create the transition object - AnimGraphStateTransition* emfxTransition = nullptr; - if (GetNewTypeIdByOldNodeTypeId(nodeHeader.mTypeID) == azrtti_typeid()) - { - emfxTransition = aznew AnimGraphStateTransition(); - } - - if (emfxTransition) - { - if (transition.mDestNode >= blendNodes.GetLength()) - { - if (GetLogging()) - { - AZ_Error("EMotionFX", false, "State machine transition refers to invalid destination blend node, transition index %d, blend node: %d", i, transition.mDestNode); - } - delete emfxTransition; - emfxTransition = nullptr; - } - // A source node index of MCORE_INVALIDINDEX32 indicates that the transition is a wildcard transition. Don't go into error state in this case. - else if (transition.mSourceNode != MCORE_INVALIDINDEX32 && transition.mSourceNode >= blendNodes.GetLength()) - { - if (GetLogging()) - { - AZ_Error("EMotionFX", false, "State machine transition refers to invalid source blend node, transition index %d, blend node: %d", i, transition.mSourceNode); - } - delete emfxTransition; - emfxTransition = nullptr; - } - else - { - AnimGraphNode* targetNode = blendNodes[transition.mDestNode]; - if (targetNode == nullptr) - { - delete emfxTransition; - emfxTransition = nullptr; - } - else - { - AZ_Assert(azrtti_istypeof(emfxTransition), "ChunkProcessorAnimGraphStateTransitions::Process : Unexpected node type expected AnimGraphStateTransition. Found %u instead", azrtti_typeid(blendNodes[stateMachineIndex])); - - // Now apply the transition settings - // Check if we are dealing with a wildcard transition - if (transition.mSourceNode == MCORE_INVALIDINDEX32) - { - emfxTransition->SetSourceNode(nullptr); - emfxTransition->SetIsWildcardTransition(true); - } - else - { - // set the source node - emfxTransition->SetSourceNode(blendNodes[transition.mSourceNode]); - } - - // set the destination node - emfxTransition->SetTargetNode(targetNode); - - emfxTransition->SetVisualOffsets(transition.mStartOffsetX, transition.mStartOffsetY, transition.mEndOffsetX, transition.mEndOffsetY); - - // now read the attributes - if (!LegacyAnimGraphNodeParser::ParseLegacyAttributes(file, nodeHeader.mNumAttributes, importParams.mEndianType, importParams, *emfxTransition)) - { - delete emfxTransition; - emfxTransition = nullptr; - AZ_Error("EMotionFX", false, "Unable to parse state transition"); - return false; - } - // add the transition to the state machine - stateMachine->AddTransition(emfxTransition); - } - } - } - - if (emfxTransition) - { - // iterate through all conditions - for (uint32 c = 0; c < transition.mNumConditions; ++c) - { - // read the condition node header - FileFormat::AnimGraph_NodeHeader conditionHeader; - file->Read(&conditionHeader, sizeof(FileFormat::AnimGraph_NodeHeader)); - - // convert endian - MCore::Endian::ConvertUnsignedInt32(&conditionHeader.mTypeID, importParams.mEndianType); - MCore::Endian::ConvertUnsignedInt32(&conditionHeader.mVersion, importParams.mEndianType); - MCore::Endian::ConvertUnsignedInt32(&conditionHeader.mNumCustomDataBytes, importParams.mEndianType); - MCore::Endian::ConvertUnsignedInt32(&conditionHeader.mNumAttributes, importParams.mEndianType); - - if (GetLogging()) - { - MCore::LogDetailedInfo(" - Transition Condition:"); - MCore::LogDetailedInfo(" + Type = %d", conditionHeader.mTypeID); - MCore::LogDetailedInfo(" + Version = %d", conditionHeader.mVersion); - MCore::LogDetailedInfo(" + Num data bytes = %d", conditionHeader.mNumCustomDataBytes); - MCore::LogDetailedInfo(" + Num attributes = %d", conditionHeader.mNumAttributes); - } - - AnimGraphTransitionCondition* emfxCondition = nullptr; - if (!LegacyAnimGraphNodeParser::ParseTransitionConditionChunk(file, importParams, conditionHeader, emfxCondition)) - { - AZ_Error("EMotionFX", false, "Unable to parse Transition condition of type %u in legacy file", azrtti_typeid(emfxCondition)); - delete emfxCondition; - emfxCondition = nullptr; - return false; - } - // add the condition to the transition - emfxTransition->AddCondition(emfxCondition); - } - - //emfxTransition->Init( animGraph ); - } - // something went wrong with creating the transition - else - { - MCore::LogWarning("Cannot load and instantiate state transition. State transition from %d to %d will be skipped.", transition.mSourceNode, transition.mDestNode); - - // skip reading the attributes - if (!ForwardAttributes(file, importParams.mEndianType, nodeHeader.mNumAttributes)) - { - return false; - } - - // skip reading the node custom data - if (file->Forward(nodeHeader.mNumCustomDataBytes) == false) - { - return false; - } - - // iterate through all conditions and skip them as well - for (uint32 c = 0; c < transition.mNumConditions; ++c) - { - // read the condition node header - FileFormat::AnimGraph_NodeHeader conditionHeader; - file->Read(&conditionHeader, sizeof(FileFormat::AnimGraph_NodeHeader)); - - // convert endian - MCore::Endian::ConvertUnsignedInt32(&conditionHeader.mTypeID, importParams.mEndianType); - MCore::Endian::ConvertUnsignedInt32(&conditionHeader.mVersion, importParams.mEndianType); - MCore::Endian::ConvertUnsignedInt32(&conditionHeader.mNumCustomDataBytes, importParams.mEndianType); - MCore::Endian::ConvertUnsignedInt32(&conditionHeader.mNumAttributes, importParams.mEndianType); - - // skip reading the attributes - if (!ForwardAttributes(file, importParams.mEndianType, conditionHeader.mNumAttributes)) - { - return false; - } - - // skip reading the node custom data - if (file->Forward(conditionHeader.mNumCustomDataBytes) == false) - { - return false; - } - } - } - } - - return true; - } - - //---------------------------------------------------------------------------------------------------------- - - // animGraph state transitions - bool ChunkProcessorAnimGraphAdditionalInfo::Process(MCore::File* file, Importer::ImportParameters& /*importParams*/) - { - return file->Forward(sizeof(FileFormat::AnimGraph_AdditionalInfo)); - } - - //---------------------------------------------------------------------------------------------------------- - - // animGraph node connections - bool ChunkProcessorAnimGraphNodeConnections::Process(MCore::File* file, Importer::ImportParameters& importParams) - { - // read the number of transitions to follow - uint32 numConnections; - file->Read(&numConnections, sizeof(uint32)); - MCore::Endian::ConvertUnsignedInt32(&numConnections, importParams.mEndianType); - - if (GetLogging()) - { - MCore::LogDetailedInfo("- Num node connections = %d", numConnections); - } - - // get the array of currently loaded nodes - MCore::Array& blendNodes = SharedHelperData::GetBlendNodes(importParams.mSharedData); - - // read the connections - FileFormat::AnimGraph_NodeConnection connection; - for (uint32 i = 0; i < numConnections; ++i) - { - // read the transition - file->Read(&connection, sizeof(FileFormat::AnimGraph_NodeConnection)); - - // convert endian - MCore::Endian::ConvertUnsignedInt32(&connection.mSourceNode, importParams.mEndianType); - MCore::Endian::ConvertUnsignedInt32(&connection.mTargetNode, importParams.mEndianType); - MCore::Endian::ConvertUnsignedInt16(&connection.mSourceNodePort, importParams.mEndianType); - MCore::Endian::ConvertUnsignedInt16(&connection.mTargetNodePort, importParams.mEndianType); - - // log details - if (GetLogging()) - { - MCore::LogDetailedInfo(" + Connection #%d = From node %d (port id %d) into node %d (port id %d)", i, connection.mSourceNode, connection.mSourceNodePort, connection.mTargetNode, connection.mTargetNodePort); - } - - // get the source and the target node and check if they are valid - AnimGraphNode* sourceNode = blendNodes[connection.mSourceNode]; - AnimGraphNode* targetNode = blendNodes[connection.mTargetNode]; - if (sourceNode == nullptr || targetNode == nullptr) - { - MCore::LogWarning("EMotionFX::ChunkProcessorAnimGraphNodeConnections() - Connection cannot be created because the source or target node is invalid! (sourcePortID=%d targetPortID=%d sourceNode=%d targetNode=%d)", connection.mSourceNodePort, connection.mTargetNodePort, connection.mSourceNode, connection.mTargetNode); - continue; - } - - // create the connection - const uint32 sourcePort = blendNodes[connection.mSourceNode]->FindOutputPortByID(connection.mSourceNodePort); - const uint32 targetPort = blendNodes[connection.mTargetNode]->FindInputPortByID(connection.mTargetNodePort); - if (sourcePort != MCORE_INVALIDINDEX32 && targetPort != MCORE_INVALIDINDEX32) - { - blendNodes[connection.mTargetNode]->AddConnection(blendNodes[connection.mSourceNode], static_cast(sourcePort), static_cast(targetPort)); - } - else - { - MCore::LogWarning("EMotionFX::ChunkProcessorAnimGraphNodeConnections() - Connection cannot be created because the source or target port doesn't exist! (sourcePortID=%d targetPortID=%d sourceNode='%s' targetNode=%s')", connection.mSourceNodePort, connection.mTargetNodePort, blendNodes[connection.mSourceNode]->GetName(), blendNodes[connection.mTargetNode]->GetName()); - } - } - - return true; - } - - //---------------------------------------------------------------------------------------------------------- - - // animGraph node - bool ChunkProcessorAnimGraphNode::Process(MCore::File* file, Importer::ImportParameters& importParams) - { - AnimGraph* animGraph = importParams.mAnimGraph; - MCORE_ASSERT(animGraph); - - // read the node header - FileFormat::AnimGraph_NodeHeader nodeHeader; - file->Read(&nodeHeader, sizeof(FileFormat::AnimGraph_NodeHeader)); - - // convert endian - MCore::Endian::ConvertUnsignedInt32(&nodeHeader.mTypeID, importParams.mEndianType); - MCore::Endian::ConvertUnsignedInt32(&nodeHeader.mParentIndex, importParams.mEndianType); - MCore::Endian::ConvertUnsignedInt32(&nodeHeader.mVersion, importParams.mEndianType); - MCore::Endian::ConvertUnsignedInt32(&nodeHeader.mNumCustomDataBytes, importParams.mEndianType); - MCore::Endian::ConvertUnsignedInt32(&nodeHeader.mNumChildNodes, importParams.mEndianType); - MCore::Endian::ConvertUnsignedInt32(&nodeHeader.mNumAttributes, importParams.mEndianType); - MCore::Endian::ConvertUnsignedInt32(&nodeHeader.mVisualizeColor, importParams.mEndianType); - MCore::Endian::ConvertSignedInt32(&nodeHeader.mVisualPosX, importParams.mEndianType); - MCore::Endian::ConvertSignedInt32(&nodeHeader.mVisualPosY, importParams.mEndianType); - - const char* nodeName = SharedHelperData::ReadString(file, importParams.mSharedData, importParams.mEndianType); - if (GetLogging()) - { - MCore::LogDetailedInfo("- Blend Node:"); - MCore::LogDetailedInfo(" + Name = %s", nodeName); - MCore::LogDetailedInfo(" + Parent index = %d", nodeHeader.mParentIndex); - MCore::LogDetailedInfo(" + Type = %d", nodeHeader.mTypeID); - MCore::LogDetailedInfo(" + Version = %d", nodeHeader.mVersion); - MCore::LogDetailedInfo(" + Num data bytes = %d", nodeHeader.mNumCustomDataBytes); - MCore::LogDetailedInfo(" + Num child nodes = %d", nodeHeader.mNumChildNodes); - MCore::LogDetailedInfo(" + Num attributes = %d", nodeHeader.mNumAttributes); - MCore::LogDetailedInfo(" + Visualize Color = %d, %d, %d", MCore::ExtractRed(nodeHeader.mVisualizeColor), MCore::ExtractGreen(nodeHeader.mVisualizeColor), MCore::ExtractBlue(nodeHeader.mVisualizeColor)); - MCore::LogDetailedInfo(" + Visual pos = (%d, %d)", nodeHeader.mVisualPosX, nodeHeader.mVisualPosY); - MCore::LogDetailedInfo(" + Collapsed = %s", (nodeHeader.mFlags & FileFormat::ANIMGRAPH_NODEFLAG_COLLAPSED) ? "Yes" : "No"); - MCore::LogDetailedInfo(" + Visualized = %s", (nodeHeader.mFlags & FileFormat::ANIMGRAPH_NODEFLAG_VISUALIZED) ? "Yes" : "No"); - MCore::LogDetailedInfo(" + Disabled = %s", (nodeHeader.mFlags & FileFormat::ANIMGRAPH_NODEFLAG_DISABLED) ? "Yes" : "No"); - MCore::LogDetailedInfo(" + Virtual FinalOut= %s", (nodeHeader.mFlags & FileFormat::ANIMGRAPH_NODEFLAG_VIRTUALFINALOUTPUT) ? "Yes" : "No"); - } - - AnimGraphNode* node = nullptr; - if (!LegacyAnimGraphNodeParser::ParseAnimGraphNodeChunk(file - , importParams - , nodeName - , nodeHeader - , node)) - { - if (importParams.mAnimGraph->GetRootStateMachine() == node) - { - importParams.mAnimGraph->SetRootStateMachine(nullptr); - } - - if (node) - { - AnimGraphNode* parentNode = node->GetParentNode(); - if (parentNode) - { - parentNode->RemoveChildNodeByPointer(node, false); - } - } - - delete node; - node = nullptr; - return false; - } - - EMotionFX::GetEventManager().OnCreatedNode(animGraph, node); - - return true; - } - - //---------------------------------------------------------------------------------------------------------- - - // animGraph parameters - bool ChunkProcessorAnimGraphParameters::Process(MCore::File* file, Importer::ImportParameters& importParams) - { - AnimGraph* animGraph = importParams.mAnimGraph; - MCORE_ASSERT(animGraph); - - // read the number of parameters - uint32 numParams; - file->Read(&numParams, sizeof(uint32)); - MCore::Endian::ConvertUnsignedInt32(&numParams, importParams.mEndianType); - - if (GetLogging()) - { - MCore::LogDetailedInfo("- Num parameters = %d", numParams); - } - - // read all parameters - for (uint32 p = 0; p < numParams; ++p) - { - // read the parameter info header - FileFormat::AnimGraph_ParameterInfo paramInfo; - file->Read(¶mInfo, sizeof(FileFormat::AnimGraph_ParameterInfo)); - - // convert endian - MCore::Endian::ConvertUnsignedInt32(¶mInfo.mNumComboValues, importParams.mEndianType); - MCore::Endian::ConvertUnsignedInt32(¶mInfo.mInterfaceType, importParams.mEndianType); - MCore::Endian::ConvertUnsignedInt32(¶mInfo.mAttributeType, importParams.mEndianType); - MCore::Endian::ConvertUnsignedInt16(¶mInfo.mFlags, importParams.mEndianType); - - // check the attribute type - const uint32 attribType = paramInfo.mAttributeType; - if (attribType == 0) - { - MCore::LogError("EMotionFX::ChunkProcessorAnimGraphParameters::Process() - Failed to convert interface type %d to an attribute type.", attribType); - return false; - } - - const AZ::TypeId parameterTypeId = EMotionFX::FileFormat::GetParameterTypeIdForInterfaceType(paramInfo.mInterfaceType); - const AZStd::string name = SharedHelperData::ReadString(file, importParams.mSharedData, importParams.mEndianType); - AZStd::unique_ptr newParam(EMotionFX::ParameterFactory::Create(parameterTypeId)); - AZ_Assert(azrtti_istypeof(newParam.get()), "Expected a value parameter"); - - if (!newParam) - { - MCore::LogError("EMotionFX::ChunkProcessorAnimGraphParameters::Process() - Failed to create parameter: '%s'.", name.c_str()); - return false; - } - - // read the strings - newParam->SetName(name); - SharedHelperData::ReadString(file, importParams.mSharedData, importParams.mEndianType); // We dont use internal name anymore - newParam->SetDescription(SharedHelperData::ReadString(file, importParams.mSharedData, importParams.mEndianType)); - - // log the details - if (GetLogging()) - { - MCore::LogDetailedInfo("- Parameter #%d:", p); - MCore::LogDetailedInfo(" + Name = %s", newParam->GetName().c_str()); - MCore::LogDetailedInfo(" + Description = %s", newParam->GetDescription().c_str()); - MCore::LogDetailedInfo(" + type = %s", newParam->RTTI_GetTypeName()); - MCore::LogDetailedInfo(" + Attribute type = %d", paramInfo.mAttributeType); - MCore::LogDetailedInfo(" + Has MinMax = %d", paramInfo.mHasMinMax); - MCore::LogDetailedInfo(" + Flags = %d", paramInfo.mFlags); - } - - MCore::Attribute* attr(MCore::GetAttributeFactory().CreateAttributeByType(attribType)); - EMotionFX::ValueParameter* valueParameter = static_cast(newParam.get()); - - // create the min, max and default value attributes - if (paramInfo.mHasMinMax == 1) - { - // min value - attr->Read(file, importParams.mEndianType); - valueParameter->SetMinValueFromAttribute(attr); - - // max value - attr->Read(file, importParams.mEndianType); - valueParameter->SetMaxValueFromAttribute(attr); - } - - // default value - attr->Read(file, importParams.mEndianType); - valueParameter->SetDefaultValueFromAttribute(attr); - delete attr; - - // Parameters were previously stored in "AttributeSettings". The calss supported - // multiple values, however, the UI did not, so this ended up not being used. - // Support for multiple values in parameters is possible, however we dont need it now. - // Leaving this code as reference - for (uint32 i = 0; i < paramInfo.mNumComboValues; ++i) - { - SharedHelperData::ReadString(file, importParams.mSharedData, importParams.mEndianType); - } - - if (!animGraph->AddParameter(newParam.get())) - { - MCore::LogError("EMotionFX::ChunkProcessorAnimGraphParameters::Process() - Failed to add parameter: '%s'.", name.c_str()); - return false; - } - newParam.release(); // ownership moved to animGraph - } - - return true; - } - - - // animGraph node groups - bool ChunkProcessorAnimGraphNodeGroups::Process(MCore::File* file, Importer::ImportParameters& importParams) - { - AnimGraph* animGraph = importParams.mAnimGraph; - MCORE_ASSERT(animGraph); - - // read the number of node groups - uint32 numNodeGroups; - file->Read(&numNodeGroups, sizeof(uint32)); - MCore::Endian::ConvertUnsignedInt32(&numNodeGroups, importParams.mEndianType); - - if (GetLogging()) - { - MCore::LogDetailedInfo("- Num Node Groups = %d", numNodeGroups); - } - - // read all node groups - for (uint32 g = 0; g < numNodeGroups; ++g) - { - // read the node group header - FileFormat::AnimGraph_NodeGroup nodeGroupChunk; - file->Read(&nodeGroupChunk, sizeof(FileFormat::AnimGraph_NodeGroup)); - - MCore::RGBAColor emfxColor(nodeGroupChunk.mColor.mR, nodeGroupChunk.mColor.mG, nodeGroupChunk.mColor.mB, nodeGroupChunk.mColor.mA); - - // convert endian - MCore::Endian::ConvertUnsignedInt32(&nodeGroupChunk.mNumNodes, importParams.mEndianType); - MCore::Endian::ConvertRGBAColor(&emfxColor, importParams.mEndianType); - - const AZ::Color color128 = MCore::EmfxColorToAzColor(emfxColor); - const AZ::u32 color32 = color128.ToU32(); - - const char* groupName = SharedHelperData::ReadString(file, importParams.mSharedData, importParams.mEndianType); - const uint32 numNodes = nodeGroupChunk.mNumNodes; - - // create and fill the new node group - AnimGraphNodeGroup* nodeGroup = aznew AnimGraphNodeGroup(groupName); - animGraph->AddNodeGroup(nodeGroup); - nodeGroup->SetIsVisible(nodeGroupChunk.mIsVisible != 0); - nodeGroup->SetColor(color32); - - // set the nodes of the node group - MCore::Array& blendNodes = SharedHelperData::GetBlendNodes(importParams.mSharedData); - nodeGroup->SetNumNodes(numNodes); - for (uint32 i = 0; i < numNodes; ++i) - { - // read the node index of the current node inside the group - uint32 nodeNr; - file->Read(&nodeNr, sizeof(uint32)); - MCore::Endian::ConvertUnsignedInt32(&nodeNr, importParams.mEndianType); - - MCORE_ASSERT(nodeNr != MCORE_INVALIDINDEX32); - - // set the id of the given node to the group - if (nodeNr != MCORE_INVALIDINDEX32 && blendNodes[nodeNr]) - { - nodeGroup->SetNode(i, blendNodes[nodeNr]->GetId()); - } - else - { - nodeGroup->SetNode(i, AnimGraphNodeId::InvalidId); - } - } - - // log the details - if (GetLogging()) - { - MCore::LogDetailedInfo("- Node Group #%d:", g); - MCore::LogDetailedInfo(" + Name = %s", nodeGroup->GetName()); - MCore::LogDetailedInfo(" + Color = (%.2f, %.2f, %.2f, %.2f)", static_cast(color128.GetR()), static_cast(color128.GetG()), static_cast(color128.GetB()), static_cast(color128.GetA())); - MCore::LogDetailedInfo(" + Num Nodes = %i", nodeGroup->GetNumNodes()); - } - } - - return true; - } - - - // animGraph group parameters - bool ChunkProcessorAnimGraphGroupParameters::Process(MCore::File* file, Importer::ImportParameters& importParams) - { - AnimGraph* animGraph = importParams.mAnimGraph; - MCORE_ASSERT(animGraph); - - // read the number of group parameters - uint32 numGroupParameters; - file->Read(&numGroupParameters, sizeof(uint32)); - MCore::Endian::ConvertUnsignedInt32(&numGroupParameters, importParams.mEndianType); - - if (GetLogging()) - { - MCore::LogDetailedInfo("- Num group parameters = %d", numGroupParameters); - } - - // Group parameters is going to re-shuffle the value parameter indices, therefore we - // need to update the connections downstream of parameter nodes. - EMotionFX::ValueParameterVector valueParametersBeforeChange = animGraph->RecursivelyGetValueParameters(); - - // Since relocating a parameter to another parent changes its index, we are going to - // compute all the relationships leaving the value parameters at the root, then relocate - // them. - AZStd::vector > parametersByGroup; - - // read all group parameters - for (uint32 g = 0; g < numGroupParameters; ++g) - { - // read the group parameter header - FileFormat::AnimGraph_GroupParameter groupChunk; - file->Read(&groupChunk, sizeof(FileFormat::AnimGraph_GroupParameter)); - - // convert endian - MCore::Endian::ConvertUnsignedInt32(&groupChunk.mNumParameters, importParams.mEndianType); - - const char* groupName = SharedHelperData::ReadString(file, importParams.mSharedData, importParams.mEndianType); - const uint32 numParameters = groupChunk.mNumParameters; - - // create and fill the new group parameter - AZStd::unique_ptr parameter(EMotionFX::ParameterFactory::Create(azrtti_typeid())); - parameter->SetName(groupName); - - // Previously collapsed/expanded state in group parameters was stored in the animgraph file. However, that - // would require to check out the animgraph file if you expand/collapse a group. Because this change was not - // done through commands, the dirty state was not properly restored. - // Collapsing state should be more of a setting per-user than something saved in the animgraph - //groupParameter->SetIsCollapsed(groupChunk.mCollapsed != 0); - - if (!animGraph->AddParameter(parameter.get())) - { - continue; - } - const EMotionFX::GroupParameter* groupParameter = static_cast(parameter.release()); - - parametersByGroup.emplace_back(groupParameter, EMotionFX::ParameterVector()); - AZStd::vector& parametersInGroup = parametersByGroup.back().second; - - // set the parameters of the group parameter - for (uint32 i = 0; i < numParameters; ++i) - { - // read the parameter index - uint32 parameterIndex; - file->Read(¶meterIndex, sizeof(uint32)); - MCore::Endian::ConvertUnsignedInt32(¶meterIndex, importParams.mEndianType); - - MCORE_ASSERT(parameterIndex != MCORE_INVALIDINDEX32); - if (parameterIndex != MCORE_INVALIDINDEX32) - { - const EMotionFX::Parameter* childParameter = animGraph->FindValueParameter(parameterIndex); - parametersInGroup.emplace_back(const_cast(childParameter)); - } - } - - // log the details - if (GetLogging()) - { - MCore::LogDetailedInfo("- Group parameter #%d:", g); - MCore::LogDetailedInfo(" + Name = %s", groupParameter->GetName().c_str()); - MCore::LogDetailedInfo(" + Num Parameters = %i", groupParameter->GetNumParameters()); - } - } - - // Now move the parameters to their groups - for (const AZStd::pair& groupAndParameters : parametersByGroup) - { - const EMotionFX::GroupParameter* groupParameter = groupAndParameters.first; - for (EMotionFX::Parameter* parameter : groupAndParameters.second) - { - animGraph->TakeParameterFromParent(parameter); - animGraph->AddParameter(const_cast(parameter), groupParameter); - } - } - - const EMotionFX::ValueParameterVector valueParametersAfterChange = animGraph->RecursivelyGetValueParameters(); - - AZStd::vector affectedObjects; - animGraph->RecursiveCollectObjectsOfType(azrtti_typeid(), affectedObjects); - - for (EMotionFX::AnimGraphObject* affectedObject : affectedObjects) - { - EMotionFX::ObjectAffectedByParameterChanges* affectedObjectByParameterChanges = azdynamic_cast(affectedObject); - affectedObjectByParameterChanges->ParameterOrderChanged(valueParametersBeforeChange, valueParametersAfterChange); - } - - return true; - } - - - // animGraph game controller settings - bool ChunkProcessorAnimGraphGameControllerSettings::Process(MCore::File* file, Importer::ImportParameters& importParams) - { - uint32 i; - - AnimGraph* animGraph = importParams.mAnimGraph; - MCORE_ASSERT(animGraph); - - // get the game controller settings for the anim graph and clear it - AnimGraphGameControllerSettings& gameControllerSettings = animGraph->GetGameControllerSettings(); - gameControllerSettings.Clear(); - - // read the number of presets and the active preset index - uint32 activePresetIndex, numPresets; - file->Read(&activePresetIndex, sizeof(uint32)); - file->Read(&numPresets, sizeof(uint32)); - - // convert endian - MCore::Endian::ConvertUnsignedInt32(&activePresetIndex, importParams.mEndianType); - MCore::Endian::ConvertUnsignedInt32(&numPresets, importParams.mEndianType); - - if (GetLogging()) - { - MCore::LogDetailedInfo("- Game Controller Settings (NumPresets=%d, ActivePreset=%d)", numPresets, activePresetIndex); - } - - // preallocate memory for the presets - gameControllerSettings.SetNumPresets(numPresets); - - // read all presets - for (uint32 p = 0; p < numPresets; ++p) - { - // read the preset chunk - FileFormat::AnimGraph_GameControllerPreset presetChunk; - file->Read(&presetChunk, sizeof(FileFormat::AnimGraph_GameControllerPreset)); - - // convert endian - MCore::Endian::ConvertUnsignedInt32(&presetChunk.mNumParameterInfos, importParams.mEndianType); - MCore::Endian::ConvertUnsignedInt32(&presetChunk.mNumButtonInfos, importParams.mEndianType); - - // read the preset name and get the number of parameter and button infos - const char* presetName = SharedHelperData::ReadString(file, importParams.mSharedData, importParams.mEndianType); - const uint32 numParamInfos = presetChunk.mNumParameterInfos; - const uint32 numButtonInfos = presetChunk.mNumButtonInfos; - - // create and fill the new preset - AnimGraphGameControllerSettings::Preset* preset = aznew AnimGraphGameControllerSettings::Preset(presetName); - gameControllerSettings.SetPreset(p, preset); - - // read the parameter infos - preset->SetNumParamInfos(numParamInfos); - for (i = 0; i < numParamInfos; ++i) - { - // read the parameter info chunk - FileFormat::AnimGraph_GameControllerParameterInfo paramInfoChunk; - file->Read(¶mInfoChunk, sizeof(FileFormat::AnimGraph_GameControllerParameterInfo)); - - // read the parameter name - const char* parameterName = SharedHelperData::ReadString(file, importParams.mSharedData, importParams.mEndianType); - - // construct and fill the parameter info - AnimGraphGameControllerSettings::ParameterInfo* parameterInfo = aznew AnimGraphGameControllerSettings::ParameterInfo(parameterName); - parameterInfo->m_axis = paramInfoChunk.mAxis; - parameterInfo->m_invert = (paramInfoChunk.mInvert != 0); - parameterInfo->m_mode = (AnimGraphGameControllerSettings::ParameterMode)paramInfoChunk.mMode; - - preset->SetParamInfo(i, parameterInfo); - } - - // read the button infos - preset->SetNumButtonInfos(numButtonInfos); - for (i = 0; i < numButtonInfos; ++i) - { - // read the button info chunk - FileFormat::AnimGraph_GameControllerButtonInfo buttonInfoChunk; - file->Read(&buttonInfoChunk, sizeof(FileFormat::AnimGraph_GameControllerButtonInfo)); - - // read the button string - const char* buttonString = SharedHelperData::ReadString(file, importParams.mSharedData, importParams.mEndianType); - - // construct and fill the button info - AnimGraphGameControllerSettings::ButtonInfo* buttonInfo = aznew AnimGraphGameControllerSettings::ButtonInfo(buttonInfoChunk.mButtonIndex); - buttonInfo->m_mode = (AnimGraphGameControllerSettings::ButtonMode)buttonInfoChunk.mMode; - buttonInfo->m_string = buttonString; - - preset->SetButtonInfo(i, buttonInfo); - } - - // log the details - if (GetLogging()) - { - MCore::LogDetailedInfo("- Preset '%s':", preset->GetName()); - MCore::LogDetailedInfo(" + Num Param Infos = %d", preset->GetNumParamInfos()); - MCore::LogDetailedInfo(" + Num Button Infos = %d", preset->GetNumButtonInfos()); - } - } - - // set the active preset - if (activePresetIndex != MCORE_INVALIDINDEX32) - { - AnimGraphGameControllerSettings::Preset* activePreset = gameControllerSettings.GetPreset(activePresetIndex); - gameControllerSettings.SetActivePreset(activePreset); - } - - return true; - } - - //---------------------------------------------------------------------------------------------------------- - // MotionSet - //---------------------------------------------------------------------------------------------------------- - - // all submotions in one chunk - bool ChunkProcessorMotionSet::Process(MCore::File* file, Importer::ImportParameters& importParams) - { - const MCore::Endian::EEndianType endianType = importParams.mEndianType; - - FileFormat::MotionSetsChunk motionSetsChunk; - file->Read(&motionSetsChunk, sizeof(FileFormat::MotionSetsChunk)); - - // convert endian - MCore::Endian::ConvertUnsignedInt32(&motionSetsChunk.mNumSets, endianType); - - // get the number of motion sets and iterate through them - const uint32 numMotionSets = motionSetsChunk.mNumSets; - for (uint32 i = 0; i < numMotionSets; ++i) - { - FileFormat::MotionSetChunk motionSetChunk; - file->Read(&motionSetChunk, sizeof(FileFormat::MotionSetChunk)); - - // convert endian - MCore::Endian::ConvertUnsignedInt32(&motionSetChunk.mNumChildSets, endianType); - MCore::Endian::ConvertUnsignedInt32(&motionSetChunk.mNumMotionEntries, endianType); - - // get the parent set - const char* parentSetName = SharedHelperData::ReadString(file, importParams.mSharedData, endianType); - GetMotionManager().Lock(); - MotionSet* parentSet = GetMotionManager().FindMotionSetByName(parentSetName, importParams.m_isOwnedByRuntime); - GetMotionManager().Unlock(); - - // read the motion set name and create our new motion set - const char* motionSetName = SharedHelperData::ReadString(file, importParams.mSharedData, endianType); - MotionSet* motionSet = aznew MotionSet(motionSetName, parentSet); - motionSet->SetIsOwnedByRuntime(importParams.m_isOwnedByRuntime); - - // set the root motion set to the importer params motion set, this will be returned by the Importer::LoadMotionSet() function - if (parentSet == nullptr) - { - assert(importParams.mMotionSet == nullptr); - importParams.mMotionSet = motionSet; - } - - // read the filename and set it - /*const char* motionSetFileName = */ SharedHelperData::ReadString(file, importParams.mSharedData, endianType); - //motionSet->SetFileName( motionSetFileName ); - - // in case this is not a root motion set add the new motion set as child set to the parent set - if (parentSet) - { - parentSet->AddChildSet(motionSet); - } - - // Read all motion entries. - const uint32 numMotionEntries = motionSetChunk.mNumMotionEntries; - motionSet->ReserveMotionEntries(numMotionEntries); - AZStd::string nativeMotionFileName; - for (uint32 j = 0; j < numMotionEntries; ++j) - { - // read the motion entry - const char* motionFileName = SharedHelperData::ReadString(file, importParams.mSharedData, endianType); - nativeMotionFileName = motionFileName; - - // read the string id and set it - const char* motionStringID = SharedHelperData::ReadString(file, importParams.mSharedData, endianType); - - // add the motion entry to the motion set - MotionSet::MotionEntry* motionEntry = aznew MotionSet::MotionEntry(nativeMotionFileName.c_str(), motionStringID); - motionSet->AddMotionEntry(motionEntry); - } - } - - return true; - } - - - //---------------------------------------------------------------------------------------------------------- // NodeMap //---------------------------------------------------------------------------------------------------------- diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/ChunkProcessors.h b/Gems/EMotionFX/Code/EMotionFX/Source/Importer/ChunkProcessors.h index 3d0412eb3f..306e4af0c8 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/ChunkProcessors.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Importer/ChunkProcessors.h @@ -16,8 +16,6 @@ #include "SharedFileFormatStructs.h" #include "ActorFileFormat.h" #include "MotionFileFormat.h" -#include "AnimGraphFileFormat.h" -#include "MotionSetFileFormat.h" #include "NodeMapFileFormat.h" #include "Importer.h" #include @@ -32,7 +30,6 @@ namespace EMotionFX class Importer; class AnimGraphNode; - /** * Shared importer data class. * Chunks can load data, which might be shared between other chunks during import. @@ -57,20 +54,11 @@ namespace EMotionFX virtual void Reset() {} protected: - /** - * The constructor. - */ SharedData() : BaseObject() {} - - /** - * The destructor. - */ virtual ~SharedData() { Reset(); } }; - - /** * Helper class for reading strings from files and file information storage. */ @@ -108,34 +96,12 @@ namespace EMotionFX */ static const char* ReadString(MCore::Stream* file, MCore::Array* sharedData, MCore::Endian::EEndianType endianType); - /** - * Get the array of currently loaded anim graph nodes. - * @param sharedData The array which holds the shared data objects. - * @result The array of currently loaded anim graph nodes. - */ - static MCore::Array& GetBlendNodes(MCore::Array* sharedData); - - /** - * Get the table to look up a state machine that needs an entry state as they are created. - * @param sharedData The array which holds the shared data objects. - * @result The map whose keys are the indices of entry states and the values are the IDs of the state machines that need those as entry states. - */ - static AZStd::map& GetEntryStateToStateMachineTable(MCore::Array* sharedData); - - /** - * Checks if the strings in the file are encoded using unicode or multi-byte based on the exporter date. - * The first official EMotion FX version to use unicode was compiled on 26th November 2012. - */ - static bool GetIsUnicodeFile(const char* dateString, MCore::Array* sharedData); - public: uint32 mFileHighVersion; /**< The high file version. For example 3 in case of v3.10. */ uint32 mFileLowVersion; /**< The low file version. For example 10 in case of v3.10. */ uint32 mStringStorageSize; /**< The size of the string buffer. */ bool mIsUnicodeFile; /**< True in case strings in the file are saved using unicode character set, false in case they are saved using multi-byte. */ char* mStringStorage; /**< The shared string buffer. */ - MCore::Array mBlendNodes; /**< Array of read anim graph nodes. */ - AZStd::map m_entryNodeIndexToStateMachineIdLookupTable; protected: /** * The constructor. @@ -338,22 +304,6 @@ namespace EMotionFX EMFX_CHUNKPROCESSOR(ChunkProcessorMotionMorphSubMotions, FileFormat::MOTION_CHUNK_MORPHSUBMOTIONS, 1) EMFX_CHUNKPROCESSOR(ChunkProcessorMotionData, FileFormat::MOTION_CHUNK_MOTIONDATA, 1) - // Anim graph file format chunk processors - EMFX_CHUNKPROCESSOR(ChunkProcessorAnimGraphStateTransitions, FileFormat::ANIMGRAPH_CHUNK_STATETRANSITIONS, 1) - EMFX_CHUNKPROCESSOR(ChunkProcessorAnimGraphNodeConnections, FileFormat::ANIMGRAPH_CHUNK_NODECONNECTIONS, 1) - EMFX_CHUNKPROCESSOR(ChunkProcessorAnimGraphParameters, FileFormat::ANIMGRAPH_CHUNK_PARAMETERS, 1) - EMFX_CHUNKPROCESSOR(ChunkProcessorAnimGraphNodeGroups, FileFormat::ANIMGRAPH_CHUNK_NODEGROUPS, 1) - EMFX_CHUNKPROCESSOR(ChunkProcessorAnimGraphGroupParameters, FileFormat::ANIMGRAPH_CHUNK_GROUPPARAMETERS, 1) - EMFX_CHUNKPROCESSOR(ChunkProcessorAnimGraphGameControllerSettings, FileFormat::ANIMGRAPH_CHUNK_GAMECONTROLLERSETTINGS, 1) - EMFX_CHUNKPROCESSOR(ChunkProcessorAnimGraphNode, FileFormat::ANIMGRAPH_CHUNK_BLENDNODE, 1) - EMFX_CHUNKPROCESSOR(ChunkProcessorAnimGraphAdditionalInfo, FileFormat::ANIMGRAPH_CHUNK_ADDITIONALINFO, 1) - - // motion set file format chunk processors - EMFX_CHUNKPROCESSOR(ChunkProcessorMotionSet, FileFormat::CHUNK_MOTIONSET, 1) - // node map file format chunk processors EMFX_CHUNKPROCESSOR(ChunkProcessorNodeMap, FileFormat::CHUNK_NODEMAP, 1) - - - //------------------------------------------------------------------------------------------------- } // namespace EMotionFX From abc501e535dcf8a3ea009df921d97284b53c573f Mon Sep 17 00:00:00 2001 From: Benjamin Jillich Date: Mon, 26 Jul 2021 09:58:24 +0200 Subject: [PATCH 033/160] Removed legacy file format loading for anim graphs and motion sets Signed-off-by: Benjamin Jillich --- .../EMotionFX/Source/Importer/Importer.cpp | 518 ++---------------- .../Code/EMotionFX/Source/Importer/Importer.h | 65 +-- 2 files changed, 35 insertions(+), 548 deletions(-) diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/Importer.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Importer/Importer.cpp index 6ac4493275..67cbb91c06 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/Importer.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Importer/Importer.cpp @@ -156,85 +156,6 @@ namespace EMotionFX return true; } - - // check if we can process the given motion set file - bool Importer::CheckIfIsValidMotionSetFile(MCore::File* f, MCore::Endian::EEndianType* outEndianType) const - { - MCORE_ASSERT(f->GetIsOpen()); - - // verify if we actually are dealing with a valid actor file - FileFormat::MotionSet_Header header; - if (f->Read(&header, sizeof(FileFormat::MotionSet_Header)) == 0) - { - MCore::LogError("Failed to read the motion set file header!"); - return false; - } - - // check the FOURCC - if (header.mFourCC[0] != 'M' || header.mFourCC[1] != 'O' || header.mFourCC[2] != 'S' || header.mFourCC[3] != ' ') - { - return false; - } - - // read the chunks - switch (header.mEndianType) - { - case 0: - *outEndianType = MCore::Endian::ENDIAN_LITTLE; - break; - case 1: - *outEndianType = MCore::Endian::ENDIAN_BIG; - break; - default: - MCore::LogError("Unsupported endian type used! (endian type = %d)", header.mEndianType); - return false; - } - ; - - // yes, it is a valid motionset file! - return true; - } - - - - // check if we can process the given anim graph file - bool Importer::CheckIfIsValidAnimGraphFile(MCore::File* f, MCore::Endian::EEndianType* outEndianType) const - { - MCORE_ASSERT(f->GetIsOpen()); - - // verify if we actually are dealing with a valid actor file - FileFormat::AnimGraph_Header header; - if (f->Read(&header, sizeof(FileFormat::AnimGraph_Header)) == 0) - { - return false; - } - - // check the FOURCC - if (header.mFourCC[0] != 'A' || header.mFourCC[1] != 'N' || header.mFourCC[2] != 'G' || header.mFourCC[3] != 'R') - { - return false; - } - - // read the chunks - switch (header.mEndianType) - { - case 0: - *outEndianType = MCore::Endian::ENDIAN_LITTLE; - break; - case 1: - *outEndianType = MCore::Endian::ENDIAN_BIG; - break; - default: - MCore::LogError("Unsupported endian type used! (endian type = %d)", header.mEndianType); - return false; - } - ; - - // yes, it is a valid anim graph file! - return true; - } - - // check if we can process the given node map file bool Importer::CheckIfIsValidNodeMapFile(MCore::File* f, MCore::Endian::EEndianType* outEndianType) const { @@ -599,125 +520,32 @@ namespace EMotionFX //------------------------------------------------------------------------------------------------- - // try to load a motion set from disk MotionSet* Importer::LoadMotionSet(AZStd::string filename, MotionSetSettings* settings, const AZ::ObjectStream::FilterDescriptor& loadFilter) { EBUS_EVENT(AzFramework::ApplicationRequests::Bus, NormalizePathKeepCase, filename); - const bool isLegacyFile = Importer::CheckFileType(filename.c_str()) == Importer::EFileType::FILETYPE_MOTIONSET; - if (!isLegacyFile) - { - AZ::SerializeContext* context = nullptr; - AZ::ComponentApplicationBus::BroadcastResult(context, &AZ::ComponentApplicationBus::Events::GetSerializeContext); - if (!context) - { - AZ_Error("EMotionFX", false, "Can't get serialize context from component application."); - return nullptr; - } - - EMotionFX::MotionSet* motionSet = EMotionFX::MotionSet::LoadFromFile(filename, context, loadFilter); - if (motionSet) - { - motionSet->SetFilename(filename.c_str()); - } - return motionSet; - } - - ////////////////////////////////////////// - // Legacy file type loading - ////////////////////////////////////////// - - // check if we want to load the motion set even if a motion set with the given filename is already inside the motion manager - if (settings == nullptr || settings->mForceLoading == false) - { - // search the motion set inside the motion manager and return it if it already got loaded - MotionSet* motionSet = GetMotionManager().FindMotionSetByFileName(filename.c_str()); - if (motionSet) - { - MCore::LogInfo(" + Motion set '%s' already loaded, returning already loaded motion set from the MotionManager.", filename.c_str()); - return motionSet; - } - } - - if (GetLogging()) - { - MCore::LogInfo("- Trying to load motion set from file '%s'...", filename.c_str()); - } - - // try to open the file from disk - MCore::DiskFile f; - if (f.Open(filename.c_str(), MCore::DiskFile::READ) == false) + AZ::SerializeContext* context = nullptr; + AZ::ComponentApplicationBus::BroadcastResult(context, &AZ::ComponentApplicationBus::Events::GetSerializeContext); + if (!context) { - if (GetLogging()) - { - MCore::LogError(" + Failed to open the file for motion set."); - } + AZ_Error("EMotionFX", false, "Can't get serialize context from component application."); return nullptr; } - // retrieve the filesize - const size_t fileSize = f.GetFileSize(); - - // create a temporary buffer for the file - uint8* fileBuffer = (uint8*)MCore::Allocate(fileSize, EMFX_MEMCATEGORY_IMPORTER); - - // read in the complete file - f.Read(fileBuffer, fileSize); - - // close the file again - f.Close(); - - // create the motion set reading from memory - MotionSet* result = LoadMotionSet(fileBuffer, fileSize, settings); - if (result) + EMotionFX::MotionSet* motionSet = EMotionFX::MotionSet::LoadFromFile(filename, context, loadFilter); + if (motionSet) { - result->SetFilename(filename.c_str()); - } - - // delete the filebuffer again - MCore::Free(fileBuffer); - - // check if it worked :) - if (result == nullptr) - { - if (GetLogging()) - { - MCore::LogError(" + Failed to load motion set from file '%s'.", filename.c_str()); - } - } - else - { - if (GetLogging()) + motionSet->SetFilename(filename.c_str()); + if (settings) { - MCore::LogInfo(" + Loading successfully finished."); + motionSet->SetIsOwnedByRuntime(settings->m_isOwnedByRuntime); } } - - // return the result - return result; + return motionSet; } - MotionSet* Importer::LoadMotionSet(uint8* memoryStart, size_t lengthInBytes, MotionSetSettings* settings) { - // Legacy file type loading. - MCore::MemoryFile memFile; - memFile.Open(memoryStart, lengthInBytes); - - const bool isLegacyFile = Importer::CheckFileType(&memFile) == Importer::EFileType::FILETYPE_MOTIONSET; - if (isLegacyFile) - { - // Open the memory file again as CheckFileType() is closing it at the end. - memFile.Open(memoryStart, lengthInBytes); - EMotionFX::MotionSet* motionSet = LoadMotionSet(&memFile, settings); - if (settings) - { - motionSet->SetIsOwnedByRuntime(settings->m_isOwnedByRuntime); - } - return motionSet; - } - - AZ::SerializeContext* context = nullptr; AZ::ComponentApplicationBus::BroadcastResult(context, &AZ::ComponentApplicationBus::Events::GetSerializeContext); if (!context) @@ -734,58 +562,6 @@ namespace EMotionFX return motionSet; } - - // try to load a motion set from a file - MotionSet* Importer::LoadMotionSet(MCore::File* f, MotionSetSettings* settings) - { - MCORE_ASSERT(f); - MCORE_ASSERT(f->GetIsOpen()); - - // create the shared data - MCore::Array sharedData; - sharedData.SetMemoryCategory(EMFX_MEMCATEGORY_IMPORTER); - PrepareSharedData(sharedData); - - // load the file header - FileFormat::MotionSet_Header fileHeader; - f->Read(&fileHeader, sizeof(FileFormat::MotionSet_Header)); - if (fileHeader.mFourCC[0] != 'M' || fileHeader.mFourCC[1] != 'O' || fileHeader.mFourCC[2] != 'S' || fileHeader.mFourCC[3] != ' ') - { - MCore::LogError("The motion set file is not a valid file."); - f->Close(); - return nullptr; - } - - // get the endian type - MCore::Endian::EEndianType endianType = (MCore::Endian::EEndianType)fileHeader.mEndianType; - - // init the import parameters - ImportParameters params; - params.mSharedData = &sharedData; - params.mEndianType = endianType; - params.m_isOwnedByRuntime = settings ? settings->m_isOwnedByRuntime : false; - - // read the chunks - while (ProcessChunk(f, params)) - { - } - - // close the file and return a pointer to the actor we loaded - f->Close(); - - // get rid of shared data - ResetSharedData(sharedData); - sharedData.Clear(); - - // check if the motion set got set - if (params.mMotionSet == nullptr) - { - return nullptr; - } - - return params.mMotionSet; - } - //------------------------------------------------------------------------------------------------- // load a node map by filename @@ -1087,19 +863,6 @@ namespace EMotionFX RegisterChunkProcessor(aznew ChunkProcessorMotionMorphSubMotions()); RegisterChunkProcessor(aznew ChunkProcessorMotionData()); - // AnimGraph file format - RegisterChunkProcessor(aznew ChunkProcessorAnimGraphParameters()); - RegisterChunkProcessor(aznew ChunkProcessorAnimGraphNodeGroups()); - RegisterChunkProcessor(aznew ChunkProcessorAnimGraphNode()); - RegisterChunkProcessor(aznew ChunkProcessorAnimGraphStateTransitions()); - RegisterChunkProcessor(aznew ChunkProcessorAnimGraphNodeConnections()); - RegisterChunkProcessor(aznew ChunkProcessorAnimGraphGroupParameters()); - RegisterChunkProcessor(aznew ChunkProcessorAnimGraphGameControllerSettings()); - RegisterChunkProcessor(aznew ChunkProcessorAnimGraphAdditionalInfo()); - - // motion set file format - RegisterChunkProcessor(aznew ChunkProcessorMotionSet()); - // node map RegisterChunkProcessor(aznew ChunkProcessorNodeMap()); } @@ -1232,6 +995,18 @@ namespace EMotionFX return FILETYPE_UNKNOWN; } + AZStd::string fileExtension; + AZ::StringFunc::Path::GetExtension(filename, fileExtension); + + if (fileExtension == ".animgraph") + { + return FILETYPE_ANIMGRAPH; + } + if (fileExtension == ".motionset") + { + return FILETYPE_MOTIONSET; + } + // try to open the file from disk MCore::MemoryFile memoryFile; memoryFile.Open(); @@ -1272,14 +1047,6 @@ namespace EMotionFX return FILETYPE_MOTION; } - // check for motion set - file->Seek(0); - if (CheckIfIsValidMotionSetFile(file, &endianType)) - { - file->Close(); - return FILETYPE_MOTIONSET; - } - // check for node map file->Seek(0); if (CheckIfIsValidNodeMapFile(file, &endianType)) @@ -1288,14 +1055,6 @@ namespace EMotionFX return FILETYPE_NODEMAP; } - // check for anim graph - file->Seek(0); - if (CheckIfIsValidAnimGraphFile(file, &endianType)) - { - file->Close(); - return FILETYPE_ANIMGRAPH; - } - // close the file again file->Close(); @@ -1304,124 +1063,30 @@ namespace EMotionFX //--------------------------------------------------------- - - // load anim graph by filename - AnimGraph* Importer::LoadAnimGraph(AZStd::string filename, AnimGraphSettings* settings, const AZ::ObjectStream::FilterDescriptor& loadFilter) + AnimGraph* Importer::LoadAnimGraph(AZStd::string filename, const AZ::ObjectStream::FilterDescriptor& loadFilter) { EBUS_EVENT(AzFramework::ApplicationRequests::Bus, NormalizePathKeepCase, filename); - const bool isLegacyFile = Importer::CheckFileType(filename.c_str()) == Importer::EFileType::FILETYPE_ANIMGRAPH; - if (!isLegacyFile) - { - AZ::SerializeContext* context = nullptr; - AZ::ComponentApplicationBus::BroadcastResult(context, &AZ::ComponentApplicationBus::Events::GetSerializeContext); - if (!context) - { - AZ_Error("EMotionFX", false, "Can't get serialize context from component application."); - return nullptr; - } - - EMotionFX::AnimGraph* animGraph = EMotionFX::AnimGraph::LoadFromFile(filename, context, loadFilter); - if (animGraph) - { - animGraph->SetFileName(filename.c_str()); - animGraph->RemoveInvalidConnections(); // Remove connections that have nullptr source node's, which happens when connections point to unknown nodes. - } - - return animGraph; - } - - ////////////////////////////////////////// - // Legacy file type loading - ////////////////////////////////////////// - - // check if we want to load the anim graph even if a anim graph with the given filename is already inside the anim graph manager - if (settings == nullptr || settings->mForceLoading == false) - { - // search the anim graph inside the anim graph manager and return it if it already got loaded - AnimGraph* animGraph = GetAnimGraphManager().FindAnimGraphByFileName(filename.c_str()); - if (animGraph) - { - MCore::LogInfo(" + Anim graph '%s' already loaded, returning already loaded anim graph from the AnimGraphManager.", filename.c_str()); - return animGraph; - } - } - - if (GetLogging()) - { - MCore::LogInfo("- Trying to load anim graph from file '%s'...", filename.c_str()); - } - - // try to open the file from disk - MCore::DiskFile f; - if (!f.Open(filename.c_str(), MCore::DiskFile::READ)) + AZ::SerializeContext* context = nullptr; + AZ::ComponentApplicationBus::BroadcastResult(context, &AZ::ComponentApplicationBus::Events::GetSerializeContext); + if (!context) { - if (GetLogging()) - { - MCore::LogError(" + Failed to open the file for anim graph '%s', anim graph not loaded!", filename.c_str()); - } + AZ_Error("EMotionFX", false, "Can't get serialize context from component application."); return nullptr; } - // retrieve the filesize - const size_t fileSize = f.GetFileSize(); - - // create a temporary buffer for the file - uint8* fileBuffer = (uint8*)MCore::Allocate(fileSize, EMFX_MEMCATEGORY_IMPORTER); - - // read in the complete file - f.Read(fileBuffer, fileSize); - - // close the file again - f.Close(); - - // create the actor reading from memory - AnimGraph* result = LoadAnimGraph(fileBuffer, fileSize, settings); - if (result) - { - result->SetFileName(filename.c_str()); - result->RemoveInvalidConnections(); // Remove connections that have nullptr source node's, which happens when connections point to unknown nodes. - } - - // delete the filebuffer again - MCore::Free(fileBuffer); - - // check if it worked - if (result == nullptr) - { - if (GetLogging()) - { - MCore::LogError(" + Failed to load anim graph from file '%s'", filename.c_str()); - } - } - else + EMotionFX::AnimGraph* animGraph = EMotionFX::AnimGraph::LoadFromFile(filename, context, loadFilter); + if (animGraph) { - if (GetLogging()) - { - MCore::LogInfo(" + Loading successfully finished"); - } + animGraph->SetFileName(filename.c_str()); + animGraph->RemoveInvalidConnections(); // Remove connections that have nullptr source node's, which happens when connections point to unknown nodes. } - // return the result - return result; + return animGraph; } - - // load the anim graph from memory - AnimGraph* Importer::LoadAnimGraph(uint8* memoryStart, size_t lengthInBytes, AnimGraphSettings* settings) + AnimGraph* Importer::LoadAnimGraph(uint8* memoryStart, size_t lengthInBytes) { - // Legacy file type loading. - MCore::MemoryFile memFile; - memFile.Open(memoryStart, lengthInBytes); - - const bool isLegacyFile = Importer::CheckFileType(&memFile) == Importer::EFileType::FILETYPE_ANIMGRAPH; - if (isLegacyFile) - { - // Open the memory file again as CheckFileType() is closing it at the end. - memFile.Open(memoryStart, lengthInBytes); - return LoadAnimGraph(&memFile, settings); - } - AZ::SerializeContext* context = nullptr; AZ::ComponentApplicationBus::BroadcastResult(context, &AZ::ComponentApplicationBus::Events::GetSerializeContext); if (!context) @@ -1434,123 +1099,6 @@ namespace EMotionFX return animGraph; } - - // load a anim graph from a file object - AnimGraph* Importer::LoadAnimGraph(MCore::File* f, AnimGraphSettings* settings) - { - MCORE_ASSERT(f); - MCORE_ASSERT(f->GetIsOpen()); - - // execute the pre-passes - if (f->GetType() != MCore::MemoryFile::TYPE_ID) - { - MCore::LogError("Given file is not a memory file. Cannot process pre-passes."); - return nullptr; - } - - // copy over the actor settings, or use defaults - AnimGraphSettings animGraphSettings; - if (settings) - { - animGraphSettings = *settings; - } - - // create the shared data - MCore::Array sharedData; - sharedData.SetMemoryCategory(EMFX_MEMCATEGORY_IMPORTER); - PrepareSharedData(sharedData); - - //----------------------------------------------- - - // load the file header - FileFormat::AnimGraph_Header fileHeader; - f->Read(&fileHeader, sizeof(FileFormat::AnimGraph_Header)); - if (fileHeader.mFourCC[0] != 'A' || fileHeader.mFourCC[1] != 'N' || fileHeader.mFourCC[2] != 'G' || fileHeader.mFourCC[3] != 'R') - { - MCore::LogError("The anim graph file is not a valid anim graph file."); - f->Close(); - return nullptr; - } - - // get the endian type - MCore::Endian::EEndianType endianType = (MCore::Endian::EEndianType)fileHeader.mEndianType; - - // convert endian of the integer values - MCore::Endian::ConvertUnsignedInt32(&fileHeader.mFileVersion, endianType); - MCore::Endian::ConvertUnsignedInt32(&fileHeader.mNumNodes, endianType); - MCore::Endian::ConvertUnsignedInt32(&fileHeader.mNumStateTransitions, endianType); - MCore::Endian::ConvertUnsignedInt32(&fileHeader.mNumNodeConnections, endianType); - MCore::Endian::ConvertUnsignedInt32(&fileHeader.mNumParameters, endianType); - - // read the anim graph name, create it, and read the other remaining info strings - SharedHelperData::ReadString(f, &sharedData, endianType); - AnimGraph* animGraph = aznew AnimGraph(); - - if (GetLogDetails()) - { - MCore::LogDetailedInfo("Anim Graph:"); - - SharedHelperData::ReadString(f, &sharedData, endianType); // copyright - SharedHelperData::ReadString(f, &sharedData, endianType); // description - MCore::LogDetailedInfo(" + Company = %s", SharedHelperData::ReadString(f, &sharedData, endianType)); // company - MCore::LogDetailedInfo(" + EMotion FX Version= %s", SharedHelperData::ReadString(f, &sharedData, endianType)); // emfx version - MCore::LogDetailedInfo(" + EMStudio Build = %s", SharedHelperData::ReadString(f, &sharedData, endianType)); // emstudio build - MCore::LogDetailedInfo(" + Num nodes = %d", fileHeader.mNumNodes); - MCore::LogDetailedInfo(" + Num transitions = %d", fileHeader.mNumStateTransitions); - MCore::LogDetailedInfo(" + Num connections = %d", fileHeader.mNumNodeConnections); - MCore::LogDetailedInfo(" + Num parameters = %d", fileHeader.mNumParameters); - MCore::LogDetailedInfo(" + File version = %d", fileHeader.mFileVersion); - MCore::LogDetailedInfo(" + Endian type = %d", fileHeader.mEndianType); - } - else - { - SharedHelperData::ReadString(f, &sharedData, endianType); // copyright - SharedHelperData::ReadString(f, &sharedData, endianType); // description - SharedHelperData::ReadString(f, &sharedData, endianType); // company - SharedHelperData::ReadString(f, &sharedData, endianType); // emfx version - SharedHelperData::ReadString(f, &sharedData, endianType); // emstudio build - } - - // init the import parameters - ImportParameters params; - params.mSharedData = &sharedData; - params.mEndianType = endianType; - params.mAnimGraph = animGraph; - params.mAnimGraphSettings = &animGraphSettings; - - // pre-allocate the blend nodes array to prevent reallocs - MCore::Array& blendNodes = SharedHelperData::GetBlendNodes(params.mSharedData); - blendNodes.Reserve(fileHeader.mNumNodes); - - // process all chunks - while (ProcessChunk(f, params)) - { - } - - // close the file and return a pointer to the actor we loaded - f->Close(); - - // get rid of shared data - ResetSharedData(sharedData); - sharedData.Clear(); - - // recursively update attributes of all state machines and blend tree nodes - if (animGraph->GetRootStateMachine()) - { - animGraph->InitAfterLoading(); - animGraph->RemoveInvalidConnections(true); // Remove connections that have nullptr source node's, which happens when connections point to unknown nodes. - } - else - { - delete animGraph; - animGraph = nullptr; - } - - // return the created actor - return animGraph; - } - - // extract the file information from an actor file bool Importer::ExtractActorFileInfo(FileInfo* outInfo, const char* filename) const { diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/Importer.h b/Gems/EMotionFX/Code/EMotionFX/Source/Importer/Importer.h index 83121a405a..2b12f93a1a 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/Importer.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Importer/Importer.h @@ -108,18 +108,15 @@ namespace EMotionFX MCore::Array mChunkIDsToIgnore; /**< Add the ID's of the chunks you wish to ignore. */ }; - /** * The motion set import options. * This can be used in combination with the LoadMotionSet method. */ struct EMFX_API MotionSetSettings { - bool mForceLoading = false; /**< Set to true in case you want to load the motion set even if a motion set with the given filename is already inside the motion manager. */ bool m_isOwnedByRuntime = false; }; - /** * The node map import options. * This can be used in combination with the LoadNodeMap method. @@ -130,30 +127,15 @@ namespace EMotionFX bool mLoadNodes = true; /**< Add nodes to the map? (default=true) */ }; - - /** - * The anim graph import settings. - */ - struct EMFX_API AnimGraphSettings - { - bool mForceLoading = false; /**< Set to true in case you want to load the anim graph even if an anim graph with the given filename is already inside the anim graph manager. */ - bool mDisableNodeVisualization = true; /**< Force disabling of node visualization code execution inside the anim graph nodes? */ - }; - - struct EMFX_API ImportParameters { Actor* mActor = nullptr; Motion* mMotion = nullptr; - MotionSet* mMotionSet = nullptr; Importer::ActorSettings* mActorSettings = nullptr; Importer::MotionSettings* mMotionSettings = nullptr; MCore::Array* mSharedData = nullptr; MCore::Endian::EEndianType mEndianType = MCore::Endian::ENDIAN_LITTLE; - AnimGraph* mAnimGraph = nullptr; - Importer::AnimGraphSettings* mAnimGraphSettings = nullptr; - NodeMap* mNodeMap = nullptr; Importer::NodeMapSettings* mNodeMapSettings = nullptr; bool m_isOwnedByRuntime = false; @@ -250,43 +232,24 @@ namespace EMotionFX //------------------------------------------------------------------------------------------------- - /** - * Load a anim graph file from a given file object. - * @param f The file object. - * @param settings The importer settings, or nullptr to use default settings. - * @result The anim graph object, or nullptr when failed. - */ - AnimGraph* LoadAnimGraph(MCore::File* f, AnimGraphSettings* settings = nullptr); - /** * Load a anim graph file by filename. * @param filename The filename to load from. - * @param settings The anim graph importer settings, or nullptr to use default settings. * @param loadFilter The filter descriptor for loading anim graph from file * @result The anim graph object, or nullptr in case loading failed. */ - AnimGraph* LoadAnimGraph(AZStd::string, AnimGraphSettings* settings = nullptr, const AZ::ObjectStream::FilterDescriptor& loadFilter = AZ::ObjectStream::FilterDescriptor(nullptr, AZ::ObjectStream::FILTERFLAG_IGNORE_UNKNOWN_CLASSES)); + AnimGraph* LoadAnimGraph(AZStd::string, const AZ::ObjectStream::FilterDescriptor& loadFilter = AZ::ObjectStream::FilterDescriptor(nullptr, AZ::ObjectStream::FILTERFLAG_IGNORE_UNKNOWN_CLASSES)); /** * Load a anim graph file from a memory location. * @param memoryStart The start address of the file in memory. * @param lengthInBytes The length of the file, in bytes. - * @param settings The settings to use during loading, or nullptr when you want to use default settings, which would load everything. * @result The anim graph object, or nullptr in case loading failed. */ - AnimGraph* LoadAnimGraph(uint8* memoryStart, size_t lengthInBytes, AnimGraphSettings* settings = nullptr); + AnimGraph* LoadAnimGraph(uint8* memoryStart, size_t lengthInBytes); //------------------------------------------------------------------------------------------------- - /** - * Load a motion set from a given file. - * A file does not have to be stored on disk, but can also be in memory or in an archive or on some network stream. Anything is possible. - * @param f The file to load the motion set from (after load, the file will be closed). - * @param settings The motion set importer settings, or nullptr to use default settings. - * @result The motion set object, or nullptr in case loading failed. - */ - MotionSet* LoadMotionSet(MCore::File* f, MotionSetSettings* settings = nullptr); - /** * Loads a motion set from a file on disk. * @param filename The name of the file on disk. @@ -430,30 +393,6 @@ namespace EMotionFX */ bool CheckIfIsValidMotionFile(MCore::File* f, MCore::Endian::EEndianType* outEndianType) const; - /** - * Verify if the given file is a valid motion set file that can be processed by the importer. - * Please note that the specified must already been opened and must also be pointing to the location where the - * XPM file header will be stored (the start of the file). The file will not be closed after this method! - * The endian type of the file will be written inside the outEndianType parameter. - * Also note that the file position (read position / cursor) will point after the header after this function has been executed. - * @param f The file to perform the check on. - * @param outEndianType The value that will contain the endian type used by the file. - * @result Returns true when the file is a valid actor file that can be processed by the importer. Otherwise false is returned. - */ - bool CheckIfIsValidMotionSetFile(MCore::File* f, MCore::Endian::EEndianType* outEndianType) const; - - /** - * Verify if the given file is a valid anim graph file that can be processed by the importer. - * Please note that the specified must already been opened and must also be pointing to the location where the - * XPM file header will be stored (the start of the file). The file will not be closed after this method! - * The endian type of the file will be written inside the outEndianType parameter. - * Also note that the file position (read position / cursor) will point after the header after this function has been executed. - * @param f The file to perform the check on. - * @param outEndianType The value that will contain the endian type used by the file. - * @result Returns true when the file is a valid actor file that can be processed by the importer. Otherwise false is returned. - */ - bool CheckIfIsValidAnimGraphFile(MCore::File* f, MCore::Endian::EEndianType* outEndianType) const; - /** * Verify if the given file is a valid node map file that can be processed by the importer. * Please note that the specified must already been opened and must also be pointing to the location where the From ff2649d0c8ef0db3ea1bd75b2585ae9b0bc9aec9 Mon Sep 17 00:00:00 2001 From: Benjamin Jillich Date: Mon, 26 Jul 2021 09:59:19 +0200 Subject: [PATCH 034/160] Adapted loading calls to removed legacy file loading Signed-off-by: Benjamin Jillich --- Gems/EMotionFX/Code/CMakeLists.txt | 2 -- .../EMotionFX/CommandSystem/Source/AnimGraphCommands.cpp | 4 +--- .../Pipeline/EMotionFXBuilder/AnimGraphBuilderWorker.cpp | 2 +- Gems/EMotionFX/Code/EMotionFX/emotionfx_files.cmake | 5 ----- .../Code/Source/Integration/Assets/AnimGraphAsset.cpp | 3 +-- 5 files changed, 3 insertions(+), 13 deletions(-) diff --git a/Gems/EMotionFX/Code/CMakeLists.txt b/Gems/EMotionFX/Code/CMakeLists.txt index 5c38faf2a6..ed5447ba25 100644 --- a/Gems/EMotionFX/Code/CMakeLists.txt +++ b/Gems/EMotionFX/Code/CMakeLists.txt @@ -219,8 +219,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) ${CMAKE_CURRENT_SOURCE_DIR}/Tests/TestAssets/EMotionFXBuilderTestAssets/AnimGraphExampleNoDependency.animgraph ${CMAKE_CURRENT_SOURCE_DIR}/Tests/TestAssets/EMotionFXBuilderTestAssets/EmptyAnimGraphExample.animgraph ${CMAKE_CURRENT_SOURCE_DIR}/Tests/TestAssets/EMotionFXBuilderTestAssets/EmptyMotionSetExample.motionset - ${CMAKE_CURRENT_SOURCE_DIR}/Tests/TestAssets/EMotionFXBuilderTestAssets/LegacyAnimGraphExample.animgraph - ${CMAKE_CURRENT_SOURCE_DIR}/Tests/TestAssets/EMotionFXBuilderTestAssets/LegacyMotionSetExample.motionset ${CMAKE_CURRENT_SOURCE_DIR}/Tests/TestAssets/EMotionFXBuilderTestAssets/MotionSetExample.motionset ${CMAKE_CURRENT_SOURCE_DIR}/Tests/TestAssets/EMotionFXBuilderTestAssets/MotionSetExampleNoDependency.motionset OUTPUT_SUBDIRECTORY diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphCommands.cpp b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphCommands.cpp index a04f6a327d..fdc4e4d0e5 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphCommands.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphCommands.cpp @@ -93,9 +93,7 @@ namespace CommandSystem } // load anim graph from file - EMotionFX::Importer::AnimGraphSettings settings; - settings.mDisableNodeVisualization = false; - EMotionFX::AnimGraph* animGraph = EMotionFX::GetImporter().LoadAnimGraph(filename.c_str(), &settings); + EMotionFX::AnimGraph* animGraph = EMotionFX::GetImporter().LoadAnimGraph(filename.c_str()); if (!animGraph) { outResult = AZStd::string::format("Failed to load anim graph from %s.", filename.c_str()); diff --git a/Gems/EMotionFX/Code/EMotionFX/Pipeline/EMotionFXBuilder/AnimGraphBuilderWorker.cpp b/Gems/EMotionFX/Code/EMotionFX/Pipeline/EMotionFXBuilder/AnimGraphBuilderWorker.cpp index 927ba67b76..cd81d81170 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Pipeline/EMotionFXBuilder/AnimGraphBuilderWorker.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Pipeline/EMotionFXBuilder/AnimGraphBuilderWorker.cpp @@ -97,7 +97,7 @@ namespace EMotionFX AZ_UNUSED(sourceFile); AZ::ObjectStream::FilterDescriptor loadFilter = AZ::ObjectStream::FilterDescriptor(&AZ::Data::AssetFilterNoAssetLoading, AZ::ObjectStream::FILTERFLAG_IGNORE_UNKNOWN_CLASSES); - AZStd::unique_ptr animGraph(GetImporter().LoadAnimGraph(fullPath, nullptr, loadFilter)); + AZStd::unique_ptr animGraph(GetImporter().LoadAnimGraph(fullPath, loadFilter)); if (!animGraph) { diff --git a/Gems/EMotionFX/Code/EMotionFX/emotionfx_files.cmake b/Gems/EMotionFX/Code/EMotionFX/emotionfx_files.cmake index 7942a5525f..b12cbe102f 100644 --- a/Gems/EMotionFX/Code/EMotionFX/emotionfx_files.cmake +++ b/Gems/EMotionFX/Code/EMotionFX/emotionfx_files.cmake @@ -364,16 +364,11 @@ set(FILES Source/TwoStringEventData.h Source/Importer/ChunkProcessors.cpp Source/Importer/ChunkProcessors.h - Source/Importer/LegacyAnimGraphNodeParser.cpp - Source/Importer/LegacyAnimGraphNodeParser.h Source/Importer/Importer.cpp Source/Importer/Importer.h - Source/Importer/MotionSetFileFormat.h Source/Importer/NodeMapFileFormat.h Source/Importer/SharedFileFormatStructs.h Source/Importer/ActorFileFormat.h - Source/Importer/AnimGraphFileFormat.cpp - Source/Importer/AnimGraphFileFormat.h Source/Importer/MotionFileFormat.h Source/Parameter/BoolParameter.cpp Source/Parameter/BoolParameter.h diff --git a/Gems/EMotionFX/Code/Source/Integration/Assets/AnimGraphAsset.cpp b/Gems/EMotionFX/Code/Source/Integration/Assets/AnimGraphAsset.cpp index d3e39840ab..3e459d31d6 100644 --- a/Gems/EMotionFX/Code/Source/Integration/Assets/AnimGraphAsset.cpp +++ b/Gems/EMotionFX/Code/Source/Integration/Assets/AnimGraphAsset.cpp @@ -53,8 +53,7 @@ namespace EMotionFX AnimGraphAsset* assetData = asset.GetAs(); assetData->m_emfxAnimGraph.reset(EMotionFX::GetImporter().LoadAnimGraph( assetData->m_emfxNativeData.data(), - assetData->m_emfxNativeData.size(), - nullptr)); + assetData->m_emfxNativeData.size())); if (assetData->m_emfxAnimGraph) { From 96aa9fde0638f8dccdeae8e705d25d8436365eab Mon Sep 17 00:00:00 2001 From: Benjamin Jillich Date: Mon, 26 Jul 2021 10:00:07 +0200 Subject: [PATCH 035/160] Removed legacy loading automated tests and ported file format for anim graph for remaining automated tests Signed-off-by: Benjamin Jillich --- .../Code/Tests/EMotionFXBuilderTests.cpp | 20 ------------------- .../LegacyAnimGraphExample.animgraph | 3 --- .../LegacyMotionSetExample.motionset | 3 --- .../Code/Tests/TestAssets/Rin/rin.animgraph | 4 ++-- 4 files changed, 2 insertions(+), 28 deletions(-) delete mode 100644 Gems/EMotionFX/Code/Tests/TestAssets/EMotionFXBuilderTestAssets/LegacyAnimGraphExample.animgraph delete mode 100644 Gems/EMotionFX/Code/Tests/TestAssets/EMotionFXBuilderTestAssets/LegacyMotionSetExample.motionset diff --git a/Gems/EMotionFX/Code/Tests/EMotionFXBuilderTests.cpp b/Gems/EMotionFX/Code/Tests/EMotionFXBuilderTests.cpp index 3e63af8d63..acdd78fc0f 100644 --- a/Gems/EMotionFX/Code/Tests/EMotionFXBuilderTests.cpp +++ b/Gems/EMotionFX/Code/Tests/EMotionFXBuilderTests.cpp @@ -97,16 +97,6 @@ namespace EMotionFX ASSERT_EQ(productDependencies.size(), 0); } - TEST_F(EMotionFXBuilderTests, TestLegacyAnimGraphAsset_NoDependency_OutputNoProductDependencies) - { - const AZStd::string fileName = "@devroot@/Gems/EMotionFX/Code/Tests/TestAssets/EMotionFXBuilderTestAssets/LegacyAnimGraphExample.animgraph"; - AZStd::vector productDependencies; - EMotionFXBuilder::AnimGraphBuilderWorker builderWorker; - - ASSERT_TRUE(builderWorker.ParseProductDependencies(ResolvePath(fileName.c_str()), fileName, productDependencies)); - ASSERT_EQ(productDependencies.size(), 0); - } - TEST_F(EMotionFXBuilderTests, TestMotionSetAsset_HasReferenceNode_OutputProductDependencies) { const AZStd::string fileName = "@devroot@/Gems/EMotionFX/Code/Tests/TestAssets/EMotionFXBuilderTestAssets/MotionSetExample.motionset"; @@ -150,14 +140,4 @@ namespace EMotionFX AZ_TEST_STOP_ASSERTTEST(2); ASSERT_EQ(productDependencies.size(), 0); } - - TEST_F(EMotionFXBuilderTests, TestLegacyMotionSetAsset_ReferenceMotionAssets_OutputProductDependencies) - { - const AZStd::string fileName = "@devroot@/Gems/EMotionFX/Code/Tests/TestAssets/EMotionFXBuilderTestAssets/LegacyMotionSetExample.motionset"; - ProductPathDependencySet productDependencies; - EMotionFXBuilder::MotionSetBuilderWorker builderWorker; - - ASSERT_TRUE(builderWorker.ParseProductDependencies(ResolvePath(fileName.c_str()), fileName, productDependencies)); - ASSERT_EQ(productDependencies.size(), 25); - } } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/Tests/TestAssets/EMotionFXBuilderTestAssets/LegacyAnimGraphExample.animgraph b/Gems/EMotionFX/Code/Tests/TestAssets/EMotionFXBuilderTestAssets/LegacyAnimGraphExample.animgraph deleted file mode 100644 index 5138720283..0000000000 --- a/Gems/EMotionFX/Code/Tests/TestAssets/EMotionFXBuilderTestAssets/LegacyAnimGraphExample.animgraph +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:33ff8a4f75b5ad918a833113fb45a21e9075b66a9d0ed8563ee34d93ae905aaf -size 50863 diff --git a/Gems/EMotionFX/Code/Tests/TestAssets/EMotionFXBuilderTestAssets/LegacyMotionSetExample.motionset b/Gems/EMotionFX/Code/Tests/TestAssets/EMotionFXBuilderTestAssets/LegacyMotionSetExample.motionset deleted file mode 100644 index e5339745ca..0000000000 --- a/Gems/EMotionFX/Code/Tests/TestAssets/EMotionFXBuilderTestAssets/LegacyMotionSetExample.motionset +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8ed5c6c8376df150ebddc8b16714012991c1892a94d2b8ad943a7f96563771e0 -size 2518 diff --git a/Gems/EMotionFX/Code/Tests/TestAssets/Rin/rin.animgraph b/Gems/EMotionFX/Code/Tests/TestAssets/Rin/rin.animgraph index 5138720283..ac370ff38d 100644 --- a/Gems/EMotionFX/Code/Tests/TestAssets/Rin/rin.animgraph +++ b/Gems/EMotionFX/Code/Tests/TestAssets/Rin/rin.animgraph @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:33ff8a4f75b5ad918a833113fb45a21e9075b66a9d0ed8563ee34d93ae905aaf -size 50863 +oid sha256:8825feb4f0946979f8a1258cdf20bb71e358b7597eca1aaed552c2b0a17b2bd9 +size 464733 From 78b07a0869563e48cf04d258de5ddf3ac959fe65 Mon Sep 17 00:00:00 2001 From: Dayo Lawal Date: Mon, 26 Jul 2021 12:51:07 -0500 Subject: [PATCH 036/160] Fixing errors and streamlining more to base class Signed-off-by: Dayo Lawal --- .../Application/AtomToolsApplication.h | 22 ++- .../Application/AtomToolsApplication.cpp | 135 ++++++++----- .../Code/Source/MaterialEditorApplication.cpp | 185 +++--------------- .../Code/Source/MaterialEditorApplication.h | 38 +--- .../ShaderManagementConsoleApplication.cpp | 112 ++--------- .../ShaderManagementConsoleApplication.h | 30 +-- 6 files changed, 143 insertions(+), 379 deletions(-) diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h index 8d3c09385c..73ba062328 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h @@ -1,3 +1,10 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + #pragma once #include @@ -25,11 +32,10 @@ namespace AtomToolsFramework , protected AzToolsFramework::AssetDatabase::AssetDatabaseRequestsBus::Handler , protected AzFramework::AssetSystemStatusBus::Handler , protected AzToolsFramework::EditorPythonConsoleNotificationBus::Handler - , protected AZ::Debug::TraceMessageBus::Handler , protected AZ::UserSettingsOwnerRequestBus::Handler { public: - AZ_TYPE_INFO(AtomTools::AtomToolsApplication, "{30F90CA5-1253-49B5-8143-19CEE37E22BB}"); + AZ_TYPE_INFO(AtomTools::AtomToolsApplication, "{A0DF25BA-6F74-4F11-9F85-0F99278D5986}"); using Base = AzFramework::Application; @@ -68,14 +74,24 @@ namespace AtomToolsFramework void SaveSettings() override; ////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////// + // EditorPythonConsoleNotificationBus::Handler overrides... + void OnTraceMessage(AZStd::string_view message) override; + void OnErrorMessage(AZStd::string_view message) override; + void OnExceptionMessage(AZStd::string_view message) override; + //////////////////////////////////////////////////////////////////////// + virtual void LoadSettings(); virtual void UnloadSettings(); - virtual void CompileCriticalAssets(); + virtual void CompileCriticalAssets(const AZStd::vector &assetFiltersArray); virtual void ProcessCommandLine(const AZ::CommandLine& commandLine); virtual bool LaunchDiscoveryService(); virtual void StartInternal(); static void PyIdleWaitFrames(uint32_t frames); + void setTargetName(AZStd::string newTargetName); + + AZStd::string targetName = "AtomTools"; AzToolsFramework::TraceLogger m_traceLogger; diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp index 464480ec53..93ea6ca499 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp @@ -1,12 +1,18 @@ /* - * 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. + * Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution. * * SPDX-License-Identifier: Apache-2.0 OR MIT * */ +#include +#include + +#include +#include + #include +#include #include #include #include @@ -26,15 +32,6 @@ #include #include -#include - -#include -#include - -#include - -#include - AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT #include #include @@ -42,15 +39,6 @@ AZ_POP_DISABLE_WARNING namespace AtomToolsFramework { - //! This function returns the build system target name of "AtomTools -// AZStd::string_view GetBuildTargetName() -// { -//#if !defined(LY_CMAKE_TARGET) -//#error "LY_CMAKE_TARGET must be defined in order to add this source file to a CMake executable target" -//#endif -// return AZStd::string_view{ LY_CMAKE_TARGET }; -// } - const char* AtomToolsApplication::GetCurrentConfigurationName() const { #if defined(_RELEASE) @@ -62,7 +50,6 @@ namespace AtomToolsFramework #endif } - AtomToolsApplication::AtomToolsApplication(int* argc, char*** argv) : Application(argc, argv) , AzQtApplication(*argc, *argv) @@ -152,22 +139,14 @@ namespace AtomToolsFramework { AzToolsFramework::EditorPythonConsoleNotificationBus::Handler::BusDisconnect(); AzToolsFramework::AssetDatabase::AssetDatabaseRequestsBus::Handler::BusDisconnect(); - AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::StartDisconnectingAssetProcessor); Application::Destroy(); } - void AtomToolsApplication::CompileCriticalAssets() + void AtomToolsApplication::CompileCriticalAssets(const AZStd::vector &assetFiltersArray) { - AZ_TracePrintf("AtomTools", "Compiling critical assets.\n"); - - // List of common asset filters for things that need to be compiled to run the material editor - // Some of these things will not be necessary once we have proper support for queued asset loading and reloading - const AZStd::string assetFiltersArray[] = { - "passes/", - "config/", - }; + AZ_TracePrintf(targetName.c_str(), "Compiling critical assets.\n"); QStringList failedAssets; @@ -208,13 +187,14 @@ namespace AtomToolsFramework AZ_Assert(context, "No serialize context"); char resolvedPath[AZ_MAX_PATH_LEN] = ""; + AZStd::string fileName = "@user@/" + targetName + "UserSettings.xml"; + AZ::IO::FileIOBase::GetInstance()->ResolvePath( - "@user@/MaterialEditorUserSettings.xml", resolvedPath, AZ_ARRAY_SIZE(resolvedPath)); + fileName.c_str(), resolvedPath, AZ_ARRAY_SIZE(resolvedPath)); m_localUserSettings.Save(resolvedPath, context); } } - void AtomToolsApplication::LoadSettings() { AZ::SerializeContext* context = nullptr; @@ -222,7 +202,9 @@ namespace AtomToolsFramework AZ_Assert(context, "No serialize context"); char resolvedPath[AZ_MAX_PATH_LEN] = ""; - AZ::IO::FileIOBase::GetInstance()->ResolvePath("@user@/EditorUserSettings.xml", resolvedPath, AZ_MAX_PATH_LEN); + AZStd::string fileName = "@user@/" + targetName + "UserSettings.xml"; + + AZ::IO::FileIOBase::GetInstance()->ResolvePath(fileName.c_str(), resolvedPath, AZ_MAX_PATH_LEN); m_localUserSettings.Load(resolvedPath, context); m_localUserSettings.Activate(AZ::UserSettings::CT_LOCAL); @@ -234,7 +216,7 @@ namespace AtomToolsFramework { if (m_activatedLocalUserSettings) { - //SaveSettings(); + SaveSettings(); m_localUserSettings.Deactivate(); AZ::UserSettingsOwnerRequestBus::Handler::BusDisconnect(); m_activatedLocalUserSettings = false; @@ -243,6 +225,34 @@ namespace AtomToolsFramework void AtomToolsApplication::ProcessCommandLine(const AZ::CommandLine& commandLine) { + const AZStd::string timeoputSwitchName = "timeout"; + if (commandLine.HasSwitch(timeoputSwitchName)) + { + const AZStd::string& timeoutValue = commandLine.GetSwitchValue(timeoputSwitchName, 0); + const uint32_t timeoutInMs = atoi(timeoutValue.c_str()); + AZ_Printf(targetName.c_str(), "Timeout scheduled, shutting down in %u ms", timeoutInMs); + QTimer::singleShot( + timeoutInMs, + [this] + { + AZ_Printf(targetName.c_str(), "Timeout reached, shutting down"); + ExitMainLoop(); + }); + } + + // Process command line options for running one or more python scripts on startup + const AZStd::string runPythonScriptSwitchName = "runpython"; + size_t runPythonScriptCount = commandLine.GetNumSwitchValues(runPythonScriptSwitchName); + for (size_t runPythonScriptIndex = 0; runPythonScriptIndex < runPythonScriptCount; ++runPythonScriptIndex) + { + const AZStd::string runPythonScriptPath = commandLine.GetSwitchValue(runPythonScriptSwitchName, runPythonScriptIndex); + AZStd::vector runPythonArgs; + + AZ_Printf(targetName.c_str(), "Launching script: %s", runPythonScriptPath.c_str()); + AzToolsFramework::EditorPythonRunnerRequestBus::Broadcast( + &AzToolsFramework::EditorPythonRunnerRequestBus::Events::ExecuteByFilenameWithArgs, runPythonScriptPath, runPythonArgs); + } + const AZStd::string exitAfterCommandsSwitchName = "exitaftercommands"; if (commandLine.HasSwitch(exitAfterCommandsSwitchName)) { @@ -313,7 +323,9 @@ namespace AtomToolsFramework return; } - m_traceLogger.WriteStartupLog("AtomTools.log"); + AZStd::string fileName = targetName + ".log"; + + m_traceLogger.WriteStartupLog(fileName.c_str()); if (!LaunchDiscoveryService()) { @@ -330,23 +342,6 @@ namespace AtomToolsFramework AZ::RPI::RPISystemInterface::Get()->InitializeSystemAssets(); LoadSettings(); - - auto editorPythonEventsInterface = AZ::Interface::Get(); - if (editorPythonEventsInterface) - { - // The PythonSystemComponent does not call StartPython to allow for lazy python initialization, so start it here - // The PythonSystemComponent will call StopPython when it deactivates, so we do not need our own corresponding call to - // StopPython - editorPythonEventsInterface->StartPython(); - } - - // Delay execution of commands and scripts post initialization - QTimer::singleShot( - 0, - [this]() - { - ProcessCommandLine(m_commandLine); - }); } bool AtomToolsApplication::GetAssetDatabaseLocation(AZStd::string& result) @@ -387,6 +382,34 @@ namespace AtomToolsFramework appType.m_maskValue = AZ::ApplicationTypeQuery::Masks::Game; } + void AtomToolsApplication::OnTraceMessage([[maybe_unused]] AZStd::string_view message) + { +#if defined(AZ_ENABLE_TRACING) + AZStd::vector lines; + AzFramework::StringFunc::Tokenize( + message, lines, "\n", + false, // Keep empty strings + false // Keep space strings + ); + + for (auto& line : lines) + { + AZ_TracePrintf(targetName.c_str(), "Python: %s\n", line.c_str()); + } +#endif + } + + void AtomToolsApplication::OnErrorMessage(AZStd::string_view message) + { + // Use AZ_TracePrintf instead of AZ_Error or AZ_Warning to avoid all the metadata noise + OnTraceMessage(message); + } + + void AtomToolsApplication::OnExceptionMessage([[maybe_unused]] AZStd::string_view message) + { + AZ_Error(targetName.c_str(), false, "Python: " AZ_STRING_FORMAT, AZ_STRING_ARG(message)); + } + // Copied from PyIdleWaitFrames in CryEdit.cpp void AtomToolsApplication::PyIdleWaitFrames(uint32_t frames) { @@ -421,5 +444,9 @@ namespace AtomToolsFramework Ticker ticker(&loop, frames); loop.exec(); } - + + void AtomToolsApplication::setTargetName(AZStd::string newTargetName) + { + targetName = newTargetName; + } } // namespace AtomToolsFramework diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp index 4b233b0212..5e08b1e8ba 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp @@ -5,7 +5,22 @@ * */ +#include + +#include +#include + +#include +#include + +#include + +#include +#include +#include + #include +#include #include #include #include @@ -25,24 +40,9 @@ #include #include -#include - -#include -#include - #include #include -#include -#include - -#include - -#include -#include -#include -#include - AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT #include #include @@ -75,6 +75,7 @@ namespace MaterialEditor { QApplication::setApplicationName("O3DE Material Editor"); + setTargetName("MaterialEditor"); AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddBuildSystemTargetSpecialization( *AZ::SettingsRegistry::Get(), GetBuildTargetName()); @@ -95,8 +96,7 @@ namespace MaterialEditor void MaterialEditorApplication::CreateStaticModules(AZStd::vector& outModules) { - Application::CreateStaticModules(outModules); - outModules.push_back(aznew AzToolsFramework::AzToolsFrameworkModule); + Base::CreateStaticModules(outModules); outModules.push_back(aznew MaterialDocumentModule); outModules.push_back(aznew MaterialViewportModule); outModules.push_back(aznew MaterialEditorWindowModule); @@ -108,14 +108,7 @@ namespace MaterialEditor //[GFX TODO][ATOM-408] This needs to be updated in some way to support the MaterialViewport render widget } - AzFramework::AssetSystemStatusBus::Handler::BusConnect(); - AzToolsFramework::EditorPythonConsoleNotificationBus::Handler::BusConnect(); - - AzFramework::Application::StartCommon(systemEntity); - - StartInternal(); - - m_timer.start(); + Base::StartCommon(systemEntity); } void MaterialEditorApplication::OnMaterialEditorWindowClosing() @@ -129,16 +122,9 @@ namespace MaterialEditor MaterialEditor::MaterialEditorWindowFactoryRequestBus::Broadcast( &MaterialEditor::MaterialEditorWindowFactoryRequestBus::Handler::DestroyMaterialEditorWindow); - AzToolsFramework::EditorPythonConsoleNotificationBus::Handler::BusDisconnect(); - AzToolsFramework::AssetDatabase::AssetDatabaseRequestsBus::Handler::BusDisconnect(); MaterialEditorWindowNotificationBus::Handler::BusDisconnect(); - AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); - m_logFile = {}; - m_startupLogSink = {}; - - AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::StartDisconnectingAssetProcessor); - Application::Destroy(); + Base::Destroy(); } void MaterialEditorApplication::AssetSystemAvailable() @@ -160,75 +146,17 @@ namespace MaterialEditor }; AzFramework::AssetSystemRequestBus::BroadcastResult(connectedToAssetProcessor, &AzFramework::AssetSystemRequestBus::Events::EstablishAssetProcessorConnection, connectionSettings); - if (connectedToAssetProcessor) - { - CompileCriticalAssets(); - } - - AzFramework::AssetSystemStatusBus::Handler::BusDisconnect(); - } - - - void MaterialEditorApplication::CompileCriticalAssets() - { - AZ_TracePrintf("MaterialEditor", "Compiling critical assets.\n"); // List of common asset filters for things that need to be compiled to run the material editor // Some of these things will not be necessary once we have proper support for queued asset loading and reloading - const AZStd::string assetFiltersArray[] = - { - "passes/", - "config/", - "MaterialEditor/", - }; - - QStringList failedAssets; - - // Forced asset processor to synchronously process all critical assets - // Note: with AssetManager's current implementation, a compiled asset won't be added in asset registry until next system tick. - // So the asset id won't be found right after CompileAssetSync call. - for (const AZStd::string& assetFilters : assetFiltersArray) - { - AZ_TracePrintf("MaterialEditor", "Compiling critical asset matching: %s.\n", assetFilters.c_str()); - - // Wait for the asset be compiled - AzFramework::AssetSystem::AssetStatus status = AzFramework::AssetSystem::AssetStatus_Unknown; - AzFramework::AssetSystemRequestBus::BroadcastResult( - status, &AzFramework::AssetSystemRequestBus::Events::CompileAssetSync, assetFilters); - if (status != AzFramework::AssetSystem::AssetStatus_Compiled) - { - failedAssets.append(assetFilters.c_str()); - } - } - - if (!failedAssets.empty()) - { - QMessageBox::critical(activeWindow(), - QString("Failed to compile critical assets"), - QString("Failed to compile the following critical assets:\n%1\n%2") - .arg(failedAssets.join(",\n")) - .arg("Make sure this is an Atom project.")); - ExitMainLoop(); - } - } + const AZStd::vector assetFiltersArray = { "passes/", "config/", "MaterialEditor/" }; - bool MaterialEditorApplication::OnOutput(const char* window, const char* message) - { - // Suppress spam from the Source Control system - if (0 == strncmp(window, AzToolsFramework::SCC_WINDOW, AZ_ARRAY_SIZE(AzToolsFramework::SCC_WINDOW))) + if (connectedToAssetProcessor) { - return true; + CompileCriticalAssets(assetFiltersArray); } - if (m_logFile) - { - m_logFile->AppendLog(AzFramework::LogFile::SEV_NORMAL, window, message); - } - else - { - m_startupLogSink.push_back({ window, message }); - } - return false; + AzFramework::AssetSystemStatusBus::Handler::BusDisconnect(); } void MaterialEditorApplication::ProcessCommandLine(const AZ::CommandLine& commandLine) @@ -286,27 +214,7 @@ namespace MaterialEditor void MaterialEditorApplication::StartInternal() { - if (WasExitMainLoopRequested()) - { - return; - } - - m_traceLogger.WriteStartupLog("MaterialEditor.log"); - - if (!LaunchDiscoveryService()) - { - ExitMainLoop(); - return; - } - - AzToolsFramework::AssetDatabase::AssetDatabaseRequestsBus::Handler::BusConnect(); - AzToolsFramework::AssetBrowser::AssetDatabaseLocationNotificationBus::Broadcast(&AzToolsFramework::AssetBrowser::AssetDatabaseLocationNotifications::OnDatabaseInitialized); - - AZ::Data::AssetCatalogRequestBus::Broadcast(&AZ::Data::AssetCatalogRequestBus::Events::LoadCatalog, "@assets@/assetcatalog.xml"); - - AZ::RPI::RPISystemInterface::Get()->InitializeSystemAssets(); - - LoadSettings(); + Base::StartInternal(); MaterialEditorWindowNotificationBus::Handler::BusConnect(); @@ -325,54 +233,11 @@ namespace MaterialEditor QTimer::singleShot(0, [this]() { ProcessCommandLine(m_commandLine); }); } - void MaterialEditorApplication::Tick(float deltaOverride) - { - TickSystem(); - Application::Tick(deltaOverride); - - if (WasExitMainLoopRequested()) - { - m_timer.disconnect(); - quit(); - } - } - void MaterialEditorApplication::Stop() { MaterialEditor::MaterialEditorWindowFactoryRequestBus::Broadcast( &MaterialEditor::MaterialEditorWindowFactoryRequestBus::Handler::DestroyMaterialEditorWindow); - UnloadSettings(); - AzFramework::Application::Stop(); - } - - void MaterialEditorApplication::OnTraceMessage([[maybe_unused]] AZStd::string_view message) - { -#if defined(AZ_ENABLE_TRACING) - AZStd::vector lines; - AzFramework::StringFunc::Tokenize( - message, - lines, - "\n", - false, // Keep empty strings - false // Keep space strings - ); - - for (auto& line : lines) - { - AZ_TracePrintf("MaterialEditor", "Python: %s\n", line.c_str()); - } -#endif - } - - void MaterialEditorApplication::OnErrorMessage(AZStd::string_view message) - { - // Use AZ_TracePrintf instead of AZ_Error or AZ_Warning to avoid all the metadata noise - OnTraceMessage(message); - } - - void MaterialEditorApplication::OnExceptionMessage([[maybe_unused]] AZStd::string_view message) - { - AZ_Error("MaterialEditor", false, "Python: " AZ_STRING_FORMAT, AZ_STRING_ARG(message)); + Base::Stop(); } } // namespace MaterialEditor diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h index d398f4406d..92f4223f99 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h @@ -9,19 +9,6 @@ #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include #include @@ -47,7 +34,6 @@ namespace MaterialEditor void CreateStaticModules(AZStd::vector& outModules) override; const char* GetCurrentConfigurationName() const override; void StartCommon(AZ::Entity* systemEntity) override; - void Tick(float deltaOverride = -1.f) override; void Stop() override; private: @@ -61,34 +47,12 @@ namespace MaterialEditor void Destroy() override; ////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////// - // EditorPythonConsoleNotificationBus::Handler overrides... - void OnTraceMessage(AZStd::string_view message) override; - void OnErrorMessage(AZStd::string_view message) override; - void OnExceptionMessage(AZStd::string_view message) override; - //////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////// // AzFramework::AssetSystemStatusBus::Handler overrides... void AssetSystemAvailable() override; ////////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////// - // AZ::Debug::TraceMessageBus::Handler overrides... - bool OnOutput(const char* window, const char* message) override; - ////////////////////////////////////////////////////////////////////////// - - void CompileCriticalAssets() override; void ProcessCommandLine(const AZ::CommandLine& commandLine) override; void StartInternal() override; - - struct LogMessage - { - AZStd::string window; - AZStd::string message; - }; - - AZStd::vector m_startupLogSink; - AZStd::unique_ptr m_logFile; - }; + }; } // namespace MaterialEditor diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp index 4a3f5dd02d..2ad61b9e3f 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp @@ -70,6 +70,7 @@ namespace ShaderManagementConsole : AtomToolsApplication(argc, argv) { QApplication::setApplicationName("O3DE Shader Management Console"); + setTargetName("ShaderManagementConsole"); // The settings registry has been created at this point, so add the CMake target AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddBuildSystemTargetSpecialization( @@ -98,7 +99,6 @@ namespace ShaderManagementConsole ShaderManagementConsoleWindowNotificationBus::Handler::BusDisconnect(); AzToolsFramework::AssetDatabase::AssetDatabaseRequestsBus::Handler::BusDisconnect(); - AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::StartDisconnectingAssetProcessor); @@ -129,66 +129,28 @@ namespace ShaderManagementConsole }; AzFramework::AssetSystemRequestBus::Broadcast(ConnectToAssetProcessorWithIdentifier); - if (connected) - { - CompileCriticalAssets(); - } - - AzFramework::AssetSystemStatusBus::Handler::BusDisconnect(); - } - - void ShaderManagementConsoleApplication::CompileCriticalAssets() - { - AZ_TracePrintf("Shader Management Console", "Compiling critical assets.\n"); - - // List of common asset filters for things that need to be compiled to run + // List of common asset filters for things that need to be compiled to run the material editor // Some of these things will not be necessary once we have proper support for queued asset loading and reloading - const AZStd::string assetFilterss[] = - { - "passes/", - "config/", - }; + const AZStd::vector assetFiltersArray = { "passes/", "config/"}; - QStringList failedAssets; - - // Forced asset processor to synchronously process all critical assets - // Note: with AssetManager's current implementation, a compiled asset won't be added in asset registry until next system tick. - // So the asset id won't be found right after CompileAssetSync call. - for (const AZStd::string& assetFilters : assetFilterss) + if (connected) { - AZ_TracePrintf("Shader Management Console", "Compiling critical asset matching: %s.\n", assetFilters.c_str()); - - // Wait for the asset be compiled - AzFramework::AssetSystem::AssetStatus status = AzFramework::AssetSystem::AssetStatus_Unknown; - AzFramework::AssetSystemRequestBus::BroadcastResult( - status, &AzFramework::AssetSystemRequestBus::Events::CompileAssetSync, assetFilters); - if (status != AzFramework::AssetSystem::AssetStatus_Compiled) - { - failedAssets.append(assetFilters.c_str()); - } + CompileCriticalAssets(assetFiltersArray); } - if (!failedAssets.empty()) - { - QMessageBox::critical(activeWindow(), - QString("Failed to compile critical assets"), - QString("Failed to compile the following critical assets:\n%1\n%2") - .arg(failedAssets.join(",\n")) - .arg("Make sure this is an Atom project.")); - ExitMainLoop(); - } + AzFramework::AssetSystemStatusBus::Handler::BusDisconnect(); } - bool ShaderManagementConsoleApplication::OnPrintf(const char* window, const char* /*message*/) - { - // Suppress spam from the Source Control system - if (0 == strncmp(window, AzToolsFramework::SCC_WINDOW, AZ_ARRAY_SIZE(AzToolsFramework::SCC_WINDOW))) - { - return true; - } - - return false; - } +// bool ShaderManagementConsoleApplication::OnPrintf(const char* window, const char* /*message*/) +// { +// // Suppress spam from the Source Control system +// if (0 == strncmp(window, AzToolsFramework::SCC_WINDOW, AZ_ARRAY_SIZE(AzToolsFramework::SCC_WINDOW))) +// { +// return true; +// } +// +// return false; +// } void ShaderManagementConsoleApplication::ProcessCommandLine() { @@ -263,46 +225,4 @@ namespace ShaderManagementConsole return false; } - - void ShaderManagementConsoleApplication::Tick(float deltaOverride) - { - TickSystem(); - Application::Tick(deltaOverride); - - if (WasExitMainLoopRequested()) - { - m_timer.disconnect(); - quit(); - } - } - - void ShaderManagementConsoleApplication::OnTraceMessage([[maybe_unused]] AZStd::string_view message) - { -#if defined(AZ_ENABLE_TRACING) - AZStd::vector lines; - AzFramework::StringFunc::Tokenize( - message, - lines, - "\n", - false, // Keep empty strings - false // Keep space strings - ); - - for (auto& line : lines) - { - AZ_TracePrintf("Shader Management Console", "Python: %s\n", line.c_str()); - } -#endif - } - - void ShaderManagementConsoleApplication::OnErrorMessage(AZStd::string_view message) - { - // Use AZ_TracePrintf instead of AZ_Error or AZ_Warning to avoid all the metadata noise - OnTraceMessage(message); - } - - void ShaderManagementConsoleApplication::OnExceptionMessage([[maybe_unused]] AZStd::string_view message) - { - AZ_Error("Shader Management Console", false, "Python: " AZ_STRING_FORMAT, AZ_STRING_ARG(message)); - } } // namespace ShaderManagementConsole diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h index d99d814627..7c4f53f4e9 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h @@ -7,22 +7,8 @@ #pragma once -#include -#include -#include -#include - -#include -#include - -#include -#include -#include - #include #include - -#include #include #include @@ -34,7 +20,7 @@ namespace ShaderManagementConsole , private ShaderManagementConsoleWindowNotificationBus::Handler { public: - AZ_TYPE_INFO(ShaderManagementConsole::ShaderManagementConsoleApplication, "{30F90CA5-1253-49B5-8143-19CEE37E22BB}"); + AZ_TYPE_INFO(ShaderManagementConsole::ShaderManagementConsoleApplication, "{A31B1AEB-4DA3-49CD-884A-CC998FF7546F}"); using Base = AzFramework::Application; @@ -45,7 +31,6 @@ namespace ShaderManagementConsole // AzFramework::Application void CreateStaticModules(AZStd::vector& outModules) override; const char* GetCurrentConfigurationName() const override; - void Tick(float deltaOverride = -1.f) override; private: ////////////////////////////////////////////////////////////////////////// @@ -63,24 +48,11 @@ namespace ShaderManagementConsole void Destroy() override; ////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////// - // EditorPythonConsoleNotificationBus::Handler overrides... - void OnTraceMessage(AZStd::string_view message) override; - void OnErrorMessage(AZStd::string_view message) override; - void OnExceptionMessage(AZStd::string_view message) override; - //////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////// // AzFramework::AssetSystemStatusBus::Handler overrides... void AssetSystemAvailable() override; ////////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////// - // AZ::Debug::TraceMessageBus::Handler overrides... - bool OnPrintf(const char* window, const char* message) override; - ////////////////////////////////////////////////////////////////////////// - - void CompileCriticalAssets() override; void ProcessCommandLine(); void StartInternal() override; }; From 4306b57230ca1830f41e645cf021e305b6518e12 Mon Sep 17 00:00:00 2001 From: Dayo Lawal Date: Mon, 26 Jul 2021 13:08:59 -0500 Subject: [PATCH 037/160] More replacement with target name Signed-off-by: Dayo Lawal --- .../AtomToolsFramework/Application/AtomToolsApplication.h | 2 ++ .../Code/Source/MaterialEditorApplication.cpp | 2 +- .../Code/Source/ShaderManagementConsoleApplication.cpp | 8 ++------ 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h index 73ba062328..1ee73ee9fb 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h @@ -81,6 +81,8 @@ namespace AtomToolsFramework void OnExceptionMessage(AZStd::string_view message) override; //////////////////////////////////////////////////////////////////////// + virtual AZStd::string_view GetBuildTargetName() {return targetName;}; + virtual void LoadSettings(); virtual void UnloadSettings(); virtual void CompileCriticalAssets(const AZStd::vector &assetFiltersArray); diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp index 5e08b1e8ba..038005891d 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp @@ -139,7 +139,7 @@ namespace MaterialEditor AzFramework::AssetSystem::ConnectionSettings connectionSettings; AzFramework::AssetSystem::ReadConnectionSettingsFromSettingsRegistry(connectionSettings); connectionSettings.m_connectionDirection = AzFramework::AssetSystem::ConnectionSettings::ConnectionDirection::ConnectToAssetProcessor; - connectionSettings.m_connectionIdentifier = "MaterialEditor"; + connectionSettings.m_connectionIdentifier = targetName.c_str(); connectionSettings.m_loggingCallback = []([[maybe_unused]] AZStd::string_view logData) { AZ_TracePrintf("Material Editor", "%.*s", aznumeric_cast(logData.size()), logData.data()); diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp index 2ad61b9e3f..48c246f938 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp @@ -79,8 +79,7 @@ namespace ShaderManagementConsole void ShaderManagementConsoleApplication::CreateStaticModules(AZStd::vector& outModules) { - Application::CreateStaticModules(outModules); - outModules.push_back(aznew AzToolsFramework::AzToolsFrameworkModule); + Base::CreateStaticModules(outModules); outModules.push_back(aznew ShaderManagementConsoleDocumentModule); outModules.push_back(aznew ShaderManagementConsoleWindowModule); } @@ -98,11 +97,8 @@ namespace ShaderManagementConsole ShaderManagementConsole::ShaderManagementConsoleWindowRequestBus::Broadcast(&ShaderManagementConsole::ShaderManagementConsoleWindowRequestBus::Handler::DestroyShaderManagementConsoleWindow); ShaderManagementConsoleWindowNotificationBus::Handler::BusDisconnect(); - AzToolsFramework::AssetDatabase::AssetDatabaseRequestsBus::Handler::BusDisconnect(); - AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::StartDisconnectingAssetProcessor); - - Application::Destroy(); + Base::Destroy(); } void ShaderManagementConsoleApplication::AssetSystemAvailable() From a87318c52a3df6148cece8eb431fdc21cc964d51 Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Mon, 26 Jul 2021 11:31:34 -0700 Subject: [PATCH 038/160] temporarily disable SC unit tests on Linux until a file case issue is solved Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com> --- .../Framework/ScriptCanvasGraphUtilities.inl | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/Gems/ScriptCanvas/Code/Editor/Framework/ScriptCanvasGraphUtilities.inl b/Gems/ScriptCanvas/Code/Editor/Framework/ScriptCanvasGraphUtilities.inl index 96febf8553..8bb2fe8c29 100644 --- a/Gems/ScriptCanvas/Code/Editor/Framework/ScriptCanvasGraphUtilities.inl +++ b/Gems/ScriptCanvas/Code/Editor/Framework/ScriptCanvasGraphUtilities.inl @@ -20,6 +20,7 @@ #include #include #include +#include namespace ScriptCanvasEditor { @@ -223,6 +224,22 @@ namespace ScriptCanvasEditor if (!dependencies.empty()) { + +#if defined(LINUX) ////////////////////////////////////////////////////////////////////////// + + // Temporarily disable testing on the Linux build until the casing discrepancy + // is sorted out through the SC build and testing pipeline. + + auto graphEntityId = AZ::Entity::MakeId(); + reporter.SetGraph(graphEntityId); + loadResult.m_entity->Activate(); + ScriptCanvas::UnitTesting::EventSender::MarkComplete(graphEntityId, ""); + loadResult.m_entity->Deactivate(); + reporter.FinishReport(); + ScriptCanvas::SystemRequestBus::Broadcast(&ScriptCanvas::SystemRequests::MarkScriptUnitTestEnd); + return; +#else /////////////////////////////////////////////////////////////////////////////////////// + // #functions2_recursive_unit_tests eventually, this will need to be recursive, or the full asset handling system will need to be integrated into the testing framework // in order to test functionality with a dependency stack greater than 2 @@ -256,6 +273,7 @@ namespace ScriptCanvasEditor Execution::Context::InitializeActivationData(dependencyData); Execution::InitializeInterpretedStatics(dependencyData); } +#endif ////////////////////////////////////////////////////////////////////////////////////// } loadResult.m_scriptAsset = luaAssetResult.m_scriptAsset; From 91e84f15884db4408ca235bd7ffe58c9b736063a Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Mon, 26 Jul 2021 11:37:38 -0700 Subject: [PATCH 039/160] remove smoke tag now that Linux tests are disabled Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com> --- Gems/ScriptCanvasTesting/Code/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/Gems/ScriptCanvasTesting/Code/CMakeLists.txt b/Gems/ScriptCanvasTesting/Code/CMakeLists.txt index dada433772..23c9627e83 100644 --- a/Gems/ScriptCanvasTesting/Code/CMakeLists.txt +++ b/Gems/ScriptCanvasTesting/Code/CMakeLists.txt @@ -113,7 +113,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) ) ly_add_googletest( NAME Gem::ScriptCanvasTesting.Editor.Tests - TEST_SUITE smoke ) endif() From 61f91d4a9ab8c9affb0e8bfb959cad8a5ad939cd Mon Sep 17 00:00:00 2001 From: Cynthia Lin <15116870+synicalsyntax@users.noreply.github.com> Date: Mon, 26 Jul 2021 12:25:50 -0700 Subject: [PATCH 040/160] Move benchmark data aggregation from ASV into ly_test_tools module. (#2335) * fix: Correct typo in profiling capture system. Signed-off-by: Cynthia Lin * Move benchmark data aggregation from ASV into ly_test_tools module. Signed-off-by: Cynthia Lin --- .../ProfilingCaptureSystemComponent.cpp | 4 +- .../benchmark/data_aggregator.py | 163 ++++++++++++++++++ 2 files changed, 165 insertions(+), 2 deletions(-) create mode 100644 Tools/LyTestTools/ly_test_tools/benchmark/data_aggregator.py diff --git a/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.cpp b/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.cpp index fefd889551..0c4c4d9689 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.cpp @@ -453,8 +453,8 @@ namespace AZ JsonSerializerSettings serializationSettings; serializationSettings.m_keepDefaults = true; - TimestampSerializer timestapSerializer(CollectPassesRecursively(root)); - const auto saveResult = JsonSerializationUtils::SaveObjectToFile(×tapSerializer, + TimestampSerializer timestampSerializer(CollectPassesRecursively(root)); + const auto saveResult = JsonSerializationUtils::SaveObjectToFile(×tampSerializer, outputFilePath, (TimestampSerializer*)nullptr, &serializationSettings); AZStd::string captureInfo = outputFilePath; diff --git a/Tools/LyTestTools/ly_test_tools/benchmark/data_aggregator.py b/Tools/LyTestTools/ly_test_tools/benchmark/data_aggregator.py new file mode 100644 index 0000000000..8a62c2e150 --- /dev/null +++ b/Tools/LyTestTools/ly_test_tools/benchmark/data_aggregator.py @@ -0,0 +1,163 @@ +""" +Copyright (c) Contributors to the Open 3D Engine Project. +For complete copyright and license terms please see the LICENSE at the root of this distribution. + +SPDX-License-Identifier: Apache-2.0 OR MIT +""" + +from argparse import ArgumentParser +import json +from pathlib import Path +import time +import subprocess + +from ly_test_tools.mars.filebeat_client import FilebeatClient + +class BenchmarkPathException(Exception): + """Custom Exception class for invalid benchmark file paths.""" + pass + +class BenchmarkDataAggregator(object): + def __init__(self, workspace, logger, test_suite): + self.build_dir = workspace.paths.build_directory() + self.results_dir = Path(workspace.paths.project(), 'user/Scripts/PerformanceBenchmarks') + self.test_suite = test_suite + self.filebeat_client = FilebeatClient(logger) + + def _update_pass(self, pass_stats, entry): + ''' + Modifies pass_stats dict keyed by pass name with the time recorded in a pass timestamp entry. + + :param pass_stats: dict aggregating statistics from each pass (key: pass name, value: dict with stats) + :param entry: dict representing the timestamp entry of a pass + :return: Time (in nanoseconds) recorded by this pass + ''' + name = entry['passName'] + time_ns = entry['timestampResultInNanoseconds'] + pass_entry = pass_stats.get(name, { 'totalTime': 0, 'maxTime': 0 }) + + pass_entry['maxTime'] = max(time_ns, pass_entry['maxTime']) + pass_entry['totalTime'] += time_ns + pass_stats[name] = pass_entry + return time_ns + + + def _process_benchmark(self, benchmark_dir, benchmark_metadata): + ''' + Aggregates data from results from a single benchmark contained in a subdirectory of self.results_dir. + + :param benchmark_dir: Path of directory containing the benchmark results + :param benchmark_metadata: Dict with benchmark metadata mutated with additional info from metadata file + :return: Tuple with two indexes: + [0]: Dict aggregating statistics from frame times (key: stat name) + [1]: Dict aggregating statistics from pass times (key: pass name, value: dict with stats) + ''' + # Parse benchmark metadata + metadata_file = benchmark_dir / 'benchmark_metadata.json' + if metadata_file.exists(): + data = json.loads(metadata_file.read_text()) + benchmark_metadata.update(data['ClassData']) + else: + raise BenchmarkPathException(f'Metadata file could not be found at {metadata_file}') + + # data structures aggregating statistics from timestamp logs + frame_stats = { 'count': 0, 'totalTime': 0, 'maxTime': 0, 'minTime': float('inf') } + pass_stats = {} # key: pass name, value: dict with totalTime and maxTime keys + + # this allows us to add additional data if necessary, e.g. frame_test_timestamps.json + is_timestamp_file = lambda file: file.name.startswith('frame') and file.name.endswith('_timestamps.json') + + # parse benchmark files + for file in benchmark_dir.iterdir(): + if file.is_dir() or not is_timestamp_file(file): + continue + + data = json.loads(file.read_text()) + entries = data['ClassData']['timestampEntries'] + + frame_time = sum(self._update_pass(pass_stats, entry) for entry in entries) + + frame_stats['totalTime'] += frame_time + frame_stats['maxTime'] = max(frame_time, frame_stats['maxTime']) + frame_stats['minTime'] = min(frame_time, frame_stats['minTime']) + frame_stats['count'] += 1 + + if frame_stats['count'] < 1: + raise BenchmarkPathException(f'No frame timestamp logs were found in {benchmark_dir}') + + return frame_stats, pass_stats + + def _generate_payloads(self, benchmark_metadata, frame_stats, pass_stats): + ''' + Generates payloads to send to Filebeat based on aggregated stats and metadata. + + :param benchmark_metadata: Dict of benchmark metadata + :param frame_stats: Dict of aggregated frame statistics + :param pass_stats: Dict of aggregated pass statistics + :return payloads: List of tuples, each with two indexes: + [0]: Elasticsearch index suffix associated with the payload + [1]: Payload dict to deliver to Filebeat + ''' + ns_to_ms = lambda ns: ns / 1e6 + payloads = [] + + # calculate statistics based on aggregated frame data + frame_time_avg = frame_stats['totalTime'] / frame_stats['count'] + frame_payload = { + 'frameTime': { + 'avg': ns_to_ms(frame_time_avg), + 'max': ns_to_ms(frame_stats['maxTime']), + 'min': ns_to_ms(frame_stats['minTime']) + } + } + # add benchmark metadata to payload + frame_payload.update(benchmark_metadata) + payloads.append(('frame_data', frame_payload)) + + # calculate statistics for each pass + for name, stat in pass_stats.items(): + avg_ms = ns_to_ms(stat['totalTime'] / frame_stats['count']) + max_ms = ns_to_ms(stat['maxTime']) + + pass_payload = { + 'passName': name, + 'passTime': { + 'avg': avg_ms, + 'max': max_ms + } + } + # add benchmark metadata to payload + pass_payload.update(benchmark_metadata) + payloads.append(('pass_data', pass_payload)) + + return payloads + + def upload_metrics(self, rhi): + ''' + Uploads metrics aggregated from all the benchmarks run in a test suite to filebeat. + + :param rhi: The RHI the benchmarks were run on + ''' + start_timestamp = time.time() + + git_commit_data = subprocess.check_output(['git', 'rev-parse', '--short', 'HEAD'], cwd=self.build_dir) + git_commit_hash = git_commit_data.decode('ascii').strip() + build_date = time.strftime('%m/%d/%y', time.localtime(start_timestamp)) # use gmtime if GMT is preferred + + for benchmark_dir in self.results_dir.iterdir(): + if not benchmark_dir.is_dir(): + continue + + benchmark_metadata = { + 'gitCommitAndBuildDate': f'{git_commit_hash} {build_date}', + 'RHI': rhi + } + frame_stats, pass_stats = self._process_benchmark(benchmark_dir, benchmark_metadata) + payloads = self._generate_payloads(benchmark_metadata, frame_stats, pass_stats) + + for index_suffix, payload in payloads: + self.filebeat_client.send_event( + payload, + f'ly_atom.performance_metrics.{self.test_suite}.{index_suffix}', + start_timestamp + ) From 3ad8f0dbf9dbb075c00bfff3bdbfb27104ac3bf1 Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Mon, 26 Jul 2021 13:20:08 -0700 Subject: [PATCH 041/160] adjust location of disabling SC unit tests on Linux Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com> --- .../Framework/ScriptCanvasGraphUtilities.inl | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Gems/ScriptCanvas/Code/Editor/Framework/ScriptCanvasGraphUtilities.inl b/Gems/ScriptCanvas/Code/Editor/Framework/ScriptCanvasGraphUtilities.inl index 2048fea08a..4b22864b6e 100644 --- a/Gems/ScriptCanvas/Code/Editor/Framework/ScriptCanvasGraphUtilities.inl +++ b/Gems/ScriptCanvas/Code/Editor/Framework/ScriptCanvasGraphUtilities.inl @@ -218,19 +218,14 @@ namespace ScriptCanvasEditor if (!reporter.IsProcessOnly()) { - dependencies = LoadInterpretedDepencies(luaAssetResult.m_dependencies.source.userSubgraphs); - RuntimeDataOverrides runtimeDataOverrides; runtimeDataOverrides.m_runtimeAsset = loadResult.m_runtimeAsset; - if (!dependencies.empty()) - { - #if defined(LINUX) ////////////////////////////////////////////////////////////////////////// - - // Temporarily disable testing on the Linux build until the casing discrepancy - // is sorted out through the SC build and testing pipeline. - + // Temporarily disable testing on the Linux build until the file name casing discrepancy + // is sorted out through the SC build and testing pipeline. + if (!luaAssetResult.m_dependencies.source.userSubgraphs.empty()) + { auto graphEntityId = AZ::Entity::MakeId(); reporter.SetGraph(graphEntityId); loadResult.m_entity->Activate(); @@ -239,8 +234,13 @@ namespace ScriptCanvasEditor reporter.FinishReport(); ScriptCanvas::SystemRequestBus::Broadcast(&ScriptCanvas::SystemRequests::MarkScriptUnitTestEnd); return; + } #else /////////////////////////////////////////////////////////////////////////////////////// + dependencies = LoadInterpretedDepencies(luaAssetResult.m_dependencies.source.userSubgraphs); + + if (!dependencies.empty()) + { // #functions2_recursive_unit_tests eventually, this will need to be recursive, or the full asset handling system will need to be integrated into the testing framework // in order to test functionality with a dependency stack greater than 2 @@ -274,8 +274,8 @@ namespace ScriptCanvasEditor Execution::Context::InitializeActivationData(dependencyData); Execution::InitializeInterpretedStatics(dependencyData); } -#endif ////////////////////////////////////////////////////////////////////////////////////// } +#endif ////////////////////////////////////////////////////////////////////////////////////// loadResult.m_scriptAsset = luaAssetResult.m_scriptAsset; loadResult.m_runtimeAsset.Get()->GetData().m_script = loadResult.m_scriptAsset; From 41ebcefe667252c30549e6b2ac81b3c12b4d21e0 Mon Sep 17 00:00:00 2001 From: amzn-phist <52085794+amzn-phist@users.noreply.github.com> Date: Mon, 26 Jul 2021 15:23:31 -0500 Subject: [PATCH 042/160] Restoring include headers that were removed These removals caused build errors on non-unity builds. Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com> --- Gems/AudioSystem/Code/Source/Editor/ATLControlsModel.cpp | 1 + Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorWindow.h | 1 + 2 files changed, 2 insertions(+) diff --git a/Gems/AudioSystem/Code/Source/Editor/ATLControlsModel.cpp b/Gems/AudioSystem/Code/Source/Editor/ATLControlsModel.cpp index 7bcce84ea4..4fbc2a72c4 100644 --- a/Gems/AudioSystem/Code/Source/Editor/ATLControlsModel.cpp +++ b/Gems/AudioSystem/Code/Source/Editor/ATLControlsModel.cpp @@ -13,6 +13,7 @@ #include #include #include +#include namespace AudioControls { diff --git a/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorWindow.h b/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorWindow.h index 761f0c1a8e..bfa08828ac 100644 --- a/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorWindow.h +++ b/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorWindow.h @@ -12,6 +12,7 @@ #if !defined(Q_MOC_RUN) #include #include +#include #include #include From 900cc08510513e46fec38261e7f67301974e1ee7 Mon Sep 17 00:00:00 2001 From: amzn-phist <52085794+amzn-phist@users.noreply.github.com> Date: Mon, 26 Jul 2021 15:29:00 -0500 Subject: [PATCH 043/160] Removing dependencies on legacy code (#2358) * Removes use of gEnv->mMainThreadId Save off the thread id that was used when initializing audio system and connecting EBuses, use that instead of gEnv. Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com> * Replace uses of gEnv->pCryPak with AZ::IO Updated uses of pCryPak to instead go through the AZ::IO::FileIOBase instance. Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com> --- .../Source/Engine/FileIOHandler_wwise.cpp | 91 ++++++++++--------- .../Code/Source/Engine/AudioSystem.cpp | 37 ++++---- .../Code/Source/Engine/FileCacheManager.cpp | 15 +-- 3 files changed, 80 insertions(+), 63 deletions(-) diff --git a/Gems/AudioEngineWwise/Code/Source/Engine/FileIOHandler_wwise.cpp b/Gems/AudioEngineWwise/Code/Source/Engine/FileIOHandler_wwise.cpp index 388a539be1..9571dd86a9 100644 --- a/Gems/AudioEngineWwise/Code/Source/Engine/FileIOHandler_wwise.cpp +++ b/Gems/AudioEngineWwise/Code/Source/Engine/FileIOHandler_wwise.cpp @@ -7,18 +7,16 @@ */ -#include #include + #include +#include #include #include #include #include - -#include -#include -#include +#include #define MAX_NUMBER_STRING_SIZE (10) // 4G #define ID_TO_STRING_FORMAT_BANK AKTEXT("%u.bnk") @@ -90,34 +88,36 @@ namespace Audio bool CBlockingDevice_wwise::Open(const char* filename, AkOpenMode openMode, AkFileDesc& fileDesc) { - const char* openModeString = nullptr; + AZ::IO::OpenMode azOpenMode = AZ::IO::OpenMode::ModeBinary; switch (openMode) { case AK_OpenModeRead: - openModeString = "rbx"; + azOpenMode |= AZ::IO::OpenMode::ModeRead; break; case AK_OpenModeWrite: - openModeString = "wbx"; + azOpenMode |= AZ::IO::OpenMode::ModeWrite; break; case AK_OpenModeWriteOvrwr: - openModeString = "w+bx"; + azOpenMode |= (AZ::IO::OpenMode::ModeUpdate | AZ::IO::OpenMode::ModeWrite); break; case AK_OpenModeReadWrite: - openModeString = "abx"; + azOpenMode |= (AZ::IO::OpenMode::ModeRead | AZ::IO::OpenMode::ModeWrite); break; default: AZ_Assert(false, "Unknown Wwise file open mode."); return false; } - const size_t fileSize = gEnv->pCryPak->FGetSize(filename); - if (fileSize > 0) + auto fileIO = AZ::IO::FileIOBase::GetInstance(); + if (AZ::u64 fileSize = 0; + fileIO->Size(filename, fileSize) && fileSize != 0) { - AZ::IO::HandleType fileHandle = gEnv->pCryPak->FOpen(filename, openModeString, AZ::IO::IArchive::FOPEN_HINT_DIRECT_OPERATION); + AZ::IO::HandleType fileHandle = AZ::IO::InvalidHandle; + fileIO->Open(filename, azOpenMode, fileHandle); if (fileHandle != AZ::IO::InvalidHandle) { fileDesc.hFile = GetAkFileHandle(fileHandle); - fileDesc.iFileSize = static_cast(fileSize); + fileDesc.iFileSize = aznumeric_cast(fileSize); fileDesc.uSector = 0; fileDesc.deviceID = m_deviceID; fileDesc.pCustomParam = nullptr; @@ -132,50 +132,58 @@ namespace Audio AKRESULT CBlockingDevice_wwise::Read(AkFileDesc& fileDesc, const AkIoHeuristics&, void* buffer, AkIOTransferInfo& transferInfo) { - AZ_Assert(buffer, "Wwise didn't provide a valid buffer to write to."); + AZ_Assert(buffer, "Wwise didn't provide a valid desination buffer to Read into."); AZ::IO::HandleType fileHandle = GetRealFileHandle(fileDesc.hFile); - const uint64_t currentFileReadPos = gEnv->pCryPak->FTell(fileHandle); - const uint64_t wantedFileReadPos = static_cast(transferInfo.uFilePosition); + auto fileIO = AZ::IO::FileIOBase::GetInstance(); + + AZ::u64 currentFileReadPos = 0; + fileIO->Tell(fileHandle, currentFileReadPos); - if (currentFileReadPos != wantedFileReadPos) + if (currentFileReadPos != transferInfo.uFilePosition) { - gEnv->pCryPak->FSeek(fileHandle, wantedFileReadPos, SEEK_SET); + fileIO->Seek(fileHandle, aznumeric_cast(transferInfo.uFilePosition), AZ::IO::SeekType::SeekFromStart); } - const size_t bytesRead = gEnv->pCryPak->FReadRaw(buffer, 1, transferInfo.uRequestedSize, fileHandle); - AZ_Assert(bytesRead == static_cast(transferInfo.uRequestedSize), - "Number of bytes read (%zu) for Wwise request doesn't match the requested size (%u).", bytesRead, transferInfo.uRequestedSize); - return (bytesRead > 0) ? AK_Success : AK_Fail; + AZ::u64 bytesRead = 0; + fileIO->Read(fileHandle, buffer, aznumeric_cast(transferInfo.uRequestedSize), &bytesRead); + const bool readOk = (bytesRead == aznumeric_cast(transferInfo.uRequestedSize)); + + AZ_Assert(readOk, + "Number of bytes read (%" PRIu64 ") for read request doesn't match the requested size (%u).", + bytesRead, transferInfo.uRequestedSize); + return readOk ? AK_Success : AK_Fail; } AKRESULT CBlockingDevice_wwise::Write(AkFileDesc& fileDesc, const AkIoHeuristics&, void* data, AkIOTransferInfo& transferInfo) { - AZ_Assert(data, "Wwise didn't provide a valid buffer to read from."); + AZ_Assert(data, "Wwise didn't provide a valid source buffer to Write from."); AZ::IO::HandleType fileHandle = GetRealFileHandle(fileDesc.hFile); + auto fileIO = AZ::IO::FileIOBase::GetInstance(); - const uint64_t currentFileWritePos = gEnv->pCryPak->FTell(fileHandle); - const uint64_t wantedFileWritePos = static_cast(transferInfo.uFilePosition); + AZ::u64 currentFileWritePos = 0; + fileIO->Tell(fileHandle, currentFileWritePos); - if (currentFileWritePos != wantedFileWritePos) + if (currentFileWritePos != transferInfo.uFilePosition) { - gEnv->pCryPak->FSeek(fileHandle, wantedFileWritePos, SEEK_SET); + fileIO->Seek(fileHandle, aznumeric_cast(transferInfo.uFilePosition), AZ::IO::SeekType::SeekFromStart); } - const size_t bytesWritten = gEnv->pCryPak->FWrite(data, 1, static_cast(transferInfo.uRequestedSize), fileHandle); - if (bytesWritten != static_cast(transferInfo.uRequestedSize)) - { - AZ_Error("Wwise", false, "Number of bytes written (%zu) for Wwise request doesn't match the requested size (%u).", + AZ::u64 bytesWritten = 0; + fileIO->Write(fileHandle, data, aznumeric_cast(transferInfo.uRequestedSize), &bytesWritten); + const bool writeOk = (bytesWritten == aznumeric_cast(transferInfo.uRequestedSize)); + + AZ_Error("Wwise", writeOk, + "Number of bytes written (%" PRIu64 ") for write request doesn't match the requested size (%u).", bytesWritten, transferInfo.uRequestedSize); - return AK_Fail; - } - return AK_Success; + return writeOk ? AK_Success : AK_Fail; } AKRESULT CBlockingDevice_wwise::Close(AkFileDesc& fileDesc) { - return gEnv->pCryPak->FClose(GetRealFileHandle(fileDesc.hFile)) ? AK_Success : AK_Fail; + auto fileIO = AZ::IO::FileIOBase::GetInstance(); + return fileIO->Close(GetRealFileHandle(fileDesc.hFile)) ? AK_Success : AK_Fail; } AkUInt32 CBlockingDevice_wwise::GetBlockSize([[maybe_unused]] AkFileDesc& fileDesc) @@ -189,7 +197,7 @@ namespace Audio deviceDesc.bCanRead = true; deviceDesc.bCanWrite = true; deviceDesc.deviceID = m_deviceID; - AK_CHAR_TO_UTF16(deviceDesc.szDeviceName, "CryPak", AZ_ARRAY_SIZE(deviceDesc.szDeviceName)); + AK_CHAR_TO_UTF16(deviceDesc.szDeviceName, "IO::IArchive", AZ_ARRAY_SIZE(deviceDesc.szDeviceName)); deviceDesc.uStringSize = AKPLATFORM::AkUtf16StrLen(deviceDesc.szDeviceName); } @@ -231,12 +239,13 @@ namespace Audio bool CStreamingDevice_wwise::Open(const char* filename, [[maybe_unused]] AkOpenMode openMode, AkFileDesc& fileDesc) { AZ_Assert(openMode == AK_OpenModeRead, "Wwise Async File IO - Only supports opening files for reading.\n"); - const size_t fileSize = gEnv->pCryPak->FGetSize(filename); - if (fileSize) + auto fileIO = AZ::IO::FileIOBase::GetInstance(); + if (AZ::u64 fileSize = 0; + fileIO->Size(filename, fileSize) && fileSize != 0) { AZStd::string* filenameStore = azcreate(AZStd::string, (filename)); fileDesc.hFile = AkFileHandle(); - fileDesc.iFileSize = static_cast(fileSize); + fileDesc.iFileSize = aznumeric_cast(fileSize); fileDesc.uSector = 0; fileDesc.deviceID = m_deviceID; fileDesc.pCustomParam = filenameStore; @@ -326,7 +335,7 @@ namespace Audio deviceDesc.bCanRead = true; deviceDesc.bCanWrite = false; deviceDesc.deviceID = m_deviceID; - AK_CHAR_TO_UTF16(deviceDesc.szDeviceName, "Streamer", AZ_ARRAY_SIZE(deviceDesc.szDeviceName)); + AK_CHAR_TO_UTF16(deviceDesc.szDeviceName, "IO::IStreamer", AZ_ARRAY_SIZE(deviceDesc.szDeviceName)); deviceDesc.uStringSize = AKPLATFORM::AkUtf16StrLen(deviceDesc.szDeviceName); } diff --git a/Gems/AudioSystem/Code/Source/Engine/AudioSystem.cpp b/Gems/AudioSystem/Code/Source/Engine/AudioSystem.cpp index 0353a8b39d..30d815cbec 100644 --- a/Gems/AudioSystem/Code/Source/Engine/AudioSystem.cpp +++ b/Gems/AudioSystem/Code/Source/Engine/AudioSystem.cpp @@ -23,6 +23,9 @@ namespace Audio extern CAudioLogger g_audioLogger; static constexpr const char AudioControlsBasePath[]{ "libs/gameaudio/" }; + // Save off the threadId of the "Main Thread" that was used to connect EBuses. + AZStd::thread_id g_mainThreadId; + /////////////////////////////////////////////////////////////////////////////////////////////////// // CAudioThread /////////////////////////////////////////////////////////////////////////////////////////////////// @@ -77,6 +80,8 @@ namespace Audio CAudioSystem::CAudioSystem() : m_bSystemInitialized(false) { + g_mainThreadId = AZStd::this_thread::get_id(); + m_apAudioProxies.reserve(Audio::CVars::s_AudioObjectPoolSize); m_apAudioProxiesToBeFreed.reserve(16); m_controlsPath.assign(Audio::AudioControlsBasePath); @@ -99,7 +104,7 @@ namespace Audio { CAudioRequestInternal request(audioRequestData); - AZ_Assert(gEnv->mMainThreadId == CryGetCurrentThreadId(), "AudioSystem::PushRequest - called from non-Main thread!"); + AZ_Assert(g_mainThreadId == AZStd::this_thread::get_id(), "AudioSystem::PushRequest - called from non-Main thread!"); AZ_Assert(0 == (request.nFlags & eARF_THREAD_SAFE_PUSH), "AudioSystem::PushRequest - called with flag THREAD_SAFE_PUSH!"); AZ_Assert(0 == (request.nFlags & eARF_EXECUTE_BLOCKING), "AudioSystem::PushRequest - called with flag EXECUTE_BLOCKING!"); @@ -114,7 +119,7 @@ namespace Audio CAudioRequestInternal request(audioRequestData); - AZ_Assert(gEnv->mMainThreadId == CryGetCurrentThreadId(), "AudioSystem::PushRequestBlocking - called from non-Main thread!"); + AZ_Assert(g_mainThreadId == AZStd::this_thread::get_id(), "AudioSystem::PushRequestBlocking - called from non-Main thread!"); AZ_Assert(0 != (request.nFlags & eARF_EXECUTE_BLOCKING), "AudioSystem::PushRequestBlocking - called without EXECUTE_BLOCKING flag!"); AZ_Assert(0 == (request.nFlags & eARF_THREAD_SAFE_PUSH), "AudioSystem::PushRequestBlocking - called with THREAD_SAFE_PUSH flag!"); @@ -139,7 +144,7 @@ namespace Audio const EAudioRequestType requestType, const TATLEnumFlagsType specificRequestMask) { - AZ_Assert(gEnv->mMainThreadId == CryGetCurrentThreadId(), "AudioSystem::AddRequestListener - called from a non-Main thread!"); + AZ_Assert(g_mainThreadId == AZStd::this_thread::get_id(), "AudioSystem::AddRequestListener - called from a non-Main thread!"); if (func) { @@ -155,7 +160,7 @@ namespace Audio /////////////////////////////////////////////////////////////////////////////////////////////////// void CAudioSystem::RemoveRequestListener(AudioRequestCallbackType func, void* const callbackOwner) { - AZ_Assert(gEnv->mMainThreadId == CryGetCurrentThreadId(), "AudioSystem::RemoveRequestListener - called from a non-Main thread!"); + AZ_Assert(g_mainThreadId == AZStd::this_thread::get_id(), "AudioSystem::RemoveRequestListener - called from a non-Main thread!"); SAudioEventListener listener; listener.m_callbackOwner = callbackOwner; @@ -167,7 +172,7 @@ namespace Audio void CAudioSystem::ExternalUpdate() { // Main Thread! - AZ_Assert(gEnv->mMainThreadId == CryGetCurrentThreadId(), "AudioSystem::ExternalUpdate - called from non-Main thread!"); + AZ_Assert(g_mainThreadId == AZStd::this_thread::get_id(), "AudioSystem::ExternalUpdate - called from non-Main thread!"); // Notify callbacks on the pending callbacks queue... // These are requests that were completed then queued for callback processing to happen here. @@ -242,7 +247,7 @@ namespace Audio /////////////////////////////////////////////////////////////////////////////////////////////////// bool CAudioSystem::Initialize() { - AZ_Assert(gEnv->mMainThreadId == CryGetCurrentThreadId(), "AudioSystem::Initialize - called from a non-Main thread!"); + AZ_Assert(g_mainThreadId == AZStd::this_thread::get_id(), "AudioSystem::Initialize - called from a non-Main thread!"); if (!m_bSystemInitialized) { @@ -265,7 +270,7 @@ namespace Audio /////////////////////////////////////////////////////////////////////////////////////////////////// void CAudioSystem::Release() { - AZ_Assert(gEnv->mMainThreadId == CryGetCurrentThreadId(), "AudioSystem::Release - called from a non-Main thread!"); + AZ_Assert(g_mainThreadId == AZStd::this_thread::get_id(), "AudioSystem::Release - called from a non-Main thread!"); for (auto audioProxy : m_apAudioProxies) { @@ -331,14 +336,14 @@ namespace Audio /////////////////////////////////////////////////////////////////////////////////////////////////// bool CAudioSystem::ReserveAudioListenerID(TAudioObjectID& rAudioObjectID) { - AZ_Assert(gEnv->mMainThreadId == CryGetCurrentThreadId(), "AudioSystem::ReserveAudioListenerID - called from a non-Main thread!"); + AZ_Assert(g_mainThreadId == AZStd::this_thread::get_id(), "AudioSystem::ReserveAudioListenerID - called from a non-Main thread!"); return m_oATL.ReserveAudioListenerID(rAudioObjectID); } /////////////////////////////////////////////////////////////////////////////////////////////////// bool CAudioSystem::ReleaseAudioListenerID(TAudioObjectID const nAudioObjectID) { - AZ_Assert(gEnv->mMainThreadId == CryGetCurrentThreadId(), "AudioSystem::ReleaseAudioListenerID - called from a non-Main thread!"); + AZ_Assert(g_mainThreadId == AZStd::this_thread::get_id(), "AudioSystem::ReleaseAudioListenerID - called from a non-Main thread!"); return m_oATL.ReleaseAudioListenerID(nAudioObjectID); } @@ -385,7 +390,7 @@ namespace Audio void CAudioSystem::RefreshAudioSystem([[maybe_unused]] const char* const levelName) { #if !defined(AUDIO_RELEASE) - AZ_Assert(gEnv->mMainThreadId == CryGetCurrentThreadId(), "AudioSystem::RefreshAudioSystem - called from a non-Main thread!"); + AZ_Assert(g_mainThreadId == AZStd::this_thread::get_id(), "AudioSystem::RefreshAudioSystem - called from a non-Main thread!"); // Get the controls path and a level-specific preload Id first. // This will be passed with the request so that it doesn't have to lookup this data @@ -409,7 +414,7 @@ namespace Audio /////////////////////////////////////////////////////////////////////////////////////////////////// IAudioProxy* CAudioSystem::GetFreeAudioProxy() { - AZ_Assert(gEnv->mMainThreadId == CryGetCurrentThreadId(), "AudioSystem::GetFreeAudioProxy - called from a non-Main thread!"); + AZ_Assert(g_mainThreadId == AZStd::this_thread::get_id(), "AudioSystem::GetFreeAudioProxy - called from a non-Main thread!"); CAudioProxy* audioProxy = nullptr; if (!m_apAudioProxies.empty()) @@ -435,7 +440,7 @@ namespace Audio /////////////////////////////////////////////////////////////////////////////////////////////////// void CAudioSystem::FreeAudioProxy(IAudioProxy* const audioProxyI) { - AZ_Assert(gEnv->mMainThreadId == CryGetCurrentThreadId(), "AudioSystem::FreeAudioProxy - called from a non-Main thread!"); + AZ_Assert(g_mainThreadId == AZStd::this_thread::get_id(), "AudioSystem::FreeAudioProxy - called from a non-Main thread!"); auto const audioProxy = static_cast(audioProxyI); if (AZStd::find(m_apAudioProxiesToBeFreed.begin(), m_apAudioProxiesToBeFreed.end(), audioProxy) != m_apAudioProxiesToBeFreed.end() || AZStd::find(m_apAudioProxies.begin(), m_apAudioProxies.end(), audioProxy) != m_apAudioProxies.end()) @@ -469,7 +474,7 @@ namespace Audio /////////////////////////////////////////////////////////////////////////////////////////////////// const char* CAudioSystem::GetAudioControlName([[maybe_unused]] const EAudioControlType controlType, [[maybe_unused]] const TATLIDType atlID) const { - AZ_Assert(gEnv->mMainThreadId == CryGetCurrentThreadId(), "AudioSystem::GetAudioControlName - called from non-Main thread!"); + AZ_Assert(g_mainThreadId == AZStd::this_thread::get_id(), "AudioSystem::GetAudioControlName - called from non-Main thread!"); const char* sResult = nullptr; #if !defined(AUDIO_RELEASE) @@ -524,7 +529,7 @@ namespace Audio /////////////////////////////////////////////////////////////////////////////////////////////////// const char* CAudioSystem::GetAudioSwitchStateName([[maybe_unused]] const TAudioControlID switchID, [[maybe_unused]] const TAudioSwitchStateID stateID) const { - AZ_Assert(gEnv->mMainThreadId == CryGetCurrentThreadId(), "AudioSystem::GetAudioSwitchStateName - called from non-Main thread!"); + AZ_Assert(g_mainThreadId == AZStd::this_thread::get_id(), "AudioSystem::GetAudioSwitchStateName - called from non-Main thread!"); const char* sResult = nullptr; #if !defined(AUDIO_RELEASE) @@ -638,7 +643,7 @@ namespace Audio AZ_PROFILE_SCOPE_DYNAMIC(AZ::Debug::ProfileCategory::Audio, "Normal Request: %s", request.ToString().c_str()); - AZ_Assert(gEnv->mMainThreadId != CryGetCurrentThreadId(), "AudioSystem::ProcessRequestByPriority - called from Main thread!"); + AZ_Assert(g_mainThreadId != AZStd::this_thread::get_id(), "AudioSystem::ProcessRequestByPriority - called from Main thread!"); if (m_oATL.CanProcessRequests()) { @@ -698,7 +703,7 @@ namespace Audio #if !defined(AUDIO_RELEASE) void CAudioSystem::DrawAudioDebugData() { - AZ_Assert(gEnv->mMainThreadId == CryGetCurrentThreadId(), "AudioSystem::DrawAudioDebugData - called from non-Main thread!"); + AZ_Assert(g_mainThreadId == AZStd::this_thread::get_id(), "AudioSystem::DrawAudioDebugData - called from non-Main thread!"); if (CVars::s_debugDrawOptions.GetRawFlags() != 0) { diff --git a/Gems/AudioSystem/Code/Source/Engine/FileCacheManager.cpp b/Gems/AudioSystem/Code/Source/Engine/FileCacheManager.cpp index d6fe618998..f1a360fd7d 100644 --- a/Gems/AudioSystem/Code/Source/Engine/FileCacheManager.cpp +++ b/Gems/AudioSystem/Code/Source/Engine/FileCacheManager.cpp @@ -9,12 +9,12 @@ #include +#include #include #include #include #include #include -#include #include #include @@ -115,9 +115,9 @@ namespace Audio newAudioFileEntry->m_dataScope = dataScope; AZStd::to_lower(newAudioFileEntry->m_filePath.begin(), newAudioFileEntry->m_filePath.end()); - const size_t fileSize = gEnv->pCryPak->FGetSize(newAudioFileEntry->m_filePath.c_str()); - - if (fileSize > 0) + auto fileIO = AZ::IO::FileIOBase::GetInstance(); + if (AZ::u64 fileSize = 0; + fileIO->Size(newAudioFileEntry->m_filePath.c_str(), fileSize) && fileSize != 0) { newAudioFileEntry->m_fileSize = fileSize; newAudioFileEntry->m_flags.ClearFlags(eAFF_NOTFOUND); @@ -770,9 +770,12 @@ namespace Audio } AZStd::to_lower(audioFileEntry->m_filePath.begin(), audioFileEntry->m_filePath.end()); - audioFileEntry->m_fileSize = gEnv->pCryPak->FGetSize(audioFileEntry->m_filePath.c_str()); + AZ::u64 fileSize = 0; + auto fileIO = AZ::IO::FileIOBase::GetInstance(); + fileIO->Size(audioFileEntry->m_filePath.c_str(), fileSize); + audioFileEntry->m_fileSize = fileSize; - AZ_Assert(audioFileEntry->m_fileSize > 0, "FileCacheManager - UpdateLocalizedFileEntryData expected file size to be greater than zero!"); + AZ_Assert(audioFileEntry->m_fileSize != 0, "FileCacheManager - UpdateLocalizedFileEntryData expected file size to be greater than zero!"); } /////////////////////////////////////////////////////////////////////////////////////////////// From e81f59d1e1bda849f7a716ab70eb3472293cd12b Mon Sep 17 00:00:00 2001 From: Steve Pham <82231385+spham-amzn@users.noreply.github.com> Date: Mon, 26 Jul 2021 13:41:28 -0700 Subject: [PATCH 044/160] Create XCB Connection mechanism for WSISurface implementation for Linux (#2400) - Add new Linux Trait to determine which display driver client API to use (only xcb supported for now) - Add support for xcb connections (initial) for Linux/Vulkan - Fix minor assertion caused by wrong use of sizeof - Fix casing issue in a couple of material files (Linux is case sensitive) --- .../AzFramework/API/ApplicationAPI_Linux.h | 32 +++++++++++++ .../Application/Application_Linux.cpp | 47 +++++++++++++++++++ .../Platform/Linux/platform_linux.cmake | 27 +++++++++++ .../Platform/Linux/glad_vulkan_linux.cmake | 18 +++++-- .../Platform/Linux/RHI/WSISurface_Linux.cpp | 22 +++++++++ .../001_lucy_regression_test.material | 2 +- .../002_wrinkle_regression_test.material | 2 +- cmake/Platform/Linux/PAL_linux.cmake | 4 ++ 8 files changed, 149 insertions(+), 5 deletions(-) diff --git a/Code/Framework/AzFramework/Platform/Linux/AzFramework/API/ApplicationAPI_Linux.h b/Code/Framework/AzFramework/Platform/Linux/AzFramework/API/ApplicationAPI_Linux.h index 2c7d6e100c..03c65ce0c3 100644 --- a/Code/Framework/AzFramework/Platform/Linux/AzFramework/API/ApplicationAPI_Linux.h +++ b/Code/Framework/AzFramework/Platform/Linux/AzFramework/API/ApplicationAPI_Linux.h @@ -9,8 +9,13 @@ #pragma once +#include #include +#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB +#include +#endif // LY_COMPILE_DEFINITIONS + namespace AzFramework { class LinuxLifecycleEvents @@ -25,4 +30,31 @@ namespace AzFramework using Bus = AZ::EBus; }; + +#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB + class LinuxXcbConnectionManager + { + public: + AZ_RTTI(LinuxXcbConnectionManager, "{649951316-3626-4C9D-9DCA-2E7ABF84C0A9}"); + + virtual ~LinuxXcbConnectionManager() = default; + + virtual xcb_connection_t* GetXcbConnection() const = 0; + }; + + class LinuxXcbConnectionManagerBusTraits + : public AZ::EBusTraits + { + public: + ////////////////////////////////////////////////////////////////////////// + // EBusTraits overrides + static constexpr AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single; + static constexpr AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single; + ////////////////////////////////////////////////////////////////////////// + }; + + using LinuxXcbConnectionManagerBus = AZ::EBus; + using LinuxXcbConnectionManagerInterface = AZ::Interface; + +#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB } // namespace AzFramework diff --git a/Code/Framework/AzFramework/Platform/Linux/AzFramework/Application/Application_Linux.cpp b/Code/Framework/AzFramework/Platform/Linux/AzFramework/Application/Application_Linux.cpp index 71779444b1..eb4165453e 100644 --- a/Code/Framework/AzFramework/Platform/Linux/AzFramework/Application/Application_Linux.cpp +++ b/Code/Framework/AzFramework/Platform/Linux/AzFramework/Application/Application_Linux.cpp @@ -12,6 +12,32 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// namespace AzFramework { +#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB + class LinuxXcbConnectionManagerImpl + : public LinuxXcbConnectionManagerBus::Handler + { + public: + LinuxXcbConnectionManagerImpl() + { + m_xcbConnection = xcb_connect(nullptr, nullptr); + AZ_Error("ApplicationLinux", m_xcbConnection != nullptr, "Unable to connect to X11 Server."); + LinuxXcbConnectionManagerBus::Handler::BusConnect(); + } + + ~LinuxXcbConnectionManagerImpl() + { + LinuxXcbConnectionManagerBus::Handler::BusDisconnect(); + xcb_disconnect(m_xcbConnection); + } + xcb_connection_t* GetXcbConnection() const override + { + return m_xcbConnection; + } + private: + xcb_connection_t* m_xcbConnection = nullptr; + }; +#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB + //////////////////////////////////////////////////////////////////////////////////////////////// class ApplicationLinux : public Application::Implementation @@ -27,6 +53,12 @@ namespace AzFramework // Application::Implementation void PumpSystemEventLoopOnce() override; void PumpSystemEventLoopUntilEmpty() override; + private: + +#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB + AZStd::unique_ptr m_xcbConnectionManager; +#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB + }; //////////////////////////////////////////////////////////////////////////////////////////////// @@ -39,11 +71,26 @@ namespace AzFramework ApplicationLinux::ApplicationLinux() { LinuxLifecycleEvents::Bus::Handler::BusConnect(); + +#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB + m_xcbConnectionManager = AZStd::make_unique(); + if (LinuxXcbConnectionManagerInterface::Get() == nullptr) + { + LinuxXcbConnectionManagerInterface::Register(m_xcbConnectionManager.get()); + } +#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB } //////////////////////////////////////////////////////////////////////////////////////////////// ApplicationLinux::~ApplicationLinux() { +#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB + if (LinuxXcbConnectionManagerInterface::Get() == m_xcbConnectionManager.get()) + { + LinuxXcbConnectionManagerInterface::Unregister(m_xcbConnectionManager.get()); + } + m_xcbConnectionManager.reset(); +#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB LinuxLifecycleEvents::Bus::Handler::BusDisconnect(); } diff --git a/Code/Framework/AzFramework/Platform/Linux/platform_linux.cmake b/Code/Framework/AzFramework/Platform/Linux/platform_linux.cmake index 7a325ca97e..c79c5f1dff 100644 --- a/Code/Framework/AzFramework/Platform/Linux/platform_linux.cmake +++ b/Code/Framework/AzFramework/Platform/Linux/platform_linux.cmake @@ -5,3 +5,30 @@ # SPDX-License-Identifier: Apache-2.0 OR MIT # # + +# Based on the linux window manager trait, perform the appropriate additional build configurations +# Only 'xcb', 'wayland', and 'xlib' are recognized +if (${PAL_TRAIT_LINUX_WINDOW_MANAGER} STREQUAL "xcb") + + find_library(XCB_LIBRARY xcb) + + set(LY_BUILD_DEPENDENCIES + PRIVATE + ${XCB_LIBRARY} + ) + + set(LY_COMPILE_DEFINITIONS PUBLIC PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB) + +elseif(PAL_TRAIT_LINUX_WINDOW_MANAGER STREQUAL "wayland") + + set(LY_COMPILE_DEFINITIONS PUBLIC PAL_TRAIT_LINUX_WINDOW_MANAGER_WAYLAND) + +elseif(PAL_TRAIT_LINUX_WINDOW_MANAGER STREQUAL "xlib") + + set(LY_COMPILE_DEFINITIONS PUBLIC PAL_TRAIT_LINUX_WINDOW_MANAGER_XLIB) + +else() + + message(FATAL_ERROR, "Linux Window Manager ${PAL_TRAIT_LINUX_WINDOW_MANAGER} is not recognized") + +endif() diff --git a/Gems/Atom/RHI/Vulkan/3rdParty/Platform/Linux/glad_vulkan_linux.cmake b/Gems/Atom/RHI/Vulkan/3rdParty/Platform/Linux/glad_vulkan_linux.cmake index 41de383023..1936c5b911 100644 --- a/Gems/Atom/RHI/Vulkan/3rdParty/Platform/Linux/glad_vulkan_linux.cmake +++ b/Gems/Atom/RHI/Vulkan/3rdParty/Platform/Linux/glad_vulkan_linux.cmake @@ -6,6 +6,18 @@ # # -set(GLAD_VULKAN_COMPILE_DEFINITIONS - VK_USE_PLATFORM_XCB_KHR -) +if (${PAL_TRAIT_LINUX_WINDOW_MANAGER} STREQUAL "xcb") + set(GLAD_VULKAN_COMPILE_DEFINITIONS + VK_USE_PLATFORM_XCB_KHR + ) +elseif(PAL_TRAIT_LINUX_WINDOW_MANAGER STREQUAL "wayland") + set(GLAD_VULKAN_COMPILE_DEFINITIONS + VK_USE_PLATFORM_WAYLAND_KHR + ) +elseif(PAL_TRAIT_LINUX_WINDOW_MANAGER STREQUAL "xlib") + set(GLAD_VULKAN_COMPILE_DEFINITIONS + VK_USE_PLATFORM_XLIB_KHR + ) +else() + message(FATAL_ERROR, "Linux Window Manager ${PAL_TRAIT_LINUX_WINDOW_MANAGER} is not recognized") +endif() diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/Platform/Linux/RHI/WSISurface_Linux.cpp b/Gems/Atom/RHI/Vulkan/Code/Source/Platform/Linux/RHI/WSISurface_Linux.cpp index 87b75d8609..98e91519ea 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/Platform/Linux/RHI/WSISurface_Linux.cpp +++ b/Gems/Atom/RHI/Vulkan/Code/Source/Platform/Linux/RHI/WSISurface_Linux.cpp @@ -5,6 +5,7 @@ * SPDX-License-Identifier: Apache-2.0 OR MIT * */ +#include #include #include #include @@ -17,15 +18,36 @@ namespace AZ { Instance& instance = Instance::GetInstance(); +#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB + + xcb_connection_t* xcb_connection = nullptr; + if (auto xcbConnectionManager = AzFramework::LinuxXcbConnectionManagerInterface::Get(); + xcbConnectionManager != nullptr) + { + xcb_connection = xcbConnectionManager->GetXcbConnection(); + } + AZ_Error("AtomVulkan_RHI", xcb_connection!=nullptr, "Unable to get XCB Connection"); + VkXcbSurfaceCreateInfoKHR createInfo{}; createInfo.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR; createInfo.pNext = nullptr; createInfo.flags = 0; + createInfo.connection = xcb_connection; createInfo.window = static_cast(m_descriptor.m_windowHandle.GetIndex()); const VkResult result = vkCreateXcbSurfaceKHR(instance.GetNativeInstance(), &createInfo, nullptr, &m_nativeSurface); AssertSuccess(result); return ConvertResult(result); +#elif PAL_TRAIT_LINUX_WINDOW_MANAGER_WAYLAND + #error "Linux Window Manager Wayland not supported." + return RHI::ResultCode::Unimplemented; +#elif PAL_TRAIT_LINUX_WINDOW_MANAGER_XLIB + #error "Linux Window Manager XLIB not supported." + return RHI::ResultCode::Unimplemented; +#else + #error "Linux Window Manager not recognized." + return RHI::ResultCode::Unimplemented; +#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB } } } diff --git a/Gems/Atom/TestData/TestData/Materials/SkinTestCases/001_lucy_regression_test.material b/Gems/Atom/TestData/TestData/Materials/SkinTestCases/001_lucy_regression_test.material index c359fea3b5..bafb047be9 100644 --- a/Gems/Atom/TestData/TestData/Materials/SkinTestCases/001_lucy_regression_test.material +++ b/Gems/Atom/TestData/TestData/Materials/SkinTestCases/001_lucy_regression_test.material @@ -30,7 +30,7 @@ }, "normal": { "flipY": true, - "textureMap": "Objects/Lucy/Lucy_normal.png" + "textureMap": "Objects/Lucy/Lucy_Normal.png" }, "subsurfaceScattering": { "enableSubsurfaceScattering": true, diff --git a/Gems/Atom/TestData/TestData/Materials/SkinTestCases/002_wrinkle_regression_test.material b/Gems/Atom/TestData/TestData/Materials/SkinTestCases/002_wrinkle_regression_test.material index ce42f32b67..400044d29f 100644 --- a/Gems/Atom/TestData/TestData/Materials/SkinTestCases/002_wrinkle_regression_test.material +++ b/Gems/Atom/TestData/TestData/Materials/SkinTestCases/002_wrinkle_regression_test.material @@ -29,7 +29,7 @@ }, "normal": { "flipY": true, - "textureMap": "Objects/Lucy/Lucy_normal.png" + "textureMap": "Objects/Lucy/Lucy_Normal.png" }, "subsurfaceScattering": { "enableSubsurfaceScattering": true, diff --git a/cmake/Platform/Linux/PAL_linux.cmake b/cmake/Platform/Linux/PAL_linux.cmake index 2f60b7e2c8..c137538ac0 100644 --- a/cmake/Platform/Linux/PAL_linux.cmake +++ b/cmake/Platform/Linux/PAL_linux.cmake @@ -37,3 +37,7 @@ set(LY_ASSET_DEPLOY_ASSET_TYPE "pc" CACHE STRING "Set the asset type for deploym # Set the python cmd tool ly_set(LY_PYTHON_CMD ${CMAKE_CURRENT_SOURCE_DIR}/python/python.sh) + +# Set the default window manager that applications should be using on Linux +# Note: Only ("xcb", "wayland", or "xlib" should be considered) +set(PAL_TRAIT_LINUX_WINDOW_MANAGER "xcb" CACHE STRING "Sets the Window Manager type to use when configuring Linux (xcb, wayland, or xlib)") From 7f84a4318c5c5a2cc21ca3a8e8718d1350b5513b Mon Sep 17 00:00:00 2001 From: Nicholas Van Sickle Date: Mon, 26 Jul 2021 13:58:50 -0700 Subject: [PATCH 045/160] Add an Orthogonal Projection option to the Camera Gem (#2414) * Add an Orthogonal Projection option to the Camera Gem This adds a check-box to opt into an ortho projection along with a half-width parameter to adjust the size of the visible area. Includes some light tweaks to ensure debug rendering looks OK and that we generate a correct camera state for these non-perspective views. Known issue: while in "Be this camera" mode in the Editor using an ortho projection manipulators aren't working correctly. This appears to be a downstream issue with CameraState consumers not actually checking the ortho flag. Signed-off-by: nvsickle * Fix some typos Signed-off-by: nvsickle * Account for reversed depth buffer Signed-off-by: nvsickle * Clarify depth reversal for MakeOrthographicMatrixRH Signed-off-by: nvsickle --- Code/Editor/EditorViewportWidget.cpp | 13 ++- .../AzCore/AzCore/Math/MatrixUtils.cpp | 7 +- .../AzCore/AzCore/Math/MatrixUtils.h | 3 +- .../AzFramework/Components/CameraBus.h | 16 +++ .../AzToolsFramework/API/EditorCameraBus.h | 7 +- .../Component/DebugCamera/CameraComponent.h | 4 + .../Code/Source/CameraComponent.cpp | 19 ++++ Gems/Camera/Code/Source/CameraComponent.cpp | 6 ++ .../Code/Source/CameraComponentController.cpp | 102 ++++++++++++++---- .../Code/Source/CameraComponentController.h | 11 ++ .../Code/Source/EditorCameraComponent.cpp | 75 +++++++++++-- .../Code/Source/EditorCameraComponent.h | 2 + 12 files changed, 232 insertions(+), 33 deletions(-) diff --git a/Code/Editor/EditorViewportWidget.cpp b/Code/Editor/EditorViewportWidget.cpp index 1f0c87ff6f..357c27fd72 100644 --- a/Code/Editor/EditorViewportWidget.cpp +++ b/Code/Editor/EditorViewportWidget.cpp @@ -463,7 +463,7 @@ void EditorViewportWidget::Update() if (m_updateCameraPositionNextTick) { - auto cameraState = m_renderViewport->GetCameraState(); + auto cameraState = GetCameraState(); AZ::Matrix3x4 matrix; matrix.SetBasisAndTranslation(cameraState.m_side, cameraState.m_forward, cameraState.m_up, cameraState.m_position); auto m = AZMatrix3x4ToLYMatrix3x4(matrix); @@ -1138,6 +1138,17 @@ void EditorViewportWidget::OnMenuSelectCurrentCamera() AzFramework::CameraState EditorViewportWidget::GetCameraState() { + if (m_viewEntityId.IsValid()) + { + bool cameraStateAcquired = false; + AzFramework::CameraState cameraState; + Camera::EditorCameraViewRequestBus::BroadcastResult(cameraStateAcquired, + &Camera::EditorCameraViewRequestBus::Events::GetCameraState, cameraState); + if (cameraStateAcquired) + { + return cameraState; + } + } return m_renderViewport->GetCameraState(); } diff --git a/Code/Framework/AzCore/AzCore/Math/MatrixUtils.cpp b/Code/Framework/AzCore/AzCore/Math/MatrixUtils.cpp index ccdabc9198..a578640d0d 100644 --- a/Code/Framework/AzCore/AzCore/Math/MatrixUtils.cpp +++ b/Code/Framework/AzCore/AzCore/Math/MatrixUtils.cpp @@ -71,7 +71,7 @@ namespace AZ return &out; } - Matrix4x4* MakeOrthographicMatrixRH(Matrix4x4& out, float left, float right, float bottom, float top, float nearDist, float farDist) + Matrix4x4* MakeOrthographicMatrixRH(Matrix4x4& out, float left, float right, float bottom, float top, float nearDist, float farDist, bool reverseDepth) { AZ_Assert(right > left, "right should be greater than left"); // valid to have matrix invert top/bottom and far/near @@ -83,6 +83,11 @@ namespace AZ return nullptr; } + if (reverseDepth) + { + AZStd::swap(nearDist, farDist); + } + out.SetRow(0, 2.f/(right - left), 0.f, 0.f, - (right + left) / (right - left) ); out.SetRow(1, 0.f, 2.f / (top - bottom), 0.f, - (top + bottom) / (top - bottom) ); out.SetRow(2, 0.f, 0.f, 1 / (nearDist - farDist), nearDist / (nearDist - farDist) ); diff --git a/Code/Framework/AzCore/AzCore/Math/MatrixUtils.h b/Code/Framework/AzCore/AzCore/Math/MatrixUtils.h index fc85b7fccc..72a7b29887 100644 --- a/Code/Framework/AzCore/AzCore/Math/MatrixUtils.h +++ b/Code/Framework/AzCore/AzCore/Math/MatrixUtils.h @@ -57,8 +57,9 @@ namespace AZ //! @param top The y coordinate of top view-plane //! @param near Distance to the near view-plane. Must be no less than zero. //! @param far Distance to the far view-plane. Must be greater than zero. + //! @param reverseDepth Set to true to reverse depth which means near distance maps to 1 and far distance maps to 0. //! @return Pointer of the output matrix - Matrix4x4* MakeOrthographicMatrixRH(Matrix4x4& out, float left, float right, float bottom, float top, float nearDist, float farDist); + Matrix4x4* MakeOrthographicMatrixRH(Matrix4x4& out, float left, float right, float bottom, float top, float nearDist, float farDist, bool reverseDepth = false); //! Transforms a position by a matrix. This function can be used with any generic cases which include projection matrices. Vector3 MatrixTransformPosition(const Matrix4x4& matrix, const Vector3& inPosition); diff --git a/Code/Framework/AzFramework/AzFramework/Components/CameraBus.h b/Code/Framework/AzFramework/AzFramework/Components/CameraBus.h index 618aa76401..0b2a0cbb78 100644 --- a/Code/Framework/AzFramework/AzFramework/Components/CameraBus.h +++ b/Code/Framework/AzFramework/AzFramework/Components/CameraBus.h @@ -63,6 +63,13 @@ namespace Camera //! @return The camera frustum's height virtual float GetFrustumHeight() = 0; + //! Gets whether or not the camera is using an orthographic projection. + //! @return True if the camera is using an orthographic projection, or false if the camera is using a perspective projection. + virtual bool IsOrthographic() = 0; + + //! @return The half width of the orthographic projection, @see SetOrthographicHalfWidth. + virtual float GetOrthographicHalfWidth() = 0; + //! Sets the camera's field of view in degrees between 0 < fov < 180 degrees //! @param fov The camera frustum's new field of view in degrees virtual void SetFov(float fov) @@ -95,6 +102,15 @@ namespace Camera //! @param height The camera frustum's new height virtual void SetFrustumHeight(float height) = 0; + //! Sets whether or not the camera should use an orthographic projection in place of a perspective projection. + //! @param orthographic If true, the camera will use an orthographic projection + virtual void SetOrthographic(bool orthographic) = 0; + + //! Sets the half-width of the orthographic projection. + //! @params halfWidth Used to calculate the bounds of the projection while in orthographic mode. + //! The height is calculated automatically based on the aspect ratio. + virtual void SetOrthographicHalfWidth(float halfWidth) = 0; + //! Makes the camera the active view virtual void MakeActiveView() = 0; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/API/EditorCameraBus.h b/Code/Framework/AzToolsFramework/AzToolsFramework/API/EditorCameraBus.h index cb4a003fb4..60d19dfd85 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/API/EditorCameraBus.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/API/EditorCameraBus.h @@ -102,7 +102,7 @@ namespace Camera using EditorCameraNotificationBus = AZ::EBus; /** - * This bus is for requesting any camera-view-related changes + * This bus is for requesting any camera-view-related changes or information */ class EditorCameraViewRequests : public AZ::ComponentBus { @@ -115,6 +115,11 @@ namespace Camera * Sets this camera as the active view in the scene, otherwise restores the default editor camera if it was already active */ virtual void ToggleCameraAsActiveView() = 0; + + /** + * Gets the camera state associated with this view. + */ + virtual bool GetCameraState(AzFramework::CameraState& cameraState) = 0; }; using EditorCameraViewRequestBus = AZ::EBus; diff --git a/Gems/Atom/Component/DebugCamera/Code/Include/Atom/Component/DebugCamera/CameraComponent.h b/Gems/Atom/Component/DebugCamera/Code/Include/Atom/Component/DebugCamera/CameraComponent.h index 6f8484de9f..d5c84c7441 100644 --- a/Gems/Atom/Component/DebugCamera/Code/Include/Atom/Component/DebugCamera/CameraComponent.h +++ b/Gems/Atom/Component/DebugCamera/Code/Include/Atom/Component/DebugCamera/CameraComponent.h @@ -92,12 +92,16 @@ namespace AZ float GetFarClipDistance() override; float GetFrustumWidth() override; float GetFrustumHeight() override; + bool IsOrthographic() override; + float GetOrthographicHalfWidth() override; void SetFovDegrees(float fov) override; void SetFovRadians(float fov) override; void SetNearClipDistance(float nearClipDistance) override; void SetFarClipDistance(float farClipDistance) override; void SetFrustumWidth(float width) override; void SetFrustumHeight(float height) override; + void SetOrthographic(bool orthographic) override; + void SetOrthographicHalfWidth(float halfWidth) override; void MakeActiveView() override; // RPI::WindowContextNotificationBus overrides... diff --git a/Gems/Atom/Component/DebugCamera/Code/Source/CameraComponent.cpp b/Gems/Atom/Component/DebugCamera/Code/Source/CameraComponent.cpp index 27359ebdce..9a6f7c83ab 100644 --- a/Gems/Atom/Component/DebugCamera/Code/Source/CameraComponent.cpp +++ b/Gems/Atom/Component/DebugCamera/Code/Source/CameraComponent.cpp @@ -185,6 +185,15 @@ namespace AZ return m_componentConfig.m_depthFar * tanf(m_componentConfig.m_fovY / 2) * 2; } + bool CameraComponent::IsOrthographic() + { + return false; + } + + float CameraComponent::GetOrthographicHalfWidth() + { + return 0.0f; + } void CameraComponent::SetFovDegrees(float fov) { @@ -226,6 +235,16 @@ namespace AZ UpdateViewToClipMatrix(); } + void CameraComponent::SetOrthographic(bool orthographic) + { + AZ_Assert(!orthographic, "DebugCamera does not support orthographic projection"); + } + + void CameraComponent::SetOrthographicHalfWidth([[maybe_unused]] float halfWidth) + { + AZ_Assert(false, "DebugCamera does not support orthographic projection"); + } + void CameraComponent::MakeActiveView() { // do nothing diff --git a/Gems/Camera/Code/Source/CameraComponent.cpp b/Gems/Camera/Code/Source/CameraComponent.cpp index 814fd1c4e7..04c245bc95 100644 --- a/Gems/Camera/Code/Source/CameraComponent.cpp +++ b/Gems/Camera/Code/Source/CameraComponent.cpp @@ -103,9 +103,15 @@ namespace Camera ->Event("SetNearClipDistance", &CameraRequestBus::Events::SetNearClipDistance) ->Event("SetFarClipDistance", &CameraRequestBus::Events::SetFarClipDistance) ->Event("MakeActiveView", &CameraRequestBus::Events::MakeActiveView) + ->Event("IsOrthographic", &CameraRequestBus::Events::IsOrthographic) + ->Event("SetOrthographic", &CameraRequestBus::Events::SetOrthographic) + ->Event("GetOrthographicHalfWidth", &CameraRequestBus::Events::GetOrthographicHalfWidth) + ->Event("SetOrthographicHalfWidth", &CameraRequestBus::Events::SetOrthographicHalfWidth) ->VirtualProperty("FieldOfView","GetFovDegrees","SetFovDegrees") ->VirtualProperty("NearClipDistance", "GetNearClipDistance", "SetNearClipDistance") ->VirtualProperty("FarClipDistance", "GetFarClipDistance", "SetFarClipDistance") + ->VirtualProperty("Orthographic", "IsOrthographic", "SetOrthographic") + ->VirtualProperty("OrthographicHalfWidth", "GetOrthographicHalfWidth", "SetOrthographicHalfWidth") ; behaviorContext->Class()->RequestBus("CameraRequestBus"); diff --git a/Gems/Camera/Code/Source/CameraComponentController.cpp b/Gems/Camera/Code/Source/CameraComponentController.cpp index dbcc7fe6f1..bbe8235449 100644 --- a/Gems/Camera/Code/Source/CameraComponentController.cpp +++ b/Gems/Camera/Code/Source/CameraComponentController.cpp @@ -24,7 +24,9 @@ namespace Camera if (auto serializeContext = azrtti_cast(context)) { serializeContext->Class() - ->Version(2) + ->Version(3) + ->Field("Orthographic", &CameraComponentConfig::m_orthographic) + ->Field("Orthographic Half Width", &CameraComponentConfig::m_orthographicHalfWidth) ->Field("Field of View", &CameraComponentConfig::m_fov) ->Field("Near Clip Plane Distance", &CameraComponentConfig::m_nearClipDistance) ->Field("Far Clip Plane Distance", &CameraComponentConfig::m_farClipDistance) @@ -42,25 +44,33 @@ namespace Camera ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly) ->DataElement(AZ::Edit::UIHandlers::Default, &CameraComponentConfig::m_makeActiveViewOnActivation, "Make active camera on activation?", "If true, this camera will become the active render camera when it activates") + ->DataElement(AZ::Edit::UIHandlers::Default, &CameraComponentConfig::m_orthographic, "Orthographic", + "If set, this camera will use an orthographic projection instead of a perspective one. Objects will appear as the same size, regardless of distance from the camera.") + ->Attribute(AZ::Edit::Attributes::ChangeNotify, AZ::Edit::PropertyRefreshLevels::EntireTree) + ->DataElement(AZ::Edit::UIHandlers::Default, &CameraComponentConfig::m_orthographicHalfWidth, "Orthographic Half-width", "The half-width used to calculate the orthographic projection. The height will be determined by the aspect ratio.") + ->Attribute(AZ::Edit::Attributes::Visibility, &CameraComponentConfig::GetOrthographicParameterVisibility) + ->Attribute(AZ::Edit::Attributes::Min, 0.001f) + ->Attribute(AZ::Edit::Attributes::ChangeNotify, AZ::Edit::PropertyRefreshLevels::ValuesOnly) ->DataElement(AZ::Edit::UIHandlers::Default, &CameraComponentConfig::m_fov, "Field of view", "Vertical field of view in degrees") ->Attribute(AZ::Edit::Attributes::Min, MIN_FOV) ->Attribute(AZ::Edit::Attributes::Suffix, " degrees") ->Attribute(AZ::Edit::Attributes::Step, 1.f) ->Attribute(AZ::Edit::Attributes::Max, AZ::RadToDeg(AZ::Constants::Pi) - 0.0001f) //We assert at fovs >= Pi so set the max for this field to be just under that - ->Attribute(AZ::Edit::Attributes::ChangeNotify, AZ_CRC("RefreshValues", 0x28e720d4)) + ->Attribute(AZ::Edit::Attributes::ChangeNotify, AZ::Edit::PropertyRefreshLevels::ValuesOnly) + ->Attribute(AZ::Edit::Attributes::Visibility, &CameraComponentConfig::GetPerspectiveParameterVisibility) ->DataElement(AZ::Edit::UIHandlers::Default, &CameraComponentConfig::m_nearClipDistance, "Near clip distance", "Distance to the near clip plane of the view Frustum") ->Attribute(AZ::Edit::Attributes::Min, CAMERA_MIN_NEAR) ->Attribute(AZ::Edit::Attributes::Suffix, " m") ->Attribute(AZ::Edit::Attributes::Step, 0.1f) ->Attribute(AZ::Edit::Attributes::Max, &CameraComponentConfig::GetFarClipDistance) - ->Attribute(AZ::Edit::Attributes::ChangeNotify, AZ_CRC("RefreshAttributesAndValues", 0xcbc2147c)) + ->Attribute(AZ::Edit::Attributes::ChangeNotify, AZ::Edit::PropertyRefreshLevels::AttributesAndValues) ->DataElement(AZ::Edit::UIHandlers::Default, &CameraComponentConfig::m_farClipDistance, "Far clip distance", "Distance to the far clip plane of the view Frustum") ->Attribute(AZ::Edit::Attributes::Min, &CameraComponentConfig::GetNearClipDistance) ->Attribute(AZ::Edit::Attributes::Suffix, " m") ->Attribute(AZ::Edit::Attributes::Step, 10.f) - ->Attribute(AZ::Edit::Attributes::ChangeNotify, AZ_CRC("RefreshAttributesAndValues", 0xcbc2147c)) + ->Attribute(AZ::Edit::Attributes::ChangeNotify, AZ::Edit::PropertyRefreshLevels::AttributesAndValues) ; } } @@ -81,6 +91,16 @@ namespace Camera return AZ::EntityId(m_editorEntityId); } + AZ::u32 CameraComponentConfig::GetPerspectiveParameterVisibility() const + { + return m_orthographic ? AZ::Edit::PropertyVisibility::Hide : AZ::Edit::PropertyVisibility::Show; + } + + AZ::u32 CameraComponentConfig::GetOrthographicParameterVisibility() const + { + return m_orthographic ? AZ::Edit::PropertyVisibility::Show : AZ::Edit::PropertyVisibility::Hide; + } + CameraComponentController::CameraComponentController(const CameraComponentConfig& config) { SetConfiguration(config); @@ -289,6 +309,16 @@ namespace Camera return m_config; } + AZ::RPI::ViewportContextPtr CameraComponentController::GetViewportContext() + { + auto atomViewportRequests = AZ::Interface::Get(); + if (m_atomCamera && atomViewportRequests) + { + return atomViewportRequests->GetDefaultViewportContext(); + } + return nullptr; + } + AZ::EntityId CameraComponentController::GetCameras() { return m_entityId; @@ -324,6 +354,16 @@ namespace Camera return m_config.m_frustumHeight; } + bool CameraComponentController::IsOrthographic() + { + return m_config.m_orthographic; + } + + float CameraComponentController::GetOrthographicHalfWidth() + { + return m_config.m_orthographicHalfWidth; + } + void CameraComponentController::SetFovDegrees(float fov) { m_config.m_fov = AZ::GetClamp(fov, MinFoV, MaxFoV); @@ -359,6 +399,18 @@ namespace Camera UpdateCamera(); } + void CameraComponentController::SetOrthographic(bool orthographic) + { + m_config.m_orthographic = orthographic; + UpdateCamera(); + } + + void CameraComponentController::SetOrthographicHalfWidth(float halfWidth) + { + m_config.m_orthographicHalfWidth = halfWidth; + UpdateCamera(); + } + void CameraComponentController::MakeActiveView() { // Set Legacy Cry view, if it exists @@ -423,30 +475,38 @@ namespace Camera m_view->SetCurrentParams(viewParams); } - auto atomViewportRequests = AZ::Interface::Get(); - if (m_atomCamera && atomViewportRequests) + if (auto viewportContext = GetViewportContext()) { AZ::Matrix4x4 viewToClipMatrix; float aspectRatio = m_view ? m_view->GetCamera().GetPixelAspectRatio() : 1.f; - auto viewportContext = atomViewportRequests->GetViewportContextByName( - atomViewportRequests->GetDefaultViewportContextName()); - if (viewportContext) + if (!m_atomAuxGeom) { - if (!m_atomAuxGeom) - { - SetupAtomAuxGeom(viewportContext); - } - auto windowSize = viewportContext->GetViewportSize(); - aspectRatio = aznumeric_cast(windowSize.m_width) / aznumeric_cast(windowSize.m_height); + SetupAtomAuxGeom(viewportContext); } + auto windowSize = viewportContext->GetViewportSize(); + aspectRatio = aznumeric_cast(windowSize.m_width) / aznumeric_cast(windowSize.m_height); // This assumes a reversed depth buffer, in line with other LY Atom integration - AZ::MakePerspectiveFovMatrixRH(viewToClipMatrix, - AZ::DegToRad(m_config.m_fov), - aspectRatio, - m_config.m_nearClipDistance, - m_config.m_farClipDistance, - true); + if (m_config.m_orthographic) + { + AZ::MakeOrthographicMatrixRH(viewToClipMatrix, + -m_config.m_orthographicHalfWidth, + m_config.m_orthographicHalfWidth, + -m_config.m_orthographicHalfWidth / aspectRatio, + m_config.m_orthographicHalfWidth / aspectRatio, + m_config.m_nearClipDistance, + m_config.m_farClipDistance, + true); + } + else + { + AZ::MakePerspectiveFovMatrixRH(viewToClipMatrix, + AZ::DegToRad(m_config.m_fov), + aspectRatio, + m_config.m_nearClipDistance, + m_config.m_farClipDistance, + true); + } m_updatingTransformFromEntity = true; m_atomCamera->SetViewToClipMatrix(viewToClipMatrix); m_updatingTransformFromEntity = false; diff --git a/Gems/Camera/Code/Source/CameraComponentController.h b/Gems/Camera/Code/Source/CameraComponentController.h index 7f4e419176..c004dbe6ec 100644 --- a/Gems/Camera/Code/Source/CameraComponentController.h +++ b/Gems/Camera/Code/Source/CameraComponentController.h @@ -40,6 +40,9 @@ namespace Camera float GetNearClipDistance() const; AZ::EntityId GetEditorEntityId() const; + AZ::u32 GetPerspectiveParameterVisibility() const; + AZ::u32 GetOrthographicParameterVisibility() const; + // Reflected members float m_fov = DefaultFoV; float m_nearClipDistance = DefaultNearPlaneDistance; @@ -49,6 +52,8 @@ namespace Camera bool m_specifyFrustumDimensions = false; AZ::u64 m_editorEntityId = AZ::EntityId::InvalidEntityId; bool m_makeActiveViewOnActivation = true; + bool m_orthographic = false; + float m_orthographicHalfWidth = 5.f; }; class CameraComponentController @@ -78,6 +83,7 @@ namespace Camera void Deactivate(); void SetConfiguration(const CameraComponentConfig& config); const CameraComponentConfig& GetConfiguration() const; + AZ::RPI::ViewportContextPtr GetViewportContext(); // CameraBus::Handler interface AZ::EntityId GetCameras() override; @@ -89,12 +95,17 @@ namespace Camera float GetFarClipDistance() override; float GetFrustumWidth() override; float GetFrustumHeight() override; + bool IsOrthographic() override; + float GetOrthographicHalfWidth() override; void SetFovDegrees(float fov) override; void SetFovRadians(float fov) override; void SetNearClipDistance(float nearClipDistance) override; void SetFarClipDistance(float farClipDistance) override; void SetFrustumWidth(float width) override; void SetFrustumHeight(float height) override; + void SetOrthographic(bool orthographic) override; + void SetOrthographicHalfWidth(float halfWidth) override; + void MakeActiveView() override; // AZ::TransformNotificationBus::Handler interface diff --git a/Gems/Camera/Code/Source/EditorCameraComponent.cpp b/Gems/Camera/Code/Source/EditorCameraComponent.cpp index beed4d7097..14e8e46e72 100644 --- a/Gems/Camera/Code/Source/EditorCameraComponent.cpp +++ b/Gems/Camera/Code/Source/EditorCameraComponent.cpp @@ -17,6 +17,9 @@ #include #include +#include +#include + namespace Camera { namespace ClassConverters @@ -155,6 +158,42 @@ namespace Camera } } + bool EditorCameraComponent::GetCameraState(AzFramework::CameraState& cameraState) + { + const CameraComponentConfig& config = m_controller.GetConfiguration(); + AZ::RPI::ViewportContextPtr viewportContext = m_controller.GetViewportContext(); + AZ::RPI::ViewPtr view = m_controller.GetView(); + + if (viewportContext == nullptr || view == nullptr) + { + return false; + } + + AzFramework::SetCameraTransform(cameraState, view->GetCameraTransform()); + + { + const AzFramework::WindowSize viewportSize = viewportContext->GetViewportSize(); + cameraState.m_viewportSize = + AZ::Vector2{aznumeric_cast(viewportSize.m_width), aznumeric_cast(viewportSize.m_height)}; + } + + if (config.m_orthographic) + { + cameraState.m_fovOrZoom = cameraState.m_viewportSize.GetX() / (config.m_orthographicHalfWidth * 2.0f); + cameraState.m_orthographic = true; + } + else + { + cameraState.m_fovOrZoom = config.m_fov; + cameraState.m_orthographic = false; + } + + cameraState.m_nearClip = config.m_nearClipDistance; + cameraState.m_farClip = config.m_farClipDistance; + + return true; + } + AZ::Crc32 EditorCameraComponent::OnPossessCameraButtonClicked() { AZ::EntityId currentViewEntity; @@ -201,9 +240,20 @@ namespace Camera const CameraComponentConfig& config = m_controller.GetConfiguration(); const float distance = config.m_farClipDistance * m_frustumViewPercentLength * 0.01f; - float tangent = static_cast(tan(0.5f * AZ::DegToRad(config.m_fov))); - float height = distance * tangent; - float width = height * debugDisplay.GetAspectRatio(); + float width; + float height; + + if (config.m_orthographic) + { + width = config.m_orthographicHalfWidth; + height = width / debugDisplay.GetAspectRatio(); + } + else + { + const float tangent = static_cast(tan(0.5f * AZ::DegToRad(config.m_fov))); + height = distance * tangent; + width = height * debugDisplay.GetAspectRatio(); + } AZ::Vector3 farPoints[4]; farPoints[0] = AZ::Vector3( width, distance, height); @@ -211,12 +261,21 @@ namespace Camera farPoints[2] = AZ::Vector3(-width, distance, -height); farPoints[3] = AZ::Vector3( width, distance, -height); - AZ::Vector3 start(0, 0, 0); AZ::Vector3 nearPoints[4]; - nearPoints[0] = farPoints[0].GetNormalizedSafe() * config.m_nearClipDistance; - nearPoints[1] = farPoints[1].GetNormalizedSafe() * config.m_nearClipDistance; - nearPoints[2] = farPoints[2].GetNormalizedSafe() * config.m_nearClipDistance; - nearPoints[3] = farPoints[3].GetNormalizedSafe() * config.m_nearClipDistance; + if (config.m_orthographic) + { + nearPoints[0] = AZ::Vector3( width, config.m_nearClipDistance, height); + nearPoints[1] = AZ::Vector3(-width, config.m_nearClipDistance, height); + nearPoints[2] = AZ::Vector3(-width, config.m_nearClipDistance, -height); + nearPoints[3] = AZ::Vector3( width, config.m_nearClipDistance, -height); + } + else + { + nearPoints[0] = farPoints[0].GetNormalizedSafe() * config.m_nearClipDistance; + nearPoints[1] = farPoints[1].GetNormalizedSafe() * config.m_nearClipDistance; + nearPoints[2] = farPoints[2].GetNormalizedSafe() * config.m_nearClipDistance; + nearPoints[3] = farPoints[3].GetNormalizedSafe() * config.m_nearClipDistance; + } debugDisplay.PushMatrix(world); debugDisplay.SetColor(m_frustumDrawColor.GetAsVector4()); diff --git a/Gems/Camera/Code/Source/EditorCameraComponent.h b/Gems/Camera/Code/Source/EditorCameraComponent.h index bf788256a9..095427a4a7 100644 --- a/Gems/Camera/Code/Source/EditorCameraComponent.h +++ b/Gems/Camera/Code/Source/EditorCameraComponent.h @@ -58,7 +58,9 @@ namespace Camera /// EditorCameraNotificationBus::Handler interface void OnViewportViewEntityChanged(const AZ::EntityId& newViewId) override; + /// EditorCameraViewRequestBus::Handler interface void ToggleCameraAsActiveView() override { OnPossessCameraButtonClicked(); } + bool GetCameraState(AzFramework::CameraState& cameraState) override; protected: void EditorDisplay(AzFramework::DebugDisplayRequests& displayInterface, const AZ::Transform& world); From da474357f3d0ae9d9c3e884a397ccdcaec7e9be6 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Mon, 26 Jul 2021 14:14:56 -0700 Subject: [PATCH 046/160] =?UTF-8?q?Some=20var=20cleanup=20so=20it=20shows?= =?UTF-8?q?=20better-organized=20in=20cmake-gui.=20Some=20vars=E2=80=A6=20?= =?UTF-8?q?(#2361)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Some var cleanup so it shows better-organized in cmake-gui. Some vars were also not following the namign convention we are using Removed some unnecessary messaging Fixed a TIF bug where it would report the wrong test in a message, fixed a message that was being triggered Changed TIF to be enabled just by the binary so running the ci_build scripts locally doesnt trigger TIF messaging Removed `LY_ENABLE_MULTIPLAYER_COMPRESSION`, it was not being used Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> * handling case where a parameter can be empty Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> * needs to be var name, not contents Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Framework/AzCore/CMakeLists.txt | 2 +- .../profile_telemetry_platform_android.cmake | 2 +- .../Mac/profile_telemetry_platform_mac.cmake | 2 +- .../profile_telemetry_platform_windows.cmake | 2 +- .../iOS/profile_telemetry_platform_ios.cmake | 2 +- Code/Framework/AzFramework/CMakeLists.txt | 4 ++-- Code/Tools/TestImpactFramework/CMakeLists.txt | 8 +++++--- Gems/AudioEngineWwise/Code/CMakeLists.txt | 3 --- Gems/MultiplayerCompression/Code/CMakeLists.txt | 2 -- Gems/RADTelemetry/Code/CMakeLists.txt | 5 +++-- cmake/3rdParty/FindWwise.cmake | 6 ++---- cmake/Deployment.cmake | 2 +- cmake/EngineJson.cmake | 3 ++- cmake/FileUtil.cmake | 2 +- cmake/O3DEJson.cmake | 2 -- cmake/Platform/Windows/Packaging_windows.cmake | 8 ++++---- .../LYTestImpactFramework.cmake | 14 ++++++-------- scripts/build/Platform/Windows/build_config.json | 4 ++-- scripts/ctest/CMakeLists.txt | 1 + 19 files changed, 34 insertions(+), 40 deletions(-) diff --git a/Code/Framework/AzCore/CMakeLists.txt b/Code/Framework/AzCore/CMakeLists.txt index ff8a825aab..ea7cc27af5 100644 --- a/Code/Framework/AzCore/CMakeLists.txt +++ b/Code/Framework/AzCore/CMakeLists.txt @@ -12,7 +12,7 @@ ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME}) ly_get_list_relative_pal_filename(common_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/Common) -if(LY_ENABLE_RAD_TELEMETRY) +if(LY_RAD_TELEMETRY_ENABLED) set(AZ_CORE_RADTELEMETRY_FILES ${common_dir}/azcore_profile_telemetry_files.cmake) set(AZ_CORE_RADTELEMETRY_PLATFORM_INCLUDES ${pal_dir}/profile_telemetry_platform_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) set(AZ_CORE_RADTELEMETRY_INCLUDE_DIRECTORIES ${common_dir}) diff --git a/Code/Framework/AzCore/Platform/Android/profile_telemetry_platform_android.cmake b/Code/Framework/AzCore/Platform/Android/profile_telemetry_platform_android.cmake index 5b74429383..df12777586 100644 --- a/Code/Framework/AzCore/Platform/Android/profile_telemetry_platform_android.cmake +++ b/Code/Framework/AzCore/Platform/Android/profile_telemetry_platform_android.cmake @@ -12,6 +12,6 @@ # is being avoided to prevent overriding functions declared in other targets platfrom # specific cmake files -if(LY_ENABLE_RAD_TELEMETRY) +if(LY_RAD_TELEMETRY_ENABLED) set(LY_COMPILE_DEFINITIONS PUBLIC AZ_PROFILE_TELEMETRY) endif() diff --git a/Code/Framework/AzCore/Platform/Mac/profile_telemetry_platform_mac.cmake b/Code/Framework/AzCore/Platform/Mac/profile_telemetry_platform_mac.cmake index 5b74429383..df12777586 100644 --- a/Code/Framework/AzCore/Platform/Mac/profile_telemetry_platform_mac.cmake +++ b/Code/Framework/AzCore/Platform/Mac/profile_telemetry_platform_mac.cmake @@ -12,6 +12,6 @@ # is being avoided to prevent overriding functions declared in other targets platfrom # specific cmake files -if(LY_ENABLE_RAD_TELEMETRY) +if(LY_RAD_TELEMETRY_ENABLED) set(LY_COMPILE_DEFINITIONS PUBLIC AZ_PROFILE_TELEMETRY) endif() diff --git a/Code/Framework/AzCore/Platform/Windows/profile_telemetry_platform_windows.cmake b/Code/Framework/AzCore/Platform/Windows/profile_telemetry_platform_windows.cmake index 5b74429383..df12777586 100644 --- a/Code/Framework/AzCore/Platform/Windows/profile_telemetry_platform_windows.cmake +++ b/Code/Framework/AzCore/Platform/Windows/profile_telemetry_platform_windows.cmake @@ -12,6 +12,6 @@ # is being avoided to prevent overriding functions declared in other targets platfrom # specific cmake files -if(LY_ENABLE_RAD_TELEMETRY) +if(LY_RAD_TELEMETRY_ENABLED) set(LY_COMPILE_DEFINITIONS PUBLIC AZ_PROFILE_TELEMETRY) endif() diff --git a/Code/Framework/AzCore/Platform/iOS/profile_telemetry_platform_ios.cmake b/Code/Framework/AzCore/Platform/iOS/profile_telemetry_platform_ios.cmake index 1a12c4b4e0..aeb91ebce6 100644 --- a/Code/Framework/AzCore/Platform/iOS/profile_telemetry_platform_ios.cmake +++ b/Code/Framework/AzCore/Platform/iOS/profile_telemetry_platform_ios.cmake @@ -6,6 +6,6 @@ # # -if(LY_ENABLE_RAD_TELEMETRY) +if(LY_RAD_TELEMETRY_ENABLED) set(LY_COMPILE_DEFINITIONS PUBLIC AZ_PROFILE_TELEMETRY) endif() diff --git a/Code/Framework/AzFramework/CMakeLists.txt b/Code/Framework/AzFramework/CMakeLists.txt index 8e80234263..8a68aac887 100644 --- a/Code/Framework/AzFramework/CMakeLists.txt +++ b/Code/Framework/AzFramework/CMakeLists.txt @@ -10,7 +10,7 @@ ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME}) ly_get_list_relative_pal_filename(common_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/Common) -set(LY_ENABLE_STATISTICAL_PROFILING OFF CACHE BOOL "Enables statistical profiling when using AZ_PROFILE_SCOPE. If True, it takes effect only if RAD Telemetry is disabled.") +set(LY_STATISTICAL_PROFILING_ENABLED OFF CACHE BOOL "Enables statistical profiling when using AZ_PROFILE_SCOPE. If True, it takes effect only if RAD Telemetry is disabled.") set(LY_TOUCHBENDING_LAYER_BIT 63 CACHE STRING "Use TouchBending as the collision layer. The TouchBending layer can be a number from 1 to 63 (Default=63).") ly_add_target( @@ -38,7 +38,7 @@ ly_add_target( 3rdParty::lz4 ) -if(LY_ENABLE_STATISTICAL_PROFILING) +if(LY_STATISTICAL_PROFILING_ENABLED) ly_add_source_properties( SOURCES AzFramework/Debug/StatisticalProfilerProxy.h PROPERTY COMPILE_DEFINITIONS diff --git a/Code/Tools/TestImpactFramework/CMakeLists.txt b/Code/Tools/TestImpactFramework/CMakeLists.txt index 1fc59d1711..04cbee98dc 100644 --- a/Code/Tools/TestImpactFramework/CMakeLists.txt +++ b/Code/Tools/TestImpactFramework/CMakeLists.txt @@ -10,7 +10,9 @@ ly_get_list_relative_pal_filename(pal_source_dir ${CMAKE_CURRENT_LIST_DIR}/Platf include(${pal_source_dir}/PAL_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) -if(${LY_TEST_IMPACT_ACTIVE} AND PAL_TRAIT_TEST_IMPACT_FRAMEWORK_SUPPORTED) - add_subdirectory(Runtime) - add_subdirectory(Frontend) +if(PAL_TRAIT_TEST_IMPACT_FRAMEWORK_SUPPORTED) + if(LY_TEST_IMPACT_INSTRUMENTATION_BIN) + add_subdirectory(Runtime) + add_subdirectory(Frontend) + endif() endif() diff --git a/Gems/AudioEngineWwise/Code/CMakeLists.txt b/Gems/AudioEngineWwise/Code/CMakeLists.txt index c6442df1ba..98a31fb91a 100644 --- a/Gems/AudioEngineWwise/Code/CMakeLists.txt +++ b/Gems/AudioEngineWwise/Code/CMakeLists.txt @@ -16,9 +16,6 @@ set(AUDIOENGINEWWISE_COMPILEDEFINITIONS ) find_package(Wwise MODULE) -if (NOT Wwise_FOUND) - message(STATUS "** Update the LY_WWISE_INSTALL_PATH cache variable if you intend to use Wwise.") -endif() ################################################################################ # Server / Unsupported diff --git a/Gems/MultiplayerCompression/Code/CMakeLists.txt b/Gems/MultiplayerCompression/Code/CMakeLists.txt index 405d92e683..f7494be3fd 100644 --- a/Gems/MultiplayerCompression/Code/CMakeLists.txt +++ b/Gems/MultiplayerCompression/Code/CMakeLists.txt @@ -6,8 +6,6 @@ # # -set(LY_ENABLE_MULTIPLAYER_COMPRESSION OFF CACHE BOOL "Enables usage of Multiplayer Compressor.") - ly_add_target( NAME MultiplayerCompression.Static STATIC NAMESPACE Gem diff --git a/Gems/RADTelemetry/Code/CMakeLists.txt b/Gems/RADTelemetry/Code/CMakeLists.txt index 3b65d6d47a..544540f273 100644 --- a/Gems/RADTelemetry/Code/CMakeLists.txt +++ b/Gems/RADTelemetry/Code/CMakeLists.txt @@ -6,8 +6,9 @@ # # -set(LY_ENABLE_RAD_TELEMETRY OFF CACHE BOOL "Enables RAD Telemetry in Debug/Profile mode.") -set(LY_RAD_TELEMETRY_INSTALL_ROOT "${LY_3RDPARTY_PATH}/RadTelemetry" CACHE PATH "Install path to RAD Telemetry.") +set(LY_RAD_TELEMETRY_ENABLED OFF CACHE BOOL "Enables RAD Telemetry in Debug/Profile mode.") +set(LY_RAD_TELEMETRY_INSTALL_ROOT "@LY_3RDPARTY_PATH@/RadTelemetry" CACHE PATH "Install path to RAD Telemetry.") +string(CONFIGURE ${LY_RAD_TELEMETRY_INSTALL_ROOT} LY_RAD_TELEMETRY_INSTALL_ROOT @ONLY) ly_get_list_relative_pal_filename(pal_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME}) diff --git a/cmake/3rdParty/FindWwise.cmake b/cmake/3rdParty/FindWwise.cmake index fa73ced3cc..8cd6db31dd 100644 --- a/cmake/3rdParty/FindWwise.cmake +++ b/cmake/3rdParty/FindWwise.cmake @@ -44,7 +44,7 @@ foreach(test_path ${WWISE_SDK_PATHS}) is_valid_sdk(${test_path} found_sdk) if(found_sdk) # Update the Wwise Install Path cache variable - set(LY_WWISE_INSTALL_PATH "${test_path}" CACHE PATH "Path to Wwise version ${WWISE_VERSION} installation." FORCE) + set(LY_WWISE_INSTALL_PATH "${test_path}") break() endif() endforeach() @@ -52,12 +52,10 @@ endforeach() if(NOT found_sdk) # If we don't find a path that appears to be a valid Wwise install, we can bail here. # No 3rdParty::Wwise target will exist, so that can be checked elsewhere. - message(STATUS "Wwise SDK version ${WWISE_VERSION} was not found.") return() -else() - message(STATUS "Using Wwise SDK at ${LY_WWISE_INSTALL_PATH}") endif() +message(STATUS "Using Wwise SDK at ${LY_WWISE_INSTALL_PATH}") set(WWISE_COMMON_LIB_NAMES # Core AK diff --git a/cmake/Deployment.cmake b/cmake/Deployment.cmake index ab18e3bfec..b6b7aa1869 100644 --- a/cmake/Deployment.cmake +++ b/cmake/Deployment.cmake @@ -9,6 +9,6 @@ # Define options that control the different options for deployment for target platforms set(LY_ASSET_DEPLOY_MODE "LOOSE" CACHE STRING "Set the Asset deployment when deploying to the target platform (LOOSE, PAK, VFS)") -set(LY_OVERRIDE_PAK_FOLDER_ROOT "" CACHE STRING "Optional root path to where Pak file folders are stored. By default, blank will use a predefined 'paks' root.") +set(LY_ASSET_OVERRIDE_PAK_FOLDER_ROOT "" CACHE STRING "Optional root path to where Pak file folders are stored. By default, blank will use a predefined 'paks' root.") diff --git a/cmake/EngineJson.cmake b/cmake/EngineJson.cmake index 180a6395b0..f175ff5a8b 100644 --- a/cmake/EngineJson.cmake +++ b/cmake/EngineJson.cmake @@ -10,7 +10,8 @@ include_guard() -set(LY_EXTERNAL_SUBDIRS "" CACHE STRING "List of subdirectories to recurse into when running cmake against the engine's CMakeLists.txt") +set(LY_EXTERNAL_SUBDIRS "" CACHE STRING "Additional list of subdirectory to recurse into via the cmake `add_subdirectory()` command. \ + The subdirectories are included after the restricted platform folders have been visited by a call to `add_subdirectory(restricted/\${restricted_platform})`") #! read_engine_external_subdirs # Read the external subdirectories from the engine.json file diff --git a/cmake/FileUtil.cmake b/cmake/FileUtil.cmake index 69a6ecc377..4607e14452 100644 --- a/cmake/FileUtil.cmake +++ b/cmake/FileUtil.cmake @@ -110,7 +110,7 @@ platform=${PAL_PLATFORM_NAME} game_projects=${LY_PROJECTS_TARGET_NAME} asset_deploy_mode=${LY_ASSET_DEPLOY_MODE} asset_deploy_type=${LY_ASSET_DEPLOY_ASSET_TYPE} -override_pak_root=${LY_OVERRIDE_PAK_FOLDER_ROOT} +override_pak_root=${LY_ASSET_OVERRIDE_PAK_FOLDER_ROOT} ") endfunction() diff --git a/cmake/O3DEJson.cmake b/cmake/O3DEJson.cmake index af55075fb8..daae3b4529 100644 --- a/cmake/O3DEJson.cmake +++ b/cmake/O3DEJson.cmake @@ -8,8 +8,6 @@ include_guard() -set(LY_EXTERNAL_SUBDIRS "" CACHE STRING "List of subdirectories to recurse into when running cmake against the engine's CMakeLists.txt") - #! read_json_external_subdirs # Read the "external_subdirectories" array from a *.json file # External subdirectories are any folders with CMakeLists.txt in them diff --git a/cmake/Platform/Windows/Packaging_windows.cmake b/cmake/Platform/Windows/Packaging_windows.cmake index d5663dadfb..7c62a4984c 100644 --- a/cmake/Platform/Windows/Packaging_windows.cmake +++ b/cmake/Platform/Windows/Packaging_windows.cmake @@ -6,11 +6,11 @@ # # -set(CPACK_WIX_ROOT "" CACHE PATH "Path to the WiX install path") +set(LY_INSTALLER_WIX_ROOT "" CACHE PATH "Path to the WiX install path") -if(CPACK_WIX_ROOT) - if(NOT EXISTS ${CPACK_WIX_ROOT}) - message(FATAL_ERROR "Invalid path supplied for CPACK_WIX_ROOT argument") +if(LY_INSTALLER_WIX_ROOT) + if(NOT EXISTS ${LY_INSTALLER_WIX_ROOT}) + message(FATAL_ERROR "Invalid path supplied for LY_INSTALLER_WIX_ROOT argument") endif() else() # early out as no path to WiX has been supplied effectively disabling support diff --git a/cmake/TestImpactFramework/LYTestImpactFramework.cmake b/cmake/TestImpactFramework/LYTestImpactFramework.cmake index 48bc5bf3df..61cc8c200a 100644 --- a/cmake/TestImpactFramework/LYTestImpactFramework.cmake +++ b/cmake/TestImpactFramework/LYTestImpactFramework.cmake @@ -6,11 +6,8 @@ # # -# Switch to enable/disable test impact analysis (and related build targets) -option(LY_TEST_IMPACT_ACTIVE "Enable test impact framework" OFF) - # Path to test instrumentation binary -option(LY_TEST_IMPACT_INSTRUMENTATION_BIN "Path to test impact framework instrumentation binary" OFF) +set(LY_TEST_IMPACT_INSTRUMENTATION_BIN "" CACHE PATH "Path to test impact framework instrumentation binary") # Name of test impact framework console static library target set(LY_TEST_IMPACT_CONSOLE_STATIC_TARGET "TestImpact.Frontend.Console.Static") @@ -213,9 +210,9 @@ function(ly_test_impact_extract_python_test_params COMPOSITE_TEST COMPOSITE_SUIT list(GET suite_components 2 test_timeout) # Get python script path relative to repo root ly_test_impact_rebase_file_to_repo_root( - ${script_path} + "${script_path}" script_path - ${LY_ROOT_FOLDER} + "${LY_ROOT_FOLDER}" ) set(suite_params "{ \"suite\": \"${test_suite}\", \"script\": \"${script_path}\", \"timeout\": ${test_timeout} }") list(APPEND test_suites "${suite_params}") @@ -259,7 +256,8 @@ function(ly_test_impact_write_test_enumeration_file TEST_ENUMERATION_TEMPLATE_FI ly_test_impact_extract_google_test_params(${test} "${test_params}" test_name test_suites) list(APPEND google_benchmarks " { \"name\": \"${test_name}\", \"launch_method\": \"${launch_method}\", \"suites\": [${test_suites}] }") else() - message("${test_name} is of unknown type (TEST_LIBRARY property is empty)") + ly_test_impact_extract_python_test_params(${test} "${test_params}" test_name test_suites) + message("${test_name} is of unknown type (TEST_LIBRARY property is \"${test_type}\")") list(APPEND unknown_tests " { \"name\": \"${test}\", \"type\": \"${test_type}\" }") endif() endforeach() @@ -440,7 +438,7 @@ endfunction() #! ly_test_impact_post_step: runs the post steps to be executed after all other cmake scripts have been executed. function(ly_test_impact_post_step) - if(NOT ${LY_TEST_IMPACT_ACTIVE}) + if(NOT LY_TEST_IMPACT_INSTRUMENTATION_BIN) return() endif() diff --git a/scripts/build/Platform/Windows/build_config.json b/scripts/build/Platform/Windows/build_config.json index 0e8a6b8746..235e1406ab 100644 --- a/scripts/build/Platform/Windows/build_config.json +++ b/scripts/build/Platform/Windows/build_config.json @@ -132,7 +132,7 @@ "PARAMETERS": { "CONFIGURATION": "profile", "OUTPUT_DIRECTORY": "build\\windows_vs2019", - "CMAKE_OPTIONS": "-G \"Visual Studio 16 2019\" -DCMAKE_SYSTEM_VERSION=10.0 -DLY_UNITY_BUILD=TRUE -DLY_TEST_IMPACT_ACTIVE=1 -DLY_TEST_IMPACT_INSTRUMENTATION_BIN=!TEST_IMPACT_WIN_BINARY!", + "CMAKE_OPTIONS": "-G \"Visual Studio 16 2019\" -DCMAKE_SYSTEM_VERSION=10.0 -DLY_UNITY_BUILD=TRUE -DLY_TEST_IMPACT_INSTRUMENTATION_BIN=!TEST_IMPACT_WIN_BINARY!", "CMAKE_LY_PROJECTS": "AutomatedTesting", "CMAKE_TARGET": "ALL_BUILD", "CMAKE_NATIVE_BUILD_ARGS": "/m /nologo" @@ -328,7 +328,7 @@ "PARAMETERS": { "CONFIGURATION": "profile", "OUTPUT_DIRECTORY": "build\\windows_vs2019", - "CMAKE_OPTIONS": "-G \"Visual Studio 16 2019\" -DCMAKE_SYSTEM_VERSION=10.0 -DLY_UNITY_BUILD=TRUE -DLY_DISABLE_TEST_MODULES=TRUE -DLY_VERSION_ENGINE_NAME=o3de-sdk -DCPACK_WIX_ROOT=\"!WIX! \"", + "CMAKE_OPTIONS": "-G \"Visual Studio 16 2019\" -DCMAKE_SYSTEM_VERSION=10.0 -DLY_UNITY_BUILD=TRUE -DLY_DISABLE_TEST_MODULES=TRUE -DLY_VERSION_ENGINE_NAME=o3de-sdk -DLY_INSTALLER_WIX_ROOT=\"!WIX! \"", "EXTRA_CMAKE_OPTIONS": "-DLY_INSTALLER_AUTO_GEN_TAG=ON -DLY_INSTALLER_DOWNLOAD_URL=https://dkb1uj4hs9ikv.cloudfront.net -DLY_INSTALLER_LICENSE_URL=https://www.o3debinaries.org/license -DLY_INSTALLER_3RD_PARTY_LICENSE_URL=https://dkb1uj4hs9ikv.cloudfront.net/SPDX-Licenses.txt", "CPACK_BUCKET": "spectra-prism-staging-us-west-2", "CMAKE_LY_PROJECTS": "", diff --git a/scripts/ctest/CMakeLists.txt b/scripts/ctest/CMakeLists.txt index 45fded24ed..98ea21e938 100644 --- a/scripts/ctest/CMakeLists.txt +++ b/scripts/ctest/CMakeLists.txt @@ -42,5 +42,6 @@ ly_add_test( TEST_COMMAND ${LY_PYTHON_CMD} ${CMAKE_CURRENT_LIST_DIR}/ctest_driver_test.py -x ${CMAKE_CTEST_COMMAND} --build-path ${CMAKE_BINARY_DIR} + TEST_LIBRARY pytest ) From 50f6ea83852a821ef86e8f9cc5d1ec586a8fe89f Mon Sep 17 00:00:00 2001 From: Dayo Lawal Date: Mon, 26 Jul 2021 16:22:34 -0500 Subject: [PATCH 047/160] Using GetBuildTargetName() and other fixes Signed-off-by: Dayo Lawal --- .../Application/AtomToolsApplication.h | 7 +-- .../Application/AtomToolsApplication.cpp | 33 ++++++------- .../Code/Source/MaterialEditorApplication.cpp | 47 ++++--------------- .../Code/Source/MaterialEditorApplication.h | 1 + .../ShaderManagementConsoleApplication.cpp | 23 +++------ .../ShaderManagementConsoleApplication.h | 1 + 6 files changed, 32 insertions(+), 80 deletions(-) diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h index 1ee73ee9fb..daec30f7d7 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h @@ -11,11 +11,9 @@ #include #include #include -#include #include #include #include -#include #include #include #include @@ -81,7 +79,7 @@ namespace AtomToolsFramework void OnExceptionMessage(AZStd::string_view message) override; //////////////////////////////////////////////////////////////////////// - virtual AZStd::string_view GetBuildTargetName() {return targetName;}; + virtual AZStd::string_view GetBuildTargetName() {return m_targetName;}; virtual void LoadSettings(); virtual void UnloadSettings(); @@ -91,9 +89,8 @@ namespace AtomToolsFramework virtual void StartInternal(); static void PyIdleWaitFrames(uint32_t frames); - void setTargetName(AZStd::string newTargetName); - AZStd::string targetName = "AtomTools"; + AZStd::string m_targetName = "AtomTools"; AzToolsFramework::TraceLogger m_traceLogger; diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp index 93ea6ca499..c8f1bebe3a 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp @@ -119,7 +119,7 @@ namespace AtomToolsFramework void AtomToolsApplication::CreateStaticModules(AZStd::vector& outModules) { - Application::CreateStaticModules(outModules); + Base::CreateStaticModules(outModules); outModules.push_back(aznew AzToolsFramework::AzToolsFrameworkModule); } @@ -128,7 +128,7 @@ namespace AtomToolsFramework AzFramework::AssetSystemStatusBus::Handler::BusConnect(); AzToolsFramework::EditorPythonConsoleNotificationBus::Handler::BusConnect(); - AzFramework::Application::StartCommon(systemEntity); + Base::StartCommon(systemEntity); StartInternal(); @@ -141,12 +141,12 @@ namespace AtomToolsFramework AzToolsFramework::AssetDatabase::AssetDatabaseRequestsBus::Handler::BusDisconnect(); AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::StartDisconnectingAssetProcessor); - Application::Destroy(); + Base::Destroy(); } void AtomToolsApplication::CompileCriticalAssets(const AZStd::vector &assetFiltersArray) { - AZ_TracePrintf(targetName.c_str(), "Compiling critical assets.\n"); + AZ_TracePrintf(m_targetName.c_str(), "Compiling critical assets.\n"); QStringList failedAssets; @@ -155,7 +155,7 @@ namespace AtomToolsFramework // So the asset id won't be found right after CompileAssetSync call. for (const AZStd::string& assetFilters : assetFiltersArray) { - AZ_TracePrintf("AtomTools", "Compiling critical asset matching: %s.\n", assetFilters.c_str()); + AZ_TracePrintf(m_targetName.c_str(), "Compiling critical asset matching: %s.\n", assetFilters.c_str()); // Wait for the asset be compiled AzFramework::AssetSystem::AssetStatus status = AzFramework::AssetSystem::AssetStatus_Unknown; @@ -187,7 +187,7 @@ namespace AtomToolsFramework AZ_Assert(context, "No serialize context"); char resolvedPath[AZ_MAX_PATH_LEN] = ""; - AZStd::string fileName = "@user@/" + targetName + "UserSettings.xml"; + AZStd::string fileName = "@user@/" + m_targetName + "UserSettings.xml"; AZ::IO::FileIOBase::GetInstance()->ResolvePath( fileName.c_str(), resolvedPath, AZ_ARRAY_SIZE(resolvedPath)); @@ -202,7 +202,7 @@ namespace AtomToolsFramework AZ_Assert(context, "No serialize context"); char resolvedPath[AZ_MAX_PATH_LEN] = ""; - AZStd::string fileName = "@user@/" + targetName + "UserSettings.xml"; + AZStd::string fileName = "@user@/" + m_targetName + "UserSettings.xml"; AZ::IO::FileIOBase::GetInstance()->ResolvePath(fileName.c_str(), resolvedPath, AZ_MAX_PATH_LEN); @@ -230,12 +230,12 @@ namespace AtomToolsFramework { const AZStd::string& timeoutValue = commandLine.GetSwitchValue(timeoputSwitchName, 0); const uint32_t timeoutInMs = atoi(timeoutValue.c_str()); - AZ_Printf(targetName.c_str(), "Timeout scheduled, shutting down in %u ms", timeoutInMs); + AZ_Printf(m_targetName.c_str(), "Timeout scheduled, shutting down in %u ms", timeoutInMs); QTimer::singleShot( timeoutInMs, [this] { - AZ_Printf(targetName.c_str(), "Timeout reached, shutting down"); + AZ_Printf(m_targetName.c_str(), "Timeout reached, shutting down"); ExitMainLoop(); }); } @@ -248,7 +248,7 @@ namespace AtomToolsFramework const AZStd::string runPythonScriptPath = commandLine.GetSwitchValue(runPythonScriptSwitchName, runPythonScriptIndex); AZStd::vector runPythonArgs; - AZ_Printf(targetName.c_str(), "Launching script: %s", runPythonScriptPath.c_str()); + AZ_Printf(m_targetName.c_str(), "Launching script: %s", runPythonScriptPath.c_str()); AzToolsFramework::EditorPythonRunnerRequestBus::Broadcast( &AzToolsFramework::EditorPythonRunnerRequestBus::Events::ExecuteByFilenameWithArgs, runPythonScriptPath, runPythonArgs); } @@ -323,7 +323,7 @@ namespace AtomToolsFramework return; } - AZStd::string fileName = targetName + ".log"; + AZStd::string fileName = m_targetName + ".log"; m_traceLogger.WriteStartupLog(fileName.c_str()); @@ -374,7 +374,7 @@ namespace AtomToolsFramework void AtomToolsApplication::Stop() { UnloadSettings(); - AzFramework::Application::Stop(); + Base::Stop(); } void AtomToolsApplication::QueryApplicationType(AZ::ApplicationTypeQuery& appType) const @@ -394,7 +394,7 @@ namespace AtomToolsFramework for (auto& line : lines) { - AZ_TracePrintf(targetName.c_str(), "Python: %s\n", line.c_str()); + AZ_TracePrintf(m_targetName.c_str(), "Python: %s\n", line.c_str()); } #endif } @@ -407,7 +407,7 @@ namespace AtomToolsFramework void AtomToolsApplication::OnExceptionMessage([[maybe_unused]] AZStd::string_view message) { - AZ_Error(targetName.c_str(), false, "Python: " AZ_STRING_FORMAT, AZ_STRING_ARG(message)); + AZ_Error(m_targetName.c_str(), false, "Python: " AZ_STRING_FORMAT, AZ_STRING_ARG(message)); } // Copied from PyIdleWaitFrames in CryEdit.cpp @@ -444,9 +444,4 @@ namespace AtomToolsFramework Ticker ticker(&loop, frames); loop.exec(); } - - void AtomToolsApplication::setTargetName(AZStd::string newTargetName) - { - targetName = newTargetName; - } } // namespace AtomToolsFramework diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp index 038005891d..0b4165cce0 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp @@ -51,7 +51,7 @@ AZ_POP_DISABLE_WARNING namespace MaterialEditor { //! This function returns the build system target name of "MaterialEditor - AZStd::string_view GetBuildTargetName() + AZStd::string_view MaterialEditorApplication::GetBuildTargetName() { #if !defined (LY_CMAKE_TARGET) #error "LY_CMAKE_TARGET must be defined in order to add this source file to a CMake executable target" @@ -75,7 +75,7 @@ namespace MaterialEditor { QApplication::setApplicationName("O3DE Material Editor"); - setTargetName("MaterialEditor"); + m_targetName = GetBuildTargetName(); AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddBuildSystemTargetSpecialization( *AZ::SettingsRegistry::Get(), GetBuildTargetName()); @@ -139,7 +139,7 @@ namespace MaterialEditor AzFramework::AssetSystem::ConnectionSettings connectionSettings; AzFramework::AssetSystem::ReadConnectionSettingsFromSettingsRegistry(connectionSettings); connectionSettings.m_connectionDirection = AzFramework::AssetSystem::ConnectionSettings::ConnectionDirection::ConnectToAssetProcessor; - connectionSettings.m_connectionIdentifier = targetName.c_str(); + connectionSettings.m_connectionIdentifier = GetBuildTargetName(); connectionSettings.m_loggingCallback = []([[maybe_unused]] AZStd::string_view logData) { AZ_TracePrintf("Material Editor", "%.*s", aznumeric_cast(logData.size()), logData.data()); @@ -147,12 +147,12 @@ namespace MaterialEditor AzFramework::AssetSystemRequestBus::BroadcastResult(connectedToAssetProcessor, &AzFramework::AssetSystemRequestBus::Events::EstablishAssetProcessorConnection, connectionSettings); - // List of common asset filters for things that need to be compiled to run the material editor - // Some of these things will not be necessary once we have proper support for queued asset loading and reloading - const AZStd::vector assetFiltersArray = { "passes/", "config/", "MaterialEditor/" }; - if (connectedToAssetProcessor) { + // List of common asset filters for things that need to be compiled to run the material editor + // Some of these things will not be necessary once we have proper support for queued asset loading and reloading + const AZStd::vector assetFiltersArray = { "passes/", "config/", "MaterialEditor/" }; + CompileCriticalAssets(assetFiltersArray); } @@ -168,33 +168,6 @@ namespace MaterialEditor &MaterialEditor::MaterialEditorWindowRequestBus::Handler::ActivateWindow); } - const AZStd::string timeoputSwitchName = "timeout"; - if (commandLine.HasSwitch(timeoputSwitchName)) - { - const AZStd::string& timeoutValue = commandLine.GetSwitchValue(timeoputSwitchName, 0); - const uint32_t timeoutInMs = atoi(timeoutValue.c_str()); - AZ_Printf("MaterialEditor", "Timeout scheduled, shutting down in %u ms", timeoutInMs); - QTimer::singleShot(timeoutInMs, [this] { - AZ_Printf("MaterialEditor", "Timeout reached, shutting down"); - ExitMainLoop(); - }); - } - - // Process command line options for running one or more python scripts on startup - const AZStd::string runPythonScriptSwitchName = "runpython"; - size_t runPythonScriptCount = commandLine.GetNumSwitchValues(runPythonScriptSwitchName); - for (size_t runPythonScriptIndex = 0; runPythonScriptIndex < runPythonScriptCount; ++runPythonScriptIndex) - { - const AZStd::string runPythonScriptPath = commandLine.GetSwitchValue(runPythonScriptSwitchName, runPythonScriptIndex); - AZStd::vector runPythonArgs; - - AZ_Printf("MaterialEditor", "Launching script: %s", runPythonScriptPath.c_str()); - AzToolsFramework::EditorPythonRunnerRequestBus::Broadcast( - &AzToolsFramework::EditorPythonRunnerRequestBus::Events::ExecuteByFilenameWithArgs, - runPythonScriptPath, - runPythonArgs); - } - // Process command line options for opening one or more material documents on startup size_t openDocumentCount = commandLine.GetNumMiscValues(); for (size_t openDocumentIndex = 0; openDocumentIndex < openDocumentCount; ++openDocumentIndex) @@ -205,11 +178,7 @@ namespace MaterialEditor MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::OpenDocument, openDocumentPath); } - const AZStd::string exitAfterCommandsSwitchName = "exitaftercommands"; - if (commandLine.HasSwitch(exitAfterCommandsSwitchName)) - { - ExitMainLoop(); - } + Base::ProcessCommandLine(commandLine); } void MaterialEditorApplication::StartInternal() diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h index 92f4223f99..0739fa6ae1 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h @@ -54,5 +54,6 @@ namespace MaterialEditor void ProcessCommandLine(const AZ::CommandLine& commandLine) override; void StartInternal() override; + AZStd::string_view GetBuildTargetName() override; }; } // namespace MaterialEditor diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp index 48c246f938..5cb98a4345 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp @@ -47,7 +47,7 @@ AZ_POP_DISABLE_WARNING namespace ShaderManagementConsole { - AZStd::string_view GetBuildTargetName() + AZStd::string_view ShaderManagementConsoleApplication::GetBuildTargetName() { #if !defined (LY_CMAKE_TARGET) #error "LY_CMAKE_TARGET must be defined in order to add this source file to a CMake executable target" @@ -70,7 +70,7 @@ namespace ShaderManagementConsole : AtomToolsApplication(argc, argv) { QApplication::setApplicationName("O3DE Shader Management Console"); - setTargetName("ShaderManagementConsole"); + m_targetName = GetBuildTargetName(); // The settings registry has been created at this point, so add the CMake target AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddBuildSystemTargetSpecialization( @@ -125,29 +125,18 @@ namespace ShaderManagementConsole }; AzFramework::AssetSystemRequestBus::Broadcast(ConnectToAssetProcessorWithIdentifier); - // List of common asset filters for things that need to be compiled to run the material editor - // Some of these things will not be necessary once we have proper support for queued asset loading and reloading - const AZStd::vector assetFiltersArray = { "passes/", "config/"}; - if (connected) { + // List of common asset filters for things that need to be compiled to run the material editor + // Some of these things will not be necessary once we have proper support for queued asset loading and reloading + const AZStd::vector assetFiltersArray = { "passes/", "config/" }; + CompileCriticalAssets(assetFiltersArray); } AzFramework::AssetSystemStatusBus::Handler::BusDisconnect(); } -// bool ShaderManagementConsoleApplication::OnPrintf(const char* window, const char* /*message*/) -// { -// // Suppress spam from the Source Control system -// if (0 == strncmp(window, AzToolsFramework::SCC_WINDOW, AZ_ARRAY_SIZE(AzToolsFramework::SCC_WINDOW))) -// { -// return true; -// } -// -// return false; -// } - void ShaderManagementConsoleApplication::ProcessCommandLine() { // Process command line options for running one or more python scripts on startup diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h index 7c4f53f4e9..277d3ef1e3 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h @@ -55,5 +55,6 @@ namespace ShaderManagementConsole void ProcessCommandLine(); void StartInternal() override; + AZStd::string_view GetBuildTargetName() override; }; } // namespace ShaderManagementConsole From 7122f1b7618d0e22dccaab8852252c77d2c0b229 Mon Sep 17 00:00:00 2001 From: Dayo Lawal Date: Mon, 26 Jul 2021 17:41:10 -0500 Subject: [PATCH 048/160] More refractoring Signed-off-by: Dayo Lawal --- .../Application/AtomToolsApplication.h | 4 +- .../Application/AtomToolsApplication.cpp | 42 +++++++++++++---- .../Code/Source/MaterialEditorApplication.cpp | 25 +--------- .../Code/Source/MaterialEditorApplication.h | 3 +- .../ShaderManagementConsoleApplication.cpp | 46 +------------------ .../ShaderManagementConsoleApplication.h | 9 +--- 6 files changed, 40 insertions(+), 89 deletions(-) diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h index daec30f7d7..9d412ec477 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h @@ -79,7 +79,7 @@ namespace AtomToolsFramework void OnExceptionMessage(AZStd::string_view message) override; //////////////////////////////////////////////////////////////////////// - virtual AZStd::string_view GetBuildTargetName() {return m_targetName;}; + virtual AZStd::string GetBuildTargetName(); virtual void LoadSettings(); virtual void UnloadSettings(); @@ -90,8 +90,6 @@ namespace AtomToolsFramework static void PyIdleWaitFrames(uint32_t frames); - AZStd::string m_targetName = "AtomTools"; - AzToolsFramework::TraceLogger m_traceLogger; //! Local user settings are used to store material browser tree expansion state diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp index c8f1bebe3a..1ad2048ae4 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp @@ -39,6 +39,11 @@ AZ_POP_DISABLE_WARNING namespace AtomToolsFramework { + AZStd::string AtomToolsApplication::GetBuildTargetName() + { + return AZStd::string("AtomTools"); + } + const char* AtomToolsApplication::GetCurrentConfigurationName() const { #if defined(_RELEASE) @@ -146,7 +151,7 @@ namespace AtomToolsFramework void AtomToolsApplication::CompileCriticalAssets(const AZStd::vector &assetFiltersArray) { - AZ_TracePrintf(m_targetName.c_str(), "Compiling critical assets.\n"); + AZ_TracePrintf(GetBuildTargetName().c_str(), "Compiling critical assets.\n"); QStringList failedAssets; @@ -155,7 +160,7 @@ namespace AtomToolsFramework // So the asset id won't be found right after CompileAssetSync call. for (const AZStd::string& assetFilters : assetFiltersArray) { - AZ_TracePrintf(m_targetName.c_str(), "Compiling critical asset matching: %s.\n", assetFilters.c_str()); + AZ_TracePrintf(GetBuildTargetName().c_str(), "Compiling critical asset matching: %s.\n", assetFilters.c_str()); // Wait for the asset be compiled AzFramework::AssetSystem::AssetStatus status = AzFramework::AssetSystem::AssetStatus_Unknown; @@ -187,7 +192,7 @@ namespace AtomToolsFramework AZ_Assert(context, "No serialize context"); char resolvedPath[AZ_MAX_PATH_LEN] = ""; - AZStd::string fileName = "@user@/" + m_targetName + "UserSettings.xml"; + AZStd::string fileName = "@user@/" + GetBuildTargetName() + "UserSettings.xml"; AZ::IO::FileIOBase::GetInstance()->ResolvePath( fileName.c_str(), resolvedPath, AZ_ARRAY_SIZE(resolvedPath)); @@ -202,7 +207,7 @@ namespace AtomToolsFramework AZ_Assert(context, "No serialize context"); char resolvedPath[AZ_MAX_PATH_LEN] = ""; - AZStd::string fileName = "@user@/" + m_targetName + "UserSettings.xml"; + AZStd::string fileName = "@user@/" + GetBuildTargetName() + "UserSettings.xml"; AZ::IO::FileIOBase::GetInstance()->ResolvePath(fileName.c_str(), resolvedPath, AZ_MAX_PATH_LEN); @@ -230,12 +235,12 @@ namespace AtomToolsFramework { const AZStd::string& timeoutValue = commandLine.GetSwitchValue(timeoputSwitchName, 0); const uint32_t timeoutInMs = atoi(timeoutValue.c_str()); - AZ_Printf(m_targetName.c_str(), "Timeout scheduled, shutting down in %u ms", timeoutInMs); + AZ_Printf(GetBuildTargetName().c_str(), "Timeout scheduled, shutting down in %u ms", timeoutInMs); QTimer::singleShot( timeoutInMs, [this] { - AZ_Printf(m_targetName.c_str(), "Timeout reached, shutting down"); + AZ_Printf(GetBuildTargetName().c_str(), "Timeout reached, shutting down"); ExitMainLoop(); }); } @@ -248,7 +253,7 @@ namespace AtomToolsFramework const AZStd::string runPythonScriptPath = commandLine.GetSwitchValue(runPythonScriptSwitchName, runPythonScriptIndex); AZStd::vector runPythonArgs; - AZ_Printf(m_targetName.c_str(), "Launching script: %s", runPythonScriptPath.c_str()); + AZ_Printf(GetBuildTargetName().c_str(), "Launching script: %s", runPythonScriptPath.c_str()); AzToolsFramework::EditorPythonRunnerRequestBus::Broadcast( &AzToolsFramework::EditorPythonRunnerRequestBus::Events::ExecuteByFilenameWithArgs, runPythonScriptPath, runPythonArgs); } @@ -323,7 +328,7 @@ namespace AtomToolsFramework return; } - AZStd::string fileName = m_targetName + ".log"; + AZStd::string fileName = GetBuildTargetName() + ".log"; m_traceLogger.WriteStartupLog(fileName.c_str()); @@ -342,6 +347,23 @@ namespace AtomToolsFramework AZ::RPI::RPISystemInterface::Get()->InitializeSystemAssets(); LoadSettings(); + + auto editorPythonEventsInterface = AZ::Interface::Get(); + if (editorPythonEventsInterface) + { + // The PythonSystemComponent does not call StartPython to allow for lazy python initialization, so start it here + // The PythonSystemComponent will call StopPython when it deactivates, so we do not need our own corresponding call to + // StopPython + editorPythonEventsInterface->StartPython(); + } + + // Delay execution of commands and scripts post initialization + QTimer::singleShot( + 0, + [this]() + { + ProcessCommandLine(m_commandLine); + }); } bool AtomToolsApplication::GetAssetDatabaseLocation(AZStd::string& result) @@ -394,7 +416,7 @@ namespace AtomToolsFramework for (auto& line : lines) { - AZ_TracePrintf(m_targetName.c_str(), "Python: %s\n", line.c_str()); + AZ_TracePrintf(GetBuildTargetName().c_str(), "Python: %s\n", line.c_str()); } #endif } @@ -407,7 +429,7 @@ namespace AtomToolsFramework void AtomToolsApplication::OnExceptionMessage([[maybe_unused]] AZStd::string_view message) { - AZ_Error(m_targetName.c_str(), false, "Python: " AZ_STRING_FORMAT, AZ_STRING_ARG(message)); + AZ_Error(GetBuildTargetName().c_str(), false, "Python: " AZ_STRING_FORMAT, AZ_STRING_ARG(message)); } // Copied from PyIdleWaitFrames in CryEdit.cpp diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp index 0b4165cce0..6832ca683c 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp @@ -51,12 +51,12 @@ AZ_POP_DISABLE_WARNING namespace MaterialEditor { //! This function returns the build system target name of "MaterialEditor - AZStd::string_view MaterialEditorApplication::GetBuildTargetName() + AZStd::string MaterialEditorApplication::GetBuildTargetName() { #if !defined (LY_CMAKE_TARGET) #error "LY_CMAKE_TARGET must be defined in order to add this source file to a CMake executable target" #endif - return AZStd::string_view{ LY_CMAKE_TARGET }; + return AZStd::string{ LY_CMAKE_TARGET }; } const char* MaterialEditorApplication::GetCurrentConfigurationName() const @@ -75,7 +75,6 @@ namespace MaterialEditor { QApplication::setApplicationName("O3DE Material Editor"); - m_targetName = GetBuildTargetName(); AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddBuildSystemTargetSpecialization( *AZ::SettingsRegistry::Get(), GetBuildTargetName()); @@ -102,15 +101,6 @@ namespace MaterialEditor outModules.push_back(aznew MaterialEditorWindowModule); } - void MaterialEditorApplication::StartCommon(AZ::Entity* systemEntity) - { - { - //[GFX TODO][ATOM-408] This needs to be updated in some way to support the MaterialViewport render widget - } - - Base::StartCommon(systemEntity); - } - void MaterialEditorApplication::OnMaterialEditorWindowClosing() { ExitMainLoop(); @@ -189,17 +179,6 @@ namespace MaterialEditor MaterialEditor::MaterialEditorWindowFactoryRequestBus::Broadcast( &MaterialEditor::MaterialEditorWindowFactoryRequestBus::Handler::CreateMaterialEditorWindow); - - auto editorPythonEventsInterface = AZ::Interface::Get(); - if (editorPythonEventsInterface) - { - // The PythonSystemComponent does not call StartPython to allow for lazy python initialization, so start it here - // The PythonSystemComponent will call StopPython when it deactivates, so we do not need our own corresponding call to StopPython - editorPythonEventsInterface->StartPython(); - } - - // Delay execution of commands and scripts post initialization - QTimer::singleShot(0, [this]() { ProcessCommandLine(m_commandLine); }); } void MaterialEditorApplication::Stop() diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h index 0739fa6ae1..1139a73827 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h @@ -33,7 +33,6 @@ namespace MaterialEditor // AzFramework::Application void CreateStaticModules(AZStd::vector& outModules) override; const char* GetCurrentConfigurationName() const override; - void StartCommon(AZ::Entity* systemEntity) override; void Stop() override; private: @@ -54,6 +53,6 @@ namespace MaterialEditor void ProcessCommandLine(const AZ::CommandLine& commandLine) override; void StartInternal() override; - AZStd::string_view GetBuildTargetName() override; + AZStd::string GetBuildTargetName() override; }; } // namespace MaterialEditor diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp index 5cb98a4345..6d5e331c75 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp @@ -47,7 +47,7 @@ AZ_POP_DISABLE_WARNING namespace ShaderManagementConsole { - AZStd::string_view ShaderManagementConsoleApplication::GetBuildTargetName() + AZStd::string ShaderManagementConsoleApplication::GetBuildTargetName() { #if !defined (LY_CMAKE_TARGET) #error "LY_CMAKE_TARGET must be defined in order to add this source file to a CMake executable target" @@ -70,7 +70,6 @@ namespace ShaderManagementConsole : AtomToolsApplication(argc, argv) { QApplication::setApplicationName("O3DE Shader Management Console"); - m_targetName = GetBuildTargetName(); // The settings registry has been created at this point, so add the CMake target AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddBuildSystemTargetSpecialization( @@ -163,51 +162,10 @@ namespace ShaderManagementConsole void ShaderManagementConsoleApplication::StartInternal() { - if (WasExitMainLoopRequested()) - { - return; - } - - m_traceLogger.WriteStartupLog("ShaderManagementConsole.log"); - - //[GFX TODO][ATOM-415] Try to factor out some of this stuff with AtomSampleViewerApplication - AzToolsFramework::AssetDatabase::AssetDatabaseRequestsBus::Handler::BusConnect(); - AzToolsFramework::AssetBrowser::AssetDatabaseLocationNotificationBus::Broadcast(&AzToolsFramework::AssetBrowser::AssetDatabaseLocationNotifications::OnDatabaseInitialized); - - AZ::Data::AssetCatalogRequestBus::Broadcast(&AZ::Data::AssetCatalogRequestBus::Events::LoadCatalog, "@assets@/assetcatalog.xml"); - - AZ::RPI::RPISystemInterface::Get()->InitializeSystemAssets(); - - LoadSettings(); - - LaunchDiscoveryService(); + Base::StartInternal(); ShaderManagementConsoleWindowNotificationBus::Handler::BusConnect(); ShaderManagementConsole::ShaderManagementConsoleWindowRequestBus::Broadcast(&ShaderManagementConsole::ShaderManagementConsoleWindowRequestBus::Handler::CreateShaderManagementConsoleWindow); - - auto editorPythonEventsInterface = AZ::Interface::Get(); - if (editorPythonEventsInterface) - { - // The PythonSystemComponent does not call StartPython to allow for lazy python initialization, so start it here - // The PythonSystemComponent will call StopPython when it deactivates, so we do not need our own corresponding call to StopPython - editorPythonEventsInterface->StartPython(); - } - - ProcessCommandLine(); - } - - bool ShaderManagementConsoleApplication::GetAssetDatabaseLocation(AZStd::string& result) - { - AZ::SettingsRegistryInterface* settingsRegistry = AZ::SettingsRegistry::Get(); - AZ::IO::FixedMaxPath assetDatabaseSqlitePath; - if (settingsRegistry && settingsRegistry->Get(assetDatabaseSqlitePath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_CacheProjectRootFolder)) - { - assetDatabaseSqlitePath /= "assetdb.sqlite"; - result = AZStd::string_view(assetDatabaseSqlitePath.Native()); - return true; - } - - return false; } } // namespace ShaderManagementConsole diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h index 277d3ef1e3..42817040ce 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h @@ -22,7 +22,7 @@ namespace ShaderManagementConsole public: AZ_TYPE_INFO(ShaderManagementConsole::ShaderManagementConsoleApplication, "{A31B1AEB-4DA3-49CD-884A-CC998FF7546F}"); - using Base = AzFramework::Application; + using Base = AtomToolsFramework::AtomToolsApplication; ShaderManagementConsoleApplication(int* argc, char*** argv); virtual ~ShaderManagementConsoleApplication() = default; @@ -33,11 +33,6 @@ namespace ShaderManagementConsole const char* GetCurrentConfigurationName() const override; private: - ////////////////////////////////////////////////////////////////////////// - // AssetDatabaseRequestsBus::Handler overrides... - bool GetAssetDatabaseLocation(AZStd::string& result) override; - ////////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////// // ShaderManagementConsoleWindowNotificationBus::Handler overrides... void OnShaderManagementConsoleWindowClosing() override; @@ -55,6 +50,6 @@ namespace ShaderManagementConsole void ProcessCommandLine(); void StartInternal() override; - AZStd::string_view GetBuildTargetName() override; + AZStd::string GetBuildTargetName() override; }; } // namespace ShaderManagementConsole From 4baea40a75985314cca06a9a154299cf5de12ecc Mon Sep 17 00:00:00 2001 From: Dayo Lawal Date: Mon, 26 Jul 2021 17:48:22 -0500 Subject: [PATCH 049/160] Reflect() fix Signed-off-by: Dayo Lawal --- .../Code/Source/Application/AtomToolsApplication.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp index 1ad2048ae4..0ee06d3fc2 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp @@ -82,12 +82,13 @@ namespace AtomToolsFramework if (auto behaviorContext = azrtti_cast(context)) { + AZStd::string fileName = GetBuildTargetName() + ".general"; // this will put these methods into the 'azlmbr.AtomTools.general' module - auto addGeneral = [](AZ::BehaviorContext::GlobalMethodBuilder methodBuilder) + auto addGeneral = [fileName](AZ::BehaviorContext::GlobalMethodBuilder methodBuilder) { methodBuilder->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation) ->Attribute(AZ::Script::Attributes::Category, "Editor") - ->Attribute(AZ::Script::Attributes::Module, "AtomTools.general"); + ->Attribute(AZ::Script::Attributes::Module, fileName); }; // The reflection here is based on patterns in CryEditPythonHandler::Reflect addGeneral(behaviorContext->Method( From b8300c6248d18bbb6ab947e656fa7180069dba69 Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Mon, 26 Jul 2021 16:02:17 -0700 Subject: [PATCH 050/160] fix entity reference removal when not in a variable Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com> --- .../ScriptCanvas/Code/Builder/ScriptCanvasBuilder.cpp | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilder.cpp b/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilder.cpp index 1771d9b4a6..6a5344ed9b 100644 --- a/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilder.cpp +++ b/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilder.cpp @@ -137,16 +137,9 @@ namespace ScriptCanvasBuilder if (!ScriptCanvas::Grammar::IsParserGeneratedId(entityId.first)) { - auto graphEntityId = variables.FindVariable(entityId.first); - if (!graphEntityId) - { - AZ_Error("ScriptCanvasBuilder", false, "Missing EntityId from graph data that was just parsed"); - continue; - } - - // copy to override list for editor display - if (graphEntityId->IsComponentProperty()) + if (auto graphEntityId = variables.FindVariable(entityId.first); graphEntityId && graphEntityId->IsComponentProperty()) { + // copy to override list for editor display m_overrides.push_back(*graphEntityId); auto& overrideValue = m_overrides.back(); overrideValue.SetScriptInputControlVisibility(AZ::Edit::PropertyVisibility::Hide); From ed6dbb48f4b292d17518c478ece4212922a070cc Mon Sep 17 00:00:00 2001 From: amzn-phist <52085794+amzn-phist@users.noreply.github.com> Date: Mon, 26 Jul 2021 18:19:07 -0500 Subject: [PATCH 051/160] Fixes failing tests and linux compile error Replaced a 'uint32' with AZ::u32 to fix a linux compile error that likely came about after cleaning up includes. Rewrites a failing unit test after the code under test was updated from CryPak to AZ::IO. Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com> --- Code/Editor/Util/UndoUtil.h | 2 +- .../Code/Tests/AudioSystemEditorTest.cpp | 109 +++++++++++------- 2 files changed, 68 insertions(+), 43 deletions(-) diff --git a/Code/Editor/Util/UndoUtil.h b/Code/Editor/Util/UndoUtil.h index f352eb317b..e825647f6b 100644 --- a/Code/Editor/Util/UndoUtil.h +++ b/Code/Editor/Util/UndoUtil.h @@ -31,7 +31,7 @@ public: static void Record(IUndoObject* undo); private: - static const uint32 scDescSize = 256; + static const AZ::u32 scDescSize = 256; char m_description[scDescSize]; bool m_bCancelled; bool m_bStartedRecord; diff --git a/Gems/AudioSystem/Code/Tests/AudioSystemEditorTest.cpp b/Gems/AudioSystem/Code/Tests/AudioSystemEditorTest.cpp index a486e24326..0debe128e2 100644 --- a/Gems/AudioSystem/Code/Tests/AudioSystemEditorTest.cpp +++ b/Gems/AudioSystem/Code/Tests/AudioSystemEditorTest.cpp @@ -10,54 +10,45 @@ #include #include +#include + #include #include -#include -#include -#include - using ::testing::NiceMock; using namespace AudioControls; namespace CustomMocks { - class AudioControlsEditorTest_CryPakMock - : public CryPakMock + class AudioControlsEditorTest_FileIOMock + : public AZ::IO::MockFileIOBase { public: - AZ_TEST_CLASS_ALLOCATOR(AudioControlsEditorTest_CryPakMock) + AZ_TEST_CLASS_ALLOCATOR(AudioControlsEditorTest_FileIOMock); - AudioControlsEditorTest_CryPakMock(const char* levelName) - : m_levelName(levelName) - {} - - AZ::IO::ArchiveFileIterator FindFirst([[maybe_unused]] AZStd::string_view dir, AZ::IO::IArchive::EFileSearchType) override + AudioControlsEditorTest_FileIOMock() { - AZ::IO::FileDesc fileDesc; - fileDesc.nSize = sizeof(AZ::IO::FileDesc); - // Add a filename and file description reference to the TestFindData map to make sure the file iterator is valid - m_findData = new TestFindData(); - m_findData->m_fileSet.emplace(AZ::IO::ArchiveFileIterator{ static_cast(m_findData.get()), m_levelName, fileDesc }); - return m_findData->Fetch(); } - AZ::IO::ArchiveFileIterator FindNext(AZ::IO::ArchiveFileIterator iter) override + bool IsDirectory([[maybe_unused]] const char* path) override { - return ++iter; + return false; } - // public: for easy resetting... - AZStd::string m_levelName; - - // Add an inherited FindData class to control the adding of a mapfile which indicates that a FileIterator is valid - struct TestFindData - : AZ::IO::FindData + AZ::IO::Result FindFiles( + [[maybe_unused]] const char* path, + [[maybe_unused]] const char* filter, + AZ::IO::FileIOBase::FindFilesCallbackType callback) override { - using AZ::IO::FindData::m_fileSet; - }; + if (callback) + { + callback(m_levelName.c_str()); + return AZ::IO::ResultCode::Success; + } + return AZ::IO::ResultCode::Error; + } - AZStd::intrusive_ptr m_findData; + AZStd::string m_levelName; }; } // namespace CustomMocks @@ -75,10 +66,6 @@ protected: void SetupEnvironment() override { m_allocatorScope.ActivateAllocators(); - - m_stubEnv.pCryPak = nullptr; - m_stubEnv.pFileIO = nullptr; - gEnv = &m_stubEnv; } void TeardownEnvironment() override @@ -87,30 +74,68 @@ protected: } private: - AZ::AllocatorScope m_allocatorScope; - SSystemGlobalEnvironment m_stubEnv; + AZ::AllocatorScope m_allocatorScope; }; AZ_UNIT_TEST_HOOK(new AudioControlsEditorTestEnvironment); -TEST(AudioControlsEditorTest, AudioControlsLoader_LoadScopes_ScopesAreAdded) +class AudioControlsEditorTest + : public ::testing::Test { - ASSERT_TRUE(gEnv != nullptr); - ASSERT_TRUE(gEnv->pCryPak == nullptr); +public: + void SetUp() override + { + // Store and remove the existing fileIO... + m_prevFileIO = AZ::IO::FileIOBase::GetInstance(); + if (m_prevFileIO) + { + AZ::IO::FileIOBase::SetInstance(nullptr); + } - NiceMock m_cryPakMock("ly_extension.ly"); - gEnv->pCryPak = &m_cryPakMock; + // Replace with a new FileIO Mock... + m_fileIO = AZStd::make_unique(); + AZ::IO::FileIOBase::SetInstance(m_fileIO.get()); + } + void TearDown() override + { + // Destroy our LocalFileIO... + m_fileIO.reset(); + + // Replace the old fileIO (set instance to null first)... + AZ::IO::FileIOBase::SetInstance(nullptr); + if (m_prevFileIO) + { + AZ::IO::FileIOBase::SetInstance(m_prevFileIO); + m_prevFileIO = nullptr; + } + } + +protected: + AZ::IO::FileIOBase* m_prevFileIO = nullptr; + AZStd::unique_ptr m_fileIO; +}; + +TEST_F(AudioControlsEditorTest, AudioControlsLoader_LoadScopes_ScopesAreAdded) +{ CATLControlsModel atlModel; CAudioControlsLoader loader(&atlModel, nullptr, nullptr); + m_fileIO->m_levelName = "ly_extension.ly"; loader.LoadScopes(); EXPECT_TRUE(atlModel.ScopeExists("ly_extension")); - m_cryPakMock.m_levelName = "cry_extension.cry"; + m_fileIO->m_levelName = "cry_extension.cry"; loader.LoadScopes(); EXPECT_TRUE(atlModel.ScopeExists("cry_extension")); + m_fileIO->m_levelName = "prefab_extension.prefab"; + loader.LoadScopes(); + EXPECT_TRUE(atlModel.ScopeExists("prefab_extension")); + + m_fileIO->m_levelName = "spawnable_extension.spawnable"; + loader.LoadScopes(); + EXPECT_FALSE(atlModel.ScopeExists("spawnable_extension")); + atlModel.ClearScopes(); - gEnv->pCryPak = nullptr; } From 223654c41bc9fb0505769804859477926acf4296 Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Mon, 26 Jul 2021 17:51:10 -0700 Subject: [PATCH 052/160] Add fix and unit tests for pure on graph start functions and direct entity id input Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com> --- .../ScriptCanvas/Translation/GraphToLua.cpp | 3 +- ..._EntityIdInputForOnGraphStart.scriptcanvas | 1047 +++++++++++++++++ .../Tests/ScriptCanvas_RuntimeInterpreted.cpp | 5 + 3 files changed, 1054 insertions(+), 1 deletion(-) create mode 100644 Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_EntityIdInputForOnGraphStart.scriptcanvas diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Translation/GraphToLua.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Translation/GraphToLua.cpp index f957071bc1..9a1ef73126 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Translation/GraphToLua.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Translation/GraphToLua.cpp @@ -1943,7 +1943,8 @@ namespace ScriptCanvas { const auto requirement = ParseConstructionRequirement(variable); - if (requirement == Grammar::VariableConstructionRequirement::None || (requirement != Grammar::VariableConstructionRequirement::Static && !execution->IsStartCall())) + if (requirement == Grammar::VariableConstructionRequirement::None + || requirement != Grammar::VariableConstructionRequirement::Static && execution != m_model.GetStart()) { m_dotLua.WriteLineIndented("local %s = %s", variable->m_name.data(), ToValueString(variable->m_datum, m_configuration).data()); } diff --git a/Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_EntityIdInputForOnGraphStart.scriptcanvas b/Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_EntityIdInputForOnGraphStart.scriptcanvas new file mode 100644 index 0000000000..1614e30678 --- /dev/null +++ b/Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_EntityIdInputForOnGraphStart.scriptcanvas @@ -0,0 +1,1047 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/ScriptCanvasTesting/Code/Tests/ScriptCanvas_RuntimeInterpreted.cpp b/Gems/ScriptCanvasTesting/Code/Tests/ScriptCanvas_RuntimeInterpreted.cpp index 2a563b0904..df29a56fd5 100644 --- a/Gems/ScriptCanvasTesting/Code/Tests/ScriptCanvas_RuntimeInterpreted.cpp +++ b/Gems/ScriptCanvasTesting/Code/Tests/ScriptCanvas_RuntimeInterpreted.cpp @@ -89,6 +89,11 @@ TEST_F(ScriptCanvasTestFixture, ProveError) EXPECT_TRUE(false); } +TEST_F(ScriptCanvasTestFixture, EntityIdInputForOnGraphStart) +{ + RunUnitTestGraph("LY_SC_UnitTest_EntityIdInputForOnGraphStart"); +} + TEST_F(ScriptCanvasTestFixture, ParseErrorOnKnownNull) { ExpectParseError("LY_SC_UnitTest_ParseErrorOnKnownNull"); From 23fb27e2a4786cc00ce2c81d077ff216fbfb68d4 Mon Sep 17 00:00:00 2001 From: kberg-amzn Date: Mon, 26 Jul 2021 19:40:39 -0700 Subject: [PATCH 053/160] New AzNetworking metrics display plus connection quality debug widgets using ImGui Signed-off-by: kberg-amzn --- .../ConnectionLayer/ConnectionMetrics.cpp | 18 ++ .../ConnectionLayer/ConnectionMetrics.h | 28 +- .../ConnectionLayer/ConnectionMetrics.inl | 29 ++ .../ConnectionLayer/IConnection.h | 16 +- .../ConnectionLayer/IConnection.inl | 10 + .../TcpTransport/TcpConnection.cpp | 13 +- .../AzNetworking/TcpTransport/TcpConnection.h | 1 - .../UdpTransport/UdpConnection.cpp | 10 +- .../AzNetworking/UdpTransport/UdpConnection.h | 8 - .../UdpTransport/UdpConnection.inl | 10 - .../UdpTransport/UdpNetworkInterface.cpp | 3 +- .../AzNetworking/UdpTransport/UdpSocket.cpp | 8 +- .../Debug/MultiplayerDebugSystemComponent.cpp | 286 ++++++++++++------ 13 files changed, 302 insertions(+), 138 deletions(-) diff --git a/Code/Framework/AzNetworking/AzNetworking/ConnectionLayer/ConnectionMetrics.cpp b/Code/Framework/AzNetworking/AzNetworking/ConnectionLayer/ConnectionMetrics.cpp index cc0851e53d..3a3ab06d02 100644 --- a/Code/Framework/AzNetworking/AzNetworking/ConnectionLayer/ConnectionMetrics.cpp +++ b/Code/Framework/AzNetworking/AzNetworking/ConnectionLayer/ConnectionMetrics.cpp @@ -22,6 +22,7 @@ namespace AzNetworking const AZ::TimeMs deltaTimeMs = currentTimeMs - m_lastLoggedTimeMs; m_atoms[m_activeAtom].m_bytesTransmitted += byteCount; + m_atoms[m_activeAtom].m_packetsSent++; m_atoms[m_activeAtom].m_timeAccumulatorMs += deltaTimeMs; if (m_atoms[m_activeAtom].m_timeAccumulatorMs >= m_maxSampleTimeMs) @@ -32,6 +33,11 @@ namespace AzNetworking m_lastLoggedTimeMs = currentTimeMs; } + void DatarateMetrics::LogPacketLost() + { + m_atoms[m_activeAtom].m_packetsLost++; + } + float DatarateMetrics::GetBytesPerSecond() const { const uint32_t sampleAtom = 1 - m_activeAtom; @@ -47,6 +53,18 @@ namespace AzNetworking return (bytesLogged * 1000.0f) / sampleTime; // (* 1000) to convert from bytes per millisecond to bytes per second } + float DatarateMetrics::GetLossRatePercent() const + { + const uint32_t sampleAtom = 1 - m_activeAtom; + + if (m_atoms[sampleAtom].m_packetsSent == 0) + { + return 0.0f; + } + + return float(m_atoms[sampleAtom].m_packetsLost) / float(m_atoms[sampleAtom].m_packetsSent); + } + void ConnectionComputeRtt::LogPacketSent(PacketId packetId, AZ::TimeMs currentTimeMs) { for (uint32_t i = 0; i < MaxTrackableEntries; i++) diff --git a/Code/Framework/AzNetworking/AzNetworking/ConnectionLayer/ConnectionMetrics.h b/Code/Framework/AzNetworking/AzNetworking/ConnectionLayer/ConnectionMetrics.h index c2227b07b6..b576c64e86 100644 --- a/Code/Framework/AzNetworking/AzNetworking/ConnectionLayer/ConnectionMetrics.h +++ b/Code/Framework/AzNetworking/AzNetworking/ConnectionLayer/ConnectionMetrics.h @@ -19,8 +19,10 @@ namespace AzNetworking { DatarateAtom() = default; + AZ::TimeMs m_timeAccumulatorMs = AZ::TimeMs{ 0 }; uint32_t m_bytesTransmitted = 0; - AZ::TimeMs m_timeAccumulatorMs = AZ::TimeMs{0}; + uint32_t m_packetsSent = 0; + uint32_t m_packetsLost = 0; }; //! @class DatarateMetrics @@ -40,19 +42,26 @@ namespace AzNetworking //! @param currentTimeMs current process time in milliseconds void LogPacket(uint32_t byteCount, AZ::TimeMs currentTimeMs); + //! Invoked whenever a packet has determined to be lost. + void LogPacketLost(); + //! Retrieve a sample of the datarate being incurred by this connection in bytes per second. //! @return datarate for traffic sent to or from the connection in bytes per second float GetBytesPerSecond() const; + //! Returns the estimated packet loss rate as a percentage of packets. + //! @return the estimated percentage loss rate + float GetLossRatePercent() const; + private: //! Used internally to swap buffers used for metric gathering. void SwapBuffers(); - static constexpr AZ::TimeMs MaxSampleTimeMs = AZ::TimeMs{500}; + static constexpr AZ::TimeMs MaxSampleTimeMs = AZ::TimeMs{ 2000 }; - AZ::TimeMs m_maxSampleTimeMs = MaxSampleTimeMs; - AZ::TimeMs m_lastLoggedTimeMs = MaxSampleTimeMs; + AZ::TimeMs m_maxSampleTimeMs = MaxSampleTimeMs; + AZ::TimeMs m_lastLoggedTimeMs = MaxSampleTimeMs; uint32_t m_activeAtom = 0; DatarateAtom m_atoms[2]; }; @@ -69,7 +78,7 @@ namespace AzNetworking ConnectionPacketEntry(PacketId packetId, AZ::TimeMs sendTimeMs); PacketId m_packetId = InvalidPacketId; - AZ::TimeMs m_sendTimeMs = AZ::TimeMs{0}; + AZ::TimeMs m_sendTimeMs = AZ::TimeMs{0}; }; //! @class ConnectionComputeRtt @@ -100,8 +109,8 @@ namespace AzNetworking private: - static constexpr uint32_t MaxTrackableEntries = 4; - static constexpr float InitialRoundTripTime = 0.1f; //< Start off with a 100 millisecond estimate for Rtt + static constexpr uint32_t MaxTrackableEntries = 8; + static constexpr float InitialRoundTripTime = 0.1f; //< Start off with a 100 millisecond estimate for Rtt float m_roundTripTime = InitialRoundTripTime; ConnectionPacketEntry m_entries[MaxTrackableEntries]; @@ -117,6 +126,11 @@ namespace AzNetworking //! Resets all internal metrics to defaults. void Reset(); + void LogPacketSent(uint32_t byteCount, AZ::TimeMs currentTimeMs); + void LogPacketRecv(uint32_t byteCount, AZ::TimeMs currentTimeMs); + void LogPacketLost(); + void LogPacketAcked(); + uint32_t m_packetsSent = 0; uint32_t m_packetsRecv = 0; uint32_t m_packetsLost = 0; diff --git a/Code/Framework/AzNetworking/AzNetworking/ConnectionLayer/ConnectionMetrics.inl b/Code/Framework/AzNetworking/AzNetworking/ConnectionLayer/ConnectionMetrics.inl index 5d7d18f709..5f196c4ed1 100644 --- a/Code/Framework/AzNetworking/AzNetworking/ConnectionLayer/ConnectionMetrics.inl +++ b/Code/Framework/AzNetworking/AzNetworking/ConnectionLayer/ConnectionMetrics.inl @@ -40,4 +40,33 @@ namespace AzNetworking { *this = ConnectionMetrics(); } + + inline void ConnectionMetrics::LogPacketSent(uint32_t byteCount, AZ::TimeMs currentTimeMs) + { + if (byteCount > 0) + { + m_packetsSent++; + } + m_sendDatarate.LogPacket(byteCount, currentTimeMs); + } + + inline void ConnectionMetrics::LogPacketRecv(uint32_t byteCount, AZ::TimeMs currentTimeMs) + { + if (byteCount > 0) + { + m_packetsRecv++; + } + m_recvDatarate.LogPacket(byteCount, currentTimeMs); + } + + inline void ConnectionMetrics::LogPacketLost() + { + m_packetsLost++; + m_sendDatarate.LogPacketLost(); + } + + inline void ConnectionMetrics::LogPacketAcked() + { + m_packetsAcked++; + } } diff --git a/Code/Framework/AzNetworking/AzNetworking/ConnectionLayer/IConnection.h b/Code/Framework/AzNetworking/AzNetworking/ConnectionLayer/IConnection.h index 1034f17585..363fd1d37b 100644 --- a/Code/Framework/AzNetworking/AzNetworking/ConnectionLayer/IConnection.h +++ b/Code/Framework/AzNetworking/AzNetworking/ConnectionLayer/IConnection.h @@ -95,11 +95,6 @@ namespace AzNetworking //! @return the max transmission unit for this connection virtual uint32_t GetConnectionMtu() const = 0; - //! Sets connection quality values for testing poor connection conditions. - //! Currently unsupported on TcpConnections - //! @param connectionQuality simulated connection quality values to use - virtual void SetConnectionQuality(const ConnectionQuality& connectionQuality) = 0; - //! Returns the connection identifier for this connection instance. //! @return the connection identifier for this connection instance ConnectionId GetConnectionId() const; @@ -128,12 +123,23 @@ namespace AzNetworking //! @return reference to the connection metric info ConnectionMetrics& GetMetrics(); + //! Retrieves debug connection quality settings. + //! Currently unsupported on TcpConnections + //! @return connection quality structure for this connection + const ConnectionQuality& GetConnectionQuality() const; + + //! Retrieves debug connection quality settings, non-const. + //! Currently unsupported on TcpConnections + //! @return connection quality structure for this connection + ConnectionQuality& GetConnectionQuality(); + private: // The following data members are here in the interface for performance reasons ConnectionId m_connectionId = InvalidConnectionId; IpAddress m_remoteAddress; ConnectionMetrics m_connectionMetrics; + ConnectionQuality m_connectionQuality; void* m_userData = nullptr; }; } diff --git a/Code/Framework/AzNetworking/AzNetworking/ConnectionLayer/IConnection.inl b/Code/Framework/AzNetworking/AzNetworking/ConnectionLayer/IConnection.inl index 646afac8f0..61e92010c7 100644 --- a/Code/Framework/AzNetworking/AzNetworking/ConnectionLayer/IConnection.inl +++ b/Code/Framework/AzNetworking/AzNetworking/ConnectionLayer/IConnection.inl @@ -59,4 +59,14 @@ namespace AzNetworking { return m_connectionMetrics; } + + inline const ConnectionQuality& IConnection::GetConnectionQuality() const + { + return m_connectionQuality; + } + + inline ConnectionQuality& IConnection::GetConnectionQuality() + { + return m_connectionQuality; + } } diff --git a/Code/Framework/AzNetworking/AzNetworking/TcpTransport/TcpConnection.cpp b/Code/Framework/AzNetworking/AzNetworking/TcpTransport/TcpConnection.cpp index ea746b9d00..1beb83e19f 100644 --- a/Code/Framework/AzNetworking/AzNetworking/TcpTransport/TcpConnection.cpp +++ b/Code/Framework/AzNetworking/AzNetworking/TcpTransport/TcpConnection.cpp @@ -122,7 +122,7 @@ namespace AzNetworking bool TcpConnection::UpdateRecv() { const AZ::TimeMs startTimeMs = AZ::GetElapsedTimeMs(); - GetMetrics().m_recvDatarate.LogPacket(0, startTimeMs); + GetMetrics().LogPacketRecv(0, startTimeMs); // Read new data off the input socket { @@ -261,11 +261,6 @@ namespace AzNetworking return 0; // do nothing, unsupported on TCP connections } - void TcpConnection::SetConnectionQuality([[maybe_unused]] const ConnectionQuality& connectionQuality) - { - ; // do nothing, unsupported on TCP connections - } - bool TcpConnection::SendPacketInternal(PacketType packetType, TcpPacketEncodingBuffer& payloadBuffer, AZ::TimeMs currentTimeMs) { AZ_Assert(payloadBuffer.GetCapacity() < AZStd::numeric_limits::max(), "Buffer capacity should be representable using 2 bytes or less"); @@ -333,8 +328,7 @@ namespace AzNetworking } m_sendRingbuffer.AdvanceWriteBuffer(headerSize + payloadSize); - GetMetrics().m_packetsSent++; - GetMetrics().m_sendDatarate.LogPacket(headerSize + payloadSize, currentTimeMs); + GetMetrics().LogPacketSent(headerSize + payloadSize, currentTimeMs); m_networkInterface.GetMetrics().m_sendPackets++; UpdateSend(); return true; @@ -379,8 +373,7 @@ namespace AzNetworking memcpy(dstData, srcData, packetSize); m_recvRingbuffer.AdvanceReadBuffer(serializer.GetReadSize() + packetSize); - GetMetrics().m_packetsRecv++; - GetMetrics().m_recvDatarate.LogPacket(packetSize, currentTimeMs); + GetMetrics().LogPacketRecv(packetSize, currentTimeMs); m_networkInterface.GetMetrics().m_recvPackets++; return true; } diff --git a/Code/Framework/AzNetworking/AzNetworking/TcpTransport/TcpConnection.h b/Code/Framework/AzNetworking/AzNetworking/TcpTransport/TcpConnection.h index af2c69292c..b769aea086 100644 --- a/Code/Framework/AzNetworking/AzNetworking/TcpTransport/TcpConnection.h +++ b/Code/Framework/AzNetworking/AzNetworking/TcpTransport/TcpConnection.h @@ -102,7 +102,6 @@ namespace AzNetworking bool Disconnect(DisconnectReason reason, TerminationEndpoint endpoint) override; void SetConnectionMtu(uint32_t connectionMtu) override; uint32_t GetConnectionMtu() const override; - void SetConnectionQuality(const ConnectionQuality& connectionQuality) override; // @} //! Sets the registered socket file descriptor for this TcpConnection in the associated ConnectionSet instance. diff --git a/Code/Framework/AzNetworking/AzNetworking/UdpTransport/UdpConnection.cpp b/Code/Framework/AzNetworking/AzNetworking/UdpTransport/UdpConnection.cpp index 798116d180..3efc6a51a8 100644 --- a/Code/Framework/AzNetworking/AzNetworking/UdpTransport/UdpConnection.cpp +++ b/Code/Framework/AzNetworking/AzNetworking/UdpTransport/UdpConnection.cpp @@ -152,7 +152,7 @@ namespace AzNetworking void UdpConnection::ProcessAcked(PacketId packetId, AZ::TimeMs currentTimeMs) { - GetMetrics().m_packetsAcked++; + GetMetrics().LogPacketAcked(); m_reliableQueue.OnPacketAcked(m_networkInterface, *this, packetId); // Compute Rtt adjustments @@ -172,8 +172,7 @@ namespace AzNetworking GetMetrics().m_connectionRtt.LogPacketSent(packetId, currentTimeMs); } - GetMetrics().m_packetsSent++; - GetMetrics().m_sendDatarate.LogPacket(packetSize, currentTimeMs); + GetMetrics().LogPacketSent(packetSize, currentTimeMs); m_lastSentPacketMs = currentTimeMs; m_unackedPacketCount = 0; } @@ -193,7 +192,7 @@ namespace AzNetworking return PacketTimeoutResult::Acked; case PacketAckState::Nacked: - GetMetrics().m_packetsLost++; + GetMetrics().LogPacketLost(); if (reliability == ReliabilityType::Reliable) { m_reliableQueue.OnPacketLost(m_networkInterface, *this, packetId); @@ -224,8 +223,7 @@ namespace AzNetworking return false; } - GetMetrics().m_packetsRecv++; - GetMetrics().m_recvDatarate.LogPacket(packetSize, currentTimeMs); + GetMetrics().LogPacketRecv(packetSize, currentTimeMs); if (header.GetIsReliable() && !m_reliableQueue.OnPacketReceived(header)) { diff --git a/Code/Framework/AzNetworking/AzNetworking/UdpTransport/UdpConnection.h b/Code/Framework/AzNetworking/AzNetworking/UdpTransport/UdpConnection.h index c8e0c2cdc9..67d626d6cb 100644 --- a/Code/Framework/AzNetworking/AzNetworking/UdpTransport/UdpConnection.h +++ b/Code/Framework/AzNetworking/AzNetworking/UdpTransport/UdpConnection.h @@ -66,13 +66,8 @@ namespace AzNetworking bool Disconnect(DisconnectReason reason, TerminationEndpoint endpoint) override; void SetConnectionMtu(uint32_t connectionMtu) override; uint32_t GetConnectionMtu() const override; - void SetConnectionQuality(const ConnectionQuality& connectionQuality) override; // @} - //! Gets connection quality values for testing poor connection conditions. - //! @return connection quality values for this IConnection instance - const ConnectionQuality& GetConnectionQuality() const; - //! Returns a suitable encryption endpoint for this connection type. //! @return reference to the connections encryption endpoint DtlsEndpoint& GetDtlsEndpoint(); @@ -146,8 +141,6 @@ namespace AzNetworking UdpFragmentQueue m_fragmentQueue; ConnectionState m_state = ConnectionState::Disconnected; ConnectionRole m_connectionRole = ConnectionRole::Connector; - - ConnectionQuality m_connectionQuality; DtlsEndpoint m_dtlsEndpoint; AZ::TimeMs m_lastSentPacketMs; @@ -160,4 +153,3 @@ namespace AzNetworking } #include - diff --git a/Code/Framework/AzNetworking/AzNetworking/UdpTransport/UdpConnection.inl b/Code/Framework/AzNetworking/AzNetworking/UdpTransport/UdpConnection.inl index 1ab273d53d..b31595263d 100644 --- a/Code/Framework/AzNetworking/AzNetworking/UdpTransport/UdpConnection.inl +++ b/Code/Framework/AzNetworking/AzNetworking/UdpTransport/UdpConnection.inl @@ -10,16 +10,6 @@ namespace AzNetworking { - inline void UdpConnection::SetConnectionQuality(const ConnectionQuality& connectionQuality) - { - m_connectionQuality = connectionQuality; - } - - inline const ConnectionQuality& UdpConnection::GetConnectionQuality() const - { - return m_connectionQuality; - } - inline DtlsEndpoint& UdpConnection::GetDtlsEndpoint() { return m_dtlsEndpoint; diff --git a/Code/Framework/AzNetworking/AzNetworking/UdpTransport/UdpNetworkInterface.cpp b/Code/Framework/AzNetworking/AzNetworking/UdpTransport/UdpNetworkInterface.cpp index 1a29dd4cae..a3ddb856d2 100644 --- a/Code/Framework/AzNetworking/AzNetworking/UdpTransport/UdpNetworkInterface.cpp +++ b/Code/Framework/AzNetworking/AzNetworking/UdpTransport/UdpNetworkInterface.cpp @@ -224,8 +224,7 @@ namespace AzNetworking continue; } - connection->GetMetrics().m_recvDatarate.LogPacket(packet.m_receivedBytes + UdpPacketHeaderSize, currentTimeMs); - connection->GetMetrics().m_packetsRecv++; + connection->GetMetrics().LogPacketRecv(packet.m_receivedBytes + UdpPacketHeaderSize, currentTimeMs); // Decode the packet flag bitset first since it's always uncompressed UdpPacketHeader header; diff --git a/Code/Framework/AzNetworking/AzNetworking/UdpTransport/UdpSocket.cpp b/Code/Framework/AzNetworking/AzNetworking/UdpTransport/UdpSocket.cpp index bb0b6d0fff..29a99f96a1 100644 --- a/Code/Framework/AzNetworking/AzNetworking/UdpTransport/UdpSocket.cpp +++ b/Code/Framework/AzNetworking/AzNetworking/UdpTransport/UdpSocket.cpp @@ -126,7 +126,7 @@ namespace AzNetworking #ifdef ENABLE_LATENCY_DEBUG if (connectionQuality.m_lossPercentage > 0) { - if (int32_t(m_random.GetRandom() % 100) < (connectionQuality.m_lossPercentage / 2)) + if (int32_t(m_random.GetRandom() % 100) < (connectionQuality.m_lossPercentage)) { // Pretend we sent, but don't actually send return true; @@ -157,9 +157,11 @@ namespace AzNetworking #ifdef ENABLE_LATENCY_DEBUG else if ((connectionQuality.m_latencyMs > AZ::TimeMs{ 0 }) || (connectionQuality.m_varianceMs > AZ::TimeMs{ 0 })) { - const AZ::TimeMs jitterMs = aznumeric_cast(m_random.GetRandom()) % (connectionQuality.m_varianceMs / aznumeric_cast(2)); + const AZ::TimeMs jitterMs = aznumeric_cast(m_random.GetRandom()) % (connectionQuality.m_varianceMs > AZ::TimeMs{ 0 } + ? connectionQuality.m_varianceMs + : AZ::TimeMs{ 1 }); const AZ::TimeMs currTimeMs = AZ::GetElapsedTimeMs(); - const AZ::TimeMs deferTimeMs = (connectionQuality.m_latencyMs / aznumeric_cast(2)) + jitterMs; + const AZ::TimeMs deferTimeMs = (connectionQuality.m_latencyMs) + jitterMs; DeferredData deferred = DeferredData(address, data, size, encrypt, dtlsEndpoint); AZ::Interface::Get()->AddCallback([&, deferredData = deferred] diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.cpp b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.cpp index 1611a3213d..4d2d47444c 100644 --- a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.cpp @@ -23,36 +23,30 @@ namespace Multiplayer ->Version(1); } } - void MultiplayerDebugSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) { provided.push_back(AZ_CRC_CE("MultiplayerDebugSystemComponent")); } - void MultiplayerDebugSystemComponent::GetRequiredServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& required) { ; } - void MultiplayerDebugSystemComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatbile) { incompatbile.push_back(AZ_CRC_CE("MultiplayerDebugSystemComponent")); } - void MultiplayerDebugSystemComponent::Activate() { #ifdef IMGUI_ENABLED ImGui::ImGuiUpdateListenerBus::Handler::BusConnect(); #endif } - void MultiplayerDebugSystemComponent::Deactivate() { #ifdef IMGUI_ENABLED ImGui::ImGuiUpdateListenerBus::Handler::BusDisconnect(); #endif } - #ifdef IMGUI_ENABLED void MultiplayerDebugSystemComponent::OnImGuiMainMenuUpdate() { @@ -63,7 +57,6 @@ namespace Multiplayer ImGui::EndMenu(); } } - void AccumulatePerSecondValues(const MultiplayerStats& stats, const MultiplayerStats::Metric& metric, float& outCallsPerSecond, float& outBytesPerSecond) { uint64_t summedCalls = 0; @@ -80,8 +73,9 @@ namespace Multiplayer bool DrawMetricsRow(const char* name, bool expandable, uint64_t totalCalls, uint64_t totalBytes, float callsPerSecond, float bytesPerSecond) { - const ImGuiTreeNodeFlags flags = expandable ? ImGuiTreeNodeFlags_SpanFullWidth - : (ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_SpanFullWidth); + const ImGuiTreeNodeFlags flags = expandable + ? ImGuiTreeNodeFlags_SpanFullWidth + : (ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_SpanFullWidth); ImGui::TableNextRow(); ImGui::TableNextColumn(); const bool open = ImGui::TreeNodeEx(name, flags); @@ -95,14 +89,12 @@ namespace Multiplayer ImGui::Text("%11.2f", bytesPerSecond); return open; } - bool DrawSummaryRow(const char* name, const MultiplayerStats& stats) { const MultiplayerStats::Metric propertyUpdatesSent = stats.CalculateTotalPropertyUpdateSentMetrics(); const MultiplayerStats::Metric propertyUpdatesRecv = stats.CalculateTotalPropertyUpdateRecvMetrics(); const MultiplayerStats::Metric rpcsSent = stats.CalculateTotalRpcsSentMetrics(); const MultiplayerStats::Metric rpcsRecv = stats.CalculateTotalRpcsRecvMetrics(); - const uint64_t totalCalls = propertyUpdatesSent.m_totalCalls + propertyUpdatesRecv.m_totalCalls + rpcsSent.m_totalCalls + rpcsRecv.m_totalCalls; const uint64_t totalBytes = propertyUpdatesSent.m_totalBytes + propertyUpdatesRecv.m_totalBytes + rpcsSent.m_totalBytes + rpcsRecv.m_totalBytes; float callsPerSecond = 0.0f; @@ -111,17 +103,14 @@ namespace Multiplayer AccumulatePerSecondValues(stats, propertyUpdatesRecv, callsPerSecond, bytesPerSecond); AccumulatePerSecondValues(stats, rpcsSent, callsPerSecond, bytesPerSecond); AccumulatePerSecondValues(stats, rpcsRecv, callsPerSecond, bytesPerSecond); - return DrawMetricsRow(name, true, totalCalls, totalBytes, callsPerSecond, bytesPerSecond); } - bool DrawComponentRow(const char* name, const MultiplayerStats& stats, NetComponentId netComponentId) { const MultiplayerStats::Metric propertyUpdatesSent = stats.CalculateComponentPropertyUpdateSentMetrics(netComponentId); const MultiplayerStats::Metric propertyUpdatesRecv = stats.CalculateComponentPropertyUpdateRecvMetrics(netComponentId); const MultiplayerStats::Metric rpcsSent = stats.CalculateComponentRpcsSentMetrics(netComponentId); const MultiplayerStats::Metric rpcsRecv = stats.CalculateComponentRpcsRecvMetrics(netComponentId); - const uint64_t totalCalls = propertyUpdatesSent.m_totalCalls + propertyUpdatesRecv.m_totalCalls + rpcsSent.m_totalCalls + rpcsRecv.m_totalCalls; const uint64_t totalBytes = propertyUpdatesSent.m_totalBytes + propertyUpdatesRecv.m_totalBytes + rpcsSent.m_totalBytes + rpcsRecv.m_totalBytes; float callsPerSecond = 0.0f; @@ -130,10 +119,8 @@ namespace Multiplayer AccumulatePerSecondValues(stats, propertyUpdatesRecv, callsPerSecond, bytesPerSecond); AccumulatePerSecondValues(stats, rpcsSent, callsPerSecond, bytesPerSecond); AccumulatePerSecondValues(stats, rpcsRecv, callsPerSecond, bytesPerSecond); - return DrawMetricsRow(name, true, totalCalls, totalBytes, callsPerSecond, bytesPerSecond); } - void DrawComponentDetails(const MultiplayerStats& stats, NetComponentId netComponentId) { MultiplayerComponentRegistry* componentRegistry = GetMultiplayerComponentRegistry(); @@ -158,7 +145,6 @@ namespace Multiplayer ImGui::TreePop(); } } - { const MultiplayerStats::Metric metric = stats.CalculateComponentPropertyUpdateRecvMetrics(netComponentId); float callsPerSecond = 0.0f; @@ -180,7 +166,6 @@ namespace Multiplayer ImGui::TreePop(); } } - { const MultiplayerStats::Metric metric = stats.CalculateComponentRpcsSentMetrics(netComponentId); float callsPerSecond = 0.0f; @@ -202,7 +187,6 @@ namespace Multiplayer ImGui::TreePop(); } } - { const MultiplayerStats::Metric metric = stats.CalculateComponentRpcsRecvMetrics(netComponentId); float callsPerSecond = 0.0f; @@ -226,96 +210,226 @@ namespace Multiplayer } } - void MultiplayerDebugSystemComponent::OnImGuiUpdate() + void DrawNetworkingStats() { const float TEXT_BASE_WIDTH = ImGui::CalcTextSize("A").x; const float TEXT_BASE_HEIGHT = ImGui::GetTextLineHeightWithSpacing(); - if (m_displayNetworkingStats) - { - if (ImGui::Begin("Networking Stats", &m_displayNetworkingStats, ImGuiWindowFlags_None)) - { - AzNetworking::INetworking* networking = AZ::Interface::Get(); + const ImGuiTableFlags flags = ImGuiTableFlags_BordersV + | ImGuiTableFlags_BordersOuterH + | ImGuiTableFlags_Resizable + | ImGuiTableFlags_RowBg + | ImGuiTableFlags_NoBordersInBody; - ImGui::Text("Total sockets monitored by TcpListenThread: %u", networking->GetTcpListenThreadSocketCount()); - ImGui::Text("Total time spent updating TcpListenThread: %lld", aznumeric_cast(networking->GetTcpListenThreadUpdateTime())); - ImGui::Text("Total sockets monitored by UdpReaderThread: %u", networking->GetUdpReaderThreadSocketCount()); - ImGui::Text("Total time spent updating UdpReaderThread: %lld", aznumeric_cast(networking->GetUdpReaderThreadUpdateTime())); + const ImGuiTreeNodeFlags nodeFlags = (ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_SpanFullWidth); - for (auto& networkInterface : networking->GetNetworkInterfaces()) - { - const char* protocol = networkInterface.second->GetType() == AzNetworking::ProtocolType::Tcp ? "Tcp" : "Udp"; - const char* trustZone = networkInterface.second->GetTrustZone() == AzNetworking::TrustZone::ExternalClientToServer ? "ExternalClientToServer" : "InternalServerToServer"; - const uint32_t port = aznumeric_cast(networkInterface.second->GetPort()); - ImGui::Text("%sNetworkInterface: %s - open to %s on port %u", protocol, networkInterface.second->GetName().GetCStr(), trustZone, port); + AzNetworking::INetworking* networking = AZ::Interface::Get(); - const AzNetworking::NetworkInterfaceMetrics& metrics = networkInterface.second->GetMetrics(); - ImGui::Text(" - Total time spent updating in milliseconds: %lld", aznumeric_cast(metrics.m_updateTimeMs)); - ImGui::Text(" - Total number of connections: %llu", aznumeric_cast(metrics.m_connectionCount)); - ImGui::Text(" - Total send time in milliseconds: %lld", aznumeric_cast(metrics.m_sendTimeMs)); - ImGui::Text(" - Total sent packets: %llu", aznumeric_cast(metrics.m_sendPackets)); - ImGui::Text(" - Total sent bytes after compression: %llu", aznumeric_cast(metrics.m_sendBytes)); - ImGui::Text(" - Total sent bytes before compression: %llu", aznumeric_cast(metrics.m_sendBytesUncompressed)); - ImGui::Text(" - Total sent compressed packets without benefit: %llu", aznumeric_cast(metrics.m_sendCompressedPacketsNoGain)); - ImGui::Text(" - Total gain from packet compression: %lld", aznumeric_cast(metrics.m_sendBytesCompressedDelta)); - ImGui::Text(" - Total packets resent: %llu", aznumeric_cast(metrics.m_resentPackets)); - ImGui::Text(" - Total receive time in milliseconds: %lld", aznumeric_cast(metrics.m_recvTimeMs)); - ImGui::Text(" - Total received packets: %llu", aznumeric_cast(metrics.m_recvPackets)); - ImGui::Text(" - Total received bytes after compression: %llu", aznumeric_cast(metrics.m_recvBytes)); - ImGui::Text(" - Total received bytes before compression: %llu", aznumeric_cast(metrics.m_recvBytesUncompressed)); - ImGui::Text(" - Total packets discarded due to load: %llu", aznumeric_cast(metrics.m_discardedPackets)); - } - } - } + ImGui::Text("Total sockets monitored by TcpListenThread: %u", networking->GetTcpListenThreadSocketCount()); + ImGui::Text("Total time spent updating TcpListenThread: %lld", aznumeric_cast(networking->GetTcpListenThreadUpdateTime())); + ImGui::Text("Total sockets monitored by UdpReaderThread: %u", networking->GetUdpReaderThreadSocketCount()); + ImGui::Text("Total time spent updating UdpReaderThread: %lld", aznumeric_cast(networking->GetUdpReaderThreadUpdateTime())); + ImGui::NewLine(); - if (m_displayMultiplayerStats) + for (auto& networkInterface : networking->GetNetworkInterfaces()) { - if (ImGui::Begin("Multiplayer Stats", &m_displayMultiplayerStats, ImGuiWindowFlags_None)) + if (ImGui::CollapsingHeader(networkInterface.second->GetName().GetCStr())) { - IMultiplayer* multiplayer = AZ::Interface::Get(); - MultiplayerComponentRegistry* componentRegistry = GetMultiplayerComponentRegistry(); - const Multiplayer::MultiplayerStats& stats = multiplayer->GetStats(); - ImGui::Text("Multiplayer operating in %s mode", GetEnumString(multiplayer->GetAgentType())); - ImGui::Text("Total networked entities: %llu", aznumeric_cast(stats.m_entityCount)); - ImGui::Text("Total client connections: %llu", aznumeric_cast(stats.m_clientConnectionCount)); - ImGui::Text("Total server connections: %llu", aznumeric_cast(stats.m_serverConnectionCount)); - ImGui::NewLine(); + const char* protocol = networkInterface.second->GetType() == AzNetworking::ProtocolType::Tcp ? "Tcp" : "Udp"; + const char* trustZone = networkInterface.second->GetTrustZone() == AzNetworking::TrustZone::ExternalClientToServer ? "ExternalClientToServer" : "InternalServerToServer"; + const uint32_t port = aznumeric_cast(networkInterface.second->GetPort()); + ImGui::Text("%sNetworkInterface open to %s on port %u", protocol, trustZone, port); - static ImGuiTableFlags flags = ImGuiTableFlags_BordersV - | ImGuiTableFlags_BordersOuterH - | ImGuiTableFlags_Resizable - | ImGuiTableFlags_RowBg - | ImGuiTableFlags_NoBordersInBody; + if (ImGui::BeginTable("", 2, flags)) + { + const AzNetworking::NetworkInterfaceMetrics& metrics = networkInterface.second->GetMetrics(); + ImGui::TableSetupColumn("Stat", ImGuiTableColumnFlags_WidthStretch); + ImGui::TableSetupColumn("Value", ImGuiTableColumnFlags_WidthFixed, TEXT_BASE_WIDTH * 12.0f); + ImGui::TableHeadersRow(); + ImGui::TableNextRow(); ImGui::TableNextColumn(); + ImGui::Text("Total time spent updating (ms)"); + ImGui::TableNextColumn(); + ImGui::Text("%lld", aznumeric_cast(metrics.m_updateTimeMs)); + ImGui::TableNextRow(); ImGui::TableNextColumn(); + ImGui::Text("Total number of connections"); + ImGui::TableNextColumn(); + ImGui::Text("%llu", aznumeric_cast(metrics.m_connectionCount)); + ImGui::TableNextRow(); ImGui::TableNextColumn(); + ImGui::Text("Total send time (ms)"); + ImGui::TableNextColumn(); + ImGui::Text("%lld", aznumeric_cast(metrics.m_sendTimeMs)); + ImGui::TableNextRow(); ImGui::TableNextColumn(); + ImGui::Text("Total sent packets"); + ImGui::TableNextColumn(); + ImGui::Text("%llu", aznumeric_cast(metrics.m_sendPackets)); + ImGui::TableNextRow(); ImGui::TableNextColumn(); + ImGui::Text("Total sent bytes after compression"); + ImGui::TableNextColumn(); + ImGui::Text("%llu", aznumeric_cast(metrics.m_sendBytes)); + ImGui::TableNextRow(); ImGui::TableNextColumn(); + ImGui::Text("Total sent bytes before compression"); + ImGui::TableNextColumn(); + ImGui::Text("%llu", aznumeric_cast(metrics.m_sendBytesUncompressed)); + ImGui::TableNextRow(); ImGui::TableNextColumn(); + ImGui::Text("Total sent compressed packets without benefit"); + ImGui::TableNextColumn(); + ImGui::Text("%llu", aznumeric_cast(metrics.m_sendCompressedPacketsNoGain)); + ImGui::TableNextRow(); ImGui::TableNextColumn(); + ImGui::Text("Total gain from packet compression"); + ImGui::TableNextColumn(); + ImGui::Text("%lld", aznumeric_cast(metrics.m_sendBytesCompressedDelta)); + ImGui::TableNextRow(); ImGui::TableNextColumn(); + ImGui::Text("Total packets resent"); + ImGui::TableNextColumn(); + ImGui::Text("%llu", aznumeric_cast(metrics.m_resentPackets)); + ImGui::TableNextRow(); ImGui::TableNextColumn(); + ImGui::Text("Total receive time (ms)"); + ImGui::TableNextColumn(); + ImGui::Text("%lld", aznumeric_cast(metrics.m_recvTimeMs)); + ImGui::TableNextRow(); ImGui::TableNextColumn(); + ImGui::Text("Total received packets"); + ImGui::TableNextColumn(); + ImGui::Text("%llu", aznumeric_cast(metrics.m_recvPackets)); + ImGui::TableNextRow(); ImGui::TableNextColumn(); + ImGui::Text("Total received bytes after compression"); + ImGui::TableNextColumn(); + ImGui::Text("%llu", aznumeric_cast(metrics.m_recvBytes)); + ImGui::TableNextRow(); ImGui::TableNextColumn(); + ImGui::Text("Total received bytes before compression"); + ImGui::TableNextColumn(); + ImGui::Text("%llu", aznumeric_cast(metrics.m_recvBytesUncompressed)); + ImGui::TableNextRow(); ImGui::TableNextColumn(); + ImGui::Text("Total packets discarded due to load"); + ImGui::TableNextColumn(); + ImGui::Text("%llu", aznumeric_cast(metrics.m_discardedPackets)); + ImGui::EndTable(); + } - if (ImGui::BeginTable("", 5, flags)) + if (ImGui::BeginTable("", 7, flags)) { // The first column will use the default _WidthStretch when ScrollX is Off and _WidthFixed when ScrollX is On - ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthStretch); - ImGui::TableSetupColumn("Total Calls", ImGuiTableColumnFlags_WidthFixed, TEXT_BASE_WIDTH * 12.0f); - ImGui::TableSetupColumn("Total Bytes", ImGuiTableColumnFlags_WidthFixed, TEXT_BASE_WIDTH * 12.0f); - ImGui::TableSetupColumn("Calls/Sec", ImGuiTableColumnFlags_WidthFixed, TEXT_BASE_WIDTH * 12.0f); - ImGui::TableSetupColumn("Bytes/Sec", ImGuiTableColumnFlags_WidthFixed, TEXT_BASE_WIDTH * 12.0f); + ImGui::TableSetupColumn("RemoteAddr", ImGuiTableColumnFlags_WidthStretch); + ImGui::TableSetupColumn("Conn. Id", ImGuiTableColumnFlags_WidthFixed, TEXT_BASE_WIDTH * 6.0f); + ImGui::TableSetupColumn("Send (Bps)", ImGuiTableColumnFlags_WidthFixed, TEXT_BASE_WIDTH * 10.0f); + ImGui::TableSetupColumn("Recv (Bps)", ImGuiTableColumnFlags_WidthFixed, TEXT_BASE_WIDTH * 10.0f); + ImGui::TableSetupColumn("RTT (ms)", ImGuiTableColumnFlags_WidthFixed, TEXT_BASE_WIDTH * 8.0f); + ImGui::TableSetupColumn("% Lost", ImGuiTableColumnFlags_WidthFixed, TEXT_BASE_WIDTH * 8.0f); + ImGui::TableSetupColumn("Debug Settings", ImGuiTableColumnFlags_WidthFixed, TEXT_BASE_WIDTH * 32.0f); ImGui::TableHeadersRow(); - if (DrawSummaryRow("Totals", stats)) + auto displayConnectionRow = [](AzNetworking::IConnection& connection) { - for (AZStd::size_t index = 0; index < stats.m_componentStats.size(); ++index) + ImGui::PushID(&connection); + + const AzNetworking::ConnectionMetrics& metrics = connection.GetMetrics(); + const AzNetworking::IpAddress::IpString remoteAddr = connection.GetRemoteAddress().GetString(); + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::TreeNodeEx(remoteAddr.c_str(), nodeFlags); + ImGui::TableNextColumn(); + ImGui::Text("%5llu", aznumeric_cast(connection.GetConnectionId())); + ImGui::TableNextColumn(); + ImGui::Text("%9.2f", metrics.m_sendDatarate.GetBytesPerSecond()); + ImGui::TableNextColumn(); + ImGui::Text("%9.2f", metrics.m_recvDatarate.GetBytesPerSecond()); + ImGui::TableNextColumn(); + ImGui::Text("%7.2f", metrics.m_connectionRtt.GetRoundTripTimeSeconds() * 1000.0f); + ImGui::TableNextColumn(); + ImGui::Text("%7.2f", metrics.m_sendDatarate.GetLossRatePercent()); + ImGui::TableNextColumn(); + { - const NetComponentId netComponentId = aznumeric_cast(index); - using StringLabel = AZStd::fixed_string<128>; - const StringLabel gemName = componentRegistry->GetComponentGemName(netComponentId); - const StringLabel componentName = componentRegistry->GetComponentName(netComponentId); - const StringLabel label = gemName + "::" + componentName; - if (DrawComponentRow(label.c_str(), stats, netComponentId)) + AzNetworking::ConnectionQuality& quality = connection.GetConnectionQuality(); + int32_t latency = aznumeric_cast(quality.m_latencyMs); + int32_t variance = aznumeric_cast(quality.m_varianceMs); + ImGui::SliderInt("Loss %", &quality.m_lossPercentage, 0, 100); + if (ImGui::SliderInt("Latency(ms)", &latency, 0, 3000)) + { + quality.m_latencyMs = AZ::TimeMs{ latency }; + } + if (ImGui::SliderInt("Jitter(ms)", &variance, 0, 1000)) { - DrawComponentDetails(stats, netComponentId); - ImGui::TreePop(); + quality.m_varianceMs = AZ::TimeMs{ variance }; } } - } + ImGui::PopID(); + }; + networkInterface.second->GetConnectionSet().VisitConnections(displayConnectionRow); ImGui::EndTable(); } - ImGui::End(); + } + ImGui::NewLine(); + } + ImGui::End(); + } + + void DrawMultiplayerStats() + { + const float TEXT_BASE_WIDTH = ImGui::CalcTextSize("A").x; + const float TEXT_BASE_HEIGHT = ImGui::GetTextLineHeightWithSpacing(); + + IMultiplayer* multiplayer = AZ::Interface::Get(); + MultiplayerComponentRegistry* componentRegistry = GetMultiplayerComponentRegistry(); + const Multiplayer::MultiplayerStats& stats = multiplayer->GetStats(); + ImGui::Text("Multiplayer operating in %s mode", GetEnumString(multiplayer->GetAgentType())); + ImGui::Text("Total networked entities: %llu", aznumeric_cast(stats.m_entityCount)); + ImGui::Text("Total client connections: %llu", aznumeric_cast(stats.m_clientConnectionCount)); + ImGui::Text("Total server connections: %llu", aznumeric_cast(stats.m_serverConnectionCount)); + ImGui::NewLine(); + + static ImGuiTableFlags flags = ImGuiTableFlags_BordersV + | ImGuiTableFlags_BordersOuterH + | ImGuiTableFlags_Resizable + | ImGuiTableFlags_RowBg + | ImGuiTableFlags_NoBordersInBody; + + if (ImGui::BeginTable("", 5, flags)) + { + // The first column will use the default _WidthStretch when ScrollX is Off and _WidthFixed when ScrollX is On + ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthStretch); + ImGui::TableSetupColumn("Total Calls", ImGuiTableColumnFlags_WidthFixed, TEXT_BASE_WIDTH * 12.0f); + ImGui::TableSetupColumn("Total Bytes", ImGuiTableColumnFlags_WidthFixed, TEXT_BASE_WIDTH * 12.0f); + ImGui::TableSetupColumn("Calls/Sec", ImGuiTableColumnFlags_WidthFixed, TEXT_BASE_WIDTH * 12.0f); + ImGui::TableSetupColumn("Bytes/Sec", ImGuiTableColumnFlags_WidthFixed, TEXT_BASE_WIDTH * 12.0f); + ImGui::TableHeadersRow(); + + if (DrawSummaryRow("Totals", stats)) + { + for (AZStd::size_t index = 0; index < stats.m_componentStats.size(); ++index) + { + const NetComponentId netComponentId = aznumeric_cast(index); + using StringLabel = AZStd::fixed_string<128>; + const StringLabel gemName = componentRegistry->GetComponentGemName(netComponentId); + const StringLabel componentName = componentRegistry->GetComponentName(netComponentId); + const StringLabel label = gemName + "::" + componentName; + if (DrawComponentRow(label.c_str(), stats, netComponentId)) + { + DrawComponentDetails(stats, netComponentId); + ImGui::TreePop(); + } + } + } + ImGui::EndTable(); + ImGui::NewLine(); + } + ImGui::End(); + } + + void MultiplayerDebugSystemComponent::OnImGuiUpdate() + { + if (m_displayNetworkingStats) + { + if (ImGui::Begin("Networking Stats", &m_displayNetworkingStats, ImGuiWindowFlags_None)) + { + DrawNetworkingStats(); + } + } + + if (m_displayMultiplayerStats) + { + if (ImGui::Begin("Multiplayer Stats", &m_displayMultiplayerStats, ImGuiWindowFlags_None)) + { + DrawMultiplayerStats(); } } } From 4b97a416a39b9dfe87b9c05b2fa9486b23534406 Mon Sep 17 00:00:00 2001 From: Dayo Lawal Date: Tue, 27 Jul 2021 02:06:33 -0500 Subject: [PATCH 054/160] GetCriticalAssetFilters() Signed-off-by: Dayo Lawal --- .../Application/AtomToolsApplication.h | 8 +++- .../Application/AtomToolsApplication.cpp | 45 ++++++++++++++++--- .../Code/Source/MaterialEditorApplication.cpp | 37 +++------------ .../Code/Source/MaterialEditorApplication.h | 8 +--- .../ShaderManagementConsoleApplication.cpp | 39 +++------------- .../ShaderManagementConsoleApplication.h | 8 +--- 6 files changed, 62 insertions(+), 83 deletions(-) diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h index 9d412ec477..08eac727a3 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h @@ -62,6 +62,11 @@ namespace AtomToolsFramework void Destroy() override; ////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////// + // AzFramework::AssetSystemStatusBus::Handler overrides... + void AssetSystemAvailable() override; + ////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////// // AZ::ComponentApplication overrides... void QueryApplicationType(AZ::ApplicationTypeQuery& appType) const override; @@ -79,7 +84,8 @@ namespace AtomToolsFramework void OnExceptionMessage(AZStd::string_view message) override; //////////////////////////////////////////////////////////////////////// - virtual AZStd::string GetBuildTargetName(); + virtual AZStd::string GetBuildTargetName() const; + virtual AZStd::vector GetCriticalAssetFilters() const; virtual void LoadSettings(); virtual void UnloadSettings(); diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp index 0ee06d3fc2..2aeb53db90 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp @@ -39,7 +39,7 @@ AZ_POP_DISABLE_WARNING namespace AtomToolsFramework { - AZStd::string AtomToolsApplication::GetBuildTargetName() + AZStd::string AtomToolsApplication::GetBuildTargetName() const { return AZStd::string("AtomTools"); } @@ -69,7 +69,7 @@ namespace AtomToolsFramework void AtomToolsApplication::Reflect(AZ::ReflectContext* context) { - Application::Reflect(context); + Base::Reflect(context); AzToolsFramework::AssetBrowser::AssetBrowserEntry::Reflect(context); AzToolsFramework::AssetBrowser::RootAssetBrowserEntry::Reflect(context); @@ -82,13 +82,12 @@ namespace AtomToolsFramework if (auto behaviorContext = azrtti_cast(context)) { - AZStd::string fileName = GetBuildTargetName() + ".general"; // this will put these methods into the 'azlmbr.AtomTools.general' module - auto addGeneral = [fileName](AZ::BehaviorContext::GlobalMethodBuilder methodBuilder) + auto addGeneral = [](AZ::BehaviorContext::GlobalMethodBuilder methodBuilder) { methodBuilder->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation) ->Attribute(AZ::Script::Attributes::Category, "Editor") - ->Attribute(AZ::Script::Attributes::Module, fileName); + ->Attribute(AZ::Script::Attributes::Module, "AtomTools"); }; // The reflection here is based on patterns in CryEditPythonHandler::Reflect addGeneral(behaviorContext->Method( @@ -150,6 +149,42 @@ namespace AtomToolsFramework Base::Destroy(); } + AZStd::vector AtomToolsApplication::GetCriticalAssetFilters() const + { + // List of common asset filters for things that need to be compiled to run the material editor + // Some of these things will not be necessary once we have proper support for queued asset loading and reloading + return AZStd::vector({ "passes/", "config/" }); + } + + void AtomToolsApplication::AssetSystemAvailable() + { + bool connectedToAssetProcessor = false; + + // When the AssetProcessor is already launched it should take less than a second to perform a connection + // but when the AssetProcessor needs to be launch it could take up to 15 seconds to have the AssetProcessor initialize + // and able to negotiate a connection when running a debug build + // and to negotiate a connection + + AzFramework::AssetSystem::ConnectionSettings connectionSettings; + AzFramework::AssetSystem::ReadConnectionSettingsFromSettingsRegistry(connectionSettings); + connectionSettings.m_connectionDirection = + AzFramework::AssetSystem::ConnectionSettings::ConnectionDirection::ConnectToAssetProcessor; + connectionSettings.m_connectionIdentifier = GetBuildTargetName(); + connectionSettings.m_loggingCallback = []([[maybe_unused]] AZStd::string_view logData) + { + AZ_TracePrintf("Atom Tools", "%.*s", aznumeric_cast(logData.size()), logData.data()); + }; + AzFramework::AssetSystemRequestBus::BroadcastResult( + connectedToAssetProcessor, &AzFramework::AssetSystemRequestBus::Events::EstablishAssetProcessorConnection, connectionSettings); + + if (connectedToAssetProcessor) + { + CompileCriticalAssets(GetCriticalAssetFilters()); + } + + AzFramework::AssetSystemStatusBus::Handler::BusDisconnect(); + } + void AtomToolsApplication::CompileCriticalAssets(const AZStd::vector &assetFiltersArray) { AZ_TracePrintf(GetBuildTargetName().c_str(), "Compiling critical assets.\n"); diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp index 6832ca683c..57313c6694 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp @@ -51,7 +51,7 @@ AZ_POP_DISABLE_WARNING namespace MaterialEditor { //! This function returns the build system target name of "MaterialEditor - AZStd::string MaterialEditorApplication::GetBuildTargetName() + AZStd::string MaterialEditorApplication::GetBuildTargetName() const { #if !defined (LY_CMAKE_TARGET) #error "LY_CMAKE_TARGET must be defined in order to add this source file to a CMake executable target" @@ -117,36 +117,11 @@ namespace MaterialEditor Base::Destroy(); } - void MaterialEditorApplication::AssetSystemAvailable() + AZStd::vector MaterialEditorApplication::GetCriticalAssetFilters() const { - bool connectedToAssetProcessor = false; - - // When the AssetProcessor is already launched it should take less than a second to perform a connection - // but when the AssetProcessor needs to be launch it could take up to 15 seconds to have the AssetProcessor initialize - // and able to negotiate a connection when running a debug build - // and to negotiate a connection - - AzFramework::AssetSystem::ConnectionSettings connectionSettings; - AzFramework::AssetSystem::ReadConnectionSettingsFromSettingsRegistry(connectionSettings); - connectionSettings.m_connectionDirection = AzFramework::AssetSystem::ConnectionSettings::ConnectionDirection::ConnectToAssetProcessor; - connectionSettings.m_connectionIdentifier = GetBuildTargetName(); - connectionSettings.m_loggingCallback = []([[maybe_unused]] AZStd::string_view logData) - { - AZ_TracePrintf("Material Editor", "%.*s", aznumeric_cast(logData.size()), logData.data()); - }; - AzFramework::AssetSystemRequestBus::BroadcastResult(connectedToAssetProcessor, - &AzFramework::AssetSystemRequestBus::Events::EstablishAssetProcessorConnection, connectionSettings); - - if (connectedToAssetProcessor) - { - // List of common asset filters for things that need to be compiled to run the material editor - // Some of these things will not be necessary once we have proper support for queued asset loading and reloading - const AZStd::vector assetFiltersArray = { "passes/", "config/", "MaterialEditor/" }; - - CompileCriticalAssets(assetFiltersArray); - } - - AzFramework::AssetSystemStatusBus::Handler::BusDisconnect(); + // List of common asset filters for things that need to be compiled to run the material editor + // Some of these things will not be necessary once we have proper support for queued asset loading and reloading + return AZStd::vector({ "passes/", "config/", "MaterialEditor" }); } void MaterialEditorApplication::ProcessCommandLine(const AZ::CommandLine& commandLine) @@ -164,7 +139,7 @@ namespace MaterialEditor { const AZStd::string openDocumentPath = commandLine.GetMiscValue(openDocumentIndex); - AZ_Printf("MaterialEditor", "Opening document: %s", openDocumentPath.c_str()); + AZ_Printf(GetBuildTargetName().c_str(), "Opening document: %s", openDocumentPath.c_str()); MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::OpenDocument, openDocumentPath); } diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h index 1139a73827..0177013a3d 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h @@ -46,13 +46,9 @@ namespace MaterialEditor void Destroy() override; ////////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////// - // AzFramework::AssetSystemStatusBus::Handler overrides... - void AssetSystemAvailable() override; - ////////////////////////////////////////////////////////////////////////// - void ProcessCommandLine(const AZ::CommandLine& commandLine) override; void StartInternal() override; - AZStd::string GetBuildTargetName() override; + AZStd::string GetBuildTargetName() const override; + AZStd::vector GetCriticalAssetFilters() const override; }; } // namespace MaterialEditor diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp index 6d5e331c75..6f6ee697d5 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp @@ -47,7 +47,7 @@ AZ_POP_DISABLE_WARNING namespace ShaderManagementConsole { - AZStd::string ShaderManagementConsoleApplication::GetBuildTargetName() + AZStd::string ShaderManagementConsoleApplication::GetBuildTargetName() const { #if !defined (LY_CMAKE_TARGET) #error "LY_CMAKE_TARGET must be defined in order to add this source file to a CMake executable target" @@ -100,40 +100,11 @@ namespace ShaderManagementConsole Base::Destroy(); } - void ShaderManagementConsoleApplication::AssetSystemAvailable() + AZStd::vector ShaderManagementConsoleApplication::GetCriticalAssetFilters() const { - // Try connect to AP first before try to launch it manually. - bool connected = false; - auto ConnectToAssetProcessorWithIdentifier = [&connected](AzFramework::AssetSystem::AssetSystemRequests* assetSystemRequests) - { - // When the AssetProcessor is already launched it should take less than a second to perform a connection - // but when the AssetProcessor needs to be launch it could take up to 15 seconds to have the AssetProcessor initialize - // and able to negotiate a connection when running a debug build - // and to negotiate a connection - - AzFramework::AssetSystem::ConnectionSettings connectionSettings; - AzFramework::AssetSystem::ReadConnectionSettingsFromSettingsRegistry(connectionSettings); - connectionSettings.m_connectionDirection = AzFramework::AssetSystem::ConnectionSettings::ConnectionDirection::ConnectToAssetProcessor; - connectionSettings.m_connectionIdentifier = "Shader Management Console"; - connectionSettings.m_loggingCallback = []([[maybe_unused]] AZStd::string_view logData) - { - AZ_TracePrintf("Shader Management Console", "%.*s", aznumeric_cast(logData.size()), logData.data()); - }; - - connected = assetSystemRequests->EstablishAssetProcessorConnection(connectionSettings); - }; - AzFramework::AssetSystemRequestBus::Broadcast(ConnectToAssetProcessorWithIdentifier); - - if (connected) - { - // List of common asset filters for things that need to be compiled to run the material editor - // Some of these things will not be necessary once we have proper support for queued asset loading and reloading - const AZStd::vector assetFiltersArray = { "passes/", "config/" }; - - CompileCriticalAssets(assetFiltersArray); - } - - AzFramework::AssetSystemStatusBus::Handler::BusDisconnect(); + // List of common asset filters for things that need to be compiled to run the material editor + // Some of these things will not be necessary once we have proper support for queued asset loading and reloading + return AZStd::vector({ "passes/", "config/" }); } void ShaderManagementConsoleApplication::ProcessCommandLine() diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h index 42817040ce..6229f5d77d 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h @@ -43,13 +43,9 @@ namespace ShaderManagementConsole void Destroy() override; ////////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////// - // AzFramework::AssetSystemStatusBus::Handler overrides... - void AssetSystemAvailable() override; - ////////////////////////////////////////////////////////////////////////// - void ProcessCommandLine(); void StartInternal() override; - AZStd::string GetBuildTargetName() override; + AZStd::string GetBuildTargetName() const override; + AZStd::vector GetCriticalAssetFilters() const override; }; } // namespace ShaderManagementConsole From 61038ccd0316bdc9dfec5ecdd0f0b4828e9af179 Mon Sep 17 00:00:00 2001 From: Dayo Lawal Date: Tue, 27 Jul 2021 02:09:45 -0500 Subject: [PATCH 055/160] Reflect() Signed-off-by: Dayo Lawal --- .../Code/Source/Application/AtomToolsApplication.cpp | 4 ++-- .../MaterialEditor/Code/Source/MaterialEditorApplication.cpp | 5 +++++ .../MaterialEditor/Code/Source/MaterialEditorApplication.h | 1 + .../Code/Source/ShaderManagementConsoleApplication.cpp | 5 +++++ .../Code/Source/ShaderManagementConsoleApplication.h | 1 + 5 files changed, 14 insertions(+), 2 deletions(-) diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp index 2aeb53db90..5e817f0125 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp @@ -98,7 +98,7 @@ namespace AtomToolsFramework void AtomToolsApplication::RegisterCoreComponents() { - Application::RegisterCoreComponents(); + Base::RegisterCoreComponents(); RegisterComponentDescriptor(AzToolsFramework::AssetBrowser::AssetBrowserComponent::CreateDescriptor()); RegisterComponentDescriptor(AzToolsFramework::Thumbnailer::ThumbnailerComponent::CreateDescriptor()); RegisterComponentDescriptor(AzToolsFramework::Components::PropertyManagerComponent::CreateDescriptor()); @@ -108,7 +108,7 @@ namespace AtomToolsFramework AZ::ComponentTypeList AtomToolsApplication::GetRequiredSystemComponents() const { - AZ::ComponentTypeList components = Application::GetRequiredSystemComponents(); + AZ::ComponentTypeList components = Base::GetRequiredSystemComponents(); components.insert( components.end(), diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp index 57313c6694..02c2af2266 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp @@ -93,6 +93,11 @@ namespace MaterialEditor AzToolsFramework::EditorPythonConsoleNotificationBus::Handler::BusDisconnect(); } + void MaterialEditorApplication::Reflect(AZ::ReflectContext* context) + { + Base::Reflect(); + } + void MaterialEditorApplication::CreateStaticModules(AZStd::vector& outModules) { Base::CreateStaticModules(outModules); diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h index 0177013a3d..bbe5a26141 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h @@ -32,6 +32,7 @@ namespace MaterialEditor ////////////////////////////////////////////////////////////////////////// // AzFramework::Application void CreateStaticModules(AZStd::vector& outModules) override; + void Reflect(AZ::ReflectContext* context) override; const char* GetCurrentConfigurationName() const override; void Stop() override; diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp index 6f6ee697d5..8532ad1f81 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp @@ -83,6 +83,11 @@ namespace ShaderManagementConsole outModules.push_back(aznew ShaderManagementConsoleWindowModule); } + void ShaderManagementConsoleApplication::Reflect(AZ::ReflectContext* context) + { + Base::Reflect(); + } + void ShaderManagementConsoleApplication::OnShaderManagementConsoleWindowClosing() { ExitMainLoop(); diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h index 6229f5d77d..26dd93c08a 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h @@ -30,6 +30,7 @@ namespace ShaderManagementConsole ////////////////////////////////////////////////////////////////////////// // AzFramework::Application void CreateStaticModules(AZStd::vector& outModules) override; + void Reflect(AZ::ReflectContext* context) override; const char* GetCurrentConfigurationName() const override; private: From e3083c7310e27f5b4df0dc4d8f527d46b97b0d19 Mon Sep 17 00:00:00 2001 From: Dayo Lawal Date: Tue, 27 Jul 2021 02:11:58 -0500 Subject: [PATCH 056/160] Reflect() fix Signed-off-by: Dayo Lawal --- .../MaterialEditor/Code/Source/MaterialEditorApplication.cpp | 2 +- .../Code/Source/ShaderManagementConsoleApplication.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp index 02c2af2266..03a80e797d 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp @@ -95,7 +95,7 @@ namespace MaterialEditor void MaterialEditorApplication::Reflect(AZ::ReflectContext* context) { - Base::Reflect(); + Base::Reflect(context); } void MaterialEditorApplication::CreateStaticModules(AZStd::vector& outModules) diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp index 8532ad1f81..de499deeaa 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp @@ -85,7 +85,7 @@ namespace ShaderManagementConsole void ShaderManagementConsoleApplication::Reflect(AZ::ReflectContext* context) { - Base::Reflect(); + Base::Reflect(context); } void ShaderManagementConsoleApplication::OnShaderManagementConsoleWindowClosing() From a3712b5564e72bdab9d2e273ddae9a2cf33f88cd Mon Sep 17 00:00:00 2001 From: Benjamin Jillich <43751992+amzn-jillich@users.noreply.github.com> Date: Tue, 27 Jul 2021 00:15:26 -0700 Subject: [PATCH 057/160] TSpace setting for MikkT tangent generation (#2386) * Added TSpace method setting which is only visible for MikkT generation. * Fixed a bug with generating tangents for blend shapes. * Renamed tangent space into generation method. * Some code cleaning Signed-off-by: Benjamin Jillich --- .../AssImpBitangentStreamImporter.cpp | 2 +- .../Importers/AssImpTangentStreamImporter.cpp | 2 +- .../GraphData/IMeshVertexBitangentData.h | 46 ++--- .../GraphData/IMeshVertexTangentData.h | 68 +++---- .../GraphData/MeshVertexBitangentData.cpp | 169 ++++++++--------- .../GraphData/MeshVertexBitangentData.h | 60 +++--- .../GraphData/MeshVertexTangentData.cpp | 176 ++++++++---------- .../GraphData/MeshVertexTangentData.h | 57 +++--- .../SceneAPI/SceneData/Rules/TangentsRule.cpp | 40 ++-- .../SceneAPI/SceneData/Rules/TangentsRule.h | 9 +- .../GraphData/GraphDataBehaviorTests.cpp | 8 +- .../TangentGenerateComponent.cpp | 50 ++--- .../TangentGenerateComponent.h | 7 +- .../BlendShapeMikkTGenerator.cpp | 54 ++++-- .../BlendShapeMikkTGenerator.h | 5 +- .../TangentGenerators/MikkTGenerator.cpp | 21 ++- .../TangentGenerators/MikkTGenerator.h | 4 +- 17 files changed, 396 insertions(+), 382 deletions(-) diff --git a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpBitangentStreamImporter.cpp b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpBitangentStreamImporter.cpp index 8379f4be7d..51e0147599 100644 --- a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpBitangentStreamImporter.cpp +++ b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpBitangentStreamImporter.cpp @@ -87,7 +87,7 @@ namespace AZ // AssImp only has one bitangentStream per mesh. bitangentStream->SetBitangentSetIndex(0); - bitangentStream->SetTangentSpace(AZ::SceneAPI::DataTypes::TangentSpace::FromSourceScene); + bitangentStream->SetGenerationMethod(AZ::SceneAPI::DataTypes::TangentGenerationMethod::FromSourceScene); bitangentStream->ReserveContainerSpace(vertexCount); for (int sdkMeshIndex = 0; sdkMeshIndex < currentNode->mNumMeshes; ++sdkMeshIndex) { diff --git a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpTangentStreamImporter.cpp b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpTangentStreamImporter.cpp index 8a1079b0d2..6f1c364399 100644 --- a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpTangentStreamImporter.cpp +++ b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpTangentStreamImporter.cpp @@ -89,7 +89,7 @@ namespace AZ // AssImp only has one tangentStream per mesh. tangentStream->SetTangentSetIndex(0); - tangentStream->SetTangentSpace(AZ::SceneAPI::DataTypes::TangentSpace::FromSourceScene); + tangentStream->SetGenerationMethod(AZ::SceneAPI::DataTypes::TangentGenerationMethod::FromSourceScene); tangentStream->ReserveContainerSpace(vertexCount); for (int sdkMeshIndex = 0; sdkMeshIndex < currentNode->mNumMeshes; ++sdkMeshIndex) { diff --git a/Code/Tools/SceneAPI/SceneCore/DataTypes/GraphData/IMeshVertexBitangentData.h b/Code/Tools/SceneAPI/SceneCore/DataTypes/GraphData/IMeshVertexBitangentData.h index d05042c534..027459460c 100644 --- a/Code/Tools/SceneAPI/SceneCore/DataTypes/GraphData/IMeshVertexBitangentData.h +++ b/Code/Tools/SceneAPI/SceneCore/DataTypes/GraphData/IMeshVertexBitangentData.h @@ -17,32 +17,24 @@ namespace AZ class Vector3; } -namespace AZ +namespace AZ::SceneAPI::DataTypes { - namespace SceneAPI + class IMeshVertexBitangentData + : public IGraphObject { - namespace DataTypes - { - - class IMeshVertexBitangentData - : public IGraphObject - { - public: - AZ_RTTI(IMeshVertexBitangentData, "{6C8F6109-B0BD-49D1-A998-4A4946557DF9}", IGraphObject); - - virtual ~IMeshVertexBitangentData() override = default; - - void CloneAttributesFrom([[maybe_unused]] const IGraphObject* sourceObject) override {} - - virtual size_t GetCount() const = 0; - virtual const AZ::Vector3& GetBitangent(size_t index) const = 0; - virtual void SetBitangent(size_t vertexIndex, const AZ::Vector3& bitangent) = 0; - virtual void SetBitangentSetIndex(size_t setIndex) = 0; - virtual size_t GetBitangentSetIndex() const = 0; - virtual TangentSpace GetTangentSpace() const = 0; - virtual void SetTangentSpace(TangentSpace space) = 0; - }; - - } // DataTypes - } // SceneAPI -} // AZ + public: + AZ_RTTI(IMeshVertexBitangentData, "{6C8F6109-B0BD-49D1-A998-4A4946557DF9}", IGraphObject); + + virtual ~IMeshVertexBitangentData() override = default; + + void CloneAttributesFrom([[maybe_unused]] const IGraphObject* sourceObject) override {} + + virtual size_t GetCount() const = 0; + virtual const AZ::Vector3& GetBitangent(size_t index) const = 0; + virtual void SetBitangent(size_t vertexIndex, const AZ::Vector3& bitangent) = 0; + virtual void SetBitangentSetIndex(size_t setIndex) = 0; + virtual size_t GetBitangentSetIndex() const = 0; + virtual TangentGenerationMethod GetGenerationMethod() const = 0; + virtual void SetGenerationMethod(TangentGenerationMethod method) = 0; + }; +} // AZ::SceneAPI::DataTypes diff --git a/Code/Tools/SceneAPI/SceneCore/DataTypes/GraphData/IMeshVertexTangentData.h b/Code/Tools/SceneAPI/SceneCore/DataTypes/GraphData/IMeshVertexTangentData.h index ffeeedf9fe..a51999c4b1 100644 --- a/Code/Tools/SceneAPI/SceneCore/DataTypes/GraphData/IMeshVertexTangentData.h +++ b/Code/Tools/SceneAPI/SceneCore/DataTypes/GraphData/IMeshVertexTangentData.h @@ -16,42 +16,36 @@ namespace AZ class Vector4; } -namespace AZ +namespace AZ::SceneAPI::DataTypes { - namespace SceneAPI + enum class TangentGenerationMethod + { + FromSourceScene = 0, + MikkT = 1 + }; + + enum class MikkTSpaceMethod + { + TSpace = 0, + TSpaceBasic = 1 + }; + + class IMeshVertexTangentData + : public IGraphObject { - namespace DataTypes - { - enum class TangentSpace - { - FromSourceScene = 0, - MikkT = 1 - }; - - enum class BitangentMethod - { - UseFromTangentSpace = 0, - Orthogonal = 1 - }; - - class IMeshVertexTangentData - : public IGraphObject - { - public: - AZ_RTTI(IMeshVertexTangentData, "{B24084FF-09B1-4EE5-BA5B-2D392E92ECC1}", IGraphObject); - - virtual ~IMeshVertexTangentData() override = default; - - void CloneAttributesFrom([[maybe_unused]] const IGraphObject* sourceObject) override {} - - virtual size_t GetCount() const = 0; - virtual const AZ::Vector4& GetTangent(size_t index) const = 0; - virtual void SetTangent(size_t vertexIndex, const AZ::Vector4& tangent) = 0; - virtual void SetTangentSetIndex(size_t setIndex) = 0; - virtual size_t GetTangentSetIndex() const = 0; - virtual TangentSpace GetTangentSpace() const = 0; - virtual void SetTangentSpace(TangentSpace space) = 0; - }; - } // DataTypes - } // SceneAPI -} // AZ + public: + AZ_RTTI(IMeshVertexTangentData, "{B24084FF-09B1-4EE5-BA5B-2D392E92ECC1}", IGraphObject); + + virtual ~IMeshVertexTangentData() override = default; + + void CloneAttributesFrom([[maybe_unused]] const IGraphObject* sourceObject) override {} + + virtual size_t GetCount() const = 0; + virtual const AZ::Vector4& GetTangent(size_t index) const = 0; + virtual void SetTangent(size_t vertexIndex, const AZ::Vector4& tangent) = 0; + virtual void SetTangentSetIndex(size_t setIndex) = 0; + virtual size_t GetTangentSetIndex() const = 0; + virtual TangentGenerationMethod GetGenerationMethod() const = 0; + virtual void SetGenerationMethod(TangentGenerationMethod method) = 0; + }; +} // AZ::SceneAPI::DataTypes diff --git a/Code/Tools/SceneAPI/SceneData/GraphData/MeshVertexBitangentData.cpp b/Code/Tools/SceneAPI/SceneData/GraphData/MeshVertexBitangentData.cpp index faa9bf457e..efd020f80a 100644 --- a/Code/Tools/SceneAPI/SceneData/GraphData/MeshVertexBitangentData.cpp +++ b/Code/Tools/SceneAPI/SceneData/GraphData/MeshVertexBitangentData.cpp @@ -10,110 +10,95 @@ #include #include -namespace AZ +namespace AZ::SceneData::GraphData { - namespace SceneData + void MeshVertexBitangentData::Reflect(ReflectContext* context) { - namespace GraphData + SerializeContext* serializeContext = azrtti_cast(context); + if (serializeContext) { - void MeshVertexBitangentData::Reflect(ReflectContext* context) - { - SerializeContext* serializeContext = azrtti_cast(context); - if (serializeContext) - { - serializeContext->Class()->Version(2); - } + serializeContext->Class()->Version(2); + } - BehaviorContext* behaviorContext = azrtti_cast(context); - if (behaviorContext) - { - behaviorContext->Class() - ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) - ->Attribute(AZ::Script::Attributes::Module, "scene") - ->Method("GetCount", &MeshVertexBitangentData::GetCount) - ->Method("GetBitangent", &MeshVertexBitangentData::GetBitangent) - ->Method("GetBitangentSetIndex", &MeshVertexBitangentData::GetBitangentSetIndex) - ->Method("GetTangentSpace", &MeshVertexBitangentData::GetTangentSpace) - ->Enum<(int)SceneAPI::DataTypes::TangentSpace::FromSourceScene>("FromSourceScene") - ->Enum<(int)SceneAPI::DataTypes::TangentSpace::MikkT>("MikkT"); - } - } - - void MeshVertexBitangentData::CloneAttributesFrom(const IGraphObject* sourceObject) - { - IMeshVertexBitangentData::CloneAttributesFrom(sourceObject); - if (const auto* typedSource = azrtti_cast(sourceObject)) - { - SetTangentSpace(typedSource->GetTangentSpace()); - SetBitangentSetIndex(typedSource->GetBitangentSetIndex()); - } - } - - size_t MeshVertexBitangentData::GetCount() const - { - return m_bitangents.size(); - } - - - const AZ::Vector3& MeshVertexBitangentData::GetBitangent(size_t index) const - { - AZ_Assert(index < m_bitangents.size(), "Invalid index %i for mesh bitangents.", index); - return m_bitangents[index]; - } - - - void MeshVertexBitangentData::ReserveContainerSpace(size_t numVerts) - { - m_bitangents.reserve(numVerts); - } - - - void MeshVertexBitangentData::Resize(size_t numVerts) - { - m_bitangents.resize(numVerts); - } - - - void MeshVertexBitangentData::AppendBitangent(const AZ::Vector3& bitangent) - { - m_bitangents.push_back(bitangent); - } + BehaviorContext* behaviorContext = azrtti_cast(context); + if (behaviorContext) + { + behaviorContext->Class() + ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) + ->Attribute(AZ::Script::Attributes::Module, "scene") + ->Method("GetCount", &MeshVertexBitangentData::GetCount) + ->Method("GetBitangent", &MeshVertexBitangentData::GetBitangent) + ->Method("GetBitangentSetIndex", &MeshVertexBitangentData::GetBitangentSetIndex) + ->Method("GetGenerationMethod", &MeshVertexBitangentData::GetGenerationMethod) + ->Enum<(int)SceneAPI::DataTypes::TangentGenerationMethod::FromSourceScene>("FromSourceScene") + ->Enum<(int)SceneAPI::DataTypes::TangentGenerationMethod::MikkT>("MikkT"); + } + } + + void MeshVertexBitangentData::CloneAttributesFrom(const IGraphObject* sourceObject) + { + IMeshVertexBitangentData::CloneAttributesFrom(sourceObject); + if (const auto* typedSource = azrtti_cast(sourceObject)) + { + SetGenerationMethod(typedSource->GetGenerationMethod()); + SetBitangentSetIndex(typedSource->GetBitangentSetIndex()); + } + } + size_t MeshVertexBitangentData::GetCount() const + { + return m_bitangents.size(); + } - void MeshVertexBitangentData::SetBitangent(size_t vertexIndex, const AZ::Vector3& bitangent) - { - m_bitangents[vertexIndex] = bitangent; - } + const AZ::Vector3& MeshVertexBitangentData::GetBitangent(size_t index) const + { + AZ_Assert(index < m_bitangents.size(), "Invalid index %i for mesh bitangents.", index); + return m_bitangents[index]; + } + void MeshVertexBitangentData::ReserveContainerSpace(size_t numVerts) + { + m_bitangents.reserve(numVerts); + } - void MeshVertexBitangentData::SetBitangentSetIndex(size_t setIndex) - { - m_setIndex = setIndex; - } + void MeshVertexBitangentData::Resize(size_t numVerts) + { + m_bitangents.resize(numVerts); + } + void MeshVertexBitangentData::AppendBitangent(const AZ::Vector3& bitangent) + { + m_bitangents.push_back(bitangent); + } - size_t MeshVertexBitangentData::GetBitangentSetIndex() const - { - return m_setIndex; - } + void MeshVertexBitangentData::SetBitangent(size_t vertexIndex, const AZ::Vector3& bitangent) + { + m_bitangents[vertexIndex] = bitangent; + } + void MeshVertexBitangentData::SetBitangentSetIndex(size_t setIndex) + { + m_setIndex = setIndex; + } - AZ::SceneAPI::DataTypes::TangentSpace MeshVertexBitangentData::GetTangentSpace() const - { - return m_tangentSpace; - } + size_t MeshVertexBitangentData::GetBitangentSetIndex() const + { + return m_setIndex; + } + AZ::SceneAPI::DataTypes::TangentGenerationMethod MeshVertexBitangentData::GetGenerationMethod() const + { + return m_generationMethod; + } - void MeshVertexBitangentData::SetTangentSpace(AZ::SceneAPI::DataTypes::TangentSpace space) - { - m_tangentSpace = space; - } + void MeshVertexBitangentData::SetGenerationMethod(AZ::SceneAPI::DataTypes::TangentGenerationMethod method) + { + m_generationMethod = method; + } - void MeshVertexBitangentData::GetDebugOutput(AZ::SceneAPI::Utilities::DebugOutput& output) const - { - output.Write("Bitangents", m_bitangents); - output.Write("TangentSpace", aznumeric_cast(m_tangentSpace)); - } - } // GraphData - } // SceneData -} // AZ + void MeshVertexBitangentData::GetDebugOutput(AZ::SceneAPI::Utilities::DebugOutput& output) const + { + output.Write("Bitangents", m_bitangents); + output.Write("GenerationMethod", aznumeric_cast(m_generationMethod)); + } +} // AZ::SceneData::GraphData diff --git a/Code/Tools/SceneAPI/SceneData/GraphData/MeshVertexBitangentData.h b/Code/Tools/SceneAPI/SceneData/GraphData/MeshVertexBitangentData.h index 9afb174f17..151f4c963b 100644 --- a/Code/Tools/SceneAPI/SceneData/GraphData/MeshVertexBitangentData.h +++ b/Code/Tools/SceneAPI/SceneData/GraphData/MeshVertexBitangentData.h @@ -10,51 +10,41 @@ #include #include - #include #include - -namespace AZ +namespace AZ::SceneData::GraphData { - namespace SceneData + class SCENE_DATA_CLASS MeshVertexBitangentData + : public AZ::SceneAPI::DataTypes::IMeshVertexBitangentData { - namespace GraphData - { - - class SCENE_DATA_CLASS MeshVertexBitangentData - : public AZ::SceneAPI::DataTypes::IMeshVertexBitangentData - { - public: - AZ_RTTI(MeshVertexBitangentData, "{F56FB088-4C92-4453-AFE9-4E820F03FA90}", AZ::SceneAPI::DataTypes::IMeshVertexBitangentData); - - static void Reflect(ReflectContext* context); + public: + AZ_RTTI(MeshVertexBitangentData, "{F56FB088-4C92-4453-AFE9-4E820F03FA90}", AZ::SceneAPI::DataTypes::IMeshVertexBitangentData); - SCENE_DATA_API ~MeshVertexBitangentData() override = default; + static void Reflect(ReflectContext* context); - SCENE_DATA_API void CloneAttributesFrom(const IGraphObject* sourceObject) override; + SCENE_DATA_API ~MeshVertexBitangentData() override = default; - SCENE_DATA_API size_t GetCount() const override; - SCENE_DATA_API const AZ::Vector3& GetBitangent(size_t index) const override; - SCENE_DATA_API void SetBitangent(size_t vertexIndex, const AZ::Vector3& bitangent) override; + SCENE_DATA_API void CloneAttributesFrom(const IGraphObject* sourceObject) override; - SCENE_DATA_API void SetBitangentSetIndex(size_t setIndex) override; - SCENE_DATA_API size_t GetBitangentSetIndex() const override; + SCENE_DATA_API size_t GetCount() const override; + SCENE_DATA_API const AZ::Vector3& GetBitangent(size_t index) const override; + SCENE_DATA_API void SetBitangent(size_t vertexIndex, const AZ::Vector3& bitangent) override; - SCENE_DATA_API void Resize(size_t numVerts); - SCENE_DATA_API void ReserveContainerSpace(size_t numVerts); - SCENE_DATA_API void AppendBitangent(const AZ::Vector3& bitangent); + SCENE_DATA_API void SetBitangentSetIndex(size_t setIndex) override; + SCENE_DATA_API size_t GetBitangentSetIndex() const override; - SCENE_DATA_API AZ::SceneAPI::DataTypes::TangentSpace GetTangentSpace() const override; - SCENE_DATA_API void SetTangentSpace(AZ::SceneAPI::DataTypes::TangentSpace space) override; + SCENE_DATA_API void Resize(size_t numVerts); + SCENE_DATA_API void ReserveContainerSpace(size_t numVerts); + SCENE_DATA_API void AppendBitangent(const AZ::Vector3& bitangent); - SCENE_DATA_API void GetDebugOutput(AZ::SceneAPI::Utilities::DebugOutput& output) const override; - protected: - AZStd::vector m_bitangents; - AZ::SceneAPI::DataTypes::TangentSpace m_tangentSpace = AZ::SceneAPI::DataTypes::TangentSpace::FromSourceScene; - size_t m_setIndex = 0; - }; + SCENE_DATA_API AZ::SceneAPI::DataTypes::TangentGenerationMethod GetGenerationMethod() const override; + SCENE_DATA_API void SetGenerationMethod(AZ::SceneAPI::DataTypes::TangentGenerationMethod method) override; - } // GraphData - } // SceneData -} // AZ + SCENE_DATA_API void GetDebugOutput(AZ::SceneAPI::Utilities::DebugOutput& output) const override; + protected: + AZStd::vector m_bitangents; + AZ::SceneAPI::DataTypes::TangentGenerationMethod m_generationMethod = AZ::SceneAPI::DataTypes::TangentGenerationMethod::FromSourceScene; + size_t m_setIndex = 0; + }; +} // AZ::SceneData::GraphData diff --git a/Code/Tools/SceneAPI/SceneData/GraphData/MeshVertexTangentData.cpp b/Code/Tools/SceneAPI/SceneData/GraphData/MeshVertexTangentData.cpp index 9f27f4eb44..31ae04b19e 100644 --- a/Code/Tools/SceneAPI/SceneData/GraphData/MeshVertexTangentData.cpp +++ b/Code/Tools/SceneAPI/SceneData/GraphData/MeshVertexTangentData.cpp @@ -10,112 +10,96 @@ #include #include -namespace AZ +namespace AZ::SceneData::GraphData { - namespace SceneData + void MeshVertexTangentData::Reflect(ReflectContext* context) { - namespace GraphData + SerializeContext* serializeContext = azrtti_cast(context); + if (serializeContext) { - void MeshVertexTangentData::Reflect(ReflectContext* context) - { - SerializeContext* serializeContext = azrtti_cast(context); - if (serializeContext) - { - serializeContext->Class()->Version(2); - } + serializeContext->Class()->Version(2); + } - BehaviorContext* behaviorContext = azrtti_cast(context); - if (behaviorContext) - { - behaviorContext->Class() - ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) - ->Attribute(AZ::Script::Attributes::Module, "scene") - ->Method("GetCount", &MeshVertexTangentData::GetCount) - ->Method("GetTangent", &MeshVertexTangentData::GetTangent) - ->Method("GetTangentSetIndex", &MeshVertexTangentData::GetTangentSetIndex) - ->Method("GetTangentSpace", &MeshVertexTangentData::GetTangentSpace) - ->Enum<(int)SceneAPI::DataTypes::TangentSpace::FromSourceScene>("FromSourceScene") - ->Enum<(int)SceneAPI::DataTypes::TangentSpace::MikkT>("MikkT"); - } - } - - void MeshVertexTangentData::CloneAttributesFrom(const IGraphObject* sourceObject) - { - IMeshVertexTangentData::CloneAttributesFrom(sourceObject); - if (const auto* typedSource = azrtti_cast(sourceObject)) - { - SetTangentSpace(typedSource->GetTangentSpace()); - SetTangentSetIndex(typedSource->GetTangentSetIndex()); - } - } - - size_t MeshVertexTangentData::GetCount() const - { - return m_tangents.size(); - } - - - const AZ::Vector4& MeshVertexTangentData::GetTangent(size_t index) const - { - AZ_Assert(index < m_tangents.size(), "Invalid index %i for mesh tangents.", index); - return m_tangents[index]; - } - - - void MeshVertexTangentData::ReserveContainerSpace(size_t numVerts) - { - m_tangents.reserve(numVerts); - } - - - void MeshVertexTangentData::Resize(size_t numVerts) - { - m_tangents.resize(numVerts); - } - - - void MeshVertexTangentData::AppendTangent(const AZ::Vector4& tangent) - { - m_tangents.push_back(tangent); - } - - void MeshVertexTangentData::GetDebugOutput(AZ::SceneAPI::Utilities::DebugOutput& output) const - { - output.Write("Tangents", m_tangents); - output.Write("TangentSpace", aznumeric_cast(m_tangentSpace)); - output.Write("SetIndex", aznumeric_cast(m_setIndex)); - } - - - void MeshVertexTangentData::SetTangent(size_t vertexIndex, const AZ::Vector4& tangent) - { - m_tangents[vertexIndex] = tangent; - } + BehaviorContext* behaviorContext = azrtti_cast(context); + if (behaviorContext) + { + behaviorContext->Class() + ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) + ->Attribute(AZ::Script::Attributes::Module, "scene") + ->Method("GetCount", &MeshVertexTangentData::GetCount) + ->Method("GetTangent", &MeshVertexTangentData::GetTangent) + ->Method("GetTangentSetIndex", &MeshVertexTangentData::GetTangentSetIndex) + ->Method("GetGenerationMethod", &MeshVertexTangentData::GetGenerationMethod) + ->Enum<(int)SceneAPI::DataTypes::TangentGenerationMethod::FromSourceScene>("FromSourceScene") + ->Enum<(int)SceneAPI::DataTypes::TangentGenerationMethod::MikkT>("MikkT"); + } + } + + void MeshVertexTangentData::CloneAttributesFrom(const IGraphObject* sourceObject) + { + IMeshVertexTangentData::CloneAttributesFrom(sourceObject); + if (const auto* typedSource = azrtti_cast(sourceObject)) + { + SetGenerationMethod(typedSource->GetGenerationMethod()); + SetTangentSetIndex(typedSource->GetTangentSetIndex()); + } + } + size_t MeshVertexTangentData::GetCount() const + { + return m_tangents.size(); + } - void MeshVertexTangentData::SetTangentSetIndex(size_t setIndex) - { - m_setIndex = setIndex; - } + const AZ::Vector4& MeshVertexTangentData::GetTangent(size_t index) const + { + AZ_Assert(index < m_tangents.size(), "Invalid index %i for mesh tangents.", index); + return m_tangents[index]; + } + void MeshVertexTangentData::ReserveContainerSpace(size_t numVerts) + { + m_tangents.reserve(numVerts); + } - size_t MeshVertexTangentData::GetTangentSetIndex() const - { - return m_setIndex; - } + void MeshVertexTangentData::Resize(size_t numVerts) + { + m_tangents.resize(numVerts); + } + void MeshVertexTangentData::AppendTangent(const AZ::Vector4& tangent) + { + m_tangents.push_back(tangent); + } - AZ::SceneAPI::DataTypes::TangentSpace MeshVertexTangentData::GetTangentSpace() const - { - return m_tangentSpace; - } + void MeshVertexTangentData::GetDebugOutput(AZ::SceneAPI::Utilities::DebugOutput& output) const + { + output.Write("Tangents", m_tangents); + output.Write("GenerationMethod", aznumeric_cast(m_generationMethod)); + output.Write("SetIndex", aznumeric_cast(m_setIndex)); + } + void MeshVertexTangentData::SetTangent(size_t vertexIndex, const AZ::Vector4& tangent) + { + m_tangents[vertexIndex] = tangent; + } - void MeshVertexTangentData::SetTangentSpace(AZ::SceneAPI::DataTypes::TangentSpace space) - { - m_tangentSpace = space; - } + void MeshVertexTangentData::SetTangentSetIndex(size_t setIndex) + { + m_setIndex = setIndex; + } - } // GraphData - } // SceneData -} // AZ + size_t MeshVertexTangentData::GetTangentSetIndex() const + { + return m_setIndex; + } + + AZ::SceneAPI::DataTypes::TangentGenerationMethod MeshVertexTangentData::GetGenerationMethod() const + { + return m_generationMethod; + } + + void MeshVertexTangentData::SetGenerationMethod(AZ::SceneAPI::DataTypes::TangentGenerationMethod method) + { + m_generationMethod = method; + } +} // AZ::SceneData::GraphData diff --git a/Code/Tools/SceneAPI/SceneData/GraphData/MeshVertexTangentData.h b/Code/Tools/SceneAPI/SceneData/GraphData/MeshVertexTangentData.h index a9d6023b70..47993c2281 100644 --- a/Code/Tools/SceneAPI/SceneData/GraphData/MeshVertexTangentData.h +++ b/Code/Tools/SceneAPI/SceneData/GraphData/MeshVertexTangentData.h @@ -14,46 +14,39 @@ #include #include -namespace AZ +namespace AZ::SceneData::GraphData { - namespace SceneData + class SCENE_DATA_CLASS MeshVertexTangentData + : public AZ::SceneAPI::DataTypes::IMeshVertexTangentData { - namespace GraphData - { + public: + AZ_RTTI(MeshVertexTangentData, "{C16F0F38-8F8F-45A2-A33B-F2758922A7C4}", AZ::SceneAPI::DataTypes::IMeshVertexTangentData); - class SCENE_DATA_CLASS MeshVertexTangentData - : public AZ::SceneAPI::DataTypes::IMeshVertexTangentData - { - public: - AZ_RTTI(MeshVertexTangentData, "{C16F0F38-8F8F-45A2-A33B-F2758922A7C4}", AZ::SceneAPI::DataTypes::IMeshVertexTangentData); + static void Reflect(ReflectContext* context); - static void Reflect(ReflectContext* context); + SCENE_DATA_API ~MeshVertexTangentData() override = default; - SCENE_DATA_API ~MeshVertexTangentData() override = default; + SCENE_DATA_API void CloneAttributesFrom(const IGraphObject* sourceObject) override; - SCENE_DATA_API void CloneAttributesFrom(const IGraphObject* sourceObject) override; + SCENE_DATA_API size_t GetCount() const override; + SCENE_DATA_API const AZ::Vector4& GetTangent(size_t index) const override; + SCENE_DATA_API void SetTangent(size_t vertexIndex, const AZ::Vector4& tangent) override; - SCENE_DATA_API size_t GetCount() const override; - SCENE_DATA_API const AZ::Vector4& GetTangent(size_t index) const override; - SCENE_DATA_API void SetTangent(size_t vertexIndex, const AZ::Vector4& tangent) override; + SCENE_DATA_API void SetTangentSetIndex(size_t setIndex) override; + SCENE_DATA_API size_t GetTangentSetIndex() const override; - SCENE_DATA_API void SetTangentSetIndex(size_t setIndex) override; - SCENE_DATA_API size_t GetTangentSetIndex() const override; + SCENE_DATA_API AZ::SceneAPI::DataTypes::TangentGenerationMethod GetGenerationMethod() const override; + SCENE_DATA_API void SetGenerationMethod(AZ::SceneAPI::DataTypes::TangentGenerationMethod method) override; - SCENE_DATA_API AZ::SceneAPI::DataTypes::TangentSpace GetTangentSpace() const override; - SCENE_DATA_API void SetTangentSpace(AZ::SceneAPI::DataTypes::TangentSpace space) override; + SCENE_DATA_API void Resize(size_t numVerts); + SCENE_DATA_API void ReserveContainerSpace(size_t numVerts); + SCENE_DATA_API void AppendTangent(const AZ::Vector4& tangent); - SCENE_DATA_API void Resize(size_t numVerts); - SCENE_DATA_API void ReserveContainerSpace(size_t numVerts); - SCENE_DATA_API void AppendTangent(const AZ::Vector4& tangent); + SCENE_DATA_API void GetDebugOutput(AZ::SceneAPI::Utilities::DebugOutput& output) const override; - SCENE_DATA_API void GetDebugOutput(AZ::SceneAPI::Utilities::DebugOutput& output) const override; - protected: - AZStd::vector m_tangents; - AZ::SceneAPI::DataTypes::TangentSpace m_tangentSpace = AZ::SceneAPI::DataTypes::TangentSpace::FromSourceScene; - size_t m_setIndex = 0; - }; - - } // GraphData - } // SceneData -} // AZ + protected: + AZStd::vector m_tangents; + AZ::SceneAPI::DataTypes::TangentGenerationMethod m_generationMethod = AZ::SceneAPI::DataTypes::TangentGenerationMethod::FromSourceScene; + size_t m_setIndex = 0; + }; +} // AZ::SceneData::GraphData diff --git a/Code/Tools/SceneAPI/SceneData/Rules/TangentsRule.cpp b/Code/Tools/SceneAPI/SceneData/Rules/TangentsRule.cpp index 7b4be1dfdf..5dcc0b99f8 100644 --- a/Code/Tools/SceneAPI/SceneData/Rules/TangentsRule.cpp +++ b/Code/Tools/SceneAPI/SceneData/Rules/TangentsRule.cpp @@ -26,13 +26,22 @@ namespace AZ { TangentsRule::TangentsRule() : DataTypes::IRule() - , m_tangentSpace(AZ::SceneAPI::DataTypes::TangentSpace::MikkT) { } - AZ::SceneAPI::DataTypes::TangentSpace TangentsRule::GetTangentSpace() const + AZ::SceneAPI::DataTypes::TangentGenerationMethod TangentsRule::GetGenerationMethod() const { - return m_tangentSpace; + return m_generationMethod; + } + + AZ::SceneAPI::DataTypes::MikkTSpaceMethod TangentsRule::GetMikkTSpaceMethod() const + { + return m_tSpaceMethod; + } + + AZ::Crc32 TangentsRule::GetSpaceMethodVisibility() const + { + return (m_generationMethod == AZ::SceneAPI::DataTypes::TangentGenerationMethod::MikkT) ? AZ::Edit::PropertyVisibility::Show : AZ::Edit::PropertyVisibility::Hide; } void TangentsRule::Reflect(AZ::ReflectContext* context) @@ -43,20 +52,29 @@ namespace AZ return; } - serializeContext->Class()->Version(3) - ->Field("tangentSpace", &TangentsRule::m_tangentSpace); + serializeContext->Class()->Version(4) + ->Field("tangentSpace", &TangentsRule::m_generationMethod) + ->Field("tSpaceMethod", &TangentsRule::m_tSpaceMethod); AZ::EditContext* editContext = serializeContext->GetEditContext(); if (editContext) { editContext->Class("Tangents", "Specify how tangents are imported or generated.") ->ClassElement(Edit::ClassElements::EditorData, "") - ->Attribute("AutoExpand", true) - ->Attribute(AZ::Edit::Attributes::NameLabelOverride, "") - ->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") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, AZ::Edit::PropertyRefreshLevels::EntireTree) + ->Attribute("AutoExpand", true) + ->Attribute(AZ::Edit::Attributes::NameLabelOverride, "") + ->DataElement(AZ::Edit::UIHandlers::ComboBox, &AZ::SceneAPI::SceneData::TangentsRule::m_generationMethod, "Generation Method", "Specify the tangent generation method. Choose 'From Source Scene' to extract the tangents and bitangents directly from the source scene file. When there is no tangents rule or the source scene has no tangents stored inside it, the 'MikkT' option will be used.") + ->EnumAttribute(AZ::SceneAPI::DataTypes::TangentGenerationMethod::FromSourceScene, "From Source Scene") + ->EnumAttribute(AZ::SceneAPI::DataTypes::TangentGenerationMethod::MikkT, "MikkT") + ->Attribute(AZ::Edit::Attributes::ChangeNotify, AZ::Edit::PropertyRefreshLevels::EntireTree) + ->DataElement(AZ::Edit::UIHandlers::ComboBox, &AZ::SceneAPI::SceneData::TangentsRule::m_tSpaceMethod, "TSpace Method", + "TSpace generates the tangents and bitangents with their true magnitudes which can be used for relief mapping effects. " + " It calculates the 'real' bitangent which may not be perpendicular to the tangent. " + "However, both, the tangent and bitangent are perpendicular to the vertex normal. " + "TSpaceBasic calculates unit vector tangents and bitangents at pixel/vertex level which are sufficient for basic normal mapping.") + ->EnumAttribute(AZ::SceneAPI::DataTypes::MikkTSpaceMethod::TSpace, "TSpace") + ->EnumAttribute(AZ::SceneAPI::DataTypes::MikkTSpaceMethod::TSpaceBasic, "TSpaceBasic") + ->Attribute(AZ::Edit::Attributes::Visibility, &TangentsRule::GetSpaceMethodVisibility); ; } } diff --git a/Code/Tools/SceneAPI/SceneData/Rules/TangentsRule.h b/Code/Tools/SceneAPI/SceneData/Rules/TangentsRule.h index b368fce88a..450b1331ed 100644 --- a/Code/Tools/SceneAPI/SceneData/Rules/TangentsRule.h +++ b/Code/Tools/SceneAPI/SceneData/Rules/TangentsRule.h @@ -45,12 +45,17 @@ namespace AZ SCENE_DATA_API TangentsRule(); SCENE_DATA_API ~TangentsRule() override = default; - SCENE_DATA_API AZ::SceneAPI::DataTypes::TangentSpace GetTangentSpace() const; + SCENE_DATA_API AZ::SceneAPI::DataTypes::TangentGenerationMethod GetGenerationMethod() const; + SCENE_DATA_API AZ::SceneAPI::DataTypes::MikkTSpaceMethod GetMikkTSpaceMethod() const; static void Reflect(ReflectContext* context); protected: - AZ::SceneAPI::DataTypes::TangentSpace m_tangentSpace; /**< Specifies how to handle tangents. Either generate them, or import them. */ + AZ::SceneAPI::DataTypes::TangentGenerationMethod m_generationMethod = AZ::SceneAPI::DataTypes::TangentGenerationMethod::MikkT; /**< Specifies how to handle tangents. Either generate them, or import them. */ + + // MikkT specific settings + AZ::Crc32 GetSpaceMethodVisibility() const; + AZ::SceneAPI::DataTypes::MikkTSpaceMethod m_tSpaceMethod = AZ::SceneAPI::DataTypes::MikkTSpaceMethod::TSpace; }; } // SceneData } // SceneAPI diff --git a/Code/Tools/SceneAPI/SceneData/Tests/GraphData/GraphDataBehaviorTests.cpp b/Code/Tools/SceneAPI/SceneData/Tests/GraphData/GraphDataBehaviorTests.cpp index bdcf690844..ab0fa79e62 100644 --- a/Code/Tools/SceneAPI/SceneData/Tests/GraphData/GraphDataBehaviorTests.cpp +++ b/Code/Tools/SceneAPI/SceneData/Tests/GraphData/GraphDataBehaviorTests.cpp @@ -84,7 +84,7 @@ namespace AZ auto* bitangentData = AZStd::any_cast(&data); bitangentData->AppendBitangent(AZ::Vector3{0.12f, 0.34f, 0.56f}); bitangentData->AppendBitangent(AZ::Vector3{0.77f, 0.88f, 0.99f}); - bitangentData->SetTangentSpace(AZ::SceneAPI::DataTypes::TangentSpace::FromSourceScene); + bitangentData->SetGenerationMethod(AZ::SceneAPI::DataTypes::TangentGenerationMethod::FromSourceScene); bitangentData->SetBitangentSetIndex(1); return true; } @@ -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::MikkT); + tangentData->SetGenerationMethod(AZ::SceneAPI::DataTypes::TangentGenerationMethod::MikkT); tangentData->SetTangentSetIndex(2); return true; } @@ -318,7 +318,7 @@ namespace AZ ExpectExecute("TestExpectFloatEquals(bitangentData.y, 0.88)"); ExpectExecute("TestExpectFloatEquals(bitangentData.z, 0.99)"); ExpectExecute("TestExpectIntegerEquals(meshVertexBitangentData:GetBitangentSetIndex(), 1)"); - ExpectExecute("TestExpectTrue(meshVertexBitangentData:GetTangentSpace(), MeshVertexBitangentData.FromSourceScene)"); + ExpectExecute("TestExpectTrue(meshVertexBitangentData:GetGenerationMethod(), MeshVertexBitangentData.FromSourceScene)"); } TEST_F(GrapDatahBehaviorScriptTest, SceneGraph_MeshVertexTangentData_AccessWorks) @@ -337,7 +337,7 @@ namespace AZ ExpectExecute("TestExpectFloatEquals(tangentData.z, 0.19)"); ExpectExecute("TestExpectFloatEquals(tangentData.w, 0.29)"); ExpectExecute("TestExpectIntegerEquals(meshVertexTangentData:GetTangentSetIndex(), 2)"); - ExpectExecute("TestExpectTrue(meshVertexTangentData:GetTangentSpace(), MeshVertexTangentData.EMotionFX)"); + ExpectExecute("TestExpectTrue(meshVertexTangentData:GetGenerationMethod(), MeshVertexTangentData.EMotionFX)"); } TEST_F(GrapDatahBehaviorScriptTest, SceneGraph_AnimationData_AccessWorks) diff --git a/Gems/SceneProcessing/Code/Source/Generation/Components/TangentGenerator/TangentGenerateComponent.cpp b/Gems/SceneProcessing/Code/Source/Generation/Components/TangentGenerator/TangentGenerateComponent.cpp index c1c47e1955..fdf58f2502 100644 --- a/Gems/SceneProcessing/Code/Source/Generation/Components/TangentGenerator/TangentGenerateComponent.cpp +++ b/Gems/SceneProcessing/Code/Source/Generation/Components/TangentGenerator/TangentGenerateComponent.cpp @@ -15,8 +15,6 @@ #include #include -#include - #include #include #include @@ -52,7 +50,7 @@ namespace AZ::SceneGenerationComponents } } - AZ::SceneAPI::DataTypes::TangentSpace TangentGenerateComponent::GetTangentSpaceFromRule(const AZ::SceneAPI::Containers::Scene& scene) const + const AZ::SceneAPI::SceneData::TangentsRule* TangentGenerateComponent::GetTangentRule(const AZ::SceneAPI::Containers::Scene& scene) const { for (const auto& object : scene.GetManifest().GetValueStorage()) { @@ -62,12 +60,12 @@ namespace AZ::SceneGenerationComponents const AZ::SceneAPI::SceneData::TangentsRule* rule = group->GetRuleContainerConst().FindFirstByType().get(); if (rule) { - return rule->GetTangentSpace(); + return rule; } } } - return AZ::SceneAPI::DataTypes::TangentSpace::FromSourceScene; + return nullptr; } AZ::SceneAPI::Events::ProcessingResult TangentGenerateComponent::GenerateTangentData(TangentGenerateContext& context) @@ -189,8 +187,8 @@ namespace AZ::SceneGenerationComponents return true; // No fatal error } - // Check what tangent spaces we need. - const AZ::SceneAPI::DataTypes::TangentSpace ruleTangentSpace = GetTangentSpaceFromRule(scene); + const AZ::SceneAPI::SceneData::TangentsRule* tangentsRule = GetTangentRule(scene); + const AZ::SceneAPI::DataTypes::TangentGenerationMethod ruleGenerationMethod = tangentsRule ? tangentsRule->GetGenerationMethod() : AZ::SceneAPI::DataTypes::TangentGenerationMethod::FromSourceScene; // Find all blend shape data under the mesh. We need to generate the tangent and bitangent for blend shape as well. AZStd::vector blendShapes; @@ -208,12 +206,12 @@ namespace AZ::SceneGenerationComponents } // Check if we had tangents inside the source scene file. - AZ::SceneAPI::DataTypes::TangentSpace tangentSpace = ruleTangentSpace; + AZ::SceneAPI::DataTypes::TangentGenerationMethod generationMethod = ruleGenerationMethod; AZ::SceneAPI::DataTypes::IMeshVertexTangentData* tangentData = FindTangentData(graph, nodeIndex, uvSetIndex); AZ::SceneAPI::DataTypes::IMeshVertexBitangentData* bitangentData = FindBitangentData(graph, nodeIndex, uvSetIndex); // If all we need is import from the source scene, and we have tangent data from the source scene already, then skip generating. - if ((tangentSpace == AZ::SceneAPI::DataTypes::TangentSpace::FromSourceScene)) + if ((generationMethod == AZ::SceneAPI::DataTypes::TangentGenerationMethod::FromSourceScene)) { if (tangentData && bitangentData) { @@ -226,50 +224,56 @@ namespace AZ::SceneGenerationComponents // In case there are no tangents/bitangents while the user selected to use the source ones, default to MikkT. AZ_Warning(AZ::SceneAPI::Utilities::WarningWindow, false, "Cannot use source scene tangents as there are none in the asset for mesh '%s' for uv set %zu. Defaulting to generating tangents using MikkT.\n", scene.GetGraph().GetNodeName(nodeIndex).GetName(), uvSetIndex); - tangentSpace = AZ::SceneAPI::DataTypes::TangentSpace::MikkT; + generationMethod = AZ::SceneAPI::DataTypes::TangentGenerationMethod::MikkT; } } if (!tangentData) { if (!AZ::SceneGenerationComponents::TangentGenerateComponent::CreateTangentLayer(scene.GetManifest(), nodeIndex, meshData->GetVertexCount(), uvSetIndex, - tangentSpace, graph, &tangentData)) + generationMethod, graph, &tangentData)) { AZ_Error(AZ::SceneAPI::Utilities::ErrorWindow, false, "Failed to create tangents data set for mesh %s for uv set %zu.\n", scene.GetGraph().GetNodeName(nodeIndex).GetName(), uvSetIndex); continue; } } + AZ_Assert(tangentData == FindTangentData(graph, nodeIndex, uvSetIndex), "Used tangent data is not the same as the graph returns."); + if (!bitangentData) { if (!AZ::SceneGenerationComponents::TangentGenerateComponent::CreateBitangentLayer(scene.GetManifest(), nodeIndex, meshData->GetVertexCount(), uvSetIndex, - tangentSpace, graph, &bitangentData)) + generationMethod, graph, &bitangentData)) { AZ_Error(AZ::SceneAPI::Utilities::ErrorWindow, false, "Failed to create bitangents data set for mesh %s for uv set %zu.\n", scene.GetGraph().GetNodeName(nodeIndex).GetName(), uvSetIndex); continue; } } - tangentData->SetTangentSpace(tangentSpace); - bitangentData->SetTangentSpace(tangentSpace); + AZ_Assert(bitangentData == FindBitangentData(graph, nodeIndex, uvSetIndex), "Used bitangent data is not the same as the graph returns."); - switch (tangentSpace) + tangentData->SetGenerationMethod(generationMethod); + bitangentData->SetGenerationMethod(generationMethod); + + switch (generationMethod) { // Generate using MikkT space. - case AZ::SceneAPI::DataTypes::TangentSpace::MikkT: + case AZ::SceneAPI::DataTypes::TangentGenerationMethod::MikkT: { - allSuccess &= AZ::TangentGeneration::Mesh::MikkT::GenerateTangents(meshData, uvData, tangentData, bitangentData); + const AZ::SceneAPI::DataTypes::MikkTSpaceMethod tSpaceMethod = tangentsRule ? tangentsRule->GetMikkTSpaceMethod() : AZ::SceneAPI::DataTypes::MikkTSpaceMethod::TSpace; + + allSuccess &= AZ::TangentGeneration::Mesh::MikkT::GenerateTangents(meshData, uvData, tangentData, bitangentData, tSpaceMethod); for (AZ::SceneData::GraphData::BlendShapeData* blendShape : blendShapes) { - allSuccess &= AZ::TangentGeneration::BlendShape::MikkT::GenerateTangents(blendShape, uvSetIndex); + allSuccess &= AZ::TangentGeneration::BlendShape::MikkT::GenerateTangents(blendShape, uvSetIndex, tSpaceMethod); } } break; default: { - AZ_Assert(false, "Unknown tangent space selected (spaceID=%d) for UV set %d, cannot generate tangents!\n", static_cast(tangentSpace), uvSetIndex); + AZ_Assert(false, "Unknown tangent generation method selected (%d) for UV set %d, cannot generate tangents.\n", static_cast(generationMethod), uvSetIndex); allSuccess = false; } } @@ -339,7 +343,7 @@ namespace AZ::SceneGenerationComponents const AZ::SceneAPI::Containers::SceneGraph::NodeIndex& nodeIndex, size_t numVerts, size_t uvSetIndex, - AZ::SceneAPI::DataTypes::TangentSpace tangentSpace, + AZ::SceneAPI::DataTypes::TangentGenerationMethod generationMethod, AZ::SceneAPI::Containers::SceneGraph& graph, AZ::SceneAPI::DataTypes::IMeshVertexTangentData** outTangentData) { @@ -356,7 +360,7 @@ namespace AZ::SceneGenerationComponents } tangentData->SetTangentSetIndex(uvSetIndex); - tangentData->SetTangentSpace(tangentSpace); + tangentData->SetGenerationMethod(generationMethod); const AZStd::string tangentGeneratedName = AZStd::string::format("TangentSet_%zu", uvSetIndex); const AZStd::string tangentSetName = AZ::SceneAPI::DataTypes::Utilities::CreateUniqueName(tangentGeneratedName, manifest); @@ -394,7 +398,7 @@ namespace AZ::SceneGenerationComponents const AZ::SceneAPI::Containers::SceneGraph::NodeIndex& nodeIndex, size_t numVerts, size_t uvSetIndex, - AZ::SceneAPI::DataTypes::TangentSpace tangentSpace, + AZ::SceneAPI::DataTypes::TangentGenerationMethod generationMethod, AZ::SceneAPI::Containers::SceneGraph& graph, AZ::SceneAPI::DataTypes::IMeshVertexBitangentData** outBitangentData) { @@ -411,7 +415,7 @@ namespace AZ::SceneGenerationComponents } bitangentData->SetBitangentSetIndex(uvSetIndex); - bitangentData->SetTangentSpace(tangentSpace); + bitangentData->SetGenerationMethod(generationMethod); const AZStd::string bitangentGeneratedName = AZStd::string::format("BitangentSet_%zu", uvSetIndex); const AZStd::string bitangentSetName = AZ::SceneAPI::DataTypes::Utilities::CreateUniqueName(bitangentGeneratedName, manifest); diff --git a/Gems/SceneProcessing/Code/Source/Generation/Components/TangentGenerator/TangentGenerateComponent.h b/Gems/SceneProcessing/Code/Source/Generation/Components/TangentGenerator/TangentGenerateComponent.h index 06d9aded11..d2aa59b549 100644 --- a/Gems/SceneProcessing/Code/Source/Generation/Components/TangentGenerator/TangentGenerateComponent.h +++ b/Gems/SceneProcessing/Code/Source/Generation/Components/TangentGenerator/TangentGenerateComponent.h @@ -10,6 +10,7 @@ #include #include +#include #include namespace AZ::SceneAPI::DataTypes { class IMeshData; } @@ -59,7 +60,7 @@ namespace AZ::SceneGenerationComponents AZStd::vector& outBlendShapes) const; bool GenerateTangentsForMesh(AZ::SceneAPI::Containers::Scene& scene, const AZ::SceneAPI::Containers::SceneGraph::NodeIndex& nodeIndex, AZ::SceneAPI::DataTypes::IMeshData* meshData); void UpdateFbxTangentWValues(AZ::SceneAPI::Containers::SceneGraph& graph, const AZ::SceneAPI::Containers::SceneGraph::NodeIndex& nodeIndex, const AZ::SceneAPI::DataTypes::IMeshData* meshData); - AZ::SceneAPI::DataTypes::TangentSpace GetTangentSpaceFromRule(const AZ::SceneAPI::Containers::Scene& scene) const; + const AZ::SceneAPI::SceneData::TangentsRule* GetTangentRule(const AZ::SceneAPI::Containers::Scene& scene) const; size_t CalcUvSetCount(AZ::SceneAPI::Containers::SceneGraph& graph, const AZ::SceneAPI::Containers::SceneGraph::NodeIndex& nodeIndex) const; AZ::SceneAPI::DataTypes::IMeshVertexUVData* FindUvData(AZ::SceneAPI::Containers::SceneGraph& graph, const AZ::SceneAPI::Containers::SceneGraph::NodeIndex& nodeIndex, AZ::u64 uvSet) const; @@ -69,7 +70,7 @@ namespace AZ::SceneGenerationComponents const AZ::SceneAPI::Containers::SceneGraph::NodeIndex& nodeIndex, size_t numVerts, size_t uvSetIndex, - AZ::SceneAPI::DataTypes::TangentSpace tangentSpace, + AZ::SceneAPI::DataTypes::TangentGenerationMethod generationMethod, AZ::SceneAPI::Containers::SceneGraph& graph, AZ::SceneAPI::DataTypes::IMeshVertexTangentData** outTangentData); @@ -78,7 +79,7 @@ namespace AZ::SceneGenerationComponents const AZ::SceneAPI::Containers::SceneGraph::NodeIndex& nodeIndex, size_t numVerts, size_t uvSetIndex, - AZ::SceneAPI::DataTypes::TangentSpace tangentSpace, + AZ::SceneAPI::DataTypes::TangentGenerationMethod generationMethod, AZ::SceneAPI::Containers::SceneGraph& graph, AZ::SceneAPI::DataTypes::IMeshVertexBitangentData** outBitangentData); }; diff --git a/Gems/SceneProcessing/Code/Source/Generation/Components/TangentGenerator/TangentGenerators/BlendShapeMikkTGenerator.cpp b/Gems/SceneProcessing/Code/Source/Generation/Components/TangentGenerator/TangentGenerators/BlendShapeMikkTGenerator.cpp index 4e60fd3d15..b472aa4e09 100644 --- a/Gems/SceneProcessing/Code/Source/Generation/Components/TangentGenerator/TangentGenerators/BlendShapeMikkTGenerator.cpp +++ b/Gems/SceneProcessing/Code/Source/Generation/Components/TangentGenerator/TangentGenerators/BlendShapeMikkTGenerator.cpp @@ -76,33 +76,47 @@ namespace AZ::TangentGeneration::BlendShape::MikkT const AZ::Vector4 tangentVec(tangent[0]*magS, tangent[1]*magS, tangent[2]*magS, flipSign); const AZ::Vector3 bitangentVec(bitangent[0]*magT, bitangent[1]*magT, bitangent[2]*magT); - // Set the tangent and bitangent back to the blendshape + // Set the tangent and bitangent back to the blend shape AZStd::vector& tangents = customData->m_blendShapeData->GetTangents(); AZStd::vector& bitangents = customData->m_blendShapeData->GetBitangents(); tangents[vertexIndex] = tangentVec; bitangents[vertexIndex] = bitangentVec; } - bool GenerateTangents(AZ::SceneData::GraphData::BlendShapeData* blendShapeData, size_t uvSetIndex) + void SetTSpaceBasic(const SMikkTSpaceContext* context, const float tangent[], const float signValue, const int face, const int vert) + { + MikktCustomData* customData = static_cast(context->m_pUserData); + const AZ::u32 vertexIndex = customData->m_blendShapeData->GetFaceVertexIndex(face, vert); + AZ::Vector3 tangentVec3(tangent[0], tangent[1], tangent[2]); + tangentVec3.NormalizeSafe(); + AZ::Vector3 normal = customData->m_blendShapeData->GetNormal(vertexIndex); + normal.NormalizeSafe(); + const AZ::Vector3 bitangent = normal.Cross(tangentVec3) * signValue; + + // Set the tangent and bitangent back to the blend shape + AZStd::vector& tangents = customData->m_blendShapeData->GetTangents(); + AZStd::vector& bitangents = customData->m_blendShapeData->GetBitangents(); + tangents[vertexIndex] = AZ::Vector4(tangentVec3.GetX(), tangentVec3.GetY(), tangentVec3.GetZ(), signValue); + bitangents[vertexIndex] = bitangent; + } + + bool GenerateTangents(AZ::SceneData::GraphData::BlendShapeData* blendShapeData, + size_t uvSetIndex, + AZ::SceneAPI::DataTypes::MikkTSpaceMethod tSpaceMethod) { // Create tangent and bitangent data sets and relate them to the given UV set. const AZStd::vector& uvSet = blendShapeData->GetUVs(uvSetIndex); if (uvSet.empty()) { - AZ_TracePrintf(AZ::SceneAPI::Utilities::ErrorWindow, "Cannot find UV data (set index=%d) to generate tangents and bitangents from in MikkT generator!\n", uvSetIndex); + AZ_Error(AZ::SceneAPI::Utilities::ErrorWindow, false, + "Cannot find UV data (set index=%d) to generate tangents and bitangents from in MikkT generator.\n", + uvSetIndex); return false; } + // Pre-allocate the tangent and bitangent data. AZStd::vector& tangents = blendShapeData->GetTangents(); AZStd::vector& bitangents = blendShapeData->GetBitangents(); - if (!tangents.empty() || !bitangents.empty()) - { - AZ_TracePrintf( - AZ::SceneAPI::Utilities::WarningWindow, "Cannot generate tangents and bitangents because existing tangent or bitangent data has been found.\n"); - return false; - } - - // Pre-allocate the tangent and bitangent data. tangents.resize(blendShapeData->GetVertexCount()); bitangents.resize(blendShapeData->GetVertexCount()); @@ -114,10 +128,24 @@ namespace AZ::TangentGeneration::BlendShape::MikkT mikkInterface.m_getNormal = GetNormal; mikkInterface.m_getPosition = GetPosition; mikkInterface.m_getTexCoord = GetTexCoord; - mikkInterface.m_setTSpace = SetTSpace; - mikkInterface.m_setTSpaceBasic = nullptr; mikkInterface.m_getNumVerticesOfFace= GetNumVerticesOfFace; + switch (tSpaceMethod) + { + case AZ::SceneAPI::DataTypes::MikkTSpaceMethod::TSpaceBasic: + { + mikkInterface.m_setTSpace = nullptr; + mikkInterface.m_setTSpaceBasic = SetTSpaceBasic; + break; + } + default: + { + mikkInterface.m_setTSpace = SetTSpace; + mikkInterface.m_setTSpaceBasic = nullptr; + break; + } + } + // Set the MikkT custom data. MikktCustomData customData; customData.m_blendShapeData = blendShapeData; diff --git a/Gems/SceneProcessing/Code/Source/Generation/Components/TangentGenerator/TangentGenerators/BlendShapeMikkTGenerator.h b/Gems/SceneProcessing/Code/Source/Generation/Components/TangentGenerator/TangentGenerators/BlendShapeMikkTGenerator.h index cbb170375a..68d4835817 100644 --- a/Gems/SceneProcessing/Code/Source/Generation/Components/TangentGenerator/TangentGenerators/BlendShapeMikkTGenerator.h +++ b/Gems/SceneProcessing/Code/Source/Generation/Components/TangentGenerator/TangentGenerators/BlendShapeMikkTGenerator.h @@ -9,6 +9,7 @@ #pragma once #include +#include namespace AZ::SceneData::GraphData { @@ -24,5 +25,7 @@ namespace AZ::TangentGeneration::BlendShape::MikkT }; // The main generation method. - bool GenerateTangents(AZ::SceneData::GraphData::BlendShapeData* blendShapeData, size_t uvSetIndex); + bool GenerateTangents(AZ::SceneData::GraphData::BlendShapeData* blendShapeData, + size_t uvSetIndex, + AZ::SceneAPI::DataTypes::MikkTSpaceMethod tSpaceMethod = AZ::SceneAPI::DataTypes::MikkTSpaceMethod::TSpace); } // namespace AZ::TangentGeneration::MikkT diff --git a/Gems/SceneProcessing/Code/Source/Generation/Components/TangentGenerator/TangentGenerators/MikkTGenerator.cpp b/Gems/SceneProcessing/Code/Source/Generation/Components/TangentGenerator/TangentGenerators/MikkTGenerator.cpp index 3f736815e5..d3b694e852 100644 --- a/Gems/SceneProcessing/Code/Source/Generation/Components/TangentGenerator/TangentGenerators/MikkTGenerator.cpp +++ b/Gems/SceneProcessing/Code/Source/Generation/Components/TangentGenerator/TangentGenerators/MikkTGenerator.cpp @@ -108,7 +108,8 @@ namespace AZ::TangentGeneration::Mesh::MikkT bool GenerateTangents(const AZ::SceneAPI::DataTypes::IMeshData* meshData, const AZ::SceneAPI::DataTypes::IMeshVertexUVData* uvData, AZ::SceneAPI::DataTypes::IMeshVertexTangentData* outTangentData, - AZ::SceneAPI::DataTypes::IMeshVertexBitangentData* outBitangentData) + AZ::SceneAPI::DataTypes::IMeshVertexBitangentData* outBitangentData, + AZ::SceneAPI::DataTypes::MikkTSpaceMethod tSpaceMethod) { // Provide the MikkT interface. SMikkTSpaceInterface mikkInterface; @@ -116,10 +117,24 @@ namespace AZ::TangentGeneration::Mesh::MikkT mikkInterface.m_getNormal = GetNormal; mikkInterface.m_getPosition = GetPosition; mikkInterface.m_getTexCoord = GetTexCoord; - mikkInterface.m_setTSpace = SetTSpace; - mikkInterface.m_setTSpaceBasic = nullptr;//SetTSpaceBasic; mikkInterface.m_getNumVerticesOfFace= GetNumVerticesOfFace; + switch (tSpaceMethod) + { + case AZ::SceneAPI::DataTypes::MikkTSpaceMethod::TSpaceBasic: + { + mikkInterface.m_setTSpace = nullptr; + mikkInterface.m_setTSpaceBasic = SetTSpaceBasic; + break; + } + default: + { + mikkInterface.m_setTSpace = SetTSpace; + mikkInterface.m_setTSpaceBasic = nullptr; + break; + } + } + // Set the MikkT custom data. MikktCustomData customData; customData.m_meshData = meshData; diff --git a/Gems/SceneProcessing/Code/Source/Generation/Components/TangentGenerator/TangentGenerators/MikkTGenerator.h b/Gems/SceneProcessing/Code/Source/Generation/Components/TangentGenerator/TangentGenerators/MikkTGenerator.h index 4b1d8ebd72..4604a6e4c5 100644 --- a/Gems/SceneProcessing/Code/Source/Generation/Components/TangentGenerator/TangentGenerators/MikkTGenerator.h +++ b/Gems/SceneProcessing/Code/Source/Generation/Components/TangentGenerator/TangentGenerators/MikkTGenerator.h @@ -8,6 +8,7 @@ #pragma once +#include #include namespace AZ::SceneAPI::DataTypes { class IMeshData; } @@ -28,5 +29,6 @@ namespace AZ::TangentGeneration::Mesh::MikkT bool GenerateTangents(const AZ::SceneAPI::DataTypes::IMeshData* meshData, const AZ::SceneAPI::DataTypes::IMeshVertexUVData* uvData, AZ::SceneAPI::DataTypes::IMeshVertexTangentData* outTangentData, - AZ::SceneAPI::DataTypes::IMeshVertexBitangentData* outBitangentData); + AZ::SceneAPI::DataTypes::IMeshVertexBitangentData* outBitangentData, + AZ::SceneAPI::DataTypes::MikkTSpaceMethod tSpaceMethod = AZ::SceneAPI::DataTypes::MikkTSpaceMethod::TSpace); } // namespace AZ::TangentGeneration::MikkT From 485f6338acd4a2a6da2c3c5d250994b19744c144 Mon Sep 17 00:00:00 2001 From: Dayo Lawal Date: Tue, 27 Jul 2021 02:19:26 -0500 Subject: [PATCH 058/160] CreateReflectionManager() Signed-off-by: Dayo Lawal --- .../Code/Source/Application/AtomToolsApplication.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp index 5e817f0125..865bd37955 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp @@ -63,7 +63,7 @@ namespace AtomToolsFramework void AtomToolsApplication::CreateReflectionManager() { - Application::CreateReflectionManager(); + Base::CreateReflectionManager(); GetSerializeContext()->CreateEditContext(); } From 06b3f7d964254e948f3678474a32488d82362f99 Mon Sep 17 00:00:00 2001 From: Dayo Lawal Date: Tue, 27 Jul 2021 12:18:12 -0500 Subject: [PATCH 059/160] Undoing adding reflect and adding target names to functions Signed-off-by: Dayo Lawal --- .../Code/Source/Application/AtomToolsApplication.cpp | 12 ++++++++---- .../Code/Source/MaterialEditorApplication.cpp | 5 ----- .../Code/Source/MaterialEditorApplication.h | 1 - .../Source/ShaderManagementConsoleApplication.cpp | 5 ----- .../Code/Source/ShaderManagementConsoleApplication.h | 1 - 5 files changed, 8 insertions(+), 16 deletions(-) diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp index 865bd37955..f968584998 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp @@ -82,12 +82,14 @@ namespace AtomToolsFramework if (auto behaviorContext = azrtti_cast(context)) { + auto targetName = GetBuildTargetName(); + // this will put these methods into the 'azlmbr.AtomTools.general' module - auto addGeneral = [](AZ::BehaviorContext::GlobalMethodBuilder methodBuilder) + auto addGeneral = [targetName](AZ::BehaviorContext::GlobalMethodBuilder methodBuilder) { methodBuilder->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation) ->Attribute(AZ::Script::Attributes::Category, "Editor") - ->Attribute(AZ::Script::Attributes::Module, "AtomTools"); + ->Attribute(AZ::Script::Attributes::Module, targetName); }; // The reflection here is based on patterns in CryEditPythonHandler::Reflect addGeneral(behaviorContext->Method( @@ -165,14 +167,16 @@ namespace AtomToolsFramework // and able to negotiate a connection when running a debug build // and to negotiate a connection + auto targetName = GetBuildTargetName(); + AzFramework::AssetSystem::ConnectionSettings connectionSettings; AzFramework::AssetSystem::ReadConnectionSettingsFromSettingsRegistry(connectionSettings); connectionSettings.m_connectionDirection = AzFramework::AssetSystem::ConnectionSettings::ConnectionDirection::ConnectToAssetProcessor; connectionSettings.m_connectionIdentifier = GetBuildTargetName(); - connectionSettings.m_loggingCallback = []([[maybe_unused]] AZStd::string_view logData) + connectionSettings.m_loggingCallback = [targetName]([[maybe_unused]] AZStd::string_view logData) { - AZ_TracePrintf("Atom Tools", "%.*s", aznumeric_cast(logData.size()), logData.data()); + AZ_TracePrintf(targetName.c_str(), "%.*s", aznumeric_cast(logData.size()), logData.data()); }; AzFramework::AssetSystemRequestBus::BroadcastResult( connectedToAssetProcessor, &AzFramework::AssetSystemRequestBus::Events::EstablishAssetProcessorConnection, connectionSettings); diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp index 03a80e797d..57313c6694 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp @@ -93,11 +93,6 @@ namespace MaterialEditor AzToolsFramework::EditorPythonConsoleNotificationBus::Handler::BusDisconnect(); } - void MaterialEditorApplication::Reflect(AZ::ReflectContext* context) - { - Base::Reflect(context); - } - void MaterialEditorApplication::CreateStaticModules(AZStd::vector& outModules) { Base::CreateStaticModules(outModules); diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h index bbe5a26141..0177013a3d 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h @@ -32,7 +32,6 @@ namespace MaterialEditor ////////////////////////////////////////////////////////////////////////// // AzFramework::Application void CreateStaticModules(AZStd::vector& outModules) override; - void Reflect(AZ::ReflectContext* context) override; const char* GetCurrentConfigurationName() const override; void Stop() override; diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp index de499deeaa..6f6ee697d5 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp @@ -83,11 +83,6 @@ namespace ShaderManagementConsole outModules.push_back(aznew ShaderManagementConsoleWindowModule); } - void ShaderManagementConsoleApplication::Reflect(AZ::ReflectContext* context) - { - Base::Reflect(context); - } - void ShaderManagementConsoleApplication::OnShaderManagementConsoleWindowClosing() { ExitMainLoop(); diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h index 26dd93c08a..6229f5d77d 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h @@ -30,7 +30,6 @@ namespace ShaderManagementConsole ////////////////////////////////////////////////////////////////////////// // AzFramework::Application void CreateStaticModules(AZStd::vector& outModules) override; - void Reflect(AZ::ReflectContext* context) override; const char* GetCurrentConfigurationName() const override; private: From 5cb001dffd1cc81af6f47ab7e492c0bb37a3961e Mon Sep 17 00:00:00 2001 From: Dayo Lawal Date: Tue, 27 Jul 2021 12:51:38 -0500 Subject: [PATCH 060/160] More fixes Signed-off-by: Dayo Lawal --- .../Application/AtomToolsApplication.h | 2 +- .../Source/Application/AtomToolsApplication.cpp | 15 ++++++++++----- .../Code/Source/MaterialEditorApplication.cpp | 6 ------ 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h index 08eac727a3..3b2e5a7e8a 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h @@ -89,7 +89,7 @@ namespace AtomToolsFramework virtual void LoadSettings(); virtual void UnloadSettings(); - virtual void CompileCriticalAssets(const AZStd::vector &assetFiltersArray); + virtual void CompileCriticalAssets(); virtual void ProcessCommandLine(const AZ::CommandLine& commandLine); virtual bool LaunchDiscoveryService(); virtual void StartInternal(); diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp index f968584998..0dc579b017 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp @@ -59,6 +59,11 @@ namespace AtomToolsFramework : Application(argc, argv) , AzQtApplication(*argc, *argv) { + connect(&m_timer, &QTimer::timeout, this, [&]() + { + this->PumpSystemEventLoopUntilEmpty(); + this->Tick(); + }); } void AtomToolsApplication::CreateReflectionManager() @@ -155,7 +160,7 @@ namespace AtomToolsFramework { // List of common asset filters for things that need to be compiled to run the material editor // Some of these things will not be necessary once we have proper support for queued asset loading and reloading - return AZStd::vector({ "passes/", "config/" }); + return AZStd::vector({}); } void AtomToolsApplication::AssetSystemAvailable() @@ -183,13 +188,13 @@ namespace AtomToolsFramework if (connectedToAssetProcessor) { - CompileCriticalAssets(GetCriticalAssetFilters()); + CompileCriticalAssets(); } AzFramework::AssetSystemStatusBus::Handler::BusDisconnect(); } - void AtomToolsApplication::CompileCriticalAssets(const AZStd::vector &assetFiltersArray) + void AtomToolsApplication::CompileCriticalAssets() { AZ_TracePrintf(GetBuildTargetName().c_str(), "Compiling critical assets.\n"); @@ -198,7 +203,7 @@ namespace AtomToolsFramework // Forced asset processor to synchronously process all critical assets // Note: with AssetManager's current implementation, a compiled asset won't be added in asset registry until next system tick. // So the asset id won't be found right after CompileAssetSync call. - for (const AZStd::string& assetFilters : assetFiltersArray) + for (const AZStd::string& assetFilters : GetCriticalAssetFilters()) { AZ_TracePrintf(GetBuildTargetName().c_str(), "Compiling critical asset matching: %s.\n", assetFilters.c_str()); @@ -424,7 +429,7 @@ namespace AtomToolsFramework void AtomToolsApplication::Tick(float deltaOverride) { TickSystem(); - Application::Tick(deltaOverride); + Base::Tick(deltaOverride); if (WasExitMainLoopRequested()) { diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp index 57313c6694..09c7588de9 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp @@ -78,12 +78,6 @@ namespace MaterialEditor AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddBuildSystemTargetSpecialization( *AZ::SettingsRegistry::Get(), GetBuildTargetName()); - - connect(&m_timer, &QTimer::timeout, this, [&]() - { - this->PumpSystemEventLoopUntilEmpty(); - this->Tick(); - }); } MaterialEditorApplication::~MaterialEditorApplication() From 76a3195487e0c0a3f4cd9f01b089653b0336093d Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Tue, 27 Jul 2021 10:52:22 -0700 Subject: [PATCH 061/160] remove null data check from connected slots Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com> --- .../Code/Include/ScriptCanvas/Grammar/AbstractCodeModel.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/AbstractCodeModel.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/AbstractCodeModel.cpp index 545500c57e..883e15cd29 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/AbstractCodeModel.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/AbstractCodeModel.cpp @@ -4343,6 +4343,9 @@ namespace ScriptCanvas execution->AddInput({ &input, inputVariable, DebugDataSource::FromSelfSlot(input, inputVariable->m_datum.GetType()) }); } + + // Check for known null reads + CheckForKnownNullDereference(execution, execution->GetInput(execution->GetInputCount() - 1), input); } else { @@ -4374,9 +4377,6 @@ namespace ScriptCanvas return; } } - - // Check for known null reads - CheckForKnownNullDereference(execution, execution->GetInput(execution->GetInputCount() - 1), input); } bool AbstractCodeModel::ParseInputThisPointer(ExecutionTreePtr execution) From bfbe6fc95c48a08bdbac419d9ea7beae060a09fc Mon Sep 17 00:00:00 2001 From: jjjoness <82226755+jjjoness@users.noreply.github.com> Date: Tue, 27 Jul 2021 19:12:36 +0100 Subject: [PATCH 062/160] Corrected the text message (#2483) Signed-off-by: John Jones-Steele --- .../Code/Source/InputConfigurationComponent.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/StartingPointInput/Code/Source/InputConfigurationComponent.cpp b/Gems/StartingPointInput/Code/Source/InputConfigurationComponent.cpp index 6739a54ddd..42fa05473c 100644 --- a/Gems/StartingPointInput/Code/Source/InputConfigurationComponent.cpp +++ b/Gems/StartingPointInput/Code/Source/InputConfigurationComponent.cpp @@ -62,7 +62,7 @@ namespace StartingPointInput ->Attribute(AZ::Edit::Attributes::ContainerCanBeModified, true) ->Attribute("BrowseIcon", ":/stylesheet/img/UI20/browse-edit-select-files.svg") ->Attribute("EditButton", "") - ->Attribute("EditDescription", "Open in Input Bindings Editor") + ->Attribute("EditDescription", "Open in Asset Editor") ->DataElement(AZ::Edit::UIHandlers::SpinBox, &InputConfigurationComponent::m_localPlayerIndex, "Local player index", "The player index that this component will receive input from (0 based, -1 means all controllers).\n" "Will only work on platforms such as PC where the local user id corresponds to the local player index.\n" From 33c408f65424358c7bfb0c1db44081fea4c31d73 Mon Sep 17 00:00:00 2001 From: Ken Pruiksma Date: Tue, 27 Jul 2021 13:31:05 -0500 Subject: [PATCH 063/160] Expose shadow bias to component & feature processors. (#2406) * Expose shadow bias to component & feature processors. Shadow bias now works more consistently with various near / far shadow planes and caster positions. Bias now also affects esm shadows which helps eliminate acne in certain situations. Signed-off-by: Ken Pruiksma * Adding jira comment to light configuration serialization version. Improved comment on final adjustment to bias before its sent to the shader. Signed-off-by: Ken Pruiksma * Hooking up bias to behavior context. Signed-off-by: Ken Pruiksma --- .../Features/Shadow/ProjectedShadow.azsli | 13 +- .../DiskLightFeatureProcessorInterface.h | 2 + .../PointLightFeatureProcessorInterface.h | 2 + ...ProjectedShadowFeatureProcessorInterface.h | 2 + .../CoreLights/DiskLightFeatureProcessor.cpp | 5 + .../CoreLights/DiskLightFeatureProcessor.h | 1 + .../CoreLights/PointLightFeatureProcessor.cpp | 5 + .../CoreLights/PointLightFeatureProcessor.h | 1 + .../ProjectedShadowFeatureProcessor.cpp | 37 ++-- .../Shadows/ProjectedShadowFeatureProcessor.h | 2 + .../CommonFeatures/CoreLights/AreaLightBus.h | 6 + .../CoreLights/AreaLightComponentConfig.h | 1 + .../CoreLights/AreaLightComponentConfig.cpp | 3 +- .../AreaLightComponentController.cpp | 18 ++ .../CoreLights/AreaLightComponentController.h | 2 + .../Source/CoreLights/DiskLightDelegate.cpp | 8 + .../Source/CoreLights/DiskLightDelegate.h | 1 + .../CoreLights/EditorAreaLightComponent.cpp | 9 + .../Source/CoreLights/LightDelegateBase.h | 1 + .../CoreLights/LightDelegateInterface.h | 4 +- .../Source/CoreLights/SphereLightDelegate.cpp | 167 +++++++++--------- .../Source/CoreLights/SphereLightDelegate.h | 1 + 22 files changed, 186 insertions(+), 105 deletions(-) diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/ProjectedShadow.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/ProjectedShadow.azsli index 97862b6f6e..2fea4650b3 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/ProjectedShadow.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/ProjectedShadow.azsli @@ -62,6 +62,7 @@ class ProjectedShadow float3 m_lightDirection; float3 m_normalVector; float3 m_shadowPosition; + float m_bias; }; float ProjectedShadow::GetVisibility( @@ -238,7 +239,7 @@ float ProjectedShadow::GetVisibilityEsm() } const float3 atlasPosition = GetAtlasPosition(m_shadowPosition.xy); const float depth = PerspectiveDepthToLinear( - m_shadowPosition.z, + m_shadowPosition.z - m_bias, coefficients); const float occluder = shadowmap.SampleLevel( PassSrg::LinearSampler, @@ -280,7 +281,7 @@ float ProjectedShadow::GetVisibilityEsmPcf() } const float3 atlasPosition = GetAtlasPosition(m_shadowPosition.xy); const float depth = PerspectiveDepthToLinear( - m_shadowPosition.z, + m_shadowPosition.z - m_bias, coefficients); const float occluder = shadowmap.SampleLevel( PassSrg::LinearSampler, @@ -346,7 +347,7 @@ float ProjectedShadow::SamplePcfBicubic() param.shadowPos = float3(atlasPosition.xy * ViewSrg::m_invShadowmapAtlasSize, atlasPosition.z); param.shadowMapSize = ViewSrg::m_shadowmapAtlasSize; param.invShadowMapSize = ViewSrg::m_invShadowmapAtlasSize; - param.comparisonValue = m_shadowPosition.z - ViewSrg::m_projectedShadows[m_shadowIndex].m_bias; + param.comparisonValue = m_shadowPosition.z - m_bias; param.samplerState = SceneSrg::m_hwPcfSampler; if (filteringSampleCount <= 4) @@ -384,8 +385,8 @@ bool ProjectedShadow::IsShadowed(float3 shadowPosition) PassSrg::LinearSampler, float3(atlasPosition.xy * invAtlasSize, atlasPosition.z), /*LOD=*/0).r; const float depthDiff = depthInShadowmap - shadowPosition.z; - float bias = ViewSrg::m_projectedShadows[m_shadowIndex].m_bias; - if (depthDiff < -bias) + + if (depthDiff < -m_bias) { return true; } @@ -428,6 +429,8 @@ void ProjectedShadow::SetShadowPosition() const float4x4 depthBiasMatrix = ViewSrg::m_projectedShadows[m_shadowIndex].m_depthBiasMatrix; float4 shadowPositionHomogeneous = mul(depthBiasMatrix, float4(m_worldPosition, 1)); m_shadowPosition = shadowPositionHomogeneous.xyz / shadowPositionHomogeneous.w; + + m_bias = ViewSrg::m_projectedShadows[m_shadowIndex].m_bias / shadowPositionHomogeneous.w; } float3 ProjectedShadow::GetAtlasPosition(float2 texturePosition) diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/DiskLightFeatureProcessorInterface.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/DiskLightFeatureProcessorInterface.h index 9248add6f5..e4986eee93 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/DiskLightFeatureProcessorInterface.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/DiskLightFeatureProcessorInterface.h @@ -84,6 +84,8 @@ namespace AZ //! Sets if shadows are enabled virtual void SetShadowsEnabled(LightHandle handle, bool enabled) = 0; + //! Sets the shadow bias + virtual void SetShadowBias(LightHandle handle, float bias) = 0; //! Sets the shadowmap size (width and height) of the light. virtual void SetShadowmapMaxResolution(LightHandle handle, ShadowmapSize shadowmapSize) = 0; //! Specifies filter method of shadows. diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/PointLightFeatureProcessorInterface.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/PointLightFeatureProcessorInterface.h index 8ad4fb89de..3383378dc7 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/PointLightFeatureProcessorInterface.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/PointLightFeatureProcessorInterface.h @@ -66,6 +66,8 @@ namespace AZ virtual void SetShadowsEnabled(LightHandle handle, bool enabled) = 0; //! Sets the shadowmap size (width and height) of the light. virtual void SetShadowmapMaxResolution(LightHandle handle, ShadowmapSize shadowmapSize) = 0; + //! Sets the shadow bias + virtual void SetShadowBias(LightHandle handle, float bias) = 0; //! Specifies filter method of shadows. virtual void SetShadowFilterMethod(LightHandle handle, ShadowFilterMethod method) = 0; //! Specifies the width of boundary between shadowed area and lit area in radians. The degree ofshadowed gradually changes on diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Shadows/ProjectedShadowFeatureProcessorInterface.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Shadows/ProjectedShadowFeatureProcessorInterface.h index c0cfff3dd5..6cbb0cfef1 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Shadows/ProjectedShadowFeatureProcessorInterface.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Shadows/ProjectedShadowFeatureProcessorInterface.h @@ -50,6 +50,8 @@ namespace AZ::Render virtual void SetFieldOfViewY(ShadowId id, float fieldOfView) = 0; //! Sets the maximum resolution of the shadow map virtual void SetShadowmapMaxResolution(ShadowId id, ShadowmapSize size) = 0; + //! Sets the shadow bias + virtual void SetShadowBias(ShadowId id, float bias) = 0; //! Sets the shadowmap Pcf method. virtual void SetPcfMethod(ShadowId id, PcfMethod method) = 0; //! Sets the shadow filter method diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DiskLightFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DiskLightFeatureProcessor.cpp index 54410544a7..55be9d232e 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DiskLightFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DiskLightFeatureProcessor.cpp @@ -308,6 +308,11 @@ namespace AZ AZStd::invoke(AZStd::forward(functor), m_shadowFeatureProcessor, shadowId, AZStd::forward(param)); } } + + void DiskLightFeatureProcessor::SetShadowBias(LightHandle handle, float bias) + { + SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetShadowBias, bias); + } void DiskLightFeatureProcessor::SetShadowmapMaxResolution(LightHandle handle, ShadowmapSize shadowmapSize) { diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DiskLightFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DiskLightFeatureProcessor.h index 0ff8efb1b1..2e97ae1ded 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DiskLightFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DiskLightFeatureProcessor.h @@ -50,6 +50,7 @@ namespace AZ void SetConstrainToConeLight(LightHandle handle, bool useCone) override; void SetConeAngles(LightHandle handle, float innerDegrees, float outerDegrees) override; void SetShadowsEnabled(LightHandle handle, bool enabled) override; + void SetShadowBias(LightHandle handle, float bias) override; void SetShadowmapMaxResolution(LightHandle handle, ShadowmapSize shadowmapSize) override; void SetShadowFilterMethod(LightHandle handle, ShadowFilterMethod method) override; void SetSofteningBoundaryWidthAngle(LightHandle handle, float boundaryWidthRadians) override; diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/PointLightFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/CoreLights/PointLightFeatureProcessor.cpp index 2b54b6ede1..9baa2ae1c2 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/PointLightFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/PointLightFeatureProcessor.cpp @@ -277,6 +277,11 @@ namespace AZ } } } + + void PointLightFeatureProcessor::SetShadowBias(LightHandle handle, float bias) + { + SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetShadowBias, bias); + } void PointLightFeatureProcessor::SetShadowmapMaxResolution(LightHandle handle, ShadowmapSize shadowmapSize) { diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/PointLightFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Source/CoreLights/PointLightFeatureProcessor.h index d7bb25c71c..b7b644da9e 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/PointLightFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/PointLightFeatureProcessor.h @@ -47,6 +47,7 @@ namespace AZ void SetAttenuationRadius(LightHandle handle, float attenuationRadius) override; void SetBulbRadius(LightHandle handle, float bulbRadius) override; void SetShadowsEnabled(LightHandle handle, bool enabled) override; + void SetShadowBias(LightHandle handle, float bias) override; void SetShadowmapMaxResolution(LightHandle handle, ShadowmapSize shadowmapSize) override; void SetShadowFilterMethod(LightHandle handle, ShadowFilterMethod method) override; void SetSofteningBoundaryWidthAngle(LightHandle handle, float boundaryWidthRadians) override; diff --git a/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.cpp index 10dcffcf74..03ee176fd0 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.cpp @@ -143,7 +143,15 @@ namespace AZ::Render shadowProperty.m_desc.m_fieldOfViewYRadians = fieldOfViewYRadians; UpdateShadowView(shadowProperty); } - + + void ProjectedShadowFeatureProcessor::SetShadowBias(ShadowId id, float bias) + { + AZ_Assert(id.IsValid(), "Invalid ShadowId passed to ProjectedShadowFeatureProcessor::SetShadowBias()."); + + ShadowProperty& shadowProperty = GetShadowPropertyFromShadowId(id); + shadowProperty.m_bias = bias; + } + void ProjectedShadowFeatureProcessor::SetShadowmapMaxResolution(ShadowId id, ShadowmapSize size) { AZ_Assert(id.IsValid(), "Invalid ShadowId passed to ProjectedShadowFeatureProcessor::SetShadowmapMaxResolution()."); @@ -265,23 +273,20 @@ namespace AZ::Render view->SetCameraTransform(Matrix3x4::CreateFromTransform(desc.m_transform)); ShadowData& shadowData = m_shadowData.GetElement(shadowProperty.m_shadowId.GetIndex()); - shadowData.m_bias = (nearDist / farDist) * 0.1f; + + // Adjust the manually set bias to a more appropriate range for the shader. Scale the bias by the + // near plane so that the bias appears consistent as other light properties change. + shadowData.m_bias = nearDist * shadowProperty.m_bias * 0.01f; FilterParameter& esmData = m_shadowData.GetElement(shadowProperty.m_shadowId.GetIndex()); - if (FilterMethodIsEsm(shadowData)) - { - // Set parameters to calculate linear depth if ESM is used. - m_filterParameterNeedsUpdate = true; - esmData.m_isEnabled = true; - esmData.m_n_f_n = nearDist / (farDist - nearDist); - esmData.m_n_f = nearDist - farDist; - esmData.m_f = farDist; - } - else - { - // Reset enabling flag if ESM is not used. - esmData.m_isEnabled = false; - } + + // Set parameters to calculate linear depth if ESM is used. + esmData.m_n_f_n = nearDist / (farDist - nearDist); + esmData.m_n_f = nearDist - farDist; + esmData.m_f = farDist; + + esmData.m_isEnabled = FilterMethodIsEsm(shadowData); + m_filterParameterNeedsUpdate = m_filterParameterNeedsUpdate || esmData.m_isEnabled; for (EsmShadowmapsPass* esmPass : m_esmShadowmapsPasses) { diff --git a/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.h index 4da4e2ff1e..3dbf88addb 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.h @@ -47,6 +47,7 @@ namespace AZ::Render void SetAspectRatio(ShadowId id, float aspectRatio) override; void SetFieldOfViewY(ShadowId id, float fieldOfViewYRadians) override; void SetShadowmapMaxResolution(ShadowId id, ShadowmapSize size) override; + void SetShadowBias(ShadowId id, float bias) override; void SetPcfMethod(ShadowId id, PcfMethod method); void SetEsmExponent(ShadowId id, float exponent); void SetShadowFilterMethod(ShadowId id, ShadowFilterMethod method) override; @@ -79,6 +80,7 @@ namespace AZ::Render { ProjectedShadowDescriptor m_desc; RPI::ViewPtr m_shadowmapView; + float m_bias = 0.1f; ShadowId m_shadowId; }; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/AreaLightBus.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/AreaLightBus.h index 9286db2817..06b00a6b84 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/AreaLightBus.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/AreaLightBus.h @@ -101,6 +101,12 @@ namespace AZ //! Sets if shadows should be enabled. virtual void SetEnableShadow(bool enabled) = 0; + + //! Returns the shadow bias. + virtual float GetShadowBias() const = 0; + + //! Sets the shadow bias. + virtual void SetShadowBias(float bias) = 0; //! Returns the maximum width and height of shadowmap. virtual ShadowmapSize GetShadowmapMaxSize() const = 0; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/AreaLightComponentConfig.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/AreaLightComponentConfig.h index 8a3bb337a2..b890b3e264 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/AreaLightComponentConfig.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/AreaLightComponentConfig.h @@ -56,6 +56,7 @@ namespace AZ // Shadows (only used for supported shapes) bool m_enableShadow = false; + float m_bias = 0.1f; ShadowmapSize m_shadowmapMaxSize = ShadowmapSize::Size256; ShadowFilterMethod m_shadowFilterMethod = ShadowFilterMethod::None; PcfMethod m_pcfMethod = PcfMethod::Bicubic; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentConfig.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentConfig.cpp index c442ee39ae..b9da5ccff4 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentConfig.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentConfig.cpp @@ -18,7 +18,7 @@ namespace AZ if (auto serializeContext = azrtti_cast(context)) { serializeContext->Class() - ->Version(6) // ATOM-15654 + ->Version(7) // ATOM-16034 ->Field("LightType", &AreaLightComponentConfig::m_lightType) ->Field("Color", &AreaLightComponentConfig::m_color) ->Field("IntensityMode", &AreaLightComponentConfig::m_intensityMode) @@ -33,6 +33,7 @@ namespace AZ ->Field("OuterShutterAngleDegrees", &AreaLightComponentConfig::m_outerShutterAngleDegrees) // Shadows ->Field("Enable Shadow", &AreaLightComponentConfig::m_enableShadow) + ->Field("Shadow Bias", &AreaLightComponentConfig::m_bias) ->Field("Shadowmap Max Size", &AreaLightComponentConfig::m_shadowmapMaxSize) ->Field("Shadow Filter Method", &AreaLightComponentConfig::m_shadowFilterMethod) ->Field("Softening Boundary Width", &AreaLightComponentConfig::m_boundaryWidthInDegrees) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentController.cpp index a6bf66d20e..b90b145320 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentController.cpp @@ -68,6 +68,8 @@ namespace AZ::Render ->Event("GetEnableShadow", &AreaLightRequestBus::Events::GetEnableShadow) ->Event("SetEnableShadow", &AreaLightRequestBus::Events::SetEnableShadow) + ->Event("GetShadowBias", &AreaLightRequestBus::Events::GetShadowBias) + ->Event("SetShadowBias", &AreaLightRequestBus::Events::SetShadowBias) ->Event("GetShadowmapMaxSize", &AreaLightRequestBus::Events::GetShadowmapMaxSize) ->Event("SetShadowmapMaxSize", &AreaLightRequestBus::Events::SetShadowmapMaxSize) ->Event("GetShadowFilterMethod", &AreaLightRequestBus::Events::GetShadowFilterMethod) @@ -94,6 +96,7 @@ namespace AZ::Render ->VirtualProperty("OuterShutterAngle", "GetOuterShutterAngle", "SetOuterShutterAngle") ->VirtualProperty("ShadowsEnabled", "GetEnableShadow", "SetEnableShadow") + ->VirtualProperty("ShadowBias", "GetShadowBias", "SetShadowBias") ->VirtualProperty("ShadowmapMaxSize", "GetShadowmapMaxSize", "SetShadowmapMaxSize") ->VirtualProperty("ShadowFilterMethod", "GetShadowFilterMethod", "SetShadowFilterMethod") ->VirtualProperty("SofteningBoundaryWidthAngle", "GetSofteningBoundaryWidthAngle", "SetSofteningBoundaryWidthAngle") @@ -307,6 +310,7 @@ namespace AZ::Render m_lightShapeDelegate->SetEnableShadow(m_configuration.m_enableShadow); if (m_configuration.m_enableShadow) { + m_lightShapeDelegate->SetShadowBias(m_configuration.m_bias); m_lightShapeDelegate->SetShadowmapMaxSize(m_configuration.m_shadowmapMaxSize); m_lightShapeDelegate->SetShadowFilterMethod(m_configuration.m_shadowFilterMethod); m_lightShapeDelegate->SetSofteningBoundaryWidthAngle(m_configuration.m_boundaryWidthInDegrees); @@ -467,6 +471,20 @@ namespace AZ::Render m_lightShapeDelegate->SetEnableShadow(enabled); } } + + float AreaLightComponentController::GetShadowBias() const + { + return m_configuration.m_bias; + } + + void AreaLightComponentController::SetShadowBias(float bias) + { + m_configuration.m_bias = bias; + if (m_lightShapeDelegate) + { + m_lightShapeDelegate->SetShadowBias(bias); + } + } ShadowmapSize AreaLightComponentController::GetShadowmapMaxSize() const { diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentController.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentController.h index 0a835a75d0..d290beb81d 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentController.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentController.h @@ -76,6 +76,8 @@ namespace AZ bool GetEnableShadow() const override; void SetEnableShadow(bool enabled) override; + float GetShadowBias() const override; + void SetShadowBias(float bias) override; ShadowmapSize GetShadowmapMaxSize() const override; void SetShadowmapMaxSize(ShadowmapSize size) override; ShadowFilterMethod GetShadowFilterMethod() const override; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DiskLightDelegate.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DiskLightDelegate.cpp index 06d0b39981..c6e4441d57 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DiskLightDelegate.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DiskLightDelegate.cpp @@ -123,6 +123,14 @@ namespace AZ::Render } } + void DiskLightDelegate::SetShadowBias(float bias) + { + if (GetShadowsEnabled() && GetLightHandle().IsValid()) + { + GetFeatureProcessor()->SetShadowBias(GetLightHandle(), bias); + } + } + void DiskLightDelegate::SetShadowmapMaxSize(ShadowmapSize size) { if (GetShadowsEnabled() && GetLightHandle().IsValid()) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DiskLightDelegate.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DiskLightDelegate.h index 53ddae669b..6931068635 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DiskLightDelegate.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DiskLightDelegate.h @@ -41,6 +41,7 @@ namespace AZ void SetShutterAngles(float innerAngleDegrees, float outerAngleDegrees) override; void SetEnableShadow(bool enabled) override; + void SetShadowBias(float bias) override; void SetShadowmapMaxSize(ShadowmapSize size) override; void SetShadowFilterMethod(ShadowFilterMethod method) override; void SetSofteningBoundaryWidthAngle(float widthInDegrees) override; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorAreaLightComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorAreaLightComponent.cpp index b58ca6448a..e45f460f18 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorAreaLightComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorAreaLightComponent.cpp @@ -131,6 +131,15 @@ namespace AZ ->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShadows) ->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::ShadowsDisabled) + ->DataElement(Edit::UIHandlers::Slider, &AreaLightComponentConfig::m_bias, "Bias", "How deep in shadow a surface must be before being affected by it.") + ->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) + ->Attribute(Edit::Attributes::Min, 0.0f) + ->Attribute(Edit::Attributes::Max, 100.0f) + ->Attribute(Edit::Attributes::SoftMin, 0.0f) + ->Attribute(Edit::Attributes::SoftMax, 1.0f) + ->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) + ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShadows) + ->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::ShadowsDisabled) ->DataElement(Edit::UIHandlers::ComboBox, &AreaLightComponentConfig::m_shadowFilterMethod, "Shadow filter method", "Filtering method of edge-softening of shadows.\n" " None: no filtering\n" diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateBase.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateBase.h index 18d88b72af..415878081c 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateBase.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateBase.h @@ -53,6 +53,7 @@ namespace AZ void SetShutterAngles([[maybe_unused]]float innerAngleDegrees, [[maybe_unused]]float outerAngleDegrees) override {}; void SetEnableShadow(bool enabled) override { m_shadowsEnabled = enabled; }; + void SetShadowBias([[maybe_unused]] float bias) override {}; void SetShadowmapMaxSize([[maybe_unused]] ShadowmapSize size) override {}; void SetShadowFilterMethod([[maybe_unused]] ShadowFilterMethod method) override {}; void SetSofteningBoundaryWidthAngle([[maybe_unused]] float widthInDegrees) override {}; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateInterface.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateInterface.h index 52f9958d40..f18c3ef9af 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateInterface.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateInterface.h @@ -67,8 +67,10 @@ namespace AZ // Shadows - //! Sets if shadows should be enabled + //! Sets if shadows should be enabled virtual void SetEnableShadow(bool enabled) = 0; + //! Sets the shadow bias + virtual void SetShadowBias(float bias) = 0; //! Sets the maximum resolution of the shadow map virtual void SetShadowmapMaxSize(ShadowmapSize size) = 0; //! Sets the filter method for the shadow diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SphereLightDelegate.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SphereLightDelegate.cpp index 1da6847269..edf08ba8c9 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SphereLightDelegate.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SphereLightDelegate.cpp @@ -11,121 +11,124 @@ #include #include -namespace AZ +namespace AZ::Render { - namespace Render + SphereLightDelegate::SphereLightDelegate(LmbrCentral::SphereShapeComponentRequests* shapeBus, EntityId entityId, bool isVisible) + : LightDelegateBase(entityId, isVisible) + , m_shapeBus(shapeBus) { - SphereLightDelegate::SphereLightDelegate(LmbrCentral::SphereShapeComponentRequests* shapeBus, EntityId entityId, bool isVisible) - : LightDelegateBase(entityId, isVisible) - , m_shapeBus(shapeBus) - { - InitBase(entityId); - } + InitBase(entityId); + } - float SphereLightDelegate::CalculateAttenuationRadius(float lightThreshold) const - { - // Calculate the radius at which the irradiance will be equal to cutoffIntensity. - float intensity = GetPhotometricValue().GetCombinedIntensity(PhotometricUnit::Lumen); - return sqrt(intensity / lightThreshold); - } + float SphereLightDelegate::CalculateAttenuationRadius(float lightThreshold) const + { + // Calculate the radius at which the irradiance will be equal to cutoffIntensity. + float intensity = GetPhotometricValue().GetCombinedIntensity(PhotometricUnit::Lumen); + return sqrt(intensity / lightThreshold); + } - void SphereLightDelegate::HandleShapeChanged() + void SphereLightDelegate::HandleShapeChanged() + { + if (GetLightHandle().IsValid()) { - if (GetLightHandle().IsValid()) - { - GetFeatureProcessor()->SetPosition(GetLightHandle(), GetTransform().GetTranslation()); - GetFeatureProcessor()->SetBulbRadius(GetLightHandle(), GetRadius()); - } + GetFeatureProcessor()->SetPosition(GetLightHandle(), GetTransform().GetTranslation()); + GetFeatureProcessor()->SetBulbRadius(GetLightHandle(), GetRadius()); } + } - float SphereLightDelegate::GetSurfaceArea() const - { - float radius = GetRadius(); - return 4.0f * Constants::Pi * radius * radius; - } + float SphereLightDelegate::GetSurfaceArea() const + { + float radius = GetRadius(); + return 4.0f * Constants::Pi * radius * radius; + } - float SphereLightDelegate::GetRadius() const - { - return m_shapeBus->GetRadius() * GetTransform().GetUniformScale(); - } + float SphereLightDelegate::GetRadius() const + { + return m_shapeBus->GetRadius() * GetTransform().GetUniformScale(); + } - void SphereLightDelegate::DrawDebugDisplay(const Transform& transform, const Color& color, AzFramework::DebugDisplayRequests& debugDisplay, bool isSelected) const + void SphereLightDelegate::DrawDebugDisplay(const Transform& transform, const Color& color, AzFramework::DebugDisplayRequests& debugDisplay, bool isSelected) const + { + if (isSelected) { - if (isSelected) - { - debugDisplay.SetColor(color); + debugDisplay.SetColor(color); - // Draw a sphere for the attenuation radius - debugDisplay.DrawWireSphere(transform.GetTranslation(), GetConfig()->m_attenuationRadius); - } + // Draw a sphere for the attenuation radius + debugDisplay.DrawWireSphere(transform.GetTranslation(), GetConfig()->m_attenuationRadius); } + } - void SphereLightDelegate::SetEnableShadow(bool enabled) - { - Base::SetEnableShadow(enabled); + void SphereLightDelegate::SetEnableShadow(bool enabled) + { + Base::SetEnableShadow(enabled); - if (GetLightHandle().IsValid()) - { - GetFeatureProcessor()->SetShadowsEnabled(GetLightHandle(), enabled); - } + if (GetLightHandle().IsValid()) + { + GetFeatureProcessor()->SetShadowsEnabled(GetLightHandle(), enabled); } - - void SphereLightDelegate::SetShadowmapMaxSize(ShadowmapSize size) + } + + void SphereLightDelegate::SetShadowBias(float bias) + { + if (GetShadowsEnabled() && GetLightHandle().IsValid()) { - if (GetShadowsEnabled() && GetLightHandle().IsValid()) - { - GetFeatureProcessor()->SetShadowmapMaxResolution(GetLightHandle(), size); - } + GetFeatureProcessor()->SetShadowBias(GetLightHandle(), bias); } + } - void SphereLightDelegate::SetShadowFilterMethod(ShadowFilterMethod method) + void SphereLightDelegate::SetShadowmapMaxSize(ShadowmapSize size) + { + if (GetShadowsEnabled() && GetLightHandle().IsValid()) { - if (GetShadowsEnabled() && GetLightHandle().IsValid()) - { - GetFeatureProcessor()->SetShadowFilterMethod(GetLightHandle(), method); - } + GetFeatureProcessor()->SetShadowmapMaxResolution(GetLightHandle(), size); } + } - void SphereLightDelegate::SetSofteningBoundaryWidthAngle(float widthInDegrees) + void SphereLightDelegate::SetShadowFilterMethod(ShadowFilterMethod method) + { + if (GetShadowsEnabled() && GetLightHandle().IsValid()) { - if (GetShadowsEnabled() && GetLightHandle().IsValid()) - { - GetFeatureProcessor()->SetSofteningBoundaryWidthAngle(GetLightHandle(), DegToRad(widthInDegrees)); - } + GetFeatureProcessor()->SetShadowFilterMethod(GetLightHandle(), method); } + } - void SphereLightDelegate::SetPredictionSampleCount(uint32_t count) + void SphereLightDelegate::SetSofteningBoundaryWidthAngle(float widthInDegrees) + { + if (GetShadowsEnabled() && GetLightHandle().IsValid()) { - if (GetShadowsEnabled() && GetLightHandle().IsValid()) - { - GetFeatureProcessor()->SetPredictionSampleCount(GetLightHandle(), count); - } + GetFeatureProcessor()->SetSofteningBoundaryWidthAngle(GetLightHandle(), DegToRad(widthInDegrees)); } + } - void SphereLightDelegate::SetFilteringSampleCount(uint32_t count) + void SphereLightDelegate::SetPredictionSampleCount(uint32_t count) + { + if (GetShadowsEnabled() && GetLightHandle().IsValid()) { - if (GetShadowsEnabled() && GetLightHandle().IsValid()) - { - GetFeatureProcessor()->SetFilteringSampleCount(GetLightHandle(), count); - } + GetFeatureProcessor()->SetPredictionSampleCount(GetLightHandle(), count); } + } - void SphereLightDelegate::SetPcfMethod(PcfMethod method) + void SphereLightDelegate::SetFilteringSampleCount(uint32_t count) + { + if (GetShadowsEnabled() && GetLightHandle().IsValid()) { - if (GetShadowsEnabled() && GetLightHandle().IsValid()) - { - GetFeatureProcessor()->SetPcfMethod(GetLightHandle(), method); - } + GetFeatureProcessor()->SetFilteringSampleCount(GetLightHandle(), count); } + } - void SphereLightDelegate::SetEsmExponent(float esmExponent) + void SphereLightDelegate::SetPcfMethod(PcfMethod method) + { + if (GetShadowsEnabled() && GetLightHandle().IsValid()) { - if (GetShadowsEnabled() && GetLightHandle().IsValid()) - { - GetFeatureProcessor()->SetEsmExponent(GetLightHandle(), esmExponent); - } + GetFeatureProcessor()->SetPcfMethod(GetLightHandle(), method); } + } - - } // namespace Render -} // namespace AZ + void SphereLightDelegate::SetEsmExponent(float esmExponent) + { + if (GetShadowsEnabled() && GetLightHandle().IsValid()) + { + GetFeatureProcessor()->SetEsmExponent(GetLightHandle(), esmExponent); + } + } +} // namespace AZ::Render diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SphereLightDelegate.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SphereLightDelegate.h index 6dd872d693..984af56c17 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SphereLightDelegate.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SphereLightDelegate.h @@ -31,6 +31,7 @@ namespace AZ float GetSurfaceArea() const override; float GetEffectiveSolidAngle() const override { return PhotometricValue::OmnidirectionalSteradians; } void SetEnableShadow(bool enabled) override; + void SetShadowBias(float bias) override; void SetShadowmapMaxSize(ShadowmapSize size) override; void SetShadowFilterMethod(ShadowFilterMethod method) override; void SetSofteningBoundaryWidthAngle(float widthInDegrees) override; From 4b0527c07f27b3bbdd7f29757e3369b487128b49 Mon Sep 17 00:00:00 2001 From: Dayo Lawal Date: Tue, 27 Jul 2021 13:42:48 -0500 Subject: [PATCH 064/160] Moving comments Signed-off-by: Dayo Lawal --- .../AtomToolsFramework/Application/AtomToolsApplication.h | 2 +- .../Code/Source/Application/AtomToolsApplication.cpp | 2 -- .../MaterialEditor/Code/Source/MaterialEditorApplication.cpp | 2 -- .../MaterialEditor/Code/Source/MaterialEditorApplication.h | 3 +++ .../Code/Source/ShaderManagementConsoleApplication.cpp | 2 -- 5 files changed, 4 insertions(+), 7 deletions(-) diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h index 3b2e5a7e8a..bceea24aad 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h @@ -23,7 +23,7 @@ namespace AtomToolsFramework { - //!Base class for Atom tools to inherit from + //! Base class for Atom tools to inherit from class AtomToolsApplication : public AzFramework::Application , public AzQtComponents::AzQtApplication diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp index 0dc579b017..3a542db1a4 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp @@ -158,8 +158,6 @@ namespace AtomToolsFramework AZStd::vector AtomToolsApplication::GetCriticalAssetFilters() const { - // List of common asset filters for things that need to be compiled to run the material editor - // Some of these things will not be necessary once we have proper support for queued asset loading and reloading return AZStd::vector({}); } diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp index 09c7588de9..4dd6b6d9dc 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp @@ -113,8 +113,6 @@ namespace MaterialEditor AZStd::vector MaterialEditorApplication::GetCriticalAssetFilters() const { - // List of common asset filters for things that need to be compiled to run the material editor - // Some of these things will not be necessary once we have proper support for queued asset loading and reloading return AZStd::vector({ "passes/", "config/", "MaterialEditor" }); } diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h index 0177013a3d..5f3b71a5aa 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h @@ -49,6 +49,9 @@ namespace MaterialEditor void ProcessCommandLine(const AZ::CommandLine& commandLine) override; void StartInternal() override; AZStd::string GetBuildTargetName() const override; + + //! List of common asset filters for things that need to be compiled to run the material editor + //! Some of these things will not be necessary once we have proper support for queued asset loading and reloading AZStd::vector GetCriticalAssetFilters() const override; }; } // namespace MaterialEditor diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp index 6f6ee697d5..96046bf98e 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp @@ -102,8 +102,6 @@ namespace ShaderManagementConsole AZStd::vector ShaderManagementConsoleApplication::GetCriticalAssetFilters() const { - // List of common asset filters for things that need to be compiled to run the material editor - // Some of these things will not be necessary once we have proper support for queued asset loading and reloading return AZStd::vector({ "passes/", "config/" }); } From ce3ec0d49c45f212972660d62c986a69fa95d49d Mon Sep 17 00:00:00 2001 From: dtamkin1 Date: Tue, 27 Jul 2021 15:26:22 -0500 Subject: [PATCH 065/160] Moved toggle swtich back to the left side per UX's request Signed-off-by: dtamkin1 --- .../AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.cpp index 49f7ba3885..5ea36bb30e 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.cpp @@ -1122,8 +1122,7 @@ namespace AzToolsFramework m_handlerName = AZ::Edit::UIHandlers::CheckBox; PropertyTypeRegistrationMessages::Bus::BroadcastResult(m_handler, &PropertyTypeRegistrationMessages::Bus::Events::ResolvePropertyHandler, m_handlerName, azrtti_typeid()); m_toggleSwitch = m_handler->CreateGUI(this); - m_toggleSwitch->setFixedWidth(38); - m_middleLayout->addWidget(m_toggleSwitch, 1, Qt::AlignRight); + m_middleLayout->insertWidget(0, m_toggleSwitch, 1); auto checkBoxCtrl = static_cast(m_toggleSwitch); QObject::connect(checkBoxCtrl, &AzToolsFramework::PropertyCheckBoxCtrl::valueChanged, this, &PropertyRowWidget::OnClickedToggleButton); } From a20588952e05f7d3ea3a5a2270f2afeeb946ec36 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Tue, 27 Jul 2021 15:41:17 -0700 Subject: [PATCH 066/160] disable vcpkg for every project (#2507) Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- cmake/Platform/Common/Directory.Build.props | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cmake/Platform/Common/Directory.Build.props b/cmake/Platform/Common/Directory.Build.props index 1adf33ee89..73aa984073 100644 --- a/cmake/Platform/Common/Directory.Build.props +++ b/cmake/Platform/Common/Directory.Build.props @@ -10,7 +10,10 @@ SPDX-License-Identifier: Apache-2.0 OR MIT true true + @VCPKG_CONFIGURATION_MAPPING@ + + false From 9742626aba3b763bfb1383e0c1a86f951a2c25ee Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Tue, 27 Jul 2021 15:59:28 -0700 Subject: [PATCH 067/160] Make SC unit tests run serially Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com> --- Gems/ScriptCanvasTesting/Code/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Gems/ScriptCanvasTesting/Code/CMakeLists.txt b/Gems/ScriptCanvasTesting/Code/CMakeLists.txt index 23c9627e83..8f3ba103e7 100644 --- a/Gems/ScriptCanvasTesting/Code/CMakeLists.txt +++ b/Gems/ScriptCanvasTesting/Code/CMakeLists.txt @@ -113,6 +113,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) ) ly_add_googletest( NAME Gem::ScriptCanvasTesting.Editor.Tests + TEST_SERIAL true ) endif() From 7b7adb8573122ad3b9b4bcffa46b4629e45bb959 Mon Sep 17 00:00:00 2001 From: amzn-phist <52085794+amzn-phist@users.noreply.github.com> Date: Tue, 27 Jul 2021 18:18:03 -0500 Subject: [PATCH 068/160] Don't require a specific version of Wwise SDK, allow for later versions to be used (#2484) * Updates the Wwise SDK detection in CMake Parses AkWwiseSDKVersion.h to obtain the version instead of requiring an exact version to be installed. Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com> * Updates readme.md information about Wwise Rewrite some of the setup info about Wwise, mention the two ways in which Wwise can be found via CMake and that users can install later versions than the one specified. Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com> * Remove unnecessary parts of Wwise version detect Don't need to parse the file contents, it was only being used to print a message to CMake. Simplify the validation to just checking that the SDK version header exists. Maybe in the future we can reinstate better version checking to make sure the version falls within a range. Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com> * Updates capitalization of Audiokinetic name Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com> --- Gems/AudioEngineWwise/gem.json | 2 +- README.md | 13 +++++++------ cmake/3rdParty/FindWwise.cmake | 30 +++++++++--------------------- 3 files changed, 17 insertions(+), 28 deletions(-) diff --git a/Gems/AudioEngineWwise/gem.json b/Gems/AudioEngineWwise/gem.json index dc5f968bc7..699ed8419a 100644 --- a/Gems/AudioEngineWwise/gem.json +++ b/Gems/AudioEngineWwise/gem.json @@ -8,5 +8,5 @@ "canonical_tags": ["Gem"], "user_tags": ["Audio", "Utility", "Tools"], "icon_path": "preview.png", - "requirements": "Users will need to download WWise from the AudioKinetic web site: https://www.audiokinetic.com/download/" + "requirements": "Users will need to download Wwise from the Audiokinetic web site: https://www.audiokinetic.com/download/" } diff --git a/README.md b/README.md index 6b88097739..c129fffb6c 100644 --- a/README.md +++ b/README.md @@ -41,11 +41,13 @@ git clone https://github.com/o3de/o3de.git #### Optional -* Wwise - 2021.1.1.7601 minimum: [https://www.audiokinetic.com/download/](https://www.audiokinetic.com/download/) +* Wwise version 2021.1.1.7601 minimum: [https://www.audiokinetic.com/download/](https://www.audiokinetic.com/download/) * Note: This requires registration and installation of a client application to download - * Make sure to select the SDK(C++) component during installation of Wwise - * You will also need to set an environment variable: `set LY_WWISE_INSTALL_PATH=` - * For example: `set LY_WWISE_INSTALL_PATH="C:\Program Files (x86)\Audiokinetic\Wwise 2021.1.1.7601"` + * Note: It is generally okay to use a more recent version of Wwise, but some SDK updates will require code changes + * Make sure to select the `SDK(C++)` component during installation of Wwise + * CMake can find the Wwise install location in two ways: + * The `LY_WWISE_INSTALL_PATH` CMake cache variable -- this is checked first + * The `WWISEROOT` environment variable which is set when installing Wwise SDK ### Quick Start Build Steps @@ -54,8 +56,7 @@ git clone https://github.com/o3de/o3de.git 1. Install the following redistributables to the following: - Visual Studio and VC++ redistributable can be installed to any location - CMake can be installed to any location, as long as it's available in the system path - - (Optional) Wwise can be installed anywhere, but you will need to set an environment variable for CMake to detect it: `set LY_WWISE_INSTALL_PATH=` - + 1. Configure the source into a solution using this command line, replacing and <3rdParty cache path> to a path you've created: ``` cmake -B -S -G "Visual Studio 16" -DLY_3RDPARTY_PATH=<3rdParty cache path> -DLY_UNITY_BUILD=ON -DLY_PROJECTS=AutomatedTesting diff --git a/cmake/3rdParty/FindWwise.cmake b/cmake/3rdParty/FindWwise.cmake index 8cd6db31dd..4cb95da319 100644 --- a/cmake/3rdParty/FindWwise.cmake +++ b/cmake/3rdParty/FindWwise.cmake @@ -6,25 +6,16 @@ # # -# The current supported version of Wwise -set(WWISE_VERSION 2021.1.1.7601) - # Wwise Install Path -# Initialize to the default 3rdParty path -set(LY_WWISE_INSTALL_PATH "" CACHE PATH "Path to Wwise version ${WWISE_VERSION} installation.") +set(LY_WWISE_INSTALL_PATH "" CACHE PATH "Path to Wwise installation.") +# Check for a known file in the SDK path to verify the path function(is_valid_sdk sdk_path is_valid) set(${is_valid} FALSE PARENT_SCOPE) if(EXISTS ${sdk_path}) set(sdk_version_file ${sdk_path}/SDK/include/AK/AkWwiseSDKVersion.h) if(EXISTS ${sdk_version_file}) - string(FIND ${sdk_path} ${WWISE_VERSION} index) - if(NOT index EQUAL -1) - set(${is_valid} TRUE PARENT_SCOPE) - else() - # The install path doesn't contain the WWISE_VERSION string. - # The path could still be correct, but it would require parsing the AkWwiseSDKVersion.h to verify. - endif() + set(${is_valid} TRUE PARENT_SCOPE) endif() endif() endfunction() @@ -32,19 +23,17 @@ endfunction() # Paths that will be checked, in order: # - CMake cache variable # - WWISEROOT Environment Variable -# - Standard 3rdParty path set(WWISE_SDK_PATHS "${LY_WWISE_INSTALL_PATH}" "$ENV{WWISEROOT}" - "${LY_3RDPARTY_PATH}/Wwise/${WWISE_VERSION}" ) set(found_sdk FALSE) -foreach(test_path ${WWISE_SDK_PATHS}) - is_valid_sdk(${test_path} found_sdk) +foreach(candidate_path ${WWISE_SDK_PATHS}) + is_valid_sdk(${candidate_path} found_sdk) if(found_sdk) - # Update the Wwise Install Path cache variable - set(LY_WWISE_INSTALL_PATH "${test_path}") + # Update the Wwise Install Path variable internally + set(LY_WWISE_INSTALL_PATH "${candidate_path}") break() endif() endforeach() @@ -112,15 +101,14 @@ set(WWISE_COMPILE_DEFINITIONS ) -# The default install path might look different than the standard 3rdParty format (${LY_3RDPARTY_PATH}//). # Use these to get the parent path and folder name before adding the external 3p target. -get_filename_component(WWISE_3P_ROOT ${LY_WWISE_INSTALL_PATH} DIRECTORY) +get_filename_component(WWISE_INSTALL_ROOT ${LY_WWISE_INSTALL_PATH} DIRECTORY) get_filename_component(WWISE_FOLDER ${LY_WWISE_INSTALL_PATH} NAME) ly_add_external_target( NAME Wwise VERSION "${WWISE_FOLDER}" - 3RDPARTY_ROOT_DIRECTORY "${WWISE_3P_ROOT}" + 3RDPARTY_ROOT_DIRECTORY "${WWISE_INSTALL_ROOT}" INCLUDE_DIRECTORIES SDK/include COMPILE_DEFINITIONS ${WWISE_COMPILE_DEFINITIONS} ) From c177fe3c040e585a0ae64504c96f6fcdd84aeff8 Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Tue, 27 Jul 2021 16:27:36 -0700 Subject: [PATCH 069/160] use work around for missing SERIAL tag for ly_add_googletest() Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com> --- Gems/ScriptCanvasTesting/Code/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/ScriptCanvasTesting/Code/CMakeLists.txt b/Gems/ScriptCanvasTesting/Code/CMakeLists.txt index 8f3ba103e7..7291cd65eb 100644 --- a/Gems/ScriptCanvasTesting/Code/CMakeLists.txt +++ b/Gems/ScriptCanvasTesting/Code/CMakeLists.txt @@ -113,8 +113,8 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) ) ly_add_googletest( NAME Gem::ScriptCanvasTesting.Editor.Tests - TEST_SERIAL true ) + set_tests_properties(Gem::ScriptCanvasTesting.Editor.Tests.main::TEST_RUN PROPERTIES RUN_SERIAL true) endif() From 2174f8415ab4233cd87a135301c24dc36422457e Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Tue, 27 Jul 2021 18:32:00 -0700 Subject: [PATCH 070/160] making azcore tests serialized as a sanity check Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com> --- Code/Framework/AzCore/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Code/Framework/AzCore/CMakeLists.txt b/Code/Framework/AzCore/CMakeLists.txt index ea7cc27af5..0a03b6b77c 100644 --- a/Code/Framework/AzCore/CMakeLists.txt +++ b/Code/Framework/AzCore/CMakeLists.txt @@ -130,6 +130,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) ly_add_googletest( NAME AZ::AzCore.Tests ) + set_tests_properties(AZ::AzCore.Tests.main::TEST_RUN PROPERTIES RUN_SERIAL true) ly_add_googlebenchmark( NAME AZ::AzCore.Benchmarks TARGET AZ::AzCore.Tests From 0cfac06c699c909626d0b7dcb41b44d301f6381b Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Tue, 27 Jul 2021 18:55:40 -0700 Subject: [PATCH 071/160] making azcore tests serialized as a sanity check only on non android Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com> --- Code/Framework/AzCore/CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Code/Framework/AzCore/CMakeLists.txt b/Code/Framework/AzCore/CMakeLists.txt index 0a03b6b77c..785352cf05 100644 --- a/Code/Framework/AzCore/CMakeLists.txt +++ b/Code/Framework/AzCore/CMakeLists.txt @@ -130,7 +130,9 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) ly_add_googletest( NAME AZ::AzCore.Tests ) - set_tests_properties(AZ::AzCore.Tests.main::TEST_RUN PROPERTIES RUN_SERIAL true) + if(PAL_TRAIT_TEST_GOOGLE_TEST_SUPPORTED) + set_tests_properties(AZ::AzCore.Tests.main::TEST_RUN PROPERTIES RUN_SERIAL true) + endif() ly_add_googlebenchmark( NAME AZ::AzCore.Benchmarks TARGET AZ::AzCore.Tests From 6868a48bb08a39cb7ea380b0f57974ad93934dfd Mon Sep 17 00:00:00 2001 From: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> Date: Tue, 27 Jul 2021 22:04:37 -0500 Subject: [PATCH 072/160] Adding o3de.py subcommands for engine.json and gem.json modification (#2411) The new commands are edit-engine-properties and edit-gem-properties They can modify specific fields within these manifest files, that should affect build system. More importantly, this commands can be used to modify the "engine_name" field in the engine.json and the "gem_name" field in the gem.json Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> --- scripts/o3de.py | 12 +- scripts/o3de/o3de/engine_properties.py | 82 +++++++++ scripts/o3de/o3de/gem_properties.py | 163 ++++++++++++++++++ scripts/o3de/o3de/project_properties.py | 6 +- scripts/o3de/tests/CMakeLists.txt | 14 ++ .../o3de/tests/unit_test_engine_properties.py | 72 ++++++++ .../o3de/tests/unit_test_gem_properties.py | 99 +++++++++++ .../tests/unit_test_project_properties.py | 3 +- 8 files changed, 444 insertions(+), 7 deletions(-) create mode 100644 scripts/o3de/o3de/engine_properties.py create mode 100644 scripts/o3de/o3de/gem_properties.py create mode 100644 scripts/o3de/tests/unit_test_engine_properties.py create mode 100644 scripts/o3de/tests/unit_test_gem_properties.py diff --git a/scripts/o3de.py b/scripts/o3de.py index 06873e1de2..03f737643f 100755 --- a/scripts/o3de.py +++ b/scripts/o3de.py @@ -28,7 +28,7 @@ def add_args(parser, subparsers) -> None: o3de_package_dir = (script_dir / 'o3de').resolve() # add the scripts/o3de directory to the front of the sys.path sys.path.insert(0, str(o3de_package_dir)) - from o3de import engine_template, global_project, register, print_registration, get_registration, \ + from o3de import engine_properties, engine_template, gem_properties, global_project, register, print_registration, get_registration, \ enable_gem, disable_gem, project_properties, sha256 # Remove the temporarily added path sys.path = sys.path[1:] @@ -52,9 +52,15 @@ def add_args(parser, subparsers) -> None: # remove a gem from a project disable_gem.add_args(subparsers) - - # modify project properties + + # modify engine properties + engine_properties.add_args(subparsers) + + # modify project properties project_properties.add_args(subparsers) + + # modify gem properties + gem_properties.add_args(subparsers) # sha256 sha256.add_args(subparsers) diff --git a/scripts/o3de/o3de/engine_properties.py b/scripts/o3de/o3de/engine_properties.py new file mode 100644 index 0000000000..92930dbb1c --- /dev/null +++ b/scripts/o3de/o3de/engine_properties.py @@ -0,0 +1,82 @@ +# +# Copyright (c) Contributors to the Open 3D Engine Project. +# For complete copyright and license terms please see the LICENSE at the root of this distribution. +# +# SPDX-License-Identifier: Apache-2.0 OR MIT +# +# + +import argparse +import json +import os +import pathlib +import sys +import logging + +from o3de import manifest, utils + +logger = logging.getLogger() +logging.basicConfig() + +def edit_engine_props(engine_path: pathlib.Path = None, + engine_name: str = None, + new_name: str = None, + new_version: str = None) -> int: + if not engine_path and not engine_name: + logger.error(f'Either a engine path or a engine name must be supplied to lookup engine.json') + return 1 + if not engine_path: + engine_path = manifest.get_registered(engine_name=engine_name) + + if not engine_path: + logger.error(f'Error unable locate engine path: No engine with name {engine_name} is registered in any manifest') + return 1 + + engine_json_data = manifest.get_engine_json_data(engine_path=engine_path) + if not engine_json_data: + return 1 + + if new_name: + if not utils.validate_identifier(new_name): + logger.error(f'Engine name must be fewer than 64 characters, contain only alphanumeric, "_" or "-"' + f' characters, and start with a letter. {new_name}') + return 1 + engine_json_data['engine_name'] = new_name + if new_version: + engine_json_data['O3DEVersion'] = new_version + + return 0 if manifest.save_o3de_manifest(engine_json_data, pathlib.Path(engine_path) / 'engine.json') else 1 + +def _edit_engine_props(args: argparse) -> int: + return edit_engine_props(args.engine_path, + args.engine_name, + args.engine_new_name, + args.engine_version) + +def add_parser_args(parser): + group = parser.add_mutually_exclusive_group(required=True) + group.add_argument('-ep', '--engine-path', type=pathlib.Path, required=False, + help='The path to the engine.') + group.add_argument('-en', '--engine-name', type=str, required=False, + help='The name of the engine.') + group = parser.add_argument_group('properties', 'arguments for modifying individual engine properties.') + group.add_argument('-enn', '--engine-new-name', type=str, required=False, + help='Sets the name for the engine.') + group.add_argument('-ev', '--engine-version', type=str, required=False, + help='Sets the version for the engine.') + parser.set_defaults(func=_edit_engine_props) + +def add_args(subparsers) -> None: + enable_engine_props_subparser = subparsers.add_parser('edit-engine-properties') + add_parser_args(enable_engine_props_subparser) + + +def main(): + the_parser = argparse.ArgumentParser() + add_parser_args(the_parser) + the_args = the_parser.parse_args() + ret = the_args.func(the_args) if hasattr(the_args, 'func') else 1 + sys.exit(ret) + +if __name__ == "__main__": + main() diff --git a/scripts/o3de/o3de/gem_properties.py b/scripts/o3de/o3de/gem_properties.py new file mode 100644 index 0000000000..c97e5db89d --- /dev/null +++ b/scripts/o3de/o3de/gem_properties.py @@ -0,0 +1,163 @@ +# +# Copyright (c) Contributors to the Open 3D Engine Project. +# For complete copyright and license terms please see the LICENSE at the root of this distribution. +# +# SPDX-License-Identifier: Apache-2.0 OR MIT +# +# + +import argparse +import json +import os +import pathlib +import sys +import logging + +from o3de import manifest, utils + +logger = logging.getLogger() +logging.basicConfig() + + +def update_values_in_key_list(existing_values: list, new_values: list or str, remove_values: list or str, + replace_values: list or str): + """ + Updates values within a list by first appending values in the new_values list, removing values in the remove_values + list and then replacing values in the replace_values list + :param existing_values list with existing values to modify + :param new_values list with values to add to the existing value list + :param remove_values list with values to remove from the existing value list + :param replace_values list with values to replace in the existing value list + + returns updated existing value list + """ + if new_values: + new_values = new_values.split() if isinstance(new_values, str) else new_values + existing_values.extend(new_values) + if remove_values: + remove_values = remove_values.split() if isinstance(remove_values, str) else remove_values + existing_values = list(filter(lambda value: value not in remove_values, existing_values)) + if replace_values: + replace_values = replace_values.split() if isinstance(replace_values, str) else replace_values + existing_values = replace_values + + return existing_values + + +def edit_gem_props(gem_path: pathlib.Path = None, + gem_name: str = None, + new_name: str = None, + new_display: str = None, + new_origin: str = None, + new_type: str = None, + new_summary: str = None, + new_icon: str = None, + new_requirements: str = None, + new_tags: list or str = None, + remove_tags: list or str = None, + replace_tags: list or str = None, + ) -> int: + + if not gem_path and not gem_name: + logger.error(f'Either a gem path or a gem name must be supplied to lookup gem.json') + return 1 + if not gem_path: + gem_path = manifest.get_registered(gem_name=gem_name) + + if not gem_path: + logger.error(f'Error unable locate gem path: No gem with name {gem_name} is registered in any manifest') + return 1 + + gem_json_data = manifest.get_gem_json_data(gem_path=gem_path) + if not gem_json_data: + return 1 + + update_key_dict = {} + if new_name: + if not utils.validate_identifier(new_name): + logger.error(f'Engine name must be fewer than 64 characters, contain only alphanumeric, "_" or "-"' + f' characters, and start with a letter. {new_name}') + return 1 + update_key_dict['gem_name'] = new_name + if new_display: + update_key_dict['display_name'] = new_display + if new_origin: + update_key_dict['origin'] = new_origin + if new_type: + update_key_dict['type'] = new_type + if new_summary: + update_key_dict['summary'] = new_summary + if new_icon: + update_key_dict['icon_path'] = new_icon + if new_requirements: + update_key_dict['icon_requirements'] = new_requirements + + update_key_dict['user_tags'] = update_values_in_key_list(gem_json_data.get('user_tags', []), new_tags, + remove_tags, replace_tags) + + gem_json_data.update(update_key_dict) + + return 0 if manifest.save_o3de_manifest(gem_json_data, pathlib.Path(gem_path) / 'gem.json') else 1 + + +def _edit_gem_props(args: argparse) -> int: + return edit_gem_props(args.gem_path, + args.gem_name, + args.gem_new_name, + args.gem_display, + args.gem_origin, + args.gem_type, + args.gem_summary, + args.gem_icon, + args.gem_requirements, + args.add_tags, + args.remove_tags, + args.replace_tags) + + +def add_parser_args(parser): + group = parser.add_mutually_exclusive_group(required=True) + group.add_argument('-gp', '--gem-path', type=pathlib.Path, required=False, + help='The path to the gem.') + group.add_argument('-gn', '--gem-name', type=str, required=False, + help='The name of the gem.') + group = parser.add_argument_group('properties', 'arguments for modifying individual gem properties.') + group.add_argument('-gnn', '--gem-new-name', type=str, required=False, + help='Sets the name for the gem.') + group.add_argument('-gd', '--gem-display', type=str, required=False, + help='Sets the gem display name.') + group.add_argument('-go', '--gem-origin', type=str, required=False, + help='Sets description for gem origin.') + group.add_argument('-gt', '--gem-type', type=str, required=False, choices=['Code', 'Tool', 'Asset'], + help='Sets the gem type. Can only be one of the selected choices') + group.add_argument('-gs', '--gem-summary', type=str, required=False, + help='Sets the summary description of the gem.') + group.add_argument('-gi', '--gem-icon', type=str, required=False, + help='Sets the path to the projects icon resource.') + group.add_argument('-gr', '--gem-requirements', type=str, required=False, + help='Sets the description of the requirements needed to use the gem') + group = parser.add_mutually_exclusive_group(required=False) + group.add_argument('-at', '--add-tags', type=str, nargs='*', required=False, + help='Adds tag(s) to user_tags property. Can be specified multiple times') + group.add_argument('-dt', '--remove-tags', type=str, nargs='*', required=False, + help='Removes tag(s) from the user_tags property. Can be specified multiple times') + group.add_argument('-rt', '--replace-tags', type=str, nargs='*', required=False, + help='Replace tag(s) in user_tags property. Can be specified multiple times') + parser.set_defaults(func=_edit_gem_props) + + +def add_args(subparsers) -> None: + enable_gem_props_subparser = subparsers.add_parser('edit-gem-properties') + add_parser_args(enable_gem_props_subparser) + + +def main(): + the_parser = argparse.ArgumentParser() + add_parser_args(the_parser) + the_args = the_parser.parse_args() + ret = the_args.func(the_args) if hasattr(the_args, 'func') else 1 + sys.exit(ret) + + +if __name__ == "__main__": + main() diff --git a/scripts/o3de/o3de/project_properties.py b/scripts/o3de/o3de/project_properties.py index 977f9777b2..04731ad3de 100644 --- a/scripts/o3de/o3de/project_properties.py +++ b/scripts/o3de/o3de/project_properties.py @@ -26,7 +26,7 @@ def get_project_props(name: str = None, path: pathlib.Path = None) -> dict: return None return proj_json -def edit_project_props(proj_path: pathlib.Path, +def edit_project_props(proj_path: pathlib.Path = None, proj_name: str = None, new_name: str = None, new_origin: str = None, @@ -71,8 +71,8 @@ def edit_project_props(proj_path: pathlib.Path, tag_list = replace_tags.split() if isinstance(replace_tags, str) else replace_tags proj_json['user_tags'] = tag_list - manifest.save_o3de_manifest(proj_json, pathlib.Path(proj_path) / 'project.json') - return 0 + + return 0 if manifest.save_o3de_manifest(proj_json, pathlib.Path(proj_path) / 'project.json') else 1 def _edit_project_props(args: argparse) -> int: return edit_project_props(args.project_path, diff --git a/scripts/o3de/tests/CMakeLists.txt b/scripts/o3de/tests/CMakeLists.txt index 42ded05b29..00d0774c45 100644 --- a/scripts/o3de/tests/CMakeLists.txt +++ b/scripts/o3de/tests/CMakeLists.txt @@ -39,6 +39,13 @@ ly_add_pytest( EXCLUDE_TEST_RUN_TARGET_FROM_IDE ) +ly_add_pytest( + NAME o3de_engine_properties + PATH ${CMAKE_CURRENT_LIST_DIR}/unit_test_engine_properties.py + TEST_SUITE smoke + EXCLUDE_TEST_RUN_TARGET_FROM_IDE +) + ly_add_pytest( NAME o3de_project_properties PATH ${CMAKE_CURRENT_LIST_DIR}/unit_test_project_properties.py @@ -46,6 +53,13 @@ ly_add_pytest( EXCLUDE_TEST_RUN_TARGET_FROM_IDE ) +ly_add_pytest( + NAME o3de_gem_properties + PATH ${CMAKE_CURRENT_LIST_DIR}/unit_test_gem_properties.py + TEST_SUITE smoke + EXCLUDE_TEST_RUN_TARGET_FROM_IDE +) + ly_add_pytest( NAME o3de_template PATH ${CMAKE_CURRENT_LIST_DIR}/unit_test_engine_template.py diff --git a/scripts/o3de/tests/unit_test_engine_properties.py b/scripts/o3de/tests/unit_test_engine_properties.py new file mode 100644 index 0000000000..19cb7d4e62 --- /dev/null +++ b/scripts/o3de/tests/unit_test_engine_properties.py @@ -0,0 +1,72 @@ +# +# Copyright (c) Contributors to the Open 3D Engine Project. +# For complete copyright and license terms please see the LICENSE at the root of this distribution. +# +# SPDX-License-Identifier: Apache-2.0 OR MIT +# +# + +import json +import pytest +import pathlib +from unittest.mock import patch + +from o3de import engine_properties + + +TEST_ENGINE_JSON_PAYLOAD = ''' +{ + "engine_name": "o3de", + "restricted_name": "o3de", + "FileVersion": 1, + "O3DEVersion": "0.0.0.0", + "O3DECopyrightYear": 2021, + "O3DEBuildNumber": 0, + "external_subdirectories": [ + "Gems/TestGem2" + ], + "projects": [ + ], + "templates": [ + "Templates/MinimalProject" + ] +} +''' + + +@pytest.fixture(scope='class') +def init_engine_json_data(request): + class EngineJsonData: + def __init__(self): + self.data = json.loads(TEST_ENGINE_JSON_PAYLOAD) + request.cls.engine_json = EngineJsonData() + +@pytest.mark.usefixtures('init_engine_json_data') +class TestEditEngineProperties: + @pytest.mark.parametrize("engine_path, engine_name, engine_new_name, engine_version, expected_result", [ + pytest.param(pathlib.PurePath('D:/o3de'), None, 'o3de-install', '1.0.0.0', 0), + pytest.param(None, 'o3de-install', 'o3de-sdk', '1.0.0.1', 0), + pytest.param(None, 'o3de-sdk', None, '2.0.0.0', 0), + ] + ) + def test_edit_engine_properties(self, engine_path, engine_name, engine_new_name, engine_version, expected_result): + + def get_engine_json_data(engine_path: pathlib.Path) -> dict: + return self.engine_json.data + + def get_engine_path(engine_name: str) -> pathlib.Path: + return pathlib.Path('D:/o3de') + + def save_o3de_manifest(new_engine_data: dict, engine_path: pathlib.Path) -> bool: + self.engine_json.data = new_engine_data + return True + + with patch('o3de.manifest.get_engine_json_data', side_effect=get_engine_json_data) as get_engine_json_data_patch, \ + patch('o3de.manifest.save_o3de_manifest', side_effect=save_o3de_manifest) as save_o3de_manifest_patch, \ + patch('o3de.manifest.get_registered', side_effect=get_engine_path) as get_registered_patch: + result = engine_properties.edit_engine_props(engine_path, engine_name, engine_new_name, engine_version) + assert result == expected_result + if engine_new_name: + assert self.engine_json.data.get('engine_name', '') == engine_new_name + if engine_version: + assert self.engine_json.data.get('O3DEVersion', '') == engine_version diff --git a/scripts/o3de/tests/unit_test_gem_properties.py b/scripts/o3de/tests/unit_test_gem_properties.py new file mode 100644 index 0000000000..29d53fbee6 --- /dev/null +++ b/scripts/o3de/tests/unit_test_gem_properties.py @@ -0,0 +1,99 @@ +# +# Copyright (c) Contributors to the Open 3D Engine Project. +# For complete copyright and license terms please see the LICENSE at the root of this distribution. +# +# SPDX-License-Identifier: Apache-2.0 OR MIT +# +# + +import json +import pytest +import pathlib +from unittest.mock import patch + +from o3de import gem_properties + + +TEST_GEM_JSON_PAYLOAD = ''' +{ + "gem_name": "TestGem", + "display_name": "TestGem", + "license": "What license TestGem uses goes here: i.e. https://opensource.org/licenses/MIT", + "origin": "The primary repo for TestGem goes here: i.e. http://www.mydomain.com", + "type": "Code", + "summary": "A short description of TestGem.", + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "TestGem" + ], + "icon_path": "preview.png", + "requirements": "" +} +''' + + +@pytest.fixture(scope='class') +def init_gem_json_data(request): + class GemJsonData: + def __init__(self): + self.data = json.loads(TEST_GEM_JSON_PAYLOAD) + request.cls.gem_json = GemJsonData() + +@pytest.mark.usefixtures('init_gem_json_data') +class TestEditGemProperties: + @pytest.mark.parametrize("gem_path, gem_name, gem_new_name, gem_display, gem_origin,\ + gem_type, gem_summary, gem_icon, gem_requirements,\ + add_tags, remove_tags, replace_tags, expected_tags, expected_result", [ + pytest.param(pathlib.PurePath('D:/TestProject'), + None, 'TestGem2', 'New Gem Name', 'O3DE', 'Code', 'Gem that exercises Default Gem Template', + 'preview.png', '', + ['Physics', 'Rendering', 'Scripting'], None, None, ['TestGem', 'Physics', 'Rendering', 'Scripting'], + 0), + pytest.param(None, + 'TestGem2', None, 'New Gem Name', 'O3DE', 'Asset', 'Gem that exercises Default Gem Template', + 'preview.png', '', None, ['Physics'], None, ['TestGem', 'Rendering', 'Scripting'], 0), + pytest.param(None, + 'TestGem2', None, 'New Gem Name', 'O3DE', 'Tool', 'Gem that exercises Default Gem Template', + 'preview.png', '', None, None, ['Animation', 'TestGem'], ['Animation', 'TestGem'], 0) + ] + ) + def test_edit_gem_properties(self, gem_path, gem_name, gem_new_name, gem_display, gem_origin, + gem_type, gem_summary, gem_icon, gem_requirements, + add_tags, remove_tags, replace_tags, + expected_tags, expected_result): + + def get_gem_json_data(gem_path: pathlib.Path) -> dict: + return self.gem_json.data + + def get_gem_path(gem_name: str) -> pathlib.Path: + return pathlib.Path('D:/TestProject') + + def save_o3de_manifest(new_gem_data: dict, gem_path: pathlib.Path) -> bool: + self.gem_json.data = new_gem_data + return True + + with patch('o3de.manifest.get_gem_json_data', side_effect=get_gem_json_data) as get_gem_json_data_patch, \ + patch('o3de.manifest.save_o3de_manifest', side_effect=save_o3de_manifest) as save_o3de_manifest_patch, \ + patch('o3de.manifest.get_registered', side_effect=get_gem_path) as get_registered_patch: + result = gem_properties.edit_gem_props(gem_path, gem_name, gem_new_name, gem_display, gem_origin, + gem_type, gem_summary, gem_icon, gem_requirements, + add_tags, remove_tags, replace_tags) + assert result == expected_result + if gem_new_name: + assert self.gem_json.data.get('gem_name', '') == gem_new_name + if gem_display: + assert self.gem_json.data.get('display_name', '') == gem_display + if gem_origin: + assert self.gem_json.data.get('origin', '') == gem_origin + if gem_type: + assert self.gem_json.data.get('type', '') == gem_type + if gem_summary: + assert self.gem_json.data.get('summary', '') == gem_summary + if gem_icon: + assert self.gem_json.data.get('icon_path', '') == gem_icon + if gem_requirements: + assert self.gem_json.data.get('requirments', '') == gem_requirements + + assert set(self.gem_json.data.get('user_tags', [])) == set(expected_tags) diff --git a/scripts/o3de/tests/unit_test_project_properties.py b/scripts/o3de/tests/unit_test_project_properties.py index d85ed121c3..f72a4dfe4c 100644 --- a/scripts/o3de/tests/unit_test_project_properties.py +++ b/scripts/o3de/tests/unit_test_project_properties.py @@ -58,8 +58,9 @@ class TestEditProjectProperties: return None return self.project_json.data - def save_o3de_manifest(new_proj_data: dict, project_path) -> None: + def save_o3de_manifest(new_proj_data: dict, project_path) -> bool: self.project_json.data = new_proj_data + return True with patch('o3de.manifest.get_project_json_data', side_effect=get_project_json_data) as get_project_json_data_patch, \ patch('o3de.manifest.save_o3de_manifest', side_effect=save_o3de_manifest) as save_o3de_manifest_patch: From d38f17131e96c612cbd9dce29cda072af81ec4bc Mon Sep 17 00:00:00 2001 From: moraaar Date: Wed, 28 Jul 2021 13:14:56 +0100 Subject: [PATCH 073/160] Fixed cloth tangent generation (from 'stabilization/2106' @26c9853f) - The output vectors were not properly filled with zeros when they already had the expected size. - The tolerance was too large and was causing patches while computing tangents and bitangents. - The handedness was inverted to what is expected in the shader (which always inverts tangent's w). Signed-off-by: moraaar --- .../ClothComponentMesh/ClothComponentMesh.cpp | 2 +- .../Code/Source/System/TangentSpaceHelper.cpp | 20 ++++++++++++------- .../ClothConstraintsTest.cpp | 12 ++++++++--- 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/Gems/NvCloth/Code/Source/Components/ClothComponentMesh/ClothComponentMesh.cpp b/Gems/NvCloth/Code/Source/Components/ClothComponentMesh/ClothComponentMesh.cpp index 9381d98620..bcce080752 100644 --- a/Gems/NvCloth/Code/Source/Components/ClothComponentMesh/ClothComponentMesh.cpp +++ b/Gems/NvCloth/Code/Source/Components/ClothComponentMesh/ClothComponentMesh.cpp @@ -578,7 +578,7 @@ namespace NvCloth const AZ::Vector3& renderTangent = renderTangents[renderVertexIndex]; destTangentsBuffer[index].Set( renderTangent, - 1.0f); + -1.0f); // Shader function ConstructTBN inverts w to change bitangent sign, but the bitangents passed are already corrected, so passing -1.0 to counteract. } if (destBitangentsBuffer) diff --git a/Gems/NvCloth/Code/Source/System/TangentSpaceHelper.cpp b/Gems/NvCloth/Code/Source/System/TangentSpaceHelper.cpp index d7ebc8b371..3c47ad46fd 100644 --- a/Gems/NvCloth/Code/Source/System/TangentSpaceHelper.cpp +++ b/Gems/NvCloth/Code/Source/System/TangentSpaceHelper.cpp @@ -12,7 +12,7 @@ namespace NvCloth { namespace { - const float Tolerance = 0.0001f; + const float Tolerance = 1e-7f; } bool TangentSpaceHelper::CalculateNormals( @@ -34,7 +34,8 @@ namespace NvCloth const size_t vertexCount = vertices.size(); // Reset results - outNormals.resize(vertexCount, AZ::Vector3::CreateZero()); + outNormals.resize(vertexCount); + AZStd::fill(outNormals.begin(), outNormals.end(), AZ::Vector3::CreateZero()); // calculate the normals per triangle for (size_t i = 0; i < triangleCount; ++i) @@ -115,8 +116,10 @@ namespace NvCloth const size_t vertexCount = vertices.size(); // Reset results - outTangents.resize(vertexCount, AZ::Vector3::CreateZero()); - outBitangents.resize(vertexCount, AZ::Vector3::CreateZero()); + outTangents.resize(vertexCount); + outBitangents.resize(vertexCount); + AZStd::fill(outTangents.begin(), outTangents.end(), AZ::Vector3::CreateZero()); + AZStd::fill(outBitangents.begin(), outBitangents.end(), AZ::Vector3::CreateZero()); // calculate the base vectors per triangle for (size_t i = 0; i < triangleCount; ++i) @@ -193,9 +196,12 @@ namespace NvCloth const size_t vertexCount = vertices.size(); // Reset results - outTangents.resize(vertexCount, AZ::Vector3::CreateZero()); - outBitangents.resize(vertexCount, AZ::Vector3::CreateZero()); - outNormals.resize(vertexCount, AZ::Vector3::CreateZero()); + outTangents.resize(vertexCount); + outBitangents.resize(vertexCount); + outNormals.resize(vertexCount); + AZStd::fill(outTangents.begin(), outTangents.end(), AZ::Vector3::CreateZero()); + AZStd::fill(outBitangents.begin(), outBitangents.end(), AZ::Vector3::CreateZero()); + AZStd::fill(outNormals.begin(), outNormals.end(), AZ::Vector3::CreateZero()); // calculate the base vectors per triangle for (size_t i = 0; i < triangleCount; ++i) diff --git a/Gems/NvCloth/Code/Tests/Components/ClothComponentMesh/ClothConstraintsTest.cpp b/Gems/NvCloth/Code/Tests/Components/ClothComponentMesh/ClothConstraintsTest.cpp index 4beb03502a..c44d200fe3 100644 --- a/Gems/NvCloth/Code/Tests/Components/ClothComponentMesh/ClothConstraintsTest.cpp +++ b/Gems/NvCloth/Code/Tests/Components/ClothComponentMesh/ClothConstraintsTest.cpp @@ -125,6 +125,9 @@ namespace UnitTest const AZStd::vector& motionConstraints = clothConstraints->GetMotionConstraints(); EXPECT_TRUE(motionConstraints.size() == SimulationParticles.size()); + EXPECT_THAT(motionConstraints[0].GetAsVector3(), IsCloseTolerance(SimulationParticles[0].GetAsVector3(), Tolerance)); + EXPECT_THAT(motionConstraints[1].GetAsVector3(), IsCloseTolerance(SimulationParticles[1].GetAsVector3(), Tolerance)); + EXPECT_THAT(motionConstraints[2].GetAsVector3(), IsCloseTolerance(SimulationParticles[2].GetAsVector3(), Tolerance)); EXPECT_NEAR(motionConstraints[0].GetW(), 6.0f, Tolerance); EXPECT_NEAR(motionConstraints[1].GetW(), 0.0f, Tolerance); EXPECT_NEAR(motionConstraints[2].GetW(), 0.0f, Tolerance); @@ -278,6 +281,9 @@ namespace UnitTest const AZStd::vector& separationConstraints = clothConstraints->GetSeparationConstraints(); EXPECT_TRUE(motionConstraints.size() == newParticles.size()); + EXPECT_THAT(motionConstraints[0].GetAsVector3(), IsCloseTolerance(newParticles[0].GetAsVector3(), Tolerance)); + EXPECT_THAT(motionConstraints[1].GetAsVector3(), IsCloseTolerance(newParticles[1].GetAsVector3(), Tolerance)); + EXPECT_THAT(motionConstraints[2].GetAsVector3(), IsCloseTolerance(newParticles[2].GetAsVector3(), Tolerance)); EXPECT_NEAR(motionConstraints[0].GetW(), 3.0f, Tolerance); EXPECT_NEAR(motionConstraints[1].GetW(), 1.5f, Tolerance); EXPECT_NEAR(motionConstraints[2].GetW(), 0.0f, Tolerance); @@ -286,8 +292,8 @@ namespace UnitTest EXPECT_NEAR(separationConstraints[0].GetW(), 3.0f, Tolerance); EXPECT_NEAR(separationConstraints[1].GetW(), 1.5f, Tolerance); EXPECT_NEAR(separationConstraints[2].GetW(), 0.3f, Tolerance); - EXPECT_THAT(separationConstraints[0].GetAsVector3(), IsCloseTolerance(AZ::Vector3(-3.03902f, 2.80752f, 3.80752f), Tolerance)); - EXPECT_THAT(separationConstraints[1].GetAsVector3(), IsCloseTolerance(AZ::Vector3(-1.41659f, 0.651243f, -0.348757f), Tolerance)); - EXPECT_THAT(separationConstraints[2].GetAsVector3(), IsCloseTolerance(AZ::Vector3(6.15313f, -0.876132f, 0.123868f), Tolerance)); + EXPECT_THAT(separationConstraints[0].GetAsVector3(), IsCloseTolerance(AZ::Vector3(0.0f, 3.53553f, 4.53553f), Tolerance)); + EXPECT_THAT(separationConstraints[1].GetAsVector3(), IsCloseTolerance(AZ::Vector3(0.0f, 2.06066f, 1.06066f), Tolerance)); + EXPECT_THAT(separationConstraints[2].GetAsVector3(), IsCloseTolerance(AZ::Vector3(1.0f, -3.74767f, -2.74767f), Tolerance)); } } // namespace UnitTest From fd07f907bc8fabfc6ef7b2a9ffd562c474bd36e9 Mon Sep 17 00:00:00 2001 From: ibtehajn <81370835+ibtehajn@users.noreply.github.com> Date: Wed, 28 Jul 2021 13:22:24 +0100 Subject: [PATCH 074/160] Implement axis locking options for rigid bodies Linear and angular motion of rigid bodies can now be restricted along specific world-space axes. Signed-off-by: Ibtehaj Nadeem <81370835+ibtehajn@users.noreply.github.com> --- .../Configuration/RigidBodyConfiguration.cpp | 6 +++ .../Configuration/RigidBodyConfiguration.h | 10 ++++ .../Code/Source/EditorRigidBodyComponent.cpp | 27 ++++++++++ Gems/PhysX/Code/Source/Utils.cpp | 8 +++ Gems/PhysX/Code/Tests/PhysXSpecificTest.cpp | 54 +++++++++++++++++++ 5 files changed, 105 insertions(+) diff --git a/Code/Framework/AzFramework/AzFramework/Physics/Configuration/RigidBodyConfiguration.cpp b/Code/Framework/AzFramework/AzFramework/Physics/Configuration/RigidBodyConfiguration.cpp index a61f6a4845..cfea76f1d7 100644 --- a/Code/Framework/AzFramework/AzFramework/Physics/Configuration/RigidBodyConfiguration.cpp +++ b/Code/Framework/AzFramework/AzFramework/Physics/Configuration/RigidBodyConfiguration.cpp @@ -123,6 +123,12 @@ namespace AzPhysics ->Field("Kinematic", &RigidBodyConfiguration::m_kinematic) ->Field("CCD Enabled", &RigidBodyConfiguration::m_ccdEnabled) ->Field("Compute Mass", &RigidBodyConfiguration::m_computeMass) + ->Field("Lock Linear X", &RigidBodyConfiguration::m_lockLinearX) + ->Field("Lock Linear Y", &RigidBodyConfiguration::m_lockLinearY) + ->Field("Lock Linear Z", &RigidBodyConfiguration::m_lockLinearZ) + ->Field("Lock Angular X", &RigidBodyConfiguration::m_lockAngularX) + ->Field("Lock Angular Y", &RigidBodyConfiguration::m_lockAngularY) + ->Field("Lock Angular Z", &RigidBodyConfiguration::m_lockAngularZ) ->Field("Mass", &RigidBodyConfiguration::m_mass) ->Field("Compute COM", &RigidBodyConfiguration::m_computeCenterOfMass) ->Field("Centre of mass offset", &RigidBodyConfiguration::m_centerOfMassOffset) diff --git a/Code/Framework/AzFramework/AzFramework/Physics/Configuration/RigidBodyConfiguration.h b/Code/Framework/AzFramework/AzFramework/Physics/Configuration/RigidBodyConfiguration.h index 59829e740c..46f2620938 100644 --- a/Code/Framework/AzFramework/AzFramework/Physics/Configuration/RigidBodyConfiguration.h +++ b/Code/Framework/AzFramework/AzFramework/Physics/Configuration/RigidBodyConfiguration.h @@ -62,6 +62,16 @@ namespace AzPhysics bool m_computeInertiaTensor = true; bool m_computeMass = true; + //! Flags to restrict motion along specific world-space axes. + bool m_lockLinearX = false; + bool m_lockLinearY = false; + bool m_lockLinearZ = false; + + //! Flags to restrict rotation around specific world-space axes. + bool m_lockAngularX = false; + bool m_lockAngularY = false; + bool m_lockAngularZ = false; + //! If set, non-simulated shapes will also be included in the mass properties calculation. bool m_includeAllShapesInMassCalculation = false; diff --git a/Gems/PhysX/Code/Source/EditorRigidBodyComponent.cpp b/Gems/PhysX/Code/Source/EditorRigidBodyComponent.cpp index d27874f030..c94cc46ba4 100644 --- a/Gems/PhysX/Code/Source/EditorRigidBodyComponent.cpp +++ b/Gems/PhysX/Code/Source/EditorRigidBodyComponent.cpp @@ -156,6 +156,33 @@ namespace PhysX ->DataElement(AZ::Edit::UIHandlers::Default, &AzPhysics::RigidBodyConfiguration::m_kinematic, "Kinematic", "Rigid body is kinematic") ->Attribute(AZ::Edit::Attributes::Visibility, &AzPhysics::RigidBodyConfiguration::GetKinematicVisibility) + + // Linear axis locking properties + ->ClassElement(AZ::Edit::ClassElements::Group, "Linear Axis Locking") + ->Attribute(AZ::Edit::Attributes::AutoExpand, false) + ->DataElement( + AZ::Edit::UIHandlers::Default, &AzPhysics::RigidBodyConfiguration::m_lockLinearX, "Lock X", + "Lock linear momentum in X direction") + ->DataElement( + AZ::Edit::UIHandlers::Default, &AzPhysics::RigidBodyConfiguration::m_lockLinearY, "Lock Y", + "Lock linear momentum in Y direction") + ->DataElement( + AZ::Edit::UIHandlers::Default, &AzPhysics::RigidBodyConfiguration::m_lockLinearZ, "Lock Z", + "Lock linear momentum in Z direction") + + // Angular axis locking properties + ->ClassElement(AZ::Edit::ClassElements::Group, "Angular Axis Locking") + ->Attribute(AZ::Edit::Attributes::AutoExpand, false) + ->DataElement( + AZ::Edit::UIHandlers::Default, &AzPhysics::RigidBodyConfiguration::m_lockAngularX, "Lock X", + "Lock angular momentum in X direction") + ->DataElement( + AZ::Edit::UIHandlers::Default, &AzPhysics::RigidBodyConfiguration::m_lockAngularY, "Lock Y", + "Lock angular momentum in Y direction") + ->DataElement( + AZ::Edit::UIHandlers::Default, &AzPhysics::RigidBodyConfiguration::m_lockAngularZ, "Lock Z", + "Lock angular momentum in Z direction") + ->ClassElement(AZ::Edit::ClassElements::Group, "Continuous Collision Detection") ->Attribute(AZ::Edit::Attributes::AutoExpand, true) ->Attribute(AZ::Edit::Attributes::Visibility, &AzPhysics::RigidBodyConfiguration::GetCCDVisibility) diff --git a/Gems/PhysX/Code/Source/Utils.cpp b/Gems/PhysX/Code/Source/Utils.cpp index 4e5695e3c6..0b7ab9436b 100644 --- a/Gems/PhysX/Code/Source/Utils.cpp +++ b/Gems/PhysX/Code/Source/Utils.cpp @@ -1466,6 +1466,14 @@ namespace PhysX rigidDynamic->setRigidBodyFlag(physx::PxRigidBodyFlag::eKINEMATIC, configuration.m_kinematic); rigidDynamic->setMaxAngularVelocity(configuration.m_maxAngularVelocity); + // Set axis locks. + rigidDynamic->setRigidDynamicLockFlag(physx::PxRigidDynamicLockFlag::eLOCK_LINEAR_X, configuration.m_lockLinearX); + rigidDynamic->setRigidDynamicLockFlag(physx::PxRigidDynamicLockFlag::eLOCK_LINEAR_Y, configuration.m_lockLinearY); + rigidDynamic->setRigidDynamicLockFlag(physx::PxRigidDynamicLockFlag::eLOCK_LINEAR_Z, configuration.m_lockLinearZ); + rigidDynamic->setRigidDynamicLockFlag(physx::PxRigidDynamicLockFlag::eLOCK_ANGULAR_X, configuration.m_lockAngularX); + rigidDynamic->setRigidDynamicLockFlag(physx::PxRigidDynamicLockFlag::eLOCK_ANGULAR_Y, configuration.m_lockAngularY); + rigidDynamic->setRigidDynamicLockFlag(physx::PxRigidDynamicLockFlag::eLOCK_ANGULAR_Z, configuration.m_lockAngularZ); + return rigidDynamic; } diff --git a/Gems/PhysX/Code/Tests/PhysXSpecificTest.cpp b/Gems/PhysX/Code/Tests/PhysXSpecificTest.cpp index 770e47d477..76ee035b70 100644 --- a/Gems/PhysX/Code/Tests/PhysXSpecificTest.cpp +++ b/Gems/PhysX/Code/Tests/PhysXSpecificTest.cpp @@ -1102,6 +1102,60 @@ namespace PhysX SanityCheckValidFrustumParams(points.value(), validHeight, validBottomRadius, validTopRadius, validSubdivisions); } + TEST_F(PhysXSpecificTest, RigidBody_RigidBodyWithAxisLockFlagsCreated_InternalPhysXFlagsSetAccordingly) + { + // Helper function wrapping creation logic + auto CreateRigidBody = [this](bool linearX, bool linearY, bool linearZ, bool angularX, bool angularY, bool angularZ) -> AzPhysics::RigidBody* + { + AzPhysics::RigidBodyConfiguration rigidBodyConfig; + + rigidBodyConfig.m_lockLinearX = linearX; + rigidBodyConfig.m_lockLinearY = linearY; + rigidBodyConfig.m_lockLinearZ = linearZ; + + rigidBodyConfig.m_lockAngularX = angularX; + rigidBodyConfig.m_lockAngularY = angularY; + rigidBodyConfig.m_lockAngularZ = angularZ; + + if (auto* sceneInterface = AZ::Interface::Get()) + { + AzPhysics::SimulatedBodyHandle simBodyHandle = sceneInterface->AddSimulatedBody(m_testSceneHandle, &rigidBodyConfig); + return azdynamic_cast(sceneInterface->GetSimulatedBodyFromHandle(m_testSceneHandle, simBodyHandle)); + } + + return nullptr; + }; + + auto RemoveRigidBody = [this](AzPhysics::RigidBody*& rigidBody) + { + auto* sceneInterface = AZ::Interface::Get(); + if (rigidBody && sceneInterface) + { + sceneInterface->RemoveSimulatedBody(rigidBody->m_sceneOwner, rigidBody->m_bodyHandle); + } + rigidBody = nullptr; + }; + + auto TestLockFlags = [&CreateRigidBody, &RemoveRigidBody](bool linearX, bool linearY, bool linearZ, + bool angularX, bool angularY, bool angularZ, + physx::PxRigidDynamicLockFlags expectedFlags) + { + auto* rigidBody = CreateRigidBody(linearX, linearY, linearZ, angularX, angularY, angularZ); + ASSERT_TRUE(rigidBody != nullptr); + + physx::PxRigidDynamic* pxRigidBody = static_cast(rigidBody->GetNativePointer()); + EXPECT_EQ(pxRigidBody->getRigidDynamicLockFlags(), expectedFlags); + + RemoveRigidBody(rigidBody); + }; + + TestLockFlags(false, false, false, false, false, false, physx::PxRigidDynamicLockFlags(0)); + TestLockFlags(true, false, false, false, false, false, physx::PxRigidDynamicLockFlags(physx::PxRigidDynamicLockFlag::eLOCK_LINEAR_X)); + TestLockFlags(false, false, false, false, true, false, physx::PxRigidDynamicLockFlags(physx::PxRigidDynamicLockFlag::eLOCK_ANGULAR_Y)); + TestLockFlags(false, true, false, false, false, true, + physx::PxRigidDynamicLockFlags(physx::PxRigidDynamicLockFlag::eLOCK_LINEAR_Y | physx::PxRigidDynamicLockFlag::eLOCK_ANGULAR_Z)); + } + TEST_F(PhysXSpecificTest, RigidBody_RigidBodyWithSimulatedFlagsHitsPlane_OnlySimulatedShapeCollidesWithPlane) { // Helper function wrapping creation logic From 16869d56f32316b8bdaa157e53de39fd68fcc6fa Mon Sep 17 00:00:00 2001 From: Ibtehaj Nadeem <81370835+ibtehajn@users.noreply.github.com> Date: Wed, 28 Jul 2021 14:09:26 +0100 Subject: [PATCH 075/160] Use regular comment The Doxygen comment would only apply to the first field in each group. Signed-off-by: Ibtehaj Nadeem <81370835+ibtehajn@users.noreply.github.com> --- .../Physics/Configuration/RigidBodyConfiguration.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Code/Framework/AzFramework/AzFramework/Physics/Configuration/RigidBodyConfiguration.h b/Code/Framework/AzFramework/AzFramework/Physics/Configuration/RigidBodyConfiguration.h index 46f2620938..51dcce842d 100644 --- a/Code/Framework/AzFramework/AzFramework/Physics/Configuration/RigidBodyConfiguration.h +++ b/Code/Framework/AzFramework/AzFramework/Physics/Configuration/RigidBodyConfiguration.h @@ -62,12 +62,12 @@ namespace AzPhysics bool m_computeInertiaTensor = true; bool m_computeMass = true; - //! Flags to restrict motion along specific world-space axes. + // Flags to restrict motion along specific world-space axes. bool m_lockLinearX = false; bool m_lockLinearY = false; bool m_lockLinearZ = false; - //! Flags to restrict rotation around specific world-space axes. + // Flags to restrict rotation around specific world-space axes. bool m_lockAngularX = false; bool m_lockAngularY = false; bool m_lockAngularZ = false; From a7b613d388cfdc365fcd7112b4aeb70246d83560 Mon Sep 17 00:00:00 2001 From: Jakub Wlodek Date: Wed, 28 Jul 2021 11:56:46 -0400 Subject: [PATCH 076/160] Fixing typos in comments in AffineParts.h file (#2407) Signed-off-by: jwlodek --- Code/Editor/Util/AffineParts.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Code/Editor/Util/AffineParts.h b/Code/Editor/Util/AffineParts.h index cb2c609ecd..a2e3d2c79b 100644 --- a/Code/Editor/Util/AffineParts.h +++ b/Code/Editor/Util/AffineParts.h @@ -20,11 +20,11 @@ struct AffineParts Vec3 scale; //!< Stretch factors. float fDet; //!< Sign of determinant. - /** Decompose matrix to its affnie parts. + /** Decompose matrix to its affine parts. */ void Decompose(const Matrix34& mat); - /** Decompose matrix to its affnie parts. + /** Decompose matrix to its affine parts. Assume there`s no stretch rotation. */ void SpectralDecompose(const Matrix34& mat); From 433aec4f3407dffb9583b7c7bb8550d789252d96 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Wed, 28 Jul 2021 09:25:31 -0700 Subject: [PATCH 077/160] Disabling this since the fast checkup in VS doesnt solve what this was hoping to solve, we need to emit and add as dependencies all the includes involved in autogen (#2383) Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Framework/AzAutoGen/AzAutoGen.props | 7 ------- cmake/LyAutoGen.cmake | 1 - 2 files changed, 8 deletions(-) delete mode 100644 Code/Framework/AzAutoGen/AzAutoGen.props diff --git a/Code/Framework/AzAutoGen/AzAutoGen.props b/Code/Framework/AzAutoGen/AzAutoGen.props deleted file mode 100644 index 2f809d03a6..0000000000 --- a/Code/Framework/AzAutoGen/AzAutoGen.props +++ /dev/null @@ -1,7 +0,0 @@ - - - - - True - - diff --git a/cmake/LyAutoGen.cmake b/cmake/LyAutoGen.cmake index a1357e15b4..64cb73a453 100644 --- a/cmake/LyAutoGen.cmake +++ b/cmake/LyAutoGen.cmake @@ -40,7 +40,6 @@ function(ly_add_autogen) ) set_target_properties(${ly_add_autogen_NAME} PROPERTIES AUTOGEN_INPUT_FILES "${AZCG_INPUTFILES}") set_target_properties(${ly_add_autogen_NAME} PROPERTIES AUTOGEN_OUTPUT_FILES "${AUTOGEN_OUTPUTS}") - set_target_properties(${ly_add_autogen_NAME} PROPERTIES VS_USER_PROPS "${LY_ROOT_FOLDER}/Code/Framework/AzAutoGen/AzAutoGen.props") target_sources(${ly_add_autogen_NAME} PRIVATE ${AUTOGEN_OUTPUTS}) endif() From 0824bb462a44cf017827d0628a4f4694f1bf68a7 Mon Sep 17 00:00:00 2001 From: Ibtehaj Nadeem <81370835+ibtehajn@users.noreply.github.com> Date: Wed, 28 Jul 2021 16:33:02 +0100 Subject: [PATCH 078/160] Improve tooltip text Signed-off-by: Ibtehaj Nadeem <81370835+ibtehajn@users.noreply.github.com> --- Gems/PhysX/Code/Source/EditorRigidBodyComponent.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Gems/PhysX/Code/Source/EditorRigidBodyComponent.cpp b/Gems/PhysX/Code/Source/EditorRigidBodyComponent.cpp index c94cc46ba4..bd7c49a0a7 100644 --- a/Gems/PhysX/Code/Source/EditorRigidBodyComponent.cpp +++ b/Gems/PhysX/Code/Source/EditorRigidBodyComponent.cpp @@ -162,26 +162,26 @@ namespace PhysX ->Attribute(AZ::Edit::Attributes::AutoExpand, false) ->DataElement( AZ::Edit::UIHandlers::Default, &AzPhysics::RigidBodyConfiguration::m_lockLinearX, "Lock X", - "Lock linear momentum in X direction") + "Lock motion along X direction") ->DataElement( AZ::Edit::UIHandlers::Default, &AzPhysics::RigidBodyConfiguration::m_lockLinearY, "Lock Y", - "Lock linear momentum in Y direction") + "Lock motion along Y direction") ->DataElement( AZ::Edit::UIHandlers::Default, &AzPhysics::RigidBodyConfiguration::m_lockLinearZ, "Lock Z", - "Lock linear momentum in Z direction") + "Lock motion along Z direction") // Angular axis locking properties ->ClassElement(AZ::Edit::ClassElements::Group, "Angular Axis Locking") ->Attribute(AZ::Edit::Attributes::AutoExpand, false) ->DataElement( AZ::Edit::UIHandlers::Default, &AzPhysics::RigidBodyConfiguration::m_lockAngularX, "Lock X", - "Lock angular momentum in X direction") + "Lock rotation around X direction") ->DataElement( AZ::Edit::UIHandlers::Default, &AzPhysics::RigidBodyConfiguration::m_lockAngularY, "Lock Y", - "Lock angular momentum in Y direction") + "Lock rotation around Y direction") ->DataElement( AZ::Edit::UIHandlers::Default, &AzPhysics::RigidBodyConfiguration::m_lockAngularZ, "Lock Z", - "Lock angular momentum in Z direction") + "Lock rotation around Z direction") ->ClassElement(AZ::Edit::ClassElements::Group, "Continuous Collision Detection") ->Attribute(AZ::Edit::Attributes::AutoExpand, true) From db8f78890f686c6549ad1771cd5863d4313158a0 Mon Sep 17 00:00:00 2001 From: Jacob Hilliard <64656371+jcbhl@users.noreply.github.com> Date: Wed, 28 Jul 2021 09:35:02 -0700 Subject: [PATCH 079/160] [ATOM-16017] Implement frame time histogram in visualizer (#2378) * Histogram: Basic working graph of frame times Signed-off-by: Jacob Hilliard * Histogram: Improve usability Implements horizontal frame limit lines, limit-based coloring, and a viewport indicator. Signed-off-by: Jacob Hilliard * Histogram: Implement interactions Signed-off-by: Jacob Hilliard --- .../Include/Atom/Utils/ImGuiCpuProfiler.h | 7 +- .../Include/Atom/Utils/ImGuiCpuProfiler.inl | 107 ++++++++++++++++-- 2 files changed, 104 insertions(+), 10 deletions(-) diff --git a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.h b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.h index c0ee4f8e02..66be0b9137 100644 --- a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.h +++ b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.h @@ -75,6 +75,8 @@ namespace AZ private: static constexpr float RowHeight = 50.0; static constexpr int DefaultFramesToCollect = 50; + static constexpr float MediumFrameTimeLimit = 16.6; // 60 fps + static constexpr float HighFrameTimeLimit = 33.3; // 30 fps // Draw the shared header between the two windows void DrawCommonHeader(); @@ -127,8 +129,11 @@ namespace AZ // Draw the ruler with frame time labels void DrawRuler(); + // Draw the frame time histogram + void DrawFrameTimeHistogram(); + // Converts raw ticks to a pixel value suitable to give to ImDrawList, handles window scrolling - float ConvertTickToPixelSpace(AZStd::sys_time_t tick) const; + float ConvertTickToPixelSpace(AZStd::sys_time_t tick, AZStd::sys_time_t leftBound, AZStd::sys_time_t rightBound) const; AZStd::sys_time_t GetViewportTickWidth() const; diff --git a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl index b59747421e..735dace1c7 100644 --- a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl +++ b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl @@ -280,7 +280,7 @@ namespace AZ { ImGui::Columns(3, "Options", true); ImGui::Text("Frames To Collect:"); - ImGui::SliderInt("", &m_framesToCollect, 10, 100, "%d", ImGuiSliderFlags_AlwaysClamp | ImGuiSliderFlags_Logarithmic); + ImGui::SliderInt("", &m_framesToCollect, 10, 10000, "%d", ImGuiSliderFlags_AlwaysClamp | ImGuiSliderFlags_Logarithmic); ImGui::NextColumn(); @@ -295,6 +295,13 @@ namespace AZ "Hold the right mouse button to move around. Zoom by scrolling the mouse wheel while holding ."); } + ImGui::Columns(1, "FrameTimeColumn", true); + + if (ImGui::BeginChild("FrameTimeHistogram", { 0, 50 }, true, ImGuiWindowFlags_NoScrollbar)) + { + DrawFrameTimeHistogram(); + } + ImGui::EndChild(); ImGui::Columns(1, "RulerColumn", true); @@ -519,8 +526,8 @@ namespace AZ ImDrawList* drawList = ImGui::GetWindowDrawList(); - const float startPixel = ConvertTickToPixelSpace(block.m_startTick); - const float endPixel = ConvertTickToPixelSpace(block.m_endTick); + const float startPixel = ConvertTickToPixelSpace(block.m_startTick, m_viewportStartTick, m_viewportEndTick); + const float endPixel = ConvertTickToPixelSpace(block.m_endTick, m_viewportStartTick, m_viewportEndTick); const ImVec2 startPoint = { startPixel, wy + targetRow * RowHeight }; const ImVec2 endPoint = { endPixel, wy + targetRow * RowHeight + 40 }; @@ -656,7 +663,7 @@ namespace AZ while (endTickItr != m_frameEndTicks.end() && *endTickItr < m_viewportEndTick) { - const float horizontalPixel = ConvertTickToPixelSpace(*endTickItr); + const float horizontalPixel = ConvertTickToPixelSpace(*endTickItr, m_viewportStartTick, m_viewportEndTick); drawList->AddLine({ horizontalPixel, wy }, { horizontalPixel, wy + windowHeight }, red); ++endTickItr; } @@ -684,8 +691,8 @@ namespace AZ break; } - const float lastFrameBoundaryPixel = ConvertTickToPixelSpace(lastFrameBoundaryTick); - const float nextFrameBoundaryPixel = ConvertTickToPixelSpace(nextFrameBoundaryTick); + const float lastFrameBoundaryPixel = ConvertTickToPixelSpace(lastFrameBoundaryTick, m_viewportStartTick, m_viewportEndTick); + const float nextFrameBoundaryPixel = ConvertTickToPixelSpace(nextFrameBoundaryTick, m_viewportStartTick, m_viewportEndTick); const AZStd::string label = AZStd::string::format("%.2f ms", CpuProfilerImGuiHelper::TicksToMs(nextFrameBoundaryTick - lastFrameBoundaryTick)); @@ -738,16 +745,98 @@ namespace AZ } } + inline void ImGuiCpuProfiler::DrawFrameTimeHistogram() + { + ImDrawList* drawList = ImGui::GetWindowDrawList(); + const auto [wx, wy] = ImGui::GetWindowPos(); + const ImU32 orange = ImGui::GetColorU32({ 1, .7, 0, 1 }); + const ImU32 red = ImGui::GetColorU32({ 1, 0, 0, 1 }); + + const AZStd::sys_time_t ticksPerSecond = AZStd::GetTimeTicksPerSecond(); + const AZStd::sys_time_t viewportCenter = m_viewportEndTick - (m_viewportEndTick - m_viewportStartTick) / 2; + const AZStd::sys_time_t leftHistogramBound = viewportCenter - ticksPerSecond; + const AZStd::sys_time_t rightHistogramBound = viewportCenter + ticksPerSecond; + + // Draw frame limit lines + drawList->AddLine( + { wx, wy + ImGui::GetWindowHeight() - MediumFrameTimeLimit }, + { wx + ImGui::GetWindowWidth(), wy + ImGui::GetWindowHeight() - MediumFrameTimeLimit }, + orange); + + drawList->AddLine( + { wx, wy + ImGui::GetWindowHeight() - HighFrameTimeLimit }, + { wx + ImGui::GetWindowWidth(), wy + ImGui::GetWindowHeight() - HighFrameTimeLimit }, + red); + + + // Draw viewport bound rectangle + const float leftViewportPixel = ConvertTickToPixelSpace(m_viewportStartTick, leftHistogramBound, rightHistogramBound); + const float rightViewportPixel = ConvertTickToPixelSpace(m_viewportEndTick, leftHistogramBound, rightHistogramBound); + const ImVec2 topLeftPos = { leftViewportPixel, wy }; + const ImVec2 botRightPos = { rightViewportPixel, wy + ImGui::GetWindowHeight() }; + const ImU32 gray = ImGui::GetColorU32({ 1, 1, 1, .3 }); + drawList->AddRectFilled(topLeftPos, botRightPos, gray); + + // Find the first onscreen frame execution time + auto frameEndTickItr = AZStd::lower_bound(m_frameEndTicks.begin(), m_frameEndTicks.end(), leftHistogramBound); + if (frameEndTickItr != m_frameEndTicks.begin()) + { + --frameEndTickItr; + } + + // Since we only store the frame end ticks, we must calculate the execution times on the fly by comparing pairs of elements. + AZStd::sys_time_t lastFrameEndTick = *frameEndTickItr; + while (*frameEndTickItr < rightHistogramBound && ++frameEndTickItr != m_frameEndTicks.end()) + { + const AZStd::sys_time_t frameEndTick = *frameEndTickItr; + + const float framePixelPos = ConvertTickToPixelSpace(frameEndTick, leftHistogramBound, rightHistogramBound); + const float frameTimeMs = CpuProfilerImGuiHelper::TicksToMs(frameEndTick - lastFrameEndTick); + + const ImVec2 lineBottom = { framePixelPos, ImGui::GetWindowHeight() + wy }; + const ImVec2 lineTop = { framePixelPos, ImGui::GetWindowHeight() + wy - frameTimeMs }; + + ImU32 lineColor = ImGui::GetColorU32({ .3, .3, .3, 1 }); // Gray + if (frameTimeMs > HighFrameTimeLimit) + { + lineColor = ImGui::GetColorU32({1, 0, 0, 1}); // Red + } + else if (frameTimeMs > MediumFrameTimeLimit) + { + lineColor = ImGui::GetColorU32({1, .7, 0, 1}); // Orange + } + + drawList->AddLine(lineBottom, lineTop, lineColor, 3.0); + + lastFrameEndTick = frameEndTick; + } + + // Handle input + ImGui::InvisibleButton("HistogramInputCapture", { ImGui::GetWindowWidth(), ImGui::GetWindowHeight() }); + ImGuiIO& io = ImGui::GetIO(); + if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) + { + const float mousePixelX = io.MousePos.x; + const float percentWindow = (mousePixelX - wx) / ImGui::GetWindowWidth(); + const AZStd::sys_time_t newViewportCenterTick = leftHistogramBound + + aznumeric_cast((rightHistogramBound - leftHistogramBound) * percentWindow); + + const AZStd::sys_time_t viewportWidth = GetViewportTickWidth(); + m_viewportEndTick = newViewportCenterTick + viewportWidth / 2; + m_viewportStartTick = newViewportCenterTick - viewportWidth / 2; + } + } + inline AZStd::sys_time_t ImGuiCpuProfiler::GetViewportTickWidth() const { return m_viewportEndTick - m_viewportStartTick; } - inline float ImGuiCpuProfiler::ConvertTickToPixelSpace(AZStd::sys_time_t tick) const + inline float ImGuiCpuProfiler::ConvertTickToPixelSpace(AZStd::sys_time_t tick, AZStd::sys_time_t leftBound, AZStd::sys_time_t rightBound) const { const float wx = ImGui::GetWindowPos().x; - const float tickSpaceShifted = aznumeric_cast(tick - m_viewportStartTick); // This will be close to zero, so FP inaccuracy should not be too bad - const float tickSpaceNormalized = tickSpaceShifted / GetViewportTickWidth(); + const float tickSpaceShifted = aznumeric_cast(tick - leftBound); // This will be close to zero, so FP inaccuracy should not be too bad + const float tickSpaceNormalized = tickSpaceShifted / (rightBound - leftBound); const float pixelSpace = tickSpaceNormalized * ImGui::GetWindowWidth() + wx; return pixelSpace; } From a7e414fafeb18834d5c930ae2eb225d8bd889d1c Mon Sep 17 00:00:00 2001 From: Ibtehaj Nadeem <81370835+ibtehajn@users.noreply.github.com> Date: Wed, 28 Jul 2021 17:58:31 +0100 Subject: [PATCH 080/160] Fix Linux compilation error in test code Signed-off-by: Ibtehaj Nadeem <81370835+ibtehajn@users.noreply.github.com> --- Gems/PhysX/Code/Tests/PhysXSpecificTest.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Gems/PhysX/Code/Tests/PhysXSpecificTest.cpp b/Gems/PhysX/Code/Tests/PhysXSpecificTest.cpp index 76ee035b70..6e96db4db2 100644 --- a/Gems/PhysX/Code/Tests/PhysXSpecificTest.cpp +++ b/Gems/PhysX/Code/Tests/PhysXSpecificTest.cpp @@ -1144,7 +1144,9 @@ namespace PhysX ASSERT_TRUE(rigidBody != nullptr); physx::PxRigidDynamic* pxRigidBody = static_cast(rigidBody->GetNativePointer()); - EXPECT_EQ(pxRigidBody->getRigidDynamicLockFlags(), expectedFlags); + + // These values need to be cast to integral types to prevent a compilation error on somme platforms. + EXPECT_EQ(static_cast(pxRigidBody->getRigidDynamicLockFlags()), static_cast((expectedFlags))); RemoveRigidBody(rigidBody); }; From d5a496751ce06593e5704b15320e521ec84b4bc7 Mon Sep 17 00:00:00 2001 From: Jacob Hilliard Date: Tue, 13 Jul 2021 10:21:56 -0700 Subject: [PATCH 081/160] Visualizer: Implement region search + highlight Signed-off-by: Jacob Hilliard --- .../Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.h | 8 +++++--- .../Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl | 10 ++++++++-- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.h b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.h index 66be0b9137..4d22458b56 100644 --- a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.h +++ b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.h @@ -165,9 +165,11 @@ namespace AZ AZStd::vector m_frameEndTicks = { INT64_MIN }; // Main data structure for storing function statistics to be shown in the popup windows. - // For now we default allocate for all regions on the first render frame and then use RegionStatistics.m_draw to determine - // if we should draw the window or not. FIXME(ATOM-15948) this should be changed once RegionStatistics gets heavier. - AZStd::unordered_map m_regionStatisticsMap; + // Uses the group name + region name as a key - just the region name does not suffice since there are collisions (ex. GarbageCollect) + AZStd::unordered_map m_regionStatisticsMap; + + // Filter for highlighting regions on the visualizer + ImGuiTextFilter m_regionHighlightFilter; }; } // namespace Render } // namespace AZ diff --git a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl index 735dace1c7..81fa440159 100644 --- a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl +++ b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl @@ -279,8 +279,8 @@ namespace AZ if (ImGui::BeginChild("Options and Statistics", { 0, 0 }, true)) { ImGui::Columns(3, "Options", true); - ImGui::Text("Frames To Collect:"); - ImGui::SliderInt("", &m_framesToCollect, 10, 10000, "%d", ImGuiSliderFlags_AlwaysClamp | ImGuiSliderFlags_Logarithmic); + ImGui::SliderInt("Saved Frames", &m_framesToCollect, 10, 10000, "%d", ImGuiSliderFlags_AlwaysClamp | ImGuiSliderFlags_Logarithmic); + m_regionHighlightFilter.Draw("Find Region"); ImGui::NextColumn(); @@ -522,6 +522,12 @@ namespace AZ inline void ImGuiCpuProfiler::DrawBlock(const TimeRegion& block, u64 targetRow) { + // Don't draw anything if the user is searching for regions and this block doesn't pass the filter + if (!m_regionHighlightFilter.PassFilter(block.m_groupRegionName->m_regionName)) + { + return; + } + float wy = ImGui::GetWindowPos().y - ImGui::GetScrollY(); ImDrawList* drawList = ImGui::GetWindowDrawList(); From 487fc631eca1dd23c83e77ad06eb898ecf567570 Mon Sep 17 00:00:00 2001 From: Jacob Hilliard Date: Mon, 12 Jul 2021 16:47:33 -0700 Subject: [PATCH 082/160] Visualizer: Tabular view of function statistics Current metrics are MTPC, max time, and invocations per frame. The invocations per frame is buggy if switching between samples but I don't know how to fix that in a context-agnostic way (editor vs ASV) - resetting works for now. Signed-off-by: Jacob Hilliard --- .../Include/Atom/Utils/ImGuiCpuProfiler.h | 43 +-- .../Include/Atom/Utils/ImGuiCpuProfiler.inl | 274 +++++++++--------- 2 files changed, 153 insertions(+), 164 deletions(-) diff --git a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.h b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.h index 4d22458b56..695ad7e332 100644 --- a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.h +++ b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.h @@ -31,28 +31,29 @@ namespace AZ AZStd::sys_time_t m_endTick = 0; }; - // Stores data about a region that is agreggated from all collected frames - // Data collection can be toggled on and off through m_record. - struct RegionStatistics + struct TableRow { - float CalcAverageTimeMs() const; void RecordRegion(const AZ::RHI::CachedTimeRegion& region); - - bool m_draw = false; - bool m_record = true; - u64 m_invocations = 0; - AZStd::sys_time_t m_totalTicks = 0; + double GetAverageInvocationsPerFrame() const; + + static u64 ms_frames; + + AZStd::string m_groupName; + AZStd::string m_regionName; + AZStd::sys_time_t m_maxTicks; + AZStd::sys_time_t m_runningAverageTicks; + u64 m_invocations; }; //! Visual profiler for Cpu statistics. //! It uses ImGui as the library for displaying the Attachments and Heaps. - //! It shows all heaps that are being used by the RHI and how the + //! It shows all heaps that are being used by the RHI and how the FIXME //! resources are allocated in each heap. class ImGuiCpuProfiler : SystemTickBus::Handler { // Region Name -> Array of ThreadRegion entries - using RegionEntryMap = AZStd::map>; + using RegionEntryMap = AZStd::map; // Group Name -> RegionEntryMap using GroupRegionMap = AZStd::map; @@ -81,12 +82,21 @@ namespace AZ // Draw the shared header between the two windows void DrawCommonHeader(); + // Draw the region statstics table in the order specified by the pointers in m_tableData + void DrawTable(); + + // Sort the table by a given column, rearranges the pointers in m_tableData + void SortTable(ImGuiTableSortSpecs* sortSpecs); + // ImGui filter used to filter TimedRegions. ImGuiTextFilter m_timedRegionFilter; - // Saves statistical view data organized by group name -> region name -> regions + // Saves statistical view data organized by group name -> region name -> row data GroupRegionMap m_groupRegionMap; + // Saves pointers to objects in m_groupRegionMap, order reflects table ordering + AZStd::vector m_tableData; + // Pause cpu profiling. The profiler will show the statistics of the last frame before pause bool m_paused = false; @@ -120,9 +130,6 @@ namespace AZ // Draw the "Thread XXXXX" label onto the viewport void DrawThreadLabel(u64 baseRow, AZStd::thread_id threadId); - // Draws all active function statistics windows - void DrawRegionStatistics(); - // Draw the vertical lines separating frames in the timeline void DrawFrameBoundaries(); @@ -164,12 +171,8 @@ namespace AZ // Tracks the frame boundaries AZStd::vector m_frameEndTicks = { INT64_MIN }; - // Main data structure for storing function statistics to be shown in the popup windows. - // Uses the group name + region name as a key - just the region name does not suffice since there are collisions (ex. GarbageCollect) - AZStd::unordered_map m_regionStatisticsMap; - // Filter for highlighting regions on the visualizer - ImGuiTextFilter m_regionHighlightFilter; + ImGuiTextFilter m_visualizerHighlightFilter; }; } // namespace Render } // namespace AZ diff --git a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl index 81fa440159..bb470f39e8 100644 --- a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl +++ b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl @@ -17,11 +17,16 @@ #include #include +#pragma optimize("", off) + +#include "../../../Gems/ImGui/External/ImGui/v1.82/imgui/imgui.h" namespace AZ { namespace Render { + inline u64 TableRow::ms_frames = 0; + namespace CpuProfilerImGuiHelper { // NOTE: Fix build error in case AZStd::thread_id is not of an arithmetic type, and instead a pointer @@ -134,6 +139,92 @@ namespace AZ } } + inline void ImGuiCpuProfiler::DrawTable() + { + const auto flags = + ImGuiTableFlags_Borders | ImGuiTableFlags_Sortable | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable; + if (ImGui::BeginTable("FunctionStatisticsTable", 5, flags)) + { + // Table header setup + ImGui::TableSetupColumn("Group"); + ImGui::TableSetupColumn("Region"); + ImGui::TableSetupColumn("MTPC (ms)"); + ImGui::TableSetupColumn("Max (ms)"); + ImGui::TableSetupColumn("Invocations/frame"); + ImGui::TableHeadersRow(); + ImGui::TableNextColumn(); + + ImGuiTableSortSpecs* sortSpecs = ImGui::TableGetSortSpecs(); + if (sortSpecs && sortSpecs->SpecsDirty) + { + SortTable(sortSpecs); + } + + // Draw all of the rows held in the GroupRegionMap + for (const auto* statistics : m_tableData) + { + if (!m_timedRegionFilter.PassFilter(statistics->m_groupName.c_str()) + && !m_timedRegionFilter.PassFilter(statistics->m_regionName.c_str())) + { + continue; + } + + ImGui::Text(statistics->m_groupName.c_str()); + ImGui::TableNextColumn(); + + ImGui::Text(statistics->m_regionName.c_str()); + ImGui::TableNextColumn(); + + ImGui::Text("%.2f", CpuProfilerImGuiHelper::TicksToMs(statistics->m_runningAverageTicks)); + ImGui::TableNextColumn(); + + ImGui::Text("%.2f", CpuProfilerImGuiHelper::TicksToMs(statistics->m_maxTicks)); + ImGui::TableNextColumn(); + + ImGui::Text("%.1f", statistics->GetAverageInvocationsPerFrame()); + ImGui::TableNextColumn(); + } + } + ImGui::EndTable(); + } + + inline void ImGuiCpuProfiler::SortTable(ImGuiTableSortSpecs* sortSpecs) + { + const bool ascending = sortSpecs->Specs->SortDirection == ImGuiSortDirection_Ascending; + const ImS16 columnToSort = sortSpecs->Specs->ColumnIndex; + + switch (columnToSort) + { + case (0): // Sort by group name + AZStd::sort(m_tableData.begin(), m_tableData.end(), [ascending](const TableRow* lhs, const TableRow* rhs){ + return ascending ? lhs->m_groupName < rhs->m_groupName : lhs->m_groupName > rhs->m_groupName; + }); + break; + case (1): // Sort by region name + AZStd::sort(m_tableData.begin(), m_tableData.end(),[ascending](const TableRow* lhs, const TableRow* rhs){ + return ascending ? lhs->m_regionName < rhs->m_regionName : lhs->m_regionName > rhs->m_regionName; + }); + break; + case (2): // Sort by average time + AZStd::sort(m_tableData.begin(), m_tableData.end(), [ascending](const TableRow* lhs, const TableRow* rhs){ + return ascending ? lhs->m_runningAverageTicks < rhs->m_runningAverageTicks + : lhs->m_runningAverageTicks > rhs->m_runningAverageTicks; + }); + break; + case (3): // Sort by max time + AZStd::sort(m_tableData.begin(), m_tableData.end(), [ascending](const TableRow* lhs, const TableRow* rhs){ + return ascending ? lhs->m_maxTicks < rhs->m_maxTicks : lhs->m_maxTicks > rhs->m_maxTicks; + }); + break; + case (4): // Sort by invocations + AZStd::sort(m_tableData.begin(), m_tableData.end(), [ascending](const TableRow* lhs, const TableRow* rhs){ + return ascending ? lhs->m_invocations < rhs->m_invocations : lhs->m_invocations > rhs->m_invocations; + }); + break; + } + sortSpecs->SpecsDirty = false; + } + inline void ImGuiCpuProfiler::DrawStatisticsView() { DrawCommonHeader(); @@ -156,62 +247,6 @@ namespace AZ ImGui::NextColumn(); }; - const auto DrawRegionHoverMarker = [this, &ShowTimeInMs](AZStd::vector& entries) - { - if (ImGui::IsItemHovered()) - { - ImGui::BeginTooltip(); - ImGui::PushTextWrapPos(ImGui::GetFontSize() * 60.0f); - - for (ThreadRegionEntry& entry : entries) - { - ImGui::Text(CpuProfilerImGuiHelper::TextThreadId(entry.m_threadId.m_id).c_str()); - - const AZStd::sys_time_t elapsed = entry.m_endTick - entry.m_startTick; - ShowTimeInMs(elapsed); - ImGui::Separator(); - } - - ImGui::PopTextWrapPos(); - ImGui::EndTooltip(); - } - }; - - const auto ShowRegionRow = - [ticksPerSecond, &DrawRegionHoverMarker, - &ShowTimeInMs](const char* regionLabel, AZStd::vector regions, AZStd::sys_time_t duration) - { - // Draw the region label - ImGui::Text(regionLabel); - ImGui::NextColumn(); - - // Draw the thread count label - AZStd::sys_time_t totalTime = 0; - AZStd::set threads; - for (ThreadRegionEntry& entry : regions) // Find the thread count and total execution time for all threads - { - threads.insert(entry.m_threadId); - totalTime += entry.m_endTick - entry.m_startTick; - } - const AZStd::string threadLabel = AZStd::string::format("Threads: %u", static_cast(threads.size())); - ImGui::Text(threadLabel.c_str()); - DrawRegionHoverMarker(regions); - ImGui::NextColumn(); - - // Draw the overall invocation count - const AZStd::string invocationLabel = AZStd::string::format("Total calls: %u", static_cast(regions.size())); - ImGui::Text(invocationLabel.c_str()); - DrawRegionHoverMarker(regions); - ImGui::NextColumn(); - - // Draw the time labels (max and then total) - const AZStd::string timeLabel = AZStd::string::format( - "%.2f ms max, %.2f ms total", CpuProfilerImGuiHelper::TicksToMs(duration), - CpuProfilerImGuiHelper::TicksToMs(totalTime)); - ImGui::Text(timeLabel.c_str()); - ImGui::NextColumn(); - }; - if (ImGui::BeginChild("Statistics View", { 0, 0 }, true)) { // Set column settings. @@ -229,44 +264,21 @@ namespace AZ ImGui::Separator(); ImGui::Columns(1, "view", false); - m_timedRegionFilter.Draw("TimedRegion Filter"); - - // Draw the timed regions - if (ImGui::BeginChild("TimedRegions")) + m_timedRegionFilter.Draw("Filter"); + ImGui::SameLine(); + if (ImGui::Button("Clear Filter")) { - for (auto& timeRegionMapEntry : m_groupRegionMap) - { - // Draw the regions - if (ImGui::TreeNodeEx(timeRegionMapEntry.first.c_str(), ImGuiTreeNodeFlags_DefaultOpen)) - { - ImGui::Columns(4, "view", false); - ImGui::SetColumnWidth(0, 400.0f); - ImGui::SetColumnWidth(1, 100.0f); - ImGui::SetColumnWidth(2, 150.0f); - ImGui::SetColumnWidth(3, 240.0f); - - for (auto& region : timeRegionMapEntry.second) - { - // Calculate the region with the longest execution time - AZStd::sys_time_t threadExecutionElapsed = 0; - for (ThreadRegionEntry& entry : region.second) - { - const AZStd::sys_time_t elapsed = entry.m_endTick - entry.m_startTick; - threadExecutionElapsed = AZStd::max(threadExecutionElapsed, elapsed); - } - - // Only draw the TimedRegion rows when it passes the filter - if (m_timedRegionFilter.PassFilter(region.first.c_str())) - { - ShowRegionRow(region.first.c_str(), region.second, threadExecutionElapsed); - } - } - ImGui::Columns(1, "view", false); - ImGui::TreePop(); - } - } - ImGui::EndChild(); + m_timedRegionFilter.Clear(); + } + ImGui::SameLine(); + if (ImGui::Button("Reset Table")) + { + m_tableData.clear(); + m_groupRegionMap.clear(); + TableRow::ms_frames = 0; } + + DrawTable(); } } @@ -280,7 +292,7 @@ namespace AZ { ImGui::Columns(3, "Options", true); ImGui::SliderInt("Saved Frames", &m_framesToCollect, 10, 10000, "%d", ImGuiSliderFlags_AlwaysClamp | ImGuiSliderFlags_Logarithmic); - m_regionHighlightFilter.Draw("Find Region"); + m_visualizerHighlightFilter.Draw("Find Region"); ImGui::NextColumn(); @@ -372,7 +384,6 @@ namespace AZ baseRow += maxDepth + 1; // Next draw loop should start one row down } - DrawRegionStatistics(); DrawFrameBoundaries(); // Draw an invisible button to capture inputs @@ -432,9 +443,6 @@ namespace AZ // view is only holding data from the last frame, the memory overhead is minimal and gives us a faster redraw // compared to if we needed to transform the visualizer's data into the statistical format every frame. - // Clear the statistical view's cached entries - m_groupRegionMap.clear(); - // Get the latest TimeRegionMap const RHI::CpuProfiler::TimeRegionMap& timeRegionMap = RHI::CpuProfiler::Get()->GetTimeRegionMap(); @@ -461,14 +469,15 @@ namespace AZ // Also update the statistical view's data const AZStd::string& groupName = region.m_groupRegionName->m_groupName; - m_groupRegionMap[groupName][regionName].push_back( - { threadId, region.m_startTick, region.m_endTick }); - // Update running statistics if we want to record this region's data - if (m_regionStatisticsMap[region.m_groupRegionName].m_record) + if (!m_groupRegionMap[groupName].contains(regionName)) { - m_regionStatisticsMap[region.m_groupRegionName].RecordRegion(region); + m_groupRegionMap[groupName][regionName].m_groupName = groupName; + m_groupRegionMap[groupName][regionName].m_regionName = regionName; + m_tableData.push_back(&m_groupRegionMap[groupName][regionName]); } + + m_groupRegionMap[groupName][regionName].RecordRegion(region); } } @@ -523,7 +532,7 @@ namespace AZ inline void ImGuiCpuProfiler::DrawBlock(const TimeRegion& block, u64 targetRow) { // Don't draw anything if the user is searching for regions and this block doesn't pass the filter - if (!m_regionHighlightFilter.PassFilter(block.m_groupRegionName->m_regionName)) + if (!m_visualizerHighlightFilter.PassFilter(block.m_groupRegionName->m_regionName)) { return; } @@ -573,13 +582,14 @@ namespace AZ // Tooltip and block highlighting if (ImGui::IsMouseHoveringRect(startPoint, endPoint) && ImGui::IsWindowHovered()) { - // Open function statistics map on click + // Go to the statistics view when a region is clicked if (ImGui::IsMouseClicked(ImGuiMouseButton_Left)) { - const GroupRegionName* key = block.m_groupRegionName; - m_regionStatisticsMap[key].m_draw = true; + m_enableVisualizer = false; + const auto newFilter = AZStd::string(block.m_groupRegionName->m_regionName); + m_timedRegionFilter = ImGuiTextFilter(newFilter.c_str()); + m_timedRegionFilter.Build(); } - // Hovering outline drawList->AddRect(startPoint, endPoint, ImGui::GetColorU32({ 1, 1, 1, 1 }), 0.0, 0, 1.5); @@ -631,31 +641,6 @@ namespace AZ ImGui::GetWindowDrawList()->AddText({ wx + 10, wy + baseRow * RowHeight + 5 }, IM_COL32_WHITE, threadIdText.c_str()); } - inline void ImGuiCpuProfiler::DrawRegionStatistics() - { - for (auto& [groupRegionName, stat] : m_regionStatisticsMap) - { - if (stat.m_draw) - { - ImGui::SetNextWindowSize({300, 340}, ImGuiCond_FirstUseEver); - ImGui::Begin(groupRegionName->m_regionName, &stat.m_draw, 0); - - if (ImGui::Button(stat.m_record ? "Pause" : "Resume")) - { - stat.m_record = !stat.m_record; - } - - ImGui::Text("Invocations: %llu", stat.m_invocations); - ImGui::Text("Average time: %.3f ms", stat.CalcAverageTimeMs()); - - ImGui::Separator(); - - ImGui::ColorPicker4("Region color", &m_regionColorMap[groupRegionName].x); - ImGui::End(); - } - } - } - inline void ImGuiCpuProfiler::DrawFrameBoundaries() { ImDrawList* drawList = ImGui::GetWindowDrawList(); @@ -857,25 +842,26 @@ namespace AZ else { m_frameEndTicks.push_back(AZStd::GetTimeNowTicks()); + TableRow::ms_frames++; } } - // ----- RegionStatistics implementation ----- - - inline float RegionStatistics::CalcAverageTimeMs() const + // ---- TableRow impl ---- + + inline void TableRow::RecordRegion(const AZ::RHI::CachedTimeRegion& region) { - if (m_invocations == 0) - { - return 0.0; - } - const double averageTicks = aznumeric_cast(m_totalTicks) / m_invocations; - return CpuProfilerImGuiHelper::TicksToMs(aznumeric_cast(averageTicks)); + m_invocations++; + const AZStd::sys_time_t deltaTime = AZStd::abs(region.m_endTick - region.m_startTick); + m_maxTicks = AZStd::max(m_maxTicks, deltaTime); + + // Standard running average algorithm + const auto newMean = m_runningAverageTicks + aznumeric_cast((deltaTime - m_runningAverageTicks) * 1.0 / m_invocations); + m_runningAverageTicks = newMean; } - inline void RegionStatistics::RecordRegion(const AZ::RHI::CachedTimeRegion& region) + inline double TableRow::GetAverageInvocationsPerFrame() const { - m_invocations++; - m_totalTicks += region.m_endTick - region.m_startTick; + return 1.0 * m_invocations / ms_frames; } } // namespace Render } // namespace AZ From bd00867fe624303c7f823e0c5551c6762efae858 Mon Sep 17 00:00:00 2001 From: Jacob Hilliard Date: Wed, 21 Jul 2021 11:57:23 -0700 Subject: [PATCH 083/160] Visualizer: Implement thread hovering tooltip Signed-off-by: Jacob Hilliard --- .../Include/Atom/Utils/ImGuiCpuProfiler.h | 12 ++++-- .../Include/Atom/Utils/ImGuiCpuProfiler.inl | 41 +++++++++++++++---- 2 files changed, 42 insertions(+), 11 deletions(-) diff --git a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.h b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.h index 695ad7e332..d21783a801 100644 --- a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.h +++ b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.h @@ -10,6 +10,7 @@ #include #include +#include #include #include @@ -33,16 +34,17 @@ namespace AZ struct TableRow { - void RecordRegion(const AZ::RHI::CachedTimeRegion& region); + void RecordRegion(const AZ::RHI::CachedTimeRegion& region, AZStd::thread_id threadId); double GetAverageInvocationsPerFrame() const; - - static u64 ms_frames; + AZStd::string TableRow::GetExecutingThreadsLabel() const; AZStd::string m_groupName; AZStd::string m_regionName; AZStd::sys_time_t m_maxTicks; AZStd::sys_time_t m_runningAverageTicks; u64 m_invocations; + + AZStd::set m_executingThreads; }; //! Visual profiler for Cpu statistics. @@ -52,6 +54,8 @@ namespace AZ class ImGuiCpuProfiler : SystemTickBus::Handler { + friend struct TableRow; + // Region Name -> Array of ThreadRegion entries using RegionEntryMap = AZStd::map; // Group Name -> RegionEntryMap @@ -79,6 +83,8 @@ namespace AZ static constexpr float MediumFrameTimeLimit = 16.6; // 60 fps static constexpr float HighFrameTimeLimit = 33.3; // 30 fps + static u64 ms_framesActive; + // Draw the shared header between the two windows void DrawCommonHeader(); diff --git a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl index bb470f39e8..124e48af13 100644 --- a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl +++ b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -25,7 +26,7 @@ namespace AZ { namespace Render { - inline u64 TableRow::ms_frames = 0; + inline u64 ImGuiCpuProfiler::ms_framesActive = 0; namespace CpuProfilerImGuiHelper { @@ -41,6 +42,7 @@ namespace AZ { return AZStd::string::format("Thread: %zu", static_cast(threadId)); } + inline float TicksToMs(AZStd::sys_time_t ticks) { // Note: converting to microseconds integer before converting to milliseconds float @@ -170,6 +172,7 @@ namespace AZ } ImGui::Text(statistics->m_groupName.c_str()); + const ImVec2 topLeftBound = ImGui::GetItemRectMin(); ImGui::TableNextColumn(); ImGui::Text(statistics->m_regionName.c_str()); @@ -182,7 +185,17 @@ namespace AZ ImGui::TableNextColumn(); ImGui::Text("%.1f", statistics->GetAverageInvocationsPerFrame()); + const ImVec2 botRightBound = ImGui::GetItemRectMax(); ImGui::TableNextColumn(); + + // NOTE: we are manually checking the bounds rather than using ImGui::IsItemHovered + Begin/EndGroup because + // ImGui reports incorrect bounds when using Begin/End group in the Tables API. + if (ImGui::IsMouseHoveringRect(topLeftBound, botRightBound, false)) + { + ImGui::BeginTooltip(); + ImGui::Text(statistics->GetExecutingThreadsLabel().c_str()); + ImGui::EndTooltip(); + } } } ImGui::EndTable(); @@ -275,7 +288,7 @@ namespace AZ { m_tableData.clear(); m_groupRegionMap.clear(); - TableRow::ms_frames = 0; + ImGuiCpuProfiler::ms_framesActive = 0; } DrawTable(); @@ -446,8 +459,8 @@ namespace AZ // Get the latest TimeRegionMap const RHI::CpuProfiler::TimeRegionMap& timeRegionMap = RHI::CpuProfiler::Get()->GetTimeRegionMap(); - m_viewportStartTick = INT64_MAX; - m_viewportEndTick = INT64_MIN; + m_viewportStartTick = AZStd::numeric_limits::max(); + m_viewportEndTick = AZStd::numeric_limits::lowest(); // Iterate through the entire TimeRegionMap and copy the data since it will get deleted on the next frame for (const auto& [threadId, singleThreadRegionMap] : timeRegionMap) @@ -477,7 +490,7 @@ namespace AZ m_tableData.push_back(&m_groupRegionMap[groupName][regionName]); } - m_groupRegionMap[groupName][regionName].RecordRegion(region); + m_groupRegionMap[groupName][regionName].RecordRegion(region, threadId); } } @@ -842,13 +855,13 @@ namespace AZ else { m_frameEndTicks.push_back(AZStd::GetTimeNowTicks()); - TableRow::ms_frames++; + ImGuiCpuProfiler::ms_framesActive++; } } // ---- TableRow impl ---- - inline void TableRow::RecordRegion(const AZ::RHI::CachedTimeRegion& region) + inline void TableRow::RecordRegion(const AZ::RHI::CachedTimeRegion& region, AZStd::thread_id threadId) { m_invocations++; const AZStd::sys_time_t deltaTime = AZStd::abs(region.m_endTick - region.m_startTick); @@ -857,11 +870,23 @@ namespace AZ // Standard running average algorithm const auto newMean = m_runningAverageTicks + aznumeric_cast((deltaTime - m_runningAverageTicks) * 1.0 / m_invocations); m_runningAverageTicks = newMean; + + m_executingThreads.insert(threadId); } inline double TableRow::GetAverageInvocationsPerFrame() const { - return 1.0 * m_invocations / ms_frames; + return 1.0 * m_invocations / ImGuiCpuProfiler::ms_framesActive; + } + + inline AZStd::string TableRow::GetExecutingThreadsLabel() const + { + AZStd::string threadString; + for (const auto& threadId : m_executingThreads) + { + threadString.append(CpuProfilerImGuiHelper::TextThreadId(threadId.m_id) + ", "); + } + return threadString; } } // namespace Render } // namespace AZ From 11a001946fef6536779a1be54d9d8348dd897e88 Mon Sep 17 00:00:00 2001 From: Jacob Hilliard Date: Wed, 21 Jul 2021 16:14:08 -0700 Subject: [PATCH 084/160] Visualizer: Implement total time + cleanup Signed-off-by: Jacob Hilliard --- .../Include/Atom/Utils/ImGuiCpuProfiler.h | 131 +++++++++--------- .../Include/Atom/Utils/ImGuiCpuProfiler.inl | 72 ++++++---- 2 files changed, 114 insertions(+), 89 deletions(-) diff --git a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.h b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.h index d21783a801..a4f5763c99 100644 --- a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.h +++ b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.h @@ -10,7 +10,6 @@ #include #include -#include #include #include @@ -25,41 +24,50 @@ namespace AZ namespace Render { - struct ThreadRegionEntry - { - AZStd::thread_id m_threadId; - AZStd::sys_time_t m_startTick = 0; - AZStd::sys_time_t m_endTick = 0; - }; - + //! Stores all the data associated with a row in the table. struct TableRow { + // Update running statistics with new region data void RecordRegion(const AZ::RHI::CachedTimeRegion& region, AZStd::thread_id threadId); - double GetAverageInvocationsPerFrame() const; + + void ResetPerFrameStatistics(); + + // Get a string of all threads that this region executed in during the last frame AZStd::string TableRow::GetExecutingThreadsLabel() const; AZStd::string m_groupName; AZStd::string m_regionName; - AZStd::sys_time_t m_maxTicks; - AZStd::sys_time_t m_runningAverageTicks; - u64 m_invocations; + // --- Per frame statistics --- + + u64 m_invocationsLastFrame = 0; + + // NOTE: set over unordered_set so the threads can be shown in increasing order in tooltip. AZStd::set m_executingThreads; + + AZStd::sys_time_t m_lastFrameTotalTicks = 0; + + // Maximum execution time of a region in the last frame. + AZStd::sys_time_t m_maxTicks = 0; + + // --- Aggregate statistics --- + + u64 m_invocationsTotal = 0; + + // Running average of Mean Time Per Call + AZStd::sys_time_t m_runningAverageTicks = 0; }; - //! Visual profiler for Cpu statistics. - //! It uses ImGui as the library for displaying the Attachments and Heaps. - //! It shows all heaps that are being used by the RHI and how the FIXME - //! resources are allocated in each heap. + //! ImGui widget for examining Atom CPU Profiling instrumentation. + //! Offers both a statistical view (with sorting and searching capability) and a visualizer + //! similar to RAD and other profiling tools. class ImGuiCpuProfiler : SystemTickBus::Handler { - friend struct TableRow; - - // Region Name -> Array of ThreadRegion entries - using RegionEntryMap = AZStd::map; - // Group Name -> RegionEntryMap - using GroupRegionMap = AZStd::map; + // Region Name -> statistical view row data + using RegionRowMap = AZStd::map; + // Group Name -> RegionRowMap + using GroupRegionMap = AZStd::map; using TimeRegion = AZ::RHI::CachedTimeRegion; using GroupRegionName = AZ::RHI::CachedTimeRegion::GroupRegionName; @@ -71,63 +79,34 @@ namespace AZ //! Draws the overall CPU profiling window, defaults to the statistical view void Draw(bool& keepDrawing, const AZ::RHI::CpuTimingStatistics& cpuTimingStatistics); - //! Draws the statistical view of the CPU profiling data - void DrawStatisticsView(); - - //! Draws the CPU profiling visualizer in a new window. - void DrawVisualizer(); - private: static constexpr float RowHeight = 50.0; static constexpr int DefaultFramesToCollect = 50; static constexpr float MediumFrameTimeLimit = 16.6; // 60 fps static constexpr float HighFrameTimeLimit = 33.3; // 30 fps - static u64 ms_framesActive; + //! Draws the statistical view of the CPU profiling data. + void DrawStatisticsView(); + + //! Draws the CPU profiling visualizer. + void DrawVisualizer(); - // Draw the shared header between the two windows + // Draw the shared header between the two windows. void DrawCommonHeader(); - // Draw the region statstics table in the order specified by the pointers in m_tableData + // Draw the region statistics table in the order specified by the pointers in m_tableData. void DrawTable(); - // Sort the table by a given column, rearranges the pointers in m_tableData + // Sort the table by a given column, rearranges the pointers in m_tableData. void SortTable(ImGuiTableSortSpecs* sortSpecs); - // ImGui filter used to filter TimedRegions. - ImGuiTextFilter m_timedRegionFilter; - - // Saves statistical view data organized by group name -> region name -> row data - GroupRegionMap m_groupRegionMap; - - // Saves pointers to objects in m_groupRegionMap, order reflects table ordering - AZStd::vector m_tableData; - - // Pause cpu profiling. The profiler will show the statistics of the last frame before pause - bool m_paused = false; - - // Export the profiling data from a single frame to a local file - bool m_captureToFile = false; - - // Toggle between the normal statistical view and the visual profiling view - bool m_enableVisualizer = false; - - // Total frames need to be saved - int m_captureFrameCount = 1; - - AZ::RHI::CpuTimingStatistics m_cpuTimingStatisticsWhenPause; - - AZStd::string m_lastCapturedFilePath; - - // Visualizer methods - // Get the profiling data from the last frame, only called when the profiler is not paused. void CollectFrameData(); // Cull old data from internal storage, only called when profiler is not paused. void CullFrameData(const AZ::RHI::CpuTimingStatistics& currentCpuTimingStatistics); - // Draws a single block onto the timeline + // Draws a single block onto the timeline into the specified row void DrawBlock(const TimeRegion& block, u64 targetRow); // Draw horizontal lines between threads in the timeline @@ -150,14 +129,14 @@ namespace AZ AZStd::sys_time_t GetViewportTickWidth() const; - // Gets the color for a block using the GroupRegionName as a key into the cache - // Generates a random ImU32 if the block does not yet have a color + // Gets the color for a block using the GroupRegionName as a key into the cache. + // Generates a random ImU32 if the block does not yet have a color. ImU32 GetBlockColor(const TimeRegion& block); // System tick bus overrides virtual void OnSystemTick() override; - // Visualizer state + // --- Visualizer Members --- int m_framesToCollect = DefaultFramesToCollect; @@ -179,6 +158,32 @@ namespace AZ // Filter for highlighting regions on the visualizer ImGuiTextFilter m_visualizerHighlightFilter; + + // --- Tabular view members --- + + // ImGui filter used to filter TimedRegions. + ImGuiTextFilter m_timedRegionFilter; + + // Saves statistical view data organized by group name -> region name -> row data + GroupRegionMap m_groupRegionMap; + + // Saves pointers to objects in m_groupRegionMap, order reflects table ordering. + // Non-owning, will be cleared when m_groupRegionMap is cleared. + AZStd::vector m_tableData; + + // Pause cpu profiling. The profiler will show the statistics of the last frame before pause. + bool m_paused = false; + + // Export the profiling data from a single frame to a local file. + bool m_captureToFile = false; + + // Toggle between the normal statistical view and the visual profiling view. + bool m_enableVisualizer = false; + + // Last captured CPU timing statistics + AZ::RHI::CpuTimingStatistics m_cpuTimingStatisticsWhenPause; + + AZStd::string m_lastCapturedFilePath; }; } // namespace Render } // namespace AZ diff --git a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl index 124e48af13..d89fed449a 100644 --- a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl +++ b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl @@ -18,16 +18,11 @@ #include #include -#pragma optimize("", off) - -#include "../../../Gems/ImGui/External/ImGui/v1.82/imgui/imgui.h" namespace AZ { namespace Render { - inline u64 ImGuiCpuProfiler::ms_framesActive = 0; - namespace CpuProfilerImGuiHelper { // NOTE: Fix build error in case AZStd::thread_id is not of an arithmetic type, and instead a pointer @@ -145,14 +140,15 @@ namespace AZ { const auto flags = ImGuiTableFlags_Borders | ImGuiTableFlags_Sortable | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable; - if (ImGui::BeginTable("FunctionStatisticsTable", 5, flags)) + if (ImGui::BeginTable("FunctionStatisticsTable", 6, flags)) { // Table header setup ImGui::TableSetupColumn("Group"); ImGui::TableSetupColumn("Region"); ImGui::TableSetupColumn("MTPC (ms)"); ImGui::TableSetupColumn("Max (ms)"); - ImGui::TableSetupColumn("Invocations/frame"); + ImGui::TableSetupColumn("Invocations"); + ImGui::TableSetupColumn("Total (ms)"); ImGui::TableHeadersRow(); ImGui::TableNextColumn(); @@ -184,13 +180,16 @@ namespace AZ ImGui::Text("%.2f", CpuProfilerImGuiHelper::TicksToMs(statistics->m_maxTicks)); ImGui::TableNextColumn(); - ImGui::Text("%.1f", statistics->GetAverageInvocationsPerFrame()); + ImGui::Text("%ld", statistics->m_invocationsLastFrame); + ImGui::TableNextColumn(); + + ImGui::Text("%.2f", CpuProfilerImGuiHelper::TicksToMs(statistics->m_lastFrameTotalTicks)); const ImVec2 botRightBound = ImGui::GetItemRectMax(); ImGui::TableNextColumn(); // NOTE: we are manually checking the bounds rather than using ImGui::IsItemHovered + Begin/EndGroup because // ImGui reports incorrect bounds when using Begin/End group in the Tables API. - if (ImGui::IsMouseHoveringRect(topLeftBound, botRightBound, false)) + if (ImGui::IsWindowHovered() && ImGui::IsMouseHoveringRect(topLeftBound, botRightBound, false)) { ImGui::BeginTooltip(); ImGui::Text(statistics->GetExecutingThreadsLabel().c_str()); @@ -215,23 +214,32 @@ namespace AZ break; case (1): // Sort by region name AZStd::sort(m_tableData.begin(), m_tableData.end(),[ascending](const TableRow* lhs, const TableRow* rhs){ - return ascending ? lhs->m_regionName < rhs->m_regionName : lhs->m_regionName > rhs->m_regionName; + return ascending ? lhs->m_regionName < rhs->m_regionName + : lhs->m_regionName > rhs->m_regionName; }); break; case (2): // Sort by average time AZStd::sort(m_tableData.begin(), m_tableData.end(), [ascending](const TableRow* lhs, const TableRow* rhs){ return ascending ? lhs->m_runningAverageTicks < rhs->m_runningAverageTicks - : lhs->m_runningAverageTicks > rhs->m_runningAverageTicks; + : lhs->m_runningAverageTicks > rhs->m_runningAverageTicks; }); break; case (3): // Sort by max time AZStd::sort(m_tableData.begin(), m_tableData.end(), [ascending](const TableRow* lhs, const TableRow* rhs){ - return ascending ? lhs->m_maxTicks < rhs->m_maxTicks : lhs->m_maxTicks > rhs->m_maxTicks; + return ascending ? lhs->m_maxTicks < rhs->m_maxTicks + : lhs->m_maxTicks > rhs->m_maxTicks; }); break; case (4): // Sort by invocations AZStd::sort(m_tableData.begin(), m_tableData.end(), [ascending](const TableRow* lhs, const TableRow* rhs){ - return ascending ? lhs->m_invocations < rhs->m_invocations : lhs->m_invocations > rhs->m_invocations; + return ascending ? lhs->m_invocationsLastFrame < rhs->m_invocationsLastFrame + : lhs->m_invocationsLastFrame > rhs->m_invocationsLastFrame; + }); + break; + case (5): // Sort by total time + AZStd::sort(m_tableData.begin(), m_tableData.end(), [ascending](const TableRow* lhs, const TableRow* rhs){ + return ascending ? lhs->m_lastFrameTotalTicks < rhs->m_lastFrameTotalTicks + : lhs->m_lastFrameTotalTicks > rhs->m_lastFrameTotalTicks; }); break; } @@ -288,7 +296,6 @@ namespace AZ { m_tableData.clear(); m_groupRegionMap.clear(); - ImGuiCpuProfiler::ms_framesActive = 0; } DrawTable(); @@ -855,7 +862,14 @@ namespace AZ else { m_frameEndTicks.push_back(AZStd::GetTimeNowTicks()); - ImGuiCpuProfiler::ms_framesActive++; + + for (auto& [groupName, regionMap] : m_groupRegionMap) + { + for (auto& [regionName, row] : regionMap) + { + row.ResetPerFrameStatistics(); + } + } } } @@ -863,28 +877,34 @@ namespace AZ inline void TableRow::RecordRegion(const AZ::RHI::CachedTimeRegion& region, AZStd::thread_id threadId) { - m_invocations++; - const AZStd::sys_time_t deltaTime = AZStd::abs(region.m_endTick - region.m_startTick); - m_maxTicks = AZStd::max(m_maxTicks, deltaTime); - - // Standard running average algorithm - const auto newMean = m_runningAverageTicks + aznumeric_cast((deltaTime - m_runningAverageTicks) * 1.0 / m_invocations); - m_runningAverageTicks = newMean; + const AZStd::sys_time_t deltaTime = region.m_endTick - region.m_startTick; + // Update per frame statistics + m_invocationsLastFrame++; m_executingThreads.insert(threadId); + m_lastFrameTotalTicks += deltaTime; + m_maxTicks = AZStd::max(m_maxTicks, deltaTime); + + // Update aggregate statistics + m_runningAverageTicks = + aznumeric_cast((1.0 * (deltaTime + m_invocationsTotal * m_runningAverageTicks)) / (m_invocationsTotal + 1)); + ++m_invocationsTotal; } - inline double TableRow::GetAverageInvocationsPerFrame() const + inline void TableRow::ResetPerFrameStatistics() { - return 1.0 * m_invocations / ImGuiCpuProfiler::ms_framesActive; + m_invocationsLastFrame = 0; + m_executingThreads.clear(); + m_lastFrameTotalTicks = 0; + m_maxTicks = 0; } inline AZStd::string TableRow::GetExecutingThreadsLabel() const { - AZStd::string threadString; + auto threadString = AZStd::string::format("Executed in %zu threads\n", m_executingThreads.size()); for (const auto& threadId : m_executingThreads) { - threadString.append(CpuProfilerImGuiHelper::TextThreadId(threadId.m_id) + ", "); + threadString.append(CpuProfilerImGuiHelper::TextThreadId(threadId.m_id) + "\n"); } return threadString; } From a064cedb59b7680c55d8e46219e82cd0e950a21a Mon Sep 17 00:00:00 2001 From: Jacob Hilliard Date: Tue, 27 Jul 2021 09:40:55 -0700 Subject: [PATCH 085/160] Visualizer: fix clang build error Signed-off-by: Jacob Hilliard --- Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.h | 2 +- Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.h b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.h index a4f5763c99..62b71bdbb8 100644 --- a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.h +++ b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.h @@ -33,7 +33,7 @@ namespace AZ void ResetPerFrameStatistics(); // Get a string of all threads that this region executed in during the last frame - AZStd::string TableRow::GetExecutingThreadsLabel() const; + AZStd::string GetExecutingThreadsLabel() const; AZStd::string m_groupName; AZStd::string m_regionName; diff --git a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl index d89fed449a..79a2ffd5a0 100644 --- a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl +++ b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl @@ -180,7 +180,7 @@ namespace AZ ImGui::Text("%.2f", CpuProfilerImGuiHelper::TicksToMs(statistics->m_maxTicks)); ImGui::TableNextColumn(); - ImGui::Text("%ld", statistics->m_invocationsLastFrame); + ImGui::Text("%llu", statistics->m_invocationsLastFrame); ImGui::TableNextColumn(); ImGui::Text("%.2f", CpuProfilerImGuiHelper::TicksToMs(statistics->m_lastFrameTotalTicks)); From a271a85d6efd7ef848c169ad1661c52b19986148 Mon Sep 17 00:00:00 2001 From: Jacob Hilliard Date: Wed, 28 Jul 2021 09:27:55 -0700 Subject: [PATCH 086/160] Visualizer: postfix -> prefix increment Signed-off-by: Jacob Hilliard --- Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl index 79a2ffd5a0..90b6c67905 100644 --- a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl +++ b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl @@ -880,7 +880,7 @@ namespace AZ const AZStd::sys_time_t deltaTime = region.m_endTick - region.m_startTick; // Update per frame statistics - m_invocationsLastFrame++; + ++m_invocationsLastFrame; m_executingThreads.insert(threadId); m_lastFrameTotalTicks += deltaTime; m_maxTicks = AZStd::max(m_maxTicks, deltaTime); From 567b4a7f282fb49d797f311fbaeee31ef3b24069 Mon Sep 17 00:00:00 2001 From: Cynthia Lin <15116870+synicalsyntax@users.noreply.github.com> Date: Wed, 28 Jul 2021 11:07:32 -0700 Subject: [PATCH 087/160] [ATOM-16016] Add initial level for AtomFeatureIntegrationBenchmark to AutomatedTesting. (#2405) * [ATOM-16016] Add initial level for AtomFeatureIntegrationBenchmark to AutomatedTesting. Signed-off-by: Cynthia Lin * [ATOM-16016] Add new AtomFeatureIntegrationBenchmark to AutomatedTesting. Signed-off-by: Cynthia Lin --- ...GPUTest_AtomFeatureIntegrationBenchmark.py | 102 ++++++++++++++++++ .../atom_utils/benchmark_utils.py | 84 +++++++++++++++ .../atom_renderer/test_Atom_GPUTests.py | 41 +++++++ .../AtomFeatureIntegrationBenchmark.ly | 3 + .../filelist.xml | 6 ++ .../AtomFeatureIntegrationBenchmark/level.pak | 3 + .../AtomFeatureIntegrationBenchmark/tags.txt | 12 +++ 7 files changed, 251 insertions(+) create mode 100644 AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_GPUTest_AtomFeatureIntegrationBenchmark.py create mode 100644 AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/benchmark_utils.py create mode 100644 AutomatedTesting/Levels/AtomFeatureIntegrationBenchmark/AtomFeatureIntegrationBenchmark.ly create mode 100644 AutomatedTesting/Levels/AtomFeatureIntegrationBenchmark/filelist.xml create mode 100644 AutomatedTesting/Levels/AtomFeatureIntegrationBenchmark/level.pak create mode 100644 AutomatedTesting/Levels/AtomFeatureIntegrationBenchmark/tags.txt diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_GPUTest_AtomFeatureIntegrationBenchmark.py b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_GPUTest_AtomFeatureIntegrationBenchmark.py new file mode 100644 index 0000000000..b899d7dcde --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_GPUTest_AtomFeatureIntegrationBenchmark.py @@ -0,0 +1,102 @@ +""" +Copyright (c) Contributors to the Open 3D Engine Project. +For complete copyright and license terms please see the LICENSE at the root of this distribution. + +SPDX-License-Identifier: Apache-2.0 OR MIT + +Hydra script that is used to create a new level with a default rendering setup. +After the level is setup, screenshots are diffed against golden images are used to verify pass/fail results of the test. + +See the run() function for more in-depth test info. +""" + +import os +import sys + +import azlmbr.legacy.general as general + +sys.path.append(os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Gem", "PythonTests")) + +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper +from atom_renderer.atom_utils.benchmark_utils import BenchmarkHelper + +SCREEN_WIDTH = 1280 +SCREEN_HEIGHT = 720 +DEGREE_RADIAN_FACTOR = 0.0174533 + +helper = EditorTestHelper(log_prefix="Test_Atom_BasicLevelSetup") + + +def run(): + """ + 1. View -> Layouts -> Restore Default Layout, sets the viewport to ratio 16:9 @ 1280 x 720 + 2. Runs console command r_DisplayInfo = 0 + 3. Opens AtomFeatureIntegrationBenchmark level + 4. Initializes benchmark helper with benchmark name to capture benchmark metadata. + 5. Idles for 100 frames, then collects pass timings for 100 frames. + :return: None + """ + def initial_viewport_setup(screen_width, screen_height): + general.set_viewport_size(screen_width, screen_height) + general.update_viewport() + helper.wait_for_condition( + function=lambda: helper.isclose(a=general.get_viewport_size().x, b=SCREEN_WIDTH, rel_tol=0.1) + and helper.isclose(a=general.get_viewport_size().y, b=SCREEN_HEIGHT, rel_tol=0.1), + timeout_in_seconds=4.0 + ) + result = helper.isclose(a=general.get_viewport_size().x, b=SCREEN_WIDTH, rel_tol=0.1) and helper.isclose( + a=general.get_viewport_size().y, b=SCREEN_HEIGHT, rel_tol=0.1) + general.log(general.get_viewport_size().x) + general.log(general.get_viewport_size().y) + general.log(general.get_viewport_size().z) + general.log(f"Viewport is set to the expected size: {result}") + general.run_console("r_DisplayInfo = 0") + + def after_level_load(): + """Function to call after creating/opening a level to ensure it loads.""" + # Give everything a second to initialize. + general.idle_enable(True) + general.idle_wait(1.0) + general.update_viewport() + general.idle_wait(0.5) # half a second is more than enough for updating the viewport. + + # Close out problematic windows, FPS meters, and anti-aliasing. + if general.is_helpers_shown(): # Turn off the helper gizmos if visible + general.toggle_helpers() + general.idle_wait(1.0) + if general.is_pane_visible("Error Report"): # Close Error Report windows that block focus. + general.close_pane("Error Report") + if general.is_pane_visible("Error Log"): # Close Error Log windows that block focus. + general.close_pane("Error Log") + general.idle_wait(1.0) + general.run_console("r_displayInfo=0") + general.run_console("r_antialiasingmode=0") + general.idle_wait(1.0) + + return True + + # Wait for Editor idle loop before executing Python hydra scripts. + general.idle_enable(True) + + general.open_level_no_prompt("AtomFeatureIntegrationBenchmark") + + # Basic setup after opening level. + after_level_load() + initial_viewport_setup(SCREEN_WIDTH, SCREEN_HEIGHT) + + general.enter_game_mode() + general.idle_wait(1.0) + helper.wait_for_condition(function=lambda: general.is_in_game_mode(), timeout_in_seconds=2.0) + benchmarker = BenchmarkHelper("AtomFeatureIntegrationBenchmark") + benchmarker.capture_benchmark_metadata() + general.idle_wait_frames(100) + for i in range(1, 101): + benchmarker.capture_pass_timestamp(i) + general.exit_game_mode() + helper.wait_for_condition(function=lambda: not general.is_in_game_mode(), timeout_in_seconds=2.0) + general.log("Capturing complete.") + + +if __name__ == "__main__": + run() diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/benchmark_utils.py b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/benchmark_utils.py new file mode 100644 index 0000000000..21c7489ed3 --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/benchmark_utils.py @@ -0,0 +1,84 @@ +""" +Copyright (c) Contributors to the Open 3D Engine Project. +For complete copyright and license terms please see the LICENSE at the root of this distribution. + +SPDX-License-Identifier: Apache-2.0 OR MIT +""" +import azlmbr.atom +import azlmbr.legacy.general as general + +FOLDER_PATH = '@user@/Scripts/PerformanceBenchmarks' +METADATA_FILE = 'benchmark_metadata.json' + +class BenchmarkHelper(object): + """ + A helper to capture benchmark data. + """ + def __init__(self, benchmark_name): + super().__init__() + self.benchmark_name = benchmark_name + self.output_path = f'{FOLDER_PATH}/{benchmark_name}' + self.done = False + self.capturedData = False + self.max_frames_to_wait = 200 + + def capture_benchmark_metadata(self): + """ + Capture benchmark metadata and block further execution until it has been written to the disk. + """ + self.handler = azlmbr.atom.ProfilingCaptureNotificationBusHandler() + self.handler.connect() + self.handler.add_callback('OnCaptureBenchmarkMetadataFinished', self.on_data_captured) + + self.done = False + self.capturedData = False + success = azlmbr.atom.ProfilingCaptureRequestBus( + azlmbr.bus.Broadcast, "CaptureBenchmarkMetadata", self.benchmark_name, f'{self.output_path}/{METADATA_FILE}' + ) + if success: + self.wait_until_data() + general.log('Benchmark metadata captured.') + else: + general.log('Failed to capture benchmark metadata.') + return self.capturedData + + def capture_pass_timestamp(self, frame_number): + """ + Capture pass timestamps and block further execution until it has been written to the disk. + """ + self.handler = azlmbr.atom.ProfilingCaptureNotificationBusHandler() + self.handler.connect() + self.handler.add_callback('OnCaptureQueryTimestampFinished', self.on_data_captured) + + self.done = False + self.capturedData = False + success = azlmbr.atom.ProfilingCaptureRequestBus( + azlmbr.bus.Broadcast, "CapturePassTimestamp", f'{self.output_path}/frame{frame_number}_timestamps.json') + if success: + self.wait_until_data() + general.log('Pass timestamps captured.') + else: + general.log('Failed to capture pass timestamps.') + return self.capturedData + + def on_data_captured(self, parameters): + # the parameters come in as a tuple + if parameters[0]: + general.log('Captured data successfully.') + self.capturedData = True + else: + general.log('Failed to capture data.') + self.done = True + self.handler.disconnect() + + def wait_until_data(self): + frames_waited = 0 + while self.done == False: + general.idle_wait_frames(1) + if frames_waited > self.max_frames_to_wait: + general.log('Timed out while waiting for the data to be captured') + self.handler.disconnect() + break + else: + frames_waited = frames_waited + 1 + general.log(f'(waited {frames_waited} frames)') diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_GPUTests.py b/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_GPUTests.py index dad92d0932..ede140c075 100644 --- a/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_GPUTests.py +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_GPUTests.py @@ -14,6 +14,7 @@ import pytest import ly_test_tools.environment.file_system as file_system from ly_test_tools.image.screenshot_compare_qssim import qssim as compare_screenshots +from ly_test_tools.benchmark.data_aggregator import BenchmarkDataAggregator import editor_python_test_tools.hydra_test_utils as hydra logger = logging.getLogger(__name__) @@ -83,3 +84,43 @@ class TestAllComponentsIndepthTests(object): for test_screenshot, golden_screenshot in zip(test_screenshots, golden_images): compare_screenshots(test_screenshot, golden_screenshot) + +@pytest.mark.parametrize('rhi', ['dx12', 'vulkan']) +@pytest.mark.parametrize("project", ["AutomatedTesting"]) +@pytest.mark.parametrize("launcher_platform", ["windows_editor"]) +@pytest.mark.parametrize("level", ["AtomFeatureIntegrationBenchmark"]) +class TestPerformanceBenchmarkSuite(object): + def test_AtomFeatureIntegrationBenchmark( + self, request, editor, workspace, rhi, project, launcher_platform, level): + """ + Please review the hydra script run by this test for more specific test info. + Tests the performance of the Simple level. + """ + expected_lines = [ + "Benchmark metadata captured.", + "Pass timestamps captured.", + "Capturing complete.", + "Captured data successfully." + ] + + unexpected_lines = [ + "Failed to capture data.", + "Failed to capture pass timestamps.", + "Failed to capture benchmark metadata." + ] + + hydra.launch_and_validate_results( + request, + TEST_DIRECTORY, + editor, + "hydra_GPUTest_AtomFeatureIntegrationBenchmark.py", + timeout=EDITOR_TIMEOUT, + expected_lines=expected_lines, + unexpected_lines=unexpected_lines, + halt_on_unexpected=True, + cfg_args=[level], + null_renderer=False, + ) + + aggregator = BenchmarkDataAggregator(workspace, logger, 'periodic') + aggregator.upload_metrics(rhi) diff --git a/AutomatedTesting/Levels/AtomFeatureIntegrationBenchmark/AtomFeatureIntegrationBenchmark.ly b/AutomatedTesting/Levels/AtomFeatureIntegrationBenchmark/AtomFeatureIntegrationBenchmark.ly new file mode 100644 index 0000000000..4fc96f242b --- /dev/null +++ b/AutomatedTesting/Levels/AtomFeatureIntegrationBenchmark/AtomFeatureIntegrationBenchmark.ly @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5232563c3ff322669808ac4daeda3d822e4ef8c9c87db0fa245f0f9c9c34aada +size 23379 diff --git a/AutomatedTesting/Levels/AtomFeatureIntegrationBenchmark/filelist.xml b/AutomatedTesting/Levels/AtomFeatureIntegrationBenchmark/filelist.xml new file mode 100644 index 0000000000..15b79f5e4f --- /dev/null +++ b/AutomatedTesting/Levels/AtomFeatureIntegrationBenchmark/filelist.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/AutomatedTesting/Levels/AtomFeatureIntegrationBenchmark/level.pak b/AutomatedTesting/Levels/AtomFeatureIntegrationBenchmark/level.pak new file mode 100644 index 0000000000..fecbc0b394 --- /dev/null +++ b/AutomatedTesting/Levels/AtomFeatureIntegrationBenchmark/level.pak @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e075be2cb7cf5aa98e3503c1119b94c3098b35500c98c4db32d025c9e1afa52d +size 5450 diff --git a/AutomatedTesting/Levels/AtomFeatureIntegrationBenchmark/tags.txt b/AutomatedTesting/Levels/AtomFeatureIntegrationBenchmark/tags.txt new file mode 100644 index 0000000000..a5e0705349 --- /dev/null +++ b/AutomatedTesting/Levels/AtomFeatureIntegrationBenchmark/tags.txt @@ -0,0 +1,12 @@ +495.045,510.96,35.8437,-0.166,0,-1.82124 +4.79827,4.71364,64.7838,-1.41886,0,2.48964 +0,0,0,0,0,0 +0,0,0,0,0,0 +0,0,0,0,0,0 +0,0,0,0,0,0 +0,0,0,0,0,0 +0,0,0,0,0,0 +0,0,0,0,0,0 +0,0,0,0,0,0 +0,0,0,0,0,0 +0,0,0,0,0,0 From 15d6ca3252696903eb073870c65a66518104fb7f Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Wed, 28 Jul 2021 11:51:21 -0700 Subject: [PATCH 088/160] abandon attepts to enable script canvas tests on the farm Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com> --- Code/Framework/AzCore/CMakeLists.txt | 3 --- Gems/ScriptCanvasTesting/Code/CMakeLists.txt | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/Code/Framework/AzCore/CMakeLists.txt b/Code/Framework/AzCore/CMakeLists.txt index 785352cf05..ea7cc27af5 100644 --- a/Code/Framework/AzCore/CMakeLists.txt +++ b/Code/Framework/AzCore/CMakeLists.txt @@ -130,9 +130,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) ly_add_googletest( NAME AZ::AzCore.Tests ) - if(PAL_TRAIT_TEST_GOOGLE_TEST_SUPPORTED) - set_tests_properties(AZ::AzCore.Tests.main::TEST_RUN PROPERTIES RUN_SERIAL true) - endif() ly_add_googlebenchmark( NAME AZ::AzCore.Benchmarks TARGET AZ::AzCore.Tests diff --git a/Gems/ScriptCanvasTesting/Code/CMakeLists.txt b/Gems/ScriptCanvasTesting/Code/CMakeLists.txt index 7291cd65eb..dada433772 100644 --- a/Gems/ScriptCanvasTesting/Code/CMakeLists.txt +++ b/Gems/ScriptCanvasTesting/Code/CMakeLists.txt @@ -113,8 +113,8 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) ) ly_add_googletest( NAME Gem::ScriptCanvasTesting.Editor.Tests + TEST_SUITE smoke ) - set_tests_properties(Gem::ScriptCanvasTesting.Editor.Tests.main::TEST_RUN PROPERTIES RUN_SERIAL true) endif() From 6839497d99e0d9a3b762b42bf16d19d2e018ceb9 Mon Sep 17 00:00:00 2001 From: kberg-amzn Date: Wed, 28 Jul 2021 12:31:19 -0700 Subject: [PATCH 089/160] Corrects math computing blend factors to interpolate state between received network updates Signed-off-by: kberg-amzn --- .../Source/MultiplayerSystemComponent.cpp | 37 +++++++++++++------ .../Code/Source/MultiplayerSystemComponent.h | 2 +- 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp index 9a46bb10de..21c7ce80d6 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp +++ b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp @@ -69,19 +69,24 @@ namespace Multiplayer { using namespace AzNetworking; - AZ_CVAR(uint16_t, cl_clientport, 0, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "The port to bind to for game traffic when connecting to a remote host, a value of 0 will select any available port"); - AZ_CVAR(AZ::CVarFixedString, cl_serveraddr, AZ::CVarFixedString(LocalHost), nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "The address of the remote server or host to connect to"); - AZ_CVAR(AZ::CVarFixedString, cl_serverpassword, "", nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "Optional server password"); + AZ_CVAR(uint16_t, cl_clientport, 0, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, + "The port to bind to for game traffic when connecting to a remote host, a value of 0 will select any available port"); + AZ_CVAR(AZ::CVarFixedString, cl_serveraddr, AZ::CVarFixedString(LocalHost), nullptr, AZ::ConsoleFunctorFlags::DontReplicate, + "The address of the remote server or host to connect to"); AZ_CVAR(uint16_t, cl_serverport, DefaultServerPort, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "The port of the remote host to connect to for game traffic"); AZ_CVAR(uint16_t, sv_port, DefaultServerPort, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "The port that this multiplayer gem will bind to for game traffic"); AZ_CVAR(AZ::CVarFixedString, sv_map, "nolevel", nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "The map the server should load"); - AZ_CVAR(AZ::CVarFixedString, sv_gamerules, "norules", nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "GameRules server works with"); AZ_CVAR(ProtocolType, sv_protocol, ProtocolType::Udp, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "This flag controls whether we use TCP or UDP for game networking"); AZ_CVAR(bool, sv_isDedicated, true, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "Whether the host command creates an independent or client hosted server"); AZ_CVAR(bool, sv_isTransient, true, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "Whether a dedicated server shuts down if all existing connections disconnect."); - AZ_CVAR(AZ::TimeMs, cl_defaultNetworkEntityActivationTimeSliceMs, AZ::TimeMs{ 0 }, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "Max Ms to use to activate entities coming from the network, 0 means instantiate everything"); + AZ_CVAR(AZ::TimeMs, cl_defaultNetworkEntityActivationTimeSliceMs, AZ::TimeMs{ 0 }, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, + "Max Ms to use to activate entities coming from the network, 0 means instantiate everything"); AZ_CVAR(AZ::TimeMs, sv_serverSendRateMs, AZ::TimeMs{ 50 }, nullptr, AZ::ConsoleFunctorFlags::Null, "Minimum number of milliseconds between each network update"); - AZ_CVAR(AZ::CVarFixedString, sv_defaultPlayerSpawnAsset, "prefabs/player.network.spawnable", nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "The default spawnable to use when a new player connects"); + AZ_CVAR(AZ::CVarFixedString, sv_defaultPlayerSpawnAsset, "prefabs/player.network.spawnable", nullptr, AZ::ConsoleFunctorFlags::DontReplicate, + "The default spawnable to use when a new player connects"); + AZ_CVAR(float, cl_renderTickBlendBase, 0.15f, nullptr, AZ::ConsoleFunctorFlags::Null, + "The base used for blending between network updates, 0.1 will be quite linear, 0.2 or 0.3 will " + "slow down quicker and may be better suited to connections with highly variable latency"); void MultiplayerSystemComponent::Reflect(AZ::ReflectContext* context) { @@ -546,7 +551,7 @@ namespace Multiplayer if ((GetAgentType() == MultiplayerAgentType::Client) && (packet.GetHostFrameId() > m_lastReplicatedHostFrameId)) { // Update client to latest server time - m_renderBlendFactor = 0.0f; + m_tickFactor = 0.0f; m_lastReplicatedHostTimeMs = packet.GetHostTimeMs(); m_lastReplicatedHostFrameId = packet.GetHostFrameId(); m_networkTime.AlterTime(m_lastReplicatedHostFrameId, m_lastReplicatedHostTimeMs, AzNetworking::InvalidConnectionId); @@ -849,10 +854,18 @@ namespace Multiplayer void MultiplayerSystemComponent::TickVisibleNetworkEntities(float deltaTime, float serverRateSeconds) { + m_tickFactor += deltaTime / serverRateSeconds; // Linear close to the origin, but asymptote at y = 1 - const float targetAdjustBlend = AZStd::clamp(deltaTime / serverRateSeconds, 0.0f, 1.0f); - m_renderBlendFactor = 1.0f - (std::pow(0.2f, m_renderBlendFactor + targetAdjustBlend)); - AZLOG(NET_Blending, "Computed blend factor of %0.2f using a frametime of %0.2f and a serverTickRate of %0.2f", m_renderBlendFactor, deltaTime, serverRateSeconds); + const float renderBlendFactor = AZStd::clamp(1.0f - (std::pow(cl_renderTickBlendBase, m_tickFactor)), 0.0f, 1.0f); + AZLOG + ( + NET_Blending, + "Computed blend factor of %0.3f using a tick factor of %0.3f, a frametime of %0.3f and a serverTickRate of %0.3f", + renderBlendFactor, + m_tickFactor, + deltaTime, + serverRateSeconds + ); if (Camera::ActiveCameraRequestBus::HasHandlers()) { @@ -895,7 +908,7 @@ namespace Multiplayer for (NetBindComponent* netBindComponent : gatheredEntities) { - netBindComponent->NotifyPreRender(deltaTime, m_renderBlendFactor); + netBindComponent->NotifyPreRender(deltaTime, renderBlendFactor); } } else @@ -907,7 +920,7 @@ namespace Multiplayer NetBindComponent* netBindComponent = entity->FindComponent(); if (netBindComponent != nullptr) { - netBindComponent->NotifyPreRender(deltaTime, m_renderBlendFactor); + netBindComponent->NotifyPreRender(deltaTime, renderBlendFactor); } } } diff --git a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h index 37e8138a71..ab37958962 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h +++ b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h @@ -155,7 +155,7 @@ namespace Multiplayer HostFrameId m_lastReplicatedHostFrameId = HostFrameId(0); double m_serverSendAccumulator = 0.0; - float m_renderBlendFactor = 0.0f; + float m_tickFactor = 0.0f; #if !defined(AZ_RELEASE_BUILD) MultiplayerEditorConnection m_editorConnectionListener; From 055df374829d5b2b9c09424e5d098dc3c2a0302d Mon Sep 17 00:00:00 2001 From: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> Date: Wed, 28 Jul 2021 16:21:37 -0500 Subject: [PATCH 090/160] Register show command fix (#2408) * Updated print_registration functions to fix "register-show" command Added unit test to validate the argparse options to the register show command. Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Updated the register.py script to once again register an engine list Previosly each engine were registered into a dictionary with multiple keys, but once the engine.json started to self describe the registered content that came with it, it was reduced to a single 'path' key. Therefore it has been changed to a list to be consistent with other o3de object paths Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Updated the SettingsRegistryMergeUtitls Code which parses the attempts to locate the engine path associated associated with the project.json engine key to check the 'engines_path' object within the o3de_manifest.json Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Updated print registration unit test to patch the get_project_path This is to make sure that the existence of the placeholder project path isn't validated when running the test Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Typo and formatting fixes for the print_registration script Also corrected indentation in unit_test_print_registration script Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> --- .../Settings/SettingsRegistryMergeUtils.cpp | 50 +-- scripts/o3de/o3de/manifest.py | 35 +- scripts/o3de/o3de/print_registration.py | 221 ++++++---- scripts/o3de/o3de/register.py | 79 ++-- scripts/o3de/tests/CMakeLists.txt | 9 +- .../tests/unit_test_print_registration.py | 383 ++++++++++++++++++ 6 files changed, 591 insertions(+), 186 deletions(-) create mode 100644 scripts/o3de/tests/unit_test_print_registration.py diff --git a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp index 74038c8aed..6b89b8c044 100644 --- a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp +++ b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp @@ -57,6 +57,7 @@ namespace AZ::Internal // and avoid all this logic. using namespace AZ::SettingsRegistryMergeUtils; + using FixedValueString = AZ::SettingsRegistryInterface::FixedValueString; AZ::IO::FixedMaxPath engineRoot; if (auto engineManifestPath = AZ::Utils::GetEngineManifestPath(); !engineManifestPath.empty()) @@ -72,45 +73,16 @@ namespace AZ::Internal struct EngineInfo { AZ::IO::FixedMaxPath m_path; - AZ::SettingsRegistryInterface::FixedValueString m_moniker; + FixedValueString m_moniker; }; struct EnginePathsVisitor : public AZ::SettingsRegistryInterface::Visitor { void Visit( - [[maybe_unused]] AZStd::string_view path, [[maybe_unused]] AZStd::string_view valueName, - [[maybe_unused]] AZ::SettingsRegistryInterface::Type type, AZStd::string_view value) override - { - m_enginePaths.emplace_back(EngineInfo{AZ::IO::FixedMaxPath{value}.LexicallyNormal(), {}}); - } - - AZ::SettingsRegistryInterface::VisitResponse Traverse( [[maybe_unused]] AZStd::string_view path, AZStd::string_view valueName, - AZ::SettingsRegistryInterface::VisitAction action, AZ::SettingsRegistryInterface::Type type) override + [[maybe_unused]] AZ::SettingsRegistryInterface::Type type, AZStd::string_view value) override { - auto response = AZ::SettingsRegistryInterface::VisitResponse::Continue; - if (action == AZ::SettingsRegistryInterface::VisitAction::Begin) - { - if (type == AZ::SettingsRegistryInterface::Type::Array) - { - if (valueName.compare("engines") != 0) - { - response = AZ::SettingsRegistryInterface::VisitResponse::Skip; - } - } - } - else if (action == AZ::SettingsRegistryInterface::VisitAction::Value) - { - if (type == AZ::SettingsRegistryInterface::Type::String) - { - if (valueName.compare("path") != 0) - { - response = AZ::SettingsRegistryInterface::VisitResponse::Skip; - } - } - } - - return response; + m_enginePaths.emplace_back(EngineInfo{ AZ::IO::FixedMaxPath{value}.LexicallyNormal(), FixedValueString{valueName} }); } AZStd::vector m_enginePaths{}; @@ -119,11 +91,11 @@ namespace AZ::Internal EnginePathsVisitor pathVisitor; if (manifestLoaded) { - auto enginePathsKey = AZ::SettingsRegistryInterface::FixedValueString::format("%s/engines", EngineManifestRootKey); + auto enginePathsKey = FixedValueString::format("%s/engines_path", EngineManifestRootKey); settingsRegistry.Visit(pathVisitor, enginePathsKey); } - const auto engineMonikerKey = AZ::SettingsRegistryInterface::FixedValueString::format("%s/engine_name", EngineSettingsRootKey); + const auto engineMonikerKey = FixedValueString::format("%s/engine_name", EngineSettingsRootKey); AZStd::set projectPathsNotFound; @@ -135,7 +107,15 @@ namespace AZ::Internal if (settingsRegistry.MergeSettingsFile( engineSettingsPath.Native(), AZ::SettingsRegistryInterface::Format::JsonMergePatch, EngineSettingsRootKey)) { - settingsRegistry.Get(engineInfo.m_moniker, engineMonikerKey); + FixedValueString engineName; + settingsRegistry.Get(engineName, engineMonikerKey); + AZ_Warning("SettingsRegistryMergeUtils",engineInfo.m_moniker == engineName, + R"(The engine name key "%s" mapped to engine path "%s" within the global manifest of "%s")" + R"( does not match the "engine_name" field "%s" in the engine.json)" "\n" + "This engine should be re-registered.", + engineInfo.m_moniker.c_str(), engineInfo.m_path.c_str(), engineManifestPath.c_str(), + engineName.c_str()) + engineInfo.m_moniker = engineName; } } diff --git a/scripts/o3de/o3de/manifest.py b/scripts/o3de/o3de/manifest.py index 5bc6b95358..7e504d29cd 100644 --- a/scripts/o3de/o3de/manifest.py +++ b/scripts/o3de/o3de/manifest.py @@ -236,15 +236,13 @@ def get_gems_from_subdirectories(external_subdirs: list) -> list: # Data query methods -def get_this_engine() -> dict: - json_data = load_o3de_manifest() - engine_data = find_engine_data(json_data) - return engine_data - - def get_engines() -> list: json_data = load_o3de_manifest() - return json_data['engines'] if 'engines' in json_data else [] + engine_list = json_data['engines'] if 'engines' in json_data else [] + # Convert each engine dict entry into a string entry + return list(map( + lambda engine_object: engine_object.get('path', '') if isinstance(engine_object, dict) else engine_object, + engine_list)) def get_projects() -> list: @@ -424,20 +422,6 @@ def get_templates_for_generic_creation(): # temporary until we have a better wa return list(filter(filter_project_and_gem_templates_out, get_all_templates())) -def find_engine_data(json_data: dict, - engine_path: str or pathlib.Path = None) -> dict or None: - if not engine_path: - engine_path = get_this_engine_path() - engine_path = pathlib.Path(engine_path).resolve() - - for engine_object in json_data['engines']: - engine_object_path = pathlib.Path(engine_object['path']).resolve() - if engine_path == engine_object_path: - return engine_object - - return None - - def get_engine_json_data(engine_name: str = None, engine_path: str or pathlib.Path = None) -> dict or None: if not engine_name and not engine_path: @@ -639,8 +623,13 @@ def get_registered(engine_name: str = None, # check global first then this engine if isinstance(engine_name, str): - for engine in json_data['engines']: - engine_path = pathlib.Path(engine['path']).resolve() + engines = get_engines() + for engine in engines: + if isinstance(engine, dict): + engine_path = pathlib.Path(engine['path']).resolve() + else: + engine_path = pathlib.Path(engine_object).resolve() + engine_json = engine_path / 'engine.json' with engine_json.open('r') as f: try: diff --git a/scripts/o3de/o3de/print_registration.py b/scripts/o3de/o3de/print_registration.py index 10316cc4a8..b164243b7c 100644 --- a/scripts/o3de/o3de/print_registration.py +++ b/scripts/o3de/o3de/print_registration.py @@ -40,61 +40,67 @@ def get_project_path(project_path: pathlib.Path, project_name: str) -> pathlib.P def print_this_engine(verbose: int) -> int: - engine_data = manifest.get_this_engine() - print(json.dumps(engine_data, indent=4)) - result = True + this_engine_path = manifest.get_this_engine_path() + print(f'This Engine:\n{json.dumps(str(this_engine_path), indent=4)}') if verbose > 0: - result = print_manifest_json_data(engine_data, 'engine.json', 'This Engine', + return print_manifest_json_data([this_engine_path], 'This Engine', manifest.get_engine_json_data, 'engine_path') - return 0 if result else 1 + return 0 def print_engines(verbose: int) -> None: engines_data = manifest.get_engines() - print(json.dumps(engines_data, indent=4)) + print(f'Engine Paths:\n{json.dumps(engines_data, indent=4)}') if verbose > 0: - return print_manifest_json_data(engines_data, 'engine.json', 'Engines', + return print_manifest_json_data(engines_data, 'Engine Jsons', manifest.get_engine_json_data, 'engine_path') return 0 def print_projects(verbose: int) -> int: projects_data = manifest.get_projects() - print(json.dumps(projects_data, indent=4)) + print(f'Project Paths:\n{json.dumps(projects_data, indent=4)}') if verbose > 0: - return print_manifest_json_data(projects_data, 'project.json', 'Projects', + return print_manifest_json_data(projects_data, 'Project Jsons', manifest.get_project_json_data, 'project_path') return 0 def print_gems(verbose: int) -> int: gems_data = manifest.get_gems() - print(json.dumps(gems_data, indent=4)) + print(f'Gem Paths:\n{json.dumps(gems_data, indent=4)}') if verbose > 0: - return print_manifest_json_data(gems_data, 'gem.json', 'Gems', + return print_manifest_json_data(gems_data, 'Gem Jsons', manifest.get_gem_json_data, 'gem_path') return 0 +def print_external_subdirectories(verbose: int) -> int: + external_subdirs_data = manifest.get_external_subdirectories() + print(f'External Subdirectories:\n{json.dumps(external_subdirs_data, indent=4)}') + return 0 + + + def print_templates(verbose: int) -> int: templates_data = manifest.get_templates() - print(json.dumps(templates_data, indent=4)) + print(f'Template Paths:\n{json.dumps(templates_data, indent=4)}') if verbose > 0: - return print_manifest_json_data(templates_data, 'template.json', 'Templates', + return print_manifest_json_data(templates_data, 'Template Jsons', manifest.get_template_json_data, 'template_path') return 0 def print_restricted(verbose: int) -> int: restricted_data = manifest.get_restricted() - print(json.dumps(restricted_data, indent=4)) + print(f'Restricted Paths:\n{json.dumps(restricted_data, indent=4)}') if verbose > 0: - return print_manifest_json_data(restricted_data, 'restricted.json', 'Restricted', + return print_manifest_json_data(restricted_data, 'Restricted Jsons', manifest.get_restricted_json_data, 'restricted_path') return 0 @@ -102,47 +108,47 @@ def print_restricted(verbose: int) -> int: # Engine output methods def print_engine_projects(verbose: int) -> int: engine_projects_data = manifest.get_engine_projects() - print(json.dumps(engine_projects_data, indent=4)) + print(f'Project Paths:\n{json.dumps(engine_projects_data, indent=4)}') if verbose > 0: - return print_manifest_json_data(engine_projects_data, 'project.json', 'Projects', + return print_manifest_json_data(engine_projects_data, 'Project Jsons', manifest.get_project_json_data, 'project_path') return 0 def print_engine_gems(verbose: int) -> int: engine_gems_data = manifest.get_engine_gems() - print(json.dumps(engine_gems_data, indent=4)) + print(f'Gem Paths:\n{json.dumps(engine_gems_data, indent=4)}') if verbose > 0: - return print_manifest_json_data(engine_gems_data, 'gem.json', 'Gems', + return print_manifest_json_data(engine_gems_data, 'Gem Jsons', manifest.get_gem_json_data, 'gem_path') return 0 def print_engine_templates(verbose: int) -> int: engine_templates_data = manifest.get_engine_templates() - print(json.dumps(engine_templates_data, indent=4)) + print(f'Template Paths:\n{json.dumps(engine_templates_data, indent=4)}') if verbose > 0: - return print_manifest_json_data(engine_templates_data, 'template.json', 'Templates', + return print_manifest_json_data(engine_templates_data, 'Template Jsons', manifest.get_template_json_data, 'template_path') return 0 def print_engine_restricted(verbose: int) -> int: engine_restricted_data = manifest.get_engine_restricted() - print(json.dumps(engine_restricted_data, indent=4)) + print(f'Restricted Paths:\n{json.dumps(engine_restricted_data, indent=4)}') if verbose > 0: - return print_manifest_json_data(engine_restricted_data, 'restricted.json', 'Restricted', + return print_manifest_json_data(engine_restricted_data, 'Restricted Jsons', manifest.get_restricted_json_data, 'restricted_path') return 0 -def print_engine_external_subdirectories() -> int: +def print_engine_external_subdirectories(verbose: int) -> int: external_subdirs_data = manifest.get_engine_external_subdirectories() - print(json.dumps(external_subdirs_data, indent=4)) + print(f'External Subdirectories:\n{json.dumps(external_subdirs_data, indent=4)}') return 0 @@ -153,21 +159,21 @@ def print_project_gems(verbose: int, project_path: pathlib.Path, project_name: s return 1 project_gems_data = manifest.get_project_gems(project_path) - print(json.dumps(project_gems_data, indent=4)) + print(f'Gem Paths:\n{json.dumps(project_gems_data, indent=4)}') if verbose > 0: - return print_manifest_json_data(project_gems_data, 'gem.json', 'Gems', + return print_manifest_json_data(project_gems_data, 'Gems Jsons', manifest.get_gem_json_data, 'gem_path') return 0 -def print_project_external_subdirectories(project_path: pathlib.Path, project_name: str) -> int: +def print_project_external_subdirectories(verbose: int, project_path: pathlib.Path, project_name: str) -> int: project_path = get_project_path(project_path, project_name) if not project_path: return 1 external_subdirs_data = manifest.get_project_external_subdirectories(project_path) - print(json.dumps(external_subdirs_data, indent=4)) + print(f'External Subdirectories:\n{json.dumps(external_subdirs_data, indent=4)}') return 0 @@ -177,9 +183,9 @@ def print_project_templates(verbose: int, project_path: pathlib.Path, project_na return 1 project_templates_data = manifest.get_project_templates(project_path) - print(json.dumps(project_templates_data, indent=4)) + print(f'Template Paths:\n{json.dumps(project_templates_data, indent=4)}') if verbose > 0: - return print_manifest_json_data(project_templates_data, 'template.json', 'Templates', + return print_manifest_json_data(project_templates_data, 'Template Jsons', manifest.get_template_json_data, 'template_path') return 0 @@ -190,73 +196,118 @@ def print_project_restricted(verbose: int, project_path: pathlib.Path, project_n return 1 project_restricted_data = manifest.get_project_restricted(project_path) - print(json.dumps(project_restricted_data, indent=4)) + print(f'Restricted Paths:\n{json.dumps(project_restricted_data, indent=4)}') if verbose > 0: - return print_manifest_json_data(project_restricted_data, 'restricted.json', 'Restricted', + return print_manifest_json_data(project_restricted_data, 'Restricted Jsons', manifest.get_restricted_json_data, 'restricted_path') return 0 def print_all_projects(verbose: int) -> int: all_projects_data = manifest.get_all_projects() - print(json.dumps(all_projects_data, indent=4)) + print(f'Project Paths:\n{json.dumps(all_projects_data, indent=4)}') if verbose > 0: - return print_manifest_json_data(all_projects_data, 'project.json', 'Projects', + return print_manifest_json_data(all_projects_data, 'Project Jsons', manifest.get_project_json_data, 'project_path') return 0 -def print_all_gems(verbose: int) -> int: - all_gems_data = manifest.get_all_gems() - print(json.dumps(all_gems_data, indent=4)) +def print_all_gems(verbose: int, project_path: pathlib.Path = None, project_name: str = None) -> int: + all_gems = manifest.get_gems() + all_gems.extend(manifest.get_engine_gems()) + + # If a project path or project name is supplied query the gems from that project, otherwise query the gems from + # all projects + project_path = get_project_path(project_path, project_name) if project_path or project_name else None + projects = [project_path] if project_path else manifest.get_all_projects() + for project in projects: + all_gems.extend(manifest.get_project_gems(project)) + + # Filter out duplicates + all_gems = list(dict.fromkeys(all_gems)) + print(f'Gem Paths:\n{json.dumps(all_gems, indent=4)}') if verbose > 0: - return print_manifest_json_data(all_gems_data, 'gem.json', 'Gems', + return print_manifest_json_data(all_gems, 'Gem Jsons', manifest.get_gem_json_data, 'gem_path') return 0 -def print_all_external_subdirectories() -> int: - all_external_subdirectories_data = manifest.get_all_external_subdirectories() - print(json.dumps(all_external_subdirectories_data, indent=4)) +def print_all_external_subdirectories(verbose: int, project_path: pathlib.Path = None, project_name: str = None) -> int: + all_external_subdirectories = manifest.get_external_subdirectories() + all_external_subdirectories.extend(manifest.get_engine_external_subdirectories()) + + # If a project path or project name is supplied query the external subdirectories from that project, + # otherwise query the external subdirectories from all projects + project_path = get_project_path(project_path, project_name) if project_path or project_name else None + projects = [project_path] if project_path else manifest.get_all_projects() + for project in projects: + all_external_subdirectories.extend(manifest.get_project_external_subdirectories(project)) + + # Filter out duplicates + all_external_subdirectories = list(dict.fromkeys(all_external_subdirectories)) + print(f'External Subdirectories:\n{json.dumps(all_external_subdirectories, indent=4)}') return 0 -def print_all_templates(verbose: int) -> int: - all_templates_data = manifest.get_all_templates() - print(json.dumps(all_templates_data, indent=4)) + +def print_all_templates(verbose: int, project_path: pathlib.Path = None, project_name: str = None) -> int: + all_templates = manifest.get_templates() + all_templates.extend(manifest.get_engine_templates()) + + # If a project path or project name is supplied query the templates from that project, + # otherwise query the templates from all projects + project_path = get_project_path(project_path, project_name) if project_path or project_name else None + projects = [project_path] if project_path else manifest.get_all_projects() + for project in projects: + all_templates.extend(manifest.get_project_templates(project)) + + # Filter out duplicates + all_templates = list(dict.fromkeys(all_templates)) + print(f'Template Paths:\n{json.dumps(all_templates, indent=4)}') if verbose > 0: - return print_manifest_json_data(all_templates_data, 'template.json', 'Templates', + return print_manifest_json_data(all_templates, 'Template Jsons', manifest.get_template_json_data, 'template_path') return 0 -def print_all_restricted(verbose: int) -> int: - all_restricted_data = manifest.get_all_restricted() - print(json.dumps(all_restricted_data, indent=4)) +def print_all_restricted(verbose: int, project_path: pathlib.Path = None, project_name: str = None) -> int: + all_restricted = manifest.get_restricted() + all_restricted.extend(manifest.get_engine_restricted()) + + # If a project path or project name is supplied query the restricted from that project, + # otherwise query the restricted from all projects + project_path = get_project_path(project_path, project_name) if project_path or project_name else None + projects = [project_path] if project_path else manifest.get_all_projects() + for project in projects: + all_restricted.extend(manifest.get_project_restricted(project)) + + # Filter out duplicates + all_restricted = list(dict.fromkeys(all_restricted)) + print(f'Restricted Paths:\n{json.dumps(all_restricted, indent=4)}') if verbose > 0: - return print_manifest_json_data(all_restricted_data, 'restricted.json', 'Restricted', + return print_manifest_json_data(all_restricted, 'Restricted Jsons', manifest.get_restricted_json_data, 'restricted_path') return 0 -def print_manifest_json_data(uri_json_data: dict, json_filename: str, +def print_manifest_json_data(uri_json_data: list, print_prefix: str, get_json_func: callable, get_json_data_kw: str) -> int: print('\n') print(f"{print_prefix}================================================") for manifest_uri in uri_json_data: # if it's not local it should be in the cache - parsed_uri = urllib.parse.urlparse(manifest_uri) + parsed_uri = urllib.parse.urlparse(pathlib.Path(manifest_uri).as_posix()) if parsed_uri.scheme in ['http', 'https', 'ftp', 'ftps']: repo_sha256 = hashlib.sha256(manifest_uri.encode()) cache_folder = manifest.get_o3de_cache_folder() manifest_json_path = cache_folder / str(repo_sha256.hexdigest() + '.json') else: - manifest_json_path = pathlib.Path(manifest_uri).resolve() / json_filename + manifest_json_path = pathlib.Path(manifest_uri).resolve() - json_data = get_json_func(**{get_json_data_kwargs: manifest_json_path}) + json_data = get_json_func(**{get_json_data_kw: manifest_json_path}) if json_data: print(manifest_json_path) print(json.dumps(json_data, indent=4) + '\n') @@ -284,29 +335,30 @@ def print_repos_data(repos_data: dict) -> int: return 0 -def register_show_repos(verbose: int) -> None: +def print_repos(verbose: int) -> int: repos_data = manifest.get_repos() print(json.dumps(repos_data, indent=4)) if verbose > 0: - return print_repos_data(repos_data) == 0 + return print_repos_data(repos_data) return 0 -def register_show(verbose: int) -> None: +def register_show(verbose: int, project_path: pathlib.Path = None, project_name: str = None) -> int: json_data = manifest.load_o3de_manifest() print(f"{manifest.get_o3de_manifest()}:") print(json.dumps(json_data, indent=4)) - result = True + result = 0 if verbose > 0: - result = print_manifest_json_data(manifest.get_engines()) == 0 and result - result = print_manifest_json_data(manifest.get_all_projects()) == 0 and result - result = print_manifest_json_data(manifest.get_gems()) == 0 and result - result = print_manifest_json_data(manifest.get_all_templates()) == 0 and result - result = print_manifest_json_data(manifest.get_all_restricted()) == 0 and result - result = print_repos_data(manifest.get_repos()) == 0 and result - return 0 if result else 1 + result = print_engines(verbose) or result + result = print_all_projects(verbose) or result + result = print_all_gems(verbose, project_path, project_name) or result + result = print_all_templates(verbose, project_path, project_name) or result + result = print_all_restricted(verbose, project_path, project_name) or result + result = print_repos(verbose) or result + + return result def _run_register_show(args: argparse) -> int: @@ -321,6 +373,8 @@ def _run_register_show(args: argparse) -> int: return print_projects(args.verbose) elif args.gems: return print_gems(args.verbose) + elif args.external_subdirectories: + return print_external_subdirectories(args.verbose) elif args.templates: return print_templates(args.verbose) elif args.repos: @@ -333,7 +387,7 @@ def _run_register_show(args: argparse) -> int: elif args.engine_gems: return print_engine_gems(args.verbose) elif args.engine_external_subdirectories: - return print_engine_external_subdirectories() + return print_engine_external_subdirectories(args.verbose) elif args.engine_templates: return print_engine_templates(args.verbose) elif args.engine_restricted: @@ -342,7 +396,7 @@ def _run_register_show(args: argparse) -> int: elif args.project_gems: return print_project_gems(args.verbose, args.project_path, args.project_name) elif args.project_external_subdirectories: - return print_project_external_subdirectories(args.project_path, args.project_name) + return print_project_external_subdirectories(args.verbose, args.project_path, args.project_name) elif args.project_templates: return print_project_templates(args.verbose, args.project_path, args.project_name) elif args.project_restricted: @@ -351,16 +405,16 @@ def _run_register_show(args: argparse) -> int: elif args.all_projects: return print_all_projects(args.verbose) elif args.all_gems: - return print_all_gems(args.verbose) + return print_all_gems(args.verbose, args.project_path, args.project_name) elif args.all_external_subdirectories: - return print_all_external_subdirectories() + return print_all_external_subdirectories(args.verbose, args.project_path, args.project_name) elif args.all_templates: - return print_all_templates(args.verbose) + return print_all_templates(args.verbose, args.project_path, args.project_name) elif args.all_restricted: - return print_all_restricted(args.verbose) + return print_all_restricted(args.verbose, args.project_path, args.project_name) else: - return register_show(args.verbose) + return register_show(args.verbose, args.project_path, args.project_name) def add_parser_args(parser): @@ -393,6 +447,9 @@ def add_parser_args(parser): group.add_argument('-rs', '--restricted', action='store_true', required=False, default=False, help='Output the restricted directories registered in the global ~/.o3de/o3de_manifest.json.') + group.add_argument('-es', '--external-subdirectories', action='store_true', required=False, + default=False, + help='Output the external subdirectories registered in the global ~/.o3de/o3de_manifest.json.') group.add_argument('-ep', '--engine-projects', action='store_true', required=False, default=False, @@ -428,16 +485,28 @@ def add_parser_args(parser): help='Output all projects registered in the ~/.o3de/o3de_manifest.json and the current engine.json. Ignores repos.') group.add_argument('-ag', '--all-gems', action='store_true', required=False, default=False, - help='Output all gems registered in the ~/.o3de/o3de_manifest.json and the current engine.json. Ignores repos') + help='Output all gems registered in the ~/.o3de/o3de_manifest.json and the current engine.json.' + ' If --project-path or --project-name option is supplied, outputs gems registered in' + ' that project\'s project.json otherwise outputs registered gems from all registered projects.' + ' Ignores repos') group.add_argument('-at', '--all-templates', action='store_true', required=False, default=False, - help='Output all templates registered in the ~/.o3de/o3de_manifest.json and the current engine.json. Ignores repos.') + help='Output all templates registered in the ~/.o3de/o3de_manifest.json and the current engine.json.' + ' If --project-path or --project-name option is supplied, outputs templates registered in' + ' that project\'s project.json otherwise outputs registered templates from all registered' + ' projects. Ignores repos') group.add_argument('-ares', '--all-restricted', action='store_true', required=False, default=False, - help='Output all restricted directory registered in the ~/.o3de/o3de_manifest.json and the current engine.json.') + help='Output all restricted directory registered in the ~/.o3de/o3de_manifest.json and the current engine.json.' + ' If --project-path or --project-name option is supplied, outputs restricted' + ' directories registered in that project\'s project.json otherwise outputs restricted' + ' directories registered from all registered projects. Ignores repos') group.add_argument('-aes', '--all-external-subdirectories', action='store_true', default=False, - help='Output all external subdirectories registered in the ~/.o3de/o3de_manifest.json and the current engine.json.') + help='Output all external subdirectories registered in the ~/.o3de/o3de_manifest.json and the current engine.json.' + ' If --project-path or --project-name options is supplied, outputs external' + ' subdirectories registered in that project\'s project.json otherwise outputs external' + ' subdirectories registered from all registered projects. Ignores repos') parser.add_argument('-v', '--verbose', action='count', required=False, default=0, diff --git a/scripts/o3de/o3de/register.py b/scripts/o3de/o3de/register.py index fb91cb5bea..8481c5fae0 100644 --- a/scripts/o3de/o3de/register.py +++ b/scripts/o3de/o3de/register.py @@ -261,43 +261,6 @@ def add_engine_name_to_path(json_data: dict, engine_path: pathlib.Path, force: b return 0 -def register_engine_path(json_data: dict, - engine_path: pathlib.Path, - remove: bool = False, - force: bool = False) -> int: - if not engine_path: - logger.error(f'Engine path cannot be empty.') - return 1 - engine_path = pathlib.Path(engine_path).resolve() - - for engine_object in json_data.get('engines', []): - if isinstance(engine_object, dict): - engine_object_path = pathlib.Path(engine_object['path']).resolve() - else: - engine_object_path = pathlib.Path(engine_object).resolve() - if engine_object_path == engine_path: - json_data['engines'].remove(engine_object) - - if remove: - return remove_engine_name_to_path(json_data, engine_path) - - if not engine_path.is_dir(): - logger.error(f'Engine path {engine_path} does not exist.') - return 1 - - engine_json = engine_path / 'engine.json' - if not validation.valid_o3de_engine_json(engine_json): - logger.error(f'Engine json {engine_json} is not valid.') - return 1 - - engine_object = {} - engine_object.update({'path': engine_path.as_posix()}) - - json_data.setdefault('engines', []).insert(0, engine_object) - - return add_engine_name_to_path(json_data, engine_path, force) - - def register_o3de_object_path(json_data: dict, o3de_object_path: str or pathlib.Path, o3de_object_key: str, @@ -343,7 +306,7 @@ def register_o3de_object_path(json_data: dict, try: paths_to_remove.append(o3de_object_path.relative_to(save_path.parent)) except ValueError: - pass # It is OK relative path cannot be formed + pass # It is not an error if a relative path cannot be formed manifest_data[o3de_object_key] = list(filter(lambda p: pathlib.Path(p) not in paths_to_remove, manifest_data.setdefault(o3de_object_key, []))) @@ -358,7 +321,7 @@ def register_o3de_object_path(json_data: dict, manifest_json_path = o3de_object_path / o3de_json_filename if validation_func and not validation_func(manifest_json_path): - logger.error(f'o3de json {manifest_json_path} is not valid.') + logger.error(f'Manifest at path {manifest_json_path} is not valid.') return 1 # if there is a save path make it relative the directory containing o3de object json file @@ -374,6 +337,27 @@ def register_o3de_object_path(json_data: dict, return 0 +def register_engine_path(json_data: dict, + engine_path: pathlib.Path, + remove: bool = False, + force: bool = False) -> int: + # If the o3de_manifest.json 'engines' key is list containing dictionary entries, transform it to a list of strings + engine_list = json_data.get('engines', []) + + def transform_engine_dict_to_string(engine): return engine.get('path', '') if isinstance(engine, dict) else engine + json_data['engines'] = list(map(transform_engine_dict_to_string, engine_list)) + + result = register_o3de_object_path(json_data, engine_path, 'engines', 'engine.json', + validation.valid_o3de_engine_json, remove) + if result != 0: + return result + + if remove: + return remove_engine_name_to_path(json_data, engine_path) + + return add_engine_name_to_path(json_data, engine_path, force) + + def register_external_subdirectory(json_data: dict, external_subdir_path: pathlib.Path, remove: bool = False, @@ -677,37 +661,30 @@ def remove_invalid_o3de_projects(manifest_path: pathlib.Path = None) -> int: return result def remove_invalid_o3de_objects() -> None: - json_data = manifest.load_o3de_manifest() - - for engine_object in json_data.get('engines', []): - engine_path = engine_object.get('path', '') + for engine_path in manifest.get_engines(): if not validation.valid_o3de_engine_json(pathlib.Path(engine_path).resolve() / 'engine.json'): logger.warn(f"Engine path {engine_path} is invalid.") register(engine_path=engine_path, remove=True) remove_invalid_o3de_projects() - for gem in json_data.get('gems', []): - if not validation.valid_o3de_gem_json(pathlib.Path(gem).resolve() / 'gem.json'): - logger.warn(f"Gem path {gem} is invalid.") - register(gem_path=gem, remove=True) - - for external in json_data.get('external_subdirectories', []): + for external in manifest.get_external_subdirectories(): external = pathlib.Path(external).resolve() if not external.is_dir(): logger.warn(f"External subdirectory {external} is invalid.") register(engine_path=engine_path, external_subdir_path=external, remove=True) - for template in json_data.get('templates', []): + for template in manifest.get_templates(): if not validation.valid_o3de_template_json(pathlib.Path(template).resolve() / 'template.json'): logger.warn(f"Template path {template} is invalid.") register(template_path=template, remove=True) - for restricted in json_data.get('restricted', []): + for restricted in manifest.get_restricted(): if not validation.valid_o3de_restricted_json(pathlib.Path(restricted).resolve() / 'restricted.json'): logger.warn(f"Restricted path {restricted} is invalid.") register(restricted_path=restricted, remove=True) + json_data = manifest.load_o3de_manifest() default_engines_folder = pathlib.Path(json_data.get('default_engines_folder', manifest.get_o3de_engines_folder())).resolve() if not default_engines_folder.is_dir(): new_default_engines_folder = manifest.get_o3de_folder() / 'Engines' diff --git a/scripts/o3de/tests/CMakeLists.txt b/scripts/o3de/tests/CMakeLists.txt index 00d0774c45..1cd6eac7ee 100644 --- a/scripts/o3de/tests/CMakeLists.txt +++ b/scripts/o3de/tests/CMakeLists.txt @@ -65,4 +65,11 @@ ly_add_pytest( PATH ${CMAKE_CURRENT_LIST_DIR}/unit_test_engine_template.py TEST_SUITE smoke EXCLUDE_TEST_RUN_TARGET_FROM_IDE -) \ No newline at end of file +) + +ly_add_pytest( + NAME o3de_register_show + PATH ${CMAKE_CURRENT_LIST_DIR}/unit_test_print_registration.py + TEST_SUITE smoke + EXCLUDE_TEST_RUN_TARGET_FROM_IDE +) diff --git a/scripts/o3de/tests/unit_test_print_registration.py b/scripts/o3de/tests/unit_test_print_registration.py new file mode 100644 index 0000000000..7e3e75edcd --- /dev/null +++ b/scripts/o3de/tests/unit_test_print_registration.py @@ -0,0 +1,383 @@ +# +# Copyright (c) Contributors to the Open 3D Engine Project. +# For complete copyright and license terms please see the LICENSE at the root of this distribution. +# +# SPDX-License-Identifier: Apache-2.0 OR MIT +# +# + +import argparse +import json +import logging +import pytest +import pathlib +from unittest.mock import patch + +from o3de import print_registration + + +TEST_PROJECT_JSON_PAYLOAD = ''' +{ + "project_name": "MinimalProject", + "origin": "The primary repo for MinimalProject goes here: i.e. http://www.mydomain.com", + "license": "What license MinimalProject uses goes here: i.e. https://opensource.org/licenses/MIT", + "display_name": "MinimalProject", + "summary": "A short description of MinimalProject.", + "canonical_tags": [ + "Project" + ], + "user_tags": [ + "MinimalProject" + ], + "icon_path": "preview.png", + "engine": "o3de-install", + "external_subdirectories": [ + "D:/TestGem" + ] +} +''' + +TEST_ENGINE_JSON_PAYLOAD = ''' +{ + "engine_name": "o3de", + "restricted_name": "o3de", + "FileVersion": 1, + "O3DEVersion": "0.0.0.0", + "O3DECopyrightYear": 2021, + "O3DEBuildNumber": 0, + "external_subdirectories": [ + "Gems/TestGem2" + ], + "projects": [ + ], + "templates": [ + "Templates/MinimalProject" + ] +} +''' + +TEST_GEM_JSON_PAYLOAD = ''' +{ + "gem_name": "TestGem", + "display_name": "TestGem", + "license": "What license TestGem uses goes here: i.e. https://opensource.org/licenses/MIT", + "origin": "The primary repo for TestGem goes here: i.e. http://www.mydomain.com", + "type": "Code", + "summary": "A short description of TestGem.", + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "TestGem" + ], + "icon_path": "preview.png", + "requirements": "" +} +''' + +TEST_TEMPLATE_JSON_PAYLOAD = ''' +{ + "template_name": "AssetGem", + "origin": "The primary repo for AssetGem goes here: i.e. http://www.mydomain.com", + "license": "What license AssetGem uses goes here: i.e. https://opensource.org/licenses/MIT", + "display_name": "AssetGem", + "summary": "A short description of AssetGem template.", + "canonical_tags": [], + "user_tags": [ + "AssetGem" + ], + "icon_path": "preview.png", + "copyFiles": [ + { + "file": "CMakeLists.txt", + "origin": "CMakeLists.txt", + "isTemplated": true, + "isOptional": false + }, + { + "file": "gem.json", + "origin": "gem.json", + "isTemplated": true, + "isOptional": false + }, + { + "file": "preview.png", + "origin": "preview.png", + "isTemplated": false, + "isOptional": false + } + ], + "createDirectories": [ + { + "dir": "Assets", + "origin": "Assets" + } + ] +} +''' + +TEST_RESTRICTED_JSON_PAYLOAD = ''' +{ + "restricted_name": "o3de" +} +''' + +TEST_O3DE_MANIFEST_JSON_PAYLOAD = ''' +{ + "o3de_manifest_name": "testuser", + "origin": "C:/Users/testuser/.o3de", + "default_engines_folder": "C:/Users/testuser/.o3de/Engines", + "default_projects_folder": "C:/Users/testuser/.o3de/Projects", + "default_gems_folder": "C:/Users/testuser/.o3de/Gems", + "default_templates_folder": "C:/Users/testuser/.o3de/Templates", + "default_restricted_folder": "C:/Users/testuser/.o3de/Restricted", + "default_third_party_folder": "C:/Users/testuser/.o3de/3rdParty", + "projects": [ + "D:/MinimalProject" + ], + "external_subdirectories": [], + "templates": [], + "restricted": [], + "repos": [], + "engines": [ + "D:/o3de/o3de" + ], + "engines_path": { + "o3de": "D:/o3de/o3de" + } +} +''' + +class TestPrintRegistration: + @staticmethod + def load_manifest_json(): + return json.loads(TEST_O3DE_MANIFEST_JSON_PAYLOAD) + + @staticmethod + def get_engine_json_data(engine_path: pathlib.Path = None): + return json.loads(TEST_ENGINE_JSON_PAYLOAD) + + @staticmethod + def get_project_json_data(project_path: pathlib.Path = None): + return json.loads(TEST_PROJECT_JSON_PAYLOAD) + + @staticmethod + def get_gem_json_data(gem_path: pathlib.Path = None): + return json.loads(TEST_GEM_JSON_PAYLOAD) + + @staticmethod + def get_template_json_data(template_path: pathlib.Path = None): + return json.loads(TEST_TEMPLATE_JSON_PAYLOAD) + + @staticmethod + def get_restricted_json_data(restricted_path: pathlib.Path = None): + return json.loads(TEST_RESTRICTED_JSON_PAYLOAD) + + @pytest.mark.parametrize("project_path, verbose", [ + pytest.param(None, 0), + pytest.param(None, 1), + pytest.param(pathlib.Path("D:/MinimalProject"), 0), + pytest.param(pathlib.Path("D:/MinimalProject"), 1) + ]) + def test_print_registration_no_option(self, project_path, verbose): + parser = argparse.ArgumentParser() + + # Register the registration script subparsers with the current argument parser + print_registration.add_parser_args(parser) + arg_list = [] + if project_path: + arg_list += ['--project-path', project_path.as_posix()] + if verbose: + arg_list += ['-' + 'v' * verbose] + test_args = parser.parse_args(arg_list) + + with patch('o3de.manifest.load_o3de_manifest', side_effect=self.load_manifest_json) as load_manifest_patch, \ + patch('o3de.manifest.get_engine_json_data', + side_effect=self.get_engine_json_data) as get_engine_json_data_patch, \ + patch('o3de.manifest.get_project_json_data', + side_effect=self.get_project_json_data) as get_project_json_patch, \ + patch('o3de.manifest.get_gem_json_data', side_effect=self.get_gem_json_data) as get_gem_json_patch, \ + patch('o3de.manifest.get_template_json_data', side_effect=self.get_template_json_data) as get_template_json_patch, \ + patch('o3de.manifest.get_restricted_json_data', side_effect=self.get_restricted_json_data) as get_json_patch: + result = print_registration._run_register_show(test_args) + assert result == 0 + + + @pytest.mark.parametrize("engine_arg_option, verbose", [ + pytest.param("--this-engine", 0), + pytest.param("--this-engine", 1), + pytest.param("--engines", 0), + pytest.param("--engines", 1) + ]) + def test_print_engine_registration(self, engine_arg_option, verbose): + parser = argparse.ArgumentParser() + + # Register the registration script subparsers with the current argument parser + print_registration.add_parser_args(parser) + arg_list = [engine_arg_option] + if verbose: + arg_list += ['-' + 'v' * verbose] + test_args = parser.parse_args(arg_list) + + + with patch('o3de.manifest.load_o3de_manifest', side_effect=self.load_manifest_json) as load_manifest_patch, \ + patch('o3de.manifest.get_engine_json_data', side_effect=self.get_engine_json_data) as get_engine_json_data_patch: + result = print_registration._run_register_show(test_args) + assert result == 0 + + + @pytest.mark.parametrize("arg_option, verbose", [ + pytest.param("--projects", 0), + pytest.param("--projects", 1), + pytest.param("--engine-projects", 0), + pytest.param("--engine-projects", 1), + pytest.param("--all-projects", 0), + pytest.param("--all-projects", 1) + ]) + def test_print_project_registration(self, arg_option, verbose): + parser = argparse.ArgumentParser() + + # Register the registration script subparsers with the current argument parser + print_registration.add_parser_args(parser) + arg_list = [arg_option] + if verbose: + arg_list += ['-' + 'v' * verbose] + test_args = parser.parse_args(arg_list) + + + with patch('o3de.manifest.load_o3de_manifest', side_effect=self.load_manifest_json) as load_manifest_patch, \ + patch('o3de.manifest.get_project_json_data', side_effect=self.get_project_json_data) as get_json_data_patch: + result = print_registration._run_register_show(test_args) + assert result == 0 + + + @pytest.mark.parametrize("arg_option, project_path, verbose", [ + pytest.param("--gems", None, 0), + pytest.param("--gems", None, 1), + pytest.param("--engine-gems", None, 0), + pytest.param("--engine-gems", None, 1), + pytest.param("--project-gems", pathlib.Path("D:/MinimalProject"), 0), + pytest.param("--project-gems", pathlib.Path("D:/MinimalProject"), 1), + pytest.param("--all-gems", pathlib.Path("D:/MinimalProject"), 0), + pytest.param("--all-gems", None, 0), + pytest.param("--all-gems", pathlib.Path("D:/MinimalProject"), 1), + pytest.param("--all-gems", None, 1) + ]) + def test_print_gem_registration(self, arg_option, project_path, verbose): + parser = argparse.ArgumentParser() + + # Register the registration script subparsers with the current argument parser + print_registration.add_parser_args(parser) + arg_list = [arg_option] + if project_path: + arg_list += ['--project-path', project_path.as_posix()] + if verbose: + arg_list += ['-' + 'v' * verbose] + test_args = parser.parse_args(arg_list) + + # Patch the manifest.py function to locate gem.json files in external subdirectories + # to just return a fake path to a single test gem + def get_gems_from_subdirectories(external_subdirs: list) -> list: + return ["D:/TestGem"] + + with patch('o3de.manifest.load_o3de_manifest', side_effect=self.load_manifest_json) as load_manifest_patch, \ + patch('o3de.manifest.get_gem_json_data', side_effect=self.get_gem_json_data) as get_json_patch, \ + patch('o3de.manifest.get_project_json_data', side_effect=self.get_project_json_data) as get_project_json_patch, \ + patch('o3de.manifest.get_gems_from_subdirectories', side_effect=get_gems_from_subdirectories) as get_gems_from_subdirs_patch, \ + patch('o3de.print_registration.get_project_path', return_value=project_path) as get_project_path_patch: + result = print_registration._run_register_show(test_args) + assert result == 0 + + + @pytest.mark.parametrize("arg_option, project_path, verbose", [ + pytest.param("--templates", None, 0), + pytest.param("--templates", None, 1), + pytest.param("--engine-templates", None, 0), + pytest.param("--engine-templates", None, 1), + pytest.param("--project-templates", pathlib.Path("D:/MinimalProject"), 0), + pytest.param("--project-templates", pathlib.Path("D:/MinimalProject"), 1), + pytest.param("--all-templates", pathlib.Path("D:/MinimalProject"), 0), + pytest.param("--all-templates", None, 0), + pytest.param("--all-templates", pathlib.Path("D:/MinimalProject"), 1), + pytest.param("--all-templates", None, 1) + ]) + def test_print_template_registration(self, arg_option, project_path, verbose): + parser = argparse.ArgumentParser() + + # Register the registration script subparsers with the current argument parser + print_registration.add_parser_args(parser) + arg_list = [arg_option] + if project_path: + arg_list += ['--project-path', project_path.as_posix()] + if verbose: + arg_list += ['-' + 'v' * verbose] + test_args = parser.parse_args(arg_list) + + + with patch('o3de.manifest.load_o3de_manifest', side_effect=self.load_manifest_json) as load_manifest_patch, \ + patch('o3de.manifest.get_template_json_data', side_effect=self.get_template_json_data) as get_json_patch, \ + patch('o3de.manifest.get_project_json_data', side_effect=self.get_project_json_data) as get_project_json_patch, \ + patch('o3de.print_registration.get_project_path', return_value=project_path) as get_project_path_patch: + result = print_registration._run_register_show(test_args) + assert result == 0 + + + @pytest.mark.parametrize("arg_option, project_path, verbose", [ + pytest.param("--restricted", None, 0), + pytest.param("--restricted", None, 1), + pytest.param("--engine-restricted", None, 0), + pytest.param("--engine-restricted", None, 1), + pytest.param("--project-restricted", pathlib.Path("D:/MinimalProject"), 0), + pytest.param("--project-restricted", pathlib.Path("D:/MinimalProject"), 1), + pytest.param("--all-restricted", pathlib.Path("D:/MinimalProject"), 0), + pytest.param("--all-restricted", None, 0), + pytest.param("--all-restricted", pathlib.Path("D:/MinimalProject"), 1), + pytest.param("--all-restricted", None, 1) + ]) + def test_print_restricted_registration(self, arg_option, project_path, verbose): + parser = argparse.ArgumentParser() + + # Register the registration script subparsers with the current argument parser + print_registration.add_parser_args(parser) + arg_list = [arg_option] + if project_path: + arg_list += ['--project-path', project_path.as_posix()] + if verbose: + arg_list += ['-' + 'v' * verbose] + test_args = parser.parse_args(arg_list) + + with patch('o3de.manifest.load_o3de_manifest', side_effect=self.load_manifest_json) as load_manifest_patch, \ + patch('o3de.manifest.get_restricted_json_data', side_effect=self.get_restricted_json_data) as get_json_patch, \ + patch('o3de.manifest.get_project_json_data', side_effect=self.get_project_json_data) as get_project_json_patch, \ + patch('o3de.print_registration.get_project_path', return_value=project_path) as get_project_path_patch: + result = print_registration._run_register_show(test_args) + assert result == 0 + + + # Setting --verbose with the --*external-subdirectories option doesn't result in any additional output + # So it is only parameterized as 0 + @pytest.mark.parametrize("arg_option, project_path, verbose", [ + pytest.param("--external-subdirectories", None, 0), + pytest.param("--engine-external-subdirectories", None, 0), + pytest.param("--project-external-subdirectories", pathlib.Path("D:/MinimalProject"), 0), + pytest.param("--all-external-subdirectories", pathlib.Path("D:/MinimalProject"), 0), + pytest.param("--all-external-subdirectories", None, 0), + ]) + def test_print_external_subdirectories_registration(self, arg_option, project_path, verbose): + parser = argparse.ArgumentParser() + + # Register the registration script subparsers with the current argument parser + print_registration.add_parser_args(parser) + arg_list = [arg_option] + if project_path: + arg_list += ['--project-path', project_path.as_posix()] + if verbose: + arg_list += ['-' + 'v' * verbose] + test_args = parser.parse_args(arg_list) + + with patch('o3de.manifest.load_o3de_manifest', side_effect=self.load_manifest_json) as load_manifest_patch, \ + patch('o3de.manifest.get_project_json_data', + side_effect=self.get_project_json_data) as get_project_json_patch, \ + patch('o3de.print_registration.get_project_path', return_value=project_path) as get_project_path_patch: + result = print_registration._run_register_show(test_args) + assert result == 0 From 0040c7fd9b42b500be6783e198d3dc0eecd801f1 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Wed, 28 Jul 2021 14:48:06 -0700 Subject: [PATCH 091/160] Tweak test projects so the console window remains open (#2380) * tweak test projects so the console window remains open Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> * doing it for all test projects Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> * newline at the end of the file to make devs happy Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- cmake/LYTestWrappers.cmake | 9 +++++++++ cmake/Platform/Common/Directory.Build.props | 7 ++++++- cmake/Platform/Common/TestProject.props | 16 ++++++++++++++++ 3 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 cmake/Platform/Common/TestProject.props diff --git a/cmake/LYTestWrappers.cmake b/cmake/LYTestWrappers.cmake index 535f00f58d..efb19a20dd 100644 --- a/cmake/LYTestWrappers.cmake +++ b/cmake/LYTestWrappers.cmake @@ -219,8 +219,17 @@ function(ly_add_test) VS_DEBUGGER_COMMAND_ARGUMENTS "${test_arguments_line}" ) + # In the case where we are creating a custom target, we need to add dependency to the target + if(ly_add_test_PARENT_NAME AND NOT ${ly_add_test_NAME} STREQUAL ${ly_add_test_PARENT_NAME}) + ly_add_dependencies(${unaliased_test_name} ${ly_add_test_PARENT_NAME}) + endif() + endif() + # For test projects that are custom targets, pass a props file that sets the project as "Console" so + # it leaves the console open when it finishes + set_target_properties(${unaliased_test_name} PROPERTIES VS_USER_PROPS "${LY_ROOT_FOLDER}/cmake/Platform/Common/TestProject.props") + # Include additional dependencies if (ly_add_test_RUNTIME_DEPENDENCIES) ly_add_dependencies(${unaliased_test_name} ${ly_add_test_RUNTIME_DEPENDENCIES}) diff --git a/cmake/Platform/Common/Directory.Build.props b/cmake/Platform/Common/Directory.Build.props index 73aa984073..76e4b28922 100644 --- a/cmake/Platform/Common/Directory.Build.props +++ b/cmake/Platform/Common/Directory.Build.props @@ -17,7 +17,12 @@ SPDX-License-Identifier: Apache-2.0 OR MIT - TurnOffAllWarnings + + TurnOffAllWarnings + + \ No newline at end of file diff --git a/cmake/Platform/Common/TestProject.props b/cmake/Platform/Common/TestProject.props new file mode 100644 index 0000000000..dff509b7ff --- /dev/null +++ b/cmake/Platform/Common/TestProject.props @@ -0,0 +1,16 @@ + + + + + + + + Console + + + From f0cafd0e9dc336e1f80a05dfacc8b7288b574b82 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Wed, 28 Jul 2021 15:53:14 -0700 Subject: [PATCH 092/160] Create RUN target as helpers for the project-centric workflow (#2520) * Create RUN target as helpers for the project-centric workflow Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> * typo fix Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> * rename target as ".Imported" and create "" as the metatarget that is used for debugging and building in o3de Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Editor/CMakeLists.txt | 2 + cmake/Platform/Common/Install_common.cmake | 43 ++++++++++++++++++---- cmake/SettingsRegistry.cmake | 7 +--- cmake/install/InstalledTarget.in | 2 + 4 files changed, 42 insertions(+), 12 deletions(-) diff --git a/Code/Editor/CMakeLists.txt b/Code/Editor/CMakeLists.txt index fe694f165a..fca16a2093 100644 --- a/Code/Editor/CMakeLists.txt +++ b/Code/Editor/CMakeLists.txt @@ -163,6 +163,8 @@ ly_add_target( editor_files.cmake PLATFORM_INCLUDE_FILES Platform/${PAL_PLATFORM_NAME}/editor_${PAL_PLATFORM_NAME_LOWERCASE}.cmake + TARGET_PROPERTIES + LY_INSTALL_GENERATE_RUN_TARGET TRUE BUILD_DEPENDENCIES PRIVATE 3rdParty::Qt::Core diff --git a/cmake/Platform/Common/Install_common.cmake b/cmake/Platform/Common/Install_common.cmake index 2157a632c7..612358f938 100644 --- a/cmake/Platform/Common/Install_common.cmake +++ b/cmake/Platform/Common/Install_common.cmake @@ -10,6 +10,15 @@ include(cmake/FileUtil.cmake) set(CMAKE_INSTALL_MESSAGE NEVER) # Simplify messages to reduce output noise +define_property(TARGET PROPERTY LY_INSTALL_GENERATE_RUN_TARGET + BRIEF_DOCS "Defines if a \"RUN\" targets should be created when installing this target Gem" + FULL_DOCS [[ + Property which is set on targets that should generate a "RUN" + target when installed. This \"RUN\" target helps to run the + binary from the installed location directly from the IDE. + ]] +) + ly_set(CMAKE_INSTALL_DEFAULT_COMPONENT_NAME Core) cmake_path(RELATIVE_PATH CMAKE_RUNTIME_OUTPUT_DIRECTORY BASE_DIRECTORY ${CMAKE_BINARY_DIR} OUTPUT_VARIABLE runtime_output_directory) @@ -117,15 +126,19 @@ function(ly_setup_target OUTPUT_CONFIGURED_TARGET ALIAS_TARGET_NAME absolute_tar set(NAMESPACE_PLACEHOLDER "") set(NAME_PLACEHOLDER ${TARGET_NAME}) endif() + get_target_property(should_create_helper ${TARGET_NAME} LY_INSTALL_GENERATE_RUN_TARGET) + if(should_create_helper) + set(NAME_PLACEHOLDER ${NAME_PLACEHOLDER}.Imported) + endif() set(TARGET_TYPE_PLACEHOLDER "") - get_target_property(target_type ${NAME_PLACEHOLDER} TYPE) + get_target_property(target_type ${TARGET_NAME} TYPE) # Remove the _LIBRARY since we dont need to pass that to ly_add_targets string(REPLACE "_LIBRARY" "" TARGET_TYPE_PLACEHOLDER ${target_type}) # For HEADER_ONLY libs we end up generating "INTERFACE" libraries, need to specify HEADERONLY instead string(REPLACE "INTERFACE" "HEADERONLY" TARGET_TYPE_PLACEHOLDER ${TARGET_TYPE_PLACEHOLDER}) if(TARGET_TYPE_PLACEHOLDER STREQUAL "MODULE") - get_target_property(gem_module ${NAME_PLACEHOLDER} GEM_MODULE) + get_target_property(gem_module ${TARGET_NAME} GEM_MODULE) if(gem_module) set(TARGET_TYPE_PLACEHOLDER "GEM_MODULE") endif() @@ -158,7 +171,6 @@ function(ly_setup_target OUTPUT_CONFIGURED_TARGET ALIAS_TARGET_NAME absolute_tar unset(RUNTIME_DEPENDENCIES_PLACEHOLDER) endif() - get_target_property(inteface_build_dependencies_props ${TARGET_NAME} INTERFACE_LINK_LIBRARIES) unset(INTERFACE_BUILD_DEPENDENCIES_PLACEHOLDER) if(inteface_build_dependencies_props) @@ -182,6 +194,23 @@ function(ly_setup_target OUTPUT_CONFIGURED_TARGET ALIAS_TARGET_NAME absolute_tar list(REMOVE_DUPLICATES INTERFACE_BUILD_DEPENDENCIES_PLACEHOLDER) string(REPLACE ";" "\n" INTERFACE_BUILD_DEPENDENCIES_PLACEHOLDER "${INTERFACE_BUILD_DEPENDENCIES_PLACEHOLDER}") + # If the target is an executable/application, add a custom target so we can debug the target in project-centric workflow + if(should_create_helper) + string(REPLACE ".Imported" "" RUN_TARGET_NAME ${NAME_PLACEHOLDER}) + set(target_types_with_debugging_helper EXECUTABLE APPLICATION) + if(NOT target_type IN_LIST target_types_with_debugging_helper) + message(FATAL_ERROR "Cannot generate a RUN target for ${TARGET_NAME}, type is ${target_type}") + endif() + set(TARGET_RUN_HELPER +"add_custom_target(${RUN_TARGET_NAME}) +set_target_properties(${RUN_TARGET_NAME} PROPERTIES + FOLDER \"CMakePredefinedTargets/SDK\" + VS_DEBUGGER_COMMAND \$> + VS_DEBUGGER_COMMAND_ARGUMENTS \"--project-path=\${LY_DEFAULT_PROJECT_PATH}\" +)" +) + endif() + # Config file set(target_file_contents "# Generated by O3DE install\n\n") if(NOT target_type STREQUAL INTERFACE_LIBRARY) @@ -194,13 +223,13 @@ function(ly_setup_target OUTPUT_CONFIGURED_TARGET ALIAS_TARGET_NAME absolute_tar set(target_location "\${LY_ROOT_FOLDER}/${library_output_directory}/${PAL_PLATFORM_NAME}/$/${target_library_output_subdirectory}/$") elseif(target_type STREQUAL SHARED_LIBRARY) string(APPEND target_file_contents -"set_property(TARGET ${TARGET_NAME} +"set_property(TARGET ${NAME_PLACEHOLDER} APPEND_STRING PROPERTY IMPORTED_IMPLIB $<$$:\"\${LY_ROOT_FOLDER}/${archive_output_directory}/${PAL_PLATFORM_NAME}/$/$\"$ ) ") string(APPEND target_file_contents -"set_property(TARGET ${TARGET_NAME} +"set_property(TARGET ${NAME_PLACEHOLDER} PROPERTY IMPORTED_IMPLIB_$> \"\${LY_ROOT_FOLDER}/${archive_output_directory}/${PAL_PLATFORM_NAME}/$/$\" ) @@ -212,11 +241,11 @@ function(ly_setup_target OUTPUT_CONFIGURED_TARGET ALIAS_TARGET_NAME absolute_tar if(target_location) string(APPEND target_file_contents -"set_property(TARGET ${TARGET_NAME} +"set_property(TARGET ${NAME_PLACEHOLDER} APPEND_STRING PROPERTY IMPORTED_LOCATION $<$$:${target_location}$ ) -set_property(TARGET ${TARGET_NAME} +set_property(TARGET ${NAME_PLACEHOLDER} PROPERTY IMPORTED_LOCATION_$> ${target_location} ) diff --git a/cmake/SettingsRegistry.cmake b/cmake/SettingsRegistry.cmake index b740fefd25..ebf2254dc6 100644 --- a/cmake/SettingsRegistry.cmake +++ b/cmake/SettingsRegistry.cmake @@ -159,10 +159,6 @@ function(ly_delayed_generate_settings_registry) message(FATAL_ERROR "Dependency ${gem_target} from ${target} does not exist") endif() - get_property(has_manually_added_dependencies TARGET ${gem_target} PROPERTY MANUALLY_ADDED_DEPENDENCIES SET) - get_target_property(target_type ${gem_target} TYPE) - - ly_get_gem_module_root(gem_module_root ${gem_target}) file(RELATIVE_PATH gem_module_root_relative_to_engine_root ${LY_ROOT_FOLDER} ${gem_module_root}) @@ -180,7 +176,8 @@ function(ly_delayed_generate_settings_registry) list(JOIN target_gem_dependencies_names ",\n" target_gem_dependencies_names) string(CONFIGURE ${gems_json_template} gem_json @ONLY) get_target_property(is_imported ${target} IMPORTED) - if(is_imported) + get_target_property(target_type ${target} TYPE) + if(is_imported OR target_type STREQUAL UTILITY) unset(target_dir) foreach(conf IN LISTS CMAKE_CONFIGURATION_TYPES) string(TOUPPER ${conf} UCONF) diff --git a/cmake/install/InstalledTarget.in b/cmake/install/InstalledTarget.in index 0503fd5f2b..a4f4fa4763 100644 --- a/cmake/install/InstalledTarget.in +++ b/cmake/install/InstalledTarget.in @@ -17,6 +17,8 @@ ly_add_target( @RUNTIME_DEPENDENCIES_PLACEHOLDER@ ) +@TARGET_RUN_HELPER@ + set(configs @CMAKE_CONFIGURATION_TYPES@) foreach(config ${configs}) include("@NAME_PLACEHOLDER@_${config}.cmake" OPTIONAL) From d7a4b0d930f92335328a99b3d398a18497628817 Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Wed, 28 Jul 2021 16:51:25 -0700 Subject: [PATCH 093/160] fix for double asset registration and multiple outs from loop nodes Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com> --- Gems/GraphCanvas/Code/Source/GraphCanvas.cpp | 29 - Gems/GraphCanvas/Code/Source/GraphCanvas.h | 2 - .../Grammar/AbstractCodeModel.cpp | 2 +- ...orEachMultipleOutSyntaxOnEach.scriptcanvas | 2215 +++++++++++++++++ .../Tests/ScriptCanvas_RuntimeInterpreted.cpp | 4 +- 5 files changed, 2218 insertions(+), 34 deletions(-) create mode 100644 Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_ForEachMultipleOutSyntaxOnEach.scriptcanvas diff --git a/Gems/GraphCanvas/Code/Source/GraphCanvas.cpp b/Gems/GraphCanvas/Code/Source/GraphCanvas.cpp index 33cc99e2d5..c5333152a0 100644 --- a/Gems/GraphCanvas/Code/Source/GraphCanvas.cpp +++ b/Gems/GraphCanvas/Code/Source/GraphCanvas.cpp @@ -191,7 +191,6 @@ namespace GraphCanvas void GraphCanvasSystemComponent::Activate() { - RegisterAssetHandler(); RegisterTranslationBuilder(); AzFramework::AssetCatalogEventBus::Handler::BusConnect(); @@ -386,34 +385,6 @@ namespace GraphCanvas AZ::Data::AssetCatalogRequestBus::Broadcast(&AZ::Data::AssetCatalogRequestBus::Events::EnumerateAssets, nullptr, collectAssetsCb, postEnumerateCb); } - void GraphCanvasSystemComponent::RegisterAssetHandler() - { - AZ::Data::AssetType assetType(azrtti_typeid()); - if (AZ::Data::AssetManager::Instance().GetHandler(assetType)) - { - return; // Asset Type already handled - } - - auto* catalogBus = AZ::Data::AssetCatalogRequestBus::FindFirstHandler(); - if (catalogBus) - { - // Register asset types the asset DB should query our catalog for. - catalogBus->AddAssetType(assetType); - - // Build the catalog (scan). - catalogBus->AddExtension(".names"); - } - - m_assetHandler = AZStd::make_unique(); - AZ::Data::AssetManager::Instance().RegisterHandler(m_assetHandler.get(), assetType); - - // Use AssetCatalog service to register ScriptEvent asset type and extension - AZ::Data::AssetCatalogRequestBus::Broadcast(&AZ::Data::AssetCatalogRequests::AddAssetType, assetType); - AZ::Data::AssetCatalogRequestBus::Broadcast(&AZ::Data::AssetCatalogRequests::EnableCatalogForAsset, assetType); - AZ::Data::AssetCatalogRequestBus::Broadcast(&AZ::Data::AssetCatalogRequests::AddExtension, TranslationAsset::GetFileFilter()); - - } - void GraphCanvasSystemComponent::UnregisterAssetHandler() { if (m_assetHandler) diff --git a/Gems/GraphCanvas/Code/Source/GraphCanvas.h b/Gems/GraphCanvas/Code/Source/GraphCanvas.h index a68052d5e1..7a4d9677ab 100644 --- a/Gems/GraphCanvas/Code/Source/GraphCanvas.h +++ b/Gems/GraphCanvas/Code/Source/GraphCanvas.h @@ -82,8 +82,6 @@ namespace GraphCanvas AZStd::unique_ptr m_assetHandler; void RegisterTranslationBuilder(); - - void RegisterAssetHandler(); void UnregisterAssetHandler(); TranslationAssetWorker m_translationAssetWorker; AZStd::vector m_translationAssets; diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/AbstractCodeModel.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/AbstractCodeModel.cpp index 883e15cd29..3e4a425a6e 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/AbstractCodeModel.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/AbstractCodeModel.cpp @@ -3230,7 +3230,7 @@ namespace ScriptCanvas auto valueSlot = forEachNodeSC->GetSlot(forEachNodeSC->GetValueSlotId()); AZ_Assert(valueSlot, "no value slot in for each node"); - lastExecution->AddChild({}); + lastExecution->AddChild({ &loopSlot, {}, nullptr }); auto outputValue = CreateOutputData(lastExecution, lastExecution->ModChild(0), *valueSlot); lastExecution->ModChild(0).m_output.push_back({ valueSlot, outputValue }); diff --git a/Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_ForEachMultipleOutSyntaxOnEach.scriptcanvas b/Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_ForEachMultipleOutSyntaxOnEach.scriptcanvas new file mode 100644 index 0000000000..40e548eae0 --- /dev/null +++ b/Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_ForEachMultipleOutSyntaxOnEach.scriptcanvas @@ -0,0 +1,2215 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/ScriptCanvasTesting/Code/Tests/ScriptCanvas_RuntimeInterpreted.cpp b/Gems/ScriptCanvasTesting/Code/Tests/ScriptCanvas_RuntimeInterpreted.cpp index df29a56fd5..5999cf9250 100644 --- a/Gems/ScriptCanvasTesting/Code/Tests/ScriptCanvas_RuntimeInterpreted.cpp +++ b/Gems/ScriptCanvasTesting/Code/Tests/ScriptCanvas_RuntimeInterpreted.cpp @@ -84,9 +84,9 @@ public: } }; -TEST_F(ScriptCanvasTestFixture, ProveError) +TEST_F(ScriptCanvasTestFixture, ForEachMultipleOutSyntaxOnEach) { - EXPECT_TRUE(false); + RunUnitTestGraph("LY_SC_UnitTest_ForEachMultipleOutSyntaxOnEach"); } TEST_F(ScriptCanvasTestFixture, EntityIdInputForOnGraphStart) From eefc448dceb9aec1771e7112899e36ea97eb058e Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Wed, 28 Jul 2021 17:48:11 -0700 Subject: [PATCH 094/160] remove stack tracer change and attempt to restore SC tests Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com> --- .../Platform/Windows/AzCore/Debug/StackTracer_Windows.cpp | 2 +- Gems/ScriptCanvasTesting/Code/CMakeLists.txt | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Code/Framework/AzCore/Platform/Windows/AzCore/Debug/StackTracer_Windows.cpp b/Code/Framework/AzCore/Platform/Windows/AzCore/Debug/StackTracer_Windows.cpp index a24d359bc9..d2cdac84c7 100644 --- a/Code/Framework/AzCore/Platform/Windows/AzCore/Debug/StackTracer_Windows.cpp +++ b/Code/Framework/AzCore/Platform/Windows/AzCore/Debug/StackTracer_Windows.cpp @@ -39,7 +39,7 @@ namespace AZ { struct SymbolStorageDynamicallyLoadedModules { size_t m_size; - DynamicallyLoadedModuleInfo m_modules[1024]; + DynamicallyLoadedModuleInfo m_modules[256]; SymbolStorageDynamicallyLoadedModules() : m_size(0) diff --git a/Gems/ScriptCanvasTesting/Code/CMakeLists.txt b/Gems/ScriptCanvasTesting/Code/CMakeLists.txt index dada433772..23c9627e83 100644 --- a/Gems/ScriptCanvasTesting/Code/CMakeLists.txt +++ b/Gems/ScriptCanvasTesting/Code/CMakeLists.txt @@ -113,7 +113,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) ) ly_add_googletest( NAME Gem::ScriptCanvasTesting.Editor.Tests - TEST_SUITE smoke ) endif() From 43dfffa3fd138ddbf0b29c1f0e7fa3ff46b30f4d Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Wed, 28 Jul 2021 20:58:49 -0700 Subject: [PATCH 095/160] fix dangling component variables on cleared script, fix EntityIDNode reflection Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com> --- .../Code/Builder/ScriptCanvasBuilder.cpp | 1 + .../EditorScriptCanvasComponent.cpp | 2 + .../ScriptCanvas/Libraries/Entity/Entity.cpp | 6 +-- .../ScriptCanvas/Libraries/Entity/Entity.h | 1 - .../Libraries/Entity/EntityIDNodes.h | 50 ------------------- .../Libraries/Entity/EntityNodes.h | 27 +++++++++- .../Code/scriptcanvasgem_common_files.cmake | 1 - 7 files changed, 30 insertions(+), 58 deletions(-) delete mode 100644 Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Entity/EntityIDNodes.h diff --git a/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilder.cpp b/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilder.cpp index 6a5344ed9b..73e18a356c 100644 --- a/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilder.cpp +++ b/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilder.cpp @@ -30,6 +30,7 @@ namespace ScriptCanvasBuilder { m_source.Reset(); m_variables.clear(); + m_overrides.clear(); m_entityIds.clear(); m_dependencies.clear(); } diff --git a/Gems/ScriptCanvas/Code/Editor/Components/EditorScriptCanvasComponent.cpp b/Gems/ScriptCanvas/Code/Editor/Components/EditorScriptCanvasComponent.cpp index 9135f348b3..dbc525e8e1 100644 --- a/Gems/ScriptCanvas/Code/Editor/Components/EditorScriptCanvasComponent.cpp +++ b/Gems/ScriptCanvas/Code/Editor/Components/EditorScriptCanvasComponent.cpp @@ -474,6 +474,8 @@ namespace ScriptCanvasEditor OnScriptCanvasAssetReady(memoryAsset); } } + + AzToolsFramework::ToolsApplicationNotificationBus::Broadcast(&AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_EntireTree_NewContent); } void EditorScriptCanvasComponent::OnStartPlayInEditor() diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Entity/Entity.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Entity/Entity.cpp index 1cce8cb3d3..b2bfd25031 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Entity/Entity.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Entity/Entity.cpp @@ -23,10 +23,10 @@ namespace ScriptCanvas // The DataElementNode is being copied purposefully in this statement to clone the data AZ::SerializeContext::DataElementNode baseNodeElement = rootNodeElement.GetSubElement(nodeElementIndex); - if (!rootNodeElement.Convert(context, azrtti_typeid())) + if (!rootNodeElement.Convert(context, azrtti_typeid())) { AZ_Error("Script Canvas", false, "Unable to convert old Entity::IsValid function node(%s) to new EntityId::IsValid function node(%s)", - rootNodeElement.GetId().ToString().data(), azrtti_typeid().ToString().data()); + rootNodeElement.GetId().ToString().data(), azrtti_typeid().ToString().data()); return false; } @@ -79,14 +79,12 @@ namespace ScriptCanvas void Entity::InitNodeRegistry(NodeRegistry& nodeRegistry) { - EntityIDNodes::Registrar::AddToRegistry(nodeRegistry); EntityNodes::Registrar::AddToRegistry(nodeRegistry); } AZStd::vector Entity::GetComponentDescriptors() { AZStd::vector descriptors; - EntityIDNodes::Registrar::AddDescriptors(descriptors); EntityNodes::Registrar::AddDescriptors(descriptors); return descriptors; } diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Entity/Entity.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Entity/Entity.h index dcfae2db9f..f8171a3fe0 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Entity/Entity.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Entity/Entity.h @@ -12,5 +12,4 @@ // shared code #include "RotateMethod.h" -#include "EntityIDNodes.h" #include "EntityNodes.h" diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Entity/EntityIDNodes.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Entity/EntityIDNodes.h deleted file mode 100644 index fa6cd9981e..0000000000 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Entity/EntityIDNodes.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -#pragma once - -#include -#include -#include - -namespace ScriptCanvas -{ - namespace EntityIDNodes - { - using namespace Data; - static const char* k_categoryName = "Entity/Entity"; - - AZ_INLINE BooleanType IsValid(const EntityIDType& source) - { - return source.IsValid(); - } - SCRIPT_CANVAS_GENERIC_FUNCTION_NODE(IsValid, k_categoryName, "{0ED8A583-A397-4657-98B1-433673323F21}", "returns true if Source is valid, else false", "Source"); - - AZ_INLINE StringType ToString(const EntityIDType& source) - { - return source.ToString(); - } - SCRIPT_CANVAS_GENERIC_FUNCTION_NODE(ToString, k_categoryName, "{B094DCAE-15D5-42A3-8D8C-5BD68FE6E356}", "returns a string representation of Source", "Source"); - - AZ_INLINE BooleanType IsActive(const EntityIDType& entityId) - { - AZ::Entity* entity = nullptr; - AZ::ComponentApplicationBus::BroadcastResult(entity, &AZ::ComponentApplicationRequests::FindEntity, entityId); - return (entity && entity->GetState() == AZ::Entity::State::Active); - } - SCRIPT_CANVAS_GENERIC_FUNCTION_NODE(IsActive, k_categoryName, "{DF5240FD-6510-4C24-8382-9515C4B0C7B4}", "returns true if entity with the provided Id is valid and active.", "Entity Id"); - - using Registrar = RegistrarGeneric< - IsValidNode, - ToStringNode, - IsActiveNode - >; - - } -} - diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Entity/EntityNodes.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Entity/EntityNodes.h index dcad06d2c7..701c3a0869 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Entity/EntityNodes.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Entity/EntityNodes.h @@ -21,7 +21,7 @@ namespace ScriptCanvas namespace EntityNodes { using namespace Data; - static const char* k_categoryName = "Entity/Transform"; + static const char* k_categoryName = "Entity/Entity"; template AZ_INLINE void DefaultScale(Node& node) { SetDefaultValuesByIndex::_(node, Data::One()); } @@ -59,10 +59,33 @@ namespace ScriptCanvas } SCRIPT_CANVAS_GENERIC_FUNCTION_NODE_WITH_DEFAULTS(GetEntityUp, DefaultScale<1>, k_categoryName, "{96B86F3F-F022-4611-9AEA-175EA952C562}", "returns the up direction vector from the specified entity's world transform, scaled by a given value (Lumberyard uses Z up, right handed)", "EntityId", "Scale"); + AZ_INLINE BooleanType IsActive(const EntityIDType& entityId) + { + AZ::Entity* entity = nullptr; + AZ::ComponentApplicationBus::BroadcastResult(entity, &AZ::ComponentApplicationRequests::FindEntity, entityId); + return (entity && entity->GetState() == AZ::Entity::State::Active); + } + SCRIPT_CANVAS_GENERIC_FUNCTION_NODE(IsActive, k_categoryName, "{DF5240FD-6510-4C24-8382-9515C4B0C7B4}", "returns true if entity with the provided Id is valid and active.", "Entity Id"); + + AZ_INLINE BooleanType IsValid(const EntityIDType& source) + { + return source.IsValid(); + } + SCRIPT_CANVAS_GENERIC_FUNCTION_NODE(IsValid, k_categoryName, "{0ED8A583-A397-4657-98B1-433673323F21}", "returns true if Source is valid, else false", "Source"); + + AZ_INLINE StringType ToString(const EntityIDType& source) + { + return source.ToString(); + } + SCRIPT_CANVAS_GENERIC_FUNCTION_NODE(ToString, k_categoryName, "{B094DCAE-15D5-42A3-8D8C-5BD68FE6E356}", "returns a string representation of Source", "Source"); + using Registrar = RegistrarGeneric< GetEntityRightNode, GetEntityForwardNode, - GetEntityUpNode + GetEntityUpNode, + IsActiveNode, + IsValidNode, + ToStringNode >; } } diff --git a/Gems/ScriptCanvas/Code/scriptcanvasgem_common_files.cmake b/Gems/ScriptCanvas/Code/scriptcanvasgem_common_files.cmake index e1c12b7068..84ba39cc72 100644 --- a/Gems/ScriptCanvas/Code/scriptcanvasgem_common_files.cmake +++ b/Gems/ScriptCanvas/Code/scriptcanvasgem_common_files.cmake @@ -297,7 +297,6 @@ set(FILES Include/ScriptCanvas/Libraries/Core/UnaryOperator.h Include/ScriptCanvas/Libraries/Entity/Entity.cpp Include/ScriptCanvas/Libraries/Entity/Entity.h - Include/ScriptCanvas/Libraries/Entity/EntityIDNodes.h Include/ScriptCanvas/Libraries/Entity/EntityNodes.h Include/ScriptCanvas/Libraries/Entity/RotateMethod.cpp Include/ScriptCanvas/Libraries/Entity/RotateMethod.h From 5bb8a17d795bc775ee2080b24d2437df039cc0ea Mon Sep 17 00:00:00 2001 From: Benjamin Jillich Date: Thu, 29 Jul 2021 14:17:29 +0200 Subject: [PATCH 096/160] Removed MCore::Quaternion.h/.inl/.cpp files Signed-off-by: Benjamin Jillich --- .../Code/MCore/Source/Quaternion.cpp | 604 ------------------ Gems/EMotionFX/Code/MCore/Source/Quaternion.h | 386 ----------- .../Code/MCore/Source/Quaternion.inl | 96 --- Gems/EMotionFX/Code/MCore/mcore_files.cmake | 3 - 4 files changed, 1089 deletions(-) delete mode 100644 Gems/EMotionFX/Code/MCore/Source/Quaternion.cpp delete mode 100644 Gems/EMotionFX/Code/MCore/Source/Quaternion.h delete mode 100644 Gems/EMotionFX/Code/MCore/Source/Quaternion.inl diff --git a/Gems/EMotionFX/Code/MCore/Source/Quaternion.cpp b/Gems/EMotionFX/Code/MCore/Source/Quaternion.cpp deleted file mode 100644 index 2f7db53d2c..0000000000 --- a/Gems/EMotionFX/Code/MCore/Source/Quaternion.cpp +++ /dev/null @@ -1,604 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -// include required headers -#include "Quaternion.h" -#include - -namespace MCore -{ - // spherical quadratic interpolation - Quaternion Quaternion::Squad(const Quaternion& p, const Quaternion& a, const Quaternion& b, const Quaternion& q, float t) - { - Quaternion q0(p.Slerp(q, t)); - Quaternion q1(a.Slerp(b, t)); - return q0.Slerp(q1, 2.0f * t * (1.0f - t)); - } - - - // returns the approximately normalized linear interpolated result [t must be between 0..1] - Quaternion Quaternion::NLerp(const Quaternion& to, float t) const - { - AZ_Assert(t > -MCore::Math::epsilon && t < (1 + MCore::Math::epsilon), "Expected t to be between 0..1"); - static const float weightCloseToOne = 1.0f - MCore::Math::epsilon; - - // Early out for boundaries (common cases) - if (t < MCore::Math::epsilon) - { - return *this; - } - else if (t > weightCloseToOne) - { - return to; - } - - #if AZ_TRAIT_USE_PLATFORM_SIMD_SSE - __m128 num1, num2, num3, num4, fromVec, toVec; - const float omt = 1.0f - t; - float dot; - - // perform dot product between this quat and the 'to' quat - num4 = _mm_setzero_ps(); // sets sum to zero - fromVec = _mm_loadu_ps(&x); // - toVec = _mm_loadu_ps(&to.x); // - num3 = _mm_mul_ps(fromVec, toVec); // performs multiplication num3 = a[3]*b[3] a[2]*b[2] a[1]*b[1] a[0]*b[0] - num3 = _mm_hadd_ps(num3, num3); // performs horizontal addition - num3= a[3]*b[3]+ a[2]*b[2] a[1]*b[1]+a[0]*b[0] a[3]*b[3]+ a[2]*b[2] a[1]*b[1]+a[0]*b[0] - num4 = _mm_add_ps(num4, num3); // performs vertical addition - num4 = _mm_hadd_ps(num4, num4); - _mm_store_ss(&dot, num4); // store the dot result - - if (dot < 0.0f) - { - t = -t; - } - - // calculate interpolated value - num2 = _mm_load_ps1(&omt); - num3 = _mm_load_ps1(&t); - num4 = _mm_mul_ps(fromVec, num2); // omt * xyzw - num1 = _mm_mul_ps(toVec, num3); // t * to.xyzw - num2 = _mm_add_ps(num1, num4); // interpolated value - - // calculate the square length - num4 = _mm_setzero_ps(); - num3 = _mm_mul_ps(num2, num2); // square length - num1 = _mm_hadd_ps(num3, num3); - num4 = _mm_add_ps(num4, num1); - num3 = _mm_hadd_ps(num4, num4); - //num4 = _mm_rsqrt_ps( num3 ); // length (argh, too inaccurate on some models) - - AZStd::aligned_storage::type numFloatStorage; - float* numFloat = reinterpret_cast(&numFloatStorage); - - _mm_store_ps(numFloat, num3); - const float invLen = Math::InvSqrt(numFloat[0]); - num4 = _mm_load_ps1(&invLen); - - // calc inverse length, which normalizes everything - num1 = _mm_mul_ps(num2, num4); - - _mm_store_ps(numFloat, num1); - return Quaternion(numFloat[0], numFloat[1], numFloat[2], numFloat[3]); - #else - const float omt = 1.0f - t; - const float dot = x * to.x + y * to.y + z * to.z + w * to.w; - if (dot < 0.0f) - { - t = -t; - } - - // calculate the interpolated values - const float newX = (omt * x + t * to.x); - const float newY = (omt * y + t * to.y); - const float newZ = (omt * z + t * to.z); - const float newW = (omt * w + t * to.w); - - // calculate the inverse length - // const float invLen = 1.0f / Math::FastSqrt( newX*newX + newY*newY + newZ*newZ + newW*newW ); - // const float invLen = Math::FastInvSqrt( newX*newX + newY*newY + newZ*newZ + newW*newW ); - const float invLen = Math::InvSqrt(newX * newX + newY * newY + newZ * newZ + newW * newW); - - // return the normalized linear interpolation - return Quaternion(newX * invLen, - newY * invLen, - newZ * invLen, - newW * invLen); - #endif - } - - - - // returns the linear interpolated result [t must be between 0..1] - Quaternion Quaternion::Lerp(const Quaternion& to, float t) const - { - const float omt = 1.0f - t; - const float cosom = x * to.x + y * to.y + z * to.z + w * to.w; - if (cosom < 0.0f) - { - t = -t; - } - - // return the linear interpolation - return Quaternion(omt * x + t * to.x, - omt * y + t * to.y, - omt * z + t * to.z, - omt * w + t * to.w); - } - - - - // quaternion from an axis and angle - Quaternion::Quaternion(const AZ::Vector3& axis, float angle) - { - const float squaredLength = axis.GetLengthSq(); - if (squaredLength > 0.0f) - { - const float halfAngle = angle * 0.5f; - const float sinScale = Math::Sin(halfAngle) / Math::Sqrt(squaredLength); - x = axis.GetX() * sinScale; - y = axis.GetY() * sinScale; - z = axis.GetZ() * sinScale; - w = Math::Cos(halfAngle); - } - else - { - x = y = z = 0.0f; - w = 1.0f; - } - } - - - - // quaternion from a spherical rotation - Quaternion::Quaternion(const AZ::Vector2& spherical, float angle) - { - const float latitude = spherical.GetX(); - const float longitude = spherical.GetY(); - - const float s = Math::Sin(angle / 2.0f); - const float c = Math::Cos(angle / 2.0f); - - const float sin_lat = Math::Sin(latitude); - const float cos_lat = Math::Cos(latitude); - - const float sin_lon = Math::Sin(longitude); - const float cos_lon = Math::Cos(longitude); - - x = s * cos_lat * sin_lon; - y = s * sin_lat; - z = s * sin_lat * cos_lon; - w = c; - } - - - // convert to an axis and angle - void Quaternion::ToAxisAngle(AZ::Vector3* axis, float* angle) const - { - *angle = 2.0f * Math::ACos(w); - - const float sinHalfAngle = Math::Sin(*angle * 0.5f); - if (sinHalfAngle > 0.0f) - { - const float invS = 1.0f / sinHalfAngle; - axis->Set(x * invS, y * invS, z * invS); - } - else - { - axis->Set(0.0f, 1.0f, 0.0f); - *angle = 0.0f; - } - } - - - // converts from unit quaternion to spherical rotation angles - void Quaternion::ToSpherical(AZ::Vector2* spherical, float* angle) const - { - AZ::Vector3 axis; - ToAxisAngle(&axis, angle); - - float longitude; - if (axis.GetX() * axis.GetX() + axis.GetZ() * axis.GetZ() < 0.0001f) - { - longitude = 0.0f; - } - else - { - longitude = Math::ATan2(axis.GetX(), axis.GetZ()); - if (longitude < 0.0f) - { - longitude += Math::twoPi; - } - } - - spherical->SetX(-Math::ASin(axis.GetY())); - spherical->SetY(longitude); - } - - - - // setup the quaternion from a roll, pitch and yaw - Quaternion& Quaternion::SetEuler(float pitch, float yaw, float roll) - { - // METHOD #1: - const float halfYaw = yaw * 0.5f; - const float halfPitch = pitch * 0.5f; - const float halfRoll = roll * 0.5f; - - const float cY = Math::Cos(halfYaw); - const float sY = Math::Sin(halfYaw); - const float cP = Math::Cos(halfPitch); - const float sP = Math::Sin(halfPitch); - const float cR = Math::Cos(halfRoll); - const float sR = Math::Sin(halfRoll); - - x = cY * sP * cR - sY * cP * sR; - y = cY * sP * sR + sY * cP * cR; - z = cY * cP * sR - sY * sP * cR; - w = cY * cP * cR + sY * sP * sR; - - // Normalize(); // we might be able to leave the normalize away, but better safe than not, this is more robust :) - - return *this; - - /* - - // METHOD #2: - Quaternion Qx(Vector3(sP, 0, 0), cP); - Quaternion Qy(Vector3(0, sY, 0), cY); - Quaternion Qz(Vector3(0, 0, sR), cR); - - Quaternion result = Qx * Qy * Qz; - - x = result.x; - y = result.y; - z = result.z; - w = result.w; - - return *this; - */ - } - - - - // convert the quaternion to a matrix - Matrix Quaternion::ToMatrix() const - { - Matrix m; - - const float xx = x * x; - const float xy = x * y, yy = y * y; - const float xz = x * z, yz = y * z, zz = z * z; - const float xw = x * w, yw = y * w, zw = z * w, ww = w * w; - - MMAT(m, 0, 0) = +xx - yy - zz + ww; - MMAT(m, 0, 1) = +xy + zw + xy + zw; - MMAT(m, 0, 2) = +xz - yw + xz - yw; - MMAT(m, 0, 3) = 0.0f; - MMAT(m, 1, 0) = +xy - zw + xy - zw; - MMAT(m, 1, 1) = -xx + yy - zz + ww; - MMAT(m, 1, 2) = +yz + xw + yz + xw; - MMAT(m, 1, 3) = 0.0f; - MMAT(m, 2, 0) = +xz + yw + xz + yw; - MMAT(m, 2, 1) = +yz - xw + yz - xw; - MMAT(m, 2, 2) = -xx - yy + zz + ww; - MMAT(m, 2, 3) = 0.0f; - MMAT(m, 3, 0) = 0.0f; - MMAT(m, 3, 1) = 0.0f; - MMAT(m, 3, 2) = 0.0f; - MMAT(m, 3, 3) = 1.0f; - - return m; - } - - - - // construct the quaternion from a given rotation matrix - Quaternion Quaternion::ConvertFromMatrix(const Matrix& m) - { - Quaternion result; - - const float trace = MMAT(m, 0, 0) + MMAT(m, 1, 1) + MMAT(m, 2, 2); - if (trace > 0.0f /*Math::epsilon*/) - { - const float s = 0.5f / Math::Sqrt(trace + 1.0f); - result.w = 0.25f / s; - result.x = (MMAT(m, 1, 2) - MMAT(m, 2, 1)) * s; - result.y = (MMAT(m, 2, 0) - MMAT(m, 0, 2)) * s; - result.z = (MMAT(m, 0, 1) - MMAT(m, 1, 0)) * s; - } - else - { - if (MMAT(m, 0, 0) > MMAT(m, 1, 1) && MMAT(m, 0, 0) > MMAT(m, 2, 2)) - { - const float s = 2.0f * Math::Sqrt(1.0f + MMAT(m, 0, 0) - MMAT(m, 1, 1) - MMAT(m, 2, 2)); - const float oneOverS = 1.0f / s; - result.x = 0.25f * s; - result.y = (MMAT(m, 1, 0) + MMAT(m, 0, 1)) * oneOverS; - result.z = (MMAT(m, 2, 0) + MMAT(m, 0, 2)) * oneOverS; - result.w = (MMAT(m, 1, 2) - MMAT(m, 2, 1)) * oneOverS; - } - else - if (MMAT(m, 1, 1) > MMAT(m, 2, 2)) - { - const float s = 2.0f * Math::Sqrt(1.0f + MMAT(m, 1, 1) - MMAT(m, 0, 0) - MMAT(m, 2, 2)); - const float oneOverS = 1.0f / s; - result.x = (MMAT(m, 1, 0) + MMAT(m, 0, 1)) * oneOverS; - result.y = 0.25f * s; - result.z = (MMAT(m, 2, 1) + MMAT(m, 1, 2)) * oneOverS; - result.w = (MMAT(m, 2, 0) - MMAT(m, 0, 2)) * oneOverS; - } - else - { - const float s = 2.0f * Math::Sqrt(1.0f + MMAT(m, 2, 2) - MMAT(m, 0, 0) - MMAT(m, 1, 1)); - const float oneOverS = 1.0f / s; - result.x = (MMAT(m, 2, 0) + MMAT(m, 0, 2)) * oneOverS; - result.y = (MMAT(m, 2, 1) + MMAT(m, 1, 2)) * oneOverS; - result.z = 0.25f * s; - result.w = (MMAT(m, 0, 1) - MMAT(m, 1, 0)) * oneOverS; - } - } - - /* - const float trace = MMAT(m,0,0) + MMAT(m,1,1) + MMAT(m,2,2) + 1.0f; - if (trace > Math::epsilon) - { - const float s = 0.5f / Math::Sqrt(trace); - result.w = 0.25f / s; - result.x = ( MMAT(m,1,2) - MMAT(m,2,1) ) * s; - result.y = ( MMAT(m,2,0) - MMAT(m,0,2) ) * s; - result.z = ( MMAT(m,0,1) - MMAT(m,1,0) ) * s; - } - else - { - if (MMAT(m,0,0) > MMAT(m,1,1) && MMAT(m,0,0) > MMAT(m,2,2)) - { - const float s = 2.0f * Math::Sqrt( 1.0f + MMAT(m,0,0) - MMAT(m,1,1) - MMAT(m,2,2)); - const float oneOverS = 1.0f / s; - result.x = 0.25f * s; - result.y = (MMAT(m,1,0) + MMAT(m,0,1) ) * oneOverS; - result.z = (MMAT(m,2,0) + MMAT(m,0,2) ) * oneOverS; - result.w = (MMAT(m,2,1) - MMAT(m,1,2) ) * oneOverS; - } - else - if (MMAT(m,1,1) > MMAT(m,2,2)) - { - const float s = 2.0f * Math::Sqrt( 1.0f + MMAT(m,1,1) - MMAT(m,0,0) - MMAT(m,2,2)); - const float oneOverS = 1.0f / s; - result.x = (MMAT(m,1,0) + MMAT(m,0,1) ) * oneOverS; - result.y = 0.25f * s; - result.z = (MMAT(m,2,1) + MMAT(m,1,2) ) * oneOverS; - result.w = (MMAT(m,2,0) - MMAT(m,0,2) ) * oneOverS; - } - else - { - const float s = 2.0f * Math::Sqrt( 1.0f + MMAT(m,2,2) - MMAT(m,0,0) - MMAT(m,1,1) ); - const float oneOverS = 1.0f / s; - result.x = (MMAT(m,2,0) + MMAT(m,0,2) ) * oneOverS; - result.y = (MMAT(m,2,1) + MMAT(m,1,2) ) * oneOverS; - result.z = 0.25f * s; - result.w = (MMAT(m,1,0) - MMAT(m,0,1) ) * oneOverS; - } - } - */ - return result; - } - - - // convert a quaternion to euler angles (in degrees) - AZ::Vector3 Quaternion::ToEuler() const - { - /* - // METHOD #1: - - Vector3 euler; - - float matrix[3][3]; - float cx,sx; - float cy,sy,yr; - float cz,sz; - - matrix[0][0] = 1.0 - (2.0 * y * y) - (2.0 * z * z); - matrix[1][0] = (2.0 * x * y) + (2.0 * w * z); - matrix[2][0] = (2.0 * x * z) - (2.0 * w * y); - matrix[2][1] = (2.0 * y * z) + (2.0 * w * x); - matrix[2][2] = 1.0 - (2.0 * x * x) - (2.0 * y * y); - - sy = -matrix[2][0]; - cy = Math::Sqrt(1 - (sy * sy)); - yr = Math::ATan2(sy,cy); - euler.y = yr; - - // avoid divide by zero only where y ~90 or ~270 - if (sy != 1.0 && sy != -1.0) - { - cx = matrix[2][2] / cy; - sx = matrix[2][1] / cy; - euler.x = Math::ATan2(sx,cx); - - cz = matrix[0][0] / cy; - sz = matrix[1][0] / cy; - euler.z = Math::ATan2(sz,cz); - } - else - { - matrix[1][1] = 1.0 - (2.0 * x * x) - (2.0 * z * z); - matrix[1][2] = (2.0 * y * z) - (2.0 * w * x); - cx = matrix[1][1]; - sx = -matrix[1][2]; - euler.x = Math::ATan2(sx,cx); - - cz = 1.0; - sz = 0.0; - euler.z = Math::ATan2(sz,cz); - } - - return euler; - */ - - /* - // METHOD #2: - Matrix mat = ToMatrix(); - - // - float cy = Math::Sqrt(mat.m44[0][0]*mat.m44[0][0] + mat.m44[0][1]*mat.m44[0][1]); - if (cy > 16.0*Math::epsilon) - { - result.x = -atan2(mat.m44[1][2], mat.m44[2][2]); - result.y = -atan2(-mat.m44[0][2], cy); - result.z = -atan2(mat.m44[0][1], mat.m44[0][0]); - } - else - { - result.x = -atan2(-mat.m44[2][1], mat.m44[1][1]); - result.y = -atan2(-mat.m44[0][2], cy); - result.z = 0.0; - } - - return result; - */ - - // METHOD #3 (without conversion to matrix first): - // TODO: safety checks? - float m00 = 1.0f - (2.0f * ((y * y) + z * z)); - float m01 = 2.0f * (x * y + w * z); - - AZ::Vector3 result( - Math::ATan2(2.0f * (y * z + w * x), 1.0f - (2.0f * ((x * x) + (y * y)))), - Math::ATan2(-2.0f * (x * z - w * y), Math::Sqrt((m00 * m00) + (m01 * m01))), - Math::ATan2(m01, m00) - ); - - return result; - } - - float Quaternion::GetEulerZ() const - { - float m00 = 1.0f - (2.0f * ((y * y) + z * z)); - float m01 = 2.0f * (x * y + w * z); - return Math::ATan2(m01, m00); - } - - // returns the spherical interpolated result [t must be between 0..1] - Quaternion Quaternion::Slerp(const Quaternion& to, float t) const - { - float cosom = (x * to.x) + (y * to.y) + (z * to.z) + (w * to.w); - float scale0, scale1, scale1sign = 1.0f; - - if (cosom < 0.0f) - { - scale1sign = -1.0f; - cosom *= -1.0f; - } - - if ((1.0 - cosom) > Math::epsilon) - { - const float omega = Math::ACos(cosom); - const float sinOmega = Math::Sin(omega); - const float oosinom = 1.0f / sinOmega; - scale0 = Math::Sin((1.0f - t) * omega) * oosinom; - scale1 = Math::Sin(t * omega) * oosinom; - } - else - { - scale0 = 1.0f - t; - scale1 = t; - } - - scale1 *= scale1sign; - - return Quaternion(scale0 * x + scale1 * to.x, - scale0 * y + scale1 * to.y, - scale0 * z + scale1 * to.z, - scale0 * w + scale1 * to.w); - } - - - // set as delta rotation - Quaternion Quaternion::CreateDeltaRotation(const AZ::Vector3& fromVector, const AZ::Vector3& toVector) - { - Quaternion q; - q.SetAsDeltaRotation(fromVector, toVector); - return q; - } - - - // set as delta rotation but limited - Quaternion Quaternion::CreateDeltaRotation(const AZ::Vector3& fromVector, const AZ::Vector3& toVector, float maxAngleRadians) - { - Quaternion q; - q.SetAsDeltaRotation(fromVector, toVector, maxAngleRadians); - return q; - } - - - // set as delta rotation - void Quaternion::SetAsDeltaRotation(const AZ::Vector3& fromVector, const AZ::Vector3& toVector) - { - // check if we are in parallel or not - const float dot = fromVector.Dot(toVector); - if (dot < 0.99999f) // we have rotated compared to the forward direction - { - const float angleRadians = Math::ACos(dot); - const AZ::Vector3 rotAxis = fromVector.Cross(toVector); - *this = Quaternion(rotAxis, angleRadians); - } - else - { - Identity(); - } - } - - - // set as delta rotation, but limited - void Quaternion::SetAsDeltaRotation(const AZ::Vector3& fromVector, const AZ::Vector3& toVector, float maxAngleRadians) - { - // check if we are in parallel or not - const float dot = fromVector.Dot(toVector); - if (dot < 0.99999f) // we have rotated compared to the forward direction - { - const float angleRadians = Math::ACos(dot); - const float rotAngle = Min(angleRadians, maxAngleRadians); - const AZ::Vector3 rotAxis = fromVector.Cross(toVector); - *this = Quaternion(rotAxis, rotAngle); - } - else - { - Identity(); - } - } - - - /* - Decompose the rotation on to 2 parts. - 1. Twist - rotation around the "direction" vector - 2. Swing - rotation around axis that is perpendicular to "direction" vector - The rotation can be composed back by - rotation = swing * twist - - has singularity in case of swing_rotation close to 180 degrees rotation. - if the input quaternion is of non-unit length, the outputs are non-unit as well - otherwise, outputs are both unit - */ - void Quaternion::DecomposeSwingTwist(const AZ::Vector3& direction, Quaternion* outSwing, Quaternion* outTwist) const - { - AZ::Vector3 rotAxis(x, y, z); - AZ::Vector3 p = Projected(rotAxis, direction); // return projection v1 on to v2 (parallel component) - outTwist->Set(p.GetX(), p.GetY(), p.GetZ(), w); - outTwist->Normalize(); - *outSwing = *this * outTwist->Conjugated(); - } - - - // rotate the current quaternion and renormalize it - void Quaternion::RotateFromTo(const AZ::Vector3& fromVector, const AZ::Vector3& toVector) - { - *this = CreateDeltaRotation(fromVector, toVector) * *this; - Normalize(); - } -} // namespace MCore - diff --git a/Gems/EMotionFX/Code/MCore/Source/Quaternion.h b/Gems/EMotionFX/Code/MCore/Source/Quaternion.h deleted file mode 100644 index bbee1d8265..0000000000 --- a/Gems/EMotionFX/Code/MCore/Source/Quaternion.h +++ /dev/null @@ -1,386 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -#pragma once - -// include required headers -#include -#include -#include "StandardHeaders.h" -#include "FastMath.h" -#include "Vector.h" -#include "Matrix4.h" -#include "Algorithms.h" - - -namespace MCore -{ - /** - * Depracated. Please use AZ::Quaternion instead. - * The quaternion class in MCore. - * Quaternions are mostly used to represent rotations in 3D applications. - * The advantages of quaternions over matrices are that they take up less space and that interpolation between - * two quaternions is easier to perform. Instead of a 3x3 rotation matrix, which is 9 floats or doubles, a quaternion - * only uses 4 floats or doubles. This template/class provides you with methods to perform all kind of operations on - * these quaternions, from interpolation to conversion to matrices and other rotation representations. - */ - class MCORE_API Quaternion - { - public: - AZ_TYPE_INFO(MCore::Quaternion, "{1807CD22-EBB5-45E8-8113-3B1DABB53F12}") - - /** - * Default constructor. Sets x, y and z to 0 and w to 1. - */ - MCORE_INLINE Quaternion() - : x(0.0f) - , y(0.0f) - , z(0.0f) - , w(1.0f) {} - - /** - * Constructor which sets the x, y, z and w. - * @param xVal The value of x. - * @param yVal The value of y. - * @param zVal The value of z. - * @param wVal The value of w. - */ - MCORE_INLINE Quaternion(float xVal, float yVal, float zVal, float wVal) - : x(xVal) - , y(yVal) - , z(zVal) - , w(wVal) {} - - /** - * Copy constructor. Copies the x, y, z, w values from the other quaternion. - * @param other The quaternion to copy the attributes from. - */ - MCORE_INLINE Quaternion(const Quaternion& other) - : x(other.x) - , y(other.y) - , z(other.z) - , w(other.w) {} - - /** - * Constructor which creates a quaternion from a pitch, yaw and roll. - * @param pitch Rotation around the x-axis, in radians. - * @param yaw Rotation around the y-axis, in radians. - * @param roll Rotation around the z-axis, in radians. - */ - MCORE_INLINE Quaternion(float pitch, float yaw, float roll) { SetEuler(pitch, yaw, roll); } - - /** - * Constructor which takes a matrix as input parameter. - * This converts the rotation of the specified matrix into a quaternion. Please keep in mind that the matrix may NOT contain - * any scaling, so if it does, please normalize your matrix first! - * @param matrix The matrix to initialize the quaternion from. - */ - MCORE_INLINE Quaternion(const Matrix& matrix) { FromMatrix(matrix); } - - /** - * Constructor which creates a quaternion from a spherical rotation. - * @param spherical The spherical coordinates in radians, which creates an axis to rotate around. - * @param angle The angle to rotate around this axis. - */ - Quaternion(const AZ::Vector2& spherical, float angle); - - /** - * Constructor which creates a quaternion from an axis and angle. - * @param axis The axis to rotate around. - * @param angle The angle in radians to rotate around the given axis. - */ - Quaternion(const AZ::Vector3& axis, float angle); - - /** - * Set the quaternion x/y/z/w component values. - * @param vx The value of x. - * @param vy The value of y. - * @param vz The value of z. - * @param vw The value of w. - */ - MCORE_INLINE void Set(float vx, float vy, float vz, float vw) { x = vx; y = vy; z = vz; w = vw; } - - /** - * Calculates the square length of the quaternion. - * @result The square length (length*length). - */ - MCORE_INLINE float SquareLength() const { return (x * x + y * y + z * z + w * w); } - - /** - * Calculates the length of the quaternion. - * It's safe, since it prevents a division by 0. - * @result The length of the quaternion. - */ - MCORE_INLINE float Length() const; - - /** - * Performs a dot product on the quaternions. - * @param q The quaternion to multiply (dot product) this quaternion with. - * @result The quaternion which is the result of the dot product. - */ - MCORE_INLINE float Dot(const Quaternion& q) const { return (x * q.x + y * q.y + z * q.z + w * q.w); } - - /** - * Normalize the quaternion. - * @result The normalized quaternion. It modifies itself, so no new quaternion is returned. - */ - MCORE_INLINE Quaternion& Normalize(); - - /** - * Sets the quaternion to identity. Where x, y and z are set to 0 and w is set to 1. - * @result The quaternion, now set to identity. - */ - MCORE_INLINE Quaternion& Identity() { x = 0.0f; y = 0.0f; z = 0.0f; w = 1.0f; return *this; } - - /** - * Calculate the inversed version of this quaternion. - * @result The inversed version of this quaternion. - */ - MCORE_INLINE Quaternion& Inverse() { const float len = 1.0f / SquareLength(); x = -x * len; y = -y * len; z = -z * len; w = w * len; return *this; } - - /** - * Conjugate this quaternion. - * @result Returns itself Conjugated. - */ - MCORE_INLINE Quaternion& Conjugate() { x = -x; y = -y; z = -z; return *this; } - - /** - * Calculate the inversed version of this quaternion. - * @result The inversed version of this quaternion. - */ - MCORE_INLINE Quaternion Inversed() const { const float len = 1.0f / SquareLength(); return Quaternion(-x * len, -y * len, -z * len, w * len); } - - /** - * Returns the normalized version of this quaternion. - * @result The normalized version of this quaternion. - */ - MCORE_INLINE Quaternion Normalized() const { Quaternion result(*this); result.Normalize(); return result; } - - /** - * Return the conjugated version of this quaternion. - * @result The conjugated version of this quaternion. - */ - MCORE_INLINE Quaternion Conjugated() const { return Quaternion(-x, -y, -z, w); } - - /** - * Calculate the exponent of this quaternion. - * @result The resulting quaternion of the exp. - */ - MCORE_INLINE Quaternion Exp() const { const float r = Math::Sqrt(x * x + y * y + z * z); const float expW = Math::Exp(w); const float s = (r >= 0.00001f) ? expW* Math::Sin(r) / r : 0.0f; return Quaternion(s * x, s * y, s * z, expW * Math::Cos(r)); } - - /** - * Calculate the log of the quaternion. - * @result The resulting quaternion of the log. - */ - MCORE_INLINE Quaternion LogN() const { const float r = Math::Sqrt(x * x + y * y + z * z); float t = (r > 0.00001f) ? Math::ATan2(r, w) / r : 0.0f; return Quaternion(t * x, t * y, t * z, 0.5f * Math::Log(SquareLength())); } - - /** - * Calculate and get the right basis vector. - * @result The basis vector pointing to the right. This assumes x+ points to the right. - */ - MCORE_INLINE AZ::Vector3 CalcRightAxis() const; - - /** - * Calculate and get the up basis vector. - * @result The basis vector pointing upwards. This assumes z+ points up. - */ - MCORE_INLINE AZ::Vector3 CalcUpAxis() const; - - /** - * Calculate and get the forward basis vector. - * @result The basis vector pointing forward. This assumes y+ points forward, into the depth. - */ - MCORE_INLINE AZ::Vector3 CalcForwardAxis() const; - - /** - * Initialize the current quaternion from a specified matrix. - * Please note that the matrix may not contain any scaling! - * So make sure the matrix has been normalized before, if it contains any scale. - * @param m The matrix to initialize the quaternion from. - */ - MCORE_INLINE void FromMatrix(const Matrix& m) { *this = Quaternion::ConvertFromMatrix(m); } - - /** - * Setup the quaternion from a pitch, yaw and roll. - * @param pitch The rotation around the x-axis, in radians. - * @param yaw The rotation around the y-axis, in radians. - * @param roll The rotation around the z-axis in radians. - * @result The quaternion, now initialized with the given pitch, yaw, roll rotation. - */ - Quaternion& SetEuler(float pitch, float yaw, float roll); - - /** - * Convert the quaternion to an axis and angle. Which represents a rotation of the resulting angle around the resulting axis. - * @param axis Pointer to the vector to store the axis in. - * @param angle Pointer to the variable to store the angle in (will be in radians). - */ - void ToAxisAngle(AZ::Vector3* axis, float* angle) const; - - /** - * Convert the quaternion to a spherical rotation. - * @param spherical A pointer to the 2D vector to store the spherical coordinates in radians, which build the axis. - * @param angle The pointer to the variable to store the angle around this axis in radians. - */ - void ToSpherical(AZ::Vector2* spherical, float* angle) const; - - /** - * Extract the euler angles in radians. - * The x component of the resulting vector represents the rotation around the x-axis (pitch). - * The y component results the rotation around the y-axis (yaw) and the z component represents - * the rotation around the z-axis (roll). - * @result The 3D vector containing the euler angles in radians, around each axis. - */ - AZ::Vector3 ToEuler() const; - - /** - * Returns the angle of rotation about the z axis. This is same as - * the z component of the vector returned by the ToEuler method. It - * is just more efficient to call this when one is interested only in rotation about the z axis. - * @result The angle of rotation about z axis in radians. - */ - float GetEulerZ() const; - - /** - * Convert this quaternion into a matrix. - * @result The matrix representing the rotation of this quaternion. - */ - Matrix ToMatrix() const; - - /** - * Convert a matrix into a quaternion. - * Please keep in mind that the specified matrix may NOT contain any scaling! - * So make sure the matrix has been normalized before, if it contains any scale. - * @param m The matrix to extract the rotation from. - * @result The quaternion, now containing the rotation of the given matrix, in quaternion form. - */ - static Quaternion ConvertFromMatrix(const Matrix& m); - - /** - * Create a delta rotation that rotates one vector onto another vector. - * @param fromVector The normalized vector to start from. This must be normalized! - * @param toVector The normalized vector to rotate towards. This must be normalized as well! - * @result The delta rotation quaternion. - */ - static Quaternion CreateDeltaRotation(const AZ::Vector3& fromVector, const AZ::Vector3& toVector); - - /** - * Create a delta rotation that rotates one vector onto another vector. - * If the angle is bigger than the max allowed angle that is specified it will rotate with an angle of the maximum specified angle. - * So if the angle between the vectors is 40 degrees and you maxAngleRadians equals 10 degrees (in radians) it will only rotate 10 degrees. - * @param fromVector The normalized vector to start from. This must be normalized! - * @param toVector The normalized vector to rotate towards. This must be normalized as well! - * @param maxAngleRadians The maximum rotation angle on the plane defined by the two vectors. This cannot be more than Math::pi (180 degrees). - * @result The delta rotation quaternion. - */ - static Quaternion CreateDeltaRotation(const AZ::Vector3& fromVector, const AZ::Vector3& toVector, float maxAngleRadians); - - /** - * Init this quaternion as a delta rotation that rotates one vector onto another vector. - * @param fromVector The normalized vector to start from. This must be normalized! - * @param toVector The normalized vector to rotate towards. This must be normalized as well! - */ - void SetAsDeltaRotation(const AZ::Vector3& fromVector, const AZ::Vector3& toVector); - - /** - * Init this quaternion as a delta rotation that rotates one vector onto another vector. - * If the angle is bigger than the max allowed angle that is specified it will rotate with an angle of the maximum specified angle. - * So if the angle between the vectors is 40 degrees and you maxAngleRadians equals 10 degrees (in radians) it will only rotate 10 degrees. - * @param fromVector The normalized vector to start from. This must be normalized! - * @param toVector The normalized vector to rotate towards. This must be normalized as well! - * @param maxAngleRadians The maximum rotation angle on the plane defined by the two vectors. This cannot be more than Math::pi (180 degrees). - */ - void SetAsDeltaRotation(const AZ::Vector3& fromVector, const AZ::Vector3& toVector, float maxAngleRadians); - - /** - * Rotate this current quaternion using a given delta that is calculated from two vectors. - * The rotation axis used is the cross product between the from and to vector. The rotation angle is the angle between these two vectors. - * @param fromVector The current direction vector, must be normalized. - * @param toVector The desired new direction vector, must be normalized. - */ - void RotateFromTo(const AZ::Vector3& fromVector, const AZ::Vector3& toVector); - - /** - * Decompose into swing and twist. - * The original rotation quat can be reassembled by doing swing * twist. - * @param direction The direction vector to get the twist from. - * @param outSwing This will contain the swing quaternion. - * @param outTwist This will contain the twist quaternion. - */ - void DecomposeSwingTwist(const AZ::Vector3& direction, Quaternion* outSwing, Quaternion* outTwist) const; - - /** - * Linear interpolate between this and another quaternion. - * @param to The quaternion to interpolate towards. - * @param t The time value, between 0 and 1. - * @result The quaternion at the given time in the interpolation process. - */ - Quaternion Lerp(const Quaternion& to, float t) const; - - /** - * Linear interpolate between this and another quaternion, and normalize afterwards. - * @param to The quaternion to interpolate towards. - * @param t The time value, between 0 and 1. - * @result The normalized quaternion at the given time in the interpolation process. - */ - Quaternion NLerp(const Quaternion& to, float t) const; - - /** - * Spherical Linear interpolate between this and another quaternion. - * @param to The quaternion to interpolate towards. - * @param t The time value, between 0 and 1. - * @result The quaternion at the given time in the interpolation process. - */ - Quaternion Slerp(const Quaternion& to, float t) const; - - /** - * Spherical cubic interpolate. - * @param p The first quaternion. - * @param a The second quaternion. - * @param b The third quaternion. - * @param q The fourth quaternion. - * @param t The time value, between 0 and 1. - * @result The quaternion at the given time in the interpolation process. - */ - static Quaternion Squad(const Quaternion& p, const Quaternion& a, const Quaternion& b, const Quaternion& q, float t); - - // operators - MCORE_INLINE const Quaternion& operator=(const Matrix& m) { FromMatrix(m); return *this; } - MCORE_INLINE const Quaternion& operator=(const Quaternion& other) { x = other.x; y = other.y; z = other.z; w = other.w; return *this; } - MCORE_INLINE Quaternion operator-() const { return Quaternion(-x, -y, -z, -w); } - MCORE_INLINE const Quaternion& operator+=(const Quaternion& q) { x += q.x; y += q.y; z += q.z; w += q.w; return *this; } - MCORE_INLINE const Quaternion& operator-=(const Quaternion& q) { x -= q.x; y -= q.y; z -= q.z; w -= q.w; return *this; } - MCORE_INLINE const Quaternion& operator*=(const Quaternion& q); - MCORE_INLINE const Quaternion& operator*=(float f) { x *= f; y *= f; z *= f; w *= f; return *this; } - //MCORE_INLINE const Quaternion& operator*=(double f) { x*=f; y*=f; z*=f; w*=f; return *this; } - MCORE_INLINE bool operator==(const Quaternion& q) const { return ((q.x == x) && (q.y == y) && (q.z == z) && (q.w == w)); } - MCORE_INLINE bool operator!=(const Quaternion& q) const { return ((q.x != x) || (q.y != y) || (q.z != z) || (q.w != w)); } - - //MCORE_INLINE float& operator[](int32 row) { return ((float*)&x)[row]; } - MCORE_INLINE operator float*() { return (float*)&x; } - MCORE_INLINE operator const float*() const { return (const float*)&x; } - - MCORE_INLINE AZ::Vector3 operator*(const AZ::Vector3& p) const; // multiply a vector by a quaternion - MCORE_INLINE Quaternion operator/(const Quaternion& q) const; // returns the ratio of two quaternions - - // attributes - float x, y, z, w; - }; - - - // operators - MCORE_INLINE Quaternion operator*(const Quaternion& a, float f) { return Quaternion(a.x * f, a.y * f, a.z * f, a.w * f); } - MCORE_INLINE Quaternion operator*(float f, const Quaternion& b) { return Quaternion(f * b.x, f * b.y, f * b.z, f * b.w); } - //MCORE_INLINE Quaternion operator*(const Quaternion& a, double f) { return Quaternion(a.x*f, a.y*f, a.z*f, a.w*f); } - //MCORE_INLINE Quaternion operator*(double f, const Quaternion& b) { return Quaternion(f*b.x, f*b.y, f*b.z, f*b.w); } - MCORE_INLINE Quaternion operator+(const Quaternion& a, const Quaternion& b) { return Quaternion(a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w); } - MCORE_INLINE Quaternion operator-(const Quaternion& a, const Quaternion& b) { return Quaternion(a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w); } - MCORE_INLINE Quaternion operator*(const Quaternion& a, const Quaternion& b) { return Quaternion(a.w * b.x + a.x * b.w + a.y * b.z - a.z * b.y, a.w * b.y + a.y * b.w + a.z * b.x - a.x * b.z, a.w * b.z + a.z * b.w + a.x * b.y - a.y * b.x, a.w * b.w - a.x * b.x - a.y * b.y - a.z * b.z); } - - // include the inline code -#include "Quaternion.inl" -} // namespace MCore diff --git a/Gems/EMotionFX/Code/MCore/Source/Quaternion.inl b/Gems/EMotionFX/Code/MCore/Source/Quaternion.inl deleted file mode 100644 index c89f497a1e..0000000000 --- a/Gems/EMotionFX/Code/MCore/Source/Quaternion.inl +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -// multiply a vector by a quaternion -MCORE_INLINE AZ::Vector3 Quaternion::operator * (const AZ::Vector3& p) const -{ - Quaternion v(p.GetX(), p.GetY(), p.GetZ(), 0.0f); - v = *this* v* this->Conjugated(); - return AZ::Vector3(v.x, v.y, v.z); -} - - - -// returns the ratio of two quaternions -MCORE_INLINE Quaternion Quaternion::operator / (const Quaternion& q) const -{ - Quaternion t((*this) * -q); - Quaternion s((-q) * (-q)); - t *= (1.0f / s.w); - return t; -} - - - -// calculates the length of the quaternion -MCORE_INLINE float Quaternion::Length() const -{ - const float sqLen = SquareLength(); - return Math::SafeSqrt(sqLen); -} - - -// normalizes the quaternion using approximation -MCORE_INLINE Quaternion& Quaternion::Normalize() -{ - // calculate 1.0 / length - // const float ooLen = 1.0f / Math::FastSqrt(x*x + y*y + z*z + w*w); - // const float ooLen = Math::FastInvSqrt(x*x + y*y + z*z + w*w); - const float squareValue = x * x + y * y + z * z + w * w; - const float ooLen = Math::InvSqrt(squareValue); - - x *= ooLen; - y *= ooLen; - z *= ooLen; - w *= ooLen; - - return *this; -} - - -// get the right axis -MCORE_INLINE AZ::Vector3 Quaternion::CalcRightAxis() const -{ - return AZ::Vector3(1.0f - 2.0f * y * y - 2.0f * z * z, - 2.0f * x * y + 2.0f * z * w, - 2.0f * x * z - 2.0f * y * w); -} - - -// get the forward axis -MCORE_INLINE AZ::Vector3 Quaternion::CalcForwardAxis() const -{ - return AZ::Vector3(2.0f * x * y - 2.0f * z * w, - 1.0f - 2.0f * x * x - 2.0f * z * z, - 2.0f * y * z + 2.0f * x * w); -} - - -// get the up axis -MCORE_INLINE AZ::Vector3 Quaternion::CalcUpAxis() const -{ - return AZ::Vector3(2.0f * x * z + 2.0f * y * w, - 2.0f * y * z - 2.0f * x * w, - 1.0f - 2.0f * x * x - 2.0f * y * y); -} - - -// multiply by a quaternion -MCORE_INLINE const Quaternion& Quaternion::operator*=(const Quaternion& q) -{ - const float vx = w * q.x + x * q.w + y * q.z - z * q.y; - const float vy = w * q.y + y * q.w + z * q.x - x * q.z; - const float vz = w * q.z + z * q.w + x * q.y - y * q.x; - const float vw = w * q.w - x * q.x - y * q.y - z * q.z; - x = vx; - y = vy; - z = vz; - w = vw; - return *this; -} - diff --git a/Gems/EMotionFX/Code/MCore/mcore_files.cmake b/Gems/EMotionFX/Code/MCore/mcore_files.cmake index b63c9e1bae..b0d8a67ccd 100644 --- a/Gems/EMotionFX/Code/MCore/mcore_files.cmake +++ b/Gems/EMotionFX/Code/MCore/mcore_files.cmake @@ -107,9 +107,6 @@ set(FILES Source/PlaneEq.cpp Source/PlaneEq.h Source/PlaneEq.inl - Source/Quaternion.cpp - Source/Quaternion.h - Source/Quaternion.inl Source/Random.cpp Source/Random.h Source/Ray.cpp From aa98be18b7e66a549dc00e18bcbb09fdf248b93c Mon Sep 17 00:00:00 2001 From: Benjamin Jillich Date: Thu, 29 Jul 2021 14:34:56 +0200 Subject: [PATCH 097/160] Removed leftover MCore::Quaternion usages and fixes some include issues Signed-off-by: Benjamin Jillich --- .../Rendering/Common/RotateManipulator.cpp | 2 +- .../Source/LogWindow/LogWindowPlugin.h | 1 + .../Code/MCore/Source/AzCoreConversions.h | 100 +----------------- Gems/EMotionFX/Code/MCore/Source/Matrix4.cpp | 45 -------- Gems/EMotionFX/Code/MCore/Source/Matrix4.h | 15 --- 5 files changed, 3 insertions(+), 160 deletions(-) diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RotateManipulator.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RotateManipulator.cpp index a10f5fe80b..123ef00333 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RotateManipulator.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RotateManipulator.cpp @@ -8,7 +8,7 @@ #include "RotateManipulator.h" #include - +#include namespace MCommon { diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/LogWindow/LogWindowPlugin.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/LogWindow/LogWindowPlugin.h index 022a6d5bd7..1b40b3fa2a 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/LogWindow/LogWindowPlugin.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/LogWindow/LogWindowPlugin.h @@ -10,6 +10,7 @@ #define __EMSTUDIO_LOGWINDOWPLUGIN_H #if !defined(Q_MOC_RUN) +#include #include "../StandardPluginsConfig.h" #include "../../../../EMStudioSDK/Source/DockWidgetPlugin.h" #endif diff --git a/Gems/EMotionFX/Code/MCore/Source/AzCoreConversions.h b/Gems/EMotionFX/Code/MCore/Source/AzCoreConversions.h index 79e3ef9608..78cc99bd98 100644 --- a/Gems/EMotionFX/Code/MCore/Source/AzCoreConversions.h +++ b/Gems/EMotionFX/Code/MCore/Source/AzCoreConversions.h @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -37,18 +38,6 @@ namespace MCore return RGBAColor(static_cast(azColor.GetR()), static_cast(azColor.GetG()), static_cast(azColor.GetB()), static_cast(azColor.GetA())); } - // Deprecated - AZ_FORCE_INLINE AZ::Quaternion EmfxQuatToAzQuat(const MCore::Quaternion& emfxQuat) - { - return AZ::Quaternion(emfxQuat.x, emfxQuat.y, emfxQuat.z, emfxQuat.w); - } - - // Deprecated - AZ_FORCE_INLINE MCore::Quaternion AzQuatToEmfxQuat(const AZ::Quaternion& azQuat) - { - return MCore::Quaternion(azQuat.GetX(), azQuat.GetY(), azQuat.GetZ(), azQuat.GetW()); - } - AZ_FORCE_INLINE AZ::Transform EmfxTransformToAzTransform(const EMotionFX::Transform& emfxTransform) { AZ::Transform transform = AZ::Transform::CreateFromQuaternionAndTranslation(emfxTransform.mRotation, emfxTransform.mPosition); @@ -530,91 +519,4 @@ namespace MCore AZ::Vector3ToVector4(m33.GetRow(2), translation.GetZ()), mat.GetRow(3)); } - - // Deprecated. Please use AZ::Transform instead of MCore::Matrix. - MCORE_INLINE AZ::Quaternion MCoreMatrixToQuaternion(const MCore::Matrix& m) - { - const float trace = MMAT(m, 0, 0) + MMAT(m, 1, 1) + MMAT(m, 2, 2); - if (trace > 0.0f /*Math::epsilon*/) - { - const float s = 0.5f / Math::Sqrt(trace + 1.0f); - return AZ::Quaternion((MMAT(m, 1, 2) - MMAT(m, 2, 1)) * s, - (MMAT(m, 2, 0) - MMAT(m, 0, 2)) * s, - (MMAT(m, 0, 1) - MMAT(m, 1, 0)) * s, - 0.25f / s); - } - else - { - if (MMAT(m, 0, 0) > MMAT(m, 1, 1) && MMAT(m, 0, 0) > MMAT(m, 2, 2)) - { - const float s = 2.0f * Math::Sqrt(1.0f + MMAT(m, 0, 0) - MMAT(m, 1, 1) - MMAT(m, 2, 2)); - const float oneOverS = 1.0f / s; - return AZ::Quaternion(0.25f * s, - (MMAT(m, 1, 0) + MMAT(m, 0, 1)) * oneOverS, - (MMAT(m, 2, 0) + MMAT(m, 0, 2)) * oneOverS, - (MMAT(m, 1, 2) - MMAT(m, 2, 1)) * oneOverS); - } - else if (MMAT(m, 1, 1) > MMAT(m, 2, 2)) - { - const float s = 2.0f * Math::Sqrt(1.0f + MMAT(m, 1, 1) - MMAT(m, 0, 0) - MMAT(m, 2, 2)); - const float oneOverS = 1.0f / s; - return AZ::Quaternion((MMAT(m, 1, 0) + MMAT(m, 0, 1)) * oneOverS, - 0.25f * s, - (MMAT(m, 2, 1) + MMAT(m, 1, 2)) * oneOverS, - (MMAT(m, 2, 0) - MMAT(m, 0, 2)) * oneOverS); - } - else - { - const float s = 2.0f * Math::Sqrt(1.0f + MMAT(m, 2, 2) - MMAT(m, 0, 0) - MMAT(m, 1, 1)); - const float oneOverS = 1.0f / s; - return AZ::Quaternion((MMAT(m, 2, 0) + MMAT(m, 0, 2)) * oneOverS, - (MMAT(m, 2, 1) + MMAT(m, 1, 2)) * oneOverS, - 0.25f * s, - (MMAT(m, 0, 1) - MMAT(m, 1, 0)) * oneOverS); - } - } - - /* - const float trace = MMAT(m,0,0) + MMAT(m,1,1) + MMAT(m,2,2) + 1.0f; - if (trace > Math::epsilon) - { - const float s = 0.5f / Math::Sqrt(trace); - result.w = 0.25f / s; - result.x = ( MMAT(m,1,2) - MMAT(m,2,1) ) * s; - result.y = ( MMAT(m,2,0) - MMAT(m,0,2) ) * s; - result.z = ( MMAT(m,0,1) - MMAT(m,1,0) ) * s; - } - else - { - if (MMAT(m,0,0) > MMAT(m,1,1) && MMAT(m,0,0) > MMAT(m,2,2)) - { - const float s = 2.0f * Math::Sqrt( 1.0f + MMAT(m,0,0) - MMAT(m,1,1) - MMAT(m,2,2)); - const float oneOverS = 1.0f / s; - result.x = 0.25f * s; - result.y = (MMAT(m,1,0) + MMAT(m,0,1) ) * oneOverS; - result.z = (MMAT(m,2,0) + MMAT(m,0,2) ) * oneOverS; - result.w = (MMAT(m,2,1) - MMAT(m,1,2) ) * oneOverS; - } - else - if (MMAT(m,1,1) > MMAT(m,2,2)) - { - const float s = 2.0f * Math::Sqrt( 1.0f + MMAT(m,1,1) - MMAT(m,0,0) - MMAT(m,2,2)); - const float oneOverS = 1.0f / s; - result.x = (MMAT(m,1,0) + MMAT(m,0,1) ) * oneOverS; - result.y = 0.25f * s; - result.z = (MMAT(m,2,1) + MMAT(m,1,2) ) * oneOverS; - result.w = (MMAT(m,2,0) - MMAT(m,0,2) ) * oneOverS; - } - else - { - const float s = 2.0f * Math::Sqrt( 1.0f + MMAT(m,2,2) - MMAT(m,0,0) - MMAT(m,1,1) ); - const float oneOverS = 1.0f / s; - result.x = (MMAT(m,2,0) + MMAT(m,0,2) ) * oneOverS; - result.y = (MMAT(m,2,1) + MMAT(m,1,2) ) * oneOverS; - result.z = 0.25f * s; - result.w = (MMAT(m,1,0) - MMAT(m,0,1) ) * oneOverS; - } - } - */ - } } // namespace MCore diff --git a/Gems/EMotionFX/Code/MCore/Source/Matrix4.cpp b/Gems/EMotionFX/Code/MCore/Source/Matrix4.cpp index 7314e9fe9c..229f67ec0c 100644 --- a/Gems/EMotionFX/Code/MCore/Source/Matrix4.cpp +++ b/Gems/EMotionFX/Code/MCore/Source/Matrix4.cpp @@ -2248,27 +2248,6 @@ namespace MCore } - - // simple decompose a matrix into translation and rotation - void Matrix::Decompose(AZ::Vector3* outTranslation, AZ::Quaternion* outRotation) const - { - // make a copy of the matrix - Matrix mat(*this); - - // normalize the basis vectors - mat.SetRight(SafeNormalize(mat.GetRight())); - mat.SetUp(SafeNormalize(mat.GetUp())); - mat.SetForward(SafeNormalize(mat.GetForward())); - - // extract the translation from the matrix - *outTranslation = mat.GetTranslation(); - - // convert the normalized 3x3 rotation part into a AZ::Quaternion - *outRotation = MCore::MCoreMatrixToQuaternion(*this); - } - - - // calculate a rotation matrix from two vectors void Matrix::SetRotationMatrixTwoVectors(const AZ::Vector3& from, const AZ::Vector3& to) { @@ -2365,30 +2344,6 @@ namespace MCore } - // - void Matrix::DecomposeQRGramSchmidt(AZ::Vector3& translation, AZ::Quaternion& rot, AZ::Vector3& scale, AZ::Vector3& shear) const - { - Matrix rotMatrix; - DecomposeQRGramSchmidt(translation, rotMatrix, scale, shear); - rot = MCore::MCoreMatrixToQuaternion(*this); - } - - // - void Matrix::DecomposeQRGramSchmidt(AZ::Vector3& translation, AZ::Quaternion& rot, AZ::Vector3& scale) const - { - Matrix rotMatrix; - DecomposeQRGramSchmidt(translation, rotMatrix, scale); - rot = MCore::MCoreMatrixToQuaternion(rotMatrix); - } - - - // - void Matrix::DecomposeQRGramSchmidt(AZ::Vector3& translation, AZ::Quaternion& rot) const - { - Matrix rotMatrix; - DecomposeQRGramSchmidt(translation, rotMatrix); - rot = MCore::MCoreMatrixToQuaternion(rotMatrix); - } // diff --git a/Gems/EMotionFX/Code/MCore/Source/Matrix4.h b/Gems/EMotionFX/Code/MCore/Source/Matrix4.h index 8cb09aa769..4be819bcc1 100644 --- a/Gems/EMotionFX/Code/MCore/Source/Matrix4.h +++ b/Gems/EMotionFX/Code/MCore/Source/Matrix4.h @@ -685,26 +685,11 @@ namespace MCore */ void Frustum(float left, float right, float top, float bottom, float znear, float zfar); - /** - * Decompose a transformation matrix into translation and rotation components. - * The translation part is just the translation part of the matrix. - * The rotation AZ::Quaternion is calculated by normalizing the basis vectors and converting the - * 3x3 rotation part of the matrix to a AZ::Quaternion. - * It is allowed for the matrix to contain scaling. - * The matrix where you call Decompose on remains unchanged. - * @param outTranslation A pointer to a vector where the translation will be written to. - * @param outRotation A pointer to a AZ::Quaternion where the rotation will be written to. - * @note Please keep in mind that nullptr values for the parameters are NOT allowed. - */ - void Decompose(AZ::Vector3* outTranslation, AZ::Quaternion* outRotation) const; // QR Gram-Schmidt decomposition - void DecomposeQRGramSchmidt(AZ::Vector3& translation, AZ::Quaternion& rot) const; void DecomposeQRGramSchmidt(AZ::Vector3& translation, Matrix& rot) const; void DecomposeQRGramSchmidt(AZ::Vector3& translation, Matrix& rot, AZ::Vector3& scale) const; void DecomposeQRGramSchmidt(AZ::Vector3& translation, Matrix& rot, AZ::Vector3& scale, AZ::Vector3& shear) const; - void DecomposeQRGramSchmidt(AZ::Vector3& translation, AZ::Quaternion& rot, AZ::Vector3& scale, AZ::Vector3& shear) const; - void DecomposeQRGramSchmidt(AZ::Vector3& translation, AZ::Quaternion& rot, AZ::Vector3& scale) const; static Matrix OuterProduct(const AZ::Vector4& column, const AZ::Vector4& row); From c13d3ec086bc9c484cd5ad1eea1e34ac5843df12 Mon Sep 17 00:00:00 2001 From: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> Date: Thu, 29 Jul 2021 09:35:25 -0400 Subject: [PATCH 098/160] Minor corrections in code gen for usability Signed-off-by: Olex Lozitskiy Signed-off-by: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> --- .../Code/Source/AutoGen/AutoComponent_Common.jinja | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Common.jinja b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Common.jinja index 05403a00ef..72583f9062 100644 --- a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Common.jinja +++ b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Common.jinja @@ -323,10 +323,12 @@ namespace {{ Component.attrib['Namespace'] }} /// Place in your .cpp #include <{{ Component.attrib['OverrideInclude'] }}> +#include + namespace {{ Component.attrib['Namespace'] }} { {% if ComponentDerived %} - void {{ ComponentName }}::{{ ComponentName }}::Reflect(AZ::ReflectContext* context) + void {{ ComponentName }}::Reflect(AZ::ReflectContext* context) { AZ::SerializeContext* serializeContext = azrtti_cast(context); if (serializeContext) From d12d7de13930dc0aa587fcdb9efa4063c60e5127 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Thu, 29 Jul 2021 08:58:10 -0500 Subject: [PATCH 099/160] Add missing display mapper operation type bindings Signed-off-by: Guthrie Adams --- .../DisplayMapperConfigurationDescriptor.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Gems/Atom/Feature/Common/Code/Source/DisplayMapper/DisplayMapperConfigurationDescriptor.cpp b/Gems/Atom/Feature/Common/Code/Source/DisplayMapper/DisplayMapperConfigurationDescriptor.cpp index 8b617cfe0f..a9ee46dd2c 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DisplayMapper/DisplayMapperConfigurationDescriptor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DisplayMapper/DisplayMapperConfigurationDescriptor.cpp @@ -124,6 +124,18 @@ namespace AZ ->Field("AcesParameterOverrides", &DisplayMapperConfigurationDescriptor::m_acesParameterOverrides) ; } + + if (auto* behaviorContext = azrtti_cast(context)) + { + behaviorContext->Class() + ->Enum<(uint32_t)DisplayMapperOperationType::Aces>("DisplayMapperOperationType_Aces") + ->Enum<(uint32_t)DisplayMapperOperationType::AcesLut>("DisplayMapperOperationType_AcesLut") + ->Enum<(uint32_t)DisplayMapperOperationType::Passthrough>("DisplayMapperOperationType_Passthrough") + ->Enum<(uint32_t)DisplayMapperOperationType::GammaSRGB>("DisplayMapperOperationType_GammaSRGB") + ->Enum<(uint32_t)DisplayMapperOperationType::Reinhard>("DisplayMapperOperationType_Reinhard") + ->Enum<(uint32_t)DisplayMapperOperationType::Invalid>("DisplayMapperOperationType_Invalid") + ; + } } void DisplayMapperPassData::Reflect(ReflectContext* context) From 4465b52de5314c78aaeb2ff771a2733127707f31 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Thu, 29 Jul 2021 09:13:49 -0500 Subject: [PATCH 100/160] AtomToolsApplication minor comments/formatting Signed-off-by: Guthrie Adams --- .../Application/AtomToolsApplication.h | 3 ++ .../Code/Source/MaterialEditorApplication.cpp | 52 +++++++++---------- .../Code/Source/MaterialEditorApplication.h | 3 -- .../ShaderManagementConsoleApplication.cpp | 44 ++++++++-------- 4 files changed, 48 insertions(+), 54 deletions(-) diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h index bceea24aad..dc57179fcc 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h @@ -84,7 +84,10 @@ namespace AtomToolsFramework void OnExceptionMessage(AZStd::string_view message) override; //////////////////////////////////////////////////////////////////////// + //! Executable target name generally used as a prefix for logging and other saved files virtual AZStd::string GetBuildTargetName() const; + + //! List of filters for assets that need to be pre-built to run the application virtual AZStd::vector GetCriticalAssetFilters() const; virtual void LoadSettings(); diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp index 7b9372e72b..0977694b90 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp @@ -6,47 +6,44 @@ * */ -#include - -#include -#include - -#include -#include - -#include - -#include -#include -#include - #include -#include #include -#include +#include +#include #include #include -#include - -#include +#include #include #include -#include -#include -#include -#include #include #include +#include +#include +#include +#include #include #include -#include +#include +#include + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include -#include +#include #include AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT -#include #include +#include AZ_POP_DISABLE_WARNING namespace MaterialEditor @@ -54,7 +51,7 @@ namespace MaterialEditor //! This function returns the build system target name of "MaterialEditor AZStd::string MaterialEditorApplication::GetBuildTargetName() const { -#if !defined (LY_CMAKE_TARGET) +#if !defined(LY_CMAKE_TARGET) #error "LY_CMAKE_TARGET must be defined in order to add this source file to a CMake executable target" #endif return AZStd::string{ LY_CMAKE_TARGET }; @@ -73,7 +70,6 @@ namespace MaterialEditor MaterialEditorApplication::MaterialEditorApplication(int* argc, char*** argv) : AtomToolsApplication(argc, argv) - { QApplication::setApplicationName("O3DE Material Editor"); diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h index b1c742d4dd..ec2a48288c 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h @@ -50,9 +50,6 @@ namespace MaterialEditor void ProcessCommandLine(const AZ::CommandLine& commandLine) override; void StartInternal() override; AZStd::string GetBuildTargetName() const override; - - //! List of common asset filters for things that need to be compiled to run the material editor - //! Some of these things will not be necessary once we have proper support for queued asset loading and reloading AZStd::vector GetCriticalAssetFilters() const override; }; } // namespace MaterialEditor diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp index 7d2aa02e19..7e09f88f4f 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp @@ -6,51 +6,48 @@ * */ -#include +#include +#include +#include #include #include - -#include +#include #include #include -#include -#include -#include -#include #include #include +#include +#include +#include +#include #include #include -#include - -#include +#include +#include #include #include +#include -#include +#include #include #include #include - #include #include -#include -#include -#include AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT #include -#include #include +#include AZ_POP_DISABLE_WARNING namespace ShaderManagementConsole { AZStd::string ShaderManagementConsoleApplication::GetBuildTargetName() const { -#if !defined (LY_CMAKE_TARGET) +#if !defined(LY_CMAKE_TARGET) #error "LY_CMAKE_TARGET must be defined in order to add this source file to a CMake executable target" #endif return AZStd::string_view{ LY_CMAKE_TARGET }; @@ -94,7 +91,8 @@ namespace ShaderManagementConsole void ShaderManagementConsoleApplication::Destroy() { // before modules are unloaded, destroy UI to free up any assets it cached - ShaderManagementConsole::ShaderManagementConsoleWindowRequestBus::Broadcast(&ShaderManagementConsole::ShaderManagementConsoleWindowRequestBus::Handler::DestroyShaderManagementConsoleWindow); + ShaderManagementConsole::ShaderManagementConsoleWindowRequestBus::Broadcast( + &ShaderManagementConsole::ShaderManagementConsoleWindowRequestBus::Handler::DestroyShaderManagementConsoleWindow); ShaderManagementConsoleWindowNotificationBus::Handler::BusDisconnect(); @@ -116,9 +114,7 @@ namespace ShaderManagementConsole const AZStd::string runPythonScriptPath = m_commandLine.GetSwitchValue(runPythonScriptSwitchName, runPythonScriptIndex); AZStd::vector runPythonArgs; AzToolsFramework::EditorPythonRunnerRequestBus::Broadcast( - &AzToolsFramework::EditorPythonRunnerRequestBus::Events::ExecuteByFilenameWithArgs, - runPythonScriptPath, - runPythonArgs); + &AzToolsFramework::EditorPythonRunnerRequestBus::Events::ExecuteByFilenameWithArgs, runPythonScriptPath, runPythonArgs); } // Process command line options for opening one or more documents on startup @@ -126,7 +122,8 @@ namespace ShaderManagementConsole for (size_t openDocumentIndex = 0; openDocumentIndex < openDocumentCount; ++openDocumentIndex) { const AZStd::string openDocumentPath = m_commandLine.GetMiscValue(openDocumentIndex); - ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::OpenDocument, openDocumentPath); + ShaderManagementConsoleDocumentSystemRequestBus::Broadcast( + &ShaderManagementConsoleDocumentSystemRequestBus::Events::OpenDocument, openDocumentPath); } } @@ -136,6 +133,7 @@ namespace ShaderManagementConsole ShaderManagementConsoleWindowNotificationBus::Handler::BusConnect(); - ShaderManagementConsole::ShaderManagementConsoleWindowRequestBus::Broadcast(&ShaderManagementConsole::ShaderManagementConsoleWindowRequestBus::Handler::CreateShaderManagementConsoleWindow); + ShaderManagementConsole::ShaderManagementConsoleWindowRequestBus::Broadcast( + &ShaderManagementConsole::ShaderManagementConsoleWindowRequestBus::Handler::CreateShaderManagementConsoleWindow); } } // namespace ShaderManagementConsole From 2237439a0e8ae8629a72db2647a1f6f362d6d3d1 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Thu, 29 Jul 2021 09:29:00 -0500 Subject: [PATCH 101/160] Material Editor: changing preset errors to warnings Signed-off-by: Guthrie Adams --- .../Code/Source/Viewport/MaterialViewportRenderer.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.cpp index 461beffd06..23e37b2f7c 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.cpp @@ -324,7 +324,7 @@ namespace MaterialEditor { if (!preset) { - AZ_Error("MaterialViewportRenderer", false, "Attempting to set invalid lighting preset."); + AZ_Warning("MaterialViewportRenderer", false, "Attempting to set invalid lighting preset."); return; } @@ -365,13 +365,13 @@ namespace MaterialEditor { if (!preset) { - AZ_Error("MaterialViewportRenderer", false, "Attempting to set invalid model preset."); + AZ_Warning("MaterialViewportRenderer", false, "Attempting to set invalid model preset."); return; } if (!preset->m_modelAsset.GetId().IsValid()) { - AZ_Error("MaterialViewportRenderer", false, "Attempting to set invalid model for preset: '%s'\n.", preset->m_displayName.c_str()); + AZ_Warning("MaterialViewportRenderer", false, "Attempting to set invalid model for preset: '%s'\n.", preset->m_displayName.c_str()); return; } From cd25dbf71fb39968ff2366380cf09900c6660717 Mon Sep 17 00:00:00 2001 From: Benjamin Jillich Date: Thu, 29 Jul 2021 14:41:55 +0200 Subject: [PATCH 102/160] Removed MCore::Quaternion AZ::Quaternion comparison tests Signed-off-by: Benjamin Jillich --- .../Rendering/Common/OrthographicCamera.cpp | 1 + .../Rendering/Common/ScaleManipulator.cpp | 2 +- .../Rendering/Common/TranslateManipulator.cpp | 2 +- .../Rendering/OpenGL2/Source/GLSLShader.cpp | 1 + .../EMotionFX/Code/EMotionFX/Source/Actor.cpp | 1 + .../Source/Importer/ChunkProcessors.cpp | 1 + .../Code/MCore/Source/AzCoreConversions.h | 1 - .../Code/Tests/EmotionFXMathLibTests.cpp | 367 ------------------ Gems/EMotionFX/Code/Tests/Matchers.h | 33 +- Gems/EMotionFX/Code/Tests/Printers.cpp | 12 - Gems/EMotionFX/Code/Tests/Printers.h | 6 - 11 files changed, 7 insertions(+), 420 deletions(-) diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/OrthographicCamera.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/OrthographicCamera.cpp index 39b382a8d3..722f43c113 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/OrthographicCamera.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/OrthographicCamera.cpp @@ -7,6 +7,7 @@ */ #include "OrthographicCamera.h" +#include #include #include #include diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/ScaleManipulator.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/ScaleManipulator.cpp index e1dd7e0563..65915aec65 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/ScaleManipulator.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/ScaleManipulator.cpp @@ -7,7 +7,7 @@ */ #include "ScaleManipulator.h" - +#include namespace MCommon { diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/TranslateManipulator.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/TranslateManipulator.cpp index b7c6b87fbf..e20ae5a77e 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/TranslateManipulator.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/TranslateManipulator.cpp @@ -7,7 +7,7 @@ */ #include "TranslateManipulator.h" - +#include namespace MCommon { diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLSLShader.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLSLShader.cpp index 6bd8ab7b2f..02aad3aa04 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLSLShader.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLSLShader.cpp @@ -7,6 +7,7 @@ */ #include +#include #include "GLSLShader.h" #include "GraphicsManager.h" #include diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp index 56d08760c3..973d8eb460 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp @@ -41,6 +41,7 @@ #include #include +#include #include #include diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/ChunkProcessors.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Importer/ChunkProcessors.cpp index e1a3e0bbfa..7e7a9ae1c2 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/ChunkProcessors.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Importer/ChunkProcessors.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include diff --git a/Gems/EMotionFX/Code/MCore/Source/AzCoreConversions.h b/Gems/EMotionFX/Code/MCore/Source/AzCoreConversions.h index 78cc99bd98..d185a804b8 100644 --- a/Gems/EMotionFX/Code/MCore/Source/AzCoreConversions.h +++ b/Gems/EMotionFX/Code/MCore/Source/AzCoreConversions.h @@ -18,7 +18,6 @@ #include #include #include -#include #include // This file is "glue" code to convert math back-forward between MCore and AZ. It also has functions that MCore used to diff --git a/Gems/EMotionFX/Code/Tests/EmotionFXMathLibTests.cpp b/Gems/EMotionFX/Code/Tests/EmotionFXMathLibTests.cpp index 43422dd654..041cc9e862 100644 --- a/Gems/EMotionFX/Code/Tests/EmotionFXMathLibTests.cpp +++ b/Gems/EMotionFX/Code/Tests/EmotionFXMathLibTests.cpp @@ -12,7 +12,6 @@ #include #include -#include #include #include @@ -25,7 +24,6 @@ protected: { m_azNormalizedVector3_a = AZ::Vector3(s_x1, s_y1, s_z1); m_azNormalizedVector3_a.Normalize(); - m_emQuaternion_a = MCore::Quaternion(m_azNormalizedVector3_a, s_angle_a); m_azQuaternion_a = AZ::Quaternion::CreateFromAxisAngle(m_azNormalizedVector3_a, s_angle_a); } @@ -55,26 +53,6 @@ protected: return true; } - bool EmfxQuaternionCompareExact(MCore::Quaternion& quaternion, float x, float y, float z, float w) - { - if (quaternion.x != x) - { - return false; - } - if (quaternion.y != y) - { - return false; - } - if (quaternion.z != z) - { - return false; - } - if (quaternion.w != w) - { - return false; - } - return true; - } bool AZQuaternionCompareClose(AZ::Quaternion& quaternion, float x, float y, float z, float w, float tolerance) { @@ -131,26 +109,6 @@ protected: return true; } - bool AZEMQuaternionsAreEqual(AZ::Quaternion& azQuaternion, const MCore::Quaternion& emQuaternion) - { - if (AZQuaternionCompareExact(azQuaternion, emQuaternion.x, emQuaternion.y, - emQuaternion.z, emQuaternion.w)) - { - return true; - } - return false; - } - - bool AZEMQuaternionsAreClose(AZ::Quaternion& azQuaternion, const MCore::Quaternion& emQuaternion, const float tolerance) - { - if (AZQuaternionCompareClose(azQuaternion, emQuaternion.x, emQuaternion.y, - emQuaternion.z, emQuaternion.w, tolerance)) - { - return true; - } - return false; - } - static const float s_toleranceHigh; static const float s_toleranceMedium; static const float s_toleranceLow; @@ -161,7 +119,6 @@ protected: static const float s_angle_a; AZ::Vector3 m_azNormalizedVector3_a; AZ::Quaternion m_azQuaternion_a; - MCore::Quaternion m_emQuaternion_a; }; const float EmotionFXMathLibTests::s_toleranceHigh = 0.00001f; @@ -174,18 +131,6 @@ const float EmotionFXMathLibTests::s_y1 = 0.3f; const float EmotionFXMathLibTests::s_z1 = 0.4f; const float EmotionFXMathLibTests::s_angle_a = 0.5f; - -/////////////////////////////////////////////////////////////////////////////// - - -// MCore::Quaternion: Test identity values -TEST_F(EmotionFXMathLibTests, QuaternionIdentity_Identity_Success) -{ - MCore::Quaternion test(0.1f, 0.2f, 0.3f, 0.4f); - test.Identity(); - ASSERT_TRUE(test == MCore::Quaternion(0.0f, 0.0f, 0.0f, 1.0f)); -} - ////////////////////////////////////////////////////////////////// //Getting and setting of Quaternions ////////////////////////////////////////////////////////////////// @@ -196,52 +141,6 @@ TEST_F(EmotionFXMathLibTests, AZQuaternionGet_Elements_Success) ASSERT_TRUE(AZQuaternionCompareExact(test, 0.1f, 0.2f, 0.3f, 0.4f)); } -// Compare equivalent normalized quaternions between systems -TEST_F(EmotionFXMathLibTests, AZEMQuaternionNormalizeEquivalent_Success) -{ - AZ::Quaternion azTest(0.1f, 0.2f, 0.3f, 0.4f); - MCore::Quaternion emTest(0.1f, 0.2f, 0.3f, 0.4f); - azTest.Normalize(); - emTest.Normalize(); - - ASSERT_TRUE(AZQuaternionCompareClose(azTest, emTest.x, emTest.y, emTest.z, emTest.w, s_toleranceMedium)); -} - -/////////////////////////////////////////////////////////////////////////////// -// Axis Angle -/////////////////////////////////////////////////////////////////////////////// - -// Compare setting a quaternion using axis and angle -TEST_F(EmotionFXMathLibTests, AZEMQuaternionConversion_SetToAxisAngleEquivalent_Success) -{ - MCore::Quaternion emQuaternion(m_azNormalizedVector3_a, s_angle_a); - AZ::Quaternion azQuaternion = AZ::Quaternion::CreateFromAxisAngle(m_azNormalizedVector3_a, s_angle_a); - - ASSERT_TRUE(AZQuaternionCompareClose(azQuaternion, emQuaternion.x, emQuaternion.y, emQuaternion.z, emQuaternion.w, s_toleranceLow)); -} - -// Compare equivalent conversions quaternions -> (axis, angle) between systems -TEST_F(EmotionFXMathLibTests, AZEMQuaternionConversion_ToAxisAngleEquivalent_Success) -{ - //populate Quaternions with same data - MCore::Quaternion emTest = m_emQuaternion_a; - AZ::Quaternion azTest(emTest.x, emTest.y, emTest.z, emTest.w); - - AZ::Vector3 emAxis; - float emAngle; - emTest.ToAxisAngle(&emAxis, &emAngle); - - AZ::Vector3 azAxis; - float azAngle; - AZ::ConvertQuaternionToAxisAngle(azTest, azAxis, azAngle); - - bool same = AZ::IsClose(azAngle, emAngle, s_toleranceLow) && - AZVector3CompareClose(azAxis, emAxis, s_toleranceLow); - - ASSERT_TRUE(same); -} - - /////////////////////////////////////////////////////////////////////////////// //Basic rotations /////////////////////////////////////////////////////////////////////////////// @@ -420,18 +319,6 @@ TEST_F(EmotionFXMathLibTests, AZQuaternion_EulerGetSet3ComponentAxisCompareTrans ASSERT_TRUE(same); } - -// EM Quaternion to Euler test -TEST_F(EmotionFXMathLibTests, EMQuaternionConversion_ToEulerEquivalent_Success) -{ - AZ::Vector3 eulerIn(0.1f, 0.2f, 0.3f); - MCore::Quaternion test; - test.SetEuler(eulerIn.GetX(), eulerIn.GetY(), eulerIn.GetZ()); - AZ::Vector3 eulerOut = test.ToEuler(); - - ASSERT_TRUE(AZVector3CompareClose(eulerOut, 0.1f, 0.2f, 0.3f, s_toleranceHigh)); -} - // AZ Quaternion to Euler test //only way to test Quaternions sameness is to apply it to a vector and measure result TEST_F(EmotionFXMathLibTests, AZQuaternionConversion_ToEulerEquivalent_Success) @@ -456,41 +343,6 @@ TEST_F(EmotionFXMathLibTests, AZQuaternionConversion_ToEulerEquivalent_Success) ASSERT_TRUE(AZVector3CompareClose(eulerOut1, eulerOut2, s_toleranceReallyLow)); } -/////////////////////////////////////////////////////////////////////////////// -//Quaternion order test -//determines that ordering is same between systems. -/////////////////////////////////////////////////////////////////////////////// -TEST_F(EmotionFXMathLibTests, AZEMQuaternion_OrderTest_Success) -{ - AZ::Vector3 axis = AZ::Vector3(1.0f, 0.7f, 0.3f); - axis.Normalize(); - AZ::Quaternion azQuaternion1 = AZ::Quaternion::CreateFromAxisAngle(axis, AZ::Constants::HalfPi); - - AZ::Vector3 axis2 = AZ::Vector3(0.2f, 0.5f, 0.9f); - axis2.Normalize(); - AZ::Quaternion azQuaternion2 = AZ::Quaternion::CreateFromAxisAngle(axis2, AZ::Constants::HalfPi); - - MCore::Quaternion emQuaternion1(azQuaternion1.GetX(), azQuaternion1.GetY(), azQuaternion1.GetZ(), azQuaternion1.GetW()); - MCore::Quaternion emQuaternion2(azQuaternion2.GetX(), azQuaternion2.GetY(), azQuaternion2.GetZ(), azQuaternion2.GetW()); - - AZ::Quaternion azQuaterionOut = azQuaternion1 * azQuaternion2; - AZ::Quaternion azQuaterionOut2 = azQuaternion2 * azQuaternion1; - MCore::Quaternion emQuaterionOut = emQuaternion1 * emQuaternion2; - - AZ::Vector3 azVertexIn(0.1f, 0.2f, 0.3f); - - AZ::Vector3 azVertexOut, azVertexOut2; - AZ::Vector3 emVertexOut; - - azVertexOut = azQuaterionOut.TransformVector(azVertexIn); - azVertexOut2 = azQuaterionOut2.TransformVector(azVertexIn); - emVertexOut = emQuaterionOut * azVertexIn; - - bool same = AZVector3CompareClose(emVertexOut, azVertexOut.GetX(), azVertexOut.GetY(), azVertexOut.GetZ(), s_toleranceMedium); - ASSERT_TRUE(same); -} - - /////////////////////////////////////////////////////////////////////////////// // Quaternion Matrix /////////////////////////////////////////////////////////////////////////////// @@ -616,225 +468,6 @@ TEST_F(EmotionFXMathLibTests, AZQuaternionConversion_ToMatrix_Success) ASSERT_TRUE(AZ::IsClose(azMatrix.GetElement(3, 3), 1.0f, s_toleranceReallyLow)); } -/////////////////////////////////////////////////////////////////////////////// -// AZEMQuaternion Compare Output tests -// Determines the AZ and MCore quaternion outputs are same/close after same math operations. -/////////////////////////////////////////////////////////////////////////////// -TEST_F(EmotionFXMathLibTests, AZEMQuaternion_CompareOperatorAddEquivalent_Success) -{ - // Quaternion test: operator '+' and operator '+=' - AZ::Quaternion azQuaternion = AZ::Quaternion(0.1f, 0.2f, 0.3f, 1.0f); - AZ::Quaternion azQuaternion2 = AZ::Quaternion(0.8f, 0.7f, 0.6f, 1.0f); - azQuaternion.Normalize(); - azQuaternion2.Normalize(); - azQuaternion = azQuaternion + azQuaternion2; - azQuaternion2 += azQuaternion; - - MCore::Quaternion emQuaternion = MCore::Quaternion(0.1f, 0.2f, 0.3f, 1.0f); - MCore::Quaternion emQuaternion2 = MCore::Quaternion(0.8f, 0.7f, 0.6f, 1.0f); - emQuaternion.Normalize(); - emQuaternion2.Normalize(); - emQuaternion = emQuaternion + emQuaternion2; - emQuaternion2 += emQuaternion; - - EXPECT_TRUE(AZEMQuaternionsAreClose(azQuaternion, emQuaternion, s_toleranceLow)) << "AZ/MCore Quaternions should have similar output with operator '+'"; - EXPECT_TRUE(AZEMQuaternionsAreClose(azQuaternion2, emQuaternion2, s_toleranceLow)) << "AZ/MCore Quaternions should have similar output with operator '+='"; -} - -TEST_F(EmotionFXMathLibTests, AZEMQuaternion_CompareOperatorSubtractEquivalent_Success) -{ - // Quaternion test: operator '-' and operator '-=' - AZ::Quaternion azQuaternion = AZ::Quaternion(0.1f, 0.2f, 0.3f, 1.0f); - AZ::Quaternion azQuaternion2 = AZ::Quaternion(0.8f, 0.7f, 0.6f, 1.0f); - azQuaternion.Normalize(); - azQuaternion2.Normalize(); - azQuaternion = azQuaternion - azQuaternion2; - azQuaternion2 -= azQuaternion; - - MCore::Quaternion emQuaternion = MCore::Quaternion(0.1f, 0.2f, 0.3f, 1.0f); - MCore::Quaternion emQuaternion2 = MCore::Quaternion(0.8f, 0.7f, 0.6f, 1.0f); - emQuaternion.Normalize(); - emQuaternion2.Normalize(); - emQuaternion = emQuaternion - emQuaternion2; - emQuaternion2 -= emQuaternion; - - EXPECT_TRUE(AZEMQuaternionsAreClose(azQuaternion, emQuaternion, s_toleranceLow)) << "AZ/MCore Quaternions should have similar output with operator '-'"; - EXPECT_TRUE(AZEMQuaternionsAreClose(azQuaternion2, emQuaternion2, s_toleranceLow)) << "AZ/MCore Quaternions should have similar output with operator '-='"; -} - -TEST_F(EmotionFXMathLibTests, AZEMQuaternion_CompareOperatorMultiplyHasSimilarOutput_Success) -{ - // Quaternion test: operator '*' and operator '*=' with another quaternion, vector3 and float - AZ::Quaternion azQuaternion = AZ::Quaternion(0.1f, 0.2f, 0.3f, 1.0f); - AZ::Quaternion azQuaternion2 = AZ::Quaternion(0.8f, 0.7f, 0.6f, 1.0f); - AZ::Quaternion azQuaternion3 = AZ::Quaternion(0.1f, 0.2f, 0.3f, 1.0f); - azQuaternion.Normalize(); - azQuaternion2.Normalize(); - azQuaternion3.Normalize(); - azQuaternion = azQuaternion * azQuaternion2; - azQuaternion2 *= azQuaternion; - azQuaternion3 *= 0.5f; - AZ::Vector3 aztestVec3 = azQuaternion2.TransformVector(m_azNormalizedVector3_a); - - MCore::Quaternion emQuaternion = MCore::Quaternion(0.1f, 0.2f, 0.3f, 1.0f); - MCore::Quaternion emQuaternion2 = MCore::Quaternion(0.8f, 0.7f, 0.6f, 1.0f); - MCore::Quaternion emQuaternion3 = MCore::Quaternion(0.1f, 0.2f, 0.3f, 1.0f); - emQuaternion.Normalize(); - emQuaternion2.Normalize(); - emQuaternion3.Normalize(); - emQuaternion = emQuaternion * emQuaternion2; - emQuaternion2 *= emQuaternion; - emQuaternion3 *= 0.5f; - AZ::Vector3 emtestVec3 = emQuaternion2 * m_azNormalizedVector3_a; - - EXPECT_TRUE(AZEMQuaternionsAreClose(azQuaternion, emQuaternion, s_toleranceLow)) << "AZ/MCore Quaternions should have similar output with operator '*' with another quaternion"; - EXPECT_TRUE(AZEMQuaternionsAreClose(azQuaternion2, emQuaternion2, s_toleranceLow)) << "AZ/MCore Quaternions should have similar output with operator '*=' with another quaternion"; - EXPECT_TRUE(AZEMQuaternionsAreClose(azQuaternion3, emQuaternion3, s_toleranceLow)) << "AZ/MCore Quaternions should have similar output with operator '*=' with a float value"; - EXPECT_TRUE(AZVector3CompareClose(aztestVec3, emtestVec3, s_toleranceLow)) << "AZ/MCore Quaternions should have similar output with operator '*' with a vector3"; -} - -TEST_F(EmotionFXMathLibTests, AZEMQuaternion_EquivalentOperatorsHasSameOutput_Success) -{ - // Testing Quaternion == Quaternion and operator!= - bool azCheck = AZ::Quaternion(0.1f, 0.2f, 0.3f, 1.0f).GetNormalized() == AZ::Quaternion(0.1f, 0.2f, 0.3f, 1.0f).GetNormalized(); - bool azCheck2 = AZ::Quaternion(0.1f, 0.2f, 0.3f, 1.0f).GetNormalized() == AZ::Quaternion(0.1000001f, 0.2000001f, 0.3000001f, 1.0f).GetNormalized(); - bool azCheck3 = AZ::Quaternion(0.1f, 0.2f, 0.3f, 1.0f).GetNormalized() != AZ::Quaternion(0.1f, 0.2f, 0.3f, 1.0f).GetNormalized(); - bool azCheck4 = AZ::Quaternion(0.1f, 0.2f, 0.3f, 1.0f).GetNormalized() != AZ::Quaternion(0.1000001f, 0.2000001f, 0.3000001f, 1.0f).GetNormalized(); - - bool emCheck = MCore::Quaternion(0.1f, 0.2f, 0.3f, 1.0f).Normalized() == MCore::Quaternion(0.1f, 0.2f, 0.3f, 1.0f).Normalized(); - bool emCheck2 = MCore::Quaternion(0.1f, 0.2f, 0.3f, 1.0f).Normalized() == MCore::Quaternion(0.1000001f, 0.2000001f, 0.3000001f, 1.0f).Normalized(); - bool emCheck3 = MCore::Quaternion(0.1f, 0.2f, 0.3f, 1.0f).Normalized() != MCore::Quaternion(0.1f, 0.2f, 0.3f, 1.0f).Normalized(); - bool emCheck4 = MCore::Quaternion(0.1f, 0.2f, 0.3f, 1.0f).Normalized() != MCore::Quaternion(0.1000001f, 0.2000001f, 0.3000001f, 1.0f).Normalized(); - - EXPECT_TRUE(azCheck == emCheck) << "AZ/MCore Quaternions should have same output of 'true' with operator '=='"; - EXPECT_TRUE(azCheck2 == emCheck2) << "AZ/MCore Quaternions should have same output of 'false' with operator '=='"; - EXPECT_TRUE(azCheck3 == emCheck3) << "AZ/MCore Quaternions should have same output of 'false' with operator '!='"; - EXPECT_TRUE(azCheck4 == emCheck4) << "AZ/MCore Quaternions should have same output of 'true' with operator '!='"; -} - -TEST_F(EmotionFXMathLibTests, AZEMQuaternion_InverseHasSimilarOutput_Success) -{ - // Test quaternions inverse method - AZ::Quaternion azQuaternion = AZ::Quaternion(0.1f, 0.2f, 0.3f, 1.0f).GetNormalized().GetInverseFull(); - AZ::Quaternion azQuaternion2 = AZ::Quaternion(0.0f, 0.0f, 0.0f, 1.0f).GetNormalized().GetInverseFull(); - - MCore::Quaternion emQuaternion = MCore::Quaternion(0.1f, 0.2f, 0.3f, 1.0f).Normalized().Inverse(); - MCore::Quaternion emQuaternion2 = MCore::Quaternion(0.0f, 0.0f, 0.0f, 1.0f).Normalized().Inverse(); - - EXPECT_TRUE(AZEMQuaternionsAreClose(azQuaternion, emQuaternion, s_toleranceLow)) << "AZ/MCore Quaternions should have similar Inverse output"; - EXPECT_TRUE(AZEMQuaternionsAreClose(azQuaternion2, emQuaternion2, s_toleranceLow)) << "AZ/MCore Quaternion(0.0f, 0.0f, 0.0f, 1.0f) should have similar Inverse output"; -} - -TEST_F(EmotionFXMathLibTests, AZEMQuaternion_ConjugateHasSimilarOutput_Success) -{ - // Test quaternion conjugate method - AZ::Quaternion azQuaternion = AZ::Quaternion(0.1f, 0.2f, 0.3f, 1.0f).GetNormalized().GetConjugate(); - AZ::Quaternion azQuaternion2 = AZ::Quaternion(0.0f, 0.0f, 0.0f, 1.0f).GetNormalized().GetConjugate(); - - MCore::Quaternion emQuaternion = MCore::Quaternion(0.1f, 0.2f, 0.3f, 1.0f).Normalized().Conjugate(); - MCore::Quaternion emQuaternion2 = MCore::Quaternion(0.0f, 0.0f, 0.0f, 1.0f).Normalized().Conjugate(); - - EXPECT_TRUE(AZEMQuaternionsAreClose(azQuaternion, emQuaternion, s_toleranceLow)) << "AZ/MCore Quaternions should have similar Conjugate output"; - EXPECT_TRUE(AZEMQuaternionsAreClose(azQuaternion2, emQuaternion2, s_toleranceLow)) << "AZ/MCore Quaternion(0.0f, 0.0f, 0.0f, 1.0f) should have similar Conjugate output"; -} - -TEST_F(EmotionFXMathLibTests, AZEMQuaternion_HasSameSquareLengthOutput_Success) -{ - // Test AZ and MCore quaternions to have similar square length - float azTest = AZ::Quaternion(0.1f, 0.2f, 0.3f, 1.0f).GetNormalized().GetLengthSq(); - float azTest2 = AZ::Quaternion(0.0f, 0.0f, 0.0f, 1.0f).GetNormalized().GetLengthSq(); - - float emTest = MCore::Quaternion(0.1f, 0.2f, 0.3f, 1.0f).Normalized().SquareLength(); - float emTest2 = MCore::Quaternion(0.0f, 0.0f, 0.0f, 1.0f).Normalized().SquareLength(); - - EXPECT_TRUE(AZ::GetAbs(azTest - emTest) < s_toleranceLow) << "AZ/MCore Quaternions should have similar square length output"; - EXPECT_TRUE(AZ::GetAbs(azTest2 - emTest2) < s_toleranceLow) << "AZ/MCore Quaternion(0.0f, 0.0f, 0.0f, 1.0f) should have similar square length output"; -} - -TEST_F(EmotionFXMathLibTests, AZEMQuaternion_HasSameLengthOutput_Success) -{ - // Test AZ and MCore quaternions to have similar length - // AZ GetLength, GetLengthApprox, GetLength all returns sqrtf(Dot(*this)) - float azTest = AZ::Quaternion(0.1f, 0.2f, 0.3f, 1.0f).GetNormalized().GetLength(); - float azTest2 = AZ::Quaternion(0.0f, 0.0f, 0.0f, 1.0f).GetNormalized().GetLength(); - - float emTest = MCore::Quaternion(0.1f, 0.2f, 0.3f, 1.0f).Normalized().Length(); - float emTest2 = MCore::Quaternion(0.0f, 0.0f, 0.0f, 1.0f).Normalized().Length(); - - EXPECT_TRUE(AZ::GetAbs(azTest - emTest) < s_toleranceLow) << "AZ/MCore Quaternions should have similar length output"; - EXPECT_TRUE(AZ::GetAbs(azTest2 - emTest2) < s_toleranceLow) << "AZ/MCore Quaternion(0.0f, 0.0f, 0.0f, 1.0f) should have similar length output"; -} - -TEST_F(EmotionFXMathLibTests, AZEMQuaternion_HasSameDotProductOutput_Success) -{ - // Test AZ and MCore quaternions to have similar dot product - float azDotTest = AZ::Quaternion(0.1f, 0.2f, 0.3f, 1.0f).GetNormalized().Dot(AZ::Quaternion(0.8f, 0.7f, 0.6f, 1.0f)); - float azDotTest2 = AZ::Quaternion(0.1f, 0.2f, 0.3f, 1.0f).GetNormalized().Dot(AZ::Quaternion(0.0f, 0.0f, 0.0f, 1.0f)); - float azDotTest3 = AZ::Quaternion(0.0f, 0.0f, 0.0f, 1.0f).GetNormalized().Dot(AZ::Quaternion(0.0f, 0.0f, 0.0f, 1.0f)); - - float emDotTest = MCore::Quaternion(0.1f, 0.2f, 0.3f, 1.0f).Normalized().Dot(MCore::Quaternion(0.8f, 0.7f, 0.6f, 1.0f)); - float emDotTest2 = MCore::Quaternion(0.1f, 0.2f, 0.3f, 1.0f).Normalized().Dot(MCore::Quaternion(0.0f, 0.0f, 0.0f, 1.0f)); - float emDotTest3 = MCore::Quaternion(0.0f, 0.0f, 0.0f, 1.0f).Normalized().Dot(MCore::Quaternion(0.0f, 0.0f, 0.0f, 1.0f)); - - EXPECT_TRUE(AZ::GetAbs(azDotTest - emDotTest) < s_toleranceLow) << "AZ/MCore Quaternions should have similar dot product output"; - EXPECT_TRUE(AZ::GetAbs(azDotTest2 - emDotTest2) < s_toleranceLow) << "AZ/MCore Quaternions should have similar dot product output"; - EXPECT_TRUE(AZ::GetAbs(azDotTest3 - emDotTest3) < s_toleranceLow) << "AZ/MCore Quaternion(0.0f, 0.0f, 0.0f, 1.0f) should have similar dot product output"; -} - -TEST_F(EmotionFXMathLibTests, AZEMQuaternion_HasSimilarLerpOutput_Success) -{ - // Test AZ and MCore quaternions to have similar Linear Interpolated quaternions - float testCases[6] = { 0.0f, 0.1f, 0.25f, 0.5f, 0.8f, 1.0f }; - for (float testVal : testCases) - { - AZ::Quaternion azQuaternionA = AZ::Quaternion(0.1f, 0.2f, 0.3f, 1.0f).GetNormalized(); - AZ::Quaternion azQuaternionB = AZ::Quaternion(0.8f, 0.7f, 0.6f, 1.0f).GetNormalized(); - AZ::Quaternion azQuaternionC = azQuaternionA.Lerp(azQuaternionB, testVal); - - MCore::Quaternion emQuaternionA = MCore::Quaternion(0.1f, 0.2f, 0.3f, 1.0f).Normalized(); - MCore::Quaternion emQuaternionB = MCore::Quaternion(0.8f, 0.7f, 0.6f, 1.0f).Normalized(); - MCore::Quaternion emQuaternionC = emQuaternionA.Lerp(emQuaternionB, testVal); - - EXPECT_TRUE(AZEMQuaternionsAreClose(azQuaternionA, emQuaternionA, s_toleranceLow)) << "AZ/MCore Quaternions should have similar Lerp output with given float: " << testVal; - } -} - -TEST_F(EmotionFXMathLibTests, AZEMQuaternion_HasSimilarNLerpOutput_Success) -{ - // Test AZ and MCore quaternions to have similar Linear Interpolated and then normalized quaternions - float testCases[6] = {0.0f, 0.1f, 0.25f, 0.5f, 0.8f, 1.0f}; - for (float testVal : testCases) - { - AZ::Quaternion azQuaternionA = AZ::Quaternion(0.1f, 0.2f, 0.3f, 1.0f).GetNormalized(); - AZ::Quaternion azQuaternionB = AZ::Quaternion(0.8f, 0.7f, 0.6f, 1.0f).GetNormalized(); - AZ::Quaternion azQuaternionC = azQuaternionA.NLerp(azQuaternionB, testVal); - - MCore::Quaternion emQuaternionA = MCore::Quaternion(0.1f, 0.2f, 0.3f, 1.0f).Normalized(); - MCore::Quaternion emQuaternionB = MCore::Quaternion(0.8f, 0.7f, 0.6f, 1.0f).Normalized(); - MCore::Quaternion emQuaternionC = emQuaternionA.NLerp(emQuaternionB, testVal); - - EXPECT_TRUE(AZEMQuaternionsAreClose(azQuaternionA, emQuaternionA, s_toleranceLow)) << "AZ/MCore Quaternions should have similar NLerp output with given float: " << testVal; - } -} - -TEST_F(EmotionFXMathLibTests, AZEMQuaternion_HasSimilarSLerpOutput_Success) -{ - // Test AZ and MCore quaternions to have similar spherical Linear Interpolated quaternions - float testCases[6] = { 0.0f, 0.1f, 0.25f, 0.5f, 0.8f, 1.0f }; - for (float testVal : testCases) - { - AZ::Quaternion azQuaternionA = AZ::Quaternion(0.1f, 0.2f, 0.3f, 1.0f).GetNormalized(); - AZ::Quaternion azQuaternionB = AZ::Quaternion(0.8f, 0.7f, 0.6f, 1.0f).GetNormalized(); - AZ::Quaternion azQuaternionC = azQuaternionA.Slerp(azQuaternionB, testVal); - - MCore::Quaternion emQuaternionA = MCore::Quaternion(0.1f, 0.2f, 0.3f, 1.0f).Normalized(); - MCore::Quaternion emQuaternionB = MCore::Quaternion(0.8f, 0.7f, 0.6f, 1.0f).Normalized(); - MCore::Quaternion emQuaternionC = emQuaternionA.Slerp(emQuaternionB, testVal); - - EXPECT_TRUE(AZEMQuaternionsAreClose(azQuaternionA, emQuaternionA, s_toleranceLow)) << "AZ/MCore Quaternions should have similar Slerp output with given float: " << testVal; - } -} - ////////////////////////////////////////////////////////////////// // Skinning ////////////////////////////////////////////////////////////////// diff --git a/Gems/EMotionFX/Code/Tests/Matchers.h b/Gems/EMotionFX/Code/Tests/Matchers.h index 64200e84f2..ad3c204f72 100644 --- a/Gems/EMotionFX/Code/Tests/Matchers.h +++ b/Gems/EMotionFX/Code/Tests/Matchers.h @@ -13,8 +13,8 @@ #include #include #include -#include #include +#include #include #include @@ -76,37 +76,6 @@ inline bool IsCloseMatcherP::gmock_Impl:: return false; } -template<> -template<> -inline bool IsCloseMatcherP::gmock_Impl::MatchAndExplain(const MCore::Quaternion& arg, ::testing::MatchResultListener* result_listener) const -{ - const MCore::Quaternion compareQuat = (expected.Dot(arg) < 0.0f) ? -arg : arg; - const AZ::Vector4 compareVec4(compareQuat.x, compareQuat.y, compareQuat.z, compareQuat.w); - - if (::testing::ExplainMatchResult(IsClose(AZ::Vector4(expected.x, expected.y, expected.z, expected.w)), compareVec4, result_listener)) - { - return true; - } - - AZ::Vector3 gotAxis; - AZ::Vector3 expectedAxis; - float gotAngle; - float expectedAngle; - - // convert to an axis and angle representation - expected.ToAxisAngle(&expectedAxis, &expectedAngle); - compareQuat.ToAxisAngle(&gotAxis, &gotAngle); - - *result_listener << "\n Got Axis: "; - PrintTo(gotAxis, result_listener->stream()); - *result_listener << ", Got Angle: " << gotAngle << "\n"; - *result_listener << "Expected Axis: "; - PrintTo(expectedAxis, result_listener->stream()); - *result_listener << ", Expected Angle: " << expectedAngle; - - return false; -} - template<> template<> inline bool IsCloseMatcherP::gmock_Impl::MatchAndExplain(const EMotionFX::Transform& arg, ::testing::MatchResultListener* result_listener) const diff --git a/Gems/EMotionFX/Code/Tests/Printers.cpp b/Gems/EMotionFX/Code/Tests/Printers.cpp index 8fd196fda0..ebf5167508 100644 --- a/Gems/EMotionFX/Code/Tests/Printers.cpp +++ b/Gems/EMotionFX/Code/Tests/Printers.cpp @@ -34,18 +34,6 @@ namespace AZStd } } // namespace AZStd -namespace MCore -{ - void PrintTo(const Quaternion& quaternion, ::std::ostream* os) - { - *os << "(x: " << quaternion.x - << ", y: " << quaternion.y - << ", z: " << quaternion.z - << ", w: " << quaternion.w - << ")"; - } -} // namespace MCore - namespace EMotionFX { void PrintTo(const Transform& transform, ::std::ostream* os) diff --git a/Gems/EMotionFX/Code/Tests/Printers.h b/Gems/EMotionFX/Code/Tests/Printers.h index c262cb2bed..afa8ea4b7b 100644 --- a/Gems/EMotionFX/Code/Tests/Printers.h +++ b/Gems/EMotionFX/Code/Tests/Printers.h @@ -11,7 +11,6 @@ #include #include #include -#include #include namespace AZ @@ -25,11 +24,6 @@ namespace AZStd void PrintTo(const string& string, ::std::ostream* os); } // namespace AZStd -namespace MCore -{ - void PrintTo(const Quaternion& quaternion, ::std::ostream* os); -} // namespace MCore - namespace EMotionFX { void PrintTo(const Transform& transform, ::std::ostream* os); From ce99e3f2ecc4970595f8ec7bdb97c338964743c8 Mon Sep 17 00:00:00 2001 From: pereslav Date: Thu, 29 Jul 2021 18:00:53 +0100 Subject: [PATCH 103/160] Fixed autogen namespace always going upper case Signed-off-by: pereslav --- .../Code/Source/AutoGen/AutoComponent_Source.jinja | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja index c0d4fe0dac..d2be2f682a 100644 --- a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja +++ b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja @@ -970,7 +970,7 @@ enum class NetworkProperties {% macro DefineComponentServiceProxyGrabs(Component, ClassType, ComponentType) %} {% for Service in Component.iter('ComponentRelation') %} {% if Service.attrib['Constraint'] != 'Incompatible' %} -m_{{ LowerFirst(Service.attrib['Name']) }} = FindComponent<{{ UpperFirst(Service.attrib['Namespace']) }}::{{ UpperFirst(Service.attrib['Name']) }}>(); +m_{{ LowerFirst(Service.attrib['Name']) }} = FindComponent<{{ Service.attrib['Namespace'] }}::{{ UpperFirst(Service.attrib['Name']) }}>(); {% endif %} {% endfor %} {% endmacro %} @@ -1709,12 +1709,12 @@ namespace {{ Component.attrib['Namespace'] }} {% for Service in Component.iter('ComponentRelation') %} {% if Service.attrib['Constraint'] != 'Incompatible' %} - const {{ UpperFirst(Service.attrib['Namespace']) }}::{{ UpperFirst(Service.attrib['Name']) }}* {{ ComponentBaseName }}::Get{{ UpperFirst(Service.attrib['Name']) }}() const + const {{ Service.attrib['Namespace'] }}::{{ UpperFirst(Service.attrib['Name']) }}* {{ ComponentBaseName }}::Get{{ UpperFirst(Service.attrib['Name']) }}() const { return m_{{ LowerFirst(Service.attrib['Name']) }}; } - {{ UpperFirst(Service.attrib['Namespace']) }}::{{ UpperFirst(Service.attrib['Name']) }}* {{ ComponentBaseName }}::Get{{ UpperFirst(Service.attrib['Name']) }}() + {{ Service.attrib['Namespace'] }}::{{ UpperFirst(Service.attrib['Name']) }}* {{ ComponentBaseName }}::Get{{ UpperFirst(Service.attrib['Name']) }}() { return m_{{ LowerFirst(Service.attrib['Name']) }}; } From 5a18b246518d26c1b89cebfb3607e5787564a8d2 Mon Sep 17 00:00:00 2001 From: Jacob Hilliard Date: Thu, 29 Jul 2021 10:08:19 -0700 Subject: [PATCH 104/160] Visualizer: use template functor over hardcoded lambdas Signed-off-by: Jacob Hilliard --- .../Include/Atom/Utils/ImGuiCpuProfiler.h | 14 +++++++++ .../Include/Atom/Utils/ImGuiCpuProfiler.inl | 29 ++++--------------- 2 files changed, 20 insertions(+), 23 deletions(-) diff --git a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.h b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.h index 62b71bdbb8..75b7ec9fdd 100644 --- a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.h +++ b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.h @@ -27,6 +27,20 @@ namespace AZ //! Stores all the data associated with a row in the table. struct TableRow { + template + struct TableRowCompareFunctor + { + TableRowCompareFunctor(T memberPointer, bool isAscending) : m_memberPointer(memberPointer), m_ascending(isAscending){}; + + bool operator()(const TableRow* lhs, const TableRow* rhs) + { + return m_ascending ? lhs->*m_memberPointer < rhs->*m_memberPointer : lhs->*m_memberPointer > rhs->*m_memberPointer; + } + + T m_memberPointer; + bool m_ascending; + }; + // Update running statistics with new region data void RecordRegion(const AZ::RHI::CachedTimeRegion& region, AZStd::thread_id threadId); diff --git a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl index 90b6c67905..ffd7af2f20 100644 --- a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl +++ b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl @@ -208,39 +208,22 @@ namespace AZ switch (columnToSort) { case (0): // Sort by group name - AZStd::sort(m_tableData.begin(), m_tableData.end(), [ascending](const TableRow* lhs, const TableRow* rhs){ - return ascending ? lhs->m_groupName < rhs->m_groupName : lhs->m_groupName > rhs->m_groupName; - }); + AZStd::sort(m_tableData.begin(), m_tableData.end(), TableRow::TableRowCompareFunctor(&TableRow::m_groupName, ascending)); break; case (1): // Sort by region name - AZStd::sort(m_tableData.begin(), m_tableData.end(),[ascending](const TableRow* lhs, const TableRow* rhs){ - return ascending ? lhs->m_regionName < rhs->m_regionName - : lhs->m_regionName > rhs->m_regionName; - }); + AZStd::sort(m_tableData.begin(), m_tableData.end(), TableRow::TableRowCompareFunctor(&TableRow::m_regionName, ascending)); break; case (2): // Sort by average time - AZStd::sort(m_tableData.begin(), m_tableData.end(), [ascending](const TableRow* lhs, const TableRow* rhs){ - return ascending ? lhs->m_runningAverageTicks < rhs->m_runningAverageTicks - : lhs->m_runningAverageTicks > rhs->m_runningAverageTicks; - }); + AZStd::sort(m_tableData.begin(), m_tableData.end(), TableRow::TableRowCompareFunctor(&TableRow::m_runningAverageTicks, ascending)); break; case (3): // Sort by max time - AZStd::sort(m_tableData.begin(), m_tableData.end(), [ascending](const TableRow* lhs, const TableRow* rhs){ - return ascending ? lhs->m_maxTicks < rhs->m_maxTicks - : lhs->m_maxTicks > rhs->m_maxTicks; - }); + AZStd::sort(m_tableData.begin(), m_tableData.end(), TableRow::TableRowCompareFunctor(&TableRow::m_maxTicks, ascending)); break; case (4): // Sort by invocations - AZStd::sort(m_tableData.begin(), m_tableData.end(), [ascending](const TableRow* lhs, const TableRow* rhs){ - return ascending ? lhs->m_invocationsLastFrame < rhs->m_invocationsLastFrame - : lhs->m_invocationsLastFrame > rhs->m_invocationsLastFrame; - }); + AZStd::sort(m_tableData.begin(), m_tableData.end(), TableRow::TableRowCompareFunctor(&TableRow::m_invocationsLastFrame, ascending)); break; case (5): // Sort by total time - AZStd::sort(m_tableData.begin(), m_tableData.end(), [ascending](const TableRow* lhs, const TableRow* rhs){ - return ascending ? lhs->m_lastFrameTotalTicks < rhs->m_lastFrameTotalTicks - : lhs->m_lastFrameTotalTicks > rhs->m_lastFrameTotalTicks; - }); + AZStd::sort(m_tableData.begin(), m_tableData.end(), TableRow::TableRowCompareFunctor(&TableRow::m_lastFrameTotalTicks, ascending)); break; } sortSpecs->SpecsDirty = false; From c9301a8c947f3f21ca1789eed84ea28fb5976e4d Mon Sep 17 00:00:00 2001 From: srikappa-amzn <82230713+srikappa-amzn@users.noreply.github.com> Date: Thu, 29 Jul 2021 12:04:04 -0700 Subject: [PATCH 105/160] Fix a bug in patching templates and improve error messaging (#2394) * Fix a bug in patching templates and improve error messaging * Fixed incorrect order of function arguments * Fix build errors regarding c style strings and casting entity ids Signed-off-by: srikappa-amzn --- .../Instance/InstanceToTemplatePropagator.cpp | 2 +- .../Prefab/PrefabPublicHandler.cpp | 59 +++++++++++++------ .../Prefab/PrefabPublicHandler.h | 7 ++- 3 files changed, 46 insertions(+), 22 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceToTemplatePropagator.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceToTemplatePropagator.cpp index c7bf72ff7b..8f93ebb6df 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceToTemplatePropagator.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceToTemplatePropagator.cpp @@ -177,7 +177,7 @@ namespace AzToolsFramework PrefabDomUtils::ApplyPatches(templateDomReference, templateDomReference.GetAllocator(), providedPatch); //trigger propagation - if (result.GetOutcome() != AZ::JsonSerializationResult::Outcomes::Success) + if (result.GetProcessing() != AZ::JsonSerializationResult::Processing::Completed) { AZ_Error("Prefab", false, "Patch was not successfully applied."); return false; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp index 16db933192..a03e48062c 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp @@ -90,10 +90,11 @@ namespace AzToolsFramework AZStd::unordered_map nestedInstanceLinkPatchesMap; // Retrieve all entities affected and identify Instances - if (!RetrieveAndSortPrefabEntitiesAndInstances(inputEntityList, commonRootEntityOwningInstance->get(), entities, instances)) + PrefabOperationResult retrieveEntitiesAndInstancesOutcome = RetrieveAndSortPrefabEntitiesAndInstances( + inputEntityList, commonRootEntityOwningInstance->get(), entities, instances); + if (!retrieveEntitiesAndInstancesOutcome.IsSuccess()) { - return AZ::Failure( - AZStd::string("Could not create a new prefab out of the entities provided - invalid selection.")); + return retrieveEntitiesAndInstancesOutcome; } AZStd::unordered_map oldEntityAliases; @@ -646,7 +647,12 @@ namespace AzToolsFramework { // Retrieve all nested instances that are part of the subtree under the current entity. EntityList entities; - RetrieveAndSortPrefabEntitiesAndInstances({ entity }, beforeOwningInstance->get(), entities, instancesInvolved); + PrefabOperationResult retrieveEntitiesAndInstancesOutcome = RetrieveAndSortPrefabEntitiesAndInstances( + { entity }, beforeOwningInstance->get(), entities, instancesInvolved); + if (!retrieveEntitiesAndInstancesOutcome.IsSuccess()) + { + return retrieveEntitiesAndInstancesOutcome; + } } for (Instance* instance : instancesInvolved) @@ -748,7 +754,9 @@ namespace AzToolsFramework AZStd::vector instances; // Retrieve all descendant entities and instances of this entity that belonged to the same owning instance. - RetrieveAndSortPrefabEntitiesAndInstances({ entity }, beforeOwningInstance->get(), entities, instances); + PrefabOperationResult retrieveEntitiesAndInstancesOutcome = RetrieveAndSortPrefabEntitiesAndInstances( + { entity }, beforeOwningInstance->get(), entities, instances); + AZ_Error("Prefab", retrieveEntitiesAndInstancesOutcome.IsSuccess(), retrieveEntitiesAndInstancesOutcome.GetError().data()); AZStd::vector> instanceUniquePtrs; AZStd::vector> instancePatches; @@ -981,11 +989,12 @@ namespace AzToolsFramework AZStd::vector instances; EntityList inputEntityList = EntityIdSetToEntityList(duplicationSet); - bool success = RetrieveAndSortPrefabEntitiesAndInstances(inputEntityList, commonOwningInstance->get(), entities, instances); + PrefabOperationResult retrieveEntitiesAndInstancesOutcome = + RetrieveAndSortPrefabEntitiesAndInstances(inputEntityList, commonOwningInstance->get(), entities, instances); - if (!success) + if (!retrieveEntitiesAndInstancesOutcome.IsSuccess()) { - return AZ::Failure(AZStd::string("Failed to retrieve entities and instances from the given list of entity ids for duplication")); + return AZStd::move(retrieveEntitiesAndInstancesOutcome); } // Take a snapshot of the instance DOM before we manipulate it @@ -1128,11 +1137,12 @@ namespace AzToolsFramework AZStd::vector entities; AZStd::vector instances; - bool success = RetrieveAndSortPrefabEntitiesAndInstances(inputEntityList, commonOwningInstance->get(), entities, instances); + PrefabOperationResult retrieveEntitiesAndInstancesOutcome = + RetrieveAndSortPrefabEntitiesAndInstances(inputEntityList, commonOwningInstance->get(), entities, instances); - if (!success) + if (!retrieveEntitiesAndInstancesOutcome.IsSuccess()) { - return AZ::Failure(AZStd::string("DeleteEntitiesAndAllDescendantsInInstance")); + return AZStd::move(retrieveEntitiesAndInstancesOutcome); } for (AZ::Entity* entity : entities) @@ -1405,13 +1415,16 @@ namespace AzToolsFramework return nullptr; } - bool PrefabPublicHandler::RetrieveAndSortPrefabEntitiesAndInstances( - const EntityList& inputEntities, Instance& commonRootEntityOwningInstance, - EntityList& outEntities, AZStd::vector& outInstances) const + PrefabOperationResult PrefabPublicHandler::RetrieveAndSortPrefabEntitiesAndInstances( + const EntityList& inputEntities, + Instance& commonRootEntityOwningInstance, + EntityList& outEntities, + AZStd::vector& outInstances) const { if (inputEntities.size() == 0) { - return false; + return AZ::Failure( + AZStd::string("An empty list of input entities is provided to retrieve the prefab entities and instances.")); } AZStd::queue entityQueue; @@ -1438,8 +1451,8 @@ namespace AzToolsFramework AZ_Assert( owningInstance.has_value(), "An error occurred while retrieving entities and prefab instances : " - "Owning instance of entity with id '%llu' couldn't be found", - entity->GetId()); + "Owning instance of entity with name '%s' and id '%llu' couldn't be found", + entity->GetName().c_str(), static_cast(entity->GetId())); // Check if this entity is owned by the same instance owning the root. if (&owningInstance->get() == &commonRootEntityOwningInstance) @@ -1480,7 +1493,10 @@ namespace AzToolsFramework else { // This can only happen if one entity does not share the common root! - return false; + return AZ::Failure(AZStd::string::format( + "Entity with name '%s' and id '%llu' has an owning instance that doesn't belong to the instance " + "hierarchy of the selected entities.", + entity->GetName().c_str(), static_cast(entity->GetId()))); } } } @@ -1501,7 +1517,12 @@ namespace AzToolsFramework outInstances.push_back(instancePtr); } - return (outEntities.size() + outInstances.size()) > 0; + if ((outEntities.size() + outInstances.size()) == 0) + { + return AZ::Failure( + AZStd::string("An empty list of entities and prefab instances were retrieved from the selected entities")); + } + return AZ::Success(); } EntityIdList PrefabPublicHandler::GenerateEntityIdListWithoutLevelInstance( diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.h index f0c88a7a79..0e24b0841d 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.h @@ -64,8 +64,11 @@ namespace AzToolsFramework private: PrefabOperationResult DeleteFromInstance(const EntityIdList& entityIds, bool deleteDescendants); - bool RetrieveAndSortPrefabEntitiesAndInstances(const EntityList& inputEntities, Instance& commonRootEntityOwningInstance, - EntityList& outEntities, AZStd::vector& outInstances) const; + PrefabOperationResult RetrieveAndSortPrefabEntitiesAndInstances( + const EntityList& inputEntities, + Instance& commonRootEntityOwningInstance, + EntityList& outEntities, + AZStd::vector& outInstances) const; EntityIdList GenerateEntityIdListWithoutLevelInstance(const EntityIdList& entityIds) const; InstanceOptionalReference GetOwnerInstanceByEntityId(AZ::EntityId entityId) const; From 99f7085c05450983e187bc31c16084f6d3c7ec59 Mon Sep 17 00:00:00 2001 From: amzn-phist <52085794+amzn-phist@users.noreply.github.com> Date: Thu, 29 Jul 2021 14:56:13 -0500 Subject: [PATCH 106/160] Fixes resource selectors not showing (#2621) These statics were getting dead-stripped by the compiler, so removed some of the macro magic and just do direct registration instead. Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com> --- .../Editor/AudioControlsEditorPlugin.cpp | 4 +- .../Source/Editor/AudioResourceSelectors.cpp | 37 +++++++++++++++---- .../Source/Editor/AudioResourceSelectors.h | 14 +++++++ .../Code/audiosystem_editor_files.cmake | 1 + 4 files changed, 46 insertions(+), 10 deletions(-) create mode 100644 Gems/AudioSystem/Code/Source/Editor/AudioResourceSelectors.h diff --git a/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorPlugin.cpp b/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorPlugin.cpp index 973cb836a0..b318cea128 100644 --- a/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorPlugin.cpp +++ b/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorPlugin.cpp @@ -14,7 +14,7 @@ #include #include -#include +#include #include #include @@ -39,7 +39,7 @@ CAudioControlsEditorPlugin::CAudioControlsEditorPlugin(IEditor* editor) QtViewOptions options; options.canHaveMultipleInstances = true; RegisterQtViewPane(editor, LyViewPane::AudioControlsEditor, LyViewPane::CategoryOther, options); - RegisterModuleResourceSelectors(GetIEditor()->GetResourceSelectorHost()); + RegisterAudioControlsResourceSelectors(); Audio::AudioSystemRequestBus::BroadcastResult(ms_pIAudioProxy, &Audio::AudioSystemRequestBus::Events::GetFreeAudioProxy); diff --git a/Gems/AudioSystem/Code/Source/Editor/AudioResourceSelectors.cpp b/Gems/AudioSystem/Code/Source/Editor/AudioResourceSelectors.cpp index f0c9ebe3d1..74233be2e9 100644 --- a/Gems/AudioSystem/Code/Source/Editor/AudioResourceSelectors.cpp +++ b/Gems/AudioSystem/Code/Source/Editor/AudioResourceSelectors.cpp @@ -7,14 +7,13 @@ */ +#include #include #include #include #include #include -using namespace AudioControls; - namespace AudioControls { //-------------------------------------------------------------------------------------------// @@ -67,10 +66,32 @@ namespace AudioControls } //-------------------------------------------------------------------------------------------// - REGISTER_RESOURCE_SELECTOR("AudioTrigger", AudioTriggerSelector, ":/AudioControlsEditor/Icons/Trigger_Icon.png"); - REGISTER_RESOURCE_SELECTOR("AudioSwitch", AudioSwitchSelector, ":/AudioControlsEditor/Icons/Switch_Icon.png"); - REGISTER_RESOURCE_SELECTOR("AudioSwitchState", AudioSwitchStateSelector, ":/AudioControlsEditor/Icons/State_Icon.png"); - REGISTER_RESOURCE_SELECTOR("AudioRTPC", AudioRTPCSelector, ":/AudioControlsEditor/Icons/RTPC_Icon.png"); - REGISTER_RESOURCE_SELECTOR("AudioEnvironment", AudioEnvironmentSelector, ":/AudioControlsEditor/Icons/Environment_Icon.png"); - REGISTER_RESOURCE_SELECTOR("AudioPreloadRequest", AudioPreloadRequestSelector, ":/AudioControlsEditor/Icons/Bank_Icon.png"); + static SStaticResourceSelectorEntry audioTriggerSelector( + "AudioTrigger", AudioTriggerSelector, ":/Icons/Trigger_Icon.svg"); + static SStaticResourceSelectorEntry audioSwitchSelector( + "AudioSwitch", AudioSwitchSelector, ":/Icons/Switch_Icon.svg"); + static SStaticResourceSelectorEntry audioStateSelector( + "AudioSwitchState", AudioSwitchStateSelector, ":/Icons/Property_Icon.png"); + static SStaticResourceSelectorEntry audioRtpcSelector( + "AudioRTPC", AudioRTPCSelector, ":/Icons/RTPC_Icon.svg"); + static SStaticResourceSelectorEntry audioEnvironmentSelector( + "AudioEnvironment", AudioEnvironmentSelector, ":/Icons/Environment_Icon.svg"); + static SStaticResourceSelectorEntry audioPreloadSelector( + "AudioPreloadRequest", AudioPreloadRequestSelector, ":/Icons/Bank_Icon.png"); + + //-------------------------------------------------------------------------------------------// + void RegisterAudioControlsResourceSelectors() + { + if (IResourceSelectorHost* host = GetIEditor()->GetResourceSelectorHost(); + host != nullptr) + { + host->RegisterResourceSelector(&audioTriggerSelector); + host->RegisterResourceSelector(&audioSwitchSelector); + host->RegisterResourceSelector(&audioStateSelector); + host->RegisterResourceSelector(&audioRtpcSelector); + host->RegisterResourceSelector(&audioEnvironmentSelector); + host->RegisterResourceSelector(&audioPreloadSelector); + } + } + } // namespace AudioControls diff --git a/Gems/AudioSystem/Code/Source/Editor/AudioResourceSelectors.h b/Gems/AudioSystem/Code/Source/Editor/AudioResourceSelectors.h new file mode 100644 index 0000000000..d2bff7c799 --- /dev/null +++ b/Gems/AudioSystem/Code/Source/Editor/AudioResourceSelectors.h @@ -0,0 +1,14 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#pragma once + +namespace AudioControls +{ + void RegisterAudioControlsResourceSelectors(); +} diff --git a/Gems/AudioSystem/Code/audiosystem_editor_files.cmake b/Gems/AudioSystem/Code/audiosystem_editor_files.cmake index 9333cea7e3..25f78121d6 100644 --- a/Gems/AudioSystem/Code/audiosystem_editor_files.cmake +++ b/Gems/AudioSystem/Code/audiosystem_editor_files.cmake @@ -54,6 +54,7 @@ set(FILES Source/Editor/AudioControlsEditorWindow.h Source/Editor/AudioControlsLoader.h Source/Editor/AudioControlsWriter.h + Source/Editor/AudioResourceSelectors.h Source/Editor/AudioSystemPanel.h Source/Editor/ImplementationManager.h Source/Editor/InspectorPanel.h From ca2889a0efda03202a41dacc6f11ad10d6ad686d Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Thu, 29 Jul 2021 15:17:58 -0500 Subject: [PATCH 107/160] fixing material property override lua test script O3DE vector usage in lua has changed since script was written Signed-off-by: Guthrie Adams --- .../material_property_overrides_demo.lua | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/Gems/Atom/Feature/Common/Assets/Scripts/material_property_overrides_demo.lua b/Gems/Atom/Feature/Common/Assets/Scripts/material_property_overrides_demo.lua index c470748801..685fd8310b 100644 --- a/Gems/Atom/Feature/Common/Assets/Scripts/material_property_overrides_demo.lua +++ b/Gems/Atom/Feature/Common/Assets/Scripts/material_property_overrides_demo.lua @@ -53,10 +53,9 @@ function PropertyOverrideTest:OnActivate() self.originalAssignments = MaterialComponentRequestBus.Event.GetOriginalMaterialAssignments(self.entityId); self.assignmentIds = self.originalAssignments:GetKeys() - for index = 0, self.assignmentIds:Size() do - local idOutcome = self.assignmentIds:At(index) - if (idOutcome:IsSuccess()) then - local id = idOutcome:GetValue() + for index = 1, self.assignmentIds:GetSize() do + local id = self.assignmentIds[index] + if (id ~= nil) then self.colors[index] = randomColor() self.lerpDirs[index] = randomDir() end @@ -88,10 +87,9 @@ end function PropertyOverrideTest:UpdateProperties() Debug.Log("Overriding properties...") - for index = 0, self.assignmentIds:Size() do - local idOutcome = self.assignmentIds:At(index) - if (idOutcome:IsSuccess()) then - local id = idOutcome:GetValue() + for index = 1, self.assignmentIds:GetSize() do + local id = self.assignmentIds[index] + if (id ~= nil) then self:UpdateFactor(id) self:UpdateTexture(id) end @@ -134,10 +132,9 @@ function lerpColor(color, lerpDir, deltaTime) end function PropertyOverrideTest:lerpColors(deltaTime) - for index = 0, self.assignmentIds:Size() do - local idOutcome = self.assignmentIds:At(index) - if (idOutcome:IsSuccess()) then - local id = idOutcome:GetValue() + for index = 1, self.assignmentIds:GetSize() do + local id = self.assignmentIds[index] + if (id ~= nil) then lerpColor(self.colors[index], self.lerpDirs[index], deltaTime) self:UpdateColor(id, self.colors[index]) end From 8612d7bce293c4f79ca115262cbf42d051e352a9 Mon Sep 17 00:00:00 2001 From: puvvadar Date: Thu, 29 Jul 2021 13:35:32 -0700 Subject: [PATCH 108/160] Fix incorrect blending math Signed-off-by: puvvadar --- .../Components/LocalPredictionPlayerInputComponent.cpp | 2 +- .../Code/Source/MultiplayerSystemComponent.cpp | 8 ++++---- Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h | 1 + 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp b/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp index a3a5a31eb2..23578e5c18 100644 --- a/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp @@ -157,7 +157,7 @@ namespace Multiplayer { // Client blends from previous frame to target so here we subtract blend factor to get to that state const float blendFactor = AZStd::min(AZStd::max(0.f, input.GetHostBlendFactor()), 1.f); - const AZ::TimeMs blendMs = AZ::TimeMs(static_cast(static_cast(cl_InputRateMs)) * blendFactor); + const AZ::TimeMs blendMs = AZ::TimeMs(static_cast(static_cast(cl_InputRateMs)) * (1.f - blendFactor)); m_clientBankedTime = AZStd::min(m_clientBankedTime + clientInputRateSec, (double)sv_MaxBankTimeWindowSec); // clamp to boundary { ScopedAlterTime scopedTime(input.GetHostFrameId(), input.GetHostTimeMs() - blendMs, input.GetHostBlendFactor(), invokingConnection->GetConnectionId()); diff --git a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp index c16d35e725..893e53fbf6 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp +++ b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp @@ -861,12 +861,12 @@ namespace Multiplayer { m_tickFactor += deltaTime / serverRateSeconds; // Linear close to the origin, but asymptote at y = 1 - const float renderBlendFactor = AZStd::clamp(1.0f - (std::pow(cl_renderTickBlendBase, m_tickFactor)), 0.0f, 1.0f); + m_renderBlendFactor = AZStd::clamp(1.0f - (std::pow(cl_renderTickBlendBase, m_tickFactor)), 0.0f, 1.0f); AZLOG ( NET_Blending, "Computed blend factor of %0.3f using a tick factor of %0.3f, a frametime of %0.3f and a serverTickRate of %0.3f", - renderBlendFactor, + m_renderBlendFactor, m_tickFactor, deltaTime, serverRateSeconds @@ -913,7 +913,7 @@ namespace Multiplayer for (NetBindComponent* netBindComponent : gatheredEntities) { - netBindComponent->NotifyPreRender(deltaTime, renderBlendFactor); + netBindComponent->NotifyPreRender(deltaTime, m_renderBlendFactor); } } else @@ -925,7 +925,7 @@ namespace Multiplayer NetBindComponent* netBindComponent = entity->FindComponent(); if (netBindComponent != nullptr) { - netBindComponent->NotifyPreRender(deltaTime, renderBlendFactor); + netBindComponent->NotifyPreRender(deltaTime, m_renderBlendFactor); } } } diff --git a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h index 36ef45d647..5f0e23b2dc 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h +++ b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h @@ -156,6 +156,7 @@ namespace Multiplayer HostFrameId m_lastReplicatedHostFrameId = HostFrameId(0); double m_serverSendAccumulator = 0.0; + float m_renderBlendFactor = 0.0f; float m_tickFactor = 0.0f; #if !defined(AZ_RELEASE_BUILD) From 70b3840288679dbca7cabebc5d48d8756f8dee39 Mon Sep 17 00:00:00 2001 From: Nicholas Van Sickle Date: Thu, 29 Jul 2021 14:30:45 -0700 Subject: [PATCH 109/160] Fix the home key popping up ImGui when it shouldn't. (#2620) This disables WM_INPUT forwarding to the input system while in game mode and makes ImGui listen to the synthetic keyboard events from the viewport instead - these synthetic events go through Qt's event system, so will only show up when the viewport "sees" a home key press. Signed-off-by: nvsickle --- Code/Editor/Core/QtEditorApplication.cpp | 42 +++++++++++++----------- Gems/ImGui/Code/Source/ImGuiManager.cpp | 20 +++++------ 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/Code/Editor/Core/QtEditorApplication.cpp b/Code/Editor/Core/QtEditorApplication.cpp index 46e789cd7c..5a4763d8e8 100644 --- a/Code/Editor/Core/QtEditorApplication.cpp +++ b/Code/Editor/Core/QtEditorApplication.cpp @@ -415,33 +415,37 @@ namespace Editor } // Ensure that the Windows WM_INPUT messages get passed through to the AzFramework input system. - // These events are now consumed both in and out of game mode. - if (msg->message == WM_INPUT) + // These events are only broadcast in game mode. In Editor mode, RenderViewportWidget creates synthetic + // keyboard and mouse events via Qt. + if (GetIEditor()->IsInGameMode()) { - UINT rawInputSize; - const UINT rawInputHeaderSize = sizeof(RAWINPUTHEADER); - GetRawInputData((HRAWINPUT)msg->lParam, RID_INPUT, NULL, &rawInputSize, rawInputHeaderSize); + if (msg->message == WM_INPUT) + { + UINT rawInputSize; + const UINT rawInputHeaderSize = sizeof(RAWINPUTHEADER); + GetRawInputData((HRAWINPUT)msg->lParam, RID_INPUT, NULL, &rawInputSize, rawInputHeaderSize); - AZStd::array rawInputBytesArray; - LPBYTE rawInputBytes = rawInputBytesArray.data(); + AZStd::array rawInputBytesArray; + LPBYTE rawInputBytes = rawInputBytesArray.data(); - const UINT bytesCopied = GetRawInputData((HRAWINPUT)msg->lParam, RID_INPUT, rawInputBytes, &rawInputSize, rawInputHeaderSize); - CRY_ASSERT(bytesCopied == rawInputSize); + const UINT bytesCopied = GetRawInputData((HRAWINPUT)msg->lParam, RID_INPUT, rawInputBytes, &rawInputSize, rawInputHeaderSize); + CRY_ASSERT(bytesCopied == rawInputSize); - RAWINPUT* rawInput = (RAWINPUT*)rawInputBytes; - CRY_ASSERT(rawInput); + RAWINPUT* rawInput = (RAWINPUT*)rawInputBytes; + CRY_ASSERT(rawInput); - AzFramework::RawInputNotificationBusWindows::Broadcast(&AzFramework::RawInputNotificationsWindows::OnRawInputEvent, *rawInput); + AzFramework::RawInputNotificationBusWindows::Broadcast(&AzFramework::RawInputNotificationsWindows::OnRawInputEvent, *rawInput); - return false; - } - else if (msg->message == WM_DEVICECHANGE) - { - if (msg->wParam == 0x0007) // DBT_DEVNODES_CHANGED + return false; + } + else if (msg->message == WM_DEVICECHANGE) { - AzFramework::RawInputNotificationBusWindows::Broadcast(&AzFramework::RawInputNotificationsWindows::OnRawInputDeviceChangeEvent); + if (msg->wParam == 0x0007) // DBT_DEVNODES_CHANGED + { + AzFramework::RawInputNotificationBusWindows::Broadcast(&AzFramework::RawInputNotificationsWindows::OnRawInputDeviceChangeEvent); + } + return true; } - return true; } return false; diff --git a/Gems/ImGui/Code/Source/ImGuiManager.cpp b/Gems/ImGui/Code/Source/ImGuiManager.cpp index cd8486b711..ac3247b6a4 100644 --- a/Gems/ImGui/Code/Source/ImGuiManager.cpp +++ b/Gems/ImGui/Code/Source/ImGuiManager.cpp @@ -452,7 +452,7 @@ bool ImGuiManager::OnInputChannelEventFiltered(const InputChannel& inputChannel) const InputDeviceId& inputDeviceId = inputChannel.GetInputDevice().GetInputDeviceId(); // Handle Keyboard Hotkeys - if (inputDeviceId == InputDeviceKeyboard::Id && inputChannel.IsStateBegan()) + if (InputDeviceKeyboard::IsKeyboardDevice(inputDeviceId) && inputChannel.IsStateBegan()) { // Cycle through ImGui Menu Bar States on Home button press if (inputChannelId == InputDeviceKeyboard::Key::NavigationHome) @@ -477,7 +477,7 @@ bool ImGuiManager::OnInputChannelEventFiltered(const InputChannel& inputChannel) } // Handle Keyboard Modifier Keys - if (inputDeviceId == InputDeviceKeyboard::Id) + if (InputDeviceKeyboard::IsKeyboardDevice(inputDeviceId)) { if (inputChannelId == InputDeviceKeyboard::Key::ModifierShiftL || inputChannelId == InputDeviceKeyboard::Key::ModifierShiftR) @@ -506,14 +506,10 @@ bool ImGuiManager::OnInputChannelEventFiltered(const InputChannel& inputChannel) // Handle Controller Inputs int inputControllerIndex = -1; bool controllerInput = false; - for (int i = 0; i < MaxControllerNumber; ++i) + if (InputDeviceGamepad::IsGamepadDevice(inputDeviceId)) { - //Allow only one controller navigating ImGui at the same time. After menu bar dismissed, other controllers could take over - if (inputDeviceId == InputDeviceGamepad::IdForIndexN(i)) - { - inputControllerIndex = i; - controllerInput = true; - } + inputControllerIndex = inputDeviceId.GetIndex(); + controllerInput = true; } @@ -570,7 +566,7 @@ bool ImGuiManager::OnInputChannelEventFiltered(const InputChannel& inputChannel) } // Handle Mouse Inputs - if (inputDeviceId == InputDeviceMouse::Id) + if (InputDeviceMouse::IsMouseDevice(inputDeviceId)) { const int mouseButtonIndex = GetAzMouseButtonIndex(inputChannelId); if (0 <= mouseButtonIndex && mouseButtonIndex < AZ_ARRAY_SIZE(io.MouseDown)) @@ -584,7 +580,7 @@ bool ImGuiManager::OnInputChannelEventFiltered(const InputChannel& inputChannel) } // Handle Touch Inputs - if (inputDeviceId == InputDeviceTouch::Id) + if (InputDeviceTouch::IsTouchDevice(inputDeviceId)) { const int touchIndex = GetAzTouchIndex(inputChannelId); if (0 <= touchIndex && touchIndex < AZ_ARRAY_SIZE(io.MouseDown)) @@ -605,7 +601,7 @@ bool ImGuiManager::OnInputChannelEventFiltered(const InputChannel& inputChannel) } // Handle Virtual Keyboard Inputs - if (inputDeviceId == InputDeviceVirtualKeyboard::Id) + if (InputDeviceVirtualKeyboard::IsVirtualKeyboardDevice(inputDeviceId)) { if (inputChannelId == AzFramework::InputDeviceVirtualKeyboard::Command::EditEnter) { From 4d618ea619e8bb2b6e4c930f77bd97411ae4d50a Mon Sep 17 00:00:00 2001 From: Jacob Hilliard Date: Tue, 20 Jul 2021 16:03:22 -0700 Subject: [PATCH 110/160] Profiling: Add more instrumentation Adds new instrumentation macros throughout the codebase, using the visualizer to find where current instrumentation is lacking using the shadowed sponza sample + editor. Some notes from exploring: - We spend ~5ms in CullingScene: BeginCulling - PipelineStateCache: Compact usually 1ms - CompileImageBarriers takes most of the time in CompileResourceBarriers Signed-off-by: Jacob Hilliard --- Gems/Atom/RHI/Code/Source/RHI/FrameGraph.cpp | 1 + Gems/Atom/RHI/Code/Source/RHI/FrameGraphExecuter.cpp | 1 + Gems/Atom/RHI/Code/Source/RHI/PipelineStateCache.cpp | 2 ++ Gems/Atom/RHI/Code/Source/RHI/RHISystem.cpp | 2 +- Gems/Atom/RHI/DX12/Code/Source/RHI/FrameGraphCompiler.cpp | 2 ++ Gems/Atom/RPI/Code/Source/RPI.Public/Culling.cpp | 1 + Gems/Atom/RPI/Code/Source/RPI.Public/Pass/PassSystem.cpp | 7 ++++++- Gems/Atom/RPI/Code/Source/RPI.Public/Scene.cpp | 4 +++- 8 files changed, 17 insertions(+), 3 deletions(-) diff --git a/Gems/Atom/RHI/Code/Source/RHI/FrameGraph.cpp b/Gems/Atom/RHI/Code/Source/RHI/FrameGraph.cpp index b670dc1234..d2298cda3f 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/FrameGraph.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/FrameGraph.cpp @@ -126,6 +126,7 @@ namespace AZ ResultCode FrameGraph::End() { + AZ_ATOM_PROFILE_FUNCTION("RHI", "FrameGraph: End"); ResultCode resultCode = ValidateEnd(); if (resultCode != ResultCode::Success) { diff --git a/Gems/Atom/RHI/Code/Source/RHI/FrameGraphExecuter.cpp b/Gems/Atom/RHI/Code/Source/RHI/FrameGraphExecuter.cpp index 3189acab49..342e537993 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/FrameGraphExecuter.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/FrameGraphExecuter.cpp @@ -72,6 +72,7 @@ namespace AZ void FrameGraphExecuter::Begin(const FrameGraph& frameGraph) { AZ_TRACE_METHOD(); + AZ_ATOM_PROFILE_FUNCTION("RHI", "FrameGraphExecuter: Begin"); BeginInternal(frameGraph); } diff --git a/Gems/Atom/RHI/Code/Source/RHI/PipelineStateCache.cpp b/Gems/Atom/RHI/Code/Source/RHI/PipelineStateCache.cpp index 1170b82d78..0210d941dc 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/PipelineStateCache.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/PipelineStateCache.cpp @@ -6,6 +6,7 @@ * */ +#include #include #include #include @@ -205,6 +206,7 @@ namespace AZ void PipelineStateCache::Compact() { + AZ_ATOM_PROFILE_FUNCTION("RHI", "PipelineStateCache: Compact"); AZStd::unique_lock lock(m_mutex); // Merge the pending cache into the read-only cache. diff --git a/Gems/Atom/RHI/Code/Source/RHI/RHISystem.cpp b/Gems/Atom/RHI/Code/Source/RHI/RHISystem.cpp index 083fb87b93..49244f776f 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/RHISystem.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/RHISystem.cpp @@ -223,7 +223,7 @@ namespace AZ * own RHI scopes to the frame scheduler. This happens prior to the RPI pass graph registration. */ { - AZ_ATOM_PROFILE_TIME_GROUP_REGION("RHI", "RHISystem :FrameUpdate: OnFramePrepare"); + AZ_ATOM_PROFILE_TIME_GROUP_REGION("RHI", "RHISystem: FrameUpdate: OnFramePrepare"); RHISystemNotificationBus::Broadcast(&RHISystemNotificationBus::Events::OnFramePrepare, m_frameScheduler); } diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI/FrameGraphCompiler.cpp b/Gems/Atom/RHI/DX12/Code/Source/RHI/FrameGraphCompiler.cpp index c98fd51fbb..ba4aa76a60 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/RHI/FrameGraphCompiler.cpp +++ b/Gems/Atom/RHI/DX12/Code/Source/RHI/FrameGraphCompiler.cpp @@ -469,6 +469,8 @@ namespace AZ ResourceTransitionLoggerNull logger(imageFrameAttachment.GetId()); #endif + AZ_ATOM_PROFILE_FUNCTION("RHI", "FrameGraphCompiler: CompileImageBarriers (DX12)"); + Image& image = static_cast(*imageFrameAttachment.GetImage()); RHI::ImageScopeAttachment* scopeAttachment = imageFrameAttachment.GetFirstScopeAttachment(); diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Culling.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Culling.cpp index e192e71fc4..c630fe0e5d 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Culling.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Culling.cpp @@ -720,6 +720,7 @@ namespace AZ void CullingScene::BeginCulling(const AZStd::vector& views) { + AZ_ATOM_PROFILE_FUNCTION("RPI", "CullingScene: BeginCulling"); m_cullDataConcurrencyCheck.soft_lock(); m_debugCtx.ResetCullStats(); diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/PassSystem.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/PassSystem.cpp index f62dfa1d70..27e3612a4c 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/PassSystem.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/PassSystem.cpp @@ -298,6 +298,7 @@ namespace AZ void PassSystem::ProcessQueuedChanges() { + AZ_ATOM_PROFILE_FUNCTION("RPI", "PassSystem: ProcessQueuedChanges"); RemovePasses(); BuildPasses(); InitializePasses(); @@ -313,7 +314,11 @@ namespace AZ m_state = PassSystemState::Rendering; Pass::FramePrepareParams params{ &frameGraphBuilder }; - m_rootPass->FrameBegin(params); + + { + AZ_ATOM_PROFILE_TIME_GROUP_REGION("RPI", "Pass: FrameBegin"); + m_rootPass->FrameBegin(params); + } } void PassSystem::FrameEnd() diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Scene.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Scene.cpp index bc700dd24f..071a07ecda 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Scene.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Scene.cpp @@ -408,6 +408,7 @@ namespace AZ { AZ_PROFILE_SCOPE(Debug::ProfileCategory::AzRender, "m_srgCallback"); + AZ_ATOM_PROFILE_TIME_GROUP_REGION("RPI", "ShaderResourceGroupCallback: SrgCallback"); // Set values for scene srg if (m_srg && m_srgCallback) { @@ -418,7 +419,7 @@ namespace AZ // Get active pipelines which need to be rendered and notify them frame started AZStd::vector activePipelines; { - AZ_ATOM_PROFILE_TIME_GROUP_REGION("RPI", "OnStartFrame"); + AZ_ATOM_PROFILE_TIME_GROUP_REGION("RPI", "Scene: OnStartFrame"); for (auto& pipeline : m_pipelines) { if (pipeline->NeedsRender()) @@ -483,6 +484,7 @@ namespace AZ { AZ_PROFILE_SCOPE(Debug::ProfileCategory::AzRender, "CollectDrawPackets"); + AZ_ATOM_PROFILE_TIME_GROUP_REGION("RPI", "CollectDrawPackets"); AZ::JobCompletion* collectDrawPacketsCompletion = aznew AZ::JobCompletion(); // Launch FeatureProcessor::Render() jobs From ffbeb903c1ee70ef978c37c420b8402bb4516bb3 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Thu, 29 Jul 2021 18:09:40 -0500 Subject: [PATCH 111/160] Material Component: Add functions to lookup material ids by name Signed-off-by: Guthrie Adams --- .../Scripts/material_find_overrides_demo.lua | 160 ++++++++++++++++++ .../Feature/Material/MaterialAssignment.h | 7 +- .../Source/Material/MaterialAssignment.cpp | 43 +++++ .../Material/MaterialComponentBus.h | 5 + .../Material/MaterialComponentController.cpp | 13 +- .../Material/MaterialComponentController.h | 1 + .../Source/Mesh/MeshComponentController.cpp | 6 + .../Source/Mesh/MeshComponentController.h | 2 + .../Code/Source/AtomActorInstance.cpp | 11 ++ .../Code/Source/AtomActorInstance.h | 2 + 10 files changed, 247 insertions(+), 3 deletions(-) create mode 100644 Gems/Atom/Feature/Common/Assets/Scripts/material_find_overrides_demo.lua diff --git a/Gems/Atom/Feature/Common/Assets/Scripts/material_find_overrides_demo.lua b/Gems/Atom/Feature/Common/Assets/Scripts/material_find_overrides_demo.lua new file mode 100644 index 0000000000..dda3974043 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Scripts/material_find_overrides_demo.lua @@ -0,0 +1,160 @@ +---------------------------------------------------------------------------------------------------- +-- +-- Copyright (c) Contributors to the Open 3D Engine Project. +-- For complete copyright and license terms please see the LICENSE at the root of this distribution. +-- +-- SPDX-License-Identifier: Apache-2.0 OR MIT +-- +-- +-- +---------------------------------------------------------------------------------------------------- + +local FindMaterialAssignmentTest = +{ + Properties = + { + Textures = + { + "materials/presets/macbeth/05_blue_flower_srgb.tif.streamingimage", + "materials/presets/macbeth/06_bluish_green_srgb.tif.streamingimage", + "materials/presets/macbeth/09_moderate_red_srgb.tif.streamingimage", + "materials/presets/macbeth/11_yellow_green_srgb.tif.streamingimage", + "materials/presets/macbeth/12_orange_yellow_srgb.tif.streamingimage", + "materials/presets/macbeth/17_magenta_srgb.tif.streamingimage" + }, + }, +} + +function randomColor() + return Color(math.random(), math.random(), math.random(), 1.0) +end + +function randomDir() + dir = {} + for i = 1, 3 do + lerpDir = math.random() + if lerpDir < 0.5 then + table.insert(dir, -1.0) + else + table.insert(dir, 1.0) + end + end + return dir +end + +function FindMaterialAssignmentTest:OnActivate() + self.timer = 0.0 + self.totalTime = 0.0 + self.totalTimeMax = 200.0 + self.timeUpdate = 2.0 + self.colors = {} + self.lerpDirs = {} + + self.assignmentIds = + { + MaterialComponentRequestBus.Event.FindMaterialAssignmentId(self.entityId, -1, "lambert"), + } + + for index = 1, #self.assignmentIds do + local id = self.assignmentIds[index] + if (id ~= nil) then + self.colors[index] = randomColor() + self.lerpDirs[index] = randomDir() + end + end + self.tickBusHandler = TickBus.Connect(self); +end + +function FindMaterialAssignmentTest:UpdateFactor(assignmentId) + local propertyName = Name("baseColor.factor") + local propertyValue = math.random() + MaterialComponentRequestBus.Event.SetPropertyOverride(self.entityId, assignmentId, propertyName, propertyValue); +end + +function FindMaterialAssignmentTest:UpdateColor(assignmentId, color) + local propertyName = Name("baseColor.color") + local propertyValue = color + MaterialComponentRequestBus.Event.SetPropertyOverride(self.entityId, assignmentId, propertyName, propertyValue); +end + +function FindMaterialAssignmentTest:UpdateTexture(assignmentId) + if (#self.Properties.Textures > 0) then + local propertyName = Name("baseColor.textureMap") + local textureName = self.Properties.Textures[ math.random( #self.Properties.Textures ) ] + Debug.Log(textureName) + local textureAssetId = AssetCatalogRequestBus.Broadcast.GetAssetIdByPath(textureName, Uuid(), false) + MaterialComponentRequestBus.Event.SetPropertyOverride(self.entityId, assignmentId, propertyName, textureAssetId); + end +end + +function FindMaterialAssignmentTest:UpdateProperties() + Debug.Log("Overriding properties...") + for index = 1, #self.assignmentIds do + local id = self.assignmentIds[index] + if (id ~= nil) then + self:UpdateFactor(id) + self:UpdateTexture(id) + end + end +end + +function FindMaterialAssignmentTest:ClearProperties() + Debug.Log("Clearing properties...") + MaterialComponentRequestBus.Event.ClearAllPropertyOverrides(self.entityId); +end + +function lerpColor(color, lerpDir, deltaTime) + local lerpSpeed = 0.5 + color.r = color.r + deltaTime * lerpDir[1] * lerpSpeed + if color.r > 1.0 then + color.r = 1.0 + lerpDir[1] = -1.0 + elseif color.r < 0 then + color.r = 0 + lerpDir[1] = 1.0 + end + + color.g = color.g + deltaTime * lerpDir[2] * lerpSpeed + if color.g > 1.0 then + color.g = 1.0 + lerpDir[2] = -1.0 + elseif color.g < 0 then + color.g = 0 + lerpDir[2] = 1.0 + end + + color.b = color.b + deltaTime * lerpDir[3] * lerpSpeed + if color.b > 1.0 then + color.b = 1.0 + lerpDir[3] = -1.0 + elseif color.b < 0 then + color.b = 0 + lerpDir[3] = 1.0 + end +end + +function FindMaterialAssignmentTest:lerpColors(deltaTime) + for index = 1, #self.assignmentIds do + local id = self.assignmentIds[index] + if (id ~= nil) then + lerpColor(self.colors[index], self.lerpDirs[index], deltaTime) + self:UpdateColor(id, self.colors[index]) + end + end +end + +function FindMaterialAssignmentTest:OnTick(deltaTime, timePoint) + self.timer = self.timer + deltaTime + self.totalTime = self.totalTime + deltaTime + self:lerpColors(deltaTime) + + if (self.timer > self.timeUpdate and self.totalTime < self.totalTimeMax) then + self.timer = self.timer - self.timeUpdate + self:UpdateProperties() + elseif self.totalTime > self.totalTimeMax then + self:ClearProperties() + self.tickBusHandler:Disconnect(self); + end +end + +return FindMaterialAssignmentTest \ No newline at end of file diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Material/MaterialAssignment.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Material/MaterialAssignment.h index 12a9c0fccc..f0f66cbd4c 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Material/MaterialAssignment.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Material/MaterialAssignment.h @@ -63,5 +63,8 @@ namespace AZ //! Utility function for generating a set of available material assignments in a model MaterialAssignmentMap GetMaterialAssignmentsFromModel(Data::Instance model); - } // namespace Render -} // namespace AZ + //! Find an assignment id corresponding to the lod and label substring filters + MaterialAssignmentId FindMaterialAssignmentIdInModel( + const Data::Instance model, const MaterialAssignmentLodIndex lodFilter, const AZStd::string& labelFilter); + } // namespace R ender + } // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/Material/MaterialAssignment.cpp b/Gems/Atom/Feature/Common/Code/Source/Material/MaterialAssignment.cpp index ec48d57d1a..074d5c39e8 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Material/MaterialAssignment.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Material/MaterialAssignment.cpp @@ -166,5 +166,48 @@ namespace AZ return materials; } + + MaterialAssignmentId FindMaterialAssignmentIdInLod( + const Data::Instance& lod, const MaterialAssignmentLodIndex lodIndex, const AZStd::string& labelFilter) + { + for (const AZ::RPI::ModelLod::Mesh& mesh : lod->GetMeshes()) + { + if (mesh.m_material && mesh.m_material->GetAssetId().IsValid()) + { + AZ::Data::AssetInfo assetInfo; + AZ::Data::AssetCatalogRequestBus::BroadcastResult( + assetInfo, &AZ::Data::AssetCatalogRequests::GetAssetInfoById, mesh.m_material->GetAssetId()); + if (assetInfo.m_assetId.IsValid() && AZ::StringFunc::Contains(assetInfo.m_relativePath, labelFilter, true)) + { + return MaterialAssignmentId::CreateFromLodAndAsset(lodIndex, mesh.m_material->GetAssetId()); + } + } + } + return MaterialAssignmentId(); + } + + MaterialAssignmentId FindMaterialAssignmentIdInModel( + const Data::Instance model, const MaterialAssignmentLodIndex lodFilter, const AZStd::string& labelFilter) + { + if (model && !labelFilter.empty()) + { + if (lodFilter < model->GetLodCount()) + { + return FindMaterialAssignmentIdInLod(model->GetLods()[lodFilter], lodFilter, labelFilter); + } + + for (size_t lodIndex = 0; lodIndex < model->GetLodCount(); ++lodIndex) + { + const MaterialAssignmentId result = + FindMaterialAssignmentIdInLod(model->GetLods()[lodIndex], MaterialAssignmentId::NonLodIndex, labelFilter); + if (!result.IsDefault()) + { + return result; + } + } + } + + return MaterialAssignmentId(); + } } // namespace Render } // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Material/MaterialComponentBus.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Material/MaterialComponentBus.h index 134bf6db47..6b637a67c5 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Material/MaterialComponentBus.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Material/MaterialComponentBus.h @@ -21,6 +21,8 @@ namespace AZ public: //! Get all material assignments that can be overridden virtual MaterialAssignmentMap GetOriginalMaterialAssignments() const = 0; + //! Get material assignment id matching lod and label substring + virtual MaterialAssignmentId FindMaterialAssignmentId(const MaterialAssignmentLodIndex lod, const AZStd::string& label) const = 0; //! Set material overrides virtual void SetMaterialOverrides(const MaterialAssignmentMap& materials) = 0; //! Get material overrides @@ -69,6 +71,9 @@ namespace AZ : public ComponentBus { public: + //! Get material assignment id matching lod and label substring + virtual MaterialAssignmentId FindMaterialAssignmentId( + const MaterialAssignmentLodIndex lod, const AZStd::string& label) const = 0; virtual MaterialAssignmentMap GetMaterialAssignments() const = 0; virtual AZStd::unordered_set GetModelUvNames() const = 0; }; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.cpp index 5d9df24854..e39f5cfad5 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.cpp @@ -33,6 +33,7 @@ namespace AZ ->Attribute(AZ::Script::Attributes::Category, "render") ->Attribute(AZ::Script::Attributes::Module, "render") ->Event("GetOriginalMaterialAssignments", &MaterialComponentRequestBus::Events::GetOriginalMaterialAssignments) + ->Event("FindMaterialAssignmentId", &MaterialComponentRequestBus::Events::FindMaterialAssignmentId) ->Event("SetMaterialOverrides", &MaterialComponentRequestBus::Events::SetMaterialOverrides) ->Event("GetMaterialOverrides", &MaterialComponentRequestBus::Events::GetMaterialOverrides) ->Event("ClearAllMaterialOverrides", &MaterialComponentRequestBus::Events::ClearAllMaterialOverrides) @@ -249,10 +250,20 @@ namespace AZ MaterialAssignmentMap MaterialComponentController::GetOriginalMaterialAssignments() const { MaterialAssignmentMap materialAssignmentMap; - MaterialReceiverRequestBus::EventResult(materialAssignmentMap, m_entityId, &MaterialReceiverRequestBus::Events::GetMaterialAssignments); + MaterialReceiverRequestBus::EventResult( + materialAssignmentMap, m_entityId, &MaterialReceiverRequestBus::Events::GetMaterialAssignments); return materialAssignmentMap; } + MaterialAssignmentId MaterialComponentController::FindMaterialAssignmentId( + const MaterialAssignmentLodIndex lod, const AZStd::string& label) const + { + MaterialAssignmentId materialAssignmentId; + MaterialReceiverRequestBus::EventResult( + materialAssignmentId, m_entityId, &MaterialReceiverRequestBus::Events::FindMaterialAssignmentId, lod, label); + return materialAssignmentId; + } + void MaterialComponentController::SetMaterialOverrides(const MaterialAssignmentMap& materials) { // this function is called twice once material asset is changed, a temp variable is diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.h index eb1d7465c0..de7f991d60 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.h @@ -46,6 +46,7 @@ namespace AZ //! MaterialComponentRequestBus overrides... MaterialAssignmentMap GetOriginalMaterialAssignments() const override; + MaterialAssignmentId FindMaterialAssignmentId(const MaterialAssignmentLodIndex lod, const AZStd::string& label) const override; void SetMaterialOverrides(const MaterialAssignmentMap& materials) override; const MaterialAssignmentMap& GetMaterialOverrides() const override; void ClearAllMaterialOverrides() override; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp index 29bd9a839b..fa4586daba 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp @@ -252,6 +252,12 @@ namespace AZ } } + MaterialAssignmentId MeshComponentController::FindMaterialAssignmentId( + const MaterialAssignmentLodIndex lod, const AZStd::string& label) const + { + return FindMaterialAssignmentIdInModel(GetModel(), lod, label); + } + MaterialAssignmentMap MeshComponentController::GetMaterialAssignments() const { return GetMaterialAssignmentsFromModel(GetModel()); diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h index 80b483452f..d99d5000eb 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h @@ -111,6 +111,8 @@ namespace AZ void OnTransformChanged(const AZ::Transform& local, const AZ::Transform& world) override; // MaterialReceiverRequestBus::Handler overrides ... + virtual MaterialAssignmentId FindMaterialAssignmentId( + const MaterialAssignmentLodIndex lod, const AZStd::string& label) const override; MaterialAssignmentMap GetMaterialAssignments() const override; AZStd::unordered_set GetModelUvNames() const override; diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp index 4c6045d7ce..706ed27a4d 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp @@ -308,6 +308,17 @@ namespace AZ m_skinnedMeshFeatureProcessor = nullptr; } + MaterialAssignmentId AtomActorInstance::FindMaterialAssignmentId( + const MaterialAssignmentLodIndex lod, const AZStd::string& label) const + { + if (m_skinnedMeshInstance && m_skinnedMeshInstance->m_model) + { + return FindMaterialAssignmentIdInModel(m_skinnedMeshInstance->m_model, lod, label); + } + + return MaterialAssignmentId(); + } + MaterialAssignmentMap AtomActorInstance::GetMaterialAssignments() const { if (m_skinnedMeshInstance && m_skinnedMeshInstance->m_model) diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.h b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.h index c854fed3c1..1686b52d1a 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.h +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.h @@ -120,6 +120,8 @@ namespace AZ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// // MaterialReceiverRequestBus::Handler overrides... + virtual MaterialAssignmentId FindMaterialAssignmentId( + const MaterialAssignmentLodIndex lod, const AZStd::string& label) const override; MaterialAssignmentMap GetMaterialAssignments() const override; AZStd::unordered_set GetModelUvNames() const override; From e087cd87fb5d3d42a5970a2c0606b61d82fa9d34 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Fri, 30 Jul 2021 10:49:41 -0500 Subject: [PATCH 112/160] removed extra space from namespace comment Signed-off-by: Guthrie Adams --- .../Code/Include/Atom/Feature/Material/MaterialAssignment.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Material/MaterialAssignment.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Material/MaterialAssignment.h index f0f66cbd4c..907b1a1740 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Material/MaterialAssignment.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Material/MaterialAssignment.h @@ -5,6 +5,7 @@ * SPDX-License-Identifier: Apache-2.0 OR MIT * */ + #pragma once #include @@ -66,5 +67,5 @@ namespace AZ //! Find an assignment id corresponding to the lod and label substring filters MaterialAssignmentId FindMaterialAssignmentIdInModel( const Data::Instance model, const MaterialAssignmentLodIndex lodFilter, const AZStd::string& labelFilter); - } // namespace R ender - } // namespace AZ + } // namespace Render +} // namespace AZ From 0313b16a85115d71a54c1def1bd6e20d31038eb9 Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Fri, 30 Jul 2021 09:50:54 -0700 Subject: [PATCH 113/160] display unused variables in the editor; bump builder version for recent change to EntityId nodes Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com> --- .../Code/Builder/ScriptCanvasBuilder.cpp | 70 +++++++++++++++---- .../Code/Builder/ScriptCanvasBuilder.h | 14 ++-- .../Code/Builder/ScriptCanvasBuilderWorker.h | 1 + .../EditorScriptCanvasComponent.cpp | 4 +- .../Grammar/AbstractCodeModel.cpp | 23 ++++-- .../ScriptCanvas/Grammar/AbstractCodeModel.h | 5 +- 6 files changed, 82 insertions(+), 35 deletions(-) diff --git a/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilder.cpp b/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilder.cpp index 73e18a356c..9c3cdca3e8 100644 --- a/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilder.cpp +++ b/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilder.cpp @@ -31,29 +31,42 @@ namespace ScriptCanvasBuilder m_source.Reset(); m_variables.clear(); m_overrides.clear(); + m_overridesUnused.clear(); m_entityIds.clear(); m_dependencies.clear(); } void BuildVariableOverrides::CopyPreviousOverriddenValues(const BuildVariableOverrides& source) { - for (auto& overriddenValue : m_overrides) + auto copyPreviousIfFound = [](ScriptCanvas::GraphVariable& overriddenValue, const AZStd::vector& source) { - auto iter = AZStd::find_if(source.m_overrides.begin(), source.m_overrides.end(), [&overriddenValue](const auto& candidate) { return candidate.GetVariableId() == overriddenValue.GetVariableId(); }); - - if (iter != source.m_overrides.end()) + if (auto iter = AZStd::find_if(source.begin(), source.end(), [&overriddenValue](const auto& candidate) { return candidate.GetVariableId() == overriddenValue.GetVariableId(); }); + iter != source.end()) { overriddenValue.DeepCopy(*iter); overriddenValue.SetScriptInputControlVisibility(AZ::Edit::PropertyVisibility::Hide); overriddenValue.SetAllowSignalOnChange(false); - // check that a name update is not necessary anymore + return true; + } + else + { + return false; + } + }; + + for (auto& overriddenValue : m_overrides) + { + if (!copyPreviousIfFound(overriddenValue, source.m_overrides)) + { + // the variable in question may have been previously unused, and is now used, so copy the previous value over + copyPreviousIfFound(overriddenValue, source.m_overridesUnused); } } ////////////////////////////////////////////////////////////////////////// // #functions2 provide an identifier for the node/variable in the source that caused the dependency. the root will not have one. // the above will provide the data to handle the cases where only certain dependency nodes were removed - // until then we do a sanity check, if any part of the depenecies were altered, assume no overrides are valid. + // until then we do a sanity check, if any part of the dependencies were altered, assume no overrides are valid. if (m_dependencies.size() != source.m_dependencies.size()) { return; @@ -86,31 +99,41 @@ namespace ScriptCanvasBuilder if (auto serializeContext = azrtti_cast(reflectContext)) { serializeContext->Class() - ->Version(0) + ->Version(1) ->Field("source", &BuildVariableOverrides::m_source) ->Field("variables", &BuildVariableOverrides::m_variables) ->Field("entityId", &BuildVariableOverrides::m_entityIds) ->Field("overrides", &BuildVariableOverrides::m_overrides) + ->Field("overridesUnused", &BuildVariableOverrides::m_overridesUnused) ->Field("dependencies", &BuildVariableOverrides::m_dependencies) ; if (auto editContext = serializeContext->GetEditContext()) { - editContext->Class< BuildVariableOverrides>("Variables", "Variables exposed by the attached Script Canvas Graph") - ->ClassElement(AZ::Edit::ClassElements::Group, "Variable Fields") - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) + editContext->Class("Variables", "Variables exposed by the attached Script Canvas Graph") ->DataElement(AZ::Edit::UIHandlers::Default, &BuildVariableOverrides::m_overrides, "Variables", "Array of Variables within Script Canvas Graph") - ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly) + ->Attribute(AZ::Edit::Attributes::AutoExpand, true) + ->Attribute(AZ::Edit::Attributes::ContainerCanBeModified, false) + ->DataElement(AZ::Edit::UIHandlers::Default, &BuildVariableOverrides::m_overridesUnused, "Unused Variables", "Unused variables within Script Canvas Graph, when used they keep the values set here") + ->Attribute(AZ::Edit::Attributes::ContainerCanBeModified, false) ->DataElement(AZ::Edit::UIHandlers::Default, &BuildVariableOverrides::m_dependencies, "Dependencies", "Variables in Dependencies of the Script Canvas Graph") - ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly) + ->Attribute(AZ::Edit::Attributes::ContainerCanBeModified, false) ; } } } // use this to initialize the new data, and make sure they have a editor graph variable for proper editor display - void BuildVariableOverrides::PopulateFromParsedResults(const ScriptCanvas::Grammar::ParsedRuntimeInputs& inputs, const ScriptCanvas::VariableData& variables) + void BuildVariableOverrides::PopulateFromParsedResults(ScriptCanvas::Grammar::AbstractCodeModelConstPtr abstractCodeModel, const ScriptCanvas::VariableData& variables) { + if (!abstractCodeModel) + { + AZ_Error("ScriptCanvasBuider", false, "null abstract code model"); + return; + } + + const ScriptCanvas::Grammar::ParsedRuntimeInputs& inputs = abstractCodeModel->GetRuntimeInputs(); + for (auto& variable : inputs.m_variables) { auto graphVariable = variables.FindVariable(variable.first); @@ -148,6 +171,23 @@ namespace ScriptCanvasBuilder } } } + + for (auto& variable : abstractCodeModel->GetVariablesUnused()) + { + auto graphVariable = variables.FindVariable(variable->m_sourceVariableId); + if (!graphVariable) + { + AZ_Error("ScriptCanvasBuilder", false, "Missing Variable from graph data that was just parsed"); + continue; + } + + // copy to override unused list for editor display + m_overridesUnused.push_back(*graphVariable); + auto& overrideValue = m_overridesUnused.back(); + overrideValue.DeepCopy(*graphVariable); + overrideValue.SetScriptInputControlVisibility(AZ::Edit::PropertyVisibility::Hide); + overrideValue.SetAllowSignalOnChange(false); + } } EditorAssetTree* EditorAssetTree::ModRoot() @@ -346,7 +386,7 @@ namespace ScriptCanvasBuilder BuildVariableOverrides result; result.m_source = editorAssetTree.m_asset; - result.PopulateFromParsedResults(parseOutcome.GetValue()->GetRuntimeInputs(), *variableData); + result.PopulateFromParsedResults(parseOutcome.GetValue(), *variableData); // recurse... for (auto& dependentAsset : editorAssetTree.m_dependencies) @@ -356,7 +396,7 @@ namespace ScriptCanvasBuilder if (!parseDependentOutcome.IsSuccess()) { return AZ::Failure(AZStd::string::format - ("ParseEditorAssetTree failed to parse dependent graph from %s-%s: %s" + ( "ParseEditorAssetTree failed to parse dependent graph from %s-%s: %s" , dependentAsset.m_asset.GetId().ToString().c_str() , dependentAsset.m_asset.GetHint().c_str() , parseDependentOutcome.GetError().c_str())); diff --git a/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilder.h b/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilder.h index c5478b51f4..f03e78bc3e 100644 --- a/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilder.h +++ b/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilder.h @@ -10,16 +10,9 @@ #include #include +#include #include -namespace ScriptCanvas -{ - namespace Grammar - { - struct ParsedRuntimeInputs; - } -} - namespace ScriptCanvasEditor { class ScriptCanvasAsset; @@ -43,7 +36,7 @@ namespace ScriptCanvasBuilder bool IsEmpty() const; // use this to initialize the new data, and make sure they have a editor graph variable for proper editor display - void PopulateFromParsedResults(const ScriptCanvas::Grammar::ParsedRuntimeInputs& inputs, const ScriptCanvas::VariableData& variables); + void PopulateFromParsedResults(ScriptCanvas::Grammar::AbstractCodeModelConstPtr abstractCodeModel, const ScriptCanvas::VariableData& variables); // #functions2 provide an identifier for the node/variable in the source that caused the dependency. the root will not have one. AZ::Data::Asset m_source; @@ -52,8 +45,9 @@ namespace ScriptCanvasBuilder AZStd::vector m_variables; // the values here may or may not be overrides AZStd::vector> m_entityIds; - // this is all that gets exposed to the edit context + // these two variable lists are all that gets exposed to the edit context AZStd::vector m_overrides; + AZStd::vector m_overridesUnused; // AZStd::vector m_entityIdRuntimeInputIndices; since all of the entity ids need to go in, they may not need indices AZStd::vector m_dependencies; }; diff --git a/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilderWorker.h b/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilderWorker.h index 6bd5caf1a6..668e1a0bcd 100644 --- a/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilderWorker.h +++ b/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilderWorker.h @@ -58,6 +58,7 @@ namespace ScriptCanvasBuilder AddAssetDependencySearch, PrefabIntegration, CorrectGraphVariableVersion, + ReflectEntityIdNodes, // add new entries above Current, }; diff --git a/Gems/ScriptCanvas/Code/Editor/Components/EditorScriptCanvasComponent.cpp b/Gems/ScriptCanvas/Code/Editor/Components/EditorScriptCanvasComponent.cpp index dbc525e8e1..4a7a11778c 100644 --- a/Gems/ScriptCanvas/Code/Editor/Components/EditorScriptCanvasComponent.cpp +++ b/Gems/ScriptCanvas/Code/Editor/Components/EditorScriptCanvasComponent.cpp @@ -424,14 +424,14 @@ namespace ScriptCanvasEditor void EditorScriptCanvasComponent::OnAssetReady(const ScriptCanvasMemoryAsset::pointer asset) { - OnScriptCanvasAssetReady(asset); + // OnScriptCanvasAssetReady(asset); } void EditorScriptCanvasComponent::OnAssetSaved(const ScriptCanvasMemoryAsset::pointer asset, bool isSuccessful) { if (isSuccessful) { - OnScriptCanvasAssetReady(asset); + // OnScriptCanvasAssetReady(asset); } } diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/AbstractCodeModel.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/AbstractCodeModel.cpp index 3e4a425a6e..4509e7e907 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/AbstractCodeModel.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/AbstractCodeModel.cpp @@ -1358,17 +1358,23 @@ namespace ScriptCanvas { if (variable->m_isMember) { - return !this->m_variableUse.memberVariables.contains(variable); + if (!this->m_variableUse.memberVariables.contains(variable)) + { + m_variablesUnused.push_back(variable); + return true; + } } else { - return !this->m_variableUse.localVariables.contains(variable); + if (!this->m_variableUse.localVariables.contains(variable)) + { + m_variablesUnused.push_back(variable); + return true; + } } } - else - { - return false; - } + + return false; }); } @@ -2068,6 +2074,11 @@ namespace ScriptCanvas return m_variables; } + const AZStd::vector& AbstractCodeModel::GetVariablesUnused() const + { + return m_variablesUnused; + } + bool AbstractCodeModel::IsActiveGraph() const { if (!m_nodeablesByNode.empty()) diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/AbstractCodeModel.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/AbstractCodeModel.h index cdbdf611e5..7c5340bd18 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/AbstractCodeModel.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/AbstractCodeModel.h @@ -138,6 +138,8 @@ namespace ScriptCanvas const AZStd::vector& GetVariables() const; + const AZStd::vector& GetVariablesUnused() const; + bool IsErrorFree() const; // has modified data or handlers @@ -166,8 +168,6 @@ namespace ScriptCanvas void AddAllVariablesPreParse(); - void AddAllVariablesPreParse_LegacyFunctions(); - void AddDebugInformation(); void AddDebugInformation(ExecutionChild& execution); @@ -519,6 +519,7 @@ namespace ScriptCanvas AZStd::unordered_map m_dependencyByVariable; AZStd::vector m_variables; + AZStd::vector m_variablesUnused; AZStd::vector m_possibleExecutionRoots; // true iff there are no internal errors and no error validation events From 3633bf2ed0ea199ff6d0309aeaef2698efd26375 Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Fri, 30 Jul 2021 10:07:23 -0700 Subject: [PATCH 114/160] remove accidental submission of commented out event handling Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com> --- .../Code/Editor/Components/EditorScriptCanvasComponent.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gems/ScriptCanvas/Code/Editor/Components/EditorScriptCanvasComponent.cpp b/Gems/ScriptCanvas/Code/Editor/Components/EditorScriptCanvasComponent.cpp index 4a7a11778c..dbc525e8e1 100644 --- a/Gems/ScriptCanvas/Code/Editor/Components/EditorScriptCanvasComponent.cpp +++ b/Gems/ScriptCanvas/Code/Editor/Components/EditorScriptCanvasComponent.cpp @@ -424,14 +424,14 @@ namespace ScriptCanvasEditor void EditorScriptCanvasComponent::OnAssetReady(const ScriptCanvasMemoryAsset::pointer asset) { - // OnScriptCanvasAssetReady(asset); + OnScriptCanvasAssetReady(asset); } void EditorScriptCanvasComponent::OnAssetSaved(const ScriptCanvasMemoryAsset::pointer asset, bool isSuccessful) { if (isSuccessful) { - // OnScriptCanvasAssetReady(asset); + OnScriptCanvasAssetReady(asset); } } From e52606da697eacb390b9ff510450483871c8de45 Mon Sep 17 00:00:00 2001 From: nemerle <96597+nemerle@users.noreply.github.com> Date: Fri, 30 Jul 2021 19:26:34 +0200 Subject: [PATCH 115/160] AZStd::ref prevented compiler from using RVO Signed-off-by: nemerle <96597+nemerle@users.noreply.github.com> --- .../Code/Include/ScriptEvents/Internal/VersionedProperty.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/ScriptEvents/Code/Include/ScriptEvents/Internal/VersionedProperty.h b/Gems/ScriptEvents/Code/Include/ScriptEvents/Internal/VersionedProperty.h index 07d85adf05..b308a074e0 100644 --- a/Gems/ScriptEvents/Code/Include/ScriptEvents/Internal/VersionedProperty.h +++ b/Gems/ScriptEvents/Code/Include/ScriptEvents/Internal/VersionedProperty.h @@ -109,7 +109,7 @@ namespace ScriptEventData { VersionedProperty property = VersionedProperty("Void"); property.Set(VoidType {}); - return AZStd::ref(property); + return property; } template From 318fee8e22a87a73483a1fc5d2d4c46b6220382c Mon Sep 17 00:00:00 2001 From: puvvadar Date: Fri, 30 Jul 2021 10:38:15 -0700 Subject: [PATCH 116/160] Fix tabs Signed-off-by: puvvadar --- Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h index 5f0e23b2dc..e2fb7deacc 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h +++ b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h @@ -156,7 +156,7 @@ namespace Multiplayer HostFrameId m_lastReplicatedHostFrameId = HostFrameId(0); double m_serverSendAccumulator = 0.0; - float m_renderBlendFactor = 0.0f; + float m_renderBlendFactor = 0.0f; float m_tickFactor = 0.0f; #if !defined(AZ_RELEASE_BUILD) From 893a80a54e5a119dfc9b92e234c049f28fcc66d2 Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Fri, 30 Jul 2021 11:37:40 -0700 Subject: [PATCH 117/160] Fix variables names in the property window Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com> --- .../View/Widgets/VariablePanel/VariableDockWidget.cpp | 1 - .../Code/Include/ScriptCanvas/Core/Datum.cpp | 1 - .../Include/ScriptCanvas/Variable/GraphVariable.cpp | 11 ----------- .../Include/ScriptCanvas/Variable/GraphVariable.h | 3 --- 4 files changed, 16 deletions(-) diff --git a/Gems/ScriptCanvas/Code/Editor/View/Widgets/VariablePanel/VariableDockWidget.cpp b/Gems/ScriptCanvas/Code/Editor/View/Widgets/VariablePanel/VariableDockWidget.cpp index 65333059cc..60bc7ba0d2 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Widgets/VariablePanel/VariableDockWidget.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Widgets/VariablePanel/VariableDockWidget.cpp @@ -120,7 +120,6 @@ namespace ScriptCanvasEditor m_variableName = m_variable->GetVariableName(); const AZStd::string variableTypeName = TranslationHelper::GetSafeTypeName(m_variable->GetDatum()->GetType()); - m_variable->SetDisplayName(variableTypeName); m_componentTitle = AZStd::string::format("%s Variable", variableTypeName.data()); diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Datum.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Datum.cpp index 47f74329e0..e4569af820 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Datum.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Datum.cpp @@ -2083,7 +2083,6 @@ namespace ScriptCanvas editContext->Class("Datum", "Datum") ->ClassElement(AZ::Edit::ClassElements::EditorData, "Datum") ->Attribute(AZ::Edit::Attributes::Visibility, &Datum::GetVisibility) - ->Attribute(AZ::Edit::Attributes::ChildNameLabelOverride, &Datum::GetLabel) ->DataElement(AZ::Edit::UIHandlers::Default, &Datum::m_storage, "Datum", "") ->Attribute(AZ::Edit::Attributes::Visibility, &Datum::GetDatumVisibility) ->Attribute(AZ::Edit::Attributes::AutoExpand, true) diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Variable/GraphVariable.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Variable/GraphVariable.cpp index cc9e60e765..3d76883adc 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Variable/GraphVariable.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Variable/GraphVariable.cpp @@ -348,7 +348,6 @@ namespace ScriptCanvas void GraphVariable::SetVariableName(AZStd::string_view variableName) { m_variableName = variableName; - SetDisplayName(variableName); } AZStd::string_view GraphVariable::GetVariableName() const @@ -356,16 +355,6 @@ namespace ScriptCanvas return m_variableName; } - void GraphVariable::SetDisplayName(const AZStd::string& displayName) - { - m_datum.SetLabel(displayName); - } - - AZStd::string_view GraphVariable::GetDisplayName() const - { - return m_datum.GetLabel(); - } - void GraphVariable::SetScriptInputControlVisibility(const AZ::Crc32& inputControlVisibility) { m_inputControlVisibility = inputControlVisibility; diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Variable/GraphVariable.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Variable/GraphVariable.h index fd15ac95ee..dbc0a814c6 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Variable/GraphVariable.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Variable/GraphVariable.h @@ -134,9 +134,6 @@ namespace ScriptCanvas void SetVariableName(AZStd::string_view displayName); AZStd::string_view GetVariableName() const; - void SetDisplayName(const AZStd::string& displayName); - AZStd::string_view GetDisplayName() const; - void SetScriptInputControlVisibility(const AZ::Crc32& inputControlVisibility); AZ::Crc32 GetInputControlVisibility() const; From 02486a6fbeeaf9898232e5a4dccf4644a8f64c92 Mon Sep 17 00:00:00 2001 From: puvvadar Date: Fri, 30 Jul 2021 11:38:53 -0700 Subject: [PATCH 118/160] Add usage intention to GetPrevious descriptor Signed-off-by: puvvadar --- .../Code/Include/Multiplayer/NetworkTime/RewindableObject.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/NetworkTime/RewindableObject.h b/Gems/Multiplayer/Code/Include/Multiplayer/NetworkTime/RewindableObject.h index 072c1843f2..a8af564c15 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/NetworkTime/RewindableObject.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/NetworkTime/RewindableObject.h @@ -60,7 +60,7 @@ namespace Multiplayer //! @return value in const base type form const BASE_TYPE& Get() const; - //! Const base type retriever for one host frame behind Get(). + //! Const base type retriever for one host frame behind Get(). Only intended for use in SyncRewind contexts. //! @return value in const base type form const BASE_TYPE& GetPrevious() const; From 0cf6ecf3f7ff64cd987917a1ab64d9f73fe3d89a Mon Sep 17 00:00:00 2001 From: Chris Santora Date: Tue, 13 Jul 2021 16:25:10 -0700 Subject: [PATCH 119/160] Deleted unused "default" materials from RPI. Long ago these were used as defaults for FBX material conversion process, but that's no longer the case. And I'm about to add a new approach for default material conversion in SceneAPI. Signed-off-by: santorac <55155825+santorac@users.noreply.github.com> --- .../RPI/Assets/Materials/Default.materialtype | 90 ------------- .../RPI/Assets/Materials/DefaultMaterial.azsl | 127 ------------------ .../Assets/Materials/DefaultMaterial.shader | 26 ---- .../Materials/DefaultMaterial_DepthPass.azsl | 33 ----- .../DefaultMaterial_DepthPass.shader | 20 --- .../RPI/Assets/atom_rpi_asset_files.cmake | 5 - 6 files changed, 301 deletions(-) delete mode 100644 Gems/Atom/RPI/Assets/Materials/Default.materialtype delete mode 100644 Gems/Atom/RPI/Assets/Materials/DefaultMaterial.azsl delete mode 100644 Gems/Atom/RPI/Assets/Materials/DefaultMaterial.shader delete mode 100644 Gems/Atom/RPI/Assets/Materials/DefaultMaterial_DepthPass.azsl delete mode 100644 Gems/Atom/RPI/Assets/Materials/DefaultMaterial_DepthPass.shader diff --git a/Gems/Atom/RPI/Assets/Materials/Default.materialtype b/Gems/Atom/RPI/Assets/Materials/Default.materialtype deleted file mode 100644 index e8e6ff24eb..0000000000 --- a/Gems/Atom/RPI/Assets/Materials/Default.materialtype +++ /dev/null @@ -1,90 +0,0 @@ -{ - "description": "A simple default base material used primarily for imported model files like FBX.", - "propertyLayout": { - "version": 1, - "properties": { - "general": [ - { - "id": "DiffuseColor", - "type": "color", - "defaultValue": [ 1.0, 1.0, 1.0 ], - "connection": { - "type": "shaderInput", - "id": "m_diffuseColor" - } - }, - { - "id": "DiffuseMap", - "type": "image", - "defaultValue": "", - "connection": { - "type": "shaderInput", - "id": "m_diffuseMap" - } - }, - { - "id": "UseDiffuseMap", - "type": "bool", - "defaultValue": false, - "connection": { - "type": "shaderOption", - "id": "o_useDiffuseMap" - } - }, - { - "id": "SpecularColor", - "type": "color", - "defaultValue": [ 0.0, 0.0, 0.0 ], - "connection": { - "type": "shaderInput", - "id": "m_specularColor" - } - }, - { - "id": "SpecularMap", - "type": "image", - "defaultValue": "", - "connection": { - "type": "shaderInput", - "id": "m_specularMap" - } - }, - { - "id": "UseSpecularMap", - "type": "bool", - "defaultValue": false, - "connection": { - "type": "shaderOption", - "id": "o_useSpecularMap" - } - }, - { - "id": "NormalMap", - "type": "image", - "defaultValue": "", - "connection": { - "type": "shaderInput", - "id": "m_normalMap" - } - }, - { - "id": "UseNormalMap", - "type": "bool", - "defaultValue": false, - "connection": { - "type": "shaderOption", - "id": "o_useNormalMap" - } - } - ] - } - }, - "shaders": [ - { - "file": "DefaultMaterial.shader" - }, - { - "file": "DefaultMaterial_DepthPass.shader" - } - ] -} diff --git a/Gems/Atom/RPI/Assets/Materials/DefaultMaterial.azsl b/Gems/Atom/RPI/Assets/Materials/DefaultMaterial.azsl deleted file mode 100644 index 6640ed3fca..0000000000 --- a/Gems/Atom/RPI/Assets/Materials/DefaultMaterial.azsl +++ /dev/null @@ -1,127 +0,0 @@ - -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -#include -#include - -#include -#include -#include - -ShaderResourceGroup MaterialSrg : SRG_PerMaterial -{ - float4 m_diffuseColor; - float3 m_specularColor; - - Texture2D m_diffuseMap; - Texture2D m_normalMap; - Texture2D m_specularMap; - - Sampler m_sampler - { - MaxAnisotropy = 16; - AddressU = Wrap; - AddressV = Wrap; - AddressW = Wrap; - }; -} - -option bool o_useDiffuseMap = false; -option bool o_useSpecularMap = false; -option bool o_useNormalMap = false; - -struct VertexInput -{ - float3 m_position : POSITION; - float3 m_normal : NORMAL; - float4 m_tangent : TANGENT; - float3 m_bitangent : BITANGENT; - float2 m_uv : UV0; -}; - -struct VertexOutput -{ - float4 m_position : SV_Position; - float3 m_normal : NORMAL; - float3 m_tangent : TANGENT; - float3 m_bitangent : BITANGENT; - float2 m_uv : UV0; - float3 m_positionToCamera : VIEW; -}; - -VertexOutput MainVS(VertexInput input) -{ - const float4x4 objectToWorldMatrix = ObjectSrg::GetWorldMatrix(); - - VertexOutput output; - float3 worldPosition = mul(objectToWorldMatrix, float4(input.m_position,1)).xyz; - output.m_position = mul(ViewSrg::m_viewProjectionMatrix, float4(worldPosition, 1.0)); - - output.m_uv = input.m_uv; - - output.m_positionToCamera = ViewSrg::m_worldPosition - worldPosition; - - float3x3 objectToWorldMatrixIT = ObjectSrg::GetWorldMatrixInverseTranspose(); - - ConstructTBN(input.m_normal, input.m_tangent, input.m_bitangent, objectToWorldMatrix, objectToWorldMatrixIT, output.m_normal, output.m_tangent, output.m_bitangent); - - return output; -} - -struct PixelOutput -{ - float4 m_color : SV_Target0; -}; - -PixelOutput MainPS(VertexOutput input) -{ - PixelOutput output; - - // Very rough placeholder lighting - static const float3 lightDir = normalize(float3(1,1,1)); - - float4 baseColor = MaterialSrg::m_diffuseColor; - if (o_useDiffuseMap) - { - baseColor *= MaterialSrg::m_diffuseMap.Sample(MaterialSrg::m_sampler, input.m_uv); - } - - float3 specular = MaterialSrg::m_specularColor; - if (o_useSpecularMap) - { - specular *= MaterialSrg::m_specularMap.Sample(MaterialSrg::m_sampler, input.m_uv).rgb; - } - - float3 normal; - if (o_useNormalMap) - { - float4 sampledValue = MaterialSrg::m_normalMap.Sample(MaterialSrg::m_sampler, input.m_uv); - normal = GetWorldSpaceNormal(sampledValue.xy, input.m_normal, input.m_tangent, input.m_bitangent); - } - else - { - normal = normalize(input.m_normal); - } - - float3 viewDir = normalize(input.m_positionToCamera); - float3 H = normalize(lightDir + viewDir); - float NdotH = max(0.001, dot(normal, H)); - float NdotL = saturate(dot(normal, lightDir)); - - float3 diffuse = NdotL * baseColor.xyz; - - specular = pow(NdotH, 5.0) * specular; - - // Combined - float3 result = diffuse + specular + float3(0.1, 0.1, 0.1) * baseColor.xyz; - - output.m_color = float4(result.xyz, baseColor.a); - - return output; -} diff --git a/Gems/Atom/RPI/Assets/Materials/DefaultMaterial.shader b/Gems/Atom/RPI/Assets/Materials/DefaultMaterial.shader deleted file mode 100644 index ceea480f43..0000000000 --- a/Gems/Atom/RPI/Assets/Materials/DefaultMaterial.shader +++ /dev/null @@ -1,26 +0,0 @@ -{ - "Source" : "DefaultMaterial.azsl", - - "DepthStencilState" : { - "Depth" : { "Enable" : true, "CompareFunc" : "Equal" } - }, - - "DrawList" : "forward", - - "ProgramSettings": - { - "EntryPoints": - [ - { - "name": "MainVS", - "type": "Vertex" - }, - { - "name": "MainPS", - "type": "Fragment" - } - ] - } -} - - diff --git a/Gems/Atom/RPI/Assets/Materials/DefaultMaterial_DepthPass.azsl b/Gems/Atom/RPI/Assets/Materials/DefaultMaterial_DepthPass.azsl deleted file mode 100644 index 961fde7568..0000000000 --- a/Gems/Atom/RPI/Assets/Materials/DefaultMaterial_DepthPass.azsl +++ /dev/null @@ -1,33 +0,0 @@ - -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -#include -#include - -#include - -struct VertexInput -{ - float3 m_position : POSITION; -}; - -struct VertexOutput -{ - float4 m_position : SV_Position; -}; - -VertexOutput MainVS(VertexInput input) -{ - const float4x4 objectToWorldMatrix = ObjectSrg::GetWorldMatrix(); - - VertexOutput output; - float3 worldPosition = mul(objectToWorldMatrix, float4(input.m_position,1)).xyz; - output.m_position = mul(ViewSrg::m_viewProjectionMatrix, float4(worldPosition, 1.0)); - return output; -} diff --git a/Gems/Atom/RPI/Assets/Materials/DefaultMaterial_DepthPass.shader b/Gems/Atom/RPI/Assets/Materials/DefaultMaterial_DepthPass.shader deleted file mode 100644 index 19ba1d5d9d..0000000000 --- a/Gems/Atom/RPI/Assets/Materials/DefaultMaterial_DepthPass.shader +++ /dev/null @@ -1,20 +0,0 @@ -{ - "Source" : "DefaultMaterial_DepthPass.azsl", - - "DepthStencilState" : { - "Depth" : { "Enable" : true, "CompareFunc" : "GreaterEqual" } - }, - - "DrawList" : "depth", - - "ProgramSettings": - { - "EntryPoints": - [ - { - "name": "MainVS", - "type": "Vertex" - } - ] - } -} diff --git a/Gems/Atom/RPI/Assets/atom_rpi_asset_files.cmake b/Gems/Atom/RPI/Assets/atom_rpi_asset_files.cmake index 8f85259f7d..9e89427a70 100644 --- a/Gems/Atom/RPI/Assets/atom_rpi_asset_files.cmake +++ b/Gems/Atom/RPI/Assets/atom_rpi_asset_files.cmake @@ -7,11 +7,6 @@ # set(FILES - Materials/Default.materialtype - Materials/DefaultMaterial.azsl - Materials/DefaultMaterial.shader - Materials/DefaultMaterial_DepthPass.azsl - Materials/DefaultMaterial_DepthPass.shader Shader/DecomposeMsImage.azsl Shader/DecomposeMsImage.shader Shader/ImagePreview.azsl From 14d2e38b90c07bf2bd4fc0afc7d2e3409d88e84f Mon Sep 17 00:00:00 2001 From: Chris Santora Date: Sat, 17 Jul 2021 00:07:23 -0700 Subject: [PATCH 120/160] Refactored how model material slots work in preparation to support more flexible material conversion options for the scene asset pipeline. The material slot IDs are based on the MaterialUid that come from SceneAPI. Since these IDs are also used as the AssetId sub-ID for the converted material assets, the system was just checking the material asset sub-ID to determine the material slot ID. But in order to support certain FBX material conversion options, we needed to break this tie, so the slot ID is separate from the AssetId of the material in that slot. This will allow some other material to be used in the slot, instead of being forced to use one that was generated from the FBX. Here we inttroduce a new struct ModelMaterialSlot which formalizes the concept of material slot, with an ID, display name, and default material assignment. The ID still comes from the MaterialUid like before. The display name is built-in, rather than being parsed out from the asset file name. And the default material assignment can be any material asset, it doesn't have to come from the FBX (or other scene file). This commit is just the preliminary set of changes. Cursory testing shows that it works pretty well but more testing is needed (and likely some fixes) before merging. Here is what's left to do... Add serialization version converters to preserve prior prefab data. See if we can get rid of GetLabelByAssetId function only rely on the display name inside ModelMaterialSlot. I'm not sure if the condition for enabling the "Edit Material Instance..." context menu item is correct. Test actors Lots more testing in general Signed-off-by: santorac <55155825+santorac@users.noreply.github.com> --- .../Feature/Material/MaterialAssignmentId.h | 35 +++-- .../Source/Material/MaterialAssignment.cpp | 6 +- .../Source/Material/MaterialAssignmentId.cpp | 51 ++++--- .../Code/Source/Mesh/MeshFeatureProcessor.cpp | 20 +-- .../SkinnedMesh/SkinnedMeshInputBuffers.cpp | 7 +- .../Include/Atom/RPI.Public/Model/ModelLod.h | 2 + .../Atom/RPI.Reflect/Model/ModelAsset.h | 3 + .../Atom/RPI.Reflect/Model/ModelLodAsset.h | 29 +++- .../RPI.Reflect/Model/ModelLodAssetCreator.h | 6 +- .../RPI.Reflect/Model/ModelMaterialSlot.h | 43 ++++++ .../Model/ModelAssetBuilderComponent.cpp | 10 +- .../Code/Source/RPI.Public/Model/ModelLod.cpp | 9 +- .../Source/RPI.Public/Model/ModelSystem.cpp | 1 + .../Source/RPI.Reflect/Model/ModelAsset.cpp | 24 ++++ .../RPI.Reflect/Model/ModelLodAsset.cpp | 48 ++++++- .../Model/ModelLodAssetCreator.cpp | 32 ++++- .../RPI.Reflect/Model/ModelMaterialSlot.cpp | 30 ++++ .../RPI/Code/atom_rpi_reflect_files.cmake | 2 + .../Material/MaterialComponentBus.h | 3 + .../Material/EditorMaterialComponent.cpp | 136 +++++++++--------- .../EditorMaterialComponentExporter.cpp | 6 +- .../EditorMaterialComponentExporter.h | 11 +- .../Material/EditorMaterialComponentSlot.cpp | 33 ++--- .../Material/EditorMaterialComponentSlot.h | 4 +- .../Material/MaterialComponentConfig.cpp | 2 +- .../Source/Mesh/MeshComponentController.cpp | 13 ++ .../Source/Mesh/MeshComponentController.h | 1 + .../EMotionFXAtom/Code/Source/ActorAsset.cpp | 8 +- .../Code/Source/AtomActorInstance.cpp | 13 ++ .../Code/Source/AtomActorInstance.h | 1 + .../Rendering/Atom/WhiteBoxAtomRenderMesh.cpp | 5 +- 31 files changed, 399 insertions(+), 195 deletions(-) create mode 100644 Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Model/ModelMaterialSlot.h create mode 100644 Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/ModelMaterialSlot.cpp diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Material/MaterialAssignmentId.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Material/MaterialAssignmentId.h index dd198a7179..d9ae8099da 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Material/MaterialAssignmentId.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Material/MaterialAssignmentId.h @@ -15,6 +15,7 @@ #include #include #include +#include namespace AZ { @@ -23,7 +24,7 @@ namespace AZ using MaterialAssignmentLodIndex = AZ::u64; //! MaterialAssignmentId is used to address available and overridable material slots on a model. - //! The LOD and one of the model's original material asset IDs are used as coordinates that identify + //! The LOD and one of the model's original material slot IDs are used as coordinates that identify //! a specific material slot or a set of slots matching either. struct MaterialAssignmentId final { @@ -33,41 +34,39 @@ namespace AZ MaterialAssignmentId() = default; - MaterialAssignmentId(MaterialAssignmentLodIndex lodIndex, const AZ::Data::AssetId& materialAssetId); + MaterialAssignmentId(MaterialAssignmentLodIndex lodIndex, RPI::ModelMaterialSlot::StableId materialSlotStableId); - //! Create an ID that maps to all material slots, regardless of asset ID or LOD, effectively applying to an entire model. + //! Create an ID that maps to all material slots, regardless of slot ID or LOD, effectively applying to an entire model. static MaterialAssignmentId CreateDefault(); - //! Create an ID that maps to all material slots with a corresponding asset ID, regardless of LOD. - static MaterialAssignmentId CreateFromAssetOnly(AZ::Data::AssetId materialAssetId); + //! Create an ID that maps to all material slots with a corresponding slot ID, regardless of LOD. + static MaterialAssignmentId CreateFromStableIdOnly(RPI::ModelMaterialSlot::StableId materialSlotStableId); - //! Create an ID that maps to a specific material slot with a corresponding asset ID and LOD. - static MaterialAssignmentId CreateFromLodAndAsset(MaterialAssignmentLodIndex lodIndex, AZ::Data::AssetId materialAssetId); + //! Create an ID that maps to a specific material slot with a corresponding stable ID and LOD. + static MaterialAssignmentId CreateFromLodAndStableId(MaterialAssignmentLodIndex lodIndex, RPI::ModelMaterialSlot::StableId materialSlotStableId); - //! Returns true if the asset ID and LOD are invalid + //! Returns true if the slot stable ID and LOD are invalid, meaning this assignment applies to the entire model. bool IsDefault() const; - //! Returns true if the asset ID is valid and LOD is invalid - bool IsAssetOnly() const; + //! Returns true if the slot stable ID is valid and LOD is invalid, meaning this assignment applies to every LOD. + bool IsSlotIdOnly() const; - //! Returns true if the asset ID and LOD are both valid - bool IsLodAndAsset() const; + //! Returns true if the slot stable ID and LOD are both valid, meaning this assignment applies to a single material slot on a specific LOD. + bool IsLodAndSlotId() const; - //! Creates a string composed of the asset path and LOD + //! Creates a string describing all the details of the assignment ID AZStd::string ToString() const; - //! Creates a hash composed of the asset ID sub ID and LOD + //! Creates a hash composed of all elements of the assignment ID size_t GetHash() const; - //! Returns true if both asset ID sub IDs and LODs match bool operator==(const MaterialAssignmentId& rhs) const; - - //! Returns true if both asset ID sub IDs and LODs do not match bool operator!=(const MaterialAssignmentId& rhs) const; static constexpr MaterialAssignmentLodIndex NonLodIndex = -1; + MaterialAssignmentLodIndex m_lodIndex = NonLodIndex; - AZ::Data::AssetId m_materialAssetId = AZ::Data::AssetId(); + RPI::ModelMaterialSlot::StableId m_materialSlotStableId = RPI::ModelMaterialSlot::InvalidStableId; }; } // namespace Render diff --git a/Gems/Atom/Feature/Common/Code/Source/Material/MaterialAssignment.cpp b/Gems/Atom/Feature/Common/Code/Source/Material/MaterialAssignment.cpp index ec48d57d1a..9ae4f65304 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Material/MaterialAssignment.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Material/MaterialAssignment.cpp @@ -123,7 +123,7 @@ namespace AZ } const MaterialAssignment& assetAssignment = - GetMaterialAssignmentFromMap(materials, MaterialAssignmentId::CreateFromAssetOnly(id.m_materialAssetId)); + GetMaterialAssignmentFromMap(materials, MaterialAssignmentId::CreateFromStableIdOnly(id.m_materialSlotStableId)); if (assetAssignment.m_materialInstance.get()) { return assetAssignment; @@ -152,11 +152,11 @@ namespace AZ { if (mesh.m_material) { - const MaterialAssignmentId generalId = MaterialAssignmentId::CreateFromAssetOnly(mesh.m_material->GetAssetId()); + const MaterialAssignmentId generalId = MaterialAssignmentId::CreateFromStableIdOnly(mesh.m_materialSlotStableId); materials[generalId] = MaterialAssignment(mesh.m_material->GetAsset(), mesh.m_material); const MaterialAssignmentId specificId = - MaterialAssignmentId::CreateFromLodAndAsset(lodIndex, mesh.m_material->GetAssetId()); + MaterialAssignmentId::CreateFromLodAndStableId(lodIndex, mesh.m_materialSlotStableId); materials[specificId] = MaterialAssignment(mesh.m_material->GetAsset(), mesh.m_material); } } diff --git a/Gems/Atom/Feature/Common/Code/Source/Material/MaterialAssignmentId.cpp b/Gems/Atom/Feature/Common/Code/Source/Material/MaterialAssignmentId.cpp index 71dea0596f..8b6b0be237 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Material/MaterialAssignmentId.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Material/MaterialAssignmentId.cpp @@ -19,9 +19,9 @@ namespace AZ if (auto serializeContext = azrtti_cast(context)) { serializeContext->Class() - ->Version(1) + ->Version(2) ->Field("lodIndex", &MaterialAssignmentId::m_lodIndex) - ->Field("materialAssetId", &MaterialAssignmentId::m_materialAssetId) + ->Field("materialSlotStableId", &MaterialAssignmentId::m_materialSlotStableId) ; } @@ -33,75 +33,72 @@ namespace AZ ->Attribute(AZ::Script::Attributes::Module, "render") ->Constructor() ->Constructor() - ->Constructor() + ->Constructor() ->Method("IsDefault", &MaterialAssignmentId::IsDefault) - ->Method("IsAssetOnly", &MaterialAssignmentId::IsAssetOnly) - ->Method("IsLodAndAsset", &MaterialAssignmentId::IsLodAndAsset) + ->Method("IsAssetOnly", &MaterialAssignmentId::IsSlotIdOnly) // Included for compatibility. Use "IsSlotIdOnly" instead. + ->Method("IsLodAndAsset", &MaterialAssignmentId::IsLodAndSlotId) // Included for compatibility. Use "IsLodAndSlotId" instead. + ->Method("IsSlotIdOnly", &MaterialAssignmentId::IsSlotIdOnly) + ->Method("IsLodAndSlotId", &MaterialAssignmentId::IsLodAndSlotId) ->Method("ToString", &MaterialAssignmentId::ToString) ->Property("lodIndex", BehaviorValueProperty(&MaterialAssignmentId::m_lodIndex)) - ->Property("materialAssetId", BehaviorValueProperty(&MaterialAssignmentId::m_materialAssetId)) + ->Property("materialSlotStableId", BehaviorValueProperty(&MaterialAssignmentId::m_materialSlotStableId)) ; } } - MaterialAssignmentId::MaterialAssignmentId(MaterialAssignmentLodIndex lodIndex, const AZ::Data::AssetId& materialAssetId) + MaterialAssignmentId::MaterialAssignmentId(MaterialAssignmentLodIndex lodIndex, RPI::ModelMaterialSlot::StableId materialSlotStableId) : m_lodIndex(lodIndex) - , m_materialAssetId(materialAssetId) + , m_materialSlotStableId(materialSlotStableId) { } MaterialAssignmentId MaterialAssignmentId::CreateDefault() { - return MaterialAssignmentId(NonLodIndex, AZ::Data::AssetId()); + return MaterialAssignmentId(NonLodIndex, RPI::ModelMaterialSlot::InvalidStableId); } - MaterialAssignmentId MaterialAssignmentId::CreateFromAssetOnly(AZ::Data::AssetId materialAssetId) + MaterialAssignmentId MaterialAssignmentId::CreateFromStableIdOnly(RPI::ModelMaterialSlot::StableId materialSlotStableId) { - return MaterialAssignmentId(NonLodIndex, materialAssetId); + return MaterialAssignmentId(NonLodIndex, materialSlotStableId); } - MaterialAssignmentId MaterialAssignmentId::CreateFromLodAndAsset( - MaterialAssignmentLodIndex lodIndex, AZ::Data::AssetId materialAssetId) + MaterialAssignmentId MaterialAssignmentId::CreateFromLodAndStableId( + MaterialAssignmentLodIndex lodIndex, RPI::ModelMaterialSlot::StableId materialSlotStableId) { - return MaterialAssignmentId(lodIndex, materialAssetId); + return MaterialAssignmentId(lodIndex, materialSlotStableId); } bool MaterialAssignmentId::IsDefault() const { - return m_lodIndex == NonLodIndex && !m_materialAssetId.IsValid(); + return m_lodIndex == NonLodIndex && m_materialSlotStableId == RPI::ModelMaterialSlot::InvalidStableId; } - bool MaterialAssignmentId::IsAssetOnly() const + bool MaterialAssignmentId::IsSlotIdOnly() const { - return m_lodIndex == NonLodIndex && m_materialAssetId.IsValid(); + return m_lodIndex == NonLodIndex && m_materialSlotStableId != RPI::ModelMaterialSlot::InvalidStableId; } - bool MaterialAssignmentId::IsLodAndAsset() const + bool MaterialAssignmentId::IsLodAndSlotId() const { - return m_lodIndex != NonLodIndex && m_materialAssetId.IsValid(); + return m_lodIndex != NonLodIndex && m_materialSlotStableId != RPI::ModelMaterialSlot::InvalidStableId; } AZStd::string MaterialAssignmentId::ToString() const { - AZStd::string assetPathString; - AZ::Data::AssetCatalogRequestBus::BroadcastResult( - assetPathString, &AZ::Data::AssetCatalogRequests::GetAssetPathById, m_materialAssetId); - AZ::StringFunc::Path::StripPath(assetPathString); - AZ::StringFunc::Path::StripExtension(assetPathString); - return AZStd::string::format("%s:%llu", assetPathString.c_str(), m_lodIndex); + return AZStd::string::format("%u:%llu", m_materialSlotStableId, m_lodIndex); } size_t MaterialAssignmentId::GetHash() const { size_t seed = 0; AZStd::hash_combine(seed, m_lodIndex); - AZStd::hash_combine(seed, m_materialAssetId.m_subId); + AZStd::hash_combine(seed, m_materialSlotStableId); return seed; } bool MaterialAssignmentId::operator==(const MaterialAssignmentId& rhs) const { - return m_lodIndex == rhs.m_lodIndex && m_materialAssetId.m_subId == rhs.m_materialAssetId.m_subId; + return m_lodIndex == rhs.m_lodIndex && m_materialSlotStableId == rhs.m_materialSlotStableId; } bool MaterialAssignmentId::operator!=(const MaterialAssignmentId& rhs) const diff --git a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp index c6362f3a5d..6e031aa853 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp @@ -589,18 +589,6 @@ namespace AZ { AZ_PROFILE_FUNCTION(Debug::ProfileCategory::AzRender); - auto modelAsset = model->GetModelAsset(); - for (const auto& modelLodAsset : modelAsset->GetLodAssets()) - { - for (const auto& mesh : modelLodAsset->GetMeshes()) - { - if (mesh.GetMaterialAsset().GetStatus() != Data::AssetData::AssetStatus::Ready) - { - - } - } - } - m_model = model; const size_t modelLodCount = m_model->GetLodCount(); m_drawPacketListsByLod.resize(modelLodCount); @@ -644,10 +632,12 @@ namespace AZ for (size_t meshIndex = 0; meshIndex < meshCount; ++meshIndex) { - Data::Instance material = modelLod.GetMeshes()[meshIndex].m_material; + const RPI::ModelLod::Mesh& mesh = modelLod.GetMeshes()[meshIndex]; + + Data::Instance material = mesh.m_material; // Determine if there is a material override specified for this sub mesh - const MaterialAssignmentId materialAssignmentId(modelLodIndex, material ? material->GetAssetId() : AZ::Data::AssetId()); + const MaterialAssignmentId materialAssignmentId(modelLodIndex, mesh.m_materialSlotStableId); const MaterialAssignment& materialAssignment = GetMaterialAssignmentFromMapWithFallback(m_materialAssignments, materialAssignmentId); if (materialAssignment.m_materialInstance.get()) { @@ -790,7 +780,7 @@ namespace AZ // retrieve the material Data::Instance material = mesh.m_material; - const MaterialAssignmentId materialAssignmentId(rayTracingLod, material ? material->GetAssetId() : AZ::Data::AssetId()); + const MaterialAssignmentId materialAssignmentId(rayTracingLod, mesh.m_materialSlotStableId); const MaterialAssignment& materialAssignment = GetMaterialAssignmentFromMapWithFallback(m_materialAssignments, materialAssignmentId); if (materialAssignment.m_materialInstance.get()) { diff --git a/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshInputBuffers.cpp b/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshInputBuffers.cpp index 155b751272..640e30d0f6 100644 --- a/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshInputBuffers.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshInputBuffers.cpp @@ -639,8 +639,13 @@ namespace AZ Aabb localAabb = lod.m_subMeshProperties[i].m_aabb; modelLodCreator.SetMeshAabb(AZStd::move(localAabb)); + + // Create a separate material slot for each sub-mesh + AZ::RPI::ModelMaterialSlot materialSlot; + materialSlot.m_stableId = i; + materialSlot.m_defaultMaterialAsset = lod.m_subMeshProperties[i].m_material; - modelLodCreator.SetMeshMaterialAsset(lod.m_subMeshProperties[i].m_material); + modelLodCreator.SetMeshMaterialSlot(materialSlot); modelLodCreator.EndMesh(); } diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Model/ModelLod.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Model/ModelLod.h index dcc4813b3d..36892d0027 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Model/ModelLod.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Model/ModelLod.h @@ -72,6 +72,8 @@ namespace AZ RHI::IndexBufferView m_indexBufferView; StreamInfoList m_streamInfo; + + ModelMaterialSlot::StableId m_materialSlotStableId = ModelMaterialSlot::InvalidStableId; //! The default material assigned to the mesh by the asset. Data::Instance m_material; diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Model/ModelAsset.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Model/ModelAsset.h index b7414f73a2..891aec04b3 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Model/ModelAsset.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Model/ModelAsset.h @@ -49,6 +49,9 @@ namespace AZ //! Returns the model-space axis aligned bounding box const AZ::Aabb& GetAabb() const; + + //! Returns the list of all ModelMaterialSlot's for the model, across all LODs. + RPI::ModelMaterialSlotMap GetModelMaterialSlots() const; //! Returns the number of Lods in the model size_t GetLodCount() const; diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Model/ModelLodAsset.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Model/ModelLodAsset.h index 4e86b0e367..61e2ebeb05 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Model/ModelLodAsset.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Model/ModelLodAsset.h @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -84,8 +85,9 @@ namespace AZ //! Returns the number of indices in this mesh uint32_t GetIndexCount() const; - //! Returns the reference to material asset used by this mesh - const Data::Asset & GetMaterialAsset() const; + //! Returns the index of the material slot used by this mesh. + //! This indexes into the ModelLodAsset's material slot list. + size_t GetMaterialSlotIndex() const; //! Returns the name of this mesh const AZ::Name& GetName() const; @@ -124,7 +126,9 @@ namespace AZ AZ::Name m_name; AZ::Aabb m_aabb = AZ::Aabb::CreateNull(); - Data::Asset m_materialAsset{ Data::AssetLoadBehavior::PreLoad }; + // Identifies the material that is used by this mesh. + // References material slot in the ModelLodAsset that owns this mesh; see ModelLodAsset::GetMaterialSlot(). + size_t m_materialSlotIndex = 0; // Both the buffer in m_indexBufferAssetView and the buffers in m_streamBufferInfo // may point to either unique buffers for the mesh or to consolidated @@ -143,11 +147,21 @@ namespace AZ //! Returns the model-space axis-aligned bounding box of all meshes in the lod const AZ::Aabb& GetAabb() const; + + //! Returns an array view into the collection of material slots available to this lod + AZStd::array_view GetMaterialSlots() const; + + //! Returns a specific material slot by index, with error checking. + //! The index can be retrieved from Mesh::GetMaterialSlotIndex(). + const ModelMaterialSlot& GetMaterialSlot(size_t slotIndex) const; + + //! Find a material slot with the given stableId, or returns null if it isn't found. + const ModelMaterialSlot* FindMaterialSlot(uint32_t stableId) const; private: AZStd::vector m_meshes; AZ::Aabb m_aabb = AZ::Aabb::CreateNull(); - + // These buffers owned by the lod are the consolidated super buffers. // Meshes may either have views into these buffers or they may own // their own buffers. @@ -155,6 +169,13 @@ namespace AZ Data::Asset m_indexBuffer; AZStd::vector> m_streamBuffers; + // Lists all of the material slots that are used by this LOD. + // Note the same slot can appear in multiple LODs in the model, so that LODs don't have to refer back to the model asset. + AZStd::vector m_materialSlots; + + // A default ModelMaterialSlot to be returned upon error conditions. + ModelMaterialSlot m_fallbackSlot; + void AddMesh(const Mesh& mesh); void SetReady(); diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Model/ModelLodAssetCreator.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Model/ModelLodAssetCreator.h index c3291e5c73..5672b49f68 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Model/ModelLodAssetCreator.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Model/ModelLodAssetCreator.h @@ -8,6 +8,7 @@ #pragma once +#include #include #include @@ -45,9 +46,10 @@ namespace AZ //! Begin and BeginMesh must be called first. void SetMeshAabb(AZ::Aabb&& aabb); - //! Sets the material asset for the current SubMesh. + //! Sets the material slot data for the current SubMesh. + //! Adds a new material slot to the ModelLodAsset if it doesn't already exist. //! Begin and BeginMesh must be called first - void SetMeshMaterialAsset(const Data::Asset& materialAsset); + void SetMeshMaterialSlot(const ModelMaterialSlot& materialSlot); //! Sets the given BufferAssetView to the current SubMesh as the index buffer. //! Begin and BeginMesh must be called first diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Model/ModelMaterialSlot.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Model/ModelMaterialSlot.h new file mode 100644 index 0000000000..27137459b7 --- /dev/null +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Model/ModelMaterialSlot.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#pragma once + +#include + +namespace AZ +{ + class ReflectContext; + + namespace RPI + { + //! Use by model assets to identify a logical material slot. + //! Each slot has a unique ID, a name, and a default material. Each mesh in model will reference a single ModelMaterialSlot. + //! Other classes like MeshFeatureProcessor and MaterialComponent can override the material associated with individual slots + //! to alter the default appearance of the mesh. + struct ModelMaterialSlot + { + AZ_TYPE_INFO(ModelMaterialSlot, "{0E88A62A-D83D-4C1B-8DE7-CE972B8124B5}"); + + static void Reflect(AZ::ReflectContext* context); + + using StableId = uint32_t; + static const StableId InvalidStableId = -1; + + //! This ID must have a consistent value when the asset is reprocessed by the asset pipeline, and must be unique within the ModelLodAsset. + //! In practice, this set using the MaterialUid from SceneAPI. See ModelAssetBuilderComponent::CreateMesh. + StableId m_stableId = InvalidStableId; + + Name m_displayName; //!< The name of the slot as displayed to the user in UI. (Using Name instead of string for fast copies) + + Data::Asset m_defaultMaterialAsset{ Data::AssetLoadBehavior::PreLoad }; //!< The material that will be applied to this slot by default. + }; + + using ModelMaterialSlotMap = AZStd::unordered_map; + + } //namespace RPI +} // namespace AZ diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/ModelAssetBuilderComponent.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/ModelAssetBuilderComponent.cpp index aa2ad37647..608ee17d95 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/ModelAssetBuilderComponent.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/ModelAssetBuilderComponent.cpp @@ -109,7 +109,7 @@ namespace AZ if (auto* serialize = azrtti_cast(context)) { serialize->Class() - ->Version(27); // [ATOM-15658] + ->Version(29); // (updated to separate material slot ID from default material asset) } } @@ -1806,8 +1806,12 @@ namespace AZ auto iter = materialAssetsByUid.find(meshView.m_materialUid); if (iter != materialAssetsByUid.end()) { - const Data::Asset& materialAsset = iter->second.m_asset; - lodAssetCreator.SetMeshMaterialAsset(materialAsset); + ModelMaterialSlot materialSlot; + materialSlot.m_stableId = meshView.m_materialUid; + materialSlot.m_displayName = iter->second.m_name; + materialSlot.m_defaultMaterialAsset = iter->second.m_asset; + + lodAssetCreator.SetMeshMaterialSlot(materialSlot); } } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Model/ModelLod.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Model/ModelLod.cpp index b68930e4a3..2dfee9e2f1 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Model/ModelLod.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Model/ModelLod.cpp @@ -100,10 +100,13 @@ namespace AZ } } - auto& materialAsset = mesh.GetMaterialAsset(); - if (materialAsset.IsReady()) + const ModelMaterialSlot& materialSlot = lodAsset.GetMaterialSlot(mesh.GetMaterialSlotIndex()); + + meshInstance.m_materialSlotStableId = materialSlot.m_stableId; + + if (materialSlot.m_defaultMaterialAsset.IsReady()) { - meshInstance.m_material = Material::FindOrCreate(materialAsset); + meshInstance.m_material = Material::FindOrCreate(materialSlot.m_defaultMaterialAsset); } m_meshes.emplace_back(AZStd::move(meshInstance)); diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Model/ModelSystem.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Model/ModelSystem.cpp index 610f183eb1..b9781843cf 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Model/ModelSystem.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Model/ModelSystem.cpp @@ -24,6 +24,7 @@ namespace AZ { ModelLodAsset::Reflect(context); ModelAsset::Reflect(context); + ModelMaterialSlot::Reflect(context); MorphTargetMetaAsset::Reflect(context); SkinMetaAsset::Reflect(context); } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/ModelAsset.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/ModelAsset.cpp index 083de10d47..486faafbdb 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/ModelAsset.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/ModelAsset.cpp @@ -56,6 +56,30 @@ namespace AZ { return m_aabb; } + + RPI::ModelMaterialSlotMap ModelAsset::GetModelMaterialSlots() const + { + RPI::ModelMaterialSlotMap slotMap; + + for (const Data::Asset& lod : GetLodAssets()) + { + for (const AZ::RPI::ModelMaterialSlot& materialSlot : lod->GetMaterialSlots()) + { + auto iter = slotMap.find(materialSlot.m_stableId); + if (iter == slotMap.end()) + { + slotMap.emplace(materialSlot.m_stableId, materialSlot); + } + else + { + AZ_Assert(materialSlot.m_displayName == iter->second.m_displayName && materialSlot.m_defaultMaterialAsset.GetId() == iter->second.m_defaultMaterialAsset.GetId(), + "Multiple LODs have mismatched data for the same material slot."); + } + } + } + + return slotMap; + } size_t ModelAsset::GetLodCount() const { diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/ModelLodAsset.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/ModelLodAsset.cpp index 190e4c5315..4811f6a1db 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/ModelLodAsset.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/ModelLodAsset.cpp @@ -23,24 +23,25 @@ namespace AZ if (auto* serializeContext = azrtti_cast(context)) { serializeContext->Class() - ->Version(0) + ->Version(1) ->Field("Meshes", &ModelLodAsset::m_meshes) ->Field("Aabb", &ModelLodAsset::m_aabb) + ->Field("MaterialSlots", &ModelLodAsset::m_materialSlots) ; } Mesh::Reflect(context); } - + void ModelLodAsset::Mesh::Reflect(AZ::ReflectContext* context) { if (auto* serializeContext = azrtti_cast(context)) { serializeContext->Class() - ->Version(0) - ->Field("Material", &ModelLodAsset::Mesh::m_materialAsset) + ->Version(1) ->Field("Name", &ModelLodAsset::Mesh::m_name) ->Field("AABB", &ModelLodAsset::Mesh::m_aabb) + ->Field("MaterialSlotIndex", &ModelLodAsset::Mesh::m_materialSlotIndex) ->Field("IndexBufferAssetView", &ModelLodAsset::Mesh::m_indexBufferAssetView) ->Field("StreamBufferInfo", &ModelLodAsset::Mesh::m_streamBufferInfo) ; @@ -75,9 +76,9 @@ namespace AZ return m_indexBufferAssetView.GetBufferViewDescriptor().m_elementCount; } - const Data::Asset & ModelLodAsset::Mesh::GetMaterialAsset() const + size_t ModelLodAsset::Mesh::GetMaterialSlotIndex() const { - return m_materialAsset; + return m_materialSlotIndex; } const AZ::Name& ModelLodAsset::Mesh::GetName() const @@ -118,6 +119,41 @@ namespace AZ { return m_aabb; } + + AZStd::array_view ModelLodAsset::GetMaterialSlots() const + { + return m_materialSlots; + } + + const ModelMaterialSlot& ModelLodAsset::GetMaterialSlot(size_t slotIndex) const + { + if (slotIndex < m_materialSlots.size()) + { + return m_materialSlots[slotIndex]; + } + else + { + AZ_Error("ModelAsset", false, "Material slot index %zu out of range. ModelAsset has %zu slots.", slotIndex, m_materialSlots.size()); + return m_fallbackSlot; + } + } + + const ModelMaterialSlot* ModelLodAsset::FindMaterialSlot(uint32_t stableId) const + { + auto iter = AZStd::find_if(m_materialSlots.begin(), m_materialSlots.end(), [&stableId](const ModelMaterialSlot& existingMaterialSlot) + { + return existingMaterialSlot.m_stableId == stableId; + }); + + if (iter == m_materialSlots.end()) + { + return nullptr; + } + else + { + return iter; + } + } const BufferAssetView* ModelLodAsset::Mesh::GetSemanticBufferAssetView(const AZ::Name& semantic) const { diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/ModelLodAssetCreator.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/ModelLodAssetCreator.cpp index 6f17a5c590..5a066d2517 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/ModelLodAssetCreator.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/ModelLodAssetCreator.cpp @@ -60,12 +60,32 @@ namespace AZ m_currentMesh.m_aabb = AZStd::move(aabb); } } - - void ModelLodAssetCreator::SetMeshMaterialAsset(const Data::Asset& materialAsset) + + void ModelLodAssetCreator::SetMeshMaterialSlot(const ModelMaterialSlot& materialSlot) { - if (ValidateIsMeshReady()) + auto iter = AZStd::find_if(m_asset->m_materialSlots.begin(), m_asset->m_materialSlots.end(), [&materialSlot](const ModelMaterialSlot& existingMaterialSlot) + { + return existingMaterialSlot.m_stableId == materialSlot.m_stableId; + }); + + if (iter == m_asset->m_materialSlots.end()) { - m_currentMesh.m_materialAsset = materialAsset; + m_currentMesh.m_materialSlotIndex = m_asset->m_materialSlots.size(); + m_asset->m_materialSlots.push_back(materialSlot); + } + else + { + if (materialSlot.m_displayName != iter->m_displayName) + { + ReportWarning("Material slot %u was already added with a different name.", materialSlot.m_stableId); + } + + if (materialSlot.m_defaultMaterialAsset != iter->m_defaultMaterialAsset) + { + ReportWarning("Material slot %u was already added with a different MaterialAsset.", materialSlot.m_stableId); + } + + *iter = materialSlot; } } @@ -288,7 +308,9 @@ namespace AZ creator.SetMeshName(sourceMesh.GetName()); AZ::Aabb aabb = sourceMesh.GetAabb(); creator.SetMeshAabb(AZStd::move(aabb)); - creator.SetMeshMaterialAsset(sourceMesh.GetMaterialAsset()); + + const ModelMaterialSlot& materialSlot = sourceAsset->GetMaterialSlot(sourceMesh.GetMaterialSlotIndex()); + creator.SetMeshMaterialSlot(materialSlot); // Mesh index buffer view const BufferAssetView& sourceIndexBufferView = sourceMesh.GetIndexBufferAssetView(); diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/ModelMaterialSlot.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/ModelMaterialSlot.cpp new file mode 100644 index 0000000000..61f3ebbe3a --- /dev/null +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/ModelMaterialSlot.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include +#include + +namespace AZ +{ + namespace RPI + { + void ModelMaterialSlot::Reflect(AZ::ReflectContext* context) + { + if (auto* serializeContext = azrtti_cast(context)) + { + serializeContext->Class() + ->Version(0) + ->Field("StableId", &ModelMaterialSlot::m_stableId) + ->Field("DisplayName", &ModelMaterialSlot::m_displayName) + ->Field("DefaultMaterialAsset", &ModelMaterialSlot::m_defaultMaterialAsset) + ; + } + } + + } // namespace RPI +} // namespace AZ diff --git a/Gems/Atom/RPI/Code/atom_rpi_reflect_files.cmake b/Gems/Atom/RPI/Code/atom_rpi_reflect_files.cmake index c049837045..49c7231fed 100644 --- a/Gems/Atom/RPI/Code/atom_rpi_reflect_files.cmake +++ b/Gems/Atom/RPI/Code/atom_rpi_reflect_files.cmake @@ -22,6 +22,7 @@ set(FILES Include/Atom/RPI.Reflect/Model/ModelKdTree.h Include/Atom/RPI.Reflect/Model/ModelLodAsset.h Include/Atom/RPI.Reflect/Model/ModelLodIndex.h + Include/Atom/RPI.Reflect/Model/ModelMaterialSlot.h Include/Atom/RPI.Reflect/Model/ModelAssetCreator.h Include/Atom/RPI.Reflect/Model/ModelLodAssetCreator.h Include/Atom/RPI.Reflect/Model/MorphTargetDelta.h @@ -106,6 +107,7 @@ set(FILES Source/RPI.Reflect/Model/ModelLodAsset.cpp Source/RPI.Reflect/Model/ModelAssetCreator.cpp Source/RPI.Reflect/Model/ModelLodAssetCreator.cpp + Source/RPI.Reflect/Model/ModelMaterialSlot.cpp Source/RPI.Reflect/Model/MorphTargetDelta.cpp Source/RPI.Reflect/Model/MorphTargetMetaAsset.cpp Source/RPI.Reflect/Model/MorphTargetMetaAssetCreator.cpp diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Material/MaterialComponentBus.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Material/MaterialComponentBus.h index 134bf6db47..4072684987 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Material/MaterialComponentBus.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Material/MaterialComponentBus.h @@ -69,6 +69,9 @@ namespace AZ : public ComponentBus { public: + //! Returns the list of all ModelMaterialSlot's for the model, across all LODs. + virtual RPI::ModelMaterialSlotMap GetModelMaterialSlots() const = 0; + virtual MaterialAssignmentMap GetMaterialAssignments() const = 0; virtual AZStd::unordered_set GetModelUvNames() const = 0; }; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.cpp index d7dc4335b3..f1767a8b1d 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.cpp @@ -44,57 +44,8 @@ namespace AZ if (classElement.GetVersion() < 3) { - // The default material was changed from an asset to an EditorMaterialComponentSlot and old data must be converted - constexpr AZ::u32 defaultMaterialAssetDataCrc = AZ_CRC("defaultMaterialAsset", 0x736fc071); - - Data::Asset oldDefaultMaterialData; - if (!classElement.GetChildData(defaultMaterialAssetDataCrc, oldDefaultMaterialData)) - { - AZ_Error("AZ::Render::EditorMaterialComponent::ConvertVersion", false, "Failed to get defaultMaterialAsset element"); - return false; - } - - if (!classElement.RemoveElementByName(defaultMaterialAssetDataCrc)) - { - AZ_Error("AZ::Render::EditorMaterialComponent::ConvertVersion", false, "Failed to remove defaultMaterialAsset element"); - return false; - } - - EditorMaterialComponentSlot newDefaultMaterialData; - newDefaultMaterialData.m_id = DefaultMaterialAssignmentId; - newDefaultMaterialData.m_materialAsset = oldDefaultMaterialData; - classElement.AddElementWithData(context, "defaultMaterialSlot", newDefaultMaterialData); - - // Slots now support and display the default material asset when empty - // The old placeholder assignments are irrelevant and must be cleared - constexpr AZ::u32 materialSlotsByLodDataCrc = AZ_CRC("materialSlotsByLod", 0xb1498db6); - - EditorMaterialComponentSlotsByLodContainer lodSlotData; - if (!classElement.GetChildData(materialSlotsByLodDataCrc, lodSlotData)) - { - AZ_Error("AZ::Render::EditorMaterialComponent::ConvertVersion", false, "Failed to get materialSlotsByLod element"); - return false; - } - - if (!classElement.RemoveElementByName(materialSlotsByLodDataCrc)) - { - AZ_Error("AZ::Render::EditorMaterialComponent::ConvertVersion", false, "Failed to remove materialSlotsByLod element"); - return false; - } - - // Find and clear all slots that are assigned to the slot's default value - for (auto& lodSlots : lodSlotData) - { - for (auto& slot : lodSlots) - { - if (slot.m_materialAsset.GetId() == slot.m_id.m_materialAssetId) - { - slot.m_materialAsset = {}; - } - } - } - - classElement.AddElementWithData(context, "materialSlotsByLod", lodSlotData); + AZ_Error("EditorMaterialComponent", false, "Material Component version < 3 is no longer supported"); + return false; } if (classElement.GetVersion() < 4) @@ -238,7 +189,7 @@ namespace AZ for (auto& materialSlotPair : GetMaterialSlots()) { EditorMaterialComponentSlot* materialSlot = materialSlotPair.second; - if (materialSlot->m_id.IsAssetOnly()) + if (materialSlot->m_id.IsSlotIdOnly()) { materialSlot->Clear(); } @@ -251,7 +202,7 @@ namespace AZ for (auto& materialSlotPair : GetMaterialSlots()) { EditorMaterialComponentSlot* materialSlot = materialSlotPair.second; - if (materialSlot->m_id.IsLodAndAsset()) + if (materialSlot->m_id.IsLodAndSlotId()) { materialSlot->Clear(); } @@ -318,6 +269,9 @@ namespace AZ // Build the controller configuration from the editor configuration MaterialComponentConfig config = m_controller.GetConfiguration(); config.m_materials.clear(); + + RPI::ModelMaterialSlotMap modelMaterialSlots; + MaterialReceiverRequestBus::EventResult(modelMaterialSlots, GetEntityId(), &MaterialReceiverRequestBus::Events::GetModelMaterialSlots); for (const auto& materialSlotPair : GetMaterialSlots()) { @@ -340,10 +294,15 @@ namespace AZ } else if (!materialSlot->m_propertyOverrides.empty() || !materialSlot->m_matModUvOverrides.empty()) { - MaterialAssignment& materialAssignment = config.m_materials[materialSlot->m_id]; - materialAssignment.m_materialAsset.Create(materialSlot->m_id.m_materialAssetId); - materialAssignment.m_propertyOverrides = materialSlot->m_propertyOverrides; - materialAssignment.m_matModUvOverrides = materialSlot->m_matModUvOverrides; + auto materialSlotIter = modelMaterialSlots.find(materialSlot->m_id.m_materialSlotStableId); + + if (materialSlotIter != modelMaterialSlots.end()) + { + MaterialAssignment& materialAssignment = config.m_materials[materialSlot->m_id]; + materialAssignment.m_materialAsset = materialSlotIter->second.m_defaultMaterialAsset; + materialAssignment.m_propertyOverrides = materialSlot->m_propertyOverrides; + materialAssignment.m_matModUvOverrides = materialSlot->m_matModUvOverrides; + } } } @@ -362,6 +321,9 @@ namespace AZ // Get the known material assignment slots from the associated model or other source MaterialAssignmentMap materialsFromSource; MaterialReceiverRequestBus::EventResult(materialsFromSource, GetEntityId(), &MaterialReceiverRequestBus::Events::GetMaterialAssignments); + + RPI::ModelMaterialSlotMap modelMaterialSlots; + MaterialReceiverRequestBus::EventResult(modelMaterialSlots, GetEntityId(), &MaterialReceiverRequestBus::Events::GetModelMaterialSlots); // Generate the table of editable materials using the source data to define number of groups, elements, and initial values for (const auto& materialPair : materialsFromSource) @@ -385,6 +347,29 @@ namespace AZ OnConfigurationChanged(); }; + const char* UnknownSlotName = ""; + + // If this is the default material assignment ID then it represents the default slot which is not contained in any other group + if (slot.m_id == DefaultMaterialAssignmentId) + { + slot.m_label = "Default Material"; + } + else + { + auto slotIter = modelMaterialSlots.find(slot.m_id.m_materialSlotStableId); + if (slotIter != modelMaterialSlots.end()) + { + const Name& displayName = slotIter->second.m_displayName; + slot.m_label = !displayName.IsEmpty() ? displayName.GetStringView() : UnknownSlotName; + + slot.m_defaultMaterialAsset = slotIter->second.m_defaultMaterialAsset; + } + else + { + slot.m_label = UnknownSlotName; + } + } + // if material is present in controller configuration, assign its data const MaterialAssignment& materialFromController = GetMaterialAssignmentFromMap(config.m_materials, slot.m_id); slot.m_materialAsset = materialFromController.m_materialAsset; @@ -400,13 +385,13 @@ namespace AZ continue; } - if (slot.m_id.IsAssetOnly()) + if (slot.m_id.IsSlotIdOnly()) { m_materialSlots.push_back(slot); continue; } - if (slot.m_id.IsLodAndAsset()) + if (slot.m_id.IsLodAndSlotId()) { // Resize the containers to fit all elements m_materialSlotsByLod.resize(AZ::GetMax(m_materialSlotsByLod.size(), aznumeric_cast(slot.m_id.m_lodIndex + 1))); @@ -452,17 +437,19 @@ namespace AZ { AzToolsFramework::ScopedUndoBatch undoBatch("Generating materials."); SetDirty(); + + RPI::ModelMaterialSlotMap modelMaterialSlots; + MaterialReceiverRequestBus::EventResult(modelMaterialSlots, GetEntityId(), &MaterialReceiverRequestBus::Events::GetModelMaterialSlots); // First generating a unique set of all material asset IDs that will be used for source data generation AZStd::unordered_set assetIds; - auto materialSlots = GetMaterialSlots(); - for (auto& materialSlotPair : materialSlots) + for (auto& materialSlot : modelMaterialSlots) { - EditorMaterialComponentSlot* materialSlot = materialSlotPair.second; - if (materialSlot->m_id.m_materialAssetId.IsValid()) + Data::AssetId defaultMaterialAssetId = materialSlot.second.m_defaultMaterialAsset.GetId(); + if (defaultMaterialAssetId.IsValid()) { - assetIds.insert(materialSlot->m_id.m_materialAssetId); + assetIds.insert(defaultMaterialAssetId); } } @@ -472,7 +459,7 @@ namespace AZ for (const AZ::Data::AssetId& assetId : assetIds) { EditorMaterialComponentExporter::ExportItem exportItem; - exportItem.m_assetId = assetId; + exportItem.m_originalAssetId = assetId; exportItems.push_back(exportItem); } @@ -489,12 +476,23 @@ namespace AZ const auto& assetIdOutcome = AZ::RPI::AssetUtils::MakeAssetId(exportItem.m_exportPath, 0); if (assetIdOutcome) { - for (auto& materialSlotPair : materialSlots) + for (auto& materialSlotPair : GetMaterialSlots()) { - EditorMaterialComponentSlot* materialSlot = materialSlotPair.second; - if (materialSlot && materialSlot->m_id.m_materialAssetId == exportItem.m_assetId) + EditorMaterialComponentSlot* editorMaterialSlot = materialSlotPair.second; + + if (editorMaterialSlot) { - materialSlot->m_materialAsset.Create(assetIdOutcome.GetValue()); + // Only update the slot of it was originally empty, having no override material. + // We need to check whether replaced material corresponds to this slot's default material. + if (!editorMaterialSlot->m_materialAsset.GetId().IsValid()) + { + auto materialSlot = modelMaterialSlots.find(editorMaterialSlot->m_id.m_materialSlotStableId); + if (materialSlot != modelMaterialSlots.end() && + materialSlot->second.m_defaultMaterialAsset.GetId() == exportItem.m_originalAssetId) + { + editorMaterialSlot->m_materialAsset.Create(assetIdOutcome.GetValue()); + } + } } } } diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentExporter.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentExporter.cpp index bde500bdc5..1e6b19f616 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentExporter.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentExporter.cpp @@ -132,7 +132,7 @@ namespace AZ int row = 0; for (ExportItem& exportItem : exportItems) { - QFileInfo fileInfo(GetExportPathByAssetId(exportItem.m_assetId).c_str()); + QFileInfo fileInfo(GetExportPathByAssetId(exportItem.m_originalAssetId).c_str()); // Configuring initial settings based on whether or not the target file already exists exportItem.m_exportPath = fileInfo.absoluteFilePath().toUtf8().constData(); @@ -147,7 +147,7 @@ namespace AZ // Create a check box for toggling the enabled state of this item QCheckBox* materialSlotCheckBox = new QCheckBox(tableWidget); materialSlotCheckBox->setChecked(exportItem.m_enabled); - materialSlotCheckBox->setText(GetLabelByAssetId(exportItem.m_assetId).c_str()); + materialSlotCheckBox->setText(GetLabelByAssetId(exportItem.m_originalAssetId).c_str()); tableWidget->setCellWidget(row, MaterialSlotColumn, materialSlotCheckBox); // Create a file picker widget for selecting the save path for the exported material @@ -256,7 +256,7 @@ namespace AZ } EditorMaterialComponentUtil::MaterialEditData editData; - if (!EditorMaterialComponentUtil::LoadMaterialEditDataFromAssetId(exportItem.m_assetId, editData)) + if (!EditorMaterialComponentUtil::LoadMaterialEditDataFromAssetId(exportItem.m_originalAssetId, editData)) { AZ_Warning("AZ::Render::EditorMaterialComponentExporter", false, "Failed to load material data."); return false; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentExporter.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentExporter.h index 00bef9ee66..289bde0c75 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentExporter.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentExporter.h @@ -19,10 +19,10 @@ namespace AZ { namespace EditorMaterialComponentExporter { - // Attemts to generate a display label for a material slot by parsing its file name + //! Attemts to generate a display label for a material slot by parsing its file name AZStd::string GetLabelByAssetId(const AZ::Data::AssetId& assetId); - // Generates a destination file path for exporting material source data + //! Generates a destination file path for exporting material source data AZStd::string GetExportPathByAssetId(const AZ::Data::AssetId& assetId); struct ExportItem @@ -30,16 +30,17 @@ namespace AZ bool m_enabled = true; bool m_exists = false; bool m_overwrite = false; - AZ::Data::AssetId m_assetId; + AZ::Data::AssetId m_originalAssetId; //!< AssetId of the original built-in material, which will be exported. AZStd::string m_exportPath; }; using ExportItemsContainer = AZStd::vector; - // Generates and opens a dialog for configuring material data export paths and actions + //! Generates and opens a dialog for configuring material data export paths and actions. + //! Note this will not modify the m_originalAssetId field in each ExportItem. bool OpenExportDialog(ExportItemsContainer& exportItems); - // Attemts to construct and save material source data from a product asset + //! Attemts to construct and save material source data from a product asset bool ExportMaterialSourceData(const ExportItem& exportItem); } // namespace EditorMaterialComponentExporter } // namespace Render diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp index d341bbb290..c8a2024b39 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp @@ -20,7 +20,7 @@ AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT #include -#include +#include #include AZ_POP_DISABLE_WARNING @@ -48,7 +48,7 @@ namespace AZ return false; } - const MaterialAssignmentId newId(oldId.first, oldId.second); + const MaterialAssignmentId newId(oldId.first, oldId.second.m_subId); classElement.AddElementWithData(context, "id", newId); } @@ -83,6 +83,7 @@ namespace AZ ->Version(5, &EditorMaterialComponentSlot::ConvertVersion) ->Field("id", &EditorMaterialComponentSlot::m_id) ->Field("materialAsset", &EditorMaterialComponentSlot::m_materialAsset) + ->Field("defaultMaterialAsset", &EditorMaterialComponentSlot::m_defaultMaterialAsset) ; if (AZ::EditContext* editContext = serializeContext->GetEditContext()) @@ -121,21 +122,12 @@ namespace AZ AZ::Data::AssetId EditorMaterialComponentSlot::GetDefaultAssetId() const { - return m_id.m_materialAssetId; + return m_defaultMaterialAsset.GetId(); } AZStd::string EditorMaterialComponentSlot::GetLabel() const { - // Generate the label for the material slot based on the assignment ID - // If this is the default material assignment ID then it represents the default slot which is not contained in any other group - if (m_id == DefaultMaterialAssignmentId) - { - return "Default Material"; - } - - // Otherwise the label can be generated by parsing the source file name associated with the asset ID - const AZStd::string& label = EditorMaterialComponentExporter::GetLabelByAssetId(m_id.m_materialAssetId); - return !label.empty() ? label : ""; + return m_label; } bool EditorMaterialComponentSlot::HasSourceData() const @@ -183,27 +175,22 @@ namespace AZ OnMaterialChanged(); } - void EditorMaterialComponentSlot::SetDefaultAsset() + void EditorMaterialComponentSlot::ResetToDefaultAsset() { - m_materialAsset = {}; + m_materialAsset = m_defaultMaterialAsset; m_propertyOverrides = {}; m_matModUvOverrides = {}; - if (m_id.m_materialAssetId.IsValid()) - { - // If no material is assigned to this slot, assign the default material from the slot id to edit its properties - m_materialAsset.Create(m_id.m_materialAssetId); - } OnMaterialChanged(); } void EditorMaterialComponentSlot::OpenMaterialExporter() { // Because we are generating a source material from this specific slot there is only one entry - // But we still need to allow the user to reconfigure it using the dialogue + // But we still need to allow the user to reconfigure it using the dialog EditorMaterialComponentExporter::ExportItemsContainer exportItems; { EditorMaterialComponentExporter::ExportItem exportItem; - exportItem.m_assetId = m_id.m_materialAssetId; + exportItem.m_originalAssetId = m_defaultMaterialAsset.GetId(); exportItems.push_back(exportItem); } @@ -275,7 +262,7 @@ namespace AZ QAction* action = nullptr; action = menu.addAction("Generate/Manage Source Material...", [this]() { OpenMaterialExporter(); }); - action->setEnabled(m_id.m_materialAssetId.IsValid()); + action->setEnabled(m_defaultMaterialAsset.GetId().IsValid()); menu.addSeparator(); diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.h index e8b4f46854..79fddf2611 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.h @@ -34,7 +34,7 @@ namespace AZ AZStd::string GetLabel() const; bool HasSourceData() const; void OpenMaterialEditor() const; - void SetDefaultAsset(); + void ResetToDefaultAsset(); void Clear(); void ClearOverrides(); void OpenMaterialExporter(); @@ -42,7 +42,9 @@ namespace AZ void OpenUvNameMapInspector(); MaterialAssignmentId m_id; + AZStd::string m_label; Data::Asset m_materialAsset; + Data::Asset m_defaultMaterialAsset; MaterialPropertyOverrideMap m_propertyOverrides; AZStd::function m_materialChangedCallback; AZStd::function m_propertyChangedCallback; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentConfig.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentConfig.cpp index a0adcd3187..f7b7177e29 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentConfig.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentConfig.cpp @@ -44,7 +44,7 @@ namespace AZ for (const auto& oldPair : oldMaterials) { const DeprecatedMaterialAssignmentId& oldId = oldPair.first; - const MaterialAssignmentId newId(oldId.first, oldId.second); + const MaterialAssignmentId newId(oldId.first, oldId.second.m_subId); newMaterials[newId] = oldPair.second; } diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp index 29bd9a839b..a2a3022e91 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp @@ -251,6 +251,19 @@ namespace AZ m_meshFeatureProcessor->SetTransform(m_meshHandle, m_transformInterface->GetWorldTM(), m_cachedNonUniformScale); } } + + RPI::ModelMaterialSlotMap MeshComponentController::GetModelMaterialSlots() const + { + Data::Asset modelAsset = GetModelAsset(); + if (modelAsset.IsReady()) + { + return modelAsset->GetModelMaterialSlots(); + } + else + { + return {}; + } + } MaterialAssignmentMap MeshComponentController::GetMaterialAssignments() const { diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h index 80b483452f..78c2e0797f 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h @@ -111,6 +111,7 @@ namespace AZ void OnTransformChanged(const AZ::Transform& local, const AZ::Transform& world) override; // MaterialReceiverRequestBus::Handler overrides ... + RPI::ModelMaterialSlotMap GetModelMaterialSlots() const override; MaterialAssignmentMap GetMaterialAssignments() const override; AZStd::unordered_set GetModelUvNames() const override; diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/ActorAsset.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/ActorAsset.cpp index 3143191135..ae617f910f 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/ActorAsset.cpp +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/ActorAsset.cpp @@ -96,12 +96,10 @@ namespace AZ skinnedSubMesh.m_vertexCount = aznumeric_cast(subMeshVertexCount); lodVertexCount += aznumeric_cast(subMeshVertexCount); - // The default material id used by a sub-mesh is the guid of the source scene file plus the subId which is a unique material ID from the scene API - AZ::u32 subId = modelMesh.GetMaterialAsset().GetId().m_subId; - AZ::Data::AssetId materialId{ actorAssetId.m_guid, subId }; - + skinnedSubMesh.m_material = lodAsset->GetMaterialSlot(modelMesh.GetMaterialSlotIndex()).m_defaultMaterialAsset; // Queue the material asset - the ModelLod seems to handle delayed material loads - skinnedSubMesh.m_material = Data::AssetManager::Instance().GetAsset(materialId, azrtti_typeid(), skinnedSubMesh.m_material.GetAutoLoadBehavior()); + skinnedSubMesh.m_material.QueueLoad(); + subMeshes.push_back(skinnedSubMesh); } else diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp index 4c6045d7ce..6697162c18 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp @@ -307,6 +307,19 @@ namespace AZ m_meshFeatureProcessor = nullptr; m_skinnedMeshFeatureProcessor = nullptr; } + + RPI::ModelMaterialSlotMap AtomActorInstance::GetModelMaterialSlots() const + { + Data::Asset modelAsset = GetModelAsset(); + if (modelAsset.IsReady()) + { + return modelAsset->GetModelMaterialSlots(); + } + else + { + return {}; + } + } MaterialAssignmentMap AtomActorInstance::GetMaterialAssignments() const { diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.h b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.h index c854fed3c1..e7a4047012 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.h +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.h @@ -120,6 +120,7 @@ namespace AZ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// // MaterialReceiverRequestBus::Handler overrides... + RPI::ModelMaterialSlotMap GetModelMaterialSlots() const override; MaterialAssignmentMap GetMaterialAssignments() const override; AZStd::unordered_set GetModelUvNames() const override; diff --git a/Gems/WhiteBox/Code/Source/Rendering/Atom/WhiteBoxAtomRenderMesh.cpp b/Gems/WhiteBox/Code/Source/Rendering/Atom/WhiteBoxAtomRenderMesh.cpp index 3f089a8639..5a9b8191ed 100644 --- a/Gems/WhiteBox/Code/Source/Rendering/Atom/WhiteBoxAtomRenderMesh.cpp +++ b/Gems/WhiteBox/Code/Source/Rendering/Atom/WhiteBoxAtomRenderMesh.cpp @@ -116,7 +116,10 @@ namespace WhiteBox // set the default material if (auto materialAsset = AZ::RPI::AssetUtils::LoadAssetByProductPath(TexturedMaterialPath.data())) { - modelLodCreator.SetMeshMaterialAsset(materialAsset); + AZ::RPI::ModelMaterialSlot materialSlot; + materialSlot.m_stableId = 0; + materialSlot.m_defaultMaterialAsset = materialAsset; + modelLodCreator.SetMeshMaterialSlot(materialSlot); } else { From e3ceaa477e338d553920f8363fed99384dac0335 Mon Sep 17 00:00:00 2001 From: Chris Santora Date: Sat, 17 Jul 2021 12:54:40 -0700 Subject: [PATCH 121/160] Added a version converter for MaterialAssignmentId. This allowed me to successfully load the Sponza level in AtomTest. Signed-off-by: santorac <55155825+santorac@users.noreply.github.com> --- .../Feature/Material/MaterialAssignmentId.h | 1 + .../Source/Material/MaterialAssignmentId.cpp | 27 ++++++++++++++++++- .../Material/EditorMaterialComponentSlot.cpp | 2 +- 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Material/MaterialAssignmentId.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Material/MaterialAssignmentId.h index d9ae8099da..e58a8397db 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Material/MaterialAssignmentId.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Material/MaterialAssignmentId.h @@ -31,6 +31,7 @@ namespace AZ AZ_RTTI(AZ::Render::MaterialAssignmentId, "{EB603581-4654-4C17-B6DE-AE61E79EDA97}"); AZ_CLASS_ALLOCATOR(AZ::Render::MaterialAssignmentId, SystemAllocator, 0); static void Reflect(ReflectContext* context); + static bool ConvertVersion(AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement); MaterialAssignmentId() = default; diff --git a/Gems/Atom/Feature/Common/Code/Source/Material/MaterialAssignmentId.cpp b/Gems/Atom/Feature/Common/Code/Source/Material/MaterialAssignmentId.cpp index 8b6b0be237..5db6c4c15c 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Material/MaterialAssignmentId.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Material/MaterialAssignmentId.cpp @@ -14,12 +14,37 @@ namespace AZ { namespace Render { + bool MaterialAssignmentId::ConvertVersion(AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement) + { + if (classElement.GetVersion() < 2) + { + constexpr AZ::u32 materialAssetIdCrc = AZ_CRC("materialAssetId"); + + AZ::Data::AssetId materialAssetId; + if (!classElement.GetChildData(materialAssetIdCrc, materialAssetId)) + { + AZ_Error("AZ::Render::MaterialAssignmentId::ConvertVersion", false, "Failed to get AssetId element"); + return false; + } + + if (!classElement.RemoveElementByName(materialAssetIdCrc)) + { + AZ_Error("AZ::Render::MaterialAssignmentId::ConvertVersion", false, "Failed to remove deprecated element materialAssetId"); + // No need to early-return, the object will still load successfully, it will just report more errors about the unrecognized element. + } + + classElement.AddElementWithData(context, "materialSlotStableId", materialAssetId.m_subId); + } + + return true; + } + void MaterialAssignmentId::Reflect(ReflectContext* context) { if (auto serializeContext = azrtti_cast(context)) { serializeContext->Class() - ->Version(2) + ->Version(2, &MaterialAssignmentId::ConvertVersion) ->Field("lodIndex", &MaterialAssignmentId::m_lodIndex) ->Field("materialSlotStableId", &MaterialAssignmentId::m_materialSlotStableId) ; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp index c8a2024b39..0a32f9b125 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp @@ -80,7 +80,7 @@ namespace AZ if (AZ::SerializeContext* serializeContext = azrtti_cast(context)) { serializeContext->Class() - ->Version(5, &EditorMaterialComponentSlot::ConvertVersion) + ->Version(6, &EditorMaterialComponentSlot::ConvertVersion) ->Field("id", &EditorMaterialComponentSlot::m_id) ->Field("materialAsset", &EditorMaterialComponentSlot::m_materialAsset) ->Field("defaultMaterialAsset", &EditorMaterialComponentSlot::m_defaultMaterialAsset) From 670dd6c5bc2031881f25737488075d6616cf3544 Mon Sep 17 00:00:00 2001 From: Chris Santora Date: Sat, 17 Jul 2021 18:18:28 -0700 Subject: [PATCH 122/160] Removed the GetLabelByAssetId function since now we can use the display name that comes with the ModelMaterialSlot. Updated OpenMaterialExporter() to account for the fact that multiple material slots can have the same default material asset. Updated the material inspector to sort material slots by name to match the order in the Material Component. Updated ExportItem to protect its data members, which makes it more clear that assetId and materialSlotName are readonly inputs. Signed-off-by: santorac <55155825+santorac@users.noreply.github.com> --- .../Material/EditorMaterialComponent.cpp | 53 +++++++---- .../EditorMaterialComponentExporter.cpp | 90 ++++++------------- .../EditorMaterialComponentExporter.h | 32 +++++-- .../Material/EditorMaterialComponentSlot.cpp | 5 +- 4 files changed, 88 insertions(+), 92 deletions(-) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.cpp index f1767a8b1d..16a657a64f 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.cpp @@ -17,6 +17,7 @@ #include #include #include +#include AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT #include @@ -438,30 +439,46 @@ namespace AZ AzToolsFramework::ScopedUndoBatch undoBatch("Generating materials."); SetDirty(); + Data::AssetId modelAssetId; + MeshComponentRequestBus::EventResult(modelAssetId, GetEntityId(), &MeshComponentRequestBus::Events::GetModelAssetId); + RPI::ModelMaterialSlotMap modelMaterialSlots; MaterialReceiverRequestBus::EventResult(modelMaterialSlots, GetEntityId(), &MaterialReceiverRequestBus::Events::GetModelMaterialSlots); + + EditorMaterialComponentExporter::ExportItemsContainer exportItems; - // First generating a unique set of all material asset IDs that will be used for source data generation - AZStd::unordered_set assetIds; - - for (auto& materialSlot : modelMaterialSlots) + // Generate a list of export items for the set of unique default material assets from the model. + for (auto& materialSlotPair : modelMaterialSlots) { - Data::AssetId defaultMaterialAssetId = materialSlot.second.m_defaultMaterialAsset.GetId(); - if (defaultMaterialAssetId.IsValid()) + // We only care about material assets that were generated from the model source file, since those are the + // ones that would need conversion (other materials already have their own source file). This can be detected + // by matching GUID component of the AssetId. + Data::AssetId defaultMaterialAssetId = materialSlotPair.second.m_defaultMaterialAsset.GetId(); + bool materialWasGeneratedFromModel = defaultMaterialAssetId.IsValid() && defaultMaterialAssetId.m_guid == modelAssetId.m_guid; + if (materialWasGeneratedFromModel) { - assetIds.insert(defaultMaterialAssetId); + auto duplicateAssetIter = AZStd::find_if(exportItems.begin(), exportItems.end(), + [defaultMaterialAssetId](const EditorMaterialComponentExporter::ExportItem& existingExportItem) + { + return existingExportItem.GetOriginalAssetId() == defaultMaterialAssetId; + }); + + // It's possible for multiple material slots to have the same default material asset. So we just use the first one, which just means the + // exported material file name will be based on the first relevant material slot's name. + if (duplicateAssetIter == exportItems.end()) + { + EditorMaterialComponentExporter::ExportItem exportItem{defaultMaterialAssetId, materialSlotPair.second.m_displayName.GetStringView()}; + exportItems.push_back(exportItem); + } } } - // Convert the unique set of asset IDs into export items that can be configured in the dialog - // The order should not matter because the table in the dialog can sort itself for a specific row - EditorMaterialComponentExporter::ExportItemsContainer exportItems; - for (const AZ::Data::AssetId& assetId : assetIds) - { - EditorMaterialComponentExporter::ExportItem exportItem; - exportItem.m_originalAssetId = assetId; - exportItems.push_back(exportItem); - } + // Sort by display name so the list order will match what's displayed in the Material Component. + AZStd::sort(exportItems.begin(), exportItems.end(), + [](const EditorMaterialComponentExporter::ExportItem& a, const EditorMaterialComponentExporter::ExportItem& b) + { + return a.GetMaterialSlotName() < b.GetMaterialSlotName(); + }); // Display the export dialog so that the user can configure how they want different materials to be exported if (EditorMaterialComponentExporter::OpenExportDialog(exportItems)) @@ -473,7 +490,7 @@ namespace AZ continue; } - const auto& assetIdOutcome = AZ::RPI::AssetUtils::MakeAssetId(exportItem.m_exportPath, 0); + const auto& assetIdOutcome = AZ::RPI::AssetUtils::MakeAssetId(exportItem.GetExportPath(), 0); if (assetIdOutcome) { for (auto& materialSlotPair : GetMaterialSlots()) @@ -488,7 +505,7 @@ namespace AZ { auto materialSlot = modelMaterialSlots.find(editorMaterialSlot->m_id.m_materialSlotStableId); if (materialSlot != modelMaterialSlots.end() && - materialSlot->second.m_defaultMaterialAsset.GetId() == exportItem.m_originalAssetId) + materialSlot->second.m_defaultMaterialAsset.GetId() == exportItem.GetOriginalAssetId()) { editorMaterialSlot->m_materialAsset.Create(assetIdOutcome.GetValue()); } diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentExporter.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentExporter.cpp index 1e6b19f616..32a36392a4 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentExporter.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentExporter.cpp @@ -37,47 +37,7 @@ namespace AZ { namespace EditorMaterialComponentExporter { - AZStd::string GetLabelByAssetId(const AZ::Data::AssetId& assetId) - { - AZStd::string label; - if (assetId.IsValid()) - { - // Material assets that are exported through the scene pipeline have their filenames generated by adding - // the DCC material name as a prefix and a unique number to the end of the source file name. - // Rather than storing the DCC material name inside of the material asset we can reproduce it by removing - // the prefix and suffix from the product file name. - - // We need the material product path as the initial string that will be stripped down - const AZStd::string& productPath = AZ::RPI::AssetUtils::GetProductPathByAssetId(assetId); - if (!productPath.empty() && AzFramework::StringFunc::Path::GetFileName(productPath.c_str(), label)) - { - // If there is a source file, typically an FBX or other model file, we must get its filename to remove the prefix from the label - AZStd::string prefix; - const AZStd::string& sourcePath = AZ::RPI::AssetUtils::GetSourcePathByAssetId(assetId); - if (!sourcePath.empty() && AZ::StringFunc::Path::GetFileName(sourcePath.c_str(), prefix)) - { - if (!prefix.empty() && prefix.size() < label.size()) - { - if (AZ::StringFunc::StartsWith(label, prefix, false)) - { - // All of the product filename's tokens are separated by underscores so we must also remove the first underscore after the prefix - label = label.substr(prefix.size() + 1); - } - } - } - - // We can remove the numeric suffix by stripping the label of everything after the last underscore - const auto iter = label.find_last_of("_"); - if (iter != AZStd::string::npos) - { - label = label.substr(0, iter); - } - } - } - return label; - } - - AZStd::string GetExportPathByAssetId(const AZ::Data::AssetId& assetId) + AZStd::string GetExportPathByAssetId(const AZ::Data::AssetId& assetId, const AZStd::string& materialSlotName) { AZStd::string exportPath; if (assetId.IsValid()) @@ -85,7 +45,7 @@ namespace AZ exportPath = AZ::RPI::AssetUtils::GetSourcePathByAssetId(assetId); AZ::StringFunc::Path::StripExtension(exportPath); exportPath += "_"; - exportPath += GetLabelByAssetId(assetId); + exportPath += materialSlotName; exportPath += "."; exportPath += AZ::RPI::MaterialSourceData::Extension; AZ::StringFunc::Path::Normalize(exportPath); @@ -132,12 +92,12 @@ namespace AZ int row = 0; for (ExportItem& exportItem : exportItems) { - QFileInfo fileInfo(GetExportPathByAssetId(exportItem.m_originalAssetId).c_str()); + QFileInfo fileInfo(GetExportPathByAssetId(exportItem.GetOriginalAssetId(), exportItem.GetMaterialSlotName()).c_str()); // Configuring initial settings based on whether or not the target file already exists - exportItem.m_exportPath = fileInfo.absoluteFilePath().toUtf8().constData(); - exportItem.m_exists = fileInfo.exists(); - exportItem.m_overwrite = false; + exportItem.SetExportPath(fileInfo.absoluteFilePath().toUtf8().constData()); + exportItem.SetExists(fileInfo.exists()); + exportItem.SetOverwrite(false); // Populate the table with data for every column tableWidget->setItem(row, MaterialSlotColumn, new QTableWidgetItem()); @@ -146,23 +106,23 @@ namespace AZ // Create a check box for toggling the enabled state of this item QCheckBox* materialSlotCheckBox = new QCheckBox(tableWidget); - materialSlotCheckBox->setChecked(exportItem.m_enabled); - materialSlotCheckBox->setText(GetLabelByAssetId(exportItem.m_originalAssetId).c_str()); + materialSlotCheckBox->setChecked(exportItem.GetEnabled()); + materialSlotCheckBox->setText(exportItem.GetMaterialSlotName().c_str()); tableWidget->setCellWidget(row, MaterialSlotColumn, materialSlotCheckBox); // Create a file picker widget for selecting the save path for the exported material AzQtComponents::BrowseEdit* materialFileWidget = new AzQtComponents::BrowseEdit(tableWidget); materialFileWidget->setLineEditReadOnly(true); materialFileWidget->setClearButtonEnabled(false); - materialFileWidget->setEnabled(exportItem.m_enabled); + materialFileWidget->setEnabled(exportItem.GetEnabled()); materialFileWidget->setText(fileInfo.fileName()); tableWidget->setCellWidget(row, MaterialFileColumn, materialFileWidget); // Create a check box for toggling the overwrite state of this item QWidget* overwriteCheckBoxContainer = new QWidget(tableWidget); QCheckBox* overwriteCheckBox = new QCheckBox(overwriteCheckBoxContainer); - overwriteCheckBox->setChecked(exportItem.m_overwrite); - overwriteCheckBox->setEnabled(exportItem.m_enabled && exportItem.m_exists); + overwriteCheckBox->setChecked(exportItem.GetOverwrite()); + overwriteCheckBox->setEnabled(exportItem.GetEnabled() && exportItem.GetExists()); overwriteCheckBoxContainer->setLayout(new QHBoxLayout(overwriteCheckBoxContainer)); overwriteCheckBoxContainer->layout()->addWidget(overwriteCheckBox); @@ -173,21 +133,21 @@ namespace AZ // Whenever the selection is updated, automatically apply the change to the export item QObject::connect(materialSlotCheckBox, &QCheckBox::stateChanged, materialSlotCheckBox, [&exportItem, materialFileWidget, materialSlotCheckBox, overwriteCheckBox]([[maybe_unused]] int state) { - exportItem.m_enabled = materialSlotCheckBox->isChecked(); - materialFileWidget->setEnabled(exportItem.m_enabled); - overwriteCheckBox->setEnabled(exportItem.m_enabled && exportItem.m_exists); + exportItem.SetEnabled(materialSlotCheckBox->isChecked()); + materialFileWidget->setEnabled(exportItem.GetEnabled()); + overwriteCheckBox->setEnabled(exportItem.GetEnabled() && exportItem.GetExists()); }); // Whenever the overwrite check box is updated, automatically apply the change to the export item QObject::connect(overwriteCheckBox, &QCheckBox::stateChanged, overwriteCheckBox, [&exportItem, overwriteCheckBox]([[maybe_unused]] int state) { - exportItem.m_overwrite = overwriteCheckBox->isChecked(); + exportItem.SetOverwrite(overwriteCheckBox->isChecked()); }); // Whenever the browse button is clicked, open a save file dialog in the same location as the current export file setting QObject::connect(materialFileWidget, &AzQtComponents::BrowseEdit::attachedButtonTriggered, materialFileWidget, [&dialog, &exportItem, materialFileWidget, overwriteCheckBox]() { QFileInfo fileInfo = QFileDialog::getSaveFileName(&dialog, QString("Select Material Filename"), - exportItem.m_exportPath.c_str(), + exportItem.GetExportPath().c_str(), QString("Material (*.material)"), nullptr, QFileDialog::DontConfirmOverwrite); @@ -195,14 +155,14 @@ namespace AZ // Only update the export data if a valid path and filename was selected if (!fileInfo.absoluteFilePath().isEmpty()) { - exportItem.m_exportPath = fileInfo.absoluteFilePath().toUtf8().constData(); - exportItem.m_exists = fileInfo.exists(); - exportItem.m_overwrite = fileInfo.exists(); + exportItem.SetExportPath(fileInfo.absoluteFilePath().toUtf8().constData()); + exportItem.SetExists(fileInfo.exists()); + exportItem.SetOverwrite(fileInfo.exists()); // Update the controls to display the new state materialFileWidget->setText(fileInfo.fileName()); - overwriteCheckBox->setChecked(exportItem.m_overwrite); - overwriteCheckBox->setEnabled(exportItem.m_enabled && exportItem.m_exists); + overwriteCheckBox->setChecked(exportItem.GetOverwrite()); + overwriteCheckBox->setEnabled(exportItem.GetEnabled() && exportItem.GetExists()); } }); @@ -245,24 +205,24 @@ namespace AZ bool ExportMaterialSourceData(const ExportItem& exportItem) { - if (!exportItem.m_enabled || exportItem.m_exportPath.empty()) + if (!exportItem.GetEnabled() || exportItem.GetExportPath().empty()) { return false; } - if (exportItem.m_exists && !exportItem.m_overwrite) + if (exportItem.GetExists() && !exportItem.GetOverwrite()) { return true; } EditorMaterialComponentUtil::MaterialEditData editData; - if (!EditorMaterialComponentUtil::LoadMaterialEditDataFromAssetId(exportItem.m_originalAssetId, editData)) + if (!EditorMaterialComponentUtil::LoadMaterialEditDataFromAssetId(exportItem.GetOriginalAssetId(), editData)) { AZ_Warning("AZ::Render::EditorMaterialComponentExporter", false, "Failed to load material data."); return false; } - if (!EditorMaterialComponentUtil::SaveSourceMaterialFromEditData(exportItem.m_exportPath, editData)) + if (!EditorMaterialComponentUtil::SaveSourceMaterialFromEditData(exportItem.GetExportPath(), editData)) { AZ_Warning("AZ::Render::EditorMaterialComponentExporter", false, "Failed to save material data."); return false; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentExporter.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentExporter.h index 289bde0c75..4830db33c4 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentExporter.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentExporter.h @@ -19,19 +19,39 @@ namespace AZ { namespace EditorMaterialComponentExporter { - //! Attemts to generate a display label for a material slot by parsing its file name - AZStd::string GetLabelByAssetId(const AZ::Data::AssetId& assetId); - //! Generates a destination file path for exporting material source data - AZStd::string GetExportPathByAssetId(const AZ::Data::AssetId& assetId); + AZStd::string GetExportPathByAssetId(const AZ::Data::AssetId& assetId, const AZStd::string& materialSlotName); - struct ExportItem + class ExportItem { + public: + //! @param originalAssetId AssetId of the original built-in material, which will be exported. + //! @param materialSlotName The name of the material slot will be used as part of the exported file name. + ExportItem(AZ::Data::AssetId originalAssetId, const AZStd::string& materialSlotName) + : m_originalAssetId(originalAssetId) + , m_materialSlotName(materialSlotName) + {} + + void SetEnabled(bool enabled) { m_enabled = enabled; } + void SetExists(bool exists) { m_exists = exists; } + void SetOverwrite(bool overwrite) { m_overwrite = overwrite; } + void SetExportPath(const AZStd::string& exportPath) { m_exportPath = exportPath; } + + bool GetEnabled() const { return m_enabled; } + bool GetExists() const { return m_exists; } + bool GetOverwrite() const { return m_overwrite; } + const AZStd::string& GetExportPath() const { return m_exportPath; } + + AZ::Data::AssetId GetOriginalAssetId() const { return m_originalAssetId; } + const AZStd::string& GetMaterialSlotName() const { return m_materialSlotName; } + + private: bool m_enabled = true; bool m_exists = false; bool m_overwrite = false; - AZ::Data::AssetId m_originalAssetId; //!< AssetId of the original built-in material, which will be exported. AZStd::string m_exportPath; + AZ::Data::AssetId m_originalAssetId; //!< AssetId of the original built-in material, which will be exported. + AZStd::string m_materialSlotName; }; using ExportItemsContainer = AZStd::vector; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp index 0a32f9b125..717b87feec 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp @@ -189,8 +189,7 @@ namespace AZ // But we still need to allow the user to reconfigure it using the dialog EditorMaterialComponentExporter::ExportItemsContainer exportItems; { - EditorMaterialComponentExporter::ExportItem exportItem; - exportItem.m_originalAssetId = m_defaultMaterialAsset.GetId(); + EditorMaterialComponentExporter::ExportItem exportItem{m_defaultMaterialAsset.GetId(), m_label}; exportItems.push_back(exportItem); } @@ -205,7 +204,7 @@ namespace AZ } // Generate a new asset ID utilizing the export file path so that we can update this material slot to reference the new asset - const auto& assetIdOutcome = AZ::RPI::AssetUtils::MakeAssetId(exportItem.m_exportPath, 0); + const auto& assetIdOutcome = AZ::RPI::AssetUtils::MakeAssetId(exportItem.GetExportPath(), 0); if (assetIdOutcome) { m_materialAsset.Create(assetIdOutcome.GetValue()); From e145ce1d01334ddea612077150138f893ea41dd7 Mon Sep 17 00:00:00 2001 From: Chris Santora Date: Sat, 17 Jul 2021 18:46:04 -0700 Subject: [PATCH 123/160] Updated EditorMaterialComponentSlot to support editing property overrides and UV overrides for the material, regardless of whether there is a material override or not. Signed-off-by: santorac <55155825+santorac@users.noreply.github.com> --- .../Material/EditorMaterialComponentSlot.cpp | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp index 717b87feec..f9243510cf 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp @@ -227,9 +227,11 @@ namespace AZ OnPropertyChanged(); }; - if (m_materialAsset.GetId().IsValid()) + Data::Asset assetToEdit = m_materialAsset.GetId().IsValid() ? m_materialAsset : m_defaultMaterialAsset; + + if (assetToEdit.GetId().IsValid()) { - if (EditorMaterialComponentInspector::OpenInspectorDialog(GetLabel(), m_materialAsset.GetId(), m_propertyOverrides, applyPropertyChangedCallback)) + if (EditorMaterialComponentInspector::OpenInspectorDialog(GetLabel(), assetToEdit.GetId(), m_propertyOverrides, applyPropertyChangedCallback)) { OnMaterialChanged(); } @@ -244,10 +246,12 @@ namespace AZ // Treated as a special property. It will be updated together with properties. OnPropertyChanged(); }; - - if (m_materialAsset.GetId().IsValid()) + + Data::Asset assetToEdit = m_materialAsset.GetId().IsValid() ? m_materialAsset : m_defaultMaterialAsset; + + if (assetToEdit.GetId().IsValid()) { - if (EditorMaterialComponentInspector::OpenInspectorDialog(m_materialAsset.GetId(), m_matModUvOverrides, m_modelUvNames, applyMatModUvOverrideChangedCallback)) + if (EditorMaterialComponentInspector::OpenInspectorDialog(assetToEdit.GetId(), m_matModUvOverrides, m_modelUvNames, applyMatModUvOverrideChangedCallback)) { OnMaterialChanged(); } @@ -268,11 +272,13 @@ namespace AZ action = menu.addAction("Edit Source Material...", [this]() { OpenMaterialEditor(); }); action->setEnabled(HasSourceData()); + bool hasAnyMaterial = m_defaultMaterialAsset.GetId().IsValid() || m_materialAsset.GetId().IsValid(); + action = menu.addAction("Edit Material Instance...", [this]() { OpenMaterialInspector(); }); - action->setEnabled(m_materialAsset.GetId().IsValid()); + action->setEnabled(hasAnyMaterial); action = menu.addAction("Edit Material Instance UV Map...", [this]() { OpenUvNameMapInspector(); }); - action->setEnabled(m_materialAsset.GetId().IsValid()); + action->setEnabled(hasAnyMaterial); menu.addSeparator(); From 28671c8546179ffe0686f658fc6ef8095a5e4a76 Mon Sep 17 00:00:00 2001 From: Chris Santora Date: Mon, 19 Jul 2021 23:40:18 -0700 Subject: [PATCH 124/160] Addressed suggestions from gadams3 to make EditorMaterialComponent get the default material assets from its own data rather than fetching them from the asset. Presumably this should give more reliable behavior. Signed-off-by: santorac <55155825+santorac@users.noreply.github.com> --- .../Material/EditorMaterialComponent.cpp | 37 +++++-------------- 1 file changed, 10 insertions(+), 27 deletions(-) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.cpp index 16a657a64f..866b2dec56 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.cpp @@ -271,9 +271,6 @@ namespace AZ MaterialComponentConfig config = m_controller.GetConfiguration(); config.m_materials.clear(); - RPI::ModelMaterialSlotMap modelMaterialSlots; - MaterialReceiverRequestBus::EventResult(modelMaterialSlots, GetEntityId(), &MaterialReceiverRequestBus::Events::GetModelMaterialSlots); - for (const auto& materialSlotPair : GetMaterialSlots()) { const EditorMaterialComponentSlot* materialSlot = materialSlotPair.second; @@ -295,15 +292,10 @@ namespace AZ } else if (!materialSlot->m_propertyOverrides.empty() || !materialSlot->m_matModUvOverrides.empty()) { - auto materialSlotIter = modelMaterialSlots.find(materialSlot->m_id.m_materialSlotStableId); - - if (materialSlotIter != modelMaterialSlots.end()) - { - MaterialAssignment& materialAssignment = config.m_materials[materialSlot->m_id]; - materialAssignment.m_materialAsset = materialSlotIter->second.m_defaultMaterialAsset; - materialAssignment.m_propertyOverrides = materialSlot->m_propertyOverrides; - materialAssignment.m_matModUvOverrides = materialSlot->m_matModUvOverrides; - } + MaterialAssignment& materialAssignment = config.m_materials[materialSlot->m_id]; + materialAssignment.m_materialAsset = materialSlot->m_defaultMaterialAsset; + materialAssignment.m_propertyOverrides = materialSlot->m_propertyOverrides; + materialAssignment.m_matModUvOverrides = materialSlot->m_matModUvOverrides; } } @@ -442,18 +434,15 @@ namespace AZ Data::AssetId modelAssetId; MeshComponentRequestBus::EventResult(modelAssetId, GetEntityId(), &MeshComponentRequestBus::Events::GetModelAssetId); - RPI::ModelMaterialSlotMap modelMaterialSlots; - MaterialReceiverRequestBus::EventResult(modelMaterialSlots, GetEntityId(), &MaterialReceiverRequestBus::Events::GetModelMaterialSlots); - EditorMaterialComponentExporter::ExportItemsContainer exportItems; // Generate a list of export items for the set of unique default material assets from the model. - for (auto& materialSlotPair : modelMaterialSlots) + for (auto& materialSlotPair : GetMaterialSlots()) { // We only care about material assets that were generated from the model source file, since those are the // ones that would need conversion (other materials already have their own source file). This can be detected // by matching GUID component of the AssetId. - Data::AssetId defaultMaterialAssetId = materialSlotPair.second.m_defaultMaterialAsset.GetId(); + Data::AssetId defaultMaterialAssetId = materialSlotPair.second->m_defaultMaterialAsset.GetId(); bool materialWasGeneratedFromModel = defaultMaterialAssetId.IsValid() && defaultMaterialAssetId.m_guid == modelAssetId.m_guid; if (materialWasGeneratedFromModel) { @@ -467,7 +456,7 @@ namespace AZ // exported material file name will be based on the first relevant material slot's name. if (duplicateAssetIter == exportItems.end()) { - EditorMaterialComponentExporter::ExportItem exportItem{defaultMaterialAssetId, materialSlotPair.second.m_displayName.GetStringView()}; + EditorMaterialComponentExporter::ExportItem exportItem{defaultMaterialAssetId, materialSlotPair.second->GetLabel()}; exportItems.push_back(exportItem); } } @@ -499,16 +488,10 @@ namespace AZ if (editorMaterialSlot) { - // Only update the slot of it was originally empty, having no override material. - // We need to check whether replaced material corresponds to this slot's default material. - if (!editorMaterialSlot->m_materialAsset.GetId().IsValid()) + if (!editorMaterialSlot->m_materialAsset.GetId().IsValid() && //< Only update the slot of it was originally empty, having no override material. + editorMaterialSlot->m_defaultMaterialAsset.GetId() == exportItem.GetOriginalAssetId()) //< We need to check whether replaced material corresponds to this slot's default material. { - auto materialSlot = modelMaterialSlots.find(editorMaterialSlot->m_id.m_materialSlotStableId); - if (materialSlot != modelMaterialSlots.end() && - materialSlot->second.m_defaultMaterialAsset.GetId() == exportItem.GetOriginalAssetId()) - { - editorMaterialSlot->m_materialAsset.Create(assetIdOutcome.GetValue()); - } + editorMaterialSlot->m_materialAsset.Create(assetIdOutcome.GetValue()); } } } From 3daf3f7d7ae71d5d98ba6ce0fe7cc4be28e542e8 Mon Sep 17 00:00:00 2001 From: Chris Santora Date: Tue, 20 Jul 2021 12:16:12 -0700 Subject: [PATCH 125/160] Fixed an issue with Actors where the material slot IDs were incorrect, and caused the displayed slot labels to be all "" (and likely other issues). Signed-off-by: santorac <55155825+santorac@users.noreply.github.com> --- .../Feature/SkinnedMesh/SkinnedMeshInputBuffers.h | 2 +- .../Source/SkinnedMesh/SkinnedMeshInputBuffers.cpp | 7 +------ .../EMotionFXAtom/Code/Source/ActorAsset.cpp | 5 +++-- .../EMotionFXAtom/Code/Source/AtomActorInstance.cpp | 12 +++++++----- 4 files changed, 12 insertions(+), 14 deletions(-) diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/SkinnedMesh/SkinnedMeshInputBuffers.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/SkinnedMesh/SkinnedMeshInputBuffers.h index 5d333e070e..c52bed8cf2 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/SkinnedMesh/SkinnedMeshInputBuffers.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/SkinnedMesh/SkinnedMeshInputBuffers.h @@ -45,7 +45,7 @@ namespace AZ uint32_t m_vertexOffset = 0; uint32_t m_vertexCount = 0; Aabb m_aabb = Aabb::CreateNull(); - Data::Asset m_material; + AZ::RPI::ModelMaterialSlot m_materialSlot; }; //! Buffer views for a specific sub-mesh that are not modified during skinning and thus are shared by all instances of the same skinned mesh diff --git a/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshInputBuffers.cpp b/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshInputBuffers.cpp index 640e30d0f6..afd215b4bc 100644 --- a/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshInputBuffers.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshInputBuffers.cpp @@ -640,12 +640,7 @@ namespace AZ Aabb localAabb = lod.m_subMeshProperties[i].m_aabb; modelLodCreator.SetMeshAabb(AZStd::move(localAabb)); - // Create a separate material slot for each sub-mesh - AZ::RPI::ModelMaterialSlot materialSlot; - materialSlot.m_stableId = i; - materialSlot.m_defaultMaterialAsset = lod.m_subMeshProperties[i].m_material; - - modelLodCreator.SetMeshMaterialSlot(materialSlot); + modelLodCreator.SetMeshMaterialSlot(lod.m_subMeshProperties[i].m_materialSlot); modelLodCreator.EndMesh(); } diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/ActorAsset.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/ActorAsset.cpp index ae617f910f..415f0d1ce3 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/ActorAsset.cpp +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/ActorAsset.cpp @@ -96,9 +96,10 @@ namespace AZ skinnedSubMesh.m_vertexCount = aznumeric_cast(subMeshVertexCount); lodVertexCount += aznumeric_cast(subMeshVertexCount); - skinnedSubMesh.m_material = lodAsset->GetMaterialSlot(modelMesh.GetMaterialSlotIndex()).m_defaultMaterialAsset; + skinnedSubMesh.m_materialSlot = lodAsset->GetMaterialSlot(modelMesh.GetMaterialSlotIndex()); + // Queue the material asset - the ModelLod seems to handle delayed material loads - skinnedSubMesh.m_material.QueueLoad(); + skinnedSubMesh.m_materialSlot.m_defaultMaterialAsset.QueueLoad(); subMeshes.push_back(skinnedSubMesh); } diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp index 6697162c18..f77e8d6bbd 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp @@ -503,16 +503,18 @@ namespace AZ const AZStd::vector< SkinnedSubMeshProperties>& subMeshProperties = inputLod.GetSubMeshProperties(); for (const SkinnedSubMeshProperties& submesh : subMeshProperties) { - AZ_Error("AtomActorInstance", submesh.m_material, "Actor does not have a valid default material in lod %d", lodIndex); - if (submesh.m_material) + Data::Asset materialAsset = submesh.m_materialSlot.m_defaultMaterialAsset; + AZ_Error("AtomActorInstance", materialAsset, "Actor does not have a valid default material in lod %d", lodIndex); + + if (materialAsset) { - if (!submesh.m_material->IsReady()) + if (!materialAsset->IsReady()) { // Start listening for the material's OnAssetReady event. // AtomActorInstance::Create is called on the main thread, so there should be no need to synchronize with the OnAssetReady event handler // since those events will also come from the main thread - m_waitForMaterialLoadIds.insert(submesh.m_material->GetId()); - Data::AssetBus::MultiHandler::BusConnect(submesh.m_material->GetId()); + m_waitForMaterialLoadIds.insert(materialAsset->GetId()); + Data::AssetBus::MultiHandler::BusConnect(materialAsset->GetId()); } } } From a71ee7eb3a3c2e3b2f4d9defa80505eb6196ed4c Mon Sep 17 00:00:00 2001 From: Chris Santora Date: Tue, 20 Jul 2021 13:43:24 -0700 Subject: [PATCH 126/160] Fixed the MaterialAssignmentId version converter to properly handle the default material assignment slot. Signed-off-by: santorac <55155825+santorac@users.noreply.github.com> --- .../Common/Code/Source/Material/MaterialAssignmentId.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Gems/Atom/Feature/Common/Code/Source/Material/MaterialAssignmentId.cpp b/Gems/Atom/Feature/Common/Code/Source/Material/MaterialAssignmentId.cpp index 5db6c4c15c..b8a03af6d1 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Material/MaterialAssignmentId.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Material/MaterialAssignmentId.cpp @@ -33,7 +33,14 @@ namespace AZ // No need to early-return, the object will still load successfully, it will just report more errors about the unrecognized element. } - classElement.AddElementWithData(context, "materialSlotStableId", materialAssetId.m_subId); + if (materialAssetId.IsValid()) + { + classElement.AddElementWithData(context, "materialSlotStableId", materialAssetId.m_subId); + } + else + { + classElement.AddElementWithData(context, "materialSlotStableId", RPI::ModelMaterialSlot::InvalidStableId); + } } return true; From fec79a7d53a0753dbd3d68a403ee9ea98a4ab172 Mon Sep 17 00:00:00 2001 From: Chris Santora Date: Tue, 20 Jul 2021 16:23:56 -0700 Subject: [PATCH 127/160] Moved the material slot list from ModelLodAsset to ModelAsset, so all the slots live in one main list. This removes data duplication between LODs and cleans up the code a bit. I had to update the ModelLod class to take in both the ModelLodAsset and ModelAsset for initialization so it can fetch the slots for each mesh. Signed-off-by: santorac <55155825+santorac@users.noreply.github.com> --- .../SkinnedMesh/SkinnedMeshInputBuffers.cpp | 5 ++- .../Include/Atom/RPI.Public/Model/Model.h | 4 +- .../Include/Atom/RPI.Public/Model/ModelLod.h | 7 +-- .../Atom/RPI.Reflect/Model/ModelAsset.h | 12 ++++- .../RPI.Reflect/Model/ModelAssetCreator.h | 4 ++ .../Atom/RPI.Reflect/Model/ModelLodAsset.h | 29 +++--------- .../RPI.Reflect/Model/ModelLodAssetCreator.h | 5 +-- .../Model/MaterialAssetBuilderComponent.cpp | 2 +- .../Model/ModelAssetBuilderComponent.cpp | 13 +++--- .../Model/ModelAssetBuilderComponent.h | 1 + .../Code/Source/RPI.Public/Model/Model.cpp | 12 ++--- .../Code/Source/RPI.Public/Model/ModelLod.cpp | 20 ++++++--- .../Source/RPI.Public/Model/ModelSystem.cpp | 6 +-- .../Source/RPI.Reflect/Model/ModelAsset.cpp | 34 +++++++------- .../RPI.Reflect/Model/ModelAssetCreator.cpp | 27 ++++++++++++ .../RPI.Reflect/Model/ModelLodAsset.cpp | 44 ++----------------- .../Model/ModelLodAssetCreator.cpp | 29 +++--------- .../Source/Mesh/MeshComponentController.cpp | 2 +- .../EMotionFXAtom/Code/Source/ActorAsset.cpp | 2 +- .../Code/Source/AtomActorInstance.cpp | 2 +- .../Rendering/Atom/WhiteBoxAtomRenderMesh.cpp | 30 +++++++------ .../Rendering/Atom/WhiteBoxAtomRenderMesh.h | 1 + 22 files changed, 134 insertions(+), 157 deletions(-) diff --git a/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshInputBuffers.cpp b/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshInputBuffers.cpp index afd215b4bc..de2c52d1c8 100644 --- a/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshInputBuffers.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshInputBuffers.cpp @@ -639,8 +639,9 @@ namespace AZ Aabb localAabb = lod.m_subMeshProperties[i].m_aabb; modelLodCreator.SetMeshAabb(AZStd::move(localAabb)); - - modelLodCreator.SetMeshMaterialSlot(lod.m_subMeshProperties[i].m_materialSlot); + + modelCreator.AddMaterialSlot(lod.m_subMeshProperties[i].m_materialSlot); + modelLodCreator.SetMeshMaterialSlot(lod.m_subMeshProperties[i].m_materialSlot.m_stableId); modelLodCreator.EndMesh(); } diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Model/Model.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Model/Model.h index 32880a221c..a19c985f2d 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Model/Model.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Model/Model.h @@ -90,8 +90,8 @@ namespace AZ private: Model() = default; - static Data::Instance CreateInternal(ModelAsset& modelAsset); - RHI::ResultCode Init(ModelAsset& modelAsset); + static Data::Instance CreateInternal(const Data::Asset& modelAsset); + RHI::ResultCode Init(const Data::Asset& modelAsset); AZStd::fixed_vector, ModelLodAsset::LodCountMax> m_lods; Data::Asset m_modelAsset; diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Model/ModelLod.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Model/ModelLod.h index 36892d0027..0d0304a04e 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Model/ModelLod.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Model/ModelLod.h @@ -18,6 +18,7 @@ #include #include +#include #include #include @@ -84,7 +85,7 @@ namespace AZ AZ_INSTANCE_DATA(ModelLod, "{3C796FC9-2067-4E0F-A660-269F8254D1D5}"); AZ_CLASS_ALLOCATOR(ModelLod, AZ::SystemAllocator, 0); - static Data::Instance FindOrCreate(const Data::Asset& lodAsset); + static Data::Instance FindOrCreate(const Data::Asset& lodAsset, const Data::Asset& modelAsset); ~ModelLod() = default; @@ -124,8 +125,8 @@ namespace AZ private: ModelLod() = default; - static Data::Instance CreateInternal(ModelLodAsset& lodAsset); - RHI::ResultCode Init(ModelLodAsset& lodAsset); + static Data::Instance CreateInternal(const Data::Asset& lodAsset, const AZStd::any* modelAssetAny); + RHI::ResultCode Init(const Data::Asset& lodAsset, const Data::Asset& modelAsset); bool SetMeshInstanceData( const ModelLodAsset::Mesh::StreamBufferInfo& streamBufferInfo, diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Model/ModelAsset.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Model/ModelAsset.h index 891aec04b3..dbcfc69d56 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Model/ModelAsset.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Model/ModelAsset.h @@ -51,7 +51,10 @@ namespace AZ const AZ::Aabb& GetAabb() const; //! Returns the list of all ModelMaterialSlot's for the model, across all LODs. - RPI::ModelMaterialSlotMap GetModelMaterialSlots() const; + const ModelMaterialSlotMap& GetMaterialSlots() const; + + //! Find a material slot with the given stableId, or returns an invalid slot if it isn't found. + const ModelMaterialSlot& FindMaterialSlot(uint32_t stableId) const; //! Returns the number of Lods in the model size_t GetLodCount() const; @@ -100,6 +103,13 @@ namespace AZ volatile mutable bool m_isKdTreeCalculationRunning = false; mutable AZStd::mutex m_kdTreeLock; mutable AZStd::optional m_modelTriangleCount; + + // Lists all of the material slots that are used by this LOD. + // Note the same slot can appear in multiple LODs in the model, so that LODs don't have to refer back to the model asset. + ModelMaterialSlotMap m_materialSlots; + + // A default ModelMaterialSlot to be returned upon error conditions. + ModelMaterialSlot m_fallbackSlot; AZStd::size_t CalculateTriangleCount() const; }; diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Model/ModelAssetCreator.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Model/ModelAssetCreator.h index 0b8cb678dc..d87ae1c57e 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Model/ModelAssetCreator.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Model/ModelAssetCreator.h @@ -29,6 +29,10 @@ namespace AZ //! Assigns a name to the model void SetName(AZStd::string_view name); + + //! Adds a new material slot to the asset. + //! If a slot with the same stable ID already exists, it will be replaced. + void AddMaterialSlot(const ModelMaterialSlot& materialSlot); //! Adds a Lod to the model. void AddLodAsset(Data::Asset&& lodAsset); diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Model/ModelLodAsset.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Model/ModelLodAsset.h index 61e2ebeb05..8c8edddfe1 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Model/ModelLodAsset.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Model/ModelLodAsset.h @@ -85,9 +85,9 @@ namespace AZ //! Returns the number of indices in this mesh uint32_t GetIndexCount() const; - //! Returns the index of the material slot used by this mesh. - //! This indexes into the ModelLodAsset's material slot list. - size_t GetMaterialSlotIndex() const; + //! Returns the ID of the material slot used by this mesh. + //! This maps into the ModelAsset's material slot list. + ModelMaterialSlot::StableId GetMaterialSlotId() const; //! Returns the name of this mesh const AZ::Name& GetName() const; @@ -126,9 +126,9 @@ namespace AZ AZ::Name m_name; AZ::Aabb m_aabb = AZ::Aabb::CreateNull(); - // Identifies the material that is used by this mesh. - // References material slot in the ModelLodAsset that owns this mesh; see ModelLodAsset::GetMaterialSlot(). - size_t m_materialSlotIndex = 0; + // Identifies the material slot that is used by this mesh. + // References material slot in the ModelAsset that owns this mesh; see ModelAsset::FindMaterialSlot(). + ModelMaterialSlot::StableId m_materialSlotId = ModelMaterialSlot::InvalidStableId; // Both the buffer in m_indexBufferAssetView and the buffers in m_streamBufferInfo // may point to either unique buffers for the mesh or to consolidated @@ -147,16 +147,6 @@ namespace AZ //! Returns the model-space axis-aligned bounding box of all meshes in the lod const AZ::Aabb& GetAabb() const; - - //! Returns an array view into the collection of material slots available to this lod - AZStd::array_view GetMaterialSlots() const; - - //! Returns a specific material slot by index, with error checking. - //! The index can be retrieved from Mesh::GetMaterialSlotIndex(). - const ModelMaterialSlot& GetMaterialSlot(size_t slotIndex) const; - - //! Find a material slot with the given stableId, or returns null if it isn't found. - const ModelMaterialSlot* FindMaterialSlot(uint32_t stableId) const; private: AZStd::vector m_meshes; @@ -169,13 +159,6 @@ namespace AZ Data::Asset m_indexBuffer; AZStd::vector> m_streamBuffers; - // Lists all of the material slots that are used by this LOD. - // Note the same slot can appear in multiple LODs in the model, so that LODs don't have to refer back to the model asset. - AZStd::vector m_materialSlots; - - // A default ModelMaterialSlot to be returned upon error conditions. - ModelMaterialSlot m_fallbackSlot; - void AddMesh(const Mesh& mesh); void SetReady(); diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Model/ModelLodAssetCreator.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Model/ModelLodAssetCreator.h index 5672b49f68..776347cb2b 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Model/ModelLodAssetCreator.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Model/ModelLodAssetCreator.h @@ -46,10 +46,9 @@ namespace AZ //! Begin and BeginMesh must be called first. void SetMeshAabb(AZ::Aabb&& aabb); - //! Sets the material slot data for the current SubMesh. - //! Adds a new material slot to the ModelLodAsset if it doesn't already exist. + //! Sets the ID of the model's material slot that this mesh uses. //! Begin and BeginMesh must be called first - void SetMeshMaterialSlot(const ModelMaterialSlot& materialSlot); + void SetMeshMaterialSlot(ModelMaterialSlot::StableId id); //! Sets the given BufferAssetView to the current SubMesh as the index buffer. //! Begin and BeginMesh must be called first diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/MaterialAssetBuilderComponent.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/MaterialAssetBuilderComponent.cpp index c55eb947a1..7187cb391a 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/MaterialAssetBuilderComponent.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/MaterialAssetBuilderComponent.cpp @@ -91,7 +91,7 @@ namespace AZ if (auto* serialize = azrtti_cast(context)) { serialize->Class() - ->Version(14); // [ATOM-13410] + ->Version(16); // Optional material conversion } } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/ModelAssetBuilderComponent.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/ModelAssetBuilderComponent.cpp index 608ee17d95..7100b2cd48 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/ModelAssetBuilderComponent.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/ModelAssetBuilderComponent.cpp @@ -367,6 +367,9 @@ namespace AZ MorphTargetMetaAssetCreator morphTargetMetaCreator; morphTargetMetaCreator.Begin(MorphTargetMetaAsset::ConstructAssetId(modelAssetId, modelAssetName)); + + ModelAssetCreator modelAssetCreator; + modelAssetCreator.Begin(modelAssetId); uint32_t lodIndex = 0; for (const SourceMeshContentList& sourceMeshContentList : sourceMeshContentListsByLod) @@ -429,7 +432,7 @@ namespace AZ for (const ProductMeshView& meshView : lodMeshViews) { - if (!CreateMesh(meshView, indexBuffer, streamBuffers, lodAssetCreator, context.m_materialsByUid)) + if (!CreateMesh(meshView, indexBuffer, streamBuffers, modelAssetCreator, lodAssetCreator, context.m_materialsByUid)) { return AZ::SceneAPI::Events::ProcessingResult::Failure; } @@ -469,10 +472,6 @@ namespace AZ } sourceMeshContentListsByLod.clear(); - // Build the final asset structure - ModelAssetCreator modelAssetCreator; - modelAssetCreator.Begin(modelAssetId); - // Finalize all LOD assets for (auto& lodAsset : lodAssets) { @@ -1796,6 +1795,7 @@ namespace AZ const ProductMeshView& meshView, const BufferAssetView& lodIndexBuffer, const AZStd::vector& lodStreamBuffers, + ModelAssetCreator& modelAssetCreator, ModelLodAssetCreator& lodAssetCreator, const MaterialAssetsByUid& materialAssetsByUid) { @@ -1811,7 +1811,8 @@ namespace AZ materialSlot.m_displayName = iter->second.m_name; materialSlot.m_defaultMaterialAsset = iter->second.m_asset; - lodAssetCreator.SetMeshMaterialSlot(materialSlot); + modelAssetCreator.AddMaterialSlot(materialSlot); + lodAssetCreator.SetMeshMaterialSlot(materialSlot.m_stableId); } } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/ModelAssetBuilderComponent.h b/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/ModelAssetBuilderComponent.h index 79dec962df..832a8700ba 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/ModelAssetBuilderComponent.h +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/ModelAssetBuilderComponent.h @@ -294,6 +294,7 @@ namespace AZ const ProductMeshView& meshView, const BufferAssetView& lodIndexBuffer, const AZStd::vector& lodStreamBuffers, + ModelAssetCreator& modelAssetCreator, ModelLodAssetCreator& lodAssetCreator, const MaterialAssetsByUid& materialAssetsByUid); diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Model/Model.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Model/Model.cpp index e684c4832a..32fe297c57 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Model/Model.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Model/Model.cpp @@ -40,7 +40,7 @@ namespace AZ return m_lods; } - Data::Instance Model::CreateInternal(ModelAsset& modelAsset) + Data::Instance Model::CreateInternal(const Data::Asset& modelAsset) { AZ_PROFILE_FUNCTION(Debug::ProfileCategory::AzRender); Data::Instance model = aznew Model(); @@ -54,15 +54,15 @@ namespace AZ return nullptr; } - RHI::ResultCode Model::Init(ModelAsset& modelAsset) + RHI::ResultCode Model::Init(const Data::Asset& modelAsset) { AZ_PROFILE_FUNCTION(Debug::ProfileCategory::AzRender); - m_lods.resize(modelAsset.GetLodAssets().size()); + m_lods.resize(modelAsset->GetLodAssets().size()); for (size_t lodIndex = 0; lodIndex < m_lods.size(); ++lodIndex) { - const Data::Asset& lodAsset = modelAsset.GetLodAssets()[lodIndex]; + const Data::Asset& lodAsset = modelAsset->GetLodAssets()[lodIndex]; if (!lodAsset) { @@ -70,7 +70,7 @@ namespace AZ return RHI::ResultCode::Fail; } - Data::Instance lodInstance = ModelLod::FindOrCreate(lodAsset); + Data::Instance lodInstance = ModelLod::FindOrCreate(lodAsset, modelAsset); if (lodInstance == nullptr) { return RHI::ResultCode::Fail; @@ -98,7 +98,7 @@ namespace AZ m_lods[lodIndex] = AZStd::move(lodInstance); } - m_modelAsset = { &modelAsset, AZ::Data::AssetLoadBehavior::PreLoad }; + m_modelAsset = modelAsset; m_isUploadPending = true; return RHI::ResultCode::Success; } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Model/ModelLod.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Model/ModelLod.cpp index 2dfee9e2f1..dc39200a65 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Model/ModelLod.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Model/ModelLod.cpp @@ -19,11 +19,14 @@ namespace AZ { namespace RPI { - Data::Instance ModelLod::FindOrCreate(const Data::Asset& lodAsset) + Data::Instance ModelLod::FindOrCreate(const Data::Asset& lodAsset, const Data::Asset& modelAsset) { + AZStd::any modelAssetAny{&modelAsset}; + return Data::InstanceDatabase::Instance().FindOrCreate( Data::InstanceId::CreateFromAssetId(lodAsset.GetId()), - lodAsset); + lodAsset, + &modelAssetAny); } AZStd::array_view ModelLod::GetMeshes() const @@ -31,10 +34,13 @@ namespace AZ return m_meshes; } - Data::Instance ModelLod::CreateInternal(ModelLodAsset& lodAsset) + Data::Instance ModelLod::CreateInternal(const Data::Asset& lodAsset, const AZStd::any* modelAssetAny) { + AZ_Assert(modelAssetAny != nullptr, "Invalid model asset param"); + auto modelAsset = AZStd::any_cast*>(*modelAssetAny); + Data::Instance lod = aznew ModelLod(); - const RHI::ResultCode resultCode = lod->Init(lodAsset); + const RHI::ResultCode resultCode = lod->Init(lodAsset, *modelAsset); if (resultCode == RHI::ResultCode::Success) { @@ -44,11 +50,11 @@ namespace AZ return nullptr; } - RHI::ResultCode ModelLod::Init(ModelLodAsset& lodAsset) + RHI::ResultCode ModelLod::Init(const Data::Asset& lodAsset, const Data::Asset& modelAsset) { AZ_TRACE_METHOD(); - for (const ModelLodAsset::Mesh& mesh : lodAsset.GetMeshes()) + for (const ModelLodAsset::Mesh& mesh : lodAsset->GetMeshes()) { Mesh meshInstance; @@ -100,7 +106,7 @@ namespace AZ } } - const ModelMaterialSlot& materialSlot = lodAsset.GetMaterialSlot(mesh.GetMaterialSlotIndex()); + const ModelMaterialSlot& materialSlot = modelAsset->FindMaterialSlot(mesh.GetMaterialSlotId()); meshInstance.m_materialSlotStableId = materialSlot.m_stableId; diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Model/ModelSystem.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Model/ModelSystem.cpp index b9781843cf..1ed81f8e16 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Model/ModelSystem.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Model/ModelSystem.cpp @@ -41,9 +41,9 @@ namespace AZ { //Create Lod Database AZ::Data::InstanceHandler lodInstanceHandler; - lodInstanceHandler.m_createFunction = [](Data::AssetData* modelLodAsset) + lodInstanceHandler.m_createFunctionWithParam = [](Data::AssetData* modelLodAsset, const AZStd::any* modelAsset) { - return ModelLod::CreateInternal(*(azrtti_cast(modelLodAsset))); + return ModelLod::CreateInternal(Data::Asset{modelLodAsset, AZ::Data::AssetLoadBehavior::PreLoad}, modelAsset); }; Data::InstanceDatabase::Create(azrtti_typeid(), lodInstanceHandler); @@ -51,7 +51,7 @@ namespace AZ AZ::Data::InstanceHandler modelInstanceHandler; modelInstanceHandler.m_createFunction = [](Data::AssetData* modelAsset) { - return Model::CreateInternal(*(azrtti_cast(modelAsset))); + return Model::CreateInternal(Data::Asset{modelAsset, AZ::Data::AssetLoadBehavior::PreLoad}); }; Data::InstanceDatabase::Create(azrtti_typeid(), modelInstanceHandler); } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/ModelAsset.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/ModelAsset.cpp index 486faafbdb..275b056514 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/ModelAsset.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/ModelAsset.cpp @@ -29,9 +29,10 @@ namespace AZ if (auto* serializeContext = azrtti_cast(context)) { serializeContext->Class() - ->Version(0) + ->Version(1) ->Field("Name", &ModelAsset::m_name) ->Field("Aabb", &ModelAsset::m_aabb) + ->Field("MaterialSlots", &ModelAsset::m_materialSlots) ->Field("LodAssets", &ModelAsset::m_lodAssets) ; } @@ -57,28 +58,23 @@ namespace AZ return m_aabb; } - RPI::ModelMaterialSlotMap ModelAsset::GetModelMaterialSlots() const + const ModelMaterialSlotMap& ModelAsset::GetMaterialSlots() const { - RPI::ModelMaterialSlotMap slotMap; + return m_materialSlots; + } - for (const Data::Asset& lod : GetLodAssets()) + const ModelMaterialSlot& ModelAsset::FindMaterialSlot(uint32_t stableId) const + { + auto iter = m_materialSlots.find(stableId); + + if (iter == m_materialSlots.end()) { - for (const AZ::RPI::ModelMaterialSlot& materialSlot : lod->GetMaterialSlots()) - { - auto iter = slotMap.find(materialSlot.m_stableId); - if (iter == slotMap.end()) - { - slotMap.emplace(materialSlot.m_stableId, materialSlot); - } - else - { - AZ_Assert(materialSlot.m_displayName == iter->second.m_displayName && materialSlot.m_defaultMaterialAsset.GetId() == iter->second.m_defaultMaterialAsset.GetId(), - "Multiple LODs have mismatched data for the same material slot."); - } - } + return m_fallbackSlot; + } + else + { + return iter->second; } - - return slotMap; } size_t ModelAsset::GetLodCount() const diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/ModelAssetCreator.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/ModelAssetCreator.cpp index 0c7a12fa8b..b35c9e44fe 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/ModelAssetCreator.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/ModelAssetCreator.cpp @@ -29,6 +29,33 @@ namespace AZ m_asset->m_name = name; } } + + void ModelAssetCreator::AddMaterialSlot(const ModelMaterialSlot& materialSlot) + { + if (ValidateIsReady()) + { + auto iter = m_asset->m_materialSlots.find(materialSlot.m_stableId); + + if (iter == m_asset->m_materialSlots.end()) + { + m_asset->m_materialSlots[materialSlot.m_stableId] = materialSlot; + } + else + { + if (materialSlot.m_displayName != iter->second.m_displayName) + { + ReportWarning("Material slot %u was already added with a different name.", materialSlot.m_stableId); + } + + if (materialSlot.m_defaultMaterialAsset != iter->second.m_defaultMaterialAsset) + { + ReportWarning("Material slot %u was already added with a different default MaterialAsset.", materialSlot.m_stableId); + } + + iter->second = materialSlot; + } + } + } void ModelAssetCreator::AddLodAsset(Data::Asset&& lodAsset) { diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/ModelLodAsset.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/ModelLodAsset.cpp index 4811f6a1db..ccf0d49b46 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/ModelLodAsset.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/ModelLodAsset.cpp @@ -23,10 +23,9 @@ namespace AZ if (auto* serializeContext = azrtti_cast(context)) { serializeContext->Class() - ->Version(1) + ->Version(0) ->Field("Meshes", &ModelLodAsset::m_meshes) ->Field("Aabb", &ModelLodAsset::m_aabb) - ->Field("MaterialSlots", &ModelLodAsset::m_materialSlots) ; } @@ -41,7 +40,7 @@ namespace AZ ->Version(1) ->Field("Name", &ModelLodAsset::Mesh::m_name) ->Field("AABB", &ModelLodAsset::Mesh::m_aabb) - ->Field("MaterialSlotIndex", &ModelLodAsset::Mesh::m_materialSlotIndex) + ->Field("MaterialSlotId", &ModelLodAsset::Mesh::m_materialSlotId) ->Field("IndexBufferAssetView", &ModelLodAsset::Mesh::m_indexBufferAssetView) ->Field("StreamBufferInfo", &ModelLodAsset::Mesh::m_streamBufferInfo) ; @@ -76,9 +75,9 @@ namespace AZ return m_indexBufferAssetView.GetBufferViewDescriptor().m_elementCount; } - size_t ModelLodAsset::Mesh::GetMaterialSlotIndex() const + ModelMaterialSlot::StableId ModelLodAsset::Mesh::GetMaterialSlotId() const { - return m_materialSlotIndex; + return m_materialSlotId; } const AZ::Name& ModelLodAsset::Mesh::GetName() const @@ -120,41 +119,6 @@ namespace AZ return m_aabb; } - AZStd::array_view ModelLodAsset::GetMaterialSlots() const - { - return m_materialSlots; - } - - const ModelMaterialSlot& ModelLodAsset::GetMaterialSlot(size_t slotIndex) const - { - if (slotIndex < m_materialSlots.size()) - { - return m_materialSlots[slotIndex]; - } - else - { - AZ_Error("ModelAsset", false, "Material slot index %zu out of range. ModelAsset has %zu slots.", slotIndex, m_materialSlots.size()); - return m_fallbackSlot; - } - } - - const ModelMaterialSlot* ModelLodAsset::FindMaterialSlot(uint32_t stableId) const - { - auto iter = AZStd::find_if(m_materialSlots.begin(), m_materialSlots.end(), [&stableId](const ModelMaterialSlot& existingMaterialSlot) - { - return existingMaterialSlot.m_stableId == stableId; - }); - - if (iter == m_materialSlots.end()) - { - return nullptr; - } - else - { - return iter; - } - } - const BufferAssetView* ModelLodAsset::Mesh::GetSemanticBufferAssetView(const AZ::Name& semantic) const { const AZStd::array_view& streamBufferList = GetStreamBufferInfoList(); diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/ModelLodAssetCreator.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/ModelLodAssetCreator.cpp index 5a066d2517..f94116db70 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/ModelLodAssetCreator.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/ModelLodAssetCreator.cpp @@ -61,32 +61,14 @@ namespace AZ } } - void ModelLodAssetCreator::SetMeshMaterialSlot(const ModelMaterialSlot& materialSlot) + void ModelLodAssetCreator::SetMeshMaterialSlot(ModelMaterialSlot::StableId id) { - auto iter = AZStd::find_if(m_asset->m_materialSlots.begin(), m_asset->m_materialSlots.end(), [&materialSlot](const ModelMaterialSlot& existingMaterialSlot) - { - return existingMaterialSlot.m_stableId == materialSlot.m_stableId; - }); - - if (iter == m_asset->m_materialSlots.end()) + if (!ValidateIsMeshReady()) { - m_currentMesh.m_materialSlotIndex = m_asset->m_materialSlots.size(); - m_asset->m_materialSlots.push_back(materialSlot); + return; } - else - { - if (materialSlot.m_displayName != iter->m_displayName) - { - ReportWarning("Material slot %u was already added with a different name.", materialSlot.m_stableId); - } - if (materialSlot.m_defaultMaterialAsset != iter->m_defaultMaterialAsset) - { - ReportWarning("Material slot %u was already added with a different MaterialAsset.", materialSlot.m_stableId); - } - - *iter = materialSlot; - } + m_currentMesh.m_materialSlotId = id; } void ModelLodAssetCreator::SetMeshIndexBuffer(const BufferAssetView& bufferAssetView) @@ -309,8 +291,7 @@ namespace AZ AZ::Aabb aabb = sourceMesh.GetAabb(); creator.SetMeshAabb(AZStd::move(aabb)); - const ModelMaterialSlot& materialSlot = sourceAsset->GetMaterialSlot(sourceMesh.GetMaterialSlotIndex()); - creator.SetMeshMaterialSlot(materialSlot); + creator.SetMeshMaterialSlot(sourceMesh.GetMaterialSlotId()); // Mesh index buffer view const BufferAssetView& sourceIndexBufferView = sourceMesh.GetIndexBufferAssetView(); diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp index a2a3022e91..2f4a649c30 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp @@ -257,7 +257,7 @@ namespace AZ Data::Asset modelAsset = GetModelAsset(); if (modelAsset.IsReady()) { - return modelAsset->GetModelMaterialSlots(); + return modelAsset->GetMaterialSlots(); } else { diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/ActorAsset.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/ActorAsset.cpp index 415f0d1ce3..feabdb9510 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/ActorAsset.cpp +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/ActorAsset.cpp @@ -96,7 +96,7 @@ namespace AZ skinnedSubMesh.m_vertexCount = aznumeric_cast(subMeshVertexCount); lodVertexCount += aznumeric_cast(subMeshVertexCount); - skinnedSubMesh.m_materialSlot = lodAsset->GetMaterialSlot(modelMesh.GetMaterialSlotIndex()); + skinnedSubMesh.m_materialSlot = actor->GetMeshAsset()->FindMaterialSlot(modelMesh.GetMaterialSlotId()); // Queue the material asset - the ModelLod seems to handle delayed material loads skinnedSubMesh.m_materialSlot.m_defaultMaterialAsset.QueueLoad(); diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp index f77e8d6bbd..062e39b844 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp @@ -313,7 +313,7 @@ namespace AZ Data::Asset modelAsset = GetModelAsset(); if (modelAsset.IsReady()) { - return modelAsset->GetModelMaterialSlots(); + return modelAsset->GetMaterialSlots(); } else { diff --git a/Gems/WhiteBox/Code/Source/Rendering/Atom/WhiteBoxAtomRenderMesh.cpp b/Gems/WhiteBox/Code/Source/Rendering/Atom/WhiteBoxAtomRenderMesh.cpp index 5a9b8191ed..daa0ad59f8 100644 --- a/Gems/WhiteBox/Code/Source/Rendering/Atom/WhiteBoxAtomRenderMesh.cpp +++ b/Gems/WhiteBox/Code/Source/Rendering/Atom/WhiteBoxAtomRenderMesh.cpp @@ -112,20 +112,8 @@ namespace WhiteBox AddLodBuffers(modelLodCreator); modelLodCreator.BeginMesh(); modelLodCreator.SetMeshAabb(meshData.GetAabb()); - - // set the default material - if (auto materialAsset = AZ::RPI::AssetUtils::LoadAssetByProductPath(TexturedMaterialPath.data())) - { - AZ::RPI::ModelMaterialSlot materialSlot; - materialSlot.m_stableId = 0; - materialSlot.m_defaultMaterialAsset = materialAsset; - modelLodCreator.SetMeshMaterialSlot(materialSlot); - } - else - { - AZ_Error("CreateLodAsset", false, "Could not load material."); - return false; - } + + modelLodCreator.SetMeshMaterialSlot(OneMaterialSlotId); AddMeshBuffers(modelLodCreator); modelLodCreator.EndMesh(); @@ -157,6 +145,20 @@ namespace WhiteBox modelCreator.Begin(AZ::Data::AssetId(AZ::Uuid::CreateRandom())); modelCreator.SetName(ModelName); modelCreator.AddLodAsset(AZStd::move(m_lodAsset)); + + if (auto materialAsset = AZ::RPI::AssetUtils::LoadAssetByProductPath(TexturedMaterialPath.data())) + { + AZ::RPI::ModelMaterialSlot materialSlot; + materialSlot.m_stableId = OneMaterialSlotId; + materialSlot.m_defaultMaterialAsset = materialAsset; + modelCreator.AddMaterialSlot(materialSlot); + } + else + { + AZ_Error("CreateLodAsset", false, "Could not load material."); + return; + } + modelCreator.End(m_modelAsset); } diff --git a/Gems/WhiteBox/Code/Source/Rendering/Atom/WhiteBoxAtomRenderMesh.h b/Gems/WhiteBox/Code/Source/Rendering/Atom/WhiteBoxAtomRenderMesh.h index 00179f196d..63aca62051 100644 --- a/Gems/WhiteBox/Code/Source/Rendering/Atom/WhiteBoxAtomRenderMesh.h +++ b/Gems/WhiteBox/Code/Source/Rendering/Atom/WhiteBoxAtomRenderMesh.h @@ -91,6 +91,7 @@ namespace WhiteBox // TODO: LYN-784 static constexpr AZStd::string_view TexturedMaterialPath = "materials/defaultpbr.azmaterial"; static constexpr AZStd::string_view SolidMaterialPath = "materials/defaultpbr.azmaterial"; + static constexpr AZ::RPI::ModelMaterialSlot::StableId OneMaterialSlotId = 0; //! White box model name. static constexpr AZStd::string_view ModelName = "WhiteBoxMesh"; From 75b4d62dcb2ae68d5900e5d5d9c07d5269e5a246 Mon Sep 17 00:00:00 2001 From: Chris Santora Date: Tue, 20 Jul 2021 16:59:25 -0700 Subject: [PATCH 128/160] Restored the version converter EditorMaterialComponent::ConvertVersion for version 3, which wasn't possible with an earlier version of my changes. Signed-off-by: santorac <55155825+santorac@users.noreply.github.com> --- .../Material/EditorMaterialComponent.cpp | 53 ++++++++++++++++++- 1 file changed, 51 insertions(+), 2 deletions(-) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.cpp index 866b2dec56..d2f8c1daa0 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.cpp @@ -45,8 +45,57 @@ namespace AZ if (classElement.GetVersion() < 3) { - AZ_Error("EditorMaterialComponent", false, "Material Component version < 3 is no longer supported"); - return false; + // The default material was changed from an asset to an EditorMaterialComponentSlot and old data must be converted + constexpr AZ::u32 defaultMaterialAssetDataCrc = AZ_CRC("defaultMaterialAsset", 0x736fc071); + + Data::Asset oldDefaultMaterialData; + if (!classElement.GetChildData(defaultMaterialAssetDataCrc, oldDefaultMaterialData)) + { + AZ_Error("AZ::Render::EditorMaterialComponent::ConvertVersion", false, "Failed to get defaultMaterialAsset element"); + return false; + } + + if (!classElement.RemoveElementByName(defaultMaterialAssetDataCrc)) + { + AZ_Error("AZ::Render::EditorMaterialComponent::ConvertVersion", false, "Failed to remove defaultMaterialAsset element"); + return false; + } + + EditorMaterialComponentSlot newDefaultMaterialData; + newDefaultMaterialData.m_id = DefaultMaterialAssignmentId; + newDefaultMaterialData.m_materialAsset = oldDefaultMaterialData; + classElement.AddElementWithData(context, "defaultMaterialSlot", newDefaultMaterialData); + + // Slots now support and display the default material asset when empty + // The old placeholder assignments are irrelevant and must be cleared + constexpr AZ::u32 materialSlotsByLodDataCrc = AZ_CRC("materialSlotsByLod", 0xb1498db6); + + EditorMaterialComponentSlotsByLodContainer lodSlotData; + if (!classElement.GetChildData(materialSlotsByLodDataCrc, lodSlotData)) + { + AZ_Error("AZ::Render::EditorMaterialComponent::ConvertVersion", false, "Failed to get materialSlotsByLod element"); + return false; + } + + if (!classElement.RemoveElementByName(materialSlotsByLodDataCrc)) + { + AZ_Error("AZ::Render::EditorMaterialComponent::ConvertVersion", false, "Failed to remove materialSlotsByLod element"); + return false; + } + + // Find and clear all slots that are assigned to the slot's default value + for (auto& lodSlots : lodSlotData) + { + for (auto& slot : lodSlots) + { + if (slot.m_materialAsset.GetId() == slot.m_defaultMaterialAsset.GetId()) + { + slot.m_materialAsset = {}; + } + } + } + + classElement.AddElementWithData(context, "materialSlotsByLod", lodSlotData); } if (classElement.GetVersion() < 4) From abec7a4f5bcb69ba4450ae538c5f0c11291f1b4e Mon Sep 17 00:00:00 2001 From: Chris Santora Date: Wed, 21 Jul 2021 09:16:01 -0700 Subject: [PATCH 129/160] Fixed an issue where a default material should show up as a filled-in value in the UI even though it should appear as empty, indicating the default is being used. Also, I'm going back on what I said in my last commit, and removing the converter for version 3 in EditorMaterialComponent::ConvertVersion. The code that I had put in before wouldn't work because it was relying on the new m_defaultMaterialAsset which will be empty for old data. The only way we could support version conversion is if we preserve legacy versions of multiple types like EditorMaterialComponentSlot and MaterialAssignmentId. Since this serialization version is old and pre-dates the public release of O3DE, it's unlikely that we need to continue supporting this version so isn't worth maintaining. Signed-off-by: santorac <55155825+santorac@users.noreply.github.com> --- .../Material/EditorMaterialComponent.cpp | 62 +++---------------- 1 file changed, 9 insertions(+), 53 deletions(-) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.cpp index d2f8c1daa0..c7bd88219a 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.cpp @@ -45,64 +45,15 @@ namespace AZ if (classElement.GetVersion() < 3) { - // The default material was changed from an asset to an EditorMaterialComponentSlot and old data must be converted - constexpr AZ::u32 defaultMaterialAssetDataCrc = AZ_CRC("defaultMaterialAsset", 0x736fc071); - - Data::Asset oldDefaultMaterialData; - if (!classElement.GetChildData(defaultMaterialAssetDataCrc, oldDefaultMaterialData)) - { - AZ_Error("AZ::Render::EditorMaterialComponent::ConvertVersion", false, "Failed to get defaultMaterialAsset element"); - return false; - } - - if (!classElement.RemoveElementByName(defaultMaterialAssetDataCrc)) - { - AZ_Error("AZ::Render::EditorMaterialComponent::ConvertVersion", false, "Failed to remove defaultMaterialAsset element"); - return false; - } - - EditorMaterialComponentSlot newDefaultMaterialData; - newDefaultMaterialData.m_id = DefaultMaterialAssignmentId; - newDefaultMaterialData.m_materialAsset = oldDefaultMaterialData; - classElement.AddElementWithData(context, "defaultMaterialSlot", newDefaultMaterialData); - - // Slots now support and display the default material asset when empty - // The old placeholder assignments are irrelevant and must be cleared - constexpr AZ::u32 materialSlotsByLodDataCrc = AZ_CRC("materialSlotsByLod", 0xb1498db6); - - EditorMaterialComponentSlotsByLodContainer lodSlotData; - if (!classElement.GetChildData(materialSlotsByLodDataCrc, lodSlotData)) - { - AZ_Error("AZ::Render::EditorMaterialComponent::ConvertVersion", false, "Failed to get materialSlotsByLod element"); - return false; - } - - if (!classElement.RemoveElementByName(materialSlotsByLodDataCrc)) - { - AZ_Error("AZ::Render::EditorMaterialComponent::ConvertVersion", false, "Failed to remove materialSlotsByLod element"); - return false; - } - - // Find and clear all slots that are assigned to the slot's default value - for (auto& lodSlots : lodSlotData) - { - for (auto& slot : lodSlots) - { - if (slot.m_materialAsset.GetId() == slot.m_defaultMaterialAsset.GetId()) - { - slot.m_materialAsset = {}; - } - } - } - - classElement.AddElementWithData(context, "materialSlotsByLod", lodSlotData); + AZ_Error("EditorMaterialComponent", false, "Material Component version < 3 is no longer supported"); + return false; } if (classElement.GetVersion() < 4) { classElement.AddElementWithData(context, "materialSlotsByLodEnabled", true); } - + return true; } @@ -414,7 +365,11 @@ namespace AZ // if material is present in controller configuration, assign its data const MaterialAssignment& materialFromController = GetMaterialAssignmentFromMap(config.m_materials, slot.m_id); - slot.m_materialAsset = materialFromController.m_materialAsset; + if (materialFromController.m_materialAsset != slot.m_defaultMaterialAsset) // Prevents the default material from showing up as a filled-in value in the property field + { + slot.m_materialAsset = materialFromController.m_materialAsset; + } + slot.m_propertyOverrides = materialFromController.m_propertyOverrides; slot.m_matModUvOverrides = materialFromController.m_matModUvOverrides; @@ -629,3 +584,4 @@ namespace AZ } } // namespace Render } // namespace AZ + From 21d5baa1843099e573e7f7085f788e02880ab20c Mon Sep 17 00:00:00 2001 From: Chris Santora Date: Wed, 21 Jul 2021 11:28:24 -0700 Subject: [PATCH 130/160] Fixed an issue where I had changed prior functionality by mistake, preventing exported materials from replacing material assignments. Signed-off-by: santorac <55155825+santorac@users.noreply.github.com> --- .../Code/Source/Material/EditorMaterialComponent.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.cpp index c7bd88219a..7d0573c027 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.cpp @@ -492,8 +492,8 @@ namespace AZ if (editorMaterialSlot) { - if (!editorMaterialSlot->m_materialAsset.GetId().IsValid() && //< Only update the slot of it was originally empty, having no override material. - editorMaterialSlot->m_defaultMaterialAsset.GetId() == exportItem.GetOriginalAssetId()) //< We need to check whether replaced material corresponds to this slot's default material. + // We need to check whether replaced material corresponds to this slot's default material. + if (editorMaterialSlot->m_defaultMaterialAsset.GetId() == exportItem.GetOriginalAssetId()) { editorMaterialSlot->m_materialAsset.Create(assetIdOutcome.GetValue()); } From 6fa891848df9a82d5cc46d01d83b8c17771b3557 Mon Sep 17 00:00:00 2001 From: Chris Santora Date: Wed, 21 Jul 2021 23:52:40 -0700 Subject: [PATCH 131/160] Factored out redundant call to GetMaterialSlots(). Removed code that was intended to handle duplicate default material assignments, but duplicacate default material assignments aren't possible yet. Signed-off-by: santorac <55155825+santorac@users.noreply.github.com> --- .../Material/EditorMaterialComponent.cpp | 45 +++++++------------ 1 file changed, 16 insertions(+), 29 deletions(-) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.cpp index 7d0573c027..bc91e8adad 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.cpp @@ -365,7 +365,7 @@ namespace AZ // if material is present in controller configuration, assign its data const MaterialAssignment& materialFromController = GetMaterialAssignmentFromMap(config.m_materials, slot.m_id); - if (materialFromController.m_materialAsset != slot.m_defaultMaterialAsset) // Prevents the default material from showing up as a filled-in value in the property field + //if (materialFromController.m_materialAsset != slot.m_defaultMaterialAsset) // Prevents the default material from showing up as a filled-in value in the property field { slot.m_materialAsset = materialFromController.m_materialAsset; } @@ -438,40 +438,27 @@ namespace AZ Data::AssetId modelAssetId; MeshComponentRequestBus::EventResult(modelAssetId, GetEntityId(), &MeshComponentRequestBus::Events::GetModelAssetId); - EditorMaterialComponentExporter::ExportItemsContainer exportItems; + // First generating a unique set of all material asset IDs that will be used for source data generation + AZStd::unordered_map assetIdMap; - // Generate a list of export items for the set of unique default material assets from the model. - for (auto& materialSlotPair : GetMaterialSlots()) + auto materialSlots = GetMaterialSlots(); + for (auto& materialSlotPair : materialSlots) { - // We only care about material assets that were generated from the model source file, since those are the - // ones that would need conversion (other materials already have their own source file). This can be detected - // by matching GUID component of the AssetId. Data::AssetId defaultMaterialAssetId = materialSlotPair.second->m_defaultMaterialAsset.GetId(); - bool materialWasGeneratedFromModel = defaultMaterialAssetId.IsValid() && defaultMaterialAssetId.m_guid == modelAssetId.m_guid; - if (materialWasGeneratedFromModel) + if (defaultMaterialAssetId.IsValid()) { - auto duplicateAssetIter = AZStd::find_if(exportItems.begin(), exportItems.end(), - [defaultMaterialAssetId](const EditorMaterialComponentExporter::ExportItem& existingExportItem) - { - return existingExportItem.GetOriginalAssetId() == defaultMaterialAssetId; - }); - - // It's possible for multiple material slots to have the same default material asset. So we just use the first one, which just means the - // exported material file name will be based on the first relevant material slot's name. - if (duplicateAssetIter == exportItems.end()) - { - EditorMaterialComponentExporter::ExportItem exportItem{defaultMaterialAssetId, materialSlotPair.second->GetLabel()}; - exportItems.push_back(exportItem); - } + assetIdMap[defaultMaterialAssetId] = materialSlotPair.second->GetLabel(); } } - // Sort by display name so the list order will match what's displayed in the Material Component. - AZStd::sort(exportItems.begin(), exportItems.end(), - [](const EditorMaterialComponentExporter::ExportItem& a, const EditorMaterialComponentExporter::ExportItem& b) - { - return a.GetMaterialSlotName() < b.GetMaterialSlotName(); - }); + // Convert the unique set of asset IDs into export items that can be configured in the dialog + // The order should not matter because the table in the dialog can sort itself for a specific row + EditorMaterialComponentExporter::ExportItemsContainer exportItems; + for (auto assetIdInfo : assetIdMap) + { + EditorMaterialComponentExporter::ExportItem exportItem{assetIdInfo.first, assetIdInfo.second}; + exportItems.push_back(exportItem); + } // Display the export dialog so that the user can configure how they want different materials to be exported if (EditorMaterialComponentExporter::OpenExportDialog(exportItems)) @@ -486,7 +473,7 @@ namespace AZ const auto& assetIdOutcome = AZ::RPI::AssetUtils::MakeAssetId(exportItem.GetExportPath(), 0); if (assetIdOutcome) { - for (auto& materialSlotPair : GetMaterialSlots()) + for (auto& materialSlotPair : materialSlots) { EditorMaterialComponentSlot* editorMaterialSlot = materialSlotPair.second; From b19a89588948d0ccffe9385e53e8bfcec65da154 Mon Sep 17 00:00:00 2001 From: Chris Santora Date: Wed, 21 Jul 2021 23:54:37 -0700 Subject: [PATCH 132/160] Reverted accidentally commented out code. Signed-off-by: santorac <55155825+santorac@users.noreply.github.com> --- .../Code/Source/Material/EditorMaterialComponent.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.cpp index bc91e8adad..9f1d0d14d2 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.cpp @@ -365,7 +365,7 @@ namespace AZ // if material is present in controller configuration, assign its data const MaterialAssignment& materialFromController = GetMaterialAssignmentFromMap(config.m_materials, slot.m_id); - //if (materialFromController.m_materialAsset != slot.m_defaultMaterialAsset) // Prevents the default material from showing up as a filled-in value in the property field + if (materialFromController.m_materialAsset != slot.m_defaultMaterialAsset) // Prevents the default material from showing up as a filled-in value in the property field { slot.m_materialAsset = materialFromController.m_materialAsset; } From 1a478608a7fd74e98ac94070faf5ea288897da28 Mon Sep 17 00:00:00 2001 From: Chris Santora Date: Thu, 22 Jul 2021 16:11:35 -0700 Subject: [PATCH 133/160] Restored the previous behavior of preventing material property overrides when there is no explicit material override assignment. Signed-off-by: santorac <55155825+santorac@users.noreply.github.com> --- .../Code/Source/Material/EditorMaterialComponent.cpp | 8 +------- .../Code/Source/Material/EditorMaterialComponentSlot.cpp | 6 ++---- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.cpp index 9f1d0d14d2..a4e058561e 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.cpp @@ -365,10 +365,7 @@ namespace AZ // if material is present in controller configuration, assign its data const MaterialAssignment& materialFromController = GetMaterialAssignmentFromMap(config.m_materials, slot.m_id); - if (materialFromController.m_materialAsset != slot.m_defaultMaterialAsset) // Prevents the default material from showing up as a filled-in value in the property field - { - slot.m_materialAsset = materialFromController.m_materialAsset; - } + slot.m_materialAsset = materialFromController.m_materialAsset; slot.m_propertyOverrides = materialFromController.m_propertyOverrides; slot.m_matModUvOverrides = materialFromController.m_matModUvOverrides; @@ -435,9 +432,6 @@ namespace AZ AzToolsFramework::ScopedUndoBatch undoBatch("Generating materials."); SetDirty(); - Data::AssetId modelAssetId; - MeshComponentRequestBus::EventResult(modelAssetId, GetEntityId(), &MeshComponentRequestBus::Events::GetModelAssetId); - // First generating a unique set of all material asset IDs that will be used for source data generation AZStd::unordered_map assetIdMap; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp index f9243510cf..7d89fb0571 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp @@ -272,13 +272,11 @@ namespace AZ action = menu.addAction("Edit Source Material...", [this]() { OpenMaterialEditor(); }); action->setEnabled(HasSourceData()); - bool hasAnyMaterial = m_defaultMaterialAsset.GetId().IsValid() || m_materialAsset.GetId().IsValid(); - action = menu.addAction("Edit Material Instance...", [this]() { OpenMaterialInspector(); }); - action->setEnabled(hasAnyMaterial); + action->setEnabled(m_materialAsset.GetId().IsValid()); action = menu.addAction("Edit Material Instance UV Map...", [this]() { OpenUvNameMapInspector(); }); - action->setEnabled(hasAnyMaterial); + action->setEnabled(m_materialAsset.GetId().IsValid()); menu.addSeparator(); From 66f7fa2f4273ac5adc46cef0a6e0f161472a54fb Mon Sep 17 00:00:00 2001 From: Chris Santora Date: Fri, 23 Jul 2021 10:53:55 -0700 Subject: [PATCH 134/160] Fixed a bug where a new entity using a mesh that was already loaded would not be able to correctly initialize a material component. Repro steps: - Create two entities. - Entity 1 - Add a mesh component and assign a model with multiple sub-meshes - Add a material component. The material component looks correct. - Entity 2 - Add a mesh component and assign the same model as the other entity - Add a material component. The material component shows "" for all material slot names The problem was that ReflectedPropertyEditor creates a new Asset<> reference with the correct ID but does not load it. This asset is passed to EditorMaterialComponent, MaterialComponentController, and MeshFeatureProcessor and none of these tell the Asset to load. The MeshFeatureProcessor was not loading the Asset or connecting to the AssetBus because the instance already existed in the InstanceDatabse so from the FP's perspecive there was no need. But for the FP's GetModelAsset() API to function correctly it needs to have the asset initialized to the available AssetData pointer. So we updated the MeshFeatureProcessor to always connect to the AssetBus so it will find the available AssetData via the OnAssetReady callback. Signed-off-by: santorac <55155825+santorac@users.noreply.github.com> --- .../Code/Source/Mesh/MeshFeatureProcessor.cpp | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp index 6e031aa853..8e2c6f2e9b 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp @@ -485,20 +485,12 @@ namespace AZ AZ_Error("MeshDataInstance::MeshLoader", false, "Invalid model asset Id."); return; } - - // Check if the model is in the instance database and skip the loading process in this case. - // The model asset id is used as instance id to indicate that it is a static and shared. - Data::Instance model = Data::InstanceDatabase::Instance().Find(Data::InstanceId::CreateFromAssetId(m_modelAsset.GetId())); - if (model) + + if (!m_modelAsset.IsReady()) { - // In case the mesh asset requires instancing (e.g. when containing a cloth buffer), the model will always be cloned and there will not be a - // model instance with the asset id as instance id as searched above. - m_parent->Init(model); - m_modelChangedEvent.Signal(AZStd::move(model)); - return; + m_modelAsset.QueueLoad(); } - m_modelAsset.QueueLoad(); Data::AssetBus::Handler::BusConnect(modelAsset.GetId()); } From 13679a7cc3437bd45430e57e7cf076ca87cbbbe8 Mon Sep 17 00:00:00 2001 From: Chris Santora Date: Fri, 23 Jul 2021 11:02:06 -0700 Subject: [PATCH 135/160] Reverted partial support for property overrides on default material assignments. This needs more UI design discussion first. Signed-off-by: santorac <55155825+santorac@users.noreply.github.com> --- .../Source/Material/EditorMaterialComponentSlot.cpp | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp index 7d89fb0571..39dde65a99 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp @@ -227,11 +227,9 @@ namespace AZ OnPropertyChanged(); }; - Data::Asset assetToEdit = m_materialAsset.GetId().IsValid() ? m_materialAsset : m_defaultMaterialAsset; - - if (assetToEdit.GetId().IsValid()) + if (m_materialAsset.GetId().IsValid()) { - if (EditorMaterialComponentInspector::OpenInspectorDialog(GetLabel(), assetToEdit.GetId(), m_propertyOverrides, applyPropertyChangedCallback)) + if (EditorMaterialComponentInspector::OpenInspectorDialog(GetLabel(), m_materialAsset.GetId(), m_propertyOverrides, applyPropertyChangedCallback)) { OnMaterialChanged(); } @@ -247,11 +245,9 @@ namespace AZ OnPropertyChanged(); }; - Data::Asset assetToEdit = m_materialAsset.GetId().IsValid() ? m_materialAsset : m_defaultMaterialAsset; - - if (assetToEdit.GetId().IsValid()) + if (m_materialAsset.GetId().IsValid()) { - if (EditorMaterialComponentInspector::OpenInspectorDialog(assetToEdit.GetId(), m_matModUvOverrides, m_modelUvNames, applyMatModUvOverrideChangedCallback)) + if (EditorMaterialComponentInspector::OpenInspectorDialog(m_materialAsset.GetId(), m_matModUvOverrides, m_modelUvNames, applyMatModUvOverrideChangedCallback)) { OnMaterialChanged(); } From da243235081f99ba9fd06e336dab5d1e7ad0839a Mon Sep 17 00:00:00 2001 From: Ken Pruiksma Date: Fri, 30 Jul 2021 15:24:32 -0500 Subject: [PATCH 136/160] [SPEC-7794] Removing references to alembic in cmake & asset processor. Signed-off-by: Ken Pruiksma --- Registry/AssetProcessorPlatformConfig.setreg | 3 --- cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake | 1 - cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake | 1 - cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake | 1 - 4 files changed, 6 deletions(-) diff --git a/Registry/AssetProcessorPlatformConfig.setreg b/Registry/AssetProcessorPlatformConfig.setreg index 26aa5b2663..f1cb49c9cf 100644 --- a/Registry/AssetProcessorPlatformConfig.setreg +++ b/Registry/AssetProcessorPlatformConfig.setreg @@ -142,9 +142,6 @@ "Exclude TempFiles": { "pattern": ".*\\\\/\\\\$tmp[0-9]*_.*" }, - "Exclude AlembicCompressionTemplates": { - "pattern": ".*\\\\/Presets\\\\/GeomCache\\\\/.*" - }, "Exclude TmpAnimationCompression": { "pattern": ".*\\\\/Editor\\\\/Tmp\\\\/AnimationCompression\\\\/.*" }, diff --git a/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake b/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake index 209ae9b062..7bb2c61774 100644 --- a/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake +++ b/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake @@ -10,7 +10,6 @@ ly_associate_package(PACKAGE_NAME zlib-1.2.8-rev2-multiplatform TARGETS zlib PACKAGE_HASH e6f34b8ac16acf881e3d666ef9fd0c1aee94c3f69283fb6524d35d6f858eebbb) ly_associate_package(PACKAGE_NAME ilmbase-2.3.0-rev4-multiplatform TARGETS ilmbase PACKAGE_HASH 97547fdf1fbc4d81b8ccf382261f8c25514ed3b3c4f8fd493f0a4fa873bba348) ly_associate_package(PACKAGE_NAME hdf5-1.0.11-rev2-multiplatform TARGETS hdf5 PACKAGE_HASH 11d5e04df8a93f8c52a5684a4cacbf0d9003056360983ce34f8d7b601082c6bd) -ly_associate_package(PACKAGE_NAME alembic-1.7.11-rev3-multiplatform TARGETS alembic PACKAGE_HASH ba7a7d4943dd752f5a662374f6c48b93493df1d8e2c5f6a8d101f3b50700dd25) ly_associate_package(PACKAGE_NAME assimp-5.0.1-rev11-multiplatform TARGETS assimplib PACKAGE_HASH 1a9113788b893ef4a2ee63ac01eb71b981a92894a5a51175703fa225f5804dec) ly_associate_package(PACKAGE_NAME squish-ccr-20150601-rev3-multiplatform TARGETS squish-ccr PACKAGE_HASH c878c6c0c705e78403c397d03f5aa7bc87e5978298710e14d09c9daf951a83b3) ly_associate_package(PACKAGE_NAME ASTCEncoder-2017_11_14-rev2-multiplatform TARGETS ASTCEncoder PACKAGE_HASH c240ffc12083ee39a5ce9dc241de44d116e513e1e3e4cc1d05305e7aa3bdc326) diff --git a/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake b/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake index f7884fae46..bdffbd5dc7 100644 --- a/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake +++ b/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake @@ -10,7 +10,6 @@ ly_associate_package(PACKAGE_NAME zlib-1.2.8-rev2-multiplatform TARGETS zlib PACKAGE_HASH e6f34b8ac16acf881e3d666ef9fd0c1aee94c3f69283fb6524d35d6f858eebbb) ly_associate_package(PACKAGE_NAME ilmbase-2.3.0-rev4-multiplatform TARGETS ilmbase PACKAGE_HASH 97547fdf1fbc4d81b8ccf382261f8c25514ed3b3c4f8fd493f0a4fa873bba348) ly_associate_package(PACKAGE_NAME hdf5-1.0.11-rev2-multiplatform TARGETS hdf5 PACKAGE_HASH 11d5e04df8a93f8c52a5684a4cacbf0d9003056360983ce34f8d7b601082c6bd) -ly_associate_package(PACKAGE_NAME alembic-1.7.11-rev3-multiplatform TARGETS alembic PACKAGE_HASH ba7a7d4943dd752f5a662374f6c48b93493df1d8e2c5f6a8d101f3b50700dd25) ly_associate_package(PACKAGE_NAME assimp-5.0.1-rev11-multiplatform TARGETS assimplib PACKAGE_HASH 1a9113788b893ef4a2ee63ac01eb71b981a92894a5a51175703fa225f5804dec) ly_associate_package(PACKAGE_NAME squish-ccr-20150601-rev3-multiplatform TARGETS squish-ccr PACKAGE_HASH c878c6c0c705e78403c397d03f5aa7bc87e5978298710e14d09c9daf951a83b3) ly_associate_package(PACKAGE_NAME ASTCEncoder-2017_11_14-rev2-multiplatform TARGETS ASTCEncoder PACKAGE_HASH c240ffc12083ee39a5ce9dc241de44d116e513e1e3e4cc1d05305e7aa3bdc326) diff --git a/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake b/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake index 2b6e1da9ab..0134a45565 100644 --- a/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake +++ b/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake @@ -10,7 +10,6 @@ ly_associate_package(PACKAGE_NAME zlib-1.2.8-rev2-multiplatform TARGETS zlib PACKAGE_HASH e6f34b8ac16acf881e3d666ef9fd0c1aee94c3f69283fb6524d35d6f858eebbb) ly_associate_package(PACKAGE_NAME ilmbase-2.3.0-rev4-multiplatform TARGETS ilmbase PACKAGE_HASH 97547fdf1fbc4d81b8ccf382261f8c25514ed3b3c4f8fd493f0a4fa873bba348) ly_associate_package(PACKAGE_NAME hdf5-1.0.11-rev2-multiplatform TARGETS hdf5 PACKAGE_HASH 11d5e04df8a93f8c52a5684a4cacbf0d9003056360983ce34f8d7b601082c6bd) -ly_associate_package(PACKAGE_NAME alembic-1.7.11-rev3-multiplatform TARGETS alembic PACKAGE_HASH ba7a7d4943dd752f5a662374f6c48b93493df1d8e2c5f6a8d101f3b50700dd25) ly_associate_package(PACKAGE_NAME assimp-5.0.1-rev11-multiplatform TARGETS assimplib PACKAGE_HASH 1a9113788b893ef4a2ee63ac01eb71b981a92894a5a51175703fa225f5804dec) ly_associate_package(PACKAGE_NAME squish-ccr-20150601-rev3-multiplatform TARGETS squish-ccr PACKAGE_HASH c878c6c0c705e78403c397d03f5aa7bc87e5978298710e14d09c9daf951a83b3) ly_associate_package(PACKAGE_NAME ASTCEncoder-2017_11_14-rev2-multiplatform TARGETS ASTCEncoder PACKAGE_HASH c240ffc12083ee39a5ce9dc241de44d116e513e1e3e4cc1d05305e7aa3bdc326) From 461743ef2dc5a9d82e51bdfcca692fb1ac915ad8 Mon Sep 17 00:00:00 2001 From: SergeyAMZN <60428010+SergeyAMZN@users.noreply.github.com> Date: Fri, 30 Jul 2021 22:14:49 +0100 Subject: [PATCH 137/160] =?UTF-8?q?Enabled=20PhysX=20system=20component=20?= =?UTF-8?q?in=20asset=20builders=20since=20it's=20required=20=E2=80=A6=20(?= =?UTF-8?q?#2652)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Enabled PhysX system component in asset builders since it's required for cooking collision meshes Signed-off-by: pereslav * Added AssetCatalogService to the list of dependent Signed-off-by: pereslav --- Gems/PhysX/Code/Source/SystemComponent.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Gems/PhysX/Code/Source/SystemComponent.cpp b/Gems/PhysX/Code/Source/SystemComponent.cpp index af38927f10..d8c4b47a2a 100644 --- a/Gems/PhysX/Code/Source/SystemComponent.cpp +++ b/Gems/PhysX/Code/Source/SystemComponent.cpp @@ -95,6 +95,7 @@ namespace PhysX { serialize->Class() ->Version(1) + ->Attribute(AZ::Edit::Attributes::SystemComponentTags, AZStd::vector({ AZ_CRC_CE("AssetBuilder") })) ->Field("Enabled", &SystemComponent::m_enabled) ; @@ -122,13 +123,14 @@ namespace PhysX incompatible.push_back(AZ_CRC("PhysXService", 0x75beae2d)); } - void SystemComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) + void SystemComponent::GetRequiredServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& required) { - required.push_back(AZ_CRC("AssetDatabaseService", 0x3abf5601)); } - void SystemComponent::GetDependentServices([[maybe_unused]]AZ::ComponentDescriptor::DependencyArrayType& dependent) + void SystemComponent::GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent) { + dependent.push_back(AZ_CRC_CE("AssetDatabaseService")); + dependent.push_back(AZ_CRC_CE("AssetCatalogService")); } SystemComponent::SystemComponent() From e2eba69d338f90493ca7ea624957f1b7bf520a03 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Fri, 30 Jul 2021 18:19:35 -0500 Subject: [PATCH 138/160] updating FindMaterialAssignmentIdInLod to use ModelMaterialSlot } Signed-off-by: Guthrie Adams --- .../Source/Material/MaterialAssignment.cpp | 30 ++++++++----------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/Gems/Atom/Feature/Common/Code/Source/Material/MaterialAssignment.cpp b/Gems/Atom/Feature/Common/Code/Source/Material/MaterialAssignment.cpp index 2c68309e27..e43dde5d78 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Material/MaterialAssignment.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Material/MaterialAssignment.cpp @@ -33,8 +33,7 @@ namespace AZ serializeContext->Class() ->Version(1) ->Field("MaterialAsset", &MaterialAssignment::m_materialAsset) - ->Field("PropertyOverrides", &MaterialAssignment::m_propertyOverrides) - ; + ->Field("PropertyOverrides", &MaterialAssignment::m_propertyOverrides); } if (auto behaviorContext = azrtti_cast(context)) @@ -50,8 +49,7 @@ namespace AZ ->Constructor&, const Data::Instance&>() ->Method("ToString", &MaterialAssignment::ToString) ->Property("materialAsset", BehaviorValueProperty(&MaterialAssignment::m_materialAsset)) - ->Property("propertyOverrides", BehaviorValueProperty(&MaterialAssignment::m_propertyOverrides)) - ; + ->Property("propertyOverrides", BehaviorValueProperty(&MaterialAssignment::m_propertyOverrides)); behaviorContext->ConstantProperty("DefaultMaterialAssignment", BehaviorConstant(DefaultMaterialAssignment)) ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) @@ -67,7 +65,6 @@ namespace AZ ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) ->Attribute(AZ::Script::Attributes::Category, "render") ->Attribute(AZ::Script::Attributes::Module, "render"); - } } @@ -152,7 +149,8 @@ namespace AZ { if (mesh.m_material) { - const MaterialAssignmentId generalId = MaterialAssignmentId::CreateFromStableIdOnly(mesh.m_materialSlotStableId); + const MaterialAssignmentId generalId = + MaterialAssignmentId::CreateFromStableIdOnly(mesh.m_materialSlotStableId); materials[generalId] = MaterialAssignment(mesh.m_material->GetAsset(), mesh.m_material); const MaterialAssignmentId specificId = @@ -168,19 +166,17 @@ namespace AZ } MaterialAssignmentId FindMaterialAssignmentIdInLod( - const Data::Instance& lod, const MaterialAssignmentLodIndex lodIndex, const AZStd::string& labelFilter) + const Data::Instance model, + const Data::Instance& lod, + const MaterialAssignmentLodIndex lodIndex, + const AZStd::string& labelFilter) { for (const AZ::RPI::ModelLod::Mesh& mesh : lod->GetMeshes()) { - if (mesh.m_material && mesh.m_material->GetAssetId().IsValid()) + const AZ::RPI::ModelMaterialSlot& slot = model->GetModelAsset()->FindMaterialSlot(mesh.m_materialSlotStableId); + if (AZ::StringFunc::Contains(slot.m_displayName.GetCStr(), labelFilter, true)) { - AZ::Data::AssetInfo assetInfo; - AZ::Data::AssetCatalogRequestBus::BroadcastResult( - assetInfo, &AZ::Data::AssetCatalogRequests::GetAssetInfoById, mesh.m_material->GetAssetId()); - if (assetInfo.m_assetId.IsValid() && AZ::StringFunc::Contains(assetInfo.m_relativePath, labelFilter, true)) - { - return MaterialAssignmentId::CreateFromLodAndAsset(lodIndex, mesh.m_material->GetAssetId()); - } + return MaterialAssignmentId::CreateFromLodAndStableId(lodIndex, mesh.m_materialSlotStableId); } } return MaterialAssignmentId(); @@ -193,13 +189,13 @@ namespace AZ { if (lodFilter < model->GetLodCount()) { - return FindMaterialAssignmentIdInLod(model->GetLods()[lodFilter], lodFilter, labelFilter); + return FindMaterialAssignmentIdInLod(model, model->GetLods()[lodFilter], lodFilter, labelFilter); } for (size_t lodIndex = 0; lodIndex < model->GetLodCount(); ++lodIndex) { const MaterialAssignmentId result = - FindMaterialAssignmentIdInLod(model->GetLods()[lodIndex], MaterialAssignmentId::NonLodIndex, labelFilter); + FindMaterialAssignmentIdInLod(model, model->GetLods()[lodIndex], MaterialAssignmentId::NonLodIndex, labelFilter); if (!result.IsDefault()) { return result; From bb372f05cda5ab1baee5af5d28b18c591a47442a Mon Sep 17 00:00:00 2001 From: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> Date: Fri, 30 Jul 2021 18:20:21 -0500 Subject: [PATCH 139/160] Fixed the emplace function implementations for stack and queue (#2657) * Fixed the emplace function implementations for stack and queue Cleaned up several functions in the stack, queue and priority_queue classes that were non-standard or weren't needed. Updated the "style" of the code to use more modern concepts: "typedef" -> "using", empty constructor body -> default keyword. Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Replaced the custom implementations of AZStd stack, (proirity)queue Theses classes now have a template alias to the standard library version of the classes Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> --- Code/Framework/AzCore/AzCore/EBus/Policies.h | 6 +- .../AzCore/Serialization/AZStdContainers.inl | 2 - .../AzCore/AzCore/std/containers/queue.h | 201 +----------------- .../AzCore/AzCore/std/containers/stack.h | 98 +-------- .../AzCore/Tests/AZStd/DequeAndSimilar.cpp | 21 +- .../UnitTest/TestDebugDisplayRequests.cpp | 8 +- .../Visibility/OctreeSystemComponent.cpp | 2 +- .../GridMate/GridMate/Replica/ReplicaMgr.cpp | 10 +- .../GridMate/GridMate/Replica/ReplicaMgr.h | 16 +- .../Source/BlendTreeParameterNode.cpp | 2 +- .../ServerToClientReplicationWindow.cpp | 6 +- 11 files changed, 55 insertions(+), 317 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/EBus/Policies.h b/Code/Framework/AzCore/AzCore/EBus/Policies.h index 0217874416..db11043ef8 100644 --- a/Code/Framework/AzCore/AzCore/EBus/Policies.h +++ b/Code/Framework/AzCore/AzCore/EBus/Policies.h @@ -268,7 +268,7 @@ namespace AZ m_messages.pop(); if (numMessages == 1) { - m_messages.get_container().clear(); // If it was the last message, free all memory. + m_messages = {}; } } ////////////////////////////////////////////////////////////////////////// @@ -280,7 +280,7 @@ namespace AZ void Clear() { AZStd::lock_guard lock(m_messagesMutex); - m_messages.get_container().clear(); + m_messages = {}; } void SetActive(bool isActive) @@ -289,7 +289,7 @@ namespace AZ m_isActive = isActive; if (!m_isActive) { - m_messages.get_container().clear(); + m_messages = {}; } }; diff --git a/Code/Framework/AzCore/AzCore/Serialization/AZStdContainers.inl b/Code/Framework/AzCore/AzCore/Serialization/AZStdContainers.inl index 35a2d64c0d..9eb65dec76 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/AZStdContainers.inl +++ b/Code/Framework/AzCore/AzCore/Serialization/AZStdContainers.inl @@ -42,8 +42,6 @@ namespace AZStd class unordered_multiset; template class bitset; - template*/ > - class stack; template class intrusive_ptr; diff --git a/Code/Framework/AzCore/AzCore/std/containers/queue.h b/Code/Framework/AzCore/AzCore/std/containers/queue.h index f1df1dd787..8026ebe943 100644 --- a/Code/Framework/AzCore/AzCore/std/containers/queue.h +++ b/Code/Framework/AzCore/AzCore/std/containers/queue.h @@ -5,206 +5,17 @@ * SPDX-License-Identifier: Apache-2.0 OR MIT * */ -#ifndef AZSTD_QUEUE_H -#define AZSTD_QUEUE_H 1 +#pragma once #include #include #include +#include namespace AZStd { - /** - * FIFO queue complaint with \ref CStd (23.2.3.1) - * The only extension we have is that we allow access - * to the underlying container via: get_container function. - * Check the queue \ref AZStdExamples. - */ - template > - class queue - { - enum - { - CONTAINER_VERSION = 1 - }; - public: - typedef queue this_type; - typedef Container container_type; - typedef typename Container::value_type value_type; - typedef typename Container::size_type size_type; - typedef typename Container::reference reference; - typedef typename Container::const_reference const_reference; - - AZ_FORCE_INLINE queue() {} - - AZ_FORCE_INLINE explicit queue(const container_type& container) - : m_container(container) {} - AZ_FORCE_INLINE bool empty() const { return m_container.empty(); } - AZ_FORCE_INLINE size_type size() const { return m_container.size(); } - AZ_FORCE_INLINE reference front() { return m_container.front(); } - AZ_FORCE_INLINE const_reference front() const { return m_container.front(); } - AZ_FORCE_INLINE reference back() { return m_container.back(); } - AZ_FORCE_INLINE const_reference back() const { return m_container.back(); } - AZ_FORCE_INLINE void push(const value_type& value) { m_container.push_back(value); } - AZ_FORCE_INLINE void pop() { m_container.pop_front(); } - - AZ_FORCE_INLINE void push() { m_container.push_back(); } - - AZ_FORCE_INLINE queue(this_type&& rhs) - : m_container(AZStd::move(rhs.m_container)) {} - AZ_FORCE_INLINE explicit queue(Container&& container) - : m_container(AZStd::move(container)) {} - this_type& operator=(this_type&& rhs) - { - m_container = AZStd::move(rhs.m_container); - return (*this); - } - void push(value_type&& value) { m_container.push_back(AZStd::move(value)); } - template - void emplace(Args&&... args) { m_container.emplace_back(AZStd::forward(args)...); } - void swap(this_type& rhs) { AZStd::swap(m_container, rhs.m_container); } - - AZ_FORCE_INLINE Container& get_container() { return m_container; } - AZ_FORCE_INLINE const Container& get_container() const { return m_container; } - - protected: - Container m_container; - }; - - // queue TEMPLATE FUNCTIONS - template - AZ_FORCE_INLINE bool operator==(const AZStd::queue& left, const AZStd::queue& right) - { - return left.get_container() == right.get_container(); - } - - template - AZ_FORCE_INLINE bool operator!=(const AZStd::queue& left, const AZStd::queue& right) - { - return left.get_container() != right.get_container(); - } - - /* template - AZ_FORCE_INLINE bool operator<(const queue& left, const queue& right) - { - return left.get_container() < right.get_container(); - } - - template - AZ_FORCE_INLINE bool operator>(const queue& left, const queue& right) - { - return left.get_container() > right.get_container(); - } - - template - AZ_FORCE_INLINE operator<=(const queue& left, const queue& right) - { - return left.get_container() <= right.get_container(); - } - - template - AZ_FORCE_INLINE bool operator>=(const queue& left, const queue& right) - { - return left.get_container() >= right.get_container(); - }*/ - - /** - * Priority queue is complaint with \ref CStd (23.2.3.2) - * The only extension we have is that we allow access - * to the underlying container via: get_container function. - * Check the priority_queue \ref AZStdExamples. - */ - template, class Predicate = AZStd::less > - class priority_queue - { - enum - { - CONTAINER_VERSION = 1 - }; - public: - typedef priority_queue this_type; - typedef Container container_type; - typedef typename Container::value_type value_type; - typedef typename Container::size_type size_type; - typedef typename Container::reference reference; - typedef typename Container::const_reference const_reference; - - AZ_FORCE_INLINE priority_queue() {} - AZ_FORCE_INLINE explicit priority_queue(const Predicate& comp) - : m_comp(comp) {} - AZ_FORCE_INLINE priority_queue(const Predicate& comp, const container_type& container) - : m_container(container) - , m_comp(comp) - { - // construct by copying specified container, comparator - AZStd::make_heap(m_container.begin(), m_container.end(), comp); - } - template - AZ_FORCE_INLINE priority_queue(InputIterator first, InputIterator last) - : m_container(first, last) - , m_comp() - { - AZStd::make_heap(m_container.begin(), m_container.end(), m_comp); - } - - template - AZ_FORCE_INLINE priority_queue(InputIterator first, InputIterator last, const Predicate& comp) - : m_container(first, last) - , m_comp(comp) - { // construct by copying [_First, _Last), specified comparator - AZStd::make_heap(m_container.begin(), m_container.end(), m_comp); - } - - template - AZ_FORCE_INLINE priority_queue(InputIterator first, InputIterator last, const Predicate& comp, const container_type& container) - : m_container(container) - , m_comp(comp) - { // construct by copying [_First, _Last), container, and comparator - m_container.insert(m_container.end(), first, last); - AZStd::make_heap(m_container.begin(), m_container.end(), m_comp); - } - - AZ_FORCE_INLINE bool empty() const { return m_container.empty(); } - AZ_FORCE_INLINE size_type size() const { return m_container.size(); } - AZ_FORCE_INLINE const_reference top() const { return m_container.front(); } - AZ_FORCE_INLINE reference top() { return m_container.front(); } - AZ_FORCE_INLINE void push(const value_type& value) - { - m_container.push_back(value); - AZStd::push_heap(m_container.begin(), m_container.end(), m_comp); - } - - AZ_FORCE_INLINE void pop() - { - AZStd::pop_heap(m_container.begin(), m_container.end(), m_comp); - m_container.pop_back(); - } - - AZ_FORCE_INLINE priority_queue(this_type&& rhs) - : m_container(AZStd::move(rhs.m_container)) - , m_comp(AZStd::move(rhs.m_comp)) {} - AZ_FORCE_INLINE explicit priority_queue(const Predicate& pred, Container&& container) - : m_container(AZStd::move(container)) - , m_comp(pred) {} - this_type& operator=(this_type&& rhs) - { - m_container = AZStd::move(rhs.m_container); - m_comp = AZStd::move(rhs.m_comp); - return (*this); - } - void push(value_type&& value) { m_container.push_back(AZStd::move(value)); AZStd::push_heap(m_container.begin(), m_container.end(), m_comp); } - template - void emplace(Args&& args) { m_container.emplace_back(AZStd::forward(args)); AZStd::push_heap(m_container.begin(), m_container.end(), m_comp); } - void swap(this_type& rhs) { AZStd::swap(m_container, rhs.m_container); AZStd::swap(m_comp, rhs.m_comp); } - - AZ_FORCE_INLINE Container& get_container() { return m_container; } - AZ_FORCE_INLINE const Container& get_container() const { return m_container; } - - protected: - Container m_container; - Predicate m_comp; - }; + template> + using queue = std::queue; + template, class Compare = AZStd::less> + using priority_queue = std::priority_queue; } - -#endif // AZSTD_QUEUE_H -#pragma once diff --git a/Code/Framework/AzCore/AzCore/std/containers/stack.h b/Code/Framework/AzCore/AzCore/std/containers/stack.h index 715d46c933..aa0d62d105 100644 --- a/Code/Framework/AzCore/AzCore/std/containers/stack.h +++ b/Code/Framework/AzCore/AzCore/std/containers/stack.h @@ -5,103 +5,13 @@ * SPDX-License-Identifier: Apache-2.0 OR MIT * */ -#ifndef AZSTD_STACK_H -#define AZSTD_STACK_H 1 +#pragma once #include +#include namespace AZStd { - /** - * Stack container is complaint with \ref CStd (23.2.3.3) - * The only extension we have is that we allow access - * to the underlying container via: get_container function. - * Check the stack \ref AZStdExamples. - */ - template > - class stack - { - enum - { - CONTAINER_VERSION = 1 - }; - public: - typedef stack this_type; - typedef Container container_type; - typedef typename Container::value_type value_type; - typedef typename Container::size_type size_type; - typedef typename Container::reference reference; - typedef typename Container::const_reference const_reference; - - AZ_FORCE_INLINE stack() {} - AZ_FORCE_INLINE explicit stack(const container_type& container) - : m_container(container) {} - AZ_FORCE_INLINE bool empty() const { return m_container.empty(); } - AZ_FORCE_INLINE size_type size() const { return m_container.size(); } - AZ_FORCE_INLINE reference top() { return m_container.back(); } - AZ_FORCE_INLINE const_reference top() const { return m_container.back(); } - AZ_FORCE_INLINE reference back() { return m_container.back(); } - AZ_FORCE_INLINE const_reference back() const { return m_container.back(); } - AZ_FORCE_INLINE void push(const value_type& value) { m_container.push_back(value); } - AZ_FORCE_INLINE void pop() { m_container.pop_back(); } - AZ_FORCE_INLINE void push() { m_container.push_back(); } - - AZ_FORCE_INLINE stack(this_type&& rhs) - : m_container(AZStd::move(rhs.m_container)) {} - AZ_FORCE_INLINE explicit stack(Container&& container) - : m_container(AZStd::move(container)) {} - this_type& operator=(this_type&& rhs) { m_container = AZStd::move(rhs.m_container); return *this; } - void push(value_type&& value) { m_container.push_back(AZStd::move(value)); } - template - void emplace(Args&& args) { m_container.emplace_back(AZStd::forward(args)); } - void swap(this_type&& rhs) { m_container.swap(AZStd::move(rhs.m_container)); } - - void swap(this_type& rhs) { AZStd::swap(m_container, rhs.m_container); } - - AZ_FORCE_INLINE Container& get_container() { return m_container; } - AZ_FORCE_INLINE const Container& get_container() const { return m_container; } - - protected: - Container m_container; - }; - - // queue TEMPLATE FUNCTIONS - template - AZ_FORCE_INLINE bool operator==(const AZStd::stack& left, const AZStd::stack& right) - { - return left.get_container() == right.get_container(); - } - - template - AZ_FORCE_INLINE bool operator!=(const AZStd::stack& left, const AZStd::stack& right) - { - return left.get_container() != right.get_container(); - } - - /* template - AZ_FORCE_INLINE bool operator<(const queue& left, const queue& right) - { - return left.get_container() < right.get_container(); - } - - template - AZ_FORCE_INLINE bool operator>(const queue& left, const queue& right) - { - return left.get_container() > right.get_container(); - } - - template - AZ_FORCE_INLINE operator<=(const queue& left, const queue& right) - { - return left.get_container() <= right.get_container(); - } - - template - AZ_FORCE_INLINE bool operator>=(const queue& left, const queue& right) - { - return left.get_container() >= right.get_container(); - }*/ + template> + using stack = std::stack; } - -#endif // AZSTD_STACK_H -#pragma once diff --git a/Code/Framework/AzCore/Tests/AZStd/DequeAndSimilar.cpp b/Code/Framework/AzCore/Tests/AZStd/DequeAndSimilar.cpp index 587d900b90..33a5d29b4f 100644 --- a/Code/Framework/AzCore/Tests/AZStd/DequeAndSimilar.cpp +++ b/Code/Framework/AzCore/Tests/AZStd/DequeAndSimilar.cpp @@ -298,7 +298,7 @@ namespace UnitTest AZ_TEST_ASSERT(int_queue.empty()); AZ_TEST_ASSERT(int_queue.size() == 0); - // Queue uses deque as default container, so try to contruct to queue from a deque. + // Queue uses deque as default container, so try to construct to queue from a deque. deque container(40, 10); int_queue_type int_queue2(container); AZ_TEST_ASSERT(!int_queue2.empty()); @@ -324,7 +324,7 @@ namespace UnitTest AZ_TEST_ASSERT(int_queue2.size() == 40); AZ_TEST_ASSERT(int_queue2.back() == 20); - int_queue.push(); + int_queue.emplace(); AZ_TEST_ASSERT(!int_queue.empty()); AZ_TEST_ASSERT(int_queue.size() == 1); @@ -423,7 +423,7 @@ namespace UnitTest AZ_TEST_ASSERT(int_stack2.size() == 40); AZ_TEST_ASSERT(int_stack2.top() == 10); - int_stack.push(); + int_stack.emplace(); AZ_TEST_ASSERT(!int_stack.empty()); AZ_TEST_ASSERT(int_stack.size() == 1); // StackContainerTest-End @@ -669,4 +669,19 @@ namespace UnitTest ++iteration; } } + + using StackContainerTestFixture = ScopedAllocatorSetupFixture; + + TEST_F(StackContainerTestFixture, StackEmplaceOperator_SupportsZeroOrMoreArguments) + { + using TestPairType = AZStd::pair; + AZStd::stack testStack; + testStack.emplace(); + testStack.emplace(1); + testStack.emplace(2, 3); + + using ContainerType = typename AZStd::stack::container_type; + AZStd::stack expectedStack(ContainerType{ TestPairType{ 0, 0 }, TestPairType{ 1, 0 }, TestPairType{ 2, 3 } }); + EXPECT_EQ(expectedStack, testStack); + } } diff --git a/Code/Framework/AzFramework/AzFramework/UnitTest/TestDebugDisplayRequests.cpp b/Code/Framework/AzFramework/AzFramework/UnitTest/TestDebugDisplayRequests.cpp index cc663f36b8..ecbacd125b 100644 --- a/Code/Framework/AzFramework/AzFramework/UnitTest/TestDebugDisplayRequests.cpp +++ b/Code/Framework/AzFramework/AzFramework/UnitTest/TestDebugDisplayRequests.cpp @@ -32,7 +32,7 @@ namespace UnitTest void TestDebugDisplayRequests::DrawWireBox(const AZ::Vector3& min, const AZ::Vector3& max) { - const AZ::Transform& tm = m_transforms.back(); + const AZ::Transform& tm = m_transforms.top(); m_points.push_back(tm.TransformPoint(AZ::Vector3(min.GetX(), min.GetY(), min.GetZ()))); m_points.push_back(tm.TransformPoint(AZ::Vector3(min.GetX(), min.GetY(), max.GetZ()))); m_points.push_back(tm.TransformPoint(AZ::Vector3(min.GetX(), max.GetY(), min.GetZ()))); @@ -50,7 +50,7 @@ namespace UnitTest void TestDebugDisplayRequests::DrawWireQuad(float width, float height) { - const AZ::Transform& tm = m_transforms.back(); + const AZ::Transform& tm = m_transforms.top(); m_points.push_back(tm.TransformPoint(AZ::Vector3(-0.5f * width, 0.0f, -0.5f * height))); m_points.push_back(tm.TransformPoint(AZ::Vector3(-0.5f * width, 0.0f, 0.5f * height))); m_points.push_back(tm.TransformPoint(AZ::Vector3(0.5f * width, 0.0f, -0.5f * height))); @@ -64,7 +64,7 @@ namespace UnitTest void TestDebugDisplayRequests::DrawPoints(const AZStd::vector& points) { - const AZ::Transform& tm = m_transforms.back(); + const AZ::Transform& tm = m_transforms.top(); for (const auto& point : points) { m_points.push_back(tm.TransformPoint(point)); @@ -100,7 +100,7 @@ namespace UnitTest void TestDebugDisplayRequests::PushMatrix(const AZ::Transform& tm) { - m_transforms.push(m_transforms.back() * tm); + m_transforms.push(m_transforms.top() * tm); } void TestDebugDisplayRequests::PopMatrix() diff --git a/Code/Framework/AzFramework/AzFramework/Visibility/OctreeSystemComponent.cpp b/Code/Framework/AzFramework/AzFramework/Visibility/OctreeSystemComponent.cpp index 5ef1cda30e..b4cad8511f 100644 --- a/Code/Framework/AzFramework/AzFramework/Visibility/OctreeSystemComponent.cpp +++ b/Code/Framework/AzFramework/AzFramework/Visibility/OctreeSystemComponent.cpp @@ -481,7 +481,7 @@ namespace AzFramework if (!m_freeOctreeNodes.empty()) { // Take a free block of child nodes from our free list - ExtractPageAndOffsetFromIndex(m_freeOctreeNodes.back(), nextChildPage, nextChildOffset); + ExtractPageAndOffsetFromIndex(m_freeOctreeNodes.top(), nextChildPage, nextChildOffset); m_freeOctreeNodes.pop(); } else diff --git a/Code/Framework/GridMate/GridMate/Replica/ReplicaMgr.cpp b/Code/Framework/GridMate/GridMate/Replica/ReplicaMgr.cpp index 2bc8d3e9f0..b8eea00871 100644 --- a/Code/Framework/GridMate/GridMate/Replica/ReplicaMgr.cpp +++ b/Code/Framework/GridMate/GridMate/Replica/ReplicaMgr.cpp @@ -1688,12 +1688,12 @@ namespace GridMate return; //No connections to update } bool updateRate = false; - AZ::u32 minRateBytesPerSecond = m_connByCongestionState.top().m_rate; + AZ::u32 minRateBytesPerSecond = m_connByCongestionState.front().m_rate; //const AZ::u32 old = minRateBytesPerSecond; //For debugging - auto connIt = AZStd::find(m_connByCongestionState.get_container().begin(), m_connByCongestionState.get_container().end(), id); + auto connIt = AZStd::find(m_connByCongestionState.begin(), m_connByCongestionState.end(), id); - if ( connIt == m_connByCongestionState.get_container().end()) + if ( connIt == m_connByCongestionState.end()) { return; //Already disconnected } @@ -1708,11 +1708,11 @@ namespace GridMate //If new min or old min increased, rebuild the heap and send an update if (bytesPerSecond < minRateBytesPerSecond - || (id == m_connByCongestionState.top().m_connection && bytesPerSecond > minRateBytesPerSecond)) + || (id == m_connByCongestionState.front().m_connection && bytesPerSecond > minRateBytesPerSecond)) { updateRate = true; minRateBytesPerSecond = bytesPerSecond; - AZStd::make_heap(m_connByCongestionState.get_container().begin(), m_connByCongestionState.get_container().end()); + AZStd::make_heap(m_connByCongestionState.begin(), m_connByCongestionState.end()); } } diff --git a/Code/Framework/GridMate/GridMate/Replica/ReplicaMgr.h b/Code/Framework/GridMate/GridMate/Replica/ReplicaMgr.h index 93a46d8ad7..bd9f1a1ee9 100644 --- a/Code/Framework/GridMate/GridMate/Replica/ReplicaMgr.h +++ b/Code/Framework/GridMate/GridMate/Replica/ReplicaMgr.h @@ -459,7 +459,7 @@ namespace GridMate } }; static bool k_enableBackPressure; - AZStd::priority_queue m_connByCongestionState; ///< Connections priority queue sorted by congestion window + AZStd::vector m_connByCongestionState; ///< Connections priority queue sorted by congestion window /*** * Updates connection's rate in priority and updates send limit * @@ -479,7 +479,9 @@ namespace GridMate } AZ_Assert(carrier, "NULL carrier!"); - m_connByCongestionState.emplace(RateConnectionPair(AZ::u32(1500), id)); //default to 1500Bps (ex 1 Ethernet frame/second minimum) + m_connByCongestionState.emplace_back(AZ::u32(1500), id); //default to 1500Bps (ex 1 Ethernet frame/second minimum) + // Restore the heap property after pushing back another element + AZStd::push_heap(m_connByCongestionState.begin(), m_connByCongestionState.end()); } void OnDisconnect(Carrier* carrier, ConnectionID id, CarrierDisconnectReason reason) override { @@ -490,17 +492,17 @@ namespace GridMate } AZ_Assert(carrier, "NULL carrier!"); - auto connIt = AZStd::find(m_connByCongestionState.get_container().begin(), m_connByCongestionState.get_container().end(), id); - if (connIt != m_connByCongestionState.get_container().end()) + auto connIt = AZStd::find(m_connByCongestionState.begin(), m_connByCongestionState.end(), id); + if (connIt != m_connByCongestionState.end()) { //Since we are using a weakly sorted heap, we need to re-generate when the top is removed - bool remake = (connIt == m_connByCongestionState.get_container().begin()); + bool remake = (connIt == m_connByCongestionState.begin()); - m_connByCongestionState.get_container().erase(connIt); + m_connByCongestionState.erase(connIt); if (remake) { - AZStd::make_heap(m_connByCongestionState.get_container().begin(), m_connByCongestionState.get_container().end()); + AZStd::make_heap(m_connByCongestionState.begin(), m_connByCongestionState.end()); } } } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeParameterNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeParameterNode.cpp index 682657e5bb..8197cae9d0 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeParameterNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeParameterNode.cpp @@ -395,7 +395,7 @@ namespace EMotionFX } // If new parameter matches the last deleted parameter, we add it back to the parameter mask. - if (!m_deletedParameterNames.empty() && newParameterName == m_deletedParameterNames.back()) + if (!m_deletedParameterNames.empty() && newParameterName == m_deletedParameterNames.top()) { m_parameterNames.push_back(newParameterName); SortAndRemoveDuplicates(GetAnimGraph(), m_parameterNames); // make sure the mask is sorted correctly. diff --git a/Gems/Multiplayer/Code/Source/ReplicationWindows/ServerToClientReplicationWindow.cpp b/Gems/Multiplayer/Code/Source/ReplicationWindows/ServerToClientReplicationWindow.cpp index 740f9abea2..ba9740f8db 100644 --- a/Gems/Multiplayer/Code/Source/ReplicationWindows/ServerToClientReplicationWindow.cpp +++ b/Gems/Multiplayer/Code/Source/ReplicationWindows/ServerToClientReplicationWindow.cpp @@ -107,8 +107,10 @@ namespace Multiplayer void ServerToClientReplicationWindow::UpdateWindow() { // clear the candidate queue, we're going to rebuild it - ReplicationCandidateQueue clearQueue; - clearQueue.get_container().reserve(sv_MaxEntitiesToTrackReplication); + ReplicationCandidateQueue::container_type clearQueueContainer; + clearQueueContainer.reserve(sv_MaxEntitiesToTrackReplication); + // Move the clearQueueContainer into the ReplicationCandidateQueue to maintain the reserved memory + ReplicationCandidateQueue clearQueue(ReplicationCandidateQueue::value_compare{}, AZStd::move(clearQueueContainer)); m_candidateQueue.swap(clearQueue); m_replicationSet.clear(); From 5d3d3b907ed528ff417091a8633ea95c39326dbb Mon Sep 17 00:00:00 2001 From: santorac <55155825+santorac@users.noreply.github.com> Date: Fri, 30 Jul 2021 16:52:43 -0700 Subject: [PATCH 140/160] Changed a couple function parameters to const& Signed-off-by: santorac <55155825+santorac@users.noreply.github.com> --- .../Code/Include/Atom/Feature/Material/MaterialAssignment.h | 2 +- .../Common/Code/Source/Material/MaterialAssignment.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Material/MaterialAssignment.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Material/MaterialAssignment.h index 907b1a1740..987e78ae0f 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Material/MaterialAssignment.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Material/MaterialAssignment.h @@ -66,6 +66,6 @@ namespace AZ //! Find an assignment id corresponding to the lod and label substring filters MaterialAssignmentId FindMaterialAssignmentIdInModel( - const Data::Instance model, const MaterialAssignmentLodIndex lodFilter, const AZStd::string& labelFilter); + const Data::Instance& model, const MaterialAssignmentLodIndex lodFilter, const AZStd::string& labelFilter); } // namespace Render } // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/Material/MaterialAssignment.cpp b/Gems/Atom/Feature/Common/Code/Source/Material/MaterialAssignment.cpp index e43dde5d78..4d437be244 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Material/MaterialAssignment.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Material/MaterialAssignment.cpp @@ -166,7 +166,7 @@ namespace AZ } MaterialAssignmentId FindMaterialAssignmentIdInLod( - const Data::Instance model, + const Data::Instance& model, const Data::Instance& lod, const MaterialAssignmentLodIndex lodIndex, const AZStd::string& labelFilter) @@ -183,7 +183,7 @@ namespace AZ } MaterialAssignmentId FindMaterialAssignmentIdInModel( - const Data::Instance model, const MaterialAssignmentLodIndex lodFilter, const AZStd::string& labelFilter) + const Data::Instance& model, const MaterialAssignmentLodIndex lodFilter, const AZStd::string& labelFilter) { if (model && !labelFilter.empty()) { From bb782e83b46d41fd8a64b7ce4a62aa598913d7c9 Mon Sep 17 00:00:00 2001 From: Jeremy Ong Date: Wed, 28 Jul 2021 09:33:28 -0600 Subject: [PATCH 141/160] Promote IndexedDataVector to public Feature/Utils header Signed-off-by: Jeremy Ong --- .../Atom/Feature/Utils}/IndexedDataVector.h | 0 .../Atom/Feature/Utils}/IndexedDataVector.inl | 0 .../Atom/Feature/Common/Code/Source/CommonSystemComponent.cpp | 2 +- .../Code/Source/CoreLights/CapsuleLightFeatureProcessor.h | 2 +- .../Code/Source/CoreLights/DirectionalLightFeatureProcessor.h | 2 +- .../Common/Code/Source/CoreLights/DiskLightFeatureProcessor.h | 2 +- .../Code/Source/CoreLights/PointLightFeatureProcessor.h | 2 +- .../Common/Code/Source/CoreLights/QuadLightFeatureProcessor.h | 2 +- .../Code/Source/CoreLights/SimplePointLightFeatureProcessor.h | 2 +- .../Code/Source/CoreLights/SimpleSpotLightFeatureProcessor.h | 2 +- .../Code/Source/Decals/DecalTextureArrayFeatureProcessor.h | 2 +- .../Code/Source/Shadows/ProjectedShadowFeatureProcessor.h | 2 +- Gems/Atom/Feature/Common/Code/atom_feature_common_files.cmake | 4 ++-- 13 files changed, 12 insertions(+), 12 deletions(-) rename Gems/Atom/Feature/Common/Code/{Source/CoreLights => Include/Atom/Feature/Utils}/IndexedDataVector.h (100%) rename Gems/Atom/Feature/Common/Code/{Source/CoreLights => Include/Atom/Feature/Utils}/IndexedDataVector.inl (100%) diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/IndexedDataVector.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/IndexedDataVector.h similarity index 100% rename from Gems/Atom/Feature/Common/Code/Source/CoreLights/IndexedDataVector.h rename to Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/IndexedDataVector.h diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/IndexedDataVector.inl b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/IndexedDataVector.inl similarity index 100% rename from Gems/Atom/Feature/Common/Code/Source/CoreLights/IndexedDataVector.inl rename to Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/IndexedDataVector.inl diff --git a/Gems/Atom/Feature/Common/Code/Source/CommonSystemComponent.cpp b/Gems/Atom/Feature/Common/Code/Source/CommonSystemComponent.cpp index 6ad0099686..1500079b00 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CommonSystemComponent.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/CommonSystemComponent.cpp @@ -284,7 +284,7 @@ namespace AZ passSystem->AddPassCreator(Name("ReflectionScreenSpaceCompositePass"), &Render::ReflectionScreenSpaceCompositePass::Create); passSystem->AddPassCreator(Name("ReflectionCopyFrameBufferPass"), &Render::ReflectionCopyFrameBufferPass::Create); - // Add RayTracing pas + // Add RayTracing pass passSystem->AddPassCreator(Name("RayTracingPass"), &Render::RayTracingPass::Create); // setup handler for load pass template mappings diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/CapsuleLightFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Source/CoreLights/CapsuleLightFeatureProcessor.h index a85831e290..6749acfcf5 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/CapsuleLightFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/CapsuleLightFeatureProcessor.h @@ -10,7 +10,7 @@ #include #include -#include +#include #include namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.h index a312b31dda..4c486c4540 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.h @@ -9,9 +9,9 @@ #pragma once #include -#include #include +#include #include #include #include diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DiskLightFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DiskLightFeatureProcessor.h index 2e97ae1ded..36837a67fb 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DiskLightFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DiskLightFeatureProcessor.h @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/PointLightFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Source/CoreLights/PointLightFeatureProcessor.h index b7b644da9e..3c231c1fb0 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/PointLightFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/PointLightFeatureProcessor.h @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/QuadLightFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Source/CoreLights/QuadLightFeatureProcessor.h index 567d309dff..17d6aab304 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/QuadLightFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/QuadLightFeatureProcessor.h @@ -10,7 +10,7 @@ #include #include -#include +#include namespace AZ { diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/SimplePointLightFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Source/CoreLights/SimplePointLightFeatureProcessor.h index 3d36bb1978..bd9160b171 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/SimplePointLightFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/SimplePointLightFeatureProcessor.h @@ -11,7 +11,7 @@ #include #include #include -#include +#include namespace AZ { diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/SimpleSpotLightFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Source/CoreLights/SimpleSpotLightFeatureProcessor.h index 1d72c3e6cc..bc132be77c 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/SimpleSpotLightFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/SimpleSpotLightFeatureProcessor.h @@ -11,7 +11,7 @@ #include #include #include -#include +#include namespace AZ { diff --git a/Gems/Atom/Feature/Common/Code/Source/Decals/DecalTextureArrayFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Source/Decals/DecalTextureArrayFeatureProcessor.h index 649928d26d..57c5c69e0d 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Decals/DecalTextureArrayFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Source/Decals/DecalTextureArrayFeatureProcessor.h @@ -9,6 +9,7 @@ #pragma once #include +#include #include #include #include @@ -16,7 +17,6 @@ #include #include #include -#include namespace AZ { diff --git a/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.h index 3dbf88addb..8beed800b6 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.h @@ -10,10 +10,10 @@ #include #include +#include #include #include #include -#include namespace AZ::Render { diff --git a/Gems/Atom/Feature/Common/Code/atom_feature_common_files.cmake b/Gems/Atom/Feature/Common/Code/atom_feature_common_files.cmake index 401fac8c0c..40188109ca 100644 --- a/Gems/Atom/Feature/Common/Code/atom_feature_common_files.cmake +++ b/Gems/Atom/Feature/Common/Code/atom_feature_common_files.cmake @@ -37,6 +37,8 @@ set(FILES Include/Atom/Feature/TransformService/TransformServiceFeatureProcessor.h Include/Atom/Feature/Utils/FrameCaptureBus.h Include/Atom/Feature/Utils/GpuBufferHandler.h + Include/Atom/Feature/Utils/IndexedDataVector.h + Include/Atom/Feature/Utils/IndexedDataVector.inl Include/Atom/Feature/Utils/MultiIndexedDataVector.h Include/Atom/Feature/Utils/MultiSparseVector.h Include/Atom/Feature/Utils/ProfilingCaptureBus.h @@ -77,8 +79,6 @@ set(FILES Source/CoreLights/DiskLightFeatureProcessor.cpp Source/CoreLights/EsmShadowmapsPass.h Source/CoreLights/EsmShadowmapsPass.cpp - Source/CoreLights/IndexedDataVector.h - Source/CoreLights/IndexedDataVector.inl Source/CoreLights/LtcCommon.h Source/CoreLights/LtcCommon.cpp Source/CoreLights/PointLightFeatureProcessor.h From e1ce742f14f096e9a2e9d0a7af68cca9068f8628 Mon Sep 17 00:00:00 2001 From: Jeremy Ong Date: Wed, 28 Jul 2021 12:30:06 -0600 Subject: [PATCH 142/160] Generalize comments pertaining to light data and consolidate inline header Signed-off-by: Jeremy Ong --- .../Atom/Feature/Utils/IndexedDataVector.h | 128 ++++++++++++++++-- .../Atom/Feature/Utils/IndexedDataVector.inl | 113 ---------------- .../Code/atom_feature_common_files.cmake | 1 - 3 files changed, 120 insertions(+), 122 deletions(-) delete mode 100644 Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/IndexedDataVector.inl diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/IndexedDataVector.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/IndexedDataVector.h index f2a372aca9..a73ba2f16b 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/IndexedDataVector.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/IndexedDataVector.h @@ -15,11 +15,15 @@ namespace AZ { namespace Render { + // Growable vector that leverages indirection to support erasure of elements while maintaining + // resident data in a densely packed region of memory. Useful as a backing store for growable + // buffers intended to be uploaded to the GPU for example. template class IndexedDataVector { public: IndexedDataVector(); + explicit IndexedDataVector(size_t initialReservedSize); ~IndexedDataVector() = default; static constexpr IndexType NoFreeSlot = std::numeric_limits::max(); @@ -39,17 +43,125 @@ namespace AZ IndexType GetRawIndex(IndexType index) const; private: + constexpr static size_t InitialReservedSize = 128; - static constexpr size_t InitialReservedCount = 128; - - // stores the index of data vector for respective light, it also include a linked list to flag the free slots + // Stores data indices and an embedded free list AZStd::vector m_indices; - // stores the index of index vector for respective light + // Stores the indirection index AZStd::vector m_dataToIndices; - // stores light data AZStd::vector m_data; }; -#include "IndexedDataVector.inl" - } -} + template + inline IndexedDataVector::IndexedDataVector() + : IndexedDataVector(InitialReservedSize) + { + } + + template + inline IndexedDataVector::IndexedDataVector(size_t initialReservedSize) + { + m_dataToIndices.reserve(initialReservedSize); + m_indices.reserve(initialReservedSize); + m_data.reserve(initialReservedSize); + } + + template + inline void IndexedDataVector::Clear() + { + m_dataToIndices.clear(); + m_indices.clear(); + m_data.clear(); + + m_firstFreeSlot = NoFreeSlot; + } + + template + inline IndexType IndexedDataVector::GetFreeSlotIndex() + { + IndexType freeSlotIndex = static_cast(m_indices.size()); + + if (freeSlotIndex == NoFreeSlot) + { + // the vector is full + return NoFreeSlot; + } + + if (m_firstFreeSlot == NoFreeSlot) + { + // If there's no free slot, add on to the end. + m_indices.push_back(freeSlotIndex); + } + else + { + // Fill the free slot. m_indices uses it's empty slots to store a linked list (via indices) to other empty slots. + freeSlotIndex = m_firstFreeSlot; + m_firstFreeSlot = m_indices.at(m_firstFreeSlot); + m_indices.at(freeSlotIndex) = static_cast(m_data.size()); + } + + // The data itself is always packed and m_indices points at it, so push a new entry to the back. + m_data.push_back(DataType()); + m_dataToIndices.push_back(freeSlotIndex); + + return freeSlotIndex; + } + + template + inline void IndexedDataVector::RemoveIndex(IndexType index) + { + IndexType dataIndex = m_indices.at(index); + + // Copy the back light on top of this one. + m_data.at(dataIndex) = m_data.back(); + m_dataToIndices.at(dataIndex) = m_dataToIndices.back(); + + // Update the index of the moved light + m_indices.at(m_dataToIndices.at(dataIndex)) = dataIndex; + + // Pop the back + m_data.pop_back(); + m_dataToIndices.pop_back(); + + // Use free slot to link to next free slot + m_indices.at(index) = m_firstFreeSlot; + m_firstFreeSlot = index; + } + + template + inline DataType& IndexedDataVector::GetData(IndexType index) + { + return m_data.at(m_indices.at(index)); + } + + template + inline const DataType& IndexedDataVector::GetData(IndexType index) const + { + return m_data.at(m_indices.at(index)); + } + + template + inline size_t IndexedDataVector::GetDataCount() const + { + return m_data.size(); + } + + template + inline AZStd::vector& IndexedDataVector::GetDataVector() + { + return m_data; + } + + template + inline const AZStd::vector& IndexedDataVector::GetDataVector() const + { + return m_data; + } + + template + IndexType IndexedDataVector::GetRawIndex(IndexType index) const + { + return m_indices.at(index); + } + } // namespace Render +} // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/IndexedDataVector.inl b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/IndexedDataVector.inl deleted file mode 100644 index da10e5a503..0000000000 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/IndexedDataVector.inl +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -template -inline IndexedDataVector::IndexedDataVector() -{ - m_dataToIndices.reserve(InitialReservedCount); - m_indices.reserve(InitialReservedCount); - m_data.reserve(InitialReservedCount); -} - -template -inline void IndexedDataVector::Clear() -{ - m_dataToIndices.clear(); - m_indices.clear(); - m_data.clear(); - - m_firstFreeSlot = NoFreeSlot; -} - -template -inline IndexType IndexedDataVector::GetFreeSlotIndex() -{ - IndexType freeSlotIndex = static_cast(m_indices.size()); - - if (freeSlotIndex == NoFreeSlot) - { - // the vector is full - return NoFreeSlot; - } - - if (m_firstFreeSlot == NoFreeSlot) - { - // If there's no free slot, add on to the end. - m_indices.push_back(freeSlotIndex); - } - else - { - // Fill the free slot. m_indices uses it's empty slots to store a linked list (via indices) to other empty slots. - freeSlotIndex = m_firstFreeSlot; - m_firstFreeSlot = m_indices.at(m_firstFreeSlot); - m_indices.at(freeSlotIndex) = static_cast(m_data.size()); - } - - // The data itself is always packed and m_indices points at it, so push a new entry to the back. - m_data.push_back(DataType()); - m_dataToIndices.push_back(freeSlotIndex); - - return freeSlotIndex; -} - -template -inline void IndexedDataVector::RemoveIndex(IndexType index) -{ - IndexType dataIndex = m_indices.at(index); - - // Copy the back light on top of this one. - m_data.at(dataIndex) = m_data.back(); - m_dataToIndices.at(dataIndex) = m_dataToIndices.back(); - - // Update the index of the moved light - m_indices.at(m_dataToIndices.at(dataIndex)) = dataIndex; - - // Pop the back - m_data.pop_back(); - m_dataToIndices.pop_back(); - - // Use free slot to link to next free slot - m_indices.at(index) = m_firstFreeSlot; - m_firstFreeSlot = index; -} - -template -inline DataType& IndexedDataVector::GetData(IndexType index) -{ - return m_data.at(m_indices.at(index)); -} - -template -inline const DataType& IndexedDataVector::GetData(IndexType index) const -{ - return m_data.at(m_indices.at(index)); -} - -template -inline size_t IndexedDataVector::GetDataCount() const -{ - return m_data.size(); -} - -template -inline AZStd::vector& IndexedDataVector::GetDataVector() -{ - return m_data; -} - -template -inline const AZStd::vector& IndexedDataVector::GetDataVector() const -{ - return m_data; -} - -template -IndexType IndexedDataVector::GetRawIndex(IndexType index) const -{ - return m_indices.at(index); -} diff --git a/Gems/Atom/Feature/Common/Code/atom_feature_common_files.cmake b/Gems/Atom/Feature/Common/Code/atom_feature_common_files.cmake index 40188109ca..e4a914ac34 100644 --- a/Gems/Atom/Feature/Common/Code/atom_feature_common_files.cmake +++ b/Gems/Atom/Feature/Common/Code/atom_feature_common_files.cmake @@ -38,7 +38,6 @@ set(FILES Include/Atom/Feature/Utils/FrameCaptureBus.h Include/Atom/Feature/Utils/GpuBufferHandler.h Include/Atom/Feature/Utils/IndexedDataVector.h - Include/Atom/Feature/Utils/IndexedDataVector.inl Include/Atom/Feature/Utils/MultiIndexedDataVector.h Include/Atom/Feature/Utils/MultiSparseVector.h Include/Atom/Feature/Utils/ProfilingCaptureBus.h From 78760245c5a96d81881ccc2b800c2a58390a3a5c Mon Sep 17 00:00:00 2001 From: Jeremy Ong Date: Wed, 28 Jul 2021 15:26:41 -0600 Subject: [PATCH 143/160] Remove one level of indentation Signed-off-by: Jeremy Ong --- .../Atom/Feature/Utils/IndexedDataVector.h | 263 +++++++++--------- 1 file changed, 130 insertions(+), 133 deletions(-) diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/IndexedDataVector.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/IndexedDataVector.h index a73ba2f16b..9231813d36 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/IndexedDataVector.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/IndexedDataVector.h @@ -8,160 +8,157 @@ #pragma once -#include #include +#include -namespace AZ +namespace AZ::Render { - namespace Render + // Growable vector that leverages indirection to support erasure of elements while maintaining + // resident data in a densely packed region of memory. Useful as a backing store for growable + // buffers intended to be uploaded to the GPU for example. + template + class IndexedDataVector { - // Growable vector that leverages indirection to support erasure of elements while maintaining - // resident data in a densely packed region of memory. Useful as a backing store for growable - // buffers intended to be uploaded to the GPU for example. - template - class IndexedDataVector - { - public: - IndexedDataVector(); - explicit IndexedDataVector(size_t initialReservedSize); - ~IndexedDataVector() = default; - - static constexpr IndexType NoFreeSlot = std::numeric_limits::max(); - IndexType m_firstFreeSlot = NoFreeSlot; - - void Clear(); - IndexType GetFreeSlotIndex(); - void RemoveIndex(IndexType index); - - DataType& GetData(IndexType index); - const DataType& GetData(IndexType index) const; - size_t GetDataCount() const; - - AZStd::vector& GetDataVector(); - const AZStd::vector& GetDataVector() const; - - IndexType GetRawIndex(IndexType index) const; - - private: - constexpr static size_t InitialReservedSize = 128; - - // Stores data indices and an embedded free list - AZStd::vector m_indices; - // Stores the indirection index - AZStd::vector m_dataToIndices; - AZStd::vector m_data; - }; - - template - inline IndexedDataVector::IndexedDataVector() - : IndexedDataVector(InitialReservedSize) - { - } + public: + IndexedDataVector(); + explicit IndexedDataVector(size_t initialReservedSize); + ~IndexedDataVector() = default; - template - inline IndexedDataVector::IndexedDataVector(size_t initialReservedSize) - { - m_dataToIndices.reserve(initialReservedSize); - m_indices.reserve(initialReservedSize); - m_data.reserve(initialReservedSize); - } + static constexpr IndexType NoFreeSlot = std::numeric_limits::max(); + IndexType m_firstFreeSlot = NoFreeSlot; - template - inline void IndexedDataVector::Clear() - { - m_dataToIndices.clear(); - m_indices.clear(); - m_data.clear(); + void Clear(); + IndexType GetFreeSlotIndex(); + void RemoveIndex(IndexType index); - m_firstFreeSlot = NoFreeSlot; - } + DataType& GetData(IndexType index); + const DataType& GetData(IndexType index) const; + size_t GetDataCount() const; - template - inline IndexType IndexedDataVector::GetFreeSlotIndex() - { - IndexType freeSlotIndex = static_cast(m_indices.size()); - - if (freeSlotIndex == NoFreeSlot) - { - // the vector is full - return NoFreeSlot; - } - - if (m_firstFreeSlot == NoFreeSlot) - { - // If there's no free slot, add on to the end. - m_indices.push_back(freeSlotIndex); - } - else - { - // Fill the free slot. m_indices uses it's empty slots to store a linked list (via indices) to other empty slots. - freeSlotIndex = m_firstFreeSlot; - m_firstFreeSlot = m_indices.at(m_firstFreeSlot); - m_indices.at(freeSlotIndex) = static_cast(m_data.size()); - } - - // The data itself is always packed and m_indices points at it, so push a new entry to the back. - m_data.push_back(DataType()); - m_dataToIndices.push_back(freeSlotIndex); - - return freeSlotIndex; - } + AZStd::vector& GetDataVector(); + const AZStd::vector& GetDataVector() const; - template - inline void IndexedDataVector::RemoveIndex(IndexType index) - { - IndexType dataIndex = m_indices.at(index); + IndexType GetRawIndex(IndexType index) const; - // Copy the back light on top of this one. - m_data.at(dataIndex) = m_data.back(); - m_dataToIndices.at(dataIndex) = m_dataToIndices.back(); + private: + constexpr static size_t InitialReservedSize = 128; - // Update the index of the moved light - m_indices.at(m_dataToIndices.at(dataIndex)) = dataIndex; + // Stores data indices and an embedded free list + AZStd::vector m_indices; + // Stores the indirection index + AZStd::vector m_dataToIndices; + AZStd::vector m_data; + }; - // Pop the back - m_data.pop_back(); - m_dataToIndices.pop_back(); + template + inline IndexedDataVector::IndexedDataVector() + : IndexedDataVector(InitialReservedSize) + { + } - // Use free slot to link to next free slot - m_indices.at(index) = m_firstFreeSlot; - m_firstFreeSlot = index; - } + template + inline IndexedDataVector::IndexedDataVector(size_t initialReservedSize) + { + m_dataToIndices.reserve(initialReservedSize); + m_indices.reserve(initialReservedSize); + m_data.reserve(initialReservedSize); + } - template - inline DataType& IndexedDataVector::GetData(IndexType index) - { - return m_data.at(m_indices.at(index)); - } + template + inline void IndexedDataVector::Clear() + { + m_dataToIndices.clear(); + m_indices.clear(); + m_data.clear(); - template - inline const DataType& IndexedDataVector::GetData(IndexType index) const - { - return m_data.at(m_indices.at(index)); - } + m_firstFreeSlot = NoFreeSlot; + } - template - inline size_t IndexedDataVector::GetDataCount() const - { - return m_data.size(); - } + template + inline IndexType IndexedDataVector::GetFreeSlotIndex() + { + IndexType freeSlotIndex = static_cast(m_indices.size()); - template - inline AZStd::vector& IndexedDataVector::GetDataVector() + if (freeSlotIndex == NoFreeSlot) { - return m_data; + // the vector is full + return NoFreeSlot; } - template - inline const AZStd::vector& IndexedDataVector::GetDataVector() const + if (m_firstFreeSlot == NoFreeSlot) { - return m_data; + // If there's no free slot, add on to the end. + m_indices.push_back(freeSlotIndex); } - - template - IndexType IndexedDataVector::GetRawIndex(IndexType index) const + else { - return m_indices.at(index); + // Fill the free slot. m_indices uses it's empty slots to store a linked list (via indices) to other empty slots. + freeSlotIndex = m_firstFreeSlot; + m_firstFreeSlot = m_indices.at(m_firstFreeSlot); + m_indices.at(freeSlotIndex) = static_cast(m_data.size()); } - } // namespace Render -} // namespace AZ + + // The data itself is always packed and m_indices points at it, so push a new entry to the back. + m_data.push_back(DataType()); + m_dataToIndices.push_back(freeSlotIndex); + + return freeSlotIndex; + } + + template + inline void IndexedDataVector::RemoveIndex(IndexType index) + { + IndexType dataIndex = m_indices.at(index); + + // Copy the back light on top of this one. + m_data.at(dataIndex) = m_data.back(); + m_dataToIndices.at(dataIndex) = m_dataToIndices.back(); + + // Update the index of the moved light + m_indices.at(m_dataToIndices.at(dataIndex)) = dataIndex; + + // Pop the back + m_data.pop_back(); + m_dataToIndices.pop_back(); + + // Use free slot to link to next free slot + m_indices.at(index) = m_firstFreeSlot; + m_firstFreeSlot = index; + } + + template + inline DataType& IndexedDataVector::GetData(IndexType index) + { + return m_data.at(m_indices.at(index)); + } + + template + inline const DataType& IndexedDataVector::GetData(IndexType index) const + { + return m_data.at(m_indices.at(index)); + } + + template + inline size_t IndexedDataVector::GetDataCount() const + { + return m_data.size(); + } + + template + inline AZStd::vector& IndexedDataVector::GetDataVector() + { + return m_data; + } + + template + inline const AZStd::vector& IndexedDataVector::GetDataVector() const + { + return m_data; + } + + template + IndexType IndexedDataVector::GetRawIndex(IndexType index) const + { + return m_indices.at(index); + } +} // namespace AZ::Render From 68a7a21e62f31633b3ab0f7b0c7f0476188549f4 Mon Sep 17 00:00:00 2001 From: Jeremy Ong Date: Sat, 31 Jul 2021 00:25:53 -0600 Subject: [PATCH 144/160] Reintroduce .h and .inl split Signed-off-by: Jeremy Ong --- .../Atom/Feature/Utils/IndexedDataVector.h | 117 +-------------- .../Atom/Feature/Utils/IndexedDataVector.inl | 134 ++++++++++++++++++ .../Code/atom_feature_common_files.cmake | 1 + 3 files changed, 140 insertions(+), 112 deletions(-) create mode 100644 Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/IndexedDataVector.inl diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/IndexedDataVector.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/IndexedDataVector.h index 9231813d36..37835bd6a8 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/IndexedDataVector.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/IndexedDataVector.h @@ -38,6 +38,9 @@ namespace AZ::Render AZStd::vector& GetDataVector(); const AZStd::vector& GetDataVector() const; + AZStd::vector& GetIndexVector(); + const AZStd::vector& GetIndexVector() const; + IndexType GetRawIndex(IndexType index) const; private: @@ -49,116 +52,6 @@ namespace AZ::Render AZStd::vector m_dataToIndices; AZStd::vector m_data; }; - - template - inline IndexedDataVector::IndexedDataVector() - : IndexedDataVector(InitialReservedSize) - { - } - - template - inline IndexedDataVector::IndexedDataVector(size_t initialReservedSize) - { - m_dataToIndices.reserve(initialReservedSize); - m_indices.reserve(initialReservedSize); - m_data.reserve(initialReservedSize); - } - - template - inline void IndexedDataVector::Clear() - { - m_dataToIndices.clear(); - m_indices.clear(); - m_data.clear(); - - m_firstFreeSlot = NoFreeSlot; - } - - template - inline IndexType IndexedDataVector::GetFreeSlotIndex() - { - IndexType freeSlotIndex = static_cast(m_indices.size()); - - if (freeSlotIndex == NoFreeSlot) - { - // the vector is full - return NoFreeSlot; - } - - if (m_firstFreeSlot == NoFreeSlot) - { - // If there's no free slot, add on to the end. - m_indices.push_back(freeSlotIndex); - } - else - { - // Fill the free slot. m_indices uses it's empty slots to store a linked list (via indices) to other empty slots. - freeSlotIndex = m_firstFreeSlot; - m_firstFreeSlot = m_indices.at(m_firstFreeSlot); - m_indices.at(freeSlotIndex) = static_cast(m_data.size()); - } - - // The data itself is always packed and m_indices points at it, so push a new entry to the back. - m_data.push_back(DataType()); - m_dataToIndices.push_back(freeSlotIndex); - - return freeSlotIndex; - } - - template - inline void IndexedDataVector::RemoveIndex(IndexType index) - { - IndexType dataIndex = m_indices.at(index); - - // Copy the back light on top of this one. - m_data.at(dataIndex) = m_data.back(); - m_dataToIndices.at(dataIndex) = m_dataToIndices.back(); - - // Update the index of the moved light - m_indices.at(m_dataToIndices.at(dataIndex)) = dataIndex; - - // Pop the back - m_data.pop_back(); - m_dataToIndices.pop_back(); - - // Use free slot to link to next free slot - m_indices.at(index) = m_firstFreeSlot; - m_firstFreeSlot = index; - } - - template - inline DataType& IndexedDataVector::GetData(IndexType index) - { - return m_data.at(m_indices.at(index)); - } - - template - inline const DataType& IndexedDataVector::GetData(IndexType index) const - { - return m_data.at(m_indices.at(index)); - } - - template - inline size_t IndexedDataVector::GetDataCount() const - { - return m_data.size(); - } - - template - inline AZStd::vector& IndexedDataVector::GetDataVector() - { - return m_data; - } - - template - inline const AZStd::vector& IndexedDataVector::GetDataVector() const - { - return m_data; - } - - template - IndexType IndexedDataVector::GetRawIndex(IndexType index) const - { - return m_indices.at(index); - } } // namespace AZ::Render + +#include diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/IndexedDataVector.inl b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/IndexedDataVector.inl new file mode 100644 index 0000000000..076caad7f4 --- /dev/null +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/IndexedDataVector.inl @@ -0,0 +1,134 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +namespace AZ::Render +{ + template + inline IndexedDataVector::IndexedDataVector() + : IndexedDataVector(InitialReservedSize) + { + } + + template + inline IndexedDataVector::IndexedDataVector(size_t initialReservedSize) + { + m_dataToIndices.reserve(initialReservedSize); + m_indices.reserve(initialReservedSize); + m_data.reserve(initialReservedSize); + } + + template + inline void IndexedDataVector::Clear() + { + m_dataToIndices.clear(); + m_indices.clear(); + m_data.clear(); + + m_firstFreeSlot = NoFreeSlot; + } + + template + inline IndexType IndexedDataVector::GetFreeSlotIndex() + { + IndexType freeSlotIndex = static_cast(m_indices.size()); + + if (freeSlotIndex == NoFreeSlot) + { + // the vector is full + return NoFreeSlot; + } + + if (m_firstFreeSlot == NoFreeSlot) + { + // If there's no free slot, add on to the end. + m_indices.push_back(freeSlotIndex); + } + else + { + // Fill the free slot. m_indices uses it's empty slots to store a linked list (via indices) to other empty slots. + freeSlotIndex = m_firstFreeSlot; + m_firstFreeSlot = m_indices.at(m_firstFreeSlot); + m_indices.at(freeSlotIndex) = static_cast(m_data.size()); + } + + // The data itself is always packed and m_indices points at it, so push a new entry to the back. + m_data.push_back(DataType()); + m_dataToIndices.push_back(freeSlotIndex); + + return freeSlotIndex; + } + + template + inline void IndexedDataVector::RemoveIndex(IndexType index) + { + IndexType dataIndex = m_indices.at(index); + + // Copy the back light on top of this one. + m_data.at(dataIndex) = m_data.back(); + m_dataToIndices.at(dataIndex) = m_dataToIndices.back(); + + // Update the index of the moved light + m_indices.at(m_dataToIndices.at(dataIndex)) = dataIndex; + + // Pop the back + m_data.pop_back(); + m_dataToIndices.pop_back(); + + // Use free slot to link to next free slot + m_indices.at(index) = m_firstFreeSlot; + m_firstFreeSlot = index; + } + + template + inline DataType& IndexedDataVector::GetData(IndexType index) + { + return m_data.at(m_indices.at(index)); + } + + template + inline const DataType& IndexedDataVector::GetData(IndexType index) const + { + return m_data.at(m_indices.at(index)); + } + + template + inline size_t IndexedDataVector::GetDataCount() const + { + return m_data.size(); + } + + template + inline AZStd::vector& IndexedDataVector::GetDataVector() + { + return m_data; + } + + template + inline const AZStd::vector& IndexedDataVector::GetDataVector() const + { + return m_data; + } + + template + inline AZStd::vector& IndexedDataVector::GetIndexVector() + { + return m_dataToIndices; + } + + template + inline const AZStd::vector& IndexedDataVector::GetIndexVector() const + { + return m_dataToIndices; + } + + template + IndexType IndexedDataVector::GetRawIndex(IndexType index) const + { + return m_indices.at(index); + } +} // namespace AZ::Render diff --git a/Gems/Atom/Feature/Common/Code/atom_feature_common_files.cmake b/Gems/Atom/Feature/Common/Code/atom_feature_common_files.cmake index e4a914ac34..40188109ca 100644 --- a/Gems/Atom/Feature/Common/Code/atom_feature_common_files.cmake +++ b/Gems/Atom/Feature/Common/Code/atom_feature_common_files.cmake @@ -38,6 +38,7 @@ set(FILES Include/Atom/Feature/Utils/FrameCaptureBus.h Include/Atom/Feature/Utils/GpuBufferHandler.h Include/Atom/Feature/Utils/IndexedDataVector.h + Include/Atom/Feature/Utils/IndexedDataVector.inl Include/Atom/Feature/Utils/MultiIndexedDataVector.h Include/Atom/Feature/Utils/MultiSparseVector.h Include/Atom/Feature/Utils/ProfilingCaptureBus.h From b46a80be2cd3313dae12c387918ec955406be533 Mon Sep 17 00:00:00 2001 From: Steve Pham <82231385+spham-amzn@users.noreply.github.com> Date: Sat, 31 Jul 2021 08:42:02 -0700 Subject: [PATCH 145/160] Fix for Linux/Vulkan/Editor crash on startup * Temporary fix for Linux/Vulkan/XCB where the swap chain is not ready to present until the resize is complete * Fix invalid GUID from LinuxXcbConnectionManager Signed-off-by: spham-amzn --- .../Linux/AzFramework/API/ApplicationAPI_Linux.h | 2 +- Gems/Atom/RHI/Code/Include/Atom/RHI/SwapChain.h | 9 +++++++++ Gems/Atom/RHI/Code/Source/RHI/SwapChain.cpp | 4 ++++ Gems/Atom/RHI/Vulkan/Code/Source/RHI/CommandQueue.cpp | 9 +++++++++ 4 files changed, 23 insertions(+), 1 deletion(-) diff --git a/Code/Framework/AzFramework/Platform/Linux/AzFramework/API/ApplicationAPI_Linux.h b/Code/Framework/AzFramework/Platform/Linux/AzFramework/API/ApplicationAPI_Linux.h index 03c65ce0c3..9b57d1d49e 100644 --- a/Code/Framework/AzFramework/Platform/Linux/AzFramework/API/ApplicationAPI_Linux.h +++ b/Code/Framework/AzFramework/Platform/Linux/AzFramework/API/ApplicationAPI_Linux.h @@ -35,7 +35,7 @@ namespace AzFramework class LinuxXcbConnectionManager { public: - AZ_RTTI(LinuxXcbConnectionManager, "{649951316-3626-4C9D-9DCA-2E7ABF84C0A9}"); + AZ_RTTI(LinuxXcbConnectionManager, "{1F756E14-8D74-42FD-843C-4863307710DB}"); virtual ~LinuxXcbConnectionManager() = default; diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/SwapChain.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/SwapChain.h index 14e9968e42..c1fd4453d4 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/SwapChain.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/SwapChain.h @@ -81,6 +81,15 @@ namespace AZ AZ_RTTI(SwapChain, "{888B64A5-D956-406F-9C33-CF6A54FC41B0}", Object); +#if defined(PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB) + // On Linux platforms that uses XCB, a resize may occur in the swap chain but the command queue may still + // reference the original surface. This flag is a temporary fix to make sure that all the swap chains + // have finished their resize events before presenting the command queue. + + // [GFX TODO][GHI - 2678] + AZStd::atomic_bool m_resized{ false }; +#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB + protected: SwapChain(); diff --git a/Gems/Atom/RHI/Code/Source/RHI/SwapChain.cpp b/Gems/Atom/RHI/Code/Source/RHI/SwapChain.cpp index b0501d937d..5fbb83fccf 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/SwapChain.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/SwapChain.cpp @@ -164,6 +164,10 @@ namespace AZ m_currentImageIndex = 0; } +#if defined(PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB) + m_resized.store(true); +#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB + return resultCode; } diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/CommandQueue.cpp b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/CommandQueue.cpp index ca6c829cca..84b4964235 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/CommandQueue.cpp +++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/CommandQueue.cpp @@ -42,6 +42,15 @@ namespace AZ void CommandQueue::ExecuteWork(const RHI::ExecuteWorkRequest& rhiRequest) { +#if defined(PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB) + for (RHI::SwapChain* swapChain : rhiRequest.m_swapChainsToPresent) + { + if (!swapChain->m_resized) + { + return; + } + } +#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB const ExecuteWorkRequest& request = static_cast(rhiRequest); QueueCommand([=](void* queue) { From f9303a2eaa1b1efb9cf25be57e7e3b3cdc42465a Mon Sep 17 00:00:00 2001 From: Jeremy Ong Date: Sat, 31 Jul 2021 17:22:51 -0600 Subject: [PATCH 146/160] Add runtime RenderDoc support for Windows dx12/vulkan via --enableRenderDoc option - RenderDoc is disabled when building the monolithic build - The installation path is inferred on Windows, but may be overridden on Windows/Linux via the ATOM_RENDERDOC_PATH environment variable - Linux support may work, but I have no means to test it - Android support shouldn't be difficult to add, but requires a renderdoc_android.cmake file that understands how the RenderDoc package is distributed as part of the Android toolchain Signed-off-by: Jeremy Ong --- Gems/Atom/RHI/Code/CMakeLists.txt | 23 +++++++ Gems/Atom/RHI/Code/Include/Atom/RHI/Factory.h | 26 +++++++- .../Atom/RHI/Code/Include/Atom/RHI/RHIUtils.h | 3 + .../Code/Platform/Linux/renderdoc_linux.cmake | 36 ++++++++++ .../Platform/Windows/renderdoc_windows.cmake | 38 +++++++++++ Gems/Atom/RHI/Code/Source/RHI/Factory.cpp | 65 +++++++++++++++++++ Gems/Atom/RHI/Code/Source/RHI/RHIUtils.cpp | 12 ++++ 7 files changed, 202 insertions(+), 1 deletion(-) create mode 100644 Gems/Atom/RHI/Code/Platform/Linux/renderdoc_linux.cmake create mode 100644 Gems/Atom/RHI/Code/Platform/Windows/renderdoc_windows.cmake diff --git a/Gems/Atom/RHI/Code/CMakeLists.txt b/Gems/Atom/RHI/Code/CMakeLists.txt index 8e1ae3bdf0..82b80e5151 100644 --- a/Gems/Atom/RHI/Code/CMakeLists.txt +++ b/Gems/Atom/RHI/Code/CMakeLists.txt @@ -10,6 +10,23 @@ ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${P include(${pal_dir}/AtomRHITests_traits_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) +set(RENDERDOC_CMAKE ${CMAKE_CURRENT_SOURCE_DIR}/${pal_dir}/renderdoc_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) +if(EXISTS ${RENDERDOC_CMAKE}) + include(${RENDERDOC_CMAKE}) +endif() + +if(TARGET "3rdParty::renderdoc") + message(STATUS "Renderdoc found") + set(USE_RENDERDOC_DEFINE "USE_RENDERDOC") + set(RENDERDOC_BUILD_DEPENDENCY "3rdParty::renderdoc") + set(RENDERDOC_API_DEPENDENCY "3rdParty::renderdoc_api") +else() + message(STATUS "Renderdoc missing") + set(USE_RENDERDOC_DEFINE "") + set(RENDERDOC_BUILD_DEPENDENCY "") + set(RENDERDOC_API_DEPENDENCY "") +endif() + ly_add_target( NAME Atom_RHI.Reflect STATIC NAMESPACE Gem @@ -43,6 +60,12 @@ ly_add_target( AZ::AzCore AZ::AzFramework Gem::Atom_RHI.Reflect + ${RENDERDOC_BUILD_DEPENDENCY} + PUBLIC + ${RENDERDOC_API_DEPENDENCY} + COMPILE_DEFINITIONS + PUBLIC + ${USE_RENDERDOC_DEFINE} ) ly_add_target( diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/Factory.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/Factory.h index a9f9120e8d..24f09c6580 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/Factory.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/Factory.h @@ -11,6 +11,11 @@ #include #include +#if defined(USE_RENDERDOC) +#include +#include +#endif + namespace AZ { namespace RHI @@ -66,7 +71,7 @@ namespace AZ public: AZ_TYPE_INFO(Factory, "{2C0231FD-DD11-4154-A4F5-177181E26D8E}"); - Factory() = default; + Factory(); virtual ~Factory() = default; // Note that you have to delete these for safety reasons, you will trip a static_assert if you do not @@ -93,6 +98,25 @@ namespace AZ /// Access the global factory instance. static Factory& Get(); +#if defined(USE_RENDERDOC) +#if defined(AZ_PLATFORM_WINDOWS) + static const char* RENDERDOC_MODULE = "renderdoc.dll"; +#elif defined(AZ_PLATFORM_LINUX) + static const char* RENDERDOC_MODULE = "librenderdoc.so"; +#elif defined(AZ_PLATFORM_ANDROID) + static const char* RENDERDOC_MODULE = "libVkLayer_GLES_RenderDoc.so" +#else + static const char* RENDERDOC_MODULE = nullptr; +#endif + + /// Access the RenderDoc API pointer if available. + /// The availability of the render doc API at runtime depends on the following: + /// - You must not be building a packaged game/product (LY_MONOLITHIC_GAME not enabled in CMake) + /// - A valid renderdoc installation was found, either by auto-discovery, or by supplying ATOM_RENDERDOC_PATH as an environment variable + /// - The module loaded successfully at runtime, and the API function pointer was retrieved successfully + static RENDERDOC_API_1_1_2* GetRenderDocAPI(); +#endif + /// Returns the name of the Factory. virtual Name GetName() = 0; diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/RHIUtils.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/RHIUtils.h index 68d92a77bb..73e8e1ad56 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/RHIUtils.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/RHIUtils.h @@ -37,6 +37,9 @@ namespace AZ //! If multiple values exist it will return the last one AZStd::string GetCommandLineValue(const AZStd::string& commandLineOption); + //! Returns true if the command line option is set + bool QueryCommandLineOption(const AZStd::string& commandLineOption); + //! Returns if the current bakcend is a null renderer bool IsNullRenderer(); } diff --git a/Gems/Atom/RHI/Code/Platform/Linux/renderdoc_linux.cmake b/Gems/Atom/RHI/Code/Platform/Linux/renderdoc_linux.cmake new file mode 100644 index 0000000000..0faccf80ec --- /dev/null +++ b/Gems/Atom/RHI/Code/Platform/Linux/renderdoc_linux.cmake @@ -0,0 +1,36 @@ +# +# Copyright (c) Contributors to the Open 3D Engine Project. +# For complete copyright and license terms please see the LICENSE at the root of this distribution. +# +# SPDX-License-Identifier: Apache-2.0 OR MIT +# +# + +# Prevent bundling the renderdoc dll with a packaged title +if(NOT LY_MONOLITHIC_GAME) + if(DEFINED ENV{"ATOM_RENDERDOC_PATH"}) + set(RENDERDOC_PATH ENV{"ATOM_RENDERDOC_PATH"}) + endif() + + if(RENDERDOC_PATH) + # Normalize file path + file(TO_CMAKE_PATH "${RENDERDOC_PATH}" RENDERDOC_PATH) + + if(EXISTS "${RENDERDOC_PATH}/librenderdoc.so") + ly_add_external_target( + NAME renderdoc + VERSION + 3RDPARTY_ROOT_DIRECTORY ${RENDERDOC_PATH} + INCLUDE_DIRECTORIES "." + RUNTIME_DEPENDENCIES "${RENDERDOC_PATH}/librenderdoc.so" + ) + + ly_add_external_target( + NAME renderdoc_api + VERSION + 3RDPARTY_ROOT_DIRECTORY ${RENDERDOC_PATH} + INCLUDE_DIRECTORIES "." + ) + endif() + endif() +endif() \ No newline at end of file diff --git a/Gems/Atom/RHI/Code/Platform/Windows/renderdoc_windows.cmake b/Gems/Atom/RHI/Code/Platform/Windows/renderdoc_windows.cmake new file mode 100644 index 0000000000..499321b2ab --- /dev/null +++ b/Gems/Atom/RHI/Code/Platform/Windows/renderdoc_windows.cmake @@ -0,0 +1,38 @@ +# +# Copyright (c) Contributors to the Open 3D Engine Project. +# For complete copyright and license terms please see the LICENSE at the root of this distribution. +# +# SPDX-License-Identifier: Apache-2.0 OR MIT +# +# + +# Prevent bundling the renderdoc dll with a packaged title +if(NOT LY_MONOLITHIC_GAME) + # Common installation path for renderdoc path + set(RENDERDOC_PATH "C:/Program Files/RenderDoc") + if(DEFINED ENV{"ATOM_RENDERDOC_PATH"}) + set(RENDERDOC_PATH ENV{"ATOM_RENDERDOC_PATH"}) + endif() + + if(RENDERDOC_PATH) + # Normalize file path + file(TO_CMAKE_PATH "${RENDERDOC_PATH}" RENDERDOC_PATH) + + if(EXISTS "${RENDERDOC_PATH}/renderdoc.dll") + ly_add_external_target( + NAME renderdoc + VERSION + 3RDPARTY_ROOT_DIRECTORY ${RENDERDOC_PATH} + INCLUDE_DIRECTORIES "." + RUNTIME_DEPENDENCIES "${RENDERDOC_PATH}/renderdoc.dll" + ) + + ly_add_external_target( + NAME renderdoc_api + VERSION + 3RDPARTY_ROOT_DIRECTORY ${RENDERDOC_PATH} + INCLUDE_DIRECTORIES "." + ) + endif() + endif() +endif() \ No newline at end of file diff --git a/Gems/Atom/RHI/Code/Source/RHI/Factory.cpp b/Gems/Atom/RHI/Code/Source/RHI/Factory.cpp index 974d63f88b..8e4a96158f 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/Factory.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/Factory.cpp @@ -11,6 +11,15 @@ #include #include +#if defined(USE_RENDERDOC) +#include +#include + +static AZStd::unique_ptr s_renderDocModule; +static RENDERDOC_API_1_1_2* s_renderDocApi = nullptr; +#endif + + namespace AZ { namespace RHI @@ -30,6 +39,48 @@ namespace AZ return AZ_CRC("RHIPlatformService", 0xfff2cea4); } + Factory::Factory() + { +#if defined(USE_RENDERDOC) + // If RenderDoc is requested, we need to load the library as early as possible (before device queries/factories are made) + bool enableRenderDoc = RHI::QueryCommandLineOption("enableRenderDoc"); + + if (enableRenderDoc && RENDERDOC_MODULE && !s_renderDocModule) + { + s_renderDocModule = DynamicModuleHandle::Create(RENDERDOC_MODULE); + if (s_renderDocModule) + { + if (s_renderDocModule->Load(false)) + { + pRENDERDOC_GetAPI renderDocGetAPI = s_renderDocModule->GetFunction("RENDERDOC_GetAPI"); + if (renderDocGetAPI) + { + if (!renderDocGetAPI(eRENDERDOC_API_Version_1_1_2, reinterpret_cast(&s_renderDocApi))) + { + s_renderDocApi = nullptr; + } + } + + if (s_renderDocApi) + { + // Prevent RenderDoc from handling any exceptions that may interfere with the O3DE exception handler + s_renderDocApi->UnloadCrashHandler(); + } + else + { + AZ_Printf("RHISystem", "RenderDoc module loaded but failed to retrieve API function pointer.\n"); + } + } + else + { + AZ_Printf("RHISystem", "RenderDoc module requested but module failed to load.\n"); + } + } + } +#endif // defined(USE_RENDERDOC) + + } + void Factory::Register(Factory* instance) { Interface::Register(instance); @@ -58,6 +109,13 @@ namespace AZ ResourceInvalidateBus::ClearQueuedEvents(); Interface::Unregister(instance); + +#if defined(USE_RENDERDOC) + if (s_renderDocModule) + { + s_renderDocModule->Unload(); + } +#endif } bool Factory::IsReady() @@ -71,5 +129,12 @@ namespace AZ AZ_Assert(factory, "RHI::Factory is not connected to a platform. Call IsReady() to get the status of the platform. A null de-reference is imminent."); return *factory; } + +#if defined(USE_RENDERDOC) + RENDERDOC_API_1_1_2* Factory::GetRenderDocAPI() + { + return s_renderDocApi; + } +#endif } } diff --git a/Gems/Atom/RHI/Code/Source/RHI/RHIUtils.cpp b/Gems/Atom/RHI/Code/Source/RHI/RHIUtils.cpp index 8df5e5b5be..bc4cde9406 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/RHIUtils.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/RHIUtils.cpp @@ -122,5 +122,17 @@ namespace AZ } return commandLineValue; } + + bool QueryCommandLineOption(const AZStd::string& commandLineOption) + { + const AzFramework::CommandLine* commandLine = nullptr; + AzFramework::ApplicationRequests::Bus::BroadcastResult(commandLine, &AzFramework::ApplicationRequests::GetApplicationCommandLine); + + if (commandLine) + { + return commandLine->HasSwitch(commandLineOption); + } + return false; + } } } From b5895bc09bd8e7b6db1f6be45012127adfba8746 Mon Sep 17 00:00:00 2001 From: rgba16f <82187279+rgba16f@users.noreply.github.com> Date: Fri, 30 Jul 2021 18:46:56 -0500 Subject: [PATCH 147/160] Move most AZ::Job function bodies out of the header Signed-off-by: rgba16f <82187279+rgba16f@users.noreply.github.com> --- Code/Framework/AzCore/AzCore/Jobs/Job.cpp | 309 +++++++++++++++++ Code/Framework/AzCore/AzCore/Jobs/Job.h | 324 +----------------- .../AzCore/AzCore/azcore_files.cmake | 1 + 3 files changed, 323 insertions(+), 311 deletions(-) create mode 100644 Code/Framework/AzCore/AzCore/Jobs/Job.cpp diff --git a/Code/Framework/AzCore/AzCore/Jobs/Job.cpp b/Code/Framework/AzCore/AzCore/Jobs/Job.cpp new file mode 100644 index 0000000000..66493e193b --- /dev/null +++ b/Code/Framework/AzCore/AzCore/Jobs/Job.cpp @@ -0,0 +1,309 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ +#include +#include +#include +#include +#include +#include + +AZ::Job::Job(bool isAutoDelete, AZ::JobContext* context, bool isCompletion, AZ::s8 priority) +{ + if (context) + { + m_context = context; + } + else + { + m_context = JobContext::GetParentContext(); + } + + unsigned int countAndFlags = 1; + if (isAutoDelete) + { + countAndFlags |= (unsigned int)FLAG_AUTO_DELETE; + } + if (isCompletion) + { + countAndFlags |= (unsigned int)FLAG_COMPLETION; + } + countAndFlags |= (unsigned int)((priority << FLAG_PRIORITY_START_BIT) & FLAG_PRIORITY_MASK); + SetDependentCountAndFlags(countAndFlags); + StoreDependent(NULL); + +#ifdef AZ_DEBUG_JOB_STATE + SetState(STATE_SETUP); +#endif // AZ_DEBUG_JOB_STATE +} + +void AZ::Job::Start() +{ + //jobs are created with a count set to 1, we remove that count to allow the job to start +#ifdef AZ_DEBUG_JOB_STATE + AZ_Assert(m_state == STATE_SETUP, ("Jobs must be in the setup state before they can be started")); + SetState(STATE_STARTED); +#endif + DecrementDependentCount(); +} + +void AZ::Job::Reset(bool isClearDependent) +{ +#ifdef AZ_DEBUG_JOB_STATE + AZ_Assert((m_state == STATE_SETUP) || (m_state == STATE_PROCESSING), "Jobs must not be running when they are reset"); + SetState(STATE_SETUP); +#endif + unsigned int countAndFlags = GetDependentCountAndFlags(); + AZ_Assert((countAndFlags & (unsigned int)FLAG_AUTO_DELETE) == 0, "You can't call reset on AutoDelete jobs!"); + // Remove the FLAG_DEPENDENTCOUNT_MASK and FLAG_CHILD_JOBS flags + countAndFlags = (countAndFlags & (~(FLAG_DEPENDENTCOUNT_MASK) & ~(FLAG_CHILD_JOBS))) | 1; + SetDependentCountAndFlags(countAndFlags); + if (isClearDependent) + { + StoreDependent(NULL); + } + else + { + Job* dependent = GetDependent(); + if (dependent) + { +#ifdef AZ_DEBUG_JOB_STATE + AZ_Assert(dependent->m_state == STATE_SETUP, ("Dependent must be in setup state before it can be re-initialized")); +#endif + dependent->IncrementDependentCount(); + } + } +} + +void AZ::Job::SetDependent(Job* dependent) +{ + AZ_Assert(!GetDependent(), ("Job already has a dependent, should be cleared after the job is done")); +#ifdef AZ_DEBUG_JOB_STATE + AZ_Assert(m_state == STATE_SETUP, ("Dependent can only be set before the jobs are started")); + AZ_Assert(dependent->m_state == STATE_SETUP, ("Dependent must be in the setup state")); +#endif + dependent->IncrementDependentCount(); + StoreDependent(dependent); +} + +void AZ::Job::SetDependentStarted(Job* dependent) +{ + AZ_Assert(!GetDependent(), ("Job already has a dependent, should be cleared after the job is done")); +#ifdef AZ_DEBUG_JOB_STATE + AZ_Assert(m_state == STATE_SETUP, ("Dependent can only be set before the jobs are started")); + //We don't require the dependent to be in STATE_SETUP, the user can call this from a context where they + //know the dependent has not started yet, although it is in STATE_STARTED already, e.g. if SetDependent + //is called from a job which the dependent is already dependent on. + //Note that if the user gets this wrong, the dependent may start before this job is finished, and the asserts + //may not even trigger due to race conditions. Hence why this function is 'experts only'. + AZ_Assert((dependent->m_state == STATE_SETUP) || (dependent->m_state == STATE_STARTED) + || (dependent->m_state == STATE_SUSPENDED), "Dependent must be in the setup, started, or suspended state"); +#endif + dependent->IncrementDependentCount(); + StoreDependent(dependent); +} + +void AZ::Job::SetDependentChild(Job* dependent) +{ + AZ_Assert(!GetDependent(), ("Job already has a dependent, should be cleared after the job is done")); +#ifdef AZ_DEBUG_JOB_STATE + AZ_Assert(m_state == STATE_SETUP, ("Dependent can only be set before the jobs are started")); + AZ_Assert(dependent->m_state == STATE_PROCESSING, "Dependent must be processing to add a child"); +#endif + dependent->IncrementDependentCountAndSetChildFlag(); + StoreDependent(dependent); +} + +void AZ::Job::SetContinuation(Job* continuationJob) +{ +#ifdef AZ_DEBUG_JOB_STATE + AZ_Assert(m_state == STATE_PROCESSING, "Continuation jobs can only be set while we are processing, otherwise a regular dependent should be used"); +#endif + Job* dependent = GetDependent(); + if (dependent) //nothing to do if there is no dependent... doesn't usually happen, except with synchronous processing and assists + { + continuationJob->SetDependentStarted(dependent); + } +} + +void AZ::Job::StartAsChild(Job* childJob) +{ +#ifdef AZ_DEBUG_JOB_STATE + AZ_Assert(m_state == STATE_PROCESSING, "Child jobs can only be added while we are processing"); +#endif + childJob->SetDependentChild(this); + childJob->Start(); +} + +void AZ::Job::WaitForChildren() +{ +#ifdef AZ_DEBUG_JOB_STATE + AZ_Assert(m_state == STATE_PROCESSING, "We must be currently processing in order to suspend"); +#endif + if (GetDependentCount() != 0) + { +#ifdef AZ_DEBUG_JOB_STATE + SetState(STATE_SUSPENDED); +#endif // AZ_DEBUG_JOB_STATE + m_context->GetJobManager().SuspendJobUntilReady(this); +#ifdef AZ_DEBUG_JOB_STATE + SetState(STATE_PROCESSING); +#endif // AZ_DEBUG_JOB_STATE + } + AZ_Assert(GetDependentCount() == 0, "Suspended job has resumed, but still has non-zero dependent count, bug in JobManager?"); +} + +bool AZ::Job::IsCancelled() const +{ + JobCancelGroup* cancelGroup = m_context->GetCancelGroup(); + if (cancelGroup && cancelGroup->IsCancelled()) + { + if (!IsCompletion()) // always run completion jobs, as they can be holding a synchronization primitive + { + return true; + } + } + return false; +} + +bool AZ::Job::IsAutoDelete() const +{ + return (GetDependentCountAndFlags() & (unsigned int)FLAG_AUTO_DELETE) ? true : false; +} + +bool AZ::Job::IsCompletion() const +{ + return (GetDependentCountAndFlags() & (unsigned int)FLAG_COMPLETION) ? true : false; +} + +void AZ::Job::StartAndAssistUntilComplete() +{ + m_context->GetJobManager().StartJobAndAssistUntilComplete(this); +} + +void AZ::Job::StartAndWaitForCompletion() +{ + //check if we are in a worker thread or a general user thread + Job* currentJob = m_context->GetJobManager().GetCurrentJob(); + if (currentJob) + { + //worker thread, so just suspend this current job until the empty job completes + currentJob->StartAsChild(this); + currentJob->WaitForChildren(); + } + else + { + StartAndAssistUntilComplete(); + } +} + +unsigned int AZ::Job::GetDependentCount() const +{ + return (GetDependentCountAndFlags() & FLAG_DEPENDENTCOUNT_MASK); +} + +void AZ::Job::IncrementDependentCount() +{ + AZ_Assert(GetDependentCount() < FLAG_DEPENDENTCOUNT_MASK, "Dependent count overflow"); +#ifdef AZCORE_JOBS_IMPL_SYNCHRONOUS + ++m_dependentCountAndFlags; +#else + m_dependentCountAndFlags.fetch_add(1, AZStd::memory_order_acq_rel); +#endif +} + +void AZ::Job::IncrementDependentCountAndSetChildFlag() +{ + AZ_Assert(GetDependentCount() < FLAG_DEPENDENTCOUNT_MASK, "Dependent count overflow"); +#ifdef AZCORE_JOBS_IMPL_SYNCHRONOUS + int oldCount = m_dependentCountAndFlags & FLAG_DEPENDENTCOUNT_MASK; + m_dependentCountAndFlags = (m_dependentCountAndFlags & ~FLAG_DEPENDENTCOUNT_MASK) | (oldCount + 1) | FLAG_CHILD_JOBS; +#else + //use a single atomic operation to increment the count and set the child flag if possible + unsigned int oldCountAndFlags, newCountAndFlags; + do + { + oldCountAndFlags = m_dependentCountAndFlags.load(AZStd::memory_order_acquire); + int oldCount = oldCountAndFlags & FLAG_DEPENDENTCOUNT_MASK; + newCountAndFlags = (oldCountAndFlags & ~FLAG_DEPENDENTCOUNT_MASK) | (oldCount + 1) | FLAG_CHILD_JOBS; + } while (!m_dependentCountAndFlags.compare_exchange_weak(oldCountAndFlags, newCountAndFlags, AZStd::memory_order_acq_rel, AZStd::memory_order_acquire)); +#endif +} + +void AZ::Job::DecrementDependentCount() +{ +#ifdef AZ_DEBUG_JOB_STATE + AZ_Assert((m_state == STATE_SETUP) || (m_state == STATE_STARTED) + || (m_state == STATE_PROCESSING) || (m_state == STATE_SUSPENDED), //child jobs + "Job dependent count should not be decremented after job is already pending"); +#endif + AZ_Assert(GetDependentCount() > 0, ("Job dependent count is already zero")); +#ifdef AZCORE_JOBS_IMPL_SYNCHRONOUS + unsigned int countAndFlags = m_dependentCountAndFlags--; +#else + unsigned int countAndFlags = m_dependentCountAndFlags.fetch_sub(1, AZStd::memory_order_acq_rel); +#endif + unsigned int count = countAndFlags & FLAG_DEPENDENTCOUNT_MASK; + if (count == 1) + { + if (!(countAndFlags & FLAG_CHILD_JOBS)) + { +#ifdef AZ_DEBUG_JOB_STATE + AZ_Assert(m_state == STATE_STARTED, "Job has not been started but the dependent count is zero, must be a dependency error"); + SetState(STATE_PENDING); +#endif + m_context->GetJobManager().AddPendingJob(this); + } + } +} + +AZ::s8 AZ::Job::GetPriority() const +{ + return (GetDependentCountAndFlags() >> FLAG_PRIORITY_START_BIT) & 0xff; +} + +#ifdef AZCORE_JOBS_IMPL_SYNCHRONOUS +void AZ::Job::StoreDependent(Job* job) +{ + m_dependent = job; +} + +AZ::Job* AZ::Job::GetDependent() const +{ + return m_dependent; +} + +void AZ::Job::SetDependentCountAndFlags(unsigned int countAndFlags) +{ + m_dependentCountAndFlags = countAndFlags; +} + +unsigned int AZ::Job::GetDependentCountAndFlags() const +{ + return m_dependentCountAndFlags; +} +#else +void AZ::Job::StoreDependent(Job* job) +{ + m_dependent.store(job, AZStd::memory_order_release); +} + +AZ::Job* AZ::Job::GetDependent() const +{ + return m_dependent.load(AZStd::memory_order_acquire); +} + +void AZ::Job::SetDependentCountAndFlags(unsigned int countAndFlags) +{ + m_dependentCountAndFlags.store(countAndFlags, AZStd::memory_order_release); +} + +unsigned int AZ::Job::GetDependentCountAndFlags() const +{ + return m_dependentCountAndFlags.load(AZStd::memory_order_acquire); +} +#endif diff --git a/Code/Framework/AzCore/AzCore/Jobs/Job.h b/Code/Framework/AzCore/AzCore/Jobs/Job.h index 18c639e2c2..b6632dd063 100644 --- a/Code/Framework/AzCore/AzCore/Jobs/Job.h +++ b/Code/Framework/AzCore/AzCore/Jobs/Job.h @@ -5,15 +5,14 @@ * SPDX-License-Identifier: Apache-2.0 OR MIT * */ -#ifndef AZCORE_JOBS_JOB_H -#define AZCORE_JOBS_JOB_H 1 - -#include -#include -#include -#include -#include +#pragma once +#include +#include +#include +#include +#include + #include #if defined(_DEBUG) @@ -234,319 +233,22 @@ namespace AZ //would require atomic ops to set/read it, so not really worth it. int m_state; }; - - //============================================================================================================ - //============================================================================================================ - //============================================================================================================ - - inline Job::Job(bool isAutoDelete, JobContext* context, bool isCompletion, AZ::s8 priority) - { - if (context) - { - m_context = context; - } - else - { - m_context = JobContext::GetParentContext(); - } - - unsigned int countAndFlags = 1; - if (isAutoDelete) - { - countAndFlags |= (unsigned int)FLAG_AUTO_DELETE; - } - if (isCompletion) - { - countAndFlags |= (unsigned int)FLAG_COMPLETION; - } - countAndFlags |= (unsigned int)((priority << FLAG_PRIORITY_START_BIT) & FLAG_PRIORITY_MASK); - SetDependentCountAndFlags(countAndFlags); - StoreDependent(NULL); - -#ifdef AZ_DEBUG_JOB_STATE - SetState(STATE_SETUP); -#endif // AZ_DEBUG_JOB_STATE - } - - AZ_FORCE_INLINE void Job::Start() - { - //jobs are created with a count set to 1, we remove that count to allow the job to start -#ifdef AZ_DEBUG_JOB_STATE - AZ_Assert(m_state == STATE_SETUP, ("Jobs must be in the setup state before they can be started")); - SetState(STATE_STARTED); -#endif - DecrementDependentCount(); - } - - inline void Job::Reset(bool isClearDependent) - { -#ifdef AZ_DEBUG_JOB_STATE - AZ_Assert((m_state == STATE_SETUP) || (m_state == STATE_PROCESSING), "Jobs must not be running when they are reset"); - SetState(STATE_SETUP); -#endif - unsigned int countAndFlags = GetDependentCountAndFlags(); - AZ_Assert((countAndFlags & (unsigned int)FLAG_AUTO_DELETE) == 0, "You can't call reset on AutoDelete jobs!"); - // Remove the FLAG_DEPENDENTCOUNT_MASK and FLAG_CHILD_JOBS flags - countAndFlags = (countAndFlags & (~(FLAG_DEPENDENTCOUNT_MASK) & ~(FLAG_CHILD_JOBS))) | 1; - SetDependentCountAndFlags(countAndFlags); - if (isClearDependent) - { - StoreDependent(NULL); - } - else - { - Job* dependent = GetDependent(); - if (dependent) - { -#ifdef AZ_DEBUG_JOB_STATE - AZ_Assert(dependent->m_state == STATE_SETUP, ("Dependent must be in setup state before it can be re-initialized")); -#endif - dependent->IncrementDependentCount(); - } - } - } - - AZ_FORCE_INLINE void Job::SetDependent(Job* dependent) - { - AZ_Assert(!GetDependent(), ("Job already has a dependent, should be cleared after the job is done")); -#ifdef AZ_DEBUG_JOB_STATE - AZ_Assert(m_state == STATE_SETUP, ("Dependent can only be set before the jobs are started")); - AZ_Assert(dependent->m_state == STATE_SETUP, ("Dependent must be in the setup state")); -#endif - dependent->IncrementDependentCount(); - StoreDependent(dependent); - } - - AZ_FORCE_INLINE void Job::SetDependentStarted(Job* dependent) - { - AZ_Assert(!GetDependent(), ("Job already has a dependent, should be cleared after the job is done")); -#ifdef AZ_DEBUG_JOB_STATE - AZ_Assert(m_state == STATE_SETUP, ("Dependent can only be set before the jobs are started")); - //We don't require the dependent to be in STATE_SETUP, the user can call this from a context where they - //know the dependent has not started yet, although it is in STATE_STARTED already, e.g. if SetDependent - //is called from a job which the dependent is already dependent on. - //Note that if the user gets this wrong, the dependent may start before this job is finished, and the asserts - //may not even trigger due to race conditions. Hence why this function is 'experts only'. - AZ_Assert((dependent->m_state == STATE_SETUP) || (dependent->m_state == STATE_STARTED) - || (dependent->m_state == STATE_SUSPENDED), "Dependent must be in the setup, started, or suspended state"); -#endif - dependent->IncrementDependentCount(); - StoreDependent(dependent); - } - - AZ_FORCE_INLINE void Job::SetDependentChild(Job* dependent) - { - AZ_Assert(!GetDependent(), ("Job already has a dependent, should be cleared after the job is done")); -#ifdef AZ_DEBUG_JOB_STATE - AZ_Assert(m_state == STATE_SETUP, ("Dependent can only be set before the jobs are started")); - AZ_Assert(dependent->m_state == STATE_PROCESSING, "Dependent must be processing to add a child"); -#endif - dependent->IncrementDependentCountAndSetChildFlag(); - StoreDependent(dependent); - } - - AZ_FORCE_INLINE void Job::SetContinuation(Job* continuationJob) - { -#ifdef AZ_DEBUG_JOB_STATE - AZ_Assert(m_state == STATE_PROCESSING, "Continuation jobs can only be set while we are processing, otherwise a regular dependent should be used"); -#endif - Job* dependent = GetDependent(); - if (dependent) //nothing to do if there is no dependent... doesn't usually happen, except with synchronous processing and assists - { - continuationJob->SetDependentStarted(dependent); - } - } - - AZ_FORCE_INLINE void Job::StartAsChild(Job* childJob) - { -#ifdef AZ_DEBUG_JOB_STATE - AZ_Assert(m_state == STATE_PROCESSING, "Child jobs can only be added while we are processing"); -#endif - childJob->SetDependentChild(this); - childJob->Start(); - } - - AZ_FORCE_INLINE void Job::WaitForChildren() - { -#ifdef AZ_DEBUG_JOB_STATE - AZ_Assert(m_state == STATE_PROCESSING, "We must be currently processing in order to suspend"); -#endif - if (GetDependentCount() != 0) - { -#ifdef AZ_DEBUG_JOB_STATE - SetState(STATE_SUSPENDED); -#endif // AZ_DEBUG_JOB_STATE - m_context->GetJobManager().SuspendJobUntilReady(this); -#ifdef AZ_DEBUG_JOB_STATE - SetState(STATE_PROCESSING); -#endif // AZ_DEBUG_JOB_STATE - } - AZ_Assert(GetDependentCount() == 0, "Suspended job has resumed, but still has non-zero dependent count, bug in JobManager?"); - } - - AZ_FORCE_INLINE bool Job::IsCancelled() const - { - JobCancelGroup* cancelGroup = m_context->GetCancelGroup(); - if (cancelGroup && cancelGroup->IsCancelled()) - { - if (!IsCompletion()) // always run completion jobs, as they can be holding a synchronization primitive - { - return true; - } - } - return false; - } - - AZ_FORCE_INLINE bool Job::IsAutoDelete() const - { - return (GetDependentCountAndFlags() & (unsigned int)FLAG_AUTO_DELETE) ? true : false; - } - - AZ_FORCE_INLINE bool Job::IsCompletion() const - { - return (GetDependentCountAndFlags() & (unsigned int)FLAG_COMPLETION) ? true : false; - } - - AZ_FORCE_INLINE void Job::StartAndAssistUntilComplete() - { - m_context->GetJobManager().StartJobAndAssistUntilComplete(this); - } - - inline void Job::StartAndWaitForCompletion() - { - //check if we are in a worker thread or a general user thread - Job* currentJob = m_context->GetJobManager().GetCurrentJob(); - if (currentJob) - { - //worker thread, so just suspend this current job until the empty job completes - currentJob->StartAsChild(this); - currentJob->WaitForChildren(); - } - else - { - StartAndAssistUntilComplete(); - } - } - - AZ_FORCE_INLINE JobContext* Job::GetContext() const + + ////////////////////////////////////////////////////////////////////////////////////////////////////// + // Inline implementations + inline JobContext* Job::GetContext() const { return m_context; } - AZ_FORCE_INLINE unsigned int Job::GetDependentCount() const - { - return (GetDependentCountAndFlags() & FLAG_DEPENDENTCOUNT_MASK); - } - - AZ_FORCE_INLINE void Job::IncrementDependentCount() - { - AZ_Assert(GetDependentCount() < FLAG_DEPENDENTCOUNT_MASK, "Dependent count overflow"); -#ifdef AZCORE_JOBS_IMPL_SYNCHRONOUS - ++m_dependentCountAndFlags; -#else - m_dependentCountAndFlags.fetch_add(1, AZStd::memory_order_acq_rel); -#endif - } - - inline void Job::IncrementDependentCountAndSetChildFlag() - { - AZ_Assert(GetDependentCount() < FLAG_DEPENDENTCOUNT_MASK, "Dependent count overflow"); -#ifdef AZCORE_JOBS_IMPL_SYNCHRONOUS - int oldCount = m_dependentCountAndFlags & FLAG_DEPENDENTCOUNT_MASK; - m_dependentCountAndFlags = (m_dependentCountAndFlags & ~FLAG_DEPENDENTCOUNT_MASK) | (oldCount + 1) | FLAG_CHILD_JOBS; -#else - //use a single atomic operation to increment the count and set the child flag if possible - unsigned int oldCountAndFlags, newCountAndFlags; - do - { - oldCountAndFlags = m_dependentCountAndFlags.load(AZStd::memory_order_acquire); - int oldCount = oldCountAndFlags & FLAG_DEPENDENTCOUNT_MASK; - newCountAndFlags = (oldCountAndFlags & ~FLAG_DEPENDENTCOUNT_MASK) | (oldCount + 1) | FLAG_CHILD_JOBS; - } while (!m_dependentCountAndFlags.compare_exchange_weak(oldCountAndFlags, newCountAndFlags, AZStd::memory_order_acq_rel, AZStd::memory_order_acquire)); -#endif - } - - inline void Job::DecrementDependentCount() - { -#ifdef AZ_DEBUG_JOB_STATE - AZ_Assert((m_state == STATE_SETUP) || (m_state == STATE_STARTED) - || (m_state == STATE_PROCESSING) || (m_state == STATE_SUSPENDED), //child jobs - "Job dependent count should not be decremented after job is already pending"); -#endif - AZ_Assert(GetDependentCount() > 0, ("Job dependent count is already zero")); -#ifdef AZCORE_JOBS_IMPL_SYNCHRONOUS - unsigned int countAndFlags = m_dependentCountAndFlags--; -#else - unsigned int countAndFlags = m_dependentCountAndFlags.fetch_sub(1, AZStd::memory_order_acq_rel); -#endif - unsigned int count = countAndFlags & FLAG_DEPENDENTCOUNT_MASK; - if (count == 1) - { - if (!(countAndFlags & FLAG_CHILD_JOBS)) - { -#ifdef AZ_DEBUG_JOB_STATE - AZ_Assert(m_state == STATE_STARTED, "Job has not been started but the dependent count is zero, must be a dependency error"); - SetState(STATE_PENDING); -#endif - m_context->GetJobManager().AddPendingJob(this); - } - } - } - - inline AZ::s8 Job::GetPriority() const - { - return (GetDependentCountAndFlags() >> FLAG_PRIORITY_START_BIT) & 0xff; - } - #ifdef AZ_DEBUG_JOB_STATE - AZ_FORCE_INLINE void Job::SetState(int state) + inline void Job::SetState(int state) { m_state = state; } #endif -#ifdef AZCORE_JOBS_IMPL_SYNCHRONOUS - AZ_FORCE_INLINE void Job::StoreDependent(Job* job) - { - m_dependent = job; - } - - AZ_FORCE_INLINE Job* Job::GetDependent() const - { - return m_dependent; - } - AZ_FORCE_INLINE void Job::SetDependentCountAndFlags(unsigned int countAndFlags) - { - m_dependentCountAndFlags = countAndFlags; - } - - AZ_FORCE_INLINE unsigned int Job::GetDependentCountAndFlags() const - { - return m_dependentCountAndFlags; - } -#else - AZ_FORCE_INLINE void Job::StoreDependent(Job* job) - { - m_dependent.store(job, AZStd::memory_order_release); - } - - AZ_FORCE_INLINE Job* Job::GetDependent() const - { - return m_dependent.load(AZStd::memory_order_acquire); - } - - AZ_FORCE_INLINE void Job::SetDependentCountAndFlags(unsigned int countAndFlags) - { - m_dependentCountAndFlags.store(countAndFlags, AZStd::memory_order_release); - } - - AZ_FORCE_INLINE unsigned int Job::GetDependentCountAndFlags() const - { - return m_dependentCountAndFlags.load(AZStd::memory_order_acquire); - } -#endif } -#endif -#pragma once + diff --git a/Code/Framework/AzCore/AzCore/azcore_files.cmake b/Code/Framework/AzCore/AzCore/azcore_files.cmake index 667ae49387..e3d2987a3c 100644 --- a/Code/Framework/AzCore/AzCore/azcore_files.cmake +++ b/Code/Framework/AzCore/AzCore/azcore_files.cmake @@ -221,6 +221,7 @@ set(FILES Jobs/Internal/JobManagerWorkStealing.cpp Jobs/Internal/JobManagerWorkStealing.h Jobs/Internal/JobNotify.h + Jobs/Job.cpp Jobs/Job.h Jobs/JobCancelGroup.h Jobs/JobCompletion.h From 06cef942a957d2805170b2c377561e4875365137 Mon Sep 17 00:00:00 2001 From: Jeremy Ong Date: Sat, 31 Jul 2021 18:30:49 -0600 Subject: [PATCH 148/160] PALify RenderDoc module name Signed-off-by: Jeremy Ong --- Gems/Atom/RHI/Code/CMakeLists.txt | 3 +++ Gems/Atom/RHI/Code/Include/Atom/RHI/Factory.h | 11 ----------- .../Platform/Android/Atom_RHI_Traits_Android.h | 10 ++++++++++ .../Platform/Android/Atom_RHI_Traits_Platform.h | 10 ++++++++++ .../Platform/Android/platform_android_files.cmake | 12 ++++++++++++ .../Source/Platform/Linux/Atom_RHI_Traits_Linux.h | 10 ++++++++++ .../Source/Platform/Linux/Atom_RHI_Traits_Platform.h | 10 ++++++++++ .../Source/Platform/Linux/platform_linux_files.cmake | 12 ++++++++++++ .../Code/Source/Platform/Mac/Atom_RHI_Traits_Mac.h | 8 ++++++++ .../Source/Platform/Mac/Atom_RHI_Traits_Platform.h | 10 ++++++++++ .../Source/Platform/Mac/platform_mac_files.cmake | 12 ++++++++++++ .../Platform/Windows/Atom_RHI_Traits_Platform.h | 10 ++++++++++ .../Platform/Windows/Atom_RHI_Traits_Windows.h | 10 ++++++++++ .../Platform/Windows/platform_windows_files.cmake | 12 ++++++++++++ .../Source/Platform/iOS/Atom_RHI_Traits_Platform.h | 10 ++++++++++ .../Code/Source/Platform/iOS/Atom_RHI_Traits_iOS.h | 8 ++++++++ .../Source/Platform/iOS/platform_ios_files.cmake | 12 ++++++++++++ Gems/Atom/RHI/Code/Source/RHI/Factory.cpp | 5 +++-- 18 files changed, 162 insertions(+), 13 deletions(-) create mode 100644 Gems/Atom/RHI/Code/Source/Platform/Android/Atom_RHI_Traits_Android.h create mode 100644 Gems/Atom/RHI/Code/Source/Platform/Android/Atom_RHI_Traits_Platform.h create mode 100644 Gems/Atom/RHI/Code/Source/Platform/Android/platform_android_files.cmake create mode 100644 Gems/Atom/RHI/Code/Source/Platform/Linux/Atom_RHI_Traits_Linux.h create mode 100644 Gems/Atom/RHI/Code/Source/Platform/Linux/Atom_RHI_Traits_Platform.h create mode 100644 Gems/Atom/RHI/Code/Source/Platform/Linux/platform_linux_files.cmake create mode 100644 Gems/Atom/RHI/Code/Source/Platform/Mac/Atom_RHI_Traits_Mac.h create mode 100644 Gems/Atom/RHI/Code/Source/Platform/Mac/Atom_RHI_Traits_Platform.h create mode 100644 Gems/Atom/RHI/Code/Source/Platform/Mac/platform_mac_files.cmake create mode 100644 Gems/Atom/RHI/Code/Source/Platform/Windows/Atom_RHI_Traits_Platform.h create mode 100644 Gems/Atom/RHI/Code/Source/Platform/Windows/Atom_RHI_Traits_Windows.h create mode 100644 Gems/Atom/RHI/Code/Source/Platform/Windows/platform_windows_files.cmake create mode 100644 Gems/Atom/RHI/Code/Source/Platform/iOS/Atom_RHI_Traits_Platform.h create mode 100644 Gems/Atom/RHI/Code/Source/Platform/iOS/Atom_RHI_Traits_iOS.h create mode 100644 Gems/Atom/RHI/Code/Source/Platform/iOS/platform_ios_files.cmake diff --git a/Gems/Atom/RHI/Code/CMakeLists.txt b/Gems/Atom/RHI/Code/CMakeLists.txt index 82b80e5151..892216c53f 100644 --- a/Gems/Atom/RHI/Code/CMakeLists.txt +++ b/Gems/Atom/RHI/Code/CMakeLists.txt @@ -7,6 +7,7 @@ # ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME}) +ly_get_list_relative_pal_filename(pal_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME}) include(${pal_dir}/AtomRHITests_traits_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) @@ -50,9 +51,11 @@ ly_add_target( NAMESPACE Gem FILES_CMAKE atom_rhi_public_files.cmake + ${pal_source_dir}/platform_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake INCLUDE_DIRECTORIES PRIVATE Source + ${pal_source_dir} PUBLIC Include BUILD_DEPENDENCIES diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/Factory.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/Factory.h index 24f09c6580..11f28e7a94 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/Factory.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/Factory.h @@ -13,7 +13,6 @@ #if defined(USE_RENDERDOC) #include -#include #endif namespace AZ @@ -99,16 +98,6 @@ namespace AZ static Factory& Get(); #if defined(USE_RENDERDOC) -#if defined(AZ_PLATFORM_WINDOWS) - static const char* RENDERDOC_MODULE = "renderdoc.dll"; -#elif defined(AZ_PLATFORM_LINUX) - static const char* RENDERDOC_MODULE = "librenderdoc.so"; -#elif defined(AZ_PLATFORM_ANDROID) - static const char* RENDERDOC_MODULE = "libVkLayer_GLES_RenderDoc.so" -#else - static const char* RENDERDOC_MODULE = nullptr; -#endif - /// Access the RenderDoc API pointer if available. /// The availability of the render doc API at runtime depends on the following: /// - You must not be building a packaged game/product (LY_MONOLITHIC_GAME not enabled in CMake) diff --git a/Gems/Atom/RHI/Code/Source/Platform/Android/Atom_RHI_Traits_Android.h b/Gems/Atom/RHI/Code/Source/Platform/Android/Atom_RHI_Traits_Android.h new file mode 100644 index 0000000000..2f9b2b7c00 --- /dev/null +++ b/Gems/Atom/RHI/Code/Source/Platform/Android/Atom_RHI_Traits_Android.h @@ -0,0 +1,10 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ +#pragma once + +#define AZ_TRAIT_RENDERDOC_MODULE "libVkLayer_GLES_RenderDoc.so" diff --git a/Gems/Atom/RHI/Code/Source/Platform/Android/Atom_RHI_Traits_Platform.h b/Gems/Atom/RHI/Code/Source/Platform/Android/Atom_RHI_Traits_Platform.h new file mode 100644 index 0000000000..6af80df81e --- /dev/null +++ b/Gems/Atom/RHI/Code/Source/Platform/Android/Atom_RHI_Traits_Platform.h @@ -0,0 +1,10 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ +#pragma once + +#include "Atom_RHI_Traits_Android.h" diff --git a/Gems/Atom/RHI/Code/Source/Platform/Android/platform_android_files.cmake b/Gems/Atom/RHI/Code/Source/Platform/Android/platform_android_files.cmake new file mode 100644 index 0000000000..167afec34d --- /dev/null +++ b/Gems/Atom/RHI/Code/Source/Platform/Android/platform_android_files.cmake @@ -0,0 +1,12 @@ +# +# Copyright (c) Contributors to the Open 3D Engine Project. +# For complete copyright and license terms please see the LICENSE at the root of this distribution. +# +# SPDX-License-Identifier: Apache-2.0 OR MIT +# +# + +set(FILES + Atom_RHI_Traits_Platform.h + Atom_RHI_Traits_Android.h +) diff --git a/Gems/Atom/RHI/Code/Source/Platform/Linux/Atom_RHI_Traits_Linux.h b/Gems/Atom/RHI/Code/Source/Platform/Linux/Atom_RHI_Traits_Linux.h new file mode 100644 index 0000000000..35219a5d57 --- /dev/null +++ b/Gems/Atom/RHI/Code/Source/Platform/Linux/Atom_RHI_Traits_Linux.h @@ -0,0 +1,10 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ +#pragma once + +#define AZ_TRAIT_RENDERDOC_MODULE "librenderdoc.so" diff --git a/Gems/Atom/RHI/Code/Source/Platform/Linux/Atom_RHI_Traits_Platform.h b/Gems/Atom/RHI/Code/Source/Platform/Linux/Atom_RHI_Traits_Platform.h new file mode 100644 index 0000000000..2c2c28a96f --- /dev/null +++ b/Gems/Atom/RHI/Code/Source/Platform/Linux/Atom_RHI_Traits_Platform.h @@ -0,0 +1,10 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ +#pragma once + +#include "Atom_RHI_Traits_Linux.h" diff --git a/Gems/Atom/RHI/Code/Source/Platform/Linux/platform_linux_files.cmake b/Gems/Atom/RHI/Code/Source/Platform/Linux/platform_linux_files.cmake new file mode 100644 index 0000000000..c31e71cd20 --- /dev/null +++ b/Gems/Atom/RHI/Code/Source/Platform/Linux/platform_linux_files.cmake @@ -0,0 +1,12 @@ +# +# Copyright (c) Contributors to the Open 3D Engine Project. +# For complete copyright and license terms please see the LICENSE at the root of this distribution. +# +# SPDX-License-Identifier: Apache-2.0 OR MIT +# +# + +set(FILES + Atom_RHI_Traits_Platform.h + Atom_RHI_Traits_Linux.h +) diff --git a/Gems/Atom/RHI/Code/Source/Platform/Mac/Atom_RHI_Traits_Mac.h b/Gems/Atom/RHI/Code/Source/Platform/Mac/Atom_RHI_Traits_Mac.h new file mode 100644 index 0000000000..03320d1dd8 --- /dev/null +++ b/Gems/Atom/RHI/Code/Source/Platform/Mac/Atom_RHI_Traits_Mac.h @@ -0,0 +1,8 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ +#pragma once diff --git a/Gems/Atom/RHI/Code/Source/Platform/Mac/Atom_RHI_Traits_Platform.h b/Gems/Atom/RHI/Code/Source/Platform/Mac/Atom_RHI_Traits_Platform.h new file mode 100644 index 0000000000..ae990ab471 --- /dev/null +++ b/Gems/Atom/RHI/Code/Source/Platform/Mac/Atom_RHI_Traits_Platform.h @@ -0,0 +1,10 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ +#pragma once + +#include "Atom_RHI_Traits_Mac.h" diff --git a/Gems/Atom/RHI/Code/Source/Platform/Mac/platform_mac_files.cmake b/Gems/Atom/RHI/Code/Source/Platform/Mac/platform_mac_files.cmake new file mode 100644 index 0000000000..2d4ecd8b4f --- /dev/null +++ b/Gems/Atom/RHI/Code/Source/Platform/Mac/platform_mac_files.cmake @@ -0,0 +1,12 @@ +# +# Copyright (c) Contributors to the Open 3D Engine Project. +# For complete copyright and license terms please see the LICENSE at the root of this distribution. +# +# SPDX-License-Identifier: Apache-2.0 OR MIT +# +# + +set(FILES + Atom_RHI_Traits_Platform.h + Atom_RHI_Traits_Mac.h +) diff --git a/Gems/Atom/RHI/Code/Source/Platform/Windows/Atom_RHI_Traits_Platform.h b/Gems/Atom/RHI/Code/Source/Platform/Windows/Atom_RHI_Traits_Platform.h new file mode 100644 index 0000000000..6e19903677 --- /dev/null +++ b/Gems/Atom/RHI/Code/Source/Platform/Windows/Atom_RHI_Traits_Platform.h @@ -0,0 +1,10 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ +#pragma once + +#include "Atom_RHI_Traits_Windows.h" diff --git a/Gems/Atom/RHI/Code/Source/Platform/Windows/Atom_RHI_Traits_Windows.h b/Gems/Atom/RHI/Code/Source/Platform/Windows/Atom_RHI_Traits_Windows.h new file mode 100644 index 0000000000..82358784a3 --- /dev/null +++ b/Gems/Atom/RHI/Code/Source/Platform/Windows/Atom_RHI_Traits_Windows.h @@ -0,0 +1,10 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ +#pragma once + +#define AZ_TRAIT_RENDERDOC_MODULE "renderdoc.dll" diff --git a/Gems/Atom/RHI/Code/Source/Platform/Windows/platform_windows_files.cmake b/Gems/Atom/RHI/Code/Source/Platform/Windows/platform_windows_files.cmake new file mode 100644 index 0000000000..fc282d0163 --- /dev/null +++ b/Gems/Atom/RHI/Code/Source/Platform/Windows/platform_windows_files.cmake @@ -0,0 +1,12 @@ +# +# Copyright (c) Contributors to the Open 3D Engine Project. +# For complete copyright and license terms please see the LICENSE at the root of this distribution. +# +# SPDX-License-Identifier: Apache-2.0 OR MIT +# +# + +set(FILES + Atom_RHI_Traits_Platform.h + Atom_RHI_Traits_Windows.h +) diff --git a/Gems/Atom/RHI/Code/Source/Platform/iOS/Atom_RHI_Traits_Platform.h b/Gems/Atom/RHI/Code/Source/Platform/iOS/Atom_RHI_Traits_Platform.h new file mode 100644 index 0000000000..c39f94db8b --- /dev/null +++ b/Gems/Atom/RHI/Code/Source/Platform/iOS/Atom_RHI_Traits_Platform.h @@ -0,0 +1,10 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ +#pragma once + +#include "Atom_RHI_Traits_iOS.h" diff --git a/Gems/Atom/RHI/Code/Source/Platform/iOS/Atom_RHI_Traits_iOS.h b/Gems/Atom/RHI/Code/Source/Platform/iOS/Atom_RHI_Traits_iOS.h new file mode 100644 index 0000000000..03320d1dd8 --- /dev/null +++ b/Gems/Atom/RHI/Code/Source/Platform/iOS/Atom_RHI_Traits_iOS.h @@ -0,0 +1,8 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ +#pragma once diff --git a/Gems/Atom/RHI/Code/Source/Platform/iOS/platform_ios_files.cmake b/Gems/Atom/RHI/Code/Source/Platform/iOS/platform_ios_files.cmake new file mode 100644 index 0000000000..d487385fa6 --- /dev/null +++ b/Gems/Atom/RHI/Code/Source/Platform/iOS/platform_ios_files.cmake @@ -0,0 +1,12 @@ +# +# Copyright (c) Contributors to the Open 3D Engine Project. +# For complete copyright and license terms please see the LICENSE at the root of this distribution. +# +# SPDX-License-Identifier: Apache-2.0 OR MIT +# +# + +set(FILES + Atom_RHI_Traits_Platform.h + Atom_RHI_Traits_iOS.h +) diff --git a/Gems/Atom/RHI/Code/Source/RHI/Factory.cpp b/Gems/Atom/RHI/Code/Source/RHI/Factory.cpp index 8e4a96158f..3162a71e34 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/Factory.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/Factory.cpp @@ -14,6 +14,7 @@ #if defined(USE_RENDERDOC) #include #include +#include static AZStd::unique_ptr s_renderDocModule; static RENDERDOC_API_1_1_2* s_renderDocApi = nullptr; @@ -45,9 +46,9 @@ namespace AZ // If RenderDoc is requested, we need to load the library as early as possible (before device queries/factories are made) bool enableRenderDoc = RHI::QueryCommandLineOption("enableRenderDoc"); - if (enableRenderDoc && RENDERDOC_MODULE && !s_renderDocModule) + if (enableRenderDoc && AZ_TRAIT_RENDERDOC_MODULE && !s_renderDocModule) { - s_renderDocModule = DynamicModuleHandle::Create(RENDERDOC_MODULE); + s_renderDocModule = DynamicModuleHandle::Create(AZ_TRAIT_RENDERDOC_MODULE); if (s_renderDocModule) { if (s_renderDocModule->Load(false)) From af0d7575560afe90991f27bc797bf8f5d014d29f Mon Sep 17 00:00:00 2001 From: Jeremy Ong Date: Mon, 2 Aug 2021 09:50:24 -0600 Subject: [PATCH 149/160] Remove CMake status message when not compiling with RenderDoc Signed-off-by: Jeremy Ong --- Gems/Atom/RHI/Code/CMakeLists.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Gems/Atom/RHI/Code/CMakeLists.txt b/Gems/Atom/RHI/Code/CMakeLists.txt index 892216c53f..eeb8f73bac 100644 --- a/Gems/Atom/RHI/Code/CMakeLists.txt +++ b/Gems/Atom/RHI/Code/CMakeLists.txt @@ -17,12 +17,11 @@ if(EXISTS ${RENDERDOC_CMAKE}) endif() if(TARGET "3rdParty::renderdoc") - message(STATUS "Renderdoc found") + message(STATUS "Renderdoc found, adding as runtime dependency") set(USE_RENDERDOC_DEFINE "USE_RENDERDOC") set(RENDERDOC_BUILD_DEPENDENCY "3rdParty::renderdoc") set(RENDERDOC_API_DEPENDENCY "3rdParty::renderdoc_api") else() - message(STATUS "Renderdoc missing") set(USE_RENDERDOC_DEFINE "") set(RENDERDOC_BUILD_DEPENDENCY "") set(RENDERDOC_API_DEPENDENCY "") From 8088e6662a2ff7036358b7d0dcf54271f6af7cbe Mon Sep 17 00:00:00 2001 From: rgba16f <82187279+rgba16f@users.noreply.github.com> Date: Mon, 2 Aug 2021 11:15:31 -0500 Subject: [PATCH 150/160] modify new jobs.cpp file to match AzCore standard of opening namespace AZ rather than prepend AZ:: to every function Signed-off-by: rgba16f <82187279+rgba16f@users.noreply.github.com> --- Code/Framework/AzCore/AzCore/Jobs/Job.cpp | 479 +++++++++++----------- 1 file changed, 241 insertions(+), 238 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/Jobs/Job.cpp b/Code/Framework/AzCore/AzCore/Jobs/Job.cpp index 66493e193b..43e26767ae 100644 --- a/Code/Framework/AzCore/AzCore/Jobs/Job.cpp +++ b/Code/Framework/AzCore/AzCore/Jobs/Job.cpp @@ -12,298 +12,301 @@ #include #include -AZ::Job::Job(bool isAutoDelete, AZ::JobContext* context, bool isCompletion, AZ::s8 priority) +namespace AZ { - if (context) + Job::Job(bool isAutoDelete, AZ::JobContext* context, bool isCompletion, AZ::s8 priority) { - m_context = context; + if (context) + { + m_context = context; + } + else + { + m_context = JobContext::GetParentContext(); + } + + unsigned int countAndFlags = 1; + if (isAutoDelete) + { + countAndFlags |= (unsigned int)FLAG_AUTO_DELETE; + } + if (isCompletion) + { + countAndFlags |= (unsigned int)FLAG_COMPLETION; + } + countAndFlags |= (unsigned int)((priority << FLAG_PRIORITY_START_BIT) & FLAG_PRIORITY_MASK); + SetDependentCountAndFlags(countAndFlags); + StoreDependent(NULL); + + #ifdef AZ_DEBUG_JOB_STATE + SetState(STATE_SETUP); + #endif // AZ_DEBUG_JOB_STATE } - else + + void Job::Start() { - m_context = JobContext::GetParentContext(); + //jobs are created with a count set to 1, we remove that count to allow the job to start + #ifdef AZ_DEBUG_JOB_STATE + AZ_Assert(m_state == STATE_SETUP, ("Jobs must be in the setup state before they can be started")); + SetState(STATE_STARTED); + #endif + DecrementDependentCount(); } - unsigned int countAndFlags = 1; - if (isAutoDelete) + void Job::Reset(bool isClearDependent) { - countAndFlags |= (unsigned int)FLAG_AUTO_DELETE; + #ifdef AZ_DEBUG_JOB_STATE + AZ_Assert((m_state == STATE_SETUP) || (m_state == STATE_PROCESSING), "Jobs must not be running when they are reset"); + SetState(STATE_SETUP); + #endif + unsigned int countAndFlags = GetDependentCountAndFlags(); + AZ_Assert((countAndFlags & (unsigned int)FLAG_AUTO_DELETE) == 0, "You can't call reset on AutoDelete jobs!"); + // Remove the FLAG_DEPENDENTCOUNT_MASK and FLAG_CHILD_JOBS flags + countAndFlags = (countAndFlags & (~(FLAG_DEPENDENTCOUNT_MASK) & ~(FLAG_CHILD_JOBS))) | 1; + SetDependentCountAndFlags(countAndFlags); + if (isClearDependent) + { + StoreDependent(NULL); + } + else + { + Job* dependent = GetDependent(); + if (dependent) + { + #ifdef AZ_DEBUG_JOB_STATE + AZ_Assert(dependent->m_state == STATE_SETUP, ("Dependent must be in setup state before it can be re-initialized")); + #endif + dependent->IncrementDependentCount(); + } + } } - if (isCompletion) + + void Job::SetDependent(Job* dependent) { - countAndFlags |= (unsigned int)FLAG_COMPLETION; + AZ_Assert(!GetDependent(), ("Job already has a dependent, should be cleared after the job is done")); + #ifdef AZ_DEBUG_JOB_STATE + AZ_Assert(m_state == STATE_SETUP, ("Dependent can only be set before the jobs are started")); + AZ_Assert(dependent->m_state == STATE_SETUP, ("Dependent must be in the setup state")); + #endif + dependent->IncrementDependentCount(); + StoreDependent(dependent); } - countAndFlags |= (unsigned int)((priority << FLAG_PRIORITY_START_BIT) & FLAG_PRIORITY_MASK); - SetDependentCountAndFlags(countAndFlags); - StoreDependent(NULL); - -#ifdef AZ_DEBUG_JOB_STATE - SetState(STATE_SETUP); -#endif // AZ_DEBUG_JOB_STATE -} -void AZ::Job::Start() -{ - //jobs are created with a count set to 1, we remove that count to allow the job to start -#ifdef AZ_DEBUG_JOB_STATE - AZ_Assert(m_state == STATE_SETUP, ("Jobs must be in the setup state before they can be started")); - SetState(STATE_STARTED); -#endif - DecrementDependentCount(); -} + void Job::SetDependentStarted(Job* dependent) + { + AZ_Assert(!GetDependent(), ("Job already has a dependent, should be cleared after the job is done")); + #ifdef AZ_DEBUG_JOB_STATE + AZ_Assert(m_state == STATE_SETUP, ("Dependent can only be set before the jobs are started")); + //We don't require the dependent to be in STATE_SETUP, the user can call this from a context where they + //know the dependent has not started yet, although it is in STATE_STARTED already, e.g. if SetDependent + //is called from a job which the dependent is already dependent on. + //Note that if the user gets this wrong, the dependent may start before this job is finished, and the asserts + //may not even trigger due to race conditions. Hence why this function is 'experts only'. + AZ_Assert((dependent->m_state == STATE_SETUP) || (dependent->m_state == STATE_STARTED) + || (dependent->m_state == STATE_SUSPENDED), "Dependent must be in the setup, started, or suspended state"); + #endif + dependent->IncrementDependentCount(); + StoreDependent(dependent); + } -void AZ::Job::Reset(bool isClearDependent) -{ -#ifdef AZ_DEBUG_JOB_STATE - AZ_Assert((m_state == STATE_SETUP) || (m_state == STATE_PROCESSING), "Jobs must not be running when they are reset"); - SetState(STATE_SETUP); -#endif - unsigned int countAndFlags = GetDependentCountAndFlags(); - AZ_Assert((countAndFlags & (unsigned int)FLAG_AUTO_DELETE) == 0, "You can't call reset on AutoDelete jobs!"); - // Remove the FLAG_DEPENDENTCOUNT_MASK and FLAG_CHILD_JOBS flags - countAndFlags = (countAndFlags & (~(FLAG_DEPENDENTCOUNT_MASK) & ~(FLAG_CHILD_JOBS))) | 1; - SetDependentCountAndFlags(countAndFlags); - if (isClearDependent) + void Job::SetDependentChild(Job* dependent) { - StoreDependent(NULL); + AZ_Assert(!GetDependent(), ("Job already has a dependent, should be cleared after the job is done")); + #ifdef AZ_DEBUG_JOB_STATE + AZ_Assert(m_state == STATE_SETUP, ("Dependent can only be set before the jobs are started")); + AZ_Assert(dependent->m_state == STATE_PROCESSING, "Dependent must be processing to add a child"); + #endif + dependent->IncrementDependentCountAndSetChildFlag(); + StoreDependent(dependent); } - else + + void Job::SetContinuation(Job* continuationJob) { + #ifdef AZ_DEBUG_JOB_STATE + AZ_Assert(m_state == STATE_PROCESSING, "Continuation jobs can only be set while we are processing, otherwise a regular dependent should be used"); + #endif Job* dependent = GetDependent(); - if (dependent) + if (dependent) //nothing to do if there is no dependent... doesn't usually happen, except with synchronous processing and assists { -#ifdef AZ_DEBUG_JOB_STATE - AZ_Assert(dependent->m_state == STATE_SETUP, ("Dependent must be in setup state before it can be re-initialized")); -#endif - dependent->IncrementDependentCount(); + continuationJob->SetDependentStarted(dependent); } } -} -void AZ::Job::SetDependent(Job* dependent) -{ - AZ_Assert(!GetDependent(), ("Job already has a dependent, should be cleared after the job is done")); -#ifdef AZ_DEBUG_JOB_STATE - AZ_Assert(m_state == STATE_SETUP, ("Dependent can only be set before the jobs are started")); - AZ_Assert(dependent->m_state == STATE_SETUP, ("Dependent must be in the setup state")); -#endif - dependent->IncrementDependentCount(); - StoreDependent(dependent); -} - -void AZ::Job::SetDependentStarted(Job* dependent) -{ - AZ_Assert(!GetDependent(), ("Job already has a dependent, should be cleared after the job is done")); -#ifdef AZ_DEBUG_JOB_STATE - AZ_Assert(m_state == STATE_SETUP, ("Dependent can only be set before the jobs are started")); - //We don't require the dependent to be in STATE_SETUP, the user can call this from a context where they - //know the dependent has not started yet, although it is in STATE_STARTED already, e.g. if SetDependent - //is called from a job which the dependent is already dependent on. - //Note that if the user gets this wrong, the dependent may start before this job is finished, and the asserts - //may not even trigger due to race conditions. Hence why this function is 'experts only'. - AZ_Assert((dependent->m_state == STATE_SETUP) || (dependent->m_state == STATE_STARTED) - || (dependent->m_state == STATE_SUSPENDED), "Dependent must be in the setup, started, or suspended state"); -#endif - dependent->IncrementDependentCount(); - StoreDependent(dependent); -} - -void AZ::Job::SetDependentChild(Job* dependent) -{ - AZ_Assert(!GetDependent(), ("Job already has a dependent, should be cleared after the job is done")); -#ifdef AZ_DEBUG_JOB_STATE - AZ_Assert(m_state == STATE_SETUP, ("Dependent can only be set before the jobs are started")); - AZ_Assert(dependent->m_state == STATE_PROCESSING, "Dependent must be processing to add a child"); -#endif - dependent->IncrementDependentCountAndSetChildFlag(); - StoreDependent(dependent); -} - -void AZ::Job::SetContinuation(Job* continuationJob) -{ -#ifdef AZ_DEBUG_JOB_STATE - AZ_Assert(m_state == STATE_PROCESSING, "Continuation jobs can only be set while we are processing, otherwise a regular dependent should be used"); -#endif - Job* dependent = GetDependent(); - if (dependent) //nothing to do if there is no dependent... doesn't usually happen, except with synchronous processing and assists + void Job::StartAsChild(Job* childJob) { - continuationJob->SetDependentStarted(dependent); + #ifdef AZ_DEBUG_JOB_STATE + AZ_Assert(m_state == STATE_PROCESSING, "Child jobs can only be added while we are processing"); + #endif + childJob->SetDependentChild(this); + childJob->Start(); } -} - -void AZ::Job::StartAsChild(Job* childJob) -{ -#ifdef AZ_DEBUG_JOB_STATE - AZ_Assert(m_state == STATE_PROCESSING, "Child jobs can only be added while we are processing"); -#endif - childJob->SetDependentChild(this); - childJob->Start(); -} -void AZ::Job::WaitForChildren() -{ -#ifdef AZ_DEBUG_JOB_STATE - AZ_Assert(m_state == STATE_PROCESSING, "We must be currently processing in order to suspend"); -#endif - if (GetDependentCount() != 0) + void Job::WaitForChildren() { -#ifdef AZ_DEBUG_JOB_STATE - SetState(STATE_SUSPENDED); -#endif // AZ_DEBUG_JOB_STATE - m_context->GetJobManager().SuspendJobUntilReady(this); -#ifdef AZ_DEBUG_JOB_STATE - SetState(STATE_PROCESSING); -#endif // AZ_DEBUG_JOB_STATE + #ifdef AZ_DEBUG_JOB_STATE + AZ_Assert(m_state == STATE_PROCESSING, "We must be currently processing in order to suspend"); + #endif + if (GetDependentCount() != 0) + { + #ifdef AZ_DEBUG_JOB_STATE + SetState(STATE_SUSPENDED); + #endif // AZ_DEBUG_JOB_STATE + m_context->GetJobManager().SuspendJobUntilReady(this); + #ifdef AZ_DEBUG_JOB_STATE + SetState(STATE_PROCESSING); + #endif // AZ_DEBUG_JOB_STATE + } + AZ_Assert(GetDependentCount() == 0, "Suspended job has resumed, but still has non-zero dependent count, bug in JobManager?"); } - AZ_Assert(GetDependentCount() == 0, "Suspended job has resumed, but still has non-zero dependent count, bug in JobManager?"); -} -bool AZ::Job::IsCancelled() const -{ - JobCancelGroup* cancelGroup = m_context->GetCancelGroup(); - if (cancelGroup && cancelGroup->IsCancelled()) + bool Job::IsCancelled() const { - if (!IsCompletion()) // always run completion jobs, as they can be holding a synchronization primitive + JobCancelGroup* cancelGroup = m_context->GetCancelGroup(); + if (cancelGroup && cancelGroup->IsCancelled()) { - return true; + if (!IsCompletion()) // always run completion jobs, as they can be holding a synchronization primitive + { + return true; + } } + return false; } - return false; -} - -bool AZ::Job::IsAutoDelete() const -{ - return (GetDependentCountAndFlags() & (unsigned int)FLAG_AUTO_DELETE) ? true : false; -} -bool AZ::Job::IsCompletion() const -{ - return (GetDependentCountAndFlags() & (unsigned int)FLAG_COMPLETION) ? true : false; -} + bool Job::IsAutoDelete() const + { + return (GetDependentCountAndFlags() & (unsigned int)FLAG_AUTO_DELETE) ? true : false; + } -void AZ::Job::StartAndAssistUntilComplete() -{ - m_context->GetJobManager().StartJobAndAssistUntilComplete(this); -} + bool Job::IsCompletion() const + { + return (GetDependentCountAndFlags() & (unsigned int)FLAG_COMPLETION) ? true : false; + } -void AZ::Job::StartAndWaitForCompletion() -{ - //check if we are in a worker thread or a general user thread - Job* currentJob = m_context->GetJobManager().GetCurrentJob(); - if (currentJob) + void Job::StartAndAssistUntilComplete() { - //worker thread, so just suspend this current job until the empty job completes - currentJob->StartAsChild(this); - currentJob->WaitForChildren(); + m_context->GetJobManager().StartJobAndAssistUntilComplete(this); } - else + + void Job::StartAndWaitForCompletion() { - StartAndAssistUntilComplete(); + //check if we are in a worker thread or a general user thread + Job* currentJob = m_context->GetJobManager().GetCurrentJob(); + if (currentJob) + { + //worker thread, so just suspend this current job until the empty job completes + currentJob->StartAsChild(this); + currentJob->WaitForChildren(); + } + else + { + StartAndAssistUntilComplete(); + } } -} -unsigned int AZ::Job::GetDependentCount() const -{ - return (GetDependentCountAndFlags() & FLAG_DEPENDENTCOUNT_MASK); -} + unsigned int Job::GetDependentCount() const + { + return (GetDependentCountAndFlags() & FLAG_DEPENDENTCOUNT_MASK); + } -void AZ::Job::IncrementDependentCount() -{ - AZ_Assert(GetDependentCount() < FLAG_DEPENDENTCOUNT_MASK, "Dependent count overflow"); -#ifdef AZCORE_JOBS_IMPL_SYNCHRONOUS - ++m_dependentCountAndFlags; -#else - m_dependentCountAndFlags.fetch_add(1, AZStd::memory_order_acq_rel); -#endif -} + void Job::IncrementDependentCount() + { + AZ_Assert(GetDependentCount() < FLAG_DEPENDENTCOUNT_MASK, "Dependent count overflow"); + #ifdef AZCORE_JOBS_IMPL_SYNCHRONOUS + ++m_dependentCountAndFlags; + #else + m_dependentCountAndFlags.fetch_add(1, AZStd::memory_order_acq_rel); + #endif + } -void AZ::Job::IncrementDependentCountAndSetChildFlag() -{ - AZ_Assert(GetDependentCount() < FLAG_DEPENDENTCOUNT_MASK, "Dependent count overflow"); -#ifdef AZCORE_JOBS_IMPL_SYNCHRONOUS - int oldCount = m_dependentCountAndFlags & FLAG_DEPENDENTCOUNT_MASK; - m_dependentCountAndFlags = (m_dependentCountAndFlags & ~FLAG_DEPENDENTCOUNT_MASK) | (oldCount + 1) | FLAG_CHILD_JOBS; -#else - //use a single atomic operation to increment the count and set the child flag if possible - unsigned int oldCountAndFlags, newCountAndFlags; - do + void Job::IncrementDependentCountAndSetChildFlag() { - oldCountAndFlags = m_dependentCountAndFlags.load(AZStd::memory_order_acquire); - int oldCount = oldCountAndFlags & FLAG_DEPENDENTCOUNT_MASK; - newCountAndFlags = (oldCountAndFlags & ~FLAG_DEPENDENTCOUNT_MASK) | (oldCount + 1) | FLAG_CHILD_JOBS; - } while (!m_dependentCountAndFlags.compare_exchange_weak(oldCountAndFlags, newCountAndFlags, AZStd::memory_order_acq_rel, AZStd::memory_order_acquire)); -#endif -} + AZ_Assert(GetDependentCount() < FLAG_DEPENDENTCOUNT_MASK, "Dependent count overflow"); + #ifdef AZCORE_JOBS_IMPL_SYNCHRONOUS + int oldCount = m_dependentCountAndFlags & FLAG_DEPENDENTCOUNT_MASK; + m_dependentCountAndFlags = (m_dependentCountAndFlags & ~FLAG_DEPENDENTCOUNT_MASK) | (oldCount + 1) | FLAG_CHILD_JOBS; + #else + //use a single atomic operation to increment the count and set the child flag if possible + unsigned int oldCountAndFlags, newCountAndFlags; + do + { + oldCountAndFlags = m_dependentCountAndFlags.load(AZStd::memory_order_acquire); + int oldCount = oldCountAndFlags & FLAG_DEPENDENTCOUNT_MASK; + newCountAndFlags = (oldCountAndFlags & ~FLAG_DEPENDENTCOUNT_MASK) | (oldCount + 1) | FLAG_CHILD_JOBS; + } while (!m_dependentCountAndFlags.compare_exchange_weak(oldCountAndFlags, newCountAndFlags, AZStd::memory_order_acq_rel, AZStd::memory_order_acquire)); + #endif + } -void AZ::Job::DecrementDependentCount() -{ -#ifdef AZ_DEBUG_JOB_STATE - AZ_Assert((m_state == STATE_SETUP) || (m_state == STATE_STARTED) - || (m_state == STATE_PROCESSING) || (m_state == STATE_SUSPENDED), //child jobs - "Job dependent count should not be decremented after job is already pending"); -#endif - AZ_Assert(GetDependentCount() > 0, ("Job dependent count is already zero")); -#ifdef AZCORE_JOBS_IMPL_SYNCHRONOUS - unsigned int countAndFlags = m_dependentCountAndFlags--; -#else - unsigned int countAndFlags = m_dependentCountAndFlags.fetch_sub(1, AZStd::memory_order_acq_rel); -#endif - unsigned int count = countAndFlags & FLAG_DEPENDENTCOUNT_MASK; - if (count == 1) + void Job::DecrementDependentCount() { - if (!(countAndFlags & FLAG_CHILD_JOBS)) + #ifdef AZ_DEBUG_JOB_STATE + AZ_Assert((m_state == STATE_SETUP) || (m_state == STATE_STARTED) + || (m_state == STATE_PROCESSING) || (m_state == STATE_SUSPENDED), //child jobs + "Job dependent count should not be decremented after job is already pending"); + #endif + AZ_Assert(GetDependentCount() > 0, ("Job dependent count is already zero")); + #ifdef AZCORE_JOBS_IMPL_SYNCHRONOUS + unsigned int countAndFlags = m_dependentCountAndFlags--; + #else + unsigned int countAndFlags = m_dependentCountAndFlags.fetch_sub(1, AZStd::memory_order_acq_rel); + #endif + unsigned int count = countAndFlags & FLAG_DEPENDENTCOUNT_MASK; + if (count == 1) { -#ifdef AZ_DEBUG_JOB_STATE - AZ_Assert(m_state == STATE_STARTED, "Job has not been started but the dependent count is zero, must be a dependency error"); - SetState(STATE_PENDING); -#endif - m_context->GetJobManager().AddPendingJob(this); + if (!(countAndFlags & FLAG_CHILD_JOBS)) + { + #ifdef AZ_DEBUG_JOB_STATE + AZ_Assert(m_state == STATE_STARTED, "Job has not been started but the dependent count is zero, must be a dependency error"); + SetState(STATE_PENDING); + #endif + m_context->GetJobManager().AddPendingJob(this); + } } } -} -AZ::s8 AZ::Job::GetPriority() const -{ - return (GetDependentCountAndFlags() >> FLAG_PRIORITY_START_BIT) & 0xff; -} + AZ::s8 Job::GetPriority() const + { + return (GetDependentCountAndFlags() >> FLAG_PRIORITY_START_BIT) & 0xff; + } #ifdef AZCORE_JOBS_IMPL_SYNCHRONOUS -void AZ::Job::StoreDependent(Job* job) -{ - m_dependent = job; -} + void Job::StoreDependent(Job* job) + { + m_dependent = job; + } -AZ::Job* AZ::Job::GetDependent() const -{ - return m_dependent; -} + Job* Job::GetDependent() const + { + return m_dependent; + } -void AZ::Job::SetDependentCountAndFlags(unsigned int countAndFlags) -{ - m_dependentCountAndFlags = countAndFlags; -} + void Job::SetDependentCountAndFlags(unsigned int countAndFlags) + { + m_dependentCountAndFlags = countAndFlags; + } -unsigned int AZ::Job::GetDependentCountAndFlags() const -{ - return m_dependentCountAndFlags; -} + unsigned int Job::GetDependentCountAndFlags() const + { + return m_dependentCountAndFlags; + } #else -void AZ::Job::StoreDependent(Job* job) -{ - m_dependent.store(job, AZStd::memory_order_release); -} + void Job::StoreDependent(Job* job) + { + m_dependent.store(job, AZStd::memory_order_release); + } -AZ::Job* AZ::Job::GetDependent() const -{ - return m_dependent.load(AZStd::memory_order_acquire); -} + Job* Job::GetDependent() const + { + return m_dependent.load(AZStd::memory_order_acquire); + } -void AZ::Job::SetDependentCountAndFlags(unsigned int countAndFlags) -{ - m_dependentCountAndFlags.store(countAndFlags, AZStd::memory_order_release); -} + void Job::SetDependentCountAndFlags(unsigned int countAndFlags) + { + m_dependentCountAndFlags.store(countAndFlags, AZStd::memory_order_release); + } -unsigned int AZ::Job::GetDependentCountAndFlags() const -{ - return m_dependentCountAndFlags.load(AZStd::memory_order_acquire); -} + unsigned int Job::GetDependentCountAndFlags() const + { + return m_dependentCountAndFlags.load(AZStd::memory_order_acquire); + } #endif +} \ No newline at end of file From 8014475abfdbacf83a874861cc7f00b66a465258 Mon Sep 17 00:00:00 2001 From: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> Date: Mon, 2 Aug 2021 11:28:04 -0500 Subject: [PATCH 151/160] Adding newline to the end of the new Job.cpp file Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> --- Code/Framework/AzCore/AzCore/Jobs/Job.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Framework/AzCore/AzCore/Jobs/Job.cpp b/Code/Framework/AzCore/AzCore/Jobs/Job.cpp index 43e26767ae..d3a2a77d92 100644 --- a/Code/Framework/AzCore/AzCore/Jobs/Job.cpp +++ b/Code/Framework/AzCore/AzCore/Jobs/Job.cpp @@ -309,4 +309,4 @@ namespace AZ return m_dependentCountAndFlags.load(AZStd::memory_order_acquire); } #endif -} \ No newline at end of file +} From 37c3f01771aa28e49d2ae37084187a52e0b09b75 Mon Sep 17 00:00:00 2001 From: Chris Galvan Date: Mon, 2 Aug 2021 12:27:03 -0500 Subject: [PATCH 152/160] Removed legacy ObjectIcons and shelve icons from Editor. Signed-off-by: Chris Galvan --- Assets/Editor/ObjectIcons/AreaTrigger.bmp | 3 -- .../Editor/ObjectIcons/AudioAreaAmbience.bmp | 3 -- Assets/Editor/ObjectIcons/AudioAreaEntity.bmp | 3 -- Assets/Editor/ObjectIcons/AudioAreaRandom.bmp | 3 -- Assets/Editor/ObjectIcons/Camera.bmp | 3 -- Assets/Editor/ObjectIcons/Checkpoint.bmp | 3 -- Assets/Editor/ObjectIcons/ClipVolume.bmp | 3 -- Assets/Editor/ObjectIcons/Clock.bmp | 3 -- Assets/Editor/ObjectIcons/Clouds.bmp | 3 -- Assets/Editor/ObjectIcons/Comment.bmp | 3 -- Assets/Editor/ObjectIcons/DeadBody.bmp | 3 -- Assets/Editor/ObjectIcons/Decal.bmp | 3 -- Assets/Editor/ObjectIcons/Dialog.bmp | 3 -- Assets/Editor/ObjectIcons/Flash.bmp | 3 -- Assets/Editor/ObjectIcons/Fog.bmp | 3 -- Assets/Editor/ObjectIcons/FogVolume.bmp | 3 -- Assets/Editor/ObjectIcons/GravitySphere.bmp | 3 -- Assets/Editor/ObjectIcons/Item.bmp | 3 -- Assets/Editor/ObjectIcons/Ladder.bmp | 3 -- Assets/Editor/ObjectIcons/Light.bmp | 3 -- .../ObjectIcons/LightPropagationVolume.bmp | 3 -- Assets/Editor/ObjectIcons/Lightning.bmp | 3 -- Assets/Editor/ObjectIcons/Magnet.bmp | 3 -- Assets/Editor/ObjectIcons/MultiTrigger.bmp | 3 -- Assets/Editor/ObjectIcons/ODD.bmp | 3 -- Assets/Editor/ObjectIcons/Particles.bmp | 3 -- Assets/Editor/ObjectIcons/PrecacheCamera.bmp | 3 -- Assets/Editor/ObjectIcons/Prefab.bmp | 3 -- Assets/Editor/ObjectIcons/Prompt.bmp | 3 -- Assets/Editor/ObjectIcons/SavePoint.bmp | 3 -- Assets/Editor/ObjectIcons/Seed.bmp | 3 -- Assets/Editor/ObjectIcons/Sound.bmp | 3 -- Assets/Editor/ObjectIcons/SpawnPoint.bmp | 3 -- Assets/Editor/ObjectIcons/T.bmp | 3 -- Assets/Editor/ObjectIcons/TagPoint.bmp | 3 -- Assets/Editor/ObjectIcons/Trigger.bmp | 3 -- .../Editor/ObjectIcons/UiCanvasRefEntity.bmp | 3 -- Assets/Editor/ObjectIcons/User.bmp | 3 -- Assets/Editor/ObjectIcons/VVVArea.bmp | 3 -- Assets/Editor/ObjectIcons/W.bmp | 3 -- Assets/Editor/ObjectIcons/Water.bmp | 3 -- Assets/Editor/ObjectIcons/animobject.bmp | 3 -- Assets/Editor/ObjectIcons/bird.bmp | 3 -- Assets/Editor/ObjectIcons/bug.bmp | 3 -- Assets/Editor/ObjectIcons/character.bmp | 3 -- Assets/Editor/ObjectIcons/death.bmp | 3 -- Assets/Editor/ObjectIcons/door.bmp | 3 -- Assets/Editor/ObjectIcons/elevator.bmp | 3 -- .../Editor/ObjectIcons/environmentProbe.bmp | 3 -- Assets/Editor/ObjectIcons/explosion.bmp | 3 -- Assets/Editor/ObjectIcons/fish.bmp | 3 -- Assets/Editor/ObjectIcons/forbiddenarea.bmp | 3 -- Assets/Editor/ObjectIcons/hazard.bmp | 3 -- Assets/Editor/ObjectIcons/health.bmp | 3 -- Assets/Editor/ObjectIcons/ledge.bmp | 3 -- Assets/Editor/ObjectIcons/mine.bmp | 3 -- Assets/Editor/ObjectIcons/physicsobject.bmp | 3 -- Assets/Editor/ObjectIcons/prefabbuilding.bmp | 3 -- .../Editor/ObjectIcons/proceduralbuilding.bmp | 3 -- .../Editor/ObjectIcons/proceduralobject.bmp | 3 -- .../Editor/ObjectIcons/proximitytrigger.bmp | 3 -- Assets/Editor/ObjectIcons/river.bmp | 3 -- Assets/Editor/ObjectIcons/road.bmp | 3 -- Assets/Editor/ObjectIcons/rope.bmp | 3 -- Assets/Editor/ObjectIcons/sequence.bmp | 3 -- Assets/Editor/ObjectIcons/shake.bmp | 3 -- Assets/Editor/ObjectIcons/smartobject.bmp | 3 -- Assets/Editor/ObjectIcons/spawngroup.bmp | 3 -- Assets/Editor/ObjectIcons/spectator.bmp | 3 -- Assets/Editor/ObjectIcons/switch.bmp | 3 -- Assets/Editor/ObjectIcons/territory.bmp | 3 -- Assets/Editor/ObjectIcons/tornado.bmp | 3 -- Assets/Editor/ObjectIcons/vehicle.bmp | 3 -- Assets/Editor/ObjectIcons/voxel.bmp | 3 -- Assets/Editor/ObjectIcons/wave.bmp | 3 -- .../Editor/Scripts/Shelves/icons/Albedo.png | 3 -- .../Shelves/icons/Diffuse_Lighting.png | 3 -- .../Shelves/icons/Diffuse_Texture_Res_360.png | 3 -- .../Scripts/Shelves/icons/Empty_Wireframe.png | 3 -- Assets/Editor/Scripts/Shelves/icons/Exit.png | 3 -- .../Scripts/Shelves/icons/Fuzziness.png | 3 -- Assets/Editor/Scripts/Shelves/icons/Gloss.png | 3 -- .../Shelves/icons/Normal_Texture_Res_360.png | 3 -- .../Shelves/icons/PrefabAddLibrary.png | 3 -- .../Shelves/icons/PrefabAddSelection.png | 3 -- .../Scripts/Shelves/icons/PrefabBreak.png | 3 -- .../Scripts/Shelves/icons/PrefabConvert.png | 3 -- .../Scripts/Shelves/icons/PrefabCreate.png | 3 -- .../Scripts/Shelves/icons/PrefabIsolate.png | 3 -- .../Scripts/Shelves/icons/Scattering.png | 3 -- .../Scripts/Shelves/icons/Solid_Wireframe.png | 3 -- .../Scripts/Shelves/icons/Spec_Amount.png | 3 -- .../Scripts/Shelves/icons/Spec_Lighting.png | 3 -- .../Shelves/icons/Texel_Per_Meter_1024.png | 3 -- .../Shelves/icons/Texel_Per_Meter_256.png | 3 -- .../Shelves/icons/Texel_Per_Meter_512.png | 3 -- Assets/Editor/Scripts/Shelves/icons/all.png | 3 -- Assets/Editor/Scripts/Shelves/icons/beams.png | 3 -- .../Editor/Scripts/Shelves/icons/blanker.png | 3 -- .../Scripts/Shelves/icons/bounding_box.png | 3 -- .../Editor/Scripts/Shelves/icons/brushes.png | 3 -- Assets/Editor/Scripts/Shelves/icons/cloud.png | 3 -- .../Scripts/Shelves/icons/cloud_dark.png | 3 -- .../Scripts/Shelves/icons/cloud_dark_rain.png | 3 -- .../Scripts/Shelves/icons/collisions.png | 3 -- .../Shelves/icons/create_ao_volume_box.png | 3 -- .../icons/create_both_vis_box_envprobe.png | 3 -- .../Scripts/Shelves/icons/create_envprobe.png | 3 -- .../Shelves/icons/create_portal_box.png | 3 -- .../Scripts/Shelves/icons/create_vis_box.png | 3 -- .../icons/create_vis_box_and_portal_box.png | 3 -- .../create_vis_box_env_probe_and_portal.png | 3 -- .../Editor/Scripts/Shelves/icons/cubemap.png | 3 -- .../Editor/Scripts/Shelves/icons/decals.png | 3 -- .../Shelves/icons/default_material.png | 3 -- .../icons/default_material_with_normals.png | 3 -- .../Editor/Scripts/Shelves/icons/designer.png | 3 -- .../Editor/Scripts/Shelves/icons/diff_acc.png | 3 -- .../Scripts/Shelves/icons/display_info.png | 3 -- .../Scripts/Shelves/icons/dual_layer_mask.png | 3 -- .../Scripts/Shelves/icons/dynamiclights.png | 3 -- .../Editor/Scripts/Shelves/icons/entities.png | 3 -- .../Shelves/icons/eye_adaptation_speed.png | 3 -- Assets/Editor/Scripts/Shelves/icons/fog.png | 3 -- .../Scripts/Shelves/icons/fogvolumes.png | 3 -- .../Shelves/icons/freeze_particles.png | 3 -- .../Scripts/Shelves/icons/full_shading.png | 3 -- Assets/Editor/Scripts/Shelves/icons/gamma.png | 3 -- Assets/Editor/Scripts/Shelves/icons/gi.png | 3 -- .../Scripts/Shelves/icons/lens_flare.png | 3 -- .../Scripts/Shelves/icons/lighting_only.png | 3 -- Assets/Editor/Scripts/Shelves/icons/lods.png | 3 -- Assets/Editor/Scripts/Shelves/icons/lsao.png | 3 -- .../Scripts/Shelves/icons/lsao_toggle.png | 3 -- Assets/Editor/Scripts/Shelves/icons/lsro.png | 3 -- .../Editor/Scripts/Shelves/icons/normals.png | 3 -- .../Scripts/Shelves/icons/normals_x.png | 3 -- .../Scripts/Shelves/icons/normals_y.png | 3 -- .../Scripts/Shelves/icons/normals_z.png | 3 -- Assets/Editor/Scripts/Shelves/icons/ocean.png | 3 -- .../Scripts/Shelves/icons/particles.png | 3 -- .../Shelves/icons/particles_bounds.png | 3 -- .../Scripts/Shelves/icons/particles_off.png | 3 -- .../Shelves/icons/particles_overdraw.png | 3 -- .../icons/particles_screen_coverage.png | 3 -- .../Scripts/Shelves/icons/placeholder.png | 3 -- .../Editor/Scripts/Shelves/icons/prefab.png | 3 -- .../Scripts/Shelves/icons/reflections.png | 3 -- Assets/Editor/Scripts/Shelves/icons/reset.png | 3 -- .../Editor/Scripts/Shelves/icons/selfocc.png | 3 -- .../Shelves/icons/shaded_wireframe.png | 3 -- .../Editor/Scripts/Shelves/icons/shadows.png | 3 -- .../Scripts/Shelves/icons/showlines.png | 3 -- Assets/Editor/Scripts/Shelves/icons/sky.png | 3 -- .../Editor/Scripts/Shelves/icons/spec_acc.png | 3 -- .../Editor/Scripts/Shelves/icons/spec_lum.png | 3 -- .../Editor/Scripts/Shelves/icons/spec_occ.png | 3 -- Assets/Editor/Scripts/Shelves/icons/ssao.png | 3 -- Assets/Editor/Scripts/Shelves/icons/ssdo.png | 3 -- .../Scripts/Shelves/icons/ssdo_toggle.png | 3 -- .../Editor/Scripts/Shelves/icons/sun.big.png | 3 -- .../Editor/Scripts/Shelves/icons/tangents.png | 3 -- .../Editor/Scripts/Shelves/icons/terrain.png | 3 -- .../Shelves/icons/time_scale_double.png | 3 -- .../Shelves/icons/time_scale_frozen.png | 3 -- .../Scripts/Shelves/icons/time_scale_half.png | 3 -- .../Shelves/icons/time_scale_quarter.png | 3 -- .../Shelves/icons/time_scale_tenth.png | 3 -- Assets/Editor/Scripts/Shelves/icons/tod.png | 3 -- .../Scripts/Shelves/icons/translucency.png | 3 -- .../Scripts/Shelves/icons/transparency.png | 3 -- .../Scripts/Shelves/icons/valid_albedo.png | 3 -- .../Scripts/Shelves/icons/valid_spec_lum.png | 3 -- .../Scripts/Shelves/icons/vegetation.png | 3 -- .../Scripts/Shelves/icons/vertex_normals.png | 3 -- .../Editor/Scripts/Shelves/icons/vis_area.png | 3 -- .../Scripts/Shelves/icons/water_volume.png | 3 -- Assets/Editor/Scripts/Shelves/icons/wind.png | 3 -- .../Scripts/Shelves/icons/wireframe.png | 3 -- Code/Editor/ToolBox.cpp | 31 +------------------ Code/Editor/ToolBox.h | 1 - 181 files changed, 1 insertion(+), 568 deletions(-) delete mode 100644 Assets/Editor/ObjectIcons/AreaTrigger.bmp delete mode 100644 Assets/Editor/ObjectIcons/AudioAreaAmbience.bmp delete mode 100644 Assets/Editor/ObjectIcons/AudioAreaEntity.bmp delete mode 100644 Assets/Editor/ObjectIcons/AudioAreaRandom.bmp delete mode 100644 Assets/Editor/ObjectIcons/Camera.bmp delete mode 100644 Assets/Editor/ObjectIcons/Checkpoint.bmp delete mode 100644 Assets/Editor/ObjectIcons/ClipVolume.bmp delete mode 100644 Assets/Editor/ObjectIcons/Clock.bmp delete mode 100644 Assets/Editor/ObjectIcons/Clouds.bmp delete mode 100644 Assets/Editor/ObjectIcons/Comment.bmp delete mode 100644 Assets/Editor/ObjectIcons/DeadBody.bmp delete mode 100644 Assets/Editor/ObjectIcons/Decal.bmp delete mode 100644 Assets/Editor/ObjectIcons/Dialog.bmp delete mode 100644 Assets/Editor/ObjectIcons/Flash.bmp delete mode 100644 Assets/Editor/ObjectIcons/Fog.bmp delete mode 100644 Assets/Editor/ObjectIcons/FogVolume.bmp delete mode 100644 Assets/Editor/ObjectIcons/GravitySphere.bmp delete mode 100644 Assets/Editor/ObjectIcons/Item.bmp delete mode 100644 Assets/Editor/ObjectIcons/Ladder.bmp delete mode 100644 Assets/Editor/ObjectIcons/Light.bmp delete mode 100644 Assets/Editor/ObjectIcons/LightPropagationVolume.bmp delete mode 100644 Assets/Editor/ObjectIcons/Lightning.bmp delete mode 100644 Assets/Editor/ObjectIcons/Magnet.bmp delete mode 100644 Assets/Editor/ObjectIcons/MultiTrigger.bmp delete mode 100644 Assets/Editor/ObjectIcons/ODD.bmp delete mode 100644 Assets/Editor/ObjectIcons/Particles.bmp delete mode 100644 Assets/Editor/ObjectIcons/PrecacheCamera.bmp delete mode 100644 Assets/Editor/ObjectIcons/Prefab.bmp delete mode 100644 Assets/Editor/ObjectIcons/Prompt.bmp delete mode 100644 Assets/Editor/ObjectIcons/SavePoint.bmp delete mode 100644 Assets/Editor/ObjectIcons/Seed.bmp delete mode 100644 Assets/Editor/ObjectIcons/Sound.bmp delete mode 100644 Assets/Editor/ObjectIcons/SpawnPoint.bmp delete mode 100644 Assets/Editor/ObjectIcons/T.bmp delete mode 100644 Assets/Editor/ObjectIcons/TagPoint.bmp delete mode 100644 Assets/Editor/ObjectIcons/Trigger.bmp delete mode 100644 Assets/Editor/ObjectIcons/UiCanvasRefEntity.bmp delete mode 100644 Assets/Editor/ObjectIcons/User.bmp delete mode 100644 Assets/Editor/ObjectIcons/VVVArea.bmp delete mode 100644 Assets/Editor/ObjectIcons/W.bmp delete mode 100644 Assets/Editor/ObjectIcons/Water.bmp delete mode 100644 Assets/Editor/ObjectIcons/animobject.bmp delete mode 100644 Assets/Editor/ObjectIcons/bird.bmp delete mode 100644 Assets/Editor/ObjectIcons/bug.bmp delete mode 100644 Assets/Editor/ObjectIcons/character.bmp delete mode 100644 Assets/Editor/ObjectIcons/death.bmp delete mode 100644 Assets/Editor/ObjectIcons/door.bmp delete mode 100644 Assets/Editor/ObjectIcons/elevator.bmp delete mode 100644 Assets/Editor/ObjectIcons/environmentProbe.bmp delete mode 100644 Assets/Editor/ObjectIcons/explosion.bmp delete mode 100644 Assets/Editor/ObjectIcons/fish.bmp delete mode 100644 Assets/Editor/ObjectIcons/forbiddenarea.bmp delete mode 100644 Assets/Editor/ObjectIcons/hazard.bmp delete mode 100644 Assets/Editor/ObjectIcons/health.bmp delete mode 100644 Assets/Editor/ObjectIcons/ledge.bmp delete mode 100644 Assets/Editor/ObjectIcons/mine.bmp delete mode 100644 Assets/Editor/ObjectIcons/physicsobject.bmp delete mode 100644 Assets/Editor/ObjectIcons/prefabbuilding.bmp delete mode 100644 Assets/Editor/ObjectIcons/proceduralbuilding.bmp delete mode 100644 Assets/Editor/ObjectIcons/proceduralobject.bmp delete mode 100644 Assets/Editor/ObjectIcons/proximitytrigger.bmp delete mode 100644 Assets/Editor/ObjectIcons/river.bmp delete mode 100644 Assets/Editor/ObjectIcons/road.bmp delete mode 100644 Assets/Editor/ObjectIcons/rope.bmp delete mode 100644 Assets/Editor/ObjectIcons/sequence.bmp delete mode 100644 Assets/Editor/ObjectIcons/shake.bmp delete mode 100644 Assets/Editor/ObjectIcons/smartobject.bmp delete mode 100644 Assets/Editor/ObjectIcons/spawngroup.bmp delete mode 100644 Assets/Editor/ObjectIcons/spectator.bmp delete mode 100644 Assets/Editor/ObjectIcons/switch.bmp delete mode 100644 Assets/Editor/ObjectIcons/territory.bmp delete mode 100644 Assets/Editor/ObjectIcons/tornado.bmp delete mode 100644 Assets/Editor/ObjectIcons/vehicle.bmp delete mode 100644 Assets/Editor/ObjectIcons/voxel.bmp delete mode 100644 Assets/Editor/ObjectIcons/wave.bmp delete mode 100644 Assets/Editor/Scripts/Shelves/icons/Albedo.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/Diffuse_Lighting.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/Diffuse_Texture_Res_360.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/Empty_Wireframe.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/Exit.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/Fuzziness.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/Gloss.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/Normal_Texture_Res_360.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/PrefabAddLibrary.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/PrefabAddSelection.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/PrefabBreak.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/PrefabConvert.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/PrefabCreate.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/PrefabIsolate.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/Scattering.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/Solid_Wireframe.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/Spec_Amount.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/Spec_Lighting.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/Texel_Per_Meter_1024.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/Texel_Per_Meter_256.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/Texel_Per_Meter_512.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/all.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/beams.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/blanker.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/bounding_box.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/brushes.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/cloud.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/cloud_dark.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/cloud_dark_rain.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/collisions.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/create_ao_volume_box.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/create_both_vis_box_envprobe.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/create_envprobe.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/create_portal_box.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/create_vis_box.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/create_vis_box_and_portal_box.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/create_vis_box_env_probe_and_portal.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/cubemap.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/decals.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/default_material.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/default_material_with_normals.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/designer.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/diff_acc.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/display_info.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/dual_layer_mask.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/dynamiclights.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/entities.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/eye_adaptation_speed.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/fog.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/fogvolumes.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/freeze_particles.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/full_shading.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/gamma.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/gi.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/lens_flare.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/lighting_only.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/lods.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/lsao.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/lsao_toggle.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/lsro.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/normals.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/normals_x.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/normals_y.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/normals_z.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/ocean.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/particles.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/particles_bounds.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/particles_off.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/particles_overdraw.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/particles_screen_coverage.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/placeholder.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/prefab.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/reflections.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/reset.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/selfocc.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/shaded_wireframe.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/shadows.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/showlines.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/sky.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/spec_acc.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/spec_lum.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/spec_occ.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/ssao.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/ssdo.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/ssdo_toggle.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/sun.big.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/tangents.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/terrain.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/time_scale_double.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/time_scale_frozen.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/time_scale_half.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/time_scale_quarter.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/time_scale_tenth.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/tod.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/translucency.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/transparency.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/valid_albedo.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/valid_spec_lum.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/vegetation.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/vertex_normals.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/vis_area.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/water_volume.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/wind.png delete mode 100644 Assets/Editor/Scripts/Shelves/icons/wireframe.png diff --git a/Assets/Editor/ObjectIcons/AreaTrigger.bmp b/Assets/Editor/ObjectIcons/AreaTrigger.bmp deleted file mode 100644 index 779e9bd30f..0000000000 --- a/Assets/Editor/ObjectIcons/AreaTrigger.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4cf08659d31a337ceb28de2765b0177abf404f3e671f5277dd7a280f2fd6c60d -size 3128 diff --git a/Assets/Editor/ObjectIcons/AudioAreaAmbience.bmp b/Assets/Editor/ObjectIcons/AudioAreaAmbience.bmp deleted file mode 100644 index 052eb463cb..0000000000 --- a/Assets/Editor/ObjectIcons/AudioAreaAmbience.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:706b12b37518596b01fc6c5cdb3aadc5fdbe76b668e9989ba2bb03ee23376dbf -size 3126 diff --git a/Assets/Editor/ObjectIcons/AudioAreaEntity.bmp b/Assets/Editor/ObjectIcons/AudioAreaEntity.bmp deleted file mode 100644 index b490f91bc4..0000000000 --- a/Assets/Editor/ObjectIcons/AudioAreaEntity.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:7e67540926b2d55c70ac5867266ac9688437fc139b459f165f9d52d9b351851c -size 3128 diff --git a/Assets/Editor/ObjectIcons/AudioAreaRandom.bmp b/Assets/Editor/ObjectIcons/AudioAreaRandom.bmp deleted file mode 100644 index 73a0a21256..0000000000 --- a/Assets/Editor/ObjectIcons/AudioAreaRandom.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:96ec04e8126bcffb7fe391dc55ea1aa6a82419825c8305117f9b0ae72b40e63e -size 3126 diff --git a/Assets/Editor/ObjectIcons/Camera.bmp b/Assets/Editor/ObjectIcons/Camera.bmp deleted file mode 100644 index fd89801011..0000000000 --- a/Assets/Editor/ObjectIcons/Camera.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4168676b803b7e3b03a90fb69502204a418b6598941c75f0c36e589a31455db5 -size 3128 diff --git a/Assets/Editor/ObjectIcons/Checkpoint.bmp b/Assets/Editor/ObjectIcons/Checkpoint.bmp deleted file mode 100644 index fd31d3c446..0000000000 --- a/Assets/Editor/ObjectIcons/Checkpoint.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b11c94da25b704a36f2b437dae98c04a5cea54f02022567306e2cf82837bf7a1 -size 3128 diff --git a/Assets/Editor/ObjectIcons/ClipVolume.bmp b/Assets/Editor/ObjectIcons/ClipVolume.bmp deleted file mode 100644 index dba0aa32ba..0000000000 --- a/Assets/Editor/ObjectIcons/ClipVolume.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8ca14c966de6d392beb4d154221b622a417163fcdf92eb049638bf8495c13774 -size 3128 diff --git a/Assets/Editor/ObjectIcons/Clock.bmp b/Assets/Editor/ObjectIcons/Clock.bmp deleted file mode 100644 index 1557a7e8dc..0000000000 --- a/Assets/Editor/ObjectIcons/Clock.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6d11fd9413f06706bc706a97f39cc72b1ae6ff7cb6c506cf2fcda98660e2a92f -size 3128 diff --git a/Assets/Editor/ObjectIcons/Clouds.bmp b/Assets/Editor/ObjectIcons/Clouds.bmp deleted file mode 100644 index 4530661aac..0000000000 --- a/Assets/Editor/ObjectIcons/Clouds.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:1f5fd7032f82fbb7364cd0a96989918defd63f26a899836c61b039541cf3b3af -size 3128 diff --git a/Assets/Editor/ObjectIcons/Comment.bmp b/Assets/Editor/ObjectIcons/Comment.bmp deleted file mode 100644 index 78a8d8f4fa..0000000000 --- a/Assets/Editor/ObjectIcons/Comment.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9201d97225c19b8fc2fc208ab913ab100a94328b64b026ab65be9c4cd9c4e28a -size 3128 diff --git a/Assets/Editor/ObjectIcons/DeadBody.bmp b/Assets/Editor/ObjectIcons/DeadBody.bmp deleted file mode 100644 index ffebc73608..0000000000 --- a/Assets/Editor/ObjectIcons/DeadBody.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a2937837233d9f313b2500232c74952cee3f4e7497ee0e1099b301ef2fa49bf8 -size 3128 diff --git a/Assets/Editor/ObjectIcons/Decal.bmp b/Assets/Editor/ObjectIcons/Decal.bmp deleted file mode 100644 index 4b33fe7422..0000000000 --- a/Assets/Editor/ObjectIcons/Decal.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ffbe8438c19ac2a9b6614beb78f0d651184dbe5cf2998063257dc7272c9c2c10 -size 3128 diff --git a/Assets/Editor/ObjectIcons/Dialog.bmp b/Assets/Editor/ObjectIcons/Dialog.bmp deleted file mode 100644 index 0722f5f1e4..0000000000 --- a/Assets/Editor/ObjectIcons/Dialog.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:63640478bd3258aa310dd639014cde714780ebaa168aa784093e74fc0da23a4c -size 3126 diff --git a/Assets/Editor/ObjectIcons/Flash.bmp b/Assets/Editor/ObjectIcons/Flash.bmp deleted file mode 100644 index d7f02ed44b..0000000000 --- a/Assets/Editor/ObjectIcons/Flash.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b66daefbb3f11f527d9c10ff1dd54f87635e6561cc546a762ae2e72793ae6ef6 -size 3128 diff --git a/Assets/Editor/ObjectIcons/Fog.bmp b/Assets/Editor/ObjectIcons/Fog.bmp deleted file mode 100644 index 2af489a79a..0000000000 --- a/Assets/Editor/ObjectIcons/Fog.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:42e0c1dc60809958d74145ae14030c22e351ef3b72ed6d820fdb19632b691c89 -size 3128 diff --git a/Assets/Editor/ObjectIcons/FogVolume.bmp b/Assets/Editor/ObjectIcons/FogVolume.bmp deleted file mode 100644 index 78d20bff41..0000000000 --- a/Assets/Editor/ObjectIcons/FogVolume.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:2cbb23fc09d47d16b2414d622fd16b330d9f684398dcfc44e0fb44378dfd3287 -size 3128 diff --git a/Assets/Editor/ObjectIcons/GravitySphere.bmp b/Assets/Editor/ObjectIcons/GravitySphere.bmp deleted file mode 100644 index 06168d4698..0000000000 --- a/Assets/Editor/ObjectIcons/GravitySphere.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:26b6e2f28ed72b9cdb90410351e3a22fee3c0498ac315e71d966a1ffb77742fe -size 3128 diff --git a/Assets/Editor/ObjectIcons/Item.bmp b/Assets/Editor/ObjectIcons/Item.bmp deleted file mode 100644 index 15c610cad2..0000000000 --- a/Assets/Editor/ObjectIcons/Item.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:bd6f39152affb52a7b3c4361032d1d7d77e7e94841613a83d7e2cdea9eaab553 -size 3128 diff --git a/Assets/Editor/ObjectIcons/Ladder.bmp b/Assets/Editor/ObjectIcons/Ladder.bmp deleted file mode 100644 index dbd4a288e7..0000000000 --- a/Assets/Editor/ObjectIcons/Ladder.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:077502953026981b6e8cc5e40ab58722fc514947f175021508e6af8058340f32 -size 3128 diff --git a/Assets/Editor/ObjectIcons/Light.bmp b/Assets/Editor/ObjectIcons/Light.bmp deleted file mode 100644 index 6a3347e78c..0000000000 --- a/Assets/Editor/ObjectIcons/Light.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c9ecfc056ab66b3221be3175889d182229c0e49bf9604abd7946fe58cc7d29a9 -size 3128 diff --git a/Assets/Editor/ObjectIcons/LightPropagationVolume.bmp b/Assets/Editor/ObjectIcons/LightPropagationVolume.bmp deleted file mode 100644 index 4ad9437883..0000000000 --- a/Assets/Editor/ObjectIcons/LightPropagationVolume.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:206820d3bb5d6a4d26bf87fc0b91a36adcbd0f154149b7cb5f5ce067f5ee4d67 -size 3128 diff --git a/Assets/Editor/ObjectIcons/Lightning.bmp b/Assets/Editor/ObjectIcons/Lightning.bmp deleted file mode 100644 index 5c02d0368c..0000000000 --- a/Assets/Editor/ObjectIcons/Lightning.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d7c81a8000339695f73277bcebaedb0cfeacdff547f51c1ff7f4761c75927ca4 -size 3126 diff --git a/Assets/Editor/ObjectIcons/Magnet.bmp b/Assets/Editor/ObjectIcons/Magnet.bmp deleted file mode 100644 index 68b6e4e7e4..0000000000 --- a/Assets/Editor/ObjectIcons/Magnet.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:560c3af6e8f2fb98ddc8638b0ea4786131e75b6fe0acece964bfdb28f8c3ec9f -size 3128 diff --git a/Assets/Editor/ObjectIcons/MultiTrigger.bmp b/Assets/Editor/ObjectIcons/MultiTrigger.bmp deleted file mode 100644 index e96dc6f1b7..0000000000 --- a/Assets/Editor/ObjectIcons/MultiTrigger.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8a3a64d33b65c4cd5d666c11abf03b4148acadfe69e4c80e79382b56d2906ae6 -size 3128 diff --git a/Assets/Editor/ObjectIcons/ODD.bmp b/Assets/Editor/ObjectIcons/ODD.bmp deleted file mode 100644 index 5c5a7bbd89..0000000000 --- a/Assets/Editor/ObjectIcons/ODD.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:113d0a416da49ce24dae2c47514318b75e0ca4d7dc257a9927e0db4bdad35d91 -size 3128 diff --git a/Assets/Editor/ObjectIcons/Particles.bmp b/Assets/Editor/ObjectIcons/Particles.bmp deleted file mode 100644 index 8f71edb74f..0000000000 --- a/Assets/Editor/ObjectIcons/Particles.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6ca81d96a5450660f7e17f75565595368fb7c0071df9589bcbfda2ba54d5c0ae -size 3128 diff --git a/Assets/Editor/ObjectIcons/PrecacheCamera.bmp b/Assets/Editor/ObjectIcons/PrecacheCamera.bmp deleted file mode 100644 index 8f1dca751a..0000000000 --- a/Assets/Editor/ObjectIcons/PrecacheCamera.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:73629b1903365aa6acf35fd7846896c23c38401fac12bc23b23285e5ed9ae89d -size 3126 diff --git a/Assets/Editor/ObjectIcons/Prefab.bmp b/Assets/Editor/ObjectIcons/Prefab.bmp deleted file mode 100644 index 539a0f5a56..0000000000 --- a/Assets/Editor/ObjectIcons/Prefab.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6d7fbb76f67165492a51e6b8715ee3716040d44bd5419b12481e2c9cc627c291 -size 3128 diff --git a/Assets/Editor/ObjectIcons/Prompt.bmp b/Assets/Editor/ObjectIcons/Prompt.bmp deleted file mode 100644 index 1e9b18a97c..0000000000 --- a/Assets/Editor/ObjectIcons/Prompt.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:2482da67fbf513a9597b3919562a65d361a4c8264fcc8510ef45321b4192ce4d -size 3128 diff --git a/Assets/Editor/ObjectIcons/SavePoint.bmp b/Assets/Editor/ObjectIcons/SavePoint.bmp deleted file mode 100644 index ce602eeeb4..0000000000 --- a/Assets/Editor/ObjectIcons/SavePoint.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:06f866e66e0458ccf3e014a30fef2dfaab832d9b4b1179f98b7cdd716b358b48 -size 3128 diff --git a/Assets/Editor/ObjectIcons/Seed.bmp b/Assets/Editor/ObjectIcons/Seed.bmp deleted file mode 100644 index 3a9452d982..0000000000 --- a/Assets/Editor/ObjectIcons/Seed.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:fdcea1e14d3b01b1ed6ea123767343eddc646969ee447b4bf725c233fd7946f4 -size 3128 diff --git a/Assets/Editor/ObjectIcons/Sound.bmp b/Assets/Editor/ObjectIcons/Sound.bmp deleted file mode 100644 index 06ab261be3..0000000000 --- a/Assets/Editor/ObjectIcons/Sound.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:14a4003a9faf9a2fb3a17d2f87825c8497aeaca364c592ab75970d00e77aa203 -size 3128 diff --git a/Assets/Editor/ObjectIcons/SpawnPoint.bmp b/Assets/Editor/ObjectIcons/SpawnPoint.bmp deleted file mode 100644 index b04a20e8c0..0000000000 --- a/Assets/Editor/ObjectIcons/SpawnPoint.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f7e109f57e5e9bc6bcaee7176a479bb6434353bc49a8021ab96e016ce27f41a1 -size 3128 diff --git a/Assets/Editor/ObjectIcons/T.bmp b/Assets/Editor/ObjectIcons/T.bmp deleted file mode 100644 index 767782c43d..0000000000 --- a/Assets/Editor/ObjectIcons/T.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4c2288c239604402f7e85d753141fbd8a82fde9f18e4f95006b039ceeec41d0c -size 3128 diff --git a/Assets/Editor/ObjectIcons/TagPoint.bmp b/Assets/Editor/ObjectIcons/TagPoint.bmp deleted file mode 100644 index 36727d9c4a..0000000000 --- a/Assets/Editor/ObjectIcons/TagPoint.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8f58cabe21df546914abc1e8f2604989d87b4a3471c1902956a4e1e1be9930b8 -size 3128 diff --git a/Assets/Editor/ObjectIcons/Trigger.bmp b/Assets/Editor/ObjectIcons/Trigger.bmp deleted file mode 100644 index ef712e4b09..0000000000 --- a/Assets/Editor/ObjectIcons/Trigger.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e9cfb325abea577e8737b837098ff3cecd564e302b2c30925b3d35a62fa6c7c3 -size 3128 diff --git a/Assets/Editor/ObjectIcons/UiCanvasRefEntity.bmp b/Assets/Editor/ObjectIcons/UiCanvasRefEntity.bmp deleted file mode 100644 index c1ff4d3291..0000000000 --- a/Assets/Editor/ObjectIcons/UiCanvasRefEntity.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:bcd9a1efaab42cdea4557265e544f2370565872115d21cc84af6e6998bb7ad01 -size 3128 diff --git a/Assets/Editor/ObjectIcons/User.bmp b/Assets/Editor/ObjectIcons/User.bmp deleted file mode 100644 index 780242c15c..0000000000 --- a/Assets/Editor/ObjectIcons/User.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:56a379a337a44617cb6ed5a20560286b8263c75871742ca04cc61cac49736a2a -size 3128 diff --git a/Assets/Editor/ObjectIcons/VVVArea.bmp b/Assets/Editor/ObjectIcons/VVVArea.bmp deleted file mode 100644 index 82712dda92..0000000000 --- a/Assets/Editor/ObjectIcons/VVVArea.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9cab80e4ce74155a3eaf771fa9b2464c1f3b36bce6de55d3f5aa180576cabec2 -size 3128 diff --git a/Assets/Editor/ObjectIcons/W.bmp b/Assets/Editor/ObjectIcons/W.bmp deleted file mode 100644 index 40448a6334..0000000000 --- a/Assets/Editor/ObjectIcons/W.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6ebc8eacd6695caafd131d5c8ca29b45fea16bc2147cdb169478e391d6f13b70 -size 3128 diff --git a/Assets/Editor/ObjectIcons/Water.bmp b/Assets/Editor/ObjectIcons/Water.bmp deleted file mode 100644 index fb7d6c7b51..0000000000 --- a/Assets/Editor/ObjectIcons/Water.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e5d24ecf0878409dc3f7ed0f447734061bb9e313e4adb767580bd961b0038236 -size 3126 diff --git a/Assets/Editor/ObjectIcons/animobject.bmp b/Assets/Editor/ObjectIcons/animobject.bmp deleted file mode 100644 index d28e4c016a..0000000000 --- a/Assets/Editor/ObjectIcons/animobject.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:514fb756bd23f0376a03ba7222a5a8479408eb68efbfcecac30957142580e494 -size 3128 diff --git a/Assets/Editor/ObjectIcons/bird.bmp b/Assets/Editor/ObjectIcons/bird.bmp deleted file mode 100644 index b6431dc2cf..0000000000 --- a/Assets/Editor/ObjectIcons/bird.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e7d72d46274c9c0863e7e34caccfdf78a7c8c77262caf1b7f4305a822ac0145c -size 3128 diff --git a/Assets/Editor/ObjectIcons/bug.bmp b/Assets/Editor/ObjectIcons/bug.bmp deleted file mode 100644 index 86cb76bed0..0000000000 --- a/Assets/Editor/ObjectIcons/bug.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d238a0d17e3469c499249bd907b5aba0b924fb8539259a1b92af64e39820b619 -size 3128 diff --git a/Assets/Editor/ObjectIcons/character.bmp b/Assets/Editor/ObjectIcons/character.bmp deleted file mode 100644 index a37997e7bf..0000000000 --- a/Assets/Editor/ObjectIcons/character.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4b7bd2ee00f000d13ef096bd4d430fbca5cd35f3d641d44f4698c1270423b484 -size 3128 diff --git a/Assets/Editor/ObjectIcons/death.bmp b/Assets/Editor/ObjectIcons/death.bmp deleted file mode 100644 index 98c673af1d..0000000000 --- a/Assets/Editor/ObjectIcons/death.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9d93aa4486316a2ba269f860d64f741da15359fec6111da1049331a5a75dee02 -size 3128 diff --git a/Assets/Editor/ObjectIcons/door.bmp b/Assets/Editor/ObjectIcons/door.bmp deleted file mode 100644 index 3c95318ef9..0000000000 --- a/Assets/Editor/ObjectIcons/door.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4be7c244d9350a46c18161222ace0eaea1213dd1e7ed5ba02fa94ee5a98dc728 -size 3128 diff --git a/Assets/Editor/ObjectIcons/elevator.bmp b/Assets/Editor/ObjectIcons/elevator.bmp deleted file mode 100644 index b256426aef..0000000000 --- a/Assets/Editor/ObjectIcons/elevator.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6c1cf46f0825ecf1d3331bdca3d5f6a0d348aa6346af9fb1fdb3b75cfc5564dd -size 3128 diff --git a/Assets/Editor/ObjectIcons/environmentProbe.bmp b/Assets/Editor/ObjectIcons/environmentProbe.bmp deleted file mode 100644 index 0a23ebb9f4..0000000000 --- a/Assets/Editor/ObjectIcons/environmentProbe.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:27c8ae2924af50058207e7a1e1f4e35799f27abd7cb2e0778b8903ce00e99732 -size 4152 diff --git a/Assets/Editor/ObjectIcons/explosion.bmp b/Assets/Editor/ObjectIcons/explosion.bmp deleted file mode 100644 index 27213da651..0000000000 --- a/Assets/Editor/ObjectIcons/explosion.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a93e2e2164781ed0de1be34bbbd0c85d630a31efd3fe568ea7f3c026646209c8 -size 3128 diff --git a/Assets/Editor/ObjectIcons/fish.bmp b/Assets/Editor/ObjectIcons/fish.bmp deleted file mode 100644 index 9c1d0b2d21..0000000000 --- a/Assets/Editor/ObjectIcons/fish.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:590e0458bbc0d528ba71cd048b6019ebb8d1764a55cc3b9b3e2b1446182cfaa9 -size 3128 diff --git a/Assets/Editor/ObjectIcons/forbiddenarea.bmp b/Assets/Editor/ObjectIcons/forbiddenarea.bmp deleted file mode 100644 index b41c47bf72..0000000000 --- a/Assets/Editor/ObjectIcons/forbiddenarea.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6a8eac076d5094c722513bcdb6b71def9116ae063d453017d7bb0b38068c3a7e -size 3128 diff --git a/Assets/Editor/ObjectIcons/hazard.bmp b/Assets/Editor/ObjectIcons/hazard.bmp deleted file mode 100644 index 4779f3730a..0000000000 --- a/Assets/Editor/ObjectIcons/hazard.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:71c3e9e9ccf404c3c17f71f806cd6ee0e4b48f6f2e172b52aeca78cc28668ac3 -size 3128 diff --git a/Assets/Editor/ObjectIcons/health.bmp b/Assets/Editor/ObjectIcons/health.bmp deleted file mode 100644 index 01833903c3..0000000000 --- a/Assets/Editor/ObjectIcons/health.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:3ded11545905ac937fe6e28929e57c10abe55befa74b44260dee5b206cdf3d15 -size 3128 diff --git a/Assets/Editor/ObjectIcons/ledge.bmp b/Assets/Editor/ObjectIcons/ledge.bmp deleted file mode 100644 index 3d6784fb44..0000000000 --- a/Assets/Editor/ObjectIcons/ledge.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c43daede42eb72eca0f80454b0e70de1e03156b5f098bcc8dbc080117c34380a -size 3128 diff --git a/Assets/Editor/ObjectIcons/mine.bmp b/Assets/Editor/ObjectIcons/mine.bmp deleted file mode 100644 index 8f4394a2dd..0000000000 --- a/Assets/Editor/ObjectIcons/mine.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:da1bb03a55949c6dc80ac18e3cf87c962e30fe2eacfd4fac74cc93db58552ac5 -size 3128 diff --git a/Assets/Editor/ObjectIcons/physicsobject.bmp b/Assets/Editor/ObjectIcons/physicsobject.bmp deleted file mode 100644 index 00bb3f2380..0000000000 --- a/Assets/Editor/ObjectIcons/physicsobject.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:74cdfbf6f61029fa6f1262f78c2787afb9dddc0218911b53349962c4ed548bbf -size 3128 diff --git a/Assets/Editor/ObjectIcons/prefabbuilding.bmp b/Assets/Editor/ObjectIcons/prefabbuilding.bmp deleted file mode 100644 index e416cbafe1..0000000000 --- a/Assets/Editor/ObjectIcons/prefabbuilding.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:98aaf6d6e532f5a3f31cdc08676432e30b4e52fd4f376331f4610379f288a191 -size 3128 diff --git a/Assets/Editor/ObjectIcons/proceduralbuilding.bmp b/Assets/Editor/ObjectIcons/proceduralbuilding.bmp deleted file mode 100644 index e416cbafe1..0000000000 --- a/Assets/Editor/ObjectIcons/proceduralbuilding.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:98aaf6d6e532f5a3f31cdc08676432e30b4e52fd4f376331f4610379f288a191 -size 3128 diff --git a/Assets/Editor/ObjectIcons/proceduralobject.bmp b/Assets/Editor/ObjectIcons/proceduralobject.bmp deleted file mode 100644 index e416cbafe1..0000000000 --- a/Assets/Editor/ObjectIcons/proceduralobject.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:98aaf6d6e532f5a3f31cdc08676432e30b4e52fd4f376331f4610379f288a191 -size 3128 diff --git a/Assets/Editor/ObjectIcons/proximitytrigger.bmp b/Assets/Editor/ObjectIcons/proximitytrigger.bmp deleted file mode 100644 index a776094539..0000000000 --- a/Assets/Editor/ObjectIcons/proximitytrigger.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ac364f478ca4dfa0186069fb69d19b8005a8d1da74cff34ced76bb85cf4402e7 -size 3128 diff --git a/Assets/Editor/ObjectIcons/river.bmp b/Assets/Editor/ObjectIcons/river.bmp deleted file mode 100644 index bf831c356a..0000000000 --- a/Assets/Editor/ObjectIcons/river.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:910d8f788514dc2d66c58027cb841a16e7d5194ee1f1ff3ccfcf5badd86c768a -size 3128 diff --git a/Assets/Editor/ObjectIcons/road.bmp b/Assets/Editor/ObjectIcons/road.bmp deleted file mode 100644 index 91a8b0916f..0000000000 --- a/Assets/Editor/ObjectIcons/road.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9e92c9792886fab49007891c38addf2f62719d6563a36cd81250de13c50fbf61 -size 3128 diff --git a/Assets/Editor/ObjectIcons/rope.bmp b/Assets/Editor/ObjectIcons/rope.bmp deleted file mode 100644 index d7f7fddb67..0000000000 --- a/Assets/Editor/ObjectIcons/rope.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:738525640cf00402ebd807ce9a35d6d7ed67be39cde7def7930b136596977a2e -size 3128 diff --git a/Assets/Editor/ObjectIcons/sequence.bmp b/Assets/Editor/ObjectIcons/sequence.bmp deleted file mode 100644 index 8e76c924f1..0000000000 --- a/Assets/Editor/ObjectIcons/sequence.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e339afca6ba8ffa2463bf6b367615e66bb953fced380d739996d52c2971feab5 -size 3128 diff --git a/Assets/Editor/ObjectIcons/shake.bmp b/Assets/Editor/ObjectIcons/shake.bmp deleted file mode 100644 index 5275a0aac9..0000000000 --- a/Assets/Editor/ObjectIcons/shake.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f3130dcb95136d806aff1882d3933eb3f7ee88aaa9876423b53dbf73f02c8cd3 -size 3128 diff --git a/Assets/Editor/ObjectIcons/smartobject.bmp b/Assets/Editor/ObjectIcons/smartobject.bmp deleted file mode 100644 index 5ecf9a273e..0000000000 --- a/Assets/Editor/ObjectIcons/smartobject.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e908579e0a62d74a1402ee786876e88eadb0ef0de0542617d02291947504078b -size 3128 diff --git a/Assets/Editor/ObjectIcons/spawngroup.bmp b/Assets/Editor/ObjectIcons/spawngroup.bmp deleted file mode 100644 index 00626fc17f..0000000000 --- a/Assets/Editor/ObjectIcons/spawngroup.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:28111b13e60816f31f3916131d4632ce2d0c48c1a7712421593f79dff79c99d0 -size 3128 diff --git a/Assets/Editor/ObjectIcons/spectator.bmp b/Assets/Editor/ObjectIcons/spectator.bmp deleted file mode 100644 index 6798c841c0..0000000000 --- a/Assets/Editor/ObjectIcons/spectator.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9a2885b3eb0845b48571f1af08d9e685b52361c78c31485c64f8e1efb38e8cc4 -size 3128 diff --git a/Assets/Editor/ObjectIcons/switch.bmp b/Assets/Editor/ObjectIcons/switch.bmp deleted file mode 100644 index 50f4e790b2..0000000000 --- a/Assets/Editor/ObjectIcons/switch.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9bdce356a35d214c4d806ba568d2de72af636410eb433be5c0390eae67d8478a -size 3128 diff --git a/Assets/Editor/ObjectIcons/territory.bmp b/Assets/Editor/ObjectIcons/territory.bmp deleted file mode 100644 index edd8b5178e..0000000000 --- a/Assets/Editor/ObjectIcons/territory.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:dc350e4d3226531a35ac810fa5ebe1894bfdcafac605334afffcdd3a14416f94 -size 3128 diff --git a/Assets/Editor/ObjectIcons/tornado.bmp b/Assets/Editor/ObjectIcons/tornado.bmp deleted file mode 100644 index e30b642441..0000000000 --- a/Assets/Editor/ObjectIcons/tornado.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c54df0fb1c9b8abeee30adc5e983bfd7dd524c551909b26466a9d8b6422a094a -size 3128 diff --git a/Assets/Editor/ObjectIcons/vehicle.bmp b/Assets/Editor/ObjectIcons/vehicle.bmp deleted file mode 100644 index f65e5bb7bf..0000000000 --- a/Assets/Editor/ObjectIcons/vehicle.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:50e0b4d6a86953c33b0c3ace60bb53d119fa5acd193f4d9aa2c0934f3074cb19 -size 3128 diff --git a/Assets/Editor/ObjectIcons/voxel.bmp b/Assets/Editor/ObjectIcons/voxel.bmp deleted file mode 100644 index dba0aa32ba..0000000000 --- a/Assets/Editor/ObjectIcons/voxel.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8ca14c966de6d392beb4d154221b622a417163fcdf92eb049638bf8495c13774 -size 3128 diff --git a/Assets/Editor/ObjectIcons/wave.bmp b/Assets/Editor/ObjectIcons/wave.bmp deleted file mode 100644 index 0465b41c38..0000000000 --- a/Assets/Editor/ObjectIcons/wave.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:573d22719ad010351a58733b63315a9a0fc07545dde71f3931f37371dfe44ce3 -size 3128 diff --git a/Assets/Editor/Scripts/Shelves/icons/Albedo.png b/Assets/Editor/Scripts/Shelves/icons/Albedo.png deleted file mode 100644 index f3225255c7..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/Albedo.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a91ea78d1ffd91490f20efcf76ad8790e450836240b8a77dda719da963235c85 -size 2987 diff --git a/Assets/Editor/Scripts/Shelves/icons/Diffuse_Lighting.png b/Assets/Editor/Scripts/Shelves/icons/Diffuse_Lighting.png deleted file mode 100644 index 4709ee81d0..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/Diffuse_Lighting.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:2d8eadc0bdc63391e88936b0acfd0616c2d7bce550ea82cee1f967f971ace8a6 -size 2905 diff --git a/Assets/Editor/Scripts/Shelves/icons/Diffuse_Texture_Res_360.png b/Assets/Editor/Scripts/Shelves/icons/Diffuse_Texture_Res_360.png deleted file mode 100644 index 25c686e46a..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/Diffuse_Texture_Res_360.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9cdb92de995635eadfbb6dceb25f44a737dde744e09f0fcfe7016de981dce786 -size 2975 diff --git a/Assets/Editor/Scripts/Shelves/icons/Empty_Wireframe.png b/Assets/Editor/Scripts/Shelves/icons/Empty_Wireframe.png deleted file mode 100644 index b4329c1beb..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/Empty_Wireframe.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:268a5b239b9988be0ae13a2f42a99ac39ac2db9988f92604154630b661b89999 -size 2865 diff --git a/Assets/Editor/Scripts/Shelves/icons/Exit.png b/Assets/Editor/Scripts/Shelves/icons/Exit.png deleted file mode 100644 index 3706ddc01c..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/Exit.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:030f4dc71dac36f220cd7e7c07eb24bda2df3c1e14b054e48fc6274573734bdb -size 2898 diff --git a/Assets/Editor/Scripts/Shelves/icons/Fuzziness.png b/Assets/Editor/Scripts/Shelves/icons/Fuzziness.png deleted file mode 100644 index 6ca7e20209..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/Fuzziness.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e0fa6d24bbb7f969a71b9e761f2dc4ec990a7e522201af9b13b2651d0565e1f0 -size 3607 diff --git a/Assets/Editor/Scripts/Shelves/icons/Gloss.png b/Assets/Editor/Scripts/Shelves/icons/Gloss.png deleted file mode 100644 index 5063b7f01e..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/Gloss.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d5b949330e86f02662bb3b25db123fd77be31c910ad7e1e21223a543820ce46a -size 2959 diff --git a/Assets/Editor/Scripts/Shelves/icons/Normal_Texture_Res_360.png b/Assets/Editor/Scripts/Shelves/icons/Normal_Texture_Res_360.png deleted file mode 100644 index 3ca3270344..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/Normal_Texture_Res_360.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:49086e4fa1736415d79d7d1d5ed8484b49582db8c27957148ef2a6d7f5dec189 -size 3176 diff --git a/Assets/Editor/Scripts/Shelves/icons/PrefabAddLibrary.png b/Assets/Editor/Scripts/Shelves/icons/PrefabAddLibrary.png deleted file mode 100644 index 899b8cbc57..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/PrefabAddLibrary.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e0d9c3f0be3c978deaa053d458a49908e99d8d0f7e87169b5b03b7f500e37f55 -size 3248 diff --git a/Assets/Editor/Scripts/Shelves/icons/PrefabAddSelection.png b/Assets/Editor/Scripts/Shelves/icons/PrefabAddSelection.png deleted file mode 100644 index 6144e48a2b..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/PrefabAddSelection.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:5d98fa218cf0c13100584611e1c4d536bdd9cf78a4a10dd1a0a49e4265b5292d -size 503 diff --git a/Assets/Editor/Scripts/Shelves/icons/PrefabBreak.png b/Assets/Editor/Scripts/Shelves/icons/PrefabBreak.png deleted file mode 100644 index 9982a71078..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/PrefabBreak.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e538188411092f7a172ef364035df77dc228bc91d43cfc35ffbbd824e716800e -size 3231 diff --git a/Assets/Editor/Scripts/Shelves/icons/PrefabConvert.png b/Assets/Editor/Scripts/Shelves/icons/PrefabConvert.png deleted file mode 100644 index cdbd6d2ac7..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/PrefabConvert.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:52b2c98b0f50fcfdd8334bcde259aef0a0533055f6caa1a1606536f5d2eca23f -size 3079 diff --git a/Assets/Editor/Scripts/Shelves/icons/PrefabCreate.png b/Assets/Editor/Scripts/Shelves/icons/PrefabCreate.png deleted file mode 100644 index 1aad8f3446..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/PrefabCreate.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:40905f7865cd5a71bfdace3943ccdd8fe532ee111419fb023befac357256eb07 -size 490 diff --git a/Assets/Editor/Scripts/Shelves/icons/PrefabIsolate.png b/Assets/Editor/Scripts/Shelves/icons/PrefabIsolate.png deleted file mode 100644 index 4c1a1766b5..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/PrefabIsolate.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:31f8f9a5ff20b33bdf86af8da579717cda40e097db6f893ec4e2fffab720f90e -size 3211 diff --git a/Assets/Editor/Scripts/Shelves/icons/Scattering.png b/Assets/Editor/Scripts/Shelves/icons/Scattering.png deleted file mode 100644 index 3c2c5cff38..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/Scattering.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9ec02e421b4e832f73576d1f1bf2b6bc60879521f3a8abbb554925982574c374 -size 3146 diff --git a/Assets/Editor/Scripts/Shelves/icons/Solid_Wireframe.png b/Assets/Editor/Scripts/Shelves/icons/Solid_Wireframe.png deleted file mode 100644 index e439baed1b..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/Solid_Wireframe.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:bcc61dfe03d5bae6060c1fc6814b7be299705803fdb9058cabe6227f386ddeef -size 2872 diff --git a/Assets/Editor/Scripts/Shelves/icons/Spec_Amount.png b/Assets/Editor/Scripts/Shelves/icons/Spec_Amount.png deleted file mode 100644 index 7561feb7c0..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/Spec_Amount.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a67c8e063331c5c6ce256892abdde113f405c60854115ba87f6798d06f57eb02 -size 2892 diff --git a/Assets/Editor/Scripts/Shelves/icons/Spec_Lighting.png b/Assets/Editor/Scripts/Shelves/icons/Spec_Lighting.png deleted file mode 100644 index f08a036519..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/Spec_Lighting.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:927d3b2f83e6e962a492ea625240bb5f336e30aa2052d1f8699b76a86a5e475d -size 2897 diff --git a/Assets/Editor/Scripts/Shelves/icons/Texel_Per_Meter_1024.png b/Assets/Editor/Scripts/Shelves/icons/Texel_Per_Meter_1024.png deleted file mode 100644 index 2d4b08f5fb..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/Texel_Per_Meter_1024.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a3861aa38f3e521127a48f08e6c24e12e61c15450bb4d10ef27a0a95c2c420c0 -size 2889 diff --git a/Assets/Editor/Scripts/Shelves/icons/Texel_Per_Meter_256.png b/Assets/Editor/Scripts/Shelves/icons/Texel_Per_Meter_256.png deleted file mode 100644 index 4b1ceef8ab..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/Texel_Per_Meter_256.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:5ecc3596974c0c9f1703d51e60de2ca00a479012d98f11316966686cc891f982 -size 2922 diff --git a/Assets/Editor/Scripts/Shelves/icons/Texel_Per_Meter_512.png b/Assets/Editor/Scripts/Shelves/icons/Texel_Per_Meter_512.png deleted file mode 100644 index 4f328adf91..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/Texel_Per_Meter_512.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ce1ca5c1d89cd6d7a0cf35142be114904ec469afab2fa69a12afe6824055b67b -size 2913 diff --git a/Assets/Editor/Scripts/Shelves/icons/all.png b/Assets/Editor/Scripts/Shelves/icons/all.png deleted file mode 100644 index 1b6e3b12d6..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/all.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ffcf54b92f48aa06f38e94826a76f350b425ad9d46c0e2170455730123a69a6d -size 3693 diff --git a/Assets/Editor/Scripts/Shelves/icons/beams.png b/Assets/Editor/Scripts/Shelves/icons/beams.png deleted file mode 100644 index 9263cc070a..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/beams.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:68c4333ba27b39baed2696fa90040cc4e669dbc5e9fab43b11abd854d5482474 -size 613 diff --git a/Assets/Editor/Scripts/Shelves/icons/blanker.png b/Assets/Editor/Scripts/Shelves/icons/blanker.png deleted file mode 100644 index 277a067134..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/blanker.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:adac9f1fc606475d1d86ca8f5b2376570ebc70161e4b5240ede3cb8f176b8f41 -size 2810 diff --git a/Assets/Editor/Scripts/Shelves/icons/bounding_box.png b/Assets/Editor/Scripts/Shelves/icons/bounding_box.png deleted file mode 100644 index 854a9f957c..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/bounding_box.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f00fa9904ce4687aaf21f1553d03bf1d47390d007fd38513ad959f324a4b6ebb -size 3618 diff --git a/Assets/Editor/Scripts/Shelves/icons/brushes.png b/Assets/Editor/Scripts/Shelves/icons/brushes.png deleted file mode 100644 index 283af0629c..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/brushes.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ed21a97324849633d156ec03f949a3cf21b8b682a3a6ad1dcfac6eee9df7a497 -size 734 diff --git a/Assets/Editor/Scripts/Shelves/icons/cloud.png b/Assets/Editor/Scripts/Shelves/icons/cloud.png deleted file mode 100644 index 8f28b28613..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/cloud.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:11599538b6bc197e92f07db149ccdfee50ddea630f095865bac9782254a7c06f -size 387 diff --git a/Assets/Editor/Scripts/Shelves/icons/cloud_dark.png b/Assets/Editor/Scripts/Shelves/icons/cloud_dark.png deleted file mode 100644 index 28d1d0281b..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/cloud_dark.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:559ec911f9cac84de411e92d746913c3828ebf1d1f8c7bab794fb9c768c1581d -size 387 diff --git a/Assets/Editor/Scripts/Shelves/icons/cloud_dark_rain.png b/Assets/Editor/Scripts/Shelves/icons/cloud_dark_rain.png deleted file mode 100644 index 7119b0387f..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/cloud_dark_rain.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:88d11b32db70a437fd8ff8c845b4ff26182d28f5b7a2f6b3de4fce61dffff98d -size 489 diff --git a/Assets/Editor/Scripts/Shelves/icons/collisions.png b/Assets/Editor/Scripts/Shelves/icons/collisions.png deleted file mode 100644 index af947db919..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/collisions.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:0510fa11c090234a2008703917834ad0455bc6e5e9a2d2375ebd0fc279b41851 -size 3491 diff --git a/Assets/Editor/Scripts/Shelves/icons/create_ao_volume_box.png b/Assets/Editor/Scripts/Shelves/icons/create_ao_volume_box.png deleted file mode 100644 index 558a3eba64..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/create_ao_volume_box.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:24fc2750f740f0b85ca720beedb564f2a01bbeed229cb89c6d8f395d5cf5d439 -size 844 diff --git a/Assets/Editor/Scripts/Shelves/icons/create_both_vis_box_envprobe.png b/Assets/Editor/Scripts/Shelves/icons/create_both_vis_box_envprobe.png deleted file mode 100644 index d4b1023cdb..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/create_both_vis_box_envprobe.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:000effa8925a61313fdf420830857172bc69c38cb8a14737a389b9c9df1b36df -size 745 diff --git a/Assets/Editor/Scripts/Shelves/icons/create_envprobe.png b/Assets/Editor/Scripts/Shelves/icons/create_envprobe.png deleted file mode 100644 index bdaf8fdf2c..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/create_envprobe.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9d91f30f31576dc957f57d59e2b94d6e45c9aef28f321240c31639c148f62aea -size 803 diff --git a/Assets/Editor/Scripts/Shelves/icons/create_portal_box.png b/Assets/Editor/Scripts/Shelves/icons/create_portal_box.png deleted file mode 100644 index 416952b279..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/create_portal_box.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6452c7e2baef1d8d285a96e72d053a8af80430e52a149ce14795c946d55896fb -size 807 diff --git a/Assets/Editor/Scripts/Shelves/icons/create_vis_box.png b/Assets/Editor/Scripts/Shelves/icons/create_vis_box.png deleted file mode 100644 index 74ac6eac4d..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/create_vis_box.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e0d5e21ccaec784d3118a2609e5f26caca4a26901a92db0821e2e0f18e555534 -size 833 diff --git a/Assets/Editor/Scripts/Shelves/icons/create_vis_box_and_portal_box.png b/Assets/Editor/Scripts/Shelves/icons/create_vis_box_and_portal_box.png deleted file mode 100644 index 5da50020d9..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/create_vis_box_and_portal_box.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e5717c6fde94577b831b8d83104733f86ed82f030664624d62cb4a6d26dd5646 -size 822 diff --git a/Assets/Editor/Scripts/Shelves/icons/create_vis_box_env_probe_and_portal.png b/Assets/Editor/Scripts/Shelves/icons/create_vis_box_env_probe_and_portal.png deleted file mode 100644 index cd39aade30..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/create_vis_box_env_probe_and_portal.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:07e831e8cab5e1e222b4a4d6a64932bbb8a9a5fcb7cae020432905a7c1e53402 -size 782 diff --git a/Assets/Editor/Scripts/Shelves/icons/cubemap.png b/Assets/Editor/Scripts/Shelves/icons/cubemap.png deleted file mode 100644 index d55d04b978..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/cubemap.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9775b4823563dbff4c3410c1751f022e2985f91202e6d691f86172ef1f820f4b -size 3353 diff --git a/Assets/Editor/Scripts/Shelves/icons/decals.png b/Assets/Editor/Scripts/Shelves/icons/decals.png deleted file mode 100644 index b9e4c92bd7..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/decals.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c12d69b2d85c339bbff06011fff7c2468a2b2e6c67726ad7fb0ab82384eb39df -size 918 diff --git a/Assets/Editor/Scripts/Shelves/icons/default_material.png b/Assets/Editor/Scripts/Shelves/icons/default_material.png deleted file mode 100644 index 9fda69eaab..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/default_material.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:98146b9b75602ddc8a46529fe0427303491dfe4584cadb914d3774377593c7ef -size 3809 diff --git a/Assets/Editor/Scripts/Shelves/icons/default_material_with_normals.png b/Assets/Editor/Scripts/Shelves/icons/default_material_with_normals.png deleted file mode 100644 index cbb0f9bbf2..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/default_material_with_normals.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a1c7e790dad53937ed0845cb89c5651c7932a696d7d34d85df6fc8c4b09c7245 -size 3106 diff --git a/Assets/Editor/Scripts/Shelves/icons/designer.png b/Assets/Editor/Scripts/Shelves/icons/designer.png deleted file mode 100644 index 9018385ebb..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/designer.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e790bb52b7f7d52e79b2c5b84ee4a4587a721c7e3c70d2d7e0eb683b478b51f7 -size 1015 diff --git a/Assets/Editor/Scripts/Shelves/icons/diff_acc.png b/Assets/Editor/Scripts/Shelves/icons/diff_acc.png deleted file mode 100644 index df3eac041c..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/diff_acc.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b341792fb1c13db8144f74c3895942251c07e67e87ac374c09df21e3459b3610 -size 3930 diff --git a/Assets/Editor/Scripts/Shelves/icons/display_info.png b/Assets/Editor/Scripts/Shelves/icons/display_info.png deleted file mode 100644 index 22572bc6e5..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/display_info.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:0fc2408c2f1801de3f625dcbdf960104195c1d47d7e240f4ec9391a7b645399c -size 3623 diff --git a/Assets/Editor/Scripts/Shelves/icons/dual_layer_mask.png b/Assets/Editor/Scripts/Shelves/icons/dual_layer_mask.png deleted file mode 100644 index c47a0f7350..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/dual_layer_mask.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:80bca215bbcec9d9e1e33abfbf0b17d6032327a175d6f9d4d76bfefd5c7f2480 -size 3517 diff --git a/Assets/Editor/Scripts/Shelves/icons/dynamiclights.png b/Assets/Editor/Scripts/Shelves/icons/dynamiclights.png deleted file mode 100644 index 541d8f9304..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/dynamiclights.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ef3cae03d5f38bdf9e82ff29b1a77133a44e5e859cfdb063c449ee5609902367 -size 780 diff --git a/Assets/Editor/Scripts/Shelves/icons/entities.png b/Assets/Editor/Scripts/Shelves/icons/entities.png deleted file mode 100644 index 0bf2eda8cc..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/entities.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:42de1878f5cef5c3f80dd56e042584eeb8759cacd58a0b22115644ed38800836 -size 870 diff --git a/Assets/Editor/Scripts/Shelves/icons/eye_adaptation_speed.png b/Assets/Editor/Scripts/Shelves/icons/eye_adaptation_speed.png deleted file mode 100644 index a485e39655..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/eye_adaptation_speed.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f1b4a6d4cca72740f14e97239bf8490d23ccb3d9283d4ff558f0302d9fa773ad -size 1017 diff --git a/Assets/Editor/Scripts/Shelves/icons/fog.png b/Assets/Editor/Scripts/Shelves/icons/fog.png deleted file mode 100644 index 68137429de..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/fog.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4dea1c985077475184c32562609e27b7919cd1c08776174a83f38f095a11f3d4 -size 394 diff --git a/Assets/Editor/Scripts/Shelves/icons/fogvolumes.png b/Assets/Editor/Scripts/Shelves/icons/fogvolumes.png deleted file mode 100644 index 8c305abb4a..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/fogvolumes.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:bbf140c23e75f1c1035defd58ec8522230abdb5fc7538953ed88eb3bc06c9ca3 -size 349 diff --git a/Assets/Editor/Scripts/Shelves/icons/freeze_particles.png b/Assets/Editor/Scripts/Shelves/icons/freeze_particles.png deleted file mode 100644 index 963374b096..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/freeze_particles.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:52986df9e8a866606cbfbe8a9702f15483a6f3bfa0b15563e64a5c6d208dab55 -size 4076 diff --git a/Assets/Editor/Scripts/Shelves/icons/full_shading.png b/Assets/Editor/Scripts/Shelves/icons/full_shading.png deleted file mode 100644 index 4decb4c800..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/full_shading.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:339d6542b6a259feeb7dc8ebc536ca6fed44a91faaf021b1453a735b39d98450 -size 3021 diff --git a/Assets/Editor/Scripts/Shelves/icons/gamma.png b/Assets/Editor/Scripts/Shelves/icons/gamma.png deleted file mode 100644 index 43b16f55a6..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/gamma.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b93bb51dd54685b9dd1a37b535c7cb456110b45c62ae64eaaceb61a58b99f254 -size 1418 diff --git a/Assets/Editor/Scripts/Shelves/icons/gi.png b/Assets/Editor/Scripts/Shelves/icons/gi.png deleted file mode 100644 index 51fb05190c..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/gi.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:cbc47ed9888c792af55b4e0ab5d5c7a7b8a582fdb202fa035e21b974c7df1022 -size 885 diff --git a/Assets/Editor/Scripts/Shelves/icons/lens_flare.png b/Assets/Editor/Scripts/Shelves/icons/lens_flare.png deleted file mode 100644 index 2da269b7c7..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/lens_flare.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e2cbf9570c227884d49ac2a702377821891d06eaa91b6bf92861088508927796 -size 670 diff --git a/Assets/Editor/Scripts/Shelves/icons/lighting_only.png b/Assets/Editor/Scripts/Shelves/icons/lighting_only.png deleted file mode 100644 index bd4590053c..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/lighting_only.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:695dcdc3004705d1489b5b2a0a750bf6d30940d343a62bc8ff06bc103d3ae6f7 -size 2870 diff --git a/Assets/Editor/Scripts/Shelves/icons/lods.png b/Assets/Editor/Scripts/Shelves/icons/lods.png deleted file mode 100644 index a6ad158679..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/lods.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:266450829046d2be9557c86f8061f1b50d8f55795436b608689d6c117c5b970d -size 1156 diff --git a/Assets/Editor/Scripts/Shelves/icons/lsao.png b/Assets/Editor/Scripts/Shelves/icons/lsao.png deleted file mode 100644 index 127b421a30..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/lsao.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:7a253c696ce28fb7699b6879c35e874d906033b59e89224d307bf029dd9257e6 -size 3926 diff --git a/Assets/Editor/Scripts/Shelves/icons/lsao_toggle.png b/Assets/Editor/Scripts/Shelves/icons/lsao_toggle.png deleted file mode 100644 index c264be14bd..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/lsao_toggle.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:734ca55bc936d229c56abb4f141a746fe64affc570570d182308f6f0d8f21638 -size 3952 diff --git a/Assets/Editor/Scripts/Shelves/icons/lsro.png b/Assets/Editor/Scripts/Shelves/icons/lsro.png deleted file mode 100644 index ff4099a887..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/lsro.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a100211ce724c005cd2fadecb4ca3c36feacad4f7cb4bbccd8761ae622d59aa3 -size 1153 diff --git a/Assets/Editor/Scripts/Shelves/icons/normals.png b/Assets/Editor/Scripts/Shelves/icons/normals.png deleted file mode 100644 index 1f723ef0d1..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/normals.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:58e65981a6b66482ac3443f644fe210d9c90d01b4a5ab381796d37bf6d5be289 -size 3215 diff --git a/Assets/Editor/Scripts/Shelves/icons/normals_x.png b/Assets/Editor/Scripts/Shelves/icons/normals_x.png deleted file mode 100644 index 98a705b559..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/normals_x.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:1be96cc2682443b03bfc4696403d5c3d98eec709878acac0b690dbb635d04ea9 -size 3227 diff --git a/Assets/Editor/Scripts/Shelves/icons/normals_y.png b/Assets/Editor/Scripts/Shelves/icons/normals_y.png deleted file mode 100644 index 8c109bee9b..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/normals_y.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:2eaf04f15e42ac910dc7c29fb61034dc5126a80832b6a0bc0a842b549c23eaf7 -size 3118 diff --git a/Assets/Editor/Scripts/Shelves/icons/normals_z.png b/Assets/Editor/Scripts/Shelves/icons/normals_z.png deleted file mode 100644 index 078ceded6c..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/normals_z.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:0c8ec3131755522c3f1a4fc45cef0b9ace4641316d890d3f6f042557f220d6ba -size 3152 diff --git a/Assets/Editor/Scripts/Shelves/icons/ocean.png b/Assets/Editor/Scripts/Shelves/icons/ocean.png deleted file mode 100644 index 04c4fff0fc..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/ocean.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:1407119e10f378a6ae375f3951dbfe42505560f75a88687f4c03e0ac2e85a05e -size 700 diff --git a/Assets/Editor/Scripts/Shelves/icons/particles.png b/Assets/Editor/Scripts/Shelves/icons/particles.png deleted file mode 100644 index daecfbc256..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/particles.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d9875276bc1b8055f306d0bf95b0ba3f6c8f9a49447a68f75334e86b360f4359 -size 713 diff --git a/Assets/Editor/Scripts/Shelves/icons/particles_bounds.png b/Assets/Editor/Scripts/Shelves/icons/particles_bounds.png deleted file mode 100644 index 04321c8ed5..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/particles_bounds.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:231f6c7939361f71b9926f551bbf2eb93ca4ec8394318dcfed0fa413ccd58e66 -size 4073 diff --git a/Assets/Editor/Scripts/Shelves/icons/particles_off.png b/Assets/Editor/Scripts/Shelves/icons/particles_off.png deleted file mode 100644 index ed7fe76f44..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/particles_off.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b6e656417153394c5466a207bd6ff21072c6ef82fe6972380ceda7fa6e60c478 -size 4053 diff --git a/Assets/Editor/Scripts/Shelves/icons/particles_overdraw.png b/Assets/Editor/Scripts/Shelves/icons/particles_overdraw.png deleted file mode 100644 index 86a8a72b52..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/particles_overdraw.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8f021d07012f712d8ab70af609974e1cb0933d571bbe0f184e0e7479ee172834 -size 3004 diff --git a/Assets/Editor/Scripts/Shelves/icons/particles_screen_coverage.png b/Assets/Editor/Scripts/Shelves/icons/particles_screen_coverage.png deleted file mode 100644 index fd20e416b2..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/particles_screen_coverage.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:387a799eeb739b6183f3d47186c122ea51c8998664bd0cff76e28f8de2cf49ee -size 4024 diff --git a/Assets/Editor/Scripts/Shelves/icons/placeholder.png b/Assets/Editor/Scripts/Shelves/icons/placeholder.png deleted file mode 100644 index f3225255c7..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/placeholder.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a91ea78d1ffd91490f20efcf76ad8790e450836240b8a77dda719da963235c85 -size 2987 diff --git a/Assets/Editor/Scripts/Shelves/icons/prefab.png b/Assets/Editor/Scripts/Shelves/icons/prefab.png deleted file mode 100644 index 84d2b08397..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/prefab.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:332071c8b20030de53ec194dfe853b29f45a0de04d99dcd1b1c4b32dcf2946a5 -size 683 diff --git a/Assets/Editor/Scripts/Shelves/icons/reflections.png b/Assets/Editor/Scripts/Shelves/icons/reflections.png deleted file mode 100644 index 0fc82618b8..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/reflections.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ee9fdf1b6ab47cfc72c3794a46b6886b9993e691a7d097b3d109127ddcde46ac -size 640 diff --git a/Assets/Editor/Scripts/Shelves/icons/reset.png b/Assets/Editor/Scripts/Shelves/icons/reset.png deleted file mode 100644 index 8cc13235ae..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/reset.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:120be39c58db0bab5450db22604f94cf31eb68a480f06daf3d4f76828461385b -size 4076 diff --git a/Assets/Editor/Scripts/Shelves/icons/selfocc.png b/Assets/Editor/Scripts/Shelves/icons/selfocc.png deleted file mode 100644 index f3a1ece6a3..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/selfocc.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:83e8233f9f0594151e734583f9fd3835250f370dac8b648554f1060d79efa43b -size 2935 diff --git a/Assets/Editor/Scripts/Shelves/icons/shaded_wireframe.png b/Assets/Editor/Scripts/Shelves/icons/shaded_wireframe.png deleted file mode 100644 index 79d4148d9c..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/shaded_wireframe.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f514eebcdcd02d8195d8b51966ad84cfb8162c3811facc6da9fc0a71e10443bc -size 3041 diff --git a/Assets/Editor/Scripts/Shelves/icons/shadows.png b/Assets/Editor/Scripts/Shelves/icons/shadows.png deleted file mode 100644 index 06fd30ee05..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/shadows.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:281c6d85ab6d7e706f73865a7beb523bf64e505d8fd2b3c367f6ad56b008a77e -size 818 diff --git a/Assets/Editor/Scripts/Shelves/icons/showlines.png b/Assets/Editor/Scripts/Shelves/icons/showlines.png deleted file mode 100644 index b4329c1beb..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/showlines.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:268a5b239b9988be0ae13a2f42a99ac39ac2db9988f92604154630b661b89999 -size 2865 diff --git a/Assets/Editor/Scripts/Shelves/icons/sky.png b/Assets/Editor/Scripts/Shelves/icons/sky.png deleted file mode 100644 index 86d018f2d8..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/sky.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:3598e1bdc4c47d6be99ad6ff10e91b307bb4a94286fff57a0c339d6aaed2e0a3 -size 620 diff --git a/Assets/Editor/Scripts/Shelves/icons/spec_acc.png b/Assets/Editor/Scripts/Shelves/icons/spec_acc.png deleted file mode 100644 index b66acb25ca..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/spec_acc.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ee2c46410495a75862d8f5d2e69cce11c94745680ef03b50ba7b17af9c137656 -size 3334 diff --git a/Assets/Editor/Scripts/Shelves/icons/spec_lum.png b/Assets/Editor/Scripts/Shelves/icons/spec_lum.png deleted file mode 100644 index 7561feb7c0..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/spec_lum.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a67c8e063331c5c6ce256892abdde113f405c60854115ba87f6798d06f57eb02 -size 2892 diff --git a/Assets/Editor/Scripts/Shelves/icons/spec_occ.png b/Assets/Editor/Scripts/Shelves/icons/spec_occ.png deleted file mode 100644 index 624f8481ad..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/spec_occ.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:23a7074e8ced66649cc8c2f69db33559bd600658709aaf287a9d9de9c98a05f6 -size 3182 diff --git a/Assets/Editor/Scripts/Shelves/icons/ssao.png b/Assets/Editor/Scripts/Shelves/icons/ssao.png deleted file mode 100644 index 376a0a2157..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/ssao.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:134cbfd478080236c3f5ea2ee32319e63ee21ff48f187b709ab9dc0f3688c2dd -size 3932 diff --git a/Assets/Editor/Scripts/Shelves/icons/ssdo.png b/Assets/Editor/Scripts/Shelves/icons/ssdo.png deleted file mode 100644 index 517658c1f5..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/ssdo.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c200aad6ad59b7d466edc44026ffca2272ca3b20944070210db1108f21f1cb60 -size 3972 diff --git a/Assets/Editor/Scripts/Shelves/icons/ssdo_toggle.png b/Assets/Editor/Scripts/Shelves/icons/ssdo_toggle.png deleted file mode 100644 index 881b07cb2f..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/ssdo_toggle.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c897d61016bc32c7072273a081e624880b90beb89e90f20b25e689f5198d1f63 -size 3966 diff --git a/Assets/Editor/Scripts/Shelves/icons/sun.big.png b/Assets/Editor/Scripts/Shelves/icons/sun.big.png deleted file mode 100644 index 0a5363ddca..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/sun.big.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c49214e755a68e48bba8b8be9183777c24c3443aa734e4969e74bc42d5979cb7 -size 539 diff --git a/Assets/Editor/Scripts/Shelves/icons/tangents.png b/Assets/Editor/Scripts/Shelves/icons/tangents.png deleted file mode 100644 index 7a1f5c0a3a..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/tangents.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e8a5f21232c186fed9bd9a0d62bd4023dca1d496e151ad0fee5b593fc67645bf -size 1115 diff --git a/Assets/Editor/Scripts/Shelves/icons/terrain.png b/Assets/Editor/Scripts/Shelves/icons/terrain.png deleted file mode 100644 index b32c4cde98..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/terrain.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:821ef3daa0cdf246985c0bc1bd988edeceadb672dd81f4813320e8d50ca0e41c -size 461 diff --git a/Assets/Editor/Scripts/Shelves/icons/time_scale_double.png b/Assets/Editor/Scripts/Shelves/icons/time_scale_double.png deleted file mode 100644 index 03ae1a21ea..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/time_scale_double.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:86ebd1c792b9024662a179995ba65d181157a9887112f12571fbfe05a3dc8a79 -size 3145 diff --git a/Assets/Editor/Scripts/Shelves/icons/time_scale_frozen.png b/Assets/Editor/Scripts/Shelves/icons/time_scale_frozen.png deleted file mode 100644 index a1756ce9fa..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/time_scale_frozen.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4fbe9783be75404b2364726b09f9013360522d2e71f479476a715b6577def003 -size 3386 diff --git a/Assets/Editor/Scripts/Shelves/icons/time_scale_half.png b/Assets/Editor/Scripts/Shelves/icons/time_scale_half.png deleted file mode 100644 index c3f9f03d98..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/time_scale_half.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:1a6740a0e38ea99c83c1460a33f62c3dead3ab85f05bf446426fb39a75aa76f8 -size 3137 diff --git a/Assets/Editor/Scripts/Shelves/icons/time_scale_quarter.png b/Assets/Editor/Scripts/Shelves/icons/time_scale_quarter.png deleted file mode 100644 index a8a9b8cdd8..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/time_scale_quarter.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4b0baf9f76bcc0bcd38fea907b79edde3bcb66e78b221094473a8abd0b222734 -size 3175 diff --git a/Assets/Editor/Scripts/Shelves/icons/time_scale_tenth.png b/Assets/Editor/Scripts/Shelves/icons/time_scale_tenth.png deleted file mode 100644 index 0aba084827..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/time_scale_tenth.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f71d44c06aa67ab94b190bd74516ce73c534a7d6421415437db262659b2ff32a -size 3124 diff --git a/Assets/Editor/Scripts/Shelves/icons/tod.png b/Assets/Editor/Scripts/Shelves/icons/tod.png deleted file mode 100644 index 0d5c4682c2..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/tod.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6028cef57651c79f5eb83c52eb0ab63eb42dbf4014dcb0f60c4c15ab8fe3cafd -size 977 diff --git a/Assets/Editor/Scripts/Shelves/icons/translucency.png b/Assets/Editor/Scripts/Shelves/icons/translucency.png deleted file mode 100644 index 8487c5916f..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/translucency.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:07457d1315f4cf1bd931187d849a1e842c931640edb53abb2a4f5b2d8d65716b -size 3110 diff --git a/Assets/Editor/Scripts/Shelves/icons/transparency.png b/Assets/Editor/Scripts/Shelves/icons/transparency.png deleted file mode 100644 index 4f41c6491b..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/transparency.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e59571a1490d7dd4696bc118bd4ccc8e08a663afac1ce3f2d88bb5d7d6fdb196 -size 558 diff --git a/Assets/Editor/Scripts/Shelves/icons/valid_albedo.png b/Assets/Editor/Scripts/Shelves/icons/valid_albedo.png deleted file mode 100644 index c3a76d6dfa..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/valid_albedo.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ce233f32949099694d4294b95252068c4486edba163a466ebdb20a54a2338f0f -size 3120 diff --git a/Assets/Editor/Scripts/Shelves/icons/valid_spec_lum.png b/Assets/Editor/Scripts/Shelves/icons/valid_spec_lum.png deleted file mode 100644 index 13f8404057..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/valid_spec_lum.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f5f365970f6f9138d6e78a2053338eb1275c562fb700670ab00e800e6a43280d -size 3199 diff --git a/Assets/Editor/Scripts/Shelves/icons/vegetation.png b/Assets/Editor/Scripts/Shelves/icons/vegetation.png deleted file mode 100644 index 4492e38ce8..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/vegetation.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:48a435a0632d7d0a8bdfee418423d8c411c4eab9b1da0fac257f32451a233d8f -size 747 diff --git a/Assets/Editor/Scripts/Shelves/icons/vertex_normals.png b/Assets/Editor/Scripts/Shelves/icons/vertex_normals.png deleted file mode 100644 index 80c51660c0..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/vertex_normals.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:101e61f7e5b40aaa48bed685f854fc01c58aec66ca8becc5386f6f0c22c020ad -size 1114 diff --git a/Assets/Editor/Scripts/Shelves/icons/vis_area.png b/Assets/Editor/Scripts/Shelves/icons/vis_area.png deleted file mode 100644 index 0d16d4a477..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/vis_area.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ae9997b5b999a6b66e56d6024617f718ea06fd389a98a97465a5d76780a1da75 -size 3915 diff --git a/Assets/Editor/Scripts/Shelves/icons/water_volume.png b/Assets/Editor/Scripts/Shelves/icons/water_volume.png deleted file mode 100644 index 2be9a96264..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/water_volume.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e88a2a6e4d14bced3d3e48c25d4bfe075d8587898cd61fbd0e3ab99e4391e663 -size 602 diff --git a/Assets/Editor/Scripts/Shelves/icons/wind.png b/Assets/Editor/Scripts/Shelves/icons/wind.png deleted file mode 100644 index 54ed666138..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/wind.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:caa003d65336c2e2a8987122ace98e0300e5d8afe1864dffef0d1651b136ccc1 -size 720 diff --git a/Assets/Editor/Scripts/Shelves/icons/wireframe.png b/Assets/Editor/Scripts/Shelves/icons/wireframe.png deleted file mode 100644 index 85a71daccc..0000000000 --- a/Assets/Editor/Scripts/Shelves/icons/wireframe.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:fd5356c97575c12fa7038443c0216a316c234e4e50e2e439ff8dde4504e56243 -size 2848 diff --git a/Code/Editor/ToolBox.cpp b/Code/Editor/ToolBox.cpp index 77cb479873..82817e1ff7 100644 --- a/Code/Editor/ToolBox.cpp +++ b/Code/Editor/ToolBox.cpp @@ -321,42 +321,13 @@ bool CToolBoxManager::SetMacroTitle(int index, const QString& title, bool bToolb } ////////////////////////////////////////////////////////////////////////// -void CToolBoxManager::Load(ActionManager* actionManager) +void CToolBoxManager::Load([[maybe_unused]] ActionManager* actionManager) { Clear(); QString path; GetSaveFilePath(path); Load(path, nullptr, true, nullptr); - - if (actionManager) - { - auto engineSourceAssetPath = AZ::IO::FixedMaxPath(AZ::Utils::GetEnginePath()) / "Assets"; - LoadShelves((engineSourceAssetPath / "Editor" / "Scripts").c_str(), - (engineSourceAssetPath / "Editor" / "Scripts" / "Shelves").c_str(), actionManager); - } -} - -void CToolBoxManager::LoadShelves(QString scriptPath, QString shelvesPath, ActionManager* actionManager) -{ - IFileUtil::FileArray files; - CFileUtil::ScanDirectory(shelvesPath, "*.xml", files); - - const int shelfCount = files.size(); - for (int idx = 0; idx < shelfCount; ++idx) - { - if (Path::GetExt(files[idx].filename) != "xml") - { - continue; - } - - QString shelfName(PathUtil::GetFileName(files[idx].filename.toUtf8().data())); - - AmazonToolbar toolbar(shelfName, shelfName); - Load(shelvesPath + QString("/") + files[idx].filename, &toolbar, false, actionManager); - - m_toolbars.push_back(toolbar); - } } void CToolBoxManager::Load(QString xmlpath, AmazonToolbar* pToolbar, bool bToolbox, ActionManager* actionManager) diff --git a/Code/Editor/ToolBox.h b/Code/Editor/ToolBox.h index 691b9cd089..0c91305c79 100644 --- a/Code/Editor/ToolBox.h +++ b/Code/Editor/ToolBox.h @@ -129,7 +129,6 @@ public: void Save() const; // Load macros configuration from registry. void Load(ActionManager* actionManager = nullptr); - void LoadShelves(QString scriptPath, QString shelvesPath, ActionManager* actionManager); //! Get the number of managed macros. int GetMacroCount(bool bToolbox) const; From 7d84a005c00c1b1c3d1b9ef0e5456d0ecf15146d Mon Sep 17 00:00:00 2001 From: santorac <55155825+santorac@users.noreply.github.com> Date: Mon, 2 Aug 2021 10:49:13 -0700 Subject: [PATCH 153/160] Updated unit tests and fixed build failures. --- .../Model/ModelAssetBuilderComponent.h | 1 + Gems/Atom/RPI/Code/Tests/Model/ModelTests.cpp | 46 +++++++++++-------- 2 files changed, 29 insertions(+), 18 deletions(-) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/ModelAssetBuilderComponent.h b/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/ModelAssetBuilderComponent.h index 832a8700ba..843f756df6 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/ModelAssetBuilderComponent.h +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/ModelAssetBuilderComponent.h @@ -42,6 +42,7 @@ namespace AZ using SkinData = AZ::SceneAPI::DataTypes::ISkinWeightData; class Stream; + class ModelAssetCreator; class ModelLodAssetCreator; class BufferAssetCreator; struct PackedCompressedMorphTargetDelta; diff --git a/Gems/Atom/RPI/Code/Tests/Model/ModelTests.cpp b/Gems/Atom/RPI/Code/Tests/Model/ModelTests.cpp index cdf0d0166d..625240a01f 100644 --- a/Gems/Atom/RPI/Code/Tests/Model/ModelTests.cpp +++ b/Gems/Atom/RPI/Code/Tests/Model/ModelTests.cpp @@ -17,6 +17,7 @@ #include #include +#include #include #include @@ -91,7 +92,7 @@ namespace UnitTest AZ::Aabb m_aabb = AZ::Aabb::CreateNull(); uint32_t m_indexCount = 0; uint32_t m_vertexCount = 0; - AZ::Data::Asset m_material; + AZ::RPI::ModelMaterialSlot::StableId m_materialSlotId = AZ::RPI::ModelMaterialSlot::InvalidStableId; }; struct ExpectedLod @@ -136,6 +137,7 @@ namespace UnitTest return true; } + //! This function assumes the model has "sharedMeshCount + separateMeshCount" unique material slots, with incremental IDs starting at 0. AZ::Data::Asset BuildTestLod(const uint32_t sharedMeshCount, const uint32_t separateMeshCount, ExpectedLod& expectedLod) { using namespace AZ; @@ -148,6 +150,8 @@ namespace UnitTest const uint32_t indexCount = 36; const uint32_t vertexCount = 36; + RPI::ModelMaterialSlot::StableId materialSlotId = 0; + if(sharedMeshCount > 0) { const uint32_t sharedIndexCount = indexCount * sharedMeshCount; @@ -164,7 +168,7 @@ namespace UnitTest ExpectedMesh expectedMesh; expectedMesh.m_indexCount = indexCount; expectedMesh.m_vertexCount = vertexCount; - expectedMesh.m_material = m_materialAsset; + expectedMesh.m_materialSlotId = i; RHI::BufferViewDescriptor indexBufferViewDescriptor = RHI::BufferViewDescriptor::CreateStructured(i * indexCount, indexCount, sizeof(uint32_t)); @@ -180,7 +184,7 @@ namespace UnitTest creator.BeginMesh(); Aabb aabb = expectedMesh.m_aabb; creator.SetMeshAabb(AZStd::move(aabb)); - creator.SetMeshMaterialAsset(m_materialAsset); + creator.SetMeshMaterialSlot(materialSlotId++); creator.SetMeshIndexBuffer({ sharedIndexBuffer, indexBufferViewDescriptor }); creator.AddMeshStreamBuffer(GetPositionSemantic(), AZ::Name(), { sharedPositionBuffer, vertexBufferViewDescriptor }); creator.EndMesh(); @@ -195,7 +199,7 @@ namespace UnitTest ExpectedMesh expectedMesh; expectedMesh.m_indexCount = indexCount; expectedMesh.m_vertexCount = vertexCount; - expectedMesh.m_material = m_materialAsset; + expectedMesh.m_materialSlotId = sharedMeshCount + i; RHI::BufferViewDescriptor indexBufferViewDescriptor = RHI::BufferViewDescriptor::CreateStructured(0, indexCount, sizeof(uint32_t)); @@ -213,7 +217,7 @@ namespace UnitTest creator.BeginMesh(); Aabb aabb = expectedMesh.m_aabb; creator.SetMeshAabb(AZStd::move(aabb)); - creator.SetMeshMaterialAsset(m_materialAsset); + creator.SetMeshMaterialSlot(materialSlotId++); creator.SetMeshIndexBuffer({ BuildTestBuffer(indexCount, sizeof(uint32_t)), indexBufferViewDescriptor }); creator.AddMeshStreamBuffer(GetPositionSemantic(), AZ::Name(), { positonBuffer, positionBufferViewDescriptor }); @@ -239,6 +243,15 @@ namespace UnitTest creator.Begin(Data::AssetId(AZ::Uuid::CreateRandom())); creator.SetName("TestModel"); + + for (RPI::ModelMaterialSlot::StableId materialSlotId = 0; materialSlotId < sharedMeshCount + separateMeshCount; ++materialSlotId) + { + RPI::ModelMaterialSlot slot; + slot.m_defaultMaterialAsset = m_materialAsset; + slot.m_displayName = AZStd::string::format("Slot%d", materialSlotId); + slot.m_stableId = materialSlotId; + creator.AddMaterialSlot(slot); + } for (uint32_t i = 0; i < lodCount; ++i) { @@ -263,7 +276,7 @@ namespace UnitTest EXPECT_TRUE(mesh.GetAabb() == expectedMesh.m_aabb); EXPECT_TRUE(mesh.GetIndexCount() == expectedMesh.m_indexCount); EXPECT_TRUE(mesh.GetVertexCount() == expectedMesh.m_vertexCount); - EXPECT_TRUE(mesh.GetMaterialAsset() == expectedMesh.m_material); + EXPECT_TRUE(mesh.GetMaterialSlotId() == expectedMesh.m_materialSlotId); } void ValidateLodAsset(const AZ::RPI::ModelLodAsset* lodAsset, const ExpectedLod& expectedLod) @@ -687,11 +700,11 @@ namespace UnitTest } } - // Tests that if we try to set the material id on a mesh + // Tests that if we try to set the material slot on a mesh // without calling Begin or BeginMesh that it fails // as expected. Also tests the case that Begin *is* // called but BeginMesh is not. - TEST_F(ModelTests, SetMaterialIdNoBeginNoBeginMesh) + TEST_F(ModelTests, SetMaterialSlotNoBeginNoBeginMesh) { using namespace AZ; @@ -699,7 +712,7 @@ namespace UnitTest { ErrorMessageFinder messageFinder("Begin() was not called"); - creator.SetMeshMaterialAsset(m_materialAsset); + creator.SetMeshMaterialSlot(0); } creator.Begin(Data::AssetId(AZ::Uuid::CreateRandom())); @@ -707,7 +720,7 @@ namespace UnitTest //This should still fail even if we call Begin but not BeginMesh { ErrorMessageFinder messageFinder("BeginMesh() was not called"); - creator.SetMeshMaterialAsset(m_materialAsset); + creator.SetMeshMaterialSlot(0); } } @@ -827,7 +840,7 @@ namespace UnitTest creator.BeginMesh(); creator.SetMeshAabb(AZStd::move(aabb)); - creator.SetMeshMaterialAsset(m_materialAsset); + creator.SetMeshMaterialSlot(0); creator.SetMeshIndexBuffer({ BuildTestBuffer(indexCount, sizeof(uint32_t)), indexBufferViewDescriptor }); creator.AddMeshStreamBuffer(GetPositionSemantic(), AZ::Name(), { BuildTestBuffer(vertexCount, sizeof(float) * 3), vertexBufferViewDescriptor }); @@ -842,7 +855,7 @@ namespace UnitTest ErrorMessageFinder messageFinder("BeginMesh() was not called", 5); creator.SetMeshAabb(AZStd::move(aabb)); - creator.SetMeshMaterialAsset(m_materialAsset); + creator.SetMeshMaterialSlot(0); creator.SetMeshIndexBuffer({ BuildTestBuffer(indexCount, sizeof(uint32_t)), indexBufferViewDescriptor }); creator.AddMeshStreamBuffer(GetPositionSemantic(), AZ::Name(), { BuildTestBuffer(vertexCount, sizeof(float) * 3), vertexBufferViewDescriptor }); @@ -885,7 +898,7 @@ namespace UnitTest creator.BeginMesh(); creator.SetMeshAabb(AZStd::move(aabb)); - creator.SetMeshMaterialAsset(m_materialAsset); + creator.SetMeshMaterialSlot(0); creator.SetMeshIndexBuffer({ BuildTestBuffer(indexCount, sizeof(uint32_t)), indexBufferViewDescriptor }); creator.AddMeshStreamBuffer(GetPositionSemantic(), AZ::Name(), { BuildTestBuffer(vertexCount, sizeof(float) * 3), vertexBufferViewDescriptor }); @@ -907,7 +920,7 @@ namespace UnitTest creator.BeginMesh(); creator.SetMeshAabb(AZStd::move(aabb)); - creator.SetMeshMaterialAsset(m_materialAsset); + creator.SetMeshMaterialSlot(0); creator.SetMeshIndexBuffer({ BuildTestBuffer(indexCount, sizeof(uint32_t)), indexBufferViewDescriptor }); creator.AddMeshStreamBuffer(GetPositionSemantic(), AZ::Name(), { BuildTestBuffer(vertexCount, sizeof(float) * 3), vertexBufferViewDescriptor }); @@ -1019,10 +1032,7 @@ namespace UnitTest lodCreator.BeginMesh(); lodCreator.SetMeshAabb(AZ::Aabb::CreateFromMinMax({-1.0f, -1.0f, -0.5f}, {1.0f, 1.0f, 0.5f})); - lodCreator.SetMeshMaterialAsset( - AZ::Data::Asset(AZ::Data::AssetId(AZ::Uuid::CreateRandom(), 0), - AZ::AzTypeInfo::Uuid(), "") - ); + lodCreator.SetMeshMaterialSlot(AZ::Sfmt::GetInstance().Rand32()); { AZ::Data::Asset indexBuffer = BuildTestBuffer(indicesCount, sizeof(uint32_t)); From 9ee9730294bb1f4b4a260a90c5f551cb8c42549d Mon Sep 17 00:00:00 2001 From: AMZN-stankowi <4838196+AMZN-stankowi@users.noreply.github.com> Date: Mon, 2 Aug 2021 10:57:57 -0700 Subject: [PATCH 154/160] Automated test for scene files with and without python scripts running python incorrectly (#2373) * Cleared m_scriptFilename between scene files. This fixes a bug where a Python script file would be run on a scene file that didn't have a script file set. Added a general case version to SceneBuilderWorker.cpp, to make it easy to mark all scene files as dirty. Automated tests for this will come in a separate pull request. Signed-off-by: stankowi <4838196+AMZN-stankowi@users.noreply.github.com> * Work in progress automated tests Signed-off-by: stankowi <4838196+AMZN-stankowi@users.noreply.github.com> * Python test done Signed-off-by: stankowi <4838196+AMZN-stankowi@users.noreply.github.com> * Sorted jobs work now. This may sort too aggressively, I'll remove the additional sorting after some testing. Signed-off-by: stankowi <4838196+AMZN-stankowi@users.noreply.github.com> * Cleaned up test Signed-off-by: stankowi <4838196+AMZN-stankowi@users.noreply.github.com> * Fixed stray ' Signed-off-by: stankowi <4838196+AMZN-stankowi@users.noreply.github.com> * Removed temp code from test Signed-off-by: stankowi <4838196+AMZN-stankowi@users.noreply.github.com> * Command line help options for AP Removed job sorting that wasn't actually sorting jobs Signed-off-by: stankowi <4838196+AMZN-stankowi@users.noreply.github.com> * Changed constant variable names to match coding standards Signed-off-by: stankowi <4838196+AMZN-stankowi@users.noreply.github.com> --- .../PythonTests/assetpipeline/CMakeLists.txt | 1 + .../assetpipeline/fbx_tests/CMakeLists.txt | 21 ++++ .../a_simple_box_with_script.fbx | 3 + .../a_simple_box_with_script.fbx.assetinfo | 9 ++ .../b_simple_box_no_script.fbx | 3 + .../b_simple_box_no_script.fbx.assetinfo | 15 +++ .../python_builder.py | 45 +++++++ .../fbx_tests/pythonassetbuildertests.py | 94 ++++++++++++++ .../AssetManager/assetProcessorManager.cpp | 6 +- .../AssetManager/assetProcessorManager.h | 5 + .../AssetProcessor/native/assetprocessor.h | 5 + .../resourcecompiler/RCQueueSortModel.cpp | 10 ++ .../resourcecompiler/RCQueueSortModel.h | 9 ++ .../native/resourcecompiler/rccontroller.cpp | 5 + .../native/resourcecompiler/rccontroller.h | 5 +- .../utilities/ApplicationManagerBase.cpp | 118 ++++++++++++++---- .../native/utilities/ApplicationManagerBase.h | 5 + 17 files changed, 329 insertions(+), 30 deletions(-) create mode 100644 AutomatedTesting/Gem/PythonTests/assetpipeline/fbx_tests/CMakeLists.txt create mode 100644 AutomatedTesting/Gem/PythonTests/assetpipeline/fbx_tests/assets/TwoSceneFiles_OneWithPythonOneWithout_PythonOnlyRunsOnFirstScene/a_simple_box_with_script.fbx create mode 100644 AutomatedTesting/Gem/PythonTests/assetpipeline/fbx_tests/assets/TwoSceneFiles_OneWithPythonOneWithout_PythonOnlyRunsOnFirstScene/a_simple_box_with_script.fbx.assetinfo create mode 100644 AutomatedTesting/Gem/PythonTests/assetpipeline/fbx_tests/assets/TwoSceneFiles_OneWithPythonOneWithout_PythonOnlyRunsOnFirstScene/b_simple_box_no_script.fbx create mode 100644 AutomatedTesting/Gem/PythonTests/assetpipeline/fbx_tests/assets/TwoSceneFiles_OneWithPythonOneWithout_PythonOnlyRunsOnFirstScene/b_simple_box_no_script.fbx.assetinfo create mode 100644 AutomatedTesting/Gem/PythonTests/assetpipeline/fbx_tests/assets/TwoSceneFiles_OneWithPythonOneWithout_PythonOnlyRunsOnFirstScene/python_builder.py create mode 100644 AutomatedTesting/Gem/PythonTests/assetpipeline/fbx_tests/pythonassetbuildertests.py diff --git a/AutomatedTesting/Gem/PythonTests/assetpipeline/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/assetpipeline/CMakeLists.txt index 1b42d0d871..29b30a12b4 100644 --- a/AutomatedTesting/Gem/PythonTests/assetpipeline/CMakeLists.txt +++ b/AutomatedTesting/Gem/PythonTests/assetpipeline/CMakeLists.txt @@ -7,6 +7,7 @@ # add_subdirectory(asset_processor_tests) +add_subdirectory(fbx_tests) if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) ## AP Python Tests ## diff --git a/AutomatedTesting/Gem/PythonTests/assetpipeline/fbx_tests/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/assetpipeline/fbx_tests/CMakeLists.txt new file mode 100644 index 0000000000..4a26500ee2 --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/assetpipeline/fbx_tests/CMakeLists.txt @@ -0,0 +1,21 @@ +# +# Copyright (c) Contributors to the Open 3D Engine Project. +# For complete copyright and license terms please see the LICENSE at the root of this distribution. +# +# SPDX-License-Identifier: Apache-2.0 OR MIT +# +# + +if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) + ly_add_pytest( + NAME SceneProcessingTests.PythonAssetBuilderTests + TEST_SUITE main + PATH ${CMAKE_CURRENT_LIST_DIR}/pythonassetbuildertests.py + PYTEST_MARKS "not SUITE_sandbox" # don't run sandbox tests in this file + EXCLUDE_TEST_RUN_TARGET_FROM_IDE + RUNTIME_DEPENDENCIES + AZ::AssetProcessorBatch + AZ::AssetProcessor + ) + +endif() diff --git a/AutomatedTesting/Gem/PythonTests/assetpipeline/fbx_tests/assets/TwoSceneFiles_OneWithPythonOneWithout_PythonOnlyRunsOnFirstScene/a_simple_box_with_script.fbx b/AutomatedTesting/Gem/PythonTests/assetpipeline/fbx_tests/assets/TwoSceneFiles_OneWithPythonOneWithout_PythonOnlyRunsOnFirstScene/a_simple_box_with_script.fbx new file mode 100644 index 0000000000..e31b4a96f2 --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/assetpipeline/fbx_tests/assets/TwoSceneFiles_OneWithPythonOneWithout_PythonOnlyRunsOnFirstScene/a_simple_box_with_script.fbx @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f82aecb36faf5cf9f2730e5ad264db38a3a469f8f48aff9b74682d1a32b098f0 +size 11644 diff --git a/AutomatedTesting/Gem/PythonTests/assetpipeline/fbx_tests/assets/TwoSceneFiles_OneWithPythonOneWithout_PythonOnlyRunsOnFirstScene/a_simple_box_with_script.fbx.assetinfo b/AutomatedTesting/Gem/PythonTests/assetpipeline/fbx_tests/assets/TwoSceneFiles_OneWithPythonOneWithout_PythonOnlyRunsOnFirstScene/a_simple_box_with_script.fbx.assetinfo new file mode 100644 index 0000000000..07018ab521 --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/assetpipeline/fbx_tests/assets/TwoSceneFiles_OneWithPythonOneWithout_PythonOnlyRunsOnFirstScene/a_simple_box_with_script.fbx.assetinfo @@ -0,0 +1,9 @@ +{ + "values": + [ + { + "$type": "ScriptProcessorRule", + "scriptFilename": "TwoSceneFiles_OneWithPythonOneWithout_PythonOnlyRunsOnFirstScene/python_builder.py" + } + ] +} diff --git a/AutomatedTesting/Gem/PythonTests/assetpipeline/fbx_tests/assets/TwoSceneFiles_OneWithPythonOneWithout_PythonOnlyRunsOnFirstScene/b_simple_box_no_script.fbx b/AutomatedTesting/Gem/PythonTests/assetpipeline/fbx_tests/assets/TwoSceneFiles_OneWithPythonOneWithout_PythonOnlyRunsOnFirstScene/b_simple_box_no_script.fbx new file mode 100644 index 0000000000..e31b4a96f2 --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/assetpipeline/fbx_tests/assets/TwoSceneFiles_OneWithPythonOneWithout_PythonOnlyRunsOnFirstScene/b_simple_box_no_script.fbx @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f82aecb36faf5cf9f2730e5ad264db38a3a469f8f48aff9b74682d1a32b098f0 +size 11644 diff --git a/AutomatedTesting/Gem/PythonTests/assetpipeline/fbx_tests/assets/TwoSceneFiles_OneWithPythonOneWithout_PythonOnlyRunsOnFirstScene/b_simple_box_no_script.fbx.assetinfo b/AutomatedTesting/Gem/PythonTests/assetpipeline/fbx_tests/assets/TwoSceneFiles_OneWithPythonOneWithout_PythonOnlyRunsOnFirstScene/b_simple_box_no_script.fbx.assetinfo new file mode 100644 index 0000000000..72d756d655 --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/assetpipeline/fbx_tests/assets/TwoSceneFiles_OneWithPythonOneWithout_PythonOnlyRunsOnFirstScene/b_simple_box_no_script.fbx.assetinfo @@ -0,0 +1,15 @@ +{ + "values": [ + { + "$type": "{07B356B7-3635-40B5-878A-FAC4EFD5AD86} MeshGroup", + "name": "b_simple_box_no_script", + "nodeSelectionList": { + "selectedNodes": [ + {}, + "RootNode", + "RootNode.Cube" + ] + } + } + ] +} \ No newline at end of file diff --git a/AutomatedTesting/Gem/PythonTests/assetpipeline/fbx_tests/assets/TwoSceneFiles_OneWithPythonOneWithout_PythonOnlyRunsOnFirstScene/python_builder.py b/AutomatedTesting/Gem/PythonTests/assetpipeline/fbx_tests/assets/TwoSceneFiles_OneWithPythonOneWithout_PythonOnlyRunsOnFirstScene/python_builder.py new file mode 100644 index 0000000000..7ad5894a86 --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/assetpipeline/fbx_tests/assets/TwoSceneFiles_OneWithPythonOneWithout_PythonOnlyRunsOnFirstScene/python_builder.py @@ -0,0 +1,45 @@ +""" +Copyright (c) Contributors to the Open 3D Engine Project. +For complete copyright and license terms please see the LICENSE at the root of this distribution. + +SPDX-License-Identifier: Apache-2.0 OR MIT +""" +import datetime, uuid, os +import azlmbr.scene as sceneApi +import azlmbr.scene.graph + +def output_test_data(scene): + source_filename = os.path.basename(scene.sourceFilename) + source_filename = source_filename.replace('.','_') + + log_output_file_name = f"{source_filename}.log" + + log_output_folder = os.path.dirname(scene.sourceFilename) + log_output_location = os.path.join(log_output_folder, log_output_file_name) + + # Saving a file to the temp folder is the easiest way to have this test communicate + # with the outer python test. + with open(log_output_location, "w") as f: + # Just write something to the file, but the filename is the main information + # used for the test. + f.write(f"scene.sourceFilename: {scene.sourceFilename}\n") + return True + +mySceneJobHandler = None + +def on_update_manifest(args): + scene = args[0] + result = output_test_data(scene) + global mySceneJobHandler + mySceneJobHandler.disconnect() + mySceneJobHandler = None + return result + +def main(): + global mySceneJobHandler + mySceneJobHandler = sceneApi.ScriptBuildingNotificationBusHandler() + mySceneJobHandler.connect() + mySceneJobHandler.add_callback('OnUpdateManifest', on_update_manifest) + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/AutomatedTesting/Gem/PythonTests/assetpipeline/fbx_tests/pythonassetbuildertests.py b/AutomatedTesting/Gem/PythonTests/assetpipeline/fbx_tests/pythonassetbuildertests.py new file mode 100644 index 0000000000..6a568349d2 --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/assetpipeline/fbx_tests/pythonassetbuildertests.py @@ -0,0 +1,94 @@ +""" +Copyright (c) Contributors to the Open 3D Engine Project. +For complete copyright and license terms please see the LICENSE at the root of this distribution. + +SPDX-License-Identifier: Apache-2.0 OR MIT +""" + +# Import builtin libraries +import pytest +import logging +import os +import stat + +# Import LyTestTools +from ly_test_tools.o3de.asset_processor import AssetProcessor +from ly_test_tools.o3de import asset_processor as asset_processor_utils +import ly_test_tools.environment.file_system as fs + +# Import fixtures +from ..ap_fixtures.asset_processor_fixture import asset_processor as asset_processor +from ..ap_fixtures.ap_setup_fixture import ap_setup_fixture as ap_setup_fixture + +# Import LyShared +from ly_test_tools.o3de.ap_log_parser import APLogParser, APOutputParser +import ly_test_tools.o3de.pipeline_utils as utils + +# Use the following logging pattern to hook all test logging together: +logger = logging.getLogger(__name__) +# Configuring the logging is done in ly_test_tools at the following location: +# ~/dev/Tools/LyTestTools/ly_test_tools/log/py_logging_util.py + +# Helper: variables we will use for parameter values in the test: +targetProjects = ["AutomatedTesting"] + +@pytest.fixture +def local_resources(request, workspace, ap_setup_fixture): + ap_setup_fixture["tests_dir"] = os.path.dirname(os.path.realpath(__file__)) + + +@pytest.mark.usefixtures("asset_processor") +@pytest.mark.usefixtures("ap_setup_fixture") +@pytest.mark.usefixtures("local_resources") +@pytest.mark.parametrize("project", targetProjects) +@pytest.mark.assetpipeline +@pytest.mark.SUITE_main +class TestsPythonAssetProcessing_APBatch(object): + + @pytest.mark.BAT + @pytest.mark.assetpipeline + def test_ProcessAssetWithoutScriptAfterAssetWithScript_ScriptOnlyRunsOnExpectedAsset(self, workspace, ap_setup_fixture, asset_processor): + # This is a regression test. The situation it's testing is, the Python script to run + # defined in scene manifest files was persisting in a single builder. So if + # that builder processed file a.fbx, then b.fbx, and a.fbx has a Python script to run, + # it was also running that Python script on b.fbx. + + asset_processor.prepare_test_environment(ap_setup_fixture["tests_dir"], "TwoSceneFiles_OneWithPythonOneWithout_PythonOnlyRunsOnFirstScene") + + asset_processor_extra_params = [ + # Disabling Atom assets disables most products, using the debugOutput flag ensures one product is output. + "--debugOutput", + # By default, if job priorities are equal, jobs run in an arbitrary order. This makes sure + # jobs are run by sorting on the database source name, so they run in the same order each time + # when this test is run. + "--sortJobsByDBSourceName", + # Disabling Atom products means this asset won't need a lot of source dependencies to be processed, + # keeping the scope of this test down. + "--regset=\"/O3DE/SceneAPI/AssetImporter/SkipAtomOutput=true\"", + # The bug this regression test happened when the same builder processed FBX files with and without Python. + # This flag ensures that only one builder is launched, so that situation can be replicated. + "--regset=\"/Amazon/AssetProcessor/Settings/Jobs/maxJobs=1\""] + + result, _ = asset_processor.batch_process(extra_params=asset_processor_extra_params) + assert result, "AP Batch failed" + + expected_product_list = [ + "a_simple_box_with_script.dbgsg", + "b_simple_box_no_script.dbgsg" + ] + + missing_assets, _ = utils.compare_assets_with_cache(expected_product_list, + asset_processor.project_test_cache_folder()) + assert not missing_assets, f'The following assets were expected to be in, but not found in cache: {str(missing_assets)}' + + # The Python script loaded in the scene manifest will write a log file with the source file's name + # to the temp folder. This is the easiest way to have the internal Python there communicate with this test. + expected_path = os.path.join(asset_processor.project_test_source_folder(), "a_simple_box_with_script_fbx.log") + unexpected_path = os.path.join(asset_processor.project_test_source_folder(), "b_simple_box_no_script_fbx.log") + + # Simple check to make sure the Python script in the scene manifest ran on the file it should have ran on. + assert os.path.exists(expected_path), f"Did not find expected output test asset {expected_path}" + # If this test fails here, it means the Python script from the first processed FBX file is being run + # on the second FBX file, when it should not be. + assert not os.path.exists(unexpected_path), f"Found unexpected output test asset {unexpected_path}" + diff --git a/Code/Tools/AssetProcessor/native/AssetManager/assetProcessorManager.cpp b/Code/Tools/AssetProcessor/native/AssetManager/assetProcessorManager.cpp index 21089ef020..3a7bc6ef3e 100644 --- a/Code/Tools/AssetProcessor/native/AssetManager/assetProcessorManager.cpp +++ b/Code/Tools/AssetProcessor/native/AssetManager/assetProcessorManager.cpp @@ -3072,6 +3072,7 @@ namespace AssetProcessor QElapsedTimer elapsedTimer; elapsedTimer.start(); + for (auto jobIter = m_jobsToProcess.begin(); jobIter != m_jobsToProcess.end();) { JobDetails& job = *jobIter; @@ -3082,7 +3083,7 @@ namespace AssetProcessor jobIter = m_jobsToProcess.erase(jobIter); m_numOfJobsToAnalyze--; - // Update the remaining job status occasionally + // Update the remaining job status occasionally if (elapsedTimer.elapsed() >= MILLISECONDS_BETWEEN_PROCESS_JOBS_STATUS_UPDATE) { Q_EMIT NumRemainingJobsChanged(m_activeFiles.size() + m_filesToExamine.size() + m_numOfJobsToAnalyze); @@ -3102,7 +3103,8 @@ namespace AssetProcessor // Process the first job if no jobs were analyzed. auto jobIter = m_jobsToProcess.begin(); JobDetails& job = *jobIter; - AZ_Warning(AssetProcessor::DebugChannel, false, " Cyclic job dependency detected. Processing job (%s, %s, %s, %s) to unblock.", + AZ_Warning( + AssetProcessor::DebugChannel, false, " Cyclic job dependency detected. Processing job (%s, %s, %s, %s) to unblock.", job.m_jobEntry.m_databaseSourceName.toUtf8().data(), job.m_jobEntry.m_jobKey.toUtf8().data(), job.m_jobEntry.m_platformInfo.m_identifier.c_str(), job.m_jobEntry.m_builderGuid.ToString().c_str()); ProcessJob(job); diff --git a/Code/Tools/AssetProcessor/native/AssetManager/assetProcessorManager.h b/Code/Tools/AssetProcessor/native/AssetManager/assetProcessorManager.h index 5fc7a73035..376af5d773 100644 --- a/Code/Tools/AssetProcessor/native/AssetManager/assetProcessorManager.h +++ b/Code/Tools/AssetProcessor/native/AssetManager/assetProcessorManager.h @@ -207,6 +207,11 @@ namespace AssetProcessor //! or a job dependency and we can only resolve these dependencies once all the create jobs are completed. struct JobToProcessEntry { + bool operator<(const JobToProcessEntry& other) + { + return m_sourceFileInfo.m_pathRelativeToScanFolder < other.m_sourceFileInfo.m_pathRelativeToScanFolder; + } + SourceFileInfo m_sourceFileInfo; AZStd::vector m_jobsToAnalyze; // a vector of pairs of diff --git a/Code/Tools/AssetProcessor/native/assetprocessor.h b/Code/Tools/AssetProcessor/native/assetprocessor.h index 2397f3b1ff..1c13eca200 100644 --- a/Code/Tools/AssetProcessor/native/assetprocessor.h +++ b/Code/Tools/AssetProcessor/native/assetprocessor.h @@ -244,6 +244,11 @@ namespace AssetProcessor m_jobEntry.m_builderGuid == rhs.m_jobEntry.m_builderGuid); } + static bool DatabaseSourceLexCompare(const JobDetails& left, const JobDetails& right) + { + return left.m_jobEntry.m_databaseSourceName <= right.m_jobEntry.m_databaseSourceName; + } + JobDetails() = default; }; diff --git a/Code/Tools/AssetProcessor/native/resourcecompiler/RCQueueSortModel.cpp b/Code/Tools/AssetProcessor/native/resourcecompiler/RCQueueSortModel.cpp index c39a0c66e9..774876234d 100644 --- a/Code/Tools/AssetProcessor/native/resourcecompiler/RCQueueSortModel.cpp +++ b/Code/Tools/AssetProcessor/native/resourcecompiler/RCQueueSortModel.cpp @@ -197,10 +197,20 @@ namespace AssetProcessor { return priorityLeft > priorityRight; } + + // Optionally stabilize queue order on the source name. + // This is used in automated tests, to allow tests to have a stable + // order that jobs with otherwise equal priority run, so tests process + // assets in the same order each time they are run. + if (m_sortQueueOnDBSourceName) + { + return leftJob->GetJobEntry().m_databaseSourceName < rightJob->GetJobEntry().m_databaseSourceName; + } // if we get all the way down here it means we're dealing with two assets which are not // in any compile groups, not a priority platform, not a priority type, priority platform, etc. // we can arrange these any way we want, but must pick at least a stable order. + return leftJob->GetJobEntry().m_jobRunKey < rightJob->GetJobEntry().m_jobRunKey; } diff --git a/Code/Tools/AssetProcessor/native/resourcecompiler/RCQueueSortModel.h b/Code/Tools/AssetProcessor/native/resourcecompiler/RCQueueSortModel.h index fbeacd8b8c..7fc60fdd60 100644 --- a/Code/Tools/AssetProcessor/native/resourcecompiler/RCQueueSortModel.h +++ b/Code/Tools/AssetProcessor/native/resourcecompiler/RCQueueSortModel.h @@ -50,6 +50,10 @@ namespace AssetProcessor void AddJobIdEntry(AssetProcessor::RCJob* rcJob); void RemoveJobIdEntry(AssetProcessor::RCJob* rcJob); + void SetQueueSortOnDBSourceName() + { + m_sortQueueOnDBSourceName = true; + } // implement QSortFilteRProxyModel: bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const override; @@ -68,6 +72,11 @@ namespace AssetProcessor QSet m_currentlyConnectedPlatforms; bool m_dirtyNeedsResort = false; // instead of constantly resorting, we resort only when someone wants to pull an element from us + // By default, jobs with equal priority and escalation sort on the job run key. This flag changes + // jobs to sort on the database source name. This is used for testing, to guarantee jobs run in the same + // order for those tests each time they are run. + bool m_sortQueueOnDBSourceName = false; + // --------------------------------------------------------- // AssetProcessorPlatformBus::Handler void AssetProcessorPlatformConnected(const AZStd::string platform) override; diff --git a/Code/Tools/AssetProcessor/native/resourcecompiler/rccontroller.cpp b/Code/Tools/AssetProcessor/native/resourcecompiler/rccontroller.cpp index 11ef68de29..660144095b 100644 --- a/Code/Tools/AssetProcessor/native/resourcecompiler/rccontroller.cpp +++ b/Code/Tools/AssetProcessor/native/resourcecompiler/rccontroller.cpp @@ -163,6 +163,11 @@ namespace AssetProcessor return ((!m_RCQueueSortModel.GetNextPendingJob()) && (m_RCJobListModel.jobsInFlight() == 0)); } + void RCController::SetQueueSortOnDBSourceName() + { + m_RCQueueSortModel.SetQueueSortOnDBSourceName(); + } + void RCController::JobSubmitted(JobDetails details) { AssetProcessor::QueueElementID checkFile(details.m_jobEntry.m_databaseSourceName, details.m_jobEntry.m_platformInfo.m_identifier.c_str(), details.m_jobEntry.m_jobKey); diff --git a/Code/Tools/AssetProcessor/native/resourcecompiler/rccontroller.h b/Code/Tools/AssetProcessor/native/resourcecompiler/rccontroller.h index c555c7a585..51ae6b4a26 100644 --- a/Code/Tools/AssetProcessor/native/resourcecompiler/rccontroller.h +++ b/Code/Tools/AssetProcessor/native/resourcecompiler/rccontroller.h @@ -54,10 +54,11 @@ namespace AssetProcessor void StartJob(AssetProcessor::RCJob* rcJob); int NumberOfPendingCriticalJobsPerPlatform(QString platform); - void SetSystemRoot(const QDir& systemRoot); int NumberOfPendingJobsPerPlatform(QString platform); bool IsIdle(); - bool IsPriorityCopyJob(AssetProcessor::RCJob* rcJob); + + void SetQueueSortOnDBSourceName(); + Q_SIGNALS: void FileCompiled(JobEntry entry, AssetBuilderSDK::ProcessJobResponse response); void FileFailed(JobEntry entry); diff --git a/Code/Tools/AssetProcessor/native/utilities/ApplicationManagerBase.cpp b/Code/Tools/AssetProcessor/native/utilities/ApplicationManagerBase.cpp index 5e2de8e4cd..b90364e1c5 100644 --- a/Code/Tools/AssetProcessor/native/utilities/ApplicationManagerBase.cpp +++ b/Code/Tools/AssetProcessor/native/utilities/ApplicationManagerBase.cpp @@ -49,8 +49,6 @@ static const qint64 s_ReservedDiskSpaceInBytes = 256 * 1024; //! Maximum number of temp folders allowed static const int s_MaximumTempFolders = 10000; -const char AdditionalScanFolders[] = "additionalScanFolders"; - ApplicationManagerBase::ApplicationManagerBase(int* argc, char*** argv, QObject* parent) : ApplicationManager(argc, argv, parent) { @@ -155,55 +153,90 @@ void ApplicationManagerBase::InitAssetProcessorManager() const AzFramework::CommandLine* commandLine = nullptr; AzFramework::ApplicationRequests::Bus::BroadcastResult(commandLine, &AzFramework::ApplicationRequests::GetCommandLine); - if(commandLine->HasSwitch("zeroAnalysisMode")) + struct APCommandLineSwitch + { + APCommandLineSwitch(const char* switchTitle, const char* helpText) + : m_switch(switchTitle) + , m_helpText(helpText) + { + + } + const char* m_switch; + const char* m_helpText; + }; + + const APCommandLineSwitch Command_waitOnLaunch("waitOnLaunch", "Briefly pauses Asset Processor during initializiation. Useful if you want to attach a debugger."); + const APCommandLineSwitch Command_zeroAnalysisMode("zeroAnalysisMode", "Enables using file modification time when examining source assets for processing."); + const APCommandLineSwitch Command_enableQueryLogging("enableQueryLogging", "Enables logging database queries."); + const APCommandLineSwitch Command_dependencyScanPattern("dependencyScanPattern", "Scans assets that match the given pattern for missing product dependencies."); + const APCommandLineSwitch Command_dsp("dsp", Command_dependencyScanPattern.m_helpText); + const APCommandLineSwitch Command_fileDependencyScanPattern("fileDependencyScanPattern", "Used with dependencyScanPattern to farther filter the scan."); + const APCommandLineSwitch Command_fdsp("fdsp", Command_fileDependencyScanPattern.m_helpText); + const APCommandLineSwitch Command_additionalScanFolders("additionalScanFolders", "Used with dependencyScanPattern to farther filter the scan."); + const APCommandLineSwitch Command_dependencyScanMaxIteration("dependencyScanMaxIteration", "Used to limit the number of recursive searches per line when running dependencyScanPattern."); + const APCommandLineSwitch Command_warningLevel("warningLevel", "Configure the error and warning reporting level for AssetProcessor. Pass in 1 for fatal errors, 2 for fatal errors and warnings."); + const APCommandLineSwitch Command_acceptInput("acceptInput", "Enable external control messaging via the ControlRequestHandler, used with automated tests."); + const APCommandLineSwitch Command_debugOutput("debugOutput", "When enabled, builders that support it will output debug information as product assets. Used primarily with scene files."); + const APCommandLineSwitch Command_sortJobsByDBSourceName("sortJobsByDBSourceName", "When enabled, sorts pending jobs with equal priority and dependencies by database source name instead of job ID. Useful for automated tests to process assets in the same order each time."); + const APCommandLineSwitch Command_truncatefingerprint("truncatefingerprint", "Truncates the fingerprint used for processed assets. Useful if you plan to compress product assets to share on another machine because some compression formats like zip will truncate file mod timestamps."); + const APCommandLineSwitch Command_help("help", "Displays this message."); + const APCommandLineSwitch Command_h("h", Command_help.m_helpText); + + if (commandLine->HasSwitch(Command_waitOnLaunch.m_switch)) + { + // Useful for attaching the debugger, this forces a short pause. + AZStd::this_thread::sleep_for(AZStd::chrono::seconds(20)); + } + + if (commandLine->HasSwitch(Command_zeroAnalysisMode.m_switch)) { m_assetProcessorManager->SetEnableModtimeSkippingFeature(true); } - if(commandLine->HasSwitch("enableQueryLogging")) + if (commandLine->HasSwitch(Command_enableQueryLogging.m_switch)) { m_assetProcessorManager->SetQueryLogging(true); } - if (commandLine->HasSwitch("dependencyScanPattern")) + if (commandLine->HasSwitch(Command_dependencyScanPattern.m_switch)) { - m_dependencyScanPattern = commandLine->GetSwitchValue("dependencyScanPattern", 0).c_str(); + m_dependencyScanPattern = commandLine->GetSwitchValue(Command_dependencyScanPattern.m_switch, 0).c_str(); } - else if (commandLine->HasSwitch("dsp")) + else if (commandLine->HasSwitch(Command_dsp.m_switch)) { - m_dependencyScanPattern = commandLine->GetSwitchValue("dsp", 0).c_str(); + m_dependencyScanPattern = commandLine->GetSwitchValue(Command_dsp.m_switch, 0).c_str(); } m_fileDependencyScanPattern = "*"; - if (commandLine->HasSwitch("fileDependencyScanPattern")) + if (commandLine->HasSwitch(Command_fileDependencyScanPattern.m_switch)) { - m_fileDependencyScanPattern = commandLine->GetSwitchValue("fileDependencyScanPattern", 0).c_str(); + m_fileDependencyScanPattern = commandLine->GetSwitchValue(Command_fileDependencyScanPattern.m_switch, 0).c_str(); } - else if (commandLine->HasSwitch("fdsp")) + else if (commandLine->HasSwitch(Command_fdsp.m_switch)) { - m_fileDependencyScanPattern = commandLine->GetSwitchValue("fdsp", 0).c_str(); + m_fileDependencyScanPattern = commandLine->GetSwitchValue(Command_fdsp.m_switch, 0).c_str(); } - if (commandLine->HasSwitch(AdditionalScanFolders)) + if (commandLine->HasSwitch(Command_additionalScanFolders.m_switch)) { - for (size_t idx = 0; idx < commandLine->GetNumSwitchValues(AdditionalScanFolders); idx++) + for (size_t idx = 0; idx < commandLine->GetNumSwitchValues(Command_additionalScanFolders.m_switch); idx++) { - AZStd::string value = commandLine->GetSwitchValue(AdditionalScanFolders, idx); + AZStd::string value = commandLine->GetSwitchValue(Command_additionalScanFolders.m_switch, idx); m_dependencyAddtionalScanFolders.emplace_back(AZStd::move(value)); } } - if (commandLine->HasSwitch("dependencyScanMaxIteration")) + if (commandLine->HasSwitch(Command_dependencyScanMaxIteration.m_switch)) { - AZStd::string maxIterationAsString = commandLine->GetSwitchValue("dependencyScanMaxIteration", 0); + AZStd::string maxIterationAsString = commandLine->GetSwitchValue(Command_dependencyScanMaxIteration.m_switch, 0); m_dependencyScanMaxIteration = AZStd::stoi(maxIterationAsString); } - if (commandLine->HasSwitch("warningLevel")) + if (commandLine->HasSwitch(Command_warningLevel.m_switch)) { using namespace AssetProcessor; - const AZStd::string& levelString = commandLine->GetSwitchValue("warningLevel", 0); + const AZStd::string& levelString = commandLine->GetSwitchValue(Command_warningLevel.m_switch, 0); WarningLevel warningLevel = WarningLevel::Default; switch(AZStd::stoi(levelString)) @@ -217,26 +250,30 @@ void ApplicationManagerBase::InitAssetProcessorManager() } AssetProcessor::JobDiagnosticRequestBus::Broadcast(&AssetProcessor::JobDiagnosticRequestBus::Events::SetWarningLevel, warningLevel); } - if (commandLine->HasSwitch("acceptInput")) + if (commandLine->HasSwitch(Command_acceptInput.m_switch)) { InitControlRequestHandler(); } - if (commandLine->HasSwitch("debugOutput")) + if (commandLine->HasSwitch(Command_debugOutput.m_switch)) { m_assetProcessorManager->SetBuilderDebugFlag(true); } - constexpr char truncateFingerprintSwitch[] = "truncatefingerprint"; - if(commandLine->HasSwitch(truncateFingerprintSwitch)) + if (commandLine->HasSwitch(Command_sortJobsByDBSourceName.m_switch)) + { + m_sortJobsByDBSourceName = true; + } + + if (commandLine->HasSwitch(Command_truncatefingerprint.m_switch)) { // Zip archive format uses 2 second precision truncated const int ArchivePrecision = 2000; int precision = ArchivePrecision; - if(commandLine->GetNumSwitchValues(truncateFingerprintSwitch) > 0) + if (commandLine->GetNumSwitchValues(Command_truncatefingerprint.m_switch) > 0) { - precision = AZStd::stoi(commandLine->GetSwitchValue(truncateFingerprintSwitch, 0)); + precision = AZStd::stoi(commandLine->GetSwitchValue(Command_truncatefingerprint.m_switch, 0)); if(precision < 1) { @@ -246,6 +283,31 @@ void ApplicationManagerBase::InitAssetProcessorManager() AssetUtilities::SetTruncateFingerprintTimestamp(precision); } + + if (commandLine->HasSwitch(Command_help.m_switch) || commandLine->HasSwitch(Command_h.m_switch)) + { + // Other O3DE tools have a more full featured system for registering command flags + // that includes help output, but right now the AssetProcessor just checks strings + // via HasSwitch. This means this help output has to be updated manually. + AZ_TracePrintf("AssetProcessor", "Asset Processor Command Line Flags:\n"); + AZ_TracePrintf("AssetProcessor", "\t%s : %s\n", Command_waitOnLaunch.m_switch, Command_waitOnLaunch.m_helpText); + AZ_TracePrintf("AssetProcessor", "\t%s : %s\n", Command_zeroAnalysisMode.m_switch, Command_zeroAnalysisMode.m_helpText); + AZ_TracePrintf("AssetProcessor", "\t%s : %s\n", Command_enableQueryLogging.m_switch, Command_enableQueryLogging.m_helpText); + AZ_TracePrintf("AssetProcessor", "\t%s : %s\n", Command_dependencyScanPattern.m_switch, Command_dependencyScanPattern.m_helpText); + AZ_TracePrintf("AssetProcessor", "\t%s : %s\n", Command_dsp.m_switch, Command_dsp.m_helpText); + AZ_TracePrintf("AssetProcessor", "\t%s : %s\n", Command_fileDependencyScanPattern.m_switch, Command_fileDependencyScanPattern.m_helpText); + AZ_TracePrintf("AssetProcessor", "\t%s : %s\n", Command_fdsp.m_switch, Command_fdsp.m_helpText); + AZ_TracePrintf("AssetProcessor", "\t%s : %s\n", Command_additionalScanFolders.m_switch, Command_additionalScanFolders.m_helpText); + AZ_TracePrintf("AssetProcessor", "\t%s : %s\n", Command_dependencyScanMaxIteration.m_switch, Command_dependencyScanMaxIteration.m_helpText); + AZ_TracePrintf("AssetProcessor", "\t%s : %s\n", Command_warningLevel.m_switch, Command_warningLevel.m_helpText); + AZ_TracePrintf("AssetProcessor", "\t%s : %s\n", Command_acceptInput.m_switch, Command_acceptInput.m_helpText); + AZ_TracePrintf("AssetProcessor", "\t%s : %s\n", Command_debugOutput.m_switch, Command_debugOutput.m_helpText); + AZ_TracePrintf("AssetProcessor", "\t%s : %s\n", Command_sortJobsByDBSourceName.m_switch, Command_sortJobsByDBSourceName.m_helpText); + AZ_TracePrintf("AssetProcessor", "\t%s : %s\n", Command_truncatefingerprint.m_switch, Command_truncatefingerprint.m_helpText); + AZ_TracePrintf("AssetProcessor", "\t%s : %s\n", Command_help.m_switch, Command_help.m_helpText); + AZ_TracePrintf("AssetProcessor", "\t%s : %s\n", Command_h.m_switch, Command_h.m_helpText); + AZ_TracePrintf("AssetProcessor", "\tregset : set the given registry key to the given value.\n"); + } } void ApplicationManagerBase::Rescan() @@ -281,6 +343,11 @@ void ApplicationManagerBase::InitRCController() { m_rcController = new AssetProcessor::RCController(m_platformConfiguration->GetMinJobs(), m_platformConfiguration->GetMaxJobs()); + if (m_sortJobsByDBSourceName) + { + m_rcController->SetQueueSortOnDBSourceName(); + } + QObject::connect(m_assetProcessorManager, &AssetProcessor::AssetProcessorManager::AssetToProcess, m_rcController, &AssetProcessor::RCController::JobSubmitted); QObject::connect(m_rcController, &AssetProcessor::RCController::FileCompiled, m_assetProcessorManager, &AssetProcessor::AssetProcessorManager::AssetProcessed, Qt::UniqueConnection); QObject::connect(m_rcController, &AssetProcessor::RCController::FileFailed, m_assetProcessorManager, &AssetProcessor::AssetProcessorManager::AssetFailed); @@ -1807,4 +1874,3 @@ void ApplicationManagerBase::OnActiveJobsCountChanged(unsigned int count) AssetProcessor::AssetProcessorStatusEntry entry(AssetProcessor::AssetProcessorStatus::Processing_Jobs, count); Q_EMIT AssetProcessorStatusChanged(entry); } - diff --git a/Code/Tools/AssetProcessor/native/utilities/ApplicationManagerBase.h b/Code/Tools/AssetProcessor/native/utilities/ApplicationManagerBase.h index 40106c69ec..7e6347b4d1 100644 --- a/Code/Tools/AssetProcessor/native/utilities/ApplicationManagerBase.h +++ b/Code/Tools/AssetProcessor/native/utilities/ApplicationManagerBase.h @@ -236,6 +236,11 @@ protected: int m_remainingAPMJobs = 0; bool m_assetProcessorManagerIsReady = false; + // When job priority and escalation is equal, jobs sort in order by job key. + // This switches that behavior to instead sort by the DB source name, which + // allows automated tests to get deterministic behavior out of Asset Processor. + bool m_sortJobsByDBSourceName = false; + unsigned int m_highestConnId = 0; AzToolsFramework::Ticker* m_ticker = nullptr; // for ticking the tickbus. From afe5398f0ff6280f039a71e7f278e1c34a0d7644 Mon Sep 17 00:00:00 2001 From: santorac <55155825+santorac@users.noreply.github.com> Date: Mon, 2 Aug 2021 11:19:03 -0700 Subject: [PATCH 155/160] Fixed model unit tests --- Gems/Atom/RPI/Code/Tests/Model/ModelTests.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/Gems/Atom/RPI/Code/Tests/Model/ModelTests.cpp b/Gems/Atom/RPI/Code/Tests/Model/ModelTests.cpp index 625240a01f..368fb2c3c6 100644 --- a/Gems/Atom/RPI/Code/Tests/Model/ModelTests.cpp +++ b/Gems/Atom/RPI/Code/Tests/Model/ModelTests.cpp @@ -107,6 +107,18 @@ namespace UnitTest AZStd::vector m_lods; }; + void SetUp() override + { + RPITestFixture::SetUp(); + + auto assetId = AZ::Data::AssetId(AZ::Uuid::CreateRandom(), 0); + auto typeId = AZ::AzTypeInfo::Uuid(); + m_materialAsset = AZ::Data::Asset(assetId, typeId, ""); + + // Some tests attempt to serialize-in the model asset, which should not attempt to actually load this dummy asset reference. + m_materialAsset.SetAutoLoadBehavior(AZ::Data::AssetLoadBehaviorNamespace::NoLoad); + } + AZ::RHI::ShaderSemantic GetPositionSemantic() const { return AZ::RHI::ShaderSemantic(AZ::Name("POSITION")); @@ -312,9 +324,7 @@ namespace UnitTest } const uint32_t m_manyMesh = 100; // Not too much to hold up the tests but enough to stress them - AZ::Data::Asset m_materialAsset = - AZ::Data::Asset(AZ::Data::AssetId(AZ::Uuid::CreateRandom(), 0), - AZ::AzTypeInfo::Uuid(), ""); + AZ::Data::Asset m_materialAsset; }; From cc57ee7d20921b9592079fb8c8b63a26b071f748 Mon Sep 17 00:00:00 2001 From: Chris Galvan Date: Mon, 2 Aug 2021 13:19:15 -0500 Subject: [PATCH 156/160] Fixed Vegetation Layer Spawner documentation link. Signed-off-by: Chris Galvan --- Gems/Vegetation/Code/Source/Editor/EditorSpawnerComponent.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/Vegetation/Code/Source/Editor/EditorSpawnerComponent.h b/Gems/Vegetation/Code/Source/Editor/EditorSpawnerComponent.h index 709b645ea2..6563a8f8b9 100644 --- a/Gems/Vegetation/Code/Source/Editor/EditorSpawnerComponent.h +++ b/Gems/Vegetation/Code/Source/Editor/EditorSpawnerComponent.h @@ -29,6 +29,6 @@ namespace Vegetation static constexpr const char* const s_componentDescription = "Creates dynamic vegetation in a specified area"; static constexpr const char* const s_icon = "Editor/Icons/Components/Vegetation.svg"; static constexpr const char* const s_viewportIcon = "Editor/Icons/Components/Viewport/Vegetation.svg"; - static constexpr const char* const s_helpUrl = "https://o3de.org/docs/user-guide/components/reference/vegetation-layer-spawner/"; + static constexpr const char* const s_helpUrl = "https://o3de.org/docs/user-guide/components/reference/vegetation/layer-spawner/"; }; } From 24607df8f303a2bf9fc75365b16ed00438fcaff4 Mon Sep 17 00:00:00 2001 From: Chris Galvan Date: Mon, 2 Aug 2021 14:02:39 -0500 Subject: [PATCH 157/160] Added .gitignore so that Script Canvas debug logs don't get picked up as untracked files. Signed-off-by: Chris Galvan --- Gems/ScriptCanvas/.gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 Gems/ScriptCanvas/.gitignore diff --git a/Gems/ScriptCanvas/.gitignore b/Gems/ScriptCanvas/.gitignore new file mode 100644 index 0000000000..7ae9da2d7f --- /dev/null +++ b/Gems/ScriptCanvas/.gitignore @@ -0,0 +1 @@ +Assets/Logs/ \ No newline at end of file From 8542de8c3291458b11bebc158e273d067d442504 Mon Sep 17 00:00:00 2001 From: santorac <55155825+santorac@users.noreply.github.com> Date: Mon, 2 Aug 2021 12:02:58 -0700 Subject: [PATCH 158/160] Fixed a link error on android (clang) --- .../Code/Include/Atom/RPI.Reflect/Model/ModelMaterialSlot.h | 2 +- .../RPI/Code/Source/RPI.Reflect/Model/ModelMaterialSlot.cpp | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Model/ModelMaterialSlot.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Model/ModelMaterialSlot.h index 27137459b7..dd46aca6cd 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Model/ModelMaterialSlot.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Model/ModelMaterialSlot.h @@ -26,7 +26,7 @@ namespace AZ static void Reflect(AZ::ReflectContext* context); using StableId = uint32_t; - static const StableId InvalidStableId = -1; + static const StableId InvalidStableId; //! This ID must have a consistent value when the asset is reprocessed by the asset pipeline, and must be unique within the ModelLodAsset. //! In practice, this set using the MaterialUid from SceneAPI. See ModelAssetBuilderComponent::CreateMesh. diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/ModelMaterialSlot.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/ModelMaterialSlot.cpp index 61f3ebbe3a..0900949625 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/ModelMaterialSlot.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/ModelMaterialSlot.cpp @@ -13,6 +13,10 @@ namespace AZ { namespace RPI { + // Normally this would be defined in the header file and substituted by the compiler, but for + // some reason clang doesn't accept it. + const ModelMaterialSlot::StableId ModelMaterialSlot::InvalidStableId = -1; + void ModelMaterialSlot::Reflect(AZ::ReflectContext* context) { if (auto* serializeContext = azrtti_cast(context)) From ed8227f47a8def7c7cec1ba3579ac026965574ff Mon Sep 17 00:00:00 2001 From: Chris Galvan Date: Mon, 2 Aug 2021 14:32:11 -0500 Subject: [PATCH 159/160] Updated new project template .gitignore files so that temporary level saves in _savebackup files will be ignored as untracked files. Signed-off-by: Chris Galvan --- Templates/DefaultProject/Template/.gitignore | 3 ++- Templates/MinimalProject/Template/.gitignore | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Templates/DefaultProject/Template/.gitignore b/Templates/DefaultProject/Template/.gitignore index f21f551ce4..28b4b330f5 100644 --- a/Templates/DefaultProject/Template/.gitignore +++ b/Templates/DefaultProject/Template/.gitignore @@ -1,4 +1,5 @@ [Bb]uild/ [Cc]ache/ [Uu]ser/ -[Uu]ser_test*/ \ No newline at end of file +[Uu]ser_test*/ +_savebackup/ \ No newline at end of file diff --git a/Templates/MinimalProject/Template/.gitignore b/Templates/MinimalProject/Template/.gitignore index 9a6d119b1b..a3c776304c 100644 --- a/Templates/MinimalProject/Template/.gitignore +++ b/Templates/MinimalProject/Template/.gitignore @@ -1,3 +1,4 @@ [Bb]uild/ [Cc]ache/ -[Uu]ser/ \ No newline at end of file +[Uu]ser/ +_savebackup/ \ No newline at end of file From d03c2c9977338fdfb0313d093c2678ff0d9841d7 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Mon, 2 Aug 2021 13:53:13 -0700 Subject: [PATCH 160/160] Copy jinja/py files to the install folder (#2643) * Copy jinja/py files to the install folder Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> * code review comment Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> * moving AzAutoGen to cmake folder and removing the header-only project Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Framework/AzAutoGen/CMakeLists.txt | 14 -------------- Code/Framework/AzAutoGen/azautogen_files.cmake | 11 ----------- Code/Framework/CMakeLists.txt | 1 - {Code/Framework/AzAutoGen => cmake}/AzAutoGen.py | 0 cmake/LyAutoGen.cmake | 6 +++--- cmake/Platform/Common/Install_common.cmake | 16 ++++++++-------- cmake/cmake_files.cmake | 1 + 7 files changed, 12 insertions(+), 37 deletions(-) delete mode 100644 Code/Framework/AzAutoGen/CMakeLists.txt delete mode 100644 Code/Framework/AzAutoGen/azautogen_files.cmake rename {Code/Framework/AzAutoGen => cmake}/AzAutoGen.py (100%) diff --git a/Code/Framework/AzAutoGen/CMakeLists.txt b/Code/Framework/AzAutoGen/CMakeLists.txt deleted file mode 100644 index 9338520570..0000000000 --- a/Code/Framework/AzAutoGen/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -# -# Copyright (c) Contributors to the Open 3D Engine Project. -# For complete copyright and license terms please see the LICENSE at the root of this distribution. -# -# SPDX-License-Identifier: Apache-2.0 OR MIT -# -# - -ly_add_target( - NAME AzAutoGen HEADERONLY - NAMESPACE AZ - FILES_CMAKE - azautogen_files.cmake -) diff --git a/Code/Framework/AzAutoGen/azautogen_files.cmake b/Code/Framework/AzAutoGen/azautogen_files.cmake deleted file mode 100644 index 9eb4460b5c..0000000000 --- a/Code/Framework/AzAutoGen/azautogen_files.cmake +++ /dev/null @@ -1,11 +0,0 @@ -# -# Copyright (c) Contributors to the Open 3D Engine Project. -# For complete copyright and license terms please see the LICENSE at the root of this distribution. -# -# SPDX-License-Identifier: Apache-2.0 OR MIT -# -# - -set(FILES - AzAutoGen.py -) diff --git a/Code/Framework/CMakeLists.txt b/Code/Framework/CMakeLists.txt index 45ccb22b14..61f65de5a4 100644 --- a/Code/Framework/CMakeLists.txt +++ b/Code/Framework/CMakeLists.txt @@ -6,7 +6,6 @@ # # -add_subdirectory(AzAutoGen) add_subdirectory(AtomCore) add_subdirectory(AzCore) add_subdirectory(AzQtComponents) diff --git a/Code/Framework/AzAutoGen/AzAutoGen.py b/cmake/AzAutoGen.py similarity index 100% rename from Code/Framework/AzAutoGen/AzAutoGen.py rename to cmake/AzAutoGen.py diff --git a/cmake/LyAutoGen.cmake b/cmake/LyAutoGen.cmake index 64cb73a453..4aec0f9726 100644 --- a/cmake/LyAutoGen.cmake +++ b/cmake/LyAutoGen.cmake @@ -25,17 +25,17 @@ function(ly_add_autogen) list(FILTER AZCG_INPUTFILES INCLUDE REGEX ".*\.(xml|json|jinja)$") target_include_directories(${ly_add_autogen_NAME} PUBLIC "${CMAKE_CURRENT_BINARY_DIR}/Azcg/Generated") execute_process( - COMMAND ${LY_PYTHON_CMD} "${LY_ROOT_FOLDER}/Code/Framework/AzAutoGen/AzAutoGen.py" "${CMAKE_BINARY_DIR}/Azcg/TemplateCache/" "${CMAKE_CURRENT_BINARY_DIR}/Azcg/Generated/" "${CMAKE_CURRENT_SOURCE_DIR}" "${AZCG_INPUTFILES}" "${ly_add_autogen_AUTOGEN_RULES}" "-n" + COMMAND ${LY_PYTHON_CMD} "${LY_ROOT_FOLDER}/cmake/AzAutoGen.py" "${CMAKE_BINARY_DIR}/Azcg/TemplateCache/" "${CMAKE_CURRENT_BINARY_DIR}/Azcg/Generated/" "${CMAKE_CURRENT_SOURCE_DIR}" "${AZCG_INPUTFILES}" "${ly_add_autogen_AUTOGEN_RULES}" "-n" OUTPUT_VARIABLE AUTOGEN_OUTPUTS ) string(STRIP "${AUTOGEN_OUTPUTS}" AUTOGEN_OUTPUTS) set(AZCG_DEPENDENCIES ${AZCG_INPUTFILES}) - list(APPEND AZCG_DEPENDENCIES "${LY_ROOT_FOLDER}/Code/Framework/AzAutoGen/AzAutoGen.py") + list(APPEND AZCG_DEPENDENCIES "${LY_ROOT_FOLDER}/cmake/AzAutoGen.py") add_custom_command( OUTPUT ${AUTOGEN_OUTPUTS} DEPENDS ${AZCG_DEPENDENCIES} COMMAND ${CMAKE_COMMAND} -E echo "Running AutoGen for ${ly_add_autogen_NAME}" - COMMAND ${LY_PYTHON_CMD} "${LY_ROOT_FOLDER}/Code/Framework/AzAutoGen/AzAutoGen.py" "${CMAKE_BINARY_DIR}/Azcg/TemplateCache/" "${CMAKE_CURRENT_BINARY_DIR}/Azcg/Generated/" "${CMAKE_CURRENT_SOURCE_DIR}" "${AZCG_INPUTFILES}" "${ly_add_autogen_AUTOGEN_RULES}" + COMMAND ${LY_PYTHON_CMD} "${LY_ROOT_FOLDER}/cmake/AzAutoGen.py" "${CMAKE_BINARY_DIR}/Azcg/TemplateCache/" "${CMAKE_CURRENT_BINARY_DIR}/Azcg/Generated/" "${CMAKE_CURRENT_SOURCE_DIR}" "${AZCG_INPUTFILES}" "${ly_add_autogen_AUTOGEN_RULES}" VERBATIM ) set_target_properties(${ly_add_autogen_NAME} PROPERTIES AUTOGEN_INPUT_FILES "${AZCG_INPUTFILES}") diff --git a/cmake/Platform/Common/Install_common.cmake b/cmake/Platform/Common/Install_common.cmake index 612358f938..353c015fd3 100644 --- a/cmake/Platform/Common/Install_common.cmake +++ b/cmake/Platform/Common/Install_common.cmake @@ -45,7 +45,6 @@ function(ly_setup_target OUTPUT_CONFIGURED_TARGET ALIAS_TARGET_NAME absolute_tar # we need to set the PUBLIC_HEADER property of the target for all the headers we are exporting. After doing that, installing the # headers end up in one folder instead of duplicating the folder structure of the public/interface include directory. # Instead, we install them with install(DIRECTORY) - set(include_location "include") get_target_property(include_directories ${TARGET_NAME} INTERFACE_INCLUDE_DIRECTORIES) if (include_directories) unset(public_headers) @@ -63,9 +62,10 @@ function(ly_setup_target OUTPUT_CONFIGURED_TARGET ALIAS_TARGET_NAME absolute_tar continue() endif() + unset(rel_include_dir) cmake_path(RELATIVE_PATH include_directory BASE_DIRECTORY ${LY_ROOT_FOLDER} OUTPUT_VARIABLE rel_include_dir) - cmake_path(APPEND include_location "${rel_include_dir}" ".." OUTPUT_VARIABLE destination_dir) - cmake_path(NORMAL_PATH destination_dir) + cmake_path(APPEND rel_include_dir "..") + cmake_path(NORMAL_PATH rel_include_dir OUTPUT_VARIABLE destination_dir) install(DIRECTORY ${include_directory} DESTINATION ${destination_dir} @@ -75,6 +75,7 @@ function(ly_setup_target OUTPUT_CONFIGURED_TARGET ALIAS_TARGET_NAME absolute_tar PATTERN *.hpp PATTERN *.inl PATTERN *.hxx + PATTERN *.jinja # LyAutoGen files ) endif() endforeach() @@ -156,10 +157,9 @@ function(ly_setup_target OUTPUT_CONFIGURED_TARGET ALIAS_TARGET_NAME absolute_tar foreach(include ${include_directories}) string(GENEX_STRIP ${include} include_genex_expr) if(include_genex_expr STREQUAL include) # only for cases where there are no generation expressions - cmake_path(RELATIVE_PATH include BASE_DIRECTORY ${LY_ROOT_FOLDER} OUTPUT_VARIABLE target_include) - cmake_path(NORMAL_PATH target_include) - # Escape the LY_ROOT_FOLDER variable so that it isn't resolved during the install step - string(APPEND INCLUDE_DIRECTORIES_PLACEHOLDER "\${LY_ROOT_FOLDER}/${include_location}/${target_include}\n") + # Make the include path relative to the source dir where the target will be declared + cmake_path(RELATIVE_PATH include BASE_DIRECTORY ${absolute_target_source_dir} OUTPUT_VARIABLE target_include) + string(APPEND INCLUDE_DIRECTORIES_PLACEHOLDER "${target_include}\n") endif() endforeach() endif() @@ -204,7 +204,7 @@ function(ly_setup_target OUTPUT_CONFIGURED_TARGET ALIAS_TARGET_NAME absolute_tar set(TARGET_RUN_HELPER "add_custom_target(${RUN_TARGET_NAME}) set_target_properties(${RUN_TARGET_NAME} PROPERTIES - FOLDER \"CMakePredefinedTargets/SDK\" + FOLDER \"O3DE_SDK\" VS_DEBUGGER_COMMAND \$> VS_DEBUGGER_COMMAND_ARGUMENTS \"--project-path=\${LY_DEFAULT_PROJECT_PATH}\" )" diff --git a/cmake/cmake_files.cmake b/cmake/cmake_files.cmake index 490817d625..aa275b634a 100644 --- a/cmake/cmake_files.cmake +++ b/cmake/cmake_files.cmake @@ -9,6 +9,7 @@ set(FILES 3rdParty.cmake 3rdPartyPackages.cmake + AzAutoGen.py CMakeFiles.cmake CommandExecution.cmake Configurations.cmake