Merge branch 'main' into sceneapi_script_regression

main
jackalbe 5 years ago
commit 085aa78ec9

1
.gitignore vendored

@ -18,3 +18,4 @@ _savebackup/
#Output folder for test results when running Automated Tests
TestResults/**
*.swatches
/imgui.ini

@ -12,4 +12,5 @@
set(GEM_DEPENDENCIES
Gem::Atom_RHI_Vulkan.Private
Gem::Atom_RHI_DX12.Private
Gem::Atom_RHI_Null.Private
)

@ -15,5 +15,7 @@ set(GEM_DEPENDENCIES
Gem::Atom_RHI_Vulkan.Builders
Gem::Atom_RHI_DX12.Private
Gem::Atom_RHI_DX12.Builders
Gem::Atom_RHI_Null.Private
Gem::Atom_RHI_Null.Builders
Gem::Atom_RHI_Metal.Builders
)

@ -157,6 +157,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>;

@ -0,0 +1,100 @@
/*
* 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 "ByteStreamSerializer.h"
#include <AzCore/Casting/numeric_cast.h>
#include <AzCore/Memory/SystemAllocator.h>
#include <AzCore/Serialization/Json/JsonSerialization.h>
#include <AzCore/StringFunc/StringFunc.h>
namespace AZ
{
namespace ByteSerializerInternal
{
static JsonSerializationResult::Result Load(void* outputValue, const rapidjson::Value& inputValue, JsonDeserializerContext& context)
{
using JsonSerializationResult::Outcomes;
using JsonSerializationResult::Tasks;
AZ_Assert(outputValue, "Expected a valid pointer to load from json value.");
switch (inputValue.GetType())
{
case rapidjson::kStringType: {
JsonByteStream buffer;
if (AZ::StringFunc::Base64::Decode(buffer, inputValue.GetString(), inputValue.GetStringLength()))
{
JsonByteStream* valAsByteStream = static_cast<JsonByteStream*>(outputValue);
*valAsByteStream = AZStd::move(buffer);
return context.Report(Tasks::ReadField, Outcomes::Success, "Successfully read ByteStream.");
}
return context.Report(Tasks::ReadField, Outcomes::Invalid, "Decode of Base64 encoded ByteStream failed.");
}
case rapidjson::kArrayType:
case rapidjson::kObjectType:
case rapidjson::kNullType:
case rapidjson::kFalseType:
case rapidjson::kTrueType:
case rapidjson::kNumberType:
return context.Report(
Tasks::ReadField, Outcomes::Unsupported,
"Unsupported type. ByteStream values cannot be read from arrays, objects, nulls, booleans or numbers.");
default:
return context.Report(Tasks::ReadField, Outcomes::Unknown, "Unknown json type encountered for ByteStream value.");
}
}
static JsonSerializationResult::Result StoreWithDefault(
rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue, JsonSerializerContext& context)
{
using JsonSerializationResult::Outcomes;
using JsonSerializationResult::Tasks;
const JsonByteStream& valAsByteStream = *static_cast<const JsonByteStream*>(inputValue);
if (context.ShouldKeepDefaults() || !defaultValue || (valAsByteStream != *static_cast<const JsonByteStream*>(defaultValue)))
{
const auto base64ByteStream = AZ::StringFunc::Base64::Encode(valAsByteStream.data(), valAsByteStream.size());
outputValue.SetString(base64ByteStream.c_str(), base64ByteStream.size(), context.GetJsonAllocator());
return context.Report(Tasks::WriteValue, Outcomes::Success, "ByteStream successfully stored.");
}
return context.Report(Tasks::WriteValue, Outcomes::DefaultsUsed, "Default ByteStream used.");
}
} // namespace ByteSerializerInternal
AZ_CLASS_ALLOCATOR_IMPL(JsonByteStreamSerializer, SystemAllocator, 0);
JsonSerializationResult::Result JsonByteStreamSerializer::Load(
void* outputValue, [[maybe_unused]] const Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
JsonDeserializerContext& context)
{
AZ_Assert(
azrtti_typeid<JsonByteStream>() == outputValueTypeId,
"Unable to deserialize AZStd::vector<AZ::u8>> to json because the provided type is %s",
outputValueTypeId.ToString<AZStd::string>().c_str());
return ByteSerializerInternal::Load(outputValue, inputValue, context);
}
JsonSerializationResult::Result JsonByteStreamSerializer::Store(
rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue, [[maybe_unused]] const Uuid& valueTypeId,
JsonSerializerContext& context)
{
AZ_Assert(
azrtti_typeid<JsonByteStream>() == valueTypeId,
"Unable to serialize AZStd::vector<AZ::u8> to json because the provided type is %s",
valueTypeId.ToString<AZStd::string>().c_str());
return ByteSerializerInternal::StoreWithDefault(outputValue, inputValue, defaultValue, context);
}
} // namespace AZ

@ -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 <AzCore/Serialization/Json/BaseJsonSerializer.h>
#include <AzCore/std/containers/vector.h>
namespace AZ
{
using JsonByteStream = AZStd::vector<AZ::u8>; //!< Alias for AZStd::vector<AZ::u8>.
//! Serialize a stream of bytes (usually binary data) as a json string value.
//! @note Related to GenericClassByteStream (part of SerializeGenericTypeInfo<AZStd::vector<AZ::u8>> - see AZStdContainers.inl for more
//! details).
class JsonByteStreamSerializer : public BaseJsonSerializer
{
public:
AZ_RTTI(JsonByteStreamSerializer, "{30F0EA5A-CD13-4BA7-BAE1-D50D851CAC45}", BaseJsonSerializer);
AZ_CLASS_ALLOCATOR_DECL;
JsonSerializationResult::Result Load(
void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
JsonDeserializerContext& context) override;
JsonSerializationResult::Result Store(
rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue, const Uuid& valueTypeId,
JsonSerializerContext& context) override;
};
} // namespace AZ

@ -14,6 +14,7 @@
#include <AzCore/Serialization/Json/ArraySerializer.h>
#include <AzCore/Serialization/Json/BasicContainerSerializer.h>
#include <AzCore/Serialization/Json/BoolSerializer.h>
#include <AzCore/Serialization/Json/ByteStreamSerializer.h>
#include <AzCore/Serialization/Json/DoubleSerializer.h>
#include <AzCore/Serialization/Json/IntSerializer.h>
#include <AzCore/Serialization/Json/JsonSystemComponent.h>
@ -68,6 +69,8 @@ namespace AZ
jsonContext->Serializer<JsonStringSerializer>()->HandlesType<AZStd::string>();
jsonContext->Serializer<JsonOSStringSerializer>()->HandlesType<OSString>();
jsonContext->Serializer<JsonByteStreamSerializer>()->HandlesType<JsonByteStream>();
jsonContext->Serializer<JsonBasicContainerSerializer>()
->HandlesType<AZStd::fixed_vector>()
->HandlesType<AZStd::forward_list>()

@ -505,6 +505,8 @@ set(FILES
Serialization/Json/BasicContainerSerializer.cpp
Serialization/Json/BoolSerializer.h
Serialization/Json/BoolSerializer.cpp
Serialization/Json/ByteStreamSerializer.h
Serialization/Json/ByteStreamSerializer.cpp
Serialization/Json/CastingHelpers.h
Serialization/Json/DoubleSerializer.h
Serialization/Json/DoubleSerializer.cpp

@ -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 <AzCore/Serialization/Json/ByteStreamSerializer.h>
#include <Tests/Serialization/Json/BaseJsonSerializerFixture.h>
#include <Tests/Serialization/Json/JsonSerializerConformityTests.h>
namespace JsonSerializationTests
{
class ByteStreamSerializerTestDescription : public JsonSerializerConformityTestDescriptor<AZ::JsonByteStream>
{
public:
AZStd::shared_ptr<AZ::BaseJsonSerializer> CreateSerializer() override
{
return AZStd::make_shared<AZ::JsonByteStreamSerializer>();
}
AZStd::shared_ptr<AZ::JsonByteStream> CreateDefaultInstance() override
{
return AZStd::make_shared<AZ::JsonByteStream>();
}
AZStd::shared_ptr<AZ::JsonByteStream> CreateFullySetInstance() override
{
// create a JsonByteStream (AZStd::vector<u8>) with ten 'a's
return AZStd::make_shared<AZ::JsonByteStream>(10, 'a');
}
AZStd::string_view GetJsonForFullySetInstance() override
{
// Base64 encoded version of 'aaaaaaaaaa' (see CreateFullySetInstance)
return R"("YWFhYWFhYWFhYQ==")";
}
void ConfigureFeatures(JsonSerializerConformityTestDescriptorFeatures& features) override
{
features.EnableJsonType(rapidjson::kStringType);
features.m_supportsPartialInitialization = false;
features.m_supportsInjection = false;
}
bool AreEqual(const AZ::JsonByteStream& lhs, const AZ::JsonByteStream& rhs) override
{
return lhs == rhs;
}
};
using ByteStreamConformityTestTypes = ::testing::Types<ByteStreamSerializerTestDescription>;
INSTANTIATE_TYPED_TEST_CASE_P(JsonByteStreamSerialzier, JsonSerializerConformityTests, ByteStreamConformityTestTypes);
} // namespace JsonSerializationTests

@ -98,6 +98,7 @@ set(FILES
Serialization/Json/BaseJsonSerializerTests.cpp
Serialization/Json/BasicContainerSerializerTests.cpp
Serialization/Json/BoolSerializerTests.cpp
Serialization/Json/ByteStreamSerializerTests.cpp
Serialization/Json/ColorSerializerTests.cpp
Serialization/Json/DoubleSerializerTests.cpp
Serialization/Json/IntSerializerTests.cpp

@ -142,6 +142,7 @@ namespace Physics
->Field("PhysicsAsset", &PhysicsAssetShapeConfiguration::m_asset)
->Field("AssetScale", &PhysicsAssetShapeConfiguration::m_assetScale)
->Field("UseMaterialsFromAsset", &PhysicsAssetShapeConfiguration::m_useMaterialsFromAsset)
->Field("SubdivisionLevel", &PhysicsAssetShapeConfiguration::m_subdivisionLevel)
;
if (auto editContext = serializeContext->GetEditContext())

@ -141,6 +141,7 @@ namespace Physics
AZ::Data::Asset<AZ::Data::AssetData> m_asset{ AZ::Data::AssetLoadBehavior::PreLoad };
AZ::Vector3 m_assetScale = AZ::Vector3::CreateOne();
bool m_useMaterialsFromAsset = true;
AZ::u8 m_subdivisionLevel = 4; ///< The level of subdivision if a primitive shape is replaced with a convex mesh due to scaling.
};
class NativeShapeConfiguration : public ShapeConfiguration

@ -142,13 +142,6 @@ namespace Physics
virtual AZStd::shared_ptr<Shape> CreateShape(const ColliderConfiguration& colliderConfiguration, const ShapeConfiguration& configuration) = 0;
/// Adds an appropriate collider component to the entity based on the provided shape configuration.
/// @param entity Entity where the component should be added to.
/// @param colliderConfiguration Configuration of the collider.
/// @param shapeConfiguration Configuration of the shape of the collider.
/// @param addEditorComponents Tells whether to add the Editor version of the collider component or the Game one.
virtual void AddColliderComponentToEntity(AZ::Entity* entity, const Physics::ColliderConfiguration& colliderConfiguration, const Physics::ShapeConfiguration& shapeConfiguration, bool addEditorComponents = false) = 0;
/// Releases the mesh object created by the physics backend.
/// @param nativeMeshObject Pointer to the mesh object.
virtual void ReleaseNativeMeshObject(void* nativeMeshObject) = 0;

@ -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.

@ -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;
};
}
}

@ -56,7 +56,7 @@ CAboutDialog::CAboutDialog(QString versionText, QString richTextCopyrightNotice,
m_backgroundImage = QPixmap::fromImage(backgroundImage.scaled(m_enforcedWidth, m_enforcedHeight, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
// Draw the Open 3D Engine logo from svg
m_ui->m_logo->load(QStringLiteral(":/StartupLogoDialog/lumberyard_logo.svg"));
m_ui->m_logo->load(QStringLiteral(":/StartupLogoDialog/o3de_logo.svg"));
// Prevent re-sizing
setFixedSize(m_enforcedWidth, m_enforcedHeight);

@ -60,35 +60,35 @@
<property name="bottomMargin">
<number>5</number>
</property>
<item>
<layout class="QVBoxLayout" name="verticalLayout_42">
<property name="leftMargin">
<number>4</number>
</property>
<property name="topMargin">
<number>12</number>
</property>
<property name="bottomMargin">
<number>9</number>
</property>
<item>
<widget class="QSvgWidget" name="m_logo" native="true">
<property name="minimumSize">
<size>
<width>250</width>
<height>60</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>250</width>
<height>60</height>
</size>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_42">
<property name="leftMargin">
<number>4</number>
</property>
<property name="topMargin">
<number>12</number>
</property>
<property name="bottomMargin">
<number>9</number>
</property>
<item>
<widget class="QSvgWidget" name="m_logo" native="true">
<property name="minimumSize">
<size>
<width>161</width>
<height>49</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>161</width>
<height>49</height>
</size>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="m_transparentVersion">
<property name="text">
@ -251,6 +251,11 @@
</layout>
</widget>
<customwidgets>
<customwidget>
<class>QSvgWidget</class>
<extends>QWidget</extends>
<header>qsvgwidget.h</header>
</customwidget>
<customwidget>
<class>ClickableLabel</class>
<extends>QLabel</extends>

@ -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 = {};

@ -49,7 +49,7 @@ CStartupLogoDialog::CStartupLogoDialog(QString versionText, QString richTextCopy
m_backgroundImage = QPixmap::fromImage(backgroundImage.scaled(m_enforcedWidth, m_enforcedHeight, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
// Draw the Open 3D Engine logo from svg
m_ui->m_logo->load(QStringLiteral(":/StartupLogoDialog/lumberyard_logo.svg"));
m_ui->m_logo->load(QStringLiteral(":/StartupLogoDialog/o3de_logo.svg"));
m_ui->m_TransparentConfidential->setObjectName("copyrightNotice");
m_ui->m_TransparentConfidential->setTextFormat(Qt::RichText);

@ -1,6 +1,6 @@
<RCC>
<qresource prefix="/StartupLogoDialog">
<file>lumberyard_logo.svg</file>
<file>o3de_logo.svg</file>
<file>splashscreen_1_27.png</file>
</qresource>
</RCC>

@ -42,14 +42,14 @@
<widget class="QSvgWidget" name="m_logo" native="true">
<property name="minimumSize">
<size>
<width>250</width>
<height>60</height>
<width>161</width>
<height>49</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>250</width>
<height>60</height>
<width>161</width>
<height>50</height>
</size>
</property>
</widget>

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 27 KiB

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="323px" height="98px" viewBox="0 0 323 98" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Group 12</title>
<defs>
<polygon id="path-1" points="0 97.741 322.084 97.741 322.084 0 0 0"></polygon>
</defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Group-12" transform="translate(0.000000, 0.000000)">
<path d="M99.7068,20.425 C91.1008,11.686 79.6658,6.841 67.5068,6.782 L67.2838,6.781 C62.9678,6.781 58.7408,7.396 54.6908,8.566 L54.6908,25.339 C58.5158,23.54 62.6988,22.563 67.0218,22.517 C67.1388,22.516 67.2538,22.515 67.3698,22.515 C75.1318,22.515 82.4608,25.519 88.0388,30.996 C93.7828,36.635 96.9708,44.124 97.0168,52.084 C97.0628,60.037 93.9658,67.554 88.2968,73.251 C82.6908,78.884 75.2578,82 67.3558,82.025 L67.2718,82.025 C59.4228,82.025 51.9878,78.959 46.3368,73.393 C40.6918,67.833 37.5578,60.397 37.5108,52.453 C37.4888,48.659 38.1798,44.975 39.5088,41.546 L23.0748,41.546 C19.4908,56.362 23.4348,72.648 34.9328,84.219 C43.5408,92.882 54.9608,97.683 67.0878,97.738 L67.3028,97.738 L67.3058,97.738 C79.3458,97.738 90.7008,93.045 99.2768,84.524 C107.8718,75.984 112.6488,64.62 112.7288,52.524 C112.8088,40.435 108.1838,29.035 99.7068,20.425" id="Fill-1" fill="#FFFFFF"></path>
<path d="M175.6326,27.8629 C175.6326,33.3889 173.9586,38.0879 170.6116,41.9599 C167.2646,45.8319 162.5656,48.4939 156.5146,49.9459 L156.5146,50.3089 C163.6536,51.1969 169.0586,53.3629 172.7296,56.8129 C176.3996,60.2619 178.2356,64.9099 178.2356,70.7579 C178.2356,79.2689 175.1496,85.8939 168.9786,90.6319 C162.8076,95.3719 153.9936,97.7409 142.5386,97.7409 C132.9386,97.7409 124.4286,96.1489 117.0076,92.9609 L117.0076,77.0489 C120.4356,78.7839 124.2076,80.1959 128.3216,81.2839 C132.4356,82.3729 136.5096,82.9179 140.5426,82.9179 C146.7146,82.9179 151.2716,81.8699 154.2156,79.7719 C157.1596,77.6749 158.6326,74.3079 158.6326,69.6679 C158.6326,65.5139 156.9386,62.5699 153.5506,60.8349 C150.1626,59.1009 144.7576,58.2329 137.3366,58.2329 L130.6206,58.2329 L130.6206,43.8939 L137.4576,43.8939 C144.3146,43.8939 149.3246,42.9979 152.4916,41.2019 C155.6576,39.4079 157.2406,36.3319 157.2406,31.9759 C157.2406,25.2809 153.0456,21.9329 144.6566,21.9329 C141.7526,21.9329 138.7986,22.4169 135.7936,23.3849 C132.7886,24.3529 129.4506,26.0279 125.7806,28.4069 L117.1306,15.5199 C125.1956,9.7119 134.8166,6.8079 145.9886,6.8079 C155.1446,6.8079 162.3736,8.6639 167.6786,12.3739 C172.9806,16.0869 175.6326,21.2499 175.6326,27.8629" id="Fill-3" fill="#FFFFFF"></path>
<path d="M241.8563,51.9425 C241.8563,32.9455 233.4653,23.4465 216.6883,23.4465 L206.7053,23.4465 L206.7053,81.0435 L214.7523,81.0435 C232.8213,81.0435 241.8563,71.3435 241.8563,51.9425 M261.3363,51.4595 C261.3363,66.0195 257.1933,77.1715 248.9043,84.9165 C240.6153,92.6605 228.6463,96.5325 212.9973,96.5325 L187.9503,96.5325 L187.9503,8.0815 L215.7193,8.0815 C230.1593,8.0815 241.3723,11.8925 249.3583,19.5155 C257.3433,27.1365 261.3363,37.7855 261.3363,51.4595" id="Fill-5" fill="#FFFFFF"></path>
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<g id="Clip-8"></g>
<polygon id="Fill-7" fill="#FFFFFF" mask="url(#mask-2)" points="23.185 30.421 45.046 30.421 45.046 8.56 23.185 8.56"></polygon>
<polygon id="Fill-9" fill="#FFFFFF" mask="url(#mask-2)" points="5.251 9.038 14.289 9.038 14.289 0 5.251 0"></polygon>
<polygon id="Fill-10" fill="#FFFFFF" mask="url(#mask-2)" points="0 36.195 14.18 36.195 14.18 22.015 0 22.015"></polygon>
<polygon id="Fill-11" fill="#FFFFFF" mask="url(#mask-2)" points="322.0838 96.4337 271.0538 96.4337 271.0538 7.8287 322.0838 7.8287 322.0838 23.2227 289.8418 23.2227 289.8418 42.6767 319.8418 42.6767 319.8418 58.0707 289.8418 58.0707 289.8418 80.9187 322.0838 80.9187"></polygon>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.9 KiB

@ -162,7 +162,7 @@ namespace AZ
AZStd::string expectedHigherPrecedenceFileFullPath;
AzFramework::StringFunc::Path::Join(gameProjectPath, RPI::ShaderVariantTreeAsset::CommonSubFolder, expectedHigherPrecedenceFileFullPath, false /* handle directory overlap? */, false /* be case insensitive? */);
AzFramework::StringFunc::Path::Join(expectedHigherPrecedenceFileFullPath.c_str(), shaderProductFileRelativePath.c_str(), expectedHigherPrecedenceFileFullPath, false /* handle directory overlap? */, false /* be case insensitive? */);
AzFramework::StringFunc::Path::ReplaceExtension(expectedHigherPrecedenceFileFullPath, AZ::RPI::ShaderVariantAsset::Extension);
AzFramework::StringFunc::Path::ReplaceExtension(expectedHigherPrecedenceFileFullPath, AZ::RPI::ShaderVariantListSourceData::Extension);
AzFramework::StringFunc::Path::Normalize(expectedHigherPrecedenceFileFullPath);
AZStd::string normalizedShaderVariantListFileFullPath = shaderVariantListFileFullPath;

@ -21,6 +21,7 @@
#include <RayTracing/RayTracingFeatureProcessor.h>
#include <AzCore/Asset/AssetCommon.h>
#include <AtomCore/std/parallel/concurrency_checker.h>
#include <AzCore/Console/Console.h>
namespace AZ
{
@ -160,8 +161,14 @@ namespace AZ
// called when reflection probes are modified in the editor so that meshes can re-evaluate their probes
void UpdateMeshReflectionProbes();
private:
void ForceRebuildDrawPackets(const AZ::ConsoleCommandContainer& arguments);
AZ_CONSOLEFUNC(MeshFeatureProcessor,
ForceRebuildDrawPackets,
AZ::ConsoleFunctorFlags::Null,
"(For Testing) Invalidates all mesh draw packets, causing them to rebuild on the next frame."
);
MeshFeatureProcessor(const MeshFeatureProcessor&) = delete;
// RPI::SceneNotificationBus::Handler overrides...

@ -387,6 +387,11 @@ namespace AZ
}
}
void MeshFeatureProcessor::ForceRebuildDrawPackets([[maybe_unused]] const AZ::ConsoleCommandContainer& arguments)
{
m_forceRebuildDrawPackets = true;
}
void MeshFeatureProcessor::OnRenderPipelineAdded(RPI::RenderPipelinePtr pipeline)
{
m_forceRebuildDrawPackets = true;;

@ -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)
uint64_t TimestampResult::GetDurationInNanoseconds() const
{
const uint64_t low = AZStd::min(timestampQueryResultLow, timestampQueryResultHigh);
const uint64_t high = AZStd::max(timestampQueryResultLow, timestampQueryResultHigh);
const RHI::Ptr<RHI::Device> device = RHI::GetRHIDevice();
const AZStd::chrono::microseconds timeInMicroseconds = device->GpuTimestampToMicroseconds(m_duration, m_hardwareQueueClass);
const auto timeInNanoseconds = AZStd::chrono::nanoseconds(timeInMicroseconds);
m_timestampInTicks = high - low;
return static_cast<uint64_t>(timeInNanoseconds.count());
}
TimestampResult::TimestampResult(AZStd::array_view<TimestampResult>&& timestampResultArray)
uint64_t TimestampResult::GetDurationInTicks() const
{
// Loop through all the child passes, and accumulate all the timestampTicks
for (const TimestampResult& timestampResult : timestampResultArray)
{
m_timestampInTicks += timestampResult.m_timestampInTicks;
}
return m_duration;
}
uint64_t TimestampResult::GetTimestampInNanoseconds() const
uint64_t TimestampResult::GetTimestampBeginInTicks() const
{
const RHI::Ptr<RHI::Device> device = RHI::GetRHIDevice();
const AZStd::chrono::microseconds timeInMicroseconds = device->GpuTimestampToMicroseconds(m_timestampInTicks, RHI::HardwareQueueClass::Graphics);
const auto timeInNanoseconds = AZStd::chrono::nanoseconds(timeInMicroseconds);
return static_cast<uint64_t>(timeInNanoseconds.count());
return m_begin;
}
uint64_t TimestampResult::GetTimestampInTicks() const
void TimestampResult::Add(const TimestampResult& extent)
{
return m_timestampInTicks;
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 ---

@ -17,11 +17,20 @@
#include <Atom/RPI.Public/Scene.h>
#include <Atom/RPI.Reflect/Material/MaterialFunctor.h>
#include <Atom/RHI/DrawPacketBuilder.h>
#include <AzCore/Console/Console.h>
namespace AZ
{
namespace RPI
{
AZ_CVAR(bool,
r_forceRootShaderVariantUsage,
false,
[](const bool&) { AZ::Interface<AZ::IConsole>::Get()->PerformCommand("MeshFeatureProcessor.ForceRebuildDrawPackets"); },
ConsoleFunctorFlags::Null,
"(For Testing) Forces usage of root shader variant in the mesh draw packet level, ignoring any other shader variants that may exist."
);
MeshDrawPacket::MeshDrawPacket(
ModelLod& modelLod,
size_t modelLodMeshIndex,
@ -187,7 +196,7 @@ namespace AZ
}
const ShaderVariantId finalVariantId = shaderOptions.GetShaderVariantId();
const ShaderVariant& variant = shader->GetVariant(finalVariantId);
const ShaderVariant& variant = r_forceRootShaderVariantUsage ? shader->GetRootVariant() : shader->GetVariant(finalVariantId);
Data::Instance<ShaderResourceGroup> drawSrg;
if (drawSrgAsset)

@ -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(&timestampResult, 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);
}
}

@ -37,6 +37,8 @@ namespace MaterialEditor
//Connect ok and cancel buttons
QObject::connect(m_ui->m_buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
QObject::connect(m_ui->m_buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
setModal(true);
}
void CreateMaterialDialog::InitMaterialTypeSelection()

@ -11,6 +11,7 @@
*/
#include <QApplication>
#include <QClipboard>
#include <QMenu>
#include <QInputDialog>
#include <QMessageBox>
@ -61,6 +62,8 @@ namespace MaterialEditor
m_caller = nullptr;
});
AddGenericContextMenuActions(caller, menu, entry);
if (entry->GetEntryType() == AssetBrowserEntry::AssetEntryType::Source)
{
const auto source = azalias_cast<const SourceAssetBrowserEntry*>(entry);
@ -84,6 +87,18 @@ namespace MaterialEditor
}
}
void MaterialBrowserInteractions::AddGenericContextMenuActions([[maybe_unused]] QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry)
{
menu->addAction(QObject::tr("Copy Name To Clipboard"), [=]()
{
QApplication::clipboard()->setText(entry->GetName().c_str());
});
menu->addAction(QObject::tr("Copy Path To Clipboard"), [=]()
{
QApplication::clipboard()->setText(entry->GetFullPath().c_str());
});
}
void MaterialBrowserInteractions::AddContextMenuActionsForMaterialTypeSource(QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::SourceAssetBrowserEntry* entry)
{
menu->addAction(AzQtComponents::fileBrowserActionName(), [entry]()

@ -44,6 +44,7 @@ namespace MaterialEditor
//! AssetBrowserInteractionNotificationBus::Handler overrides...
void AddContextMenuActions(QWidget* caller, QMenu* menu, const AZStd::vector<AzToolsFramework::AssetBrowser::AssetBrowserEntry*>& entries) override;
void AddGenericContextMenuActions(QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry);
void AddContextMenuActionsForOtherSource(QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::SourceAssetBrowserEntry* entry);
void AddContextMenuActionsForMaterialSource(QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::SourceAssetBrowserEntry* entry);
void AddContextMenuActionsForMaterialTypeSource(QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::SourceAssetBrowserEntry* entry);

@ -35,6 +35,7 @@ namespace MaterialEditor
SetupPresetList();
SetupSearchWidget();
SetupDialogButtons();
setModal(true);
}
void PresetBrowserDialog::SetupPresetList()

@ -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": {
"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.800000011920929,
0.800000011920929,
0.800000011920929,
0.0,
0.0,
0.0,
1.0
],
"textureMap": "Textures/ceiling_1k_basecolor.png"
]
},
"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

@ -25,6 +25,7 @@ AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnin
#include <QApplication>
#include <QCheckBox>
#include <QComboBox>
#include <QDialogButtonBox>
#include <QFileDialog>
#include <QHBoxLayout>
#include <QHeaderView>
@ -215,19 +216,10 @@ namespace AZ
tableWidget->sortItems(MaterialSlotColumn);
// Create the bottom row of the dialog with action buttons for exporting or canceling the operation
QWidget* buttonRow = new QWidget(&dialog);
buttonRow->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
QPushButton* confirmButton = new QPushButton("Confirm", buttonRow);
QObject::connect(confirmButton, &QPushButton::clicked, confirmButton, [&dialog] { dialog.accept(); });
QPushButton* cancelButton = new QPushButton("Cancel", buttonRow);
QObject::connect(cancelButton, &QPushButton::clicked, cancelButton, [&dialog] { dialog.reject(); });
QHBoxLayout* buttonLayout = new QHBoxLayout(buttonRow);
buttonLayout->addStretch();
buttonLayout->addWidget(confirmButton);
buttonLayout->addWidget(cancelButton);
QDialogButtonBox* buttonBox = new QDialogButtonBox(&dialog);
buttonBox->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Ok);
QObject::connect(buttonBox, &QDialogButtonBox::accepted, &dialog, &QDialog::accept);
QObject::connect(buttonBox, &QDialogButtonBox::rejected, &dialog, &QDialog::reject);
// Create a heading label for the top of the dialog
QLabel* labelWidget = new QLabel("\nSelect the material slots that you want to generate new source materials for. Edit the material file name and location using the file picker.\n", &dialog);
@ -236,8 +228,9 @@ namespace AZ
QVBoxLayout* dialogLayout = new QVBoxLayout(&dialog);
dialogLayout->addWidget(labelWidget);
dialogLayout->addWidget(tableWidget);
dialogLayout->addWidget(buttonRow);
dialogLayout->addWidget(buttonBox);
dialog.setLayout(dialogLayout);
dialog.setModal(true);
// Forcing the initial dialog size to accomodate typical content.
// Temporarily settng fixed size because dialog.show/exec invokes WindowDecorationWrapper::showEvent.

@ -37,6 +37,7 @@
AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT
#include <QApplication>
#include <QDialog>
#include <QDialogButtonBox>
#include <QFileInfo>
#include <QHBoxLayout>
#include <QLabel>
@ -534,7 +535,7 @@ namespace AZ
inspector->Populate();
inspector->SetOverrides(propertyOverrideMap);
// Create the menu bottom row with actions for exporting or canceling the operation
// Create the menu button
QToolButton* menuButton = new QToolButton(&dialog);
menuButton->setAutoRaise(true);
menuButton->setIcon(QIcon(":/Cards/img/UI20/Cards/menu_ico.svg"));
@ -546,10 +547,6 @@ namespace AZ
action = menu.addAction("Clear Overrides", [&] { inspector->SetOverrides(MaterialPropertyOverrideMap()); });
action = menu.addAction("Revert Changes", [&] { inspector->SetOverrides(propertyOverrideMap); });
menu.addSeparator();
action = menu.addAction("Confirm Changes", [&] { dialog.accept(); });
action = menu.addAction("Cancel Changes", [&] { dialog.reject(); });
menu.addSeparator();
action = menu.addAction("Save Material", [&] { inspector->SaveMaterial(); });
action = menu.addAction("Save Material To Source", [&] { inspector->SaveMaterialToSource(); });
@ -563,12 +560,19 @@ namespace AZ
menu.exec(QCursor::pos());
});
QDialogButtonBox* buttonBox = new QDialogButtonBox(&dialog);
buttonBox->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Ok);
QObject::connect(buttonBox, &QDialogButtonBox::accepted, &dialog, &QDialog::accept);
QObject::connect(buttonBox, &QDialogButtonBox::rejected, &dialog, &QDialog::reject);
QObject::connect(&dialog, &QDialog::rejected, &dialog, [&] { inspector->SetOverrides(propertyOverrideMap); });
QVBoxLayout* dialogLayout = new QVBoxLayout(&dialog);
dialogLayout->addWidget(menuButton);
dialogLayout->addWidget(inspector);
dialogLayout->addWidget(buttonBox);
dialog.setLayout(dialogLayout);
dialog.setModal(true);
// Forcing the initial dialog size to accomodate typical content.
// Temporarily settng fixed size because dialog.show/exec invokes WindowDecorationWrapper::showEvent.

@ -32,8 +32,11 @@
AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT
#include <QApplication>
#include <QDialog>
#include <QPushButton>
#include <QDialogButtonBox>
#include <QHBoxLayout>
#include <QMenu>
#include <QPushButton>
#include <QToolButton>
#include <QVBoxLayout>
AZ_POP_DISABLE_WARNING
@ -286,42 +289,31 @@ namespace AZ
MaterialModelUvNameMapInspector* inspector = new MaterialModelUvNameMapInspector(assetId, matModUvOverrides, modelUvNames, matModUvOverrideMapChangedCallBack, &dialog);
inspector->Populate();
// Create the bottom row of the dialog with action buttons for exporting or canceling the operation
QWidget* buttonRow = new QWidget(&dialog);
buttonRow->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
QPushButton* revertButton = new QPushButton("Revert", buttonRow);
QObject::connect(revertButton, &QPushButton::clicked, revertButton, [inspector, matModUvOverrides] {
inspector->SetUvNameMap(matModUvOverrides);
});
QPushButton* clearButton = new QPushButton("Clear", buttonRow);
QObject::connect(clearButton, &QPushButton::clicked, clearButton, [inspector] {
inspector->SetUvNameMap(RPI::MaterialModelUvOverrideMap());
});
QPushButton* confirmButton = new QPushButton("Confirm", buttonRow);
QObject::connect(confirmButton, &QPushButton::clicked, confirmButton, [&dialog] {
dialog.accept();
});
QPushButton* cancelButton = new QPushButton("Cancel", buttonRow);
QObject::connect(cancelButton, &QPushButton::clicked, cancelButton, [inspector, matModUvOverrides, &dialog] {
inspector->SetUvNameMap(matModUvOverrides);
dialog.reject();
});
QHBoxLayout* buttonLayout = new QHBoxLayout(buttonRow);
buttonLayout->addStretch();
buttonLayout->addWidget(revertButton);
buttonLayout->addWidget(clearButton);
buttonLayout->addWidget(confirmButton);
buttonLayout->addWidget(cancelButton);
// Create the menu button
QToolButton* menuButton = new QToolButton(&dialog);
menuButton->setAutoRaise(true);
menuButton->setIcon(QIcon(":/Cards/img/UI20/Cards/menu_ico.svg"));
menuButton->setVisible(true);
QObject::connect(menuButton, &QToolButton::clicked, &dialog, [&]() {
QAction* action = nullptr;
QMenu menu(&dialog);
action = menu.addAction("Clear", [&] { inspector->SetUvNameMap(RPI::MaterialModelUvOverrideMap()); });
action = menu.addAction("Revert", [&] { inspector->SetUvNameMap(matModUvOverrides);; });
menu.exec(QCursor::pos());
});
QDialogButtonBox* buttonBox = new QDialogButtonBox(&dialog);
buttonBox->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Ok);
QObject::connect(buttonBox, &QDialogButtonBox::accepted, &dialog, &QDialog::accept);
QObject::connect(buttonBox, &QDialogButtonBox::rejected, &dialog, &QDialog::reject);
QVBoxLayout* dialogLayout = new QVBoxLayout(&dialog);
dialogLayout->addWidget(menuButton);
dialogLayout->addWidget(inspector);
dialogLayout->addWidget(buttonRow);
dialogLayout->addWidget(buttonBox);
dialog.setLayout(dialogLayout);
dialog.setModal(true);
// Forcing the initial dialog size to accomodate typical content.
// Temporarily settng fixed size because dialog.show/exec invokes WindowDecorationWrapper::showEvent.

@ -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))

@ -213,9 +213,6 @@ namespace Blast
CreateShape,
AZStd::shared_ptr<Physics::Shape>(
const Physics::ColliderConfiguration&, const Physics::ShapeConfiguration&));
MOCK_METHOD4(
AddColliderComponentToEntity,
void(AZ::Entity*, const Physics::ColliderConfiguration&, const Physics::ShapeConfiguration&, bool));
MOCK_METHOD1(ReleaseNativeMeshObject, void(void*));
MOCK_METHOD1(CreateMaterial, AZStd::shared_ptr<Physics::Material>(const Physics::MaterialConfiguration&));
MOCK_METHOD0(GetDefaultMaterial, AZStd::shared_ptr<Physics::Material>());

@ -33,7 +33,6 @@ namespace Physics
BusDisconnect();
}
MOCK_METHOD2(CreateShape, AZStd::shared_ptr<Physics::Shape>(const Physics::ColliderConfiguration& colliderConfiguration, const Physics::ShapeConfiguration& configuration));
MOCK_METHOD4(AddColliderComponentToEntity, void(AZ::Entity* entity, const Physics::ColliderConfiguration& colliderConfiguration, const Physics::ShapeConfiguration& shapeConfiguration, bool addEditorComponents));
MOCK_METHOD1(ReleaseNativeMeshObject, void(void* nativeMeshObject));
MOCK_METHOD1(CreateMaterial, AZStd::shared_ptr<Physics::Material>(const Physics::MaterialConfiguration& materialConfiguration));
MOCK_METHOD0(GetDefaultMaterial, AZStd::shared_ptr<Physics::Material>());

@ -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;

@ -65,6 +65,7 @@ namespace LmbrCentral
ShapeComponentNotificationsBus::Handler::BusDisconnect();
PolygonPrismShapeComponentNotificationBus::Handler::BusDisconnect();
AZ::TransformNotificationBus::Handler::BusDisconnect();
m_nonUniformScaleChangedHandler.Disconnect();
DestroyManipulators();
}

@ -217,6 +217,7 @@ namespace LmbrCentral
AZ::TransformBus::EventResult(m_currentTransform, entityId, &AZ::TransformBus::Events::GetWorldTM);
m_currentNonUniformScale = AZ::Vector3::CreateOne();
AZ::NonUniformScaleRequestBus::EventResult(m_currentNonUniformScale, m_entityId, &AZ::NonUniformScaleRequests::GetScale);
m_polygonPrism->SetNonUniformScale(m_currentNonUniformScale);
m_intersectionDataCache.InvalidateCache(InvalidateShapeCacheReason::ShapeChange);
AZ::TransformNotificationBus::Handler::BusConnect(entityId);

@ -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) }};
}
}
}

@ -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;

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save