93#include "RNA_prototypes.hh"
105#include <fmt/format.h>
116#define NODE_ZONE_PADDING UI_UNIT_X
117#define ZONE_ZONE_PADDING 0.3f * UI_UNIT_X
118#define EXTRA_INFO_ROW_HEIGHT (20.0f * UI_SCALE_FAC)
197 if (
id ==
nullptr || ntree ==
nullptr) {
228 else if (
id == &ntree->
id) {
241 if (socket.
runtime->declaration ==
nullptr) {
245 const std::optional<std::string> &translation_context =
246 socket.
runtime->declaration->translation_context;
249 if (!translation_context.has_value()) {
253 return translation_context->c_str();
282 for (
bNode *parent =
b->parent; parent; parent = parent->parent) {
305 if (a_active && !b_active) {
308 if (b_active && !a_active) {
311 if (!b_select && (a_active || a_select)) {
314 if (!a_select && (b_active || b_select)) {
325 return a->ui_order < b->ui_order;
329 sort_nodes[
i]->ui_order =
i;
336 if (
nodes.is_empty()) {
340 return a->ui_order < b->ui_order;
348 if (
nodes.is_empty()) {
352 return a->ui_order > b->ui_order;
365 for (
const int i :
nodes.index_range()) {
367 std::string block_name =
"node_" + std::string(node.
name);
370 blocks[node.index()] = block;
406 return node.declaration() && node.declaration()->use_custom_socket_order;
440 if (node.is_muted()) {
446 draw_buttons(layout, (
bContext *)&
C, &nodeptr);
463 if (socket_short_label.has_value()) {
464 return CTX_IFACE_(socket_translation_context, socket_short_label->c_str());
468 const char *translated_socket_label =
CTX_IFACE_(socket_translation_context,
469 socket_label.
c_str());
473 const int len_prefix = strlen(panel_label);
474 if (
STREQLEN(translated_socket_label, panel_label, len_prefix) &&
475 translated_socket_label[len_prefix] ==
' ')
477 return translated_socket_label + len_prefix + 1;
482 return translated_socket_label;
488 const char *panel_label,
495 if ((!input_socket || !input_socket->is_visible()) &&
496 (!output_socket || !output_socket->is_visible()))
501 const int topy = locy;
506 const float multi_input_socket_offset = is_multi_input ?
507 std::max(input_socket->
runtime->total_inputs - 2,
511 locy -= multi_input_socket_offset * 0.5f;
523 if (node.is_muted()) {
574 locy = buty - multi_input_socket_offset * 0.5;
630 return std::visit([](
auto &&
item) {
return item.type; }, this->
item);
637 bool potentially_visible =
false;
640 const bNodeSocket &socket = node.socket_by_decl(*socket_decl);
641 potentially_visible |= socket.is_visible();
646 potentially_visible |= r_result[sub_panel_decl->index];
649 r_result[panel_decl.
index] = potentially_visible;
669 if (!potentially_visible_states[panel_decl.
index]) {
673 r_result[panel_decl.
index] =
true;
675 if (panel_state.is_collapsed()) {
682 node, *sub_panel_decl, potentially_visible_states, r_result);
694 node, *panel_decl, potentially_visible_states, r_result);
706 Array<bool> potentially_visible_states(r_visibility_states.
size(),
false);
717 bNodeSocket &socket = node.socket_by_decl(socket_decl);
718 if (!socket.is_visible()) {
722 if (!prev_socket_decl || !node.socket_by_decl(*prev_socket_decl).is_visible()) {
732 item.
input = &socket;
761 if (!panel_visibility[panel_decl.
index]) {
765 header_item.
decl = &panel_decl;
767 if (panel_input_decl) {
768 header_item.
input = &node.socket_by_decl(*panel_input_decl);
770 r_items.
append({header_item});
773 if (panel_state.is_collapsed()) {
779 if (item_decl == panel_input_decl) {
784 prev_socket_decl = socket_decl;
797 prev_socket_decl =
nullptr;
821 prev_socket_decl = socket_decl;
834 prev_socket_decl =
nullptr;
851 switch (first_item_type) {
873 switch (last_item_type) {
898 const Type prev_type = prev.type();
908 case Type::Separator:
912 case Type::PanelHeader:
914 case Type::PanelContentBegin:
916 case Type::PanelContentEnd:
925 case Type::Separator:
929 case Type::PanelHeader:
931 case Type::PanelContentBegin:
933 case Type::PanelContentEnd:
938 case Type::Separator: {
942 case Type::Separator:
946 case Type::PanelHeader:
948 case Type::PanelContentBegin:
950 case Type::PanelContentEnd:
955 case Type::PanelHeader: {
959 case Type::Separator:
963 case Type::PanelHeader:
965 case Type::PanelContentBegin:
967 case Type::PanelContentEnd:
972 case Type::PanelContentBegin: {
976 case Type::Separator:
980 case Type::PanelHeader:
982 case Type::PanelContentBegin:
984 case Type::PanelContentEnd:
989 case Type::PanelContentEnd: {
993 case Type::Separator:
997 case Type::PanelHeader:
999 case Type::PanelContentBegin:
1001 case Type::PanelContentEnd:
1013 const int node_left_x,
1027 bNodeSocket &socket = node.socket_by_decl(*socket_decl);
1041 const int node_left_x,
1045 if (panel_state.is_collapsed()) {
1076 for (
int item_i = items.
size() - 1; item_i >= 0; item_i--) {
1078 if (
const auto *panel_item = std::get_if<flat_item::PanelContentEnd>(&item.
item)) {
1079 final_panel = panel_item;
1104 for (
bNodeSocket *socket : node.input_sockets()) {
1107 for (
bNodeSocket *socket : node.output_sockets()) {
1119 for (
const int item_i : flat_items.
index_range()) {
1133 [&](
const auto &item) {
1134 using ItemT = std::decay_t<
decltype(item)>;
1135 if constexpr (std::is_same_v<ItemT, flat_item::Socket>) {
1139 const char *parent_label = panel_decl ? panel_decl->
name.c_str() :
"";
1141 C, ntree, node, parent_label, input_socket, output_socket, block, locx, locy);
1143 else if constexpr (std::is_same_v<ItemT, flat_item::Layout>) {
1156 if (node.is_muted()) {
1167 else if constexpr (std::is_same_v<ItemT, flat_item::Separator>) {
1180 else if constexpr (std::is_same_v<ItemT, flat_item::PanelHeader>) {
1183 const float panel_header_height =
NODE_DYS;
1184 locy -= panel_header_height / 2;
1186 locy -= panel_header_height / 2;
1193 else if constexpr (std::is_same_v<ItemT, flat_item::PanelContentBegin>) {
1199 else if constexpr (std::is_same_v<ItemT, flat_item::PanelContentEnd>) {
1209 locy -= bottom_margin;
1223 bool add_output_space =
false;
1225 for (
bNodeSocket *socket : node.output_sockets()) {
1233 add_output_space =
true;
1237 if (add_output_space) {
1242 C, ntree, node, node.
typeinfo->draw_buttons, block, locy);
1244 bool add_input_space =
false;
1247 for (
bNodeSocket *socket : node.input_sockets()) {
1255 add_input_space =
true;
1260 if (add_input_space || add_button_space) {
1289 node.
runtime->draw_bounds.xmin = loc.x;
1291 node.
runtime->draw_bounds.ymax = loc.y;
1298 node.
runtime->draw_bounds.ymin,
1300 node.
runtime->draw_bounds.ymax);
1308 int totin = 0, totout = 0;
1314 for (
const bNodeSocket *socket : node.input_sockets()) {
1315 if (socket->is_visible()) {
1319 for (
const bNodeSocket *socket : node.output_sockets()) {
1320 if (socket->is_visible()) {
1326 float tot = std::max(totin, totout);
1328 hiddenrad += 5.0f * float(tot - 4);
1331 node.
runtime->draw_bounds.xmin = loc.x;
1333 node.
runtime->draw_bounds.ymax = loc.y + (hiddenrad - 0.5f *
NODE_DY);
1334 node.
runtime->draw_bounds.ymin = node.
runtime->draw_bounds.ymax - 2 * hiddenrad;
1337 float rad = float(
M_PI) / (1.0f + float(totout));
1340 for (
bNodeSocket *socket : node.output_sockets()) {
1341 if (socket->is_visible()) {
1343 socket->runtime->location = {
1345 round(node.
runtime->draw_bounds.ymin + hiddenrad +
cosf(rad) * hiddenrad)};
1351 rad = drad = -float(
M_PI) / (1.0f + float(totin));
1353 for (
bNodeSocket *socket : node.input_sockets()) {
1354 if (socket->is_visible()) {
1356 socket->runtime->location = {
1358 round(node.
runtime->draw_bounds.ymin + hiddenrad +
cosf(rad) * hiddenrad)};
1367 node.
runtime->draw_bounds.ymin,
1369 node.
runtime->draw_bounds.ymax);
1374 const int nclass = (node.
typeinfo->ui_class ==
nullptr) ? node.
typeinfo->nclass :
1429 for (
const bNodeLink &link : node.internal_links()) {
1439 const int socket_index_in_tree,
1449 location.x -
size.x / 2.0f,
1450 location.y -
size.y / 2.0f,
1463 ntree.ensure_topology_cache();
1473 const int socket_type,
1474 float r_outline_color[4])
1486 r_outline_color[3] = 1.0f;
1498 if (sock.
typeinfo->draw_color_simple) {
1509 &
const_cast<ID &
>(ntree.
id), &RNA_NodeSocket, &
const_cast<bNodeSocket &
>(sock));
1515 fmt::memory_buffer &buf)
1517 auto id_to_inspection_string = [&](
const ID *id,
const short idcode) {
1518 fmt::format_to(fmt::appender(buf),
"{}",
id ? id->
name + 2 :
TIP_(
"None"));
1519 fmt::format_to(fmt::appender(buf),
" (");
1521 fmt::format_to(fmt::appender(buf),
")");
1525 const void *buffer = value.
get();
1527 id_to_inspection_string(*
static_cast<const ID *
const *
>(buffer),
ID_OB);
1531 id_to_inspection_string(*
static_cast<const ID *
const *
>(buffer),
ID_MA);
1534 if (value_type.
is<
Tex *>()) {
1535 id_to_inspection_string(*
static_cast<const ID *
const *
>(buffer),
ID_TE);
1538 if (value_type.
is<
Image *>()) {
1539 id_to_inspection_string(*
static_cast<const ID *
const *
>(buffer),
ID_IM);
1543 id_to_inspection_string(*
static_cast<const ID *
const *
>(buffer),
ID_GR);
1550 if (!value_type.
is<
int>()) {
1553 const int item_identifier = *
static_cast<const int *
>(buffer);
1555 if (!socket_storage->enum_items) {
1558 if (socket_storage->has_conflict()) {
1562 socket_storage->enum_items->find_item_by_identifier(item_identifier);
1566 fmt::format_to(fmt::appender(buf), fmt::runtime(
TIP_(
"{} (Menu)")), enum_item->
name);
1571 if (value_type != socket_type) {
1572 if (!convert.is_convertible(value_type, socket_type)) {
1578 convert.convert_to_uninitialized(value_type, socket_type, buffer, socket_value);
1581 if (socket_type.
is<
int>()) {
1583 fmt::appender(buf), fmt::runtime(
TIP_(
"{} (Integer)")), *
static_cast<int *
>(socket_value));
1585 else if (socket_type.
is<
float>()) {
1586 const float float_value = *
static_cast<float *
>(socket_value);
1588 if (std::abs(float_value) > (1 << 24)) {
1591 fmt::format_to(fmt::appender(buf), fmt::runtime(
TIP_(
"{:.10} (Float)")), float_value);
1594 fmt::format_to(fmt::appender(buf), fmt::runtime(
TIP_(
"{} (Float)")), float_value);
1599 fmt::format_to(fmt::appender(buf),
1600 fmt::runtime(
TIP_(
"({}, {}, {}) (Vector)")),
1607 fmt::format_to(fmt::appender(buf),
1608 fmt::runtime(
TIP_(
"({}, {}, {}, {}) (Color)")),
1617 fmt::format_to(fmt::appender(buf),
1623 fmt::format_to(fmt::appender(buf),
"{}",
TIP_(
"(Rotation)"));
1625 else if (socket_type.
is<
bool>()) {
1626 fmt::format_to(fmt::appender(buf),
1627 fmt::runtime(
TIP_(
"{} (Boolean)")),
1628 ((*
static_cast<bool *
>(socket_value)) ?
TIP_(
"True") :
TIP_(
"False")));
1633 std::stringstream ss;
1634 ss << value[0] <<
",\n";
1635 ss << value[1] <<
",\n";
1636 ss << value[2] <<
",\n";
1637 ss << value[3] <<
",\n";
1638 buf.append(ss.str());
1639 fmt::format_to(fmt::appender(buf),
"{}",
TIP_(
"(Matrix)"));
1645 fmt::memory_buffer &buf)
1653 fmt::format_to(fmt::appender(buf),
"{}",
TIP_(
"Value has not been logged"));
1656 if (socket_type.
is<
int>()) {
1657 fmt::format_to(fmt::appender(buf),
"{}",
TIP_(
"Integer field based on:"));
1659 else if (socket_type.
is<
float>()) {
1660 fmt::format_to(fmt::appender(buf),
"{}",
TIP_(
"Float field based on:"));
1663 fmt::format_to(fmt::appender(buf),
"{}",
TIP_(
"Vector field based on:"));
1665 else if (socket_type.
is<
bool>()) {
1666 fmt::format_to(fmt::appender(buf),
"{}",
TIP_(
"Boolean field based on:"));
1668 else if (socket_type.
is<std::string>()) {
1669 fmt::format_to(fmt::appender(buf),
"{}",
TIP_(
"String field based on:"));
1672 fmt::format_to(fmt::appender(buf),
"{}",
TIP_(
"Color field based on:"));
1675 fmt::format_to(fmt::appender(buf),
"{}",
TIP_(
"Rotation field based on:"));
1677 fmt::format_to(fmt::appender(buf),
"\n");
1681 fmt::format_to(fmt::appender(buf), fmt::runtime(
TIP_(
"\u2022 {}")),
TIP_(tooltip));
1682 if (
i < input_tooltips.
size() - 1) {
1683 fmt::format_to(fmt::appender(buf),
".\n");
1690 fmt::memory_buffer &buf)
1695 return std::string(
str);
1701 fmt::appender(buf),
"{}", grid_info.
is_empty ?
TIP_(
"Empty Grid") :
TIP_(
"\u2022 Grid"));
1707 fmt::format_to(fmt::appender(buf),
"{}",
TIP_(
"Empty Geometry"));
1711 fmt::format_to(fmt::appender(buf),
"{}",
TIP_(
"Geometry:"));
1712 if (!value_log.
name.empty()) {
1713 fmt::format_to(fmt::appender(buf),
" \"{}\"", value_log.
name);
1715 fmt::format_to(fmt::appender(buf),
"\n");
1720 fmt::format_to(fmt::appender(buf),
1721 fmt::runtime(
TIP_(
"\u2022 Mesh: {} vertices, {} edges, {} faces")),
1730 fmt::format_to(fmt::appender(buf),
1731 fmt::runtime(
TIP_(
"\u2022 Point Cloud: {} points")),
1737 fmt::format_to(fmt::appender(buf),
1738 fmt::runtime(
TIP_(
"\u2022 Curve: {} points, {} splines")),
1745 fmt::format_to(fmt::appender(buf),
1746 fmt::runtime(
TIP_(
"\u2022 Instances: {}")),
1752 fmt::format_to(fmt::appender(buf),
1753 fmt::runtime(
TIP_(
"\u2022 Volume: {} grids")),
1760 fmt::format_to(fmt::appender(buf),
1761 fmt::runtime(
TIP_(
"\u2022 Edit: {}, {}, {}")),
1763 TIP_(
"no positions"),
1772 fmt::format_to(fmt::appender(buf),
1773 fmt::runtime(
TIP_(
"\u2022 Grease Pencil: {} layers")),
1778 if (type != component_types.
last()) {
1779 fmt::format_to(fmt::appender(buf),
".\n");
1795 fmt::format_to(fmt::appender(buf),
"{}",
TIP_(
"Supported: All Types"));
1799 fmt::format_to(fmt::appender(buf),
"{}",
TIP_(
"Supported: "));
1803 fmt::format_to(fmt::appender(buf),
"{}",
TIP_(
"Mesh"));
1807 fmt::format_to(fmt::appender(buf),
"{}",
TIP_(
"Point Cloud"));
1811 fmt::format_to(fmt::appender(buf),
"{}",
TIP_(
"Curve"));
1815 fmt::format_to(fmt::appender(buf),
"{}",
TIP_(
"Instances"));
1826 fmt::format_to(fmt::appender(buf),
"{}",
TIP_(
"Grease Pencil"));
1830 if (type != supported_types.
last()) {
1831 fmt::format_to(fmt::appender(buf),
", ");
1837 fmt::memory_buffer &buf)
1840 fmt::format_to(fmt::appender(buf),
"{}",
TIP_(
"Empty Bundle"));
1843 fmt::format_to(fmt::appender(buf),
"{}",
TIP_(
"Bundle values:\n"));
1845 fmt::format_to(fmt::appender(buf),
1846 fmt::runtime(
"\u2022 \"{}\" ({})\n"),
1853 fmt::memory_buffer &buf)
1856 fmt::format_to(fmt::appender(buf),
"{}",
TIP_(
"Empty Closure"));
1859 fmt::format_to(fmt::appender(buf),
"{}:\n",
TIP_(
"Inputs"));
1861 fmt::format_to(fmt::appender(buf),
1862 fmt::runtime(
"\u2022 {} ({})\n"),
1868 fmt::format_to(fmt::appender(buf),
"{}:\n",
TIP_(
"Outputs"));
1870 fmt::format_to(fmt::appender(buf),
1871 fmt::runtime(
"\u2022 {} ({})\n"),
1879 fmt::memory_buffer &buf)
1881 if (!socket.is_input()) {
1884 if (socket.is_multi_input()) {
1887 if (socket.owner_node().is_reroute()) {
1891 if (!connected_sockets.
is_empty() && !connected_sockets[0]->owner_node().is_dangling_reroute()) {
1899 if (socket.
typeinfo->base_cpp_type ==
nullptr) {
1912 if (socket.
runtime->declaration ==
nullptr) {
1916 return std::nullopt;
1921 return std::nullopt;
1924 return TIP_(description);
1930 if (geo_tree_log ==
nullptr) {
1931 return std::nullopt;
1933 if (socket.
typeinfo->base_cpp_type ==
nullptr) {
1934 return std::nullopt;
1939 fmt::memory_buffer buf;
1948 if (string_log->truncated) {
1949 fmt::format_to(fmt::appender(buf), fmt::runtime(
TIP_(
"{}... (String)")), string_log->value);
1952 fmt::format_to(fmt::appender(buf), fmt::runtime(
TIP_(
"{} (String)")), string_log->value);
1976 std::string
str = fmt::to_string(buf);
1978 return std::nullopt;
1985 fmt::memory_buffer buf;
1992 std::string
str = fmt::to_string(buf);
1994 return std::nullopt;
2002 std::istringstream text_stream(
text);
2003 for (std::string line; std::getline(text_stream, line);) {
2012 if (!socket.is_multi_input()) {
2013 return std::nullopt;
2019 for (
const int index : connected_links.
index_range()) {
2020 const bNodeLink *link = connected_links[index];
2021 const int connection_number = index + 1;
2022 if (!link->is_used()) {
2028 if (link->
fromnode->is_dangling_reroute()) {
2036 if (!input_log.has_value()) {
2039 numerated_info.
append({connection_number, std::move(*input_log)});
2043 return std::nullopt;
2046 fmt::memory_buffer buf;
2047 for (
const std::pair<int, std::string> &info : numerated_info) {
2049 fmt::format_to(fmt::appender(buf),
"{}", info.first);
2050 fmt::format_to(fmt::appender(buf),
". ");
2051 fmt::format_to(fmt::appender(buf),
"{}", lines.
first());
2052 for (
const std::string &line : lines.
as_span().drop_front(1)) {
2053 fmt::format_to(fmt::appender(buf),
"\n {}", line);
2055 if (&info != &numerated_info.
last()) {
2060 const std::string
str = fmt::to_string(buf);
2062 return std::nullopt;
2070 fmt::memory_buffer buf;
2073 std::string
str = fmt::to_string(buf);
2075 return std::nullopt;
2084 visited_nodes.
add(&reroute_output.owner_node());
2087 if (linked_sockets.
size() != 1) {
2090 const bNode &target_node = linked_sockets[0]->owner_node();
2091 if (!visited_nodes.
add(&target_node)) {
2094 if (!target_node.is_dangling_reroute()) {
2095 return linked_sockets[0];
2097 output = target_node.output_sockets()[0];
2105 return std::nullopt;
2108 const bNode &node = socket.owner_node();
2109 if (!node.is_dangling_reroute()) {
2110 return std::nullopt;
2113 const bNodeSocket &output_socket = *node.output_sockets()[0];
2116 if (target_socket ==
nullptr) {
2117 if (!output_socket.directly_linked_sockets().is_empty()) {
2118 return TIP_(
"Dangling reroute is ignored by all targets");
2120 return std::nullopt;
2123 if (target_socket->is_multi_input()) {
2124 return TIP_(
"Dangling reroute branch is ignored by multi input socket");
2127 fmt::memory_buffer buf;
2129 std::string
str = fmt::to_string(buf);
2131 return TIP_(
"Dangling reroute is ignored");
2133 fmt::format_to(fmt::appender(buf),
".\n\n");
2134 fmt::format_to(fmt::appender(buf),
2136 TIP_(
"Dangling reroute is ignored, default value of target socket is used"));
2145 if (snode !=
nullptr) {
2156 inspection_strings.
append(std::move(*info));
2159 inspection_strings.
append(std::move(*info));
2164 inspection_strings.
append(std::move(*info));
2167 inspection_strings.
append(std::move(*info));
2170 socket, tree_draw_ctx))
2172 inspection_strings.
append(std::move(*info));
2175 inspection_strings.
append(std::move(*info));
2177 if (
U.experimental.use_socket_structure_type) {
2178 if (socket.
runtime->declaration) {
2179 switch (socket.
runtime->declaration->structure_type) {
2180 case nodes::StructureType::Single:
2181 inspection_strings.
append(
TIP_(
"(Single Value)"));
2183 case nodes::StructureType::Dynamic:
2184 inspection_strings.
append(
TIP_(
"(Dynamic Structure Type)"));
2186 case nodes::StructureType::Field:
2189 case nodes::StructureType::Grid:
2190 inspection_strings.
append(
TIP_(
"(Volume Grid)"));
2196 std::stringstream
output;
2197 for (
const std::string &info : inspection_strings) {
2199 if (&info != &inspection_strings.
last()) {
2204 if (inspection_strings.
is_empty()) {
2205 const bool is_extend =
StringRef(socket.
idname) ==
"NodeSocketVirtual";
2206 const bNode &node = socket.owner_node();
2207 if (node.is_reroute()) {
2210 else if (is_extend) {
2211 output <<
TIP_(
"Connect a link to create a new socket");
2216 const char *translated_socket_label =
CTX_TIP_(socket_translation_context,
2217 socket_label.
c_str());
2218 output << translated_socket_label;
2224 "Unknown socket value. Either the socket was not used or its value was not logged "
2225 "during the last evaluation");
2240 ntree.ensure_topology_cache();
2250 struct SocketTooltipData {
2256 data->ntree = &ntree;
2257 data->socket = &sock;
2262 SocketTooltipData *
data =
static_cast<SocketTooltipData *
>(argN);
2271#define NODE_SOCKET_OUTLINE U.pixelsize
2277 const rctf draw_rect = {
2296#define NODE_TREE_SCALE_SMALL 0.2f
2323 immUniform4f(
"color1", checker_dark, checker_dark, checker_dark, 1.0f);
2324 immUniform4f(
"color2", checker_light, checker_light, checker_light, 1.0f);
2335 float xscale = xrect / float(preview->
x);
2336 float yscale = yrect / float(preview->
y);
2340 rctf draw_rect = *prv;
2341 if (xscale < yscale) {
2342 float offset = 0.5f * (yrect - float(preview->
y) * xscale);
2343 draw_rect.
ymin += offset;
2344 draw_rect.
ymax -= offset;
2348 float offset = 0.5f * (xrect - float(preview->
x) * yscale);
2349 draw_rect.
xmin += offset;
2350 draw_rect.
xmax -= offset;
2371 float black[4] = {0.0f, 0.0f, 0.0f, 1.0f};
2373 const float outline_width = 1.0f;
2374 draw_rect.
xmin -= outline_width;
2375 draw_rect.
xmax += outline_width;
2376 draw_rect.
ymin -= outline_width;
2377 draw_rect.
ymax += outline_width;
2387 const char *opname = (
const char *)op_argv;
2403 const float shadow_width = 0.6f *
U.widget_unit;
2404 const float shadow_alpha = 0.5f * alpha;
2409 const float color[4] = {0.0f, 0.0f, 0.0f, 0.4f};
2424 const float outline_thickness,
2425 const bool selected,
2441 socket_location.x - half_width,
2442 socket_location.x + half_width,
2443 socket_location.y - half_height,
2444 socket_location.y + half_height,
2448 &rect, socket_color, outline_color, outline_thickness, sock.
display_shape, aspect);
2451 block, sock.index_in_tree(), socket_location,
float2(2.0f * half_width, 2.0f * half_height));
2464 if (node.input_sockets().is_empty() && node.output_sockets().is_empty()) {
2469 const_cast<ID *
>(&ntree.
id), &RNA_Node,
const_cast<bNode *
>(&node));
2475 for (
const bNodeSocket *sock : node.input_sockets()) {
2476 if (!sock->is_icon_visible()) {
2479 const bool selected = (sock->flag &
SELECT);
2481 C, ntree, node, nodeptr, block, *sock, outline_thickness, selected, snode.
runtime->
aspect);
2485 for (
const bNodeSocket *sock : node.output_sockets()) {
2486 if (!sock->is_icon_visible()) {
2489 const bool selected = (sock->flag &
SELECT);
2491 C, ntree, node, nodeptr, block, *sock, outline_thickness, selected, snode.
runtime->
aspect);
2512 float panel_color[4];
2515 panel_color[3] *= 1.5f;
2516 const rctf &draw_bounds = node.
runtime->draw_bounds;
2521 for (
const int panel_i : node_decl.
panels.index_range()) {
2527 const rctf content_rect = {draw_bounds.
xmin,
2534 final_panel_decl = &panel_decl;
2537 if (final_panel_decl) {
2540 const rctf content_rect = {draw_bounds.
xmin,
2545 const int repeats = final_panel_decl->
depth() + 1;
2546 for ([[maybe_unused]]
const int i :
IndexRange(repeats)) {
2562 if (socket_decl->in_out ==
SOCK_OUT) {
2565 const bNodeSocket &socket = node.socket_by_decl(*socket_decl);
2566 if (!socket.is_inactive()) {
2583 const rctf &draw_bounds = node.
runtime->draw_bounds;
2586 for (
const int panel_i : node_decl.
panels.index_range()) {
2595 const rctf header_rect = {draw_bounds.
xmin,
2608 header_rect.
xmin + header_but_margin,
2610 std::max(
int(header_rect.
xmax - header_rect.
xmin - 2 * header_but_margin), 0),
2611 header_rect.
ymax - header_rect.
ymin,
2617 toggle_action_but, [&panel_state](
const uiBut &) {
return panel_state.is_collapsed(); });
2624 const int but_size =
U.widget_unit * 0.8f;
2630 panel_state.is_collapsed() ? ICON_RIGHTARROW : ICON_DOWNARROW_HLT,
2639 offsetx += but_size + but_padding;
2644 if (input_socket && !input_socket->is_logically_linked()) {
2646 &ntree.
id, &RNA_NodeSocket, input_socket);
2683 if (node.is_muted() || only_inactive_inputs) {
2691 int highest_priority = 0;
2694 const int priority = node_warning_type_severity(warning.type);
2695 if (priority > highest_priority) {
2696 highest_priority = priority;
2697 highest_priority_type = warning.type;
2700 return highest_priority_type;
2705 std::string complete_string;
2708 complete_string += warning.message;
2711 complete_string +=
'.';
2712 complete_string +=
'\n';
2716 complete_string += warnings.
last().message;
2718 return complete_string;
2721#define NODE_HEADER_ICON_SIZE (0.8f * U.widget_unit)
2771 if (node_log !=
nullptr) {
2819 if (tree_log ==
nullptr) {
2820 return std::nullopt;
2822 if (node.is_group_output()) {
2825 if (node.is_frame()) {
2827 std::chrono::nanoseconds run_time{0};
2828 bool found_node =
false;
2830 for (
const bNode *tnode : node.direct_children_in_frame()) {
2831 if (tnode->is_frame()) {
2833 tree_draw_ctx, snode, *tnode);
2834 if (sub_frame_run_time.has_value()) {
2835 run_time += *sub_frame_run_time;
2843 run_time += node_log->execution_time;
2850 return std::nullopt;
2853 return node_log->execution_time;
2855 return std::nullopt;
2880 bool has_any_execution_time =
false;
2882 for (
const bNode *current_node : node.direct_children_in_frame()) {
2887 frame_execution_time += *node_execution_time;
2888 has_any_execution_time =
true;
2892 if (!has_any_execution_time) {
2893 return std::nullopt;
2896 return frame_execution_time;
2905 if (node.is_frame()) {
2915 return *execution_time;
2918 return std::nullopt;
2930 return std::nullopt;
2939 tree_draw_ctx, snode, node);
2941 if (!exec_time.has_value()) {
2942 return std::string(
"");
2946 std::chrono::duration_cast<std::chrono::microseconds>(*exec_time).count();
2949 if (exec_time_us == 0) {
2950 return std::string(
"-");
2952 if (exec_time_us < 100) {
2953 return std::string(
"< 0.1 ms");
2958 if (exec_time_us < 1000) {
2961 else if (exec_time_us < 10000) {
2965 std::stringstream stream;
2966 stream << std::fixed << std::setprecision(precision) << (exec_time_us / 1000.0f);
2967 return stream.str() +
" ms";
2978 fmt::memory_buffer buf;
2979 fmt::format_to(fmt::appender(buf),
"{}",
TIP_(
"Accessed named attributes:"));
2980 fmt::format_to(fmt::appender(buf),
"\n");
2982 struct NameWithUsage {
2989 sorted_used_attribute.
append({item.key, item.value});
2991 std::sort(sorted_used_attribute.
begin(),
2992 sorted_used_attribute.
end(),
2993 [](
const NameWithUsage &a,
const NameWithUsage &
b) {
2994 return BLI_strcasecmp_natural(a.name.c_str(), b.name.c_str()) < 0;
2997 for (
const NameWithUsage &attribute : sorted_used_attribute) {
3000 fmt::format_to(fmt::appender(buf), fmt::runtime(
TIP_(
" \u2022 \"{}\": ")), name);
3012 fmt::format_to(fmt::appender(buf),
"{}", usages[
i]);
3013 if (
i < usages.
size() - 1) {
3014 fmt::format_to(fmt::appender(buf),
", ");
3017 fmt::format_to(fmt::appender(buf),
"\n");
3019 fmt::format_to(fmt::appender(buf),
"\n");
3022 fmt::runtime(
TIP_(
"Attributes with these names used within the group may conflict with "
3023 "existing attributes")));
3024 return fmt::to_string(buf);
3030 const int attributes_num = usage_by_attribute_name.
size();
3033 row.
text = std::to_string(attributes_num) +
3034 (attributes_num == 1 ?
RPT_(
" Named Attribute") :
RPT_(
" Named Attributes"));
3035 row.
icon = ICON_SPREADSHEET;
3046 if (geo_tree_log ==
nullptr) {
3047 return std::nullopt;
3055 for (
const bNodeSocket *socket : node.input_sockets()) {
3056 if (
STREQ(socket->name,
"Name")) {
3057 if (!socket->is_directly_linked()) {
3058 return std::nullopt;
3065 if (node_log ==
nullptr) {
3066 return std::nullopt;
3069 return std::nullopt;
3079 if (row.
text.empty()) {
3080 return std::nullopt;
3083 "The execution time from the node tree's latest evaluation. For frame and group "
3084 "nodes, the time for all sub-nodes");
3085 row.
icon = ICON_PREVIEW_RANGE;
3096 tree_draw_ctx, snode, node);
3097 if (row.has_value()) {
3098 rows.
append(std::move(*row));
3110 if (node.
typeinfo->get_extra_info) {
3115 if (node.
typeinfo->deprecation_notice) {
3118 row.
icon = ICON_INFO;
3120 rows.
append(std::move(row));
3137 rows.
append(std::move(*row));
3153 tree_draw_ctx, snode, node);
3154 if (row.has_value()) {
3155 rows.
append(std::move(*row));
3164 if (node_log !=
nullptr) {
3168 row.
icon = ICON_INFO;
3169 rows.
append(std::move(row));
3185 const float but_icon_right = but_icon_left + but_icon_width;
3191 extra_info_row.
icon,
3208 const float but_text_left = but_icon_right + 6.0f *
UI_SCALE_FAC;
3209 const float but_text_right = rect.
xmax;
3210 const float but_text_width = but_text_right - but_text_left;
3215 extra_info_row.
text.c_str(),
3218 short(but_text_width),
3231 if (node.is_muted()) {
3239 const rctf &node_rect = node.
runtime->draw_bounds;
3240 rctf panel_back_rect = extra_info_rect;
3247 if (node.is_muted()) {
3258 const float outline_width =
U.pixelsize;
3259 BLI_rctf_pad(&panel_back_rect, outline_width, outline_width);
3263 &panel_back_rect,
color,
nullptr, 0.0f, color_outline, outline_width,
BASIS_RAD);
3277 if (preview && !(preview->
x > 0 && preview->
y > 0)) {
3283 if (extra_info_rows.
is_empty() && !preview) {
3288 rctf extra_info_rect;
3290 if (node.is_frame()) {
3304 float preview_height = 0.0f;
3308 if (preview->
x > preview->
y) {
3309 preview_height = (width - 2.0f *
padding) *
float(preview->
y) / float(preview->
x) +
3315 extra_info_rect.
ymax += preview_height;
3318 preview_height = width;
3319 const float preview_width = (width - 2.0f *
padding) *
float(preview->
x) /
3324 preview_rect.
xmin = extra_info_rect.
xmin +
padding + (width - preview_width) / 2;
3325 preview_rect.
xmax = extra_info_rect.
xmax -
padding - (width - preview_width) / 2;
3326 extra_info_rect.
ymax += preview_height;
3337 extra_info_rect.
ymin += preview_height;
3347 BLI_assert(node.is_type(
"CompositorNodeViewer") || node.is_type(
"GeometryNodeViewer"));
3353 return ICON_EVENT_ONEKEY;
3355 return ICON_EVENT_TWOKEY;
3357 return ICON_EVENT_THREEKEY;
3359 return ICON_EVENT_FOURKEY;
3361 return ICON_EVENT_FIVEKEY;
3363 return ICON_EVENT_SIXKEY;
3365 return ICON_EVENT_SEVENKEY;
3367 return ICON_EVENT_EIGHTKEY;
3369 return ICON_EVENT_NINEKEY;
3383 const char *disabled_hint =
nullptr;
3388 if (node.is_group()) {
3389 const ID *group_tree = node.
id;
3390 if (group_tree ==
nullptr) {
3421 rctf rect_with_preview = node.
runtime->draw_bounds;
3427 tree_draw_ctx.
bmain,
3429 tree_draw_ctx.
scene,
3449 bool drawn_with_previews =
false;
3457 if (previews_shader) {
3461 drawn_with_previews =
true;
3463 else if (previews_compo) {
3466 C, tree_draw_ctx, snode, node, preview_compositor->ibuf, block);
3467 drawn_with_previews =
true;
3472 if (drawn_with_previews ==
false) {
3489 float color_header[4];
3492 if (node.is_muted()) {
3504 float iconofs = rct.
xmax - 0.35f *
U.widget_unit;
3509 iconofs -= iconbutw;
3526 (
void *)
"NODE_OT_group_edit");
3535 iconofs -= iconbutw;
3540 is_active ? ICON_HIDE_OFF : ICON_HIDE_ON,
3552 (
void *)
"NODE_OT_preview_toggle");
3556 node.
typeinfo->ui_icon != ICON_NONE)
3558 iconofs -= iconbutw;
3576 iconofs -= iconbutw;
3581 is_active ? ICON_RESTRICT_VIEW_OFF : ICON_RESTRICT_VIEW_ON,
3591 const char *operator_idname = is_active ?
"NODE_OT_deactivate_viewer" :
3592 "NODE_OT_activate_viewer";
3601 iconofs - 1.2 * iconbutw,
3612 if (node.is_type(
"CompositorNodeViewer")) {
3614 iconofs -= iconbutw;
3620 is_active ? ICON_RESTRICT_VIEW_OFF : ICON_RESTRICT_VIEW_ON,
3633 (
void *)
"NODE_OT_activate_viewer");
3639 iconofs - 1.2 * iconbutw,
3662 const int but_size =
U.widget_unit * 0.8f;
3681 (
void *)
"NODE_OT_hide_toggle");
3702 const bNode &node = *
static_cast<const bNode *
>(arg);
3703 if (node.
typeinfo->ui_description_fn) {
3704 return node.
typeinfo->ui_description_fn(node);
3708 const_cast<bNode *
>(&node),
3711 if (node.is_muted()) {
3716 if (node.is_muted()) {
3721 const float outline_width =
U.pixelsize;
3728 else if (node.is_muted()) {
3744 if (node.is_muted()) {
3766 float color_underline[4];
3768 if (node.is_muted()) {
3770 color_underline[3] = 1.0f;
3790 rct.
xmin - outline_width,
3791 rct.
xmax + outline_width,
3792 rct.
ymin - outline_width,
3793 rct.
ymax + outline_width,
3797 float color_outline[4];
3807 color_outline[3] = 1.0f;
3827 tree_draw_ctx.
bmain,
3829 tree_draw_ctx.
scene,
3859 if (node.is_muted()) {
3870 else if (node.is_muted()) {
3887 if (node.is_muted()) {
3913 const int but_size =
U.widget_unit * 1.0f;
3921 centy - but_size / 2,
3932 (
void *)
"NODE_OT_hide_toggle");
3953 const float outline_width =
U.pixelsize;
3955 rct.
xmin - outline_width,
3956 rct.
xmax + outline_width,
3957 rct.
ymin - outline_width,
3958 rct.
ymax + outline_width,
3962 float color_outline[4];
3978 if (node.is_muted()) {
3988 float dx = 0.5f *
U.widget_unit;
3990 const float dy = 0.2f *
U.widget_unit;
4017 tree_draw_ctx.
bmain,
4019 tree_draw_ctx.
scene,
4028 if (directions == 0) {
4053 if (ntree ==
nullptr) {
4083 for (
bNode *node : ntree.all_nodes()) {
4084 for (
bNodeSocket *socket : node->input_sockets()) {
4085 if (socket->is_multi_input()) {
4086 socket->runtime->total_inputs = socket->directly_linked_links().size();
4123 frame_layout.
margin = 1.5f *
U.widget_unit;
4128 float room_for_label = 1.5f * frame_layout.
label_height + 0.2f * frame_layout.
margin;
4146 return frame_layout;
4160 if (!node.is_frame()) {
4163 float zone_padding = 0;
4164 float extra_row_padding = 0;
4179 node_bounds.
ymax += std::max(zone_padding, extra_row_padding);
4180 node_bounds.
ymin -= zone_padding;
4198 for (
bNode *child : node.direct_children_in_frame()) {
4226 node.
runtime->draw_bounds = rect;
4235 node.input_socket(0).
runtime->location = loc;
4236 node.output_socket(0).
runtime->location = loc;
4239 node.
width = radius * 2;
4240 node.
runtime->draw_bounds.xmin = loc.x - radius;
4241 node.
runtime->draw_bounds.xmax = loc.x + radius;
4242 node.
runtime->draw_bounds.ymax = loc.y + radius;
4243 node.
runtime->draw_bounds.ymin = loc.y - radius;
4257 for (
const int i :
nodes.index_range()) {
4259 uiBlock &block = *blocks[node.index()];
4260 if (node.is_frame()) {
4265 if (node.is_reroute()) {
4279 for (
bNode *frame : ntree.root_frames()) {
4330 const int y_min = rct.
ymin + frame_layout.
margin;
4338 if (line->line[0]) {
4341 BLF_draw(fontid, line->line, line->len, &info);
4342 y -= line_spacing * info.
lines;
4369 const float alpha =
color[3];
4382 if (depth % 2 == 0) {
4406 bool draw_outline =
false;
4409 draw_outline =
true;
4413 draw_outline =
true;
4437 tree_draw_ctx.
bmain,
4439 tree_draw_ctx.
scene,
4452 tree_draw_ctx.
bmain,
4454 tree_draw_ctx.
scene,
4464 const std::optional<ed::space_node::ObjectAndModifier> object_and_modifier =
4466 if (!object_and_modifier) {
4469 snode.
edittree->ensure_topology_cache();
4473 snode, compute_context_cache);
4474 if (!current_compute_context) {
4482 compute_context_cache,
4483 [&](
const Object &gizmo_object,
4486 const bNode &gizmo_node,
4488 if (&gizmo_object != object_and_modifier->object) {
4491 if (&gizmo_nmd != object_and_modifier->nmd) {
4501 if (compute_context.
hash() == current_compute_context->
hash()) {
4502 sockets_on_gizmo_paths.
add(&socket);
4507 return sockets_on_gizmo_paths;
4517 const bNodeSocket *input_socket = reroute.input_sockets().first();
4518 if (input_socket->directly_linked_links().is_empty()) {
4521 const bNodeLink *input_link = input_socket->directly_linked_links().first();
4523 return from_node->is_reroute() ? from_node :
nullptr;
4531 const bNode &src_reroute)
4535 if (src_reroute.
label[0] !=
'\0') {
4536 return src_reroute.
label;
4545 for (
const bNode *reroute = &src_reroute; reroute;
4548 reroute_path.
append(reroute);
4553 if (reroute->label[0] !=
'\0') {
4554 label = reroute->label;
4558 reroute_auto_labels.
add(reroute,
"");
4562 for (
const bNode *reroute : reroute_path) {
4574 const bool selected)
4581 const_cast<ID *
>(&ntree.
id), &RNA_Node,
const_cast<bNode *
>(&node));
4608 const bool has_label = node.
label[0] !=
'\0';
4612 if (!has_label && !use_auto_label) {
4622 if (
text.is_empty()) {
4626 const short width = 512;
4628 const int y = node.
runtime->draw_bounds.ymax;
4631 &block,
UI_BTYPE_LABEL, 0,
text,
x,
y, width,
NODE_DY,
nullptr, 0, 0, std::nullopt);
4656 tree_draw_ctx.
bmain,
4658 tree_draw_ctx.
scene,
4674 tree_draw_ctx.
bmain,
4676 tree_draw_ctx.
scene,
4692 if (node.is_frame()) {
4696 else if (node.is_reroute()) {
4727 if (!
bounds.is_empty()) {
4735 for (
const float2 &
pos : child_bounds) {
4742 const bNode *child_node = snode.
edittree->node_by_id(child_node_id);
4752 const rctf &draw_bounds = input_node->runtime->draw_bounds;
4753 rctf rect = draw_bounds;
4759 const rctf &draw_bounds = output_node->runtime->draw_bounds;
4760 rctf rect = draw_bounds;
4784 reinterpret_cast<float(*)[2]
>(possible_bounds.
data()),
4785 possible_bounds.
size(),
4786 convex_indices.
data());
4787 convex_indices.
resize(convex_positions_num);
4789 for (
const int i : convex_indices) {
4790 bounds.append(possible_bounds[
i]);
4801 zones = ntree.
runtime->last_valid_zones.get();
4803 const int zones_num = zones ? zones->
zones.size() : 0;
4810 for (
const int zone_i :
IndexRange(zones_num)) {
4814 const Span<float2> boundary_positions = bounds_by_zone[zone_i];
4815 const int boundary_positions_num = boundary_positions.
size();
4816 if (boundary_positions_num < 3) {
4822 const float bounding_box_width = bounding_box.
max.x - bounding_box.
min.x;
4823 bounding_box_width_by_zone[zone_i] = bounding_box_width;
4831 boundary_curve_positions[
i] =
float3(boundary_positions[
i], 0.0f);
4846 float line_width = 1.0f * scale;
4847 float viewport[4] = {};
4850 const auto get_theme_id = [&](
const int zone_i) {
4851 const bNode *node = zones->
zones[zone_i]->output_node();
4861 using ZoneOrNode = std::variant<const bNodeTreeZone *, const bNode *>;
4863 for (
const int zone_i :
IndexRange(zones_num)) {
4866 for (
const bNode *node : ntree.all_nodes()) {
4871 auto get_zone_or_node_width = [&](
const ZoneOrNode &zone_or_node) {
4872 if (
const bNodeTreeZone *
const *zone_p = std::get_if<const bNodeTreeZone *>(&zone_or_node)) {
4874 return bounding_box_width_by_zone[zone.
index];
4876 if (
const bNode *
const *node_p = std::get_if<const bNode *>(&zone_or_node)) {
4877 const bNode &node = **node_p;
4883 std::sort(draw_order.
begin(), draw_order.
end(), [&](
const ZoneOrNode &a,
const ZoneOrNode &
b) {
4885 return get_zone_or_node_width(a) > get_zone_or_node_width(b);
4888 for (
const ZoneOrNode &zone_or_node : draw_order) {
4889 if (
const bNodeTreeZone *
const *zone_p = std::get_if<const bNodeTreeZone *>(&zone_or_node)) {
4891 const int zone_i = zone.
index;
4892 float zone_color[4];
4894 if (zone_color[3] == 0.0f) {
4897 if (!fillet_curve_by_zone[zone_i].has_value()) {
4901 const Span<float3> fillet_boundary_positions = fillet_curve_by_zone[zone_i]->positions();
4907 for (
const float3 &p : fillet_boundary_positions) {
4915 if (
const bNode *
const *node_p = std::get_if<const bNode *>(&zone_or_node)) {
4916 const bNode &node = **node_p;
4924 for (
const ZoneOrNode &zone_or_node : draw_order) {
4925 if (
const bNodeTreeZone *
const *zone_p = std::get_if<const bNodeTreeZone *>(&zone_or_node)) {
4927 const int zone_i = zone.
index;
4928 if (!fillet_curve_by_zone[zone_i].has_value()) {
4932 const Span<float3> fillet_boundary_positions = fillet_curve_by_zone[zone_i]->positions();
4942 get_theme_id(zone_i);
4946 for (
const float3 &p : fillet_boundary_positions) {
4954 if (
const bNode *
const *node_p = std::get_if<const bNode *>(&zone_or_node)) {
4955 const bNode &node = **node_p;
4970 for (
const bNode *node : ntree.nodes_by_type(
"NodeFrame")) {
4983 const float region_padding)
4992 BLI_rctf_pad(&inner_rect, -(region_padding + radius), -(region_padding + radius));
5004 std::array<float2, NODE_LINK_RESOL + 1> link_points;
5007 const float required_socket_distance =
UI_UNIT_X;
5010 const auto cost_function = [&](
const float2 &p) ->
float {
5011 const float distance_to_inner_rect = std::max(
BLI_rctf_length_x(&inner_rect, p.x),
5019 if (distance_to_socket < required_socket_distance) {
5020 return 1e5f + distance_to_center;
5025 std::sqrt(distance_to_center)
5029 + 10.0f * distance_to_inner_rect;
5037 std::optional<float2> best_position;
5038 for (
const int i :
IndexRange(link_points.size() - 1)) {
5040 float2 p1 = link_points[
i + 1];
5045 const float point_distance = 1.0f;
5048 const int points_to_check = std::max(2, 1 +
int(
length / point_distance));
5049 for (
const int j :
IndexRange(points_to_check)) {
5050 const float t = float(j) / (points_to_check - 1);
5052 const float cost = cost_function(p);
5053 if (!best_position.has_value() || cost < best_cost) {
5059 return best_position;
5078 std::string error_tooltip;
5079 if (errors.
size() == 1) {
5080 error_tooltip = errors[0].tooltip;
5084 error_tooltip += fmt::format(
"\u2022 {}\n",
error.tooltip);
5088 const float bg_radius =
UI_UNIT_X * 0.5f;
5089 const float bg_corner_radius =
UI_UNIT_X * 0.2f;
5091 const float region_padding =
UI_UNIT_X * 0.5f;
5095 region.
v2d, link, bg_radius, region_padding);
5096 if (!draw_position_opt.has_value()) {
5099 const int2 draw_position =
int2(draw_position_opt.value());
5116 draw_position.x - icon_size / 2,
5117 draw_position.y - icon_size / 2,
5125 but, [tooltip = std::move(error_tooltip)](
const uiBut * ) {
return tooltip; });
5137#define USE_DRAW_TOT_UPDATE
5148#ifdef USE_DRAW_TOT_UPDATE
5152 for (
const int i :
nodes.index_range()) {
5153#ifdef USE_DRAW_TOT_UPDATE
5164 for (
const bNodeLink *link : ntree.all_links()) {
5171 for (
const bNodeLink *link : ntree.all_links()) {
5184 for (
const int i :
nodes.index_range()) {
5192 node_draw(
C, tree_draw_ctx, region, snode, ntree, node, *blocks[node.index()], key);
5196 for (
auto &&item : ntree.
runtime->link_errors.items()) {
5197 if (
const bNodeLink *link = item.key.try_find(ntree)) {
5217 const int x = rect->
xmin + padding_x;
5264 const View3D &view_3d =
reinterpret_cast<const View3D &
>(space);
5288 ntree.ensure_topology_cache();
5306 log.ensure_node_warnings(*tree_draw_ctx.
bmain);
5307 log.ensure_execution_times();
5321 &scene->
runtime->compositor.per_node_execution_time;
5331 for (
const int i :
nodes.index_range()) {
5334 C, tree_draw_ctx, *snode, node);
5347 const int max_tree_length = 3;
5348 const float bright_factor = 0.25f;
5355 const int depth =
max_ii(0, clamped_tree_path_length - 1);
5432 float original_proj[4][4];
void ED_draw_imbuf(ImBuf *ibuf, float x, float y, bool use_filter, const ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings, float zoom_x, float zoom_y)
PointerRNA CTX_data_pointer_get(const bContext *C, const char *member)
WorkSpace * CTX_wm_workspace(const bContext *C)
SpaceNode * CTX_wm_space_node(const bContext *C)
wmWindow * CTX_wm_window(const bContext *C)
Depsgraph * CTX_data_depsgraph_pointer(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
Main * CTX_data_main(const bContext *C)
ARegion * CTX_wm_region(const bContext *C)
wmWindowManager * CTX_wm_manager(const bContext *C)
Low-level operations for curves.
const char * BKE_idtype_idcode_to_name(short idcode)
void id_us_ensure_real(ID *id)
void BKE_main_ensure_invariants(Main &bmain, std::optional< blender::Span< ID * > > modified_ids=std::nullopt)
#define NODE_CLASS_OUTPUT
#define NODE_CLASS_INTERFACE
#define NODE_CUSTOM_GROUP
#define NODE_CLASS_CONVERTER
#define NODE_CLASS_PATTERN
#define NODE_CLASS_GEOMETRY
#define NODE_GROUP_OUTPUT
#define NODE_CLASS_DISTORT
#define NODE_CLASS_OP_VECTOR
#define NODE_CLASS_LAYOUT
#define NODE_CLASS_OP_COLOR
#define NODE_CLASS_OP_FILTER
#define NODE_CLASS_ATTRIBUTE
#define NODE_CLASS_TEXTURE
#define NODE_CLASS_SHADER
#define NODE_CLASS_SCRIPT
#define GEO_NODE_STORE_NAMED_ATTRIBUTE
#define GEO_NODE_REMOVE_ATTRIBUTE
#define GEO_NODE_FOREACH_GEOMETRY_ELEMENT_OUTPUT
#define GEO_NODE_INPUT_NAMED_ATTRIBUTE
#define GEO_NODE_SIMULATION_OUTPUT
#define CMP_NODE_OUTPUT_FILE
#define GEO_NODE_EVALUATE_CLOSURE
#define GEO_NODE_REPEAT_OUTPUT
General operations, lookup, etc. for blender objects.
bool BKE_scene_uses_shader_previews(const Scene *scene)
void BLF_size(int fontid, float size)
void BLF_aspect(int fontid, float x, float y, float z)
void BLF_color3ubv(int fontid, const unsigned char rgb[3])
void BLF_clipping(int fontid, int xmin, int ymin, int xmax, int ymax)
void BLF_disable(int fontid, int option)
void BLF_draw(int fontid, const char *str, size_t str_len, ResultBLF *r_info=nullptr) ATTR_NONNULL(2)
void BLF_wordwrap(int fontid, int wrap_width, BLFWrapMode mode=BLFWrapMode::Minimal)
void BLF_enable(int fontid, int option)
float BLF_width(int fontid, const char *str, size_t str_len, ResultBLF *r_info=nullptr) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(2)
int BLF_height_max(int fontid) ATTR_WARN_UNUSED_RESULT
void BLF_position(int fontid, float x, float y, float z)
#define BLI_assert_unreachable()
int BLI_convexhull_2d(const float(*points)[2], int points_num, int r_points[])
#define BUFFER_FOR_CPP_TYPE_VALUE(type, variable_name)
#define LISTBASE_FOREACH(type, var, list)
int BLI_listbase_count_at_most(const ListBase *listbase, int count_max) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
MINLINE int round_fl_to_int(float a)
MINLINE float max_ff(float a, float b)
MINLINE int min_ii(int a, int b)
MINLINE float min_ff(float a, float b)
MINLINE int max_ii(int a, int b)
MINLINE void rgba_float_args_set(float col[4], float r, float g, float b, float a)
MINLINE void copy_v4_v4(float r[4], const float a[4])
MINLINE void copy_v2_v2(float r[2], const float a[2])
MINLINE void mul_v3_fl(float r[3], float f)
#define BLI_SCOPED_DEFER(function_to_defer)
void BLI_rctf_union(struct rctf *rct_a, const struct rctf *rct_b)
BLI_INLINE float BLI_rcti_cent_x_fl(const struct rcti *rct)
bool BLI_rctf_isect_pt_v(const struct rctf *rect, const float xy[2])
BLI_INLINE float BLI_rctf_cent_y(const struct rctf *rct)
bool BLI_rctf_isect(const struct rctf *src1, const struct rctf *src2, struct rctf *dest)
BLI_INLINE float BLI_rctf_cent_x(const struct rctf *rct)
bool BLI_rctf_clamp_segment(const struct rctf *rect, float s1[2], float s2[2])
float BLI_rctf_length_x(const rctf *rect, float x)
BLI_INLINE int BLI_rcti_size_x(const struct rcti *rct)
void BLI_rctf_pad(struct rctf *rect, float pad_x, float pad_y)
bool BLI_rctf_isect_pt(const struct rctf *rect, float x, float y)
BLI_INLINE float BLI_rcti_cent_y_fl(const struct rcti *rct)
BLI_INLINE float BLI_rctf_size_x(const struct rctf *rct)
void BLI_rctf_mul(struct rctf *rect, float factor)
BLI_INLINE float BLI_rctf_size_y(const struct rctf *rct)
void BLI_rctf_init_pt_radius(struct rctf *rect, const float xy[2], float size)
float BLI_rctf_length_y(const rctf *rect, float y)
void BLI_rctf_init_minmax(struct rctf *rect)
size_t BLI_str_format_int_grouped(char dst[BLI_STR_FORMAT_INT32_GROUPED_SIZE], int num) ATTR_NONNULL(1)
#define BLI_STR_FORMAT_INT32_GROUPED_SIZE
char * STRNCPY(char(&dst)[N], const char *src)
#define BLI_STR_UTF8_DEGREE_SIGN
#define STREQLEN(a, b, n)
#define POINTER_FROM_INT(i)
#define POINTER_AS_INT(i)
#define BLT_I18NCONTEXT_ID_ID
#define CTX_IFACE_(context, msgid)
#define CTX_TIP_(context, msgid)
void DEG_id_tag_update(ID *id, unsigned int flags)
@ NODE_VIEWER_SHORCTUT_SLOT_9
@ NODE_VIEWER_SHORCTUT_SLOT_5
@ NODE_VIEWER_SHORCTUT_SLOT_4
@ NODE_VIEWER_SHORCTUT_SLOT_2
@ NODE_VIEWER_SHORCTUT_SLOT_7
@ NODE_VIEWER_SHORCTUT_SLOT_1
@ NODE_VIEWER_SHORCTUT_SLOT_3
@ NODE_VIEWER_SHORTCUT_NONE
@ NODE_VIEWER_SHORCTUT_SLOT_8
@ NODE_VIEWER_SHORCTUT_SLOT_6
@ SN_OVERLAY_SHOW_PREVIEWS
@ SN_OVERLAY_SHOW_REROUTE_AUTO_LABELS
@ SN_OVERLAY_SHOW_TIMINGS
@ SN_OVERLAY_SHOW_OVERLAYS
@ SN_OVERLAY_SHOW_NAMED_ATTRIBUTES
#define USER_EXPERIMENTAL_TEST(userdef, member)
@ V3D_SHADING_USE_COMPOSITOR_DISABLED
#define NODE_GRID_STEP_SIZE
const rcti * ED_region_visible_rect(ARegion *region)
void ED_region_draw_cb_draw(const bContext *C, ARegion *region, int type)
#define REGION_DRAW_POST_VIEW
#define REGION_DRAW_PRE_VIEW
void GPU_framebuffer_bind_no_srgb(GPUFrameBuffer *fb)
void GPU_clear_color(float red, float green, float blue, float alpha)
void GPU_matrix_identity_set()
void GPU_matrix_push_projection()
void GPU_matrix_pop_projection()
#define GPU_matrix_projection_get(x)
#define GPU_matrix_projection_set(x)
@ GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR
@ GPU_SHADER_3D_UNIFORM_COLOR
void GPU_blend(eGPUBlend blend)
void GPU_scissor_test(bool enable)
void GPU_line_width(float width)
void GPU_line_smooth(bool enable)
void GPU_depth_test(eGPUDepthTest test)
void GPU_viewport_size_get_f(float coords[4])
GPUFrameBuffer * GPU_viewport_framebuffer_overlay_get(GPUViewport *viewport)
Read Guarded memory(de)allocation.
void UI_but_func_set(uiBut *but, std::function< void(bContext &)> func)
void UI_but_func_pushed_state_set(uiBut *but, std::function< bool(const uiBut &)> func)
#define UI_ALPHA_CHECKER_LIGHT
void UI_draw_roundbox_4fv(const rctf *rect, bool filled, float rad, const float col[4])
void ui_draw_dropshadow(const rctf *rct, float radius, float width, float aspect, float alpha)
void UI_block_emboss_set(uiBlock *block, blender::ui::EmbossType emboss)
uiBlock * UI_block_begin(const bContext *C, ARegion *region, std::string name, blender::ui::EmbossType emboss)
void UI_but_icon_indicator_number_set(uiBut *but, const int indicator_number)
void UI_but_func_tooltip_set(uiBut *but, uiButToolTipFunc func, void *arg, uiFreeArgFunc free_arg)
uiBut * uiDefBut(uiBlock *block, int type, int retval, blender::StringRef str, int x, int y, short width, short height, void *poin, float min, float max, std::optional< blender::StringRef > tip)
void UI_draw_roundbox_4fv_ex(const rctf *rect, const float inner1[4], const float inner2[4], float shade_dir, const float outline[4], float outline_width, float rad)
#define UI_ALPHA_CHECKER_DARK
const uiStyle * UI_style_get_dpi()
void UI_draw_roundbox_corner_set(int type)
const uiStyle * UI_style_get()
void UI_but_drawflag_disable(uiBut *but, int flag)
void UI_block_draw(const bContext *C, uiBlock *block)
uiBut * uiDefIconBut(uiBlock *block, int type, int retval, int icon, int x, int y, short width, short height, void *poin, float min, float max, std::optional< blender::StringRef > tip)
void UI_block_flag_enable(uiBlock *block, int flag)
uiBut * uiDefButR(uiBlock *block, int type, int retval, std::optional< blender::StringRef > str, int x, int y, short width, short height, PointerRNA *ptr, blender::StringRefNull propname, int index, float min, float max, std::optional< blender::StringRef > tip)
void UI_draw_roundbox_aa(const rctf *rect, bool filled, float rad, const float color[4])
void UI_block_end_ex(const bContext *C, Main *bmain, wmWindow *window, Scene *scene, ARegion *region, Depsgraph *depsgraph, uiBlock *block, const int xy[2]=nullptr, int r_xy[2]=nullptr)
void UI_block_end(const bContext *C, uiBlock *block)
void UI_but_func_quick_tooltip_set(uiBut *but, std::function< std::string(const uiBut *but)> func)
void UI_but_flag_enable(uiBut *but, int flag)
void UI_block_bounds_set_explicit(uiBlock *block, int minx, int miny, int maxx, int maxy)
void UI_block_align_end(uiBlock *block)
void uiLayoutSetContextPointer(uiLayout *layout, blender::StringRef name, PointerRNA *ptr)
void uiLayoutSetActive(uiLayout *layout, bool active)
uiLayout * UI_block_layout(uiBlock *block, int dir, int type, int x, int y, int size, int em, int padding, const uiStyle *style)
void uiLayoutSetAlignment(uiLayout *layout, char alignment)
void uiLayoutSetTooltipFunc(uiLayout *layout, uiButToolTipFunc func, void *arg, uiCopyArgFunc copy_arg, uiFreeArgFunc free_arg)
void UI_block_layout_resolve(uiBlock *block, int *r_x, int *r_y)
void UI_GetThemeColor3fv(int colorid, float col[3])
int UI_GetThemeValueType(int colorid, int spacetype)
void UI_GetThemeColorBlend4f(int colorid1, int colorid2, float fac, float r_col[4])
void UI_GetThemeColorBlendShade4fv(int colorid1, int colorid2, float fac, int offset, float col[4])
void UI_GetThemeColorShadeAlpha4fv(int colorid, int coloffset, int alphaoffset, float col[4])
void UI_GetThemeColor4fv(int colorid, float col[4])
void UI_GetThemeColorShade4fv(int colorid, int offset, float col[4])
void UI_GetThemeColorBlendShade3ubv(int colorid1, int colorid2, float fac, int offset, unsigned char col[3])
void UI_view2d_scrollers_draw(View2D *v2d, const rcti *mask_custom)
void UI_view2d_view_restore(const bContext *C)
void UI_view2d_center_get(const View2D *v2d, float *r_x, float *r_y)
void UI_view2d_view_ortho(const View2D *v2d)
void UI_view2d_scale_get(const View2D *v2d, float *r_x, float *r_y)
void UI_view2d_region_to_view(const View2D *v2d, float x, float y, float *r_view_x, float *r_view_y) ATTR_NONNULL()
void UI_view2d_center_set(View2D *v2d, float x, float y)
void UI_view2d_dot_grid_draw(const View2D *v2d, int grid_color_id, float min_step, int grid_subdivisions)
@ WM_GIZMOMAP_DRAWSTEP_2D
void ED_annotation_draw_view2d(const bContext *C, bool onlyv2d)
BMesh const char void * data
unsigned long long int uint64_t
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
const Value * lookup_ptr(const Key &key) const
constexpr T & first() const
constexpr void copy_from(Span< T > values) const
IndexRange index_range() const
void destruct(void *ptr) const
const ComputeContextHash & hash() const
const CPPType * type() const
const Value * lookup_ptr(const Key &key) const
bool add_overwrite(const Key &key, const Value &value)
bool add(const Key &key, const Value &value)
constexpr int64_t size() const
constexpr Span drop_back(int64_t n) const
constexpr int64_t size() const
constexpr const T & last(const int64_t n=0) const
constexpr IndexRange index_range() const
constexpr bool is_empty() const
constexpr bool is_empty() const
constexpr bool startswith(StringRef prefix) const
constexpr const char * c_str() const
static VArray ForSingle(T value, const int64_t size)
void append(const T &value)
const T & last(const int64_t n=0) const
IndexRange index_range() const
void resize(const int64_t new_size)
Span< T > as_span() const
MutableSpan< float3 > positions_for_write()
void fill_curve_types(CurveType type)
MutableSpan< int > offsets_for_write()
MutableSpan< bool > cyclic_for_write()
bNodeSocket * input_socket
std::optional< float > header_center_y
std::optional< bNodePanelExtent > content_extent
Vector< int > child_node_ids
bNodeTreeZone * parent_zone
std::optional< int > output_node_id
const bNode * output_node() const
bool contains_node_recursively(const bNode &node) const
std::optional< int > input_node_id
Vector< bNodeTreeZone * > child_zones
const bNode * input_node() const
Vector< bNodeTreeZone * > zones
const bNodeTreeZone * get_zone_by_node(const int32_t node_id) const
std::function< DrawNodeLayoutFn > draw
Vector< PanelDeclaration * > panels
std::optional< std::string > translation_context
Vector< ItemDeclaration * > items
const SocketDeclaration * panel_input_decl() const
bool align_with_previous_socket
Span< std::string > identifiers() const
Span< bke::GeometryComponent::Type > supported_types() const
GeoTreeLog * get_main_tree_log(const bke::bNodeTreeZone *zone) const
void foreach_tree_log(FunctionRef< void(GeoTreeLog &)> callback) const
Vector< std::string > input_tooltips
Map< StringRefNull, NamedAttributeUsage > used_named_attributes
VectorSet< NodeWarning > warnings
Vector< StringRefNull > debug_messages
static ContextualGeoTreeLogs get_contextual_tree_logs(const SpaceNode &snode)
void ensure_used_named_attributes()
void ensure_socket_values()
std::chrono::nanoseconds execution_time
Map< int32_t, GeoNodeLog > nodes
void ensure_debug_messages()
ValueLog * find_socket_value_log(const bNodeSocket &query_socket)
std::optional< EditDataInfo > edit_data_info
std::optional< GridInfo > grid_info
std::optional< MeshInfo > mesh_info
std::optional< GreasePencilInfo > grease_pencil_info
std::optional< PointCloudInfo > pointcloud_info
Vector< bke::GeometryComponent::Type > component_types
std::optional< InstancesInfo > instances_info
std::optional< VolumeInfo > volume_info
std::optional< CurveInfo > curve_info
static const char * to_string(const Interpolation &interp)
float length(VecOp< float, D >) RET
#define ID_IS_LINKED(_id)
#define ID_REAL_USERS(id)
void * MEM_callocN(size_t len, const char *str)
void * MEM_dupallocN(const void *vmemh)
void MEM_freeN(void *vmemh)
static void error(const char *str)
const bNodeZoneType * zone_type_by_node_type(const int node_type)
std::string node_label(const bNodeTree &ntree, const bNode &node)
bool node_link_is_selected(const bNodeLink &link)
const DataTypeConversions & get_implicit_type_conversions()
std::optional< StringRefNull > node_socket_short_label(const bNodeSocket &sock)
bNodeType NodeTypeUndefined
bNodeInstanceKey node_instance_key(bNodeInstanceKey parent_key, const bNodeTree *ntree, const bNode *node)
Span< int > all_zone_node_types()
const bNodeInstanceKey NODE_INSTANCE_KEY_NONE
bNodeTree * node_tree_from_id(ID *id)
StringRefNull node_socket_label(const bNodeSocket &sock)
bool node_link_is_hidden(const bNodeLink &link)
std::optional< Bounds< T > > min_max(const std::optional< Bounds< T > > &a, const T &b)
static bool compare_node_depth(const bNode *a, const bNode *b)
void tag_update_id(ID *id)
static rctf calc_node_frame_dimensions(const bContext &C, TreeDrawContext &tree_draw_ctx, const SpaceNode &snode, bNode &node)
static void determine_visible_panels_impl_recursive(const bNode &node, const nodes::PanelDeclaration &panel_decl, const Span< bool > potentially_visible_states, MutableSpan< bool > r_result)
static bool compositor_is_in_use(const bContext &context)
static bool node_update_basis_socket(const bContext &C, bNodeTree &ntree, bNode &node, const char *panel_label, bNodeSocket *input_socket, bNodeSocket *output_socket, uiBlock &block, const int &locx, int &locy)
static void add_flat_items_for_panel(bNode &node, const nodes::PanelDeclaration &panel_decl, const Span< bool > panel_visibility, Vector< FlatNodeItem > &r_items)
float node_socket_calculate_height(const bNodeSocket &socket)
rctf node_frame_rect_inside(const SpaceNode &snode, const bNode &node)
static bNodeInstanceKey current_node_instance_key(const SpaceNode &snode, const bNode &node)
int node_get_resize_cursor(NodeResizeDirection directions)
static void reroute_node_draw(const bContext &C, TreeDrawContext &tree_draw_ctx, ARegion ®ion, const SpaceNode &snode, bNodeTree &ntree, const bNode &node, uiBlock &block)
static float get_margin_to_bottom(const Span< FlatNodeItem > items)
static void node_socket_outline_color_get(const bool selected, const int socket_type, float r_outline_color[4])
static void mark_sockets_collapsed_recursive(bNode &node, const int node_left_x, const nodes::PanelDeclaration &visible_panel_decl, const nodes::PanelDeclaration &panel_decl)
void nodelink_batch_start(SpaceNode &)
static const bNode * reroute_node_get_linked_reroute(const bNode &reroute)
void tree_draw_order_update(bNodeTree &ntree)
static void draw_link_errors(const bContext &C, SpaceNode &snode, const bNodeLink &link, const Span< bke::NodeLinkError > errors, uiBlock &invalid_links_block)
void node_socket_draw(bNodeSocket *sock, const rcti *rect, const float color[4], float scale)
static void update_collapsed_sockets(bNode &node, const int node_left_x)
static std::optional< std::string > create_description_inspection_string(const bNodeSocket &socket)
static std::optional< std::string > create_multi_input_log_inspection_string(const bNodeSocket &socket, TreeDrawContext &tree_draw_ctx)
static void tag_final_panel(bNode &node, const Span< FlatNodeItem > items)
static void draw_nodetree(const bContext &C, ARegion ®ion, bNodeTree &ntree, bNodeInstanceKey parent_key)
static void frame_node_draw_label(TreeDrawContext &tree_draw_ctx, const bNode &node, const SpaceNode &snode)
static float get_margin_between_elements(const Span< FlatNodeItem > items, const int next_index)
static void reroute_node_draw_body(const bContext &C, const SpaceNode &snode, const bNodeTree &ntree, const bNode &node, uiBlock &block, const bool selected)
static void node_update_nodetree(const bContext &C, TreeDrawContext &tree_draw_ctx, bNodeTree &ntree, Span< bNode * > nodes, Span< uiBlock * > blocks)
static float node_tree_view_scale(const SpaceNode &snode)
static void determine_potentially_visible_panels(const bNode &node, MutableSpan< bool > r_result)
static std::optional< std::string > create_log_inspection_string(geo_log::GeoTreeLog *geo_tree_log, const bNodeSocket &socket)
static void frame_node_draw_background(const ARegion ®ion, const SpaceNode &snode, const bNode &node)
float2 node_from_view(const float2 &co)
void node_draw_link_bezier(const bContext &C, const View2D &v2d, const SpaceNode &snode, const bNodeLink &link, const int th_col1, const int th_col2, const int th_col3, const bool selected)
static void draw_background_color(const SpaceNode &snode)
static void create_inspection_string_for_bundle(const geo_log::BundleValueLog &value_log, fmt::memory_buffer &buf)
static std::optional< std::chrono::nanoseconds > node_get_execution_time(const TreeDrawContext &tree_draw_ctx, const SpaceNode &snode, const bNode &node)
static void create_inspection_string_for_geometry_info(const geo_log::GeometryInfoLog &value_log, fmt::memory_buffer &buf)
void nodelink_batch_end(SpaceNode &snode)
static std::optional< std::chrono::nanoseconds > compositor_accumulate_frame_node_execution_time(const TreeDrawContext &tree_draw_ctx, const SpaceNode &snode, const bNode &node)
static void reroute_node_draw_label(TreeDrawContext &tree_draw_ctx, const SpaceNode &snode, const bNode &node, uiBlock &block)
static float get_margin_from_top(const Span< FlatNodeItem > items)
ImBuf * node_preview_acquire_ibuf(bNodeTree &ntree, NestedTreePreviews &tree_previews, const bNode &node)
void nodesocket_batch_start()
std::array< float2, 4 > node_link_bezier_points_dragged(const SpaceNode &snode, const bNodeLink &link)
bNodeSocket * node_find_indicated_socket(SpaceNode &snode, ARegion ®ion, const float2 &cursor, const eNodeSocketInOut in_out)
static void node_draw_panels_background(const bNode &node)
static void find_bounds_by_zone_recursive(const SpaceNode &snode, const bNodeTreeZone &zone, const Span< const bNodeTreeZone * > all_zones, MutableSpan< Vector< float2 > > r_bounds_by_zone)
static void node_draw_hidden(const bContext &C, TreeDrawContext &tree_draw_ctx, const View2D &v2d, const SpaceNode &snode, bNodeTree &ntree, bNode &node, uiBlock &block)
static std::optional< NodeExtraInfoRow > node_get_accessed_attributes_row(TreeDrawContext &tree_draw_ctx, const bNode &node)
void node_socket_color_get(const bContext &C, const bNodeTree &ntree, PointerRNA &node_ptr, const bNodeSocket &sock, float r_color[4])
Array< bNode * > tree_draw_order_calc_nodes_reversed(bNodeTree &ntree)
static void node_get_compositor_extra_info(TreeDrawContext &tree_draw_ctx, const SpaceNode &snode, const bNode &node, Vector< NodeExtraInfoRow > &rows)
void node_set_cursor(wmWindow &win, ARegion ®ion, SpaceNode &snode, const float2 &cursor)
void node_draw_link(const bContext &C, const View2D &v2d, const SpaceNode &snode, const bNodeLink &link, const bool selected)
static const bNodeSocket * target_for_reroute(const bNodeSocket &reroute_output)
static void node_draw_mute_line(const bContext &C, const View2D &v2d, const SpaceNode &snode, const bNode &node)
static void reroute_node_prepare_for_draw(bNode &node)
static const bNode * find_node_under_cursor(SpaceNode &snode, const float2 &cursor)
static bool is_node_panels_supported(const bNode &node)
static NodeExtraInfoRow row_from_used_named_attribute(const Map< StringRefNull, geo_log::NamedAttributeUsage > &usage_by_attribute_name)
void node_draw_link_dragged(const bContext &C, const View2D &v2d, const SpaceNode &snode, const bNodeLink &link)
static void node_add_unsupported_compositor_operation_error_message_button(const bNode &node, uiBlock &block, const rctf &rect, float &icon_offset)
static std::optional< std::chrono::nanoseconds > compositor_node_get_execution_time(const TreeDrawContext &tree_draw_ctx, const SpaceNode &snode, const bNode &node)
static void add_flat_items_for_separator(Vector< FlatNodeItem > &r_items)
static void node_toggle_button_cb(bContext *C, void *node_argv, void *op_argv)
static Array< uiBlock * > node_uiblocks_init(const bContext &C, const Span< bNode * > nodes)
static void add_rect_corner_positions(Vector< float2 > &positions, const rctf &rect)
bool node_is_previewable(const SpaceNode &snode, const bNodeTree &ntree, const bNode &node)
static void node_socket_tooltip_set(uiBlock &block, const int socket_index_in_tree, const float2 location, const float2 size)
static void determine_potentially_visible_panels_recursive(const bNode &node, const nodes::PanelDeclaration &panel_decl, MutableSpan< bool > r_result)
static bool node_update_basis_buttons(const bContext &C, bNodeTree &ntree, bNode &node, blender::FunctionRef< nodes::DrawNodeLayoutFn > draw_buttons, uiBlock &block, int &dy)
const ComputeContext * compute_context_for_edittree(const SpaceNode &snode, bke::ComputeContextCache &compute_context_cache)
void draw_nodespace_back_pix(const bContext &C, ARegion ®ion, SpaceNode &snode, bNodeInstanceKey parent_key)
static std::optional< std::string > create_default_value_inspection_string(const bNodeSocket &socket)
static void draw_frame_overlays(const bContext &C, TreeDrawContext &tree_draw_ctx, const ARegion ®ion, const SpaceNode &snode, const bNodeTree &ntree, Span< uiBlock * > blocks)
static std::optional< std::chrono::nanoseconds > geo_node_get_execution_time(const TreeDrawContext &tree_draw_ctx, const SpaceNode &snode, const bNode &node)
static bool panel_has_only_inactive_inputs(const bNode &node, const nodes::PanelDeclaration &panel_decl)
static std::string named_attribute_tooltip(bContext *, void *argN, const StringRef)
static void node_draw_basis(const bContext &C, TreeDrawContext &tree_draw_ctx, const View2D &v2d, const SpaceNode &snode, bNodeTree &ntree, const bNode &node, uiBlock &block, bNodeInstanceKey key)
static void node_draw_extra_info_panel_back(const bNode &node, const rctf &extra_info_rect)
static void node_draw_extra_info_panel(const bContext &C, TreeDrawContext &tree_draw_ctx, const SpaceNode &snode, const bNode &node, ImBuf *preview, uiBlock &block)
static void count_multi_input_socket_links(bNodeTree &ntree, SpaceNode &snode)
static void node_update_basis_from_declaration(const bContext &C, bNodeTree &ntree, bNode &node, uiBlock &block, const int locx, int &locy)
static void determine_visible_panels(const bNode &node, MutableSpan< bool > r_visibility_states)
static void node_draw_sockets(const bContext &C, uiBlock &block, const SpaceNode &snode, const bNodeTree &ntree, const bNode &node)
static void node_update_basis(const bContext &C, const TreeDrawContext &, bNodeTree &ntree, bNode &node, uiBlock &block)
static bNodeTree * node_tree_from_ID(ID *id)
const char * node_socket_get_label(const bNodeSocket *socket, const char *panel_label)
static void create_inspection_string_for_geometry_socket(fmt::memory_buffer &buf, const nodes::decl::Geometry *socket_decl)
void tree_update(const bContext *C)
static std::string node_get_execution_time_label(TreeDrawContext &tree_draw_ctx, const SpaceNode &snode, const bNode &node)
static void create_inspection_string_for_default_socket_value(const bNodeSocket &socket, fmt::memory_buffer &buf)
static void node_draw_extra_info_row(const bNode &node, uiBlock &block, const rctf &rect, const int row, const NodeExtraInfoRow &extra_info_row)
static void node_draw_preview(const Scene *scene, ImBuf *preview, const rctf *prv)
static void node_draw_nodetree(const bContext &C, TreeDrawContext &tree_draw_ctx, ARegion ®ion, SpaceNode &snode, bNodeTree &ntree, Span< bNode * > nodes, Span< uiBlock * > blocks, bNodeInstanceKey parent_key)
static void node_update_basis_from_socket_lists(const bContext &C, bNodeTree &ntree, bNode &node, uiBlock &block, const int locx, int &locy)
void nodesocket_batch_end()
static short get_viewer_shortcut_icon(const bNode &node)
Array< bNode * > tree_draw_order_calc_nodes(bNodeTree &ntree)
static void update_collapsed_sockets_recursive(bNode &node, const int node_left_x, const nodes::PanelDeclaration &panel_decl)
Vector< ui::ContextPathItem > context_path_for_space_node(const bContext &C)
float2 node_to_view(const float2 &co)
static void add_flat_items_for_socket(bNode &node, const nodes::SocketDeclaration &socket_decl, const nodes::PanelDeclaration *panel_decl, const nodes::SocketDeclaration *prev_socket_decl, Vector< FlatNodeItem > &r_items)
static void node_update_hidden(bNode &node, uiBlock &block)
void node_select_single(bContext &C, bNode &node)
static std::string node_errors_tooltip_fn(const Span< geo_log::NodeWarning > warnings)
static rctf node_to_rect(const bNode &node)
static Vector< NodeExtraInfoRow > node_get_extra_info(const bContext &C, TreeDrawContext &tree_draw_ctx, const SpaceNode &snode, const bNode &node)
NestedTreePreviews * get_nested_previews(const bContext &C, SpaceNode &snode)
std::optional< ObjectAndModifier > get_modifier_for_node_editor(const SpaceNode &snode)
static std::optional< std::string > create_dangling_reroute_inspection_string(const bNodeTree &ntree, const bNodeSocket &socket)
static std::optional< NodeExtraInfoRow > node_get_execution_time_label_row(TreeDrawContext &tree_draw_ctx, const SpaceNode &snode, const bNode &node)
static std::optional< std::string > create_declaration_inspection_string(const bNodeSocket &socket)
static nodes::NodeWarningType node_error_highest_priority(Span< geo_log::NodeWarning > warnings)
void node_link_bezier_points_evaluated(const bNodeLink &link, std::array< float2, NODE_LINK_RESOL+1 > &coords)
static Vector< FlatNodeItem > make_flat_node_items(bNode &node)
static const float virtual_node_socket_outline_color[4]
static std::optional< float2 > find_visible_center_of_link(const View2D &v2d, const bNodeLink &link, const float radius, const float region_padding)
static void create_inspection_string_for_field_info(const bNodeSocket &socket, const geo_log::FieldInfoLog &value_log, fmt::memory_buffer &buf)
float2 socket_link_connection_location(const bNode &node, const bNodeSocket &socket, const bNodeLink &link)
static void node_draw_socket(const bContext &C, const bNodeTree &ntree, const bNode &node, PointerRNA &node_ptr, uiBlock &block, const bNodeSocket &sock, const float outline_thickness, const bool selected, const float aspect)
static FrameNodeLayout frame_node_layout(const bNode &frame_node)
static void frame_node_draw_outline(const ARegion ®ion, const SpaceNode &snode, const bNode &node)
void snode_set_context(const bContext &C)
static void node_socket_add_tooltip_in_node_editor(const bNodeSocket &sock, uiLayout &layout)
static void node_panel_toggle_button_cb(bContext *C, void *panel_state_argv, void *ntree_argv)
NodeResizeDirection node_get_resize_direction(const SpaceNode &snode, const bNode *node, const int x, const int y)
static const char * node_socket_get_translation_context(const bNodeSocket &socket)
static void node_draw(const bContext &C, TreeDrawContext &tree_draw_ctx, ARegion ®ion, const SpaceNode &snode, bNodeTree &ntree, bNode &node, uiBlock &block, bNodeInstanceKey key)
void node_release_preview_ibuf(NestedTreePreviews &tree_previews)
static void node_draw_zones_and_frames(const ARegion ®ion, const SpaceNode &snode, const bNodeTree &ntree)
static void add_flat_items_for_layout(const bNode &node, const nodes::LayoutDeclaration &layout_decl, Vector< FlatNodeItem > &r_items)
static void create_inspection_string_for_generic_value(const bNodeSocket &socket, const GPointer value, fmt::memory_buffer &buf)
void node_to_updated_rect(const bNode &node, rctf &r_rect)
static bool draw_node_details(const SpaceNode &snode)
static std::string node_socket_get_tooltip(const SpaceNode *snode, const bNodeTree &ntree, const bNodeSocket &socket)
static void node_add_error_message_button(const TreeDrawContext &tree_draw_ctx, const bNode &node, uiBlock &block, const rctf &rect, float &icon_offset)
void node_draw_space(const bContext &C, ARegion ®ion)
static void node_draw_preview_background(rctf *rect)
static void node_draw_panels(bNodeTree &ntree, const bNode &node, uiBlock &block)
static void node_draw_shadow(const SpaceNode &snode, const bNode &node, const float radius, const float alpha)
static uiBlock & invalid_links_uiblock_init(const bContext &C)
static void create_inspection_string_for_closure(const geo_log::ClosureValueLog &value_log, fmt::memory_buffer &buf)
static bool node_undefined_or_unsupported(const bNodeTree &node_tree, const bNode &node)
static void frame_node_draw_overlay(const bContext &C, TreeDrawContext &tree_draw_ctx, const ARegion ®ion, const SpaceNode &snode, const bNode &node, uiBlock &block)
static void draw_tree_path(const bContext &C, ARegion ®ion)
static Vector< std::string > lines_of_text(std::string text)
static Set< const bNodeSocket * > find_sockets_on_active_gizmo_paths(const bContext &C, const SpaceNode &snode)
static float get_margin_empty()
void node_socket_add_tooltip(const bNodeTree &ntree, const bNodeSocket &sock, uiLayout &layout)
static StringRef reroute_node_get_auto_label(TreeDrawContext &tree_draw_ctx, const bNode &src_reroute)
void node_draw_nodesocket(const rctf *rect, const float color_inner[4], const float color_outline[4], float outline_thickness, int shape, float aspect)
static int node_get_colorid(TreeDrawContext &tree_draw_ctx, const bNode &node)
static void determine_visible_panels_impl(const bNode &node, const Span< bool > potentially_visible_states, MutableSpan< bool > r_result)
static void snode_setup_v2d(SpaceNode &snode, ARegion ®ion, const float2 ¢er)
bNode * find_geometry_nodes_viewer(const ViewerPath &viewer_path, SpaceNode &snode)
bke::CurvesGeometry fillet_curves_poly(const bke::CurvesGeometry &src_curves, const IndexMask &curve_selection, const VArray< float > &radius, const VArray< int > &counts, bool limit_radius, const bke::AttributeFilter &attribute_filter)
QuaternionBase< float > Quaternion
MatBase< T, NumCol, NumRow > transpose(const MatBase< T, NumRow, NumCol > &mat)
T distance(const T &a, const T &b)
EulerXYZBase< float > EulerXYZ
T midpoint(const T &a, const T &b)
T interpolate(const T &a, const T &b, const FactorT &t)
Euler3Base< T > to_euler(const AxisAngleBase< T, AngleT > &axis_angle, EulerOrder order)
void foreach_socket_on_gizmo_path(const ComputeContext &gizmo_context, const bNode &gizmo_node, const bNodeSocket &gizmo_socket, FunctionRef< void(const ComputeContext &context, const bNodeSocket &socket, const ie::ElemVariant &elem)> fn)
void foreach_active_gizmo(const bContext &C, bke::ComputeContextCache &compute_context_cache, const ForeachGizmoFn fn)
int node_warning_type_icon(const NodeWarningType type)
std::chrono::nanoseconds Nanoseconds
void template_breadcrumbs(uiLayout &layout, Span< ContextPathItem > context_path)
MatBase< float, 4, 4 > float4x4
VecBase< float, 4 > float4
VecBase< int32_t, 2 > int2
VecBase< float, 2 > float2
ColorSceneLinear4f< eAlpha::Premultiplied > ColorGeometry4f
ColorTheme4< float > ColorTheme4f
VecBase< float, 3 > float3
#define NODE_HEADER_ICON_SIZE
#define NODE_SOCKET_OUTLINE
#define ZONE_ZONE_PADDING
#define EXTRA_INFO_ROW_HEIGHT
#define NODE_ZONE_PADDING
#define NODE_TREE_SCALE_SMALL
#define NODE_MULTI_INPUT_LINK_GAP
#define NODE_ITEM_SPACING_Y
bool RNA_struct_is_a(const StructRNA *type, const StructRNA *srna)
PointerRNA RNA_pointer_create_discrete(ID *id, StructRNA *type, void *data)
ARegionRuntimeHandle * runtime
struct bNodeTree * nodetree
ColorManagedViewSettings view_settings
SceneRuntimeHandle * runtime
ColorManagedDisplaySettings display_settings
SpaceNode_Runtime * runtime
struct bNodeTree * edittree
struct bNodeTree * nodetree
bNodeSocketRuntimeHandle * runtime
bNodeSocketTypeHandle * typeinfo
struct bNodeTree * nodetree
bNodeInstanceKey parent_key
bNodeTreeRuntimeHandle * runtime
bNodeTypeHandle * typeinfo
bNodePanelState * panel_states_array
bNodeRuntimeHandle * runtime
std::variant< flat_item::Socket, flat_item::Separator, flat_item::PanelHeader, flat_item::PanelContentBegin, flat_item::PanelContentEnd, flat_item::Layout > item
flat_item::Type type() const
std::optional< int > frame_identifier_to_highlight
std::unique_ptr< bNodeLinkDrag > linkdrag
geo_log::ContextualGeoTreeLogs tree_logs
NestedTreePreviews * nested_group_infos
Map< bNodeInstanceKey, timeit::Nanoseconds > * compositor_per_node_execution_time
const bNode * active_geometry_nodes_viewer
Array< Vector< NodeExtraInfoRow > > extra_info_rows_per_node
Map< const bNode *, StringRef > reroute_auto_labels
const nodes::LayoutDeclaration * decl
static constexpr Type type
const nodes::PanelDeclaration * decl
static constexpr Type type
static constexpr Type type
const nodes::PanelDeclaration * decl
static constexpr Type type
static constexpr Type type
const nodes::PanelDeclaration * panel_decl
const bke::bNodeSocketType * type
const bke::bNodeSocketType * type
bool has_deformed_positions
void separator(float factor=1.0f, LayoutSeparatorType type=LayoutSeparatorType::Auto)
uiLayout & row(bool align)
struct wmEvent * eventstate
void WM_cursor_set(wmWindow *win, int curs)
GPUViewport * WM_draw_region_get_viewport(ARegion *region)
void WM_main_add_notifier(uint type, void *reference)
wmOperatorStatus WM_operator_name_call(bContext *C, const char *opstring, wmOperatorCallContext context, PointerRNA *properties, const wmEvent *event)
void WM_gizmomap_draw(wmGizmoMap *gzmap, const bContext *C, const eWM_GizmoFlagMapDrawStep drawstep)
void wmOrtho2_pixelspace(const float x, const float y)
void wmOrtho2_region_pixelspace(const ARegion *region)
bScreen * WM_window_get_active_screen(const wmWindow *win)