42#include "RNA_prototypes.hh"
59 const char *engine_id = scene->
r.
engine;
83 *r_id =
static_cast<ID *
>(ob->
data);
100 *r_id = &linestyle->
id;
133 if (node->is_muted() || node->is_reroute()) {
134 if (node->is_group() && node->id) {
193 tt->
idname =
"ShaderNodeTree";
196 tt->
ui_icon = ICON_NODE_MATERIAL;
197 tt->
ui_description =
N_(
"Edit materials, lights, and world shading using nodes");
221 bNode *output_node =
nullptr;
224 if (!
ELEM(node->type_legacy,
233 if (output_node ==
nullptr) {
242 else if (node->custom1 == target) {
243 if (output_node ==
nullptr) {
262 if (
STREQ(sock->identifier, identifier)) {
315 if (fromnode->
runtime->tmp_flag == -1 &&
321 if (tonode->
runtime->tmp_flag == -1 &&
333 bool (*node_filter)(
const bNode *node))
335 auto gather_branch_nodes = [](
bNode *fromnode,
bNode * ,
void *userdata) {
342 ntree, start_node, gather_branch_nodes, &branch_nodes, 0);
358 if (node->
runtime->tmp_flag >= 0) {
359 int id = node->
runtime->tmp_flag;
373 copy->runtime->tmp_flag = -2;
377 sock->link =
nullptr;
380 sock->link =
nullptr;
387 bool from_copy = link->fromnode->runtime->tmp_flag >= 0;
388 bool to_copy = link->tonode->runtime->tmp_flag >= 0;
389 if (from_copy && to_copy) {
390 bNode *from_node = nodes_copy[link->fromnode->runtime->tmp_flag];
391 bNode *to_node = nodes_copy[link->tonode->runtime->tmp_flag];
400 bNode *to_node = nodes_copy[link->tonode->runtime->tmp_flag];
408 else if (from_copy && branch_nodes.
contains(link->tonode)) {
409 bNode *from_node = nodes_copy[link->fromnode->runtime->tmp_flag];
426 bool modified =
false;
433 *ntree, *link->fromnode, *link->fromsock, *emission_node, *in_sock);
459 addnode->
runtime->tmp_flag = -2;
469 *tosock = addsock_out;
474 int *node_count = (
int *)userdata;
481 if (tonode->
runtime->tmp_flag == -1 && to_node_from_weight_tree) {
482 tonode->
runtime->tmp_flag = *node_count;
485 if (fromnode->
runtime->tmp_flag == -1 &&
488 fromnode->
runtime->tmp_flag = *node_count;
491 return to_node_from_weight_tree;
500 if (displace_output && displace_output->
link) {
502 displace_link = displace_output->
link;
503 displace_output->
link =
nullptr;
507 if (thickness_output && thickness_output->
link) {
509 thickness_link = thickness_output->
link;
510 thickness_output->
link =
nullptr;
514 node->runtime->tmp_flag = -1;
517 output_node->
runtime->tmp_flag = 0;
524 if (node->runtime->tmp_flag >= 0) {
525 int id = node->runtime->tmp_flag;
527 switch (node->type_legacy) {
534 nodes_copy[id]->runtime->tmp_flag = -2;
544 nodes_copy[id]->runtime->tmp_flag = -2;
551 bNode *fromnode, *tonode;
557 nodes_copy[id]->runtime->tmp_flag = -2;
562 nodes_copy[id]->runtime->tmp_flag = -2;
568 nodes_copy[id]->runtime->tmp_flag = -2;
573 if (!fac_sock->
link) {
583 nodes_copy[id]->runtime->tmp_flag = -2;
588 fromnode = nodes_copy[id_start];
589 tonode = nodes_copy[id_start + 1];
594 fromnode = nodes_copy[id_start + 2];
595 tonode = nodes_copy[id_start];
600 fromnode = nodes_copy[id_start + 3];
602 tonode = nodes_copy[id_start];
605 tonode = nodes_copy[id_start + 1];
618 if (node->runtime->tmp_flag >= 0) {
626 switch (node->type_legacy) {
632 tonode = nodes_copy[node->runtime->tmp_flag];
637 if (socket_index == 0) {
639 tonode = nodes_copy[node->runtime->tmp_flag + 2];
642 else if (socket_index == 1) {
644 tonode = nodes_copy[node->runtime->tmp_flag + 1];
649 tonode = nodes_copy[node->runtime->tmp_flag];
661 bNode *fromnode = sock->link->fromnode;
665 fromnode = nodes_copy[fromnode->
runtime->tmp_flag];
667 if (fromsock->
link) {
673 fromnode = nodes_copy[fromnode->
runtime->tmp_flag + 3];
675 if (fromsock->
link) {
706 if (fromsock->
link) {
718 *ntree, *fromnode, *fromsock, *tonode, *tosock);
732 if (thickness_link) {
781 shader_to_rgba_nodes.
append(node);
785 for (
bNode *shader_to_rgba : shader_to_rgba_nodes) {
787 if (closure_input->
link ==
nullptr) {
808 stack.
push({node_start, 0});
811 StackNode s_node = !stack.
is_empty() ? stack.
pop() : zone_stack.
pop();
813 bNode *node = s_node.node;
814 int16_t depth_level = s_node.depth;
816 if (node->
runtime->tmp_flag >= depth_level) {
823 max_depth = std::max(max_depth, depth_level);
826 node->
runtime->tmp_flag = std::max(node->
runtime->tmp_flag, depth_level);
830 if (link ==
nullptr) {
846 if (
bNode *zone_input_node = zone_type->get_corresponding_input(*ntree, *node)) {
847 zone_stack.
push({zone_input_node, depth_level});
864 int factor_socket_index,
870 if (factor_socket->
link ==
nullptr) {
876 factor =
clamp_f(factor, 0.0f, 1.0f);
881 float vfactor_copy[3];
882 for (
int i = 0;
i < 3;
i++) {
884 vfactor_copy[
i] =
clamp_f(vfactor[
i], 0.0f, 1.0f);
887 vfactor_copy[
i] = vfactor[
i];
890 if (vfactor_copy[0] == vfactor_copy[1] && vfactor_copy[0] == vfactor_copy[2]) {
891 factor = vfactor_copy[0];
895 if (factor == 1.0f && a_socket_index >= 0) {
898 else if (factor == 0.0f && b_socket_index >= 0) {
910 else if (node->typeinfo->type_legacy ==
SH_NODE_MIX) {
915 for (
int i : {1, 4, 5, 6, 7}) {
922 ntree, node, factor_socket, 4, 5, storage->
clamp_factor);
924 int unused_factor_socket = factor_socket == 0 ? 1 : 0;
925 for (
int i : {unused_factor_socket, 2, 3, 6, 7}) {
933 for (
int i : {1, 2, 3, 4, 5}) {
943 fromnode->
runtime->tmp_flag = 1;
955 bool changed =
false;
958 node->runtime->tmp_flag = 0;
963 output_node->
runtime->tmp_flag = 1;
970 node->runtime->tmp_flag = 1;
976 if (node->runtime->tmp_flag == 0) {
1009 int16_t max_depth = 0;
1011 node->runtime->tmp_flag = -1;
1021 for (
int depth = max_depth; depth >= 0; depth--) {
1046 node->runtime->need_exec = 1;
1060 if (ntree->
runtime->execdata) {
1061 return ntree->
runtime->execdata;
1076 if (
exec->threadstack) {
1087 exec->threadstack =
nullptr;
1102 ntree->
runtime->execdata =
nullptr;
SpaceNode * CTX_wm_space_node(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
ViewLayer * CTX_data_view_layer(const bContext *C)
void BKE_view_layer_synced_ensure(const Scene *scene, ViewLayer *view_layer)
Object * BKE_view_layer_active_object_get(const ViewLayer *view_layer)
@ LIB_ID_CREATE_NO_USER_REFCOUNT
Blender kernel freestyle line style functionality.
FreestyleLineStyle * BKE_linestyle_active_from_view_layer(struct ViewLayer *view_layer)
General operations, lookup, etc. for materials.
Material * BKE_object_material_get(Object *ob, short act)
#define NODE_CLASS_OUTPUT
#define NODE_CLASS_INTERFACE
#define NODE_CLASS_CONVERTER
#define NODE_CLASS_OP_VECTOR
#define NODE_CLASS_LAYOUT
#define NODE_CLASS_OP_COLOR
#define NODE_CLASS_TEXTURE
#define NODE_CLASS_SHADER
#define NODE_CLASS_SCRIPT
#define SH_NODE_MIX_SHADER
#define SH_NODE_BSDF_METALLIC
#define SH_NODE_VOLUME_COEFFICIENTS
#define SH_NODE_OUTPUT_WORLD
#define SH_NODE_BSDF_PRINCIPLED
#define SH_NODE_BSDF_SHEEN
#define SH_NODE_ADD_SHADER
#define SH_NODE_SUBSURFACE_SCATTERING
#define SH_NODE_VOLUME_ABSORPTION
#define SH_NODE_BSDF_TOON
#define SH_NODE_BSDF_TRANSPARENT
#define SH_NODE_BSDF_DIFFUSE
#define SH_NODE_SHADERTORGB
#define SH_NODE_OUTPUT_MATERIAL
#define SH_NODE_BSDF_TRANSLUCENT
#define SH_NODE_BSDF_HAIR_PRINCIPLED
#define SH_NODE_BSDF_HAIR
#define SH_NODE_BACKGROUND
#define SH_NODE_BSDF_RAY_PORTAL
#define SH_NODE_BSDF_GLOSSY
#define SH_NODE_EEVEE_SPECULAR
#define SH_NODE_BSDF_GLASS
#define SH_NODE_VOLUME_PRINCIPLED
#define SH_NODE_BSDF_REFRACTION
#define SH_NODE_OUTPUT_LIGHT
#define SH_NODE_VOLUME_SCATTER
#define SH_NODE_OUTPUT_AOV
void BKE_ntree_update_without_main(bNodeTree &tree)
bool BKE_scene_use_shading_nodes_custom(Scene *scene)
void * BLI_findlink(const ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
#define LISTBASE_FOREACH(type, var, list)
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
void void BLI_freelistN(ListBase *listbase) ATTR_NONNULL(1)
#define LISTBASE_FOREACH_INDEX(type, var, list, index_var)
MINLINE float clamp_f(float value, float min, float max)
#define BLENDER_MAX_THREADS
struct blender::bke::bNodeTreeType * ntreeType_Shader
bool contains(const Key &key) const
void push(const T &value)
void append(const T &value)
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
void MEM_freeN(void *vmemh)
void node_chain_iterator_backwards(const bNodeTree *ntree, bNode *node_start, bool(*callback)(bNode *, bNode *, void *), void *userdata, int recursion_lvl)
void node_tree_free_local_node(bNodeTree &ntree, bNode &node)
void node_tree_set_output(bNodeTree &ntree)
const bNodeZoneType * zone_type_by_node_type(const int node_type)
void node_unlink_node(bNodeTree &ntree, bNode &node)
void node_tree_free_tree(bNodeTree &ntree)
void node_remove_link(bNodeTree *ntree, bNodeLink &link)
void node_tree_type_add(bNodeTreeType &nt)
void node_internal_relink(bNodeTree &ntree, bNode &node)
const bNodeInstanceKey NODE_INSTANCE_KEY_BASE
void node_free_node(bNodeTree *tree, bNode &node)
void(*)(void *calldata, int nclass, StringRefNull name) bNodeClassCallback
bNode * node_add_static_node(const bContext *C, bNodeTree &ntree, int type)
bNodeLink & node_add_link(bNodeTree &ntree, bNode &fromnode, bNodeSocket &fromsock, bNode &tonode, bNodeSocket &tosock)
bNode * node_copy_with_mapping(bNodeTree *dst_tree, const bNode &node_src, int flag, std::optional< StringRefNull > dst_unique_name, std::optional< int > dst_unique_identifier, Map< const bNodeSocket *, bNodeSocket * > &new_socket_map, bool allow_duplicate_names=false)
bool node_is_static_socket_type(const bNodeSocketType &stype)
void ntree_update_reroute_nodes(bNodeTree *ntree)
static void localize(bNodeTree *localtree, bNodeTree *ntree)
static void update(bNodeTree *ntree)
static void foreach_nodeclass(void *calldata, blender::bke::bNodeClassCallback func)
bNodeTreeExec * ntree_exec_begin(bNodeExecContext *context, bNodeTree *ntree, bNodeInstanceKey parent_key)
void ntree_exec_end(bNodeTreeExec *exec)
static bNodeSocket * ntree_shader_node_input_get(bNode *node, int n)
static bool ntree_shader_implicit_closure_cast(bNodeTree *ntree)
static bool ntree_branch_count_and_tag_nodes(bNode *fromnode, bNode *tonode, void *userdata)
bNodeTreeExec * ntreeShaderBeginExecTree_internal(bNodeExecContext *context, bNodeTree *ntree, bNodeInstanceKey parent_key)
static bool ntree_weight_tree_tag_nodes(bNode *fromnode, bNode *tonode, void *userdata)
static bNodeSocket * ntree_shader_node_find_output(bNode *node, const char *identifier)
static void ntree_weight_tree_merge_weight(bNodeTree *ntree, bNode *, bNodeSocket *fromsock, bNode **tonode, bNodeSocket **tosock)
static void ntree_shader_disconnect_inactive_mix_branches(bNodeTree *ntree)
static void ntree_shader_shader_to_rgba_branches(bNodeTree *ntree)
static bNodeSocket * ntree_shader_node_find_input(bNode *node, const char *identifier)
static void shader_node_disconnect_inactive_mix_branch(bNodeTree *ntree, bNode *node, int factor_socket_index, int a_socket_index, int b_socket_index, bool clamp_factor)
static bool closure_node_filter(const bNode *node)
static void ntree_shader_weight_tree_invert(bNodeTree *ntree, bNode *output_node)
static bool shader_node_tree_socket_type_valid(blender::bke::bNodeTreeType *, blender::bke::bNodeSocketType *socket_type)
static void iter_shader_to_rgba_depth_count(bNodeTree *ntree, bNode *node_start, int16_t &max_depth)
void register_node_tree_type_sh()
static void update(bNodeTree *ntree)
static void ntree_shader_unlink_script_nodes(bNodeTree *ntree)
bNode * ntreeShaderOutputNode(bNodeTree *ntree, int target)
static bNodeSocket * ntree_shader_node_find_socket(ListBase *sockets, const char *identifier)
static void shader_get_from_context(const bContext *C, blender::bke::bNodeTreeType *, bNodeTree **r_ntree, ID **r_id, ID **r_from)
static bool shader_validate_link(eNodeSocketDatatype from, eNodeSocketDatatype to)
static void ntree_shader_pruned_unused(bNodeTree *ntree, bNode *output_node)
static bool ntree_branch_node_tag(bNode *fromnode, bNode *tonode, void *)
static void ntree_shader_copy_branch(bNodeTree *ntree, bNode *start_node, bool(*node_filter)(const bNode *node))
bNodeTreeExec * ntreeShaderBeginExecTree(bNodeTree *ntree)
static bool shader_tree_poll(const bContext *C, blender::bke::bNodeTreeType *)
void ntreeShaderEndExecTree(bNodeTreeExec *exec)
static void shader_node_disconnect_input(bNodeTree *ntree, bNode *node, int index)
static bNodeSocket * ntree_shader_node_output_get(bNode *node, int n)
static void localize(bNodeTree *localtree, bNodeTree *)
void ntreeShaderEndExecTree_internal(bNodeTreeExec *exec)
static void foreach_nodeclass(void *calldata, blender::bke::bNodeClassCallback func)
void ntreeExecGPUNodes(bNodeTreeExec *exec, GPUMaterial *mat, bNode *output_node, const int *depth_level)
static void exec(void *data, int, bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out)
static void copy(bNodeTree *dest_ntree, bNode *dest_node, const bNode *src_node)
const char * RE_engine_id_CYCLES
struct bNodeTree * nodetree
struct bNodeTree * nodetree
struct bNodeTree * nodetree
bNodeTreeRuntimeHandle * runtime
bNodeRuntimeHandle * runtime
void(* update)(bNodeTree *ntree)
void(* foreach_nodeclass)(void *calldata, bNodeClassCallback func)
std::string ui_description
bool(* poll)(const bContext *C, bNodeTreeType *ntreetype)
void(* get_from_context)(const bContext *C, bNodeTreeType *ntreetype, bNodeTree **r_ntree, ID **r_id, ID **r_from)
void(* localize)(bNodeTree *localtree, bNodeTree *ntree)
bool(* validate_link)(eNodeSocketDatatype from, eNodeSocketDatatype to)
bool(* valid_socket_type)(bNodeTreeType *ntreetype, bNodeSocketType *socket_type)
bool(* node_filter)(const bNode *node)
void * ntreeGPUMaterialNodes