merge stabilization/2106 into development
Signed-off-by: hultonha <hultonha@amazon.co.uk>
This commit is contained in:
@@ -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.
|
||||
};
|
||||
|
||||
+19
-10
@@ -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, ¶mStringArray));
|
||||
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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user