Merge branch 'main' into Prefab/CreatePrefab
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)->
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
+14
-3
@@ -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)
|
||||
|
||||
+13
@@ -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
@@ -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(); }
|
||||
|
||||
|
||||
+1
-1
@@ -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;
|
||||
}
|
||||
|
||||
+8
-2
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
+2
@@ -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
|
||||
|
||||
+5
@@ -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
|
||||
{
|
||||
}
|
||||
|
||||
+2
@@ -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;
|
||||
|
||||
+4
@@ -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)
|
||||
{
|
||||
|
||||
+25
-24
@@ -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;
|
||||
|
||||
+24
-5
@@ -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:
|
||||
|
||||
+47
-10
@@ -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);
|
||||
|
||||
+9
@@ -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;
|
||||
|
||||
@@ -28,8 +28,9 @@ ly_add_target(
|
||||
${pal_dir}
|
||||
BUILD_DEPENDENCIES
|
||||
PRIVATE
|
||||
3rdParty::OpenSSL
|
||||
AZ::AzCore
|
||||
PUBLIC
|
||||
3rdParty::OpenSSL
|
||||
)
|
||||
|
||||
ly_add_source_properties(
|
||||
|
||||
Reference in New Issue
Block a user