Merge branch 'main' into default_3rdparty
This commit is contained in:
@@ -127,13 +127,14 @@ namespace AZ
|
||||
*/
|
||||
class EditContext
|
||||
{
|
||||
public:
|
||||
/// @cond EXCLUDE_DOCS
|
||||
class ClassBuilder;
|
||||
class EnumBuilder;
|
||||
using ClassInfo = ClassBuilder; ///< @deprecated Use EditContext::ClassBuilder
|
||||
using EnumInfo = EnumBuilder; ///< @deprecated Use EditContext::EnumBuilder
|
||||
/// @endcond
|
||||
public:
|
||||
|
||||
AZ_CLASS_ALLOCATOR(EditContext, SystemAllocator, 0);
|
||||
|
||||
/**
|
||||
@@ -186,6 +187,7 @@ namespace AZ
|
||||
* look at the unit tests and example to see use cases.
|
||||
*
|
||||
*/
|
||||
public:
|
||||
class ClassBuilder
|
||||
{
|
||||
friend EditContext;
|
||||
@@ -399,6 +401,7 @@ namespace AZ
|
||||
EnumBuilder* Value(const char* name, E value);
|
||||
};
|
||||
|
||||
private:
|
||||
typedef AZStd::list<Edit::ClassData> ClassDataListType;
|
||||
typedef AZStd::unordered_map<AZ::Uuid, Edit::ElementData> EnumDataMapType;
|
||||
|
||||
|
||||
@@ -101,6 +101,9 @@ namespace AZ
|
||||
class SerializeContext
|
||||
: public ReflectContext
|
||||
{
|
||||
static const unsigned int VersionClassDeprecated = (unsigned int)-1;
|
||||
|
||||
public:
|
||||
/// @cond EXCLUDE_DOCS
|
||||
friend class EditContext;
|
||||
class ClassBuilder;
|
||||
@@ -108,9 +111,6 @@ namespace AZ
|
||||
/// @endcond
|
||||
class EnumBuilder;
|
||||
|
||||
static const unsigned int VersionClassDeprecated = (unsigned int)-1;
|
||||
|
||||
public:
|
||||
class ClassData;
|
||||
struct EnumerateInstanceCallContext;
|
||||
struct ClassElement;
|
||||
@@ -1131,6 +1131,7 @@ namespace AZ
|
||||
* ->Version(3,&MyVersionConverter)
|
||||
* ->Field("data",&MyStruct::m_data);
|
||||
*/
|
||||
public:
|
||||
class ClassBuilder
|
||||
{
|
||||
friend class SerializeContext;
|
||||
@@ -1330,7 +1331,8 @@ namespace AZ
|
||||
AZStd::vector<AttributeSharedPair, AZStdFunctorAllocator>* m_currentAttributes = nullptr;
|
||||
};
|
||||
|
||||
EditContext* m_editContext; ///< Pointer to optional edit context.
|
||||
private:
|
||||
EditContext* m_editContext; ///< Pointer to optional edit context.
|
||||
UuidToClassMap m_uuidMap; ///< Map for all class in this serialize context
|
||||
AZStd::unordered_multimap<AZ::Crc32, AZ::Uuid> m_classNameToUuid; /// Map all class names to their uuid
|
||||
AZStd::unordered_multimap<Uuid, GenericClassInfo*> m_uuidGenericMap; ///< Uuid to ClassData map of reflected classes with GenericTypeInfo
|
||||
|
||||
@@ -294,7 +294,8 @@ namespace O3DE::ProjectManager
|
||||
RegisterThisEngine();
|
||||
|
||||
return result == 0 && !PyErr_Occurred();
|
||||
} catch ([[maybe_unused]] const std::exception& e)
|
||||
}
|
||||
catch ([[maybe_unused]] const std::exception& e)
|
||||
{
|
||||
AZ_Warning("ProjectManagerWindow", false, "Py_Initialize() failed with %s", e.what());
|
||||
return false;
|
||||
@@ -320,25 +321,25 @@ namespace O3DE::ProjectManager
|
||||
bool registrationResult = true; // already registered is considered successful
|
||||
bool pythonResult = ExecuteWithLock(
|
||||
[&]
|
||||
{
|
||||
// check current engine path against all other registered engines
|
||||
// to see if we are already registered
|
||||
auto allEngines = m_manifest.attr("get_engines")();
|
||||
if (pybind11::isinstance<pybind11::list>(allEngines))
|
||||
{
|
||||
// check current engine path against all other registered engines
|
||||
// to see if we are already registered
|
||||
auto allEngines = m_manifest.attr("get_engines")();
|
||||
if (pybind11::isinstance<pybind11::list>(allEngines))
|
||||
for (auto engine : allEngines)
|
||||
{
|
||||
for (auto engine : allEngines)
|
||||
AZ::IO::FixedMaxPath enginePath(Py_To_String(engine["path"]));
|
||||
if (enginePath.Compare(m_enginePath) == 0)
|
||||
{
|
||||
AZ::IO::FixedMaxPath enginePath(Py_To_String(engine["path"]));
|
||||
if (enginePath.Compare(m_enginePath) == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto result = m_register.attr("register")(m_enginePath.c_str());
|
||||
registrationResult = (result.cast<int>() == 0);
|
||||
});
|
||||
auto result = m_register.attr("register")(m_enginePath.c_str());
|
||||
registrationResult = (result.cast<int>() == 0);
|
||||
});
|
||||
|
||||
bool finalResult = (registrationResult && pythonResult);
|
||||
AZ_Assert(finalResult, "Registration of this engine failed!");
|
||||
@@ -378,12 +379,12 @@ namespace O3DE::ProjectManager
|
||||
auto o3deData = m_manifest.attr("load_o3de_manifest")();
|
||||
if (pybind11::isinstance<pybind11::dict>(o3deData))
|
||||
{
|
||||
engineInfo.m_path = Py_To_String(enginePath);
|
||||
engineInfo.m_defaultGemsFolder = Py_To_String(o3deData["default_gems_folder"]);
|
||||
engineInfo.m_defaultProjectsFolder = Py_To_String(o3deData["default_projects_folder"]);
|
||||
engineInfo.m_path = Py_To_String(enginePath);
|
||||
engineInfo.m_defaultGemsFolder = Py_To_String(o3deData["default_gems_folder"]);
|
||||
engineInfo.m_defaultProjectsFolder = Py_To_String(o3deData["default_projects_folder"]);
|
||||
engineInfo.m_defaultRestrictedFolder = Py_To_String(o3deData["default_restricted_folder"]);
|
||||
engineInfo.m_defaultTemplatesFolder = Py_To_String(o3deData["default_templates_folder"]);
|
||||
engineInfo.m_thirdPartyPath = Py_To_String(o3deData["default_third_party_folder"]);
|
||||
engineInfo.m_defaultTemplatesFolder = Py_To_String(o3deData["default_templates_folder"]);
|
||||
engineInfo.m_thirdPartyPath = Py_To_String(o3deData["default_third_party_folder"]);
|
||||
}
|
||||
|
||||
auto engineData = m_manifest.attr("get_engine_json_data")(pybind11::none(), enginePath);
|
||||
@@ -391,8 +392,8 @@ namespace O3DE::ProjectManager
|
||||
{
|
||||
try
|
||||
{
|
||||
engineInfo.m_version = Py_To_String_Optional(engineData,"O3DEVersion","0.0.0.0");
|
||||
engineInfo.m_name = Py_To_String_Optional(engineData,"engine_name","O3DE");
|
||||
engineInfo.m_version = Py_To_String_Optional(engineData, "O3DEVersion", "0.0.0.0");
|
||||
engineInfo.m_name = Py_To_String_Optional(engineData, "engine_name", "O3DE");
|
||||
}
|
||||
catch ([[maybe_unused]] const std::exception& e)
|
||||
{
|
||||
@@ -416,20 +417,20 @@ namespace O3DE::ProjectManager
|
||||
bool PythonBindings::SetEngineInfo(const EngineInfo& engineInfo)
|
||||
{
|
||||
bool result = ExecuteWithLock([&] {
|
||||
pybind11::str enginePath = engineInfo.m_path.toStdString();
|
||||
pybind11::str defaultProjectsFolder = engineInfo.m_defaultProjectsFolder.toStdString();
|
||||
pybind11::str defaultGemsFolder = engineInfo.m_defaultGemsFolder.toStdString();
|
||||
pybind11::str enginePath = engineInfo.m_path.toStdString();
|
||||
pybind11::str defaultProjectsFolder = engineInfo.m_defaultProjectsFolder.toStdString();
|
||||
pybind11::str defaultGemsFolder = engineInfo.m_defaultGemsFolder.toStdString();
|
||||
pybind11::str defaultTemplatesFolder = engineInfo.m_defaultTemplatesFolder.toStdString();
|
||||
pybind11::str defaultThridPartyFolder = engineInfo.m_thirdPartyPath.toStdString();
|
||||
|
||||
auto registrationResult = m_register.attr("register")(
|
||||
enginePath, // engine_path
|
||||
pybind11::none(), // project_path
|
||||
enginePath, // engine_path
|
||||
pybind11::none(), // project_path
|
||||
pybind11::none(), // gem_path
|
||||
pybind11::none(), // external_subdir_path
|
||||
pybind11::none(), // template_path
|
||||
pybind11::none(), // restricted_path
|
||||
pybind11::none(), // repo_uri
|
||||
pybind11::none(), // external_subdir_path
|
||||
pybind11::none(), // template_path
|
||||
pybind11::none(), // restricted_path
|
||||
pybind11::none(), // repo_uri
|
||||
pybind11::none(), // default_engines_folder
|
||||
defaultProjectsFolder,
|
||||
defaultGemsFolder,
|
||||
@@ -465,12 +466,12 @@ namespace O3DE::ProjectManager
|
||||
QVector<GemInfo> gems;
|
||||
|
||||
auto result = ExecuteWithLockErrorHandling([&]
|
||||
{
|
||||
for (auto path : m_manifest.attr("get_engine_gems")())
|
||||
{
|
||||
for (auto path : m_manifest.attr("get_engine_gems")())
|
||||
{
|
||||
gems.push_back(GemInfoFromPath(path));
|
||||
}
|
||||
});
|
||||
gems.push_back(GemInfoFromPath(path));
|
||||
}
|
||||
});
|
||||
if (!result.IsSuccess())
|
||||
{
|
||||
return AZ::Failure<AZStd::string>(result.GetError().c_str());
|
||||
@@ -485,13 +486,13 @@ namespace O3DE::ProjectManager
|
||||
QVector<GemInfo> gems;
|
||||
|
||||
auto result = ExecuteWithLockErrorHandling([&]
|
||||
{
|
||||
pybind11::str pyProjectPath = projectPath.toStdString();
|
||||
for (auto path : m_manifest.attr("get_all_gems")(pyProjectPath))
|
||||
{
|
||||
pybind11::str pyProjectPath = projectPath.toStdString();
|
||||
for (auto path : m_manifest.attr("get_all_gems")(pyProjectPath))
|
||||
{
|
||||
gems.push_back(GemInfoFromPath(path));
|
||||
}
|
||||
});
|
||||
gems.push_back(GemInfoFromPath(path));
|
||||
}
|
||||
});
|
||||
if (!result.IsSuccess())
|
||||
{
|
||||
return AZ::Failure<AZStd::string>(result.GetError().c_str());
|
||||
@@ -506,12 +507,12 @@ namespace O3DE::ProjectManager
|
||||
// Retrieve the path to the cmake file that lists the enabled gems.
|
||||
pybind11::str enabledGemsFilename;
|
||||
auto result = ExecuteWithLockErrorHandling([&]
|
||||
{
|
||||
const pybind11::str pyProjectPath = projectPath.toStdString();
|
||||
enabledGemsFilename = m_cmake.attr("get_enabled_gem_cmake_file")(
|
||||
pybind11::none(), // project_name
|
||||
pyProjectPath); // project_path
|
||||
});
|
||||
{
|
||||
const pybind11::str pyProjectPath = projectPath.toStdString();
|
||||
enabledGemsFilename = m_cmake.attr("get_enabled_gem_cmake_file")(
|
||||
pybind11::none(), // project_name
|
||||
pyProjectPath); // project_path
|
||||
});
|
||||
if (!result.IsSuccess())
|
||||
{
|
||||
return AZ::Failure<AZStd::string>(result.GetError().c_str());
|
||||
@@ -520,13 +521,13 @@ namespace O3DE::ProjectManager
|
||||
// Retrieve the actual list of names from the cmake file.
|
||||
QVector<AZStd::string> gemNames;
|
||||
result = ExecuteWithLockErrorHandling([&]
|
||||
{
|
||||
const auto pyGemNames = m_cmake.attr("get_enabled_gems")(enabledGemsFilename);
|
||||
for (auto gemName : pyGemNames)
|
||||
{
|
||||
const auto pyGemNames = m_cmake.attr("get_enabled_gems")(enabledGemsFilename);
|
||||
for (auto gemName : pyGemNames)
|
||||
{
|
||||
gemNames.push_back(Py_To_String(gemName));
|
||||
}
|
||||
});
|
||||
gemNames.push_back(Py_To_String(gemName));
|
||||
}
|
||||
});
|
||||
if (!result.IsSuccess())
|
||||
{
|
||||
return AZ::Failure<AZStd::string>(result.GetError().c_str());
|
||||
@@ -540,13 +541,13 @@ namespace O3DE::ProjectManager
|
||||
bool registrationResult = false;
|
||||
bool result = ExecuteWithLock(
|
||||
[&]
|
||||
{
|
||||
pybind11::str projectPath = path.toStdString();
|
||||
auto pythonRegistrationResult = m_register.attr("register")(pybind11::none(), projectPath);
|
||||
{
|
||||
pybind11::str projectPath = path.toStdString();
|
||||
auto pythonRegistrationResult = m_register.attr("register")(pybind11::none(), projectPath);
|
||||
|
||||
// Returns an exit code so boolify it then invert result
|
||||
registrationResult = !pythonRegistrationResult.cast<bool>();
|
||||
});
|
||||
// Returns an exit code so boolify it then invert result
|
||||
registrationResult = !pythonRegistrationResult.cast<bool>();
|
||||
});
|
||||
|
||||
return result && registrationResult;
|
||||
}
|
||||
@@ -556,30 +557,30 @@ namespace O3DE::ProjectManager
|
||||
bool registrationResult = false;
|
||||
bool result = ExecuteWithLock(
|
||||
[&]
|
||||
{
|
||||
pybind11::str projectPath = path.toStdString();
|
||||
auto pythonRegistrationResult = m_register.attr("register")(
|
||||
pybind11::none(), // engine_path
|
||||
projectPath, // project_path
|
||||
pybind11::none(), // gem_path
|
||||
pybind11::none(), // external_subdir_path
|
||||
pybind11::none(), // template_path
|
||||
pybind11::none(), // restricted_path
|
||||
pybind11::none(), // repo_uri
|
||||
pybind11::none(), // default_engines_folder
|
||||
pybind11::none(), // default_projects_folder
|
||||
pybind11::none(), // default_gems_folder
|
||||
pybind11::none(), // default_templates_folder
|
||||
pybind11::none(), // default_restricted_folder
|
||||
pybind11::none(), // external_subdir_engine_path
|
||||
pybind11::none(), // external_subdir_project_path
|
||||
true, // remove
|
||||
false // force
|
||||
{
|
||||
pybind11::str projectPath = path.toStdString();
|
||||
auto pythonRegistrationResult = m_register.attr("register")(
|
||||
pybind11::none(), // engine_path
|
||||
projectPath, // project_path
|
||||
pybind11::none(), // gem_path
|
||||
pybind11::none(), // external_subdir_path
|
||||
pybind11::none(), // template_path
|
||||
pybind11::none(), // restricted_path
|
||||
pybind11::none(), // repo_uri
|
||||
pybind11::none(), // default_engines_folder
|
||||
pybind11::none(), // default_projects_folder
|
||||
pybind11::none(), // default_gems_folder
|
||||
pybind11::none(), // default_templates_folder
|
||||
pybind11::none(), // default_restricted_folder
|
||||
pybind11::none(), // external_subdir_engine_path
|
||||
pybind11::none(), // external_subdir_project_path
|
||||
true, // remove
|
||||
false // force
|
||||
);
|
||||
|
||||
// Returns an exit code so boolify it then invert result
|
||||
registrationResult = !pythonRegistrationResult.cast<bool>();
|
||||
});
|
||||
|
||||
// Returns an exit code so boolify it then invert result
|
||||
registrationResult = !pythonRegistrationResult.cast<bool>();
|
||||
});
|
||||
|
||||
return result && registrationResult;
|
||||
}
|
||||
@@ -637,12 +638,12 @@ namespace O3DE::ProjectManager
|
||||
try
|
||||
{
|
||||
// required
|
||||
gemInfo.m_name = Py_To_String(data["gem_name"]);
|
||||
gemInfo.m_name = Py_To_String(data["gem_name"]);
|
||||
|
||||
// optional
|
||||
gemInfo.m_displayName = Py_To_String_Optional(data, "DisplayName", gemInfo.m_name);
|
||||
gemInfo.m_summary = Py_To_String_Optional(data, "Summary", "");
|
||||
gemInfo.m_version = Py_To_String_Optional(data, "Version", "");
|
||||
gemInfo.m_summary = Py_To_String_Optional(data, "Summary", "");
|
||||
gemInfo.m_version = Py_To_String_Optional(data, "Version", "");
|
||||
|
||||
if (data.contains("Tags"))
|
||||
{
|
||||
@@ -673,7 +674,7 @@ namespace O3DE::ProjectManager
|
||||
try
|
||||
{
|
||||
projectInfo.m_projectName = Py_To_String(projectData["project_name"]);
|
||||
projectInfo.m_displayName = Py_To_String_Optional(projectData,"display_name", projectInfo.m_projectName);
|
||||
projectInfo.m_displayName = Py_To_String_Optional(projectData, "display_name", projectInfo.m_projectName);
|
||||
}
|
||||
catch ([[maybe_unused]] const std::exception& e)
|
||||
{
|
||||
@@ -715,33 +716,33 @@ namespace O3DE::ProjectManager
|
||||
AZ::Outcome<void, AZStd::string> PythonBindings::AddGemToProject(const QString& gemPath, const QString& projectPath)
|
||||
{
|
||||
return ExecuteWithLockErrorHandling([&]
|
||||
{
|
||||
pybind11::str pyGemPath = gemPath.toStdString();
|
||||
pybind11::str pyProjectPath = projectPath.toStdString();
|
||||
{
|
||||
pybind11::str pyGemPath = gemPath.toStdString();
|
||||
pybind11::str pyProjectPath = projectPath.toStdString();
|
||||
|
||||
m_enableGemProject.attr("enable_gem_in_project")(
|
||||
pybind11::none(), // gem name not needed as path is provided
|
||||
pyGemPath,
|
||||
pybind11::none(), // project name not needed as path is provided
|
||||
pyProjectPath
|
||||
m_enableGemProject.attr("enable_gem_in_project")(
|
||||
pybind11::none(), // gem name not needed as path is provided
|
||||
pyGemPath,
|
||||
pybind11::none(), // project name not needed as path is provided
|
||||
pyProjectPath
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
AZ::Outcome<void, AZStd::string> PythonBindings::RemoveGemFromProject(const QString& gemPath, const QString& projectPath)
|
||||
{
|
||||
return ExecuteWithLockErrorHandling([&]
|
||||
{
|
||||
pybind11::str pyGemPath = gemPath.toStdString();
|
||||
pybind11::str pyProjectPath = projectPath.toStdString();
|
||||
{
|
||||
pybind11::str pyGemPath = gemPath.toStdString();
|
||||
pybind11::str pyProjectPath = projectPath.toStdString();
|
||||
|
||||
m_disableGemProject.attr("disable_gem_in_project")(
|
||||
pybind11::none(), // gem name not needed as path is provided
|
||||
pyGemPath,
|
||||
pybind11::none(), // project name not needed as path is provided
|
||||
pyProjectPath
|
||||
m_disableGemProject.attr("disable_gem_in_project")(
|
||||
pybind11::none(), // gem name not needed as path is provided
|
||||
pyGemPath,
|
||||
pybind11::none(), // project name not needed as path is provided
|
||||
pyProjectPath
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
bool PythonBindings::UpdateProject([[maybe_unused]] const ProjectInfo& projectInfo)
|
||||
@@ -761,8 +762,8 @@ namespace O3DE::ProjectManager
|
||||
{
|
||||
// required
|
||||
templateInfo.m_displayName = Py_To_String(data["display_name"]);
|
||||
templateInfo.m_name = Py_To_String(data["template_name"]);
|
||||
templateInfo.m_summary = Py_To_String(data["summary"]);
|
||||
templateInfo.m_name = Py_To_String(data["template_name"]);
|
||||
templateInfo.m_summary = Py_To_String(data["summary"]);
|
||||
|
||||
// optional
|
||||
if (data.contains("canonical_tags"))
|
||||
@@ -794,7 +795,7 @@ namespace O3DE::ProjectManager
|
||||
QVector<ProjectTemplateInfo> templates;
|
||||
|
||||
bool result = ExecuteWithLock([&] {
|
||||
for (auto path : m_manifest.attr("get_project_templates")())
|
||||
for (auto path : m_manifest.attr("get_templates_for_project_creation")())
|
||||
{
|
||||
templates.push_back(ProjectTemplateInfoFromPath(path));
|
||||
}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:a476e99b55cf2a76fef6775c5a57dad29f8ffcb942c625bab04c89051a72a560
|
||||
size 62626
|
||||
oid sha256:838830c99f344f5b68e5e85c9bc52751350caf48e662c9c2b767ab77039bbd8f
|
||||
size 103472
|
||||
|
||||
@@ -91,7 +91,8 @@ AZ_POP_DISABLE_WARNING
|
||||
#include <ScriptCanvas/Variable/VariableBus.h>
|
||||
#include <ScriptCanvas/Libraries/UnitTesting/UnitTestingLibrary.h>
|
||||
|
||||
////
|
||||
AZ_CVAR(bool, g_disableDeprecatedNodeUpdates, false, {}, AZ::ConsoleFunctorFlags::Null,
|
||||
"Disables automatic update attempts of deprecated nodes, so that graphs that require and update can be viewed in their original form");
|
||||
|
||||
namespace EditorGraphCpp
|
||||
{
|
||||
@@ -3642,7 +3643,7 @@ namespace ScriptCanvasEditor
|
||||
|
||||
if (scriptCanvasNode)
|
||||
{
|
||||
if (scriptCanvasNode->IsDeprecated())
|
||||
if (scriptCanvasNode->IsDeprecated() && !g_disableDeprecatedNodeUpdates)
|
||||
{
|
||||
ScriptCanvas::NodeConfiguration nodeConfig = scriptCanvasNode->GetReplacementNodeConfiguration();
|
||||
if (nodeConfig.IsValid())
|
||||
|
||||
+36
-4
@@ -22,6 +22,11 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/RTTI/TypeInfo.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
#include <AzCore/RTTI/BehaviorContext.h>
|
||||
|
||||
#include <ScriptCanvas/Core/Nodeable.h>
|
||||
#include <ScriptCanvas/Core/NodeableNode.h>
|
||||
|
||||
@@ -43,6 +48,11 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{%- set attribute_Base = Class.attrib['Base'] %}
|
||||
{% if not Class.attrib['Base'] is defined %}
|
||||
{% set attribute_Base = "ScriptCanvas::Nodeable" %}
|
||||
{% endif %}
|
||||
|
||||
{% if attribute_Namespace is defined %}
|
||||
namespace {{attribute_Namespace}}
|
||||
{
|
||||
@@ -66,6 +76,9 @@ namespace {{attribute_Namespace}}
|
||||
public: \
|
||||
AZ_RTTI({{className}}, "{{nodeableClassName|createHashGuid}}"{% if Class.attrib['Base'] is defined %}, {{ Class.attrib['Base'] }}{% endif %}); \
|
||||
static void Reflect(AZ::ReflectContext* reflection); \
|
||||
static void ExtendReflectionSerialize([[maybe_unused]] AZ::SerializeContext::ClassBuilder* builder){% if Class.attrib['ExtendReflectionSerialize'] is defined %};{% else %}{}{% endif %} \
|
||||
static void ExtendReflectionEdit([[maybe_unused]] AZ::EditContext::ClassBuilder* builder){% if Class.attrib['ExtendReflectionEdit'] is defined %};{% else %}{}{% endif %} \
|
||||
static void ExtendReflectionBehavior([[maybe_unused]] AZ::BehaviorContext::ClassBuilder<{{className}}>* builder){% if Class.attrib['ExtendReflectionBehavior'] is defined %};{% else %}{}{% endif %} \
|
||||
static const char* GetDescription() { return "{{ macros.GetAttributeAsString(Class.attrib, 'Description') }}"; } \
|
||||
ScriptCanvas::NodePropertyInterface* GetPropertyInterface(AZ::Crc32 propertyId) override; \
|
||||
bool IsActive() const override { return false; } \
|
||||
@@ -83,13 +96,33 @@ public: \
|
||||
AZ_COMPONENT({{nodeableNodeName}}, {% if Class.attrib['NodeableUuid'] is defined %}"{{Class.attrib['NodeableUuid']}}"{% else %}"{{nodeableNodeName|createHashGuid}}"{% endif %}, ScriptCanvas::Nodes::NodeableNode);
|
||||
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
static void ExtendReflectionSerialize([[maybe_unused]] AZ::SerializeContext::ClassBuilder* builder){% if Class.attrib['ExtendReflectionSerialize'] is defined %};{% else %}{}{% endif %}
|
||||
|
||||
static void ExtendReflectionEdit([[maybe_unused]] AZ::EditContext::ClassBuilder* builder){% if Class.attrib['ExtendReflectionEdit'] is defined %};{% else %}{}{% endif %}
|
||||
|
||||
static void ExtendReflectionBehavior([[maybe_unused]] AZ::BehaviorContext::ClassBuilder<{{nodeableNodeName}}>* builder){% if Class.attrib['ExtendReflectionBehavior'] is defined %};{% else %}{}{% endif %}
|
||||
|
||||
void ConfigureSlots() override;
|
||||
|
||||
{% if Class.attrib['ExtendConfigureSlots'] is defined %}
|
||||
void ExtendConfigureSlots([[maybe_unused]] SlotExecution::Ins& ins, [[maybe_unused]] SlotExecution::Outs& latents);
|
||||
|
||||
{% else %}
|
||||
/* no slot configuration extension, Use Class attribute 'ExtendConfigureSlots' to extend them */
|
||||
|
||||
{% endif %}
|
||||
void ConfigureVisualExtensions() override;
|
||||
|
||||
size_t GenerateFingerprint() const override;
|
||||
{% if Class.attrib['EntryPoint'] is defined and Class.attrib['EntryPoint'] == "true" %}
|
||||
|
||||
{% if Class.attrib['EntryPoint'] is defined and Class.attrib['EntryPoint'] == "true" %}
|
||||
bool IsEntryPoint() const override { return true; }
|
||||
{% endif %}
|
||||
|
||||
{% endif %}
|
||||
{{nodeableNodeName}}();
|
||||
|
||||
{{Class.attrib['NodeDeclarations']}}
|
||||
};
|
||||
}
|
||||
{% endif %}
|
||||
@@ -100,6 +133,5 @@ public: \
|
||||
|
||||
{{ macros.ReportErrors() }}
|
||||
|
||||
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
+86
-74
@@ -19,15 +19,10 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <AzCore/RTTI/BehaviorContext.h>
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
#include <AzCore/RTTI/TypeInfo.h>
|
||||
|
||||
#include <ScriptCanvas/Core/Contracts.h>
|
||||
#include <ScriptCanvas/Core/NodeableNode.h>
|
||||
#include <ScriptCanvas/Core/SlotExecutionMap.h>
|
||||
#include <ScriptCanvas/Grammar/ParsingUtilities.h>
|
||||
|
||||
#include <ScriptCanvas/Utils/VersionConverters.h>
|
||||
|
||||
{% for xml in dataFiles %}
|
||||
@@ -47,13 +42,18 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
{%- set attribute_Category = Class.attrib['Category'] %}
|
||||
{%- set attribute_Uuid = Class.attrib['Uuid'] %}
|
||||
{%- set attribute_Icon = Class.attrib['Icon'] %}
|
||||
{%- set attribute_Base = Class.attrib['Base'] %}
|
||||
{%- set attribute_GeneratePropertyFriend = Class.attrib['GeneratePropertyFriend'] %}
|
||||
{%- set attribute_Version = Class.attrib['Version'] %}
|
||||
{%- set attribute_VersionConverter = Class.attrib['VersionConverter'] %}
|
||||
{%- set attribute_EventHandler = Class.attrib['EventHandler'] %}
|
||||
{%- set attribute_Deprecated = Class.attrib['Deprecated'] %}
|
||||
|
||||
|
||||
{%- set attribute_Base = Class.attrib['Base'] %}
|
||||
{% if not Class.attrib['Base'] is defined %}
|
||||
{% set attribute_Base = "ScriptCanvas::Nodeable" %}
|
||||
{% endif %}
|
||||
|
||||
{% set attribute_Namespace = undefined %}
|
||||
{%- if Class.attrib['Namespace'] is defined %}
|
||||
{% if Class.attrib['Namespace'] != "None" %}
|
||||
@@ -95,19 +95,6 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
{{CollectDisplayGroups('Output')}}
|
||||
{{CollectDisplayGroups('Parameter')}}
|
||||
|
||||
{# FOR DEBUGGING / DIAGNOSTIC
|
||||
|
||||
// Standalone (No DisplayGroup) {{ global_standaloneTagMap }}
|
||||
{% for key, value in global_standaloneTagMap.items() %}
|
||||
// {{key}} : {{value}}
|
||||
{% endfor %}
|
||||
|
||||
// DisplayGrouped {{ global_displayGroupMap }}
|
||||
{% for key, value in global_displayGroupMap.items() %}
|
||||
// {{key}} : {{value}}
|
||||
{% endfor %}
|
||||
#}
|
||||
|
||||
{# ----------------------------------------------------------------------------------------- #}
|
||||
|
||||
{% if attribute_Namespace is defined %}
|
||||
@@ -115,33 +102,6 @@ namespace {{attribute_Namespace}}
|
||||
{
|
||||
{% endif %}
|
||||
|
||||
{# Standard "In" function }
|
||||
{{nodemacro.FunctionSignature(attribute_QualifiedName, Class)}}
|
||||
{
|
||||
{%- for parameter in Class.findall('Parameter') -%}
|
||||
{% if parameter.attrib['Input'] is defined and parameter.attrib['Input'] == "True" %}
|
||||
|
||||
// this->{{parameter.attrib['Name']}} = arg{{loop.index0}};
|
||||
|
||||
{%- endif -%}
|
||||
{% endfor %}
|
||||
|
||||
{% set returnNames = [] %}
|
||||
{% set returnTypes = [] %}
|
||||
{%- for return in Class.findall('Parameter') -%}
|
||||
{%- if return.attrib['Output'] is defined and return.attrib['Output'] == "True" -%}
|
||||
{% if returnTypes.append(return.attrib['Type']) %}{% endif %}
|
||||
{% if returnNames.append("this->" + return.attrib['Name']) %}{% endif %}
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
|
||||
{% if returnNames|length() == 1 %}
|
||||
return {{returnNames[0]}};
|
||||
{% elif returnNames|length() > 1 %}
|
||||
return AZStd::tuple<{{returnTypes|join(", ")}}>({{returnNames|join(", ")}});
|
||||
{% endif %}
|
||||
}
|
||||
#}
|
||||
{%- set nodeableNodeName = attribute_Name + 'Node' %}
|
||||
{% set list_outputs = [] %}
|
||||
{% for output in Class.iter('Output') %}
|
||||
@@ -156,43 +116,81 @@ return {{returnNames[0]}};
|
||||
{% for item in Class.iter('Output') %}
|
||||
{% if item.attrib['DisplayGroup'] is defined %}{% set displayGroup = item.attrib['DisplayGroup'] %}{% endif %}
|
||||
{% endfor %}
|
||||
{% set branches = [] %}
|
||||
{% for method in Class.findall('Input') %}
|
||||
{% for branch in method.findall('Branch') %}
|
||||
{% if branches.append(branch) %}{% endif %}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
{# ExecutionOuts #}
|
||||
// ExecutionOuts begin
|
||||
{{ nodemacro.ExecutionOutDefinitions(Class, attribute_QualifiedName)}}
|
||||
{% if not Class.attrib['ExtendConfigureSlots'] is defined %} size_t {{attribute_QualifiedName}}::GetRequiredOutCount() const { return {{Class.findall('Output')|length + branches|length}}; }{% endif %}
|
||||
// ExecutionOuts end
|
||||
{# Reflect #}
|
||||
|
||||
{% if Class.attrib['ExtendReflectionSerialize'] is defined %}
|
||||
{% set ExtendReflectionSerialize = "defined" %}
|
||||
{% set preSerialize = "serializeBuilder" %}
|
||||
{% set postSerialize = ";" %}
|
||||
{% else %}
|
||||
{% set preSerialize = "" %}
|
||||
{% set postSerialize = "" %}
|
||||
{% endif %}
|
||||
|
||||
{% if Class.attrib['ExtendReflectionEdit'] is defined %}
|
||||
{% set ExtendReflectionEdit = "defined" %}
|
||||
{% set preEdit = "editorBuilder" %}
|
||||
{% set postEdit = ";" %}
|
||||
{% else %}
|
||||
{% set preEdit = "" %}
|
||||
{% set postEdit = "" %}
|
||||
{% endif %}
|
||||
|
||||
{% if Class.attrib['ExtendReflectionBehavior'] is defined %}
|
||||
{% set ExtendReflectionBehavior = "defined" %}
|
||||
{% set preBehavior = "behaviorBuilder" %}
|
||||
{% set postBehavior = ";" %}
|
||||
{% else %}
|
||||
{% set preBehavior = "" %}
|
||||
{% set postBehavior = "" %}
|
||||
{% endif %}
|
||||
|
||||
void {{attribute_QualifiedName}}::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
using namespace ScriptCanvas;
|
||||
|
||||
if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<{{ attribute_Name }}{% if attribute_Base is defined %}, {{ attribute_Base }}{% endif %}>()
|
||||
{% if ExtendReflectionSerialize is defined %} auto {{preSerialize}} = {% else %} {% endif %}serializeContext->Class<{{ attribute_Name }}{% if attribute_Base is defined %}, {{ attribute_Base }}{% endif %}>(){{postSerialize}}
|
||||
{% if attribute_EventHandler is defined %}
|
||||
->EventHandler<{{ attribute_EventHandler }}>()
|
||||
{{preSerialize}}->EventHandler<{{ attribute_EventHandler }}>(){{postSerialize}}
|
||||
{% endif %}
|
||||
|
||||
{# Serialized Properties #}
|
||||
{% for Property in Class.iter('Property') %}
|
||||
{% set property_Name = Property.attrib['Name'] %}
|
||||
->Field("{{ property_Name }}", &{{ attribute_Name }}::{{ property_Name | replace(' ','') }})
|
||||
{{preSerialize}}->Field("{{ property_Name }}", &{{ attribute_Name }}::{{ property_Name | replace(' ','') }}){{postSerialize}}
|
||||
{% endfor %}
|
||||
;
|
||||
|
||||
{% if ExtendReflectionSerialize is defined %}
|
||||
ExtendReflectionSerialize(&{{preSerialize}});
|
||||
{% endif %}
|
||||
|
||||
if (AZ::EditContext* editContext = serializeContext->GetEditContext())
|
||||
{
|
||||
editContext->Class<{{ attribute_QualifiedName }}>("{{ attribute_PreferredClassName }}", "{{ attribute_Description }}")
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
|
||||
|
||||
{% if ExtendReflectionEdit is defined %} auto {{preEdit}} = {% else %} {% endif %}editContext->Class<{{ attribute_QualifiedName }}>("{{ attribute_PreferredClassName }}", "{{ attribute_Description }}"){{postEdit}}
|
||||
{{preEdit}}->ClassElement(AZ::Edit::ClassElements::EditorData, ""){{postEdit}}
|
||||
{{preEdit}}->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly){{postEdit}}
|
||||
{% if attribute_Category is defined %}
|
||||
->Attribute(AZ::Edit::Attributes::Category, "{{ attribute_Category }}")
|
||||
{{preEdit}}->Attribute(AZ::Edit::Attributes::Category, "{{ attribute_Category }}"){{postEdit}}
|
||||
{%- endif %}
|
||||
{% if attribute_Icon is defined %}
|
||||
->Attribute(AZ::Edit::Attributes::Icon, "{{ attribute_Icon }}")
|
||||
{{preEdit}}->Attribute(AZ::Edit::Attributes::Icon, "{{ attribute_Icon }}"){{postEdit}}
|
||||
{%- endif %}
|
||||
{% if attribute_Deprecated is defined %}
|
||||
->Attribute(AZ::Edit::Attributes::Deprecated, "{{ attribute_Deprecated }}")
|
||||
{{preEdit}}->Attribute(AZ::Edit::Attributes::Deprecated, "{{ attribute_Deprecated }}"){{postEdit}}
|
||||
{%- endif %}
|
||||
{% set uihandler = 'AZ::Edit::UIHandlers::Default' %}
|
||||
{% for item in Class.iter('Property') %}
|
||||
@@ -203,29 +201,34 @@ void {{attribute_QualifiedName}}::Reflect(AZ::ReflectContext* context)
|
||||
{% if item.attrib['Description'] is defined %}
|
||||
{% set description = item.attrib['Description'] %}
|
||||
{% endif %}
|
||||
// {{ item.attrib['Name'] }}
|
||||
->DataElement({{ uihandler }}, &{{ attribute_Name }}::{{ item.attrib['Name'] }}, "{{ item.attrib['Name'] }}", "{{ description }}")
|
||||
// {{ item.attrib['Name'] }}
|
||||
{{preEdit}}->DataElement({{ uihandler }}, &{{ attribute_Name }}::{{ item.attrib['Name'] }}, "{{ item.attrib['Name'] }}", "{{ description }}"){{postEdit}}
|
||||
{% for EditAttribute in item.iter('EditAttribute') %}
|
||||
->Attribute({{ EditAttribute.attrib['Key'] }}, {{ EditAttribute.attrib['Value'] }})
|
||||
{{preEdit}}->Attribute({{ EditAttribute.attrib['Key'] }}, {{ EditAttribute.attrib['Value'] }}){{postEdit}}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
;
|
||||
{% if ExtendReflectionEdit is defined %}
|
||||
ExtendReflectionEdit(&{{preEdit}});
|
||||
{% endif %}
|
||||
}
|
||||
}
|
||||
|
||||
// Behavior Context Reflection
|
||||
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
|
||||
{
|
||||
behaviorContext->Class<{{ attribute_Name }}>("{{ attribute_Name }}")
|
||||
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::List)
|
||||
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
|
||||
{% if ExtendReflectionBehavior is defined %} auto {{preBehavior}} = {% else %} {% endif %}behaviorContext->Class<{{ attribute_Name }}>("{{ attribute_Name }}"){{postBehavior}}
|
||||
{{preBehavior}}->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::List){{postBehavior}}
|
||||
{{preBehavior}}->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common){{postBehavior}}
|
||||
{% for inputMethod in Class.iter('Input') %}
|
||||
{% set methodName = inputMethod.attrib['Name'] %}
|
||||
// {{ inputMethod.attrib['Name'] }}
|
||||
->Method(Grammar::ToIdentifier("{{ macros.SlotName(methodName) }}").c_str(), &{{ attribute_Name }}::{{ macros.CleanName(methodName) }})
|
||||
{{preBehavior}}->Method(Grammar::ToIdentifier("{{ macros.SlotName(methodName) }}").c_str(), &{{ attribute_Name }}::{{ macros.CleanName(methodName) }}){{postBehavior}}
|
||||
{% endfor %}
|
||||
|
||||
;
|
||||
{% if ExtendReflectionBehavior is defined %}
|
||||
ExtendReflectionBehavior(&{{preBehavior}});
|
||||
{% endif %}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -253,27 +256,32 @@ Nodes::{{ nodeableNodeName }}::{{ nodeableNodeName }}()
|
||||
{# NodeableNode Reflection #}
|
||||
void Nodes::{{ nodeableNodeName }}::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
|
||||
{{ attribute_QualifiedName }}::Reflect(context);
|
||||
|
||||
// Serialization Context Reflection
|
||||
if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<{{ nodeableNodeName }}, NodeableNode>()
|
||||
{%if ExtendReflectionSerialize is defined%}auto {{preSerialize}} = {%endif%}serializeContext->Class<{{ nodeableNodeName }}, NodeableNode>(){{postSerialize}}
|
||||
{% if attribute_Version is defined %}
|
||||
->Version({{ attribute_Version }}{% if attribute_VersionConverter is defined %}, &{{ attribute_VersionConverter }}{% endif %})
|
||||
{{preSerialize}}->Version({{ attribute_Version }}{% if attribute_VersionConverter is defined %}, &{{ attribute_VersionConverter }}{% endif %}){{postSerialize}}
|
||||
{% else %}
|
||||
->Version(0)
|
||||
{{preSerialize}}->Version(0){{postSerialize}}
|
||||
{% endif %}
|
||||
;
|
||||
{% if ExtendReflectionSerialize is defined %}
|
||||
ExtendReflectionSerialize(&{{preSerialize}});
|
||||
{% endif %}
|
||||
;
|
||||
|
||||
if (AZ::EditContext* editContext = serializeContext->GetEditContext())
|
||||
{
|
||||
editContext->Class<{{ nodeableNodeName }}>("{{ attribute_PreferredClassName }}", "{{ attribute_Description }}")
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
|
||||
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
||||
;
|
||||
{% if ExtendReflectionEdit is defined %}auto {{preEdit}} = {%endif%}editContext->Class<{{ nodeableNodeName }}>("{{ attribute_PreferredClassName }}", "{{ attribute_Description }}"){{postEdit}}
|
||||
{{preEdit}}->ClassElement(AZ::Edit::ClassElements::EditorData, ""){{postEdit}}
|
||||
{{preEdit}}->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly){{postEdit}}
|
||||
{{preEdit}}->Attribute(AZ::Edit::Attributes::AutoExpand, true){{postEdit}}
|
||||
;
|
||||
{% if ExtendReflectionEdit is defined %}
|
||||
ExtendReflectionEdit(&{{preEdit}});
|
||||
{% endif %}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -324,6 +332,7 @@ void Nodes::{{ nodeableNodeName }}::ConfigureVisualExtensions()
|
||||
RegisterExtension(visualExtensions);
|
||||
}
|
||||
{% endfor %}
|
||||
OnConfigureVisualExtensions();
|
||||
}
|
||||
|
||||
{# ConfigureSlots #}
|
||||
@@ -457,6 +466,9 @@ void Nodes::{{ nodeableNodeName }}::ConfigureSlots()
|
||||
{% endfor %}
|
||||
#}
|
||||
|
||||
{% if Class.attrib['ExtendConfigureSlots'] is defined %}
|
||||
ExtendConfigureSlots(ins, outs);
|
||||
{% endif %}
|
||||
// Generate the execution map
|
||||
m_slotExecutionMap = SlotExecution::Map(AZStd::move(ins), AZStd::move(outs));
|
||||
|
||||
|
||||
+1
-4
@@ -349,7 +349,4 @@ void {{qualifiedName}}::Call{{CleanName(outName)}}({{ExecutionOutReturnDefinitio
|
||||
{%- for executionOut in Class.findall('Output') -%}
|
||||
{{ ExecutionOutDefinition(Class, qualifiedName, executionOut, loop.index0 + branches|length) }}
|
||||
{%- endfor %}
|
||||
|
||||
size_t {{qualifiedName}}::GetRequiredOutCount() const { return {{Class.findall('Output')|length + branches|length}}; }
|
||||
|
||||
{% endmacro %}
|
||||
{% endmacro %}
|
||||
@@ -250,7 +250,6 @@ namespace ScriptCanvas
|
||||
};
|
||||
|
||||
using ScriptCanvasSettingsRequestBus = AZ::EBus<ScriptCanvasSettingsRequests>;
|
||||
|
||||
}
|
||||
|
||||
namespace AZStd
|
||||
|
||||
@@ -1476,9 +1476,11 @@ namespace ScriptCanvas
|
||||
|
||||
const void* Datum::GetValueAddress() const
|
||||
{
|
||||
return m_type.GetType() != Data::eType::BehaviorContextObject
|
||||
? AZStd::any_cast<void>(&m_storage)
|
||||
: (*AZStd::any_cast<BehaviorContextObjectPtr>(&m_storage))->Get();
|
||||
return !m_storage.empty()
|
||||
? m_type.GetType() != Data::eType::BehaviorContextObject
|
||||
? AZStd::any_cast<void>(&m_storage)
|
||||
: (*AZStd::any_cast<BehaviorContextObjectPtr>(&m_storage))->Get()
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
bool Datum::Initialize(const Data::Type& type, eOriginality originality, const void* source, const AZ::Uuid& sourceTypeID)
|
||||
|
||||
@@ -389,7 +389,7 @@ namespace ScriptCanvas
|
||||
|
||||
bool Datum::Empty() const
|
||||
{
|
||||
return GetValueAddress() == nullptr;
|
||||
return m_storage.empty() || GetValueAddress() == nullptr;
|
||||
}
|
||||
|
||||
template<typename t_Value>
|
||||
|
||||
@@ -3577,12 +3577,12 @@ namespace ScriptCanvas
|
||||
}
|
||||
|
||||
if (targetSlotType == CombinedSlotType::DataOut
|
||||
&& executionSlot.GetType() == CombinedSlotType::ExecutionIn
|
||||
&& executionInCount > 1)
|
||||
&& executionSlot.GetType() == CombinedSlotType::ExecutionIn
|
||||
&& executionInCount > 1)
|
||||
{
|
||||
if (!executionChildSlot || executionChildSlot->GetType() != CombinedSlotType::ExecutionOut)
|
||||
{
|
||||
return AZ::Failure(AZStd::string("Data out by ExcutionIn must have child out slot"));
|
||||
return AZ::Failure(AZStd::string("Data out by ExecutionIn must have child out slot"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3626,6 +3626,11 @@ namespace ScriptCanvas
|
||||
return {};
|
||||
}
|
||||
|
||||
Grammar::MultipleFunctionCallFromSingleSlotInfo Node::GetMultipleFunctionCallFromSingleSlotInfo([[maybe_unused]] const Slot& slot) const
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
VariableId Node::GetVariableIdRead(const Slot*) const
|
||||
{
|
||||
return {};
|
||||
|
||||
@@ -715,6 +715,8 @@ namespace ScriptCanvas
|
||||
|
||||
virtual PropertyFields GetPropertyFields() const;
|
||||
|
||||
virtual Grammar::MultipleFunctionCallFromSingleSlotInfo GetMultipleFunctionCallFromSingleSlotInfo(const Slot& slot) const;
|
||||
|
||||
virtual VariableId GetVariableIdRead(const Slot*) const;
|
||||
|
||||
virtual VariableId GetVariableIdWritten(const Slot*) const;
|
||||
|
||||
@@ -73,6 +73,8 @@ namespace ScriptCanvas
|
||||
|
||||
void ConfigureSlots() override;
|
||||
|
||||
virtual void OnConfigureVisualExtensions() {}
|
||||
|
||||
AZ::Outcome<const AZ::BehaviorClass*, AZStd::string> GetBehaviorContextClass() const;
|
||||
|
||||
ConstSlotsOutcome GetBehaviorContextOutName(const Slot& inSlot) const;
|
||||
|
||||
@@ -46,6 +46,8 @@ namespace ScriptCanvas
|
||||
|
||||
const AZStd::unordered_map<AZStd::string, AZStd::pair<SlotId, SlotId>>& GetPropertyNameSlotMap() const;
|
||||
|
||||
AZ_INLINE AZ::Outcome<DependencyReport, void> GetDependencies() const override { return AZ::Success(DependencyReport{}); }
|
||||
|
||||
~PureData() override;
|
||||
|
||||
protected:
|
||||
|
||||
@@ -2249,6 +2249,10 @@ namespace ScriptCanvas
|
||||
}
|
||||
#endif
|
||||
AddAllVariablesPreParse();
|
||||
if (!IsErrorFree())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto& nodeEntity : m_source.m_graphData->m_nodes)
|
||||
{
|
||||
@@ -2270,6 +2274,16 @@ namespace ScriptCanvas
|
||||
{
|
||||
AddError(nullptr, ValidationConstPtr(aznew NullEntityInGraph()));
|
||||
}
|
||||
|
||||
if (!IsErrorFree())
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!IsErrorFree())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ParseAutoConnectedEBusHandlerVariables();
|
||||
@@ -2638,7 +2652,8 @@ namespace ScriptCanvas
|
||||
AZStd::vector<VariableId> inputVariableIds;
|
||||
AZStd::unordered_map<VariableId, Grammar::VariableConstPtr> inputVariablesById;
|
||||
|
||||
for (auto variable : GetVariables())
|
||||
auto& variables = GetVariables();
|
||||
for (auto variable : variables)
|
||||
{
|
||||
auto constructionRequirement = ParseConstructionRequirement(variable);
|
||||
|
||||
@@ -2655,18 +2670,30 @@ namespace ScriptCanvas
|
||||
|
||||
case VariableConstructionRequirement::InputNodeable:
|
||||
{
|
||||
if (variable->m_datum.Empty())
|
||||
{
|
||||
AddError(nullptr, aznew Internal::ParseError(AZ::EntityId{}, "Empty nodeable datum in variable, probably due to a problem with azrtti declarations"));
|
||||
break;
|
||||
}
|
||||
|
||||
// I solemnly swear no harm shall come to the nodeable
|
||||
const Nodeable* nodeableSource = reinterpret_cast<const Nodeable*>(variable->m_datum.GetAsDanger());
|
||||
AZ_Assert(nodeableSource != nullptr, "the must be a raw nodeable held by this pointer");
|
||||
AZ_Assert(azrtti_typeid(nodeableSource) != azrtti_typeid<Nodeable>(), "type problem with nodeable");
|
||||
|
||||
if (!nodeableSource)
|
||||
{
|
||||
AddError(nullptr, aznew Internal::ParseError(AZ::EntityId{}, "No raw nodeable held by variable"));
|
||||
break;
|
||||
}
|
||||
|
||||
nodeablesById.push_back({ variable->m_nodeableNodeId, const_cast<Nodeable*>(nodeableSource) });
|
||||
}
|
||||
break;
|
||||
|
||||
case VariableConstructionRequirement::InputVariable:
|
||||
{
|
||||
inputVariableIds.push_back(variable->m_sourceVariableId);
|
||||
inputVariablesById.insert({ variable->m_sourceVariableId, variable });
|
||||
auto variableID = variable->m_sourceVariableId.IsValid() ? variable->m_sourceVariableId : VariableId::MakeVariableId();
|
||||
inputVariableIds.push_back(variableID);
|
||||
inputVariablesById.insert({ variableID, variable });
|
||||
// sort revealed a datum copy issue: type is not preserved, workaround below
|
||||
// m_runtimeInputs.m_variables.emplace_back(variable->m_sourceVariableId, variable->m_datum);
|
||||
}
|
||||
@@ -4310,6 +4337,7 @@ namespace ScriptCanvas
|
||||
{
|
||||
if (auto variable = FindVariable(execution->GetNodeId()))
|
||||
{
|
||||
execution->MarkInputHasThisPointer();
|
||||
execution->AddInput({ nullptr, variable, DebugDataSource::FromInternal() });
|
||||
}
|
||||
else
|
||||
@@ -4327,6 +4355,7 @@ namespace ScriptCanvas
|
||||
{
|
||||
auto variable = AZStd::make_shared<Variable>();
|
||||
variable->m_datum = Datum(eventHandling->m_handlerName);
|
||||
execution->MarkInputHasThisPointer();
|
||||
execution->AddInput({ nullptr, variable, DebugDataSource::FromInternal() });
|
||||
}
|
||||
else
|
||||
@@ -4338,6 +4367,7 @@ namespace ScriptCanvas
|
||||
{
|
||||
if (auto variable = FindVariable(execution->GetNodeId()))
|
||||
{
|
||||
execution->MarkInputHasThisPointer();
|
||||
execution->AddInput({ nullptr, variable, DebugDataSource::FromInternal() });
|
||||
}
|
||||
else
|
||||
@@ -4367,12 +4397,159 @@ namespace ScriptCanvas
|
||||
void AbstractCodeModel::ParseMultiExecutionPost(ExecutionTreePtr execution)
|
||||
{
|
||||
ParsePropertyExtractionsPost(execution);
|
||||
ParseMultipleFunctionCallPost(execution);
|
||||
}
|
||||
|
||||
void AbstractCodeModel::ParseMultiExecutionPre(ExecutionTreePtr execution)
|
||||
{
|
||||
ParsePropertyExtractionsPre(execution);
|
||||
}
|
||||
}
|
||||
|
||||
void AbstractCodeModel::ParseMultipleFunctionCallPost(ExecutionTreePtr execution)
|
||||
{
|
||||
auto& id = execution->GetId();
|
||||
MultipleFunctionCallFromSingleSlotInfo info = id.m_node->GetMultipleFunctionCallFromSingleSlotInfo(*id.m_slot);
|
||||
|
||||
if (info.functionCalls.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto parent = execution->ModParent();
|
||||
|
||||
if (!parent)
|
||||
{
|
||||
AddError(execution, aznew Internal::ParseError(id.m_node->GetEntityId(), "Null parent in MultipleFunctionCall"));
|
||||
return;
|
||||
}
|
||||
|
||||
size_t indexInParentCall = parent->FindChildIndex(execution);
|
||||
if (indexInParentCall >= parent->GetChildrenCount())
|
||||
{
|
||||
AddError(execution, aznew Internal::ParseError(id.m_node->GetEntityId(), ParseErrors::MultipleFunctionCallFromSingleSlotNoChildren));
|
||||
return;
|
||||
}
|
||||
|
||||
ExecutionChild* executionChildInParent = &parent->ModChild(indexInParentCall);
|
||||
|
||||
const size_t executionInputCount = execution->GetInputCount();
|
||||
const size_t thisInputOffset = execution->InputHasThisPointer() ? 1 : 0;
|
||||
|
||||
// the original index has ALL the input from the slots on the node
|
||||
// create multiple calls with separate function call nodes, but ONLY take the inputs required
|
||||
// as indicated by the function call info
|
||||
|
||||
AZStd::unordered_set<const Slot*> usedSlots;
|
||||
bool variadicIsFound = false;
|
||||
|
||||
auto createChild = [&](auto parentCall, ExecutionChild* childInParent, auto& functionCallInfo)
|
||||
{
|
||||
auto child = CreateChild(parentCall, id.m_node, id.m_slot);
|
||||
child->SetSymbol(Symbol::FunctionCall);
|
||||
child->SetName(functionCallInfo.functionName);
|
||||
child->SetNameLexicalScope(functionCallInfo.lexicalScope);
|
||||
childInParent->m_execution = child;
|
||||
return child;
|
||||
};
|
||||
|
||||
auto addThisInput = [&](auto functionCall)
|
||||
{
|
||||
if (thisInputOffset != 0)
|
||||
{
|
||||
if (executionInputCount == 0)
|
||||
{
|
||||
AddError(execution, aznew Internal::ParseError(id.m_node->GetEntityId(), ParseErrors::MultipleFunctionCallFromSingleSlotNotEnoughInputForThis));
|
||||
return;
|
||||
}
|
||||
|
||||
const ExecutionInput& input = execution->GetInput(0);
|
||||
usedSlots.insert(input.m_slot);
|
||||
functionCall->AddInput(input);
|
||||
}
|
||||
};
|
||||
|
||||
auto addSlotInput = [&](auto functionCall, size_t inputIndex)
|
||||
{
|
||||
if (inputIndex >= executionInputCount)
|
||||
{
|
||||
AddError(execution, aznew Internal::ParseError(id.m_node->GetEntityId(), ParseErrors::MultipleFunctionCallFromSingleSlotNotEnoughInput));
|
||||
return;
|
||||
}
|
||||
|
||||
const ExecutionInput& input = execution->GetInput(inputIndex);
|
||||
|
||||
if (usedSlots.contains(input.m_slot))
|
||||
{
|
||||
AddError(execution, aznew Internal::ParseError(id.m_node->GetEntityId(), ParseErrors::MultipleFunctionCallFromSingleSlotNotEnoughInput));
|
||||
return;
|
||||
}
|
||||
|
||||
usedSlots.insert(input.m_slot);
|
||||
|
||||
if (input.m_value->m_source == execution)
|
||||
{
|
||||
input.m_value->m_source = functionCall;
|
||||
}
|
||||
|
||||
functionCall->AddInput(input);
|
||||
};
|
||||
|
||||
auto addCall = [&](auto& functionCallInfo, auto childInParent, size_t startingIndex, size_t sentinel, size_t variadicOffset = 0)
|
||||
{
|
||||
auto child = createChild(parent, childInParent, functionCallInfo);
|
||||
addThisInput(child);
|
||||
|
||||
for (size_t index = startingIndex; index < sentinel; ++index)
|
||||
{
|
||||
const size_t inputIndex = index + thisInputOffset + variadicOffset;
|
||||
addSlotInput(child, inputIndex);
|
||||
}
|
||||
|
||||
child->AddChild({});
|
||||
childInParent = &child->ModChild(0);
|
||||
return AZStd::make_pair(childInParent, child);
|
||||
};
|
||||
|
||||
// loop through each call...
|
||||
for (auto& functionCallInfo : info.functionCalls)
|
||||
{
|
||||
// ...first add any pre-variadic calls, using the starting index and the number of args, since they could come in any order, not input slot order...
|
||||
if (!functionCallInfo.isVariadic)
|
||||
{
|
||||
AZStd::pair<ExecutionChild*, ExecutionTreePtr> childInParentAndParent = addCall(functionCallInfo, executionChildInParent, functionCallInfo.startingIndex, functionCallInfo.startingIndex + functionCallInfo.numArguments);
|
||||
executionChildInParent = childInParentAndParent.first;
|
||||
parent = childInParentAndParent.second;
|
||||
}
|
||||
else
|
||||
{
|
||||
// ...then add only one variadic call if there is one...
|
||||
if (variadicIsFound)
|
||||
{
|
||||
AddError(execution, aznew Internal::ParseError(id.m_node->GetEntityId(), ParseErrors::MultipleFunctionCallFromSingleSlotMultipleVariadic));
|
||||
return;
|
||||
}
|
||||
|
||||
variadicIsFound = true;
|
||||
const size_t sentinel = executionInputCount == 0 ? 0 : executionInputCount - thisInputOffset;
|
||||
// ... by looping through the remaining slots, striding by functionCallInfo.numArguments, making repeated calls to the function
|
||||
for (size_t slotInputIndex = functionCallInfo.startingIndex; slotInputIndex < sentinel; slotInputIndex += functionCallInfo.numArguments)
|
||||
{
|
||||
AZStd::pair<ExecutionChild*, ExecutionTreePtr> childInParentAndParent = addCall(functionCallInfo, executionChildInParent, 0, functionCallInfo.numArguments, slotInputIndex);
|
||||
executionChildInParent = childInParentAndParent.first;
|
||||
parent = childInParentAndParent.second;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (info.errorOnUnusedSlot && usedSlots.size() != executionInputCount)
|
||||
{
|
||||
AddError(execution, aznew Internal::ParseError(id.m_node->GetEntityId(), ParseErrors::MultipleFunctionCallFromSingleSlotUnused));
|
||||
}
|
||||
|
||||
// parent now refers to the last child call created
|
||||
parent->SwapChildren(execution);
|
||||
execution->Clear();
|
||||
}
|
||||
|
||||
void AbstractCodeModel::ParseNodelingVariables(const Node& node, NodelingType nodelingType)
|
||||
{
|
||||
@@ -5146,6 +5323,6 @@ namespace ScriptCanvas
|
||||
return type == Data::eType::BehaviorContextObject;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -387,6 +387,8 @@ namespace ScriptCanvas
|
||||
|
||||
void ParseMultiExecutionPre(ExecutionTreePtr execution);
|
||||
|
||||
void ParseMultipleFunctionCallPost(ExecutionTreePtr execution);
|
||||
|
||||
void ParseNodelingVariables(const Node& node, NodelingType nodelingType);
|
||||
|
||||
void ParseOperatorArithmetic(ExecutionTreePtr execution);
|
||||
|
||||
@@ -1132,14 +1132,14 @@ namespace ScriptCanvas
|
||||
}
|
||||
else if (variable->m_isExposedToConstruction)
|
||||
{
|
||||
if (variable->m_sourceVariableId.IsValid())
|
||||
{
|
||||
return VariableConstructionRequirement::InputVariable;
|
||||
}
|
||||
else if (variable->m_nodeableNodeId.IsValid())
|
||||
if (variable->m_nodeableNodeId.IsValid())
|
||||
{
|
||||
return VariableConstructionRequirement::InputNodeable;
|
||||
}
|
||||
else if (variable->m_sourceVariableId.IsValid())
|
||||
{
|
||||
return VariableConstructionRequirement::InputVariable;
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Assert(false, "A member variable in the model has no valid id");
|
||||
|
||||
@@ -164,6 +164,34 @@ namespace ScriptCanvas
|
||||
virtual void PostParseExecutionTreeBody(AbstractCodeModel& /*model*/, ExecutionTreePtr /*execution*/) {}
|
||||
};
|
||||
|
||||
// for now, no return values supported
|
||||
struct MultipleFunctionCallFromSingleSlotEntry
|
||||
{
|
||||
AZ_TYPE_INFO(MultipleFunctionCallFromSingleSlotEntry, "{360A23A3-C490-4047-B71E-64E290E441D3}");
|
||||
AZ_CLASS_ALLOCATOR(MultipleFunctionCallFromSingleSlotEntry, AZ::SystemAllocator, 0);
|
||||
|
||||
bool isVariadic = false;
|
||||
AZStd::string functionName;
|
||||
LexicalScope lexicalScope;
|
||||
size_t numArguments = 0; // stride in case isVariadic == true
|
||||
size_t startingIndex = 0; // the index of the slot order
|
||||
};
|
||||
|
||||
// for now, no return values supported
|
||||
struct MultipleFunctionCallFromSingleSlotInfo
|
||||
{
|
||||
AZ_TYPE_INFO(MultipleFunctionCallFromSingleSlotInfo, "{DF51F08A-8B28-4851-9888-9AB7CC0B90D2}");
|
||||
AZ_CLASS_ALLOCATOR(MultipleFunctionCallFromSingleSlotInfo, AZ::SystemAllocator, 0);
|
||||
|
||||
// this could likely be implemented, but needs care to duplicate input that the execution-slot created
|
||||
// bool errorOnReusedSlot = false;
|
||||
|
||||
bool errorOnUnusedSlot = false;
|
||||
|
||||
// calls are executed in the order they arrive in the vector
|
||||
AZStd::vector<MultipleFunctionCallFromSingleSlotEntry> functionCalls;
|
||||
};
|
||||
|
||||
struct NodeableParse
|
||||
: public AZStd::enable_shared_from_this<NodeableParse>
|
||||
{
|
||||
|
||||
@@ -313,6 +313,11 @@ namespace ScriptCanvas
|
||||
return !m_returnValues.empty();
|
||||
}
|
||||
|
||||
bool ExecutionTree::InputHasThisPointer() const
|
||||
{
|
||||
return m_inputHasThisPointer;
|
||||
}
|
||||
|
||||
bool ExecutionTree::IsInfiniteLoopDetectionPoint() const
|
||||
{
|
||||
return m_isInfiniteLoopDetectionPoint;
|
||||
@@ -377,6 +382,11 @@ namespace ScriptCanvas
|
||||
m_isInfiniteLoopDetectionPoint = true;
|
||||
}
|
||||
|
||||
void ExecutionTree::MarkInputHasThisPointer()
|
||||
{
|
||||
m_inputHasThisPointer = true;
|
||||
}
|
||||
|
||||
void ExecutionTree::MarkInputOutputPreprocessed()
|
||||
{
|
||||
m_isInputOutputPreprocessed = true;
|
||||
@@ -587,6 +597,32 @@ namespace ScriptCanvas
|
||||
m_symbol = val;
|
||||
}
|
||||
|
||||
}
|
||||
void ExecutionTree::SwapChildren(ExecutionTreePtr execution)
|
||||
{
|
||||
if (execution)
|
||||
{
|
||||
m_children.swap(execution->m_children);
|
||||
|
||||
for (auto& child : m_children)
|
||||
{
|
||||
if (child.m_execution)
|
||||
{
|
||||
child.m_execution->SetParent(shared_from_this());
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& orphan : execution->m_children)
|
||||
{
|
||||
if (orphan.m_execution)
|
||||
{
|
||||
orphan.m_execution->SetParent(execution);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ClearChildren();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,6 +190,8 @@ namespace ScriptCanvas
|
||||
|
||||
bool HasReturnValues() const;
|
||||
|
||||
bool InputHasThisPointer() const;
|
||||
|
||||
bool IsInfiniteLoopDetectionPoint() const;
|
||||
|
||||
void InsertChild(size_t index, const ExecutionChild& child);
|
||||
@@ -208,6 +210,8 @@ namespace ScriptCanvas
|
||||
|
||||
void MarkInfiniteLoopDetectionPoint();
|
||||
|
||||
void MarkInputHasThisPointer();
|
||||
|
||||
void MarkInputOutputPreprocessed();
|
||||
|
||||
void MarkInternalOut();
|
||||
@@ -262,6 +266,8 @@ namespace ScriptCanvas
|
||||
|
||||
void SetSymbol(Symbol val);
|
||||
|
||||
void SwapChildren(ExecutionTreePtr execution);
|
||||
|
||||
private:
|
||||
// the (possible) slot(s) through which execution exited, along with associated output
|
||||
AZStd::vector<ExecutionChild> m_children;
|
||||
@@ -275,6 +281,8 @@ namespace ScriptCanvas
|
||||
|
||||
bool m_isInfiniteLoopDetectionPoint = false;
|
||||
|
||||
bool m_inputHasThisPointer = false;
|
||||
|
||||
bool m_isInputOutputPreprocessed = false;
|
||||
|
||||
bool m_isInternalOut = false;
|
||||
|
||||
@@ -57,6 +57,12 @@ namespace ScriptCanvas
|
||||
constexpr const char* MissingVariableForEBusHandlerAddress = "missing variable for ebus handler address";
|
||||
constexpr const char* MissingVariableForEBusHandlerAddressConnected = "missing variable for ebus handler address";
|
||||
constexpr const char* MultipleExecutionOutConnections = "This node has multiple, unordered execution Out connections";
|
||||
constexpr const char* MultipleFunctionCallFromSingleSlotMultipleVariadic = "Only one variadic call (the last one) is supported in the multi-call per single slot.";
|
||||
constexpr const char* MultipleFunctionCallFromSingleSlotNoChildren = "Node missing from parent children.";
|
||||
constexpr const char* MultipleFunctionCallFromSingleSlotNotEnoughInput = "Not enough input to support multi call input information.";
|
||||
constexpr const char* MultipleFunctionCallFromSingleSlotNotEnoughInputForThis = "Node doesn't have enough input for a parsed this pointer.";
|
||||
constexpr const char* MultipleFunctionCallFromSingleSlotReused = "Multiple function slot reused an input slot";
|
||||
constexpr const char* MultipleFunctionCallFromSingleSlotUnused = "Multiple function slot left an input slot unused.";
|
||||
constexpr const char* MultipleSimulaneousInputValues = "Multiple values routed to the same single input with no way to discern which to take.";
|
||||
constexpr const char* MultipleStartNodes = "Multiple Start nodes in a single graph. Only one is allowed.";
|
||||
constexpr const char* NoChildrenAfterRoot = "No children after parsing function root";
|
||||
|
||||
+3989
-5135
File diff suppressed because it is too large
Load Diff
@@ -310,64 +310,95 @@ def get_project_external_subdirectories(project_path: pathlib.Path) -> list:
|
||||
project_object['external_subdirectories'])) if 'external_subdirectories' in project_object else []
|
||||
|
||||
|
||||
def get_project_templates(project_path: pathlib.Path) -> list:
|
||||
project_object = get_project_json_data(project_path=project_path)
|
||||
return list(map(lambda rel_path: (pathlib.Path(project_path) / rel_path).as_posix(),
|
||||
project_object['templates']))
|
||||
|
||||
|
||||
def get_project_restricted(project_path: pathlib.Path) -> list:
|
||||
project_object = get_project_json_data(project_path=project_path)
|
||||
return list(map(lambda rel_path: (pathlib.Path(project_path) / rel_path).as_posix(),
|
||||
project_object['restricted'])) if 'restricted' in project_object else []
|
||||
|
||||
|
||||
# Combined manifest queries
|
||||
def get_all_projects() -> list:
|
||||
projects_data = set(get_projects())
|
||||
projects_data.update(get_engine_projects())
|
||||
return list(projects_data)
|
||||
projects_data = get_projects()
|
||||
projects_data.extend(get_engine_projects())
|
||||
# Remove duplicates from the list
|
||||
return list(dict.fromkeys(projects_data))
|
||||
|
||||
|
||||
def get_all_gems(project_path: pathlib.Path = None) -> list:
|
||||
gems_data = set(get_gems())
|
||||
gems_data.update(get_engine_gems())
|
||||
gems_data = get_gems()
|
||||
gems_data.extend(get_engine_gems())
|
||||
if project_path:
|
||||
gems_data.update(get_project_gems(project_path))
|
||||
return list(gems_data)
|
||||
gems_data.extend(get_project_gems(project_path))
|
||||
return list(dict.fromkeys(gems_data))
|
||||
|
||||
|
||||
def get_all_external_subdirectories(project_path: pathlib.Path = None) -> list:
|
||||
external_subdirectories_data = set(get_external_subdirectories())
|
||||
external_subdirectories_data.update(get_engine_external_subdirectories())
|
||||
external_subdirectories_data = get_external_subdirectories()
|
||||
external_subdirectories_data.extend(get_engine_external_subdirectories())
|
||||
if project_path:
|
||||
external_subdirectories_data.update(get_project_external_subdirectories(project_path))
|
||||
return list(templates_data)
|
||||
external_subdirectories_data.extend(get_project_external_subdirectories(project_path))
|
||||
return list(dict.fromkeys(external_subdirectories_data))
|
||||
|
||||
|
||||
def get_all_templates() -> list:
|
||||
templates_data = set(get_templates())
|
||||
templates_data.update(get_engine_templates())
|
||||
return list(templates_data)
|
||||
def get_all_templates(project_path: pathlib.Path = None) -> list:
|
||||
templates_data = get_templates()
|
||||
templates_data.extend(get_engine_templates())
|
||||
if project_path:
|
||||
templates_data.extend(get_project_templates(project_path))
|
||||
return list(dict.fromkeys(templates_data))
|
||||
|
||||
|
||||
def get_all_restricted() -> list:
|
||||
restricted_data = set(get_restricted())
|
||||
restricted_data.update(get_engine_restricted())
|
||||
return list(gems_data)
|
||||
restricted_data = get_restricted()
|
||||
restricted_data.extend(get_engine_restricted())
|
||||
if project_path:
|
||||
restricted_data.extend(get_project_restricted(project_path))
|
||||
return list(dict.fromkeys(restricted_data))
|
||||
|
||||
|
||||
# Template functions
|
||||
def get_project_templates(): # temporary until we have a better way to do this... maybe template_type element
|
||||
def get_templates_for_project_creation():
|
||||
project_templates = []
|
||||
for template in get_all_templates():
|
||||
if 'Project' in template:
|
||||
project_templates.append(template)
|
||||
for template_path in get_all_templates():
|
||||
template_path = pathlib.Path(template_path)
|
||||
template_json_path = pathlib.Path(template_path) / 'template.json'
|
||||
if not validation.valid_o3de_template_json(template_json_path):
|
||||
continue
|
||||
|
||||
project_json_path = template_path / 'Template' / 'project.json'
|
||||
if validation.valid_o3de_project_json(project_json_path):
|
||||
project_templates.append(template_path)
|
||||
return project_templates
|
||||
|
||||
|
||||
def get_gem_templates(): # temporary until we have a better way to do this... maybe template_type element
|
||||
def get_templates_for_gem_creation():
|
||||
gem_templates = []
|
||||
for template in get_all_templates():
|
||||
if 'Gem' in template:
|
||||
gem_templates.append(template)
|
||||
for template_path in get_all_templates():
|
||||
template_path = pathlib.Path(template_path)
|
||||
template_json_path = pathlib.Path(template_path) / 'template.json'
|
||||
if not validation.valid_o3de_template_json(template_json_path):
|
||||
continue
|
||||
|
||||
gem_json_path = template_path / 'Template' / 'gem.json'
|
||||
if validation.valid_o3de_gem_json(gem_json_path):
|
||||
gem_templates.append(template_path)
|
||||
return gem_templates
|
||||
|
||||
|
||||
def get_generic_templates(): # temporary until we have a better way to do this... maybe template_type element
|
||||
generic_templates = []
|
||||
for template in get_all_templates():
|
||||
if 'Project' not in template and 'Gem' not in template:
|
||||
generic_templates.append(template)
|
||||
return generic_templates
|
||||
def get_templates_for_generic_creation(): # temporary until we have a better way to do this... maybe template_type element
|
||||
def filter_project_and_gem_templates_out(template_path,
|
||||
templates_for_project_creation = get_templates_for_project_creation(),
|
||||
templates_for_gem_creation = get_templates_for_gem_creation()):
|
||||
template_path = pathlib.Path(template_path)
|
||||
return template_path not in templates_for_project_creation and template_path not in templates_for_gem_creation
|
||||
|
||||
return list(filter(filter_project_and_gem_templates_out, get_all_templates()))
|
||||
|
||||
|
||||
def get_all_restricted() -> list:
|
||||
@@ -523,7 +554,7 @@ def get_template_json_data(template_name: str = None,
|
||||
return None
|
||||
|
||||
|
||||
def get_restricted_data(restricted_name: str = None,
|
||||
def get_restricted_json_data(restricted_name: str = None,
|
||||
restricted_path: str or pathlib.Path = None) -> dict or None:
|
||||
if not restricted_name and not restricted_path:
|
||||
logger.error('Must specify either a Restricted name or Restricted Path.')
|
||||
|
||||
@@ -13,6 +13,7 @@ import argparse
|
||||
import json
|
||||
import hashlib
|
||||
import logging
|
||||
import pathlib
|
||||
import sys
|
||||
import urllib.parse
|
||||
|
||||
@@ -21,219 +22,251 @@ from o3de import manifest, validation
|
||||
logger = logging.getLogger()
|
||||
logging.basicConfig()
|
||||
|
||||
def print_this_engine(verbose: int) -> None:
|
||||
|
||||
def get_project_path(project_path: pathlib.Path, project_name: str) -> pathlib.Path:
|
||||
if not project_name and not project_path:
|
||||
logger.error(f'Must either specify a Project path or Project Name.')
|
||||
return None
|
||||
|
||||
if not project_path:
|
||||
project_path = manifest.get_registered(project_name=project_name)
|
||||
if not project_path:
|
||||
logger.error(f'Unable to locate project path from the registered manifest json files:'
|
||||
f' {str(pathlib.Path("~/.o3de/o3de_manifest.json").expanduser())}, engine.json')
|
||||
return None
|
||||
|
||||
if not project_path.is_dir():
|
||||
logger.error(f'Project path {project_path} is not a folder.')
|
||||
return None
|
||||
|
||||
return project_path
|
||||
|
||||
|
||||
def print_this_engine(verbose: int) -> int:
|
||||
engine_data = manifest.get_this_engine()
|
||||
print(json.dumps(engine_data, indent=4))
|
||||
result = True
|
||||
if verbose > 0:
|
||||
print_engines_data(engine_data)
|
||||
result = print_manifest_json_data(engine_data, 'engine.json', 'This Engine',
|
||||
manifest.get_engine_json_data, 'engine_path')
|
||||
return 0 if result else 1
|
||||
|
||||
|
||||
def print_engines(verbose: int) -> None:
|
||||
engines_data = manifest.get_engines()
|
||||
print(json.dumps(engines_data, indent=4))
|
||||
|
||||
if verbose > 0:
|
||||
print_engines_data(engines_data)
|
||||
return print_manifest_json_data(engines_data, 'engine.json', 'Engines',
|
||||
manifest.get_engine_json_data, 'engine_path')
|
||||
return 0
|
||||
|
||||
|
||||
def print_projects(verbose: int) -> None:
|
||||
def print_projects(verbose: int) -> int:
|
||||
projects_data = manifest.get_projects()
|
||||
print(json.dumps(projects_data, indent=4))
|
||||
|
||||
if verbose > 0:
|
||||
print_projects_data(projects_data)
|
||||
return print_manifest_json_data(projects_data, 'project.json', 'Projects',
|
||||
manifest.get_project_json_data, 'project_path')
|
||||
return 0
|
||||
|
||||
|
||||
def print_gems(verbose: int) -> None:
|
||||
def print_gems(verbose: int) -> int:
|
||||
gems_data = manifest.get_gems()
|
||||
print(json.dumps(gems_data, indent=4))
|
||||
|
||||
if verbose > 0:
|
||||
print_gems_data(gems_data)
|
||||
return print_manifest_json_data(gems_data, 'gem.json', 'Gems',
|
||||
manifest.get_gem_json_data, 'gem_path')
|
||||
return 0
|
||||
|
||||
|
||||
def print_templates(verbose: int) -> None:
|
||||
def print_templates(verbose: int) -> int:
|
||||
templates_data = manifest.get_templates()
|
||||
print(json.dumps(templates_data, indent=4))
|
||||
|
||||
if verbose > 0:
|
||||
print_templates_data(templates_data)
|
||||
return print_manifest_json_data(templates_data, 'template.json', 'Templates',
|
||||
manifest.get_template_json_data, 'template_path')
|
||||
return 0
|
||||
|
||||
|
||||
def print_restricted(verbose: int) -> None:
|
||||
def print_restricted(verbose: int) -> int:
|
||||
restricted_data = manifest.get_restricted()
|
||||
print(json.dumps(restricted_data, indent=4))
|
||||
if verbose > 0:
|
||||
print_restricted_data(restricted_data)
|
||||
|
||||
def print_engine_projects(verbose: int) -> None:
|
||||
if verbose > 0:
|
||||
return print_manifest_json_data(restricted_data, 'restricted.json', 'Restricted',
|
||||
manifest.get_restricted_json_data, 'restricted_path')
|
||||
return 0
|
||||
|
||||
|
||||
# Engine output methods
|
||||
def print_engine_projects(verbose: int) -> int:
|
||||
engine_projects_data = manifest.get_engine_projects()
|
||||
print(json.dumps(engine_projects_data, indent=4))
|
||||
|
||||
if verbose > 0:
|
||||
print_projects_data(engine_projects_data)
|
||||
return print_manifest_json_data(engine_projects_data, 'project.json', 'Projects',
|
||||
manifest.get_project_json_data, 'project_path')
|
||||
return 0
|
||||
|
||||
|
||||
def print_engine_gems(verbose: int) -> None:
|
||||
def print_engine_gems(verbose: int) -> int:
|
||||
engine_gems_data = manifest.get_engine_gems()
|
||||
print(json.dumps(engine_gems_data, indent=4))
|
||||
|
||||
if verbose > 0:
|
||||
print_gems_data(engine_gems_data)
|
||||
return print_manifest_json_data(engine_gems_data, 'gem.json', 'Gems',
|
||||
manifest.get_gem_json_data, 'gem_path')
|
||||
return 0
|
||||
|
||||
|
||||
def print_engine_templates(verbose: int) -> None:
|
||||
def print_engine_templates(verbose: int) -> int:
|
||||
engine_templates_data = manifest.get_engine_templates()
|
||||
print(json.dumps(engine_templates_data, indent=4))
|
||||
|
||||
if verbose > 0:
|
||||
print_templates_data(engine_templates_data)
|
||||
return print_manifest_json_data(engine_templates_data, 'template.json', 'Templates',
|
||||
manifest.get_template_json_data, 'template_path')
|
||||
return 0
|
||||
|
||||
|
||||
def print_engine_restricted(verbose: int) -> None:
|
||||
def print_engine_restricted(verbose: int) -> int:
|
||||
engine_restricted_data = manifest.get_engine_restricted()
|
||||
print(json.dumps(engine_restricted_data, indent=4))
|
||||
|
||||
if verbose > 0:
|
||||
print_restricted_data(engine_restricted_data)
|
||||
return print_manifest_json_data(engine_restricted_data, 'restricted.json', 'Restricted',
|
||||
manifest.get_restricted_json_data, 'restricted_path')
|
||||
return 0
|
||||
|
||||
|
||||
def print_engine_external_subdirectories(verbose: int) -> None:
|
||||
def print_engine_external_subdirectories() -> int:
|
||||
external_subdirs_data = manifest.get_engine_external_subdirectories()
|
||||
print(json.dumps(external_subdirs_data, indent=4))
|
||||
return 0
|
||||
|
||||
|
||||
def print_all_projects(verbose: int) -> None:
|
||||
# Project output methods
|
||||
def print_project_gems(verbose: int, project_path: pathlib.Path, project_name: str) -> int:
|
||||
project_path = get_project_path(project_path, project_name)
|
||||
if not project_path:
|
||||
return 1
|
||||
|
||||
project_gems_data = manifest.get_project_gems(project_path)
|
||||
print(json.dumps(project_gems_data, indent=4))
|
||||
|
||||
if verbose > 0:
|
||||
return print_manifest_json_data(project_gems_data, 'gem.json', 'Gems',
|
||||
manifest.get_gem_json_data, 'gem_path')
|
||||
return 0
|
||||
|
||||
|
||||
def print_project_external_subdirectories(project_path: pathlib.Path, project_name: str) -> int:
|
||||
project_path = get_project_path(project_path, project_name)
|
||||
if not project_path:
|
||||
return 1
|
||||
|
||||
external_subdirs_data = manifest.get_project_external_subdirectories(project_path)
|
||||
print(json.dumps(external_subdirs_data, indent=4))
|
||||
return 0
|
||||
|
||||
|
||||
def print_project_templates(verbose: int, project_path: pathlib.Path, project_name: str) -> int:
|
||||
project_path = get_project_path(project_path, project_name)
|
||||
if not project_path:
|
||||
return 1
|
||||
|
||||
project_templates_data = manifest.get_project_templates(project_path)
|
||||
print(json.dumps(project_templates_data, indent=4))
|
||||
if verbose > 0:
|
||||
return print_manifest_json_data(project_templates_data, 'template.json', 'Templates',
|
||||
manifest.get_template_json_data, 'template_path')
|
||||
return 0
|
||||
|
||||
|
||||
def print_project_restricted(verbose: int, project_path: pathlib.Path, project_name: str) -> int:
|
||||
project_path = get_project_path(project_path, project_name)
|
||||
if not project_path:
|
||||
return 1
|
||||
|
||||
project_restricted_data = manifest.get_project_restricted(project_path)
|
||||
print(json.dumps(project_restricted_data, indent=4))
|
||||
if verbose > 0:
|
||||
return print_manifest_json_data(project_restricted_data, 'restricted.json', 'Restricted',
|
||||
manifest.get_restricted_json_data, 'restricted_path')
|
||||
return 0
|
||||
|
||||
|
||||
def print_all_projects(verbose: int) -> int:
|
||||
all_projects_data = manifest.get_all_projects()
|
||||
print(json.dumps(all_projects_data, indent=4))
|
||||
|
||||
if verbose > 0:
|
||||
print_projects_data(all_projects_data)
|
||||
return print_manifest_json_data(all_projects_data, 'project.json', 'Projects',
|
||||
manifest.get_project_json_data, 'project_path')
|
||||
return 0
|
||||
|
||||
|
||||
def print_all_gems(verbose: int) -> None:
|
||||
def print_all_gems(verbose: int) -> int:
|
||||
all_gems_data = manifest.get_all_gems()
|
||||
print(json.dumps(all_gems_data, indent=4))
|
||||
|
||||
if verbose > 0:
|
||||
print_gems_data(all_gems_data)
|
||||
return print_manifest_json_data(all_gems_data, 'gem.json', 'Gems',
|
||||
manifest.get_gem_json_data, 'gem_path')
|
||||
return 0
|
||||
|
||||
|
||||
def print_all_templates(verbose: int) -> None:
|
||||
def print_all_external_subdirectories() -> int:
|
||||
all_external_subdirectories_data = manifest.get_all_external_subdirectories()
|
||||
print(json.dumps(all_external_subdirectories_data, indent=4))
|
||||
return 0
|
||||
|
||||
def print_all_templates(verbose: int) -> int:
|
||||
all_templates_data = manifest.get_all_templates()
|
||||
print(json.dumps(all_templates_data, indent=4))
|
||||
|
||||
if verbose > 0:
|
||||
print_templates_data(all_templates_data)
|
||||
return print_manifest_json_data(all_templates_data, 'template.json', 'Templates',
|
||||
manifest.get_template_json_data, 'template_path')
|
||||
return 0
|
||||
|
||||
|
||||
def print_all_restricted(verbose: int) -> None:
|
||||
def print_all_restricted(verbose: int) -> int:
|
||||
all_restricted_data = manifest.get_all_restricted()
|
||||
print(json.dumps(all_restricted_data, indent=4))
|
||||
|
||||
if verbose > 0:
|
||||
print_restricted_data(all_restricted_data)
|
||||
return print_manifest_json_data(all_restricted_data, 'restricted.json', 'Restricted',
|
||||
manifest.get_restricted_json_data, 'restricted_path')
|
||||
return 0
|
||||
|
||||
|
||||
def print_engines_data(engines_data: dict) -> None:
|
||||
def print_manifest_json_data(uri_json_data: dict, json_filename: str,
|
||||
print_prefix: str, get_json_func: callable, get_json_data_kw: str) -> int:
|
||||
print('\n')
|
||||
print("Engines================================================")
|
||||
for engine_object in engines_data:
|
||||
print(f"{print_prefix}================================================")
|
||||
for manifest_uri in uri_json_data:
|
||||
# if it's not local it should be in the cache
|
||||
engine_uri = engine_object['path']
|
||||
parsed_uri = urllib.parse.urlparse(engine_uri)
|
||||
if parsed_uri.scheme == 'http' or \
|
||||
parsed_uri.scheme == 'https' or \
|
||||
parsed_uri.scheme == 'ftp' or \
|
||||
parsed_uri.scheme == 'ftps':
|
||||
repo_sha256 = hashlib.sha256(engine_uri.encode())
|
||||
parsed_uri = urllib.parse.urlparse(manifest_uri)
|
||||
if parsed_uri.scheme in ['http', 'https', 'ftp', 'ftps']:
|
||||
repo_sha256 = hashlib.sha256(manifest_uri.encode())
|
||||
cache_folder = manifest.get_o3de_cache_folder()
|
||||
engine = cache_folder / str(repo_sha256.hexdigest() + '.json')
|
||||
print(f'{engine_uri}/engine.json cached as:')
|
||||
manifest_json_path = cache_folder / str(repo_sha256.hexdigest() + '.json')
|
||||
else:
|
||||
engine_json = pathlib.Path(engine_uri).resolve() / 'engine.json'
|
||||
manifest_json_path = pathlib.Path(manifest_uri).resolve() / json_filename
|
||||
|
||||
with engine_json.open('r') as f:
|
||||
try:
|
||||
engine_json_data = json.load(f)
|
||||
except json.JSONDecodeError as e:
|
||||
logger.warn(f'{engine_json} failed to load: {str(e)}')
|
||||
else:
|
||||
print(engine_json)
|
||||
print(json.dumps(engine_json_data, indent=4))
|
||||
print('\n')
|
||||
json_data = get_json_func(**{get_json_data_kwargs: manifest_json_path})
|
||||
if json_data:
|
||||
print(manifest_json_path)
|
||||
print(json.dumps(json_data, indent=4) + '\n')
|
||||
return 0
|
||||
|
||||
|
||||
def print_projects_data(projects_data: dict) -> None:
|
||||
print('\n')
|
||||
print("Projects================================================")
|
||||
for project_uri in projects_data:
|
||||
# if it's not local it should be in the cache
|
||||
parsed_uri = urllib.parse.urlparse(project_uri)
|
||||
if parsed_uri.scheme == 'http' or \
|
||||
parsed_uri.scheme == 'https' or \
|
||||
parsed_uri.scheme == 'ftp' or \
|
||||
parsed_uri.scheme == 'ftps':
|
||||
repo_sha256 = hashlib.sha256(project_uri.encode())
|
||||
cache_folder = manifest.get_o3de_cache_folder()
|
||||
project_json = cache_folder / str(repo_sha256.hexdigest() + '.json')
|
||||
else:
|
||||
project_json = pathlib.Path(project_uri).resolve() / 'project.json'
|
||||
|
||||
with project_json.open('r') as f:
|
||||
try:
|
||||
project_json_data = json.load(f)
|
||||
except json.JSONDecodeError as e:
|
||||
logger.warn(f'{project_json} failed to load: {str(e)}')
|
||||
else:
|
||||
print(project_json)
|
||||
print(json.dumps(project_json_data, indent=4))
|
||||
print('\n')
|
||||
|
||||
|
||||
def print_gems_data(gems_data: dict) -> None:
|
||||
print('\n')
|
||||
print("Gems================================================")
|
||||
for gem_uri in gems_data:
|
||||
# if it's not local it should be in the cache
|
||||
parsed_uri = urllib.parse.urlparse(gem_uri)
|
||||
if parsed_uri.scheme == 'http' or \
|
||||
parsed_uri.scheme == 'https' or \
|
||||
parsed_uri.scheme == 'ftp' or \
|
||||
parsed_uri.scheme == 'ftps':
|
||||
repo_sha256 = hashlib.sha256(gem_uri.encode())
|
||||
cache_folder = manifest.get_o3de_cache_folder()
|
||||
gem_json = cache_folder / str(repo_sha256.hexdigest() + '.json')
|
||||
else:
|
||||
gem_json = pathlib.Path(gem_uri).resolve() / 'gem.json'
|
||||
|
||||
with gem_json.open('r') as f:
|
||||
try:
|
||||
gem_json_data = json.load(f)
|
||||
except json.JSONDecodeError as e:
|
||||
logger.warn(f'{gem_json} failed to load: {str(e)}')
|
||||
else:
|
||||
print(gem_json)
|
||||
print(json.dumps(gem_json_data, indent=4))
|
||||
print('\n')
|
||||
|
||||
|
||||
def print_templates_data(templates_data: dict) -> None:
|
||||
print('\n')
|
||||
print("Templates================================================")
|
||||
for template_uri in templates_data:
|
||||
# if it's not local it should be in the cache
|
||||
parsed_uri = urllib.parse.urlparse(template_uri)
|
||||
if parsed_uri.scheme == 'http' or \
|
||||
parsed_uri.scheme == 'https' or \
|
||||
parsed_uri.scheme == 'ftp' or \
|
||||
parsed_uri.scheme == 'ftps':
|
||||
repo_sha256 = hashlib.sha256(template_uri.encode())
|
||||
cache_folder = manifest.get_o3de_cache_folder()
|
||||
template_json = cache_folder / str(repo_sha256.hexdigest() + '.json')
|
||||
else:
|
||||
template_json = pathlib.Path(template_uri).resolve() / 'template.json'
|
||||
|
||||
with template_json.open('r') as f:
|
||||
try:
|
||||
template_json_data = json.load(f)
|
||||
except json.JSONDecodeError as e:
|
||||
logger.warn(f'{template_json} failed to load: {str(e)}')
|
||||
else:
|
||||
print(template_json)
|
||||
print(json.dumps(template_json_data, indent=4))
|
||||
print('\n')
|
||||
|
||||
|
||||
def print_repos_data(repos_data: dict) -> None:
|
||||
def print_repos_data(repos_data: dict) -> int:
|
||||
print('\n')
|
||||
print("Repos================================================")
|
||||
cache_folder = manifest.get_o3de_cache_folder()
|
||||
@@ -251,29 +284,16 @@ def print_repos_data(repos_data: dict) -> None:
|
||||
print(cache_file)
|
||||
print(json.dumps(repo_json_data, indent=4))
|
||||
print('\n')
|
||||
|
||||
|
||||
def print_restricted_data(restricted_data: dict) -> None:
|
||||
print('\n')
|
||||
print("Restricted================================================")
|
||||
for restricted_path in restricted_data:
|
||||
restricted_json = pathlib.Path(restricted_path).resolve() / 'restricted.json'
|
||||
with restricted_json.open('r') as f:
|
||||
try:
|
||||
restricted_json_data = json.load(f)
|
||||
except json.JSONDecodeError as e:
|
||||
logger.warn(f'{restricted_json} failed to load: {str(e)}')
|
||||
else:
|
||||
print(restricted_json)
|
||||
print(json.dumps(restricted_json_data, indent=4))
|
||||
print('\n')
|
||||
return 0
|
||||
|
||||
|
||||
def register_show_repos(verbose: int) -> None:
|
||||
repos_data = get_repos()
|
||||
repos_data = manifest.get_repos()
|
||||
print(json.dumps(repos_data, indent=4))
|
||||
|
||||
if verbose > 0:
|
||||
print_repos_data(repos_data)
|
||||
return print_repos_data(repos_data) == 0
|
||||
return 0
|
||||
|
||||
|
||||
def register_show(verbose: int) -> None:
|
||||
@@ -281,13 +301,15 @@ def register_show(verbose: int) -> None:
|
||||
print(f"{manifest.get_o3de_manifest()}:")
|
||||
print(json.dumps(json_data, indent=4))
|
||||
|
||||
result = True
|
||||
if verbose > 0:
|
||||
print_engines_data(manifest.get_engines())
|
||||
print_projects_data(manifest.get_all_projects())
|
||||
print_gems_data(manifest.get_gems())
|
||||
print_templates_data(manifest.get_all_templates())
|
||||
print_restricted_data(manifest.get_all_restricted())
|
||||
print_repos_data(manifest.get_repos())
|
||||
result = print_manifest_json_data(manifest.get_engines()) == 0 and result
|
||||
result = print_manifest_json_data(manifest.get_all_projects()) == 0 and result
|
||||
result = print_manifest_json_data(manifest.get_gems()) == 0 and result
|
||||
result = print_manifest_json_data(manifest.get_all_templates()) == 0 and result
|
||||
result = print_manifest_json_data(manifest.get_all_restricted()) == 0 and result
|
||||
result = print_repos_data(manifest.get_repos()) == 0 and result
|
||||
return 0 if result else 1
|
||||
|
||||
|
||||
def _run_register_show(args: argparse) -> int:
|
||||
@@ -295,75 +317,53 @@ def _run_register_show(args: argparse) -> int:
|
||||
manifest.override_home_folder = args.override_home_folder
|
||||
|
||||
if args.this_engine:
|
||||
print_this_engine(args.verbose)
|
||||
return 0
|
||||
|
||||
return print_this_engine(args.verbose)
|
||||
elif args.engines:
|
||||
print_engines(args.verbose)
|
||||
return 0
|
||||
return print_engines(args.verbose)
|
||||
elif args.projects:
|
||||
print_projects(args.verbose)
|
||||
return 0
|
||||
return print_projects(args.verbose)
|
||||
elif args.gems:
|
||||
print_gems(args.verbose)
|
||||
return 0
|
||||
return print_gems(args.verbose)
|
||||
elif args.templates:
|
||||
print_templates(args.verbose)
|
||||
return 0
|
||||
return print_templates(args.verbose)
|
||||
elif args.repos:
|
||||
register_show_repos(args.verbose)
|
||||
return 0
|
||||
return register_show_repos(args.verbose)
|
||||
elif args.restricted:
|
||||
print_restricted(args.verbose)
|
||||
return 0
|
||||
return print_restricted(args.verbose)
|
||||
|
||||
elif args.engine_projects:
|
||||
print_engine_projects(args.verbose)
|
||||
return 0
|
||||
return print_engine_projects(args.verbose)
|
||||
elif args.engine_gems:
|
||||
print_engine_gems(args.verbose)
|
||||
return 0
|
||||
elif args.engine_templates:
|
||||
print_engine_templates(args.verbose)
|
||||
return 0
|
||||
elif args.engine_restricted:
|
||||
print_engine_restricted(args.verbose)
|
||||
return 0
|
||||
return print_engine_gems(args.verbose)
|
||||
elif args.engine_external_subdirectories:
|
||||
print_engine_external_subdirectories(args.verbose)
|
||||
return 0
|
||||
return print_engine_external_subdirectories()
|
||||
elif args.engine_templates:
|
||||
return print_engine_templates(args.verbose)
|
||||
elif args.engine_restricted:
|
||||
return print_engine_restricted(args.verbose)
|
||||
|
||||
elif args.project_gems:
|
||||
return print_project_gems(args.verbose, args.project_path, args.project_name)
|
||||
elif args.project_external_subdirectories:
|
||||
return print_project_external_subdirectories(args.project_path, args.project_name)
|
||||
elif args.project_templates:
|
||||
return print_project_templates(args.verbose, args.project_path, args.project_name)
|
||||
elif args.project_restricted:
|
||||
return print_project_restricted(args.verbose, args.project_path, args.project_name)
|
||||
|
||||
elif args.all_projects:
|
||||
print_all_projects(args.verbose)
|
||||
return 0
|
||||
return print_all_projects(args.verbose)
|
||||
elif args.all_gems:
|
||||
print_all_gems(args.verbose)
|
||||
return 0
|
||||
return print_all_gems(args.verbose)
|
||||
elif args.all_external_subdirectories:
|
||||
return print_all_external_subdirectories()
|
||||
elif args.all_templates:
|
||||
print_all_templates(args.verbose)
|
||||
return 0
|
||||
return print_all_templates(args.verbose)
|
||||
elif args.all_restricted:
|
||||
print_all_restricted(args.verbose)
|
||||
return 0
|
||||
return print_all_restricted(args.verbose)
|
||||
|
||||
elif args.downloadables:
|
||||
print_downloadables(args.verbose)
|
||||
return 0
|
||||
if args.downloadable_engines:
|
||||
print_downloadable_engines(args.verbose)
|
||||
return 0
|
||||
elif args.downloadable_projects:
|
||||
print_downloadable_projects(args.verbose)
|
||||
return 0
|
||||
elif args.downloadable_gems:
|
||||
print_downloadable_gems(args.verbose)
|
||||
return 0
|
||||
elif args.downloadable_templates:
|
||||
print_downloadable_templates(args.verbose)
|
||||
return 0
|
||||
else:
|
||||
register_show(args.verbose)
|
||||
return 0
|
||||
return register_show(args.verbose)
|
||||
|
||||
|
||||
def add_parser_args(parser):
|
||||
@@ -376,78 +376,84 @@ def add_parser_args(parser):
|
||||
group = parser.add_mutually_exclusive_group(required=False)
|
||||
group.add_argument('-te', '--this-engine', action='store_true', required=False,
|
||||
default=False,
|
||||
help='Just the local engines.')
|
||||
help='Output the current engine path.')
|
||||
|
||||
group.add_argument('-e', '--engines', action='store_true', required=False,
|
||||
default=False,
|
||||
help='Just the local engines.')
|
||||
help='Output the engines registered in the global ~/.o3de/o3de_manifest.json.')
|
||||
group.add_argument('-p', '--projects', action='store_true', required=False,
|
||||
default=False,
|
||||
help='Just the local projects.')
|
||||
help='Output the projects registered in the global ~/.o3de/o3de_manifest.json.')
|
||||
group.add_argument('-g', '--gems', action='store_true', required=False,
|
||||
default=False,
|
||||
help='Just the local gems.')
|
||||
help='Output the gems registered in the global ~/.o3de/o3de_manifest.json.')
|
||||
group.add_argument('-t', '--templates', action='store_true', required=False,
|
||||
default=False,
|
||||
help='Just the local templates.')
|
||||
help='Output the templates registered in the global ~/.o3de/o3de_manifest.json.')
|
||||
group.add_argument('-r', '--repos', action='store_true', required=False,
|
||||
default=False,
|
||||
help='Just the local repos. Ignores repos.')
|
||||
help='Output the repos registered in the global ~/.o3de/o3de_manifest.json. Ignores repos.')
|
||||
group.add_argument('-rs', '--restricted', action='store_true', required=False,
|
||||
default=False,
|
||||
help='The local restricted folders.')
|
||||
help='Output the restricted directories registered in the global ~/.o3de/o3de_manifest.json.')
|
||||
|
||||
group.add_argument('-ep', '--engine-projects', action='store_true', required=False,
|
||||
default=False,
|
||||
help='Just the local projects. Ignores repos.')
|
||||
help='Output the projects registered in the current engine engine.json. Ignores repos.')
|
||||
group.add_argument('-eg', '--engine-gems', action='store_true', required=False,
|
||||
default=False,
|
||||
help='Just the local gems. Ignores repos')
|
||||
help='Output the gems registered in the current engine engine.json. Ignores repos')
|
||||
group.add_argument('-et', '--engine-templates', action='store_true', required=False,
|
||||
default=False,
|
||||
help='Just the local templates. Ignores repos.')
|
||||
help='Output the templates registered in the current engine engine.json. Ignores repos.')
|
||||
group.add_argument('-ers', '--engine-restricted', action='store_true', required=False,
|
||||
default=False,
|
||||
help='The restricted folders.')
|
||||
group.add_argument('-x', '--engine-external-subdirectories', action='store_true', required=False,
|
||||
help='Output the restricted directories registered in the current engine engine.json.')
|
||||
group.add_argument('-ees', '--engine-external-subdirectories', action='store_true', required=False,
|
||||
default=False,
|
||||
help='The external subdirectories.')
|
||||
help='Output the external subdirectories registered in the current engine engine.json.')
|
||||
|
||||
group.add_argument('-pg', '--project-gems', action='store_true',
|
||||
default=False,
|
||||
help='Returns the gems registered with the project.json.')
|
||||
group.add_argument('-pt', '--project-templates', action='store_true',
|
||||
default=False,
|
||||
help='Returns the templates registered with the project.json.')
|
||||
group.add_argument('-prs', '--project-restricted', action='store_true',
|
||||
default=False,
|
||||
help='Returns the restricted directories registered with the project.json.')
|
||||
group.add_argument('-pes', '--project-external-subdirectories', action='store_true',
|
||||
default=False,
|
||||
help='Returns the external subdirectories register with the project.json.')
|
||||
|
||||
group.add_argument('-ap', '--all-projects', action='store_true', required=False,
|
||||
default=False,
|
||||
help='Just the local projects. Ignores repos.')
|
||||
help='Output all projects registered in the ~/.o3de/o3de_manifest.json and the current engine.json. Ignores repos.')
|
||||
group.add_argument('-ag', '--all-gems', action='store_true', required=False,
|
||||
default=False,
|
||||
help='Just the local gems. Ignores repos')
|
||||
help='Output all gems registered in the ~/.o3de/o3de_manifest.json and the current engine.json. Ignores repos')
|
||||
group.add_argument('-at', '--all-templates', action='store_true', required=False,
|
||||
default=False,
|
||||
help='Just the local templates. Ignores repos.')
|
||||
group.add_argument('-ars', '--all-restricted', action='store_true', required=False,
|
||||
help='Output all templates registered in the ~/.o3de/o3de_manifest.json and the current engine.json. Ignores repos.')
|
||||
group.add_argument('-ares', '--all-restricted', action='store_true', required=False,
|
||||
default=False,
|
||||
help='The restricted folders.')
|
||||
|
||||
group.add_argument('-d', '--downloadables', action='store_true', required=False,
|
||||
help='Output all restricted directory registered in the ~/.o3de/o3de_manifest.json and the current engine.json.')
|
||||
group.add_argument('-aes', '--all-external-subdirectories', action='store_true',
|
||||
default=False,
|
||||
help='Combine all repos into a single list of resources.')
|
||||
group.add_argument('-de', '--downloadable-engines', action='store_true', required=False,
|
||||
default=False,
|
||||
help='Combine all repos engines into a single list of resources.')
|
||||
group.add_argument('-dp', '--downloadable-projects', action='store_true', required=False,
|
||||
default=False,
|
||||
help='Combine all repos projects into a single list of resources.')
|
||||
group.add_argument('-dg', '--downloadable-gems', action='store_true', required=False,
|
||||
default=False,
|
||||
help='Combine all repos gems into a single list of resources.')
|
||||
group.add_argument('-dt', '--downloadable-templates', action='store_true', required=False,
|
||||
default=False,
|
||||
help='Combine all repos templates into a single list of resources.')
|
||||
help='Output all external subdirectories registered in the ~/.o3de/o3de_manifest.json and the current engine.json.')
|
||||
|
||||
parser.add_argument('-v', '--verbose', action='count', required=False,
|
||||
default=0,
|
||||
help='How verbose do you want the output to be.')
|
||||
default=0,
|
||||
help='How verbose do you want the output to be.')
|
||||
|
||||
project_group = parser.add_mutually_exclusive_group(required=False)
|
||||
project_group.add_argument('-pp', '--project-path', type=pathlib.Path,
|
||||
help='The path to a project.')
|
||||
project_group.add_argument('-pn', '--project-name', type=str,
|
||||
help='The name of a project.')
|
||||
|
||||
parser.add_argument('-ohf', '--override-home-folder', type=str, required=False,
|
||||
help='By default the home folder is the user folder, override it to this folder.')
|
||||
help='By default the home folder is the user folder, override it to this folder.')
|
||||
|
||||
parser.set_defaults(func=_run_register_show)
|
||||
|
||||
|
||||
@@ -34,3 +34,10 @@ ly_add_pytest(
|
||||
TEST_SUITE smoke
|
||||
EXCLUDE_TEST_RUN_TARGET_FROM_IDE
|
||||
)
|
||||
|
||||
ly_add_pytest(
|
||||
NAME o3de_manifest
|
||||
PATH ${CMAKE_CURRENT_LIST_DIR}/unit_test_manifest.py
|
||||
TEST_SUITE smoke
|
||||
EXCLUDE_TEST_RUN_TARGET_FROM_IDE
|
||||
)
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
#
|
||||
# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
# its licensors.
|
||||
#
|
||||
# For complete copyright and license terms please see the LICENSE at the root of this
|
||||
# distribution (the "License"). All use of this software is governed by the License,
|
||||
# or, if provided, by the license below or the license accompanying this file. Do not
|
||||
# remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
#
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import logging
|
||||
import pytest
|
||||
import pathlib
|
||||
from unittest.mock import patch
|
||||
|
||||
from o3de import manifest
|
||||
|
||||
|
||||
@pytest.mark.parametrize("valid_project_json_paths, valid_gem_json_paths", [
|
||||
pytest.param([pathlib.Path('D:/o3de/Templates/DefaultProject/Template/project.json')],
|
||||
[pathlib.Path('D:/o3de/Templates/DefaultGem/Template/gem.json')])
|
||||
])
|
||||
class TestGetTemplatesForCreation:
|
||||
@staticmethod
|
||||
def get_templates() -> list:
|
||||
return []
|
||||
|
||||
@staticmethod
|
||||
def get_project_templates() -> list:
|
||||
return []
|
||||
|
||||
@staticmethod
|
||||
def get_engine_templates() -> list:
|
||||
return [pathlib.Path('D:/o3de/Templates/DefaultProject'), pathlib.Path('D:/o3de/Templates/DefaultGem')]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("expected_template_paths", [
|
||||
pytest.param([])
|
||||
]
|
||||
)
|
||||
def test_get_templates_for_generic_creation(self, valid_project_json_paths, valid_gem_json_paths,
|
||||
expected_template_paths):
|
||||
def validate_project_json(template_path) -> bool:
|
||||
return pathlib.Path(template_path) in valid_project_json_paths
|
||||
|
||||
def validate_gem_json(template_path) -> bool:
|
||||
return pathlib.Path(template_path) in valid_gem_json_paths
|
||||
|
||||
with patch('o3de.manifest.get_templates', side_effect=self.get_templates) as get_templates_patch, \
|
||||
patch('o3de.manifest.get_project_templates', side_effect=self.get_project_templates)\
|
||||
as get_project_templates_patch, \
|
||||
patch('o3de.manifest.get_engine_templates', side_effect=self.get_engine_templates)\
|
||||
as get_engine_templates_patch, \
|
||||
patch('o3de.validation.valid_o3de_template_json', return_value=True) as validate_template_json,\
|
||||
patch('o3de.validation.valid_o3de_project_json', side_effect=validate_project_json) as validate_project_json,\
|
||||
patch('o3de.validation.valid_o3de_gem_json', side_effect=validate_gem_json) as validate_gem_json:
|
||||
templates = manifest.get_templates_for_generic_creation()
|
||||
assert templates == expected_template_paths
|
||||
|
||||
|
||||
@pytest.mark.parametrize("expected_template_paths", [
|
||||
pytest.param([pathlib.Path('D:/o3de/Templates/DefaultProject')])
|
||||
]
|
||||
)
|
||||
def test_get_templates_for_gem_creation(self, valid_project_json_paths, valid_gem_json_paths,
|
||||
expected_template_paths):
|
||||
def validate_project_json(template_path) -> bool:
|
||||
return pathlib.Path(template_path) in valid_project_json_paths
|
||||
|
||||
def validate_gem_json(template_path) -> bool:
|
||||
return pathlib.Path(template_path) in valid_gem_json_paths
|
||||
|
||||
with patch('o3de.manifest.get_templates', side_effect=self.get_templates) as get_templates_patch, \
|
||||
patch('o3de.manifest.get_project_templates', side_effect=self.get_project_templates) \
|
||||
as get_project_templates_patch, \
|
||||
patch('o3de.manifest.get_engine_templates', side_effect=self.get_engine_templates) \
|
||||
as get_engine_templates_patch, \
|
||||
patch('o3de.validation.valid_o3de_template_json', return_value=True) as validate_template_json, \
|
||||
patch('o3de.validation.valid_o3de_project_json',
|
||||
side_effect=validate_project_json) as validate_project_json, \
|
||||
patch('o3de.validation.valid_o3de_gem_json', side_effect=validate_gem_json) as validate_gem_json:
|
||||
templates = manifest.get_templates_for_project_creation()
|
||||
assert templates == expected_template_paths
|
||||
|
||||
|
||||
@pytest.mark.parametrize("expected_template_paths", [
|
||||
pytest.param([pathlib.Path('D:/o3de/Templates/DefaultGem')])
|
||||
]
|
||||
)
|
||||
def test_get_templates_for_project_creation(self, valid_project_json_paths, valid_gem_json_paths,
|
||||
expected_template_paths):
|
||||
def validate_project_json(template_path) -> bool:
|
||||
return pathlib.Path(template_path) in valid_project_json_paths
|
||||
|
||||
def validate_gem_json(template_path) -> bool:
|
||||
return pathlib.Path(template_path) in valid_gem_json_paths
|
||||
|
||||
with patch('o3de.manifest.get_templates', side_effect=self.get_templates) as get_templates_patch, \
|
||||
patch('o3de.manifest.get_project_templates', side_effect=self.get_project_templates) \
|
||||
as get_project_templates_patch, \
|
||||
patch('o3de.manifest.get_engine_templates', side_effect=self.get_engine_templates) \
|
||||
as get_engine_templates_patch, \
|
||||
patch('o3de.validation.valid_o3de_template_json', return_value=True) as validate_template_json, \
|
||||
patch('o3de.validation.valid_o3de_project_json',
|
||||
side_effect=validate_project_json) as validate_project_json, \
|
||||
patch('o3de.validation.valid_o3de_gem_json', side_effect=validate_gem_json) as validate_gem_json:
|
||||
templates = manifest.get_templates_for_gem_creation()
|
||||
assert templates == expected_template_paths
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
import pytest
|
||||
|
||||
from . import utils
|
||||
from o3de import utils
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"value, expected_result", [
|
||||
|
||||
Reference in New Issue
Block a user