Merge branch 'main' into LY-113714
This commit is contained in:
@@ -189,7 +189,7 @@ namespace AZ
|
||||
if (!WasLoadSuccess(result.GetOutcome()))
|
||||
{
|
||||
// This if is a hack around fault in the JSON serialization system
|
||||
// Jira: https://jira.agscollab.com/browse/LY-106587
|
||||
// Jira: LY-106587
|
||||
if (message != "No part of the string could be interpreted as a uuid.")
|
||||
{
|
||||
deserializeError.append(message);
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <AzCore/Component/Entity.h>
|
||||
#include <AzCore/Component/ComponentApplicationBus.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/Interface/Interface.h>
|
||||
#include <AzCore/Math/Sfmt.h>
|
||||
#include <AzCore/Math/Crc.h>
|
||||
|
||||
@@ -173,7 +174,11 @@ namespace AZ
|
||||
//=========================================================================
|
||||
void ComponentDescriptor::ReleaseDescriptor()
|
||||
{
|
||||
EBUS_EVENT(ComponentApplicationBus, UnregisterComponentDescriptor, this);
|
||||
AZ::ComponentApplicationRequests* componentApplication = AZ::Interface<AZ::ComponentApplicationRequests>::Get();
|
||||
if (componentApplication != nullptr)
|
||||
{
|
||||
componentApplication->UnregisterComponentDescriptor(this);
|
||||
}
|
||||
delete this;
|
||||
}
|
||||
} // namespace AZ
|
||||
|
||||
@@ -526,6 +526,11 @@ namespace AZ
|
||||
// are destroyed
|
||||
m_commandLine = {};
|
||||
|
||||
m_entityAddedEvent.DisconnectAllHandlers();
|
||||
m_entityRemovedEvent.DisconnectAllHandlers();
|
||||
m_entityActivatedEvent.DisconnectAllHandlers();
|
||||
m_entityDeactivatedEvent.DisconnectAllHandlers();
|
||||
|
||||
DestroyAllocator();
|
||||
}
|
||||
|
||||
@@ -980,6 +985,26 @@ namespace AZ
|
||||
handler.Connect(m_entityRemovedEvent);
|
||||
}
|
||||
|
||||
void ComponentApplication::RegisterEntityActivatedEventHandler(EntityActivatedEvent::Handler& handler)
|
||||
{
|
||||
handler.Connect(m_entityActivatedEvent);
|
||||
}
|
||||
|
||||
void ComponentApplication::RegisterEntityDeactivatedEventHandler(EntityDeactivatedEvent::Handler& handler)
|
||||
{
|
||||
handler.Connect(m_entityDeactivatedEvent);
|
||||
}
|
||||
|
||||
void ComponentApplication::SignalEntityActivated(AZ::Entity* entity)
|
||||
{
|
||||
m_entityActivatedEvent.Signal(entity);
|
||||
}
|
||||
|
||||
void ComponentApplication::SignalEntityDeactivated(AZ::Entity* entity)
|
||||
{
|
||||
m_entityDeactivatedEvent.Signal(entity);
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
// AddEntity
|
||||
// [5/30/2012]
|
||||
|
||||
@@ -204,6 +204,10 @@ namespace AZ
|
||||
void UnregisterComponentDescriptor(const ComponentDescriptor* descriptor) override final;
|
||||
void RegisterEntityAddedEventHandler(EntityAddedEvent::Handler& handler) override final;
|
||||
void RegisterEntityRemovedEventHandler(EntityRemovedEvent::Handler& handler) override final;
|
||||
void RegisterEntityActivatedEventHandler(EntityActivatedEvent::Handler& handler) override final;
|
||||
void RegisterEntityDeactivatedEventHandler(EntityDeactivatedEvent::Handler& handler) override final;
|
||||
void SignalEntityActivated(Entity* entity) override final;
|
||||
void SignalEntityDeactivated(Entity* entity) override final;
|
||||
bool AddEntity(Entity* entity) override;
|
||||
bool RemoveEntity(Entity* entity) override;
|
||||
bool DeleteEntity(const EntityId& id) override;
|
||||
@@ -382,6 +386,8 @@ namespace AZ
|
||||
AZStd::unique_ptr<SettingsRegistryInterface> m_settingsRegistry;
|
||||
EntityAddedEvent m_entityAddedEvent;
|
||||
EntityRemovedEvent m_entityRemovedEvent;
|
||||
EntityAddedEvent m_entityActivatedEvent;
|
||||
EntityRemovedEvent m_entityDeactivatedEvent;
|
||||
AZ::IConsole* m_console{};
|
||||
Descriptor m_descriptor;
|
||||
bool m_isStarted{ false };
|
||||
|
||||
@@ -72,6 +72,8 @@ namespace AZ
|
||||
|
||||
using EntityAddedEvent = AZ::Event<AZ::Entity*>;
|
||||
using EntityRemovedEvent = AZ::Event<AZ::Entity*>;
|
||||
using EntityActivatedEvent = AZ::Event<AZ::Entity*>;
|
||||
using EntityDeactivatedEvent = AZ::Event<AZ::Entity*>;
|
||||
|
||||
//! Interface that components can use to make requests of the main application.
|
||||
class ComponentApplicationRequests
|
||||
@@ -102,6 +104,22 @@ namespace AZ
|
||||
//! @param handler the event handler to signal.
|
||||
virtual void RegisterEntityRemovedEventHandler(EntityRemovedEvent::Handler& handler) = 0;
|
||||
|
||||
//! Registers an event handler that will be signalled whenever an entity is added.
|
||||
//! @param handler the event handler to signal.
|
||||
virtual void RegisterEntityActivatedEventHandler(EntityActivatedEvent::Handler& handler) = 0;
|
||||
|
||||
//! Registers an event handler that will be signalled whenever an entity is removed.
|
||||
//! @param handler the event handler to signal.
|
||||
virtual void RegisterEntityDeactivatedEventHandler(EntityDeactivatedEvent::Handler& handler) = 0;
|
||||
|
||||
//! Signals that the provided entity has been activated.
|
||||
//! @param entity the entity being activated.
|
||||
virtual void SignalEntityActivated(AZ::Entity* entity) = 0;
|
||||
|
||||
//! Signals that the provided entity has been deactivated.
|
||||
//! @param entity the entity being deactivated.
|
||||
virtual void SignalEntityDeactivated(AZ::Entity* entity) = 0;
|
||||
|
||||
//! Adds an entity to the application's registry.
|
||||
//! Calling Init() on an entity automatically performs this operation.
|
||||
//! @param entity A pointer to the entity to add to the application's registry.
|
||||
|
||||
@@ -112,7 +112,11 @@ namespace AZ
|
||||
{
|
||||
EBUS_EVENT(EntitySystemBus, OnEntityDestruction, m_id);
|
||||
EBUS_EVENT_ID(m_id, EntityBus, OnEntityDestruction, m_id);
|
||||
EBUS_EVENT(ComponentApplicationBus, RemoveEntity, this);
|
||||
AZ::ComponentApplicationRequests* componentApplication = AZ::Interface<AZ::ComponentApplicationRequests>::Get();
|
||||
if (componentApplication != nullptr)
|
||||
{
|
||||
componentApplication->RemoveEntity(this);
|
||||
}
|
||||
m_stateEvent.Signal(State::Init, State::Destroying);
|
||||
}
|
||||
|
||||
@@ -216,12 +220,22 @@ namespace AZ
|
||||
|
||||
EBUS_EVENT_ID(m_id, EntityBus, OnEntityActivated, m_id);
|
||||
EBUS_EVENT(EntitySystemBus, OnEntityActivated, m_id);
|
||||
AZ::ComponentApplicationRequests* componentApplication = AZ::Interface<AZ::ComponentApplicationRequests>::Get();
|
||||
if (componentApplication != nullptr)
|
||||
{
|
||||
componentApplication->SignalEntityActivated(this);
|
||||
}
|
||||
}
|
||||
|
||||
void Entity::Deactivate()
|
||||
{
|
||||
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzCore);
|
||||
|
||||
AZ::ComponentApplicationRequests* componentApplication = AZ::Interface<AZ::ComponentApplicationRequests>::Get();
|
||||
if (componentApplication != nullptr)
|
||||
{
|
||||
componentApplication->SignalEntityDeactivated(this);
|
||||
}
|
||||
EBUS_EVENT_ID(m_id, EntityBus, OnEntityDeactivated, m_id);
|
||||
EBUS_EVENT(EntitySystemBus, OnEntityDeactivated, m_id);
|
||||
|
||||
|
||||
@@ -126,9 +126,11 @@ namespace AZ
|
||||
char buffer[MaxLogBufferSize];
|
||||
|
||||
const AZStd::size_t length = azvsnprintf(buffer, MaxLogBufferSize, format, args);
|
||||
buffer[AZStd::min<AZStd::size_t>(length, MaxLogBufferSize - 2)] = '\n';
|
||||
buffer[AZStd::min<AZStd::size_t>(length + 1, MaxLogBufferSize - 1)] = '\0';
|
||||
m_logEvent.Signal(level, buffer, file, function, line);
|
||||
|
||||
// Force a new-line before calling the AZ::Debug::Trace functions, as they assume a newline is present
|
||||
buffer[AZStd::min<AZStd::size_t>(length + 1, MaxLogBufferSize - 2)] = '\n';
|
||||
switch (level)
|
||||
{
|
||||
case LogLevel::Warn:
|
||||
@@ -142,8 +144,6 @@ namespace AZ
|
||||
AZ::Debug::Trace::Output("Logger", buffer);
|
||||
break;
|
||||
}
|
||||
|
||||
m_logEvent.Signal(level, buffer, file, function, line);
|
||||
}
|
||||
|
||||
void LoggerSystemComponent::SetLevel(const AZ::ConsoleCommandContainer& arguments)
|
||||
|
||||
@@ -233,6 +233,14 @@ namespace AZ
|
||||
AZ_Assert(handler->m_event == this, "Entry event does not match");
|
||||
handler->Disconnect();
|
||||
}
|
||||
|
||||
// Free up any owned memory
|
||||
AZStd::vector<Handler*> freeHandlers;
|
||||
m_handlers.swap(freeHandlers);
|
||||
AZStd::vector<Handler*> freeAdds;
|
||||
m_addList.swap(freeAdds);
|
||||
AZStd::stack<size_t> freeFree;
|
||||
m_freeList.swap(freeFree);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -13,16 +13,17 @@
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/base.h>
|
||||
#include <AzCore/std/math.h>
|
||||
#include <AzCore/std/typetraits/conditional.h>
|
||||
#include <AzCore/std/typetraits/is_integral.h>
|
||||
#include <AzCore/std/typetraits/is_signed.h>
|
||||
#include <AzCore/std/typetraits/is_unsigned.h>
|
||||
#include <AzCore/std/utils.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <float.h>
|
||||
#include <limits>
|
||||
#include <cmath>
|
||||
#include <math.h>
|
||||
#include <utility>
|
||||
#include <AzCore/std/typetraits/conditional.h>
|
||||
#include <AzCore/std/typetraits/is_integral.h>
|
||||
|
||||
// We have a separate inline define for math functions.
|
||||
// The performance of these functions is very sensitive to inlining, and some compilers don't deal well with this.
|
||||
@@ -308,12 +309,12 @@ namespace AZ
|
||||
|
||||
AZ_MATH_INLINE bool IsClose(float a, float b, float tolerance = Constants::Tolerance)
|
||||
{
|
||||
return (fabsf(a - b) <= tolerance);
|
||||
return (AZStd::abs(a - b) <= tolerance);
|
||||
}
|
||||
|
||||
AZ_MATH_INLINE bool IsClose(double a, double b, double tolerance = Constants::Tolerance)
|
||||
{
|
||||
return (fabs(a - b) <= tolerance);
|
||||
return (AZStd::abs(a - b) <= tolerance);
|
||||
}
|
||||
|
||||
//! Returns x >= 0.0f ? 1.0f : -1.0f.
|
||||
@@ -402,12 +403,12 @@ namespace AZ
|
||||
|
||||
AZ_MATH_INLINE float GetAbs(float a)
|
||||
{
|
||||
return fabsf(a);
|
||||
return AZStd::abs(a);
|
||||
}
|
||||
|
||||
AZ_MATH_INLINE double GetAbs(double a)
|
||||
{
|
||||
return std::abs(a);
|
||||
return AZStd::abs(a);
|
||||
}
|
||||
|
||||
AZ_MATH_INLINE float GetMod(float a, float b)
|
||||
@@ -441,7 +442,7 @@ namespace AZ
|
||||
template<typename T>
|
||||
AZ_MATH_INLINE bool IsCloseMag(T x, T y, T epsilonValue = std::numeric_limits<T>::epsilon())
|
||||
{
|
||||
return (std::fabs(x - y) <= epsilonValue * GetMax<T>(GetMax<T>(T(1.0), std::fabs(x)), std::fabs(y)));
|
||||
return (AZStd::abs(x - y) <= epsilonValue * GetMax<T>(GetMax<T>(T(1.0), AZStd::abs(x)), AZStd::abs(y)));
|
||||
}
|
||||
|
||||
//! ClampIfCloseMag(x, y, epsilon) returns y when x and y are within epsilon of each other (taking magnitude into account). Otherwise returns x.
|
||||
|
||||
@@ -33,6 +33,10 @@ namespace UnitTest
|
||||
MOCK_METHOD1(UnregisterComponentDescriptor, void (const AZ::ComponentDescriptor*));
|
||||
MOCK_METHOD1(RegisterEntityAddedEventHandler, void(AZ::EntityAddedEvent::Handler&));
|
||||
MOCK_METHOD1(RegisterEntityRemovedEventHandler, void(AZ::EntityRemovedEvent::Handler&));
|
||||
MOCK_METHOD1(RegisterEntityActivatedEventHandler, void(AZ::EntityActivatedEvent::Handler&));
|
||||
MOCK_METHOD1(RegisterEntityDeactivatedEventHandler, void(AZ::EntityDeactivatedEvent::Handler&));
|
||||
MOCK_METHOD1(SignalEntityActivated, void(AZ::Entity*));
|
||||
MOCK_METHOD1(SignalEntityDeactivated, void(AZ::Entity*));
|
||||
MOCK_METHOD1(RemoveEntity, bool (AZ::Entity*));
|
||||
MOCK_METHOD1(DeleteEntity, bool (const AZ::EntityId&));
|
||||
MOCK_METHOD1(GetEntityName, AZStd::string (const AZ::EntityId&));
|
||||
|
||||
@@ -169,5 +169,10 @@ namespace AZ::Utils
|
||||
template AZ::Outcome<AZStd::vector<int8_t>, AZStd::string> ReadFile(AZStd::string_view filePath, size_t maxFileSize);
|
||||
template AZ::Outcome<AZStd::vector<uint8_t>, AZStd::string> ReadFile(AZStd::string_view filePath, size_t maxFileSize);
|
||||
|
||||
|
||||
AZ::IO::FixedMaxPathString GetO3deManifestDirectory()
|
||||
{
|
||||
AZ::IO::FixedMaxPath path = GetHomeDirectory();
|
||||
path /= ".o3de";
|
||||
return path.Native();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,6 +88,9 @@ namespace AZ
|
||||
//! Retrieves the project name from the settings registry
|
||||
AZ::SettingsRegistryInterface::FixedValueString GetProjectName();
|
||||
|
||||
//! Retrieves the full directory to the Home directory, i.e. "<userhome> or overrideHomeDirectory"
|
||||
AZ::IO::FixedMaxPathString GetHomeDirectory();
|
||||
|
||||
//! Retrieves the full directory to the O3DE manifest directory, i.e. "<userhome>/.o3de"
|
||||
AZ::IO::FixedMaxPathString GetO3deManifestDirectory();
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ set(FILES
|
||||
iterator.h
|
||||
limits.h
|
||||
numeric.h
|
||||
math.h
|
||||
optional.h
|
||||
ratio.h
|
||||
reference_wrapper.h
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cmath>
|
||||
|
||||
namespace AZStd
|
||||
{
|
||||
using std::abs;
|
||||
}
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
|
||||
namespace AZ::Utils
|
||||
{
|
||||
AZ::IO::FixedMaxPathString GetO3deManifestDirectory()
|
||||
AZ::IO::FixedMaxPathString GetHomeDirectory()
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -25,8 +25,19 @@ namespace AZ
|
||||
|
||||
void NativeErrorMessageBox(const char*, const char*) {}
|
||||
|
||||
AZ::IO::FixedMaxPathString GetO3deManifestDirectory()
|
||||
AZ::IO::FixedMaxPathString GetHomeDirectory()
|
||||
{
|
||||
constexpr AZStd::string_view overrideHomeDirKey = "/Amazon/Settings/override_home_dir";
|
||||
AZ::IO::FixedMaxPathString overrideHomeDir;
|
||||
if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr)
|
||||
{
|
||||
if (settingsRegistry->Get(overrideHomeDir, overrideHomeDirKey))
|
||||
{
|
||||
AZ::IO::FixedMaxPath path{overrideHomeDir};
|
||||
return path.Native();
|
||||
}
|
||||
}
|
||||
|
||||
if (const char* homePath = std::getenv("HOME"); homePath != nullptr)
|
||||
{
|
||||
AZ::IO::FixedMaxPath path{homePath};
|
||||
|
||||
@@ -22,15 +22,25 @@ namespace AZ::Utils
|
||||
::MessageBox(0, message, title, MB_OK | MB_ICONERROR);
|
||||
}
|
||||
|
||||
AZ::IO::FixedMaxPathString GetO3deManifestDirectory()
|
||||
AZ::IO::FixedMaxPathString GetHomeDirectory()
|
||||
{
|
||||
constexpr AZStd::string_view overrideHomeDirKey = "/Amazon/Settings/override_home_dir";
|
||||
AZ::IO::FixedMaxPathString overrideHomeDir;
|
||||
if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr)
|
||||
{
|
||||
if (settingsRegistry->Get(overrideHomeDir, overrideHomeDirKey))
|
||||
{
|
||||
AZ::IO::FixedMaxPath path{overrideHomeDir};
|
||||
return path.Native();
|
||||
}
|
||||
}
|
||||
|
||||
char userProfileBuffer[AZ::IO::MaxPathLength]{};
|
||||
size_t variableSize = 0;
|
||||
auto err = getenv_s(&variableSize, userProfileBuffer, AZ::IO::MaxPathLength, "USERPROFILE");
|
||||
if (!err)
|
||||
{
|
||||
AZ::IO::FixedMaxPath path{ userProfileBuffer };
|
||||
path /= ".o3de";
|
||||
return path.Native();
|
||||
}
|
||||
|
||||
|
||||
@@ -49,9 +49,13 @@ namespace UnitTest
|
||||
// ComponentApplicationBus
|
||||
AZ::ComponentApplication* GetApplication() override { return nullptr; }
|
||||
void RegisterComponentDescriptor(const AZ::ComponentDescriptor*) override {}
|
||||
void UnregisterComponentDescriptor(const AZ::ComponentDescriptor*) override {}
|
||||
void RegisterEntityAddedEventHandler(AZ::EntityAddedEvent::Handler&) override {}
|
||||
void RegisterEntityRemovedEventHandler(AZ::EntityRemovedEvent::Handler&) override {}
|
||||
void UnregisterComponentDescriptor(const AZ::ComponentDescriptor*) override {}
|
||||
void RegisterEntityActivatedEventHandler(AZ::EntityActivatedEvent::Handler&) override {}
|
||||
void RegisterEntityDeactivatedEventHandler(AZ::EntityDeactivatedEvent::Handler&) override {}
|
||||
void SignalEntityActivated(AZ::Entity*) override {}
|
||||
void SignalEntityDeactivated(AZ::Entity*) override {}
|
||||
bool AddEntity(AZ::Entity*) override { return true; }
|
||||
bool RemoveEntity(AZ::Entity*) override { return true; }
|
||||
bool DeleteEntity(const AZ::EntityId&) override { return true; }
|
||||
|
||||
@@ -1232,6 +1232,10 @@ namespace UnitTest
|
||||
void UnregisterComponentDescriptor(const ComponentDescriptor*) override { }
|
||||
void RegisterEntityAddedEventHandler(EntityAddedEvent::Handler&) override { }
|
||||
void RegisterEntityRemovedEventHandler(EntityRemovedEvent::Handler&) override { }
|
||||
void RegisterEntityActivatedEventHandler(EntityActivatedEvent::Handler&) override { }
|
||||
void RegisterEntityDeactivatedEventHandler(EntityDeactivatedEvent::Handler&) override { }
|
||||
void SignalEntityActivated(Entity*) override { }
|
||||
void SignalEntityDeactivated(Entity*) override { }
|
||||
bool AddEntity(Entity*) override { return false; }
|
||||
bool RemoveEntity(Entity*) override { return false; }
|
||||
bool DeleteEntity(const EntityId&) override { return false; }
|
||||
@@ -1252,6 +1256,7 @@ namespace UnitTest
|
||||
m_serializeContext.reset(aznew AZ::SerializeContext());
|
||||
|
||||
ComponentApplicationBus::Handler::BusConnect();
|
||||
AZ::Interface<AZ::ComponentApplicationRequests>::Register(this);
|
||||
|
||||
AZ::AllocatorInstance<AZ::PoolAllocator>::Create();
|
||||
AZ::AllocatorInstance<AZ::ThreadPoolAllocator>::Create();
|
||||
@@ -1270,6 +1275,7 @@ namespace UnitTest
|
||||
AZ::AllocatorInstance<AZ::ThreadPoolAllocator>::Destroy();
|
||||
AZ::AllocatorInstance<AZ::PoolAllocator>::Destroy();
|
||||
|
||||
AZ::Interface<AZ::ComponentApplicationRequests>::Unregister(this);
|
||||
ComponentApplicationBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
|
||||
@@ -51,7 +51,6 @@ namespace AZ::IO
|
||||
: ArchiveLocationPriority::ePakPriorityFileFirst }; // Which file location to favor (loose vs. pak files)
|
||||
int nMessageInvalidFileAccess{};
|
||||
int nLogInvalidFileAccess{ IsReleaseConfig ? 0 : 1 };
|
||||
int nLoadFrontendShaderCache{ FRONTEND_SHADER_CACHE_DEFAULT };
|
||||
int nDisableNonLevelRelatedPaks{ 1 };
|
||||
int nWarnOnPakAccessFails{ 1 }; // Whether to treat failed pak access as a warning or log message
|
||||
int nSetLogLevel{ 3 };
|
||||
|
||||
@@ -11,10 +11,12 @@
|
||||
*/
|
||||
|
||||
#include <AzFramework/Components/TransformComponent.h>
|
||||
#include <AzFramework/Visibility/EntityBoundsUnionBus.h>
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
#include <AzCore/RTTI/BehaviorContext.h>
|
||||
#include <AzCore/Component/Entity.h>
|
||||
#include <AzCore/Component/ComponentApplicationBus.h>
|
||||
#include <AzCore/Interface/Interface.h>
|
||||
#include <AzCore/Math/Transform.h>
|
||||
#include <AzCore/Math/Quaternion.h>
|
||||
|
||||
@@ -693,9 +695,8 @@ namespace AzFramework
|
||||
parentId = handler->GetParentId();
|
||||
}
|
||||
#endif
|
||||
|
||||
AZ::Entity* parentEntity = nullptr;
|
||||
EBUS_EVENT_RESULT(parentEntity, AZ::ComponentApplicationBus, FindEntity, parentEntityId);
|
||||
AZ::ComponentApplicationRequests* componentApplication = AZ::Interface<AZ::ComponentApplicationRequests>::Get();
|
||||
AZ::Entity* parentEntity = (componentApplication != nullptr) ? componentApplication->FindEntity(parentEntityId) : nullptr;
|
||||
AZ_Assert(parentEntity, "We expect to have a parent entity associated with the provided parent's entity Id.");
|
||||
if (parentEntity)
|
||||
{
|
||||
@@ -744,8 +745,8 @@ namespace AzFramework
|
||||
m_parentId = parentId;
|
||||
if (m_parentId.IsValid())
|
||||
{
|
||||
AZ::Entity* parentEntity = nullptr;
|
||||
AZ::ComponentApplicationBus::BroadcastResult(parentEntity, &AZ::ComponentApplicationBus::Events::FindEntity, m_parentId);
|
||||
AZ::ComponentApplicationRequests* componentApplication = AZ::Interface<AZ::ComponentApplicationRequests>::Get();
|
||||
AZ::Entity* parentEntity = (componentApplication != nullptr) ? componentApplication->FindEntity(m_parentId) : nullptr;
|
||||
m_parentActive = parentEntity && (parentEntity->GetState() == AZ::Entity::State::Active);
|
||||
|
||||
m_onNewParentKeepWorldTM = isKeepWorldTM;
|
||||
@@ -832,6 +833,12 @@ namespace AzFramework
|
||||
|
||||
EBUS_EVENT_PTR(m_notificationBus, AZ::TransformNotificationBus, OnTransformChanged, m_localTM, m_worldTM);
|
||||
m_transformChangedEvent.Signal(m_localTM, m_worldTM);
|
||||
|
||||
AzFramework::IEntityBoundsUnion* boundsUnion = AZ::Interface<AzFramework::IEntityBoundsUnion>::Get();
|
||||
if (boundsUnion != nullptr)
|
||||
{
|
||||
boundsUnion->OnTransformUpdated(GetEntity());
|
||||
}
|
||||
}
|
||||
|
||||
void TransformComponent::ComputeWorldTM()
|
||||
|
||||
@@ -93,6 +93,8 @@ namespace AzFramework
|
||||
InitContext();
|
||||
|
||||
GameEntityContextRequestBus::Handler::BusConnect();
|
||||
|
||||
m_entityVisibilityBoundsUnionSystem.Connect();
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
@@ -100,6 +102,8 @@ namespace AzFramework
|
||||
//=========================================================================
|
||||
void GameEntityContextComponent::Deactivate()
|
||||
{
|
||||
m_entityVisibilityBoundsUnionSystem.Disconnect();
|
||||
|
||||
GameEntityContextRequestBus::Handler::BusDisconnect();
|
||||
|
||||
DestroyContext();
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <AzCore/Component/Component.h>
|
||||
#include <AzFramework/Entity/GameEntityContextBus.h>
|
||||
#include <AzFramework/Entity/SliceGameEntityOwnershipService.h>
|
||||
#include <AzFramework/Visibility/EntityVisibilityBoundsUnionSystem.h>
|
||||
|
||||
#include "EntityContext.h"
|
||||
|
||||
@@ -91,6 +92,9 @@ namespace AzFramework
|
||||
{
|
||||
required.push_back(AZ_CRC("SliceSystemService", 0x1a5b7aad));
|
||||
}
|
||||
|
||||
private:
|
||||
AzFramework::EntityVisibilityBoundsUnionSystem m_entityVisibilityBoundsUnionSystem;
|
||||
};
|
||||
} // namespace AzFramework
|
||||
|
||||
|
||||
@@ -139,7 +139,8 @@ namespace AzFramework
|
||||
"Implementers of IntersectionRequestBus must also implement BoundsRequestBus to ensure valid "
|
||||
"bounds are returned");
|
||||
|
||||
m_registeredEntities.Update({ entityId, CalculateEntityWorldBoundsUnion(entityId) });
|
||||
AZ::Entity* entity = AZ::Interface<AZ::ComponentApplicationRequests>::Get()->FindEntity(entityId);
|
||||
m_registeredEntities.Update({ entityId, CalculateEntityWorldBoundsUnion(entity) });
|
||||
}
|
||||
|
||||
m_dirtyEntities.clear();
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Component/Entity.h>
|
||||
#include <AzCore/Component/ComponentBus.h>
|
||||
#include <AzCore/Component/TransformBus.h>
|
||||
#include <AzFramework/Render/GeometryIntersectionStructures.h>
|
||||
@@ -27,7 +28,8 @@ namespace AZ
|
||||
namespace AzFramework
|
||||
{
|
||||
//! Implemented by components that provide bounds for use with various systems.
|
||||
class BoundsRequests : public AZ::ComponentBus
|
||||
class BoundsRequests
|
||||
: public AZ::ComponentBus
|
||||
{
|
||||
public:
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
@@ -37,6 +39,7 @@ namespace AzFramework
|
||||
//! more than one component may be providing a bound. It isn't guaranteed which bound
|
||||
//! will be returned by a single call to GetWorldBounds.
|
||||
virtual AZ::Aabb GetWorldBounds() = 0;
|
||||
|
||||
//! Returns an axis aligned bounding box in local space.
|
||||
//! @note It is preferred to use CalculateEntityLocalBoundsUnion in the general case as
|
||||
//! more than one component may be providing a bound. It isn't guaranteed which bound
|
||||
@@ -46,17 +49,15 @@ namespace AzFramework
|
||||
protected:
|
||||
~BoundsRequests() = default;
|
||||
};
|
||||
|
||||
using BoundsRequestBus = AZ::EBus<BoundsRequests>;
|
||||
|
||||
//! Returns a union of all local Aabbs provided by components implementing the BoundsRequestBus.
|
||||
//! @note It is preferred to call this function as opposed to GetLocalBounds directly as more than one
|
||||
//! component may be implementing this bus on an Entity and so only the first result (Aabb) will be returned.
|
||||
inline AZ::Aabb CalculateEntityLocalBoundsUnion(const AZ::EntityId entityId)
|
||||
inline AZ::Aabb CalculateEntityLocalBoundsUnion(const AZ::Entity* entity)
|
||||
{
|
||||
AZ::EBusReduceResult<AZ::Aabb, AabbUnionAggregator> aabbResult(AZ::Aabb::CreateNull());
|
||||
BoundsRequestBus::EventResult(
|
||||
aabbResult, entityId, &BoundsRequestBus::Events::GetLocalBounds);
|
||||
BoundsRequestBus::EventResult(aabbResult, entity->GetId(), &BoundsRequestBus::Events::GetLocalBounds);
|
||||
|
||||
if (aabbResult.value.IsValid())
|
||||
{
|
||||
@@ -69,18 +70,18 @@ namespace AzFramework
|
||||
//! Returns a union of all world Aabbs provided by components implementing the BoundsRequestBus.
|
||||
//! @note It is preferred to call this function as opposed to GetWorldBounds directly as more than one
|
||||
//! component may be implementing this bus on an Entity and so only the first result (Aabb) will be returned.
|
||||
inline AZ::Aabb CalculateEntityWorldBoundsUnion(const AZ::EntityId entityId)
|
||||
inline AZ::Aabb CalculateEntityWorldBoundsUnion(const AZ::Entity* entity)
|
||||
{
|
||||
AZ::EBusReduceResult<AZ::Aabb, AabbUnionAggregator> aabbResult(AZ::Aabb::CreateNull());
|
||||
BoundsRequestBus::EventResult(aabbResult, entityId, &BoundsRequestBus::Events::GetWorldBounds);
|
||||
BoundsRequestBus::EventResult(aabbResult, entity->GetId(), &BoundsRequestBus::Events::GetWorldBounds);
|
||||
|
||||
if (aabbResult.value.IsValid())
|
||||
{
|
||||
return aabbResult.value;
|
||||
}
|
||||
|
||||
AZ::Vector3 worldTranslation = AZ::Vector3::CreateZero();
|
||||
AZ::TransformBus::EventResult(worldTranslation, entityId, &AZ::TransformBus::Events::GetWorldTranslation);
|
||||
AZ::TransformInterface* transformInterface = entity->GetTransform();
|
||||
const AZ::Vector3 worldTranslation = transformInterface->GetWorldTranslation();
|
||||
return AZ::Aabb::CreateCenterHalfExtents(worldTranslation, AZ::Vector3(0.5f));
|
||||
}
|
||||
} // namespace AzFramework
|
||||
|
||||
@@ -23,9 +23,11 @@ namespace AzFramework
|
||||
{
|
||||
//! Provides an interface to retrieve and update the union of all Aabbs on a single Entity.
|
||||
//! @note This will be the combination/union of all individual Component Aabbs.
|
||||
class EntityBoundsUnionRequests : public AZ::EBusTraits
|
||||
class IEntityBoundsUnion
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(IEntityBoundsUnion, "{106968DD-43C0-478E-8045-523E0BF5D0F5}");
|
||||
|
||||
//! Requests the cached union of component Aabbs to be recalculated as one may have changed.
|
||||
//! @note This is used to drive event driven updates to the visibility system.
|
||||
virtual void RefreshEntityLocalBoundsUnion(AZ::EntityId entityId) = 0;
|
||||
@@ -38,9 +40,21 @@ namespace AzFramework
|
||||
//! also be called explicitly (e.g. For testing purposes).
|
||||
virtual void ProcessEntityBoundsUnionRequests() = 0;
|
||||
|
||||
//! Notifies the EntityBoundsUnion system that an entities transform has been modified.
|
||||
//! @param entity the entity whose transform has been modified.
|
||||
virtual void OnTransformUpdated(AZ::Entity* entity) = 0;
|
||||
|
||||
protected:
|
||||
~EntityBoundsUnionRequests() = default;
|
||||
~IEntityBoundsUnion() = default;
|
||||
};
|
||||
|
||||
using EntityBoundsUnionRequestBus = AZ::EBus<EntityBoundsUnionRequests>;
|
||||
// EBus wrapper for ScriptCanvas
|
||||
class IEntityBoundsUnionTraits
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
|
||||
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
|
||||
};
|
||||
using IEntityBoundsUnionRequestBus = AZ::EBus<IEntityBoundsUnion, IEntityBoundsUnionTraits>;
|
||||
} // namespace AzFramework
|
||||
|
||||
+57
-64
@@ -17,69 +17,70 @@
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
EntityVisibilityBoundsUnionSystem::EntityVisibilityBoundsUnionSystem()
|
||||
: m_entityActivatedEventHandler([this](AZ::Entity* entity) { OnEntityActivated(entity); })
|
||||
, m_entityDeactivatedEventHandler([this](AZ::Entity* entity) { OnEntityDeactivated(entity); })
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
void EntityVisibilityBoundsUnionSystem::Connect()
|
||||
{
|
||||
EntityBoundsUnionRequestBus::Handler::BusConnect();
|
||||
AZ::TransformNotificationBus::Router::BusRouterConnect();
|
||||
AZ::EntitySystemBus::Handler::BusConnect();
|
||||
AZ::Interface<IEntityBoundsUnion>::Register(this);
|
||||
IEntityBoundsUnionRequestBus::Handler::BusConnect();
|
||||
AZ::TickBus::Handler::BusConnect();
|
||||
|
||||
AZ::Interface<AZ::ComponentApplicationRequests>::Get()->RegisterEntityActivatedEventHandler(m_entityActivatedEventHandler);
|
||||
AZ::Interface<AZ::ComponentApplicationRequests>::Get()->RegisterEntityDeactivatedEventHandler(m_entityDeactivatedEventHandler);
|
||||
}
|
||||
|
||||
void EntityVisibilityBoundsUnionSystem::Disconnect()
|
||||
{
|
||||
m_entityActivatedEventHandler.Disconnect();
|
||||
m_entityDeactivatedEventHandler.Disconnect();
|
||||
|
||||
AZ::TickBus::Handler::BusDisconnect();
|
||||
AZ::EntitySystemBus::Handler::BusDisconnect();
|
||||
AZ::TransformNotificationBus::Router::BusRouterDisconnect();
|
||||
EntityBoundsUnionRequestBus::Handler::BusDisconnect();
|
||||
IEntityBoundsUnionRequestBus::Handler::BusDisconnect();
|
||||
AZ::Interface<IEntityBoundsUnion>::Unregister(this);
|
||||
}
|
||||
|
||||
static void SetUserDataEntityId(VisibilityEntry& visibilityEntry, const AZ::EntityId entityId)
|
||||
{
|
||||
static_assert(
|
||||
sizeof(AZ::EntityId) <= sizeof(visibilityEntry.m_userData), "Ensure EntityId fits into m_userData");
|
||||
|
||||
visibilityEntry.m_typeFlags = VisibilityEntry::TYPE_Entity;
|
||||
|
||||
std::memcpy(&visibilityEntry.m_userData, &entityId, sizeof(AZ::EntityId));
|
||||
}
|
||||
|
||||
void EntityVisibilityBoundsUnionSystem::OnEntityActivated(const AZ::EntityId& entityId)
|
||||
void EntityVisibilityBoundsUnionSystem::OnEntityActivated(AZ::Entity* entity)
|
||||
{
|
||||
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzFramework);
|
||||
|
||||
// ignore any entity that might activate which does not have a TransformComponent
|
||||
if (!AZ::TransformBus::HasHandlers(entityId))
|
||||
if (entity->GetTransform() == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (auto instance_it = m_entityVisibilityBoundsUnionInstanceMapping.find(entityId);
|
||||
if (auto instance_it = m_entityVisibilityBoundsUnionInstanceMapping.find(entity);
|
||||
instance_it == m_entityVisibilityBoundsUnionInstanceMapping.end())
|
||||
{
|
||||
AZ::Transform worldFromLocal = AZ::Transform::CreateIdentity();
|
||||
AZ::TransformBus::EventResult(worldFromLocal, entityId, &AZ::TransformBus::Events::GetWorldTM);
|
||||
AZ::TransformInterface* transformInterface = entity->GetTransform();
|
||||
const AZ::Vector3 entityPosition = transformInterface->GetWorldTranslation();
|
||||
|
||||
EntityVisibilityBoundsUnionInstance instance;
|
||||
instance.m_worldTransform = worldFromLocal;
|
||||
instance.m_localEntityBoundsUnion = CalculateEntityLocalBoundsUnion(entityId);
|
||||
SetUserDataEntityId(instance.m_visibilityEntry, entityId);
|
||||
instance.m_localEntityBoundsUnion = CalculateEntityLocalBoundsUnion(entity);
|
||||
instance.m_visibilityEntry.m_typeFlags = VisibilityEntry::TYPE_Entity;
|
||||
instance.m_visibilityEntry.m_userData = static_cast<void*>(entity);
|
||||
|
||||
auto next_it = m_entityVisibilityBoundsUnionInstanceMapping.insert({entityId, instance});
|
||||
UpdateVisibilitySystem(next_it.first->second);
|
||||
auto next_it = m_entityVisibilityBoundsUnionInstanceMapping.insert({ entity, instance });
|
||||
UpdateVisibilitySystem(entity, next_it.first->second);
|
||||
}
|
||||
}
|
||||
|
||||
void EntityVisibilityBoundsUnionSystem::OnEntityDeactivated(const AZ::EntityId& entityId)
|
||||
void EntityVisibilityBoundsUnionSystem::OnEntityDeactivated(AZ::Entity* entity)
|
||||
{
|
||||
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzFramework);
|
||||
|
||||
// ignore any entity that might deactivate which does not have a TransformComponent
|
||||
if (!AZ::TransformBus::HasHandlers(entityId))
|
||||
if (entity->GetTransform() == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (auto instance_it = m_entityVisibilityBoundsUnionInstanceMapping.find(entityId);
|
||||
if (auto instance_it = m_entityVisibilityBoundsUnionInstanceMapping.find(entity);
|
||||
instance_it != m_entityVisibilityBoundsUnionInstanceMapping.end())
|
||||
{
|
||||
if (IVisibilitySystem* visibilitySystem = AZ::Interface<IVisibilitySystem>::Get())
|
||||
@@ -90,7 +91,7 @@ namespace AzFramework
|
||||
}
|
||||
}
|
||||
|
||||
void EntityVisibilityBoundsUnionSystem::UpdateVisibilitySystem(EntityVisibilityBoundsUnionInstance& instance)
|
||||
void EntityVisibilityBoundsUnionSystem::UpdateVisibilitySystem(AZ::Entity* entity, EntityVisibilityBoundsUnionInstance& instance)
|
||||
{
|
||||
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzFramework);
|
||||
|
||||
@@ -98,8 +99,8 @@ namespace AzFramework
|
||||
{
|
||||
// note: worldEntityBounds will not be a 'tight-fit' Aabb but that of a transformed local aabb
|
||||
// there will be some wasted space but it should be sufficient for the visibility system
|
||||
const AZ::Aabb worldEntityBoundsUnion =
|
||||
localEntityBoundsUnions.GetTransformedAabb(instance.m_worldTransform);
|
||||
AZ::TransformInterface* transformInterface = entity->GetTransform();
|
||||
const AZ::Aabb worldEntityBoundsUnion = localEntityBoundsUnions.GetTransformedAabb(transformInterface->GetWorldTM());
|
||||
IVisibilitySystem* visibilitySystem = AZ::Interface<IVisibilitySystem>::Get();
|
||||
if (visibilitySystem && !worldEntityBoundsUnion.IsClose(instance.m_visibilityEntry.m_boundingVolume))
|
||||
{
|
||||
@@ -111,19 +112,27 @@ namespace AzFramework
|
||||
|
||||
void EntityVisibilityBoundsUnionSystem::RefreshEntityLocalBoundsUnion(const AZ::EntityId entityId)
|
||||
{
|
||||
// track entities that need their bounds union to be recalculated
|
||||
m_entityIdsBoundsDirty.insert(entityId);
|
||||
AZ::Entity* entity = AZ::Interface<AZ::ComponentApplicationRequests>::Get()->FindEntity(entityId);
|
||||
if (entity != nullptr)
|
||||
{
|
||||
// track entities that need their bounds union to be recalculated
|
||||
m_entityBoundsDirty.insert(entity);
|
||||
}
|
||||
}
|
||||
|
||||
AZ::Aabb EntityVisibilityBoundsUnionSystem::GetEntityLocalBoundsUnion(const AZ::EntityId entityId) const
|
||||
{
|
||||
// if the EntityId is not found in the mapping then return a null Aabb, this is to mimic
|
||||
// as closely as possible the behavior of an individual GetLocalBounds call to an Entity that
|
||||
// had been deleted (there would be no response, leaving the default value assigned)
|
||||
if (auto instance_it = m_entityVisibilityBoundsUnionInstanceMapping.find(entityId);
|
||||
instance_it != m_entityVisibilityBoundsUnionInstanceMapping.end())
|
||||
AZ::Entity* entity = AZ::Interface<AZ::ComponentApplicationRequests>::Get()->FindEntity(entityId);
|
||||
if (entity != nullptr)
|
||||
{
|
||||
return instance_it->second.m_localEntityBoundsUnion;
|
||||
// if the entity is not found in the mapping then return a null Aabb, this is to mimic
|
||||
// as closely as possible the behavior of an individual GetLocalBounds call to an Entity that
|
||||
// had been deleted (there would be no response, leaving the default value assigned)
|
||||
if (auto instance_it = m_entityVisibilityBoundsUnionInstanceMapping.find(entity);
|
||||
instance_it != m_entityVisibilityBoundsUnionInstanceMapping.end())
|
||||
{
|
||||
return instance_it->second.m_localEntityBoundsUnion;
|
||||
}
|
||||
}
|
||||
|
||||
return AZ::Aabb::CreateNull();
|
||||
@@ -134,45 +143,29 @@ namespace AzFramework
|
||||
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzFramework);
|
||||
|
||||
// iterate over all entities whose bounds changed and recalculate them
|
||||
for (const auto& entityId : m_entityIdsBoundsDirty)
|
||||
for (const auto& entity : m_entityBoundsDirty)
|
||||
{
|
||||
if (auto instance_it = m_entityVisibilityBoundsUnionInstanceMapping.find(entityId);
|
||||
if (auto instance_it = m_entityVisibilityBoundsUnionInstanceMapping.find(entity);
|
||||
instance_it != m_entityVisibilityBoundsUnionInstanceMapping.end())
|
||||
{
|
||||
instance_it->second.m_localEntityBoundsUnion = CalculateEntityLocalBoundsUnion(entityId);
|
||||
}
|
||||
}
|
||||
|
||||
auto allDirtyEntityIds = m_entityIdsTransformDirty;
|
||||
allDirtyEntityIds.insert(m_entityIdsBoundsDirty.begin(), m_entityIdsBoundsDirty.end());
|
||||
|
||||
for (const auto& dirtyEntityId : allDirtyEntityIds)
|
||||
{
|
||||
if (auto instance_it = m_entityVisibilityBoundsUnionInstanceMapping.find(dirtyEntityId);
|
||||
instance_it != m_entityVisibilityBoundsUnionInstanceMapping.end())
|
||||
{
|
||||
UpdateVisibilitySystem(instance_it->second);
|
||||
instance_it->second.m_localEntityBoundsUnion = CalculateEntityLocalBoundsUnion(entity);
|
||||
UpdateVisibilitySystem(entity, instance_it->second);
|
||||
}
|
||||
}
|
||||
|
||||
// clear dirty entities once the visibility system has been updated
|
||||
m_entityIdsBoundsDirty.clear();
|
||||
m_entityIdsTransformDirty.clear();
|
||||
m_entityBoundsDirty.clear();
|
||||
}
|
||||
|
||||
void EntityVisibilityBoundsUnionSystem::OnTransformChanged(
|
||||
[[maybe_unused]] const AZ::Transform& local, const AZ::Transform& world)
|
||||
void EntityVisibilityBoundsUnionSystem::OnTransformUpdated(AZ::Entity* entity)
|
||||
{
|
||||
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzFramework);
|
||||
|
||||
const AZ::EntityId entityId = *AZ::TransformNotificationBus::GetCurrentBusId();
|
||||
m_entityIdsTransformDirty.insert(entityId);
|
||||
|
||||
// update the world transform of the visibility bounds union
|
||||
if (auto instance_it = m_entityVisibilityBoundsUnionInstanceMapping.find(entityId);
|
||||
if (auto instance_it = m_entityVisibilityBoundsUnionInstanceMapping.find(entity);
|
||||
instance_it != m_entityVisibilityBoundsUnionInstanceMapping.end())
|
||||
{
|
||||
instance_it->second.m_worldTransform = world;
|
||||
UpdateVisibilitySystem(entity, instance_it->second);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+15
-18
@@ -23,12 +23,12 @@ namespace AzFramework
|
||||
{
|
||||
//! Provide a unified hook between entities and the visibility system.
|
||||
class EntityVisibilityBoundsUnionSystem
|
||||
: public EntityBoundsUnionRequestBus::Handler
|
||||
, private AZ::EntitySystemBus::Handler
|
||||
, private AZ::TransformNotificationBus::Router
|
||||
: public IEntityBoundsUnionRequestBus::Handler
|
||||
, private AZ::TickBus::Handler
|
||||
{
|
||||
public:
|
||||
EntityVisibilityBoundsUnionSystem();
|
||||
|
||||
void Connect();
|
||||
void Disconnect();
|
||||
|
||||
@@ -36,34 +36,31 @@ namespace AzFramework
|
||||
void RefreshEntityLocalBoundsUnion(AZ::EntityId entityId) override;
|
||||
AZ::Aabb GetEntityLocalBoundsUnion(AZ::EntityId entityId) const override;
|
||||
void ProcessEntityBoundsUnionRequests() override;
|
||||
void OnTransformUpdated(AZ::Entity* entity) override;
|
||||
|
||||
private:
|
||||
struct EntityVisibilityBoundsUnionInstance
|
||||
{
|
||||
AZ::Transform m_worldTransform = AZ::Transform::CreateIdentity(); //!< The world transform of the Entity.
|
||||
AZ::Aabb m_localEntityBoundsUnion =
|
||||
AZ::Aabb::CreateNull(); //!< Entity union bounding volume in local space.
|
||||
AZ::Aabb m_localEntityBoundsUnion = AZ::Aabb::CreateNull(); //!< Entity union bounding volume in local space.
|
||||
VisibilityEntry m_visibilityEntry; //!< Hook into the IVisibilitySystem interface.
|
||||
};
|
||||
|
||||
using UniqueEntityIds = AZStd::unordered_set<AZ::EntityId>;
|
||||
using UniqueEntities = AZStd::set<AZ::Entity*>;
|
||||
using EntityVisibilityBoundsUnionInstanceMapping =
|
||||
AZStd::unordered_map<AZ::EntityId, EntityVisibilityBoundsUnionInstance>;
|
||||
AZStd::unordered_map<AZ::Entity*, EntityVisibilityBoundsUnionInstance>;
|
||||
|
||||
void OnEntityActivated(AZ::Entity* entity);
|
||||
void OnEntityDeactivated(AZ::Entity* entity);
|
||||
|
||||
// TickBus overrides ...
|
||||
void OnTick(float deltaTime, AZ::ScriptTimePoint time) override;
|
||||
|
||||
// EntitySystemBus overrides ...
|
||||
void OnEntityActivated(const AZ::EntityId& entityId) override;
|
||||
void OnEntityDeactivated(const AZ::EntityId& entityId) override;
|
||||
|
||||
// TransformNotificationBus overrides ...
|
||||
void OnTransformChanged(const AZ::Transform& local, const AZ::Transform& world) override;
|
||||
|
||||
void UpdateVisibilitySystem(EntityVisibilityBoundsUnionInstance& instance);
|
||||
void UpdateVisibilitySystem(AZ::Entity* entity, EntityVisibilityBoundsUnionInstance& instance);
|
||||
|
||||
EntityVisibilityBoundsUnionInstanceMapping m_entityVisibilityBoundsUnionInstanceMapping;
|
||||
UniqueEntityIds m_entityIdsBoundsDirty;
|
||||
UniqueEntityIds m_entityIdsTransformDirty;
|
||||
UniqueEntities m_entityBoundsDirty;
|
||||
|
||||
AZ::EntityActivatedEvent::Handler m_entityActivatedEventHandler;
|
||||
AZ::EntityDeactivatedEvent::Handler m_entityDeactivatedEventHandler;
|
||||
};
|
||||
} // namespace AzFramework
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
#include <AzCore/Console/Console.h>
|
||||
#include <AzCore/Debug/Profiler.h>
|
||||
#include <AzCore/Component/Entity.h>
|
||||
#include <AzCore/Math/ShapeIntersection.h>
|
||||
#include <AzFramework/Entity/EntityDebugDisplayBus.h>
|
||||
#include <AzFramework/Visibility/IVisibilitySystem.h>
|
||||
@@ -66,6 +67,7 @@ namespace AzFramework
|
||||
octreeDebug.m_nodeBounds.push_back(nodeData.m_bounds);
|
||||
}
|
||||
|
||||
visibleEntityIdsOut.reserve(visibleEntityIdsOut.size() + nodeData.m_entries.size());
|
||||
for (const auto* visibilityEntry : nodeData.m_entries)
|
||||
{
|
||||
if (ed_visibility_showDebug)
|
||||
@@ -88,8 +90,7 @@ namespace AzFramework
|
||||
octreeDebug.m_entryAabbsInFrustum.push_back(visibilityEntry->m_boundingVolume);
|
||||
}
|
||||
|
||||
AZ::EntityId entityId;
|
||||
std::memcpy(&entityId, &visibilityEntry->m_userData, sizeof(AZ::EntityId));
|
||||
AZ::EntityId entityId = static_cast<AZ::Entity*>(visibilityEntry->m_userData)->GetId();
|
||||
visibleEntityIdsOut.push_back(entityId);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -13,4 +13,3 @@
|
||||
#pragma once
|
||||
|
||||
#define STREAM_CACHE_DEFAULT 0
|
||||
#define FRONTEND_SHADER_CACHE_DEFAULT 0
|
||||
|
||||
@@ -13,4 +13,3 @@
|
||||
#pragma once
|
||||
|
||||
#define STREAM_CACHE_DEFAULT 0
|
||||
#define FRONTEND_SHADER_CACHE_DEFAULT 0
|
||||
|
||||
@@ -13,4 +13,3 @@
|
||||
#pragma once
|
||||
|
||||
#define STREAM_CACHE_DEFAULT 0
|
||||
#define FRONTEND_SHADER_CACHE_DEFAULT 0
|
||||
|
||||
@@ -13,4 +13,3 @@
|
||||
#pragma once
|
||||
|
||||
#define STREAM_CACHE_DEFAULT 0
|
||||
#define FRONTEND_SHADER_CACHE_DEFAULT 0
|
||||
|
||||
@@ -13,4 +13,3 @@
|
||||
#pragma once
|
||||
|
||||
#define STREAM_CACHE_DEFAULT 0
|
||||
#define FRONTEND_SHADER_CACHE_DEFAULT 0
|
||||
|
||||
@@ -19,9 +19,10 @@ namespace AzNetworking
|
||||
static const int32_t FloatHashMinValue = (INT_MIN >> 7);
|
||||
static const int32_t FloatHashMaxValue = (INT_MAX >> 7);
|
||||
|
||||
AZ::HashValue64 HashSerializer::GetHash() const
|
||||
AZ::HashValue32 HashSerializer::GetHash() const
|
||||
{
|
||||
return m_hash;
|
||||
// Just truncate the upper bits
|
||||
return static_cast<AZ::HashValue32>(m_hash);
|
||||
}
|
||||
|
||||
SerializerMode HashSerializer::GetSerializerMode() const
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace AzNetworking
|
||||
|
||||
HashSerializer() = default;
|
||||
|
||||
AZ::HashValue64 GetHash() const;
|
||||
AZ::HashValue32 GetHash() const;
|
||||
|
||||
// ISerializer interfaces
|
||||
SerializerMode GetSerializerMode() const override;
|
||||
|
||||
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzNetworking/Serialization/StringifySerializer.h>
|
||||
|
||||
namespace AzNetworking
|
||||
{
|
||||
StringifySerializer::StringifySerializer(char delimeter, bool outputFieldNames, const AZStd::string& seperator)
|
||||
: m_delimeter(delimeter)
|
||||
, m_outputFieldNames(outputFieldNames)
|
||||
, m_separator(seperator)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
const AZStd::string& StringifySerializer::GetString() const
|
||||
{
|
||||
return m_string;
|
||||
}
|
||||
|
||||
const StringifySerializer::StringMap& StringifySerializer::GetValueMap() const
|
||||
{
|
||||
return m_map;
|
||||
}
|
||||
|
||||
SerializerMode StringifySerializer::GetSerializerMode() const
|
||||
{
|
||||
return SerializerMode::ReadFromObject;
|
||||
}
|
||||
|
||||
bool StringifySerializer::Serialize(bool& value, const char* name)
|
||||
{
|
||||
return ProcessData(name, value);
|
||||
}
|
||||
|
||||
bool StringifySerializer::Serialize(char& value, const char* name, char, char)
|
||||
{
|
||||
const int val = value; // Print chars as integers
|
||||
return ProcessData(name, val);
|
||||
}
|
||||
|
||||
bool StringifySerializer::Serialize(int8_t& value, const char* name, int8_t, int8_t)
|
||||
{
|
||||
return ProcessData(name, value);
|
||||
}
|
||||
|
||||
bool StringifySerializer::Serialize(int16_t& value, const char* name, int16_t, int16_t)
|
||||
{
|
||||
return ProcessData(name, value);
|
||||
}
|
||||
|
||||
bool StringifySerializer::Serialize(int32_t& value, const char* name, int32_t, int32_t)
|
||||
{
|
||||
return ProcessData(name, value);
|
||||
}
|
||||
|
||||
bool StringifySerializer::Serialize(int64_t& value, const char* name, int64_t, int64_t)
|
||||
{
|
||||
return ProcessData(name, value);
|
||||
}
|
||||
|
||||
bool StringifySerializer::Serialize(uint8_t& value, const char* name, uint8_t, uint8_t)
|
||||
{
|
||||
return ProcessData(name, value);
|
||||
}
|
||||
|
||||
bool StringifySerializer::Serialize(uint16_t& value, const char* name, uint16_t, uint16_t)
|
||||
{
|
||||
return ProcessData(name, value);
|
||||
}
|
||||
|
||||
bool StringifySerializer::Serialize(uint32_t& value, const char* name, uint32_t, uint32_t)
|
||||
{
|
||||
return ProcessData(name, value);
|
||||
}
|
||||
|
||||
bool StringifySerializer::Serialize(uint64_t& value, const char* name, uint64_t, uint64_t)
|
||||
{
|
||||
return ProcessData(name, value);
|
||||
}
|
||||
|
||||
bool StringifySerializer::Serialize(float& value, const char* name, float, float)
|
||||
{
|
||||
return ProcessData(name, value);
|
||||
}
|
||||
|
||||
bool StringifySerializer::Serialize(double& value, const char* name, double, double)
|
||||
{
|
||||
return ProcessData(name, value);
|
||||
}
|
||||
|
||||
bool StringifySerializer::SerializeBytes(uint8_t* buffer, uint32_t, bool isString, uint32_t&, const char* name)
|
||||
{
|
||||
if (isString)
|
||||
{
|
||||
AZ::CVarFixedString value = reinterpret_cast<char*>(buffer);
|
||||
return ProcessData(name, value);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool StringifySerializer::BeginObject(const char* name, const char*)
|
||||
{
|
||||
m_prefixSizeStack.push_back(m_prefix.size());
|
||||
m_prefix += name;
|
||||
m_prefix += ".";
|
||||
return true;
|
||||
}
|
||||
|
||||
bool StringifySerializer::EndObject(const char*, const char*)
|
||||
{
|
||||
m_prefix.resize(m_prefixSizeStack.back());
|
||||
m_prefixSizeStack.pop_back();
|
||||
return true;
|
||||
}
|
||||
|
||||
const uint8_t* StringifySerializer::GetBuffer() const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint32_t StringifySerializer::GetCapacity() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t StringifySerializer::GetSize() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool StringifySerializer::ProcessData(const char* name, const T& value)
|
||||
{
|
||||
// Only add delimeters after we have processed at least one element
|
||||
if (!m_string.empty())
|
||||
{
|
||||
m_string += m_delimeter;
|
||||
}
|
||||
|
||||
if (m_outputFieldNames)
|
||||
{
|
||||
m_string += m_prefix;
|
||||
m_string += name;
|
||||
m_string += m_separator;
|
||||
}
|
||||
|
||||
AZ::CVarFixedString string = AZ::ConsoleTypeHelpers::ValueToString(value);
|
||||
m_string += string.c_str();
|
||||
m_map[m_prefix + name] = string.c_str();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzNetworking/Serialization/ISerializer.h>
|
||||
#include <AzCore/std/containers/map.h>
|
||||
|
||||
namespace AzNetworking
|
||||
{
|
||||
// StringifySerializer
|
||||
// Generate a debug string of a serializable object
|
||||
class StringifySerializer
|
||||
: public ISerializer
|
||||
{
|
||||
public:
|
||||
|
||||
using StringMap = AZStd::map<AZStd::string, AZStd::string>;
|
||||
|
||||
StringifySerializer(char delimeter = ' ', bool outputFieldNames = true, const AZStd::string& seperator = "=");
|
||||
|
||||
// GetString
|
||||
// After serializing objects, get the serialized values as a single string
|
||||
const AZStd::string& GetString() const;
|
||||
|
||||
// GetValueMap
|
||||
// After serializing objects, get the serialized values as key value pairs
|
||||
const StringMap& GetValueMap() const;
|
||||
|
||||
// ISerializer interfaces
|
||||
SerializerMode GetSerializerMode() const override;
|
||||
bool Serialize(bool& value, const char* name) override;
|
||||
bool Serialize(char& value, const char* name, char minValue, char maxValue) override;
|
||||
bool Serialize(int8_t& value, const char* name, int8_t minValue, int8_t maxValue) override;
|
||||
bool Serialize(int16_t& value, const char* name, int16_t minValue, int16_t maxValue) override;
|
||||
bool Serialize(int32_t& value, const char* name, int32_t minValue, int32_t maxValue) override;
|
||||
bool Serialize(int64_t& value, const char* name, int64_t minValue, int64_t maxValue) override;
|
||||
bool Serialize(uint8_t& value, const char* name, uint8_t minValue, uint8_t maxValue) override;
|
||||
bool Serialize(uint16_t& value, const char* name, uint16_t minValue, uint16_t maxValue) override;
|
||||
bool Serialize(uint32_t& value, const char* name, uint32_t minValue, uint32_t maxValue) override;
|
||||
bool Serialize(uint64_t& value, const char* name, uint64_t minValue, uint64_t maxValue) override;
|
||||
bool Serialize(float& value, const char* name, float minValue, float maxValue) override;
|
||||
bool Serialize(double& value, const char* name, double minValue, double maxValue) override;
|
||||
bool SerializeBytes(uint8_t* buffer, uint32_t bufferCapacity, bool isString, uint32_t& outSize, const char* name) override;
|
||||
bool BeginObject(const char* name, const char* typeName) override;
|
||||
bool EndObject(const char* name, const char* typeName) override;
|
||||
|
||||
const uint8_t* GetBuffer() const override;
|
||||
uint32_t GetCapacity() const override;
|
||||
uint32_t GetSize() const override;
|
||||
void ClearTrackedChangesFlag() override {}
|
||||
bool GetTrackedChangesFlag() const override { return false; }
|
||||
// ISerializer interfaces
|
||||
|
||||
private:
|
||||
|
||||
template <typename T>
|
||||
bool ProcessData(const char* name, const T& value);
|
||||
|
||||
private:
|
||||
|
||||
char m_delimeter;
|
||||
bool m_outputFieldNames = true;
|
||||
|
||||
StringMap m_map;
|
||||
AZStd::string m_string;
|
||||
AZStd::string m_prefix;
|
||||
AZStd::string m_separator;
|
||||
AZStd::deque<AZStd::size_t> m_prefixSizeStack;
|
||||
};
|
||||
}
|
||||
@@ -65,6 +65,8 @@ set(FILES
|
||||
Serialization/NetworkOutputSerializer.cpp
|
||||
Serialization/NetworkOutputSerializer.h
|
||||
Serialization/NetworkOutputSerializer.inl
|
||||
Serialization/StringifySerializer.cpp
|
||||
Serialization/StringifySerializer.h
|
||||
Serialization/TrackChangedSerializer.h
|
||||
Serialization/TrackChangedSerializer.inl
|
||||
TcpTransport/TcpConnection.cpp
|
||||
|
||||
@@ -180,6 +180,8 @@ namespace AzQtComponents
|
||||
textSearch->setFrame(false);
|
||||
textSearch->setText(QString());
|
||||
textSearch->setPlaceholderText(QObject::tr("Search..."));
|
||||
textSearch->setClearButtonEnabled(true);
|
||||
LineEdit::applySearchStyle(textSearch);
|
||||
connect(textSearch, &QLineEdit::textChanged, this, &SearchTypeSelector::FilterTextChanged);
|
||||
|
||||
m_searchLayout->addWidget(textSearch);
|
||||
|
||||
@@ -761,16 +761,6 @@ namespace AzToolsFramework
|
||||
/// If the view pane was not registered with the ViewPaneOptions.isDeletable set to true, the view pane will be hidden instead.
|
||||
virtual void CloseViewPane(const char* /*paneName*/) {}
|
||||
|
||||
/// Request generation of all level cubemaps.
|
||||
virtual void GenerateAllCubemaps() {}
|
||||
|
||||
/// Regenerate cubemap for a particular entity.
|
||||
/// \param entityId ID of the entity that the cubemap is for
|
||||
/// \param cubemapOutputPath path to a image file to generate
|
||||
/// \param hideEntity Indicates whether the entity should be hidden during cubemap generation. Controls whether the entity's current cubemap output is baked into the new cubemap.
|
||||
virtual void GenerateCubemapForEntity(AZ::EntityId /*entityId*/, AZStd::string* /*cubemapOutputPath*/, bool /*hideEntity*/) {}
|
||||
virtual void GenerateCubemapWithIDForEntity(AZ::EntityId /*entityId*/, AZ::Uuid /*cubemapId*/, AZStd::string* /*cubemapOutputPath*/, bool /*hideEntity*/, bool /*hasCubemapId*/) {}
|
||||
|
||||
//! Spawn asset browser for the appropriate asset types.
|
||||
virtual void BrowseForAssets(AssetBrowser::AssetSelectionModel& /*selection*/) = 0;
|
||||
|
||||
|
||||
-5
@@ -189,9 +189,6 @@ namespace AzToolsFramework
|
||||
SliceEditorEntityOwnershipServiceNotificationBus::Handler::BusConnect();
|
||||
|
||||
EditorLegacyGameModeNotificationBus::Handler::BusConnect();
|
||||
|
||||
m_entityVisibilityBoundsUnionSystem.Connect();
|
||||
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
@@ -199,8 +196,6 @@ namespace AzToolsFramework
|
||||
//=========================================================================
|
||||
void EditorEntityContextComponent::Deactivate()
|
||||
{
|
||||
m_entityVisibilityBoundsUnionSystem.Disconnect();
|
||||
|
||||
EditorLegacyGameModeNotificationBus::Handler::BusDisconnect();
|
||||
|
||||
SliceEditorEntityOwnershipServiceNotificationBus::Handler::BusDisconnect();
|
||||
|
||||
@@ -189,8 +189,6 @@ namespace AzToolsFramework
|
||||
//! EditorEntityContextRequestBus::Events::AddRequiredComponents()
|
||||
AZ::ComponentTypeList m_requiredEditorComponentTypes;
|
||||
|
||||
//! Edit time visibility management integrating entities with the IVisibilitySystem.
|
||||
AzFramework::EntityVisibilityBoundsUnionSystem m_entityVisibilityBoundsUnionSystem;
|
||||
bool m_isLegacySliceService;
|
||||
|
||||
UndoSystem::UndoCacheInterface* m_undoCacheInterface = nullptr;
|
||||
|
||||
+2
-2
@@ -85,14 +85,14 @@ namespace AzToolsFramework
|
||||
|
||||
// if we're snapping, only increment current radians when we know
|
||||
// preSnapRadians is greater than the angleStep
|
||||
if (snapping)
|
||||
if (snapping && AZStd::abs(angleStepDegrees) > 0.0f)
|
||||
{
|
||||
actionInternal.m_current.m_preSnapRadians += rotationAngleRad * rotateSign;
|
||||
|
||||
const float angleStepRad = AZ::DegToRad(angleStepDegrees);
|
||||
const float preSnapRotateSign = Sign(actionInternal.m_current.m_preSnapRadians);
|
||||
// if we move more than angleStep in a frame, make sure we catch up
|
||||
while (fabsf(actionInternal.m_current.m_preSnapRadians) >= angleStepRad)
|
||||
while (AZStd::abs(actionInternal.m_current.m_preSnapRadians) >= angleStepRad)
|
||||
{
|
||||
actionInternal.m_current.m_radians += angleStepRad * preSnapRotateSign;
|
||||
actionInternal.m_current.m_preSnapRadians -= angleStepRad * preSnapRotateSign;
|
||||
|
||||
@@ -89,7 +89,7 @@ namespace AzToolsFramework
|
||||
if (!RetrieveAndSortPrefabEntitiesAndInstances(inputEntityList, commonRootEntityOwningInstance->get(), entities, instances))
|
||||
{
|
||||
return AZ::Failure(
|
||||
AZStd::string("Could not create a new prefab out of the entities provided - entities do not share a common root."));
|
||||
AZStd::string("Could not create a new prefab out of the entities provided - invalid selection."));
|
||||
}
|
||||
|
||||
// When we create a prefab with other prefab instances, we have to remove the existing links between the source and
|
||||
@@ -140,9 +140,13 @@ namespace AzToolsFramework
|
||||
// Mark them as dirty so this change is correctly applied to the template
|
||||
for (AZ::Entity* topLevelEntity : topLevelEntities)
|
||||
{
|
||||
m_prefabUndoCache.UpdateCache(topLevelEntity->GetId());
|
||||
undoBatch.MarkEntityDirty(topLevelEntity->GetId());
|
||||
AZ::TransformBus::Event(topLevelEntity->GetId(), &AZ::TransformBus::Events::SetParent, containerEntityId);
|
||||
AZ::EntityId topLevelEntityId = topLevelEntity->GetId();
|
||||
if (topLevelEntityId.IsValid())
|
||||
{
|
||||
m_prefabUndoCache.UpdateCache(topLevelEntityId);
|
||||
undoBatch.MarkEntityDirty(topLevelEntityId);
|
||||
AZ::TransformBus::Event(topLevelEntityId, &AZ::TransformBus::Events::SetParent, containerEntityId);
|
||||
}
|
||||
}
|
||||
|
||||
// Select Container Entity
|
||||
@@ -237,6 +241,21 @@ namespace AzToolsFramework
|
||||
// Retrieve entityList from entityIds
|
||||
inputEntityList = EntityIdListToEntityList(entityIds);
|
||||
|
||||
// Remove Level Container Entity if it's part of the list
|
||||
AZ::EntityId levelEntityId = GetLevelInstanceContainerEntityId();
|
||||
if (levelEntityId.IsValid())
|
||||
{
|
||||
AZ::Entity* levelEntity = GetEntityById(levelEntityId);
|
||||
if (levelEntity)
|
||||
{
|
||||
auto levelEntityIter = AZStd::find(inputEntityList.begin(), inputEntityList.end(), levelEntity);
|
||||
if (levelEntityIter != inputEntityList.end())
|
||||
{
|
||||
inputEntityList.erase(levelEntityIter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Find common root and top level entities
|
||||
bool entitiesHaveCommonRoot = false;
|
||||
|
||||
@@ -807,6 +826,11 @@ namespace AzToolsFramework
|
||||
const EntityList& inputEntities, Instance& commonRootEntityOwningInstance,
|
||||
EntityList& outEntities, AZStd::vector<AZStd::unique_ptr<Instance>>& outInstances) const
|
||||
{
|
||||
if (inputEntities.size() == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
AZStd::queue<AZ::Entity*> entityQueue;
|
||||
|
||||
for (auto inputEntity : inputEntities)
|
||||
@@ -894,7 +918,7 @@ namespace AzToolsFramework
|
||||
outInstances.push_back(AZStd::move(commonRootEntityOwningInstance.DetachNestedInstance(instancePtr->GetInstanceAlias())));
|
||||
}
|
||||
|
||||
return true;
|
||||
return (outEntities.size() + outInstances.size()) > 0;
|
||||
}
|
||||
|
||||
bool PrefabPublicHandler::EntitiesBelongToSameInstance(const EntityIdList& entityIds) const
|
||||
|
||||
@@ -1353,7 +1353,7 @@ namespace AzToolsFramework
|
||||
// Iterate over the entities left in the instance and if none of them have this
|
||||
// asset entity as its ancestor, then we want to remove it.
|
||||
// \todo - Investigate ways to make this non-linear time. Tricky since removed entities
|
||||
// obviously aren't maintained in any maps. (https://jira.agscollab.com/browse/LY-88218)
|
||||
// obviously aren't maintained in any maps. (LY-88218)
|
||||
bool foundAsAncestor = false;
|
||||
for (const AZ::Entity* instanceEntity : instanceEntities)
|
||||
{
|
||||
|
||||
+12
-5
@@ -25,6 +25,7 @@
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzFramework/API/ApplicationAPI.h>
|
||||
#include <AzFramework/Components/TransformComponent.h>
|
||||
#include <AzFramework/Visibility/EntityBoundsUnionBus.h>
|
||||
#include <AzToolsFramework/API/EntityCompositionRequestBus.h>
|
||||
#include <AzToolsFramework/API/EntityPropertyEditorRequestsBus.h>
|
||||
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
|
||||
@@ -265,6 +266,13 @@ namespace AzToolsFramework
|
||||
|
||||
AZ::TransformNotificationBus::Event(
|
||||
GetEntityId(), &TransformNotification::OnTransformChanged, localTM, worldTM);
|
||||
m_transformChangedEvent.Signal(localTM, worldTM);
|
||||
|
||||
AzFramework::IEntityBoundsUnion* boundsUnion = AZ::Interface<AzFramework::IEntityBoundsUnion>::Get();
|
||||
if (boundsUnion != nullptr)
|
||||
{
|
||||
boundsUnion->OnTransformUpdated(GetEntity());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -933,15 +941,14 @@ namespace AzToolsFramework
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AZ::Entity* pEntity = nullptr;
|
||||
EBUS_EVENT_RESULT(pEntity, AZ::ComponentApplicationBus, FindEntity, otherEntityId);
|
||||
if (!pEntity)
|
||||
|
||||
AZ::Entity* entity = AZ::Interface<AZ::ComponentApplicationRequests>::Get()->FindEntity(otherEntityId);
|
||||
if (!entity)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return pEntity->FindComponent<TransformComponent>();
|
||||
return entity->FindComponent<TransformComponent>();
|
||||
}
|
||||
|
||||
AZ::TransformInterface* TransformComponent::GetParent()
|
||||
|
||||
+32
-19
@@ -151,32 +151,36 @@ namespace AzToolsFramework
|
||||
{
|
||||
if (!selectedEntities.empty())
|
||||
{
|
||||
bool layerInSelection = false;
|
||||
|
||||
for (AZ::EntityId entityId : selectedEntities)
|
||||
// Hide if the only selected entity is the Level Container
|
||||
if (selectedEntities.size() > 1 || !s_prefabPublicInterface->IsLevelInstanceContainerEntity(selectedEntities[0]))
|
||||
{
|
||||
if (!layerInSelection)
|
||||
{
|
||||
AzToolsFramework::Layers::EditorLayerComponentRequestBus::EventResult(
|
||||
layerInSelection, entityId,
|
||||
&AzToolsFramework::Layers::EditorLayerComponentRequestBus::Events::HasLayer);
|
||||
bool layerInSelection = false;
|
||||
|
||||
if (layerInSelection)
|
||||
for (AZ::EntityId entityId : selectedEntities)
|
||||
{
|
||||
if (!layerInSelection)
|
||||
{
|
||||
break;
|
||||
AzToolsFramework::Layers::EditorLayerComponentRequestBus::EventResult(
|
||||
layerInSelection, entityId,
|
||||
&AzToolsFramework::Layers::EditorLayerComponentRequestBus::Events::HasLayer);
|
||||
|
||||
if (layerInSelection)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Layers can't be in prefabs.
|
||||
if (!layerInSelection)
|
||||
{
|
||||
QAction* createAction = menu->addAction(QObject::tr("Create Prefab..."));
|
||||
createAction->setToolTip(QObject::tr("Creates a prefab out of the currently selected entities."));
|
||||
// Layers can't be in prefabs.
|
||||
if (!layerInSelection)
|
||||
{
|
||||
QAction* createAction = menu->addAction(QObject::tr("Create Prefab..."));
|
||||
createAction->setToolTip(QObject::tr("Creates a prefab out of the currently selected entities."));
|
||||
|
||||
QObject::connect(createAction, &QAction::triggered, createAction, [this, selectedEntities] {
|
||||
ContextMenu_CreatePrefab(selectedEntities);
|
||||
});
|
||||
QObject::connect(createAction, &QAction::triggered, createAction, [this, selectedEntities] {
|
||||
ContextMenu_CreatePrefab(selectedEntities);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -272,6 +276,15 @@ namespace AzToolsFramework
|
||||
QWidget* activeWindow = QApplication::activeWindow();
|
||||
const AZStd::string prefabFilesPath = "@devassets@/Prefabs";
|
||||
|
||||
// Remove Level entity if it's part of the list
|
||||
|
||||
auto levelContainerIter =
|
||||
AZStd::find(selectedEntities.begin(), selectedEntities.end(), s_prefabPublicInterface->GetLevelInstanceContainerEntityId());
|
||||
if (levelContainerIter != selectedEntities.end())
|
||||
{
|
||||
selectedEntities.erase(levelContainerIter);
|
||||
}
|
||||
|
||||
// Set default folder for prefabs
|
||||
AZ::IO::FileIOBase* fileIoBaseInstance = AZ::IO::FileIOBase::GetInstance();
|
||||
|
||||
|
||||
+1
@@ -335,6 +335,7 @@ namespace AzToolsFramework
|
||||
m_gui->m_entityDetailsLabel->setObjectName("LabelEntityDetails");
|
||||
m_gui->m_entitySearchBox->setReadOnly(false);
|
||||
m_gui->m_entitySearchBox->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
m_gui->m_entitySearchBox->setClearButtonEnabled(true);
|
||||
AzQtComponents::LineEdit::applySearchStyle(m_gui->m_entitySearchBox);
|
||||
|
||||
AzFramework::ApplicationRequests::Bus::BroadcastResult(
|
||||
|
||||
+4
-4
@@ -68,6 +68,7 @@ namespace AzToolsFramework
|
||||
{
|
||||
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzToolsFramework);
|
||||
|
||||
const AZ::Entity* entity = AZ::Interface<AZ::ComponentApplicationRequests>::Get()->FindEntity(entityId);
|
||||
AzFramework::EntityDebugDisplayEventBus::Event(
|
||||
entityId, &AzFramework::EntityDebugDisplayEvents::DisplayEntityViewport,
|
||||
viewportInfo, debugDisplay);
|
||||
@@ -84,10 +85,9 @@ namespace AzToolsFramework
|
||||
|
||||
if (ed_visibility_showAggregateEntityTransformedLocalBounds)
|
||||
{
|
||||
AZ::Transform worldFromLocal = AZ::Transform::CreateIdentity();
|
||||
AZ::TransformBus::EventResult(worldFromLocal, entityId, &AZ::TransformBus::Events::GetWorldTM);
|
||||
AZ::Transform worldFromLocal = entity->GetTransform()->GetWorldTM();
|
||||
|
||||
if (const AZ::Aabb localAabb = AzFramework::CalculateEntityLocalBoundsUnion(entityId); localAabb.IsValid())
|
||||
if (const AZ::Aabb localAabb = AzFramework::CalculateEntityLocalBoundsUnion(entity); localAabb.IsValid())
|
||||
{
|
||||
const AZ::Aabb worldAabb = localAabb.GetTransformedAabb(worldFromLocal);
|
||||
debugDisplay.SetColor(AZ::Colors::Turquoise);
|
||||
@@ -97,7 +97,7 @@ namespace AzToolsFramework
|
||||
|
||||
if (ed_visibility_showAggregateEntityWorldBounds)
|
||||
{
|
||||
if (const AZ::Aabb worldAabb = AzFramework::CalculateEntityWorldBoundsUnion(entityId); worldAabb.IsValid())
|
||||
if (const AZ::Aabb worldAabb = AzFramework::CalculateEntityWorldBoundsUnion(entity); worldAabb.IsValid())
|
||||
{
|
||||
debugDisplay.SetColor(AZ::Colors::Magenta);
|
||||
debugDisplay.DrawWireBox(worldAabb.GetMin(), worldAabb.GetMax());
|
||||
|
||||
+4
-1
@@ -13,7 +13,9 @@
|
||||
#include "EditorSelectionUtil.h"
|
||||
|
||||
#include <AzCore/Math/Aabb.h>
|
||||
#include <AzCore/Interface/Interface.h>
|
||||
#include <AzCore/Math/IntersectSegment.h>
|
||||
#include <AzCore/Component/ComponentApplicationBus.h>
|
||||
#include <AzFramework/Visibility/BoundsBus.h>
|
||||
#include <AzToolsFramework/API/ComponentEntitySelectionBus.h>
|
||||
#include <AzToolsFramework/Viewport/ViewportMessages.h>
|
||||
@@ -28,7 +30,8 @@ namespace AzToolsFramework
|
||||
{
|
||||
if (Centered(pivot))
|
||||
{
|
||||
if (const AZ::Aabb localBound = AzFramework::CalculateEntityLocalBoundsUnion(entityId);
|
||||
const AZ::Entity* entity = AZ::Interface<AZ::ComponentApplicationRequests>::Get()->FindEntity(entityId);
|
||||
if (const AZ::Aabb localBound = AzFramework::CalculateEntityLocalBoundsUnion(entity);
|
||||
localBound.IsValid())
|
||||
{
|
||||
return localBound.GetCenter();
|
||||
|
||||
@@ -62,8 +62,8 @@ namespace UnitTest
|
||||
SetupRowOfEntities(AZ::Vector3::CreateAxisX(-20.0f), AZ::Vector3::CreateAxisX(2.0f));
|
||||
|
||||
// request the entity union bounds system to update
|
||||
AzFramework::EntityBoundsUnionRequestBus::Broadcast(
|
||||
&AzFramework::EntityBoundsUnionRequestBus::Events::ProcessEntityBoundsUnionRequests);
|
||||
AzFramework::IEntityBoundsUnionRequestBus::Broadcast(
|
||||
&AzFramework::IEntityBoundsUnionRequestBus::Events::ProcessEntityBoundsUnionRequests);
|
||||
|
||||
// create default camera looking down the negative y-axis moved just back from the origin
|
||||
AzFramework::CameraState cameraState = AzFramework::CreateDefaultCamera(
|
||||
@@ -101,8 +101,8 @@ namespace UnitTest
|
||||
SetupRowOfEntities(AZ::Vector3::CreateAxisX(-20.0f), AZ::Vector3::CreateAxisX(2.0f));
|
||||
|
||||
// request the entity union bounds system to update
|
||||
AzFramework::EntityBoundsUnionRequestBus::Broadcast(
|
||||
&AzFramework::EntityBoundsUnionRequestBus::Events::ProcessEntityBoundsUnionRequests);
|
||||
AzFramework::IEntityBoundsUnionRequestBus::Broadcast(
|
||||
&AzFramework::IEntityBoundsUnionRequestBus::Events::ProcessEntityBoundsUnionRequests);
|
||||
|
||||
// create default camera looking down the negative x-axis moved along the x-axis and tilted slightly down
|
||||
AzFramework::CameraState cameraState = AzFramework::CreateDefaultCamera(
|
||||
@@ -143,15 +143,15 @@ namespace UnitTest
|
||||
SetupRowOfEntities(AZ::Vector3::CreateAxisX(-20.0f), AZ::Vector3::CreateAxisX(2.0f));
|
||||
|
||||
// request the entity union bounds system to update
|
||||
AzFramework::EntityBoundsUnionRequestBus::Broadcast(
|
||||
&AzFramework::EntityBoundsUnionRequestBus::Events::ProcessEntityBoundsUnionRequests);
|
||||
AzFramework::IEntityBoundsUnionRequestBus::Broadcast(
|
||||
&AzFramework::IEntityBoundsUnionRequestBus::Events::ProcessEntityBoundsUnionRequests);
|
||||
|
||||
const AZ::EntityId entityIdToMove = m_editorEntityIds[10];
|
||||
AZ::TransformBus::Event(
|
||||
entityIdToMove, &AZ::TransformBus::Events::SetWorldTranslation, AZ::Vector3::CreateAxisZ(100.0f));
|
||||
|
||||
AzFramework::EntityBoundsUnionRequestBus::Broadcast(
|
||||
&AzFramework::EntityBoundsUnionRequestBus::Events::ProcessEntityBoundsUnionRequests);
|
||||
AzFramework::IEntityBoundsUnionRequestBus::Broadcast(
|
||||
&AzFramework::IEntityBoundsUnionRequestBus::Events::ProcessEntityBoundsUnionRequests);
|
||||
|
||||
// create default camera looking down the negative y-axis moved just back from the origin
|
||||
AzFramework::CameraState cameraState = AzFramework::CreateDefaultCamera(
|
||||
@@ -241,8 +241,8 @@ namespace UnitTest
|
||||
{
|
||||
m_localAabb = localAabb;
|
||||
|
||||
AzFramework::EntityBoundsUnionRequestBus::Broadcast(
|
||||
&AzFramework::EntityBoundsUnionRequestBus::Events::RefreshEntityLocalBoundsUnion, GetEntityId());
|
||||
AzFramework::IEntityBoundsUnionRequestBus::Broadcast(
|
||||
&AzFramework::IEntityBoundsUnionRequestBus::Events::RefreshEntityLocalBoundsUnion, GetEntityId());
|
||||
}
|
||||
|
||||
TEST_F(EditorVisibilityFixture, UpdatedBoundsIntersectingFrustumAddsVisibleEntity)
|
||||
@@ -264,8 +264,8 @@ namespace UnitTest
|
||||
entityId, &AZ::TransformBus::Events::SetWorldTranslation, AZ::Vector3(40.0f, -3.0f, 20.0f));
|
||||
|
||||
// request the entity union bounds system to update
|
||||
AzFramework::EntityBoundsUnionRequestBus::Broadcast(
|
||||
&AzFramework::EntityBoundsUnionRequestBus::Events::ProcessEntityBoundsUnionRequests);
|
||||
AzFramework::IEntityBoundsUnionRequestBus::Broadcast(
|
||||
&AzFramework::IEntityBoundsUnionRequestBus::Events::ProcessEntityBoundsUnionRequests);
|
||||
|
||||
// create default camera looking down the positive x-axis moved to position offset from world origin
|
||||
AzFramework::CameraState cameraState = AzFramework::CreateDefaultCamera(
|
||||
@@ -288,8 +288,8 @@ namespace UnitTest
|
||||
testBoundComponent->ChangeBounds(AZ::Aabb::CreateFromMinMax(AZ::Vector3(-2.5f), AZ::Vector3(2.5f)));
|
||||
|
||||
// perform an 'update' of the visibility system
|
||||
AzFramework::EntityBoundsUnionRequestBus::Broadcast(
|
||||
&AzFramework::EntityBoundsUnionRequestBus::Events::ProcessEntityBoundsUnionRequests);
|
||||
AzFramework::IEntityBoundsUnionRequestBus::Broadcast(
|
||||
&AzFramework::IEntityBoundsUnionRequestBus::Events::ProcessEntityBoundsUnionRequests);
|
||||
|
||||
entityVisibilityQuery.UpdateVisibility(cameraState);
|
||||
|
||||
|
||||
@@ -1100,6 +1100,10 @@ namespace UnitTest
|
||||
void UnregisterComponentDescriptor(const ComponentDescriptor*) override {}
|
||||
void RegisterEntityAddedEventHandler(EntityAddedEvent::Handler&) override {}
|
||||
void RegisterEntityRemovedEventHandler(EntityRemovedEvent::Handler&) override {}
|
||||
void RegisterEntityActivatedEventHandler(EntityActivatedEvent::Handler&) override {}
|
||||
void RegisterEntityDeactivatedEventHandler(EntityDeactivatedEvent::Handler&) override {}
|
||||
void SignalEntityActivated(Entity*) override {}
|
||||
void SignalEntityDeactivated(Entity*) override {}
|
||||
bool AddEntity(Entity*) override { return true; }
|
||||
bool RemoveEntity(Entity*) override { return true; }
|
||||
bool DeleteEntity(const EntityId&) override { return true; }
|
||||
@@ -1125,6 +1129,7 @@ namespace UnitTest
|
||||
AllocatorsFixture::SetUp();
|
||||
|
||||
ComponentApplicationBus::Handler::BusConnect();
|
||||
AZ::Interface<AZ::ComponentApplicationRequests>::Register(this);
|
||||
m_serializeContext.reset(aznew AZ::SerializeContext(true, true));
|
||||
|
||||
Entity::Reflect(m_serializeContext.get());
|
||||
@@ -1139,6 +1144,7 @@ namespace UnitTest
|
||||
m_descriptors.set_capacity(0);
|
||||
|
||||
m_serializeContext.reset();
|
||||
AZ::Interface<AZ::ComponentApplicationRequests>::Unregister(this);
|
||||
ComponentApplicationBus::Handler::BusDisconnect();
|
||||
|
||||
AllocatorsFixture::TearDown();
|
||||
|
||||
@@ -279,6 +279,10 @@ namespace UnitTest
|
||||
MOCK_METHOD1(UnregisterComponentDescriptor, void (const AZ::ComponentDescriptor*));
|
||||
MOCK_METHOD1(RegisterEntityAddedEventHandler, void(AZ::EntityAddedEvent::Handler&));
|
||||
MOCK_METHOD1(RegisterEntityRemovedEventHandler, void(AZ::EntityRemovedEvent::Handler&));
|
||||
MOCK_METHOD1(RegisterEntityActivatedEventHandler, void(AZ::EntityActivatedEvent::Handler&));
|
||||
MOCK_METHOD1(RegisterEntityDeactivatedEventHandler, void(AZ::EntityDeactivatedEvent::Handler&));
|
||||
MOCK_METHOD1(SignalEntityActivated, void(AZ::Entity*));
|
||||
MOCK_METHOD1(SignalEntityDeactivated, void(AZ::Entity*));
|
||||
MOCK_METHOD1(RemoveEntity, bool (AZ::Entity*));
|
||||
MOCK_METHOD1(DeleteEntity, bool (const AZ::EntityId&));
|
||||
MOCK_METHOD1(GetEntityName, AZStd::string (const AZ::EntityId&));
|
||||
|
||||
Reference in New Issue
Block a user