Merge branch 'main' into hultonha_LYN-2528_whitebox_prefab
This commit is contained in:
@@ -18,3 +18,4 @@ _savebackup/
|
||||
#Output folder for test results when running Automated Tests
|
||||
TestResults/**
|
||||
*.swatches
|
||||
/imgui.ini
|
||||
|
||||
@@ -138,6 +138,7 @@ endif()
|
||||
if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
|
||||
ly_add_pytest(
|
||||
NAME AutomatedTesting::BlastTests
|
||||
TEST_SUITE sandbox
|
||||
TEST_SERIAL TRUE
|
||||
PATH ${CMAKE_CURRENT_LIST_DIR}/Blast/TestSuite_Active.py
|
||||
TIMEOUT 3600
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace AZ
|
||||
{
|
||||
class Transform;
|
||||
|
||||
using TransformChangedEvent = Event<Transform, Transform>;
|
||||
using TransformChangedEvent = Event<const Transform&, const Transform&>;
|
||||
|
||||
using ParentChangedEvent = Event<EntityId, EntityId>;
|
||||
|
||||
|
||||
@@ -114,6 +114,9 @@ namespace AzNetworking
|
||||
void ClearUnusedBits();
|
||||
|
||||
ContainerType m_container;
|
||||
|
||||
template <AZStd::size_t, typename>
|
||||
friend class FixedSizeVectorBitset;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -192,19 +192,11 @@ namespace AzNetworking
|
||||
template <AZStd::size_t CAPACITY, typename ElementType>
|
||||
inline void FixedSizeVectorBitset<CAPACITY, ElementType>::ClearUnusedBits()
|
||||
{
|
||||
constexpr ElementType AllOnes = static_cast<ElementType>(~0);
|
||||
const ElementType LastUsedBits = (GetSize() % BitsetType::ElementTypeBits);
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4293) // shift count negative or too big, undefined behaviour
|
||||
#pragma warning(disable : 6326) // constant constant comparison
|
||||
const ElementType ShiftAmount = (LastUsedBits == 0) ? 0 : BitsetType::ElementTypeBits - LastUsedBits;
|
||||
const ElementType ClearBitMask = AllOnes >> ShiftAmount;
|
||||
#pragma warning(pop)
|
||||
uint32_t usedElementSize = (GetSize() + BitsetType::ElementTypeBits - 1) / BitsetType::ElementTypeBits;
|
||||
for (uint32_t i = usedElementSize + 1; i < CAPACITY; ++i)
|
||||
for (uint32_t i = usedElementSize + 1; i < BitsetType::ElementCount; ++i)
|
||||
{
|
||||
m_bitset.GetContainer()[i] = 0;
|
||||
}
|
||||
m_bitset.GetContainer()[m_bitset.GetContainer().size() - 1] &= ClearBitMask;
|
||||
m_bitset.ClearUnusedBits();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -270,7 +270,7 @@ namespace AzNetworking
|
||||
value.StoreToFloat3(values);
|
||||
serializer.Serialize(values[0], "xValue");
|
||||
serializer.Serialize(values[1], "yValue");
|
||||
serializer.Serialize(values[1], "zValue");
|
||||
serializer.Serialize(values[2], "zValue");
|
||||
value = AZ::Vector3::CreateFromFloat3(values);
|
||||
return serializer.IsValid();
|
||||
}
|
||||
@@ -285,8 +285,8 @@ namespace AzNetworking
|
||||
value.StoreToFloat4(values);
|
||||
serializer.Serialize(values[0], "xValue");
|
||||
serializer.Serialize(values[1], "yValue");
|
||||
serializer.Serialize(values[1], "zValue");
|
||||
serializer.Serialize(values[1], "wValue");
|
||||
serializer.Serialize(values[2], "zValue");
|
||||
serializer.Serialize(values[3], "wValue");
|
||||
value = AZ::Vector4::CreateFromFloat4(values);
|
||||
return serializer.IsValid();
|
||||
}
|
||||
@@ -301,8 +301,8 @@ namespace AzNetworking
|
||||
value.StoreToFloat4(values);
|
||||
serializer.Serialize(values[0], "xValue");
|
||||
serializer.Serialize(values[1], "yValue");
|
||||
serializer.Serialize(values[1], "zValue");
|
||||
serializer.Serialize(values[1], "wValue");
|
||||
serializer.Serialize(values[2], "zValue");
|
||||
serializer.Serialize(values[3], "wValue");
|
||||
value = AZ::Quaternion::CreateFromFloat4(values);
|
||||
return serializer.IsValid();
|
||||
}
|
||||
|
||||
@@ -256,6 +256,8 @@ namespace AzToolsFramework
|
||||
|
||||
m_userSettings = AZ::UserSettings::CreateFind<AssetEditorWidgetUserSettings>(k_assetEditorWidgetSettings, AZ::UserSettings::CT_LOCAL);
|
||||
|
||||
UpdateRecentFileListState();
|
||||
|
||||
QObject::connect(m_recentFileMenu, &QMenu::aboutToShow, this, &AssetEditorWidget::PopulateRecentMenu);
|
||||
}
|
||||
|
||||
@@ -952,7 +954,8 @@ namespace AzToolsFramework
|
||||
|
||||
void AssetEditorWidget::AddRecentPath(const AZStd::string& recentPath)
|
||||
{
|
||||
m_userSettings->AddRecentPath(recentPath);
|
||||
m_userSettings->AddRecentPath(recentPath);
|
||||
UpdateRecentFileListState();
|
||||
}
|
||||
|
||||
void AssetEditorWidget::PopulateRecentMenu()
|
||||
@@ -989,6 +992,21 @@ namespace AzToolsFramework
|
||||
m_saveAsAssetAction->setEnabled(true);
|
||||
}
|
||||
|
||||
void AssetEditorWidget::UpdateRecentFileListState()
|
||||
{
|
||||
if (m_recentFileMenu)
|
||||
{
|
||||
if (!m_userSettings || m_userSettings->m_recentPaths.empty())
|
||||
{
|
||||
m_recentFileMenu->setEnabled(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_recentFileMenu->setEnabled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace AssetEditor
|
||||
} // namespace AzToolsFramework
|
||||
|
||||
|
||||
@@ -122,6 +122,8 @@ namespace AzToolsFramework
|
||||
void OnCatalogAssetAdded(const AZ::Data::AssetId& assetId) override;
|
||||
void OnCatalogAssetRemoved(const AZ::Data::AssetId& assetId, const AZ::Data::AssetInfo& assetInfo) override;
|
||||
|
||||
void UpdateRecentFileListState();
|
||||
|
||||
private:
|
||||
void DirtyAsset();
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ namespace AzToolsFramework
|
||||
m_prefabUndoCache.Destroy();
|
||||
}
|
||||
|
||||
PrefabOperationResult PrefabPublicHandler::CreatePrefab(const AZStd::vector<AZ::EntityId>& entityIds, AZStd::string_view filePath)
|
||||
PrefabOperationResult PrefabPublicHandler::CreatePrefab(const AZStd::vector<AZ::EntityId>& entityIds, AZ::IO::PathView filePath)
|
||||
{
|
||||
// Retrieve entityList from entityIds
|
||||
EntityList inputEntityList;
|
||||
|
||||
@@ -42,7 +42,7 @@ namespace AzToolsFramework
|
||||
void UnregisterPrefabPublicHandlerInterface();
|
||||
|
||||
// PrefabPublicInterface...
|
||||
PrefabOperationResult CreatePrefab(const AZStd::vector<AZ::EntityId>& entityIds, AZStd::string_view filePath) override;
|
||||
PrefabOperationResult CreatePrefab(const AZStd::vector<AZ::EntityId>& entityIds, AZ::IO::PathView filePath) override;
|
||||
PrefabOperationResult InstantiatePrefab(AZStd::string_view filePath, AZ::EntityId parent, AZ::Vector3 position) override;
|
||||
PrefabOperationResult SavePrefab(AZ::IO::Path filePath) override;
|
||||
PrefabEntityResult CreateEntity(AZ::EntityId parentId, const AZ::Vector3& position) override;
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace AzToolsFramework
|
||||
* @param filePath The 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<AZ::EntityId>& entityIds, AZStd::string_view filePath) = 0;
|
||||
virtual PrefabOperationResult CreatePrefab(const AZStd::vector<AZ::EntityId>& entityIds, AZ::IO::PathView filePath) = 0;
|
||||
|
||||
/**
|
||||
* Instantiate a prefab from a prefab file.
|
||||
|
||||
+14
-2
@@ -24,6 +24,7 @@
|
||||
#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
|
||||
#include <AzToolsFramework/AssetBrowser/AssetSelectionModel.h>
|
||||
#include <AzToolsFramework/AssetBrowser/Entries/SourceAssetBrowserEntry.h>
|
||||
#include <AzToolsFramework/Prefab/PrefabLoaderInterface.h>
|
||||
#include <AzToolsFramework/ToolsComponents/EditorLayerComponentBus.h>
|
||||
#include <AzToolsFramework/UI/EditorEntityUi/EditorEntityUiInterface.h>
|
||||
#include <AzToolsFramework/UI/Prefab/PrefabIntegrationInterface.h>
|
||||
@@ -39,9 +40,12 @@ namespace AzToolsFramework
|
||||
{
|
||||
namespace Prefab
|
||||
{
|
||||
|
||||
EditorEntityUiInterface* PrefabIntegrationManager::s_editorEntityUiInterface = nullptr;
|
||||
PrefabPublicInterface* PrefabIntegrationManager::s_prefabPublicInterface = nullptr;
|
||||
PrefabEditInterface* PrefabIntegrationManager::s_prefabEditInterface = nullptr;
|
||||
PrefabLoaderInterface* PrefabIntegrationManager::s_prefabLoaderInterface = nullptr;
|
||||
|
||||
const AZStd::string PrefabIntegrationManager::s_prefabFileExtension = ".prefab";
|
||||
|
||||
void PrefabUserSettings::Reflect(AZ::ReflectContext* context)
|
||||
@@ -79,6 +83,13 @@ namespace AzToolsFramework
|
||||
return;
|
||||
}
|
||||
|
||||
s_prefabLoaderInterface = AZ::Interface<PrefabLoaderInterface>::Get();
|
||||
if (s_prefabLoaderInterface == nullptr)
|
||||
{
|
||||
AZ_Assert(false, "Prefab - could not get PrefabLoaderInterface on PrefabIntegrationManager construction.");
|
||||
return;
|
||||
}
|
||||
|
||||
EditorContextMenuBus::Handler::BusConnect();
|
||||
PrefabInstanceContainerNotificationBus::Handler::BusConnect();
|
||||
AZ::Interface<PrefabIntegrationInterface>::Register(this);
|
||||
@@ -320,14 +331,15 @@ namespace AzToolsFramework
|
||||
|
||||
GenerateSuggestedFilenameFromEntities(prefabRootEntities, suggestedName);
|
||||
|
||||
if (!QueryUserForPrefabSaveLocation(suggestedName, targetDirectory, AZ_CRC("PrefabUserSettings"), activeWindow, prefabName, prefabFilePath))
|
||||
if (!QueryUserForPrefabSaveLocation(
|
||||
suggestedName, targetDirectory, AZ_CRC("PrefabUserSettings"), activeWindow, prefabName, prefabFilePath))
|
||||
{
|
||||
// User canceled prefab creation, or error prevented continuation.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
auto createPrefabOutcome = s_prefabPublicInterface->CreatePrefab(selectedEntities, prefabFilePath);
|
||||
auto createPrefabOutcome = s_prefabPublicInterface->CreatePrefab(selectedEntities, s_prefabLoaderInterface->GetRelativePathToProject(prefabFilePath.data()));
|
||||
|
||||
if (!createPrefabOutcome.IsSuccess())
|
||||
{
|
||||
|
||||
@@ -29,6 +29,9 @@ namespace AzToolsFramework
|
||||
{
|
||||
namespace Prefab
|
||||
{
|
||||
|
||||
class PrefabLoaderInterface;
|
||||
|
||||
//! Structure for saving/retrieving user settings related to prefab workflows.
|
||||
class PrefabUserSettings
|
||||
: public AZ::UserSettings
|
||||
@@ -129,6 +132,7 @@ namespace AzToolsFramework
|
||||
static EditorEntityUiInterface* s_editorEntityUiInterface;
|
||||
static PrefabPublicInterface* s_prefabPublicInterface;
|
||||
static PrefabEditInterface* s_prefabEditInterface;
|
||||
static PrefabLoaderInterface* s_prefabLoaderInterface;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,6 +96,11 @@ bool LegacyViewportCameraControllerInstance::HandleMouseMove(
|
||||
speedScale *= gSettings.cameraFastMoveSpeed;
|
||||
}
|
||||
|
||||
if (m_inMoveMode || m_inOrbitMode || m_inRotateMode || m_inZoomMode)
|
||||
{
|
||||
m_totalMouseMoveDelta += (QPoint(currentMousePos.m_x, currentMousePos.m_y)-QPoint(previousMousePos.m_x, previousMousePos.m_y)).manhattanLength();
|
||||
}
|
||||
|
||||
if ((m_inRotateMode && m_inMoveMode) || m_inZoomMode)
|
||||
{
|
||||
Matrix34 m = AZTransformToLYTransform(viewportContext->GetCameraTransform());
|
||||
@@ -343,11 +348,15 @@ bool LegacyViewportCameraControllerInstance::HandleInputChannelEvent(const AzFra
|
||||
}
|
||||
|
||||
shouldCaptureCursor = true;
|
||||
// Record how much the cursor has been moved to see if we should own the mouse up event.
|
||||
m_totalMouseMoveDelta = 0;
|
||||
}
|
||||
else if (state == InputChannel::State::Ended)
|
||||
{
|
||||
m_inZoomMode = false;
|
||||
m_inRotateMode = false;
|
||||
// If we've moved the cursor more than a couple pixels, we should eat this mouse up event to prevent the context menu controller from seeing it.
|
||||
shouldConsumeEvent = m_totalMouseMoveDelta > 2;
|
||||
shouldCaptureCursor = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,6 +58,7 @@ namespace SandboxEditor
|
||||
bool m_inMoveMode = false;
|
||||
bool m_inOrbitMode = false;
|
||||
bool m_inZoomMode = false;
|
||||
int m_totalMouseMoveDelta = 0;
|
||||
float m_orbitDistance = 10.f;
|
||||
float m_moveSpeed = 1.f;
|
||||
AZ::Vector3 m_orbitTarget = {};
|
||||
|
||||
@@ -186,7 +186,7 @@ namespace AZ
|
||||
{
|
||||
for (const RPI::Pass* pass : passes)
|
||||
{
|
||||
m_timestampEntries.push_back({ pass->GetName(), pass->GetTimestampResult().GetTimestampInNanoseconds() });
|
||||
m_timestampEntries.push_back({pass->GetName(), pass->GetLatestTimestampResult().GetDurationInNanoseconds()});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -223,7 +223,7 @@ namespace AZ
|
||||
{
|
||||
for (const RPI::Pass* pass : passes)
|
||||
{
|
||||
m_pipelineStatisticsEntries.push_back({ pass->GetName(), pass->GetPipelineStatisticsResult() });
|
||||
m_pipelineStatisticsEntries.push_back({pass->GetName(), pass->GetLatestPipelineStatisticsResult()});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <Atom/RHI.Reflect/AttachmentEnums.h>
|
||||
#include <Atom/RHI.Reflect/QueryPoolDescriptor.h>
|
||||
|
||||
#include <AtomCore/std/containers/array_view.h>
|
||||
@@ -43,15 +44,19 @@ namespace AZ
|
||||
{
|
||||
public:
|
||||
TimestampResult() = default;
|
||||
TimestampResult(uint64_t timestampInTicks);
|
||||
TimestampResult(uint64_t timestampQueryResultLow, uint64_t timestampQueryResultHigh);
|
||||
TimestampResult(AZStd::array_view<TimestampResult>&& timestampResultArray);
|
||||
TimestampResult(uint64_t beginTick, uint64_t endTick, RHI::HardwareQueueClass hardwareQueueClass);
|
||||
|
||||
uint64_t GetTimestampInNanoseconds() const;
|
||||
uint64_t GetTimestampInTicks() const;
|
||||
uint64_t GetDurationInNanoseconds() const;
|
||||
uint64_t GetDurationInTicks() const;
|
||||
uint64_t GetTimestampBeginInTicks() const;
|
||||
|
||||
void Add(const TimestampResult& extent);
|
||||
|
||||
private:
|
||||
uint64_t m_timestampInTicks = 0u;
|
||||
// the timestamp of begin and duration in ticks.
|
||||
uint64_t m_begin = 0;
|
||||
uint64_t m_duration = 0;
|
||||
RHI::HardwareQueueClass m_hardwareQueueClass = RHI::HardwareQueueClass::Graphics;
|
||||
};
|
||||
|
||||
//! The structure that is used to read back the results form the PipelineStatistics queries
|
||||
|
||||
@@ -122,7 +122,6 @@ namespace AZ
|
||||
|
||||
private:
|
||||
// RPI::Pass overrides...
|
||||
TimestampResult GetTimestampResultInternal() const override;
|
||||
PipelineStatisticsResult GetPipelineStatisticsResultInternal() const override;
|
||||
|
||||
// --- Hierarchy related functions ---
|
||||
|
||||
@@ -211,11 +211,11 @@ namespace AZ
|
||||
//! Prints the pass
|
||||
virtual void DebugPrint() const;
|
||||
|
||||
//! Return the Timestamp result of this pass
|
||||
TimestampResult GetTimestampResult() const;
|
||||
//! Return the latest Timestamp result of this pass
|
||||
TimestampResult GetLatestTimestampResult() const;
|
||||
|
||||
//! Return the PipelineStatistic result of this pass
|
||||
PipelineStatisticsResult GetPipelineStatisticsResult() const;
|
||||
//! Return the latest PipelineStatistic result of this pass
|
||||
PipelineStatisticsResult GetLatestPipelineStatisticsResult() const;
|
||||
|
||||
//! Enables/Disables Timestamp queries for this pass
|
||||
virtual void SetTimestampQueryEnabled(bool enable);
|
||||
|
||||
@@ -45,7 +45,7 @@ namespace AZ
|
||||
AssetBuilderSDK::AssetBuilderDesc builderDescriptor;
|
||||
|
||||
builderDescriptor.m_name = "Atom Resource Pool Asset Builder";
|
||||
builderDescriptor.m_version = 1;
|
||||
builderDescriptor.m_version = 2; //ATOM-15196
|
||||
builderDescriptor.m_patterns.emplace_back(AssetBuilderSDK::AssetBuilderPattern(AZStd::string("*.") + s_sourcePoolAssetExt,
|
||||
AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard));
|
||||
builderDescriptor.m_busId = azrtti_typeid<ResourcePoolBuilder>();
|
||||
|
||||
@@ -100,12 +100,12 @@ namespace AZ
|
||||
bufferPoolDesc.m_hostMemoryAccess = RHI::HostMemoryAccess::Write;
|
||||
break;
|
||||
case CommonBufferPoolType::StaticInputAssembly:
|
||||
bufferPoolDesc.m_bindFlags = RHI::BufferBindFlags::InputAssembly;
|
||||
bufferPoolDesc.m_bindFlags = RHI::BufferBindFlags::InputAssembly | RHI::BufferBindFlags::ShaderRead;
|
||||
bufferPoolDesc.m_heapMemoryLevel = RHI::HeapMemoryLevel::Device;
|
||||
bufferPoolDesc.m_hostMemoryAccess = RHI::HostMemoryAccess::Write;
|
||||
break;
|
||||
case CommonBufferPoolType::DynamicInputAssembly:
|
||||
bufferPoolDesc.m_bindFlags = RHI::BufferBindFlags::DynamicInputAssembly;
|
||||
bufferPoolDesc.m_bindFlags = RHI::BufferBindFlags::DynamicInputAssembly | RHI::BufferBindFlags::ShaderRead;
|
||||
bufferPoolDesc.m_heapMemoryLevel = RHI::HeapMemoryLevel::Host;
|
||||
bufferPoolDesc.m_hostMemoryAccess = RHI::HostMemoryAccess::Write;
|
||||
break;
|
||||
|
||||
@@ -21,41 +21,39 @@ namespace AZ
|
||||
namespace RPI
|
||||
{
|
||||
// --- TimestampResult ---
|
||||
|
||||
TimestampResult::TimestampResult(uint64_t timestampInTicks)
|
||||
TimestampResult::TimestampResult(uint64_t beginTick, uint64_t endTick, RHI::HardwareQueueClass hardwareQueueClass)
|
||||
{
|
||||
m_timestampInTicks = timestampInTicks;
|
||||
AZ_Assert(endTick >= beginTick, "TimestampResult: bad inputs");
|
||||
m_begin = beginTick;
|
||||
m_duration = endTick - beginTick;
|
||||
m_hardwareQueueClass = hardwareQueueClass;
|
||||
}
|
||||
|
||||
TimestampResult::TimestampResult(uint64_t timestampQueryResultLow, uint64_t timestampQueryResultHigh)
|
||||
{
|
||||
const uint64_t low = AZStd::min(timestampQueryResultLow, timestampQueryResultHigh);
|
||||
const uint64_t high = AZStd::max(timestampQueryResultLow, timestampQueryResultHigh);
|
||||
|
||||
m_timestampInTicks = high - low;
|
||||
}
|
||||
|
||||
TimestampResult::TimestampResult(AZStd::array_view<TimestampResult>&& timestampResultArray)
|
||||
{
|
||||
// Loop through all the child passes, and accumulate all the timestampTicks
|
||||
for (const TimestampResult& timestampResult : timestampResultArray)
|
||||
{
|
||||
m_timestampInTicks += timestampResult.m_timestampInTicks;
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t TimestampResult::GetTimestampInNanoseconds() const
|
||||
uint64_t TimestampResult::GetDurationInNanoseconds() const
|
||||
{
|
||||
const RHI::Ptr<RHI::Device> device = RHI::GetRHIDevice();
|
||||
const AZStd::chrono::microseconds timeInMicroseconds = device->GpuTimestampToMicroseconds(m_timestampInTicks, RHI::HardwareQueueClass::Graphics);
|
||||
const AZStd::chrono::microseconds timeInMicroseconds = device->GpuTimestampToMicroseconds(m_duration, m_hardwareQueueClass);
|
||||
const auto timeInNanoseconds = AZStd::chrono::nanoseconds(timeInMicroseconds);
|
||||
|
||||
return static_cast<uint64_t>(timeInNanoseconds.count());
|
||||
}
|
||||
|
||||
uint64_t TimestampResult::GetTimestampInTicks() const
|
||||
uint64_t TimestampResult::GetDurationInTicks() const
|
||||
{
|
||||
return m_timestampInTicks;
|
||||
return m_duration;
|
||||
}
|
||||
|
||||
uint64_t TimestampResult::GetTimestampBeginInTicks() const
|
||||
{
|
||||
return m_begin;
|
||||
}
|
||||
|
||||
void TimestampResult::Add(const TimestampResult& extent)
|
||||
{
|
||||
uint64_t end1 = m_begin + m_duration;
|
||||
uint64_t end2 = extent.m_begin + extent.m_duration;
|
||||
m_begin = m_begin < extent.m_begin ? m_begin : extent.m_begin;
|
||||
m_duration = (end1 > end2 ? end1 : end2) - m_begin;
|
||||
}
|
||||
|
||||
// --- PipelineStatisticsResult ---
|
||||
|
||||
@@ -393,19 +393,6 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
TimestampResult ParentPass::GetTimestampResultInternal() const
|
||||
{
|
||||
AZStd::vector<TimestampResult> timestampResultArray;
|
||||
timestampResultArray.reserve(m_children.size());
|
||||
|
||||
// Calculate the Timestamp result by summing all of its child's TimestampResults
|
||||
for (const Ptr<Pass>& childPass : m_children)
|
||||
{
|
||||
timestampResultArray.emplace_back(childPass->GetTimestampResult());
|
||||
}
|
||||
return TimestampResult(timestampResultArray);
|
||||
}
|
||||
|
||||
PipelineStatisticsResult ParentPass::GetPipelineStatisticsResultInternal() const
|
||||
{
|
||||
AZStd::vector<PipelineStatisticsResult> pipelineStatisticsResultArray;
|
||||
@@ -414,7 +401,7 @@ namespace AZ
|
||||
// Calculate the PipelineStatistics result by summing all of its child's PipelineStatistics
|
||||
for (const Ptr<Pass>& childPass : m_children)
|
||||
{
|
||||
pipelineStatisticsResultArray.emplace_back(childPass->GetPipelineStatisticsResult());
|
||||
pipelineStatisticsResultArray.emplace_back(childPass->GetLatestPipelineStatisticsResult());
|
||||
}
|
||||
return PipelineStatisticsResult(pipelineStatisticsResultArray);
|
||||
}
|
||||
|
||||
@@ -1273,24 +1273,14 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
TimestampResult Pass::GetTimestampResult() const
|
||||
TimestampResult Pass::GetLatestTimestampResult() const
|
||||
{
|
||||
if (IsEnabled() && IsTimestampQueryEnabled())
|
||||
{
|
||||
return GetTimestampResultInternal();
|
||||
}
|
||||
|
||||
return TimestampResult();
|
||||
return GetTimestampResultInternal();
|
||||
}
|
||||
|
||||
PipelineStatisticsResult Pass::GetPipelineStatisticsResult() const
|
||||
PipelineStatisticsResult Pass::GetLatestPipelineStatisticsResult() const
|
||||
{
|
||||
if (IsEnabled() && IsPipelineStatisticsQueryEnabled())
|
||||
{
|
||||
return GetPipelineStatisticsResultInternal();
|
||||
}
|
||||
|
||||
return PipelineStatisticsResult();
|
||||
return GetPipelineStatisticsResultInternal();
|
||||
}
|
||||
|
||||
TimestampResult Pass::GetTimestampResultInternal() const
|
||||
|
||||
@@ -539,7 +539,7 @@ namespace AZ
|
||||
const uint32_t TimestampResultQueryCount = 2u;
|
||||
uint64_t timestampResult[TimestampResultQueryCount] = {0};
|
||||
query->GetLatestResult(×tampResult, sizeof(uint64_t) * TimestampResultQueryCount);
|
||||
m_timestampResult = TimestampResult(timestampResult[0], timestampResult[1]);
|
||||
m_timestampResult = TimestampResult(timestampResult[0], timestampResult[1], RHI::HardwareQueueClass::Graphics);
|
||||
});
|
||||
|
||||
ExecuteOnPipelineStatisticsQuery([this](RHI::Ptr<Query> query)
|
||||
|
||||
@@ -109,8 +109,8 @@ namespace MaterialEditor
|
||||
AZ::RHI::Ptr<AZ::RPI::ParentPass> rootPass = AZ::RPI::PassSystemInterface::Get()->GetRootPass();
|
||||
if (rootPass)
|
||||
{
|
||||
AZ::RPI::TimestampResult timestampResult = rootPass->GetTimestampResult();
|
||||
double gpuFrameTimeMs = aznumeric_cast<double>(timestampResult.GetTimestampInNanoseconds()) / 1000000;
|
||||
AZ::RPI::TimestampResult timestampResult = rootPass->GetLatestTimestampResult();
|
||||
double gpuFrameTimeMs = aznumeric_cast<double>(timestampResult.GetDurationInNanoseconds()) / 1000000;
|
||||
m_gpuFrameTimeMs.PushSample(gpuFrameTimeMs);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,7 +93,9 @@ namespace AZ
|
||||
ImGuiPipelineStatisticsView();
|
||||
|
||||
//! Draw the PipelineStatistics window.
|
||||
void DrawPipelineStatisticsWindow(bool& draw, const PassEntry* rootPassEntry, AZStd::unordered_map<AZ::Name, PassEntry>& m_timestampEntryDatabase);
|
||||
void DrawPipelineStatisticsWindow(bool& draw, const PassEntry* rootPassEntry,
|
||||
AZStd::unordered_map<AZ::Name, PassEntry>& m_timestampEntryDatabase,
|
||||
AZ::RHI::Ptr<AZ::RPI::ParentPass> rootPass);
|
||||
|
||||
//! Total number of columns (Attribute columns + PassName column).
|
||||
static const uint32_t HeaderAttributeCount = PassEntry::PipelineStatisticsAttributeCount + 1u;
|
||||
@@ -139,6 +141,9 @@ namespace AZ
|
||||
|
||||
// ImGui filter used to filter passes by the user's input.
|
||||
ImGuiTextFilter m_passFilter;
|
||||
|
||||
// Pause and showing the pipeline statistics result when it's paused.
|
||||
bool m_paused = false;
|
||||
};
|
||||
|
||||
class ImGuiTimestampView
|
||||
@@ -180,9 +185,19 @@ namespace AZ
|
||||
Count
|
||||
};
|
||||
|
||||
// Timestamp refresh type .
|
||||
enum class RefreshType : int32_t
|
||||
{
|
||||
Realtime = 0,
|
||||
OncePerSecond,
|
||||
Count
|
||||
};
|
||||
|
||||
public:
|
||||
//! Draw the Timestamp window.
|
||||
void DrawTimestampWindow(bool& draw, const PassEntry* rootPassEntry, AZStd::unordered_map<Name, PassEntry>& m_timestampEntryDatabase);
|
||||
void DrawTimestampWindow(bool& draw, const PassEntry* rootPassEntry,
|
||||
AZStd::unordered_map<Name, PassEntry>& m_timestampEntryDatabase,
|
||||
AZ::RHI::Ptr<AZ::RPI::ParentPass> rootPass);
|
||||
|
||||
private:
|
||||
// Draw option for the hierarchical view of the passes.
|
||||
@@ -223,6 +238,20 @@ namespace AZ
|
||||
|
||||
// ImGui filter used to filter passes.
|
||||
ImGuiTextFilter m_passFilter;
|
||||
|
||||
// Pause and showing the timestamp result when it's paused.
|
||||
bool m_paused = false;
|
||||
|
||||
// Hide non-parent passes which has 0 execution time.
|
||||
bool m_hideZeroPasses = false;
|
||||
|
||||
// Show pass execution timeline
|
||||
bool m_showTimeline = false;
|
||||
|
||||
// Controls how often the timestamp data is refreshed
|
||||
RefreshType m_refreshType = RefreshType::OncePerSecond;
|
||||
AZStd::sys_time_t m_lastUpdateTimeMicroSecond;
|
||||
|
||||
};
|
||||
|
||||
class ImGuiGpuProfiler
|
||||
|
||||
@@ -105,9 +105,9 @@ namespace AZ
|
||||
|
||||
// [GFX TODO][ATOM-4001] Cache the timestamp and PipelineStatistics results.
|
||||
// Get the query results from the passes.
|
||||
m_timestampResult = pass->GetTimestampResult();
|
||||
m_timestampResult = pass->GetLatestTimestampResult();
|
||||
|
||||
const RPI::PipelineStatisticsResult rps = pass->GetPipelineStatisticsResult();
|
||||
const RPI::PipelineStatisticsResult rps = pass->GetLatestPipelineStatisticsResult();
|
||||
m_pipelineStatistics = { rps.m_vertexCount, rps.m_primitiveCount, rps.m_vertexShaderInvocationCount,
|
||||
rps.m_rasterizedPrimitiveCount, rps.m_renderedPrimitiveCount, rps.m_pixelShaderInvocationCount, rps.m_computeShaderInvocationCount };
|
||||
|
||||
@@ -153,7 +153,9 @@ namespace AZ
|
||||
|
||||
}
|
||||
|
||||
inline void ImGuiPipelineStatisticsView::DrawPipelineStatisticsWindow(bool& draw, const PassEntry* rootPassEntry, AZStd::unordered_map<Name, PassEntry>& passEntryDatabase)
|
||||
inline void ImGuiPipelineStatisticsView::DrawPipelineStatisticsWindow(bool& draw,
|
||||
const PassEntry* rootPassEntry, AZStd::unordered_map<Name, PassEntry>& passEntryDatabase,
|
||||
AZ::RHI::Ptr<RPI::ParentPass> rootPass)
|
||||
{
|
||||
// Early out if nothing is supposed to be drawn
|
||||
if (!draw)
|
||||
@@ -188,12 +190,6 @@ namespace AZ
|
||||
continue;
|
||||
}
|
||||
|
||||
// Filter out disabled passes for the PipelineStatistics window if necessary.
|
||||
if (!m_showDisabledPasses && !passEntry.IsPipelineStatisticsEnabled())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Filter out parent passes if necessary.
|
||||
if (!m_showParentPasses && passEntry.m_isParent)
|
||||
{
|
||||
@@ -230,6 +226,13 @@ namespace AZ
|
||||
// Start drawing the PipelineStatistics window.
|
||||
if (ImGui::Begin("PipelineStatistics Window", &draw, ImGuiWindowFlags_NoResize))
|
||||
{
|
||||
// Pause/unpause the profiling
|
||||
if (ImGui::Button(m_paused ? "Resume" : "Pause"))
|
||||
{
|
||||
m_paused = !m_paused;
|
||||
rootPass->SetPipelineStatisticsQueryEnabled(!m_paused);
|
||||
}
|
||||
|
||||
ImGui::Columns(2, "HeaderColumns");
|
||||
|
||||
// Draw the statistics of the RootPass.
|
||||
@@ -426,23 +429,16 @@ namespace AZ
|
||||
}
|
||||
|
||||
AZStd::string label;
|
||||
if (passEntry->IsPipelineStatisticsEnabled())
|
||||
if (rootEntry && m_showAttributeContribution)
|
||||
{
|
||||
if (rootEntry && m_showAttributeContribution)
|
||||
{
|
||||
label = AZStd::string::format("%llu (%u%%)",
|
||||
static_cast<AZ::u64>(passEntry->m_pipelineStatistics[attributeIdx]),
|
||||
static_cast<uint32_t>(normalized * 100.0f));
|
||||
}
|
||||
else
|
||||
{
|
||||
label = AZStd::string::format("%llu",
|
||||
static_cast<AZ::u64>(passEntry->m_pipelineStatistics[attributeIdx]));
|
||||
}
|
||||
label = AZStd::string::format("%llu (%u%%)",
|
||||
static_cast<AZ::u64>(passEntry->m_pipelineStatistics[attributeIdx]),
|
||||
static_cast<uint32_t>(normalized * 100.0f));
|
||||
}
|
||||
else
|
||||
{
|
||||
label = "-";
|
||||
label = AZStd::string::format("%llu",
|
||||
static_cast<AZ::u64>(passEntry->m_pipelineStatistics[attributeIdx]));
|
||||
}
|
||||
|
||||
if (rootEntry)
|
||||
@@ -523,7 +519,9 @@ namespace AZ
|
||||
|
||||
// --- ImGuiTimestampView ---
|
||||
|
||||
inline void ImGuiTimestampView::DrawTimestampWindow(bool& draw, const PassEntry* rootPassEntry, AZStd::unordered_map<Name, PassEntry>& timestampEntryDatabase)
|
||||
inline void ImGuiTimestampView::DrawTimestampWindow(
|
||||
bool& draw, const PassEntry* rootPassEntry, AZStd::unordered_map<Name, PassEntry>& timestampEntryDatabase,
|
||||
AZ::RHI::Ptr<RPI::ParentPass> rootPass)
|
||||
{
|
||||
// Early out if nothing is supposed to be drawn
|
||||
if (!draw)
|
||||
@@ -534,10 +532,28 @@ namespace AZ
|
||||
// Clear the references from the previous frame.
|
||||
m_passEntryReferences.clear();
|
||||
|
||||
// pass entry grid based on its timestamp
|
||||
AZStd::vector<PassEntry*> sortedPassEntries;
|
||||
AZStd::vector<AZStd::vector<PassEntry*>> sortedPassGrid;
|
||||
|
||||
// Set the child of the parent, only if it passes the filter.
|
||||
for (auto& passEntryIt : timestampEntryDatabase)
|
||||
{
|
||||
PassEntry* passEntry = &passEntryIt.second;
|
||||
|
||||
// Collect all pass entries with non-zero durations
|
||||
if (passEntry->m_timestampResult.GetDurationInTicks() > 0)
|
||||
{
|
||||
sortedPassEntries.push_back(passEntry);
|
||||
}
|
||||
|
||||
// Skip the pass if the pass' timestamp duration is 0
|
||||
if (m_hideZeroPasses && (!passEntry->m_isParent) && passEntry->m_timestampResult.GetDurationInTicks() == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Only add pass if it pass the filter.
|
||||
if (m_passFilter.PassFilter(passEntry->m_name.GetCStr()))
|
||||
{
|
||||
if (passEntry->m_parent && !passEntry->m_linked)
|
||||
@@ -545,19 +561,94 @@ namespace AZ
|
||||
passEntry->m_parent->LinkChild(passEntry);
|
||||
}
|
||||
|
||||
AZ_Assert(m_passEntryReferences.size() < TimestampEntryCount, "Too many PassEntry references. Increase the size of the array.");
|
||||
AZ_Assert(
|
||||
m_passEntryReferences.size() < TimestampEntryCount,
|
||||
"Too many PassEntry references. Increase the size of the array.");
|
||||
m_passEntryReferences.push_back(passEntry);
|
||||
}
|
||||
}
|
||||
|
||||
// Sort the pass entries based on their starting time and duration
|
||||
AZStd::sort(sortedPassEntries.begin(), sortedPassEntries.end(), [](const PassEntry* passEntry1, const PassEntry* passEntry2) {
|
||||
if (passEntry1->m_timestampResult.GetTimestampBeginInTicks() == passEntry2->m_timestampResult.GetTimestampBeginInTicks())
|
||||
{
|
||||
return passEntry1->m_timestampResult.GetDurationInTicks() < passEntry2->m_timestampResult.GetDurationInTicks();
|
||||
}
|
||||
return passEntry1->m_timestampResult.GetTimestampBeginInTicks() < passEntry2->m_timestampResult.GetTimestampBeginInTicks();
|
||||
});
|
||||
|
||||
// calculate the total GPU duration.
|
||||
RPI::TimestampResult gpuTimestamp;
|
||||
if (sortedPassEntries.size() > 0)
|
||||
{
|
||||
gpuTimestamp = sortedPassEntries.front()->m_timestampResult;
|
||||
gpuTimestamp.Add(sortedPassEntries.back()->m_timestampResult);
|
||||
}
|
||||
|
||||
// Add a pass to the pass grid which none of the pass's timestamp range won't overlap each other.
|
||||
// Search each row until the pass can be added to the end of row without overlap the previous one.
|
||||
for (auto& passEntry : sortedPassEntries)
|
||||
{
|
||||
auto row = sortedPassGrid.begin();
|
||||
for (; row != sortedPassGrid.end(); row++)
|
||||
{
|
||||
if (row->empty())
|
||||
{
|
||||
break;
|
||||
}
|
||||
auto last = (*row).back();
|
||||
if (passEntry->m_timestampResult.GetTimestampBeginInTicks() >=
|
||||
last->m_timestampResult.GetTimestampBeginInTicks() + last->m_timestampResult.GetDurationInTicks())
|
||||
{
|
||||
row->push_back(passEntry);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (row == sortedPassGrid.end())
|
||||
{
|
||||
sortedPassGrid.push_back();
|
||||
sortedPassGrid.back().push_back(passEntry);
|
||||
}
|
||||
}
|
||||
|
||||
// Refresh timestamp query
|
||||
bool needEnable = false;
|
||||
if (!m_paused)
|
||||
{
|
||||
if (m_refreshType == RefreshType::OncePerSecond)
|
||||
{
|
||||
auto now = AZStd::GetTimeNowMicroSecond();
|
||||
if (m_lastUpdateTimeMicroSecond == 0 || now - m_lastUpdateTimeMicroSecond > 1000000)
|
||||
{
|
||||
needEnable = true;
|
||||
m_lastUpdateTimeMicroSecond = now;
|
||||
}
|
||||
}
|
||||
else if (m_refreshType == RefreshType::Realtime)
|
||||
{
|
||||
needEnable = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (rootPass->IsTimestampQueryEnabled() != needEnable)
|
||||
{
|
||||
rootPass->SetTimestampQueryEnabled(needEnable);
|
||||
}
|
||||
|
||||
const ImVec2 windowSize(680.0f, 620.0f);
|
||||
ImGui::SetNextWindowSize(windowSize, ImGuiCond_Always);
|
||||
if (ImGui::Begin("Timestamp View", &draw, ImGuiWindowFlags_NoResize))
|
||||
{
|
||||
// Draw the header.
|
||||
{
|
||||
// Pause/unpause the profiling
|
||||
if (ImGui::Button(m_paused? "Resume":"Pause"))
|
||||
{
|
||||
m_paused = !m_paused;
|
||||
}
|
||||
|
||||
// Draw the frame time (GPU).
|
||||
const AZStd::string formattedTimestamp = FormatTimestampLabel(rootPassEntry->m_interpolatedTimestampInNanoseconds);
|
||||
const AZStd::string formattedTimestamp = FormatTimestampLabel(gpuTimestamp.GetDurationInNanoseconds());
|
||||
const AZStd::string headerFrameTime = AZStd::string::format("Total frame duration (GPU): %s", formattedTimestamp.c_str());
|
||||
ImGui::Text(headerFrameTime.c_str());
|
||||
|
||||
@@ -566,6 +657,17 @@ namespace AZ
|
||||
ImGui::SameLine();
|
||||
ImGui::RadioButton("Flat", reinterpret_cast<int32_t*>(&m_viewType), static_cast<int32_t>(ProfilerViewType::Flat));
|
||||
|
||||
// Draw the refresh option
|
||||
ImGui::RadioButton("Realtime", reinterpret_cast<int32_t*>(&m_refreshType), static_cast<int32_t>(RefreshType::Realtime));
|
||||
ImGui::SameLine();
|
||||
ImGui::RadioButton("Once Per Second", reinterpret_cast<int32_t*>(&m_refreshType), static_cast<int32_t>(RefreshType::OncePerSecond));
|
||||
|
||||
// Show/hide non-parent passes which have zero execution time
|
||||
ImGui::Checkbox("Hide Zero Cost Passes", &m_hideZeroPasses);
|
||||
|
||||
// Show/hide the timeline bar of all the passes which has non-zero execution time
|
||||
ImGui::Checkbox("Show Timeline", &m_showTimeline);
|
||||
|
||||
// Draw advanced options.
|
||||
const ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_None;
|
||||
GpuProfilerImGuiHelper::TreeNode("Advanced options", flags, [this](bool unrolled)
|
||||
@@ -587,6 +689,56 @@ namespace AZ
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
// Draw the pass entry grid
|
||||
if (!sortedPassEntries.empty() && m_showTimeline)
|
||||
{
|
||||
const float passBarHeight = 20.f;
|
||||
const float passBarSpace = 3.f;
|
||||
float areaWidth = ImGui::GetContentRegionAvail().x - 20.f;
|
||||
|
||||
if (ImGui::BeginChild("Timeline", ImVec2(areaWidth, (passBarHeight + passBarSpace) * sortedPassGrid.size()), false))
|
||||
{
|
||||
// start tick and end tick for the area
|
||||
uint64_t areaStartTick = sortedPassEntries.front()->m_timestampResult.GetTimestampBeginInTicks();
|
||||
uint64_t areaEndTick = sortedPassEntries.back()->m_timestampResult.GetTimestampBeginInTicks() +
|
||||
sortedPassEntries.back()->m_timestampResult.GetDurationInTicks();
|
||||
uint64_t areaDurationInTicks = areaEndTick - areaStartTick;
|
||||
|
||||
float rowStartY = 0.f;
|
||||
for (auto& row : sortedPassGrid)
|
||||
{
|
||||
// row start y
|
||||
for (auto passEntry : row)
|
||||
{
|
||||
// button start and end
|
||||
float buttonStartX = (passEntry->m_timestampResult.GetTimestampBeginInTicks() - areaStartTick) * areaWidth /
|
||||
areaDurationInTicks;
|
||||
float buttonWidth = passEntry->m_timestampResult.GetDurationInTicks() * areaWidth / areaDurationInTicks;
|
||||
ImGui::SetCursorPosX(buttonStartX);
|
||||
ImGui::SetCursorPosY(rowStartY);
|
||||
|
||||
// Adds a button and the hover colors.
|
||||
ImGui::Button(passEntry->m_name.GetCStr(), ImVec2(buttonWidth, passBarHeight));
|
||||
|
||||
if (ImGui::IsItemHovered())
|
||||
{
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::Text("Name: %s", passEntry->m_name.GetCStr());
|
||||
ImGui::Text("Path: %s", passEntry->m_path.GetCStr());
|
||||
ImGui::Text("Duration in ticks: %lu", passEntry->m_timestampResult.GetDurationInTicks());
|
||||
ImGui::Text("Duration in microsecond: %.3f us", passEntry->m_timestampResult.GetDurationInNanoseconds()/1000.f);
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
}
|
||||
|
||||
rowStartY += passBarHeight + passBarSpace;
|
||||
}
|
||||
}
|
||||
ImGui::EndChild();
|
||||
|
||||
ImGui::Separator();
|
||||
}
|
||||
|
||||
// Draw the timestamp view.
|
||||
{
|
||||
static const AZStd::array<const char*, static_cast<int32_t>(TimestampMetricUnit::Count)> MetricUnitText =
|
||||
@@ -713,20 +865,18 @@ namespace AZ
|
||||
const auto drawWorkloadBar = [this](const AZStd::string& entryTime, const PassEntry* entry)
|
||||
{
|
||||
ImGui::NextColumn();
|
||||
ImGui::Text(entryTime.c_str());
|
||||
ImGui::NextColumn();
|
||||
|
||||
// Only draw the workload bar when the entry is enabled.
|
||||
if (entry->IsTimestampEnabled())
|
||||
if (entry->m_isParent)
|
||||
{
|
||||
DrawFrameWorkloadBar(NormalizeFrameWorkload(entry->m_interpolatedTimestampInNanoseconds));
|
||||
ImGui::NextColumn();
|
||||
ImGui::NextColumn();
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui::ProgressBar(0.0f, ImVec2(-1.0f, 0.0f), "Disabled");
|
||||
ImGui::Text(entryTime.c_str());
|
||||
ImGui::NextColumn();
|
||||
DrawFrameWorkloadBar(NormalizeFrameWorkload(entry->m_interpolatedTimestampInNanoseconds));
|
||||
ImGui::NextColumn();
|
||||
}
|
||||
|
||||
ImGui::NextColumn();
|
||||
};
|
||||
|
||||
static const auto createHoverMarker = [](const char* text)
|
||||
@@ -800,23 +950,17 @@ namespace AZ
|
||||
// Draw the flat view.
|
||||
for (const PassEntry* entry : m_passEntryReferences)
|
||||
{
|
||||
if (entry->m_isParent)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
const AZStd::string entryTime = FormatTimestampLabel(entry->m_interpolatedTimestampInNanoseconds);
|
||||
|
||||
ImGui::Text(entry->m_name.GetCStr());
|
||||
ImGui::NextColumn();
|
||||
ImGui::Text(entryTime.c_str());
|
||||
ImGui::NextColumn();
|
||||
|
||||
// Only draw the workload bar if the entry is enabled.
|
||||
if (entry->IsTimestampEnabled())
|
||||
{
|
||||
DrawFrameWorkloadBar(NormalizeFrameWorkload(entry->m_interpolatedTimestampInNanoseconds));
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui::ProgressBar(0.0f, ImVec2(-1.0f, 0.0f), "Disabled");
|
||||
}
|
||||
|
||||
DrawFrameWorkloadBar(NormalizeFrameWorkload(entry->m_interpolatedTimestampInNanoseconds));
|
||||
ImGui::NextColumn();
|
||||
}
|
||||
}
|
||||
@@ -890,23 +1034,33 @@ namespace AZ
|
||||
// Update the PassEntry database.
|
||||
const PassEntry* rootPassEntryRef = CreatePassEntries(rootPass);
|
||||
|
||||
bool wasDraw = draw;
|
||||
|
||||
GpuProfilerImGuiHelper::Begin("Gpu Profiler", &draw, ImGuiWindowFlags_NoResize, [this, &rootPass]()
|
||||
{
|
||||
ImGui::Checkbox("Enable TimestampView", &m_drawTimestampView);
|
||||
if (ImGui::Checkbox("Enable TimestampView", &m_drawTimestampView))
|
||||
{
|
||||
rootPass->SetTimestampQueryEnabled(m_drawTimestampView);
|
||||
}
|
||||
ImGui::Spacing();
|
||||
ImGui::Checkbox("Enable PipelineStatisticsView", &m_drawPipelineStatisticsView);
|
||||
if(ImGui::Checkbox("Enable PipelineStatisticsView", &m_drawPipelineStatisticsView))
|
||||
{
|
||||
rootPass->SetPipelineStatisticsQueryEnabled(m_drawPipelineStatisticsView);
|
||||
}
|
||||
});
|
||||
|
||||
// Draw the PipelineStatistics window.
|
||||
m_timestampView.DrawTimestampWindow(m_drawTimestampView, rootPassEntryRef, m_passEntryDatabase);
|
||||
m_timestampView.DrawTimestampWindow(m_drawTimestampView, rootPassEntryRef, m_passEntryDatabase, rootPass);
|
||||
|
||||
// Draw the PipelineStatistics window.
|
||||
m_pipelineStatisticsView.DrawPipelineStatisticsWindow(m_drawPipelineStatisticsView, rootPassEntryRef, m_passEntryDatabase);
|
||||
m_pipelineStatisticsView.DrawPipelineStatisticsWindow(m_drawPipelineStatisticsView, rootPassEntryRef, m_passEntryDatabase, rootPass);
|
||||
|
||||
// [GFX TODO][ATOM-13792] Optimization: ImGui GpuProfiler Pass hierarchy traversal.
|
||||
// Enable/Disable the Timestamp and PipelineStatistics on the RootPass
|
||||
rootPass->SetTimestampQueryEnabled(draw && m_drawTimestampView);
|
||||
rootPass->SetPipelineStatisticsQueryEnabled(draw && m_drawPipelineStatisticsView);
|
||||
//closing window
|
||||
if (wasDraw && !draw)
|
||||
{
|
||||
rootPass->SetTimestampQueryEnabled(false);
|
||||
rootPass->SetPipelineStatisticsQueryEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
inline void ImGuiGpuProfiler::InterpolatePassEntries(AZStd::unordered_map<Name, PassEntry>& passEntryDatabase, float weight) const
|
||||
@@ -918,7 +1072,7 @@ namespace AZ
|
||||
{
|
||||
// Interpolate the timestamps.
|
||||
const double interpolated = Lerp(static_cast<double>(oldEntryIt->second.m_interpolatedTimestampInNanoseconds),
|
||||
static_cast<double>(entry.second.m_timestampResult.GetTimestampInNanoseconds()),
|
||||
static_cast<double>(entry.second.m_timestampResult.GetDurationInNanoseconds()),
|
||||
static_cast<double>(weight));
|
||||
entry.second.m_interpolatedTimestampInNanoseconds = static_cast<uint64_t>(interpolated);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:9d3c18d76f00688d15c54736ef3d8c953df08baf46a796fa71627de18bdb3c0f
|
||||
size 22804332
|
||||
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:6cbfc4d0a6722726070468da4368df7c76be67e8d067a7e3130fd29cdcdd5c6b
|
||||
size 7613840
|
||||
oid sha256:35a880abc018520d4b30d21a64f7a14fca74d936593320d5afd03ddf25771bf3
|
||||
size 9176416
|
||||
|
||||
@@ -4,6 +4,10 @@
|
||||
"parentMaterial": "",
|
||||
"propertyLayoutVersion": 3,
|
||||
"properties": {
|
||||
"ambientOcclusion": {
|
||||
"enable": true,
|
||||
"textureMap": "Textures/arch_1k_ao.png"
|
||||
},
|
||||
"baseColor": {
|
||||
"color": [
|
||||
0.800000011920929,
|
||||
@@ -13,6 +17,17 @@
|
||||
],
|
||||
"textureMap": "Textures/arch_1k_basecolor.png"
|
||||
},
|
||||
"general": {
|
||||
"applySpecularAA": true
|
||||
},
|
||||
"irradiance": {
|
||||
"color": [
|
||||
1.0,
|
||||
0.885053813457489,
|
||||
0.801281750202179,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"metallic": {
|
||||
"textureMap": "Textures/arch_1k_metallic.png"
|
||||
},
|
||||
|
||||
@@ -4,6 +4,10 @@
|
||||
"parentMaterial": "",
|
||||
"propertyLayoutVersion": 3,
|
||||
"properties": {
|
||||
"ambientOcclusion": {
|
||||
"enable": true,
|
||||
"textureMap": "Textures/background_1k_ao.png"
|
||||
},
|
||||
"baseColor": {
|
||||
"color": [
|
||||
0.800000011920929,
|
||||
@@ -13,6 +17,23 @@
|
||||
],
|
||||
"textureMap": "Textures/background_1k_basecolor.png"
|
||||
},
|
||||
"clearCoat": {
|
||||
"enable": true,
|
||||
"factor": 0.5,
|
||||
"normalMap": "Textures/background_1k_normal.jpg",
|
||||
"roughness": 0.4000000059604645
|
||||
},
|
||||
"general": {
|
||||
"applySpecularAA": true
|
||||
},
|
||||
"irradiance": {
|
||||
"color": [
|
||||
1.0,
|
||||
0.8911573886871338,
|
||||
0.7894102334976196,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"metallic": {
|
||||
"textureMap": "Textures/background_1k_metallic.png"
|
||||
},
|
||||
@@ -24,7 +45,6 @@
|
||||
},
|
||||
"parallax": {
|
||||
"algorithm": "POM",
|
||||
"enable": true,
|
||||
"factor": 0.03099999949336052,
|
||||
"pdo": true,
|
||||
"quality": "High",
|
||||
|
||||
@@ -4,6 +4,10 @@
|
||||
"parentMaterial": "",
|
||||
"propertyLayoutVersion": 3,
|
||||
"properties": {
|
||||
"ambientOcclusion": {
|
||||
"enable": true,
|
||||
"textureMap": "Textures/bricks_1k_ao.png"
|
||||
},
|
||||
"baseColor": {
|
||||
"color": [
|
||||
0.800000011920929,
|
||||
@@ -13,6 +17,23 @@
|
||||
],
|
||||
"textureMap": "Textures/bricks_1k_basecolor.png"
|
||||
},
|
||||
"clearCoat": {
|
||||
"enable": true,
|
||||
"factor": 0.5,
|
||||
"normalMap": "Textures/bricks_1k_normal.jpg",
|
||||
"roughness": 0.5
|
||||
},
|
||||
"general": {
|
||||
"applySpecularAA": true
|
||||
},
|
||||
"irradiance": {
|
||||
"color": [
|
||||
1.0,
|
||||
0.9703211784362793,
|
||||
0.9703211784362793,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"metallic": {
|
||||
"textureMap": "Textures/bricks_1k_metallic.png"
|
||||
},
|
||||
@@ -23,11 +44,9 @@
|
||||
"factor": 1.0
|
||||
},
|
||||
"parallax": {
|
||||
"algorithm": "POM",
|
||||
"enable": true,
|
||||
"algorithm": "ContactRefinement",
|
||||
"factor": 0.03500000014901161,
|
||||
"pdo": true,
|
||||
"quality": "High",
|
||||
"quality": "Medium",
|
||||
"textureMap": "Textures/bricks_1k_height.png"
|
||||
},
|
||||
"roughness": {
|
||||
|
||||
@@ -4,17 +4,55 @@
|
||||
"parentMaterial": "",
|
||||
"propertyLayoutVersion": 3,
|
||||
"properties": {
|
||||
"ambientOcclusion": {
|
||||
"enable": true,
|
||||
"textureMap": "Textures/ceiling_1k_ao.png"
|
||||
},
|
||||
"baseColor": {
|
||||
"color": [
|
||||
0.800000011920929,
|
||||
0.800000011920929,
|
||||
0.800000011920929,
|
||||
1.0
|
||||
],
|
||||
"textureBlendMode": "Lerp",
|
||||
"textureMap": "Textures/ceiling_1k_basecolor.png"
|
||||
},
|
||||
"clearCoat": {
|
||||
"enable": true,
|
||||
"factor": 0.5,
|
||||
"influenceMap": "Textures/ceiling_1k_ao.png",
|
||||
"normalMap": "Textures/ceiling_1k_normal.png",
|
||||
"roughness": 0.30000001192092898
|
||||
},
|
||||
"emissive": {
|
||||
"color": [
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"general": {
|
||||
"applySpecularAA": true
|
||||
},
|
||||
"irradiance": {
|
||||
"color": [
|
||||
1.0,
|
||||
0.7591058015823364,
|
||||
0.43776607513427737,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"normal": {
|
||||
"textureMap": "Textures/ceiling_1k_normal.png"
|
||||
},
|
||||
"opacity": {
|
||||
"factor": 1.0
|
||||
},
|
||||
"parallax": {
|
||||
"algorithm": "ContactRefinement",
|
||||
"factor": 0.019999999552965165,
|
||||
"pdo": true,
|
||||
"quality": "Medium",
|
||||
"textureMap": "Textures/ceiling_1k_height.png"
|
||||
},
|
||||
"roughness": {
|
||||
"textureMap": "Textures/ceiling_1k_roughness.png"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,17 @@
|
||||
],
|
||||
"textureMap": "Textures/chain_basecolor.png"
|
||||
},
|
||||
"general": {
|
||||
"applySpecularAA": true
|
||||
},
|
||||
"irradiance": {
|
||||
"color": [
|
||||
0.4891279339790344,
|
||||
0.7931944727897644,
|
||||
1.0,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"metallic": {
|
||||
"textureMap": "Textures/chain_alpha.png"
|
||||
},
|
||||
@@ -21,7 +32,7 @@
|
||||
},
|
||||
"opacity": {
|
||||
"alphaSource": "Split",
|
||||
"factor": 1.0,
|
||||
"factor": 0.30000001192092898,
|
||||
"mode": "Cutout",
|
||||
"textureMap": "Textures/chain_alpha.png"
|
||||
},
|
||||
|
||||
@@ -4,6 +4,10 @@
|
||||
"parentMaterial": "",
|
||||
"propertyLayoutVersion": 3,
|
||||
"properties": {
|
||||
"ambientOcclusion": {
|
||||
"enable": true,
|
||||
"textureMap": "Textures/columnA_1k_ao.png"
|
||||
},
|
||||
"baseColor": {
|
||||
"color": [
|
||||
0.800000011920929,
|
||||
@@ -13,6 +17,23 @@
|
||||
],
|
||||
"textureMap": "Textures/columnA_1k_basecolor.png"
|
||||
},
|
||||
"clearCoat": {
|
||||
"enable": true,
|
||||
"factor": 0.5,
|
||||
"normalMap": "Textures/columnA_1k_normal.jpg",
|
||||
"roughness": 0.30000001192092898
|
||||
},
|
||||
"general": {
|
||||
"applySpecularAA": true
|
||||
},
|
||||
"irradiance": {
|
||||
"color": [
|
||||
1.0,
|
||||
0.8964369893074036,
|
||||
0.8264744281768799,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"metallic": {
|
||||
"textureMap": "Textures/columnA_1k_metallic.png"
|
||||
},
|
||||
@@ -24,7 +45,6 @@
|
||||
},
|
||||
"parallax": {
|
||||
"algorithm": "POM",
|
||||
"enable": true,
|
||||
"factor": 0.017000000923871995,
|
||||
"pdo": true,
|
||||
"quality": "High",
|
||||
|
||||
@@ -4,6 +4,10 @@
|
||||
"parentMaterial": "",
|
||||
"propertyLayoutVersion": 3,
|
||||
"properties": {
|
||||
"ambientOcclusion": {
|
||||
"enable": true,
|
||||
"textureMap": "Textures/columnB_1k_ao.png"
|
||||
},
|
||||
"baseColor": {
|
||||
"color": [
|
||||
0.800000011920929,
|
||||
@@ -13,6 +17,23 @@
|
||||
],
|
||||
"textureMap": "Textures/columnB_1k_basecolor.png"
|
||||
},
|
||||
"clearCoat": {
|
||||
"enable": true,
|
||||
"factor": 0.5,
|
||||
"normalMap": "Textures/columnB_1k_normal.jpg",
|
||||
"roughness": 0.30000001192092898
|
||||
},
|
||||
"general": {
|
||||
"applySpecularAA": true
|
||||
},
|
||||
"irradiance": {
|
||||
"color": [
|
||||
1.0,
|
||||
0.9015335440635681,
|
||||
0.8348516225814819,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"metallic": {
|
||||
"textureMap": "Textures/columnB_1k_metallic.png"
|
||||
},
|
||||
@@ -23,7 +44,6 @@
|
||||
"factor": 1.0
|
||||
},
|
||||
"parallax": {
|
||||
"enable": true,
|
||||
"factor": 0.020999999716877939,
|
||||
"pdo": true,
|
||||
"quality": "High",
|
||||
|
||||
@@ -4,6 +4,10 @@
|
||||
"parentMaterial": "",
|
||||
"propertyLayoutVersion": 3,
|
||||
"properties": {
|
||||
"ambientOcclusion": {
|
||||
"enable": true,
|
||||
"textureMap": "Textures/columnC_1k_ao.png"
|
||||
},
|
||||
"baseColor": {
|
||||
"color": [
|
||||
0.800000011920929,
|
||||
@@ -13,6 +17,23 @@
|
||||
],
|
||||
"textureMap": "Textures/columnC_1k_basecolor.png"
|
||||
},
|
||||
"clearCoat": {
|
||||
"enable": true,
|
||||
"factor": 0.5,
|
||||
"normalMap": "Textures/columnC_1k_normal.jpg",
|
||||
"roughness": 0.30000001192092898
|
||||
},
|
||||
"general": {
|
||||
"applySpecularAA": true
|
||||
},
|
||||
"irradiance": {
|
||||
"color": [
|
||||
0.9050736427307129,
|
||||
0.9050736427307129,
|
||||
1.0,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"metallic": {
|
||||
"textureMap": "Textures/columnC_1k_metallic.png"
|
||||
},
|
||||
@@ -24,7 +45,6 @@
|
||||
},
|
||||
"parallax": {
|
||||
"algorithm": "POM",
|
||||
"enable": true,
|
||||
"factor": 0.014000000432133675,
|
||||
"pdo": true,
|
||||
"quality": "High",
|
||||
|
||||
@@ -4,6 +4,10 @@
|
||||
"parentMaterial": "",
|
||||
"propertyLayoutVersion": 3,
|
||||
"properties": {
|
||||
"ambientOcclusion": {
|
||||
"enable": true,
|
||||
"textureMap": "Textures/curtain_ao.png"
|
||||
},
|
||||
"baseColor": {
|
||||
"color": [
|
||||
0.800000011920929,
|
||||
@@ -13,10 +17,22 @@
|
||||
],
|
||||
"textureMap": "Textures/curtainBlue_1k_basecolor.png"
|
||||
},
|
||||
"general": {
|
||||
"applySpecularAA": true
|
||||
},
|
||||
"irradiance": {
|
||||
"color": [
|
||||
0.06195162981748581,
|
||||
0.2056153267621994,
|
||||
1.0,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"metallic": {
|
||||
"textureMap": "Textures/curtain_metallic.png"
|
||||
},
|
||||
"normal": {
|
||||
"factor": 0.5,
|
||||
"textureMap": "Textures/curtain_normal.jpg"
|
||||
},
|
||||
"opacity": {
|
||||
@@ -24,6 +40,9 @@
|
||||
},
|
||||
"roughness": {
|
||||
"textureMap": "Textures/curtain_roughness.png"
|
||||
},
|
||||
"specularF0": {
|
||||
"enableMultiScatterCompensation": true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,10 @@
|
||||
"parentMaterial": "",
|
||||
"propertyLayoutVersion": 3,
|
||||
"properties": {
|
||||
"ambientOcclusion": {
|
||||
"enable": true,
|
||||
"textureMap": "Textures/curtain_ao.png"
|
||||
},
|
||||
"baseColor": {
|
||||
"color": [
|
||||
0.800000011920929,
|
||||
@@ -13,10 +17,22 @@
|
||||
],
|
||||
"textureMap": "Textures/curtainGreen_1k_basecolor.png"
|
||||
},
|
||||
"general": {
|
||||
"applySpecularAA": true
|
||||
},
|
||||
"irradiance": {
|
||||
"color": [
|
||||
0.0,
|
||||
1.0,
|
||||
0.029526207596063615,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"metallic": {
|
||||
"textureMap": "Textures/curtain_metallic.png"
|
||||
},
|
||||
"normal": {
|
||||
"factor": 0.5,
|
||||
"textureMap": "Textures/curtain_normal.jpg"
|
||||
},
|
||||
"opacity": {
|
||||
|
||||
@@ -4,6 +4,10 @@
|
||||
"parentMaterial": "",
|
||||
"propertyLayoutVersion": 3,
|
||||
"properties": {
|
||||
"ambientOcclusion": {
|
||||
"enable": true,
|
||||
"textureMap": "Textures/curtain_ao.png"
|
||||
},
|
||||
"baseColor": {
|
||||
"color": [
|
||||
0.800000011920929,
|
||||
@@ -13,6 +17,17 @@
|
||||
],
|
||||
"textureMap": "Textures/curtainRed_1k_basecolor.png"
|
||||
},
|
||||
"general": {
|
||||
"applySpecularAA": true
|
||||
},
|
||||
"irradiance": {
|
||||
"color": [
|
||||
1.0,
|
||||
0.023315785452723504,
|
||||
0.048538949340581897,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"metallic": {
|
||||
"textureMap": "Textures/curtain_metallic.png"
|
||||
},
|
||||
@@ -24,6 +39,12 @@
|
||||
},
|
||||
"roughness": {
|
||||
"textureMap": "Textures/curtain_roughness.png"
|
||||
},
|
||||
"uv": {
|
||||
"center": [
|
||||
16.0,
|
||||
0.0
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,10 @@
|
||||
"parentMaterial": "",
|
||||
"propertyLayoutVersion": 3,
|
||||
"properties": {
|
||||
"ambientOcclusion": {
|
||||
"enable": true,
|
||||
"textureMap": "Textures/details_1k_ao.png"
|
||||
},
|
||||
"baseColor": {
|
||||
"color": [
|
||||
0.800000011920929,
|
||||
@@ -13,6 +17,15 @@
|
||||
],
|
||||
"textureMap": "Textures/details_1k_basecolor.png"
|
||||
},
|
||||
"clearCoat": {
|
||||
"enable": true,
|
||||
"factor": 0.5,
|
||||
"normalMap": "Textures/details_1k_normal.png",
|
||||
"roughness": 0.25
|
||||
},
|
||||
"general": {
|
||||
"applySpecularAA": true
|
||||
},
|
||||
"metallic": {
|
||||
"textureMap": "Textures/details_1k_metallic.png"
|
||||
},
|
||||
@@ -24,7 +37,6 @@
|
||||
},
|
||||
"parallax": {
|
||||
"algorithm": "POM",
|
||||
"enable": true,
|
||||
"factor": 0.02500000037252903,
|
||||
"pdo": true,
|
||||
"textureMap": "Textures/details_1k_height.png"
|
||||
|
||||
@@ -4,6 +4,10 @@
|
||||
"parentMaterial": "",
|
||||
"propertyLayoutVersion": 3,
|
||||
"properties": {
|
||||
"ambientOcclusion": {
|
||||
"enable": true,
|
||||
"textureMap": "Textures/fabric_ao.png"
|
||||
},
|
||||
"baseColor": {
|
||||
"color": [
|
||||
0.800000011920929,
|
||||
@@ -13,10 +17,22 @@
|
||||
],
|
||||
"textureMap": "Textures/fabricBlue_1k_basecolor.png"
|
||||
},
|
||||
"general": {
|
||||
"applySpecularAA": true
|
||||
},
|
||||
"irradiance": {
|
||||
"color": [
|
||||
0.0,
|
||||
0.15049973130226136,
|
||||
1.0,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"metallic": {
|
||||
"textureMap": "Textures/fabric_metallic.png"
|
||||
},
|
||||
"normal": {
|
||||
"factor": 0.5,
|
||||
"textureMap": "Textures/fabric_normal.jpg"
|
||||
},
|
||||
"opacity": {
|
||||
|
||||
@@ -4,6 +4,10 @@
|
||||
"parentMaterial": "",
|
||||
"propertyLayoutVersion": 3,
|
||||
"properties": {
|
||||
"ambientOcclusion": {
|
||||
"enable": true,
|
||||
"textureMap": "Textures/fabric_ao.png"
|
||||
},
|
||||
"baseColor": {
|
||||
"color": [
|
||||
0.800000011920929,
|
||||
@@ -13,10 +17,22 @@
|
||||
],
|
||||
"textureMap": "Textures/fabricGreen_1k_basecolor.png"
|
||||
},
|
||||
"general": {
|
||||
"applySpecularAA": true
|
||||
},
|
||||
"irradiance": {
|
||||
"color": [
|
||||
0.0,
|
||||
1.0,
|
||||
0.15378041565418244,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"metallic": {
|
||||
"textureMap": "Textures/fabric_metallic.png"
|
||||
},
|
||||
"normal": {
|
||||
"factor": 0.5,
|
||||
"textureMap": "Textures/fabric_normal.jpg"
|
||||
},
|
||||
"opacity": {
|
||||
|
||||
@@ -4,6 +4,10 @@
|
||||
"parentMaterial": "",
|
||||
"propertyLayoutVersion": 3,
|
||||
"properties": {
|
||||
"ambientOcclusion": {
|
||||
"enable": true,
|
||||
"textureMap": "Textures/fabric_ao.png"
|
||||
},
|
||||
"baseColor": {
|
||||
"color": [
|
||||
0.800000011920929,
|
||||
@@ -13,10 +17,22 @@
|
||||
],
|
||||
"textureMap": "Textures/fabricRed_1k_basecolor.png"
|
||||
},
|
||||
"general": {
|
||||
"applySpecularAA": true
|
||||
},
|
||||
"irradiance": {
|
||||
"color": [
|
||||
1.0,
|
||||
0.08197146654129029,
|
||||
0.10267795622348786,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"metallic": {
|
||||
"textureMap": "Textures/fabric_metallic.png"
|
||||
},
|
||||
"normal": {
|
||||
"factor": 0.5,
|
||||
"textureMap": "Textures/fabric_normal.jpg"
|
||||
},
|
||||
"opacity": {
|
||||
|
||||
@@ -4,6 +4,10 @@
|
||||
"parentMaterial": "",
|
||||
"propertyLayoutVersion": 3,
|
||||
"properties": {
|
||||
"ambientOcclusion": {
|
||||
"enable": true,
|
||||
"textureMap": "Textures/flagpole_1k_ao.png"
|
||||
},
|
||||
"baseColor": {
|
||||
"color": [
|
||||
0.800000011920929,
|
||||
@@ -13,6 +17,17 @@
|
||||
],
|
||||
"textureMap": "Textures/flagpole_1k_basecolor.png"
|
||||
},
|
||||
"general": {
|
||||
"applySpecularAA": true
|
||||
},
|
||||
"irradiance": {
|
||||
"color": [
|
||||
1.0,
|
||||
0.6520485281944275,
|
||||
0.7122911214828491,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"metallic": {
|
||||
"textureMap": "Textures/flagpole_1k_metallic.png"
|
||||
},
|
||||
@@ -24,7 +39,6 @@
|
||||
},
|
||||
"parallax": {
|
||||
"algorithm": "POM",
|
||||
"enable": true,
|
||||
"factor": 0.014000000432133675,
|
||||
"pdo": true,
|
||||
"quality": "High",
|
||||
@@ -32,6 +46,9 @@
|
||||
},
|
||||
"roughness": {
|
||||
"textureMap": "Textures/flagpole_1k_roughness.png"
|
||||
},
|
||||
"specularF0": {
|
||||
"enableMultiScatterCompensation": true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,10 @@
|
||||
"parentMaterial": "",
|
||||
"propertyLayoutVersion": 3,
|
||||
"properties": {
|
||||
"ambientOcclusion": {
|
||||
"enable": true,
|
||||
"textureMap": "Textures/floor_1k_ao.png"
|
||||
},
|
||||
"baseColor": {
|
||||
"color": [
|
||||
0.800000011920929,
|
||||
@@ -13,6 +17,23 @@
|
||||
],
|
||||
"textureMap": "Textures/floor_1k_basecolor.png"
|
||||
},
|
||||
"clearCoat": {
|
||||
"enable": true,
|
||||
"influenceMap": "Textures/floor_1k_ao.png",
|
||||
"normalMap": "Textures/floor_1k_normal.png",
|
||||
"roughness": 0.25
|
||||
},
|
||||
"general": {
|
||||
"applySpecularAA": true
|
||||
},
|
||||
"irradiance": {
|
||||
"color": [
|
||||
1.0,
|
||||
0.9404135346412659,
|
||||
0.8688944578170776,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"normal": {
|
||||
"textureMap": "Textures/floor_1k_normal.png"
|
||||
},
|
||||
@@ -21,7 +42,6 @@
|
||||
},
|
||||
"parallax": {
|
||||
"algorithm": "POM",
|
||||
"enable": true,
|
||||
"factor": 0.012000000104308129,
|
||||
"pdo": true,
|
||||
"textureMap": "Textures/floor_1k_height.png"
|
||||
|
||||
@@ -13,6 +13,23 @@
|
||||
],
|
||||
"textureMap": "Textures/thorn_basecolor.png"
|
||||
},
|
||||
"clearCoat": {
|
||||
"enable": true,
|
||||
"factor": 0.05000000074505806,
|
||||
"normalMap": "Textures/thorn_normal.jpg",
|
||||
"roughness": 0.10000000149011612
|
||||
},
|
||||
"general": {
|
||||
"applySpecularAA": true
|
||||
},
|
||||
"irradiance": {
|
||||
"color": [
|
||||
0.46506446599960329,
|
||||
1.0,
|
||||
0.3944609761238098,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"metallic": {
|
||||
"textureMap": "Textures/thorn_metallic.png"
|
||||
},
|
||||
@@ -20,7 +37,8 @@
|
||||
"textureMap": "Textures/thorn_normal.jpg"
|
||||
},
|
||||
"opacity": {
|
||||
"factor": 0.5699999928474426,
|
||||
"doubleSided": true,
|
||||
"factor": 0.20000000298023225,
|
||||
"mode": "Cutout"
|
||||
},
|
||||
"parallax": {
|
||||
@@ -28,6 +46,25 @@
|
||||
},
|
||||
"roughness": {
|
||||
"textureMap": "Textures/thorn_roughness.png"
|
||||
},
|
||||
"subsurfaceScattering": {
|
||||
"enableSubsurfaceScattering": true,
|
||||
"quality": 1.0,
|
||||
"scatterColor": [
|
||||
0.28143739700317385,
|
||||
1.0,
|
||||
0.13000686466693879,
|
||||
1.0
|
||||
],
|
||||
"scatterDistance": 1.0,
|
||||
"thickness": 0.10000000149011612,
|
||||
"transmissionMode": "ThinObject",
|
||||
"transmissionTint": [
|
||||
0.07225146889686585,
|
||||
0.16981765627861024,
|
||||
0.04444953054189682,
|
||||
1.0
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,10 @@
|
||||
"parentMaterial": "",
|
||||
"propertyLayoutVersion": 3,
|
||||
"properties": {
|
||||
"ambientOcclusion": {
|
||||
"enable": true,
|
||||
"textureMap": "Textures/lion_1k_ao.png"
|
||||
},
|
||||
"baseColor": {
|
||||
"color": [
|
||||
0.800000011920929,
|
||||
@@ -13,6 +17,17 @@
|
||||
],
|
||||
"textureMap": "Textures/lion_1k_basecolor.png"
|
||||
},
|
||||
"general": {
|
||||
"applySpecularAA": true
|
||||
},
|
||||
"irradiance": {
|
||||
"color": [
|
||||
1.0,
|
||||
0.7364919781684876,
|
||||
0.3672388792037964,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"metallic": {
|
||||
"textureMap": "Textures/lion_1k_metallic.png"
|
||||
},
|
||||
@@ -23,14 +38,18 @@
|
||||
"factor": 1.0
|
||||
},
|
||||
"parallax": {
|
||||
"algorithm": "POM",
|
||||
"algorithm": "ContactRefinement",
|
||||
"enable": true,
|
||||
"factor": 0.023000000044703485,
|
||||
"factor": 0.009999999776482582,
|
||||
"pdo": true,
|
||||
"quality": "Ultra",
|
||||
"textureMap": "Textures/lion_1k_height.png"
|
||||
},
|
||||
"roughness": {
|
||||
"textureMap": "Textures/lion_1k_roughness.png"
|
||||
},
|
||||
"specularF0": {
|
||||
"enableMultiScatterCompensation": true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,10 @@
|
||||
"parentMaterial": "",
|
||||
"propertyLayoutVersion": 3,
|
||||
"properties": {
|
||||
"ambientOcclusion": {
|
||||
"enable": true,
|
||||
"textureMap": "Textures/roof_1k_ao.png"
|
||||
},
|
||||
"baseColor": {
|
||||
"color": [
|
||||
0.800000011920929,
|
||||
@@ -11,24 +15,27 @@
|
||||
0.800000011920929,
|
||||
1.0
|
||||
],
|
||||
"textureBlendMode": "Lerp",
|
||||
"textureMap": "Textures/roof_1k_basecolor.png"
|
||||
},
|
||||
"general": {
|
||||
"applySpecularAA": true
|
||||
},
|
||||
"metallic": {
|
||||
"factor": 0.009999999776482582,
|
||||
"useTexture": false
|
||||
},
|
||||
"normal": {
|
||||
"factor": 0.5,
|
||||
"flipY": true,
|
||||
"textureMap": "Textures/roof_1k_normal.jpg"
|
||||
},
|
||||
"opacity": {
|
||||
"factor": 1.0
|
||||
},
|
||||
"parallax": {
|
||||
"algorithm": "POM",
|
||||
"enable": true,
|
||||
"algorithm": "ContactRefinement",
|
||||
"factor": 0.019999999552965165,
|
||||
"pdo": true,
|
||||
"quality": "High",
|
||||
"quality": "Medium",
|
||||
"textureMap": "Textures/roof_1k_height.png"
|
||||
},
|
||||
"roughness": {
|
||||
|
||||
@@ -4,6 +4,10 @@
|
||||
"parentMaterial": "",
|
||||
"propertyLayoutVersion": 3,
|
||||
"properties": {
|
||||
"ambientOcclusion": {
|
||||
"enable": true,
|
||||
"textureMap": "Textures/vase_1k_ao.png"
|
||||
},
|
||||
"baseColor": {
|
||||
"color": [
|
||||
0.800000011920929,
|
||||
@@ -13,6 +17,17 @@
|
||||
],
|
||||
"textureMap": "Textures/vase_1k_basecolor.png"
|
||||
},
|
||||
"general": {
|
||||
"applySpecularAA": true
|
||||
},
|
||||
"irradiance": {
|
||||
"color": [
|
||||
1.0,
|
||||
0.8713664412498474,
|
||||
0.6021667718887329,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"metallic": {
|
||||
"textureMap": "Textures/vase_1k_metallic.png"
|
||||
},
|
||||
@@ -24,7 +39,6 @@
|
||||
},
|
||||
"parallax": {
|
||||
"algorithm": "POM",
|
||||
"enable": true,
|
||||
"factor": 0.027000000700354577,
|
||||
"pdo": true,
|
||||
"quality": "High",
|
||||
@@ -32,6 +46,9 @@
|
||||
},
|
||||
"roughness": {
|
||||
"textureMap": "Textures/vase_1k_roughness.png"
|
||||
},
|
||||
"specularF0": {
|
||||
"enableMultiScatterCompensation": true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,10 @@
|
||||
"parentMaterial": "",
|
||||
"propertyLayoutVersion": 3,
|
||||
"properties": {
|
||||
"ambientOcclusion": {
|
||||
"enable": true,
|
||||
"textureMap": "Textures/vaseHanging_1k_ao.png"
|
||||
},
|
||||
"baseColor": {
|
||||
"color": [
|
||||
0.800000011920929,
|
||||
@@ -13,6 +17,17 @@
|
||||
],
|
||||
"textureMap": "Textures/vaseHanging_1k_basecolor.png"
|
||||
},
|
||||
"general": {
|
||||
"applySpecularAA": true
|
||||
},
|
||||
"irradiance": {
|
||||
"color": [
|
||||
0.765606164932251,
|
||||
1.0,
|
||||
0.7052567601203919,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"metallic": {
|
||||
"textureMap": "Textures/vaseHanging_1k_metallic.png"
|
||||
},
|
||||
@@ -24,7 +39,6 @@
|
||||
},
|
||||
"parallax": {
|
||||
"algorithm": "POM",
|
||||
"enable": true,
|
||||
"factor": 0.04600000008940697,
|
||||
"pdo": true,
|
||||
"quality": "High",
|
||||
|
||||
@@ -13,9 +13,39 @@
|
||||
],
|
||||
"textureMap": "Textures/vasePlant_1k_basecolor.png"
|
||||
},
|
||||
"general": {
|
||||
"applySpecularAA": true
|
||||
},
|
||||
"irradiance": {
|
||||
"color": [
|
||||
0.6788738965988159,
|
||||
1.0,
|
||||
0.026138704270124437,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"opacity": {
|
||||
"factor": 0.8399999737739563,
|
||||
"doubleSided": true,
|
||||
"factor": 0.28999999165534975,
|
||||
"mode": "Cutout"
|
||||
},
|
||||
"subsurfaceScattering": {
|
||||
"enableSubsurfaceScattering": true,
|
||||
"quality": 1.0,
|
||||
"scatterColor": [
|
||||
0.07421988248825073,
|
||||
0.10223544389009476,
|
||||
0.0,
|
||||
1.0
|
||||
],
|
||||
"subsurfaceScatterFactor": 0.0,
|
||||
"transmissionMode": "ThinObject",
|
||||
"transmissionTint": [
|
||||
0.33716335892677309,
|
||||
0.4620737135410309,
|
||||
0.0,
|
||||
1.0
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,10 @@
|
||||
"parentMaterial": "",
|
||||
"propertyLayoutVersion": 3,
|
||||
"properties": {
|
||||
"ambientOcclusion": {
|
||||
"enable": true,
|
||||
"textureMap": "Textures/vaseRound_1k_ao.png"
|
||||
},
|
||||
"baseColor": {
|
||||
"color": [
|
||||
0.800000011920929,
|
||||
@@ -13,6 +17,24 @@
|
||||
],
|
||||
"textureMap": "Textures/vaseRound_1k_basecolor.png"
|
||||
},
|
||||
"clearCoat": {
|
||||
"enable": true,
|
||||
"factor": 0.5,
|
||||
"influenceMap": "Textures/vaseRound_1k_ao.png",
|
||||
"normalMap": "Textures/vaseRound_1k_normal.jpg",
|
||||
"roughness": 0.25
|
||||
},
|
||||
"general": {
|
||||
"applySpecularAA": true
|
||||
},
|
||||
"irradiance": {
|
||||
"color": [
|
||||
1.0,
|
||||
0.5939116477966309,
|
||||
0.29176774621009829,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"normal": {
|
||||
"textureMap": "Textures/vaseRound_1k_normal.jpg"
|
||||
},
|
||||
@@ -21,7 +43,6 @@
|
||||
},
|
||||
"parallax": {
|
||||
"algorithm": "POM",
|
||||
"enable": true,
|
||||
"factor": 0.019999999552965165,
|
||||
"pdo": true,
|
||||
"quality": "High",
|
||||
@@ -29,6 +50,9 @@
|
||||
},
|
||||
"roughness": {
|
||||
"textureMap": "Textures/vaseRound_1k_roughness.png"
|
||||
},
|
||||
"specularF0": {
|
||||
"enableMultiScatterCompensation": true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -44,7 +44,7 @@ CD /d %LY_PROJECT_PATH%\%DEV_REL_PATH%
|
||||
set LY_DEV=%CD%
|
||||
echo LY_DEV = %LY_DEV%
|
||||
|
||||
CALL %LY_DEV%\Gems\AtomLyIntegration\TechnicalArt\DccScriptingInterface\Launchers\Windows\Env.bat
|
||||
CALL %LY_DEV%\Gems\AtomLyIntegration\TechnicalArt\DccScriptingInterface\Launchers\Windows\Env_Maya.bat
|
||||
|
||||
rem :: Constant Vars (Global)
|
||||
rem SET LYPY_GDEBUG=0
|
||||
|
||||
@@ -34,7 +34,6 @@ namespace AZ
|
||||
#if !defined(IMGUI_ENABLED)
|
||||
class DebugConsole {};
|
||||
#else
|
||||
#endif // defined(IMGUI_ENABLED)
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//! A debug console used to enter debug console commands and display debug log messages.
|
||||
//!
|
||||
@@ -132,4 +131,5 @@ namespace AZ
|
||||
bool m_autoScroll = true; //!< Should we auto-scroll as new entries are added?
|
||||
bool m_forceScroll = false; //!< Do we need to force scroll after input entered?
|
||||
};
|
||||
#endif // defined(IMGUI_ENABLED)
|
||||
} // namespace AZ
|
||||
|
||||
@@ -158,10 +158,10 @@ def bootstrap_dccsi_py_libs(dccsi_dirpath=return_stub_dir()):
|
||||
"""Builds and adds local site dir libs based on py version"""
|
||||
|
||||
from azpy.constants import STR_DCCSI_PYTHON_LIB_PATH # a path string constructor
|
||||
_DCCSI_PYTHON_LIB_PATH = "E:\\P4\\jromnoa_spectra_atom_2\\dev\\Tools\\Python\\3.7.5\\windows\\Lib\\site-packages"
|
||||
# _DCCSI_PYTHON_LIB_PATH = STR_DCCSI_PYTHON_LIB_PATH.format(dccsi_dirpath,
|
||||
# sys.version_info[0],
|
||||
# sys.version_info[1])
|
||||
#_DCCSI_PYTHON_LIB_PATH = "E:\\P4\\jromnoa_spectra_atom_2\\dev\\Tools\\Python\\3.7.5\\windows\\Lib\\site-packages"
|
||||
_DCCSI_PYTHON_LIB_PATH = STR_DCCSI_PYTHON_LIB_PATH.format(dccsi_dirpath,
|
||||
sys.version_info[0],
|
||||
sys.version_info[1])
|
||||
|
||||
if os.path.exists(_DCCSI_PYTHON_LIB_PATH):
|
||||
_LOGGER.debug('Performed site.addsitedir({})'.format(_DCCSI_PYTHON_LIB_PATH))
|
||||
|
||||
@@ -222,6 +222,10 @@ void ImGuiManager::Initialize()
|
||||
io.DisplaySize.x = 1920;
|
||||
io.DisplaySize.y = 1080;
|
||||
|
||||
// Create a default font
|
||||
io.Fonts->AddFontDefault();
|
||||
io.Fonts->Build();
|
||||
|
||||
// Broadcast ImGui Ready to Listeners
|
||||
ImGuiUpdateListenerBus::Broadcast(&IImGuiUpdateListener::OnImGuiInitialize);
|
||||
m_currentControllerIndex = -1;
|
||||
|
||||
@@ -95,4 +95,20 @@ namespace Multiplayer
|
||||
private:
|
||||
MultiplayerStats m_stats;
|
||||
};
|
||||
|
||||
inline const char* GetEnumString(MultiplayerAgentType value)
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case MultiplayerAgentType::Uninitialized:
|
||||
return "Uninitialized";
|
||||
case MultiplayerAgentType::Client:
|
||||
return "Client";
|
||||
case MultiplayerAgentType::ClientServer:
|
||||
return "ClientServer";
|
||||
case MultiplayerAgentType::DedicatedServer:
|
||||
return "DedicatedServer";
|
||||
}
|
||||
return "INVALID";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/std/containers/list.h>
|
||||
#include <Source/MultiplayerTypes.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
@@ -17,7 +18,13 @@ namespace {{ Namespace }}
|
||||
{% set ComponentName = Component.attrib['Name'] %}
|
||||
{{ ComponentName }},
|
||||
{% endfor %}
|
||||
Count
|
||||
};
|
||||
static_assert(ComponentTypes::Count < static_cast<ComponentTypes>(Multiplayer::InvalidNetComponentId), "ComponentId overflow");
|
||||
|
||||
//! For reflecting multiplayer components into the serialize, edit, and behaviour contexts.
|
||||
void CreateComponentDescriptors(AZStd::list<AZ::ComponentDescriptor*>& descriptors);
|
||||
|
||||
//! For creating multiplayer component network inputs.
|
||||
void CreateComponentNetworkInput();
|
||||
}
|
||||
|
||||
@@ -33,22 +33,20 @@ const {{ Property.attrib['Type'] }}& Get{{ PropertyName }}() const;
|
||||
#}
|
||||
{% macro DeclareNetworkPropertySetter(Property) %}
|
||||
{% set PropertyName = UpperFirst(Property.attrib['Name']) %}
|
||||
{% if Property.attrib['IsPredictable'] | booleanTrue %}
|
||||
{% if Property.attrib['Container'] == 'Array' %}
|
||||
void Set{{ PropertyName }}(const Multiplayer::NetworkInput&, int32_t index, const {{ Property.attrib['Type'] }}& value);
|
||||
{{ Property.attrib['Type'] }}& Modify{{ PropertyName }}(const Multiplayer::NetworkInput&, int32_t index);
|
||||
{% elif Property.attrib['Container'] == 'Vector' %}
|
||||
void Set{{ PropertyName }}(const Multiplayer::NetworkInput&, int32_t index, const {{ Property.attrib['Type'] }}& value);
|
||||
{{ Property.attrib['Type'] }}& Modify{{ PropertyName }}(const Multiplayer::NetworkInput&, int32_t index);
|
||||
bool {{ PropertyName }}PushBack(const Multiplayer::NetworkInput&, const {{ Property.attrib['Type'] }}& value);
|
||||
bool {{ PropertyName }}PopBack(const Multiplayer::NetworkInput&);
|
||||
void {{ PropertyName }}Clear(const Multiplayer::NetworkInput&);
|
||||
{% elif Property.attrib['Container'] == 'Object' %}
|
||||
void Set{{ PropertyName }}(const Multiplayer::NetworkInput&, const {{ Property.attrib['Type'] }}& value);
|
||||
{{ Property.attrib['Type'] }}& Modify{{ PropertyName }}(const Multiplayer::NetworkInput&);
|
||||
{% else %}
|
||||
void Set{{ PropertyName }}(const Multiplayer::NetworkInput&, const {{ Property.attrib['Type'] }}& value);
|
||||
{% endif %}
|
||||
{% if Property.attrib['Container'] == 'Array' %}
|
||||
void Set{{ PropertyName }}(int32_t index, const {{ Property.attrib['Type'] }}& value);
|
||||
{{ Property.attrib['Type'] }}& Modify{{ PropertyName }}(int32_t index);
|
||||
{% elif Property.attrib['Container'] == 'Vector' %}
|
||||
void Set{{ PropertyName }}(int32_t index, const {{ Property.attrib['Type'] }}& value);
|
||||
{{ Property.attrib['Type'] }}& Modify{{ PropertyName }}(int32_t index);
|
||||
bool {{ PropertyName }}PushBack(const {{ Property.attrib['Type'] }}& value);
|
||||
bool {{ PropertyName }}PopBack();
|
||||
void {{ PropertyName }}Clear();
|
||||
{% elif Property.attrib['Container'] == 'Object' %}
|
||||
void Set{{ PropertyName }}(const {{ Property.attrib['Type'] }}& value);
|
||||
{{ Property.attrib['Type'] }}& Modify{{ PropertyName }}();
|
||||
{% else %}
|
||||
void Set{{ PropertyName }}(const {{ Property.attrib['Type'] }}& value);
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
{#
|
||||
@@ -417,6 +415,7 @@ namespace {{ Component.attrib['Namespace'] }}
|
||||
static const Multiplayer::NetComponentId s_componentId = static_cast<Multiplayer::NetComponentId>({{ Component.attrib['Namespace'] }}::ComponentTypes::{{ Component.attrib['Name'] }});
|
||||
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
static void ReflectToEditContext(AZ::ReflectContext* context);
|
||||
static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided);
|
||||
static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required);
|
||||
static void GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent);
|
||||
|
||||
@@ -73,18 +73,17 @@ void {{ ClassName }}::{{ UpperFirst(Property.attrib['Name']) }}AddEvent(AZ::Even
|
||||
{#
|
||||
|
||||
#}
|
||||
{% macro DefineNetworkPropertyPredictableSet(Component, ReplicateFrom, ReplicateTo, ClassName, Property) %}
|
||||
{% if Property.attrib['IsPredictable'] | booleanTrue %}
|
||||
{% if Property.attrib['Container'] == 'Array' %}
|
||||
void {{ ClassName }}::Set{{ UpperFirst(Property.attrib['Name']) }}(const Multiplayer::NetworkInput& inputCommand, int32_t index, const {{ Property.attrib['Type'] }}& value)
|
||||
{% macro DefineNetworkPropertySet(Component, ReplicateFrom, ReplicateTo, ClassName, Property) %}
|
||||
{% if Property.attrib['Container'] == 'Array' %}
|
||||
void {{ ClassName }}::Set{{ UpperFirst(Property.attrib['Name']) }}(int32_t index, const {{ Property.attrib['Type'] }}& value)
|
||||
{
|
||||
if (GetParent().m_{{ LowerFirst(Property.attrib['Name']) }}[index] != value)
|
||||
{
|
||||
Modify{{ UpperFirst(Property.attrib['Name']) }}(inputCommand, index) = value;
|
||||
Modify{{ UpperFirst(Property.attrib['Name']) }}(index) = value;
|
||||
}
|
||||
}
|
||||
|
||||
{{ Property.attrib['Type'] }}& {{ ClassName }}::Modify{{ UpperFirst(Property.attrib['Name']) }}(const Multiplayer::NetworkInput&, int32_t index)
|
||||
{{ Property.attrib['Type'] }}& {{ ClassName }}::Modify{{ UpperFirst(Property.attrib['Name']) }}(int32_t index)
|
||||
{
|
||||
int32_t bitIndex = index + static_cast<int32_t>({{ AutoComponentMacros.GetNetPropertiesQualifiedPropertyDirtyEnum(Component.attrib['Name'], ReplicateFrom, ReplicateTo, Property, 'Start') }});
|
||||
GetParent().m_currentRecord->m_{{ LowerFirst(AutoComponentMacros.GetNetPropertiesSetName(ReplicateFrom, ReplicateTo)) }}.SetBit(bitIndex, true);
|
||||
@@ -92,16 +91,16 @@ void {{ ClassName }}::Set{{ UpperFirst(Property.attrib['Name']) }}(const Multipl
|
||||
return GetParent().m_{{ LowerFirst(Property.attrib['Name']) }}[index];
|
||||
}
|
||||
|
||||
{% elif Property.attrib['Container'] == 'Vector' %}
|
||||
void {{ ClassName }}::Set{{ UpperFirst(Property.attrib['Name']) }}(const Multiplayer::NetworkInput& inputCommand, int32_t index, const {{ Property.attrib['Type'] }}& value)
|
||||
{% elif Property.attrib['Container'] == 'Vector' %}
|
||||
void {{ ClassName }}::Set{{ UpperFirst(Property.attrib['Name']) }}(int32_t index, const {{ Property.attrib['Type'] }}& value)
|
||||
{
|
||||
if (GetParent().m_{{ LowerFirst(Property.attrib['Name']) }}[index] != value)
|
||||
{
|
||||
Modify{{ UpperFirst(Property.attrib['Name']) }}(inputCommand, index) = value;
|
||||
Modify{{ UpperFirst(Property.attrib['Name']) }}(index) = value;
|
||||
}
|
||||
}
|
||||
|
||||
{{ Property.attrib['Type'] }}& {{ ClassName }}::Modify{{ UpperFirst(Property.attrib['Name']) }}(const Multiplayer::NetworkInput&, int32_t index)
|
||||
{{ Property.attrib['Type'] }}& {{ ClassName }}::Modify{{ UpperFirst(Property.attrib['Name']) }}(int32_t index)
|
||||
{
|
||||
int32_t bitIndex = index + static_cast<int32_t>({{ AutoComponentMacros.GetNetPropertiesQualifiedPropertyDirtyEnum(Component.attrib['Name'], ReplicateFrom, ReplicateTo, Property, 'Start') }});
|
||||
GetParent().m_currentRecord->m_{{ LowerFirst(AutoComponentMacros.GetNetPropertiesSetName(ReplicateFrom, ReplicateTo)) }}.SetBit(bitIndex, true);
|
||||
@@ -109,7 +108,7 @@ void {{ ClassName }}::Set{{ UpperFirst(Property.attrib['Name']) }}(const Multipl
|
||||
return GetParent().m_{{ LowerFirst(Property.attrib['Name']) }}[index];
|
||||
}
|
||||
|
||||
bool {{ ClassName }}::{{ UpperFirst(Property.attrib['Name']) }}PushBack(const Multiplayer::NetworkInput& inputCommand, const {{ Property.attrib['Type'] }} &value)
|
||||
bool {{ ClassName }}::{{ UpperFirst(Property.attrib['Name']) }}PushBack(const {{ Property.attrib['Type'] }} &value)
|
||||
{
|
||||
int32_t indexToSet = GetParent().m_{{ LowerFirst(Property.attrib['Name']) }}.GetSize();
|
||||
GetParent().m_{{ LowerFirst(Property.attrib['Name']) }}.PushBack(value);
|
||||
@@ -134,24 +133,24 @@ void {{ ClassName }}::{{ UpperFirst(Property.attrib['Name']) }}Clear(const Multi
|
||||
GetParent().MarkDirty();
|
||||
}
|
||||
|
||||
{% elif Property.attrib['Container'] == 'Object' %}
|
||||
void {{ ClassName }}::Set{{ UpperFirst(Property.attrib['Name']) }}(const Multiplayer::NetworkInput& inputCommand, const {{ Property.attrib['Type'] }}& value)
|
||||
{% elif Property.attrib['Container'] == 'Object' %}
|
||||
void {{ ClassName }}::Set{{ UpperFirst(Property.attrib['Name']) }}(const {{ Property.attrib['Type'] }}& value)
|
||||
{
|
||||
if (GetParent().m_{{ LowerFirst(Property.attrib['Name']) }} != value)
|
||||
{
|
||||
Modify{{ UpperFirst(Property.attrib['Name']) }}(inputCommand) = value;
|
||||
Modify{{ UpperFirst(Property.attrib['Name']) }}() = value;
|
||||
}
|
||||
}
|
||||
|
||||
{{ Property.attrib['Type'] }}& {{ ClassName }}::Modify{{ UpperFirst(Property.attrib['Name']) }}(const Multiplayer::NetworkInput&)
|
||||
{{ Property.attrib['Type'] }}& {{ ClassName }}::Modify{{ UpperFirst(Property.attrib['Name']) }}()
|
||||
{
|
||||
GetParent().m_currentRecord->m_{{ LowerFirst(AutoComponentMacros.GetNetPropertiesSetName(ReplicateFrom, ReplicateTo)) }}.SetBit(static_cast<int32_t>({{ AutoComponentMacros.GetNetPropertiesQualifiedPropertyDirtyEnum(Component.attrib['Name'], ReplicateFrom, ReplicateTo, Property) }}), true);
|
||||
GetParent().MarkDirty();
|
||||
return GetParent().m_{{ LowerFirst(Property.attrib['Name']) }}{% if Property.attrib['IsRewindable']|booleanTrue %}.Modify(){% endif %};
|
||||
}
|
||||
|
||||
{% else %}
|
||||
void {{ ClassName }}::Set{{ UpperFirst(Property.attrib['Name']) }}(const Multiplayer::NetworkInput&, const {{ Property.attrib['Type'] }}& value)
|
||||
{% else %}
|
||||
void {{ ClassName }}::Set{{ UpperFirst(Property.attrib['Name']) }}(const {{ Property.attrib['Type'] }}& value)
|
||||
{
|
||||
if (GetParent().m_{{ LowerFirst(Property.attrib['Name']) }} != value)
|
||||
{
|
||||
@@ -161,7 +160,6 @@ void {{ ClassName }}::Set{{ UpperFirst(Property.attrib['Name']) }}(const Multipl
|
||||
}
|
||||
}
|
||||
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
{#
|
||||
@@ -273,7 +271,7 @@ void {{ ClassName }}::Set{{ UpperFirst(Property.attrib['Name']) }}(const {{ Prop
|
||||
{% call(Property) AutoComponentMacros.ParseNetworkProperties(Component, ReplicateFrom, ReplicateTo) %}
|
||||
{% if Property.attrib['IsPublic'] | booleanTrue != IsProtected %}
|
||||
{{ DefineNetworkPropertyGet(ClassName, Property, "GetParent().") }}
|
||||
{{ DefineNetworkPropertyPredictableSet(Component, ReplicateFrom, ReplicateTo, ClassName, Property) }}
|
||||
{{ DefineNetworkPropertySet(Component, ReplicateFrom, ReplicateTo, ClassName, Property) }}
|
||||
{% endif %}
|
||||
{% endcall %}
|
||||
{% endmacro %}
|
||||
@@ -478,6 +476,7 @@ bool {{ ClassName }}::Serialize{{ AutoComponentMacros.GetNetPropertiesSetName(Re
|
||||
{%- if networkPropertyCount.update({'value': networkPropertyCount.value + 1}) %}{% endif -%}
|
||||
{% endcall %}
|
||||
{% if networkPropertyCount.value > 0 %}
|
||||
MultiplayerStats& stats = AZ::Interface<IMultiplayer>::Get()->GetStats();
|
||||
// We modify the record if we are writing an update so that we don't notify for a change that really didn't change the value (just a duplicated send from the server)
|
||||
[[maybe_unused]] bool modifyRecord = serializer.GetSerializerMode() == AzNetworking::SerializerMode::WriteToObject;
|
||||
{% call(Property) AutoComponentMacros.ParseNetworkProperties(Component, ReplicateFrom, ReplicateTo) %}
|
||||
@@ -509,7 +508,8 @@ bool {{ ClassName }}::Serialize{{ AutoComponentMacros.GetNetPropertiesSetName(Re
|
||||
static_cast<int32_t>({{ AutoComponentMacros.GetNetPropertiesQualifiedPropertyDirtyEnum(Component.attrib['Name'], ReplicateFrom, ReplicateTo, Property) }}),
|
||||
m_{{ LowerFirst(Property.attrib['Name']) }},
|
||||
"{{ Property.attrib['Name'] }}",
|
||||
GetNetComponentId()
|
||||
GetNetComponentId(),
|
||||
stats
|
||||
);
|
||||
{% endif %}
|
||||
{% endcall %}
|
||||
@@ -1111,23 +1111,29 @@ namespace {{ Component.attrib['Namespace'] }}
|
||||
{{ DefineNetworkPropertyReflection(Component, 'Authority', 'Client', ComponentBaseName)|indent(16) -}}
|
||||
{{ DefineNetworkPropertyReflection(Component, 'Authority', 'Autonomous', ComponentBaseName)|indent(16) -}}
|
||||
{{ DefineNetworkPropertyReflection(Component, 'Autonomous', 'Authority', ComponentBaseName)|indent(16) }}
|
||||
{{ DefineArchetypePropertyReflection(Component, ComponentBaseName)|indent(16) }}
|
||||
;
|
||||
{{ DefineArchetypePropertyReflection(Component, ComponentBaseName)|indent(16) }};
|
||||
}
|
||||
ReflectToEditContext(context);
|
||||
}
|
||||
|
||||
void {{ ComponentBaseName }}::{{ ComponentBaseName }}::ReflectToEditContext(AZ::ReflectContext* context)
|
||||
{
|
||||
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
|
||||
if (serializeContext)
|
||||
{
|
||||
AZ::EditContext* editContext = serializeContext->GetEditContext();
|
||||
if (editContext)
|
||||
{
|
||||
editContext->Class<{{ ComponentBaseName }}>("{{ ComponentName }}", "{{ Component.attrib['Description'] }}")
|
||||
editContext->Class<{{ ComponentName }}>("{{ ComponentName }}", "{{ Component.attrib['Description'] }}")
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::Category, "Multiplayer")
|
||||
->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC_CE("Game"))
|
||||
{{ DefineNetworkPropertyEditReflection(Component, 'Authority', 'Authority', ComponentBaseName)|indent(20) -}}
|
||||
{{ DefineNetworkPropertyEditReflection(Component, 'Authority', 'Server', ComponentBaseName)|indent(20) -}}
|
||||
{{ DefineNetworkPropertyEditReflection(Component, 'Authority', 'Client', ComponentBaseName)|indent(20) -}}
|
||||
{{ DefineNetworkPropertyEditReflection(Component, 'Authority', 'Autonomous', ComponentBaseName)|indent(20) -}}
|
||||
{{ DefineNetworkPropertyEditReflection(Component, 'Autonomous', 'Authority', ComponentBaseName)|indent(20) }}
|
||||
{{ DefineArchetypePropertyEditReflection(Component, ComponentBaseName)|indent(20) }}
|
||||
;
|
||||
{{ DefineNetworkPropertyEditReflection(Component, 'Authority', 'Authority', ComponentName)|indent(20) -}}
|
||||
{{ DefineNetworkPropertyEditReflection(Component, 'Authority', 'Server', ComponentName)|indent(20) -}}
|
||||
{{ DefineNetworkPropertyEditReflection(Component, 'Authority', 'Client', ComponentName)|indent(20) -}}
|
||||
{{ DefineNetworkPropertyEditReflection(Component, 'Authority', 'Autonomous', ComponentName)|indent(20) -}}
|
||||
{{ DefineNetworkPropertyEditReflection(Component, 'Autonomous', 'Authority', ComponentName)|indent(20) }}
|
||||
{{ DefineArchetypePropertyEditReflection(Component, ComponentName)|indent(20) }};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -16,7 +16,7 @@
|
||||
<Include File="Source/NetworkInput/NetworkInputVector.h"/>
|
||||
<Include File="AzNetworking/DataStructures/ByteBuffer.h"/>
|
||||
|
||||
<NetworkProperty Type="Multiplayer::NetworkInputId" Name="LastInputId" Init="Multiplayer::NetworkInputId{0}" ReplicateFrom="Authority" ReplicateTo="Authority" IsRewindable="false" IsPredictable="false" IsPublic="false" Container="Object" ExposeToEditor="false" GenerateEventBindings="false" />
|
||||
<NetworkProperty Type="Multiplayer::ClientInputId" Name="LastInputId" Init="Multiplayer::ClientInputId{0}" ReplicateFrom="Authority" ReplicateTo="Authority" IsRewindable="false" IsPredictable="false" IsPublic="false" Container="Object" ExposeToEditor="false" GenerateEventBindings="false" />
|
||||
|
||||
<RemoteProcedure Name="SendClientInput" InvokeFrom="Autonomous" HandleOn="Authority" IsPublic="true" IsReliable="false" Description="Client to server move / input RPC">
|
||||
<Param Type="Multiplayer::NetworkInputVector" Name="inputArray" />
|
||||
@@ -25,7 +25,7 @@
|
||||
</RemoteProcedure>
|
||||
|
||||
<RemoteProcedure Name="SendClientInputCorrection" InvokeFrom="Authority" HandleOn="Autonomous" IsPublic="true" IsReliable="false" Description="Autonomous proxy correction RPC">
|
||||
<Param Type="Multiplayer::NetworkInputId" Name="inputId" />
|
||||
<Param Type="Multiplayer::ClientInputId" Name="inputId" />
|
||||
<Param Type="AzNetworking::PacketEncodingBuffer" Name="correction" />
|
||||
</RemoteProcedure>
|
||||
|
||||
|
||||
@@ -24,7 +24,6 @@ namespace Multiplayer
|
||||
serializeContext->Class<LocalPredictionPlayerInputComponent, LocalPredictionPlayerInputComponentBase>()
|
||||
->Version(1);
|
||||
}
|
||||
|
||||
LocalPredictionPlayerInputComponentBase::Reflect(context);
|
||||
}
|
||||
|
||||
@@ -48,7 +47,7 @@ namespace Multiplayer
|
||||
|
||||
void LocalPredictionPlayerInputComponentController::HandleSendClientInputCorrection
|
||||
(
|
||||
[[maybe_unused]] const Multiplayer::NetworkInputId& inputId,
|
||||
[[maybe_unused]] const Multiplayer::ClientInputId& inputId,
|
||||
[[maybe_unused]] const AzNetworking::PacketEncodingBuffer& correction
|
||||
)
|
||||
{
|
||||
|
||||
@@ -42,6 +42,6 @@ namespace Multiplayer
|
||||
|
||||
void HandleSendClientInput(const Multiplayer::NetworkInputVector& inputArray, const uint32_t& stateHash, const AzNetworking::PacketEncodingBuffer& clientState) override;
|
||||
void HandleSendMigrateClientInput(const Multiplayer::MigrateNetworkInputVector& inputArray) override;
|
||||
void HandleSendClientInputCorrection(const Multiplayer::NetworkInputId& inputId, const AzNetworking::PacketEncodingBuffer& correction) override;
|
||||
void HandleSendClientInputCorrection(const Multiplayer::ClientInputId& inputId, const AzNetworking::PacketEncodingBuffer& correction) override;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -43,8 +43,12 @@ namespace Multiplayer
|
||||
|
||||
NetEntityId MultiplayerComponent::GetNetEntityId() const
|
||||
{
|
||||
const NetBindComponent* netBindComponent = GetNetBindComponent();
|
||||
return netBindComponent ? netBindComponent->GetNetEntityId() : InvalidNetEntityId;
|
||||
return m_netBindComponent ? m_netBindComponent->GetNetEntityId() : InvalidNetEntityId;
|
||||
}
|
||||
|
||||
NetEntityRole MultiplayerComponent::GetNetEntityRole() const
|
||||
{
|
||||
return m_netBindComponent ? m_netBindComponent->GetNetEntityRole() : NetEntityRole::InvalidRole;
|
||||
}
|
||||
|
||||
ConstNetworkEntityHandle MultiplayerComponent::GetEntityHandle() const
|
||||
|
||||
@@ -62,6 +62,7 @@ namespace Multiplayer
|
||||
//! @}
|
||||
|
||||
NetEntityId GetNetEntityId() const;
|
||||
NetEntityRole GetNetEntityRole() const;
|
||||
ConstNetworkEntityHandle GetEntityHandle() const;
|
||||
NetworkEntityHandle GetEntityHandle();
|
||||
void MarkDirty();
|
||||
@@ -109,7 +110,8 @@ namespace Multiplayer
|
||||
int32_t bitIndex,
|
||||
TYPE& value,
|
||||
const char* name,
|
||||
[[maybe_unused]] NetComponentId componentId
|
||||
[[maybe_unused]] NetComponentId componentId,
|
||||
MultiplayerStats& stats
|
||||
)
|
||||
{
|
||||
if (bitset.GetBit(bitIndex))
|
||||
@@ -119,6 +121,7 @@ namespace Multiplayer
|
||||
serializer.Serialize(value, name);
|
||||
if (modifyRecord && !serializer.GetTrackedChangesFlag())
|
||||
{
|
||||
// If the serializer didn't change any values, then lower the flag so we don't unnecessarily notify
|
||||
bitset.SetBit(bitIndex, false);
|
||||
}
|
||||
const uint32_t postUpdateSize = serializer.GetSize();
|
||||
@@ -126,8 +129,7 @@ namespace Multiplayer
|
||||
const uint32_t updateSize = (postUpdateSize - prevUpdateSize);
|
||||
if (updateSize > 0)
|
||||
{
|
||||
MultiplayerStats& stats = AZ::Interface<IMultiplayer>::Get()->GetStats();
|
||||
if (serializer.GetSerializerMode() == AzNetworking::SerializerMode::WriteToObject)
|
||||
if (modifyRecord)
|
||||
{
|
||||
stats.m_propertyUpdatesRecv++;
|
||||
stats.m_propertyUpdatesRecvBytes += updateSize;
|
||||
|
||||
@@ -27,6 +27,11 @@ namespace Multiplayer
|
||||
return m_owner.GetNetEntityId();
|
||||
}
|
||||
|
||||
NetEntityRole MultiplayerController::GetNetEntityRole() const
|
||||
{
|
||||
return GetNetBindComponent()->GetNetEntityRole();
|
||||
}
|
||||
|
||||
AZ::Entity* MultiplayerController::GetEntity() const
|
||||
{
|
||||
return m_owner.GetEntity();
|
||||
|
||||
@@ -47,6 +47,10 @@ namespace Multiplayer
|
||||
//! @return the networkId for the entity that owns this controller
|
||||
NetEntityId GetNetEntityId() const;
|
||||
|
||||
//! Returns the networkRole for the entity that owns this controller.
|
||||
//! @return the networkRole for the entity that owns this controller
|
||||
NetEntityRole GetNetEntityRole() const;
|
||||
|
||||
//! Returns the raw AZ::Entity pointer for the entity that owns this controller.
|
||||
//! @return the raw AZ::Entity pointer for the entity that owns this controller
|
||||
AZ::Entity* GetEntity() const;
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
#include <Source/Components/NetworkTransformComponent.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
#include <AzCore/EBus/IEventScheduler.h>
|
||||
#include <AzFramework/Components/TransformComponent.h>
|
||||
|
||||
namespace Multiplayer
|
||||
{
|
||||
@@ -24,7 +26,81 @@ namespace Multiplayer
|
||||
serializeContext->Class<NetworkTransformComponent, NetworkTransformComponentBase>()
|
||||
->Version(1);
|
||||
}
|
||||
|
||||
NetworkTransformComponentBase::Reflect(context);
|
||||
}
|
||||
|
||||
NetworkTransformComponent::NetworkTransformComponent()
|
||||
: m_rotationEventHandler([this](const AZ::Quaternion& rotation) { OnRotationChangedEvent(rotation); })
|
||||
, m_translationEventHandler([this](const AZ::Vector3& translation) { OnTranslationChangedEvent(translation); })
|
||||
, m_scaleEventHandler([this](const AZ::Vector3& scale) { OnScaleChangedEvent(scale); })
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
void NetworkTransformComponent::OnInit()
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
void NetworkTransformComponent::OnActivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating)
|
||||
{
|
||||
RotationAddEvent(m_rotationEventHandler);
|
||||
TranslationAddEvent(m_translationEventHandler);
|
||||
ScaleAddEvent(m_scaleEventHandler);
|
||||
}
|
||||
|
||||
void NetworkTransformComponent::OnDeactivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
void NetworkTransformComponent::OnRotationChangedEvent(const AZ::Quaternion& rotation)
|
||||
{
|
||||
AZ::Transform worldTm = GetTransformComponent()->GetWorldTM();
|
||||
worldTm.SetRotation(rotation);
|
||||
GetTransformComponent()->SetWorldTM(worldTm);
|
||||
}
|
||||
|
||||
void NetworkTransformComponent::OnTranslationChangedEvent(const AZ::Vector3& translation)
|
||||
{
|
||||
AZ::Transform worldTm = GetTransformComponent()->GetWorldTM();
|
||||
worldTm.SetTranslation(translation);
|
||||
GetTransformComponent()->SetWorldTM(worldTm);
|
||||
}
|
||||
|
||||
void NetworkTransformComponent::OnScaleChangedEvent(const AZ::Vector3& scale)
|
||||
{
|
||||
AZ::Transform worldTm = GetTransformComponent()->GetWorldTM();
|
||||
worldTm.SetScale(scale);
|
||||
GetTransformComponent()->SetWorldTM(worldTm);
|
||||
}
|
||||
|
||||
|
||||
NetworkTransformComponentController::NetworkTransformComponentController(NetworkTransformComponent& parent)
|
||||
: NetworkTransformComponentControllerBase(parent)
|
||||
, m_transformChangedHandler([this](const AZ::Transform&, const AZ::Transform& worldTm) { OnTransformChangedEvent(worldTm); })
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
void NetworkTransformComponentController::OnActivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating)
|
||||
{
|
||||
GetParent().GetTransformComponent()->BindTransformChangedEventHandler(m_transformChangedHandler);
|
||||
OnTransformChangedEvent(GetParent().GetTransformComponent()->GetWorldTM());
|
||||
}
|
||||
|
||||
void NetworkTransformComponentController::OnDeactivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
void NetworkTransformComponentController::OnTransformChangedEvent(const AZ::Transform& worldTm)
|
||||
{
|
||||
if (GetNetEntityRole() == NetEntityRole::Authority)
|
||||
{
|
||||
SetRotation(worldTm.GetRotation());
|
||||
SetTranslation(worldTm.GetTranslation());
|
||||
SetScale(worldTm.GetScale());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <Source/AutoGen/NetworkTransformComponent.AutoComponent.h>
|
||||
#include <AzCore/Component/TransformBus.h>
|
||||
|
||||
namespace Multiplayer
|
||||
{
|
||||
@@ -22,20 +23,36 @@ namespace Multiplayer
|
||||
public:
|
||||
AZ_MULTIPLAYER_COMPONENT(Multiplayer::NetworkTransformComponent, s_networkTransformComponentConcreteUuid, Multiplayer::NetworkTransformComponentBase);
|
||||
|
||||
static void Reflect([[maybe_unused]] AZ::ReflectContext* context);
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
void OnInit() override {}
|
||||
void OnActivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) override {}
|
||||
void OnDeactivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) override {}
|
||||
NetworkTransformComponent();
|
||||
|
||||
void OnInit() override;
|
||||
void OnActivate(Multiplayer::EntityIsMigrating entityIsMigrating) override;
|
||||
void OnDeactivate(Multiplayer::EntityIsMigrating entityIsMigrating) override;
|
||||
|
||||
private:
|
||||
void OnRotationChangedEvent(const AZ::Quaternion& rotation);
|
||||
void OnTranslationChangedEvent(const AZ::Vector3& translation);
|
||||
void OnScaleChangedEvent(const AZ::Vector3& scale);
|
||||
|
||||
AZ::Event<AZ::Quaternion>::Handler m_rotationEventHandler;
|
||||
AZ::Event<AZ::Vector3>::Handler m_translationEventHandler;
|
||||
AZ::Event<AZ::Vector3>::Handler m_scaleEventHandler;
|
||||
};
|
||||
|
||||
class NetworkTransformComponentController
|
||||
: public NetworkTransformComponentControllerBase
|
||||
{
|
||||
public:
|
||||
NetworkTransformComponentController(NetworkTransformComponent& parent) : NetworkTransformComponentControllerBase(parent) {}
|
||||
NetworkTransformComponentController(NetworkTransformComponent& parent);
|
||||
|
||||
void OnActivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) override {}
|
||||
void OnDeactivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) override {}
|
||||
void OnActivate(Multiplayer::EntityIsMigrating entityIsMigrating) override;
|
||||
void OnDeactivate(Multiplayer::EntityIsMigrating entityIsMigrating) override;
|
||||
|
||||
private:
|
||||
void OnTransformChangedEvent(const AZ::Transform& worldTm);
|
||||
|
||||
AZ::TransformChangedEvent::Handler m_transformChangedHandler;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 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 <Source/ConnectionData/ClientToServerConnectionData.h>
|
||||
|
||||
namespace Multiplayer
|
||||
{
|
||||
static constexpr uint32_t Uint32Max = AZStd::numeric_limits<uint32_t>::max();
|
||||
|
||||
// This can be used to help mitigate client side performance when large numbers of entities are created off the network
|
||||
AZ_CVAR(uint32_t, cl_ClientMaxRemoteEntitiesPendingCreationCount, Uint32Max, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "Maximum number of entities that we have sent to the client, but have not had a confirmation back from the client");
|
||||
AZ_CVAR(AZ::TimeMs, cl_ClientEntityReplicatorPendingRemovalTimeMs, AZ::TimeMs{ 10000 }, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "How long should wait prior to removing an entity for the client through a change in the replication window, entity deletes are still immediate");
|
||||
|
||||
ClientToServerConnectionData::ClientToServerConnectionData
|
||||
(
|
||||
AzNetworking::IConnection* connection,
|
||||
AzNetworking::IConnectionListener& connectionListener
|
||||
)
|
||||
: m_connection(connection)
|
||||
, m_entityReplicationManager(*connection, connectionListener, EntityReplicationManager::Mode::LocalClientToRemoteServer)
|
||||
{
|
||||
m_entityReplicationManager.SetMaxRemoteEntitiesPendingCreationCount(cl_ClientMaxRemoteEntitiesPendingCreationCount);
|
||||
m_entityReplicationManager.SetEntityPendingRemovalMs(cl_ClientEntityReplicatorPendingRemovalTimeMs);
|
||||
}
|
||||
|
||||
ClientToServerConnectionData::~ClientToServerConnectionData()
|
||||
{
|
||||
m_entityReplicationManager.Clear(false);
|
||||
}
|
||||
|
||||
ConnectionDataType ClientToServerConnectionData::GetConnectionDataType() const
|
||||
{
|
||||
return ConnectionDataType::ClientToServer;
|
||||
}
|
||||
|
||||
AzNetworking::IConnection* ClientToServerConnectionData::GetConnection() const
|
||||
{
|
||||
return m_connection;
|
||||
}
|
||||
|
||||
EntityReplicationManager& ClientToServerConnectionData::GetReplicationManager()
|
||||
{
|
||||
return m_entityReplicationManager;
|
||||
}
|
||||
|
||||
void ClientToServerConnectionData::Update([[maybe_unused]] AZ::TimeMs serverGameTimeMs)
|
||||
{
|
||||
m_entityReplicationManager.ActivatePendingEntities();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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 <Source/ConnectionData/IConnectionData.h>
|
||||
|
||||
namespace Multiplayer
|
||||
{
|
||||
class ClientToServerConnectionData final
|
||||
: public IConnectionData
|
||||
{
|
||||
public:
|
||||
ClientToServerConnectionData
|
||||
(
|
||||
AzNetworking::IConnection* connection,
|
||||
AzNetworking::IConnectionListener& connectionListener
|
||||
);
|
||||
~ClientToServerConnectionData() override;
|
||||
|
||||
//! IConnectionData interface
|
||||
//! @{
|
||||
ConnectionDataType GetConnectionDataType() const override;
|
||||
AzNetworking::IConnection* GetConnection() const override;
|
||||
EntityReplicationManager& GetReplicationManager() override;
|
||||
void Update(AZ::TimeMs serverGameTimeMs) override;
|
||||
//! @}
|
||||
|
||||
bool CanSendUpdates();
|
||||
|
||||
private:
|
||||
EntityReplicationManager m_entityReplicationManager;
|
||||
AzNetworking::IConnection* m_connection = nullptr;
|
||||
bool m_canSendUpdates = true;
|
||||
};
|
||||
}
|
||||
|
||||
#include <Source/ConnectionData/ClientToServerConnectionData.inl>
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Multiplayer
|
||||
{
|
||||
inline bool ClientToServerConnectionData::CanSendUpdates()
|
||||
{
|
||||
return m_canSendUpdates;
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,7 @@ namespace Multiplayer
|
||||
{
|
||||
enum class ConnectionDataType
|
||||
{
|
||||
ClientToServer,
|
||||
ServerToClient,
|
||||
ServerToServer
|
||||
};
|
||||
|
||||
@@ -13,7 +13,9 @@
|
||||
#include <Source/MultiplayerSystemComponent.h>
|
||||
#include <Source/Components/MultiplayerComponent.h>
|
||||
#include <Source/AutoGen/AutoComponentTypes.h>
|
||||
#include <Source/ConnectionData/ClientToServerConnectionData.h>
|
||||
#include <Source/ConnectionData/ServerToClientConnectionData.h>
|
||||
#include <Source/ReplicationWindows/NullReplicationWindow.h>
|
||||
#include <Source/ReplicationWindows/ServerToClientReplicationWindow.h>
|
||||
#include <Source/EntityDomains/FullOwnershipEntityDomain.h>
|
||||
#include <AzNetworking/Framework/INetworking.h>
|
||||
@@ -66,6 +68,7 @@ namespace Multiplayer
|
||||
AZ_CVAR(AZ::CVarFixedString, sv_gamerules, "norules", nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "GameRules server works with");
|
||||
AZ_CVAR(ProtocolType, sv_protocol, ProtocolType::Udp, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "This flag controls whether we use TCP or UDP for game networking");
|
||||
AZ_CVAR(bool, sv_isDedicated, true, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "Whether the host command creates an independent or client hosted server");
|
||||
AZ_CVAR(AZ::TimeMs, cl_defaultNetworkEntityActivationTimeSliceMs, AZ::TimeMs{ 0 }, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "Max Ms to use to activate entities coming from the network, 0 means instantiate everything");
|
||||
|
||||
void MultiplayerSystemComponent::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
@@ -126,24 +129,27 @@ namespace Multiplayer
|
||||
// Handle deferred local rpc messages that were generated during the updates
|
||||
m_networkEntityManager.DispatchLocalDeferredRpcMessages();
|
||||
m_networkEntityManager.NotifyEntitiesChanged();
|
||||
|
||||
// Let the network system know the frame is done and we can collect dirty bits
|
||||
m_networkEntityManager.NotifyEntitiesDirtied();
|
||||
|
||||
// Send out the game state update to all connections
|
||||
{
|
||||
auto sendNetworkUpdates = [serverGameTimeMs](IConnection& connection)
|
||||
{
|
||||
if (connection.GetUserData() != nullptr)
|
||||
{
|
||||
IConnectionData* connectionData = reinterpret_cast<IConnectionData*>(connection.GetUserData());
|
||||
connectionData->Update(serverGameTimeMs);
|
||||
}
|
||||
};
|
||||
|
||||
m_networkInterface->GetConnectionSet().VisitConnections(sendNetworkUpdates);
|
||||
}
|
||||
|
||||
MultiplayerStats& stats = GetStats();
|
||||
stats.m_entityCount = GetNetworkEntityManager()->GetEntityCount();
|
||||
|
||||
auto sendNetworkUpdates = [serverGameTimeMs](IConnection& connection)
|
||||
{
|
||||
if (connection.GetUserData() != nullptr)
|
||||
{
|
||||
IConnectionData* connectionData = reinterpret_cast<IConnectionData*>(connection.GetUserData());
|
||||
connectionData->Update(serverGameTimeMs);
|
||||
}
|
||||
};
|
||||
|
||||
// Send out the game state update to all connections
|
||||
m_networkInterface->GetConnectionSet().VisitConnections(sendNetworkUpdates);
|
||||
|
||||
MultiplayerPackets::SyncConsole packet;
|
||||
AZ::ThreadSafeDeque<AZStd::string>::DequeType cvarUpdates;
|
||||
m_cvarCommands.Swap(cvarUpdates);
|
||||
@@ -245,12 +251,8 @@ namespace Multiplayer
|
||||
AZ::CVarFixedString commandString = "sv_map " + packet.GetMap();
|
||||
AZ::Interface<AZ::IConsole>::Get()->PerformCommand(commandString.c_str());
|
||||
|
||||
// This is a bit tricky, so it warrants extra commenting
|
||||
// The cry level loader has a 'map' command used to invoke the level load system
|
||||
// We don't want any explicit cry dependencies, so instead we rely on the
|
||||
// az console binding inside SystemInit to echo any unhandled commands to
|
||||
// the cry console by stripping off the prefix 'sv_'
|
||||
AZ::Interface<AZ::IConsole>::Get()->PerformCommand(commandString.c_str() + 3);
|
||||
AZ::CVarFixedString loadLevelString = "LoadLevel " + packet.GetMap();
|
||||
AZ::Interface<AZ::IConsole>::Get()->PerformCommand(loadLevelString.c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -410,6 +412,16 @@ namespace Multiplayer
|
||||
AZStd::unique_ptr<IReplicationWindow> window = AZStd::make_unique<ServerToClientReplicationWindow>(controlledEntity, connection);
|
||||
reinterpret_cast<ServerToClientConnectionData*>(connection->GetUserData())->GetReplicationManager().SetReplicationWindow(AZStd::move(window));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (connection->GetUserData() == nullptr) // Only add user data if the connect event handler has not already done so
|
||||
{
|
||||
connection->SetUserData(new ClientToServerConnectionData(connection, *this));
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<IReplicationWindow> window = AZStd::make_unique<NullReplicationWindow>();
|
||||
reinterpret_cast<ServerToClientConnectionData*>(connection->GetUserData())->GetReplicationManager().SetEntityActivationTimeSliceMs(cl_defaultNetworkEntityActivationTimeSliceMs);
|
||||
}
|
||||
}
|
||||
|
||||
bool MultiplayerSystemComponent::OnPacketReceived(AzNetworking::IConnection* connection, const IPacketHeader& packetHeader, ISerializer& serializer)
|
||||
@@ -463,6 +475,7 @@ namespace Multiplayer
|
||||
}
|
||||
}
|
||||
m_agentType = multiplayerType;
|
||||
AZLOG_INFO("Multiplayer operating in %s mode", GetEnumString(m_agentType));
|
||||
}
|
||||
|
||||
void MultiplayerSystemComponent::AddConnectionAcquiredHandler(ConnectionAcquiredEvent::Handler& handler)
|
||||
@@ -535,14 +548,15 @@ namespace Multiplayer
|
||||
void host([[maybe_unused]] const AZ::ConsoleCommandContainer& arguments)
|
||||
{
|
||||
Multiplayer::MultiplayerAgentType serverType = sv_isDedicated ? MultiplayerAgentType::DedicatedServer : MultiplayerAgentType::ClientServer;
|
||||
AZ::Interface<IMultiplayer>::Get()->InitializeMultiplayer(serverType);
|
||||
INetworkInterface* networkInterface = AZ::Interface<INetworking>::Get()->RetrieveNetworkInterface(AZ::Name(s_networkInterfaceName));
|
||||
networkInterface->Listen(sv_port);
|
||||
AZ::Interface<IMultiplayer>::Get()->InitializeMultiplayer(serverType);
|
||||
}
|
||||
AZ_CONSOLEFREEFUNC(host, AZ::ConsoleFunctorFlags::DontReplicate, "Opens a multiplayer connection as a host for other clients to connect to");
|
||||
|
||||
void connect([[maybe_unused]] const AZ::ConsoleCommandContainer& arguments)
|
||||
{
|
||||
AZ::Interface<IMultiplayer>::Get()->InitializeMultiplayer(MultiplayerAgentType::Client);
|
||||
INetworkInterface* networkInterface = AZ::Interface<INetworking>::Get()->RetrieveNetworkInterface(AZ::Name(s_networkInterfaceName));
|
||||
|
||||
if (arguments.size() < 1)
|
||||
@@ -567,12 +581,12 @@ namespace Multiplayer
|
||||
int32_t portNumber = atol(portStr);
|
||||
const IpAddress ipAddress(addressStr, aznumeric_cast<uint16_t>(portNumber), networkInterface->GetType());
|
||||
networkInterface->Connect(ipAddress);
|
||||
AZ::Interface<IMultiplayer>::Get()->InitializeMultiplayer(MultiplayerAgentType::Client);
|
||||
}
|
||||
AZ_CONSOLEFREEFUNC(connect, AZ::ConsoleFunctorFlags::DontReplicate, "Opens a multiplayer connection to a remote host");
|
||||
|
||||
void disconnect([[maybe_unused]] const AZ::ConsoleCommandContainer& arguments)
|
||||
{
|
||||
AZ::Interface<IMultiplayer>::Get()->InitializeMultiplayer(MultiplayerAgentType::Uninitialized);
|
||||
INetworkInterface* networkInterface = AZ::Interface<INetworking>::Get()->RetrieveNetworkInterface(AZ::Name(s_networkInterfaceName));
|
||||
auto visitor = [](IConnection& connection) { connection.Disconnect(DisconnectReason::TerminatedByUser, TerminationEndpoint::Local); };
|
||||
networkInterface->GetConnectionSet().VisitConnections(visitor);
|
||||
|
||||
@@ -21,8 +21,8 @@
|
||||
#include <AzNetworking/ConnectionLayer/IConnectionListener.h>
|
||||
#include <Include/IMultiplayer.h>
|
||||
#include <Source/NetworkTime/NetworkTime.h>
|
||||
#include <Source/AutoGen/Multiplayer.AutoPacketDispatcher.h>
|
||||
#include <Source/NetworkEntity/NetworkEntityManager.h>
|
||||
#include <Source/AutoGen/Multiplayer.AutoPacketDispatcher.h>
|
||||
|
||||
namespace AzNetworking
|
||||
{
|
||||
|
||||
+18
-19
@@ -25,6 +25,7 @@
|
||||
#include <AzNetworking/PacketLayer/IPacketHeader.h>
|
||||
#include <AzNetworking/Serialization/NetworkInputSerializer.h>
|
||||
#include <AzNetworking/Serialization/NetworkOutputSerializer.h>
|
||||
#include <AzNetworking/Serialization/TrackChangedSerializer.h>
|
||||
#include <AzCore/Component/ComponentApplicationBus.h>
|
||||
#include <AzCore/Console/IConsole.h>
|
||||
#include <AzCore/Console/ILogger.h>
|
||||
@@ -126,9 +127,9 @@ namespace Multiplayer
|
||||
MultiplayerPackets::EntityUpdates entityUpdatePacket;
|
||||
entityUpdatePacket.SetHostTimeMs(serverGameTimeMs);
|
||||
// Serialize everything
|
||||
for (auto it = toSendList.begin(); it != toSendList.end();)
|
||||
while (!toSendList.empty())
|
||||
{
|
||||
EntityReplicator* replicator = *it;
|
||||
EntityReplicator* replicator = toSendList.front();
|
||||
NetworkEntityUpdateMessage updateMessage(replicator->GenerateUpdatePacket());
|
||||
|
||||
const uint32_t nextMessageSize = updateMessage.GetEstimatedSerializeSize();
|
||||
@@ -144,15 +145,15 @@ namespace Multiplayer
|
||||
|
||||
pendingPacketSize += nextMessageSize;
|
||||
entityUpdatePacket.ModifyEntityMessages().push_back(updateMessage);
|
||||
replicatorUpdatedList.push_back(*it);
|
||||
it = toSendList.erase(it);
|
||||
replicatorUpdatedList.push_back(replicator);
|
||||
toSendList.pop_front();
|
||||
|
||||
if (largeEntityDetected)
|
||||
{
|
||||
AZLOG_WARN("\n\n*******************************");
|
||||
AZLOG_WARN
|
||||
(
|
||||
"Serializing Extremely Large Entity (%u) - MaxPayload: %d NeededSize %d",
|
||||
"Serializing extremely large entity (%u) - MaxPayload: %d NeededSize %d",
|
||||
aznumeric_cast<uint32_t>(replicator->GetEntityHandle().GetNetEntityId()),
|
||||
maxPayloadSize,
|
||||
nextMessageSize
|
||||
@@ -173,16 +174,16 @@ namespace Multiplayer
|
||||
|
||||
EntityReplicationManager::EntityReplicatorList EntityReplicationManager::GenerateEntityUpdateList()
|
||||
{
|
||||
if (m_replicationWindow == nullptr)
|
||||
{
|
||||
return EntityReplicatorList();
|
||||
}
|
||||
|
||||
// Generate a list of all our entities that need updates
|
||||
EntityReplicatorList autonomousReplicators;
|
||||
autonomousReplicators.reserve(m_replicatorsPendingSend.size());
|
||||
EntityReplicatorList proxyReplicators;
|
||||
proxyReplicators.reserve(m_replicatorsPendingSend.size());
|
||||
EntityReplicatorList toSendList;
|
||||
|
||||
uint32_t elementsAdded = 0;
|
||||
for (auto iter = m_replicatorsPendingSend.begin();
|
||||
iter != m_replicatorsPendingSend.end()
|
||||
&& elementsAdded < m_replicationWindow->GetMaxEntityReplicatorSendCount();)
|
||||
for (auto iter = m_replicatorsPendingSend.begin(); iter != m_replicatorsPendingSend.end() && elementsAdded < m_replicationWindow->GetMaxEntityReplicatorSendCount(); )
|
||||
{
|
||||
EntityReplicator* replicator = GetEntityReplicator(*iter);
|
||||
bool clearPendingSend = true;
|
||||
@@ -218,13 +219,13 @@ namespace Multiplayer
|
||||
|
||||
if (replicator->GetRemoteNetworkRole() == NetEntityRole::Autonomous)
|
||||
{
|
||||
autonomousReplicators.push_back(replicator);
|
||||
toSendList.push_back(replicator);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (elementsAdded < m_replicationWindow->GetMaxEntityReplicatorSendCount())
|
||||
{
|
||||
proxyReplicators.push_back(replicator);
|
||||
toSendList.push_back(replicator);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -243,9 +244,6 @@ namespace Multiplayer
|
||||
}
|
||||
}
|
||||
|
||||
EntityReplicatorList toSendList;
|
||||
toSendList.swap(autonomousReplicators);
|
||||
toSendList.insert(toSendList.end(), proxyReplicators.begin(), proxyReplicators.end());
|
||||
return toSendList;
|
||||
}
|
||||
|
||||
@@ -543,6 +541,7 @@ namespace Multiplayer
|
||||
// Create an entity if we don't have one
|
||||
if (createEntity)
|
||||
{
|
||||
// @pereslav
|
||||
//replicatorEntity = GetNetworkEntityManager()->CreateSingleEntityImmediateInternal(prefabEntityId, EntitySpawnType::Replicate, AutoActivate::DoNotActivate, netEntityId, localNetworkRole, AZ::Transform::Identity());
|
||||
AZ_Assert(replicatorEntity != nullptr, "Failed to create entity from prefab");// %s", prefabEntityId.GetString());
|
||||
if (replicatorEntity == nullptr)
|
||||
@@ -765,7 +764,7 @@ namespace Multiplayer
|
||||
return HandleEntityDeleteMessage(entityReplicator, packetHeader, updateMessage);
|
||||
}
|
||||
|
||||
AzNetworking::NetworkOutputSerializer outputSerializer(updateMessage.GetData()->GetBuffer(), updateMessage.GetData()->GetSize());
|
||||
AzNetworking::TrackChangedSerializer<AzNetworking::NetworkOutputSerializer> outputSerializer(updateMessage.GetData()->GetBuffer(), updateMessage.GetData()->GetSize());
|
||||
|
||||
PrefabEntityId prefabEntityId;
|
||||
if (updateMessage.GetHasValidPrefabId())
|
||||
@@ -1125,7 +1124,7 @@ namespace Multiplayer
|
||||
{
|
||||
if (message.GetPropertyUpdateData().GetSize() > 0)
|
||||
{
|
||||
AzNetworking::NetworkOutputSerializer outputSerializer(message.ModifyPropertyUpdateData().GetBuffer(), message.ModifyPropertyUpdateData().GetSize());
|
||||
AzNetworking::TrackChangedSerializer<AzNetworking::NetworkOutputSerializer> outputSerializer(message.ModifyPropertyUpdateData().GetBuffer(), message.ModifyPropertyUpdateData().GetSize());
|
||||
if (!HandlePropertyChangeMessage
|
||||
(
|
||||
replicator,
|
||||
|
||||
+2
-1
@@ -22,6 +22,7 @@
|
||||
#include <AzNetworking/PacketLayer/IPacketHeader.h>
|
||||
#include <AzCore/std/containers/map.h>
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
#include <AzCore/std/containers/deque.h>
|
||||
#include <AzCore/std/limits.h>
|
||||
#include <AzCore/EBus/Event.h>
|
||||
#include <AzCore/EBus/ScheduledEvent.h>
|
||||
@@ -114,7 +115,7 @@ namespace Multiplayer
|
||||
using RpcMessages = AZStd::list<NetworkEntityRpcMessage>;
|
||||
bool DispatchOrphanedRpc(NetworkEntityRpcMessage& message, EntityReplicator* entityReplicator);
|
||||
|
||||
using EntityReplicatorList = AZStd::vector<EntityReplicator*>;
|
||||
using EntityReplicatorList = AZStd::deque<EntityReplicator*>;
|
||||
EntityReplicatorList GenerateEntityUpdateList();
|
||||
|
||||
void SendEntityUpdatesPacketHelper(AZ::TimeMs serverGameTimeMs, EntityReplicatorList& toSendList, uint32_t maxPayloadSize, AzNetworking::IConnection& connection);
|
||||
|
||||
@@ -283,7 +283,7 @@ namespace Multiplayer
|
||||
AZ_Assert(netBindComponent, "No Multiplayer::NetBindComponent");
|
||||
|
||||
bool isAuthority = (GetBoundLocalNetworkRole() == NetEntityRole::Authority)
|
||||
&& (GetBoundLocalNetworkRole() == netBindComponent->GetNetEntityRole());
|
||||
&& (GetBoundLocalNetworkRole() == netBindComponent->GetNetEntityRole());
|
||||
bool isClient = GetRemoteNetworkRole() == NetEntityRole::Client;
|
||||
bool isAutonomous = GetBoundLocalNetworkRole() == NetEntityRole::Autonomous;
|
||||
if (isAuthority || isClient || isAutonomous)
|
||||
@@ -311,9 +311,9 @@ namespace Multiplayer
|
||||
{
|
||||
bool ret(false);
|
||||
bool isServer = (GetBoundLocalNetworkRole() == NetEntityRole::Server)
|
||||
&& (GetRemoteNetworkRole() == NetEntityRole::Authority);
|
||||
&& (GetRemoteNetworkRole() == NetEntityRole::Authority);
|
||||
bool isClient = (GetBoundLocalNetworkRole() == NetEntityRole::Client)
|
||||
|| (GetBoundLocalNetworkRole() == NetEntityRole::Autonomous);
|
||||
|| (GetBoundLocalNetworkRole() == NetEntityRole::Autonomous);
|
||||
if (isServer || isClient)
|
||||
{
|
||||
ret = true;
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
#include <Source/NetworkEntity/NetworkEntityManager.h>
|
||||
#include <Source/Components/NetBindComponent.h>
|
||||
#include <Include/IMultiplayer.h>
|
||||
#include <AzCore/Interface/Interface.h>
|
||||
#include <AzCore/Console/IConsole.h>
|
||||
#include <AzCore/Console/ILogger.h>
|
||||
@@ -34,6 +35,12 @@ namespace Multiplayer
|
||||
, m_entityRemovedEventHandler([this](AZ::Entity* entity) { OnEntityRemoved(entity); })
|
||||
{
|
||||
AZ::Interface<INetworkEntityManager>::Register(this);
|
||||
if (AZ::Interface<AZ::ComponentApplicationRequests>::Get() != nullptr)
|
||||
{
|
||||
// Null guard needed for unit tests
|
||||
AZ::Interface<AZ::ComponentApplicationRequests>::Get()->RegisterEntityAddedEventHandler(m_entityAddedEventHandler);
|
||||
AZ::Interface<AZ::ComponentApplicationRequests>::Get()->RegisterEntityRemovedEventHandler(m_entityRemovedEventHandler);
|
||||
}
|
||||
}
|
||||
|
||||
NetworkEntityManager::~NetworkEntityManager()
|
||||
@@ -43,13 +50,6 @@ namespace Multiplayer
|
||||
|
||||
void NetworkEntityManager::Initialize(HostId hostId, AZStd::unique_ptr<IEntityDomain> entityDomain)
|
||||
{
|
||||
if (AZ::Interface<AZ::ComponentApplicationRequests>::Get() != nullptr)
|
||||
{
|
||||
// Null guard needed for unit tests
|
||||
AZ::Interface<AZ::ComponentApplicationRequests>::Get()->RegisterEntityAddedEventHandler(m_entityAddedEventHandler);
|
||||
AZ::Interface<AZ::ComponentApplicationRequests>::Get()->RegisterEntityRemovedEventHandler(m_entityRemovedEventHandler);
|
||||
}
|
||||
|
||||
m_hostId = hostId;
|
||||
m_entityDomain = AZStd::move(entityDomain);
|
||||
m_updateEntityDomainEvent.Enqueue(net_EntityDomainUpdateMs, true);
|
||||
@@ -282,8 +282,13 @@ namespace Multiplayer
|
||||
NetBindComponent* netBindComponent = entity->FindComponent<NetBindComponent>();
|
||||
if (netBindComponent != nullptr)
|
||||
{
|
||||
// @pereslav
|
||||
// Note that this is a total hack.. we should not be listening to this event on a client
|
||||
// Entities should instead be spawned by the prefabEntityId inside EntityReplicationManager::HandlePropertyChangeMessage()
|
||||
const bool isClient = AZ::Interface<IMultiplayer>::Get()->GetAgentType() == MultiplayerAgentType::Client;
|
||||
const NetEntityRole netEntityRole = isClient ? NetEntityRole::Client: NetEntityRole::Authority;
|
||||
const NetEntityId netEntityId = m_nextEntityId++;
|
||||
netBindComponent->PreInit(entity, PrefabEntityId(), netEntityId, NetEntityRole::Authority);
|
||||
netBindComponent->PreInit(entity, PrefabEntityId(), netEntityId, netEntityRole);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -33,22 +33,36 @@ namespace Multiplayer
|
||||
return *this;
|
||||
}
|
||||
|
||||
void NetworkInput::SetNetworkInputId(NetworkInputId inputId)
|
||||
void NetworkInput::SetClientInputId(ClientInputId inputId)
|
||||
{
|
||||
m_inputId = inputId;
|
||||
}
|
||||
|
||||
NetworkInputId NetworkInput::GetNetworkInputId() const
|
||||
ClientInputId NetworkInput::GetClientInputId() const
|
||||
{
|
||||
return m_inputId;
|
||||
}
|
||||
|
||||
|
||||
NetworkInputId& NetworkInput::ModifyNetworkInputId()
|
||||
ClientInputId& NetworkInput::ModifyClientInputId()
|
||||
{
|
||||
return m_inputId;
|
||||
}
|
||||
|
||||
void NetworkInput::SetServerTimeMs(AZ::TimeMs serverTimeMs)
|
||||
{
|
||||
m_serverTimeMs = serverTimeMs;
|
||||
}
|
||||
|
||||
AZ::TimeMs NetworkInput::GetServerTimeMs() const
|
||||
{
|
||||
return m_serverTimeMs;
|
||||
}
|
||||
|
||||
AZ::TimeMs& NetworkInput::ModifyServerTimeMs()
|
||||
{
|
||||
return m_serverTimeMs;
|
||||
}
|
||||
|
||||
void NetworkInput::AttachNetBindComponent(NetBindComponent* netBindComponent)
|
||||
{
|
||||
m_wasAttached = true;
|
||||
@@ -62,7 +76,6 @@ namespace Multiplayer
|
||||
|
||||
bool NetworkInput::Serialize(AzNetworking::ISerializer& serializer)
|
||||
{
|
||||
//static_assert(UINT8_MAX >= Multiplayer::ComponentTypes::c_Count, "Expected fewer than 255 components, this code needs to be updated");
|
||||
if (!serializer.Serialize(m_inputId, "InputId"))
|
||||
{
|
||||
return false;
|
||||
@@ -135,8 +148,9 @@ namespace Multiplayer
|
||||
void NetworkInput::CopyInternal(const NetworkInput& rhs)
|
||||
{
|
||||
m_inputId = rhs.m_inputId;
|
||||
m_serverTimeMs = rhs.m_serverTimeMs;
|
||||
m_componentInputs.resize(rhs.m_componentInputs.size());
|
||||
for (int i = 0; i < rhs.m_componentInputs.size(); ++i)
|
||||
for (int32_t i = 0; i < rhs.m_componentInputs.size(); ++i)
|
||||
{
|
||||
if (m_componentInputs[i] == nullptr || m_componentInputs[i]->GetComponentId() != rhs.m_componentInputs[i]->GetComponentId())
|
||||
{
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace Multiplayer
|
||||
// Forwards
|
||||
class NetBindComponent;
|
||||
|
||||
AZ_TYPE_SAFE_INTEGRAL(NetworkInputId, uint16_t);
|
||||
AZ_TYPE_SAFE_INTEGRAL(ClientInputId, uint16_t);
|
||||
|
||||
//! @class NetworkInput
|
||||
//! @brief A single networked client input command.
|
||||
@@ -38,9 +38,13 @@ namespace Multiplayer
|
||||
NetworkInput(const NetworkInput&);
|
||||
NetworkInput& operator= (const NetworkInput&);
|
||||
|
||||
void SetNetworkInputId(NetworkInputId inputId);
|
||||
NetworkInputId GetNetworkInputId() const;
|
||||
NetworkInputId& ModifyNetworkInputId();
|
||||
void SetClientInputId(ClientInputId inputId);
|
||||
ClientInputId GetClientInputId() const;
|
||||
ClientInputId& ModifyClientInputId();
|
||||
|
||||
void SetServerTimeMs(AZ::TimeMs serverTimeMs);
|
||||
AZ::TimeMs GetServerTimeMs() const;
|
||||
AZ::TimeMs& ModifyServerTimeMs();
|
||||
|
||||
void AttachNetBindComponent(NetBindComponent* netBindComponent);
|
||||
|
||||
@@ -67,10 +71,11 @@ namespace Multiplayer
|
||||
void CopyInternal(const NetworkInput& rhs);
|
||||
|
||||
MultiplayerComponentInputVector m_componentInputs;
|
||||
NetworkInputId m_inputId = NetworkInputId{ 0 };
|
||||
ClientInputId m_inputId = ClientInputId{ 0 };
|
||||
AZ::TimeMs m_serverTimeMs = AZ::TimeMs{ 0 };
|
||||
ConstNetworkEntityHandle m_owner;
|
||||
bool m_wasAttached = false;
|
||||
};
|
||||
}
|
||||
|
||||
AZ_TYPE_SAFE_INTEGRAL_SERIALIZEBINDING(Multiplayer::NetworkInputId);
|
||||
AZ_TYPE_SAFE_INTEGRAL_SERIALIZEBINDING(Multiplayer::ClientInputId);
|
||||
|
||||
@@ -48,12 +48,12 @@ namespace Multiplayer
|
||||
return m_inputs[index].m_networkInput;
|
||||
}
|
||||
|
||||
void NetworkInputVector::SetPreviousInputId(NetworkInputId previousInputId)
|
||||
void NetworkInputVector::SetPreviousInputId(ClientInputId previousInputId)
|
||||
{
|
||||
m_previousInputId = previousInputId;
|
||||
}
|
||||
|
||||
NetworkInputId NetworkInputVector::GetPreviousInputId() const
|
||||
ClientInputId NetworkInputVector::GetPreviousInputId() const
|
||||
{
|
||||
return m_previousInputId;
|
||||
}
|
||||
|
||||
@@ -32,8 +32,8 @@ namespace Multiplayer
|
||||
NetworkInput& operator[](uint32_t index);
|
||||
const NetworkInput& operator[](uint32_t index) const;
|
||||
|
||||
void SetPreviousInputId(NetworkInputId previousInputId);
|
||||
NetworkInputId GetPreviousInputId() const;
|
||||
void SetPreviousInputId(ClientInputId previousInputId);
|
||||
ClientInputId GetPreviousInputId() const;
|
||||
|
||||
bool Serialize(AzNetworking::ISerializer& serializer);
|
||||
|
||||
@@ -48,7 +48,7 @@ namespace Multiplayer
|
||||
|
||||
ConstNetworkEntityHandle m_owner;
|
||||
AZStd::fixed_vector<Wrapper, MaxElements> m_inputs;
|
||||
NetworkInputId m_previousInputId;
|
||||
ClientInputId m_previousInputId;
|
||||
};
|
||||
|
||||
//! @class MigrateNetworkInputVector
|
||||
|
||||
@@ -73,7 +73,7 @@ namespace Multiplayer
|
||||
template <typename BASE_TYPE, AZStd::size_t REWIND_SIZE>
|
||||
inline BASE_TYPE& RewindableObject<BASE_TYPE, REWIND_SIZE>::Modify()
|
||||
{
|
||||
ApplicationFrameId frameTime = GetCurrentTimeForProperty();
|
||||
const ApplicationFrameId frameTime = GetCurrentTimeForProperty();
|
||||
if (frameTime < m_headTime)
|
||||
{
|
||||
AZ_Assert(false, "Trying to mutate a rewindable in the past");
|
||||
@@ -82,7 +82,7 @@ namespace Multiplayer
|
||||
{
|
||||
SetValueForTime(GetValueForTime(frameTime), frameTime);
|
||||
}
|
||||
const BASE_TYPE& returnValue = GetValueForTime(GetCurrentTimeForProperty());
|
||||
const BASE_TYPE& returnValue = GetValueForTime(frameTime);
|
||||
return const_cast<BASE_TYPE&>(returnValue);
|
||||
}
|
||||
|
||||
@@ -103,10 +103,11 @@ namespace Multiplayer
|
||||
template <typename BASE_TYPE, AZStd::size_t REWIND_SIZE>
|
||||
inline bool RewindableObject<BASE_TYPE, REWIND_SIZE>::Serialize(AzNetworking::ISerializer& serializer)
|
||||
{
|
||||
BASE_TYPE current = GetValueForTime(GetCurrentTimeForProperty());
|
||||
if (serializer.Serialize(current, "Element") && (serializer.GetSerializerMode() == AzNetworking::SerializerMode::WriteToObject))
|
||||
const ApplicationFrameId frameTime = GetCurrentTimeForProperty();
|
||||
BASE_TYPE value = GetValueForTime(frameTime);
|
||||
if (serializer.Serialize(value, "Element") && (serializer.GetSerializerMode() == AzNetworking::SerializerMode::WriteToObject))
|
||||
{
|
||||
SetValueForTime(current, GetCurrentTimeForProperty());
|
||||
SetValueForTime(value, frameTime);
|
||||
}
|
||||
return serializer.IsValid();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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 "NullReplicationWindow.h"
|
||||
|
||||
namespace Multiplayer
|
||||
{
|
||||
bool NullReplicationWindow::ReplicationSetUpdateReady()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
const ReplicationSet& NullReplicationWindow::GetReplicationSet() const
|
||||
{
|
||||
return m_emptySet;
|
||||
}
|
||||
|
||||
uint32_t NullReplicationWindow::GetMaxEntityReplicatorSendCount() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool NullReplicationWindow::IsInWindow([[maybe_unused]] const ConstNetworkEntityHandle& entityHandle, NetEntityRole& outNetworkRole) const
|
||||
{
|
||||
outNetworkRole = NetEntityRole::InvalidRole;
|
||||
return false;
|
||||
}
|
||||
|
||||
void NullReplicationWindow::UpdateWindow()
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
void NullReplicationWindow::DebugDraw() const
|
||||
{
|
||||
// Nothing to draw
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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 <Source/ReplicationWindows/IReplicationWindow.h>
|
||||
|
||||
namespace Multiplayer
|
||||
{
|
||||
class NullReplicationWindow
|
||||
: public IReplicationWindow
|
||||
{
|
||||
public:
|
||||
NullReplicationWindow() = default;
|
||||
|
||||
//! IReplicationWindow interface
|
||||
//! @{
|
||||
bool ReplicationSetUpdateReady() override;
|
||||
const ReplicationSet& GetReplicationSet() const override;
|
||||
uint32_t GetMaxEntityReplicatorSendCount() const override;
|
||||
bool IsInWindow(const ConstNetworkEntityHandle& entityPtr, NetEntityRole& outNetworkRole) const override;
|
||||
void UpdateWindow() override;
|
||||
void DebugDraw() const override;
|
||||
//! @}
|
||||
|
||||
private:
|
||||
ReplicationSet m_emptySet;
|
||||
};
|
||||
}
|
||||
@@ -202,8 +202,7 @@ namespace Multiplayer
|
||||
|
||||
void ServerToClientReplicationWindow::OnEntityActivated(const AZ::EntityId& entityId)
|
||||
{
|
||||
AZ::Entity* entity = nullptr;
|
||||
EBUS_EVENT_RESULT(entity, AZ::ComponentApplicationBus, FindEntity, entityId);
|
||||
AZ::Entity* entity = AZ::Interface<AZ::ComponentApplicationRequests>::Get()->FindEntity(entityId);
|
||||
|
||||
ConstNetworkEntityHandle entityHandle(entity, GetNetworkEntityTracker());
|
||||
NetBindComponent* netBindComponent = entityHandle.GetNetBindComponent();
|
||||
@@ -234,8 +233,7 @@ namespace Multiplayer
|
||||
|
||||
void ServerToClientReplicationWindow::OnEntityDeactivated(const AZ::EntityId& entityId)
|
||||
{
|
||||
AZ::Entity* entity = nullptr;
|
||||
EBUS_EVENT_RESULT(entity, AZ::ComponentApplicationBus, FindEntity, entityId);
|
||||
AZ::Entity* entity = AZ::Interface<AZ::ComponentApplicationRequests>::Get()->FindEntity(entityId);
|
||||
|
||||
ConstNetworkEntityHandle entityHandle(entity, GetNetworkEntityTracker());
|
||||
NetBindComponent* netBindComponent = entityHandle.GetNetBindComponent();
|
||||
|
||||
@@ -97,6 +97,10 @@ namespace UnitTest
|
||||
m_mpComponent->OnConnect(&connMock2);
|
||||
|
||||
EXPECT_EQ(m_connectionAcquiredCount, 25);
|
||||
|
||||
// Clean up connection data
|
||||
m_mpComponent->OnDisconnect(&connMock1, AzNetworking::DisconnectReason::None, AzNetworking::TerminationEndpoint::Local);
|
||||
m_mpComponent->OnDisconnect(&connMock2, AzNetworking::DisconnectReason::None, AzNetworking::TerminationEndpoint::Local);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -34,6 +34,9 @@ set(FILES
|
||||
Source/Components/NetBindComponent.h
|
||||
Source/Components/NetworkTransformComponent.cpp
|
||||
Source/Components/NetworkTransformComponent.h
|
||||
Source/ConnectionData/ClientToServerConnectionData.cpp
|
||||
Source/ConnectionData/ClientToServerConnectionData.h
|
||||
Source/ConnectionData/ClientToServerConnectionData.inl
|
||||
Source/ConnectionData/IConnectionData.h
|
||||
Source/ConnectionData/ServerToClientConnectionData.cpp
|
||||
Source/ConnectionData/ServerToClientConnectionData.h
|
||||
@@ -81,6 +84,8 @@ set(FILES
|
||||
Source/NetworkTime/NetworkTime.h
|
||||
Source/NetworkTime/RewindableObject.h
|
||||
Source/NetworkTime/RewindableObject.inl
|
||||
Source/ReplicationWindows/NullReplicationWindow.cpp
|
||||
Source/ReplicationWindows/NullReplicationWindow.h
|
||||
Source/ReplicationWindows/IReplicationWindow.h
|
||||
Source/ReplicationWindows/ServerToClientReplicationWindow.cpp
|
||||
Source/ReplicationWindows/ServerToClientReplicationWindow.h
|
||||
|
||||
@@ -98,7 +98,7 @@ namespace WhiteBox
|
||||
|
||||
// specify the data format for vertex stream data
|
||||
AZ::RHI::BufferDescriptor bufferDescriptor;
|
||||
bufferDescriptor.m_bindFlags = AZ::RHI::BufferBindFlags::InputAssembly;
|
||||
bufferDescriptor.m_bindFlags = AZ::RHI::BufferBindFlags::InputAssembly | AZ::RHI::BufferBindFlags::ShaderRead;
|
||||
bufferDescriptor.m_byteCount = bufferSize;
|
||||
bufferDescriptor.m_alignment = elementSize;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user