Merge branch 'main' into LYN-3077
This commit is contained in:
@@ -394,11 +394,13 @@ namespace ScriptCanvasBuilder
|
||||
|
||||
int GetBuilderVersion()
|
||||
{
|
||||
// #functions2 remove-execution-out-hash include version from all library nodes, split fingerprint generation to relax Is Out of Data restriction when graphs only need a recompile
|
||||
return static_cast<int>(BuilderVersion::Current)
|
||||
+ static_cast<int>(ScriptCanvas::GrammarVersion::Current)
|
||||
+ static_cast<int>(ScriptCanvas::RuntimeVersion::Current)
|
||||
;
|
||||
}
|
||||
|
||||
AZ::Outcome < AZ::Data::Asset<ScriptCanvasEditor::ScriptCanvasAsset>, AZStd::string> LoadEditorAsset(AZStd::string_view filePath)
|
||||
{
|
||||
AZStd::shared_ptr<AZ::Data::AssetDataStream> assetDataStream = AZStd::make_shared<AZ::Data::AssetDataStream>();
|
||||
|
||||
@@ -2347,7 +2347,7 @@ namespace ScriptCanvasEditor
|
||||
AZ::Outcome<ScriptCanvas::VariableId, AZStd::string> addOutcome;
|
||||
|
||||
// #functions2 slot<->variable re-use the activeDatum, send the pointer (actually, all of the source slot information, and make a special conversion)
|
||||
ScriptCanvas::GraphVariableManagerRequestBus::EventResult(addOutcome, GetScriptCanvasId(), &ScriptCanvas::GraphVariableManagerRequests::AddVariable, variableName, variableDatum);
|
||||
ScriptCanvas::GraphVariableManagerRequestBus::EventResult(addOutcome, GetScriptCanvasId(), &ScriptCanvas::GraphVariableManagerRequests::AddVariable, variableName, variableDatum, true);
|
||||
|
||||
if (addOutcome.IsSuccess())
|
||||
{
|
||||
|
||||
@@ -172,7 +172,7 @@ namespace ScriptCanvasEditor
|
||||
{
|
||||
ScriptCanvas::Datum datum = ScriptCanvas::Datum(entityId);
|
||||
|
||||
AZ::Outcome<ScriptCanvas::VariableId, AZStd::string > addVariableOutcome = variableManagerRequests->AddVariable(variableName, datum);
|
||||
AZ::Outcome<ScriptCanvas::VariableId, AZStd::string > addVariableOutcome = variableManagerRequests->AddVariable(variableName, datum, false);
|
||||
|
||||
if (addVariableOutcome.IsSuccess())
|
||||
{
|
||||
|
||||
@@ -79,15 +79,19 @@ namespace
|
||||
|
||||
|
||||
// Create the nodes in a horizontal list at the top of the canvas.
|
||||
AZ::Vector2 pos(20.0f, -100.0f);
|
||||
AZ::Vector2 pos(20.0f, 20.0f);
|
||||
for (const auto& index : ui->commandList->selectionModel()->selectedIndexes())
|
||||
{
|
||||
if (index.column() != CommandListDataModel::ColumnIndex::Command)
|
||||
if (index.column() != CommandListDataModel::ColumnIndex::CommandIndex)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
AZ::Uuid type = dataModel->data(index, CommandListDataModel::CustomRole::Types).value<AZ::Uuid>();
|
||||
if (type.IsNull())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
[[maybe_unused]] const AZ::SerializeContext::ClassData* classData = serializeContext->FindClassData(type);
|
||||
AZ_Assert(classData, "Failed to find ClassData for ID: %s", type.ToString<AZStd::string>().data());
|
||||
@@ -115,6 +119,8 @@ namespace ScriptCanvasEditor
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
CommandListDataModel::CommandListDataModel([[maybe_unused]] QWidget* parent /*= nullptr*/)
|
||||
{
|
||||
ScriptCanvasCommandLineRequestBus::Handler::BusConnect();
|
||||
|
||||
AZ::SerializeContext* serializeContext = nullptr;
|
||||
AZ::ComponentApplicationBus::BroadcastResult(serializeContext, &AZ::ComponentApplicationRequests::GetSerializeContext);
|
||||
|
||||
@@ -138,12 +144,62 @@ namespace ScriptCanvasEditor
|
||||
|
||||
if (add)
|
||||
{
|
||||
m_nodeTypes.push_back(classData->m_typeId);
|
||||
Entry entry;
|
||||
entry.m_type = classData->m_typeId;
|
||||
m_entries.emplace_back(entry);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
);
|
||||
);
|
||||
|
||||
ScriptCanvasCommandLineRequestBus::Broadcast(&ScriptCanvasCommandLineRequests::AddCommand, "add_node", "Adds the specified node to the graph",
|
||||
[serializeContext](const AZStd::vector<AZStd::string>& nodes)
|
||||
{
|
||||
AZ::Uuid nodeTypeToAdd = AZ::Uuid::CreateNull();
|
||||
if (nodes.size() > 0)
|
||||
{
|
||||
const AZStd::string& nodeName = *(nodes.begin());
|
||||
|
||||
serializeContext->EnumerateDerived<ScriptCanvas::Node>(
|
||||
[&nodeName, &nodeTypeToAdd](const AZ::SerializeContext::ClassData* classData, [[maybe_unused]] const AZ::Uuid& classUuid) -> bool
|
||||
{
|
||||
if (classData && classData->m_editData)
|
||||
{
|
||||
if (nodeName.compare(classData->m_name) == 0)
|
||||
{
|
||||
nodeTypeToAdd = classData->m_typeId;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
);
|
||||
|
||||
if (!nodeTypeToAdd.IsNull())
|
||||
{
|
||||
ScriptCanvas::ScriptCanvasId scriptCanvasId;
|
||||
ScriptCanvasEditor::GeneralRequestBus::BroadcastResult(scriptCanvasId, &ScriptCanvasEditor::GeneralRequests::GetActiveScriptCanvasId);
|
||||
|
||||
AZ::EntityId graphCanvasGraphId;
|
||||
ScriptCanvasEditor::GeneralRequestBus::BroadcastResult(graphCanvasGraphId, &ScriptCanvasEditor::GeneralRequests::GetActiveGraphCanvasGraphId);
|
||||
|
||||
if (scriptCanvasId.IsValid() && graphCanvasGraphId.IsValid())
|
||||
{
|
||||
ScriptCanvasEditor::Nodes::StyleConfiguration styleConfiguration;
|
||||
|
||||
AZ::Vector2 pos(100.0f, 20.0f);
|
||||
NodeIdPair nodePair = ScriptCanvasEditor::Nodes::CreateNode(nodeTypeToAdd, scriptCanvasId, styleConfiguration);
|
||||
GraphCanvas::SceneRequestBus::Event(graphCanvasGraphId, &GraphCanvas::SceneRequests::AddNode, nodePair.m_graphCanvasId, pos, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
CommandListDataModel::~CommandListDataModel()
|
||||
{
|
||||
ScriptCanvasCommandLineRequestBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
QModelIndex CommandListDataModel::index(int row, int column, const QModelIndex& parent /*= QModelIndex()*/) const
|
||||
@@ -162,7 +218,7 @@ namespace ScriptCanvasEditor
|
||||
|
||||
int CommandListDataModel::rowCount([[maybe_unused]] const QModelIndex& parent /*= QModelIndex()*/) const
|
||||
{
|
||||
return static_cast<int>(m_nodeTypes.size());
|
||||
return static_cast<int>(m_entries.size());
|
||||
}
|
||||
|
||||
int CommandListDataModel::columnCount([[maybe_unused]] const QModelIndex& parent /*= QModelIndex()*/) const
|
||||
@@ -190,19 +246,40 @@ namespace ScriptCanvasEditor
|
||||
}
|
||||
}
|
||||
|
||||
AZ::Uuid nodeType = m_nodeTypes[index.row()];
|
||||
const AZ::SerializeContext::ClassData* classData = serializeContext->FindClassData(nodeType);
|
||||
if (index.column() == ColumnIndex::Command)
|
||||
AZ::Uuid nodeType = m_entries[index.row()].m_type;
|
||||
if (nodeType.IsNull())
|
||||
{
|
||||
return QVariant(QString(classData->m_name));
|
||||
if (index.column() == ColumnIndex::CommandIndex)
|
||||
{
|
||||
return QVariant(QString(m_entries[index.row()].m_command.c_str()));
|
||||
}
|
||||
if (index.column() == ColumnIndex::DescriptionIndex)
|
||||
{
|
||||
AZStd::string command = m_entries[index.row()].m_command;
|
||||
const auto& entry = m_commands.find(command);
|
||||
if (entry != m_commands.end())
|
||||
{
|
||||
return QVariant(QString(entry->second->GetDescription().c_str()));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (index.column() == ColumnIndex::Description)
|
||||
else
|
||||
{
|
||||
return QVariant(QString(classData->m_editData ? classData->m_editData->m_description : tr("No description provided.")));
|
||||
}
|
||||
if (index.column() == ColumnIndex::Trail)
|
||||
{
|
||||
return QVariant(QString(""));
|
||||
if (const AZ::SerializeContext::ClassData* classData = serializeContext->FindClassData(nodeType))
|
||||
{
|
||||
if (index.column() == ColumnIndex::CommandIndex)
|
||||
{
|
||||
return QVariant(QString(classData->m_name));
|
||||
}
|
||||
if (index.column() == ColumnIndex::DescriptionIndex)
|
||||
{
|
||||
return QVariant(QString(classData->m_editData ? classData->m_editData->m_description : tr("No description provided.")));
|
||||
}
|
||||
if (index.column() == ColumnIndex::TrailIndex)
|
||||
{
|
||||
return QVariant(QString(""));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -210,25 +287,42 @@ namespace ScriptCanvasEditor
|
||||
{
|
||||
case CustomRole::Types:
|
||||
{
|
||||
AZ::Uuid nodeType = m_nodeTypes[index.row()];
|
||||
AZ::Uuid nodeType = m_entries[index.row()].m_type;
|
||||
return QVariant::fromValue<AZ::Uuid>(nodeType);
|
||||
}
|
||||
break;
|
||||
case CustomRole::Node:
|
||||
{
|
||||
AZ::Uuid nodeType = m_nodeTypes[index.row()];
|
||||
const AZ::SerializeContext::ClassData* classData = serializeContext->FindClassData(nodeType);
|
||||
if (index.column() == ColumnIndex::Command)
|
||||
AZ::Uuid nodeType = m_entries[index.row()].m_type;
|
||||
if (nodeType.IsNull())
|
||||
{
|
||||
return QVariant(QString(classData->m_name));
|
||||
return QVariant(QString(m_entries[index.row()].m_command.c_str()));
|
||||
}
|
||||
if (index.column() == ColumnIndex::Description)
|
||||
else
|
||||
{
|
||||
return QVariant(QString(classData->m_editData ? classData->m_editData->m_description : tr("No description provided.")));
|
||||
if (const AZ::SerializeContext::ClassData* classData = serializeContext->FindClassData(nodeType))
|
||||
{
|
||||
if (index.column() == ColumnIndex::CommandIndex)
|
||||
{
|
||||
return QVariant(QString(classData->m_name));
|
||||
}
|
||||
if (index.column() == ColumnIndex::DescriptionIndex)
|
||||
{
|
||||
return QVariant(QString(classData->m_editData ? classData->m_editData->m_description : tr("No description provided.")));
|
||||
}
|
||||
if (index.column() == ColumnIndex::TrailIndex)
|
||||
{
|
||||
return QVariant(QString(""));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (index.column() == ColumnIndex::Trail)
|
||||
}
|
||||
break;
|
||||
case CustomRole::Commands:
|
||||
{
|
||||
if (index.column() == ColumnIndex::CommandIndex)
|
||||
{
|
||||
return QVariant(QString(""));
|
||||
return QVariant(QString(m_entries[index.row()].m_command.c_str()));
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -250,21 +344,31 @@ namespace ScriptCanvasEditor
|
||||
AZ::SerializeContext* serializeContext = nullptr;
|
||||
AZ::ComponentApplicationBus::BroadcastResult(serializeContext, &AZ::ComponentApplicationRequests::GetSerializeContext);
|
||||
|
||||
for (const auto& entry : m_nodeTypes)
|
||||
for (const auto& entry : m_entries)
|
||||
{
|
||||
const AZ::SerializeContext::ClassData* classData = serializeContext->FindClassData(entry);
|
||||
if (classData)
|
||||
if (!entry.m_type.IsNull())
|
||||
{
|
||||
QString name = QString(classData->m_name);
|
||||
if (name.startsWith(input.c_str(), Qt::CaseSensitivity::CaseInsensitive))
|
||||
if (const AZ::SerializeContext::ClassData* classData = serializeContext->FindClassData(entry.m_type))
|
||||
{
|
||||
return true;
|
||||
QString name = QString(classData->m_name);
|
||||
if (name.startsWith(input.c_str(), Qt::CaseSensitivity::CaseInsensitive))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QString commandName = entry.m_command.c_str();
|
||||
return (commandName.startsWith(input.c_str(), Qt::CaseSensitivity::CaseInsensitive));
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ScriptCanvasEditor::Widget::CommandRegistry CommandListDataModel::m_commands;
|
||||
|
||||
// CommandLineEdit
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -335,8 +439,25 @@ namespace ScriptCanvasEditor
|
||||
case Qt::Key_Return:
|
||||
{
|
||||
// Invoke the command
|
||||
// TODO: trigger invoke
|
||||
// CommandRequestBus::Broadcast(&CommandRequest::Invoke, text().toStdString().c_str());
|
||||
AZStd::string commandText = text().toStdString().c_str();
|
||||
AZStd::vector<AZStd::string> tokens;
|
||||
AZ::StringFunc::Tokenize(commandText, tokens, " ");
|
||||
if (tokens.size() == 1)
|
||||
{
|
||||
ScriptCanvasCommandLineRequestBus::Broadcast(&ScriptCanvasCommandLineRequests::Invoke, tokens.begin()->c_str());
|
||||
}
|
||||
else if (tokens.size() > 1)
|
||||
{
|
||||
AZStd::string command = *(tokens.begin());
|
||||
AZStd::vector<AZStd::string> args;
|
||||
for (auto it = tokens.begin() + 1; it != tokens.end(); ++it)
|
||||
{
|
||||
args.push_back(*it);
|
||||
}
|
||||
ScriptCanvasCommandLineRequestBus::Broadcast(&ScriptCanvasCommandLineRequests::InvokeWithArguments, command.c_str(), args);
|
||||
}
|
||||
|
||||
|
||||
ResetState();
|
||||
qobject_cast<QWidget*>(parent())->hide();
|
||||
}
|
||||
@@ -376,20 +497,29 @@ namespace ScriptCanvasEditor
|
||||
|
||||
// CommandListDataProxyModel
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
CommandListDataProxyModel::CommandListDataProxyModel(QObject* parent /*= nullptr*/)
|
||||
CommandListDataProxyModel::CommandListDataProxyModel(CommandListDataModel* commandListData, QObject* parent /*= nullptr*/)
|
||||
: QSortFilterProxyModel(parent)
|
||||
{
|
||||
QStringList commands;
|
||||
setSourceModel(commandListData);
|
||||
|
||||
QStringList commandList;
|
||||
|
||||
CommandListDataModel* commandListData = new CommandListDataModel();
|
||||
for (int i = 0; i < commandListData->rowCount(); ++i)
|
||||
{
|
||||
QModelIndex index = commandListData->index(i, CommandListDataModel::ColumnIndex::Command);
|
||||
QModelIndex index = commandListData->index(i, CommandListDataModel::ColumnIndex::CommandIndex);
|
||||
QString command = commandListData->data(index, CommandListDataModel::CustomRole::Node).toString();
|
||||
commands.push_back(command);
|
||||
commandList.push_back(command);
|
||||
}
|
||||
|
||||
m_completer = new QCompleter(commands);
|
||||
ScriptCanvasCommandLineRequests::CommandNameList commands;
|
||||
ScriptCanvasCommandLineRequestBus::BroadcastResult(commands, &ScriptCanvasCommandLineRequests::GetCommands);
|
||||
for (auto& command : commands)
|
||||
{
|
||||
QString commandName = command.first.c_str();
|
||||
commandList.push_back(commandName);
|
||||
}
|
||||
|
||||
m_completer = new QCompleter(commandList);
|
||||
m_completer->setCompletionMode(QCompleter::UnfilteredPopupCompletion);
|
||||
m_completer->setCaseSensitivity(Qt::CaseInsensitive);
|
||||
}
|
||||
@@ -421,7 +551,7 @@ namespace ScriptCanvasEditor
|
||||
}
|
||||
}
|
||||
|
||||
QModelIndex index = dataModel->index(sourceRow, CommandListDataModel::ColumnIndex::Command);
|
||||
QModelIndex index = dataModel->index(sourceRow, CommandListDataModel::ColumnIndex::CommandIndex);
|
||||
|
||||
QString sourceStr = dataModel->data(index).toString();
|
||||
if (sourceRow > 0 && sourceStr.startsWith(m_input.c_str(), Qt::CaseSensitivity::CaseInsensitive))
|
||||
@@ -450,8 +580,7 @@ namespace ScriptCanvasEditor
|
||||
ui->setupUi(this);
|
||||
|
||||
CommandListDataModel* commandListDataModel = new CommandListDataModel();
|
||||
CommandListDataProxyModel* commandListDataProxyModel = new CommandListDataProxyModel();
|
||||
commandListDataProxyModel->setSourceModel(commandListDataModel);
|
||||
CommandListDataProxyModel* commandListDataProxyModel = new CommandListDataProxyModel(commandListDataModel);
|
||||
|
||||
ui->commandList->setModel(commandListDataProxyModel);
|
||||
|
||||
@@ -460,8 +589,8 @@ namespace ScriptCanvasEditor
|
||||
connect(ui->commandText, &CommandLineEdit::onKeyReleased, this, &CommandLine::onEditKeyReleaseEvent);
|
||||
connect(ui->commandList, &CommandLineList::onKeyReleased, this, &CommandLine::onListKeyReleaseEvent);
|
||||
|
||||
ui->commandList->setColumnWidth(CommandListDataModel::ColumnIndex::Command, 250);
|
||||
ui->commandList->setColumnWidth(CommandListDataModel::ColumnIndex::Description, 1000);
|
||||
ui->commandList->setColumnWidth(CommandListDataModel::ColumnIndex::CommandIndex, 250);
|
||||
ui->commandList->setColumnWidth(CommandListDataModel::ColumnIndex::DescriptionIndex, 1000);
|
||||
}
|
||||
|
||||
void CommandLine::onTextChanged(const QString& text)
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
#include <AzCore/Console/Console.h>
|
||||
#endif
|
||||
|
||||
namespace Ui
|
||||
@@ -36,10 +37,49 @@ namespace ScriptCanvasEditor
|
||||
{
|
||||
namespace Widget
|
||||
{
|
||||
class Command
|
||||
{
|
||||
public:
|
||||
using Functor = AZStd::function<void(AZStd::vector<AZStd::string>)>;
|
||||
|
||||
Command(const AZStd::string& name, const AZStd::string& description, Functor functor)
|
||||
: m_name(name)
|
||||
, m_description(description)
|
||||
, m_functor(functor)
|
||||
{}
|
||||
|
||||
void operator()(const AZStd::vector<AZStd::string>& args)
|
||||
{
|
||||
m_functor(args);
|
||||
}
|
||||
|
||||
const AZStd::string& GetName() const { return m_name; }
|
||||
const AZStd::string& GetDescription() const { return m_description; }
|
||||
|
||||
private:
|
||||
AZStd::string m_name;
|
||||
AZStd::string m_description;
|
||||
Functor m_functor;
|
||||
};
|
||||
|
||||
using CommandRegistry = AZStd::unordered_map<AZStd::string, AZStd::unique_ptr<Command>>;
|
||||
|
||||
struct ScriptCanvasCommandLineRequests : public AZ::EBusTraits
|
||||
{
|
||||
virtual void AddCommand(const AZStd::string commandName, const AZStd::string description, Command::Functor) = 0;
|
||||
virtual void Invoke(const char* commandName) = 0;
|
||||
virtual void InvokeWithArguments(const char* commandName, const AZStd::vector<AZStd::string>&) = 0;
|
||||
|
||||
using CommandNameList = AZStd::list<AZStd::pair<AZStd::string, AZStd::string>>;
|
||||
virtual CommandNameList GetCommands() = 0;
|
||||
};
|
||||
using ScriptCanvasCommandLineRequestBus = AZ::EBus<ScriptCanvasCommandLineRequests>;
|
||||
|
||||
// TODO #lsempe: this deserves its own file
|
||||
// CommandListDataModel
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
class CommandListDataModel : public QAbstractTableModel
|
||||
, ScriptCanvasCommandLineRequestBus::Handler
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@@ -49,9 +89,9 @@ namespace ScriptCanvasEditor
|
||||
|
||||
enum ColumnIndex
|
||||
{
|
||||
Command,
|
||||
Description,
|
||||
Trail,
|
||||
CommandIndex,
|
||||
DescriptionIndex,
|
||||
TrailIndex,
|
||||
Count
|
||||
};
|
||||
|
||||
@@ -65,6 +105,8 @@ namespace ScriptCanvasEditor
|
||||
};
|
||||
|
||||
CommandListDataModel(QWidget* parent = nullptr);
|
||||
~CommandListDataModel() override;
|
||||
|
||||
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
|
||||
QModelIndex parent(const QModelIndex &child) const override;
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
@@ -75,10 +117,62 @@ namespace ScriptCanvasEditor
|
||||
|
||||
bool HasMatches(const AZStd::string& input);
|
||||
|
||||
struct Entry
|
||||
{
|
||||
AZ::Uuid m_type;
|
||||
AZStd::string m_command;
|
||||
|
||||
Entry()
|
||||
{
|
||||
m_type = AZ::Uuid::CreateNull();
|
||||
}
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
AZStd::vector<AZ::Uuid> m_nodeTypes;
|
||||
AZStd::vector<Entry> m_entries;
|
||||
|
||||
static CommandRegistry m_commands;
|
||||
|
||||
void AddCommand(const AZStd::string commandName, const AZStd::string description, Command::Functor f) override
|
||||
{
|
||||
if (m_commands.find(commandName) == m_commands.end())
|
||||
{
|
||||
m_commands[commandName] = AZStd::make_unique<Command>(commandName, description, f);
|
||||
Entry entry;
|
||||
entry.m_command = commandName;
|
||||
entry.m_type = AZ::Uuid::CreateNull();
|
||||
m_entries.emplace_back(entry);
|
||||
}
|
||||
}
|
||||
|
||||
void Invoke(const char* commandName) override
|
||||
{
|
||||
auto command = m_commands.find(commandName);
|
||||
if (command != m_commands.end())
|
||||
{
|
||||
command->second->operator()({});
|
||||
}
|
||||
}
|
||||
|
||||
void InvokeWithArguments(const char* commandName, const AZStd::vector<AZStd::string>& args) override
|
||||
{
|
||||
auto command = m_commands.find(commandName);
|
||||
if (command != m_commands.end())
|
||||
{
|
||||
command->second->operator()(args);
|
||||
}
|
||||
}
|
||||
|
||||
ScriptCanvasCommandLineRequests::CommandNameList GetCommands() override
|
||||
{
|
||||
ScriptCanvasCommandLineRequests::CommandNameList commands;
|
||||
for (auto& command : m_commands)
|
||||
{
|
||||
commands.push_back(AZStd::make_pair(command.second->GetName(), command.second->GetDescription()));
|
||||
}
|
||||
return commands;
|
||||
}
|
||||
};
|
||||
|
||||
class CommandListDataProxyModel : public QSortFilterProxyModel
|
||||
@@ -88,7 +182,7 @@ namespace ScriptCanvasEditor
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(CommandListDataProxyModel, AZ::SystemAllocator, 0);
|
||||
|
||||
CommandListDataProxyModel(QObject* parent = nullptr);
|
||||
CommandListDataProxyModel(CommandListDataModel* commandListData, QObject* parent = nullptr);
|
||||
|
||||
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override;
|
||||
|
||||
@@ -168,4 +262,4 @@ namespace ScriptCanvasEditor
|
||||
AZStd::unique_ptr<Ui::CommandLine> ui;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -41,11 +41,11 @@ namespace ScriptCanvasEditor
|
||||
if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(reflectContext))
|
||||
{
|
||||
serializeContext->Class<CreateFunctionMimeEvent, CreateNodeMimeEvent>()
|
||||
->Version(4)
|
||||
->Version(5)
|
||||
->Field("AssetId", &CreateFunctionMimeEvent::m_assetId)
|
||||
->Field("sourceId", &CreateFunctionMimeEvent::m_sourceId)
|
||||
;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
CreateFunctionMimeEvent::CreateFunctionMimeEvent(const AZ::Data::AssetId& assetId, const AZ::Data::AssetType& assetType, const ScriptCanvas::Grammar::FunctionSourceId& sourceId)
|
||||
|
||||
@@ -57,7 +57,7 @@ namespace
|
||||
{
|
||||
if (excludeAttributeData)
|
||||
{
|
||||
AZ::u64 exclusionFlags = AZ::Script::Attributes::ExcludeFlags::List | AZ::Script::Attributes::ExcludeFlags::ListOnly | AZ::ScriptCanvasAttributes::VariableCreationForbidden;
|
||||
AZ::u64 exclusionFlags = AZ::Script::Attributes::ExcludeFlags::List | AZ::Script::Attributes::ExcludeFlags::ListOnly;
|
||||
|
||||
if (typeId == AzToolsFramework::Components::EditorComponentBase::TYPEINFO_Uuid())
|
||||
{
|
||||
@@ -143,11 +143,6 @@ namespace
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ScriptCanvas::Data::IsAllowedBehaviorClassVariableType(behaviorClass->m_typeId))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const auto isExposableOutcome = ScriptCanvas::IsExposable(method);
|
||||
@@ -479,38 +474,24 @@ namespace
|
||||
continue;
|
||||
}
|
||||
|
||||
// Only bind Behavior Classes marked with the Scope type of Launcher
|
||||
if (auto excludeFromPointer = AZ::FindAttribute(AZ::Script::Attributes::ExcludeFrom, behaviorClass->m_attributes))
|
||||
{
|
||||
AZ::Script::Attributes::ExcludeFlags excludeFlags{};
|
||||
AZ::AttributeReader(nullptr, excludeFromPointer).Read<AZ::Script::Attributes::ExcludeFlags>(excludeFlags);
|
||||
|
||||
if ((excludeFlags & (AZ::Script::Attributes::ExcludeFlags::List | AZ::Script::Attributes::ExcludeFlags::ListOnly)) != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!AZ::Internal::IsInScope(behaviorClass->m_attributes, AZ::Script::Attributes::ScopeFlags::Launcher))
|
||||
{
|
||||
continue; // skip this class
|
||||
continue;
|
||||
}
|
||||
|
||||
// Objects and Object methods
|
||||
{
|
||||
bool canCreate = serializeContext->FindClassData(behaviorClass->m_typeId) != nullptr &&
|
||||
!HasAttribute(behaviorClass, AZ::ScriptCanvasAttributes::VariableCreationForbidden);
|
||||
|
||||
// In order to create variables, the class must have full memory support
|
||||
canCreate = canCreate &&
|
||||
(behaviorClass->m_allocate
|
||||
&& behaviorClass->m_cloner
|
||||
&& behaviorClass->m_mover
|
||||
&& behaviorClass->m_destructor
|
||||
&& behaviorClass->m_deallocate);
|
||||
|
||||
if (canCreate)
|
||||
{
|
||||
// Do not allow variable creation for data that derives from AZ::Component
|
||||
for (auto base : behaviorClass->m_baseClasses)
|
||||
{
|
||||
if (AZ::Component::TYPEINFO_Uuid() == base)
|
||||
{
|
||||
canCreate = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AZStd::string categoryPath;
|
||||
|
||||
AZStd::string translationContext = ScriptCanvasEditor::TranslationHelper::GetContextName(ScriptCanvasEditor::TranslationContextGroup::ClassMethod, behaviorClass->m_name);
|
||||
@@ -530,17 +511,14 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
if (canCreate)
|
||||
{
|
||||
auto dataRegistry = ScriptCanvas::GetDataRegistry();
|
||||
ScriptCanvas::Data::Type type = dataRegistry->m_typeIdTraitMap[ScriptCanvas::Data::eType::BehaviorContextObject].m_dataTraits.GetSCType(behaviorClass->m_typeId);
|
||||
auto dataRegistry = ScriptCanvas::GetDataRegistry();
|
||||
ScriptCanvas::Data::Type type = dataRegistry->m_typeIdTraitMap[ScriptCanvas::Data::eType::BehaviorContextObject].m_dataTraits.GetSCType(behaviorClass->m_typeId);
|
||||
|
||||
if (type.IsValid())
|
||||
if (type.IsValid())
|
||||
{
|
||||
if (dataRegistry->m_creatableTypes.contains(type))
|
||||
{
|
||||
if (!AZ::FindAttribute(AZ::ScriptCanvasAttributes::AllowInternalCreation, behaviorClass->m_attributes))
|
||||
{
|
||||
ScriptCanvasEditor::VariablePaletteRequestBus::Broadcast(&ScriptCanvasEditor::VariablePaletteRequests::RegisterVariableType, type);
|
||||
}
|
||||
ScriptCanvasEditor::VariablePaletteRequestBus::Broadcast(&ScriptCanvasEditor::VariablePaletteRequests::RegisterVariableType, type);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -578,6 +556,14 @@ namespace
|
||||
categoryPath.append(displayName.c_str());
|
||||
}
|
||||
|
||||
for (auto property : behaviorClass->m_properties)
|
||||
{
|
||||
if (property.second->m_setter)
|
||||
{
|
||||
RegisterMethod(nodePaletteModel, behaviorContext, categoryPath, behaviorClass, property.first, *property.second->m_setter, behaviorClass->IsMethodOverloaded(property.first));
|
||||
}
|
||||
}
|
||||
|
||||
for (auto methodIter : behaviorClass->m_methods)
|
||||
{
|
||||
if (!IsExplicitOverload(*methodIter.second))
|
||||
|
||||
+1
-1
@@ -1011,7 +1011,7 @@ namespace ScriptCanvasEditor
|
||||
ScriptCanvas::Datum datum(variableType, ScriptCanvas::Datum::eOriginality::Original);
|
||||
|
||||
AZ::Outcome<ScriptCanvas::VariableId, AZStd::string> outcome = AZ::Failure(AZStd::string());
|
||||
ScriptCanvas::GraphVariableManagerRequestBus::EventResult(outcome, m_activeGraphIds.scriptCanvasId, &ScriptCanvas::GraphVariableManagerRequests::AddVariable, varName, datum);
|
||||
ScriptCanvas::GraphVariableManagerRequestBus::EventResult(outcome, m_activeGraphIds.scriptCanvasId, &ScriptCanvas::GraphVariableManagerRequests::AddVariable, varName, datum, false);
|
||||
|
||||
if (outcome.IsSuccess())
|
||||
{
|
||||
|
||||
+28
-1
@@ -41,6 +41,7 @@
|
||||
#include <ScriptCanvas/Bus/EditorScriptCanvasBus.h>
|
||||
|
||||
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
|
||||
#include <ScriptCanvas/Variable/GraphVariable.h>
|
||||
|
||||
namespace ScriptCanvasEditor
|
||||
{
|
||||
@@ -538,7 +539,24 @@ namespace ScriptCanvasEditor
|
||||
}
|
||||
else if (index.column() == ColumnIndex::Scope)
|
||||
{
|
||||
// Scope is not changed by users
|
||||
ScriptCanvas::GraphVariable* graphVariable = nullptr;
|
||||
ScriptCanvas::GraphVariableManagerRequestBus::EventResult(graphVariable, m_scriptCanvasId, &ScriptCanvas::GraphVariableManagerRequests::FindVariableById, varId.m_identifier);
|
||||
|
||||
if (graphVariable)
|
||||
{
|
||||
QString comboBoxValue = value.toString();
|
||||
|
||||
if (!comboBoxValue.isEmpty())
|
||||
{
|
||||
AZStd::string scopeLabel = ScriptCanvas::VariableFlags::GetScopeDisplayLabel(graphVariable->GetScope());
|
||||
if (scopeLabel.compare(comboBoxValue.toUtf8().data()) != 0)
|
||||
{
|
||||
modifiedData = true;
|
||||
graphVariable->SetScope(ScriptCanvas::VariableFlags::GetScopeFromLabel(comboBoxValue.toUtf8().data()));
|
||||
AzToolsFramework::PropertyEditorGUIMessages::Bus::Broadcast(&AzToolsFramework::PropertyEditorGUIMessages::RequestRefresh, AzToolsFramework::Refresh_EntireTree);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (index.column() == ColumnIndex::InitialValueSource)
|
||||
{
|
||||
@@ -607,8 +625,17 @@ namespace ScriptCanvasEditor
|
||||
}
|
||||
else if (index.column() == ColumnIndex::Scope)
|
||||
{
|
||||
ScriptCanvas::GraphScopedVariableId varId = FindScopedVariableIdForIndex(index);
|
||||
|
||||
ScriptCanvas::GraphVariable* graphVariable = nullptr;
|
||||
ScriptCanvas::GraphVariableManagerRequestBus::EventResult(graphVariable, m_scriptCanvasId, &ScriptCanvas::GraphVariableManagerRequests::FindVariableById, varId.m_identifier);
|
||||
|
||||
if (graphVariable->GetScope() != ScriptCanvas::VariableFlags::Scope::FunctionReadOnly)
|
||||
{
|
||||
itemFlags |= Qt::ItemIsEditable;
|
||||
}
|
||||
|
||||
}
|
||||
else if (index.column() == ColumnIndex::InitialValueSource)
|
||||
{
|
||||
itemFlags |= Qt::ItemIsEditable;
|
||||
|
||||
@@ -73,6 +73,8 @@ namespace ScriptCanvasEditor
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
ui->variablePalette->SetActiveScene(scriptCanvasId);
|
||||
|
||||
ui->searchFilter->setClearButtonEnabled(true);
|
||||
QObject::connect(ui->searchFilter, &QLineEdit::textChanged, this, &SlotTypeSelectorWidget::OnQuickFilterChanged);
|
||||
QObject::connect(ui->slotName, &QLineEdit::returnPressed, this, &SlotTypeSelectorWidget::OnReturnPressed);
|
||||
|
||||
@@ -812,7 +812,7 @@ namespace ScriptCanvasEditor
|
||||
ScriptCanvas::Datum datum(varType, ScriptCanvas::Datum::eOriginality::Original);
|
||||
|
||||
AZ::Outcome<ScriptCanvas::VariableId, AZStd::string> outcome = AZ::Failure(AZStd::string());
|
||||
ScriptCanvas::GraphVariableManagerRequestBus::EventResult(outcome, m_scriptCanvasId, &ScriptCanvas::GraphVariableManagerRequests::AddVariable, variableName, datum);
|
||||
ScriptCanvas::GraphVariableManagerRequestBus::EventResult(outcome, m_scriptCanvasId, &ScriptCanvas::GraphVariableManagerRequests::AddVariable, variableName, datum, false);
|
||||
|
||||
AZ_Warning("VariablePanel", outcome.IsSuccess(), "Could not create new variable: %s", outcome.GetError().c_str());
|
||||
GeneralRequestBus::Broadcast(&GeneralRequests::PostUndoPoint, m_scriptCanvasId);
|
||||
|
||||
+2
-2
@@ -122,8 +122,8 @@ namespace ScriptCanvasEditor
|
||||
|
||||
for (const AZ::Uuid& objectId : objectTypes)
|
||||
{
|
||||
// Verify whether this is an allowed BC variable type
|
||||
if (!ScriptCanvas::Data::IsAllowedBehaviorClassVariableType(objectId))
|
||||
ScriptCanvas::Data::Type type = dataRegistry->m_typeIdTraitMap[ScriptCanvas::Data::eType::BehaviorContextObject].m_dataTraits.GetSCType(objectId);
|
||||
if (!type.IsValid() || !dataRegistry->m_creatableTypes.contains(type))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -595,7 +595,6 @@ namespace ScriptCanvasEditor
|
||||
m_commandLine = new Widget::CommandLine(this);
|
||||
m_commandLine->setBaseSize(QSize(size().width(), m_commandLine->size().height()));
|
||||
m_commandLine->setObjectName("CommandLine");
|
||||
m_commandLine->hide();
|
||||
|
||||
m_layout->addWidget(m_commandLine);
|
||||
m_layout->addWidget(m_emptyCanvas);
|
||||
|
||||
@@ -244,7 +244,7 @@
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="visible">
|
||||
<bool>false</bool>
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_ViewNodePalette">
|
||||
|
||||
+1
-1
@@ -66,7 +66,7 @@ namespace {{attribute_Namespace}}
|
||||
|
||||
{% set deprecationUuid = Class.attrib['DeprecationUUID'] %}
|
||||
|
||||
// The following will be injected directly into the source header file for which AzCodeGenerator is being run.
|
||||
// The following will be injected directly into the source header file for which AZ AutoGen is being run.
|
||||
// You must #include the generated header into the source header
|
||||
#define SCRIPTCANVAS_NODE_{{ className }} \
|
||||
public: \
|
||||
|
||||
+1
-1
@@ -158,7 +158,7 @@ return {{returnNames[0]}};
|
||||
{% endfor %}
|
||||
{# ExecutionOuts #}
|
||||
// ExecutionOuts begin
|
||||
{{ nodemacro.ExecutionOutDefinitions(Class, attribute_QualifiedName )}}
|
||||
{{ nodemacro.ExecutionOutDefinitions(Class, attribute_QualifiedName)}}
|
||||
// ExecutionOuts end
|
||||
{# Reflect #}
|
||||
void {{attribute_QualifiedName}}::Reflect(AZ::ReflectContext* context)
|
||||
|
||||
+21
-13
@@ -307,41 +307,49 @@ AZStd::tuple<{{returns|join(", ")}}>
|
||||
{% for executionOut in Class.findall('Output') %}
|
||||
{{ ExecutionOutDeclaration(Class, executionOut) }}
|
||||
{%- endfor %}
|
||||
size_t GetRequiredOutCount() const override;
|
||||
{% endmacro %}
|
||||
|
||||
{% macro ExecutionBranchDefinition(Class, qualifiedName, executionOut) %}
|
||||
{% macro ExecutionBranchDefinition(Class, qualifiedName, executionOut, outIndexBranch) %}
|
||||
{% set outName = CleanName(executionOut.attrib['Name']) %}
|
||||
{% set returns = executionOut.findall('Parameter') %}
|
||||
{% set params = executionOut.findall('Return') %}
|
||||
void {{qualifiedName}}::Call{{CleanName(outName)}}({{ExecutionOutReturnDefinition(returns)}}{{ExecutionOutParameterDefinition(returns, params)}}) {
|
||||
void {{qualifiedName}}::Call{{outName}}({{ExecutionOutReturnDefinition(returns)}}{{ExecutionOutParameterDefinition(returns, params)}}) {
|
||||
{% if returns|length() == 0 %}
|
||||
ExecutionOut(AZ_CRC_CE("{{ executionOut.attrib['Name'] }}"){% for parameter in params %}, {{CleanName(parameter.attrib['Name'])}} {% endfor %}
|
||||
ExecutionOut({{ outIndexBranch }}{% for parameter in params %}, {{CleanName(parameter.attrib['Name'])}}{% endfor %}
|
||||
{% else %}
|
||||
OutResult(AZ_CRC_CE("{{ executionOut.attrib['Name'] }}"), result{% for parameter in params %}, {{CleanName(parameter.attrib['Name'])}} {% endfor %}
|
||||
{% endif -%});
|
||||
ExecutionOutResult({{ outIndexBranch }}, result{% for parameter in params %}, {{CleanName(parameter.attrib['Name'])}}{% endfor %}
|
||||
{% endif -%}); // {{ executionOut.attrib['Name'] }}
|
||||
}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro ExecutionOutDefinition(Class, qualifiedName, executionOut) %}
|
||||
{% macro ExecutionOutDefinition(Class, qualifiedName, executionOut, outIndexLatent) %}
|
||||
{% set outName = CleanName(executionOut.attrib['Name']) %}
|
||||
{% set returns = executionOut.findall('Return') %}
|
||||
{% set params = executionOut.findall('Parameter') %}
|
||||
void {{qualifiedName}}::Call{{CleanName(outName)}}({{ExecutionOutReturnDefinition(returns)}}{{ExecutionOutParameterDefinition(returns, params)}}) {
|
||||
{% if returns|length() == 0 %}
|
||||
ExecutionOut(AZ_CRC_CE("{{ executionOut.attrib['Name'] }}"){% for parameter in params %}, {{CleanName(parameter.attrib['Name'])}} {% endfor %}
|
||||
ExecutionOut({{ outIndexLatent }}{% for parameter in params %}, {{CleanName(parameter.attrib['Name'])}}{% endfor %}
|
||||
{% else %}
|
||||
OutResult(AZ_CRC_CE("{{ executionOut.attrib['Name'] }}"), result{% for parameter in params %}, {{CleanName(parameter.attrib['Name'])}} {% endfor %}
|
||||
{% endif -%} );
|
||||
ExecutionOutResult({{ outIndexLatent }}, result{% for parameter in params %}, {{CleanName(parameter.attrib['Name'])}}{% endfor %}
|
||||
{% endif -%}); // {{ executionOut.attrib['Name'] }}
|
||||
}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro ExecutionOutDefinitions(Class, qualifiedName) %}
|
||||
{% set branches = [] %}
|
||||
{% for method in Class.findall('Input') %}
|
||||
{%- for branch in method.findall('Branch') %}
|
||||
{{ ExecutionBranchDefinition(Class, qualifiedName, branch) }}
|
||||
{% if branches.append(branch) %}{% endif %}
|
||||
{%- endfor %}
|
||||
{% endfor %}
|
||||
{%- for executionOut in Class.findall('Output') -%}
|
||||
{{ ExecutionOutDefinition(Class, qualifiedName, executionOut) }}
|
||||
{% endfor %}
|
||||
{%- for branch in branches -%}
|
||||
{{ ExecutionBranchDefinition(Class, qualifiedName, branch, loop.index0) }}
|
||||
{%- endfor %}
|
||||
{%- 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 %}
|
||||
@@ -208,7 +208,13 @@ namespace ScriptCanvas
|
||||
static const t_Value* Help(Datum& datum)
|
||||
{
|
||||
static_assert(!AZStd::is_pointer<t_Value>::value, "no pointer types in the Datum::GetAsHelper<t_Value, false>");
|
||||
if (datum.m_type.GetType() == Data::eType::BehaviorContextObject)
|
||||
|
||||
if (datum.m_storage.empty())
|
||||
{
|
||||
// rare, but can be caused by removals or problems with reflection to BehaviorContext, so must be checked
|
||||
return nullptr;
|
||||
}
|
||||
else if (datum.m_type.GetType() == Data::eType::BehaviorContextObject)
|
||||
{
|
||||
return (*AZStd::any_cast<BehaviorContextObjectPtr>(&datum.m_storage))->CastConst<t_Value>();
|
||||
}
|
||||
|
||||
@@ -88,17 +88,7 @@ namespace ScriptCanvas
|
||||
void EBusHandler::InitializeEBusHandling(AZStd::string_view busName, AZ::BehaviorContext* behaviorContext)
|
||||
{
|
||||
CreateHandler(busName, behaviorContext);
|
||||
|
||||
const AZ::BehaviorEBusHandler::EventArray& events = m_handler->GetEvents();
|
||||
AZStd::vector<AZ::Crc32> eventKeys;
|
||||
eventKeys.reserve(events.size());
|
||||
|
||||
for (int eventIndex(0); eventIndex < events.size(); ++eventIndex)
|
||||
{
|
||||
eventKeys.push_back(eventIndex);
|
||||
}
|
||||
|
||||
InitializeExecutionOuts(eventKeys);
|
||||
InitializeExecutionOuts(m_handler->GetEvents().size());
|
||||
}
|
||||
|
||||
bool EBusHandler::IsConnected() const
|
||||
@@ -137,7 +127,7 @@ namespace ScriptCanvas
|
||||
|
||||
void EBusHandler::OnEvent(const char* /*eventName*/, const int eventIndex, AZ::BehaviorValueParameter* result, const int numParameters, AZ::BehaviorValueParameter* parameters)
|
||||
{
|
||||
CallOut(AZ::Crc32(eventIndex), result, parameters, numParameters);
|
||||
CallOut(eventIndex, result, parameters, numParameters);
|
||||
}
|
||||
|
||||
void EBusHandler::Reflect(AZ::ReflectContext* reflectContext)
|
||||
|
||||
@@ -57,7 +57,7 @@ namespace ScriptCanvas
|
||||
|
||||
for (size_t resultIndex = 0; resultIndex < unpackedTypes.size(); ++resultIndex)
|
||||
{
|
||||
const Data::Type outputType(Data::FromAZType(unpackedTypes[resultIndex]));
|
||||
const Data::Type outputType = (unpackedTypes.size() == 1 && AZ::BehaviorContextHelper::IsStringParameter(*result)) ? Data::Type::String() : Data::FromAZType(unpackedTypes[resultIndex]);
|
||||
|
||||
const AZStd::string resultSlotName(AZStd::string::format("Result: %s", Data::GetName(outputType).data()));
|
||||
SlotId addedSlotId;
|
||||
|
||||
@@ -3155,6 +3155,11 @@ namespace ScriptCanvas
|
||||
return {};
|
||||
}
|
||||
|
||||
AZStd::optional<size_t> Node::GetEventIndex([[maybe_unused]] AZStd::string eventName) const
|
||||
{
|
||||
return AZStd::nullopt;
|
||||
}
|
||||
|
||||
AZStd::vector<SlotId> Node::GetEventSlotIds() const
|
||||
{
|
||||
return {};
|
||||
@@ -3404,6 +3409,45 @@ namespace ScriptCanvas
|
||||
return GetSlotByName("True");
|
||||
}
|
||||
|
||||
size_t Node::GetOutIndex(const Slot& slot) const
|
||||
{
|
||||
size_t index = 0;
|
||||
auto slotId = slot.GetId();
|
||||
|
||||
if (auto map = GetSlotExecutionMap())
|
||||
{
|
||||
auto& ins = map->GetIns();
|
||||
for (auto& in : ins)
|
||||
{
|
||||
for (auto& out : in.outs)
|
||||
{
|
||||
// only count branches
|
||||
if (in.outs.size() > 1)
|
||||
{
|
||||
if (out.slotId == slotId)
|
||||
{
|
||||
return index;
|
||||
}
|
||||
|
||||
++index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& latent : map->GetLatents())
|
||||
{
|
||||
if (latent.slotId == slotId)
|
||||
{
|
||||
return index;
|
||||
}
|
||||
|
||||
++index;
|
||||
}
|
||||
}
|
||||
|
||||
return std::numeric_limits<size_t>::max();
|
||||
}
|
||||
|
||||
AZ::Outcome<AZStd::string> Node::GetInternalOutKey(const Slot& slot) const
|
||||
{
|
||||
if (auto map = GetSlotExecutionMap())
|
||||
|
||||
@@ -700,6 +700,8 @@ namespace ScriptCanvas
|
||||
// override if necessary, usually only when the node's execution topology dramatically alters at edit-time in a way that is not generally parseable
|
||||
ConstSlotsOutcome GetSlotsInExecutionThreadByType(const Slot& executionSlot, CombinedSlotType targetSlotType, const Slot* executionChildSlot = nullptr) const;
|
||||
|
||||
size_t GetOutIndex(const Slot& slot) const;
|
||||
|
||||
// override if necessary, only used by NodeableNodes which can hide branched outs and rename them later
|
||||
virtual AZ::Outcome<AZStd::string> GetInternalOutKey(const Slot& slot) const;
|
||||
|
||||
@@ -751,6 +753,8 @@ namespace ScriptCanvas
|
||||
|
||||
virtual AZStd::string GetEBusName() const;
|
||||
|
||||
virtual AZStd::optional<size_t> GetEventIndex(AZStd::string eventName) const;
|
||||
|
||||
virtual AZStd::vector<SlotId> GetEventSlotIds() const;
|
||||
|
||||
virtual AZStd::vector<SlotId> GetNonEventSlotIds() const;
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
namespace NodeableOutCpp
|
||||
{
|
||||
void NoOp(AZ::BehaviorValueParameter* /*result*/, AZ::BehaviorValueParameter* /*arguments*/, int /*numArguments*/) {}
|
||||
void NoOp([[maybe_unused]] AZ::BehaviorValueParameter*, [[maybe_unused]] AZ::BehaviorValueParameter*, [[maybe_unused]] int) {}
|
||||
}
|
||||
|
||||
namespace ScriptCanvas
|
||||
@@ -36,14 +36,14 @@ namespace ScriptCanvas
|
||||
{}
|
||||
|
||||
#if !defined(RELEASE)
|
||||
void Nodeable::CallOut(const AZ::Crc32 key, AZ::BehaviorValueParameter* resultBVP, AZ::BehaviorValueParameter* argsBVPs, int numArguments) const
|
||||
void Nodeable::CallOut(size_t index, AZ::BehaviorValueParameter* resultBVP, AZ::BehaviorValueParameter* argsBVPs, int numArguments) const
|
||||
{
|
||||
GetExecutionOutChecked(key)(resultBVP, argsBVPs, numArguments);
|
||||
GetExecutionOutChecked(index)(resultBVP, argsBVPs, numArguments);
|
||||
}
|
||||
#else
|
||||
void Nodeable::CallOut(const AZ::Crc32 key, AZ::BehaviorValueParameter* resultBVP, AZ::BehaviorValueParameter* argsBVPs, int numArguments) const
|
||||
void Nodeable::CallOut(size_t index, AZ::BehaviorValueParameter* resultBVP, AZ::BehaviorValueParameter* argsBVPs, int numArguments) const
|
||||
{
|
||||
GetExecutionOut(key)(resultBVP, argsBVPs, numArguments);
|
||||
GetExecutionOut(index)(resultBVP, argsBVPs, numArguments);
|
||||
}
|
||||
#endif // !defined(RELEASE)
|
||||
|
||||
@@ -62,11 +62,6 @@ namespace ScriptCanvas
|
||||
return m_executionState->GetEntityId();
|
||||
}
|
||||
|
||||
AZ::EntityId Nodeable::GetScriptCanvasId() const
|
||||
{
|
||||
return m_executionState->GetScriptCanvasId();
|
||||
}
|
||||
|
||||
void Nodeable::Reflect(AZ::ReflectContext* reflectContext)
|
||||
{
|
||||
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(reflectContext))
|
||||
@@ -77,9 +72,9 @@ namespace ScriptCanvas
|
||||
{
|
||||
editContext->Class<Nodeable>("Nodeable", "Nodeable")
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
||||
->Attribute(AZ::Edit::Attributes::ContainerCanBeModified, false)
|
||||
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
|
||||
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
||||
->Attribute(AZ::Edit::Attributes::ContainerCanBeModified, false)
|
||||
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
|
||||
;
|
||||
}
|
||||
}
|
||||
@@ -92,33 +87,45 @@ namespace ScriptCanvas
|
||||
->Constructor<ExecutionStateWeakPtr>()
|
||||
->Method("Deactivate", &Nodeable::Deactivate)
|
||||
->Method("InitializeExecutionState", &Nodeable::InitializeExecutionState)
|
||||
->Method("InitializeExecutionOuts", &Nodeable::InitializeExecutionOuts)
|
||||
->Method("InitializeExecutionOutByRequiredCount", &Nodeable::InitializeExecutionOutByRequiredCount)
|
||||
->Method("IsActive", &Nodeable::IsActive)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
const FunctorOut& Nodeable::GetExecutionOut(AZ::Crc32 key) const
|
||||
const FunctorOut& Nodeable::GetExecutionOut(size_t index) const
|
||||
{
|
||||
auto iter = m_outs.find(key);
|
||||
AZ_Assert(iter != m_outs.end(), "no out registered for key: %d", key);
|
||||
AZ_Assert(iter->second, "null execution methods are not allowed, key: %d", key);
|
||||
return iter->second;
|
||||
AZ_Assert(index < m_outs.size(), "index out of range in Nodeable::m_outs");
|
||||
auto& iter = m_outs[index];
|
||||
AZ_Assert(iter, "null execution methods are not allowed, index: %zu", index);
|
||||
return iter;
|
||||
}
|
||||
|
||||
const FunctorOut& Nodeable::GetExecutionOutChecked(AZ::Crc32 key) const
|
||||
const FunctorOut& Nodeable::GetExecutionOutChecked(size_t index) const
|
||||
{
|
||||
auto iter = m_outs.find(key);
|
||||
|
||||
if (iter == m_outs.end())
|
||||
{
|
||||
return m_noOpFunctor;
|
||||
}
|
||||
else if (!iter->second)
|
||||
|
||||
if (index >= m_outs.size() && m_outs[index])
|
||||
{
|
||||
return m_noOpFunctor;
|
||||
}
|
||||
|
||||
return iter->second;
|
||||
return m_outs[index];
|
||||
}
|
||||
|
||||
AZ::EntityId Nodeable::GetScriptCanvasId() const
|
||||
{
|
||||
return m_executionState->GetScriptCanvasId();
|
||||
}
|
||||
|
||||
void Nodeable::InitializeExecutionOuts(size_t count)
|
||||
{
|
||||
m_outs.resize(count, m_noOpFunctor);
|
||||
}
|
||||
|
||||
void Nodeable::InitializeExecutionOutByRequiredCount()
|
||||
{
|
||||
InitializeExecutionOuts(GetRequiredOutCount());
|
||||
}
|
||||
|
||||
void Nodeable::InitializeExecutionState(ExecutionState* executionState)
|
||||
@@ -126,37 +133,23 @@ namespace ScriptCanvas
|
||||
AZ_Assert(executionState != nullptr, "execution state for nodeable must not be nullptr");
|
||||
AZ_Assert(m_executionState == nullptr, "execution state already initialized");
|
||||
m_executionState = executionState->WeakFromThis();
|
||||
OnInitializeExecutionState();
|
||||
}
|
||||
|
||||
void Nodeable::InitializeExecutionOuts(const AZ::Crc32* begin, const AZ::Crc32* end)
|
||||
void Nodeable::SetExecutionOut(size_t index, FunctorOut&& out)
|
||||
{
|
||||
m_outs.reserve(end - begin);
|
||||
|
||||
for (; begin != end; ++begin)
|
||||
{
|
||||
SetExecutionOut(*begin, AZStd::move(FunctorOut(&NodeableOutCpp::NoOp)));
|
||||
}
|
||||
AZ_Assert(out, "null executions methods are not allowed, index: %zu", index);
|
||||
m_outs[index] = AZStd::move(out);
|
||||
}
|
||||
|
||||
void Nodeable::InitializeExecutionOuts(const AZStd::vector<AZ::Crc32>& keys)
|
||||
{
|
||||
InitializeExecutionOuts(keys.begin(), keys.end());
|
||||
}
|
||||
|
||||
void Nodeable::SetExecutionOut(AZ::Crc32 key, FunctorOut&& out)
|
||||
{
|
||||
AZ_Assert(out, "null executions methods are not allowed, key: %d", key);
|
||||
m_outs[key] = AZStd::move(out);
|
||||
}
|
||||
|
||||
void Nodeable::SetExecutionOutChecked(AZ::Crc32 key, FunctorOut&& out)
|
||||
void Nodeable::SetExecutionOutChecked(size_t index, FunctorOut&& out)
|
||||
{
|
||||
if (!out)
|
||||
{
|
||||
AZ_Error("ScriptCanvas", false, "null executions methods are not allowed, key: %d", key);
|
||||
AZ_Error("ScriptCanvas", false, "null executions methods are not allowed, index: %zu", index);
|
||||
return;
|
||||
}
|
||||
|
||||
SetExecutionOut(key, AZStd::move(out));
|
||||
SetExecutionOut(index, AZStd::move(out));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,23 @@ namespace ScriptCanvas
|
||||
class SubgraphInterface;
|
||||
}
|
||||
|
||||
/*
|
||||
Note: Many parts of AzAutoGen, compilation, and runtime depend on the order of declaration and addition of slots.
|
||||
The display order can be manipulated in the editor, but it will always just be a change of view.
|
||||
|
||||
Whenever in doubt, this is the order, in pseudo code
|
||||
|
||||
for in : Ins do
|
||||
somethingOrdered(in)
|
||||
for branch : in.Branches do
|
||||
somethingOrdered(branch)
|
||||
end
|
||||
end
|
||||
for out : Outs do
|
||||
somethingOrdered(out)
|
||||
end
|
||||
*/
|
||||
|
||||
// derive from this to make an object that when wrapped with a NodeableNode can be instantly turned into a node that is easily embedded in graphs,
|
||||
// and easily compiled in
|
||||
class Nodeable
|
||||
@@ -40,21 +57,23 @@ namespace ScriptCanvas
|
||||
// reflect nodeable class API
|
||||
static void Reflect(AZ::ReflectContext* reflectContext);
|
||||
|
||||
// the run-time constructor for non-EBus handlers
|
||||
Nodeable();
|
||||
|
||||
// this constructor is used by EBus handlers only
|
||||
Nodeable(ExecutionStateWeakPtr executionState);
|
||||
|
||||
virtual ~Nodeable() = default;
|
||||
|
||||
void CallOut(const AZ::Crc32 key, AZ::BehaviorValueParameter* resultBVP, AZ::BehaviorValueParameter* argsBVPs, int numArguments) const;
|
||||
void CallOut(size_t index, AZ::BehaviorValueParameter* resultBVP, AZ::BehaviorValueParameter* argsBVPs, int numArguments) const;
|
||||
|
||||
AZ::Data::AssetId GetAssetId() const;
|
||||
|
||||
AZ::EntityId GetEntityId() const;
|
||||
|
||||
const Execution::FunctorOut& GetExecutionOut(AZ::Crc32 key) const;
|
||||
const Execution::FunctorOut& GetExecutionOut(size_t index) const;
|
||||
|
||||
const Execution::FunctorOut& GetExecutionOutChecked(AZ::Crc32 key) const;
|
||||
const Execution::FunctorOut& GetExecutionOutChecked(size_t index) const;
|
||||
|
||||
virtual NodePropertyInterface* GetPropertyInterface(AZ::Crc32 /*propertyId*/) { return nullptr; }
|
||||
|
||||
@@ -66,98 +85,97 @@ namespace ScriptCanvas
|
||||
// any would only be good if graphs could opt into it, and execution slots could annotate changing activity level
|
||||
virtual bool IsActive() const { return false; }
|
||||
|
||||
void InitializeExecutionOuts(const AZ::Crc32* begin, const AZ::Crc32* end);
|
||||
void InitializeExecutionOuts(size_t count);
|
||||
|
||||
void InitializeExecutionOuts(const AZStd::vector<AZ::Crc32>& keys);
|
||||
void SetExecutionOut(size_t index, Execution::FunctorOut&& out);
|
||||
|
||||
void SetExecutionOut(AZ::Crc32 key, Execution::FunctorOut&& out);
|
||||
|
||||
void SetExecutionOutChecked(AZ::Crc32 key, Execution::FunctorOut&& out);
|
||||
void SetExecutionOutChecked(size_t index, Execution::FunctorOut&& out);
|
||||
|
||||
protected:
|
||||
void InitializeExecutionOutByRequiredCount();
|
||||
|
||||
void InitializeExecutionState(ExecutionState* executionState);
|
||||
|
||||
virtual void OnInitializeExecutionState() {}
|
||||
|
||||
virtual void OnDeactivate() {}
|
||||
|
||||
// all of these hooks are known at compile time, so no branching
|
||||
// we will need with and without result calls for each time for method
|
||||
// methods with result but no result requested, etc
|
||||
|
||||
template<typename t_Return>
|
||||
void OutResult(const AZ::Crc32 key, t_Return& result) const
|
||||
{
|
||||
// this is correct, it is up to the FunctorOut referenced by key to decide what to do with these params (whether to modify or handle strings differently)
|
||||
AZ::BehaviorValueParameter resultBVP(&result);
|
||||
|
||||
CallOut(key, &resultBVP, nullptr, 0);
|
||||
|
||||
#if !defined(RELEASE)
|
||||
if (!resultBVP.GetAsUnsafe<t_Return>())
|
||||
{
|
||||
AZ_Error("ScriptCanvas", false, "%s:CallOut(%u) failed to provide a useable result", TYPEINFO_Name(), (AZ::u32)key);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
result = *resultBVP.GetAsUnsafe<t_Return>();
|
||||
}
|
||||
virtual size_t GetRequiredOutCount() const { return 0; }
|
||||
|
||||
// Required to decay array type to pointer type
|
||||
template<typename T>
|
||||
using decay_array = AZStd::conditional_t<AZStd::is_array_v<AZStd::remove_reference_t<T>>, std::remove_extent_t<AZStd::remove_reference_t<T>>*, T&&>;
|
||||
|
||||
template<typename t_Return, typename... t_Args>
|
||||
void OutResult(const AZ::Crc32 key, t_Return& result, t_Args&&... args) const
|
||||
// all of these hooks are known at compile time, so no branching
|
||||
// we will need with and without result calls for each type of method
|
||||
// methods with result but no result requested, etc
|
||||
|
||||
template<typename... t_Args>
|
||||
void ExecutionOut(size_t index, t_Args&&... args) const
|
||||
{
|
||||
// this is correct, it is up to the FunctorOut referenced by key to decide what to do with these params (whether to modify or handle strings differently)
|
||||
// it is up to the FunctorOut referenced by key to decide what to do with these params (whether to modify or handle strings differently)
|
||||
AZStd::tuple<decay_array<t_Args>...> lvalueWrapper(AZStd::forward<t_Args>(args)...);
|
||||
using BVPReserveArray = AZStd::array<AZ::BehaviorValueParameter, sizeof...(args)>;
|
||||
auto MakeBVPArrayFunction = [](auto&&... element)
|
||||
{
|
||||
return BVPReserveArray{ {AZ::BehaviorValueParameter{&element}...} };
|
||||
};
|
||||
BVPReserveArray argsBVPs = AZStd::apply(MakeBVPArrayFunction, lvalueWrapper);
|
||||
AZ::BehaviorValueParameter resultBVP(&result);
|
||||
|
||||
CallOut(key, &resultBVP, argsBVPs.data(), sizeof...(t_Args));
|
||||
BVPReserveArray argsBVPs = AZStd::apply(MakeBVPArrayFunction, lvalueWrapper);
|
||||
CallOut(index, nullptr, argsBVPs.data(), sizeof...(t_Args));
|
||||
}
|
||||
|
||||
void ExecutionOut(size_t index) const
|
||||
{
|
||||
// it is up to the FunctorOut referenced by key to decide what to do with these params (whether to modify or handle strings differently)
|
||||
CallOut(index, nullptr, nullptr, 0);
|
||||
}
|
||||
template<typename t_Return>
|
||||
void ExecutionOutResult(size_t index, t_Return& result) const
|
||||
{
|
||||
// It is up to the FunctorOut referenced by the index to decide what to do with these params (whether to modify or handle strings differently)
|
||||
AZ::BehaviorValueParameter resultBVP(&result);
|
||||
CallOut(index, &resultBVP, nullptr, 0);
|
||||
|
||||
#if !defined(RELEASE)
|
||||
if (!resultBVP.GetAsUnsafe<t_Return>())
|
||||
{
|
||||
AZ_Error("ScriptCanvas", false, "%s:CallOut(%u) failed to provide a useable result", TYPEINFO_Name(), (AZ::u32)key);
|
||||
AZ_Error("ScriptCanvas", false, "%s:CallOut(%zu) failed to provide a useable result", TYPEINFO_Name(), index);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
result = *resultBVP.GetAsUnsafe<t_Return>();
|
||||
}
|
||||
|
||||
template<typename... t_Args>
|
||||
void ExecutionOut(const AZ::Crc32 key, t_Args&&... args) const
|
||||
template<typename t_Return, typename... t_Args>
|
||||
void ExecutionOutResult(size_t index, t_Return& result, t_Args&&... args) const
|
||||
{
|
||||
// this is correct, it is up to the FunctorOut referenced by key to decide what to do with these params (whether to modify or handle strings differently)
|
||||
// it is up to the FunctorOut referenced by key to decide what to do with these params (whether to modify or handle strings differently)
|
||||
AZStd::tuple<decay_array<t_Args>...> lvalueWrapper(AZStd::forward<t_Args>(args)...);
|
||||
using BVPReserveArray = AZStd::array<AZ::BehaviorValueParameter, sizeof...(args)>;
|
||||
auto MakeBVPArrayFunction = [](auto&&... element)
|
||||
{
|
||||
return BVPReserveArray{ {AZ::BehaviorValueParameter{&element}...} };
|
||||
};
|
||||
|
||||
BVPReserveArray argsBVPs = AZStd::apply(MakeBVPArrayFunction, lvalueWrapper);
|
||||
AZ::BehaviorValueParameter resultBVP(&result);
|
||||
CallOut(index, &resultBVP, argsBVPs.data(), sizeof...(t_Args));
|
||||
|
||||
CallOut(key, nullptr, argsBVPs.data(), sizeof...(t_Args));
|
||||
#if !defined(RELEASE)
|
||||
if (!resultBVP.GetAsUnsafe<t_Return>())
|
||||
{
|
||||
AZ_Error("ScriptCanvas", false, "%s:CallOut(%zu) failed to provide a useable result", TYPEINFO_Name(), index);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
result = *resultBVP.GetAsUnsafe<t_Return>();
|
||||
}
|
||||
|
||||
void ExecutionOut(const AZ::Crc32 key) const
|
||||
{
|
||||
// this is correct, it is up to the FunctorOut referenced by key to decide what to do with these params (whether to modify or handle strings differently)
|
||||
CallOut(key, nullptr, nullptr, 0);
|
||||
}
|
||||
|
||||
private:
|
||||
// keep this here, and don't even think about putting it back in the FunctorOuts by any method*, lambda capture or other.
|
||||
// programmers will need this for internal node state debugging and who knows what other reasons
|
||||
// * Lua execution is an exception
|
||||
ExecutionStateWeakPtr m_executionState = nullptr;
|
||||
Execution::FunctorOut m_noOpFunctor;
|
||||
AZStd::unordered_map<AZ::Crc32, Execution::FunctorOut> m_outs;
|
||||
AZStd::vector<Execution::FunctorOut> m_outs;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -91,19 +91,6 @@ namespace ScriptCanvas
|
||||
AZ_Error("ScriptCanvas", m_nodeable, "null Nodeable in NodeableNode::ConfigureSlots");
|
||||
}
|
||||
|
||||
AZ::Outcome<AZStd::pair<size_t, size_t>> NodeableNode::FindMethodAndInputIndexOfSlot(const SlotId& slotID) const
|
||||
{
|
||||
if (auto thisSlot = GetSlot(slotID))
|
||||
{
|
||||
if (thisSlot->GetType() == CombinedSlotType::DataIn)
|
||||
{
|
||||
return m_slotExecutionMap.FindInAndInputIndexOfSlot(slotID);
|
||||
}
|
||||
}
|
||||
|
||||
return AZ::Failure();
|
||||
}
|
||||
|
||||
AZ::Outcome<const AZ::BehaviorClass*, AZStd::string> NodeableNode::GetBehaviorContextClass() const
|
||||
{
|
||||
AZ::BehaviorContext* behaviorContext = NodeableNodeCpp::GetBehaviorContext();
|
||||
|
||||
@@ -73,8 +73,6 @@ namespace ScriptCanvas
|
||||
|
||||
void ConfigureSlots() override;
|
||||
|
||||
AZ::Outcome<AZStd::pair<size_t, size_t>> FindMethodAndInputIndexOfSlot(const SlotId& slotID) const;
|
||||
|
||||
AZ::Outcome<const AZ::BehaviorClass*, AZStd::string> GetBehaviorContextClass() const;
|
||||
|
||||
ConstSlotsOutcome GetBehaviorContextOutName(const Slot& inSlot) const;
|
||||
|
||||
@@ -105,11 +105,9 @@ namespace ScriptCanvas
|
||||
|
||||
void DataSlotConfiguration::SetType(const AZ::BehaviorParameter& typeDesc)
|
||||
{
|
||||
auto dataRegistry = GetDataRegistry();
|
||||
Data::Type scType = !AZ::BehaviorContextHelper::IsStringParameter(typeDesc) ? Data::FromAZType(typeDesc.m_typeId) : Data::Type::String();
|
||||
auto typeIter = dataRegistry->m_creatableTypes.find(scType);
|
||||
|
||||
if (typeIter != dataRegistry->m_creatableTypes.end())
|
||||
auto dataRegistry = GetDataRegistry();
|
||||
if (dataRegistry->IsUseableInSlot(scType))
|
||||
{
|
||||
m_datum.SetType(scType);
|
||||
}
|
||||
|
||||
@@ -152,22 +152,6 @@ namespace ScriptCanvas
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AZ::Outcome<AZStd::pair<size_t, size_t>> Map::FindInAndInputIndexOfSlot(const SlotId& slotID) const
|
||||
{
|
||||
for (const auto& in : m_ins)
|
||||
{
|
||||
auto inputIter = find_if(in.inputs, [&slotID](const Input& input) { return input.slotId == slotID; });
|
||||
if (inputIter != in.inputs.end())
|
||||
{
|
||||
const size_t inIndex = &in - m_ins.begin();
|
||||
const size_t inputIndex = inputIter - in.inputs.begin();
|
||||
return AZ::Success(AZStd::make_pair(inIndex, inputIndex));
|
||||
}
|
||||
}
|
||||
|
||||
return AZ::Failure();
|
||||
}
|
||||
|
||||
const In* Map::FindInFromInputSlot(const SlotId& slotID) const
|
||||
{
|
||||
auto iter = find_if
|
||||
|
||||
@@ -124,8 +124,6 @@ namespace ScriptCanvas
|
||||
|
||||
Map(Outs&& latents);
|
||||
|
||||
AZ::Outcome<AZStd::pair<size_t, size_t>> FindInAndInputIndexOfSlot(const SlotId& slotID) const;
|
||||
|
||||
const In* FindInFromInputSlot(const SlotId& slotID) const;
|
||||
|
||||
SlotId FindInputSlotIdBySource(VariableId inputSourceId, Grammar::FunctionSourceId inSourceId) const;
|
||||
|
||||
@@ -209,13 +209,18 @@ namespace ScriptCanvas
|
||||
m_latents.push_back(out);
|
||||
}
|
||||
|
||||
void SubgraphInterface::AddOutKey(const AZStd::string& name)
|
||||
bool SubgraphInterface::AddOutKey(const AZStd::string& name)
|
||||
{
|
||||
const AZ::Crc32 key(name);
|
||||
|
||||
if (AZStd::find(m_outKeys.begin(), m_outKeys.end(), key) == m_outKeys.end())
|
||||
{
|
||||
m_outKeys.push_back(key);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -708,7 +713,7 @@ namespace ScriptCanvas
|
||||
}
|
||||
|
||||
// Populates the list of out keys
|
||||
void SubgraphInterface::Parse()
|
||||
AZ::Outcome<void, AZStd::string> SubgraphInterface::Parse()
|
||||
{
|
||||
m_outKeys.clear();
|
||||
|
||||
@@ -716,14 +721,22 @@ namespace ScriptCanvas
|
||||
{
|
||||
for (const auto& out : in.outs)
|
||||
{
|
||||
AddOutKey(out.displayName);
|
||||
if (!AddOutKey(out.displayName))
|
||||
{
|
||||
return AZ::Failure(AZStd::string::format("Out %s was already in the list", out.displayName.c_str()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& latent : m_latents)
|
||||
{
|
||||
AddOutKey(latent.displayName);
|
||||
if (!AddOutKey(latent.displayName))
|
||||
{
|
||||
return AZ::Failure(AZStd::string::format("Out %s was already in the list", latent.displayName.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
return AZ::Success();
|
||||
}
|
||||
|
||||
void SubgraphInterface::Reflect(AZ::ReflectContext* refectContext)
|
||||
|
||||
@@ -232,7 +232,7 @@ namespace ScriptCanvas
|
||||
bool operator==(const SubgraphInterface& rhs) const;
|
||||
|
||||
// Populates the list of out keys
|
||||
void Parse();
|
||||
AZ::Outcome<void, AZStd::string> Parse();
|
||||
|
||||
bool RequiresConstructionParameters() const;
|
||||
|
||||
@@ -266,7 +266,7 @@ namespace ScriptCanvas
|
||||
AZStd::vector<AZ::Crc32> m_outKeys;
|
||||
NamespacePath m_namespacePath;
|
||||
|
||||
void AddOutKey(const AZStd::string& name);
|
||||
bool AddOutKey(const AZStd::string& name);
|
||||
const Out* FindImmediateOut(const AZStd::string& in, const AZStd::string& out) const;
|
||||
const In* FindIn(const AZStd::string& inSlotId) const;
|
||||
const Out* FindLatentOut(const AZStd::string& latent) const;
|
||||
|
||||
@@ -389,29 +389,6 @@ namespace ScriptCanvas
|
||||
return AZ::Utils::IsVectorContainerType(ToAZType(type));
|
||||
}
|
||||
|
||||
bool IsAllowedBehaviorClassVariableType(const AZ::Uuid& id)
|
||||
{
|
||||
AZ::BehaviorContext* behaviorContext = nullptr;
|
||||
AZ::ComponentApplicationBus::BroadcastResult(behaviorContext, &AZ::ComponentApplicationRequests::GetBehaviorContext);
|
||||
AZ_Assert(behaviorContext, "Unable to retrieve behavior context.");
|
||||
|
||||
const auto& classIterator = behaviorContext->m_typeToClassMap.find(id);
|
||||
if (classIterator != behaviorContext->m_typeToClassMap.end())
|
||||
{
|
||||
AZ::BehaviorClass* behaviorClass = classIterator->second;
|
||||
if (behaviorClass->FindAttribute(AZ::ScriptCanvasAttributes::VariableCreationForbidden))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IsSetContainerType(const AZ::Uuid& type)
|
||||
{
|
||||
return AZ::Utils::IsSetContainerType(type);
|
||||
|
||||
@@ -197,8 +197,6 @@ namespace ScriptCanvas
|
||||
bool IsVectorContainerType(const AZ::Uuid& type);
|
||||
bool IsVectorContainerType(const Type& type);
|
||||
|
||||
bool IsAllowedBehaviorClassVariableType(const AZ::Uuid& id);
|
||||
|
||||
AZStd::vector<AZ::Uuid> GetContainedTypes(const AZ::Uuid& type);
|
||||
AZStd::vector<Type> GetContainedTypes(const Type& type);
|
||||
AZStd::pair<AZ::Uuid, AZ::Uuid> GetOutcomeTypes(const AZ::Uuid& type);
|
||||
|
||||
@@ -105,14 +105,24 @@ namespace ScriptCanvas
|
||||
AZ_Error("Script Canvas", it.second, "Cannot register a second Trait struct with the same ScriptCanvas type(%u)", it.first->first);
|
||||
}
|
||||
|
||||
void DataRegistry::RegisterType(const AZ::TypeId& typeId, TypeProperties typeProperties)
|
||||
void DataRegistry::RegisterType(const AZ::TypeId& typeId, TypeProperties typeProperties, Createability registration)
|
||||
{
|
||||
Data::Type behaviorContextType = Data::FromAZType(typeId);
|
||||
if (behaviorContextType.GetType() == Data::eType::BehaviorContextObject && !behaviorContextType.GetAZType().IsNull())
|
||||
{
|
||||
if (m_creatableTypes.find(behaviorContextType) == m_creatableTypes.end())
|
||||
if (registration == Createability::SlotAndVariable)
|
||||
{
|
||||
m_creatableTypes[behaviorContextType] = typeProperties;
|
||||
if (m_creatableTypes.find(behaviorContextType) == m_creatableTypes.end())
|
||||
{
|
||||
m_creatableTypes[behaviorContextType] = typeProperties;
|
||||
}
|
||||
}
|
||||
else if (registration == Createability::SlotOnly)
|
||||
{
|
||||
if (m_slottableTypes.find(behaviorContextType) == m_slottableTypes.end())
|
||||
{
|
||||
m_slottableTypes[behaviorContextType] = typeProperties;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -125,4 +135,15 @@ namespace ScriptCanvas
|
||||
m_creatableTypes.erase(behaviorContextType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool DataRegistry::IsUseableInSlot(const Data::Type& scType) const
|
||||
{
|
||||
return m_creatableTypes.contains(scType) || m_slottableTypes.contains(scType);
|
||||
}
|
||||
|
||||
bool DataRegistry::IsUseableInSlot(const AZ::TypeId& typeId) const
|
||||
{
|
||||
Data::Type scType = Data::FromAZType(typeId);
|
||||
return IsUseableInSlot(scType);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,11 +34,21 @@ namespace ScriptCanvas
|
||||
AZ_TYPE_INFO(DataRegistry, "{41049FA8-EA56-401F-9720-6FE9028A1C01}");
|
||||
AZ_CLASS_ALLOCATOR(DataRegistry, AZ::SystemAllocator, 0);
|
||||
|
||||
void RegisterType(const AZ::TypeId& typeId, TypeProperties typeProperties);
|
||||
enum class Createability
|
||||
{
|
||||
None,
|
||||
SlotAndVariable,
|
||||
SlotOnly,
|
||||
};
|
||||
void RegisterType(const AZ::TypeId& typeId, TypeProperties typeProperties, Createability registration);
|
||||
void UnregisterType(const AZ::TypeId& typeId);
|
||||
|
||||
bool IsUseableInSlot(const AZ::TypeId& typeId) const;
|
||||
bool IsUseableInSlot(const Data::Type& type) const;
|
||||
|
||||
AZStd::unordered_map<Data::eType, Data::TypeErasedTraits> m_typeIdTraitMap; // Creates a mapping of the Data::eType TypeId to the trait structure
|
||||
AZStd::unordered_map<Data::Type, TypeProperties> m_creatableTypes;
|
||||
AZStd::unordered_map<Data::Type, TypeProperties> m_slottableTypes;
|
||||
};
|
||||
|
||||
void InitDataRegistry();
|
||||
|
||||
+30
-43
@@ -508,11 +508,10 @@ namespace ScriptCanvas
|
||||
const int argsCount = lua_gettop(lua);
|
||||
AZ_Assert(argsCount >= 2, "CallExecutionOut: Error in compiled Lua file, not enough arguments");
|
||||
AZ_Assert(lua_isuserdata(lua, 1), "CallExecutionOut: Error in compiled lua file, 1st argument to SetExecutionOut is not userdata (Nodeable)");
|
||||
AZ_Assert(lua_isstring(lua, 2), "CallExecutionOut: Error in compiled lua file, 2nd argument to SetExecutionOut is not a string (Crc key)");
|
||||
AZ_Assert(lua_isnumber(lua, 2), "CallExecutionOut: Error in compiled lua file, 2nd argument to SetExecutionOut is not a number");
|
||||
Nodeable* nodeable = AZ::ScriptValue<Nodeable*>::StackRead(lua, 1);
|
||||
const char* keyStr = AZ::ScriptValue<const char*>::StackRead(lua, 2);
|
||||
AZ_Assert(keyStr, "CallExecutionOut: Failed to read key string");
|
||||
nodeable->CallOut(AZ::Crc32(keyStr), nullptr, nullptr, argsCount - 2);
|
||||
size_t index = aznumeric_caster(lua_tointeger(lua, -2));
|
||||
nodeable->CallOut(index, nullptr, nullptr, argsCount - 2);
|
||||
// Lua: results...
|
||||
return lua_gettop(lua);
|
||||
}
|
||||
@@ -559,23 +558,14 @@ namespace ScriptCanvas
|
||||
int InitializeNodeableOutKeys(lua_State* lua)
|
||||
{
|
||||
using namespace ExecutionInterpretedAPICpp;
|
||||
// Lua: usernodeable, outKeys...
|
||||
// Lua: usernodeable, keyCount
|
||||
const int argsCount = lua_gettop(lua);
|
||||
AZ_Assert(argsCount >= 2, "InitializeNodeableOutKeys: Error in compiled Lua file, not enough arguments");
|
||||
AZ_Assert((argsCount - 1) < k_MaxNodeableOuts, "InitializeNodeableOutKeys: Error in compiled Lua file, too many outs for nodeable out)");
|
||||
AZ_Assert(argsCount == 2, "InitializeNodeableOutKeys: Error in compiled Lua file, not enough arguments");
|
||||
AZ_Assert(lua_isuserdata(lua, 1), "InitializeNodeableOutKeys: Error in compiled lua file, 1st argument to SetExecutionOut is not userdata (Nodeable)");
|
||||
Nodeable* nodeable = AZ::ScriptValue<Nodeable*>::StackRead(lua, 1);
|
||||
const int keyCount = argsCount - 1;
|
||||
|
||||
AZStd::array<AZ::Crc32, k_MaxNodeableOuts> keys;
|
||||
|
||||
for (int argumentIndex = 2, sentinel = argsCount + 1; argumentIndex != sentinel; ++argumentIndex)
|
||||
{
|
||||
AZ_Assert(lua_isnumber(lua, argumentIndex), "InitializeNodeableOutKeys: Error in compiled lua file, argument at Lua index #%d was not an integer", argumentIndex);
|
||||
keys[argumentIndex - 2] = static_cast<AZ::u32>(lua_tointeger(lua, argumentIndex));
|
||||
}
|
||||
|
||||
nodeable->InitializeExecutionOuts(keys.begin(), keys.begin() + keyCount);
|
||||
AZ_Assert(lua_isnumber(lua, 2), "InitializeNodeableOutKeys: Error in compiled lua file, 2nd argument was not an integer");
|
||||
const size_t keyCount = aznumeric_caster(lua_tointeger(lua, 2));
|
||||
nodeable->InitializeExecutionOuts(keyCount);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -595,19 +585,18 @@ namespace ScriptCanvas
|
||||
// \see https://jira.agscollab.com/browse/LY-99750
|
||||
|
||||
AZ_Assert(lua_isuserdata(lua, -3), "Error in compiled lua file, 1st argument to SetExecutionOut is not userdata (Nodeable)");
|
||||
AZ_Assert(lua_isstring(lua, -2), "Error in compiled lua file, 2nd argument to SetExecutionOut is not a string (Crc key)");
|
||||
AZ_Assert(lua_isnumber(lua, -2), "Error in compiled lua file, 2nd argument to SetExecutionOut is not a number");
|
||||
AZ_Assert(lua_isfunction(lua, -1), "Error in compiled lua file, 3rd argument to SetExecutionOut is not a function (lambda need to get around atypically routed arguments)");
|
||||
Nodeable* nodeable = AZ::ScriptValue<Nodeable*>::StackRead(lua, -3);
|
||||
AZ_Assert(nodeable, "Failed to read nodeable");
|
||||
const char* keyStr = AZ::ScriptValue<const char*>::StackRead(lua, -2);
|
||||
AZ_Assert(keyStr, "Failed to read key string");
|
||||
// Lua: nodeable, string, lambda
|
||||
size_t index = aznumeric_caster(lua_tointeger(lua, -2));
|
||||
// Lua: nodeable, index, lambda
|
||||
|
||||
lua_pushvalue(lua, -1);
|
||||
// Lua: nodeable, string, lambda, lambda
|
||||
// Lua: nodeable, index, lambda, lambda
|
||||
|
||||
nodeable->SetExecutionOut(AZ::Crc32(keyStr), OutInterpreted(lua));
|
||||
// Lua: nodeable, string, lambda
|
||||
nodeable->SetExecutionOut(index, OutInterpreted(lua));
|
||||
// Lua: nodeable, index, lambda
|
||||
|
||||
// \todo clear these immediately after they are not needed with an explicit call written by the translator
|
||||
return 0;
|
||||
@@ -618,20 +607,19 @@ namespace ScriptCanvas
|
||||
// \note Return values could become necessary.
|
||||
// \see https://jira.agscollab.com/browse/LY-99750
|
||||
|
||||
AZ_Assert(lua_isuserdata(lua, -3), "Error in compiled lua file, 1st argument to SetExecutionOut is not userdata (Nodeable)");
|
||||
AZ_Assert(lua_isstring(lua, -2), "Error in compiled lua file, 2nd argument to SetExecutionOut is not a string (Crc key)");
|
||||
AZ_Assert(lua_isfunction(lua, -1), "Error in compiled lua file, 3rd argument to SetExecutionOut is not a function (lambda need to get around atypically routed arguments)");
|
||||
AZ_Assert(lua_isuserdata(lua, -3), "Error in compiled lua file, 1st argument to SetExecutionOutResult is not userdata (Nodeable)");
|
||||
AZ_Assert(lua_isnumber(lua, -2), "Error in compiled lua file, 2nd argument to SetExecutionOutResult is not a number");
|
||||
AZ_Assert(lua_isfunction(lua, -1), "Error in compiled lua file, 3rd argument to SetExecutionOutResult is not a function (lambda need to get around atypically routed arguments)");
|
||||
Nodeable* nodeable = AZ::ScriptValue<Nodeable*>::StackRead(lua, -3); // this won't be a BCO, because BCOs won't be necessary in the interpreted mode...most likely
|
||||
AZ_Assert(nodeable, "Failed to read nodeable");
|
||||
const char* keyStr = AZ::ScriptValue<const char*>::StackRead(lua, -2);
|
||||
AZ_Assert(keyStr, "Failed to read key string");
|
||||
// Lua: nodeable, string, lambda
|
||||
size_t index = aznumeric_caster(lua_tointeger(lua, -2));
|
||||
// Lua: nodeable, index, lambda
|
||||
|
||||
lua_pushvalue(lua, -1);
|
||||
// Lua: nodeable, string, lambda, lambda
|
||||
// Lua: nodeable, index, lambda, lambda
|
||||
|
||||
nodeable->SetExecutionOut(AZ::Crc32(keyStr), OutInterpretedResult(lua));
|
||||
// Lua: nodeable, string, lambda
|
||||
nodeable->SetExecutionOut(index, OutInterpretedResult(lua));
|
||||
// Lua: nodeable, index, lambda
|
||||
|
||||
// \todo clear these immediately after they are not needed with an explicit call written by the translator
|
||||
return 0;
|
||||
@@ -639,20 +627,19 @@ namespace ScriptCanvas
|
||||
|
||||
int SetExecutionOutUserSubgraph(lua_State* lua)
|
||||
{
|
||||
AZ_Assert(lua_isuserdata(lua, -3), "Error in compiled lua file, 1st argument to SetExecutionOut is not userdata (Nodeable)");
|
||||
AZ_Assert(lua_isstring(lua, -2), "Error in compiled lua file, 2nd argument to SetExecutionOut is not a string (Crc key)");
|
||||
AZ_Assert(lua_isfunction(lua, -1), "Error in compiled lua file, 3rd argument to SetExecutionOut is not a function (lambda need to get around atypically routed arguments)");
|
||||
AZ_Assert(lua_isuserdata(lua, -3), "Error in compiled lua file, 1st argument to SetExecutionOutUserSubgraph is not userdata (Nodeable)");
|
||||
AZ_Assert(lua_isnumber(lua, -2), "Error in compiled lua file, 2nd argument to SetExecutionOutUserSubgraph is not a number");
|
||||
AZ_Assert(lua_isfunction(lua, -1), "Error in compiled lua file, 3rd argument to SetExecutionOutUserSubgraph is not a function (lambda need to get around atypically routed arguments)");
|
||||
Nodeable* nodeable = AZ::ScriptValue<Nodeable*>::StackRead(lua, -3);
|
||||
AZ_Assert(nodeable, "Failed to read nodeable");
|
||||
const char* keyStr = AZ::ScriptValue<const char*>::StackRead(lua, -2);
|
||||
AZ_Assert(keyStr, "Failed to read key string");
|
||||
// Lua: nodeable, string, lambda
|
||||
size_t index = aznumeric_caster(lua_tointeger(lua, -2));
|
||||
// Lua: nodeable, index, lambda
|
||||
|
||||
lua_pushvalue(lua, -1);
|
||||
// Lua: nodeable, string, lambda, lambda
|
||||
// Lua: nodeable, index, lambda, lambda
|
||||
|
||||
nodeable->SetExecutionOut(AZ::Crc32(keyStr), OutInterpretedUserSubgraph(lua));
|
||||
// Lua: nodeable, string, lambda
|
||||
nodeable->SetExecutionOut(index, OutInterpretedUserSubgraph(lua));
|
||||
// Lua: nodeable, index, lambda
|
||||
|
||||
// \todo clear these immediately after they are not needed with an explicit call written by the translator
|
||||
return 0;
|
||||
|
||||
+14
-21
@@ -83,7 +83,7 @@ namespace ScriptCanvas
|
||||
|
||||
int EBusHandlerCreateAndConnectTo(lua_State* lua)
|
||||
{
|
||||
// Lua: executionState, (event name) string, (address aztypeid) string, (address) ?
|
||||
// Lua: executionState, (ebus name) string, (address aztypeid) string, (address) ?
|
||||
auto executionState = AZ::ScriptValue<ExecutionStateInterpreted*>::StackRead(lua, 1);
|
||||
auto ebusName = AZ::ScriptValue<const char*>::StackRead(lua, 2);
|
||||
EBusHandler* ebusHandler = aznew EBusHandler(executionState->WeakFromThis(), ebusName, AZ::ScriptContext::FromNativeContext(lua)->GetBoundContext());
|
||||
@@ -96,7 +96,7 @@ namespace ScriptCanvas
|
||||
ebusHandler->ConnectTo(address);
|
||||
|
||||
AZ::Internal::LuaClassToStack(lua, ebusHandler, azrtti_typeid<EBusHandler>(), AZ::ObjectToLua::ByReference, AZ::AcquisitionOnPush::ScriptAcquire);
|
||||
// Lua: executionState, (event name) string, (address aztypeid) string, (address) ?, handler
|
||||
// Lua: executionState, (ebus name) string, (address aztypeid) string, (address) ?, handler
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -114,27 +114,23 @@ namespace ScriptCanvas
|
||||
const int k_eventNameIndex = -2;
|
||||
const int k_lambdaIndex = -1;
|
||||
|
||||
AZ_Assert(lua_isuserdata(lua, k_nodeableIndex), "Error in compiled lua file, 1st argument to SetExecutionOut is not userdata (Nodeable)");
|
||||
AZ_Assert(lua_isstring(lua, k_eventNameIndex), "Error in compiled lua file, 2nd argument to SetExecutionOut is not a string (Crc key)");
|
||||
AZ_Assert(lua_isfunction(lua, k_lambdaIndex), "Error in compiled lua file, 3rd argument to SetExecutionOut is not a function (lambda need to get around atypically routed arguments)");
|
||||
AZ_Assert(lua_isuserdata(lua, k_nodeableIndex), "Error in compiled lua file, 1st argument to EBusHandlerHandleEvent is not userdata (EBusHandler)");
|
||||
AZ_Assert(lua_isnumber(lua, k_eventNameIndex), "Error in compiled lua file, 2nd argument to EBusHandlerHandleEvent is not a number");
|
||||
AZ_Assert(lua_isfunction(lua, k_lambdaIndex), "Error in compiled lua file, 3rd argument to EBusHandlerHandleEvent is not a function");
|
||||
|
||||
auto nodeable = AZ::ScriptValue<EBusHandler*>::StackRead(lua, k_nodeableIndex); // this won't be a BCO, because BCOs won't be necessary in the interpreted mode...most likely
|
||||
auto nodeable = AZ::ScriptValue<EBusHandler*>::StackRead(lua, k_nodeableIndex);
|
||||
AZ_Assert(nodeable, "Failed to read EBusHandler");
|
||||
const char* keyStr = lua_tostring(lua, k_eventNameIndex);
|
||||
AZ_Assert(keyStr, "Failed to read key string");
|
||||
const int eventIndex = nodeable->GetEventIndex(keyStr);
|
||||
AZ_Assert(eventIndex != -1, "Event index was not found for %s-%s", nodeable->GetEBusName().data(), keyStr);
|
||||
const int eventIndex = lua_tointeger(lua, k_eventNameIndex);
|
||||
AZ_Assert(eventIndex != -1, "Event index was not found for %s", nodeable->GetEBusName().data());
|
||||
// install the generic hook for the event
|
||||
nodeable->HandleEvent(eventIndex);
|
||||
// Lua: nodeable, string, lambda
|
||||
|
||||
lua_pushvalue(lua, k_lambdaIndex);
|
||||
// Lua: nodeable, string, lambda, lambda
|
||||
|
||||
// route the event handling to the lambda on the top of the stack
|
||||
nodeable->SetExecutionOut(AZ::Crc32(eventIndex), OutInterpreted(lua));
|
||||
// Lua: nodeable, string, lambda
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -145,16 +141,14 @@ namespace ScriptCanvas
|
||||
const int k_eventNameIndex = -2;
|
||||
const int k_lambdaIndex = -1;
|
||||
|
||||
AZ_Assert(lua_isuserdata(lua, k_nodeableIndex), "Error in compiled lua file, 1st argument to SetExecutionOut is not userdata (Nodeable)");
|
||||
AZ_Assert(lua_isstring(lua, k_eventNameIndex), "Error in compiled lua file, 2nd argument to SetExecutionOut is not a string (Crc key)");
|
||||
AZ_Assert(lua_isfunction(lua, k_lambdaIndex), "Error in compiled lua file, 3rd argument to SetExecutionOut is not a function (lambda need to get around atypically routed arguments)");
|
||||
AZ_Assert(lua_isuserdata(lua, k_nodeableIndex), "Error in compiled lua file, 1st argument to EBusHandlerHandleEventResult is not userdata (EBusHandler)");
|
||||
AZ_Assert(lua_isnumber(lua, k_eventNameIndex), "Error in compiled lua file, 2nd argument to EBusHandlerHandleEventResult is not a number");
|
||||
AZ_Assert(lua_isfunction(lua, k_lambdaIndex), "Error in compiled lua file, 3rd argument to EBusHandlerHandleEventResult is not a function");
|
||||
|
||||
auto nodeable = AZ::ScriptValue<EBusHandler*>::StackRead(lua, k_nodeableIndex); // this won't be a BCO, because BCOs won't be necessary in the interpreted mode...most likely
|
||||
auto nodeable = AZ::ScriptValue<EBusHandler*>::StackRead(lua, k_nodeableIndex);
|
||||
AZ_Assert(nodeable, "Failed to read EBusHandler");
|
||||
const char* keyStr = lua_tostring(lua, k_eventNameIndex);
|
||||
AZ_Assert(keyStr, "Failed to read key string");
|
||||
const int eventIndex = nodeable->GetEventIndex(keyStr);
|
||||
AZ_Assert(eventIndex != -1, "Event index was not found for %s-%s", nodeable->GetEBusName().data(), keyStr);
|
||||
const int eventIndex = lua_tointeger(lua, k_eventNameIndex);
|
||||
AZ_Assert(eventIndex != -1, "Event index was not found for %s", nodeable->GetEBusName().data());
|
||||
// install the generic hook for the event
|
||||
nodeable->HandleEvent(eventIndex);
|
||||
// Lua: nodeable, string, lambda
|
||||
@@ -165,7 +159,6 @@ namespace ScriptCanvas
|
||||
// route the event handling to the lambda on the top of the stack
|
||||
nodeable->SetExecutionOut(AZ::Crc32(eventIndex), OutInterpretedResult(lua));
|
||||
// Lua: nodeable, string, lambda
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@ namespace ScriptCanvas
|
||||
|
||||
void RuntimeComponent::Execute()
|
||||
{
|
||||
AZ_PROFILE_SCOPE_DYNAMIC(AZ::Debug::ProfileCategory::ScriptCanvas, "RuntimeComponent::InitializeExecution (%s)", m_runtimeAsset.GetId().ToString<AZStd::string>().c_str());
|
||||
AZ_PROFILE_SCOPE_DYNAMIC(AZ::Debug::ProfileCategory::ScriptCanvas, "RuntimeComponent::Execute (%s)", m_runtimeAsset.GetId().ToString<AZStd::string>().c_str());
|
||||
AZ_Assert(m_executionState, "RuntimeComponent::Execute called without an execution state");
|
||||
SC_EXECUTION_TRACE_GRAPH_ACTIVATED(CreateActivationInfo());
|
||||
SCRIPT_CANVAS_PERFORMANCE_SCOPE_EXECUTION(m_executionState->GetScriptCanvasId(), m_runtimeAsset.GetId());
|
||||
|
||||
@@ -434,7 +434,7 @@ namespace ScriptCanvas
|
||||
|
||||
if (!root->HasExplicitUserOutCalls())
|
||||
{
|
||||
// there is a single out call, default or not
|
||||
// there is a single out, default or not
|
||||
Out out;
|
||||
|
||||
if (outCalls.empty())
|
||||
@@ -468,9 +468,7 @@ namespace ScriptCanvas
|
||||
}
|
||||
else
|
||||
{
|
||||
// for now, all outs must return all the same output,
|
||||
// if the UI changes, we'll need to track the output of each individual output
|
||||
if (outCalls.empty())
|
||||
if (outCalls.size() < 2)
|
||||
{
|
||||
AddError(root->GetNodeId(), root, ScriptCanvas::ParseErrors::NotEnoughBranchesForReturn);
|
||||
return;
|
||||
@@ -503,6 +501,9 @@ namespace ScriptCanvas
|
||||
, returnValueVariable->m_sourceVariableId });
|
||||
}
|
||||
|
||||
AZStd::const_pointer_cast<ExecutionTree>(outCall)->SetOutCallIndex(m_outIndexCount);
|
||||
++m_outIndexCount;
|
||||
|
||||
in.outs.push_back(AZStd::move(out));
|
||||
}
|
||||
}
|
||||
@@ -543,6 +544,8 @@ namespace ScriptCanvas
|
||||
, returnValueVariable->m_sourceVariableId });
|
||||
}
|
||||
|
||||
AZStd::const_pointer_cast<ExecutionTree>(outCall)->SetOutCallIndex(m_outIndexCount);
|
||||
++m_outIndexCount;
|
||||
m_subgraphInterface.AddLatent(AZStd::move(out));
|
||||
}
|
||||
|
||||
@@ -908,6 +911,7 @@ namespace ScriptCanvas
|
||||
ebusHandling->m_startingAdress = startingAddress;
|
||||
}
|
||||
|
||||
ebusHandling->m_node = &node;
|
||||
m_ebusHandlingByNode.emplace(&node, ebusHandling);
|
||||
return true;
|
||||
}
|
||||
@@ -3252,6 +3256,15 @@ namespace ScriptCanvas
|
||||
AZ_Assert(childOutSlot, "null slot in child out slot list");
|
||||
ExecutionTreePtr internalOut = OpenScope(child, node, childOutSlot);
|
||||
internalOut->SetNodeable(execution->GetNodeable());
|
||||
|
||||
const size_t outIndex = node->GetOutIndex(*childOutSlot);
|
||||
if (outIndex == std::numeric_limits<size_t>::max())
|
||||
{
|
||||
AddError(execution, aznew Internal::ParseError(node->GetEntityId(), AZStd::string::format("Missing internal out key for slot %s", childOutSlot->GetName().c_str())));
|
||||
return;
|
||||
}
|
||||
|
||||
internalOut->SetOutCallIndex(outIndex);
|
||||
internalOut->MarkInternalOut();
|
||||
internalOut->SetSymbol(Symbol::FunctionDefinition);
|
||||
auto outNameOutcome = node->GetInternalOutKey(*childOutSlot);
|
||||
@@ -3893,6 +3906,14 @@ namespace ScriptCanvas
|
||||
auto latentOutKeyOutcome = node.GetLatentOutKey(*slot);
|
||||
if (latentOutKeyOutcome.IsSuccess())
|
||||
{
|
||||
const size_t outIndex = node.GetOutIndex(*slot);
|
||||
if (outIndex == std::numeric_limits<size_t>::max())
|
||||
{
|
||||
AddError(outRoot, aznew Internal::ParseError(node.GetEntityId(), AZStd::string::format("Missing internal out key for slot %s", slot->GetName().c_str())));
|
||||
return;
|
||||
}
|
||||
|
||||
outRoot->SetOutCallIndex(outIndex);
|
||||
outRoot->SetName(latentOutKeyOutcome.GetValue().data());
|
||||
AZStd::const_pointer_cast<NodeableParse>(nodeableParseIter->second)->m_latents.emplace_back(outRoot->GetName(), outRoot);
|
||||
}
|
||||
@@ -4622,7 +4643,13 @@ namespace ScriptCanvas
|
||||
m_userInsThatRequireTopology.clear();
|
||||
|
||||
ParseUserOuts();
|
||||
m_subgraphInterface.Parse();
|
||||
|
||||
auto parseOutcome = m_subgraphInterface.Parse();
|
||||
|
||||
if (!parseOutcome.IsSuccess())
|
||||
{
|
||||
AddError(nullptr, aznew Internal::ParseError(AZ::EntityId(), AZStd::string::format("Subgraph interface failed to parse: %s", parseOutcome.GetError().c_str()).c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
void AbstractCodeModel::ParseUserIn(ExecutionTreePtr root, const Nodes::Core::FunctionDefinitionNode* nodeling)
|
||||
|
||||
@@ -507,6 +507,7 @@ namespace ScriptCanvas
|
||||
|
||||
static UserInParseTopologyResult ParseUserInTolopology(size_t nodelingsOutCount, size_t leavesWithoutNodelingsCount);
|
||||
|
||||
size_t m_outIndexCount = 0;
|
||||
ExecutionTreePtr m_start;
|
||||
AZStd::vector<const Nodes::Core::Start*> m_startNodes;
|
||||
ScopePtr m_graphScope;
|
||||
|
||||
@@ -1057,6 +1057,13 @@ namespace ScriptCanvas
|
||||
&& azrtti_istypeof<const ScriptCanvas::Nodes::Core::FunctionCallNode*>(execution->GetId().m_node);
|
||||
}
|
||||
|
||||
bool IsUserFunctionCallPure(const ExecutionTreeConstPtr& execution)
|
||||
{
|
||||
return (execution->GetSymbol() == Symbol::FunctionCall)
|
||||
&& azrtti_istypeof<const ScriptCanvas::Nodes::Core::FunctionCallNode*>(execution->GetId().m_node)
|
||||
&& azrtti_cast<const ScriptCanvas::Nodes::Core::FunctionCallNode*>(execution->GetId().m_node)->IsPure();
|
||||
}
|
||||
|
||||
bool IsUserFunctionDefinition(const ExecutionTreeConstPtr& execution)
|
||||
{
|
||||
auto nodeling = azrtti_cast<const ScriptCanvas::Nodes::Core::FunctionDefinitionNode*>(execution->GetId().m_node);
|
||||
|
||||
@@ -163,6 +163,8 @@ namespace ScriptCanvas
|
||||
|
||||
bool IsUserFunctionCall(const ExecutionTreeConstPtr& execution);
|
||||
|
||||
bool IsUserFunctionCallPure(const ExecutionTreeConstPtr& execution);
|
||||
|
||||
bool IsUserFunctionDefinition(const ExecutionTreeConstPtr& execution);
|
||||
|
||||
const ScriptCanvas::Nodes::Core::FunctionDefinitionNode* IsUserOutNode(const Node* node);
|
||||
|
||||
@@ -90,11 +90,11 @@ namespace ScriptCanvas
|
||||
AZ_CLASS_ALLOCATOR(EBusHandling, AZ::SystemAllocator, 0);
|
||||
|
||||
bool m_isAddressed = false;
|
||||
const Node* m_node = nullptr;
|
||||
VariableConstPtr m_startingAdress;
|
||||
AZStd::string m_ebusName;
|
||||
AZStd::string m_handlerName;
|
||||
AZStd::vector<AZStd::pair<AZStd::string, ExecutionTreeConstPtr>> m_events;
|
||||
|
||||
void Clear();
|
||||
};
|
||||
|
||||
|
||||
@@ -110,7 +110,7 @@ namespace ScriptCanvas
|
||||
|
||||
constexpr const char* k_InitializeStaticsName = "InitializeStatics";
|
||||
constexpr const char* k_InitializeNodeableOutKeys = "InitializeNodeableOutKeys";
|
||||
|
||||
constexpr const char* k_InitializeExecutionOutByRequiredCountName = "InitializeExecutionOutByRequiredCount";
|
||||
constexpr const char* k_InterpretedConfigurationPerformance = "SCRIPT_CANVAS_GLOBAL_PERFORMANCE";
|
||||
constexpr const char* k_InterpretedConfigurationRelease = "SCRIPT_CANVAS_GLOBAL_RELEASE";
|
||||
|
||||
|
||||
@@ -260,6 +260,11 @@ namespace ScriptCanvas
|
||||
return m_nodeable;
|
||||
}
|
||||
|
||||
AZStd::optional<size_t> ExecutionTree::GetOutCallIndex() const
|
||||
{
|
||||
return m_outCallIndex != std::numeric_limits<size_t>::max() ? AZStd::optional<size_t>(m_outCallIndex) : AZStd::nullopt;
|
||||
}
|
||||
|
||||
ExecutionTreeConstPtr ExecutionTree::GetParent() const
|
||||
{
|
||||
return m_parent;
|
||||
@@ -559,6 +564,11 @@ namespace ScriptCanvas
|
||||
m_lexicalScope = lexicalScope;
|
||||
}
|
||||
|
||||
void ExecutionTree::SetOutCallIndex(size_t index)
|
||||
{
|
||||
m_outCallIndex = index;
|
||||
}
|
||||
|
||||
void ExecutionTree::SetParent(ExecutionTreePtr parent)
|
||||
{
|
||||
m_parent = parent;
|
||||
|
||||
@@ -170,6 +170,8 @@ namespace ScriptCanvas
|
||||
|
||||
VariableConstPtr GetNodeable() const;
|
||||
|
||||
AZStd::optional<size_t> GetOutCallIndex() const;
|
||||
|
||||
ExecutionTreeConstPtr GetParent() const;
|
||||
|
||||
ExecutionTreeConstPtr GetRoot() const;
|
||||
@@ -252,6 +254,8 @@ namespace ScriptCanvas
|
||||
|
||||
void SetNodeable(VariableConstPtr nodeable);
|
||||
|
||||
void SetOutCallIndex(size_t index);
|
||||
|
||||
void SetParent(ExecutionTreePtr parent);
|
||||
|
||||
void SetScope(ScopePtr scope);
|
||||
@@ -286,6 +290,8 @@ namespace ScriptCanvas
|
||||
|
||||
bool m_hasExplicitUserOutCalls = false;
|
||||
|
||||
size_t m_outCallIndex = std::numeric_limits<size_t>::max();
|
||||
|
||||
// The node and the activation slot. The execution in, or the event or latent out slot.
|
||||
ExecutionId m_in;
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ namespace ScriptCanvas
|
||||
break;
|
||||
}
|
||||
|
||||
while (m_timerCounter > m_timerDuration)
|
||||
while (m_timerCounter >= m_timerDuration)
|
||||
{
|
||||
if (!m_isActive)
|
||||
{
|
||||
|
||||
@@ -393,6 +393,11 @@ namespace ScriptCanvas
|
||||
return false;
|
||||
}
|
||||
|
||||
AZStd::optional<size_t> EBusEventHandler::GetEventIndex(AZStd::string eventName) const
|
||||
{
|
||||
return m_handler->GetFunctionIndex(eventName.c_str());
|
||||
}
|
||||
|
||||
const EBusEventEntry* EBusEventHandler::FindEvent(const AZStd::string& name) const
|
||||
{
|
||||
AZ::Crc32 key = AZ::Crc32(name.c_str());
|
||||
|
||||
@@ -115,6 +115,7 @@ namespace ScriptCanvas
|
||||
|
||||
AZ::Outcome<AZStd::string, void> GetFunctionCallName(const Slot* /*slot*/) const override;
|
||||
bool IsEBusAddressed() const override;
|
||||
AZStd::optional<size_t> GetEventIndex(AZStd::string eventName) const;
|
||||
const EBusEventEntry* FindEvent(const AZStd::string& name) const;
|
||||
AZStd::string GetEBusName() const override;
|
||||
bool IsAutoConnected() const override;
|
||||
|
||||
@@ -548,6 +548,11 @@ namespace ScriptCanvas
|
||||
return EBusEventHandlerProperty::GetDisconnectSlot(this);
|
||||
}
|
||||
|
||||
AZStd::optional<size_t> ReceiveScriptEvent::GetEventIndex(AZStd::string eventName) const
|
||||
{
|
||||
return m_handler->GetFunctionIndex(eventName.c_str());;
|
||||
}
|
||||
|
||||
AZStd::vector<SlotId> ReceiveScriptEvent::GetEventSlotIds() const
|
||||
{
|
||||
AZStd::vector<SlotId> eventSlotIds;
|
||||
|
||||
@@ -57,6 +57,7 @@ namespace ScriptCanvas
|
||||
AZ::Outcome<AZStd::string> GetInternalOutKey(const Slot& slot) const override;
|
||||
const Slot* GetEBusConnectSlot() const override;
|
||||
const Slot* GetEBusDisconnectSlot() const override;
|
||||
AZStd::optional<size_t> GetEventIndex(AZStd::string eventName) const override;
|
||||
AZStd::vector<SlotId> GetEventSlotIds() const override;
|
||||
AZStd::vector<SlotId> GetNonEventSlotIds() const override;
|
||||
|
||||
|
||||
+7
-2
@@ -136,16 +136,21 @@ namespace ScriptCanvas
|
||||
}
|
||||
|
||||
protected:
|
||||
size_t GetRequiredOutCount() const override
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
void Lerp(float t)
|
||||
{
|
||||
const t_Operand step = m_start + (m_difference * t);
|
||||
// make a release note that the lerp complete and tick slot are two different execution threads
|
||||
ExecutionOut(AZ_CRC_CE("Tick"), step, t);
|
||||
ExecutionOut(0, step, t);
|
||||
|
||||
if (AZ::IsClose(t, 1.0f, AZ::Constants::FloatEpsilon))
|
||||
{
|
||||
StopLerp();
|
||||
ExecutionOut(AZ_CRC_CE("Lerp Complete"));
|
||||
ExecutionOut(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <ScriptCanvas/Core/ScriptCanvasBus.h>
|
||||
#include <ScriptCanvas/Variable/VariableCore.h>
|
||||
#include <ScriptCanvas/PerformanceTracker.h>
|
||||
#include <ScriptCanvas/Data/DataRegistry.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
@@ -65,6 +66,8 @@ namespace ScriptCanvas
|
||||
|
||||
inline bool IsAnyScriptInterpreted() const { return true; }
|
||||
|
||||
AZStd::pair<DataRegistry::Createability, TypeProperties> GetCreatibility(AZ::SerializeContext* serializeContext, AZ::BehaviorClass* behaviorClass);
|
||||
|
||||
// SystemRequestBus::Handler...
|
||||
bool IsScriptUnitTestingInProgress() override;
|
||||
void MarkScriptUnitTestBegin() override;
|
||||
@@ -100,7 +103,7 @@ namespace ScriptCanvas
|
||||
using LockType = AZStd::lock_guard<MutexType>;
|
||||
AZStd::unordered_map<const void*, BehaviorContextObject*> m_ownedObjectsByAddress;
|
||||
MutexType m_ownedObjectsByAddressMutex;
|
||||
int m_infiniteLoopDetectionMaxIterations = 3000;
|
||||
int m_infiniteLoopDetectionMaxIterations = 1000000;
|
||||
int m_maxHandlerStackDepth = 50;
|
||||
|
||||
static void SafeRegisterPerformanceTracker();
|
||||
|
||||
@@ -689,8 +689,16 @@ namespace ScriptCanvas
|
||||
|
||||
void GraphToLua::TranslateExecutionTreeUserOutCall(Grammar::ExecutionTreeConstPtr execution)
|
||||
{
|
||||
// \todo revisit with per-entity run time storage that keeps execution out calls
|
||||
m_dotLua.WriteIndented("%s(self, \"%s\"", Grammar::k_NodeableCallInterpretedOut, execution->GetName().data());
|
||||
auto outCallIndexOptional = execution->GetOutCallIndex();
|
||||
if (!outCallIndexOptional)
|
||||
{
|
||||
AddError(nullptr, aznew Internal::ParseError(execution->GetNodeId(), "Execution did not return required out call index"));
|
||||
return;
|
||||
}
|
||||
|
||||
const size_t outIndex = *outCallIndexOptional;
|
||||
|
||||
m_dotLua.WriteIndented("%s(self, %zu", Grammar::k_NodeableCallInterpretedOut, outIndex);
|
||||
|
||||
if (execution->GetInputCount() > 0)
|
||||
{
|
||||
@@ -698,7 +706,7 @@ namespace ScriptCanvas
|
||||
WriteFunctionCallInput(execution);
|
||||
}
|
||||
|
||||
m_dotLua.WriteLine(")");
|
||||
m_dotLua.WriteLine(") -- %s", execution->GetName().data());
|
||||
}
|
||||
|
||||
void GraphToLua::TranslateFunction(Grammar::ExecutionTreeConstPtr execution, IsNamed lex)
|
||||
@@ -861,14 +869,23 @@ namespace ScriptCanvas
|
||||
|
||||
const bool hasResults = eventThread->HasReturnValues();
|
||||
|
||||
AZStd::optional<size_t> eventIndex = ebusHandling->m_node->GetEventIndex(nameAndEventThread.first);
|
||||
if (!eventIndex)
|
||||
{
|
||||
AddError(nullptr, aznew Internal::ParseError(ebusHandling->m_node->GetEntityId(), AZStd::string::format("EBus handler did not return a valid index for event %s", nameAndEventThread.first.c_str())));
|
||||
return;
|
||||
}
|
||||
|
||||
m_dotLua.WriteNewLine();
|
||||
m_dotLua.WriteLineIndented("%s(%s%s, '%s',"
|
||||
m_dotLua.WriteLineIndented("%s(%s%s, %zu, -- %s"
|
||||
, hasResults ? Grammar::k_EBusHandlerHandleEventResultName : Grammar::k_EBusHandlerHandleEventName
|
||||
, leftValue.data()
|
||||
, ebusHandling->m_handlerName.data()
|
||||
, *eventIndex
|
||||
, eventThread->GetName().data());
|
||||
|
||||
m_dotLua.Indent();
|
||||
|
||||
TranslateFunction(eventThread, IsNamed::No);
|
||||
m_dotLua.WriteLine(")");
|
||||
|
||||
@@ -983,14 +1000,7 @@ namespace ScriptCanvas
|
||||
const auto& outKeys = m_model.GetInterface().GetOutKeys();
|
||||
if (!outKeys.empty())
|
||||
{
|
||||
m_dotLua.WriteIndented("%s(self", Grammar::k_InitializeNodeableOutKeys);
|
||||
|
||||
for (auto& key : outKeys)
|
||||
{
|
||||
m_dotLua.Write(", %u", AZ::u32(key));
|
||||
}
|
||||
|
||||
m_dotLua.WriteLine(")");
|
||||
m_dotLua.WriteLineIndented("%s(self, %zu)", Grammar::k_InitializeNodeableOutKeys, outKeys.size());
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1009,15 +1019,26 @@ namespace ScriptCanvas
|
||||
|
||||
void GraphToLua::TranslateNodeableOut(Grammar::ExecutionTreeConstPtr execution)
|
||||
{
|
||||
auto outCallIndexOptional = execution->GetOutCallIndex();
|
||||
if (!outCallIndexOptional)
|
||||
{
|
||||
AddError(nullptr, aznew Internal::ParseError(execution->GetNodeId(), "Execution did not return required out call index"));
|
||||
return;
|
||||
}
|
||||
|
||||
const size_t outIndex = *outCallIndexOptional;
|
||||
|
||||
// #functions2 remove-execution-out-hash
|
||||
const auto setExecutionOutName = Grammar::IsUserFunctionDefinition(execution)
|
||||
? Grammar::k_NodeableSetExecutionOutUserSubgraphName
|
||||
: execution->HasReturnValues()
|
||||
? Grammar::k_NodeableSetExecutionOutResultName
|
||||
: Grammar::k_NodeableSetExecutionOutName;
|
||||
|
||||
m_dotLua.WriteLineIndented("%s(self.%s, '%s',"
|
||||
m_dotLua.WriteLineIndented("%s(self.%s, %zu, -- %s"
|
||||
, setExecutionOutName
|
||||
, execution->GetNodeable()->m_name.data()
|
||||
, execution->GetNodeable()->m_name.data()
|
||||
, outIndex
|
||||
, execution->GetName().data());
|
||||
|
||||
m_dotLua.Indent();
|
||||
@@ -1050,7 +1071,6 @@ namespace ScriptCanvas
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
m_dotLua.WriteIndented("function %s.%s(self, ", m_tableName.c_str(), Grammar::k_InitializeStaticsName);
|
||||
WriteStaticInitializerInput(IsLeadingCommaRequired::No);
|
||||
m_dotLua.WriteLine(")");
|
||||
@@ -1078,7 +1098,7 @@ namespace ScriptCanvas
|
||||
continue;
|
||||
}
|
||||
|
||||
if (variable->m_datum.GetType().GetAZType() == azrtti_typeid<Nodeable>())
|
||||
if (m_model.IsUserNodeable(variable))
|
||||
{
|
||||
auto nodeableName = variable->m_name;
|
||||
if (nodeableName.starts_with(Grammar::k_memberNamePrefix))
|
||||
@@ -1104,7 +1124,7 @@ namespace ScriptCanvas
|
||||
// indexInfo->second.requiresCtorParamsForDependencies
|
||||
// self.nonLeafDependency = NonLeafDependency.new(executionState, UnpackDependencyArgs(executionState, dependentAssets, 7))
|
||||
// -- has more dependencies, index, known from compile time, pushes the correct asset further down construction
|
||||
m_dotLua.WriteLineIndented("%s%s = %s.new(%s, %s(%s, %s, %s))"
|
||||
m_dotLua.WriteLineIndented("%s%s = %s.new(%s, %s(%s, %s, %zu))"
|
||||
, leftValue.data()
|
||||
, variable->m_name.data()
|
||||
, nodeableName.data()
|
||||
@@ -1112,7 +1132,7 @@ namespace ScriptCanvas
|
||||
, Grammar::k_UnpackDependencyConstructionArgsFunctionName
|
||||
, Grammar::k_executionStateVariableName
|
||||
, Grammar::k_DependentAssetsArgName
|
||||
, AZStd::to_string(indexInfo->first).data());
|
||||
, indexInfo->first);
|
||||
|
||||
}
|
||||
else // vs.
|
||||
@@ -1120,7 +1140,7 @@ namespace ScriptCanvas
|
||||
// !indexInfo->second.hasMoreDependencies
|
||||
// self.leafDependency = LeafDependency.new(executionState, UnpackDependencyArgsLeaf(executionState, dependentAssets, 10))
|
||||
// -- has NO more dependencies, index, known from compile time
|
||||
m_dotLua.WriteLineIndented("%s%s = %s.new(%s, %s(%s, %s, %s))"
|
||||
m_dotLua.WriteLineIndented("%s%s = %s.new(%s, %s(%s, %s, %zu))"
|
||||
, leftValue.data()
|
||||
, variable->m_name.data()
|
||||
, nodeableName.data()
|
||||
@@ -1128,7 +1148,7 @@ namespace ScriptCanvas
|
||||
, Grammar::k_UnpackDependencyConstructionArgsLeafFunctionName
|
||||
, Grammar::k_executionStateVariableName
|
||||
, Grammar::k_DependentAssetsArgName
|
||||
, AZStd::to_string(indexInfo->first).data());
|
||||
, indexInfo->first);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1158,6 +1178,7 @@ namespace ScriptCanvas
|
||||
|
||||
case Grammar::VariableConstructionRequirement::InputNodeable:
|
||||
m_dotLua.WriteLineIndented("%s:InitializeExecutionState(%s)", variable->m_name.data(), Grammar::k_executionStateVariableName);
|
||||
m_dotLua.WriteLineIndented("%s:%s()", variable->m_name.c_str(), Grammar::k_InitializeExecutionOutByRequiredCountName);
|
||||
m_dotLua.WriteLineIndented("%s%s = %s", leftValue.data(), variable->m_name.data(), variable->m_name.data());
|
||||
break;
|
||||
|
||||
@@ -1227,9 +1248,7 @@ namespace ScriptCanvas
|
||||
|
||||
void GraphToLua::WriteConstructionDependencyArgs()
|
||||
{
|
||||
auto& dependencyArgs = m_model.GetOrderedDependencies().orderedAssetIds;
|
||||
|
||||
if (!dependencyArgs.empty())
|
||||
if (m_model.GetInterface().RequiresConstructionParametersForDependencies())
|
||||
{
|
||||
m_dotLua.Write(", %s", Grammar::k_DependentAssetsArgName);
|
||||
}
|
||||
@@ -1740,7 +1759,7 @@ namespace ScriptCanvas
|
||||
|
||||
size_t GraphToLua::WriteFunctionCallInputThisPointer(Grammar::ExecutionTreeConstPtr execution)
|
||||
{
|
||||
if (IsUserFunctionCall(execution) && execution->GetRoot()->IsPure())
|
||||
if (IsUserFunctionCallPure(execution))
|
||||
{
|
||||
m_dotLua.Write("%s", Grammar::k_executionStateVariableName);
|
||||
|
||||
|
||||
@@ -81,6 +81,8 @@ namespace ScriptCanvas
|
||||
{
|
||||
return ConstructCustomNodeIdentifier(scriptCanvasNode->RTTI_GetType());
|
||||
}
|
||||
|
||||
return NodeTypeIdentifier(0);
|
||||
}
|
||||
|
||||
NodeTypeIdentifier NodeUtils::ConstructEBusIdentifier(ScriptCanvas::EBusBusId ebusIdentifier)
|
||||
|
||||
@@ -43,20 +43,12 @@ namespace ScriptCanvas
|
||||
{
|
||||
const char* GetScopeDisplayLabel(Scope scopeType)
|
||||
{
|
||||
switch (scopeType)
|
||||
{
|
||||
case Scope::Graph:
|
||||
return "Graph";
|
||||
case Scope::Function:
|
||||
return "Function";
|
||||
default:
|
||||
return "?";
|
||||
}
|
||||
return GraphVariable::s_ScopeNames[static_cast<int>(scopeType)];
|
||||
}
|
||||
|
||||
Scope GetScopeFromLabel(const char* label)
|
||||
{
|
||||
if (strcmp("Function", label) == 0)
|
||||
if (strcmp(GraphVariable::s_ScopeNames[static_cast<int>(VariableFlags::Scope::Function)], label) == 0)
|
||||
{
|
||||
return Scope::Function;
|
||||
}
|
||||
@@ -71,6 +63,7 @@ namespace ScriptCanvas
|
||||
case Scope::Graph:
|
||||
return "Variable is accessible in the entire graph.";
|
||||
case Scope::Function:
|
||||
case Scope::FunctionReadOnly:
|
||||
return "Variable is accessible only in the execution path of the function that defined it";
|
||||
default:
|
||||
return "?";
|
||||
@@ -162,6 +155,14 @@ namespace ScriptCanvas
|
||||
"From Component"
|
||||
};
|
||||
|
||||
const char* GraphVariable::s_ScopeNames[static_cast<int>(VariableFlags::Scope::COUNT)] =
|
||||
{
|
||||
"Graph",
|
||||
"Function",
|
||||
"Function",
|
||||
};
|
||||
|
||||
|
||||
void GraphVariable::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
@@ -197,6 +198,13 @@ namespace ScriptCanvas
|
||||
return choices;
|
||||
};
|
||||
|
||||
auto scopeChoices = [] {
|
||||
AZStd::vector< AZStd::pair<VariableFlags::Scope, AZStd::string>> choices;
|
||||
choices.emplace_back(AZStd::make_pair(VariableFlags::Scope::Graph, s_ScopeNames[0]));
|
||||
choices.emplace_back(AZStd::make_pair(VariableFlags::Scope::Function, s_ScopeNames[1]));
|
||||
return choices;
|
||||
};
|
||||
|
||||
editContext->Class<GraphVariable>("Variable", "Represents a Variable field within a Script Canvas Graph")
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::Visibility, &GraphVariable::GetVisibility)
|
||||
@@ -215,8 +223,8 @@ namespace ScriptCanvas
|
||||
->Attribute(AZ::Edit::Attributes::ChangeNotify, &GraphVariable::OnValueChanged)
|
||||
|
||||
->DataElement(AZ::Edit::UIHandlers::ComboBox, &GraphVariable::m_scope, "Scope", "Controls the scope of this variable. i.e. If this is exposed as input to this script, or output from this script, or if the variable is just locally scoped.")
|
||||
->Attribute(AZ::Edit::Attributes::Visibility, &GraphVariable::GetInputControlVisibility)
|
||||
->Attribute(AZ::Edit::Attributes::GenericValueList, &GraphVariable::GetScopes)
|
||||
->Attribute(AZ::Edit::Attributes::Visibility, &GraphVariable::GetScopeControlVisibility)
|
||||
->Attribute(AZ::Edit::Attributes::GenericValueList, scopeChoices)
|
||||
->Attribute(AZ::Edit::Attributes::ChangeNotify, &GraphVariable::OnScopeTypedChanged)
|
||||
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &GraphVariable::m_networkProperties, "Network Properties", "Enables whether or not this value should be network synchronized")
|
||||
@@ -382,6 +390,16 @@ namespace ScriptCanvas
|
||||
m_inputControlVisibility = inputControlVisibility;
|
||||
}
|
||||
|
||||
AZ::Crc32 GraphVariable::GetScopeControlVisibility() const
|
||||
{
|
||||
if (m_scope == VariableFlags::Scope::FunctionReadOnly)
|
||||
{
|
||||
return AZ::Edit::PropertyVisibility::Hide;
|
||||
}
|
||||
|
||||
return GetInputControlVisibility();
|
||||
}
|
||||
|
||||
AZ::Crc32 GraphVariable::GetInputControlVisibility() const
|
||||
{
|
||||
return m_inputControlVisibility;
|
||||
@@ -462,6 +480,8 @@ namespace ScriptCanvas
|
||||
return m_scope == VariableFlags::Scope::Graph;
|
||||
// All graph variables are in function local scope
|
||||
case VariableFlags::Scope::Function:
|
||||
case VariableFlags::Scope::FunctionReadOnly:
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -52,8 +52,10 @@ namespace ScriptCanvas
|
||||
|
||||
enum class Scope : AZ::u8
|
||||
{
|
||||
Graph = 0,
|
||||
Function = 1,
|
||||
Graph,
|
||||
Function,
|
||||
FunctionReadOnly,
|
||||
COUNT
|
||||
};
|
||||
|
||||
enum InitialValueSource : AZ::u8
|
||||
@@ -142,6 +144,7 @@ namespace ScriptCanvas
|
||||
void SetScriptInputControlVisibility(const AZ::Crc32& inputControlVisibility);
|
||||
|
||||
AZ::Crc32 GetInputControlVisibility() const;
|
||||
AZ::Crc32 GetScopeControlVisibility() const;
|
||||
AZ::Crc32 GetScriptInputControlVisibility() const;
|
||||
AZ::Crc32 GetNetworkSettingsVisibility() const;
|
||||
AZ::Crc32 GetFunctionInputControlVisibility() const;
|
||||
@@ -181,6 +184,7 @@ namespace ScriptCanvas
|
||||
int GetSortPriority() const;
|
||||
|
||||
static const char* s_InitialValueSourceNames[VariableFlags::InitialValueSource::COUNT];
|
||||
static const char* s_ScopeNames[static_cast<int>(VariableFlags::Scope::COUNT)];
|
||||
|
||||
private:
|
||||
|
||||
|
||||
+6
-2
@@ -225,7 +225,7 @@ namespace ScriptCanvas
|
||||
}
|
||||
|
||||
// #functions2 slot<->variable add this to the graph, using the old datum
|
||||
AZ::Outcome<VariableId, AZStd::string> GraphVariableManagerComponent::AddVariable(AZStd::string_view name, const Datum& value)
|
||||
AZ::Outcome<VariableId, AZStd::string> GraphVariableManagerComponent::AddVariable(AZStd::string_view name, const Datum& value, bool functionScope)
|
||||
{
|
||||
if (FindVariable(name))
|
||||
{
|
||||
@@ -245,6 +245,10 @@ namespace ScriptCanvas
|
||||
|
||||
GraphVariable* variable = m_variableData.FindVariable(newId);
|
||||
variable->SetOwningScriptCanvasId(GetScriptCanvasId());
|
||||
if (functionScope)
|
||||
{
|
||||
variable->SetScope(VariableFlags::Scope::FunctionReadOnly);
|
||||
}
|
||||
|
||||
VariableRequestBus::MultiHandler::BusConnect(GraphScopedVariableId(m_scriptCanvasId, newId));
|
||||
GraphVariableManagerNotificationBus::Event(GetScriptCanvasId(), &GraphVariableManagerNotifications::OnVariableAddedToGraph, newId, name);
|
||||
@@ -254,7 +258,7 @@ namespace ScriptCanvas
|
||||
|
||||
AZ::Outcome<VariableId, AZStd::string> GraphVariableManagerComponent::AddVariablePair(const AZStd::pair<AZStd::string_view, Datum>& keyValuePair)
|
||||
{
|
||||
return AddVariable(keyValuePair.first, keyValuePair.second);
|
||||
return AddVariable(keyValuePair.first, keyValuePair.second, false);
|
||||
}
|
||||
|
||||
VariableValidationOutcome GraphVariableManagerComponent::IsNameValid(AZStd::string_view varName)
|
||||
|
||||
+1
-1
@@ -63,7 +63,7 @@ namespace ScriptCanvas
|
||||
//// GraphVariableManagerRequestBus
|
||||
AZ::Outcome<VariableId, AZStd::string> CloneVariable(const GraphVariable& variableConfiguration) override;
|
||||
AZ::Outcome<VariableId, AZStd::string> RemapVariable(const GraphVariable& variableConfiguration) override;
|
||||
AZ::Outcome<VariableId, AZStd::string> AddVariable(AZStd::string_view name, const Datum& value) override;
|
||||
AZ::Outcome<VariableId, AZStd::string> AddVariable(AZStd::string_view name, const Datum& value, bool functionScope) override;
|
||||
AZ::Outcome<VariableId, AZStd::string> AddVariablePair(const AZStd::pair<AZStd::string_view, Datum>& nameValuePair) override;
|
||||
|
||||
VariableValidationOutcome IsNameValid(AZStd::string_view key) override;
|
||||
|
||||
@@ -90,7 +90,7 @@ namespace ScriptCanvas
|
||||
//! returns an AZ::Outcome which on success contains the VariableId and on Failure contains a string with error information
|
||||
virtual AZ::Outcome<VariableId, AZStd::string> CloneVariable(const GraphVariable& baseVariable) = 0;
|
||||
virtual AZ::Outcome<VariableId, AZStd::string> RemapVariable(const GraphVariable& variableConfiguration) = 0;
|
||||
virtual AZ::Outcome<VariableId, AZStd::string> AddVariable(AZStd::string_view key, const Datum& value) = 0;
|
||||
virtual AZ::Outcome<VariableId, AZStd::string> AddVariable(AZStd::string_view key, const Datum& value, bool functionScope) = 0;
|
||||
virtual AZ::Outcome<VariableId, AZStd::string> AddVariablePair(const AZStd::pair<AZStd::string_view, Datum>& keyValuePair) = 0;
|
||||
|
||||
virtual VariableValidationOutcome IsNameValid(AZStd::string_view variableName) = 0;
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
#include <ScriptCanvas/Core/Node.h>
|
||||
#include <ScriptCanvas/Core/Nodeable.h>
|
||||
#include <ScriptCanvas/Core/Slot.h>
|
||||
#include <ScriptCanvas/Data/DataRegistry.h>
|
||||
#include <ScriptCanvas/Execution/ExecutionPerformanceTimer.h>
|
||||
#include <ScriptCanvas/Execution/Interpreted/ExecutionInterpretedAPI.h>
|
||||
#include <ScriptCanvas/Execution/RuntimeComponent.h>
|
||||
@@ -37,10 +36,10 @@
|
||||
namespace ScriptCanvasSystemComponentCpp
|
||||
{
|
||||
#if !defined(_RELEASE) && !defined(PERFORMANCE_BUILD)
|
||||
const int k_infiniteLoopDetectionMaxIterations = 3000;
|
||||
const int k_infiniteLoopDetectionMaxIterations = 1000000;
|
||||
const int k_maxHandlerStackDepth = 25;
|
||||
#else
|
||||
const int k_infiniteLoopDetectionMaxIterations = 10000;
|
||||
const int k_infiniteLoopDetectionMaxIterations = 10000000;
|
||||
const int k_maxHandlerStackDepth = 100;
|
||||
#endif
|
||||
|
||||
@@ -285,6 +284,72 @@ namespace ScriptCanvas
|
||||
m_ownedObjectsByAddress.erase(object);
|
||||
}
|
||||
|
||||
AZStd::pair<DataRegistry::Createability, TypeProperties> SystemComponent::GetCreatibility(AZ::SerializeContext* serializeContext, AZ::BehaviorClass* behaviorClass)
|
||||
{
|
||||
TypeProperties typeProperties;
|
||||
|
||||
bool canCreate{};
|
||||
// BehaviorContext classes with the ExcludeFrom attribute with a value of the ExcludeFlags::List is not creatable
|
||||
const AZ::u64 exclusionFlags = AZ::Script::Attributes::ExcludeFlags::List;
|
||||
auto excludeClassAttributeData = azrtti_cast<const AZ::Edit::AttributeData<AZ::Script::Attributes::ExcludeFlags>*>(AZ::FindAttribute(AZ::Script::Attributes::ExcludeFrom, behaviorClass->m_attributes));
|
||||
|
||||
const AZ::u64 flags = excludeClassAttributeData ? excludeClassAttributeData->Get(nullptr) : 0;
|
||||
bool listOnly = ((flags & AZ::Script::Attributes::ExcludeFlags::ListOnly) == AZ::Script::Attributes::ExcludeFlags::ListOnly); // ListOnly exclusions may create variables
|
||||
canCreate = listOnly || (!excludeClassAttributeData || (!(flags & exclusionFlags)));
|
||||
canCreate = canCreate && (serializeContext->FindClassData(behaviorClass->m_typeId));
|
||||
canCreate = canCreate && !ScriptCanvasSystemComponentCpp::IsDeprecated(behaviorClass->m_attributes);
|
||||
|
||||
if (canCreate)
|
||||
{
|
||||
for (auto base : behaviorClass->m_baseClasses)
|
||||
{
|
||||
if (AZ::Component::TYPEINFO_Uuid() == base)
|
||||
{
|
||||
canCreate = false;
|
||||
break; // only out of the for : base classes loop. DO NOT break out of the parent loop.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Assets are not safe enough for variable creation, yet. They can be created with one Az type (Data::Asset<T>), but set to nothing.
|
||||
// When read back in, they will (if lucky) just be Data::Asset<Data>, which breaks type safety at best, and requires a lot of sanity checking.
|
||||
// This is NOT blacked at the createable types or BehaviorContext level, since they could be used to at least pass information through,
|
||||
// and may be used other scripting contexts.
|
||||
AZ::IRttiHelper* rttiHelper = behaviorClass->m_azRtti;
|
||||
if (rttiHelper && rttiHelper->GetGenericTypeId() == azrtti_typeid<AZ::Data::Asset>())
|
||||
{
|
||||
canCreate = false;
|
||||
}
|
||||
|
||||
if (AZ::FindAttribute(AZ::ScriptCanvasAttributes::AllowInternalCreation, behaviorClass->m_attributes))
|
||||
{
|
||||
canCreate = true;
|
||||
typeProperties.m_isTransient = true;
|
||||
}
|
||||
|
||||
// create able variables must have full memory support
|
||||
canCreate = canCreate &&
|
||||
(behaviorClass->m_allocate
|
||||
&& behaviorClass->m_cloner
|
||||
&& behaviorClass->m_mover
|
||||
&& behaviorClass->m_destructor
|
||||
&& behaviorClass->m_deallocate) &&
|
||||
AZStd::none_of(behaviorClass->m_baseClasses.begin(), behaviorClass->m_baseClasses.end(), [](const AZ::TypeId& base) { return azrtti_typeid<AZ::Component>() == base; });
|
||||
|
||||
if (!canCreate)
|
||||
{
|
||||
return { DataRegistry::Createability::None , TypeProperties{} };
|
||||
}
|
||||
else if (!AZ::FindAttribute(AZ::ScriptCanvasAttributes::VariableCreationForbidden, behaviorClass->m_attributes))
|
||||
{
|
||||
return { DataRegistry::Createability::SlotAndVariable, typeProperties };
|
||||
}
|
||||
else
|
||||
{
|
||||
return { DataRegistry::Createability::SlotOnly, typeProperties };
|
||||
}
|
||||
}
|
||||
|
||||
void SystemComponent::RegisterCreatableTypes()
|
||||
{
|
||||
AZ::SerializeContext* serializeContext{};
|
||||
@@ -297,40 +362,11 @@ namespace ScriptCanvas
|
||||
auto dataRegistry = ScriptCanvas::GetDataRegistry();
|
||||
for (const auto& classIter : behaviorContext->m_classes)
|
||||
{
|
||||
TypeProperties typeProperties;
|
||||
|
||||
bool canCreate{};
|
||||
const AZ::BehaviorClass* behaviorClass = classIter.second;
|
||||
// BehaviorContext classes with the ExcludeFrom attribute with a value of the ExcludeFlags::List is not creatable
|
||||
const AZ::u64 exclusionFlags = AZ::Script::Attributes::ExcludeFlags::List;
|
||||
auto excludeClassAttributeData = azrtti_cast<const AZ::Edit::AttributeData<AZ::Script::Attributes::ExcludeFlags>*>(AZ::FindAttribute(AZ::Script::Attributes::ExcludeFrom, behaviorClass->m_attributes));
|
||||
|
||||
const AZ::u64 flags = excludeClassAttributeData ? excludeClassAttributeData->Get(nullptr) : 0;
|
||||
bool listOnly = ((flags & AZ::Script::Attributes::ExcludeFlags::ListOnly) == AZ::Script::Attributes::ExcludeFlags::ListOnly); // ListOnly exclusions may create variables
|
||||
|
||||
canCreate = listOnly || (!excludeClassAttributeData || (!(flags & exclusionFlags)));
|
||||
canCreate = canCreate && (serializeContext->FindClassData(behaviorClass->m_typeId));
|
||||
canCreate = canCreate && !ScriptCanvasSystemComponentCpp::IsDeprecated(behaviorClass->m_attributes);
|
||||
|
||||
if (AZ::FindAttribute(AZ::ScriptCanvasAttributes::AllowInternalCreation, behaviorClass->m_attributes))
|
||||
{
|
||||
canCreate = true;
|
||||
typeProperties.m_isTransient = true;
|
||||
}
|
||||
|
||||
// create able variables must have full memory support
|
||||
canCreate = canCreate &&
|
||||
( behaviorClass->m_allocate
|
||||
&& behaviorClass->m_cloner
|
||||
&& behaviorClass->m_mover
|
||||
&& behaviorClass->m_destructor
|
||||
&& behaviorClass->m_deallocate) &&
|
||||
AZStd::none_of(behaviorClass->m_baseClasses.begin(), behaviorClass->m_baseClasses.end(), [](const AZ::TypeId& base) { return azrtti_typeid<AZ::Component>() == base; });
|
||||
|
||||
if (canCreate)
|
||||
{
|
||||
dataRegistry->RegisterType(behaviorClass->m_typeId, typeProperties);
|
||||
}
|
||||
auto createability = GetCreatibility(serializeContext, classIter.second);
|
||||
if (createability.first != DataRegistry::Createability::None)
|
||||
{
|
||||
dataRegistry->RegisterType(classIter.second->m_typeId, createability.second, createability.first);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -339,33 +375,19 @@ namespace ScriptCanvas
|
||||
auto dataRegistry = ScriptCanvas::GetDataRegistry();
|
||||
if (!dataRegistry)
|
||||
{
|
||||
AZ_Warning("ScriptCanvas", false, "Data registry not available. Can't register new class.");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
AZ::SerializeContext* serializeContext{};
|
||||
AZ::ComponentApplicationBus::BroadcastResult(serializeContext, &AZ::ComponentApplicationRequests::GetSerializeContext);
|
||||
AZ_Assert(serializeContext, "Serialize Context should not be missing at this point");
|
||||
AZ_Assert(serializeContext, "Serialize Context missing. Can't register new class.");
|
||||
|
||||
TypeProperties typeProperties;
|
||||
|
||||
// BehaviorContext classes with the ExcludeFrom attribute with a value of the ExcludeFlags::List is not creatable
|
||||
const AZ::u64 exclusionFlags = AZ::Script::Attributes::ExcludeFlags::List;
|
||||
auto excludeClassAttributeData = azrtti_cast<const AZ::Edit::AttributeData<AZ::Script::Attributes::ExcludeFlags>*>(AZ::FindAttribute(AZ::Script::Attributes::ExcludeFrom, behaviorClass->m_attributes));
|
||||
bool canCreate = !excludeClassAttributeData || !(excludeClassAttributeData->Get(nullptr) & exclusionFlags);
|
||||
canCreate = canCreate && (serializeContext->FindClassData(behaviorClass->m_typeId) || AZ::FindAttribute(AZ::ScriptCanvasAttributes::AllowInternalCreation, behaviorClass->m_attributes));
|
||||
canCreate = canCreate && !ScriptCanvasSystemComponentCpp::IsDeprecated(behaviorClass->m_attributes);
|
||||
|
||||
// create able variables must have full memory support
|
||||
canCreate = canCreate &&
|
||||
(behaviorClass->m_allocate
|
||||
&& behaviorClass->m_cloner
|
||||
&& behaviorClass->m_mover
|
||||
&& behaviorClass->m_destructor
|
||||
&& behaviorClass->m_deallocate) &&
|
||||
AZStd::none_of(behaviorClass->m_baseClasses.begin(), behaviorClass->m_baseClasses.end(), [](const AZ::TypeId& base) { return azrtti_typeid<AZ::Component>() == base; });
|
||||
|
||||
if (canCreate)
|
||||
auto createability = GetCreatibility(serializeContext, behaviorClass);
|
||||
if (createability.first != DataRegistry::Createability::None)
|
||||
{
|
||||
dataRegistry->RegisterType(behaviorClass->m_typeId, typeProperties);
|
||||
dataRegistry->RegisterType(behaviorClass->m_typeId, createability.second, createability.first);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user