merge stabilization/2106 into development

Signed-off-by: hultonha <hultonha@amazon.co.uk>
monroegm-disable-blank-issue-2
hultonha 5 years ago
commit 2ea9bfb144

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:d1c5941f584d35b3d21eb9c311b02698c30499895e9a8c827fb71168e2656255
size 1436672

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:5f480ade0a4190f7cb1d7cf286e970f958632d88e19b8c21ead11f838358a750
size 369584

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:d5eba063346e9163f43bbfec7e71497c847645fb12a3ec573314c9f44afbc801
size 364464

@ -49,14 +49,7 @@ set(ENABLED_GEMS
HttpRequestor
Atom_AtomBridge
PythonCoverage
AWSCore
AWSClientAuth
AWSMetrics
)
# TODO remove conditional add once AWSNativeSDK libs are fixed for Android and Linux Monolithic release.
set(aws_excluded_platforms Android)
if (NOT (LY_MONOLITHIC_GAME AND ${PAL_PLATFORM_NAME} IN_LIST aws_excluded_platforms))
list(APPEND ENABLED_GEMS
AWSCore
AWSClientAuth
AWSMetrics
)
endif()

@ -9,6 +9,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
ly_add_pytest(
NAME AutomatedTesting::NvClothTests_Main
TEST_SUITE main
TEST_REQUIRES gpu
TEST_SERIAL
PATH ${CMAKE_CURRENT_LIST_DIR}/TestSuite_Active.py
TIMEOUT 1500

@ -20,10 +20,13 @@ from base import TestAutomationBase
@pytest.mark.parametrize("project", ["AutomatedTesting"])
class TestAutomation(TestAutomationBase):
use_null_renderer = False # Use default renderer (needs gpu)
extra_cmdline_args = []
def test_C18977329_NvCloth_AddClothSimulationToMesh(self, request, workspace, editor, launcher_platform):
from . import C18977329_NvCloth_AddClothSimulationToMesh as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, self.extra_cmdline_args, self.use_null_renderer)
def test_C18977330_NvCloth_AddClothSimulationToActor(self, request, workspace, editor, launcher_platform):
from . import C18977330_NvCloth_AddClothSimulationToActor as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, self.extra_cmdline_args, self.use_null_renderer)

@ -51,7 +51,7 @@ class TestAutomationBase:
cls._kill_ly_processes()
def _run_test(self, request, workspace, editor, testcase_module, extra_cmdline_args=[]):
def _run_test(self, request, workspace, editor, testcase_module, extra_cmdline_args=[], use_null_renderer=True):
test_starttime = time.time()
self.logger = logging.getLogger(__name__)
errors = []
@ -89,7 +89,10 @@ class TestAutomationBase:
editor_starttime = time.time()
self.logger.debug("Running automated test")
testcase_module_filepath = self._get_testcase_module_filepath(testcase_module)
pycmd = ["--runpythontest", testcase_module_filepath, "-BatchMode", "-autotest_mode", "-rhi=null", f"-pythontestcase={request.node.originalname}"] + extra_cmdline_args
pycmd = ["--runpythontest", testcase_module_filepath, "-BatchMode", "-autotest_mode", f"-pythontestcase={request.node.originalname}"]
if use_null_renderer:
pycmd += ["-rhi=null"]
pycmd += extra_cmdline_args
editor.args.extend(pycmd) # args are added to the WinLauncher start command
editor.start(backupFiles = False, launch_ap = False)
try:

@ -58,8 +58,11 @@ class TestFileMenuDefaultNewOpen:
sc_main = sc.findChild(QtWidgets.QMainWindow)
sc_tabs = sc_main.findChild(QtWidgets.QTabWidget, "ScriptCanvasTabs")
# 3) Trigger File->New action
# wait for the intial tab count
general.idle_wait(GENERAL_WAIT)
initial_tabs_count = sc_tabs.count()
# 3) Trigger File->New action
action = pyside_utils.find_child_by_pattern(
sc_main, {"objectName": "action_New_Script", "type": QtWidgets.QAction}
)

@ -51,17 +51,4 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
AutomatedTesting.GameLauncher
AutomatedTesting.Assets
)
ly_add_pytest(
NAME AutomatedTesting::GameLauncherWithGPU
TEST_REQUIRES gpu
PATH ${CMAKE_CURRENT_LIST_DIR}/test_GameLauncher_EnterExitGameMode_Works.py
TIMEOUT 100
RUNTIME_DEPENDENCIES
AZ::AssetProcessor
AZ::PythonBindingsExample
Legacy::Editor
AutomatedTesting.GameLauncher
AutomatedTesting.Assets
)
endif()

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:ec428aee9c49ffd58a00fdcbb0625185a22f5690f7b2e81326ef5443699019e6
size 10945
oid sha256:e04b536d187793187b64a55914d92c1a1c18393a0369715269a295c7b7a7d370
size 8883

@ -45,7 +45,7 @@ CAboutDialog::CAboutDialog(QString versionText, QString richTextCopyrightNotice,
CAboutDialog > QLabel#link { text-decoration: underline; color: #94D2FF; }");
// Prepare background image
QImage backgroundImage(QStringLiteral(":/StartupLogoDialog/splashscreen_background_gradient.jpg"));
QImage backgroundImage(QStringLiteral(":/StartupLogoDialog/splashscreen_background_developer_preview.jpg"));
m_backgroundImage = QPixmap::fromImage(backgroundImage.scaled(m_enforcedWidth, m_enforcedHeight, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
// Draw the Open 3D Engine logo from svg

@ -36,11 +36,11 @@ CStartupLogoDialog::CStartupLogoDialog(QString versionText, QString richTextCopy
s_pLogoWindow = this;
m_backgroundImage = QPixmap(QStringLiteral(":/StartupLogoDialog/splashscreen_background_gradient.jpg"));
m_backgroundImage = QPixmap(QStringLiteral(":/StartupLogoDialog/splashscreen_background_developer_preview.jpg"));
setFixedSize(QSize(600, 300));
// Prepare background image
QImage backgroundImage(QStringLiteral(":/StartupLogoDialog/splashscreen_background_gradient.jpg"));
QImage backgroundImage(QStringLiteral(":/StartupLogoDialog/splashscreen_background_developer_preview.jpg"));
m_backgroundImage = QPixmap::fromImage(backgroundImage.scaled(m_enforcedWidth, m_enforcedHeight, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
// Draw the Open 3D Engine logo from svg

@ -1,6 +1,6 @@
<RCC>
<qresource prefix="/StartupLogoDialog">
<file>o3de_logo.svg</file>
<file>splashscreen_background_gradient.jpg</file>
<file>splashscreen_background_developer_preview.jpg</file>
</qresource>
</RCC>

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:7105ec99477f124a8ac8d588f2dfc4ee7bb54f39386c8131b7703c86754c0cb8
size 248690

@ -689,6 +689,81 @@ namespace AZ
return 1;
}
int Class__IndexAllowNil(lua_State* l)
{
LSV_BEGIN(l, 1);
// calling format __index(table,key)
lua_getmetatable(l, -2); // load the userdata metatable
int metaTableIndex = lua_gettop(l);
// Check if the key is string, if so we expect it to be a function or property name
// otherwise we allow users to provide custom index handlers
// Technically we can allow strings too, but it will clash with function/property names and it be hard to figure
// out what is going on from with in the system.
if (lua_type(l, -2) == LUA_TSTRING)
{
lua_pushvalue(l, -2); // duplicate the key
lua_rawget(l, -2); // load the value at this index
}
else
{
lua_pushliteral(l, "__AZ_Index");
lua_rawget(l, -2); // check if the user provided custom Index method in the class metatable
if (lua_isnil(l, -1)) // if not report an error
{
lua_rawgeti(l, -2, AZ_LUA_CLASS_METATABLE_NAME_INDEX); // load the class name for a better error
if (!lua_isstring(l, -1)) // if we failed it means we are the base metatable
{
lua_pop(l, 1);
lua_rawgeti(l, 1, AZ_LUA_CLASS_METATABLE_NAME_INDEX);
}
ScriptContext::FromNativeContext(l)->Error(ScriptContext::ErrorType::Warning, true, "Invalid index type [], should be string! '%s:%s'!", lua_tostring(l, -1), lua_tostring(l, -4));
}
else
{
// if we have custom index handler
lua_pushvalue(l, -4); // duplicate the table (class pointer)
lua_pushvalue(l, -4); // duplicate the index value for the call
lua_call(l, 2, 1); // call the function
}
lua_remove(l, metaTableIndex); // remove the metatable
return 1;
}
if (!lua_isnil(l, -1))
{
if (lua_tocfunction(l, -1) == &Internal::LuaPropertyTagHelper) // if it's a property
{
lua_getupvalue(l, -1, 1); // push on the stack the getter function
lua_remove(l, -2); // remove property object
if (lua_isnil(l, -1))
{
lua_rawgeti(l, -2, AZ_LUA_CLASS_METATABLE_NAME_INDEX); // load the class name for a better error
if (!lua_isstring(l, -1)) // if we failed it means we are the base metatable
{
lua_pop(l, 1);
lua_rawgeti(l, 1, AZ_LUA_CLASS_METATABLE_NAME_INDEX);
}
ScriptContext::FromNativeContext(l)->Error(ScriptContext::ErrorType::Warning, true, "Property '%s:%s' is write only", lua_tostring(l, -1), lua_tostring(l, -4));
lua_pop(l, 1); // pop class name
}
else
{
lua_pushvalue(l, -4); // copy the user data to be passed as a this pointer.
lua_call(l, 1, 1); // call a function with one argument (this pointer) and 1 result
}
}
}
lua_remove(l, metaTableIndex); // remove the metatable
return 1;
}
//=========================================================================
// Class__NewIndex
// [3/22/2012]
@ -826,30 +901,6 @@ namespace AZ
return 1;
}
//=========================================================================
// ClassMetatable__Index
// [3/24/2012]
//=========================================================================
int ClassMetatable__Index(lua_State* l)
{
// since the Class__Index is generic function (ask for the class metatable)
// we can reuse the code for the base metatable (which is a metatable
// of the class metatable)
return Class__Index(l);
}
//=========================================================================
// ClassMetatable__NewIndex
// [3/30/2012]
//=========================================================================
int ClassMetatable__NewIndex(lua_State* l)
{
// since the Class__NewIndex is generic function (ask for the class metatable)
// we can reuse the code for the base metatable (which is a metatable
// of the class metatable)
return Class__NewIndex(l);
}
inline size_t BufferStringCopy(const char* source, char* destination, size_t destinationSize)
{
size_t srcLen = strlen(source);
@ -5053,9 +5104,20 @@ LUA_API const Node* lua_getDummyNode()
lua_pushcclosure(m_lua, &DefaultBehaviorCaller::Destroy, 0);
lua_rawset(m_lua, -3);
lua_pushliteral(m_lua, "__index");
lua_pushcclosure(m_lua, &Internal::Class__Index, 0);
lua_rawset(m_lua, -3);
{
lua_pushliteral(m_lua, "__index");
if (FindAttribute(Script::Attributes::UseClassIndexAllowNil, behaviorClass->m_attributes))
{
lua_pushcclosure(m_lua, &Internal::Class__IndexAllowNil, 0);
}
else
{
lua_pushcclosure(m_lua, &Internal::Class__Index, 0);
}
lua_rawset(m_lua, -3);
}
lua_pushliteral(m_lua, "__newindex");
lua_pushcclosure(m_lua, &Internal::Class__NewIndex, 0);

@ -16,19 +16,20 @@ namespace AZ
{
namespace Attributes
{
const static AZ::Crc32 Ignore = AZ_CRC("ScriptIgnore", 0xeb7615e1); ///< Don't use the element in the script reflection
const static AZ::Crc32 ClassNameOverride = AZ_CRC("ScriptClassNameOverride", 0x891238a3); ///< Provide a custom name for script reflection, that doesn't match the behavior Context name
const static AZ::Crc32 MethodOverride = AZ_CRC("ScriptFunctionOverride", 0xf89a7882); ///< Use a custom function in the attribute instead of the function
const static AZ::Crc32 ConstructorOverride = AZ_CRC("ConstructorOverride", 0xef5ce4aa); ///< You can provide a custom constructor to be called when created from Lua script
const static AZ::Crc32 EventHandlerCreationFunction = AZ_CRC_CE("EventHandlerCreationFunction"); ///< helps create a handler for any script target so that script functions can be used for AZ::Event signals
const static AZ::Crc32 GenericConstructorOverride = AZ_CRC("GenericConstructorOverride", 0xe6a1698e); ///< You can provide a custom constructor to be called when creating a script
const static AZ::Crc32 ReaderWriterOverride = AZ_CRC("ReaderWriterOverride", 0x1ad9ce2a); ///< paired with \ref ScriptContext::CustomReaderWriter allows you to customize read/write to Lua VM
const static AZ::Crc32 ConstructibleFromNil = AZ_CRC("ConstructibleFromNil", 0x23908169); ///< Applied to classes. Value (bool) specifies if the class be default constructed when nil is provided.
const static AZ::Crc32 ToolTip = AZ_CRC("ToolTip", 0xa1b95fb0); ///< Add a tooltip for a method/event/property
const static AZ::Crc32 Category = AZ_CRC("Category", 0x064c19c1); ///< Provide a category to allow for partitioning/sorting/ordering of the element
const static AZ::Crc32 Deprecated = AZ_CRC("Deprecated", 0xfe49a138); ///< Marks a reflected class, method, EBus or property as deprecated.
const static AZ::Crc32 DisallowBroadcast = AZ_CRC("DisallowBroadcast", 0x389b0ac7); ///< Marks a reflected EBus as not allowing Broadcasts, only Events.
const static AZ::Crc32 ClassConstantValue = AZ_CRC_CE("ClassConstantValue"); ///< Indicates the property is backed by a constant value
static constexpr AZ::Crc32 Ignore = AZ_CRC_CE("ScriptIgnore"); ///< Don't use the element in the script reflection
static constexpr AZ::Crc32 ClassNameOverride = AZ_CRC_CE("ScriptClassNameOverride"); ///< Provide a custom name for script reflection, that doesn't match the behavior Context name
static constexpr AZ::Crc32 MethodOverride = AZ_CRC_CE("ScriptFunctionOverride"); ///< Use a custom function in the attribute instead of the function
static constexpr AZ::Crc32 ConstructorOverride = AZ_CRC_CE("ConstructorOverride"); ///< You can provide a custom constructor to be called when created from Lua script
static constexpr AZ::Crc32 EventHandlerCreationFunction = AZ_CRC_CE("EventHandlerCreationFunction"); ///< helps create a handler for any script target so that script functions can be used for AZ::Event signals
static constexpr AZ::Crc32 GenericConstructorOverride = AZ_CRC_CE("GenericConstructorOverride"); ///< You can provide a custom constructor to be called when creating a script
static constexpr AZ::Crc32 ReaderWriterOverride = AZ_CRC_CE("ReaderWriterOverride"); ///< paired with \ref ScriptContext::CustomReaderWriter allows you to customize read/write to Lua VM
static constexpr AZ::Crc32 ConstructibleFromNil = AZ_CRC_CE("ConstructibleFromNil"); ///< Applied to classes. Value (bool) specifies if the class be default constructed when nil is provided.
static constexpr AZ::Crc32 ToolTip = AZ_CRC_CE("ToolTip"); ///< Add a tooltip for a method/event/property
static constexpr AZ::Crc32 Category = AZ_CRC_CE("Category"); ///< Provide a category to allow for partitioning/sorting/ordering of the element
static constexpr AZ::Crc32 Deprecated = AZ_CRC_CE("Deprecated"); ///< Marks a reflected class, method, EBus or property as deprecated.
static constexpr AZ::Crc32 DisallowBroadcast = AZ_CRC_CE("DisallowBroadcast"); ///< Marks a reflected EBus as not allowing Broadcasts, only Events.
static constexpr AZ::Crc32 ClassConstantValue = AZ_CRC_CE("ClassConstantValue"); ///< Indicates the property is backed by a constant value
static constexpr AZ::Crc32 UseClassIndexAllowNil = AZ_CRC_CE("UseClassIndexAllowNil"); ///< Use the Class__IndexAllowNil method, which will not report an error on accessing undeclared values (allows for nil)
//! Attribute which stores BehaviorAzEventDescription structure which contains
//! the script name of an AZ::Event and the name of it's parameter arguments
@ -39,11 +40,11 @@ namespace AZ
static constexpr AZ::Crc32 EventParameterTypes = AZ_CRC_CE("EventParameterTypes");
///< Recommends that the Lua runtime look up the member function in the meta table of the first argument, rather than in the original table
const static AZ::Crc32 TreatAsMemberFunction = AZ_CRC("TreatAsMemberFunction", 0x64be831a);
static constexpr AZ::Crc32 TreatAsMemberFunction = AZ_CRC_CE("TreatAsMemberFunction");
///< This attribute can be attached to the EditContext Attribute of a reflected class, the BehaviorContext Attribute of a reflected class, method, ebus or property.
///< ExcludeFlags can be used to prevent elements from appearing in List, Documentation, etc...
const static AZ::Crc32 ExcludeFrom = AZ_CRC("ExcludeFrom", 0xa98972fe);
static constexpr AZ::Crc32 ExcludeFrom = AZ_CRC_CE("ExcludeFrom");
enum ExcludeFlags : AZ::u64
{
List = 1 << 0, //< The reflected item will be excluded from any list (e.g. node palette)
@ -54,7 +55,7 @@ namespace AZ
};
//! Used to specify the usage of a Behavior Context element (e.g. Class or EBus) designed for automation scripts
const static AZ::Crc32 Scope = AZ_CRC("Scope", 0x00af55d3);
static constexpr AZ::Crc32 Scope = AZ_CRC_CE("Scope");
enum class ScopeFlags : AZ::u64
{
Launcher = 1 << 0, //< a type meant for game run-time Launcher client (default value)
@ -63,15 +64,15 @@ namespace AZ
};
//! Provide a partition hierarchy in a string dotted notation to namespace a script element
const static AZ::Crc32 Module = AZ_CRC("Module", 0x0c242628);
static constexpr AZ::Crc32 Module = AZ_CRC_CE("Module");
//! Provide an alternate name for script elements such as helpful PEP8 Python methods and property aliases
const static AZ::Crc32 Alias = AZ_CRC("Alias", 0xe16c6b94);
static constexpr AZ::Crc32 Alias = AZ_CRC_CE("Alias");
const static AZ::Crc32 EnableAsScriptEventParamType = AZ_CRC("ScriptEventParam", 0xa41e4cb0);
const static AZ::Crc32 EnableAsScriptEventReturnType = AZ_CRC("ScriptEventReturn", 0xf89b5337);
static constexpr AZ::Crc32 EnableAsScriptEventParamType = AZ_CRC_CE("ScriptEventParam");
static constexpr AZ::Crc32 EnableAsScriptEventReturnType = AZ_CRC_CE("ScriptEventReturn");
const static AZ::Crc32 Storage = AZ_CRC("ScriptStorage", 0xcd95b44d);
static constexpr AZ::Crc32 Storage = AZ_CRC_CE("ScriptStorage");
enum class StorageType
{
ScriptOwn, // default, Host allocated memory, Lua will destruct object, Lua will free host-memory via host-supplied function
@ -79,7 +80,7 @@ namespace AZ
Value, // Object is Lua allocated memory, Lua will destruct object, Lua will free Lua-memory
};
const static AZ::Crc32 Operator = AZ_CRC("ScriptOperator", 0xfee681b6);
static constexpr AZ::Crc32 Operator = AZ_CRC_CE("ScriptOperator");
enum class OperatorType
{
// note storage policy can be T*,T (only if we store raw pointers), shared_ptr<T>, intrusive pointer<T>
@ -100,7 +101,7 @@ namespace AZ
IndexWrite, // given a key/index and a value, you can store it in the class
};
const static AZ::Crc32 AssetType = AZ_CRC("AssetType", 0xabbf8d5f); ///< Provide an asset type for a generic AssetId method
static constexpr AZ::Crc32 AssetType = AZ_CRC_CE("AssetType"); ///< Provide an asset type for a generic AssetId method
} // Attributes
} // Script

@ -24,7 +24,6 @@ namespace AZ
//=========================================================================
AZStd::string ExtractUserMessage(const ScriptDataContext& dc)
{
AZStd::string userMessage = "Condition failed";
const int argCount = dc.GetNumArguments();
if (argCount > 0 && dc.IsString(argCount - 1))
{
@ -33,12 +32,12 @@ namespace AZ
{
if (value)
{
userMessage = value;
return value;
}
}
}
return userMessage;
return "ExtractUserMessage from print/Debug.Log/Warn/Error/Assert failed. Consider wrapping your argument in tostring().";
}
//=========================================================================

@ -188,7 +188,7 @@ namespace AzPhysics
AZ::Transform m_start = AZ::Transform::CreateIdentity(); //!< World space start position. Assumes only rotation + translation (no scaling).
AZ::Vector3 m_direction = AZ::Vector3::CreateZero(); //!< World space direction (Should be normalized)
AZStd::shared_ptr<Physics::ShapeConfiguration> m_shapeConfiguration; //!< Shape information.
SceneQuery::HitFlags m_hitFlags = SceneQuery::HitFlags::Default; //!< Query behavior flags
SceneQuery::HitFlags m_hitFlags = SceneQuery::HitFlags::Default | SceneQuery::HitFlags::MTD; //!< Query behavior flags. MTD Is On by default to correctly report objects that are initially in contact with the start pose.
SceneQuery::FilterCallback m_filterCallback = nullptr; //!< Hit filtering function
bool m_reportMultipleHits = false; //!< flag to have the cast stop after the first hit or return all hits along the query.
};

@ -46,10 +46,11 @@ namespace AzToolsFramework::Prefab::SpawnableUtils
}
}
template<typename EntityPtr>
void OrganizeEntitiesForSorting(
AzFramework::Spawnable::EntityList& entities,
AZStd::vector<EntityPtr>& entities,
AZStd::unordered_set<AZ::EntityId>& existingEntityIds,
AZStd::unordered_map<AZ::EntityId, AzFramework::Spawnable::EntityList>& parentIdToChildren,
AZStd::unordered_map<AZ::EntityId, AZStd::vector<EntityPtr>>& parentIdToChildren,
AZStd::vector<AZ::EntityId>& candidateIds,
size_t& removedEntitiesCount)
{
@ -90,7 +91,7 @@ namespace AzToolsFramework::Prefab::SpawnableUtils
// entities with no transform component will be treated like entities with no parent.
AZ::EntityId parentId;
if (AZ::TransformInterface* transformInterface =
AZ::EntityUtils::FindFirstDerivedComponent<AZ::TransformInterface>(entity.get()))
AZ::EntityUtils::FindFirstDerivedComponent<AZ::TransformInterface>(&(*entity)))
{
parentId = transformInterface->GetParentId();
if (parentId == entityId)
@ -104,8 +105,7 @@ namespace AzToolsFramework::Prefab::SpawnableUtils
}
auto& children = parentIdToChildren[parentId];
children.emplace_back(nullptr);
children.back().swap(entity);
children.emplace_back(AZStd::move(entity));
}
// clear 'entities', we'll refill it in sorted order.
@ -125,9 +125,10 @@ namespace AzToolsFramework::Prefab::SpawnableUtils
}
template<typename EntityPtr>
void TraceParentingLoop(
const AZ::EntityId& parentFromLoopId,
const AZStd::unordered_map<AZ::EntityId, AzFramework::Spawnable::EntityList>& parentIdToChildren)
const AZStd::unordered_map<AZ::EntityId, AZStd::vector<EntityPtr>>& parentIdToChildren)
{
// Find name to use in warning message
@ -153,16 +154,22 @@ namespace AzToolsFramework::Prefab::SpawnableUtils
parentFromLoopId.ToString().c_str());
}
void SortEntitiesByTransformHierarchy(AzFramework::Spawnable& spawnable)
{
auto& entities = spawnable.GetEntities();
SortEntitiesByTransformHierarchy(spawnable.GetEntities());
}
template<typename EntityPtr>
void SortEntitiesByTransformHierarchy(AZStd::vector<EntityPtr>& entities)
{
const size_t originalEntityCount = entities.size();
// IDs of those present in 'entities'. Does not include parent ID if parent not found in 'entities'
AZStd::unordered_set<AZ::EntityId> existingEntityIds;
// map children by their parent ID (even if parent not found in 'entities')
AZStd::unordered_map<AZ::EntityId, AzFramework::Spawnable::EntityList> parentIdToChildren;
AZStd::unordered_map<AZ::EntityId, AZStd::vector<EntityPtr>> parentIdToChildren;
// use 'candidateIds' to track the parent IDs we're going to process next.
AZStd::vector<AZ::EntityId> candidateIds;
@ -199,8 +206,7 @@ namespace AzToolsFramework::Prefab::SpawnableUtils
for (auto& child : foundChildren->second)
{
candidateIds.push_back(child->GetId());
entities.emplace_back(nullptr);
entities.back().swap(child);
entities.emplace_back(AZStd::move(child));
}
parentIdToChildren.erase(foundChildren);
@ -217,4 +223,7 @@ namespace AzToolsFramework::Prefab::SpawnableUtils
}
// Explicit specializations of SortEntitiesByTransformHierarchy (have to be in cpp due to clang errors)
template void SortEntitiesByTransformHierarchy(AZStd::vector<AZ::Entity*>& entities);
template void SortEntitiesByTransformHierarchy(AZStd::vector<AZStd::unique_ptr<AZ::Entity>>& entities);
} // namespace AzToolsFramework::Prefab::SpawnableUtils

@ -16,4 +16,8 @@ namespace AzToolsFramework::Prefab::SpawnableUtils
bool CreateSpawnable(AzFramework::Spawnable& spawnable, const PrefabDom& prefabDom, AZStd::vector<AZ::Data::Asset<AZ::Data::AssetData>>& referencedAssets);
void SortEntitiesByTransformHierarchy(AzFramework::Spawnable& spawnable);
template <typename EntityPtr>
void SortEntitiesByTransformHierarchy(AZStd::vector<EntityPtr>& entities);
} // namespace AzToolsFramework::Prefab::SpawnableUtils

@ -20,14 +20,6 @@ struct IUiAnimationSystem;
class UiCanvasInterface
: public AZ::ComponentBus
{
public: // types
enum class ErrorCode
{
NoError,
PrefabContainsExternalEntityRefs
};
public: // member functions
//! Deleting a canvas will delete all its child elements recursively and all of their components
@ -110,23 +102,6 @@ public: // member functions
//! \return true if no error
virtual bool SaveToXml(const string& assetIdPathname, const string& sourceAssetPathname) = 0;
//! Save the given UI element entity to the given path as a prefab
//! \param pathname the path to save the prefab to
//! \param entity pointer to the entity to save as a prefab
//! \return true if no error
virtual bool SaveAsPrefab(const string& pathname, AZ::Entity* entity) = 0;
//! Check if it is OK to save the given UI element entity to the given path as a prefab
//! \param entity pointer to the entity to save as a prefab
//! \return errorCode which is NoError if OK to save
virtual ErrorCode CheckElementValidToSaveAsPrefab(AZ::Entity* entity) = 0;
//! Load a prefab element from the given file and optionally insert as child of given entity
//! \return the top level entity created
virtual AZ::Entity* LoadFromPrefab(const string& pathname,
bool makeUniqueName,
AZ::Entity* optionalInsertionPoint) = 0;
//! Initialize a set of entities that have been added to the canvas
//! Used when instantiating a slice or for undo/redo, copy/paste
//! \param topLevelEntities - The elements that were created

@ -2548,7 +2548,7 @@ namespace AssetProcessor
jobdetail.m_jobParam[AZ_CRC(AutoFailReasonKey)] = AZStd::string::format(
"Source file ( %s ) contains non ASCII characters.\n"
"Open 3D Engine currently only supports file paths having ASCII characters and therefore asset processor will not be able to process this file.\n"
"O3DE currently only supports file paths having ASCII characters and therefore asset processor will not be able to process this file.\n"
"Please rename the source file to fix this error.\n",
normalizedPath.toUtf8().data());

@ -10,6 +10,7 @@
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
#include <AzCore/UserSettings/UserSettingsComponent.h>
#include <AzCore/IO/FileIOEventBus.h>
#include <AzCore/Utils/Utils.h>
#include "BaseAssetProcessorTest.h"
#include <native/utilities/BatchApplicationManager.h>
@ -67,11 +68,19 @@ namespace AssetProcessor
static char** paramStringArray = &namePtr;
auto registry = AZ::SettingsRegistry::Get();
auto projectPathKey =
AZ::SettingsRegistryInterface::FixedValueString(AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey) + "/project_path";
auto bootstrapKey = AZ::SettingsRegistryInterface::FixedValueString(AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey);
auto projectPathKey = bootstrapKey + "/project_path";
registry->Set(projectPathKey, "AutomatedTesting");
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddRuntimeFilePaths(*registry);
// Forcing the branch token into settings registry before starting the application manager.
// This avoids writing the asset_processor.setreg file which can cause fileIO errors.
AZ::IO::FixedMaxPathString enginePath = AZ::Utils::GetEnginePath();
auto branchTokenKey = bootstrapKey + "/assetProcessor_branch_token";
AZStd::string token;
AzFramework::StringFunc::AssetPath::CalculateBranchToken(enginePath.c_str(), token);
registry->Set(branchTokenKey, token.c_str());
m_application.reset(new UnitTestAppManager(&numParams, &paramStringArray));
ASSERT_EQ(m_application->BeforeRun(), ApplicationManager::Status_Success);
ASSERT_TRUE(m_application->PrepareForTests());

@ -17,7 +17,7 @@
</size>
</property>
<property name="windowTitle">
<string>Asset Processor</string>
<string>O3DE Asset Processor</string>
</property>
<widget class="QWidget" name="centralWidget">
<layout class="QVBoxLayout" name="verticalLayout_1" stretch="0,1">

@ -478,7 +478,7 @@ void ApplicationManagerBase::InitConnectionManager()
result = QObject::connect(GetRCController(), &AssetProcessor::RCController::JobStarted, this,
[](QString inputFile, QString platform)
{
QString msg = QCoreApplication::translate("Asset Processor", "Processing %1 (%2)...\n", "%1 is the name of the file, and %2 is the platform to process it for").arg(inputFile, platform);
QString msg = QCoreApplication::translate("O3DE Asset Processor", "Processing %1 (%2)...\n", "%1 is the name of the file, and %2 is the platform to process it for").arg(inputFile, platform);
AZ_Printf(AssetProcessor::ConsoleChannel, "%s", msg.toUtf8().constData());
AssetNotificationMessage message(inputFile.toUtf8().constData(), AssetNotificationMessage::JobStarted, AZ::Data::s_invalidAssetType, platform.toUtf8().constData());
EBUS_EVENT(AssetProcessor::ConnectionBus, SendPerPlatform, 0, message, platform);

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:342c3eaccf68a178dfd8c2b1792a93a8c9197c8184dca11bf90706d7481df087
size 1611268

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:7088e902885d98953f6a1715efab319c063a4ab8918fd0e810251c8ed82b8514
size 542983

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:797794816e4b1702f1ae1f32b408c95c79eb1f8a95aba43cfad9cccc181b0bda
size 1135182

@ -26,12 +26,13 @@
<file>o3de.svg</file>
<file>menu.svg</file>
<file>menu_hover.svg</file>
<file>Backgrounds/FirstTimeBackgroundImage.jpg</file>
<file>ArrowDownLine.svg</file>
<file>ArrowUpLine.svg</file>
<file>CarrotArrowDown.svg</file>
<file>Summary.svg</file>
<file>WindowClose.svg</file>
<file>Warning.svg</file>
<file>Backgrounds/DefaultBackground.jpg</file>
<file>Backgrounds/FtueBackground.jpg</file>
</qresource>
</RCC>

@ -11,7 +11,6 @@
#include <ProjectInfo.h>
#endif
// due to current limitations, customizing template Gems is disabled
#define TEMPLATE_GEM_CONFIGURATION_ENABLED
QT_FORWARD_DECLARE_CLASS(QStackedWidget)

@ -61,8 +61,8 @@ namespace O3DE::ProjectManager
{
switch (origin)
{
case O3DEFoundation:
return "Open 3D Foundation";
case Open3DEEngine:
return "Open 3D Engine";
case Local:
return "Local";
default:

@ -43,7 +43,7 @@ namespace O3DE::ProjectManager
enum GemOrigin
{
O3DEFoundation = 1 << 0,
Open3DEEngine = 1 << 0,
Local = 1 << 1,
NumGemOrigins = 2
};

@ -99,7 +99,13 @@ namespace O3DE::ProjectManager
painter->drawText(gemCreatorRect, Qt::TextSingleLine, gemCreator);
// Gem summary
const QSize summarySize = QSize(contentRect.width() - s_summaryStartX - s_buttonWidth - s_itemMargins.right() * 3, contentRect.height());
// In case there are feature tags displayed at the bottom, decrease the size of the summary text field.
const QStringList featureTags = GemModel::GetFeatures(modelIndex);
const int summaryHeight = contentRect.height() - (!featureTags.empty() * 30);
const QSize summarySize = QSize(contentRect.width() - s_summaryStartX - s_buttonWidth - s_itemMargins.right() * 3,
summaryHeight);
const QRect summaryRect = QRect(/*topLeft=*/QPoint(contentRect.left() + s_summaryStartX, contentRect.top()), summarySize);
painter->setFont(standardFont);
@ -108,9 +114,9 @@ namespace O3DE::ProjectManager
const QString summary = GemModel::GetSummary(modelIndex);
painter->drawText(summaryRect, Qt::AlignLeft | Qt::TextWordWrap, summary);
DrawButton(painter, contentRect, modelIndex);
DrawPlatformIcons(painter, contentRect, modelIndex);
DrawFeatureTags(painter, contentRect, featureTags, standardFont, summaryRect);
painter->restore();
}
@ -206,6 +212,46 @@ namespace O3DE::ProjectManager
}
}
void GemItemDelegate::DrawFeatureTags(QPainter* painter, const QRect& contentRect, const QStringList& featureTags, const QFont& standardFont, const QRect& summaryRect) const
{
QFont gemFeatureTagFont(standardFont);
gemFeatureTagFont.setPixelSize(s_featureTagFontSize);
gemFeatureTagFont.setBold(false);
painter->setFont(gemFeatureTagFont);
int x = s_summaryStartX;
for (const QString& featureTag : featureTags)
{
QRect featureTagRect = GetTextRect(gemFeatureTagFont, featureTag, s_featureTagFontSize);
featureTagRect.moveTo(contentRect.left() + x + s_featureTagBorderMarginX,
contentRect.top() + 47);
featureTagRect = painter->boundingRect(featureTagRect, Qt::TextSingleLine, featureTag);
QRect backgroundRect = featureTagRect;
backgroundRect = backgroundRect.adjusted(/*left=*/-s_featureTagBorderMarginX,
/*top=*/-s_featureTagBorderMarginY,
/*right=*/s_featureTagBorderMarginX,
/*bottom=*/s_featureTagBorderMarginY);
// Skip drawing all following feature tags as there is no more space available.
if (backgroundRect.right() > summaryRect.right())
{
break;
}
// Draw border.
painter->setPen(m_textColor);
painter->setBrush(Qt::NoBrush);
painter->drawRect(backgroundRect);
// Draw text within the border.
painter->setPen(m_textColor);
painter->drawText(featureTagRect, Qt::TextSingleLine, featureTag);
x += backgroundRect.width() + s_featureTagSpacing;
}
}
void GemItemDelegate::DrawButton(QPainter* painter, const QRect& contentRect, const QModelIndex& modelIndex) const
{
painter->save();

@ -57,12 +57,19 @@ namespace O3DE::ProjectManager
inline constexpr static int s_buttonCircleRadius = s_buttonBorderRadius - 2;
inline constexpr static qreal s_buttonFontSize = 10.0;
// Feature tags
inline constexpr static int s_featureTagFontSize = 10;
inline constexpr static int s_featureTagBorderMarginX = 3;
inline constexpr static int s_featureTagBorderMarginY = 3;
inline constexpr static int s_featureTagSpacing = 7;
protected:
void CalcRects(const QStyleOptionViewItem& option, QRect& outFullRect, QRect& outItemRect, QRect& outContentRect) const;
QRect GetTextRect(QFont& font, const QString& text, qreal fontSize) const;
QRect CalcButtonRect(const QRect& contentRect) const;
void DrawPlatformIcons(QPainter* painter, const QRect& contentRect, const QModelIndex& modelIndex) const;
void DrawButton(QPainter* painter, const QRect& contentRect, const QModelIndex& modelIndex) const;
void DrawFeatureTags(QPainter* painter, const QRect& contentRect, const QStringList& featureTags, const QFont& standardFont, const QRect& summaryRect) const;
QAbstractItemModel* m_model = nullptr;

@ -97,10 +97,21 @@ namespace O3DE::ProjectManager
{
m_templates = templatesResult.GetValue();
// sort alphabetically by display name because they could be in any order
// sort alphabetically by display name (but putting Standard first) because they could be in any order
std::sort(m_templates.begin(), m_templates.end(), [](const ProjectTemplateInfo& arg1, const ProjectTemplateInfo& arg2)
{
return arg1.m_displayName.toLower() < arg2.m_displayName.toLower();
if (arg1.m_displayName == "Standard")
{
return true;
}
else if (arg2.m_displayName == "Standard")
{
return false;
}
else
{
return arg1.m_displayName.toLower() < arg2.m_displayName.toLower();
}
});
for (int index = 0; index < m_templates.size(); ++index)

@ -19,6 +19,7 @@ QT_FORWARD_DECLARE_CLASS(QFrame)
namespace O3DE::ProjectManager
{
QT_FORWARD_DECLARE_CLASS(TagContainerWidget)
class NewProjectSettingsScreen
: public ProjectSettingsScreen
{

@ -92,10 +92,18 @@ namespace O3DE::ProjectManager
// Open application assigned to this file type
QDesktopServices::openUrl(QUrl("file:///" + m_worker->GetLogFilePath()));
}
m_projectInfo.m_buildFailed = true;
m_projectInfo.m_logUrl = QUrl("file:///" + m_worker->GetLogFilePath());
emit NotifyBuildProject(m_projectInfo);
}
else
{
QMessageBox::critical(m_parent, tr("Project Failed to Build!"), result);
m_projectInfo.m_buildFailed = true;
m_projectInfo.m_logUrl = QUrl();
emit NotifyBuildProject(m_projectInfo);
}
emit Done(false);

@ -38,6 +38,7 @@ namespace O3DE::ProjectManager
signals:
void Done(bool success = true);
void NotifyBuildProject(const ProjectInfo& projectInfo);
private:
ProjectInfo m_projectInfo;

@ -14,7 +14,7 @@
namespace O3DE::ProjectManager
{
const QString ProjectBuilderWorker::BuildCancelled = ProjectBuilderWorker::tr("Build Cancelled.");
const QString ProjectBuilderWorker::BuildCancelled = QObject::tr("Build Cancelled.");
ProjectBuilderWorker::ProjectBuilderWorker(const ProjectInfo& projectInfo)
: QObject()

@ -11,6 +11,7 @@
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QEvent>
#include <QResizeEvent>
#include <QLabel>
#include <QPushButton>
@ -20,6 +21,7 @@
#include <QProgressBar>
#include <QDir>
#include <QFileInfo>
#include <QDesktopServices>
namespace O3DE::ProjectManager
{
@ -40,8 +42,57 @@ namespace O3DE::ProjectManager
m_overlayLabel->setVisible(false);
vLayout->addWidget(m_overlayLabel);
m_buildOverlayLayout = new QVBoxLayout();
m_buildOverlayLayout->addSpacing(10);
QHBoxLayout* horizontalMessageLayout = new QHBoxLayout();
horizontalMessageLayout->addSpacing(10);
m_warningIcon = new QLabel(this);
m_warningIcon->setPixmap(QIcon(":/Warning.svg").pixmap(20, 20));
m_warningIcon->setAlignment(Qt::AlignTop);
m_warningIcon->setVisible(false);
horizontalMessageLayout->addWidget(m_warningIcon);
horizontalMessageLayout->addSpacing(10);
m_warningText = new QLabel("", this);
m_warningText->setObjectName("projectWarningOverlay");
m_warningText->setWordWrap(true);
m_warningText->setAlignment(Qt::AlignLeft);
m_warningText->setVisible(false);
connect(m_warningText, &QLabel::linkActivated, this, &LabelButton::OnLinkActivated);
horizontalMessageLayout->addWidget(m_warningText);
QSpacerItem* textSpacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Expanding);
horizontalMessageLayout->addSpacerItem(textSpacer);
m_buildOverlayLayout->addLayout(horizontalMessageLayout);
QSpacerItem* buttonSpacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Expanding);
m_buildOverlayLayout->addSpacerItem(buttonSpacer);
QHBoxLayout* horizontalOpenEditorButtonLayout = new QHBoxLayout();
horizontalOpenEditorButtonLayout->addSpacing(34);
m_openEditorButton = new QPushButton(tr("Open Editor"), this);
m_openEditorButton->setObjectName("openEditorButton");
m_openEditorButton->setDefault(true);
m_openEditorButton->setVisible(false);
horizontalOpenEditorButtonLayout->addWidget(m_openEditorButton);
horizontalOpenEditorButtonLayout->addSpacing(34);
m_buildOverlayLayout->addLayout(horizontalOpenEditorButtonLayout);
QHBoxLayout* horizontalButtonLayout = new QHBoxLayout();
horizontalButtonLayout->addSpacing(34);
m_actionButton = new QPushButton(tr("Project Action"), this);
m_actionButton->setVisible(false);
horizontalButtonLayout->addWidget(m_actionButton);
horizontalButtonLayout->addSpacing(34);
m_buildOverlayLayout->addLayout(horizontalButtonLayout);
m_buildOverlayLayout->addSpacing(16);
vLayout->addItem(m_buildOverlayLayout);
m_progressBar = new QProgressBar(this);
m_progressBar->setObjectName("labelButtonProgressBar");
@ -73,16 +124,41 @@ namespace O3DE::ProjectManager
return m_overlayLabel;
}
void LabelButton::SetLogUrl(const QUrl& url)
{
m_logUrl = url;
}
QProgressBar* LabelButton::GetProgressBar()
{
return m_progressBar;
}
QPushButton* LabelButton::GetOpenEditorButton()
{
return m_openEditorButton;
}
QPushButton* LabelButton::GetActionButton()
{
return m_actionButton;
}
QLabel* LabelButton::GetWarningLabel()
{
return m_warningText;
}
QLabel* LabelButton::GetWarningIcon()
{
return m_warningIcon;
}
void LabelButton::OnLinkActivated(const QString& /*link*/)
{
QDesktopServices::openUrl(m_logUrl);
}
ProjectButton::ProjectButton(const ProjectInfo& projectInfo, QWidget* parent, bool processing)
: QFrame(parent)
, m_projectInfo(projectInfo)
@ -110,7 +186,6 @@ namespace O3DE::ProjectManager
m_projectImageLabel = new LabelButton(this);
m_projectImageLabel->setFixedSize(ProjectPreviewImageWidth, ProjectPreviewImageHeight);
m_projectImageLabel->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
connect(m_projectImageLabel, &LabelButton::triggered, [this]() { emit OpenProject(m_projectInfo.m_path); });
vLayout->addWidget(m_projectImageLabel);
QString projectPreviewPath = QDir(m_projectInfo.m_path).filePath(m_projectInfo.m_iconPath);
@ -145,6 +220,8 @@ namespace O3DE::ProjectManager
void ProjectButton::ReadySetup()
{
connect(m_projectImageLabel->GetOpenEditorButton(), &QPushButton::clicked, [this](){ emit OpenProject(m_projectInfo.m_path); });
QMenu* menu = new QMenu(this);
menu->addAction(tr("Edit Project Settings..."), this, [this]() { emit EditProject(m_projectInfo.m_path); });
menu->addAction(tr("Build"), this, [this]() { emit BuildProject(m_projectInfo); });
@ -170,9 +247,6 @@ namespace O3DE::ProjectManager
QPushButton* projectActionButton = m_projectImageLabel->GetActionButton();
if (!m_actionButtonConnection)
{
QSpacerItem* buttonSpacer = new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding);
m_projectImageLabel->layout()->addItem(buttonSpacer);
m_projectImageLabel->layout()->addWidget(projectActionButton);
projectActionButton->setVisible(true);
}
else
@ -186,6 +260,27 @@ namespace O3DE::ProjectManager
void ProjectButton::SetProjectBuildButtonAction()
{
m_projectImageLabel->GetWarningLabel()->setText(tr("Building project required."));
m_projectImageLabel->GetWarningIcon()->setVisible(true);
m_projectImageLabel->GetWarningLabel()->setVisible(true);
SetProjectButtonAction(tr("Build Project"), [this]() { emit BuildProject(m_projectInfo); });
}
void ProjectButton::ShowBuildFailed(bool show, const QUrl& logUrl)
{
if (!logUrl.isEmpty())
{
m_projectImageLabel->GetWarningLabel()->setText(tr("Failed to build. Click to <a href=\"logs\">view logs</a>."));
}
else
{
m_projectImageLabel->GetWarningLabel()->setText(tr("Project failed to build."));
}
m_projectImageLabel->GetWarningLabel()->setTextInteractionFlags(Qt::LinksAccessibleByMouse);
m_projectImageLabel->GetWarningIcon()->setVisible(show);
m_projectImageLabel->GetWarningLabel()->setVisible(show);
m_projectImageLabel->SetLogUrl(logUrl);
SetProjectButtonAction(tr("Build Project"), [this]() { emit BuildProject(m_projectInfo); });
}
@ -209,6 +304,16 @@ namespace O3DE::ProjectManager
m_projectImageLabel->GetProgressBar()->setValue(progress);
}
void ProjectButton::enterEvent(QEvent* /*event*/)
{
m_projectImageLabel->GetOpenEditorButton()->setVisible(true);
}
void ProjectButton::leaveEvent(QEvent* /*event*/)
{
m_projectImageLabel->GetOpenEditorButton()->setVisible(false);
}
LabelButton* ProjectButton::GetLabelButton()
{
return m_projectImageLabel;

@ -20,6 +20,9 @@
QT_FORWARD_DECLARE_CLASS(QPixmap)
QT_FORWARD_DECLARE_CLASS(QAction)
QT_FORWARD_DECLARE_CLASS(QProgressBar)
QT_FORWARD_DECLARE_CLASS(QLayout)
QT_FORWARD_DECLARE_CLASS(QVBoxLayout)
QT_FORWARD_DECLARE_CLASS(QEvent)
namespace O3DE::ProjectManager
{
@ -34,21 +37,32 @@ namespace O3DE::ProjectManager
void SetEnabled(bool enabled);
void SetOverlayText(const QString& text);
void SetLogUrl(const QUrl& url);
QLabel* GetOverlayLabel();
QProgressBar* GetProgressBar();
QPushButton* GetOpenEditorButton();
QPushButton* GetActionButton();
QLabel* GetWarningLabel();
QLabel* GetWarningIcon();
QLayout* GetBuildOverlayLayout();
signals:
void triggered();
public slots:
void mousePressEvent(QMouseEvent* event) override;
void OnLinkActivated(const QString& link);
private:
QVBoxLayout* m_buildOverlayLayout;
QLabel* m_overlayLabel;
QProgressBar* m_progressBar;
QPushButton* m_openEditorButton;
QPushButton* m_actionButton;
QLabel* m_warningText;
QLabel* m_warningIcon;
QUrl m_logUrl;
bool m_enabled = true;
};
@ -63,6 +77,7 @@ namespace O3DE::ProjectManager
void SetProjectButtonAction(const QString& text, AZStd::function<void()> lambda);
void SetProjectBuildButtonAction();
void ShowBuildFailed(bool show, const QUrl& logUrl);
void SetLaunchButtonEnabled(bool enabled);
void SetButtonOverlayText(const QString& text);
@ -81,11 +96,14 @@ namespace O3DE::ProjectManager
void BaseSetup();
void ProcessingSetup();
void ReadySetup();
void enterEvent(QEvent* event) override;
void leaveEvent(QEvent* event) override;
void BuildThisProject();
ProjectInfo m_projectInfo;
LabelButton* m_projectImageLabel;
QFrame* m_projectFooter;
QLayout* m_requiresBuildLayout;
QMetaObject::Connection m_actionButtonConnection;
};

@ -9,6 +9,7 @@
#if !defined(Q_MOC_RUN)
#include <AzCore/Math/Uuid.h>
#include <QUrl>
#include <QString>
#include <QStringList>
#endif
@ -54,5 +55,7 @@ namespace O3DE::ProjectManager
// Used in project creation
bool m_needsBuild = false; //! Does this project need to be built
bool m_buildFailed = false;
QUrl m_logUrl;
};
} // namespace O3DE::ProjectManager

@ -53,8 +53,6 @@ namespace O3DE::ProjectManager
vLayout->setContentsMargins(s_contentMargins, 0, s_contentMargins, 0);
setLayout(vLayout);
m_background.load(":/Backgrounds/FirstTimeBackgroundImage.jpg");
m_stack = new QStackedWidget(this);
m_firstTimeContent = CreateFirstTimeContent();
@ -117,6 +115,8 @@ namespace O3DE::ProjectManager
QFrame* ProjectsScreen::CreateProjectsContent(QString buildProjectPath, ProjectButton** projectButton)
{
RemoveInvalidProjects();
QFrame* frame = new QFrame(this);
frame->setObjectName("projectsContent");
{
@ -193,7 +193,19 @@ namespace O3DE::ProjectManager
}
else if (RequiresBuildProjectIterator(project.m_path) != m_requiresBuild.end())
{
projectButtonWidget->SetProjectBuildButtonAction();
auto buildProjectIterator = RequiresBuildProjectIterator(project.m_path);
if (buildProjectIterator != m_requiresBuild.end())
{
if (buildProjectIterator->m_buildFailed)
{
projectButtonWidget->ShowBuildFailed(true, buildProjectIterator->m_logUrl);
}
else
{
projectButtonWidget->SetProjectBuildButtonAction();
}
}
}
}
@ -232,6 +244,8 @@ namespace O3DE::ProjectManager
m_projectsContent->deleteLater();
}
m_background.load(":/Backgrounds/DefaultBackground.jpg");
// Make sure to update builder with latest Project Button
if (m_currentBuilder)
{
@ -269,21 +283,30 @@ namespace O3DE::ProjectManager
// we paint the background here because qss does not support background cover scaling
QPainter painter(this);
auto winSize = size();
auto pixmapRatio = (float)m_background.width() / m_background.height();
auto windowRatio = (float)winSize.width() / winSize.height();
const QSize winSize = size();
const float pixmapRatio = (float)m_background.width() / m_background.height();
const float windowRatio = (float)winSize.width() / winSize.height();
QRect backgroundRect;
if (pixmapRatio > windowRatio)
{
auto newWidth = (int)(winSize.height() * pixmapRatio);
auto offset = (newWidth - winSize.width()) / -2;
painter.drawPixmap(offset, 0, newWidth, winSize.height(), m_background);
const int newWidth = (int)(winSize.height() * pixmapRatio);
const int offset = (newWidth - winSize.width()) / -2;
backgroundRect = QRect(offset, 0, newWidth, winSize.height());
}
else
{
auto newHeight = (int)(winSize.width() / pixmapRatio);
painter.drawPixmap(0, 0, winSize.width(), newHeight, m_background);
const int newHeight = (int)(winSize.width() / pixmapRatio);
backgroundRect = QRect(0, 0, winSize.width(), newHeight);
}
// Draw the background image.
painter.drawPixmap(backgroundRect, m_background);
// Draw a semi-transparent overlay to darken down the colors.
painter.setCompositionMode (QPainter::CompositionMode_DestinationIn);
const float overlayTransparency = 0.7f;
painter.fillRect(backgroundRect, QColor(0, 0, 0, static_cast<int>(255.0f * overlayTransparency)));
}
void ProjectsScreen::HandleNewProjectButton()
@ -407,7 +430,7 @@ namespace O3DE::ProjectManager
void ProjectsScreen::SuggestBuildProjectMsg(const ProjectInfo& projectInfo, bool showMessage)
{
if (RequiresBuildProjectIterator(projectInfo.m_path) == m_requiresBuild.end())
if (RequiresBuildProjectIterator(projectInfo.m_path) == m_requiresBuild.end() || projectInfo.m_buildFailed)
{
m_requiresBuild.append(projectInfo);
}
@ -459,6 +482,7 @@ namespace O3DE::ProjectManager
{
if (ShouldDisplayFirstTimeContent())
{
m_background.load(":/Backgrounds/FtueBackground.jpg");
m_stack->setCurrentWidget(m_firstTimeContent);
}
else
@ -485,6 +509,11 @@ namespace O3DE::ProjectManager
return displayFirstTimeContent;
}
bool ProjectsScreen::RemoveInvalidProjects()
{
return PythonBindingsInterface::Get()->RemoveInvalidProjects();
}
bool ProjectsScreen::StartProjectBuild(const ProjectInfo& projectInfo)
{
if (ProjectUtils::IsVS2019Installed())
@ -500,6 +529,7 @@ namespace O3DE::ProjectManager
m_currentBuilder = new ProjectBuilderController(projectInfo, nullptr, this);
ResetProjectsContent();
connect(m_currentBuilder, &ProjectBuilderController::Done, this, &ProjectsScreen::ProjectBuildDone);
connect(m_currentBuilder, &ProjectBuilderController::NotifyBuildProject, this, &ProjectsScreen::SuggestBuildProject);
m_currentBuilder->Start();
}

@ -62,6 +62,7 @@ namespace O3DE::ProjectManager
ProjectButton* CreateProjectButton(ProjectInfo& project, QLayout* flowLayout, bool processing = false);
void ResetProjectsContent();
bool ShouldDisplayFirstTimeContent();
bool RemoveInvalidProjects();
bool StartProjectBuild(const ProjectInfo& projectInfo);
QList<ProjectInfo>::iterator RequiresBuildProjectIterator(const QString& projectPath);

@ -1,6 +1,6 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
@ -23,6 +23,8 @@
#include <AzCore/std/string/conversions.h>
#include <AzCore/StringFunc/StringFunc.h>
#include <QDir>
namespace Platform
{
bool InsertPythonLibraryPath(
@ -42,7 +44,7 @@ namespace Platform
return false;
}
// Implemented in each different platform's PAL implentation files, as it differs per platform.
// Implemented in each different platform's PAL implementation files, as it differs per platform.
AZStd::string GetPythonHomePath(const char* pythonPackage, const char* engineRoot);
} // namespace Platform
@ -650,6 +652,12 @@ namespace O3DE::ProjectManager
gemInfo.m_summary = Py_To_String_Optional(data, "summary", "");
gemInfo.m_version = "";
gemInfo.m_requirement = Py_To_String_Optional(data, "requirements", "");
gemInfo.m_creator = Py_To_String_Optional(data, "origin", "");
if (gemInfo.m_creator.contains("Open 3D Engine"))
{
gemInfo.m_gemOrigin = GemInfo::GemOrigin::Open3DEEngine;
}
if (data.contains("user_tags"))
{
@ -769,6 +777,21 @@ namespace O3DE::ProjectManager
});
}
bool PythonBindings::RemoveInvalidProjects()
{
bool removalResult = false;
bool result = ExecuteWithLock(
[&]
{
auto pythonRemovalResult = m_register.attr("remove_invalid_o3de_projects")();
// Returns an exit code so boolify it then invert result
removalResult = !pythonRemovalResult.cast<bool>();
});
return result && removalResult;
}
AZ::Outcome<void, AZStd::string> PythonBindings::UpdateProject(const ProjectInfo& projectInfo)
{
bool updateProjectSucceeded = false;
@ -836,11 +859,19 @@ namespace O3DE::ProjectManager
templateInfo.m_canonicalTags.push_back(Py_To_String(tag));
}
}
if (data.contains("included_gems"))
QString templateProjectPath = QDir(templateInfo.m_path).filePath("Template");
auto enabledGemNames = GetEnabledGemNames(templateProjectPath);
if (enabledGemNames)
{
for (auto gem : data["included_gems"])
for (auto gem : enabledGemNames.GetValue())
{
templateInfo.m_includedGems.push_back(Py_To_String(gem));
// Exclude the template ${Name} placeholder for the list of included gems
// That Gem gets created with the project
if (!gem.contains("${Name}"))
{
templateInfo.m_includedGems.push_back(Py_To_String(gem.c_str()));
}
}
}
}

@ -50,6 +50,7 @@ namespace O3DE::ProjectManager
AZ::Outcome<void, AZStd::string> UpdateProject(const ProjectInfo& projectInfo) override;
AZ::Outcome<void, AZStd::string> AddGemToProject(const QString& gemPath, const QString& projectPath) override;
AZ::Outcome<void, AZStd::string> RemoveGemFromProject(const QString& gemPath, const QString& projectPath) override;
bool RemoveInvalidProjects() override;
// ProjectTemplate
AZ::Outcome<QVector<ProjectTemplateInfo>> GetProjectTemplates(const QString& projectPath = {}) override;

@ -141,6 +141,11 @@ namespace O3DE::ProjectManager
*/
virtual AZ::Outcome<void, AZStd::string> RemoveGemFromProject(const QString& gemPath, const QString& projectPath) = 0;
/**
* Removes invalid projects from the manifest
*/
virtual bool RemoveInvalidProjects() = 0;
// Project Templates

@ -22,7 +22,7 @@ namespace AWSClientAuth
virtual ~AWSCognitoAuthenticationProvider() = default;
// AuthenticationProviderInterface overrides
bool Initialize(AZStd::weak_ptr<AZ::SettingsRegistryInterface> settingsRegistry) override;
bool Initialize() override;
void PasswordGrantSingleFactorSignInAsync(const AZStd::string& username, const AZStd::string& password) override;
void PasswordGrantMultiFactorSignInAsync(const AZStd::string& username, const AZStd::string& password) override;
void PasswordGrantMultiFactorConfirmSignInAsync(const AZStd::string& username, const AZStd::string& confirmationCode) override;

@ -22,9 +22,8 @@ namespace AWSClientAuth
virtual ~AuthenticationProviderInterface() = default;
//! Extract required settings for the provider from setting registry.
//! @param settingsRegistry Passed in initialized settings registry object.
//! @return bool True: if provider can parse required settings and validate. False: fails to parse required settings.
virtual bool Initialize(AZStd::weak_ptr<AZ::SettingsRegistryInterface> settingsRegistry) = 0;
virtual bool Initialize() = 0;
//! Call sign in endpoint for provider password grant flow.
//! @param username Username to use to for sign in.

@ -29,7 +29,7 @@ namespace AWSClientAuth
protected:
// AuthenticationProviderRequestsBus Interface
bool Initialize(const AZStd::vector<ProviderNameEnum>& providerNames, const AZStd::string& settingsRegistryPath) override;
bool Initialize(const AZStd::vector<ProviderNameEnum>& providerNames) override;
void PasswordGrantSingleFactorSignInAsync(const ProviderNameEnum& providerName, const AZStd::string& username, const AZStd::string& password) override;
void PasswordGrantMultiFactorSignInAsync(const ProviderNameEnum& providerName, const AZStd::string& username, const AZStd::string& password) override;
void PasswordGrantMultiFactorConfirmSignInAsync(const ProviderNameEnum& providerName, const AZStd::string& username, const AZStd::string& confirmationCode) override;
@ -42,7 +42,7 @@ namespace AWSClientAuth
AuthenticationTokens GetAuthenticationTokens(const ProviderNameEnum& providerName) override;
// AuthenticationProviderScriptCanvasRequest interface
bool Initialize(const AZStd::vector<AZStd::string>& providerNames, const AZStd::string& settingsRegistryPath) override;
bool Initialize(const AZStd::vector<AZStd::string>& providerNames) override;
void PasswordGrantSingleFactorSignInAsync(
const AZStd::string& providerName, const AZStd::string& username, const AZStd::string& password) override;
void PasswordGrantMultiFactorSignInAsync(
@ -64,8 +64,6 @@ namespace AWSClientAuth
bool IsProviderInitialized(const ProviderNameEnum& providerName);
void ResetProviders();
ProviderNameEnum GetProviderNameEnum(AZStd::string name);
AZStd::shared_ptr<AZ::SettingsRegistryInterface> m_settingsRegistry;
};
} // namespace AWSClientAuth

@ -20,9 +20,8 @@ namespace AWSClientAuth
//! Parse the settings file for required settings for authentication providers. Instantiate and initialize authentication providers
//! @param providerNames List of provider names to instantiate and initialize for Authentication.
//! @param settingsRegistryPath Path for the settings registry file to use to configure providers.
//! @return bool True: if all providers initialized successfully. False: If any provider fails initialization.
virtual bool Initialize(const AZStd::vector<AZStd::string>& providerNames, const AZStd::string& settingsRegistryPath) = 0;
virtual bool Initialize(const AZStd::vector<AZStd::string>& providerNames) = 0;
//! Checks if user is signed in.
//! If access tokens are available and not expired.

@ -21,7 +21,7 @@ namespace AWSClientAuth
virtual ~GoogleAuthenticationProvider();
// AuthenticationProviderInterface overrides
bool Initialize(AZStd::weak_ptr<AZ::SettingsRegistryInterface> settingsRegistry) override;
bool Initialize() override;
void PasswordGrantSingleFactorSignInAsync(const AZStd::string& username, const AZStd::string& password) override;
void PasswordGrantMultiFactorSignInAsync(const AZStd::string& username, const AZStd::string& password) override;
void PasswordGrantMultiFactorConfirmSignInAsync(const AZStd::string& username, const AZStd::string& confirmationCode) override;

@ -21,7 +21,7 @@ namespace AWSClientAuth
virtual ~LWAAuthenticationProvider();
// AuthenticationProviderInterface overrides
bool Initialize(AZStd::weak_ptr<AZ::SettingsRegistryInterface> settingsRegistry) override;
bool Initialize() override;
void PasswordGrantSingleFactorSignInAsync(const AZStd::string& username, const AZStd::string& password) override;
void PasswordGrantMultiFactorSignInAsync(const AZStd::string& username, const AZStd::string& password) override;
void PasswordGrantMultiFactorConfirmSignInAsync(const AZStd::string& username, const AZStd::string& confirmationCode) override;

@ -19,9 +19,8 @@ namespace AWSClientAuth
//! Parse the settings file for required settings for authentication providers. Instantiate and initialize authentication providers
//! @param providerNames List of provider names to instantiate and initialize for Authentication.
//! @param settingsRegistryPath Path for the settings registry file to use to configure providers.
//! @return bool True: if all providers initialized successfully. False: If any provider fails initialization.
virtual bool Initialize(const AZStd::vector<ProviderNameEnum>& providerNames, const AZStd::string& settingsRegistryPath) = 0;
virtual bool Initialize(const AZStd::vector<ProviderNameEnum>& providerNames) = 0;
//! Checks if user is signed in.
//! If access tokens are available and not expired.

@ -30,9 +30,8 @@ namespace AWSClientAuth
constexpr char CognitoRefreshTokenAuthParamKey[] = "REFRESH_TOKEN";
constexpr char CognitoSmsMfaCodeKey[] = "SMS_MFA_CODE";
bool AWSCognitoAuthenticationProvider::Initialize(AZStd::weak_ptr<AZ::SettingsRegistryInterface> settingsRegistry)
bool AWSCognitoAuthenticationProvider::Initialize()
{
AZ_UNUSED(settingsRegistry);
AWSCore::AWSResourceMappingRequestBus::BroadcastResult(
m_cognitoAppClientId, &AWSCore::AWSResourceMappingRequests::GetResourceNameId, CognitoAppClientIdResourceMappingKey);
AZ_Warning("AWSCognitoAuthenticationProvider", !m_cognitoAppClientId.empty(), "Missing Cognito App Client Id from resource mappings. Calls to Cognito will fail.");

@ -6,7 +6,6 @@
*/
#include <AzCore/std/smart_ptr/make_shared.h>
#include <AzCore/Settings/SettingsRegistryImpl.h>
#include <AzCore/IO/FileIO.h>
#include <Authentication/AuthenticationProviderTypes.h>
@ -27,37 +26,21 @@ namespace AWSClientAuth
AuthenticationProviderManager::~AuthenticationProviderManager()
{
ResetProviders();
m_settingsRegistry.reset();
AuthenticationProviderScriptCanvasRequestBus::Handler::BusDisconnect();
AuthenticationProviderRequestBus::Handler::BusDisconnect();
AZ::Interface<IAuthenticationProviderRequests>::Unregister(this);
}
bool AuthenticationProviderManager::Initialize(const AZStd::vector<ProviderNameEnum>& providerNames, const AZStd::string& settingsRegistryPath)
bool AuthenticationProviderManager::Initialize(const AZStd::vector<ProviderNameEnum>& providerNames)
{
ResetProviders();
AZ::IO::FileIOBase* fileIO = AZ::IO::FileIOBase::GetInstance();
AZ_Assert(fileIO, "File IO is not initialized.");
m_settingsRegistry.reset();
m_settingsRegistry = AZStd::make_shared<AZ::SettingsRegistryImpl>();
AZStd::array<char, AZ::IO::MaxPathLength> resolvedPath{};
fileIO->ResolvePath(settingsRegistryPath.data(), resolvedPath.data(), resolvedPath.size());
if (!m_settingsRegistry->MergeSettingsFile(resolvedPath.data(), AZ::SettingsRegistryInterface::Format::JsonMergePatch))
{
AZ_Error("AuthenticationProviderManager", false, "Error merging settings registry for path: %s", resolvedPath.data());
return false;
}
bool initializeSuccess = true;
for (auto providerName : providerNames)
{
m_authenticationProvidersMap[providerName] = CreateAuthenticationProviderObject(providerName);
initializeSuccess = initializeSuccess && m_authenticationProvidersMap[providerName]->Initialize(m_settingsRegistry);
initializeSuccess = initializeSuccess && m_authenticationProvidersMap[providerName]->Initialize();
}
return initializeSuccess;
@ -199,14 +182,14 @@ namespace AWSClientAuth
}
bool AuthenticationProviderManager::Initialize(
const AZStd::vector<AZStd::string>& providerNames, const AZStd::string& settingsRegistryPath)
const AZStd::vector<AZStd::string>& providerNames)
{
AZStd::vector<ProviderNameEnum> providerNamesEnum;
for (auto name : providerNames)
{
providerNamesEnum.push_back(GetProviderNameEnum(name));
}
return Initialize(providerNamesEnum, settingsRegistryPath);
return Initialize(providerNamesEnum);
}
void AuthenticationProviderManager::PasswordGrantSingleFactorSignInAsync(const AZStd::string& providerName, const AZStd::string& username, const AZStd::string& password)

@ -30,9 +30,16 @@ namespace AWSClientAuth
m_settings.reset();
}
bool GoogleAuthenticationProvider::Initialize(AZStd::weak_ptr<AZ::SettingsRegistryInterface> settingsRegistry)
bool GoogleAuthenticationProvider::Initialize()
{
if (!settingsRegistry.lock()->GetObject(m_settings.get(), azrtti_typeid(m_settings.get()), GoogleSettingsPath))
AZ::SettingsRegistryInterface* settingsRegistry = AZ::SettingsRegistry::Get();
if (!settingsRegistry)
{
AZ_Warning("AWSCognitoAuthenticationProvider", false, "Failed to load the setting registry");
return false;
}
if (!settingsRegistry->GetObject(m_settings.get(), azrtti_typeid(m_settings.get()), GoogleSettingsPath))
{
AZ_Warning("AWSCognitoAuthenticationProvider", false, "Failed to get Google settings object for path %s", GoogleSettingsPath);
return false;

@ -29,9 +29,16 @@ namespace AWSClientAuth
m_settings.reset();
}
bool LWAAuthenticationProvider::Initialize(AZStd::weak_ptr<AZ::SettingsRegistryInterface> settingsRegistry)
bool LWAAuthenticationProvider::Initialize()
{
if (!settingsRegistry.lock()->GetObject(m_settings.get(), azrtti_typeid(m_settings.get()), LwaSettingsPath))
AZ::SettingsRegistryInterface* settingsRegistry = AZ::SettingsRegistry::Get();
if (!settingsRegistry)
{
AZ_Warning("AWSCognitoAuthenticationProvider", false, "Failed to load the setting registry");
return false;
}
if (!settingsRegistry->GetObject(m_settings.get(), azrtti_typeid(m_settings.get()), LwaSettingsPath))
{
AZ_Warning("AWSCognitoAuthenticationProvider", false, "Failed to get login with Amazon settings object for path %s", LwaSettingsPath);
return false;

@ -351,12 +351,12 @@ namespace AWSClientAuthUnitTest
AuthenticationProviderMock()
{
ON_CALL(*this, Initialize(testing::_)).WillByDefault(testing::Return(true));
ON_CALL(*this, Initialize()).WillByDefault(testing::Return(true));
}
virtual ~AuthenticationProviderMock() = default;
MOCK_METHOD1(Initialize, bool(AZStd::weak_ptr<AZ::SettingsRegistryInterface> settingsRegistry));
MOCK_METHOD0(Initialize, bool());
MOCK_METHOD2(PasswordGrantSingleFactorSignInAsync, void(const AZStd::string& username, const AZStd::string& password));
MOCK_METHOD2(PasswordGrantMultiFactorSignInAsync, void(const AZStd::string& username, const AZStd::string& password));
MOCK_METHOD2(PasswordGrantMultiFactorConfirmSignInAsync, void(const AZStd::string& username, const AZStd::string& confirmationCode));
@ -495,6 +495,8 @@ namespace AWSClientAuthUnitTest
m_settingsRegistry->SetContext(m_serializeContext.get());
m_settingsRegistry->SetContext(m_registrationContext.get());
AZ::SettingsRegistry::Register(m_settingsRegistry.get());
AZ::ComponentApplicationBus::Handler::BusConnect();
AZ::Interface<AZ::ComponentApplicationRequests>::Register(this);
@ -555,6 +557,8 @@ namespace AWSClientAuthUnitTest
AWSClientAuth::AWSClientAuthRequestBus::Handler::BusDisconnect();
}
AZ::SettingsRegistry::Unregister(m_settingsRegistry.get());
m_testFolder.reset();
m_settingsRegistry.reset();
m_serializeContext.reset();
@ -660,8 +664,5 @@ namespace AWSClientAuthUnitTest
m_testFolderCreated = true;
return path;
}
};
};
}

@ -31,7 +31,7 @@ class AWSCognitoAuthenticationProviderTest
{
AWSClientAuthUnitTest::AWSClientAuthGemAllocatorFixture::SetUp();
m_cognitoAuthenticationProviderMock.Initialize(m_settingsRegistry);
m_cognitoAuthenticationProviderMock.Initialize();
AWSCore::AWSCoreRequestBus::Handler::BusConnect();
@ -98,7 +98,7 @@ TEST_F(AWSCognitoAuthenticationProviderTest, Initialize_Success)
{
EXPECT_CALL(m_awsResourceMappingRequestBusMock, GetResourceNameId(testing::_)).Times(1);
AWSClientAuthUnitTest::AWSCognitoAuthenticationProviderrLocalMock mock;
ASSERT_TRUE(mock.Initialize(m_settingsRegistry));
ASSERT_TRUE(mock.Initialize());
ASSERT_EQ(mock.m_cognitoAppClientId, AWSClientAuthUnitTest::TEST_RESOURCE_NAME_ID);
}
@ -260,5 +260,5 @@ TEST_F(AWSCognitoAuthenticationProviderTest, Initialize_Fail_EmptyResourceName)
{
AWSClientAuthUnitTest::AWSCognitoAuthenticationProviderrLocalMock mock;
EXPECT_CALL(m_awsResourceMappingRequestBusMock, GetResourceNameId(testing::_)).Times(1).WillOnce(testing::Return(""));
ASSERT_FALSE(mock.Initialize(m_settingsRegistry));
ASSERT_FALSE(mock.Initialize());
}

@ -28,7 +28,8 @@ protected:
AWSClientAuth::LWAProviderSetting::Reflect(*m_serializeContext);
AWSClientAuth::GoogleProviderSetting::Reflect(*m_serializeContext);
m_settingspath = AZStd::string::format("%s/%s/authenticationProvider.setreg",
AZStd::string settingspath = AZStd::string::format(
"%s/%s/authenticationProvider.setreg",
m_testFolder->c_str(), AZ::SettingsRegistryInterface::RegistryFolder);
CreateTestFile("authenticationProvider.setreg"
, R"({
@ -54,6 +55,7 @@ protected:
}
}
})");
m_settingsRegistry->MergeSettingsFile(settingspath, AZ::SettingsRegistryInterface::Format::JsonMergePatch, {});
m_mockController = AZStd::make_unique<testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderManagerLocalMock>>();
}
@ -66,20 +68,19 @@ protected:
public:
AZStd::unique_ptr<testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderManagerLocalMock>> m_mockController;
AZStd::string m_settingspath;
AZStd::vector<AZStd::string> m_enabledProviderNames { AWSClientAuth::ProvideNameEnumStringAWSCognitoIDP,
AWSClientAuth::ProvideNameEnumStringLoginWithAmazon, AWSClientAuth::ProvideNameEnumStringGoogle};
};
TEST_F(AuthenticationProviderManagerScriptCanvasTest, Initialize_Success)
{
ASSERT_TRUE(m_mockController->Initialize(m_enabledProviderNames, m_settingspath));
ASSERT_TRUE(m_mockController->Initialize(m_enabledProviderNames));
ASSERT_TRUE(m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP] != nullptr);
}
TEST_F(AuthenticationProviderManagerScriptCanvasTest, PasswordGrantSingleFactorSignInAsync_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
m_mockController->Initialize(m_enabledProviderNames);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock> *cognitoProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get();
EXPECT_CALL(*cognitoProviderMock, PasswordGrantSingleFactorSignInAsync(testing::_, testing::_)).Times(1);
@ -96,7 +97,7 @@ TEST_F(AuthenticationProviderManagerScriptCanvasTest, PasswordGrantSingleFactorS
TEST_F(AuthenticationProviderManagerScriptCanvasTest, PasswordGrantMultiFactorSignInAsync_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
m_mockController->Initialize(m_enabledProviderNames);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* cognitoProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get();
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* lwaProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::LoginWithAmazon].get();
@ -111,7 +112,7 @@ TEST_F(AuthenticationProviderManagerScriptCanvasTest, PasswordGrantMultiFactorSi
TEST_F(AuthenticationProviderManagerScriptCanvasTest, PasswordGrantMultiFactorConfirmSignInAsync_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
m_mockController->Initialize(m_enabledProviderNames);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock> *cognitoProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get();
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock> *lwaProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::LoginWithAmazon].get();
@ -126,7 +127,7 @@ TEST_F(AuthenticationProviderManagerScriptCanvasTest, PasswordGrantMultiFactorCo
TEST_F(AuthenticationProviderManagerScriptCanvasTest, DeviceCodeGrantSignInAsync_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
m_mockController->Initialize(m_enabledProviderNames);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* cognitoProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get();
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* lwaProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::LoginWithAmazon].get();
@ -142,7 +143,7 @@ TEST_F(AuthenticationProviderManagerScriptCanvasTest, DeviceCodeGrantSignInAsync
TEST_F(AuthenticationProviderManagerScriptCanvasTest, DeviceCodeGrantConfirmSignInAsync_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
m_mockController->Initialize(m_enabledProviderNames);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* cognitoProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get();
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* lwaProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::LoginWithAmazon].get();
@ -157,7 +158,7 @@ TEST_F(AuthenticationProviderManagerScriptCanvasTest, DeviceCodeGrantConfirmSign
TEST_F(AuthenticationProviderManagerScriptCanvasTest, RefreshTokenAsync_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
m_mockController->Initialize(m_enabledProviderNames);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock> *cognitoProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get();
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock> *lwaProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::LoginWithAmazon].get();
@ -172,7 +173,7 @@ TEST_F(AuthenticationProviderManagerScriptCanvasTest, RefreshTokenAsync_Success)
TEST_F(AuthenticationProviderManagerScriptCanvasTest, GetTokensWithRefreshAsync_ValidToken_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
m_mockController->Initialize(m_enabledProviderNames);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* cognitoProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get();
AWSClientAuth::AuthenticationTokens tokens(
@ -188,7 +189,7 @@ TEST_F(AuthenticationProviderManagerScriptCanvasTest, GetTokensWithRefreshAsync_
TEST_F(AuthenticationProviderManagerScriptCanvasTest, GetTokensWithRefreshAsync_InvalidToken_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
m_mockController->Initialize(m_enabledProviderNames);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* cognitoProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get();
AWSClientAuth::AuthenticationTokens tokens;
EXPECT_CALL(*cognitoProviderMock, GetAuthenticationTokens()).Times(1).WillOnce(testing::Return(tokens));
@ -209,7 +210,7 @@ TEST_F(AuthenticationProviderManagerScriptCanvasTest, GetTokensWithRefreshAsync_
TEST_F(AuthenticationProviderManagerScriptCanvasTest, GetTokens_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
m_mockController->Initialize(m_enabledProviderNames);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* cognitoProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get();
AWSClientAuth::AuthenticationTokens tokens(
@ -224,7 +225,7 @@ TEST_F(AuthenticationProviderManagerScriptCanvasTest, GetTokens_Success)
TEST_F(AuthenticationProviderManagerScriptCanvasTest, IsSignedIn_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
m_mockController->Initialize(m_enabledProviderNames);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* cognitoProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get();
AWSClientAuth::AuthenticationTokens tokens(
@ -238,7 +239,7 @@ TEST_F(AuthenticationProviderManagerScriptCanvasTest, IsSignedIn_Success)
TEST_F(AuthenticationProviderManagerScriptCanvasTest, SignOut_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
m_mockController->Initialize(m_enabledProviderNames);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* googleProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::Google].get();
EXPECT_CALL(*googleProviderMock, SignOut()).Times(1);
@ -248,9 +249,3 @@ TEST_F(AuthenticationProviderManagerScriptCanvasTest, SignOut_Success)
googleProviderMock = nullptr;
}
TEST_F(AuthenticationProviderManagerScriptCanvasTest, Initialize_Fail_InvalidPath)
{
AZ_TEST_START_TRACE_SUPPRESSION;
ASSERT_FALSE(m_mockController->Initialize(m_enabledProviderNames, ""));
AZ_TEST_STOP_TRACE_SUPPRESSION(2);
}

@ -27,7 +27,8 @@ protected:
AWSClientAuth::LWAProviderSetting::Reflect(*m_serializeContext);
AWSClientAuth::GoogleProviderSetting::Reflect(*m_serializeContext);
m_settingspath = AZStd::string::format("%s/%s/authenticationProvider.setreg",
AZStd::string settingspath = AZStd::string::format(
"%s/%s/authenticationProvider.setreg",
m_testFolder->c_str(), AZ::SettingsRegistryInterface::RegistryFolder);
CreateTestFile("authenticationProvider.setreg"
, R"({
@ -53,6 +54,7 @@ protected:
}
}
})");
m_settingsRegistry->MergeSettingsFile(settingspath, AZ::SettingsRegistryInterface::Format::JsonMergePatch, {});
m_mockController = AZStd::make_unique<testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderManagerLocalMock>>();
}
@ -65,20 +67,19 @@ protected:
public:
AZStd::unique_ptr<testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderManagerLocalMock>> m_mockController;
AZStd::string m_settingspath;
AZStd::vector<AWSClientAuth::ProviderNameEnum> m_enabledProviderNames {AWSClientAuth::ProviderNameEnum::AWSCognitoIDP,
AWSClientAuth::ProviderNameEnum::LoginWithAmazon, AWSClientAuth::ProviderNameEnum::Google};
};
TEST_F(AuthenticationProviderManagerTest, Initialize_Success)
{
ASSERT_TRUE(m_mockController->Initialize(m_enabledProviderNames, m_settingspath));
ASSERT_TRUE(m_mockController->Initialize(m_enabledProviderNames));
ASSERT_TRUE(m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP] != nullptr);
}
TEST_F(AuthenticationProviderManagerTest, PasswordGrantSingleFactorSignInAsync_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
m_mockController->Initialize(m_enabledProviderNames);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock> *cognitoProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get();
EXPECT_CALL(*cognitoProviderMock, PasswordGrantSingleFactorSignInAsync(testing::_, testing::_)).Times(1);
@ -95,7 +96,7 @@ TEST_F(AuthenticationProviderManagerTest, PasswordGrantSingleFactorSignInAsync_F
TEST_F(AuthenticationProviderManagerTest, PasswordGrantMultiFactorSignInAsync_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
m_mockController->Initialize(m_enabledProviderNames);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* cognitoProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get();
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* lwaProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::LoginWithAmazon].get();
@ -110,7 +111,7 @@ TEST_F(AuthenticationProviderManagerTest, PasswordGrantMultiFactorSignInAsync_Su
TEST_F(AuthenticationProviderManagerTest, PasswordGrantMultiFactorConfirmSignInAsync_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
m_mockController->Initialize(m_enabledProviderNames);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock> *cognitoProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get();
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock> *lwaProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::LoginWithAmazon].get();
@ -125,7 +126,7 @@ TEST_F(AuthenticationProviderManagerTest, PasswordGrantMultiFactorConfirmSignInA
TEST_F(AuthenticationProviderManagerTest, DeviceCodeGrantSignInAsync_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
m_mockController->Initialize(m_enabledProviderNames);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* cognitoProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get();
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* lwaProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::LoginWithAmazon].get();
@ -141,7 +142,7 @@ TEST_F(AuthenticationProviderManagerTest, DeviceCodeGrantSignInAsync_Success)
TEST_F(AuthenticationProviderManagerTest, DeviceCodeGrantConfirmSignInAsync_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
m_mockController->Initialize(m_enabledProviderNames);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* cognitoProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get();
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* lwaProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::LoginWithAmazon].get();
@ -156,7 +157,7 @@ TEST_F(AuthenticationProviderManagerTest, DeviceCodeGrantConfirmSignInAsync_Succ
TEST_F(AuthenticationProviderManagerTest, RefreshTokenAsync_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
m_mockController->Initialize(m_enabledProviderNames);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock> *cognitoProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get();
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock> *lwaProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::LoginWithAmazon].get();
@ -171,7 +172,7 @@ TEST_F(AuthenticationProviderManagerTest, RefreshTokenAsync_Success)
TEST_F(AuthenticationProviderManagerTest, GetTokensWithRefreshAsync_ValidToken_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
m_mockController->Initialize(m_enabledProviderNames);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* cognitoProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get();
AWSClientAuth::AuthenticationTokens tokens(
@ -187,7 +188,7 @@ TEST_F(AuthenticationProviderManagerTest, GetTokensWithRefreshAsync_ValidToken_S
TEST_F(AuthenticationProviderManagerTest, GetTokensWithRefreshAsync_InvalidToken_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
m_mockController->Initialize(m_enabledProviderNames);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* cognitoProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get();
AWSClientAuth::AuthenticationTokens tokens;
EXPECT_CALL(*cognitoProviderMock, GetAuthenticationTokens()).Times(1).WillOnce(testing::Return(tokens));
@ -208,7 +209,7 @@ TEST_F(AuthenticationProviderManagerTest, GetTokensWithRefreshAsync_NotInitializ
TEST_F(AuthenticationProviderManagerTest, GetTokens_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
m_mockController->Initialize(m_enabledProviderNames);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* cognitoProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get();
AWSClientAuth::AuthenticationTokens tokens(
@ -223,7 +224,7 @@ TEST_F(AuthenticationProviderManagerTest, GetTokens_Success)
TEST_F(AuthenticationProviderManagerTest, IsSignedIn_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
m_mockController->Initialize(m_enabledProviderNames);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* cognitoProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get();
AWSClientAuth::AuthenticationTokens tokens(
@ -237,7 +238,7 @@ TEST_F(AuthenticationProviderManagerTest, IsSignedIn_Success)
TEST_F(AuthenticationProviderManagerTest, SignOut_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
m_mockController->Initialize(m_enabledProviderNames);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* googleProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::Google].get();
EXPECT_CALL(*googleProviderMock, SignOut()).Times(1);
@ -247,9 +248,3 @@ TEST_F(AuthenticationProviderManagerTest, SignOut_Success)
googleProviderMock = nullptr;
}
TEST_F(AuthenticationProviderManagerTest, Initialize_Fail_InvalidPath)
{
AZ_TEST_START_TRACE_SUPPRESSION;
ASSERT_FALSE(m_mockController->Initialize(m_enabledProviderNames, ""));
AZ_TEST_STOP_TRACE_SUPPRESSION(2);
}

@ -47,7 +47,7 @@ class GoogleAuthenticationProviderTest
})");
m_settingsRegistry->MergeSettingsFile(path, AZ::SettingsRegistryInterface::Format::JsonMergePatch, {});
m_googleAuthenticationProviderLocalMock.Initialize(m_settingsRegistry);
m_googleAuthenticationProviderLocalMock.Initialize();
}
void TearDown() override
@ -63,7 +63,7 @@ public:
TEST_F(GoogleAuthenticationProviderTest, Initialize_Success)
{
AWSClientAuthUnitTest::GoogleAuthenticationProviderLocalMock mock;
ASSERT_TRUE(mock.Initialize(m_settingsRegistry));
ASSERT_TRUE(mock.Initialize());
ASSERT_EQ(mock.m_settings->m_appClientId, "TestGoogleClientId");
}
@ -117,14 +117,19 @@ TEST_F(GoogleAuthenticationProviderTest, RefreshTokensAsync_Fail_RequestHttpErro
TEST_F(GoogleAuthenticationProviderTest, Initialize_Fail_EmptyRegistry)
{
AZ::SettingsRegistry::Unregister(m_settingsRegistry.get());
AZStd::shared_ptr<AZ::SettingsRegistryImpl> registry = AZStd::make_shared<AZ::SettingsRegistryImpl>();
registry->SetContext(m_serializeContext.get());
AZ::SettingsRegistry::Register(registry.get());
AWSClientAuthUnitTest::GoogleAuthenticationProviderLocalMock mock;
ASSERT_FALSE(mock.Initialize(registry));
ASSERT_FALSE(mock.Initialize());
ASSERT_EQ(mock.m_settings->m_appClientId, "");
AZ::SettingsRegistry::Unregister(registry.get());
registry.reset();
// Restore
mock.Initialize(m_settingsRegistry);
AZ::SettingsRegistry::Register(m_settingsRegistry.get());
mock.Initialize();
}

@ -47,7 +47,7 @@ class LWAAuthenticationProviderTest
})");
m_settingsRegistry->MergeSettingsFile(path, AZ::SettingsRegistryInterface::Format::JsonMergePatch, {});
m_lwaAuthenticationProviderLocalMock.Initialize(m_settingsRegistry);
m_lwaAuthenticationProviderLocalMock.Initialize();
}
void TearDown() override
@ -63,7 +63,7 @@ public:
TEST_F(LWAAuthenticationProviderTest, Initialize_Success)
{
AWSClientAuthUnitTest::LWAAuthenticationProviderLocalMock mock;
ASSERT_TRUE(mock.Initialize(m_settingsRegistry));
ASSERT_TRUE(mock.Initialize());
ASSERT_EQ(mock.m_settings->m_appClientId, "TestLWAClientId");
}
@ -117,14 +117,19 @@ TEST_F(LWAAuthenticationProviderTest, RefreshTokensAsync_Fail_RequestHttpError)
TEST_F(LWAAuthenticationProviderTest, Initialize_Fail_EmptyRegistry)
{
AZ::SettingsRegistry::Unregister(m_settingsRegistry.get());
AZStd::shared_ptr<AZ::SettingsRegistryImpl> registry = AZStd::make_shared<AZ::SettingsRegistryImpl>();
registry->SetContext(m_serializeContext.get());
AZ::SettingsRegistry::Register(registry.get());
AWSClientAuthUnitTest::LWAAuthenticationProviderLocalMock mock;
ASSERT_FALSE(mock.Initialize(registry));
ASSERT_FALSE(mock.Initialize());
ASSERT_EQ(mock.m_settings->m_appClientId, "");
AZ::SettingsRegistry::Unregister(registry.get());
registry.reset();
// Restore
mock.Initialize(m_settingsRegistry);
AZ::SettingsRegistry::Register(m_settingsRegistry.get());
mock.Initialize();
}

@ -7,7 +7,6 @@
#pragma once
#include <AzCore/Settings/SettingsRegistryImpl.h>
#include <AzCore/std/string/string.h>
#include <AWSCoreInternalBus.h>
@ -35,8 +34,10 @@ namespace AWSCore
"Failed to get profile name, return default value instead.";
static constexpr const char ResourceMappingFileNameNotFoundErrorMessage[] =
"Failed to get resource mapping config file name, return empty value instead.";
static constexpr const char SettingsRegistryLoadFailureErrorMessage[] =
static constexpr const char SettingsRegistryFileLoadFailureErrorMessage[] =
"Failed to load AWSCore settings registry file.";
static constexpr const char GlobalSettingsRegistryLoadFailureErrorMessage[] =
"Failed to load AWSCore configurations from global settings registry.";
AWSCoreConfiguration();
@ -53,9 +54,6 @@ namespace AWSCore
void ReloadConfiguration() override;
private:
// Initialize settings registry reference by loading for project .setreg file
void InitSettingsRegistry();
// Initialize source project folder path
void InitSourceProjectFolderPath();
@ -66,7 +64,6 @@ namespace AWSCore
void ResetSettingsRegistryData();
AZStd::string m_sourceProjectFolder;
AZ::SettingsRegistryImpl m_settingsRegistry;
AZStd::string m_profileName;
AZStd::string m_resourceMappingConfigFileName;
};

@ -6,6 +6,8 @@
*/
#include <AzCore/IO/FileIO.h>
#include <AzCore/IO/Path/Path.h>
#include <AzCore/Settings/SettingsRegistryImpl.h>
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
#include <AzFramework/StringFunc/StringFunc.h>
@ -69,27 +71,6 @@ namespace AWSCore
void AWSCoreConfiguration::InitConfig()
{
InitSourceProjectFolderPath();
InitSettingsRegistry();
}
void AWSCoreConfiguration::InitSettingsRegistry()
{
if (m_sourceProjectFolder.empty())
{
AZ_Warning(AWSCoreConfigurationName, false, ProjectSourceFolderNotFoundErrorMessage);
return;
}
AZStd::string settingsRegistryPath = AZStd::string::format("%s/%s/%s",
m_sourceProjectFolder.c_str(), AZ::SettingsRegistryInterface::RegistryFolder, AWSCoreConfiguration::AWSCoreConfigurationFileName);
AzFramework::StringFunc::Path::Normalize(settingsRegistryPath);
if (!m_settingsRegistry.MergeSettingsFile(settingsRegistryPath, AZ::SettingsRegistryInterface::Format::JsonMergePatch, ""))
{
AZ_Warning(AWSCoreConfigurationName, false, SettingsRegistryLoadFailureErrorMessage);
return;
}
ParseSettingsRegistryValues();
}
@ -108,10 +89,17 @@ namespace AWSCore
void AWSCoreConfiguration::ParseSettingsRegistryValues()
{
AZ::SettingsRegistryInterface* settingsRegistry = AZ::SettingsRegistry::Get();
if (!settingsRegistry)
{
AZ_Warning(AWSCoreConfigurationName, false, GlobalSettingsRegistryLoadFailureErrorMessage);
return;
}
m_resourceMappingConfigFileName.clear();
auto resourceMappingConfigFileNamePath = AZStd::string::format("%s%s",
AZ::SettingsRegistryMergeUtils::OrganizationRootKey, AWSCoreResourceMappingConfigFileNameKey);
if (!m_settingsRegistry.Get(m_resourceMappingConfigFileName, resourceMappingConfigFileNamePath))
if (!settingsRegistry->Get(m_resourceMappingConfigFileName, resourceMappingConfigFileNamePath))
{
AZ_Warning(AWSCoreConfigurationName, false, ResourceMappingFileNameNotFoundErrorMessage);
}
@ -119,7 +107,7 @@ namespace AWSCore
m_profileName.clear();
auto profileNamePath = AZStd::string::format(
"%s%s", AZ::SettingsRegistryMergeUtils::OrganizationRootKey, AWSCoreProfileNameKey);
if (!m_settingsRegistry.Get(m_profileName, profileNamePath))
if (!settingsRegistry->Get(m_profileName, profileNamePath))
{
AZ_Warning(AWSCoreConfigurationName, false, ProfileNameNotFoundErrorMessage);
m_profileName = AWSCoreDefaultProfileName;
@ -128,20 +116,43 @@ namespace AWSCore
void AWSCoreConfiguration::ResetSettingsRegistryData()
{
AZ::SettingsRegistryInterface* settingsRegistry = AZ::SettingsRegistry::Get();
if (!settingsRegistry)
{
AZ_Warning(AWSCoreConfigurationName, false, GlobalSettingsRegistryLoadFailureErrorMessage);
return;
}
auto profileNamePath = AZStd::string::format("%s%s",
AZ::SettingsRegistryMergeUtils::OrganizationRootKey, AWSCoreProfileNameKey);
m_settingsRegistry.Remove(profileNamePath);
settingsRegistry->Remove(profileNamePath);
m_profileName = AWSCoreDefaultProfileName;
auto resourceMappingConfigFileNamePath = AZStd::string::format("%s%s",
AZ::SettingsRegistryMergeUtils::OrganizationRootKey, AWSCoreResourceMappingConfigFileNameKey);
m_settingsRegistry.Remove(resourceMappingConfigFileNamePath);
settingsRegistry->Remove(resourceMappingConfigFileNamePath);
m_resourceMappingConfigFileName.clear();
// Reload the AWSCore setting registry file from disk.
if (m_sourceProjectFolder.empty())
{
AZ_Warning(AWSCoreConfigurationName, false, SettingsRegistryFileLoadFailureErrorMessage);
return;
}
auto settingsRegistryPath = AZ::IO::FixedMaxPath(AZStd::string_view{ m_sourceProjectFolder }) /
AZ::SettingsRegistryInterface::RegistryFolder /
AWSCoreConfiguration::AWSCoreConfigurationFileName;
if (!settingsRegistry->MergeSettingsFile(settingsRegistryPath.c_str(), AZ::SettingsRegistryInterface::Format::JsonMergePatch, ""))
{
AZ_Warning(AWSCoreConfigurationName, false, SettingsRegistryFileLoadFailureErrorMessage);
return;
}
}
void AWSCoreConfiguration::ReloadConfiguration()
{
ResetSettingsRegistryData();
InitSettingsRegistry();
ParseSettingsRegistryValues();
}
} // namespace AWSCore

@ -38,9 +38,8 @@ namespace AWSCore
constexpr char AWSAttributionDelaySecondsKey[] = "/Amazon/AWS/Preferences/AWSAttributionDelaySeconds";
constexpr char AWSAttributionLastTimeStampKey[] = "/Amazon/AWS/Preferences/AWSAttributionLastTimeStamp";
constexpr char AWSAttributionConsentShownKey[] = "/Amazon/AWS/Preferences/AWSAttributionConsentShown";
constexpr char AWSAttributionApiId[] = "2zxvvmv8d7";
constexpr char AWSAttributionChinaApiId[] = "";
constexpr char AWSAttributionApiStage[] = "prod";
constexpr char AWSAttributionEndpoint[] = "https://o3deattribution.us-east-1.amazonaws.com";
constexpr char AWSAttributionChinaEndpoint[] = "";
const int AWSAttributionDefaultDelayInDays = 7;
AWSAttributionManager::AWSAttributionManager()
@ -253,17 +252,17 @@ namespace AWSCore
// Assumption to determine China region is the default profile is set to China region.
auto profile_name = Aws::Auth::GetConfigProfileName();
Aws::Client::ClientConfiguration clientConfig(profile_name.c_str());
AZStd::string apiId = AWSAttributionApiId;
if (clientConfig.region == Aws::Region::CN_NORTH_1 || clientConfig.region == Aws::Region::CN_NORTHWEST_1)
{
config->region = Aws::Region::CN_NORTH_1;
apiId = AWSAttributionChinaApiId;
config->endpointOverride = AWSAttributionChinaEndpoint;
}
else
{
config->region = Aws::Region::US_EAST_1;
config->endpointOverride = AWSAttributionEndpoint;
}
config->region = Aws::Region::US_WEST_2;
config->endpointOverride =
AWSResourceMappingUtils::FormatRESTApiUrl(apiId, config->region.value().c_str(), AWSAttributionApiStage).c_str();
}
bool AWSAttributionManager::CheckConsentShown()

@ -31,7 +31,7 @@ namespace AWSCore
void AWSResourceMappingManager::ActivateManager()
{
ReloadConfigFile(true);
ReloadConfigFile();
AWSResourceMappingRequestBus::Handler::BusConnect();
}

@ -67,10 +67,13 @@ protected:
m_serializeContext = AZStd::make_unique<AZ::SerializeContext>();
m_serializeContext->CreateEditContext();
m_behaviorContext = AZStd::make_unique<AZ::BehaviorContext>();
m_componentDescriptor.reset(AWSCoreSystemComponent::CreateDescriptor());
m_componentDescriptor->Reflect(m_serializeContext.get());
m_componentDescriptor->Reflect(m_behaviorContext.get());
m_settingsRegistry->SetContext(m_serializeContext.get());
m_entity = aznew AZ::Entity();
m_coreSystemsComponent.reset(m_entity->CreateComponent<AWSCoreSystemComponent>());
}

@ -60,6 +60,8 @@ public:
AzFramework::StringFunc::Path::Normalize(m_normalizedSetRegFolderPath);
m_localFileIO->SetAlias("@devassets@", m_normalizedSourceProjectFolder.c_str());
CreateTestSetRegFile(TEST_VALID_RESOURCE_MAPPING_SETREG);
}
void TearDown() override
@ -73,11 +75,11 @@ public:
}
AZStd::unique_ptr<AWSCore::AWSCoreConfiguration> m_awsCoreConfiguration;
AZStd::string m_normalizedSetRegFilePath;
private:
AZStd::string m_normalizedSourceProjectFolder;
AZStd::string m_normalizedSetRegFolderPath;
AZStd::string m_normalizedSetRegFilePath;
void CreateTestFile(const AZStd::string& filePath, const AZStd::string& fileContent)
{
@ -118,17 +120,9 @@ private:
TEST_F(AWSCoreConfigurationTest, InitConfig_NoSourceProjectFolderFound_ReturnEmptyConfigFilePath)
{
m_settingsRegistry->MergeSettingsFile(m_normalizedSetRegFilePath, AZ::SettingsRegistryInterface::Format::JsonMergePatch, {});
m_localFileIO->ClearAlias("@devassets@");
AZ_TEST_START_TRACE_SUPPRESSION;
m_awsCoreConfiguration->InitConfig();
AZ_TEST_STOP_TRACE_SUPPRESSION(1); // expect the above have thrown an AZ_Error
auto actualConfigFilePath = m_awsCoreConfiguration->GetResourceMappingConfigFilePath();
EXPECT_TRUE(actualConfigFilePath.empty());
}
TEST_F(AWSCoreConfigurationTest, InitConfig_NoSettingsRegistryFileFound_ReturnEmptyConfigFilePath)
{
AZ_TEST_START_TRACE_SUPPRESSION;
m_awsCoreConfiguration->InitConfig();
AZ_TEST_STOP_TRACE_SUPPRESSION(1); // expect the above have thrown an AZ_Error
@ -140,6 +134,7 @@ TEST_F(AWSCoreConfigurationTest, InitConfig_NoSettingsRegistryFileFound_ReturnEm
TEST_F(AWSCoreConfigurationTest, InitConfig_SettingsRegistryIsEmpty_ReturnEmptyConfigFilePath)
{
CreateTestSetRegFile(TEST_INVALID_RESOURCE_MAPPING_SETREG);
m_settingsRegistry->MergeSettingsFile(m_normalizedSetRegFilePath, AZ::SettingsRegistryInterface::Format::JsonMergePatch, {});
m_awsCoreConfiguration->InitConfig();
auto actualConfigFilePath = m_awsCoreConfiguration->GetResourceMappingConfigFilePath();
@ -148,7 +143,7 @@ TEST_F(AWSCoreConfigurationTest, InitConfig_SettingsRegistryIsEmpty_ReturnEmptyC
TEST_F(AWSCoreConfigurationTest, InitConfig_LoadValidSettingsRegistry_ReturnNonEmptyConfigFilePath)
{
CreateTestSetRegFile(TEST_VALID_RESOURCE_MAPPING_SETREG);
m_settingsRegistry->MergeSettingsFile(m_normalizedSetRegFilePath, AZ::SettingsRegistryInterface::Format::JsonMergePatch, {});
m_awsCoreConfiguration->InitConfig();
auto actualConfigFilePath = m_awsCoreConfiguration->GetResourceMappingConfigFilePath();
@ -157,6 +152,7 @@ TEST_F(AWSCoreConfigurationTest, InitConfig_LoadValidSettingsRegistry_ReturnNonE
TEST_F(AWSCoreConfigurationTest, ReloadConfiguration_NoSourceProjectFolderFound_ReturnEmptyConfigFilePath)
{
m_settingsRegistry->MergeSettingsFile(m_normalizedSetRegFilePath, AZ::SettingsRegistryInterface::Format::JsonMergePatch, {});
m_localFileIO->ClearAlias("@devassets@");
m_awsCoreConfiguration->ReloadConfiguration();
@ -167,6 +163,7 @@ TEST_F(AWSCoreConfigurationTest, ReloadConfiguration_NoSourceProjectFolderFound_
TEST_F(AWSCoreConfigurationTest, ReloadConfiguration_LoadValidSettingsRegistryAfterInvalidOne_ReturnNonEmptyConfigFilePath)
{
CreateTestSetRegFile(TEST_INVALID_RESOURCE_MAPPING_SETREG);
m_settingsRegistry->MergeSettingsFile(m_normalizedSetRegFilePath, AZ::SettingsRegistryInterface::Format::JsonMergePatch, {});
m_awsCoreConfiguration->InitConfig();
auto actualConfigFilePath = m_awsCoreConfiguration->GetResourceMappingConfigFilePath();
@ -185,7 +182,7 @@ TEST_F(AWSCoreConfigurationTest, ReloadConfiguration_LoadValidSettingsRegistryAf
TEST_F(AWSCoreConfigurationTest, ReloadConfiguration_LoadInvalidSettingsRegistryAfterValidOne_ReturnEmptyConfigFilePath)
{
CreateTestSetRegFile(TEST_VALID_RESOURCE_MAPPING_SETREG);
m_settingsRegistry->MergeSettingsFile(m_normalizedSetRegFilePath, AZ::SettingsRegistryInterface::Format::JsonMergePatch, {});
m_awsCoreConfiguration->InitConfig();
auto actualConfigFilePath = m_awsCoreConfiguration->GetResourceMappingConfigFilePath();

@ -14,7 +14,6 @@
#include <AzCore/std/smart_ptr/make_shared.h>
#include <AzCore/base.h>
#include <AzCore/Settings/SettingsRegistry.h>
#include <AzCore/Settings/SettingsRegistryImpl.h>
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
#include <AzCore/Serialization/Json/JsonSystemComponent.h>
#include <AzCore/Serialization/Json/RegistrationContext.h>
@ -161,7 +160,6 @@ namespace AWSAttributionUnitTest
protected:
AZStd::shared_ptr<AZ::SerializeContext> m_serializeContext;
AZStd::unique_ptr<AZ::JsonRegistrationContext> m_registrationContext;
AZStd::shared_ptr<AZ::SettingsRegistryImpl> m_settingsRegistry;
AZStd::unique_ptr<AZ::JobContext> m_jobContext;
AZStd::unique_ptr<AZ::JobCancelGroup> m_jobCancelGroup;
AZStd::unique_ptr<AZ::JobManager> m_jobManager;
@ -186,13 +184,9 @@ namespace AWSAttributionUnitTest
AZ::JsonSystemComponent::Reflect(m_registrationContext.get());
m_settingsRegistry = AZStd::make_unique<AZ::SettingsRegistryImpl>();
m_settingsRegistry->SetContext(m_serializeContext.get());
m_settingsRegistry->SetContext(m_registrationContext.get());
AZ::SettingsRegistry::Register(m_settingsRegistry.get());
AZ::JobManagerDesc jobManagerDesc;
AZ::JobManagerThreadDesc threadDesc;
@ -210,9 +204,6 @@ namespace AWSAttributionUnitTest
m_jobCancelGroup.reset();
m_jobManager.reset();
AZ::SettingsRegistry::Unregister(m_settingsRegistry.get());
m_settingsRegistry.reset();
m_serializeContext.reset();
m_registrationContext.reset();
@ -427,8 +418,8 @@ namespace AWSAttributionUnitTest
manager.SetApiEndpointAndRegion(config);
// THEN
ASSERT_TRUE(config->region == Aws::Region::US_WEST_2);
ASSERT_TRUE(config->endpointOverride->find("execute-api.us-west-2.amazonaws.com") != Aws::String::npos);
ASSERT_TRUE(config->region == Aws::Region::US_EAST_1);
ASSERT_TRUE(config->endpointOverride->find("o3deattribution.us-east-1.amazonaws.com") != Aws::String::npos);
delete config;
}

@ -8,7 +8,6 @@
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/Serialization/EditContext.h>
#include <AzCore/std/smart_ptr/unique_ptr.h>
#include <AzCore/Settings/SettingsRegistryImpl.h>
#include <AzCore/Serialization/Json/JsonSystemComponent.h>
#include <AzCore/Serialization/Json/RegistrationContext.h>
#include <AzTest/AzTest.h>
@ -87,13 +86,9 @@ namespace AWSCoreUnitTest
m_componentDescriptor->Reflect(m_serializeContext.get());
m_componentDescriptor->Reflect(m_behaviorContext.get());
m_settingsRegistry = AZStd::make_unique<AZ::SettingsRegistryImpl>();
m_settingsRegistry->SetContext(m_serializeContext.get());
m_settingsRegistry->SetContext(m_registrationContext.get());
AZ::SettingsRegistry::Register(m_settingsRegistry.get());
m_entity = aznew AZ::Entity();
m_awsCoreSystemComponentMock = aznew testing::NiceMock<AWSCoreSystemComponentMock>();
m_entity->AddComponent(m_awsCoreSystemComponentMock);
@ -113,7 +108,6 @@ namespace AWSCoreUnitTest
m_awsCoreComponentDescriptor.reset();
m_componentDescriptor.reset();
m_behaviorContext.reset();
m_settingsRegistry.reset();
m_registrationContext.reset();
m_serializeContext.reset();
AWSCoreFixture::TearDown();
@ -130,7 +124,6 @@ namespace AWSCoreUnitTest
AZStd::unique_ptr<AZ::JsonRegistrationContext> m_registrationContext;
AZStd::unique_ptr<AZ::ComponentDescriptor> m_componentDescriptor;
AZStd::unique_ptr<AZ::ComponentDescriptor> m_awsCoreComponentDescriptor;
AZStd::shared_ptr<AZ::SettingsRegistryImpl> m_settingsRegistry;
};
TEST_F(AWSAttributionSystemComponentTest, SystemComponentInitActivate_Success)

@ -171,7 +171,7 @@ TEST_F(AWSResourceMappingManagerTest, ActivateManager_ParseInvalidConfigFile_Con
AZStd::string actualRegion;
AWSResourceMappingRequestBus::BroadcastResult(actualAccountId, &AWSResourceMappingRequests::GetDefaultAccountId);
AWSResourceMappingRequestBus::BroadcastResult(actualRegion, &AWSResourceMappingRequests::GetDefaultRegion);
EXPECT_EQ(m_reloadConfigurationCounter, 1);
EXPECT_EQ(m_reloadConfigurationCounter, 0);
EXPECT_TRUE(actualAccountId.empty());
EXPECT_TRUE(actualRegion.empty());
EXPECT_TRUE(m_resourceMappingManager->GetStatus() == AWSResourceMappingManager::Status::Error);
@ -186,7 +186,7 @@ TEST_F(AWSResourceMappingManagerTest, ActivateManager_ParseValidConfigFile_Confi
AZStd::string actualRegion;
AWSResourceMappingRequestBus::BroadcastResult(actualAccountId, &AWSResourceMappingRequests::GetDefaultAccountId);
AWSResourceMappingRequestBus::BroadcastResult(actualRegion, &AWSResourceMappingRequests::GetDefaultRegion);
EXPECT_EQ(m_reloadConfigurationCounter, 1);
EXPECT_EQ(m_reloadConfigurationCounter, 0);
EXPECT_FALSE(actualAccountId.empty());
EXPECT_FALSE(actualRegion.empty());
EXPECT_TRUE(m_resourceMappingManager->GetStatus() == AWSResourceMappingManager::Status::Ready);
@ -413,7 +413,7 @@ TEST_F(AWSResourceMappingManagerTest, ReloadConfigFile_ParseValidConfigFileAfter
AZStd::string actualRegion;
AWSResourceMappingRequestBus::BroadcastResult(actualAccountId, &AWSResourceMappingRequests::GetDefaultAccountId);
AWSResourceMappingRequestBus::BroadcastResult(actualRegion, &AWSResourceMappingRequests::GetDefaultRegion);
EXPECT_EQ(m_reloadConfigurationCounter, 1);
EXPECT_EQ(m_reloadConfigurationCounter, 0);
EXPECT_TRUE(actualAccountId.empty());
EXPECT_TRUE(actualRegion.empty());
EXPECT_TRUE(m_resourceMappingManager->GetStatus() == AWSResourceMappingManager::Status::Error);
@ -423,7 +423,7 @@ TEST_F(AWSResourceMappingManagerTest, ReloadConfigFile_ParseValidConfigFileAfter
AWSResourceMappingRequestBus::BroadcastResult(actualAccountId, &AWSResourceMappingRequests::GetDefaultAccountId);
AWSResourceMappingRequestBus::BroadcastResult(actualRegion, &AWSResourceMappingRequests::GetDefaultRegion);
EXPECT_EQ(m_reloadConfigurationCounter, 1);
EXPECT_EQ(m_reloadConfigurationCounter, 0);
EXPECT_FALSE(actualAccountId.empty());
EXPECT_FALSE(actualRegion.empty());
EXPECT_TRUE(m_resourceMappingManager->GetStatus() == AWSResourceMappingManager::Status::Ready);

@ -9,6 +9,7 @@
#include <AzCore/Memory/PoolAllocator.h>
#include <AzCore/UnitTest/TestTypes.h>
#include <AzCore/Settings/SettingsRegistryImpl.h>
#include <AzFramework/IO/LocalFileIO.h>
#include <Framework/JsonObjectHandler.h>
@ -117,10 +118,16 @@ public:
m_otherFileIO = AZ::IO::FileIOBase::GetInstance();
AZ::IO::FileIOBase::SetInstance(nullptr);
AZ::IO::FileIOBase::SetInstance(m_localFileIO);
m_settingsRegistry = AZStd::make_unique<AZ::SettingsRegistryImpl>();
AZ::SettingsRegistry::Register(m_settingsRegistry.get());
}
void TearDown() override
{
AZ::SettingsRegistry::Unregister(m_settingsRegistry.get());
m_settingsRegistry.reset();
AZ::IO::FileIOBase::SetInstance(nullptr);
if (m_otherFileIO)
@ -160,4 +167,7 @@ public:
private:
AZ::IO::FileIOBase* m_otherFileIO = nullptr;
protected:
AZStd::unique_ptr<AZ::SettingsRegistryImpl> m_settingsRegistry;
};

@ -17,12 +17,16 @@ namespace AWSMetrics
class ClientConfiguration
{
public:
static constexpr const char AWSMetricsMaxQueueSizeInMbKey[] = "/Gems/AWSMetrics/MaxQueueSizeInMb";
static constexpr const char AWSMetricsQueueFlushPeriodInSecondsKey[] = "/Gems/AWSMetrics/QueueFlushPeriodInSeconds";
static constexpr const char AWSMetricsOfflineRecordingEnabledKey[] = "/Gems/AWSMetrics/OfflineRecording";
static constexpr const char AWSMetricsMaxNumRetriesKey[] = "/Gems/AWSMetrics/MaxNumRetries";
ClientConfiguration();
//! Reset the client settings based on the provided configuration file.
//! @param settingsRegistryPath Full path to the configuration file.
//! Initialize the client settings based on the global setting registry.
//! @return whether the operation is successful
bool ResetClientConfiguration(const AZStd::string& settingsRegistryPath);
bool InitClientConfiguration();
//! Retrieve the max queue size setting.
//! @return Max queue size in bytes.

@ -33,9 +33,8 @@ namespace AWSMetrics
~MetricsManager();
//! Initializing the metrics manager
//! @param settingsRegistryPath Path to the settings registry file.
//! @return Whether the operation is successful.
bool Init(const AZStd::string& settingsRegistryPath = "");
bool Init();
//! Start sending metircs to the backend or a local file.
void StartMetrics();
//! Stop sending metircs to the backend or a local file.

@ -192,11 +192,7 @@ namespace AWSMetrics
void AWSMetricsSystemComponent::Init()
{
AZStd::string priorAlias = AZ::IO::FileIOBase::GetInstance()->GetAlias("@devroot@");
AZStd::string configFilePath = priorAlias + "\\Gems\\AWSMetrics\\Code\\" + AZ::SettingsRegistryInterface::RegistryFolder + "\\awsMetricsClientConfiguration.setreg";
AzFramework::StringFunc::Path::Normalize(configFilePath);
m_metricsManager->Init(configFilePath);
m_metricsManager->Init();
}
void AWSMetricsSystemComponent::Activate()

@ -9,6 +9,7 @@
#include <AzCore/IO/FileIO.h>
#include <AzCore/Settings/SettingsRegistryImpl.h>
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
#include <AzCore/std/smart_ptr/unique_ptr.h>
#include <AzFramework/StringFunc/StringFunc.h>
@ -23,38 +24,44 @@ namespace AWSMetrics
{
}
bool ClientConfiguration::ResetClientConfiguration(const AZStd::string& settingsRegistryPath)
bool ClientConfiguration::InitClientConfiguration()
{
AZStd::unique_ptr<AZ::SettingsRegistryInterface> settingsRegistry = AZStd::make_unique<AZ::SettingsRegistryImpl>();
AZ_Printf("AWSMetrics", "Reset client settings using the confiugration file %s", settingsRegistryPath.c_str());
if (!settingsRegistry->MergeSettingsFile(settingsRegistryPath, AZ::SettingsRegistryInterface::Format::JsonMergePatch))
AZ::SettingsRegistryInterface* settingsRegistry = AZ::SettingsRegistry::Get();
if (!settingsRegistry)
{
AZ_Warning("AWSMetrics", false, "Failed to merge the configuration file");
AZ_Warning("AWSMetrics", false, "Failed to load the setting registry");
return false;
}
if (!settingsRegistry->Get(m_maxQueueSizeInMb, "/Amazon/Gems/AWSMetrics/MaxQueueSizeInMb"))
if (!settingsRegistry->Get(
m_maxQueueSizeInMb,
AZStd::string::format("%s%s", AZ::SettingsRegistryMergeUtils::OrganizationRootKey, AWSMetricsMaxQueueSizeInMbKey)))
{
AZ_Warning("AWSMetrics", false, "Failed to read the maximum queue size setting in the configuration file");
AZ_Warning("AWSMetrics", false, "Failed to read the maximum queue size setting from the setting registry");
return false;
}
if (!settingsRegistry->Get(m_queueFlushPeriodInSeconds, "/Amazon/Gems/AWSMetrics/QueueFlushPeriodInSeconds"))
if (!settingsRegistry->Get(
m_queueFlushPeriodInSeconds,
AZStd::string::format("%s%s", AZ::SettingsRegistryMergeUtils::OrganizationRootKey, AWSMetricsQueueFlushPeriodInSecondsKey)))
{
AZ_Warning("AWSMetrics", false, "Failed to read the queue flush period setting in the configuration file");
AZ_Warning("AWSMetrics", false, "Failed to read the queue flush period setting from the setting registry");
return false;
}
bool enableOfflineRecording = false;
if (!settingsRegistry->Get(enableOfflineRecording, "/Amazon/Gems/AWSMetrics/OfflineRecording"))
if (!settingsRegistry->Get(
enableOfflineRecording,
AZStd::string::format("%s%s", AZ::SettingsRegistryMergeUtils::OrganizationRootKey, AWSMetricsOfflineRecordingEnabledKey)))
{
AZ_Warning("AWSMetrics", false, "Failed to read the submission target setting in the configuration file");
AZ_Warning("AWSMetrics", false, "Failed to read the submission target setting from the setting registry");
return false;
}
m_offlineRecordingEnabled = enableOfflineRecording;
if (!settingsRegistry->Get(m_maxNumRetries, "/Amazon/Gems/AWSMetrics/MaxNumRetries"))
if (!settingsRegistry->Get(
m_maxNumRetries,
AZStd::string::format("%s%s", AZ::SettingsRegistryMergeUtils::OrganizationRootKey, AWSMetricsMaxNumRetriesKey)))
{
AZ_Warning("AWSMetrics", false, "Failed to read the maximum number of retries setting in the configuration file");
return false;

@ -34,9 +34,9 @@ namespace AWSMetrics
ShutdownMetrics();
}
bool MetricsManager::Init(const AZStd::string& settingsRegistryPath)
bool MetricsManager::Init()
{
if (!m_clientConfiguration->ResetClientConfiguration(settingsRegistryPath))
if (!m_clientConfiguration->InitClientConfiguration())
{
return false;
}

@ -52,10 +52,14 @@ namespace AWSMetrics
m_settingsRegistry->SetContext(m_serializeContext.get());
m_settingsRegistry->SetContext(m_registrationContext.get());
AZ::SettingsRegistry::Register(m_settingsRegistry.get());
}
void TearDown() override
{
AZ::SettingsRegistry::Unregister(m_settingsRegistry.get());
m_registrationContext->EnableRemoveReflection();
AZ::JsonSystemComponent::Reflect(m_registrationContext.get());
m_registrationContext->DisableRemoveReflection();
@ -130,7 +134,7 @@ namespace AWSMetrics
AZStd::unique_ptr<AZ::SerializeContext> m_serializeContext;
AZStd::unique_ptr<AZ::JsonRegistrationContext> m_registrationContext;
AZStd::shared_ptr<AZ::SettingsRegistryImpl> m_settingsRegistry;
AZStd::unique_ptr<AZ::SettingsRegistryImpl> m_settingsRegistry;
private:
AZStd::string GetTestFolderPath()

@ -135,7 +135,8 @@ namespace AWSMetrics
m_metricsManager = AZStd::make_unique<MetricsManager>();
AZStd::string configFilePath = CreateClientConfigFile(true, (double) TestMetricsEventSizeInBytes / MbToBytes * 2, DefaultFlushPeriodInSeconds, 0);
m_metricsManager->Init(configFilePath);
m_settingsRegistry->MergeSettingsFile(configFilePath, AZ::SettingsRegistryInterface::Format::JsonMergePatch, {});
m_metricsManager->Init();
RemoveFile(m_metricsManager->GetMetricsFilePath());
@ -161,7 +162,8 @@ namespace AWSMetrics
RevertMockIOToLocalFileIO();
AZStd::string configFilePath = CreateClientConfigFile(offlineRecordingEnabled, maxQueueSizeInMb, queueFlushPeriodInSeconds, MaxNumRetries);
m_metricsManager->Init(configFilePath);
m_settingsRegistry->MergeSettingsFile(configFilePath, AZ::SettingsRegistryInterface::Format::JsonMergePatch, {});
m_metricsManager->Init();
ReplaceLocalFileIOWithMockIO();
}
@ -555,10 +557,11 @@ namespace AWSMetrics
AZStd::unique_ptr<ClientConfiguration> m_clientConfiguration;
};
TEST_F(ClientConfigurationTest, ResetClientConfiguration_ValidConfigurationFile_Success)
TEST_F(ClientConfigurationTest, ResetClientConfiguration_ValidClientConfiguration_Success)
{
AZStd::string configFilePath = CreateClientConfigFile(true, DEFAULT_MAX_QUEUE_SIZE_IN_MB, DefaultFlushPeriodInSeconds, DEFAULT_MAX_NUM_RETRIES);
ASSERT_TRUE(m_clientConfiguration->ResetClientConfiguration(configFilePath));
m_settingsRegistry->MergeSettingsFile(configFilePath, AZ::SettingsRegistryInterface::Format::JsonMergePatch, {});
ASSERT_TRUE(m_clientConfiguration->InitClientConfiguration());
ASSERT_TRUE(m_clientConfiguration->OfflineRecordingEnabled());
ASSERT_EQ(m_clientConfiguration->GetMaxQueueSizeInBytes(), DEFAULT_MAX_QUEUE_SIZE_IN_MB * 1000000);
@ -573,12 +576,4 @@ namespace AWSMetrics
ASSERT_EQ(strcmp(m_clientConfiguration->GetMetricsFileDir(), resolvedPath), 0);
ASSERT_EQ(m_clientConfiguration->GetMetricsFileFullPath(), expectedMetricsFilePath);
}
TEST_F(ClientConfigurationTest, ResetClientConfiguration_InvalidConfigurationFile_Fail)
{
AZStd::string configFilePath = "invalidConfig";
AZ_TEST_START_TRACE_SUPPRESSION;
ASSERT_FALSE(m_clientConfiguration->ResetClientConfiguration(configFilePath));
AZ_TEST_STOP_TRACE_SUPPRESSION(1);
}
}

@ -14,3 +14,11 @@ add_subdirectory(RPI)
add_subdirectory(Tools)
add_subdirectory(Utils)
# The "Atom" Gem will alias the real Atom_AtomBridge target variants
# allows the enabling and disabling the "Atom" Gem to build the pre-requisite dependencies
ly_create_alias(NAME Atom.Clients NAMESPACE Gem TARGETS Gem::Atom_AtomBridge.Clients)
ly_create_alias(NAME Atom.Servers NAMESPACE Gem TARGETS Gem::Atom_AtomBridge.Servers)
if(PAL_TRAIT_BUILD_HOST_TOOLS)
ly_create_alias(NAME Atom.Builders NAMESPACE Gem TARGETS Gem::Atom_AtomBridge.Builders)
ly_create_alias(NAME Atom.Tools NAMESPACE Gem TARGETS Gem::Atom_AtomBridge.Tools)
endif()

@ -33,7 +33,12 @@ bool m_detail_normal_flipX; \
bool m_detail_normal_flipY; \
\
float3x3 m_detailUvMatrix; \
float3x3 m_detailUvMatrixInverse;
float4 m_detailUvMatrixPad; \
float3x3 m_detailUvMatrixInverse; \
float4 m_detailUvMatrixInversePad;
// [GFX TODO][ATOM-14595] m_detailUvMatrixPad and m_detailUvMatrixInversePad are a workaround for a data stomping bug.
// Remove them once the bug is fixed.
#define COMMON_OPTIONS_DETAIL_MAPS(prefix) \

@ -82,6 +82,12 @@ function ProcessEditor(context)
context:SetMaterialPropertyVisibility("opacity.factor", mainVisibility)
context:SetMaterialPropertyVisibility("opacity.doubleSided", mainVisibility)
if(opacityMode == OpacityMode_Blended or opacityMode == OpacityMode_TintedTransparent) then
context:SetMaterialPropertyVisibility("opacity.alphaAffectsSpecular", MaterialPropertyVisibility_Enabled)
else
context:SetMaterialPropertyVisibility("opacity.alphaAffectsSpecular", MaterialPropertyVisibility_Hidden)
end
if(mainVisibility == MaterialPropertyVisibility_Enabled) then
local alphaSource = context:GetMaterialPropertyValue_enum("opacity.alphaSource")

@ -54,7 +54,7 @@
"Attachment": "Depth"
},
"ImageDescriptor": {
"Format": "R32_FLOAT"
"Format": "R16_FLOAT"
}
}
],

@ -54,7 +54,7 @@
"Attachment": "Input"
},
"ImageDescriptor": {
"Format": "R32_FLOAT"
"Format": "R16_FLOAT"
}
}
],

@ -356,8 +356,9 @@ float DirectionalLightShadow::GetVisibilityFromLightEsm()
{
const float distanceWithinCameraView = depthDiff / (1. - distanceMin);
const float3 coord = float3(shadowCoord.xy, indexOfCascade);
const float expDepthInShadowmap = expShadowmap.Sample(PassSrg::LinearSampler, coord).r;
const float ratio = exp(-EsmExponentialShift * distanceWithinCameraView) * expDepthInShadowmap;
const float occluder = expShadowmap.Sample(PassSrg::LinearSampler, coord).r;
const float exponent = -EsmExponentialShift * (distanceWithinCameraView - occluder);
const float ratio = exp(exponent);
m_debugInfo.m_cascadeIndex = indexOfCascade;
return saturate(ratio);
@ -385,8 +386,9 @@ float DirectionalLightShadow::GetVisibilityFromLightEsmPcf()
{
const float distanceWithinCameraView = depthDiff / (1. - distanceMin);
const float3 coord = float3(shadowCoord.xy, indexOfCascade);
const float expDepthInShadowmap = expShadowmap.Sample(PassSrg::LinearSampler, coord).r;
float ratio = exp(-EsmExponentialShift * distanceWithinCameraView) * expDepthInShadowmap;
const float occluder = expShadowmap.Sample(PassSrg::LinearSampler, coord).r;
const float exponent = -EsmExponentialShift * (distanceWithinCameraView - occluder);
float ratio = exp(exponent);
static const float pcfFallbackThreshold = 1.04;
if (ratio > pcfFallbackThreshold)

@ -63,12 +63,7 @@ void MainCS(uint3 dispatchId: SV_DispatchThreadID)
// So this converts it to "depth" to emphasize the difference
// within the frustum.
const float depth = (depthInClip - distanceMin) / (1. - distanceMin);
// Todo: Expose Esm exponent slider for directional lights
// This would remove the exp calculation below, collapsing it into a subtraction in DirectionalLightShadow.azsli
// ATOM-15775
const float outValue = exp(EsmExponentialShift * depth);
PassSrg::m_outputShadowmap[dispatchId].r = outValue;
PassSrg::m_outputShadowmap[dispatchId].r = depth;
break;
}
case ShadowmapLightType::Spot:

@ -14,3 +14,12 @@ add_subdirectory(TechnicalArt)
add_subdirectory(AtomBridge)
add_subdirectory(AtomViewportDisplayInfo)
add_subdirectory(AtomViewportDisplayIcons)
# The "AtomLyIntegration" Gem will also alias the real Atom_AtomBridge target variants
# The Atom Gem does the same at the moment.
ly_create_alias(NAME AtomLyIntegration.Clients NAMESPACE Gem TARGETS Gem::Atom_AtomBridge.Clients)
ly_create_alias(NAME AtomLyIntegration.Servers NAMESPACE Gem TARGETS Gem::Atom_AtomBridge.Servers)
if(PAL_TRAIT_BUILD_HOST_TOOLS)
ly_create_alias(NAME AtomLyIntegration.Builders NAMESPACE Gem TARGETS Gem::Atom_AtomBridge.Builders)
ly_create_alias(NAME AtomLyIntegration.Tools NAMESPACE Gem TARGETS Gem::Atom_AtomBridge.Tools)
endif()

@ -2598,7 +2598,6 @@ struct ImFontAtlas
// NB: Consider using ImFontGlyphRangesBuilder to build glyph ranges from textual data.
IMGUI_API const ImWchar* GetGlyphRangesDefault(); // Basic Latin, Extended Latin
IMGUI_API const ImWchar* GetGlyphRangesKorean(); // Default + Korean characters
IMGUI_API const ImWchar* GetGlyphRangesJapanese(); // Default + Hiragana, Katakana, Half-Width, Selection of 2999 Ideographs
IMGUI_API const ImWchar* GetGlyphRangesChineseFull(); // Default + Half-Width + Japanese Hiragana/Katakana + full set of about 21000 CJK Unified Ideographs
IMGUI_API const ImWchar* GetGlyphRangesChineseSimplifiedCommon();// Default + Half-Width + Japanese Hiragana/Katakana + set of 2500 CJK Unified Ideographs for common simplified Chinese
IMGUI_API const ImWchar* GetGlyphRangesCyrillic(); // Default + about 400 Cyrillic characters

@ -2901,95 +2901,6 @@ const ImWchar* ImFontAtlas::GetGlyphRangesChineseSimplifiedCommon()
return &full_ranges[0];
}
const ImWchar* ImFontAtlas::GetGlyphRangesJapanese()
{
// 2999 ideograms code points for Japanese
// - 2136 Joyo (meaning "for regular use" or "for common use") Kanji code points
// - 863 Jinmeiyo (meaning "for personal name") Kanji code points
// - Sourced from the character information database of the Information-technology Promotion Agency, Japan
// - https://mojikiban.ipa.go.jp/mji/
// - Available under the terms of the Creative Commons Attribution-ShareAlike 2.1 Japan (CC BY-SA 2.1 JP).
// - https://creativecommons.org/licenses/by-sa/2.1/jp/deed.en
// - https://creativecommons.org/licenses/by-sa/2.1/jp/legalcode
// - You can generate this code by the script at:
// - https://github.com/vaiorabbit/everyday_use_kanji
// - References:
// - List of Joyo Kanji
// - (Official list by the Agency for Cultural Affairs) https://www.bunka.go.jp/kokugo_nihongo/sisaku/joho/joho/kakuki/14/tosin02/index.html
// - (Wikipedia) https://en.wikipedia.org/wiki/List_of_j%C5%8Dy%C5%8D_kanji
// - List of Jinmeiyo Kanji
// - (Official list by the Ministry of Justice) http://www.moj.go.jp/MINJI/minji86.html
// - (Wikipedia) https://en.wikipedia.org/wiki/Jinmeiy%C5%8D_kanji
// - Missing 1 Joyo Kanji: U+20B9F (Kun'yomi: Shikaru, On'yomi: Shitsu,shichi), see https://github.com/ocornut/imgui/pull/3627 for details.
// You can use ImFontGlyphRangesBuilder to create your own ranges derived from this, by merging existing ranges or adding new characters.
// (Stored as accumulative offsets from the initial unicode codepoint 0x4E00. This encoding is designed to helps us compact the source code size.)
static const short accumulative_offsets_from_0x4E00[] =
{
0,1,2,4,1,1,1,1,2,1,3,3,2,2,1,5,3,5,7,5,6,1,2,1,7,2,6,3,1,8,1,1,4,1,1,18,2,11,2,6,2,1,2,1,5,1,2,1,3,1,2,1,2,3,3,1,1,2,3,1,1,1,12,7,9,1,4,5,1,
1,2,1,10,1,1,9,2,2,4,5,6,9,3,1,1,1,1,9,3,18,5,2,2,2,2,1,6,3,7,1,1,1,1,2,2,4,2,1,23,2,10,4,3,5,2,4,10,2,4,13,1,6,1,9,3,1,1,6,6,7,6,3,1,2,11,3,
2,2,3,2,15,2,2,5,4,3,6,4,1,2,5,2,12,16,6,13,9,13,2,1,1,7,16,4,7,1,19,1,5,1,2,2,7,7,8,2,6,5,4,9,18,7,4,5,9,13,11,8,15,2,1,1,1,2,1,2,2,1,2,2,8,
2,9,3,3,1,1,4,4,1,1,1,4,9,1,4,3,5,5,2,7,5,3,4,8,2,1,13,2,3,3,1,14,1,1,4,5,1,3,6,1,5,2,1,1,3,3,3,3,1,1,2,7,6,6,7,1,4,7,6,1,1,1,1,1,12,3,3,9,5,
2,6,1,5,6,1,2,3,18,2,4,14,4,1,3,6,1,1,6,3,5,5,3,2,2,2,2,12,3,1,4,2,3,2,3,11,1,7,4,1,2,1,3,17,1,9,1,24,1,1,4,2,2,4,1,2,7,1,1,1,3,1,2,2,4,15,1,
1,2,1,1,2,1,5,2,5,20,2,5,9,1,10,8,7,6,1,1,1,1,1,1,6,2,1,2,8,1,1,1,1,5,1,1,3,1,1,1,1,3,1,1,12,4,1,3,1,1,1,1,1,10,3,1,7,5,13,1,2,3,4,6,1,1,30,
2,9,9,1,15,38,11,3,1,8,24,7,1,9,8,10,2,1,9,31,2,13,6,2,9,4,49,5,2,15,2,1,10,2,1,1,1,2,2,6,15,30,35,3,14,18,8,1,16,10,28,12,19,45,38,1,3,2,3,
13,2,1,7,3,6,5,3,4,3,1,5,7,8,1,5,3,18,5,3,6,1,21,4,24,9,24,40,3,14,3,21,3,2,1,2,4,2,3,1,15,15,6,5,1,1,3,1,5,6,1,9,7,3,3,2,1,4,3,8,21,5,16,4,
5,2,10,11,11,3,6,3,2,9,3,6,13,1,2,1,1,1,1,11,12,6,6,1,4,2,6,5,2,1,1,3,3,6,13,3,1,1,5,1,2,3,3,14,2,1,2,2,2,5,1,9,5,1,1,6,12,3,12,3,4,13,2,14,
2,8,1,17,5,1,16,4,2,2,21,8,9,6,23,20,12,25,19,9,38,8,3,21,40,25,33,13,4,3,1,4,1,2,4,1,2,5,26,2,1,1,2,1,3,6,2,1,1,1,1,1,1,2,3,1,1,1,9,2,3,1,1,
1,3,6,3,2,1,1,6,6,1,8,2,2,2,1,4,1,2,3,2,7,3,2,4,1,2,1,2,2,1,1,1,1,1,3,1,2,5,4,10,9,4,9,1,1,1,1,1,1,5,3,2,1,6,4,9,6,1,10,2,31,17,8,3,7,5,40,1,
7,7,1,6,5,2,10,7,8,4,15,39,25,6,28,47,18,10,7,1,3,1,1,2,1,1,1,3,3,3,1,1,1,3,4,2,1,4,1,3,6,10,7,8,6,2,2,1,3,3,2,5,8,7,9,12,2,15,1,1,4,1,2,1,1,
1,3,2,1,3,3,5,6,2,3,2,10,1,4,2,8,1,1,1,11,6,1,21,4,16,3,1,3,1,4,2,3,6,5,1,3,1,1,3,3,4,6,1,1,10,4,2,7,10,4,7,4,2,9,4,3,1,1,1,4,1,8,3,4,1,3,1,
6,1,4,2,1,4,7,2,1,8,1,4,5,1,1,2,2,4,6,2,7,1,10,1,1,3,4,11,10,8,21,4,6,1,3,5,2,1,2,28,5,5,2,3,13,1,2,3,1,4,2,1,5,20,3,8,11,1,3,3,3,1,8,10,9,2,
10,9,2,3,1,1,2,4,1,8,3,6,1,7,8,6,11,1,4,29,8,4,3,1,2,7,13,1,4,1,6,2,6,12,12,2,20,3,2,3,6,4,8,9,2,7,34,5,1,18,6,1,1,4,4,5,7,9,1,2,2,4,3,4,1,7,
2,2,2,6,2,3,25,5,3,6,1,4,6,7,4,2,1,4,2,13,6,4,4,3,1,5,3,4,4,3,2,1,1,4,1,2,1,1,3,1,11,1,6,3,1,7,3,6,2,8,8,6,9,3,4,11,3,2,10,12,2,5,11,1,6,4,5,
3,1,8,5,4,6,6,3,5,1,1,3,2,1,2,2,6,17,12,1,10,1,6,12,1,6,6,19,9,6,16,1,13,4,4,15,7,17,6,11,9,15,12,6,7,2,1,2,2,15,9,3,21,4,6,49,18,7,3,2,3,1,
6,8,2,2,6,2,9,1,3,6,4,4,1,2,16,2,5,2,1,6,2,3,5,3,1,2,5,1,2,1,9,3,1,8,6,4,8,11,3,1,1,1,1,3,1,13,8,4,1,3,2,2,1,4,1,11,1,5,2,1,5,2,5,8,6,1,1,7,
4,3,8,3,2,7,2,1,5,1,5,2,4,7,6,2,8,5,1,11,4,5,3,6,18,1,2,13,3,3,1,21,1,1,4,1,4,1,1,1,8,1,2,2,7,1,2,4,2,2,9,2,1,1,1,4,3,6,3,12,5,1,1,1,5,6,3,2,
4,8,2,2,4,2,7,1,8,9,5,2,3,2,1,3,2,13,7,14,6,5,1,1,2,1,4,2,23,2,1,1,6,3,1,4,1,15,3,1,7,3,9,14,1,3,1,4,1,1,5,8,1,3,8,3,8,15,11,4,14,4,4,2,5,5,
1,7,1,6,14,7,7,8,5,15,4,8,6,5,6,2,1,13,1,20,15,11,9,2,5,6,2,11,2,6,2,5,1,5,8,4,13,19,25,4,1,1,11,1,34,2,5,9,14,6,2,2,6,1,1,14,1,3,14,13,1,6,
12,21,14,14,6,32,17,8,32,9,28,1,2,4,11,8,3,1,14,2,5,15,1,1,1,1,3,6,4,1,3,4,11,3,1,1,11,30,1,5,1,4,1,5,8,1,1,3,2,4,3,17,35,2,6,12,17,3,1,6,2,
1,1,12,2,7,3,3,2,1,16,2,8,3,6,5,4,7,3,3,8,1,9,8,5,1,2,1,3,2,8,1,2,9,12,1,1,2,3,8,3,24,12,4,3,7,5,8,3,3,3,3,3,3,1,23,10,3,1,2,2,6,3,1,16,1,16,
22,3,10,4,11,6,9,7,7,3,6,2,2,2,4,10,2,1,1,2,8,7,1,6,4,1,3,3,3,5,10,12,12,2,3,12,8,15,1,1,16,6,6,1,5,9,11,4,11,4,2,6,12,1,17,5,13,1,4,9,5,1,11,
2,1,8,1,5,7,28,8,3,5,10,2,17,3,38,22,1,2,18,12,10,4,38,18,1,4,44,19,4,1,8,4,1,12,1,4,31,12,1,14,7,75,7,5,10,6,6,13,3,2,11,11,3,2,5,28,15,6,18,
18,5,6,4,3,16,1,7,18,7,36,3,5,3,1,7,1,9,1,10,7,2,4,2,6,2,9,7,4,3,32,12,3,7,10,2,23,16,3,1,12,3,31,4,11,1,3,8,9,5,1,30,15,6,12,3,2,2,11,19,9,
14,2,6,2,3,19,13,17,5,3,3,25,3,14,1,1,1,36,1,3,2,19,3,13,36,9,13,31,6,4,16,34,2,5,4,2,3,3,5,1,1,1,4,3,1,17,3,2,3,5,3,1,3,2,3,5,6,3,12,11,1,3,
1,2,26,7,12,7,2,14,3,3,7,7,11,25,25,28,16,4,36,1,2,1,6,2,1,9,3,27,17,4,3,4,13,4,1,3,2,2,1,10,4,2,4,6,3,8,2,1,18,1,1,24,2,2,4,33,2,3,63,7,1,6,
40,7,3,4,4,2,4,15,18,1,16,1,1,11,2,41,14,1,3,18,13,3,2,4,16,2,17,7,15,24,7,18,13,44,2,2,3,6,1,1,7,5,1,7,1,4,3,3,5,10,8,2,3,1,8,1,1,27,4,2,1,
12,1,2,1,10,6,1,6,7,5,2,3,7,11,5,11,3,6,6,2,3,15,4,9,1,1,2,1,2,11,2,8,12,8,5,4,2,3,1,5,2,2,1,14,1,12,11,4,1,11,17,17,4,3,2,5,5,7,3,1,5,9,9,8,
2,5,6,6,13,13,2,1,2,6,1,2,2,49,4,9,1,2,10,16,7,8,4,3,2,23,4,58,3,29,1,14,19,19,11,11,2,7,5,1,3,4,6,2,18,5,12,12,17,17,3,3,2,4,1,6,2,3,4,3,1,
1,1,1,5,1,1,9,1,3,1,3,6,1,8,1,1,2,6,4,14,3,1,4,11,4,1,3,32,1,2,4,13,4,1,2,4,2,1,3,1,11,1,4,2,1,4,4,6,3,5,1,6,5,7,6,3,23,3,5,3,5,3,3,13,3,9,10,
1,12,10,2,3,18,13,7,160,52,4,2,2,3,2,14,5,4,12,4,6,4,1,20,4,11,6,2,12,27,1,4,1,2,2,7,4,5,2,28,3,7,25,8,3,19,3,6,10,2,2,1,10,2,5,4,1,3,4,1,5,
3,2,6,9,3,6,2,16,3,3,16,4,5,5,3,2,1,2,16,15,8,2,6,21,2,4,1,22,5,8,1,1,21,11,2,1,11,11,19,13,12,4,2,3,2,3,6,1,8,11,1,4,2,9,5,2,1,11,2,9,1,1,2,
14,31,9,3,4,21,14,4,8,1,7,2,2,2,5,1,4,20,3,3,4,10,1,11,9,8,2,1,4,5,14,12,14,2,17,9,6,31,4,14,1,20,13,26,5,2,7,3,6,13,2,4,2,19,6,2,2,18,9,3,5,
12,12,14,4,6,2,3,6,9,5,22,4,5,25,6,4,8,5,2,6,27,2,35,2,16,3,7,8,8,6,6,5,9,17,2,20,6,19,2,13,3,1,1,1,4,17,12,2,14,7,1,4,18,12,38,33,2,10,1,1,
2,13,14,17,11,50,6,33,20,26,74,16,23,45,50,13,38,33,6,6,7,4,4,2,1,3,2,5,8,7,8,9,3,11,21,9,13,1,3,10,6,7,1,2,2,18,5,5,1,9,9,2,68,9,19,13,2,5,
1,4,4,7,4,13,3,9,10,21,17,3,26,2,1,5,2,4,5,4,1,7,4,7,3,4,2,1,6,1,1,20,4,1,9,2,2,1,3,3,2,3,2,1,1,1,20,2,3,1,6,2,3,6,2,4,8,1,3,2,10,3,5,3,4,4,
3,4,16,1,6,1,10,2,4,2,1,1,2,10,11,2,2,3,1,24,31,4,10,10,2,5,12,16,164,15,4,16,7,9,15,19,17,1,2,1,1,5,1,1,1,1,1,3,1,4,3,1,3,1,3,1,2,1,1,3,3,7,
2,8,1,2,2,2,1,3,4,3,7,8,12,92,2,10,3,1,3,14,5,25,16,42,4,7,7,4,2,21,5,27,26,27,21,25,30,31,2,1,5,13,3,22,5,6,6,11,9,12,1,5,9,7,5,5,22,60,3,5,
13,1,1,8,1,1,3,3,2,1,9,3,3,18,4,1,2,3,7,6,3,1,2,3,9,1,3,1,3,2,1,3,1,1,1,2,1,11,3,1,6,9,1,3,2,3,1,2,1,5,1,1,4,3,4,1,2,2,4,4,1,7,2,1,2,2,3,5,13,
18,3,4,14,9,9,4,16,3,7,5,8,2,6,48,28,3,1,1,4,2,14,8,2,9,2,1,15,2,4,3,2,10,16,12,8,7,1,1,3,1,1,1,2,7,4,1,6,4,38,39,16,23,7,15,15,3,2,12,7,21,
37,27,6,5,4,8,2,10,8,8,6,5,1,2,1,3,24,1,16,17,9,23,10,17,6,1,51,55,44,13,294,9,3,6,2,4,2,2,15,1,1,1,13,21,17,68,14,8,9,4,1,4,9,3,11,7,1,1,1,
5,6,3,2,1,1,1,2,3,8,1,2,2,4,1,5,5,2,1,4,3,7,13,4,1,4,1,3,1,1,1,5,5,10,1,6,1,5,2,1,5,2,4,1,4,5,7,3,18,2,9,11,32,4,3,3,2,4,7,11,16,9,11,8,13,38,
32,8,4,2,1,1,2,1,2,4,4,1,1,1,4,1,21,3,11,1,16,1,1,6,1,3,2,4,9,8,57,7,44,1,3,3,13,3,10,1,1,7,5,2,7,21,47,63,3,15,4,7,1,16,1,1,2,8,2,3,42,15,4,
1,29,7,22,10,3,78,16,12,20,18,4,67,11,5,1,3,15,6,21,31,32,27,18,13,71,35,5,142,4,10,1,2,50,19,33,16,35,37,16,19,27,7,1,133,19,1,4,8,7,20,1,4,
4,1,10,3,1,6,1,2,51,5,40,15,24,43,22928,11,1,13,154,70,3,1,1,7,4,10,1,2,1,1,2,1,2,1,2,2,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,
3,2,1,1,1,1,2,1,1,
};
static ImWchar base_ranges[] = // not zero-terminated
{
0x0020, 0x00FF, // Basic Latin + Latin Supplement
0x3000, 0x30FF, // CJK Symbols and Punctuations, Hiragana, Katakana
0x31F0, 0x31FF, // Katakana Phonetic Extensions
0xFF00, 0xFFEF // Half-width characters
};
static ImWchar full_ranges[IM_ARRAYSIZE(base_ranges) + IM_ARRAYSIZE(accumulative_offsets_from_0x4E00)*2 + 1] = { 0 };
if (!full_ranges[0])
{
memcpy(full_ranges, base_ranges, sizeof(base_ranges));
UnpackAccumulativeOffsetsIntoRanges(0x4E00, accumulative_offsets_from_0x4E00, IM_ARRAYSIZE(accumulative_offsets_from_0x4E00), full_ranges + IM_ARRAYSIZE(base_ranges));
}
return &full_ranges[0];
}
const ImWchar* ImFontAtlas::GetGlyphRangesCyrillic()
{
static const ImWchar ranges[] =

@ -1,9 +1,3 @@
<EngineDependencies versionnumber="1.0.0">
<Dependency path="textures/defaults/unchecked_nohover.tif" optional="true" />
<Dependency path="textures/defaults/unchecked_nohover.sprite" optional="true" />
<Dependency path="textures/defaults/checkmark.tif" optional="true" />
<Dependency path="textures/defaults/checkmark.sprite" optional="true" />
<Dependency path="textures/defaults/sliderManipulator.tif" optional="true" />
<Dependency path="textures/defaults/sliderManipulator.sprite" optional="true" />
<Dependency path="engineassets/textures/cursor_green.sprite" optional="true" />
<Dependency path="textures/cursor_default.tif" optional="true" />
</EngineDependencies>

@ -1 +0,0 @@
/autooptimizefile=0 /dns=1 /preset=ReferenceImage_Linear /reduce=0 /ser=0

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:a268774eb6d4d4590960c28edbf2a35d3fb7a73caab38d9ad15812c3df1c0c02
size 4529

@ -0,0 +1,69 @@
<ObjectStream version="3">
<Class name="TextureSettings" version="1" type="{980132FF-C450-425D-8AE0-BD96A8486177}">
<Class name="AZ::Uuid" field="PresetID" value="{83003128-F63E-422B-AEC2-68F0A947225F}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="SizeReduceLevel" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="bool" field="EngineReduce" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
<Class name="bool" field="EnableMipmap" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
<Class name="bool" field="MaintainAlphaCoverage" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
<Class name="AZStd::vector" field="MipMapAlphaAdjustments" type="{3349AACD-BE04-50BC-9478-528BF2ACFD55}">
<Class name="unsigned int" field="element" value="50" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="unsigned int" field="element" value="50" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="unsigned int" field="element" value="50" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="unsigned int" field="element" value="50" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="unsigned int" field="element" value="50" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="unsigned int" field="element" value="50" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
</Class>
<Class name="unsigned int" field="MipMapGenEval" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="ImageProcessingAtom::MipGenType" field="MipMapGenType" value="1" type="{8524F650-1417-44DA-BBB0-C707A7A1A709}"/>
<Class name="AZStd::map" field="PlatformSpecificOverrides" type="{74E4843B-0924-583D-8C6E-A37B09BD51FE}">
<Class name="AZStd::pair" field="element" type="{CAC4E67F-D626-5452-A057-ACB57D53F549}">
<Class name="AZStd::string" field="value1" value="android" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
<Class name="DataPatch" field="value2" type="{BFF7A3F5-9014-4000-92C7-9B2BC7913DA9}">
<Class name="AZ::Uuid" field="m_targetClassId" value="{980132FF-C450-425D-8AE0-BD96A8486177}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="m_targetClassVersion" value="1" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::unordered_map" field="m_patch" type="{CEA836FC-77E0-5E46-BD0F-2E5A39D845E9}"/>
</Class>
</Class>
<Class name="AZStd::pair" field="element" type="{CAC4E67F-D626-5452-A057-ACB57D53F549}">
<Class name="AZStd::string" field="value1" value="ios" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
<Class name="DataPatch" field="value2" type="{BFF7A3F5-9014-4000-92C7-9B2BC7913DA9}">
<Class name="AZ::Uuid" field="m_targetClassId" value="{980132FF-C450-425D-8AE0-BD96A8486177}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="m_targetClassVersion" value="1" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::unordered_map" field="m_patch" type="{CEA836FC-77E0-5E46-BD0F-2E5A39D845E9}">
<Class name="AZStd::pair" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
<Class name="AddressType" field="value1" value="AZStd::map({74E4843B-0924-583D-8C6E-A37B09BD51FE})::PlatformSpecificOverrides·0/AZStd::pair({CAC4E67F-D626-5452-A057-ACB57D53F549})#0·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
<Class name="any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"/>
</Class>
</Class>
</Class>
</Class>
<Class name="AZStd::pair" field="element" type="{CAC4E67F-D626-5452-A057-ACB57D53F549}">
<Class name="AZStd::string" field="value1" value="mac" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
<Class name="DataPatch" field="value2" type="{BFF7A3F5-9014-4000-92C7-9B2BC7913DA9}">
<Class name="AZ::Uuid" field="m_targetClassId" value="{980132FF-C450-425D-8AE0-BD96A8486177}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="m_targetClassVersion" value="1" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::unordered_map" field="m_patch" type="{CEA836FC-77E0-5E46-BD0F-2E5A39D845E9}">
<Class name="AZStd::pair" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
<Class name="AddressType" field="value1" value="AZStd::map({74E4843B-0924-583D-8C6E-A37B09BD51FE})::PlatformSpecificOverrides·0/AZStd::pair({CAC4E67F-D626-5452-A057-ACB57D53F549})#1·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
<Class name="any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"/>
</Class>
<Class name="AZStd::pair" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
<Class name="AddressType" field="value1" value="AZStd::map({74E4843B-0924-583D-8C6E-A37B09BD51FE})::PlatformSpecificOverrides·0/AZStd::pair({CAC4E67F-D626-5452-A057-ACB57D53F549})#0·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
<Class name="any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"/>
</Class>
</Class>
</Class>
</Class>
<Class name="AZStd::pair" field="element" type="{CAC4E67F-D626-5452-A057-ACB57D53F549}">
<Class name="AZStd::string" field="value1" value="pc" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
<Class name="DataPatch" field="value2" type="{BFF7A3F5-9014-4000-92C7-9B2BC7913DA9}">
<Class name="AZ::Uuid" field="m_targetClassId" value="{980132FF-C450-425D-8AE0-BD96A8486177}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="m_targetClassVersion" value="1" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::unordered_map" field="m_patch" type="{CEA836FC-77E0-5E46-BD0F-2E5A39D845E9}"/>
</Class>
</Class>
</Class>
<Class name="AZStd::string" field="OverridingPlatform" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
</ObjectStream>

@ -1,28 +1,12 @@
<ObjectStream version="3">
<Class name="AZStd::vector" type="{82FC5264-88D0-57CD-9307-FC52E4DAD550}">
<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
<Class name="AZ::Uuid" field="guid" value="{EFA11E15-FC2F-533B-9E73-6351C0E82EF2}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
</Class>
<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::string" field="pathHint" value="textures/basic/button_sliced_normal.sprite" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
<Class name="AZ::Uuid" field="guid" value="{99FDCF74-F290-5367-BAE4-05AB38996ED8}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
</Class>
<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::string" field="pathHint" value="engineassets/textures/cursor_green.dds" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
<Class name="AZ::Uuid" field="guid" value="{E993215C-FF5F-5891-8475-D4EDBD560807}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
</Class>
<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::string" field="pathHint" value="textures/basic/button_sliced_normal.dds" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
<Class name="AZStd::string" field="pathHint" value="textures/cursor_default.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">

@ -112,7 +112,6 @@ enum class FusibleCommand
#include "FileHelpers.h"
#include "ComponentHelpers.h"
#include "HierarchyHelpers.h"
#include "PrefabHelpers.h"
#include "UiSliceManager.h"
#include "SelectionHelpers.h"
#include "ViewportInteraction.h"
@ -173,8 +172,6 @@ bool ClipboardContainsOurDataType();
#define UICANVASEDITOR_COORDINATE_SYSTEM_CYCLE_SHORTCUT_KEY_SEQUENCE QKeySequence(Qt::CTRL + Qt::Key_W)
#define UICANVASEDITOR_SNAP_TO_GRID_TOGGLE_SHORTCUT_KEY_SEQUENCE QKeySequence(Qt::Key_G)
#define UICANVASEDITOR_PREFAB_EXTENSION "uiprefab"
#define UICANVASEDITOR_CANVAS_DIRECTORY "UI/Canvases"
#define UICANVASEDITOR_CANVAS_EXTENSION "uicanvas"

@ -146,19 +146,6 @@ void EditorWindow::AddMenu_File()
menu->addSeparator();
// "Save as Prefab..." file menu option
{
HierarchyWidget* widget = GetHierarchy();
QAction* action = PrefabHelpers::CreateSavePrefabAction(widget);
action->setEnabled(canvasLoaded);
// This menu option is always available to the user
menu->addAction(action);
addAction(action); // Also add the action to the window until the shortcut dispatcher can find the menu action
}
menu->addSeparator();
// Close the active canvas
{
QAction* action = CreateCloseCanvasAction(GetCanvas());

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

Loading…
Cancel
Save