nodeview: prelim work towards show all functionality
This commit is contained in:
+105
-101
@@ -101,7 +101,7 @@ void NodeView::SetGraph(NodeGraph *graph, const QVector<Node*> &nodes)
|
||||
if (graph_changed) {
|
||||
if (graph_) {
|
||||
// Disconnect from current graph
|
||||
disconnect(graph_, &NodeGraph::NodeAdded, this, &NodeView::AddNode);
|
||||
//disconnect(graph_, &NodeGraph::NodeAdded, this, &NodeView::AddNode);
|
||||
disconnect(graph_, &NodeGraph::NodeRemoved, this, &NodeView::RemoveNode);
|
||||
disconnect(graph_, &NodeGraph::InputConnected, this, &NodeView::AddEdge);
|
||||
disconnect(graph_, &NodeGraph::InputDisconnected, this, &NodeView::RemoveEdge);
|
||||
@@ -113,7 +113,7 @@ void NodeView::SetGraph(NodeGraph *graph, const QVector<Node*> &nodes)
|
||||
|
||||
if (graph_) {
|
||||
// Connect to new graph
|
||||
connect(graph_, &NodeGraph::NodeAdded, this, &NodeView::AddNode);
|
||||
//connect(graph_, &NodeGraph::NodeAdded, this, &NodeView::AddNode);
|
||||
connect(graph_, &NodeGraph::NodeRemoved, this, &NodeView::RemoveNode);
|
||||
connect(graph_, &NodeGraph::InputConnected, this, &NodeView::AddEdge);
|
||||
connect(graph_, &NodeGraph::InputDisconnected, this, &NodeView::RemoveEdge);
|
||||
@@ -122,47 +122,50 @@ void NodeView::SetGraph(NodeGraph *graph, const QVector<Node*> &nodes)
|
||||
}
|
||||
}
|
||||
|
||||
if (context_changed) {
|
||||
if (context_changed && filter_mode_ == kFilterShowSelective) {
|
||||
filter_nodes_ = nodes;
|
||||
}
|
||||
|
||||
if (refresh_required && nodes_visible) {
|
||||
|
||||
if (filter_mode_ == kFilterShowAll) {
|
||||
/* = WIP =
|
||||
for (auto it=graph_->GetPositionMap().cbegin(); it!=graph_->GetPositionMap().cend(); it++) {
|
||||
// Determine which contexts in the graph have no outputs, these are considered "root-level"
|
||||
filter_nodes_.clear();
|
||||
for (auto it=graph->GetPositionMap().cbegin(); it!=graph->GetPositionMap().cend(); it++) {
|
||||
Node *context = it.key();
|
||||
const NodeGraph::PositionMap &map = it.value();
|
||||
|
||||
for (auto jt=map.cbegin(); jt!=map.cend(); jt++) {
|
||||
|
||||
if (context->output_connections().empty()) {
|
||||
filter_nodes_.append(context);
|
||||
}
|
||||
}*/
|
||||
} else {
|
||||
// Reserve an arbitrary number to reduce the amount of reallocations
|
||||
qreal last_offset = 0;
|
||||
int additional_spacing = 0;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (Node *n, filter_nodes_) {
|
||||
const NodeGraph::PositionMap &map = graph_->GetNodesForContext(n);
|
||||
// Standard root-level positioning code
|
||||
qreal last_offset = 0;
|
||||
int additional_spacing = 0;
|
||||
|
||||
// First determine the total "height" of this graph and how much we need to offset it
|
||||
qreal top = 0;
|
||||
qreal bottom = 0;
|
||||
for (auto it=map.cbegin(); it!=map.cend(); it++) {
|
||||
const QPointF &node_pos_in_context = it.value();
|
||||
top = qMin(node_pos_in_context.y(), top);
|
||||
bottom = qMax(node_pos_in_context.y(), bottom);
|
||||
}
|
||||
// Contexts may be added to this later, so to ensure we only process the root-level nodes we
|
||||
// found above, we'll store the current size and stop iterating after that
|
||||
int sz = filter_nodes_.size();
|
||||
for (int i=0; i<sz; i++) {
|
||||
Node *n = filter_nodes_.at(i);
|
||||
const NodeGraph::PositionMap &map = graph_->GetNodesForContext(n);
|
||||
|
||||
last_offset += (additional_spacing + (bottom - top));
|
||||
additional_spacing = 1;
|
||||
context_offsets_.insert(n, QPointF(0, last_offset));
|
||||
// First determine the total "height" of this graph and how much we need to offset it
|
||||
qreal top = 0;
|
||||
qreal bottom = 0;
|
||||
for (auto it=map.cbegin(); it!=map.cend(); it++) {
|
||||
const QPointF &node_pos_in_context = it.value();
|
||||
top = qMin(node_pos_in_context.y(), top);
|
||||
bottom = qMax(node_pos_in_context.y(), bottom);
|
||||
}
|
||||
|
||||
// Finally add all nodes
|
||||
for (auto it=map.cbegin(); it!=map.cend(); it++) {
|
||||
AddNodePosition(it.key(), n);
|
||||
}
|
||||
last_offset += (additional_spacing + (bottom - top));
|
||||
additional_spacing = 1;
|
||||
context_offsets_.insert(n, QPointF(0, last_offset));
|
||||
|
||||
// Finally add all nodes
|
||||
for (auto it=map.cbegin(); it!=map.cend(); it++) {
|
||||
AddNodePosition(it.key(), n);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -994,13 +997,9 @@ void NodeView::ShowContextMenu(const QPoint &pos)
|
||||
Menu* filter_menu = new Menu(tr("Filter"), &m);
|
||||
m.addMenu(filter_menu);
|
||||
|
||||
filter_menu->AddActionWithData(tr("Show All Nodes"),
|
||||
kFilterShowAll,
|
||||
filter_mode_);
|
||||
filter_menu->AddActionWithData(tr("Show All Nodes"), kFilterShowAll, filter_mode_);
|
||||
|
||||
filter_menu->AddActionWithData(tr("Show Selected"),
|
||||
kFilterShowSelective,
|
||||
filter_mode_);
|
||||
filter_menu->AddActionWithData(tr("Show Selected"), kFilterShowSelective, filter_mode_);
|
||||
|
||||
connect(filter_menu, &Menu::triggered, this, &NodeView::ContextMenuFilterChanged);
|
||||
|
||||
@@ -1098,12 +1097,15 @@ void NodeView::OpenSelectedNodeInViewer()
|
||||
}
|
||||
}
|
||||
|
||||
void NodeView::AddNode(Node *node)
|
||||
{
|
||||
if (filter_mode_ == kFilterShowAll) {
|
||||
scene_.AddNode(node);
|
||||
}
|
||||
}
|
||||
// Commenting out because there shouldn't be any situations where a node would be added without
|
||||
// being in a context. We're keeping RemoveNode as a fail-safe because it could provide crash
|
||||
// resistance where RemoveNodePosition might be missed.
|
||||
//void NodeView::AddNode(Node *node)
|
||||
//{
|
||||
// if (filter_mode_ == kFilterShowAll) {
|
||||
// scene_.AddNode(node);
|
||||
// }
|
||||
//}
|
||||
|
||||
void NodeView::RemoveNode(Node *node)
|
||||
{
|
||||
@@ -1112,15 +1114,11 @@ void NodeView::RemoveNode(Node *node)
|
||||
|
||||
void NodeView::AddEdge(const NodeOutput &output, const NodeInput &input)
|
||||
{
|
||||
if (filter_mode_ == kFilterShowAll) {
|
||||
scene_.AddEdge(output, input);
|
||||
} else if (filter_mode_ == kFilterShowSelective) {
|
||||
Node *output_node = output.node();
|
||||
Node *input_node = input.node();
|
||||
Node *output_node = output.node();
|
||||
Node *input_node = input.node();
|
||||
|
||||
if (scene_.item_map().contains(output_node) && scene_.item_map().contains(input_node)) {
|
||||
scene_.AddEdge(output, input);
|
||||
}
|
||||
if (scene_.item_map().contains(output_node) && scene_.item_map().contains(input_node)) {
|
||||
scene_.AddEdge(output, input);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1131,74 +1129,80 @@ void NodeView::RemoveEdge(const NodeOutput &output, const NodeInput &input)
|
||||
|
||||
void NodeView::AddNodePosition(Node *node, Node *relative)
|
||||
{
|
||||
if (filter_mode_ == kFilterShowSelective) {
|
||||
if (filter_nodes_.contains(relative)) {
|
||||
// Get UI item or create if it doesn't exist
|
||||
NodeViewItem *item = scene_.item_map().value(node);
|
||||
if (!item) {
|
||||
item = scene_.AddNode(node);
|
||||
if (filter_nodes_.contains(relative)) {
|
||||
// Get UI item or create if it doesn't exist
|
||||
NodeViewItem *item = scene_.item_map().value(node);
|
||||
if (!item) {
|
||||
item = scene_.AddNode(node);
|
||||
|
||||
for (auto it=node->input_connections().cbegin(); it!=node->input_connections().cend(); it++) {
|
||||
if (scene_.item_map().contains(it->second.node())) {
|
||||
scene_.AddEdge(it->second, it->first);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto it=node->output_connections().cbegin(); it!=node->output_connections().cend(); it++) {
|
||||
if (scene_.item_map().contains(it->second.node())) {
|
||||
scene_.AddEdge(it->first, it->second);
|
||||
}
|
||||
for (auto it=node->input_connections().cbegin(); it!=node->input_connections().cend(); it++) {
|
||||
if (scene_.item_map().contains(it->second.node())) {
|
||||
scene_.AddEdge(it->second, it->first);
|
||||
}
|
||||
}
|
||||
|
||||
// Determine "view" position by averaging the Y value and "min"ing the X value of all contexts
|
||||
QPointF item_pos(DBL_MAX, 0.0);
|
||||
int average_count = 0;
|
||||
foreach (Node *context, filter_nodes_) {
|
||||
if (graph_->GetNodesForContext(context).contains(node)) {
|
||||
QPointF this_context_pos = graph_->GetNodePosition(node, context);
|
||||
this_context_pos += context_offsets_.value(context);
|
||||
item_pos.setX(qMin(item_pos.x(), this_context_pos.x()));
|
||||
item_pos.setY(item_pos.y() + this_context_pos.y());
|
||||
average_count++;
|
||||
for (auto it=node->output_connections().cbegin(); it!=node->output_connections().cend(); it++) {
|
||||
if (scene_.item_map().contains(it->second.node())) {
|
||||
scene_.AddEdge(it->first, it->second);
|
||||
}
|
||||
}
|
||||
item_pos.setY(item_pos.y() / average_count);
|
||||
}
|
||||
|
||||
// Set position
|
||||
item->SetNodePosition(item_pos);
|
||||
positions_.insert(item, {node, item_pos});
|
||||
// Determine "view" position by averaging the Y value and "min"ing the X value of all contexts
|
||||
QPointF item_pos(DBL_MAX, 0.0);
|
||||
int average_count = 0;
|
||||
foreach (Node *context, filter_nodes_) {
|
||||
if (graph_->GetNodesForContext(context).contains(node)) {
|
||||
QPointF this_context_pos = graph_->GetNodePosition(node, context);
|
||||
this_context_pos += context_offsets_.value(context);
|
||||
item_pos.setX(qMin(item_pos.x(), this_context_pos.x()));
|
||||
item_pos.setY(item_pos.y() + this_context_pos.y());
|
||||
average_count++;
|
||||
}
|
||||
}
|
||||
item_pos.setY(item_pos.y() / average_count);
|
||||
|
||||
// Set position
|
||||
item->SetNodePosition(item_pos);
|
||||
positions_.insert(item, {node, item_pos});
|
||||
|
||||
// For "show all" mode, we recursively add more nodes to the graph
|
||||
if (filter_mode_ == kFilterShowAll && !filter_nodes_.contains(node) && graph_->GetPositionMap().contains(node)) {
|
||||
filter_nodes_.append(node);
|
||||
context_offsets_.insert(node, item_pos);
|
||||
const NodeGraph::PositionMap &map = graph_->GetNodesForContext(node);
|
||||
for (auto it=map.cbegin(); it!=map.cend(); it++) {
|
||||
AddNodePosition(it.key(), node);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NodeView::RemoveNodePosition(Node *node, Node *relative)
|
||||
{
|
||||
if (filter_mode_ == kFilterShowSelective) {
|
||||
if (filter_nodes_.contains(relative)) {
|
||||
NodeViewItem *item = scene_.item_map().value(node);
|
||||
if (filter_nodes_.contains(relative)) {
|
||||
NodeViewItem *item = scene_.item_map().value(node);
|
||||
|
||||
if (item && !item->GetPreventRemoving()) {
|
||||
// Determine if any other contexts have this node
|
||||
bool found = false;
|
||||
if (item && !item->GetPreventRemoving()) {
|
||||
// Determine if any other contexts have this node
|
||||
bool found = false;
|
||||
|
||||
foreach (Node *context, filter_nodes_) {
|
||||
if (graph_->ContextContainsNode(node, context)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
foreach (Node *context, filter_nodes_) {
|
||||
if (graph_->ContextContainsNode(node, context)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
foreach (const Node::OutputConnection &oc, node->output_connections()) {
|
||||
scene_.RemoveEdge(oc.first, oc.second);
|
||||
}
|
||||
for (auto it=node->input_connections().cbegin(); it!=node->input_connections().cend(); it++) {
|
||||
scene_.RemoveEdge(it->second, it->first);
|
||||
}
|
||||
positions_.remove(item);
|
||||
scene_.RemoveNode(node);
|
||||
if (!found) {
|
||||
foreach (const Node::OutputConnection &oc, node->output_connections()) {
|
||||
scene_.RemoveEdge(oc.first, oc.second);
|
||||
}
|
||||
for (auto it=node->input_connections().cbegin(); it!=node->input_connections().cend(); it++) {
|
||||
scene_.RemoveEdge(it->second, it->first);
|
||||
}
|
||||
positions_.remove(item);
|
||||
scene_.RemoveNode(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user