Files
oak-editor/app/widget/nodetreeview/nodetreeview.cpp
T
itsmattkc 81c1922911 use strings to connect nodes
This makes the node system somewhat more high-level with the intent of making
working with them far more flexible and stable. By making the architecture more
abstracted, it becomes far less rigid which should allow us to do even more
with it and make it much less crash prone.
2021-02-09 15:48:37 +11:00

231 lines
5.9 KiB
C++

#include "nodetreeview.h"
namespace olive {
NodeTreeView::NodeTreeView(QWidget *parent) :
QTreeWidget(parent),
only_show_keyframable_(false),
show_keyframe_tracks_as_rows_(false)
{
connect(this, &NodeTreeView::itemChanged, this, &NodeTreeView::ItemCheckStateChanged);
connect(this, &NodeTreeView::itemSelectionChanged, this, &NodeTreeView::SelectionChanged);
Retranslate();
}
bool NodeTreeView::IsNodeEnabled(Node *n) const
{
return !disabled_nodes_.contains(n);
}
bool NodeTreeView::IsInputEnabled(const NodeKeyframeTrackReference &ref) const
{
return !disabled_inputs_.contains(ref);
}
void NodeTreeView::SetKeyframeTrackColor(const NodeKeyframeTrackReference &ref, const QColor &color)
{
// Insert into hashmap
keyframe_colors_.insert(ref, color);
// If we currently have an item for this, set it
QTreeWidgetItem* item = item_map_.value(ref);
if (item) {
item->setForeground(0, color);
}
}
void NodeTreeView::SetNodes(const QVector<Node *> &nodes)
{
nodes_ = nodes;
this->clear();
item_map_.clear();
foreach (Node* n, nodes_) {
QTreeWidgetItem* node_item = new QTreeWidgetItem();
node_item->setText(0, n->Name());
node_item->setCheckState(0, disabled_nodes_.contains(n) ? Qt::Unchecked : Qt::Checked);
node_item->setData(0, kItemType, kItemTypeNode);
node_item->setData(0, kItemNodePointer, Node::PtrToValue(n));
foreach (const QString& input, n->inputs()) {
if (only_show_keyframable_ && !n->IsInputKeyframable(input)) {
continue;
}
QTreeWidgetItem* input_item = nullptr;
int arr_sz = n->InputArraySize(input);
for (int i=-1; i<arr_sz; i++) {
NodeInput input_ref(n, input, i);
const QVector<NodeKeyframeTrack>& key_tracks = n->GetKeyframeTracks(input_ref);
int this_element_track;
if (show_keyframe_tracks_as_rows_
&& (key_tracks.size() == 1 || (i == -1 && n->InputIsArray(input)))) {
this_element_track = 0;
} else {
this_element_track = -1;
}
QTreeWidgetItem* element_item;
if (input_item) {
element_item = CreateItem(input_item, NodeKeyframeTrackReference(input_ref, this_element_track));
} else {
input_item = CreateItem(node_item, NodeKeyframeTrackReference(input_ref, this_element_track));
element_item = input_item;
}
if (show_keyframe_tracks_as_rows_ && key_tracks.size() > 1 && (!n->InputIsArray(input) || i >= 0)) {
CreateItemsForTracks(element_item, input_ref, key_tracks.size());
}
}
}
// Add at the end to prevent unnecessary signalling while we're setting these objects up
if (node_item->childCount() > 0) {
this->addTopLevelItem(node_item);
} else {
delete node_item;
}
}
}
void NodeTreeView::changeEvent(QEvent *e)
{
QTreeWidget::changeEvent(e);
if (e->type() == QEvent::LanguageChange) {
Retranslate();
}
}
void NodeTreeView::mouseDoubleClickEvent(QMouseEvent *e)
{
QTreeWidget::mouseDoubleClickEvent(e);
NodeKeyframeTrackReference ref = GetSelectedInput();
if (ref.input().IsValid()) {
emit InputDoubleClicked(ref);
}
}
void NodeTreeView::Retranslate()
{
setHeaderLabel(tr("Nodes"));
}
NodeKeyframeTrackReference NodeTreeView::GetSelectedInput()
{
QList<QTreeWidgetItem*> sel = selectedItems();
NodeKeyframeTrackReference selected_ref;
if (!sel.isEmpty()) {
QTreeWidgetItem* item = sel.first();
if (item->data(0, kItemType).toInt() == kItemTypeInput) {
selected_ref = item->data(0, kItemInputReference).value<NodeKeyframeTrackReference>();
}
}
return selected_ref;
}
QTreeWidgetItem* NodeTreeView::CreateItem(QTreeWidgetItem *parent, const NodeKeyframeTrackReference& ref)
{
QTreeWidgetItem* input_item = new QTreeWidgetItem(parent);
QString item_name;
if (ref.track() == -1 || NodeValue::get_number_of_keyframe_tracks(ref.input().GetDataType()) == 1) {
item_name = ref.input().name();
} else {
switch (ref.track()) {
case 0:
item_name = tr("X");
break;
case 1:
item_name = tr("Y");
break;
case 2:
item_name = tr("Z");
break;
case 3:
item_name = tr("W");
break;
default:
item_name = QString::number(ref.track());
}
}
input_item->setText(0, item_name);
input_item->setCheckState(0, disabled_inputs_.contains(ref) ? Qt::Unchecked : Qt::Checked);
input_item->setData(0, kItemType, kItemTypeInput);
input_item->setData(0, kItemInputReference, QVariant::fromValue(ref));
if (keyframe_colors_.contains(ref)) {
input_item->setForeground(0, keyframe_colors_.value(ref));
}
item_map_.insert(ref, input_item);
return input_item;
}
void NodeTreeView::CreateItemsForTracks(QTreeWidgetItem *parent, const NodeInput& input, int track_count)
{
for (int j=0; j<track_count; j++) {
CreateItem(parent, NodeKeyframeTrackReference(input, j));
}
}
void NodeTreeView::ItemCheckStateChanged(QTreeWidgetItem *item, int column)
{
Q_UNUSED(column)
switch (item->data(0, kItemType).toInt()) {
case kItemTypeNode:
{
Node* n = Node::ValueToPtr<Node>(item->data(0, kItemNodePointer));
if (item->checkState(0) == Qt::Checked) {
if (disabled_nodes_.contains(n)) {
disabled_nodes_.removeOne(n);
emit NodeEnableChanged(n, true);
}
} else if (!disabled_nodes_.contains(n)) {
disabled_nodes_.append(n);
emit NodeEnableChanged(n, false);
}
break;
}
case kItemTypeInput:
{
NodeKeyframeTrackReference i = item->data(0, kItemInputReference).value<NodeKeyframeTrackReference>();
if (item->checkState(0) == Qt::Checked) {
if (disabled_inputs_.contains(i)) {
disabled_inputs_.removeOne(i);
emit InputEnableChanged(i, true);
}
} else if (!disabled_inputs_.contains(i)) {
disabled_inputs_.append(i);
emit InputEnableChanged(i, false);
}
break;
}
}
}
void NodeTreeView::SelectionChanged()
{
emit InputSelectionChanged(GetSelectedInput());
}
}