implemented node groups
This commit is contained in:
@@ -20,6 +20,7 @@ add_subdirectory(color)
|
||||
add_subdirectory(distort)
|
||||
add_subdirectory(filter)
|
||||
add_subdirectory(generator)
|
||||
add_subdirectory(group)
|
||||
add_subdirectory(input)
|
||||
add_subdirectory(math)
|
||||
add_subdirectory(output)
|
||||
@@ -34,8 +35,6 @@ set(OLIVE_SOURCES
|
||||
node/globals.h
|
||||
node/graph.cpp
|
||||
node/graph.h
|
||||
node/group.cpp
|
||||
node/group.h
|
||||
node/hashtraverser.cpp
|
||||
node/hashtraverser.h
|
||||
node/inputdragger.cpp
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2021 Olive Team
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#include "group.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
NodeGroup::NodeGroup()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2021 Olive Team
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#ifndef NODEGROUP_H
|
||||
#define NODEGROUP_H
|
||||
|
||||
#include "node.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class NodeGroup : public Node
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
NodeGroup();
|
||||
|
||||
void SetNodes(Node *nodes);
|
||||
|
||||
private:
|
||||
QVector<Node*> nodes_;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // NODEGROUP_H
|
||||
@@ -0,0 +1,22 @@
|
||||
# Olive - Non-Linear Video Editor
|
||||
# Copyright (C) 2021 Olive Team
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
set(OLIVE_SOURCES
|
||||
${OLIVE_SOURCES}
|
||||
node/group/group.cpp
|
||||
node/group/group.h
|
||||
PARENT_SCOPE
|
||||
)
|
||||
@@ -0,0 +1,177 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2021 Olive Team
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#include "group.h"
|
||||
|
||||
#include "node/graph.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
NodeGroup::NodeGroup() :
|
||||
output_passthrough_(nullptr)
|
||||
{
|
||||
graph_ = new NodeGraph();
|
||||
graph_->setParent(this);
|
||||
}
|
||||
|
||||
QString NodeGroup::Name() const
|
||||
{
|
||||
if (custom_name_.isEmpty()) {
|
||||
return tr("Group");
|
||||
} else {
|
||||
return custom_name_;
|
||||
}
|
||||
}
|
||||
|
||||
QString NodeGroup::id() const
|
||||
{
|
||||
return QStringLiteral("org.olivevideoeditor.Olive.group");
|
||||
}
|
||||
|
||||
QVector<Node::CategoryID> NodeGroup::Category() const
|
||||
{
|
||||
return {kCategoryGeneral};
|
||||
}
|
||||
|
||||
QString NodeGroup::Description() const
|
||||
{
|
||||
return tr("A group of nodes that is represented as a single node.");
|
||||
}
|
||||
|
||||
void NodeGroup::Retranslate()
|
||||
{
|
||||
foreach (Node *n, graph_->nodes()) {
|
||||
n->Retranslate();
|
||||
}
|
||||
}
|
||||
|
||||
void NodeGroup::AddNode(Node *node)
|
||||
{
|
||||
node->setParent(graph_);
|
||||
}
|
||||
|
||||
void NodeGroup::RemoveNode(Node *node, QObject *new_parent)
|
||||
{
|
||||
if (node->parent() == graph_) {
|
||||
node->setParent(new_parent);
|
||||
}
|
||||
}
|
||||
|
||||
void NodeGroup::AddInputPassthrough(const NodeInput &input)
|
||||
{
|
||||
Q_ASSERT(graph_->nodes().contains(input.node()));
|
||||
|
||||
for (auto it=input_passthroughs_.cbegin(); it!=input_passthroughs_.cend(); it++) {
|
||||
if (it.value() == input) {
|
||||
// Already passing this input through
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Add input
|
||||
QString id = GetGroupInputIDFromInput(input);
|
||||
|
||||
AddInput(id, input.GetDataType(), input.GetDefaultValue(), input.GetFlags());
|
||||
|
||||
input_passthroughs_.insert(id, input);
|
||||
}
|
||||
|
||||
void NodeGroup::RemoveInputPassthrough(const NodeInput &input)
|
||||
{
|
||||
for (auto it=input_passthroughs_.cbegin(); it!=input_passthroughs_.cend(); it++) {
|
||||
if (it.value() == input) {
|
||||
RemoveInput(it.key());
|
||||
input_passthroughs_.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NodeGroup::SetOutputPassthrough(Node *node)
|
||||
{
|
||||
Q_ASSERT(graph_->nodes().contains(node));
|
||||
|
||||
output_passthrough_ = node;
|
||||
}
|
||||
|
||||
QString NodeGroup::GetGroupInputIDFromInput(const NodeInput &input)
|
||||
{
|
||||
QCryptographicHash hash(QCryptographicHash::Sha1);
|
||||
|
||||
hash.addData(input.node()->GetUUID().toByteArray());
|
||||
|
||||
hash.addData(input.input().toUtf8());
|
||||
|
||||
hash.addData((const char*) &input.element(), sizeof(input.element()));
|
||||
|
||||
return QString::fromLatin1(hash.result().toHex());
|
||||
}
|
||||
|
||||
bool NodeGroup::ContainsInputPassthrough(const NodeInput &input) const
|
||||
{
|
||||
for (auto it=input_passthroughs_.cbegin(); it!=input_passthroughs_.cend(); it++) {
|
||||
if (it.value() == input) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void NodeAddToGroupCommand::redo()
|
||||
{
|
||||
previous_parent_ = node_->parent();
|
||||
group_->AddNode(node_);
|
||||
}
|
||||
|
||||
void NodeAddToGroupCommand::undo()
|
||||
{
|
||||
group_->RemoveNode(node_, previous_parent_);
|
||||
}
|
||||
|
||||
void NodeGroupSetCustomNameCommand::redo()
|
||||
{
|
||||
old_name_ = group_->GetCustomName();
|
||||
group_->SetCustomName(new_name_);
|
||||
}
|
||||
|
||||
void NodeGroupSetCustomNameCommand::undo()
|
||||
{
|
||||
group_->SetCustomName(old_name_);
|
||||
}
|
||||
|
||||
void NodeGroupAddInputPassthrough::redo()
|
||||
{
|
||||
if (!group_->ContainsInputPassthrough(input_)) {
|
||||
group_->AddInputPassthrough(input_);
|
||||
actually_added_ = true;
|
||||
} else {
|
||||
actually_added_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
void NodeGroupAddInputPassthrough::undo()
|
||||
{
|
||||
if (actually_added_) {
|
||||
group_->RemoveInputPassthrough(input_);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2021 Olive Team
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#ifndef NODEGROUP_H
|
||||
#define NODEGROUP_H
|
||||
|
||||
#include "node/node.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class NodeGroup : public Node
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
NodeGroup();
|
||||
|
||||
NODE_DEFAULT_DESTRUCTOR(NodeGroup)
|
||||
NODE_COPY_FUNCTION(NodeGroup)
|
||||
|
||||
virtual QString Name() const override;
|
||||
virtual QString id() const override;
|
||||
virtual QVector<CategoryID> Category() const override;
|
||||
virtual QString Description() const override;
|
||||
|
||||
virtual void Retranslate() override;
|
||||
|
||||
void AddNode(Node *node);
|
||||
|
||||
void RemoveNode(Node *node, QObject *new_parent = nullptr);
|
||||
|
||||
void AddInputPassthrough(const NodeInput &input);
|
||||
|
||||
void RemoveInputPassthrough(const NodeInput &input);
|
||||
|
||||
void SetOutputPassthrough(Node *node);
|
||||
|
||||
const QString &GetCustomName() const
|
||||
{
|
||||
return custom_name_;
|
||||
}
|
||||
|
||||
void SetCustomName(const QString &name)
|
||||
{
|
||||
custom_name_ = name;
|
||||
|
||||
// NOTE: Not technically the right signal, but should achieve the right goal
|
||||
emit LabelChanged(custom_name_);
|
||||
}
|
||||
|
||||
void ClearCustomName()
|
||||
{
|
||||
custom_name_.clear();
|
||||
}
|
||||
|
||||
static QString GetGroupInputIDFromInput(const NodeInput &input);
|
||||
|
||||
const QHash<QString, NodeInput> &GetInputPassthroughs() const
|
||||
{
|
||||
return input_passthroughs_;
|
||||
}
|
||||
|
||||
bool ContainsInputPassthrough(const NodeInput &input) const;
|
||||
|
||||
private:
|
||||
NodeGraph *graph_;
|
||||
|
||||
QHash<QString, NodeInput> input_passthroughs_;
|
||||
|
||||
Node *output_passthrough_;
|
||||
|
||||
QString custom_name_;
|
||||
|
||||
};
|
||||
|
||||
class NodeAddToGroupCommand : public UndoCommand
|
||||
{
|
||||
public:
|
||||
NodeAddToGroupCommand(Node *node, NodeGroup *group) :
|
||||
node_(node),
|
||||
group_(group)
|
||||
{}
|
||||
|
||||
virtual Project * GetRelevantProject() const override
|
||||
{
|
||||
return node_->project();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void redo() override;
|
||||
|
||||
virtual void undo() override;
|
||||
|
||||
private:
|
||||
Node *node_;
|
||||
|
||||
NodeGroup *group_;
|
||||
|
||||
QObject *previous_parent_;
|
||||
|
||||
};
|
||||
|
||||
class NodeGroupSetCustomNameCommand : public UndoCommand
|
||||
{
|
||||
public:
|
||||
NodeGroupSetCustomNameCommand(NodeGroup *group, const QString &name) :
|
||||
group_(group),
|
||||
new_name_(name)
|
||||
{}
|
||||
|
||||
virtual Project * GetRelevantProject() const override
|
||||
{
|
||||
return group_->project();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void redo() override;
|
||||
|
||||
virtual void undo() override;
|
||||
|
||||
private:
|
||||
NodeGroup *group_;
|
||||
|
||||
QString old_name_;
|
||||
|
||||
QString new_name_;
|
||||
|
||||
};
|
||||
|
||||
class NodeGroupAddInputPassthrough : public UndoCommand
|
||||
{
|
||||
public:
|
||||
NodeGroupAddInputPassthrough(NodeGroup *group, const NodeInput &input) :
|
||||
group_(group),
|
||||
input_(input),
|
||||
actually_added_(false)
|
||||
{}
|
||||
|
||||
virtual Project * GetRelevantProject() const override
|
||||
{
|
||||
return group_->project();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void redo() override;
|
||||
|
||||
virtual void undo() override;
|
||||
|
||||
private:
|
||||
NodeGroup *group_;
|
||||
|
||||
NodeInput input_;
|
||||
|
||||
bool actually_added_;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // NODEGROUP_H
|
||||
+16
-3
@@ -49,6 +49,7 @@ Node::Node() :
|
||||
operation_stack_(0),
|
||||
cache_result_(false)
|
||||
{
|
||||
uuid_ = QUuid::createUuid();
|
||||
}
|
||||
|
||||
Node::~Node()
|
||||
@@ -88,6 +89,8 @@ void Node::Load(QXmlStreamReader *reader, XMLNodeData& xml_node_data, uint versi
|
||||
xml_node_data.node_ptrs.insert(reader->readElementText().toULongLong(), this);
|
||||
} else if (reader->name() == QStringLiteral("label")) {
|
||||
SetLabel(reader->readElementText());
|
||||
} else if (reader->name() == QStringLiteral("uuid")) {
|
||||
SetUUID(QUuid::fromString(reader->readElementText()));
|
||||
} else if (reader->name() == QStringLiteral("color")) {
|
||||
override_color_ = reader->readElementText().toInt();
|
||||
} else if (reader->name() == QStringLiteral("links")) {
|
||||
@@ -169,6 +172,7 @@ void Node::Save(QXmlStreamWriter *writer) const
|
||||
{
|
||||
writer->writeTextElement(QStringLiteral("ptr"), QString::number(reinterpret_cast<quintptr>(this)));
|
||||
|
||||
writer->writeTextElement(QStringLiteral("uuid"), uuid_.toString());
|
||||
writer->writeTextElement(QStringLiteral("label"), GetLabel());
|
||||
writer->writeTextElement(QStringLiteral("color"), QString::number(override_color_));
|
||||
|
||||
@@ -219,7 +223,16 @@ void Node::Save(QXmlStreamWriter *writer) const
|
||||
|
||||
Project* Node::project() const
|
||||
{
|
||||
return dynamic_cast<Project*>(parent());
|
||||
QObject *t = this->parent();
|
||||
|
||||
while (t) {
|
||||
if (Project *p = dynamic_cast<Project*>(t)) {
|
||||
return p;
|
||||
}
|
||||
t = t->parent();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QString Node::ShortName() const
|
||||
@@ -1089,7 +1102,7 @@ NodeInputImmediate *Node::GetImmediate(const QString &input, int element) const
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Node::InputFlags Node::GetInputFlags(const QString &input) const
|
||||
InputFlags Node::GetInputFlags(const QString &input) const
|
||||
{
|
||||
const Input* i = GetInternalInputData(input);
|
||||
|
||||
@@ -1343,7 +1356,7 @@ void Node::HashAddNodeSignature(QCryptographicHash &hash) const
|
||||
hash.addData(id().toUtf8());
|
||||
}
|
||||
|
||||
void Node::InsertInput(const QString &id, NodeValue::Type type, const QVariant &default_value, Node::InputFlags flags, int index)
|
||||
void Node::InsertInput(const QString &id, NodeValue::Type type, const QVariant &default_value, InputFlags flags, int index)
|
||||
{
|
||||
if (id.isEmpty()) {
|
||||
qWarning() << "Rejected adding input with an empty ID on node" << this->id();
|
||||
|
||||
+8
-33
@@ -27,6 +27,7 @@
|
||||
#include <QObject>
|
||||
#include <QPainter>
|
||||
#include <QPointF>
|
||||
#include <QUuid>
|
||||
#include <QXmlStreamWriter>
|
||||
|
||||
#include "codec/frame.h"
|
||||
@@ -112,6 +113,9 @@ public:
|
||||
|
||||
Project* project() const;
|
||||
|
||||
const QUuid &GetUUID() const {return uuid_;}
|
||||
void SetUUID(const QUuid &uuid) {uuid_ = uuid;}
|
||||
|
||||
/**
|
||||
* @brief Clear current node variables and replace them with
|
||||
*/
|
||||
@@ -935,38 +939,9 @@ public:
|
||||
|
||||
};
|
||||
|
||||
InputFlags GetInputFlags(const QString& input) const;
|
||||
|
||||
protected:
|
||||
enum InputFlag {
|
||||
/// By default, inputs are keyframable, connectable, and NOT arrays
|
||||
kInputFlagNormal = 0x0,
|
||||
kInputFlagArray = 0x1,
|
||||
kInputFlagNotKeyframable = 0x2,
|
||||
kInputFlagNotConnectable = 0x4,
|
||||
kInputFlagHidden = 0x8
|
||||
};
|
||||
|
||||
class InputFlags {
|
||||
public:
|
||||
explicit InputFlags()
|
||||
{
|
||||
f_ = kInputFlagNormal;
|
||||
}
|
||||
|
||||
explicit InputFlags(uint64_t flags)
|
||||
{
|
||||
f_ = flags;
|
||||
}
|
||||
|
||||
bool operator&(const InputFlag& f) const
|
||||
{
|
||||
return f_ & f;
|
||||
}
|
||||
|
||||
private:
|
||||
uint64_t f_;
|
||||
|
||||
};
|
||||
|
||||
virtual void Hash(QCryptographicHash& hash, const NodeGlobals &globals, const VideoParams& video_params) const;
|
||||
|
||||
void HashAddNodeSignature(QCryptographicHash &hash) const;
|
||||
@@ -1216,8 +1191,6 @@ private:
|
||||
return input_ids_.indexOf(input);
|
||||
}
|
||||
|
||||
InputFlags GetInputFlags(const QString& input) const;
|
||||
|
||||
Input* GetInternalInputData(const QString& input)
|
||||
{
|
||||
int i = GetInternalInputIndex(input);
|
||||
@@ -1336,6 +1309,8 @@ private:
|
||||
|
||||
PositionMap context_positions_;
|
||||
|
||||
QUuid uuid_;
|
||||
|
||||
private slots:
|
||||
/**
|
||||
* @brief Slot when a keyframe's time changes to keep the keyframes correctly sorted by time
|
||||
|
||||
@@ -254,8 +254,6 @@ private:
|
||||
|
||||
AudioPlaybackCache audio_playback_cache_;
|
||||
|
||||
int operation_stack_;
|
||||
|
||||
VideoParams cached_video_params_;
|
||||
|
||||
AudioParams cached_audio_params_;
|
||||
|
||||
@@ -69,6 +69,15 @@ bool NodeInput::IsArray() const
|
||||
}
|
||||
}
|
||||
|
||||
InputFlags NodeInput::GetFlags() const
|
||||
{
|
||||
if (IsValid()) {
|
||||
return node_->GetInputFlags(input_);
|
||||
} else {
|
||||
return InputFlags(kInputFlagNormal);
|
||||
}
|
||||
}
|
||||
|
||||
Node *NodeInput::GetConnectedOutput() const
|
||||
{
|
||||
if (IsValid()) {
|
||||
@@ -87,6 +96,15 @@ NodeValue::Type NodeInput::GetDataType() const
|
||||
}
|
||||
}
|
||||
|
||||
QVariant NodeInput::GetDefaultValue() const
|
||||
{
|
||||
if (IsValid()) {
|
||||
return node_->GetDefaultValue(input_);
|
||||
} else {
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
QStringList NodeInput::GetComboBoxStrings() const
|
||||
{
|
||||
if (IsValid()) {
|
||||
|
||||
+36
-1
@@ -31,6 +31,37 @@ namespace olive {
|
||||
class Node;
|
||||
class NodeKeyframe;
|
||||
|
||||
enum InputFlag {
|
||||
/// By default, inputs are keyframable, connectable, and NOT arrays
|
||||
kInputFlagNormal = 0x0,
|
||||
kInputFlagArray = 0x1,
|
||||
kInputFlagNotKeyframable = 0x2,
|
||||
kInputFlagNotConnectable = 0x4,
|
||||
kInputFlagHidden = 0x8
|
||||
};
|
||||
|
||||
class InputFlags {
|
||||
public:
|
||||
explicit InputFlags()
|
||||
{
|
||||
f_ = kInputFlagNormal;
|
||||
}
|
||||
|
||||
explicit InputFlags(uint64_t flags)
|
||||
{
|
||||
f_ = flags;
|
||||
}
|
||||
|
||||
bool operator&(const InputFlag& f) const
|
||||
{
|
||||
return f_ & f;
|
||||
}
|
||||
|
||||
private:
|
||||
uint64_t f_;
|
||||
|
||||
};
|
||||
|
||||
struct NodeInputPair {
|
||||
bool operator==(const NodeInputPair& rhs) const
|
||||
{
|
||||
@@ -98,7 +129,7 @@ public:
|
||||
return input_;
|
||||
}
|
||||
|
||||
int element() const
|
||||
const int &element() const
|
||||
{
|
||||
return element_;
|
||||
}
|
||||
@@ -123,10 +154,14 @@ public:
|
||||
|
||||
bool IsArray() const;
|
||||
|
||||
InputFlags GetFlags() const;
|
||||
|
||||
Node *GetConnectedOutput() const;
|
||||
|
||||
NodeValue::Type GetDataType() const;
|
||||
|
||||
QVariant GetDefaultValue() const;
|
||||
|
||||
QStringList GetComboBoxStrings() const;
|
||||
|
||||
QVariant GetProperty(const QString& key) const;
|
||||
|
||||
Reference in New Issue
Block a user