summaryrefslogtreecommitdiff
path: root/scene/gui/graph_node.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'scene/gui/graph_node.cpp')
-rw-r--r--scene/gui/graph_node.cpp150
1 files changed, 117 insertions, 33 deletions
diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp
index 7a7b35585e..5cb28a30e8 100644
--- a/scene/gui/graph_node.cpp
+++ b/scene/gui/graph_node.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -31,6 +31,7 @@
#include "graph_node.h"
#include "core/string/translation.h"
+
#ifdef TOOLS_ENABLED
#include "graph_edit.h"
#endif
@@ -46,7 +47,7 @@ bool GraphNode::_set(const StringName &p_name, const Variant &p_value) {
if (str.begins_with("opentype_features/")) {
String name = str.get_slicec('/', 1);
int32_t tag = TS->name_to_tag(name);
- double value = p_value;
+ int value = p_value;
if (value == -1) {
if (opentype_features.has(tag)) {
opentype_features.erase(tag);
@@ -54,7 +55,7 @@ bool GraphNode::_set(const StringName &p_name, const Variant &p_value) {
update();
}
} else {
- if ((double)opentype_features[tag] != value) {
+ if (!opentype_features.has(tag) || (int)opentype_features[tag] != value) {
opentype_features[tag] = value;
_shape();
update();
@@ -92,11 +93,13 @@ bool GraphNode::_set(const StringName &p_name, const Variant &p_value) {
si.color_right = p_value;
} else if (what == "right_icon") {
si.custom_slot_right = p_value;
+ } else if (what == "draw_stylebox") {
+ si.draw_stylebox = p_value;
} else {
return false;
}
- set_slot(idx, si.enable_left, si.type_left, si.color_left, si.enable_right, si.type_right, si.color_right, si.custom_slot_left, si.custom_slot_right);
+ set_slot(idx, si.enable_left, si.type_left, si.color_left, si.enable_right, si.type_right, si.color_right, si.custom_slot_left, si.custom_slot_right, si.draw_stylebox);
update();
return true;
}
@@ -143,6 +146,8 @@ bool GraphNode::_get(const StringName &p_name, Variant &r_ret) const {
r_ret = si.color_right;
} else if (what == "right_icon") {
r_ret = si.custom_slot_right;
+ } else if (what == "draw_stylebox") {
+ r_ret = si.draw_stylebox;
} else {
return false;
}
@@ -153,7 +158,7 @@ bool GraphNode::_get(const StringName &p_name, Variant &r_ret) const {
void GraphNode::_get_property_list(List<PropertyInfo> *p_list) const {
for (const Variant *ftr = opentype_features.next(nullptr); ftr != nullptr; ftr = opentype_features.next(ftr)) {
String name = TS->tag_to_name(*ftr);
- p_list->push_back(PropertyInfo(Variant::FLOAT, "opentype_features/" + name));
+ p_list->push_back(PropertyInfo(Variant::INT, "opentype_features/" + name));
}
p_list->push_back(PropertyInfo(Variant::NIL, "opentype_features/_new", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR));
@@ -174,7 +179,7 @@ void GraphNode::_get_property_list(List<PropertyInfo> *p_list) const {
p_list->push_back(PropertyInfo(Variant::INT, base + "right_type"));
p_list->push_back(PropertyInfo(Variant::COLOR, base + "right_color"));
p_list->push_back(PropertyInfo(Variant::OBJECT, base + "right_icon", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_STORE_IF_NULL));
-
+ p_list->push_back(PropertyInfo(Variant::BOOL, base + "draw_stylebox"));
idx++;
}
}
@@ -184,6 +189,7 @@ void GraphNode::_resort() {
Size2i new_size = get_size();
Ref<StyleBox> sb = get_theme_stylebox(SNAME("frame"));
+ Ref<StyleBox> sb_slot = get_theme_stylebox(SNAME("slot"));
int sep = get_theme_constant(SNAME("separation"));
@@ -192,7 +198,7 @@ void GraphNode::_resort() {
int stretch_min = 0;
int stretch_avail = 0;
float stretch_ratio_total = 0;
- Map<Control *, _MinSizeCache> min_size_cache;
+ HashMap<Control *, _MinSizeCache> min_size_cache;
for (int i = 0; i < get_child_count(); i++) {
Control *c = Object::cast_to<Control>(get_child(i));
@@ -203,7 +209,7 @@ void GraphNode::_resort() {
continue;
}
- Size2i size = c->get_combined_minimum_size();
+ Size2i size = c->get_combined_minimum_size() + (slot_info[i].draw_stylebox ? sb_slot->get_minimum_size() : Size2());
_MinSizeCache msc;
stretch_min += size.height;
@@ -311,7 +317,9 @@ void GraphNode::_resort() {
int size = to - from;
- Rect2 rect(sb->get_margin(SIDE_LEFT), from, w, size);
+ float margin = sb->get_margin(SIDE_LEFT) + (slot_info[i].draw_stylebox ? sb_slot->get_margin(SIDE_LEFT) : 0);
+ float width = w - (slot_info[i].draw_stylebox ? sb_slot->get_minimum_size().x : 0);
+ Rect2 rect(margin, from, width, size);
fit_child_in_rect(c, rect);
cache_y.push_back(from - sb->get_margin(SIDE_TOP) + size * 0.5);
@@ -350,14 +358,14 @@ void GraphNode::_notification(int p_what) {
Ref<StyleBox> sb;
if (comment) {
- sb = get_theme_stylebox(selected ? "commentfocus" : "comment");
+ sb = get_theme_stylebox(selected ? SNAME("comment_focus") : SNAME("comment"));
} else {
- sb = get_theme_stylebox(selected ? "selectedframe" : "frame");
+ sb = get_theme_stylebox(selected ? SNAME("selected_frame") : SNAME("frame"));
}
- //sb=sb->duplicate();
- //sb->call("set_modulate",modulate);
+ Ref<StyleBox> sb_slot = get_theme_stylebox(SNAME("slot"));
+
Ref<Texture2D> port = get_theme_icon(SNAME("port"));
Ref<Texture2D> close = get_theme_icon(SNAME("close"));
Ref<Texture2D> resizer = get_theme_icon(SNAME("resizer"));
@@ -388,14 +396,9 @@ void GraphNode::_notification(int p_what) {
int w = get_size().width - sb->get_minimum_size().x;
- if (show_close) {
- w -= close->get_width();
- }
-
- title_buf->set_width(w);
title_buf->draw(get_canvas_item(), Point2(sb->get_margin(SIDE_LEFT) + title_h_offset, -title_buf->get_size().y + title_offset), title_color);
if (show_close) {
- Vector2 cpos = Point2(w + sb->get_margin(SIDE_LEFT) + close_h_offset, -close->get_height() + close_offset);
+ Vector2 cpos = Point2(w + sb->get_margin(SIDE_LEFT) + close_h_offset - close->get_width(), -close->get_height() + close_offset);
draw_texture(close, cpos, close_color);
close_rect.position = cpos;
close_rect.size = close->get_size();
@@ -411,7 +414,7 @@ void GraphNode::_notification(int p_what) {
continue;
}
const Slot &s = slot_info[E.key];
- //left
+ // Left port.
if (s.enable_left) {
Ref<Texture2D> p = port;
if (s.custom_slot_left.is_valid()) {
@@ -419,6 +422,7 @@ void GraphNode::_notification(int p_what) {
}
p->draw(get_canvas_item(), icofs + Point2(edgeofs, cache_y[E.key]), s.color_left);
}
+ // Right port.
if (s.enable_right) {
Ref<Texture2D> p = port;
if (s.custom_slot_right.is_valid()) {
@@ -426,6 +430,15 @@ void GraphNode::_notification(int p_what) {
}
p->draw(get_canvas_item(), icofs + Point2(get_size().x - edgeofs, cache_y[E.key]), s.color_right);
}
+
+ // Draw slot stylebox.
+ if (s.draw_stylebox) {
+ Control *c = Object::cast_to<Control>(get_child(E.key));
+ Rect2 c_rect = c->get_rect();
+ c_rect.position.x = sb->get_margin(SIDE_LEFT);
+ c_rect.size.width = w;
+ draw_style_box(sb_slot, c_rect);
+ }
}
if (resizable) {
@@ -482,7 +495,7 @@ void GraphNode::_validate_property(PropertyInfo &property) const {
}
#endif
-void GraphNode::set_slot(int p_idx, bool p_enable_left, int p_type_left, const Color &p_color_left, bool p_enable_right, int p_type_right, const Color &p_color_right, const Ref<Texture2D> &p_custom_left, const Ref<Texture2D> &p_custom_right) {
+void GraphNode::set_slot(int p_idx, bool p_enable_left, int p_type_left, const Color &p_color_left, bool p_enable_right, int p_type_right, const Color &p_color_right, const Ref<Texture2D> &p_custom_left, const Ref<Texture2D> &p_custom_right, bool p_draw_stylebox) {
ERR_FAIL_COND_MSG(p_idx < 0, vformat("Cannot set slot with p_idx (%d) lesser than zero.", p_idx));
if (!p_enable_left && p_type_left == 0 && p_color_left == Color(1, 1, 1, 1) &&
@@ -501,6 +514,7 @@ void GraphNode::set_slot(int p_idx, bool p_enable_left, int p_type_left, const C
s.color_right = p_color_right;
s.custom_slot_left = p_custom_left;
s.custom_slot_right = p_custom_right;
+ s.draw_stylebox = p_draw_stylebox;
slot_info[p_idx] = s;
update();
connpos_dirty = true;
@@ -622,16 +636,39 @@ Color GraphNode::get_slot_color_right(int p_idx) const {
return slot_info[p_idx].color_right;
}
+bool GraphNode::is_slot_draw_stylebox(int p_idx) const {
+ if (!slot_info.has(p_idx)) {
+ return false;
+ }
+ return slot_info[p_idx].draw_stylebox;
+}
+
+void GraphNode::set_slot_draw_stylebox(int p_idx, bool p_enable) {
+ ERR_FAIL_COND_MSG(p_idx < 0, vformat("Cannot set draw_stylebox for the slot with p_idx (%d) lesser than zero.", p_idx));
+
+ slot_info[p_idx].draw_stylebox = p_enable;
+ update();
+ connpos_dirty = true;
+
+ emit_signal(SNAME("slot_updated"), p_idx);
+}
+
Size2 GraphNode::get_minimum_size() const {
- int sep = get_theme_constant(SNAME("separation"));
Ref<StyleBox> sb = get_theme_stylebox(SNAME("frame"));
+ Ref<StyleBox> sb_slot = get_theme_stylebox(SNAME("slot"));
+
+ int sep = get_theme_constant(SNAME("separation"));
+ int title_h_offset = get_theme_constant(SNAME("title_h_offset"));
+
bool first = true;
Size2 minsize;
- minsize.x = title_buf->get_size().x;
+ minsize.x = title_buf->get_size().x + title_h_offset;
if (show_close) {
+ int close_h_offset = get_theme_constant(SNAME("close_h_offset"));
Ref<Texture2D> close = get_theme_icon(SNAME("close"));
- minsize.x += sep + close->get_width();
+ //TODO: Remove this magic number after GraphNode rework.
+ minsize.x += 12 + close->get_width() + close_h_offset;
}
for (int i = 0; i < get_child_count(); i++) {
@@ -644,6 +681,9 @@ Size2 GraphNode::get_minimum_size() const {
}
Size2i size = c->get_combined_minimum_size();
+ if (slot_info.has(i)) {
+ size += slot_info[i].draw_stylebox ? sb_slot->get_minimum_size() : Size2();
+ }
minsize.y += size.y;
minsize.x = MAX(minsize.x, size.x);
@@ -792,6 +832,7 @@ void GraphNode::_connpos_update() {
cc.pos = Point2i(edgeofs, y + h / 2);
cc.type = slot_info[idx].type_left;
cc.color = slot_info[idx].color_left;
+ cc.height = size.height;
conn_input_cache.push_back(cc);
}
if (slot_info[idx].enable_right) {
@@ -799,6 +840,7 @@ void GraphNode::_connpos_update() {
cc.pos = Point2i(get_size().width - edgeofs, y + h / 2);
cc.type = slot_info[idx].type_right;
cc.color = slot_info[idx].color_right;
+ cc.height = size.height;
conn_output_cache.push_back(cc);
}
}
@@ -819,12 +861,13 @@ int GraphNode::get_connection_input_count() {
return conn_input_cache.size();
}
-int GraphNode::get_connection_output_count() {
+int GraphNode::get_connection_input_height(int p_idx) {
if (connpos_dirty) {
_connpos_update();
}
- return conn_output_cache.size();
+ ERR_FAIL_INDEX_V(p_idx, conn_input_cache.size(), 0);
+ return conn_input_cache[p_idx].height;
}
Vector2 GraphNode::get_connection_input_position(int p_idx) {
@@ -857,6 +900,23 @@ Color GraphNode::get_connection_input_color(int p_idx) {
return conn_input_cache[p_idx].color;
}
+int GraphNode::get_connection_output_count() {
+ if (connpos_dirty) {
+ _connpos_update();
+ }
+
+ return conn_output_cache.size();
+}
+
+int GraphNode::get_connection_output_height(int p_idx) {
+ if (connpos_dirty) {
+ _connpos_update();
+ }
+
+ ERR_FAIL_INDEX_V(p_idx, conn_output_cache.size(), 0);
+ return conn_output_cache[p_idx].height;
+}
+
Vector2 GraphNode::get_connection_output_position(int p_idx) {
if (connpos_dirty) {
_connpos_update();
@@ -959,6 +1019,25 @@ bool GraphNode::is_resizable() const {
return resizable;
}
+Vector<int> GraphNode::get_allowed_size_flags_horizontal() const {
+ Vector<int> flags;
+ flags.append(SIZE_FILL);
+ flags.append(SIZE_SHRINK_BEGIN);
+ flags.append(SIZE_SHRINK_CENTER);
+ flags.append(SIZE_SHRINK_END);
+ return flags;
+}
+
+Vector<int> GraphNode::get_allowed_size_flags_vertical() const {
+ Vector<int> flags;
+ flags.append(SIZE_FILL);
+ flags.append(SIZE_EXPAND);
+ flags.append(SIZE_SHRINK_BEGIN);
+ flags.append(SIZE_SHRINK_CENTER);
+ flags.append(SIZE_SHRINK_END);
+ return flags;
+}
+
void GraphNode::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_title", "title"), &GraphNode::set_title);
ClassDB::bind_method(D_METHOD("get_title"), &GraphNode::get_title);
@@ -970,7 +1049,7 @@ void GraphNode::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_language", "language"), &GraphNode::set_language);
ClassDB::bind_method(D_METHOD("get_language"), &GraphNode::get_language);
- ClassDB::bind_method(D_METHOD("set_slot", "idx", "enable_left", "type_left", "color_left", "enable_right", "type_right", "color_right", "custom_left", "custom_right"), &GraphNode::set_slot, DEFVAL(Ref<Texture2D>()), DEFVAL(Ref<Texture2D>()));
+ ClassDB::bind_method(D_METHOD("set_slot", "idx", "enable_left", "type_left", "color_left", "enable_right", "type_right", "color_right", "custom_left", "custom_right", "enable"), &GraphNode::set_slot, DEFVAL(Ref<Texture2D>()), DEFVAL(Ref<Texture2D>()), DEFVAL(true));
ClassDB::bind_method(D_METHOD("clear_slot", "idx"), &GraphNode::clear_slot);
ClassDB::bind_method(D_METHOD("clear_all_slots"), &GraphNode::clear_all_slots);
@@ -992,6 +1071,9 @@ void GraphNode::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_slot_color_right", "idx", "color_right"), &GraphNode::set_slot_color_right);
ClassDB::bind_method(D_METHOD("get_slot_color_right", "idx"), &GraphNode::get_slot_color_right);
+ ClassDB::bind_method(D_METHOD("is_slot_draw_stylebox", "idx"), &GraphNode::is_slot_draw_stylebox);
+ ClassDB::bind_method(D_METHOD("set_slot_draw_stylebox", "idx", "draw_stylebox"), &GraphNode::set_slot_draw_stylebox);
+
ClassDB::bind_method(D_METHOD("set_position_offset", "offset"), &GraphNode::set_position_offset);
ClassDB::bind_method(D_METHOD("get_position_offset"), &GraphNode::get_position_offset);
@@ -1004,15 +1086,17 @@ void GraphNode::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_selected", "selected"), &GraphNode::set_selected);
ClassDB::bind_method(D_METHOD("is_selected"), &GraphNode::is_selected);
- ClassDB::bind_method(D_METHOD("get_connection_output_count"), &GraphNode::get_connection_output_count);
ClassDB::bind_method(D_METHOD("get_connection_input_count"), &GraphNode::get_connection_input_count);
+ ClassDB::bind_method(D_METHOD("get_connection_input_height", "idx"), &GraphNode::get_connection_input_height);
+ ClassDB::bind_method(D_METHOD("get_connection_input_position", "idx"), &GraphNode::get_connection_input_position);
+ ClassDB::bind_method(D_METHOD("get_connection_input_type", "idx"), &GraphNode::get_connection_input_type);
+ ClassDB::bind_method(D_METHOD("get_connection_input_color", "idx"), &GraphNode::get_connection_input_color);
+ ClassDB::bind_method(D_METHOD("get_connection_output_count"), &GraphNode::get_connection_output_count);
+ ClassDB::bind_method(D_METHOD("get_connection_output_height", "idx"), &GraphNode::get_connection_output_height);
ClassDB::bind_method(D_METHOD("get_connection_output_position", "idx"), &GraphNode::get_connection_output_position);
ClassDB::bind_method(D_METHOD("get_connection_output_type", "idx"), &GraphNode::get_connection_output_type);
ClassDB::bind_method(D_METHOD("get_connection_output_color", "idx"), &GraphNode::get_connection_output_color);
- ClassDB::bind_method(D_METHOD("get_connection_input_position", "idx"), &GraphNode::get_connection_input_position);
- ClassDB::bind_method(D_METHOD("get_connection_input_type", "idx"), &GraphNode::get_connection_input_type);
- ClassDB::bind_method(D_METHOD("get_connection_input_color", "idx"), &GraphNode::get_connection_input_color);
ClassDB::bind_method(D_METHOD("set_show_close_button", "show"), &GraphNode::set_show_close_button);
ClassDB::bind_method(D_METHOD("is_close_button_visible"), &GraphNode::is_close_button_visible);
@@ -1022,7 +1106,7 @@ void GraphNode::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::STRING, "title"), "set_title", "get_title");
ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction");
- ADD_PROPERTY(PropertyInfo(Variant::STRING, "language"), "set_language", "get_language");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "language", PROPERTY_HINT_LOCALE_ID, ""), "set_language", "get_language");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "position_offset"), "set_position_offset", "get_position_offset");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_close"), "set_show_close_button", "is_close_button_visible");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "resizable"), "set_resizable", "is_resizable");