diff --git a/AutomatedTesting/surfacetypemateriallibrary.physmaterial b/AutomatedTesting/surfacetypemateriallibrary.physmaterial
index 434d673998..481cd2fbfa 100644
--- a/AutomatedTesting/surfacetypemateriallibrary.physmaterial
+++ b/AutomatedTesting/surfacetypemateriallibrary.physmaterial
@@ -4,17 +4,152 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp b/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp
index 1010ae3473..7b33359023 100644
--- a/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp
+++ b/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp
@@ -77,6 +77,27 @@
#endif // defined(AZ_ENABLE_DEBUG_TOOLS)
#include
+#include
+
+static void PrintEntityName(const AZ::ConsoleCommandContainer& arguments)
+{
+ if (arguments.empty())
+ {
+ return;
+ }
+
+ const auto entityIdStr = AZStd::string(arguments.front());
+ const auto entityIdValue = AZStd::stoull(entityIdStr);
+
+ AZStd::string entityName;
+ AZ::ComponentApplicationBus::BroadcastResult(
+ entityName, &AZ::ComponentApplicationBus::Events::GetEntityName, AZ::EntityId(entityIdValue));
+
+ AZ_Printf("Entity Debug", "EntityId: %" PRIu64 ", Entity Name: %s", entityIdValue, entityName.c_str());
+}
+
+AZ_CONSOLEFREEFUNC(
+ PrintEntityName, AZ::ConsoleFunctorFlags::Null, "Parameter: EntityId value, Prints the name of the entity to the console");
namespace AZ
{
diff --git a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp
index d5f02c957c..559f7ce460 100644
--- a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp
+++ b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp
@@ -29,7 +29,7 @@ namespace AzFramework
AZ_CVAR(float, ed_cameraSystemOrbitDollyScrollSpeed, 0.02f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
AZ_CVAR(float, ed_cameraSystemOrbitDollyCursorSpeed, 0.01f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
AZ_CVAR(float, ed_cameraSystemScrollTranslateSpeed, 0.02f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
- AZ_CVAR(float, ed_cameraSystemMinOrbitDistance, 6.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
+ AZ_CVAR(float, ed_cameraSystemMinOrbitDistance, 10.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
AZ_CVAR(float, ed_cameraSystemMaxOrbitDistance, 50.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
AZ_CVAR(float, ed_cameraSystemLookSmoothness, 5.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
AZ_CVAR(float, ed_cameraSystemTranslateSmoothness, 5.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
@@ -37,7 +37,6 @@ namespace AzFramework
AZ_CVAR(float, ed_cameraSystemPanSpeed, 0.01f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
AZ_CVAR(bool, ed_cameraSystemPanInvertX, true, nullptr, AZ::ConsoleFunctorFlags::Null, "");
AZ_CVAR(bool, ed_cameraSystemPanInvertY, true, nullptr, AZ::ConsoleFunctorFlags::Null, "");
- AZ_CVAR(float, ed_cameraSystemLookDeadzone, 2.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
AZ_CVAR(
AZ::CVarFixedString, ed_cameraSystemTranslateForwardKey, "keyboard_key_alphanumeric_W", nullptr, AZ::ConsoleFunctorFlags::Null, "");
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp
index e4507227b5..d7de634c11 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp
@@ -303,6 +303,45 @@ namespace AzToolsFramework
return true;
}
+ bool PrefabLoader::SaveTemplateToFile(TemplateId templateId, AZ::IO::PathView absolutePath)
+ {
+ AZ_Assert(absolutePath.IsAbsolute(), "SaveTemplateToFile requires an absolute path for saving the initial prefab file.");
+
+ const auto& domAndFilepath = StoreTemplateIntoFileFormat(templateId);
+ if (!domAndFilepath)
+ {
+ return false;
+ }
+
+ // Verify that the absolute path provided to this matches the relative path saved in the template.
+ // Otherwise, the saved prefab won't be able to be loaded.
+ auto relativePath = GenerateRelativePath(absolutePath);
+ if (relativePath != domAndFilepath->second)
+ {
+ AZ_Error(
+ "Prefab", false,
+ "PrefabLoader::SaveTemplateToFile - "
+ "Failed to save template '%s' to location '%.*s'."
+ "Error: Relative path '%.*s' for location didn't match template name.",
+ domAndFilepath->second.c_str(), AZ_STRING_ARG(absolutePath.Native()), AZ_STRING_ARG(relativePath.Native()));
+ return false;
+ }
+
+ auto outcome = AzFramework::FileFunc::WriteJsonFile(domAndFilepath->first, absolutePath);
+ if (!outcome.IsSuccess())
+ {
+ AZ_Error(
+ "Prefab", false,
+ "PrefabLoader::SaveTemplateToFile - "
+ "Failed to save template '%s' to location '%.*s'."
+ "Error: %s",
+ domAndFilepath->second.c_str(), AZ_STRING_ARG(absolutePath.Native()), outcome.GetError().c_str());
+ return false;
+ }
+ m_prefabSystemComponentInterface->SetTemplateDirtyFlag(templateId, false);
+ return true;
+ }
+
bool PrefabLoader::SaveTemplateToString(TemplateId templateId, AZStd::string& output)
{
const auto& domAndFilepath = StoreTemplateIntoFileFormat(templateId);
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.h
index aed24e153e..3722e14a97 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.h
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.h
@@ -72,6 +72,16 @@ namespace AzToolsFramework
*/
bool SaveTemplate(TemplateId templateId) override;
+ /**
+ * Saves a Prefab Template to the provided absolute source path, which needs to match the relative path in the template.
+ * Converts Prefab Template form into .prefab form by collapsing nested Template info
+ * into a source path and patches.
+ * @param templateId Id of the template to be saved
+ * @param absolutePath Absolute path to save the file to
+ * @return bool on whether the operation succeeded or not
+ */
+ bool SaveTemplateToFile(TemplateId templateId, AZ::IO::PathView absolutePath) override;
+
/**
* Saves a Prefab Template into the provided output string.
* Converts Prefab Template form into .prefab form by collapsing nested Template info
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoaderInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoaderInterface.h
index d71fbff80f..0e551cee6b 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoaderInterface.h
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoaderInterface.h
@@ -60,6 +60,16 @@ namespace AzToolsFramework
*/
virtual bool SaveTemplate(TemplateId templateId) = 0;
+ /**
+ * Saves a Prefab Template to the provided absolute source path, which needs to match the relative path in the template.
+ * Converts Prefab Template form into .prefab form by collapsing nested Template info
+ * into a source path and patches.
+ * @param templateId Id of the template to be saved
+ * @param absolutePath Absolute path to save the file to
+ * @return bool on whether the operation succeeded or not
+ */
+ virtual bool SaveTemplateToFile(TemplateId templateId, AZ::IO::PathView absolutePath) = 0;
+
/**
* Saves a Prefab Template into the provided output string.
* Converts Prefab Template form into .prefab form by collapsing nested Template info
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp
index 9dd5199ea2..fadcc1b81f 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp
@@ -64,7 +64,7 @@ namespace AzToolsFramework
m_prefabUndoCache.Destroy();
}
- PrefabOperationResult PrefabPublicHandler::CreatePrefab(const AZStd::vector& entityIds, AZ::IO::PathView filePath)
+ PrefabOperationResult PrefabPublicHandler::CreatePrefab(const AZStd::vector& entityIds, AZ::IO::PathView absolutePath)
{
EntityList inputEntityList, topLevelEntities;
AZ::EntityId commonRootEntityId;
@@ -76,6 +76,8 @@ namespace AzToolsFramework
return findCommonRootOutcome;
}
+ AZ_Assert(absolutePath.IsAbsolute(), "CreatePrefab requires an absolute path for saving the initial prefab file.");
+
InstanceOptionalReference instanceToCreate;
{
// Initialize Undo Batch object
@@ -144,7 +146,8 @@ namespace AzToolsFramework
// Create the Prefab
instanceToCreate = prefabEditorEntityOwnershipInterface->CreatePrefab(
- entities, AZStd::move(instancePtrs), filePath, commonRootEntityOwningInstance);
+ entities, AZStd::move(instancePtrs), m_prefabLoaderInterface->GenerateRelativePath(absolutePath),
+ commonRootEntityOwningInstance);
if (!instanceToCreate)
{
@@ -254,7 +257,7 @@ namespace AzToolsFramework
}
// Save Template to file
- m_prefabLoaderInterface->SaveTemplate(instanceToCreate->get().GetTemplateId());
+ m_prefabLoaderInterface->SaveTemplateToFile(instanceToCreate->get().GetTemplateId(), absolutePath);
return AZ::Success();
}
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.h
index 7e2357dd44..e68a3e0b1e 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.h
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.h
@@ -46,7 +46,7 @@ namespace AzToolsFramework
void UnregisterPrefabPublicHandlerInterface();
// PrefabPublicInterface...
- PrefabOperationResult CreatePrefab(const AZStd::vector& entityIds, AZ::IO::PathView filePath) override;
+ PrefabOperationResult CreatePrefab(const AZStd::vector& entityIds, AZ::IO::PathView absolutePath) override;
PrefabOperationResult InstantiatePrefab(AZStd::string_view filePath, AZ::EntityId parent, const AZ::Vector3& position) override;
PrefabOperationResult SavePrefab(AZ::IO::Path filePath) override;
PrefabEntityResult CreateEntity(AZ::EntityId parentId, const AZ::Vector3& position) override;
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicInterface.h
index 0750c4d264..2e9152fd1b 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicInterface.h
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicInterface.h
@@ -46,10 +46,10 @@ namespace AzToolsFramework
* Create a prefab out of the entities provided, at the path provided.
* Automatically detects descendants of entities, and discerns between entities and child instances.
* @param entityIds The entities that should form the new prefab (along with their descendants).
- * @param filePath The path for the new prefab file.
+ * @param filePath The absolute path for the new prefab file.
* @return An outcome object; on failure, it comes with an error message detailing the cause of the error.
*/
- virtual PrefabOperationResult CreatePrefab(const AZStd::vector& entityIds, AZ::IO::PathView filePath) = 0;
+ virtual PrefabOperationResult CreatePrefab(const AZStd::vector& entityIds, AZ::IO::PathView absolutePath) = 0;
/**
* Instantiate a prefab from a prefab file.
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp
index 61d4433c0e..021b97a7dd 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp
@@ -333,8 +333,7 @@ namespace AzToolsFramework
}
}
- auto createPrefabOutcome = s_prefabPublicInterface->CreatePrefab(
- selectedEntities, s_prefabLoaderInterface->GenerateRelativePath(prefabFilePath.data()));
+ auto createPrefabOutcome = s_prefabPublicInterface->CreatePrefab(selectedEntities, prefabFilePath.data());
if (!createPrefabOutcome.IsSuccess())
{
diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/ModularViewportCameraController.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/ModularViewportCameraController.cpp
index 6fb3edfa22..896d9f8043 100644
--- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/ModularViewportCameraController.cpp
+++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/ModularViewportCameraController.cpp
@@ -15,6 +15,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -24,6 +25,11 @@
namespace AtomToolsFramework
{
+ AZ_CVAR(
+ AZ::Color, ed_cameraSystemOrbitPointColor, AZ::Color::CreateFromRgba(255, 255, 255, 255), nullptr, AZ::ConsoleFunctorFlags::Null,
+ "");
+ AZ_CVAR(float, ed_cameraSystemOrbitPointSize, 0.5f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
+
// debug
void DrawPreviewAxis(AzFramework::DebugDisplayRequests& display, const AZ::Transform& transform, const float axisLength)
{
@@ -73,7 +79,8 @@ namespace AtomToolsFramework
if (auto viewportContext = RetrieveViewportContext(GetViewportId()))
{
- auto handleCameraChange = [this, viewportContext](const AZ::Matrix4x4&) {
+ auto handleCameraChange = [this, viewportContext](const AZ::Matrix4x4&)
+ {
if (!m_updatingTransform)
{
UpdateCameraFromTransform(m_targetCamera, viewportContext->GetCameraTransform());
@@ -137,7 +144,10 @@ namespace AtomToolsFramework
}
else if (m_cameraMode == CameraMode::Animation)
{
- const auto smootherStepFn = [](const float t) { return t * t * t * (t * (t * 6.0f - 15.0f) + 10.0f); };
+ const auto smootherStepFn = [](const float t)
+ {
+ return t * t * t * (t * (t * 6.0f - 15.0f) + 10.0f);
+ };
const float transitionT = smootherStepFn(m_animationT);
const AZ::Transform current = AZ::Transform::CreateFromQuaternionAndTranslation(
@@ -169,8 +179,9 @@ namespace AtomToolsFramework
{
if (const float alpha = AZStd::min(-m_camera.m_lookDist / 5.0f, 1.0f); alpha > AZ::Constants::FloatEpsilon)
{
- debugDisplay.SetColor(1.0f, 1.0f, 1.0f, alpha);
- debugDisplay.DrawWireSphere(m_camera.m_lookAt, 0.5f);
+ const AZ::Color orbitPointColor = ed_cameraSystemOrbitPointColor;
+ debugDisplay.SetColor(orbitPointColor.GetR(), orbitPointColor.GetG(), orbitPointColor.GetB(), alpha);
+ debugDisplay.DrawWireSphere(m_camera.m_lookAt, ed_cameraSystemOrbitPointSize);
}
}
diff --git a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Header.jinja b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Header.jinja
index 8cf1eeeb58..79fbb4a99e 100644
--- a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Header.jinja
+++ b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Header.jinja
@@ -383,6 +383,8 @@ namespace {{ Component.attrib['Namespace'] }}
{{ DeclareNetworkPropertyAccessors(Component, 'Authority', 'Client', true)|indent(8) -}}
{{ DeclareNetworkPropertyAccessors(Component, 'Authority', 'Autonomous', false)|indent(8) -}}
{{ DeclareNetworkPropertyAccessors(Component, 'Authority', 'Autonomous', true)|indent(8) -}}
+ {{ DeclareNetworkPropertyAccessors(Component, 'Autonomous', 'Authority', false)|indent(8) -}}
+ {{ DeclareNetworkPropertyAccessors(Component, 'Autonomous', 'Authority', true)|indent(8) -}}
{{ DeclareArchetypePropertyGetters(Component)|indent(8) -}}
{{ DeclareRpcInvocations(Component, 'Server', 'Authority', false)|indent(8) -}}
{{ DeclareRpcInvocations(Component, 'Server', 'Authority', true)|indent(8) -}}
@@ -456,7 +458,6 @@ namespace {{ Component.attrib['Namespace'] }}
{% endif %}
{{ DeclareNetworkPropertyGetters(Component, 'Authority', 'Server', false)|indent(8) -}}
- {{ DeclareNetworkPropertyGetters(Component, 'Authority', 'Autonomous', false)|indent(8) -}}
{{ DeclareNetworkPropertyGetters(Component, 'Authority', 'Client', false)|indent(8) -}}
{{ DeclareArchetypePropertyGetters(Component)|indent(8) -}}
{{ DeclareRpcInvocations(Component, 'Server', 'Authority', false)|indent(8) -}}
@@ -481,8 +482,6 @@ namespace {{ Component.attrib['Namespace'] }}
//! @}
{{ DeclareNetworkPropertyGetters(Component, 'Authority', 'Server', true)|indent(8) -}}
- {{ DeclareNetworkPropertyGetters(Component, 'Authority', 'Autonomous', true)|indent(8) -}}
- {{ DeclareNetworkPropertyGetters(Component, 'Autonomous', 'Authority', true)|indent(8) -}}
{{ DeclareNetworkPropertyGetters(Component, 'Authority', 'Client', true)|indent(8) -}}
{{ DeclareRpcInvocations(Component, 'Server', 'Authority', true)|indent(8) -}}
{{ AutoComponentMacros.DeclareRpcHandlers(Component, 'Authority', 'Client', false)|indent(8) -}}
diff --git a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja
index 0feff5c07c..5cfd0bfc4d 100644
--- a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja
+++ b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja
@@ -796,12 +796,27 @@ enum class NetworkProperties
AZ_Warning("Network Property", false, "{{ ClassName }} Get{{ UpperFirst(Property.attrib['Name']) }} failed. Entity '%s' (id: %s) is missing {{ ClassName }}, be sure to add {{ ClassName }} to this entity.", entity->GetName().c_str(), id.ToString().c_str())
return {{ Property.attrib['Type'] }}();
}
+{% if (ReplicateTo == 'Autonomous') or (ReplicateFrom == 'Autonomous' and ReplicateTo == 'Authority') %}
+ // {{ UpperFirst(Property.attrib['Name']) }} is only sent and received between contoller objects (ie Authority, Autonomous); we must go through the controller in order to get this property
+ {{ ClassName }}Controller* controller = static_cast<{{ ClassName }}Controller*>(networkComponent->GetController());
+ if (!controller)
+ {
+ AZ_Warning("Network Property", false, "{{ ClassName }} Get{{ UpperFirst(Property.attrib['Name']) }} method failed. Entity '%s' (id: %s) {{ ClassName }} is missing the network controller. This property is replicated to autonomous network entities, because this entity doesn't have a controller, it must not be automonous. Please check your network context before attempting to get {{ UpperFirst(Property.attrib['Name']) }}.", entity->GetName().c_str(), id.ToString().c_str())
+ return {{ Property.attrib['Type'] }}();
+ }
+{% if Property.attrib['Container'] == 'Vector' or Property.attrib['Container'] == 'Array' %}
+ return controller->Get{{ UpperFirst(Property.attrib['Name']) }}(index);
+{% else %}
+ return controller->Get{{ UpperFirst(Property.attrib['Name']) }}();
+{% endif %}
+{% else %}
{% if Property.attrib['Container'] == 'Vector' or Property.attrib['Container'] == 'Array' %}
return networkComponent->Get{{ UpperFirst(Property.attrib['Name']) }}(index);
{% else %}
return networkComponent->Get{{ UpperFirst(Property.attrib['Name']) }}();
{% endif %}
+{% endif %}
})
{% if Property.attrib['Container'] == 'Vector' or Property.attrib['Container'] == 'Array' %}
->Method("Set{{ UpperFirst(Property.attrib['Name']) }}", [](AZ::EntityId id, int32_t index, const {{ Property.attrib['Type'] }}& value) -> void
@@ -1480,12 +1495,8 @@ namespace {{ Component.attrib['Namespace'] }}
}
{{ DefineNetworkPropertyGets(Component, 'Authority', 'Server', false, ComponentBaseName)|indent(4) -}}
-{{ DefineNetworkPropertyGets(Component, 'Authority', 'Autonomous', false, ComponentBaseName)|indent(4) -}}
-{{ DefineNetworkPropertyGets(Component, 'Autonomous', 'Authority', false, ComponentBaseName)|indent(4) -}}
{{ DefineNetworkPropertyGets(Component, 'Authority', 'Client', false, ComponentBaseName)|indent(4) -}}
{{ DefineNetworkPropertyGets(Component, 'Authority', 'Server', true, ComponentBaseName)|indent(4) -}}
-{{ DefineNetworkPropertyGets(Component, 'Authority', 'Autonomous', true, ComponentBaseName)|indent(4) -}}
-{{ DefineNetworkPropertyGets(Component, 'Autonomous', 'Authority', true, ComponentBaseName)|indent(4) -}}
{{ DefineNetworkPropertyGets(Component, 'Authority', 'Client', true, ComponentBaseName)|indent(4) }}
{{ DefineArchetypePropertyGets(Component, ClassType, ComponentBaseName)|indent(4) -}}
{{ DefineRpcInvocations(Component, ComponentBaseName, 'Server', 'Authority', false)|indent(4) -}}
diff --git a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp
index ef8627fe54..0818f605df 100644
--- a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp
+++ b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp
@@ -438,19 +438,16 @@ namespace Multiplayer
m_connAcquiredEvent.Signal(datum);
}
+ // Hosts will spawn a new default player prefab for the user that just connected
if (GetAgentType() == MultiplayerAgentType::ClientServer
|| GetAgentType() == MultiplayerAgentType::DedicatedServer)
{
- PrefabEntityId playerPrefabEntityId(AZ::Name(static_cast(sv_defaultPlayerSpawnAsset).c_str()), 1);
- INetworkEntityManager::EntityList entityList = m_networkEntityManager.CreateEntitiesImmediate(playerPrefabEntityId, NetEntityRole::Authority, AZ::Transform::CreateIdentity());
-
- NetworkEntityHandle controlledEntity;
- if (entityList.size() > 0)
+ NetworkEntityHandle controlledEntity = SpawnDefaultPlayerPrefab();
+ if (controlledEntity.Exists())
{
- controlledEntity = entityList[0];
controlledEntity.GetNetBindComponent()->SetOwningConnectionId(connection->GetConnectionId());
}
-
+
if (connection->GetUserData() == nullptr) // Only add user data if the connect event handler has not already done so
{
connection->SetUserData(new ServerToClientConnectionData(connection, *this, controlledEntity));
@@ -522,6 +519,17 @@ namespace Multiplayer
}
}
m_agentType = multiplayerType;
+
+ // Spawn the default player for this host since the host is also a player (not a dedicated server)
+ if (m_agentType == MultiplayerAgentType::ClientServer)
+ {
+ NetworkEntityHandle controlledEntity = SpawnDefaultPlayerPrefab();
+ if (NetBindComponent* controlledEntityNetBindComponent = controlledEntity.GetNetBindComponent())
+ {
+ controlledEntityNetBindComponent->SetAllowAutonomy(true);
+ }
+ }
+
AZLOG_INFO("Multiplayer operating in %s mode", GetEnumString(m_agentType));
}
@@ -629,6 +637,19 @@ namespace Multiplayer
}
}
+ NetworkEntityHandle MultiplayerSystemComponent::SpawnDefaultPlayerPrefab()
+ {
+ PrefabEntityId playerPrefabEntityId(AZ::Name(static_cast(sv_defaultPlayerSpawnAsset).c_str()), 1);
+ INetworkEntityManager::EntityList entityList = m_networkEntityManager.CreateEntitiesImmediate(playerPrefabEntityId, NetEntityRole::Authority, AZ::Transform::CreateIdentity());
+
+ NetworkEntityHandle controlledEntity;
+ if (entityList.size() > 0)
+ {
+ controlledEntity = entityList[0];
+ }
+ return controlledEntity;
+ }
+
void host([[maybe_unused]] const AZ::ConsoleCommandContainer& arguments)
{
Multiplayer::MultiplayerAgentType serverType = sv_isDedicated ? MultiplayerAgentType::DedicatedServer : MultiplayerAgentType::ClientServer;
diff --git a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h
index db83c50fb5..e8e05a9d4c 100644
--- a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h
+++ b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h
@@ -104,7 +104,8 @@ namespace Multiplayer
void OnConsoleCommandInvoked(AZStd::string_view command, const AZ::ConsoleCommandContainer& args, AZ::ConsoleFunctorFlags flags, AZ::ConsoleInvokedFrom invokedFrom);
void ExecuteConsoleCommandList(AzNetworking::IConnection* connection, const AZStd::fixed_vector& commands);
-
+ NetworkEntityHandle SpawnDefaultPlayerPrefab();
+
AZ_CONSOLEFUNC(MultiplayerSystemComponent, DumpStats, AZ::ConsoleFunctorFlags::Null, "Dumps stats for the current multiplayer session");
AzNetworking::INetworkInterface* m_networkInterface = nullptr;
diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp
index dda3f18ad4..eaf89f3489 100644
--- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp
+++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp
@@ -402,8 +402,12 @@ namespace Multiplayer
const AZ::Transform& transform
)
{
- INetworkEntityManager::EntityList returnList;
-
+ EntityList returnList;
+ if (!AZ::Data::AssetManager::IsReady())
+ {
+ return returnList;
+ }
+
auto spawnableAssetId = m_networkPrefabLibrary.GetAssetIdByName(prefabEntryId.m_prefabName);
// Required for sync-instantiation. Todo: keep the reference in NetworkSpawnableLibrary
auto netSpawnableAsset = AZ::Data::AssetManager::Instance().GetAsset(spawnableAssetId, AZ::Data::AssetLoadBehavior::PreLoad);
diff --git a/Gems/PhysX/Code/CMakeLists.txt b/Gems/PhysX/Code/CMakeLists.txt
index b0318af9f2..d281270ce4 100644
--- a/Gems/PhysX/Code/CMakeLists.txt
+++ b/Gems/PhysX/Code/CMakeLists.txt
@@ -128,6 +128,9 @@ if(PAL_TRAIT_BUILD_HOST_TOOLS)
AUTOMOC
FILES_CMAKE
physx_editor_shared_files.cmake
+ COMPILE_DEFINITIONS
+ PUBLIC
+ PHYSX_ENABLE_MULTI_THREADING
INCLUDE_DIRECTORIES
PRIVATE
.
diff --git a/Gems/PythonAssetBuilder/Code/CMakeLists.txt b/Gems/PythonAssetBuilder/Code/CMakeLists.txt
index 4af266f56d..73fa90ab67 100644
--- a/Gems/PythonAssetBuilder/Code/CMakeLists.txt
+++ b/Gems/PythonAssetBuilder/Code/CMakeLists.txt
@@ -13,24 +13,11 @@ if(NOT PAL_TRAIT_BUILD_HOST_TOOLS)
return()
endif()
-set(static_files pythonassetbuilder_common_files.cmake)
-set(editor_files pythonassetbuilder_editor_files.cmake)
-set(shared_files pythonassetbuilder_shared_files.cmake)
-set(static_dependencies
- 3rdParty::Python
- Gem::EditorPythonBindings.Static
- AZ::AssetBuilderSDK
-)
-set(editor_dependencies
- Gem::EditorPythonBindings.Static
- AZ::AssetBuilderSDK
-)
-
ly_add_target(
NAME PythonAssetBuilder.Static STATIC
NAMESPACE Gem
FILES_CMAKE
- ${static_files}
+ pythonassetbuilder_common_files.cmake
PLATFORM_INCLUDE_FILES
Source/Platform/Common/${PAL_TRAIT_COMPILER_ID}/pythonassetbuilder_static_${PAL_TRAIT_COMPILER_ID_LOWERCASE}.cmake
INCLUDE_DIRECTORIES
@@ -43,7 +30,9 @@ ly_add_target(
PRIVATE
AZ::AzCore
PUBLIC
- ${static_dependencies}
+ 3rdParty::Python
+ Gem::EditorPythonBindings.Static
+ AZ::AssetBuilderSDK
AZ::AzToolsFramework
)
@@ -52,8 +41,8 @@ ly_add_target(
NAMESPACE Gem
FILES_CMAKE
- ${editor_files}
- ${shared_files}
+ pythonassetbuilder_editor_files.cmake
+ pythonassetbuilder_shared_files.cmake
PLATFORM_INCLUDE_FILES
Source/Platform/Common/${PAL_TRAIT_COMPILER_ID}/pythonassetbuilder_static_${PAL_TRAIT_COMPILER_ID_LOWERCASE}.cmake
INCLUDE_DIRECTORIES
@@ -64,7 +53,8 @@ ly_add_target(
Include
BUILD_DEPENDENCIES
PRIVATE
- ${editor_dependencies}
+ Gem::EditorPythonBindings.Static
+ AZ::AssetBuilderSDK
RUNTIME_DEPENDENCIES
Gem::EditorPythonBindings.Editor
)
diff --git a/cmake/Platform/Common/RuntimeDependencies_common.cmake b/cmake/Platform/Common/RuntimeDependencies_common.cmake
index d9d0fe4c7f..4ae914744f 100644
--- a/cmake/Platform/Common/RuntimeDependencies_common.cmake
+++ b/cmake/Platform/Common/RuntimeDependencies_common.cmake
@@ -105,7 +105,7 @@ function(ly_get_runtime_dependencies ly_RUNTIME_DEPENDENCIES ly_TARGET)
set(skip_imported TRUE)
endif()
endif()
- if(target_type MATCHES "(INTERFACE_LIBRARY|STATIC_LIBRARY)")
+ if(target_type MATCHES "(STATIC_LIBRARY)")
# No need to copy these dependencies since the outputs are not used at runtime
set(skip_imported TRUE)
endif()