Merge branch 'main' into Prefab/CreatePrefab

This commit is contained in:
srikappa
2021-04-22 14:54:01 -07:00
710 changed files with 29481 additions and 30600 deletions
@@ -341,6 +341,16 @@ namespace AZ
;
}
}
if (auto behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
{
behaviorContext->EBus<ComponentApplicationBus>("ComponentApplicationBus")
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
->Attribute(AZ::Script::Attributes::Category, "Components")
->Event("GetEntityName", &ComponentApplicationBus::Events::GetEntityName)
->Event("SetEntityName", &ComponentApplicationBus::Events::SetEntityName);
}
}
//=========================================================================
@@ -1050,6 +1060,20 @@ namespace AZ
return AZStd::string();
}
//=========================================================================
// SetEntityName
//=========================================================================
bool ComponentApplication::SetEntityName(const EntityId& id, const AZStd::string_view name)
{
Entity* entity = FindEntity(id);
if (entity)
{
entity->SetName(name);
return true;
}
return false;
}
//=========================================================================
// EnumerateEntities
//=========================================================================
@@ -209,6 +209,7 @@ namespace AZ
bool DeleteEntity(const EntityId& id) override;
Entity* FindEntity(const EntityId& id) override;
AZStd::string GetEntityName(const EntityId& id) override;
bool SetEntityName(const EntityId& id, const AZStd::string_view name) override;
void EnumerateEntities(const ComponentApplicationRequests::EntityCallback& callback) override;
ComponentApplication* GetApplication() override { return this; }
/// Returns the serialize context that has been registered with the app, if there is one.
@@ -130,7 +130,13 @@ namespace AZ
//! @param entity A reference to the entity whose name you are seeking.
//! @return The name of the entity with the specified entity ID.
//! If no entity is found for the specified ID, it returns an empty string.
virtual AZStd::string GetEntityName(const EntityId& id) { (void)id; return AZStd::string(); };
virtual AZStd::string GetEntityName(const EntityId& id) { (void)id; return AZStd::string(); }
//! Sets the name of the entity that has the specified entity ID.
//! Entity names are not enforced to be unique.
//! @param entityId A reference to the entity whose name you want to change.
//! @return True if the name was changed successfully, false if it wasn't.
virtual bool SetEntityName([[maybe_unused]] const EntityId& id, [[maybe_unused]] const AZStd::string_view name) { return false; }
//! The type that AZ::ComponentApplicationRequests::EnumerateEntities uses to
//! pass entity callbacks to the application for enumeration.
@@ -63,13 +63,13 @@ namespace AZ
static AssetTrackingImpl* GetSharedInstance();
static ThreadData& GetSharedThreadData();
using MasterAssets = AZStd::unordered_map<AssetTrackingId, AssetMasterInfo, AZStd::hash<AssetTrackingId>, AZStd::equal_to<AssetTrackingId>, AZStdAssetTrackingAllocator>;
using PrimaryAssets = AZStd::unordered_map<AssetTrackingId, AssetPrimaryInfo, AZStd::hash<AssetTrackingId>, AZStd::equal_to<AssetTrackingId>, AZStdAssetTrackingAllocator>;
using ThreadData = ThreadData;
using mutex_type = AZStd::mutex;
using lock_type = AZStd::lock_guard<mutex_type>;
mutex_type m_mutex;
MasterAssets m_masterAssets;
PrimaryAssets m_primaryAssets;
AssetTreeNodeBase* m_assetRoot = nullptr;
AssetAllocationTableBase* m_allocationTable = nullptr;
bool m_performingAnalysis = false;
@@ -118,7 +118,7 @@ namespace AZ
auto& threadData = GetSharedThreadData();
AssetTreeNodeBase* parentAsset = threadData.m_currentAssetStack.empty() ? nullptr : threadData.m_currentAssetStack.back();
AssetTreeNodeBase* childAsset;
AssetMasterInfo* assetMasterInfo;
AssetPrimaryInfo* assetPrimaryInfo;
if (!parentAsset)
{
@@ -128,22 +128,22 @@ namespace AZ
{
lock_type lock(m_mutex);
// Locate or create the master record for this asset
auto masterItr = m_masterAssets.find(assetId);
// Locate or create the primary record for this asset
auto primaryItr = m_primaryAssets.find(assetId);
if (masterItr != m_masterAssets.end())
if (primaryItr != m_primaryAssets.end())
{
assetMasterInfo = &masterItr->second;
assetPrimaryInfo = &primaryItr->second;
}
else
{
auto insertResult = m_masterAssets.emplace(assetId, AssetMasterInfo());
assetMasterInfo = &insertResult.first->second;
assetMasterInfo->m_id = &insertResult.first->first;
auto insertResult = m_primaryAssets.emplace(assetId, AssetPrimaryInfo());
assetPrimaryInfo = &insertResult.first->second;
assetPrimaryInfo->m_id = &insertResult.first->first;
}
// Add this asset to the stack for this thread's context
childAsset = parentAsset->FindOrAddChild(assetId, assetMasterInfo);
childAsset = parentAsset->FindOrAddChild(assetId, assetPrimaryInfo);
}
threadData.m_currentAssetStack.push_back(childAsset);
@@ -304,7 +304,7 @@ namespace AZ
char* pos = buffer;
for (auto itr = assetStack.rbegin(); itr != assetStack.rend(); ++itr)
{
pos += azsnprintf(pos, BUFFER_SIZE - (pos - buffer), "%s\n", (*itr)->GetAssetMasterInfo()->m_id->m_id.c_str());
pos += azsnprintf(pos, BUFFER_SIZE - (pos - buffer), "%s\n", (*itr)->GetAssetPrimaryInfo()->m_id->m_id.c_str());
if (pos >= buffer + BUFFER_SIZE)
{
@@ -79,9 +79,9 @@ namespace AZ
AssetTrackingString m_id;
};
// Master information about an asset.
// Primary information about an asset.
// Currently just contains the ID of the asset, but in the future may carry additional information about that asset (such as where in code it was initialized).
struct AssetMasterInfo
struct AssetPrimaryInfo
{
const AssetTrackingId* m_id;
};
@@ -90,8 +90,8 @@ namespace AZ
class AssetTreeNodeBase
{
public:
virtual const AssetMasterInfo* GetAssetMasterInfo() const = 0;
virtual AssetTreeNodeBase* FindOrAddChild(const AssetTrackingId& id, const AssetMasterInfo* info) = 0;
virtual const AssetPrimaryInfo* GetAssetPrimaryInfo() const = 0;
virtual AssetTreeNodeBase* FindOrAddChild(const AssetTrackingId& id, const AssetPrimaryInfo* info) = 0;
};
// Base class for an asset tree. Implemented by the template AssetTree<>.
@@ -29,18 +29,18 @@ namespace AZ
class AssetTreeNode : public AssetTreeNodeBase
{
public:
AssetTreeNode(const AssetMasterInfo* masterInfo = nullptr, AssetTreeNode* parent = nullptr) :
m_masterInfo(masterInfo),
AssetTreeNode(const AssetPrimaryInfo* primaryInfo = nullptr, AssetTreeNode* parent = nullptr) :
m_primaryinfo(primaryInfo),
m_parent(parent)
{
}
const AssetMasterInfo* GetAssetMasterInfo() const override
const AssetPrimaryInfo* GetAssetPrimaryInfo() const override
{
return m_masterInfo;
return m_primaryinfo;
}
AssetTreeNodeBase* FindOrAddChild(const AssetTrackingId& id, const AssetMasterInfo* info) override
AssetTreeNodeBase* FindOrAddChild(const AssetTrackingId& id, const AssetPrimaryInfo* info) override
{
AssetTreeNodeBase* result = nullptr;
auto childItr = m_children.find(id);
@@ -61,7 +61,7 @@ namespace AZ
using AssetMap = AssetTrackingMap<AssetTrackingId, AssetTreeNode>;
const AssetMasterInfo* m_masterInfo;
const AssetPrimaryInfo* m_primaryinfo;
AssetTreeNode* m_parent;
AssetMap m_children;
AssetDataT m_data;
+9 -2
View File
@@ -70,6 +70,7 @@ namespace AZ
static const char* logVerbosityUID = "sys_LogLevel";
static const int assertLevel_log = 1;
static const int assertLevel_nativeUI = 2;
static const int assertLevel_crash = 3;
static const int logLevel_errorWarning = 1;
static const int logLevel_full = 2;
static AZ::EnvironmentVariable<AZStd::unordered_set<size_t>> g_ignoredAsserts;
@@ -289,8 +290,8 @@ namespace AZ
}
#if AZ_ENABLE_TRACE_ASSERTS
//display native UI dialogs at verbosity level 2 or higher
if (currentLevel >= assertLevel_nativeUI)
//display native UI dialogs at verbosity level 2
if (currentLevel == assertLevel_nativeUI)
{
AZ::NativeUI::AssertAction buttonResult;
EBUS_EVENT_RESULT(buttonResult, AZ::NativeUI::NativeUIRequestBus, DisplayAssertDialog, dialogBoxText);
@@ -314,7 +315,13 @@ namespace AZ
break;
}
}
else
#endif //AZ_ENABLE_TRACE_ASSERTS
// Crash the application directly at assert level 3
if (currentLevel >= assertLevel_crash)
{
AZ_Crash();
}
}
g_alreadyHandlingAssertOrFatal = false;
}
+29 -2
View File
@@ -146,8 +146,8 @@ namespace AZ
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Method("GetTranslated", &Aabb::GetTranslated)
->Method("GetSurfaceArea", &Aabb::GetSurfaceArea)
->Method("GetTransformedObb", &Aabb::GetTransformedObb)
->Method("GetTransformedAabb", &Aabb::GetTransformedAabb)
->Method("GetTransformedObb", static_cast<Obb(Aabb::*)(const Transform&) const>(&Aabb::GetTransformedObb))
->Method("GetTransformedAabb", static_cast<Aabb(Aabb::*)(const Transform&) const>(&Aabb::GetTransformedAabb))
->Method("ApplyTransform", &Aabb::ApplyTransform)
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Method("Clone", [](const Aabb& rhs) -> Aabb { return rhs; })
@@ -195,6 +195,20 @@ namespace AZ
}
Obb Aabb::GetTransformedObb(const Matrix3x4& matrix3x4) const
{
Matrix3x4 matrixNoScale = matrix3x4;
const AZ::Vector3 scale = matrixNoScale.ExtractScale();
const AZ::Quaternion rotation = AZ::Quaternion::CreateFromMatrix3x4(matrixNoScale);
return Obb::CreateFromPositionRotationAndHalfLengths(
matrix3x4 * GetCenter(),
rotation,
0.5f * scale * GetExtents()
);
}
void Aabb::ApplyTransform(const Transform& transform)
{
Vector3 a, b, axisCoeffs;
@@ -224,4 +238,17 @@ namespace AZ
m_min = newMin;
m_max = newMax;
}
void Aabb::ApplyMatrix3x4(const Matrix3x4& matrix3x4)
{
const AZ::Vector3 extents = GetExtents();
const AZ::Vector3 center = matrix3x4 * GetCenter();
AZ::Vector3 newHalfExtents(
0.5f * matrix3x4.GetRowAsVector3(0).GetAbs().Dot(extents),
0.5f * matrix3x4.GetRowAsVector3(1).GetAbs().Dot(extents),
0.5f * matrix3x4.GetRowAsVector3(2).GetAbs().Dot(extents));
m_min = center - newHalfExtents;
m_max = center + newHalfExtents;
}
}
+12 -2
View File
@@ -129,11 +129,21 @@ namespace AZ
void ApplyTransform(const Transform& transform);
void ApplyMatrix3x4(const Matrix3x4& matrix3x4);
void MultiplyByScale(const Vector3& scale);
//! Transforms an Aabb and returns the resulting Obb.
class Obb GetTransformedObb(const Transform& transform) const;
[[nodiscard]] Obb GetTransformedObb(const Transform& transform) const;
//! Transforms an Aabb and returns the resulting Obb.
[[nodiscard]] Obb GetTransformedObb(const Matrix3x4& matrix3x4) const;
//! Returns a new AABB containing the transformed AABB.
Aabb GetTransformedAabb(const Transform& transform) const;
[[nodiscard]] Aabb GetTransformedAabb(const Transform& transform) const;
//! Returns a new AABB containing the transformed AABB.
[[nodiscard]] Aabb GetTransformedAabb(const Matrix3x4& matrix3x4) const;
//! Checks if this aabb is equal to another within a floating point tolerance.
bool IsClose(const Aabb& rhs, float tolerance = Constants::Tolerance) const;
@@ -292,6 +292,14 @@ namespace AZ
}
AZ_MATH_INLINE void Aabb::MultiplyByScale(const Vector3& scale)
{
m_min *= scale;
m_max *= scale;
AZ_MATH_ASSERT(IsValid(), "Min must be less than Max");
}
AZ_MATH_INLINE Aabb Aabb::GetTransformedAabb(const Transform& transform) const
{
Aabb aabb = Aabb::CreateFromMinMax(m_min, m_max);
@@ -300,6 +308,14 @@ namespace AZ
}
AZ_MATH_INLINE Aabb Aabb::GetTransformedAabb(const Matrix3x4& matrix3x4) const
{
Aabb aabb = Aabb::CreateFromMinMax(m_min, m_max);
aabb.ApplyMatrix3x4(matrix3x4);
return aabb;
}
AZ_MATH_INLINE bool Aabb::IsClose(const Aabb& rhs, float tolerance) const
{
return m_min.IsClose(rhs.m_min, tolerance) && m_max.IsClose(rhs.m_max, tolerance);
@@ -258,7 +258,8 @@ namespace AZ
Method("CreateFromMatrix3x3", &Quaternion::CreateFromMatrix3x3)->
Method("CreateFromMatrix4x4", &Quaternion::CreateFromMatrix4x4)->
Method("CreateFromAxisAngle", &Quaternion::CreateFromAxisAngle)->
Method("CreateShortestArc", &Quaternion::CreateShortestArc)
Method("CreateShortestArc", &Quaternion::CreateShortestArc)->
Method("CreateFromEulerAnglesDegrees", &Quaternion::CreateFromEulerAnglesDegrees)
;
}
}
@@ -250,6 +250,7 @@ namespace AZ
Attribute(Script::Attributes::ExcludeFrom, Script::Attributes::ExcludeFlags::All)->
Attribute(Script::Attributes::Storage, Script::Attributes::StorageType::Value)->
Attribute(Script::Attributes::GenericConstructorOverride, &Internal::TransformDefaultConstructor)->
Constructor<const Vector3&, const Quaternion&, const Vector3&>()->
Method("GetBasis", &Transform::GetBasis)->
Method("GetBasisX", &Transform::GetBasisX)->
Method("GetBasisY", &Transform::GetBasisY)->
+3 -4
View File
@@ -40,14 +40,13 @@ ly_add_target(
${common_dir}
${AZ_CORE_RADTELEMETRY_INCLUDE_DIRECTORIES}
BUILD_DEPENDENCIES
PRIVATE
3rdParty::zlib
3rdParty::zstd
3rdParty::cityhash
PUBLIC
3rdParty::Lua
3rdParty::RapidJSON
3rdParty::RapidXML
3rdParty::zlib
3rdParty::zstd
3rdParty::cityhash
${AZ_CORE_RADTELEMETRY_BUILD_DEPENDENCIES}
)
ly_add_source_properties(
@@ -105,7 +105,7 @@ namespace UnitTest
EXPECT_EQ(&rootAsset, &m_env->m_tree.GetRoot());
ASSERT_NE(itr, rootAsset.m_children.end());
EXPECT_EQ(itr->second.m_masterInfo->m_id->m_id, "TestScopedAllocation.1");
EXPECT_EQ(itr->second.m_primaryinfo->m_id->m_id, "TestScopedAllocation.1");
EXPECT_EQ(&itr->second, m_env->m_table.FindAllocation(TEST_POINTER));
@@ -15,6 +15,7 @@
#include <AzCore/Math/Vector3.h>
#include <AzCore/Math/Transform.h>
#include <AzCore/UnitTest/TestTypes.h>
#include <AZTestShared/Math/MathTestHelpers.h>
using namespace AZ;
@@ -385,4 +386,77 @@ namespace UnitTest
EXPECT_TRUE(aabb.GetMin().IsClose(transAabb.GetMin()));
EXPECT_TRUE(aabb.GetMax().IsClose(transAabb.GetMax()));
}
TEST(MATH_AabbTransform, GetTransformedObbMatrix3x4)
{
Vector3 min(-1.0f, -2.0f, -3.0f);
Vector3 max(4.0f, 3.0f, 2.0f);
Aabb aabb = Aabb::CreateFromMinMax(min, max);
Quaternion rotation(0.46f, 0.26f, 0.58f, 0.62f);
Vector3 translation(5.0f, 7.0f, 9.0f);
Matrix3x4 matrix3x4 = Matrix3x4::CreateFromQuaternionAndTranslation(rotation, translation);
matrix3x4.MultiplyByScale(Vector3(0.5f, 1.5f, 2.0f));
Obb obb = aabb.GetTransformedObb(matrix3x4);
EXPECT_THAT(obb.GetRotation(), IsClose(rotation));
EXPECT_THAT(obb.GetHalfLengths(), IsClose(Vector3(1.25f, 3.75f, 5.0f)));
EXPECT_THAT(obb.GetPosition(), IsClose(Vector3(3.928f, 7.9156f, 9.3708f)));
}
TEST(MATH_AabbTransform, GetTransformedAabbMatrix3x4)
{
Vector3 min(2.0f, 3.0f, 5.0f);
Vector3 max(6.0f, 5.0f, 11.0f);
Aabb aabb = Aabb::CreateFromMinMax(min, max);
Quaternion rotation(0.34f, 0.46f, 0.58f, 0.58f);
Vector3 translation(-3.0f, -4.0f, -5.0f);
Matrix3x4 matrix3x4 = Matrix3x4::CreateFromQuaternionAndTranslation(rotation, translation);
matrix3x4.MultiplyByScale(Vector3(1.2f, 0.8f, 2.0f));
Aabb transformedAabb = aabb.GetTransformedAabb(matrix3x4);
EXPECT_THAT(transformedAabb.GetMin(), IsClose(Vector3(4.1488f, -0.01216f, -0.31904f)));
EXPECT_THAT(transformedAabb.GetMax(), IsClose(Vector3(16.3216f, 6.54272f, 5.98112f)));
}
TEST(MATH_AabbTransform, GetTransformedObbFitsInsideTransformedAabb)
{
Vector3 min(4.0f, 3.0f, 1.0f);
Vector3 max(7.0f, 6.0f, 8.0f);
Aabb aabb = Aabb::CreateFromMinMax(min, max);
Quaternion rotation(0.40f, 0.40f, 0.64f, 0.52f);
Vector3 translation(-2.0f, 4.0f, -3.0f);
Matrix3x4 matrix3x4 = Matrix3x4::CreateFromQuaternionAndTranslation(rotation, translation);
matrix3x4.MultiplyByScale(Vector3(2.2f, 0.6f, 1.4f));
Aabb transformedAabb = aabb.GetTransformedAabb(matrix3x4);
Obb transformedObb = aabb.GetTransformedObb(matrix3x4);
Aabb aabbContainingTransformedObb = Aabb::CreateFromObb(transformedObb);
EXPECT_THAT(transformedAabb.GetMin(), IsClose(aabbContainingTransformedObb.GetMin()));
EXPECT_THAT(transformedAabb.GetMax(), IsClose(aabbContainingTransformedObb.GetMax()));
}
TEST(MATH_AabbTransform, MultiplyByScale)
{
Vector3 min(2.0f, 6.0f, 8.0f);
Vector3 max(6.0f, 9.0f, 10.0f);
Aabb aabb = Aabb::CreateFromMinMax(min, max);
Vector3 scale(0.5f, 2.0f, 1.5f);
aabb.MultiplyByScale(scale);
EXPECT_THAT(aabb.GetMin(), IsClose(Vector3(1.0f, 12.0f, 12.0f)));
EXPECT_THAT(aabb.GetMax(), IsClose(Vector3(3.0f, 18.0f, 15.0f)));
}
}
@@ -28,7 +28,7 @@ namespace Physics
class CharacterColliderNodeConfiguration
{
public:
AZ_RTTI(CharacterColliderNodeConfiguration, "{C16F3301-0979-400C-B734-692D83755C39}");
AZ_RTTI(Physics::CharacterColliderNodeConfiguration, "{C16F3301-0979-400C-B734-692D83755C39}");
AZ_CLASS_ALLOCATOR_DECL
virtual ~CharacterColliderNodeConfiguration() = default;
@@ -42,7 +42,7 @@ namespace Physics
class CharacterColliderConfiguration
{
public:
AZ_RTTI(CharacterColliderConfiguration, "{4DFF1434-DF5B-4ED5-BE0F-D3E66F9B331A}");
AZ_RTTI(Physics::CharacterColliderConfiguration, "{4DFF1434-DF5B-4ED5-BE0F-D3E66F9B331A}");
AZ_CLASS_ALLOCATOR_DECL
virtual ~CharacterColliderConfiguration() = default;
@@ -63,21 +63,23 @@ namespace Physics
{
public:
AZ_CLASS_ALLOCATOR(CharacterConfiguration, AZ::SystemAllocator, 0);
AZ_RTTI(CharacterConfiguration, "{58D5A6CA-113B-4AC3-8D53-239DB0C4E240}", AzPhysics::SimulatedBodyConfiguration);
AZ_RTTI(Physics::CharacterConfiguration, "{58D5A6CA-113B-4AC3-8D53-239DB0C4E240}", AzPhysics::SimulatedBodyConfiguration);
virtual ~CharacterConfiguration() = default;
static void Reflect(AZ::ReflectContext* context);
AzPhysics::CollisionGroups::Id m_collisionGroupId; ///< Which layers does this character collide with.
AzPhysics::CollisionLayer m_collisionLayer; ///< Which collision layer is this character on.
MaterialSelection m_materialSelection; ///< Material selected from library for the body associated with the character.
AZ::Vector3 m_upDirection = AZ::Vector3::CreateAxisZ(); ///< Up direction for character orientation and step behavior.
float m_maximumSlopeAngle = 30.0f; ///< The maximum slope on which the character can move, in degrees.
float m_stepHeight = 0.5f; ///< Affects what size steps the character can climb.
float m_minimumMovementDistance = 0.001f; ///< To avoid jittering, the controller will not attempt to move distances below this.
float m_maximumSpeed = 100.0f; ///< If the accumulated requested velocity for a tick exceeds this magnitude, it will be clamped.
AZStd::string m_colliderTag; ///< Used to identify the collider associated with the character controller.
AzPhysics::CollisionGroups::Id m_collisionGroupId; //!< Which layers does this character collide with.
AzPhysics::CollisionLayer m_collisionLayer; //!< Which collision layer is this character on.
MaterialSelection m_materialSelection; //!< Material selected from library for the body associated with the character.
AZ::Vector3 m_upDirection = AZ::Vector3::CreateAxisZ(); //!< Up direction for character orientation and step behavior.
float m_maximumSlopeAngle = 30.0f; //!< The maximum slope on which the character can move, in degrees.
float m_stepHeight = 0.5f; //!< Affects what size steps the character can climb.
float m_minimumMovementDistance = 0.001f; //!< To avoid jittering, the controller will not attempt to move distances below this.
float m_maximumSpeed = 100.0f; //!< If the accumulated requested velocity for a tick exceeds this magnitude, it will be clamped.
AZStd::string m_colliderTag; //!< Used to identify the collider associated with the character controller.
AZStd::shared_ptr<Physics::ShapeConfiguration> m_shapeConfig = nullptr; //!< The shape to use when creating the character controller.
AZStd::vector<AZStd::shared_ptr<Physics::Shape>> m_colliders; //!< The list of colliders to attach to the character controller.
};
/// Basic implementation of common character-style needs as a WorldBody. Is not a full-functional ship-ready
@@ -88,7 +90,7 @@ namespace Physics
{
public:
AZ_CLASS_ALLOCATOR(Character, AZ::SystemAllocator, 0);
AZ_RTTI(Character, "{962E37A1-3401-4672-B896-0A6157CFAC97}", AzPhysics::SimulatedBody);
AZ_RTTI(Physics::Character, "{962E37A1-3401-4672-B896-0A6157CFAC97}", AzPhysics::SimulatedBody);
~Character() override = default;
@@ -29,7 +29,7 @@ namespace AzPhysics
struct SimulatedBodyConfiguration
{
AZ_CLASS_ALLOCATOR_DECL;
AZ_RTTI(SimulatedBodyConfiguration, "{52844E3D-79C8-4F34-AF63-5C45ADE77F85}");
AZ_RTTI(AzPhysics::SimulatedBodyConfiguration, "{52844E3D-79C8-4F34-AF63-5C45ADE77F85}");
static void Reflect(AZ::ReflectContext* context);
SimulatedBodyConfiguration() = default;
@@ -246,26 +246,6 @@ namespace Physics
using SystemRequests = System;
using SystemRequestBus = AZ::EBus<SystemRequests, SystemRequestsTraits>;
/// Physics character system global requests.
class CharacterSystemRequests
: public AZ::EBusTraits
{
public:
// EBusTraits
// singleton pattern
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
virtual ~CharacterSystemRequests() = default;
/// Creates the physics representation used to handle basic character interactions (also known as a character
/// controller).
virtual AZStd::unique_ptr<Character> CreateCharacter(const CharacterConfiguration& characterConfig,
const ShapeConfiguration& shapeConfig, AzPhysics::SceneHandle& sceneHandle) = 0;
};
typedef AZ::EBus<CharacterSystemRequests> CharacterSystemRequestBus;
/// Physics system global debug requests.
class SystemDebugRequests
: public AZ::EBusTraits
@@ -37,6 +37,7 @@ namespace AzFramework
// ViewportControllerInterface ...
bool HandleInputChannelEvent(const ViewportControllerInputEvent& event) override;
void ResetInputChannels() override;
void UpdateViewport(const ViewportControllerUpdateEvent& event) override;
void RegisterViewportContext(ViewportId viewport) override;
void UnregisterViewportContext(ViewportId viewport) override;
@@ -58,6 +59,7 @@ namespace AzFramework
ViewportId GetViewportId() const { return m_viewportId; }
virtual bool HandleInputChannelEvent([[maybe_unused]]const ViewportControllerInputEvent& event) { return false; }
virtual void ResetInputChannels() {}
virtual void UpdateViewport([[maybe_unused]]const ViewportControllerUpdateEvent& event) {}
private:
@@ -30,6 +30,15 @@ namespace AzFramework
return instanceIt->second->HandleInputChannelEvent(event);
}
template <class TViewportControllerInstance, ViewportControllerPriority Priority>
void MultiViewportController<TViewportControllerInstance, Priority>::ResetInputChannels()
{
for (auto instanceIt = m_instances.begin(); instanceIt != m_instances.end(); ++instanceIt)
{
instanceIt->second->ResetInputChannels();
}
}
template <class TViewportControllerInstance, ViewportControllerPriority Priority>
void MultiViewportController<TViewportControllerInstance, Priority>::UpdateViewport(const ViewportControllerUpdateEvent& event)
{
@@ -49,6 +49,11 @@ namespace AzFramework
bool ViewportControllerList::HandleInputChannelEvent(const AzFramework::ViewportControllerInputEvent& event)
{
if (!IsEnabled())
{
return false;
}
// If our event priority is "custom", we should dispatch at all priority levels in order
using AzFramework::ViewportControllerPriority;
if (event.m_priority == AzFramework::ViewportControllerPriority::DispatchToAllPriorities)
@@ -76,6 +81,23 @@ namespace AzFramework
}
}
void ViewportControllerList::ResetInputChannels()
{
// We don't need to send this while we're disabled, we're guaranteed to call ResetInputChannels after being re-enabled.
if (!IsEnabled())
{
return;
}
for (const auto& controllerList : m_controllers)
{
for (const auto& controller : controllerList.second)
{
controller->ResetInputChannels();
}
}
}
bool ViewportControllerList::DispatchInputChannelEvent(const AzFramework::ViewportControllerInputEvent& event)
{
if (auto priorityListIt = m_controllers.find(event.m_priority); priorityListIt != m_controllers.end())
@@ -106,6 +128,11 @@ namespace AzFramework
void ViewportControllerList::UpdateViewport(const AzFramework::ViewportControllerUpdateEvent& event)
{
if (!IsEnabled())
{
return;
}
// If our event priority is "custom", we should dispatch at all priority levels in reverse order
// Reverse order lets high priority controllers get the last say in viewport update operations
using AzFramework::ViewportControllerPriority;
@@ -174,4 +201,22 @@ namespace AzFramework
}
}
}
bool ViewportControllerList::IsEnabled() const
{
return m_enabled;
}
void ViewportControllerList::SetEnabled(bool enabled)
{
if (m_enabled != enabled)
{
m_enabled = enabled;
// If we've been re-enabled, reset our input channels as they may have missed state changes.
if (m_enabled)
{
ResetInputChannels();
}
}
}
} //namespace AzFramework
@@ -37,6 +37,9 @@ namespace AzFramework
//! either a controller returns true to consume the event in OnInputChannelEvent or the controller list is exhausted.
//! InputChannelEvents are sent to controllers in priority order (from the lowest priority value to the highest).
bool HandleInputChannelEvent(const AzFramework::ViewportControllerInputEvent& event) override;
//! Dispatches a ResetInputChannels call to all controllers registered to this list.
//! Calls to controllers are made in an undefined order.
void ResetInputChannels() override;
//! Dispatches an update tick to all controllers registered to this list.
//! This occurs in *reverse* priority order (i.e. from the highest priority value to the lowest) so that
//! controllers with the highest registration priority may override the transforms of the controllers with the
@@ -50,6 +53,12 @@ namespace AzFramework
//! All ViewportControllerLists have a priority of Custom to ensure
//! that they receive events at all priorities from any parent controllers.
AzFramework::ViewportControllerPriority GetPriority() const { return ViewportControllerPriority::DispatchToAllPriorities; }
//! Returns true if this controller list is enabled, i.e.
//! it is accepting and forwarding input and update events to its children.
bool IsEnabled() const;
//! Set this controller list's enabled state.
//! If a controller list is disabled, it will ignore all input and update events rather than dispatching them to its children.
void SetEnabled(bool enabled);
private:
void SortControllers();
@@ -58,5 +67,6 @@ namespace AzFramework
AZStd::unordered_map<AzFramework::ViewportControllerPriority, AZStd::vector<ViewportControllerPtr>> m_controllers;
AZStd::unordered_set<ViewportId> m_viewports;
bool m_enabled = true;
};
} //namespace AzFramework
+2 -2
View File
@@ -33,12 +33,12 @@ ly_add_target(
BUILD_DEPENDENCIES
PRIVATE
AZ::AzCore
PUBLIC
AZ::GridMate
3rdParty::md5
3rdParty::zlib
3rdParty::zstd
3rdParty::lz4
PUBLIC
AZ::GridMate
)
if(LY_ENABLE_STATISTICAL_PROFILING)
@@ -29,6 +29,20 @@ namespace AzFramework::AssetSystem::Platform
bool LaunchAssetProcessor(AZStd::string_view executableDirectory, AZStd::string_view engineRoot,
AZStd::string_view projectPath)
{
AZ::IO::FixedMaxPath assetProcessorPath{ executableDirectory };
assetProcessorPath /= "AssetProcessor";
if (!AZ::IO::SystemFile::Exists(assetProcessorPath.c_str()))
{
// Check for existence of one under a "bin" directory, i.e. engineRoot is an SDK structure.
assetProcessorPath = AZ::IO::FixedMaxPath{engineRoot} / "bin" / AZ_BUILD_CONFIGURATION_TYPE / "AssetProcessor";
if (!AZ::IO::SystemFile::Exists(assetProcessorPath.c_str()))
{
return false;
}
}
pid_t firstChildPid = fork();
if (firstChildPid == 0)
{
@@ -47,9 +61,6 @@ namespace AzFramework::AssetSystem::Platform
pid_t secondChildPid = fork();
if (secondChildPid == 0)
{
AZ::IO::FixedMaxPath assetProcessorPath{ executableDirectory };
assetProcessorPath /= "AssetProcessor";
AZStd::array args {
assetProcessorPath.c_str(), assetProcessorPath.c_str(), "--start-hidden",
static_cast<const char*>(nullptr), static_cast<const char*>(nullptr), static_cast<const char*>(nullptr)
@@ -11,6 +11,7 @@
*/
#include <AzCore/IO/Path/Path.h>
#include <AzCore/IO/SystemFile.h>
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
#include <sys/types.h>
@@ -20,6 +21,7 @@ namespace AzFramework::AssetSystem::Platform
{
void AllowAssetProcessorToForeground()
{}
bool LaunchAssetProcessor(AZStd::string_view executableDirectory, AZStd::string_view engineRoot,
AZStd::string_view projectPath)
{
@@ -29,6 +31,17 @@ namespace AzFramework::AssetSystem::Platform
assetProcessorPath /= "../../../AssetProcessor.app";
assetProcessorPath = assetProcessorPath.LexicallyNormal();
if (!AZ::IO::SystemFile::Exists(assetProcessorPath.c_str()))
{
// Check for existence of one under a "bin" directory, i.e. engineRoot is an SDK structure.
assetProcessorPath = AZ::IO::FixedMaxPath{engineRoot} / "bin" / AZ_BUILD_CONFIGURATION_TYPE / "AssetProcessor.app";
if (!AZ::IO::SystemFile::Exists(assetProcessorPath.c_str()))
{
return false;
}
}
auto fullLaunchCommand = AZ::IO::FixedMaxPathString::format(R"(open -g "%s" --args --start-hidden)", assetProcessorPath.c_str());
// Add the engine path to the launch command if not empty
if (!engineRoot.empty())
@@ -12,6 +12,7 @@
#include <AzCore/PlatformIncl.h>
#include <AzCore/IO/Path/Path.h>
#include <AzCore/IO/SystemFile.h>
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
#include <Psapi.h>
@@ -67,6 +68,17 @@ namespace AzFramework::AssetSystem::Platform
AZ::IO::FixedMaxPath assetProcessorPath{ executableDirectory };
assetProcessorPath /= "AssetProcessor.exe";
if (!AZ::IO::SystemFile::Exists(assetProcessorPath.c_str()))
{
// Check for existence of one under a "bin" directory, i.e. engineRoot is an SDK structure.
assetProcessorPath = AZ::IO::FixedMaxPath{engineRoot} / "bin" / AZ_BUILD_CONFIGURATION_TYPE / "AssetProcessor.exe";
if (!AZ::IO::SystemFile::Exists(assetProcessorPath.c_str()))
{
return false;
}
}
auto fullLaunchCommand = AZ::IO::FixedMaxPathString::format(R"("%s" --start-hidden)", assetProcessorPath.c_str());
// Add the engine path to the launch command if not empty
@@ -18,6 +18,8 @@
#include <AzCore/std/typetraits/is_enum.h>
#include <AzCore/RTTI/TypeInfo.h>
#include <AzCore/RTTI/TypeSafeIntegral.h>
#include <AzCore/Name/Name.h>
#include <AzCore/Name/NameDictionary.h>
namespace AzNetworking
{
@@ -173,6 +175,22 @@ namespace AzNetworking
return true;
}
};
template<>
struct SerializeObjectHelper<AZ::Name>
{
static bool SerializeObject(ISerializer& serializer, AZ::Name& value)
{
AZ::Name::Hash nameHash = value.GetHash();
bool result = serializer.Serialize(nameHash, "NameHash");
if (result && serializer.GetSerializerMode() == SerializerMode::WriteToObject)
{
value = AZ::NameDictionary::Instance().FindName(nameHash);
}
return result;
}
};
}
#include <AzNetworking/Serialization/AzContainerSerializers.h>
@@ -2298,6 +2298,12 @@ namespace AzQtComponents
OptimizedSetParent(dock, mainWindow);
mainWindow->addDockWidget(Qt::LeftDockWidgetArea, dock);
dock->show();
// Make sure we listen for events on the dock widget being put into a floating dock window
// because this might be called programmatically, so the dock widget might have never been
// parented to our m_mainWindow initially, so it won't already have an event filter,
// which will prevent the docking functionality from working.
dock->installEventFilter(this);
}
}
@@ -815,8 +815,6 @@ namespace AzToolsFramework
/// Hide or show the circular dependency error when saving slices
virtual void SetShowCircularDependencyError(const bool& /*showCircularDependencyError*/) {}
virtual void SetEditTool(const char* /*tool*/) {}
/// Launches the Lua editor and opens the specified (space separated) files.
virtual void LaunchLuaEditor(const char* /*files*/) {}
@@ -170,6 +170,15 @@ namespace AzToolsFramework
return m_filter;
}
QSharedPointer<CompositeFilter> SearchWidget::GetStringFilter() const
{
return m_stringFilter;
}
QSharedPointer<CompositeFilter> SearchWidget::GetTypesFilter() const
{
return m_typesFilter;
}
} // namespace AssetBrowser
} // namespace AzToolsFramework
@@ -39,6 +39,10 @@ namespace AzToolsFramework
QSharedPointer<CompositeFilter> GetFilter() const;
QSharedPointer<CompositeFilter> GetStringFilter() const;
QSharedPointer<CompositeFilter> GetTypesFilter() const;
QString GetFilterString() const { return textFilter(); }
void ClearStringFilter() { ClearTextFilter(); }
@@ -140,7 +140,7 @@ namespace AzToolsFramework
else
{
QPixmap pixmap = thumbnail->GetPixmap(size);
painter->drawPixmap(point.x(), point.y(), size.width(), size.height(), pixmap);
painter->drawPixmap(point, pixmap.scaled(size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
}
return m_iconSize;
}
@@ -491,6 +491,14 @@ namespace AzToolsFramework
EditorEntityContextNotificationBus::Broadcast(&EditorEntityContextNotification::OnStartPlayInEditorBegin);
//cache the current selected entities.
ToolsApplicationRequests::Bus::BroadcastResult(m_selectedBeforeStartingGame, &ToolsApplicationRequests::GetSelectedEntities);
//deselect entities if selected when entering game mode before deactivating the entities in StartPlayInEditor(...)
if (!m_selectedBeforeStartingGame.empty())
{
ToolsApplicationRequests::Bus::Broadcast(&ToolsApplicationRequests::MarkEntitiesDeselected, m_selectedBeforeStartingGame);
}
if (m_isLegacySliceService)
{
SliceEditorEntityOwnershipService* editorEntityOwnershipService =
@@ -507,8 +515,6 @@ namespace AzToolsFramework
m_isRunningGame = true;
ToolsApplicationRequests::Bus::BroadcastResult(m_selectedBeforeStartingGame, &ToolsApplicationRequests::GetSelectedEntities);
EditorEntityContextNotificationBus::Broadcast(&EditorEntityContextNotification::OnStartPlayInEditor);
}
@@ -94,6 +94,7 @@ namespace AzToolsFramework
m_prefabSystemComponent->RemoveTemplate(templateId);
}
m_rootInstance->Reset();
m_rootInstance->SetContainerEntityName("Level");
AzFramework::EntityOwnershipServiceNotificationBus::Event(
m_entityContextId, &AzFramework::EntityOwnershipServiceNotificationBus::Events::OnEntityOwnershipServiceReset);
@@ -198,6 +199,7 @@ namespace AzToolsFramework
m_rootInstance->SetTemplateId(templateId);
m_rootInstance->SetTemplateSourcePath(m_loaderInterface->GetRelativePathToProject(filename));
m_rootInstance->SetContainerEntityName("Level");
m_prefabSystemComponent->PropagateTemplateChanges(templateId);
return true;
@@ -123,7 +123,11 @@ namespace AzToolsFramework
void Instance::SetTemplateSourcePath(AZ::IO::PathView sourcePath)
{
m_templateSourcePath = sourcePath;
m_containerEntity->SetName(sourcePath.Filename().Native());
}
void Instance::SetContainerEntityName(AZStd::string_view containerName)
{
m_containerEntity->SetName(containerName);
}
bool Instance::AddEntity(AZ::Entity& entity)
@@ -570,7 +574,7 @@ namespace AzToolsFramework
AZ::EntityId Instance::GetContainerEntityId() const
{
return m_containerEntity->GetId();
return m_containerEntity ? m_containerEntity->GetId() : AZ::EntityId();
}
bool Instance::HasContainerEntity() const
@@ -80,6 +80,7 @@ namespace AzToolsFramework
const AZ::IO::Path& GetTemplateSourcePath() const;
void SetTemplateSourcePath(AZ::IO::PathView sourcePath);
void SetContainerEntityName(AZStd::string_view containerName);
bool AddEntity(AZ::Entity& entity);
bool AddEntity(AZ::Entity& entity, EntityAlias entityAlias);
@@ -709,7 +709,7 @@ namespace AzToolsFramework
InstanceOptionalReference owningInstance = m_instanceEntityMapperInterface->FindOwningInstance(entity->GetId());
AZ_Assert(
owningInstance.has_value(),
"An error occored while retrieving entities and prefab instances : "
"An error occurred while retrieving entities and prefab instances : "
"Owning instance of entity with id '%llu' couldn't be found",
entity->GetId());
@@ -793,7 +793,7 @@ namespace AzToolsFramework
{
AZ_Assert(
false,
"An error occored in function EntitiesBelongToSameInstance: "
"An error occurred in function EntitiesBelongToSameInstance: "
"Owning instance of entity with id '%llu' couldn't be found",
entityId);
return false;
@@ -122,6 +122,7 @@ namespace AzToolsFramework
}
newInstance->SetTemplateSourcePath(relativeFilePath);
newInstance->SetContainerEntityName(relativeFilePath.Stem().Native());
TemplateId newTemplateId = CreateTemplateFromInstance(*newInstance, shouldCreateLinks);
if (newTemplateId == InvalidTemplateId)
@@ -10,12 +10,14 @@
*
*/
#include <AzToolsFramework/Thumbnails/ThumbnailerBus.h>
#include <AzToolsFramework/Thumbnails/Thumbnail.h>
AZ_PUSH_DISABLE_WARNING(4127 4251 4800 4244, "-Wunknown-warning-option") // 4127: conditional expression is constant
// 4251: 'QTextCodec::ConverterState::flags': class 'QFlags<QTextCodec::ConversionFlag>' needs to have dll-interface to be used by clients of struct 'QTextCodec::ConverterState'
// 4800: 'QTextBoundaryFinderPrivate *const ': forcing value to bool 'true' or 'false' (performance warning)
// 4244: conversion from 'int' to 'qint8', possible loss of data
#include <QtConcurrent/QtConcurrent>
#include <QThreadPool>
AZ_POP_DISABLE_WARNING
namespace AzToolsFramework
@@ -80,7 +82,11 @@ namespace AzToolsFramework
if (m_state == State::Unloaded)
{
m_state = State::Loading;
QFuture<void> future = QtConcurrent::run([this](){ LoadThread(); });
QThreadPool* threadPool;
ThumbnailContextRequestBus::BroadcastResult(
threadPool,
&ThumbnailContextRequestBus::Handler::GetThreadPool);
QFuture<void> future = QtConcurrent::run(threadPool, [this](){ LoadThread(); });
m_watcher.setFuture(future);
}
}
@@ -28,10 +28,15 @@ namespace AzToolsFramework
: m_missingThumbnail(new MissingThumbnail(thumbnailSize))
, m_loadingThumbnail(new LoadingThumbnail(thumbnailSize))
, m_thumbnailSize(thumbnailSize)
, m_threadPool(this)
{
ThumbnailContextRequestBus::Handler::BusConnect();
}
ThumbnailContext::~ThumbnailContext() = default;
ThumbnailContext::~ThumbnailContext()
{
ThumbnailContextRequestBus::Handler::BusDisconnect();
}
bool ThumbnailContext::IsLoading(SharedThumbnailKey key)
{
@@ -53,6 +58,11 @@ namespace AzToolsFramework
AzToolsFramework::AssetBrowser::AssetBrowserViewRequestBus::Broadcast(&AzToolsFramework::AssetBrowser::AssetBrowserViewRequests::Update);
}
QThreadPool* ThumbnailContext::GetThreadPool()
{
return &m_threadPool;
}
SharedThumbnail ThumbnailContext::GetThumbnail(SharedThumbnailKey key)
{
SharedThumbnail thumbnail;
@@ -19,6 +19,7 @@
#include <QObject>
#include <QList>
#include <QThreadPool>
#endif
class QString;
@@ -40,6 +41,7 @@ namespace AzToolsFramework
*/
class ThumbnailContext
: public QObject
, public ThumbnailContextRequestBus::Handler
{
Q_OBJECT
public:
@@ -58,10 +60,13 @@ namespace AzToolsFramework
void UnregisterThumbnailProvider(const char* providerName);
void RedrawThumbnail();
//! Default context used for most thumbnails
static constexpr const char* DefaultContext = "Default";
// ThumbnailContextRequestBus::Handler interface overrides...
QThreadPool* GetThreadPool() override;
private:
struct ProviderCompare {
bool operator() (const SharedThumbnailProvider& lhs, const SharedThumbnailProvider& rhs) const
@@ -79,6 +84,9 @@ namespace AzToolsFramework
SharedThumbnail m_loadingThumbnail;
//! Thumbnail size (width and height in pixels)
int m_thumbnailSize;
//! There is only a limited number of threads on global threadPool, because there can be many thumbnails rendering at once
//! an individual threadPool is needed to avoid deadlocks
QThreadPool m_threadPool;
};
} // namespace Thumbnailer
} // namespace AzToolsFramework
@@ -79,7 +79,12 @@ namespace AzToolsFramework
int realHeight = qMin(aznumeric_cast<int>(originalWidth /aspectRatio), originalHeight);
int realWidth = aznumeric_cast<int>(realHeight * aspectRatio);
int x = (originalWidth - realWidth) / 2;
painter.drawPixmap(QRect(x, 0, realHeight, realWidth), pixmap);
// pixmap needs to be manually scaled to produce smoother result and avoid looking pixelated
// using painter.setRenderHint(QPainter::SmoothPixmapTransform); does not seem to work
// Note: there is a potential issue with pixmap.scaled:
// it is multithreaded (using global threadPool) and blocking until finished.
// A deadlock will happen if global threadPool has no free threads available.
painter.drawPixmap(QPoint(x, 0), pixmap.scaled(realWidth, realHeight, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
}
QWidget::paintEvent(event);
}
@@ -17,11 +17,23 @@
#include <AzToolsFramework/Thumbnails/Thumbnail.h>
class QPixmap;
class QThreadPool;
namespace AzToolsFramework
{
namespace Thumbnailer
{
//! Interaction with thumbnail context
class ThumbnailContextRequests
: public AZ::EBusTraits
{
public:
//! Get thread pool for drawing thumbnails
virtual QThreadPool* GetThreadPool() = 0;
};
using ThumbnailContextRequestBus = AZ::EBus<ThumbnailContextRequests>;
//! Interaction with thumbnailer
class ThumbnailerRequests
: public AZ::EBusTraits
@@ -61,6 +61,11 @@ namespace AzToolsFramework
return true;
}
bool EditorEntityUiHandlerBase::CanRename(AZ::EntityId /*entityId*/) const
{
return true;
}
void EditorEntityUiHandlerBase::PaintItemBackground(QPainter* /*painter*/, const QStyleOptionViewItem& /*option*/, const QModelIndex& /*index*/) const
{
}
@@ -47,6 +47,8 @@ namespace AzToolsFramework
virtual QPixmap GenerateItemIcon(AZ::EntityId entityId) const;
//! Returns whether the element's lock and visibility state should be accessible in the Outliner
virtual bool CanToggleLockVisibility(AZ::EntityId entityId) const;
//! Returns whether the element's name should be editable
virtual bool CanRename(AZ::EntityId entityId) const;
//! Paints the background of the item in the Outliner.
virtual void PaintItemBackground(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const;
@@ -192,6 +192,10 @@ namespace LegacyFramework
// if we're in console mode, listen for CTRL+C
::SetConsoleCtrlHandler(CTRL_BREAK_HandlerRoutine, true);
#endif
m_ptrCommandLineParser = aznew AzFramework::CommandLine();
m_ptrCommandLineParser->Parse(m_desc.m_argc, m_desc.m_argv);
// If we don't have one create a serialize context
if (GetSerializeContext() == nullptr)
{
@@ -945,6 +945,12 @@ namespace AzToolsFramework
return false;
}
// Disable reparenting to the root level
if (!newParentId.IsValid())
{
return false;
}
// Ignore entities not owned by the editor context. It is assumed that all entities belong
// to the same context since multiple selection doesn't span across views.
for (const AZ::EntityId& entityId : selectedEntityIds)
@@ -974,39 +980,33 @@ namespace AzToolsFramework
}
}
if (newParentId.IsValid())
bool isLayerEntity = false;
Layers::EditorLayerComponentRequestBus::EventResult(
isLayerEntity,
entityId,
&Layers::EditorLayerComponentRequestBus::Events::HasLayer);
// Layers can only have other layers as parents, or have no parent.
if (isLayerEntity)
{
bool isLayerEntity = false;
bool newParentIsLayer = false;
Layers::EditorLayerComponentRequestBus::EventResult(
isLayerEntity,
entityId,
newParentIsLayer,
newParentId,
&Layers::EditorLayerComponentRequestBus::Events::HasLayer);
// Layers can only have other layers as parents, or have no parent.
if (isLayerEntity)
if (!newParentIsLayer)
{
bool newParentIsLayer = false;
Layers::EditorLayerComponentRequestBus::EventResult(
newParentIsLayer,
newParentId,
&Layers::EditorLayerComponentRequestBus::Events::HasLayer);
if (!newParentIsLayer)
{
return false;
}
return false;
}
}
}
//Only check the entity pointer if the entity id is valid because
//we want to allow dragging items to unoccupied parts of the tree to un-parent them
if (newParentId.IsValid())
AZ::Entity* newParentEntity = nullptr;
AZ::ComponentApplicationBus::BroadcastResult(newParentEntity, &AZ::ComponentApplicationRequests::FindEntity, newParentId);
if (!newParentEntity)
{
AZ::Entity* newParentEntity = nullptr;
AZ::ComponentApplicationBus::BroadcastResult(newParentEntity, &AZ::ComponentApplicationRequests::FindEntity, newParentId);
if (!newParentEntity)
{
return false;
}
return false;
}
//reject dragging on to yourself or your children
@@ -1344,14 +1344,15 @@ namespace AzToolsFramework
emit EnableSelectionUpdates(false);
auto parentIndex = GetIndexFromEntity(parentId);
auto childIndex = GetIndexFromEntity(childId);
beginRemoveRows(parentIndex, childIndex.row(), childIndex.row());
beginResetModel();
}
void EntityOutlinerListModel::OnEntityInfoUpdatedRemoveChildEnd(AZ::EntityId parentId, AZ::EntityId childId)
{
(void)childId;
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzToolsFramework);
endRemoveRows();
endResetModel();
//must refresh partial lock/visibility of parents
m_isFilterDirty = true;
@@ -30,6 +30,7 @@
#include <AzToolsFramework/Entity/EditorEntityHelpers.h>
#include <AzToolsFramework/Entity/EditorEntityInfoBus.h>
#include <AzToolsFramework/UI/ComponentPalette/ComponentPaletteUtil.hxx>
#include <AzToolsFramework/UI/EditorEntityUi/EditorEntityUiHandlerBase.h>
#include <AzToolsFramework/UI/Outliner/EntityOutlinerDisplayOptionsMenu.h>
#include <AzToolsFramework/UI/Outliner/EntityOutlinerListModel.hxx>
#include <AzToolsFramework/UI/Outliner/EntityOutlinerSortFilterProxyModel.hxx>
@@ -271,6 +272,12 @@ 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();
@@ -562,7 +569,13 @@ namespace AzToolsFramework
if (m_selectedEntityIds.size() == 1)
{
contextMenu->addAction(m_actionToRenameSelection);
auto entityId = m_selectedEntityIds.front();
auto entityUiHandler = m_editorEntityUiInterface->GetHandler(entityId);
if (!entityUiHandler || entityUiHandler->CanRename(entityId))
{
contextMenu->addAction(m_actionToRenameSelection);
}
}
if (m_selectedEntityIds.size() == 1)
@@ -688,11 +701,17 @@ namespace AzToolsFramework
if (m_selectedEntityIds.size() == 1)
{
const QModelIndex proxyIndex = GetIndexFromEntityId(m_selectedEntityIds.front());
if (proxyIndex.isValid())
auto entityId = m_selectedEntityIds.front();
auto entityUiHandler = m_editorEntityUiInterface->GetHandler(entityId);
if (!entityUiHandler || entityUiHandler->CanRename(entityId))
{
m_gui->m_objectTree->setCurrentIndex(proxyIndex);
m_gui->m_objectTree->QTreeView::edit(proxyIndex);
const QModelIndex proxyIndex = GetIndexFromEntityId(entityId);
if (proxyIndex.isValid())
{
m_gui->m_objectTree->setCurrentIndex(proxyIndex);
m_gui->m_objectTree->QTreeView::edit(proxyIndex);
}
}
}
}
@@ -42,6 +42,7 @@ namespace Ui
namespace AzToolsFramework
{
class EditorEntityUiInterface;
class EntityOutlinerListModel;
class EntityOutlinerSortFilterProxyModel;
@@ -193,6 +194,8 @@ namespace AzToolsFramework
EntityIdSet m_entitiesToSort;
EntityOutliner::DisplaySortMode m_sortMode;
bool m_sortContentQueued;
EditorEntityUiInterface* m_editorEntityUiInterface = nullptr;
};
}
@@ -50,11 +50,31 @@ namespace AzToolsFramework
return QPixmap(m_levelRootIconPath);
}
QString LevelRootUiHandler::GenerateItemInfoString(AZ::EntityId entityId) const
{
QString infoString;
AZ::IO::Path path = m_prefabPublicInterface->GetOwningInstancePrefabPath(entityId);
if (!path.empty())
{
infoString =
QObject::tr("<span style=\"font-style: italic; font-weight: 400;\">(%1)</span>").arg(path.Filename().Native().data());
}
return infoString;
}
bool LevelRootUiHandler::CanToggleLockVisibility(AZ::EntityId /*entityId*/) const
{
return false;
}
bool LevelRootUiHandler::CanRename(AZ::EntityId /*entityId*/) const
{
return false;
}
void LevelRootUiHandler::PaintItemBackground(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& /*index*/) const
{
if (!painter)
@@ -34,7 +34,9 @@ namespace AzToolsFramework
// EditorEntityUiHandler...
QPixmap GenerateItemIcon(AZ::EntityId entityId) const override;
QString GenerateItemInfoString(AZ::EntityId entityId) const override;
bool CanToggleLockVisibility(AZ::EntityId entityId) const override;
bool CanRename(AZ::EntityId entityId) const override;
void PaintItemBackground(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
private:
@@ -310,6 +310,9 @@ namespace AzToolsFramework
{
initEntityPropertyEditorResources();
m_prefabPublicInterface = AZ::Interface<Prefab::PrefabPublicInterface>::Get();
AZ_Assert(m_prefabPublicInterface != nullptr, "EntityPropertyEditor requires a PrefabPublicInterface instance on Initialize.");
setObjectName("EntityPropertyEditor");
setAcceptDrops(true);
@@ -405,8 +408,6 @@ namespace AzToolsFramework
CreateActions();
UpdateContents();
m_prefabPublicInterface = AZ::Interface<Prefab::PrefabPublicInterface>::Get();
EditorEntityContextNotificationBus::Handler::BusConnect();
//forced to register global event filter with application for selection
@@ -693,11 +694,38 @@ namespace AzToolsFramework
m_gui->m_entityIcon->repaint();
}
EntityPropertyEditor::InspectorLayout EntityPropertyEditor::GetCurrentInspectorLayout() const
{
if (!m_prefabsAreEnabled)
{
return m_isLevelEntityEditor ? InspectorLayout::LEVEL : InspectorLayout::ENTITY;
}
AZ::EntityId levelContainerEntityId = m_prefabPublicInterface->GetLevelInstanceContainerEntityId();
if (AZStd::find(m_selectedEntityIds.begin(), m_selectedEntityIds.end(), levelContainerEntityId) != m_selectedEntityIds.end())
{
if (m_selectedEntityIds.size() > 1)
{
return InspectorLayout::INVALID;
}
else
{
return InspectorLayout::LEVEL;
}
}
else
{
return InspectorLayout::ENTITY;
}
}
void EntityPropertyEditor::UpdateEntityDisplay()
{
UpdateStatusComboBox();
if (m_isLevelEntityEditor)
InspectorLayout layout = GetCurrentInspectorLayout();
if (layout == InspectorLayout::LEVEL)
{
AZStd::string levelName;
AzToolsFramework::EditorRequestBus::BroadcastResult(levelName, &AzToolsFramework::EditorRequests::GetLevelName);
@@ -737,13 +765,20 @@ namespace AzToolsFramework
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzToolsFramework);
SelectionEntityTypeInfo result = SelectionEntityTypeInfo::None;
if (m_isLevelEntityEditor)
InspectorLayout layout = GetCurrentInspectorLayout();
if (layout == InspectorLayout::LEVEL)
{
// The Level Inspector should only have a list of selectable components after the
// level entity itself is valid (i.e. "selected").
return selection.empty() ? SelectionEntityTypeInfo::None : SelectionEntityTypeInfo::LevelEntity;
}
if (layout == InspectorLayout::INVALID)
{
return SelectionEntityTypeInfo::Mixed;
}
for (AZ::EntityId selectedEntityId : selection)
{
bool isLayerEntity = false;
@@ -909,16 +944,18 @@ namespace AzToolsFramework
}
}
bool isLevelLayout = GetCurrentInspectorLayout() == InspectorLayout::LEVEL;
m_gui->m_entityDetailsLabel->setText(entityDetailsLabelText);
m_gui->m_entityDetailsLabel->setVisible(entityDetailsVisible);
m_gui->m_entityNameEditor->setVisible(hasEntitiesDisplayed);
m_gui->m_entityNameLabel->setVisible(hasEntitiesDisplayed);
m_gui->m_entityIcon->setVisible(hasEntitiesDisplayed);
m_gui->m_pinButton->setVisible(m_overrideSelectedEntityIds.empty() && hasEntitiesDisplayed && !m_isSystemEntityEditor && !m_isLevelEntityEditor);
m_gui->m_statusLabel->setVisible(hasEntitiesDisplayed && !m_isSystemEntityEditor && !m_isLevelEntityEditor);
m_gui->m_statusComboBox->setVisible(hasEntitiesDisplayed && !m_isSystemEntityEditor && !m_isLevelEntityEditor);
m_gui->m_entityIdLabel->setVisible(hasEntitiesDisplayed && !m_isSystemEntityEditor && !m_isLevelEntityEditor);
m_gui->m_entityIdText->setVisible(hasEntitiesDisplayed && !m_isSystemEntityEditor && !m_isLevelEntityEditor);
m_gui->m_pinButton->setVisible(m_overrideSelectedEntityIds.empty() && hasEntitiesDisplayed && !m_isSystemEntityEditor);
m_gui->m_statusLabel->setVisible(hasEntitiesDisplayed && !m_isSystemEntityEditor && !isLevelLayout);
m_gui->m_statusComboBox->setVisible(hasEntitiesDisplayed && !m_isSystemEntityEditor && !isLevelLayout);
m_gui->m_entityIdLabel->setVisible(hasEntitiesDisplayed && !m_isSystemEntityEditor && !isLevelLayout);
m_gui->m_entityIdText->setVisible(hasEntitiesDisplayed && !m_isSystemEntityEditor && !isLevelLayout);
bool displayComponentSearchBox = hasEntitiesDisplayed;
if (hasEntitiesDisplayed)
@@ -941,7 +978,7 @@ namespace AzToolsFramework
UpdateEntityDisplay();
}
m_gui->m_darkBox->setVisible(displayComponentSearchBox && !m_isSystemEntityEditor && !m_isLevelEntityEditor);
m_gui->m_darkBox->setVisible(displayComponentSearchBox && !m_isSystemEntityEditor && !isLevelLayout);
m_gui->m_entitySearchBox->setVisible(displayComponentSearchBox);
bool displayAddComponentMenu = CanAddComponentsToSelection(selectionEntityTypeInfo);
@@ -521,6 +521,15 @@ namespace AzToolsFramework
bool m_isSystemEntityEditor;
bool m_isLevelEntityEditor = false;
enum class InspectorLayout
{
ENTITY = 0, // All selected entities are regular entities
LEVEL, // The selected entity is the level prefab container entity
INVALID // Other entities are selected alongside the level prefab container entity
};
InspectorLayout GetCurrentInspectorLayout() const;
// the spacer's job is to make sure that its always at the end of the list of components.
QSpacerItem* m_spacer;
bool m_isAlreadyQueuedRefresh;
+2 -1
View File
@@ -28,8 +28,9 @@ ly_add_target(
${pal_dir}
BUILD_DEPENDENCIES
PRIVATE
3rdParty::OpenSSL
AZ::AzCore
PUBLIC
3rdParty::OpenSSL
)
ly_add_source_properties(