Merge branch 'main' into Atom/dmcdiar/ATOM-15718
This commit is contained in:
@@ -137,5 +137,6 @@ enum class AnimParamType
|
||||
Invalid = static_cast<int>(0xFFFFFFFF)
|
||||
};
|
||||
|
||||
static const int OLD_APARAM_USER = 100;
|
||||
|
||||
#endif // CRYINCLUDE_CRYCOMMON_MAESTRO_TYPES_ANIMPARAMTYPE_H
|
||||
|
||||
@@ -561,7 +561,7 @@ void DebugCallStack::LogExceptionInfo(EXCEPTION_POINTERS* pex)
|
||||
|
||||
if (pex)
|
||||
{
|
||||
MINIDUMP_TYPE mdumpValue;
|
||||
MINIDUMP_TYPE mdumpValue = MiniDumpNormal;
|
||||
bool bDump = true;
|
||||
switch (g_cvars.sys_dump_type)
|
||||
{
|
||||
|
||||
@@ -66,7 +66,7 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
}
|
||||
if (pSystem && !pSystem->IsQuitting())
|
||||
{
|
||||
LRESULT result;
|
||||
LRESULT result = 0;
|
||||
bool bAny = false;
|
||||
for (std::vector<IWindowMessageHandler*>::const_iterator it = pSystem->m_windowMessageHandlers.begin(); it != pSystem->m_windowMessageHandlers.end(); ++it)
|
||||
{
|
||||
|
||||
@@ -634,7 +634,7 @@ ICVar* CSystem::attachVariable (const char* szVarName, int* pContainer, const ch
|
||||
IConsole* pConsole = GetIConsole();
|
||||
|
||||
ICVar* pOldVar = pConsole->GetCVar (szVarName);
|
||||
int nDefault;
|
||||
int nDefault = 0;
|
||||
if (pOldVar)
|
||||
{
|
||||
nDefault = pOldVar->GetIVal();
|
||||
|
||||
@@ -127,13 +127,14 @@ namespace AZ
|
||||
*/
|
||||
class EditContext
|
||||
{
|
||||
public:
|
||||
/// @cond EXCLUDE_DOCS
|
||||
class ClassBuilder;
|
||||
class EnumBuilder;
|
||||
using ClassInfo = ClassBuilder; ///< @deprecated Use EditContext::ClassBuilder
|
||||
using EnumInfo = EnumBuilder; ///< @deprecated Use EditContext::EnumBuilder
|
||||
/// @endcond
|
||||
public:
|
||||
|
||||
AZ_CLASS_ALLOCATOR(EditContext, SystemAllocator, 0);
|
||||
|
||||
/**
|
||||
@@ -186,6 +187,7 @@ namespace AZ
|
||||
* look at the unit tests and example to see use cases.
|
||||
*
|
||||
*/
|
||||
public:
|
||||
class ClassBuilder
|
||||
{
|
||||
friend EditContext;
|
||||
@@ -399,6 +401,7 @@ namespace AZ
|
||||
EnumBuilder* Value(const char* name, E value);
|
||||
};
|
||||
|
||||
private:
|
||||
typedef AZStd::list<Edit::ClassData> ClassDataListType;
|
||||
typedef AZStd::unordered_map<AZ::Uuid, Edit::ElementData> EnumDataMapType;
|
||||
|
||||
|
||||
@@ -101,6 +101,9 @@ namespace AZ
|
||||
class SerializeContext
|
||||
: public ReflectContext
|
||||
{
|
||||
static const unsigned int VersionClassDeprecated = (unsigned int)-1;
|
||||
|
||||
public:
|
||||
/// @cond EXCLUDE_DOCS
|
||||
friend class EditContext;
|
||||
class ClassBuilder;
|
||||
@@ -108,9 +111,6 @@ namespace AZ
|
||||
/// @endcond
|
||||
class EnumBuilder;
|
||||
|
||||
static const unsigned int VersionClassDeprecated = (unsigned int)-1;
|
||||
|
||||
public:
|
||||
class ClassData;
|
||||
struct EnumerateInstanceCallContext;
|
||||
struct ClassElement;
|
||||
@@ -1131,6 +1131,7 @@ namespace AZ
|
||||
* ->Version(3,&MyVersionConverter)
|
||||
* ->Field("data",&MyStruct::m_data);
|
||||
*/
|
||||
public:
|
||||
class ClassBuilder
|
||||
{
|
||||
friend class SerializeContext;
|
||||
@@ -1330,7 +1331,8 @@ namespace AZ
|
||||
AZStd::vector<AttributeSharedPair, AZStdFunctorAllocator>* m_currentAttributes = nullptr;
|
||||
};
|
||||
|
||||
EditContext* m_editContext; ///< Pointer to optional edit context.
|
||||
private:
|
||||
EditContext* m_editContext; ///< Pointer to optional edit context.
|
||||
UuidToClassMap m_uuidMap; ///< Map for all class in this serialize context
|
||||
AZStd::unordered_multimap<AZ::Crc32, AZ::Uuid> m_classNameToUuid; /// Map all class names to their uuid
|
||||
AZStd::unordered_multimap<Uuid, GenericClassInfo*> m_uuidGenericMap; ///< Uuid to ClassData map of reflected classes with GenericTypeInfo
|
||||
|
||||
@@ -971,6 +971,10 @@ namespace AZ
|
||||
*/
|
||||
void RestoreCachedInstances();
|
||||
|
||||
/// Returns data flags for use when instantiating an instance of this slice.
|
||||
/// These data flags include those harvested from the entire slice ancestry.
|
||||
const DataFlagsPerEntity& GetDataFlagsForInstances() const;
|
||||
|
||||
protected:
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -1004,9 +1008,6 @@ namespace AZ
|
||||
DataFlagsPerEntity* GetCorrectBundleOfDataFlags(EntityId entityId);
|
||||
const DataFlagsPerEntity* GetCorrectBundleOfDataFlags(EntityId entityId) const;
|
||||
|
||||
/// Returns data flags for use when instantiating an instance of this slice.
|
||||
/// These data flags include those harvested from the entire slice ancestry.
|
||||
const DataFlagsPerEntity& GetDataFlagsForInstances() const;
|
||||
void BuildDataFlagsForInstances();
|
||||
|
||||
/**
|
||||
|
||||
+16
-7
@@ -13,9 +13,10 @@
|
||||
#include <AzCore/Module/DynamicModuleHandle.h>
|
||||
#include <AzCore/IO/Path/Path.h>
|
||||
#include <AzCore/IO/SystemFile.h>
|
||||
|
||||
#include <AzCore/Memory/OSAllocator.h>
|
||||
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
|
||||
#include <AzCore/Utils/Utils.h>
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <libgen.h>
|
||||
|
||||
@@ -61,10 +62,11 @@ namespace AZ
|
||||
// If it doesn't attempt to append the path to the executable path
|
||||
if (!AZ::IO::SystemFile::Exists(fullFilePath.c_str()))
|
||||
{
|
||||
auto candidatePath = Platform::GetModulePath() / fullFilePath;
|
||||
AZ::IO::FixedMaxPath candidatePath = Platform::GetModulePath() / fullFilePath;
|
||||
if (AZ::IO::SystemFile::Exists(candidatePath.c_str()))
|
||||
{
|
||||
fullFilePath = candidatePath;
|
||||
m_fileName.assign(candidatePath.Native().c_str(), candidatePath.Native().size());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,19 +76,26 @@ namespace AZ
|
||||
{
|
||||
if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr)
|
||||
{
|
||||
if(AZ::IO::FixedMaxPath projectModulePath;
|
||||
if (AZ::IO::FixedMaxPath projectModulePath;
|
||||
settingsRegistry->Get(projectModulePath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_ProjectConfigurationBinPath))
|
||||
{
|
||||
projectModulePath /= fullFilePath;
|
||||
if (AZ::IO::SystemFile::Exists(projectModulePath.c_str()))
|
||||
{
|
||||
fullFilePath = projectModulePath;
|
||||
m_fileName.assign(projectModulePath.c_str(), projectModulePath.Native().size());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_fileName = AZStd::string_view{fullFilePath.Native()};
|
||||
else
|
||||
{
|
||||
// The module does exist (in 'cwd'), but still needs to be an absolute path for the module to be loaded.
|
||||
AZStd::optional<AZ::IO::FixedMaxPathString> absPathOptional = AZ::Utils::ConvertToAbsolutePath(m_fileName);
|
||||
if (absPathOptional.has_value())
|
||||
{
|
||||
m_fileName.assign(absPathOptional->c_str(), absPathOptional->size());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
~DynamicModuleHandleUnixLike() override
|
||||
|
||||
+13
-3
@@ -24,9 +24,9 @@ namespace AZ
|
||||
: public DynamicModuleHandle
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(DynamicModuleHandleWindows, OSAllocator, 0)
|
||||
AZ_CLASS_ALLOCATOR(DynamicModuleHandleWindows, OSAllocator, 0);
|
||||
|
||||
DynamicModuleHandleWindows(const char* fullFileName)
|
||||
DynamicModuleHandleWindows(const char* fullFileName)
|
||||
: DynamicModuleHandle(fullFileName)
|
||||
, m_handle(nullptr)
|
||||
{
|
||||
@@ -52,6 +52,7 @@ namespace AZ
|
||||
if (AZ::IO::SystemFile::Exists(candidatePath.c_str()))
|
||||
{
|
||||
m_fileName.assign(candidatePath.Native().c_str(), candidatePath.Native().size());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -65,7 +66,7 @@ namespace AZ
|
||||
// Therefore an existence check is needed
|
||||
if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr)
|
||||
{
|
||||
if(AZ::IO::FixedMaxPath projectModulePath;
|
||||
if (AZ::IO::FixedMaxPath projectModulePath;
|
||||
settingsRegistry->Get(projectModulePath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_ProjectConfigurationBinPath))
|
||||
{
|
||||
projectModulePath /= AZStd::string_view(m_fileName);
|
||||
@@ -76,6 +77,15 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// The module does exist (in 'cwd'), but still needs to be an absolute path for the module to be loaded.
|
||||
AZStd::optional<AZ::IO::FixedMaxPathString> absPathOptional = AZ::Utils::ConvertToAbsolutePath(m_fileName);
|
||||
if (absPathOptional.has_value())
|
||||
{
|
||||
m_fileName.assign(absPathOptional->c_str(), absPathOptional->size());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
~DynamicModuleHandleWindows() override
|
||||
|
||||
@@ -1914,7 +1914,7 @@ namespace UnitTest
|
||||
TEST_F(String, StringView_CompareIsConstexpr)
|
||||
{
|
||||
using TypeParam = char;
|
||||
auto MakeCompileTimeString1 = []() constexpr -> const TypeParam*
|
||||
auto ThisTestMakeCompileTimeString1 = []() constexpr -> const TypeParam*
|
||||
{
|
||||
return "HelloWorld";
|
||||
};
|
||||
@@ -1922,7 +1922,7 @@ namespace UnitTest
|
||||
{
|
||||
return "HelloPearl";
|
||||
};
|
||||
constexpr const TypeParam* compileTimeString1 = MakeCompileTimeString1();
|
||||
constexpr const TypeParam* compileTimeString1 = ThisTestMakeCompileTimeString1();
|
||||
constexpr const TypeParam* compileTimeString2 = MakeCompileTimeString2();
|
||||
constexpr basic_string_view<TypeParam> lhsView(compileTimeString1);
|
||||
constexpr basic_string_view<TypeParam> rhsView(compileTimeString2);
|
||||
@@ -1937,11 +1937,11 @@ namespace UnitTest
|
||||
TEST_F(String, StringView_CompareOperatorsAreConstexpr)
|
||||
{
|
||||
using TypeParam = char;
|
||||
auto MakeCompileTimeString1 = []() constexpr -> const TypeParam*
|
||||
auto TestMakeCompileTimeString1 = []() constexpr -> const TypeParam*
|
||||
{
|
||||
return "HelloWorld";
|
||||
};
|
||||
constexpr const TypeParam* compileTimeString1 = MakeCompileTimeString1();
|
||||
constexpr const TypeParam* compileTimeString1 = TestMakeCompileTimeString1();
|
||||
constexpr basic_string_view<TypeParam> compareView(compileTimeString1);
|
||||
static_assert(compareView == "HelloWorld", "string_view operator== comparison has failed");
|
||||
static_assert(compareView != "MadWorld", "string_view operator!= comparison has failed");
|
||||
@@ -1955,7 +1955,7 @@ namespace UnitTest
|
||||
{
|
||||
auto swap_test_func = []() constexpr -> basic_string_view<TypeParam>
|
||||
{
|
||||
constexpr auto MakeCompileTimeString1 = []() constexpr -> const TypeParam*
|
||||
constexpr auto ThisTestMakeCompileTimeString1 = []() constexpr -> const TypeParam*
|
||||
{
|
||||
if constexpr (AZStd::is_same_v<TypeParam, char>)
|
||||
{
|
||||
@@ -1977,7 +1977,7 @@ namespace UnitTest
|
||||
return L"InuWorld";
|
||||
}
|
||||
};
|
||||
constexpr const TypeParam* compileTimeString1 = MakeCompileTimeString1();
|
||||
constexpr const TypeParam* compileTimeString1 = ThisTestMakeCompileTimeString1();
|
||||
constexpr const TypeParam* compileTimeString2 = MakeCompileTimeString2();
|
||||
basic_string_view<TypeParam> lhsView(compileTimeString1);
|
||||
basic_string_view<TypeParam> rhsView(compileTimeString2);
|
||||
@@ -2001,7 +2001,7 @@ namespace UnitTest
|
||||
|
||||
TYPED_TEST(BasicStringViewConstexprFixture, HashString_FunctionIsConstexpr)
|
||||
{
|
||||
auto MakeCompileTimeString1 = []() constexpr -> const TypeParam*
|
||||
auto ThisTestMakeCompileTimeString1 = []() constexpr -> const TypeParam*
|
||||
{
|
||||
if constexpr (AZStd::is_same_v<TypeParam, char>)
|
||||
{
|
||||
@@ -2012,7 +2012,7 @@ namespace UnitTest
|
||||
return L"HelloWorld";
|
||||
}
|
||||
};
|
||||
constexpr const TypeParam* compileTimeString1 = MakeCompileTimeString1();
|
||||
constexpr const TypeParam* compileTimeString1 = ThisTestMakeCompileTimeString1();
|
||||
constexpr basic_string_view<TypeParam> hashView(compileTimeString1);
|
||||
constexpr size_t compileHash = AZStd::hash<basic_string_view<TypeParam>>{}(hashView);
|
||||
static_assert(compileHash != 0, "Hash of \"HelloWorld\" should not be 0");
|
||||
|
||||
@@ -395,7 +395,8 @@ namespace UnitTest
|
||||
}
|
||||
else
|
||||
{
|
||||
int result1, result2;
|
||||
int result1 = 0;
|
||||
int result2 = 0;
|
||||
Job* job1 = aznew FibonacciJob2(m_n - 1, &result1, m_context);
|
||||
Job* job2 = aznew FibonacciJob2(m_n - 2, &result2, m_context);
|
||||
StartAsChild(job1);
|
||||
|
||||
@@ -59,7 +59,7 @@ namespace UnitTest
|
||||
|
||||
TEST(MATH_Matrix4x4, TestCreateFrom)
|
||||
{
|
||||
float testFloats[] =
|
||||
float thisTestFloats[] =
|
||||
{
|
||||
1.0f, 2.0f, 3.0f, 4.0f,
|
||||
5.0f, 6.0f, 7.0f, 8.0f,
|
||||
@@ -67,20 +67,20 @@ namespace UnitTest
|
||||
13.0f, 14.0f, 15.0f, 16.0f
|
||||
};
|
||||
float testFloatMtx[16];
|
||||
Matrix4x4 m1 = Matrix4x4::CreateFromRowMajorFloat16(testFloats);
|
||||
Matrix4x4 m1 = Matrix4x4::CreateFromRowMajorFloat16(thisTestFloats);
|
||||
AZ_TEST_ASSERT(m1.GetRow(0) == Vector4(1.0f, 2.0f, 3.0f, 4.0f));
|
||||
AZ_TEST_ASSERT(m1.GetRow(1) == Vector4(5.0f, 6.0f, 7.0f, 8.0f));
|
||||
AZ_TEST_ASSERT(m1.GetRow(2) == Vector4(9.0f, 10.0f, 11.0f, 12.0f));
|
||||
AZ_TEST_ASSERT(m1.GetRow(3) == Vector4(13.0f, 14.0f, 15.0f, 16.0f));
|
||||
m1.StoreToRowMajorFloat16(testFloatMtx);
|
||||
AZ_TEST_ASSERT(memcmp(testFloatMtx, testFloats, sizeof(testFloatMtx)) == 0);
|
||||
m1 = Matrix4x4::CreateFromColumnMajorFloat16(testFloats);
|
||||
AZ_TEST_ASSERT(memcmp(testFloatMtx, thisTestFloats, sizeof(testFloatMtx)) == 0);
|
||||
m1 = Matrix4x4::CreateFromColumnMajorFloat16(thisTestFloats);
|
||||
AZ_TEST_ASSERT(m1.GetRow(0) == Vector4(1.0f, 5.0f, 9.0f, 13.0f));
|
||||
AZ_TEST_ASSERT(m1.GetRow(1) == Vector4(2.0f, 6.0f, 10.0f, 14.0f));
|
||||
AZ_TEST_ASSERT(m1.GetRow(2) == Vector4(3.0f, 7.0f, 11.0f, 15.0f));
|
||||
AZ_TEST_ASSERT(m1.GetRow(3) == Vector4(4.0f, 8.0f, 12.0f, 16.0f));
|
||||
m1.StoreToColumnMajorFloat16(testFloatMtx);
|
||||
AZ_TEST_ASSERT(memcmp(testFloatMtx, testFloats, sizeof(testFloatMtx)) == 0);
|
||||
AZ_TEST_ASSERT(memcmp(testFloatMtx, thisTestFloats, sizeof(testFloatMtx)) == 0);
|
||||
}
|
||||
|
||||
TEST(MATH_Matrix4x4, TestCreateFromMatrix3x4)
|
||||
|
||||
@@ -119,10 +119,10 @@ namespace UnitTest
|
||||
|
||||
TEST(MATH_Obb, Contains)
|
||||
{
|
||||
const Vector3 position(1.0f, 2.0f, 3.0f);
|
||||
const Quaternion rotation = Quaternion::CreateRotationZ(DegToRad(30.0f));
|
||||
const Vector3 halfLengths(2.0f, 1.0f, 2.5f);
|
||||
const Obb obb = Obb::CreateFromPositionRotationAndHalfLengths(position, rotation, halfLengths);
|
||||
const Vector3 testPosition(1.0f, 2.0f, 3.0f);
|
||||
const Quaternion testRotation = Quaternion::CreateRotationZ(DegToRad(30.0f));
|
||||
const Vector3 testHalfLengths(2.0f, 1.0f, 2.5f);
|
||||
const Obb obb = Obb::CreateFromPositionRotationAndHalfLengths(testPosition, testRotation, testHalfLengths);
|
||||
// test some pairs of points which should be just either side of the Obb boundary
|
||||
EXPECT_TRUE(obb.Contains(Vector3(1.35f, 3.35f, 3.5f)));
|
||||
EXPECT_FALSE(obb.Contains(Vector3(1.35f, 3.4f, 3.5f)));
|
||||
@@ -134,10 +134,10 @@ namespace UnitTest
|
||||
|
||||
TEST(MATH_Obb, GetDistance)
|
||||
{
|
||||
const Vector3 position(5.0f, 3.0f, 2.0f);
|
||||
const Quaternion rotation = Quaternion::CreateRotationX(DegToRad(60.0f));
|
||||
const Vector3 halfLengths(0.5f, 2.0f, 1.5f);
|
||||
const Obb obb = Obb::CreateFromPositionRotationAndHalfLengths(position, rotation, halfLengths);
|
||||
const Vector3 testPosition(5.0f, 3.0f, 2.0f);
|
||||
const Quaternion testRotation = Quaternion::CreateRotationX(DegToRad(60.0f));
|
||||
const Vector3 testHalfLengths(0.5f, 2.0f, 1.5f);
|
||||
const Obb obb = Obb::CreateFromPositionRotationAndHalfLengths(testPosition, testRotation, testHalfLengths);
|
||||
EXPECT_NEAR(obb.GetDistance(Vector3(5.3f, 3.2f, 1.8f)), 0.0f, 1e-3f);
|
||||
EXPECT_NEAR(obb.GetDistance(Vector3(5.1f, 1.1f, 3.7f)), 0.9955f, 1e-3f);
|
||||
EXPECT_NEAR(obb.GetDistance(Vector3(4.7f, 4.5f, 4.2f)), 0.6553f, 1e-3f);
|
||||
@@ -146,10 +146,10 @@ namespace UnitTest
|
||||
|
||||
TEST(MATH_Obb, GetDistanceSq)
|
||||
{
|
||||
const Vector3 position(1.0f, 4.0f, 3.0f);
|
||||
const Quaternion rotation = Quaternion::CreateRotationY(DegToRad(45.0f));
|
||||
const Vector3 halfLengths(1.5f, 3.0f, 1.0f);
|
||||
const Obb obb = Obb::CreateFromPositionRotationAndHalfLengths(position, rotation, halfLengths);
|
||||
const Vector3 testPosition(1.0f, 4.0f, 3.0f);
|
||||
const Quaternion testRotation = Quaternion::CreateRotationY(DegToRad(45.0f));
|
||||
const Vector3 testHalfLengths(1.5f, 3.0f, 1.0f);
|
||||
const Obb obb = Obb::CreateFromPositionRotationAndHalfLengths(testPosition, testRotation, testHalfLengths);
|
||||
EXPECT_NEAR(obb.GetDistanceSq(Vector3(1.1f, 4.3f, 2.7f)), 0.0f, 1e-3f);
|
||||
EXPECT_NEAR(obb.GetDistanceSq(Vector3(-0.7f, 3.5f, 2.0f)), 0.8266f, 1e-3f);
|
||||
EXPECT_NEAR(obb.GetDistanceSq(Vector3(2.4f, 0.5f, 1.5f)), 0.5532f, 1e-3f);
|
||||
|
||||
+1
@@ -353,6 +353,7 @@ namespace AzFramework
|
||||
|
||||
// Get the dimensions of the display device on which the window is currently displayed.
|
||||
MONITORINFO monitorInfo;
|
||||
memset(&monitorInfo, 0, sizeof(MONITORINFO)); // C4701 potentially uninitialized local variable 'monitorInfo' used
|
||||
monitorInfo.cbSize = sizeof(MONITORINFO);
|
||||
const BOOL success = monitor ? GetMonitorInfo(monitor, &monitorInfo) : FALSE;
|
||||
if (!success)
|
||||
|
||||
@@ -46,7 +46,7 @@ namespace AzNetworking
|
||||
}
|
||||
else if (m_updateRate < updateTimeMs)
|
||||
{
|
||||
AZLOG_INFO("TimedThread bled %d ms", aznumeric_cast<int32_t>(updateTimeMs - m_updateRate));
|
||||
AZLOG(NET_TimedThread, "TimedThread bled %d ms", aznumeric_cast<int32_t>(updateTimeMs - m_updateRate));
|
||||
}
|
||||
}
|
||||
OnStop();
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <AzToolsFramework/Entity/EditorEntityContextBus.h>
|
||||
#include <AzToolsFramework/Entity/EditorEntityHelpers.h>
|
||||
#include <AzToolsFramework/Prefab/Instance/Instance.h>
|
||||
#include <AzToolsFramework/Prefab/PrefabDomUtils.h>
|
||||
#include <AzToolsFramework/Prefab/Instance/InstanceEntityMapperInterface.h>
|
||||
#include <AzToolsFramework/Prefab/Instance/TemplateInstanceMapperInterface.h>
|
||||
|
||||
@@ -49,8 +50,7 @@ namespace AzToolsFramework
|
||||
m_alias = GenerateInstanceAlias();
|
||||
m_containerEntity = containerEntity ? AZStd::move(containerEntity)
|
||||
: AZStd::make_unique<AZ::Entity>();
|
||||
EntityAlias containerEntityAlias = GenerateEntityAlias();
|
||||
RegisterEntity(m_containerEntity->GetId(), containerEntityAlias);
|
||||
RegisterEntity(m_containerEntity->GetId(), PrefabDomUtils::ContainerEntityName);
|
||||
}
|
||||
|
||||
Instance::~Instance()
|
||||
@@ -311,8 +311,15 @@ namespace AzToolsFramework
|
||||
Instance& Instance::AddInstance(AZStd::unique_ptr<Instance> instance)
|
||||
{
|
||||
InstanceAlias newInstanceAlias = GenerateInstanceAlias();
|
||||
return AddInstance(AZStd::move(instance), newInstanceAlias);
|
||||
}
|
||||
|
||||
Instance& Instance::AddInstance(AZStd::unique_ptr<Instance> instance, InstanceAlias newInstanceAlias)
|
||||
{
|
||||
AZ_Assert(instance.get(), "instance argument is nullptr");
|
||||
AZ_Assert(m_nestedInstances.find(newInstanceAlias) == m_nestedInstances.end(), "InstanceAlias' unique id collision, this should never happen.");
|
||||
AZ_Assert(
|
||||
m_nestedInstances.find(newInstanceAlias) == m_nestedInstances.end(),
|
||||
"InstanceAlias' unique id collision, this should never happen.");
|
||||
instance->m_parent = this;
|
||||
instance->m_alias = newInstanceAlias;
|
||||
return *(m_nestedInstances[newInstanceAlias] = std::move(instance));
|
||||
|
||||
@@ -93,6 +93,7 @@ namespace AzToolsFramework
|
||||
void Reset();
|
||||
|
||||
Instance& AddInstance(AZStd::unique_ptr<Instance> instance);
|
||||
Instance& AddInstance(AZStd::unique_ptr<Instance> instance, InstanceAlias instanceAlias);
|
||||
AZStd::unique_ptr<Instance> DetachNestedInstance(const InstanceAlias& instanceAlias);
|
||||
|
||||
/**
|
||||
@@ -173,6 +174,8 @@ namespace AzToolsFramework
|
||||
static EntityAlias GenerateEntityAlias();
|
||||
AliasPath GetAbsoluteInstanceAliasPath() const;
|
||||
|
||||
static InstanceAlias GenerateInstanceAlias();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Gets the entities owned by this instance
|
||||
@@ -189,8 +192,6 @@ namespace AzToolsFramework
|
||||
bool RegisterEntity(const AZ::EntityId& entityId, const EntityAlias& entityAlias);
|
||||
AZStd::unique_ptr<AZ::Entity> DetachEntity(const EntityAlias& entityAlias);
|
||||
|
||||
static InstanceAlias GenerateInstanceAlias();
|
||||
|
||||
// Provide access to private data members in the serializer
|
||||
friend class JsonInstanceSerializer;
|
||||
friend class InstanceEntityIdMapper;
|
||||
|
||||
+24
@@ -152,6 +152,30 @@ namespace AzToolsFramework
|
||||
Instance::EntityList newEntities;
|
||||
if (PrefabDomUtils::LoadInstanceFromPrefabDom(*instanceToUpdate, newEntities, currentTemplate.GetPrefabDom()))
|
||||
{
|
||||
// If a link was created for a nested instance before the changes were propagated,
|
||||
// then we associate it correctly here
|
||||
instanceToUpdate->GetNestedInstances([&](AZStd::unique_ptr<Instance>& nestedInstance) {
|
||||
if (nestedInstance->GetLinkId() != InvalidLinkId)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto linkId : currentTemplate.GetLinks())
|
||||
{
|
||||
LinkReference nestedLink = m_prefabSystemComponentInterface->FindLink(linkId);
|
||||
if (!nestedLink.has_value())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (nestedLink->get().GetInstanceName() == nestedInstance->GetInstanceAlias())
|
||||
{
|
||||
nestedInstance->SetLinkId(linkId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
AzToolsFramework::EditorEntityContextRequestBus::Broadcast(
|
||||
&AzToolsFramework::EditorEntityContextRequests::HandleEntitiesAdded, newEntities);
|
||||
}
|
||||
|
||||
@@ -297,7 +297,7 @@ namespace AzToolsFramework
|
||||
m_instanceToTemplateInterface->AppendEntityAliasToPatchPaths(patch, containerEntityId);
|
||||
|
||||
// Update the cache - this prevents these changes from being stored in the regular undo/redo nodes
|
||||
m_prefabUndoCache.Store(containerEntityId, AZStd::move(containerEntityDomAfter));
|
||||
m_prefabUndoCache.Store(containerEntityId, AZStd::move(containerEntityDomAfter), parentEntityId);
|
||||
|
||||
return AZStd::move(patch);
|
||||
}
|
||||
@@ -595,54 +595,199 @@ namespace AzToolsFramework
|
||||
{
|
||||
// Create Undo node on entities if they belong to an instance
|
||||
InstanceOptionalReference owningInstance = m_instanceEntityMapperInterface->FindOwningInstance(entityId);
|
||||
|
||||
if (owningInstance.has_value())
|
||||
if (!owningInstance.has_value())
|
||||
{
|
||||
PrefabDom afterState;
|
||||
AZ::Entity* entity = GetEntityById(entityId);
|
||||
if (entity)
|
||||
return;
|
||||
}
|
||||
|
||||
AZ::Entity* entity = GetEntityById(entityId);
|
||||
if (!entity)
|
||||
{
|
||||
m_prefabUndoCache.PurgeCache(entityId);
|
||||
return;
|
||||
}
|
||||
|
||||
PrefabDom beforeState;
|
||||
AZ::EntityId beforeParentId;
|
||||
m_prefabUndoCache.Retrieve(entityId, beforeState, beforeParentId);
|
||||
|
||||
PrefabDom afterState;
|
||||
AZ::EntityId afterParentId;
|
||||
AZ::TransformBus::EventResult(afterParentId, entityId, &AZ::TransformBus::Events::GetParentId);
|
||||
|
||||
m_instanceToTemplateInterface->GenerateDomForEntity(afterState, *entity);
|
||||
|
||||
PrefabDom patch;
|
||||
m_instanceToTemplateInterface->GeneratePatch(patch, beforeState, afterState);
|
||||
m_instanceToTemplateInterface->AppendEntityAliasToPatchPaths(patch, entityId);
|
||||
|
||||
if (patch.IsArray() && !patch.Empty() && beforeState.IsObject())
|
||||
{
|
||||
bool isInstanceContainerEntity = IsInstanceContainerEntity(entityId) && !IsLevelInstanceContainerEntity(entityId);
|
||||
bool isNewParentOwnedByDifferentInstance = false;
|
||||
|
||||
if (beforeParentId != afterParentId)
|
||||
{
|
||||
PrefabDom beforeState;
|
||||
m_prefabUndoCache.Retrieve(entityId, beforeState);
|
||||
// If the entity parent changed, verify if the owning instance changed too
|
||||
InstanceOptionalReference beforeOwningInstance = m_instanceEntityMapperInterface->FindOwningInstance(beforeParentId);
|
||||
InstanceOptionalReference afterOwningInstance = m_instanceEntityMapperInterface->FindOwningInstance(afterParentId);
|
||||
|
||||
m_instanceToTemplateInterface->GenerateDomForEntity(afterState, *entity);
|
||||
|
||||
PrefabDom patch;
|
||||
m_instanceToTemplateInterface->GeneratePatch(patch, beforeState, afterState);
|
||||
|
||||
if (patch.IsArray() && !patch.Empty() && beforeState.IsObject())
|
||||
if (beforeOwningInstance.has_value() && afterOwningInstance.has_value() &&
|
||||
(&beforeOwningInstance->get() != &afterOwningInstance->get()))
|
||||
{
|
||||
if (IsInstanceContainerEntity(entityId) && !IsLevelInstanceContainerEntity(entityId))
|
||||
{
|
||||
m_instanceToTemplateInterface->AppendEntityAliasToPatchPaths(patch, entityId);
|
||||
|
||||
// Save these changes as patches to the link
|
||||
PrefabUndoLinkUpdate* linkUpdate =
|
||||
aznew PrefabUndoLinkUpdate(AZStd::to_string(static_cast<AZ::u64>(entityId)));
|
||||
linkUpdate->SetParent(parentUndoBatch);
|
||||
linkUpdate->Capture(patch, owningInstance->get().GetLinkId());
|
||||
|
||||
linkUpdate->Redo();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Update the state of the entity
|
||||
PrefabUndoEntityUpdate* state = aznew PrefabUndoEntityUpdate(AZStd::to_string(static_cast<AZ::u64>(entityId)));
|
||||
state->SetParent(parentUndoBatch);
|
||||
state->Capture(beforeState, afterState, entityId);
|
||||
|
||||
state->Redo();
|
||||
}
|
||||
isNewParentOwnedByDifferentInstance = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Update the cache
|
||||
m_prefabUndoCache.Store(entityId, AZStd::move(afterState));
|
||||
if (isInstanceContainerEntity)
|
||||
{
|
||||
if (isNewParentOwnedByDifferentInstance)
|
||||
{
|
||||
Internal_HandleInstanceChange(parentUndoBatch, entity, beforeParentId, afterParentId);
|
||||
|
||||
PrefabDom afterStateafterReparenting;
|
||||
m_instanceToTemplateInterface->GenerateDomForEntity(afterStateafterReparenting, *entity);
|
||||
|
||||
PrefabDom newPatch;
|
||||
m_instanceToTemplateInterface->GeneratePatch(newPatch, afterState, afterStateafterReparenting);
|
||||
m_instanceToTemplateInterface->AppendEntityAliasToPatchPaths(newPatch, entityId);
|
||||
|
||||
InstanceOptionalReference owningInstanceAfterReparenting =
|
||||
m_instanceEntityMapperInterface->FindOwningInstance(entityId);
|
||||
|
||||
Internal_HandleContainerOverride(
|
||||
parentUndoBatch, entityId, newPatch, owningInstanceAfterReparenting->get().GetLinkId());
|
||||
}
|
||||
else
|
||||
{
|
||||
Internal_HandleContainerOverride(
|
||||
parentUndoBatch, entityId, patch, owningInstance->get().GetLinkId());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_prefabUndoCache.PurgeCache(entityId);
|
||||
Internal_HandleEntityChange(parentUndoBatch, entityId, beforeState, afterState);
|
||||
|
||||
if (isNewParentOwnedByDifferentInstance)
|
||||
{
|
||||
Internal_HandleInstanceChange(parentUndoBatch, entity, beforeParentId, afterParentId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_prefabUndoCache.UpdateCache(entityId);
|
||||
}
|
||||
|
||||
void PrefabPublicHandler::Internal_HandleContainerOverride(
|
||||
UndoSystem::URSequencePoint* undoBatch, AZ::EntityId entityId, const PrefabDom& patch, const LinkId linkId)
|
||||
{
|
||||
// Save these changes as patches to the link
|
||||
PrefabUndoLinkUpdate* linkUpdate = aznew PrefabUndoLinkUpdate(AZStd::to_string(static_cast<AZ::u64>(entityId)));
|
||||
linkUpdate->SetParent(undoBatch);
|
||||
linkUpdate->Capture(patch, linkId);
|
||||
|
||||
linkUpdate->Redo();
|
||||
}
|
||||
|
||||
void PrefabPublicHandler::Internal_HandleEntityChange(
|
||||
UndoSystem::URSequencePoint* undoBatch, AZ::EntityId entityId, PrefabDom& beforeState, PrefabDom& afterState)
|
||||
{
|
||||
// Update the state of the entity
|
||||
PrefabUndoEntityUpdate* state = aznew PrefabUndoEntityUpdate(AZStd::to_string(static_cast<AZ::u64>(entityId)));
|
||||
state->SetParent(undoBatch);
|
||||
state->Capture(beforeState, afterState, entityId);
|
||||
|
||||
state->Redo();
|
||||
}
|
||||
|
||||
void PrefabPublicHandler::Internal_HandleInstanceChange(
|
||||
UndoSystem::URSequencePoint* undoBatch, AZ::Entity* entity, AZ::EntityId beforeParentId, AZ::EntityId afterParentId)
|
||||
{
|
||||
// If the entity parent changed, verify if the owning instance changed too
|
||||
InstanceOptionalReference beforeOwningInstance = m_instanceEntityMapperInterface->FindOwningInstance(beforeParentId);
|
||||
InstanceOptionalReference afterOwningInstance = m_instanceEntityMapperInterface->FindOwningInstance(afterParentId);
|
||||
|
||||
EntityList entities;
|
||||
AZStd::vector<Instance*> instances;
|
||||
|
||||
// Retrieve all descendant entities and instances of this entity that belonged to the same owning instance.
|
||||
RetrieveAndSortPrefabEntitiesAndInstances({ entity }, beforeOwningInstance->get(), entities, instances);
|
||||
|
||||
AZStd::vector<AZStd::unique_ptr<Instance>> instanceUniquePtrs;
|
||||
AZStd::vector<AZStd::pair<Instance*, PrefabDom>> instancePatches;
|
||||
|
||||
// Remove Entities and Instances from the prior instance
|
||||
{
|
||||
// Remove Instances
|
||||
for (Instance* nestedInstance : instances)
|
||||
{
|
||||
auto linkRef = m_prefabSystemComponentInterface->FindLink(nestedInstance->GetLinkId());
|
||||
|
||||
PrefabDom oldLinkPatches;
|
||||
|
||||
if (linkRef.has_value())
|
||||
{
|
||||
auto patches = linkRef->get().GetLinkPatches();
|
||||
if (patches.has_value())
|
||||
{
|
||||
oldLinkPatches.CopyFrom(patches->get(), oldLinkPatches.GetAllocator());
|
||||
}
|
||||
}
|
||||
|
||||
auto nestedInstanceUniquePtr = beforeOwningInstance->get().DetachNestedInstance(nestedInstance->GetInstanceAlias());
|
||||
RemoveLink(nestedInstanceUniquePtr, beforeOwningInstance->get().GetTemplateId(), undoBatch);
|
||||
|
||||
instancePatches.emplace_back(AZStd::make_pair(nestedInstanceUniquePtr.get(), AZStd::move(oldLinkPatches)));
|
||||
instanceUniquePtrs.emplace_back(AZStd::move(nestedInstanceUniquePtr));
|
||||
}
|
||||
|
||||
// Get the previous state of the prior instance for undo/redo purposes
|
||||
PrefabDom beforeInstanceDomBeforeRemoval;
|
||||
m_instanceToTemplateInterface->GenerateDomForInstance(beforeInstanceDomBeforeRemoval, beforeOwningInstance->get());
|
||||
|
||||
// Remove Entities
|
||||
for (AZ::Entity* nestedEntity : entities)
|
||||
{
|
||||
beforeOwningInstance->get().DetachEntity(nestedEntity->GetId()).release();
|
||||
}
|
||||
|
||||
// Create the Update node for the prior owning instance
|
||||
// Instance removal will be taken care of from the RemoveLink function for undo/redo purposes
|
||||
PrefabUndoHelpers::UpdatePrefabInstance(
|
||||
beforeOwningInstance->get(), "Update prior prefab instance", beforeInstanceDomBeforeRemoval, undoBatch);
|
||||
}
|
||||
|
||||
// Add Entities and Instances to new instance
|
||||
{
|
||||
// Add Instances
|
||||
for (auto& instanceUniquePtr : instanceUniquePtrs)
|
||||
{
|
||||
afterOwningInstance->get().AddInstance(AZStd::move(instanceUniquePtr));
|
||||
}
|
||||
|
||||
// Create Links
|
||||
for (auto& instanceInfo : instancePatches)
|
||||
{
|
||||
// Add a new link with the old dom
|
||||
CreateLink(
|
||||
*instanceInfo.first, afterOwningInstance->get().GetTemplateId(), undoBatch,
|
||||
AZStd::move(instanceInfo.second));
|
||||
}
|
||||
|
||||
// Get the previous state of the new instance for undo/redo purposes
|
||||
PrefabDom afterInstanceDomBeforeAdd;
|
||||
m_instanceToTemplateInterface->GenerateDomForInstance(afterInstanceDomBeforeAdd, afterOwningInstance->get());
|
||||
|
||||
// Add Entities
|
||||
for (AZ::Entity* nestedEntity : entities)
|
||||
{
|
||||
afterOwningInstance->get().AddEntity(*nestedEntity);
|
||||
}
|
||||
|
||||
// Create the Update node for the new owning instance
|
||||
PrefabUndoHelpers::UpdatePrefabInstance(
|
||||
afterOwningInstance->get(), "Update new prefab instance", afterInstanceDomBeforeAdd, undoBatch);
|
||||
}
|
||||
}
|
||||
|
||||
bool PrefabPublicHandler::IsInstanceContainerEntity(AZ::EntityId entityId) const
|
||||
@@ -754,16 +899,29 @@ namespace AzToolsFramework
|
||||
|
||||
if (!EntitiesBelongToSameInstance(entityIds))
|
||||
{
|
||||
return AZ::Failure(AZStd::string("Cannot duplicate multiple "
|
||||
"entities belonging to different instances with one operation."));
|
||||
return AZ::Failure(AZStd::string("Cannot duplicate multiple entities belonging to different instances with one operation."
|
||||
"Change your selection to contain entities in the same instance."));
|
||||
}
|
||||
|
||||
// We've already verified the entities are all owned by the same instance,
|
||||
// so we can just retrieve our instance from the first entity in the list.
|
||||
InstanceOptionalReference commonEntityOwningInstance = GetOwnerInstanceByEntityId(entityIds[0]);
|
||||
AZ_Assert(
|
||||
commonEntityOwningInstance.has_value(),
|
||||
"Failed to duplicate : Couldn't get a valid owning instance for the common root entity of the entities provided");
|
||||
AZ::EntityId firstEntityIdToDuplicate = entityIds[0];
|
||||
InstanceOptionalReference commonOwningInstance = GetOwnerInstanceByEntityId(firstEntityIdToDuplicate);
|
||||
if (!commonOwningInstance.has_value())
|
||||
{
|
||||
return AZ::Failure(AZStd::string("Failed to duplicate : Couldn't get a valid owning instance for the common root entity of the entities provided."));
|
||||
}
|
||||
|
||||
// If the first entity id is a container entity id, then we need to mark its parent as the common owning instance because you
|
||||
// cannot duplicate an instance from itself.
|
||||
if (commonOwningInstance->get().GetContainerEntityId() == firstEntityIdToDuplicate)
|
||||
{
|
||||
commonOwningInstance = commonOwningInstance->get().GetParentInstance();
|
||||
}
|
||||
if (!commonOwningInstance.has_value())
|
||||
{
|
||||
return AZ::Failure(AZStd::string("Failed to duplicate : Couldn't get a valid owning instance for the common root entity of the entities provided."));
|
||||
}
|
||||
|
||||
// This will cull out any entities that have ancestors in the list, since we will end up duplicating
|
||||
// the full nested hierarchy with what is returned from RetrieveAndSortPrefabEntitiesAndInstances
|
||||
@@ -776,105 +934,63 @@ namespace AzToolsFramework
|
||||
{
|
||||
AZ_PROFILE_SCOPE(AZ::Debug::ProfileCategory::AzToolsFramework, "DuplicateEntitiesInInstance::UndoCaptureAndDuplicateEntities");
|
||||
|
||||
// Take a snapshot of the instance DOM before we manipulate it
|
||||
Prefab::PrefabDom instanceDomBefore;
|
||||
m_instanceToTemplateInterface->GenerateDomForInstance(instanceDomBefore, commonEntityOwningInstance->get());
|
||||
|
||||
AZStd::vector<AZ::Entity*> entities;
|
||||
AZStd::vector<Instance*> instances;
|
||||
|
||||
// Gather all entities/instances in the hierarchy, but don't detach them because we are duplicating not deleting.
|
||||
EntityList inputEntityList = EntityIdSetToEntityList(duplicationSet);
|
||||
bool success = RetrieveAndSortPrefabEntitiesAndInstances(inputEntityList, commonEntityOwningInstance->get(), entities, instances);
|
||||
bool success = RetrieveAndSortPrefabEntitiesAndInstances(inputEntityList, commonOwningInstance->get(), entities, instances);
|
||||
|
||||
if (!success)
|
||||
{
|
||||
return AZ::Failure(AZStd::string("Failed to retrieve entities and instances from the given list of entity ids for duplication"));
|
||||
}
|
||||
|
||||
// Make a copy of our before instance DOM where we will add our duplicated entities
|
||||
Prefab::PrefabDom instanceDomAfter;
|
||||
// Take a snapshot of the instance DOM before we manipulate it
|
||||
PrefabDom instanceDomBefore;
|
||||
m_instanceToTemplateInterface->GenerateDomForInstance(instanceDomBefore, commonOwningInstance->get());
|
||||
|
||||
// Make a copy of our before instance DOM where we will add our duplicated entities and/or instances
|
||||
PrefabDom instanceDomAfter;
|
||||
instanceDomAfter.CopyFrom(instanceDomBefore, instanceDomAfter.GetAllocator());
|
||||
|
||||
AZStd::unordered_map<EntityAlias, EntityAlias> oldAliasToNewAliasMap;
|
||||
AZStd::unordered_map<EntityAlias, QString> aliasToEntityDomMap;
|
||||
EntityIdList duplicatedEntityAndInstanceIds;
|
||||
|
||||
for (AZ::Entity* entity : entities)
|
||||
{
|
||||
EntityAliasOptionalReference oldAliasRef = commonEntityOwningInstance->get().GetEntityAlias(entity->GetId());
|
||||
AZ_Assert(oldAliasRef.has_value(), "No alias found for Entity in the DOM");
|
||||
EntityAlias oldAlias = oldAliasRef.value();
|
||||
// Duplicate any nested entities and instances as requested
|
||||
AZStd::unordered_map<InstanceAlias, Instance*> newInstanceAliasToOldInstanceMap;
|
||||
DuplicateNestedEntitiesInInstance(commonOwningInstance->get(),
|
||||
entities, instanceDomAfter, duplicatedEntityAndInstanceIds);
|
||||
DuplicateNestedInstancesInInstance(commonOwningInstance->get(),
|
||||
instances, instanceDomAfter, duplicatedEntityAndInstanceIds,
|
||||
newInstanceAliasToOldInstanceMap);
|
||||
|
||||
// Give this the outer allocator so that the memory reference will be valid when
|
||||
// it gets used for AddMember
|
||||
Prefab::PrefabDom entityDomBefore(&instanceDomAfter.GetAllocator());
|
||||
m_instanceToTemplateInterface->GenerateDomForEntity(entityDomBefore, *entity);
|
||||
|
||||
// Keep track of the old alias <-> new alias mapping for this duplicated entity
|
||||
// so we can fixup references later
|
||||
EntityAlias newEntityAlias = Instance::GenerateEntityAlias();
|
||||
oldAliasToNewAliasMap.insert(AZStd::make_pair(oldAlias, newEntityAlias));
|
||||
|
||||
rapidjson::StringBuffer buffer;
|
||||
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
|
||||
entityDomBefore.Accept(writer);
|
||||
|
||||
// Store our duplicated Entity DOM with its new alias as a string
|
||||
// so that we can fixup entity alias references before adding it
|
||||
// to the Entities member of our instance DOM
|
||||
QString entityDomString(buffer.GetString());
|
||||
aliasToEntityDomMap.insert(AZStd::make_pair(newEntityAlias, entityDomString));
|
||||
}
|
||||
|
||||
auto entitiesIter = instanceDomAfter.FindMember(PrefabDomUtils::EntitiesName);
|
||||
AZ_Assert(entitiesIter != instanceDomAfter.MemberEnd(), "Instance DOM missing the Entities member.");
|
||||
|
||||
// Now that all the duplicated Entity DOMs have been created, we need to iterate
|
||||
// through them and replace any previous EntityAlias references with the new ones.
|
||||
// These are more than just parent entity references for nested entities, this will
|
||||
// also cover any EntityId references that were made in the components between them.
|
||||
for (auto aliasEntityPair : aliasToEntityDomMap)
|
||||
{
|
||||
EntityAlias newEntityAlias = aliasEntityPair.first;
|
||||
QString newEntityDomString = aliasEntityPair.second;
|
||||
|
||||
// Replace all of the old alias references with the new ones
|
||||
// We bookend the aliases with \" and also with a / as an extra precaution to prevent
|
||||
// inadvertently replacing a matching string vs. where an actual EntityId is expected
|
||||
// This will cover both cases where an alias could be used in a normal entity vs. an instance
|
||||
for (auto aliasMapIter : oldAliasToNewAliasMap)
|
||||
{
|
||||
ReplaceOldAliases(newEntityDomString, aliasMapIter.first, aliasMapIter.second);
|
||||
}
|
||||
|
||||
// Create the new Entity DOM from parsing the JSON string
|
||||
Prefab::PrefabDom entityDomAfter(&instanceDomAfter.GetAllocator());
|
||||
entityDomAfter.Parse(newEntityDomString.toUtf8().constData());
|
||||
|
||||
// Add the new Entity DOM to the Entities member of the instance
|
||||
rapidjson::Value aliasName(newEntityAlias.c_str(), newEntityAlias.length(), instanceDomAfter.GetAllocator());
|
||||
entitiesIter->value.AddMember(AZStd::move(aliasName), entityDomAfter, instanceDomAfter.GetAllocator());
|
||||
}
|
||||
|
||||
PrefabUndoInstance* command = aznew PrefabUndoInstance("Entity duplication");
|
||||
PrefabUndoInstance* command = aznew PrefabUndoInstance("Entity/Instance duplication");
|
||||
command->SetParent(undoBatch.GetUndoBatch());
|
||||
command->Capture(instanceDomBefore, instanceDomAfter, commonEntityOwningInstance->get().GetTemplateId());
|
||||
command->RunRedo();
|
||||
command->Capture(instanceDomBefore, instanceDomAfter, commonOwningInstance->get().GetTemplateId());
|
||||
command->Redo();
|
||||
|
||||
EntityIdList duplicatedEntityIds;
|
||||
for (auto aliasMapIter : oldAliasToNewAliasMap)
|
||||
// Create links for our duplicated instances (if any were duplicated)
|
||||
for (auto [newInstanceAlias, oldInstance] : newInstanceAliasToOldInstanceMap)
|
||||
{
|
||||
EntityAlias newEntityAlias = aliasMapIter.second;
|
||||
LinkId oldLinkId = oldInstance->GetLinkId();
|
||||
auto linkRef = m_prefabSystemComponentInterface->FindLink(oldLinkId);
|
||||
AZ_Assert(
|
||||
linkRef.has_value(), "Unable to find link with id '%llu' during instance duplication.",
|
||||
oldLinkId);
|
||||
|
||||
AliasPath absoluteEntityPath = commonEntityOwningInstance->get().GetAbsoluteInstanceAliasPath();
|
||||
absoluteEntityPath.Append(newEntityAlias);
|
||||
PrefabDomValueReference linkPatches = linkRef->get().GetLinkPatches();
|
||||
AZ_Assert(
|
||||
linkPatches.has_value(), "Link with id '%llu' is missing patches.",
|
||||
oldLinkId);
|
||||
|
||||
AZ::EntityId newEntityId = InstanceEntityIdMapper::GenerateEntityIdForAliasPath(absoluteEntityPath);
|
||||
duplicatedEntityIds.push_back(newEntityId);
|
||||
PrefabDom linkPatchesCopy;
|
||||
linkPatchesCopy.CopyFrom(linkPatches->get(), linkPatchesCopy.GetAllocator());
|
||||
|
||||
m_prefabSystemComponentInterface->CreateLink(
|
||||
commonOwningInstance->get().GetTemplateId(), oldInstance->GetTemplateId(), newInstanceAlias, linkPatchesCopy);
|
||||
}
|
||||
|
||||
// Select the duplicated entities
|
||||
auto selectionUndo = aznew SelectionCommand(duplicatedEntityIds, "Select Duplicated Entities");
|
||||
// Select the duplicated entities/instances
|
||||
auto selectionUndo = aznew SelectionCommand(duplicatedEntityAndInstanceIds, "Select Duplicated Entities/Instances");
|
||||
selectionUndo->SetParent(undoBatch.GetUndoBatch());
|
||||
ToolsApplicationRequestBus::Broadcast(&ToolsApplicationRequestBus::Events::RunRedoSeparately, selectionUndo);
|
||||
}
|
||||
@@ -1363,8 +1479,159 @@ namespace AzToolsFramework
|
||||
return true;
|
||||
}
|
||||
|
||||
void PrefabPublicHandler::DuplicateNestedEntitiesInInstance(Instance& commonOwningInstance,
|
||||
const AZStd::vector<AZ::Entity*>& entities, PrefabDom& domToAddDuplicatedEntitiesUnder,
|
||||
EntityIdList& duplicatedEntityIds)
|
||||
{
|
||||
if (entities.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AZStd::unordered_map<EntityAlias, EntityAlias> oldAliasToNewAliasMap;
|
||||
AZStd::unordered_map<EntityAlias, QString> aliasToEntityDomMap;
|
||||
|
||||
for (AZ::Entity* entity : entities)
|
||||
{
|
||||
EntityAliasOptionalReference oldAliasRef = commonOwningInstance.GetEntityAlias(entity->GetId());
|
||||
AZ_Assert(oldAliasRef.has_value(), "No alias found for Entity in the DOM");
|
||||
EntityAlias oldAlias = oldAliasRef.value();
|
||||
|
||||
// Give this the outer allocator so that the memory reference will be valid when
|
||||
// it gets used for AddMember
|
||||
PrefabDom entityDomBefore(&domToAddDuplicatedEntitiesUnder.GetAllocator());
|
||||
m_instanceToTemplateInterface->GenerateDomForEntity(entityDomBefore, *entity);
|
||||
|
||||
// Keep track of the old alias <-> new alias mapping for this duplicated entity
|
||||
// so we can fixup references later
|
||||
EntityAlias newEntityAlias = Instance::GenerateEntityAlias();
|
||||
oldAliasToNewAliasMap.emplace(oldAlias, newEntityAlias);
|
||||
|
||||
rapidjson::StringBuffer buffer;
|
||||
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
|
||||
entityDomBefore.Accept(writer);
|
||||
|
||||
// Store our duplicated Entity DOM with its new alias as a string
|
||||
// so that we can fixup entity alias references before adding it
|
||||
// to the Entities member of our instance DOM
|
||||
QString entityDomString(buffer.GetString());
|
||||
aliasToEntityDomMap.emplace(newEntityAlias, entityDomString);
|
||||
}
|
||||
|
||||
auto entitiesIter = domToAddDuplicatedEntitiesUnder.FindMember(PrefabDomUtils::EntitiesName);
|
||||
AZ_Assert(entitiesIter != domToAddDuplicatedEntitiesUnder.MemberEnd(), "Instance DOM missing the Entities member.");
|
||||
|
||||
// Now that all the duplicated Entity DOMs have been created, we need to iterate
|
||||
// through them and replace any previous EntityAlias references with the new ones.
|
||||
// These are more than just parent entity references for nested entities, this will
|
||||
// also cover any EntityId references that were made in the components between them.
|
||||
for (auto [newEntityAlias, newEntityDomString] : aliasToEntityDomMap)
|
||||
{
|
||||
// Replace all of the old alias references with the new ones
|
||||
for (auto [oldAlias, newAlias] : oldAliasToNewAliasMap)
|
||||
{
|
||||
ReplaceOldAliases(newEntityDomString, oldAlias, newAlias);
|
||||
}
|
||||
|
||||
// Create the new Entity DOM from parsing the JSON string
|
||||
PrefabDom entityDomAfter(&domToAddDuplicatedEntitiesUnder.GetAllocator());
|
||||
entityDomAfter.Parse(newEntityDomString.toUtf8().constData());
|
||||
|
||||
// Add the new Entity DOM to the Entities member of the instance
|
||||
rapidjson::Value aliasName(newEntityAlias.c_str(), newEntityAlias.length(), domToAddDuplicatedEntitiesUnder.GetAllocator());
|
||||
entitiesIter->value.AddMember(AZStd::move(aliasName), entityDomAfter, domToAddDuplicatedEntitiesUnder.GetAllocator());
|
||||
}
|
||||
|
||||
for (auto aliasMapIter : oldAliasToNewAliasMap)
|
||||
{
|
||||
EntityAlias newEntityAlias = aliasMapIter.second;
|
||||
|
||||
AliasPath absoluteEntityPath = commonOwningInstance.GetAbsoluteInstanceAliasPath();
|
||||
absoluteEntityPath.Append(newEntityAlias);
|
||||
|
||||
AZ::EntityId newEntityId = InstanceEntityIdMapper::GenerateEntityIdForAliasPath(absoluteEntityPath);
|
||||
duplicatedEntityIds.push_back(newEntityId);
|
||||
}
|
||||
}
|
||||
|
||||
void PrefabPublicHandler::DuplicateNestedInstancesInInstance(Instance& commonOwningInstance,
|
||||
const AZStd::vector<Instance*>& instances, PrefabDom& domToAddDuplicatedInstancesUnder,
|
||||
EntityIdList& duplicatedEntityIds, AZStd::unordered_map<InstanceAlias, Instance*>& newInstanceAliasToOldInstanceMap)
|
||||
{
|
||||
if (instances.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AZStd::unordered_map<InstanceAlias, InstanceAlias> oldInstanceAliasToNewInstanceAliasMap;
|
||||
AZStd::unordered_map<InstanceAlias, QString> aliasToInstanceDomMap;
|
||||
|
||||
for (auto instance : instances)
|
||||
{
|
||||
PrefabDom nestedInstanceDomBefore;
|
||||
m_instanceToTemplateInterface->GenerateDomForInstance(nestedInstanceDomBefore, *instance);
|
||||
|
||||
// Keep track of the old alias <-> new alias mapping for this duplicated instance
|
||||
// so we can fixup references later
|
||||
InstanceAlias oldAlias = instance->GetInstanceAlias();
|
||||
InstanceAlias newInstanceAlias = Instance::GenerateInstanceAlias();
|
||||
oldInstanceAliasToNewInstanceAliasMap.emplace(oldAlias, newInstanceAlias);
|
||||
|
||||
// Keep track of our new instance alias with the Instance it was duplicated from,
|
||||
// so that after all instances are duplicated, we can go back and create links for them
|
||||
newInstanceAliasToOldInstanceMap.emplace(newInstanceAlias, instance);
|
||||
|
||||
rapidjson::StringBuffer buffer;
|
||||
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
|
||||
nestedInstanceDomBefore.Accept(writer);
|
||||
|
||||
// Store our duplicated Instance DOM with its new alias as a string
|
||||
// so that we can fixup instance alias references before adding it
|
||||
// to the Instances member of our instance DOM
|
||||
QString instanceDomString(buffer.GetString());
|
||||
aliasToInstanceDomMap.emplace(newInstanceAlias, instanceDomString);
|
||||
}
|
||||
|
||||
auto instancesIter = domToAddDuplicatedInstancesUnder.FindMember(PrefabDomUtils::InstancesName);
|
||||
AZ_Assert(instancesIter != domToAddDuplicatedInstancesUnder.MemberEnd(), "Instance DOM missing the Instances member.");
|
||||
|
||||
// Now that all the duplicated Instance DOMs have been created, we need to iterate
|
||||
// through them and replace any previous InstanceAlias references with the new ones.
|
||||
for (auto [newInstanceAlias, newInstanceDomString]: aliasToInstanceDomMap)
|
||||
{
|
||||
// Replace all of the old alias references with the new ones
|
||||
for (auto [oldAlias, newAlias] : oldInstanceAliasToNewInstanceAliasMap)
|
||||
{
|
||||
ReplaceOldAliases(newInstanceDomString, oldAlias, newAlias);
|
||||
}
|
||||
|
||||
// Create the new Instance DOM from parsing the JSON string
|
||||
PrefabDom nestedInstanceDomAfter(&domToAddDuplicatedInstancesUnder.GetAllocator());
|
||||
nestedInstanceDomAfter.Parse(newInstanceDomString.toUtf8().constData());
|
||||
|
||||
// Add the new Instance DOM to the Instances member of the instance
|
||||
rapidjson::Value aliasName(newInstanceAlias.c_str(), newInstanceAlias.length(), domToAddDuplicatedInstancesUnder.GetAllocator());
|
||||
instancesIter->value.AddMember(AZStd::move(aliasName), nestedInstanceDomAfter, domToAddDuplicatedInstancesUnder.GetAllocator());
|
||||
}
|
||||
|
||||
for (auto aliasMapIter : oldInstanceAliasToNewInstanceAliasMap)
|
||||
{
|
||||
InstanceAlias newInstanceAlias = aliasMapIter.second;
|
||||
|
||||
AliasPath absoluteInstancePath = commonOwningInstance.GetAbsoluteInstanceAliasPath();
|
||||
absoluteInstancePath.Append(newInstanceAlias);
|
||||
|
||||
AZ::EntityId newEntityId = InstanceEntityIdMapper::GenerateEntityIdForAliasPath(absoluteInstancePath);
|
||||
duplicatedEntityIds.push_back(newEntityId);
|
||||
}
|
||||
}
|
||||
|
||||
void PrefabPublicHandler::ReplaceOldAliases(QString& stringToReplace, AZStd::string_view oldAlias, AZStd::string_view newAlias)
|
||||
{
|
||||
// Replace all of the old alias references with the new ones
|
||||
// We bookend the aliases with \" and also with a / as an extra precaution to prevent
|
||||
// inadvertently replacing a matching string vs. where an actual EntityId is expected
|
||||
// This will cover both cases where an alias could be used in a normal entity vs. an instance
|
||||
QString oldAliasQuotes = QString("\"%1\"").arg(oldAlias.data());
|
||||
QString newAliasQuotes = QString("\"%1\"").arg(newAlias.data());
|
||||
|
||||
|
||||
@@ -73,6 +73,33 @@ namespace AzToolsFramework
|
||||
|
||||
InstanceOptionalReference GetOwnerInstanceByEntityId(AZ::EntityId entityId) const;
|
||||
bool EntitiesBelongToSameInstance(const EntityIdList& entityIds) const;
|
||||
|
||||
/**
|
||||
* Duplicate a list of entities owned by a common owning instance by directly
|
||||
* copying/modifying their entries in the instance DOM
|
||||
*
|
||||
* \param commonOwningInstance The common owning instance of all the entities being duplicated.
|
||||
* \param entities The list of Entities that will be duplicated.
|
||||
* \param domToAddDuplicatedEntitiesUnder The DOM of the common owning instance where the duplicated
|
||||
* entity DOM values will be added to.
|
||||
* \param duplicatedEntityIds A list of EntityIds corresponding to the entities that were duplicated.
|
||||
*/
|
||||
void DuplicateNestedEntitiesInInstance(Instance& commonOwningInstance,
|
||||
const AZStd::vector<AZ::Entity*>& entities, PrefabDom& domToAddDuplicatedEntitiesUnder,
|
||||
EntityIdList& duplicatedEntityIds);
|
||||
/**
|
||||
* Duplicate a list of instances owned by a common owning instance by directly
|
||||
* copying/modifying their entries in the instance DOM
|
||||
*
|
||||
* \param commonOwningInstance The common owning instance of all the instances being duplicated.
|
||||
* \param entities The list of Instances that will be duplicated.
|
||||
* \param domToAddDuplicatedInstancesUnder The DOM of the common owning instance where the duplicated
|
||||
* instance DOM values will be added to.
|
||||
* \param duplicatedEntityIds A list of EntityIds corresponding to the instances that were duplicated.
|
||||
*/
|
||||
void DuplicateNestedInstancesInInstance(Instance& commonOwningInstance,
|
||||
const AZStd::vector<Instance*>& instances, PrefabDom& domToAddDuplicatedInstancesUnder,
|
||||
EntityIdList& duplicatedEntityIds, AZStd::unordered_map<InstanceAlias, Instance*>& newInstanceAliasToOldInstanceMap);
|
||||
|
||||
/**
|
||||
* Applies the correct transform changes to the container entity based on the parent and child entities provided, and returns an appropriate patch.
|
||||
@@ -90,8 +117,8 @@ namespace AzToolsFramework
|
||||
/**
|
||||
* Creates a link between the templates of an instance and its parent.
|
||||
*
|
||||
* \param sourceInstance The instance that corresponds to the source template of the link.
|
||||
* \param targetInstance The id of the target template.
|
||||
* \param sourceInstance The instance that corresponds to the source template of the link (child).
|
||||
* \param targetInstance The id of the target template (parent).
|
||||
* \param undoBatch The undo batch to set as parent for this create link action.
|
||||
* \param patch The patch to store in the newly created link dom.
|
||||
* \param isUndoRedoSupportNeeded The flag indicating whether the link should be created with undo/redo support or not.
|
||||
@@ -134,6 +161,12 @@ namespace AzToolsFramework
|
||||
bool IsCyclicalDependencyFound(
|
||||
InstanceOptionalConstReference instance, const AZStd::unordered_set<AZ::IO::Path>& templateSourcePaths);
|
||||
|
||||
static void Internal_HandleContainerOverride(
|
||||
UndoSystem::URSequencePoint* undoBatch, AZ::EntityId entityId, const PrefabDom& patch, const LinkId linkId);
|
||||
static void Internal_HandleEntityChange(
|
||||
UndoSystem::URSequencePoint* undoBatch, AZ::EntityId entityId, PrefabDom& beforeState, PrefabDom& afterState);
|
||||
void Internal_HandleInstanceChange(UndoSystem::URSequencePoint* undoBatch, AZ::Entity* entity, AZ::EntityId beforeParentId, AZ::EntityId afterParentId);
|
||||
|
||||
void UpdateLinkPatchesWithNewEntityAliases(
|
||||
PrefabDom& linkPatch,
|
||||
const AZStd::unordered_map<AZ::EntityId, AZStd::string>& oldEntityAliases,
|
||||
|
||||
@@ -706,14 +706,14 @@ namespace AzToolsFramework
|
||||
"Prefab - PrefabSystemComponent::RemoveLink - "
|
||||
"Failed to remove Link with Id '%llu' for Instance '%s' of source Template with Id '%llu' "
|
||||
"from TemplateToLinkIdsMap.",
|
||||
linkId, link.GetSourceTemplateId(), link.GetInstanceName().c_str());
|
||||
linkId, link.GetInstanceName().c_str(), link.GetSourceTemplateId());
|
||||
|
||||
result = RemoveLinkFromTargetTemplate(linkId, link);
|
||||
AZ_Assert(result,
|
||||
"Prefab - PrefabSystemComponent::RemoveLink - "
|
||||
"Failed to remove Link with Id '%llu' for Instance '%s' of source Template with Id '%llu' "
|
||||
"from target Template with Id '%llu'.",
|
||||
linkId, link.GetSourceTemplateId(), link.GetInstanceName().c_str(), link.GetTargetTemplateId());
|
||||
linkId, link.GetInstanceName().c_str(), link.GetSourceTemplateId(), link.GetTargetTemplateId());
|
||||
|
||||
m_linkIdMap.erase(linkId);
|
||||
|
||||
|
||||
@@ -73,14 +73,16 @@ namespace AzToolsFramework
|
||||
}
|
||||
|
||||
PrefabDom oldData;
|
||||
Retrieve(entityId, oldData);
|
||||
AZ::EntityId oldParentId;
|
||||
Retrieve(entityId, oldData, oldParentId);
|
||||
|
||||
UpdateCache(entityId);
|
||||
|
||||
PrefabDom newData;
|
||||
Retrieve(entityId, newData);
|
||||
AZ::EntityId newParentId;
|
||||
Retrieve(entityId, newData, newParentId);
|
||||
|
||||
if (newData != oldData)
|
||||
if (newData != oldData || oldParentId != newParentId)
|
||||
{
|
||||
// display a useful message
|
||||
AZ::Entity* entity = nullptr;
|
||||
@@ -106,7 +108,7 @@ namespace AzToolsFramework
|
||||
// Clear out newly generated data and
|
||||
// replace with original data to ensure debug mode has the same data as profile/release
|
||||
// in the event of the consistency check failing.
|
||||
m_entitySavedStates[entityId] = AZStd::move(oldData);
|
||||
m_entitySavedStates[entityId] = {AZStd::move(oldData), oldParentId};
|
||||
|
||||
#endif // ENABLE_UNDOCACHE_CONSISTENCY_CHECKS
|
||||
}
|
||||
@@ -140,10 +142,13 @@ namespace AzToolsFramework
|
||||
return;
|
||||
}
|
||||
|
||||
AZ::EntityId parentId;
|
||||
AZ::TransformBus::EventResult(parentId, entityId, &AZ::TransformBus::Events::GetParentId);
|
||||
|
||||
// Capture it
|
||||
PrefabDom entityDom;
|
||||
m_instanceToTemplateInterface->GenerateDomForEntity(entityDom, *entity);
|
||||
m_entitySavedStates.emplace(AZStd::make_pair(entityId, AZStd::move(entityDom)));
|
||||
m_entitySavedStates[entityId] = {AZStd::move(entityDom), parentId};
|
||||
|
||||
AZLOG("Prefab Undo", "Correctly updated cache for entity of id %llu (%s)", static_cast<AZ::u64>(entityId), entity->GetName().c_str());
|
||||
|
||||
@@ -155,7 +160,7 @@ namespace AzToolsFramework
|
||||
m_entitySavedStates.erase(entityId);
|
||||
}
|
||||
|
||||
bool PrefabUndoCache::Retrieve(const AZ::EntityId& entityId, PrefabDom& outDom)
|
||||
bool PrefabUndoCache::Retrieve(const AZ::EntityId& entityId, PrefabDom& outDom, AZ::EntityId& parentId)
|
||||
{
|
||||
auto it = m_entitySavedStates.find(entityId);
|
||||
|
||||
@@ -164,14 +169,15 @@ namespace AzToolsFramework
|
||||
return false;
|
||||
}
|
||||
|
||||
outDom = AZStd::move(m_entitySavedStates[entityId]);
|
||||
outDom = AZStd::move(m_entitySavedStates[entityId].dom);
|
||||
parentId = m_entitySavedStates[entityId].parentId;
|
||||
m_entitySavedStates.erase(entityId);
|
||||
return true;
|
||||
}
|
||||
|
||||
void PrefabUndoCache::Store(const AZ::EntityId& entityId, PrefabDom&& dom)
|
||||
void PrefabUndoCache::Store(const AZ::EntityId& entityId, PrefabDom&& dom, const AZ::EntityId& parentId)
|
||||
{
|
||||
m_entitySavedStates.emplace(AZStd::make_pair(entityId, AZStd::move(dom)));
|
||||
m_entitySavedStates[entityId] = {AZStd::move(dom), parentId};
|
||||
}
|
||||
|
||||
void PrefabUndoCache::Clear()
|
||||
|
||||
@@ -46,14 +46,19 @@ namespace AzToolsFramework
|
||||
void Validate(const AZ::EntityId& entityId) override;
|
||||
|
||||
// Retrieve the last known state for an entity
|
||||
bool Retrieve(const AZ::EntityId& entityId, PrefabDom& outDom);
|
||||
bool Retrieve(const AZ::EntityId& entityId, PrefabDom& outDom, AZ::EntityId& parentId);
|
||||
|
||||
// Store dom as the cached state of entityId
|
||||
void Store(const AZ::EntityId& entityId, PrefabDom&& dom);
|
||||
void Store(const AZ::EntityId& entityId, PrefabDom&& dom, const AZ::EntityId& parentId);
|
||||
|
||||
private:
|
||||
typedef AZStd::unordered_map<AZ::EntityId, PrefabDom> EntityDomMap;
|
||||
EntityDomMap m_entitySavedStates;
|
||||
struct PrefabUndoCacheItem
|
||||
{
|
||||
PrefabDom dom;
|
||||
AZ::EntityId parentId;
|
||||
};
|
||||
typedef AZStd::unordered_map<AZ::EntityId, PrefabUndoCacheItem> EntityCache;
|
||||
EntityCache m_entitySavedStates;
|
||||
|
||||
InstanceEntityMapperInterface* m_instanceEntityMapperInterface = nullptr;
|
||||
InstanceToTemplateInterface* m_instanceToTemplateInterface = nullptr;
|
||||
|
||||
+11
@@ -124,4 +124,15 @@ namespace AzToolsFramework
|
||||
|
||||
return cameraState;
|
||||
}
|
||||
|
||||
float GetScreenDisplayScaling(const int viewportId)
|
||||
{
|
||||
float scaling = 1.0f;
|
||||
ViewportInteraction::ViewportInteractionRequestBus::EventResult(
|
||||
scaling, viewportId,
|
||||
&ViewportInteraction::ViewportInteractionRequestBus::Events::DeviceScalingFactor);
|
||||
|
||||
return scaling;
|
||||
}
|
||||
|
||||
} // namespace AzToolsFramework
|
||||
|
||||
+3
@@ -60,6 +60,9 @@ namespace AzToolsFramework
|
||||
/// Wrapper for EBus call to return the CameraState for a given viewport.
|
||||
AzFramework::CameraState GetCameraState(int viewportId);
|
||||
|
||||
/// Wrapper for EBus call to return the DPI scaling for a given viewport.
|
||||
float GetScreenDisplayScaling(const int viewportId);
|
||||
|
||||
/// A utility to return the center of several points.
|
||||
/// Take several positions and store the min and max of each in
|
||||
/// turn - when all points have been added return the center/midpoint.
|
||||
|
||||
+4
-3
@@ -3573,9 +3573,10 @@ namespace AzToolsFramework
|
||||
debugDisplay.SetLineWidth(1.0f);
|
||||
|
||||
const float labelOffset = cl_viewportGizmoAxisLabelOffset;
|
||||
const auto labelXScreenPosition = (gizmoStart + (gizmoAxisX * labelOffset)) * editorCameraState.m_viewportSize;
|
||||
const auto labelYScreenPosition = (gizmoStart + (gizmoAxisY * labelOffset)) * editorCameraState.m_viewportSize;
|
||||
const auto labelZScreenPosition = (gizmoStart + (gizmoAxisZ * labelOffset)) * editorCameraState.m_viewportSize;
|
||||
const float screenScale = GetScreenDisplayScaling(viewportId);
|
||||
const auto labelXScreenPosition = (gizmoStart + (gizmoAxisX * labelOffset)) * editorCameraState.m_viewportSize * screenScale;
|
||||
const auto labelYScreenPosition = (gizmoStart + (gizmoAxisY * labelOffset)) * editorCameraState.m_viewportSize * screenScale;
|
||||
const auto labelZScreenPosition = (gizmoStart + (gizmoAxisZ * labelOffset)) * editorCameraState.m_viewportSize * screenScale;
|
||||
|
||||
// draw the label of of each axis for the gizmo
|
||||
const float labelSize = cl_viewportGizmoAxisLabelSize;
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <Launcher.h>
|
||||
|
||||
#include <AzCore/Casting/numeric_cast.h>
|
||||
@@ -22,6 +23,8 @@
|
||||
#include <AzCore/Utils/Utils.h>
|
||||
#include <AzFramework/Asset/AssetSystemBus.h>
|
||||
#include <AzFramework/IO/RemoteStorageDrive.h>
|
||||
#include <AzFramework/Windowing/NativeWindow.h>
|
||||
#include <AzFramework/Windowing/WindowBus.h>
|
||||
|
||||
#include <AzGameFramework/Application/GameApplication.h>
|
||||
|
||||
@@ -45,6 +48,19 @@ extern "C" void CreateStaticModules(AZStd::vector<AZ::Module*>& modulesOut);
|
||||
|
||||
namespace
|
||||
{
|
||||
void OnViewportResize(const AZ::Vector2& value);
|
||||
|
||||
AZ_CVAR(AZ::Vector2, r_viewportSize, AZ::Vector2::CreateZero(), OnViewportResize, AZ::ConsoleFunctorFlags::DontReplicate,
|
||||
"The default size for the launcher viewport, 0 0 means full screen");
|
||||
|
||||
void OnViewportResize(const AZ::Vector2& value)
|
||||
{
|
||||
AzFramework::NativeWindowHandle windowHandle = nullptr;
|
||||
AzFramework::WindowSystemRequestBus::BroadcastResult(windowHandle, &AzFramework::WindowSystemRequestBus::Events::GetDefaultWindowHandle);
|
||||
AzFramework::WindowSize newSize = AzFramework::WindowSize(aznumeric_cast<int32_t>(value.GetX()), aznumeric_cast<int32_t>(value.GetY()));
|
||||
AzFramework::WindowRequestBus::Broadcast(&AzFramework::WindowRequestBus::Events::ResizeClientArea, newSize);
|
||||
}
|
||||
|
||||
void ExecuteConsoleCommandFile(AzFramework::Application& application)
|
||||
{
|
||||
const AZStd::string_view customConCmdKey = "console-command-file";
|
||||
|
||||
@@ -1233,7 +1233,7 @@ void EditorViewportWidget::SetViewportId(int id)
|
||||
|
||||
auto controller = AZStd::make_shared<AtomToolsFramework::ModularViewportCameraController>();
|
||||
controller->SetCameraListBuilderCallback(
|
||||
[](AzFramework::Cameras& cameras)
|
||||
[id](AzFramework::Cameras& cameras)
|
||||
{
|
||||
auto firstPersonRotateCamera = AZStd::make_shared<AzFramework::RotateCameraInput>(AzFramework::CameraFreeLookButton);
|
||||
auto firstPersonPanCamera =
|
||||
@@ -1243,17 +1243,17 @@ void EditorViewportWidget::SetViewportId(int id)
|
||||
|
||||
auto orbitCamera = AZStd::make_shared<AzFramework::OrbitCameraInput>();
|
||||
orbitCamera->SetLookAtFn(
|
||||
[](const AZ::Vector3& position, const AZ::Vector3& direction) -> AZStd::optional<AZ::Vector3>
|
||||
[id](const AZ::Vector3& position, const AZ::Vector3& direction) -> AZStd::optional<AZ::Vector3>
|
||||
{
|
||||
AZStd::optional<AZ::Transform> manipulatorTransform;
|
||||
AzToolsFramework::EditorTransformComponentSelectionRequestBus::EventResult(
|
||||
manipulatorTransform, AzToolsFramework::GetEntityContextId(),
|
||||
&AzToolsFramework::EditorTransformComponentSelectionRequestBus::Events::GetManipulatorTransform);
|
||||
AZStd::optional<AZ::Vector3> lookAtAfterInterpolation;
|
||||
AtomToolsFramework::ModularViewportCameraControllerRequestBus::EventResult(
|
||||
lookAtAfterInterpolation, id,
|
||||
&AtomToolsFramework::ModularViewportCameraControllerRequestBus::Events::LookAtAfterInterpolation);
|
||||
|
||||
// initially attempt to use manipulator transform if one exists (there is a selection)
|
||||
if (manipulatorTransform)
|
||||
// initially attempt to use the last set look at point after an interpolation has finished
|
||||
if (lookAtAfterInterpolation.has_value())
|
||||
{
|
||||
return manipulatorTransform->GetTranslation();
|
||||
return *lookAtAfterInterpolation;
|
||||
}
|
||||
|
||||
const float RayDistance = 1000.0f;
|
||||
|
||||
@@ -553,7 +553,7 @@ void CLogFile::OnWriteToConsole(const char* sText, bool bNewLine)
|
||||
|
||||
// remember selection and the top row
|
||||
int len = m_hWndEditBox->document()->toPlainText().length();
|
||||
int top;
|
||||
int top = 0;
|
||||
int from = m_hWndEditBox->textCursor().selectionStart();
|
||||
int to = from + m_hWndEditBox->textCursor().selectionEnd();
|
||||
bool keepPos = false;
|
||||
|
||||
@@ -121,7 +121,7 @@ protected:
|
||||
};
|
||||
#endif
|
||||
|
||||
Q_GLOBAL_STATIC(QtViewPaneManager, s_instance)
|
||||
Q_GLOBAL_STATIC(QtViewPaneManager, s_viewPaneManagerInstance)
|
||||
|
||||
|
||||
QWidget* QtViewPane::CreateWidget()
|
||||
@@ -611,12 +611,12 @@ void QtViewPaneManager::UnregisterPane(const QString& name)
|
||||
|
||||
QtViewPaneManager* QtViewPaneManager::instance()
|
||||
{
|
||||
return s_instance();
|
||||
return s_viewPaneManagerInstance();
|
||||
}
|
||||
|
||||
bool QtViewPaneManager::exists()
|
||||
{
|
||||
return s_instance.exists();
|
||||
return s_viewPaneManagerInstance.exists();
|
||||
}
|
||||
|
||||
void QtViewPaneManager::SetMainWindow(AzQtComponents::DockMainWindow* mainWindow, QSettings* settings, const QByteArray& lastMainWindowState)
|
||||
|
||||
@@ -59,7 +59,7 @@ namespace
|
||||
{
|
||||
int fps;
|
||||
const char* fpsDesc;
|
||||
} fps[] = {
|
||||
} fpsOptions[] = {
|
||||
{24, "Film(24)"}, {25, "PAL(25)"}, {30, "NTSC(30)"},
|
||||
{48, "Show(48)"}, {50, "PAL Field(50)"}, {60, "NTSC Field(60)"}
|
||||
};
|
||||
@@ -213,9 +213,9 @@ void CSequenceBatchRenderDialog::OnInitDialog()
|
||||
m_ui->m_resolutionCombo->setCurrentIndex(0);
|
||||
|
||||
// Fill the FPS combo box.
|
||||
for (int i = 0; i < AZStd::size(fps); ++i)
|
||||
for (int i = 0; i < AZStd::size(fpsOptions); ++i)
|
||||
{
|
||||
m_ui->m_fpsCombo->addItem(fps[i].fpsDesc);
|
||||
m_ui->m_fpsCombo->addItem(fpsOptions[i].fpsDesc);
|
||||
}
|
||||
m_ui->m_fpsCombo->setCurrentIndex(0);
|
||||
|
||||
@@ -306,9 +306,9 @@ void CSequenceBatchRenderDialog::OnRenderItemSelChange()
|
||||
m_ui->m_destinationEdit->setText(item.folder);
|
||||
// fps
|
||||
bool bFound = false;
|
||||
for (int i = 0; i < arraysize(fps); ++i)
|
||||
for (int i = 0; i < arraysize(fpsOptions); ++i)
|
||||
{
|
||||
if (item.fps == fps[i].fps)
|
||||
if (item.fps == fpsOptions[i].fps)
|
||||
{
|
||||
m_ui->m_fpsCombo->setCurrentIndex(i);
|
||||
bFound = true;
|
||||
@@ -621,7 +621,7 @@ void CSequenceBatchRenderDialog::OnFPSEditChange()
|
||||
|
||||
void CSequenceBatchRenderDialog::OnFPSChange(int itemIndex)
|
||||
{
|
||||
m_customFPS = fps[itemIndex].fps;
|
||||
m_customFPS = fpsOptions[itemIndex].fps;
|
||||
CheckForEnableUpdateButton();
|
||||
}
|
||||
|
||||
@@ -1543,13 +1543,13 @@ bool CSequenceBatchRenderDialog::SetUpNewRenderItem(SRenderItem& item)
|
||||
item.frameRange = Range(m_ui->m_startFrame->value() / m_fpsForTimeToFrameConversion,
|
||||
m_ui->m_endFrame->value() / m_fpsForTimeToFrameConversion);
|
||||
// fps
|
||||
if (m_ui->m_fpsCombo->currentIndex() == -1 || m_ui->m_fpsCombo->currentText() != fps[m_ui->m_fpsCombo->currentIndex()].fpsDesc)
|
||||
if (m_ui->m_fpsCombo->currentIndex() == -1 || m_ui->m_fpsCombo->currentText() != fpsOptions[m_ui->m_fpsCombo->currentIndex()].fpsDesc)
|
||||
{
|
||||
item.fps = m_customFPS;
|
||||
}
|
||||
else
|
||||
{
|
||||
item.fps = fps[m_ui->m_fpsCombo->currentIndex()].fps;
|
||||
item.fps = fpsOptions[m_ui->m_fpsCombo->currentIndex()].fps;
|
||||
}
|
||||
// prefix
|
||||
item.prefix = m_ui->BATCH_RENDER_FILE_PREFIX->text();
|
||||
|
||||
@@ -157,7 +157,7 @@ static Quatern Qt_FromMatrix(HMatrix mat)
|
||||
* |w| is greater than 1/2, which is as small as a largest component can be.
|
||||
* Otherwise, the largest diagonal entry corresponds to the largest of |x|,
|
||||
* |y|, or |z|, one of which must be larger than |w|, and at least 1/2. */
|
||||
Quatern qu;
|
||||
Quatern qu = { 0.0f, 0.0f, 0.0f, 1.0f };
|
||||
double tr, s;
|
||||
|
||||
tr = mat[X][X] + mat[Y][Y] + mat[Z][Z];
|
||||
@@ -531,7 +531,7 @@ Quatern snuggle(Quatern q, HVect* k)
|
||||
#define swap(a, i, j) {a[3] = a[i]; a[i] = a[j]; a[j] = a[3]; }
|
||||
#define cycle(a, p) if (p) {a[3] = a[0]; a[0] = a[1]; a[1] = a[2]; a[2] = a[3]; } \
|
||||
else {a[3] = a[2]; a[2] = a[1]; a[1] = a[0]; a[0] = a[3]; }
|
||||
Quatern p;
|
||||
Quatern p = { 0.0f, 0.0f, 0.0f, 1.0f };
|
||||
float ka[4];
|
||||
int i, turn = -1;
|
||||
ka[X] = k->x;
|
||||
|
||||
@@ -2239,7 +2239,8 @@ uint32 CFileUtil::GetAttributes(const char* filename, bool bUseSourceControl /*=
|
||||
bool CFileUtil::CompareFiles(const QString& strFilePath1, const QString& strFilePath2)
|
||||
{
|
||||
// Get the size of both files. If either fails we say they are different (most likely one doesn't exist)
|
||||
uint64 size1, size2;
|
||||
uint64 size1 = 0;
|
||||
uint64 size2 = 0;
|
||||
if (!GetDiskFileSize(strFilePath1.toUtf8().data(), size1) || !GetDiskFileSize(strFilePath2.toUtf8().data(), size2))
|
||||
{
|
||||
return false;
|
||||
|
||||
@@ -116,6 +116,7 @@ bool CImageBT::Load(const QString& fileName, CFloatImage& image)
|
||||
|
||||
// Get the BT header data
|
||||
BtHeader header;
|
||||
memset(&header, 0, sizeof(BtHeader)); // C4701 potentially uninitialized local variable 'header' used
|
||||
bool validData = true;
|
||||
validData = validData && (fread(&header, sizeof(BtHeader), 1, file) != 0);
|
||||
|
||||
|
||||
@@ -419,7 +419,7 @@ static inline bool MatchesWildcardsIgnoreCaseExt_Tpl(const TS& str, const TS& wi
|
||||
const typename TS::value_type* savedStrBegin = 0;
|
||||
const typename TS::value_type* savedStrEnd = 0;
|
||||
const typename TS::value_type* savedWild = 0;
|
||||
size_t savedWildCount;
|
||||
size_t savedWildCount = 0;
|
||||
|
||||
const typename TS::value_type* pStr = str.c_str();
|
||||
const typename TS::value_type* pWild = wildcards.c_str();
|
||||
|
||||
@@ -179,11 +179,11 @@ ComponentEntityEditorPlugin::ComponentEntityEditorPlugin([[maybe_unused]] IEdito
|
||||
LyViewPane::EntityOutliner,
|
||||
LyViewPane::CategoryTools,
|
||||
outlinerOptions);
|
||||
}
|
||||
|
||||
AzToolsFramework::ViewPaneOptions options;
|
||||
options.preferedDockingArea = Qt::NoDockWidgetArea;
|
||||
RegisterViewPane<SliceRelationshipWidget>(LyViewPane::SliceRelationships, LyViewPane::CategoryTools, options);
|
||||
AzToolsFramework::ViewPaneOptions options;
|
||||
options.preferedDockingArea = Qt::NoDockWidgetArea;
|
||||
RegisterViewPane<SliceRelationshipWidget>(LyViewPane::SliceRelationships, LyViewPane::CategoryTools, options);
|
||||
}
|
||||
|
||||
RegisterModuleResourceSelectors(GetIEditor()->GetResourceSelectorHost());
|
||||
|
||||
|
||||
@@ -1732,13 +1732,14 @@ void SandboxIntegrationManager::GoToEntitiesInViewports(const AzToolsFramework::
|
||||
// compute new camera transform
|
||||
const float fov = AzFramework::RetrieveFov(viewportContext->GetCameraProjectionMatrix());
|
||||
const float fovScale = (1.0f / AZStd::tan(fov * 0.5f));
|
||||
const float distanceToTarget = selectionSize * fovScale * centerScale;
|
||||
const float distanceToLookAt = selectionSize * fovScale * centerScale;
|
||||
const AZ::Transform nextCameraTransform =
|
||||
AZ::Transform::CreateLookAt(aabb.GetCenter() - (forward * distanceToTarget), aabb.GetCenter());
|
||||
AZ::Transform::CreateLookAt(aabb.GetCenter() - (forward * distanceToLookAt), aabb.GetCenter());
|
||||
|
||||
AtomToolsFramework::ModularViewportCameraControllerRequestBus::Event(
|
||||
viewportContext->GetId(),
|
||||
&AtomToolsFramework::ModularViewportCameraControllerRequestBus::Events::InterpolateToTransform, nextCameraTransform);
|
||||
&AtomToolsFramework::ModularViewportCameraControllerRequestBus::Events::InterpolateToTransform, nextCameraTransform,
|
||||
distanceToLookAt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -294,7 +294,8 @@ namespace O3DE::ProjectManager
|
||||
RegisterThisEngine();
|
||||
|
||||
return result == 0 && !PyErr_Occurred();
|
||||
} catch ([[maybe_unused]] const std::exception& e)
|
||||
}
|
||||
catch ([[maybe_unused]] const std::exception& e)
|
||||
{
|
||||
AZ_Warning("ProjectManagerWindow", false, "Py_Initialize() failed with %s", e.what());
|
||||
return false;
|
||||
@@ -320,25 +321,25 @@ namespace O3DE::ProjectManager
|
||||
bool registrationResult = true; // already registered is considered successful
|
||||
bool pythonResult = ExecuteWithLock(
|
||||
[&]
|
||||
{
|
||||
// check current engine path against all other registered engines
|
||||
// to see if we are already registered
|
||||
auto allEngines = m_manifest.attr("get_engines")();
|
||||
if (pybind11::isinstance<pybind11::list>(allEngines))
|
||||
{
|
||||
// check current engine path against all other registered engines
|
||||
// to see if we are already registered
|
||||
auto allEngines = m_manifest.attr("get_engines")();
|
||||
if (pybind11::isinstance<pybind11::list>(allEngines))
|
||||
for (auto engine : allEngines)
|
||||
{
|
||||
for (auto engine : allEngines)
|
||||
AZ::IO::FixedMaxPath enginePath(Py_To_String(engine["path"]));
|
||||
if (enginePath.Compare(m_enginePath) == 0)
|
||||
{
|
||||
AZ::IO::FixedMaxPath enginePath(Py_To_String(engine["path"]));
|
||||
if (enginePath.Compare(m_enginePath) == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto result = m_register.attr("register")(m_enginePath.c_str());
|
||||
registrationResult = (result.cast<int>() == 0);
|
||||
});
|
||||
auto result = m_register.attr("register")(m_enginePath.c_str());
|
||||
registrationResult = (result.cast<int>() == 0);
|
||||
});
|
||||
|
||||
bool finalResult = (registrationResult && pythonResult);
|
||||
AZ_Assert(finalResult, "Registration of this engine failed!");
|
||||
@@ -378,12 +379,12 @@ namespace O3DE::ProjectManager
|
||||
auto o3deData = m_manifest.attr("load_o3de_manifest")();
|
||||
if (pybind11::isinstance<pybind11::dict>(o3deData))
|
||||
{
|
||||
engineInfo.m_path = Py_To_String(enginePath);
|
||||
engineInfo.m_defaultGemsFolder = Py_To_String(o3deData["default_gems_folder"]);
|
||||
engineInfo.m_defaultProjectsFolder = Py_To_String(o3deData["default_projects_folder"]);
|
||||
engineInfo.m_path = Py_To_String(enginePath);
|
||||
engineInfo.m_defaultGemsFolder = Py_To_String(o3deData["default_gems_folder"]);
|
||||
engineInfo.m_defaultProjectsFolder = Py_To_String(o3deData["default_projects_folder"]);
|
||||
engineInfo.m_defaultRestrictedFolder = Py_To_String(o3deData["default_restricted_folder"]);
|
||||
engineInfo.m_defaultTemplatesFolder = Py_To_String(o3deData["default_templates_folder"]);
|
||||
engineInfo.m_thirdPartyPath = Py_To_String_Optional(o3deData,"third_party_path","");
|
||||
engineInfo.m_defaultTemplatesFolder = Py_To_String(o3deData["default_templates_folder"]);
|
||||
engineInfo.m_thirdPartyPath = Py_To_String_Optional(o3deData, "third_party_path", "");
|
||||
}
|
||||
|
||||
auto engineData = m_manifest.attr("get_engine_json_data")(pybind11::none(), enginePath);
|
||||
@@ -391,8 +392,8 @@ namespace O3DE::ProjectManager
|
||||
{
|
||||
try
|
||||
{
|
||||
engineInfo.m_version = Py_To_String_Optional(engineData,"O3DEVersion","0.0.0.0");
|
||||
engineInfo.m_name = Py_To_String_Optional(engineData,"engine_name","O3DE");
|
||||
engineInfo.m_version = Py_To_String_Optional(engineData, "O3DEVersion", "0.0.0.0");
|
||||
engineInfo.m_name = Py_To_String_Optional(engineData, "engine_name", "O3DE");
|
||||
}
|
||||
catch ([[maybe_unused]] const std::exception& e)
|
||||
{
|
||||
@@ -416,19 +417,19 @@ namespace O3DE::ProjectManager
|
||||
bool PythonBindings::SetEngineInfo(const EngineInfo& engineInfo)
|
||||
{
|
||||
bool result = ExecuteWithLock([&] {
|
||||
pybind11::str enginePath = engineInfo.m_path.toStdString();
|
||||
pybind11::str defaultProjectsFolder = engineInfo.m_defaultProjectsFolder.toStdString();
|
||||
pybind11::str defaultGemsFolder = engineInfo.m_defaultGemsFolder.toStdString();
|
||||
pybind11::str enginePath = engineInfo.m_path.toStdString();
|
||||
pybind11::str defaultProjectsFolder = engineInfo.m_defaultProjectsFolder.toStdString();
|
||||
pybind11::str defaultGemsFolder = engineInfo.m_defaultGemsFolder.toStdString();
|
||||
pybind11::str defaultTemplatesFolder = engineInfo.m_defaultTemplatesFolder.toStdString();
|
||||
|
||||
auto registrationResult = m_register.attr("register")(
|
||||
enginePath, // engine_path
|
||||
pybind11::none(), // project_path
|
||||
enginePath, // engine_path
|
||||
pybind11::none(), // project_path
|
||||
pybind11::none(), // gem_path
|
||||
pybind11::none(), // external_subdir_path
|
||||
pybind11::none(), // template_path
|
||||
pybind11::none(), // restricted_path
|
||||
pybind11::none(), // repo_uri
|
||||
pybind11::none(), // external_subdir_path
|
||||
pybind11::none(), // template_path
|
||||
pybind11::none(), // restricted_path
|
||||
pybind11::none(), // repo_uri
|
||||
pybind11::none(), // default_engines_folder
|
||||
defaultProjectsFolder,
|
||||
defaultGemsFolder,
|
||||
@@ -477,12 +478,12 @@ namespace O3DE::ProjectManager
|
||||
QVector<GemInfo> gems;
|
||||
|
||||
auto result = ExecuteWithLockErrorHandling([&]
|
||||
{
|
||||
for (auto path : m_manifest.attr("get_engine_gems")())
|
||||
{
|
||||
for (auto path : m_manifest.attr("get_engine_gems")())
|
||||
{
|
||||
gems.push_back(GemInfoFromPath(path));
|
||||
}
|
||||
});
|
||||
gems.push_back(GemInfoFromPath(path));
|
||||
}
|
||||
});
|
||||
if (!result.IsSuccess())
|
||||
{
|
||||
return AZ::Failure<AZStd::string>(result.GetError().c_str());
|
||||
@@ -497,13 +498,13 @@ namespace O3DE::ProjectManager
|
||||
QVector<GemInfo> gems;
|
||||
|
||||
auto result = ExecuteWithLockErrorHandling([&]
|
||||
{
|
||||
pybind11::str pyProjectPath = projectPath.toStdString();
|
||||
for (auto path : m_manifest.attr("get_all_gems")(pyProjectPath))
|
||||
{
|
||||
pybind11::str pyProjectPath = projectPath.toStdString();
|
||||
for (auto path : m_manifest.attr("get_all_gems")(pyProjectPath))
|
||||
{
|
||||
gems.push_back(GemInfoFromPath(path));
|
||||
}
|
||||
});
|
||||
gems.push_back(GemInfoFromPath(path));
|
||||
}
|
||||
});
|
||||
if (!result.IsSuccess())
|
||||
{
|
||||
return AZ::Failure<AZStd::string>(result.GetError().c_str());
|
||||
@@ -518,12 +519,12 @@ namespace O3DE::ProjectManager
|
||||
// Retrieve the path to the cmake file that lists the enabled gems.
|
||||
pybind11::str enabledGemsFilename;
|
||||
auto result = ExecuteWithLockErrorHandling([&]
|
||||
{
|
||||
const pybind11::str pyProjectPath = projectPath.toStdString();
|
||||
enabledGemsFilename = m_cmake.attr("get_enabled_gem_cmake_file")(
|
||||
pybind11::none(), // project_name
|
||||
pyProjectPath); // project_path
|
||||
});
|
||||
{
|
||||
const pybind11::str pyProjectPath = projectPath.toStdString();
|
||||
enabledGemsFilename = m_cmake.attr("get_enabled_gem_cmake_file")(
|
||||
pybind11::none(), // project_name
|
||||
pyProjectPath); // project_path
|
||||
});
|
||||
if (!result.IsSuccess())
|
||||
{
|
||||
return AZ::Failure<AZStd::string>(result.GetError().c_str());
|
||||
@@ -532,13 +533,13 @@ namespace O3DE::ProjectManager
|
||||
// Retrieve the actual list of names from the cmake file.
|
||||
QVector<AZStd::string> gemNames;
|
||||
result = ExecuteWithLockErrorHandling([&]
|
||||
{
|
||||
const auto pyGemNames = m_cmake.attr("get_enabled_gems")(enabledGemsFilename);
|
||||
for (auto gemName : pyGemNames)
|
||||
{
|
||||
const auto pyGemNames = m_cmake.attr("get_enabled_gems")(enabledGemsFilename);
|
||||
for (auto gemName : pyGemNames)
|
||||
{
|
||||
gemNames.push_back(Py_To_String(gemName));
|
||||
}
|
||||
});
|
||||
gemNames.push_back(Py_To_String(gemName));
|
||||
}
|
||||
});
|
||||
if (!result.IsSuccess())
|
||||
{
|
||||
return AZ::Failure<AZStd::string>(result.GetError().c_str());
|
||||
@@ -552,13 +553,13 @@ namespace O3DE::ProjectManager
|
||||
bool registrationResult = false;
|
||||
bool result = ExecuteWithLock(
|
||||
[&]
|
||||
{
|
||||
pybind11::str projectPath = path.toStdString();
|
||||
auto pythonRegistrationResult = m_register.attr("register")(pybind11::none(), projectPath);
|
||||
{
|
||||
pybind11::str projectPath = path.toStdString();
|
||||
auto pythonRegistrationResult = m_register.attr("register")(pybind11::none(), projectPath);
|
||||
|
||||
// Returns an exit code so boolify it then invert result
|
||||
registrationResult = !pythonRegistrationResult.cast<bool>();
|
||||
});
|
||||
// Returns an exit code so boolify it then invert result
|
||||
registrationResult = !pythonRegistrationResult.cast<bool>();
|
||||
});
|
||||
|
||||
return result && registrationResult;
|
||||
}
|
||||
@@ -568,30 +569,30 @@ namespace O3DE::ProjectManager
|
||||
bool registrationResult = false;
|
||||
bool result = ExecuteWithLock(
|
||||
[&]
|
||||
{
|
||||
pybind11::str projectPath = path.toStdString();
|
||||
auto pythonRegistrationResult = m_register.attr("register")(
|
||||
pybind11::none(), // engine_path
|
||||
projectPath, // project_path
|
||||
pybind11::none(), // gem_path
|
||||
pybind11::none(), // external_subdir_path
|
||||
pybind11::none(), // template_path
|
||||
pybind11::none(), // restricted_path
|
||||
pybind11::none(), // repo_uri
|
||||
pybind11::none(), // default_engines_folder
|
||||
pybind11::none(), // default_projects_folder
|
||||
pybind11::none(), // default_gems_folder
|
||||
pybind11::none(), // default_templates_folder
|
||||
pybind11::none(), // default_restricted_folder
|
||||
pybind11::none(), // external_subdir_engine_path
|
||||
pybind11::none(), // external_subdir_project_path
|
||||
true, // remove
|
||||
false // force
|
||||
{
|
||||
pybind11::str projectPath = path.toStdString();
|
||||
auto pythonRegistrationResult = m_register.attr("register")(
|
||||
pybind11::none(), // engine_path
|
||||
projectPath, // project_path
|
||||
pybind11::none(), // gem_path
|
||||
pybind11::none(), // external_subdir_path
|
||||
pybind11::none(), // template_path
|
||||
pybind11::none(), // restricted_path
|
||||
pybind11::none(), // repo_uri
|
||||
pybind11::none(), // default_engines_folder
|
||||
pybind11::none(), // default_projects_folder
|
||||
pybind11::none(), // default_gems_folder
|
||||
pybind11::none(), // default_templates_folder
|
||||
pybind11::none(), // default_restricted_folder
|
||||
pybind11::none(), // external_subdir_engine_path
|
||||
pybind11::none(), // external_subdir_project_path
|
||||
true, // remove
|
||||
false // force
|
||||
);
|
||||
|
||||
// Returns an exit code so boolify it then invert result
|
||||
registrationResult = !pythonRegistrationResult.cast<bool>();
|
||||
});
|
||||
|
||||
// Returns an exit code so boolify it then invert result
|
||||
registrationResult = !pythonRegistrationResult.cast<bool>();
|
||||
});
|
||||
|
||||
return result && registrationResult;
|
||||
}
|
||||
@@ -649,12 +650,12 @@ namespace O3DE::ProjectManager
|
||||
try
|
||||
{
|
||||
// required
|
||||
gemInfo.m_name = Py_To_String(data["gem_name"]);
|
||||
gemInfo.m_name = Py_To_String(data["gem_name"]);
|
||||
|
||||
// optional
|
||||
gemInfo.m_displayName = Py_To_String_Optional(data, "DisplayName", gemInfo.m_name);
|
||||
gemInfo.m_summary = Py_To_String_Optional(data, "Summary", "");
|
||||
gemInfo.m_version = Py_To_String_Optional(data, "Version", "");
|
||||
gemInfo.m_summary = Py_To_String_Optional(data, "Summary", "");
|
||||
gemInfo.m_version = Py_To_String_Optional(data, "Version", "");
|
||||
|
||||
if (data.contains("Tags"))
|
||||
{
|
||||
@@ -685,7 +686,7 @@ namespace O3DE::ProjectManager
|
||||
try
|
||||
{
|
||||
projectInfo.m_projectName = Py_To_String(projectData["project_name"]);
|
||||
projectInfo.m_displayName = Py_To_String_Optional(projectData,"display_name", projectInfo.m_projectName);
|
||||
projectInfo.m_displayName = Py_To_String_Optional(projectData, "display_name", projectInfo.m_projectName);
|
||||
}
|
||||
catch ([[maybe_unused]] const std::exception& e)
|
||||
{
|
||||
@@ -727,33 +728,33 @@ namespace O3DE::ProjectManager
|
||||
AZ::Outcome<void, AZStd::string> PythonBindings::AddGemToProject(const QString& gemPath, const QString& projectPath)
|
||||
{
|
||||
return ExecuteWithLockErrorHandling([&]
|
||||
{
|
||||
pybind11::str pyGemPath = gemPath.toStdString();
|
||||
pybind11::str pyProjectPath = projectPath.toStdString();
|
||||
{
|
||||
pybind11::str pyGemPath = gemPath.toStdString();
|
||||
pybind11::str pyProjectPath = projectPath.toStdString();
|
||||
|
||||
m_enableGemProject.attr("enable_gem_in_project")(
|
||||
pybind11::none(), // gem name not needed as path is provided
|
||||
pyGemPath,
|
||||
pybind11::none(), // project name not needed as path is provided
|
||||
pyProjectPath
|
||||
m_enableGemProject.attr("enable_gem_in_project")(
|
||||
pybind11::none(), // gem name not needed as path is provided
|
||||
pyGemPath,
|
||||
pybind11::none(), // project name not needed as path is provided
|
||||
pyProjectPath
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
AZ::Outcome<void, AZStd::string> PythonBindings::RemoveGemFromProject(const QString& gemPath, const QString& projectPath)
|
||||
{
|
||||
return ExecuteWithLockErrorHandling([&]
|
||||
{
|
||||
pybind11::str pyGemPath = gemPath.toStdString();
|
||||
pybind11::str pyProjectPath = projectPath.toStdString();
|
||||
{
|
||||
pybind11::str pyGemPath = gemPath.toStdString();
|
||||
pybind11::str pyProjectPath = projectPath.toStdString();
|
||||
|
||||
m_disableGemProject.attr("disable_gem_in_project")(
|
||||
pybind11::none(), // gem name not needed as path is provided
|
||||
pyGemPath,
|
||||
pybind11::none(), // project name not needed as path is provided
|
||||
pyProjectPath
|
||||
m_disableGemProject.attr("disable_gem_in_project")(
|
||||
pybind11::none(), // gem name not needed as path is provided
|
||||
pyGemPath,
|
||||
pybind11::none(), // project name not needed as path is provided
|
||||
pyProjectPath
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
bool PythonBindings::UpdateProject([[maybe_unused]] const ProjectInfo& projectInfo)
|
||||
@@ -773,8 +774,8 @@ namespace O3DE::ProjectManager
|
||||
{
|
||||
// required
|
||||
templateInfo.m_displayName = Py_To_String(data["display_name"]);
|
||||
templateInfo.m_name = Py_To_String(data["template_name"]);
|
||||
templateInfo.m_summary = Py_To_String(data["summary"]);
|
||||
templateInfo.m_name = Py_To_String(data["template_name"]);
|
||||
templateInfo.m_summary = Py_To_String(data["summary"]);
|
||||
|
||||
// optional
|
||||
if (data.contains("canonical_tags"))
|
||||
@@ -806,7 +807,7 @@ namespace O3DE::ProjectManager
|
||||
QVector<ProjectTemplateInfo> templates;
|
||||
|
||||
bool result = ExecuteWithLock([&] {
|
||||
for (auto path : m_manifest.attr("get_project_templates")())
|
||||
for (auto path : m_manifest.attr("get_templates_for_project_creation")())
|
||||
{
|
||||
templates.push_back(ProjectTemplateInfoFromPath(path));
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <AzCore/Utils/Utils.h>
|
||||
|
||||
#include <AzToolsFramework/Thumbnails/ThumbnailerNullComponent.h>
|
||||
#include <SliceConverterEditorEntityContextComponent.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
@@ -34,6 +35,9 @@ namespace AZ
|
||||
Application::Application(int argc, char** argv)
|
||||
: AzToolsFramework::ToolsApplication(&argc, &argv)
|
||||
{
|
||||
// We need a specialized variant of EditorEntityContextCompnent for the SliceConverter, so we register the descriptor here.
|
||||
RegisterComponentDescriptor(AzToolsFramework::SliceConverterEditorEntityContextComponent::CreateDescriptor());
|
||||
|
||||
AZ::IO::FixedMaxPath projectPath = AZ::Utils::GetProjectPath();
|
||||
if (projectPath.empty())
|
||||
{
|
||||
@@ -110,10 +114,21 @@ namespace AZ
|
||||
|
||||
AZ::ComponentTypeList Application::GetRequiredSystemComponents() const
|
||||
{
|
||||
// Use all of the default system components, but also add in the ThumbnailerNullComponent so that components requiring
|
||||
// a ThumbnailService can still be started up.
|
||||
// By default, we use all of the standard system components.
|
||||
AZ::ComponentTypeList components = AzToolsFramework::ToolsApplication::GetRequiredSystemComponents();
|
||||
|
||||
// Also add in the ThumbnailerNullComponent so that components requiring a ThumbnailService can still be started up.
|
||||
components.emplace_back(azrtti_typeid<AzToolsFramework::Thumbnailer::ThumbnailerNullComponent>());
|
||||
|
||||
// The Slice Converter requires a specialized variant of the EditorEntityContextComponent that exposes the ability
|
||||
// to disable the behavior of activating entities on creation. During conversion, the creation flow will be triggered,
|
||||
// but entity activation requires a significant amount of subsystem initialization that's unneeded for conversion.
|
||||
// So, to get around this, we swap out EditorEntityContextComponent with SliceConverterEditorEntityContextComponent.
|
||||
components.erase(
|
||||
AZStd::remove(
|
||||
components.begin(), components.end(), azrtti_typeid<AzToolsFramework::EditorEntityContextComponent>()),
|
||||
components.end());
|
||||
components.emplace_back(azrtti_typeid<AzToolsFramework::SliceConverterEditorEntityContextComponent>());
|
||||
return components;
|
||||
}
|
||||
} // namespace SerializeContextTools
|
||||
|
||||
@@ -30,13 +30,16 @@
|
||||
#include <AzToolsFramework/Prefab/PrefabDomUtils.h>
|
||||
#include <AzToolsFramework/Prefab/EditorPrefabComponent.h>
|
||||
#include <AzToolsFramework/Prefab/PrefabPublicInterface.h>
|
||||
#include <AzToolsFramework/Prefab/Instance/InstanceUpdateExecutorInterface.h>
|
||||
#include <AzToolsFramework/Entity/EditorEntityContextBus.h>
|
||||
#include <AzToolsFramework/Entity/PrefabEditorEntityOwnershipInterface.h>
|
||||
#include <AzToolsFramework/ToolsComponents/TransformComponent.h>
|
||||
#include <Application.h>
|
||||
#include <SliceConverter.h>
|
||||
#include <SliceConverterEditorEntityContextComponent.h>
|
||||
#include <Utilities.h>
|
||||
|
||||
|
||||
// SliceConverter reads in a slice file (saved in an ObjectStream format), instantiates it, creates a prefab out of the data,
|
||||
// and saves the prefab in a JSON format. This can be used for one-time migrations of slices or slice-based levels to prefabs.
|
||||
//
|
||||
@@ -99,12 +102,26 @@ namespace AZ
|
||||
bool result = true;
|
||||
rapidjson::StringBuffer scratchBuffer;
|
||||
|
||||
// For slice conversion, disable the EditorEntityContextComponent logic that activates entities on creation.
|
||||
// This prevents a lot of error messages and crashes during conversion due to lack of full environment and subsystem setup.
|
||||
AzToolsFramework::SliceConverterEditorEntityContextComponent::DisableOnContextEntityLogic();
|
||||
|
||||
// Loop through the list of requested files and convert them.
|
||||
AZStd::vector<AZStd::string> fileList = Utilities::ReadFileListFromCommandLine(application, "files");
|
||||
for (AZStd::string& filePath : fileList)
|
||||
{
|
||||
bool convertResult = ConvertSliceFile(convertSettings.m_serializeContext, filePath, isDryRun);
|
||||
result = result && convertResult;
|
||||
|
||||
// Clear out all registered prefab templates between each top-level file that gets processed.
|
||||
auto prefabSystemComponentInterface = AZ::Interface<AzToolsFramework::Prefab::PrefabSystemComponentInterface>::Get();
|
||||
for (auto templateId : m_createdTemplateIds)
|
||||
{
|
||||
// We don't just want to call RemoveAllTemplates() because the root template should remain between file conversions.
|
||||
prefabSystemComponentInterface->RemoveTemplate(templateId);
|
||||
}
|
||||
m_aliasIdMapper.clear();
|
||||
m_createdTemplateIds.clear();
|
||||
}
|
||||
|
||||
DisconnectFromAssetProcessor();
|
||||
@@ -114,6 +131,13 @@ namespace AZ
|
||||
bool SliceConverter::ConvertSliceFile(
|
||||
AZ::SerializeContext* serializeContext, const AZStd::string& slicePath, bool isDryRun)
|
||||
{
|
||||
/* To convert a slice file, we read the input file in via ObjectStream, then use the "class ready" callback to convert
|
||||
* the data in memory to a Prefab.
|
||||
* If the input file is a level file (.ly), we actually need to load the level slice file ("levelentities.editor_xml") from
|
||||
* within the level file, which effectively is a zip file of the level slice file and a bunch of legacy level files that won't
|
||||
* be converted, since the systems that would use them no longer exist.
|
||||
*/
|
||||
|
||||
bool result = true;
|
||||
bool packOpened = false;
|
||||
|
||||
@@ -144,7 +168,7 @@ namespace AZ
|
||||
AZ_STRING_ARG(fileExtension.Native()));
|
||||
}
|
||||
|
||||
auto callback = [&outputPath, isDryRun](void* classPtr, const Uuid& classId, SerializeContext* context)
|
||||
auto callback = [this, &outputPath, isDryRun](void* classPtr, const Uuid& classId, SerializeContext* context)
|
||||
{
|
||||
if (classId != azrtti_typeid<AZ::Entity>())
|
||||
{
|
||||
@@ -178,6 +202,13 @@ namespace AZ
|
||||
bool SliceConverter::ConvertSliceToPrefab(
|
||||
AZ::SerializeContext* serializeContext, AZ::IO::PathView outputPath, bool isDryRun, AZ::Entity* rootEntity)
|
||||
{
|
||||
/* Given a root slice entity, we convert it to a prefab by doing the following:
|
||||
* - Locate the SliceComponent
|
||||
* - Take all the entities directly located on the slice, and put them into a prefab
|
||||
* - Fix up any top-level entities to have the prefab container entity as their parent
|
||||
* - If there are any nested slice instances, convert the nested slices to prefabs, then convert the instances.
|
||||
*/
|
||||
|
||||
auto prefabSystemComponentInterface = AZ::Interface<AzToolsFramework::Prefab::PrefabSystemComponentInterface>::Get();
|
||||
|
||||
// Find the slice from the root entity.
|
||||
@@ -192,9 +223,14 @@ namespace AZ
|
||||
SliceComponent::EntityList sliceEntities = sliceComponent->GetNewEntities();
|
||||
AZ_Printf("Convert-Slice", " Slice contains %zu entities.\n", sliceEntities.size());
|
||||
|
||||
// Create the Prefab with the entities from the slice
|
||||
// Create the Prefab with the entities from the slice.
|
||||
// The entities are added in a separate step so that we can give them deterministic entity aliases that match their entity Ids
|
||||
AZStd::unique_ptr<AzToolsFramework::Prefab::Instance> sourceInstance(
|
||||
prefabSystemComponentInterface->CreatePrefab(sliceEntities, {}, outputPath));
|
||||
prefabSystemComponentInterface->CreatePrefab({}, {}, outputPath));
|
||||
for (auto& entity : sliceEntities)
|
||||
{
|
||||
sourceInstance->AddEntity(*entity, AZStd::string::format("Entity_%s", entity->GetId().ToString().c_str()));
|
||||
}
|
||||
|
||||
// Dispatch events here, because prefab creation might trigger asset loads in rare circumstances.
|
||||
AZ::Data::AssetManager::Instance().DispatchEvents();
|
||||
@@ -204,12 +240,28 @@ namespace AZ
|
||||
AzToolsFramework::Prefab::EntityOptionalReference container = sourceInstance->GetContainerEntity();
|
||||
FixPrefabEntities(container->get(), sliceEntities);
|
||||
|
||||
// Keep track of the template Id we created, we're going to remove it at the end of slice file conversion to make sure
|
||||
// the data doesn't stick around between file conversions.
|
||||
auto templateId = sourceInstance->GetTemplateId();
|
||||
if (templateId == AzToolsFramework::Prefab::InvalidTemplateId)
|
||||
{
|
||||
AZ_Printf("Convert-Slice", " Path error. Path could be invalid, or the prefab may not be loaded in this level.\n");
|
||||
return false;
|
||||
}
|
||||
m_createdTemplateIds.emplace(templateId);
|
||||
|
||||
// Save off a mapping of the original slice entity IDs to the new prefab template entity aliases.
|
||||
// When converting nested slices, this mapping will be needed to fix up the parent entity hierarchy correctly.
|
||||
auto entityAliases = sourceInstance->GetEntityAliases();
|
||||
for (auto& alias : entityAliases)
|
||||
{
|
||||
auto id = sourceInstance->GetEntityId(alias);
|
||||
auto result = m_aliasIdMapper.emplace(TemplateEntityIdPair(templateId, id), alias);
|
||||
if (!result.second)
|
||||
{
|
||||
AZ_Printf("Convert-Slice", " Duplicate entity alias -> entity id entries found, conversion may not be successful.\n");
|
||||
}
|
||||
}
|
||||
|
||||
// Update the prefab template with the fixed-up data in our prefab instance.
|
||||
AzToolsFramework::Prefab::PrefabDom prefabDom;
|
||||
@@ -254,21 +306,26 @@ namespace AZ
|
||||
// via an EditorRequests EBus in CreatePrefab, but the subsystem that listens for it isn't present in this tool.)
|
||||
AzToolsFramework::EditorEntityContextRequestBus::Broadcast(
|
||||
&AzToolsFramework::EditorEntityContextRequestBus::Events::AddRequiredComponents, containerEntity);
|
||||
containerEntity.AddComponent(aznew AzToolsFramework::Prefab::EditorPrefabComponent());
|
||||
if (containerEntity.FindComponent<AzToolsFramework::Prefab::EditorPrefabComponent>() == nullptr)
|
||||
{
|
||||
containerEntity.AddComponent(aznew AzToolsFramework::Prefab::EditorPrefabComponent());
|
||||
}
|
||||
|
||||
// Make all the components on the container entity have deterministic component IDs, so that multiple runs of the tool
|
||||
// on the same slice will produce the same prefab output. We're going to cheat a bit and just use the component type hash
|
||||
// as the component ID. This would break if we had multiple components of the same type, but that currently doesn't
|
||||
// happen for the container entity.
|
||||
auto containerComponents = containerEntity.GetComponents();
|
||||
for (auto& component : containerComponents)
|
||||
{
|
||||
component->SetId(component->GetUnderlyingComponentType().GetHash());
|
||||
}
|
||||
|
||||
// Reparent any root-level slice entities to the container entity.
|
||||
for (auto entity : sliceEntities)
|
||||
{
|
||||
AzToolsFramework::Components::TransformComponent* transformComponent =
|
||||
entity->FindComponent<AzToolsFramework::Components::TransformComponent>();
|
||||
if (transformComponent)
|
||||
{
|
||||
if (!transformComponent->GetParentId().IsValid())
|
||||
{
|
||||
transformComponent->SetParent(containerEntity.GetId());
|
||||
transformComponent->UpdateCachedWorldTransform();
|
||||
}
|
||||
}
|
||||
constexpr bool onlySetIfInvalid = true;
|
||||
SetParentEntity(*entity, containerEntity.GetId(), onlySetIfInvalid);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -276,9 +333,13 @@ namespace AZ
|
||||
SliceComponent* sliceComponent, AzToolsFramework::Prefab::Instance* sourceInstance,
|
||||
AZ::SerializeContext* serializeContext, bool isDryRun)
|
||||
{
|
||||
/* Given a root slice, find all the nested slices and convert them. */
|
||||
|
||||
// Get the list of nested slices that this slice uses.
|
||||
const SliceComponent::SliceList& sliceList = sliceComponent->GetSlices();
|
||||
auto prefabSystemComponentInterface = AZ::Interface<AzToolsFramework::Prefab::PrefabSystemComponentInterface>::Get();
|
||||
|
||||
// For each nested slice, convert it.
|
||||
for (auto& slice : sliceList)
|
||||
{
|
||||
// Get the nested slice asset
|
||||
@@ -312,7 +373,7 @@ namespace AZ
|
||||
return false;
|
||||
}
|
||||
|
||||
// Load the prefab template for the newly-created nested prefab.
|
||||
// Find the prefab template we created for the newly-created nested prefab.
|
||||
// To get the template, we need to take our absolute slice path and turn it into a project-relative prefab path.
|
||||
AZ::IO::Path nestedPrefabPath = assetPath;
|
||||
nestedPrefabPath.ReplaceExtension("prefab");
|
||||
@@ -346,11 +407,25 @@ namespace AZ
|
||||
}
|
||||
|
||||
bool SliceConverter::ConvertSliceInstance(
|
||||
[[maybe_unused]] AZ::SliceComponent::SliceInstance& instance,
|
||||
[[maybe_unused]] AZ::Data::Asset<AZ::SliceAsset>& sliceAsset,
|
||||
AZ::SliceComponent::SliceInstance& instance,
|
||||
AZ::Data::Asset<AZ::SliceAsset>& sliceAsset,
|
||||
AzToolsFramework::Prefab::TemplateReference nestedTemplate,
|
||||
AzToolsFramework::Prefab::Instance* topLevelInstance)
|
||||
{
|
||||
/* To convert a slice instance, it's important to understand the similarities and differences between slices and prefabs.
|
||||
* Both slices and prefabs have the concept of instances of a nested slice/prefab, where each instance can have its own
|
||||
* set of changed data (transforms, component values, etc).
|
||||
* For slices, the changed data comes from applying a DataPatch to an instantiated set of entities from the nested slice.
|
||||
* From prefabs, the changed data comes from Json patches that are applied to the instantiated set of entities from the
|
||||
* nested prefab. The prefab instance entities also have different IDs than the slice instance entities, so we'll need
|
||||
* to remap some of them along the way.
|
||||
* To get from one to the other, we'll need to do the following:
|
||||
* - Instantiate the nested slice and nested prefab
|
||||
* - Patch the nested slice instance and fix up the entity ID references
|
||||
* - Replace the nested prefab instance entities with the fixed-up slice ones
|
||||
* - Add the nested instance (and the link patch) to the top-level prefab
|
||||
*/
|
||||
|
||||
auto instanceToTemplateInterface = AZ::Interface<AzToolsFramework::Prefab::InstanceToTemplateInterface>::Get();
|
||||
auto prefabSystemComponentInterface = AZ::Interface<AzToolsFramework::Prefab::PrefabSystemComponentInterface>::Get();
|
||||
|
||||
@@ -371,22 +446,83 @@ namespace AZ
|
||||
AzToolsFramework::Prefab::PrefabDom unmodifiedNestedInstanceDom;
|
||||
instanceToTemplateInterface->GenerateDomForInstance(unmodifiedNestedInstanceDom, *(nestedInstance.get()));
|
||||
|
||||
// Currently, DataPatch conversions for nested slices aren't implemented, so all nested slice overrides will
|
||||
// be lost.
|
||||
AZ_Warning(
|
||||
"Convert-Slice", false, " Nested slice instances will lose all of their override data during conversion.",
|
||||
nestedTemplate->get().GetFilePath().c_str());
|
||||
// Instantiate a new instance of the nested slice
|
||||
SliceComponent* dependentSlice = sliceAsset.Get()->GetComponent();
|
||||
[[maybe_unused]] AZ::SliceComponent::InstantiateResult instantiationResult = dependentSlice->Instantiate();
|
||||
AZ_Assert(instantiationResult == AZ::SliceComponent::InstantiateResult::Success, "Failed to instantiate instance");
|
||||
|
||||
// Set the container entity of the nested prefab to have the top-level prefab as the parent.
|
||||
// Once DataPatch conversions are supported, this will need to change to nest the prefab under the appropriate entity
|
||||
// within the level.
|
||||
// Apply the data patch for this instance of the nested slice. This will provide us with a version of the slice's entities
|
||||
// with all data overrides applied to them.
|
||||
DataPatch::FlagsMap sourceDataFlags = dependentSlice->GetDataFlagsForInstances().GetDataFlagsForPatching();
|
||||
DataPatch::FlagsMap targetDataFlags = instance.GetDataFlags().GetDataFlagsForPatching(&instance.GetEntityIdToBaseMap());
|
||||
AZ::ObjectStream::FilterDescriptor filterDesc(AZ::Data::AssetFilterNoAssetLoading);
|
||||
|
||||
AZ::SliceComponent::InstantiatedContainer sourceObjects(false);
|
||||
dependentSlice->GetEntities(sourceObjects.m_entities);
|
||||
dependentSlice->GetAllMetadataEntities(sourceObjects.m_metadataEntities);
|
||||
|
||||
const DataPatch& dataPatch = instance.GetDataPatch();
|
||||
auto instantiated =
|
||||
dataPatch.Apply(&sourceObjects, dependentSlice->GetSerializeContext(), filterDesc, sourceDataFlags, targetDataFlags);
|
||||
|
||||
// Run through all the instantiated entities and fix up their parent hierarchy:
|
||||
// - Invalid parents need to get set to the container.
|
||||
// - Valid parents into the top-level instance mean that the nested slice instance is also child-nested under an entity.
|
||||
// Prefabs handle this type of nesting differently - we need to set the parent to the container, and the container's
|
||||
// parent to that other instance.
|
||||
auto containerEntity = nestedInstance->GetContainerEntity();
|
||||
AzToolsFramework::Components::TransformComponent* transformComponent =
|
||||
containerEntity->get().FindComponent<AzToolsFramework::Components::TransformComponent>();
|
||||
if (transformComponent)
|
||||
auto containerEntityId = containerEntity->get().GetId();
|
||||
for (auto entity : instantiated->m_entities)
|
||||
{
|
||||
transformComponent->SetParent(topLevelInstance->GetContainerEntityId());
|
||||
transformComponent->UpdateCachedWorldTransform();
|
||||
AzToolsFramework::Components::TransformComponent* transformComponent =
|
||||
entity->FindComponent<AzToolsFramework::Components::TransformComponent>();
|
||||
if (transformComponent)
|
||||
{
|
||||
bool onlySetIfInvalid = true;
|
||||
auto parentId = transformComponent->GetParentId();
|
||||
if (parentId.IsValid())
|
||||
{
|
||||
auto parentAlias = m_aliasIdMapper.find(TemplateEntityIdPair(topLevelInstance->GetTemplateId(), parentId));
|
||||
if (parentAlias != m_aliasIdMapper.end())
|
||||
{
|
||||
// Set the container's parent to this entity's parent, and set this entity's parent to the container
|
||||
// (i.e. go from A->B to A->container->B)
|
||||
auto newParentId = topLevelInstance->GetEntityId(parentAlias->second);
|
||||
SetParentEntity(containerEntity->get(), newParentId, false);
|
||||
onlySetIfInvalid = false;
|
||||
}
|
||||
}
|
||||
|
||||
SetParentEntity(*entity, containerEntityId, onlySetIfInvalid);
|
||||
}
|
||||
}
|
||||
|
||||
// Replace all the entities in the instance with the new patched ones.
|
||||
// (This is easier than trying to figure out what the patched data changes are - we can let the JSON patch handle it for us)
|
||||
nestedInstance->RemoveNestedEntities(
|
||||
[](const AZStd::unique_ptr<AZ::Entity>&)
|
||||
{
|
||||
return true;
|
||||
});
|
||||
for (auto& entity : instantiated->m_entities)
|
||||
{
|
||||
auto entityAlias = m_aliasIdMapper.find(TemplateEntityIdPair(nestedInstance->GetTemplateId(), entity->GetId()));
|
||||
if (entityAlias != m_aliasIdMapper.end())
|
||||
{
|
||||
nestedInstance->AddEntity(*entity, entityAlias->second);
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Assert(false, "Failed to find entity alias.");
|
||||
nestedInstance->AddEntity(*entity);
|
||||
}
|
||||
}
|
||||
|
||||
// Set the container entity of the nested prefab to have the top-level prefab as the parent if it hasn't already gotten
|
||||
// another entity as its parent.
|
||||
{
|
||||
constexpr bool onlySetIfInvalid = true;
|
||||
SetParentEntity(containerEntity->get(), topLevelInstance->GetContainerEntityId(), onlySetIfInvalid);
|
||||
}
|
||||
|
||||
// Add the nested instance itself to the top-level prefab. To do this, we need to add it to our top-level instance,
|
||||
@@ -395,7 +531,22 @@ namespace AZ
|
||||
AzToolsFramework::Prefab::PrefabDom topLevelInstanceDomBefore;
|
||||
instanceToTemplateInterface->GenerateDomForInstance(topLevelInstanceDomBefore, *topLevelInstance);
|
||||
|
||||
AzToolsFramework::Prefab::Instance& addedInstance = topLevelInstance->AddInstance(AZStd::move(nestedInstance));
|
||||
// When creating the new instance, we would like to have deterministic instance aliases. Prefabs that depend on this one
|
||||
// will have patches that reference the alias, so if we reconvert this slice a second time, we would like it to produce
|
||||
// the same results. To get a deterministic and unique alias, we rely on the slice instance. The slice instance contains
|
||||
// a map of slice entity IDs to unique instance entity IDs. We'll just consistently use the first entry in the map as the
|
||||
// unique instance ID.
|
||||
AZStd::string instanceAlias;
|
||||
auto entityIdMap = instance.GetEntityIdMap();
|
||||
if (!entityIdMap.empty())
|
||||
{
|
||||
instanceAlias = AZStd::string::format("Instance_%s", entityIdMap.begin()->second.ToString().c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
instanceAlias = AZStd::string::format("Instance_%s", AZ::Entity::MakeId().ToString().c_str());
|
||||
}
|
||||
AzToolsFramework::Prefab::Instance& addedInstance = topLevelInstance->AddInstance(AZStd::move(nestedInstance), instanceAlias);
|
||||
|
||||
AzToolsFramework::Prefab::PrefabDom topLevelInstanceDomAfter;
|
||||
instanceToTemplateInterface->GenerateDomForInstance(topLevelInstanceDomAfter, *topLevelInstance);
|
||||
@@ -418,9 +569,26 @@ namespace AZ
|
||||
AzToolsFramework::Prefab::InvalidLinkId);
|
||||
prefabSystemComponentInterface->PropagateTemplateChanges(topLevelInstance->GetTemplateId());
|
||||
|
||||
AZ::Interface<AzToolsFramework::Prefab::InstanceUpdateExecutorInterface>::Get()->UpdateTemplateInstancesInQueue();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SliceConverter::SetParentEntity(const AZ::Entity& entity, const AZ::EntityId& parentId, bool onlySetIfInvalid)
|
||||
{
|
||||
AzToolsFramework::Components::TransformComponent* transformComponent =
|
||||
entity.FindComponent<AzToolsFramework::Components::TransformComponent>();
|
||||
if (transformComponent)
|
||||
{
|
||||
// Only set the parent if we didn't set the onlySetIfInvalid flag, or if we did and the parent is currently invalid
|
||||
if (!onlySetIfInvalid || !transformComponent->GetParentId().IsValid())
|
||||
{
|
||||
transformComponent->SetParent(parentId);
|
||||
transformComponent->UpdateCachedWorldTransform();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SliceConverter::PrintPrefab(AzToolsFramework::Prefab::TemplateId templateId)
|
||||
{
|
||||
auto prefabSystemComponentInterface = AZ::Interface<AzToolsFramework::Prefab::PrefabSystemComponentInterface>::Get();
|
||||
|
||||
@@ -39,24 +39,35 @@ namespace AZ
|
||||
class SliceConverter : public Converter
|
||||
{
|
||||
public:
|
||||
static bool ConvertSliceFiles(Application& application);
|
||||
bool ConvertSliceFiles(Application& application);
|
||||
|
||||
private:
|
||||
static bool ConnectToAssetProcessor();
|
||||
static void DisconnectFromAssetProcessor();
|
||||
using TemplateEntityIdPair = AZStd::pair<AzToolsFramework::Prefab::TemplateId, AZ::EntityId>;
|
||||
|
||||
static bool ConvertSliceFile(AZ::SerializeContext* serializeContext, const AZStd::string& slicePath, bool isDryRun);
|
||||
static bool ConvertSliceToPrefab(
|
||||
bool ConnectToAssetProcessor();
|
||||
void DisconnectFromAssetProcessor();
|
||||
|
||||
bool ConvertSliceFile(AZ::SerializeContext* serializeContext, const AZStd::string& slicePath, bool isDryRun);
|
||||
bool ConvertSliceToPrefab(
|
||||
AZ::SerializeContext* serializeContext, AZ::IO::PathView outputPath, bool isDryRun, AZ::Entity* rootEntity);
|
||||
static void FixPrefabEntities(AZ::Entity& containerEntity, SliceComponent::EntityList& sliceEntities);
|
||||
static bool ConvertNestedSlices(
|
||||
void FixPrefabEntities(AZ::Entity& containerEntity, SliceComponent::EntityList& sliceEntities);
|
||||
bool ConvertNestedSlices(
|
||||
SliceComponent* sliceComponent, AzToolsFramework::Prefab::Instance* sourceInstance,
|
||||
AZ::SerializeContext* serializeContext, bool isDryRun);
|
||||
static bool ConvertSliceInstance(
|
||||
bool ConvertSliceInstance(
|
||||
AZ::SliceComponent::SliceInstance& instance, AZ::Data::Asset<AZ::SliceAsset>& sliceAsset,
|
||||
AzToolsFramework::Prefab::TemplateReference nestedTemplate, AzToolsFramework::Prefab::Instance* topLevelInstance);
|
||||
static void PrintPrefab(AzToolsFramework::Prefab::TemplateId templateId);
|
||||
static bool SavePrefab(AZ::IO::PathView outputPath, AzToolsFramework::Prefab::TemplateId templateId);
|
||||
void SetParentEntity(const AZ::Entity& entity, const AZ::EntityId& parentId, bool onlySetIfInvalid);
|
||||
void PrintPrefab(AzToolsFramework::Prefab::TemplateId templateId);
|
||||
bool SavePrefab(AZ::IO::PathView outputPath, AzToolsFramework::Prefab::TemplateId templateId);
|
||||
|
||||
// Track all of the entity IDs created and the prefab entity aliases that map to them. This mapping is used
|
||||
// with nested slice conversion to remap parent entity IDs to the correct prefab entity IDs.
|
||||
AZStd::unordered_map<TemplateEntityIdPair, AzToolsFramework::Prefab::EntityAlias> m_aliasIdMapper;
|
||||
|
||||
// Track all of the created prefab template IDs on a slice conversion so that they can get removed at the end of the
|
||||
// conversion for that file.
|
||||
AZStd::unordered_set<AzToolsFramework::Prefab::TemplateId> m_createdTemplateIds;
|
||||
};
|
||||
} // namespace SerializeContextTools
|
||||
} // namespace AZ
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* 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 <AzToolsFramework/Entity/EditorEntityContextComponent.h>
|
||||
|
||||
namespace AzToolsFramework
|
||||
{
|
||||
// This class is an inelegant workaround for use by the Slice Converter to selectively disable entity add/remove logic
|
||||
// during slice conversion in the EditorEntityContextComponent. Specifically, the standard versions of these methods will
|
||||
// attempt to activate the entities as they're added. This is both unnecessary and undesirable during slice conversion, since
|
||||
// entity activation requires a lot of subsystems to be active and valid.
|
||||
// Instead, by selectively disabling this logic, the entities can remain in an initialized state, which is sufficient for conversion,
|
||||
// without requiring those extra subsystems.
|
||||
|
||||
// This problem also could have been solved by adding APIs to the EditorEntityContextComponent or the EntityContext, but there aren't
|
||||
// any other known valid use cases for disabling this logic, so the extra APIs would simply encourage "bad behavior" by using them
|
||||
// when they likely aren't necessary or desired.
|
||||
|
||||
class SliceConverterEditorEntityContextComponent
|
||||
: public EditorEntityContextComponent
|
||||
{
|
||||
public:
|
||||
|
||||
AZ_COMPONENT(SliceConverterEditorEntityContextComponent, "{1CB0C38F-8E85-4422-91C6-E1F3B9B4B853}");
|
||||
|
||||
SliceConverterEditorEntityContextComponent() : EditorEntityContextComponent() {}
|
||||
|
||||
// Simple API to selectively disable this logic *only* when performing slice to prefab conversion.
|
||||
static void DisableOnContextEntityLogic()
|
||||
{
|
||||
m_enableOnContextEntityLogic = false;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
void OnContextEntitiesAdded([[maybe_unused]] const EntityList& entities) override
|
||||
{
|
||||
if (m_enableOnContextEntityLogic)
|
||||
{
|
||||
EditorEntityContextComponent::OnContextEntitiesAdded(entities);
|
||||
}
|
||||
}
|
||||
|
||||
void OnContextEntityRemoved([[maybe_unused]] const AZ::EntityId& id) override
|
||||
{
|
||||
if (m_enableOnContextEntityLogic)
|
||||
{
|
||||
EditorEntityContextComponent::OnContextEntityRemoved(id);
|
||||
}
|
||||
}
|
||||
|
||||
// By default, act just like the EditorEntityContextComponent
|
||||
static inline bool m_enableOnContextEntityLogic = true;
|
||||
};
|
||||
} // namespace AzToolsFramework
|
||||
@@ -125,7 +125,8 @@ int main(int argc, char** argv)
|
||||
}
|
||||
else if (AZ::StringFunc::Equal("convert-slice", action.c_str()))
|
||||
{
|
||||
result = SliceConverter::ConvertSliceFiles(application);
|
||||
SliceConverter sliceConverter;
|
||||
result = sliceConverter.ConvertSliceFiles(application);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -17,6 +17,7 @@ set(FILES
|
||||
Dumper.h
|
||||
Dumper.cpp
|
||||
main.cpp
|
||||
SliceConverterEditorEntityContextComponent.h
|
||||
SliceConverter.h
|
||||
SliceConverter.cpp
|
||||
Utilities.h
|
||||
|
||||
@@ -48,7 +48,8 @@ class ConfigurationManager(object):
|
||||
def configuration(self, new_configuration: ConfigurationManager) -> None:
|
||||
self._configuration = new_configuration
|
||||
|
||||
def setup(self, config_path: str) -> None:
|
||||
def setup(self, config_path: str) -> bool:
|
||||
result: bool = True
|
||||
logger.info("Setting up default configuration ...")
|
||||
try:
|
||||
normalized_config_path: str = file_utils.normalize_file_path(config_path);
|
||||
@@ -63,5 +64,7 @@ class ConfigurationManager(object):
|
||||
self._configuration.account_id = aws_utils.get_default_account_id()
|
||||
self._configuration.region = aws_utils.get_default_region()
|
||||
except (RuntimeError, FileNotFoundError) as e:
|
||||
logger.exception(e)
|
||||
logger.error(e)
|
||||
result = False
|
||||
logger.debug(self._configuration)
|
||||
return result
|
||||
|
||||
@@ -74,11 +74,18 @@ if __name__ == "__main__":
|
||||
logger.warning("Failed to load style sheet for resource mapping tool")
|
||||
|
||||
logger.info("Initializing boto3 default session ...")
|
||||
aws_utils.setup_default_session(arguments.profile)
|
||||
try:
|
||||
aws_utils.setup_default_session(arguments.profile)
|
||||
except RuntimeError as error:
|
||||
logger.error(error)
|
||||
environment_utils.cleanup_qt_environment()
|
||||
exit(-1)
|
||||
|
||||
logger.info("Initializing configuration manager ...")
|
||||
configuration_manager: ConfigurationManager = ConfigurationManager()
|
||||
configuration_manager.setup(arguments.config_path)
|
||||
if not configuration_manager.setup(arguments.config_path):
|
||||
environment_utils.cleanup_qt_environment()
|
||||
exit(-1)
|
||||
|
||||
logger.info("Initializing thread manager ...")
|
||||
thread_manager: ThreadManager = ThreadManager()
|
||||
|
||||
+1238
-1124
File diff suppressed because it is too large
Load Diff
@@ -12,10 +12,10 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
import boto3
|
||||
from botocore.paginate import (PageIterator, Paginator)
|
||||
from botocore.client import BaseClient
|
||||
from botocore.exceptions import ClientError
|
||||
from botocore.exceptions import (ClientError, ConfigNotFound, NoCredentialsError, ProfileNotFound)
|
||||
from typing import Dict, List
|
||||
|
||||
from model import (constants, error_messages)
|
||||
from model import error_messages
|
||||
from model.basic_resource_attributes import (BasicResourceAttributes, BasicResourceAttributesBuilder)
|
||||
|
||||
"""
|
||||
@@ -65,8 +65,11 @@ def _initialize_boto3_aws_client(service: str, region: str = "") -> BaseClient:
|
||||
|
||||
|
||||
def setup_default_session(profile: str) -> None:
|
||||
global default_session
|
||||
default_session = boto3.session.Session(profile_name=profile)
|
||||
try:
|
||||
global default_session
|
||||
default_session = boto3.session.Session(profile_name=profile)
|
||||
except (ConfigNotFound, ProfileNotFound) as error:
|
||||
raise RuntimeError(error)
|
||||
|
||||
|
||||
def get_default_account_id() -> str:
|
||||
@@ -76,6 +79,8 @@ def get_default_account_id() -> str:
|
||||
except ClientError as error:
|
||||
raise RuntimeError(error_messages.AWS_SERVICE_REQUEST_CLIENT_ERROR_MESSAGE.format(
|
||||
"get_caller_identity", error.response['Error']['Code'], error.response['Error']['Message']))
|
||||
except NoCredentialsError as error:
|
||||
raise RuntimeError(error)
|
||||
|
||||
|
||||
def get_default_region() -> str:
|
||||
|
||||
@@ -88,7 +88,7 @@ namespace ImageProcessingAtom
|
||||
int dstPosition;
|
||||
signed short int n;
|
||||
bool trimZeros = true, stillzero;
|
||||
int lastnonzero, hWeight, highest;
|
||||
int lastnonzero = 0, hWeight, highest = 0;
|
||||
signed int sumiWeights, iWeight;
|
||||
signed short int* weightsPtr;
|
||||
signed short int* weightsMem;
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
"Name": "IBLSpecular",
|
||||
"Description": "The input cubemap generates an IBL specular output cubemap.",
|
||||
"FileMasks": [
|
||||
"_iblspecularcm"
|
||||
"_iblspecularcm",
|
||||
"_iblspecularcm256"
|
||||
],
|
||||
"SourceColor": "Linear",
|
||||
"DestColor": "Linear",
|
||||
@@ -34,7 +35,8 @@
|
||||
"UUID": "{908DA68C-97FB-4C4A-97BC-5A55F30F14FA}",
|
||||
"Name": "IBLSpecular",
|
||||
"FileMasks": [
|
||||
"_iblspecularcm"
|
||||
"_iblspecularcm",
|
||||
"_iblspecularcm256"
|
||||
],
|
||||
"SourceColor": "Linear",
|
||||
"DestColor": "Linear",
|
||||
@@ -59,7 +61,8 @@
|
||||
"UUID": "{908DA68C-97FB-4C4A-97BC-5A55F30F14FA}",
|
||||
"Name": "IBLSpecular",
|
||||
"FileMasks": [
|
||||
"_iblspecularcm"
|
||||
"_iblspecularcm",
|
||||
"_iblspecularcm256"
|
||||
],
|
||||
"SourceColor": "Linear",
|
||||
"DestColor": "Linear",
|
||||
@@ -84,7 +87,8 @@
|
||||
"UUID": "{908DA68C-97FB-4C4A-97BC-5A55F30F14FA}",
|
||||
"Name": "IBLSpecular",
|
||||
"FileMasks": [
|
||||
"_iblspecularcm"
|
||||
"_iblspecularcm",
|
||||
"_iblspecularcm256"
|
||||
],
|
||||
"SourceColor": "Linear",
|
||||
"DestColor": "Linear",
|
||||
@@ -109,7 +113,8 @@
|
||||
"UUID": "{908DA68C-97FB-4C4A-97BC-5A55F30F14FA}",
|
||||
"Name": "IBLSpecular",
|
||||
"FileMasks": [
|
||||
"_iblspecularcm"
|
||||
"_iblspecularcm",
|
||||
"_iblspecularcm256"
|
||||
],
|
||||
"SourceColor": "Linear",
|
||||
"DestColor": "Linear",
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
{
|
||||
"Type": "JsonSerialization",
|
||||
"Version": 1,
|
||||
"ClassName": "MultiplatformPresetSettings",
|
||||
"ClassData": {
|
||||
"DefaultPreset": {
|
||||
"UUID": "{B66395E1-8D0E-4159-989B-FC2B9F091B75}",
|
||||
"Name": "IBLSpecularHigh",
|
||||
"Description": "The input cubemap generates an IBL specular output cubemap.",
|
||||
"FileMasks": [
|
||||
"_iblspecularcm512"
|
||||
],
|
||||
"SourceColor": "Linear",
|
||||
"DestColor": "Linear",
|
||||
"SuppressEngineReduce": true,
|
||||
"PixelFormat": "R9G9B9E5",
|
||||
"DiscardAlpha": true,
|
||||
"MinTextureSize": 512,
|
||||
"MaxTextureSize": 512,
|
||||
"IsPowerOf2": true,
|
||||
"CubemapSettings": {
|
||||
"Filter": "GGX",
|
||||
"MipAngle": 7.0,
|
||||
"MipSlope": 2.299999952316284,
|
||||
"EdgeFixup": -431602080.0,
|
||||
"SubId": 2000
|
||||
},
|
||||
"MipMapSetting": {
|
||||
"MipGenType": "Box"
|
||||
}
|
||||
},
|
||||
"PlatformsPresets": {
|
||||
"android": {
|
||||
"UUID": "{B66395E1-8D0E-4159-989B-FC2B9F091B75}",
|
||||
"Name": "IBLSpecularHigh",
|
||||
"FileMasks": [
|
||||
"_iblspecularcm512"
|
||||
],
|
||||
"SourceColor": "Linear",
|
||||
"DestColor": "Linear",
|
||||
"SuppressEngineReduce": true,
|
||||
"PixelFormat": "R9G9B9E5",
|
||||
"DiscardAlpha": true,
|
||||
"MinTextureSize": 512,
|
||||
"MaxTextureSize": 512,
|
||||
"IsPowerOf2": true,
|
||||
"CubemapSettings": {
|
||||
"Filter": "GGX",
|
||||
"MipAngle": 7.0,
|
||||
"MipSlope": 2.299999952316284,
|
||||
"EdgeFixup": -431602080.0,
|
||||
"SubId": 2000
|
||||
},
|
||||
"MipMapSetting": {
|
||||
"MipGenType": "Box"
|
||||
}
|
||||
},
|
||||
"ios": {
|
||||
"UUID": "{B66395E1-8D0E-4159-989B-FC2B9F091B75}",
|
||||
"Name": "IBLSpecularHigh",
|
||||
"FileMasks": [
|
||||
"_iblspecularcm512"
|
||||
],
|
||||
"SourceColor": "Linear",
|
||||
"DestColor": "Linear",
|
||||
"SuppressEngineReduce": true,
|
||||
"PixelFormat": "R9G9B9E5",
|
||||
"DiscardAlpha": true,
|
||||
"MinTextureSize": 512,
|
||||
"MaxTextureSize": 512,
|
||||
"IsPowerOf2": true,
|
||||
"CubemapSettings": {
|
||||
"Filter": "GGX",
|
||||
"MipAngle": 7.0,
|
||||
"MipSlope": 2.299999952316284,
|
||||
"EdgeFixup": -431602080.0,
|
||||
"SubId": 2000
|
||||
},
|
||||
"MipMapSetting": {
|
||||
"MipGenType": "Box"
|
||||
}
|
||||
},
|
||||
"mac": {
|
||||
"UUID": "{B66395E1-8D0E-4159-989B-FC2B9F091B75}",
|
||||
"Name": "IBLSpecularHigh",
|
||||
"FileMasks": [
|
||||
"_iblspecularcm512"
|
||||
],
|
||||
"SourceColor": "Linear",
|
||||
"DestColor": "Linear",
|
||||
"SuppressEngineReduce": true,
|
||||
"PixelFormat": "R9G9B9E5",
|
||||
"DiscardAlpha": true,
|
||||
"MinTextureSize": 512,
|
||||
"MaxTextureSize": 512,
|
||||
"IsPowerOf2": true,
|
||||
"CubemapSettings": {
|
||||
"Filter": "GGX",
|
||||
"MipAngle": 7.0,
|
||||
"MipSlope": 2.299999952316284,
|
||||
"EdgeFixup": -431602080.0,
|
||||
"SubId": 2000
|
||||
},
|
||||
"MipMapSetting": {
|
||||
"MipGenType": "Box"
|
||||
}
|
||||
},
|
||||
"provo": {
|
||||
"UUID": "{B66395E1-8D0E-4159-989B-FC2B9F091B75}",
|
||||
"Name": "IBLSpecularHigh",
|
||||
"FileMasks": [
|
||||
"_iblspecularcm512"
|
||||
],
|
||||
"SourceColor": "Linear",
|
||||
"DestColor": "Linear",
|
||||
"SuppressEngineReduce": true,
|
||||
"PixelFormat": "R9G9B9E5",
|
||||
"DiscardAlpha": true,
|
||||
"MinTextureSize": 512,
|
||||
"MaxTextureSize": 512,
|
||||
"IsPowerOf2": true,
|
||||
"CubemapSettings": {
|
||||
"Filter": "GGX",
|
||||
"MipAngle": 7.0,
|
||||
"MipSlope": 2.299999952316284,
|
||||
"EdgeFixup": -431602080.0,
|
||||
"SubId": 2000
|
||||
},
|
||||
"MipMapSetting": {
|
||||
"MipGenType": "Box"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
{
|
||||
"Type": "JsonSerialization",
|
||||
"Version": 1,
|
||||
"ClassName": "MultiplatformPresetSettings",
|
||||
"ClassData": {
|
||||
"DefaultPreset": {
|
||||
"UUID": "{7273ACAE-6E34-487C-AF71-99423A6E1CB0}",
|
||||
"Name": "IBLSpecularLow",
|
||||
"Description": "The input cubemap generates an IBL specular output cubemap.",
|
||||
"FileMasks": [
|
||||
"_iblspecularcm128"
|
||||
],
|
||||
"SourceColor": "Linear",
|
||||
"DestColor": "Linear",
|
||||
"SuppressEngineReduce": true,
|
||||
"PixelFormat": "R9G9B9E5",
|
||||
"DiscardAlpha": true,
|
||||
"MinTextureSize": 128,
|
||||
"MaxTextureSize": 128,
|
||||
"IsPowerOf2": true,
|
||||
"CubemapSettings": {
|
||||
"Filter": "GGX",
|
||||
"MipAngle": 7.0,
|
||||
"MipSlope": 2.299999952316284,
|
||||
"EdgeFixup": -431602080.0,
|
||||
"SubId": 2000
|
||||
},
|
||||
"MipMapSetting": {
|
||||
"MipGenType": "Box"
|
||||
}
|
||||
},
|
||||
"PlatformsPresets": {
|
||||
"android": {
|
||||
"UUID": "{7273ACAE-6E34-487C-AF71-99423A6E1CB0}",
|
||||
"Name": "IBLSpecularLow",
|
||||
"FileMasks": [
|
||||
"_iblspecularcm128"
|
||||
],
|
||||
"SourceColor": "Linear",
|
||||
"DestColor": "Linear",
|
||||
"SuppressEngineReduce": true,
|
||||
"PixelFormat": "R9G9B9E5",
|
||||
"DiscardAlpha": true,
|
||||
"MinTextureSize": 128,
|
||||
"MaxTextureSize": 128,
|
||||
"IsPowerOf2": true,
|
||||
"CubemapSettings": {
|
||||
"Filter": "GGX",
|
||||
"MipAngle": 7.0,
|
||||
"MipSlope": 2.299999952316284,
|
||||
"EdgeFixup": -431602080.0,
|
||||
"SubId": 2000
|
||||
},
|
||||
"MipMapSetting": {
|
||||
"MipGenType": "Box"
|
||||
}
|
||||
},
|
||||
"ios": {
|
||||
"UUID": "{7273ACAE-6E34-487C-AF71-99423A6E1CB0}",
|
||||
"Name": "IBLSpecularLow",
|
||||
"FileMasks": [
|
||||
"_iblspecularcm128"
|
||||
],
|
||||
"SourceColor": "Linear",
|
||||
"DestColor": "Linear",
|
||||
"SuppressEngineReduce": true,
|
||||
"PixelFormat": "R9G9B9E5",
|
||||
"DiscardAlpha": true,
|
||||
"MinTextureSize": 128,
|
||||
"MaxTextureSize": 128,
|
||||
"IsPowerOf2": true,
|
||||
"CubemapSettings": {
|
||||
"Filter": "GGX",
|
||||
"MipAngle": 7.0,
|
||||
"MipSlope": 2.299999952316284,
|
||||
"EdgeFixup": -431602080.0,
|
||||
"SubId": 2000
|
||||
},
|
||||
"MipMapSetting": {
|
||||
"MipGenType": "Box"
|
||||
}
|
||||
},
|
||||
"mac": {
|
||||
"UUID": "{7273ACAE-6E34-487C-AF71-99423A6E1CB0}",
|
||||
"Name": "IBLSpecularLow",
|
||||
"FileMasks": [
|
||||
"_iblspecularcm128"
|
||||
],
|
||||
"SourceColor": "Linear",
|
||||
"DestColor": "Linear",
|
||||
"SuppressEngineReduce": true,
|
||||
"PixelFormat": "R9G9B9E5",
|
||||
"DiscardAlpha": true,
|
||||
"MinTextureSize": 128,
|
||||
"MaxTextureSize": 128,
|
||||
"IsPowerOf2": true,
|
||||
"CubemapSettings": {
|
||||
"Filter": "GGX",
|
||||
"MipAngle": 7.0,
|
||||
"MipSlope": 2.299999952316284,
|
||||
"EdgeFixup": -431602080.0,
|
||||
"SubId": 2000
|
||||
},
|
||||
"MipMapSetting": {
|
||||
"MipGenType": "Box"
|
||||
}
|
||||
},
|
||||
"provo": {
|
||||
"UUID": "{7273ACAE-6E34-487C-AF71-99423A6E1CB0}",
|
||||
"Name": "IBLSpecularLow",
|
||||
"FileMasks": [
|
||||
"_iblspecularcm128"
|
||||
],
|
||||
"SourceColor": "Linear",
|
||||
"DestColor": "Linear",
|
||||
"SuppressEngineReduce": true,
|
||||
"PixelFormat": "R9G9B9E5",
|
||||
"DiscardAlpha": true,
|
||||
"MinTextureSize": 128,
|
||||
"MaxTextureSize": 128,
|
||||
"IsPowerOf2": true,
|
||||
"CubemapSettings": {
|
||||
"Filter": "GGX",
|
||||
"MipAngle": 7.0,
|
||||
"MipSlope": 2.299999952316284,
|
||||
"EdgeFixup": -431602080.0,
|
||||
"SubId": 2000
|
||||
},
|
||||
"MipMapSetting": {
|
||||
"MipGenType": "Box"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
{
|
||||
"Type": "JsonSerialization",
|
||||
"Version": 1,
|
||||
"ClassName": "MultiplatformPresetSettings",
|
||||
"ClassData": {
|
||||
"DefaultPreset": {
|
||||
"UUID": "{5CD1AFA6-915B-4716-893C-A5B1F4074C22}",
|
||||
"Name": "IBLSpecularVeryHigh",
|
||||
"Description": "The input cubemap generates an IBL specular output cubemap.",
|
||||
"FileMasks": [
|
||||
"_iblspecularcm1024"
|
||||
],
|
||||
"SourceColor": "Linear",
|
||||
"DestColor": "Linear",
|
||||
"SuppressEngineReduce": true,
|
||||
"PixelFormat": "R9G9B9E5",
|
||||
"DiscardAlpha": true,
|
||||
"MinTextureSize": 1024,
|
||||
"MaxTextureSize": 1024,
|
||||
"IsPowerOf2": true,
|
||||
"CubemapSettings": {
|
||||
"Filter": "GGX",
|
||||
"MipAngle": 7.0,
|
||||
"MipSlope": 2.299999952316284,
|
||||
"EdgeFixup": -431602080.0,
|
||||
"SubId": 2000
|
||||
},
|
||||
"MipMapSetting": {
|
||||
"MipGenType": "Box"
|
||||
}
|
||||
},
|
||||
"PlatformsPresets": {
|
||||
"android": {
|
||||
"UUID": "{5CD1AFA6-915B-4716-893C-A5B1F4074C22}",
|
||||
"Name": "IBLSpecularVeryHigh",
|
||||
"FileMasks": [
|
||||
"_iblspecularcm1024"
|
||||
],
|
||||
"SourceColor": "Linear",
|
||||
"DestColor": "Linear",
|
||||
"SuppressEngineReduce": true,
|
||||
"PixelFormat": "R9G9B9E5",
|
||||
"DiscardAlpha": true,
|
||||
"MinTextureSize": 1024,
|
||||
"MaxTextureSize": 1024,
|
||||
"IsPowerOf2": true,
|
||||
"CubemapSettings": {
|
||||
"Filter": "GGX",
|
||||
"MipAngle": 7.0,
|
||||
"MipSlope": 2.299999952316284,
|
||||
"EdgeFixup": -431602080.0,
|
||||
"SubId": 2000
|
||||
},
|
||||
"MipMapSetting": {
|
||||
"MipGenType": "Box"
|
||||
}
|
||||
},
|
||||
"ios": {
|
||||
"UUID": "{5CD1AFA6-915B-4716-893C-A5B1F4074C22}",
|
||||
"Name": "IBLSpecularVeryHigh",
|
||||
"FileMasks": [
|
||||
"_iblspecularcm1024"
|
||||
],
|
||||
"SourceColor": "Linear",
|
||||
"DestColor": "Linear",
|
||||
"SuppressEngineReduce": true,
|
||||
"PixelFormat": "R9G9B9E5",
|
||||
"DiscardAlpha": true,
|
||||
"MinTextureSize": 1024,
|
||||
"MaxTextureSize": 1024,
|
||||
"IsPowerOf2": true,
|
||||
"CubemapSettings": {
|
||||
"Filter": "GGX",
|
||||
"MipAngle": 7.0,
|
||||
"MipSlope": 2.299999952316284,
|
||||
"EdgeFixup": -431602080.0,
|
||||
"SubId": 2000
|
||||
},
|
||||
"MipMapSetting": {
|
||||
"MipGenType": "Box"
|
||||
}
|
||||
},
|
||||
"mac": {
|
||||
"UUID": "{5CD1AFA6-915B-4716-893C-A5B1F4074C22}",
|
||||
"Name": "IBLSpecularVeryHigh",
|
||||
"FileMasks": [
|
||||
"_iblspecularcm1024"
|
||||
],
|
||||
"SourceColor": "Linear",
|
||||
"DestColor": "Linear",
|
||||
"SuppressEngineReduce": true,
|
||||
"PixelFormat": "R9G9B9E5",
|
||||
"DiscardAlpha": true,
|
||||
"MinTextureSize": 1024,
|
||||
"MaxTextureSize": 1024,
|
||||
"IsPowerOf2": true,
|
||||
"CubemapSettings": {
|
||||
"Filter": "GGX",
|
||||
"MipAngle": 7.0,
|
||||
"MipSlope": 2.299999952316284,
|
||||
"EdgeFixup": -431602080.0,
|
||||
"SubId": 2000
|
||||
},
|
||||
"MipMapSetting": {
|
||||
"MipGenType": "Box"
|
||||
}
|
||||
},
|
||||
"provo": {
|
||||
"UUID": "{5CD1AFA6-915B-4716-893C-A5B1F4074C22}",
|
||||
"Name": "IBLSpecularVeryHigh",
|
||||
"FileMasks": [
|
||||
"_iblspecularcm1024"
|
||||
],
|
||||
"SourceColor": "Linear",
|
||||
"DestColor": "Linear",
|
||||
"SuppressEngineReduce": true,
|
||||
"PixelFormat": "R9G9B9E5",
|
||||
"DiscardAlpha": true,
|
||||
"MinTextureSize": 1024,
|
||||
"MaxTextureSize": 1024,
|
||||
"IsPowerOf2": true,
|
||||
"CubemapSettings": {
|
||||
"Filter": "GGX",
|
||||
"MipAngle": 7.0,
|
||||
"MipSlope": 2.299999952316284,
|
||||
"EdgeFixup": -431602080.0,
|
||||
"SubId": 2000
|
||||
},
|
||||
"MipMapSetting": {
|
||||
"MipGenType": "Box"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
{
|
||||
"Type": "JsonSerialization",
|
||||
"Version": 1,
|
||||
"ClassName": "MultiplatformPresetSettings",
|
||||
"ClassData": {
|
||||
"DefaultPreset": {
|
||||
"UUID": "{8293C236-D3E8-4352-8B18-C2E82EEE6547}",
|
||||
"Name": "IBLSpecularVeryLow",
|
||||
"Description": "The input cubemap generates an IBL specular output cubemap.",
|
||||
"FileMasks": [
|
||||
"_iblspecularcm64"
|
||||
],
|
||||
"SourceColor": "Linear",
|
||||
"DestColor": "Linear",
|
||||
"SuppressEngineReduce": true,
|
||||
"PixelFormat": "R9G9B9E5",
|
||||
"DiscardAlpha": true,
|
||||
"MinTextureSize": 64,
|
||||
"MaxTextureSize": 64,
|
||||
"IsPowerOf2": true,
|
||||
"CubemapSettings": {
|
||||
"Filter": "GGX",
|
||||
"MipAngle": 7.0,
|
||||
"MipSlope": 2.299999952316284,
|
||||
"EdgeFixup": -431602080.0,
|
||||
"SubId": 2000
|
||||
},
|
||||
"MipMapSetting": {
|
||||
"MipGenType": "Box"
|
||||
}
|
||||
},
|
||||
"PlatformsPresets": {
|
||||
"android": {
|
||||
"UUID": "{8293C236-D3E8-4352-8B18-C2E82EEE6547}",
|
||||
"Name": "IBLSpecularVeryLow",
|
||||
"FileMasks": [
|
||||
"_iblspecularcm64"
|
||||
],
|
||||
"SourceColor": "Linear",
|
||||
"DestColor": "Linear",
|
||||
"SuppressEngineReduce": true,
|
||||
"PixelFormat": "R9G9B9E5",
|
||||
"DiscardAlpha": true,
|
||||
"MinTextureSize": 64,
|
||||
"MaxTextureSize": 64,
|
||||
"IsPowerOf2": true,
|
||||
"CubemapSettings": {
|
||||
"Filter": "GGX",
|
||||
"MipAngle": 7.0,
|
||||
"MipSlope": 2.299999952316284,
|
||||
"EdgeFixup": -431602080.0,
|
||||
"SubId": 2000
|
||||
},
|
||||
"MipMapSetting": {
|
||||
"MipGenType": "Box"
|
||||
}
|
||||
},
|
||||
"ios": {
|
||||
"UUID": "{8293C236-D3E8-4352-8B18-C2E82EEE6547}",
|
||||
"Name": "IBLSpecularVeryLow",
|
||||
"FileMasks": [
|
||||
"_iblspecularcm64"
|
||||
],
|
||||
"SourceColor": "Linear",
|
||||
"DestColor": "Linear",
|
||||
"SuppressEngineReduce": true,
|
||||
"PixelFormat": "R9G9B9E5",
|
||||
"DiscardAlpha": true,
|
||||
"MinTextureSize": 64,
|
||||
"MaxTextureSize": 64,
|
||||
"IsPowerOf2": true,
|
||||
"CubemapSettings": {
|
||||
"Filter": "GGX",
|
||||
"MipAngle": 7.0,
|
||||
"MipSlope": 2.299999952316284,
|
||||
"EdgeFixup": -431602080.0,
|
||||
"SubId": 2000
|
||||
},
|
||||
"MipMapSetting": {
|
||||
"MipGenType": "Box"
|
||||
}
|
||||
},
|
||||
"mac": {
|
||||
"UUID": "{8293C236-D3E8-4352-8B18-C2E82EEE6547}",
|
||||
"Name": "IBLSpecularVeryLow",
|
||||
"FileMasks": [
|
||||
"_iblspecularcm64"
|
||||
],
|
||||
"SourceColor": "Linear",
|
||||
"DestColor": "Linear",
|
||||
"SuppressEngineReduce": true,
|
||||
"PixelFormat": "R9G9B9E5",
|
||||
"DiscardAlpha": true,
|
||||
"MinTextureSize": 64,
|
||||
"MaxTextureSize": 64,
|
||||
"IsPowerOf2": true,
|
||||
"CubemapSettings": {
|
||||
"Filter": "GGX",
|
||||
"MipAngle": 7.0,
|
||||
"MipSlope": 2.299999952316284,
|
||||
"EdgeFixup": -431602080.0,
|
||||
"SubId": 2000
|
||||
},
|
||||
"MipMapSetting": {
|
||||
"MipGenType": "Box"
|
||||
}
|
||||
},
|
||||
"provo": {
|
||||
"UUID": "{8293C236-D3E8-4352-8B18-C2E82EEE6547}",
|
||||
"Name": "IBLSpecularVeryLow",
|
||||
"FileMasks": [
|
||||
"_iblspecularcm64"
|
||||
],
|
||||
"SourceColor": "Linear",
|
||||
"DestColor": "Linear",
|
||||
"SuppressEngineReduce": true,
|
||||
"PixelFormat": "R9G9B9E5",
|
||||
"DiscardAlpha": true,
|
||||
"MinTextureSize": 64,
|
||||
"MaxTextureSize": 64,
|
||||
"IsPowerOf2": true,
|
||||
"CubemapSettings": {
|
||||
"Filter": "GGX",
|
||||
"MipAngle": 7.0,
|
||||
"MipSlope": 2.299999952316284,
|
||||
"EdgeFixup": -431602080.0,
|
||||
"SubId": 2000
|
||||
},
|
||||
"MipMapSetting": {
|
||||
"MipGenType": "Box"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1106,7 +1106,7 @@ namespace ImageProcessingAtom
|
||||
//fractional amount to apply change in tap intensity along edge to taps
|
||||
// in a perpendicular direction to edge
|
||||
CP_ITYPE fixupFrac = (CP_ITYPE)(fixupDist - iFixup) / (CP_ITYPE)(fixupDist);
|
||||
CP_ITYPE fixupWeight;
|
||||
CP_ITYPE fixupWeight = 0.0f;
|
||||
|
||||
switch(a_FixupType )
|
||||
{
|
||||
|
||||
@@ -37,7 +37,7 @@ ShaderResourceGroup MaterialSrg : SRG_PerMaterial
|
||||
}
|
||||
|
||||
#include <Atom/Features/PBR/DefaultObjectSrg.azsli>
|
||||
#include <Atom/Features/PBR/TransparentPassSrg.azsli>
|
||||
#include <Atom/Features/PBR/ForwardPassSrg.azsli>
|
||||
#include <Atom/Features/Shadow/DirectionalLightShadow.azsli>
|
||||
#include <Atom/RPI/ShaderResourceGroups/DefaultDrawSrg.azsli>
|
||||
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:a476e99b55cf2a76fef6775c5a57dad29f8ffcb942c625bab04c89051a72a560
|
||||
size 62626
|
||||
oid sha256:838830c99f344f5b68e5e85c9bc52751350caf48e662c9c2b767ab77039bbd8f
|
||||
size 103472
|
||||
|
||||
@@ -124,7 +124,7 @@
|
||||
"DrawListSortType": "KeyThenReverseDepth",
|
||||
"PipelineViewTag": "MainCamera",
|
||||
"PassSrgAsset": {
|
||||
"FilePath": "shaderlib/atom/features/pbr/transparentpasssrg.azsli:PassSrg"
|
||||
"FilePath": "shaderlib/atom/features/pbr/forwardpasssrg.azsli:PassSrg"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,4 +35,5 @@ ShaderResourceGroup PassSrg : SRG_PerPass
|
||||
|
||||
Texture2D<uint4> m_tileLightData;
|
||||
StructuredBuffer<uint> m_lightListRemapped;
|
||||
Texture2D<float> m_linearDepthTexture;
|
||||
}
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
* 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 <Atom/Features/SrgSemantics.azsli>
|
||||
|
||||
ShaderResourceGroup PassSrg : SRG_PerPass
|
||||
{
|
||||
// [GFX TODO][ATOM-2012] adapt to multiple shadowmaps
|
||||
Texture2DArray<float> m_directionalLightShadowmap;
|
||||
Texture2DArray<float> m_directionalLightExponentialShadowmap;
|
||||
Texture2DArray<float> m_projectedShadowmaps;
|
||||
Texture2DArray<float> m_projectedExponentialShadowmap;
|
||||
Texture2D m_brdfMap;
|
||||
|
||||
Sampler LinearSampler
|
||||
{
|
||||
MinFilter = Linear;
|
||||
MagFilter = Linear;
|
||||
MipFilter = Linear;
|
||||
AddressU = Clamp;
|
||||
AddressV = Clamp;
|
||||
AddressW = Clamp;
|
||||
};
|
||||
|
||||
Texture2D<uint4> m_tileLightData;
|
||||
StructuredBuffer<uint> m_lightListRemapped;
|
||||
Texture2D<float> m_linearDepthTexture;
|
||||
}
|
||||
@@ -246,7 +246,6 @@ set(FILES
|
||||
ShaderLib/Atom/Features/PBR/Hammersley.azsli
|
||||
ShaderLib/Atom/Features/PBR/LightingOptions.azsli
|
||||
ShaderLib/Atom/Features/PBR/LightingUtils.azsli
|
||||
ShaderLib/Atom/Features/PBR/TransparentPassSrg.azsli
|
||||
ShaderLib/Atom/Features/PBR/Lighting/DualSpecularLighting.azsli
|
||||
ShaderLib/Atom/Features/PBR/Lighting/EnhancedLighting.azsli
|
||||
ShaderLib/Atom/Features/PBR/Lighting/LightingData.azsli
|
||||
|
||||
-2
@@ -46,8 +46,6 @@ namespace AZ
|
||||
uint16_t m_padding; // Explicit padding.
|
||||
};
|
||||
|
||||
static constexpr size_t size = sizeof(DiskLightData);
|
||||
|
||||
//! DiskLightFeatureProcessorInterface provides an interface to acquire, release, and update a disk light. This is necessary for code outside of
|
||||
//! the Atom features gem to communicate with the DiskLightFeatureProcessor.
|
||||
class DiskLightFeatureProcessorInterface
|
||||
|
||||
@@ -484,6 +484,7 @@ namespace AZ
|
||||
}
|
||||
|
||||
D3D12_RESOURCE_TRANSITION_BARRIER transition;
|
||||
memset(&transition, 0, sizeof(D3D12_RESOURCE_TRANSITION_BARRIER)); // C4701 potentially unitialized local variable 'transition' used
|
||||
transition.pResource = image.GetMemoryView().GetMemory();
|
||||
|
||||
Scope& firstScope = static_cast<Scope&>(scopeAttachment->GetScope());
|
||||
|
||||
@@ -45,7 +45,7 @@ namespace AZ
|
||||
Fence* fenceToSignal)
|
||||
{
|
||||
AZStd::vector<VkCommandBuffer> vkCommandBuffers;
|
||||
AZStd::vector<VkSemaphore> vkWaitSemaphores;
|
||||
AZStd::vector<VkSemaphore> vkWaitSemaphoreVector; // vulkan.h has a #define called vkWaitSemaphores, so we name this differently
|
||||
AZStd::vector<VkPipelineStageFlags> vkWaitPipelineStages;
|
||||
AZStd::vector<VkSemaphore> vkSignalSemaphores;
|
||||
VkSubmitInfo submitInfo;
|
||||
@@ -65,11 +65,11 @@ namespace AZ
|
||||
return item->GetNativeSemaphore();
|
||||
});
|
||||
vkWaitPipelineStages.reserve(waitSemaphoresInfo.size());
|
||||
vkWaitSemaphores.reserve(waitSemaphoresInfo.size());
|
||||
vkWaitSemaphoreVector.reserve(waitSemaphoresInfo.size());
|
||||
AZStd::for_each(waitSemaphoresInfo.begin(), waitSemaphoresInfo.end(), [&](auto& item)
|
||||
{
|
||||
vkWaitPipelineStages.push_back(item.first);
|
||||
vkWaitSemaphores.push_back(item.second->GetNativeSemaphore());
|
||||
vkWaitSemaphoreVector.push_back(item.second->GetNativeSemaphore());
|
||||
// Wait until the wait semaphores has been submitted for signaling.
|
||||
item.second->WaitEvent();
|
||||
});
|
||||
@@ -77,8 +77,8 @@ namespace AZ
|
||||
submitInfo = {};
|
||||
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
||||
submitInfo.pNext = nullptr;
|
||||
submitInfo.waitSemaphoreCount = static_cast<uint32_t>(vkWaitSemaphores.size());
|
||||
submitInfo.pWaitSemaphores = vkWaitSemaphores.empty() ? nullptr : vkWaitSemaphores.data();
|
||||
submitInfo.waitSemaphoreCount = static_cast<uint32_t>(vkWaitSemaphoreVector.size());
|
||||
submitInfo.pWaitSemaphores = vkWaitSemaphoreVector.empty() ? nullptr : vkWaitSemaphoreVector.data();
|
||||
submitInfo.pWaitDstStageMask = vkWaitPipelineStages.empty() ? nullptr : vkWaitPipelineStages.data();
|
||||
submitInfo.commandBufferCount = static_cast<uint32_t>(vkCommandBuffers.size());
|
||||
submitInfo.pCommandBuffers = vkCommandBuffers.empty() ? nullptr : vkCommandBuffers.data();
|
||||
|
||||
@@ -239,16 +239,26 @@ namespace AZ
|
||||
|
||||
void CullingScene::RegisterOrUpdateCullable(Cullable& cullable)
|
||||
{
|
||||
m_cullDataConcurrencyCheck.soft_lock();
|
||||
// Multiple threads can call RegisterOrUpdateCullable at the same time
|
||||
// since the underlying visScene is thread safe, but if you're inserting or
|
||||
// updating between BeginCulling and EndCulling, you'll get non-deterministic
|
||||
// results depending on a race condition if you happen to update before or after
|
||||
// the culling system starts Enumerating, so use soft_lock_shared here
|
||||
m_cullDataConcurrencyCheck.soft_lock_shared();
|
||||
m_visScene->InsertOrUpdateEntry(cullable.m_cullData.m_visibilityEntry);
|
||||
m_cullDataConcurrencyCheck.soft_unlock();
|
||||
m_cullDataConcurrencyCheck.soft_unlock_shared();
|
||||
}
|
||||
|
||||
void CullingScene::UnregisterCullable(Cullable& cullable)
|
||||
{
|
||||
m_cullDataConcurrencyCheck.soft_lock();
|
||||
// Multiple threads can call RegisterOrUpdateCullable at the same time
|
||||
// since the underlying visScene is thread safe, but if you're inserting or
|
||||
// updating between BeginCulling and EndCulling, you'll get non-deterministic
|
||||
// results depending on a race condition if you happen to update before or after
|
||||
// the culling system starts Enumerating, so use soft_lock_shared here
|
||||
m_cullDataConcurrencyCheck.soft_lock_shared();
|
||||
m_visScene->RemoveEntry(cullable.m_cullData.m_visibilityEntry);
|
||||
m_cullDataConcurrencyCheck.soft_unlock();
|
||||
m_cullDataConcurrencyCheck.soft_unlock_shared();
|
||||
}
|
||||
|
||||
uint32_t CullingScene::GetNumCullables() const
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
*
|
||||
*/
|
||||
#include <Atom/RPI.Reflect/Shader/ShaderAsset.h>
|
||||
#include <Atom/RPI.Reflect/Shader/ShaderCommonTypes.h>
|
||||
|
||||
#include <AzCore/Casting/numeric_cast.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
@@ -34,10 +35,6 @@ namespace AZ
|
||||
|
||||
uint32_t ShaderAsset::MakeAssetProductSubId(uint32_t rhiApiUniqueIndex, uint32_t subProductType)
|
||||
{
|
||||
static constexpr uint32_t RhiIndexBitPosition = 30;
|
||||
static constexpr uint32_t RhiIndexNumBits = 32 - RhiIndexBitPosition;
|
||||
static constexpr uint32_t RhiIndexMaxValue = (1 << RhiIndexNumBits) - 1;
|
||||
|
||||
static constexpr uint32_t SubProductTypeBitPosition = 0;
|
||||
static constexpr uint32_t SubProductTypeNumBits = RhiIndexBitPosition - SubProductTypeBitPosition;
|
||||
static constexpr uint32_t SubProductTypeMaxValue = (1 << SubProductTypeNumBits) - 1;
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
*
|
||||
*/
|
||||
#include <Atom/RPI.Reflect/Shader/ShaderVariantAsset.h>
|
||||
#include <Atom/RPI.Reflect/Shader/ShaderCommonTypes.h>
|
||||
|
||||
#include <AzCore/Casting/numeric_cast.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
@@ -24,10 +25,6 @@ namespace AZ
|
||||
uint32_t ShaderVariantAsset::MakeAssetProductSubId(
|
||||
uint32_t rhiApiUniqueIndex, ShaderVariantStableId variantStableId, uint32_t subProductType)
|
||||
{
|
||||
static constexpr uint32_t RhiIndexBitPosition = 30;
|
||||
static constexpr uint32_t RhiIndexNumBits = 32 - RhiIndexBitPosition;
|
||||
static constexpr uint32_t RhiIndexMaxValue = (1 << RhiIndexNumBits) - 1;
|
||||
|
||||
static constexpr uint32_t SubProductTypeBitPosition = 17;
|
||||
static constexpr uint32_t SubProductTypeNumBits = RhiIndexBitPosition - SubProductTypeBitPosition;
|
||||
static constexpr uint32_t SubProductTypeMaxValue = (1 << SubProductTypeNumBits) - 1;
|
||||
|
||||
+4
-1
@@ -51,7 +51,8 @@ namespace AtomToolsFramework
|
||||
void UpdateViewport(const AzFramework::ViewportControllerUpdateEvent& event) override;
|
||||
|
||||
// ModularViewportCameraControllerRequestBus overrides ...
|
||||
void InterpolateToTransform(const AZ::Transform& worldFromLocal) override;
|
||||
void InterpolateToTransform(const AZ::Transform& worldFromLocal, float lookAtDistance) override;
|
||||
AZStd::optional<AZ::Vector3> LookAtAfterInterpolation() const override;
|
||||
|
||||
private:
|
||||
// AzFramework::ViewportDebugDisplayEventBus overrides ...
|
||||
@@ -71,6 +72,8 @@ namespace AtomToolsFramework
|
||||
AZ::Transform m_transformEnd = AZ::Transform::CreateIdentity();
|
||||
float m_animationT = 0.0f;
|
||||
CameraMode m_cameraMode = CameraMode::Control;
|
||||
AZStd::optional<AZ::Vector3> m_lookAtAfterInterpolation; //!< The look at point after an interpolation has finished.
|
||||
//!< Will be cleared when the view changes (camera looks away).
|
||||
bool m_updatingTransform = false;
|
||||
|
||||
AZ::RPI::ViewportContext::MatrixChangedEvent::Handler m_cameraViewMatrixChangeHandler;
|
||||
|
||||
+6
-1
@@ -32,7 +32,12 @@ namespace AtomToolsFramework
|
||||
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
|
||||
|
||||
//! Begin a smooth transition of the camera to the requested transform.
|
||||
virtual void InterpolateToTransform(const AZ::Transform& worldFromLocal) = 0;
|
||||
//! @param worldFromLocal The transform of where the camera should end up.
|
||||
//! @param lookAtDistance The distance between the camera transform and the imagined look at point.
|
||||
virtual void InterpolateToTransform(const AZ::Transform& worldFromLocal, float lookAtDistance) = 0;
|
||||
|
||||
//! Look at point after an interpolation has finished and no translation has occurred.
|
||||
virtual AZStd::optional<AZ::Vector3> LookAtAfterInterpolation() const = 0;
|
||||
|
||||
protected:
|
||||
~ModularViewportCameraControllerRequests() = default;
|
||||
|
||||
+20
-2
@@ -140,6 +140,18 @@ namespace AtomToolsFramework
|
||||
m_targetCamera = m_cameraSystem.StepCamera(m_targetCamera, event.m_deltaTime.count());
|
||||
m_camera = AzFramework::SmoothCamera(m_camera, m_targetCamera, event.m_deltaTime.count());
|
||||
|
||||
// if there has been an interpolation, only clear the look at point if it is no longer
|
||||
// centered in the view (the camera has looked away from it)
|
||||
if (m_lookAtAfterInterpolation.has_value())
|
||||
{
|
||||
if (const float lookDirection =
|
||||
(*m_lookAtAfterInterpolation - m_camera.Translation()).GetNormalized().Dot(m_camera.Transform().GetBasisY());
|
||||
!AZ::IsCloseMag(lookDirection, 1.0f, 0.001f))
|
||||
{
|
||||
m_lookAtAfterInterpolation = {};
|
||||
}
|
||||
}
|
||||
|
||||
viewportContext->SetCameraTransform(m_camera.Transform());
|
||||
}
|
||||
else if (m_cameraMode == CameraMode::Animation)
|
||||
@@ -148,8 +160,8 @@ namespace AtomToolsFramework
|
||||
{
|
||||
return t * t * t * (t * (t * 6.0f - 15.0f) + 10.0f);
|
||||
};
|
||||
const float transitionT = smootherStepFn(m_animationT);
|
||||
|
||||
const float transitionT = smootherStepFn(m_animationT);
|
||||
const AZ::Transform current = AZ::Transform::CreateFromQuaternionAndTranslation(
|
||||
m_transformStart.GetRotation().Slerp(m_transformEnd.GetRotation(), transitionT),
|
||||
m_transformStart.GetTranslation().Lerp(m_transformEnd.GetTranslation(), transitionT));
|
||||
@@ -185,11 +197,17 @@ namespace AtomToolsFramework
|
||||
}
|
||||
}
|
||||
|
||||
void ModernViewportCameraControllerInstance::InterpolateToTransform(const AZ::Transform& worldFromLocal)
|
||||
void ModernViewportCameraControllerInstance::InterpolateToTransform(const AZ::Transform& worldFromLocal, const float lookAtDistance)
|
||||
{
|
||||
m_animationT = 0.0f;
|
||||
m_cameraMode = CameraMode::Animation;
|
||||
m_transformStart = m_camera.Transform();
|
||||
m_transformEnd = worldFromLocal;
|
||||
m_lookAtAfterInterpolation = m_transformEnd.GetTranslation() + m_transformEnd.GetBasisY() * lookAtDistance;
|
||||
}
|
||||
|
||||
AZStd::optional<AZ::Vector3> ModernViewportCameraControllerInstance::LookAtAfterInterpolation() const
|
||||
{
|
||||
return m_lookAtAfterInterpolation;
|
||||
}
|
||||
} // namespace AtomToolsFramework
|
||||
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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/EBus/EBus.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace LyIntegration
|
||||
{
|
||||
namespace Thumbnails
|
||||
{
|
||||
//! ThumbnailFeatureProcessorProviderRequests allows registering custom Feature Processors for thumbnail generation
|
||||
//! Duplicates will be ignored
|
||||
//! You can check minimal feature processors that are already registered in CommonThumbnailRenderer.cpp
|
||||
class ThumbnailFeatureProcessorProviderRequests
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
//! Get a list of custom feature processors to register with thumbnail renderer
|
||||
virtual const AZStd::vector<AZStd::string>& GetCustomFeatureProcessors() const = 0;
|
||||
};
|
||||
|
||||
using ThumbnailFeatureProcessorProviderBus = AZ::EBus<ThumbnailFeatureProcessorProviderRequests>;
|
||||
} // namespace Thumbnails
|
||||
} // namespace LyIntegration
|
||||
} // namespace AZ
|
||||
+19
-1
@@ -39,6 +39,7 @@ namespace AZ
|
||||
serializeContext->Class<EditorReflectionProbeComponent, BaseClass>()
|
||||
->Version(2, ConvertToEditorRenderComponentAdapter<1>)
|
||||
->Field("useBakedCubemap", &EditorReflectionProbeComponent::m_useBakedCubemap)
|
||||
->Field("bakedCubeMapQualityLevel", &EditorReflectionProbeComponent::m_bakedCubeMapQualityLevel)
|
||||
->Field("bakedCubeMapRelativePath", &EditorReflectionProbeComponent::m_bakedCubeMapRelativePath)
|
||||
->Field("authoredCubeMapAsset", &EditorReflectionProbeComponent::m_authoredCubeMapAsset)
|
||||
;
|
||||
@@ -67,6 +68,13 @@ namespace AZ
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &EditorReflectionProbeComponent::m_useBakedCubemap, "Use Baked Cubemap", "Selects between a cubemap that captures the environment at location in the scene or a preauthored cubemap")
|
||||
->Attribute(AZ::Edit::Attributes::ChangeValidate, &EditorReflectionProbeComponent::OnUseBakedCubemapValidate)
|
||||
->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorReflectionProbeComponent::OnUseBakedCubemapChanged)
|
||||
->DataElement(AZ::Edit::UIHandlers::ComboBox, &EditorReflectionProbeComponent::m_bakedCubeMapQualityLevel, "Baked Cubemap Quality", "Resolution of the baked cubemap")
|
||||
->Attribute(AZ::Edit::Attributes::Visibility, &EditorReflectionProbeComponent::GetBakedCubemapVisibilitySetting)
|
||||
->EnumAttribute(BakedCubeMapQualityLevel::VeryLow, "Very Low")
|
||||
->EnumAttribute(BakedCubeMapQualityLevel::Low, "Low")
|
||||
->EnumAttribute(BakedCubeMapQualityLevel::Medium, "Medium")
|
||||
->EnumAttribute(BakedCubeMapQualityLevel::High, "High")
|
||||
->EnumAttribute(BakedCubeMapQualityLevel::VeryHigh, "Very High")
|
||||
->DataElement(AZ::Edit::UIHandlers::MultiLineEdit, &EditorReflectionProbeComponent::m_bakedCubeMapRelativePath, "Baked Cubemap Path", "Baked Cubemap Path")
|
||||
->Attribute(AZ::Edit::Attributes::ReadOnly, true)
|
||||
->Attribute(AZ::Edit::Attributes::Visibility, &EditorReflectionProbeComponent::GetBakedCubemapVisibilitySetting)
|
||||
@@ -332,6 +340,12 @@ namespace AZ
|
||||
// clear it to force the generation of a new filename
|
||||
cubeMapRelativePath.clear();
|
||||
}
|
||||
|
||||
// if the quality level changed we need to generate a new filename
|
||||
if (m_controller.m_configuration.m_bakedCubeMapQualityLevel != m_bakedCubeMapQualityLevel)
|
||||
{
|
||||
cubeMapRelativePath.clear();
|
||||
}
|
||||
}
|
||||
|
||||
// build a new cubemap path if necessary
|
||||
@@ -345,7 +359,10 @@ namespace AZ
|
||||
AZStd::string uuidString;
|
||||
uuid.ToString(uuidString);
|
||||
|
||||
cubeMapRelativePath = "ReflectionProbes/" + entity->GetName() + "_" + uuidString + "_iblspecularcm.dds";
|
||||
// determine the filemask suffix from the cubemap quality level setting
|
||||
AZStd::string fileSuffix = BakedCubeMapFileSuffixes[aznumeric_cast<uint32_t>(m_bakedCubeMapQualityLevel)];
|
||||
|
||||
cubeMapRelativePath = "ReflectionProbes/" + entity->GetName() + "_" + uuidString + fileSuffix;
|
||||
|
||||
// replace any invalid filename characters
|
||||
auto invalidCharacters = [](char letter)
|
||||
@@ -384,6 +401,7 @@ namespace AZ
|
||||
// save the relative source path in the configuration
|
||||
AzToolsFramework::ScopedUndoBatch undoBatch("Cubemap path changed.");
|
||||
m_controller.m_configuration.m_bakedCubeMapRelativePath = cubeMapRelativePath;
|
||||
m_controller.m_configuration.m_bakedCubeMapQualityLevel = m_bakedCubeMapQualityLevel;
|
||||
SetDirty();
|
||||
|
||||
// update UI cubemap path display
|
||||
|
||||
+1
@@ -77,6 +77,7 @@ namespace AZ
|
||||
// UI settings
|
||||
// the user can select between a baked cubemap or an authored cubemap asset
|
||||
bool m_useBakedCubemap = true;
|
||||
BakedCubeMapQualityLevel m_bakedCubeMapQualityLevel = BakedCubeMapQualityLevel::Medium;
|
||||
AZStd::string m_bakedCubeMapRelativePath;
|
||||
Data::Asset<RPI::StreamingImageAsset> m_bakedCubeMapAsset;
|
||||
Data::Asset<RPI::StreamingImageAsset> m_authoredCubeMapAsset;
|
||||
|
||||
+1
@@ -46,6 +46,7 @@ namespace AZ
|
||||
->Field("InnerLength", &ReflectionProbeComponentConfig::m_innerLength)
|
||||
->Field("InnerWidth", &ReflectionProbeComponentConfig::m_innerWidth)
|
||||
->Field("UseBakedCubemap", &ReflectionProbeComponentConfig::m_useBakedCubemap)
|
||||
->Field("BakedCubemapQualityLevel", &ReflectionProbeComponentConfig::m_bakedCubeMapQualityLevel)
|
||||
->Field("BakedCubeMapRelativePath", &ReflectionProbeComponentConfig::m_bakedCubeMapRelativePath)
|
||||
->Field("BakedCubeMapAsset", &ReflectionProbeComponentConfig::m_bakedCubeMapAsset)
|
||||
->Field("AuthoredCubeMapAsset", &ReflectionProbeComponentConfig::m_authoredCubeMapAsset)
|
||||
|
||||
+24
@@ -24,6 +24,29 @@ namespace AZ
|
||||
{
|
||||
namespace Render
|
||||
{
|
||||
enum class BakedCubeMapQualityLevel : uint32_t
|
||||
{
|
||||
VeryLow, // 64
|
||||
Low, // 128
|
||||
Medium, // 256
|
||||
High, // 512
|
||||
VeryHigh, // 1024
|
||||
|
||||
Count
|
||||
};
|
||||
|
||||
static const char* BakedCubeMapFileSuffixes[] =
|
||||
{
|
||||
"_iblspecularcm64.dds",
|
||||
"_iblspecularcm128.dds",
|
||||
"_iblspecularcm256.dds",
|
||||
"_iblspecularcm512.dds",
|
||||
"_iblspecularcm1024.dds"
|
||||
};
|
||||
|
||||
static_assert(AZ_ARRAY_SIZE(BakedCubeMapFileSuffixes) == aznumeric_cast<uint32_t>(BakedCubeMapQualityLevel::Count),
|
||||
"BakedCubeMapFileSuffixes must have the same number of entries as BakedCubeMapQualityLevel");
|
||||
|
||||
class ReflectionProbeComponentConfig final
|
||||
: public AZ::ComponentConfig
|
||||
{
|
||||
@@ -43,6 +66,7 @@ namespace AZ
|
||||
bool m_showVisualization = true;
|
||||
bool m_useBakedCubemap = true;
|
||||
|
||||
BakedCubeMapQualityLevel m_bakedCubeMapQualityLevel = BakedCubeMapQualityLevel::Medium;
|
||||
AZStd::string m_bakedCubeMapRelativePath;
|
||||
Data::Asset<RPI::StreamingImageAsset> m_bakedCubeMapAsset;
|
||||
Data::Asset<RPI::StreamingImageAsset> m_authoredCubeMapAsset;
|
||||
|
||||
+28
@@ -34,12 +34,34 @@ namespace AZ
|
||||
AzToolsFramework::Thumbnailer::ThumbnailerRendererRequestBus::MultiHandler::BusConnect(RPI::MaterialAsset::RTTI_Type());
|
||||
AzToolsFramework::Thumbnailer::ThumbnailerRendererRequestBus::MultiHandler::BusConnect(RPI::ModelAsset::RTTI_Type());
|
||||
SystemTickBus::Handler::BusConnect();
|
||||
ThumbnailFeatureProcessorProviderBus::Handler::BusConnect();
|
||||
|
||||
m_steps[Step::Initialize] = AZStd::make_shared<InitializeStep>(this);
|
||||
m_steps[Step::FindThumbnailToRender] = AZStd::make_shared<FindThumbnailToRenderStep>(this);
|
||||
m_steps[Step::WaitForAssetsToLoad] = AZStd::make_shared<WaitForAssetsToLoadStep>(this);
|
||||
m_steps[Step::Capture] = AZStd::make_shared<CaptureStep>(this);
|
||||
m_steps[Step::ReleaseResources] = AZStd::make_shared<ReleaseResourcesStep>(this);
|
||||
|
||||
m_minimalFeatureProcessors =
|
||||
{
|
||||
"AZ::Render::TransformServiceFeatureProcessor",
|
||||
"AZ::Render::MeshFeatureProcessor",
|
||||
"AZ::Render::SimplePointLightFeatureProcessor",
|
||||
"AZ::Render::SimpleSpotLightFeatureProcessor",
|
||||
"AZ::Render::PointLightFeatureProcessor",
|
||||
// There is currently a bug where having multiple DirectionalLightFeatureProcessors active can result in shadow
|
||||
// flickering [ATOM-13568]
|
||||
// as well as continually rebuilding MeshDrawPackets [ATOM-13633]. Lets just disable the directional light FP for now.
|
||||
// Possibly re-enable with [GFX TODO][ATOM-13639]
|
||||
// "AZ::Render::DirectionalLightFeatureProcessor",
|
||||
"AZ::Render::DiskLightFeatureProcessor",
|
||||
"AZ::Render::CapsuleLightFeatureProcessor",
|
||||
"AZ::Render::QuadLightFeatureProcessor",
|
||||
"AZ::Render::DecalTextureArrayFeatureProcessor",
|
||||
"AZ::Render::ImageBasedLightFeatureProcessor",
|
||||
"AZ::Render::PostProcessFeatureProcessor",
|
||||
"AZ::Render::SkyBoxFeatureProcessor"
|
||||
};
|
||||
}
|
||||
|
||||
CommonThumbnailRenderer::~CommonThumbnailRenderer()
|
||||
@@ -50,6 +72,7 @@ namespace AZ
|
||||
}
|
||||
AzToolsFramework::Thumbnailer::ThumbnailerRendererRequestBus::MultiHandler::BusDisconnect();
|
||||
SystemTickBus::Handler::BusDisconnect();
|
||||
ThumbnailFeatureProcessorProviderBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
void CommonThumbnailRenderer::SetStep(Step step)
|
||||
@@ -77,6 +100,11 @@ namespace AZ
|
||||
AzToolsFramework::Thumbnailer::ThumbnailerRendererRequestBus::ExecuteQueuedEvents();
|
||||
}
|
||||
|
||||
const AZStd::vector<AZStd::string>& CommonThumbnailRenderer::GetCustomFeatureProcessors() const
|
||||
{
|
||||
return m_minimalFeatureProcessors;
|
||||
}
|
||||
|
||||
AZStd::shared_ptr<ThumbnailRendererData> CommonThumbnailRenderer::GetData() const
|
||||
{
|
||||
return m_data;
|
||||
|
||||
+9
-2
@@ -17,6 +17,8 @@
|
||||
#include <Thumbnails/Rendering/ThumbnailRendererContext.h>
|
||||
#include <Thumbnails/Rendering/ThumbnailRendererData.h>
|
||||
|
||||
#include <AtomLyIntegration/CommonFeatures/Thumbnails/ThumbnailFeatureProcessorProviderBus.h>
|
||||
|
||||
// Disables warning messages triggered by the Qt library
|
||||
// 4251: class needs to have dll-interface to be used by clients of class
|
||||
// 4800: forcing value to bool 'true' or 'false' (performance warning)
|
||||
@@ -34,9 +36,10 @@ namespace AZ
|
||||
|
||||
//! Provides custom rendering of material and model thumbnails
|
||||
class CommonThumbnailRenderer
|
||||
: private AzToolsFramework::Thumbnailer::ThumbnailerRendererRequestBus::MultiHandler
|
||||
: public ThumbnailRendererContext
|
||||
, private AzToolsFramework::Thumbnailer::ThumbnailerRendererRequestBus::MultiHandler
|
||||
, private SystemTickBus::Handler
|
||||
, public ThumbnailRendererContext
|
||||
, private ThumbnailFeatureProcessorProviderBus::Handler
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(CommonThumbnailRenderer, AZ::SystemAllocator, 0)
|
||||
@@ -57,9 +60,13 @@ namespace AZ
|
||||
//! SystemTickBus::Handler interface overrides...
|
||||
void OnSystemTick() override;
|
||||
|
||||
//! Render::ThumbnailFeatureProcessorProviderBus::Handler interface overrides...
|
||||
const AZStd::vector<AZStd::string>& GetCustomFeatureProcessors() const override;
|
||||
|
||||
AZStd::unordered_map<Step, AZStd::shared_ptr<ThumbnailRendererStep>> m_steps;
|
||||
Step m_currentStep = Step::None;
|
||||
AZStd::shared_ptr<ThumbnailRendererData> m_data;
|
||||
AZStd::vector<AZStd::string> m_minimalFeatureProcessors;
|
||||
};
|
||||
} // namespace Thumbnails
|
||||
} // namespace LyIntegration
|
||||
|
||||
+25
-20
@@ -11,10 +11,16 @@
|
||||
*/
|
||||
|
||||
|
||||
#include <AzCore/Math/MatrixUtils.h>
|
||||
#include <AzCore/EBus/Results.h>
|
||||
|
||||
#include <AzFramework/Components/TransformComponent.h>
|
||||
|
||||
#include <Atom/Feature/ImageBasedLights/ImageBasedLightFeatureProcessorInterface.h>
|
||||
#include <Atom/Feature/PostProcess/PostProcessFeatureProcessorInterface.h>
|
||||
#include <Atom/Feature/SkyBox/SkyBoxFeatureProcessorInterface.h>
|
||||
#include <Atom/Feature/Utils/LightingPreset.h>
|
||||
|
||||
#include <Atom/RPI.Public/RenderPipeline.h>
|
||||
#include <Atom/RPI.Public/Scene.h>
|
||||
#include <Atom/RPI.Public/View.h>
|
||||
@@ -23,10 +29,11 @@
|
||||
#include <Atom/RPI.Reflect/Model/ModelAsset.h>
|
||||
#include <Atom/RPI.Reflect/System/RenderPipelineDescriptor.h>
|
||||
#include <Atom/RPI.Reflect/System/SceneDescriptor.h>
|
||||
|
||||
#include <AtomLyIntegration/CommonFeatures/Material/MaterialComponentConstants.h>
|
||||
#include <AtomLyIntegration/CommonFeatures/Mesh/MeshComponentConstants.h>
|
||||
#include <AzCore/Math/MatrixUtils.h>
|
||||
#include <AzFramework/Components/TransformComponent.h>
|
||||
#include <AtomLyIntegration/CommonFeatures/Thumbnails/ThumbnailFeatureProcessorProviderBus.h>
|
||||
|
||||
#include <Thumbnails/Rendering/ThumbnailRendererData.h>
|
||||
#include <Thumbnails/Rendering/ThumbnailRendererContext.h>
|
||||
#include <Thumbnails/Rendering/ThumbnailRendererSteps/InitializeStep.h>
|
||||
@@ -37,7 +44,6 @@ namespace AZ
|
||||
{
|
||||
namespace Thumbnails
|
||||
{
|
||||
|
||||
InitializeStep::InitializeStep(ThumbnailRendererContext* context)
|
||||
: ThumbnailRendererStep(context)
|
||||
{
|
||||
@@ -50,24 +56,23 @@ namespace AZ
|
||||
data->m_entityContext = AZStd::make_unique<AzFramework::EntityContext>();
|
||||
data->m_entityContext->InitContext();
|
||||
|
||||
// Create and register a scene with minimum required feature processors
|
||||
// Create and register a scene with all required feature processors
|
||||
RPI::SceneDescriptor sceneDesc;
|
||||
sceneDesc.m_featureProcessorNames.push_back("AZ::Render::TransformServiceFeatureProcessor");
|
||||
sceneDesc.m_featureProcessorNames.push_back("AZ::Render::MeshFeatureProcessor");
|
||||
sceneDesc.m_featureProcessorNames.push_back("AZ::Render::SimplePointLightFeatureProcessor");
|
||||
sceneDesc.m_featureProcessorNames.push_back("AZ::Render::SimpleSpotLightFeatureProcessor");
|
||||
sceneDesc.m_featureProcessorNames.push_back("AZ::Render::PointLightFeatureProcessor");
|
||||
// There is currently a bug where having multiple DirectionalLightFeatureProcessors active can result in shadow flickering [ATOM-13568]
|
||||
// as well as continually rebuilding MeshDrawPackets [ATOM-13633]. Lets just disable the directional light FP for now.
|
||||
// Possibly re-enable with [GFX TODO][ATOM-13639]
|
||||
// sceneDesc.m_featureProcessorNames.push_back("AZ::Render::DirectionalLightFeatureProcessor");
|
||||
sceneDesc.m_featureProcessorNames.push_back("AZ::Render::DiskLightFeatureProcessor");
|
||||
sceneDesc.m_featureProcessorNames.push_back("AZ::Render::CapsuleLightFeatureProcessor");
|
||||
sceneDesc.m_featureProcessorNames.push_back("AZ::Render::QuadLightFeatureProcessor");
|
||||
sceneDesc.m_featureProcessorNames.push_back("AZ::Render::DecalTextureArrayFeatureProcessor");
|
||||
sceneDesc.m_featureProcessorNames.push_back("AZ::Render::ImageBasedLightFeatureProcessor");
|
||||
sceneDesc.m_featureProcessorNames.push_back("AZ::Render::PostProcessFeatureProcessor");
|
||||
sceneDesc.m_featureProcessorNames.push_back("AZ::Render::SkyBoxFeatureProcessor");
|
||||
|
||||
AZ::EBusAggregateResults<AZStd::vector<AZStd::string>> results;
|
||||
ThumbnailFeatureProcessorProviderBus::BroadcastResult(results, &ThumbnailFeatureProcessorProviderBus::Handler::GetCustomFeatureProcessors);
|
||||
|
||||
AZStd::set<AZStd::string> featureProcessorNames;
|
||||
for (auto& resultCollection : results.values)
|
||||
{
|
||||
for (auto& featureProcessorName : resultCollection)
|
||||
{
|
||||
if (featureProcessorNames.emplace(featureProcessorName).second)
|
||||
{
|
||||
sceneDesc.m_featureProcessorNames.push_back(featureProcessorName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data->m_scene = RPI::Scene::CreateScene(sceneDesc);
|
||||
|
||||
|
||||
+3
-2
@@ -10,11 +10,12 @@
|
||||
#
|
||||
|
||||
set(FILES
|
||||
Include/AtomLyIntegration/CommonFeatures/Material/EditorMaterialSystemComponentRequestBus.h
|
||||
Include/AtomLyIntegration/CommonFeatures/ReflectionProbe/EditorReflectionProbeBus.h
|
||||
Include/AtomLyIntegration/CommonFeatures/Thumbnails/ThumbnailFeatureProcessorProviderBus.h
|
||||
Source/Module.cpp
|
||||
Source/Animation/EditorAttachmentComponent.h
|
||||
Source/Animation/EditorAttachmentComponent.cpp
|
||||
Include/AtomLyIntegration/CommonFeatures/Material/EditorMaterialSystemComponentRequestBus.h
|
||||
Include/AtomLyIntegration/CommonFeatures/ReflectionProbe/EditorReflectionProbeBus.h
|
||||
Source/EditorCommonFeaturesSystemComponent.h
|
||||
Source/EditorCommonFeaturesSystemComponent.cpp
|
||||
Source/CoreLights/EditorAreaLightComponent.h
|
||||
|
||||
@@ -9,6 +9,10 @@
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
#
|
||||
|
||||
if(NOT PAL_TRAIT_BUILD_HOST_TOOLS)
|
||||
return()
|
||||
endif()
|
||||
|
||||
ly_add_target(
|
||||
NAME DccScriptingInterface.Static STATIC
|
||||
NAMESPACE Gem
|
||||
@@ -38,3 +42,9 @@ ly_add_target(
|
||||
PRIVATE
|
||||
Gem::DccScriptingInterface.Static
|
||||
)
|
||||
|
||||
# Any 'tool' type applications should use Gem::DccScriptingInterface.Editor:
|
||||
ly_create_alias(NAME DccScriptingInterface.Tools NAMESPACE Gem TARGETS Gem::DccScriptingInterface.Editor)
|
||||
# Add an empty 'builders' alias to allow the DccScriptInterface root gem path to be added to the generated
|
||||
# cmake_dependencies.<project>.assetprocessor.setreg to allow the asset scan folder for it to be added
|
||||
ly_create_alias(NAME DccScriptingInterface.Builders NAMESPACE Gem)
|
||||
|
||||
@@ -178,7 +178,10 @@ namespace Camera
|
||||
if ((!m_viewSystem)||(!m_system))
|
||||
{
|
||||
// perform first-time init
|
||||
m_system = gEnv->pSystem;
|
||||
if (gEnv)
|
||||
{
|
||||
m_system = gEnv->pSystem;
|
||||
}
|
||||
if (m_system)
|
||||
{
|
||||
// Initialize local view.
|
||||
|
||||
@@ -165,8 +165,8 @@ namespace EMotionFX
|
||||
const AZ::Outcome<size_t> boolYParamIndexOutcome = m_animGraphInstance->FindParameterIndex(nameBoolY);
|
||||
success = boolXParamIndexOutcome.IsSuccess() && boolYParamIndexOutcome.IsSuccess();
|
||||
|
||||
uint32 boolXOutputPortIndex;
|
||||
uint32 boolYOutputPortIndex;
|
||||
uint32 boolXOutputPortIndex = InvalidIndex32;
|
||||
uint32 boolYOutputPortIndex = InvalidIndex32;
|
||||
const int portIndicesTosetCount = 2;
|
||||
int portIndicesFound = 0;
|
||||
const AZStd::vector<EMotionFX::AnimGraphNode::Port>& parameterNodeOutputPorts = parameterNode->GetOutputPorts();
|
||||
|
||||
+15
-6
@@ -612,7 +612,9 @@ FN_DECIMAL FastNoise::SingleValue(unsigned char offset, FN_DECIMAL x, FN_DECIMAL
|
||||
int y1 = y0 + 1;
|
||||
int z1 = z0 + 1;
|
||||
|
||||
FN_DECIMAL xs, ys, zs;
|
||||
FN_DECIMAL xs = 0.0f;
|
||||
FN_DECIMAL ys = 0.0f;
|
||||
FN_DECIMAL zs = 0.0f;
|
||||
switch (m_interp)
|
||||
{
|
||||
case Linear:
|
||||
@@ -726,7 +728,8 @@ FN_DECIMAL FastNoise::SingleValue(unsigned char offset, FN_DECIMAL x, FN_DECIMAL
|
||||
int x1 = x0 + 1;
|
||||
int y1 = y0 + 1;
|
||||
|
||||
FN_DECIMAL xs, ys;
|
||||
FN_DECIMAL xs = 0.0f;
|
||||
FN_DECIMAL ys = 0.0f;
|
||||
switch (m_interp)
|
||||
{
|
||||
case Linear:
|
||||
@@ -840,7 +843,9 @@ FN_DECIMAL FastNoise::SinglePerlin(unsigned char offset, FN_DECIMAL x, FN_DECIMA
|
||||
int y1 = y0 + 1;
|
||||
int z1 = z0 + 1;
|
||||
|
||||
FN_DECIMAL xs, ys, zs;
|
||||
FN_DECIMAL xs = 0.0f;
|
||||
FN_DECIMAL ys = 0.0f;
|
||||
FN_DECIMAL zs = 0.0f;
|
||||
switch (m_interp)
|
||||
{
|
||||
case Linear:
|
||||
@@ -962,7 +967,8 @@ FN_DECIMAL FastNoise::SinglePerlin(unsigned char offset, FN_DECIMAL x, FN_DECIMA
|
||||
int x1 = x0 + 1;
|
||||
int y1 = y0 + 1;
|
||||
|
||||
FN_DECIMAL xs, ys;
|
||||
FN_DECIMAL xs = 0.0f;
|
||||
FN_DECIMAL ys = 0.0f;
|
||||
switch (m_interp)
|
||||
{
|
||||
case Linear:
|
||||
@@ -1699,7 +1705,9 @@ FN_DECIMAL FastNoise::SingleCellular(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) c
|
||||
int zr = FastRound(z);
|
||||
|
||||
FN_DECIMAL distance = 999999;
|
||||
int xc, yc, zc;
|
||||
int xc = 0;
|
||||
int yc = 0;
|
||||
int zc = 0;
|
||||
|
||||
switch (m_cellularDistanceFunction)
|
||||
{
|
||||
@@ -1923,7 +1931,8 @@ FN_DECIMAL FastNoise::SingleCellular(FN_DECIMAL x, FN_DECIMAL y) const
|
||||
int yr = FastRound(y);
|
||||
|
||||
FN_DECIMAL distance = 999999;
|
||||
int xc, yc;
|
||||
int xc = 0;
|
||||
int yc = 0;
|
||||
|
||||
switch (m_cellularDistanceFunction)
|
||||
{
|
||||
|
||||
@@ -1072,8 +1072,7 @@ namespace GraphCanvas
|
||||
|
||||
if (!id.empty())
|
||||
{
|
||||
Selector selector = Selector::Get(id);
|
||||
result.emplace_back(selector);
|
||||
result.emplace_back(Selector::Get(id));
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1111,8 +1110,7 @@ namespace GraphCanvas
|
||||
{
|
||||
bits.emplace_back(stateSelector);
|
||||
}
|
||||
Selector selector = aznew CompoundSelector(std::move(bits));
|
||||
nestedSelectors.emplace_back(selector);
|
||||
nestedSelectors.emplace_back(aznew CompoundSelector(std::move(bits)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1239,7 +1239,7 @@ namespace GraphCanvas
|
||||
|
||||
bool GraphUtils::IsValidModelConnection(const GraphId& graphId, const Endpoint& sourceEndpoint, const Endpoint& targetEndpoint)
|
||||
{
|
||||
bool validConnection;
|
||||
bool validConnection = false;
|
||||
|
||||
AZStd::unordered_set< Endpoint > finalSourceEndpoints = RemapEndpointForModel(sourceEndpoint);
|
||||
AZStd::unordered_set< Endpoint > finalTargetEndpoints = RemapEndpointForModel(targetEndpoint);
|
||||
|
||||
@@ -23,10 +23,6 @@
|
||||
#include <QPainter>
|
||||
#include <QStaticText>
|
||||
|
||||
static const QColor timeMarkerCol = QColor(255, 0, 255);
|
||||
static const QColor textCol = QColor(0, 0, 0);
|
||||
static const QColor ltgrayCol = QColor(110, 110, 110);
|
||||
|
||||
QColor InterpolateColor(const QColor& c1, const QColor& c2, float fraction)
|
||||
{
|
||||
const int r = (c2.red() - c1.red()) * fraction + c1.red();
|
||||
|
||||
@@ -48,7 +48,6 @@ static const EUiAnimCurveType DEFAULT_TRACK_TYPE = eUiAnimCurveType_BezierFloat;
|
||||
|
||||
// Old serialization values that are no longer
|
||||
// defined in IUiAnimationSystem.h, but needed for conversion:
|
||||
static const int OLD_APARAM_USER = 100;
|
||||
static const int OLD_ACURVE_GOTO = 21;
|
||||
static const int OLD_APARAM_PARTICLE_COUNT_SCALE = 95;
|
||||
static const int OLD_APARAM_PARTICLE_PULSE_PERIOD = 96;
|
||||
|
||||
@@ -691,7 +691,7 @@ IUiAnimTrack* CUiAnimAzEntityNode::CreateTrackForAzField(const UiAnimParamData&
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
EUiAnimValue valueType;
|
||||
EUiAnimValue valueType = eUiAnimValue_Unknown;
|
||||
switch (numElements)
|
||||
{
|
||||
case 2:
|
||||
|
||||
@@ -375,7 +375,7 @@ namespace LyShine
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void LyShineSystemComponent::OnCrySystemInitialized(ISystem& system, [[maybe_unused]] const SSystemInitParams& startupParams)
|
||||
void LyShineSystemComponent::OnCrySystemInitialized([[maybe_unused]] ISystem& system, [[maybe_unused]] const SSystemInitParams& startupParams)
|
||||
{
|
||||
#if !defined(AZ_MONOLITHIC_BUILD)
|
||||
// When module is linked dynamically, we must set our gEnv pointer.
|
||||
|
||||
@@ -107,7 +107,8 @@ void UiLayoutGridComponent::ApplyLayoutHeight()
|
||||
AZStd::vector<AZ::EntityId> childEntityIds;
|
||||
EBUS_EVENT_ID_RESULT(childEntityIds, GetEntityId(), UiElementBus, GetChildEntityIds);
|
||||
int childIndex = 0;
|
||||
int columnIndex, rowIndex;
|
||||
int columnIndex = 0;
|
||||
int rowIndex = 0;
|
||||
for (auto child : childEntityIds)
|
||||
{
|
||||
// Set the anchors
|
||||
@@ -627,7 +628,8 @@ AZ::Vector2 UiLayoutGridComponent::GetChildrenBoundingRectSize(const AZ::Vector2
|
||||
UiLayoutHelpers::GetSizeInsidePadding(GetEntityId(), m_padding, layoutRectSize);
|
||||
|
||||
// Calculate number of rows and columns
|
||||
int numColumns, numRows;
|
||||
int numColumns = 0;
|
||||
int numRows = 0;
|
||||
switch (m_startingDirection)
|
||||
{
|
||||
case StartingDirection::HorizontalOrder:
|
||||
|
||||
@@ -151,6 +151,8 @@ namespace UiNavigationHelpers
|
||||
}
|
||||
|
||||
UiTransformInterface::Rect parentRect;
|
||||
parentRect.Set(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
|
||||
AZ::Matrix4x4 parentTransformFromViewport;
|
||||
if (parentElement.IsValid() && !isCurElementDescendantOfParentElement)
|
||||
{
|
||||
|
||||
@@ -60,7 +60,6 @@ static const EAnimCurveType DEFAULT_TRACK_TYPE = eAnimCurveType_BezierFloat;
|
||||
|
||||
// Old serialization values that are no longer
|
||||
// defined in IMovieSystem.h, but needed for conversion:
|
||||
static const int OLD_APARAM_USER = 100;
|
||||
static const int OLD_ACURVE_GOTO = 21;
|
||||
static const int OLD_APARAM_PARTICLE_COUNT_SCALE = 95;
|
||||
static const int OLD_APARAM_PARTICLE_PULSE_PERIOD = 96;
|
||||
|
||||
@@ -281,7 +281,6 @@ void CAnimPostFXNode::SerializeAnims(XmlNodeRef& xmlNode, bool bLoading, bool bL
|
||||
paramType.Serialize(trackNode, true);
|
||||
// Don't use APARAM_USER because it could change in newer versions
|
||||
// CAnimNode::SerializeAnims will then take care of that
|
||||
static const unsigned int OLD_APARAM_USER = 100;
|
||||
paramType = static_cast<AnimParamType>(static_cast<int>(paramType.GetType()) + OLD_APARAM_USER);
|
||||
paramType.Serialize(trackNode, false);
|
||||
}
|
||||
|
||||
@@ -51,11 +51,11 @@ namespace Audio
|
||||
// To avoid errors, we initialize COM here with the same model.
|
||||
CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
|
||||
|
||||
const CLSID CLSID_MMDeviceEnumerator = __uuidof(MMDeviceEnumerator);
|
||||
const IID IID_IMMDeviceEnumerator = __uuidof(IMMDeviceEnumerator);
|
||||
const CLSID CLSID_MMDeviceEnumerator_UUID = __uuidof(MMDeviceEnumerator);
|
||||
const IID IID_IMMDeviceEnumerator_UUID = __uuidof(IMMDeviceEnumerator);
|
||||
HRESULT hresult = CoCreateInstance(
|
||||
CLSID_MMDeviceEnumerator, nullptr,
|
||||
CLSCTX_ALL, IID_IMMDeviceEnumerator,
|
||||
CLSID_MMDeviceEnumerator_UUID, nullptr,
|
||||
CLSCTX_ALL, IID_IMMDeviceEnumerator_UUID,
|
||||
reinterpret_cast<void**>(&m_enumerator)
|
||||
);
|
||||
|
||||
@@ -133,8 +133,8 @@ namespace Audio
|
||||
AZ_Assert(m_device != nullptr, "Attempting to start a Microphone session while the device is uninitialized - Windows!\n");
|
||||
|
||||
// Get the IAudioClient from the device
|
||||
const IID IID_IAudioClient = __uuidof(IAudioClient);
|
||||
HRESULT hresult = m_device->Activate(IID_IAudioClient, CLSCTX_ALL, nullptr, reinterpret_cast<void**>(&m_audioClient));
|
||||
const IID IID_IAudioClient_UUID = __uuidof(IAudioClient);
|
||||
HRESULT hresult = m_device->Activate(IID_IAudioClient_UUID, CLSCTX_ALL, nullptr, reinterpret_cast<void**>(&m_audioClient));
|
||||
|
||||
if (FAILED(hresult))
|
||||
{
|
||||
@@ -182,8 +182,8 @@ namespace Audio
|
||||
}
|
||||
|
||||
// Get the IAudioCaptureClient
|
||||
const IID IID_IAudioCaptureClient = __uuidof(IAudioCaptureClient);
|
||||
hresult = m_audioClient->GetService(IID_IAudioCaptureClient, reinterpret_cast<void**>(&m_audioCaptureClient));
|
||||
const IID IID_IAudioCaptureClient_UUID = __uuidof(IAudioCaptureClient);
|
||||
hresult = m_audioClient->GetService(IID_IAudioCaptureClient_UUID, reinterpret_cast<void**>(&m_audioCaptureClient));
|
||||
|
||||
if (FAILED(hresult))
|
||||
{
|
||||
|
||||
@@ -39,6 +39,7 @@ namespace Multiplayer
|
||||
using EntityMigrationStartEvent = AZ::Event<ClientInputId>;
|
||||
using EntityMigrationEndEvent = AZ::Event<>;
|
||||
using EntityServerMigrationEvent = AZ::Event<const ConstNetworkEntityHandle&, HostId, AzNetworking::ConnectionId>;
|
||||
using EntityPreRenderEvent = AZ::Event<float, float>;
|
||||
|
||||
//! @class NetBindComponent
|
||||
//! @brief Component that provides net-binding to a networked entity.
|
||||
@@ -97,6 +98,7 @@ namespace Multiplayer
|
||||
void NotifyMigrationStart(ClientInputId migratedInputId);
|
||||
void NotifyMigrationEnd();
|
||||
void NotifyServerMigration(HostId hostId, AzNetworking::ConnectionId connectionId);
|
||||
void NotifyPreRender(float deltaTime, float blendFactor);
|
||||
|
||||
void AddEntityStopEventHandler(EntityStopEvent::Handler& eventHandler);
|
||||
void AddEntityDirtiedEventHandler(EntityDirtiedEvent::Handler& eventHandler);
|
||||
@@ -104,6 +106,7 @@ namespace Multiplayer
|
||||
void AddEntityMigrationStartEventHandler(EntityMigrationStartEvent::Handler& eventHandler);
|
||||
void AddEntityMigrationEndEventHandler(EntityMigrationEndEvent::Handler& eventHandler);
|
||||
void AddEntityServerMigrationEventHandler(EntityServerMigrationEvent::Handler& eventHandler);
|
||||
void AddEntityPreRenderEventHandler(EntityPreRenderEvent::Handler& eventHandler);
|
||||
|
||||
bool SerializeEntityCorrection(AzNetworking::ISerializer& serializer);
|
||||
|
||||
@@ -152,6 +155,7 @@ namespace Multiplayer
|
||||
EntityMigrationStartEvent m_entityMigrationStartEvent;
|
||||
EntityMigrationEndEvent m_entityMigrationEndEvent;
|
||||
EntityServerMigrationEvent m_entityServerMigrationEvent;
|
||||
EntityPreRenderEvent m_entityPreRenderEvent;
|
||||
AZ::Event<> m_onRemove;
|
||||
RpcSendEvent::Handler m_handleLocalServerRpcMessageEventHandle;
|
||||
AZ::Event<>::Handler m_handleMarkedDirty;
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <Source/AutoGen/NetworkTransformComponent.AutoComponent.h>
|
||||
#include <Multiplayer/Components/NetBindComponent.h>
|
||||
#include <AzCore/Component/TransformBus.h>
|
||||
|
||||
namespace Multiplayer
|
||||
@@ -32,13 +33,22 @@ namespace Multiplayer
|
||||
void OnDeactivate(Multiplayer::EntityIsMigrating entityIsMigrating) override;
|
||||
|
||||
private:
|
||||
void OnPreRender(float deltaTime, float blendFactor);
|
||||
|
||||
void OnRotationChangedEvent(const AZ::Quaternion& rotation);
|
||||
void OnTranslationChangedEvent(const AZ::Vector3& translation);
|
||||
void OnScaleChangedEvent(float scale);
|
||||
void OnResetCountChangedEvent();
|
||||
|
||||
AZ::Transform m_previousTransform = AZ::Transform::CreateIdentity();
|
||||
AZ::Transform m_targetTransform = AZ::Transform::CreateIdentity();
|
||||
|
||||
AZ::Event<AZ::Quaternion>::Handler m_rotationEventHandler;
|
||||
AZ::Event<AZ::Vector3>::Handler m_translationEventHandler;
|
||||
AZ::Event<float>::Handler m_scaleEventHandler;
|
||||
AZ::Event<uint8_t>::Handler m_resetCountEventHandler;
|
||||
|
||||
EntityPreRenderEvent::Handler m_entityPreRenderEventHandler;
|
||||
};
|
||||
|
||||
class NetworkTransformComponentController
|
||||
|
||||
+4
-4
@@ -45,10 +45,10 @@ namespace Multiplayer
|
||||
static constexpr uint32_t MaxRecordBits = 2048;
|
||||
|
||||
ReplicationRecord() = default;
|
||||
ReplicationRecord(NetEntityRole netEntityRole);
|
||||
ReplicationRecord(NetEntityRole remoteNetEntityRole);
|
||||
|
||||
void SetNetworkRole(NetEntityRole netEntityRole);
|
||||
NetEntityRole GetNetworkRole() const;
|
||||
void SetRemoteNetworkRole(NetEntityRole remoteNetEntityRole);
|
||||
NetEntityRole GetRemoteNetworkRole() const;
|
||||
|
||||
bool AreAllBitsConsumed() const;
|
||||
void ResetConsumedBits();
|
||||
@@ -92,6 +92,6 @@ namespace Multiplayer
|
||||
// Sequence number this ReplicationRecord was sent on
|
||||
AzNetworking::PacketId m_sentPacketId = AzNetworking::InvalidPacketId;
|
||||
|
||||
NetEntityRole m_netEntityRole = NetEntityRole::InvalidRole;;
|
||||
NetEntityRole m_remoteNetEntityRole = NetEntityRole::InvalidRole;;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -175,7 +175,7 @@ void Handle{{ PropertyName }}(AzNetworking::IConnection* invokingConnection, {{
|
||||
//! {{ PropertyName }} Handler
|
||||
//! {{ Property.attrib['Description'] }}
|
||||
//! HandleOn {{ HandleOn }}
|
||||
virtual void Handle{{ PropertyName }}(AzNetworking::IConnection* invokingConnection, {{ ', '.join(paramDefines) }}) = 0;
|
||||
virtual void Handle{{ PropertyName }}([[maybe_unused]] AzNetworking::IConnection* invokingConnection, [[maybe_unused]] {{ ', [[maybe_unused]] '.join(paramDefines) }}) {}
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
{#
|
||||
|
||||
@@ -311,7 +311,7 @@ void {{ ClassName }}::Set{{ UpperFirst(Property.attrib['Name']) }}(const {{ Prop
|
||||
{{ AutoComponentMacros.ParseRpcParams(Property, paramNames, paramTypes, paramDefines) }}
|
||||
void {{ ClassName }}::{{ UpperFirst(Property.attrib['Name']) }}({{ ', '.join(paramDefines) }})
|
||||
{
|
||||
constexpr RpcIndex rpcId = static_cast<RpcIndex>({{ UpperFirst(Component.attrib['Name']) }}Internal::RemoteProcedure::{{ UpperFirst(Property.attrib['Name']) }});
|
||||
constexpr Multiplayer::RpcIndex rpcId = static_cast<Multiplayer::RpcIndex>({{ UpperFirst(Component.attrib['Name']) }}Internal::RemoteProcedure::{{ UpperFirst(Property.attrib['Name']) }});
|
||||
{% if Property.attrib['IsReliable']|booleanTrue %}
|
||||
constexpr AzNetworking::ReliabilityType isReliable = Multiplayer::ReliabilityType::Reliable;
|
||||
{% else %}
|
||||
@@ -368,6 +368,31 @@ void {{ ClassName }}::Signal{{ UpperFirst(Property.attrib['Name']) }}({{ ', '.jo
|
||||
->Method("{{ UpperFirst(Property.attrib['Name']) }}", [](const {{ ClassName }}* self, {{ ', '.join(paramDefines) }}) {
|
||||
self->m_controller->{{ UpperFirst(Property.attrib['Name']) }}({{ ', '.join(paramNames) }});
|
||||
})
|
||||
->Method("{{ UpperFirst(Property.attrib['Name']) }}ByEntity", [](AZ::EntityId id, {{ ', '.join(paramDefines) }}) {
|
||||
|
||||
AZ::Entity* entity = AZ::Interface<AZ::ComponentApplicationRequests>::Get()->FindEntity(id);
|
||||
if (!entity)
|
||||
{
|
||||
AZ_Warning("Network Property", false, "{{ ClassName }} Get{{ UpperFirst(Property.attrib['Name']) }} failed. The entity with id %s doesn't exist, please provide a valid entity id.", id.ToString().c_str())
|
||||
return;
|
||||
}
|
||||
|
||||
{{ ClassName }}* networkComponent = entity->FindComponent<{{ ClassName }}>();
|
||||
if (!networkComponent)
|
||||
{
|
||||
AZ_Warning("Network Property", false, "{{ ClassName }} Get{{ UpperFirst(Property.attrib['Name']) }} failed. Entity '%s' (id: %s) is missing {{ ClassName }}, be sure to add {{ ClassName }} to this entity.", entity->GetName().c_str(), id.ToString().c_str())
|
||||
return;
|
||||
}
|
||||
|
||||
{{ ClassName }}Controller* controller = static_cast<{{ ClassName }}Controller*>(networkComponent->GetController());
|
||||
if (!controller)
|
||||
{
|
||||
AZ_Warning("Network Property", false, "{{ ClassName }} Get{{ UpperFirst(Property.attrib['Name']) }} method failed. Entity '%s' (id: %s) {{ ClassName }} is missing the network controller. This RemoteProcedure can only be invoked from {{InvokeFrom}} network entities, because this entity doesn't have a controller, it must not be a {{InvokeFrom}} entity. Please check your network context before attempting to call {{ UpperFirst(Property.attrib['Name']) }}.", entity->GetName().c_str(), id.ToString().c_str())
|
||||
return;
|
||||
}
|
||||
|
||||
controller->{{ UpperFirst(Property.attrib['Name']) }}({{ ', '.join(paramNames) }});
|
||||
})
|
||||
{% endif %}
|
||||
{% endcall %}
|
||||
{% endmacro %}
|
||||
|
||||
@@ -25,6 +25,7 @@ namespace Multiplayer
|
||||
AZ_CVAR(AZ::TimeMs, cl_MaxRewindHistoryMs, AZ::TimeMs{ 2000 }, nullptr, AZ::ConsoleFunctorFlags::Null, "Maximum number of milliseconds to keep for server correction rewind and replay");
|
||||
#ifndef AZ_RELEASE_BUILD
|
||||
AZ_CVAR(float, cl_DebugHackTimeMultiplier, 1.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "Scalar value used to simulate clock hacking cheats for validating bank time system and anticheat");
|
||||
AZ_CVAR(bool, cl_EnableDesyncDebugging, false, nullptr, AZ::ConsoleFunctorFlags::Null, "If enabled, debug logs will contain verbose information on detected state desyncs");
|
||||
#endif
|
||||
|
||||
AZ_CVAR(bool, sv_EnableCorrections, true, nullptr, AZ::ConsoleFunctorFlags::Null, "Enables server corrections on autonomous proxy desyncs");
|
||||
@@ -214,11 +215,12 @@ namespace Multiplayer
|
||||
// Send correction
|
||||
SendClientInputCorrection(GetLastInputId(), correction);
|
||||
|
||||
#ifdef _DEBUG
|
||||
// In debug, show which states caused the correction
|
||||
#ifndef AZ_RELEASE_BUILD
|
||||
AZStd::string clientStateString;
|
||||
AZStd::string serverStateString;
|
||||
if (cl_EnableDesyncDebugging)
|
||||
{
|
||||
// In debug, show which states caused the correction
|
||||
// Write in client state
|
||||
AzNetworking::NetworkOutputSerializer clientStateSerializer(clientState.GetBuffer(), clientState.GetSize());
|
||||
GetNetBindComponent()->SerializeEntityCorrection(clientStateSerializer);
|
||||
@@ -236,11 +238,13 @@ namespace Multiplayer
|
||||
GetNetBindComponent()->SerializeEntityCorrection(serverValues);
|
||||
|
||||
AZStd::map<AZStd::string, AZStd::pair<AZStd::string, AZStd::string>> mapComparison;
|
||||
|
||||
// put the server value in the first part of the pair
|
||||
for (const auto& pair : serverValues.GetValueMap())
|
||||
{
|
||||
mapComparison[pair.first].first = pair.second;
|
||||
}
|
||||
|
||||
// put the client value in the second part of the pair
|
||||
for (const auto& pair : clientValues.GetValueMap())
|
||||
{
|
||||
@@ -266,12 +270,13 @@ namespace Multiplayer
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
const AZStd::string clientStateString = "available in debug only";
|
||||
const AZStd::string serverStateString = "available in debug only";
|
||||
#endif
|
||||
|
||||
else
|
||||
{
|
||||
clientStateString = "available in debug only";
|
||||
serverStateString = "available in debug only";
|
||||
}
|
||||
AZLOG_ERROR("** Autonomous proxy desync detected! ** clientState=[%s], serverState=[%s]", clientStateString.c_str(), serverStateString.c_str());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -416,7 +421,7 @@ namespace Multiplayer
|
||||
|
||||
ClientInputId LocalPredictionPlayerInputComponentController::GetLastInputId() const
|
||||
{
|
||||
return m_clientInputId;
|
||||
return m_lastClientInputId;
|
||||
}
|
||||
|
||||
HostFrameId LocalPredictionPlayerInputComponentController::GetInputFrameId(const NetworkInput& input) const
|
||||
@@ -520,10 +525,13 @@ namespace Multiplayer
|
||||
|
||||
// In debug, send the entire client output state to the server to make it easier to debug desync issues
|
||||
AzNetworking::PacketEncodingBuffer processInputResult;
|
||||
#ifdef _DEBUG
|
||||
AzNetworking::NetworkInputSerializer processInputResultSerializer(processInputResult.GetBuffer(), processInputResult.GetCapacity());
|
||||
GetNetBindComponent()->SerializeEntityCorrection(processInputResultSerializer);
|
||||
processInputResult.Resize(processInputResultSerializer.GetSize());
|
||||
#ifndef AZ_RELEASE_BUILD
|
||||
if (cl_EnableDesyncDebugging)
|
||||
{
|
||||
AzNetworking::NetworkInputSerializer processInputResultSerializer(processInputResult.GetBuffer(), processInputResult.GetCapacity());
|
||||
GetNetBindComponent()->SerializeEntityCorrection(processInputResultSerializer);
|
||||
processInputResult.Resize(processInputResultSerializer.GetSize());
|
||||
}
|
||||
#endif
|
||||
|
||||
// Save this input and discard move history outside our client rewind window
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user