Hierarchical components, phase 1, unittests

Signed-off-by: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com>
This commit is contained in:
AMZN-Olex
2021-09-13 16:51:50 -04:00
parent 3535d6b6b3
commit aa6c038880
20 changed files with 2886 additions and 45 deletions
@@ -199,6 +199,8 @@ namespace Multiplayer
friend class NetworkEntityManager;
friend class EntityReplicationManager;
friend class HierarchyTests;
};
bool NetworkRoleHasController(NetEntityRole networkRole);
@@ -0,0 +1,46 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzCore/Component/ComponentBus.h>
namespace Multiplayer
{
class NetworkHierarchyNotifications
: public AZ::ComponentBus
{
public:
//! Called when a hierarchy has been updated (a child added or removed, etc.)
virtual void OnNetworkHierarchyUpdated([[maybe_unused]] const AZ::EntityId& rootEntityId) {}
//! Called when an entity has left a hierarchy
virtual void OnLeavingNetworkHierarchy() {}
};
typedef AZ::EBus<NetworkHierarchyNotifications> NetworkHierarchyNotificationBus;
class NetworkHierarchyRequests
: public AZ::ComponentBus
{
public:
//! @returns hierarchical entities, the first element is the top level root
virtual AZStd::vector<AZ::Entity*> GetHierarchicalEntities() const = 0;
//! @returns the top level root of a hierarchy, or nullptr if this entity is not in a hierarchy
virtual AZ::Entity* GetHierarchicalRoot() const = 0;
//! @return true if this entity is a child entity within a hierarchy
virtual bool IsHierarchicalChild() const = 0;
//! @return true if this entity is the top level root of a hierarchy
virtual bool IsHierarchicalRoot() const = 0;
};
typedef AZ::EBus<NetworkHierarchyRequests> NetworkHierarchyRequestBus;
}
@@ -0,0 +1,66 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzCore/Component/Component.h>
#include <Multiplayer/Components/NetworkHierarchyBus.h>
#include <Source/AutoGen/NetworkHierarchyChildComponent.AutoComponent.h>
namespace Multiplayer
{
class NetworkHierarchyRootComponent;
//! @class NetworkHierarchyChildComponent
//! @brief Component that declares network dependency on the parent of this entity
/*
* The parent of this entity should have @NetworkHierarchyChildComponent (or @NetworkHierarchyRootComponent).
* A network hierarchy is a collection of entities with one @NetworkHierarchyRootComponent at the top parent
* and one or more @NetworkHierarchyChildComponent on its child entities.
*/
class NetworkHierarchyChildComponent final
: public NetworkHierarchyChildComponentBase
, public NetworkHierarchyRequestBus::Handler
{
friend class NetworkHierarchyRootComponent;
public:
AZ_MULTIPLAYER_COMPONENT(Multiplayer::NetworkHierarchyChildComponent, s_networkHierarchyChildComponentConcreteUuid, Multiplayer::NetworkHierarchyChildComponentBase);
static void Reflect(AZ::ReflectContext* context);
static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required);
static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided);
static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible);
NetworkHierarchyChildComponent();
//! @{
void OnInit() override;
void OnActivate(Multiplayer::EntityIsMigrating entityIsMigrating) override;
void OnDeactivate(Multiplayer::EntityIsMigrating entityIsMigrating) override;
//! @}
//! NetworkHierarchyRequestBus overrides
//! @{
bool IsHierarchicalChild() const override;
bool IsHierarchicalRoot() const override { return false; }
AZ::Entity* GetHierarchicalRoot() const override;
AZStd::vector<AZ::Entity*> GetHierarchicalEntities() const override;
//! @}
protected:
//! Used by @NetworkHierarchyRootComponent
void SetTopLevelHierarchyRootComponent(NetworkHierarchyRootComponent* hierarchyRoot);
private:
const NetworkHierarchyRootComponent* m_hierarchyRootComponent = nullptr;
AZ::Event<NetEntityId>::Handler m_hierarchyRootNetIdChanged;
void OnHierarchyRootNetIdChanged(NetEntityId rootNetId);
};
}
@@ -0,0 +1,76 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzCore/Component/Component.h>
#include <AzCore/Component/TransformBus.h>
#include <Source/AutoGen/NetworkHierarchyRootComponent.AutoComponent.h>
#include <Multiplayer/Components/NetworkHierarchyBus.h>
namespace Multiplayer
{
//! @class NetworkHierarchyRootComponent
//! @brief Component that declares the top level entity of a network hierarchy.
/*
* Call @GetHierarchyChildren to get the list of hierarchical entities.
* A network hierarchy is meant to be a small group of entities. You can control the maximum supported size of
* a network hierarchy by modifying CVar @bg_hierarchyEntityMaxLimit.
*
* A root component marks either a top most root of a hierarchy, or an inner root of an attach hierarchy.
*/
class NetworkHierarchyRootComponent final
: public NetworkHierarchyRootComponentBase
, public NetworkHierarchyRequestBus::Handler
, protected AZ::TransformNotificationBus::MultiHandler
{
public:
AZ_MULTIPLAYER_COMPONENT(Multiplayer::NetworkHierarchyRootComponent, s_networkHierarchyRootComponentConcreteUuid, Multiplayer::NetworkHierarchyRootComponentBase);
static void Reflect(AZ::ReflectContext* context);
static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required);
static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided);
static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible);
//! NetworkHierarchyRootComponentBase overrides.
//! @{
void OnInit() override;
void OnActivate(Multiplayer::EntityIsMigrating entityIsMigrating) override;
void OnDeactivate(Multiplayer::EntityIsMigrating entityIsMigrating) override;
//! @}
//! NetworkHierarchyRequestBus overrides.
//! @{
bool IsHierarchicalRoot() const override;
bool IsHierarchicalChild() const override;
AZStd::vector<AZ::Entity*> GetHierarchicalEntities() const override;
AZ::Entity* GetHierarchicalRoot() const override;
//! @}
protected:
//! AZ::TransformNotificationBus::Handler overrides.
//! @{
void OnParentChanged(AZ::EntityId oldParent, AZ::EntityId newParent) override;
void OnChildAdded(AZ::EntityId child) override;
void OnChildRemoved(AZ::EntityId childRemovedId) override;
//! @}
void SetTopLevelHierarchyRootEntity(AZ::Entity* hierarchyRoot);
private:
AZ::Entity* m_higherRootEntity = nullptr;
AZStd::vector<AZ::Entity*> m_hierarchicalEntities;
void RebuildHierarchy();
//! @returns false if the maximum supported hierarchy size has been reached
bool RecursiveAttachHierarchicalEntities(AZ::EntityId underEntity, uint32_t& currentEntityCount);
//! @returns false if the maximum supported hierarchy size has been reached
bool RecursiveAttachHierarchicalChild(AZ::EntityId entity, uint32_t& currentEntityCount);
};
}
@@ -36,6 +36,7 @@ namespace Multiplayer
void OnTranslationChangedEvent(const AZ::Vector3& translation);
void OnScaleChangedEvent(float scale);
void OnResetCountChangedEvent();
void OnParentIdChangedEvent(NetEntityId newParent);
void UpdateTargetHostFrameId();
@@ -46,6 +47,7 @@ namespace Multiplayer
AZ::Event<AZ::Vector3>::Handler m_translationEventHandler;
AZ::Event<float>::Handler m_scaleEventHandler;
AZ::Event<uint8_t>::Handler m_resetCountEventHandler;
AZ::Event<NetEntityId>::Handler m_parentIdChangedEventHandler;
EntityPreRenderEvent::Handler m_entityPreRenderEventHandler;
EntityCorrectionEvent::Handler m_entityCorrectionEventHandler;
@@ -64,7 +66,9 @@ namespace Multiplayer
private:
void OnTransformChangedEvent(const AZ::Transform& worldTm);
void OnParentIdChangedEvent(AZ::EntityId oldParent, AZ::EntityId newParent);
AZ::TransformChangedEvent::Handler m_transformChangedHandler;
AZ::ParentChangedEvent::Handler m_parentIdChangedHandler;
};
}