Compare commits
14 Commits
tmp-workbe
...
temp-field
Author | SHA1 | Date | |
---|---|---|---|
d26165747e | |||
6dc2045054 | |||
362bd7889b | |||
620da869f1 | |||
50df35e4a4 | |||
6a72188b3e | |||
5d183c5af3 | |||
dcf72a30e1 | |||
0bec1f5dad | |||
a5fbd81510 | |||
234de0bf71 | |||
a5b9323fd5 | |||
52de232811 | |||
1931878f57 |
@@ -731,7 +731,7 @@ void nodeSetSocketAvailability(struct bNodeSocket *sock, bool is_available);
|
|||||||
|
|
||||||
int nodeSocketLinkLimit(const struct bNodeSocket *sock);
|
int nodeSocketLinkLimit(const struct bNodeSocket *sock);
|
||||||
|
|
||||||
void nodeDeclarationEnsure(struct bNodeTree *ntree, struct bNode *node);
|
NodeDeclarationHandle *nodeDeclarationEnsure(struct bNodeTree *ntree, struct bNode *node);
|
||||||
|
|
||||||
/* Node Clipboard */
|
/* Node Clipboard */
|
||||||
void BKE_node_clipboard_init(const struct bNodeTree *ntree);
|
void BKE_node_clipboard_init(const struct bNodeTree *ntree);
|
||||||
|
@@ -29,6 +29,7 @@
|
|||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <queue>
|
||||||
|
|
||||||
/* Allow using deprecated functionality for .blend file I/O. */
|
/* Allow using deprecated functionality for .blend file I/O. */
|
||||||
#define DNA_DEPRECATED_ALLOW
|
#define DNA_DEPRECATED_ALLOW
|
||||||
@@ -52,9 +53,12 @@
|
|||||||
#include "BLI_map.hh"
|
#include "BLI_map.hh"
|
||||||
#include "BLI_math.h"
|
#include "BLI_math.h"
|
||||||
#include "BLI_path_util.h"
|
#include "BLI_path_util.h"
|
||||||
|
#include "BLI_set.hh"
|
||||||
|
#include "BLI_stack.hh"
|
||||||
#include "BLI_string.h"
|
#include "BLI_string.h"
|
||||||
#include "BLI_string_utils.h"
|
#include "BLI_string_utils.h"
|
||||||
#include "BLI_utildefines.h"
|
#include "BLI_utildefines.h"
|
||||||
|
#include "BLI_vector_set.hh"
|
||||||
|
|
||||||
#include "BLT_translation.h"
|
#include "BLT_translation.h"
|
||||||
|
|
||||||
@@ -80,6 +84,7 @@
|
|||||||
#include "NOD_function.h"
|
#include "NOD_function.h"
|
||||||
#include "NOD_geometry.h"
|
#include "NOD_geometry.h"
|
||||||
#include "NOD_node_declaration.hh"
|
#include "NOD_node_declaration.hh"
|
||||||
|
#include "NOD_node_tree_ref.hh"
|
||||||
#include "NOD_shader.h"
|
#include "NOD_shader.h"
|
||||||
#include "NOD_socket.h"
|
#include "NOD_socket.h"
|
||||||
#include "NOD_texture.h"
|
#include "NOD_texture.h"
|
||||||
@@ -93,6 +98,14 @@
|
|||||||
|
|
||||||
#define NODE_DEFAULT_MAX_WIDTH 700
|
#define NODE_DEFAULT_MAX_WIDTH 700
|
||||||
|
|
||||||
|
using blender::Array;
|
||||||
|
using blender::Set;
|
||||||
|
using blender::Span;
|
||||||
|
using blender::Stack;
|
||||||
|
using blender::Vector;
|
||||||
|
using blender::VectorSet;
|
||||||
|
using namespace blender::nodes::node_tree_ref_types;
|
||||||
|
|
||||||
/* Fallback types for undefined tree, nodes, sockets */
|
/* Fallback types for undefined tree, nodes, sockets */
|
||||||
static bNodeTreeType NodeTreeTypeUndefined;
|
static bNodeTreeType NodeTreeTypeUndefined;
|
||||||
bNodeType NodeTypeUndefined;
|
bNodeType NodeTypeUndefined;
|
||||||
@@ -647,6 +660,8 @@ void ntreeBlendReadData(BlendDataReader *reader, bNodeTree *ntree)
|
|||||||
ntree->progress = nullptr;
|
ntree->progress = nullptr;
|
||||||
ntree->execdata = nullptr;
|
ntree->execdata = nullptr;
|
||||||
|
|
||||||
|
ntree->output_field_dependencies = nullptr;
|
||||||
|
|
||||||
BLO_read_data_address(reader, &ntree->adt);
|
BLO_read_data_address(reader, &ntree->adt);
|
||||||
BKE_animdata_blend_read_data(reader, ntree->adt);
|
BKE_animdata_blend_read_data(reader, ntree->adt);
|
||||||
|
|
||||||
@@ -1015,8 +1030,8 @@ IDTypeInfo IDType_ID_NT = {
|
|||||||
static void node_add_sockets_from_type(bNodeTree *ntree, bNode *node, bNodeType *ntype)
|
static void node_add_sockets_from_type(bNodeTree *ntree, bNode *node, bNodeType *ntype)
|
||||||
{
|
{
|
||||||
if (ntype->declare != nullptr) {
|
if (ntype->declare != nullptr) {
|
||||||
nodeDeclarationEnsure(ntree, node);
|
blender::nodes::NodeDeclaration *node_decl = nodeDeclarationEnsure(ntree, node);
|
||||||
node->declaration->build(*ntree, *node);
|
node_decl->build(*ntree, *node);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
bNodeSocketTemplate *sockdef;
|
bNodeSocketTemplate *sockdef;
|
||||||
@@ -3942,18 +3957,19 @@ int nodeSocketLinkLimit(const bNodeSocket *sock)
|
|||||||
* If the node implements a `declare` function, this function makes sure that `node->declaration`
|
* If the node implements a `declare` function, this function makes sure that `node->declaration`
|
||||||
* is up to date.
|
* is up to date.
|
||||||
*/
|
*/
|
||||||
void nodeDeclarationEnsure(bNodeTree *UNUSED(ntree), bNode *node)
|
NodeDeclarationHandle *nodeDeclarationEnsure(bNodeTree *UNUSED(ntree), bNode *node)
|
||||||
{
|
{
|
||||||
if (node->typeinfo->declare == nullptr) {
|
if (node->typeinfo->declare == nullptr) {
|
||||||
return;
|
return nullptr;
|
||||||
}
|
}
|
||||||
if (node->declaration != nullptr) {
|
if (node->declaration != nullptr) {
|
||||||
return;
|
return node->declaration;
|
||||||
}
|
}
|
||||||
|
|
||||||
node->declaration = new blender::nodes::NodeDeclaration();
|
node->declaration = new blender::nodes::NodeDeclaration();
|
||||||
blender::nodes::NodeDeclarationBuilder builder{*node->declaration};
|
blender::nodes::NodeDeclarationBuilder builder{*node->declaration};
|
||||||
node->typeinfo->declare(builder);
|
node->typeinfo->declare(builder);
|
||||||
|
return node->declaration;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************** Node Clipboard *********** */
|
/* ************** Node Clipboard *********** */
|
||||||
@@ -4468,6 +4484,296 @@ void ntreeUpdateAllUsers(Main *main, ID *id)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool is_field_socket_type(eNodeSocketDatatype type)
|
||||||
|
{
|
||||||
|
return ELEM(type, SOCK_FLOAT, SOCK_INT, SOCK_BOOLEAN, SOCK_VECTOR, SOCK_RGBA);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool sockets_have_links(blender::Span<const SocketRef *> sockets)
|
||||||
|
{
|
||||||
|
for (const SocketRef *socket : sockets) {
|
||||||
|
if (!socket->directly_linked_links().is_empty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
using OutputFieldDependencies = Vector<std::optional<Vector<int>>>;
|
||||||
|
|
||||||
|
static const std::optional<Vector<int>> *get_group_output_field_dependencies(
|
||||||
|
const OutputSocketRef &output_socket)
|
||||||
|
{
|
||||||
|
const NodeRef &node = output_socket.node();
|
||||||
|
BLI_assert(node.is_group_node());
|
||||||
|
bNodeTree *group = (bNodeTree *)node.bnode()->id;
|
||||||
|
if (group == nullptr) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
if (group->output_field_dependencies == nullptr) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
const OutputFieldDependencies *output_field_dependencies = (const OutputFieldDependencies *)
|
||||||
|
group->output_field_dependencies;
|
||||||
|
if (output_socket.index() >= output_field_dependencies->size()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return &(*output_field_dependencies)[output_socket.index()];
|
||||||
|
}
|
||||||
|
|
||||||
|
static Vector<int> get_linked_field_input_indices(const OutputSocketRef &output_socket)
|
||||||
|
{
|
||||||
|
Vector<int> indices;
|
||||||
|
const NodeRef &node = output_socket.node();
|
||||||
|
if (node.is_group_node()) {
|
||||||
|
const std::optional<Vector<int>> *optional_dependencies = get_group_output_field_dependencies(
|
||||||
|
output_socket);
|
||||||
|
if (optional_dependencies && optional_dependencies->has_value()) {
|
||||||
|
indices.extend(**optional_dependencies);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (const InputSocketRef *input_socket : output_socket.node().inputs()) {
|
||||||
|
if (is_field_socket_type((eNodeSocketDatatype)input_socket->typeinfo()->type)) {
|
||||||
|
indices.append(input_socket->index());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return indices;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Vector<const NodeRef *> toposort_nodes(const NodeTreeRef &tree, bool left_to_right = true)
|
||||||
|
{
|
||||||
|
Vector<const NodeRef *> toposort;
|
||||||
|
toposort.reserve(tree.nodes().size());
|
||||||
|
Array<bool> node_is_pushed_by_id(tree.nodes().size(), false);
|
||||||
|
std::queue<const NodeRef *> nodes_to_check;
|
||||||
|
|
||||||
|
for (const NodeRef *node : tree.nodes()) {
|
||||||
|
if (!sockets_have_links(node->inputs_or_outputs(!left_to_right))) {
|
||||||
|
node_is_pushed_by_id[node->id()] = true;
|
||||||
|
nodes_to_check.push(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!nodes_to_check.empty()) {
|
||||||
|
const NodeRef *node = nodes_to_check.front();
|
||||||
|
nodes_to_check.pop();
|
||||||
|
toposort.append(node);
|
||||||
|
|
||||||
|
for (const SocketRef *input_socket : node->inputs_or_outputs(left_to_right)) {
|
||||||
|
for (const SocketRef *linked_socket : input_socket->directly_linked_sockets()) {
|
||||||
|
const NodeRef &linked_node = linked_socket->node();
|
||||||
|
const int linked_node_id = linked_node.id();
|
||||||
|
if (!node_is_pushed_by_id[linked_node_id]) {
|
||||||
|
node_is_pushed_by_id[linked_node_id] = true;
|
||||||
|
nodes_to_check.push(&linked_node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
toposort.as_mutable_span().reverse();
|
||||||
|
return toposort;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SocketFieldState {
|
||||||
|
bool is_single = true;
|
||||||
|
bool is_field_source = false;
|
||||||
|
bool requires_single = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
static std::optional<Vector<int>> find_dependent_group_input_indices(
|
||||||
|
const InputSocketRef &group_output_socket,
|
||||||
|
const Span<SocketFieldState> field_state_by_socket_id)
|
||||||
|
{
|
||||||
|
Set<const InputSocketRef *> handled_sockets;
|
||||||
|
Stack<const InputSocketRef *> sockets_to_check;
|
||||||
|
|
||||||
|
handled_sockets.add(&group_output_socket);
|
||||||
|
sockets_to_check.push(&group_output_socket);
|
||||||
|
|
||||||
|
Set<int> found_input_indices;
|
||||||
|
|
||||||
|
while (!sockets_to_check.is_empty()) {
|
||||||
|
const InputSocketRef *input_socket = sockets_to_check.pop();
|
||||||
|
for (const OutputSocketRef *origin_socket : input_socket->logically_linked_sockets()) {
|
||||||
|
const NodeRef &origin_node = origin_socket->node();
|
||||||
|
const SocketFieldState &origin_state = field_state_by_socket_id[origin_socket->id()];
|
||||||
|
if (origin_state.is_field_source) {
|
||||||
|
if (origin_node.is_group_input_node()) {
|
||||||
|
found_input_indices.add(origin_socket->index());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!origin_state.is_single) {
|
||||||
|
const Vector<int> input_socket_indices = get_linked_field_input_indices(*origin_socket);
|
||||||
|
for (const int input_index : input_socket_indices) {
|
||||||
|
const InputSocketRef &origin_input_socket = origin_node.input(input_index);
|
||||||
|
if (!field_state_by_socket_id[origin_input_socket.id()].is_single) {
|
||||||
|
if (handled_sockets.add(&origin_input_socket)) {
|
||||||
|
sockets_to_check.push(&origin_input_socket);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Vector<int>(found_input_indices.begin(), found_input_indices.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void update_socket_shapes_for_fields(bNodeTree &btree)
|
||||||
|
{
|
||||||
|
using namespace blender;
|
||||||
|
using namespace blender::nodes;
|
||||||
|
if (btree.type != NTREE_GEOMETRY) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeTreeRef tree{&btree};
|
||||||
|
Vector<const NodeRef *> toposort_left_to_right = toposort_nodes(tree, true);
|
||||||
|
Vector<const NodeRef *> toposort_right_to_left = toposort_nodes(tree, false);
|
||||||
|
|
||||||
|
Array<SocketFieldState> field_state_by_socket_id(tree.sockets().size());
|
||||||
|
|
||||||
|
auto check_if_node_is_adaptive = [](const NodeRef &node) {
|
||||||
|
const StringRef node_idname = node.idname();
|
||||||
|
return !node_idname.startswith("GeometryNode");
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const NodeRef *node : toposort_right_to_left) {
|
||||||
|
NodeDeclaration *node_decl = nodeDeclarationEnsure(&btree, node->bnode());
|
||||||
|
|
||||||
|
const bool node_is_adaptive = check_if_node_is_adaptive(*node);
|
||||||
|
|
||||||
|
for (const OutputSocketRef *output_socket : node->outputs()) {
|
||||||
|
SocketFieldState &state = field_state_by_socket_id[output_socket->id()];
|
||||||
|
for (const InputSocketRef *target_socket : output_socket->directly_linked_sockets()) {
|
||||||
|
state.requires_single |= field_state_by_socket_id[target_socket->id()].requires_single;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state.requires_single) {
|
||||||
|
const Vector<int> input_socket_indices = get_linked_field_input_indices(*output_socket);
|
||||||
|
for (const int input_index : input_socket_indices) {
|
||||||
|
const InputSocketRef &input_socket = node->input(input_index);
|
||||||
|
field_state_by_socket_id[input_socket.id()].requires_single = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const InputSocketRef *input_socket : node->inputs()) {
|
||||||
|
SocketFieldState &state = field_state_by_socket_id[input_socket->id()];
|
||||||
|
if (state.requires_single) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (node_decl != nullptr && !node_is_adaptive) {
|
||||||
|
const SocketDeclaration &socket_decl = *node_decl->inputs()[input_socket->index()];
|
||||||
|
state.requires_single |= !socket_decl.is_field();
|
||||||
|
}
|
||||||
|
if (!is_field_socket_type((eNodeSocketDatatype)input_socket->bsocket()->type)) {
|
||||||
|
state.requires_single = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const NodeRef *node : tree.nodes_by_type("NodeGroupInput")) {
|
||||||
|
for (const OutputSocketRef *output_socket : node->outputs().drop_back(1)) {
|
||||||
|
SocketFieldState &state = field_state_by_socket_id[output_socket->id()];
|
||||||
|
if (!state.requires_single) {
|
||||||
|
state.is_single = false;
|
||||||
|
state.is_field_source = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const NodeRef *node : toposort_left_to_right) {
|
||||||
|
NodeDeclaration *node_decl = nodeDeclarationEnsure(&btree, node->bnode());
|
||||||
|
|
||||||
|
for (const InputSocketRef *input_socket : node->inputs()) {
|
||||||
|
SocketFieldState &state = field_state_by_socket_id[input_socket->id()];
|
||||||
|
if (state.requires_single) {
|
||||||
|
state.is_single = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
state.is_single = true;
|
||||||
|
for (const OutputSocketRef *origin_socket : input_socket->logically_linked_sockets()) {
|
||||||
|
if (!field_state_by_socket_id[origin_socket->id()].is_single) {
|
||||||
|
state.is_single = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const OutputSocketRef *output_socket : node->outputs()) {
|
||||||
|
SocketFieldState &state = field_state_by_socket_id[output_socket->id()];
|
||||||
|
if (node_decl != nullptr) {
|
||||||
|
const SocketDeclaration &socket_decl = *node_decl->outputs()[output_socket->index()];
|
||||||
|
if (socket_decl.is_field()) {
|
||||||
|
state.is_single = false;
|
||||||
|
state.is_field_source = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (output_socket->node().is_group_node()) {
|
||||||
|
const std::optional<Vector<int>> *optional_dependencies =
|
||||||
|
get_group_output_field_dependencies(*output_socket);
|
||||||
|
if (optional_dependencies && !optional_dependencies->has_value()) {
|
||||||
|
state.is_single = false;
|
||||||
|
state.is_field_source = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const Vector<int> input_socket_indices = get_linked_field_input_indices(*output_socket);
|
||||||
|
for (const int input_index : input_socket_indices) {
|
||||||
|
const InputSocketRef &input_socket = node->input(input_index);
|
||||||
|
if (!field_state_by_socket_id[input_socket.id()].is_single) {
|
||||||
|
state.is_single = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const NodeRef *group_output_node : tree.nodes_by_type("NodeGroupOutput")) {
|
||||||
|
if (!(group_output_node->bnode()->flag & NODE_DO_OUTPUT)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
OutputFieldDependencies *output_field_dependencies = new OutputFieldDependencies();
|
||||||
|
for (const InputSocketRef *group_output_socket : group_output_node->inputs().drop_back(1)) {
|
||||||
|
std::optional<Vector<int>> dependent_input_indices = find_dependent_group_input_indices(
|
||||||
|
*group_output_socket, field_state_by_socket_id);
|
||||||
|
output_field_dependencies->append(std::move(dependent_input_indices));
|
||||||
|
}
|
||||||
|
if (btree.output_field_dependencies != nullptr) {
|
||||||
|
delete (OutputFieldDependencies *)btree.output_field_dependencies;
|
||||||
|
}
|
||||||
|
btree.output_field_dependencies = output_field_dependencies;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const InputSocketRef *socket : tree.input_sockets()) {
|
||||||
|
bNodeSocket *bsocket = socket->bsocket();
|
||||||
|
const SocketFieldState &state = field_state_by_socket_id[socket->id()];
|
||||||
|
if (state.requires_single) {
|
||||||
|
bsocket->display_shape = SOCK_DISPLAY_SHAPE_CIRCLE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
bsocket->display_shape = SOCK_DISPLAY_SHAPE_DIAMOND;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const OutputSocketRef *socket : tree.output_sockets()) {
|
||||||
|
bNodeSocket *bsocket = socket->bsocket();
|
||||||
|
const SocketFieldState &state = field_state_by_socket_id[socket->id()];
|
||||||
|
if (state.is_single) {
|
||||||
|
bsocket->display_shape = SOCK_DISPLAY_SHAPE_CIRCLE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
bsocket->display_shape = SOCK_DISPLAY_SHAPE_DIAMOND;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ntreeUpdateTree(Main *bmain, bNodeTree *ntree)
|
void ntreeUpdateTree(Main *bmain, bNodeTree *ntree)
|
||||||
{
|
{
|
||||||
if (!ntree) {
|
if (!ntree) {
|
||||||
@@ -4519,6 +4825,8 @@ void ntreeUpdateTree(Main *bmain, bNodeTree *ntree)
|
|||||||
/* update the node level from link dependencies */
|
/* update the node level from link dependencies */
|
||||||
ntree_update_node_level(ntree);
|
ntree_update_node_level(ntree);
|
||||||
|
|
||||||
|
update_socket_shapes_for_fields(*ntree);
|
||||||
|
|
||||||
/* check link validity */
|
/* check link validity */
|
||||||
ntree_validate_links(ntree);
|
ntree_validate_links(ntree);
|
||||||
}
|
}
|
||||||
|
@@ -4282,6 +4282,12 @@ void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link)
|
|||||||
// th_col3 = -1; /* no shadow */
|
// th_col3 = -1; /* no shadow */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (snode->edittree->type == NTREE_GEOMETRY) {
|
||||||
|
if ((link->fromsock && link->fromsock->display_shape == SOCK_DISPLAY_SHAPE_DIAMOND) &&
|
||||||
|
(link->tosock && link->tosock->display_shape == SOCK_DISPLAY_SHAPE_CIRCLE)) {
|
||||||
|
th_col1 = th_col2 = th_col3 = TH_REDALERT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
node_draw_link_bezier(v2d, snode, link, th_col1, th_col2, th_col3);
|
node_draw_link_bezier(v2d, snode, link, th_col1, th_col2, th_col3);
|
||||||
}
|
}
|
||||||
|
@@ -481,6 +481,8 @@ typedef struct bNodeTree {
|
|||||||
float view_center[2];
|
float view_center[2];
|
||||||
|
|
||||||
ListBase nodes, links;
|
ListBase nodes, links;
|
||||||
|
/* Vector<std::optional<Vector<int>>>. */
|
||||||
|
void *output_field_dependencies;
|
||||||
|
|
||||||
/** Set init on fileread. */
|
/** Set init on fileread. */
|
||||||
int type, init;
|
int type, init;
|
||||||
|
@@ -37,6 +37,7 @@ class SocketDeclaration {
|
|||||||
bool hide_label_ = false;
|
bool hide_label_ = false;
|
||||||
bool hide_value_ = false;
|
bool hide_value_ = false;
|
||||||
bool is_multi_input_ = false;
|
bool is_multi_input_ = false;
|
||||||
|
bool is_field_ = false;
|
||||||
|
|
||||||
friend NodeDeclarationBuilder;
|
friend NodeDeclarationBuilder;
|
||||||
template<typename SocketDecl> friend class SocketDeclarationBuilder;
|
template<typename SocketDecl> friend class SocketDeclarationBuilder;
|
||||||
@@ -51,6 +52,8 @@ class SocketDeclaration {
|
|||||||
StringRefNull name() const;
|
StringRefNull name() const;
|
||||||
StringRefNull identifier() const;
|
StringRefNull identifier() const;
|
||||||
|
|
||||||
|
bool is_field() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void set_common_flags(bNodeSocket &socket) const;
|
void set_common_flags(bNodeSocket &socket) const;
|
||||||
bool matches_common_data(const bNodeSocket &socket) const;
|
bool matches_common_data(const bNodeSocket &socket) const;
|
||||||
@@ -93,6 +96,12 @@ class SocketDeclarationBuilder : public BaseSocketDeclarationBuilder {
|
|||||||
decl_->is_multi_input_ = value;
|
decl_->is_multi_input_ = value;
|
||||||
return *(Self *)this;
|
return *(Self *)this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Self &is_field(bool value = true)
|
||||||
|
{
|
||||||
|
decl_->is_field_ = value;
|
||||||
|
return *(Self *)this;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
using SocketDeclarationPtr = std::unique_ptr<SocketDeclaration>;
|
using SocketDeclarationPtr = std::unique_ptr<SocketDeclaration>;
|
||||||
@@ -148,6 +157,11 @@ inline StringRefNull SocketDeclaration::identifier() const
|
|||||||
return identifier_;
|
return identifier_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool SocketDeclaration::is_field() const
|
||||||
|
{
|
||||||
|
return is_field_;
|
||||||
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------
|
/* --------------------------------------------------------------------
|
||||||
* NodeDeclarationBuilder inline methods.
|
* NodeDeclarationBuilder inline methods.
|
||||||
*/
|
*/
|
||||||
|
@@ -181,6 +181,7 @@ class NodeRef : NonCopyable, NonMovable {
|
|||||||
|
|
||||||
Span<const InputSocketRef *> inputs() const;
|
Span<const InputSocketRef *> inputs() const;
|
||||||
Span<const OutputSocketRef *> outputs() const;
|
Span<const OutputSocketRef *> outputs() const;
|
||||||
|
Span<const SocketRef *> inputs_or_outputs(bool get_inputs) const;
|
||||||
Span<const InternalLinkRef *> internal_links() const;
|
Span<const InternalLinkRef *> internal_links() const;
|
||||||
|
|
||||||
const InputSocketRef &input(int index) const;
|
const InputSocketRef &input(int index) const;
|
||||||
@@ -496,6 +497,12 @@ inline Span<const OutputSocketRef *> NodeRef::outputs() const
|
|||||||
return outputs_;
|
return outputs_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline Span<const SocketRef *> NodeRef::inputs_or_outputs(bool get_inputs) const
|
||||||
|
{
|
||||||
|
return get_inputs ? inputs_.as_span().cast<const SocketRef *>() :
|
||||||
|
outputs_.as_span().cast<const SocketRef *>();
|
||||||
|
}
|
||||||
|
|
||||||
inline Span<const InternalLinkRef *> NodeRef::internal_links() const
|
inline Span<const InternalLinkRef *> NodeRef::internal_links() const
|
||||||
{
|
{
|
||||||
return internal_links_;
|
return internal_links_;
|
||||||
|
@@ -173,6 +173,12 @@ class Bool : public SocketDeclaration {
|
|||||||
public:
|
public:
|
||||||
using Builder = BoolBuilder;
|
using Builder = BoolBuilder;
|
||||||
|
|
||||||
|
Bool &is_field(bool value)
|
||||||
|
{
|
||||||
|
is_field_ = value;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
bNodeSocket &build(bNodeTree &ntree, bNode &node, eNodeSocketInOut in_out) const override;
|
bNodeSocket &build(bNodeTree &ntree, bNode &node, eNodeSocketInOut in_out) const override;
|
||||||
bool matches(const bNodeSocket &socket) const override;
|
bool matches(const bNodeSocket &socket) const override;
|
||||||
};
|
};
|
||||||
|
@@ -20,7 +20,7 @@ namespace blender::nodes {
|
|||||||
|
|
||||||
static void geo_node_input_index_declare(NodeDeclarationBuilder &b)
|
static void geo_node_input_index_declare(NodeDeclarationBuilder &b)
|
||||||
{
|
{
|
||||||
b.add_output<decl::Int>("Index");
|
b.add_output<decl::Int>("Index").is_field();
|
||||||
}
|
}
|
||||||
|
|
||||||
class IndexFieldInput final : public fn::FieldInput {
|
class IndexFieldInput final : public fn::FieldInput {
|
||||||
|
@@ -25,7 +25,7 @@ namespace blender::nodes {
|
|||||||
|
|
||||||
static void geo_node_input_normal_declare(NodeDeclarationBuilder &b)
|
static void geo_node_input_normal_declare(NodeDeclarationBuilder &b)
|
||||||
{
|
{
|
||||||
b.add_output<decl::Vector>("Normal");
|
b.add_output<decl::Vector>("Normal").is_field();
|
||||||
}
|
}
|
||||||
|
|
||||||
static GVArrayPtr mesh_face_normals(const Mesh &mesh,
|
static GVArrayPtr mesh_face_normals(const Mesh &mesh,
|
||||||
|
@@ -20,7 +20,7 @@ namespace blender::nodes {
|
|||||||
|
|
||||||
static void geo_node_input_position_declare(NodeDeclarationBuilder &b)
|
static void geo_node_input_position_declare(NodeDeclarationBuilder &b)
|
||||||
{
|
{
|
||||||
b.add_output<decl::Vector>("Position");
|
b.add_output<decl::Vector>("Position").is_field();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void geo_node_input_position_exec(GeoNodeExecParams params)
|
static void geo_node_input_position_exec(GeoNodeExecParams params)
|
||||||
|
@@ -23,8 +23,8 @@ namespace blender::nodes {
|
|||||||
static void geo_node_set_position_declare(NodeDeclarationBuilder &b)
|
static void geo_node_set_position_declare(NodeDeclarationBuilder &b)
|
||||||
{
|
{
|
||||||
b.add_input<decl::Geometry>("Geometry");
|
b.add_input<decl::Geometry>("Geometry");
|
||||||
b.add_input<decl::Vector>("Position");
|
b.add_input<decl::Vector>("Position").is_field();
|
||||||
b.add_input<decl::Bool>("Selection").default_value(true).hide_value();
|
b.add_input<decl::Bool>("Selection").default_value(true).hide_value().is_field();
|
||||||
b.add_output<decl::Geometry>("Geometry");
|
b.add_output<decl::Geometry>("Geometry");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user