Merge branch 'development' into profiler_capture_api
Signed-off-by: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com>
This commit is contained in:
@@ -9,7 +9,7 @@
|
||||
#import <AppKit/NSEvent.h>
|
||||
|
||||
#include "EditorDefs.h"
|
||||
#include "QtEditorApplication.h"
|
||||
#include "QtEditorApplication_mac.h"
|
||||
|
||||
// AzFramework
|
||||
#include <AzFramework/Input/Buses/Notifications/RawInputNotificationBus_Platform.h>
|
||||
|
||||
@@ -1788,6 +1788,11 @@ AZStd::string SandboxIntegrationManager::GetComponentEditorIcon(const AZ::Uuid&
|
||||
return iconPath;
|
||||
}
|
||||
|
||||
AZStd::string SandboxIntegrationManager::GetComponentTypeEditorIcon(const AZ::Uuid& componentType)
|
||||
{
|
||||
return GetComponentEditorIcon(componentType, nullptr);
|
||||
}
|
||||
|
||||
AZStd::string SandboxIntegrationManager::GetComponentIconPath(const AZ::Uuid& componentType,
|
||||
AZ::Crc32 componentIconAttrib, AZ::Component* component)
|
||||
{
|
||||
|
||||
@@ -233,6 +233,7 @@ private:
|
||||
}
|
||||
|
||||
AZStd::string GetComponentEditorIcon(const AZ::Uuid& componentType, AZ::Component* component) override;
|
||||
AZStd::string GetComponentTypeEditorIcon(const AZ::Uuid& componentType) override;
|
||||
AZStd::string GetComponentIconPath(const AZ::Uuid& componentType, AZ::Crc32 componentIconAttrib, AZ::Component* component) override;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
+1
-1
@@ -139,7 +139,7 @@ ComponentDataModel::ComponentDataModel(QObject* parent)
|
||||
if (element.m_elementId == AZ::Edit::ClassElements::EditorData)
|
||||
{
|
||||
AZStd::string iconPath;
|
||||
EBUS_EVENT_RESULT(iconPath, AzToolsFramework::EditorRequests::Bus, GetComponentEditorIcon, classData->m_typeId, nullptr);
|
||||
AzToolsFramework::EditorRequestBus::BroadcastResult(iconPath, &AzToolsFramework::EditorRequests::GetComponentTypeEditorIcon, classData->m_typeId);
|
||||
if (!iconPath.empty())
|
||||
{
|
||||
m_componentIcons[classData->m_typeId] = QIcon(iconPath.c_str());
|
||||
|
||||
@@ -408,7 +408,7 @@ CTrackViewNodesCtrl::CTrackViewNodesCtrl(QWidget* hParentWnd, CTrackViewDialog*
|
||||
serializeContext->EnumerateDerived<AZ::Component>([this](const AZ::SerializeContext::ClassData* classData, const AZ::Uuid&) -> bool
|
||||
{
|
||||
AZStd::string iconPath;
|
||||
EBUS_EVENT_RESULT(iconPath, AzToolsFramework::EditorRequests::Bus, GetComponentEditorIcon, classData->m_typeId, nullptr);
|
||||
AzToolsFramework::EditorRequestBus::BroadcastResult(iconPath, &AzToolsFramework::EditorRequests::GetComponentTypeEditorIcon, classData->m_typeId);
|
||||
if (!iconPath.empty())
|
||||
{
|
||||
m_componentTypeToIconMap[classData->m_typeId] = QIcon(iconPath.c_str());
|
||||
|
||||
@@ -215,11 +215,6 @@ namespace AZ
|
||||
m_oldProjectPath = newProjectPath;
|
||||
|
||||
// Merge the project.json file into settings registry under ProjectSettingsRootKey path.
|
||||
AZ::IO::FixedMaxPath projectMetadataFile{ AZ::SettingsRegistryMergeUtils::FindEngineRoot(m_registry) / newProjectPath };
|
||||
projectMetadataFile /= "project.json";
|
||||
m_registry.MergeSettingsFile(projectMetadataFile.Native(),
|
||||
AZ::SettingsRegistryInterface::Format::JsonMergePatch, AZ::SettingsRegistryMergeUtils::ProjectSettingsRootKey);
|
||||
|
||||
// Update all the runtime file paths based on the new "project_path" value.
|
||||
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddRuntimeFilePaths(m_registry);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,239 @@
|
||||
/*
|
||||
* 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 <AzCore/DOM/DomVisitor.h>
|
||||
|
||||
namespace AZ::DOM
|
||||
{
|
||||
const char* VisitorError::CodeToString(VisitorErrorCode code)
|
||||
{
|
||||
switch (code)
|
||||
{
|
||||
case VisitorErrorCode::UnsupportedOperation:
|
||||
return "operation not supported";
|
||||
case VisitorErrorCode::InvalidData:
|
||||
return "invalid data specified";
|
||||
case VisitorErrorCode::InternalError:
|
||||
return "internal error";
|
||||
default:
|
||||
return "unknown error";
|
||||
}
|
||||
}
|
||||
|
||||
VisitorError::VisitorError(VisitorErrorCode code)
|
||||
: m_code(code)
|
||||
{
|
||||
}
|
||||
|
||||
VisitorError::VisitorError(VisitorErrorCode code, AZStd::string additionalInfo)
|
||||
: m_code(code)
|
||||
, m_additionalInfo(AZStd::move(additionalInfo))
|
||||
{
|
||||
}
|
||||
|
||||
VisitorErrorCode VisitorError::GetCode() const
|
||||
{
|
||||
return m_code;
|
||||
}
|
||||
|
||||
const AZStd::string& VisitorError::GetAdditionalInfo() const
|
||||
{
|
||||
return m_additionalInfo;
|
||||
}
|
||||
|
||||
AZStd::string VisitorError::FormatVisitorErrorMessage() const
|
||||
{
|
||||
if (m_additionalInfo.empty())
|
||||
{
|
||||
return AZStd::string::format("VisitorError: %s.", CodeToString(m_code));
|
||||
}
|
||||
return AZStd::string::format("VisitorError: %s. %s.", CodeToString(m_code), m_additionalInfo.c_str());
|
||||
}
|
||||
|
||||
Visitor::Result Visitor::VisitorFailure(VisitorErrorCode code)
|
||||
{
|
||||
return AZ::Failure(VisitorError(code));
|
||||
}
|
||||
|
||||
Visitor::Result Visitor::VisitorFailure(VisitorErrorCode code, AZStd::string additionalInfo)
|
||||
{
|
||||
return AZ::Failure(VisitorError(code, AZStd::move(additionalInfo)));
|
||||
}
|
||||
|
||||
Visitor::Result Visitor::VisitorFailure(VisitorError error)
|
||||
{
|
||||
return AZ::Failure(error);
|
||||
}
|
||||
|
||||
Visitor::Result Visitor::VisitorSuccess()
|
||||
{
|
||||
return AZ::Success();
|
||||
}
|
||||
|
||||
Visitor::Result Visitor::Null()
|
||||
{
|
||||
return VisitorSuccess();
|
||||
}
|
||||
|
||||
Visitor::Result Visitor::Bool([[maybe_unused]] bool value)
|
||||
{
|
||||
return VisitorSuccess();
|
||||
}
|
||||
|
||||
Visitor::Result Visitor::Int64([[maybe_unused]] AZ::s64 value)
|
||||
{
|
||||
return VisitorSuccess();
|
||||
}
|
||||
|
||||
Visitor::Result Visitor::Uint64([[maybe_unused]] AZ::u64 value)
|
||||
{
|
||||
return VisitorSuccess();
|
||||
}
|
||||
|
||||
Visitor::Result Visitor::Double([[maybe_unused]] double value)
|
||||
{
|
||||
return VisitorSuccess();
|
||||
}
|
||||
|
||||
Visitor::Result Visitor::String([[maybe_unused]] AZStd::string_view value, [[maybe_unused]] Lifetime lifetime)
|
||||
{
|
||||
return VisitorSuccess();
|
||||
}
|
||||
|
||||
Visitor::Result Visitor::OpaqueValue([[maybe_unused]] const OpaqueType& value, [[maybe_unused]] Lifetime lifetime)
|
||||
{
|
||||
if (!SupportsOpaqueValues())
|
||||
{
|
||||
return VisitorFailure(VisitorErrorCode::UnsupportedOperation, "Opaque values are not supported by this visitor");
|
||||
}
|
||||
return VisitorSuccess();
|
||||
}
|
||||
|
||||
Visitor::Result Visitor::RawValue([[maybe_unused]] AZStd::string_view value, [[maybe_unused]] Lifetime lifetime)
|
||||
{
|
||||
if (!SupportsRawValues())
|
||||
{
|
||||
return VisitorFailure(VisitorErrorCode::UnsupportedOperation, "Raw values are not supported by this visitor");
|
||||
}
|
||||
return VisitorSuccess();
|
||||
}
|
||||
|
||||
Visitor::Result Visitor::StartObject()
|
||||
{
|
||||
if (!SupportsObjects())
|
||||
{
|
||||
return VisitorFailure(VisitorErrorCode::UnsupportedOperation, "Objects are not supported by this visitor");
|
||||
}
|
||||
return VisitorSuccess();
|
||||
}
|
||||
|
||||
Visitor::Result Visitor::EndObject([[maybe_unused]] AZ::u64 attributeCount)
|
||||
{
|
||||
if (!SupportsObjects())
|
||||
{
|
||||
return VisitorFailure(VisitorErrorCode::UnsupportedOperation, "Objects are not supported by this visitor");
|
||||
}
|
||||
return VisitorSuccess();
|
||||
}
|
||||
|
||||
Visitor::Result Visitor::Key([[maybe_unused]] AZ::Name key)
|
||||
{
|
||||
if (!SupportsObjects() && !SupportsNodes())
|
||||
{
|
||||
return VisitorFailure(VisitorErrorCode::UnsupportedOperation, "Keys are not supported by this visitor");
|
||||
}
|
||||
return VisitorSuccess();
|
||||
}
|
||||
|
||||
Visitor::Result Visitor::RawKey(AZStd::string_view key, [[maybe_unused]] Lifetime lifetime)
|
||||
{
|
||||
if (!SupportsRawKeys())
|
||||
{
|
||||
return VisitorFailure(VisitorErrorCode::UnsupportedOperation, "Raw keys are not supported by this visitor");
|
||||
}
|
||||
return Key(AZ::Name(key));
|
||||
}
|
||||
|
||||
Visitor::Result Visitor::StartArray()
|
||||
{
|
||||
if (!SupportsArrays())
|
||||
{
|
||||
return VisitorFailure(VisitorErrorCode::UnsupportedOperation, "Arrays are not supported by this visitor");
|
||||
}
|
||||
return VisitorSuccess();
|
||||
}
|
||||
|
||||
Visitor::Result Visitor::EndArray([[maybe_unused]] AZ::u64 elementCount)
|
||||
{
|
||||
if (!SupportsArrays())
|
||||
{
|
||||
return VisitorFailure(VisitorErrorCode::UnsupportedOperation, "Arrays are not supported by this visitor");
|
||||
}
|
||||
return VisitorSuccess();
|
||||
}
|
||||
|
||||
Visitor::Result Visitor::StartNode([[maybe_unused]] AZ::Name name)
|
||||
{
|
||||
if (!SupportsNodes())
|
||||
{
|
||||
return VisitorFailure(VisitorErrorCode::UnsupportedOperation, "Nodes are not supported by this visitor");
|
||||
}
|
||||
return VisitorSuccess();
|
||||
}
|
||||
|
||||
Visitor::Result Visitor::RawStartNode(AZStd::string_view name, [[maybe_unused]] Lifetime lifetime)
|
||||
{
|
||||
return StartNode(AZ::Name(name));
|
||||
}
|
||||
|
||||
Visitor::Result Visitor::EndNode([[maybe_unused]] AZ::u64 attributeCount, [[maybe_unused]] AZ::u64 elementCount)
|
||||
{
|
||||
if (!SupportsNodes())
|
||||
{
|
||||
return VisitorFailure(VisitorErrorCode::UnsupportedOperation, "Nodes are not supported by this visitor");
|
||||
}
|
||||
return VisitorSuccess();
|
||||
}
|
||||
|
||||
VisitorFlags Visitor::GetVisitorFlags() const
|
||||
{
|
||||
// By default support raw keys (promoting them to AZ::Name) and support Array / Object / Node
|
||||
// We leave Opaque type support and Raw Values to more specialized, implementation-specific cases
|
||||
return VisitorFlags::SupportsRawKeys | VisitorFlags::SupportsArrays | VisitorFlags::SupportsObjects | VisitorFlags::SupportsNodes;
|
||||
}
|
||||
|
||||
bool Visitor::SupportsRawValues() const
|
||||
{
|
||||
return (GetVisitorFlags() & VisitorFlags::SupportsRawValues) != VisitorFlags::Null;
|
||||
}
|
||||
|
||||
bool Visitor::SupportsRawKeys() const
|
||||
{
|
||||
return (GetVisitorFlags() & VisitorFlags::SupportsRawKeys) != VisitorFlags::Null;
|
||||
}
|
||||
|
||||
bool Visitor::SupportsObjects() const
|
||||
{
|
||||
return (GetVisitorFlags() & VisitorFlags::SupportsObjects) != VisitorFlags::Null;
|
||||
}
|
||||
|
||||
bool Visitor::SupportsArrays() const
|
||||
{
|
||||
return (GetVisitorFlags() & VisitorFlags::SupportsArrays) != VisitorFlags::Null;
|
||||
}
|
||||
|
||||
bool Visitor::SupportsNodes() const
|
||||
{
|
||||
return (GetVisitorFlags() & VisitorFlags::SupportsNodes) != VisitorFlags::Null;
|
||||
}
|
||||
|
||||
bool Visitor::SupportsOpaqueValues() const
|
||||
{
|
||||
return (GetVisitorFlags() & VisitorFlags::SupportsOpaqueValues) != VisitorFlags::Null;
|
||||
}
|
||||
} // namespace AZ::DOM
|
||||
@@ -0,0 +1,237 @@
|
||||
/*
|
||||
* 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 <AzCore/Name/Name.h>
|
||||
#include <AzCore/Outcome/Outcome.h>
|
||||
#include <AzCore/std/any.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
|
||||
namespace AZ::DOM
|
||||
{
|
||||
//
|
||||
// Lifetime enum
|
||||
//
|
||||
//! Specifies the period in which a reference value will still be alive and safe to read.
|
||||
enum class Lifetime
|
||||
{
|
||||
//! Specifies that the value is safe to read and will remain so indefinitely.
|
||||
//! This implies that the value will not be mutated for the duration of this storage.
|
||||
Persistent,
|
||||
//! Specifies that the value may change or be deallocated, and must be copied to be safely stored.
|
||||
Temporary,
|
||||
};
|
||||
|
||||
//
|
||||
// VisitorErrorCode enum
|
||||
//
|
||||
//! Error code specifying the reason a Visitor operation failed.
|
||||
enum class VisitorErrorCode
|
||||
{
|
||||
//! Set when a Visitor doesn't have an implementation for a given attribute type.
|
||||
//! A pure-JSON serializer might reject a Node attribute, for example, and serialization visitors
|
||||
//! can forbid non-serializable Opaque types.
|
||||
UnsupportedOperation,
|
||||
//! Set when a Visitor has received malformed or invalid data.
|
||||
//! Potential sources include mismatching Begin/End call pairs or invalid attribute or element counts
|
||||
//! being sent to End methods.
|
||||
InvalidData,
|
||||
//! The Visitor failed for some other reason not caused by invalid input.
|
||||
//! If returning a custom error with this code, it's preferrable to also provide supplemental info
|
||||
//! in the form of an explanatory string.
|
||||
InternalError
|
||||
};
|
||||
|
||||
//
|
||||
// VisitorError class
|
||||
//
|
||||
//! Details of the reason for failure within a VisitorInterface operation.
|
||||
class VisitorError final
|
||||
{
|
||||
public:
|
||||
explicit VisitorError(VisitorErrorCode code);
|
||||
VisitorError(VisitorErrorCode code, AZStd::string additionalInfo);
|
||||
|
||||
//! Gets the error code associated with this error.
|
||||
VisitorErrorCode GetCode() const;
|
||||
//! Gets a supplemental error info string from the error.
|
||||
//! Returns an empty string if no additional information was provided to the error.
|
||||
const AZStd::string& GetAdditionalInfo() const;
|
||||
//! Provides a formatted, human-readable error description that can be used for logging purposes.
|
||||
AZStd::string FormatVisitorErrorMessage() const;
|
||||
|
||||
//! Helper method, translates a VisitorErrorCode to a human readable string.
|
||||
static const char* CodeToString(VisitorErrorCode code);
|
||||
|
||||
private:
|
||||
VisitorErrorCode m_code;
|
||||
AZStd::string m_additionalInfo;
|
||||
};
|
||||
|
||||
//! A type alias for opaque DOM types that aren't meant to be serializable.
|
||||
//! /see VisitorInterface::OpaqueValue
|
||||
using OpaqueType = AZStd::any;
|
||||
|
||||
//
|
||||
// VisitorFlags enum
|
||||
//
|
||||
//! Flags representning capabilities of a \ref Visitor.
|
||||
enum class VisitorFlags : AZ::u16
|
||||
{
|
||||
//! No flags are set. This can be used in conjunction with bitwise operators to check a flag.
|
||||
Null = 0,
|
||||
//! If set, this Visitor interface supports raw strings in place of specific value types.
|
||||
//! Visitors with this flag accept RawValue calls in lieu of more specific value calls such as Int64 or String.
|
||||
SupportsRawValues = (1 << 1),
|
||||
//! If set, this Visitor interface supports raw strings in place of Name types for keys and Node names.
|
||||
//! Visitors with this flag accept RawKey and RawStartNode in lieu of Key and StartNode calls.
|
||||
SupportsRawKeys = (1 << 2),
|
||||
//! If set, this Visitor interface supports Object types described via BeginObject and EndObject.
|
||||
SupportsObjects = (1 << 3),
|
||||
//! If set, this Visitor interface supports Array types described via BeginArray and EndArray.
|
||||
SupportsArrays = (1 << 4),
|
||||
//! If set, this Visitor interface supports Node types described BeginNode and EndNode.
|
||||
SupportsNodes = (1 << 4),
|
||||
//! If set, this Visitor interface supports opaque values described via OpaqueValue.
|
||||
SupportsOpaqueValues = (1 << 5),
|
||||
};
|
||||
|
||||
AZ_DEFINE_ENUM_BITWISE_OPERATORS(VisitorFlags);
|
||||
|
||||
//
|
||||
// Visitor class
|
||||
//
|
||||
//! An interface for performing operations on elements of a generic DOM (Document Object Model).
|
||||
//! A Document Object Model is defined here as a tree structure comprised of one of the following values:
|
||||
//! - Primitives: plain data types, including
|
||||
//! - \ref Int64: 64 bit signed integer
|
||||
//! - \ref Uint64: 64 bit unsigned integer
|
||||
//! - \ref Bool: boolean value
|
||||
//! - \ref Double: 64 bit double precision float
|
||||
//! - \ref Null: sentinel "empty" type with no value representation
|
||||
//! - \ref String: UTF8 encoded string
|
||||
//! - \ref Object: an ordered container of key/value pairs where keys are AZ::Names and values may be any DOM type
|
||||
//! (including Object)
|
||||
//! - \ref Array: an ordered container of values, in which values are any DOM value type (including Array)
|
||||
//! - \ref Node: a container
|
||||
//! - \ref OpaqueValue: An arbitrary value stored in an AZStd::any. This is a non-serializable representation of an
|
||||
//! entry useful for in-memory options. This is intended to be used as an intermediate value over the course of DOM
|
||||
//! transformation and as a proxy to pass through types of which the DOM has no knowledge to other systems.
|
||||
//!
|
||||
//! Opaque values are rejected by the default VisitorInterface implementation.
|
||||
//!
|
||||
//! Care should be ensured that DOMs representing opaque types are only visited by consumers that understand them.
|
||||
class Visitor
|
||||
{
|
||||
public:
|
||||
virtual ~Visitor() = default;
|
||||
|
||||
//! The result of a Visitor operation.
|
||||
//! A failure indicates a non-recoverable issue and signals that no further visit calls may be made in the
|
||||
//! current state.
|
||||
using Result = AZ::Outcome<void, VisitorError>;
|
||||
|
||||
//! Returns a set of flags representing the operations this Visitor supports.
|
||||
//! The base implementation supports raw keys (\see VisitorFlags::SupportsRawKeys) and
|
||||
//! arrays (\see VisitorFlags::SupportsArrays), objects (\see VisitorFlags::SupportsObjects), and
|
||||
//! nodes (\see VisitorFlags::SupportsNodes).
|
||||
//! Raw (\see VisitorFlags::SupportsRawValues) and opaque values (\see VisitorFlags::SupportsOpaqueValues)
|
||||
//! are disallowed by default, as their handling is intended to be implementation-specific.
|
||||
virtual VisitorFlags GetVisitorFlags() const;
|
||||
//! /see VisitorFlags::SupportsRawValues
|
||||
bool SupportsRawValues() const;
|
||||
//! /see VisitorFlags::SupportsRawKeys
|
||||
bool SupportsRawKeys() const;
|
||||
//! /see VisitorFlags::SupportsObjects
|
||||
bool SupportsObjects() const;
|
||||
//! /see VisitorFlags::SupportsArrays
|
||||
bool SupportsArrays() const;
|
||||
//! /see VisitorFlags::SupportsNodes
|
||||
bool SupportsNodes() const;
|
||||
//! /see VisitorFlags::SupportsOpaqueValues
|
||||
bool SupportsOpaqueValues() const;
|
||||
|
||||
//! Operates on an empty null value.
|
||||
virtual Result Null();
|
||||
//! Operates on a bool value.
|
||||
virtual Result Bool(bool value);
|
||||
//! Operates on a signed, 64 bit integer value.
|
||||
virtual Result Int64(AZ::s64 value);
|
||||
//! Operates on an unsigned, 64 bit integer value.
|
||||
virtual Result Uint64(AZ::u64 value);
|
||||
//! Operates on a double precision, 64 bit floating point value.
|
||||
virtual Result Double(double value);
|
||||
//! Operates on a string value. As strings are a reference type.
|
||||
//! Storage semantics are provided to indicate where the value may be stored persistently or requires a copy.
|
||||
virtual Result String(AZStd::string_view value, Lifetime lifetime);
|
||||
//! Operates on an opaque value. As opaque values are a reference type, storage semantics are provided to
|
||||
//! indicate where the value may be stored persistently or requires a copy.
|
||||
//! The base implementation of OpaqueValue rejects the operation, as opaque values are meant for special
|
||||
//! cases with specific implementations, not generic usage.
|
||||
//! Storage semantics are provided to indicate where the value may be stored persistently or requires a copy.
|
||||
virtual Result OpaqueValue(const OpaqueType& value, Lifetime lifetime);
|
||||
//! Operates on a raw value encoded as a UTF-8 string that hasn't had its type deduced.
|
||||
//! Visitors that support raw values (\see VisitorFlags::SupportsRawValues) may parse the raw value and
|
||||
//! forward it to the corresponding value call or calls of their choice.
|
||||
//! The base implementation of RawValue rejects the operation, as raw values are meant to be handled on
|
||||
//! a per-implementation basis.
|
||||
virtual Result RawValue(AZStd::string_view value, Lifetime lifetime);
|
||||
|
||||
//! Operates on an Object.
|
||||
//! Callers may make any number of Key calls, followed by calls representing a value (including a nested
|
||||
//! StartObject call) and then must call EndObject.
|
||||
virtual Result StartObject();
|
||||
//! Finishes operating on an Object.
|
||||
//! Callers must provide the number of attributes that were provided to the object, i.e. the number of key
|
||||
//! and value calls made within the direct context of this object (but not any nested objects / nodes).
|
||||
virtual Result EndObject(AZ::u64 attributeCount);
|
||||
|
||||
//! Specifies a key for a key/value pair.
|
||||
//! Key must be called subsequent to a call to \ref StartObject or \ref StartNode and immediately followed by
|
||||
//! calls representing the key's associated value.
|
||||
virtual Result Key(AZ::Name key);
|
||||
//! Specifies a key for a key/value pair using a raw string instead of \ref AZ::Name.
|
||||
//! \see Key
|
||||
virtual Result RawKey(AZStd::string_view key, Lifetime lifetime);
|
||||
|
||||
//! Operates on an Array.
|
||||
//! Callers may make any number of subsequent value calls to represent the elements of the array, and then must
|
||||
//! call EndArray.
|
||||
virtual Result StartArray();
|
||||
//! Finishes operating on an Array.
|
||||
//! Callers must provide the number of elements that were provided to the array, i.e. the number of value calls
|
||||
//! made within the direct context of this array (but not any nested arrays / nodes).
|
||||
virtual Result EndArray(AZ::u64 elementCount);
|
||||
|
||||
//! Operates on a Node.
|
||||
//! Callers may make any number of Key calls followed by value calls or value calls not prefixed with a Key
|
||||
//! call, and then must call EndNode. See \ref StartObject and \ref StartArray as Node types combine the
|
||||
//! functionality of both structures into a named Node structure.
|
||||
virtual Result StartNode(AZ::Name name);
|
||||
//! Operates on a Node using a raw string instead of \ref AZ::Name.
|
||||
//! \see StartNode
|
||||
virtual Result RawStartNode(AZStd::string_view name, Lifetime lifetime);
|
||||
//! Finishes operating on a Node.
|
||||
//! Callers must provide both the number of attributes the were provided and the number of elements that were
|
||||
//! provided to the node, attributes being values prefaced by a call to Key.
|
||||
virtual Result EndNode(AZ::u64 attributeCount, AZ::u64 elementCount);
|
||||
|
||||
protected:
|
||||
Visitor() = default;
|
||||
|
||||
//! Helper method, constructs a failure \ref Result with the specified code.
|
||||
static Result VisitorFailure(VisitorErrorCode code);
|
||||
//! Helper method, constructs a failure \ref Result with the specified code and supplemental info.
|
||||
static Result VisitorFailure(VisitorErrorCode code, AZStd::string additionalInfo);
|
||||
//! Helper method, constructs a failure \ref Result with the specified error.
|
||||
static Result VisitorFailure(VisitorError error);
|
||||
//! Helper method, constructs a success \ref Result.
|
||||
static Result VisitorSuccess();
|
||||
};
|
||||
} // namespace AZ::DOM
|
||||
@@ -634,12 +634,18 @@ namespace AZ::SettingsRegistryMergeUtils
|
||||
}
|
||||
|
||||
// Project name - if it was set via merging project.json use that value, otherwise use the project path's folder name.
|
||||
auto projectNameKey =
|
||||
AZ::SettingsRegistryInterface::FixedValueString(AZ::SettingsRegistryMergeUtils::ProjectSettingsRootKey)
|
||||
constexpr auto projectNameKey =
|
||||
FixedValueString(AZ::SettingsRegistryMergeUtils::ProjectSettingsRootKey)
|
||||
+ "/project_name";
|
||||
|
||||
AZ::SettingsRegistryInterface::FixedValueString projectName;
|
||||
if (!registry.Get(projectName, projectNameKey))
|
||||
// Read the project name from the project.json file if it exists
|
||||
if (AZ::IO::FixedMaxPath projectJsonPath = normalizedProjectPath / "project.json";
|
||||
AZ::IO::SystemFile::Exists(projectJsonPath.c_str()))
|
||||
{
|
||||
registry.MergeSettingsFile(projectJsonPath.Native(),
|
||||
AZ::SettingsRegistryInterface::Format::JsonMergePatch, AZ::SettingsRegistryMergeUtils::ProjectSettingsRootKey);
|
||||
}
|
||||
if (FixedValueString projectName; !registry.Get(projectName, projectNameKey))
|
||||
{
|
||||
projectName = path.Filename().Native();
|
||||
registry.Set(projectNameKey, projectName);
|
||||
|
||||
@@ -125,6 +125,8 @@ set(FILES
|
||||
Debug/TraceMessagesDrillerBus.h
|
||||
Debug/TraceReflection.cpp
|
||||
Debug/TraceReflection.h
|
||||
DOM/DomVisitor.cpp
|
||||
DOM/DomVisitor.h
|
||||
Driller/DefaultStringPool.h
|
||||
Driller/Driller.cpp
|
||||
Driller/Driller.h
|
||||
|
||||
@@ -258,10 +258,17 @@ namespace AzFramework
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void XcbNativeWindow::SetWindowTitle(const AZStd::string& title)
|
||||
{
|
||||
// Set the title of both the window and the task bar by using
|
||||
// a buffer to hold the title twice, separated by a null-terminator
|
||||
auto doubleTitleSize = (title.size() + 1) * 2;
|
||||
AZStd::string doubleTitle(doubleTitleSize, '\0');
|
||||
azstrncpy(doubleTitle.data(), doubleTitleSize, title.c_str(), title.size());
|
||||
azstrncpy(&doubleTitle.data()[title.size() + 1], title.size(), title.c_str(), title.size());
|
||||
|
||||
xcb_void_cookie_t xcbCheckResult;
|
||||
xcbCheckResult = xcb_change_property(
|
||||
m_xcbConnection, XCB_PROP_MODE_REPLACE, m_xcbWindow, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8, static_cast<uint32_t>(title.size()),
|
||||
title.c_str());
|
||||
m_xcbConnection, XCB_PROP_MODE_REPLACE, m_xcbWindow, XCB_ATOM_WM_CLASS, XCB_ATOM_STRING, 8, static_cast<uint32_t>(doubleTitle.size()),
|
||||
doubleTitle.c_str());
|
||||
AZ_Assert(ValidateXcbResult(xcbCheckResult), "Failed to set window title.");
|
||||
}
|
||||
|
||||
|
||||
@@ -82,7 +82,7 @@ namespace AzGameFramework
|
||||
|
||||
// Used the lowercase the platform name since the bootstrap.game.<config>.<platform>.setreg is being loaded
|
||||
// from the asset cache root where all the files are in lowercased from regardless of the filesystem case-sensitivity
|
||||
static constexpr char filename[] = "bootstrap.game." AZ_BUILD_CONFIGURATION_TYPE "." AZ_TRAIT_OS_PLATFORM_CODENAME_LOWER ".setreg";
|
||||
static constexpr char filename[] = "bootstrap.game." AZ_BUILD_CONFIGURATION_TYPE ".setreg";
|
||||
|
||||
AZ::IO::FixedMaxPath cacheRootPath;
|
||||
if (registry.Get(cacheRootPath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_CacheRootFolder))
|
||||
|
||||
@@ -22,6 +22,7 @@ namespace AzQtComponents
|
||||
, m_closeOnClick(true)
|
||||
, m_ui(new Ui::ToastNotification())
|
||||
, m_fadeAnimation(nullptr)
|
||||
, m_configuration(toastConfiguration)
|
||||
{
|
||||
setProperty("HasNoWindowDecorations", true);
|
||||
|
||||
@@ -80,7 +81,13 @@ namespace AzQtComponents
|
||||
}
|
||||
|
||||
ToastNotification::~ToastNotification()
|
||||
{
|
||||
{
|
||||
}
|
||||
|
||||
bool ToastNotification::IsDuplicate(const ToastConfiguration& toastConfiguration)
|
||||
{
|
||||
return toastConfiguration.m_title == m_configuration.m_title
|
||||
&& toastConfiguration.m_description == m_configuration.m_description;
|
||||
}
|
||||
|
||||
void ToastNotification::paintEvent(QPaintEvent* event)
|
||||
|
||||
@@ -45,6 +45,8 @@ namespace AzQtComponents
|
||||
void ShowToastAtPoint(const QPoint& screenPosition, const QPointF& anchorPoint);
|
||||
|
||||
void UpdatePosition(const QPoint& screenPosition, const QPointF& anchorPoint);
|
||||
|
||||
bool IsDuplicate(const ToastConfiguration& toastConfiguration);
|
||||
|
||||
// QDialog
|
||||
void showEvent(QShowEvent* showEvent) override;
|
||||
@@ -64,7 +66,7 @@ namespace AzQtComponents
|
||||
|
||||
private:
|
||||
QPropertyAnimation* m_fadeAnimation;
|
||||
|
||||
ToastConfiguration m_configuration;
|
||||
bool m_closeOnClick;
|
||||
QTimer m_lifeSpan;
|
||||
uint32_t m_borderRadius = 0;
|
||||
|
||||
@@ -826,6 +826,10 @@ namespace AzToolsFramework
|
||||
/// Path will be empty if component should have no icon.
|
||||
virtual AZStd::string GetComponentEditorIcon(const AZ::Uuid& /*componentType*/, AZ::Component* /*component*/) { return AZStd::string(); }
|
||||
|
||||
//! Return path to icon for component type.
|
||||
//! Path will be empty if component type should have no icon.
|
||||
virtual AZStd::string GetComponentTypeEditorIcon(const AZ::Uuid& /*componentType*/) { return AZStd::string(); }
|
||||
|
||||
/**
|
||||
* Return the icon image path based on the component type and where it is used.
|
||||
* \param componentType component type
|
||||
|
||||
+2
@@ -43,6 +43,8 @@ namespace AzToolsFramework
|
||||
};
|
||||
|
||||
//! Provides a bus to notify when the different editor modes are entered/exit.
|
||||
//! @note The editor modes are not discrete states but rather each progression of mode retain the active the parent
|
||||
//! mode that the new mode progressed from.
|
||||
class ViewportEditorModeNotifications : public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
|
||||
+27
-2
@@ -9,9 +9,27 @@
|
||||
#include <AzToolsFramework/Application/EditorEntityManager.h>
|
||||
|
||||
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
|
||||
#include <AzToolsFramework/Entity/EditorEntityHelpers.h>
|
||||
|
||||
namespace AzToolsFramework
|
||||
{
|
||||
static bool AreEntitiesValidForDuplication(const EntityIdList& entityIds)
|
||||
{
|
||||
for (AZ::EntityId entityId : entityIds)
|
||||
{
|
||||
if (GetEntityById(entityId) == nullptr)
|
||||
{
|
||||
AZ_Error(
|
||||
"Entity", false,
|
||||
"Entity with id '%llu' is not found. This can happen when you try to duplicate the entity before it is created. Please "
|
||||
"ensure entities are created before trying to duplicate them.",
|
||||
static_cast<AZ::u64>(entityId));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void EditorEntityManager::Start()
|
||||
{
|
||||
m_prefabPublicInterface = AZ::Interface<Prefab::PrefabPublicInterface>::Get();
|
||||
@@ -62,7 +80,11 @@ namespace AzToolsFramework
|
||||
EntityIdList selectedEntities;
|
||||
ToolsApplicationRequestBus::BroadcastResult(selectedEntities, &ToolsApplicationRequests::GetSelectedEntities);
|
||||
|
||||
m_prefabPublicInterface->DuplicateEntitiesInInstance(selectedEntities);
|
||||
if (AreEntitiesValidForDuplication(selectedEntities))
|
||||
{
|
||||
m_prefabPublicInterface->DuplicateEntitiesInInstance(selectedEntities);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void EditorEntityManager::DuplicateEntityById(AZ::EntityId entityId)
|
||||
@@ -72,7 +94,10 @@ namespace AzToolsFramework
|
||||
|
||||
void EditorEntityManager::DuplicateEntities(const EntityIdList& entities)
|
||||
{
|
||||
m_prefabPublicInterface->DuplicateEntitiesInInstance(entities);
|
||||
if (AreEntitiesValidForDuplication(entities))
|
||||
{
|
||||
m_prefabPublicInterface->DuplicateEntitiesInInstance(entities);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -34,5 +34,4 @@ namespace AzToolsFramework
|
||||
private:
|
||||
Prefab::PrefabPublicInterface* m_prefabPublicInterface = nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -176,7 +176,7 @@ namespace AzToolsFramework
|
||||
, public AZ::BehaviorEBusHandler
|
||||
{
|
||||
AZ_EBUS_BEHAVIOR_BINDER(ToolsApplicationNotificationBusHandler, "{7EB67956-FF86-461A-91E2-7B08279CFACF}", AZ::SystemAllocator,
|
||||
EntityRegistered, EntityDeregistered);
|
||||
EntityRegistered, EntityDeregistered, AfterEntitySelectionChanged);
|
||||
|
||||
void EntityRegistered(AZ::EntityId entityId) override
|
||||
{
|
||||
@@ -187,6 +187,11 @@ namespace AzToolsFramework
|
||||
{
|
||||
Call(FN_EntityDeregistered, entityId);
|
||||
}
|
||||
|
||||
void AfterEntitySelectionChanged(const EntityIdList& newlySelectedEntities, const EntityIdList& newlyDeselectedEntities) override
|
||||
{
|
||||
Call(FN_AfterEntitySelectionChanged, newlySelectedEntities, newlyDeselectedEntities);
|
||||
}
|
||||
};
|
||||
|
||||
struct ViewPaneCallbackBusHandler final
|
||||
@@ -410,6 +415,7 @@ namespace AzToolsFramework
|
||||
->Handler<Internal::ToolsApplicationNotificationBusHandler>()
|
||||
->Event("EntityRegistered", &ToolsApplicationEvents::EntityRegistered)
|
||||
->Event("EntityDeregistered", &ToolsApplicationEvents::EntityDeregistered)
|
||||
->Event("AfterEntitySelectionChanged", &ToolsApplicationEvents::AfterEntitySelectionChanged)
|
||||
;
|
||||
|
||||
behaviorContext->Class<ViewPaneOptions>()
|
||||
@@ -428,6 +434,7 @@ namespace AzToolsFramework
|
||||
->Attribute(AZ::Script::Attributes::Module, "editor")
|
||||
->Event("RegisterCustomViewPane", &EditorRequests::RegisterCustomViewPane)
|
||||
->Event("UnregisterViewPane", &EditorRequests::UnregisterViewPane)
|
||||
->Event("GetComponentTypeEditorIcon", &EditorRequests::GetComponentTypeEditorIcon)
|
||||
;
|
||||
|
||||
behaviorContext->EBus<EditorEventsBus>("EditorEventBus")
|
||||
|
||||
@@ -1110,7 +1110,8 @@ namespace AzToolsFramework
|
||||
// Select the duplicated entities/instances
|
||||
auto selectionUndo = aznew SelectionCommand(duplicatedEntityAndInstanceIds, "Select Duplicated Entities/Instances");
|
||||
selectionUndo->SetParent(undoBatch.GetUndoBatch());
|
||||
ToolsApplicationRequestBus::Broadcast(&ToolsApplicationRequestBus::Events::SetSelectedEntities, duplicatedEntityAndInstanceIds);
|
||||
ToolsApplicationRequestBus::Broadcast(
|
||||
&ToolsApplicationRequestBus::Events::SetSelectedEntities, duplicatedEntityAndInstanceIds);
|
||||
}
|
||||
|
||||
return AZ::Success(AZStd::move(duplicatedEntityAndInstanceIds));
|
||||
|
||||
+1
-1
@@ -90,7 +90,7 @@ namespace AzToolsFramework
|
||||
}
|
||||
|
||||
AZStd::string componentIconPath;
|
||||
EBUS_EVENT_RESULT(componentIconPath, AzToolsFramework::EditorRequests::Bus, GetComponentEditorIcon, componentClass->m_typeId, nullptr);
|
||||
AzToolsFramework::EditorRequestBus::BroadcastResult(componentIconPath, &AzToolsFramework::EditorRequests::GetComponentTypeEditorIcon, componentClass->m_typeId);
|
||||
componentIconTable[componentClass] = QString::fromUtf8(componentIconPath.c_str());
|
||||
}
|
||||
|
||||
|
||||
+34
@@ -63,6 +63,12 @@ namespace AzToolsFramework
|
||||
|
||||
ToastId ToastNotificationsView::ShowToastNotification(const AzQtComponents::ToastConfiguration& toastConfiguration)
|
||||
{
|
||||
// reject duplicate messages
|
||||
if (m_rejectDuplicates && DuplicateNotificationInQueue(toastConfiguration))
|
||||
{
|
||||
return ToastId();
|
||||
}
|
||||
|
||||
ToastId toastId = CreateToastNotification(toastConfiguration);
|
||||
m_queuedNotifications.emplace_back(toastId);
|
||||
|
||||
@@ -70,10 +76,28 @@ namespace AzToolsFramework
|
||||
{
|
||||
DisplayQueuedNotification();
|
||||
}
|
||||
else if (m_queuedNotifications.size() >= m_maxQueuedNotifications)
|
||||
{
|
||||
// hiding the active toast will cause the next toast to be displayed
|
||||
HideToastNotification(m_activeNotification);
|
||||
}
|
||||
|
||||
return toastId;
|
||||
}
|
||||
|
||||
bool ToastNotificationsView::DuplicateNotificationInQueue(const AzQtComponents::ToastConfiguration& toastConfiguration)
|
||||
{
|
||||
for (auto iter : m_notifications)
|
||||
{
|
||||
if (iter.second && iter.second->IsDuplicate(toastConfiguration))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ToastId ToastNotificationsView::ShowToastAtCursor(const AzQtComponents::ToastConfiguration& toastConfiguration)
|
||||
{
|
||||
ToastId toastId = CreateToastNotification(toastConfiguration);
|
||||
@@ -187,4 +211,14 @@ namespace AzToolsFramework
|
||||
{
|
||||
m_anchorPoint = anchorPoint;
|
||||
}
|
||||
|
||||
void ToastNotificationsView::SetMaxQueuedNotifications(AZ::u32 maxQueuedNotifications)
|
||||
{
|
||||
m_maxQueuedNotifications = maxQueuedNotifications;
|
||||
}
|
||||
|
||||
void ToastNotificationsView::SetRejectDuplicates(bool rejectDuplicates)
|
||||
{
|
||||
m_rejectDuplicates = rejectDuplicates;
|
||||
}
|
||||
}
|
||||
|
||||
+5
@@ -52,10 +52,13 @@ namespace AzToolsFramework
|
||||
|
||||
void SetOffset(const QPoint& offset);
|
||||
void SetAnchorPoint(const QPointF& anchorPoint);
|
||||
void SetMaxQueuedNotifications(AZ::u32 maxQueuedNotifications);
|
||||
void SetRejectDuplicates(bool rejectDuplicates);
|
||||
|
||||
private:
|
||||
ToastId CreateToastNotification(const AzQtComponents::ToastConfiguration& toastConfiguration);
|
||||
void DisplayQueuedNotification();
|
||||
bool DuplicateNotificationInQueue(const AzQtComponents::ToastConfiguration& toastConfiguration);
|
||||
QPoint GetGlobalPoint();
|
||||
|
||||
ToastId m_activeNotification;
|
||||
@@ -64,5 +67,7 @@ namespace AzToolsFramework
|
||||
|
||||
QPoint m_offset = QPoint(10, 10);
|
||||
QPointF m_anchorPoint = QPointF(1, 0);
|
||||
AZ::u32 m_maxQueuedNotifications = 5;
|
||||
bool m_rejectDuplicates = true;
|
||||
};
|
||||
} // AzToolsFramework
|
||||
|
||||
+2
-2
@@ -72,7 +72,7 @@ namespace AzToolsFramework
|
||||
|
||||
void EntityOutlinerTreeView::leaveEvent([[maybe_unused]] QEvent* event)
|
||||
{
|
||||
m_mousePosition = QPoint();
|
||||
m_mousePosition = QPoint(-1, -1);
|
||||
m_currentHoveredIndex = QModelIndex();
|
||||
update();
|
||||
}
|
||||
@@ -200,7 +200,7 @@ namespace AzToolsFramework
|
||||
const bool isEnabled = (this->model()->flags(index) & Qt::ItemIsEnabled);
|
||||
|
||||
const bool isSelected = selectionModel()->isSelected(index);
|
||||
const bool isHovered = (index == indexAt(m_mousePosition)) && isEnabled;
|
||||
const bool isHovered = (index == indexAt(m_mousePosition).siblingAtColumn(0)) && isEnabled;
|
||||
|
||||
// Paint the branch Selection/Hover Rect
|
||||
PaintBranchSelectionHoverRect(painter, rect, isSelected, isHovered);
|
||||
|
||||
+3
-6
@@ -153,6 +153,9 @@ namespace AzToolsFramework
|
||||
{
|
||||
initEntityOutlinerWidgetResources();
|
||||
|
||||
m_editorEntityUiInterface = AZ::Interface<AzToolsFramework::EditorEntityUiInterface>::Get();
|
||||
AZ_Assert(m_editorEntityUiInterface != nullptr, "EntityOutlinerWidget requires a EditorEntityUiInterface instance on Initialize.");
|
||||
|
||||
m_gui = new Ui::EntityOutlinerWidgetUI();
|
||||
m_gui->setupUi(this);
|
||||
|
||||
@@ -282,12 +285,6 @@ namespace AzToolsFramework
|
||||
|
||||
m_listModel->Initialize();
|
||||
|
||||
m_editorEntityUiInterface = AZ::Interface<AzToolsFramework::EditorEntityUiInterface>::Get();
|
||||
|
||||
AZ_Assert(
|
||||
m_editorEntityUiInterface != nullptr,
|
||||
"EntityOutlinerWidget requires a EditorEntityUiInterface instance on Initialize.");
|
||||
|
||||
EditorPickModeNotificationBus::Handler::BusConnect(GetEntityContextId());
|
||||
EntityHighlightMessages::Bus::Handler::BusConnect();
|
||||
EntityOutlinerModelNotificationBus::Handler::BusConnect();
|
||||
|
||||
+1
-1
@@ -583,7 +583,7 @@ namespace AzToolsFramework
|
||||
}
|
||||
|
||||
AZStd::string iconPath;
|
||||
EBUS_EVENT_RESULT(iconPath, AzToolsFramework::EditorRequests::Bus, GetComponentEditorIcon, componentType, const_cast<AZ::Component*>(&componentInstance));
|
||||
AzToolsFramework::EditorRequestBus::BroadcastResult(iconPath, &AzToolsFramework::EditorRequests::GetComponentEditorIcon, componentType, const_cast<AZ::Component*>(&componentInstance));
|
||||
GetHeader()->SetIcon(QIcon(iconPath.c_str()));
|
||||
|
||||
bool isExpanded = true;
|
||||
|
||||
@@ -427,8 +427,8 @@ namespace AzToolsFramework::ViewportUi::Internal
|
||||
void ViewportUiDisplay::PositionUiOverlayOverRenderViewport()
|
||||
{
|
||||
QPoint offset = m_renderOverlay->mapToGlobal(QPoint());
|
||||
m_uiMainWindow.move(offset);
|
||||
m_uiOverlay.setFixedSize(m_renderOverlay->width(), m_renderOverlay->height());
|
||||
m_uiMainWindow.setGeometry(offset.x(), offset.y(), m_renderOverlay->width(), m_renderOverlay->height());
|
||||
m_uiOverlay.setGeometry(m_uiMainWindow.rect());
|
||||
UpdateUiOverlayGeometry();
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include <AzTest/AzTest.h>
|
||||
#include <AzToolsFramework/ComponentMode/EditorComponentModeBus.h>
|
||||
#include <AzToolsFramework/FocusMode/FocusModeInterface.h>
|
||||
#include <AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h>
|
||||
#include <AzToolsFramework/Viewport/ViewportMessages.h>
|
||||
#include <AzToolsFramework/ViewportSelection/EditorPickEntitySelection.h>
|
||||
@@ -187,10 +188,13 @@ namespace UnitTest
|
||||
ASSERT_NE(m_viewportEditorModeTracker, nullptr);
|
||||
m_viewportEditorModes = m_viewportEditorModeTracker->GetViewportEditorModes({AzToolsFramework::GetEntityContextId()});
|
||||
ASSERT_NE(m_viewportEditorModes, nullptr);
|
||||
m_focusModeInterface = AZ::Interface<AzToolsFramework::FocusModeInterface>::Get();
|
||||
ASSERT_NE(m_focusModeInterface, nullptr);
|
||||
}
|
||||
|
||||
ViewportEditorModeTrackerInterface* m_viewportEditorModeTracker = nullptr;
|
||||
const ViewportEditorModesInterface* m_viewportEditorModes = nullptr;
|
||||
AzToolsFramework::FocusModeInterface* m_focusModeInterface = nullptr;
|
||||
};
|
||||
|
||||
TEST_F(ViewportEditorModesTestsFixture, NumberOfEditorModesIsEqualTo4)
|
||||
@@ -522,32 +526,48 @@ namespace UnitTest
|
||||
}
|
||||
|
||||
TEST_F(
|
||||
ViewportEditorModeTrackerIntegrationTestFixture, EnteringComponentModeAfterInitialStateHasViewportEditorModesDefaultAndComponentModeActive)
|
||||
ViewportEditorModeTrackerIntegrationTestFixture,
|
||||
EnteringComponentModeAfterInitialStateHasViewportEditorModesDefaultAndComponentModeActive)
|
||||
{
|
||||
// When component mode is entered
|
||||
AzToolsFramework::ComponentModeFramework::ComponentModeSystemRequestBus::Broadcast(
|
||||
&AzToolsFramework::ComponentModeFramework::ComponentModeSystemRequests::BeginComponentMode,
|
||||
AZStd::vector<AzToolsFramework::ComponentModeFramework::EntityAndComponentModeBuilders>{});
|
||||
|
||||
bool inComponentMode = false;
|
||||
AzToolsFramework::ComponentModeFramework::ComponentModeSystemRequestBus::BroadcastResult(
|
||||
inComponentMode, &AzToolsFramework::ComponentModeFramework::ComponentModeSystemRequests::InComponentMode);
|
||||
|
||||
// Expect to be in component mode
|
||||
EXPECT_TRUE(inComponentMode);
|
||||
EXPECT_TRUE(AzToolsFramework::ComponentModeFramework::InComponentMode());
|
||||
|
||||
// Expect the default and component viewport editor modes to be active
|
||||
EXPECT_TRUE(m_viewportEditorModes->IsModeActive(ViewportEditorMode::Default));
|
||||
EXPECT_TRUE(m_viewportEditorModes->IsModeActive(ViewportEditorMode::Component));
|
||||
|
||||
// Do not expect the pick and focus viewport editor modes to be active
|
||||
EXPECT_FALSE(m_viewportEditorModes->IsModeActive(ViewportEditorMode::Pick));
|
||||
EXPECT_FALSE(m_viewportEditorModes->IsModeActive(ViewportEditorMode::Focus));
|
||||
}
|
||||
|
||||
TEST_F(
|
||||
ViewportEditorModeTrackerIntegrationTestFixture,
|
||||
EnteringEditorPickEntitySelectionAfterInitialStateHasOnlyViewportEditorModePickModeActive)
|
||||
ExitingComponentModeAfterEnteringFrominitialStateHasViewportEditorModesDefaultActive)
|
||||
{
|
||||
// When component mode is entered and exited
|
||||
AzToolsFramework::ComponentModeFramework::ComponentModeSystemRequestBus::Broadcast(
|
||||
&AzToolsFramework::ComponentModeFramework::ComponentModeSystemRequests::BeginComponentMode,
|
||||
AZStd::vector<AzToolsFramework::ComponentModeFramework::EntityAndComponentModeBuilders>{});
|
||||
|
||||
EXPECT_TRUE(AzToolsFramework::ComponentModeFramework::InComponentMode());
|
||||
|
||||
AzToolsFramework::ComponentModeFramework::ComponentModeSystemRequestBus::Broadcast(
|
||||
&AzToolsFramework::ComponentModeFramework::ComponentModeSystemRequests::EndComponentMode);
|
||||
|
||||
// Expect to not be in component mode
|
||||
EXPECT_FALSE(AzToolsFramework::ComponentModeFramework::InComponentMode());
|
||||
|
||||
// Expect only the default viewport editor mode to be active
|
||||
ExpectOnlyModeActive(*m_viewportEditorModes, ViewportEditorMode::Default);
|
||||
}
|
||||
|
||||
TEST_F(
|
||||
ViewportEditorModeTrackerIntegrationTestFixture,
|
||||
EnteringEditorPickEntitySelectionAfterInitialStateHasOnlyViewportEditorModePickActive)
|
||||
{
|
||||
// When entering pick mode
|
||||
using AzToolsFramework::EditorInteractionSystemViewportSelectionRequestBus;
|
||||
@@ -563,6 +583,96 @@ namespace UnitTest
|
||||
ExpectOnlyModeActive(*m_viewportEditorModes, ViewportEditorMode::Pick);
|
||||
}
|
||||
|
||||
// FocusMode integration tests will follow (LYN-6995)
|
||||
TEST_F(
|
||||
ViewportEditorModeTrackerIntegrationTestFixture,
|
||||
EnteringEditorDefaultEntitySelectionFromEditorPickEntitySelectionHasOnlyViewportEditorModeDefaultActive)
|
||||
{
|
||||
// When pick mode is entered and exited
|
||||
using AzToolsFramework::EditorInteractionSystemViewportSelectionRequestBus;
|
||||
EditorInteractionSystemViewportSelectionRequestBus::Event(
|
||||
AzToolsFramework::GetEntityContextId(), &EditorInteractionSystemViewportSelectionRequestBus::Events::SetHandler,
|
||||
[](const AzToolsFramework::EditorVisibleEntityDataCache* entityDataCache,
|
||||
[[maybe_unused]] AzToolsFramework::ViewportEditorModeTrackerInterface* viewportEditorModeTracker)
|
||||
{
|
||||
return AZStd::make_unique<AzToolsFramework::EditorPickEntitySelection>(entityDataCache, viewportEditorModeTracker);
|
||||
});
|
||||
|
||||
EditorInteractionSystemViewportSelectionRequestBus::Event(
|
||||
AzToolsFramework::GetEntityContextId(), &EditorInteractionSystemViewportSelectionRequestBus::Events::SetHandler,
|
||||
[](const AzToolsFramework::EditorVisibleEntityDataCache* entityDataCache,
|
||||
[[maybe_unused]] AzToolsFramework::ViewportEditorModeTrackerInterface* viewportEditorModeTracker)
|
||||
{
|
||||
return AZStd::make_unique<AzToolsFramework::EditorDefaultSelection>(entityDataCache, viewportEditorModeTracker);
|
||||
});
|
||||
|
||||
// Expect only the default viewport editor mode to be active
|
||||
ExpectOnlyModeActive(*m_viewportEditorModes, ViewportEditorMode::Default);
|
||||
}
|
||||
|
||||
TEST_F(ViewportEditorModeTrackerIntegrationTestFixture, EnteringFocusModeAfterInitialStateHasViewportEditorModeDefaultAndPickActive)
|
||||
{
|
||||
// When entering focus mode
|
||||
m_focusModeInterface->SetFocusRoot(AZ::EntityId{ 1 });
|
||||
|
||||
// Expect the default and focus viewport editor modes to be active
|
||||
EXPECT_TRUE(m_viewportEditorModes->IsModeActive(ViewportEditorMode::Default));
|
||||
EXPECT_TRUE(m_viewportEditorModes->IsModeActive(ViewportEditorMode::Focus));
|
||||
EXPECT_FALSE(m_viewportEditorModes->IsModeActive(ViewportEditorMode::Pick));
|
||||
EXPECT_FALSE(m_viewportEditorModes->IsModeActive(ViewportEditorMode::Component));
|
||||
}
|
||||
|
||||
TEST_F(
|
||||
ViewportEditorModeTrackerIntegrationTestFixture,
|
||||
ExitingFocusModeAfterEnteringFromInitialStateHasOnlyViewportEditorModeDefaultActive)
|
||||
{
|
||||
// When entering and leaving focus mode
|
||||
m_focusModeInterface->SetFocusRoot(AZ::EntityId{ 1 });
|
||||
m_focusModeInterface->SetFocusRoot(AZ::EntityId());
|
||||
|
||||
// Expect only the default mode to be active
|
||||
ExpectOnlyModeActive(*m_viewportEditorModes, ViewportEditorMode::Default);
|
||||
}
|
||||
|
||||
TEST_F(ViewportEditorModeTrackerIntegrationTestFixture, EnteringComponentModeFromFocusModeStateHasViewportEditorModeDefaultAndFocusAndComponentActive)
|
||||
{
|
||||
// When entering component mode from focus mode
|
||||
m_focusModeInterface->SetFocusRoot(AZ::EntityId{ 1 });
|
||||
AzToolsFramework::ComponentModeFramework::ComponentModeSystemRequestBus::Broadcast(
|
||||
&AzToolsFramework::ComponentModeFramework::ComponentModeSystemRequests::BeginComponentMode,
|
||||
AZStd::vector<AzToolsFramework::ComponentModeFramework::EntityAndComponentModeBuilders>{});
|
||||
|
||||
// Expect to be in component mode
|
||||
EXPECT_TRUE(AzToolsFramework::ComponentModeFramework::InComponentMode());
|
||||
|
||||
// Expect the default, focus and component viewport editor modes to be active
|
||||
EXPECT_TRUE(m_viewportEditorModes->IsModeActive(ViewportEditorMode::Default));
|
||||
EXPECT_TRUE(m_viewportEditorModes->IsModeActive(ViewportEditorMode::Focus));
|
||||
EXPECT_TRUE(m_viewportEditorModes->IsModeActive(ViewportEditorMode::Component));
|
||||
EXPECT_FALSE(m_viewportEditorModes->IsModeActive(ViewportEditorMode::Pick));
|
||||
}
|
||||
|
||||
TEST_F(
|
||||
ViewportEditorModeTrackerIntegrationTestFixture,
|
||||
ExitingComponentModeAfterEnteringFromFocusModeHasViewportEditorModeDefaultAndFocusActive)
|
||||
{
|
||||
// When entering and leaving component mode from focus mode
|
||||
m_focusModeInterface->SetFocusRoot(AZ::EntityId{ 1 });
|
||||
AzToolsFramework::ComponentModeFramework::ComponentModeSystemRequestBus::Broadcast(
|
||||
&AzToolsFramework::ComponentModeFramework::ComponentModeSystemRequests::BeginComponentMode,
|
||||
AZStd::vector<AzToolsFramework::ComponentModeFramework::EntityAndComponentModeBuilders>{});
|
||||
|
||||
EXPECT_TRUE(AzToolsFramework::ComponentModeFramework::InComponentMode());
|
||||
|
||||
AzToolsFramework::ComponentModeFramework::ComponentModeSystemRequestBus::Broadcast(
|
||||
&AzToolsFramework::ComponentModeFramework::ComponentModeSystemRequests::EndComponentMode);
|
||||
|
||||
// Expect to not be in component mode
|
||||
EXPECT_FALSE(AzToolsFramework::ComponentModeFramework::InComponentMode());
|
||||
|
||||
// Expect the default and focus viewport editor modes to be active
|
||||
EXPECT_TRUE(m_viewportEditorModes->IsModeActive(ViewportEditorMode::Default));
|
||||
EXPECT_TRUE(m_viewportEditorModes->IsModeActive(ViewportEditorMode::Focus));
|
||||
EXPECT_FALSE(m_viewportEditorModes->IsModeActive(ViewportEditorMode::Component));
|
||||
EXPECT_FALSE(m_viewportEditorModes->IsModeActive(ViewportEditorMode::Pick));
|
||||
}
|
||||
} // namespace UnitTest
|
||||
|
||||
@@ -10,12 +10,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Debug/TraceMessageBus.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/Serialization/AZStdContainers.inl>
|
||||
#include <AzCore/std/string/regex.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
#include <AzCore/std/parallel/atomic.h>
|
||||
#include <AzCore/Asset/AssetCommon.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/std/containers/bitset.h>
|
||||
#include <AzFramework/Asset/AssetProcessorMessages.h>
|
||||
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
|
||||
|
||||
@@ -259,6 +259,11 @@ namespace AssetProcessor
|
||||
scratchBuffer.reserve(512 * 1024); // Reserve 512kb to avoid repeatedly resizing the buffer;
|
||||
AZStd::fixed_vector<AZStd::string_view, AzFramework::MaxPlatformCodeNames> platformCodes;
|
||||
AzFramework::PlatformHelper::AppendPlatformCodeNames(platformCodes, request.m_platformInfo.m_identifier);
|
||||
AZ_Assert(platformCodes.size() <= 1, "A one-to-one mapping of asset type platform identifier"
|
||||
" to platform codename is required in the SettingsRegistryBuilder."
|
||||
" The bootstrap.game is now only produced per build configuration and doesn't take into account"
|
||||
" different platforms names");
|
||||
|
||||
const AZStd::string& assetPlatformIdentifier = request.m_jobDescription.GetPlatformIdentifier();
|
||||
// Determines the suffix that will be used for the launcher based on processing server vs non-server assets
|
||||
const char* launcherType = assetPlatformIdentifier != AzFramework::PlatformHelper::GetPlatformName(AzFramework::PlatformId::SERVER)
|
||||
@@ -293,9 +298,10 @@ namespace AssetProcessor
|
||||
outputBuffer.Reserve(512 * 1024); // Reserve 512kb to avoid repeatedly resizing the buffer;
|
||||
SettingsExporter exporter(outputBuffer, excludes);
|
||||
|
||||
for (AZStd::string_view platform : platformCodes)
|
||||
if (!platformCodes.empty())
|
||||
{
|
||||
AZ::u32 productSubID = static_cast<AZ::u32>(AZStd::hash<AZStd::string_view>{}(platform)); // Deliberately ignoring half the bits.
|
||||
AZStd::string_view platform = platformCodes.front();
|
||||
constexpr AZ::u32 productSubID = 0;
|
||||
for (size_t i = 0; i < AZStd::size(specializations); ++i)
|
||||
{
|
||||
const AZ::SettingsRegistryInterface::Specializations& specialization = specializations[i];
|
||||
@@ -337,7 +343,7 @@ namespace AssetProcessor
|
||||
// The purpose of this section is to copy the Gem's SourcePaths from the Global Settings Registry
|
||||
// the local SettingsRegistry. The reason this is needed is so that the call to
|
||||
// `MergeSettingsToRegistry_GemRegistries` below is able to locate each gem's "<gem-root>/Registry" folder
|
||||
// that will be merged into the bootstrap.game.<configuration>.<platform>.setreg file
|
||||
// that will be merged into the bootstrap.game.<configuration>.setreg file
|
||||
// This is used by the GameLauncher applications to read from a single merged .setreg file
|
||||
// containing the settings needed to run a game/simulation without have access to the source code base registry
|
||||
AZStd::vector<AzFramework::GemInfo> gemInfos;
|
||||
@@ -408,8 +414,6 @@ namespace AssetProcessor
|
||||
}
|
||||
|
||||
outputPath += specialization.GetSpecialization(0); // Append configuration
|
||||
outputPath += '.';
|
||||
outputPath += platform;
|
||||
outputPath += ".setreg";
|
||||
|
||||
AZ::IO::SystemFile file;
|
||||
|
||||
@@ -281,7 +281,7 @@ namespace AssetProcessor
|
||||
|
||||
ExcludeAssetRecognizer excludeRecogniser;
|
||||
excludeRecogniser.m_name = "backup";
|
||||
excludeRecogniser.m_patternMatcher = AssetBuilderSDK::FilePatternMatcher(".*\\/savebackup\\/.*", AssetBuilderSDK::AssetBuilderPattern::Regex);
|
||||
excludeRecogniser.m_patternMatcher = AssetBuilderSDK::FilePatternMatcher("(^|.+/)savebackup/.*", AssetBuilderSDK::AssetBuilderPattern::Regex);
|
||||
config.AddExcludeRecognizer(excludeRecogniser);
|
||||
}
|
||||
|
||||
|
||||
@@ -123,7 +123,7 @@ namespace AssetProcessor
|
||||
ExcludeAssetRecognizer excludeRecogniser;
|
||||
excludeRecogniser.m_name = "backup";
|
||||
// we are excluding all the files in the folder but not the folder itself
|
||||
excludeRecogniser.m_patternMatcher = AssetBuilderSDK::FilePatternMatcher(".*\\/subfolder2\\/aaa\\/.*", AssetBuilderSDK::AssetBuilderPattern::Regex);
|
||||
excludeRecogniser.m_patternMatcher = AssetBuilderSDK::FilePatternMatcher("(^|[^/]+/)aaa/.*", AssetBuilderSDK::AssetBuilderPattern::Regex);
|
||||
m_platformConfig.get()->AddExcludeRecognizer(excludeRecogniser);
|
||||
m_assetScanner.get()->StartScan();
|
||||
|
||||
@@ -144,7 +144,7 @@ namespace AssetProcessor
|
||||
ExcludeAssetRecognizer excludeRecogniser;
|
||||
excludeRecogniser.m_name = "backup";
|
||||
// we are excluding the complete folder here
|
||||
excludeRecogniser.m_patternMatcher = AssetBuilderSDK::FilePatternMatcher(".*\\/subfolder2\\/aaa", AssetBuilderSDK::AssetBuilderPattern::Regex);
|
||||
excludeRecogniser.m_patternMatcher = AssetBuilderSDK::FilePatternMatcher("(^|[^/]+/)aaa", AssetBuilderSDK::AssetBuilderPattern::Regex);
|
||||
m_platformConfig.get()->AddExcludeRecognizer(excludeRecogniser);
|
||||
m_assetScanner.get()->StartScan();
|
||||
|
||||
|
||||
+2
@@ -405,6 +405,8 @@ TEST_F(PlatformConfigurationUnitTests, TestFailReadConfigFile_RegularExcludes)
|
||||
auto configRoot = AZ::IO::FileIOBase::GetInstance()->ResolvePath("@exefolder@/testdata/config_regular");
|
||||
ASSERT_TRUE(configRoot);
|
||||
UnitTestPlatformConfiguration config;
|
||||
|
||||
config.AddScanFolder(ScanFolderInfo("blahblah", "Blah ScanFolder", "sf2", true, true), true);
|
||||
m_absorber.Clear();
|
||||
ASSERT_TRUE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), EmptyDummyProjectName, false, false));
|
||||
ASSERT_EQ(m_absorber.m_numErrorsAbsorbed, 0);
|
||||
|
||||
@@ -347,7 +347,7 @@ namespace AssetProcessor
|
||||
|
||||
ExcludeAssetRecognizer excludeRecogniser;
|
||||
excludeRecogniser.m_name = "backup";
|
||||
excludeRecogniser.m_patternMatcher = AssetBuilderSDK::FilePatternMatcher(".*\\/savebackup\\/.*", AssetBuilderSDK::AssetBuilderPattern::Regex);
|
||||
excludeRecogniser.m_patternMatcher = AssetBuilderSDK::FilePatternMatcher("(^|.+/)savebackup/.*", AssetBuilderSDK::AssetBuilderPattern::Regex);
|
||||
config.AddExcludeRecognizer(excludeRecogniser);
|
||||
|
||||
AssetProcessorManager_Test apm(&config); // note, this will 'push' the scan folders in to the db.
|
||||
@@ -1791,13 +1791,8 @@ namespace AssetProcessor
|
||||
UNIT_TEST_EXPECT_TRUE((newfingerprintForPCAfterVersionChange != fingerprintForPC) || (newfingerprintForPCAfterVersionChange != newfingerprintForPC));//Fingerprints should be different
|
||||
UNIT_TEST_EXPECT_TRUE((newfingerprintForANDROIDAfterVersionChange != fingerprintForANDROID) || (newfingerprintForANDROIDAfterVersionChange != newfingerprintForANDROID));//Fingerprints should be different
|
||||
|
||||
//------Test for Files which are excluded
|
||||
processResults.clear();
|
||||
absolutePath = AssetUtilities::NormalizeFilePath(tempPath.absoluteFilePath("subfolder3/savebackup/test.txt"));
|
||||
QMetaObject::invokeMethod(&apm, "AssessModifiedFile", Qt::QueuedConnection, Q_ARG(QString, absolutePath));
|
||||
UNIT_TEST_EXPECT_FALSE(BlockUntil(idling, 3000)); //Processing a file that will be excluded should not cause assetprocessor manager to emit the onBecameIdle signal because its state should not change
|
||||
UNIT_TEST_EXPECT_TRUE(processResults.size() == 0);
|
||||
|
||||
|
||||
// ------------- Test querying asset status -------------------
|
||||
{
|
||||
absolutePath = tempPath.absoluteFilePath("subfolder2/folder/ship.tiff");
|
||||
|
||||
@@ -1633,13 +1633,18 @@ namespace AssetProcessor
|
||||
|
||||
bool AssetProcessor::PlatformConfiguration::IsFileExcluded(QString fileName) const
|
||||
{
|
||||
for (const ExcludeAssetRecognizer& excludeRecognizer : m_excludeAssetRecognizers)
|
||||
QString relPath, scanFolderName;
|
||||
if (ConvertToRelativePath(fileName, relPath, scanFolderName))
|
||||
{
|
||||
if (excludeRecognizer.m_patternMatcher.MatchesPath(fileName.toUtf8().constData()))
|
||||
for (const ExcludeAssetRecognizer& excludeRecognizer : m_excludeAssetRecognizers)
|
||||
{
|
||||
return true;
|
||||
if (excludeRecognizer.m_patternMatcher.MatchesPath(relPath.toUtf8().constData()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -50,10 +50,10 @@
|
||||
"order": 6000
|
||||
},
|
||||
"Exclude HoldFiles": {
|
||||
"pattern": ".*\\\\/Levels\\\\/.*_hold\\\\/.*"
|
||||
"pattern": "(^|.+/)Levels/.*_hold(/.*)?$"
|
||||
},
|
||||
"Exclude TempFiles": {
|
||||
"pattern": ".*\\\\/\\\\$tmp[0-9]*_.*"
|
||||
"pattern": "(^|.+/)\\\\$tmp[0-9]*_.*"
|
||||
},
|
||||
"RC i_caf": {
|
||||
"glob": "*.i_caf",
|
||||
|
||||
+2
-2
@@ -74,10 +74,10 @@
|
||||
"include": "test"
|
||||
},
|
||||
"Exclude HoldFiles": {
|
||||
"pattern": ".*\\\\/Levels\\\\/.*_hold\\\\/.*"
|
||||
"pattern": "(^|.+/)Levels/.*_hold(/.*)?$"
|
||||
},
|
||||
"Exclude TempFiles": {
|
||||
"pattern": ".*\\\\/\\\\$tmp[0-9]*_.*"
|
||||
"pattern": "(^|.+/)\\\\$tmp[0-9]*_.*"
|
||||
},
|
||||
"RC i_caf": {
|
||||
"glob": "*.i_caf",
|
||||
|
||||
@@ -691,6 +691,12 @@ QProgressBar::chunk {
|
||||
|
||||
#gemRepoAddDialogInstructionTitleLabel {
|
||||
font-size:14px;
|
||||
font-weight:bold;
|
||||
}
|
||||
|
||||
#gemRepoAddDialogWarningLabel {
|
||||
font-size:12px;
|
||||
font-style:italic;
|
||||
}
|
||||
|
||||
#addGemRepoDialog #formFrame {
|
||||
|
||||
@@ -42,7 +42,9 @@ namespace O3DE::ProjectManager
|
||||
m_headerWidget = new GemCatalogHeaderWidget(m_gemModel, m_proxModel, m_downloadController);
|
||||
vLayout->addWidget(m_headerWidget);
|
||||
|
||||
connect(m_gemModel, &GemModel::gemStatusChanged, this, &GemCatalogScreen::OnGemStatusChanged);
|
||||
connect(m_headerWidget, &GemCatalogHeaderWidget::OpenGemsRepo, this, &GemCatalogScreen::HandleOpenGemRepo);
|
||||
connect(m_headerWidget, &GemCatalogHeaderWidget::AddGem, this, &GemCatalogScreen::OnAddGemClicked);
|
||||
|
||||
QHBoxLayout* hLayout = new QHBoxLayout();
|
||||
hLayout->setMargin(0);
|
||||
@@ -73,6 +75,7 @@ namespace O3DE::ProjectManager
|
||||
|
||||
m_notificationsView = AZStd::make_unique<AzToolsFramework::ToastNotificationsView>(this, AZ_CRC("GemCatalogNotificationsView"));
|
||||
m_notificationsView->SetOffset(QPoint(10, 70));
|
||||
m_notificationsView->SetMaxQueuedNotifications(1);
|
||||
}
|
||||
|
||||
void GemCatalogScreen::ReinitForProject(const QString& projectPath)
|
||||
@@ -94,48 +97,6 @@ namespace O3DE::ProjectManager
|
||||
m_headerWidget->ReinitForProject();
|
||||
|
||||
connect(m_gemModel, &GemModel::dataChanged, m_filterWidget, &GemFilterWidget::ResetGemStatusFilter);
|
||||
connect(m_gemModel, &GemModel::gemStatusChanged, this, &GemCatalogScreen::OnGemStatusChanged);
|
||||
connect(
|
||||
m_headerWidget, &GemCatalogHeaderWidget::AddGem,
|
||||
[&]()
|
||||
{
|
||||
EngineInfo engineInfo;
|
||||
QString defaultPath;
|
||||
|
||||
AZ::Outcome<EngineInfo> engineInfoResult = PythonBindingsInterface::Get()->GetEngineInfo();
|
||||
if (engineInfoResult.IsSuccess())
|
||||
{
|
||||
engineInfo = engineInfoResult.GetValue();
|
||||
defaultPath = engineInfo.m_defaultGemsFolder;
|
||||
}
|
||||
|
||||
if (defaultPath.isEmpty())
|
||||
{
|
||||
defaultPath = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
|
||||
}
|
||||
|
||||
QString directory = QDir::toNativeSeparators(QFileDialog::getExistingDirectory(this, tr("Browse"), defaultPath));
|
||||
if (!directory.isEmpty())
|
||||
{
|
||||
// register the gem to the o3de_manifest.json and to the project after the user confirms
|
||||
// project creation/update
|
||||
auto registerResult = PythonBindingsInterface::Get()->RegisterGem(directory);
|
||||
if(!registerResult)
|
||||
{
|
||||
QMessageBox::critical(this, tr("Failed to add gem"), registerResult.GetError().c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_gemsToRegisterWithProject.insert(directory);
|
||||
AZ::Outcome<GemInfo, void> gemInfoResult = PythonBindingsInterface::Get()->GetGemInfo(directory);
|
||||
if (gemInfoResult)
|
||||
{
|
||||
m_gemModel->AddGem(gemInfoResult.GetValue<GemInfo>());
|
||||
m_gemModel->UpdateGemDependencies();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Select the first entry after everything got correctly sized
|
||||
QTimer::singleShot(200, [=]{
|
||||
@@ -144,6 +105,46 @@ namespace O3DE::ProjectManager
|
||||
});
|
||||
}
|
||||
|
||||
void GemCatalogScreen::OnAddGemClicked()
|
||||
{
|
||||
EngineInfo engineInfo;
|
||||
QString defaultPath;
|
||||
|
||||
AZ::Outcome<EngineInfo> engineInfoResult = PythonBindingsInterface::Get()->GetEngineInfo();
|
||||
if (engineInfoResult.IsSuccess())
|
||||
{
|
||||
engineInfo = engineInfoResult.GetValue();
|
||||
defaultPath = engineInfo.m_defaultGemsFolder;
|
||||
}
|
||||
|
||||
if (defaultPath.isEmpty())
|
||||
{
|
||||
defaultPath = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
|
||||
}
|
||||
|
||||
QString directory = QDir::toNativeSeparators(QFileDialog::getExistingDirectory(this, tr("Browse"), defaultPath));
|
||||
if (!directory.isEmpty())
|
||||
{
|
||||
// register the gem to the o3de_manifest.json and to the project after the user confirms
|
||||
// project creation/update
|
||||
auto registerResult = PythonBindingsInterface::Get()->RegisterGem(directory);
|
||||
if(!registerResult)
|
||||
{
|
||||
QMessageBox::critical(this, tr("Failed to add gem"), registerResult.GetError().c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_gemsToRegisterWithProject.insert(directory);
|
||||
AZ::Outcome<GemInfo, void> gemInfoResult = PythonBindingsInterface::Get()->GetGemInfo(directory);
|
||||
if (gemInfoResult)
|
||||
{
|
||||
m_gemModel->AddGem(gemInfoResult.GetValue<GemInfo>());
|
||||
m_gemModel->UpdateGemDependencies();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GemCatalogScreen::OnGemStatusChanged(const QModelIndex& modelIndex, uint32_t numChangedDependencies)
|
||||
{
|
||||
if (m_notificationsEnabled)
|
||||
@@ -166,6 +167,10 @@ namespace O3DE::ProjectManager
|
||||
{
|
||||
notification += " " + tr("and") + " ";
|
||||
}
|
||||
if (added && GemModel::GetDownloadStatus(modelIndex) == GemInfo::DownloadStatus::NotDownloaded)
|
||||
{
|
||||
m_downloadController->AddGemDownload(GemModel::GetName(modelIndex));
|
||||
}
|
||||
}
|
||||
|
||||
if (numChangedDependencies == 1 )
|
||||
@@ -174,7 +179,7 @@ namespace O3DE::ProjectManager
|
||||
}
|
||||
else if (numChangedDependencies > 1)
|
||||
{
|
||||
notification += QString("%d Gem ").arg(numChangedDependencies) + tr("dependencies");
|
||||
notification += QString("%1 Gem ").arg(numChangedDependencies) + tr("dependencies");
|
||||
}
|
||||
notification += " " + (added ? tr("activated") : tr("deactivated"));
|
||||
|
||||
|
||||
@@ -47,6 +47,7 @@ namespace O3DE::ProjectManager
|
||||
|
||||
public slots:
|
||||
void OnGemStatusChanged(const QModelIndex& modelIndex, uint32_t numChangedDependencies);
|
||||
void OnAddGemClicked();
|
||||
|
||||
protected:
|
||||
void hideEvent(QHideEvent* event) override;
|
||||
|
||||
@@ -225,21 +225,22 @@ namespace O3DE::ProjectManager
|
||||
QVector<QString> elementNames;
|
||||
QVector<int> elementCounts;
|
||||
const int totalGems = m_gemModel->rowCount();
|
||||
const int selectedGemTotal = m_gemModel->TotalAddedGems();
|
||||
const int selectedGemTotal = m_gemModel->GatherGemsToBeAdded(/*includeDependencies=*/true).size();
|
||||
const int unselectedGemTotal = m_gemModel->GatherGemsToBeRemoved(/*includeDependencies=*/true).size();
|
||||
const int enabledGemTotal = m_gemModel->TotalAddedGems(/*includeDependencies=*/true);
|
||||
|
||||
elementNames.push_back(GemSortFilterProxyModel::GetGemSelectedString(GemSortFilterProxyModel::GemSelected::Unselected));
|
||||
elementCounts.push_back(totalGems - selectedGemTotal);
|
||||
|
||||
elementNames.push_back(GemSortFilterProxyModel::GetGemSelectedString(GemSortFilterProxyModel::GemSelected::Selected));
|
||||
elementCounts.push_back(selectedGemTotal);
|
||||
|
||||
elementNames.push_back(GemSortFilterProxyModel::GetGemActiveString(GemSortFilterProxyModel::GemActive::Inactive));
|
||||
elementCounts.push_back(totalGems - enabledGemTotal);
|
||||
elementNames.push_back(GemSortFilterProxyModel::GetGemSelectedString(GemSortFilterProxyModel::GemSelected::Unselected));
|
||||
elementCounts.push_back(unselectedGemTotal);
|
||||
|
||||
elementNames.push_back(GemSortFilterProxyModel::GetGemActiveString(GemSortFilterProxyModel::GemActive::Active));
|
||||
elementCounts.push_back(enabledGemTotal);
|
||||
|
||||
elementNames.push_back(GemSortFilterProxyModel::GetGemActiveString(GemSortFilterProxyModel::GemActive::Inactive));
|
||||
elementCounts.push_back(totalGems - enabledGemTotal);
|
||||
|
||||
bool wasCollapsed = false;
|
||||
if (m_statusFilter)
|
||||
{
|
||||
@@ -262,44 +263,51 @@ namespace O3DE::ProjectManager
|
||||
|
||||
const QList<QAbstractButton*> buttons = m_statusFilter->GetButtonGroup()->buttons();
|
||||
|
||||
QAbstractButton* unselectedButton = buttons[0];
|
||||
QAbstractButton* selectedButton = buttons[1];
|
||||
unselectedButton->setChecked(m_filterProxyModel->GetGemSelected() == GemSortFilterProxyModel::GemSelected::Unselected);
|
||||
selectedButton->setChecked(m_filterProxyModel->GetGemSelected() == GemSortFilterProxyModel::GemSelected::Selected);
|
||||
QAbstractButton* selectedButton = buttons[0];
|
||||
QAbstractButton* unselectedButton = buttons[1];
|
||||
selectedButton->setChecked(m_filterProxyModel->GetGemSelected() == GemSortFilterProxyModel::GemSelected::Selected);
|
||||
unselectedButton->setChecked(m_filterProxyModel->GetGemSelected() == GemSortFilterProxyModel::GemSelected::Unselected);
|
||||
|
||||
auto updateGemSelection = [=]([[maybe_unused]] bool checked)
|
||||
{
|
||||
if (unselectedButton->isChecked() && !selectedButton->isChecked())
|
||||
{
|
||||
m_filterProxyModel->SetGemSelected(GemSortFilterProxyModel::GemSelected::Unselected);
|
||||
}
|
||||
else if (!unselectedButton->isChecked() && selectedButton->isChecked())
|
||||
if (!unselectedButton->isChecked() && selectedButton->isChecked())
|
||||
{
|
||||
m_filterProxyModel->SetGemSelected(GemSortFilterProxyModel::GemSelected::Selected);
|
||||
}
|
||||
else if (unselectedButton->isChecked() && !selectedButton->isChecked())
|
||||
{
|
||||
m_filterProxyModel->SetGemSelected(GemSortFilterProxyModel::GemSelected::Unselected);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_filterProxyModel->SetGemSelected(GemSortFilterProxyModel::GemSelected::NoFilter);
|
||||
if (unselectedButton->isChecked() && selectedButton->isChecked())
|
||||
{
|
||||
m_filterProxyModel->SetGemSelected(GemSortFilterProxyModel::GemSelected::Both);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_filterProxyModel->SetGemSelected(GemSortFilterProxyModel::GemSelected::NoFilter);
|
||||
}
|
||||
}
|
||||
};
|
||||
connect(unselectedButton, &QAbstractButton::toggled, this, updateGemSelection);
|
||||
connect(selectedButton, &QAbstractButton::toggled, this, updateGemSelection);
|
||||
|
||||
QAbstractButton* inactiveButton = buttons[2];
|
||||
QAbstractButton* activeButton = buttons[3];
|
||||
inactiveButton->setChecked(m_filterProxyModel->GetGemActive() == GemSortFilterProxyModel::GemActive::Inactive);
|
||||
activeButton->setChecked(m_filterProxyModel->GetGemActive() == GemSortFilterProxyModel::GemActive::Active);
|
||||
QAbstractButton* activeButton = buttons[2];
|
||||
QAbstractButton* inactiveButton = buttons[3];
|
||||
activeButton->setChecked(m_filterProxyModel->GetGemActive() == GemSortFilterProxyModel::GemActive::Active);
|
||||
inactiveButton->setChecked(m_filterProxyModel->GetGemActive() == GemSortFilterProxyModel::GemActive::Inactive);
|
||||
|
||||
auto updateGemActive = [=]([[maybe_unused]] bool checked)
|
||||
{
|
||||
if (inactiveButton->isChecked() && !activeButton->isChecked())
|
||||
{
|
||||
m_filterProxyModel->SetGemActive(GemSortFilterProxyModel::GemActive::Inactive);
|
||||
}
|
||||
else if (!inactiveButton->isChecked() && activeButton->isChecked())
|
||||
if (!inactiveButton->isChecked() && activeButton->isChecked())
|
||||
{
|
||||
m_filterProxyModel->SetGemActive(GemSortFilterProxyModel::GemActive::Active);
|
||||
}
|
||||
else if (inactiveButton->isChecked() && !activeButton->isChecked())
|
||||
{
|
||||
m_filterProxyModel->SetGemActive(GemSortFilterProxyModel::GemActive::Inactive);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_filterProxyModel->SetGemActive(GemSortFilterProxyModel::GemActive::NoFilter);
|
||||
|
||||
@@ -50,11 +50,26 @@ namespace O3DE::ProjectManager
|
||||
}
|
||||
}
|
||||
|
||||
// Gem selected
|
||||
if (m_gemSelectedFilter != GemSelected::NoFilter)
|
||||
// Gem selected
|
||||
if (m_gemSelectedFilter == GemSelected::Selected)
|
||||
{
|
||||
const GemSelected sourceGemStatus = static_cast<GemSelected>(GemModel::IsAdded(sourceIndex));
|
||||
if (m_gemSelectedFilter != sourceGemStatus)
|
||||
if (!GemModel::NeedsToBeAdded(sourceIndex, true))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Gem unselected
|
||||
else if (m_gemSelectedFilter == GemSelected::Unselected)
|
||||
{
|
||||
if (!GemModel::NeedsToBeRemoved(sourceIndex, true))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Gem selected or unselected
|
||||
else if (m_gemSelectedFilter == GemSelected::Both)
|
||||
{
|
||||
if (!GemModel::NeedsToBeAdded(sourceIndex, true) && !GemModel::NeedsToBeRemoved(sourceIndex, true))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -29,7 +29,8 @@ namespace O3DE::ProjectManager
|
||||
{
|
||||
NoFilter = -1,
|
||||
Unselected,
|
||||
Selected
|
||||
Selected,
|
||||
Both
|
||||
};
|
||||
enum class GemActive
|
||||
{
|
||||
|
||||
@@ -27,6 +27,7 @@ namespace O3DE::ProjectManager
|
||||
QVBoxLayout* vLayout = new QVBoxLayout();
|
||||
vLayout->setContentsMargins(30, 30, 25, 10);
|
||||
vLayout->setSpacing(0);
|
||||
vLayout->setAlignment(Qt::AlignTop);
|
||||
setLayout(vLayout);
|
||||
|
||||
QLabel* instructionTitleLabel = new QLabel(tr("Enter a valid path to add a new user repository"));
|
||||
@@ -41,9 +42,18 @@ namespace O3DE::ProjectManager
|
||||
vLayout->addWidget(instructionContextLabel);
|
||||
|
||||
m_repoPath = new FormFolderBrowseEditWidget(tr("Repository Path"), "", this);
|
||||
m_repoPath->setFixedWidth(600);
|
||||
m_repoPath->setFixedSize(QSize(600, 100));
|
||||
vLayout->addWidget(m_repoPath);
|
||||
|
||||
vLayout->addSpacing(10);
|
||||
|
||||
QLabel* warningLabel = new QLabel(tr("Online repositories may contain files that could potentially harm your computer,"
|
||||
" please ensure you understand the risks before downloading Gems from third-party sources."));
|
||||
warningLabel->setObjectName("gemRepoAddDialogWarningLabel");
|
||||
warningLabel->setWordWrap(true);
|
||||
warningLabel->setAlignment(Qt::AlignLeft);
|
||||
vLayout->addWidget(warningLabel);
|
||||
|
||||
vLayout->addSpacing(40);
|
||||
|
||||
QDialogButtonBox* dialogButtons = new QDialogButtonBox();
|
||||
|
||||
@@ -133,6 +133,11 @@ namespace O3DE::ProjectManager
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If we are already on this screen still notify we are on this screen to refresh it
|
||||
newScreen->NotifyCurrentScreen();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
@@ -187,6 +187,7 @@ namespace AZ
|
||||
|
||||
// Register utilities
|
||||
AZ::SceneAPI::SceneCore::PatternMatcher::Reflect(context);
|
||||
AZ::SceneAPI::Utilities::DebugSceneGraph::Reflect(context);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <AzCore/std/optional.h>
|
||||
|
||||
#include <AzCore/IO/SystemFile.h>
|
||||
#include <AzCore/Serialization/Utils.h>
|
||||
#include <AzFramework/StringFunc/StringFunc.h>
|
||||
#include <SceneAPI/SceneCore/Containers/Scene.h>
|
||||
#include <SceneAPI/SceneCore/Containers/Views/PairIterator.h>
|
||||
@@ -20,6 +21,36 @@
|
||||
|
||||
namespace AZ::SceneAPI::Utilities
|
||||
{
|
||||
void DebugNode::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context);
|
||||
|
||||
if (serialize)
|
||||
{
|
||||
serialize->Class<DebugNode>()
|
||||
->Field("Name", &DebugNode::m_name)
|
||||
->Field("Path", &DebugNode::m_path)
|
||||
->Field("Type", &DebugNode::m_type)
|
||||
->Field("Data", &DebugNode::m_data);
|
||||
}
|
||||
}
|
||||
|
||||
void DebugSceneGraph::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
DebugNode::Reflect(context);
|
||||
|
||||
AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context);
|
||||
|
||||
if (serialize)
|
||||
{
|
||||
serialize->Class<DebugSceneGraph>()
|
||||
->Field("Version", &DebugSceneGraph::m_version)
|
||||
->Field("ProductName", &DebugSceneGraph::m_productName)
|
||||
->Field("SceneName", &DebugSceneGraph::m_sceneName)
|
||||
->Field("Nodes", &DebugSceneGraph::m_nodes);
|
||||
}
|
||||
}
|
||||
|
||||
void DebugOutput::Write(const char* name, const char* data)
|
||||
{
|
||||
m_output += AZStd::string::format("\t%s: %s\n", name, data);
|
||||
@@ -38,21 +69,29 @@ namespace AZ::SceneAPI::Utilities
|
||||
void DebugOutput::Write(const char* name, const AZStd::string& data)
|
||||
{
|
||||
Write(name, data.c_str());
|
||||
|
||||
AddToNode(name, data);
|
||||
}
|
||||
|
||||
void DebugOutput::Write(const char* name, double data)
|
||||
{
|
||||
m_output += AZStd::string::format("\t%s: %f\n", name, data);
|
||||
|
||||
AddToNode(name, data);
|
||||
}
|
||||
|
||||
void DebugOutput::Write(const char* name, uint64_t data)
|
||||
{
|
||||
m_output += AZStd::string::format("\t%s: %" PRIu64 "\n", name, data);
|
||||
|
||||
AddToNode(name, data);
|
||||
}
|
||||
|
||||
void DebugOutput::Write(const char* name, int64_t data)
|
||||
{
|
||||
m_output += AZStd::string::format("\t%s: %" PRId64 "\n", name, data);
|
||||
|
||||
AddToNode(name, data);
|
||||
}
|
||||
|
||||
void DebugOutput::Write(const char* name, const DataTypes::MatrixType& data)
|
||||
@@ -63,6 +102,7 @@ namespace AZ::SceneAPI::Utilities
|
||||
AZ::Vector3 translation{};
|
||||
data.GetBasisAndTranslation(&basisX, &basisY, &basisZ, &translation);
|
||||
|
||||
m_pauseNodeData = true;
|
||||
m_output += AZStd::string::format("\t%s:\n", name);
|
||||
|
||||
m_output += "\t";
|
||||
@@ -76,16 +116,23 @@ namespace AZ::SceneAPI::Utilities
|
||||
|
||||
m_output += "\t";
|
||||
Write("Transl", translation);
|
||||
m_pauseNodeData = false;
|
||||
|
||||
AddToNode(name, data);
|
||||
}
|
||||
|
||||
void DebugOutput::Write(const char* name, bool data)
|
||||
{
|
||||
m_output += AZStd::string::format("\t%s: %s\n", name, data ? "true" : "false");
|
||||
|
||||
AddToNode(name, data);
|
||||
}
|
||||
|
||||
void DebugOutput::Write(const char* name, Vector3 data)
|
||||
{
|
||||
m_output += AZStd::string::format("\t%s: <% f, % f, % f>\n", name, data.GetX(), data.GetY(), data.GetZ());
|
||||
|
||||
AddToNode(name, data);
|
||||
}
|
||||
|
||||
void DebugOutput::Write(const char* name, AZStd::optional<bool> data)
|
||||
@@ -128,6 +175,11 @@ namespace AZ::SceneAPI::Utilities
|
||||
return m_output;
|
||||
}
|
||||
|
||||
DebugNode DebugOutput::GetDebugNode() const
|
||||
{
|
||||
return m_currentNode;
|
||||
}
|
||||
|
||||
void WriteAndLog(AZ::IO::SystemFile& dbgFile, const char* strToWrite)
|
||||
{
|
||||
AZ_TracePrintf(AZ::SceneAPI::Utilities::LogWindow, "%s", strToWrite);
|
||||
@@ -137,7 +189,6 @@ namespace AZ::SceneAPI::Utilities
|
||||
|
||||
void DebugOutput::BuildDebugSceneGraph(const char* outputFolder, AZ::SceneAPI::Events::ExportProductList& productList, const AZStd::shared_ptr<AZ::SceneAPI::Containers::Scene>& scene, AZStd::string productName)
|
||||
{
|
||||
const int debugSceneGraphVersion = 1;
|
||||
AZStd::string debugSceneFile;
|
||||
|
||||
AzFramework::StringFunc::Path::ConstructFull(outputFolder, productName.c_str(), debugSceneFile);
|
||||
@@ -147,7 +198,7 @@ namespace AZ::SceneAPI::Utilities
|
||||
if (dbgFile.Open(debugSceneFile.c_str(), AZ::IO::SystemFile::SF_OPEN_CREATE | AZ::IO::SystemFile::SF_OPEN_WRITE_ONLY))
|
||||
{
|
||||
WriteAndLog(dbgFile, AZStd::string::format("ProductName: %s", productName.c_str()).c_str());
|
||||
WriteAndLog(dbgFile, AZStd::string::format("debugSceneGraphVersion: %d", debugSceneGraphVersion).c_str());
|
||||
WriteAndLog(dbgFile, AZStd::string::format("debugSceneGraphVersion: %d", SceneGraphVersion).c_str());
|
||||
WriteAndLog(dbgFile, scene->GetName().c_str());
|
||||
|
||||
const AZ::SceneAPI::Containers::SceneGraph& sceneGraph = scene->GetGraph();
|
||||
@@ -158,6 +209,11 @@ namespace AZ::SceneAPI::Utilities
|
||||
AZ::SceneAPI::Containers::Views::BreadthFirst>(
|
||||
sceneGraph, sceneGraph.GetRoot(), pairView.cbegin(), true);
|
||||
|
||||
DebugSceneGraph debugSceneGraph;
|
||||
debugSceneGraph.m_version = SceneGraphVersion;
|
||||
debugSceneGraph.m_productName = productName;
|
||||
debugSceneGraph.m_sceneName = scene->GetName().c_str();
|
||||
|
||||
for (auto&& viewIt : view)
|
||||
{
|
||||
if (viewIt.second == nullptr)
|
||||
@@ -170,20 +226,31 @@ namespace AZ::SceneAPI::Utilities
|
||||
WriteAndLog(dbgFile, AZStd::string::format("Node Name: %s", viewIt.first.GetName()).c_str());
|
||||
WriteAndLog(dbgFile, AZStd::string::format("Node Path: %s", viewIt.first.GetPath()).c_str());
|
||||
WriteAndLog(dbgFile, AZStd::string::format("Node Type: %s", graphObject->RTTI_GetTypeName()).c_str());
|
||||
|
||||
AZ::SceneAPI::Utilities::DebugOutput debugOutput;
|
||||
|
||||
AZ::SceneAPI::Utilities::DebugOutput debugOutput(
|
||||
DebugNode(viewIt.first.GetName(), viewIt.first.GetPath(), graphObject->RTTI_GetTypeName()));
|
||||
|
||||
viewIt.second->GetDebugOutput(debugOutput);
|
||||
|
||||
if (!debugOutput.GetOutput().empty())
|
||||
{
|
||||
WriteAndLog(dbgFile, debugOutput.GetOutput().c_str());
|
||||
}
|
||||
|
||||
debugSceneGraph.m_nodes.push_back(debugOutput.GetDebugNode());
|
||||
}
|
||||
dbgFile.Close();
|
||||
|
||||
Utils::SaveObjectToFile((debugSceneFile + ".xml").c_str(), DataStream::StreamType::ST_XML, &debugSceneGraph);
|
||||
|
||||
static const AZ::Data::AssetType dbgSceneGraphAssetType("{07F289D1-4DC7-4C40-94B4-0A53BBCB9F0B}");
|
||||
productList.AddProduct(productName, AZ::Uuid::CreateName(productName.c_str()), dbgSceneGraphAssetType,
|
||||
AZStd::nullopt, AZStd::nullopt);
|
||||
|
||||
static const AZ::Data::AssetType dbgSceneGraphXmlAssetType("{51F37614-0D77-4F36-9AC6-7ED70A0AC868}");
|
||||
productList.AddProduct(
|
||||
(productName + ".xml"), AZ::Uuid::CreateName((productName + ".xml").c_str()), dbgSceneGraphXmlAssetType,
|
||||
AZStd::nullopt, AZStd::nullopt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
#include <AzCore/std/optional.h>
|
||||
#include <cinttypes>
|
||||
#include <AzCore/std/any.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
@@ -34,15 +35,63 @@ namespace AZ
|
||||
|
||||
namespace AZ::SceneAPI::Utilities
|
||||
{
|
||||
constexpr int SceneGraphVersion = 1;
|
||||
|
||||
struct DebugNode
|
||||
{
|
||||
AZ_TYPE_INFO(DebugNode, "{490B9D4C-1847-46EB-BEBC-49812E104626}");
|
||||
|
||||
AZStd::string m_name;
|
||||
AZStd::string m_path;
|
||||
AZStd::string m_type;
|
||||
|
||||
DebugNode() = default;
|
||||
|
||||
DebugNode(AZStd::string name, AZStd::string path, AZStd::string type)
|
||||
: m_name(AZStd::move(name)),
|
||||
m_path(AZStd::move(path)),
|
||||
m_type(AZStd::move(type))
|
||||
{
|
||||
}
|
||||
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
using DataItem = AZStd::pair<AZStd::string, AZStd::any>;
|
||||
AZStd::vector<DataItem> m_data;
|
||||
};
|
||||
|
||||
struct DebugSceneGraph
|
||||
{
|
||||
AZ_TYPE_INFO(DebugSceneGraph, "{375F6558-5709-409F-881E-8ED575D56C92}");
|
||||
|
||||
int m_version = SceneGraphVersion;
|
||||
AZStd::string m_productName;
|
||||
AZStd::string m_sceneName;
|
||||
AZStd::vector<DebugNode> m_nodes;
|
||||
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
};
|
||||
|
||||
class DebugOutput
|
||||
{
|
||||
public:
|
||||
DebugOutput(DebugNode node) : m_currentNode(AZStd::move(node)){}
|
||||
|
||||
template<typename T>
|
||||
void Write(const char* name, const AZStd::vector<T>& data);
|
||||
|
||||
template<typename T>
|
||||
void Write(const char* name, const AZStd::vector<AZStd::vector<T>>& data);
|
||||
|
||||
template<typename T>
|
||||
void AddToNode(const char* name, const T& data)
|
||||
{
|
||||
if (!m_pauseNodeData)
|
||||
{
|
||||
m_currentNode.m_data.emplace_back(name, AZStd::make_any<AZStd::decay_t<T>>(data));
|
||||
}
|
||||
}
|
||||
|
||||
SCENE_CORE_API void Write(const char* name, const char* data);
|
||||
SCENE_CORE_API void WriteArray(const char* name, const unsigned int* data, int size);
|
||||
SCENE_CORE_API void Write(const char* name, const AZStd::string& data);
|
||||
@@ -57,11 +106,15 @@ namespace AZ::SceneAPI::Utilities
|
||||
SCENE_CORE_API void Write(const char* name, AZStd::optional<AZ::Vector3> data);
|
||||
|
||||
SCENE_CORE_API const AZStd::string& GetOutput() const;
|
||||
SCENE_CORE_API DebugNode GetDebugNode() const;
|
||||
|
||||
SCENE_CORE_API static void BuildDebugSceneGraph(const char* outputFolder, AZ::SceneAPI::Events::ExportProductList& productList, const AZStd::shared_ptr<AZ::SceneAPI::Containers::Scene>& scene, AZStd::string productName);
|
||||
|
||||
protected:
|
||||
AZStd::string m_output;
|
||||
DebugSceneGraph m_graph;
|
||||
DebugNode m_currentNode;
|
||||
bool m_pauseNodeData = false; // If true, don't append any data to the DebugNode. Useful when a Write function calls other Write functions
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,11 @@ namespace AZ::SceneAPI::Utilities
|
||||
template <typename T>
|
||||
void DebugOutput::Write(const char* name, const AZStd::vector<T>& data)
|
||||
{
|
||||
m_output += AZStd::string::format("\t%s: Count %zu. Hash: %zu\n", name, data.size(), AZStd::hash_range(data.begin(), data.end()));
|
||||
size_t hash = AZStd::hash_range(data.begin(), data.end());
|
||||
m_output += AZStd::string::format("\t%s: Count %zu. Hash: %zu\n", name, data.size(), hash);
|
||||
|
||||
AddToNode(AZStd::string::format("%s - Count", name).c_str(), data.size());
|
||||
AddToNode(AZStd::string::format("%s - Hash", name).c_str(), hash);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@@ -27,5 +31,9 @@ namespace AZ::SceneAPI::Utilities
|
||||
}
|
||||
|
||||
m_output += AZStd::string::format("\t%s: Count %zu. Hash: %zu\n", name, data.size(), hash);
|
||||
|
||||
AddToNode(AZStd::string::format("%s - Count", name).c_str(), data.size());
|
||||
AddToNode(AZStd::string::format("%s - Hash", name).c_str(), hash);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user