Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukas Toenne <lukas.toenne@googlemail.com>2013-03-18 20:34:57 +0400
committerLukas Toenne <lukas.toenne@googlemail.com>2013-03-18 20:34:57 +0400
commit4638e5f99a9ba59ad0b8a1fd52b12e876480b9e8 (patch)
tree2444f12b4612440f44cf02835cdf5951b6564e92
parent7bfef29f2f2a1b262d28abdc6e30fcd9c1f1caad (diff)
Merge of the PyNodes branch (aka "custom nodes") into trunk.
PyNodes opens up the node system in Blender to scripters and adds a number of UI-level improvements. === Dynamic node type registration === Node types can now be added at runtime, using the RNA registration mechanism from python. This enables addons such as render engines to create a complete user interface with nodes. Examples of how such nodes can be defined can be found in my personal wiki docs atm [1] and as a script template in release/scripts/templates_py/custom_nodes.py [2]. === Node group improvements === Each node editor now has a tree history of edited node groups, which allows opening and editing nested node groups. The node editor also supports pinning now, so that different spaces can be used to edit different node groups simultaneously. For more ramblings and rationale see (really old) blog post on code.blender.org [3]. The interface of node groups has been overhauled. Sockets of a node group are no longer displayed in columns on either side, but instead special input/output nodes are used to mirror group sockets inside a node tree. This solves the problem of long node lines in groups and allows more adaptable node layout. Internal sockets can be exposed from a group by either connecting to the extension sockets in input/output nodes (shown as empty circle) or by adding sockets from the node property bar in the "Interface" panel. Further details such as the socket name can also be changed there. [1] http://wiki.blender.org/index.php/User:Phonybone/Python_Nodes [2] http://projects.blender.org/scm/viewvc.php/trunk/blender/release/scripts/templates_py/custom_nodes.py?view=markup&root=bf-blender [3] http://code.blender.org/index.php/2012/01/improving-node-group-interface-editing/
-rw-r--r--doc/python_api/examples/bpy.types.NodeTree.py23
-rw-r--r--intern/cycles/blender/blender_python.cpp93
-rw-r--r--intern/cycles/blender/blender_shader.cpp1148
-rw-r--r--intern/cycles/blender/blender_util.h60
-rw-r--r--intern/cycles/render/graph.h2
-rw-r--r--intern/cycles/render/nodes.cpp9
-rw-r--r--intern/cycles/render/nodes.h4
-rw-r--r--release/scripts/modules/bpy_types.py155
-rw-r--r--release/scripts/startup/bl_operators/node.py194
-rw-r--r--release/scripts/startup/bl_ui/space_node.py43
-rw-r--r--release/scripts/templates_py/custom_nodes.py159
-rw-r--r--source/blender/blenkernel/BKE_blender.h2
-rw-r--r--source/blender/blenkernel/BKE_node.h489
-rw-r--r--source/blender/blenkernel/intern/image.c2
-rw-r--r--source/blender/blenkernel/intern/mask.c9
-rw-r--r--source/blender/blenkernel/intern/material.c4
-rw-r--r--source/blender/blenkernel/intern/movieclip.c9
-rw-r--r--source/blender/blenkernel/intern/node.c2902
-rw-r--r--source/blender/blenkernel/intern/texture.c2
-rw-r--r--source/blender/blenlib/BLI_ghash.h1
-rw-r--r--source/blender/blenlib/CMakeLists.txt3
-rw-r--r--source/blender/blenlib/intern/BLI_ghash.c32
-rw-r--r--source/blender/blenloader/intern/readfile.c1105
-rw-r--r--source/blender/blenloader/intern/readfile.h1
-rw-r--r--source/blender/blenloader/intern/versioning_250.c180
-rw-r--r--source/blender/blenloader/intern/writefile.c229
-rw-r--r--source/blender/compositor/intern/COM_CompositorContext.cpp1
-rw-r--r--source/blender/compositor/intern/COM_CompositorContext.h19
-rw-r--r--source/blender/compositor/intern/COM_Converter.cpp7
-rw-r--r--source/blender/compositor/intern/COM_ExecutionSystem.cpp5
-rw-r--r--source/blender/compositor/intern/COM_ExecutionSystemHelper.cpp66
-rw-r--r--source/blender/compositor/intern/COM_ExecutionSystemHelper.h2
-rw-r--r--source/blender/compositor/intern/COM_InputSocket.cpp21
-rw-r--r--source/blender/compositor/intern/COM_InputSocket.h1
-rw-r--r--source/blender/compositor/intern/COM_Node.cpp33
-rw-r--r--source/blender/compositor/intern/COM_Node.h12
-rw-r--r--source/blender/compositor/intern/COM_NodeBase.h20
-rw-r--r--source/blender/compositor/intern/COM_Socket.cpp25
-rw-r--r--source/blender/compositor/intern/COM_Socket.h5
-rw-r--r--source/blender/compositor/intern/COM_compositor.cpp10
-rw-r--r--source/blender/compositor/nodes/COM_BlurNode.cpp3
-rw-r--r--source/blender/compositor/nodes/COM_BokehBlurNode.cpp6
-rw-r--r--source/blender/compositor/nodes/COM_ColorCurveNode.cpp9
-rw-r--r--source/blender/compositor/nodes/COM_ColorNode.cpp9
-rw-r--r--source/blender/compositor/nodes/COM_GroupNode.cpp89
-rw-r--r--source/blender/compositor/nodes/COM_LensDistortionNode.cpp4
-rw-r--r--source/blender/compositor/nodes/COM_NormalNode.cpp6
-rw-r--r--source/blender/compositor/nodes/COM_SocketProxyNode.cpp94
-rw-r--r--source/blender/compositor/nodes/COM_ValueNode.cpp7
-rw-r--r--source/blender/compositor/operations/COM_PreviewOperation.cpp35
-rw-r--r--source/blender/compositor/operations/COM_PreviewOperation.h5
-rw-r--r--source/blender/editors/include/ED_node.h35
-rw-r--r--source/blender/editors/include/UI_interface.h5
-rw-r--r--source/blender/editors/include/UI_resources.h1
-rw-r--r--source/blender/editors/include/UI_view2d.h5
-rw-r--r--source/blender/editors/interface/interface_draw.c66
-rw-r--r--source/blender/editors/interface/interface_handlers.c1
-rw-r--r--source/blender/editors/interface/interface_intern.h1
-rw-r--r--source/blender/editors/interface/interface_templates.c64
-rw-r--r--source/blender/editors/interface/interface_widgets.c4
-rw-r--r--source/blender/editors/interface/resources.c12
-rw-r--r--source/blender/editors/interface/view2d.c31
-rw-r--r--source/blender/editors/object/object_add.c2
-rw-r--r--source/blender/editors/render/render_preview.c16
-rw-r--r--source/blender/editors/render/render_shading.c4
-rw-r--r--source/blender/editors/render/render_update.c2
-rw-r--r--source/blender/editors/screen/screen_ops.c4
-rw-r--r--source/blender/editors/sculpt_paint/paint_image.c4
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c4
-rw-r--r--source/blender/editors/space_buttons/buttons_texture.c2
-rw-r--r--source/blender/editors/space_node/drawnode.c970
-rw-r--r--source/blender/editors/space_node/node_add.c199
-rw-r--r--source/blender/editors/space_node/node_buttons.c93
-rw-r--r--source/blender/editors/space_node/node_draw.c578
-rw-r--r--source/blender/editors/space_node/node_edit.c688
-rw-r--r--source/blender/editors/space_node/node_group.c1310
-rw-r--r--source/blender/editors/space_node/node_header.c177
-rw-r--r--source/blender/editors/space_node/node_intern.h38
-rw-r--r--source/blender/editors/space_node/node_ops.c52
-rw-r--r--source/blender/editors/space_node/node_relationships.c213
-rw-r--r--source/blender/editors/space_node/node_select.c74
-rw-r--r--source/blender/editors/space_node/node_templates.c226
-rw-r--r--source/blender/editors/space_node/node_view.c5
-rw-r--r--source/blender/editors/space_node/space_node.c242
-rw-r--r--source/blender/editors/uvedit/uvedit_ops.c2
-rw-r--r--source/blender/makesdna/DNA_node_types.h199
-rw-r--r--source/blender/makesdna/DNA_space_types.h29
-rw-r--r--source/blender/makesrna/RNA_access.h12
-rw-r--r--source/blender/makesrna/RNA_define.h2
-rw-r--r--source/blender/makesrna/RNA_enum_types.h23
-rw-r--r--source/blender/makesrna/intern/CMakeLists.txt2
-rw-r--r--source/blender/makesrna/intern/rna_access.c61
-rw-r--r--source/blender/makesrna/intern/rna_color.c2
-rw-r--r--source/blender/makesrna/intern/rna_define.c72
-rw-r--r--source/blender/makesrna/intern/rna_lamp.c8
-rw-r--r--source/blender/makesrna/intern/rna_main_api.c40
-rw-r--r--source/blender/makesrna/intern/rna_material.c10
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c4154
-rw-r--r--source/blender/makesrna/intern/rna_scene.c9
-rw-r--r--source/blender/makesrna/intern/rna_space.c168
-rw-r--r--source/blender/makesrna/intern/rna_texture.c20
-rw-r--r--source/blender/makesrna/intern/rna_ui_api.c16
-rw-r--r--source/blender/makesrna/intern/rna_userdef.c6
-rw-r--r--source/blender/makesrna/intern/rna_world.c8
-rw-r--r--source/blender/nodes/CMakeLists.txt5
-rw-r--r--source/blender/nodes/NOD_common.h54
-rw-r--r--source/blender/nodes/NOD_composite.h190
-rw-r--r--source/blender/nodes/NOD_shader.h156
-rw-r--r--source/blender/nodes/NOD_socket.h36
-rw-r--r--source/blender/nodes/NOD_static_types.h (renamed from source/blender/makesrna/intern/rna_nodetree_types.h)24
-rw-r--r--source/blender/nodes/NOD_texture.h74
-rw-r--r--source/blender/nodes/composite/node_composite_tree.c108
-rw-r--r--source/blender/nodes/composite/node_composite_util.c59
-rw-r--r--source/blender/nodes/composite/node_composite_util.h5
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_alphaOver.c8
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_bilateralblur.c8
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_blur.c8
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_bokehblur.c8
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_bokehimage.c9
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_boxmask.c8
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_brightness.c6
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_channelMatte.c8
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_chromaMatte.c8
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_colorMatte.c8
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_colorSpill.c8
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_colorbalance.c8
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_colorcorrection.c8
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_common.c26
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_composite.c6
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_crop.c8
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_curves.c24
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_defocus.c8
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_despeckle.c8
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_diffMatte.c8
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_dilate.c9
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_directionalblur.c8
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_displace.c6
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_distanceMatte.c8
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_doubleEdgeMask.c7
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_ellipsemask.c8
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_filter.c6
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_flip.c6
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_gamma.c6
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_glare.c8
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_hueSatVal.c8
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_huecorrect.c8
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_idMask.c6
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_image.c37
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_inpaint.c6
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_invert.c8
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_keying.c8
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_keyingscreen.c8
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_lensdist.c8
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_levels.c8
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_lummaMatte.c8
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_mapRange.c6
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_mapUV.c6
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_mapValue.c8
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_mask.c8
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_math.c6
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_mixrgb.c6
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_movieclip.c8
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_moviedistortion.c12
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_normal.c20
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_normalize.c6
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_outputFile.c45
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_pixelate.c6
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_premulkey.c6
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_rgb.c21
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_rotate.c8
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_scale.c6
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_sepcombHSVA.c12
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_sepcombRGBA.c12
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_sepcombYCCA.c12
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_sepcombYUVA.c13
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_setalpha.c6
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_splitViewer.c8
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_stabilize2d.c6
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_switch.c6
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_texture.c6
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_tonemap.c8
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_trackpos.c8
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_transform.c6
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_translate.c8
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_valToRgb.c14
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_value.c20
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_vecBlur.c8
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_viewer.c8
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_zcombine.c6
-rw-r--r--source/blender/nodes/intern/node_common.c514
-rw-r--r--source/blender/nodes/intern/node_common.h9
-rw-r--r--source/blender/nodes/intern/node_exec.c100
-rw-r--r--source/blender/nodes/intern/node_exec.h18
-rw-r--r--source/blender/nodes/intern/node_socket.c712
-rw-r--r--source/blender/nodes/intern/node_util.c57
-rw-r--r--source/blender/nodes/intern/node_util.h27
-rw-r--r--source/blender/nodes/shader/node_shader_tree.c211
-rw-r--r--source/blender/nodes/shader/node_shader_util.c110
-rw-r--r--source/blender/nodes/shader/node_shader_util.h39
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_add_shader.c9
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_ambient_occlusion.c9
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_attribute.c10
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_background.c8
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_brightness.c9
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.c9
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_diffuse.c9
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_glass.c9
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.c9
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_refraction.c9
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_translucent.c9
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_transparent.c9
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_velvet.c9
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bump.c9
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_camera.c12
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_common.c122
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_curves.c30
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_emission.c9
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_fresnel.c9
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_gamma.c8
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_geom.c14
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_geometry.c9
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_hair_info.c8
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_holdout.c8
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_hueSatVal.c12
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_invert.c12
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_layer_weight.c9
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_light_falloff.c9
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_light_path.c9
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_mapping.c14
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_material.c25
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_math.c13
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_mixRgb.c12
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_mix_shader.c9
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_normal.c34
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_normal_map.c11
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_object_info.c9
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_output.c14
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_output_lamp.c8
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_output_material.c9
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_output_world.c8
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_particle_info.c6
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_rgb.c36
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_script.c28
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_sepcombRGB.c24
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_squeeze.c12
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tangent.c11
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_brick.c11
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_checker.c11
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_coord.c9
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_environment.c11
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_gradient.c11
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_image.c11
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_magic.c11
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c11
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_noise.c11
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_sky.c11
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_voronoi.c11
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_wave.c11
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_texture.c17
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_valToRgb.c26
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_value.c36
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_vectMath.c12
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_volume_isotropic.c9
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_volume_transparent.c9
-rw-r--r--source/blender/nodes/texture/node_texture_tree.c206
-rw-r--r--source/blender/nodes/texture/node_texture_util.c28
-rw-r--r--source/blender/nodes/texture/node_texture_util.h10
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_at.c12
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_bricks.c14
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_checker.c12
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_common.c69
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_compose.c12
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_coord.c12
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_curves.c30
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_decompose.c18
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_distance.c12
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_hueSatVal.c12
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_image.c14
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_invert.c12
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_math.c12
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_mixRgb.c12
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_output.c22
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_proc.c16
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_rotate.c12
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_scale.c12
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_texture.c12
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_translate.c12
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_valToNor.c12
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_valToRgb.c26
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_viewer.c12
-rw-r--r--source/blender/python/intern/bpy_rna.c28
-rw-r--r--source/blender/render/intern/source/render_texture.c4
-rw-r--r--source/blenderplayer/bad_level_call_stubs/stubs.c27
293 files changed, 13263 insertions, 8911 deletions
diff --git a/doc/python_api/examples/bpy.types.NodeTree.py b/doc/python_api/examples/bpy.types.NodeTree.py
new file mode 100644
index 00000000000..401b3a01ae0
--- /dev/null
+++ b/doc/python_api/examples/bpy.types.NodeTree.py
@@ -0,0 +1,23 @@
+"""
+Poll Function
++++++++++++++++
+The :class:`NodeTree.poll` function determines if a node tree is visible
+in the given context (similar to how :class:`Panel.poll`
+and :class:`Menu.poll` define visibility). If it returns False,
+the node tree type will not be selectable in the node editor.
+
+A typical condition for shader nodes would be to check the active render engine
+of the scene and only show nodes of the renderer they are designed for.
+"""
+import bpy
+
+
+class CyclesNodeTree(bpy.types.NodeTree):
+ """ This operator is only visible when Cycles is the selected render engine"""
+ bl_label = "Cycles Node Tree"
+
+ @classmethod
+ def poll(cls, context):
+ return context.scene.render.engine == 'CYCLES'
+
+bpy.utils.register_class(CyclesNodeTree)
diff --git a/intern/cycles/blender/blender_python.cpp b/intern/cycles/blender/blender_python.cpp
index a10f3b63033..f7a05463f66 100644
--- a/intern/cycles/blender/blender_python.cpp
+++ b/intern/cycles/blender/blender_python.cpp
@@ -207,6 +207,7 @@ static PyObject *available_devices_func(PyObject *self, PyObject *args)
}
#ifdef WITH_OSL
+
static PyObject *osl_update_node_func(PyObject *self, PyObject *args)
{
PyObject *pynodegroup, *pynode;
@@ -248,17 +249,19 @@ static PyObject *osl_update_node_func(PyObject *self, PyObject *args)
continue;
/* determine socket type */
- BL::NodeSocket::type_enum socket_type;
- float default_float4[4] = {0.0f, 0.0f, 0.0f, 1.0f};
+ std::string socket_type;
+ BL::NodeSocket::type_enum data_type = BL::NodeSocket::type_VALUE;
+ float4 default_float4 = make_float4(0.0f, 0.0f, 0.0f, 1.0f);
float default_float = 0.0f;
int default_int = 0;
std::string default_string = "";
if(param->isclosure) {
- socket_type = BL::NodeSocket::type_SHADER;
+ socket_type = "NodeSocketShader";
}
else if(param->type.vecsemantics == TypeDesc::COLOR) {
- socket_type = BL::NodeSocket::type_RGBA;
+ socket_type = "NodeSocketColor";
+ data_type = BL::NodeSocket::type_RGBA;
if(param->validdefault) {
default_float4[0] = param->fdefault[0];
@@ -269,7 +272,8 @@ static PyObject *osl_update_node_func(PyObject *self, PyObject *args)
else if(param->type.vecsemantics == TypeDesc::POINT ||
param->type.vecsemantics == TypeDesc::VECTOR ||
param->type.vecsemantics == TypeDesc::NORMAL) {
- socket_type = BL::NodeSocket::type_VECTOR;
+ socket_type = "NodeSocketVector";
+ data_type = BL::NodeSocket::type_VECTOR;
if(param->validdefault) {
default_float4[0] = param->fdefault[0];
@@ -279,17 +283,20 @@ static PyObject *osl_update_node_func(PyObject *self, PyObject *args)
}
else if(param->type.aggregate == TypeDesc::SCALAR) {
if(param->type.basetype == TypeDesc::INT) {
- socket_type = BL::NodeSocket::type_INT;
+ socket_type = "NodeSocketInt";
+ data_type = BL::NodeSocket::type_INT;
if(param->validdefault)
default_int = param->idefault[0];
}
else if(param->type.basetype == TypeDesc::FLOAT) {
- socket_type = BL::NodeSocket::type_VALUE;
+ socket_type = "NodeSocketFloat";
+ data_type = BL::NodeSocket::type_VALUE;
if(param->validdefault)
default_float = param->fdefault[0];
}
else if(param->type.basetype == TypeDesc::STRING) {
- socket_type = BL::NodeSocket::type_STRING;
+ socket_type = "NodeSocketString";
+ data_type = BL::NodeSocket::type_STRING;
if(param->validdefault)
default_string = param->sdefault[0];
}
@@ -300,38 +307,52 @@ static PyObject *osl_update_node_func(PyObject *self, PyObject *args)
continue;
/* find socket socket */
- BL::NodeSocket b_sock = b_node.find_socket(param->name.c_str(), param->isoutput);
-
- /* remove if type no longer matches */
- if(b_sock && b_sock.type() != socket_type) {
- b_node.remove_socket(b_sock);
- b_sock = BL::NodeSocket(PointerRNA_NULL);
+ BL::NodeSocket b_sock(PointerRNA_NULL);
+ if (param->isoutput) {
+ b_sock = b_node.outputs[param->name];
+
+ /* remove if type no longer matches */
+ if(b_sock && b_sock.bl_idname() != socket_type) {
+ b_node.outputs.remove(b_sock);
+ b_sock = BL::NodeSocket(PointerRNA_NULL);
+ }
+
+ if (!b_sock) {
+ /* create new socket */
+ b_sock = b_node.outputs.create(socket_type.c_str(), param->name.c_str(), param->name.c_str());
+ }
+ }
+ else {
+ b_sock = b_node.inputs[param->name];
+
+ /* remove if type no longer matches */
+ if(b_sock && b_sock.bl_idname() != socket_type) {
+ b_node.inputs.remove(b_sock);
+ b_sock = BL::NodeSocket(PointerRNA_NULL);
+ }
+
+ if (!b_sock) {
+ /* create new socket */
+ b_sock = b_node.inputs.create(socket_type.c_str(), param->name.c_str(), param->name.c_str());
+ }
}
- /* create new socket */
- if(!b_sock) {
- b_sock = b_node.add_socket(param->name.c_str(), socket_type, param->isoutput);
-
- /* set default value */
- if(socket_type == BL::NodeSocket::type_VALUE) {
- BL::NodeSocketFloatNone b_float_sock(b_sock.ptr);
- b_float_sock.default_value(default_float);
+ /* set default value */
+ if(b_sock) {
+ if(data_type == BL::NodeSocket::type_VALUE) {
+ set_float(b_sock.ptr, "default_value", default_float);
}
- else if(socket_type == BL::NodeSocket::type_INT) {
- BL::NodeSocketIntNone b_int_sock(b_sock.ptr);
- b_int_sock.default_value(default_int);
+ else if(data_type == BL::NodeSocket::type_INT) {
+ set_int(b_sock.ptr, "default_value", default_int);
}
- else if(socket_type == BL::NodeSocket::type_RGBA) {
- BL::NodeSocketRGBA b_rgba_sock(b_sock.ptr);
- b_rgba_sock.default_value(default_float4);
+ else if(data_type == BL::NodeSocket::type_RGBA) {
+ set_float4(b_sock.ptr, "default_value", default_float4);
}
- else if(socket_type == BL::NodeSocket::type_VECTOR) {
- BL::NodeSocketVectorNone b_vector_sock(b_sock.ptr);
- b_vector_sock.default_value(default_float4);
+ else if(data_type == BL::NodeSocket::type_VECTOR) {
+ set_float3(b_sock.ptr, "default_value", float4_to_float3(default_float4));
}
- else if(socket_type == BL::NodeSocket::type_STRING) {
- BL::NodeSocketStringNone b_string_sock(b_sock.ptr);
- b_string_sock.default_value(default_string);
+ else if(data_type == BL::NodeSocket::type_STRING) {
+ set_string(b_sock.ptr, "default_value", default_string);
}
}
@@ -349,7 +370,7 @@ static PyObject *osl_update_node_func(PyObject *self, PyObject *args)
for (b_node.inputs.begin(b_input); b_input != b_node.inputs.end(); ++b_input) {
if(used_sockets.find(b_input->ptr.data) == used_sockets.end()) {
- b_node.remove_socket(*b_input);
+ b_node.inputs.remove(*b_input);
removed = true;
break;
}
@@ -357,7 +378,7 @@ static PyObject *osl_update_node_func(PyObject *self, PyObject *args)
for (b_node.outputs.begin(b_output); b_output != b_node.outputs.end(); ++b_output) {
if(used_sockets.find(b_output->ptr.data) == used_sockets.end()) {
- b_node.remove_socket(*b_output);
+ b_node.outputs.remove(*b_output);
removed = true;
break;
}
diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp
index 0f7dc15db19..45a97f1d530 100644
--- a/intern/cycles/blender/blender_shader.cpp
+++ b/intern/cycles/blender/blender_shader.cpp
@@ -31,9 +31,9 @@
CCL_NAMESPACE_BEGIN
-typedef map<void*, ShaderNode*> PtrNodeMap;
-typedef pair<ShaderNode*, std::string> SocketPair;
-typedef map<void*, SocketPair> PtrSockMap;
+typedef map<void*, ShaderInput*> PtrInputMap;
+typedef map<void*, ShaderOutput*> PtrOutputMap;
+typedef map<std::string, ProxyNode*> ProxyMap;
/* Find */
@@ -55,83 +55,88 @@ void BlenderSync::find_shader(BL::ID id, vector<uint>& used_shaders, int default
static BL::NodeSocket get_node_output(BL::Node b_node, const string& name)
{
BL::Node::outputs_iterator b_out;
-
+
for(b_node.outputs.begin(b_out); b_out != b_node.outputs.end(); ++b_out)
if(b_out->name() == name)
return *b_out;
-
+
assert(0);
-
+
return *b_out;
}
static float3 get_node_output_rgba(BL::Node b_node, const string& name)
{
- BL::NodeSocketRGBA sock(get_node_output(b_node, name));
- return get_float3(sock.default_value());
+ BL::NodeSocket b_sock = get_node_output(b_node, name);
+ float value[4];
+ RNA_float_get_array(&b_sock.ptr, "default_value", value);
+ return make_float3(value[0], value[1], value[2]);
}
static float get_node_output_value(BL::Node b_node, const string& name)
{
- BL::NodeSocketFloatNone sock(get_node_output(b_node, name));
- return sock.default_value();
+ BL::NodeSocket b_sock = get_node_output(b_node, name);
+ return RNA_float_get(&b_sock.ptr, "default_value");
}
-static ShaderSocketType convert_socket_type(BL::NodeSocket::type_enum b_type)
+static float3 get_node_output_vector(BL::Node b_node, const string& name)
{
- switch (b_type) {
- case BL::NodeSocket::type_VALUE:
- return SHADER_SOCKET_FLOAT;
- case BL::NodeSocket::type_INT:
- return SHADER_SOCKET_INT;
- case BL::NodeSocket::type_VECTOR:
- return SHADER_SOCKET_VECTOR;
- case BL::NodeSocket::type_RGBA:
- return SHADER_SOCKET_COLOR;
- case BL::NodeSocket::type_SHADER:
- return SHADER_SOCKET_CLOSURE;
- case BL::NodeSocket::type_STRING:
- return SHADER_SOCKET_STRING;
-
- case BL::NodeSocket::type_BOOLEAN:
- case BL::NodeSocket::type_MESH:
- default:
- return SHADER_SOCKET_FLOAT;
+ BL::NodeSocket b_sock = get_node_output(b_node, name);
+ float value[3];
+ RNA_float_get_array(&b_sock.ptr, "default_value", value);
+ return make_float3(value[0], value[1], value[2]);
+}
+
+static ShaderSocketType convert_socket_type(BL::NodeSocket b_socket)
+{
+ switch (b_socket.type()) {
+ case BL::NodeSocket::type_VALUE:
+ return SHADER_SOCKET_FLOAT;
+ case BL::NodeSocket::type_INT:
+ return SHADER_SOCKET_INT;
+ case BL::NodeSocket::type_VECTOR:
+ return SHADER_SOCKET_VECTOR;
+ case BL::NodeSocket::type_RGBA:
+ return SHADER_SOCKET_COLOR;
+ case BL::NodeSocket::type_STRING:
+ return SHADER_SOCKET_STRING;
+ case BL::NodeSocket::type_SHADER:
+ return SHADER_SOCKET_CLOSURE;
+
+ default:
+ return SHADER_SOCKET_UNDEFINED;
}
}
-static void set_default_value(ShaderInput *input, BL::NodeSocket sock, BL::BlendData b_data, BL::ID b_id)
+static void set_default_value(ShaderInput *input, BL::Node b_node, BL::NodeSocket b_sock, BL::BlendData b_data, BL::ID b_id)
{
/* copy values for non linked inputs */
switch(input->type) {
case SHADER_SOCKET_FLOAT: {
- BL::NodeSocketFloatNone value_sock(sock);
- input->set(value_sock.default_value());
+ input->set(get_float(b_sock.ptr, "default_value"));
break;
}
case SHADER_SOCKET_INT: {
- BL::NodeSocketIntNone value_sock(sock);
- input->set((float)value_sock.default_value());
+ input->set((float)get_int(b_sock.ptr, "default_value"));
break;
}
case SHADER_SOCKET_COLOR: {
- BL::NodeSocketRGBA rgba_sock(sock);
- input->set(get_float3(rgba_sock.default_value()));
+ input->set(float4_to_float3(get_float4(b_sock.ptr, "default_value")));
break;
}
case SHADER_SOCKET_NORMAL:
case SHADER_SOCKET_POINT:
case SHADER_SOCKET_VECTOR: {
- BL::NodeSocketVectorNone vec_sock(sock);
- input->set(get_float3(vec_sock.default_value()));
+ input->set(get_float3(b_sock.ptr, "default_value"));
break;
}
case SHADER_SOCKET_STRING: {
- BL::NodeSocketStringNone string_sock(sock);
- input->set((ustring)blender_absolute_path(b_data, b_id, string_sock.default_value()));
+ input->set((ustring)blender_absolute_path(b_data, b_id, get_string(b_sock.ptr, "default_value")));
break;
}
+
case SHADER_SOCKET_CLOSURE:
+ case SHADER_SOCKET_UNDEFINED:
break;
}
}
@@ -171,295 +176,226 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen
{
ShaderNode *node = NULL;
- switch(b_node.type()) {
- /* not supported */
- case BL::ShaderNode::type_GEOMETRY: break;
- case BL::ShaderNode::type_MATERIAL: break;
- case BL::ShaderNode::type_MATERIAL_EXT: break;
- case BL::ShaderNode::type_OUTPUT: break;
- case BL::ShaderNode::type_SQUEEZE: break;
- case BL::ShaderNode::type_TEXTURE: break;
- case BL::ShaderNode::type_FRAME: break;
- /* handled outside this function */
- case BL::ShaderNode::type_GROUP: break;
- /* existing blender nodes */
- case BL::ShaderNode::type_REROUTE: {
- BL::Node::inputs_iterator b_input;
- b_node.inputs.begin(b_input);
- BL::Node::outputs_iterator b_output;
- b_node.outputs.begin(b_output);
- ProxyNode *proxy = new ProxyNode(convert_socket_type(b_input->type()), convert_socket_type(b_output->type()));
- node = proxy;
- break;
- }
- case BL::ShaderNode::type_CURVE_VEC: {
- BL::ShaderNodeVectorCurve b_curve_node(b_node);
- VectorCurvesNode *curves = new VectorCurvesNode();
- curvemapping_color_to_array(b_curve_node.mapping(), curves->curves, RAMP_TABLE_SIZE, false);
- node = curves;
- break;
- }
- case BL::ShaderNode::type_CURVE_RGB: {
- BL::ShaderNodeRGBCurve b_curve_node(b_node);
- RGBCurvesNode *curves = new RGBCurvesNode();
- curvemapping_color_to_array(b_curve_node.mapping(), curves->curves, RAMP_TABLE_SIZE, true);
- node = curves;
- break;
- }
- case BL::ShaderNode::type_VALTORGB: {
- RGBRampNode *ramp = new RGBRampNode();
- BL::ShaderNodeValToRGB b_ramp_node(b_node);
- colorramp_to_array(b_ramp_node.color_ramp(), ramp->ramp, RAMP_TABLE_SIZE);
- node = ramp;
- break;
- }
- case BL::ShaderNode::type_RGB: {
- ColorNode *color = new ColorNode();
- color->value = get_node_output_rgba(b_node, "Color");
- node = color;
- break;
- }
- case BL::ShaderNode::type_VALUE: {
- ValueNode *value = new ValueNode();
- value->value = get_node_output_value(b_node, "Value");
- node = value;
- break;
- }
- case BL::ShaderNode::type_CAMERA: {
- node = new CameraNode();
- break;
- }
- case BL::ShaderNode::type_INVERT: {
- node = new InvertNode();
- break;
- }
- case BL::ShaderNode::type_GAMMA: {
- node = new GammaNode();
- break;
- }
- case BL::ShaderNode::type_BRIGHTCONTRAST: {
- node = new BrightContrastNode();
- break;
- }
- case BL::ShaderNode::type_MIX_RGB: {
- BL::ShaderNodeMixRGB b_mix_node(b_node);
- MixNode *mix = new MixNode();
- mix->type = MixNode::type_enum[b_mix_node.blend_type()];
+ /* existing blender nodes */
+ if (b_node.is_a(&RNA_ShaderNodeRGBCurve)) {
+ BL::ShaderNodeRGBCurve b_curve_node(b_node);
+ RGBCurvesNode *curves = new RGBCurvesNode();
+ curvemapping_color_to_array(b_curve_node.mapping(), curves->curves, RAMP_TABLE_SIZE, true);
+ node = curves;
+ }
+ if (b_node.is_a(&RNA_ShaderNodeVectorCurve)) {
+ BL::ShaderNodeVectorCurve b_curve_node(b_node);
+ VectorCurvesNode *curves = new VectorCurvesNode();
+ curvemapping_color_to_array(b_curve_node.mapping(), curves->curves, RAMP_TABLE_SIZE, false);
+ node = curves;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeValToRGB)) {
+ RGBRampNode *ramp = new RGBRampNode();
+ BL::ShaderNodeValToRGB b_ramp_node(b_node);
+ colorramp_to_array(b_ramp_node.color_ramp(), ramp->ramp, RAMP_TABLE_SIZE);
+ node = ramp;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeRGB)) {
+ ColorNode *color = new ColorNode();
+ color->value = get_node_output_rgba(b_node, "Color");
+ node = color;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeValue)) {
+ ValueNode *value = new ValueNode();
+ value->value = get_node_output_value(b_node, "Value");
+ node = value;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeCameraData)) {
+ node = new CameraNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeInvert)) {
+ node = new InvertNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeGamma)) {
+ node = new GammaNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeBrightContrast)) {
+ node = new BrightContrastNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeMixRGB)) {
+ BL::ShaderNodeMixRGB b_mix_node(b_node);
+ MixNode *mix = new MixNode();
+ mix->type = MixNode::type_enum[b_mix_node.blend_type()];
mix->use_clamp = b_mix_node.use_clamp();
- node = mix;
- break;
- }
- case BL::ShaderNode::type_SEPRGB: {
- node = new SeparateRGBNode();
- break;
- }
- case BL::ShaderNode::type_COMBRGB: {
- node = new CombineRGBNode();
- break;
- }
- case BL::ShaderNode::type_HUE_SAT: {
- node = new HSVNode();
- break;
- }
- case BL::ShaderNode::type_RGBTOBW: {
- node = new ConvertNode(SHADER_SOCKET_COLOR, SHADER_SOCKET_FLOAT);
- break;
- }
- case BL::ShaderNode::type_MATH: {
- BL::ShaderNodeMath b_math_node(b_node);
- MathNode *math = new MathNode();
- math->type = MathNode::type_enum[b_math_node.operation()];
+ node = mix;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeSeparateRGB)) {
+ node = new SeparateRGBNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeCombineRGB)) {
+ node = new CombineRGBNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeHueSaturation)) {
+ node = new HSVNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeRGBToBW)) {
+ node = new ConvertNode(SHADER_SOCKET_COLOR, SHADER_SOCKET_FLOAT);
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeMath)) {
+ BL::ShaderNodeMath b_math_node(b_node);
+ MathNode *math = new MathNode();
+ math->type = MathNode::type_enum[b_math_node.operation()];
math->use_clamp = b_math_node.use_clamp();
- node = math;
- break;
- }
- case BL::ShaderNode::type_VECT_MATH: {
- BL::ShaderNodeVectorMath b_vector_math_node(b_node);
- VectorMathNode *vmath = new VectorMathNode();
- vmath->type = VectorMathNode::type_enum[b_vector_math_node.operation()];
- node = vmath;
- break;
- }
- case BL::ShaderNode::type_NORMAL: {
- BL::Node::outputs_iterator out_it;
- b_node.outputs.begin(out_it);
- BL::NodeSocketVectorNone vec_sock(*out_it);
-
- NormalNode *norm = new NormalNode();
- norm->direction = get_float3(vec_sock.default_value());
-
- node = norm;
- break;
- }
- case BL::ShaderNode::type_MAPPING: {
- BL::ShaderNodeMapping b_mapping_node(b_node);
- MappingNode *mapping = new MappingNode();
-
- get_tex_mapping(&mapping->tex_mapping, b_mapping_node);
-
- node = mapping;
- break;
- }
-
- /* new nodes */
- case BL::ShaderNode::type_OUTPUT_MATERIAL:
- case BL::ShaderNode::type_OUTPUT_WORLD:
- case BL::ShaderNode::type_OUTPUT_LAMP: {
- node = graph->output();
- break;
- }
- case BL::ShaderNode::type_FRESNEL: {
- node = new FresnelNode();
- break;
- }
- case BL::ShaderNode::type_LAYER_WEIGHT: {
- node = new LayerWeightNode();
- break;
- }
- case BL::ShaderNode::type_ADD_SHADER: {
- node = new AddClosureNode();
- break;
- }
- case BL::ShaderNode::type_MIX_SHADER: {
- node = new MixClosureNode();
- break;
- }
- case BL::ShaderNode::type_ATTRIBUTE: {
- BL::ShaderNodeAttribute b_attr_node(b_node);
- AttributeNode *attr = new AttributeNode();
- attr->attribute = b_attr_node.attribute_name();
- node = attr;
- break;
- }
- case BL::ShaderNode::type_BACKGROUND: {
- node = new BackgroundNode();
- break;
- }
- case BL::ShaderNode::type_HOLDOUT: {
- node = new HoldoutNode();
- break;
- }
- case BL::ShaderNode::type_BSDF_ANISOTROPIC: {
- node = new WardBsdfNode();
- break;
- }
- case BL::ShaderNode::type_BSDF_DIFFUSE: {
- node = new DiffuseBsdfNode();
- break;
- }
- case BL::ShaderNode::type_BSDF_GLOSSY: {
- BL::ShaderNodeBsdfGlossy b_glossy_node(b_node);
- GlossyBsdfNode *glossy = new GlossyBsdfNode();
-
- switch(b_glossy_node.distribution()) {
- case BL::ShaderNodeBsdfGlossy::distribution_SHARP:
- glossy->distribution = ustring("Sharp");
- break;
- case BL::ShaderNodeBsdfGlossy::distribution_BECKMANN:
- glossy->distribution = ustring("Beckmann");
- break;
- case BL::ShaderNodeBsdfGlossy::distribution_GGX:
- glossy->distribution = ustring("GGX");
- break;
- }
- node = glossy;
- break;
- }
- case BL::ShaderNode::type_BSDF_GLASS: {
- BL::ShaderNodeBsdfGlass b_glass_node(b_node);
- GlassBsdfNode *glass = new GlassBsdfNode();
- switch(b_glass_node.distribution()) {
- case BL::ShaderNodeBsdfGlass::distribution_SHARP:
- glass->distribution = ustring("Sharp");
- break;
- case BL::ShaderNodeBsdfGlass::distribution_BECKMANN:
- glass->distribution = ustring("Beckmann");
- break;
- case BL::ShaderNodeBsdfGlass::distribution_GGX:
- glass->distribution = ustring("GGX");
- break;
- }
- node = glass;
- break;
- }
- case BL::ShaderNode::type_BSDF_REFRACTION: {
- BL::ShaderNodeBsdfRefraction b_refraction_node(b_node);
- RefractionBsdfNode *refraction = new RefractionBsdfNode();
- switch(b_refraction_node.distribution()) {
- case BL::ShaderNodeBsdfRefraction::distribution_SHARP:
- refraction->distribution = ustring("Sharp");
- break;
- case BL::ShaderNodeBsdfRefraction::distribution_BECKMANN:
- refraction->distribution = ustring("Beckmann");
- break;
- case BL::ShaderNodeBsdfRefraction::distribution_GGX:
- refraction->distribution = ustring("GGX");
- break;
- }
- node = refraction;
- break;
- }
- case BL::ShaderNode::type_BSDF_TRANSLUCENT: {
- node = new TranslucentBsdfNode();
- break;
- }
- case BL::ShaderNode::type_BSDF_TRANSPARENT: {
- node = new TransparentBsdfNode();
- break;
- }
- case BL::ShaderNode::type_BSDF_VELVET: {
- node = new VelvetBsdfNode();
- break;
- }
- case BL::ShaderNode::type_EMISSION: {
- node = new EmissionNode();
- break;
- }
- case BL::ShaderNode::type_AMBIENT_OCCLUSION: {
- node = new AmbientOcclusionNode();
- break;
- }
- case BL::ShaderNode::type_VOLUME_ISOTROPIC: {
- node = new IsotropicVolumeNode();
- break;
- }
- case BL::ShaderNode::type_VOLUME_TRANSPARENT: {
- node = new TransparentVolumeNode();
- break;
- }
- case BL::ShaderNode::type_NEW_GEOMETRY: {
- node = new GeometryNode();
+ node = math;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeVectorMath)) {
+ BL::ShaderNodeVectorMath b_vector_math_node(b_node);
+ VectorMathNode *vmath = new VectorMathNode();
+ vmath->type = VectorMathNode::type_enum[b_vector_math_node.operation()];
+ node = vmath;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeNormal)) {
+ BL::Node::outputs_iterator out_it;
+ b_node.outputs.begin(out_it);
+ BL::NodeSocket vec_sock(*out_it);
+
+ NormalNode *norm = new NormalNode();
+ norm->direction = get_node_output_vector(b_node, "Normal");
+ node = norm;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeMapping)) {
+ BL::ShaderNodeMapping b_mapping_node(b_node);
+ MappingNode *mapping = new MappingNode();
+
+ get_tex_mapping(&mapping->tex_mapping, b_mapping_node);
+
+ node = mapping;
+ }
+ /* new nodes */
+ else if (b_node.is_a(&RNA_ShaderNodeOutputMaterial)
+ || b_node.is_a(&RNA_ShaderNodeOutputWorld)
+ || b_node.is_a(&RNA_ShaderNodeOutputLamp)) {
+ node = graph->output();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeFresnel)) {
+ node = new FresnelNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeLayerWeight)) {
+ node = new LayerWeightNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeAddShader)) {
+ node = new AddClosureNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeMixShader)) {
+ node = new MixClosureNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeAttribute)) {
+ BL::ShaderNodeAttribute b_attr_node(b_node);
+ AttributeNode *attr = new AttributeNode();
+ attr->attribute = b_attr_node.attribute_name();
+ node = attr;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeBackground)) {
+ node = new BackgroundNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeHoldout)) {
+ node = new HoldoutNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeBsdfAnisotropic)) {
+ node = new WardBsdfNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeBsdfDiffuse)) {
+ node = new DiffuseBsdfNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeBsdfGlossy)) {
+ BL::ShaderNodeBsdfGlossy b_glossy_node(b_node);
+ GlossyBsdfNode *glossy = new GlossyBsdfNode();
+
+ switch(b_glossy_node.distribution()) {
+ case BL::ShaderNodeBsdfGlossy::distribution_SHARP:
+ glossy->distribution = ustring("Sharp");
break;
- }
- case BL::ShaderNode::type_LIGHT_PATH: {
- node = new LightPathNode();
+ case BL::ShaderNodeBsdfGlossy::distribution_BECKMANN:
+ glossy->distribution = ustring("Beckmann");
break;
- }
- case BL::ShaderNode::type_LIGHT_FALLOFF: {
- node = new LightFalloffNode();
+ case BL::ShaderNodeBsdfGlossy::distribution_GGX:
+ glossy->distribution = ustring("GGX");
break;
}
- case BL::ShaderNode::type_OBJECT_INFO: {
- node = new ObjectInfoNode();
+ node = glossy;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeBsdfGlass)) {
+ BL::ShaderNodeBsdfGlass b_glass_node(b_node);
+ GlassBsdfNode *glass = new GlassBsdfNode();
+ switch(b_glass_node.distribution()) {
+ case BL::ShaderNodeBsdfGlass::distribution_SHARP:
+ glass->distribution = ustring("Sharp");
break;
- }
- case BL::ShaderNode::type_PARTICLE_INFO: {
- node = new ParticleInfoNode();
+ case BL::ShaderNodeBsdfGlass::distribution_BECKMANN:
+ glass->distribution = ustring("Beckmann");
break;
- }
- case BL::ShaderNode::type_HAIR_INFO: {
- node = new HairInfoNode();
+ case BL::ShaderNodeBsdfGlass::distribution_GGX:
+ glass->distribution = ustring("GGX");
break;
}
- case BL::ShaderNode::type_BUMP: {
- node = new BumpNode();
- break;
+ node = glass;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeBsdfRefraction)) {
+ BL::ShaderNodeBsdfRefraction b_refraction_node(b_node);
+ RefractionBsdfNode *refraction = new RefractionBsdfNode();
+ switch(b_refraction_node.distribution()) {
+ case BL::ShaderNodeBsdfRefraction::distribution_SHARP:
+ refraction->distribution = ustring("Sharp");
+ break;
+ case BL::ShaderNodeBsdfRefraction::distribution_BECKMANN:
+ refraction->distribution = ustring("Beckmann");
+ break;
+ case BL::ShaderNodeBsdfRefraction::distribution_GGX:
+ refraction->distribution = ustring("GGX");
+ break;
}
- case BL::ShaderNode::type_SCRIPT: {
+ node = refraction;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeBsdfTranslucent)) {
+ node = new TranslucentBsdfNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeBsdfTransparent)) {
+ node = new TransparentBsdfNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeBsdfVelvet)) {
+ node = new VelvetBsdfNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeEmission)) {
+ node = new EmissionNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeAmbientOcclusion)) {
+ node = new AmbientOcclusionNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeVolumeIsotropic)) {
+ node = new IsotropicVolumeNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeVolumeTransparent)) {
+ node = new TransparentVolumeNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeNewGeometry)) {
+ node = new GeometryNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeLightPath)) {
+ node = new LightPathNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeLightFalloff)) {
+ node = new LightFalloffNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeObjectInfo)) {
+ node = new ObjectInfoNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeParticleInfo)) {
+ node = new ParticleInfoNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeHairInfo)) {
+ node = new HairInfoNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeBump)) {
+ node = new BumpNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeScript)) {
#ifdef WITH_OSL
- if(!scene->shader_manager->use_osl())
- break;
-
+ if(scene->shader_manager->use_osl()) {
/* create script node */
BL::ShaderNodeScript b_script_node(b_node);
OSLScriptNode *script_node = new OSLScriptNode();
@@ -472,29 +408,31 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen
* Note 2: ShaderInput/ShaderOutput store shallow string copies only!
* Socket names must be stored in the extra lists instead. */
BL::Node::inputs_iterator b_input;
-
+
for (b_script_node.inputs.begin(b_input); b_input != b_script_node.inputs.end(); ++b_input) {
script_node->input_names.push_back(ustring(b_input->name()));
- ShaderInput *input = script_node->add_input(script_node->input_names.back().c_str(), convert_socket_type(b_input->type()));
- set_default_value(input, *b_input, b_data, b_ntree);
+ ShaderInput *input = script_node->add_input(script_node->input_names.back().c_str(),
+ convert_socket_type(*b_input));
+ set_default_value(input, b_node, *b_input, b_data, b_ntree);
}
-
+
BL::Node::outputs_iterator b_output;
-
+
for (b_script_node.outputs.begin(b_output); b_output != b_script_node.outputs.end(); ++b_output) {
script_node->output_names.push_back(ustring(b_output->name()));
- script_node->add_output(script_node->output_names.back().c_str(), convert_socket_type(b_output->type()));
+ script_node->add_output(script_node->output_names.back().c_str(),
+ convert_socket_type(*b_output));
}
-
+
/* load bytecode or filepath */
OSLShaderManager *manager = (OSLShaderManager*)scene->shader_manager;
string bytecode_hash = b_script_node.bytecode_hash();
-
+
if(!bytecode_hash.empty()) {
/* loaded bytecode if not already done */
if(!manager->shader_test_loaded(bytecode_hash))
manager->shader_load_bytecode(bytecode_hash, b_script_node.bytecode());
-
+
script_node->bytecode_hash = bytecode_hash;
}
else {
@@ -503,173 +441,157 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen
}
node = script_node;
-#endif
-
- break;
}
- case BL::ShaderNode::type_TEX_IMAGE: {
- BL::ShaderNodeTexImage b_image_node(b_node);
- BL::Image b_image(b_image_node.image());
- ImageTextureNode *image = new ImageTextureNode();
- if(b_image) {
- /* builtin images will use callback-based reading because
- * they could only be loaded correct from blender side
+#endif
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeTexImage)) {
+ BL::ShaderNodeTexImage b_image_node(b_node);
+ BL::Image b_image(b_image_node.image());
+ ImageTextureNode *image = new ImageTextureNode();
+ if(b_image) {
+ /* builtin images will use callback-based reading because
+ * they could only be loaded correct from blender side
+ */
+ bool is_builtin = b_image.packed_file() ||
+ b_image.source() == BL::Image::source_GENERATED ||
+ b_image.source() == BL::Image::source_MOVIE;
+
+ if(is_builtin) {
+ /* for builtin images we're using image datablock name to find an image to
+ * read pixels from later
+ *
+ * also store frame number as well, so there's no differences in handling
+ * builtin names for packed images and movies
*/
- bool is_builtin = b_image.packed_file() ||
- b_image.source() == BL::Image::source_GENERATED ||
- b_image.source() == BL::Image::source_MOVIE;
-
- if(is_builtin) {
- /* for builtin images we're using image datablock name to find an image to
- * read pixels from later
- *
- * also store frame number as well, so there's no differences in handling
- * builtin names for packed images and movies
- */
- int scene_frame = b_scene.frame_current();
- int image_frame = image_user_frame_number(b_image_node.image_user(), scene_frame);
- image->filename = b_image.name() + "@" + string_printf("%d", image_frame);
- image->builtin_data = b_image.ptr.data;
- }
- else {
- image->filename = image_user_file_path(b_image_node.image_user(), b_image, b_scene.frame_current());
- image->builtin_data = NULL;
- }
-
- image->animated = b_image_node.image_user().use_auto_refresh();
+ int scene_frame = b_scene.frame_current();
+ int image_frame = image_user_frame_number(b_image_node.image_user(), scene_frame);
+ image->filename = b_image.name() + "@" + string_printf("%d", image_frame);
+ image->builtin_data = b_image.ptr.data;
}
- image->color_space = ImageTextureNode::color_space_enum[(int)b_image_node.color_space()];
- image->projection = ImageTextureNode::projection_enum[(int)b_image_node.projection()];
- image->projection_blend = b_image_node.projection_blend();
- get_tex_mapping(&image->tex_mapping, b_image_node.texture_mapping());
- node = image;
- break;
- }
- case BL::ShaderNode::type_TEX_ENVIRONMENT: {
- BL::ShaderNodeTexEnvironment b_env_node(b_node);
- BL::Image b_image(b_env_node.image());
- EnvironmentTextureNode *env = new EnvironmentTextureNode();
- if(b_image) {
- bool is_builtin = b_image.packed_file() ||
- b_image.source() == BL::Image::source_GENERATED ||
- b_image.source() == BL::Image::source_MOVIE;
-
- if(is_builtin) {
- int scene_frame = b_scene.frame_current();
- int image_frame = image_user_frame_number(b_env_node.image_user(), scene_frame);
- env->filename = b_image.name() + "@" + string_printf("%d", image_frame);
- env->builtin_data = b_image.ptr.data;
- }
- else {
- env->filename = image_user_file_path(b_env_node.image_user(), b_image, b_scene.frame_current());
- env->animated = b_env_node.image_user().use_auto_refresh();
- env->builtin_data = NULL;
- }
+ else {
+ image->filename = image_user_file_path(b_image_node.image_user(), b_image, b_scene.frame_current());
+ image->builtin_data = NULL;
}
- env->color_space = EnvironmentTextureNode::color_space_enum[(int)b_env_node.color_space()];
- env->projection = EnvironmentTextureNode::projection_enum[(int)b_env_node.projection()];
- get_tex_mapping(&env->tex_mapping, b_env_node.texture_mapping());
- node = env;
- break;
- }
- case BL::ShaderNode::type_TEX_GRADIENT: {
- BL::ShaderNodeTexGradient b_gradient_node(b_node);
- GradientTextureNode *gradient = new GradientTextureNode();
- gradient->type = GradientTextureNode::type_enum[(int)b_gradient_node.gradient_type()];
- get_tex_mapping(&gradient->tex_mapping, b_gradient_node.texture_mapping());
- node = gradient;
- break;
- }
- case BL::ShaderNode::type_TEX_VORONOI: {
- BL::ShaderNodeTexVoronoi b_voronoi_node(b_node);
- VoronoiTextureNode *voronoi = new VoronoiTextureNode();
- voronoi->coloring = VoronoiTextureNode::coloring_enum[(int)b_voronoi_node.coloring()];
- get_tex_mapping(&voronoi->tex_mapping, b_voronoi_node.texture_mapping());
- node = voronoi;
- break;
- }
- case BL::ShaderNode::type_TEX_MAGIC: {
- BL::ShaderNodeTexMagic b_magic_node(b_node);
- MagicTextureNode *magic = new MagicTextureNode();
- magic->depth = b_magic_node.turbulence_depth();
- get_tex_mapping(&magic->tex_mapping, b_magic_node.texture_mapping());
- node = magic;
- break;
- }
- case BL::ShaderNode::type_TEX_WAVE: {
- BL::ShaderNodeTexWave b_wave_node(b_node);
- WaveTextureNode *wave = new WaveTextureNode();
- wave->type = WaveTextureNode::type_enum[(int)b_wave_node.wave_type()];
- get_tex_mapping(&wave->tex_mapping, b_wave_node.texture_mapping());
- node = wave;
- break;
- }
- case BL::ShaderNode::type_TEX_CHECKER: {
- BL::ShaderNodeTexChecker b_checker_node(b_node);
- CheckerTextureNode *checker = new CheckerTextureNode();
- get_tex_mapping(&checker->tex_mapping, b_checker_node.texture_mapping());
- node = checker;
- break;
- }
- case BL::ShaderNode::type_TEX_BRICK: {
- BL::ShaderNodeTexBrick b_brick_node(b_node);
- BrickTextureNode *brick = new BrickTextureNode();
- brick->offset = b_brick_node.offset();
- brick->offset_frequency = b_brick_node.offset_frequency();
- brick->squash = b_brick_node.squash();
- brick->squash_frequency = b_brick_node.squash_frequency();
- get_tex_mapping(&brick->tex_mapping, b_brick_node.texture_mapping());
- node = brick;
- break;
- }
- case BL::ShaderNode::type_TEX_NOISE: {
- BL::ShaderNodeTexNoise b_noise_node(b_node);
- NoiseTextureNode *noise = new NoiseTextureNode();
- get_tex_mapping(&noise->tex_mapping, b_noise_node.texture_mapping());
- node = noise;
- break;
- }
- case BL::ShaderNode::type_TEX_MUSGRAVE: {
- BL::ShaderNodeTexMusgrave b_musgrave_node(b_node);
- MusgraveTextureNode *musgrave = new MusgraveTextureNode();
- musgrave->type = MusgraveTextureNode::type_enum[(int)b_musgrave_node.musgrave_type()];
- get_tex_mapping(&musgrave->tex_mapping, b_musgrave_node.texture_mapping());
- node = musgrave;
- break;
- }
- case BL::ShaderNode::type_TEX_COORD: {
- BL::ShaderNodeTexCoord b_tex_coord_node(b_node);
- TextureCoordinateNode *tex_coord = new TextureCoordinateNode();
- tex_coord->from_dupli = b_tex_coord_node.from_dupli();
- node = tex_coord;
- break;
- }
- case BL::ShaderNode::type_TEX_SKY: {
- BL::ShaderNodeTexSky b_sky_node(b_node);
- SkyTextureNode *sky = new SkyTextureNode();
- sky->sun_direction = get_float3(b_sky_node.sun_direction());
- sky->turbidity = b_sky_node.turbidity();
- get_tex_mapping(&sky->tex_mapping, b_sky_node.texture_mapping());
- node = sky;
- break;
- }
- case BL::ShaderNode::type_NORMAL_MAP: {
- BL::ShaderNodeNormalMap b_normal_map_node(b_node);
- NormalMapNode *nmap = new NormalMapNode();
- nmap->space = NormalMapNode::space_enum[(int)b_normal_map_node.space()];
- nmap->attribute = b_normal_map_node.uv_map();
- node = nmap;
- break;
+
+ image->animated = b_image_node.image_user().use_auto_refresh();
}
- case BL::ShaderNode::type_TANGENT: {
- BL::ShaderNodeTangent b_tangent_node(b_node);
- TangentNode *tangent = new TangentNode();
- tangent->direction_type = TangentNode::direction_type_enum[(int)b_tangent_node.direction_type()];
- tangent->axis = TangentNode::axis_enum[(int)b_tangent_node.axis()];
- tangent->attribute = b_tangent_node.uv_map();
- node = tangent;
- break;
+ image->color_space = ImageTextureNode::color_space_enum[(int)b_image_node.color_space()];
+ image->projection = ImageTextureNode::projection_enum[(int)b_image_node.projection()];
+ image->projection_blend = b_image_node.projection_blend();
+ get_tex_mapping(&image->tex_mapping, b_image_node.texture_mapping());
+ node = image;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeTexEnvironment)) {
+ BL::ShaderNodeTexEnvironment b_env_node(b_node);
+ BL::Image b_image(b_env_node.image());
+ EnvironmentTextureNode *env = new EnvironmentTextureNode();
+ if(b_image) {
+ bool is_builtin = b_image.packed_file() ||
+ b_image.source() == BL::Image::source_GENERATED ||
+ b_image.source() == BL::Image::source_MOVIE;
+
+ if(is_builtin) {
+ int scene_frame = b_scene.frame_current();
+ int image_frame = image_user_frame_number(b_env_node.image_user(), scene_frame);
+ env->filename = b_image.name() + "@" + string_printf("%d", image_frame);
+ env->builtin_data = b_image.ptr.data;
+ }
+ else {
+ env->filename = image_user_file_path(b_env_node.image_user(), b_image, b_scene.frame_current());
+ env->animated = b_env_node.image_user().use_auto_refresh();
+ env->builtin_data = NULL;
+ }
}
+ env->color_space = EnvironmentTextureNode::color_space_enum[(int)b_env_node.color_space()];
+ env->projection = EnvironmentTextureNode::projection_enum[(int)b_env_node.projection()];
+ get_tex_mapping(&env->tex_mapping, b_env_node.texture_mapping());
+ node = env;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeTexGradient)) {
+ BL::ShaderNodeTexGradient b_gradient_node(b_node);
+ GradientTextureNode *gradient = new GradientTextureNode();
+ gradient->type = GradientTextureNode::type_enum[(int)b_gradient_node.gradient_type()];
+ get_tex_mapping(&gradient->tex_mapping, b_gradient_node.texture_mapping());
+ node = gradient;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeTexVoronoi)) {
+ BL::ShaderNodeTexVoronoi b_voronoi_node(b_node);
+ VoronoiTextureNode *voronoi = new VoronoiTextureNode();
+ voronoi->coloring = VoronoiTextureNode::coloring_enum[(int)b_voronoi_node.coloring()];
+ get_tex_mapping(&voronoi->tex_mapping, b_voronoi_node.texture_mapping());
+ node = voronoi;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeTexMagic)) {
+ BL::ShaderNodeTexMagic b_magic_node(b_node);
+ MagicTextureNode *magic = new MagicTextureNode();
+ magic->depth = b_magic_node.turbulence_depth();
+ get_tex_mapping(&magic->tex_mapping, b_magic_node.texture_mapping());
+ node = magic;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeTexWave)) {
+ BL::ShaderNodeTexWave b_wave_node(b_node);
+ WaveTextureNode *wave = new WaveTextureNode();
+ wave->type = WaveTextureNode::type_enum[(int)b_wave_node.wave_type()];
+ get_tex_mapping(&wave->tex_mapping, b_wave_node.texture_mapping());
+ node = wave;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeTexChecker)) {
+ BL::ShaderNodeTexChecker b_checker_node(b_node);
+ CheckerTextureNode *checker = new CheckerTextureNode();
+ get_tex_mapping(&checker->tex_mapping, b_checker_node.texture_mapping());
+ node = checker;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeTexBrick)) {
+ BL::ShaderNodeTexBrick b_brick_node(b_node);
+ BrickTextureNode *brick = new BrickTextureNode();
+ brick->offset = b_brick_node.offset();
+ brick->offset_frequency = b_brick_node.offset_frequency();
+ brick->squash = b_brick_node.squash();
+ brick->squash_frequency = b_brick_node.squash_frequency();
+ get_tex_mapping(&brick->tex_mapping, b_brick_node.texture_mapping());
+ node = brick;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeTexNoise)) {
+ BL::ShaderNodeTexNoise b_noise_node(b_node);
+ NoiseTextureNode *noise = new NoiseTextureNode();
+ get_tex_mapping(&noise->tex_mapping, b_noise_node.texture_mapping());
+ node = noise;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeTexMusgrave)) {
+ BL::ShaderNodeTexMusgrave b_musgrave_node(b_node);
+ MusgraveTextureNode *musgrave = new MusgraveTextureNode();
+ musgrave->type = MusgraveTextureNode::type_enum[(int)b_musgrave_node.musgrave_type()];
+ get_tex_mapping(&musgrave->tex_mapping, b_musgrave_node.texture_mapping());
+ node = musgrave;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeTexCoord)) {
+ BL::ShaderNodeTexCoord b_tex_coord_node(b_node);
+ TextureCoordinateNode *tex_coord = new TextureCoordinateNode();
+ tex_coord->from_dupli = b_tex_coord_node.from_dupli();
+ node = tex_coord;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeTexSky)) {
+ BL::ShaderNodeTexSky b_sky_node(b_node);
+ SkyTextureNode *sky = new SkyTextureNode();
+ sky->sun_direction = get_float3(b_sky_node.sun_direction());
+ sky->turbidity = b_sky_node.turbidity();
+ get_tex_mapping(&sky->tex_mapping, b_sky_node.texture_mapping());
+ node = sky;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeNormalMap)) {
+ BL::ShaderNodeNormalMap b_normal_map_node(b_node);
+ NormalMapNode *nmap = new NormalMapNode();
+ nmap->space = NormalMapNode::space_enum[(int)b_normal_map_node.space()];
+ nmap->attribute = b_normal_map_node.uv_map();
+ node = nmap;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeTangent)) {
+ BL::ShaderNodeTangent b_tangent_node(b_node);
+ TangentNode *tangent = new TangentNode();
+ tangent->direction_type = TangentNode::direction_type_enum[(int)b_tangent_node.direction_type()];
+ tangent->axis = TangentNode::axis_enum[(int)b_tangent_node.axis()];
+ tangent->attribute = b_tangent_node.uv_map();
+ node = tangent;
}
if(node && node != graph->output())
@@ -678,18 +600,16 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen
return node;
}
-static SocketPair node_socket_map_pair(PtrNodeMap& node_map, BL::Node b_node, BL::NodeSocket b_socket)
+static ShaderInput *node_find_input_by_name(ShaderNode *node, BL::Node b_node, BL::NodeSocket b_socket)
{
BL::Node::inputs_iterator b_input;
- BL::Node::outputs_iterator b_output;
string name = b_socket.name();
bool found = false;
int counter = 0, total = 0;
-
- /* find in inputs */
- for(b_node.inputs.begin(b_input); b_input != b_node.inputs.end(); ++b_input) {
- if(b_input->name() == name) {
- if(!found)
+
+ for (b_node.inputs.begin(b_input); b_input != b_node.inputs.end(); ++b_input) {
+ if (b_input->name() == name) {
+ if (!found)
counter++;
total++;
}
@@ -697,128 +617,145 @@ static SocketPair node_socket_map_pair(PtrNodeMap& node_map, BL::Node b_node, BL
if(b_input->ptr.data == b_socket.ptr.data)
found = true;
}
+
+ /* rename if needed */
+ if (name == "Shader")
+ name = "Closure";
+
+ if (total > 1)
+ name = string_printf("%s%d", name.c_str(), counter);
+
+ return node->input(name.c_str());
+}
- if(!found) {
- /* find in outputs */
- found = false;
- counter = 0;
- total = 0;
-
- for(b_node.outputs.begin(b_output); b_output != b_node.outputs.end(); ++b_output) {
- if(b_output->name() == name) {
- if(!found)
- counter++;
- total++;
- }
-
- if(b_output->ptr.data == b_socket.ptr.data)
- found = true;
+static ShaderOutput *node_find_output_by_name(ShaderNode *node, BL::Node b_node, BL::NodeSocket b_socket)
+{
+ BL::Node::outputs_iterator b_output;
+ string name = b_socket.name();
+ bool found = false;
+ int counter = 0, total = 0;
+
+ for (b_node.outputs.begin(b_output); b_output != b_node.outputs.end(); ++b_output) {
+ if (b_output->name() == name) {
+ if (!found)
+ counter++;
+ total++;
}
- }
+ if(b_output->ptr.data == b_socket.ptr.data)
+ found = true;
+ }
+
/* rename if needed */
- if(name == "Shader")
+ if (name == "Shader")
name = "Closure";
-
- if(total > 1)
+
+ if (total > 1)
name = string_printf("%s%d", name.c_str(), counter);
-
- return SocketPair(node_map[b_node.ptr.data], name);
+
+ return node->output(name.c_str());
}
-static void add_nodes(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, ShaderGraph *graph, BL::ShaderNodeTree b_ntree, PtrSockMap& sockets_map)
+static void add_nodes(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, ShaderGraph *graph, BL::ShaderNodeTree b_ntree, ProxyMap &proxy_map)
{
/* add nodes */
BL::ShaderNodeTree::nodes_iterator b_node;
- PtrNodeMap node_map;
- PtrSockMap proxy_map;
+ PtrInputMap input_map;
+ PtrOutputMap output_map;
+
+ BL::Node::inputs_iterator b_input;
+ BL::Node::outputs_iterator b_output;
for(b_ntree.nodes.begin(b_node); b_node != b_ntree.nodes.end(); ++b_node) {
- if(b_node->mute()) {
- BL::Node::inputs_iterator b_input;
- BL::Node::outputs_iterator b_output;
- bool found_match = false;
-
- /* this is slightly different than blender logic, we just connect a
- * single pair for of input/output, but works ok for the node we have */
- for(b_node->inputs.begin(b_input); b_input != b_node->inputs.end(); ++b_input) {
- if(b_input->is_linked()) {
- for(b_node->outputs.begin(b_output); b_output != b_node->outputs.end(); ++b_output) {
- if(b_output->is_linked() && b_input->type() == b_output->type()) {
- ProxyNode *proxy = new ProxyNode(convert_socket_type(b_input->type()), convert_socket_type(b_output->type()));
- graph->add(proxy);
-
- proxy_map[b_input->ptr.data] = SocketPair(proxy, proxy->inputs[0]->name);
- proxy_map[b_output->ptr.data] = SocketPair(proxy, proxy->outputs[0]->name);
- found_match = true;
-
- break;
- }
- }
- }
-
- if(found_match)
- break;
+ if (b_node->mute() || b_node->is_a(&RNA_NodeReroute)) {
+ /* replace muted node with internal links */
+ BL::Node::internal_links_iterator b_link;
+ for (b_node->internal_links.begin(b_link); b_link != b_node->internal_links.end(); ++b_link) {
+ ProxyNode *proxy = new ProxyNode(convert_socket_type(b_link->to_socket()));
+
+ input_map[b_link->from_socket().ptr.data] = proxy->inputs[0];
+ output_map[b_link->to_socket().ptr.data] = proxy->outputs[0];
+
+ graph->add(proxy);
}
}
- else if(b_node->is_a(&RNA_NodeGroup)) {
- /* add proxy converter nodes for inputs and outputs */
+ else if (b_node->is_a(&RNA_ShaderNodeGroup)) {
BL::NodeGroup b_gnode(*b_node);
BL::ShaderNodeTree b_group_ntree(b_gnode.node_tree());
+ ProxyMap group_proxy_map;
+
if (!b_group_ntree)
continue;
-
- BL::Node::inputs_iterator b_input;
- BL::Node::outputs_iterator b_output;
- PtrSockMap group_sockmap;
+ add_nodes(scene, b_data, b_scene, graph, b_group_ntree, group_proxy_map);
+ /* map the outer socket to the internal proxy nodes */
for(b_node->inputs.begin(b_input); b_input != b_node->inputs.end(); ++b_input) {
- ShaderSocketType extern_type = convert_socket_type(b_input->type());
- ShaderSocketType intern_type = convert_socket_type(b_input->group_socket().type());
- ShaderNode *proxy = graph->add(new ProxyNode(extern_type, intern_type));
- /* map the external node socket to the proxy node socket */
- proxy_map[b_input->ptr.data] = SocketPair(proxy, proxy->inputs[0]->name);
- /* map the internal group socket to the proxy node socket */
- group_sockmap[b_input->group_socket().ptr.data] = SocketPair(proxy, proxy->outputs[0]->name);
+ /* get internal proxy node from group proxy map */
+ assert(group_proxy_map.find(b_input->identifier()) != group_proxy_map.end());
+ assert(group_proxy_map[b_input->identifier()]->special_type == SHADER_SPECIAL_TYPE_PROXY);
+ ProxyNode *proxy = group_proxy_map[b_input->identifier()];
+
+ input_map[b_input->ptr.data] = proxy->inputs[0];
- /* default input values of the group node */
- set_default_value(proxy->inputs[0], *b_input, b_data, b_group_ntree);
+ /* input value for proxy inputs is defined by group node */
+ set_default_value(proxy->inputs[0], *b_node, *b_input, b_data, b_ntree);
}
+ /* map the outer socket to the internal proxy nodes */
for(b_node->outputs.begin(b_output); b_output != b_node->outputs.end(); ++b_output) {
- ShaderSocketType extern_type = convert_socket_type(b_output->type());
- ShaderSocketType intern_type = convert_socket_type(b_output->group_socket().type());
- ShaderNode *proxy = graph->add(new ProxyNode(intern_type, extern_type));
- /* map the external node socket to the proxy node socket */
- proxy_map[b_output->ptr.data] = SocketPair(proxy, proxy->outputs[0]->name);
- /* map the internal group socket to the proxy node socket */
- group_sockmap[b_output->group_socket().ptr.data] = SocketPair(proxy, proxy->inputs[0]->name);
+ /* get internal proxy node from group node map */
+ assert(group_proxy_map.find(b_output->identifier()) != group_proxy_map.end());
+ assert(group_proxy_map[b_output->identifier()]->special_type == SHADER_SPECIAL_TYPE_PROXY);
+ ProxyNode *proxy = group_proxy_map[b_output->identifier()];
- /* default input values of internal, unlinked group outputs */
- set_default_value(proxy->inputs[0], b_output->group_socket(), b_data, b_group_ntree);
+ output_map[b_output->ptr.data] = proxy->outputs[0];
+ }
+ }
+ else if (b_node->is_a(&RNA_NodeGroupInput)) {
+ /* add a proxy node for each socket */
+ for(b_node->outputs.begin(b_output); b_output != b_node->outputs.end(); ++b_output) {
+ ProxyNode *proxy = new ProxyNode(convert_socket_type(*b_output));
+
+ output_map[b_output->ptr.data] = proxy->outputs[0];
+
+ /* register the proxy node for external binding */
+ proxy_map[b_output->identifier()] = proxy;
+
+ graph->add(proxy);
+ }
+ }
+ else if (b_node->is_a(&RNA_NodeGroupOutput)) {
+ /* add a proxy node for each socket */
+ for(b_node->inputs.begin(b_input); b_input != b_node->inputs.end(); ++b_input) {
+ ProxyNode *proxy = new ProxyNode(convert_socket_type(*b_input));
+
+ input_map[b_input->ptr.data] = proxy->inputs[0];
+
+ set_default_value(proxy->inputs[0], *b_node, *b_input, b_data, b_ntree);
+
+ /* register the proxy node for external binding */
+ proxy_map[b_input->identifier()] = proxy;
+
+ graph->add(proxy);
}
-
- add_nodes(scene, b_data, b_scene, graph, b_group_ntree, group_sockmap);
}
else {
ShaderNode *node = add_node(scene, b_data, b_scene, graph, b_ntree, BL::ShaderNode(*b_node));
if(node) {
- BL::Node::inputs_iterator b_input;
-
- node_map[b_node->ptr.data] = node;
-
+ /* map node sockets for linking */
for(b_node->inputs.begin(b_input); b_input != b_node->inputs.end(); ++b_input) {
- SocketPair pair = node_socket_map_pair(node_map, *b_node, *b_input);
- ShaderInput *input = pair.first->input(pair.second.c_str());
+ ShaderInput *input = node_find_input_by_name(node, *b_node, *b_input);
+ input_map[b_input->ptr.data] = input;
- assert(input);
-
- /* copy values for non linked inputs */
- set_default_value(input, *b_input, b_data, b_ntree);
+ set_default_value(input, *b_node, *b_input, b_data, b_ntree);
+ }
+ for(b_node->outputs.begin(b_output); b_output != b_node->outputs.end(); ++b_output) {
+ ShaderOutput *output = node_find_output_by_name(node, *b_node, *b_output);
+ output_map[b_output->ptr.data] = output;
}
}
}
@@ -829,44 +766,23 @@ static void add_nodes(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, Sha
for(b_ntree.links.begin(b_link); b_link != b_ntree.links.end(); ++b_link) {
/* get blender link data */
- BL::Node b_from_node = b_link->from_node();
- BL::Node b_to_node = b_link->to_node();
-
BL::NodeSocket b_from_sock = b_link->from_socket();
BL::NodeSocket b_to_sock = b_link->to_socket();
- SocketPair from_pair, to_pair;
-
- /* links without a node pointer are connections to group inputs/outputs */
-
- /* from sock */
- if(b_from_node) {
- if (b_from_node.mute() || b_from_node.is_a(&RNA_NodeGroup))
- from_pair = proxy_map[b_from_sock.ptr.data];
- else
- from_pair = node_socket_map_pair(node_map, b_from_node, b_from_sock);
- }
- else
- from_pair = sockets_map[b_from_sock.ptr.data];
-
- /* to sock */
- if(b_to_node) {
- if (b_to_node.mute() || b_to_node.is_a(&RNA_NodeGroup))
- to_pair = proxy_map[b_to_sock.ptr.data];
- else
- to_pair = node_socket_map_pair(node_map, b_to_node, b_to_sock);
- }
- else
- to_pair = sockets_map[b_to_sock.ptr.data];
+ ShaderOutput *output = 0;
+ ShaderInput *input = 0;
+
+ PtrOutputMap::iterator output_it = output_map.find(b_from_sock.ptr.data);
+ if (output_it != output_map.end())
+ output = output_it->second;
+ PtrInputMap::iterator input_it = input_map.find(b_to_sock.ptr.data);
+ if (input_it != input_map.end())
+ input = input_it->second;
/* either node may be NULL when the node was not exported, typically
* because the node type is not supported */
- if(from_pair.first && to_pair.first) {
- ShaderOutput *output = from_pair.first->output(from_pair.second.c_str());
- ShaderInput *input = to_pair.first->input(to_pair.second.c_str());
-
+ if(output && input)
graph->connect(output, input);
- }
}
}
@@ -891,10 +807,10 @@ void BlenderSync::sync_materials(bool update_all)
/* create nodes */
if(b_mat->use_nodes() && b_mat->node_tree()) {
- PtrSockMap sock_to_node;
+ ProxyMap proxy_map;
BL::ShaderNodeTree b_ntree(b_mat->node_tree());
- add_nodes(scene, b_data, b_scene, graph, b_ntree, sock_to_node);
+ add_nodes(scene, b_data, b_scene, graph, b_ntree, proxy_map);
}
else {
ShaderNode *closure, *out;
@@ -932,10 +848,10 @@ void BlenderSync::sync_world(bool update_all)
/* create nodes */
if(b_world && b_world.use_nodes() && b_world.node_tree()) {
- PtrSockMap sock_to_node;
+ ProxyMap proxy_map;
BL::ShaderNodeTree b_ntree(b_world.node_tree());
- add_nodes(scene, b_data, b_scene, graph, b_ntree, sock_to_node);
+ add_nodes(scene, b_data, b_scene, graph, b_ntree, proxy_map);
}
else if(b_world) {
ShaderNode *closure, *out;
@@ -991,10 +907,10 @@ void BlenderSync::sync_lamps(bool update_all)
if(b_lamp->use_nodes() && b_lamp->node_tree()) {
shader->name = b_lamp->name().c_str();
- PtrSockMap sock_to_node;
+ ProxyMap proxy_map;
BL::ShaderNodeTree b_ntree(b_lamp->node_tree());
- add_nodes(scene, b_data, b_scene, graph, b_ntree, sock_to_node);
+ add_nodes(scene, b_data, b_scene, graph, b_ntree, proxy_map);
}
else {
ShaderNode *closure, *out;
diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h
index 976ed875211..bd4852d08e1 100644
--- a/intern/cycles/blender/blender_util.h
+++ b/intern/cycles/blender/blender_util.h
@@ -202,30 +202,60 @@ static inline uint get_layer(BL::Array<int, 20> array, BL::Array<int, 8> local_a
return layer;
}
-#if 0
static inline float3 get_float3(PointerRNA& ptr, const char *name)
{
float3 f;
RNA_float_get_array(&ptr, name, &f.x);
return f;
}
-#endif
+
+static inline void set_float3(PointerRNA& ptr, const char *name, float3 value)
+{
+ RNA_float_set_array(&ptr, name, &value.x);
+}
+
+static inline float4 get_float4(PointerRNA& ptr, const char *name)
+{
+ float4 f;
+ RNA_float_get_array(&ptr, name, &f.x);
+ return f;
+}
+
+static inline void set_float4(PointerRNA& ptr, const char *name, float4 value)
+{
+ RNA_float_set_array(&ptr, name, &value.x);
+}
static inline bool get_boolean(PointerRNA& ptr, const char *name)
{
return RNA_boolean_get(&ptr, name)? true: false;
}
+static inline void set_boolean(PointerRNA& ptr, const char *name, bool value)
+{
+ RNA_boolean_set(&ptr, name, (int)value);
+}
+
static inline float get_float(PointerRNA& ptr, const char *name)
{
return RNA_float_get(&ptr, name);
}
+static inline void set_float(PointerRNA& ptr, const char *name, float value)
+{
+ RNA_float_set(&ptr, name, value);
+}
+
static inline int get_int(PointerRNA& ptr, const char *name)
{
return RNA_int_get(&ptr, name);
}
+static inline void set_int(PointerRNA& ptr, const char *name, int value)
+{
+ RNA_int_set(&ptr, name, value);
+}
+
static inline int get_enum(PointerRNA& ptr, const char *name)
{
return RNA_enum_get(&ptr, name);
@@ -242,6 +272,32 @@ static inline string get_enum_identifier(PointerRNA& ptr, const char *name)
return string(identifier);
}
+static inline void set_enum(PointerRNA& ptr, const char *name, int value)
+{
+ RNA_enum_set(&ptr, name, value);
+}
+
+static inline void set_enum(PointerRNA& ptr, const char *name, const string &identifier)
+{
+ RNA_enum_set_identifier(&ptr, name, identifier.c_str());
+}
+
+static inline string get_string(PointerRNA& ptr, const char *name)
+{
+ char cstrbuf[1024];
+ char *cstr = RNA_string_get_alloc(&ptr, name, cstrbuf, sizeof(cstrbuf));
+ string str(cstr);
+ if (cstr != cstrbuf)
+ MEM_freeN(cstr);
+
+ return str;
+}
+
+static inline void set_string(PointerRNA& ptr, const char *name, const string &value)
+{
+ RNA_string_set(&ptr, name, value.c_str());
+}
+
/* Relative Paths */
static inline string blender_absolute_path(BL::BlendData b_data, BL::ID b_id, const string& path)
diff --git a/intern/cycles/render/graph.h b/intern/cycles/render/graph.h
index 61b5bd83534..c6b9ae08508 100644
--- a/intern/cycles/render/graph.h
+++ b/intern/cycles/render/graph.h
@@ -43,6 +43,8 @@ class OSLCompiler;
* Data type for inputs and outputs */
enum ShaderSocketType {
+ SHADER_SOCKET_UNDEFINED,
+
SHADER_SOCKET_FLOAT,
SHADER_SOCKET_INT,
SHADER_SOCKET_COLOR,
diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp
index 8ac12242e15..398b9f0a758 100644
--- a/intern/cycles/render/nodes.cpp
+++ b/intern/cycles/render/nodes.cpp
@@ -1242,15 +1242,14 @@ void ConvertNode::compile(OSLCompiler& compiler)
/* Proxy */
-ProxyNode::ProxyNode(ShaderSocketType from_, ShaderSocketType to_)
+ProxyNode::ProxyNode(ShaderSocketType type_)
: ShaderNode("proxy")
{
- from = from_;
- to = to_;
+ type = type_;
special_type = SHADER_SPECIAL_TYPE_PROXY;
- add_input("Input", from);
- add_output("Output", to);
+ add_input("Input", type);
+ add_output("Output", type);
}
void ProxyNode::compile(SVMCompiler& compiler)
diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h
index 3609497e5ce..1efe4ae076d 100644
--- a/intern/cycles/render/nodes.h
+++ b/intern/cycles/render/nodes.h
@@ -190,10 +190,10 @@ public:
class ProxyNode : public ShaderNode {
public:
- ProxyNode(ShaderSocketType from, ShaderSocketType to);
+ ProxyNode(ShaderSocketType type);
SHADER_NODE_BASE_CLASS(ProxyNode)
- ShaderSocketType from, to;
+ ShaderSocketType type;
};
class BsdfNode : public ShaderNode {
diff --git a/release/scripts/modules/bpy_types.py b/release/scripts/modules/bpy_types.py
index 4398b1721f7..f42fd8e3107 100644
--- a/release/scripts/modules/bpy_types.py
+++ b/release/scripts/modules/bpy_types.py
@@ -485,17 +485,6 @@ class Text(bpy_types.ID):
)
-class NodeSocket(StructRNA): # , metaclass=RNAMeta
- __slots__ = ()
-
- @property
- def links(self):
- """List of node links from or to this socket"""
- return tuple(link for link in self.id_data.links
- if (link.from_socket == self or
- link.to_socket == self))
-
-
# values are module: [(cls, path, line), ...]
TypeMap = {}
@@ -757,3 +746,147 @@ class Region(StructRNA):
return None
+
+class NodeTree(bpy_types.ID, metaclass=RNAMetaPropGroup):
+ __slots__ = ()
+
+
+class NodeSocketTemplate():
+ type = 'UNDEFINED'
+
+ # Default implementation:
+ # Create a single property using the socket template's 'value_property' attribute
+ # value_property should be created in the __init__ function
+ #
+ # If necessary this function can be overloaded in subclasses, e.g. to create multiple value properties
+ def define_node_properties(self, node_type, prefix):
+ if hasattr(self, "value_property"):
+ setattr(node_type, prefix+"value", self.value_property)
+
+ def init_socket(self, socket):
+ socket.type = self.type
+ if hasattr(self, "value_property"):
+ socket.value_property = self.value_property[1]['attr']
+
+
+def gen_valid_identifier(seq):
+ # get an iterator
+ itr = iter(seq)
+ # pull characters until we get a legal one for first in identifer
+ for ch in itr:
+ if ch == '_' or ch.isalpha():
+ yield ch
+ break
+ # pull remaining characters and yield legal ones for identifier
+ for ch in itr:
+ if ch == '_' or ch.isalpha() or ch.isdigit():
+ yield ch
+
+def sanitize_identifier(name):
+ return ''.join(gen_valid_identifier(name))
+
+def unique_identifier(name, identifier_list):
+ # First some basic sanitation, to make a usable identifier string from the name
+ base = sanitize_identifier(name)
+ # Now make a unique identifier by appending an unused index
+ identifier = base
+ index = 0
+ while identifier in identifier_list:
+ index += 1
+ identifier = base + str(index)
+ return identifier
+
+class RNAMetaNode(RNAMetaPropGroup):
+ def __new__(cls, name, bases, classdict, **args):
+ # Wrapper for node.init, to add sockets from templates
+
+ def create_sockets(self):
+ inputs = getattr(self, 'input_templates', None)
+ if inputs:
+ for temp in inputs:
+ socket = self.inputs.new(type=temp.bl_socket_idname, name=temp.name, identifier=temp.identifier)
+ temp.init_socket(socket)
+ outputs = getattr(self, 'output_templates', None)
+ if outputs:
+ for temp in outputs:
+ socket = self.outputs.new(type=temp.bl_socket_idname, name=temp.name, identifier=temp.identifier)
+ temp.init_socket(socket)
+
+ init_base = classdict.get('init', None)
+ if init_base:
+ def init_node(self, context):
+ create_sockets(self)
+ init_base(self, context)
+ else:
+ def init_node(self, context):
+ create_sockets(self)
+
+ classdict['init'] = init_node
+
+ # Create the regular class
+ result = RNAMetaPropGroup.__new__(cls, name, bases, classdict)
+
+ # Add properties from socket templates
+ inputs = classdict.get('input_templates', None)
+ if inputs:
+ for i, temp in enumerate(inputs):
+ temp.identifier = unique_identifier(temp.name, [t.identifier for t in inputs[0:i]])
+ temp.define_node_properties(result, "input_"+temp.identifier+"_")
+ outputs = classdict.get('output_templates', None)
+ if outputs:
+ for i, temp in enumerate(outputs):
+ temp.identifier = unique_identifier(temp.name, [t.identifier for t in outputs[0:i]])
+ temp.define_node_properties(result, "output_"+temp.identifier+"_")
+
+ return result
+
+
+class Node(StructRNA, metaclass=RNAMetaNode):
+ __slots__ = ()
+
+ @classmethod
+ def poll(cls, ntree):
+ return True
+
+
+class NodeSocket(StructRNA, metaclass=RNAMetaPropGroup):
+ __slots__ = ()
+
+ @property
+ def links(self):
+ """List of node links from or to this socket"""
+ return tuple(link for link in self.id_data.links
+ if (link.from_socket == self or
+ link.to_socket == self))
+
+
+class NodeSocketInterface(StructRNA, metaclass=RNAMetaPropGroup):
+ __slots__ = ()
+
+
+# These are intermediate subclasses, need a bpy type too
+class CompositorNode(Node):
+ __slots__ = ()
+
+ @classmethod
+ def poll(cls, ntree):
+ return ntree.bl_idname == 'CompositorNodeTree'
+
+ def update(self):
+ self.tag_need_exec()
+
+class ShaderNode(Node):
+ __slots__ = ()
+
+ @classmethod
+ def poll(cls, ntree):
+ return ntree.bl_idname == 'ShaderNodeTree'
+
+
+class TextureNode(Node):
+ __slots__ = ()
+
+ @classmethod
+ def poll(cls, ntree):
+ return ntree.bl_idname == 'TextureNodeTree'
+
diff --git a/release/scripts/startup/bl_operators/node.py b/release/scripts/startup/bl_operators/node.py
index bc0224db765..9839e0ee092 100644
--- a/release/scripts/startup/bl_operators/node.py
+++ b/release/scripts/startup/bl_operators/node.py
@@ -100,75 +100,55 @@ class NODE_OT_add_node(NodeAddOperator, Operator):
return result
-# XXX These node item lists should actually be generated by a callback at
-# operator execution time (see node_type_items below),
-# using the active node tree from the context.
-# Due to a difficult bug in bpy this is not possible
-# (item list memory gets freed too early),
-# so for now just copy the static item lists to these global variables.
-#
-# In the custom_nodes branch, the static per-tree-type node items are replaced
-# by a single independent type list anyway (with a poll function to limit node
-# types to the respective trees). So this workaround is only temporary.
-
-# lazy init
-node_type_items_dict = {}
-
-# Prefixes used to distinguish base node types and node groups
-node_type_prefix = 'NODE_'
-node_group_prefix = 'GROUP_'
-
-
-# Generate a list of enum items for a given node class
-# Copy existing type enum, adding a prefix to distinguish from node groups
-# Skip the base node group type,
-# node groups will be added below for all existing group trees
-def node_type_items(node_class):
- return [(node_type_prefix + item.identifier, item.name, item.description)
- for item in node_class.bl_rna.properties['type'].enum_items
- if item.identifier != 'GROUP']
-
-
-# Generate items for node group types
-# Filter by the given tree_type
-# Node group trees don't have a description property yet
-# (could add this as a custom property though)
-def node_group_items(tree_type):
- return [(node_group_prefix + group.name, group.name, '')
- for group in bpy.data.node_groups if group.type == tree_type]
+def node_classes_iter(base=bpy.types.Node):
+ """
+ Yields all true node classes by checking for the is_registered_node_type classmethod.
+ Node types can use specialized subtypes of bpy.types.Node, which are not usable
+ nodes themselves (e.g. CompositorNode).
+ """
+ if base.is_registered_node_type():
+ yield base
+ for subclass in base.__subclasses__():
+ for node_class in node_classes_iter(subclass):
+ yield node_class
+
+
+def node_class_items_iter(node_class, context):
+ identifier = node_class.bl_rna.identifier
+ # XXX Checking for explicit group node types is stupid.
+ # This should be replaced by a generic system of generating
+ # node items via callback.
+ # Group node_tree pointer should also use a poll function to filter the library list,
+ # but cannot do that without a node instance here. A node callback could just use the internal poll function.
+ if identifier in {'ShaderNodeGroup', 'CompositorNodeGroup', 'TextureNodeGroup'}:
+ tree_idname = context.space_data.edit_tree.bl_idname
+ for group in bpy.data.node_groups:
+ if group.bl_idname == tree_idname:
+ yield (group.name, "", {"node_tree":group}) # XXX empty string should be replaced by description from tree
+ else:
+ yield (node_class.bl_rna.name, node_class.bl_rna.description, {})
-# Returns the enum item list for the edited tree in the context
-def node_type_items_cb(self, context):
+def node_items_iter(context):
snode = context.space_data
if not snode:
- return ()
+ return
tree = snode.edit_tree
if not tree:
- return ()
-
- # Lists of basic node types for each
- if not node_type_items_dict:
- node_type_items_dict.update({
- 'SHADER': node_type_items(bpy.types.ShaderNode),
- 'COMPOSITING': node_type_items(bpy.types.CompositorNode),
- 'TEXTURE': node_type_items(bpy.types.TextureNode),
- })
-
- # XXX Does not work correctly, see comment above
- '''
- return [(item.identifier, item.name, item.description, item.value)
- for item in
- tree.nodes.bl_rna.functions['new'].parameters['type'].enum_items]
- '''
-
- if tree.type in node_type_items_dict:
- return node_type_items_dict[tree.type] + node_group_items(tree.type)
- else:
- return ()
+ return
+
+ for node_class in node_classes_iter():
+ if node_class.poll(tree):
+ for item in node_class_items_iter(node_class, context):
+ yield (node_class,) + item
+
+
+# Create an enum list from node class items
+def node_type_items_cb(self, context):
+ return [(str(index), item[1], item[2]) for index, item in enumerate(node_items_iter(context))]
-class NODE_OT_add_search(Operator):
+class NODE_OT_add_search(NodeAddOperator, Operator):
'''Add a node to the active tree'''
bl_idname = "node.add_search"
bl_label = "Search and Add Node"
@@ -182,55 +162,48 @@ class NODE_OT_add_search(Operator):
items=node_type_items_cb,
)
- _node_type_items_dict = None
+ def execute(self, context):
+ for index, item in enumerate(node_items_iter(context)):
+ if str(index) == self.type:
+ node = self.create_node(context, item[0].bl_rna.identifier)
+ for prop,value in item[3].items():
+ setattr(node, prop, value)
+ break
+ return {'FINISHED'}
- def create_node(self, context):
- space = context.space_data
- tree = space.edit_tree
+ def invoke(self, context, event):
+ self.store_mouse_cursor(context, event)
+ # Delayed execution in the search popup
+ context.window_manager.invoke_search_popup(self)
+ return {'CANCELLED'}
- # Enum item identifier has an additional prefix to
- # distinguish base node types from node groups
- item = self.type
- if item.startswith(node_type_prefix):
- # item means base node type
- node = tree.nodes.new(type=item[len(node_type_prefix):])
- elif item.startswith(node_group_prefix):
- # item means node group type
- node = tree.nodes.new(
- type='GROUP',
- group=bpy.data.node_groups[item[len(node_group_prefix):]])
- else:
- return None
- for n in tree.nodes:
- if n == node:
- node.select = True
- tree.nodes.active = node
- else:
- node.select = False
- node.location = space.cursor_location
- return node
+# Simple basic operator for adding a node without further initialization
+class NODE_OT_add_node(NodeAddOperator, bpy.types.Operator):
+ '''Add a node to the active tree'''
+ bl_idname = "node.add_node"
+ bl_label = "Add Node"
- @classmethod
- def poll(cls, context):
- space = context.space_data
- # needs active node editor and a tree to add nodes to
- return (space.type == 'NODE_EDITOR' and space.edit_tree)
+ type = StringProperty(name="Node Type", description="Node type")
def execute(self, context):
- self.create_node(context)
+ node = self.create_node(context, self.type)
return {'FINISHED'}
- def invoke(self, context, event):
- space = context.space_data
- v2d = context.region.view2d
- # convert mouse position to the View2D for later node placement
- space.cursor_location = v2d.region_to_view(event.mouse_region_x,
- event.mouse_region_y)
+class NODE_OT_add_group_node(NodeAddOperator, bpy.types.Operator):
+ '''Add a group node to the active tree'''
+ bl_idname = "node.add_group_node"
+ bl_label = "Add Group Node"
- context.window_manager.invoke_search_popup(self)
- return {'CANCELLED'}
+ type = StringProperty(name="Node Type", description="Node type")
+ grouptree = StringProperty(name="Group tree", description="Group node tree name")
+
+ def execute(self, context):
+ node = self.create_node(context, self.type)
+ node.node_tree = bpy.data.node_groups[self.grouptree]
+
+ return {'FINISHED'}
class NODE_OT_collapse_hide_unused_toggle(Operator):
@@ -261,3 +234,24 @@ class NODE_OT_collapse_hide_unused_toggle(Operator):
socket.hide = hide
return {'FINISHED'}
+
+
+class NODE_OT_tree_path_parent(Operator):
+ '''Go to parent node tree'''
+ bl_idname = "node.tree_path_parent"
+ bl_label = "Parent Node Tree"
+ bl_options = {'REGISTER', 'UNDO'}
+
+ @classmethod
+ def poll(cls, context):
+ space = context.space_data
+ # needs active node editor and a tree
+ return (space.type == 'NODE_EDITOR' and len(space.path) > 1)
+
+ def execute(self, context):
+ space = context.space_data
+
+ space.path.pop()
+
+ return {'FINISHED'}
+
diff --git a/release/scripts/startup/bl_ui/space_node.py b/release/scripts/startup/bl_ui/space_node.py
index 1865b049a03..e739c5ea5d4 100644
--- a/release/scripts/startup/bl_ui/space_node.py
+++ b/release/scripts/startup/bl_ui/space_node.py
@@ -44,8 +44,8 @@ class NODE_HT_header(Header):
row.menu("NODE_MT_node")
layout.prop(snode, "tree_type", text="", expand=True)
-
- if snode.tree_type == 'SHADER':
+
+ if snode.tree_type == 'ShaderNodeTree':
if scene.render.use_shading_nodes:
layout.prop(snode, "shader_type", text="", expand=True)
@@ -65,7 +65,7 @@ class NODE_HT_header(Header):
if snode_id:
layout.prop(snode_id, "use_nodes")
- elif snode.tree_type == 'TEXTURE':
+ elif snode.tree_type == 'TextureNodeTree':
layout.prop(snode, "texture_type", text="", expand=True)
if id_from:
@@ -76,7 +76,7 @@ class NODE_HT_header(Header):
if snode_id:
layout.prop(snode_id, "use_nodes")
- elif snode.tree_type == 'COMPOSITING':
+ elif snode.tree_type == 'CompositorNodeTree':
layout.prop(snode_id, "use_nodes")
layout.prop(snode_id.render, "use_free_unused_nodes", text="Free Unused")
layout.prop(snode, "show_backdrop")
@@ -84,6 +84,13 @@ class NODE_HT_header(Header):
row = layout.row(align=True)
row.prop(snode, "backdrop_channels", text="", expand=True)
layout.prop(snode, "use_auto_render")
+
+ else:
+ # Custom node tree is edited as independent ID block
+ layout.template_ID(snode, "node_tree", new="node.new_node_tree")
+
+ layout.prop(snode, "pin", text="")
+ layout.operator("node.tree_path_parent", text="", icon='FILE_PARENT')
layout.separator()
@@ -182,6 +189,7 @@ class NODE_MT_node(Menu):
layout.operator("node.group_edit")
layout.operator("node.group_ungroup")
layout.operator("node.group_make")
+ layout.operator("node.group_insert")
layout.separator()
@@ -208,7 +216,7 @@ class NODE_PT_properties(Panel):
@classmethod
def poll(cls, context):
snode = context.space_data
- return snode.tree_type == 'COMPOSITING'
+ return snode.tree_type == 'CompositorNodeTree'
def draw_header(self, context):
snode = context.space_data
@@ -237,7 +245,7 @@ class NODE_PT_quality(bpy.types.Panel):
@classmethod
def poll(cls, context):
snode = context.space_data
- return snode.tree_type == 'COMPOSITING' and snode.node_tree is not None
+ return snode.tree_type == 'CompositorNodeTree' and snode.node_tree is not None
def draw(self, context):
layout = self.layout
@@ -276,5 +284,28 @@ class NODE_MT_node_color_specials(Menu):
layout.operator("node.node_copy_color", icon='COPY_ID')
+class NODE_UL_interface_sockets(bpy.types.UIList):
+ def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
+ socket = item
+ color = socket.draw_color(context)
+
+ if self.layout_type in {'DEFAULT', 'COMPACT'}:
+ row = layout.row(align=True)
+
+ # inputs get icon on the left
+ if socket.in_out == 'IN':
+ row.template_node_socket(color)
+
+ row.label(text=socket.name, icon_value=icon)
+
+ # outputs get icon on the right
+ if socket.in_out == 'OUT':
+ row.template_node_socket(color)
+
+ elif self.layout_type in {'GRID'}:
+ layout.alignment = 'CENTER'
+ layout.template_node_socket(color)
+
+
if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
diff --git a/release/scripts/templates_py/custom_nodes.py b/release/scripts/templates_py/custom_nodes.py
new file mode 100644
index 00000000000..485ee0ebe05
--- /dev/null
+++ b/release/scripts/templates_py/custom_nodes.py
@@ -0,0 +1,159 @@
+import bpy
+# XXX these don't work yet ...
+#from bpy_types import NodeTree, Node, NodeSocket
+
+# Implementation of custom nodes from Python
+
+
+# Shortcut for node type menu
+def add_nodetype(layout, type):
+ layout.operator("node.add_node", text=type.bl_label).type = type.bl_rna.identifier
+
+# Derived from the NodeTree base type, similar to Menu, Operator, Panel, etc.
+class MyCustomTree(bpy.types.NodeTree):
+ # Description string
+ '''A custom node tree type that will show up in the node editor header'''
+ # Optional identifier string. If not explicitly defined, the python class name is used.
+ bl_idname = 'CustomTreeType'
+ # Label for nice name display
+ bl_label = 'Custom Node Tree'
+ # Icon identifier
+ # NOTE: If no icon is defined, the node tree will not show up in the editor header!
+ # This can be used to make additional tree types for groups and similar nodes (see below)
+ # Only one base tree class is needed in the editor for selecting the general category
+ bl_icon = 'NODETREE'
+
+ def draw_add_menu(self, context, layout):
+ layout.label("Hello World!")
+ add_nodetype(layout, bpy.types.CustomNodeType)
+ add_nodetype(layout, bpy.types.MyCustomGroup)
+
+
+# Custom socket type
+class MyCustomSocket(bpy.types.NodeSocket):
+ # Description string
+ '''Custom node socket type'''
+ # Optional identifier string. If not explicitly defined, the python class name is used.
+ bl_idname = 'CustomSocketType'
+ # Label for nice name display
+ bl_label = 'Custom Node Socket'
+ # Socket color
+ bl_color = (1.0, 0.4, 0.216, 0.5)
+
+ # Enum items list
+ my_items = [
+ ("DOWN", "Down", "Where your feet are"),
+ ("UP", "Up", "Where your head should be"),
+ ("LEFT", "Left", "Not right"),
+ ("RIGHT", "Right", "Not left")
+ ]
+
+ myEnumProperty = bpy.props.EnumProperty(name="Direction", description="Just an example", items=my_items, default='UP')
+
+ # Optional function for drawing the socket input value
+ def draw(self, context, layout, node):
+ layout.prop(self, "myEnumProperty", text=self.name)
+
+
+# Base class for all custom nodes in this tree type.
+# Defines a poll function to enable instantiation.
+class MyCustomTreeNode :
+ @classmethod
+ def poll(cls, ntree):
+ return ntree.bl_idname == 'CustomTreeType'
+
+# Derived from the Node base type.
+class MyCustomNode(bpy.types.Node, MyCustomTreeNode):
+ # === Basics ===
+ # Description string
+ '''A custom node'''
+ # Optional identifier string. If not explicitly defined, the python class name is used.
+ bl_idname = 'CustomNodeType'
+ # Label for nice name display
+ bl_label = 'Custom Node'
+ # Icon identifier
+ bl_icon = 'SOUND'
+
+ # === Custom Properties ===
+ # These work just like custom properties in ID data blocks
+ # Extensive information can be found under
+ # http://wiki.blender.org/index.php/Doc:2.6/Manual/Extensions/Python/Properties
+ myStringProperty = bpy.props.StringProperty()
+ myFloatProperty = bpy.props.FloatProperty(default=3.1415926)
+
+ # === Optional Functions ===
+ # Initialization function, called when a new node is created.
+ # This is the most common place to create the sockets for a node, as shown below.
+ # NOTE: this is not the same as the standard __init__ function in Python, which is
+ # a purely internal Python method and unknown to the node system!
+ def init(self, context):
+ self.inputs.new('CustomSocketType', "Hello")
+ self.inputs.new('NodeSocketFloat', "World")
+ self.inputs.new('NodeSocketVector', "!")
+
+ self.outputs.new('NodeSocketColor', "How")
+ self.outputs.new('NodeSocketColor', "are")
+ self.outputs.new('NodeSocketFloat', "you")
+
+ # Copy function to initialize a copied node from an existing one.
+ def copy(self, node):
+ print("Copying from node ", node)
+
+ # Free function to clean up on removal.
+ def free(self):
+ print("Removing node ", self, ", Goodbye!")
+
+ # Additional buttons displayed on the node.
+ def draw_buttons(self, context, layout):
+ layout.label("Node settings")
+ layout.prop(self, "myFloatProperty")
+
+ # Detail buttons in the sidebar.
+ # If this function is not defined, the draw_buttons function is used instead
+ def draw_buttons_ext(self, context, layout):
+ layout.prop(self, "myFloatProperty")
+ # myStringProperty button will only be visible in the sidebar
+ layout.prop(self, "myStringProperty")
+
+
+# A customized group-like node.
+class MyCustomGroup(bpy.types.NodeGroup, MyCustomTreeNode):
+ # === Basics ===
+ # Description string
+ '''A custom group node'''
+ # Label for nice name display
+ bl_label = 'Custom Group Node'
+ bl_group_tree_idname = 'CustomTreeType'
+
+ orks = bpy.props.IntProperty(default=3)
+ dwarfs = bpy.props.IntProperty(default=12)
+ wizards = bpy.props.IntProperty(default=1)
+
+ # Additional buttons displayed on the node.
+ def draw_buttons(self, context, layout):
+ col = layout.column(align=True)
+ col.prop(self, "orks")
+ col.prop(self, "dwarfs")
+ col.prop(self, "wizards")
+
+ layout.label("The Node Tree:")
+ layout.prop(self, "node_tree", text="")
+
+
+def register():
+ bpy.utils.register_class(MyCustomTree)
+ bpy.utils.register_class(MyCustomSocket)
+ bpy.utils.register_class(MyCustomNode)
+ bpy.utils.register_class(MyCustomGroup)
+
+
+def unregister():
+ bpy.utils.unregister_class(MyCustomTree)
+ bpy.utils.unregister_class(MyCustomSocket)
+ bpy.utils.unregister_class(MyCustomNode)
+ bpy.utils.unregister_class(MyCustomGroup)
+
+
+if __name__ == "__main__":
+ register()
+
diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h
index a53fc15714e..d03c631f7a1 100644
--- a/source/blender/blenkernel/BKE_blender.h
+++ b/source/blender/blenkernel/BKE_blender.h
@@ -42,7 +42,7 @@ extern "C" {
* and keep comment above the defines.
* Use STRINGIFY() rather than defining with quotes */
#define BLENDER_VERSION 266
-#define BLENDER_SUBVERSION 1
+#define BLENDER_SUBVERSION 2
/* 262 was the last editmesh release but it has compatibility code for bmesh data */
#define BLENDER_MINVERSION 262
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index 80955729326..513851ce18f 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -32,8 +32,21 @@
* \ingroup bke
*/
+#include "BLI_ghash.h"
+#include "BLI_utildefines.h"
+
#include "DNA_listBase.h"
+/* for FOREACH_NODETREE */
+#include "DNA_lamp_types.h"
+#include "DNA_material_types.h"
+#include "DNA_node_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_world_types.h"
+
+#include "RNA_types.h"
+
/* not very important, but the stack solver likes to know a maximum */
#define MAX_SOCKET 64
@@ -43,7 +56,10 @@ struct bNodeLink;
struct bNodeSocket;
struct bNodeStack;
struct bNodeTree;
+struct bNodeTreeType;
struct bNodeTreeExec;
+struct bNodeExecContext;
+struct bNodeExecData;
struct GPUMaterial;
struct GPUNode;
struct GPUNodeStack;
@@ -65,6 +81,7 @@ struct ARegion;
struct Object;
struct ColorManagedViewSettings;
struct ColorManagedDisplaySettings;
+struct bNodeInstanceHash;
/* ************** NODE TYPE DEFINITIONS ***** */
@@ -72,9 +89,9 @@ struct ColorManagedDisplaySettings;
* Can be used to quickly define a list of static sockets for a node,
* which are added to each new node of that type.
*
- * \deprecated New nodes should add default sockets in the initialization
- * function instead. This struct is mostly kept for old nodes and should
- * be removed some time.
+ * \deprecated This struct is used by C nodes to define templates as simple
+ * static struct lists. These are converted to the new template collections
+ * in RNA types automatically.
*/
typedef struct bNodeSocketTemplate {
int type, limit;
@@ -86,38 +103,38 @@ typedef struct bNodeSocketTemplate {
/* after this line is used internal only */
struct bNodeSocket *sock; /* used to hold verified socket */
+ char identifier[64]; /* generated from name */
} bNodeSocketTemplate;
-typedef void (*NodeSocketButtonFunction)(const struct bContext *C, struct uiBlock *block,
- struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *sock,
- const char *name, int x, int y, int width);
-
/** Defines a socket type.
* Defines the appearance and behavior of a socket in the UI.
*/
typedef struct bNodeSocketType {
- int type;
- char ui_name[64]; /* MAX_NAME */
- char ui_description[128];
- int ui_icon;
- char ui_color[4];
+ char idname[64]; /* identifier name */
+
+ void (*draw)(struct bContext *C, struct uiLayout *layout, struct PointerRNA *ptr, struct PointerRNA *node_ptr);
+ void (*draw_color)(struct bContext *C, struct PointerRNA *ptr, struct PointerRNA *node_ptr, float *r_color);
+
+ void (*interface_draw)(struct bContext *C, struct uiLayout *layout, struct PointerRNA *ptr);
+ void (*interface_draw_color)(struct bContext *C, struct PointerRNA *ptr, float *r_color);
+ void (*interface_register_properties)(struct bNodeTree *ntree, struct bNodeSocket *stemp, struct StructRNA *data_srna);
+ void (*interface_init_socket)(struct bNodeTree *ntree, struct bNodeSocket *stemp, struct bNode *node, struct bNodeSocket *sock, const char *data_path);
+ void (*interface_from_socket)(struct bNodeTree *ntree, struct bNodeSocket *stemp, struct bNode *node, struct bNodeSocket *sock);
- const char *value_structname;
- int value_structsize;
+ /* RNA integration */
+ ExtensionRNA ext_socket;
+ ExtensionRNA ext_interface;
- NodeSocketButtonFunction buttonfunc;
+ /* for standard socket types in C */
+ int type, subtype;
} bNodeSocketType;
-/** Template for creating a node.
- * Stored required parameters to make a new node of a specific type.
- */
-typedef struct bNodeTemplate {
- int type;
-
- struct Main *main;
- struct Scene *scene;
- struct bNodeTree *ngroup; /* group tree */
-} bNodeTemplate;
+typedef void (*NodeSocketDrawFunction)(struct bContext *C, struct uiLayout *layout, struct PointerRNA *ptr, struct PointerRNA *node_ptr, int linked);
+
+typedef void *(*NodeInitExecFunction)(struct bNodeExecContext *context, struct bNode *node, bNodeInstanceKey key);
+typedef void (*NodeFreeExecFunction)(struct bNode *node, void *nodedata);
+typedef void (*NodeExecFunction)(void *data, int thread, struct bNode *, struct bNodeExecData *execdata, struct bNodeStack **in, struct bNodeStack **out);
+typedef int (*NodeGPUExecFunction)(struct GPUMaterial *mat, struct bNode *node, struct bNodeExecData *execdata, struct GPUNodeStack *in, struct GPUNodeStack *out);
/** Defines a node type.
* Initial attributes and constants for a node as well as callback functions
@@ -127,8 +144,13 @@ typedef struct bNodeType {
void *next, *prev;
short needs_free; /* set for allocated types that need to be freed */
+ char idname[64]; /* identifier name */
int type;
- char name[64]; /* MAX_NAME */
+
+ char ui_name[64]; /* MAX_NAME */
+ char ui_description[256];
+ int ui_icon;
+
float width, minwidth, maxwidth;
float height, minheight, maxheight;
short nclass, flag, compatibility;
@@ -139,7 +161,8 @@ typedef struct bNodeType {
char storagename[64]; /* struct name for DNA */
/// Main draw function for the node.
- void (*drawfunc)(const struct bContext *C, struct ARegion *ar, struct SpaceNode *snode, struct bNodeTree *ntree, struct bNode *node);
+ void (*drawfunc)(const struct bContext *C, struct ARegion *ar, struct SpaceNode *snode,
+ struct bNodeTree *ntree, struct bNode *node, bNodeInstanceKey key);
/// Updates the node geometry attributes according to internal state before actual drawing.
void (*drawupdatefunc)(const struct bContext *C, struct bNodeTree *ntree, struct bNode *node);
/// Draw the option buttons on the node.
@@ -150,8 +173,11 @@ typedef struct bNodeType {
void (*uibackdropfunc)(struct SpaceNode *snode, struct ImBuf *backdrop, struct bNode *node, int x, int y);
/// Draw a node socket. Default draws the input value button.
- NodeSocketButtonFunction drawinputfunc;
- NodeSocketButtonFunction drawoutputfunc;
+ /* XXX deprecated, only used for the OutputFile node,
+ * should be removed at some point.
+ */
+ NodeSocketDrawFunction drawinputfunc;
+ NodeSocketDrawFunction drawoutputfunc;
/// Optional custom label function for the node header.
const char *(*labelfunc)(struct bNode *);
@@ -168,45 +194,42 @@ typedef struct bNodeType {
void (*verifyfunc)(struct bNodeTree *ntree, struct bNode *node, struct ID *id);
/// Initialize a new node instance of this type after creation.
- void (*initfunc)(struct bNodeTree *ntree, struct bNode *node, struct bNodeTemplate *ntemp);
- /// Free the custom storage data.
- void (*freestoragefunc)(struct bNode *node);
- /// Make a copy of the custom storage data.
- void (*copystoragefunc)(struct bNode *node, struct bNode *target);
+ void (*initfunc)(struct bNodeTree *ntree, struct bNode *node);
+ /// Free the node instance.
+ void (*freefunc)(struct bNode *node);
+ /// Make a copy of the node instance.
+ void (*copyfunc)(struct bNodeTree *dest_ntree, struct bNode *dest_node, struct bNode *src_node);
- /// Create a template from an existing node.
- struct bNodeTemplate (*templatefunc)(struct bNode *);
- /** If a node can be made from the template in the given node tree.
- * \note Node groups can not be created inside their own node tree.
- */
- int (*validfunc)(struct bNodeTree *ntree, struct bNodeTemplate *ntemp);
+ /* Registerable API callback versions, called in addition to C callbacks */
+ void (*initfunc_api)(const struct bContext *C, struct PointerRNA *ptr);
+ void (*freefunc_api)(struct PointerRNA *ptr);
+ void (*copyfunc_api)(struct PointerRNA *ptr, struct bNode *src_node);
- /// Initialize a node tree associated to this node type.
- void (*inittreefunc)(struct bNodeTree *ntree);
- /// Update a node tree associated to this node type.
- void (*updatetreefunc)(struct bNodeTree *ntree);
-
- /* group edit callbacks for operators */
- /* XXX this is going to be changed as required by the UI */
- struct bNodeTree *(*group_edit_get)(struct bNode *node);
- struct bNodeTree *(*group_edit_set)(struct bNode *node, int edit);
- void (*group_edit_clear)(struct bNode *node);
+ /* can this node type be added to a node tree */
+ int (*poll)(struct bNodeType *ntype, struct bNodeTree *nodetree);
+ /* can this node be added to a node tree */
+ int (*poll_instance)(struct bNode *node, struct bNodeTree *nodetree);
/* Update the internal links list, for muting and disconnect operators. */
void (*update_internal_links)(struct bNodeTree *, struct bNode *node);
/* **** execution callbacks **** */
- void *(*initexecfunc)(struct bNode *node);
- void (*freeexecfunc)(struct bNode *node, void *nodedata);
- void (*execfunc)(void *data, struct bNode *, struct bNodeStack **, struct bNodeStack **);
- /* XXX this alternative exec function has been added to avoid changing all node types.
- * when a final generic version of execution code is defined, this will be changed anyway
- */
- void (*newexecfunc)(void *data, int thread, struct bNode *, void *nodedata, struct bNodeStack **, struct bNodeStack **);
+ NodeInitExecFunction initexecfunc;
+ NodeFreeExecFunction freeexecfunc;
+ NodeExecFunction execfunc;
/* gpu */
- int (*gpufunc)(struct GPUMaterial *mat, struct bNode *node, struct GPUNodeStack *in, struct GPUNodeStack *out);
- /* extended gpu function */
- int (*gpuextfunc)(struct GPUMaterial *mat, struct bNode *node, void *nodedata, struct GPUNodeStack *in, struct GPUNodeStack *out);
+ NodeGPUExecFunction gpufunc;
+
+ /* Group type static info
+ *
+ * XXX This data is needed by group operators. If these operators could be implemented completely in Python,
+ * the static data could instead be stored in Python classes and would need no special treatment.
+ * Due to the way group operators move nodes between data blocks this is currently not possible.
+ */
+ char group_tree_idname[64]; /* tree type associated to the group node type */
+
+ /* RNA integration */
+ ExtensionRNA ext;
} bNodeType;
/* node->exec, now in use for composites (#define for break is same as ready yes) */
@@ -245,6 +268,7 @@ typedef struct bNodeType {
#define NODE_CLASS_TRANSFORM 30
#define NODE_CLASS_COMBINE 31
#define NODE_CLASS_SCRIPT 32
+#define NODE_CLASS_INTERFACE 33
#define NODE_CLASS_SHADER 40
#define NODE_CLASS_LAYOUT 100
@@ -258,10 +282,6 @@ typedef struct bNodeType {
#define NODE_RESIZE_RIGHT 4
#define NODE_RESIZE_LEFT 8
-/* enum values for input/output */
-#define SOCK_IN 1
-#define SOCK_OUT 2
-
typedef enum eNodeSizePreset {
NODE_SIZE_DEFAULT,
NODE_SIZE_SMALL,
@@ -270,19 +290,26 @@ typedef enum eNodeSizePreset {
struct bNodeTreeExec;
-typedef void (*bNodeTreeCallback)(void *calldata, struct ID *owner_id, struct bNodeTree *ntree);
typedef void (*bNodeClassCallback)(void *calldata, int nclass, const char *name);
typedef struct bNodeTreeType {
int type; /* type identifier */
- char idname[64]; /* id name for RNA identification */
-
- ListBase node_types; /* type definitions */
+ char idname[64]; /* identifier name */
+
+ char ui_name[64];
+ char ui_description[256];
+ int ui_icon;
/* callbacks */
void (*free_cache)(struct bNodeTree *ntree);
void (*free_node_cache)(struct bNodeTree *ntree, struct bNode *node);
- void (*foreach_nodetree)(struct Main *main, void *calldata, bNodeTreeCallback func); /* iteration over all node trees */
void (*foreach_nodeclass)(struct Scene *scene, void *calldata, bNodeClassCallback func); /* iteration over all node classes */
+ /* Add menu for this node tree. */
+ void (*draw_add_menu)(const struct bContext *C, struct uiLayout *layout, struct bNodeTree *ntree);
+ /* Check visibility in the node editor */
+ int (*poll)(const struct bContext *C, struct bNodeTreeType *ntreetype);
+ /* Select a node tree from the context */
+ void (*get_from_context)(const struct bContext *C, struct bNodeTreeType *ntreetype,
+ struct bNodeTree **r_ntree, struct ID **r_id, struct ID **r_from);
/* calls allowing threaded composite */
void (*localize)(struct bNodeTree *localtree, struct bNodeTree *ntree);
@@ -291,23 +318,37 @@ typedef struct bNodeTreeType {
/* Tree update. Overrides nodetype->updatetreefunc! */
void (*update)(struct bNodeTree *ntree);
- /* Node update. Overrides nodetype->updatefunc! */
- void (*update_node)(struct bNodeTree *ntree, struct bNode *node);
int (*validate_link)(struct bNodeTree *ntree, struct bNodeLink *link);
-
- /* Default internal linking. */
- void (*update_internal_links)(struct bNodeTree *, struct bNode *node);
+
+ /* RNA integration */
+ ExtensionRNA ext;
} bNodeTreeType;
+
/* ************** GENERIC API, TREES *************** */
-struct bNodeTreeType *ntreeGetType(int type);
-struct bNodeType *ntreeGetNodeType(struct bNodeTree *ntree);
-struct bNodeSocketType *ntreeGetSocketType(int type);
+struct bNodeTreeType *ntreeTypeFind(const char *idname);
+void ntreeTypeAdd(struct bNodeTreeType* nt);
+void ntreeTypeFreeLink(struct bNodeTreeType* nt);
+struct GHashIterator *ntreeTypeGetIterator(void);
+
+/* helper macros for iterating over tree types */
+#define NODE_TREE_TYPES_BEGIN(ntype) \
+{ \
+ GHashIterator *__node_tree_type_iter__ = ntreeTypeGetIterator(); \
+ for (; BLI_ghashIterator_notDone(__node_tree_type_iter__); BLI_ghashIterator_step(__node_tree_type_iter__)) { \
+ bNodeTreeType *ntype = BLI_ghashIterator_getValue(__node_tree_type_iter__);
-struct bNodeTree *ntreeAddTree(struct Main *bmain, const char *name, int type, int nodetype);
-void ntreeInitTypes(struct bNodeTree *ntree);
+#define NODE_TREE_TYPES_END \
+ } \
+ BLI_ghashIterator_free(__node_tree_type_iter__); \
+}
+
+void ntreeSetTypes(const struct bContext *C, struct bNodeTree *ntree);
+int ntreeIsValid(struct bNodeTree *ntree);
+
+struct bNodeTree *ntreeAddTree(struct Main *bmain, const char *name, const char *idname);
/* copy/free funcs, need to manage ID users */
void ntreeFreeTree_ex(struct bNodeTree *ntree, const short do_id_user);
@@ -337,8 +378,6 @@ void ntreeGetDependencyList(struct bNodeTree *ntree, struct bNode *
* new tree types have a per-output socket flag to indicate the final output to use explicitly.
*/
void ntreeSetOutput(struct bNodeTree *ntree);
-void ntreeInitPreview(struct bNodeTree *, int xsize, int ysize);
-void ntreeClearPreview(struct bNodeTree *ntree);
void ntreeFreeCache(struct bNodeTree *ntree);
@@ -348,29 +387,86 @@ struct bNodeTree *ntreeLocalize(struct bNodeTree *ntree);
void ntreeLocalSync(struct bNodeTree *localtree, struct bNodeTree *ntree);
void ntreeLocalMerge(struct bNodeTree *localtree, struct bNodeTree *ntree);
+/* ************** NODE TREE INTERFACE *************** */
+
+struct bNodeSocket *ntreeFindSocketInterface(struct bNodeTree *ntree, int in_out, const char *identifier);
+struct bNodeSocket *ntreeAddSocketInterface(struct bNodeTree *ntree, int in_out, const char *idname, const char *name);
+struct bNodeSocket *ntreeInsertSocketInterface(struct bNodeTree *ntree, int in_out, const char *idname,
+ struct bNodeSocket *next_sock, const char *name);
+struct bNodeSocket *ntreeAddSocketInterfaceFromSocket(struct bNodeTree *ntree, struct bNode *from_node, struct bNodeSocket *from_sock);
+struct bNodeSocket *ntreeInsertSocketInterfaceFromSocket(struct bNodeTree *ntree, struct bNodeSocket *next_sock,
+ struct bNode *from_node, struct bNodeSocket *from_sock);
+void ntreeRemoveSocketInterface(struct bNodeTree *ntree, struct bNodeSocket *sock);
+
+struct StructRNA *ntreeInterfaceTypeGet(struct bNodeTree *ntree, int create);
+void ntreeInterfaceTypeFree(struct bNodeTree *ntree);
+void ntreeInterfaceTypeUpdate(struct bNodeTree *ntree);
+
/* ************** GENERIC API, NODES *************** */
-struct bNodeSocket *nodeAddSocket(struct bNodeTree *ntree, struct bNode *node, int in_out, const char *name, int type);
-struct bNodeSocket *nodeInsertSocket(struct bNodeTree *ntree, struct bNode *node, int in_out, struct bNodeSocket *next_sock, const char *name, int type);
+struct bNodeType *nodeTypeFind(const char *idname);
+void nodeRegisterType(struct bNodeType* ntype);
+void nodeUnregisterType(struct bNodeType* ntype);
+struct GHashIterator *nodeTypeGetIterator(void);
+
+/* helper macros for iterating over node types */
+#define NODE_TYPES_BEGIN(ntype) \
+{ \
+ GHashIterator *__node_type_iter__ = nodeTypeGetIterator(); \
+ for (; BLI_ghashIterator_notDone(__node_type_iter__); BLI_ghashIterator_step(__node_type_iter__)) { \
+ bNodeType *ntype = BLI_ghashIterator_getValue(__node_type_iter__);
+
+#define NODE_TYPES_END \
+ } \
+ BLI_ghashIterator_free(__node_type_iter__); \
+}
+
+struct bNodeSocketType *nodeSocketTypeFind(const char *idname);
+void nodeRegisterSocketType(struct bNodeSocketType* stype);
+void nodeUnregisterSocketType(struct bNodeSocketType* stype);
+struct GHashIterator *nodeSocketTypeGetIterator(void);
+const char * nodeStaticSocketType(int type, int subtype);
+const char * nodeStaticSocketInterfaceType(int type, int subtype);
+
+/* helper macros for iterating over node types */
+#define NODE_SOCKET_TYPES_BEGIN(stype) \
+{ \
+ GHashIterator *__node_socket_type_iter__ = nodeSocketTypeGetIterator(); \
+ for (; BLI_ghashIterator_notDone(__node_socket_type_iter__); BLI_ghashIterator_step(__node_socket_type_iter__)) { \
+ bNodeSocketType *stype = BLI_ghashIterator_getValue(__node_socket_type_iter__);
+
+#define NODE_SOCKET_TYPES_END \
+ } \
+ BLI_ghashIterator_free(__node_socket_type_iter__); \
+}
+
+void nodeMakeDynamicType(struct bNode *node);
+int nodeDynamicUnlinkText(struct ID *txtid);
+
+struct bNodeSocket *nodeFindSocket(struct bNode *node, int in_out, const char *identifier);
+struct bNodeSocket *nodeAddSocket(struct bNodeTree *ntree, struct bNode *node, int in_out, const char *idname,
+ const char *identifier, const char *name);
+struct bNodeSocket *nodeInsertSocket(struct bNodeTree *ntree, struct bNode *node, int in_out, const char *idname,
+ struct bNodeSocket *next_sock, const char *identifier, const char *name);
+struct bNodeSocket *nodeAddStaticSocket(struct bNodeTree *ntree, struct bNode *node, int in_out, int type, int subtype,
+ const char *identifier, const char *name);
+struct bNodeSocket *nodeInsertStaticSocket(struct bNodeTree *ntree, struct bNode *node, int in_out, int type, int subtype,
+ struct bNodeSocket *next_sock, const char *identifier, const char *name);
void nodeRemoveSocket(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *sock);
void nodeRemoveAllSockets(struct bNodeTree *ntree, struct bNode *node);
-void nodeAddToPreview(struct bNode *node, const float col[4], int x, int y, int do_manage);
-
-struct bNode *nodeAddNode(struct bNodeTree *ntree, struct bNodeTemplate *ntemp);
+struct bNode *nodeAddNode(const struct bContext *C, struct bNodeTree *ntree, const char *idname);
+struct bNode *nodeAddStaticNode(const struct bContext *C, struct bNodeTree *ntree, int type);
void nodeUnlinkNode(struct bNodeTree *ntree, struct bNode *node);
void nodeUniqueName(struct bNodeTree *ntree, struct bNode *node);
-void nodeRegisterType(struct bNodeTreeType *ttype, struct bNodeType *ntype);
-void nodeMakeDynamicType(struct bNode *node);
-int nodeDynamicUnlinkText(struct ID *txtid);
-
void nodeFreeNode(struct bNodeTree *ntree, struct bNode *node);
struct bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node);
struct bNodeLink *nodeAddLink(struct bNodeTree *ntree, struct bNode *fromnode, struct bNodeSocket *fromsock, struct bNode *tonode, struct bNodeSocket *tosock);
void nodeRemLink(struct bNodeTree *ntree, struct bNodeLink *link);
void nodeRemSocketLinks(struct bNodeTree *ntree, struct bNodeSocket *sock);
+int nodeLinkIsHidden(struct bNodeLink *link);
void nodeInternalRelink(struct bNodeTree *ntree, struct bNode *node);
void nodeToView(struct bNode *node, float x, float y, float *rx, float *ry);
@@ -380,11 +476,12 @@ void nodeAttachNode(struct bNode *node, struct bNode *parent);
void nodeDetachNode(struct bNode *node);
struct bNode *nodeFindNodebyName(struct bNodeTree *ntree, const char *name);
-int nodeFindNode(struct bNodeTree *ntree, struct bNodeSocket *sock, struct bNode **nodep, int *sockindex, int *in_out);
+int nodeFindNode(struct bNodeTree *ntree, struct bNodeSocket *sock, struct bNode **nodep, int *sockindex);
struct bNodeLink *nodeFindLink(struct bNodeTree *ntree, struct bNodeSocket *from, struct bNodeSocket *to);
int nodeCountSocketLinks(struct bNodeTree *ntree, struct bNodeSocket *sock);
+void nodeSetSelected(struct bNode *node, int select);
void nodeSetActive(struct bNodeTree *ntree, struct bNode *node);
struct bNode *nodeGetActive(struct bNodeTree *ntree);
struct bNode *nodeGetActiveID(struct bNodeTree *ntree, short idtype);
@@ -396,11 +493,9 @@ struct bNode *nodeGetActiveTexture(struct bNodeTree *ntree);
void nodeUpdate(struct bNodeTree *ntree, struct bNode *node);
int nodeUpdateID(struct bNodeTree *ntree, struct ID *id);
void nodeUpdateInternalLinks(struct bNodeTree *ntree, struct bNode *node);
-
-void nodeFreePreview(struct bNode *node);
+void nodeSynchronizeID(struct bNode *node, bool copy_to_id);
int nodeSocketIsHidden(struct bNodeSocket *sock);
-void nodeSocketSetType(struct bNodeSocket *sock, int type);
/* Node Clipboard */
void BKE_node_clipboard_init(struct bNodeTree *ntree);
@@ -412,78 +507,189 @@ const struct ListBase *BKE_node_clipboard_get_nodes(void);
const struct ListBase *BKE_node_clipboard_get_links(void);
int BKE_node_clipboard_get_type(void);
+/* Node Instance Hash */
+typedef struct bNodeInstanceHash
+{
+ GHash *ghash; /* XXX should be made a direct member, GHash allocation needs to support it */
+} bNodeInstanceHash;
+
+typedef void (*bNodeInstanceValueFP)(void *value);
+
+extern const bNodeInstanceKey NODE_INSTANCE_KEY_BASE;
+
+bNodeInstanceKey BKE_node_instance_key(bNodeInstanceKey parent_key, struct bNodeTree *ntree, struct bNode *node);
+
+bNodeInstanceHash * BKE_node_instance_hash_new(const char *info);
+void BKE_node_instance_hash_free(bNodeInstanceHash *hash, bNodeInstanceValueFP valfreefp);
+void BKE_node_instance_hash_insert(bNodeInstanceHash *hash, bNodeInstanceKey key, void *value);
+void* BKE_node_instance_hash_lookup(bNodeInstanceHash *hash, bNodeInstanceKey key);
+int BKE_node_instance_hash_remove(bNodeInstanceHash *hash, bNodeInstanceKey key, bNodeInstanceValueFP valfreefp);
+void BKE_node_instance_hash_clear(bNodeInstanceHash *hash, bNodeInstanceValueFP valfreefp);
+void* BKE_node_instance_hash_pop(bNodeInstanceHash *hash, bNodeInstanceKey key);
+int BKE_node_instance_hash_haskey(bNodeInstanceHash *hash, bNodeInstanceKey key);
+int BKE_node_instance_hash_size(bNodeInstanceHash *hash);
+
+void BKE_node_instance_hash_clear_tags(bNodeInstanceHash *hash);
+void BKE_node_instance_hash_tag(bNodeInstanceHash *hash, void *value);
+int BKE_node_instance_hash_tag_key(bNodeInstanceHash *hash, bNodeInstanceKey key);
+void BKE_node_instance_hash_remove_untagged(bNodeInstanceHash *hash, bNodeInstanceValueFP valfreefp);
+
+typedef GHashIterator bNodeInstanceHashIterator;
+
+BLI_INLINE bNodeInstanceHashIterator *BKE_node_instance_hash_iterator_new(bNodeInstanceHash *hash) { return BLI_ghashIterator_new(hash->ghash); }
+BLI_INLINE void BKE_node_instance_hash_iterator_init(bNodeInstanceHashIterator *iter, bNodeInstanceHash *hash) { BLI_ghashIterator_init(iter, hash->ghash); }
+BLI_INLINE void BKE_node_instance_hash_iterator_free(bNodeInstanceHashIterator *iter) { BLI_ghashIterator_free(iter); }
+BLI_INLINE bNodeInstanceKey BKE_node_instance_hash_iterator_get_key(bNodeInstanceHashIterator *iter) { return *(bNodeInstanceKey *)BLI_ghashIterator_getKey(iter); }
+BLI_INLINE void* BKE_node_instance_hash_iterator_get_value(bNodeInstanceHashIterator *iter) { return BLI_ghashIterator_getValue(iter); }
+BLI_INLINE void BKE_node_instance_hash_iterator_step(bNodeInstanceHashIterator *iter) { BLI_ghashIterator_step(iter); }
+BLI_INLINE bool BKE_node_instance_hash_iterator_not_done(bNodeInstanceHashIterator *iter) { return BLI_ghashIterator_notDone(iter); }
+
+#define NODE_INSTANCE_HASH_ITER(iter_, hash_) \
+ for (BKE_node_instance_hash_iterator_init(&iter_, hash_); \
+ BKE_node_instance_hash_iterator_not_done(&iter_); \
+ BKE_node_instance_hash_iterator_step(&iter_))
+
+
+/* Node Previews */
+
+int BKE_node_preview_used(struct bNode *node);
+bNodePreview* BKE_node_preview_verify(struct bNodeInstanceHash *previews, bNodeInstanceKey key, int xsize, int ysize, int create);
+bNodePreview* BKE_node_preview_copy(struct bNodePreview *preview);
+void BKE_node_preview_free(struct bNodePreview *preview);
+void BKE_node_preview_init_tree(struct bNodeTree *ntree, int xsize, int ysize, int create_previews);
+void BKE_node_preview_free_tree(struct bNodeTree *ntree);
+void BKE_node_preview_remove_unused(struct bNodeTree *ntree);
+void BKE_node_preview_clear(struct bNodePreview *preview);
+void BKE_node_preview_clear_tree(struct bNodeTree *ntree);
+
+void BKE_node_preview_sync_tree(struct bNodeTree *to_ntree, struct bNodeTree *from_ntree);
+void BKE_node_preview_merge_tree(struct bNodeTree *to_ntree, struct bNodeTree *from_ntree);
+
+void BKE_node_preview_set_pixel(struct bNodePreview *preview, const float col[4], int x, int y, int do_manage);
+
+
/* ************** NODE TYPE ACCESS *************** */
-struct bNodeTemplate nodeMakeTemplate(struct bNode *node);
-int nodeValid(struct bNodeTree *ntree, struct bNodeTemplate *ntemp);
const char *nodeLabel(struct bNode *node);
struct bNodeTree *nodeGroupEditGet(struct bNode *node);
struct bNodeTree *nodeGroupEditSet(struct bNode *node, int edit);
void nodeGroupEditClear(struct bNode *node);
+int nodeGroupPoll(struct bNodeTree *nodetree, struct bNodeTree *grouptree);
+
/* Init a new node type struct with default values and callbacks */
-void node_type_base(struct bNodeTreeType *ttype, struct bNodeType *ntype, int type,
- const char *name, short nclass, short flag);
+void node_type_base(struct bNodeType *ntype, int type, const char *name, short nclass, short flag);
+void node_type_base_custom(struct bNodeType *ntype, const char *idname, const char *name, short nclass, short flag);
void node_type_socket_templates(struct bNodeType *ntype, struct bNodeSocketTemplate *inputs, struct bNodeSocketTemplate *outputs);
void node_type_size(struct bNodeType *ntype, int width, int minwidth, int maxwidth);
void node_type_size_preset(struct bNodeType *ntype, eNodeSizePreset size);
-void node_type_init(struct bNodeType *ntype, void (*initfunc)(struct bNodeTree *ntree, struct bNode *node, struct bNodeTemplate *ntemp));
-void node_type_valid(struct bNodeType *ntype, int (*validfunc)(struct bNodeTree *ntree, struct bNodeTemplate *ntemp));
+void node_type_init(struct bNodeType *ntype, void (*initfunc)(struct bNodeTree *ntree, struct bNode *node));
void node_type_storage(struct bNodeType *ntype,
const char *storagename,
- void (*freestoragefunc)(struct bNode *),
- void (*copystoragefunc)(struct bNode *, struct bNode *));
+ void (*freefunc)(struct bNode *node),
+ void (*copyfunc)(struct bNodeTree *dest_ntree, struct bNode *dest_node, struct bNode *src_node));
void node_type_label(struct bNodeType *ntype, const char *(*labelfunc)(struct bNode *));
-void node_type_template(struct bNodeType *ntype, struct bNodeTemplate (*templatefunc)(struct bNode *));
void node_type_update(struct bNodeType *ntype,
void (*updatefunc)(struct bNodeTree *ntree, struct bNode *node),
void (*verifyfunc)(struct bNodeTree *ntree, struct bNode *node, struct ID *id));
-void node_type_tree(struct bNodeType *ntype,
- void (*inittreefunc)(struct bNodeTree *),
- void (*updatetreefunc)(struct bNodeTree *));
-void node_type_group_edit(struct bNodeType *ntype,
- struct bNodeTree *(*group_edit_get)(struct bNode *node),
- struct bNodeTree *(*group_edit_set)(struct bNode *node, int edit),
- void (*group_edit_clear)(struct bNode *node));
-
-void node_type_exec(struct bNodeType *ntype, void (*execfunc)(void *data, struct bNode *, struct bNodeStack **,
- struct bNodeStack **));
-void node_type_exec_new(struct bNodeType *ntype,
- void *(*initexecfunc)(struct bNode *node),
- void (*freeexecfunc)(struct bNode *node, void *nodedata),
- void (*newexecfunc)(void *data, int thread, struct bNode *, void *nodedata,
- struct bNodeStack **, struct bNodeStack **));
+
+void node_type_exec(struct bNodeType *ntype, NodeInitExecFunction initexecfunc, NodeFreeExecFunction freeexecfunc, NodeExecFunction execfunc);
+void node_type_gpu(struct bNodeType *ntype, NodeGPUExecFunction gpufunc);
void node_type_internal_links(struct bNodeType *ntype, void (*update_internal_links)(struct bNodeTree *, struct bNode *));
-void node_type_gpu(struct bNodeType *ntype, int (*gpufunc)(struct GPUMaterial *mat, struct bNode *node,
- struct GPUNodeStack *in, struct GPUNodeStack *out));
-void node_type_gpu_ext(struct bNodeType *ntype, int (*gpuextfunc)(struct GPUMaterial *mat, struct bNode *node,
- void *nodedata, struct GPUNodeStack *in,
- struct GPUNodeStack *out));
void node_type_compatibility(struct bNodeType *ntype, short compatibility);
/* ************** COMMON NODES *************** */
+#define NODE_UNDEFINED -2 /* node type is not registered */
+#define NODE_CUSTOM -1 /* for dynamically registered custom types */
#define NODE_GROUP 2
-#define __NODE_FORLOOP 3 /* deprecated */
+#define __NODE_FORLOOP 3 /* deprecated */
#define __NODE_WHILELOOP 4 /* deprecated */
#define NODE_FRAME 5
#define NODE_REROUTE 6
+#define NODE_GROUP_INPUT 7
+#define NODE_GROUP_OUTPUT 8
-/* look up a socket on a group node by the internal group socket */
-struct bNodeSocket *node_group_find_input(struct bNode *gnode, struct bNodeSocket *gsock);
-struct bNodeSocket *node_group_find_output(struct bNode *gnode, struct bNodeSocket *gsock);
+void BKE_node_tree_unlink_id(ID *id, struct bNodeTree *ntree);
-struct bNodeSocket *node_group_add_socket(struct bNodeTree *ngroup, const char *name, int type, int in_out);
-struct bNodeSocket *node_group_expose_socket(struct bNodeTree *ngroup, struct bNodeSocket *sock, int in_out);
-void node_group_expose_all_sockets(struct bNodeTree *ngroup);
-void node_group_remove_socket(struct bNodeTree *ngroup, struct bNodeSocket *gsock, int in_out);
-struct bNodeSocket *node_group_add_extern_socket(struct bNodeTree *ntree, ListBase *lb, int in_out, struct bNodeSocket *gsock);
-
-/* in node_common.c */
-void register_node_type_frame(struct bNodeTreeType *ttype);
-void register_node_type_reroute(struct bNodeTreeType *ttype);
+/* Utility macro for visiting every node tree in the library data, including local bNodeTree blocks in other IDs.
+ * This avoids the need for callback functions and allows executing code in a single inner code block.
+ *
+ * Variables:
+ *
+ * nodetree: The actual bNodeTree data block.
+ * Check nodetree->idname or nodetree->typeinfo to use only specific types.
+ *
+ * id: The owner of the bNodeTree data block.
+ * Same as nodetree if it's a linkable node tree from the library.
+ *
+ * Examples:
+ *
+ * FOREACH_NODETREE(bmain, nodetree)
+ * if (id == nodetree)
+ * printf("This is a linkable node tree");
+ * FOREACH_NODETREE_END
+ *
+ * FOREACH_NODETREE(bmain, nodetree)
+ * if (nodetree->idname == "ShaderNodeTree")
+ * printf("This is a shader node tree);
+ * if (GS(id) == ID_MA)
+ * printf(" and it's owned by a material");
+ * FOREACH_NODETREE_END
+ */
-void BKE_node_tree_unlink_id_cb(void *calldata, struct ID *owner_id, struct bNodeTree *ntree);
+#define FOREACH_NODETREE(bmain, _nodetree, _id) \
+{ \
+ bNodeTree *_nodetree; \
+ ID *_id; \
+ bNodeTree *_ngroup = bmain->nodetree.first; \
+ Scene *_scene = bmain->scene.first; \
+ Material *_mat = bmain->mat.first; \
+ Tex *_tex = bmain->tex.first; \
+ Lamp *_lamp = bmain->lamp.first; \
+ World *_world = bmain->world.first; \
+ /* avoid compiler warning about unused variables */ \
+ (void)_id; \
+ (void)_nodetree; \
+ do { \
+ if (_ngroup) { \
+ _nodetree = _ngroup; \
+ _id = (ID *)_ngroup; \
+ _ngroup = _ngroup->id.next; \
+ } \
+ else if (_scene) { \
+ _nodetree = _scene->nodetree; \
+ _id = (ID *)_scene; \
+ _scene = _scene->id.next; \
+ } \
+ else if (_mat) { \
+ _nodetree = _mat->nodetree; \
+ _id = (ID *)_mat; \
+ _mat = _mat->id.next; \
+ } \
+ else if (_tex) { \
+ _nodetree = _tex->nodetree; \
+ _id = (ID *)_tex; \
+ _tex = _tex->id.next; \
+ } \
+ else if (_lamp) { \
+ _nodetree = _lamp->nodetree; \
+ _id = (ID *)_lamp; \
+ _lamp = _lamp->id.next; \
+ } \
+ else if (_world) { \
+ _nodetree = _world->nodetree; \
+ _id = (ID *)_world; \
+ _world = _world->id.next; \
+ } \
+ else \
+ break; \
+ if (_nodetree) {
+
+#define FOREACH_NODETREE_END \
+ } \
+ } while (TRUE); \
+}
/* ************** SHADER NODES *************** */
@@ -583,11 +789,10 @@ struct ShadeResult;
/* API */
-struct bNodeTreeExec *ntreeShaderBeginExecTree(struct bNodeTree *ntree, int use_tree_data);
-void ntreeShaderEndExecTree(struct bNodeTreeExec *exec, int use_tree_data);
+struct bNodeTreeExec *ntreeShaderBeginExecTree(struct bNodeTree *ntree);
+void ntreeShaderEndExecTree(struct bNodeTreeExec *exec);
bool ntreeShaderExecTree(struct bNodeTree *ntree, struct ShadeInput *shi, struct ShadeResult *shr);
void ntreeShaderGetTexcoMode(struct bNodeTree *ntree, int osa, short *texco, int *mode);
-void nodeShaderSynchronizeID(struct bNode *node, int copyto);
/* switch material render loop */
extern void (*node_shader_lamp_loop)(struct ShadeInput *, struct ShadeResult *);
@@ -798,8 +1003,8 @@ struct TexResult;
int ntreeTexTagAnimated(struct bNodeTree *ntree);
void ntreeTexCheckCyclics(struct bNodeTree *ntree);
-struct bNodeTreeExec *ntreeTexBeginExecTree(struct bNodeTree *ntree, int use_tree_data);
-void ntreeTexEndExecTree(struct bNodeTreeExec *exec, int use_tree_data);
+struct bNodeTreeExec *ntreeTexBeginExecTree(struct bNodeTree *ntree);
+void ntreeTexEndExecTree(struct bNodeTreeExec *exec);
int ntreeTexExecTree(struct bNodeTree *ntree, struct TexResult *target,
float coord[3], float dxt[3], float dyt[3], int osatex, const short thread,
struct Tex *tex, short which_output, int cfra, int preview, struct ShadeInput *shi, struct MTex *mtex);
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index c27f5e62520..355541557ea 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -2171,7 +2171,7 @@ void BKE_image_walk_all_users(const Main *mainp, void *customdata,
}
else if (sa->spacetype == SPACE_NODE) {
SpaceNode *snode = sa->spacedata.first;
- if ((snode->treetype == NTREE_COMPOSIT) && (snode->nodetree)) {
+ if (snode->nodetree && snode->nodetree->type==NTREE_COMPOSIT) {
bNode *node;
for (node = snode->nodetree->nodes.first; node; node = node->next) {
if (node->id && node->type == CMP_NODE_IMAGE) {
diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c
index 87802ab8ee6..a5241684e3a 100644
--- a/source/blender/blenkernel/intern/mask.c
+++ b/source/blender/blenkernel/intern/mask.c
@@ -57,6 +57,8 @@
#include "BKE_movieclip.h"
#include "BKE_image.h"
+#include "NOD_composite.h"
+
static MaskSplinePoint *mask_spline_point_next(MaskSpline *spline, MaskSplinePoint *points_array, MaskSplinePoint *point)
{
if (point == &points_array[spline->tot_point - 1]) {
@@ -966,10 +968,9 @@ void BKE_mask_free(Main *bmain, Mask *mask)
}
}
- {
- bNodeTreeType *treetype = ntreeGetType(NTREE_COMPOSIT);
- treetype->foreach_nodetree(bmain, (void *)mask, &BKE_node_tree_unlink_id_cb);
- }
+ FOREACH_NODETREE(bmain, ntree, id) {
+ BKE_node_tree_unlink_id((ID *)mask, ntree);
+ } FOREACH_NODETREE_END
/* free mask data */
BKE_mask_layer_free_list(&mask->masklayers);
diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c
index ab425d8e5b9..c47eb7eac45 100644
--- a/source/blender/blenkernel/intern/material.c
+++ b/source/blender/blenkernel/intern/material.c
@@ -1012,7 +1012,7 @@ void init_render_material(Material *mat, int r_mode, float *amb)
init_render_nodetree(mat->nodetree, mat, r_mode, amb);
if (!mat->nodetree->execdata)
- mat->nodetree->execdata = ntreeShaderBeginExecTree(mat->nodetree, 1);
+ mat->nodetree->execdata = ntreeShaderBeginExecTree(mat->nodetree);
}
}
@@ -1046,7 +1046,7 @@ void end_render_material(Material *mat)
{
if (mat && mat->nodetree && mat->use_nodes) {
if (mat->nodetree->execdata)
- ntreeShaderEndExecTree(mat->nodetree->execdata, 1);
+ ntreeShaderEndExecTree(mat->nodetree->execdata);
}
}
diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c
index e79754ca203..821c8fe3bda 100644
--- a/source/blender/blenkernel/intern/movieclip.c
+++ b/source/blender/blenkernel/intern/movieclip.c
@@ -86,6 +86,8 @@
#include "intern/openexr/openexr_multi.h"
#endif
+#include "NOD_composite.h"
+
/*********************** movieclip buffer loaders *************************/
static int sequence_guess_offset(const char *full_name, int head_len, unsigned short numlen)
@@ -1401,10 +1403,9 @@ void BKE_movieclip_unlink(Main *bmain, MovieClip *clip)
}
}
- {
- bNodeTreeType *treetype = ntreeGetType(NTREE_COMPOSIT);
- treetype->foreach_nodetree(bmain, (void *)clip, &BKE_node_tree_unlink_id_cb);
- }
+ FOREACH_NODETREE(bmain, ntree, id) {
+ BKE_node_tree_unlink_id((ID *)clip, ntree);
+ } FOREACH_NODETREE_END
clip->id.us = 0;
}
diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c
index 974a564b9da..0b63c4d8842 100644
--- a/source/blender/blenkernel/intern/node.c
+++ b/source/blender/blenkernel/intern/node.c
@@ -58,133 +58,634 @@
#include "BKE_action.h"
#include "BKE_fcurve.h"
#include "BKE_global.h"
+#include "BKE_idprop.h"
#include "BKE_image.h"
#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_node.h"
+#include "BLI_ghash.h"
#include "RNA_access.h"
+#include "RNA_define.h"
#include "NOD_socket.h"
+#include "NOD_common.h"
#include "NOD_composite.h"
#include "NOD_shader.h"
#include "NOD_texture.h"
-bNodeTreeType *ntreeGetType(int type)
+static void node_add_sockets_from_type(bNodeTree *ntree, bNode *node, bNodeType *ntype)
{
- static bNodeTreeType *types[NUM_NTREE_TYPES];
- static int types_init = 1;
- if (types_init) {
- types[NTREE_SHADER] = &ntreeType_Shader;
- types[NTREE_COMPOSIT] = &ntreeType_Composite;
- types[NTREE_TEXTURE] = &ntreeType_Texture;
- types_init = 0;
+ bNodeSocketTemplate *sockdef;
+ /* bNodeSocket *sock; */ /* UNUSED */
+
+ if (ntype->inputs) {
+ sockdef = ntype->inputs;
+ while (sockdef->type != -1) {
+ /* sock = */ node_add_socket_from_template(ntree, node, sockdef, SOCK_IN);
+
+ sockdef++;
+ }
+ }
+ if (ntype->outputs) {
+ sockdef = ntype->outputs;
+ while (sockdef->type != -1) {
+ /* sock = */ node_add_socket_from_template(ntree, node, sockdef, SOCK_OUT);
+
+ sockdef++;
+ }
}
+}
+
+/* Note: This function is called to initialize node data based on the type.
+ * The bNodeType may not be registered at creation time of the node,
+ * so this can be delayed until the node type gets registered.
+ * The node->typeinfo must not be used in that case until it is defined!
+ */
+static void node_init(const struct bContext *C, bNodeTree *ntree, bNode *node)
+{
+ bNodeType *ntype = node->typeinfo;
+ if (!ntype)
+ return;
+
+ /* only do this once */
+ if (node->flag & NODE_INIT)
+ return;
+
+ node->flag = NODE_SELECT | ntype->flag;
+ node->width = ntype->width;
+ node->miniwidth = 42.0f;
+ node->height = ntype->height;
+ node->color[0] = node->color[1] = node->color[2] = 0.608; /* default theme color */
- if (type >= 0 && type < NUM_NTREE_TYPES) {
- return types[type];
+ /* initialize the node name with the node label.
+ * note: do this after the initfunc so nodes get their data set which may be used in naming
+ * (node groups for example) */
+ /* XXX Do not use nodeLabel() here, it returns translated content, which should *only* be used
+ * in UI, *never* in data...
+ * This solution may be a bit rougher than nodeLabel()'s returned string, but it's simpler
+ * than adding a "no translate" flag to this func (and labelfunc() as well). */
+ BLI_strncpy(node->name, ntype->ui_name, NODE_MAXSTR);
+ nodeUniqueName(ntree, node);
+
+ node_add_sockets_from_type(ntree, node, ntype);
+
+ if (ntype->initfunc != NULL)
+ ntype->initfunc(ntree, node);
+
+ /* extra init callback */
+ if (ntype->initfunc_api) {
+ PointerRNA ptr;
+ RNA_pointer_create((ID *)ntree, &RNA_Node, node, &ptr);
+
+ /* XXX Warning: context can be NULL in case nodes are added in do_versions.
+ * Delayed init is not supported for nodes with context-based initfunc_api atm.
+ */
+ BLI_assert(C != NULL);
+ ntype->initfunc_api(C, &ptr);
+ }
+
+ node->flag |= NODE_INIT;
+}
+
+static void ntree_set_typeinfo(bNodeTree *ntree, bNodeTreeType *typeinfo)
+{
+ ntree->typeinfo = typeinfo;
+
+ if (typeinfo) {
+ /* deprecated integer type */
+ ntree->type = typeinfo->type;
}
else {
- return NULL;
+ ntree->init &= ~NTREE_TYPE_INIT;
}
}
-static bNodeType *node_get_type(bNodeTree *ntree, int type)
+static void node_set_typeinfo(const struct bContext *C, bNodeTree *ntree, bNode *node, bNodeType *typeinfo)
{
- bNodeType *ntype = ntreeGetType(ntree->type)->node_types.first;
- for (; ntype; ntype = ntype->next)
- if (ntype->type == type)
- return ntype;
+ node->typeinfo = typeinfo;
+ if (typeinfo) {
+ /* deprecated integer type */
+ node->type = typeinfo->type;
+
+ /* initialize the node if necessary */
+ node_init(C, ntree, node);
+ }
+ else {
+ ntree->init &= ~NTREE_TYPE_INIT;
+ }
+}
+
+static void node_socket_set_typeinfo(bNodeTree *ntree, bNodeSocket *sock, bNodeSocketType *typeinfo)
+{
+ sock->typeinfo = typeinfo;
+
+ if (typeinfo) {
+ if (sock->default_value == NULL) {
+ /* initialize the default_value pointer used by standard socket types */
+ node_socket_init_default_value(sock);
+ }
+ }
+ else {
+ ntree->init &= ~NTREE_TYPE_INIT;
+ }
+}
+
+/* Set specific typeinfo pointers in all node trees on register/unregister */
+static void update_typeinfo(Main *bmain, const struct bContext *C, bNodeTreeType *treetype, bNodeType *nodetype, bNodeSocketType *socktype, bool unregister)
+{
+ if (!bmain)
+ return;
+
+ FOREACH_NODETREE(bmain, ntree, id) {
+ bNode *node;
+ bNodeSocket *sock;
+
+ ntree->init |= NTREE_TYPE_INIT;
+
+ if (treetype && strcmp(ntree->idname, treetype->idname)==0)
+ ntree_set_typeinfo(ntree, unregister ? NULL : treetype);
+
+ /* initialize nodes */
+ for (node=ntree->nodes.first; node; node=node->next) {
+ if (nodetype && strcmp(node->idname, nodetype->idname)==0)
+ node_set_typeinfo(C, ntree, node, unregister ? NULL : nodetype);
+
+ /* initialize node sockets */
+ for (sock=node->inputs.first; sock; sock=sock->next)
+ if (socktype && strcmp(sock->idname, socktype->idname)==0)
+ node_socket_set_typeinfo(ntree, sock, unregister ? NULL : socktype);
+ for (sock=node->outputs.first; sock; sock=sock->next)
+ if (socktype && strcmp(sock->idname, socktype->idname)==0)
+ node_socket_set_typeinfo(ntree, sock, unregister ? NULL : socktype);
+ }
+
+ /* initialize tree sockets */
+ for (sock=ntree->inputs.first; sock; sock=sock->next)
+ if (socktype && strcmp(sock->idname, socktype->idname)==0)
+ node_socket_set_typeinfo(ntree, sock, unregister ? NULL : socktype);
+ for (sock=ntree->outputs.first; sock; sock=sock->next)
+ if (socktype && strcmp(sock->idname, socktype->idname)==0)
+ node_socket_set_typeinfo(ntree, sock, unregister ? NULL : socktype);
+ }
+ FOREACH_NODETREE_END
+}
+
+/* Try to initialize all typeinfo in a node tree.
+ * NB: In general undefined typeinfo is a perfectly valid case, the type may just be registered later.
+ * In that case the update_typeinfo function will set typeinfo on registration
+ * and do necessary updates.
+ */
+void ntreeSetTypes(const struct bContext *C, bNodeTree *ntree)
+{
+ bNode *node;
+ bNodeSocket *sock;
+
+ ntree->init |= NTREE_TYPE_INIT;
+
+ ntree_set_typeinfo(ntree, ntreeTypeFind(ntree->idname));
+
+ for (node = ntree->nodes.first; node; node = node->next) {
+ node_set_typeinfo(C, ntree, node, nodeTypeFind(node->idname));
+
+ for (sock=node->inputs.first; sock; sock=sock->next)
+ node_socket_set_typeinfo(ntree, sock, nodeSocketTypeFind(sock->idname));
+ for (sock=node->outputs.first; sock; sock=sock->next)
+ node_socket_set_typeinfo(ntree, sock, nodeSocketTypeFind(sock->idname));
+ }
+
+ for (sock=ntree->inputs.first; sock; sock=sock->next)
+ node_socket_set_typeinfo(ntree, sock, nodeSocketTypeFind(sock->idname));
+ for (sock=ntree->outputs.first; sock; sock=sock->next)
+ node_socket_set_typeinfo(ntree, sock, nodeSocketTypeFind(sock->idname));
+}
+
+
+static GHash *nodetreetypes_hash= NULL;
+static GHash *nodetypes_hash= NULL;
+static GHash *nodesockettypes_hash= NULL;
+
+bNodeTreeType *ntreeTypeFind(const char *idname)
+{
+ bNodeTreeType* nt;
+
+ if (idname[0]) {
+ nt= BLI_ghash_lookup(nodetreetypes_hash, idname);
+ if(nt)
+ return nt;
+ }
+
return NULL;
}
-bNodeType *ntreeGetNodeType(bNodeTree *ntree)
+void ntreeTypeAdd(bNodeTreeType* nt)
{
- return node_get_type(ntree, ntree->nodetype);
+ BLI_ghash_insert(nodetreetypes_hash, (void *)nt->idname, nt);
+ /* XXX pass Main to register function? */
+ update_typeinfo(G.main, NULL, nt, NULL, NULL, false);
}
-bNodeSocketType *ntreeGetSocketType(int type)
+/* callback for hash value free function */
+static void ntree_free_type(void *treetype_v)
{
- static bNodeSocketType *types[NUM_SOCKET_TYPES] = {NULL};
- static int types_init = 1;
+ bNodeTreeType *treetype = treetype_v;
+ /* XXX pass Main to unregister function? */
+ update_typeinfo(G.main, NULL, treetype, NULL, NULL, true);
+ MEM_freeN(treetype);
+}
- if (types_init) {
- node_socket_type_init(types);
- types_init = 0;
+void ntreeTypeFreeLink(bNodeTreeType* nt)
+{
+ BLI_ghash_remove(nodetreetypes_hash, nt->idname, NULL, ntree_free_type);
+}
+
+GHashIterator *ntreeTypeGetIterator()
+{
+ return BLI_ghashIterator_new(nodetreetypes_hash);
+}
+
+int ntreeIsValid(bNodeTree *ntree)
+{
+ return (ntree && (ntree->init & NTREE_TYPE_INIT));
+}
+
+bNodeType *nodeTypeFind(const char *idname)
+{
+ bNodeType* nt;
+
+ if (idname[0]) {
+ nt= BLI_ghash_lookup(nodetypes_hash, idname);
+ if(nt)
+ return nt;
}
- if (type < NUM_SOCKET_TYPES) {
- return types[type];
+ return NULL;
+}
+
+static void free_dynamic_typeinfo(bNodeType *ntype)
+{
+ if(ntype->type==NODE_DYNAMIC) {
+ if(ntype->inputs) {
+ MEM_freeN(ntype->inputs);
+ }
+ if(ntype->outputs) {
+ MEM_freeN(ntype->outputs);
+ }
+ if(ntype->ui_name) {
+ MEM_freeN((void *)ntype->ui_name);
+ }
}
- else {
- return NULL;
+}
+
+/* callback for hash value free function */
+static void node_free_type(void *nodetype_v)
+{
+ bNodeType *nodetype = nodetype_v;
+ /* XXX pass Main to unregister function? */
+ update_typeinfo(G.main, NULL, NULL, nodetype, NULL, true);
+
+ /* XXX deprecated */
+ if (nodetype->type==NODE_DYNAMIC)
+ free_dynamic_typeinfo(nodetype);
+
+ if (nodetype->needs_free)
+ MEM_freeN(nodetype);
+}
+
+void nodeRegisterType(bNodeType *nt)
+{
+ /* debug only: basic verification of registered types */
+ BLI_assert(nt->idname[0] != '\0');
+ BLI_assert(nt->poll != NULL);
+
+ BLI_ghash_insert(nodetypes_hash, (void *)nt->idname, nt);
+ /* XXX pass Main to register function? */
+ update_typeinfo(G.main, NULL, NULL, nt, NULL, false);
+}
+
+void nodeUnregisterType(bNodeType* nt)
+{
+ BLI_ghash_remove(nodetypes_hash, nt->idname, NULL, node_free_type);
+}
+
+GHashIterator *nodeTypeGetIterator()
+{
+ return BLI_ghashIterator_new(nodetypes_hash);
+}
+
+bNodeSocketType *nodeSocketTypeFind(const char *idname)
+{
+ bNodeSocketType* st;
+
+ if (idname[0]) {
+ st= BLI_ghash_lookup(nodesockettypes_hash, idname);
+ if(st)
+ return st;
}
+
+ return NULL;
}
-void ntreeInitTypes(bNodeTree *ntree)
+/* callback for hash value free function */
+static void node_free_socket_type(void *socktype_v)
{
- bNode *node, *next;
+ bNodeSocketType *socktype = socktype_v;
+ /* XXX pass Main to unregister function? */
+ update_typeinfo(G.main, NULL, NULL, NULL, socktype, true);
- for (node = ntree->nodes.first; node; node = next) {
- next = node->next;
-
- node->typeinfo = node_get_type(ntree, node->type);
+ MEM_freeN(socktype);
+}
- if (node->typeinfo == NULL) {
- printf("Error: Node type %s doesn't exist anymore, removed\n", node->name);
- nodeFreeNode(ntree, node);
- }
+void nodeRegisterSocketType(bNodeSocketType* st)
+{
+ BLI_ghash_insert(nodesockettypes_hash, (void *)st->idname, st);
+ /* XXX pass Main to register function? */
+ update_typeinfo(G.main, NULL, NULL, NULL, st, false);
+}
+
+void nodeUnregisterSocketType(bNodeSocketType* st)
+{
+ BLI_ghash_remove(nodesockettypes_hash, st->idname, NULL, node_free_socket_type);
+}
+
+GHashIterator *nodeSocketTypeGetIterator(void)
+{
+ return BLI_ghashIterator_new(nodesockettypes_hash);
+}
+
+void nodeMakeDynamicType(bNode *UNUSED(node))
+{
+ #if 0 /* XXX deprecated */
+ /* find SH_DYNAMIC_NODE ntype */
+ bNodeType *ntype= ntreeType_Shader->node_types.first;
+ while(ntype) {
+ if(ntype->type==NODE_DYNAMIC)
+ break;
+ ntype= ntype->next;
}
-
- ntree->init |= NTREE_TYPE_INIT;
+
+ /* make own type struct to fill */
+ if(ntype) {
+ /*node->typeinfo= MEM_dupallocN(ntype);*/
+ bNodeType *newtype= MEM_callocN(sizeof(bNodeType), "dynamic bNodeType");
+ *newtype= *ntype;
+ BLI_strncpy(newtype->name, ntype->name, sizeof(newtype->name));
+ node->typeinfo= newtype;
+ }
+ #endif
}
-static bNodeSocket *make_socket(bNodeTree *UNUSED(ntree), int in_out, const char *name, int type)
+struct bNodeSocket *nodeFindSocket(bNode *node, int in_out, const char *identifier)
+{
+ bNodeSocket *sock = (in_out == SOCK_IN ? node->inputs.first : node->outputs.first);
+ for (; sock; sock=sock->next) {
+ if (strcmp(sock->identifier, identifier)==0)
+ return sock;
+ }
+ return NULL;
+}
+
+/* find unique socket identifier */
+static bool unique_identifier_check(void *arg, const char *identifier)
+{
+ struct ListBase *lb = arg;
+ bNodeSocket *sock;
+ for (sock = lb->first; sock; sock = sock->next) {
+ if (strcmp(sock->identifier, identifier)==0)
+ return true;
+ }
+ return false;
+}
+
+static bNodeSocket *make_socket(bNodeTree *ntree, bNode *UNUSED(node), int in_out, ListBase *lb,
+ const char *idname, const char *identifier, const char *name)
{
bNodeSocket *sock;
+ char auto_identifier[MAX_NAME];
+
+ if (identifier && identifier[0] != '\0') {
+ /* use explicit identifier */
+ BLI_strncpy(auto_identifier, identifier, sizeof(auto_identifier));
+ }
+ else {
+ /* if no explicit identifier is given, assign a unique identifier based on the name */
+ BLI_strncpy(auto_identifier, name, sizeof(auto_identifier));
+ }
+ /* make the identifier unique */
+ BLI_uniquename_cb(unique_identifier_check, lb, NULL, '.', auto_identifier, sizeof(auto_identifier));
sock = MEM_callocN(sizeof(bNodeSocket), "sock");
+ sock->in_out = in_out;
- BLI_strncpy(sock->name, name, NODE_MAXSTR);
+ BLI_strncpy(sock->identifier, auto_identifier, NODE_MAXSTR);
sock->limit = (in_out == SOCK_IN ? 1 : 0xFFF);
- sock->type = type;
+
+ BLI_strncpy(sock->name, name, NODE_MAXSTR);
sock->storage = NULL;
sock->flag |= SOCK_COLLAPSED;
+ sock->type = SOCK_CUSTOM; /* int type undefined by default */
- sock->default_value = node_socket_make_default_value(type);
- node_socket_init_default_value(type, sock->default_value);
+ BLI_strncpy(sock->idname, idname, sizeof(sock->idname));
+ node_socket_set_typeinfo(ntree, sock, nodeSocketTypeFind(idname));
return sock;
}
-bNodeSocket *nodeAddSocket(bNodeTree *ntree, bNode *node, int in_out, const char *name, int type)
+bNodeSocket *nodeAddSocket(bNodeTree *ntree, bNode *node, int in_out, const char *idname,
+ const char *identifier, const char *name)
{
- bNodeSocket *sock = make_socket(ntree, in_out, name, type);
- if (in_out == SOCK_IN)
- BLI_addtail(&node->inputs, sock);
- else if (in_out == SOCK_OUT)
- BLI_addtail(&node->outputs, sock);
+ ListBase *lb = (in_out == SOCK_IN ? &node->inputs : &node->outputs);
+ bNodeSocket *sock = make_socket(ntree, node, in_out, lb, idname, identifier, name);
+
+ BLI_remlink(lb, sock); /* does nothing for new socket */
+ BLI_addtail(lb, sock);
node->update |= NODE_UPDATE;
return sock;
}
-bNodeSocket *nodeInsertSocket(bNodeTree *ntree, bNode *node, int in_out, bNodeSocket *next_sock, const char *name, int type)
+bNodeSocket *nodeInsertSocket(bNodeTree *ntree, bNode *node, int in_out, const char *idname,
+ bNodeSocket *next_sock, const char *identifier, const char *name)
{
- bNodeSocket *sock = make_socket(ntree, in_out, name, type);
- if (in_out == SOCK_IN)
- BLI_insertlinkbefore(&node->inputs, next_sock, sock);
- else if (in_out == SOCK_OUT)
- BLI_insertlinkbefore(&node->outputs, next_sock, sock);
+ ListBase *lb = (in_out == SOCK_IN ? &node->inputs : &node->outputs);
+ bNodeSocket *sock = make_socket(ntree, node, in_out, lb, idname, identifier, name);
+
+ BLI_remlink(lb, sock); /* does nothing for new socket */
+ BLI_insertlinkbefore(lb, next_sock, sock);
node->update |= NODE_UPDATE;
return sock;
}
+const char *nodeStaticSocketType(int type, int subtype)
+{
+ switch (type) {
+ case SOCK_FLOAT:
+ switch (subtype) {
+ case PROP_UNSIGNED:
+ return "NodeSocketFloatUnsigned";
+ case PROP_PERCENTAGE:
+ return "NodeSocketFloatPercentage";
+ case PROP_FACTOR:
+ return "NodeSocketFloatFactor";
+ case PROP_ANGLE:
+ return "NodeSocketFloatAngle";
+ case PROP_TIME:
+ return "NodeSocketFloatTime";
+ case PROP_NONE:
+ default:
+ return "NodeSocketFloat";
+ }
+ case SOCK_INT:
+ switch (subtype) {
+ case PROP_UNSIGNED:
+ return "NodeSocketIntUnsigned";
+ case PROP_PERCENTAGE:
+ return "NodeSocketIntPercentage";
+ case PROP_FACTOR:
+ return "NodeSocketIntFactor";
+ case PROP_NONE:
+ default:
+ return "NodeSocketInt";
+ }
+ case SOCK_BOOLEAN:
+ return "NodeSocketBool";
+ case SOCK_VECTOR:
+ switch (subtype) {
+ case PROP_TRANSLATION:
+ return "NodeSocketVectorTranslation";
+ case PROP_DIRECTION:
+ return "NodeSocketVectorDirection";
+ case PROP_VELOCITY:
+ return "NodeSocketVectorVelocity";
+ case PROP_ACCELERATION:
+ return "NodeSocketVectorAcceleration";
+ case PROP_EULER:
+ return "NodeSocketVectorEuler";
+ case PROP_XYZ:
+ return "NodeSocketVectorXYZ";
+ case PROP_NONE:
+ default:
+ return "NodeSocketVector";
+ }
+ case SOCK_RGBA:
+ return "NodeSocketColor";
+ case SOCK_STRING:
+ return "NodeSocketString";
+ case SOCK_SHADER:
+ return "NodeSocketShader";
+ }
+ return NULL;
+}
+
+const char *nodeStaticSocketInterfaceType(int type, int subtype)
+{
+ switch (type) {
+ case SOCK_FLOAT:
+ switch (subtype) {
+ case PROP_UNSIGNED:
+ return "NodeSocketInterfaceFloatUnsigned";
+ case PROP_PERCENTAGE:
+ return "NodeSocketInterfaceFloatPercentage";
+ case PROP_FACTOR:
+ return "NodeSocketInterfaceFloatFactor";
+ case PROP_ANGLE:
+ return "NodeSocketInterfaceFloatAngle";
+ case PROP_TIME:
+ return "NodeSocketInterfaceFloatTime";
+ case PROP_NONE:
+ default:
+ return "NodeSocketInterfaceFloat";
+ }
+ case SOCK_INT:
+ switch (subtype) {
+ case PROP_UNSIGNED:
+ return "NodeSocketInterfaceIntUnsigned";
+ case PROP_PERCENTAGE:
+ return "NodeSocketInterfaceIntPercentage";
+ case PROP_FACTOR:
+ return "NodeSocketInterfaceIntFactor";
+ case PROP_NONE:
+ default:
+ return "NodeSocketInterfaceInt";
+ }
+ case SOCK_BOOLEAN:
+ return "NodeSocketInterfaceBool";
+ case SOCK_VECTOR:
+ switch (subtype) {
+ case PROP_TRANSLATION:
+ return "NodeSocketInterfaceVectorTranslation";
+ case PROP_DIRECTION:
+ return "NodeSocketInterfaceVectorDirection";
+ case PROP_VELOCITY:
+ return "NodeSocketInterfaceVectorVelocity";
+ case PROP_ACCELERATION:
+ return "NodeSocketInterfaceVectorAcceleration";
+ case PROP_EULER:
+ return "NodeSocketInterfaceVectorEuler";
+ case PROP_XYZ:
+ return "NodeSocketInterfaceVectorXYZ";
+ case PROP_NONE:
+ default:
+ return "NodeSocketInterfaceVector";
+ }
+ case SOCK_RGBA:
+ return "NodeSocketInterfaceColor";
+ case SOCK_STRING:
+ return "NodeSocketInterfaceString";
+ case SOCK_SHADER:
+ return "NodeSocketInterfaceShader";
+ }
+ return NULL;
+}
+
+bNodeSocket *nodeAddStaticSocket(bNodeTree *ntree, bNode *node, int in_out, int type, int subtype,
+ const char *identifier, const char *name)
+{
+ const char *idname = nodeStaticSocketType(type, subtype);
+ bNodeSocket *sock;
+
+ if (!idname) {
+ printf("Error: static node socket type %d undefined\n", type);
+ return NULL;
+ }
+
+ sock = nodeAddSocket(ntree, node, in_out, idname, identifier, name);
+ sock->type = type;
+ return sock;
+}
+
+bNodeSocket *nodeInsertStaticSocket(bNodeTree *ntree, bNode *node, int in_out, int type, int subtype,
+ bNodeSocket *next_sock, const char *identifier, const char *name)
+{
+ const char *idname = nodeStaticSocketType(type, subtype);
+ bNodeSocket *sock;
+
+ if (!idname) {
+ printf("Error: static node socket type %d undefined\n", type);
+ return NULL;
+ }
+
+ sock = nodeInsertSocket(ntree, node, in_out, idname, next_sock, identifier, name);
+ sock->type = type;
+ return sock;
+}
+
+static void node_socket_free(bNodeTree *UNUSED(ntree), bNodeSocket *sock, bNode *UNUSED(node))
+{
+ if (sock->prop) {
+ IDP_FreeProperty(sock->prop);
+ MEM_freeN(sock->prop);
+ }
+
+ if (sock->default_value)
+ MEM_freeN(sock->default_value);
+}
+
void nodeRemoveSocket(bNodeTree *ntree, bNode *node, bNodeSocket *sock)
{
bNodeLink *link, *next;
@@ -200,7 +701,7 @@ void nodeRemoveSocket(bNodeTree *ntree, bNode *node, bNodeSocket *sock)
BLI_remlink(&node->inputs, sock);
BLI_remlink(&node->outputs, sock);
- node_socket_free_default_value(sock->type, sock->default_value);
+ node_socket_free(ntree, sock, node);
MEM_freeN(sock);
node->update |= NODE_UPDATE;
@@ -208,7 +709,7 @@ void nodeRemoveSocket(bNodeTree *ntree, bNode *node, bNodeSocket *sock)
void nodeRemoveAllSockets(bNodeTree *ntree, bNode *node)
{
- bNodeSocket *sock;
+ bNodeSocket *sock, *sock_next;
bNodeLink *link, *next;
for (link = ntree->links.first; link; link = next) {
@@ -218,12 +719,16 @@ void nodeRemoveAllSockets(bNodeTree *ntree, bNode *node)
}
}
- for (sock = node->inputs.first; sock; sock = sock->next)
- node_socket_free_default_value(sock->type, sock->default_value);
- BLI_freelistN(&node->inputs);
- for (sock = node->outputs.first; sock; sock = sock->next)
- node_socket_free_default_value(sock->type, sock->default_value);
- BLI_freelistN(&node->outputs);
+ for (sock = node->inputs.first; sock; sock = sock_next) {
+ sock_next = sock->next;
+ node_socket_free(ntree, sock, node);
+ MEM_freeN(sock);
+ }
+ for (sock = node->outputs.first; sock; sock = sock_next) {
+ sock_next = sock->next;
+ node_socket_free(ntree, sock, node);
+ MEM_freeN(sock);
+ }
node->update |= NODE_UPDATE;
}
@@ -235,26 +740,18 @@ bNode *nodeFindNodebyName(bNodeTree *ntree, const char *name)
}
/* finds a node based on given socket */
-int nodeFindNode(bNodeTree *ntree, bNodeSocket *sock, bNode **nodep, int *sockindex, int *in_out)
+int nodeFindNode(bNodeTree *ntree, bNodeSocket *sock, bNode **nodep, int *sockindex)
{
+ int in_out = sock->in_out;
bNode *node;
bNodeSocket *tsock;
int index = 0;
for (node = ntree->nodes.first; node; node = node->next) {
- for (index = 0, tsock = node->inputs.first; tsock; tsock = tsock->next, index++) {
- if (tsock == sock) {
- if (in_out) *in_out = SOCK_IN;
+ tsock = (in_out == SOCK_IN ? node->inputs.first : node->outputs.first);
+ for (index = 0; tsock; tsock = tsock->next, index++) {
+ if (tsock == sock)
break;
- }
- }
- if (tsock)
- break;
- for (index = 0, tsock = node->outputs.first; tsock; tsock = tsock->next, index++) {
- if (tsock == sock) {
- if (in_out) *in_out = SOCK_OUT;
- break;
- }
}
if (tsock)
break;
@@ -271,28 +768,6 @@ int nodeFindNode(bNodeTree *ntree, bNodeSocket *sock, bNode **nodep, int *sockin
}
/* ************** Add stuff ********** */
-static void node_add_sockets_from_type(bNodeTree *ntree, bNode *node, bNodeType *ntype)
-{
- bNodeSocketTemplate *sockdef;
- /* bNodeSocket *sock; */ /* UNUSED */
-
- if (ntype->inputs) {
- sockdef = ntype->inputs;
- while (sockdef->type != -1) {
- /* sock = */ node_add_input_from_template(ntree, node, sockdef);
-
- sockdef++;
- }
- }
- if (ntype->outputs) {
- sockdef = ntype->outputs;
- while (sockdef->type != -1) {
- /* sock = */ node_add_output_from_template(ntree, node, sockdef);
-
- sockdef++;
- }
- }
-}
/* Find the first available, non-duplicate name for a given node */
void nodeUniqueName(bNodeTree *ntree, bNode *node)
@@ -300,51 +775,55 @@ void nodeUniqueName(bNodeTree *ntree, bNode *node)
BLI_uniquename(&ntree->nodes, node, "Node", '.', offsetof(bNode, name), sizeof(node->name));
}
-bNode *nodeAddNode(bNodeTree *ntree, struct bNodeTemplate *ntemp)
+bNode *nodeAddNode(const struct bContext *C, bNodeTree *ntree, const char *idname)
{
bNode *node;
- bNodeType *ntype;
-
- ntype = node_get_type(ntree, ntemp->type);
- if (ntype == NULL) {
- printf("nodeAddNodeType() error: '%d' type invalid\n", ntemp->type);
- return NULL;
- }
- /* validity check */
- if (!nodeValid(ntree, ntemp))
- return NULL;
node = MEM_callocN(sizeof(bNode), "new node");
- node->type = ntype->type;
- node->typeinfo = ntype;
- node->flag = NODE_SELECT | ntype->flag;
- node->width = ntype->width;
- node->miniwidth = 42.0f;
- node->height = ntype->height;
- node->color[0] = node->color[1] = node->color[2] = 0.608; /* default theme color */
-
- node_add_sockets_from_type(ntree, node, ntype);
-
BLI_addtail(&ntree->nodes, node);
- if (ntype->initfunc != NULL)
- ntype->initfunc(ntree, node, ntemp);
-
- /* initialize the node name with the node label.
- * note: do this after the initfunc so nodes get their data set which may be used in naming
- * (node groups for example) */
- /* XXX Do not use nodeLabel() here, it returns translated content, which should *only* be used
- * in UI, *never* in data...
- * This solution may be a bit rougher than nodeLabel()'s returned string, but it's simpler
- * than adding a "no translate" flag to this func (and labelfunc() as well). */
- BLI_strncpy(node->name, node->typeinfo->name, NODE_MAXSTR);
- nodeUniqueName(ntree, node);
+ BLI_strncpy(node->idname, idname, sizeof(node->idname));
+ node_set_typeinfo(C, ntree, node, nodeTypeFind(idname));
ntree->update |= NTREE_UPDATE_NODES;
return node;
}
+bNode *nodeAddStaticNode(const struct bContext *C, bNodeTree *ntree, int type)
+{
+ const char *idname=NULL;
+
+ NODE_TYPES_BEGIN(ntype)
+ if(ntype->type==type) {
+ idname = ntype->idname;
+ break;
+ }
+ NODE_TYPES_END
+ if (!idname) {
+ printf("Error: static node type %d undefined\n", type);
+ return NULL;
+ }
+ return nodeAddNode(C, ntree, idname);
+}
+
+static void node_socket_copy(bNodeSocket *dst, bNodeSocket *src)
+{
+ src->new_sock = dst;
+
+ if (src->prop)
+ dst->prop = IDP_CopyProperty(src->prop);
+
+ if (src->default_value)
+ dst->default_value = MEM_dupallocN(src->default_value);
+
+ dst->stack_index = 0;
+ /* XXX some compositor node (e.g. image, render layers) still store
+ * some persistent buffer data here, need to clear this to avoid dangling pointers.
+ */
+ dst->cache = NULL;
+}
+
/* keep socket listorder identical, for copying links */
/* ntree is the target tree */
bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node)
@@ -363,33 +842,16 @@ bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node)
BLI_duplicatelist(&nnode->inputs, &node->inputs);
oldsock = node->inputs.first;
- for (sock = nnode->inputs.first; sock; sock = sock->next, oldsock = oldsock->next) {
- oldsock->new_sock = sock;
- sock->stack_index = 0;
-
- sock->default_value = node_socket_make_default_value(oldsock->type);
- node_socket_copy_default_value(oldsock->type, sock->default_value, oldsock->default_value);
-
- /* XXX some compositor node (e.g. image, render layers) still store
- * some persistent buffer data here, need to clear this to avoid dangling pointers.
- */
- sock->cache = NULL;
- }
+ for (sock = nnode->inputs.first; sock; sock = sock->next, oldsock = oldsock->next)
+ node_socket_copy(sock, oldsock);
BLI_duplicatelist(&nnode->outputs, &node->outputs);
oldsock = node->outputs.first;
- for (sock = nnode->outputs.first; sock; sock = sock->next, oldsock = oldsock->next) {
- oldsock->new_sock = sock;
- sock->stack_index = 0;
-
- sock->default_value = node_socket_make_default_value(oldsock->type);
- node_socket_copy_default_value(oldsock->type, sock->default_value, oldsock->default_value);
-
- /* XXX some compositor node (e.g. image, render layers) still store
- * some persistent buffer data here, need to clear this to avoid dangling pointers.
- */
- sock->cache = NULL;
- }
+ for (sock = nnode->outputs.first; sock; sock = sock->next, oldsock = oldsock->next)
+ node_socket_copy(sock, oldsock);
+
+ if (node->prop)
+ nnode->prop = IDP_CopyProperty(node->prop);
BLI_duplicatelist(&nnode->internal_links, &node->internal_links);
oldlink = node->internal_links.first;
@@ -402,22 +864,17 @@ bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node)
/* don't increase node->id users, freenode doesn't decrement either */
- if (node->typeinfo->copystoragefunc)
- node->typeinfo->copystoragefunc(node, nnode);
+ if (node->typeinfo->copyfunc)
+ node->typeinfo->copyfunc(ntree, nnode, node);
node->new_node = nnode;
nnode->new_node = NULL;
- /* only shader nodes get pleasant preview updating this way, compo uses own system */
- if (node->preview) {
- if (ntree && (ntree->type == NTREE_SHADER)) {
- nnode->preview = MEM_dupallocN(node->preview);
- if (node->preview->rect)
- nnode->preview->rect = MEM_dupallocN(node->preview->rect);
- }
- else {
- nnode->preview = NULL;
- }
+ if (nnode->typeinfo->copyfunc_api) {
+ PointerRNA ptr;
+ RNA_pointer_create((ID *)ntree, &RNA_Node, nnode, &ptr);
+
+ nnode->typeinfo->copyfunc_api(&ptr, node);
}
if (ntree)
@@ -429,71 +886,13 @@ bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node)
/* also used via rna api, so we check for proper input output direction */
bNodeLink *nodeAddLink(bNodeTree *ntree, bNode *fromnode, bNodeSocket *fromsock, bNode *tonode, bNodeSocket *tosock)
{
- bNodeSocket *sock;
bNodeLink *link = NULL;
- int from = 0, to = 0;
- if (fromnode) {
- /* test valid input */
- for (sock = fromnode->outputs.first; sock; sock = sock->next)
- if (sock == fromsock)
- break;
- if (sock)
- from = 1; /* OK */
- else {
- for (sock = fromnode->inputs.first; sock; sock = sock->next)
- if (sock == fromsock)
- break;
- if (sock)
- from = -1; /* OK but flip */
- }
- }
- else if (ntree) {
- /* check tree sockets */
- for (sock = ntree->inputs.first; sock; sock = sock->next)
- if (sock == fromsock)
- break;
- if (sock)
- from = 1; /* OK */
- else {
- for (sock = ntree->outputs.first; sock; sock = sock->next)
- if (sock == fromsock)
- break;
- if (sock)
- from = -1; /* OK but flip */
- }
- }
- if (tonode) {
- for (sock = tonode->inputs.first; sock; sock = sock->next)
- if (sock == tosock)
- break;
- if (sock)
- to = 1; /* OK */
- else {
- for (sock = tonode->outputs.first; sock; sock = sock->next)
- if (sock == tosock)
- break;
- if (sock)
- to = -1; /* OK but flip */
- }
- }
- else if (ntree) {
- /* check tree sockets */
- for (sock = ntree->outputs.first; sock; sock = sock->next)
- if (sock == tosock)
- break;
- if (sock)
- to = 1; /* OK */
- else {
- for (sock = ntree->inputs.first; sock; sock = sock->next)
- if (sock == tosock)
- break;
- if (sock)
- to = -1; /* OK but flip */
- }
- }
+ /* test valid input */
+ BLI_assert(fromnode);
+ BLI_assert(tonode);
- if (from >= 0 && to >= 0) {
+ if (fromsock->in_out == SOCK_OUT && tosock->in_out == SOCK_IN) {
link = MEM_callocN(sizeof(bNodeLink), "link");
if (ntree)
BLI_addtail(&ntree->links, link);
@@ -502,7 +901,8 @@ bNodeLink *nodeAddLink(bNodeTree *ntree, bNode *fromnode, bNodeSocket *fromsock,
link->tonode = tonode;
link->tosock = tosock;
}
- else if (from <= 0 && to <= 0) {
+ else if (fromsock->in_out == SOCK_IN && tosock->in_out == SOCK_OUT) {
+ /* OK but flip */
link = MEM_callocN(sizeof(bNodeLink), "link");
if (ntree)
BLI_addtail(&ntree->links, link);
@@ -546,6 +946,11 @@ void nodeRemSocketLinks(bNodeTree *ntree, bNodeSocket *sock)
ntree->update |= NTREE_UPDATE_LINKS;
}
+int nodeLinkIsHidden(bNodeLink *link)
+{
+ return nodeSocketIsHidden(link->fromsock) || nodeSocketIsHidden(link->tosock);
+}
+
void nodeInternalRelink(bNodeTree *ntree, bNode *node)
{
bNodeLink *link, *link_next;
@@ -662,30 +1067,29 @@ void nodeDetachNode(struct bNode *node)
}
}
-bNodeTree *ntreeAddTree(Main *bmain, const char *name, int type, int nodetype)
+bNodeTree *ntreeAddTree(Main *bmain, const char *name, const char *idname)
{
bNodeTree *ntree;
- bNodeType *ntype;
- /* trees are created as local trees if they of compositor, material or texture type,
+ /* trees are created as local trees for compositor, material or texture nodes,
* node groups and other tree types are created as library data.
*/
- if (ELEM3(type, NTREE_COMPOSIT, NTREE_SHADER, NTREE_TEXTURE) && nodetype == 0) {
+ if (bmain) {
+ ntree= BKE_libblock_alloc(&bmain->nodetree, ID_NT, name);
+ }
+ else {
ntree = MEM_callocN(sizeof(bNodeTree), "new node tree");
- *( (short *)ntree->id.name) = ID_NT; /* not "type", as that is ntree->type */
+ *( (short *)ntree->id.name ) = ID_NT;
BLI_strncpy(ntree->id.name + 2, name, sizeof(ntree->id.name));
}
- else
- ntree = BKE_libblock_alloc(&bmain->nodetree, ID_NT, name);
- ntree->type = type;
- ntree->nodetype = nodetype;
-
- ntreeInitTypes(ntree);
+ /* Types are fully initialized at this point,
+ * if an undefined node is added later this will be reset.
+ */
+ ntree->init |= NTREE_TYPE_INIT;
- ntype = node_get_type(ntree, ntree->nodetype);
- if (ntype && ntype->inittreefunc)
- ntype->inittreefunc(ntree);
+ BLI_strncpy(ntree->idname, idname, sizeof(ntree->idname));
+ ntree_set_typeinfo(ntree, ntreeTypeFind(idname));
return ntree;
}
@@ -699,12 +1103,12 @@ bNodeTree *ntreeAddTree(Main *bmain, const char *name, int type, int nodetype)
* copying for internal use (threads for eg), where you wont want it to modify the
* scene data.
*/
-static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, const short do_id_user, const short do_make_extern)
+static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, const short do_id_user, const short do_make_extern, const short copy_previews)
{
bNodeTree *newtree;
bNode *node /*, *nnode */ /* UNUSED */, *last;
+ bNodeSocket *sock, *oldsock;
bNodeLink *link;
- bNodeSocket *gsock, *oldgsock;
if (ntree == NULL) return NULL;
@@ -747,22 +1151,6 @@ static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, const short do_id_use
break;
}
- /* socket definition for group usage */
- BLI_duplicatelist(&newtree->inputs, &ntree->inputs);
- for (gsock = newtree->inputs.first, oldgsock = ntree->inputs.first; gsock; gsock = gsock->next, oldgsock = oldgsock->next) {
- oldgsock->new_sock = gsock;
- gsock->groupsock = (oldgsock->groupsock ? oldgsock->groupsock->new_sock : NULL);
- gsock->default_value = node_socket_make_default_value(oldgsock->type);
- node_socket_copy_default_value(oldgsock->type, gsock->default_value, oldgsock->default_value);
- }
- BLI_duplicatelist(&newtree->outputs, &ntree->outputs);
- for (gsock = newtree->outputs.first, oldgsock = ntree->outputs.first; gsock; gsock = gsock->next, oldgsock = oldgsock->next) {
- oldgsock->new_sock = gsock;
- gsock->groupsock = (oldgsock->groupsock ? oldgsock->groupsock->new_sock : NULL);
- gsock->default_value = node_socket_make_default_value(oldgsock->type);
- node_socket_copy_default_value(oldgsock->type, gsock->default_value, oldgsock->default_value);
- }
-
/* copy links */
BLI_duplicatelist(&newtree->links, &ntree->links);
for (link = newtree->links.first; link; link = link->next) {
@@ -775,18 +1163,47 @@ static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, const short do_id_use
link->tosock->link = link;
}
+ /* copy interface sockets */
+ BLI_duplicatelist(&newtree->inputs, &ntree->inputs);
+ oldsock = ntree->inputs.first;
+ for (sock = newtree->inputs.first; sock; sock = sock->next, oldsock = oldsock->next)
+ node_socket_copy(sock, oldsock);
+
+ BLI_duplicatelist(&newtree->outputs, &ntree->outputs);
+ oldsock = ntree->outputs.first;
+ for (sock = newtree->outputs.first; sock; sock = sock->next, oldsock = oldsock->next)
+ node_socket_copy(sock, oldsock);
+
+ /* copy preview hash */
+ if (ntree->previews && copy_previews) {
+ bNodeInstanceHashIterator iter;
+
+ newtree->previews = BKE_node_instance_hash_new("node previews");
+
+ NODE_INSTANCE_HASH_ITER(iter, ntree->previews) {
+ bNodeInstanceKey key = BKE_node_instance_hash_iterator_get_key(&iter);
+ bNodePreview *preview = BKE_node_instance_hash_iterator_get_value(&iter);
+ BKE_node_instance_hash_insert(newtree->previews, key, BKE_node_preview_copy(preview));
+ }
+ }
+ else
+ newtree->previews = NULL;
+
/* update node->parent pointers */
for (node = newtree->nodes.first; node; node = node->next) {
if (node->parent)
node->parent = node->parent->new_node;
}
+ /* node tree will generate its own interface type */
+ ntree->interface_type = NULL;
+
return newtree;
}
bNodeTree *ntreeCopyTree_ex(bNodeTree *ntree, const short do_id_user)
{
- return ntreeCopyTree_internal(ntree, do_id_user, TRUE);
+ return ntreeCopyTree_internal(ntree, do_id_user, TRUE, TRUE);
}
bNodeTree *ntreeCopyTree(bNodeTree *ntree)
{
@@ -835,62 +1252,225 @@ void ntreeUserDecrefID(bNodeTree *ntree)
}
}
-/* *************** preview *********** */
-/* if node->preview, then we assume the rect to exist */
+/* *************** Node Preview *********** */
-void nodeFreePreview(bNode *node)
+/* XXX this should be removed eventually ...
+ * Currently BKE functions are modelled closely on previous code,
+ * using BKE_node_preview_init_tree to set up previews for a whole node tree in advance.
+ * This should be left more to the individual node tree implementations.
+ */
+int BKE_node_preview_used(bNode *node)
{
- if (node->preview) {
- if (node->preview->rect)
- MEM_freeN(node->preview->rect);
- MEM_freeN(node->preview);
- node->preview = NULL;
- }
+ /* XXX check for closed nodes? */
+ return (node->typeinfo->flag & NODE_PREVIEW) != 0;
}
-static void node_init_preview(bNode *node, int xsize, int ysize)
+bNodePreview *BKE_node_preview_verify(bNodeInstanceHash *previews, bNodeInstanceKey key, int xsize, int ysize, int create)
{
+ bNodePreview *preview;
- if (node->preview == NULL) {
- node->preview = MEM_callocN(sizeof(bNodePreview), "node preview");
- // printf("added preview %s\n", node->name);
+ preview = BKE_node_instance_hash_lookup(previews, key);
+ if (!preview) {
+ if (create) {
+ preview = MEM_callocN(sizeof(bNodePreview), "node preview");
+ BKE_node_instance_hash_insert(previews, key, preview);
+ }
+ else
+ return NULL;
}
/* node previews can get added with variable size this way */
if (xsize == 0 || ysize == 0)
- return;
+ return preview;
/* sanity checks & initialize */
- if (node->preview->rect) {
- if (node->preview->xsize != xsize && node->preview->ysize != ysize) {
- MEM_freeN(node->preview->rect);
- node->preview->rect = NULL;
+ if (preview->rect) {
+ if (preview->xsize != xsize || preview->ysize != ysize) {
+ MEM_freeN(preview->rect);
+ preview->rect = NULL;
}
}
- if (node->preview->rect == NULL) {
- node->preview->rect = MEM_callocN(4 * xsize + xsize * ysize * sizeof(char) * 4, "node preview rect");
- node->preview->xsize = xsize;
- node->preview->ysize = ysize;
+ if (preview->rect == NULL) {
+ preview->rect = MEM_callocN(4 * xsize + xsize * ysize * sizeof(char) * 4, "node preview rect");
+ preview->xsize = xsize;
+ preview->ysize = ysize;
}
/* no clear, makes nicer previews */
+
+ return preview;
}
-void ntreeInitPreview(bNodeTree *ntree, int xsize, int ysize)
+bNodePreview *BKE_node_preview_copy(bNodePreview *preview)
+{
+ bNodePreview *new_preview = MEM_dupallocN(preview);
+ if (preview->rect)
+ new_preview->rect = MEM_dupallocN(preview->rect);
+ return new_preview;
+}
+
+void BKE_node_preview_free(bNodePreview *preview)
+{
+ if (preview->rect)
+ MEM_freeN(preview->rect);
+ MEM_freeN(preview);
+}
+
+static void node_preview_init_tree_recursive(bNodeInstanceHash *previews, bNodeTree *ntree, bNodeInstanceKey parent_key, int xsize, int ysize, int create)
{
bNode *node;
-
- if (ntree == NULL)
+ for (node = ntree->nodes.first; node; node = node->next) {
+ bNodeInstanceKey key = BKE_node_instance_key(parent_key, ntree, node);
+
+ if (BKE_node_preview_used(node)) {
+ node->preview_xsize = xsize;
+ node->preview_ysize = ysize;
+
+ BKE_node_preview_verify(previews, key, xsize, ysize, create);
+ }
+
+ if (node->type == NODE_GROUP)
+ node_preview_init_tree_recursive(previews, (bNodeTree *)node->id, key, xsize, ysize, create);
+ }
+}
+
+void BKE_node_preview_init_tree(bNodeTree *ntree, int xsize, int ysize, int create_previews)
+{
+ if (!ntree)
return;
+ if (!ntree->previews)
+ ntree->previews = BKE_node_instance_hash_new("node previews");
+
+ node_preview_init_tree_recursive(ntree->previews, ntree, NODE_INSTANCE_KEY_BASE, xsize, ysize, create_previews);
+}
+
+static void node_preview_tag_used_recursive(bNodeInstanceHash *previews, bNodeTree *ntree, bNodeInstanceKey parent_key)
+{
+ bNode *node;
for (node = ntree->nodes.first; node; node = node->next) {
- if (node->typeinfo->flag & NODE_PREVIEW) /* hrms, check for closed nodes? */
- node_init_preview(node, xsize, ysize);
- if (node->type == NODE_GROUP && (node->flag & NODE_GROUP_EDIT))
- ntreeInitPreview((bNodeTree *)node->id, xsize, ysize);
+ bNodeInstanceKey key = BKE_node_instance_key(parent_key, ntree, node);
+
+ if (BKE_node_preview_used(node))
+ BKE_node_instance_hash_tag_key(previews, key);
+
+ if (node->type == NODE_GROUP)
+ node_preview_tag_used_recursive(previews, (bNodeTree *)node->id, key);
+ }
+}
+
+void BKE_node_preview_remove_unused(bNodeTree *ntree)
+{
+ if (!ntree || !ntree->previews)
+ return;
+
+ /* use the instance hash functions for tagging and removing unused previews */
+ BKE_node_instance_hash_clear_tags(ntree->previews);
+ node_preview_tag_used_recursive(ntree->previews, ntree, NODE_INSTANCE_KEY_BASE);
+
+ BKE_node_instance_hash_remove_untagged(ntree->previews, (bNodeInstanceValueFP)BKE_node_preview_free);
+}
+
+void BKE_node_preview_free_tree(bNodeTree *ntree)
+{
+ if (!ntree)
+ return;
+
+ if (ntree->previews) {
+ BKE_node_instance_hash_free(ntree->previews, (bNodeInstanceValueFP)BKE_node_preview_free);
+ ntree->previews = NULL;
+ }
+}
+
+void BKE_node_preview_clear(bNodePreview *preview)
+{
+ if (preview && preview->rect)
+ memset(preview->rect, 0, MEM_allocN_len(preview->rect));
+}
+
+void BKE_node_preview_clear_tree(bNodeTree *ntree)
+{
+ bNodeInstanceHashIterator iter;
+
+ if (!ntree || !ntree->previews)
+ return;
+
+ NODE_INSTANCE_HASH_ITER(iter, ntree->previews) {
+ bNodePreview *preview = BKE_node_instance_hash_iterator_get_value(&iter);
+ BKE_node_preview_clear(preview);
+ }
+}
+
+static void node_preview_sync(bNodePreview *to, bNodePreview *from)
+{
+ /* sizes should have been initialized by BKE_node_preview_init_tree */
+ BLI_assert(to->xsize == from->xsize && to->ysize == from->ysize);
+
+ /* copy over contents of previews */
+ if (to->rect && from->rect) {
+ int xsize = to->xsize;
+ int ysize = to->ysize;
+ memcpy(to->rect, from->rect, 4 * xsize + xsize * ysize * sizeof(char) * 4);
}
}
+void BKE_node_preview_sync_tree(bNodeTree *to_ntree, bNodeTree *from_ntree)
+{
+ bNodeInstanceHash *from_previews = from_ntree->previews;
+ bNodeInstanceHash *to_previews = to_ntree->previews;
+ bNodeInstanceHashIterator iter;
+
+ if (!from_previews || !to_previews)
+ return;
+
+ NODE_INSTANCE_HASH_ITER(iter, from_previews) {
+ bNodeInstanceKey key = BKE_node_instance_hash_iterator_get_key(&iter);
+ bNodePreview *from = BKE_node_instance_hash_iterator_get_value(&iter);
+ bNodePreview *to = BKE_node_instance_hash_lookup(to_previews, key);
+
+ if (from && to)
+ node_preview_sync(to, from);
+ }
+}
+
+void BKE_node_preview_merge_tree(bNodeTree *to_ntree, bNodeTree *from_ntree)
+{
+ /* free old previews */
+ if (to_ntree->previews)
+ BKE_node_instance_hash_free(to_ntree->previews, (bNodeInstanceValueFP)BKE_node_preview_free);
+
+ /* transfer previews */
+ to_ntree->previews = from_ntree->previews;
+ from_ntree->previews = NULL;
+
+ /* clean up, in case any to_ntree nodes have been removed */
+ BKE_node_preview_remove_unused(to_ntree);
+}
+
+/* hack warning! this function is only used for shader previews, and
+ * since it gets called multiple times per pixel for Ztransp we only
+ * add the color once. Preview gets cleared before it starts render though */
+void BKE_node_preview_set_pixel(bNodePreview *preview, const float col[4], int x, int y, int do_manage)
+{
+ if (preview) {
+ if (x >= 0 && y >= 0) {
+ if (x < preview->xsize && y < preview->ysize) {
+ unsigned char *tar = preview->rect + 4 * ((preview->xsize * y) + x);
+
+ if (do_manage) {
+ linearrgb_to_srgb_uchar4(tar, col);
+ }
+ else {
+ rgba_float_to_uchar(tar, col);
+ }
+ }
+ //else printf("prv out bound x y %d %d\n", x, y);
+ }
+ //else printf("prv out bound x y %d %d\n", x, y);
+ }
+}
+
+#if 0
static void nodeClearPreview(bNode *node)
{
if (node->preview && node->preview->rect)
@@ -908,7 +1488,7 @@ void ntreeClearPreview(bNodeTree *ntree)
for (node = ntree->nodes.first; node; node = node->next) {
if (node->typeinfo->flag & NODE_PREVIEW)
nodeClearPreview(node);
- if (node->type == NODE_GROUP && (node->flag & NODE_GROUP_EDIT))
+ if (node->type == NODE_GROUP)
ntreeClearPreview((bNodeTree *)node->id);
}
}
@@ -936,6 +1516,7 @@ void nodeAddToPreview(bNode *node, const float col[4], int x, int y, int do_mana
//else printf("prv out bound x y %d %d\n", x, y);
}
}
+#endif
/* ************** Free stuff ********** */
@@ -985,45 +1566,54 @@ void nodeFreeNode(bNodeTree *ntree, bNode *node)
{
bNodeSocket *sock, *nextsock;
+ /* extra free callback */
+ if (node->typeinfo && node->typeinfo->freefunc_api) {
+ PointerRNA ptr;
+ RNA_pointer_create((ID *)ntree, &RNA_Node, node, &ptr);
+
+ node->typeinfo->freefunc_api(&ptr);
+ }
+
+ /* since it is called while free database, node->id is undefined */
+
/* can be called for nodes outside a node tree (e.g. clipboard) */
if (ntree) {
- bNodeTreeType *treetype = ntreeGetType(ntree->type);
-
/* remove all references to this node */
nodeUnlinkNode(ntree, node);
node_unlink_attached(ntree, node);
-
+
BLI_remlink(&ntree->nodes, node);
-
- if (treetype->free_node_cache)
- treetype->free_node_cache(ntree, node);
+
+ if (ntree->typeinfo && ntree->typeinfo->free_node_cache)
+ ntree->typeinfo->free_node_cache(ntree, node);
/* texture node has bad habit of keeping exec data around */
if (ntree->type == NTREE_TEXTURE && ntree->execdata) {
- ntreeTexEndExecTree(ntree->execdata, 1);
+ ntreeTexEndExecTree(ntree->execdata);
ntree->execdata = NULL;
}
+
+ if(node->typeinfo && node->typeinfo->freefunc)
+ node->typeinfo->freefunc(node);
}
- /* since it is called while free database, node->id is undefined */
-
- if (node->typeinfo && node->typeinfo->freestoragefunc)
- node->typeinfo->freestoragefunc(node);
-
for (sock = node->inputs.first; sock; sock = nextsock) {
nextsock = sock->next;
- node_socket_free_default_value(sock->type, sock->default_value);
+ node_socket_free(ntree, sock, node);
MEM_freeN(sock);
}
for (sock = node->outputs.first; sock; sock = nextsock) {
nextsock = sock->next;
- node_socket_free_default_value(sock->type, sock->default_value);
+ node_socket_free(ntree, sock, node);
MEM_freeN(sock);
}
BLI_freelistN(&node->internal_links);
- nodeFreePreview(node);
+ if (node->prop) {
+ IDP_FreeProperty(node->prop);
+ MEM_freeN(node->prop);
+ }
MEM_freeN(node);
@@ -1031,12 +1621,24 @@ void nodeFreeNode(bNodeTree *ntree, bNode *node)
ntree->update |= NTREE_UPDATE_NODES;
}
+static void node_socket_interface_free(bNodeTree *UNUSED(ntree), bNodeSocket *sock)
+{
+ if (sock->prop) {
+ IDP_FreeProperty(sock->prop);
+ MEM_freeN(sock->prop);
+ }
+
+ /* can be left over from old files */
+ if (sock->default_value)
+ MEM_freeN(sock->default_value);
+}
+
/* do not free ntree itself here, BKE_libblock_free calls this function too */
void ntreeFreeTree_ex(bNodeTree *ntree, const short do_id_user)
{
bNodeTree *tntree;
bNode *node, *next;
- bNodeSocket *sock;
+ bNodeSocket *sock, *nextsock;
if (ntree == NULL) return;
@@ -1048,15 +1650,18 @@ void ntreeFreeTree_ex(bNodeTree *ntree, const short do_id_user)
if (ntree->execdata) {
switch (ntree->type) {
case NTREE_SHADER:
- ntreeShaderEndExecTree(ntree->execdata, 1);
+ ntreeShaderEndExecTree(ntree->execdata);
break;
case NTREE_TEXTURE:
- ntreeTexEndExecTree(ntree->execdata, 1);
+ ntreeTexEndExecTree(ntree->execdata);
ntree->execdata = NULL;
break;
}
}
+ /* unregister associated RNA types */
+ ntreeInterfaceTypeFree(ntree);
+
BKE_free_animdata((ID *)ntree);
id_us_min((ID *)ntree->gpd);
@@ -1082,13 +1687,23 @@ void ntreeFreeTree_ex(bNodeTree *ntree, const short do_id_user)
nodeFreeNode(ntree, node);
}
+
+ /* free interface sockets */
+ for (sock = ntree->inputs.first; sock; sock = nextsock) {
+ nextsock = sock->next;
+ node_socket_interface_free(ntree, sock);
+ MEM_freeN(sock);
+ }
+ for (sock = ntree->outputs.first; sock; sock = nextsock) {
+ nextsock = sock->next;
+ node_socket_interface_free(ntree, sock);
+ MEM_freeN(sock);
+ }
- for (sock = ntree->inputs.first; sock; sock = sock->next)
- node_socket_free_default_value(sock->type, sock->default_value);
- BLI_freelistN(&ntree->inputs);
- for (sock = ntree->outputs.first; sock; sock = sock->next)
- node_socket_free_default_value(sock->type, sock->default_value);
- BLI_freelistN(&ntree->outputs);
+ /* free preview hash */
+ if (ntree->previews) {
+ BKE_node_instance_hash_free(ntree->previews, (bNodeInstanceValueFP)BKE_node_preview_free);
+ }
/* if ntree is not part of library, free the libblock data explicitly */
for (tntree = G.main->nodetree.first; tntree; tntree = tntree->id.next)
@@ -1106,13 +1721,10 @@ void ntreeFreeTree(bNodeTree *ntree)
void ntreeFreeCache(bNodeTree *ntree)
{
- bNodeTreeType *treetype;
-
if (ntree == NULL) return;
- treetype = ntreeGetType(ntree->type);
- if (treetype->free_cache)
- treetype->free_cache(ntree);
+ if (ntree->typeinfo->free_cache)
+ ntree->typeinfo->free_cache(ntree);
}
void ntreeSetOutput(bNodeTree *ntree)
@@ -1162,6 +1774,24 @@ void ntreeSetOutput(bNodeTree *ntree)
if (output == 0)
node->flag |= NODE_DO_OUTPUT;
}
+
+ /* group node outputs use this flag too */
+ if (node->type == NODE_GROUP_OUTPUT) {
+ bNode *tnode;
+ int output = 0;
+
+ for (tnode = ntree->nodes.first; tnode; tnode = tnode->next) {
+ if (tnode->type == NODE_GROUP_OUTPUT) {
+ if (tnode->flag & NODE_DO_OUTPUT) {
+ output++;
+ if (output > 1)
+ tnode->flag &= ~NODE_DO_OUTPUT;
+ }
+ }
+ }
+ if (output == 0)
+ node->flag |= NODE_DO_OUTPUT;
+ }
}
/* here we could recursively set which nodes have to be done,
@@ -1180,52 +1810,10 @@ bNodeTree *ntreeFromID(ID *id)
}
}
-typedef struct MakeLocalCallData {
- ID *group_id;
- ID *new_id;
- int lib, local;
-} MakeLocalCallData;
-
-static void ntreeMakeLocal_CheckLocal(void *calldata, ID *owner_id, bNodeTree *ntree)
-{
- MakeLocalCallData *cd = (MakeLocalCallData *)calldata;
- bNode *node;
-
- /* find if group is in tree */
- for (node = ntree->nodes.first; node; node = node->next) {
- if (node->id == cd->group_id) {
- if (owner_id->lib) {
- cd->lib = TRUE;
- }
- else {
- cd->local = TRUE;
- }
- }
- }
-}
-
-static void ntreeMakeLocal_LinkNew(void *calldata, ID *owner_id, bNodeTree *ntree)
-{
- MakeLocalCallData *cd = (MakeLocalCallData *)calldata;
- bNode *node;
-
- /* find if group is in tree */
- for (node = ntree->nodes.first; node; node = node->next) {
- if (node->id == cd->group_id) {
- if (owner_id->lib == NULL) {
- node->id = cd->new_id;
- cd->new_id->us++;
- cd->group_id->us--;
- }
- }
- }
-}
-
void ntreeMakeLocal(bNodeTree *ntree)
{
Main *bmain = G.main;
- bNodeTreeType *treetype = ntreeGetType(ntree->type);
- MakeLocalCallData cd;
+ int lib = FALSE, local = FALSE;
/* - only lib users: do nothing
* - only local users: set flag
@@ -1239,26 +1827,42 @@ void ntreeMakeLocal(bNodeTree *ntree)
}
/* now check users of groups... again typedepending, callback... */
- cd.group_id = &ntree->id;
- cd.new_id = NULL;
- cd.local = 0;
- cd.lib = 0;
-
- treetype->foreach_nodetree(G.main, &cd, &ntreeMakeLocal_CheckLocal);
+ FOREACH_NODETREE(G.main, tntree, owner_id) {
+ bNode *node;
+ /* find if group is in tree */
+ for (node = tntree->nodes.first; node; node = node->next) {
+ if (node->id == (ID *)ntree) {
+ if (owner_id->lib)
+ lib = TRUE;
+ else
+ local = TRUE;
+ }
+ }
+ } FOREACH_NODETREE_END
/* if all users are local, we simply make tree local */
- if (cd.local && cd.lib == 0) {
+ if (local && !lib) {
id_clear_lib_data(bmain, (ID *)ntree);
}
- else if (cd.local && cd.lib) {
+ else if (local && lib) {
/* this is the mixed case, we copy the tree and assign it to local users */
bNodeTree *newtree = ntreeCopyTree(ntree);
newtree->id.us = 0;
-
- cd.new_id = &newtree->id;
- treetype->foreach_nodetree(G.main, &cd, &ntreeMakeLocal_LinkNew);
+ FOREACH_NODETREE(G.main, tntree, owner_id) {
+ bNode *node;
+ /* find if group is in tree */
+ for (node = tntree->nodes.first; node; node = node->next) {
+ if (node->id == (ID *)ntree) {
+ if (owner_id->lib == NULL) {
+ node->id = (ID *)newtree;
+ newtree->id.us++;
+ ntree->id.us--;
+ }
+ }
+ }
+ } FOREACH_NODETREE_END
}
}
@@ -1283,90 +1887,326 @@ int ntreeOutputExists(bNode *node, bNodeSocket *testsock)
/* returns localized tree for execution in threads */
bNodeTree *ntreeLocalize(bNodeTree *ntree)
{
- bNodeTreeType *ntreetype = ntreeGetType(ntree->type);
-
- bNodeTree *ltree;
- bNode *node;
+ if (ntreeIsValid(ntree)) {
+ bNodeTree *ltree;
+ bNode *node;
+
+ bAction *action_backup = NULL, *tmpact_backup = NULL;
+
+ /* Workaround for copying an action on each render!
+ * set action to NULL so animdata actions don't get copied */
+ AnimData *adt = BKE_animdata_from_id(&ntree->id);
+
+ if (adt) {
+ action_backup = adt->action;
+ tmpact_backup = adt->tmpact;
+
+ adt->action = NULL;
+ adt->tmpact = NULL;
+ }
- bAction *action_backup = NULL, *tmpact_backup = NULL;
+ /* Make full copy.
+ * Note: previews are not copied here.
+ */
+ ltree = ntreeCopyTree_internal(ntree, FALSE, FALSE, FALSE);
+
+ if (adt) {
+ AnimData *ladt = BKE_animdata_from_id(&ltree->id);
+
+ adt->action = ladt->action = action_backup;
+ adt->tmpact = ladt->tmpact = tmpact_backup;
+
+ if (action_backup) action_backup->id.us++;
+ if (tmpact_backup) tmpact_backup->id.us++;
+
+ }
+ /* end animdata uglyness */
- /* Workaround for copying an action on each render!
- * set action to NULL so animdata actions don't get copied */
- AnimData *adt = BKE_animdata_from_id(&ntree->id);
+ /* ensures only a single output node is enabled */
+ ntreeSetOutput(ntree);
+
+ for (node = ntree->nodes.first; node; node = node->next) {
+ /* store new_node pointer to original */
+ node->new_node->new_node = node;
+ }
+
+ if (ntree->typeinfo->localize)
+ ntree->typeinfo->localize(ltree, ntree);
+
+ return ltree;
+ }
+ else
+ return NULL;
+}
- if (adt) {
- action_backup = adt->action;
- tmpact_backup = adt->tmpact;
+/* sync local composite with real tree */
+/* local tree is supposed to be running, be careful moving previews! */
+/* is called by jobs manager, outside threads, so it doesnt happen during draw */
+void ntreeLocalSync(bNodeTree *localtree, bNodeTree *ntree)
+{
+ if (localtree && ntreeIsValid(ntree)) {
+ /* XXX syncing was disabled for compositor nodes.
+ * It has to be ensured that there is no concurrent read/write access!
+ * Possibly needs a mutex lock or a flag to disable for certain tree types ...
+ */
+ BKE_node_preview_sync_tree(ntree, localtree);
+
+ if (ntree->typeinfo->local_sync)
+ ntree->typeinfo->local_sync(localtree, ntree);
+ }
+}
- adt->action = NULL;
- adt->tmpact = NULL;
+/* merge local tree results back, and free local tree */
+/* we have to assume the editor already changed completely */
+void ntreeLocalMerge(bNodeTree *localtree, bNodeTree *ntree)
+{
+ if (localtree && ntreeIsValid(ntree)) {
+ BKE_node_preview_merge_tree(ntree, localtree);
+
+ if (ntree->typeinfo->local_merge)
+ ntree->typeinfo->local_merge(localtree, ntree);
+
+ ntreeFreeTree_ex(localtree, FALSE);
+ MEM_freeN(localtree);
}
+}
- /* node copy func */
- ltree = ntreeCopyTree_internal(ntree, FALSE, FALSE);
- if (adt) {
- AnimData *ladt = BKE_animdata_from_id(&ltree->id);
+/* ************ NODE TREE INTERFACE *************** */
- adt->action = ladt->action = action_backup;
- adt->tmpact = ladt->tmpact = tmpact_backup;
+static bNodeSocket *make_socket_template(bNodeTree *ntree, int in_out,
+ const char *idname, const char *name)
+{
+ bNodeSocketType *stype = nodeSocketTypeFind(idname);
+ bNodeSocket *sock;
+ int own_index = ntree->cur_index++;
+
+ if (stype == NULL) {
+ printf("Error: node socket type '%s' undefined\n", idname);
+ return NULL;
+ }
+
+ sock = MEM_callocN(sizeof(bNodeSocket), "socket template");
+ sock->typeinfo= stype;
+ BLI_strncpy(sock->idname, stype->idname, sizeof(sock->idname));
+ sock->in_out = in_out;
+ sock->type = SOCK_CUSTOM; /* int type undefined by default */
+
+ /* assign new unique index */
+ own_index = ntree->cur_index++;
+ /* use the own_index as socket identifier */
+ if (in_out == SOCK_IN)
+ BLI_snprintf(sock->identifier, MAX_NAME, "Input_%d", own_index);
+ else
+ BLI_snprintf(sock->identifier, MAX_NAME, "Output_%d", own_index);
+#ifdef USE_NODE_COMPAT_CUSTOMNODES
+ /* XXX forward compatibility:
+ * own_index is deprecated, but needs to be set here.
+ * Node sockets generally use the identifier string instead now,
+ * but reconstructing own_index in writefile.c would require parsing the identifier string.
+ */
+ sock->own_index = own_index;
+#endif
+
+ sock->limit = (in_out == SOCK_IN ? 1 : 0xFFF);
+
+ BLI_strncpy(sock->name, name, NODE_MAXSTR);
+ sock->storage = NULL;
+ sock->flag |= SOCK_COLLAPSED;
+
+ return sock;
+}
- if (action_backup) action_backup->id.us++;
- if (tmpact_backup) tmpact_backup->id.us++;
-
+bNodeSocket *ntreeFindSocketInterface(bNodeTree *ntree, int in_out, const char *identifier)
+{
+ bNodeSocket *iosock = (in_out == SOCK_IN ? ntree->inputs.first : ntree->outputs.first);
+ for (; iosock; iosock = iosock->next)
+ if (strcmp(iosock->identifier, identifier)==0)
+ return iosock;
+ return NULL;
+}
+
+bNodeSocket *ntreeAddSocketInterface(bNodeTree *ntree, int in_out, const char *idname, const char *name)
+{
+ bNodeSocket *iosock;
+
+ iosock = make_socket_template(ntree, in_out, idname, name);
+ if (in_out == SOCK_IN) {
+ BLI_addtail(&ntree->inputs, iosock);
+ ntree->update |= NTREE_UPDATE_GROUP_IN;
}
- /* end animdata uglyness */
+ else if (in_out == SOCK_OUT) {
+ BLI_addtail(&ntree->outputs, iosock);
+ ntree->update |= NTREE_UPDATE_GROUP_OUT;
+ }
+
+ return iosock;
+}
- /* ensures only a single output node is enabled */
- ntreeSetOutput(ntree);
+bNodeSocket *ntreeInsertSocketInterface(bNodeTree *ntree, int in_out, const char *idname,
+ bNodeSocket *next_sock, const char *name)
+{
+ bNodeSocket *iosock;
+
+ iosock = make_socket_template(ntree, in_out, idname, name);
+ if (in_out == SOCK_IN) {
+ BLI_insertlinkbefore(&ntree->inputs, next_sock, iosock);
+ ntree->update |= NTREE_UPDATE_GROUP_IN;
+ }
+ else if (in_out == SOCK_OUT) {
+ BLI_insertlinkbefore(&ntree->outputs, next_sock, iosock);
+ ntree->update |= NTREE_UPDATE_GROUP_OUT;
+ }
+
+ return iosock;
+}
- for (node = ntree->nodes.first; node; node = node->next) {
- /* store new_node pointer to original */
- node->new_node->new_node = node;
+struct bNodeSocket *ntreeAddSocketInterfaceFromSocket(bNodeTree *ntree, bNode *from_node, bNodeSocket *from_sock)
+{
+ bNodeSocket *iosock = ntreeAddSocketInterface(ntree, from_sock->in_out, from_sock->idname, from_sock->name);
+ if (iosock) {
+ if (iosock->typeinfo->interface_from_socket)
+ iosock->typeinfo->interface_from_socket(ntree, iosock, from_node, from_sock);
}
+ return iosock;
+}
- if (ntreetype->localize)
- ntreetype->localize(ltree, ntree);
+struct bNodeSocket *ntreeInsertSocketInterfaceFromSocket(bNodeTree *ntree, bNodeSocket *next_sock, bNode *from_node, bNodeSocket *from_sock)
+{
+ bNodeSocket *iosock = ntreeInsertSocketInterface(ntree, from_sock->in_out, from_sock->idname, next_sock, from_sock->name);
+ if (iosock) {
+ if (iosock->typeinfo->interface_from_socket)
+ iosock->typeinfo->interface_from_socket(ntree, iosock, from_node, from_sock);
+ }
+ return iosock;
+}
- return ltree;
+void ntreeRemoveSocketInterface(bNodeTree *ntree, bNodeSocket *sock)
+{
+ /* this is fast, this way we don't need an in_out argument */
+ BLI_remlink(&ntree->inputs, sock);
+ BLI_remlink(&ntree->outputs, sock);
+
+ node_socket_interface_free(ntree, sock);
+ MEM_freeN(sock);
+
+ ntree->update |= NTREE_UPDATE_GROUP;
}
-/* sync local composite with real tree */
-/* local tree is supposed to be running, be careful moving previews! */
-/* is called by jobs manager, outside threads, so it doesnt happen during draw */
-void ntreeLocalSync(bNodeTree *localtree, bNodeTree *ntree)
+/* generates a valid RNA identifier from the node tree name */
+static void ntree_interface_identifier_base(bNodeTree *ntree, char *base)
{
- bNodeTreeType *ntreetype = ntreeGetType(ntree->type);
+ /* generate a valid RNA identifier */
+ sprintf(base, "NodeTreeInterface_%s", ntree->id.name+2);
+ RNA_identifier_sanitize(base, FALSE);
+}
- if (ntreetype->local_sync)
- ntreetype->local_sync(localtree, ntree);
+/* check if the identifier is already in use */
+static bool ntree_interface_unique_identifier_check(void *UNUSED(data), const char *identifier)
+{
+ return (RNA_struct_find(identifier) != NULL);
}
-/* merge local tree results back, and free local tree */
-/* we have to assume the editor already changed completely */
-void ntreeLocalMerge(bNodeTree *localtree, bNodeTree *ntree)
+/* generates the actual unique identifier and ui name and description */
+static void ntree_interface_identifier(bNodeTree *ntree, const char *base, char *identifier, int maxlen, char *name, char *description)
{
- bNodeTreeType *ntreetype = ntreeGetType(ntree->type);
- bNode *lnode;
+ /* There is a possibility that different node tree names get mapped to the same identifier
+ * after sanitization (e.g. "SomeGroup_A", "SomeGroup.A" both get sanitized to "SomeGroup_A").
+ * On top of the sanitized id string add a number suffix if necessary to avoid duplicates.
+ */
+ identifier[0] = '\0';
+ BLI_uniquename_cb(ntree_interface_unique_identifier_check, NULL, base, '_', identifier, maxlen);
- /* move over the compbufs and previews */
- for (lnode = localtree->nodes.first; lnode; lnode = lnode->next) {
- if (ntreeNodeExists(ntree, lnode->new_node)) {
- if (lnode->preview && lnode->preview->rect) {
- nodeFreePreview(lnode->new_node);
- lnode->new_node->preview = lnode->preview;
- lnode->preview = NULL;
- }
+ sprintf(name, "Node Tree %s Interface", ntree->id.name+2);
+ sprintf(description, "Interface properties of node group %s", ntree->id.name+2);
+}
+
+static void ntree_interface_type_create(bNodeTree *ntree)
+{
+ StructRNA *srna;
+ bNodeSocket *sock;
+ /* strings are generated from base string + ID name, sizes are sufficient */
+ char base[MAX_ID_NAME+64], identifier[MAX_ID_NAME+64], name[MAX_ID_NAME+64], description[MAX_ID_NAME+64];
+
+ /* generate a valid RNA identifier */
+ ntree_interface_identifier_base(ntree, base);
+ ntree_interface_identifier(ntree, base, identifier, sizeof(identifier), name, description);
+
+ /* register a subtype of PropertyGroup */
+ srna = RNA_def_struct_ptr(&BLENDER_RNA, identifier, &RNA_PropertyGroup);
+ RNA_def_struct_ui_text(srna, name, description);
+ RNA_def_struct_duplicate_pointers(srna);
+
+ /* associate the RNA type with the node tree */
+ ntree->interface_type = srna;
+ RNA_struct_blender_type_set(srna, ntree);
+
+ /* add socket properties */
+ for (sock = ntree->inputs.first; sock; sock = sock->next) {
+ bNodeSocketType *stype = sock->typeinfo;
+ if (stype && stype->interface_register_properties)
+ stype->interface_register_properties(ntree, sock, srna);
+ }
+ for (sock = ntree->outputs.first; sock; sock = sock->next) {
+ bNodeSocketType *stype = sock->typeinfo;
+ if (stype && stype->interface_register_properties)
+ stype->interface_register_properties(ntree, sock, srna);
+ }
+}
+
+StructRNA *ntreeInterfaceTypeGet(bNodeTree *ntree, int create)
+{
+ if (ntree->interface_type) {
+ /* strings are generated from base string + ID name, sizes are sufficient */
+ char base[MAX_ID_NAME+64], identifier[MAX_ID_NAME+64], name[MAX_ID_NAME+64], description[MAX_ID_NAME+64];
+
+ /* A bit of a hack: when changing the ID name, update the RNA type identifier too,
+ * so that the names match. This is not strictly necessary to keep it working,
+ * but better for identifying associated NodeTree blocks and RNA types.
+ */
+ StructRNA *srna = ntree->interface_type;
+
+ ntree_interface_identifier_base(ntree, base);
+
+ /* RNA identifier may have a number suffix, but should start with the idbase string */
+ if (strncmp(RNA_struct_identifier(srna), base, sizeof(base)) != 0) {
+ /* generate new unique RNA identifier from the ID name */
+ ntree_interface_identifier(ntree, base, identifier, sizeof(identifier), name, description);
+
+ /* rename the RNA type */
+ RNA_def_struct_free_pointers(srna);
+ RNA_def_struct_identifier(srna, identifier);
+ RNA_def_struct_ui_text(srna, name, description);
+ RNA_def_struct_duplicate_pointers(srna);
}
}
+ else if (create) {
+ ntree_interface_type_create(ntree);
+ }
+
+ return ntree->interface_type;
+}
- if (ntreetype->local_merge)
- ntreetype->local_merge(localtree, ntree);
+void ntreeInterfaceTypeFree(bNodeTree *ntree)
+{
+ if (ntree->interface_type) {
+ RNA_struct_free(&BLENDER_RNA, ntree->interface_type);
+ ntree->interface_type = NULL;
+ }
+}
- ntreeFreeTree_ex(localtree, FALSE);
- MEM_freeN(localtree);
+void ntreeInterfaceTypeUpdate(bNodeTree *ntree)
+{
+ /* XXX it would be sufficient to just recreate all properties
+ * instead of re-registering the whole struct type,
+ * but there is currently no good way to do this in the RNA functions.
+ * Overhead should be negligible.
+ */
+ ntreeInterfaceTypeFree(ntree);
+ ntree_interface_type_create(ntree);
}
+
/* ************ find stuff *************** */
int ntreeHasType(bNodeTree *ntree, int type)
@@ -1420,25 +2260,25 @@ bNode *nodeGetActive(bNodeTree *ntree)
/* two active flags, ID nodes have special flag for buttons display */
bNode *nodeGetActiveID(bNodeTree *ntree, short idtype)
{
- bNode *node;
+ bNode *node, *tnode;
if (ntree == NULL) return NULL;
- /* check for group edit */
- for (node = ntree->nodes.first; node; node = node->next)
- if (node->flag & NODE_GROUP_EDIT)
- break;
-
- if (node)
- ntree = (bNodeTree *)node->id;
-
- /* now find active node with this id */
for (node = ntree->nodes.first; node; node = node->next)
if (node->id && GS(node->id->name) == idtype)
if (node->flag & NODE_ACTIVE_ID)
- break;
-
- return node;
+ return node;
+
+ /* no node with active ID in this tree, look inside groups */
+ for(node= ntree->nodes.first; node; node= node->next) {
+ if(node->type==NODE_GROUP) {
+ tnode = nodeGetActiveID((bNodeTree*)node->id, idtype);
+ if (tnode)
+ return tnode;
+ }
+ }
+
+ return NULL;
}
int nodeSetActiveID(bNodeTree *ntree, short idtype, ID *id)
@@ -1448,15 +2288,6 @@ int nodeSetActiveID(bNodeTree *ntree, short idtype, ID *id)
if (ntree == NULL) return ok;
- /* check for group edit */
- for (node = ntree->nodes.first; node; node = node->next)
- if (node->flag & NODE_GROUP_EDIT)
- break;
-
- if (node)
- ntree = (bNodeTree *)node->id;
-
- /* now find active node with this id */
for (node = ntree->nodes.first; node; node = node->next) {
if (node->id && GS(node->id->name) == idtype) {
if (id && ok == FALSE && node->id == id) {
@@ -1469,6 +2300,15 @@ int nodeSetActiveID(bNodeTree *ntree, short idtype, ID *id)
}
}
+ /* update all groups linked from here
+ * if active ID node has been found already,
+ * just pass NULL so other matching nodes are deactivated.
+ */
+ for(node= ntree->nodes.first; node; node= node->next) {
+ if(node->type==NODE_GROUP)
+ ok |= nodeSetActiveID((bNodeTree*)node->id, idtype, (ok==FALSE ? id : NULL));
+ }
+
return ok;
}
@@ -1485,6 +2325,24 @@ void nodeClearActiveID(bNodeTree *ntree, short idtype)
node->flag &= ~NODE_ACTIVE_ID;
}
+void nodeSetSelected(bNode *node, int select)
+{
+ if (select) {
+ node->flag |= NODE_SELECT;
+ }
+ else {
+ bNodeSocket *sock;
+
+ node->flag &= ~NODE_SELECT;
+
+ /* deselect sockets too */
+ for (sock=node->inputs.first; sock; sock=sock->next)
+ sock->flag &= ~NODE_SELECT;
+ for (sock=node->outputs.first; sock; sock=sock->next)
+ sock->flag &= ~NODE_SELECT;
+ }
+}
+
void nodeClearActive(bNodeTree *ntree)
{
bNode *node;
@@ -1495,7 +2353,6 @@ void nodeClearActive(bNodeTree *ntree)
node->flag &= ~(NODE_ACTIVE | NODE_ACTIVE_ID);
}
-
/* two active flags, ID nodes have special flag for buttons display */
void nodeSetActive(bNodeTree *ntree, bNode *node)
{
@@ -1525,19 +2382,6 @@ int nodeSocketIsHidden(bNodeSocket *sock)
return ((sock->flag & (SOCK_HIDDEN | SOCK_UNAVAIL)) != 0);
}
-void nodeSocketSetType(bNodeSocket *sock, int type)
-{
- int old_type = sock->type;
- void *old_default_value = sock->default_value;
-
- sock->type = type;
-
- sock->default_value = node_socket_make_default_value(sock->type);
- node_socket_init_default_value(type, sock->default_value);
- node_socket_convert_default_value(sock->type, sock->default_value, old_type, old_default_value);
- node_socket_free_default_value(old_type, old_default_value);
-}
-
/* ************** Node Clipboard *********** */
#define USE_NODE_CB_VALIDATE
@@ -1692,6 +2536,163 @@ int BKE_node_clipboard_get_type(void)
return node_clipboard.type;
}
+
+/* Node Instance Hash */
+
+/* magic number for initial hash key */
+const bNodeInstanceKey NODE_INSTANCE_KEY_BASE = {5381};
+
+/* Generate a hash key from ntree and node names
+ * Uses the djb2 algorithm with xor by Bernstein:
+ * http://www.cse.yorku.ca/~oz/hash.html
+ */
+static bNodeInstanceKey node_hash_int_str(bNodeInstanceKey hash, const char *str)
+{
+ char c;
+
+ while ((c = *str++))
+ hash.value = ((hash.value << 5) + hash.value) ^ c; /* (hash * 33) ^ c */
+
+ /* separator '\0' character, to avoid ambiguity from concatenated strings */
+ hash.value = (hash.value << 5) + hash.value; /* hash * 33 */
+
+ return hash;
+}
+
+bNodeInstanceKey BKE_node_instance_key(bNodeInstanceKey parent_key, bNodeTree *ntree, bNode *node)
+{
+ bNodeInstanceKey key;
+
+ key = node_hash_int_str(parent_key, ntree->id.name+2);
+
+ if (node)
+ key = node_hash_int_str(key, node->name);
+
+ return key;
+}
+
+static unsigned int node_instance_hash_key(const void *key)
+{
+ return ((const bNodeInstanceKey *)key)->value;
+}
+
+static int node_instance_hash_key_cmp(const void *a, const void *b)
+{
+ unsigned int value_a = ((const bNodeInstanceKey *)a)->value;
+ unsigned int value_b = ((const bNodeInstanceKey *)b)->value;
+ if (value_a == value_b)
+ return 0;
+ else if (value_a < value_b)
+ return -1;
+ else
+ return 1;
+}
+
+bNodeInstanceHash *BKE_node_instance_hash_new(const char *info)
+{
+ bNodeInstanceHash *hash = MEM_mallocN(sizeof(bNodeInstanceHash), info);
+ hash->ghash = BLI_ghash_new(node_instance_hash_key, node_instance_hash_key_cmp, "node instance hash ghash");
+ return hash;
+}
+
+void BKE_node_instance_hash_free(bNodeInstanceHash *hash, bNodeInstanceValueFP valfreefp)
+{
+ BLI_ghash_free(hash->ghash, NULL, (GHashValFreeFP)valfreefp);
+ MEM_freeN(hash);
+}
+
+void BKE_node_instance_hash_insert(bNodeInstanceHash *hash, bNodeInstanceKey key, void *value)
+{
+ bNodeInstanceHashEntry *entry = value;
+ entry->key = key;
+ entry->tag = 0;
+ BLI_ghash_insert(hash->ghash, &entry->key, value);
+}
+
+void *BKE_node_instance_hash_lookup(bNodeInstanceHash *hash, bNodeInstanceKey key)
+{
+ return BLI_ghash_lookup(hash->ghash, &key);
+}
+
+int BKE_node_instance_hash_remove(bNodeInstanceHash *hash, bNodeInstanceKey key, bNodeInstanceValueFP valfreefp)
+{
+ return BLI_ghash_remove(hash->ghash, &key, NULL, (GHashValFreeFP)valfreefp);
+}
+
+void BKE_node_instance_hash_clear(bNodeInstanceHash *hash, bNodeInstanceValueFP valfreefp)
+{
+ BLI_ghash_clear(hash->ghash, NULL, (GHashValFreeFP)valfreefp);
+}
+
+void *BKE_node_instance_hash_pop(bNodeInstanceHash *hash, bNodeInstanceKey key)
+{
+ return BLI_ghash_pop(hash->ghash, &key, NULL);
+}
+
+int BKE_node_instance_hash_haskey(bNodeInstanceHash *hash, bNodeInstanceKey key)
+{
+ return BLI_ghash_haskey(hash->ghash, &key);
+}
+
+int BKE_node_instance_hash_size(bNodeInstanceHash *hash)
+{
+ return BLI_ghash_size(hash->ghash);
+}
+
+void BKE_node_instance_hash_clear_tags(bNodeInstanceHash *hash)
+{
+ bNodeInstanceHashIterator iter;
+
+ NODE_INSTANCE_HASH_ITER(iter, hash) {
+ bNodeInstanceHashEntry *value = BKE_node_instance_hash_iterator_get_value(&iter);
+
+ value->tag = 0;
+ }
+}
+
+void BKE_node_instance_hash_tag(bNodeInstanceHash *UNUSED(hash), void *value)
+{
+ bNodeInstanceHashEntry *entry = value;
+ entry->tag = 1;
+}
+
+int BKE_node_instance_hash_tag_key(bNodeInstanceHash *hash, bNodeInstanceKey key)
+{
+ bNodeInstanceHashEntry *entry = BKE_node_instance_hash_lookup(hash, key);
+
+ if (entry) {
+ entry->tag = 1;
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+void BKE_node_instance_hash_remove_untagged(bNodeInstanceHash *hash, bNodeInstanceValueFP valfreefp)
+{
+ /* NOTE: Hash must not be mutated during iterating!
+ * Store tagged entries in a separate list and remove items afterward.
+ */
+ bNodeInstanceKey *untagged = MEM_mallocN(sizeof(bNodeInstanceKey)*BKE_node_instance_hash_size(hash), "temporary node instance key list");
+ bNodeInstanceHashIterator iter;
+ int num_untagged, i;
+
+ num_untagged = 0;
+ NODE_INSTANCE_HASH_ITER(iter, hash) {
+ bNodeInstanceHashEntry *value = BKE_node_instance_hash_iterator_get_value(&iter);
+
+ if (!value->tag)
+ untagged[num_untagged++] = BKE_node_instance_hash_iterator_get_key(&iter);
+ }
+
+ for (i = 0; i < num_untagged; ++i) {
+ BKE_node_instance_hash_remove(hash, untagged[i], valfreefp);
+ }
+
+ MEM_freeN(untagged);
+}
+
+
/* ************** dependency stuff *********** */
/* node is guaranteed to be not checked before */
@@ -1707,12 +2708,10 @@ static int node_get_deplist_recurs(bNodeTree *ntree, bNode *node, bNode ***nsort
for (link = ntree->links.first; link; link = link->next) {
if (link->tonode == node) {
fromnode = link->fromnode;
- if (fromnode) {
- if (fromnode->done == 0)
- fromnode->level = node_get_deplist_recurs(ntree, fromnode, nsort);
- if (fromnode->level <= level)
- level = fromnode->level - 1;
- }
+ if (fromnode->done == 0)
+ fromnode->level = node_get_deplist_recurs(ntree, fromnode, nsort);
+ if (fromnode->level <= level)
+ level = fromnode->level - 1;
}
}
@@ -1792,13 +2791,6 @@ static void ntree_update_link_pointers(bNodeTree *ntree)
sock->flag &= ~SOCK_IN_USE;
}
}
- for (sock = ntree->inputs.first; sock; sock = sock->next) {
- sock->flag &= ~SOCK_IN_USE;
- }
- for (sock = ntree->outputs.first; sock; sock = sock->next) {
- sock->link = NULL;
- sock->flag &= ~SOCK_IN_USE;
- }
for (link = ntree->links.first; link; link = link->next) {
link->tosock->link = link;
@@ -1810,144 +2802,133 @@ static void ntree_update_link_pointers(bNodeTree *ntree)
static void ntree_validate_links(bNodeTree *ntree)
{
- bNodeTreeType *ntreetype = ntreeGetType(ntree->type);
bNodeLink *link;
for (link = ntree->links.first; link; link = link->next) {
link->flag |= NODE_LINK_VALID;
if (link->fromnode && link->tonode && link->fromnode->level <= link->tonode->level)
link->flag &= ~NODE_LINK_VALID;
- else if (ntreetype->validate_link) {
- if (!ntreetype->validate_link(ntree, link))
+ else if (ntree->typeinfo->validate_link) {
+ if (!ntree->typeinfo->validate_link(ntree, link))
link->flag &= ~NODE_LINK_VALID;
}
}
}
-static void ntree_verify_nodes_cb(void *calldata, struct ID *UNUSED(owner_id), struct bNodeTree *ntree)
-{
- ID *id = (ID *)calldata;
- bNode *node;
-
- for (node = ntree->nodes.first; node; node = node->next)
- if (node->typeinfo->verifyfunc)
- node->typeinfo->verifyfunc(ntree, node, id);
-}
-
void ntreeVerifyNodes(struct Main *main, struct ID *id)
{
- bNodeTreeType *ntreetype;
- bNodeTree *ntree;
- int n;
-
- for (n = 0; n < NUM_NTREE_TYPES; ++n) {
- ntreetype = ntreeGetType(n);
- if (ntreetype && ntreetype->foreach_nodetree)
- ntreetype->foreach_nodetree(main, id, ntree_verify_nodes_cb);
- }
- for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next)
- ntree_verify_nodes_cb(id, NULL, ntree);
+ FOREACH_NODETREE(main, ntree, owner_id) {
+ bNode *node;
+
+ if (!ntreeIsValid(ntree))
+ return;
+
+ for (node = ntree->nodes.first; node; node = node->next)
+ if (node->typeinfo && node->typeinfo->verifyfunc)
+ node->typeinfo->verifyfunc(ntree, node, id);
+ } FOREACH_NODETREE_END
}
void ntreeUpdateTree(bNodeTree *ntree)
{
- bNodeTreeType *ntreetype = ntreeGetType(ntree->type);
bNode *node;
+ /* avoid reentrant updates, can be caused by RNA update callbacks */
+ if (ntree->is_updating)
+ return;
+ ntree->is_updating = TRUE;
+
+ /* only if types are initialized */
+ if (!ntreeIsValid(ntree))
+ return;
+
if (ntree->update & (NTREE_UPDATE_LINKS | NTREE_UPDATE_NODES)) {
/* set the bNodeSocket->link pointers */
ntree_update_link_pointers(ntree);
-
- /* update the node level from link dependencies */
- ntree_update_node_level(ntree);
}
/* update individual nodes */
for (node = ntree->nodes.first; node; node = node->next) {
/* node tree update tags override individual node update flags */
if ((node->update & NODE_UPDATE) || (ntree->update & NTREE_UPDATE)) {
- if (ntreetype->update_node)
- ntreetype->update_node(ntree, node);
- else if (node->typeinfo->updatefunc)
+ if (node->typeinfo->updatefunc)
node->typeinfo->updatefunc(ntree, node);
nodeUpdateInternalLinks(ntree, node);
}
}
- /* check link validity */
- if (ntree->update & (NTREE_UPDATE_LINKS | NTREE_UPDATE_NODES))
- ntree_validate_links(ntree);
-
/* generic tree update callback */
- if (ntreetype->update)
- ntreetype->update(ntree);
- else {
- /* Trees can be associated with a specific node type (i.e. group nodes),
- * in that case a tree update function may be defined by that node type.
- */
- bNodeType *ntype = node_get_type(ntree, ntree->nodetype);
- if (ntype && ntype->updatetreefunc)
- ntype->updatetreefunc(ntree);
- }
+ if (ntree->typeinfo->update)
+ ntree->typeinfo->update(ntree);
+ /* XXX this should be moved into the tree type update callback for tree supporting node groups.
+ * Currently the node tree interface is still a generic feature of the base NodeTree type.
+ */
+ if (ntree->update & NTREE_UPDATE_GROUP)
+ ntreeInterfaceTypeUpdate(ntree);
/* XXX hack, should be done by depsgraph!! */
ntreeVerifyNodes(G.main, &ntree->id);
+ if (ntree->update & (NTREE_UPDATE_LINKS | NTREE_UPDATE_NODES)) {
+ /* node updates can change sockets or links, repeat link pointer update afterward */
+ ntree_update_link_pointers(ntree);
+
+ /* update the node level from link dependencies */
+ ntree_update_node_level(ntree);
+
+ /* check link validity */
+ ntree_validate_links(ntree);
+ }
+
/* clear update flags */
for (node = ntree->nodes.first; node; node = node->next) {
node->update = 0;
}
ntree->update = 0;
+
+ ntree->is_updating = FALSE;
}
void nodeUpdate(bNodeTree *ntree, bNode *node)
{
- bNodeTreeType *ntreetype = ntreeGetType(ntree->type);
+ /* avoid reentrant updates, can be caused by RNA update callbacks */
+ if (ntree->is_updating)
+ return;
+ ntree->is_updating = TRUE;
- if (ntreetype->update_node)
- ntreetype->update_node(ntree, node);
- else if (node->typeinfo->updatefunc)
+ if (node->typeinfo->updatefunc)
node->typeinfo->updatefunc(ntree, node);
nodeUpdateInternalLinks(ntree, node);
/* clear update flag */
node->update = 0;
+
+ ntree->is_updating = FALSE;
}
int nodeUpdateID(bNodeTree *ntree, ID *id)
{
- bNodeTreeType *ntreetype;
bNode *node;
int change = FALSE;
if (ELEM(NULL, id, ntree))
return change;
- ntreetype = ntreeGetType(ntree->type);
+ /* avoid reentrant updates, can be caused by RNA update callbacks */
+ if (ntree->is_updating)
+ return change;
+ ntree->is_updating = TRUE;
- if (ntreetype->update_node) {
- for (node = ntree->nodes.first; node; node = node->next) {
- if (node->id == id) {
- change = TRUE;
- node->update |= NODE_UPDATE_ID;
- ntreetype->update_node(ntree, node);
- /* clear update flag */
- node->update = 0;
- }
- }
- }
- else {
- for (node = ntree->nodes.first; node; node = node->next) {
- if (node->id == id) {
- change = TRUE;
- node->update |= NODE_UPDATE_ID;
- if (node->typeinfo->updatefunc)
- node->typeinfo->updatefunc(ntree, node);
- /* clear update flag */
- node->update = 0;
- }
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if(node->id == id) {
+ change = TRUE;
+ node->update |= NODE_UPDATE_ID;
+ if (node->typeinfo->updatefunc)
+ node->typeinfo->updatefunc(ntree, node);
+ /* clear update flag */
+ node->update = 0;
}
}
@@ -1955,6 +2936,7 @@ int nodeUpdateID(bNodeTree *ntree, ID *id)
nodeUpdateInternalLinks(ntree, node);
}
+ ntree->is_updating = FALSE;
return change;
}
@@ -1967,21 +2949,75 @@ void nodeUpdateInternalLinks(bNodeTree *ntree, bNode *node)
}
-/* ************* node type access ********** */
-
-int nodeValid(bNodeTree *ntree, bNodeTemplate *ntemp)
+/* nodes that use ID data get synced with local data */
+void nodeSynchronizeID(bNode *node, bool copy_to_id)
{
- bNodeType *ntype = node_get_type(ntree, ntemp->type);
- if (ntype) {
- if (ntype->validfunc)
- return ntype->validfunc(ntree, ntemp);
- else
- return 1;
+ if (node->id==NULL) return;
+
+ if (ELEM(node->type, SH_NODE_MATERIAL, SH_NODE_MATERIAL_EXT)) {
+ bNodeSocket *sock;
+ Material *ma= (Material *)node->id;
+ int a;
+
+ /* hrmf, case in loop isn't super fast, but we don't edit 100s of material at same time either! */
+ for (a=0, sock= node->inputs.first; sock; sock= sock->next, a++) {
+ if (!nodeSocketIsHidden(sock)) {
+ if (copy_to_id) {
+ switch (a) {
+ case MAT_IN_COLOR:
+ copy_v3_v3(&ma->r, ((bNodeSocketValueRGBA *)sock->default_value)->value); break;
+ case MAT_IN_SPEC:
+ copy_v3_v3(&ma->specr, ((bNodeSocketValueRGBA *)sock->default_value)->value); break;
+ case MAT_IN_REFL:
+ ma->ref= ((bNodeSocketValueFloat *)sock->default_value)->value; break;
+ case MAT_IN_MIR:
+ copy_v3_v3(&ma->mirr, ((bNodeSocketValueRGBA *)sock->default_value)->value); break;
+ case MAT_IN_AMB:
+ ma->amb = ((bNodeSocketValueFloat *)sock->default_value)->value; break;
+ case MAT_IN_EMIT:
+ ma->emit = ((bNodeSocketValueFloat *)sock->default_value)->value; break;
+ case MAT_IN_SPECTRA:
+ ma->spectra = ((bNodeSocketValueFloat *)sock->default_value)->value; break;
+ case MAT_IN_RAY_MIRROR:
+ ma->ray_mirror = ((bNodeSocketValueFloat *)sock->default_value)->value; break;
+ case MAT_IN_ALPHA:
+ ma->alpha = ((bNodeSocketValueFloat *)sock->default_value)->value; break;
+ case MAT_IN_TRANSLUCENCY:
+ ma->translucency = ((bNodeSocketValueFloat *)sock->default_value)->value; break;
+ }
+ }
+ else {
+ switch (a) {
+ case MAT_IN_COLOR:
+ copy_v3_v3(((bNodeSocketValueRGBA *)sock->default_value)->value, &ma->r); break;
+ case MAT_IN_SPEC:
+ copy_v3_v3(((bNodeSocketValueRGBA *)sock->default_value)->value, &ma->specr); break;
+ case MAT_IN_REFL:
+ ((bNodeSocketValueFloat *)sock->default_value)->value= ma->ref; break;
+ case MAT_IN_MIR:
+ copy_v3_v3(((bNodeSocketValueRGBA *)sock->default_value)->value, &ma->mirr); break;
+ case MAT_IN_AMB:
+ ((bNodeSocketValueFloat *)sock->default_value)->value = ma->amb; break;
+ case MAT_IN_EMIT:
+ ((bNodeSocketValueFloat *)sock->default_value)->value = ma->emit; break;
+ case MAT_IN_SPECTRA:
+ ((bNodeSocketValueFloat *)sock->default_value)->value = ma->spectra; break;
+ case MAT_IN_RAY_MIRROR:
+ ((bNodeSocketValueFloat *)sock->default_value)->value = ma->ray_mirror; break;
+ case MAT_IN_ALPHA:
+ ((bNodeSocketValueFloat *)sock->default_value)->value = ma->alpha; break;
+ case MAT_IN_TRANSLUCENCY:
+ ((bNodeSocketValueFloat *)sock->default_value)->value = ma->translucency; break;
+ }
+ }
+ }
+ }
}
- else
- return 0;
}
+
+/* ************* node type access ********** */
+
const char *nodeLabel(bNode *node)
{
if (node->label[0] != '\0')
@@ -1989,81 +3025,136 @@ const char *nodeLabel(bNode *node)
else if (node->typeinfo->labelfunc)
return node->typeinfo->labelfunc(node);
else
- return IFACE_(node->typeinfo->name);
+ return IFACE_(node->typeinfo->ui_name);
}
-struct bNodeTree *nodeGroupEditGet(struct bNode *node)
+static void node_type_base_defaults(bNodeType *ntype)
{
- if (node->typeinfo->group_edit_get)
- return node->typeinfo->group_edit_get(node);
- else
- return NULL;
+ /* default size values */
+ node_type_size_preset(ntype, NODE_SIZE_DEFAULT);
+ ntype->height = 100;
+ ntype->minheight = 30;
+ ntype->maxheight = FLT_MAX;
}
-struct bNodeTree *nodeGroupEditSet(struct bNode *node, int edit)
+/* allow this node for any tree type */
+static int node_poll_default(bNodeType *UNUSED(ntype), bNodeTree *UNUSED(ntree))
{
- if (node->typeinfo->group_edit_set)
- return node->typeinfo->group_edit_set(node, edit);
- else if (node->typeinfo->group_edit_get)
- return node->typeinfo->group_edit_get(node);
- else
- return NULL;
+ return TRUE;
}
-void nodeGroupEditClear(struct bNode *node)
+/* use the basic poll function */
+static int node_poll_instance_default(bNode *node, bNodeTree *ntree)
{
- if (node->typeinfo->group_edit_clear)
- node->typeinfo->group_edit_clear(node);
+ return node->typeinfo->poll(node->typeinfo, ntree);
}
-struct bNodeTemplate nodeMakeTemplate(struct bNode *node)
+void node_type_base(bNodeType *ntype, int type, const char *name, short nclass, short flag)
{
- bNodeTemplate ntemp;
- if (node->typeinfo->templatefunc)
- return node->typeinfo->templatefunc(node);
- else {
- ntemp.type = node->type;
- return ntemp;
+ /* Use static type info header to map static int type to identifier string and RNA struct type.
+ * Associate the RNA struct type with the bNodeType.
+ * Dynamically registered nodes will create an RNA type at runtime
+ * and call RNA_struct_blender_type_set, so this only needs to be done for old RNA types
+ * created in makesrna, which can not be associated to a bNodeType immediately,
+ * since bNodeTypes are registered afterward ...
+ */
+ #define DefNode(Category, ID, DefFunc, EnumName, StructName, UIName, UIDesc) \
+ case ID: \
+ BLI_strncpy(ntype->idname, #Category #StructName, sizeof(ntype->idname)); \
+ ntype->ext.srna = RNA_struct_find(#Category #StructName); \
+ BLI_assert(ntype->ext.srna != NULL); \
+ RNA_struct_blender_type_set(ntype->ext.srna, ntype); \
+ break;
+
+ switch (type) {
+ #include "NOD_static_types.h"
}
+
+ /* make sure we have a valid type (everything registered) */
+ BLI_assert(ntype->idname[0] != '\0');
+
+ ntype->type = type;
+ BLI_strncpy(ntype->ui_name, name, sizeof(ntype->ui_name));
+ ntype->nclass = nclass;
+ ntype->flag = flag;
+
+ node_type_base_defaults(ntype);
+
+ ntype->poll = node_poll_default;
+ ntype->poll_instance = node_poll_instance_default;
}
-void node_type_base(bNodeTreeType *ttype, bNodeType *ntype, int type, const char *name, short nclass, short flag)
+void node_type_base_custom(bNodeType *ntype, const char *idname, const char *name, short nclass, short flag)
{
- memset(ntype, 0, sizeof(bNodeType));
-
- ntype->type = type;
- BLI_strncpy(ntype->name, name, sizeof(ntype->name));
+ BLI_strncpy(ntype->idname, idname, sizeof(ntype->idname));
+ ntype->type = NODE_CUSTOM;
+ BLI_strncpy(ntype->ui_name, name, sizeof(ntype->ui_name));
ntype->nclass = nclass;
ntype->flag = flag;
- /* Default muting stuff. */
- if (ttype)
- ntype->update_internal_links = ttype->update_internal_links;
+ node_type_base_defaults(ntype);
+}
- /* default size values */
- node_type_size_preset(ntype, NODE_SIZE_DEFAULT);
+static bool unique_socket_template_identifier_check(void *arg, const char *name)
+{
+ bNodeSocketTemplate *ntemp;
+ struct {bNodeSocketTemplate *list; bNodeSocketTemplate *ntemp;} *data= arg;
- ntype->height = 100;
- ntype->minheight = 30;
- ntype->maxheight = FLT_MAX;
+ for (ntemp = data->list; ntemp->type >= 0; ++ntemp) {
+ if (ntemp != data->ntemp) {
+ if (!strcmp(ntemp->identifier, name)) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+static void unique_socket_template_identifier(bNodeSocketTemplate *list, bNodeSocketTemplate *ntemp, const char defname[], char delim)
+{
+ struct {bNodeSocketTemplate *list; bNodeSocketTemplate *ntemp;} data;
+ data.list= list;
+ data.ntemp = ntemp;
+
+ BLI_uniquename_cb(unique_socket_template_identifier_check, &data, defname, delim, ntemp->identifier, sizeof(ntemp->identifier));
}
void node_type_socket_templates(struct bNodeType *ntype, struct bNodeSocketTemplate *inputs, struct bNodeSocketTemplate *outputs)
{
+ bNodeSocketTemplate *ntemp;
+
ntype->inputs = inputs;
ntype->outputs = outputs;
+
+ /* automatically generate unique identifiers */
+ if (inputs) {
+ /* clear identifier strings (uninitialized memory) */
+ for (ntemp=inputs; ntemp->type >= 0; ++ntemp)
+ ntemp->identifier[0] = '\0';
+
+ for (ntemp=inputs; ntemp->type >= 0; ++ntemp) {
+ BLI_strncpy(ntemp->identifier, ntemp->name, sizeof(ntemp->identifier));
+ unique_socket_template_identifier(inputs, ntemp, ntemp->identifier, '_');
+ }
+ }
+ if (outputs) {
+ /* clear identifier strings (uninitialized memory) */
+ for (ntemp=outputs; ntemp->type >= 0; ++ntemp)
+ ntemp->identifier[0] = '\0';
+
+ for (ntemp=outputs; ntemp->type >= 0; ++ntemp) {
+ BLI_strncpy(ntemp->identifier, ntemp->name, sizeof(ntemp->identifier));
+ unique_socket_template_identifier(outputs, ntemp, ntemp->identifier, '_');
+ }
+ }
}
-void node_type_init(struct bNodeType *ntype, void (*initfunc)(struct bNodeTree *ntree, struct bNode *node, struct bNodeTemplate *ntemp))
+void node_type_init(struct bNodeType *ntype, void (*initfunc)(struct bNodeTree *ntree, struct bNode *node))
{
ntype->initfunc = initfunc;
}
-void node_type_valid(struct bNodeType *ntype, int (*validfunc)(struct bNodeTree *ntree, struct bNodeTemplate *ntemp))
-{
- ntype->validfunc = validfunc;
-}
-
void node_type_size(struct bNodeType *ntype, int width, int minwidth, int maxwidth)
{
ntype->width = width;
@@ -2089,14 +3180,17 @@ void node_type_size_preset(struct bNodeType *ntype, eNodeSizePreset size)
}
}
-void node_type_storage(bNodeType *ntype, const char *storagename, void (*freestoragefunc)(struct bNode *), void (*copystoragefunc)(struct bNode *, struct bNode *))
+void node_type_storage(bNodeType *ntype,
+ const char *storagename,
+ void (*freefunc)(struct bNode *node),
+ void (*copyfunc)(struct bNodeTree *dest_ntree, struct bNode *dest_node, struct bNode *src_node))
{
if (storagename)
BLI_strncpy(ntype->storagename, storagename, sizeof(ntype->storagename));
else
ntype->storagename[0] = '\0';
- ntype->copystoragefunc = copystoragefunc;
- ntype->freestoragefunc = freestoragefunc;
+ ntype->copyfunc = copyfunc;
+ ntype->freefunc = freefunc;
}
void node_type_label(struct bNodeType *ntype, const char *(*labelfunc)(struct bNode *))
@@ -2104,11 +3198,6 @@ void node_type_label(struct bNodeType *ntype, const char *(*labelfunc)(struct bN
ntype->labelfunc = labelfunc;
}
-void node_type_template(struct bNodeType *ntype, struct bNodeTemplate (*templatefunc)(struct bNode *))
-{
- ntype->templatefunc = templatefunc;
-}
-
void node_type_update(struct bNodeType *ntype,
void (*updatefunc)(struct bNodeTree *ntree, struct bNode *node),
void (*verifyfunc)(struct bNodeTree *ntree, struct bNode *node, struct ID *id))
@@ -2117,50 +3206,21 @@ void node_type_update(struct bNodeType *ntype,
ntype->verifyfunc = verifyfunc;
}
-void node_type_tree(struct bNodeType *ntype, void (*inittreefunc)(struct bNodeTree *), void (*updatetreefunc)(struct bNodeTree *))
-{
- ntype->inittreefunc = inittreefunc;
- ntype->updatetreefunc = updatetreefunc;
-}
-
-void node_type_group_edit(struct bNodeType *ntype,
- struct bNodeTree *(*group_edit_get)(struct bNode *node),
- struct bNodeTree *(*group_edit_set)(struct bNode *node, int edit),
- void (*group_edit_clear)(struct bNode *node))
-{
- ntype->group_edit_get = group_edit_get;
- ntype->group_edit_set = group_edit_set;
- ntype->group_edit_clear = group_edit_clear;
-}
-
-void node_type_exec(struct bNodeType *ntype, void (*execfunc)(void *data, struct bNode *, struct bNodeStack **, struct bNodeStack **))
-{
- ntype->execfunc = execfunc;
-}
-
-void node_type_exec_new(struct bNodeType *ntype,
- void *(*initexecfunc)(struct bNode *node),
- void (*freeexecfunc)(struct bNode *node, void *nodedata),
- void (*newexecfunc)(void *data, int thread, struct bNode *, void *nodedata, struct bNodeStack **, struct bNodeStack **))
+void node_type_exec(struct bNodeType *ntype, NodeInitExecFunction initexecfunc, NodeFreeExecFunction freeexecfunc, NodeExecFunction execfunc)
{
ntype->initexecfunc = initexecfunc;
ntype->freeexecfunc = freeexecfunc;
- ntype->newexecfunc = newexecfunc;
-}
-
-void node_type_internal_links(bNodeType *ntype, void (*update_internal_links)(bNodeTree *, bNode *))
-{
- ntype->update_internal_links = update_internal_links;
+ ntype->execfunc = execfunc;
}
-void node_type_gpu(struct bNodeType *ntype, int (*gpufunc)(struct GPUMaterial *mat, struct bNode *node, struct GPUNodeStack *in, struct GPUNodeStack *out))
+void node_type_gpu(struct bNodeType *ntype, NodeGPUExecFunction gpufunc)
{
ntype->gpufunc = gpufunc;
}
-void node_type_gpu_ext(struct bNodeType *ntype, int (*gpuextfunc)(struct GPUMaterial *mat, struct bNode *node, void *nodedata, struct GPUNodeStack *in, struct GPUNodeStack *out))
+void node_type_internal_links(bNodeType *ntype, void (*update_internal_links)(bNodeTree *, bNode *))
{
- ntype->gpuextfunc = gpuextfunc;
+ ntype->update_internal_links = update_internal_links;
}
void node_type_compatibility(struct bNodeType *ntype, short compatibility)
@@ -2168,298 +3228,276 @@ void node_type_compatibility(struct bNodeType *ntype, short compatibility)
ntype->compatibility = compatibility;
}
-static bNodeType *is_nodetype_registered(ListBase *typelist, int type)
-{
- bNodeType *ntype = typelist->first;
-
- for (; ntype; ntype = ntype->next)
- if (ntype->type == type)
- return ntype;
-
- return NULL;
-}
-
-void nodeRegisterType(bNodeTreeType *ttype, bNodeType *ntype)
-{
- ListBase *typelist = &(ttype->node_types);
- bNodeType *found = is_nodetype_registered(typelist, ntype->type);
-
- if (found == NULL)
- BLI_addtail(typelist, ntype);
-
- /* Associate the RNA struct type with the bNodeType.
- * Dynamically registered nodes will create an RNA type at runtime
- * and call RNA_struct_blender_type_set, so this only needs to be done for old RNA types
- * created in makesrna, which can not be associated to a bNodeType immediately,
- * since bNodeTypes are registered afterward ...
- */
- #define DefNode(Category, ID, DefFunc, EnumName, StructName, UIName, UIDesc) \
- if (ID == ntype->type) { \
- StructRNA *srna = RNA_struct_find(STRINGIFY_ARG(Category##StructName)); \
- BLI_assert(srna != NULL); \
- RNA_struct_blender_type_set(srna, ntype); \
- }
-
- /* XXX hack, this file will be moved to the nodes folder in customnodes branch,
- * then this stupid include path is not needed any more.
- */
- #include "intern/rna_nodetree_types.h"
-}
-
-static void registerCompositNodes(bNodeTreeType *ttype)
-{
- register_node_type_frame(ttype);
- register_node_type_reroute(ttype);
-
- register_node_type_cmp_group(ttype);
-
- register_node_type_cmp_rlayers(ttype);
- register_node_type_cmp_image(ttype);
- register_node_type_cmp_texture(ttype);
- register_node_type_cmp_value(ttype);
- register_node_type_cmp_rgb(ttype);
- register_node_type_cmp_curve_time(ttype);
- register_node_type_cmp_movieclip(ttype);
-
- register_node_type_cmp_composite(ttype);
- register_node_type_cmp_viewer(ttype);
- register_node_type_cmp_splitviewer(ttype);
- register_node_type_cmp_output_file(ttype);
- register_node_type_cmp_view_levels(ttype);
-
- register_node_type_cmp_curve_rgb(ttype);
- register_node_type_cmp_mix_rgb(ttype);
- register_node_type_cmp_hue_sat(ttype);
- register_node_type_cmp_brightcontrast(ttype);
- register_node_type_cmp_gamma(ttype);
- register_node_type_cmp_invert(ttype);
- register_node_type_cmp_alphaover(ttype);
- register_node_type_cmp_zcombine(ttype);
- register_node_type_cmp_colorbalance(ttype);
- register_node_type_cmp_huecorrect(ttype);
-
- register_node_type_cmp_normal(ttype);
- register_node_type_cmp_curve_vec(ttype);
- register_node_type_cmp_map_value(ttype);
- register_node_type_cmp_map_range(ttype);
- register_node_type_cmp_normalize(ttype);
-
- register_node_type_cmp_filter(ttype);
- register_node_type_cmp_blur(ttype);
- register_node_type_cmp_dblur(ttype);
- register_node_type_cmp_bilateralblur(ttype);
- register_node_type_cmp_vecblur(ttype);
- register_node_type_cmp_dilateerode(ttype);
- register_node_type_cmp_inpaint(ttype);
- register_node_type_cmp_despeckle(ttype);
- register_node_type_cmp_defocus(ttype);
-
- register_node_type_cmp_valtorgb(ttype);
- register_node_type_cmp_rgbtobw(ttype);
- register_node_type_cmp_setalpha(ttype);
- register_node_type_cmp_idmask(ttype);
- register_node_type_cmp_math(ttype);
- register_node_type_cmp_seprgba(ttype);
- register_node_type_cmp_combrgba(ttype);
- register_node_type_cmp_sephsva(ttype);
- register_node_type_cmp_combhsva(ttype);
- register_node_type_cmp_sepyuva(ttype);
- register_node_type_cmp_combyuva(ttype);
- register_node_type_cmp_sepycca(ttype);
- register_node_type_cmp_combycca(ttype);
- register_node_type_cmp_premulkey(ttype);
-
- register_node_type_cmp_diff_matte(ttype);
- register_node_type_cmp_distance_matte(ttype);
- register_node_type_cmp_chroma_matte(ttype);
- register_node_type_cmp_color_matte(ttype);
- register_node_type_cmp_channel_matte(ttype);
- register_node_type_cmp_color_spill(ttype);
- register_node_type_cmp_luma_matte(ttype);
- register_node_type_cmp_doubleedgemask(ttype);
- register_node_type_cmp_keyingscreen(ttype);
- register_node_type_cmp_keying(ttype);
-
- register_node_type_cmp_translate(ttype);
- register_node_type_cmp_rotate(ttype);
- register_node_type_cmp_scale(ttype);
- register_node_type_cmp_flip(ttype);
- register_node_type_cmp_crop(ttype);
- register_node_type_cmp_displace(ttype);
- register_node_type_cmp_mapuv(ttype);
- register_node_type_cmp_glare(ttype);
- register_node_type_cmp_tonemap(ttype);
- register_node_type_cmp_lensdist(ttype);
- register_node_type_cmp_transform(ttype);
- register_node_type_cmp_stabilize2d(ttype);
- register_node_type_cmp_moviedistortion(ttype);
-
- register_node_type_cmp_colorcorrection(ttype);
- register_node_type_cmp_boxmask(ttype);
- register_node_type_cmp_ellipsemask(ttype);
- register_node_type_cmp_bokehimage(ttype);
- register_node_type_cmp_bokehblur(ttype);
- register_node_type_cmp_switch(ttype);
- register_node_type_cmp_pixelate(ttype);
-
- register_node_type_cmp_mask(ttype);
- register_node_type_cmp_trackpos(ttype);
-}
-
-static void registerShaderNodes(bNodeTreeType *ttype)
-{
- register_node_type_frame(ttype);
- register_node_type_reroute(ttype);
-
- register_node_type_sh_group(ttype);
-
- register_node_type_sh_output(ttype);
- register_node_type_sh_material(ttype);
- register_node_type_sh_camera(ttype);
- register_node_type_sh_gamma(ttype);
- register_node_type_sh_brightcontrast(ttype);
- register_node_type_sh_value(ttype);
- register_node_type_sh_rgb(ttype);
- register_node_type_sh_mix_rgb(ttype);
- register_node_type_sh_valtorgb(ttype);
- register_node_type_sh_rgbtobw(ttype);
- register_node_type_sh_texture(ttype);
- register_node_type_sh_normal(ttype);
- register_node_type_sh_geom(ttype);
- register_node_type_sh_mapping(ttype);
- register_node_type_sh_curve_vec(ttype);
- register_node_type_sh_curve_rgb(ttype);
- register_node_type_sh_math(ttype);
- register_node_type_sh_vect_math(ttype);
- register_node_type_sh_squeeze(ttype);
- register_node_type_sh_material_ext(ttype);
- register_node_type_sh_invert(ttype);
- register_node_type_sh_seprgb(ttype);
- register_node_type_sh_combrgb(ttype);
- register_node_type_sh_hue_sat(ttype);
-
- register_node_type_sh_attribute(ttype);
- register_node_type_sh_geometry(ttype);
- register_node_type_sh_light_path(ttype);
- register_node_type_sh_light_falloff(ttype);
- register_node_type_sh_object_info(ttype);
- register_node_type_sh_fresnel(ttype);
- register_node_type_sh_layer_weight(ttype);
- register_node_type_sh_tex_coord(ttype);
- register_node_type_sh_particle_info(ttype);
- register_node_type_sh_hair_info(ttype);
- register_node_type_sh_bump(ttype);
- register_node_type_sh_script(ttype);
- register_node_type_sh_tangent(ttype);
- register_node_type_sh_normal_map(ttype);
-
- register_node_type_sh_background(ttype);
- register_node_type_sh_bsdf_anisotropic(ttype);
- register_node_type_sh_bsdf_diffuse(ttype);
- register_node_type_sh_bsdf_glossy(ttype);
- register_node_type_sh_bsdf_glass(ttype);
- register_node_type_sh_bsdf_refraction(ttype);
- register_node_type_sh_bsdf_translucent(ttype);
- register_node_type_sh_bsdf_transparent(ttype);
- register_node_type_sh_bsdf_velvet(ttype);
- register_node_type_sh_emission(ttype);
- register_node_type_sh_holdout(ttype);
- register_node_type_sh_ambient_occlusion(ttype);
- //register_node_type_sh_volume_transparent(ttype);
- //register_node_type_sh_volume_isotropic(ttype);
- register_node_type_sh_mix_shader(ttype);
- register_node_type_sh_add_shader(ttype);
-
- register_node_type_sh_output_lamp(ttype);
- register_node_type_sh_output_material(ttype);
- register_node_type_sh_output_world(ttype);
-
- register_node_type_sh_tex_image(ttype);
- register_node_type_sh_tex_environment(ttype);
- register_node_type_sh_tex_sky(ttype);
- register_node_type_sh_tex_noise(ttype);
- register_node_type_sh_tex_wave(ttype);
- register_node_type_sh_tex_voronoi(ttype);
- register_node_type_sh_tex_musgrave(ttype);
- register_node_type_sh_tex_gradient(ttype);
- register_node_type_sh_tex_magic(ttype);
- register_node_type_sh_tex_checker(ttype);
- register_node_type_sh_tex_brick(ttype);
-}
-
-static void registerTextureNodes(bNodeTreeType *ttype)
-{
- register_node_type_frame(ttype);
- register_node_type_reroute(ttype);
-
- register_node_type_tex_group(ttype);
-
- register_node_type_tex_math(ttype);
- register_node_type_tex_mix_rgb(ttype);
- register_node_type_tex_valtorgb(ttype);
- register_node_type_tex_rgbtobw(ttype);
- register_node_type_tex_valtonor(ttype);
- register_node_type_tex_curve_rgb(ttype);
- register_node_type_tex_curve_time(ttype);
- register_node_type_tex_invert(ttype);
- register_node_type_tex_hue_sat(ttype);
- register_node_type_tex_coord(ttype);
- register_node_type_tex_distance(ttype);
- register_node_type_tex_compose(ttype);
- register_node_type_tex_decompose(ttype);
-
- register_node_type_tex_output(ttype);
- register_node_type_tex_viewer(ttype);
-
- register_node_type_tex_checker(ttype);
- register_node_type_tex_texture(ttype);
- register_node_type_tex_bricks(ttype);
- register_node_type_tex_image(ttype);
-
- register_node_type_tex_rotate(ttype);
- register_node_type_tex_translate(ttype);
- register_node_type_tex_scale(ttype);
- register_node_type_tex_at(ttype);
-
- register_node_type_tex_proc_voronoi(ttype);
- register_node_type_tex_proc_blend(ttype);
- register_node_type_tex_proc_magic(ttype);
- register_node_type_tex_proc_marble(ttype);
- register_node_type_tex_proc_clouds(ttype);
- register_node_type_tex_proc_wood(ttype);
- register_node_type_tex_proc_musgrave(ttype);
- register_node_type_tex_proc_noise(ttype);
- register_node_type_tex_proc_stucci(ttype);
- register_node_type_tex_proc_distnoise(ttype);
-}
-
-static void free_typeinfos(ListBase *list)
-{
- bNodeType *ntype, *next;
- for (ntype = list->first; ntype; ntype = next) {
- next = ntype->next;
-
- if (ntype->needs_free)
- MEM_freeN(ntype);
- }
+static void registerCompositNodes(void)
+{
+ register_node_type_cmp_group();
+
+ register_node_type_cmp_rlayers();
+ register_node_type_cmp_image();
+ register_node_type_cmp_texture();
+ register_node_type_cmp_value();
+ register_node_type_cmp_rgb();
+ register_node_type_cmp_curve_time();
+ register_node_type_cmp_movieclip();
+
+ register_node_type_cmp_composite();
+ register_node_type_cmp_viewer();
+ register_node_type_cmp_splitviewer();
+ register_node_type_cmp_output_file();
+ register_node_type_cmp_view_levels();
+
+ register_node_type_cmp_curve_rgb();
+ register_node_type_cmp_mix_rgb();
+ register_node_type_cmp_hue_sat();
+ register_node_type_cmp_brightcontrast();
+ register_node_type_cmp_gamma();
+ register_node_type_cmp_invert();
+ register_node_type_cmp_alphaover();
+ register_node_type_cmp_zcombine();
+ register_node_type_cmp_colorbalance();
+ register_node_type_cmp_huecorrect();
+
+ register_node_type_cmp_normal();
+ register_node_type_cmp_curve_vec();
+ register_node_type_cmp_map_value();
+ register_node_type_cmp_map_range();
+ register_node_type_cmp_normalize();
+
+ register_node_type_cmp_filter();
+ register_node_type_cmp_blur();
+ register_node_type_cmp_dblur();
+ register_node_type_cmp_bilateralblur();
+ register_node_type_cmp_vecblur();
+ register_node_type_cmp_dilateerode();
+ register_node_type_cmp_inpaint();
+ register_node_type_cmp_despeckle();
+ register_node_type_cmp_defocus();
+
+ register_node_type_cmp_valtorgb();
+ register_node_type_cmp_rgbtobw();
+ register_node_type_cmp_setalpha();
+ register_node_type_cmp_idmask();
+ register_node_type_cmp_math();
+ register_node_type_cmp_seprgba();
+ register_node_type_cmp_combrgba();
+ register_node_type_cmp_sephsva();
+ register_node_type_cmp_combhsva();
+ register_node_type_cmp_sepyuva();
+ register_node_type_cmp_combyuva();
+ register_node_type_cmp_sepycca();
+ register_node_type_cmp_combycca();
+ register_node_type_cmp_premulkey();
+
+ register_node_type_cmp_diff_matte();
+ register_node_type_cmp_distance_matte();
+ register_node_type_cmp_chroma_matte();
+ register_node_type_cmp_color_matte();
+ register_node_type_cmp_channel_matte();
+ register_node_type_cmp_color_spill();
+ register_node_type_cmp_luma_matte();
+ register_node_type_cmp_doubleedgemask();
+ register_node_type_cmp_keyingscreen();
+ register_node_type_cmp_keying();
+
+ register_node_type_cmp_translate();
+ register_node_type_cmp_rotate();
+ register_node_type_cmp_scale();
+ register_node_type_cmp_flip();
+ register_node_type_cmp_crop();
+ register_node_type_cmp_displace();
+ register_node_type_cmp_mapuv();
+ register_node_type_cmp_glare();
+ register_node_type_cmp_tonemap();
+ register_node_type_cmp_lensdist();
+ register_node_type_cmp_transform();
+ register_node_type_cmp_stabilize2d();
+ register_node_type_cmp_moviedistortion();
+
+ register_node_type_cmp_colorcorrection();
+ register_node_type_cmp_boxmask();
+ register_node_type_cmp_ellipsemask();
+ register_node_type_cmp_bokehimage();
+ register_node_type_cmp_bokehblur();
+ register_node_type_cmp_switch();
+ register_node_type_cmp_pixelate();
+
+ register_node_type_cmp_mask();
+ register_node_type_cmp_trackpos();
+}
+
+static void registerShaderNodes(void)
+{
+ register_node_type_sh_group();
+
+ register_node_type_sh_output();
+ register_node_type_sh_material();
+ register_node_type_sh_camera();
+ register_node_type_sh_gamma();
+ register_node_type_sh_brightcontrast();
+ register_node_type_sh_value();
+ register_node_type_sh_rgb();
+ register_node_type_sh_mix_rgb();
+ register_node_type_sh_valtorgb();
+ register_node_type_sh_rgbtobw();
+ register_node_type_sh_texture();
+ register_node_type_sh_normal();
+ register_node_type_sh_geom();
+ register_node_type_sh_mapping();
+ register_node_type_sh_curve_vec();
+ register_node_type_sh_curve_rgb();
+ register_node_type_sh_math();
+ register_node_type_sh_vect_math();
+ register_node_type_sh_squeeze();
+ register_node_type_sh_material_ext();
+ register_node_type_sh_invert();
+ register_node_type_sh_seprgb();
+ register_node_type_sh_combrgb();
+ register_node_type_sh_hue_sat();
+
+ register_node_type_sh_attribute();
+ register_node_type_sh_geometry();
+ register_node_type_sh_light_path();
+ register_node_type_sh_light_falloff();
+ register_node_type_sh_object_info();
+ register_node_type_sh_fresnel();
+ register_node_type_sh_layer_weight();
+ register_node_type_sh_tex_coord();
+ register_node_type_sh_particle_info();
+ register_node_type_sh_bump();
+
+ register_node_type_sh_background();
+ register_node_type_sh_bsdf_anisotropic();
+ register_node_type_sh_bsdf_diffuse();
+ register_node_type_sh_bsdf_glossy();
+ register_node_type_sh_bsdf_glass();
+ register_node_type_sh_bsdf_translucent();
+ register_node_type_sh_bsdf_transparent();
+ register_node_type_sh_bsdf_velvet();
+ register_node_type_sh_emission();
+ register_node_type_sh_holdout();
+ //register_node_type_sh_volume_transparent();
+ //register_node_type_sh_volume_isotropic();
+ register_node_type_sh_mix_shader();
+ register_node_type_sh_add_shader();
+
+ register_node_type_sh_output_lamp();
+ register_node_type_sh_output_material();
+ register_node_type_sh_output_world();
+
+ register_node_type_sh_tex_image();
+ register_node_type_sh_tex_environment();
+ register_node_type_sh_tex_sky();
+ register_node_type_sh_tex_noise();
+ register_node_type_sh_tex_wave();
+ register_node_type_sh_tex_voronoi();
+ register_node_type_sh_tex_musgrave();
+ register_node_type_sh_tex_gradient();
+ register_node_type_sh_tex_magic();
+ register_node_type_sh_tex_checker();
+ register_node_type_sh_tex_brick();
+}
+
+static void registerTextureNodes(void)
+{
+ register_node_type_tex_group();
+
+
+ register_node_type_tex_math();
+ register_node_type_tex_mix_rgb();
+ register_node_type_tex_valtorgb();
+ register_node_type_tex_rgbtobw();
+ register_node_type_tex_valtonor();
+ register_node_type_tex_curve_rgb();
+ register_node_type_tex_curve_time();
+ register_node_type_tex_invert();
+ register_node_type_tex_hue_sat();
+ register_node_type_tex_coord();
+ register_node_type_tex_distance();
+ register_node_type_tex_compose();
+ register_node_type_tex_decompose();
+
+ register_node_type_tex_output();
+ register_node_type_tex_viewer();
+ register_node_type_sh_script();
+ register_node_type_sh_tangent();
+ register_node_type_sh_normal_map();
+ register_node_type_sh_hair_info();
+
+ register_node_type_tex_checker();
+ register_node_type_tex_texture();
+ register_node_type_tex_bricks();
+ register_node_type_tex_image();
+ register_node_type_sh_bsdf_refraction();
+ register_node_type_sh_ambient_occlusion();
+
+ register_node_type_tex_rotate();
+ register_node_type_tex_translate();
+ register_node_type_tex_scale();
+ register_node_type_tex_at();
+
+ register_node_type_tex_proc_voronoi();
+ register_node_type_tex_proc_blend();
+ register_node_type_tex_proc_magic();
+ register_node_type_tex_proc_marble();
+ register_node_type_tex_proc_clouds();
+ register_node_type_tex_proc_wood();
+ register_node_type_tex_proc_musgrave();
+ register_node_type_tex_proc_noise();
+ register_node_type_tex_proc_stucci();
+ register_node_type_tex_proc_distnoise();
}
void init_nodesystem(void)
{
- /* init clipboard */
- node_clipboard.nodes.first = node_clipboard.nodes.last = NULL;
- node_clipboard.links.first = node_clipboard.links.last = NULL;
+ nodetreetypes_hash = BLI_ghash_new(BLI_ghashutil_strhash, BLI_ghashutil_strcmp, "nodetreetypes_hash gh");
+ nodetypes_hash = BLI_ghash_new(BLI_ghashutil_strhash, BLI_ghashutil_strcmp, "nodetypes_hash gh");
+ nodesockettypes_hash = BLI_ghash_new(BLI_ghashutil_strhash, BLI_ghashutil_strcmp, "nodesockettypes_hash gh");
+
+ register_standard_node_socket_types();
+
+ register_node_tree_type_cmp();
+ register_node_tree_type_sh();
+ register_node_tree_type_tex();
+
+ register_node_type_frame();
+ register_node_type_reroute();
+ register_node_type_group_input();
+ register_node_type_group_output();
- registerCompositNodes(ntreeGetType(NTREE_COMPOSIT));
- registerShaderNodes(ntreeGetType(NTREE_SHADER));
- registerTextureNodes(ntreeGetType(NTREE_TEXTURE));
+ registerCompositNodes();
+ registerShaderNodes();
+ registerTextureNodes();
}
void free_nodesystem(void)
{
- free_typeinfos(&ntreeGetType(NTREE_COMPOSIT)->node_types);
- free_typeinfos(&ntreeGetType(NTREE_SHADER)->node_types);
- free_typeinfos(&ntreeGetType(NTREE_TEXTURE)->node_types);
+ NODE_TYPES_BEGIN(nt)
+ if(nt->ext.free) {
+ nt->ext.free(nt->ext.data);
+ }
+ NODE_TYPES_END
+
+ NODE_SOCKET_TYPES_BEGIN(st)
+ if(st->ext_socket.free)
+ st->ext_socket.free(st->ext_socket.data);
+ if(st->ext_interface.free)
+ st->ext_interface.free(st->ext_interface.data);
+ NODE_SOCKET_TYPES_END
+
+ NODE_TREE_TYPES_BEGIN(nt)
+ if(nt->ext.free) {
+ nt->ext.free(nt->ext.data);
+ }
+ NODE_TREE_TYPES_END
+
+ BLI_ghash_free(nodetypes_hash, NULL, node_free_type);
+ nodetypes_hash = NULL;
+
+ BLI_ghash_free(nodesockettypes_hash, NULL, node_free_socket_type);
+ nodesockettypes_hash = NULL;
+
+ BLI_ghash_free(nodetreetypes_hash, NULL, ntree_free_type);
+ nodetreetypes_hash = NULL;
}
/* called from BKE_scene_unlink, when deleting a scene goes over all scenes
diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c
index bdf2ce622de..c6d4cf1412d 100644
--- a/source/blender/blenkernel/intern/texture.c
+++ b/source/blender/blenkernel/intern/texture.c
@@ -695,7 +695,7 @@ Tex *BKE_texture_copy(Tex *tex)
if (tex->nodetree) {
if (tex->nodetree->execdata) {
- ntreeTexEndExecTree(tex->nodetree->execdata, 1);
+ ntreeTexEndExecTree(tex->nodetree->execdata);
}
texn->nodetree = ntreeCopyTree(tex->nodetree);
}
diff --git a/source/blender/blenlib/BLI_ghash.h b/source/blender/blenlib/BLI_ghash.h
index 97564ca5363..641aaa1f3fc 100644
--- a/source/blender/blenlib/BLI_ghash.h
+++ b/source/blender/blenlib/BLI_ghash.h
@@ -70,6 +70,7 @@ void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfre
void BLI_ghash_insert(GHash *gh, void *key, void *val);
void *BLI_ghash_lookup(GHash *gh, const void *key);
bool BLI_ghash_remove(GHash *gh, void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp);
+void BLI_ghash_clear(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp);
void *BLI_ghash_pop(GHash *gh, void *key, GHashKeyFreeFP keyfreefp);
bool BLI_ghash_haskey(GHash *gh, const void *key);
int BLI_ghash_size(GHash *gh);
diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt
index bd6e84f7ef9..e39ae395ffa 100644
--- a/source/blender/blenlib/CMakeLists.txt
+++ b/source/blender/blenlib/CMakeLists.txt
@@ -23,10 +23,13 @@
#
# ***** END GPL LICENSE BLOCK *****
+# XXX allowing blenkernel and RNA includes in blenlib is a hack,
+# but needed in a few places atm (bpath.c for instance)
set(INC
.
# ../blenkernel # dont add this back!
../makesdna
+ ../makesrna
../../../intern/ghost
../../../intern/guardedalloc
../../../extern/wcwidth
diff --git a/source/blender/blenlib/intern/BLI_ghash.c b/source/blender/blenlib/intern/BLI_ghash.c
index ebc40ebc5e3..0887d646479 100644
--- a/source/blender/blenlib/intern/BLI_ghash.c
+++ b/source/blender/blenlib/intern/BLI_ghash.c
@@ -62,8 +62,7 @@ GHash *BLI_ghash_new(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info)
gh->nentries = 0;
gh->nbuckets = hashsizes[gh->cursize];
- gh->buckets = MEM_mallocN(gh->nbuckets * sizeof(*gh->buckets), "buckets");
- memset(gh->buckets, 0, gh->nbuckets * sizeof(*gh->buckets));
+ gh->buckets = MEM_callocN(gh->nbuckets * sizeof(*gh->buckets), "buckets");
return gh;
}
@@ -88,8 +87,7 @@ void BLI_ghash_insert(GHash *gh, void *key, void *val)
int i, nold = gh->nbuckets;
gh->nbuckets = hashsizes[++gh->cursize];
- gh->buckets = (Entry **)MEM_mallocN(gh->nbuckets * sizeof(*gh->buckets), "buckets");
- memset(gh->buckets, 0, gh->nbuckets * sizeof(*gh->buckets));
+ gh->buckets = (Entry **)MEM_callocN(gh->nbuckets * sizeof(*gh->buckets), "buckets");
for (i = 0; i < nold; i++) {
for (e = old[i]; e; ) {
@@ -148,6 +146,32 @@ bool BLI_ghash_remove(GHash *gh, void *key, GHashKeyFreeFP keyfreefp, GHashValFr
return false;
}
+void BLI_ghash_clear(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
+{
+ int i;
+
+ if (keyfreefp || valfreefp) {
+ for (i = 0; i < gh->nbuckets; i++) {
+ Entry *e;
+
+ for (e = gh->buckets[i]; e; ) {
+ Entry *n = e->next;
+
+ if (keyfreefp) keyfreefp(e->key);
+ if (valfreefp) valfreefp(e->val);
+
+ e = n;
+ }
+ }
+ }
+
+ gh->cursize = 0;
+ gh->nentries = 0;
+ gh->nbuckets = hashsizes[gh->cursize];
+
+ gh->buckets = MEM_recallocN(gh->buckets, gh->nbuckets * sizeof(*gh->buckets));
+}
+
/* same as above but return the value,
* no free value argument since it will be returned */
void *BLI_ghash_pop(GHash *gh, void *key, GHashKeyFreeFP keyfreefp)
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index be2b45a3e12..ea5610af3b5 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -127,6 +127,7 @@
#include "BKE_lattice.h"
#include "BKE_library.h" // for which_libbase
#include "BKE_idcode.h"
+#include "BKE_idprop.h"
#include "BKE_material.h"
#include "BKE_main.h" // for Main
#include "BKE_mesh.h" // for ME_ defines (patching)
@@ -150,7 +151,11 @@
#include "IMB_imbuf.h" // for proxy / timecode versioning stuff
+#include "NOD_common.h"
#include "NOD_socket.h"
+#include "NOD_composite.h"
+#include "NOD_shader.h"
+#include "NOD_texture.h"
#include "BLO_readfile.h"
#include "BLO_undofile.h"
@@ -1313,10 +1318,12 @@ void blo_make_image_pointer_map(FileData *fd, Main *oldmain)
oldnewmap_insert(fd->imamap, ima->renders[a], ima->renders[a], 0);
}
for (; sce; sce = sce->id.next) {
- if (sce->nodetree) {
- bNode *node;
- for (node = sce->nodetree->nodes.first; node; node = node->next)
- oldnewmap_insert(fd->imamap, node->preview, node->preview, 0);
+ if (sce->nodetree && sce->nodetree->previews) {
+ bNodeInstanceHashIterator iter;
+ NODE_INSTANCE_HASH_ITER(iter, sce->nodetree->previews) {
+ bNodePreview *preview = BKE_node_instance_hash_iterator_get_value(&iter);
+ oldnewmap_insert(fd->imamap, preview, preview, 0);
+ }
}
}
}
@@ -1355,10 +1362,23 @@ void blo_end_image_pointer_map(FileData *fd, Main *oldmain)
ima->gputexture = newimaadr(fd, ima->gputexture);
}
for (; sce; sce = sce->id.next) {
- if (sce->nodetree) {
- bNode *node;
- for (node = sce->nodetree->nodes.first; node; node = node->next)
- node->preview = newimaadr(fd, node->preview);
+ if (sce->nodetree && sce->nodetree->previews) {
+ bNodeInstanceHash *new_previews = BKE_node_instance_hash_new("node previews");
+ bNodeInstanceHashIterator iter;
+
+ /* reconstruct the preview hash, only using remaining pointers */
+ NODE_INSTANCE_HASH_ITER(iter, sce->nodetree->previews) {
+ bNodePreview *preview = BKE_node_instance_hash_iterator_get_value(&iter);
+ if (preview) {
+ bNodePreview *new_preview = newimaadr(fd, preview);
+ if (new_preview) {
+ bNodeInstanceKey key = BKE_node_instance_hash_iterator_get_key(&iter);
+ BKE_node_instance_hash_insert(new_previews, key, new_preview);
+ }
+ }
+ }
+ BKE_node_instance_hash_free(sce->nodetree->previews, NULL);
+ sce->nodetree->previews = new_previews;
}
}
}
@@ -2286,17 +2306,42 @@ static void direct_link_motionpath(FileData *fd, bMotionPath *mpath)
/* ************ READ NODE TREE *************** */
+static void lib_link_node_socket(FileData *fd, ID *UNUSED(id), bNodeSocket *sock)
+{
+ /* Link ID Properties -- and copy this comment EXACTLY for easy finding
+ * of library blocks that implement this.*/
+ if (sock->prop)
+ IDP_LibLinkProperty(sock->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
+}
+
/* singe node tree (also used for material/scene trees), ntree is not NULL */
static void lib_link_ntree(FileData *fd, ID *id, bNodeTree *ntree)
{
bNode *node;
+ bNodeSocket *sock;
if (ntree->adt) lib_link_animdata(fd, &ntree->id, ntree->adt);
ntree->gpd = newlibadr_us(fd, id->lib, ntree->gpd);
- for (node = ntree->nodes.first; node; node = node->next)
- node->id = newlibadr_us(fd, id->lib, node->id);
+ for (node = ntree->nodes.first; node; node = node->next) {
+ /* Link ID Properties -- and copy this comment EXACTLY for easy finding
+ * of library blocks that implement this.*/
+ if (node->prop)
+ IDP_LibLinkProperty(node->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
+
+ node->id= newlibadr_us(fd, id->lib, node->id);
+
+ for (sock=node->inputs.first; sock; sock=sock->next)
+ lib_link_node_socket(fd, id, sock);
+ for (sock=node->outputs.first; sock; sock=sock->next)
+ lib_link_node_socket(fd, id, sock);
+ }
+
+ for (sock=ntree->inputs.first; sock; sock=sock->next)
+ lib_link_node_socket(fd, id, sock);
+ for (sock=ntree->outputs.first; sock; sock=sock->next)
+ lib_link_node_socket(fd, id, sock);
}
/* library ntree linking after fileread */
@@ -2313,131 +2358,49 @@ static void lib_link_nodetree(FileData *fd, Main *main)
}
}
-static void do_versions_socket_default_value(bNodeSocket *sock)
-{
- bNodeSocketValueFloat *valfloat;
- bNodeSocketValueVector *valvector;
- bNodeSocketValueRGBA *valrgba;
-
- if (sock->default_value)
- return;
-
- switch (sock->type) {
- case SOCK_FLOAT:
- valfloat = sock->default_value = MEM_callocN(sizeof(bNodeSocketValueFloat), "default socket value");
- valfloat->value = sock->ns.vec[0];
- valfloat->min = sock->ns.min;
- valfloat->max = sock->ns.max;
- valfloat->subtype = PROP_NONE;
- break;
- case SOCK_VECTOR:
- valvector = sock->default_value = MEM_callocN(sizeof(bNodeSocketValueVector), "default socket value");
- copy_v3_v3(valvector->value, sock->ns.vec);
- valvector->min = sock->ns.min;
- valvector->max = sock->ns.max;
- valvector->subtype = PROP_NONE;
- break;
- case SOCK_RGBA:
- valrgba = sock->default_value = MEM_callocN(sizeof(bNodeSocketValueRGBA), "default socket value");
- copy_v4_v4(valrgba->value, sock->ns.vec);
- break;
- }
-}
-
-void blo_do_versions_nodetree_default_value(bNodeTree *ntree)
-{
- bNode *node;
- bNodeSocket *sock;
- for (node=ntree->nodes.first; node; node=node->next) {
- for (sock=node->inputs.first; sock; sock=sock->next)
- do_versions_socket_default_value(sock);
- for (sock=node->outputs.first; sock; sock=sock->next)
- do_versions_socket_default_value(sock);
- }
- for (sock=ntree->inputs.first; sock; sock=sock->next)
- do_versions_socket_default_value(sock);
- for (sock=ntree->outputs.first; sock; sock=sock->next)
- do_versions_socket_default_value(sock);
-}
-
-static void lib_nodetree_init_types_cb(void *UNUSED(data), ID *UNUSED(id), bNodeTree *ntree)
-{
- bNode *node;
-
- ntreeInitTypes(ntree);
-
- /* need to do this here instead of in do_versions, otherwise next function can crash */
- blo_do_versions_nodetree_default_value(ntree);
-
- /* XXX could be replaced by do_versions for new nodes */
- for (node=ntree->nodes.first; node; node=node->next)
- node_verify_socket_templates(ntree, node);
-}
-
-/* updates group node socket own_index so that
+/* updates group node socket identifier so that
* external links to/from the group node are preserved.
*/
static void lib_node_do_versions_group_indices(bNode *gnode)
{
bNodeTree *ngroup = (bNodeTree*)gnode->id;
- bNode *intnode;
- bNodeSocket *sock, *gsock, *intsock;
- int found;
+ bNodeSocket *sock;
+ bNodeLink *link;
for (sock=gnode->outputs.first; sock; sock=sock->next) {
int old_index = sock->to_index;
- for (gsock=ngroup->outputs.first; gsock; gsock=gsock->next) {
- if (gsock->link && gsock->link->fromsock->own_index == old_index) {
- sock->own_index = gsock->own_index;
- break;
+
+ for (link = ngroup->links.first; link; link = link->next) {
+ if (link->tonode->type == NODE_GROUP_OUTPUT && link->fromsock->own_index == old_index) {
+ strcpy(sock->identifier, link->fromsock->identifier);
+ /* deprecated */
+ sock->own_index = link->fromsock->own_index;
+ sock->to_index = 0;
+ sock->groupsock = NULL;
}
}
}
for (sock=gnode->inputs.first; sock; sock=sock->next) {
int old_index = sock->to_index;
- /* can't use break in double loop */
- found = 0;
- for (intnode=ngroup->nodes.first; intnode && !found; intnode=intnode->next) {
- for (intsock=intnode->inputs.first; intsock; intsock=intsock->next) {
- if (intsock->own_index == old_index && intsock->link) {
- sock->own_index = intsock->link->fromsock->own_index;
- found = 1;
- break;
- }
+
+ for (link = ngroup->links.first; link; link = link->next) {
+ if (link->fromnode->type == NODE_GROUP_INPUT && link->tosock->own_index == old_index) {
+ strcpy(sock->identifier, link->tosock->identifier);
+ /* deprecated */
+ sock->own_index = link->tosock->own_index;
+ sock->to_index = 0;
+ sock->groupsock = NULL;
}
}
}
}
-/* updates external links for all group nodes in a tree */
-static void lib_nodetree_do_versions_group_indices_cb(void *UNUSED(data), ID *UNUSED(id), bNodeTree *ntree)
-{
- bNode *node;
-
- for (node = ntree->nodes.first; node; node = node->next) {
- if (node->type == NODE_GROUP) {
- bNodeTree *ngroup = (bNodeTree*)node->id;
- if (ngroup && (ngroup->flag & NTREE_DO_VERSIONS_GROUP_EXPOSE))
- lib_node_do_versions_group_indices(node);
- }
- }
-}
-
-/* make an update call for the tree */
-static void lib_nodetree_do_versions_update_cb(void *UNUSED(data), ID *UNUSED(id), bNodeTree *ntree)
-{
- if (ntree->update)
- ntreeUpdateTree(ntree);
-}
-
/* verify types for nodes and groups, all data has to be read */
/* open = 0: appending/linking, open = 1: open new file (need to clean out dynamic
* typedefs */
static void lib_verify_nodetree(Main *main, int UNUSED(open))
{
bNodeTree *ntree;
- int i;
- bNodeTreeType *ntreetype;
/* this crashes blender on undo/redo */
#if 0
@@ -2447,41 +2410,138 @@ static void lib_verify_nodetree(Main *main, int UNUSED(open))
#endif
/* set node->typeinfo pointers */
- for (i = 0; i < NUM_NTREE_TYPES; ++i) {
- ntreetype = ntreeGetType(i);
- if (ntreetype && ntreetype->foreach_nodetree)
- ntreetype->foreach_nodetree(main, NULL, lib_nodetree_init_types_cb);
- }
- for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next)
- lib_nodetree_init_types_cb(NULL, NULL, ntree);
+ FOREACH_NODETREE(main, ntree, id) {
+ ntreeSetTypes(NULL, ntree);
+ } FOREACH_NODETREE_END
+
+ /* verify static socket templates */
+ FOREACH_NODETREE(main, ntree, id) {
+ bNode *node;
+ for (node=ntree->nodes.first; node; node=node->next)
+ node_verify_socket_templates(ntree, node);
+ } FOREACH_NODETREE_END
{
int has_old_groups = 0;
/* XXX this should actually be part of do_versions, but since we need
* finished library linking, it is not possible there. Instead in do_versions
- * we have set the NTREE_DO_VERSIONS flag, so at this point we can do the
+ * we have set the NTREE_DO_VERSIONS_GROUP_EXPOSE_2_56_2 flag, so at this point we can do the
* actual group node updates.
*/
for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next) {
- if (ntree->flag & NTREE_DO_VERSIONS_GROUP_EXPOSE) {
- /* this adds copies and links from all unlinked internal sockets to group inputs/outputs. */
- node_group_expose_all_sockets(ntree);
+ if (ntree->flag & NTREE_DO_VERSIONS_GROUP_EXPOSE_2_56_2)
has_old_groups = 1;
- }
}
if (has_old_groups) {
- for (i = 0; i < NUM_NTREE_TYPES; ++i) {
- ntreetype = ntreeGetType(i);
- if (ntreetype && ntreetype->foreach_nodetree)
- ntreetype->foreach_nodetree(main, NULL, lib_nodetree_do_versions_group_indices_cb);
- }
+ FOREACH_NODETREE(main, ntree, id) {
+ /* updates external links for all group nodes in a tree */
+ bNode *node;
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == NODE_GROUP) {
+ bNodeTree *ngroup = (bNodeTree*)node->id;
+ if (ngroup && (ngroup->flag & NTREE_DO_VERSIONS_GROUP_EXPOSE_2_56_2))
+ lib_node_do_versions_group_indices(node);
+ }
+ }
+ } FOREACH_NODETREE_END
}
for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next)
- ntree->flag &= ~NTREE_DO_VERSIONS_GROUP_EXPOSE;
+ ntree->flag &= ~NTREE_DO_VERSIONS_GROUP_EXPOSE_2_56_2;
}
+
+ {
+ /* Convert the previously used ntree->inputs/ntree->outputs lists to interface nodes.
+ * Pre 2.56.2 node trees automatically have all unlinked sockets exposed already
+ * (see NTREE_DO_VERSIONS_GROUP_EXPOSE_2_56_2).
+ *
+ * XXX this should actually be part of do_versions,
+ * but needs valid typeinfo pointers to create interface nodes.
+ */
+ for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next) {
+ if (ntree->flag & NTREE_DO_VERSIONS_CUSTOMNODES_GROUP) {
+ bNode *input_node = NULL, *output_node = NULL;
+ int num_inputs = 0, num_outputs = 0;
+ bNodeLink *link, *next_link;
+ /* Only create new interface nodes for actual older files.
+ * New file versions already have input/output nodes with duplicate links,
+ * in that case just remove the invalid links.
+ */
+ int create_io_nodes = (ntree->flag & NTREE_DO_VERSIONS_CUSTOMNODES_GROUP_CREATE_INTERFACE);
+
+ float input_locx = 1000000.0f, input_locy = 0.0f;
+ float output_locx = -1000000.0f, output_locy = 0.0f;
+ /* rough guess, not nice but we don't have access to UI constants here ... */
+ static const float offsetx = 42 + 3*20 + 20;
+ /*static const float offsety = 0.0f;*/
+
+ if (create_io_nodes) {
+ if (ntree->inputs.first)
+ input_node = nodeAddStaticNode(NULL, ntree, NODE_GROUP_INPUT);
+
+ if (ntree->outputs.first)
+ output_node = nodeAddStaticNode(NULL, ntree, NODE_GROUP_OUTPUT);
+ }
+
+ /* Redirect links from/to the node tree interface to input/output node.
+ * If the fromnode/tonode pointers are NULL, this means a link from/to
+ * the ntree interface sockets, which need to be redirected to new interface nodes.
+ */
+ for (link = ntree->links.first; link; link = next_link) {
+ int free_link = FALSE;
+ next_link = link->next;
+
+ if (link->fromnode == NULL) {
+ if (input_node) {
+ link->fromnode = input_node;
+ link->fromsock = node_group_input_find_socket(input_node, link->fromsock->identifier);
+ ++num_inputs;
+
+ if (input_locx > link->tonode->locx - offsetx)
+ input_locx = link->tonode->locx - offsetx;
+ input_locy += link->tonode->locy;
+ }
+ else
+ free_link = TRUE;
+ }
+
+ if (link->tonode == NULL) {
+ if (output_node) {
+ link->tonode = output_node;
+ link->tosock = node_group_output_find_socket(output_node, link->tosock->identifier);
+ ++num_outputs;
+
+ if (output_locx < link->fromnode->locx + offsetx)
+ output_locx = link->fromnode->locx + offsetx;
+ output_locy += link->fromnode->locy;
+ }
+ else
+ free_link = TRUE;
+ }
+
+ if (free_link)
+ nodeRemLink(ntree, link);
+ }
+
+ if (num_inputs > 0) {
+ input_locy /= num_inputs;
+ input_node->locx = input_locx;
+ input_node->locy = input_locy;
+ }
+ if (num_outputs > 0) {
+ output_locy /= num_outputs;
+ output_node->locx = output_locx;
+ output_node->locy = output_locy;
+ }
+
+ /* clear do_versions flags */
+ ntree->flag &= ~(NTREE_DO_VERSIONS_CUSTOMNODES_GROUP | NTREE_DO_VERSIONS_CUSTOMNODES_GROUP_CREATE_INTERFACE);
+ }
+ }
+ }
+
/* verify all group user nodes */
for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next) {
ntreeVerifyNodes(main, &ntree->id);
@@ -2489,21 +2549,22 @@ static void lib_verify_nodetree(Main *main, int UNUSED(open))
/* make update calls where necessary */
{
- for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next)
+ FOREACH_NODETREE(main, ntree, id) {
+ /* make an update call for the tree */
if (ntree->update)
ntreeUpdateTree(ntree);
-
- for (i = 0; i < NUM_NTREE_TYPES; i++) {
- ntreetype = ntreeGetType(i);
- if (ntreetype && ntreetype->foreach_nodetree)
- ntreetype->foreach_nodetree(main, NULL, lib_nodetree_do_versions_update_cb);
- }
+ } FOREACH_NODETREE_END
}
}
static void direct_link_node_socket(FileData *fd, bNodeSocket *sock)
{
+ sock->prop = newdataadr(fd, sock->prop);
+ if (sock->prop)
+ IDP_DirectLinkProperty(sock->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
+
sock->link = newdataadr(fd, sock->link);
+ sock->typeinfo = NULL;
sock->storage = newdataadr(fd, sock->storage);
sock->default_value = newdataadr(fd, sock->default_value);
sock->cache = NULL;
@@ -2518,6 +2579,10 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree)
bNodeLink *link;
ntree->init = 0; /* to set callbacks and force setting types */
+ ntree->is_updating = FALSE;
+ ntree->typeinfo= NULL;
+ ntree->interface_type = NULL;
+
ntree->progress = NULL;
ntree->execdata = NULL;
@@ -2533,6 +2598,10 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree)
link_list(fd, &node->inputs);
link_list(fd, &node->outputs);
+ node->prop = newdataadr(fd, node->prop);
+ if (node->prop)
+ IDP_DirectLinkProperty(node->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
+
link_list(fd, &node->internal_links);
for (link = node->internal_links.first; link; link = link->next) {
link->fromnode = newdataadr(fd, link->fromnode);
@@ -2544,8 +2613,9 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree)
if (node->type == CMP_NODE_MOVIEDISTORTION) {
node->storage = newmclipadr(fd, node->storage);
}
- else
+ else {
node->storage = newdataadr(fd, node->storage);
+ }
if (node->storage) {
/* could be handlerized at some point */
@@ -2556,9 +2626,6 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree)
else if (node->type==SH_NODE_SCRIPT) {
NodeShaderScript *nss = (NodeShaderScript *) node->storage;
nss->bytecode = newdataadr(fd, nss->bytecode);
- nss->prop = newdataadr(fd, nss->prop);
- if (nss->prop)
- IDP_DirectLinkProperty(nss->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
}
}
else if (ntree->type==NTREE_COMPOSIT) {
@@ -2577,14 +2644,9 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree)
}
link_list(fd, &ntree->links);
- /* external sockets */
- link_list(fd, &ntree->inputs);
- link_list(fd, &ntree->outputs);
-
/* and we connect the rest */
for (node = ntree->nodes.first; node; node = node->next) {
node->parent = newdataadr(fd, node->parent);
- node->preview = newimaadr(fd, node->preview);
node->lasty = 0;
for (sock = node->inputs.first; sock; sock = sock->next)
@@ -2592,6 +2654,10 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree)
for (sock = node->outputs.first; sock; sock = sock->next)
direct_link_node_socket(fd, sock);
}
+
+ /* interface socket lists */
+ link_list(fd, &ntree->inputs);
+ link_list(fd, &ntree->outputs);
for (sock = ntree->inputs.first; sock; sock = sock->next)
direct_link_node_socket(fd, sock);
for (sock = ntree->outputs.first; sock; sock = sock->next)
@@ -2604,6 +2670,29 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree)
link->tosock = newdataadr(fd, link->tosock);
}
+#if 0
+ if (ntree->previews) {
+ bNodeInstanceHash *new_previews = BKE_node_instance_hash_new("node previews");
+ bNodeInstanceHashIterator iter;
+
+ NODE_INSTANCE_HASH_ITER(iter, ntree->previews) {
+ bNodePreview *preview = BKE_node_instance_hash_iterator_get_value(&iter);
+ if (preview) {
+ bNodePreview *new_preview = newimaadr(fd, preview);
+ if (new_preview) {
+ bNodeInstanceKey key = BKE_node_instance_hash_iterator_get_key(&iter);
+ BKE_node_instance_hash_insert(new_previews, key, new_preview);
+ }
+ }
+ }
+ BKE_node_instance_hash_free(ntree->previews, NULL);
+ ntree->previews = new_previews;
+ }
+#else
+ /* XXX TODO */
+ ntree->previews = NULL;
+#endif
+
/* type verification is in lib-link */
}
@@ -5543,28 +5632,34 @@ static void lib_link_screen(FileData *fd, Main *main)
}
else if (sl->spacetype == SPACE_NODE) {
SpaceNode *snode = (SpaceNode *)sl;
+ bNodeTreePath *path, *path_next;
- snode->id = newlibadr(fd, sc->id.lib, snode->id);
+ for (path=snode->treepath.first; path; path=path->next) {
+ path->nodetree = newlibadr(fd, sc->id.lib, path->nodetree);
+
+ if (!path->nodetree)
+ break;
+ }
- if (ELEM3(snode->treetype, NTREE_COMPOSIT, NTREE_SHADER, NTREE_TEXTURE)) {
- /* internal data, a bit patchy */
- snode->nodetree = NULL;
- if (snode->id) {
- if (GS(snode->id->name)==ID_MA)
- snode->nodetree = ((Material *)snode->id)->nodetree;
- else if (GS(snode->id->name)==ID_WO)
- snode->nodetree = ((World *)snode->id)->nodetree;
- else if (GS(snode->id->name)==ID_LA)
- snode->nodetree = ((Lamp *)snode->id)->nodetree;
- else if (GS(snode->id->name)==ID_SCE)
- snode->nodetree = ((Scene *)snode->id)->nodetree;
- else if (GS(snode->id->name)==ID_TE)
- snode->nodetree = ((Tex *)snode->id)->nodetree;
- }
+ /* remaining path entries are invalid, remove */
+ for (; path; path = path_next) {
+ path_next = path->next;
+
+ BLI_remlink(&snode->treepath, path);
+ MEM_freeN(path);
}
- else {
- snode->nodetree = newlibadr_us(fd, sc->id.lib, snode->nodetree);
+
+ snode->nodetree = newlibadr(fd, sc->id.lib, snode->nodetree);
+ /* edittree is just the last in the path,
+ * set this directly since the path may have been shortened above */
+ if (snode->treepath.last) {
+ path = snode->treepath.last;
+ snode->edittree = path->nodetree;
}
+ else
+ snode->edittree = NULL;
+ snode->id = newlibadr(fd, sc->id.lib, snode->id);
+ snode->from = newlibadr(fd, sc->id.lib, snode->from);
}
else if (sl->spacetype == SPACE_CLIP) {
SpaceClip *sclip = (SpaceClip *)sl;
@@ -5584,6 +5679,24 @@ static void lib_link_screen(FileData *fd, Main *main)
}
}
+static bool restore_pointer(ID *id, ID *newid, int user)
+{
+ if (strcmp(newid->name+2, id->name+2) == 0) {
+ if (newid->lib == id->lib) {
+ if (user == 1) {
+ if (newid->us == 0) {
+ newid->us++;
+ }
+ }
+ else if (user == 2) {
+ id_us_ensure_real(newid);
+ }
+ return true;
+ }
+ }
+ return false;
+}
+
/**
* Only for undo files, or to restore a screen after reading without UI...
*
@@ -5595,30 +5708,33 @@ static void lib_link_screen(FileData *fd, Main *main)
static void *restore_pointer_by_name(Main *mainp, ID *id, int user)
{
if (id) {
- ListBase *lb = which_libbase(mainp, GS(id->name));
-
- if (lb) { // there's still risk of checking corrupt mem (freed Ids in oops)
- ID *idn = lb->first;
- char *name = id->name + 2;
-
- for (; idn; idn = idn->next) {
- if (idn->name[2] == name[0] && strcmp(idn->name+2, name) == 0) {
- if (idn->lib == id->lib) {
- if (user == 1) {
- if (idn->us == 0) {
- idn->us++;
- }
- }
- else if (user == 2) {
- id_us_ensure_real(idn);
- }
- break;
- }
+ /* node trees can be stored locally in other IDs, needs special handling ... */
+ if (GS(id->name) == ID_NT) {
+ ID *idn = NULL;
+
+ FOREACH_NODETREE(mainp, ntree, owner_id) {
+ if (restore_pointer(id, &ntree->id, user)) {
+ idn = &ntree->id;
+ break;
}
}
+ FOREACH_NODETREE_END
return idn;
}
+ else {
+ ListBase *lb = which_libbase(mainp, GS(id->name));
+ if (lb) { // there's still risk of checking corrupt mem (freed Ids in oops)
+ ID *idn = lb->first;
+
+ for (; idn; idn = idn->next) {
+ if (restore_pointer(id, idn, user))
+ break;
+ }
+
+ return idn;
+ }
+ }
}
return NULL;
}
@@ -5848,24 +5964,34 @@ void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *cursc
}
else if (sl->spacetype == SPACE_NODE) {
SpaceNode *snode= (SpaceNode *)sl;
+ bNodeTreePath *path, *path_next;
- snode->id = restore_pointer_by_name(newmain, snode->id, 1);
- snode->edittree = NULL;
+ for (path=snode->treepath.first; path; path=path->next) {
+ path->nodetree= restore_pointer_by_name(newmain, (ID*)path->nodetree, 0);
+
+ if (!path->nodetree)
+ break;
+ }
- if (ELEM3(snode->treetype, NTREE_COMPOSIT, NTREE_SHADER, NTREE_TEXTURE)) {
- snode->nodetree = NULL;
- if (snode->id) {
- if (GS(snode->id->name)==ID_MA)
- snode->nodetree = ((Material *)snode->id)->nodetree;
- else if (GS(snode->id->name)==ID_SCE)
- snode->nodetree = ((Scene *)snode->id)->nodetree;
- else if (GS(snode->id->name)==ID_TE)
- snode->nodetree = ((Tex *)snode->id)->nodetree;
- }
+ /* remaining path entries are invalid, remove */
+ for (; path; path = path_next) {
+ path_next = path->next;
+
+ BLI_remlink(&snode->treepath, path);
+ MEM_freeN(path);
}
- else {
- snode->nodetree= restore_pointer_by_name(newmain, &snode->nodetree->id, 1);
+
+ snode->nodetree = restore_pointer_by_name(newmain, (ID*)snode->nodetree, 0);
+ /* edittree is just the last in the path,
+ * set this directly since the path may have been shortened above */
+ if (snode->treepath.last) {
+ path = snode->treepath.last;
+ snode->edittree = path->nodetree;
}
+ else
+ snode->edittree = NULL;
+ snode->id = restore_pointer_by_name(newmain, snode->id, 1);
+ snode->from = restore_pointer_by_name(newmain, snode->from, 0);
}
else if (sl->spacetype == SPACE_CLIP) {
SpaceClip *sclip = (SpaceClip *)sl;
@@ -6116,6 +6242,8 @@ static void direct_link_screen(FileData *fd, bScreen *sc)
snode->gpd = newdataadr(fd, snode->gpd);
direct_link_gpencil(fd, snode->gpd);
}
+
+ link_list(fd, &snode->treepath);
snode->edittree = NULL;
snode->linkdrag.first = snode->linkdrag.last = NULL;
}
@@ -6855,7 +6983,6 @@ static void link_global(FileData *fd, BlendFileData *bfd)
}
}
-/* deprecated, only keep this for readfile.c */
void convert_tface_mt(FileData *fd, Main *main)
{
Main *gmain;
@@ -6890,22 +7017,6 @@ static void do_versions_nodetree_image_default_alpha_output(bNodeTree *ntree)
}
}
-static void do_version_ntree_tex_mapping_260(void *UNUSED(data), ID *UNUSED(id), bNodeTree *ntree)
-{
- bNode *node;
-
- for (node = ntree->nodes.first; node; node = node->next) {
- if (node->type == SH_NODE_MAPPING) {
- TexMapping *tex_mapping;
-
- tex_mapping= node->storage;
- tex_mapping->projx= PROJ_X;
- tex_mapping->projy= PROJ_Y;
- tex_mapping->projz= PROJ_Z;
- }
- }
-}
-
static void do_versions_nodetree_convert_angle(bNodeTree *ntree)
{
bNode *node;
@@ -7240,151 +7351,6 @@ static void do_versions_nodetree_frame_2_64_6(bNodeTree *ntree)
}
}
-static void do_version_ntree_image_user_264(void *UNUSED(data), ID *UNUSED(id), bNodeTree *ntree)
-{
- bNode *node;
-
- for (node = ntree->nodes.first; node; node = node->next) {
- if (ELEM(node->type, SH_NODE_TEX_IMAGE, SH_NODE_TEX_ENVIRONMENT)) {
- NodeTexImage *tex = node->storage;
-
- tex->iuser.frames= 1;
- tex->iuser.sfra= 1;
- tex->iuser.fie_ima= 2;
- tex->iuser.ok= 1;
- }
- }
-}
-
-static void do_version_ntree_dilateerode_264(void *UNUSED(data), ID *UNUSED(id), bNodeTree *ntree)
-{
- bNode *node;
-
- for (node = ntree->nodes.first; node; node = node->next) {
- if (node->type == CMP_NODE_DILATEERODE) {
- if (node->storage == NULL) {
- NodeDilateErode *data = MEM_callocN(sizeof(NodeDilateErode), __func__);
- data->falloff = PROP_SMOOTH;
- node->storage = data;
- }
- }
- }
-}
-
-static void do_version_ntree_defocus_264(void *UNUSED(data), ID *UNUSED(id), bNodeTree *ntree)
-{
- bNode *node;
-
- for (node = ntree->nodes.first; node; node = node->next) {
- if (node->type == CMP_NODE_DEFOCUS) {
- NodeDefocus *data = node->storage;
- if (data->maxblur == 0.0f) {
- data->maxblur = 16.0f;
- }
- }
- }
-}
-
-static void do_version_ntree_mask_264(void *UNUSED(data), ID *UNUSED(id), bNodeTree *ntree)
-{
- bNode *node;
-
- for (node = ntree->nodes.first; node; node = node->next) {
- if (node->type == CMP_NODE_MASK) {
- if (node->storage == NULL) {
- NodeMask *data = MEM_callocN(sizeof(NodeMask), __func__);
- /* move settings into own struct */
- data->size_x = (int)node->custom3;
- data->size_y = (int)node->custom4;
- node->custom3 = 0.5f; /* default shutter */
- node->storage = data;
- }
- }
- }
-}
-
-static void do_version_ntree_keying_despill_balance(void *UNUSED(data), ID *UNUSED(id), bNodeTree *ntree)
-{
- bNode *node;
-
- for (node = ntree->nodes.first; node; node = node->next) {
- if (node->type == CMP_NODE_KEYING) {
- NodeKeyingData *data = node->storage;
-
- if (data->despill_balance == 0.0f) {
- data->despill_balance = 0.5f;
- }
- }
- }
-}
-
-static void do_version_ntree_tex_coord_from_dupli_264(void *UNUSED(data), ID *UNUSED(id), bNodeTree *ntree)
-{
- bNode *node;
-
- for (node = ntree->nodes.first; node; node = node->next)
- if (node->type == SH_NODE_TEX_COORD)
- node->flag |= NODE_OPTIONS;
-}
-
-static void do_version_node_cleanup_dynamic_sockets_264(void *UNUSED(data), ID *UNUSED(id), bNodeTree *ntree)
-{
- bNode *node;
- bNodeSocket *sock;
-
- for (node = ntree->nodes.first; node; node = node->next) {
- if (!ELEM(node->type, NODE_GROUP, CMP_NODE_IMAGE)) {
- for (sock = node->inputs.first; sock; sock = sock->next)
- sock->flag &= ~SOCK_DYNAMIC;
- for (sock = node->outputs.first; sock; sock = sock->next)
- sock->flag &= ~SOCK_DYNAMIC;
- }
- }
-}
-
-static void do_version_node_fix_translate_wrapping(void *UNUSED(data), ID *UNUSED(id), bNodeTree *ntree)
-{
- bNode *node;
-
- for (node = ntree->nodes.first; node; node = node->next) {
- if (node->type == CMP_NODE_TRANSLATE && node->storage == NULL) {
- node->storage = MEM_callocN(sizeof(NodeTranslateData), "node translate data");
- }
- }
-}
-
-static void do_version_node_straight_image_alpha_workaround(void *data, ID *UNUSED(id), bNodeTree *ntree)
-{
- FileData *fd = (FileData *) data;
- bNode *node;
-
- for (node = ntree->nodes.first; node; node = node->next) {
- if (node->type == CMP_NODE_IMAGE) {
- Image *image = blo_do_versions_newlibadr(fd, ntree->id.lib, node->id);
-
- if (image) {
- if ((image->flag & IMA_DO_PREMUL) == 0 && image->alpha_mode == IMA_ALPHA_STRAIGHT)
- node->custom1 |= CMP_NODE_IMAGE_USE_STRAIGHT_OUTPUT;
- }
- }
- }
-}
-
-static void do_version_node_fix_internal_links_264(void *UNUSED(data), ID *UNUSED(id), bNodeTree *ntree)
-{
- bNode *node;
- bNodeLink *link, *nextlink;
-
- for (node = ntree->nodes.first; node; node = node->next) {
- for (link = node->internal_links.first; link; link = nextlink) {
- nextlink = link->next;
- if (!link->fromnode || !link->fromsock || !link->tonode || !link->tosock) {
- BLI_remlink(&node->internal_links, link);
- }
- }
- }
-}
-
static void do_version_logic_264(ListBase *regionbase)
{
ARegion *ar;
@@ -7436,6 +7402,146 @@ static void do_versions_affine_tracker_track(MovieTrackingTrack *track)
}
}
+
+static const char *node_get_static_idname(int type, int treetype)
+{
+ /* use static type info header to map static int type to identifier string */
+ #define DefNode(Category, ID, DefFunc, EnumName, StructName, UIName, UIDesc) \
+ case ID: return #Category #StructName;
+
+ /* XXX hack, group types share a single static integer identifier, but are registered as separate types */
+ if (type == NODE_GROUP) {
+ switch (treetype) {
+ case NTREE_COMPOSIT: return "CompositorNodeGroup";
+ case NTREE_SHADER: return "ShaderNodeGroup";
+ case NTREE_TEXTURE: return "TextureNodeGroup";
+ }
+ }
+ else {
+ switch (type) {
+ #include "NOD_static_types.h"
+ }
+ }
+ return "";
+}
+
+static const char *node_socket_get_static_idname(bNodeSocket *sock)
+{
+ switch (sock->type) {
+ case SOCK_FLOAT: {
+ bNodeSocketValueFloat *dval = sock->default_value;
+ return nodeStaticSocketType(SOCK_FLOAT, dval->subtype);
+ }
+ case SOCK_INT: {
+ bNodeSocketValueInt *dval = sock->default_value;
+ return nodeStaticSocketType(SOCK_INT, dval->subtype);
+ }
+ case SOCK_BOOLEAN: {
+ return nodeStaticSocketType(SOCK_BOOLEAN, PROP_NONE);
+ }
+ case SOCK_VECTOR: {
+ bNodeSocketValueVector *dval = sock->default_value;
+ return nodeStaticSocketType(SOCK_VECTOR, dval->subtype);
+ }
+ case SOCK_RGBA: {
+ return nodeStaticSocketType(SOCK_RGBA, PROP_NONE);
+ }
+ case SOCK_STRING: {
+ bNodeSocketValueString *dval = sock->default_value;
+ return nodeStaticSocketType(SOCK_STRING, dval->subtype);
+ }
+ case SOCK_SHADER: {
+ return nodeStaticSocketType(SOCK_SHADER, PROP_NONE);
+ }
+ }
+ return "";
+}
+
+static void do_versions_nodetree_customnodes(bNodeTree *ntree, int UNUSED(is_group))
+{
+ /* initialize node tree type idname */
+ {
+ bNode *node;
+ bNodeSocket *sock;
+
+ ntree->typeinfo = NULL;
+
+ /* tree type idname */
+ switch (ntree->type) {
+ case NTREE_COMPOSIT:
+ strcpy(ntree->idname, "CompositorNodeTree");
+ break;
+ case NTREE_SHADER:
+ strcpy(ntree->idname, "ShaderNodeTree");
+ break;
+ case NTREE_TEXTURE:
+ strcpy(ntree->idname, "TextureNodeTree");
+ break;
+ }
+
+ /* node type idname */
+ for (node=ntree->nodes.first; node; node=node->next) {
+ BLI_strncpy(node->idname, node_get_static_idname(node->type, ntree->type), sizeof(node->idname));
+
+ /* existing old nodes have been initialized already */
+ node->flag |= NODE_INIT;
+
+ /* sockets idname */
+ for (sock=node->inputs.first; sock; sock=sock->next)
+ BLI_strncpy(sock->idname, node_socket_get_static_idname(sock), sizeof(sock->idname));
+ for (sock=node->outputs.first; sock; sock=sock->next)
+ BLI_strncpy(sock->idname, node_socket_get_static_idname(sock), sizeof(sock->idname));
+ }
+ /* tree sockets idname */
+ for (sock=ntree->inputs.first; sock; sock=sock->next)
+ BLI_strncpy(sock->idname, node_socket_get_static_idname(sock), sizeof(sock->idname));
+ for (sock=ntree->outputs.first; sock; sock=sock->next)
+ BLI_strncpy(sock->idname, node_socket_get_static_idname(sock), sizeof(sock->idname));
+ }
+
+ /* initialize socket in_out values */
+ {
+ bNode *node;
+ bNodeSocket *sock;
+
+ for (node=ntree->nodes.first; node; node=node->next) {
+ for (sock=node->inputs.first; sock; sock=sock->next)
+ sock->in_out = SOCK_IN;
+ for (sock=node->outputs.first; sock; sock=sock->next)
+ sock->in_out = SOCK_OUT;
+ }
+ for (sock=ntree->inputs.first; sock; sock=sock->next)
+ sock->in_out = SOCK_IN;
+ for (sock=ntree->outputs.first; sock; sock=sock->next)
+ sock->in_out = SOCK_OUT;
+ }
+
+ /* initialize socket identifier strings */
+ {
+ bNode *node;
+ bNodeSocket *sock;
+
+ for (node=ntree->nodes.first; node; node=node->next) {
+ for (sock=node->inputs.first; sock; sock=sock->next) {
+ BLI_strncpy(sock->identifier, sock->name, sizeof(sock->identifier));
+ BLI_uniquename(&node->inputs, sock, sock->identifier, '.', offsetof(bNodeSocket, identifier), sizeof(sock->identifier));
+ }
+ for (sock=node->outputs.first; sock; sock=sock->next) {
+ BLI_strncpy(sock->identifier, sock->name, sizeof(sock->identifier));
+ BLI_uniquename(&node->outputs, sock, sock->identifier, '.', offsetof(bNodeSocket, identifier), sizeof(sock->identifier));
+ }
+ }
+ for (sock=ntree->inputs.first; sock; sock=sock->next) {
+ BLI_strncpy(sock->identifier, sock->name, sizeof(sock->identifier));
+ BLI_uniquename(&ntree->inputs, sock, sock->identifier, '.', offsetof(bNodeSocket, identifier), sizeof(sock->identifier));
+ }
+ for (sock=ntree->outputs.first; sock; sock=sock->next) {
+ BLI_strncpy(sock->identifier, sock->name, sizeof(sock->identifier));
+ BLI_uniquename(&ntree->outputs, sock, sock->identifier, '.', offsetof(bNodeSocket, identifier), sizeof(sock->identifier));
+ }
+ }
+}
+
/* initialize userdef with non-UI dependency stuff */
/* other initializers (such as theme color defaults) go to resources.c */
static void do_versions_userdef(FileData *fd, BlendFileData *bfd)
@@ -7451,7 +7557,6 @@ static void do_versions_userdef(FileData *fd, BlendFileData *bfd)
user->image_gpubuffer_limit = 10;
}
}
-
static void do_versions(FileData *fd, Library *lib, Main *main)
{
/* WATCH IT!!!: pointers from libdata have not been converted */
@@ -7517,10 +7622,21 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
}
if (main->versionfile < 260 || (main->versionfile == 260 && main->subversionfile < 2)) {
- bNodeTreeType *ntreetype = ntreeGetType(NTREE_SHADER);
-
- if (ntreetype && ntreetype->foreach_nodetree)
- ntreetype->foreach_nodetree(main, NULL, do_version_ntree_tex_mapping_260);
+ FOREACH_NODETREE(main, ntree, id) {
+ if (ntree->type == NTREE_SHADER) {
+ bNode *node;
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == SH_NODE_MAPPING) {
+ TexMapping *tex_mapping;
+
+ tex_mapping= node->storage;
+ tex_mapping->projx= PROJ_X;
+ tex_mapping->projy= PROJ_Y;
+ tex_mapping->projz= PROJ_Z;
+ }
+ }
+ }
+ } FOREACH_NODETREE_END
}
if (main->versionfile < 260 || (main->versionfile == 260 && main->subversionfile < 4)) {
@@ -8156,16 +8272,26 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
}
if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 9)) {
- bNodeTreeType *ntreetype = ntreeGetType(NTREE_SHADER);
-
- if (ntreetype && ntreetype->foreach_nodetree)
- ntreetype->foreach_nodetree(main, NULL, do_version_ntree_image_user_264);
+ FOREACH_NODETREE(main, ntree, id) {
+ if (ntree->type == NTREE_SHADER) {
+ bNode *node;
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (ELEM(node->type, SH_NODE_TEX_IMAGE, SH_NODE_TEX_ENVIRONMENT)) {
+ NodeTexImage *tex = node->storage;
+
+ tex->iuser.frames= 1;
+ tex->iuser.sfra= 1;
+ tex->iuser.fie_ima= 2;
+ tex->iuser.ok= 1;
+ }
+ }
+ }
+ } FOREACH_NODETREE_END
}
if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 10)) {
{
Scene *scene;
- bNodeTreeType *ntreetype;
// composite redesign
for (scene=main->scene.first; scene; scene=scene->id.next) {
if (scene->nodetree) {
@@ -8174,11 +8300,20 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
}
}
}
- ntreetype = ntreeGetType(NTREE_COMPOSIT);
-
- if (ntreetype && ntreetype->foreach_nodetree)
- ntreetype->foreach_nodetree(main, NULL, do_version_ntree_defocus_264);
+ FOREACH_NODETREE(main, ntree, id) {
+ if (ntree->type == NTREE_COMPOSIT) {
+ bNode *node;
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == CMP_NODE_DEFOCUS) {
+ NodeDefocus *data = node->storage;
+ if (data->maxblur == 0.0f) {
+ data->maxblur = 16.0f;
+ }
+ }
+ }
+ }
+ } FOREACH_NODETREE_END
}
{
@@ -8236,19 +8371,40 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
}
if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 13)) {
- bNodeTreeType *ntreetype = ntreeGetType(NTREE_COMPOSIT);
-
- if (ntreetype && ntreetype->foreach_nodetree)
- ntreetype->foreach_nodetree(main, NULL, do_version_ntree_dilateerode_264);
+ FOREACH_NODETREE(main, ntree, id) {
+ if (ntree->type == NTREE_COMPOSIT) {
+ bNode *node;
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == CMP_NODE_DILATEERODE) {
+ if (node->storage == NULL) {
+ NodeDilateErode *data = MEM_callocN(sizeof(NodeDilateErode), __func__);
+ data->falloff = PROP_SMOOTH;
+ node->storage = data;
+ }
+ }
+ }
+ }
+ } FOREACH_NODETREE_END
}
if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 14)) {
ParticleSettings *part;
- bNodeTreeType *ntreetype = ntreeGetType(NTREE_COMPOSIT);
-
- if (ntreetype && ntreetype->foreach_nodetree)
- ntreetype->foreach_nodetree(main, NULL, do_version_ntree_keying_despill_balance);
-
+
+ FOREACH_NODETREE(main, ntree, id) {
+ if (ntree->type == NTREE_COMPOSIT) {
+ bNode *node;
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == CMP_NODE_KEYING) {
+ NodeKeyingData *data = node->storage;
+
+ if (data->despill_balance == 0.0f) {
+ data->despill_balance = 0.5f;
+ }
+ }
+ }
+ }
+ } FOREACH_NODETREE_END
+
/* keep compatibility for dupliobject particle size */
for (part=main->particle.first; part; part=part->id.next)
if (ELEM(part->ren_as, PART_DRAW_OB, PART_DRAW_GR))
@@ -8257,12 +8413,25 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
}
if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 17)) {
- bNodeTreeType *ntreetype = ntreeGetType(NTREE_COMPOSIT);
-
- if (ntreetype && ntreetype->foreach_nodetree)
- ntreetype->foreach_nodetree(main, NULL, do_version_ntree_mask_264);
+ FOREACH_NODETREE(main, ntree, id) {
+ if (ntree->type == NTREE_COMPOSIT) {
+ bNode *node;
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == CMP_NODE_MASK) {
+ if (node->storage == NULL) {
+ NodeMask *data = MEM_callocN(sizeof(NodeMask), __func__);
+ /* move settings into own struct */
+ data->size_x = (int)node->custom3;
+ data->size_y = (int)node->custom4;
+ node->custom3 = 0.5f; /* default shutter */
+ node->storage = data;
+ }
+ }
+ }
+ }
+ } FOREACH_NODETREE_END
}
-
+
if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 18)) {
Scene *scene;
@@ -8387,15 +8556,14 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
}
if (main->versionfile < 264 || (main->versionfile == 264 && main->subversionfile < 1)) {
- bNodeTreeType *ntreetype = ntreeGetType(NTREE_SHADER);
- bNodeTree *ntree;
-
- if (ntreetype && ntreetype->foreach_nodetree)
- ntreetype->foreach_nodetree(main, NULL, do_version_ntree_tex_coord_from_dupli_264);
-
- for (ntree=main->nodetree.first; ntree; ntree=ntree->id.next)
- if (ntree->type==NTREE_SHADER)
- do_version_ntree_tex_coord_from_dupli_264(NULL, NULL, ntree);
+ FOREACH_NODETREE(main, ntree, id) {
+ if (ntree->type == NTREE_SHADER) {
+ bNode *node;
+ for (node = ntree->nodes.first; node; node = node->next)
+ if (node->type == SH_NODE_TEX_COORD)
+ node->flag |= NODE_OPTIONS;
+ }
+ } FOREACH_NODETREE_END
}
if (main->versionfile < 264 || (main->versionfile == 264 && main->subversionfile < 2)) {
@@ -8481,28 +8649,6 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
}
}
- if (main->versionfile < 264 || (main->versionfile == 264 && main->subversionfile < 4)) {
- /* Fix for old node flags: Apparently the SOCK_DYNAMIC flag has been in use for other
- * purposes before and then removed and later reused for SOCK_DYNAMIC. This socket should
- * only be used by certain node types which don't use template lists, cleaning this up here.
- */
- bNodeTreeType *ntreetype;
- bNodeTree *ntree;
-
- ntreetype = ntreeGetType(NTREE_COMPOSIT);
- if (ntreetype && ntreetype->foreach_nodetree)
- ntreetype->foreach_nodetree(main, NULL, do_version_node_cleanup_dynamic_sockets_264);
- ntreetype = ntreeGetType(NTREE_SHADER);
- if (ntreetype && ntreetype->foreach_nodetree)
- ntreetype->foreach_nodetree(main, NULL, do_version_node_cleanup_dynamic_sockets_264);
- ntreetype = ntreeGetType(NTREE_TEXTURE);
- if (ntreetype && ntreetype->foreach_nodetree)
- ntreetype->foreach_nodetree(main, NULL, do_version_node_cleanup_dynamic_sockets_264);
-
- for (ntree=main->nodetree.first; ntree; ntree=ntree->id.next)
- do_version_node_cleanup_dynamic_sockets_264(NULL, NULL, ntree);
- }
-
if (main->versionfile < 264 || (main->versionfile == 264 && main->subversionfile < 5)) {
/* set a unwrapping margin and ABF by default */
Scene *scene;
@@ -8519,22 +8665,19 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
/* Fix for bug #32982, internal_links list could get corrupted from r51630 onward.
* Simply remove bad internal_links lists to avoid NULL pointers.
*/
- bNodeTreeType *ntreetype;
- bNodeTree *ntree;
-
- ntreetype = ntreeGetType(NTREE_COMPOSIT);
- if (ntreetype && ntreetype->foreach_nodetree)
- ntreetype->foreach_nodetree(main, NULL, do_version_node_fix_internal_links_264);
- ntreetype = ntreeGetType(NTREE_SHADER);
- if (ntreetype && ntreetype->foreach_nodetree)
- ntreetype->foreach_nodetree(main, NULL, do_version_node_fix_internal_links_264);
- ntreetype = ntreeGetType(NTREE_TEXTURE);
- if (ntreetype && ntreetype->foreach_nodetree)
- ntreetype->foreach_nodetree(main, NULL, do_version_node_fix_internal_links_264);
-
- for (ntree=main->nodetree.first; ntree; ntree=ntree->id.next)
- do_version_node_fix_internal_links_264(NULL, NULL, ntree);
-
+ FOREACH_NODETREE(main, ntree, id)
+ bNode *node;
+ bNodeLink *link, *nextlink;
+
+ for (node = ntree->nodes.first; node; node = node->next) {
+ for (link = node->internal_links.first; link; link = nextlink) {
+ nextlink = link->next;
+ if (!link->fromnode || !link->fromsock || !link->tonode || !link->tosock) {
+ BLI_remlink(&node->internal_links, link);
+ }
+ }
+ }
+ FOREACH_NODETREE_END
}
if (main->versionfile < 264 || (main->versionfile == 264 && main->subversionfile < 6)) {
@@ -8678,8 +8821,6 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
Scene *scene;
Image *image;
Tex *tex;
- bNodeTreeType *ntreetype;
- bNodeTree *ntree;
for (scene = main->scene.first; scene; scene = scene->id.next) {
Sequence *seq;
@@ -8735,12 +8876,21 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
}
}
- ntreetype = ntreeGetType(NTREE_COMPOSIT);
- if (ntreetype && ntreetype->foreach_nodetree)
- ntreetype->foreach_nodetree(main, fd, do_version_node_straight_image_alpha_workaround);
+ FOREACH_NODETREE(main, ntree, id) {
+ if (ntree->type == NTREE_COMPOSIT) {
+ bNode *node;
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == CMP_NODE_IMAGE) {
+ Image *image = blo_do_versions_newlibadr(fd, ntree->id.lib, node->id);
- for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next)
- do_version_node_straight_image_alpha_workaround(fd, NULL, ntree);
+ if (image) {
+ if ((image->flag & IMA_DO_PREMUL) == 0 && image->alpha_mode == IMA_ALPHA_STRAIGHT)
+ node->custom1 |= CMP_NODE_IMAGE_USE_STRAIGHT_OUTPUT;
+ }
+ }
+ }
+ }
+ } FOREACH_NODETREE_END
}
else if (main->versionfile < 266 || (main->versionfile == 266 && main->subversionfile < 1)) {
/* texture use alpha was removed for 2.66 but added back again for 2.66a,
@@ -8805,15 +8955,76 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
// add storage for compositor translate nodes when not existing
if (MAIN_VERSION_OLDER(main, 265, 11)) {
- bNodeTreeType *ntreetype;
- bNodeTree *ntree;
+ FOREACH_NODETREE(main, ntree, id) {
+ if (ntree->type == NTREE_COMPOSIT) {
+ bNode *node;
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == CMP_NODE_TRANSLATE && node->storage == NULL) {
+ node->storage = MEM_callocN(sizeof(NodeTranslateData), "node translate data");
+ }
+ }
+ }
+ } FOREACH_NODETREE_END
+ }
- ntreetype = ntreeGetType(NTREE_COMPOSIT);
- if (ntreetype && ntreetype->foreach_nodetree)
- ntreetype->foreach_nodetree(main, NULL, do_version_node_fix_translate_wrapping);
+ if (!MAIN_VERSION_ATLEAST(main, 266, 2)) {
+ FOREACH_NODETREE(main, ntree, id) {
+ do_versions_nodetree_customnodes(ntree, ((ID *)ntree == id));
+ } FOREACH_NODETREE_END
+ }
- for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next)
- do_version_node_fix_translate_wrapping(NULL, NULL, ntree);
+ if (!MAIN_VERSION_ATLEAST(main, 266, 2)) {
+ bScreen *sc;
+ for (sc= main->screen.first; sc; sc= sc->id.next) {
+ ScrArea *sa;
+ for (sa= sc->areabase.first; sa; sa= sa->next) {
+ SpaceLink *sl;
+ for (sl= sa->spacedata.first; sl; sl= sl->next) {
+ if(sl->spacetype==SPACE_NODE) {
+ SpaceNode *snode = (SpaceNode *)sl;
+
+ /* reset pointers to force tree path update from context */
+ snode->nodetree = NULL;
+ snode->edittree = NULL;
+ snode->id = NULL;
+ snode->from = NULL;
+
+ /* convert deprecated treetype setting to tree_idname */
+ switch (snode->treetype) {
+ case NTREE_COMPOSIT:
+ strcpy(snode->tree_idname, "CompositorNodeTree");
+ break;
+ case NTREE_SHADER:
+ strcpy(snode->tree_idname, "ShaderNodeTree");
+ break;
+ case NTREE_TEXTURE:
+ strcpy(snode->tree_idname, "TextureNodeTree");
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* Set flag for delayed do_versions in lib_verify_nodetree. It needs valid typeinfo pointers ... */
+ {
+ bNodeTree *ntree;
+ for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next) {
+ /* XXX This should be kept without version check for now!
+ * As long as USE_NODE_COMPAT_CUSTOMNODES is active, files will write links
+ * to tree interface sockets for forward compatibility. These links need to be removed again
+ * on file load in new versions.
+ * Once forward compatibility is not required any longer, make a subversion bump
+ * and only execute this for older versions.
+ */
+ ntree->flag |= NTREE_DO_VERSIONS_CUSTOMNODES_GROUP;
+
+ /* Only add interface nodes once.
+ * In old Blender versions they will be removed automatically due to undefined type */
+ if (!MAIN_VERSION_ATLEAST(main, 266, 2))
+ ntree->flag |= NTREE_DO_VERSIONS_CUSTOMNODES_GROUP_CREATE_INTERFACE;
+ }
}
if (main->versionfile < 267) {
diff --git a/source/blender/blenloader/intern/readfile.h b/source/blender/blenloader/intern/readfile.h
index 46b95434e53..6d5fc056d89 100644
--- a/source/blender/blenloader/intern/readfile.h
+++ b/source/blender/blenloader/intern/readfile.h
@@ -152,7 +152,6 @@ void *blo_do_versions_newlibadr_us(struct FileData *fd, void *lib, void *adr);
struct PartEff *blo_do_version_give_parteff_245(struct Object *ob);
void blo_do_version_old_trackto_to_constraints(struct Object *ob);
void blo_do_versions_view3d_split_250(struct View3D *v3d, struct ListBase *regions);
-void blo_do_versions_nodetree_default_value(struct bNodeTree *ntree);
void blo_do_versions_pre250(struct FileData *fd, struct Library *lib, struct Main *main);
void blo_do_versions_250(struct FileData *fd, struct Library *lib, struct Main *main);
diff --git a/source/blender/blenloader/intern/versioning_250.c b/source/blender/blenloader/intern/versioning_250.c
index 36f3ea3654c..f92a8678300 100644
--- a/source/blender/blenloader/intern/versioning_250.c
+++ b/source/blender/blenloader/intern/versioning_250.c
@@ -672,13 +672,90 @@ static void do_version_bone_roll_256(Bone *bone)
do_version_bone_roll_256(child);
}
-static void do_versions_nodetree_dynamic_sockets(bNodeTree *ntree)
+/* deprecated, only keep this for readfile.c */
+/* XXX Deprecated function to add a socket in ntree->inputs/ntree->outputs list
+ * (previously called node_group_add_socket). This function has been superseded
+ * by the implementation of proxy nodes. It is still necessary though
+ * for do_versions of pre-2.56.2 code (r35033), so later proxy nodes
+ * can be generated consistently from ntree socket lists.
+ */
+static bNodeSocket *do_versions_node_group_add_socket_2_56_2(bNodeTree *ngroup, const char *name, int type, int in_out)
+{
+// bNodeSocketType *stype = ntreeGetSocketType(type);
+ bNodeSocket *gsock = MEM_callocN(sizeof(bNodeSocket), "bNodeSocket");
+
+ BLI_strncpy(gsock->name, name, sizeof(gsock->name));
+ gsock->type = type;
+
+ gsock->next = gsock->prev = NULL;
+ gsock->new_sock = NULL;
+ gsock->link = NULL;
+ /* assign new unique index */
+ gsock->own_index = ngroup->cur_index++;
+ gsock->limit = (in_out==SOCK_IN ? 0xFFF : 1);
+
+// if (stype->value_structsize > 0)
+// gsock->default_value = MEM_callocN(stype->value_structsize, "default socket value");
+
+ BLI_addtail(in_out==SOCK_IN ? &ngroup->inputs : &ngroup->outputs, gsock);
+
+ ngroup->update |= (in_out==SOCK_IN ? NTREE_UPDATE_GROUP_IN : NTREE_UPDATE_GROUP_OUT);
+
+ return gsock;
+}
+
+/* Create default_value structs for node sockets from the internal bNodeStack value.
+ * These structs were used from 2.59.2 on, but are replaced in the subsequent do_versions for custom nodes
+ * by generic ID property values. This conversion happened _after_ do_versions originally due to messy type initialization
+ * for node sockets. Now created here intermediately for convenience and to keep do_versions consistent.
+ *
+ * Node compatibility code is gross ...
+ */
+static void do_versions_socket_default_value_259(bNodeSocket *sock)
+{
+ bNodeSocketValueFloat *valfloat;
+ bNodeSocketValueVector *valvector;
+ bNodeSocketValueRGBA *valrgba;
+
+ if (sock->default_value)
+ return;
+
+ switch (sock->type) {
+ case SOCK_FLOAT:
+ valfloat = sock->default_value = MEM_callocN(sizeof(bNodeSocketValueFloat), "default socket value");
+ valfloat->value = sock->ns.vec[0];
+ valfloat->min = sock->ns.min;
+ valfloat->max = sock->ns.max;
+ valfloat->subtype = PROP_NONE;
+ break;
+ case SOCK_VECTOR:
+ valvector = sock->default_value = MEM_callocN(sizeof(bNodeSocketValueVector), "default socket value");
+ copy_v3_v3(valvector->value, sock->ns.vec);
+ valvector->min = sock->ns.min;
+ valvector->max = sock->ns.max;
+ valvector->subtype = PROP_NONE;
+ break;
+ case SOCK_RGBA:
+ valrgba = sock->default_value = MEM_callocN(sizeof(bNodeSocketValueRGBA), "default socket value");
+ copy_v4_v4(valrgba->value, sock->ns.vec);
+ break;
+ }
+}
+
+static void do_versions_nodetree_default_value_259(bNodeTree *ntree)
{
+ bNode *node;
bNodeSocket *sock;
- for (sock = ntree->inputs.first; sock; sock = sock->next)
- sock->flag |= SOCK_DYNAMIC;
- for (sock = ntree->outputs.first; sock; sock = sock->next)
- sock->flag |= SOCK_DYNAMIC;
+ for (node=ntree->nodes.first; node; node=node->next) {
+ for (sock=node->inputs.first; sock; sock=sock->next)
+ do_versions_socket_default_value_259(sock);
+ for (sock=node->outputs.first; sock; sock=sock->next)
+ do_versions_socket_default_value_259(sock);
+ }
+ for (sock=ntree->inputs.first; sock; sock=sock->next)
+ do_versions_socket_default_value_259(sock);
+ for (sock=ntree->outputs.first; sock; sock=sock->next)
+ do_versions_socket_default_value_259(sock);
}
void blo_do_versions_250(FileData *fd, Library *lib, Main *main)
@@ -2289,16 +2366,79 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *main)
if (main->versionfile < 256 || (main->versionfile == 256 && main->subversionfile < 2)) {
bNodeTree *ntree;
-
+ bNode *node;
+ bNodeSocket *sock, *gsock;
+ bNodeLink *link;
+
/* node sockets are not exposed automatically any more,
* this mimics the old behavior by adding all unlinked sockets to groups.
*/
- for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next) {
- /* XXX Only setting a flag here. Actual adding of group sockets
- * is done in lib_verify_nodetree, because at this point the internal
- * nodes may not be up-to-date! (missing lib-link)
+ for (ntree=main->nodetree.first; ntree; ntree=ntree->id.next) {
+ /* this adds copies and links from all unlinked internal sockets to group inputs/outputs. */
+
+ /* first make sure the own_index for new sockets is valid */
+ for (node=ntree->nodes.first; node; node=node->next) {
+ for (sock=node->inputs.first; sock; sock=sock->next)
+ if (sock->own_index >= ntree->cur_index)
+ ntree->cur_index = sock->own_index+1;
+ for (sock=node->outputs.first; sock; sock=sock->next)
+ if (sock->own_index >= ntree->cur_index)
+ ntree->cur_index = sock->own_index+1;
+ }
+
+ /* add ntree->inputs/ntree->outputs sockets for all unlinked sockets in the group tree. */
+ for (node=ntree->nodes.first; node; node=node->next) {
+ for (sock=node->inputs.first; sock; sock=sock->next) {
+ if (!sock->link && !nodeSocketIsHidden(sock)) {
+
+ gsock = do_versions_node_group_add_socket_2_56_2(ntree, sock->name, sock->type, SOCK_IN);
+
+ /* initialize the default socket value */
+ copy_v4_v4(gsock->ns.vec, sock->ns.vec);
+
+ /* XXX nodeAddLink does not work with incomplete (node==NULL) links any longer,
+ * have to create these directly here. These links are updated again in subsequent do_version!
+ */
+ link= MEM_callocN(sizeof(bNodeLink), "link");
+ BLI_addtail(&ntree->links, link);
+ link->fromnode= NULL;
+ link->fromsock= gsock;
+ link->tonode= node;
+ link->tosock= sock;
+ ntree->update |= NTREE_UPDATE_LINKS;
+
+ sock->link = link;
+ }
+ }
+ for (sock=node->outputs.first; sock; sock=sock->next) {
+ if (nodeCountSocketLinks(ntree, sock)==0 && !nodeSocketIsHidden(sock)) {
+ gsock = do_versions_node_group_add_socket_2_56_2(ntree, sock->name, sock->type, SOCK_OUT);
+
+ /* initialize the default socket value */
+ copy_v4_v4(gsock->ns.vec, sock->ns.vec);
+
+ /* XXX nodeAddLink does not work with incomplete (node==NULL) links any longer,
+ * have to create these directly here. These links are updated again in subsequent do_version!
+ */
+ link= MEM_callocN(sizeof(bNodeLink), "link");
+ BLI_addtail(&ntree->links, link);
+ link->fromnode= node;
+ link->fromsock= sock;
+ link->tonode= NULL;
+ link->tosock= gsock;
+ ntree->update |= NTREE_UPDATE_LINKS;
+
+ gsock->link = link;
+ }
+ }
+ }
+
+ /* XXX The external group node sockets needs to adjust their own_index to point at
+ * associated ntree inputs/outputs internal sockets. However, this can only happen
+ * after lib-linking (needs access to internal node group tree)!
+ * Setting a temporary flag here, actual do_versions happens in lib_verify_nodetree.
*/
- ntree->flag |= NTREE_DO_VERSIONS_GROUP_EXPOSE;
+ ntree->flag |= NTREE_DO_VERSIONS_GROUP_EXPOSE_2_56_2;
}
}
@@ -2601,39 +2741,29 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *main)
bNodeTree *ntree;
for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next) {
- blo_do_versions_nodetree_default_value(ntree);
+ do_versions_nodetree_default_value_259(ntree);
ntree->update |= NTREE_UPDATE;
}
for (sce = main->scene.first; sce; sce = sce->id.next)
if (sce->nodetree) {
- blo_do_versions_nodetree_default_value(sce->nodetree);
+ do_versions_nodetree_default_value_259(sce->nodetree);
sce->nodetree->update |= NTREE_UPDATE;
}
for (mat = main->mat.first; mat; mat = mat->id.next)
if (mat->nodetree) {
- blo_do_versions_nodetree_default_value(mat->nodetree);
+ do_versions_nodetree_default_value_259(mat->nodetree);
mat->nodetree->update |= NTREE_UPDATE;
}
for (tex = main->tex.first; tex; tex = tex->id.next)
if (tex->nodetree) {
- blo_do_versions_nodetree_default_value(tex->nodetree);
+ do_versions_nodetree_default_value_259(tex->nodetree);
tex->nodetree->update |= NTREE_UPDATE;
}
}
- /* add SOCK_DYNAMIC flag to existing group sockets */
- {
- bNodeTree *ntree;
- /* only need to do this for trees in main, local trees are not used as groups */
- for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next) {
- do_versions_nodetree_dynamic_sockets(ntree);
- ntree->update |= NTREE_UPDATE;
- }
- }
-
{
/* Initialize group tree nodetypes.
* These are used to distinguish tree types and
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index 4f7ec77a8e6..d78c6687e16 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -74,6 +74,7 @@
#include <math.h>
#include <fcntl.h>
+#include <limits.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
@@ -151,6 +152,7 @@
#include "BKE_curve.h"
#include "BKE_constraint.h"
#include "BKE_global.h" // for G
+#include "BKE_idprop.h"
#include "BKE_library.h" // for set_listbasepointers
#include "BKE_main.h"
#include "BKE_node.h"
@@ -162,6 +164,13 @@
#include "BKE_pointcache.h"
#include "BKE_mesh.h"
+#ifdef USE_NODE_COMPAT_CUSTOMNODES
+#include "NOD_common.h"
+#include "NOD_socket.h" /* for sock->default_value data */
+#endif
+
+#include "RNA_access.h"
+
#include "BLO_writefile.h"
#include "BLO_readfile.h"
#include "BLO_undofile.h"
@@ -670,46 +679,54 @@ static void write_curvemapping(WriteData *wd, CurveMapping *cumap)
write_curvemapping_curves(wd, cumap);
}
-static void write_node_socket(WriteData *wd, bNodeSocket *sock)
+static void write_node_socket(WriteData *wd, bNodeTree *UNUSED(ntree), bNode *node, bNodeSocket *sock)
{
- bNodeSocketType *stype= ntreeGetSocketType(sock->type);
-
+#ifdef USE_NODE_COMPAT_CUSTOMNODES
/* forward compatibility code, so older blenders still open */
sock->stack_type = 1;
- if (sock->default_value) {
- bNodeSocketValueFloat *valfloat;
- bNodeSocketValueVector *valvector;
- bNodeSocketValueRGBA *valrgba;
-
- switch (sock->type) {
- case SOCK_FLOAT:
- valfloat = sock->default_value;
- sock->ns.vec[0] = valfloat->value;
- sock->ns.min = valfloat->min;
- sock->ns.max = valfloat->max;
- break;
- case SOCK_VECTOR:
- valvector = sock->default_value;
- copy_v3_v3(sock->ns.vec, valvector->value);
- sock->ns.min = valvector->min;
- sock->ns.max = valvector->max;
- break;
- case SOCK_RGBA:
- valrgba = sock->default_value;
- copy_v4_v4(sock->ns.vec, valrgba->value);
- sock->ns.min = 0.0f;
- sock->ns.max = 1.0f;
- break;
+ if (node->type == NODE_GROUP) {
+ bNodeTree *ngroup = (bNodeTree *)node->id;
+ if (ngroup) {
+ /* for node groups: look up the deprecated groupsock pointer */
+ sock->groupsock = ntreeFindSocketInterface(ngroup, sock->in_out, sock->identifier);
+ BLI_assert(sock->groupsock != NULL);
+
+ /* node group sockets now use the generic identifier string to verify group nodes,
+ * old blender uses the own_index.
+ */
+ sock->own_index = sock->groupsock->own_index;
}
}
+#endif
/* actual socket writing */
writestruct(wd, DATA, "bNodeSocket", 1, sock);
+
+ if (sock->prop)
+ IDP_WriteProperty(sock->prop, wd);
+
if (sock->default_value)
- writestruct(wd, DATA, stype->value_structname, 1, sock->default_value);
+ writedata(wd, DATA, MEM_allocN_len(sock->default_value), sock->default_value);
}
+static void write_node_socket_interface(WriteData *wd, bNodeTree *UNUSED(ntree), bNodeSocket *sock)
+{
+#ifdef USE_NODE_COMPAT_CUSTOMNODES
+ /* forward compatibility code, so older blenders still open */
+ sock->stack_type = 1;
+
+ /* Reconstruct the deprecated default_value structs in socket interface DNA. */
+ if (sock->default_value == NULL && sock->typeinfo) {
+ node_socket_init_default_value(sock);
+ }
+#endif
+ /* actual socket writing */
+ writestruct(wd, DATA, "bNodeSocket", 1, sock);
+
+ if (sock->prop)
+ IDP_WriteProperty(sock->prop, wd);
+}
/* this is only direct data, tree itself should have been written */
static void write_nodetree(WriteData *wd, bNodeTree *ntree)
{
@@ -721,18 +738,19 @@ static void write_nodetree(WriteData *wd, bNodeTree *ntree)
if (ntree->adt) write_animdata(wd, ntree->adt);
- for (node= ntree->nodes.first; node; node= node->next)
+ for (node= ntree->nodes.first; node; node= node->next) {
writestruct(wd, DATA, "bNode", 1, node);
- for (node= ntree->nodes.first; node; node= node->next) {
+ if (node->prop)
+ IDP_WriteProperty(node->prop, wd);
+
for (sock= node->inputs.first; sock; sock= sock->next)
- write_node_socket(wd, sock);
+ write_node_socket(wd, ntree, node, sock);
for (sock= node->outputs.first; sock; sock= sock->next)
- write_node_socket(wd, sock);
+ write_node_socket(wd, ntree, node, sock);
for (link = node->internal_links.first; link; link = link->next)
writestruct(wd, DATA, "bNodeLink", 1, link);
-
if (node->storage) {
/* could be handlerized at some point, now only 1 exception still */
if (ntree->type==NTREE_SHADER && (node->type==SH_NODE_CURVE_VEC || node->type==SH_NODE_CURVE_RGB))
@@ -741,10 +759,6 @@ static void write_nodetree(WriteData *wd, bNodeTree *ntree)
NodeShaderScript *nss = (NodeShaderScript *)node->storage;
if (nss->bytecode)
writedata(wd, DATA, strlen(nss->bytecode)+1, nss->bytecode);
- /* Write ID Properties -- and copy this comment EXACTLY for easy finding
- * of library blocks that implement this.*/
- if (nss->prop)
- IDP_WriteProperty(nss->prop, wd);
writestruct(wd, DATA, node->typeinfo->storagename, 1, node->storage);
}
else if (ntree->type==NTREE_COMPOSIT && ELEM4(node->type, CMP_NODE_TIME, CMP_NODE_CURVE_VEC, CMP_NODE_CURVE_RGB, CMP_NODE_HUECORRECT))
@@ -773,11 +787,10 @@ static void write_nodetree(WriteData *wd, bNodeTree *ntree)
for (link= ntree->links.first; link; link= link->next)
writestruct(wd, DATA, "bNodeLink", 1, link);
- /* external sockets */
- for (sock= ntree->inputs.first; sock; sock= sock->next)
- write_node_socket(wd, sock);
- for (sock= ntree->outputs.first; sock; sock= sock->next)
- write_node_socket(wd, sock);
+ for (sock = ntree->inputs.first; sock; sock = sock->next)
+ write_node_socket_interface(wd, ntree, sock);
+ for (sock = ntree->outputs.first; sock; sock = sock->next)
+ write_node_socket_interface(wd, ntree, sock);
}
static void current_screen_compat(Main *mainvar, bScreen **screen)
@@ -2518,7 +2531,12 @@ static void write_screens(WriteData *wd, ListBase *scrbase)
writestruct(wd, DATA, "SpaceTime", 1, sl);
}
else if (sl->spacetype==SPACE_NODE) {
- writestruct(wd, DATA, "SpaceNode", 1, sl);
+ SpaceNode *snode = (SpaceNode *)sl;
+ bNodeTreePath *path;
+ writestruct(wd, DATA, "SpaceNode", 1, snode);
+
+ for (path=snode->treepath.first; path; path=path->next)
+ writestruct(wd, DATA, "bNodeTreePath", 1, path);
}
else if (sl->spacetype==SPACE_LOGIC) {
writestruct(wd, DATA, "SpaceLogic", 1, sl);
@@ -2770,6 +2788,118 @@ static void write_nodetrees(WriteData *wd, ListBase *idbase)
}
}
+#ifdef USE_NODE_COMPAT_CUSTOMNODES
+static void customnodes_add_deprecated_nodetree_data(bNodeTree *ntree)
+{
+ bNodeLink *link, *last_link = ntree->links.last;
+ /* Forward compatibility for group nodes: add links to node tree interface sockets.
+ * These links are invalid by new rules (missing node pointer)!
+ * They will be removed again in customnodes_free_deprecated_data,
+ * cannot do this directly lest bNodeLink pointer mapping becomes ambiguous.
+ * When loading files with such links in a new Blender version
+ * they will be removed as well.
+ */
+ for (link = ntree->links.first; link; link = link->next) {
+ bNode *fromnode = link->fromnode, *tonode = link->tonode;
+ bNodeSocket *fromsock = link->fromsock, *tosock = link->tosock;
+
+ /* check both sides of the link, to handle direct input-to-output links */
+ if (fromnode->type == NODE_GROUP_INPUT) {
+ fromnode = NULL;
+ fromsock = ntreeFindSocketInterface(ntree, SOCK_IN, fromsock->identifier);
+ }
+ /* only the active output node defines links */
+ if (tonode->type == NODE_GROUP_OUTPUT && (tonode->flag & NODE_DO_OUTPUT)) {
+ tonode = NULL;
+ tosock = ntreeFindSocketInterface(ntree, SOCK_OUT, tosock->identifier);
+ }
+
+ if (!fromnode || !tonode) {
+ /* Note: not using nodeAddLink here, it asserts existing node pointers */
+ bNodeLink *tlink = MEM_callocN(sizeof(bNodeLink), "group node link");
+ tlink->fromnode = fromnode;
+ tlink->fromsock = fromsock;
+ tlink->tonode = tonode;
+ tlink->tosock= tosock;
+ tosock->link = tlink;
+ tlink->flag |= NODE_LINK_VALID;
+ BLI_addtail(&ntree->links, tlink);
+ }
+
+ /* don't check newly created compatibility links */
+ if (link == last_link)
+ break;
+ }
+}
+
+static void customnodes_add_deprecated_data(Main *mainvar)
+{
+ bNodeTree *ntree;
+ Scene *scene;
+ Material *mat;
+ World *world;
+ Lamp *lamp;
+ Tex *tex;
+
+ for (ntree = mainvar->nodetree.first; ntree; ntree = ntree->id.next)
+ customnodes_add_deprecated_nodetree_data(ntree);
+ for (scene = mainvar->scene.first; scene; scene = scene->id.next)
+ if (scene->nodetree)
+ customnodes_add_deprecated_nodetree_data(scene->nodetree);
+ for (mat = mainvar->mat.first; mat; mat = mat->id.next)
+ if (mat->nodetree)
+ customnodes_add_deprecated_nodetree_data(mat->nodetree);
+ for (world = mainvar->world.first; world; world = world->id.next)
+ if (world->nodetree)
+ customnodes_add_deprecated_nodetree_data(world->nodetree);
+ for (lamp = mainvar->lamp.first; lamp; lamp = lamp->id.next)
+ if (lamp->nodetree)
+ customnodes_add_deprecated_nodetree_data(lamp->nodetree);
+ for (tex = mainvar->tex.first; tex; tex = tex->id.next)
+ if (tex->nodetree)
+ customnodes_add_deprecated_nodetree_data(tex->nodetree);
+}
+
+static void customnodes_free_deprecated_nodetree_data(bNodeTree *ntree)
+{
+ bNodeLink *link, *next_link;
+
+ for (link = ntree->links.first; link; link = next_link) {
+ next_link = link->next;
+ if (link->fromnode == NULL || link->tonode == NULL)
+ nodeRemLink(ntree, link);
+ }
+}
+
+static void customnodes_free_deprecated_data(Main *mainvar)
+{
+ bNodeTree *ntree;
+ Scene *scene;
+ Material *mat;
+ World *world;
+ Lamp *lamp;
+ Tex *tex;
+
+ for (ntree = mainvar->nodetree.first; ntree; ntree = ntree->id.next)
+ customnodes_free_deprecated_nodetree_data(ntree);
+ for (scene = mainvar->scene.first; scene; scene = scene->id.next)
+ if (scene->nodetree)
+ customnodes_free_deprecated_nodetree_data(scene->nodetree);
+ for (mat = mainvar->mat.first; mat; mat = mat->id.next)
+ if (mat->nodetree)
+ customnodes_free_deprecated_nodetree_data(mat->nodetree);
+ for (world = mainvar->world.first; world; world = world->id.next)
+ if (world->nodetree)
+ customnodes_free_deprecated_nodetree_data(world->nodetree);
+ for (lamp = mainvar->lamp.first; lamp; lamp = lamp->id.next)
+ if (lamp->nodetree)
+ customnodes_free_deprecated_nodetree_data(lamp->nodetree);
+ for (tex = mainvar->tex.first; tex; tex = tex->id.next)
+ if (tex->nodetree)
+ customnodes_free_deprecated_nodetree_data(tex->nodetree);
+}
+#endif
+
static void write_brushes(WriteData *wd, ListBase *idbase)
{
Brush *brush;
@@ -2981,6 +3111,11 @@ static int write_file_handle(Main *mainvar, int handle, MemFile *compare, MemFil
wd->use_mesh_compat = (write_flags & G_FILE_MESH_COMPAT) != 0;
#endif
+#ifdef USE_NODE_COMPAT_CUSTOMNODES
+ /* deprecated forward compat data is freed again below */
+ customnodes_add_deprecated_data(mainvar);
+#endif
+
sprintf(buf, "BLENDER%c%c%.3d", (sizeof(void*)==8)?'-':'_', (ENDIAN_ORDER==B_ENDIAN)?'V':'v', BLENDER_VERSION);
mywrite(wd, buf, 12);
@@ -3026,6 +3161,14 @@ static int write_file_handle(Main *mainvar, int handle, MemFile *compare, MemFil
/* dna as last, because (to be implemented) test for which structs are written */
writedata(wd, DNA1, wd->sdna->datalen, wd->sdna->data);
+#ifdef USE_NODE_COMPAT_CUSTOMNODES
+ /* Ugly, forward compatibility code generates deprecated data during writing,
+ * this has to be freed again. Can not be done directly after writing, otherwise
+ * the data pointers could be reused and not be mapped correctly.
+ */
+ customnodes_free_deprecated_data(mainvar);
+#endif
+
/* end of file */
memset(&bhead, 0, sizeof(BHead));
bhead.code= ENDB;
diff --git a/source/blender/compositor/intern/COM_CompositorContext.cpp b/source/blender/compositor/intern/COM_CompositorContext.cpp
index e1cc25d028a..6008a889205 100644
--- a/source/blender/compositor/intern/COM_CompositorContext.cpp
+++ b/source/blender/compositor/intern/COM_CompositorContext.cpp
@@ -29,7 +29,6 @@ CompositorContext::CompositorContext()
this->m_rd = NULL;
this->m_quality = COM_QUALITY_HIGH;
this->m_hasActiveOpenCLDevices = false;
- this->m_activegNode = NULL;
this->m_fastCalculation = false;
this->m_viewSettings = NULL;
this->m_displaySettings = NULL;
diff --git a/source/blender/compositor/intern/COM_CompositorContext.h b/source/blender/compositor/intern/COM_CompositorContext.h
index 840a9e59584..3c7db703bf9 100644
--- a/source/blender/compositor/intern/COM_CompositorContext.h
+++ b/source/blender/compositor/intern/COM_CompositorContext.h
@@ -64,11 +64,12 @@ private:
* @see ExecutionSystem
*/
bNodeTree *m_bnodetree;
-
+
/**
- * @brief activegNode the group node that is currently being edited.
+ * @brief Preview image hash table
+ * This field is initialized in ExecutionSystem and must only be read from that point on.
*/
- bNode *m_activegNode;
+ bNodeInstanceHash *m_previews;
/**
* @brief does this system have active opencl devices?
@@ -115,19 +116,19 @@ public:
const bNodeTree *getbNodeTree() const { return this->m_bnodetree; }
/**
- * @brief set the active groupnode of the context
+ * @brief get the scene of the context
*/
- void setActivegNode(bNode *gnode) { this->m_activegNode = gnode; }
+ const RenderData *getRenderData() const { return this->m_rd; }
/**
- * @brief get the active groupnode of the context
+ * @brief set the preview image hash table
*/
- const bNode *getActivegNode() const { return this->m_activegNode; }
+ void setPreviewHash(bNodeInstanceHash *previews) { this->m_previews = previews; }
/**
- * @brief get the scene of the context
+ * @brief get the preview image hash table
*/
- const RenderData *getRenderData() const { return this->m_rd; }
+ bNodeInstanceHash *getPreviewHash() const { return this->m_previews; }
/**
* @brief set view settings of color color management
diff --git a/source/blender/compositor/intern/COM_Converter.cpp b/source/blender/compositor/intern/COM_Converter.cpp
index 9c4a32f20c9..80f5b4fc149 100644
--- a/source/blender/compositor/intern/COM_Converter.cpp
+++ b/source/blender/compositor/intern/COM_Converter.cpp
@@ -124,7 +124,7 @@
Node *Converter::convert(bNode *b_node, bool fast)
{
- Node *node;
+ Node *node = NULL;
if (b_node->flag & NODE_MUTED) {
node = new MuteNode(b_node);
@@ -226,6 +226,10 @@ Node *Converter::convert(bNode *b_node, bool fast)
case NODE_GROUP:
node = new GroupNode(b_node);
break;
+ case NODE_GROUP_INPUT:
+ case NODE_GROUP_OUTPUT:
+ /* handled in GroupNode::ungroup */
+ break;
case CMP_NODE_NORMAL:
node = new NormalNode(b_node);
break;
@@ -399,7 +403,6 @@ Node *Converter::convert(bNode *b_node, bool fast)
node = new PixelateNode(b_node);
break;
default:
- node = new MuteNode(b_node);
break;
}
return node;
diff --git a/source/blender/compositor/intern/COM_ExecutionSystem.cpp b/source/blender/compositor/intern/COM_ExecutionSystem.cpp
index 2b2af73d0c8..2da1c34ab44 100644
--- a/source/blender/compositor/intern/COM_ExecutionSystem.cpp
+++ b/source/blender/compositor/intern/COM_ExecutionSystem.cpp
@@ -49,7 +49,9 @@ ExecutionSystem::ExecutionSystem(RenderData *rd, bNodeTree *editingtree, bool re
const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings)
{
this->m_context.setbNodeTree(editingtree);
+ this->m_context.setPreviewHash(editingtree->previews);
this->m_context.setFastCalculation(fastcalculation);
+#if 0 /* XXX TODO find a better way to define visible output nodes from all editors */
bNode *gnode;
for (gnode = (bNode *)editingtree->nodes.first; gnode; gnode = gnode->next) {
if (gnode->type == NODE_GROUP && gnode->typeinfo->group_edit_get(gnode)) {
@@ -57,6 +59,7 @@ ExecutionSystem::ExecutionSystem(RenderData *rd, bNodeTree *editingtree, bool re
break;
}
}
+#endif
/* initialize the CompositorContext */
if (rendering) {
@@ -68,7 +71,7 @@ ExecutionSystem::ExecutionSystem(RenderData *rd, bNodeTree *editingtree, bool re
this->m_context.setRendering(rendering);
this->m_context.setHasActiveOpenCLDevices(WorkScheduler::hasGPUDevices() && (editingtree->flag & NTREE_COM_OPENCL));
- ExecutionSystemHelper::addbNodeTree(*this, 0, editingtree, NULL);
+ ExecutionSystemHelper::addbNodeTree(*this, 0, editingtree, NODE_INSTANCE_KEY_BASE);
this->m_context.setRenderData(rd);
this->m_context.setViewSettings(viewSettings);
diff --git a/source/blender/compositor/intern/COM_ExecutionSystemHelper.cpp b/source/blender/compositor/intern/COM_ExecutionSystemHelper.cpp
index 506bd42ace3..ad396e053f2 100644
--- a/source/blender/compositor/intern/COM_ExecutionSystemHelper.cpp
+++ b/source/blender/compositor/intern/COM_ExecutionSystemHelper.cpp
@@ -26,7 +26,6 @@
#include <stdio.h>
#include "PIL_time.h"
-#include "BKE_node.h"
#include "COM_Converter.h"
#include "COM_NodeOperation.h"
@@ -39,18 +38,25 @@
#include "COM_ReadBufferOperation.h"
#include "COM_ViewerBaseOperation.h"
-void ExecutionSystemHelper::addbNodeTree(ExecutionSystem &system, int nodes_start, bNodeTree *tree, bNode *groupnode)
+extern "C" {
+#include "BKE_node.h"
+}
+
+void ExecutionSystemHelper::addbNodeTree(ExecutionSystem &system, int nodes_start, bNodeTree *tree, bNodeInstanceKey parent_key)
{
vector<Node *>& nodes = system.getNodes();
vector<SocketConnection *>& links = system.getConnections();
- const bNode *activeGroupNode = system.getContext().getActivegNode();
- bool isActiveGroup = activeGroupNode == groupnode;
/* add all nodes of the tree to the node list */
bNode *node = (bNode *)tree->nodes.first;
while (node != NULL) {
+ /* XXX TODO replace isActiveGroup by a more accurate check, all visible editors should do this! */
+ bool isActiveGroup = true;
Node *nnode = addNode(nodes, node, isActiveGroup, system.getContext().isFastCalculation());
- nnode->setbNodeGroup(groupnode);
+ if (nnode) {
+ nnode->setbNodeTree(tree);
+ nnode->setInstanceKey(BKE_node_instance_key(parent_key, tree, node));
+ }
node = node->next;
}
@@ -81,8 +87,10 @@ void ExecutionSystemHelper::addNode(vector<Node *>& nodes, Node *node)
Node *ExecutionSystemHelper::addNode(vector<Node *>& nodes, bNode *b_node, bool inActiveGroup, bool fast)
{
Node *node = Converter::convert(b_node, fast);
- node->setIsInActiveGroup(inActiveGroup);
- addNode(nodes, node);
+ if (node) {
+ node->setIsInActiveGroup(inActiveGroup);
+ addNode(nodes, node);
+ }
return node;
}
void ExecutionSystemHelper::addOperation(vector<NodeOperation *>& operations, NodeOperation *operation)
@@ -109,43 +117,21 @@ void ExecutionSystemHelper::findOutputNodeOperations(vector<NodeOperation *> *re
static InputSocket *find_input(NodeRange &node_range, bNode *bnode, bNodeSocket *bsocket)
{
- if (bnode != NULL) {
- for (NodeIterator it = node_range.first; it != node_range.second; ++it) {
- Node *node = *it;
- if (node->getbNode() == bnode)
- return node->findInputSocketBybNodeSocket(bsocket);
- }
- }
- else {
- for (NodeIterator it = node_range.first; it != node_range.second; ++it) {
- Node *node = *it;
- if (node->isProxyNode()) {
- InputSocket *proxySocket = node->getInputSocket(0);
- if (proxySocket->getbNodeSocket() == bsocket)
- return proxySocket;
- }
- }
+ for (NodeIterator it = node_range.first; it != node_range.second; ++it) {
+ Node *node = *it;
+ InputSocket *input = node->findInputSocketBybNodeSocket(bsocket);
+ if (input)
+ return input;
}
return NULL;
}
static OutputSocket *find_output(NodeRange &node_range, bNode *bnode, bNodeSocket *bsocket)
{
- if (bnode != NULL) {
- for (NodeIterator it = node_range.first; it != node_range.second; ++it) {
- Node *node = *it;
- if (node->getbNode() == bnode)
- return node->findOutputSocketBybNodeSocket(bsocket);
- }
- }
- else {
- for (NodeIterator it = node_range.first; it != node_range.second; ++it) {
- Node *node = *it;
- if (node->isProxyNode()) {
- OutputSocket *proxySocket = node->getOutputSocket(0);
- if (proxySocket->getbNodeSocket() == bsocket)
- return proxySocket;
- }
- }
+ for (NodeIterator it = node_range.first; it != node_range.second; ++it) {
+ Node *node = *it;
+ OutputSocket *output = node->findOutputSocketBybNodeSocket(bsocket);
+ if (output)
+ return output;
}
return NULL;
}
@@ -190,7 +176,7 @@ void ExecutionSystemHelper::debugDump(ExecutionSystem *system)
tot = system->getNodes().size();
for (int i = 0; i < tot; i++) {
node = system->getNodes()[i];
- printf("// NODE: %s\r\n", node->getbNode()->typeinfo->name);
+ printf("// NODE: %s\r\n", node->getbNode()->typeinfo->ui_name);
}
tot = system->getOperations().size();
for (int i = 0; i < tot; i++) {
diff --git a/source/blender/compositor/intern/COM_ExecutionSystemHelper.h b/source/blender/compositor/intern/COM_ExecutionSystemHelper.h
index 307e082ea80..e05796b9127 100644
--- a/source/blender/compositor/intern/COM_ExecutionSystemHelper.h
+++ b/source/blender/compositor/intern/COM_ExecutionSystemHelper.h
@@ -48,7 +48,7 @@ public:
* @param tree bNodeTree to add
* @return Node representing the "Compositor node" of the maintree. or NULL when a subtree is added
*/
- static void addbNodeTree(ExecutionSystem &system, int nodes_start, bNodeTree *tree, bNode *groupnode);
+ static void addbNodeTree(ExecutionSystem &system, int nodes_start, bNodeTree *tree, bNodeInstanceKey parent_key);
/**
* @brief add an editor node to the system.
diff --git a/source/blender/compositor/intern/COM_InputSocket.cpp b/source/blender/compositor/intern/COM_InputSocket.cpp
index 2493d4e5a27..6868745d631 100644
--- a/source/blender/compositor/intern/COM_InputSocket.cpp
+++ b/source/blender/compositor/intern/COM_InputSocket.cpp
@@ -157,24 +157,3 @@ NodeOperation *InputSocket::getOperation() const
return NULL;
}
}
-
-float *InputSocket::getStaticValues()
-{
- /* XXX only works for socket types with actual float input values.
- * currently all compositor socket types (value, rgba, vector) support this.
- */
- bNodeSocket *b_socket = this->getbNodeSocket();
- static float default_null = 0.0f;
-
- switch (this->getDataType()) {
- case COM_DT_VALUE:
- return &((bNodeSocketValueFloat *)b_socket->default_value)->value;
- case COM_DT_COLOR:
- return ((bNodeSocketValueRGBA *)b_socket->default_value)->value;
- case COM_DT_VECTOR:
- return ((bNodeSocketValueVector *)b_socket->default_value)->value;
- default:
- /* XXX this should never happen, just added to please the compiler */
- return &default_null;
- }
-}
diff --git a/source/blender/compositor/intern/COM_InputSocket.h b/source/blender/compositor/intern/COM_InputSocket.h
index 5cd4cf3beb7..5a36fe3f33b 100644
--- a/source/blender/compositor/intern/COM_InputSocket.h
+++ b/source/blender/compositor/intern/COM_InputSocket.h
@@ -143,7 +143,6 @@ public:
bool isStatic();
- float *getStaticValues();
SocketReader *getReader();
NodeOperation *getOperation() const;
};
diff --git a/source/blender/compositor/intern/COM_Node.cpp b/source/blender/compositor/intern/COM_Node.cpp
index d49bb5f96fb..f59580acb50 100644
--- a/source/blender/compositor/intern/COM_Node.cpp
+++ b/source/blender/compositor/intern/COM_Node.cpp
@@ -67,10 +67,9 @@ Node::Node(bNode *editorNode, bool create_sockets): NodeBase()
void Node::addSetValueOperation(ExecutionSystem *graph, InputSocket *inputsocket, int editorNodeInputSocketIndex)
{
- bNodeSocket *bSock = this->getEditorInputSocket(editorNodeInputSocketIndex);
+ InputSocket *input = getInputSocket(editorNodeInputSocketIndex);
SetValueOperation *operation = new SetValueOperation();
- bNodeSocketValueFloat *val = (bNodeSocketValueFloat *)bSock->default_value;
- operation->setValue(val->value);
+ operation->setValue(input->getEditorValueFloat());
this->addLink(graph, operation->getOutputSocket(), inputsocket);
graph->addOperation(operation);
}
@@ -79,11 +78,13 @@ void Node::addPreviewOperation(ExecutionSystem *system, CompositorContext *conte
{
if (this->isInActiveGroup()) {
if (!(this->getbNode()->flag & NODE_HIDDEN)) { // do not calculate previews of hidden nodes.
- if (this->getbNode()->flag & NODE_PREVIEW) {
+ bNodeInstanceHash *previews = context->getPreviewHash();
+ if (previews && (this->getbNode()->flag & NODE_PREVIEW)) {
PreviewOperation *operation = new PreviewOperation(context->getViewSettings(), context->getDisplaySettings());
system->addOperation(operation);
operation->setbNode(this->getbNode());
operation->setbNodeTree(system->getContext().getbNodeTree());
+ operation->verifyPreview(previews, this->getInstanceKey());
this->addLink(system, outputSocket, operation->getInputSocket(0));
}
}
@@ -114,25 +115,27 @@ SocketConnection *Node::addLink(ExecutionSystem *graph, OutputSocket *outputSock
void Node::addSetColorOperation(ExecutionSystem *graph, InputSocket *inputsocket, int editorNodeInputSocketIndex)
{
- bNodeSocket *bSock = this->getEditorInputSocket(editorNodeInputSocketIndex);
+ InputSocket *input = getInputSocket(editorNodeInputSocketIndex);
SetColorOperation *operation = new SetColorOperation();
- bNodeSocketValueRGBA *val = (bNodeSocketValueRGBA *)bSock->default_value;
- operation->setChannel1(val->value[0]);
- operation->setChannel2(val->value[1]);
- operation->setChannel3(val->value[2]);
- operation->setChannel4(val->value[3]);
+ float col[4];
+ input->getEditorValueColor(col);
+ operation->setChannel1(col[0]);
+ operation->setChannel2(col[1]);
+ operation->setChannel3(col[2]);
+ operation->setChannel4(col[3]);
this->addLink(graph, operation->getOutputSocket(), inputsocket);
graph->addOperation(operation);
}
void Node::addSetVectorOperation(ExecutionSystem *graph, InputSocket *inputsocket, int editorNodeInputSocketIndex)
{
- bNodeSocket *bSock = this->getEditorInputSocket(editorNodeInputSocketIndex);
- bNodeSocketValueVector *val = (bNodeSocketValueVector *)bSock->default_value;
+ InputSocket *input = getInputSocket(editorNodeInputSocketIndex);
SetVectorOperation *operation = new SetVectorOperation();
- operation->setX(val->value[0]);
- operation->setY(val->value[1]);
- operation->setZ(val->value[2]);
+ float vec[3];
+ input->getEditorValueVector(vec);
+ operation->setX(vec[0]);
+ operation->setY(vec[1]);
+ operation->setZ(vec[2]);
this->addLink(graph, operation->getOutputSocket(), inputsocket);
graph->addOperation(operation);
}
diff --git a/source/blender/compositor/intern/COM_Node.h b/source/blender/compositor/intern/COM_Node.h
index 5b0381f6443..fb5dfe2e9b7 100644
--- a/source/blender/compositor/intern/COM_Node.h
+++ b/source/blender/compositor/intern/COM_Node.h
@@ -53,12 +53,11 @@ private:
* @brief Is this node part of the active group
*/
bool m_inActiveGroup;
-
+
/**
- * @brief The group node this node belongs to.
- * @note: used to find the links in the current subtree for muting nodes
+ * @brief Instance key to identify the node in an instance hash table
*/
- bNode *m_bNodeGroup;
+ bNodeInstanceKey m_instanceKey;
public:
Node(bNode *editorNode, bool create_sockets = true);
@@ -145,8 +144,9 @@ public:
*/
OutputSocket *findOutputSocketBybNodeSocket(bNodeSocket *socket);
- inline void setbNodeGroup(bNode *group) {this->m_bNodeGroup = group;}
- inline bNode *getbNodeGroup() {return this->m_bNodeGroup;}
+ void setInstanceKey(bNodeInstanceKey instance_key) { m_instanceKey = instance_key; }
+ bNodeInstanceKey getInstanceKey() const { return m_instanceKey; }
+
protected:
void addPreviewOperation(ExecutionSystem *system, CompositorContext *context, InputSocket *inputSocket);
void addPreviewOperation(ExecutionSystem *system, CompositorContext *context, OutputSocket *outputSocket);
diff --git a/source/blender/compositor/intern/COM_NodeBase.h b/source/blender/compositor/intern/COM_NodeBase.h
index e386b5e08a0..41b6ab70bf9 100644
--- a/source/blender/compositor/intern/COM_NodeBase.h
+++ b/source/blender/compositor/intern/COM_NodeBase.h
@@ -59,6 +59,11 @@ private:
*/
bNode *m_editorNode;
+ /**
+ * @brief stores the reference to the SDNA bNode struct
+ */
+ bNodeTree *m_editorNodeTree;
+
protected:
/**
* @brief get access to the vector of input sockets
@@ -82,14 +87,25 @@ public:
/**
* @brief get the reference to the SDNA bNode struct
*/
- bNode *getbNode() {return m_editorNode;}
+ bNode *getbNode() const {return m_editorNode;}
+
+ /**
+ * @brief get the reference to the SDNA bNodeTree struct
+ */
+ bNodeTree *getbNodeTree() const {return m_editorNodeTree;}
/**
* @brief set the reference to the bNode
* @note used in Node instances to receive the storage/settings and complex node for highlight during execution
* @param bNode
*/
- void setbNode(bNode *bNode) {this->m_editorNode = bNode;}
+ void setbNode(bNode *node) {this->m_editorNode = node;}
+
+ /**
+ * @brief set the reference to the bNodeTree
+ * @param bNodeTree
+ */
+ void setbNodeTree(bNodeTree *nodetree) {this->m_editorNodeTree = nodetree;}
/**
* @brief is this node an operation?
diff --git a/source/blender/compositor/intern/COM_Socket.cpp b/source/blender/compositor/intern/COM_Socket.cpp
index 30f28f9dddb..3465fa6f56d 100644
--- a/source/blender/compositor/intern/COM_Socket.cpp
+++ b/source/blender/compositor/intern/COM_Socket.cpp
@@ -24,6 +24,10 @@
#include "COM_Node.h"
#include "COM_SocketConnection.h"
+extern "C" {
+#include "RNA_access.h"
+}
+
Socket::Socket(DataType datatype)
{
this->m_datatype = datatype;
@@ -41,3 +45,24 @@ int Socket::isOutputSocket() const { return false; }
const int Socket::isConnected() const { return false; }
void Socket::setNode(NodeBase *node) { this->m_node = node; }
NodeBase *Socket::getNode() const { return this->m_node; }
+
+float Socket::getEditorValueFloat()
+{
+ PointerRNA ptr;
+ RNA_pointer_create((ID *)getNode()->getbNodeTree(), &RNA_NodeSocket, getbNodeSocket(), &ptr);
+ return RNA_float_get(&ptr, "default_value");
+}
+
+void Socket::getEditorValueColor(float *value)
+{
+ PointerRNA ptr;
+ RNA_pointer_create((ID *)getNode()->getbNodeTree(), &RNA_NodeSocket, getbNodeSocket(), &ptr);
+ return RNA_float_get_array(&ptr, "default_value", value);
+}
+
+void Socket::getEditorValueVector(float *value)
+{
+ PointerRNA ptr;
+ RNA_pointer_create((ID *)getNode()->getbNodeTree(), &RNA_NodeSocket, getbNodeSocket(), &ptr);
+ return RNA_float_get_array(&ptr, "default_value", value);
+}
diff --git a/source/blender/compositor/intern/COM_Socket.h b/source/blender/compositor/intern/COM_Socket.h
index bad112d20c7..6532864a4d9 100644
--- a/source/blender/compositor/intern/COM_Socket.h
+++ b/source/blender/compositor/intern/COM_Socket.h
@@ -36,6 +36,7 @@
using namespace std;
class SocketConnection;
class NodeBase;
+struct PointerRNA;
/**
* @brief Base class for InputSocket and OutputSocket.
@@ -86,6 +87,10 @@ public:
void setEditorSocket(bNodeSocket *editorSocket) { this->m_editorSocket = editorSocket; }
bNodeSocket *getbNodeSocket() const { return this->m_editorSocket; }
+ float getEditorValueFloat();
+ void getEditorValueColor(float *value);
+ void getEditorValueVector(float *value);
+
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("COM:Socket")
#endif
diff --git a/source/blender/compositor/intern/COM_compositor.cpp b/source/blender/compositor/intern/COM_compositor.cpp
index 49ab9db5dd8..94a27e17b68 100644
--- a/source/blender/compositor/intern/COM_compositor.cpp
+++ b/source/blender/compositor/intern/COM_compositor.cpp
@@ -21,9 +21,9 @@
*/
-#include "BKE_node.h"
extern "C" {
- #include "BLI_threads.h"
+#include "BKE_node.h"
+#include "BLI_threads.h"
}
#include "BKE_main.h"
#include "BKE_global.h"
@@ -63,6 +63,11 @@ void COM_execute(RenderData *rd, bNodeTree *editingtree, int rendering,
return;
}
+ /* Make sure node tree has previews.
+ * Don't create previews in advance, this is done when adding preview operations.
+ */
+ BKE_node_preview_init_tree(editingtree, COM_PREVIEW_SIZE, COM_PREVIEW_SIZE, FALSE);
+
/* initialize workscheduler, will check if already done. TODO deinitialize somewhere */
bool use_opencl = (editingtree->flag & NTREE_COM_OPENCL);
WorkScheduler::initialize(use_opencl);
@@ -85,7 +90,6 @@ void COM_execute(RenderData *rd, bNodeTree *editingtree, int rendering,
}
}
-
ExecutionSystem *system = new ExecutionSystem(rd, editingtree, rendering, false, viewSettings, displaySettings);
system->execute();
delete system;
diff --git a/source/blender/compositor/nodes/COM_BlurNode.cpp b/source/blender/compositor/nodes/COM_BlurNode.cpp
index 6a4987c2075..b59a92710bc 100644
--- a/source/blender/compositor/nodes/COM_BlurNode.cpp
+++ b/source/blender/compositor/nodes/COM_BlurNode.cpp
@@ -45,8 +45,7 @@ void BlurNode::convertToOperations(ExecutionSystem *graph, CompositorContext *co
InputSocket *inputSizeSocket = this->getInputSocket(1);
bool connectedSizeSocket = inputSizeSocket->isConnected();
- const bNodeSocket *sock = this->getInputSocket(1)->getbNodeSocket();
- const float size = ((const bNodeSocketValueFloat *)sock->default_value)->value;
+ const float size = this->getInputSocket(1)->getEditorValueFloat();
CompositorQuality quality = context->getQuality();
NodeOperation *input_operation = NULL, *output_operation = NULL;
diff --git a/source/blender/compositor/nodes/COM_BokehBlurNode.cpp b/source/blender/compositor/nodes/COM_BokehBlurNode.cpp
index 70f20e3235b..5725bc6cb32 100644
--- a/source/blender/compositor/nodes/COM_BokehBlurNode.cpp
+++ b/source/blender/compositor/nodes/COM_BokehBlurNode.cpp
@@ -60,21 +60,17 @@ void BokehBlurNode::convertToOperations(ExecutionSystem *graph, CompositorContex
else {
BokehBlurOperation *operation = new BokehBlurOperation();
- const bNodeSocket *sock = this->getInputSocket(2)->getbNodeSocket();
- const float size = ((const bNodeSocketValueFloat *)sock->default_value)->value;
-
this->getInputSocket(0)->relinkConnections(operation->getInputSocket(0), 0, graph);
this->getInputSocket(1)->relinkConnections(operation->getInputSocket(1), 1, graph);
this->getInputSocket(2)->relinkConnections(operation->getInputSocket(3), 2, graph);
this->getInputSocket(3)->relinkConnections(operation->getInputSocket(2), 3, graph);
- //operation->setSize(((bNodeSocketValueFloat *)this->getInputSocket(2)->getbNodeSocket()->default_value)->value);
operation->setQuality(context->getQuality());
operation->setbNode(this->getbNode());
graph->addOperation(operation);
this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket());
if (!connectedSizeSocket) {
- operation->setSize(size);
+ operation->setSize(this->getInputSocket(2)->getEditorValueFloat());
}
}
}
diff --git a/source/blender/compositor/nodes/COM_ColorCurveNode.cpp b/source/blender/compositor/nodes/COM_ColorCurveNode.cpp
index 93ff304afd8..103fbf26c7d 100644
--- a/source/blender/compositor/nodes/COM_ColorCurveNode.cpp
+++ b/source/blender/compositor/nodes/COM_ColorCurveNode.cpp
@@ -50,10 +50,11 @@ void ColorCurveNode::convertToOperations(ExecutionSystem *graph, CompositorConte
this->getInputSocket(0)->relinkConnections(operation->getInputSocket(0), 0, graph);
this->getInputSocket(1)->relinkConnections(operation->getInputSocket(1), 1, graph);
- bNodeSocketValueRGBA *val = (bNodeSocketValueRGBA *)this->getInputSocket(2)->getbNodeSocket()->default_value;
- operation->setBlackLevel(val->value);
- val = (bNodeSocketValueRGBA *)this->getInputSocket(3)->getbNodeSocket()->default_value;
- operation->setWhiteLevel(val->value);
+ float col[4];
+ this->getInputSocket(2)->getEditorValueColor(col);
+ operation->setBlackLevel(col);
+ this->getInputSocket(3)->getEditorValueColor(col);
+ operation->setWhiteLevel(col);
this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket());
operation->setCurveMapping((CurveMapping *)this->getbNode()->storage);
diff --git a/source/blender/compositor/nodes/COM_ColorNode.cpp b/source/blender/compositor/nodes/COM_ColorNode.cpp
index 088f8bbb19d..fc2566e5a47 100644
--- a/source/blender/compositor/nodes/COM_ColorNode.cpp
+++ b/source/blender/compositor/nodes/COM_ColorNode.cpp
@@ -32,9 +32,10 @@ ColorNode::ColorNode(bNode *editorNode) : Node(editorNode)
void ColorNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context)
{
SetColorOperation *operation = new SetColorOperation();
- bNodeSocket *socket = this->getEditorOutputSocket(0);
- bNodeSocketValueRGBA *dval = (bNodeSocketValueRGBA *)socket->default_value;
- this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket());
- operation->setChannels(dval->value);
+ OutputSocket *output = this->getOutputSocket(0);
+ output->relinkConnections(operation->getOutputSocket());
+ float col[4];
+ output->getEditorValueColor(col);
+ operation->setChannels(col);
graph->addOperation(operation);
}
diff --git a/source/blender/compositor/nodes/COM_GroupNode.cpp b/source/blender/compositor/nodes/COM_GroupNode.cpp
index 05c749345d5..3b67d0912d4 100644
--- a/source/blender/compositor/nodes/COM_GroupNode.cpp
+++ b/source/blender/compositor/nodes/COM_GroupNode.cpp
@@ -20,6 +20,8 @@
* Monique Dewanchand
*/
+#include "BKE_node.h"
+
#include "COM_GroupNode.h"
#include "COM_SocketProxyNode.h"
#include "COM_SetColorOperation.h"
@@ -37,13 +39,38 @@ void GroupNode::convertToOperations(ExecutionSystem *graph, CompositorContext *c
}
}
+static int find_group_input(GroupNode *gnode, const char *identifier, InputSocket **r_sock)
+{
+ int index;
+ for (index = 0; index < gnode->getNumberOfInputSockets(); ++index) {
+ InputSocket *sock = gnode->getInputSocket(index);
+ if (strcmp(sock->getbNodeSocket()->identifier, identifier)==0) {
+ *r_sock = sock;
+ return index;
+ }
+ }
+ *r_sock = NULL;
+ return -1;
+}
+
+static int find_group_output(GroupNode *gnode, const char *identifier, OutputSocket **r_sock)
+{
+ int index;
+ for (index = 0; index < gnode->getNumberOfOutputSockets(); ++index) {
+ OutputSocket *sock = gnode->getOutputSocket(index);
+ if (strcmp(sock->getbNodeSocket()->identifier, identifier)==0) {
+ *r_sock = sock;
+ return index;
+ }
+ }
+ *r_sock = NULL;
+ return -1;
+}
+
void GroupNode::ungroup(ExecutionSystem &system)
{
bNode *bnode = this->getbNode();
bNodeTree *subtree = (bNodeTree *)bnode->id;
- vector<InputSocket *> &inputsockets = this->getInputSockets();
- vector<OutputSocket *> &outputsockets = this->getOutputSockets();
- unsigned int index;
/* get the node list size _before_ adding proxy nodes, so they are available for linking */
int nodes_start = system.getNodes().size();
@@ -54,26 +81,44 @@ void GroupNode::ungroup(ExecutionSystem &system)
return;
}
- for (index = 0; index < inputsockets.size(); index++) {
- InputSocket *inputSocket = inputsockets[index];
- bNodeSocket *editorInput = inputSocket->getbNodeSocket();
- if (editorInput->groupsock) {
- SocketProxyNode *proxy = new SocketProxyNode(bnode, editorInput, editorInput->groupsock, false);
- inputSocket->relinkConnections(proxy->getInputSocket(0), index, &system);
- ExecutionSystemHelper::addNode(system.getNodes(), proxy);
- }
- }
-
const bool groupnodeBuffering = system.getContext().isGroupnodeBufferEnabled();
- for (index = 0; index < outputsockets.size(); index++) {
- OutputSocket *outputSocket = outputsockets[index];
- bNodeSocket *editorOutput = outputSocket->getbNodeSocket();
- if (editorOutput->groupsock) {
- SocketProxyNode *proxy = new SocketProxyNode(bnode, editorOutput->groupsock, editorOutput, groupnodeBuffering);
- outputSocket->relinkConnections(proxy->getOutputSocket(0));
- ExecutionSystemHelper::addNode(system.getNodes(), proxy);
+
+ /* create proxy nodes for group input/output nodes */
+ for (bNode *bionode = (bNode *)subtree->nodes.first; bionode; bionode = bionode->next) {
+ if (bionode->type == NODE_GROUP_INPUT) {
+ for (bNodeSocket *bsock = (bNodeSocket *)bionode->outputs.first; bsock; bsock = bsock->next) {
+ InputSocket *gsock;
+ int gsock_index = find_group_input(this, bsock->identifier, &gsock);
+ /* ignore virtual sockets */
+ if (gsock) {
+ SocketProxyNode *proxy = new SocketProxyNode(bionode, gsock->getbNodeSocket(), bsock, false);
+ ExecutionSystemHelper::addNode(system.getNodes(), proxy);
+
+ gsock->relinkConnectionsDuplicate(proxy->getInputSocket(0), gsock_index, &system);
+ }
+ }
+ }
+
+ if (bionode->type == NODE_GROUP_OUTPUT && (bionode->flag & NODE_DO_OUTPUT)) {
+ for (bNodeSocket *bsock = (bNodeSocket *)bionode->inputs.first; bsock; bsock = bsock->next) {
+ OutputSocket *gsock;
+ find_group_output(this, bsock->identifier, &gsock);
+ /* ignore virtual sockets */
+ if (gsock) {
+ SocketProxyNode *proxy = new SocketProxyNode(bionode, bsock, gsock->getbNodeSocket(), groupnodeBuffering);
+ ExecutionSystemHelper::addNode(system.getNodes(), proxy);
+
+ gsock->relinkConnections(proxy->getOutputSocket(0));
+ }
+ }
}
}
-
- ExecutionSystemHelper::addbNodeTree(system, nodes_start, subtree, bnode);
+
+ /* unlink the group node itself, input links have been duplicated */
+ for (int index = 0; index < this->getNumberOfInputSockets(); ++index) {
+ InputSocket *sock = this->getInputSocket(index);
+ sock->unlinkConnections(&system);
+ }
+
+ ExecutionSystemHelper::addbNodeTree(system, nodes_start, subtree, this->getInstanceKey());
}
diff --git a/source/blender/compositor/nodes/COM_LensDistortionNode.cpp b/source/blender/compositor/nodes/COM_LensDistortionNode.cpp
index 94c2fc885fb..f91744d88b6 100644
--- a/source/blender/compositor/nodes/COM_LensDistortionNode.cpp
+++ b/source/blender/compositor/nodes/COM_LensDistortionNode.cpp
@@ -51,8 +51,8 @@ void LensDistortionNode::convertToOperations(ExecutionSystem *graph, CompositorC
operation->setData(data);
if (!(this->getInputSocket(1)->isConnected() || this->getInputSocket(2)->isConnected())) {
// no nodes connected to the distortion and dispersion. We can precalculate some values
- float distortion = ((const bNodeSocketValueFloat *)this->getInputSocket(1)->getbNodeSocket()->default_value)->value;
- float dispersion = ((const bNodeSocketValueFloat *)this->getInputSocket(2)->getbNodeSocket()->default_value)->value;
+ float distortion = this->getInputSocket(1)->getEditorValueFloat();
+ float dispersion = this->getInputSocket(2)->getEditorValueFloat();
operation->setDistortionAndDispersion(distortion, dispersion);
}
diff --git a/source/blender/compositor/nodes/COM_NormalNode.cpp b/source/blender/compositor/nodes/COM_NormalNode.cpp
index fbfff8386d0..41b91f61328 100644
--- a/source/blender/compositor/nodes/COM_NormalNode.cpp
+++ b/source/blender/compositor/nodes/COM_NormalNode.cpp
@@ -36,15 +36,13 @@ void NormalNode::convertToOperations(ExecutionSystem *graph, CompositorContext *
InputSocket *inputSocket = this->getInputSocket(0);
OutputSocket *outputSocket = this->getOutputSocket(0);
OutputSocket *outputSocketDotproduct = this->getOutputSocket(1);
- bNode *editorNode = this->getbNode();
SetVectorOperation *operationSet = new SetVectorOperation();
- bNodeSocket *insock = (bNodeSocket *)editorNode->outputs.first;
- bNodeSocketValueVector *dval = (bNodeSocketValueVector *)insock->default_value;
float normal[3];
+ outputSocket->getEditorValueVector(normal);
/* animation can break normalization, this restores it */
- normalize_v3_v3(normal, dval->value);
+ normalize_v3(normal);
operationSet->setX(normal[0]);
operationSet->setY(normal[1]);
diff --git a/source/blender/compositor/nodes/COM_SocketProxyNode.cpp b/source/blender/compositor/nodes/COM_SocketProxyNode.cpp
index ded6186ad77..c822d2107ec 100644
--- a/source/blender/compositor/nodes/COM_SocketProxyNode.cpp
+++ b/source/blender/compositor/nodes/COM_SocketProxyNode.cpp
@@ -50,54 +50,54 @@ void SocketProxyNode::convertToOperations(ExecutionSystem *graph, CompositorCont
{
OutputSocket *outputsocket = this->getOutputSocket(0);
InputSocket *inputsocket = this->getInputSocket(0);
- if (outputsocket->isConnected()) {
- if (inputsocket->isConnected()) {
- SocketProxyOperation *operation = new SocketProxyOperation(this->getOutputSocket()->getDataType());
- inputsocket->relinkConnections(operation->getInputSocket(0));
- outputsocket->relinkConnections(operation->getOutputSocket(0));
- graph->addOperation(operation);
- if (m_buffer) {
- WriteBufferOperation *writeOperation = new WriteBufferOperation();
- ReadBufferOperation *readOperation = new ReadBufferOperation();
- readOperation->setMemoryProxy(writeOperation->getMemoryProxy());
-
- operation->getOutputSocket()->relinkConnections(readOperation->getOutputSocket());
- addLink(graph, operation->getOutputSocket(), writeOperation->getInputSocket(0));
-
- graph->addOperation(writeOperation);
- graph->addOperation(readOperation);
- }
+ if (inputsocket->isConnected()) {
+ SocketProxyOperation *operation = new SocketProxyOperation(this->getOutputSocket()->getDataType());
+ inputsocket->relinkConnections(operation->getInputSocket(0));
+ outputsocket->relinkConnections(operation->getOutputSocket(0));
+ graph->addOperation(operation);
+
+ if (m_buffer) {
+ WriteBufferOperation *writeOperation = new WriteBufferOperation();
+ ReadBufferOperation *readOperation = new ReadBufferOperation();
+ readOperation->setMemoryProxy(writeOperation->getMemoryProxy());
+
+ operation->getOutputSocket()->relinkConnections(readOperation->getOutputSocket());
+ addLink(graph, operation->getOutputSocket(), writeOperation->getInputSocket(0));
+
+ graph->addOperation(writeOperation);
+ graph->addOperation(readOperation);
}
- else {
- /* If input is not connected, add a constant value operation instead */
- switch (outputsocket->getDataType()) {
- case COM_DT_VALUE:
- {
- SetValueOperation *operation = new SetValueOperation();
- bNodeSocketValueFloat *dval = (bNodeSocketValueFloat *)inputsocket->getbNodeSocket()->default_value;
- operation->setValue(dval->value);
- outputsocket->relinkConnections(operation->getOutputSocket(0));
- graph->addOperation(operation);
- break;
- }
- case COM_DT_COLOR:
- {
- SetColorOperation *operation = new SetColorOperation();
- bNodeSocketValueRGBA *dval = (bNodeSocketValueRGBA *)inputsocket->getbNodeSocket()->default_value;
- operation->setChannels(dval->value);
- outputsocket->relinkConnections(operation->getOutputSocket(0));
- graph->addOperation(operation);
- break;
- }
- case COM_DT_VECTOR:
- {
- SetVectorOperation *operation = new SetVectorOperation();
- bNodeSocketValueVector *dval = (bNodeSocketValueVector *)inputsocket->getbNodeSocket()->default_value;
- operation->setVector(dval->value);
- outputsocket->relinkConnections(operation->getOutputSocket(0));
- graph->addOperation(operation);
- break;
- }
+ }
+ else if (outputsocket->isConnected()) {
+ /* If input is not connected, add a constant value operation instead */
+ switch (outputsocket->getDataType()) {
+ case COM_DT_VALUE:
+ {
+ SetValueOperation *operation = new SetValueOperation();
+ operation->setValue(inputsocket->getEditorValueFloat());
+ outputsocket->relinkConnections(operation->getOutputSocket(0));
+ graph->addOperation(operation);
+ break;
+ }
+ case COM_DT_COLOR:
+ {
+ SetColorOperation *operation = new SetColorOperation();
+ float col[4];
+ inputsocket->getEditorValueColor(col);
+ operation->setChannels(col);
+ outputsocket->relinkConnections(operation->getOutputSocket(0));
+ graph->addOperation(operation);
+ break;
+ }
+ case COM_DT_VECTOR:
+ {
+ SetVectorOperation *operation = new SetVectorOperation();
+ float vec[3];
+ inputsocket->getEditorValueVector(vec);
+ operation->setVector(vec);
+ outputsocket->relinkConnections(operation->getOutputSocket(0));
+ graph->addOperation(operation);
+ break;
}
}
}
diff --git a/source/blender/compositor/nodes/COM_ValueNode.cpp b/source/blender/compositor/nodes/COM_ValueNode.cpp
index 593d74952ee..ed4440aa099 100644
--- a/source/blender/compositor/nodes/COM_ValueNode.cpp
+++ b/source/blender/compositor/nodes/COM_ValueNode.cpp
@@ -32,9 +32,8 @@ ValueNode::ValueNode(bNode *editorNode) : Node(editorNode)
void ValueNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context)
{
SetValueOperation *operation = new SetValueOperation();
- bNodeSocket *socket = this->getEditorOutputSocket(0);
- bNodeSocketValueFloat *dval = (bNodeSocketValueFloat *)socket->default_value;
- this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket());
- operation->setValue(dval->value);
+ OutputSocket *output = this->getOutputSocket(0);
+ output->relinkConnections(operation->getOutputSocket());
+ operation->setValue(output->getEditorValueFloat());
graph->addOperation(operation);
}
diff --git a/source/blender/compositor/operations/COM_PreviewOperation.cpp b/source/blender/compositor/operations/COM_PreviewOperation.cpp
index 6e58b277f66..ba158fb2509 100644
--- a/source/blender/compositor/operations/COM_PreviewOperation.cpp
+++ b/source/blender/compositor/operations/COM_PreviewOperation.cpp
@@ -36,42 +36,47 @@ extern "C" {
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
#include "IMB_colormanagement.h"
+ #include "BKE_node.h"
}
PreviewOperation::PreviewOperation(const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings) : NodeOperation()
{
this->addInputSocket(COM_DT_COLOR, COM_SC_NO_RESIZE);
+ this->m_preview = NULL;
this->m_outputBuffer = NULL;
this->m_input = NULL;
this->m_divider = 1.0f;
- this->m_node = NULL;
this->m_viewSettings = viewSettings;
this->m_displaySettings = displaySettings;
}
+void PreviewOperation::verifyPreview(bNodeInstanceHash *previews, bNodeInstanceKey key)
+{
+ /* Size (0, 0) ensures the preview rect is not allocated in advance,
+ * this is set later in initExecution once the resolution is determined.
+ */
+ this->m_preview = BKE_node_preview_verify(previews, key, 0, 0, TRUE);
+}
+
void PreviewOperation::initExecution()
{
this->m_input = getInputSocketReader(0);
- if (!this->m_node->preview) {
- this->m_node->preview = (bNodePreview *)MEM_callocN(sizeof(bNodePreview), "node preview");
- }
- else {
- if (this->getWidth() == (unsigned int)this->m_node->preview->xsize &&
- this->getHeight() == (unsigned int)this->m_node->preview->ysize)
- {
- this->m_outputBuffer = this->m_node->preview->rect;
- }
+
+ if (this->getWidth() == (unsigned int)this->m_preview->xsize &&
+ this->getHeight() == (unsigned int)this->m_preview->ysize)
+ {
+ this->m_outputBuffer = this->m_preview->rect;
}
if (this->m_outputBuffer == NULL) {
this->m_outputBuffer = (unsigned char *)MEM_callocN(sizeof(unsigned char) * 4 * getWidth() * getHeight(), "PreviewOperation");
- if (this->m_node->preview->rect) {
- MEM_freeN(this->m_node->preview->rect);
+ if (this->m_preview->rect) {
+ MEM_freeN(this->m_preview->rect);
}
- this->m_node->preview->xsize = getWidth();
- this->m_node->preview->ysize = getHeight();
- this->m_node->preview->rect = this->m_outputBuffer;
+ this->m_preview->xsize = getWidth();
+ this->m_preview->ysize = getHeight();
+ this->m_preview->rect = this->m_outputBuffer;
}
}
diff --git a/source/blender/compositor/operations/COM_PreviewOperation.h b/source/blender/compositor/operations/COM_PreviewOperation.h
index 0da6b8e4e56..bb60dfa0420 100644
--- a/source/blender/compositor/operations/COM_PreviewOperation.h
+++ b/source/blender/compositor/operations/COM_PreviewOperation.h
@@ -35,7 +35,7 @@ protected:
/**
* @brief holds reference to the SDNA bNode, where this nodes will render the preview image for
*/
- bNode *m_node;
+ bNodePreview *m_preview;
SocketReader *m_input;
float m_divider;
@@ -43,6 +43,8 @@ protected:
const ColorManagedDisplaySettings *m_displaySettings;
public:
PreviewOperation(const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings);
+ void verifyPreview(bNodeInstanceHash *previews, bNodeInstanceKey key);
+
bool isOutputOperation(bool rendering) const { return !G.background; }
void initExecution();
void deinitExecution();
@@ -50,7 +52,6 @@ public:
void executeRegion(rcti *rect, unsigned int tileNumber);
void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
- void setbNode(bNode *node) { this->m_node = node; }
bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output);
bool isPreviewOperation() { return true; }
diff --git a/source/blender/editors/include/ED_node.h b/source/blender/editors/include/ED_node.h
index 32baa8883e1..448a15334c7 100644
--- a/source/blender/editors/include/ED_node.h
+++ b/source/blender/editors/include/ED_node.h
@@ -39,7 +39,10 @@ struct Tex;
struct bContext;
struct bNodeTree;
struct bNode;
+struct bNodeType;
+struct bNodeSocketType;
struct bNodeTree;
+struct bNodeTreeType;
struct ScrArea;
struct Scene;
struct View2D;
@@ -51,15 +54,30 @@ typedef enum {
NODE_RIGHT = 8
} NodeBorder;
+/* space_node.c */
+int ED_node_tree_path_length(struct SpaceNode *snode);
+void ED_node_tree_path_get(struct SpaceNode *snode, char *value);
+void ED_node_tree_path_get_fixedbuf(struct SpaceNode *snode, char *value, int max_length);
+
+void ED_node_tree_start(struct SpaceNode *snode, struct bNodeTree *ntree, struct ID *id, struct ID *from);
+void ED_node_tree_push(struct SpaceNode *snode, struct bNodeTree *ntree, struct bNode *gnode);
+void ED_node_tree_pop(struct SpaceNode *snode);
+int ED_node_tree_depth(struct SpaceNode *snode);
+struct bNodeTree *ED_node_tree_get(struct SpaceNode *snode, int level);
+
/* drawnode.c */
void ED_node_init_butfuncs(void);
+void ED_init_custom_node_type(struct bNodeType *ntype);
+void ED_init_custom_node_socket_type(struct bNodeSocketType *stype);
+void ED_init_standard_node_socket_type(struct bNodeSocketType *stype);
+void ED_init_node_socket_type_virtual(struct bNodeSocketType *stype);
void ED_node_sample_set(const float col[4]);
void ED_node_draw_snap(struct View2D *v2d, const float cent[2], float size, NodeBorder border);
/* node_draw.c */
-void ED_node_tree_update(struct SpaceNode *snode, struct Scene *scene);
-void ED_node_changed_update(struct ID *id, struct bNode *node);
-void ED_node_generic_update(struct Main *bmain, struct bNodeTree *ntree, struct bNode *node);
+void ED_node_tree_update(const struct bContext *C);
+void ED_node_tag_update_id(struct ID *id);
+void ED_node_tag_update_nodetree(struct Main *bmain, struct bNodeTree *ntree);
void ED_node_sort(struct bNodeTree *ntree);
/* node_relationships.c */
@@ -67,9 +85,14 @@ void ED_node_link_intersect_test(struct ScrArea *sa, int test);
void ED_node_link_insert(struct ScrArea *sa);
/* node_edit.c */
-void ED_node_shader_default(struct Scene *scene, struct ID *id);
-void ED_node_composit_default(struct Scene *sce);
-void ED_node_texture_default(struct Tex *tex);
+void ED_node_set_tree_type(struct SpaceNode *snode, struct bNodeTreeType *typeinfo);
+int ED_node_is_compositor(struct SpaceNode *snode);
+int ED_node_is_shader(struct SpaceNode *snode);
+int ED_node_is_texture(struct SpaceNode *snode);
+
+void ED_node_shader_default(const struct bContext *C, struct ID *id);
+void ED_node_composit_default(const struct bContext *C, struct Scene *scene);
+void ED_node_texture_default(const struct bContext *C, struct Tex *tex);
int ED_node_select_check(ListBase *lb);
void ED_node_post_apply_transform(struct bContext *C, struct bNodeTree *ntree);
void ED_node_set_active(struct Main *bmain, struct bNodeTree *ntree, struct bNode *node);
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 3c8a9a87fbe..f805b199280 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -259,7 +259,8 @@ typedef enum {
WAVEFORM = (49 << 9),
VECTORSCOPE = (50 << 9),
PROGRESSBAR = (51 << 9),
- SEARCH_MENU_UNLINK = (52 << 9)
+ SEARCH_MENU_UNLINK = (52 << 9),
+ NODESOCKET = (53 << 9)
} eButType;
#define BUTTYPE (63 << 9)
@@ -835,6 +836,8 @@ void uiTemplateEditModeSelection(uiLayout *layout, struct bContext *C);
void uiTemplateTextureImage(uiLayout *layout, struct bContext *C, struct Tex *tex);
void uiTemplateReportsBanner(uiLayout *layout, struct bContext *C);
void uiTemplateKeymapItemProperties(uiLayout *layout, struct PointerRNA *ptr);
+void uiTemplateComponentMenu(uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *name);
+void uiTemplateNodeSocket(uiLayout *layout, struct bContext *C, float *color);
/* Default UIList class name, keep in sync with its declaration in bl_ui/__init__.py */
#define UI_UL_DEFAULT_CLASS_NAME "UI_UL_list"
diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h
index 0086ef03b65..0cb3b2ce6d1 100644
--- a/source/blender/editors/include/UI_resources.h
+++ b/source/blender/editors/include/UI_resources.h
@@ -144,6 +144,7 @@ enum {
TH_NODE,
TH_NODE_IN_OUT,
+ TH_NODE_INTERFACE,
TH_NODE_OPERATOR,
TH_NODE_CONVERTOR,
TH_NODE_GROUP,
diff --git a/source/blender/editors/include/UI_view2d.h b/source/blender/editors/include/UI_view2d.h
index 81a0f526049..3743539a9bd 100644
--- a/source/blender/editors/include/UI_view2d.h
+++ b/source/blender/editors/include/UI_view2d.h
@@ -167,7 +167,7 @@ View2DGrid *UI_view2d_grid_calc(struct Scene *scene, struct View2D *v2d,
short xunits, short xclamp, short yunits, short yclamp, int winx, int winy);
void UI_view2d_grid_draw(struct View2D *v2d, View2DGrid *grid, int flag);
void UI_view2d_constant_grid_draw(struct View2D *v2d);
-void UI_view2d_multi_grid_draw(struct View2D *v2d, float step, int level_size, int totlevels);
+void UI_view2d_multi_grid_draw(struct View2D *v2d, int colorid, float step, int level_size, int totlevels);
void UI_view2d_grid_size(View2DGrid *grid, float *r_dx, float *r_dy);
void UI_view2d_grid_free(View2DGrid *grid);
@@ -200,6 +200,9 @@ struct View2D *UI_view2d_fromcontext_rwin(const struct bContext *C);
void UI_view2d_getscale(struct View2D *v2d, float *x, float *y);
void UI_view2d_getscale_inverse(struct View2D *v2d, float *x, float *y);
+void UI_view2d_getcenter(struct View2D *v2d, float *x, float *y);
+void UI_view2d_setcenter(struct View2D *v2d, float x, float y);
+
short UI_view2d_mouse_in_scrollers(const struct bContext *C, struct View2D *v2d, int x, int y);
/* cached text drawing in v2d, to allow pixel-aligned draw as post process */
diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c
index 5486e12c6bf..7fc5c21f052 100644
--- a/source/blender/editors/interface/interface_draw.c
+++ b/source/blender/editors/interface/interface_draw.c
@@ -42,6 +42,7 @@
#include "BLI_utildefines.h"
#include "BKE_colortools.h"
+#include "BKE_node.h"
#include "BKE_texture.h"
#include "BKE_tracking.h"
@@ -1685,6 +1686,71 @@ void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wc
glDisable(GL_BLEND);
}
+void ui_draw_but_NODESOCKET(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), rcti *recti)
+{
+ static const float size = 5.0f;
+
+ /* 16 values of sin function */
+ static float si[16] = {
+ 0.00000000f, 0.39435585f, 0.72479278f, 0.93775213f,
+ 0.99871650f, 0.89780453f, 0.65137248f, 0.29936312f,
+ -0.10116832f, -0.48530196f, -0.79077573f, -0.96807711f,
+ -0.98846832f, -0.84864425f, -0.57126821f, -0.20129852f
+ };
+ /* 16 values of cos function */
+ static float co[16] = {
+ 1.00000000f, 0.91895781f, 0.68896691f, 0.34730525f,
+ -0.05064916f, -0.44039415f, -0.75875812f, -0.95413925f,
+ -0.99486932f, -0.87434661f, -0.61210598f, -0.25065253f,
+ 0.15142777f, 0.52896401f, 0.82076344f, 0.97952994f,
+ };
+
+ unsigned char *col = but->col;
+ int a;
+ GLint scissor[4];
+ rcti scissor_new;
+ float x, y;
+
+ x = 0.5f * (recti->xmin + recti->xmax);
+ y = 0.5f * (recti->ymin + recti->ymax);
+
+ /* need scissor test, can draw outside of boundary */
+ glGetIntegerv(GL_VIEWPORT, scissor);
+ scissor_new.xmin = ar->winrct.xmin + recti->xmin;
+ scissor_new.ymin = ar->winrct.ymin + recti->ymin;
+ scissor_new.xmax = ar->winrct.xmin + recti->xmax;
+ scissor_new.ymax = ar->winrct.ymin + recti->ymax;
+ BLI_rcti_isect(&scissor_new, &ar->winrct, &scissor_new);
+ glScissor(scissor_new.xmin,
+ scissor_new.ymin,
+ BLI_rcti_size_x(&scissor_new),
+ BLI_rcti_size_y(&scissor_new));
+
+ glColor4ubv(col);
+
+ glEnable(GL_BLEND);
+ glBegin(GL_POLYGON);
+ for (a = 0; a < 16; a++)
+ glVertex2f(x + size * si[a], y + size * co[a]);
+ glEnd();
+ glDisable(GL_BLEND);
+
+ glColor4ub(0, 0, 0, 150);
+
+ glEnable(GL_BLEND);
+ glEnable(GL_LINE_SMOOTH);
+ glBegin(GL_LINE_LOOP);
+ for (a = 0; a < 16; a++)
+ glVertex2f(x + size * si[a], y + size * co[a]);
+ glEnd();
+ glDisable(GL_LINE_SMOOTH);
+ glDisable(GL_BLEND);
+ glLineWidth(1.0f);
+
+ /* restore scissortest */
+ glScissor(scissor[0], scissor[1], scissor[2], scissor[3]);
+}
+
/* ****************************************************** */
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 39aef38fadb..54a173af603 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -5434,6 +5434,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
case LISTROW:
case BUT_IMAGE:
case PROGRESSBAR:
+ case NODESOCKET:
retval = ui_do_but_EXIT(C, but, data, event);
break;
case HISTOGRAM:
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index 6065fcfe574..19b863dd6fa 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -510,6 +510,7 @@ void ui_draw_but_NORMAL(uiBut *but, struct uiWidgetColors *wcol, rcti *rect);
void ui_draw_but_CURVE(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, rcti *rect);
void ui_draw_but_IMAGE(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, rcti *rect);
void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, rcti *rect);
+void ui_draw_but_NODESOCKET(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, rcti *rect);
/* interface_handlers.c */
extern void ui_pan_to_scroll(const struct wmEvent *event, int *type, int *val);
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index eeddd8c7a9a..ee2625cf94b 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -32,6 +32,7 @@
#include "MEM_guardedalloc.h"
#include "DNA_dynamicpaint_types.h"
+#include "DNA_node_types.h"
#include "DNA_scene_types.h"
#include "DNA_object_types.h"
#include "DNA_object_force.h"
@@ -57,6 +58,7 @@
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_modifier.h"
+#include "BKE_node.h"
#include "BKE_object.h"
#include "BKE_packedFile.h"
#include "BKE_particle.h"
@@ -3064,3 +3066,65 @@ void uiTemplateColormanagedViewSettings(uiLayout *layout, bContext *UNUSED(C), P
if (view_settings->flag & COLORMANAGE_VIEW_USE_CURVES)
uiTemplateCurveMapping(col, &view_transform_ptr, "curve_mapping", 'c', TRUE, 0);
}
+
+/********************************* Component Menu *************************************/
+
+typedef struct ComponentMenuArgs {
+ PointerRNA ptr;
+ char propname[64]; /* XXX arbitrary */
+} ComponentMenuArgs;
+/* NOTE: this is a block-menu, needs 0 events, otherwise the menu closes */
+static uiBlock *component_menu(bContext *C, ARegion *ar, void *args_v)
+{
+ ComponentMenuArgs *args = (ComponentMenuArgs*)args_v;
+ uiBlock *block;
+ uiLayout *layout;
+
+ block = uiBeginBlock(C, ar, __func__, UI_EMBOSS);
+ uiBlockSetFlag(block, UI_BLOCK_KEEP_OPEN);
+
+ layout = uiLayoutColumn(uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, UI_UNIT_X * 6, UI_UNIT_Y, UI_GetStyle()), 0);
+
+ uiItemR(layout, &args->ptr, args->propname, UI_ITEM_R_EXPAND, "", ICON_NONE);
+
+ uiBoundsBlock(block, 6);
+ uiBlockSetDirection(block, UI_DOWN);
+ uiEndBlock(C, block);
+
+ return block;
+}
+void uiTemplateComponentMenu(uiLayout *layout, PointerRNA *ptr, const char *propname, const char *name)
+{
+ ComponentMenuArgs *args = MEM_callocN(sizeof(ComponentMenuArgs), "component menu template args");
+ uiBlock *block;
+
+ args->ptr = *ptr;
+ BLI_strncpy(args->propname, propname, sizeof(args->propname));
+
+ block = uiLayoutGetBlock(layout);
+ uiBlockBeginAlign(block);
+
+ uiDefBlockButN(block, component_menu, args, name, 0, 0, UI_UNIT_X * 6, UI_UNIT_Y, "");
+
+ uiBlockEndAlign(block);
+}
+
+/************************* Node Socket Icon **************************/
+
+void uiTemplateNodeSocket(uiLayout *layout, bContext *UNUSED(C), float *color)
+{
+ uiBlock *block;
+ uiBut *but;
+
+ block = uiLayoutGetBlock(layout);
+ uiBlockBeginAlign(block);
+
+ /* XXX using explicit socket colors is not quite ideal.
+ * Eventually it should be possible to use theme colors for this purpose,
+ * but this requires a better design for extendable color palettes in user prefs.
+ */
+ but = uiDefBut(block, NODESOCKET, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
+ rgba_float_to_uchar(but->col, color);
+
+ uiBlockEndAlign(block);
+}
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index 78b6d2541fd..fc379468c6b 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -3367,6 +3367,10 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
ui_draw_but_TRACKPREVIEW(ar, but, &tui->wcol_regular, rect);
break;
+ case NODESOCKET:
+ ui_draw_but_NODESOCKET(ar, but, &tui->wcol_regular, rect);
+ break;
+
default:
wt = widget_type(UI_WTYPE_REGULAR);
}
diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c
index 7ff5677259e..6b278358db9 100644
--- a/source/blender/editors/interface/resources.c
+++ b/source/blender/editors/interface/resources.c
@@ -389,6 +389,8 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
cp = ts->syntaxv; break;
case TH_NODE_GROUP:
cp = ts->syntaxc; break;
+ case TH_NODE_INTERFACE:
+ cp= ts->console_output; break;
case TH_NODE_FRAME:
cp = ts->movie; break;
case TH_NODE_MATTE:
@@ -951,7 +953,7 @@ void ui_theme_init_default(void)
rgba_char_args_set_fl(btheme->ttime.grid, 0.36, 0.36, 0.36, 1.0);
rgba_char_args_set(btheme->ttime.shade1, 173, 173, 173, 255); /* sliders */
- /* space node, re-uses syntax color storage */
+ /* space node, re-uses syntax and console color storage */
btheme->tnode = btheme->tv3d;
rgba_char_args_set(btheme->tnode.edge_select, 255, 255, 255, 255); /* wire selected */
rgba_char_args_set(btheme->tnode.syntaxl, 155, 155, 155, 160); /* TH_NODE, backdrop */
@@ -960,6 +962,7 @@ void ui_theme_init_default(void)
rgba_char_args_set(btheme->tnode.syntaxv, 104, 106, 117, 255); /* generator */
rgba_char_args_set(btheme->tnode.syntaxc, 105, 117, 110, 255); /* group */
rgba_char_args_set(btheme->tnode.movie, 155, 155, 155, 160); /* frame */
+ rgba_char_args_set(btheme->tnode.console_output, 190, 190, 80, 255); /* group input/output */
btheme->tnode.noodle_curving = 5;
/* space logic */
@@ -2149,6 +2152,13 @@ void init_userdef_do_versions(void)
}
}
+ if (U.versionfile < 266 || (U.versionfile == 266 && U.subversionfile < 2)) {
+ bTheme *btheme;
+ for (btheme = U.themes.first; btheme; btheme = btheme->next) {
+ rgba_char_args_test_set(btheme->tnode.console_output, 223, 202, 53, 255); /* interface nodes */
+ }
+ }
+
/* NOTE!! from now on use U.versionfile and U.subversionfile */
diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c
index 8a6de9a549b..fe7e6d01955 100644
--- a/source/blender/editors/interface/view2d.c
+++ b/source/blender/editors/interface/view2d.c
@@ -1368,7 +1368,7 @@ void UI_view2d_constant_grid_draw(View2D *v2d)
}
/* Draw a multi-level grid in given 2d-region */
-void UI_view2d_multi_grid_draw(View2D *v2d, float step, int level_size, int totlevels)
+void UI_view2d_multi_grid_draw(View2D *v2d, int colorid, float step, int level_size, int totlevels)
{
int offset = -10;
float lstep = step;
@@ -1378,7 +1378,7 @@ void UI_view2d_multi_grid_draw(View2D *v2d, float step, int level_size, int totl
int i;
float start;
- UI_ThemeColorShade(TH_BACK, offset);
+ UI_ThemeColorShade(colorid, offset);
i = (v2d->cur.xmin >= 0.0f ? -(int)(-v2d->cur.xmin / lstep) : (int)(v2d->cur.xmin / lstep));
start = i * lstep;
@@ -1402,7 +1402,7 @@ void UI_view2d_multi_grid_draw(View2D *v2d, float step, int level_size, int totl
}
/* X and Y axis */
- UI_ThemeColorShade(TH_BACK, offset - 8);
+ UI_ThemeColorShade(colorid, offset - 8);
glVertex2f(0.0f, v2d->cur.ymin);
glVertex2f(0.0f, v2d->cur.ymax);
glVertex2f(v2d->cur.xmin, 0.0f);
@@ -2075,6 +2075,31 @@ void UI_view2d_getscale_inverse(View2D *v2d, float *x, float *y)
if (y) *y = BLI_rctf_size_y(&v2d->cur) / BLI_rcti_size_y(&v2d->mask);
}
+/* Simple functions for consistent center offset access.
+ * Used by node editor to shift view center for each individual node tree.
+ */
+void UI_view2d_getcenter(struct View2D *v2d, float *x, float *y)
+{
+ /* get center */
+ if (x) *x = 0.5f*(v2d->cur.xmin + v2d->cur.xmax);
+ if (y) *y = 0.5f*(v2d->cur.ymin + v2d->cur.ymax);
+}
+void UI_view2d_setcenter(struct View2D *v2d, float x, float y)
+{
+ /* get delta from current center */
+ float dx = x - 0.5f*(v2d->cur.xmin + v2d->cur.xmax);
+ float dy = y - 0.5f*(v2d->cur.ymin + v2d->cur.ymax);
+
+ /* add to cur */
+ v2d->cur.xmin += dx;
+ v2d->cur.xmax += dx;
+ v2d->cur.ymin += dy;
+ v2d->cur.ymax += dy;
+
+ /* make sure that 'cur' rect is in a valid state as a result of these changes */
+ UI_view2d_curRect_validate(v2d);
+}
+
/* Check if mouse is within scrollers
* - Returns appropriate code for match
* 'h' = in horizontal scroller
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index dbb0d55a2b1..312cceac77d 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -852,7 +852,7 @@ static int object_lamp_add_exec(bContext *C, wmOperator *op)
rename_id(&la->id, get_lamp_defname(type));
if (BKE_scene_use_new_shading_nodes(scene)) {
- ED_node_shader_default(scene, &la->id);
+ ED_node_shader_default(C, &la->id);
la->use_nodes = TRUE;
}
diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c
index dd5b97a68ed..948e272eca0 100644
--- a/source/blender/editors/render/render_preview.c
+++ b/source/blender/editors/render/render_preview.c
@@ -378,8 +378,8 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre
sce->lay = 1 << mat->pr_type;
if (mat->nodetree && sp->pr_method == PR_NODE_RENDER) {
/* two previews, they get copied by wmJob */
- ntreeInitPreview(mat->nodetree, sp->sizex, sp->sizey);
- ntreeInitPreview(origmat->nodetree, sp->sizex, sp->sizey);
+ BKE_node_preview_init_tree(mat->nodetree, sp->sizex, sp->sizey, TRUE);
+ BKE_node_preview_init_tree(origmat->nodetree, sp->sizex, sp->sizey, TRUE);
}
}
}
@@ -442,8 +442,8 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre
if (tex && tex->nodetree && sp->pr_method == PR_NODE_RENDER) {
/* two previews, they get copied by wmJob */
- ntreeInitPreview(origtex->nodetree, sp->sizex, sp->sizey);
- ntreeInitPreview(tex->nodetree, sp->sizex, sp->sizey);
+ BKE_node_preview_init_tree(origtex->nodetree, sp->sizex, sp->sizey, TRUE);
+ BKE_node_preview_init_tree(tex->nodetree, sp->sizex, sp->sizey, TRUE);
}
}
else if (id_type == ID_LA) {
@@ -479,8 +479,8 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre
if (la && la->nodetree && sp->pr_method == PR_NODE_RENDER) {
/* two previews, they get copied by wmJob */
- ntreeInitPreview(origla->nodetree, sp->sizex, sp->sizey);
- ntreeInitPreview(la->nodetree, sp->sizex, sp->sizey);
+ BKE_node_preview_init_tree(origla->nodetree, sp->sizex, sp->sizey, TRUE);
+ BKE_node_preview_init_tree(la->nodetree, sp->sizex, sp->sizey, TRUE);
}
}
else if (id_type == ID_WO) {
@@ -497,8 +497,8 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre
if (wrld && wrld->nodetree && sp->pr_method == PR_NODE_RENDER) {
/* two previews, they get copied by wmJob */
- ntreeInitPreview(wrld->nodetree, sp->sizex, sp->sizey);
- ntreeInitPreview(origwrld->nodetree, sp->sizex, sp->sizey);
+ BKE_node_preview_init_tree(wrld->nodetree, sp->sizex, sp->sizey, TRUE);
+ BKE_node_preview_init_tree(origwrld->nodetree, sp->sizex, sp->sizey, TRUE);
}
}
diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c
index c33b7442e41..54f59a82adc 100644
--- a/source/blender/editors/render/render_shading.c
+++ b/source/blender/editors/render/render_shading.c
@@ -379,7 +379,7 @@ static int new_material_exec(bContext *C, wmOperator *UNUSED(op))
ma = BKE_material_add(bmain, "Material");
if (BKE_scene_use_new_shading_nodes(scene)) {
- ED_node_shader_default(scene, &ma->id);
+ ED_node_shader_default(C, &ma->id);
ma->use_nodes = TRUE;
}
}
@@ -481,7 +481,7 @@ static int new_world_exec(bContext *C, wmOperator *UNUSED(op))
wo = add_world(bmain, "World");
if (BKE_scene_use_new_shading_nodes(scene)) {
- ED_node_shader_default(scene, &wo->id);
+ ED_node_shader_default(C, &wo->id);
wo->use_nodes = TRUE;
}
}
diff --git a/source/blender/editors/render/render_update.c b/source/blender/editors/render/render_update.c
index a467b053443..d29c711cad0 100644
--- a/source/blender/editors/render/render_update.c
+++ b/source/blender/editors/render/render_update.c
@@ -377,7 +377,7 @@ static void texture_changed(Main *bmain, Tex *tex)
if (scene->use_nodes && scene->nodetree) {
for (node = scene->nodetree->nodes.first; node; node = node->next) {
if (node->id == &tex->id)
- ED_node_changed_update(&scene->id, node);
+ ED_node_tag_update_id(&scene->id);
}
}
diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c
index 1906a3259a9..8b69e6e831d 100644
--- a/source/blender/editors/screen/screen_ops.c
+++ b/source/blender/editors/screen/screen_ops.c
@@ -47,6 +47,7 @@
#include "DNA_meta_types.h"
#include "DNA_mesh_types.h"
#include "DNA_mask_types.h"
+#include "DNA_node_types.h"
#include "DNA_userdef_types.h"
#include "BKE_context.h"
@@ -54,6 +55,7 @@
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_mesh.h"
+#include "BKE_node.h"
#include "BKE_object.h"
#include "BKE_report.h"
#include "BKE_scene.h"
@@ -252,7 +254,7 @@ int ED_operator_node_active(bContext *C)
{
SpaceNode *snode = CTX_wm_space_node(C);
- if (snode && snode->edittree)
+ if (snode && ntreeIsValid(snode->edittree))
return 1;
return 0;
diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c
index d94b9372560..92a55151b66 100644
--- a/source/blender/editors/sculpt_paint/paint_image.c
+++ b/source/blender/editors/sculpt_paint/paint_image.c
@@ -407,7 +407,7 @@ void paint_brush_init_tex(Brush *brush)
if (brush) {
MTex *mtex = &brush->mtex;
if (mtex->tex && mtex->tex->nodetree)
- ntreeTexBeginExecTree(mtex->tex->nodetree, 1); /* has internal flag to detect it only does it once */
+ ntreeTexBeginExecTree(mtex->tex->nodetree); /* has internal flag to detect it only does it once */
}
}
@@ -416,7 +416,7 @@ void paint_brush_exit_tex(Brush *brush)
if (brush) {
MTex *mtex = &brush->mtex;
if (mtex->tex && mtex->tex->nodetree)
- ntreeTexEndExecTree(mtex->tex->nodetree->execdata, 1);
+ ntreeTexEndExecTree(mtex->tex->nodetree->execdata);
}
}
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 156be008a96..51500ab8e1c 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -4073,7 +4073,7 @@ static void sculpt_brush_init_tex(const Scene *scene, Sculpt *sd, SculptSession
/* init mtex nodes */
if (mtex->tex && mtex->tex->nodetree)
- ntreeTexBeginExecTree(mtex->tex->nodetree, 1); /* has internal flag to detect it only does it once */
+ ntreeTexBeginExecTree(mtex->tex->nodetree); /* has internal flag to detect it only does it once */
/* TODO: Shouldn't really have to do this at the start of every
* stroke, but sculpt would need some sort of notification when
@@ -4249,7 +4249,7 @@ static void sculpt_brush_exit_tex(Sculpt *sd)
MTex *mtex = &brush->mtex;
if (mtex->tex && mtex->tex->nodetree)
- ntreeTexEndExecTree(mtex->tex->nodetree->execdata, 1);
+ ntreeTexEndExecTree(mtex->tex->nodetree->execdata);
}
static void sculpt_stroke_done(const bContext *C, struct PaintStroke *UNUSED(stroke))
diff --git a/source/blender/editors/space_buttons/buttons_texture.c b/source/blender/editors/space_buttons/buttons_texture.c
index 1643921e4dd..bb1310d486a 100644
--- a/source/blender/editors/space_buttons/buttons_texture.c
+++ b/source/blender/editors/space_buttons/buttons_texture.c
@@ -113,7 +113,7 @@ static void buttons_texture_users_find_nodetree(ListBase *users, ID *id,
{
bNode *node;
- if (ntree) {
+ if (ntreeIsValid(ntree)) {
for (node = ntree->nodes.first; node; node = node->next) {
if (node->typeinfo->nclass == NODE_CLASS_TEXTURE) {
PointerRNA ptr;
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index 4a14d6ba6fd..fddecf267a9 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -43,18 +43,23 @@
#include "BKE_image.h"
#include "BKE_main.h"
#include "BKE_node.h"
+#include "BKE_scene.h"
#include "BKE_tracking.h"
#include "BLF_api.h"
#include "BLF_translation.h"
+#include "NOD_texture.h"
#include "BIF_gl.h"
#include "BIF_glutil.h"
+#include "BLF_translation.h"
#include "MEM_guardedalloc.h"
#include "RNA_access.h"
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
#include "ED_node.h"
@@ -68,189 +73,137 @@
#include "IMB_imbuf_types.h"
#include "node_intern.h" /* own include */
+#include "NOD_composite.h"
+#include "NOD_shader.h"
+#include "NOD_texture.h"
-/* ****************** SOCKET BUTTON DRAW FUNCTIONS ***************** */
+/* ****************** MENU FUNCTIONS ***************** */
-static void node_sync_cb(bContext *UNUSED(C), void *snode_v, void *node_v)
+static void node_add_menu_class(bContext *C, uiLayout *layout, void *arg_nodeclass)
{
- SpaceNode *snode = snode_v;
+ Scene *scene= CTX_data_scene(C);
+ SpaceNode *snode= CTX_wm_space_node(C);
+ bNodeTree *ntree;
+ int nodeclass= GET_INT_FROM_POINTER(arg_nodeclass);
+ int event, compatibility= 0;
- if (snode->treetype == NTREE_SHADER) {
- nodeShaderSynchronizeID(node_v, 1);
- // allqueue(REDRAWBUTSSHADING, 0);
+ ntree = snode->nodetree;
+
+ if(!ntree) {
+ uiItemS(layout);
+ return;
}
-}
-
-static void node_socket_button_label(const bContext *UNUSED(C), uiBlock *block,
- bNodeTree *UNUSED(ntree), bNode *UNUSED(node), bNodeSocket *sock,
- const char *UNUSED(name), int x, int y, int width)
-{
- uiDefBut(block, LABEL, 0, IFACE_(sock->name), x, y, width, NODE_DY, NULL, 0, 0, 0, 0, "");
-}
-static void node_socket_button_default(const bContext *C, uiBlock *block,
- bNodeTree *ntree, bNode *node, bNodeSocket *sock,
- const char *name, int x, int y, int width)
-{
- if (sock->link || (sock->flag & SOCK_HIDE_VALUE))
- node_socket_button_label(C, block, ntree, node, sock, name, x, y, width);
- else {
+ if(ntree->type == NTREE_SHADER) {
+ if(BKE_scene_use_new_shading_nodes(scene))
+ compatibility= NODE_NEW_SHADING;
+ else
+ compatibility= NODE_OLD_SHADING;
+ }
+
+ if (nodeclass==NODE_CLASS_GROUP) {
+ Main *bmain= CTX_data_main(C);
+ bNodeTree *ngroup;
+ const char *ngroup_type, *node_type;
PointerRNA ptr;
- uiBut *bt;
-
- RNA_pointer_create(&ntree->id, &RNA_NodeSocket, sock, &ptr);
- bt = uiDefButR(block, NUM, B_NODE_EXEC, IFACE_(name),
- x, y + 1, width, NODE_DY - 2,
- &ptr, "default_value", 0, 0, 0, -1, -1, NULL);
- if (node)
- uiButSetFunc(bt, node_sync_cb, CTX_wm_space_node(C), node);
+ NODE_TYPES_BEGIN(ntype)
+ if (ntype->nclass!=nodeclass || !ntype->ui_name)
+ continue;
+ if (!ntype->poll(ntype, ntree))
+ continue;
+
+ switch (ntree->type) {
+ case NTREE_COMPOSIT:
+ ngroup_type = "CompositorNodeTree";
+ node_type = "CompositorNodeGroup";
+ break;
+ case NTREE_SHADER:
+ ngroup_type = "ShaderNodeTree";
+ node_type = "ShaderNodeGroup";
+ break;
+ case NTREE_TEXTURE:
+ ngroup_type = "TextureNodeTree";
+ node_type = "TextureNodeGroup";
+ break;
+ }
+
+ ptr = uiItemFullO(layout, "NODE_OT_group_make", "New Group", ntype->ui_icon, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS);
+ RNA_string_set(&ptr, "node_type", node_type);
+
+ uiItemS(layout);
+
+ for(ngroup=bmain->nodetree.first, event=0; ngroup; ngroup= ngroup->id.next, ++event) {
+ /* only use group trees of the right type */
+ if (strcmp(ngroup->idname, ngroup_type)!=0)
+ continue;
+ if (!nodeGroupPoll(ntree, ngroup))
+ continue;
+
+ ptr = uiItemFullO(layout, "NODE_OT_add_group_node", ngroup->id.name+2, ntype->ui_icon, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS);
+ RNA_string_set(&ptr, "type", ntype->idname);
+ RNA_string_set(&ptr, "grouptree", ngroup->id.name+2);
+ }
+ NODE_TYPES_END
}
-}
-
-static void node_socket_button_string(const bContext *C, uiBlock *block,
- bNodeTree *ntree, bNode *node, bNodeSocket *sock,
- const char *name, int x, int y, int width)
-{
- if (sock->link || (sock->flag & SOCK_HIDE_VALUE))
- node_socket_button_label(C, block, ntree, node, sock, name, x, y, width);
- else {
+ else if (nodeclass==NODE_DYNAMIC) {
+ /* disabled */
+ }
+ else
+ {
PointerRNA ptr;
- uiBut *bt;
-
- SpaceNode *snode = CTX_wm_space_node(C);
- const char *ui_name = IFACE_(name);
- float slen;
-
- UI_ThemeColor(TH_TEXT);
- slen = (UI_GetStringWidth(ui_name) + NODE_MARGIN_X) * snode->aspect; /* XXX, check for dpis */
- while (slen > (width * 0.5f) && *ui_name) {
- ui_name = BLI_str_find_next_char_utf8(ui_name, NULL);
- slen = (UI_GetStringWidth(ui_name) + NODE_MARGIN_X) * snode->aspect;
- }
-
- RNA_pointer_create(&ntree->id, &RNA_NodeSocket, sock, &ptr);
-
- if (name[0] == '\0')
- slen = 0.0;
-
- bt = uiDefButR(block, TEX, B_NODE_EXEC, "",
- x, y + 1, width - slen, NODE_DY - 2,
- &ptr, "default_value", 0, 0, 0, -1, -1, "");
- if (node)
- uiButSetFunc(bt, node_sync_cb, CTX_wm_space_node(C), node);
- if (slen > 0.0f)
- uiDefBut(block, LABEL, 0, IFACE_(name), x + (width - slen), y + 2, slen, NODE_DY - 2, NULL, 0, 0, 0, 0, "");
+ NODE_TYPES_BEGIN(ntype)
+ if (ntype->nclass!=nodeclass || !ntype->ui_name)
+ continue;
+ if (!ntype->poll(ntype, ntree))
+ continue;
+ if (compatibility && (ntype->compatibility & compatibility)==0)
+ continue;
+
+ ptr = uiItemFullO(layout, "NODE_OT_add_node", IFACE_(ntype->ui_name), ntype->ui_icon, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS);
+ RNA_string_set(&ptr, "type", ntype->idname);
+ NODE_TYPES_END
}
}
-typedef struct SocketComponentMenuArgs {
- PointerRNA ptr;
- int x, y, width;
- uiButHandleFunc cb;
- void *arg1, *arg2;
-} SocketComponentMenuArgs;
-/* NOTE: this is a block-menu, needs 0 events, otherwise the menu closes */
-static uiBlock *socket_component_menu(bContext *C, ARegion *ar, void *args_v)
+static void node_add_menu_foreach_class_cb(void *calldata, int nclass, const char *name)
{
- SocketComponentMenuArgs *args = (SocketComponentMenuArgs *)args_v;
- uiBlock *block;
- uiLayout *layout;
-
- block = uiBeginBlock(C, ar, __func__, UI_EMBOSS);
- uiBlockSetFlag(block, UI_BLOCK_KEEP_OPEN);
-
- layout = uiLayoutColumn(uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL,
- args->x, args->y + 2, args->width, NODE_DY, UI_GetStyle()), FALSE);
-
- uiItemR(layout, &args->ptr, "default_value", UI_ITEM_R_EXPAND, "", ICON_NONE);
-
- return block;
+ uiLayout *layout= calldata;
+ uiItemMenuF(layout, IFACE_(name), 0, node_add_menu_class, SET_INT_IN_POINTER(nclass));
}
-static void node_socket_button_components(const bContext *C, uiBlock *block,
- bNodeTree *ntree, bNode *node, bNodeSocket *sock,
- const char *name, int x, int y, int width)
+
+static void node_add_menu_default(const bContext *C, uiLayout *layout, bNodeTree *ntree)
{
- if (sock->link || (sock->flag & SOCK_HIDE_VALUE))
- node_socket_button_label(C, block, ntree, node, sock, name, x, y, width);
- else {
- PointerRNA ptr;
- SocketComponentMenuArgs *args;
-
- RNA_pointer_create(&ntree->id, &RNA_NodeSocket, sock, &ptr);
-
- args = MEM_callocN(sizeof(SocketComponentMenuArgs), "SocketComponentMenuArgs");
-
- args->ptr = ptr;
- args->x = x;
- args->y = y;
- args->width = width;
- args->cb = node_sync_cb;
- args->arg1 = CTX_wm_space_node(C);
- args->arg2 = node;
-
- uiDefBlockButN(block, socket_component_menu, args, IFACE_(name), x, y + 1, width, NODE_DY - 2, "");
- }
+ Scene *scene= CTX_data_scene(C);
+
+ if(ntree->typeinfo->foreach_nodeclass)
+ ntree->typeinfo->foreach_nodeclass(scene, layout, node_add_menu_foreach_class_cb);
}
-static void node_socket_button_color(const bContext *C, uiBlock *block,
- bNodeTree *ntree, bNode *node, bNodeSocket *sock,
- const char *name, int x, int y, int width)
+/* ****************** SOCKET BUTTON DRAW FUNCTIONS ***************** */
+
+static void node_socket_button_label(bContext *UNUSED(C), uiLayout *layout, PointerRNA *ptr, PointerRNA *UNUSED(node_ptr))
{
- if (sock->link || (sock->flag & SOCK_HIDE_VALUE))
- node_socket_button_label(C, block, ntree, node, sock, IFACE_(name), x, y, width);
- else {
- PointerRNA ptr;
- uiBut *bt;
- int labelw = width - 40;
- RNA_pointer_create(&ntree->id, &RNA_NodeSocket, sock, &ptr);
-
- bt = uiDefButR(block, COLOR, B_NODE_EXEC, "",
- x, y + 2, (labelw > 0 ? 40 : width), NODE_DY - 2,
- &ptr, "default_value", -1, 0, 0, -1, -1, NULL);
- if (node)
- uiButSetFunc(bt, node_sync_cb, CTX_wm_space_node(C), node);
-
- if (name[0] != '\0' && labelw > 0)
- uiDefBut(block, LABEL, 0, IFACE_(name), x + 40, y + 2, labelw, NODE_DY - 2, NULL, 0, 0, 0, 0, "");
- }
+ bNodeSocket *sock = (bNodeSocket *)ptr->data;
+ uiItemL(layout, sock->name, 0);
}
-/* standard draw function, display the default input value */
-static void node_draw_input_default(const bContext *C, uiBlock *block,
- bNodeTree *ntree, bNode *node, bNodeSocket *sock,
- const char *name, int x, int y, int width)
+static void node_draw_input_default(bContext *C, uiLayout *layout, PointerRNA *ptr, PointerRNA *node_ptr, int linked)
{
- bNodeSocketType *stype = ntreeGetSocketType(sock->type);
- if (stype->buttonfunc)
- stype->buttonfunc(C, block, ntree, node, sock, name, x, y, width);
+ bNodeSocket *sock = (bNodeSocket *)ptr->data;
+ if (linked || (sock->flag & SOCK_HIDE_VALUE))
+ node_socket_button_label(C, layout, ptr, node_ptr);
else
- node_socket_button_label(C, block, ntree, node, sock, IFACE_(name), x, y, width);
+ sock->typeinfo->draw(C, layout, ptr, node_ptr);
}
-static void node_draw_output_default(const bContext *UNUSED(C), uiBlock *block,
- bNodeTree *UNUSED(ntree), bNode *node, bNodeSocket *sock,
- const char *name, int UNUSED(x), int UNUSED(y), int UNUSED(width))
+static void node_draw_output_default(bContext *C, uiLayout *layout, PointerRNA *ptr, PointerRNA *node_ptr, int UNUSED(linked))
{
- const char *ui_name = IFACE_(name);
- float slen;
-
- UI_ThemeColor(TH_TEXT);
- slen = (UI_GetStringWidth(ui_name) + NODE_MARGIN_X) ;
- while (slen > NODE_WIDTH(node) && *ui_name) {
- ui_name = BLI_str_find_next_char_utf8(ui_name, NULL);
- slen = (UI_GetStringWidth(ui_name) + NODE_MARGIN_X);
- }
-
- if (*ui_name) {
- uiDefBut(block, LABEL, 0, ui_name,
- (int)(sock->locx - slen), (int)(sock->locy - 9.0f),
- (short)slen, (short)NODE_DY,
- NULL, 0, 0, 0, 0, "");
- }
+ node_socket_button_label(C, layout, ptr, node_ptr);
}
+
/* ****************** BASE DRAW FUNCTIONS FOR NEW OPERATOR NODES ***************** */
#if 0 /* UNUSED */
@@ -297,25 +250,23 @@ static void node_draw_socket_new(bNodeSocket *sock, float size)
static void node_buts_value(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
+ bNode *node = ptr->data;
+ /* first output stores value */
+ bNodeSocket *output = node->outputs.first;
PointerRNA sockptr;
- PropertyRNA *prop;
-
- /* first socket stores value */
- prop = RNA_struct_find_property(ptr, "outputs");
- RNA_property_collection_lookup_int(ptr, prop, 0, &sockptr);
+ RNA_pointer_create(ptr->id.data, &RNA_NodeSocket, output, &sockptr);
uiItemR(layout, &sockptr, "default_value", 0, "", ICON_NONE);
}
static void node_buts_rgb(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiLayout *col;
+ bNode *node = ptr->data;
+ /* first output stores value */
+ bNodeSocket *output = node->outputs.first;
PointerRNA sockptr;
- PropertyRNA *prop;
-
- /* first socket stores value */
- prop = RNA_struct_find_property(ptr, "outputs");
- RNA_property_collection_lookup_int(ptr, prop, 0, &sockptr);
+ uiLayout *col;
+ RNA_pointer_create(ptr->id.data, &RNA_NodeSocket, output, &sockptr);
col = uiLayoutColumn(layout, FALSE);
uiTemplateColorPicker(col, &sockptr, "default_value", 1, 0, 0, 0);
@@ -399,14 +350,15 @@ static void node_buts_curvecol(uiLayout *layout, bContext *UNUSED(C), PointerRNA
static void node_buts_normal(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- bNodeTree *ntree = (bNodeTree *)ptr->id.data;
- bNode *node = (bNode *)ptr->data;
- bNodeSocket *sock = node->outputs.first; /* first socket stores normal */
+ bNode *node = ptr->data;
+ /* first output stores normal */
+ bNodeSocket *output = node->outputs.first;
PointerRNA sockptr;
-
- RNA_pointer_create(&ntree->id, &RNA_NodeSocket, sock, &sockptr);
+ RNA_pointer_create(ptr->id.data, &RNA_NodeSocket, output, &sockptr);
+
uiItemR(layout, &sockptr, "default_value", 0, "", ICON_NONE);
}
+
#if 0 /* not used in 2.5x yet */
static void node_browse_tex_cb(bContext *C, void *ntree_v, void *node_v)
{
@@ -491,427 +443,6 @@ static int node_resize_area_default(bNode *node, int x, int y)
/* ****************** BUTTON CALLBACKS FOR COMMON NODES ***************** */
-/* width of socket columns in group display */
-#define NODE_GROUP_FRAME 120
-
-/* based on settings in node, sets drawing rect info. each redraw! */
-/* note: this assumes only 1 group at a time is drawn (linked data) */
-/* in node->totr the entire boundbox for the group is stored */
-static void node_update_group(const bContext *C, bNodeTree *ntree, bNode *gnode)
-{
- if (!(gnode->flag & NODE_GROUP_EDIT)) {
- node_update_default(C, ntree, gnode);
- }
- else {
- bNodeTree *ngroup = (bNodeTree *)gnode->id;
- bNode *node;
- bNodeSocket *sock, *gsock;
- float locx, locy;
- rctf *rect = &gnode->totr;
- const float dpi_fac = UI_DPI_FAC;
- const float node_group_frame = NODE_GROUP_FRAME * dpi_fac;
- const float group_header = 26 * dpi_fac;
- int counter;
- int dy;
-
- /* get "global" coords */
- node_to_view(gnode, 0.0f, 0.0f, &locx, &locy);
-
- /* center them, is a bit of abuse of locx and locy though */
- node_update_nodetree(C, ngroup, locx, locy);
-
- rect->xmin = rect->xmax = locx;
- rect->ymin = rect->ymax = locy;
-
- counter = 1;
- for (node = ngroup->nodes.first; node; node = node->next) {
- if (counter) {
- *rect = node->totr;
- counter = 0;
- }
- else
- BLI_rctf_union(rect, &node->totr);
- }
-
- /* add some room for links to group sockets */
- rect->xmin -= 4 * NODE_DY;
- rect->xmax += 4 * NODE_DY;
- rect->ymin -= NODE_DY;
- rect->ymax += NODE_DY;
-
- /* input sockets */
- dy = BLI_rctf_cent_y(rect) + (NODE_DY * (BLI_countlist(&gnode->inputs) - 1));
- gsock = ngroup->inputs.first;
- sock = gnode->inputs.first;
- while (gsock || sock) {
- while (sock && !sock->groupsock) {
- sock->locx = rect->xmin - node_group_frame;
- sock->locy = dy;
-
- /* prevent long socket lists from growing out of the group box */
- if (dy - 3 * NODE_DYS < rect->ymin)
- rect->ymin = dy - 3 * NODE_DYS;
- if (dy + 3 * NODE_DYS > rect->ymax)
- rect->ymax = dy + 3 * NODE_DYS;
- dy -= 2 * NODE_DY;
-
- sock = sock->next;
- }
- while (gsock && (!sock || sock->groupsock != gsock)) {
- gsock->locx = rect->xmin;
- gsock->locy = dy;
-
- /* prevent long socket lists from growing out of the group box */
- if (dy - 3 * NODE_DYS < rect->ymin)
- rect->ymin = dy - 3 * NODE_DYS;
- if (dy + 3 * NODE_DYS > rect->ymax)
- rect->ymax = dy + 3 * NODE_DYS;
- dy -= 2 * NODE_DY;
-
- gsock = gsock->next;
- }
- while (sock && gsock && sock->groupsock == gsock) {
- gsock->locx = rect->xmin;
- sock->locx = rect->xmin - node_group_frame;
- sock->locy = gsock->locy = dy;
-
- /* prevent long socket lists from growing out of the group box */
- if (dy - 3 * NODE_DYS < rect->ymin)
- rect->ymin = dy - 3 * NODE_DYS;
- if (dy + 3 * NODE_DYS > rect->ymax)
- rect->ymax = dy + 3 * NODE_DYS;
- dy -= 2 * NODE_DY;
-
- sock = sock->next;
- gsock = gsock->next;
- }
- }
-
- /* output sockets */
- dy = BLI_rctf_cent_y(rect) + (NODE_DY * (BLI_countlist(&gnode->outputs) - 1));
- gsock = ngroup->outputs.first;
- sock = gnode->outputs.first;
- while (gsock || sock) {
- while (sock && !sock->groupsock) {
- sock->locx = rect->xmax + node_group_frame;
- sock->locy = dy - NODE_DYS;
-
- /* prevent long socket lists from growing out of the group box */
- if (dy - 3 * NODE_DYS < rect->ymin)
- rect->ymin = dy - 3 * NODE_DYS;
- if (dy + 3 * NODE_DYS > rect->ymax)
- rect->ymax = dy + 3 * NODE_DYS;
- dy -= 2 * NODE_DY;
-
- sock = sock->next;
- }
- while (gsock && (!sock || sock->groupsock != gsock)) {
- gsock->locx = rect->xmax;
- gsock->locy = dy - NODE_DYS;
-
- /* prevent long socket lists from growing out of the group box */
- if (dy - 3 * NODE_DYS < rect->ymin)
- rect->ymin = dy - 3 * NODE_DYS;
- if (dy + 3 * NODE_DYS > rect->ymax)
- rect->ymax = dy + 3 * NODE_DYS;
- dy -= 2 * NODE_DY;
-
- gsock = gsock->next;
- }
- while (sock && gsock && sock->groupsock == gsock) {
- gsock->locx = rect->xmax;
- sock->locx = rect->xmax + node_group_frame;
- sock->locy = gsock->locy = dy - NODE_DYS;
-
- /* prevent long socket lists from growing out of the group box */
- if (dy - 3 * NODE_DYS < rect->ymin)
- rect->ymin = dy - 3 * NODE_DYS;
- if (dy + 3 * NODE_DYS > rect->ymax)
- rect->ymax = dy + 3 * NODE_DYS;
- dy -= 2 * NODE_DY;
-
- sock = sock->next;
- gsock = gsock->next;
- }
- }
-
- /* Set the block bounds to clip mouse events from underlying nodes.
- * Add margin for header and input/output columns.
- */
- uiExplicitBoundsBlock(gnode->block,
- rect->xmin - node_group_frame,
- rect->ymin,
- rect->xmax + node_group_frame,
- rect->ymax + group_header);
- }
-}
-
-static void update_group_input_cb(bContext *UNUSED(C), void *UNUSED(snode_v), void *ngroup_v)
-{
- bNodeTree *ngroup = (bNodeTree *)ngroup_v;
-
- ngroup->update |= NTREE_UPDATE_GROUP_IN;
- ntreeUpdateTree(ngroup);
-}
-
-static void update_group_output_cb(bContext *UNUSED(C), void *UNUSED(snode_v), void *ngroup_v)
-{
- bNodeTree *ngroup = (bNodeTree *)ngroup_v;
-
- ngroup->update |= NTREE_UPDATE_GROUP_OUT;
- ntreeUpdateTree(ngroup);
-}
-
-static void draw_group_socket_name(SpaceNode *snode, bNode *gnode, bNodeSocket *sock,
- int in_out, float xoffset, float yoffset, short width, short height)
-{
- if (sock->flag & SOCK_DYNAMIC) {
- bNodeTree *ngroup = (bNodeTree *)gnode->id;
- uiBut *but;
- but = uiDefBut(gnode->block, TEX, 0, "",
- sock->locx + xoffset, sock->locy + 1 + yoffset, width, height,
- sock->name, 0, sizeof(sock->name), 0, 0, "");
- if (in_out == SOCK_IN)
- uiButSetFunc(but, update_group_input_cb, snode, ngroup);
- else
- uiButSetFunc(but, update_group_output_cb, snode, ngroup);
- }
- else {
- const char *ui_name = IFACE_(sock->name);
- uiDefBut(gnode->block, LABEL, 0, ui_name,
- sock->locx + xoffset, sock->locy + 1 + yoffset, width, height,
- NULL, 0, 0, 0, 0, "");
- }
-}
-
-static void draw_group_socket(const bContext *C, SpaceNode *snode, bNodeTree *ntree, bNode *gnode,
- bNodeSocket *sock, bNodeSocket *gsock, int index, int in_out)
-{
- const float dpi_fac = UI_DPI_FAC;
- bNodeTree *ngroup = (bNodeTree *)gnode->id;
- bNodeSocketType *stype = ntreeGetSocketType(gsock ? gsock->type : sock->type);
- uiBut *bt;
- float offset;
- int draw_value;
- const float node_group_frame = NODE_GROUP_FRAME * dpi_fac;
- const float socket_size = NODE_SOCKSIZE;
- const float arrowbutw = 0.8f * UI_UNIT_X;
- const short co_text_w = 72 * dpi_fac;
- const float co_margin = 6.0f * dpi_fac;
- /* layout stuff for buttons on group left frame */
- const float colw = 0.6f * node_group_frame;
- const float col1 = co_margin - node_group_frame;
- const float col2 = col1 + colw + co_margin;
- const float col3 = -arrowbutw - co_margin;
- /* layout stuff for buttons on group right frame */
- const float cor1 = co_margin;
- const float cor2 = cor1 + arrowbutw;
- const float cor3 = cor2 + arrowbutw + co_margin;
-
- /* node and group socket circles */
- if (sock)
- node_socket_circle_draw(ntree, sock, socket_size, sock->flag & SELECT);
- if (gsock)
- node_socket_circle_draw(ngroup, gsock, socket_size, gsock->flag & SELECT);
-
- /* socket name */
- offset = (in_out == SOCK_IN ? col1 : cor3);
- if (!gsock)
- offset += (in_out == SOCK_IN ? node_group_frame : -node_group_frame);
-
- /* draw both name and value button if:
- * 1) input: not internal
- * 2) output: (node type uses const outputs) and (group output is unlinked)
- */
- draw_value = 0;
- switch (in_out) {
- case SOCK_IN:
- draw_value = !(gsock && (gsock->flag & SOCK_INTERNAL));
- break;
- case SOCK_OUT:
- if (gnode->typeinfo->flag & NODE_CONST_OUTPUT)
- draw_value = !(gsock && gsock->link);
- break;
- }
- if (draw_value) {
- /* both name and value buttons */
- if (gsock) {
- draw_group_socket_name(snode, gnode, gsock, in_out, offset, 0, co_text_w, NODE_DY);
- if (stype->buttonfunc)
- stype->buttonfunc(C, gnode->block, ngroup, NULL, gsock, "",
- gsock->locx + offset, gsock->locy - NODE_DY, colw);
- }
- else {
- draw_group_socket_name(snode, gnode, sock, in_out, offset, 0, co_text_w, NODE_DY);
- if (stype->buttonfunc)
- stype->buttonfunc(C, gnode->block, ngroup, NULL, sock, "",
- sock->locx + offset, sock->locy - NODE_DY, colw);
- }
- }
- else {
- /* only name, no value button */
- if (gsock)
- draw_group_socket_name(snode, gnode, gsock, in_out, offset, -NODE_DYS, co_text_w, NODE_DY);
- else
- draw_group_socket_name(snode, gnode, sock, in_out, offset, -NODE_DYS, co_text_w, NODE_DY);
- }
-
- if (gsock && (gsock->flag & SOCK_DYNAMIC)) {
- /* up/down buttons */
- offset = (in_out == SOCK_IN ? col2 : cor2);
- uiBlockSetDirection(gnode->block, UI_TOP);
- uiBlockBeginAlign(gnode->block);
- bt = uiDefIconButO(gnode->block, BUT, "NODE_OT_group_socket_move_up", 0, ICON_TRIA_UP,
- gsock->locx + offset, gsock->locy, arrowbutw, arrowbutw, "");
- if (!gsock->prev || !(gsock->prev->flag & SOCK_DYNAMIC))
- uiButSetFlag(bt, UI_BUT_DISABLED);
- RNA_int_set(uiButGetOperatorPtrRNA(bt), "index", index);
- RNA_enum_set(uiButGetOperatorPtrRNA(bt), "in_out", in_out);
- bt = uiDefIconButO(gnode->block, BUT, "NODE_OT_group_socket_move_down", 0, ICON_TRIA_DOWN,
- gsock->locx + offset, gsock->locy - arrowbutw, arrowbutw, arrowbutw, "");
- if (!gsock->next || !(gsock->next->flag & SOCK_DYNAMIC))
- uiButSetFlag(bt, UI_BUT_DISABLED);
- RNA_int_set(uiButGetOperatorPtrRNA(bt), "index", index);
- RNA_enum_set(uiButGetOperatorPtrRNA(bt), "in_out", in_out);
- uiBlockEndAlign(gnode->block);
- uiBlockSetDirection(gnode->block, 0);
-
- /* remove button */
- offset = (in_out == SOCK_IN ? col3 : cor1);
- uiBlockSetEmboss(gnode->block, UI_EMBOSSN);
- bt = uiDefIconButO(gnode->block, BUT, "NODE_OT_group_socket_remove", 0, ICON_X,
- gsock->locx + offset, gsock->locy - 0.5f * arrowbutw, arrowbutw, arrowbutw, "");
- RNA_int_set(uiButGetOperatorPtrRNA(bt), "index", index);
- RNA_enum_set(uiButGetOperatorPtrRNA(bt), "in_out", in_out);
- uiBlockSetEmboss(gnode->block, UI_EMBOSS);
- }
-}
-
-/* groups are, on creation, centered around 0,0 */
-static void node_draw_group(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *gnode)
-{
- if (!(gnode->flag & NODE_GROUP_EDIT)) {
- node_draw_default(C, ar, snode, ntree, gnode);
- }
- else {
- bNodeTree *ngroup = (bNodeTree *)gnode->id;
- bNodeSocket *sock, *gsock;
- uiLayout *layout;
- PointerRNA ptr;
- rctf rect = gnode->totr;
- const float dpi_fac = UI_DPI_FAC;
- const float node_group_frame = NODE_GROUP_FRAME * dpi_fac;
- const float group_header = 26 * dpi_fac;
-
- int index;
-
- /* backdrop header */
- glEnable(GL_BLEND);
- uiSetRoundBox(UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT);
- UI_ThemeColorShadeAlpha(TH_NODE_GROUP, 0, -70);
- uiDrawBox(GL_POLYGON,
- rect.xmin - node_group_frame, rect.ymax,
- rect.xmax + node_group_frame, rect.ymax + group_header, BASIS_RAD);
-
- /* backdrop body */
- UI_ThemeColorShadeAlpha(TH_BACK, -8, -70);
- uiSetRoundBox(UI_CNR_NONE);
- uiDrawBox(GL_POLYGON, rect.xmin, rect.ymin, rect.xmax, rect.ymax, BASIS_RAD);
-
- /* input column */
- UI_ThemeColorShadeAlpha(TH_BACK, 10, -50);
- uiSetRoundBox(UI_CNR_BOTTOM_LEFT);
- uiDrawBox(GL_POLYGON, rect.xmin - node_group_frame, rect.ymin, rect.xmin, rect.ymax, BASIS_RAD);
-
- /* output column */
- UI_ThemeColorShadeAlpha(TH_BACK, 10, -50);
- uiSetRoundBox(UI_CNR_BOTTOM_RIGHT);
- uiDrawBox(GL_POLYGON, rect.xmax, rect.ymin, rect.xmax + node_group_frame, rect.ymax, BASIS_RAD);
-
- /* input column separator */
- glColor4ub(200, 200, 200, 140);
- glBegin(GL_LINES);
- glVertex2f(rect.xmin, rect.ymin);
- glVertex2f(rect.xmin, rect.ymax);
- glEnd();
-
- /* output column separator */
- glColor4ub(200, 200, 200, 140);
- glBegin(GL_LINES);
- glVertex2f(rect.xmax, rect.ymin);
- glVertex2f(rect.xmax, rect.ymax);
- glEnd();
-
- /* group node outline */
- uiSetRoundBox(UI_CNR_ALL);
- glColor4ub(200, 200, 200, 140);
- glEnable(GL_LINE_SMOOTH);
- uiDrawBox(GL_LINE_LOOP,
- rect.xmin - node_group_frame, rect.ymin,
- rect.xmax + node_group_frame, rect.ymax + group_header, BASIS_RAD);
- glDisable(GL_LINE_SMOOTH);
- glDisable(GL_BLEND);
-
- /* backdrop title */
- UI_ThemeColor(TH_TEXT_HI);
-
- layout = uiBlockLayout(gnode->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL,
- (int)(rect.xmin + NODE_MARGIN_X), (int)(rect.ymax + (group_header - (2.5f * dpi_fac))),
- min_ii((int)(BLI_rctf_size_x(&rect) - 18.0f), node_group_frame + 20), group_header, UI_GetStyle());
- RNA_pointer_create(&ntree->id, &RNA_Node, gnode, &ptr);
- uiTemplateIDBrowse(layout, (bContext *)C, &ptr, "node_tree", NULL, NULL, NULL);
- uiBlockLayoutResolve(gnode->block, NULL, NULL);
-
- /* draw the internal tree nodes and links */
- node_draw_nodetree(C, ar, snode, ngroup);
-
- /* group sockets */
- gsock = ngroup->inputs.first;
- sock = gnode->inputs.first;
- index = 0;
- while (gsock || sock) {
- while (sock && !sock->groupsock) {
- draw_group_socket(C, snode, ntree, gnode, sock, NULL, index, SOCK_IN);
- sock = sock->next;
- }
- while (gsock && (!sock || sock->groupsock != gsock)) {
- draw_group_socket(C, snode, ntree, gnode, NULL, gsock, index, SOCK_IN);
- gsock = gsock->next;
- index++;
- }
- while (sock && gsock && sock->groupsock == gsock) {
- draw_group_socket(C, snode, ntree, gnode, sock, gsock, index, SOCK_IN);
- sock = sock->next;
- gsock = gsock->next;
- index++;
- }
- }
- gsock = ngroup->outputs.first;
- sock = gnode->outputs.first;
- index = 0;
- while (gsock || sock) {
- while (sock && !sock->groupsock) {
- draw_group_socket(C, snode, ntree, gnode, sock, NULL, index, SOCK_OUT);
- sock = sock->next;
- }
- while (gsock && (!sock || sock->groupsock != gsock)) {
- draw_group_socket(C, snode, ntree, gnode, NULL, gsock, index, SOCK_OUT);
- gsock = gsock->next;
- index++;
- }
- while (sock && gsock && sock->groupsock == gsock) {
- draw_group_socket(C, snode, ntree, gnode, sock, gsock, index, SOCK_OUT);
- sock = sock->next;
- gsock = gsock->next;
- index++;
- }
- }
-
- uiEndBlock(C, gnode->block);
- uiDrawBlock(C, gnode->block);
- gnode->block = NULL;
- }
-}
static void node_uifunc_group(uiLayout *layout, bContext *C, PointerRNA *ptr)
{
@@ -1003,7 +534,8 @@ static void node_draw_frame_label(bNode *node, const float aspect)
BLF_disable(fontid, BLF_ASPECT);
}
-static void node_draw_frame(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *UNUSED(ntree), bNode *node)
+static void node_draw_frame(const bContext *C, ARegion *ar, SpaceNode *snode,
+ bNodeTree *UNUSED(ntree), bNode *node, bNodeInstanceKey UNUSED(key))
{
rctf *rct = &node->totr;
int color_id = node_get_colorid(node);
@@ -1118,7 +650,8 @@ static void node_update_reroute(const bContext *UNUSED(C), bNodeTree *UNUSED(ntr
node->totr.ymin = locy - size;
}
-static void node_draw_reroute(const bContext *C, ARegion *ar, SpaceNode *UNUSED(snode), bNodeTree *ntree, bNode *node)
+static void node_draw_reroute(const bContext *C, ARegion *ar, SpaceNode *UNUSED(snode),
+ bNodeTree *ntree, bNode *node, bNodeInstanceKey UNUSED(key))
{
bNodeSocket *sock;
char showname[128]; /* 128 used below */
@@ -1178,7 +711,7 @@ static void node_draw_reroute(const bContext *C, ARegion *ar, SpaceNode *UNUSED(
* highlight also if node itself is selected, since we don't display the node body separately!
*/
for (sock = node->inputs.first; sock; sock = sock->next) {
- node_socket_circle_draw(ntree, sock, socket_size, (sock->flag & SELECT) || (node->flag & SELECT));
+ node_socket_circle_draw(C, ntree, node, sock, socket_size, (sock->flag & SELECT) || (node->flag & SELECT));
}
uiEndBlock(C, node->block);
@@ -1205,8 +738,6 @@ static void node_common_set_butfunc(bNodeType *ntype)
switch (ntype->type) {
case NODE_GROUP:
ntype->uifunc = node_uifunc_group;
- ntype->drawfunc = node_draw_group;
- ntype->drawupdatefunc = node_update_group;
break;
case NODE_FRAME:
ntype->drawfunc = node_draw_frame;
@@ -1491,8 +1022,6 @@ static void node_shader_buts_script_details(uiLayout *layout, bContext *C, Point
static void node_shader_set_butfunc(bNodeType *ntype)
{
switch (ntype->type) {
- /* case NODE_GROUP: note, typeinfo for group is generated... see "XXX ugly hack" */
-
case SH_NODE_MATERIAL:
case SH_NODE_MATERIAL_EXT:
ntype->uifunc = node_shader_buts_material;
@@ -2092,20 +1621,17 @@ static void node_composit_buts_id_mask(uiLayout *layout, bContext *UNUSED(C), Po
}
/* draw function for file output node sockets, displays only sub-path and format, no value button */
-static void node_draw_input_file_output(const bContext *C, uiBlock *block,
- bNodeTree *ntree, bNode *node, bNodeSocket *sock,
- const char *UNUSED(name), int x, int y, int width)
+static void node_draw_input_file_output(bContext *C, uiLayout *layout, PointerRNA *ptr, PointerRNA *node_ptr, int UNUSED(linked))
{
- uiLayout *layout, *row;
- PointerRNA nodeptr, inputptr, imfptr;
+ bNodeTree *ntree = ptr->id.data;
+ bNodeSocket *sock = ptr->data;
+ uiLayout *row;
+ PointerRNA inputptr, imfptr;
int imtype;
- int rx, ry;
- RNA_pointer_create(&ntree->id, &RNA_Node, node, &nodeptr);
- layout = uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, x, y + NODE_DY, width, 20, UI_GetStyle());
row = uiLayoutRow(layout, FALSE);
- imfptr = RNA_pointer_get(&nodeptr, "format");
+ imfptr = RNA_pointer_get(node_ptr, "format");
imtype = RNA_enum_get(&imfptr, "file_format");
if (imtype == R_IMF_IMTYPE_MULTILAYER) {
NodeImageMultiFileSocket *input = sock->storage;
@@ -2117,6 +1643,7 @@ static void node_draw_input_file_output(const bContext *C, uiBlock *block,
NodeImageMultiFileSocket *input = sock->storage;
PropertyRNA *imtype_prop;
const char *imtype_name;
+ uiBlock *block;
RNA_pointer_create(&ntree->id, &RNA_NodeOutputFileSlotFile, input, &inputptr);
uiItemL(row, input->path, ICON_NONE);
@@ -2127,12 +1654,11 @@ static void node_draw_input_file_output(const bContext *C, uiBlock *block,
imtype_prop = RNA_struct_find_property(&imfptr, "file_format");
RNA_property_enum_name((bContext *)C, &imfptr, imtype_prop,
RNA_property_enum_get(&imfptr, imtype_prop), &imtype_name);
+ block = uiLayoutGetBlock(row);
uiBlockSetEmboss(block, UI_EMBOSSP);
uiItemL(row, imtype_name, ICON_NONE);
uiBlockSetEmboss(block, UI_EMBOSSN);
}
-
- uiBlockLayoutResolve(block, &rx, &ry);
}
static void node_composit_buts_file_output(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
@@ -2781,8 +2307,6 @@ static void node_composit_buts_trackpos(uiLayout *layout, bContext *C, PointerRN
static void node_composit_set_butfunc(bNodeType *ntype)
{
switch (ntype->type) {
- /* case NODE_GROUP: note, typeinfo for group is generated... see "XXX ugly hack" */
-
case CMP_NODE_IMAGE:
ntype->uifunc = node_composit_buts_image;
ntype->uifuncbut = node_composit_buts_image_details;
@@ -2998,8 +2522,6 @@ static void node_composit_set_butfunc(bNodeType *ntype)
case CMP_NODE_TRACKPOS:
ntype->uifunc = node_composit_buts_trackpos;
break;
- default:
- ntype->uifunc = NULL;
}
}
@@ -3158,81 +2680,170 @@ static void node_texture_set_butfunc(bNodeType *ntype)
/* ******* init draw callbacks for all tree types, only called in usiblender.c, once ************* */
-void ED_node_init_butfuncs(void)
+static void node_property_update_default(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
- bNodeTreeType *treetype;
- bNodeType *ntype;
- bNodeSocketType *stype;
- int i;
+ bNodeTree *ntree = ptr->id.data;
+ ED_node_tag_update_nodetree(bmain, ntree);
+}
+
+static void node_socket_template_properties_update(bNodeType *ntype, bNodeSocketTemplate *stemp)
+{
+ StructRNA *srna = ntype->ext.srna;
+ PropertyRNA *prop = RNA_struct_type_find_property(srna, stemp->identifier);
- /* node type ui functions */
- for (i = 0; i < NUM_NTREE_TYPES; ++i) {
- treetype = ntreeGetType(i);
- if (treetype) {
- for (ntype = treetype->node_types.first; ntype; ntype = ntype->next) {
- /* default ui functions */
- ntype->drawfunc = node_draw_default;
- ntype->drawupdatefunc = node_update_default;
- ntype->select_area_func = node_select_area_default;
- ntype->tweak_area_func = node_tweak_area_default;
- ntype->uifunc = NULL;
- ntype->uifuncbut = NULL;
- ntype->drawinputfunc = node_draw_input_default;
- ntype->drawoutputfunc = node_draw_output_default;
- ntype->resize_area_func = node_resize_area_default;
-
- node_common_set_butfunc(ntype);
-
- switch (i) {
- case NTREE_COMPOSIT:
- node_composit_set_butfunc(ntype);
- break;
- case NTREE_SHADER:
- node_shader_set_butfunc(ntype);
- break;
- case NTREE_TEXTURE:
- node_texture_set_butfunc(ntype);
- break;
- }
- }
- }
+ if (prop)
+ RNA_def_property_update_runtime(prop, node_property_update_default);
+}
+
+static void node_template_properties_update(bNodeType *ntype)
+{
+ bNodeSocketTemplate *stemp;
+
+ if (ntype->inputs) {
+ for (stemp = ntype->inputs; stemp->type >= 0; ++stemp)
+ node_socket_template_properties_update(ntype, stemp);
}
+ if (ntype->outputs) {
+ for (stemp = ntype->outputs; stemp->type >= 0; ++stemp)
+ node_socket_template_properties_update(ntype, stemp);
+ }
+}
+
+void ED_node_init_butfuncs(void)
+{
+ /* node type ui functions */
+ NODE_TYPES_BEGIN(ntype)
+ /* default ui functions */
+ ntype->drawfunc = node_draw_default;
+ ntype->drawupdatefunc = node_update_default;
+ ntype->select_area_func = node_select_area_default;
+ ntype->tweak_area_func = node_tweak_area_default;
+ ntype->uifunc = NULL;
+ ntype->uifuncbut = NULL;
+ ntype->drawinputfunc = node_draw_input_default;
+ ntype->drawoutputfunc = node_draw_output_default;
+ ntype->resize_area_func = node_resize_area_default;
+
+ node_common_set_butfunc(ntype);
+
+ node_composit_set_butfunc(ntype);
+ node_shader_set_butfunc(ntype);
+ node_texture_set_butfunc(ntype);
+
+ /* define update callbacks for socket properties */
+ node_template_properties_update(ntype);
+ NODE_TYPES_END
- /* socket type ui functions */
- for (i = 0; i < NUM_SOCKET_TYPES; ++i) {
- stype = ntreeGetSocketType(i);
- if (stype) {
- switch (stype->type) {
- case SOCK_FLOAT:
- case SOCK_INT:
- case SOCK_BOOLEAN:
- stype->buttonfunc = node_socket_button_default;
- break;
- case SOCK_STRING:
- stype->buttonfunc = node_socket_button_string;
- break;
- case SOCK_VECTOR:
- stype->buttonfunc = node_socket_button_components;
- break;
- case SOCK_RGBA:
- stype->buttonfunc = node_socket_button_color;
- break;
- case SOCK_SHADER:
- stype->buttonfunc = node_socket_button_label;
- break;
- default:
- stype->buttonfunc = NULL;
- }
+ /* tree type icons */
+ ntreeType_Composite->ui_icon = ICON_RENDERLAYERS;
+ ntreeType_Composite->draw_add_menu = node_add_menu_default;
+ ntreeType_Shader->ui_icon = ICON_MATERIAL;
+ ntreeType_Shader->draw_add_menu = node_add_menu_default;
+ ntreeType_Texture->ui_icon = ICON_TEXTURE;
+ ntreeType_Texture->draw_add_menu = node_add_menu_default;
+}
+
+void ED_init_custom_node_type(bNodeType *ntype)
+{
+ /* default ui functions */
+ ntype->drawfunc = node_draw_default;
+ ntype->drawupdatefunc = node_update_default;
+ ntype->drawinputfunc = node_draw_input_default;
+ ntype->drawoutputfunc = node_draw_output_default;
+ ntype->resize_area_func = node_resize_area_default;
+ ntype->select_area_func = node_select_area_default;
+ ntype->tweak_area_func = node_tweak_area_default;
+}
+
+void ED_init_custom_node_socket_type(bNodeSocketType *stype)
+{
+ /* default ui functions */
+ stype->draw = node_socket_button_label;
+}
+
+/* maps standard socket integer type to a color */
+static const float std_node_socket_colors[][4] = {
+ {0.63, 0.63, 0.63, 1.0}, /* SOCK_FLOAT */
+ {0.39, 0.39, 0.78, 1.0}, /* SOCK_VECTOR */
+ {0.78, 0.78, 0.16, 1.0}, /* SOCK_RGBA */
+ {0.39, 0.78, 0.39, 1.0}, /* SOCK_SHADER */
+ {0.70, 0.65, 0.19, 1.0}, /* SOCK_BOOLEAN */
+ {0.0, 0.0, 0.0, 1.0}, /*__SOCK_MESH (deprecated) */
+ {0.06, 0.52, 0.15, 1.0}, /* SOCK_INT */
+ {1.0, 1.0, 1.0, 1.0}, /* SOCK_STRING */
+};
+
+/* common color callbacks for standard types */
+static void std_node_socket_draw_color(bContext *UNUSED(C), PointerRNA *ptr, PointerRNA *UNUSED(node_ptr), float *r_color)
+{
+ bNodeSocket *sock = ptr->data;
+ int type = sock->typeinfo->type;
+ copy_v4_v4(r_color, std_node_socket_colors[type]);
+}
+static void std_node_socket_interface_draw_color(bContext *UNUSED(C), PointerRNA *ptr, float *r_color)
+{
+ bNodeSocket *sock = ptr->data;
+ int type = sock->typeinfo->type;
+ copy_v4_v4(r_color, std_node_socket_colors[type]);
+}
+
+static void std_node_socket_draw(bContext *UNUSED(C), uiLayout *layout, PointerRNA *ptr, PointerRNA *UNUSED(node_ptr))
+{
+ bNodeSocket *sock = ptr->data;
+ int type = sock->typeinfo->type;
+ /*int subtype = sock->typeinfo->subtype;*/
+
+ switch (type) {
+ case SOCK_FLOAT:
+ case SOCK_INT:
+ case SOCK_BOOLEAN:
+ uiItemR(layout, ptr, "default_value", 0, sock->name, 0);
+ break;
+ case SOCK_VECTOR:
+ uiTemplateComponentMenu(layout, ptr, "default_value", sock->name);
+ break;
+ case SOCK_RGBA: {
+ uiLayout *row = uiLayoutRow(layout, false);
+ uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_LEFT);
+ /* draw the socket name right of the actual button */
+ uiItemR(row, ptr, "default_value", 0, "", 0);
+ uiItemL(row, sock->name, 0);
+ break;
+ }
+ case SOCK_STRING: {
+ uiLayout *row = uiLayoutRow(layout, true);
+ /* draw the socket name right of the actual button */
+ uiItemR(row, ptr, "default_value", 0, "", 0);
+ uiItemL(row, sock->name, 0);
+ break;
}
}
}
+void ED_init_standard_node_socket_type(bNodeSocketType *stype)
+{
+ stype->draw = std_node_socket_draw;
+ stype->draw_color = std_node_socket_draw_color;
+ stype->interface_draw_color = std_node_socket_interface_draw_color;
+}
+
+static void node_socket_virtual_draw_color(bContext *UNUSED(C), PointerRNA *UNUSED(ptr), PointerRNA *UNUSED(node_ptr), float *r_color)
+{
+ /* alpha = 0, empty circle */
+ zero_v4(r_color);
+}
+
+void ED_init_node_socket_type_virtual(bNodeSocketType *stype)
+{
+ stype->draw = node_socket_button_label;
+ stype->draw_color = node_socket_virtual_draw_color;
+}
+
/* ************** Generic drawing ************** */
void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode)
{
-
- if ((snode->flag & SNODE_BACKDRAW) && snode->treetype == NTREE_COMPOSIT) {
+ if ((snode->flag & SNODE_BACKDRAW) && ED_node_is_compositor(snode)) {
Image *ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
void *lock;
ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
@@ -3640,18 +3251,13 @@ void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link)
do_triple = TRUE;
}
else {
- int cycle = 0;
-
/* going to give issues once... */
if (link->tosock->flag & SOCK_UNAVAIL)
return;
if (link->fromsock->flag & SOCK_UNAVAIL)
return;
- /* check cyclic */
- if (link->fromnode && link->tonode)
- cycle = (link->fromnode->level < link->tonode->level || link->tonode->level == 0xFFF);
- if (!cycle && (link->flag & NODE_LINK_VALID)) {
+ if (link->flag & NODE_LINK_VALID) {
/* special indicated link, on drop-node */
if (link->flag & NODE_LINKFLAG_HILITE) {
th_col1 = th_col2 = TH_ACTIVE;
diff --git a/source/blender/editors/space_node/node_add.c b/source/blender/editors/space_node/node_add.c
index 235d91ecd92..cd04957c0a5 100644
--- a/source/blender/editors/space_node/node_add.c
+++ b/source/blender/editors/space_node/node_add.c
@@ -62,62 +62,60 @@
#include "node_intern.h" /* own include */
-/* can be called from menus too, but they should do own undopush and redraws */
-bNode *node_add_node(SpaceNode *snode, Main *bmain, Scene *scene,
- bNodeTemplate *ntemp, float locx, float locy)
+/* XXX Does some additional initialization on top of nodeAddNode
+ * Can be used with both custom and static nodes, if idname==NULL the static int type will be used instead.
+ * Can be called from menus too, but they should do own undopush and redraws.
+ */
+bNode *node_add_node(const bContext *C, const char *idname, int type, float locx, float locy)
{
- bNode *node = NULL, *gnode;
-
+ SpaceNode *snode = CTX_wm_space_node(C);
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ bNode *node = NULL;
+
node_deselect_all(snode);
-
- node = nodeAddNode(snode->edittree, ntemp);
-
+
+ if (idname)
+ node = nodeAddNode(C, snode->edittree, idname);
+ else
+ node = nodeAddStaticNode(C, snode->edittree, type);
+ BLI_assert(node && node->typeinfo);
+
/* generics */
- if (node) {
- node_select(node);
-
- /* node location is mapped */
- locx /= UI_DPI_FAC;
- locy /= UI_DPI_FAC;
-
- gnode = node_tree_get_editgroup(snode->nodetree);
- // arbitrary y offset of 60 so its visible
- if (gnode) {
- node_from_view(gnode, locx, locy + 60.0f, &node->locx, &node->locy);
- }
- else {
- node->locx = locx;
- node->locy = locy + 60.0f;
+ node->locx = locx;
+ node->locy = locy + 60.0f; // arbitrary.. so its visible, (0,0) is top of node
+ nodeSetSelected(node, TRUE);
+
+ /* node location is mapped */
+ locx /= UI_DPI_FAC;
+ locy /= UI_DPI_FAC;
+
+ node->locx = locx;
+ node->locy = locy + 60.0f;
+
+ ntreeUpdateTree(snode->edittree);
+ ED_node_set_active(bmain, snode->edittree, node);
+
+ if (snode->nodetree->type == NTREE_COMPOSIT) {
+ if (ELEM4(node->type, CMP_NODE_R_LAYERS, CMP_NODE_COMPOSITE, CMP_NODE_DEFOCUS, CMP_NODE_OUTPUT_FILE)) {
+ node->id = &scene->id;
}
-
- ntreeUpdateTree(snode->edittree);
- ED_node_set_active(bmain, snode->edittree, node);
-
- if (snode->nodetree->type == NTREE_COMPOSIT) {
- if (ELEM4(node->type, CMP_NODE_R_LAYERS, CMP_NODE_COMPOSITE, CMP_NODE_DEFOCUS, CMP_NODE_OUTPUT_FILE)) {
- node->id = &scene->id;
- }
- else if (ELEM3(node->type, CMP_NODE_MOVIECLIP, CMP_NODE_MOVIEDISTORTION, CMP_NODE_STABILIZE2D)) {
- node->id = (ID *)scene->clip;
- }
-
- ntreeCompositForceHidden(snode->edittree, scene);
+ else if (ELEM3(node->type, CMP_NODE_MOVIECLIP, CMP_NODE_MOVIEDISTORTION, CMP_NODE_STABILIZE2D)) {
+ node->id = (ID *)scene->clip;
}
-
- if (node->id)
- id_us_plus(node->id);
-
-
- if (snode->flag & SNODE_USE_HIDDEN_PREVIEW)
- node->flag &= ~NODE_PREVIEW;
-
- snode_update(snode, node);
+
+ ntreeCompositForceHidden(snode->edittree, scene);
}
-
+
+ if (node->id)
+ id_us_plus(node->id);
+
+ snode_update(snode, node);
+
if (snode->nodetree->type == NTREE_TEXTURE) {
ntreeTexCheckCyclics(snode->edittree);
}
-
+
return node;
}
@@ -183,9 +181,7 @@ static bNodeSocketLink *add_reroute_do_socket_section(bContext *C, bNodeSocketLi
/* create the reroute node for this cursock */
if (!reroute_node) {
- bNodeTemplate ntemp;
- ntemp.type = NODE_REROUTE;
- reroute_node = nodeAddNode(ntree, &ntemp);
+ reroute_node = nodeAddStaticNode(C, ntree, NODE_REROUTE);
/* add a single link to/from the reroute node to replace multiple links */
if (in_out == SOCK_OUT) {
@@ -213,18 +209,11 @@ static bNodeSocketLink *add_reroute_do_socket_section(bContext *C, bNodeSocketLi
}
if (num_links > 0) {
- bNode *gnode = node_tree_get_editgroup(snode->nodetree);
-
/* average cut point from shared links */
mul_v2_fl(insert_point, 1.0f / num_links);
- if (gnode) {
- node_from_view(gnode, insert_point[0], insert_point[1], &reroute_node->locx, &reroute_node->locy);
- }
- else {
- reroute_node->locx = insert_point[0];
- reroute_node->locy = insert_point[1];
- }
+ reroute_node->locx = insert_point[0];
+ reroute_node->locy = insert_point[1];
}
return socklink;
@@ -266,6 +255,8 @@ static int add_reroute_exec(bContext *C, wmOperator *op)
output_links.first = output_links.last = NULL;
input_links.first = input_links.last = NULL;
for (link = ntree->links.first; link; link = link->next) {
+ if (nodeLinkIsHidden(link))
+ continue;
if (add_reroute_intersect_check(link, mcoords, i, insert_point)) {
add_reroute_insert_socket_link(&output_links, link->fromsock, link, insert_point);
add_reroute_insert_socket_link(&input_links, link->tosock, link, insert_point);
@@ -330,12 +321,10 @@ void NODE_OT_add_reroute(wmOperatorType *ot)
static int node_add_file_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
SpaceNode *snode = CTX_wm_space_node(C);
bNode *node;
Image *ima = NULL;
- bNodeTemplate ntemp;
+ int type= 0;
/* check input variables */
if (RNA_struct_property_is_set(op->ptr, "filepath")) {
@@ -367,36 +356,35 @@ static int node_add_file_exec(bContext *C, wmOperator *op)
switch (snode->nodetree->type) {
case NTREE_SHADER:
- ntemp.type = SH_NODE_TEX_IMAGE;
+ type = SH_NODE_TEX_IMAGE;
break;
case NTREE_TEXTURE:
- ntemp.type = TEX_NODE_IMAGE;
+ type = TEX_NODE_IMAGE;
break;
case NTREE_COMPOSIT:
- ntemp.type = CMP_NODE_IMAGE;
+ type = CMP_NODE_IMAGE;
break;
default:
return OPERATOR_CANCELLED;
}
-
+
ED_preview_kill_jobs(C);
-
- node = node_add_node(snode, bmain, scene, &ntemp, snode->cursor[0], snode->cursor[1]);
-
+
+ node = node_add_node(C, NULL, type, snode->cursor[0], snode->cursor[1]);
+
if (!node) {
BKE_report(op->reports, RPT_WARNING, "Could not add an image node");
return OPERATOR_CANCELLED;
}
-
+
node->id = (ID *)ima;
- id_us_plus(node->id);
-
+
BKE_image_signal(ima, NULL, IMA_SIGNAL_RELOAD);
WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima);
snode_notify(C, snode);
snode_dag_update(C, snode);
-
+
return OPERATOR_FINISHED;
}
@@ -404,11 +392,11 @@ static int node_add_file_invoke(bContext *C, wmOperator *op, const wmEvent *even
{
ARegion *ar = CTX_wm_region(C);
SpaceNode *snode = CTX_wm_space_node(C);
-
+
/* convert mouse coordinates to v2d space */
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1],
&snode->cursor[0], &snode->cursor[1]);
-
+
if (RNA_struct_property_is_set(op->ptr, "filepath") || RNA_struct_property_is_set(op->ptr, "name"))
return node_add_file_exec(C, op);
else
@@ -435,35 +423,35 @@ void NODE_OT_add_file(wmOperatorType *ot)
RNA_def_string(ot->srna, "name", "Image", MAX_ID_NAME - 2, "Name", "Datablock name to assign");
}
-
/********************** New node tree operator *********************/
static int new_node_tree_exec(bContext *C, wmOperator *op)
{
- SpaceNode *snode;
+ SpaceNode *snode= CTX_wm_space_node(C);
+ Main *bmain = CTX_data_main(C);
bNodeTree *ntree;
- Main *bmain;
PointerRNA ptr, idptr;
PropertyRNA *prop;
- int treetype;
+ const char *idname;
char treename[MAX_ID_NAME - 2] = "NodeTree";
-
- /* retrieve state */
- snode = CTX_wm_space_node(C);
- bmain = CTX_data_main(C);
-
- if (RNA_struct_property_is_set(op->ptr, "type"))
- treetype = RNA_enum_get(op->ptr, "type");
- else
- treetype = snode->treetype;
-
+
+ if (RNA_struct_property_is_set(op->ptr, "type")) {
+ prop = RNA_struct_find_property(op->ptr, "type");
+ RNA_property_enum_identifier(C, op->ptr, prop, RNA_property_enum_get(op->ptr, prop), &idname);
+ }
+ else if (snode)
+ idname = snode->tree_idname;
+
if (RNA_struct_property_is_set(op->ptr, "name"))
RNA_string_get(op->ptr, "name", treename);
-
- ntree = ntreeAddTree(bmain, treename, treetype, 0);
- if (!ntree)
+
+ if (!ntreeTypeFind(idname)) {
+ BKE_reportf(op->reports, RPT_ERROR, "Node tree type %s undefined", idname);
return OPERATOR_CANCELLED;
-
+ }
+
+ ntree = ntreeAddTree(bmain, treename, idname);
+
/* hook into UI */
uiIDContextProperty(C, &ptr, &prop);
@@ -477,29 +465,36 @@ static int new_node_tree_exec(bContext *C, wmOperator *op)
RNA_property_update(C, &ptr, prop);
}
else if (snode) {
- Scene *scene = CTX_data_scene(C);
snode->nodetree = ntree;
-
- ED_node_tree_update(snode, scene);
+
+ ED_node_tree_update(C);
}
-
+
return OPERATOR_FINISHED;
}
+static EnumPropertyItem *new_node_tree_type_itemf(bContext *UNUSED(C), PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), int *free)
+{
+ return rna_node_tree_type_itemf(NULL, NULL, free);
+}
+
void NODE_OT_new_node_tree(wmOperatorType *ot)
{
+ PropertyRNA *prop;
+
/* identifiers */
ot->name = "New Node Tree";
ot->idname = "NODE_OT_new_node_tree";
ot->description = "Create a new node tree";
-
+
/* api callbacks */
ot->exec = new_node_tree_exec;
- ot->poll = ED_operator_node_active;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_enum(ot->srna, "type", nodetree_type_items, NTREE_COMPOSIT, "Tree Type", "");
+
+ prop = RNA_def_enum(ot->srna, "type", DummyRNA_NULL_items, 0, "Tree Type", "");
+ RNA_def_enum_funcs(prop, new_node_tree_type_itemf);
RNA_def_string(ot->srna, "name", "NodeTree", MAX_ID_NAME - 2, "Name", "");
}
+
diff --git a/source/blender/editors/space_node/node_buttons.c b/source/blender/editors/space_node/node_buttons.c
index 300328f5fd4..30cc3b93e8a 100644
--- a/source/blender/editors/space_node/node_buttons.c
+++ b/source/blender/editors/space_node/node_buttons.c
@@ -62,7 +62,7 @@ static int active_nodetree_poll(const bContext *C, PanelType *UNUSED(pt))
{
SpaceNode *snode = CTX_wm_space_node(C);
- return (snode && snode->nodetree);
+ return (snode && ntreeIsValid(snode->nodetree));
}
/* poll callback for active node */
@@ -70,7 +70,7 @@ static int active_node_poll(const bContext *C, PanelType *UNUSED(pt))
{
SpaceNode *snode = CTX_wm_space_node(C);
- return (snode && snode->edittree && nodeGetActive(snode->edittree));
+ return (snode && ntreeIsValid(snode->edittree) && nodeGetActive(snode->edittree));
}
/* active node */
@@ -160,6 +160,86 @@ static void node_sockets_panel(const bContext *C, Panel *pa)
}
}
+static int node_tree_interface_poll(const bContext *C, PanelType *UNUSED(pt))
+{
+ SpaceNode *snode= CTX_wm_space_node(C);
+
+ return (snode && snode->edittree && (snode->edittree->inputs.first || snode->edittree->outputs.first));
+}
+
+static int node_tree_find_active_socket(bNodeTree *ntree, bNodeSocket **r_sock, int *r_in_out)
+{
+ bNodeSocket *sock;
+ for (sock = ntree->inputs.first; sock; sock = sock->next) {
+ if (sock->flag & SELECT) {
+ *r_sock = sock;
+ *r_in_out = SOCK_IN;
+ return TRUE;
+ }
+ }
+ for (sock = ntree->outputs.first; sock; sock = sock->next) {
+ if (sock->flag & SELECT) {
+ *r_sock = sock;
+ *r_in_out = SOCK_OUT;
+ return TRUE;
+ }
+ }
+
+ *r_sock = NULL;
+ *r_in_out = 0;
+ return FALSE;
+}
+
+static void node_tree_interface_panel(const bContext *C, Panel *pa)
+{
+ SpaceNode *snode= CTX_wm_space_node(C);
+ bNodeTree *ntree= (snode) ? snode->edittree : NULL;
+ bNodeSocket *sock;
+ int in_out;
+ uiLayout *layout= pa->layout, *row, *split, *col;
+ PointerRNA ptr, sockptr, opptr;
+
+ if(!ntree)
+ return;
+
+ RNA_id_pointer_create((ID *)ntree, &ptr);
+
+ node_tree_find_active_socket(ntree, &sock, &in_out);
+ RNA_pointer_create((ID *)ntree, &RNA_NodeSocketInterface, sock, &sockptr);
+
+ row = uiLayoutRow(layout, FALSE);
+
+ split = uiLayoutRow(row, TRUE);
+ col = uiLayoutColumn(split, TRUE);
+ uiItemL(col, "Inputs:", ICON_NONE);
+ uiTemplateList(col, (bContext*)C, "NODE_UL_interface_sockets", "", &ptr, "inputs", &ptr, "active_input", 0, 0, 0);
+ opptr = uiItemFullO(col, "NODE_OT_tree_socket_add", "", ICON_PLUS, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
+ RNA_enum_set(&opptr, "in_out", SOCK_IN);
+
+ col = uiLayoutColumn(split, TRUE);
+ uiItemL(col, "Outputs:", ICON_NONE);
+ uiTemplateList(col, (bContext*)C, "NODE_UL_interface_sockets", "", &ptr, "outputs", &ptr, "active_output", 0, 0, 0);
+ opptr = uiItemFullO(col, "NODE_OT_tree_socket_add", "", ICON_PLUS, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
+ RNA_enum_set(&opptr, "in_out", SOCK_OUT);
+
+ col = uiLayoutColumn(row, TRUE);
+ opptr = uiItemFullO(col, "NODE_OT_tree_socket_move", "", ICON_TRIA_UP, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
+ RNA_enum_set(&opptr, "direction", 1);
+ opptr = uiItemFullO(col, "NODE_OT_tree_socket_move", "", ICON_TRIA_DOWN, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
+ RNA_enum_set(&opptr, "direction", 2);
+
+ if (sock) {
+ row = uiLayoutRow(layout, TRUE);
+ uiItemR(row, &sockptr, "name", 0, NULL, ICON_NONE);
+ uiItemO(row, "", ICON_X, "NODE_OT_tree_socket_remove");
+
+ uiItemS(layout);
+
+ if (sock->typeinfo->interface_draw)
+ sock->typeinfo->interface_draw((bContext*)C, layout, &sockptr);
+ }
+}
+
/* ******************* node buttons registration ************** */
void node_buttons_register(ARegionType *art)
@@ -180,7 +260,14 @@ void node_buttons_register(ARegionType *art)
pt->poll = node_sockets_poll;
pt->flag |= PNL_DEFAULT_CLOSED;
BLI_addtail(&art->paneltypes, pt);
-
+
+ pt= MEM_callocN(sizeof(PanelType), "spacetype node panel tree interface");
+ strcpy(pt->idname, "NODE_PT_node_tree_interface");
+ strcpy(pt->label, "Interface");
+ pt->draw= node_tree_interface_panel;
+ pt->poll= node_tree_interface_poll;
+ BLI_addtail(&art->paneltypes, pt);
+
pt = MEM_callocN(sizeof(PanelType), "spacetype node panel gpencil");
strcpy(pt->idname, "NODE_PT_gpencil");
strcpy(pt->label, "Grease Pencil");
diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c
index d2cc42b0a56..80a6ff1a393 100644
--- a/source/blender/editors/space_node/node_draw.c
+++ b/source/blender/editors/space_node/node_draw.c
@@ -29,10 +29,14 @@
* \brief higher level node drawing for the node editor.
*/
+#include "DNA_lamp_types.h"
#include "DNA_node_types.h"
+#include "DNA_material_types.h"
#include "DNA_object_types.h"
-#include "DNA_space_types.h"
#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_world_types.h"
#include "BLI_math.h"
#include "BLI_blenlib.h"
@@ -44,6 +48,8 @@
#include "BKE_main.h"
#include "BKE_node.h"
+#include "BLF_api.h"
+
#include "BIF_gl.h"
#include "BIF_glutil.h"
@@ -52,6 +58,7 @@
#include "ED_node.h"
#include "ED_gpencil.h"
+#include "ED_screen.h"
#include "ED_space_api.h"
#include "UI_resources.h"
@@ -65,25 +72,49 @@
/* XXX interface.h */
extern void ui_dropshadow(const rctf *rct, float radius, float aspect, float alpha, int select);
-/* XXX update functions for node editor are a mess, needs a clear concept */
-void ED_node_tree_update(SpaceNode *snode, Scene *scene)
+void ED_node_tree_update(const bContext *C)
{
- snode_set_context(snode, scene);
+ SpaceNode *snode = CTX_wm_space_node(C);
+ snode_set_context(C);
if (snode->nodetree && snode->nodetree->id.us == 0)
snode->nodetree->id.us = 1;
}
-void ED_node_changed_update(ID *id, bNode *node)
+/* id is supposed to contain a node tree */
+static bNodeTree *node_tree_from_ID(ID *id)
{
- bNodeTree *nodetree, *edittree;
- int treetype;
-
- node_tree_from_ID(id, &nodetree, &edittree, &treetype);
+ if (id) {
+ short idtype = GS(id->name);
+
+ switch (idtype) {
+ case ID_NT:
+ return (bNodeTree*)id;
+ case ID_MA:
+ return ((Material*)id)->nodetree;
+ case ID_LA:
+ return ((Lamp*)id)->nodetree;
+ case ID_WO:
+ return ((World*)id)->nodetree;
+ case ID_SCE:
+ return ((Scene*)id)->nodetree;
+ case ID_TE:
+ return ((Tex*)id)->nodetree;
+ }
+ }
+
+ return NULL;
+}
- if (treetype == NTREE_SHADER) {
+void ED_node_tag_update_id(ID *id)
+{
+ bNodeTree *ntree = node_tree_from_ID(id);
+ if (id == NULL)
+ return;
+
+ if (ntree->type == NTREE_SHADER) {
DAG_id_tag_update(id, 0);
-
+
if (GS(id->name) == ID_MA)
WM_main_add_notifier(NC_MATERIAL | ND_SHADING_DRAW, id);
else if (GS(id->name) == ID_LA)
@@ -91,18 +122,10 @@ void ED_node_changed_update(ID *id, bNode *node)
else if (GS(id->name) == ID_WO)
WM_main_add_notifier(NC_WORLD | ND_WORLD_DRAW, id);
}
- else if (treetype == NTREE_COMPOSIT) {
- if (node)
- nodeUpdate(edittree, node);
- /* don't use NodeTagIDChanged, it gives far too many recomposites for image, scene layers, ... */
-
- node = node_tree_get_editgroup(nodetree);
- if (node)
- nodeUpdateID(nodetree, node->id);
-
+ else if (ntree->type == NTREE_COMPOSIT) {
WM_main_add_notifier(NC_SCENE | ND_NODES, id);
}
- else if (treetype == NTREE_TEXTURE) {
+ else if (ntree->type == NTREE_TEXTURE) {
DAG_id_tag_update(id, 0);
WM_main_add_notifier(NC_TEXTURE | ND_NODES, id);
}
@@ -123,25 +146,17 @@ static int has_nodetree(bNodeTree *ntree, bNodeTree *lookup)
return 0;
}
-typedef struct NodeUpdateCalldata {
- bNodeTree *ntree;
- bNode *node;
-} NodeUpdateCalldata;
-static void node_generic_update_cb(void *calldata, ID *owner_id, bNodeTree *ntree)
-{
- NodeUpdateCalldata *cd = (NodeUpdateCalldata *)calldata;
- /* check if nodetree uses the group stored in calldata */
- if (has_nodetree(ntree, cd->ntree))
- ED_node_changed_update(owner_id, cd->node);
-}
-void ED_node_generic_update(Main *bmain, bNodeTree *ntree, bNode *node)
+void ED_node_tag_update_nodetree(Main *bmain, bNodeTree *ntree)
{
- bNodeTreeType *tti = ntreeGetType(ntree->type);
- NodeUpdateCalldata cd;
- cd.ntree = ntree;
- cd.node = node;
+ if (!ntreeIsValid(ntree))
+ return;
+
/* look through all datablocks, to support groups */
- tti->foreach_nodetree(bmain, &cd, node_generic_update_cb);
+ FOREACH_NODETREE(bmain, tntree, id) {
+ /* check if nodetree uses the group */
+ if (has_nodetree(tntree, ntree))
+ ED_node_tag_update_id(id);
+ } FOREACH_NODETREE_END
if (ntree->type == NTREE_TEXTURE)
ntreeTexCheckCyclics(ntree);
@@ -251,12 +266,12 @@ void ED_node_sort(bNodeTree *ntree)
}
-static void do_node_internal_buttons(bContext *C, void *node_v, int event)
+static void do_node_internal_buttons(bContext *C, void *UNUSED(node_v), int event)
{
if (event == B_NODE_EXEC) {
SpaceNode *snode = CTX_wm_space_node(C);
if (snode && snode->id)
- ED_node_changed_update(snode->id, node_v);
+ ED_node_tag_update_id(snode->id);
}
}
@@ -296,13 +311,15 @@ void node_from_view(struct bNode *node, float x, float y, float *rx, float *ry)
/* based on settings in node, sets drawing rect info. each redraw! */
static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node)
{
- uiLayout *layout;
- PointerRNA ptr;
+ uiLayout *layout, *row;
+ PointerRNA nodeptr, sockptr;
bNodeSocket *nsock;
float locx, locy;
float dy;
int buty;
+ RNA_pointer_create(&ntree->id, &RNA_Node, node, &nodeptr);
+
/* get "global" coords */
node_to_view(node, 0.0f, 0.0f, &locx, &locy);
dy = locy;
@@ -313,14 +330,36 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node)
/* little bit space in top */
if (node->outputs.first)
dy -= NODE_DYS / 2;
-
+
/* output sockets */
for (nsock = node->outputs.first; nsock; nsock = nsock->next) {
- if (!nodeSocketIsHidden(nsock)) {
- nsock->locx = locx + NODE_WIDTH(node);
- nsock->locy = dy - NODE_DYS;
- dy -= NODE_DY;
- }
+ if (nodeSocketIsHidden(nsock))
+ continue;
+
+ RNA_pointer_create(&ntree->id, &RNA_NodeSocket, nsock, &sockptr);
+
+ layout = uiBlockLayout(node->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL,
+ locx+NODE_DYS, dy, NODE_WIDTH(node)-NODE_DY, NODE_DY, UI_GetStyle());
+ /* context pointers for current node and socket */
+ uiLayoutSetContextPointer(layout, "node", &nodeptr);
+ uiLayoutSetContextPointer(layout, "socket", &sockptr);
+
+ /* align output buttons to the right */
+ row = uiLayoutRow(layout, 1);
+ uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_RIGHT);
+
+ node->typeinfo->drawoutputfunc((bContext *)C, row, &sockptr, &nodeptr, (nsock->flag & SOCK_IN_USE));
+
+ uiBlockEndAlign(node->block);
+ uiBlockLayoutResolve(node->block, NULL, &buty);
+
+ /* ensure minimum socket height in case layout is empty */
+ buty = MIN2(buty, dy - NODE_DY);
+
+ nsock->locx = locx + NODE_WIDTH(node);
+ /* place the socket circle in the middle of the layout */
+ nsock->locy = 0.5f * (dy + buty);
+ dy = buty;
}
node->prvr.xmin = locx + NODE_DYS;
@@ -328,43 +367,32 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node)
/* preview rect? */
if (node->flag & NODE_PREVIEW) {
- if (node->preview && node->preview->rect) {
- float aspect = 1.0f;
-
- if (node->preview && node->preview->xsize && node->preview->ysize)
- aspect = (float)node->preview->ysize / (float)node->preview->xsize;
+ float aspect = 1.0f;
+
+ if (node->preview_xsize && node->preview_ysize)
+ aspect = (float)node->preview_ysize / (float)node->preview_xsize;
+
+ dy -= NODE_DYS / 2;
+ node->prvr.ymax = dy;
+
+ if (aspect <= 1.0f)
+ node->prvr.ymin = dy - aspect * (NODE_WIDTH(node) - NODE_DY);
+ else {
+ /* width correction of image */
+ /* XXX huh? (ton) */
+ float dx = (NODE_WIDTH(node) - NODE_DYS) - (NODE_WIDTH(node) - NODE_DYS) / aspect;
- dy -= NODE_DYS / 2;
- node->prvr.ymax = dy;
+ node->prvr.ymin = dy - (NODE_WIDTH(node) - NODE_DY);
- if (aspect <= 1.0f)
- node->prvr.ymin = dy - aspect * (NODE_WIDTH(node) - NODE_DY);
- else {
- /* width correction of image */
- /* XXX huh? (ton) */
- float dx = (NODE_WIDTH(node) - NODE_DYS) - (NODE_WIDTH(node) - NODE_DYS) / aspect;
-
- node->prvr.ymin = dy - (NODE_WIDTH(node) - NODE_DY);
-
- node->prvr.xmin += 0.5f * dx;
- node->prvr.xmax -= 0.5f * dx;
- }
-
- dy = node->prvr.ymin - NODE_DYS / 2;
-
- /* make sure that maximums are bigger or equal to minimums */
- if (node->prvr.xmax < node->prvr.xmin) SWAP(float, node->prvr.xmax, node->prvr.xmin);
- if (node->prvr.ymax < node->prvr.ymin) SWAP(float, node->prvr.ymax, node->prvr.ymin);
- }
- else {
- float oldh = BLI_rctf_size_y(&node->prvr);
- if (oldh == 0.0f)
- oldh = 0.6f * NODE_WIDTH(node) - NODE_DY;
- dy -= NODE_DYS / 2;
- node->prvr.ymax = dy;
- node->prvr.ymin = dy - oldh;
- dy = node->prvr.ymin - NODE_DYS / 2;
+ node->prvr.xmin += 0.5f * dx;
+ node->prvr.xmax -= 0.5f * dx;
}
+
+ dy = node->prvr.ymin - NODE_DYS / 2;
+
+ /* make sure that maximums are bigger or equal to minimums */
+ if (node->prvr.xmax < node->prvr.xmin) SWAP(float, node->prvr.xmax, node->prvr.xmin);
+ if (node->prvr.ymax < node->prvr.ymin) SWAP(float, node->prvr.ymax, node->prvr.ymin);
}
/* buttons rect? */
@@ -378,14 +406,12 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node)
node->butr.ymin = 0;
node->butr.ymax = 0;
- RNA_pointer_create(&ntree->id, &RNA_Node, node, &ptr);
-
layout = uiBlockLayout(node->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL,
locx + NODE_DYS, dy, node->butr.xmax, 0, UI_GetStyle());
- uiLayoutSetContextPointer(layout, "node", &ptr);
+ uiLayoutSetContextPointer(layout, "node", &nodeptr);
- node->typeinfo->uifunc(layout, (bContext *)C, &ptr);
+ node->typeinfo->uifunc(layout, (bContext *)C, &nodeptr);
uiBlockEndAlign(node->block);
uiBlockLayoutResolve(node->block, NULL, &buty);
@@ -395,11 +421,29 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node)
/* input sockets */
for (nsock = node->inputs.first; nsock; nsock = nsock->next) {
- if (!nodeSocketIsHidden(nsock)) {
- nsock->locx = locx;
- nsock->locy = dy - NODE_DYS;
- dy -= NODE_DY;
- }
+ if (nodeSocketIsHidden(nsock))
+ continue;
+
+ RNA_pointer_create(&ntree->id, &RNA_NodeSocket, nsock, &sockptr);
+
+ layout = uiBlockLayout(node->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL,
+ locx+NODE_DYS, dy, NODE_WIDTH(node)-NODE_DY, NODE_DY, UI_GetStyle());
+ /* context pointers for current node and socket */
+ uiLayoutSetContextPointer(layout, "node", &nodeptr);
+ uiLayoutSetContextPointer(layout, "socket", &sockptr);
+
+ node->typeinfo->drawinputfunc((bContext *)C, layout, &sockptr, &nodeptr, (nsock->flag & SOCK_IN_USE));
+
+ uiBlockEndAlign(node->block);
+ uiBlockLayoutResolve(node->block, NULL, &buty);
+
+ /* ensure minimum socket height in case layout is empty */
+ buty = MIN2(buty, dy - NODE_DY);
+
+ nsock->locx = locx;
+ /* place the socket circle in the middle of the layout */
+ nsock->locy = 0.5f * (dy + buty);
+ dy = buty;
}
/* little bit space in end */
@@ -510,6 +554,7 @@ int node_get_colorid(bNode *node)
case NODE_CLASS_OP_VECTOR:
case NODE_CLASS_OP_FILTER: return TH_NODE_OPERATOR;
case NODE_CLASS_GROUP: return TH_NODE_GROUP;
+ case NODE_CLASS_INTERFACE: return TH_NODE_INTERFACE;
case NODE_CLASS_MATTE: return TH_NODE_MATTE;
case NODE_CLASS_DISTORT: return TH_NODE_DISTORT;
default: return TH_NODE;
@@ -534,7 +579,7 @@ static void node_draw_mute_line(View2D *v2d, SpaceNode *snode, bNode *node)
}
/* this might have some more generic use */
-static void node_circle_draw(float x, float y, float size, char *col, int highlight)
+static void node_circle_draw(float x, float y, float size, float *col, int highlight)
{
/* 16 values of sin function */
static float si[16] = {
@@ -552,12 +597,14 @@ static void node_circle_draw(float x, float y, float size, char *col, int highli
};
int a;
- glColor3ub(col[0], col[1], col[2]);
+ glColor4fv(col);
+ glEnable(GL_BLEND);
glBegin(GL_POLYGON);
for (a = 0; a < 16; a++)
glVertex2f(x + size * si[a], y + size * co[a]);
glEnd();
+ glDisable(GL_BLEND);
if (highlight) {
UI_ThemeColor(TH_TEXT_HI);
@@ -577,66 +624,93 @@ static void node_circle_draw(float x, float y, float size, char *col, int highli
glLineWidth(1.0f);
}
-void node_socket_circle_draw(bNodeTree *UNUSED(ntree), bNodeSocket *sock, float size, int highlight)
+void node_socket_circle_draw(const bContext *C, bNodeTree *ntree, bNode *node, bNodeSocket *sock, float size, int highlight)
{
- bNodeSocketType *stype = ntreeGetSocketType(sock->type);
- node_circle_draw(sock->locx, sock->locy, size, stype->ui_color, highlight);
+ PointerRNA ptr, node_ptr;
+ float color[4];
+
+ RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr);
+ RNA_pointer_create((ID *)ntree, &RNA_Node, node, &node_ptr);
+ sock->typeinfo->draw_color((bContext *)C, &ptr, &node_ptr, color);
+ node_circle_draw(sock->locx, sock->locy, size, color, highlight);
}
/* ************** Socket callbacks *********** */
-/* not a callback */
-static void node_draw_preview(bNodePreview *preview, rctf *prv)
+static void node_draw_preview_background(float tile, rctf *rect)
{
- float xscale = BLI_rctf_size_x(prv) / ((float)preview->xsize);
- float yscale = BLI_rctf_size_y(prv) / ((float)preview->ysize);
- float tile = BLI_rctf_size_x(prv) / 10.0f;
float x, y;
/* draw checkerboard backdrop to show alpha */
glColor3ub(120, 120, 120);
- glRectf(prv->xmin, prv->ymin, prv->xmax, prv->ymax);
+ glRectf(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
glColor3ub(160, 160, 160);
- for (y = prv->ymin; y < prv->ymax; y += tile * 2) {
- for (x = prv->xmin; x < prv->xmax; x += tile * 2) {
+ for (y = rect->ymin; y < rect->ymax; y += tile * 2) {
+ for (x = rect->xmin; x < rect->xmax; x += tile * 2) {
float tilex = tile, tiley = tile;
- if (x + tile > prv->xmax)
- tilex = prv->xmax - x;
- if (y + tile > prv->ymax)
- tiley = prv->ymax - y;
+ if (x + tile > rect->xmax)
+ tilex = rect->xmax - x;
+ if (y + tile > rect->ymax)
+ tiley = rect->ymax - y;
glRectf(x, y, x + tilex, y + tiley);
}
}
- for (y = prv->ymin + tile; y < prv->ymax; y += tile * 2) {
- for (x = prv->xmin + tile; x < prv->xmax; x += tile * 2) {
+ for (y = rect->ymin + tile; y < rect->ymax; y += tile * 2) {
+ for (x = rect->xmin + tile; x < rect->xmax; x += tile * 2) {
float tilex = tile, tiley = tile;
- if (x + tile > prv->xmax)
- tilex = prv->xmax - x;
- if (y + tile > prv->ymax)
- tiley = prv->ymax - y;
+ if (x + tile > rect->xmax)
+ tilex = rect->xmax - x;
+ if (y + tile > rect->ymax)
+ tiley = rect->ymax - y;
glRectf(x, y, x + tilex, y + tiley);
}
}
-
- glPixelZoom(xscale, yscale);
+}
+/* not a callback */
+static void node_draw_preview(bNodePreview *preview, rctf *prv)
+{
+ float xrect = BLI_rctf_size_x(prv);
+ float yrect = BLI_rctf_size_y(prv);
+ float xscale = xrect / ((float)preview->xsize);
+ float yscale = yrect / ((float)preview->ysize);
+ float scale;
+ rctf draw_rect;
+
+ /* uniform scale and offset */
+ draw_rect = *prv;
+ if (xscale < yscale) {
+ float offset = 0.5f * (yrect - ((float)preview->ysize) * xscale);
+ draw_rect.ymin += offset;
+ draw_rect.ymax -= offset;
+ scale = xscale;
+ }
+ else {
+ float offset = 0.5f * (xrect - ((float)preview->xsize) * yscale);
+ draw_rect.xmin += offset;
+ draw_rect.xmax -= offset;
+ scale = yscale;
+ }
+
+ node_draw_preview_background(BLI_rctf_size_x(prv) / 10.0f, &draw_rect);
+
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); /* premul graphics */
glColor4f(1.0, 1.0, 1.0, 1.0);
- glaDrawPixelsTex(prv->xmin, prv->ymin, preview->xsize, preview->ysize, GL_UNSIGNED_BYTE, GL_LINEAR, preview->rect);
+ glPixelZoom(scale, scale);
+ glaDrawPixelsTex(draw_rect.xmin, draw_rect.ymin, preview->xsize, preview->ysize, GL_UNSIGNED_BYTE, GL_LINEAR, preview->rect);
+ glPixelZoom(1.0f, 1.0f);
glDisable(GL_BLEND);
- glPixelZoom(1.0f, 1.0f);
UI_ThemeColorShadeAlpha(TH_BACK, -15, +100);
- fdrawbox(prv->xmin, prv->ymin, prv->xmax, prv->ymax);
-
+ fdrawbox(draw_rect.xmin, draw_rect.ymin, draw_rect.xmax, draw_rect.ymax);
}
/* common handle function for operator buttons that need to select the node first */
@@ -669,8 +743,9 @@ void node_draw_shadow(SpaceNode *snode, bNode *node, float radius, float alpha)
}
}
-static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node)
+static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node, bNodeInstanceKey key)
{
+ bNodeInstanceHash *previews = CTX_data_pointer_get(C, "node_previews").data;
bNodeSocket *sock;
rctf *rct = &node->totr;
float iconofs;
@@ -680,9 +755,9 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
char showname[128]; /* 128 used below */
View2D *v2d = &ar->v2d;
- /* hurmf... another candidate for callback, have to see how this works first */
- if (node->id && node->block && snode->treetype == NTREE_SHADER)
- nodeShaderSynchronizeID(node, 0);
+ /* XXX hack: copy values from linked ID data where displayed as sockets */
+ if (node->block)
+ nodeSynchronizeID(node, false);
/* skip if out of view */
if (BLI_rctf_isect(&node->totr, &ar->v2d.cur, NULL) == FALSE) {
@@ -823,11 +898,7 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
if (nodeSocketIsHidden(sock))
continue;
- node_socket_circle_draw(ntree, sock, NODE_SOCKSIZE, sock->flag & SELECT);
-
- node->typeinfo->drawinputfunc(C, node->block, ntree, node, sock, IFACE_(sock->name),
- sock->locx + (NODE_DYS), sock->locy - NODE_DYS,
- NODE_WIDTH(node) - NODE_DY);
+ node_socket_circle_draw(C, ntree, node, sock, NODE_SOCKSIZE, sock->flag & SELECT);
}
/* socket outputs */
@@ -835,17 +906,14 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
if (nodeSocketIsHidden(sock))
continue;
- node_socket_circle_draw(ntree, sock, NODE_SOCKSIZE, sock->flag & SELECT);
-
- node->typeinfo->drawoutputfunc(C, node->block, ntree, node, sock, IFACE_(sock->name),
- sock->locx - NODE_WIDTH(node) + (NODE_DYS), sock->locy - NODE_DYS,
- NODE_WIDTH(node) - NODE_DY);
+ node_socket_circle_draw(C, ntree, node, sock, NODE_SOCKSIZE, sock->flag & SELECT);
}
/* preview */
if (node->flag & NODE_PREVIEW) {
- if (node->preview && node->preview->rect && !BLI_rctf_is_empty(&node->prvr))
- node_draw_preview(node->preview, &node->prvr);
+ bNodePreview *preview = previews ? BKE_node_instance_hash_lookup(previews, key) : NULL;
+ if (preview && preview->rect && !BLI_rctf_is_empty(&node->prvr))
+ node_draw_preview(preview, &node->prvr);
}
UI_ThemeClearColor(color_id);
@@ -855,7 +923,7 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
node->block = NULL;
}
-static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node)
+static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node, bNodeInstanceKey UNUSED(key))
{
bNodeSocket *sock;
rctf *rct = &node->totr;
@@ -957,12 +1025,12 @@ static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, b
/* sockets */
for (sock = node->inputs.first; sock; sock = sock->next) {
if (!nodeSocketIsHidden(sock))
- node_socket_circle_draw(snode->nodetree, sock, socket_size, sock->flag & SELECT);
+ node_socket_circle_draw(C, ntree, node, sock, socket_size, sock->flag & SELECT);
}
for (sock = node->outputs.first; sock; sock = sock->next) {
if (!nodeSocketIsHidden(sock))
- node_socket_circle_draw(snode->nodetree, sock, socket_size, sock->flag & SELECT);
+ node_socket_circle_draw(C, ntree, node, sock, socket_size, sock->flag & SELECT);
}
uiEndBlock(C, node->block);
@@ -989,7 +1057,7 @@ void node_set_cursor(wmWindow *win, SpaceNode *snode)
bNodeSocket *sock;
int cursor = CURSOR_STD;
- if (ntree) {
+ if (ntreeIsValid(ntree)) {
if (node_find_indicated_socket(snode, &node, &sock, SOCK_IN | SOCK_OUT)) {
/* pass */
}
@@ -1009,12 +1077,12 @@ void node_set_cursor(wmWindow *win, SpaceNode *snode)
WM_cursor_set(win, cursor);
}
-void node_draw_default(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node)
+void node_draw_default(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node, bNodeInstanceKey key)
{
if (node->flag & NODE_HIDDEN)
- node_draw_hidden(C, ar, snode, ntree, node);
+ node_draw_hidden(C, ar, snode, ntree, node, key);
else
- node_draw_basis(C, ar, snode, ntree, node);
+ node_draw_basis(C, ar, snode, ntree, node, key);
}
static void node_update(const bContext *C, bNodeTree *ntree, bNode *node)
@@ -1023,34 +1091,28 @@ static void node_update(const bContext *C, bNodeTree *ntree, bNode *node)
node->typeinfo->drawupdatefunc(C, ntree, node);
}
-void node_update_nodetree(const bContext *C, bNodeTree *ntree, float offsetx, float offsety)
+void node_update_nodetree(const bContext *C, bNodeTree *ntree)
{
bNode *node;
/* update nodes front to back, so children sizes get updated before parents */
for (node = ntree->nodes.last; node; node = node->prev) {
- /* XXX little hack (not used anyore?) */
- node->locx += offsetx;
- node->locy += offsety;
-
node_update(C, ntree, node);
-
- node->locx -= offsetx;
- node->locy -= offsety;
}
}
-static void node_draw(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node)
+static void node_draw(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node, bNodeInstanceKey key)
{
if (node->typeinfo->drawfunc)
- node->typeinfo->drawfunc(C, ar, snode, ntree, node);
+ node->typeinfo->drawfunc(C, ar, snode, ntree, node, key);
}
#define USE_DRAW_TOT_UPDATE
-void node_draw_nodetree(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree)
+void node_draw_nodetree(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNodeInstanceKey parent_key)
{
bNode *node;
+ bNodeInstanceKey key;
bNodeLink *link;
int a;
@@ -1073,122 +1135,200 @@ void node_draw_nodetree(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeT
if (!(node->flag & NODE_BACKGROUND))
continue;
+
+ key = BKE_node_instance_key(parent_key, ntree, node);
node->nr = a; /* index of node in list, used for exec event code */
- node_draw(C, ar, snode, ntree, node);
+ node_draw(C, ar, snode, ntree, node, key);
}
/* node lines */
glEnable(GL_BLEND);
glEnable(GL_LINE_SMOOTH);
- for (link = ntree->links.first; link; link = link->next)
- node_draw_link(&ar->v2d, snode, link);
+ for (link = ntree->links.first; link; link = link->next) {
+ if (!nodeLinkIsHidden(link))
+ node_draw_link(&ar->v2d, snode, link);
+ }
glDisable(GL_LINE_SMOOTH);
glDisable(GL_BLEND);
/* draw foreground nodes, last nodes in front */
for (a = 0, node = ntree->nodes.first; node; node = node->next, a++) {
+ bNodeInstanceKey key = BKE_node_instance_key(parent_key, ntree, node);
if (node->flag & NODE_BACKGROUND)
continue;
+
+ key = BKE_node_instance_key(parent_key, ntree, node);
node->nr = a; /* index of node in list, used for exec event code */
- node_draw(C, ar, snode, ntree, node);
+ node_draw(C, ar, snode, ntree, node, key);
}
}
-void drawnodespace(const bContext *C, ARegion *ar, View2D *v2d)
+/* draw tree path info in lower left corner */
+static void draw_tree_path(SpaceNode *snode)
+{
+ char info[256];
+
+ ED_node_tree_path_get_fixedbuf(snode, info, sizeof(info));
+
+ UI_ThemeColor(TH_TEXT_HI);
+ BLF_draw_default(30, 30, 0.0f, info, sizeof(info));
+}
+
+static void snode_setup_v2d(SpaceNode *snode, ARegion *ar, float centerx, float centery)
+{
+ View2D *v2d = &ar->v2d;
+
+ /* shift view to node tree center */
+ UI_view2d_setcenter(v2d, centerx, centery);
+ UI_view2d_view_ortho(v2d);
+
+ /* aspect+font, set each time */
+ snode->aspect = BLI_rctf_size_x(&v2d->cur) / (float)ar->winx;
+ // XXX snode->curfont = uiSetCurFont_ext(snode->aspect);
+}
+
+static void draw_nodetree(const bContext *C, ARegion *ar, bNodeTree *ntree, bNodeInstanceKey parent_key)
+{
+ SpaceNode *snode = CTX_wm_space_node(C);
+
+ node_uiblocks_init(C, ntree);
+
+#ifdef WITH_COMPOSITOR
+ if (ntree->type == NTREE_COMPOSIT) {
+ COM_startReadHighlights();
+ }
+#endif
+
+ node_update_nodetree(C, ntree);
+ node_draw_nodetree(C, ar, snode, ntree, parent_key);
+}
+
+/* shade the parent node group and add a uiBlock to clip mouse events */
+static void draw_group_overlay(const bContext *C, ARegion *ar)
+{
+ View2D *v2d = &ar->v2d;
+ rctf rect = v2d->cur;
+ uiBlock *block;
+
+ /* shade node groups to separate them visually */
+ UI_ThemeColorShadeAlpha(TH_NODE_GROUP, 0, -70);
+ glEnable(GL_BLEND);
+ uiSetRoundBox(0);
+ uiDrawBox(GL_POLYGON, rect.xmin, rect.ymin, rect.xmax, rect.ymax, 0);
+ glDisable(GL_BLEND);
+
+ /* set the block bounds to clip mouse events from underlying nodes */
+ block = uiBeginBlock(C, ar, "node tree bounds block", UI_EMBOSS);
+ uiExplicitBoundsBlock(block, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+ uiBlockSetFlag(block, UI_BLOCK_CLIP_EVENTS);
+ uiEndBlock(C, block);
+}
+
+void drawnodespace(const bContext *C, ARegion *ar)
{
View2DScrollers *scrollers;
SpaceNode *snode = CTX_wm_space_node(C);
- bNodeLinkDrag *nldrag;
- LinkData *linkdata;
+ View2D *v2d = &ar->v2d;
UI_ThemeClearColor(TH_BACK);
glClear(GL_COLOR_BUFFER_BIT);
UI_view2d_view_ortho(v2d);
-
- //uiFreeBlocksWin(&sa->uiblocks, sa->win);
ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW);
/* only set once */
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_MAP1_VERTEX_3);
-
- /* aspect+font, set each time */
- snode->aspect = BLI_rctf_size_x(&v2d->cur) / (float)ar->winx;
- // XXX snode->curfont = uiSetCurFont_ext(snode->aspect);
-
- /* grid */
- UI_view2d_multi_grid_draw(v2d, U.widget_unit, 5, 2);
-
- /* backdrop */
- draw_nodespace_back_pix(C, ar, snode);
/* nodes */
- snode_set_context(snode, CTX_data_scene(C));
-
- if (snode->nodetree) {
- bNode *node;
- /* void **highlights = 0; */ /* UNUSED */
+ snode_set_context(C);
+
+ /* draw parent node trees */
+ if (snode->treepath.last) {
+ static const int max_depth = 2;
+ bNodeTreePath *path;
+ int depth, curdepth;
+ float center[2];
+ bNodeTree *ntree;
+ bNodeLinkDrag *nldrag;
+ LinkData *linkdata;
- node_uiblocks_init(C, snode->nodetree);
+ /* current View2D center, will be set temporarily for parent node trees */
+ UI_view2d_getcenter(v2d, &center[0], &center[1]);
- /* uiBlocks must be initialized in drawing order for correct event clipping.
- * Node group internal blocks added after the main group block.
- */
- for (node = snode->nodetree->nodes.first; node; node = node->next) {
- if (node->flag & NODE_GROUP_EDIT)
- node_uiblocks_init(C, (bNodeTree *)node->id);
+ /* store new view center in current edittree */
+ if (snode->edittree)
+ copy_v2_v2(snode->edittree->view_center, center);
+
+ depth = 0;
+ path = snode->treepath.last;
+ while (path->prev && depth < max_depth) {
+ path = path->prev;
+ ++depth;
+ }
+ /* parent node trees in the background */
+ for (curdepth = depth; curdepth >= 0; path = path->next, --curdepth) {
+ ntree = path->nodetree;
+
+ if (ntreeIsValid(ntree)) {
+ snode_setup_v2d(snode, ar, ntree->view_center[0], ntree->view_center[1]);
+
+ if (curdepth == 0) {
+ /* grid, uses theme color based on node path depth */
+ UI_view2d_multi_grid_draw(v2d, (depth > 0 ? TH_NODE_GROUP : TH_BACK), U.widget_unit, 5, 2);
+
+ /* backdrop */
+ draw_nodespace_back_pix(C, ar, snode);
+ }
+
+ draw_nodetree(C, ar, ntree, path->parent_key);
+
+ if (curdepth > 0)
+ draw_group_overlay(C, ar);
+ }
}
- node_update_nodetree(C, snode->nodetree, 0.0f, 0.0f);
-
-#ifdef WITH_COMPOSITOR
- if (snode->nodetree->type == NTREE_COMPOSIT) {
- COM_startReadHighlights();
+ /* reset View2D */
+ UI_view2d_setcenter(v2d, center[0], center[1]);
+
+ /* temporary links */
+ glEnable(GL_BLEND);
+ glEnable(GL_LINE_SMOOTH);
+ for (nldrag = snode->linkdrag.first; nldrag; nldrag = nldrag->next) {
+ for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next)
+ node_draw_link(v2d, snode, (bNodeLink *)linkdata->data);
}
-#endif
-
- node_draw_nodetree(C, ar, snode, snode->nodetree);
+ glDisable(GL_LINE_SMOOTH);
+ glDisable(GL_BLEND);
- #if 0
- /* active group */
- for (node = snode->nodetree->nodes.first; node; node = node->next) {
- if (node->flag & NODE_GROUP_EDIT)
- node_draw_group(C, ar, snode, snode->nodetree, node);
+ if (snode->flag & SNODE_SHOW_GPENCIL) {
+ /* draw grease-pencil ('canvas' strokes) */
+ draw_gpencil_view2d(C, TRUE);
}
- #endif
}
-
- /* temporary links */
- glEnable(GL_BLEND);
- glEnable(GL_LINE_SMOOTH);
- for (nldrag = snode->linkdrag.first; nldrag; nldrag = nldrag->next) {
- for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) {
- node_draw_link(&ar->v2d, snode, (bNodeLink *)linkdata->data);
- }
+ else {
+ /* default grid */
+ UI_view2d_multi_grid_draw(v2d, TH_BACK, U.widget_unit, 5, 2);
+
+ /* backdrop */
+ draw_nodespace_back_pix(C, ar, snode);
}
- glDisable(GL_LINE_SMOOTH);
- glDisable(GL_BLEND);
ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);
- if (snode->flag & SNODE_SHOW_GPENCIL) {
- /* draw grease-pencil ('canvas' strokes) */
- if (snode->nodetree) {
- draw_gpencil_view2d(C, TRUE);
- }
- }
-
/* reset view matrix */
UI_view2d_view_restore(C);
- if (snode->flag & SNODE_SHOW_GPENCIL) {
- /* draw grease-pencil (screen strokes, and also paintbuffer) */
- if (snode->nodetree) {
+ if (snode->treepath.last) {
+ if (snode->flag & SNODE_SHOW_GPENCIL) {
+ /* draw grease-pencil (screen strokes, and also paintbuffer) */
draw_gpencil_view2d(C, FALSE);
}
}
+
+ /* tree path info */
+ draw_tree_path(snode);
/* scrollers */
scrollers = UI_view2d_scrollers_calc(C, v2d, 10, V2D_GRID_CLAMP, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c
index 941bd783c39..2012284f39b 100644
--- a/source/blender/editors/space_node/node_edit.c
+++ b/source/blender/editors/space_node/node_edit.c
@@ -31,6 +31,8 @@
#include "MEM_guardedalloc.h"
+#include "DNA_action_types.h"
+#include "DNA_anim_types.h"
#include "DNA_lamp_types.h"
#include "DNA_material_types.h"
#include "DNA_node_types.h"
@@ -65,6 +67,7 @@
#include "RNA_access.h"
#include "RNA_define.h"
+#include "RNA_enum_types.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -76,6 +79,12 @@
#include "IMB_imbuf_types.h"
#include "node_intern.h" /* own include */
+#include "NOD_common.h"
+#include "NOD_socket.h"
+#include "NOD_composite.h"
+#include "NOD_shader.h"
+#include "NOD_texture.h"
+
#define USE_ESC_COMPO
@@ -241,27 +250,12 @@ int composite_node_active(bContext *C)
{
if (ED_operator_node_active(C)) {
SpaceNode *snode = CTX_wm_space_node(C);
- if (snode->treetype == NTREE_COMPOSIT)
+ if (ED_node_is_compositor(snode))
return 1;
}
return 0;
}
-/* also checks for edited groups */
-bNode *editnode_get_active(bNodeTree *ntree)
-{
- bNode *node;
-
- /* check for edited group */
- for (node = ntree->nodes.first; node; node = node->next)
- if (nodeGroupEditGet(node))
- break;
- if (node)
- return nodeGetActive((bNodeTree *)node->id);
- else
- return nodeGetActive(ntree);
-}
-
static int has_nodetree(bNodeTree *ntree, bNodeTree *lookup)
{
bNode *node;
@@ -277,20 +271,16 @@ static int has_nodetree(bNodeTree *ntree, bNodeTree *lookup)
return 0;
}
-static void snode_dag_update_group(void *calldata, ID *owner_id, bNodeTree *ntree)
-{
- if (has_nodetree(ntree, calldata))
- DAG_id_tag_update(owner_id, 0);
-}
-
void snode_dag_update(bContext *C, SpaceNode *snode)
{
Main *bmain = CTX_data_main(C);
/* for groups, update all ID's using this */
if (snode->edittree != snode->nodetree) {
- bNodeTreeType *tti = ntreeGetType(snode->edittree->type);
- tti->foreach_nodetree(bmain, snode->edittree, snode_dag_update_group);
+ FOREACH_NODETREE(bmain, tntree, id) {
+ if (has_nodetree(tntree, snode->edittree))
+ DAG_id_tag_update(id, 0);
+ } FOREACH_NODETREE_END
}
DAG_id_tag_update(snode->id, 0);
@@ -300,37 +290,53 @@ void snode_notify(bContext *C, SpaceNode *snode)
{
WM_event_add_notifier(C, NC_NODE | NA_EDITED, NULL);
- if (snode->treetype == NTREE_SHADER)
+ if(ED_node_is_shader(snode))
WM_event_add_notifier(C, NC_MATERIAL | ND_NODES, snode->id);
- else if (snode->treetype == NTREE_COMPOSIT)
+ else if(ED_node_is_compositor(snode))
WM_event_add_notifier(C, NC_SCENE | ND_NODES, snode->id);
- else if (snode->treetype == NTREE_TEXTURE)
+ else if(ED_node_is_texture(snode))
WM_event_add_notifier(C, NC_TEXTURE | ND_NODES, snode->id);
}
-bNode *node_tree_get_editgroup(bNodeTree *nodetree)
+void ED_node_set_tree_type(SpaceNode *snode, bNodeTreeType *typeinfo)
{
- bNode *gnode;
-
- /* get the groupnode */
- for (gnode = nodetree->nodes.first; gnode; gnode = gnode->next)
- if (nodeGroupEditGet(gnode))
- break;
- return gnode;
+ if (typeinfo)
+ BLI_strncpy(snode->tree_idname, typeinfo->idname, sizeof(snode->tree_idname));
+ else
+ snode->tree_idname[0] = '\0';
+}
+
+int ED_node_is_compositor(struct SpaceNode *snode)
+{
+ return (strcmp(snode->tree_idname, ntreeType_Composite->idname)==0);
+}
+
+int ED_node_is_shader(struct SpaceNode *snode)
+{
+ return (strcmp(snode->tree_idname, ntreeType_Shader->idname)==0);
+}
+
+int ED_node_is_texture(struct SpaceNode *snode)
+{
+ return (strcmp(snode->tree_idname, ntreeType_Texture->idname)==0);
}
/* assumes nothing being done in ntree yet, sets the default in/out node */
/* called from shading buttons or header */
-void ED_node_shader_default(Scene *scene, ID *id)
+void ED_node_shader_default(const bContext *C, ID *id)
{
+ Scene *scene = CTX_data_scene(C);
bNode *in, *out;
bNodeSocket *fromsock, *tosock, *sock;
bNodeTree *ntree;
- bNodeTemplate ntemp;
+ PointerRNA ptr;
int output_type, shader_type;
- float color[3], strength = 1.0f;
+ float color[4] = { 0.0f, 0.0f, 0.0f, 1.0f }, strength = 1.0f;
- ntree = ntreeAddTree(G.main, "Shader Nodetree", NTREE_SHADER, 0);
+ ntree = ntreeAddTree(NULL, "Shader Nodetree", ntreeType_Shader->idname);
+
+ RNA_id_pointer_create((ID *)ntree, &ptr);
+ RNA_boolean_set(&ptr, "is_local_tree", TRUE);
switch (GS(id->name)) {
case ID_MA:
@@ -383,12 +389,10 @@ void ED_node_shader_default(Scene *scene, ID *id)
return;
}
- ntemp.type = output_type;
- out = nodeAddNode(ntree, &ntemp);
+ out = nodeAddStaticNode(C, ntree, output_type);
out->locx = 300.0f; out->locy = 300.0f;
- ntemp.type = shader_type;
- in = nodeAddNode(ntree, &ntemp);
+ in = nodeAddStaticNode(C, ntree, shader_type);
in->locx = 10.0f; in->locy = 300.0f;
nodeSetActive(ntree, in);
@@ -399,12 +403,16 @@ void ED_node_shader_default(Scene *scene, ID *id)
/* default values */
if (BKE_scene_use_new_shading_nodes(scene)) {
+ PointerRNA sockptr;
sock = in->inputs.first;
- copy_v3_v3(((bNodeSocketValueRGBA *)sock->default_value)->value, color);
+ RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &sockptr);
+
+ RNA_float_set_array(&sockptr, "default_value", color);
if (strength != 0.0f) {
sock = in->inputs.last;
- ((bNodeSocketValueFloat *)sock->default_value)->value = strength;
+ RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &sockptr);
+ RNA_float_set(&sockptr, "default_value", strength);
}
}
@@ -413,11 +421,11 @@ void ED_node_shader_default(Scene *scene, ID *id)
/* assumes nothing being done in ntree yet, sets the default in/out node */
/* called from shading buttons or header */
-void ED_node_composit_default(Scene *sce)
+void ED_node_composit_default(const bContext *C, struct Scene *sce)
{
bNode *in, *out;
bNodeSocket *fromsock, *tosock;
- bNodeTemplate ntemp;
+ PointerRNA ptr;
/* but lets check it anyway */
if (sce->nodetree) {
@@ -426,20 +434,21 @@ void ED_node_composit_default(Scene *sce)
return;
}
- sce->nodetree = ntreeAddTree(G.main, "Compositing Nodetree", NTREE_COMPOSIT, 0);
-
+ sce->nodetree = ntreeAddTree(NULL, "Compositing Nodetree", ntreeType_Composite->idname);
+
+ RNA_id_pointer_create((ID *)sce->nodetree, &ptr);
+ RNA_boolean_set(&ptr, "is_local_tree", TRUE);
+
sce->nodetree->chunksize = 256;
sce->nodetree->edit_quality = NTREE_QUALITY_HIGH;
sce->nodetree->render_quality = NTREE_QUALITY_HIGH;
- ntemp.type = CMP_NODE_COMPOSITE;
- out = nodeAddNode(sce->nodetree, &ntemp);
+ out = nodeAddStaticNode(C, sce->nodetree, CMP_NODE_COMPOSITE);
out->locx = 300.0f; out->locy = 400.0f;
out->id = &sce->id;
id_us_plus(out->id);
- ntemp.type = CMP_NODE_R_LAYERS;
- in = nodeAddNode(sce->nodetree, &ntemp);
+ in = nodeAddStaticNode(C, sce->nodetree, CMP_NODE_R_LAYERS);
in->locx = 10.0f; in->locy = 400.0f;
in->id = &sce->id;
id_us_plus(in->id);
@@ -457,11 +466,11 @@ void ED_node_composit_default(Scene *sce)
/* assumes nothing being done in ntree yet, sets the default in/out node */
/* called from shading buttons or header */
-void ED_node_texture_default(Tex *tx)
+void ED_node_texture_default(const bContext *C, Tex *tx)
{
bNode *in, *out;
bNodeSocket *fromsock, *tosock;
- bNodeTemplate ntemp;
+ PointerRNA ptr;
/* but lets check it anyway */
if (tx->nodetree) {
@@ -470,14 +479,15 @@ void ED_node_texture_default(Tex *tx)
return;
}
- tx->nodetree = ntreeAddTree(G.main, "Texture Nodetree", NTREE_TEXTURE, 0);
+ tx->nodetree = ntreeAddTree(NULL, "Texture Nodetree", ntreeType_Texture->idname);
+
+ RNA_id_pointer_create((ID *)tx->nodetree, &ptr);
+ RNA_boolean_set(&ptr, "is_local_tree", TRUE);
- ntemp.type = TEX_NODE_OUTPUT;
- out = nodeAddNode(tx->nodetree, &ntemp);
+ out = nodeAddStaticNode(C, tx->nodetree, TEX_NODE_OUTPUT);
out->locx = 300.0f; out->locy = 300.0f;
- ntemp.type = TEX_NODE_CHECKER;
- in = nodeAddNode(tx->nodetree, &ntemp);
+ in = nodeAddStaticNode(C, tx->nodetree, TEX_NODE_CHECKER);
in->locx = 10.0f; in->locy = 300.0f;
nodeSetActive(tx->nodetree, in);
@@ -488,162 +498,66 @@ void ED_node_texture_default(Tex *tx)
ntreeUpdateTree(tx->nodetree);
}
-/* id is supposed to contain a node tree */
-void node_tree_from_ID(ID *id, bNodeTree **ntree, bNodeTree **edittree, int *treetype)
+/* Here we set the active tree(s), even called for each redraw now, so keep it fast :) */
+void snode_set_context(const bContext *C)
{
- if (id) {
- bNode *node = NULL;
- short idtype = GS(id->name);
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNodeTreeType *treetype = ntreeTypeFind(snode->tree_idname);
+ bNodeTree *ntree = snode->nodetree;
+ ID *id = snode->id, *from = snode->from;
- if (idtype == ID_NT) {
- *ntree = (bNodeTree *)id;
- if (treetype) *treetype = (*ntree)->type;
- }
- else if (idtype == ID_MA) {
- *ntree = ((Material *)id)->nodetree;
- if (treetype) *treetype = NTREE_SHADER;
- }
- else if (idtype == ID_LA) {
- *ntree = ((Lamp *)id)->nodetree;
- if (treetype) *treetype = NTREE_SHADER;
- }
- else if (idtype == ID_WO) {
- *ntree = ((World *)id)->nodetree;
- if (treetype) *treetype = NTREE_SHADER;
- }
- else if (idtype == ID_SCE) {
- *ntree = ((Scene *)id)->nodetree;
- if (treetype) *treetype = NTREE_COMPOSIT;
- }
- else if (idtype == ID_TE) {
- *ntree = ((Tex *)id)->nodetree;
- if (treetype) *treetype = NTREE_TEXTURE;
- }
- else {
- if (treetype) *treetype = 0;
- return;
- }
+ /* we use this to signal warnings, when node shaders are drawn in wrong render engine */
+ if (BKE_scene_use_new_shading_nodes(CTX_data_scene(C)))
+ snode->flag |= SNODE_NEW_SHADERS;
+ else
+ snode->flag &= ~SNODE_NEW_SHADERS;
+
+ /* check the tree type */
+ if (!treetype
+ || (treetype->poll && !treetype->poll(C, treetype))) {
+ /* invalid tree type, disable */
+ snode->tree_idname[0] = '\0';
+ ED_node_tree_start(snode, NULL, NULL, NULL);
+ return;
+ }
- /* find editable group */
- if (edittree) {
- if (*ntree)
- for (node = (*ntree)->nodes.first; node; node = node->next)
- if (nodeGroupEditGet(node))
- break;
-
- if (node && node->id)
- *edittree = (bNodeTree *)node->id;
- else
- *edittree = *ntree;
- }
+ if (snode->nodetree && strcmp(snode->nodetree->idname, snode->tree_idname) != 0) {
+ /* current tree does not match selected type, clear tree path */
+ ntree = NULL;
+ id = NULL;
+ from = NULL;
}
- else {
- *ntree = NULL;
- *edittree = NULL;
- if (treetype) *treetype = 0;
+
+ if (!(snode->flag & SNODE_PIN) || ntree == NULL) {
+ if (treetype->get_from_context)
+ treetype->get_from_context(C, treetype, &ntree, &id, &from);
}
+
+ if (snode->nodetree!=ntree || snode->id!=id || snode->from!=snode->from)
+ ED_node_tree_start(snode, ntree, id, from);
}
-/* Here we set the active tree(s), even called for each redraw now, so keep it fast :) */
-void snode_set_context(SpaceNode *snode, Scene *scene)
+void snode_update(SpaceNode *snode, bNode *node)
{
- Object *ob = OBACT;
+ bNodeTreePath *path;
- snode->id = snode->from = NULL;
+ /* XXX this only updates nodes in the current node space tree path.
+ * The function supposedly should update any potential group node linking to changed tree,
+ * this really requires a working depsgraph ...
+ */
- if (snode->treetype == NTREE_SHADER) {
- /* we use this to signal warnings, when node shaders are drawn in wrong render engine */
- if (BKE_scene_use_new_shading_nodes(scene))
- snode->flag |= SNODE_NEW_SHADERS;
- else
- snode->flag &= ~SNODE_NEW_SHADERS;
-
- /* need active object, or we allow pinning... */
- if (snode->shaderfrom == SNODE_SHADER_OBJECT) {
- if (ob) {
- if (ob->type == OB_LAMP) {
- snode->from = &ob->id;
- snode->id = ob->data;
- }
- else {
- Material *ma = give_current_material(ob, ob->actcol);
- if (ma) {
- snode->from = &ob->id;
- snode->id = &ma->id;
- }
- }
- }
- }
- else { /* SNODE_SHADER_WORLD */
- if (scene->world) {
- snode->from = NULL;
- snode->id = &scene->world->id;
- }
- }
- }
- else if (snode->treetype == NTREE_COMPOSIT) {
- snode->id = &scene->id;
-
- /* update output sockets based on available layers */
- ntreeCompositForceHidden(scene->nodetree, scene);
- }
- else if (snode->treetype == NTREE_TEXTURE) {
- Tex *tx = NULL;
-
- if (snode->texfrom == SNODE_TEX_OBJECT) {
- if (ob) {
- tx = give_current_object_texture(ob);
-
- if (ob->type == OB_LAMP)
- snode->from = (ID *)ob->data;
- else
- snode->from = (ID *)give_current_material(ob, ob->actcol);
-
- /* from is not set fully for material nodes, should be ID + Node then */
- snode->id = &tx->id;
- }
- }
- else if (snode->texfrom == SNODE_TEX_WORLD) {
- tx = give_current_world_texture(scene->world);
- snode->from = (ID *)scene->world;
- snode->id = &tx->id;
- }
- else {
- struct Brush *brush = NULL;
-
- if (ob && (ob->mode & OB_MODE_SCULPT))
- brush = paint_brush(&scene->toolsettings->sculpt->paint);
- else
- brush = paint_brush(&scene->toolsettings->imapaint.paint);
-
- if (brush) {
- snode->from = (ID *)brush;
- tx = give_current_brush_texture(brush);
- snode->id = &tx->id;
- }
+ /* update all edited group nodes */
+ path=snode->treepath.last;
+ if (path) {
+ bNodeTree *ngroup = path->nodetree;
+ for (path=path->prev; path; path=path->prev) {
+ nodeUpdateID(path->nodetree, (ID*)ngroup);
+ ngroup = path->nodetree;
}
}
- else {
- if (snode->nodetree && snode->nodetree->type == snode->treetype)
- snode->id = &snode->nodetree->id;
- else
- snode->id = NULL;
- }
-
- node_tree_from_ID(snode->id, &snode->nodetree, &snode->edittree, NULL);
-}
-void snode_update(SpaceNode *snode, bNode *node)
-{
- bNode *gnode;
-
if (node)
nodeUpdate(snode->edittree, node);
-
- /* if inside group, tag entire group */
- gnode = node_tree_get_editgroup(snode->nodetree);
- if (gnode)
- nodeUpdateID(snode->nodetree, gnode->id);
}
void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node)
@@ -654,6 +568,19 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node)
if (node->type != NODE_GROUP) {
int was_output = (node->flag & NODE_DO_OUTPUT);
+ int do_update = 0;
+
+ /* generic node group output: set node as active output */
+ if (node->type == NODE_GROUP_OUTPUT) {
+ bNode *tnode;
+ for (tnode = ntree->nodes.first; tnode; tnode = tnode->next)
+ if (tnode->type == NODE_GROUP_OUTPUT)
+ tnode->flag &= ~NODE_DO_OUTPUT;
+
+ node->flag |= NODE_DO_OUTPUT;
+ if (!was_output)
+ do_update = 1;
+ }
/* tree specific activate calls */
if (ntree->type == NTREE_SHADER) {
@@ -670,8 +597,10 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node)
node->flag |= NODE_DO_OUTPUT;
if (was_output == 0)
- ED_node_generic_update(bmain, ntree, node);
+ ED_node_tag_update_nodetree(bmain, ntree);
}
+ else if (do_update)
+ ED_node_tag_update_nodetree(bmain, ntree);
/* if active texture changed, free glsl materials */
if ((node->flag & NODE_ACTIVE_TEXTURE) && !was_active_texture) {
@@ -698,7 +627,7 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node)
node->flag |= NODE_DO_OUTPUT;
if (was_output == 0)
- ED_node_generic_update(bmain, ntree, node);
+ ED_node_tag_update_nodetree(bmain, ntree);
/* addnode() doesnt link this yet... */
node->id = (ID *)BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
@@ -723,9 +652,11 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node)
tnode->flag &= ~NODE_DO_OUTPUT;
node->flag |= NODE_DO_OUTPUT;
- ED_node_generic_update(bmain, ntree, node);
+ ED_node_tag_update_nodetree(bmain, ntree);
}
}
+ else if (do_update)
+ ED_node_tag_update_nodetree(bmain, ntree);
}
else if (ntree->type == NTREE_TEXTURE) {
// XXX
@@ -762,7 +693,7 @@ static void edit_node_properties(wmOperatorType *ot)
/* XXX could node be a context pointer? */
RNA_def_string(ot->srna, "node", "", MAX_NAME, "Node", "");
RNA_def_int(ot->srna, "socket", 0, 0, MAX_SOCKET, "Socket", "", 0, MAX_SOCKET);
- RNA_def_enum(ot->srna, "in_out", socket_in_out_items, SOCK_IN, "Socket Side", "");
+ RNA_def_enum(ot->srna, "in_out", node_socket_in_out_items, SOCK_IN, "Socket Side", "");
}
static int edit_node_invoke_properties(bContext *C, wmOperator *op)
@@ -874,7 +805,7 @@ static int node_resize_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
SpaceNode *snode = CTX_wm_space_node(C);
ARegion *ar = CTX_wm_region(C);
- bNode *node = editnode_get_active(snode->edittree);
+ bNode *node = nodeGetActive(snode->edittree);
NodeSizeWidget *nsw = op->customdata;
float mx, my, dx, dy;
@@ -977,7 +908,7 @@ static int node_resize_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
SpaceNode *snode = CTX_wm_space_node(C);
ARegion *ar = CTX_wm_region(C);
- bNode *node = editnode_get_active(snode->edittree);
+ bNode *node = nodeGetActive(snode->edittree);
int dir;
if (node) {
@@ -1056,33 +987,6 @@ void node_set_hidden_sockets(SpaceNode *snode, bNode *node, int set)
}
}
-/* return 0, nothing done */
-static int UNUSED_FUNCTION(node_mouse_groupheader) (SpaceNode *snode)
-{
- bNode *gnode;
- float mx = 0, my = 0;
-// XXX int mval[2];
-
- gnode = node_tree_get_editgroup(snode->nodetree);
- if (gnode == NULL) return 0;
-
-// XXX getmouseco_areawin(mval);
-// XXX areamouseco_to_ipoco(G.v2d, mval, &mx, &my);
-
- /* click in header or outside? */
- if (BLI_rctf_isect_pt(&gnode->totr, mx, my) == 0) {
- rctf rect = gnode->totr;
-
- rect.ymax += NODE_DY;
- if (BLI_rctf_isect_pt(&rect, mx, my) == 0)
- snode_make_group_editable(snode, NULL); /* toggles, so exits editmode */
-// else
-// XXX transform_nodes(snode->nodetree, 'g', "Move group");
-
- return 1;
- }
- return 0;
-}
/* checks snode->mouse position, and returns found node/socket */
/* type is SOCK_IN and/or SOCK_OUT */
@@ -1143,32 +1047,6 @@ int node_find_indicated_socket(SpaceNode *snode, bNode **nodep, bNodeSocket **so
}
}
- /* check group sockets
- * NB: using ngroup->outputs as input sockets and vice versa here!
- */
- if (in_out & SOCK_IN) {
- for (sock = snode->edittree->outputs.first; sock; sock = sock->next) {
- if (!nodeSocketIsHidden(sock)) {
- if (BLI_rctf_isect_pt(&rect, sock->locx, sock->locy)) {
- *nodep = NULL; /* NULL node pointer indicates group socket */
- *sockp = sock;
- return 1;
- }
- }
- }
- }
- if (in_out & SOCK_OUT) {
- for (sock = snode->edittree->inputs.first; sock; sock = sock->next) {
- if (!nodeSocketIsHidden(sock)) {
- if (BLI_rctf_isect_pt(&rect, sock->locx, sock->locy)) {
- *nodep = NULL; /* NULL node pointer indicates group socket */
- *sockp = sock;
- return 1;
- }
- }
- }
- }
-
return 0;
}
@@ -1215,7 +1093,7 @@ static int node_duplicate_exec(bContext *C, wmOperator *op)
* but operators and readfile.c do. */
id_us_plus(newnode->id);
/* to ensure redraws or rerenders happen */
- ED_node_changed_update(snode->id, newnode);
+ ED_node_tag_update_id(snode->id);
}
}
@@ -1276,9 +1154,9 @@ static int node_duplicate_exec(bContext *C, wmOperator *op)
/* has been set during copy above */
newnode = node->new_node;
- node_deselect(node);
+ nodeSetSelected(node, FALSE);
node->flag &= ~NODE_ACTIVE;
- node_select(newnode);
+ nodeSetSelected(newnode, TRUE);
}
/* make sure we don't copy new nodes again! */
@@ -1312,6 +1190,8 @@ void NODE_OT_duplicate(wmOperatorType *ot)
}
int ED_node_select_check(ListBase *lb)
+
+
{
bNode *node;
@@ -1456,6 +1336,7 @@ void NODE_OT_render_changed(wmOperatorType *ot)
ot->flag = 0;
}
+
/* ****************** Hide operator *********************** */
static void node_flag_toggle_exec(SpaceNode *snode, int toggle_flag)
@@ -1962,8 +1843,6 @@ static int node_clipboard_copy_exec(bContext *C, wmOperator *UNUSED(op))
{
SpaceNode *snode = CTX_wm_space_node(C);
bNodeTree *ntree = snode->edittree;
- bNode *gnode = node_tree_get_editgroup(snode->nodetree);
- float gnode_x = 0.0f, gnode_y = 0.0f;
bNode *node;
bNodeLink *link, *newlink;
@@ -1973,10 +1852,6 @@ static int node_clipboard_copy_exec(bContext *C, wmOperator *UNUSED(op))
BKE_node_clipboard_clear();
BKE_node_clipboard_init(ntree);
- /* get group node offset */
- if (gnode)
- node_to_view(gnode, 0.0f, 0.0f, &gnode_x, &gnode_y);
-
for (node = ntree->nodes.first; node; node = node->next) {
if (node->flag & SELECT) {
bNode *new_node;
@@ -1999,12 +1874,6 @@ static int node_clipboard_copy_exec(bContext *C, wmOperator *UNUSED(op))
nodeDetachNode(new_node);
}
}
-
- /* transform to basic view space. child node location is relative to parent */
- if (!new_node->parent) {
- new_node->locx += gnode_x;
- new_node->locy += gnode_y;
- }
}
}
@@ -2051,8 +1920,6 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *op)
{
SpaceNode *snode = CTX_wm_space_node(C);
bNodeTree *ntree = snode->edittree;
- bNode *gnode = node_tree_get_editgroup(snode->nodetree);
- float gnode_center[2];
const ListBase *clipboard_nodes_lb;
const ListBase *clipboard_links_lb;
bNode *node;
@@ -2086,14 +1953,6 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *op)
/* deselect old nodes */
node_deselect_all(snode);
- /* get group node offset */
- if (gnode) {
- node_to_view(gnode, 0.0f, 0.0f, &gnode_center[0], &gnode_center[1]);
- }
- else {
- zero_v2(gnode_center);
- }
-
/* calculate "barycenter" for placing on mouse cursor */
zero_v2(center);
for (node = clipboard_nodes_lb->first, num_nodes = 0; node; node = node->next, num_nodes++) {
@@ -2110,7 +1969,7 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *op)
id_us_plus(node->id);
/* pasted nodes are selected */
- node_select(new_node);
+ nodeSetSelected(new_node, TRUE);
}
/* reparent copied nodes */
@@ -2118,13 +1977,6 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *op)
bNode *new_node = node->new_node;
if (new_node->parent)
new_node->parent = new_node->parent->new_node;
-
-
- /* place nodes around the mouse cursor. child nodes locations are relative to parent */
- if (!new_node->parent) {
- new_node->locx += snode->cursor[0] - center[0] - gnode_center[0];
- new_node->locy += snode->cursor[1] - center[1] - gnode_center[1];
- }
}
for (link = clipboard_links_lb->first; link; link = link->next) {
@@ -2167,15 +2019,186 @@ void NODE_OT_clipboard_paste(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* ********************** Shader Script Update ******************/
+/********************** Add interface socket operator *********************/
-typedef struct ScriptUpdateData {
- RenderEngine *engine;
- RenderEngineType *type;
+static bNodeSocket *ntree_get_active_interface_socket(ListBase *lb)
+{
+ bNodeSocket *sock;
+ for (sock = lb->first; sock; sock = sock->next)
+ if (sock->flag & SELECT)
+ return sock;
+ return NULL;
+}
- Text *text;
- int found;
-} ScriptUpdateData;
+static int ntree_socket_add_exec(bContext *C, wmOperator *op)
+{
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNodeTree *ntree = snode->edittree;
+ int in_out = RNA_enum_get(op->ptr, "in_out");
+ PointerRNA ntree_ptr;
+ bNodeSocket *sock, *tsock, *active_sock;
+ const char *default_name;
+
+ RNA_id_pointer_create((ID *)ntree, &ntree_ptr);
+
+ if (in_out == SOCK_IN) {
+ active_sock = ntree_get_active_interface_socket(&ntree->inputs);
+ default_name = "Input";
+ }
+ else {
+ active_sock = ntree_get_active_interface_socket(&ntree->outputs);
+ default_name = "Output";
+ }
+
+ if (active_sock) {
+ /* insert a copy of the active socket right after it */
+ sock = ntreeInsertSocketInterface(ntree, in_out, active_sock->idname, active_sock->next, active_sock->name);
+ /* XXX this only works for actual sockets, not interface templates! */
+ /*nodeSocketCopyValue(sock, &ntree_ptr, active_sock, &ntree_ptr);*/
+ }
+ else {
+ /* XXX TODO define default socket type for a tree! */
+ sock = ntreeAddSocketInterface(ntree, in_out, "NodeSocketFloat", default_name);
+ }
+
+ /* deactivate sockets (has to check both lists) */
+ for (tsock = ntree->inputs.first; tsock; tsock = tsock->next)
+ tsock->flag &= ~SELECT;
+ for (tsock = ntree->outputs.first; tsock; tsock = tsock->next)
+ tsock->flag &= ~SELECT;
+ /* make the new socket active */
+ sock->flag |= SELECT;
+
+ ntreeUpdateTree(ntree);
+
+ return OPERATOR_FINISHED;
+}
+
+void NODE_OT_tree_socket_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Add Node Tree Interface Socket";
+ ot->idname= "NODE_OT_tree_socket_add";
+
+ /* api callbacks */
+ ot->exec= ntree_socket_add_exec;
+ ot->poll= ED_operator_node_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_enum(ot->srna, "in_out", node_socket_in_out_items, SOCK_IN, "Socket Type", "");
+}
+
+/********************** Remove interface socket operator *********************/
+
+static int ntree_socket_remove_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNodeTree *ntree = snode->edittree;
+ bNodeSocket *iosock, *active_sock;
+
+ iosock = ntree_get_active_interface_socket(&ntree->inputs);
+ if (!iosock)
+ iosock = ntree_get_active_interface_socket(&ntree->outputs);
+ if (!iosock)
+ return OPERATOR_CANCELLED;
+
+ /* preferably next socket becomes active, otherwise try previous socket */
+ active_sock = (iosock->next ? iosock->next : iosock->prev);
+ ntreeRemoveSocketInterface(ntree, iosock);
+
+ /* set active socket */
+ if (active_sock)
+ active_sock->flag |= SELECT;
+
+ ntreeUpdateTree(ntree);
+
+ return OPERATOR_FINISHED;
+}
+
+void NODE_OT_tree_socket_remove(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Remove Node Tree Interface Socket";
+ ot->idname= "NODE_OT_tree_socket_remove";
+
+ /* api callbacks */
+ ot->exec= ntree_socket_remove_exec;
+ ot->poll= ED_operator_node_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/********************** Move interface socket operator *********************/
+
+static EnumPropertyItem move_direction_items[] = {
+ { 1, "UP", 0, "Up", "" },
+ { 2, "DOWN", 0, "Down", "" },
+ { 0, NULL, 0, NULL, NULL },
+};
+
+static int ntree_socket_move_exec(bContext *C, wmOperator *op)
+{
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNodeTree *ntree = snode->edittree;
+ int direction = RNA_enum_get(op->ptr, "direction");
+ bNodeSocket *iosock;
+ ListBase *lb;
+
+ lb = &ntree->inputs;
+ iosock = ntree_get_active_interface_socket(lb);
+ if (!iosock) {
+ lb = &ntree->outputs;
+ iosock = ntree_get_active_interface_socket(lb);
+ }
+ if (!iosock)
+ return OPERATOR_CANCELLED;
+
+ switch (direction) {
+ case 1: { /* up */
+ bNodeSocket *before = iosock->prev;
+ BLI_remlink(lb, iosock);
+ if (before)
+ BLI_insertlinkbefore(lb, before, iosock);
+ else
+ BLI_addhead(lb, iosock);
+ break;
+ }
+ case 2: { /* down */
+ bNodeSocket *after = iosock->next;
+ BLI_remlink(lb, iosock);
+ if (after)
+ BLI_insertlinkafter(lb, after, iosock);
+ else
+ BLI_addtail(lb, iosock);
+ break;
+ }
+ }
+
+ ntreeUpdateTree(ntree);
+
+ return OPERATOR_FINISHED;
+}
+
+void NODE_OT_tree_socket_move(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Move Node Tree Socket";
+ ot->idname= "NODE_OT_tree_socket_move";
+
+ /* api callbacks */
+ ot->exec= ntree_socket_move_exec;
+ ot->poll= ED_operator_node_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_enum(ot->srna, "direction", move_direction_items, 1, "Direction", "");
+}
+
+/* ********************** Shader Script Update ******************/
static int node_shader_script_update_poll(bContext *C)
{
@@ -2208,64 +2231,79 @@ static int node_shader_script_update_poll(bContext *C)
return 0;
}
-static void node_shader_script_update_text(void *data_, ID *UNUSED(id), bNodeTree *ntree)
+/* recursively check for script nodes in groups using this text and update */
+static int node_shader_script_update_text_recursive(RenderEngine *engine, RenderEngineType *type, bNodeTree *ntree, Text *text)
{
- ScriptUpdateData *data = (ScriptUpdateData *)data_;
+ int found = FALSE;
bNode *node;
-
+
+ ntree->done = TRUE;
+
/* update each script that is using this text datablock */
for (node = ntree->nodes.first; node; node = node->next) {
if (node->type == NODE_GROUP) {
- node_shader_script_update_text(data_, NULL, (bNodeTree *)node->id);
+ bNodeTree *ngroup = (bNodeTree *)node->id;
+ if (ngroup && !ngroup->done)
+ found |= node_shader_script_update_text_recursive(engine, type, ngroup, text);
}
- else if (node->type == SH_NODE_SCRIPT && node->id == &data->text->id) {
- data->type->update_script_node(data->engine, ntree, node);
- data->found = TRUE;
+ else if (node->type == SH_NODE_SCRIPT && node->id == &text->id) {
+ type->update_script_node(engine, ntree, node);
+ found = TRUE;
}
}
+
+ return found;
}
static int node_shader_script_update_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
- ScriptUpdateData data;
PointerRNA nodeptr = CTX_data_pointer_get_type(C, "node", &RNA_ShaderNodeScript);
+ RenderEngine *engine;
+ RenderEngineType *type;
+ int found = FALSE;
/* setup render engine */
- data.type = RE_engines_find(scene->r.engine);
- data.engine = RE_engine_create(data.type);
- data.engine->reports = op->reports;
- data.text = NULL;
- data.found = FALSE;
+ type = RE_engines_find(scene->r.engine);
+ engine = RE_engine_create(type);
+ engine->reports = op->reports;
if (nodeptr.data) {
/* update single node */
bNodeTree *ntree = nodeptr.id.data;
bNode *node = nodeptr.data;
- data.type->update_script_node(data.engine, ntree, node);
+ type->update_script_node(engine, ntree, node);
- data.found = TRUE;
+ found = TRUE;
}
else {
/* update all nodes using text datablock */
- data.text = CTX_data_pointer_get_type(C, "edit_text", &RNA_Text).data;
-
- if (data.text) {
- bNodeTreeType *ntreetype = ntreeGetType(NTREE_SHADER);
-
- if (ntreetype && ntreetype->foreach_nodetree)
- ntreetype->foreach_nodetree(bmain, &data, node_shader_script_update_text);
+ Text *text = CTX_data_pointer_get_type(C, "edit_text", &RNA_Text).data;
+
+ if (text) {
+ /* clear flags for recursion check */
+ FOREACH_NODETREE(bmain, ntree, id) {
+ if (ntree->type == NTREE_SHADER)
+ ntree->done = FALSE;
+ } FOREACH_NODETREE_END
+
+ FOREACH_NODETREE(bmain, ntree, id) {
+ if (ntree->type == NTREE_SHADER) {
+ if (!ntree->done)
+ found |= node_shader_script_update_text_recursive(engine, type, ntree, text);
+ }
+ } FOREACH_NODETREE_END
- if (!data.found)
+ if (!found)
BKE_report(op->reports, RPT_INFO, "Text not used by any node, no update done");
}
}
- RE_engine_free(data.engine);
+ RE_engine_free(engine);
- return (data.found)? OPERATOR_FINISHED: OPERATOR_CANCELLED;
+ return (found)? OPERATOR_FINISHED: OPERATOR_CANCELLED;
}
void NODE_OT_shader_script_update(wmOperatorType *ot)
diff --git a/source/blender/editors/space_node/node_group.c b/source/blender/editors/space_node/node_group.c
index 6696284b169..ba98f9ea94d 100644
--- a/source/blender/editors/space_node/node_group.c
+++ b/source/blender/editors/space_node/node_group.c
@@ -66,85 +66,132 @@
#include "UI_resources.h"
#include "node_intern.h" /* own include */
+#include "NOD_common.h"
#include "NOD_socket.h"
-static EnumPropertyItem socket_in_out_items[] = {
- { SOCK_IN, "SOCK_IN", 0, "Input", "" },
- { SOCK_OUT, "SOCK_OUT", 0, "Output", "" },
- { 0, NULL, 0, NULL, NULL },
-};
-
-/* ***************** Edit Group operator ************* */
-
-void snode_make_group_editable(SpaceNode *snode, bNode *gnode)
+/* define common group node operator properties */
+static void node_group_operator_properties(wmOperatorType *ot)
{
- bNode *node;
-
- /* make sure nothing has group editing on */
- for (node = snode->nodetree->nodes.first; node; node = node->next) {
- nodeGroupEditClear(node);
+ /* NB: not using an enum here, because that it would have to use an item callback and thus require
+ * copying of identifier strings anyway. node_type is not a user option, just a way of allowing
+ * node group operators to work on different types of group nodes.
+ */
+ RNA_def_string(ot->srna, "node_type", "", 0, "Node Type", "Group node type the operator works on");
+}
- /* while we're here, clear texture active */
- if (node->typeinfo->nclass == NODE_CLASS_TEXTURE) {
- /* this is not 100% sure to be reliable, see comment on the flag */
- node->flag &= ~NODE_ACTIVE_TEXTURE;
- }
+/* Internal poll functions so group node operators can work with different group node types.
+ * This checks the operator node type property and looks up the respective types.
+ * If this function returns FALSE the operator should return PASS_THROUGH to allow other variants.
+ */
+static int node_group_operator_check_type(bContext *C, wmOperator *op, char **r_node_idname, char **r_ntree_idname)
+{
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNodeTree *ntree = snode->edittree;
+ PropertyRNA *ntype_prop = RNA_struct_find_property(op->ptr, "node_type");
+ char *node_idname, *ntree_idname;
+ bNodeType *ntype;
+ bNodeTreeType *ntreetype;
+
+ if (!RNA_property_is_set(op->ptr, ntype_prop)) {
+ BKE_report(op->reports, RPT_ERROR, "Group node type not set");
+ return FALSE;
}
-
- if (gnode == NULL) {
- /* with NULL argument we do a toggle */
- if (snode->edittree == snode->nodetree)
- gnode = nodeGetActive(snode->nodetree);
+
+ node_idname = RNA_property_string_get_alloc(op->ptr, ntype_prop, NULL, 0, NULL);
+ ntype = nodeTypeFind(node_idname);
+ if (!ntype) {
+ BKE_reportf(op->reports, RPT_ERROR, "Group node type %s undefined", node_idname);
+ MEM_freeN(node_idname);
+ return FALSE;
}
-
- if (gnode) {
- snode->edittree = nodeGroupEditSet(gnode, 1);
-
- /* deselect all other nodes, so we can also do grabbing of entire subtree */
- for (node = snode->nodetree->nodes.first; node; node = node->next) {
- node_deselect(node);
-
- if (node->typeinfo->nclass == NODE_CLASS_TEXTURE) {
- /* this is not 100% sure to be reliable, see comment on the flag */
- node->flag &= ~NODE_ACTIVE_TEXTURE;
- }
- }
- node_select(gnode);
+
+ if (!ntype->poll(ntype, ntree)) {
+ MEM_freeN(node_idname);
+ return FALSE;
}
+
+ ntree_idname = BLI_strdup(ntype->group_tree_idname);
+ ntreetype = ntreeTypeFind(ntree_idname);
+ if (!ntreetype) {
+ BKE_reportf(op->reports, RPT_ERROR, "Group node tree type %s undefined", ntree_idname);
+ MEM_freeN(node_idname);
+ MEM_freeN(ntree_idname);
+ return FALSE;
+ }
+
+ if (r_node_idname)
+ *r_node_idname = node_idname;
+ else
+ MEM_freeN(node_idname);
+
+ if (r_ntree_idname)
+ *r_ntree_idname = ntree_idname;
else
- snode->edittree = snode->nodetree;
+ MEM_freeN(ntree_idname);
+
+ return TRUE;
}
-static int node_group_edit_exec(bContext *C, wmOperator *UNUSED(op))
+static bNode *node_group_get_active(bContext *C, const char *node_idname)
{
SpaceNode *snode = CTX_wm_space_node(C);
+ bNode *node = nodeGetActive(snode->edittree);
+
+ if (node && strcmp(node->idname, node_idname)==0)
+ return node;
+ else
+ return NULL;
+}
- ED_preview_kill_jobs(C);
+/* ***************** Edit Group operator ************* */
- if (snode->nodetree == snode->edittree) {
- bNode *gnode = nodeGetActive(snode->edittree);
- snode_make_group_editable(snode, gnode);
+static int node_group_edit_exec(bContext *C, wmOperator *op)
+{
+ SpaceNode *snode = CTX_wm_space_node(C);
+ char *node_idname;
+ bNode *gnode;
+ int exit = RNA_boolean_get(op->ptr, "exit");
+
+ ED_preview_kill_jobs(C);
+
+ if (!node_group_operator_check_type(C, op, &node_idname, NULL))
+ return OPERATOR_PASS_THROUGH;
+
+ gnode = node_group_get_active(C, node_idname);
+ MEM_freeN(node_idname);
+
+ if (gnode && !exit) {
+ bNodeTree *ngroup= (bNodeTree*)gnode->id;
+
+ if (ngroup) {
+ if (ngroup->id.lib)
+ ntreeMakeLocal(ngroup);
+
+ ED_node_tree_push(snode, ngroup, gnode);
+ }
}
else
- snode_make_group_editable(snode, NULL);
-
+ ED_node_tree_pop(snode);
+
WM_event_add_notifier(C, NC_SCENE | ND_NODES, NULL);
-
+
return OPERATOR_FINISHED;
}
static int node_group_edit_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- SpaceNode *snode = CTX_wm_space_node(C);
+ char *node_idname;
bNode *gnode;
-
- /* XXX callback? */
- if (snode->nodetree == snode->edittree) {
- gnode = nodeGetActive(snode->edittree);
- if (gnode && gnode->id && GS(gnode->id->name) == ID_NT && gnode->id->lib) {
- uiPupMenuOkee(C, op->type->idname, "Make group local?");
- return OPERATOR_CANCELLED;
- }
+
+ if (!node_group_operator_check_type(C, op, &node_idname, NULL))
+ return OPERATOR_PASS_THROUGH;
+
+ gnode = node_group_get_active(C, node_idname);
+ MEM_freeN(node_idname);
+
+ if (gnode && gnode->id && gnode->id->lib) {
+ WM_operator_confirm_message(C, op, "Make group local?");
+ return OPERATOR_CANCELLED;
}
return node_group_edit_exec(C, op);
@@ -156,258 +203,17 @@ void NODE_OT_group_edit(wmOperatorType *ot)
ot->name = "Edit Group";
ot->description = "Edit node group";
ot->idname = "NODE_OT_group_edit";
-
+
/* api callbacks */
ot->invoke = node_group_edit_invoke;
ot->exec = node_group_edit_exec;
ot->poll = ED_operator_node_active;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-/* ***************** Add Group Socket operator ************* */
-
-static int node_group_socket_add_exec(bContext *C, wmOperator *op)
-{
- SpaceNode *snode = CTX_wm_space_node(C);
- int in_out = -1;
- char name[MAX_NAME] = "";
- int type = SOCK_FLOAT;
- bNodeTree *ngroup = snode->edittree;
- /* bNodeSocket *sock; */ /* UNUSED */
-
- ED_preview_kill_jobs(C);
-
- if (RNA_struct_property_is_set(op->ptr, "name"))
- RNA_string_get(op->ptr, "name", name);
-
- if (RNA_struct_property_is_set(op->ptr, "type"))
- type = RNA_enum_get(op->ptr, "type");
-
- if (RNA_struct_property_is_set(op->ptr, "in_out"))
- in_out = RNA_enum_get(op->ptr, "in_out");
- else
- return OPERATOR_CANCELLED;
-
- /* using placeholder subtype first */
- /* sock = */ /* UNUSED */ node_group_add_socket(ngroup, name, type, in_out);
-
- ntreeUpdateTree(ngroup);
-
- snode_notify(C, snode);
-
- return OPERATOR_FINISHED;
-}
-
-void NODE_OT_group_socket_add(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Add Group Socket";
- ot->description = "Add node group socket";
- ot->idname = "NODE_OT_group_socket_add";
-
- /* api callbacks */
- ot->exec = node_group_socket_add_exec;
- ot->poll = ED_operator_node_active;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_enum(ot->srna, "in_out", socket_in_out_items, SOCK_IN, "Socket Type", "Input or Output");
- RNA_def_string(ot->srna, "name", "", MAX_NAME, "Name", "Group socket name");
- RNA_def_enum(ot->srna, "type", node_socket_type_items, SOCK_FLOAT, "Type", "Type of the group socket");
-}
-
-/* ***************** Remove Group Socket operator ************* */
-
-static int node_group_socket_remove_exec(bContext *C, wmOperator *op)
-{
- SpaceNode *snode = CTX_wm_space_node(C);
- int index = -1;
- int in_out = -1;
- bNodeTree *ngroup = snode->edittree;
- bNodeSocket *sock;
-
- ED_preview_kill_jobs(C);
-
- if (RNA_struct_property_is_set(op->ptr, "index"))
- index = RNA_int_get(op->ptr, "index");
- else
- return OPERATOR_CANCELLED;
-
- if (RNA_struct_property_is_set(op->ptr, "in_out"))
- in_out = RNA_enum_get(op->ptr, "in_out");
- else
- return OPERATOR_CANCELLED;
-
- sock = (bNodeSocket *)BLI_findlink(in_out == SOCK_IN ? &ngroup->inputs : &ngroup->outputs, index);
- if (sock) {
- node_group_remove_socket(ngroup, sock, in_out);
- ntreeUpdateTree(ngroup);
-
- snode_notify(C, snode);
- }
-
- return OPERATOR_FINISHED;
-}
-
-void NODE_OT_group_socket_remove(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Remove Group Socket";
- ot->description = "Remove a node group socket";
- ot->idname = "NODE_OT_group_socket_remove";
-
- /* api callbacks */
- ot->exec = node_group_socket_remove_exec;
- ot->poll = ED_operator_node_active;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "", 0, INT_MAX);
- RNA_def_enum(ot->srna, "in_out", socket_in_out_items, SOCK_IN, "Socket Type", "Input or Output");
-}
-
-/* ***************** Move Group Socket Up operator ************* */
-
-static int node_group_socket_move_up_exec(bContext *C, wmOperator *op)
-{
- SpaceNode *snode = CTX_wm_space_node(C);
- int index = -1;
- int in_out = -1;
- bNodeTree *ngroup = snode->edittree;
- bNodeSocket *sock, *prev;
-
- ED_preview_kill_jobs(C);
-
- if (RNA_struct_property_is_set(op->ptr, "index"))
- index = RNA_int_get(op->ptr, "index");
- else
- return OPERATOR_CANCELLED;
-
- if (RNA_struct_property_is_set(op->ptr, "in_out"))
- in_out = RNA_enum_get(op->ptr, "in_out");
- else
- return OPERATOR_CANCELLED;
-
- /* swap */
- if (in_out == SOCK_IN) {
- sock = (bNodeSocket *)BLI_findlink(&ngroup->inputs, index);
- prev = sock->prev;
- /* can't move up the first socket */
- if (!prev)
- return OPERATOR_CANCELLED;
- BLI_remlink(&ngroup->inputs, sock);
- BLI_insertlinkbefore(&ngroup->inputs, prev, sock);
-
- ngroup->update |= NTREE_UPDATE_GROUP_IN;
- }
- else if (in_out == SOCK_OUT) {
- sock = (bNodeSocket *)BLI_findlink(&ngroup->outputs, index);
- prev = sock->prev;
- /* can't move up the first socket */
- if (!prev)
- return OPERATOR_CANCELLED;
- BLI_remlink(&ngroup->outputs, sock);
- BLI_insertlinkbefore(&ngroup->outputs, prev, sock);
-
- ngroup->update |= NTREE_UPDATE_GROUP_OUT;
- }
- ntreeUpdateTree(ngroup);
-
- snode_notify(C, snode);
-
- return OPERATOR_FINISHED;
-}
-
-void NODE_OT_group_socket_move_up(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Move Group Socket Up";
- ot->description = "Move up node group socket";
- ot->idname = "NODE_OT_group_socket_move_up";
-
- /* api callbacks */
- ot->exec = node_group_socket_move_up_exec;
- ot->poll = ED_operator_node_active;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "", 0, INT_MAX);
- RNA_def_enum(ot->srna, "in_out", socket_in_out_items, SOCK_IN, "Socket Type", "Input or Output");
-}
-
-/* ***************** Move Group Socket Up operator ************* */
-
-static int node_group_socket_move_down_exec(bContext *C, wmOperator *op)
-{
- SpaceNode *snode = CTX_wm_space_node(C);
- int index = -1;
- int in_out = -1;
- bNodeTree *ngroup = snode->edittree;
- bNodeSocket *sock, *next;
-
- ED_preview_kill_jobs(C);
-
- if (RNA_struct_property_is_set(op->ptr, "index"))
- index = RNA_int_get(op->ptr, "index");
- else
- return OPERATOR_CANCELLED;
-
- if (RNA_struct_property_is_set(op->ptr, "in_out"))
- in_out = RNA_enum_get(op->ptr, "in_out");
- else
- return OPERATOR_CANCELLED;
-
- /* swap */
- if (in_out == SOCK_IN) {
- sock = (bNodeSocket *)BLI_findlink(&ngroup->inputs, index);
- next = sock->next;
- /* can't move down the last socket */
- if (!next)
- return OPERATOR_CANCELLED;
- BLI_remlink(&ngroup->inputs, sock);
- BLI_insertlinkafter(&ngroup->inputs, next, sock);
-
- ngroup->update |= NTREE_UPDATE_GROUP_IN;
- }
- else if (in_out == SOCK_OUT) {
- sock = (bNodeSocket *)BLI_findlink(&ngroup->outputs, index);
- next = sock->next;
- /* can't move down the last socket */
- if (!next)
- return OPERATOR_CANCELLED;
- BLI_remlink(&ngroup->outputs, sock);
- BLI_insertlinkafter(&ngroup->outputs, next, sock);
-
- ngroup->update |= NTREE_UPDATE_GROUP_OUT;
- }
- ntreeUpdateTree(ngroup);
-
- snode_notify(C, snode);
-
- return OPERATOR_FINISHED;
-}
-
-void NODE_OT_group_socket_move_down(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Move Group Socket Down";
- ot->description = "Move down node group socket";
- ot->idname = "NODE_OT_group_socket_move_down";
-
- /* api callbacks */
- ot->exec = node_group_socket_move_down_exec;
- ot->poll = ED_operator_node_active;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "", 0, INT_MAX);
- RNA_def_enum(ot->srna, "in_out", socket_in_out_items, SOCK_IN, "Socket Type", "Input or Output");
+
+ node_group_operator_properties(ot);
+ RNA_def_boolean(ot->srna, "exit", FALSE, "Exit", "");
}
/* ******************** Ungroup operator ********************** */
@@ -415,180 +221,185 @@ void NODE_OT_group_socket_move_down(wmOperatorType *ot)
/* returns 1 if its OK */
static int node_group_ungroup(bNodeTree *ntree, bNode *gnode)
{
- bNodeLink *link, *linkn;
- bNode *node, *nextn;
+ bNodeLink *link, *linkn, *tlink;
+ bNode *node, *nextnode;
bNodeTree *ngroup, *wgroup;
ListBase anim_basepaths = {NULL, NULL};
-
+
ngroup = (bNodeTree *)gnode->id;
- if (ngroup == NULL) return 0;
-
+
/* clear new pointers, set in copytree */
for (node = ntree->nodes.first; node; node = node->next)
node->new_node = NULL;
-
+
/* wgroup is a temporary copy of the NodeTree we're merging in
* - all of wgroup's nodes are transferred across to their new home
* - ngroup (i.e. the source NodeTree) is left unscathed
* - temp copy. don't change ID usercount
*/
wgroup = ntreeCopyTree_ex(ngroup, FALSE);
-
- /* add the nodes into the ntree */
- for (node = wgroup->nodes.first; node; node = nextn) {
- nextn = node->next;
-
- /* keep track of this node's RNA "base" path (the part of the path identifying the node)
+
+ /* Add the nodes into the ntree */
+ for(node= wgroup->nodes.first; node; node= nextnode) {
+ nextnode= node->next;
+
+ /* Remove interface nodes.
+ * This also removes remaining links to and from interface nodes.
+ */
+ if (ELEM(node->type, NODE_GROUP_INPUT, NODE_GROUP_OUTPUT)) {
+ nodeFreeNode(wgroup, node);
+ continue;
+ }
+
+ /* keep track of this node's RNA "base" path (the part of the path identifying the node)
* if the old nodetree has animation data which potentially covers this node
*/
if (wgroup->adt) {
PointerRNA ptr;
char *path;
-
+
RNA_pointer_create(&wgroup->id, &RNA_Node, node, &ptr);
path = RNA_path_from_ID_to_struct(&ptr);
-
+
if (path)
BLI_addtail(&anim_basepaths, BLI_genericNodeN(path));
}
-
+
/* migrate node */
BLI_remlink(&wgroup->nodes, node);
BLI_addtail(&ntree->nodes, node);
-
- /* ensure unique node name in the nodee tree */
+
+ /* ensure unique node name in the node tree */
nodeUniqueName(ntree, node);
-
+
if (!node->parent) {
node->locx += gnode->locx;
node->locy += gnode->locy;
}
-
+
node->flag |= NODE_SELECT;
}
-
- /* restore external links to and from the gnode */
- for (link = ntree->links.first; link; link = link->next) {
- if (link->fromnode == gnode) {
- if (link->fromsock->groupsock) {
- bNodeSocket *gsock = link->fromsock->groupsock;
- if (gsock->link) {
- if (gsock->link->fromnode) {
- /* NB: using the new internal copies here! the groupsock pointer still maps to the old tree */
- link->fromnode = (gsock->link->fromnode ? gsock->link->fromnode->new_node : NULL);
- link->fromsock = gsock->link->fromsock->new_sock;
- }
- else {
- /* group output directly maps to group input */
- bNodeSocket *insock = node_group_find_input(gnode, gsock->link->fromsock);
- if (insock->link) {
- link->fromnode = insock->link->fromnode;
- link->fromsock = insock->link->fromsock;
- }
- }
- }
- else {
- /* copy the default input value from the group socket default to the external socket */
- node_socket_convert_default_value(link->tosock->type, link->tosock->default_value, gsock->type, gsock->default_value);
- }
- }
- }
- }
- /* remove internal output links, these are not used anymore */
- for (link = wgroup->links.first; link; link = linkn) {
- linkn = link->next;
- if (!link->tonode)
- nodeRemLink(wgroup, link);
- }
- /* restore links from internal nodes */
- for (link = wgroup->links.first; link; link = linkn) {
- linkn = link->next;
- /* indicates link to group input */
- if (!link->fromnode) {
- /* NB: can't use find_group_node_input here,
- * because gnode sockets still point to the old tree!
- */
- bNodeSocket *insock;
- for (insock = gnode->inputs.first; insock; insock = insock->next)
- if (insock->groupsock->new_sock == link->fromsock)
- break;
- if (insock->link) {
- link->fromnode = insock->link->fromnode;
- link->fromsock = insock->link->fromsock;
- }
- else {
- /* copy the default input value from the group node socket default to the internal socket */
- node_socket_convert_default_value(link->tosock->type, link->tosock->default_value, insock->type, insock->default_value);
- nodeRemLink(wgroup, link);
- }
- }
- }
-
- /* add internal links to the ntree */
+
+ /* Add internal links to the ntree */
for (link = wgroup->links.first; link; link = linkn) {
linkn = link->next;
BLI_remlink(&wgroup->links, link);
BLI_addtail(&ntree->links, link);
}
-
+
/* and copy across the animation,
* note that the animation data's action can be NULL here */
if (wgroup->adt) {
LinkData *ld, *ldn = NULL;
bAction *waction;
-
+
/* firstly, wgroup needs to temporary dummy action that can be destroyed, as it shares copies */
waction = wgroup->adt->action = BKE_action_copy(wgroup->adt->action);
-
+
/* now perform the moving */
BKE_animdata_separate_by_basepath(&wgroup->id, &ntree->id, &anim_basepaths);
-
+
/* paths + their wrappers need to be freed */
for (ld = anim_basepaths.first; ld; ld = ldn) {
ldn = ld->next;
-
+
MEM_freeN(ld->data);
BLI_freelinkN(&anim_basepaths, ld);
}
-
+
/* free temp action too */
if (waction) {
BKE_libblock_free(&G.main->action, waction);
}
}
-
- /* delete the group instance. this also removes old input links! */
- nodeFreeNode(ntree, gnode);
-
+
/* free the group tree (takes care of user count) */
BKE_libblock_free(&G.main->nodetree, wgroup);
-
+
+ /* restore external links to and from the gnode */
+ /* note: the nodes have been copied to intermediate wgroup first (so need to use new_node),
+ * then transferred to ntree (new_node pointers remain valid).
+ */
+
+ /* input links */
+ for (link = ngroup->links.first; link; link = link->next) {
+ if (link->fromnode->type == NODE_GROUP_INPUT) {
+ const char *identifier = link->fromsock->identifier;
+ int num_external_links = 0;
+
+ /* find external links to this input */
+ for (tlink = ntree->links.first; tlink; tlink = tlink->next) {
+ if (tlink->tonode == gnode && strcmp(tlink->tosock->identifier, identifier)==0) {
+ nodeAddLink(ntree, tlink->fromnode, tlink->fromsock, link->tonode->new_node, link->tosock->new_sock);
+ ++num_external_links;
+ }
+ }
+
+ /* if group output is not externally linked,
+ * convert the constant input value to ensure somewhat consistent behavior */
+ if (num_external_links == 0) {
+ bNodeSocket *sock = node_group_find_input_socket(gnode, identifier);
+ BLI_assert(sock);
+
+ /* XXX TODO nodeSocketCopy(ntree, link->tosock->new_sock, link->tonode->new_node, ntree, sock, gnode);*/
+ }
+ }
+ }
+
+ /* output links */
+ for (link = ntree->links.first; link; link = link->next) {
+ if (link->fromnode == gnode) {
+ const char *identifier = link->fromsock->identifier;
+ int num_internal_links = 0;
+
+ /* find internal links to this output */
+ for (tlink = ngroup->links.first; tlink; tlink = tlink->next) {
+ /* only use active output node */
+ if (tlink->tonode->type == NODE_GROUP_OUTPUT && (tlink->tonode->flag & NODE_DO_OUTPUT)) {
+ if (strcmp(tlink->tosock->identifier, identifier)==0) {
+ nodeAddLink(ntree, tlink->fromnode->new_node, tlink->fromsock->new_sock, link->tonode, link->tosock);
+ ++num_internal_links;
+ }
+ }
+ }
+
+ /* if group output is not internally linked,
+ * convert the constant output value to ensure somewhat consistent behavior */
+ if (num_internal_links == 0) {
+ bNodeSocket *sock = node_group_find_output_socket(gnode, identifier);
+ BLI_assert(sock);
+
+ /* XXX TODO nodeSocketCopy(ntree, link->tosock, link->tonode, ntree, sock, gnode); */
+ }
+ }
+ }
+
+ /* delete the group instance */
+ nodeFreeNode(ntree, gnode);
+
ntree->update |= NTREE_UPDATE_NODES | NTREE_UPDATE_LINKS;
-
+
return 1;
}
+
static int node_group_ungroup_exec(bContext *C, wmOperator *op)
{
SpaceNode *snode = CTX_wm_space_node(C);
+ char *node_idname;
bNode *gnode;
ED_preview_kill_jobs(C);
- /* are we inside of a group? */
- gnode = node_tree_get_editgroup(snode->nodetree);
- if (gnode)
- snode_make_group_editable(snode, NULL);
-
- gnode = nodeGetActive(snode->edittree);
- if (gnode == NULL)
+ if (!node_group_operator_check_type(C, op, &node_idname, NULL))
+ return OPERATOR_PASS_THROUGH;
+
+ gnode = node_group_get_active(C, node_idname);
+ MEM_freeN(node_idname);
+ if (!gnode)
return OPERATOR_CANCELLED;
-
- if (gnode->type != NODE_GROUP) {
- BKE_report(op->reports, RPT_WARNING, "Not a group");
- return OPERATOR_CANCELLED;
- }
- else if (node_group_ungroup(snode->nodetree, gnode)) {
+
+ if (gnode->id && node_group_ungroup(snode->edittree, gnode)) {
ntreeUpdateTree(snode->nodetree);
}
else {
@@ -608,93 +419,92 @@ void NODE_OT_group_ungroup(wmOperatorType *ot)
ot->name = "Ungroup";
ot->description = "Ungroup selected nodes";
ot->idname = "NODE_OT_group_ungroup";
-
+
/* api callbacks */
ot->exec = node_group_ungroup_exec;
ot->poll = ED_operator_node_active;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ node_group_operator_properties(ot);
}
/* ******************** Separate operator ********************** */
/* returns 1 if its OK */
-static int node_group_separate_selected(bNodeTree *ntree, bNode *gnode, int make_copy)
+static int node_group_separate_selected(bNodeTree *ntree, bNodeTree *ngroup, float offx, float offy, int make_copy)
{
bNodeLink *link, *link_next;
bNode *node, *node_next, *newnode;
- bNodeTree *ngroup;
ListBase anim_basepaths = {NULL, NULL};
-
- ngroup = (bNodeTree *)gnode->id;
- if (ngroup == NULL) return 0;
-
+
/* deselect all nodes in the target tree */
for (node = ntree->nodes.first; node; node = node->next)
- node_deselect(node);
-
+ nodeSetSelected(node, FALSE);
+
/* clear new pointers, set in nodeCopyNode */
for (node = ngroup->nodes.first; node; node = node->next)
node->new_node = NULL;
-
+
/* add selected nodes into the ntree */
for (node = ngroup->nodes.first; node; node = node_next) {
node_next = node->next;
- if (node->flag & NODE_SELECT) {
-
- if (make_copy) {
- /* make a copy */
- newnode = nodeCopyNode(ngroup, node);
- }
- else {
- /* use the existing node */
- newnode = node;
- }
-
- /* keep track of this node's RNA "base" path (the part of the path identifying the node)
- * if the old nodetree has animation data which potentially covers this node
- */
- if (ngroup->adt) {
- PointerRNA ptr;
- char *path;
-
- RNA_pointer_create(&ngroup->id, &RNA_Node, newnode, &ptr);
- path = RNA_path_from_ID_to_struct(&ptr);
-
- if (path)
- BLI_addtail(&anim_basepaths, BLI_genericNodeN(path));
- }
-
- /* ensure valid parent pointers, detach if parent stays inside the group */
- if (newnode->parent && !(newnode->parent->flag & NODE_SELECT))
- nodeDetachNode(newnode);
-
- /* migrate node */
- BLI_remlink(&ngroup->nodes, newnode);
- BLI_addtail(&ntree->nodes, newnode);
+ if (!(node->flag & NODE_SELECT))
+ continue;
+
+ /* ignore interface nodes */
+ if (ELEM(node->type, NODE_GROUP_INPUT, NODE_GROUP_OUTPUT)) {
+ nodeSetSelected(node, FALSE);
+ continue;
+ }
+
+ if (make_copy) {
+ /* make a copy */
+ newnode = nodeCopyNode(ngroup, node);
+ }
+ else {
+ /* use the existing node */
+ newnode = node;
+ }
+
+ /* keep track of this node's RNA "base" path (the part of the path identifying the node)
+ * if the old nodetree has animation data which potentially covers this node
+ */
+ if (ngroup->adt) {
+ PointerRNA ptr;
+ char *path;
- /* ensure unique node name in the node tree */
- nodeUniqueName(ntree, newnode);
+ RNA_pointer_create(&ngroup->id, &RNA_Node, newnode, &ptr);
+ path = RNA_path_from_ID_to_struct(&ptr);
- if (!newnode->parent) {
- newnode->locx += gnode->locx;
- newnode->locy += gnode->locy;
- }
+ if (path)
+ BLI_addtail(&anim_basepaths, BLI_genericNodeN(path));
}
- else {
- /* ensure valid parent pointers, detach if child stays inside the group */
- if (node->parent && (node->parent->flag & NODE_SELECT))
- nodeDetachNode(node);
+
+ /* ensure valid parent pointers, detach if parent stays inside the group */
+ if (newnode->parent && !(newnode->parent->flag & NODE_SELECT))
+ nodeDetachNode(newnode);
+
+ /* migrate node */
+ BLI_remlink(&ngroup->nodes, newnode);
+ BLI_addtail(&ntree->nodes, newnode);
+
+ /* ensure unique node name in the node tree */
+ nodeUniqueName(ntree, newnode);
+
+ if (!newnode->parent) {
+ newnode->locx += offx;
+ newnode->locy += offy;
}
}
-
+
/* add internal links to the ntree */
for (link = ngroup->links.first; link; link = link_next) {
int fromselect = (link->fromnode && (link->fromnode->flag & NODE_SELECT));
int toselect = (link->tonode && (link->tonode->flag & NODE_SELECT));
link_next = link->next;
-
+
if (make_copy) {
/* make a copy of internal links */
if (fromselect && toselect)
@@ -711,28 +521,28 @@ static int node_group_separate_selected(bNodeTree *ntree, bNode *gnode, int make
}
}
}
-
+
/* and copy across the animation,
* note that the animation data's action can be NULL here */
if (ngroup->adt) {
LinkData *ld, *ldn = NULL;
-
+
/* now perform the moving */
BKE_animdata_separate_by_basepath(&ngroup->id, &ntree->id, &anim_basepaths);
-
+
/* paths + their wrappers need to be freed */
for (ld = anim_basepaths.first; ld; ld = ldn) {
ldn = ld->next;
-
+
MEM_freeN(ld->data);
BLI_freelinkN(&anim_basepaths, ld);
}
}
-
+
ntree->update |= NTREE_UPDATE_NODES | NTREE_UPDATE_LINKS;
if (!make_copy)
ngroup->update |= NTREE_UPDATE_NODES | NTREE_UPDATE_LINKS;
-
+
return 1;
}
@@ -751,56 +561,64 @@ EnumPropertyItem node_group_separate_types[] = {
static int node_group_separate_exec(bContext *C, wmOperator *op)
{
SpaceNode *snode = CTX_wm_space_node(C);
- bNode *gnode;
+ bNodeTree *ngroup, *nparent;
int type = RNA_enum_get(op->ptr, "type");
+ float offx, offy;
ED_preview_kill_jobs(C);
/* are we inside of a group? */
- gnode = node_tree_get_editgroup(snode->nodetree);
- if (!gnode) {
+ ngroup = snode->edittree;
+ nparent = ED_node_tree_get(snode, 1);
+ if (!nparent) {
BKE_report(op->reports, RPT_WARNING, "Not inside node group");
return OPERATOR_CANCELLED;
}
-
+ /* get node tree offset */
+ snode_group_offset(snode, &offx, &offy);
+
switch (type) {
case NODE_GS_COPY:
- if (!node_group_separate_selected(snode->nodetree, gnode, 1)) {
+ if (!node_group_separate_selected(nparent, ngroup, offx, offy, 1)) {
BKE_report(op->reports, RPT_WARNING, "Cannot separate nodes");
return OPERATOR_CANCELLED;
}
break;
case NODE_GS_MOVE:
- if (!node_group_separate_selected(snode->nodetree, gnode, 0)) {
+ if (!node_group_separate_selected(nparent, ngroup, offx, offy, 0)) {
BKE_report(op->reports, RPT_WARNING, "Cannot separate nodes");
return OPERATOR_CANCELLED;
}
break;
}
-
+
/* switch to parent tree */
- snode_make_group_editable(snode, NULL);
-
+ ED_node_tree_pop(snode);
+
ntreeUpdateTree(snode->nodetree);
-
+
snode_notify(C, snode);
snode_dag_update(C, snode);
return OPERATOR_FINISHED;
}
-static int node_group_separate_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event))
+static int node_group_separate_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- uiPopupMenu *pup = uiPupMenuBegin(C, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Separate"), ICON_NONE);
- uiLayout *layout = uiPupMenuLayout(pup);
-
- uiLayoutSetOperatorContext(layout, WM_OP_EXEC_DEFAULT);
- uiItemEnumO(layout, "NODE_OT_group_separate", NULL, 0, "type", NODE_GS_COPY);
- uiItemEnumO(layout, "NODE_OT_group_separate", NULL, 0, "type", NODE_GS_MOVE);
-
- uiPupMenuEnd(C, pup);
-
- return OPERATOR_CANCELLED;
+ if (!node_group_operator_check_type(C, op, NULL, NULL))
+ return OPERATOR_PASS_THROUGH;
+ else {
+ uiPopupMenu *pup = uiPupMenuBegin(C, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Separate"), ICON_NONE);
+ uiLayout *layout = uiPupMenuLayout(pup);
+
+ uiLayoutSetOperatorContext(layout, WM_OP_EXEC_DEFAULT);
+ uiItemEnumO(layout, "NODE_OT_group_separate", NULL, 0, "type", NODE_GS_COPY);
+ uiItemEnumO(layout, "NODE_OT_group_separate", NULL, 0, "type", NODE_GS_MOVE);
+
+ uiPupMenuEnd(C, pup);
+
+ return OPERATOR_CANCELLED;
+ }
}
void NODE_OT_group_separate(wmOperatorType *ot)
@@ -809,162 +627,181 @@ void NODE_OT_group_separate(wmOperatorType *ot)
ot->name = "Separate";
ot->description = "Separate selected nodes from the node group";
ot->idname = "NODE_OT_group_separate";
-
+
/* api callbacks */
ot->invoke = node_group_separate_invoke;
ot->exec = node_group_separate_exec;
ot->poll = ED_operator_node_active;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
+ node_group_operator_properties(ot);
RNA_def_enum(ot->srna, "type", node_group_separate_types, NODE_GS_COPY, "Type", "");
}
/* ****************** Make Group operator ******************* */
-static int node_group_make_test(bNodeTree *ntree, bNode *gnode)
+static int node_group_make_use_node(bNode *node, bNode *gnode)
{
+ return (node != gnode
+ && !ELEM(node->type, NODE_GROUP_INPUT, NODE_GROUP_OUTPUT)
+ && (node->flag & NODE_SELECT));
+}
+
+static int node_group_make_test_selected(bNodeTree *ntree, bNode *gnode, const char *ntree_idname, struct ReportList *reports)
+{
+ bNodeTree *ngroup;
bNode *node;
bNodeLink *link;
- int totnode = 0;
-
- /* is there something to group? also do some clearing */
+ int ok = TRUE;
+
+ /* make a local pseudo node tree to pass to the node poll functions */
+ ngroup = ntreeAddTree(NULL, "Pseudo Node Group", ntree_idname);
+
+ /* check poll functions for selected nodes */
for (node = ntree->nodes.first; node; node = node->next) {
- if (node == gnode)
- continue;
-
- if (node->flag & NODE_SELECT) {
- /* no groups in groups */
- if (node->type == NODE_GROUP)
- return 0;
- totnode++;
+ if (node_group_make_use_node(node, gnode)) {
+ if (!node->typeinfo->poll_instance(node, ngroup)) {
+ BKE_reportf(reports, RPT_WARNING, "Can not add node '%s' in a group", node->name);
+ ok = FALSE;
+ break;
+ }
}
node->done = 0;
}
- if (totnode == 0) return 0;
-
+
+ /* free local pseudo node tree again */
+ ntreeFreeTree(ngroup);
+ MEM_freeN(ngroup);
+ if (!ok)
+ return FALSE;
+
/* check if all connections are OK, no unselected node has both
* inputs and outputs to a selection */
for (link = ntree->links.first; link; link = link->next) {
- if (link->fromnode && link->tonode && link->fromnode->flag & NODE_SELECT && link->fromnode != gnode)
+ if (node_group_make_use_node(link->fromnode, gnode))
link->tonode->done |= 1;
- if (link->fromnode && link->tonode && link->tonode->flag & NODE_SELECT && link->tonode != gnode)
+ if (node_group_make_use_node(link->tonode, gnode))
link->fromnode->done |= 2;
}
-
for (node = ntree->nodes.first; node; node = node->next) {
- if (node == gnode)
- continue;
- if ((node->flag & NODE_SELECT) == 0)
- if (node->done == 3)
- break;
+ if (!(node->flag & NODE_SELECT)
+ && node != gnode
+ && node->done == 3)
+ return FALSE;
}
- if (node)
- return 0;
-
- return 1;
+ return TRUE;
}
-
-static void node_get_selected_minmax(bNodeTree *ntree, bNode *gnode, float *min, float *max)
+static int node_get_selected_minmax(bNodeTree *ntree, bNode *gnode, float *min, float *max)
{
bNode *node;
float loc[2];
+ int totselect = 0;
+
INIT_MINMAX2(min, max);
for (node = ntree->nodes.first; node; node = node->next) {
- if (node == gnode)
- continue;
- if (node->flag & NODE_SELECT) {
+ if (node_group_make_use_node(node, gnode)) {
nodeToView(node, 0.0f, 0.0f, &loc[0], &loc[1]);
minmax_v2v2_v2(min, max, loc);
+ ++totselect;
}
}
+
+ /* sane min/max if no selected nodes */
+ if (totselect == 0) {
+ min[0] = min[1] = max[0] = max[1] = 0.0f;
+ }
+
+ return totselect;
}
-static int node_group_make_insert_selected(bNodeTree *ntree, bNode *gnode)
+static void node_group_make_insert_selected(const bContext *C, bNodeTree *ntree, bNode *gnode)
{
bNodeTree *ngroup = (bNodeTree *)gnode->id;
bNodeLink *link, *linkn;
bNode *node, *nextn;
- bNodeSocket *gsock, *sock;
+ bNodeSocket *sock;
ListBase anim_basepaths = {NULL, NULL};
- float min[2], max[2];
-
+ float min[2], max[2], center[2];
+ int totselect;
+ int expose_all = FALSE;
+ bNode *input_node = NULL, *output_node = NULL; /* lazy initialized, in case there are no external links */
+
+ /* XXX rough guess, not nice but we don't have access to UI constants here ... */
+ static const float offsetx = 200;
+ static const float offsety = 0.0f;
+
/* deselect all nodes in the target tree */
for (node = ngroup->nodes.first; node; node = node->next)
- node_deselect(node);
-
- node_get_selected_minmax(ntree, gnode, min, max);
-
+ nodeSetSelected(node, FALSE);
+
+ totselect = node_get_selected_minmax(ntree, gnode, min, max);
+ add_v2_v2v2(center, min, max);
+ mul_v2_fl(center, 0.5f);
+
+ /* auto-add interface for "solo" nodes */
+ if (totselect == 1)
+ expose_all = TRUE;
+
/* move nodes over */
for (node = ntree->nodes.first; node; node = nextn) {
nextn = node->next;
- if (node == gnode)
- continue;
- if (node->flag & NODE_SELECT) {
- /* keep track of this node's RNA "base" path (the part of the pat identifying the node)
+ if (node_group_make_use_node(node, gnode)) {
+ /* keep track of this node's RNA "base" path (the part of the pat identifying the node)
* if the old nodetree has animation data which potentially covers this node
*/
if (ntree->adt) {
PointerRNA ptr;
char *path;
-
+
RNA_pointer_create(&ntree->id, &RNA_Node, node, &ptr);
path = RNA_path_from_ID_to_struct(&ptr);
-
+
if (path)
BLI_addtail(&anim_basepaths, BLI_genericNodeN(path));
}
-
+
/* ensure valid parent pointers, detach if parent stays outside the group */
if (node->parent && !(node->parent->flag & NODE_SELECT))
nodeDetachNode(node);
-
+
/* change node-collection membership */
BLI_remlink(&ntree->nodes, node);
BLI_addtail(&ngroup->nodes, node);
-
+
/* ensure unique node name in the ngroup */
nodeUniqueName(ngroup, node);
-
- if (!node->parent) {
- node->locx -= 0.5f * (min[0] + max[0]);
- node->locy -= 0.5f * (min[1] + max[1]);
- }
- }
- else {
- /* if the parent is to be inserted but not the child, detach properly */
- if (node->parent && (node->parent->flag & NODE_SELECT))
- nodeDetachNode(node);
}
}
-
+
/* move animation data over */
if (ntree->adt) {
LinkData *ld, *ldn = NULL;
-
+
BKE_animdata_separate_by_basepath(&ntree->id, &ngroup->id, &anim_basepaths);
-
+
/* paths + their wrappers need to be freed */
for (ld = anim_basepaths.first; ld; ld = ldn) {
ldn = ld->next;
-
+
MEM_freeN(ld->data);
BLI_freelinkN(&anim_basepaths, ld);
}
}
-
+
/* node groups don't use internal cached data */
ntreeFreeCache(ngroup);
-
+
/* relink external sockets */
for (link = ntree->links.first; link; link = linkn) {
- int fromselect = (link->fromnode && (link->fromnode->flag & NODE_SELECT) && link->fromnode != gnode);
- int toselect = (link->tonode && (link->tonode->flag & NODE_SELECT) && link->tonode != gnode);
+ int fromselect = node_group_make_use_node(link->fromnode, gnode);
+ int toselect = node_group_make_use_node(link->tonode, gnode);
+
linkn = link->next;
-
+
if ((fromselect && link->tonode == gnode) || (toselect && link->fromnode == gnode)) {
/* remove all links to/from the gnode.
* this can remove link information, but there's no general way to preserve it.
@@ -976,58 +813,123 @@ static int node_group_make_insert_selected(bNodeTree *ntree, bNode *gnode)
BLI_addtail(&ngroup->links, link);
}
else if (toselect) {
- gsock = node_group_expose_socket(ngroup, link->tosock, SOCK_IN);
- link->tosock->link = nodeAddLink(ngroup, NULL, gsock, link->tonode, link->tosock);
- link->tosock = node_group_add_extern_socket(ntree, &gnode->inputs, SOCK_IN, gsock);
+ bNodeSocket *iosock = ntreeAddSocketInterfaceFromSocket(ngroup, link->tonode, link->tosock);
+ bNodeSocket *input_sock;
+
+ /* lazy init */
+ if (!input_node) {
+ input_node = nodeAddStaticNode(C, ngroup, NODE_GROUP_INPUT);
+
+ input_node->locx = min[0] - center[0] - offsetx;
+ input_node->locy = -offsety;
+ }
+ /* update the group node and interface node sockets,
+ * so the new interface socket can be linked.
+ */
+ node_group_verify(ntree, gnode, (ID *)ngroup);
+ node_group_input_verify(ngroup, input_node, (ID *)ngroup);
+
+ /* create new internal link */
+ input_sock = node_group_input_find_socket(input_node, iosock->identifier);
+ nodeAddLink(ngroup, input_node, input_sock, link->tonode, link->tosock);
+
+ /* redirect external link */
link->tonode = gnode;
+ link->tosock = node_group_find_input_socket(gnode, iosock->identifier);
}
else if (fromselect) {
- /* search for existing group node socket */
- for (gsock = ngroup->outputs.first; gsock; gsock = gsock->next)
- if (gsock->link && gsock->link->fromsock == link->fromsock)
- break;
- if (!gsock) {
- gsock = node_group_expose_socket(ngroup, link->fromsock, SOCK_OUT);
- gsock->link = nodeAddLink(ngroup, link->fromnode, link->fromsock, NULL, gsock);
- link->fromsock = node_group_add_extern_socket(ntree, &gnode->outputs, SOCK_OUT, gsock);
+ bNodeSocket *iosock = ntreeAddSocketInterfaceFromSocket(ngroup, link->fromnode, link->fromsock);
+ bNodeSocket *output_sock;
+
+ /* lazy init */
+ if (!output_node) {
+ output_node = nodeAddStaticNode(C, ngroup, NODE_GROUP_OUTPUT);
+
+ output_node->locx = max[0] - center[0] + offsetx;
+ output_node->locy = -offsety;
}
- else
- link->fromsock = node_group_find_output(gnode, gsock);
+ /* update the group node and interface node sockets,
+ * so the new interface socket can be linked.
+ */
+ node_group_verify(ntree, gnode, (ID *)ngroup);
+ node_group_output_verify(ngroup, output_node, (ID *)ngroup);
+
+ /* create new internal link */
+ output_sock = node_group_output_find_socket(output_node, iosock->identifier);
+ nodeAddLink(ngroup, link->fromnode, link->fromsock, output_node, output_sock);
+
+ /* redirect external link */
link->fromnode = gnode;
+ link->fromsock = node_group_find_output_socket(gnode, iosock->identifier);
}
}
- /* auto-add interface for "solo" nodes */
- node = ((bNodeTree *)gnode->id)->nodes.first;
- if (node && !node->next) {
- for (sock = node->inputs.first; sock; sock = sock->next) {
- int skip = FALSE;
-
- for (link = ((bNodeTree *)gnode->id)->links.first; link; link = link->next)
- if (link->tosock == sock)
- skip = TRUE;
-
- if (skip == TRUE)
- continue;
-
- gsock = node_group_expose_socket(ngroup, sock, SOCK_IN);
- node_group_add_extern_socket(ntree, &gnode->inputs, SOCK_IN, gsock);
- nodeAddLink(ngroup, NULL, gsock, node, sock);
+ /* move nodes in the group to the center */
+ for (node = ngroup->nodes.first; node; node = node->next) {
+ if (node_group_make_use_node(node, gnode) && !node->parent) {
+ node->locx -= center[0];
+ node->locy -= center[1];
}
-
- for (sock = node->outputs.first; sock; sock = sock->next) {
- int skip = FALSE;
-
- for (link = ((bNodeTree *)gnode->id)->links.first; link; link = link->next)
- if (link->fromsock == sock)
- skip = TRUE;
-
- if (skip == TRUE)
- continue;
-
- gsock = node_group_expose_socket(ngroup, sock, SOCK_OUT);
- node_group_add_extern_socket(ntree, &gnode->outputs, SOCK_OUT, gsock);
- nodeAddLink(ngroup, NULL, gsock, node, sock);
+ }
+
+ /* expose all unlinked sockets too */
+ if (expose_all) {
+ for (node = ngroup->nodes.first; node; node = node->next) {
+ if (node_group_make_use_node(node, gnode)) {
+ for (sock = node->inputs.first; sock; sock = sock->next) {
+ bNodeSocket *iosock, *input_sock;
+ int skip = FALSE;
+ for (link = ngroup->links.first; link; link = link->next) {
+ if (link->tosock == sock) {
+ skip = TRUE;
+ break;
+ }
+ }
+ if (skip)
+ continue;
+
+ iosock = ntreeAddSocketInterfaceFromSocket(ngroup, node, sock);
+
+ /* lazy init */
+ if (!input_node) {
+ input_node = nodeAddStaticNode(C, ngroup, NODE_GROUP_INPUT);
+
+ input_node->locx = min[0] - center[0] - offsetx;
+ input_node->locy = -offsety;
+ }
+ node_group_input_verify(ngroup, input_node, (ID *)ngroup);
+
+ /* create new internal link */
+ input_sock = node_group_input_find_socket(input_node, iosock->identifier);
+ nodeAddLink(ngroup, input_node, input_sock, node, sock);
+ }
+
+ for (sock = node->outputs.first; sock; sock = sock->next) {
+ bNodeSocket *iosock, *output_sock;
+ int skip = FALSE;
+ for (link = ngroup->links.first; link; link = link->next)
+ if (link->fromsock == sock)
+ skip = TRUE;
+ if (skip)
+ continue;
+
+ iosock = ntreeAddSocketInterfaceFromSocket(ngroup, node, sock);
+
+ /* lazy init */
+ if (!output_node) {
+ output_node = nodeAddStaticNode(C, ngroup, NODE_GROUP_OUTPUT);
+
+ output_node->locx = max[0] - center[0] + offsetx;
+ output_node->locy = -offsety;
+ }
+
+ node_group_output_verify(ngroup, output_node, (ID *)ngroup);
+
+ /* create new internal link */
+ output_sock = node_group_output_find_socket(output_node, iosock->identifier);
+ nodeAddLink(ngroup, node, sock, output_node, output_sock);
+ }
+ }
}
}
@@ -1035,30 +937,32 @@ static int node_group_make_insert_selected(bNodeTree *ntree, bNode *gnode)
ngroup->update |= NTREE_UPDATE | NTREE_UPDATE_LINKS;
/* update of the tree containing the group instance node */
ntree->update |= NTREE_UPDATE_NODES | NTREE_UPDATE_LINKS;
-
- return 1;
}
-static bNode *node_group_make_from_selected(bNodeTree *ntree)
+static bNode *node_group_make_from_selected(const bContext *C, bNodeTree *ntree, const char *ntype, const char *ntreetype)
{
+ Main *bmain = CTX_data_main(C);
bNode *gnode;
bNodeTree *ngroup;
float min[2], max[2];
- bNodeTemplate ntemp;
-
- node_get_selected_minmax(ntree, NULL, min, max);
-
+ int totselect;
+
+ totselect = node_get_selected_minmax(ntree, NULL, min, max);
+ /* don't make empty group */
+ if (totselect == 0)
+ return NULL;
+
/* new nodetree */
- ngroup = ntreeAddTree(G.main, "NodeGroup", ntree->type, NODE_GROUP);
-
+ ngroup = ntreeAddTree(bmain, "NodeGroup", ntreetype);
+
/* make group node */
- ntemp.type = NODE_GROUP;
- ntemp.ngroup = ngroup;
- gnode = nodeAddNode(ntree, &ntemp);
+ gnode = nodeAddNode(C, ntree, ntype);
+ gnode->id = (ID *)ngroup;
+
gnode->locx = 0.5f * (min[0] + max[0]);
gnode->locy = 0.5f * (min[1] + max[1]);
-
- node_group_make_insert_selected(ntree, gnode);
+
+ node_group_make_insert_selected(C, ntree, gnode);
/* update of the tree containing the group instance node */
ntree->update |= NTREE_UPDATE_NODES;
@@ -1066,120 +970,116 @@ static bNode *node_group_make_from_selected(bNodeTree *ntree)
return gnode;
}
-typedef enum eNodeGroupMakeType {
- NODE_GM_NEW,
- NODE_GM_INSERT
-} eNodeGroupMakeType;
-
-/* Operator Property */
-EnumPropertyItem node_group_make_types[] = {
- {NODE_GM_NEW, "NEW", 0, "New", "Create a new node group from selected nodes"},
- {NODE_GM_INSERT, "INSERT", 0, "Insert", "Insert into active node group"},
- {0, NULL, 0, NULL, NULL}
-};
-
static int node_group_make_exec(bContext *C, wmOperator *op)
{
SpaceNode *snode = CTX_wm_space_node(C);
+ bNodeTree *ntree = snode->edittree;
+ char *node_idname, *ntree_idname;
+ bNodeTree *ngroup;
bNode *gnode;
- int type = RNA_enum_get(op->ptr, "type");
-
- if (snode->edittree != snode->nodetree) {
- BKE_report(op->reports, RPT_WARNING, "Cannot add a new group in a group");
- return OPERATOR_CANCELLED;
- }
-
- /* for time being... is too complex to handle */
- if (snode->treetype == NTREE_COMPOSIT) {
- for (gnode = snode->nodetree->nodes.first; gnode; gnode = gnode->next) {
- if (gnode->flag & SELECT)
- if (gnode->type == CMP_NODE_R_LAYERS)
- break;
- }
-
- if (gnode) {
- BKE_report(op->reports, RPT_WARNING, "Cannot add a Render Layers node in a group");
- return OPERATOR_CANCELLED;
- }
- }
-
+
ED_preview_kill_jobs(C);
-
- switch (type) {
- case NODE_GM_NEW:
- if (node_group_make_test(snode->nodetree, NULL)) {
- gnode = node_group_make_from_selected(snode->nodetree);
- }
- else {
- BKE_report(op->reports, RPT_WARNING, "Cannot make group");
- return OPERATOR_CANCELLED;
- }
- break;
- case NODE_GM_INSERT:
- gnode = nodeGetActive(snode->nodetree);
- if (!gnode || gnode->type != NODE_GROUP) {
- BKE_report(op->reports, RPT_WARNING, "No active group node");
- return OPERATOR_CANCELLED;
- }
- if (node_group_make_test(snode->nodetree, gnode)) {
- node_group_make_insert_selected(snode->nodetree, gnode);
- }
- else {
- BKE_report(op->reports, RPT_WARNING, "Cannot insert into group");
- return OPERATOR_CANCELLED;
- }
- break;
+
+ if (!node_group_operator_check_type(C, op, &node_idname, &ntree_idname))
+ return OPERATOR_PASS_THROUGH;
+
+ if (!node_group_make_test_selected(ntree, NULL, ntree_idname, op->reports)) {
+ MEM_freeN(node_idname);
+ MEM_freeN(ntree_idname);
+ return OPERATOR_CANCELLED;
}
-
+
+ gnode = node_group_make_from_selected(C, ntree, node_idname, ntree_idname);
+ MEM_freeN(node_idname);
+ MEM_freeN(ntree_idname);
+
if (gnode) {
- nodeSetActive(snode->nodetree, gnode);
- snode_make_group_editable(snode, gnode);
+ ngroup = (bNodeTree *)gnode->id;
+
+ nodeSetActive(ntree, gnode);
+ if (ngroup) {
+ ED_node_tree_push(snode, ngroup, gnode);
+ ntreeUpdateTree(ngroup);
+ }
}
-
- if (gnode)
- ntreeUpdateTree((bNodeTree *)gnode->id);
- ntreeUpdateTree(snode->nodetree);
+
+ ntreeUpdateTree(ntree);
snode_notify(C, snode);
snode_dag_update(C, snode);
-
+
return OPERATOR_FINISHED;
}
-static int node_group_make_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event))
-{
- SpaceNode *snode = CTX_wm_space_node(C);
- bNode *act = nodeGetActive(snode->edittree);
- uiPopupMenu *pup = uiPupMenuBegin(C, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Make Group"), ICON_NONE);
- uiLayout *layout = uiPupMenuLayout(pup);
-
- uiLayoutSetOperatorContext(layout, WM_OP_EXEC_DEFAULT);
- uiItemEnumO(layout, "NODE_OT_group_make", NULL, 0, "type", NODE_GM_NEW);
-
- /* if active node is a group, add insert option */
- if (act && act->type == NODE_GROUP) {
- uiItemEnumO(layout, "NODE_OT_group_make", NULL, 0, "type", NODE_GM_INSERT);
- }
-
- uiPupMenuEnd(C, pup);
-
- return OPERATOR_CANCELLED;
-}
-
void NODE_OT_group_make(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Group";
+ ot->name = "Make Group";
ot->description = "Make group from selected nodes";
ot->idname = "NODE_OT_group_make";
-
+
/* api callbacks */
- ot->invoke = node_group_make_invoke;
ot->exec = node_group_make_exec;
ot->poll = ED_operator_node_active;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ node_group_operator_properties(ot);
+}
- RNA_def_enum(ot->srna, "type", node_group_make_types, NODE_GM_NEW, "Type", "");
+/* ****************** Group Insert operator ******************* */
+
+static int node_group_insert_exec(bContext *C, wmOperator *op)
+{
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNodeTree *ntree = snode->edittree;
+ bNodeTree *ngroup;
+ char *node_idname;
+ bNode *gnode;
+
+ ED_preview_kill_jobs(C);
+
+ if (!node_group_operator_check_type(C, op, &node_idname, NULL))
+ return OPERATOR_PASS_THROUGH;
+
+ gnode = node_group_get_active(C, node_idname);
+ MEM_freeN(node_idname);
+
+ if (!gnode || !gnode->id)
+ return OPERATOR_CANCELLED;
+
+ ngroup = (bNodeTree *)gnode->id;
+ if (!node_group_make_test_selected(ntree, gnode, ngroup->idname, op->reports))
+ return OPERATOR_CANCELLED;
+
+ node_group_make_insert_selected(C, ntree, gnode);
+
+ nodeSetActive(ntree, gnode);
+ ED_node_tree_push(snode, ngroup, gnode);
+ ntreeUpdateTree(ngroup);
+
+ ntreeUpdateTree(ntree);
+
+ snode_notify(C, snode);
+ snode_dag_update(C, snode);
+
+ return OPERATOR_FINISHED;
+}
+
+void NODE_OT_group_insert(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Group Insert";
+ ot->description = "Insert selected nodes into a node group";
+ ot->idname = "NODE_OT_group_insert";
+
+ /* api callbacks */
+ ot->exec = node_group_insert_exec;
+ ot->poll = ED_operator_node_active;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ node_group_operator_properties(ot);
}
diff --git a/source/blender/editors/space_node/node_header.c b/source/blender/editors/space_node/node_header.c
index f26b6ff0f54..175bbce756e 100644
--- a/source/blender/editors/space_node/node_header.c
+++ b/source/blender/editors/space_node/node_header.c
@@ -58,186 +58,21 @@
/* ************************ add menu *********************** */
-static void do_node_add(bContext *C, bNodeTemplate *ntemp)
-{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- SpaceNode *snode = CTX_wm_space_node(C);
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar;
- bNode *node, *node_new;
-
- /* get location to add node at mouse */
- for (ar = sa->regionbase.first; ar; ar = ar->next) {
- if (ar->regiontype == RGN_TYPE_WINDOW) {
- wmWindow *win = CTX_wm_window(C);
- int x = win->eventstate->x - ar->winrct.xmin;
- int y = win->eventstate->y - ar->winrct.ymin;
-
- if (y < 60) y += 60;
- UI_view2d_region_to_view(&ar->v2d, x, y, &snode->cursor[0], &snode->cursor[1]);
- }
- }
-
- /* store selection in temp test flag */
- for (node = snode->edittree->nodes.first; node; node = node->next) {
- if (node->flag & NODE_SELECT) node->flag |= NODE_TEST;
- else node->flag &= ~NODE_TEST;
- }
-
- node_new = node_add_node(snode, bmain, scene, ntemp, snode->cursor[0], snode->cursor[1]);
-
- /* select previous selection before autoconnect */
- for (node = snode->edittree->nodes.first; node; node = node->next) {
- if (node->flag & NODE_TEST) node->flag |= NODE_SELECT;
- }
-
- /* deselect after autoconnection */
- for (node = snode->edittree->nodes.first; node; node = node->next) {
- if (node->flag & NODE_TEST) node->flag &= ~NODE_SELECT;
- }
-
- /* once this is called from an operator, this should be removed */
- if (node_new) {
- char undostr[BKE_UNDO_STR_MAX];
- BLI_snprintf(undostr, sizeof(undostr), "Add Node %s", nodeLabel(node_new));
- BKE_write_undo(C, undostr);
- }
-
- snode_notify(C, snode);
- snode_dag_update(C, snode);
-}
-
-static void do_node_add_static(bContext *C, void *UNUSED(arg), int event)
-{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- bNodeTemplate ntemp;
-
- ntemp.type = event;
- ntemp.main = bmain;
- ntemp.scene = scene;
-
- do_node_add(C, &ntemp);
-}
-
-static void do_node_add_group(bContext *C, void *UNUSED(arg), int event)
-{
- SpaceNode *snode = CTX_wm_space_node(C);
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- bNodeTemplate ntemp;
-
- if (event >= 0) {
- ntemp.ngroup = BLI_findlink(&G.main->nodetree, event);
- ntemp.type = ntemp.ngroup->nodetype;
- }
- else {
- ntemp.type = -event;
- switch (ntemp.type) {
- case NODE_GROUP:
- ntemp.ngroup = ntreeAddTree(bmain, "Group", snode->treetype, ntemp.type);
- break;
- default:
- ntemp.ngroup = NULL;
- }
- }
- if (!ntemp.ngroup)
- return;
-
- ntemp.main = bmain;
- ntemp.scene = scene;
-
- do_node_add(C, &ntemp);
-}
-
-static int node_tree_has_type(int treetype, int nodetype)
-{
- bNodeTreeType *ttype = ntreeGetType(treetype);
- bNodeType *ntype;
- for (ntype = ttype->node_types.first; ntype; ntype = ntype->next) {
- if (ntype->type == nodetype)
- return 1;
- }
- return 0;
-}
-
-static void node_add_menu(bContext *C, uiLayout *layout, void *arg_nodeclass)
-{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- SpaceNode *snode = CTX_wm_space_node(C);
- bNodeTree *ntree;
- int nodeclass = GET_INT_FROM_POINTER(arg_nodeclass);
- int event, compatibility = 0;
-
- ntree = snode->nodetree;
-
- if (!ntree) {
- uiItemS(layout);
- return;
- }
-
- if (ntree->type == NTREE_SHADER) {
- if (BKE_scene_use_new_shading_nodes(scene))
- compatibility = NODE_NEW_SHADING;
- else
- compatibility = NODE_OLD_SHADING;
- }
-
- if (nodeclass == NODE_CLASS_GROUP) {
- bNodeTree *ngroup;
-
- uiLayoutSetFunc(layout, do_node_add_group, NULL);
-
- /* XXX hack: negative numbers used for empty group types */
- if (node_tree_has_type(ntree->type, NODE_GROUP))
- uiItemV(layout, IFACE_("New Group"), 0, -NODE_GROUP);
- uiItemS(layout);
-
- for (ngroup = bmain->nodetree.first, event = 0; ngroup; ngroup = ngroup->id.next, ++event) {
- /* only use group trees */
- if (ngroup->type == ntree->type && ngroup->nodetype == NODE_GROUP) {
- uiItemV(layout, ngroup->id.name + 2, 0, event);
- }
- }
- }
- else {
- bNodeType *ntype;
-
- uiLayoutSetFunc(layout, do_node_add_static, NULL);
-
- for (ntype = ntreeGetType(ntree->type)->node_types.first; ntype; ntype = ntype->next) {
- if (ntype->nclass == nodeclass && ntype->name) {
- if (!compatibility || (ntype->compatibility & compatibility)) {
- uiItemV(layout, IFACE_(ntype->name), 0, ntype->type);
- }
- }
- }
- }
-}
-
-static void node_menu_add_foreach_cb(void *calldata, int nclass, const char *name)
-{
- uiLayout *layout = calldata;
- uiItemMenuF(layout, IFACE_(name), 0, node_add_menu, SET_INT_IN_POINTER(nclass));
-}
-
static void node_menu_add(const bContext *C, Menu *menu)
{
- Scene *scene = CTX_data_scene(C);
SpaceNode *snode = CTX_wm_space_node(C);
uiLayout *layout = menu->layout;
- bNodeTreeType *ntreetype = ntreeGetType(snode->treetype);
+ bNodeTree *ntree = snode->edittree;
- if (!snode->nodetree)
+ if (!ntree || !ntree->typeinfo || !ntree->typeinfo->draw_add_menu) {
uiLayoutSetActive(layout, FALSE);
-
+ return;
+ }
+
uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT);
uiItemO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Search ..."), 0, "NODE_OT_add_search");
- if (ntreetype && ntreetype->foreach_nodeclass)
- ntreetype->foreach_nodeclass(scene, layout, node_menu_add_foreach_cb);
+ ntree->typeinfo->draw_add_menu(C, layout, ntree);
}
void node_menus_register(void)
diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h
index cbf7101a101..a24da7143f9 100644
--- a/source/blender/editors/space_node/node_intern.h
+++ b/source/blender/editors/space_node/node_intern.h
@@ -32,6 +32,7 @@
#define __NODE_INTERN_H__
#include <stddef.h> /* for size_t */
+#include "BKE_node.h"
#include "UI_interface.h"
/* internal exports only */
@@ -43,7 +44,6 @@ struct bContext;
struct wmWindow;
struct wmWindowManager;
struct wmEvent;
-struct bNodeTemplate;
struct bNode;
struct bNodeSocket;
struct bNodeLink;
@@ -66,21 +66,26 @@ typedef struct bNodeLinkDrag {
ARegion *node_has_buttons_region(ScrArea *sa);
ARegion *node_has_tools_region(ScrArea *sa);
+void snode_group_offset(struct SpaceNode *snode, float *x, float *y); /* transform between View2Ds in the tree path */
+
/* node_header.c */
void node_menus_register(void);
/* node_draw.c */
int node_get_colorid(struct bNode *node);
-void node_socket_circle_draw(struct bNodeTree *ntree, struct bNodeSocket *sock, float size, int highlight);
+void node_socket_circle_draw(const struct bContext *C, struct bNodeTree *ntree, struct bNode *node,
+ struct bNodeSocket *sock, float size, int highlight);
int node_get_resize_cursor(int directions);
void node_draw_shadow(struct SpaceNode *snode, struct bNode *node, float radius, float alpha);
-void node_draw_default(const struct bContext *C, struct ARegion *ar, struct SpaceNode *snode, struct bNodeTree *ntree, struct bNode *node);
+void node_draw_default(const struct bContext *C, struct ARegion *ar, struct SpaceNode *snode,
+ struct bNodeTree *ntree, struct bNode *node, bNodeInstanceKey key);
void node_update_default(const struct bContext *C, struct bNodeTree *ntree, struct bNode *node);
int node_select_area_default(struct bNode *node, int x, int y);
int node_tweak_area_default(struct bNode *node, int x, int y);
-void node_update_nodetree(const struct bContext *C, struct bNodeTree *ntree, float offsetx, float offsety);
-void node_draw_nodetree(const struct bContext *C, struct ARegion *ar, struct SpaceNode *snode, struct bNodeTree *ntree);
-void drawnodespace(const bContext *C, ARegion *ar, View2D *v2d);
+void node_update_nodetree(const struct bContext *C, struct bNodeTree *ntree);
+void node_draw_nodetree(const struct bContext *C, struct ARegion *ar, struct SpaceNode *snode,
+ struct bNodeTree *ntree, bNodeInstanceKey parent_key);
+void drawnodespace(const bContext *C, ARegion *ar);
void node_set_cursor(struct wmWindow *win, struct SpaceNode *snode);
/* DPI scaled coords */
@@ -100,8 +105,6 @@ void node_operatortypes(void);
void node_keymap(struct wmKeyConfig *keyconf);
/* node_select.c */
-void node_select(struct bNode *node);
-void node_deselect(struct bNode *node);
void node_deselect_all(struct SpaceNode *snode);
void node_socket_select(struct bNode *node, struct bNodeSocket *sock);
void node_socket_deselect(struct bNode *node, struct bNodeSocket *sock, int deselect_node);
@@ -138,13 +141,15 @@ void draw_nodespace_back_pix(const struct bContext *C, struct ARegion *ar, struc
/* node_add.c */
-bNode *node_add_node(struct SpaceNode *snode, struct Main *bmain, struct Scene *scene,
- struct bNodeTemplate *ntemp, float locx, float locy);
+bNode *node_add_node(const struct bContext *C, const char *idname, int type, float locx, float locy);
void NODE_OT_add_reroute(struct wmOperatorType *ot);
+void NODE_OT_add_file(struct wmOperatorType *ot);
+void NODE_OT_new_node_tree(struct wmOperatorType *ot);
/* node_group.c */
void NODE_OT_group_make(struct wmOperatorType *ot);
+void NODE_OT_group_insert(struct wmOperatorType *ot);
void NODE_OT_group_ungroup(struct wmOperatorType *ot);
void NODE_OT_group_separate(struct wmOperatorType *ot);
void NODE_OT_group_edit(struct wmOperatorType *ot);
@@ -154,11 +159,6 @@ void NODE_OT_group_socket_move_up(struct wmOperatorType *ot);
void NODE_OT_group_socket_move_down(struct wmOperatorType *ot);
-/* note_add.c */
-void NODE_OT_add_file(struct wmOperatorType *ot);
-void NODE_OT_new_node_tree(struct wmOperatorType *ot);
-
-
/* node_relationships.c */
void NODE_OT_link(struct wmOperatorType *ot);
void NODE_OT_link_make(struct wmOperatorType *ot);
@@ -175,11 +175,9 @@ void NODE_OT_show_cyclic_dependencies(struct wmOperatorType *ot);
void NODE_OT_link_viewer(struct wmOperatorType *ot);
/* node_edit.c */
-void node_tree_from_ID(ID *id, bNodeTree **ntree, bNodeTree **edittree, int *treetype);
void snode_notify(struct bContext *C, struct SpaceNode *snode);
void snode_dag_update(struct bContext *C, struct SpaceNode *snode);
-void snode_set_context(struct SpaceNode *snode, Scene *scene);
-void snode_make_group_editable(struct SpaceNode *snode, struct bNode *gnode);
+void snode_set_context(const struct bContext *C);
bNode *node_tree_get_editgroup(bNodeTree *ntree);
void snode_update(struct SpaceNode *snode, struct bNode *node);
@@ -215,6 +213,10 @@ void NODE_OT_output_file_move_active_socket(struct wmOperatorType *ot);
void NODE_OT_clipboard_copy(struct wmOperatorType *ot);
void NODE_OT_clipboard_paste(struct wmOperatorType *ot);
+void NODE_OT_tree_socket_add(struct wmOperatorType *ot);
+void NODE_OT_tree_socket_remove(struct wmOperatorType *ot);
+void NODE_OT_tree_socket_move(struct wmOperatorType *ot);
+
void NODE_OT_shader_script_update(struct wmOperatorType *ot);
void NODE_OT_viewer_border(struct wmOperatorType *ot);
diff --git a/source/blender/editors/space_node/node_ops.c b/source/blender/editors/space_node/node_ops.c
index d16c6627d3f..db664265466 100644
--- a/source/blender/editors/space_node/node_ops.c
+++ b/source/blender/editors/space_node/node_ops.c
@@ -84,13 +84,10 @@ void node_operatortypes(void)
WM_operatortype_append(NODE_OT_add_reroute);
WM_operatortype_append(NODE_OT_group_make);
+ WM_operatortype_append(NODE_OT_group_insert);
WM_operatortype_append(NODE_OT_group_ungroup);
WM_operatortype_append(NODE_OT_group_separate);
WM_operatortype_append(NODE_OT_group_edit);
- WM_operatortype_append(NODE_OT_group_socket_add);
- WM_operatortype_append(NODE_OT_group_socket_remove);
- WM_operatortype_append(NODE_OT_group_socket_move_up);
- WM_operatortype_append(NODE_OT_group_socket_move_down);
WM_operatortype_append(NODE_OT_link_viewer);
@@ -122,6 +119,10 @@ void node_operatortypes(void)
WM_operatortype_append(NODE_OT_shader_script_update);
WM_operatortype_append(NODE_OT_viewer_border);
+
+ WM_operatortype_append(NODE_OT_tree_socket_add);
+ WM_operatortype_append(NODE_OT_tree_socket_remove);
+ WM_operatortype_append(NODE_OT_tree_socket_move);
}
void ED_operatormacros_node(void)
@@ -198,6 +199,29 @@ static void node_select_keymap(wmKeyMap *keymap, int extend)
}
}
+/* register group operators for a specific group node type */
+static void node_group_operators(wmKeyMap *keymap, const char *node_type)
+{
+ wmKeyMapItem *kmi;
+
+ kmi = WM_keymap_add_item(keymap, "NODE_OT_group_make", GKEY, KM_PRESS, KM_CTRL, 0);
+ RNA_string_set(kmi->ptr, "node_type", node_type);
+
+ kmi = WM_keymap_add_item(keymap, "NODE_OT_group_ungroup", GKEY, KM_PRESS, KM_ALT, 0);
+ RNA_string_set(kmi->ptr, "node_type", node_type);
+
+ kmi = WM_keymap_add_item(keymap, "NODE_OT_group_separate", PKEY, KM_PRESS, 0, 0);
+ RNA_string_set(kmi->ptr, "node_type", node_type);
+
+ kmi= WM_keymap_add_item(keymap, "NODE_OT_group_edit", TABKEY, KM_PRESS, 0, 0);
+ RNA_string_set(kmi->ptr, "node_type", node_type);
+ RNA_boolean_set(kmi->ptr, "exit", FALSE);
+
+ kmi= WM_keymap_add_item(keymap, "NODE_OT_group_edit", TABKEY, KM_PRESS, KM_SHIFT, 0);
+ RNA_string_set(kmi->ptr, "node_type", node_type);
+ RNA_boolean_set(kmi->ptr, "exit", TRUE);
+}
+
void node_keymap(struct wmKeyConfig *keyconf)
{
wmKeyMap *keymap;
@@ -230,9 +254,18 @@ void node_keymap(struct wmKeyConfig *keyconf)
RNA_boolean_set(kmi->ptr, "deselect", TRUE);
/* each of these falls through if not handled... */
- WM_keymap_add_item(keymap, "NODE_OT_link", LEFTMOUSE, KM_PRESS, 0, 0);
+ kmi = WM_keymap_add_item(keymap, "NODE_OT_link", LEFTMOUSE, KM_PRESS, 0, 0);
+ RNA_boolean_set(kmi->ptr, "detach", FALSE);
+ RNA_boolean_set(kmi->ptr, "expose", FALSE);
kmi = WM_keymap_add_item(keymap, "NODE_OT_link", LEFTMOUSE, KM_PRESS, KM_CTRL, 0);
RNA_boolean_set(kmi->ptr, "detach", TRUE);
+ RNA_boolean_set(kmi->ptr, "expose", FALSE);
+ kmi = WM_keymap_add_item(keymap, "NODE_OT_link", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0);
+ RNA_boolean_set(kmi->ptr, "detach", FALSE);
+ RNA_boolean_set(kmi->ptr, "expose", TRUE);
+ kmi = WM_keymap_add_item(keymap, "NODE_OT_link", LEFTMOUSE, KM_PRESS, KM_SHIFT|KM_CTRL, 0);
+ RNA_boolean_set(kmi->ptr, "detach", TRUE);
+ RNA_boolean_set(kmi->ptr, "expose", TRUE);
WM_keymap_add_item(keymap, "NODE_OT_resize", LEFTMOUSE, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "NODE_OT_add_reroute", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0);
@@ -288,11 +321,10 @@ void node_keymap(struct wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "NODE_OT_select_same_type_next", RIGHTBRACKETKEY, KM_PRESS, KM_SHIFT, 0);
WM_keymap_add_item(keymap, "NODE_OT_select_same_type_prev", LEFTBRACKETKEY, KM_PRESS, KM_SHIFT, 0);
- WM_keymap_add_item(keymap, "NODE_OT_group_make", GKEY, KM_PRESS, KM_CTRL, 0);
- WM_keymap_add_item(keymap, "NODE_OT_group_ungroup", GKEY, KM_PRESS, KM_ALT, 0);
- WM_keymap_add_item(keymap, "NODE_OT_group_separate", PKEY, KM_PRESS, 0, 0);
- WM_keymap_add_item(keymap, "NODE_OT_group_edit", TABKEY, KM_PRESS, 0, 0);
-
+ node_group_operators(keymap, "ShaderNodeGroup");
+ node_group_operators(keymap, "CompositorNodeGroup");
+ node_group_operators(keymap, "TextureNodeGroup");
+
WM_keymap_add_item(keymap, "NODE_OT_read_renderlayers", RKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "NODE_OT_read_fullsamplelayers", RKEY, KM_PRESS, KM_SHIFT, 0);
WM_keymap_add_item(keymap, "NODE_OT_render_changed", ZKEY, KM_PRESS, 0, 0);
diff --git a/source/blender/editors/space_node/node_relationships.c b/source/blender/editors/space_node/node_relationships.c
index 097e4f418e0..d95487bb24e 100644
--- a/source/blender/editors/space_node/node_relationships.c
+++ b/source/blender/editors/space_node/node_relationships.c
@@ -54,6 +54,7 @@
#include "UI_view2d.h"
#include "node_intern.h" /* own include */
+#include "NOD_common.h"
/* ****************** Add *********************** */
@@ -323,13 +324,8 @@ static int node_link_viewer(const bContext *C, bNode *tonode)
if (sock) {
/* add a new viewer if none exists yet */
if (!node) {
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- bNodeTemplate ntemp;
-
- ntemp.type = CMP_NODE_VIEWER;
/* XXX location is a quick hack, just place it next to the linked socket */
- node = node_add_node(snode, bmain, scene, &ntemp, sock->locx + 100, sock->locy);
+ node = node_add_node(C, NULL, CMP_NODE_VIEWER, sock->locx + 100, sock->locy);
if (!node)
return OPERATOR_CANCELLED;
@@ -364,7 +360,7 @@ static int node_active_link_viewer(bContext *C, wmOperator *UNUSED(op))
SpaceNode *snode = CTX_wm_space_node(C);
bNode *node;
- node = editnode_get_active(snode->edittree);
+ node = nodeGetActive(snode->edittree);
if (!node)
return OPERATOR_CANCELLED;
@@ -434,18 +430,6 @@ static void node_remove_extra_links(SpaceNode *snode, bNodeSocket *tsock, bNodeL
}
}
-static int outside_group_rect(SpaceNode *snode)
-{
- bNode *gnode = node_tree_get_editgroup(snode->nodetree);
- if (gnode) {
- return (snode->cursor[0] < gnode->totr.xmin ||
- snode->cursor[0] >= gnode->totr.xmax ||
- snode->cursor[1] < gnode->totr.ymin ||
- snode->cursor[1] >= gnode->totr.ymax);
- }
- return 0;
-}
-
/* loop that adds a nodelink, called by function below */
/* in_out = starting socket */
static int node_link_modal(bContext *C, wmOperator *op, const wmEvent *event)
@@ -459,55 +443,41 @@ static int node_link_modal(bContext *C, wmOperator *op, const wmEvent *event)
bNodeLink *link;
LinkData *linkdata;
int in_out;
+ int expose;
in_out = nldrag->in_out;
-
+
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1],
&snode->cursor[0], &snode->cursor[1]);
+ expose = RNA_boolean_get(op->ptr, "expose");
+
switch (event->type) {
case MOUSEMOVE:
-
+
if (in_out == SOCK_OUT) {
if (node_find_indicated_socket(snode, &tnode, &tsock, SOCK_IN)) {
for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) {
link = linkdata->data;
-
+
/* skip if this is already the target socket */
if (link->tosock == tsock)
continue;
/* skip if socket is on the same node as the fromsock */
if (tnode && link->fromnode == tnode)
continue;
-
+
/* attach links to the socket */
link->tonode = tnode;
link->tosock = tsock;
- /* add it to the node tree temporarily */
- if (BLI_findindex(&ntree->links, link) < 0)
- BLI_addtail(&ntree->links, link);
-
- ntree->update |= NTREE_UPDATE_LINKS;
}
- ntreeUpdateTree(ntree);
}
else {
- int do_update = FALSE;
for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) {
link = linkdata->data;
-
- if (link->tonode || link->tosock) {
- BLI_remlink(&ntree->links, link);
- link->prev = link->next = NULL;
- link->tonode = NULL;
- link->tosock = NULL;
-
- ntree->update |= NTREE_UPDATE_LINKS;
- do_update = TRUE;
- }
- }
- if (do_update) {
- ntreeUpdateTree(ntree);
+
+ link->tonode = NULL;
+ link->tosock = NULL;
}
}
}
@@ -515,108 +485,126 @@ static int node_link_modal(bContext *C, wmOperator *op, const wmEvent *event)
if (node_find_indicated_socket(snode, &tnode, &tsock, SOCK_OUT)) {
for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) {
link = linkdata->data;
-
+
/* skip if this is already the target socket */
if (link->fromsock == tsock)
continue;
/* skip if socket is on the same node as the fromsock */
if (tnode && link->tonode == tnode)
continue;
-
+
/* attach links to the socket */
link->fromnode = tnode;
link->fromsock = tsock;
- /* add it to the node tree temporarily */
- if (BLI_findindex(&ntree->links, link) < 0)
- BLI_addtail(&ntree->links, link);
-
- ntree->update |= NTREE_UPDATE_LINKS;
}
- ntreeUpdateTree(ntree);
}
else {
- int do_update = FALSE;
for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) {
link = linkdata->data;
-
- if (link->fromnode || link->fromsock) {
- BLI_remlink(&ntree->links, link);
- link->prev = link->next = NULL;
- link->fromnode = NULL;
- link->fromsock = NULL;
-
- ntree->update |= NTREE_UPDATE_LINKS;
- do_update = TRUE;
- }
- }
- if (do_update) {
- ntreeUpdateTree(ntree);
+
+ link->fromnode = NULL;
+ link->fromsock = NULL;
}
}
}
-
+
ED_region_tag_redraw(ar);
break;
-
+
case LEFTMOUSE:
case RIGHTMOUSE:
case MIDDLEMOUSE:
{
+ /* XXX expose + detach could have some ugly corner cases and is not great.
+ * The first link will define the exposed socket type, which is arbitrary.
+ * Some of the resulting links may turn out to be invalid.
+ */
+ bNode *ionode = NULL;
+ bNodeSocket *iosock = NULL, *gsock;
for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) {
link = linkdata->data;
-
+
if (link->tosock && link->fromsock) {
- /* send changed events for original tonode and new */
- if (link->tonode)
- snode_update(snode, link->tonode);
-
+ /* add link to the node tree */
+ BLI_addtail(&ntree->links, link);
+
+ ntree->update |= NTREE_UPDATE_LINKS;
+
+ /* tag tonode for update */
+ link->tonode->update |= NODE_UPDATE;
+
/* we might need to remove a link */
if (in_out == SOCK_OUT)
node_remove_extra_links(snode, link->tosock, link);
-
- /* when linking to group outputs, update the socket type */
- /* XXX this should all be part of a generic update system */
- if (!link->tonode) {
- if (link->tosock->type != link->fromsock->type)
- nodeSocketSetType(link->tosock, link->fromsock->type);
- }
}
- else if (outside_group_rect(snode) && (link->tonode || link->fromnode)) {
- /* automatically add new group socket */
- if (link->tonode && link->tosock) {
- link->fromsock = node_group_expose_socket(ntree, link->tosock, SOCK_IN);
- link->fromnode = NULL;
- if (BLI_findindex(&ntree->links, link) < 0)
- BLI_addtail(&ntree->links, link);
-
+ else if (expose) {
+ if (link->tosock) {
+ if (!ionode) {
+ ionode = nodeAddStaticNode(C, snode->edittree, NODE_GROUP_INPUT);
+ gsock = ntreeAddSocketInterfaceFromSocket(snode->edittree, link->tonode, link->tosock);
+ node_group_input_verify(snode->edittree, ionode, (ID *)snode->edittree);
+ iosock = node_group_input_find_socket(ionode, gsock->identifier);
+
+ {
+ /* place the node at the mouse pointer */
+ float sockx = 42.f + 3*HIDDEN_RAD; /* XXX totally arbitrary initial hidden node size ... */
+ float socky = -HIDDEN_RAD;
+
+ ionode->locx = snode->cursor[0] - sockx;
+ ionode->locy = snode->cursor[1] - socky;
+ }
+ }
+ link->fromnode = ionode;
+ link->fromsock = iosock;
+
+ BLI_addtail(&ntree->links, link);
+
ntree->update |= NTREE_UPDATE_GROUP_IN | NTREE_UPDATE_LINKS;
}
- else if (link->fromnode && link->fromsock) {
- link->tosock = node_group_expose_socket(ntree, link->fromsock, SOCK_OUT);
- link->tonode = NULL;
- if (BLI_findindex(&ntree->links, link) < 0)
- BLI_addtail(&ntree->links, link);
-
+ else if (link->fromsock) {
+ if (!ionode) {
+ ionode = nodeAddStaticNode(C, snode->edittree, NODE_GROUP_OUTPUT);
+ gsock = ntreeAddSocketInterfaceFromSocket(snode->edittree, link->fromnode, link->fromsock);
+ node_group_output_verify(snode->edittree, ionode, (ID *)snode->edittree);
+ iosock = node_group_output_find_socket(ionode, gsock->identifier);
+
+ {
+ /* place the node at the mouse pointer */
+ float sockx = 0;
+ float socky = -HIDDEN_RAD;
+
+ ionode->locx = snode->cursor[0] - sockx;
+ ionode->locy = snode->cursor[1] - socky;
+ }
+ }
+ link->tonode = ionode;
+ link->tosock = iosock;
+
+ BLI_addtail(&ntree->links, link);
+
ntree->update |= NTREE_UPDATE_GROUP_OUT | NTREE_UPDATE_LINKS;
}
+ else {
+ nodeRemLink(snode->edittree, link);
+ }
}
else
nodeRemLink(ntree, link);
}
-
+
ntreeUpdateTree(ntree);
snode_notify(C, snode);
snode_dag_update(C, snode);
-
+
BLI_remlink(&snode->linkdrag, nldrag);
/* links->data pointers are either held by the tree or freed already */
BLI_freelistN(&nldrag->links);
MEM_freeN(nldrag);
-
+
return OPERATOR_FINISHED;
}
}
-
+
return OPERATOR_RUNNING_MODAL;
}
@@ -646,6 +634,8 @@ static bNodeLinkDrag *node_link_init(SpaceNode *snode, int detach)
linkdata->data = oplink = MEM_callocN(sizeof(bNodeLink), "drag link op link");
*oplink = *link;
oplink->next = oplink->prev = NULL;
+ oplink->flag |= NODE_LINK_VALID;
+
BLI_addtail(&nldrag->links, linkdata);
nodeRemLink(snode->edittree, link);
}
@@ -659,6 +649,8 @@ static bNodeLinkDrag *node_link_init(SpaceNode *snode, int detach)
linkdata->data = oplink = MEM_callocN(sizeof(bNodeLink), "drag link op link");
oplink->fromnode = node;
oplink->fromsock = sock;
+ oplink->flag |= NODE_LINK_VALID;
+
BLI_addtail(&nldrag->links, linkdata);
}
}
@@ -678,9 +670,11 @@ static bNodeLinkDrag *node_link_init(SpaceNode *snode, int detach)
linkdata->data = oplink = MEM_callocN(sizeof(bNodeLink), "drag link op link");
*oplink = *link;
oplink->next = oplink->prev = NULL;
+ oplink->flag |= NODE_LINK_VALID;
+
BLI_addtail(&nldrag->links, linkdata);
nodeRemLink(snode->edittree, link);
-
+
/* send changed event to original link->tonode */
if (node)
snode_update(snode, node);
@@ -695,6 +689,8 @@ static bNodeLinkDrag *node_link_init(SpaceNode *snode, int detach)
linkdata->data = oplink = MEM_callocN(sizeof(bNodeLink), "drag link op link");
oplink->tonode = node;
oplink->tosock = sock;
+ oplink->flag |= NODE_LINK_VALID;
+
BLI_addtail(&nldrag->links, linkdata);
}
}
@@ -760,6 +756,7 @@ void NODE_OT_link(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
RNA_def_boolean(ot->srna, "detach", FALSE, "Detach", "Detach and redirect existing links");
+ RNA_def_boolean(ot->srna, "expose", FALSE, "Expose", "Expose the socket as an interface node");
}
/* ********************** Make Link operator ***************** */
@@ -845,6 +842,8 @@ static int cut_links_exec(bContext *C, wmOperator *op)
for (link = snode->edittree->links.first; link; link = next) {
next = link->next;
+ if (nodeLinkIsHidden(link))
+ continue;
if (cut_links_intersect(link, mcoords, i)) {
@@ -1075,11 +1074,8 @@ static void node_join_attach_recursive(bNode *node, bNode *frame)
static int node_join_exec(bContext *C, wmOperator *UNUSED(op))
{
SpaceNode *snode = CTX_wm_space_node(C);
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
bNodeTree *ntree = snode->edittree;
bNode *node, *frame;
- bNodeTemplate ntemp;
/* XXX save selection: node_add_node call below sets the new frame as single active+selected node */
for (node = ntree->nodes.first; node; node = node->next) {
@@ -1089,10 +1085,7 @@ static int node_join_exec(bContext *C, wmOperator *UNUSED(op))
node->flag &= ~NODE_TEST;
}
- ntemp.main = bmain;
- ntemp.scene = scene;
- ntemp.type = NODE_FRAME;
- frame = node_add_node(snode, bmain, scene, &ntemp, 0.0f, 0.0f);
+ frame = node_add_node(C, NULL, NODE_FRAME, 0.0f, 0.0f);
/* reset tags */
for (node = ntree->nodes.first; node; node = node->next)
@@ -1310,6 +1303,9 @@ static SpaceNode *ed_node_link_conditions(ScrArea *sa, bNode **select)
/* test node for links */
for (link = snode->edittree->links.first; link; link = link->next) {
+ if (nodeLinkIsHidden(link))
+ continue;
+
if (link->tonode == *select || link->fromnode == *select)
return NULL;
}
@@ -1350,7 +1346,9 @@ void ED_node_link_intersect_test(ScrArea *sa, int test)
/* we only tag a single link for intersect now */
/* idea; use header dist when more? */
for (link = snode->edittree->links.first; link; link = link->next) {
-
+ if (nodeLinkIsHidden(link))
+ continue;
+
if (cut_links_intersect(link, mcoords, 5)) { /* intersect code wants edges */
if (selink)
break;
@@ -1415,11 +1413,12 @@ void ED_node_link_insert(ScrArea *sa)
link->tonode = select;
link->tosock = socket_best_match(&select->inputs);
+ node_remove_extra_links(snode, link->tosock, link);
link->flag &= ~NODE_LINKFLAG_HILITE;
nodeAddLink(snode->edittree, select, socket_best_match(&select->outputs), node, sockto);
ntreeUpdateTree(snode->edittree); /* needed for pointers */
snode_update(snode, select);
- ED_node_changed_update(snode->id, select);
+ ED_node_tag_update_id(snode->id);
}
}
diff --git a/source/blender/editors/space_node/node_select.c b/source/blender/editors/space_node/node_select.c
index c917b8ee756..291fe86e016 100644
--- a/source/blender/editors/space_node/node_select.c
+++ b/source/blender/editors/space_node/node_select.c
@@ -82,30 +82,9 @@ static bNode *node_under_mouse_tweak(bNodeTree *ntree, int mx, int my)
return NULL;
}
-void node_select(bNode *node)
-{
- node->flag |= SELECT;
-}
-
-void node_deselect(bNode *node)
-{
- bNodeSocket *sock;
-
- node->flag &= ~SELECT;
-
- /* deselect sockets too */
- for (sock = node->inputs.first; sock; sock = sock->next)
- sock->flag &= ~SELECT;
- for (sock = node->outputs.first; sock; sock = sock->next)
- sock->flag &= ~SELECT;
-}
-
static void node_toggle(bNode *node)
{
- if (node->flag & SELECT)
- node_deselect(node);
- else
- node_select(node);
+ nodeSetSelected(node, !(node->flag & SELECT));
}
void node_socket_select(bNode *node, bNodeSocket *sock)
@@ -157,7 +136,7 @@ void node_deselect_all(SpaceNode *snode)
bNode *node;
for (node = snode->edittree->nodes.first; node; node = node->next)
- node_deselect(node);
+ nodeSetSelected(node, FALSE);
}
void node_deselect_all_input_sockets(SpaceNode *snode, int deselect_nodes)
@@ -189,9 +168,6 @@ void node_deselect_all_input_sockets(SpaceNode *snode, int deselect_nodes)
node->flag &= ~SELECT;
}
}
-
- for (sock = snode->edittree->outputs.first; sock; sock = sock->next)
- sock->flag &= ~SELECT;
}
void node_deselect_all_output_sockets(SpaceNode *snode, int deselect_nodes)
@@ -223,9 +199,6 @@ void node_deselect_all_output_sockets(SpaceNode *snode, int deselect_nodes)
node->flag &= ~SELECT;
}
}
-
- for (sock = snode->edittree->inputs.first; sock; sock = sock->next)
- sock->flag &= ~SELECT;
}
/* return 1 if we need redraw otherwise zero. */
@@ -249,12 +222,12 @@ int node_select_same_type(SpaceNode *snode)
if (p->type != nac->type && p->flag & SELECT) {
/* if it's selected but different type, unselect */
redraw = 1;
- node_deselect(p);
+ nodeSetSelected(p, FALSE);
}
else if (p->type == nac->type && (!(p->flag & SELECT))) {
/* if it's the same type and is not selected, select! */
redraw = 1;
- node_select(p);
+ nodeSetSelected(p, TRUE);
}
}
return(redraw);
@@ -296,8 +269,8 @@ int node_select_same_type_np(SpaceNode *snode, int dir)
if (p) {
for (tnode = snode->edittree->nodes.first; tnode; tnode = tnode->next)
if (tnode != p)
- node_deselect(tnode);
- node_select(p);
+ nodeSetSelected(tnode, FALSE);
+ nodeSetSelected(p, TRUE);
return(1);
}
return(0);
@@ -311,8 +284,8 @@ void node_select_single(bContext *C, bNode *node)
for (tnode = snode->edittree->nodes.first; tnode; tnode = tnode->next)
if (tnode != node)
- node_deselect(tnode);
- node_select(node);
+ nodeSetSelected(tnode, FALSE);
+ nodeSetSelected(node, TRUE);
ED_node_set_active(bmain, snode->edittree, node);
@@ -387,8 +360,8 @@ static int node_mouse_select(Main *bmain, SpaceNode *snode, ARegion *ar, const i
if (node) {
for (tnode = snode->edittree->nodes.first; tnode; tnode = tnode->next)
- node_deselect(tnode);
- node_select(node);
+ nodeSetSelected(tnode, FALSE);
+ nodeSetSelected(node, TRUE);
ED_node_set_active(bmain, snode->edittree, node);
selected = 1;
}
@@ -477,13 +450,10 @@ static int node_borderselect_exec(bContext *C, wmOperator *op)
for (node = snode->edittree->nodes.first; node; node = node->next) {
if (BLI_rctf_isect(&rectf, &node->totr, NULL)) {
- if (gesture_mode == GESTURE_MODAL_SELECT)
- node_select(node);
- else
- node_deselect(node);
+ nodeSetSelected(node, (gesture_mode == GESTURE_MODAL_SELECT));
}
else if (!extend) {
- node_deselect(node);
+ nodeSetSelected(node, FALSE);
}
}
@@ -566,11 +536,7 @@ static int do_lasso_select_node(bContext *C, const int mcords[][2], short moves,
if (BLI_rcti_isect_pt(&rect, screen_co[0], screen_co[1]) &&
BLI_lasso_is_point_inside(mcords, moves, screen_co[0], screen_co[1], INT_MAX))
{
- if (select)
- node_select(node);
- else
- node_deselect(node);
-
+ nodeSetSelected(node, select);
change = TRUE;
}
}
@@ -642,13 +608,13 @@ static int node_select_all_exec(bContext *C, wmOperator *op)
for (node = node_lb->first; node; node = node->next) {
switch (action) {
case SEL_SELECT:
- node_select(node);
+ nodeSetSelected(node, TRUE);
break;
case SEL_DESELECT:
- node_deselect(node);
+ nodeSetSelected(node, FALSE);
break;
case SEL_INVERT:
- ((node->flag & SELECT) ? node_deselect : node_select)(node);
+ nodeSetSelected(node, !(node->flag & SELECT));
break;
}
}
@@ -688,13 +654,15 @@ static int node_select_linked_to_exec(bContext *C, wmOperator *UNUSED(op))
node->flag &= ~NODE_TEST;
for (link = snode->edittree->links.first; link; link = link->next) {
+ if (nodeLinkIsHidden(link))
+ continue;
if (link->fromnode && link->tonode && (link->fromnode->flag & NODE_SELECT))
link->tonode->flag |= NODE_TEST;
}
for (node = snode->edittree->nodes.first; node; node = node->next) {
if (node->flag & NODE_TEST)
- node_select(node);
+ nodeSetSelected(node, TRUE);
}
ED_node_sort(snode->edittree);
@@ -730,13 +698,15 @@ static int node_select_linked_from_exec(bContext *C, wmOperator *UNUSED(op))
node->flag &= ~NODE_TEST;
for (link = snode->edittree->links.first; link; link = link->next) {
+ if (nodeLinkIsHidden(link))
+ continue;
if (link->fromnode && link->tonode && (link->tonode->flag & NODE_SELECT))
link->fromnode->flag |= NODE_TEST;
}
for (node = snode->edittree->nodes.first; node; node = node->next) {
if (node->flag & NODE_TEST)
- node_select(node);
+ nodeSetSelected(node, TRUE);
}
ED_node_sort(snode->edittree);
diff --git a/source/blender/editors/space_node/node_templates.c b/source/blender/editors/space_node/node_templates.c
index ca85415cb5a..e4b0512d992 100644
--- a/source/blender/editors/space_node/node_templates.c
+++ b/source/blender/editors/space_node/node_templates.c
@@ -130,7 +130,7 @@ static void node_socket_disconnect(Main *bmain, bNodeTree *ntree, bNode *node_to
nodeUpdate(ntree, node_to);
ntreeUpdateTree(ntree);
- ED_node_generic_update(bmain, ntree, node_to);
+ ED_node_tag_update_nodetree(bmain, ntree);
}
/* remove all nodes connected to this socket, if they aren't connected to other nodes */
@@ -145,11 +145,11 @@ static void node_socket_remove(Main *bmain, bNodeTree *ntree, bNode *node_to, bN
nodeUpdate(ntree, node_to);
ntreeUpdateTree(ntree);
- ED_node_generic_update(bmain, ntree, node_to);
+ ED_node_tag_update_nodetree(bmain, ntree);
}
/* add new node connected to this socket, or replace an existing one */
-static void node_socket_add_replace(Main *bmain, bNodeTree *ntree, bNode *node_to, bNodeSocket *sock_to, bNodeTemplate *ntemp, int sock_num)
+static void node_socket_add_replace(const bContext *C, bNodeTree *ntree, bNode *node_to, bNodeSocket *sock_to, int type, bNodeTree *ngroup, int sock_num)
{
bNode *node_from;
bNodeSocket *sock_from_tmp;
@@ -163,24 +163,29 @@ static void node_socket_add_replace(Main *bmain, bNodeTree *ntree, bNode *node_t
/* find existing node that we can use */
for (node_from = ntree->nodes.first; node_from; node_from = node_from->next)
- if (node_from->type == ntemp->type)
+ if (node_from->type == type)
break;
if (node_from)
if (!(node_from->inputs.first == NULL && !(node_from->typeinfo->flag & NODE_OPTIONS)))
node_from = NULL;
- if (node_prev && node_prev->type == ntemp->type &&
- (ntemp->type != NODE_GROUP || node_prev->id == &ntemp->ngroup->id))
- {
+ /* XXX how can this be done nicely? bNodeTemplate is removed, it doesn't work for generic custom nodes */
+ if (node_prev && node_prev->type == type &&
+ (type != NODE_GROUP || node_prev->id == &ngroup->id)) {
/* keep the previous node if it's the same type */
node_from = node_prev;
}
else if (!node_from) {
- node_from = nodeAddNode(ntree, ntemp);
+ node_from = nodeAddStaticNode(C, ntree, type);
node_from->locx = node_to->locx - (node_from->typeinfo->width + 50);
node_from->locy = node_to->locy;
-
+
+ /* XXX bad, should be dispatched to generic operator or something ... */
+ if (type==NODE_GROUP) {
+ node_from->id = (ID*)ngroup;
+ }
+
if (node_from->id)
id_us_plus(node_from->id);
}
@@ -209,9 +214,11 @@ static void node_socket_add_replace(Main *bmain, bNodeTree *ntree, bNode *node_t
nodeRemLink(ntree, link);
}
- node_socket_free_default_value(sock_from->type, sock_from->default_value);
- sock_from->default_value = node_socket_make_default_value(sock_from->type);
- node_socket_copy_default_value(sock_from->type, sock_from->default_value, sock_prev->default_value);
+#if 0 /* XXX TODO */
+ node_socket_free_default_value(sock_from->typeinfo, sock_from->default_value);
+ sock_from->default_value = node_socket_make_default_value(sock_from->typeinfo);
+ node_socket_copy_default_value(sock_from->typeinfo, sock_from->default_value, sock_prev->default_value);
+#endif
}
}
}
@@ -231,7 +238,7 @@ static void node_socket_add_replace(Main *bmain, bNodeTree *ntree, bNode *node_t
nodeUpdate(ntree, node_to);
ntreeUpdateTree(ntree);
- ED_node_generic_update(bmain, ntree, node_to);
+ ED_node_tag_update_nodetree(CTX_data_main(C), ntree);
}
/****************************** Node Link Menu *******************************/
@@ -262,19 +269,13 @@ static void ui_node_link(bContext *C, void *arg_p, void *event_p)
bNodeSocket *sock_to = arg->sock;
bNodeTree *ntree = arg->ntree;
int event = GET_INT_FROM_POINTER(event_p);
- bNodeTemplate ntemp;
-
- ntemp.type = arg->type;
- ntemp.ngroup = arg->ngroup;
- ntemp.scene = CTX_data_scene(C);
- ntemp.main = CTX_data_main(C);
if (event == UI_NODE_LINK_DISCONNECT)
node_socket_disconnect(bmain, ntree, node_to, sock_to);
else if (event == UI_NODE_LINK_REMOVE)
node_socket_remove(bmain, ntree, node_to, sock_to);
else
- node_socket_add_replace(bmain, ntree, node_to, sock_to, &ntemp, arg->output);
+ node_socket_add_replace(C, ntree, node_to, sock_to, arg->type, arg->ngroup, arg->output);
ED_undo_push(C, "Node input modify");
}
@@ -289,10 +290,10 @@ static void ui_node_sock_name(bNodeSocket *sock, char name[UI_MAX_NAME_STR])
if (node->id)
BLI_strncpy(node_name, node->id->name + 2, UI_MAX_NAME_STR);
else
- BLI_strncpy(node_name, N_("Group"), UI_MAX_NAME_STR);
+ BLI_strncpy(node_name, N_(node->typeinfo->ui_name), UI_MAX_NAME_STR);
}
else
- BLI_strncpy(node_name, node->typeinfo->name, UI_MAX_NAME_STR);
+ BLI_strncpy(node_name, node->typeinfo->ui_name, UI_MAX_NAME_STR);
if (node->inputs.first == NULL &&
node->outputs.first != node->outputs.last)
@@ -316,19 +317,16 @@ static int ui_compatible_sockets(int typeA, int typeB)
static void ui_node_menu_column(NodeLinkArg *arg, int nclass, const char *cname)
{
- Main *bmain = arg->bmain;
bNodeTree *ntree = arg->ntree;
bNodeSocket *sock = arg->sock;
uiLayout *layout = arg->layout;
uiLayout *column = NULL;
uiBlock *block = uiLayoutGetBlock(layout);
uiBut *but;
- bNodeType *ntype;
- bNodeTree *ngroup;
NodeLinkArg *argN;
int first = 1;
int compatibility = 0;
-
+
if (ntree->type == NTREE_SHADER) {
if (BKE_scene_use_new_shading_nodes(arg->scene))
compatibility = NODE_NEW_SHADING;
@@ -336,114 +334,58 @@ static void ui_node_menu_column(NodeLinkArg *arg, int nclass, const char *cname)
compatibility = NODE_OLD_SHADING;
}
- if (nclass == NODE_CLASS_GROUP) {
- for (ngroup = bmain->nodetree.first; ngroup; ngroup = ngroup->id.next) {
- bNodeSocket *gsock;
- char name[UI_MAX_NAME_STR];
- int i, j, num = 0;
-
- if (ngroup->type != ntree->type)
+ NODE_TYPES_BEGIN(ntype)
+ bNodeSocketTemplate *stemp;
+ char name[UI_MAX_NAME_STR];
+ int i, j, num = 0;
+
+ if (compatibility && !(ntype->compatibility & compatibility))
+ continue;
+
+ if (ntype->nclass != nclass)
+ continue;
+
+ for (i = 0, stemp = ntype->outputs; stemp && stemp->type != -1; stemp++, i++)
+ if (ui_compatible_sockets(stemp->type, sock->type))
+ num++;
+
+ for (i = 0, j = 0, stemp = ntype->outputs; stemp && stemp->type != -1; stemp++, i++) {
+ if (!ui_compatible_sockets(stemp->type, sock->type))
continue;
-
- for (gsock = ngroup->inputs.first; gsock; gsock = gsock->next)
- if (ui_compatible_sockets(gsock->type, sock->type))
- num++;
-
- for (i = 0, j = 0, gsock = ngroup->outputs.first; gsock; gsock = gsock->next, i++) {
- if (!ui_compatible_sockets(gsock->type, sock->type))
- continue;
-
- if (first) {
- column = uiLayoutColumn(layout, FALSE);
- uiBlockSetCurLayout(block, column);
-
- uiItemL(column, IFACE_(cname), ICON_NODE);
- but = block->buttons.last;
- but->flag = UI_TEXT_LEFT;
-
- first = 0;
- }
-
- if (num > 1) {
- if (j == 0) {
- uiItemL(column, ngroup->id.name + 2, ICON_NODE);
- but = block->buttons.last;
- but->flag = UI_TEXT_LEFT;
- }
-
- BLI_snprintf(name, UI_MAX_NAME_STR, " %s", gsock->name);
- j++;
- }
- else
- BLI_strncpy(name, ngroup->id.name + 2, UI_MAX_NAME_STR);
-
- but = uiDefBut(block, BUT, 0, ngroup->id.name + 2, 0, 0, UI_UNIT_X * 4, UI_UNIT_Y,
- NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Add node to input"));
-
- argN = MEM_dupallocN(arg);
- argN->type = NODE_GROUP;
- argN->ngroup = ngroup;
- argN->output = i;
- uiButSetNFunc(but, ui_node_link, argN, NULL);
+
+ if (first) {
+ column = uiLayoutColumn(layout, 0);
+ uiBlockSetCurLayout(block, column);
+
+ uiItemL(column, IFACE_(cname), ICON_NODE);
+ but = block->buttons.last;
+ but->flag = UI_TEXT_LEFT;
+
+ first = 0;
}
- }
- }
- else {
- bNodeTreeType *ttype = ntreeGetType(ntree->type);
-
- for (ntype = ttype->node_types.first; ntype; ntype = ntype->next) {
- bNodeSocketTemplate *stemp;
- char name[UI_MAX_NAME_STR];
- int i, j, num = 0;
-
- if (compatibility && !(ntype->compatibility & compatibility))
- continue;
-
- if (ntype->nclass != nclass)
- continue;
-
- for (i = 0, stemp = ntype->outputs; stemp && stemp->type != -1; stemp++, i++)
- if (ui_compatible_sockets(stemp->type, sock->type))
- num++;
-
- for (i = 0, j = 0, stemp = ntype->outputs; stemp && stemp->type != -1; stemp++, i++) {
- if (!ui_compatible_sockets(stemp->type, sock->type))
- continue;
-
- if (first) {
- column = uiLayoutColumn(layout, FALSE);
- uiBlockSetCurLayout(block, column);
-
- uiItemL(column, IFACE_(cname), ICON_NODE);
+
+ if (num > 1) {
+ if (j == 0) {
+ uiItemL(column, IFACE_(ntype->ui_name), ICON_NODE);
but = block->buttons.last;
but->flag = UI_TEXT_LEFT;
-
- first = 0;
- }
-
- if (num > 1) {
- if (j == 0) {
- uiItemL(column, IFACE_(ntype->name), ICON_NODE);
- but = block->buttons.last;
- but->flag = UI_TEXT_LEFT;
- }
-
- BLI_snprintf(name, UI_MAX_NAME_STR, " %s", IFACE_(stemp->name));
- j++;
}
- else
- BLI_strncpy(name, IFACE_(ntype->name), UI_MAX_NAME_STR);
-
- but = uiDefBut(block, BUT, 0, name, 0, 0, UI_UNIT_X * 4, UI_UNIT_Y,
- NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Add node to input"));
-
- argN = MEM_dupallocN(arg);
- argN->type = ntype->type;
- argN->output = i;
- uiButSetNFunc(but, ui_node_link, argN, NULL);
+
+ BLI_snprintf(name, UI_MAX_NAME_STR, " %s", IFACE_(stemp->name));
+ j++;
}
+ else
+ BLI_strncpy(name, IFACE_(ntype->ui_name), UI_MAX_NAME_STR);
+
+ but = uiDefBut(block, BUT, 0, name, 0, 0, UI_UNIT_X*4, UI_UNIT_Y,
+ NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Add node to input"));
+
+ argN = MEM_dupallocN(arg);
+ argN->type = ntype->type;
+ argN->output = i;
+ uiButSetNFunc(but, ui_node_link, argN, NULL);
}
- }
+ NODE_TYPES_END
}
static void node_menu_column_foreach_cb(void *calldata, int nclass, const char *name)
@@ -463,7 +405,7 @@ static void ui_template_node_link_menu(bContext *C, uiLayout *layout, void *but_
uiLayout *split, *column;
NodeLinkArg *arg = (NodeLinkArg *)but->func_argN;
bNodeSocket *sock = arg->sock;
- bNodeTreeType *ntreetype = ntreeGetType(arg->ntree->type);
+ bNodeTreeType *ntreetype = arg->ntree->typeinfo;
uiBlockSetCurLayout(block, layout);
split = uiLayoutSplit(layout, 0.0f, FALSE);
@@ -557,7 +499,7 @@ static void ui_node_draw_node(uiLayout *layout, bContext *C, bNodeTree *ntree, b
static void ui_node_draw_input(uiLayout *layout, bContext *C, bNodeTree *ntree, bNode *node, bNodeSocket *input, int depth)
{
- PointerRNA inputptr;
+ PointerRNA inputptr, nodeptr;
uiBlock *block = uiLayoutGetBlock(layout);
uiBut *bt;
uiLayout *split, *row, *col;
@@ -579,6 +521,7 @@ static void ui_node_draw_input(uiLayout *layout, bContext *C, bNodeTree *ntree,
/* socket RNA pointer */
RNA_pointer_create(&ntree->id, &RNA_NodeSocket, input, &inputptr);
+ RNA_pointer_create(&ntree->id, &RNA_Node, node, &nodeptr);
/* indented label */
memset(label, ' ', indent);
@@ -627,16 +570,25 @@ static void ui_node_draw_input(uiLayout *layout, bContext *C, bNodeTree *ntree,
}
else {
/* input not linked, show value */
- if (input->type != SOCK_SHADER && !(input->flag & SOCK_HIDE_VALUE)) {
- if (input->type == SOCK_VECTOR) {
+ if (!(input->flag & SOCK_HIDE_VALUE)) {
+ switch (input->type) {
+ case SOCK_FLOAT:
+ case SOCK_INT:
+ case SOCK_BOOLEAN:
+ case SOCK_RGBA:
+ case SOCK_STRING:
+ row = uiLayoutRow(split, TRUE);
+ uiItemR(row, &inputptr, "default_value", 0, "", ICON_NONE);
+ break;
+ case SOCK_VECTOR:
row = uiLayoutRow(split, FALSE);
col = uiLayoutColumn(row, FALSE);
-
uiItemR(col, &inputptr, "default_value", 0, "", ICON_NONE);
- }
- else {
- row = uiLayoutRow(split, TRUE);
- uiItemR(row, &inputptr, "default_value", 0, "", ICON_NONE);
+ break;
+
+ default:
+ row = uiLayoutRow(split, FALSE);
+ break;
}
}
else
@@ -653,7 +605,7 @@ void uiTemplateNodeView(uiLayout *layout, bContext *C, bNodeTree *ntree, bNode *
{
bNode *tnode;
- if (!ntree)
+ if (!ntreeIsValid(ntree))
return;
/* clear for cycle check */
diff --git a/source/blender/editors/space_node/node_view.c b/source/blender/editors/space_node/node_view.c
index a2fa7d3caf6..1241227c9d8 100644
--- a/source/blender/editors/space_node/node_view.c
+++ b/source/blender/editors/space_node/node_view.c
@@ -61,6 +61,7 @@
#include "IMB_imbuf_types.h"
#include "node_intern.h" /* own include */
+#include "NOD_composite.h"
/* **************** View All Operator ************** */
@@ -370,7 +371,7 @@ int ED_space_node_color_sample(SpaceNode *snode, ARegion *ar, int mval[2], float
float fx, fy, bufx, bufy;
int ret = FALSE;
- if (snode->treetype != NTREE_COMPOSIT || (snode->flag & SNODE_BACKDRAW) == 0) {
+ if (strcmp(snode->tree_idname, ntreeType_Composite->idname)==0 || (snode->flag & SNODE_BACKDRAW) == 0) {
/* use viewer image for color sampling only if we're in compositor tree
* with backdrop enabled
*/
@@ -524,7 +525,7 @@ static int sample_invoke(bContext *C, wmOperator *op, const wmEvent *event)
ARegion *ar = CTX_wm_region(C);
ImageSampleInfo *info;
- if (snode->treetype != NTREE_COMPOSIT || !(snode->flag & SNODE_BACKDRAW))
+ if (!ED_node_is_compositor(snode) || !(snode->flag & SNODE_BACKDRAW))
return OPERATOR_CANCELLED;
info = MEM_callocN(sizeof(ImageSampleInfo), "ImageSampleInfo");
diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c
index 75f28baf558..ac2f36ed51d 100644
--- a/source/blender/editors/space_node/space_node.c
+++ b/source/blender/editors/space_node/space_node.c
@@ -45,10 +45,10 @@
#include "BKE_node.h"
#include "ED_space_api.h"
+#include "ED_node.h"
#include "ED_render.h"
#include "ED_screen.h"
#include "ED_node.h"
-
#include "WM_api.h"
#include "WM_types.h"
@@ -59,6 +59,168 @@
#include "node_intern.h" /* own include */
+
+/* ******************** tree path ********************* */
+
+void ED_node_tree_start(SpaceNode *snode, bNodeTree *ntree, ID *id, ID *from)
+{
+ bNodeTreePath *path, *path_next;
+ for (path=snode->treepath.first; path; path=path_next) {
+ path_next = path->next;
+ MEM_freeN(path);
+ }
+ snode->treepath.first = snode->treepath.last = NULL;
+
+ if (ntree) {
+ path = MEM_callocN(sizeof(bNodeTreePath), "node tree path");
+ path->nodetree = ntree;
+ path->parent_key = NODE_INSTANCE_KEY_BASE;
+ if (id)
+ BLI_strncpy(path->node_name, id->name+2, sizeof(path->node_name));
+ BLI_addtail(&snode->treepath, path);
+ }
+
+ /* update current tree */
+ snode->nodetree = snode->edittree = ntree;
+ snode->id = id;
+ snode->from = from;
+
+ /* listener updates the View2D center from edittree */
+ WM_main_add_notifier(NC_SCENE|ND_NODES, NULL);
+}
+
+void ED_node_tree_push(SpaceNode *snode, bNodeTree *ntree, bNode *gnode)
+{
+ bNodeTreePath *path = MEM_callocN(sizeof(bNodeTreePath), "node tree path");
+ bNodeTreePath *prev_path = snode->treepath.last;
+ path->nodetree = ntree;
+ if (gnode) {
+ if (prev_path)
+ path->parent_key = BKE_node_instance_key(prev_path->parent_key, prev_path->nodetree, gnode);
+ else
+ path->parent_key = NODE_INSTANCE_KEY_BASE;
+
+ BLI_strncpy(path->node_name, gnode->name, sizeof(path->node_name));
+ }
+ else
+ path->parent_key = NODE_INSTANCE_KEY_BASE;
+
+ BLI_addtail(&snode->treepath, path);
+
+ /* update current tree */
+ snode->edittree = ntree;
+
+ /* listener updates the View2D center from edittree */
+ WM_main_add_notifier(NC_SCENE|ND_NODES, NULL);
+}
+
+void ED_node_tree_pop(SpaceNode *snode)
+{
+ bNodeTreePath *path = snode->treepath.last;
+
+ /* don't remove root */
+ if (path == snode->treepath.first)
+ return;
+
+ BLI_remlink(&snode->treepath, path);
+ MEM_freeN(path);
+
+ /* update current tree */
+ path = snode->treepath.last;
+ snode->edittree = path->nodetree;
+
+ /* listener updates the View2D center from edittree */
+ WM_main_add_notifier(NC_SCENE|ND_NODES, NULL);
+}
+
+int ED_node_tree_depth(SpaceNode *snode)
+{
+ return BLI_countlist(&snode->treepath);
+}
+
+bNodeTree *ED_node_tree_get(SpaceNode *snode, int level)
+{
+ bNodeTreePath *path;
+ int i;
+ for (path = snode->treepath.last, i = 0; path; path=path->prev, ++i) {
+ if (i == level)
+ return path->nodetree;
+ }
+ return NULL;
+}
+
+int ED_node_tree_path_length(SpaceNode *snode)
+{
+ bNodeTreePath *path;
+ int length = 0;
+ int i;
+ for (path=snode->treepath.first, i=0; path; path=path->next, ++i) {
+ length += strlen(path->node_name);
+ if (i > 0)
+ length += 1; /* for separator char */
+ }
+ return length;
+}
+
+void ED_node_tree_path_get(SpaceNode *snode, char *value)
+{
+ bNodeTreePath *path;
+ int i;
+
+ value[0] = '\0';
+ for (path=snode->treepath.first, i=0; path; path=path->next, ++i) {
+ if (i == 0) {
+ strcpy(value, path->node_name);
+ value += strlen(path->node_name);
+ }
+ else {
+ sprintf(value, "/%s", path->node_name);
+ value += strlen(path->node_name) + 1;
+ }
+ }
+}
+
+void ED_node_tree_path_get_fixedbuf(SpaceNode *snode, char *value, int max_length)
+{
+ bNodeTreePath *path;
+ int size, i;
+
+ value[0] = '\0';
+ for (path=snode->treepath.first, i=0; path; path=path->next, ++i) {
+ if (i == 0) {
+ BLI_strncpy(value, path->node_name, max_length);
+ size = strlen(path->node_name);
+ }
+ else {
+ BLI_snprintf(value, max_length, "/%s", path->node_name);
+ size = strlen(path->node_name) + 1;
+ }
+ max_length -= size;
+ if (max_length <= 0)
+ break;
+ value += size;
+ }
+}
+
+void snode_group_offset(SpaceNode *snode, float *x, float *y)
+{
+ bNodeTreePath *path = snode->treepath.last;
+ float cx, cy;
+
+ if (path) {
+ cx = path->nodetree->view_center[0];
+ cy = path->nodetree->view_center[1];
+
+ if (path->prev) {
+ *x = cx - path->prev->nodetree->view_center[0];
+ *y = cy - path->prev->nodetree->view_center[1];
+ return;
+ }
+ }
+
+ *x = *y = 0.0f;
+}
+
/* ******************** manage regions ********************* */
ARegion *node_has_buttons_region(ScrArea *sa)
@@ -124,6 +286,12 @@ static SpaceLink *node_new(const bContext *UNUSED(C))
/* backdrop */
snode->zoom = 1.0f;
+ /* select the first tree type for valid type */
+ NODE_TREE_TYPES_BEGIN(treetype)
+ strcpy(snode->tree_idname, treetype->idname);
+ break;
+ NODE_TREE_TYPES_END
+
/* header */
ar = MEM_callocN(sizeof(ARegion), "header for node");
@@ -167,10 +335,15 @@ static SpaceLink *node_new(const bContext *UNUSED(C))
return (SpaceLink *)snode;
}
-/* not spacelink itself */
-static void node_free(SpaceLink *UNUSED(sl))
+static void node_free(SpaceLink *sl)
{
+ SpaceNode *snode = (SpaceNode*)sl;
+ bNodeTreePath *path, *path_next;
+ for (path=snode->treepath.first; path; path=path_next) {
+ path_next = path->next;
+ MEM_freeN(path);
+ }
}
@@ -184,14 +357,21 @@ static void node_area_listener(ScrArea *sa, wmNotifier *wmn)
{
/* note, ED_area_tag_refresh will re-execute compositor */
SpaceNode *snode = sa->spacedata.first;
- int type = snode->treetype;
short shader_type = snode->shaderfrom;
/* preview renders */
switch (wmn->category) {
case NC_SCENE:
switch (wmn->data) {
- case ND_NODES:
+ case ND_NODES: {
+ ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
+ /* shift view to node tree center */
+ if (ar && snode->edittree)
+ UI_view2d_setcenter(&ar->v2d, snode->edittree->view_center[0], snode->edittree->view_center[1]);
+
+ ED_area_tag_refresh(sa);
+ break;
+ }
case ND_FRAME:
ED_area_tag_refresh(sa);
break;
@@ -199,7 +379,7 @@ static void node_area_listener(ScrArea *sa, wmNotifier *wmn)
ED_area_tag_redraw(sa);
break;
case ND_TRANSFORM_DONE:
- if (type == NTREE_COMPOSIT) {
+ if (ED_node_is_compositor(snode)) {
if (snode->flag & SNODE_AUTO_RENDER) {
snode->recalc = 1;
ED_area_tag_refresh(sa);
@@ -211,7 +391,7 @@ static void node_area_listener(ScrArea *sa, wmNotifier *wmn)
/* future: add ID checks? */
case NC_MATERIAL:
- if (type == NTREE_SHADER) {
+ if (ED_node_is_shader(snode)) {
if (wmn->data == ND_SHADING)
ED_area_tag_refresh(sa);
else if (wmn->data == ND_SHADING_DRAW)
@@ -224,18 +404,18 @@ static void node_area_listener(ScrArea *sa, wmNotifier *wmn)
}
break;
case NC_TEXTURE:
- if (type == NTREE_SHADER || type == NTREE_TEXTURE) {
+ if (ED_node_is_shader(snode) || ED_node_is_texture(snode)) {
if (wmn->data == ND_NODES)
ED_area_tag_refresh(sa);
}
break;
case NC_WORLD:
- if (type == NTREE_SHADER && shader_type == SNODE_SHADER_WORLD) {
+ if (ED_node_is_shader(snode) && shader_type == SNODE_SHADER_WORLD) {
ED_area_tag_refresh(sa);
}
break;
case NC_OBJECT:
- if (type == NTREE_SHADER) {
+ if (ED_node_is_shader(snode)) {
if (wmn->data == ND_OB_SHADING)
ED_area_tag_refresh(sa);
}
@@ -261,7 +441,7 @@ static void node_area_listener(ScrArea *sa, wmNotifier *wmn)
break;
case NC_MASK:
if (wmn->action == NA_EDITED) {
- if (type == NTREE_COMPOSIT) {
+ if (snode->nodetree && snode->nodetree->type == NTREE_COMPOSIT) {
ED_area_tag_refresh(sa);
}
}
@@ -269,7 +449,7 @@ static void node_area_listener(ScrArea *sa, wmNotifier *wmn)
case NC_IMAGE:
if (wmn->action == NA_EDITED) {
- if (type == NTREE_COMPOSIT) {
+ if (ED_node_is_compositor(snode)) {
/* note that nodeUpdateID is already called by BKE_image_signal() on all
* scenes so really this is just to know if the images is used in the compo else
* painting on images could become very slow when the compositor is open. */
@@ -281,7 +461,7 @@ static void node_area_listener(ScrArea *sa, wmNotifier *wmn)
case NC_MOVIECLIP:
if (wmn->action == NA_EDITED) {
- if (type == NTREE_COMPOSIT) {
+ if (ED_node_is_compositor(snode)) {
if (nodeUpdateID(snode->nodetree, wmn->reference))
ED_area_tag_refresh(sa);
}
@@ -294,11 +474,13 @@ static void node_area_refresh(const struct bContext *C, ScrArea *sa)
{
/* default now: refresh node is starting preview */
SpaceNode *snode = sa->spacedata.first;
+
+ ED_preview_kill_jobs(C);
+
+ snode_set_context(C);
- snode_set_context(snode, CTX_data_scene(C));
-
- if (snode->nodetree) {
- if (snode->treetype == NTREE_SHADER) {
+ if (ntreeIsValid(snode->nodetree)) {
+ if (snode->nodetree->type == NTREE_SHADER) {
if (GS(snode->id->name) == ID_MA) {
Material *ma = (Material *)snode->id;
if (ma->use_nodes)
@@ -315,7 +497,7 @@ static void node_area_refresh(const struct bContext *C, ScrArea *sa)
ED_preview_shader_job(C, sa, snode->id, NULL, NULL, 100, 100, PR_NODE_RENDER);
}
}
- else if (snode->treetype == NTREE_COMPOSIT) {
+ else if (snode->nodetree->type == NTREE_COMPOSIT) {
Scene *scene = (Scene *)snode->id;
if (scene->use_nodes) {
/* recalc is set on 3d view changes for auto compo */
@@ -328,7 +510,7 @@ static void node_area_refresh(const struct bContext *C, ScrArea *sa)
}
}
}
- else if (snode->treetype == NTREE_TEXTURE) {
+ else if (snode->nodetree->type == NTREE_TEXTURE) {
Tex *tex = (Tex *)snode->id;
if (tex->use_nodes) {
ED_preview_shader_job(C, sa, snode->id, NULL, NULL, 100, 100, PR_NODE_RENDER);
@@ -339,11 +521,14 @@ static void node_area_refresh(const struct bContext *C, ScrArea *sa)
static SpaceLink *node_duplicate(SpaceLink *sl)
{
- SpaceNode *snoden = MEM_dupallocN(sl);
+ SpaceNode *snode = (SpaceNode*)sl;
+ SpaceNode *snoden = MEM_dupallocN(snode);
/* clear or remove stuff from old */
snoden->nodetree = NULL;
snoden->linkdrag.first = snoden->linkdrag.last = NULL;
+
+ BLI_duplicatelist(&snoden->treepath, &snode->treepath);
return (SpaceLink *)snoden;
}
@@ -415,9 +600,7 @@ static void node_main_area_init(wmWindowManager *wm, ARegion *ar)
static void node_main_area_draw(const bContext *C, ARegion *ar)
{
- View2D *v2d = &ar->v2d;
-
- drawnodespace(C, ar, v2d);
+ drawnodespace(C, ar);
}
@@ -469,11 +652,8 @@ static void node_header_area_init(wmWindowManager *UNUSED(wm), ARegion *ar)
static void node_header_area_draw(const bContext *C, ARegion *ar)
{
- SpaceNode *snode = CTX_wm_space_node(C);
- Scene *scene = CTX_data_scene(C);
-
/* find and set the context */
- snode_set_context(snode, scene);
+ snode_set_context(C);
ED_region_header(C, ar);
}
@@ -549,6 +729,14 @@ static int node_context(const bContext *C, const char *member, bContextDataResul
CTX_data_type_set(result, CTX_DATA_TYPE_POINTER);
return 1;
}
+ else if (CTX_data_equals(member, "node_previews")) {
+ if (snode->nodetree) {
+ CTX_data_pointer_set(result, &snode->nodetree->id, &RNA_NodeInstanceHash, snode->nodetree->previews);
+ }
+
+ CTX_data_type_set(result, CTX_DATA_TYPE_POINTER);
+ return 1;
+ }
return 0;
}
diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c
index 85375bcaf83..6ea37644533 100644
--- a/source/blender/editors/uvedit/uvedit_ops.c
+++ b/source/blender/editors/uvedit/uvedit_ops.c
@@ -159,7 +159,7 @@ void ED_object_assign_active_image(Main *bmain, Object *ob, int mat_nr, Image *i
if (node && is_image_texture_node(node)) {
node->id = &ima->id;
- ED_node_generic_update(bmain, ma->nodetree, node);
+ ED_node_tag_update_nodetree(bmain, ma->nodetree);
}
}
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index 2e24b6ed78d..5ccdd5c6ac2 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -44,11 +44,19 @@ struct SpaceNode;
struct bNodeLink;
struct bNodeType;
struct bNodeTreeExec;
+struct bNodePreview;
+struct bNodeInstanceHash;
struct AnimData;
struct bGPdata;
struct uiBlock;
struct Image;
+/* In writefile.c: write deprecated DNA data,
+ * to ensure forward compatibility in 2.6x versions.
+ * Will be removed eventually.
+ */
+#define USE_NODE_COMPAT_CUSTOMNODES
+
#define NODE_MAXSTR 64
typedef struct bNodeStack {
@@ -79,13 +87,22 @@ typedef struct bNodeStack {
typedef struct bNodeSocket {
struct bNodeSocket *next, *prev, *new_sock;
+ IDProperty *prop; /* user-defined properties */
+
+ char identifier[64]; /* unique identifier for mapping */
+
char name[64]; /* MAX_NAME */
+ /* XXX deprecated, only used for the Image and OutputFile nodes,
+ * should be removed at some point.
+ */
void *storage; /* custom storage */
short type, flag;
short limit; /* max. number of links */
- short pad1;
+ short in_out; /* input/output type */
+ struct bNodeSocketType *typeinfo; /* runtime type information */
+ char idname[64]; /* runtime type identifier */
float locx, locy;
@@ -98,11 +115,14 @@ typedef struct bNodeSocket {
int resizemode; /* compositor resize mode of the socket */
void *cache; /* cached data from execution */
- /* internal data to retrieve relations and groups */
- int own_index; /* group socket identifiers, to find matching pairs after reading files */
+ /* internal data to retrieve relations and groups
+ * DEPRECATED, now uses the generic identifier string instead
+ */
+ int own_index DNA_DEPRECATED; /* group socket identifiers, to find matching pairs after reading files */
/* XXX deprecated, only used for restoring old group node links */
int to_index DNA_DEPRECATED;
- struct bNodeSocket *groupsock;
+ /* XXX deprecated, still forward compatible since verification restores pointer from matching own_index. */
+ struct bNodeSocket *groupsock DNA_DEPRECATED;
struct bNodeLink *link; /* a link pointer, set in ntreeUpdateTree */
@@ -111,31 +131,34 @@ typedef struct bNodeSocket {
} bNodeSocket;
/* sock->type */
+#define SOCK_CUSTOM -1 /* socket has no integer type */
#define SOCK_FLOAT 0
#define SOCK_VECTOR 1
#define SOCK_RGBA 2
#define SOCK_SHADER 3
#define SOCK_BOOLEAN 4
-#define SOCK_MESH 5
+#define __SOCK_MESH 5 /* deprecated */
#define SOCK_INT 6
#define SOCK_STRING 7
#define NUM_SOCKET_TYPES 8 /* must be last! */
/* socket side (input/output) */
-#define SOCK_IN 1
-#define SOCK_OUT 2
+typedef enum eNodeSocketInOut {
+ SOCK_IN = 1,
+ SOCK_OUT = 2
+} eNodeSocketInOut;
/* sock->flag, first bit is select */
/* hidden is user defined, to hide unused */
#define SOCK_HIDDEN 2
/* for quick check if socket is linked */
-#define SOCK_IN_USE 4 /* XXX deprecated */
+#define SOCK_IN_USE 4
/* unavailable is for dynamic sockets */
#define SOCK_UNAVAIL 8
- /* dynamic socket (can be modified by user) */
-#define SOCK_DYNAMIC 16
- /* group socket should not be exposed */
-#define SOCK_INTERNAL 32
+ /* DEPRECATED dynamic socket (can be modified by user) */
+#define __SOCK_DYNAMIC 16
+ /* DEPRECATED group socket should not be exposed */
+#define __SOCK_INTERNAL 32
/* socket collapsed in UI */
#define SOCK_COLLAPSED 64
/* hide socket value, if it gets auto default */
@@ -144,19 +167,18 @@ typedef struct bNodeSocket {
/* DEPRECATED, only kept here to avoid reusing the flag */
#define SOCK_AUTO_HIDDEN__DEPRECATED 256
-typedef struct bNodePreview {
- unsigned char *rect;
- short xsize, ysize;
- int pad;
-} bNodePreview;
-
/* limit data in bNode to what we want to see saved? */
typedef struct bNode {
struct bNode *next, *prev, *new_node;
+
+ IDProperty *prop; /* user-defined properties */
+
+ struct bNodeType *typeinfo; /* runtime type information */
+ char idname[64]; /* runtime type identifier */
char name[64]; /* MAX_NAME */
int flag;
- short type, pad2;
+ short type, pad;
short done, level; /* both for dependency and sorting */
short lasty, menunr; /* lasty: check preview render status, menunr: browse ID blocks */
short stack_index; /* for groupnode, offset in global caller stack */
@@ -186,10 +208,17 @@ typedef struct bNode {
rctf totr; /* entire boundbox (worldspace) */
rctf butr; /* optional buttons area */
rctf prvr; /* optional preview area */
- bNodePreview *preview; /* optional preview image */
+ /* XXX TODO
+ * Node totr size depends on the prvr size, which in turn is determined from preview size.
+ * In earlier versions bNodePreview was stored directly in nodes, but since now there can be
+ * multiple instances using different preview images it is possible that required node size varies between instances.
+ * preview_xsize, preview_ysize defines a common reserved size for preview rect for now,
+ * could be replaced by more accurate node instance drawing, but that requires removing totr from DNA
+ * and replacing all uses with per-instance data.
+ */
+ short preview_xsize, preview_ysize; /* reserved size of the preview rect */
+ int pad2;
struct uiBlock *block; /* runtime during drawing */
-
- struct bNodeType *typeinfo; /* lookup of callbacks and defaults */
} bNode;
/* node->flag */
@@ -200,7 +229,7 @@ typedef struct bNode {
#define NODE_ACTIVE 16
#define NODE_ACTIVE_ID 32
#define NODE_DO_OUTPUT 64
-#define NODE_GROUP_EDIT 128
+#define __NODE_GROUP_EDIT 128 /* DEPRECATED */
/* free test flag, undefined */
#define NODE_TEST 256
/* node is disabled */
@@ -221,6 +250,12 @@ typedef struct bNode {
#define NODE_ACTIVE_TEXTURE (1<<14)
/* use a custom color for the node */
#define NODE_CUSTOM_COLOR (1<<15)
+ /* Node has been initialized
+ * This flag indicates the node->typeinfo->init function has been called.
+ * In case of undefined type at creation time this can be delayed until
+ * until the node type is registered.
+ */
+#define NODE_INIT (1<<16)
/* node->update */
/* XXX NODE_UPDATE is a generic update flag. More fine-grained updates
@@ -229,6 +264,36 @@ typedef struct bNode {
#define NODE_UPDATE 0xFFFF /* generic update flag (includes all others) */
#define NODE_UPDATE_ID 1 /* associated id data block has changed */
+/* Unique hash key for identifying node instances
+ * Defined as a struct because DNA does not support other typedefs.
+ */
+typedef struct bNodeInstanceKey
+{
+ unsigned int value;
+} bNodeInstanceKey;
+
+/* Base struct for entries in node instance hash.
+ * WARNING: pointers are cast to this struct internally,
+ * it must be first member in hash entry structs!
+ */
+typedef struct bNodeInstanceHashEntry {
+ bNodeInstanceKey key;
+
+ /* tags for cleaning the cache */
+ short tag;
+ short pad;
+} bNodeInstanceHashEntry;
+
+
+typedef struct bNodePreview {
+ bNodeInstanceHashEntry hash_entry; /* must be first */
+
+ unsigned char *rect;
+ short xsize, ysize;
+ int pad;
+} bNodePreview;
+
+
typedef struct bNodeLink {
struct bNodeLink *next, *prev;
@@ -263,7 +328,13 @@ typedef struct bNodeTree {
ID id;
struct AnimData *adt; /* animation data (must be immediately after id for utilities to use it) */
+ struct bNodeTreeType *typeinfo; /* runtime type information */
+ char idname[64]; /* runtime type identifier */
+
+ struct StructRNA *interface_type; /* runtime RNA type of the group interface */
+
struct bGPdata *gpd; /* grease pencil data */
+ float view_center[2]; /* node tree stores own offset for consistent editor view */
ListBase nodes, links;
@@ -272,8 +343,11 @@ typedef struct bNodeTree {
* will increase this counter */
int flag;
int update; /* update flags */
+ short is_updating; /* flag to prevent reentrant update calls */
+ short done; /* generic temporary flag for recursion check (DFS/BFS) */
+ int pad2;
- int nodetype; /* specific node type this tree is used for */
+ int nodetype DNA_DEPRECATED; /* specific node type this tree is used for */
short edit_quality; /* Quality setting when editing */
short render_quality; /* Quality setting when rendering */
@@ -281,7 +355,16 @@ typedef struct bNodeTree {
rctf viewer_border;
- ListBase inputs, outputs; /* external sockets for group nodes */
+ /* Lists of bNodeSocket to hold default values and own_index.
+ * Warning! Don't make links to these sockets, input/output nodes are used for that.
+ * These sockets are used only for generating external interfaces.
+ */
+ ListBase inputs, outputs;
+
+ /* Node preview hash table
+ * Only available in base node trees (e.g. scene->node_tree)
+ */
+ struct bNodeInstanceHash *previews;
/* execution data */
/* XXX It would be preferable to completely move this data out of the underlying node tree,
@@ -302,10 +385,10 @@ typedef struct bNodeTree {
} bNodeTree;
/* ntree->type, index */
+#define NTREE_CUSTOM -1 /* for dynamically registered custom types */
#define NTREE_SHADER 0
#define NTREE_COMPOSIT 1
#define NTREE_TEXTURE 2
-#define NUM_NTREE_TYPES 3
/* ntree->init, flag */
#define NTREE_TYPE_INIT 1
@@ -320,18 +403,24 @@ typedef struct bNodeTree {
/* XXX not nice, but needed as a temporary flags
* for group updates after library linking.
*/
-#define NTREE_DO_VERSIONS_GROUP_EXPOSE 1024
+#define NTREE_DO_VERSIONS_GROUP_EXPOSE_2_56_2 1024 /* changes from r35033 */
+#define NTREE_DO_VERSIONS_CUSTOMNODES_GROUP 2048 /* custom_nodes branch: remove links to node tree sockets */
+#define NTREE_DO_VERSIONS_CUSTOMNODES_GROUP_CREATE_INTERFACE 4096 /* custom_nodes branch: create group input/output nodes */
/* ntree->update */
-#define NTREE_UPDATE 0xFFFF /* generic update flag (includes all others) */
-#define NTREE_UPDATE_LINKS 1 /* links have been added or removed */
-#define NTREE_UPDATE_NODES 2 /* nodes or sockets have been added or removed */
-#define NTREE_UPDATE_GROUP_IN 16 /* group inputs have changed */
-#define NTREE_UPDATE_GROUP_OUT 32 /* group outputs have changed */
-#define NTREE_UPDATE_GROUP 48 /* group has changed (generic flag including all other group flags) */
-
-
-/* socket value structs for input buttons */
+typedef enum eNodeTreeUpdate {
+ NTREE_UPDATE = 0xFFFF, /* generic update flag (includes all others) */
+ NTREE_UPDATE_LINKS = 1, /* links have been added or removed */
+ NTREE_UPDATE_NODES = 2, /* nodes or sockets have been added or removed */
+ NTREE_UPDATE_GROUP_IN = 16, /* group inputs have changed */
+ NTREE_UPDATE_GROUP_OUT = 32, /* group outputs have changed */
+ NTREE_UPDATE_GROUP = 48 /* group has changed (generic flag including all other group flags) */
+} eNodeTreeUpdate;
+
+
+/* socket value structs for input buttons
+ * DEPRECATED now using ID properties
+ */
typedef struct bNodeSocketValueInt {
int subtype; /* RNA subtype */
@@ -731,8 +820,6 @@ typedef struct NodeShaderScript {
char bytecode_hash[64];
char *bytecode;
-
- IDProperty *prop;
} NodeShaderScript;
typedef struct NodeShaderTangent {
@@ -758,6 +845,9 @@ typedef struct NodeShaderNormalMap {
#define NODE_FRAME_SHRINK 1 /* keep the bounding box minimal */
#define NODE_FRAME_RESIZEABLE 2 /* test flag, if frame can be resized by user */
+/* proxy node flags */
+#define NODE_PROXY_AUTOTYPE 1 /* automatically change output type based on link */
+
/* comp channel matte */
#define CMP_NODE_CHANNEL_MATTE_CS_RGB 1
#define CMP_NODE_CHANNEL_MATTE_CS_HSV 2
@@ -857,6 +947,39 @@ typedef struct NodeShaderNormalMap {
#define CMP_NODE_MASK_MBLUR_SAMPLES_MAX 64
+/* geometry output socket defines */
+#define GEOM_OUT_GLOB 0
+#define GEOM_OUT_LOCAL 1
+#define GEOM_OUT_VIEW 2
+#define GEOM_OUT_ORCO 3
+#define GEOM_OUT_UV 4
+#define GEOM_OUT_NORMAL 5
+#define GEOM_OUT_VCOL 6
+#define GEOM_OUT_VCOL_ALPHA 7
+#define GEOM_OUT_FRONTBACK 8
+
+/* material input socket defines */
+#define MAT_IN_COLOR 0
+#define MAT_IN_SPEC 1
+#define MAT_IN_REFL 2
+#define MAT_IN_NORMAL 3
+#define MAT_IN_MIR 4
+#define MAT_IN_AMB 5
+#define MAT_IN_EMIT 6
+#define MAT_IN_SPECTRA 7
+#define MAT_IN_RAY_MIRROR 8
+#define MAT_IN_ALPHA 9
+#define MAT_IN_TRANSLUCENCY 10
+#define NUM_MAT_IN 11 /* for array size */
+
+/* material output socket defines */
+#define MAT_OUT_COLOR 0
+#define MAT_OUT_ALPHA 1
+#define MAT_OUT_NORMAL 2
+#define MAT_OUT_DIFFUSE 3
+#define MAT_OUT_SPEC 4
+#define MAT_OUT_AO 5
+
/* image */
#define CMP_NODE_IMAGE_USE_STRAIGHT_OUTPUT 1
diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h
index 0873c2278c5..a810f4219e0 100644
--- a/source/blender/makesdna/DNA_space_types.h
+++ b/source/blender/makesdna/DNA_space_types.h
@@ -43,6 +43,7 @@
#include "DNA_image_types.h" /* ImageUser */
#include "DNA_movieclip_types.h" /* MovieClipUser */
#include "DNA_sequence_types.h" /* SequencerScopes */
+#include "DNA_node_types.h" /* for bNodeInstanceKey */
/* Hum ... Not really nice... but needed for spacebuts. */
#include "DNA_view2d_types.h"
@@ -880,6 +881,17 @@ typedef struct SpaceScript {
/* Nodes Editor =========================================== */
/* Node Editor */
+
+typedef struct bNodeTreePath {
+ struct bNodeTreePath *next, *prev;
+
+ struct bNodeTree *nodetree;
+ bNodeInstanceKey parent_key; /* base key for nodes in this tree instance */
+ int pad;
+ /* XXX this is not automatically updated when node names are changed! */
+ char node_name[64]; /* MAX_NAME */
+} bNodeTreePath;
+
typedef struct SpaceNode {
SpaceLink *next, *prev;
ListBase regionbase; /* storage of regions for inactive spaces */
@@ -897,12 +909,24 @@ typedef struct SpaceNode {
float zoom; /* zoom for backdrop */
float cursor[2]; /* mouse pos for drawing socketless link and adding nodes */
+ /* XXX nodetree pointer info is all in the path stack now,
+ * remove later on and use bNodeTreePath instead. For now these variables are set when pushing/popping
+ * from path stack, to avoid having to update all the functions and operators. Can be done when
+ * design is accepted and everything is properly tested.
+ */
+ ListBase treepath;
+
struct bNodeTree *nodetree, *edittree;
- int treetype; /* treetype: as same nodetree->type */
+
+ /* tree type for the current node tree */
+ char tree_idname[64];
+ int treetype DNA_DEPRECATED; /* treetype: as same nodetree->type */
+ int pad3;
+
short texfrom; /* texfrom object, world or brush */
short shaderfrom; /* shader from object or world */
short recalc; /* currently on 0/1, for auto compo */
- short pad[3];
+ short pad4;
ListBase linkdrag; /* temporary data for modal linking operator */
struct bGPdata *gpd; /* grease-pencil data */
@@ -921,6 +945,7 @@ typedef enum eSpaceNode_Flag {
SNODE_SHOW_HIGHLIGHT = (1 << 6),
SNODE_USE_HIDDEN_PREVIEW = (1 << 10),
SNODE_NEW_SHADERS = (1 << 11),
+ SNODE_PIN = (1 << 12),
} eSpaceNode_Flag;
/* snode->texfrom */
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index cde104710df..efa6f37648a 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -363,14 +363,13 @@ extern StructRNA RNA_NearSensor;
extern StructRNA RNA_NlaStrip;
extern StructRNA RNA_NlaTrack;
extern StructRNA RNA_Node;
-extern StructRNA RNA_NodeForLoop;
-extern StructRNA RNA_NodeGroup;
extern StructRNA RNA_NodeOutputFileSlotFile;
extern StructRNA RNA_NodeOutputFileSlotLayer;
+extern StructRNA RNA_NodeInstanceHash;
extern StructRNA RNA_NodeLink;
extern StructRNA RNA_NodeSocket;
+extern StructRNA RNA_NodeSocketInterface;
extern StructRNA RNA_NodeTree;
-extern StructRNA RNA_NodeWhileLoop;
extern StructRNA RNA_NoiseTexture;
extern StructRNA RNA_NorController;
extern StructRNA RNA_Object;
@@ -655,7 +654,9 @@ StructRNA *RNA_struct_find(const char *identifier);
const char *RNA_struct_identifier(StructRNA *type);
const char *RNA_struct_ui_name(StructRNA *type);
+const char *RNA_struct_ui_name_raw(StructRNA *type);
const char *RNA_struct_ui_description(StructRNA *type);
+const char *RNA_struct_ui_description_raw(StructRNA *type);
const char *RNA_struct_translation_context(StructRNA *type);
int RNA_struct_ui_icon(StructRNA *type);
@@ -721,7 +722,9 @@ int RNA_property_array_item_index(PropertyRNA *prop, char name);
int RNA_property_string_maxlength(PropertyRNA *prop);
const char *RNA_property_ui_name(PropertyRNA *prop);
+const char *RNA_property_ui_name_raw(PropertyRNA *prop);
const char *RNA_property_ui_description(PropertyRNA *prop);
+const char *RNA_property_ui_description_raw(PropertyRNA *prop);
const char *RNA_property_translation_context(PropertyRNA *prop);
int RNA_property_ui_icon(PropertyRNA *prop);
@@ -976,9 +979,11 @@ void RNA_collection_clear(PointerRNA *ptr, const char *name);
/* check if the idproperty exists, for operators */
bool RNA_property_is_set_ex(PointerRNA *ptr, PropertyRNA *prop, bool use_ghost);
bool RNA_property_is_set(PointerRNA *ptr, PropertyRNA *prop);
+void RNA_property_unset(PointerRNA *ptr, PropertyRNA *prop);
bool RNA_struct_property_is_set_ex(PointerRNA *ptr, const char *identifier, bool use_ghost);
bool RNA_struct_property_is_set(PointerRNA *ptr, const char *identifier);
bool RNA_property_is_idprop(PropertyRNA *prop);
+void RNA_struct_property_unset(PointerRNA *ptr, const char *identifier);
/* python compatible string representation of this property, (must be freed!) */
char *RNA_property_as_string(struct bContext *C, PointerRNA *ptr, PropertyRNA *prop, int index);
@@ -995,6 +1000,7 @@ char *RNA_function_as_string_keywords(struct bContext *C, FunctionRNA *func, Poi
const char *RNA_function_identifier(FunctionRNA *func);
const char *RNA_function_ui_description(FunctionRNA *func);
+const char *RNA_function_ui_description_raw(FunctionRNA *func);
int RNA_function_flag(FunctionRNA *func);
int RNA_function_defined(FunctionRNA *func);
diff --git a/source/blender/makesrna/RNA_define.h b/source/blender/makesrna/RNA_define.h
index 5ab37c6d97b..924fc505fda 100644
--- a/source/blender/makesrna/RNA_define.h
+++ b/source/blender/makesrna/RNA_define.h
@@ -223,6 +223,8 @@ const char *RNA_property_typename(PropertyType type);
#define IS_DNATYPE_FLOAT_COMPAT(_str) (strcmp(_str, "float") == 0 || strcmp(_str, "double") == 0)
#define IS_DNATYPE_INT_COMPAT(_str) (strcmp(_str, "int") == 0 || strcmp(_str, "short") == 0 || strcmp(_str, "char") == 0)
+void RNA_identifier_sanitize(char *identifier, int property);
+
/* max size for dynamic defined type descriptors,
* this value is arbitrary */
#define RNA_DYN_DESCR_MAX 240
diff --git a/source/blender/makesrna/RNA_enum_types.h b/source/blender/makesrna/RNA_enum_types.h
index eabf0391c01..2719ae889d4 100644
--- a/source/blender/makesrna/RNA_enum_types.h
+++ b/source/blender/makesrna/RNA_enum_types.h
@@ -29,6 +29,10 @@
#include "RNA_types.h"
+struct bNodeTreeType;
+struct bNodeType;
+struct bNodeSocketType;
+
/* Types */
extern EnumPropertyItem id_type_items[];
@@ -128,8 +132,23 @@ extern EnumPropertyItem gameproperty_type_items[];
extern EnumPropertyItem viewport_shade_items[];
-extern EnumPropertyItem nodetree_type_items[];
-extern EnumPropertyItem node_socket_type_items[];
+int rna_node_tree_type_to_enum(struct bNodeTreeType *typeinfo);
+int rna_node_tree_idname_to_enum(const char *idname);
+struct bNodeTreeType *rna_node_tree_type_from_enum(int value);
+EnumPropertyItem *rna_node_tree_type_itemf(void *data, int (*poll)(void *data, struct bNodeTreeType *), int *free);
+
+int rna_node_type_to_enum(struct bNodeType *typeinfo);
+int rna_node_idname_to_enum(const char *idname);
+struct bNodeType *rna_node_type_from_enum(int value);
+EnumPropertyItem *rna_node_type_itemf(void *data, int (*poll)(void *data, struct bNodeType*), int *free);
+
+int rna_node_socket_type_to_enum(struct bNodeSocketType *typeinfo);
+int rna_node_socket_idname_to_enum(const char *idname);
+struct bNodeSocketType *rna_node_socket_type_from_enum(int value);
+EnumPropertyItem *rna_node_socket_type_itemf(void *data, int (*poll)(void *data, struct bNodeSocketType*), int *free);
+
+extern EnumPropertyItem node_socket_in_out_items[];
+extern EnumPropertyItem node_icon_items[];
extern EnumPropertyItem node_math_items[];
extern EnumPropertyItem node_vec_math_items[];
diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt
index 7621ebb70b3..a0ee5e05390 100644
--- a/source/blender/makesrna/intern/CMakeLists.txt
+++ b/source/blender/makesrna/intern/CMakeLists.txt
@@ -259,6 +259,7 @@ blender_include_dirs(
../../imbuf
../../ikplugin
../../makesdna
+ ../../nodes/
../../windowmanager
../../editors/include
../../render/extern/include
@@ -296,7 +297,6 @@ set(SRC
${SRC_RNA_INC}
rna_internal.h
rna_internal_types.h
- rna_nodetree_types.h
rna_mesh_utils.h
)
diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c
index f3efbd0d53e..92ce8122597 100644
--- a/source/blender/makesrna/intern/rna_access.c
+++ b/source/blender/makesrna/intern/rna_access.c
@@ -282,6 +282,20 @@ static IDProperty *rna_idproperty_find(PointerRNA *ptr, const char *name)
return NULL;
}
+static void rna_idproperty_free(PointerRNA *ptr, const char *name)
+{
+ IDProperty *group = RNA_struct_idprops(ptr, 0);
+
+ if (group) {
+ IDProperty *idprop = IDP_GetPropertyFromGroup(group, name);
+ if (idprop) {
+ IDP_RemFromGroup(group, idprop);
+ IDP_FreeProperty(idprop);
+ MEM_freeN(idprop);
+ }
+ }
+}
+
static int rna_ensure_property_array_length(PointerRNA *ptr, PropertyRNA *prop)
{
if (prop->magic == RNA_MAGIC) {
@@ -477,7 +491,7 @@ static const char *rna_ensure_property_description(PropertyRNA *prop)
description = ((IDProperty *)prop)->name; /* XXX - not correct */
}
- return TIP_(description);
+ return description;
}
static const char *rna_ensure_property_name(PropertyRNA *prop)
@@ -489,7 +503,7 @@ static const char *rna_ensure_property_name(PropertyRNA *prop)
else
name = ((IDProperty *)prop)->name;
- return CTX_IFACE_(prop->translation_context, name);
+ return name;
}
/* Structs */
@@ -515,6 +529,11 @@ const char *RNA_struct_ui_name(StructRNA *type)
return CTX_IFACE_(type->translation_context, type->name);
}
+const char *RNA_struct_ui_name_raw(StructRNA *type)
+{
+ return type->name;
+}
+
int RNA_struct_ui_icon(StructRNA *type)
{
if (type)
@@ -528,6 +547,11 @@ const char *RNA_struct_ui_description(StructRNA *type)
return TIP_(type->description);
}
+const char *RNA_struct_ui_description_raw(StructRNA *type)
+{
+ return type->description;
+}
+
const char *RNA_struct_translation_context(StructRNA *type)
{
return type->translation_context ? type->translation_context : BLF_I18NCONTEXT_DEFAULT;
@@ -778,7 +802,7 @@ const char *RNA_property_identifier(PropertyRNA *prop)
const char *RNA_property_description(PropertyRNA *prop)
{
- return rna_ensure_property_description(prop);
+ return TIP_(rna_ensure_property_description(prop));
}
PropertyType RNA_property_type(PropertyRNA *prop)
@@ -1401,11 +1425,21 @@ int RNA_property_enum_bitflag_identifiers(bContext *C, PointerRNA *ptr, Property
const char *RNA_property_ui_name(PropertyRNA *prop)
{
+ return CTX_IFACE_(prop->translation_context, rna_ensure_property_name(prop));
+}
+
+const char *RNA_property_ui_name_raw(PropertyRNA *prop)
+{
return rna_ensure_property_name(prop);
}
const char *RNA_property_ui_description(PropertyRNA *prop)
{
+ return TIP_(rna_ensure_property_description(prop));
+}
+
+const char *RNA_property_ui_description_raw(PropertyRNA *prop)
+{
return rna_ensure_property_description(prop);
}
@@ -4797,6 +4831,13 @@ bool RNA_property_is_set(PointerRNA *ptr, PropertyRNA *prop)
}
}
+void RNA_property_unset(PointerRNA *ptr, PropertyRNA *prop)
+{
+ if (prop->flag & PROP_IDPROPERTY) {
+ rna_idproperty_free(ptr, prop->identifier);
+ }
+}
+
bool RNA_struct_property_is_set_ex(PointerRNA *ptr, const char *identifier, bool use_ghost)
{
PropertyRNA *prop = RNA_struct_find_property(ptr, identifier);
@@ -4825,6 +4866,15 @@ bool RNA_struct_property_is_set(PointerRNA *ptr, const char *identifier)
}
}
+void RNA_struct_property_unset(PointerRNA *ptr, const char *identifier)
+{
+ PropertyRNA *prop = RNA_struct_find_property(ptr, identifier);
+
+ if (prop) {
+ RNA_property_unset(ptr, prop);
+ }
+}
+
bool RNA_property_is_idprop(PropertyRNA *prop)
{
return (prop->magic != RNA_MAGIC);
@@ -5190,6 +5240,11 @@ const char *RNA_function_identifier(FunctionRNA *func)
const char *RNA_function_ui_description(FunctionRNA *func)
{
+ return TIP_(func->description);
+}
+
+const char *RNA_function_ui_description_raw(FunctionRNA *func)
+{
return func->description;
}
diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c
index 74d212fae57..49e1122bf18 100644
--- a/source/blender/makesrna/intern/rna_color.c
+++ b/source/blender/makesrna/intern/rna_color.c
@@ -298,7 +298,7 @@ static void rna_ColorRamp_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *
for (node = ntree->nodes.first; node; node = node->next) {
if (ELEM3(node->type, SH_NODE_VALTORGB, CMP_NODE_VALTORGB, TEX_NODE_VALTORGB)) {
- ED_node_generic_update(bmain, ntree, node);
+ ED_node_tag_update_nodetree(bmain, ntree);
}
}
}
diff --git a/source/blender/makesrna/intern/rna_define.c b/source/blender/makesrna/intern/rna_define.c
index c92777af8fd..61e67ad3298 100644
--- a/source/blender/makesrna/intern/rna_define.c
+++ b/source/blender/makesrna/intern/rna_define.c
@@ -458,6 +458,78 @@ static int rna_validate_identifier(const char *identifier, char *error, int prop
return 1;
}
+void RNA_identifier_sanitize(char *identifier, int property)
+{
+ int a = 0;
+
+ /* list from http://docs.python.org/py3k/reference/lexical_analysis.html#keywords */
+ static const char *kwlist[] = {
+ /* "False", "None", "True", */
+ "and", "as", "assert", "break",
+ "class", "continue", "def", "del", "elif", "else", "except",
+ "finally", "for", "from", "global", "if", "import", "in",
+ "is", "lambda", "nonlocal", "not", "or", "pass", "raise",
+ "return", "try", "while", "with", "yield", NULL
+ };
+
+
+ if (!isalpha(identifier[0])) {
+ /* first character failed isalpha() check */
+ identifier[0] = '_';
+ }
+
+ for (a = 0; identifier[a]; a++) {
+ if (DefRNA.preprocess && property) {
+ if (isalpha(identifier[a]) && isupper(identifier[a])) {
+ /* property names must contain lower case characters only */
+ identifier[a] = tolower(identifier[a]);
+ }
+ }
+
+ if (identifier[a] == '_') {
+ continue;
+ }
+
+ if (identifier[a] == ' ') {
+ /* spaces are not okay in identifier names */
+ identifier[a] = '_';
+ }
+
+ if (isalnum(identifier[a]) == 0) {
+ /* one of the characters failed an isalnum() check and is not an underscore */
+ identifier[a] = '_';
+ }
+ }
+
+ for (a = 0; kwlist[a]; a++) {
+ if (strcmp(identifier, kwlist[a]) == 0) {
+ /* this keyword is reserved by python.
+ * just replace the last character by '_' to keep it readable.
+ */
+ identifier[strlen(identifier)-1] = '_';
+ break;
+ }
+ }
+
+ if (property) {
+ static const char *kwlist_prop[] = {
+ /* not keywords but reserved all the same because py uses */
+ "keys", "values", "items", "get",
+ NULL
+ };
+
+ for (a = 0; kwlist_prop[a]; a++) {
+ if (strcmp(identifier, kwlist_prop[a]) == 0) {
+ /* this keyword is reserved by python.
+ * just replace the last character by '_' to keep it readable.
+ */
+ identifier[strlen(identifier)-1] = '_';
+ break;
+ }
+ }
+ }
+}
+
/* Blender Data Definition */
BlenderRNA *RNA_create(void)
diff --git a/source/blender/makesrna/intern/rna_lamp.c b/source/blender/makesrna/intern/rna_lamp.c
index 912f4d914cb..7fee67cd569 100644
--- a/source/blender/makesrna/intern/rna_lamp.c
+++ b/source/blender/makesrna/intern/rna_lamp.c
@@ -42,6 +42,7 @@
#include "MEM_guardedalloc.h"
+#include "BKE_context.h"
#include "BKE_depsgraph.h"
#include "BKE_main.h"
#include "BKE_texture.h"
@@ -169,14 +170,14 @@ static void rna_Lamp_spot_size_set(PointerRNA *ptr, float value)
la->spotsize = RAD2DEGF(value);
}
-static void rna_Lamp_use_nodes_update(Main *blain, Scene *scene, PointerRNA *ptr)
+static void rna_Lamp_use_nodes_update(bContext *C, PointerRNA *ptr)
{
Lamp *la = (Lamp *)ptr->data;
if (la->use_nodes && la->nodetree == NULL)
- ED_node_shader_default(scene, &la->id);
+ ED_node_shader_default(C, &la->id);
- rna_Lamp_update(blain, scene, ptr);
+ rna_Lamp_update(CTX_data_main(C), CTX_data_scene(C), ptr);
}
#else
@@ -414,6 +415,7 @@ static void rna_def_lamp(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_nodes", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "use_nodes", 1);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_ui_text(prop, "Use Nodes", "Use shader nodes to render the lamp");
RNA_def_property_update(prop, 0, "rna_Lamp_use_nodes_update");
diff --git a/source/blender/makesrna/intern/rna_main_api.c b/source/blender/makesrna/intern/rna_main_api.c
index 4d5d4d4a7cd..a79fa1aaed4 100644
--- a/source/blender/makesrna/intern/rna_main_api.c
+++ b/source/blender/makesrna/intern/rna_main_api.c
@@ -235,23 +235,32 @@ static void rna_Main_materials_remove(Main *bmain, ReportList *reports, PointerR
}
}
-static bNodeTree *rna_Main_nodetree_new(Main *bmain, const char *name, int type)
+static EnumPropertyItem *rna_Main_nodetree_type_itemf(bContext *UNUSED(C), PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), int *free)
{
- bNodeTree *tree = ntreeAddTree(bmain, name, type, NODE_GROUP);
-
- id_us_min(&tree->id);
- return tree;
+ return rna_node_tree_type_itemf(NULL, NULL, free);
+}
+static struct bNodeTree *rna_Main_nodetree_new(Main *bmain, const char *name, int type)
+{
+ bNodeTreeType *typeinfo = rna_node_tree_type_from_enum(type);
+ if (typeinfo) {
+ bNodeTree *ntree = ntreeAddTree(bmain, name, typeinfo->idname);
+
+ id_us_min(&ntree->id);
+ return ntree;
+ }
+ else
+ return NULL;
}
-static void rna_Main_nodetree_remove(Main *bmain, ReportList *reports, PointerRNA *tree_ptr)
+static void rna_Main_nodetree_remove(Main *bmain, ReportList *reports, PointerRNA *ntree_ptr)
{
- bNodeTree *tree = tree_ptr->data;
- if (ID_REAL_USERS(tree) <= 0) {
- BKE_libblock_free(&bmain->nodetree, tree);
- RNA_POINTER_INVALIDATE(tree_ptr);
+ bNodeTree *ntree = ntree_ptr->data;
+ if (ID_REAL_USERS(ntree) <= 0) {
+ BKE_libblock_free(&bmain->nodetree, ntree);
+ RNA_POINTER_INVALIDATE(ntree_ptr);
}
else {
BKE_reportf(reports, RPT_ERROR, "Node tree '%s' must have zero users to be removed, found %d",
- tree->id.name + 2, ID_REAL_USERS(tree));
+ ntree->id.name + 2, ID_REAL_USERS(ntree));
}
}
@@ -1069,10 +1078,8 @@ void RNA_def_main_node_groups(BlenderRNA *brna, PropertyRNA *cprop)
PropertyRNA *parm;
PropertyRNA *prop;
- static EnumPropertyItem node_nodetree_items[] = {
- {0, "SHADER", 0, "Shader", ""},
- {1, "COMPOSITE", 0, "Composite", ""},
- {2, "TEXTURE", 0, "Texture", ""},
+ static EnumPropertyItem dummy_items[] = {
+ {0, "DUMMY", 0, "", ""},
{0, NULL, 0, NULL, NULL}
};
@@ -1085,7 +1092,8 @@ void RNA_def_main_node_groups(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_function_ui_description(func, "Add a new node tree to the main database");
parm = RNA_def_string(func, "name", "NodeGroup", 0, "", "New name for the datablock");
RNA_def_property_flag(parm, PROP_REQUIRED);
- parm = RNA_def_enum(func, "type", node_nodetree_items, 0, "Type", "The type of node_group to add");
+ parm = RNA_def_enum(func, "type", dummy_items, 0, "Type", "The type of node_group to add");
+ RNA_def_property_enum_funcs(parm, NULL, NULL, "rna_Main_nodetree_type_itemf");
RNA_def_property_flag(parm, PROP_REQUIRED);
/* return type */
parm = RNA_def_pointer(func, "tree", "NodeTree", "", "New node tree datablock");
diff --git a/source/blender/makesrna/intern/rna_material.c b/source/blender/makesrna/intern/rna_material.c
index d1c81200e6a..57ae217cff6 100644
--- a/source/blender/makesrna/intern/rna_material.c
+++ b/source/blender/makesrna/intern/rna_material.c
@@ -82,6 +82,7 @@ EnumPropertyItem ramp_blend_items[] = {
#include "DNA_node_types.h"
#include "DNA_object_types.h"
+#include "BKE_context.h"
#include "BKE_depsgraph.h"
#include "BKE_main.h"
#include "BKE_material.h"
@@ -111,7 +112,7 @@ static void rna_Material_update_previews(Main *bmain, Scene *scene, PointerRNA *
Material *ma = ptr->id.data;
if (ma->nodetree)
- ntreeClearPreview(ma->nodetree);
+ BKE_node_preview_clear_tree(ma->nodetree);
WM_main_add_notifier(NC_MATERIAL | ND_SHADING, ma);
}
@@ -287,14 +288,14 @@ static void rna_Material_use_specular_ramp_set(PointerRNA *ptr, int value)
ma->ramp_spec = add_colorband(0);
}
-static void rna_Material_use_nodes_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_Material_use_nodes_update(bContext *C, PointerRNA *ptr)
{
Material *ma = (Material *)ptr->data;
if (ma->use_nodes && ma->nodetree == NULL)
- ED_node_shader_default(scene, &ma->id);
+ ED_node_shader_default(C, &ma->id);
- rna_Material_update(bmain, scene, ptr);
+ rna_Material_update(CTX_data_main(C), CTX_data_scene(C), ptr);
}
static EnumPropertyItem *rna_Material_texture_coordinates_itemf(bContext *UNUSED(C), PointerRNA *ptr,
@@ -2024,6 +2025,7 @@ void RNA_def_material(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_nodes", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "use_nodes", 1);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_ui_text(prop, "Use Nodes", "Use shader nodes to render the material");
RNA_def_property_update(prop, 0, "rna_Material_use_nodes_update");
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index e7c030d5cdf..99b4f5a794d 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -26,6 +26,7 @@
#include <stdlib.h>
#include <string.h>
+#include <limits.h>
#include "BLI_listbase.h"
#include "BLI_math.h"
@@ -61,11 +62,22 @@
#include "MEM_guardedalloc.h"
-EnumPropertyItem nodetree_type_items[] = {
- {NTREE_SHADER, "SHADER", ICON_MATERIAL, "Shader", "Shader nodes"},
- {NTREE_TEXTURE, "TEXTURE", ICON_TEXTURE, "Texture", "Texture nodes"},
- {NTREE_COMPOSIT, "COMPOSITING", ICON_RENDERLAYERS, "Compositing", "Compositing nodes"},
- {0, NULL, 0, NULL, NULL}
+EnumPropertyItem node_socket_in_out_items[] = {
+ { SOCK_IN, "IN", 0, "Input", "" },
+ { SOCK_OUT, "OUT", 0, "Output", "" },
+ { 0, NULL, 0, NULL, NULL }
+};
+
+EnumPropertyItem node_socket_type_items[] = {
+ {SOCK_CUSTOM, "CUSTOM", 0, "Custom", ""},
+ {SOCK_FLOAT, "VALUE", 0, "Value", ""},
+ {SOCK_INT, "INT", 0, "Int", ""},
+ {SOCK_BOOLEAN, "BOOLEAN", 0, "Boolean", ""},
+ {SOCK_VECTOR, "VECTOR", 0, "Vector", ""},
+ {SOCK_STRING, "STRING", 0, "String", ""},
+ {SOCK_RGBA, "RGBA", 0, "RGBA", ""},
+ {SOCK_SHADER, "SHADER", 0, "Shader", ""},
+ {0, NULL, 0, NULL, NULL}
};
EnumPropertyItem node_quality_items[] = {
@@ -85,17 +97,15 @@ EnumPropertyItem node_chunksize_items[] = {
{0, NULL, 0, NULL, NULL}
};
-EnumPropertyItem node_socket_type_items[] = {
- {SOCK_FLOAT, "VALUE", 0, "Value", ""},
- {SOCK_VECTOR, "VECTOR", 0, "Vector", ""},
- {SOCK_RGBA, "RGBA", 0, "RGBA", ""},
- {SOCK_SHADER, "SHADER", 0, "Shader", ""},
- {SOCK_BOOLEAN, "BOOLEAN", 0, "Boolean", ""},
- {SOCK_MESH, "MESH", 0, "Mesh", ""},
- {SOCK_INT, "INT", 0, "Int", ""},
- {SOCK_STRING, "STRING", 0, "String", ""},
- {0, NULL, 0, NULL, NULL}
-};
+#define DEF_ICON_BLANK_SKIP
+#define DEF_ICON(name) {ICON_##name, (#name), 0, (#name), ""},
+#define DEF_VICO(name)
+EnumPropertyItem node_icon_items[] = {
+#include "UI_icons.h"
+ {0, NULL, 0, NULL, NULL}};
+#undef DEF_ICON_BLANK_SKIP
+#undef DEF_ICON
+#undef DEF_VICO
EnumPropertyItem node_math_items[] = {
{ 0, "ADD", 0, "Add", ""},
@@ -174,52 +184,20 @@ EnumPropertyItem prop_wave_items[] = {
};
#endif
-/* Add any new socket value subtype here.
- * When adding a new subtype here, make sure you also add it
- * to the subtype definitions in DNA_node_types.h.
- * This macro is used by the RNA and the internal converter functions
- * to define all socket subtypes. The SUBTYPE macro must be defined
- * before using this macro, and undefined afterwards.
- */
-#define NODE_DEFINE_SUBTYPES_INT \
- SUBTYPE(INT, Int, NONE, None) \
- SUBTYPE(INT, Int, UNSIGNED, Unsigned)
-
-#define NODE_DEFINE_SUBTYPES_FLOAT \
- SUBTYPE(FLOAT, Float, NONE, None) \
- SUBTYPE(FLOAT, Float, UNSIGNED, Unsigned) \
- SUBTYPE(FLOAT, Float, PERCENTAGE, Percentage) \
- SUBTYPE(FLOAT, Float, FACTOR, Factor) \
- SUBTYPE(FLOAT, Float, ANGLE, Angle) \
- SUBTYPE(FLOAT, Float, TIME, Time) \
- SUBTYPE(FLOAT, Float, DISTANCE, Distance)
-
-#define NODE_DEFINE_SUBTYPES_STRING \
- SUBTYPE(STRING, String, NONE, None) \
- SUBTYPE(STRING, String, FILEPATH, Filepath)
-
-#define NODE_DEFINE_SUBTYPES_VECTOR \
- SUBTYPE(VECTOR, Vector, NONE, None) \
- SUBTYPE(VECTOR, Vector, TRANSLATION, Translation) \
- SUBTYPE(VECTOR, Vector, DIRECTION, Direction) \
- SUBTYPE(VECTOR, Vector, VELOCITY, Velocity) \
- SUBTYPE(VECTOR, Vector, ACCELERATION, Acceleration) \
- SUBTYPE(VECTOR, Vector, EULER, Euler) \
- SUBTYPE(VECTOR, Vector, XYZ, XYZ)
-
-#define NODE_DEFINE_SUBTYPES \
- NODE_DEFINE_SUBTYPES_INT \
- NODE_DEFINE_SUBTYPES_FLOAT \
- NODE_DEFINE_SUBTYPES_STRING \
- NODE_DEFINE_SUBTYPES_VECTOR \
-
#ifdef RNA_RUNTIME
#include "BLI_linklist.h"
+#include "BLI_string.h"
+
+#include "BKE_context.h"
+#include "BKE_idprop.h"
#include "BKE_global.h"
#include "ED_node.h"
+#include "ED_render.h"
+
+#include "NOD_socket.h"
#include "RE_engine.h"
#include "RE_pipeline.h"
@@ -227,66 +205,1334 @@ EnumPropertyItem prop_wave_items[] = {
#include "DNA_scene_types.h"
#include "WM_api.h"
-static StructRNA *rna_Node_refine(struct PointerRNA *ptr)
+
+int rna_node_tree_type_to_enum(bNodeTreeType *typeinfo)
{
- bNode *node = (bNode *)ptr->data;
+ int i=0, result=-1;
+ NODE_TREE_TYPES_BEGIN(nt)
+ if (nt == typeinfo) {
+ result = i;
+ break;
+ }
+ ++i;
+ NODE_TREE_TYPES_END
+ return result;
+}
+
+int rna_node_tree_idname_to_enum(const char *idname)
+{
+ int i=0, result=-1;
+ NODE_TREE_TYPES_BEGIN(nt)
+ if (strcmp(nt->idname, idname)==0) {
+ result = i;
+ break;
+ }
+ ++i;
+ NODE_TREE_TYPES_END
+ return result;
+}
- switch (node->type) {
+bNodeTreeType *rna_node_tree_type_from_enum(int value)
+{
+ int i=0;
+ bNodeTreeType *result=NULL;
+ NODE_TREE_TYPES_BEGIN(nt)
+ if (i == value) {
+ result = nt;
+ break;
+ }
+ ++i;
+ NODE_TREE_TYPES_END
+ return result;
+}
+
+EnumPropertyItem *rna_node_tree_type_itemf(void *data, int (*poll)(void *data, bNodeTreeType *), int *free)
+{
+ EnumPropertyItem tmp = {0, "", 0, "", ""};
+ EnumPropertyItem *item = NULL;
+ int totitem=0, i=0;
+
+ NODE_TREE_TYPES_BEGIN(nt)
+ if (poll && !poll(data, nt)) {
+ ++i;
+ continue;
+ }
- #define DefNode(Category, ID, DefFunc, EnumName, StructName, UIName, UIDesc) \
- case ID: return &RNA_##Category##StructName;
-
- #include "rna_nodetree_types.h"
+ tmp.value = i;
+ tmp.identifier = nt->idname;
+ tmp.icon = nt->ui_icon;
+ tmp.name = nt->ui_name;
+ tmp.description = nt->ui_description;
- case NODE_GROUP:
- return &RNA_NodeGroup;
- case NODE_FRAME:
- return &RNA_NodeFrame;
- case NODE_REROUTE:
- return &RNA_NodeReroute;
- default:
- return &RNA_Node;
+ RNA_enum_item_add(&item, &totitem, &tmp);
+
+ ++i;
+ NODE_TREE_TYPES_END
+
+ RNA_enum_item_end(&item, &totitem);
+ *free = 1;
+
+ return item;
+}
+
+int rna_node_type_to_enum(bNodeType *typeinfo)
+{
+ int i=0, result=-1;
+ NODE_TYPES_BEGIN(ntype)
+ if (ntype==typeinfo) {
+ result = i;
+ break;
+ }
+ ++i;
+ NODE_TYPES_END
+ return result;
+}
+
+int rna_node_idname_to_enum(const char *idname)
+{
+ int i=0, result=-1;
+ NODE_TYPES_BEGIN(ntype)
+ if (strcmp(ntype->idname, idname)==0) {
+ result = i;
+ break;
+ }
+ ++i;
+ NODE_TYPES_END
+ return result;
+}
+
+bNodeType *rna_node_type_from_enum(int value)
+{
+ int i=0;
+ bNodeType *result=NULL;
+ NODE_TYPES_BEGIN(ntype)
+ if (i==value) {
+ result = ntype;
+ break;
+ }
+ ++i;
+ NODE_TYPES_END
+ return result;
+}
+
+EnumPropertyItem *rna_node_type_itemf(void *data, int (*poll)(void *data, bNodeType *), int *free)
+{
+ EnumPropertyItem *item = NULL;
+ EnumPropertyItem tmp = {0, "", 0, "", ""};
+ int totitem=0, i=0;
+
+ NODE_TYPES_BEGIN(ntype)
+ if (poll && !poll(data, ntype)) {
+ ++i;
+ continue;
+ }
+
+ tmp.value = i;
+ tmp.identifier = ntype->idname;
+ tmp.icon = ntype->ui_icon;
+ tmp.name = ntype->ui_name;
+ tmp.description = ntype->ui_description;
+
+ RNA_enum_item_add(&item, &totitem, &tmp);
+
+ ++i;
+ NODE_TYPES_END
+ RNA_enum_item_end(&item, &totitem);
+ *free = 1;
+
+ return item;
+}
+
+int rna_node_socket_type_to_enum(bNodeSocketType *typeinfo)
+{
+ int i=0, result=-1;
+ NODE_SOCKET_TYPES_BEGIN(stype)
+ if (stype==typeinfo) {
+ result = i;
+ break;
+ }
+ ++i;
+ NODE_SOCKET_TYPES_END
+ return result;
+}
+
+int rna_node_socket_idname_to_enum(const char *idname)
+{
+ int i=0, result=-1;
+ NODE_SOCKET_TYPES_BEGIN(stype)
+ if (strcmp(stype->idname, idname)==0) {
+ result = i;
+ break;
+ }
+ ++i;
+ NODE_SOCKET_TYPES_END
+ return result;
+}
+
+bNodeSocketType *rna_node_socket_type_from_enum(int value)
+{
+ int i=0;
+ bNodeSocketType *result=NULL;
+ NODE_SOCKET_TYPES_BEGIN(stype)
+ if (i==value) {
+ result = stype;
+ break;
+ }
+ ++i;
+ NODE_SOCKET_TYPES_END
+ return result;
+}
+
+EnumPropertyItem *rna_node_socket_type_itemf(void *data, int (*poll)(void *data, bNodeSocketType *), int *free)
+{
+ EnumPropertyItem *item = NULL;
+ EnumPropertyItem tmp = {0, "", 0, "", ""};
+ int totitem=0, i=0;
+ StructRNA *srna;
+
+ NODE_SOCKET_TYPES_BEGIN(stype)
+ if (poll && !poll(data, stype)) {
+ ++i;
+ continue;
+ }
+
+ srna = stype->ext_socket.srna;
+ tmp.value = i;
+ tmp.identifier = stype->idname;
+ tmp.icon = RNA_struct_ui_icon(srna);
+ tmp.name = RNA_struct_ui_name(srna);
+ tmp.description = RNA_struct_ui_description(srna);
+
+ RNA_enum_item_add(&item, &totitem, &tmp);
+
+ ++i;
+ NODE_SOCKET_TYPES_END
+ RNA_enum_item_end(&item, &totitem);
+ *free = 1;
+
+ return item;
+}
+
+static EnumPropertyItem *rna_node_static_type_itemf(bContext *UNUSED(C), PointerRNA *ptr, PropertyRNA *UNUSED(prop), int *free)
+{
+ EnumPropertyItem *item = NULL;
+ EnumPropertyItem tmp;
+ int totitem=0;
+
+ /* hack, don't want to add include path to RNA just for this, since in the future RNA types
+ * for nodes should be defined locally at runtime anyway ...
+ */
+
+ tmp.value = NODE_CUSTOM;
+ tmp.identifier = "CUSTOM";
+ tmp.name = "Custom";
+ tmp.description = "Custom Node";
+ tmp.icon = ICON_NONE;
+ RNA_enum_item_add(&item, &totitem, &tmp);
+
+ tmp.value = NODE_UNDEFINED;
+ tmp.identifier = "UNDEFINED";
+ tmp.name = "UNDEFINED";
+ tmp.description = "";
+ tmp.icon = ICON_NONE;
+ RNA_enum_item_add(&item, &totitem, &tmp);
+
+ #define DefNode(Category, ID, DefFunc, EnumName, StructName, UIName, UIDesc) \
+ if (strcmp(#Category, "Node")==0) { \
+ tmp.value = ID; \
+ tmp.identifier = EnumName; \
+ tmp.name = UIName; \
+ tmp.description = UIDesc; \
+ tmp.icon = ICON_NONE; \
+ RNA_enum_item_add(&item, &totitem, &tmp); \
+ }
+ #include "../../nodes/NOD_static_types.h"
+ #undef DefNode
+
+ if (RNA_struct_is_a(ptr->type, &RNA_ShaderNode)) {
+ #define DefNode(Category, ID, DefFunc, EnumName, StructName, UIName, UIDesc) \
+ if (strcmp(#Category, "ShaderNode")==0) { \
+ tmp.value = ID; \
+ tmp.identifier = EnumName; \
+ tmp.name = UIName; \
+ tmp.description = UIDesc; \
+ tmp.icon = ICON_NONE; \
+ RNA_enum_item_add(&item, &totitem, &tmp); \
+ }
+ #include "../../nodes/NOD_static_types.h"
+ #undef DefNode
+ }
+
+ if (RNA_struct_is_a(ptr->type, &RNA_CompositorNode)) {
+ #define DefNode(Category, ID, DefFunc, EnumName, StructName, UIName, UIDesc) \
+ if (strcmp(#Category, "CompositorNode")==0) { \
+ tmp.value = ID; \
+ tmp.identifier = EnumName; \
+ tmp.name = UIName; \
+ tmp.description = UIDesc; \
+ tmp.icon = ICON_NONE; \
+ RNA_enum_item_add(&item, &totitem, &tmp); \
+ }
+ #include "../../nodes/NOD_static_types.h"
+ #undef DefNode
+ }
+
+ if (RNA_struct_is_a(ptr->type, &RNA_TextureNode)) {
+ #define DefNode(Category, ID, DefFunc, EnumName, StructName, UIName, UIDesc) \
+ if (strcmp(#Category, "TextureNode")==0) { \
+ tmp.value = ID; \
+ tmp.identifier = EnumName; \
+ tmp.name = UIName; \
+ tmp.description = UIDesc; \
+ tmp.icon = ICON_NONE; \
+ RNA_enum_item_add(&item, &totitem, &tmp); \
+ }
+ #include "../../nodes/NOD_static_types.h"
+ #undef DefNode
}
+
+ RNA_enum_item_end(&item, &totitem);
+ *free = 1;
+
+ return item;
}
+/* ******** Node Tree ******** */
+
static StructRNA *rna_NodeTree_refine(struct PointerRNA *ptr)
{
+ bNodeTree *ntree= (bNodeTree*)ptr->data;
+
+ if (ntree->typeinfo && ntree->typeinfo->ext.srna)
+ return ntree->typeinfo->ext.srna;
+ else
+ return &RNA_NodeTree;
+}
+
+static int rna_NodeTree_poll(const bContext *C, bNodeTreeType *ntreetype)
+{
+ extern FunctionRNA rna_NodeTree_poll_func;
+
+ PointerRNA ptr;
+ ParameterList list;
+ FunctionRNA *func;
+ void *ret;
+ int visible;
+
+ RNA_pointer_create(NULL, ntreetype->ext.srna, NULL, &ptr); /* dummy */
+ func = &rna_NodeTree_poll_func; /* RNA_struct_find_function(&ptr, "poll"); */
+
+ RNA_parameter_list_create(&list, &ptr, func);
+ RNA_parameter_set_lookup(&list, "context", &C);
+ ntreetype->ext.call((bContext *)C, &ptr, func, &list);
+
+ RNA_parameter_get_lookup(&list, "visible", &ret);
+ visible = *(int*)ret;
+
+ RNA_parameter_list_free(&list);
+
+ return visible;
+}
+
+static void rna_NodeTree_draw_add_menu(const bContext *C, struct uiLayout *layout, bNodeTree *ntree)
+{
+ extern FunctionRNA rna_NodeTree_draw_add_menu_func;
+
+ PointerRNA ptr;
+ ParameterList list;
+ FunctionRNA *func;
+
+ if (!ntreeIsValid(ntree))
+ return;
+
+ RNA_id_pointer_create(&ntree->id, &ptr);
+ func = &rna_NodeTree_draw_add_menu_func; /* RNA_struct_find_function(&ptr, "draw_add_menu"); */
+
+ RNA_parameter_list_create(&list, &ptr, func);
+ RNA_parameter_set_lookup(&list, "context", &C);
+ RNA_parameter_set_lookup(&list, "layout", &layout);
+ ntree->typeinfo->ext.call((bContext *)C, &ptr, func, &list);
+
+ RNA_parameter_list_free(&list);
+}
+
+static void rna_NodeTree_get_from_context(const bContext *C, bNodeTreeType *ntreetype,
+ bNodeTree **r_ntree, ID **r_id, ID **r_from)
+{
+ extern FunctionRNA rna_NodeTree_get_from_context_func;
+
+ PointerRNA ptr;
+ ParameterList list;
+ FunctionRNA *func;
+ void *ret1, *ret2, *ret3;
+
+ RNA_pointer_create(NULL, ntreetype->ext.srna, NULL, &ptr); /* dummy */
+ func = &rna_NodeTree_get_from_context_func; /* RNA_struct_find_function(&ptr, "get_from_context"); */
+
+ RNA_parameter_list_create(&list, &ptr, func);
+ RNA_parameter_set_lookup(&list, "context", &C);
+ ntreetype->ext.call((bContext *)C, &ptr, func, &list);
+
+ RNA_parameter_get_lookup(&list, "result_1", &ret1);
+ RNA_parameter_get_lookup(&list, "result_2", &ret2);
+ RNA_parameter_get_lookup(&list, "result_3", &ret3);
+ *r_ntree = *(bNodeTree **)ret1;
+ *r_id = *(ID **)ret2;
+ *r_from = *(ID **)ret3;
+
+ RNA_parameter_list_free(&list);
+}
+
+static void rna_NodeTree_unregister(Main *UNUSED(bmain), StructRNA *type)
+{
+ bNodeTreeType *nt= RNA_struct_blender_type_get(type);
+
+ if(!nt)
+ return;
+
+ RNA_struct_free_extension(type, &nt->ext);
+
+ ntreeTypeFreeLink(nt);
+
+ RNA_struct_free(&BLENDER_RNA, type);
+
+ /* update while blender is running */
+ WM_main_add_notifier(NC_NODE|NA_EDITED, NULL);
+}
+
+static StructRNA *rna_NodeTree_register(Main *bmain, ReportList *reports, void *data, const char *identifier,
+ StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
+{
+ bNodeTreeType *nt, dummynt;
+ bNodeTree dummyntree;
+ PointerRNA dummyptr;
+ int have_function[3];
+
+ /* setup dummy tree & tree type to store static properties in */
+ memset(&dummynt, 0, sizeof(bNodeTreeType));
+ memset(&dummyntree, 0, sizeof(bNodeTree));
+ dummyntree.typeinfo= &dummynt;
+ RNA_pointer_create(NULL, &RNA_NodeTree, &dummyntree, &dummyptr);
+
+ /* validate the python class */
+ if(validate(&dummyptr, data, have_function) != 0)
+ return NULL;
+
+ if(strlen(identifier) >= sizeof(dummynt.idname)) {
+ BKE_reportf(reports, RPT_ERROR, "registering node tree class: '%s' is too long, maximum length is %d",
+ identifier, (int)sizeof(dummynt.idname));
+ return NULL;
+ }
+
+ /* check if we have registered this tree type before, and remove it */
+ nt= ntreeTypeFind(dummynt.idname);
+ if(nt)
+ rna_NodeTree_unregister(bmain, nt->ext.srna);
+
+ /* create a new node tree type */
+ nt= MEM_callocN(sizeof(bNodeTreeType), "node tree type");
+ memcpy(nt, &dummynt, sizeof(dummynt));
+
+ nt->type = NTREE_CUSTOM;
+
+ nt->ext.srna= RNA_def_struct_ptr(&BLENDER_RNA, nt->idname, &RNA_NodeTree);
+ nt->ext.data= data;
+ nt->ext.call= call;
+ nt->ext.free= free;
+ RNA_struct_blender_type_set(nt->ext.srna, nt);
+
+ RNA_def_struct_ui_text(nt->ext.srna, nt->ui_name, nt->ui_description);
+ RNA_def_struct_ui_icon(nt->ext.srna, nt->ui_icon);
+
+ nt->poll = (have_function[0]) ? rna_NodeTree_poll : NULL;
+ nt->draw_add_menu = (have_function[1]) ? rna_NodeTree_draw_add_menu : NULL;
+ nt->get_from_context = (have_function[2]) ? rna_NodeTree_get_from_context : NULL;
+
+ ntreeTypeAdd(nt);
+
+ /* update while blender is running */
+ WM_main_add_notifier(NC_NODE|NA_EDITED, NULL);
+
+ return nt->ext.srna;
+}
+
+static void rna_NodeTree_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+ bNodeTree *ntree = (bNodeTree *)ptr->id.data;
+
+ /* when using border, make it so no old data from outside of
+ * border is hanging around
+ * ideally shouldn't be in RNA callback, but how to teach
+ * compo to only clear frame when border usage is actually
+ * toggling
+ */
+ if (ntree->flag & NTREE_VIEWER_BORDER) {
+ Image *ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
+ void *lock;
+ ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
+
+ if (ibuf) {
+ if (ibuf->rect)
+ memset(ibuf->rect, 0, 4 * ibuf->x * ibuf->y);
+
+ if (ibuf->rect_float)
+ memset(ibuf->rect_float, 0, 4 * ibuf->x * ibuf->y * sizeof(float));
+
+ ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
+ }
+
+ BKE_image_release_ibuf(ima, ibuf, lock);
+ }
+
+ WM_main_add_notifier(NC_NODE | NA_EDITED, NULL);
+ WM_main_add_notifier(NC_SCENE | ND_NODES, &ntree->id);
+
+ ED_node_tag_update_nodetree(bmain, ntree);
+}
+
+static bNode *rna_NodeTree_node_new(bNodeTree *ntree, bContext *C, ReportList *reports, const char *type)
+{
+ bNodeType *ntype;
+ bNode *node;
+
+ if (!ntreeIsValid(ntree)) {
+ BKE_reportf(reports, RPT_ERROR, "Node tree %s invalid", ntree->id.name+2);
+ return NULL;
+ }
+
+ ntype = nodeTypeFind(type);
+ if (!ntype) {
+ BKE_reportf(reports, RPT_ERROR, "Node type %s undefined", type);
+ return NULL;
+ }
+
+ if (ntype->poll && !ntype->poll(ntype, ntree)) {
+ BKE_reportf(reports, RPT_ERROR, "Cannot add node of type %s to node tree '%s'", type, ntree->id.name+2);
+ return NULL;
+ }
+
+ node = nodeAddNode(C, ntree, type);
+ BLI_assert(node && node->typeinfo);
+
+ /* XXX ugly stuff, should be done with specialized operators (after actual node creation)! */
+ if (ntree->type==NTREE_COMPOSIT) {
+ if(ELEM4(node->type, CMP_NODE_COMPOSITE, CMP_NODE_DEFOCUS, CMP_NODE_OUTPUT_FILE, CMP_NODE_R_LAYERS)) {
+ /* annoying, find the node tree we are in, scene can be NULL */
+ Scene *scene;
+ for(scene= CTX_data_main(C)->scene.first; scene; scene= scene->id.next) {
+ if(scene->nodetree == ntree) {
+ break;
+ }
+ }
+ node->id= (ID *)scene;
+ id_us_plus(node->id);
+ }
+
+ ntreeCompositForceHidden(ntree, CTX_data_scene(C));
+ }
+ else if (ntree->type==NTREE_TEXTURE) {
+ ntreeTexCheckCyclics(ntree);
+ }
+
+ ntreeUpdateTree(ntree);
+ nodeUpdate(ntree, node);
+ WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
+
+ return node;
+}
+
+static void rna_NodeTree_node_remove(bNodeTree *ntree, ReportList *reports, PointerRNA *node_ptr)
+{
+ bNode *node = node_ptr->data;
+
+ if (!ntreeIsValid(ntree)) {
+ BKE_reportf(reports, RPT_ERROR, "Node tree %s invalid", ntree->id.name+2);
+ return;
+ }
+
+ if (BLI_findindex(&ntree->nodes, node) == -1) {
+ BKE_reportf(reports, RPT_ERROR, "Unable to locate node '%s' in node tree", node->name);
+ return;
+ }
+
+ id_us_min(node->id);
+ nodeFreeNode(ntree, node);
+ RNA_POINTER_INVALIDATE(node_ptr);
+
+ ntreeUpdateTree(ntree); /* update group node socket links */
+ WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
+}
+
+static void rna_NodeTree_node_clear(bNodeTree *ntree, ReportList *reports)
+{
+ bNode *node = ntree->nodes.first;
+
+ if (!ntreeIsValid(ntree)) {
+ BKE_reportf(reports, RPT_ERROR, "Node tree %s invalid", ntree->id.name+2);
+ return;
+ }
+
+ while (node) {
+ bNode *next_node = node->next;
+
+ if (node->id)
+ id_us_min(node->id);
+
+ nodeFreeNode(ntree, node);
+
+ node = next_node;
+ }
+
+ ntreeUpdateTree(ntree);
+
+ WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
+}
+
+static PointerRNA rna_NodeTree_active_node_get(PointerRNA *ptr)
+{
bNodeTree *ntree = (bNodeTree *)ptr->data;
+ bNode *node = nodeGetActive(ntree);
+ return rna_pointer_inherit_refine(ptr, &RNA_Node, node);
+}
- switch (ntree->type) {
- case NTREE_SHADER:
- return &RNA_ShaderNodeTree;
- case NTREE_COMPOSIT:
- return &RNA_CompositorNodeTree;
- case NTREE_TEXTURE:
- return &RNA_TextureNodeTree;
- default:
- return &RNA_NodeTree;
+static void rna_NodeTree_active_node_set(PointerRNA *ptr, const PointerRNA value)
+{
+ bNodeTree *ntree = (bNodeTree *)ptr->data;
+ bNode *node = (bNode *)value.data;
+
+ /* activating node might require valid typeinfo */
+ if (!ntreeIsValid(ntree))
+ return;
+
+ if (node && BLI_findindex(&ntree->nodes, node) != -1)
+ nodeSetActive(ntree, node);
+ else
+ nodeClearActive(ntree);
+}
+
+static bNodeLink *rna_NodeTree_link_new(bNodeTree *ntree, ReportList *reports,
+ bNodeSocket *fromsock, bNodeSocket *tosock,
+ int verify_limits)
+{
+ bNodeLink *ret;
+ bNode *fromnode = NULL, *tonode = NULL;
+
+ if (!ntreeIsValid(ntree)) {
+ BKE_reportf(reports, RPT_ERROR, "Node tree %s invalid", ntree->id.name+2);
+ return NULL;
+ }
+
+ nodeFindNode(ntree, fromsock, &fromnode, NULL);
+ nodeFindNode(ntree, tosock, &tonode, NULL);
+
+ if (&fromsock->in_out == &tosock->in_out) {
+ BKE_report(reports, RPT_ERROR, "Same input/output direction of sockets");
+ return NULL;
+ }
+
+ if (verify_limits) {
+ /* remove other socket links if limit is exceeded */
+ if (nodeCountSocketLinks(ntree, fromsock) > fromsock->limit)
+ nodeRemSocketLinks(ntree, fromsock);
+ if (nodeCountSocketLinks(ntree, tosock) > tosock->limit)
+ nodeRemSocketLinks(ntree, tosock);
+ }
+
+ ret = nodeAddLink(ntree, fromnode, fromsock, tonode, tosock);
+
+ if (ret) {
+ if (tonode)
+ nodeUpdate(ntree, tonode);
+
+ ntreeUpdateTree(ntree);
+
+ WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
}
+ return ret;
}
-static char *rna_Node_path(PointerRNA *ptr)
+static void rna_NodeTree_link_remove(bNodeTree *ntree, ReportList *reports, PointerRNA *link_ptr)
+{
+ bNodeLink *link = link_ptr->data;
+
+ if (!ntreeIsValid(ntree)) {
+ BKE_reportf(reports, RPT_ERROR, "Node tree %s invalid", ntree->id.name+2);
+ return;
+ }
+
+ if (BLI_findindex(&ntree->links, link) == -1) {
+ BKE_report(reports, RPT_ERROR, "Unable to locate link in node tree");
+ return;
+ }
+
+ nodeRemLink(ntree, link);
+ RNA_POINTER_INVALIDATE(link_ptr);
+
+ ntreeUpdateTree(ntree);
+ WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
+}
+
+static void rna_NodeTree_link_clear(bNodeTree *ntree, ReportList *reports)
+{
+ bNodeLink *link = ntree->links.first;
+
+ if (!ntreeIsValid(ntree)) {
+ BKE_reportf(reports, RPT_ERROR, "Node tree %s invalid", ntree->id.name+2);
+ return;
+ }
+
+ while (link) {
+ bNodeLink *next_link = link->next;
+
+ nodeRemLink(ntree, link);
+
+ link = next_link;
+ }
+ ntreeUpdateTree(ntree);
+
+ WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
+}
+
+static int rna_NodeTree_active_input_get(PointerRNA *ptr)
+{
+ bNodeTree *ntree = (bNodeTree*)ptr->data;
+ bNodeSocket *gsock;
+ int index;
+
+ for (gsock = ntree->inputs.first, index = 0; gsock; gsock = gsock->next, ++index)
+ if (gsock->flag & SELECT)
+ return index;
+ return -1;
+}
+
+static void rna_NodeTree_active_input_set(PointerRNA *ptr, int value)
+{
+ bNodeTree *ntree = (bNodeTree*)ptr->data;
+ bNodeSocket *gsock;
+ int index;
+
+ for (gsock = ntree->inputs.first, index = 0; gsock; gsock = gsock->next, ++index) {
+ if (index == value)
+ gsock->flag |= SELECT;
+ else
+ gsock->flag &= ~SELECT;
+ }
+ for (gsock = ntree->outputs.first; gsock; gsock = gsock->next) {
+ gsock->flag &= ~SELECT;
+ }
+}
+
+static int rna_NodeTree_active_output_get(PointerRNA *ptr)
+{
+ bNodeTree *ntree = (bNodeTree*)ptr->data;
+ bNodeSocket *gsock;
+ int index;
+
+ for (gsock = ntree->outputs.first, index = 0; gsock; gsock = gsock->next, ++index)
+ if (gsock->flag & SELECT)
+ return index;
+ return -1;
+}
+
+static void rna_NodeTree_active_output_set(PointerRNA *ptr, int value)
+{
+ bNodeTree *ntree = (bNodeTree*)ptr->data;
+ bNodeSocket *gsock;
+ int index;
+
+ for (gsock = ntree->inputs.first; gsock; gsock = gsock->next) {
+ gsock->flag &= ~SELECT;
+ }
+ for (gsock = ntree->outputs.first, index = 0; gsock; gsock = gsock->next, ++index) {
+ if (index == value)
+ gsock->flag |= SELECT;
+ else
+ gsock->flag &= ~SELECT;
+ }
+}
+
+static int rna_NodeTree_inputs_lookupstring(PointerRNA *ptr, const char *key, PointerRNA *r_ptr)
+{
+ bNodeTree *ntree = (bNodeTree *)ptr->data;
+ bNodeSocket *sock = ntreeFindSocketInterface(ntree, SOCK_IN, key);
+ RNA_pointer_create(ptr->id.data, &RNA_NodeSocketInterface, sock, r_ptr);
+ return (sock != NULL);
+}
+
+static int rna_NodeTree_outputs_lookupstring(PointerRNA *ptr, const char *key, PointerRNA *r_ptr)
+{
+ bNodeTree *ntree = (bNodeTree *)ptr->data;
+ bNodeSocket *sock = ntreeFindSocketInterface(ntree, SOCK_OUT, key);
+ RNA_pointer_create(ptr->id.data, &RNA_NodeSocketInterface, sock, r_ptr);
+ return (sock != NULL);
+}
+
+static bNodeSocket *rna_NodeTree_inputs_new(bNodeTree *ntree, ReportList *reports, const char *type, const char *name)
+{
+ bNodeSocket *sock;
+
+ if (!ntreeIsValid(ntree)) {
+ BKE_reportf(reports, RPT_ERROR, "Node tree %s invalid", ntree->id.name+2);
+ return NULL;
+ }
+
+ sock = ntreeAddSocketInterface(ntree, SOCK_IN, type, name);
+
+ ntreeUpdateTree(ntree);
+ WM_main_add_notifier(NC_NODE|NA_EDITED, ntree);
+
+ return sock;
+}
+
+static bNodeSocket *rna_NodeTree_outputs_new(bNodeTree *ntree, ReportList *reports, const char *type, const char *name)
+{
+ bNodeSocket *sock;
+
+ if (!ntreeIsValid(ntree)) {
+ BKE_reportf(reports, RPT_ERROR, "Node tree %s invalid", ntree->id.name+2);
+ return NULL;
+ }
+
+ sock = ntreeAddSocketInterface(ntree, SOCK_OUT, type, name);
+
+ ntreeUpdateTree(ntree);
+ WM_main_add_notifier(NC_NODE|NA_EDITED, ntree);
+
+ return sock;
+}
+
+static void rna_NodeTree_socket_remove(bNodeTree *ntree, ReportList *reports, bNodeSocket *sock)
+{
+ if (!ntreeIsValid(ntree)) {
+ BKE_reportf(reports, RPT_ERROR, "Node tree %s invalid", ntree->id.name+2);
+ return;
+ }
+
+ if (BLI_findindex(&ntree->inputs, sock) == -1 && BLI_findindex(&ntree->outputs, sock) == -1) {
+ BKE_reportf(reports, RPT_ERROR, "Unable to locate socket '%s' in node", sock->identifier);
+ }
+ else {
+ ntreeRemoveSocketInterface(ntree, sock);
+
+ ntreeUpdateTree(ntree);
+ WM_main_add_notifier(NC_NODE|NA_EDITED, ntree);
+ }
+}
+
+static void rna_NodeTree_inputs_clear(bNodeTree *ntree, ReportList *reports)
+{
+ bNodeSocket *sock, *nextsock;
+
+ if (!ntreeIsValid(ntree)) {
+ BKE_reportf(reports, RPT_ERROR, "Node tree %s invalid", ntree->id.name+2);
+ return;
+ }
+
+ for (sock = ntree->inputs.first; sock; sock = nextsock) {
+ nextsock = sock->next;
+ ntreeRemoveSocketInterface(ntree, sock);
+ }
+
+ ntreeUpdateTree(ntree);
+ WM_main_add_notifier(NC_NODE|NA_EDITED, ntree);
+}
+
+static void rna_NodeTree_outputs_clear(bNodeTree *ntree, ReportList *reports)
+{
+ bNodeSocket *sock, *nextsock;
+
+ if (!ntreeIsValid(ntree)) {
+ BKE_reportf(reports, RPT_ERROR, "Node tree %s invalid", ntree->id.name+2);
+ return;
+ }
+
+ for (sock = ntree->outputs.first; sock; sock = nextsock) {
+ nextsock = sock->next;
+ ntreeRemoveSocketInterface(ntree, sock);
+ }
+
+ ntreeUpdateTree(ntree);
+ WM_main_add_notifier(NC_NODE|NA_EDITED, ntree);
+}
+
+static void rna_NodeTree_interface_update(bNodeTree *ntree, bContext *C)
+{
+ if (!ntreeIsValid(ntree))
+ return;
+
+ ntree->update |= NTREE_UPDATE_GROUP;
+ ntreeUpdateTree(ntree);
+
+ ED_node_tag_update_nodetree(CTX_data_main(C), ntree);
+}
+
+static void rna_NodeTree_bl_idname_get(PointerRNA *ptr, char *value)
+{
+ bNodeTree *ntree = ptr->data;
+ if (ntree->typeinfo)
+ strcpy(value, ntree->typeinfo->idname);
+ else
+ strcpy(value, "UNDEFINED");
+}
+static int rna_NodeTree_bl_idname_length(PointerRNA *ptr)
+{
+ bNodeTree *ntree = ptr->data;
+ if (ntree->typeinfo)
+ return strlen(ntree->typeinfo->idname);
+ else
+ return strlen("UNDEFINED");
+}
+
+static void rna_NodeTree_bl_label_get(PointerRNA *ptr, char *value)
+{
+ bNodeTree *ntree = ptr->data;
+ if (ntree->typeinfo)
+ strcpy(value, ntree->typeinfo->ui_name);
+ else
+ strcpy(value, "UNDEFINED");
+}
+static int rna_NodeTree_bl_label_length(PointerRNA *ptr)
+{
+ bNodeTree *ntree = ptr->data;
+ if (ntree->typeinfo)
+ return strlen(ntree->typeinfo->ui_name);
+ else
+ return strlen("UNDEFINED");
+}
+
+static void rna_NodeTree_bl_description_get(PointerRNA *ptr, char *value)
+{
+ bNodeTree *ntree = ptr->data;
+ if (ntree->typeinfo)
+ strcpy(value, ntree->typeinfo->ui_description);
+ else
+ strcpy(value, "UNDEFINED");
+}
+static int rna_NodeTree_bl_description_length(PointerRNA *ptr)
+{
+ bNodeTree *ntree = ptr->data;
+ if (ntree->typeinfo)
+ return strlen(ntree->typeinfo->ui_description);
+ else
+ return strlen("UNDEFINED");
+}
+
+static int rna_NodeTree_bl_icon_get(PointerRNA *ptr)
+{
+ bNodeTree *ntree = ptr->data;
+ if (ntree->typeinfo)
+ return ntree->typeinfo->ui_icon;
+ else
+ return ICON_NONE;
+}
+
+
+/* ******** NodeLink ******** */
+
+static int rna_NodeLink_is_hidden_get(PointerRNA *ptr)
+{
+ bNodeLink *link = ptr->data;
+ return nodeLinkIsHidden(link);
+}
+
+
+/* ******** Node ******** */
+
+static StructRNA *rna_Node_refine(struct PointerRNA *ptr)
{
bNode *node = (bNode *)ptr->data;
+
+ if (node->typeinfo && node->typeinfo->ext.srna)
+ return node->typeinfo->ext.srna;
+ else
+ return ptr->type;
+}
+
+static char *rna_Node_path(PointerRNA *ptr)
+{
+ bNode *node = (bNode*)ptr->data;
return BLI_sprintfN("nodes[\"%s\"]", node->name);
}
-static const char *rna_Node_get_node_type(StructRNA *type)
+static int rna_Node_poll(bNodeType *ntype, bNodeTree *ntree)
{
- bNodeType *nodetype = RNA_struct_blender_type_get(type);
- if (nodetype) {
- /* XXX hack: with customnodes branch, nodes will use an identifier string instead of integer ID.
- * Then this can be returned directly instead of doing this ugly include thingy ...
- */
- #define DefNode(Category, ID, DefFunc, EnumName, StructName, UIName, UIDesc) \
- if (ID == nodetype->type) { \
- return EnumName; \
- }
-
- #include "rna_nodetree_types.h"
+ extern FunctionRNA rna_Node_poll_func;
+
+ PointerRNA ptr;
+ ParameterList list;
+ FunctionRNA *func;
+ void *ret;
+ int visible;
+
+ RNA_pointer_create(NULL, ntype->ext.srna, NULL, &ptr); /* dummy */
+ func = &rna_Node_poll_func; /* RNA_struct_find_function(&ptr, "poll"); */
+
+ RNA_parameter_list_create(&list, &ptr, func);
+ RNA_parameter_set_lookup(&list, "node_tree", &ntree);
+ ntype->ext.call(NULL, &ptr, func, &list);
+
+ RNA_parameter_get_lookup(&list, "visible", &ret);
+ visible = *(int*)ret;
+
+ RNA_parameter_list_free(&list);
+
+ return visible;
+}
+
+static int rna_Node_poll_instance(bNode *node, bNodeTree *ntree)
+{
+ extern FunctionRNA rna_Node_poll_instance_func;
+
+ PointerRNA ptr;
+ ParameterList list;
+ FunctionRNA *func;
+ void *ret;
+ int visible;
+
+ if (!node->typeinfo)
+ return FALSE;
+
+ RNA_pointer_create(NULL, node->typeinfo->ext.srna, node, &ptr); /* dummy */
+ func = &rna_Node_poll_instance_func; /* RNA_struct_find_function(&ptr, "poll_instance"); */
+
+ RNA_parameter_list_create(&list, &ptr, func);
+ RNA_parameter_set_lookup(&list, "node_tree", &ntree);
+ node->typeinfo->ext.call(NULL, &ptr, func, &list);
+
+ RNA_parameter_get_lookup(&list, "visible", &ret);
+ visible = *(int*)ret;
+
+ RNA_parameter_list_free(&list);
+
+ return visible;
+}
+
+static int rna_Node_poll_instance_default(bNode *node, bNodeTree *ntree)
+{
+ if (!node->typeinfo)
+ return FALSE;
+
+ /* use the basic poll function */
+ return rna_Node_poll(node->typeinfo, ntree);
+}
+
+static void rna_Node_update_reg(bNodeTree *ntree, bNode *node)
+{
+ extern FunctionRNA rna_Node_update_func;
+
+ PointerRNA ptr;
+ ParameterList list;
+ FunctionRNA *func;
+
+ if (!node->typeinfo)
+ return;
+
+ RNA_pointer_create((ID *)ntree, node->typeinfo->ext.srna, node, &ptr);
+ func = &rna_Node_update_func; /* RNA_struct_find_function(&ptr, "update"); */
+
+ RNA_parameter_list_create(&list, &ptr, func);
+ node->typeinfo->ext.call(NULL, &ptr, func, &list);
+
+ RNA_parameter_list_free(&list);
+}
+
+static void rna_Node_init(const bContext *C, PointerRNA *ptr)
+{
+ extern FunctionRNA rna_Node_init_func;
+
+ bNode *node = (bNode *)ptr->data;
+ ParameterList list;
+ FunctionRNA *func;
+
+ if (!node->typeinfo)
+ return;
+
+ func = &rna_Node_init_func; /* RNA_struct_find_function(&ptr, "init"); */
+
+ RNA_parameter_list_create(&list, ptr, func);
+ node->typeinfo->ext.call((bContext *)C, ptr, func, &list);
+
+ RNA_parameter_list_free(&list);
+}
+
+static void rna_Node_copy(PointerRNA *ptr, struct bNode *copynode)
+{
+ extern FunctionRNA rna_Node_copy_func;
+
+ bNode *node = (bNode *)ptr->data;
+ ParameterList list;
+ FunctionRNA *func;
+
+ if (!node->typeinfo)
+ return;
+
+ func = &rna_Node_copy_func; /* RNA_struct_find_function(&ptr, "copy"); */
+
+ RNA_parameter_list_create(&list, ptr, func);
+ RNA_parameter_set_lookup(&list, "node", &copynode);
+ node->typeinfo->ext.call(NULL, ptr, func, &list);
+
+ RNA_parameter_list_free(&list);
+}
+
+static void rna_Node_free(PointerRNA *ptr)
+{
+ extern FunctionRNA rna_Node_free_func;
+
+ bNode *node = (bNode *)ptr->data;
+ ParameterList list;
+ FunctionRNA *func;
+
+ if (!node->typeinfo)
+ return;
+
+ func = &rna_Node_free_func; /* RNA_struct_find_function(&ptr, "free"); */
+
+ RNA_parameter_list_create(&list, ptr, func);
+ node->typeinfo->ext.call(NULL, ptr, func, &list);
+
+ RNA_parameter_list_free(&list);
+}
+
+static void rna_Node_draw_buttons(struct uiLayout *layout, bContext *C, PointerRNA *ptr)
+{
+ extern FunctionRNA rna_Node_draw_buttons_func;
+
+ bNode *node = (bNode *)ptr->data;
+ ParameterList list;
+ FunctionRNA *func;
+
+ if (!node->typeinfo)
+ return;
+
+ func = &rna_Node_draw_buttons_func; /* RNA_struct_find_function(&ptr, "draw_buttons"); */
+
+ RNA_parameter_list_create(&list, ptr, func);
+ RNA_parameter_set_lookup(&list, "context", &C);
+ RNA_parameter_set_lookup(&list, "layout", &layout);
+ node->typeinfo->ext.call(C, ptr, func, &list);
+
+ RNA_parameter_list_free(&list);
+}
+
+static void rna_Node_draw_buttons_ext(struct uiLayout *layout, bContext *C, PointerRNA *ptr)
+{
+ extern FunctionRNA rna_Node_draw_buttons_ext_func;
+
+ bNode *node = (bNode *)ptr->data;
+ ParameterList list;
+ FunctionRNA *func;
+
+ if (!node->typeinfo)
+ return;
+
+ func = &rna_Node_draw_buttons_ext_func; /* RNA_struct_find_function(&ptr, "draw_buttons_ext"); */
+
+ RNA_parameter_list_create(&list, ptr, func);
+ RNA_parameter_set_lookup(&list, "context", &C);
+ RNA_parameter_set_lookup(&list, "layout", &layout);
+ node->typeinfo->ext.call(C, ptr, func, &list);
+
+ RNA_parameter_list_free(&list);
+}
+
+static int rna_Node_is_registered_node_type(StructRNA *type)
+{
+ return (RNA_struct_blender_type_get(type) != NULL);
+}
+
+static void rna_Node_is_registered_node_type_runtime(bContext *UNUSED(C), ReportList *UNUSED(reports), PointerRNA *ptr, ParameterList *parms)
+{
+ int result = (RNA_struct_blender_type_get(ptr->type) != NULL);
+ RNA_parameter_set_lookup(parms, "result", &result);
+}
+
+static void rna_Node_unregister(Main *UNUSED(bmain), StructRNA *type)
+{
+ bNodeType *nt= RNA_struct_blender_type_get(type);
+
+ if(!nt)
+ return;
+
+ RNA_struct_free_extension(type, &nt->ext);
+
+ /* this also frees the allocated nt pointer, no MEM_free call needed! */
+ nodeUnregisterType(nt);
+
+ RNA_struct_free(&BLENDER_RNA, type);
+
+ /* update while blender is running */
+ WM_main_add_notifier(NC_NODE|NA_EDITED, NULL);
+}
+
+/* Generic internal registration function.
+ * Can be used to implement callbacks for registerable RNA node subtypes.
+ */
+static bNodeType *rna_Node_register_base(Main *bmain, ReportList *reports, StructRNA *basetype,
+ void *data, const char *identifier,
+ StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
+{
+ bNodeType *nt, dummynt;
+ bNode dummynode;
+ PointerRNA dummyptr;
+ FunctionRNA *func;
+ PropertyRNA *parm;
+ int have_function[8];
+
+ /* setup dummy node & node type to store static properties in */
+ memset(&dummynt, 0, sizeof(bNodeType));
+ /* this does some additional initialization of default values */
+ node_type_base_custom(&dummynt, identifier, "", 0, 0);
+
+ memset(&dummynode, 0, sizeof(bNode));
+ dummynode.typeinfo= &dummynt;
+ RNA_pointer_create(NULL, basetype, &dummynode, &dummyptr);
+
+ /* validate the python class */
+ if(validate(&dummyptr, data, have_function) != 0)
+ return NULL;
+
+ if(strlen(identifier) >= sizeof(dummynt.idname)) {
+ BKE_reportf(reports, RPT_ERROR, "registering node class: '%s' is too long, maximum length is %d",
+ identifier, (int)sizeof(dummynt.idname));
+ return NULL;
+ }
+
+ /* check if we have registered this node type before, and remove it */
+ nt= nodeTypeFind(dummynt.idname);
+ if(nt)
+ rna_Node_unregister(bmain, nt->ext.srna);
+
+ /* create a new node type */
+ nt= MEM_callocN(sizeof(bNodeType), "node type");
+ memcpy(nt, &dummynt, sizeof(dummynt));
+ /* make sure the node type struct is freed on unregister */
+ nt->needs_free = 1;
+
+ nt->ext.srna= RNA_def_struct_ptr(&BLENDER_RNA, nt->idname, basetype);
+ nt->ext.data= data;
+ nt->ext.call= call;
+ nt->ext.free= free;
+ RNA_struct_blender_type_set(nt->ext.srna, nt);
+
+ RNA_def_struct_ui_text(nt->ext.srna, nt->ui_name, nt->ui_description);
+ RNA_def_struct_ui_icon(nt->ext.srna, nt->ui_icon);
+
+ func = RNA_def_function_runtime(nt->ext.srna, "is_registered_node_type", rna_Node_is_registered_node_type_runtime);
+ RNA_def_function_ui_description(func, "True if a registered node type");
+ RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_USE_SELF_TYPE);
+ parm = RNA_def_boolean(func, "result", FALSE, "Result", "");
+ RNA_def_function_return(func, parm);
+
+ /* XXX bad level call! needed to initialize the basic draw functions ... */
+ ED_init_custom_node_type(nt);
+
+ nt->poll = (have_function[0]) ? rna_Node_poll : NULL;
+ nt->poll_instance = (have_function[1]) ? rna_Node_poll_instance : rna_Node_poll_instance_default;
+ nt->updatefunc = (have_function[2]) ? rna_Node_update_reg : NULL;
+ nt->initfunc_api = (have_function[3]) ? rna_Node_init : NULL;
+ nt->copyfunc_api = (have_function[4]) ? rna_Node_copy : NULL;
+ nt->freefunc_api = (have_function[5]) ? rna_Node_free : NULL;
+ nt->uifunc = (have_function[6]) ? rna_Node_draw_buttons : NULL;
+ nt->uifuncbut = (have_function[7]) ? rna_Node_draw_buttons_ext : NULL;
+ /* node buttons are only drawn if the options flag is set */
+ if (nt->uifunc || nt->uifuncbut)
+ nt->flag |= NODE_OPTIONS;
+
+ return nt;
+}
+
+static StructRNA *rna_Node_register(Main *bmain, ReportList *reports,
+ void *data, const char *identifier,
+ StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
+{
+ bNodeType *nt = rna_Node_register_base(bmain, reports, &RNA_Node, data, identifier, validate, call, free);
+ if (!nt)
+ return NULL;
+
+ nodeRegisterType(nt);
+
+ /* update while blender is running */
+ WM_main_add_notifier(NC_NODE|NA_EDITED, NULL);
+
+ return nt->ext.srna;
+}
+
+static StructRNA *rna_NodeGroup_register(Main *bmain, ReportList *reports,
+ void *data, const char *identifier,
+ StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
+{
+ bNodeType *nt = rna_Node_register_base(bmain, reports, &RNA_NodeGroup, data, identifier, validate, call, free);
+ if (!nt)
+ return NULL;
+
+ nodeRegisterType(nt);
+
+ /* update while blender is running */
+ WM_main_add_notifier(NC_NODE|NA_EDITED, NULL);
+
+ return nt->ext.srna;
+}
+
+static StructRNA *rna_ShaderNode_register(Main *bmain, ReportList *reports,
+ void *data, const char *identifier,
+ StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
+{
+ bNodeType *nt = rna_Node_register_base(bmain, reports, &RNA_ShaderNode, data, identifier, validate, call, free);
+ if (!nt)
+ return NULL;
+
+ nodeRegisterType(nt);
+
+ /* update while blender is running */
+ WM_main_add_notifier(NC_NODE|NA_EDITED, NULL);
+
+ return nt->ext.srna;
+}
+
+static StructRNA *rna_CompositorNode_register(Main *bmain, ReportList *reports,
+ void *data, const char *identifier,
+ StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
+{
+ bNodeType *nt = rna_Node_register_base(bmain, reports, &RNA_CompositorNode, data, identifier, validate, call, free);
+ if (!nt)
+ return NULL;
+
+ nodeRegisterType(nt);
+
+ /* update while blender is running */
+ WM_main_add_notifier(NC_NODE|NA_EDITED, NULL);
+
+ return nt->ext.srna;
+}
+
+static StructRNA *rna_TextureNode_register(Main *bmain, ReportList *reports,
+ void *data, const char *identifier,
+ StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
+{
+ bNodeType *nt = rna_Node_register_base(bmain, reports, &RNA_TextureNode, data, identifier, validate, call, free);
+ if (!nt)
+ return NULL;
+
+ nodeRegisterType(nt);
+
+ /* update while blender is running */
+ WM_main_add_notifier(NC_NODE|NA_EDITED, NULL);
+
+ return nt->ext.srna;
+}
+
+static IDProperty *rna_Node_idprops(PointerRNA *ptr, bool create)
+{
+ bNode *node = ptr->data;
+
+ if (create && !node->prop) {
+ IDPropertyTemplate val = {0};
+ node->prop = IDP_New(IDP_GROUP, &val, "RNA_Node ID properties");
}
- return "";
+
+ return node->prop;
}
static void rna_Node_parent_set(PointerRNA *ptr, PointerRNA value)
@@ -330,47 +1576,388 @@ static int rna_Node_parent_poll(PointerRNA *ptr, PointerRNA value)
return TRUE;
}
-static StructRNA *rna_NodeSocket_refine(PointerRNA *ptr)
+static void rna_Node_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
- bNodeSocket *sock = (bNodeSocket *)ptr->data;
+ bNodeTree *ntree = (bNodeTree*)ptr->id.data;
+ ED_node_tag_update_nodetree(bmain, ntree);
+}
+
+static void rna_Node_socket_value_update(ID *id, bNode *UNUSED(node), bContext *C)
+{
+ ED_node_tag_update_nodetree(CTX_data_main(C), (bNodeTree *)id);
+}
+
+static void rna_Node_select_set(PointerRNA *ptr, int value)
+{
+ bNode *node= (bNode*)ptr->data;
+ nodeSetSelected(node, value);
+}
+
+static void rna_Node_name_set(PointerRNA *ptr, const char *value)
+{
+ bNodeTree *ntree = (bNodeTree*)ptr->id.data;
+ bNode *node = (bNode*)ptr->data;
+ char oldname[sizeof(node->name)];
- if (sock->default_value) {
- /* This returns the refined socket type with the full definition
- * of the default input value with type and subtype.
- */
-
- #define SUBTYPE(socktype, stypename, id, idname) \
- { \
- bNodeSocketValue##stypename *value = (bNodeSocketValue##stypename *)sock->default_value; \
- if (value->subtype == PROP_##id) \
- return &RNA_NodeSocket##stypename##idname; \
- }
+ /* make a copy of the old name first */
+ BLI_strncpy(oldname, node->name, sizeof(node->name));
+ /* set new name */
+ BLI_strncpy_utf8(node->name, value, sizeof(node->name));
+
+ nodeUniqueName(ntree, node);
+
+ /* fix all the animation data which may link to this */
+ BKE_all_animdata_fix_paths_rename(NULL, "nodes", oldname, node->name);
+}
+
+static int rna_Node_inputs_lookupstring(PointerRNA *ptr, const char *key, PointerRNA *r_ptr)
+{
+ bNode *node = (bNode *)ptr->data;
+ bNodeSocket *sock = nodeFindSocket(node, SOCK_IN, key);
+ RNA_pointer_create(ptr->id.data, &RNA_NodeSocket, sock, r_ptr);
+ return (sock != NULL);
+}
+
+static int rna_Node_outputs_lookupstring(PointerRNA *ptr, const char *key, PointerRNA *r_ptr)
+{
+ bNode *node = (bNode *)ptr->data;
+ bNodeSocket *sock = nodeFindSocket(node, SOCK_OUT, key);
+ RNA_pointer_create(ptr->id.data, &RNA_NodeSocket, sock, r_ptr);
+ return (sock != NULL);
+}
+
+static bNodeSocket *rna_Node_inputs_new(ID *id, bNode *node, ReportList *reports, const char *type, const char *name, const char *identifier)
+{
+ bNodeTree *ntree = (bNodeTree *)id;
+ bNodeSocket *sock;
+
+ if (!node->typeinfo) {
+ BKE_reportf(reports, RPT_ERROR, "Node type %s of node %s undefined", node->idname, node->name);
+ return NULL;
+ }
+
+ sock = nodeAddSocket(ntree, node, SOCK_IN, type, identifier, name);
+
+ if (sock == NULL) {
+ BKE_report(reports, RPT_ERROR, "Unable to create socket");
+ }
+ else {
+ ntreeUpdateTree(ntree);
+ WM_main_add_notifier(NC_NODE|NA_EDITED, ntree);
+ }
+
+ return sock;
+}
+
+static bNodeSocket *rna_Node_outputs_new(ID *id, bNode *node, ReportList *reports, const char *type, const char *name, const char *identifier)
+{
+ bNodeTree *ntree = (bNodeTree *)id;
+ bNodeSocket *sock;
+
+ if (!node->typeinfo) {
+ BKE_reportf(reports, RPT_ERROR, "Node type %s of node %s undefined", node->idname, node->name);
+ return NULL;
+ }
+
+ sock = nodeAddSocket(ntree, node, SOCK_OUT, type, identifier, name);
+
+ if (sock == NULL) {
+ BKE_reportf(reports, RPT_ERROR, "Unable to create socket");
+ }
+ else {
+ ntreeUpdateTree(ntree);
+ WM_main_add_notifier(NC_NODE|NA_EDITED, ntree);
+ }
+
+ return sock;
+}
+
+static void rna_Node_socket_remove(ID *id, bNode *node, ReportList *reports, bNodeSocket *sock)
+{
+ bNodeTree *ntree = (bNodeTree *)id;
+
+ if (!node->typeinfo) {
+ BKE_reportf(reports, RPT_ERROR, "Node type %s of node %s undefined", node->idname, node->name);
+ return;
+ }
+
+ if (BLI_findindex(&node->inputs, sock) == -1 && BLI_findindex(&node->outputs, sock) == -1) {
+ BKE_reportf(reports, RPT_ERROR, "Unable to locate socket '%s' in node", sock->identifier);
+ }
+ else {
+ nodeRemoveSocket(ntree, node, sock);
- switch (sock->type) {
- case SOCK_FLOAT:
- NODE_DEFINE_SUBTYPES_FLOAT
- break;
- case SOCK_INT:
- NODE_DEFINE_SUBTYPES_INT
- break;
- case SOCK_BOOLEAN:
- return &RNA_NodeSocketBoolean;
- case SOCK_VECTOR:
- NODE_DEFINE_SUBTYPES_VECTOR
- break;
- case SOCK_STRING:
- NODE_DEFINE_SUBTYPES_STRING
- break;
- case SOCK_RGBA:
- return &RNA_NodeSocketRGBA;
- case SOCK_SHADER:
- return &RNA_NodeSocketShader;
- }
+ ntreeUpdateTree(ntree);
+ WM_main_add_notifier(NC_NODE|NA_EDITED, ntree);
+ }
+}
+
+static void rna_Node_inputs_clear(ID *id, bNode *node, ReportList *reports)
+{
+ bNodeTree *ntree = (bNodeTree *)id;
+ bNodeSocket *sock, *nextsock;
+
+ if (!node->typeinfo) {
+ BKE_reportf(reports, RPT_ERROR, "Node type %s of node %s undefined", node->idname, node->name);
+ return;
+ }
+
+ for (sock = node->inputs.first; sock; sock = nextsock) {
+ nextsock = sock->next;
+ nodeRemoveSocket(ntree, node, sock);
+ }
+
+ ntreeUpdateTree(ntree);
+ WM_main_add_notifier(NC_NODE|NA_EDITED, ntree);
+}
+
+static void rna_Node_outputs_clear(ID *id, bNode *node, ReportList *reports)
+{
+ bNodeTree *ntree = (bNodeTree *)id;
+ bNodeSocket *sock, *nextsock;
+
+ if (!node->typeinfo) {
+ BKE_reportf(reports, RPT_ERROR, "Node type %s of node %s undefined", node->idname, node->name);
+ return;
+ }
+
+ for (sock = node->outputs.first; sock; sock = nextsock) {
+ nextsock = sock->next;
+ nodeRemoveSocket(ntree, node, sock);
+ }
+
+ ntreeUpdateTree(ntree);
+ WM_main_add_notifier(NC_NODE|NA_EDITED, ntree);
+}
+
+static void rna_Node_width_range(PointerRNA *ptr, float *min, float *max, float *softmin, float *softmax)
+{
+ bNode *node = ptr->data;
+ if (node->typeinfo) {
+ *min = *softmin = node->typeinfo->minwidth;
+ *max = *softmax = node->typeinfo->maxwidth;
+ }
+ else {
+ *min = *softmin = 0.0f;
+ *max = *softmax = 0.0f;
+ }
+}
+
+static void rna_Node_height_range(PointerRNA *ptr, float *min, float *max, float *softmin, float *softmax)
+{
+ bNode *node = ptr->data;
+ if (node->typeinfo) {
+ *min = *softmin = node->typeinfo->minheight;
+ *max = *softmax = node->typeinfo->maxheight;
+ }
+ else {
+ *min = *softmin = 0.0f;
+ *max = *softmax = 0.0f;
+ }
+}
+
+static void rna_Node_bl_idname_get(PointerRNA *ptr, char *value)
+{
+ bNode *node= ptr->data;
+ if (node->typeinfo)
+ strcpy(value, node->typeinfo->idname);
+ else
+ strcpy(value, "UNDEFINED");
+}
+static int rna_Node_bl_idname_length(PointerRNA *ptr)
+{
+ bNode *node = ptr->data;
+ if (node->typeinfo)
+ return strlen(node->typeinfo->idname);
+ else
+ return strlen("UNDEFINED");
+}
+
+static void rna_Node_bl_label_get(PointerRNA *ptr, char *value)
+{
+ bNode *node= ptr->data;
+ if (node->typeinfo)
+ strcpy(value, node->typeinfo->ui_name);
+ else
+ strcpy(value, "UNDEFINED");
+}
+static int rna_Node_bl_label_length(PointerRNA *ptr)
+{
+ bNode *node = ptr->data;
+ if (node->typeinfo)
+ return strlen(node->typeinfo->ui_name);
+ else
+ return strlen("UNDEFINED");
+}
+
+static void rna_Node_bl_description_get(PointerRNA *ptr, char *value)
+{
+ bNode *node= ptr->data;
+ if (node->typeinfo)
+ strcpy(value, node->typeinfo->ui_description);
+ else
+ strcpy(value, "");
+}
+static int rna_Node_bl_description_length(PointerRNA *ptr)
+{
+ bNode *node = ptr->data;
+ if (node->typeinfo)
+ return strlen(node->typeinfo->ui_description);
+ else
+ return strlen("");
+}
+
+static int rna_Node_bl_icon_get(PointerRNA *ptr)
+{
+ bNode *node = ptr->data;
+ if (node->typeinfo)
+ return node->typeinfo->ui_icon;
+ else
+ return ICON_NONE;
+}
+
+static int rna_Node_bl_static_type_get(PointerRNA *ptr)
+{
+ bNode *node = ptr->data;
+ if (node->typeinfo)
+ return node->typeinfo->type;
+ else
+ return NODE_UNDEFINED;
+}
+
+
+/* ******** Node Socket ******** */
+
+static void rna_NodeSocket_draw(bContext *C, struct uiLayout *layout, PointerRNA *ptr, PointerRNA *node_ptr)
+{
+ extern FunctionRNA rna_NodeSocket_draw_func;
+
+ bNodeSocket *sock = (bNodeSocket *)ptr->data;
+ ParameterList list;
+ FunctionRNA *func;
+
+ if (!sock->typeinfo)
+ return;
+
+ func = &rna_NodeSocket_draw_func; /* RNA_struct_find_function(&ptr, "draw"); */
+
+ RNA_parameter_list_create(&list, ptr, func);
+ RNA_parameter_set_lookup(&list, "context", &C);
+ RNA_parameter_set_lookup(&list, "layout", &layout);
+ RNA_parameter_set_lookup(&list, "node", node_ptr);
+ sock->typeinfo->ext_socket.call(C, ptr, func, &list);
+
+ RNA_parameter_list_free(&list);
+}
+
+static void rna_NodeSocket_draw_color(bContext *C, PointerRNA *ptr, PointerRNA *node_ptr, float *r_color)
+{
+ extern FunctionRNA rna_NodeSocket_draw_color_func;
+
+ bNodeSocket *sock = (bNodeSocket *)ptr->data;
+ ParameterList list;
+ FunctionRNA *func;
+ void *ret;
+
+ if (!sock->typeinfo)
+ return;
+
+ func = &rna_NodeSocket_draw_color_func; /* RNA_struct_find_function(&ptr, "draw_color"); */
+
+ RNA_parameter_list_create(&list, ptr, func);
+ RNA_parameter_set_lookup(&list, "context", &C);
+ RNA_parameter_set_lookup(&list, "node", node_ptr);
+ sock->typeinfo->ext_socket.call(C, ptr, func, &list);
+
+ RNA_parameter_get_lookup(&list, "color", &ret);
+ copy_v4_v4(r_color, (float *)ret);
+
+ RNA_parameter_list_free(&list);
+}
+
+static void rna_NodeSocket_unregister(Main *UNUSED(bmain), StructRNA *type)
+{
+ bNodeSocketType *st= RNA_struct_blender_type_get(type);
+ if(!st)
+ return;
+
+ RNA_struct_free_extension(type, &st->ext_socket);
+
+ nodeUnregisterSocketType(st);
+
+ RNA_struct_free(&BLENDER_RNA, type);
+
+ /* update while blender is running */
+ WM_main_add_notifier(NC_NODE|NA_EDITED, NULL);
+}
+
+static StructRNA *rna_NodeSocket_register(Main *bmain, ReportList *reports, void *data, const char *identifier,
+ StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
+{
+ bNodeSocketType *st, dummyst;
+ bNodeSocket dummysock;
+ PointerRNA dummyptr;
+ int have_function[2];
+
+ /* setup dummy socket & socket type to store static properties in */
+ memset(&dummyst, 0, sizeof(bNodeSocketType));
+
+ memset(&dummysock, 0, sizeof(bNodeSocket));
+ dummysock.typeinfo= &dummyst;
+ RNA_pointer_create(NULL, &RNA_NodeSocket, &dummysock, &dummyptr);
+
+ /* validate the python class */
+ if(validate(&dummyptr, data, have_function) != 0)
+ return NULL;
+
+ if(strlen(identifier) >= sizeof(dummyst.idname)) {
+ BKE_reportf(reports, RPT_ERROR, "registering node socket class: '%s' is too long, maximum length is %d",
+ identifier, (int)sizeof(dummyst.idname));
+ return NULL;
+ }
+
+ /* check if we have registered this socket type before */
+ st= nodeSocketTypeFind(dummyst.idname);
+ if (!st) {
+ /* create a new node socket type */
+ st= MEM_callocN(sizeof(bNodeSocketType), "node socket type");
+ memcpy(st, &dummyst, sizeof(dummyst));
- #undef SUBTYPE
+ nodeRegisterSocketType(st);
+ }
+
+ /* if RNA type is already registered, unregister first */
+ if (st->ext_socket.srna) {
+ StructRNA *srna = st->ext_socket.srna;
+ RNA_struct_free_extension(srna, &st->ext_socket);
+ RNA_struct_free(&BLENDER_RNA, srna);
}
+ st->ext_socket.srna= RNA_def_struct_ptr(&BLENDER_RNA, st->idname, &RNA_NodeSocket);
+ st->ext_socket.data= data;
+ st->ext_socket.call= call;
+ st->ext_socket.free= free;
+ RNA_struct_blender_type_set(st->ext_socket.srna, st);
- return &RNA_NodeSocket;
+ /* XXX bad level call! needed to initialize the basic draw functions ... */
+ ED_init_custom_node_socket_type(st);
+
+ st->draw = (have_function[0]) ? rna_NodeSocket_draw : NULL;
+ st->draw_color = (have_function[1]) ? rna_NodeSocket_draw_color : NULL;
+
+ /* update while blender is running */
+ WM_main_add_notifier(NC_NODE|NA_EDITED, NULL);
+
+ return st->ext_socket.srna;
+}
+
+static StructRNA *rna_NodeSocket_refine(PointerRNA *ptr)
+{
+ bNodeSocket *sock = (bNodeSocket *)ptr->data;
+
+ if (sock->typeinfo && sock->typeinfo->ext_socket.srna)
+ return sock->typeinfo->ext_socket.srna;
+ else
+ return &RNA_NodeSocket;
}
static char *rna_NodeSocket_path(PointerRNA *ptr)
@@ -380,29 +1967,65 @@ static char *rna_NodeSocket_path(PointerRNA *ptr)
bNode *node;
int socketindex;
- /* group sockets */
- socketindex = BLI_findindex(&ntree->inputs, sock);
- if (socketindex != -1)
- return BLI_sprintfN("inputs[%d]", socketindex);
-
- socketindex = BLI_findindex(&ntree->outputs, sock);
- if (socketindex != -1)
- return BLI_sprintfN("outputs[%d]", socketindex);
-
- /* node sockets */
- if (!nodeFindNode(ntree, sock, &node, NULL, NULL)) return NULL;
+ if (!nodeFindNode(ntree, sock, &node, &socketindex))
+ return NULL;
- socketindex = BLI_findindex(&node->inputs, sock);
- if (socketindex != -1)
+ if (sock->in_out == SOCK_IN)
return BLI_sprintfN("nodes[\"%s\"].inputs[%d]", node->name, socketindex);
-
- socketindex = BLI_findindex(&node->outputs, sock);
- if (socketindex != -1)
+ else
return BLI_sprintfN("nodes[\"%s\"].outputs[%d]", node->name, socketindex);
return NULL;
}
+static IDProperty *rna_NodeSocket_idprops(PointerRNA *ptr, bool create)
+{
+ bNodeSocket *sock = ptr->data;
+
+ if (create && !sock->prop) {
+ IDPropertyTemplate val = {0};
+ sock->prop = IDP_New(IDP_GROUP, &val, "RNA_NodeSocket ID properties");
+ }
+
+ return sock->prop;
+}
+
+static void rna_NodeSocket_bl_idname_get(PointerRNA *ptr, char *value)
+{
+ bNodeSocket *sock = ptr->data;
+ if (sock->typeinfo)
+ strcpy(value, sock->typeinfo->idname);
+ else
+ strcpy(value, "UNDEFINED");
+}
+static int rna_NodeSocket_bl_idname_length(PointerRNA *ptr)
+{
+ bNodeSocket *sock = ptr->data;
+ if (sock->typeinfo)
+ return strlen(sock->typeinfo->idname);
+ else
+ return strlen("UNDEFINED");
+}
+
+static PointerRNA rna_NodeSocket_node_get(PointerRNA *ptr)
+{
+ bNodeTree *ntree = (bNodeTree*)ptr->id.data;
+ bNodeSocket *sock = (bNodeSocket *)ptr->data;
+ bNode *node;
+ PointerRNA r_ptr;
+
+ nodeFindNode(ntree, sock, &node, NULL);
+
+ RNA_pointer_create((ID *)ntree, &RNA_Node, node, &r_ptr);
+ return r_ptr;
+}
+
+static void rna_NodeSocket_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
+{
+ bNodeTree *ntree = (bNodeTree*)ptr->id.data;
+ ED_node_tag_update_nodetree(bmain, ntree);
+}
+
static void rna_NodeSocket_hide_set(PointerRNA *ptr, int value)
{
bNodeSocket *sock = (bNodeSocket *)ptr->data;
@@ -417,151 +2040,334 @@ static void rna_NodeSocket_hide_set(PointerRNA *ptr, int value)
sock->flag &= ~SOCK_HIDDEN;
}
-/* Button Set Funcs for Matte Nodes */
-static void rna_Matte_t1_set(PointerRNA *ptr, float value)
+
+static void rna_NodeSocketInterface_draw(bContext *C, struct uiLayout *layout, PointerRNA *ptr)
{
- bNode *node = (bNode *)ptr->data;
- NodeChroma *chroma = node->storage;
-
- chroma->t1 = value;
-
- if (value < chroma->t2)
- chroma->t2 = value;
+ extern FunctionRNA rna_NodeSocketInterface_draw_func;
+
+ bNodeSocket *stemp = (bNodeSocket *)ptr->data;
+ ParameterList list;
+ FunctionRNA *func;
+
+ if (!stemp->typeinfo)
+ return;
+
+ func = &rna_NodeSocketInterface_draw_func; /* RNA_struct_find_function(&ptr, "draw"); */
+
+ RNA_parameter_list_create(&list, ptr, func);
+ RNA_parameter_set_lookup(&list, "context", &C);
+ RNA_parameter_set_lookup(&list, "layout", &layout);
+ stemp->typeinfo->ext_interface.call(C, ptr, func, &list);
+
+ RNA_parameter_list_free(&list);
}
-static void rna_Matte_t2_set(PointerRNA *ptr, float value)
+static void rna_NodeSocketInterface_draw_color(bContext *C, PointerRNA *ptr, float *r_color)
{
- bNode *node = (bNode *)ptr->data;
- NodeChroma *chroma = node->storage;
-
- if (value > chroma->t1)
- value = chroma->t1;
-
- chroma->t2 = value;
+ extern FunctionRNA rna_NodeSocketInterface_draw_color_func;
+
+ bNodeSocket *sock = (bNodeSocket *)ptr->data;
+ ParameterList list;
+ FunctionRNA *func;
+ void *ret;
+
+ if (!sock->typeinfo)
+ return;
+
+ func = &rna_NodeSocketInterface_draw_color_func; /* RNA_struct_find_function(&ptr, "draw_color"); */
+
+ RNA_parameter_list_create(&list, ptr, func);
+ RNA_parameter_set_lookup(&list, "context", &C);
+ sock->typeinfo->ext_interface.call(C, ptr, func, &list);
+
+ RNA_parameter_get_lookup(&list, "color", &ret);
+ copy_v4_v4(r_color, (float *)ret);
+
+ RNA_parameter_list_free(&list);
}
-static void rna_distance_matte_t1_set(PointerRNA *ptr, float value)
+static void rna_NodeSocketInterface_register_properties(bNodeTree *ntree, bNodeSocket *stemp, StructRNA *data_srna)
{
- bNode *node = (bNode *)ptr->data;
- NodeChroma *chroma = node->storage;
+ extern FunctionRNA rna_NodeSocketInterface_register_properties_func;
- chroma->t1 = value;
+ PointerRNA ptr;
+ ParameterList list;
+ FunctionRNA *func;
+
+ if (!stemp->typeinfo)
+ return;
+
+ RNA_pointer_create((ID *)ntree, &RNA_NodeSocketInterface, stemp, &ptr);
+ func = &rna_NodeSocketInterface_register_properties_func; /* RNA_struct_find_function(&ptr, "register_properties"); */
+
+ RNA_parameter_list_create(&list, &ptr, func);
+ RNA_parameter_set_lookup(&list, "data_rna_type", &data_srna);
+ stemp->typeinfo->ext_interface.call(NULL, &ptr, func, &list);
+
+ RNA_parameter_list_free(&list);
}
-static void rna_distance_matte_t2_set(PointerRNA *ptr, float value)
+static void rna_NodeSocketInterface_init_socket(bNodeTree *ntree, bNodeSocket *stemp, bNode *node, bNodeSocket *sock, const char *data_path)
{
- bNode *node = (bNode *)ptr->data;
- NodeChroma *chroma = node->storage;
+ extern FunctionRNA rna_NodeSocketInterface_init_socket_func;
- chroma->t2 = value;
+ PointerRNA ptr, node_ptr, sock_ptr;
+ ParameterList list;
+ FunctionRNA *func;
+
+ if (!stemp->typeinfo)
+ return;
+
+ RNA_pointer_create((ID *)ntree, &RNA_NodeSocketInterface, stemp, &ptr);
+ RNA_pointer_create((ID *)ntree, &RNA_Node, node, &node_ptr);
+ RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &sock_ptr);
+ func = &rna_NodeSocketInterface_init_socket_func; /* RNA_struct_find_function(&ptr, "init_socket"); */
+
+ RNA_parameter_list_create(&list, &ptr, func);
+ RNA_parameter_set_lookup(&list, "node", &node_ptr);
+ RNA_parameter_set_lookup(&list, "socket", &sock_ptr);
+ RNA_parameter_set_lookup(&list, "data_path", &data_path);
+ stemp->typeinfo->ext_interface.call(NULL, &ptr, func, &list);
+
+ RNA_parameter_list_free(&list);
}
-static void rna_difference_matte_t1_set(PointerRNA *ptr, float value)
+static void rna_NodeSocketInterface_from_socket(bNodeTree *ntree, bNodeSocket *stemp, bNode *node, bNodeSocket *sock)
{
- bNode *node = (bNode *)ptr->data;
- NodeChroma *chroma = node->storage;
+ extern FunctionRNA rna_NodeSocketInterface_from_socket_func;
- chroma->t1 = value;
+ PointerRNA ptr, node_ptr, sock_ptr;
+ ParameterList list;
+ FunctionRNA *func;
+
+ if (!stemp->typeinfo)
+ return;
+
+ RNA_pointer_create((ID *)ntree, &RNA_NodeSocketInterface, stemp, &ptr);
+ RNA_pointer_create((ID *)ntree, &RNA_Node, node, &node_ptr);
+ RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &sock_ptr);
+ func = &rna_NodeSocketInterface_from_socket_func; /* RNA_struct_find_function(&ptr, "from_socket"); */
+
+ RNA_parameter_list_create(&list, &ptr, func);
+ RNA_parameter_set_lookup(&list, "node", &node_ptr);
+ RNA_parameter_set_lookup(&list, "socket", &sock_ptr);
+ stemp->typeinfo->ext_interface.call(NULL, &ptr, func, &list);
+
+ RNA_parameter_list_free(&list);
}
-static void rna_difference_matte_t2_set(PointerRNA *ptr, float value)
+static void rna_NodeSocketInterface_unregister(Main *UNUSED(bmain), StructRNA *type)
{
- bNode *node = (bNode *)ptr->data;
- NodeChroma *chroma = node->storage;
+ bNodeSocketType *st= RNA_struct_blender_type_get(type);
+ if(!st)
+ return;
+
+ RNA_struct_free_extension(type, &st->ext_interface);
+
+ RNA_struct_free(&BLENDER_RNA, type);
+
+ /* update while blender is running */
+ WM_main_add_notifier(NC_NODE|NA_EDITED, NULL);
+}
- chroma->t2 = value;
+static StructRNA *rna_NodeSocketInterface_register(Main *bmain, ReportList *reports, void *data, const char *identifier,
+ StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
+{
+ bNodeSocketType *st, dummyst;
+ bNodeSocket dummysock;
+ PointerRNA dummyptr;
+ int have_function[5];
+
+ /* setup dummy socket & socket type to store static properties in */
+ memset(&dummyst, 0, sizeof(bNodeSocketType));
+
+ memset(&dummysock, 0, sizeof(bNodeSocket));
+ dummysock.typeinfo= &dummyst;
+ RNA_pointer_create(NULL, &RNA_NodeSocketInterface, &dummysock, &dummyptr);
+
+ /* validate the python class */
+ if (validate(&dummyptr, data, have_function) != 0)
+ return NULL;
+
+ /* check if we have registered this socket type before */
+ st= nodeSocketTypeFind(dummyst.idname);
+ if (st) {
+ /* basic socket type registered by a socket class before. */
+ }
+ else {
+ /* create a new node socket type */
+ st= MEM_callocN(sizeof(bNodeSocketType), "node socket type");
+ memcpy(st, &dummyst, sizeof(dummyst));
+
+ nodeRegisterSocketType(st);
+ }
+
+ /* if RNA type is already registered, unregister first */
+ if (st->ext_interface.srna) {
+ StructRNA *srna = st->ext_interface.srna;
+ RNA_struct_free_extension(srna, &st->ext_interface);
+ RNA_struct_free(&BLENDER_RNA, srna);
+ }
+ st->ext_interface.srna= RNA_def_struct_ptr(&BLENDER_RNA, identifier, &RNA_NodeSocketInterface);
+ st->ext_interface.data= data;
+ st->ext_interface.call= call;
+ st->ext_interface.free= free;
+ RNA_struct_blender_type_set(st->ext_interface.srna, st);
+
+ st->interface_draw = (have_function[0]) ? rna_NodeSocketInterface_draw : NULL;
+ st->interface_draw_color = (have_function[1]) ? rna_NodeSocketInterface_draw_color : NULL;
+ st->interface_register_properties = (have_function[2]) ? rna_NodeSocketInterface_register_properties : NULL;
+ st->interface_init_socket = (have_function[3]) ? rna_NodeSocketInterface_init_socket : NULL;
+ st->interface_from_socket = (have_function[4]) ? rna_NodeSocketInterface_from_socket : NULL;
+
+ /* update while blender is running */
+ WM_main_add_notifier(NC_NODE|NA_EDITED, NULL);
+
+ return st->ext_interface.srna;
}
+static StructRNA *rna_NodeSocketInterface_refine(PointerRNA *ptr)
+{
+ bNodeSocket *sock = (bNodeSocket *)ptr->data;
+
+ if (sock->typeinfo && sock->typeinfo->ext_interface.srna)
+ return sock->typeinfo->ext_interface.srna;
+ else
+ return &RNA_NodeSocketInterface;
+}
-static void rna_Node_scene_set(PointerRNA *ptr, PointerRNA value)
+static char *rna_NodeSocketInterface_path(PointerRNA *ptr)
{
- bNode *node = (bNode *)ptr->data;
+ bNodeTree *ntree = (bNodeTree *)ptr->id.data;
+ bNodeSocket *sock = (bNodeSocket *)ptr->data;
+ int socketindex;
+
+ socketindex = BLI_findindex(&ntree->inputs, sock);
+ if (socketindex != -1)
+ return BLI_sprintfN("inputs[%d]", socketindex);
+
+ socketindex = BLI_findindex(&ntree->outputs, sock);
+ if (socketindex != -1)
+ return BLI_sprintfN("outputs[%d]", socketindex);
+
+ return NULL;
+}
- if (node->id) {
- id_us_min(node->id);
- node->id = NULL;
+static IDProperty *rna_NodeSocketInterface_idprops(PointerRNA *ptr, bool create)
+{
+ bNodeSocket *sock = ptr->data;
+
+ if (create && !sock->prop) {
+ IDPropertyTemplate val = {0};
+ sock->prop = IDP_New(IDP_GROUP, &val, "RNA_NodeSocketInterface ID properties");
}
+
+ return sock->prop;
+}
- node->id = value.data;
-
- id_us_plus(node->id);
+static void rna_NodeSocketInterface_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
+{
+ bNodeTree *ntree = ptr->id.data;
+ bNodeSocket *stemp = ptr->data;
+
+ if (!stemp->typeinfo)
+ return;
+
+ ntree->update |= NTREE_UPDATE_GROUP;
+ ntreeUpdateTree(ntree);
+
+ ED_node_tag_update_nodetree(bmain, ntree);
}
+/* ******** Standard Node Socket Base Types ******** */
-static void node_update(Main *bmain, Scene *UNUSED(scene), bNodeTree *ntree, bNode *node)
+static void rna_NodeSocketStandard_draw(ID *id, bNodeSocket *sock, struct bContext *C, struct uiLayout *layout, PointerRNA *nodeptr)
{
- ED_node_generic_update(bmain, ntree, node);
+ PointerRNA ptr;
+ RNA_pointer_create(id, &RNA_NodeSocket, sock, &ptr);
+ sock->typeinfo->draw(C, layout, &ptr, nodeptr);
}
-static void rna_Node_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_NodeSocketStandard_draw_color(ID *id, bNodeSocket *sock, struct bContext *C, PointerRNA *nodeptr, float *r_color)
{
- bNodeTree *ntree = (bNodeTree *)ptr->id.data;
- bNode *node = (bNode *)ptr->data;
-
- node_update(bmain, scene, ntree, node);
+ PointerRNA ptr;
+ RNA_pointer_create(id, &RNA_NodeSocket, sock, &ptr);
+ sock->typeinfo->draw_color(C, &ptr, nodeptr, r_color);
}
-static void rna_Node_tex_image_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_NodeSocketInterfaceStandard_draw(ID *id, bNodeSocket *sock, struct bContext *C, struct uiLayout *layout)
{
- bNodeTree *ntree = (bNodeTree *)ptr->id.data;
- bNode *node = (bNode *)ptr->data;
+ PointerRNA ptr;
+ RNA_pointer_create(id, &RNA_NodeSocket, sock, &ptr);
+ sock->typeinfo->interface_draw(C, layout, &ptr);
+}
- node_update(bmain, scene, ntree, node);
- WM_main_add_notifier(NC_IMAGE, NULL);
+static void rna_NodeSocketInterfaceStandard_draw_color(ID *id, bNodeSocket *sock, struct bContext *C, float *r_color)
+{
+ PointerRNA ptr;
+ RNA_pointer_create(id, &RNA_NodeSocket, sock, &ptr);
+ sock->typeinfo->interface_draw_color(C, &ptr, r_color);
}
-static void rna_Node_material_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+/* using a context update function here, to avoid searching the node if possible */
+static void rna_NodeSocketStandard_value_update(struct bContext *C, PointerRNA *ptr)
{
- bNodeTree *ntree = (bNodeTree *)ptr->id.data;
- bNode *node = (bNode *)ptr->data;
+ bNode *node;
+
+ /* default update */
+ rna_NodeSocket_update(CTX_data_main(C), CTX_data_scene(C), ptr);
+
+ /* try to use node from context, faster */
+ node = CTX_data_pointer_get(C, "node").data;
+ if (!node) {
+ bNodeTree *ntree = ptr->id.data;
+ bNodeSocket *sock = ptr->data;
+
+ /* fall back to searching node in the tree */
+ nodeFindNode(ntree, sock, &node, NULL);
+ }
+
+ if (node)
+ nodeSynchronizeID(node, true);
+}
- if (node->id)
- nodeSetActive(ntree, node);
- node_update(bmain, scene, ntree, node);
+/* ******** Node Types ******** */
+
+static void rna_CompositorNode_tag_need_exec(bNode *node)
+{
+ node->need_exec = TRUE;
}
-static void rna_NodeTree_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_Node_tex_image_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
bNodeTree *ntree = (bNodeTree *)ptr->id.data;
- /* when using border, make it so no old data from outside of
- * border is hanging around
- * ideally shouldn't be in RNA callback, but how to teach
- * compo to only clear frame when border usage is actually
- * toggling
- */
- if (ntree->flag & NTREE_VIEWER_BORDER) {
- Image *ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
- void *lock;
- ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
-
- if (ibuf) {
- if (ibuf->rect)
- memset(ibuf->rect, 0, 4 * ibuf->x * ibuf->y);
-
- if (ibuf->rect_float)
- memset(ibuf->rect_float, 0, 4 * ibuf->x * ibuf->y * sizeof(float));
+ ED_node_tag_update_nodetree(bmain, ntree);
+ WM_main_add_notifier(NC_IMAGE, NULL);
+}
- ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
- }
+static void rna_Node_material_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
+{
+ bNodeTree *ntree = (bNodeTree *)ptr->id.data;
+ bNode *node = (bNode *)ptr->data;
- BKE_image_release_ibuf(ima, ibuf, lock);
- }
+ if (node->id)
+ nodeSetActive(ntree, node);
- WM_main_add_notifier(NC_NODE | NA_EDITED, NULL);
- WM_main_add_notifier(NC_SCENE | ND_NODES, &ntree->id);
+ ED_node_tag_update_nodetree(bmain, ntree);
}
-static void rna_NodeGroup_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_NodeGroup_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
bNodeTree *ntree = (bNodeTree *)ptr->id.data;
bNode *node = (bNode *)ptr->data;
- ntreeUpdateTree((bNodeTree *)node->id);
+ if (node->id)
+ ntreeUpdateTree((bNodeTree *)node->id);
- node_update(bmain, scene, ntree, node);
+ ED_node_tag_update_nodetree(bmain, ntree);
}
static int rna_NodeGroup_node_tree_poll(PointerRNA *ptr, const PointerRNA value)
@@ -573,91 +2379,99 @@ static int rna_NodeGroup_node_tree_poll(PointerRNA *ptr, const PointerRNA value)
return (ngroup->type == ntree->type);
}
-static void rna_Node_name_set(PointerRNA *ptr, const char *value)
+
+static StructRNA *rna_NodeGroup_interface_typef(PointerRNA *ptr)
{
- bNodeTree *ntree = (bNodeTree *)ptr->id.data;
- bNode *node = (bNode *)ptr->data;
- char oldname[sizeof(node->name)];
-
- /* make a copy of the old name first */
- BLI_strncpy(oldname, node->name, sizeof(node->name));
- /* set new name */
- BLI_strncpy_utf8(node->name, value, sizeof(node->name));
-
- nodeUniqueName(ntree, node);
-
- /* fix all the animation data which may link to this */
- BKE_all_animdata_fix_paths_rename(NULL, "nodes", oldname, node->name);
+ bNode *node = ptr->data;
+ bNodeTree *ngroup = (bNodeTree *)node->id;
+
+ if (ngroup) {
+ StructRNA *srna = ntreeInterfaceTypeGet(ngroup, TRUE);
+ if (srna)
+ return srna;
+ }
+ return &RNA_PropertyGroup;
}
-static void rna_Node_width_range(PointerRNA *ptr, float *min, float *max, float *softmin, float *softmax)
+static StructRNA *rna_NodeGroupInputOutput_interface_typef(PointerRNA *ptr)
{
- bNode *node = ptr->data;
- *min = *softmin = node->typeinfo->minwidth;
- *max = *softmax = node->typeinfo->maxwidth;
+ bNodeTree *ntree = ptr->id.data;
+
+ if (ntree) {
+ StructRNA *srna = ntreeInterfaceTypeGet(ntree, TRUE);
+ if (srna)
+ return srna;
+ }
+ return &RNA_PropertyGroup;
}
-static void rna_Node_height_range(PointerRNA *ptr, float *min, float *max, float *softmin, float *softmax)
+static void rna_distance_matte_t1_set(PointerRNA *ptr, float value)
{
- bNode *node = ptr->data;
- *min = *softmin = node->typeinfo->minheight;
- *max = *softmax = node->typeinfo->maxheight;
+ bNode *node = (bNode *)ptr->data;
+ NodeChroma *chroma = node->storage;
+
+ chroma->t1 = value;
}
-static void rna_NodeSocket_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_distance_matte_t2_set(PointerRNA *ptr, float value)
{
- bNodeTree *ntree = (bNodeTree *)ptr->id.data;
- bNodeSocket *sock = (bNodeSocket *)ptr->data;
- bNode *node;
-
- if (nodeFindNode(ntree, sock, &node, NULL, NULL))
- node_update(bmain, scene, ntree, node);
+ bNode *node = (bNode *)ptr->data;
+ NodeChroma *chroma = node->storage;
+
+ chroma->t2 = value;
}
-static void rna_NodeGroupSocket_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_difference_matte_t1_set(PointerRNA *ptr, float value)
{
- bNodeTree *ntree = (bNodeTree *)ptr->id.data;
- bNodeSocket *sock = (bNodeSocket *)ptr->data;
- bNode *node;
-
- ntreeUpdateTree(ntree);
-
- if (nodeFindNode(ntree, sock, &node, NULL, NULL))
- node_update(bmain, scene, ntree, node);
+ bNode *node = (bNode *)ptr->data;
+ NodeChroma *chroma = node->storage;
+
+ chroma->t1 = value;
}
-#if 0 /* UNUSED */
-static void rna_NodeLink_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_difference_matte_t2_set(PointerRNA *ptr, float value)
{
- bNodeTree *ntree = (bNodeTree *)ptr->id.data;
+ bNode *node = (bNode *)ptr->data;
+ NodeChroma *chroma = node->storage;
- ntree->update |= NTREE_UPDATE_LINKS;
- ntreeUpdateTree(ntree);
+ chroma->t2 = value;
}
-#endif
-static void rna_NodeSocketInt_range(PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax)
+/* Button Set Funcs for Matte Nodes */
+static void rna_Matte_t1_set(PointerRNA *ptr, float value)
{
- bNodeSocket *sock = (bNodeSocket *)ptr->data;
- bNodeSocketValueInt *val = (bNodeSocketValueInt *)sock->default_value;
- *softmin = val->min;
- *softmax = val->max;
+ bNode *node = (bNode *)ptr->data;
+ NodeChroma *chroma = node->storage;
+
+ chroma->t1 = value;
+
+ if (value < chroma->t2)
+ chroma->t2 = value;
}
-static void rna_NodeSocketFloat_range(PointerRNA *ptr, float *min, float *max, float *softmin, float *softmax)
+static void rna_Matte_t2_set(PointerRNA *ptr, float value)
{
- bNodeSocket *sock = (bNodeSocket *)ptr->data;
- bNodeSocketValueFloat *val = (bNodeSocketValueFloat *)sock->default_value;
- *softmin = val->min;
- *softmax = val->max;
+ bNode *node = (bNode *)ptr->data;
+ NodeChroma *chroma = node->storage;
+
+ if (value > chroma->t1)
+ value = chroma->t1;
+
+ chroma->t2 = value;
}
-static void rna_NodeSocketVector_range(PointerRNA *ptr, float *min, float *max, float *softmin, float *softmax)
+static void rna_Node_scene_set(PointerRNA *ptr, PointerRNA value)
{
- bNodeSocket *sock = (bNodeSocket *)ptr->data;
- bNodeSocketValueVector *val = (bNodeSocketValueVector *)sock->default_value;
- *softmin = val->min;
- *softmax = val->max;
+ bNode *node = (bNode *)ptr->data;
+
+ if (node->id) {
+ id_us_min(node->id);
+ node->id = NULL;
+ }
+
+ node->id = value.data;
+
+ id_us_plus(node->id);
}
static void rna_Node_image_layer_update(Main *bmain, Scene *scene, PointerRNA *ptr)
@@ -741,35 +2555,35 @@ static EnumPropertyItem *rna_Node_channel_itemf(bContext *UNUSED(C), PointerRNA
switch (node->custom1) {
case CMP_NODE_CHANNEL_MATTE_CS_RGB:
- tmp.identifier = "R"; tmp.name = "R"; tmp.value = 1;
+ tmp.identifier = "R"; tmp.name= "R"; tmp.value= 1;
RNA_enum_item_add(&item, &totitem, &tmp);
- tmp.identifier = "G"; tmp.name = "G"; tmp.value = 2;
+ tmp.identifier = "G"; tmp.name= "G"; tmp.value= 2;
RNA_enum_item_add(&item, &totitem, &tmp);
- tmp.identifier = "B"; tmp.name = "B"; tmp.value = 3;
+ tmp.identifier = "B"; tmp.name= "B"; tmp.value= 3;
RNA_enum_item_add(&item, &totitem, &tmp);
break;
case CMP_NODE_CHANNEL_MATTE_CS_HSV:
- tmp.identifier = "H"; tmp.name = "H"; tmp.value = 1;
+ tmp.identifier = "H"; tmp.name= "H"; tmp.value= 1;
RNA_enum_item_add(&item, &totitem, &tmp);
- tmp.identifier = "S"; tmp.name = "S"; tmp.value = 2;
+ tmp.identifier = "S"; tmp.name= "S"; tmp.value= 2;
RNA_enum_item_add(&item, &totitem, &tmp);
- tmp.identifier = "V"; tmp.name = "V"; tmp.value = 3;
+ tmp.identifier = "V"; tmp.name= "V"; tmp.value= 3;
RNA_enum_item_add(&item, &totitem, &tmp);
break;
case CMP_NODE_CHANNEL_MATTE_CS_YUV:
- tmp.identifier = "Y"; tmp.name = "Y"; tmp.value = 1;
+ tmp.identifier = "Y"; tmp.name= "Y"; tmp.value= 1;
RNA_enum_item_add(&item, &totitem, &tmp);
- tmp.identifier = "G"; tmp.name = "U"; tmp.value = 2;
+ tmp.identifier = "G"; tmp.name= "U"; tmp.value= 2;
RNA_enum_item_add(&item, &totitem, &tmp);
- tmp.identifier = "V"; tmp.name = "V"; tmp.value = 3;
+ tmp.identifier = "V"; tmp.name= "V"; tmp.value= 3;
RNA_enum_item_add(&item, &totitem, &tmp);
break;
case CMP_NODE_CHANNEL_MATTE_CS_YCC:
- tmp.identifier = "Y"; tmp.name = "Y"; tmp.value = 1;
+ tmp.identifier = "Y"; tmp.name= "Y"; tmp.value= 1;
RNA_enum_item_add(&item, &totitem, &tmp);
- tmp.identifier = "CB"; tmp.name = "Cr"; tmp.value = 2;
+ tmp.identifier = "CB"; tmp.name= "Cr"; tmp.value= 2;
RNA_enum_item_add(&item, &totitem, &tmp);
- tmp.identifier = "CR"; tmp.name = "Cb"; tmp.value = 3;
+ tmp.identifier = "CR"; tmp.name= "Cb"; tmp.value= 3;
RNA_enum_item_add(&item, &totitem, &tmp);
break;
default:
@@ -782,274 +2596,13 @@ static EnumPropertyItem *rna_Node_channel_itemf(bContext *UNUSED(C), PointerRNA
return item;
}
-static PointerRNA rna_NodeTree_active_node_get(PointerRNA *ptr)
-{
- bNodeTree *ntree = (bNodeTree *)ptr->data;
- bNode *node = nodeGetActive(ntree);
- return rna_pointer_inherit_refine(ptr, &RNA_Node, node);
-}
-
-static void rna_NodeTree_active_node_set(PointerRNA *ptr, PointerRNA value)
-{
- bNodeTree *ntree = (bNodeTree *)ptr->data;
- bNode *node = (bNode *)value.data;
- if (node && BLI_findindex(&ntree->nodes, node) != -1)
- nodeSetActive(ntree, node);
- else
- nodeClearActive(ntree);
-}
-
-static bNode *rna_NodeTree_node_new(bNodeTree *ntree, bContext *C, ReportList *reports,
- int type, bNodeTree *group)
-{
- bNode *node;
- bNodeTemplate ntemp;
-
- if (type == NODE_GROUP && group == NULL) {
- BKE_report(reports, RPT_ERROR, "Node type 'GROUP' missing group argument");
- return NULL;
- }
-
- ntemp.type = type;
- ntemp.ngroup = group;
- ntemp.scene = CTX_data_scene(C);
- ntemp.main = CTX_data_main(C);
- node = nodeAddNode(ntree, &ntemp);
-
- if (node == NULL) {
- BKE_report(reports, RPT_ERROR, "Unable to create node");
- }
- else {
- ntreeUpdateTree(ntree); /* update group node socket links*/
- nodeUpdate(ntree, node);
- WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
-
- if (group)
- id_us_plus(&group->id);
- }
-
- return node;
-}
-
-static bNode *rna_NodeTree_node_composite_new(bNodeTree *ntree, bContext *C, ReportList *reports,
- int type, bNodeTree *group)
-{
- /* raises error on failure */
- bNode *node = rna_NodeTree_node_new(ntree, C, reports, type, group);
-
- if (node) {
- if (ELEM4(node->type, CMP_NODE_COMPOSITE, CMP_NODE_DEFOCUS, CMP_NODE_OUTPUT_FILE, CMP_NODE_R_LAYERS)) {
- /* annoying, find the node tree we are in, scene can be NULL */
- Scene *scene;
- for (scene = CTX_data_main(C)->scene.first; scene; scene = scene->id.next) {
- if (scene->nodetree == ntree) {
- break;
- }
- }
- node->id = (ID *)scene;
- id_us_plus(node->id);
- }
-
- ntreeCompositForceHidden(ntree, CTX_data_scene(C));
- ntreeUpdateTree(ntree);
- }
-
- return node;
-}
-
-static bNode *rna_NodeTree_node_texture_new(bNodeTree *ntree, bContext *C, ReportList *reports,
- int type, bNodeTree *group)
-{
- /* raises error on failure */
- bNode *node = rna_NodeTree_node_new(ntree, C, reports, type, group);
-
- if (node) {
- ntreeTexCheckCyclics(ntree);
- }
-
- return node;
-}
-
-static void rna_NodeTree_node_remove(bNodeTree *ntree, ReportList *reports, PointerRNA *node_ptr)
-{
- bNode *node = node_ptr->data;
- if (BLI_findindex(&ntree->nodes, node) == -1) {
- BKE_reportf(reports, RPT_ERROR, "Unable to locate node '%s' in node tree", node->name);
- return;
- }
-
- id_us_min(node->id);
- nodeFreeNode(ntree, node);
- RNA_POINTER_INVALIDATE(node_ptr);
-
- ntreeUpdateTree(ntree); /* update group node socket links */
- WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
-}
-
-static void rna_NodeTree_node_clear(bNodeTree *ntree)
-{
- bNode *node = ntree->nodes.first;
-
- while (node) {
- bNode *next_node = node->next;
-
- if (node->id)
- id_us_min(node->id);
-
- nodeFreeNode(ntree, node);
-
- node = next_node;
- }
-
- ntreeUpdateTree(ntree); /* update group node socket links*/
-
- WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
-}
-
-static bNodeLink *rna_NodeTree_link_new(bNodeTree *ntree, ReportList *reports,
- bNodeSocket *fromsock, bNodeSocket *tosock)
-{
- bNodeLink *ret;
- bNode *fromnode = NULL, *tonode = NULL;
- int from_in_out, to_in_out;
-
- nodeFindNode(ntree, fromsock, &fromnode, NULL, &from_in_out);
- nodeFindNode(ntree, tosock, &tonode, NULL, &to_in_out);
-
- if (&from_in_out == &to_in_out) {
- BKE_report(reports, RPT_ERROR, "Same input/output direction of sockets");
- return NULL;
- }
-
- /* unlink node input socket */
- if (to_in_out == SOCK_IN)
- nodeRemSocketLinks(ntree, tosock);
- else
- nodeRemSocketLinks(ntree, fromsock);
-
- ret = nodeAddLink(ntree, fromnode, fromsock, tonode, tosock);
-
- if (ret) {
- if (tonode)
- nodeUpdate(ntree, tonode);
-
- ntreeUpdateTree(ntree);
-
- WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
- }
-
- return ret;
-}
-
-static void rna_NodeTree_link_remove(bNodeTree *ntree, ReportList *reports, PointerRNA *link_ptr)
-{
- bNodeLink *link = link_ptr->data;
- if (BLI_findindex(&ntree->links, link) == -1) {
- BKE_report(reports, RPT_ERROR, "Unable to locate link in node tree");
- return;
- }
-
- nodeRemLink(ntree, link);
- RNA_POINTER_INVALIDATE(link_ptr);
-
- ntreeUpdateTree(ntree);
- WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
-}
-
-static void rna_NodeTree_link_clear(bNodeTree *ntree)
-{
- bNodeLink *link = ntree->links.first;
-
- while (link) {
- bNodeLink *next_link = link->next;
-
- nodeRemLink(ntree, link);
-
- link = next_link;
- }
- ntreeUpdateTree(ntree);
-
- WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
-}
-
-static bNodeSocket *rna_NodeTree_input_new(bNodeTree *ntree, ReportList *UNUSED(reports), const char *name, int type)
-{
- /* XXX should check if tree is a group here! no good way to do this currently. */
- bNodeSocket *gsock = node_group_add_socket(ntree, name, type, SOCK_IN);
-
- ntree->update |= NTREE_UPDATE_GROUP_IN;
- ntreeUpdateTree(ntree);
- WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
- return gsock;
-}
-
-static bNodeSocket *rna_NodeTree_output_new(bNodeTree *ntree, ReportList *UNUSED(reports), const char *name, int type)
-{
- /* XXX should check if tree is a group here! no good way to do this currently. */
- bNodeSocket *gsock = node_group_add_socket(ntree, name, type, SOCK_OUT);
-
- ntree->update |= NTREE_UPDATE_GROUP_OUT;
- ntreeUpdateTree(ntree);
- WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
- return gsock;
-}
-
-static bNodeSocket *rna_NodeTree_input_expose(bNodeTree *ntree, ReportList *reports, bNodeSocket *sock, int add_link)
-{
- bNode *node;
- bNodeSocket *gsock;
- int index, in_out;
-
- if (!nodeFindNode(ntree, sock, &node, &index, &in_out))
- BKE_report(reports, RPT_ERROR, "Unable to locate socket in node tree");
- else if (in_out != SOCK_IN)
- BKE_report(reports, RPT_ERROR, "Socket is not an input");
- else {
- /* XXX should check if tree is a group here! no good way to do this currently. */
- gsock = node_group_add_socket(ntree, sock->name, sock->type, SOCK_IN);
- if (add_link)
- nodeAddLink(ntree, NULL, gsock, node, sock);
-
- ntree->update |= NTREE_UPDATE_GROUP_IN;
- ntreeUpdateTree(ntree);
- WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
- return gsock;
- }
- return NULL;
-}
-
-static bNodeSocket *rna_NodeTree_output_expose(bNodeTree *ntree, ReportList *reports, bNodeSocket *sock, int add_link)
-{
- bNode *node;
- bNodeSocket *gsock;
- int index, in_out;
-
- if (!nodeFindNode(ntree, sock, &node, &index, &in_out))
- BKE_report(reports, RPT_ERROR, "Unable to locate socket in node tree");
- else if (in_out != SOCK_OUT)
- BKE_report(reports, RPT_ERROR, "Socket is not an output");
- else {
- /* XXX should check if tree is a group here! no good way to do this currently. */
- gsock = node_group_add_socket(ntree, sock->name, sock->type, SOCK_OUT);
- if (add_link)
- nodeAddLink(ntree, node, sock, NULL, gsock);
-
- ntree->update |= NTREE_UPDATE_GROUP_OUT;
- ntreeUpdateTree(ntree);
- WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
- return gsock;
- }
- return NULL;
-}
-
-static void rna_Image_Node_update_id(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_Image_Node_update_id(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
bNodeTree *ntree = (bNodeTree *)ptr->id.data;
bNode *node = (bNode *)ptr->data;
node->update |= NODE_UPDATE_ID;
- node_update(bmain, scene, ntree, node);
- node->update &= ~NODE_UPDATE_ID;
+ nodeUpdate(ntree, node); /* to update image node sockets */
}
static void rna_Mapping_Node_update(Main *bmain, Scene *scene, PointerRNA *ptr)
@@ -1073,6 +2626,8 @@ static PointerRNA rna_NodeOutputFile_slot_file_get(CollectionPropertyIterator *i
return ptr;
}
+/* ******** Node Socket Types ******** */
+
static PointerRNA rna_NodeOutputFile_slot_layer_get(CollectionPropertyIterator *iter)
{
PointerRNA ptr;
@@ -1126,53 +2681,6 @@ static void rna_NodeOutputFileSlotLayer_name_set(PointerRNA *ptr, const char *va
}
}
-static bNodeSocket *rna_ShaderNodeScript_find_socket(bNode *node, const char *name, int is_output)
-{
- bNodeSocket *sock;
-
- if (is_output) {
- for (sock = node->outputs.first; sock; sock = sock->next) {
- if (strcmp(sock->name, name) == 0) {
- return sock;
- }
- }
- }
- else {
- for (sock = node->inputs.first; sock; sock = sock->next) {
- if (strcmp(sock->name, name) == 0) {
- return sock;
- }
- }
- }
-
- return NULL;
-}
-
-static void rna_ShaderNodeScript_remove_socket(ID *id, bNode *node, bNodeSocket *sock)
-{
- bNodeTree *ntree = (bNodeTree *)id;
-
- nodeRemoveSocket(ntree, node, sock);
-
- ED_node_generic_update(G.main, ntree, node);
-}
-
-static bNodeSocket *rna_ShaderNodeScript_add_socket(ID *id, bNode *node, const char *name, int type, int is_output)
-{
- bNodeTree *ntree = (bNodeTree *)id;
- bNodeSocket *sock;
-
- /* replace existing socket with the same name, to keep it unique */
- sock = rna_ShaderNodeScript_find_socket(node, name, is_output);
- if (sock)
- nodeRemoveSocket(ntree, node, sock);
- sock = nodeAddSocket(ntree, node, (is_output ? SOCK_OUT : SOCK_IN), name, type);
-
- ED_node_generic_update(G.main, ntree, node);
-
- return sock;
-}
-
static void rna_ShaderNodeScript_mode_set(PointerRNA *ptr, int value)
{
bNode *node = (bNode *)ptr->data;
@@ -1236,19 +2744,6 @@ static void rna_ShaderNodeScript_bytecode_set(PointerRNA *ptr, const char *value
nss->bytecode = NULL;
}
-static IDProperty *rna_ShaderNodeScript_idprops(PointerRNA *ptr, bool create)
-{
- bNode *node = (bNode *)ptr->data;
- NodeShaderScript *nss = node->storage;
-
- if (create && !nss->prop) {
- IDPropertyTemplate val = {0};
- nss->prop = IDP_New(IDP_GROUP, &val, "RNA_ShaderNodeScript ID properties");
- }
-
- return nss->prop;
-}
-
static void rna_ShaderNodeScript_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
bNodeTree *ntree = (bNodeTree *)ptr->id.data;
@@ -1262,7 +2757,7 @@ static void rna_ShaderNodeScript_update(Main *bmain, Scene *scene, PointerRNA *p
RE_engine_free(engine);
}
- node_update(bmain, scene, ntree, node);
+ ED_node_tag_update_nodetree(bmain, ntree);
}
#else
@@ -1311,139 +2806,36 @@ static EnumPropertyItem node_script_mode_items[] = {
{0, NULL, 0, NULL, NULL}
};
-#define MaxNodes 50000
-
-enum
-{
- Category_GroupNode,
- Category_LayoutNode,
- Category_ShaderNode,
- Category_CompositorNode,
- Category_TextureNode,
-};
-
-typedef struct NodeInfo {
- int defined;
- int category;
- const char *enum_name;
- const char *struct_name;
- const char *base_name;
- int icon;
- const char *ui_name;
- const char *ui_desc;
-} NodeInfo;
-
-static NodeInfo nodes[MaxNodes];
-
-static void reg_node(int ID, int category, const char *enum_name, const char *struct_name,
- const char *base_name, const char *ui_name, const char *ui_desc)
-{
- NodeInfo *ni = nodes + ID;
-
- ni->defined = 1;
- ni->category = category;
- ni->enum_name = enum_name;
- ni->struct_name = struct_name;
- ni->base_name = base_name;
- ni->ui_name = ui_name;
- ni->ui_desc = ui_desc;
-}
-
-static void init(void)
-{
- memset(nodes, 0, sizeof(nodes));
-
- #define DefNode(Category, ID, DefFunc, EnumName, StructName, UIName, UIDesc) \
- reg_node(ID, Category_##Category, EnumName, STRINGIFY_ARG(Category##StructName), #Category, UIName, UIDesc);
-
- #include "rna_nodetree_types.h"
-
- reg_node(NODE_GROUP, Category_GroupNode, "GROUP", "NodeGroup", "SpecialNode", "Group", "");
- reg_node(NODE_FRAME, Category_LayoutNode, "FRAME", "NodeFrame", "SpecialNode", "Frame", "");
- reg_node(NODE_REROUTE, Category_LayoutNode, "REROUTE", "NodeReroute", "SpecialNode", "Reroute", "");
-}
+/* -- Common nodes ---------------------------------------------------------- */
-static StructRNA *def_node(BlenderRNA *brna, int node_id)
+static void def_group_input(StructRNA *srna)
{
- StructRNA *srna;
- FunctionRNA *func;
- PropertyRNA *parm;
- NodeInfo *node = nodes + node_id;
-
- srna = RNA_def_struct(brna, node->struct_name, node->base_name);
- RNA_def_struct_ui_text(srna, node->ui_name, node->ui_desc);
- RNA_def_struct_sdna(srna, "bNode");
-
- func = RNA_def_function(srna, "get_node_type", "rna_Node_get_node_type");
- RNA_def_function_ui_description(func, "Get the identifier of the node type");
- RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_USE_SELF_TYPE);
- parm = RNA_def_string(func, "result", "", 0, "Result", "");
- RNA_def_function_return(func, parm);
+ PropertyRNA *prop;
- return srna;
+ prop = RNA_def_property(srna, "interface", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_funcs(prop, NULL, NULL, "rna_NodeGroupInputOutput_interface_typef", NULL);
+ RNA_def_property_struct_type(prop, "PropertyGroup");
+ RNA_def_property_flag(prop, PROP_IDPROPERTY);
+ RNA_def_property_ui_text(prop, "Interface", "Interface socket data");
}
-static void alloc_node_type_items(EnumPropertyItem *items, int category)
+static void def_group_output(StructRNA *srna)
{
- int i;
- int count = 4;
- EnumPropertyItem *item = items;
-
- for (i = 0; i < MaxNodes; i++)
- if (nodes[i].defined && nodes[i].category == category)
- count++;
-
- /*item = items = MEM_callocN(count * sizeof(EnumPropertyItem), "alloc_node_type_items");*/
-
- for (i = 0; i < MaxNodes; i++) {
- NodeInfo *node = nodes + i;
- if (node->defined && node->category == category) {
- item->value = i;
- item->identifier = node->enum_name;
- item->icon = node->icon;
- item->name = node->ui_name;
- item->description = node->ui_desc;
-
- item++;
- }
- }
-
- item->value = NODE_GROUP;
- item->identifier = "GROUP";
- item->icon = 0;
- item->name = "Group";
- item->description = "";
-
- item++;
-
- item->value = NODE_REROUTE;
- item->identifier = "REROUTE";
- item->icon = 0;
- item->name = "Reroute";
- item->description = "";
-
- item++;
-
- item->value = NODE_FRAME;
- item->identifier = "FRAME";
- item->icon = 0;
- item->name = "Frame";
- item->description = "";
-
- item++;
-
- /* NOTE!, increase 'count' when adding items here */
+ PropertyRNA *prop;
- memset(item, 0, sizeof(EnumPropertyItem));
+ prop = RNA_def_property(srna, "interface", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_funcs(prop, NULL, NULL, "rna_NodeGroupInputOutput_interface_typef", NULL);
+ RNA_def_property_struct_type(prop, "PropertyGroup");
+ RNA_def_property_flag(prop, PROP_IDPROPERTY);
+ RNA_def_property_ui_text(prop, "Interface", "Interface socket data");
}
-
-/* -- Common nodes ---------------------------------------------------------- */
-
static void def_group(StructRNA *srna)
{
PropertyRNA *prop;
+ RNA_def_struct_register_funcs(srna, "rna_NodeGroup_register", "rna_Node_unregister", NULL);
+
prop = RNA_def_property(srna, "node_tree", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "id");
RNA_def_property_struct_type(prop, "NodeTree");
@@ -1451,6 +2843,18 @@ static void def_group(StructRNA *srna)
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Node Tree", "");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeGroup_update");
+
+ prop = RNA_def_property(srna, "interface", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_funcs(prop, NULL, NULL, "rna_NodeGroup_interface_typef", NULL);
+ RNA_def_property_struct_type(prop, "PropertyGroup");
+ RNA_def_property_flag(prop, PROP_IDPROPERTY);
+ RNA_def_property_ui_text(prop, "Interface", "Interface socket data");
+
+ /* registration */
+ prop = RNA_def_property(srna, "bl_group_tree_idname", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "typeinfo->group_tree_idname");
+ RNA_def_property_flag(prop, PROP_REGISTER | PROP_NEVER_CLAMP);
+ RNA_def_property_ui_text(prop, "Group Tree Type", "");
}
static void def_frame(StructRNA *srna)
@@ -2062,8 +3466,7 @@ static void def_sh_tangent(StructRNA *srna)
static void def_sh_script(StructRNA *srna)
{
- FunctionRNA *func;
- PropertyRNA *prop, *parm;
+ PropertyRNA *prop;
prop = RNA_def_property(srna, "script", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "id");
@@ -2073,7 +3476,6 @@ static void def_sh_script(StructRNA *srna)
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNodeScript_update");
RNA_def_struct_sdna_from(srna, "NodeShaderScript", "storage");
- RNA_def_struct_idprops_func(srna, "rna_ShaderNodeScript_idprops");
prop = RNA_def_property(srna, "filepath", PROP_STRING, PROP_FILEPATH);
RNA_def_property_ui_text(prop, "File Path", "Shader script path");
@@ -2104,7 +3506,8 @@ static void def_sh_script(StructRNA *srna)
RNA_def_struct_sdna_from(srna, "bNode", NULL);
/* API functions */
-
+
+#if 0 /* XXX TODO use general node api for this */
func = RNA_def_function(srna, "find_socket", "rna_ShaderNodeScript_find_socket");
RNA_def_function_ui_description(func, "Find a socket by name");
parm = RNA_def_string(func, "name", "", 0, "Socket name", "");
@@ -2129,6 +3532,7 @@ static void def_sh_script(StructRNA *srna)
RNA_def_function_flag(func, FUNC_USE_SELF_ID);
parm = RNA_def_pointer(func, "sock", "NodeSocket", "Socket", "");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+#endif
}
/* -- Compositor Nodes ------------------------------------------------------ */
@@ -4382,390 +5786,571 @@ static void def_tex_bricks(StructRNA *srna)
/* -------------------------------------------------------------------------- */
-static EnumPropertyItem shader_node_type_items[MaxNodes];
static void rna_def_shader_node(BlenderRNA *brna)
{
StructRNA *srna;
- PropertyRNA *prop;
- alloc_node_type_items(shader_node_type_items, Category_ShaderNode);
-
srna = RNA_def_struct(brna, "ShaderNode", "Node");
RNA_def_struct_ui_text(srna, "Shader Node", "Material shader node");
RNA_def_struct_sdna(srna, "bNode");
-
- prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_enum_items(prop, shader_node_type_items);
- RNA_def_property_ui_text(prop, "Type", "");
+ RNA_def_struct_register_funcs(srna, "rna_ShaderNode_register", "rna_Node_unregister", NULL);
}
-static EnumPropertyItem compositor_node_type_items[MaxNodes];
static void rna_def_compositor_node(BlenderRNA *brna)
{
StructRNA *srna;
- PropertyRNA *prop;
-
- alloc_node_type_items(compositor_node_type_items, Category_CompositorNode);
+ FunctionRNA *func;
srna = RNA_def_struct(brna, "CompositorNode", "Node");
RNA_def_struct_ui_text(srna, "Compositor Node", "");
RNA_def_struct_sdna(srna, "bNode");
-
- prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_enum_items(prop, compositor_node_type_items);
- RNA_def_property_ui_text(prop, "Type", "");
+ RNA_def_struct_register_funcs(srna, "rna_CompositorNode_register", "rna_Node_unregister", NULL);
+
+ /* compositor node need_exec flag */
+ func = RNA_def_function(srna, "tag_need_exec", "rna_CompositorNode_tag_need_exec");
+ RNA_def_function_ui_description(func, "Tag the node for compositor update");
}
-static EnumPropertyItem texture_node_type_items[MaxNodes];
static void rna_def_texture_node(BlenderRNA *brna)
{
StructRNA *srna;
- PropertyRNA *prop;
-
- alloc_node_type_items(texture_node_type_items, Category_TextureNode);
srna = RNA_def_struct(brna, "TextureNode", "Node");
RNA_def_struct_ui_text(srna, "Texture Node", "");
RNA_def_struct_sdna(srna, "bNode");
-
- prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_enum_items(prop, texture_node_type_items);
- RNA_def_property_ui_text(prop, "Type", "");
+ RNA_def_struct_register_funcs(srna, "rna_TextureNode_register", "rna_Node_unregister", NULL);
}
-static void rna_def_special_node(BlenderRNA *brna)
+/* -------------------------------------------------------------------------- */
+
+static void rna_def_node_socket(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
+ PropertyRNA *parm;
+ FunctionRNA *func;
+
+ static float default_draw_color[] = { 0.0f, 0.0f, 0.0f, 1.0f };
+
+ srna = RNA_def_struct(brna, "NodeSocket", NULL);
+ RNA_def_struct_ui_text(srna, "Node Socket", "Input or output socket of a node");
+ RNA_def_struct_sdna(srna, "bNodeSocket");
+ RNA_def_struct_refine_func(srna, "rna_NodeSocket_refine");
+ RNA_def_struct_ui_icon(srna, ICON_PLUG);
+ RNA_def_struct_path_func(srna, "rna_NodeSocket_path");
+ RNA_def_struct_register_funcs(srna, "rna_NodeSocket_register", "rna_NodeSocket_unregister", NULL);
+ RNA_def_struct_idprops_func(srna, "rna_NodeSocket_idprops");
- static EnumPropertyItem specific_node_type_items[] = {
- {NODE_GROUP, "GROUP", ICON_NODE, "Group", ""},
- {NODE_FRAME, "FRAME", ICON_NODE, "Frame", ""},
- {NODE_REROUTE, "REROUTE", ICON_NODE, "Reroute", ""},
- {0, NULL, 0, NULL, NULL}
- };
-
- srna = RNA_def_struct(brna, "SpecialNode", "Node");
- RNA_def_struct_ui_text(srna, "Special Node", "");
- RNA_def_struct_sdna(srna, "bNode");
+ prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Name", "Socket name");
+ RNA_def_struct_name_property(srna, prop);
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocket_update");
- prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
+ prop = RNA_def_property(srna, "identifier", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "identifier");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_enum_items(prop, specific_node_type_items);
- RNA_def_property_ui_text(prop, "Type", "");
-}
+ RNA_def_property_ui_text(prop, "Identifier", "Unique identifier for mapping sockets");
-/* -------------------------------------------------------------------------- */
+ prop = RNA_def_property(srna, "in_out", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "in_out");
+ RNA_def_property_enum_items(prop, node_socket_in_out_items);
+ RNA_def_property_enum_default(prop, SOCK_IN);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Input or Output", "Input or Output type");
-static void rna_def_nodetree_link_api(BlenderRNA *brna, PropertyRNA *cprop)
-{
- StructRNA *srna;
- PropertyRNA *parm;
- FunctionRNA *func;
+ prop = RNA_def_property(srna, "hide", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", SOCK_HIDDEN);
+ RNA_def_property_boolean_funcs(prop, NULL, "rna_NodeSocket_hide_set");
+ RNA_def_property_ui_text(prop, "Hide", "Hide the socket");
+ RNA_def_property_update(prop, NC_NODE | ND_DISPLAY, NULL);
- RNA_def_property_srna(cprop, "NodeLinks");
- srna = RNA_def_struct(brna, "NodeLinks", NULL);
- RNA_def_struct_sdna(srna, "bNodeTree");
- RNA_def_struct_ui_text(srna, "Node Links", "Collection of Node Links");
+ prop = RNA_def_property(srna, "enabled", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SOCK_UNAVAIL);
+ RNA_def_property_ui_text(prop, "Enabled", "Enable the socket");
+ RNA_def_property_update(prop, NC_NODE | ND_DISPLAY, NULL);
- func = RNA_def_function(srna, "new", "rna_NodeTree_link_new");
- RNA_def_function_ui_description(func, "Add a node link to this node tree");
- RNA_def_function_flag(func, FUNC_USE_REPORTS);
- parm = RNA_def_pointer(func, "input", "NodeSocket", "", "The input socket");
- RNA_def_property_flag(parm, PROP_REQUIRED);
- parm = RNA_def_pointer(func, "output", "NodeSocket", "", "The output socket");
- RNA_def_property_flag(parm, PROP_REQUIRED);
- /* return */
- parm = RNA_def_pointer(func, "link", "NodeLink", "", "New node link");
- RNA_def_function_return(func, parm);
+ prop = RNA_def_property(srna, "is_linked", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", SOCK_IN_USE);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Linked", "True if the socket is connected");
- func = RNA_def_function(srna, "remove", "rna_NodeTree_link_remove");
- RNA_def_function_ui_description(func, "remove a node link from the node tree");
- RNA_def_function_flag(func, FUNC_USE_REPORTS);
- parm = RNA_def_pointer(func, "link", "NodeLink", "", "The node link to remove");
- RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
- RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
+ prop = RNA_def_property(srna, "show_expanded", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SOCK_COLLAPSED);
+ RNA_def_property_ui_text(prop, "Expanded", "Socket links are expanded in the user interface");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, NULL);
- func = RNA_def_function(srna, "clear", "rna_NodeTree_link_clear");
- RNA_def_function_ui_description(func, "remove all node links from the node tree");
-}
+ prop = RNA_def_property(srna, "node", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_funcs(prop, "rna_NodeSocket_node_get", NULL, NULL, NULL);
+ RNA_def_property_struct_type(prop, "Node");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Node", "Node owning this socket");
-/* shared between all note tree types*/
-static void rna_def_nodetree_active_api(StructRNA *srna, PropertyRNA *UNUSED(cprop))
-{
- PropertyRNA *prop;
+ /* NB: the type property is used by standard sockets.
+ * Ideally should be defined only for the registered subclass,
+ * but to use the existing DNA is added in the base type here.
+ * Future socket types can ignore or override this if needed.
+ */
+ prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "type");
+ RNA_def_property_enum_items(prop, node_socket_type_items);
+ RNA_def_property_enum_default(prop, SOCK_FLOAT);
+ RNA_def_property_ui_text(prop, "Type", "Data type");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocket_update");
+
+ /* registration */
+ prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "typeinfo->idname");
+ RNA_def_property_string_funcs(prop, "rna_NodeSocket_bl_idname_get", "rna_NodeSocket_bl_idname_length", NULL);
+ RNA_def_property_flag(prop, PROP_REGISTER | PROP_NEVER_CLAMP);
+ RNA_def_property_ui_text(prop, "ID Name", "");
+
+ /* draw socket */
+ func = RNA_def_function(srna, "draw", NULL);
+ RNA_def_function_ui_description(func, "Draw socket");
+ RNA_def_function_flag(func, FUNC_REGISTER);
+ parm = RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+ parm = RNA_def_property(func, "layout", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(parm, "UILayout");
+ RNA_def_property_ui_text(parm, "Layout", "Layout in the UI");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+ parm = RNA_def_property(func, "node", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(parm, "Node");
+ RNA_def_property_ui_text(parm, "Node", "Node the socket belongs to");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
- prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE);
- RNA_def_property_struct_type(prop, "Node");
- RNA_def_property_pointer_funcs(prop, "rna_NodeTree_active_node_get", "rna_NodeTree_active_node_set", NULL, NULL);
- RNA_def_property_flag(prop, PROP_EDITABLE | PROP_NEVER_UNLINK);
- RNA_def_property_ui_text(prop, "Active Node", "Active node in this tree");
- RNA_def_property_update(prop, NC_SCENE | ND_OB_ACTIVE, NULL);
+ func = RNA_def_function(srna, "draw_color", NULL);
+ RNA_def_function_ui_description(func, "Color of the socket icon");
+ RNA_def_function_flag(func, FUNC_REGISTER);
+ parm = RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+ parm = RNA_def_property(func, "node", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(parm, "Node");
+ RNA_def_property_ui_text(parm, "Node", "Node the socket belongs to");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
+ parm = RNA_def_float_array(func, "color", 4, default_draw_color, 0.0f, 1.0f, "Color", "", 0.0f, 1.0f);
+ RNA_def_function_output(func, parm);
}
-static void rna_def_composite_nodetree_api(BlenderRNA *brna, PropertyRNA *cprop)
+static void rna_def_node_socket_interface(BlenderRNA *brna)
{
StructRNA *srna;
+ PropertyRNA *prop;
PropertyRNA *parm;
FunctionRNA *func;
+
+ static float default_draw_color[] = { 0.0f, 0.0f, 0.0f, 1.0f };
+
+ srna = RNA_def_struct(brna, "NodeSocketInterface", NULL);
+ RNA_def_struct_ui_text(srna, "Node Socket Template", "Parameters to define node sockets");
+ /* XXX Using bNodeSocket DNA for templates is a compatibility hack.
+ * This allows to keep the inputs/outputs lists in bNodeTree working for earlier versions
+ * and at the same time use them for socket templates in groups.
+ */
+ RNA_def_struct_sdna(srna, "bNodeSocket");
+ RNA_def_struct_refine_func(srna, "rna_NodeSocketInterface_refine");
+ RNA_def_struct_path_func(srna, "rna_NodeSocketInterface_path");
+ RNA_def_struct_idprops_func(srna, "rna_NodeSocketInterface_idprops");
+ RNA_def_struct_register_funcs(srna, "rna_NodeSocketInterface_register", "rna_NodeSocketInterface_unregister", NULL);
- RNA_def_property_srna(cprop, "CompositorNodes");
- srna = RNA_def_struct(brna, "CompositorNodes", NULL);
- RNA_def_struct_sdna(srna, "bNodeTree");
- RNA_def_struct_ui_text(srna, "Compositor Nodes", "Collection of Compositor Nodes");
+ prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Name", "Socket name");
+ RNA_def_struct_name_property(srna, prop);
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketInterface_update");
- func = RNA_def_function(srna, "new", "rna_NodeTree_node_composite_new");
- RNA_def_function_ui_description(func, "Add a node to this node tree");
- RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
- parm = RNA_def_enum(func, "type", compositor_node_type_items, 0, "Type", "Type of node to add");
+ prop = RNA_def_property(srna, "identifier", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "identifier");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Identifier", "Unique identifier for mapping sockets");
+
+ prop = RNA_def_property(srna, "in_out", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "in_out");
+ RNA_def_property_enum_items(prop, node_socket_in_out_items);
+ RNA_def_property_enum_default(prop, SOCK_IN);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Input or Output", "Input or Output type");
+
+ /* registration */
+ prop = RNA_def_property(srna, "bl_socket_idname", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "typeinfo->idname");
+ RNA_def_property_string_funcs(prop, "rna_NodeSocket_bl_idname_get", "rna_NodeSocket_bl_idname_length", NULL);
+ RNA_def_property_flag(prop, PROP_REGISTER | PROP_NEVER_CLAMP);
+ RNA_def_property_ui_text(prop, "ID Name", "");
+
+ func = RNA_def_function(srna, "draw", NULL);
+ RNA_def_function_ui_description(func, "Draw template settings");
+ RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL);
+ parm = RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+ parm = RNA_def_property(func, "layout", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(parm, "UILayout");
+ RNA_def_property_ui_text(parm, "Layout", "Layout in the UI");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+
+ func = RNA_def_function(srna, "draw_color", NULL);
+ RNA_def_function_ui_description(func, "Color of the socket icon");
+ RNA_def_function_flag(func, FUNC_REGISTER);
+ parm = RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+ parm = RNA_def_float_array(func, "color", 4, default_draw_color, 0.0f, 1.0f, "Color", "", 0.0f, 1.0f);
+ RNA_def_function_output(func, parm);
+
+ func = RNA_def_function(srna, "register_properties", NULL);
+ RNA_def_function_ui_description(func, "Define RNA properties of a socket");
+ RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL | FUNC_ALLOW_WRITE);
+ parm = RNA_def_pointer(func, "data_rna_type", "Struct", "Data RNA Type", "RNA type for special socket properties");
RNA_def_property_flag(parm, PROP_REQUIRED);
- RNA_def_pointer(func, "group", "NodeTree", "", "The group tree");
- /* return value */
- parm = RNA_def_pointer(func, "node", "Node", "", "New node");
- RNA_def_function_return(func, parm);
- func = RNA_def_function(srna, "remove", "rna_NodeTree_node_remove");
- RNA_def_function_ui_description(func, "Remove a node from this node tree");
- RNA_def_function_flag(func, FUNC_USE_REPORTS);
- parm = RNA_def_pointer(func, "node", "Node", "", "The node to remove");
+ func = RNA_def_function(srna, "init_socket", NULL);
+ RNA_def_function_ui_description(func, "Initialize a node socket instance");
+ RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL | FUNC_ALLOW_WRITE);
+ parm = RNA_def_pointer(func, "node", "Node", "Node", "Node of the socket to initialize");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
- RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
+ parm = RNA_def_pointer(func, "socket", "NodeSocket", "Socket", "Socket to initialize");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
+ parm = RNA_def_string(func, "data_path", "", 0, "Data Path", "Path to specialized socket data");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
- func = RNA_def_function(srna, "clear", "rna_NodeTree_node_clear");
- RNA_def_function_ui_description(func, "Remove all nodes from this node tree");
+ func = RNA_def_function(srna, "from_socket", NULL);
+ RNA_def_function_ui_description(func, "Setup template parameters from an existing socket");
+ RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL | FUNC_ALLOW_WRITE);
+ parm = RNA_def_pointer(func, "node", "Node", "Node", "Node of the original socket");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
+ parm = RNA_def_pointer(func, "socket", "NodeSocket", "Socket", "Original socket");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
+}
- rna_def_nodetree_active_api(srna, cprop);
+static void rna_def_node_socket_float(BlenderRNA *brna, const char *idname, const char *interface_idname, PropertySubType subtype)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, idname, "NodeSocketStandard");
+ RNA_def_struct_ui_text(srna, "Float Node Socket", "Floating point number socket of a node");
+ RNA_def_struct_sdna(srna, "bNodeSocket");
+
+ RNA_def_struct_sdna_from(srna, "bNodeSocketValueFloat", "default_value");
+
+ prop = RNA_def_property(srna, "default_value", PROP_FLOAT, subtype);
+ RNA_def_property_float_sdna(prop, NULL, "value");
+ RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketStandard_value_update");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+
+ /* XXX need to reset the from-type here, so subtype subclasses cast correctly! (RNA bug) */
+ RNA_def_struct_sdna_from(srna, "bNodeSocket", NULL);
+
+ /* socket interface */
+ srna = RNA_def_struct(brna, interface_idname, "NodeSocketInterfaceStandard");
+ RNA_def_struct_ui_text(srna, "Float Node Socket Interface", "Floating point number socket of a node");
+ RNA_def_struct_sdna(srna, "bNodeSocket");
}
-static void rna_def_shader_nodetree_api(BlenderRNA *brna, PropertyRNA *cprop)
+static void rna_def_node_socket_int(BlenderRNA *brna, const char *identifier, const char *interface_idname, PropertySubType subtype)
{
StructRNA *srna;
- PropertyRNA *parm;
- FunctionRNA *func;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, identifier, "NodeSocketStandard");
+ RNA_def_struct_ui_text(srna, "Integer Node Socket", "Integer number socket of a node");
+ RNA_def_struct_sdna(srna, "bNodeSocket");
+
+ RNA_def_struct_sdna_from(srna, "bNodeSocketValueInt", "default_value");
+
+ prop = RNA_def_property(srna, "default_value", PROP_INT, subtype);
+ RNA_def_property_int_sdna(prop, NULL, "value");
+ RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketStandard_value_update");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+
+ /* XXX need to reset the from-type here, so subtype subclasses cast correctly! (RNA bug) */
+ RNA_def_struct_sdna_from(srna, "bNodeSocket", NULL);
+
+ /* socket interface */
+ srna = RNA_def_struct(brna, interface_idname, "NodeSocketInterfaceStandard");
+ RNA_def_struct_ui_text(srna, "Integer Node Socket Interface", "Integer number socket of a node");
+ RNA_def_struct_sdna(srna, "bNodeSocket");
+}
- RNA_def_property_srna(cprop, "ShaderNodes");
- srna = RNA_def_struct(brna, "ShaderNodes", NULL);
- RNA_def_struct_sdna(srna, "bNodeTree");
- RNA_def_struct_ui_text(srna, "Shader Nodes", "Collection of Shader Nodes");
+static void rna_def_node_socket_bool(BlenderRNA *brna, const char *identifier, const char *interface_idname)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, identifier, "NodeSocketStandard");
+ RNA_def_struct_ui_text(srna, "Boolean Node Socket", "Boolean value socket of a node");
+ RNA_def_struct_sdna(srna, "bNodeSocket");
+
+ RNA_def_struct_sdna_from(srna, "bNodeSocketValueBoolean", "default_value");
+
+ prop = RNA_def_property(srna, "default_value", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "value", 1);
+ RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketStandard_value_update");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+
+ /* XXX need to reset the from-type here, so subtype subclasses cast correctly! (RNA bug) */
+ RNA_def_struct_sdna_from(srna, "bNodeSocket", NULL);
+
+ /* socket interface */
+ srna = RNA_def_struct(brna, interface_idname, "NodeSocketInterfaceStandard");
+ RNA_def_struct_ui_text(srna, "Boolean Node Socket Interface", "Boolean value socket of a node");
+ RNA_def_struct_sdna(srna, "bNodeSocket");
+}
- func = RNA_def_function(srna, "new", "rna_NodeTree_node_new");
- RNA_def_function_ui_description(func, "Add a node to this node tree");
- RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
- parm = RNA_def_enum(func, "type", shader_node_type_items, 0, "Type", "Type of node to add");
- RNA_def_property_flag(parm, PROP_REQUIRED);
- RNA_def_pointer(func, "group", "NodeTree", "", "The group tree");
- /* return value */
- parm = RNA_def_pointer(func, "node", "Node", "", "New node");
- RNA_def_function_return(func, parm);
+static void rna_def_node_socket_vector(BlenderRNA *brna, const char *identifier, const char *interface_idname, PropertySubType subtype)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, identifier, "NodeSocketStandard");
+ RNA_def_struct_ui_text(srna, "Vector Node Socket", "3D vector socket of a node");
+ RNA_def_struct_sdna(srna, "bNodeSocket");
+
+ RNA_def_struct_sdna_from(srna, "bNodeSocketValueVector", "default_value");
+
+ prop = RNA_def_property(srna, "default_value", PROP_FLOAT, subtype);
+ RNA_def_property_float_sdna(prop, NULL, "value");
+ RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketStandard_value_update");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+
+ /* XXX need to reset the from-type here, so subtype subclasses cast correctly! (RNA bug) */
+ RNA_def_struct_sdna_from(srna, "bNodeSocket", NULL);
+
+ /* socket interface */
+ srna = RNA_def_struct(brna, interface_idname, "NodeSocketInterfaceStandard");
+ RNA_def_struct_ui_text(srna, "Vector Node Socket Interface", "3D vector socket of a node");
+ RNA_def_struct_sdna(srna, "bNodeSocket");
+}
- func = RNA_def_function(srna, "remove", "rna_NodeTree_node_remove");
- RNA_def_function_ui_description(func, "Remove a node from this node tree");
- RNA_def_function_flag(func, FUNC_USE_REPORTS);
- parm = RNA_def_pointer(func, "node", "Node", "", "The node to remove");
- RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
- RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
+static void rna_def_node_socket_color(BlenderRNA *brna, const char *identifier, const char *interface_idname)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, identifier, "NodeSocketStandard");
+ RNA_def_struct_ui_text(srna, "Color Node Socket", "RGBA color socket of a node");
+ RNA_def_struct_sdna(srna, "bNodeSocket");
+
+ RNA_def_struct_sdna_from(srna, "bNodeSocketValueRGBA", "default_value");
+
+ prop = RNA_def_property(srna, "default_value", PROP_FLOAT, PROP_COLOR);
+ RNA_def_property_float_sdna(prop, NULL, "value");
+ RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketStandard_value_update");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+
+ /* XXX need to reset the from-type here, so subtype subclasses cast correctly! (RNA bug) */
+ RNA_def_struct_sdna_from(srna, "bNodeSocket", NULL);
+
+ /* socket interface */
+ srna = RNA_def_struct(brna, interface_idname, "NodeSocketInterfaceStandard");
+ RNA_def_struct_ui_text(srna, "Color Node Socket Interface", "RGBA color socket of a node");
+ RNA_def_struct_sdna(srna, "bNodeSocket");
+}
- func = RNA_def_function(srna, "clear", "rna_NodeTree_node_clear");
- RNA_def_function_ui_description(func, "Remove all nodes from this node tree");
+static void rna_def_node_socket_string(BlenderRNA *brna, const char *identifier, const char *interface_idname)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, identifier, "NodeSocketStandard");
+ RNA_def_struct_ui_text(srna, "String Node Socket", "String socket of a node");
+ RNA_def_struct_sdna(srna, "bNodeSocket");
+
+ RNA_def_struct_sdna_from(srna, "bNodeSocketValueString", "default_value");
+
+ prop = RNA_def_property(srna, "default_value", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "value");
+ RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketStandard_value_update");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+
+ /* XXX need to reset the from-type here, so subtype subclasses cast correctly! (RNA bug) */
+ RNA_def_struct_sdna_from(srna, "bNodeSocket", NULL);
+
+ /* socket interface */
+ srna = RNA_def_struct(brna, interface_idname, "NodeSocketInterfaceStandard");
+ RNA_def_struct_ui_text(srna, "String Node Socket Interface", "String socket of a node");
+ RNA_def_struct_sdna(srna, "bNodeSocket");
+}
+
+static void rna_def_node_socket_shader(BlenderRNA *brna, const char *identifier, const char *interface_idname)
+{
+ StructRNA *srna;
+
+ srna = RNA_def_struct(brna, identifier, "NodeSocketStandard");
+ RNA_def_struct_ui_text(srna, "Shader Node Socket", "Shader socket of a node");
+ RNA_def_struct_sdna(srna, "bNodeSocket");
+
+ /* socket interface */
+ srna = RNA_def_struct(brna, interface_idname, "NodeSocketInterfaceStandard");
+ RNA_def_struct_ui_text(srna, "Shader Node Socket Interface", "Shader socket of a node");
+ RNA_def_struct_sdna(srna, "bNodeSocket");
+}
- rna_def_nodetree_active_api(srna, cprop);
+static void rna_def_node_socket_virtual(BlenderRNA *brna, const char *identifier)
+{
+ StructRNA *srna;
+
+ srna = RNA_def_struct(brna, identifier, "NodeSocketStandard");
+ RNA_def_struct_ui_text(srna, "Virtual Node Socket", "Virtual socket of a node");
+ RNA_def_struct_sdna(srna, "bNodeSocket");
}
-static void rna_def_texture_nodetree_api(BlenderRNA *brna, PropertyRNA *cprop)
+static void rna_def_node_socket_standard_types(BlenderRNA *brna)
{
+ /* XXX Workaround: Registered functions are not exposed in python by bpy,
+ * it expects them to be registered from python and use the native implementation.
+ * However, the standard socket types below are not registering these functions from python,
+ * so in order to call them in py scripts we need to overload and replace them with plain C callbacks.
+ * These types provide a usable basis for socket types defined in C.
+ */
+
StructRNA *srna;
PropertyRNA *parm;
FunctionRNA *func;
+
+ static float default_draw_color[] = { 0.0f, 0.0f, 0.0f, 1.0f };
+
+ srna = RNA_def_struct(brna, "NodeSocketStandard", "NodeSocket");
+ RNA_def_struct_sdna(srna, "bNodeSocket");
+
+ /* draw socket */
+ func = RNA_def_function(srna, "draw", "rna_NodeSocketStandard_draw");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID);
+ RNA_def_function_ui_description(func, "Draw socket");
+ parm = RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+ parm = RNA_def_property(func, "layout", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(parm, "UILayout");
+ RNA_def_property_ui_text(parm, "Layout", "Layout in the UI");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+ parm = RNA_def_property(func, "node", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(parm, "Node");
+ RNA_def_property_ui_text(parm, "Node", "Node the socket belongs to");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
- RNA_def_property_srna(cprop, "TextureNodes");
- srna = RNA_def_struct(brna, "TextureNodes", NULL);
- RNA_def_struct_sdna(srna, "bNodeTree");
- RNA_def_struct_ui_text(srna, "Texture Nodes", "Collection of Texture Nodes");
-
- func = RNA_def_function(srna, "new", "rna_NodeTree_node_texture_new");
- RNA_def_function_ui_description(func, "Add a node to this node tree");
- RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
- parm = RNA_def_enum(func, "type", texture_node_type_items, 0, "Type", "Type of node to add");
- RNA_def_property_flag(parm, PROP_REQUIRED);
- RNA_def_pointer(func, "group", "NodeTree", "", "The group tree");
- /* return value */
- parm = RNA_def_pointer(func, "node", "Node", "", "New node");
- RNA_def_function_return(func, parm);
-
- func = RNA_def_function(srna, "remove", "rna_NodeTree_node_remove");
- RNA_def_function_ui_description(func, "Remove a node from this node tree");
- RNA_def_function_flag(func, FUNC_USE_REPORTS);
- parm = RNA_def_pointer(func, "node", "Node", "", "The node to remove");
+ func = RNA_def_function(srna, "draw_color", "rna_NodeSocketStandard_draw_color");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID);
+ RNA_def_function_ui_description(func, "Color of the socket icon");
+ parm = RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+ parm = RNA_def_property(func, "node", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(parm, "Node");
+ RNA_def_property_ui_text(parm, "Node", "Node the socket belongs to");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
- RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
+ parm = RNA_def_float_array(func, "color", 4, default_draw_color, 0.0f, 1.0f, "Color", "", 0.0f, 1.0f);
+ RNA_def_function_output(func, parm);
+
+
+ srna = RNA_def_struct(brna, "NodeSocketInterfaceStandard", "NodeSocketInterface");
+ RNA_def_struct_sdna(srna, "bNodeSocket");
+
+ func = RNA_def_function(srna, "draw", "rna_NodeSocketInterfaceStandard_draw");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID);
+ RNA_def_function_ui_description(func, "Draw template settings");
+ parm = RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+ parm = RNA_def_property(func, "layout", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(parm, "UILayout");
+ RNA_def_property_ui_text(parm, "Layout", "Layout in the UI");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
- func = RNA_def_function(srna, "clear", "rna_NodeTree_node_clear");
- RNA_def_function_ui_description(func, "Remove all nodes from this node tree");
+ func = RNA_def_function(srna, "draw_color", "rna_NodeSocketInterfaceStandard_draw_color");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID);
+ RNA_def_function_ui_description(func, "Color of the socket icon");
+ parm = RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+ parm = RNA_def_float_array(func, "color", 4, default_draw_color, 0.0f, 1.0f, "Color", "", 0.0f, 1.0f);
+ RNA_def_function_output(func, parm);
- rna_def_nodetree_active_api(srna, cprop);
-}
-static void rna_def_node_socket(BlenderRNA *brna)
-{
- StructRNA *srna;
- PropertyRNA *prop;
+ /* XXX These types should eventually be registered at runtime.
+ * Then use the nodeStaticSocketType and nodeStaticSocketInterfaceType functions
+ * to get the idname strings from int type and subtype (see node_socket.c, register_standard_node_socket_types).
+ */
+
+ rna_def_node_socket_float(brna, "NodeSocketFloat", "NodeSocketInterfaceFloat", PROP_NONE);
+ rna_def_node_socket_float(brna, "NodeSocketFloatUnsigned", "NodeSocketInterfaceFloatUnsigned", PROP_UNSIGNED);
+ rna_def_node_socket_float(brna, "NodeSocketFloatPercentage", "NodeSocketInterfaceFloatPercentage", PROP_PERCENTAGE);
+ rna_def_node_socket_float(brna, "NodeSocketFloatFactor", "NodeSocketInterfaceFloatFactor", PROP_FACTOR);
+ rna_def_node_socket_float(brna, "NodeSocketFloatAngle", "NodeSocketInterfaceFloatAngle", PROP_ANGLE);
+ rna_def_node_socket_float(brna, "NodeSocketFloatTime", "NodeSocketInterfaceFloatTime", PROP_TIME);
- srna = RNA_def_struct(brna, "NodeSocket", NULL);
- RNA_def_struct_ui_text(srna, "Node Socket", "Input or output socket of a node");
- RNA_def_struct_sdna(srna, "bNodeSocket");
- RNA_def_struct_refine_func(srna, "rna_NodeSocket_refine");
- RNA_def_struct_ui_icon(srna, ICON_PLUG);
- RNA_def_struct_path_func(srna, "rna_NodeSocket_path");
+ rna_def_node_socket_int(brna, "NodeSocketInt", "NodeSocketInterfaceInt", PROP_NONE);
+ rna_def_node_socket_int(brna, "NodeSocketIntUnsigned", "NodeSocketInterfaceIntUnsigned", PROP_UNSIGNED);
+ rna_def_node_socket_int(brna, "NodeSocketIntPercentage", "NodeSocketInterfaceIntPercentage", PROP_PERCENTAGE);
+ rna_def_node_socket_int(brna, "NodeSocketIntFactor", "NodeSocketInterfaceIntFactor", PROP_FACTOR);
- prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "type");
- RNA_def_property_enum_items(prop, node_socket_type_items);
- RNA_def_property_enum_default(prop, 0);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Type", "Node Socket type");
+ rna_def_node_socket_bool(brna, "NodeSocketBool", "NodeSocketInterfaceBool");
- prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
- /* XXX must be editable for group sockets. if necessary use a special rna definition for these */
-/* RNA_def_property_clear_flag(prop, PROP_EDITABLE); */
- RNA_def_property_ui_text(prop, "Name", "Socket name");
- RNA_def_struct_name_property(srna, prop);
- RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeGroupSocket_update");
+ rna_def_node_socket_vector(brna, "NodeSocketVector", "NodeSocketInterfaceVector", PROP_NONE);
+ rna_def_node_socket_vector(brna, "NodeSocketVectorTranslation", "NodeSocketInterfaceVectorTranslation", PROP_TRANSLATION);
+ rna_def_node_socket_vector(brna, "NodeSocketVectorDirection", "NodeSocketInterfaceVectorDirection", PROP_DIRECTION);
+ rna_def_node_socket_vector(brna, "NodeSocketVectorVelocity", "NodeSocketInterfaceVectorVelocity", PROP_VELOCITY);
+ rna_def_node_socket_vector(brna, "NodeSocketVectorAcceleration", "NodeSocketInterfaceVectorAcceleration", PROP_ACCELERATION);
+ rna_def_node_socket_vector(brna, "NodeSocketVectorEuler", "NodeSocketInterfaceVectorEuler", PROP_EULER);
+ rna_def_node_socket_vector(brna, "NodeSocketVectorXYZ", "NodeSocketInterfaceVectorXYZ", PROP_XYZ);
- prop = RNA_def_property(srna, "group_socket", PROP_POINTER, PROP_NONE);
- RNA_def_property_pointer_sdna(prop, NULL, "groupsock");
- RNA_def_property_struct_type(prop, "NodeSocket");
- RNA_def_property_ui_text(prop, "Group Socket",
- "For group nodes, the group input or output socket this corresponds to");
+ rna_def_node_socket_color(brna, "NodeSocketColor", "NodeSocketInterfaceColor");
- prop = RNA_def_property(srna, "hide", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", SOCK_HIDDEN);
- RNA_def_property_boolean_funcs(prop, NULL, "rna_NodeSocket_hide_set");
- RNA_def_property_ui_text(prop, "Hide", "Hide the socket");
- RNA_def_property_update(prop, NC_NODE | ND_DISPLAY, NULL);
+ rna_def_node_socket_string(brna, "NodeSocketString", "NodeSocketInterfaceString");
- prop = RNA_def_property(srna, "is_linked", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", SOCK_IN_USE);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Linked", "True if the socket is connected");
+ rna_def_node_socket_shader(brna, "NodeSocketShader", "NodeSocketInterfaceShader");
- prop = RNA_def_property(srna, "show_expanded", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SOCK_COLLAPSED);
- RNA_def_property_ui_text(prop, "Expanded", "Socket links are expanded in the user interface");
- RNA_def_property_update(prop, NC_NODE | NA_EDITED, NULL);
+ rna_def_node_socket_virtual(brna, "NodeSocketVirtual");
}
-static void rna_def_node_socket_subtype(BlenderRNA *brna, int type, int subtype, const char *name, const char *ui_name)
+static void rna_def_node_sockets_api(BlenderRNA *brna, PropertyRNA *cprop, int in_out)
{
StructRNA *srna;
- PropertyRNA *prop = NULL;
- PropertySubType propsubtype = PROP_NONE;
-
- #define SUBTYPE(socktype, stypename, id, idname) { PROP_##id, #socktype "_" #id, 0, #idname, ""},
- static EnumPropertyItem subtype_items[] = {
- NODE_DEFINE_SUBTYPES
- {0, NULL, 0, NULL, NULL}
- };
- #undef SUBTYPE
+ PropertyRNA *parm;
+ FunctionRNA *func;
+ const char *structtype = (in_out == SOCK_IN ? "NodeInputs" : "NodeOutputs");
+ const char *uiname = (in_out == SOCK_IN ? "Node Inputs" : "Node Outputs");
+ const char *newfunc = (in_out == SOCK_IN ? "rna_Node_inputs_new" : "rna_Node_outputs_new");
+ const char *clearfunc = (in_out == SOCK_IN ? "rna_Node_inputs_clear" : "rna_Node_outputs_clear");
- #define SUBTYPE(socktype, stypename, id, idname) if (subtype == (PROP_##id)) propsubtype = PROP_##id;
- NODE_DEFINE_SUBTYPES
- #undef SUBTYPE
-
- srna = RNA_def_struct(brna, name, "NodeSocket");
- RNA_def_struct_ui_text(srna, ui_name, "Input or output socket of a node");
- RNA_def_struct_sdna(srna, "bNodeSocket");
- RNA_def_struct_ui_icon(srna, ICON_PLUG);
- RNA_def_struct_path_func(srna, "rna_NodeSocket_path");
-
- switch (type) {
- case SOCK_INT:
- RNA_def_struct_sdna_from(srna, "bNodeSocketValueInt", "default_value");
-
- prop = RNA_def_property(srna, "subtype", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "subtype");
- RNA_def_property_enum_items(prop, subtype_items);
- RNA_def_property_ui_text(prop, "Subtype", "Subtype defining the socket value details");
- RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocket_update");
-
- prop = RNA_def_property(srna, "default_value", PROP_INT, propsubtype);
- RNA_def_property_int_sdna(prop, NULL, "value");
- RNA_def_property_int_funcs(prop, NULL, NULL, "rna_NodeSocketInt_range");
- RNA_def_property_ui_text(prop, "Default Value", "");
- RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocket_update");
- break;
- case SOCK_FLOAT:
- RNA_def_struct_sdna_from(srna, "bNodeSocketValueFloat", "default_value");
-
- prop = RNA_def_property(srna, "subtype", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "subtype");
- RNA_def_property_enum_items(prop, subtype_items);
- RNA_def_property_ui_text(prop, "Subtype", "Subtype defining the socket value details");
- RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocket_update");
-
- prop = RNA_def_property(srna, "default_value", PROP_FLOAT, propsubtype);
- RNA_def_property_float_sdna(prop, NULL, "value");
- RNA_def_property_float_funcs(prop, NULL, NULL, "rna_NodeSocketFloat_range");
- RNA_def_property_ui_text(prop, "Default Value", "");
- RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocket_update");
- break;
- case SOCK_BOOLEAN:
- RNA_def_struct_sdna_from(srna, "bNodeSocketValueBoolean", "default_value");
-
- prop = RNA_def_property(srna, "default_value", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "value", 1);
- RNA_def_property_ui_text(prop, "Default Value", "");
- RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocket_update");
- break;
- case SOCK_VECTOR:
- RNA_def_struct_sdna_from(srna, "bNodeSocketValueVector", "default_value");
-
- prop = RNA_def_property(srna, "subtype", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "subtype");
- RNA_def_property_enum_items(prop, subtype_items);
- RNA_def_property_ui_text(prop, "Subtype", "Subtype defining the socket value details");
- RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocket_update");
-
- prop = RNA_def_property(srna, "default_value", PROP_FLOAT, propsubtype);
- RNA_def_property_float_sdna(prop, NULL, "value");
- RNA_def_property_float_funcs(prop, NULL, NULL, "rna_NodeSocketVector_range");
- RNA_def_property_ui_text(prop, "Default Value", "");
- RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocket_update");
- break;
- case SOCK_RGBA:
- RNA_def_struct_sdna_from(srna, "bNodeSocketValueRGBA", "default_value");
+ RNA_def_property_srna(cprop, structtype);
+ srna= RNA_def_struct(brna, structtype, NULL);
+ RNA_def_struct_sdna(srna, "bNode");
+ RNA_def_struct_ui_text(srna, uiname, "Collection of Node Sockets");
- prop = RNA_def_property(srna, "default_value", PROP_FLOAT, PROP_COLOR);
- RNA_def_property_float_sdna(prop, NULL, "value");
- RNA_def_property_ui_text(prop, "Default Value", "");
- RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocket_update");
- break;
- case SOCK_STRING:
- RNA_def_struct_sdna_from(srna, "bNodeSocketValueString", "default_value");
-
- prop = RNA_def_property(srna, "subtype", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "subtype");
- RNA_def_property_enum_items(prop, subtype_items);
- RNA_def_property_ui_text(prop, "Subtype", "Subtype defining the socket value details");
- RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocket_update");
-
- prop = RNA_def_property(srna, "default_value", PROP_STRING, PROP_FILEPATH);
- RNA_def_property_string_sdna(prop, NULL, "value");
- RNA_def_property_ui_text(prop, "Default Value", "");
- RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocket_update");
- break;
- }
-
- /* XXX need to reset the from-type here, so subtype subclasses cast correctly! (RNA bug) */
- RNA_def_struct_sdna_from(srna, "bNodeSocket", NULL);
+ func= RNA_def_function(srna, "new", newfunc);
+ RNA_def_function_ui_description(func, "Add a socket to this node");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_REPORTS);
+ parm= RNA_def_string(func, "type", "", MAX_NAME, "Type", "Data type");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ parm= RNA_def_string(func, "name", "", MAX_NAME, "Name", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ RNA_def_string(func, "identifier", "", MAX_NAME, "Identifier", "Unique socket identifier");
+ /* return value */
+ parm= RNA_def_pointer(func, "socket", "NodeSocket", "", "New socket");
+ RNA_def_function_return(func, parm);
+
+ func= RNA_def_function(srna, "remove", "rna_Node_socket_remove");
+ RNA_def_function_ui_description(func, "Remove a socket from this node");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_REPORTS);
+ parm= RNA_def_pointer(func, "socket", "NodeSocket", "", "The socket to remove");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+
+ func= RNA_def_function(srna, "clear", clearfunc);
+ RNA_def_function_ui_description(func, "Remove all sockets from this node");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_REPORTS);
}
static void rna_def_node(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
+ FunctionRNA *func;
+ PropertyRNA *parm;
+
+ static EnumPropertyItem dummy_static_type_items[] = {
+ {NODE_CUSTOM, "CUSTOM", 0, "Custom", "Custom Node"},
+ {0, NULL, 0, NULL, NULL}};
srna = RNA_def_struct(brna, "Node", NULL);
RNA_def_struct_ui_text(srna, "Node", "Node in a node tree");
@@ -4773,6 +6358,16 @@ static void rna_def_node(BlenderRNA *brna)
RNA_def_struct_ui_icon(srna, ICON_NODE);
RNA_def_struct_refine_func(srna, "rna_Node_refine");
RNA_def_struct_path_func(srna, "rna_Node_path");
+ RNA_def_struct_register_funcs(srna, "rna_Node_register", "rna_Node_unregister", NULL);
+ RNA_def_struct_idprops_func(srna, "rna_Node_idprops");
+
+ prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "type");
+ RNA_def_property_enum_items(prop, dummy_static_type_items);
+ RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_node_static_type_itemf");
+ RNA_def_property_enum_default(prop, NODE_CUSTOM);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Type", "Node type (deprecated, use bl_static_type or bl_idname for the actual identifier string)");
prop = RNA_def_property(srna, "location", PROP_FLOAT, PROP_XYZ);
RNA_def_property_float_sdna(prop, NULL, "locx");
@@ -4812,13 +6407,24 @@ static void rna_def_node(BlenderRNA *brna)
prop = RNA_def_property(srna, "inputs", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "inputs", NULL);
+ RNA_def_property_collection_funcs(prop, NULL, NULL, NULL, NULL, NULL, NULL,
+ "rna_Node_inputs_lookupstring", NULL);
RNA_def_property_struct_type(prop, "NodeSocket");
RNA_def_property_ui_text(prop, "Inputs", "");
+ rna_def_node_sockets_api(brna, prop, SOCK_IN);
prop = RNA_def_property(srna, "outputs", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "outputs", NULL);
+ RNA_def_property_collection_funcs(prop, NULL, NULL, NULL, NULL, NULL, NULL,
+ "rna_Node_outputs_lookupstring", NULL);
RNA_def_property_struct_type(prop, "NodeSocket");
RNA_def_property_ui_text(prop, "Outputs", "");
+ rna_def_node_sockets_api(brna, prop, SOCK_OUT);
+
+ prop = RNA_def_property(srna, "internal_links", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "internal_links", NULL);
+ RNA_def_property_struct_type(prop, "NodeLink");
+ RNA_def_property_ui_text(prop, "Internal Links", "Internal input-to-output connections for muting");
prop = RNA_def_property(srna, "parent", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "parent");
@@ -4840,8 +6446,9 @@ static void rna_def_node(BlenderRNA *brna)
RNA_def_property_update(prop, NC_NODE | ND_DISPLAY, NULL);
prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", NODE_SELECT);
- RNA_def_property_ui_text(prop, "Select", "");
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", SELECT);
+ RNA_def_property_boolean_funcs(prop, NULL, "rna_Node_select_set");
+ RNA_def_property_ui_text(prop, "Select", "Node selection state");
RNA_def_property_update(prop, NC_NODE | NA_SELECTED, NULL);
prop = RNA_def_property(srna, "show_options", PROP_BOOLEAN, PROP_NONE);
@@ -4868,6 +6475,115 @@ static void rna_def_node(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flag", NODE_ACTIVE_TEXTURE);
RNA_def_property_ui_text(prop, "Show Texture", "Draw node in viewport textured draw mode");
RNA_def_property_update(prop, 0, "rna_Node_update");
+
+ /* generic property update function */
+ func = RNA_def_function(srna, "socket_value_update", "rna_Node_socket_value_update");
+ RNA_def_function_ui_description(func, "Update after property changes");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID);
+ parm = RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+
+ func = RNA_def_function(srna, "is_registered_node_type", "rna_Node_is_registered_node_type");
+ RNA_def_function_ui_description(func, "True if a registered node type");
+ RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_USE_SELF_TYPE);
+ parm = RNA_def_boolean(func, "result", FALSE, "Result", "");
+ RNA_def_function_return(func, parm);
+
+ /* registration */
+ prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "typeinfo->idname");
+ RNA_def_property_string_funcs(prop, "rna_Node_bl_idname_get", "rna_Node_bl_idname_length", NULL);
+ RNA_def_property_flag(prop, PROP_REGISTER|PROP_NEVER_CLAMP);
+ RNA_def_property_ui_text(prop, "ID Name", "");
+
+ prop = RNA_def_property(srna, "bl_label", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "typeinfo->ui_name");
+ RNA_def_property_string_funcs(prop, "rna_Node_bl_label_get", "rna_Node_bl_label_length", NULL);
+ RNA_def_property_flag(prop, PROP_REGISTER);
+ RNA_def_property_ui_text(prop, "Label", "The node label");
+
+ prop = RNA_def_property(srna, "bl_description", PROP_STRING, PROP_TRANSLATION);
+ RNA_def_property_string_sdna(prop, NULL, "typeinfo->ui_description");
+ RNA_def_property_string_funcs(prop, "rna_Node_bl_description_get", "rna_Node_bl_description_length", NULL);
+ RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
+
+ prop = RNA_def_property(srna, "bl_icon", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "typeinfo->ui_icon");
+ RNA_def_property_enum_funcs(prop, "rna_Node_bl_icon_get", NULL, NULL);
+ RNA_def_property_enum_items(prop, node_icon_items);
+ RNA_def_property_enum_default(prop, ICON_NODE);
+ RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
+ RNA_def_property_ui_text(prop, "Icon", "The node icon");
+
+ prop = RNA_def_property(srna, "bl_static_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "typeinfo->type");
+ RNA_def_property_enum_funcs(prop, "rna_Node_bl_static_type_get", NULL, NULL);
+ RNA_def_property_enum_items(prop, dummy_static_type_items);
+ RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_node_static_type_itemf");
+ RNA_def_property_enum_default(prop, NODE_CUSTOM);
+ RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
+ RNA_def_property_ui_text(prop, "Static Type", "Node type (deprecated, use with care)");
+
+ /* poll */
+ func = RNA_def_function(srna, "poll", NULL);
+ RNA_def_function_ui_description(func, "If non-null output is returned, the node type can be added to the tree");
+ RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_REGISTER);
+ RNA_def_function_return(func, RNA_def_boolean(func, "visible", FALSE, "", ""));
+ parm = RNA_def_pointer(func, "node_tree", "NodeTree", "Node Tree", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+
+ func = RNA_def_function(srna, "poll_instance", NULL);
+ RNA_def_function_ui_description(func, "If non-null output is returned, the node can be added to the tree");
+ RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL);
+ RNA_def_function_return(func, RNA_def_boolean(func, "visible", FALSE, "", ""));
+ parm = RNA_def_pointer(func, "node_tree", "NodeTree", "Node Tree", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+
+ /* update */
+ func = RNA_def_function(srna, "update", NULL);
+ RNA_def_function_ui_description(func, "Update on editor changes");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_REGISTER_OPTIONAL | FUNC_ALLOW_WRITE);
+
+ /* init */
+ func = RNA_def_function(srna, "init", NULL);
+ RNA_def_function_ui_description(func, "Initialize a new instance of this node");
+ RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL | FUNC_ALLOW_WRITE);
+ parm = RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+
+ /* copy */
+ func = RNA_def_function(srna, "copy", NULL);
+ RNA_def_function_ui_description(func, "Initialize a new instance of this node from an existing node");
+ RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL | FUNC_ALLOW_WRITE);
+ parm = RNA_def_pointer(func, "node", "Node", "Node", "Existing node to copy");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+
+ /* free */
+ func = RNA_def_function(srna, "free", NULL);
+ RNA_def_function_ui_description(func, "Clean up node on removal");
+ RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL | FUNC_ALLOW_WRITE);
+
+ /* draw buttons */
+ func = RNA_def_function(srna, "draw_buttons", NULL);
+ RNA_def_function_ui_description(func, "Draw node buttons");
+ RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL);
+ parm = RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED|PROP_NEVER_NULL);
+ parm = RNA_def_property(func, "layout", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(parm, "UILayout");
+ RNA_def_property_ui_text(parm, "Layout", "Layout in the UI");
+ RNA_def_property_flag(parm, PROP_REQUIRED|PROP_NEVER_NULL);
+
+ /* draw buttons extended */
+ func = RNA_def_function(srna, "draw_buttons_ext", NULL);
+ RNA_def_function_ui_description(func, "Draw node buttons in the sidebar");
+ RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL);
+ parm = RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED|PROP_NEVER_NULL);
+ parm = RNA_def_property(func, "layout", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(parm, "UILayout");
+ RNA_def_property_ui_text(parm, "Layout", "Layout in the UI");
+ RNA_def_property_flag(parm, PROP_REQUIRED|PROP_NEVER_NULL);
}
static void rna_def_node_link(BlenderRNA *brna)
@@ -4880,63 +6596,165 @@ static void rna_def_node_link(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "bNodeLink");
RNA_def_struct_ui_icon(srna, ICON_NODE);
+ prop = RNA_def_property(srna, "is_valid", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", NODE_LINK_VALID);
+ RNA_def_struct_ui_text(srna, "Valid", "Link is valid");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, NULL);
+
prop = RNA_def_property(srna, "from_node", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "fromnode");
RNA_def_property_struct_type(prop, "Node");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "From node", "");
prop = RNA_def_property(srna, "to_node", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "tonode");
RNA_def_property_struct_type(prop, "Node");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "To node", "");
prop = RNA_def_property(srna, "from_socket", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "fromsock");
RNA_def_property_struct_type(prop, "NodeSocket");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "From socket", "");
prop = RNA_def_property(srna, "to_socket", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "tosock");
RNA_def_property_struct_type(prop, "NodeSocket");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "To socket", "");
+
+ prop = RNA_def_property(srna, "is_hidden", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_funcs(prop, "rna_NodeLink_is_hidden_get", NULL);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Is Hidden", "Link is hidden due to invisible sockets");
}
-static void rna_def_group_sockets_api(BlenderRNA *brna, PropertyRNA *cprop, int in_out)
+static void rna_def_nodetree_nodes_api(BlenderRNA *brna, PropertyRNA *cprop)
+{
+ StructRNA *srna;
+ PropertyRNA *parm, *prop;
+ FunctionRNA *func;
+
+ RNA_def_property_srna(cprop, "Nodes");
+ srna= RNA_def_struct(brna, "Nodes", NULL);
+ RNA_def_struct_sdna(srna, "bNodeTree");
+ RNA_def_struct_ui_text(srna, "Nodes", "Collection of Nodes");
+
+ func= RNA_def_function(srna, "new", "rna_NodeTree_node_new");
+ RNA_def_function_ui_description(func, "Add a node to this node tree");
+ RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
+ parm= RNA_def_string(func, "type", "", MAX_NAME, "Type", "Type of node to add");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ /* return value */
+ parm= RNA_def_pointer(func, "node", "Node", "", "New node");
+ RNA_def_function_return(func, parm);
+
+ func= RNA_def_function(srna, "remove", "rna_NodeTree_node_remove");
+ RNA_def_function_ui_description(func, "Remove a node from this node tree");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ parm= RNA_def_pointer(func, "node", "Node", "", "The node to remove");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
+ RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
+
+ func= RNA_def_function(srna, "clear", "rna_NodeTree_node_clear");
+ RNA_def_function_ui_description(func, "Remove all nodes from this node tree");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+
+ prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(prop, "Node");
+ RNA_def_property_pointer_funcs(prop, "rna_NodeTree_active_node_get", "rna_NodeTree_active_node_set", NULL, NULL);
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_NEVER_UNLINK);
+ RNA_def_property_ui_text(prop, "Active Node", "Active node in this tree");
+ RNA_def_property_update(prop, NC_SCENE | ND_OB_ACTIVE, NULL);
+}
+
+static void rna_def_nodetree_link_api(BlenderRNA *brna, PropertyRNA *cprop)
{
StructRNA *srna;
PropertyRNA *parm;
FunctionRNA *func;
- RNA_def_property_srna(cprop, (in_out == SOCK_IN ? "GroupInputs" : "GroupOutputs"));
- srna = RNA_def_struct(brna, (in_out == SOCK_IN ? "GroupInputs" : "GroupOutputs"), NULL);
+ RNA_def_property_srna(cprop, "NodeLinks");
+ srna = RNA_def_struct(brna, "NodeLinks", NULL);
RNA_def_struct_sdna(srna, "bNodeTree");
- RNA_def_struct_ui_text(srna, "Group Sockets", "Collection of group sockets");
+ RNA_def_struct_ui_text(srna, "Node Links", "Collection of Node Links");
- func = RNA_def_function(srna, "new", (in_out == SOCK_IN ? "rna_NodeTree_input_new" : "rna_NodeTree_output_new"));
- RNA_def_function_ui_description(func, "Add a socket to the group tree");
+ func = RNA_def_function(srna, "new", "rna_NodeTree_link_new");
+ RNA_def_function_ui_description(func, "Add a node link to this node tree");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
- RNA_def_string(func, "name", "Socket", MAX_NAME, "Name", "Name of the socket");
- RNA_def_enum(func, "type", node_socket_type_items, SOCK_FLOAT, "Type", "Type of socket");
- /* return value */
- parm = RNA_def_pointer(func, "socket", "NodeSocket", "", "New socket");
+ parm = RNA_def_pointer(func, "input", "NodeSocket", "", "The input socket");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ parm = RNA_def_pointer(func, "output", "NodeSocket", "", "The output socket");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ RNA_def_boolean(func, "verify_limits", TRUE, "Verify Limits", "Remove existing links if connection limit is exceeded");
+ /* return */
+ parm = RNA_def_pointer(func, "link", "NodeLink", "", "New node link");
RNA_def_function_return(func, parm);
- func = RNA_def_function(srna, "expose",
- (in_out == SOCK_IN ? "rna_NodeTree_input_expose" : "rna_NodeTree_output_expose"));
- RNA_def_function_ui_description(func, "Expose an internal socket in the group tree");
+ func = RNA_def_function(srna, "remove", "rna_NodeTree_link_remove");
+ RNA_def_function_ui_description(func, "remove a node link from the node tree");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ parm = RNA_def_pointer(func, "link", "NodeLink", "", "The node link to remove");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
+ RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
+
+ func = RNA_def_function(srna, "clear", "rna_NodeTree_link_clear");
+ RNA_def_function_ui_description(func, "remove all node links from the node tree");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+}
+
+static void rna_def_node_tree_sockets_api(BlenderRNA *brna, PropertyRNA *cprop, int in_out)
+{
+ StructRNA *srna;
+ PropertyRNA *parm;
+ FunctionRNA *func;
+ const char *structtype = (in_out == SOCK_IN ? "NodeTreeInputs" : "NodeTreeOutputs");
+ const char *uiname = (in_out == SOCK_IN ? "Node Tree Inputs" : "Node Tree Outputs");
+ const char *newfunc = (in_out == SOCK_IN ? "rna_NodeTree_inputs_new" : "rna_NodeTree_outputs_new");
+ const char *clearfunc = (in_out == SOCK_IN ? "rna_NodeTree_inputs_clear" : "rna_NodeTree_outputs_clear");
+
+ RNA_def_property_srna(cprop, structtype);
+ srna= RNA_def_struct(brna, structtype, NULL);
+ RNA_def_struct_sdna(srna, "bNodeTree");
+ RNA_def_struct_ui_text(srna, uiname, "Collection of Node Tree Sockets");
+
+ func= RNA_def_function(srna, "new", newfunc);
+ RNA_def_function_ui_description(func, "Add a socket to this node tree");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
- RNA_def_pointer(func, "sock", "NodeSocket", "Socket", "Internal node socket to expose");
+ parm= RNA_def_string(func, "type", "", MAX_NAME, "Type", "Data type");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ parm= RNA_def_string(func, "name", "", MAX_NAME, "Name", "");
RNA_def_property_flag(parm, PROP_REQUIRED);
- RNA_def_boolean(func, "add_link", TRUE, "Add Link", "If TRUE, adds a link to the internal socket");
/* return value */
- parm = RNA_def_pointer(func, "socket", "NodeSocket", "", "New socket");
+ parm= RNA_def_pointer(func, "socket", "NodeSocketInterface", "", "New socket");
RNA_def_function_return(func, parm);
+
+ func= RNA_def_function(srna, "remove", "rna_NodeTree_socket_remove");
+ RNA_def_function_ui_description(func, "Remove a socket from this node tree");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ parm= RNA_def_pointer(func, "socket", "NodeSocketInterface", "", "The socket to remove");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+
+ func= RNA_def_function(srna, "clear", clearfunc);
+ RNA_def_function_ui_description(func, "Remove all sockets from this node tree");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
}
static void rna_def_nodetree(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
+ FunctionRNA *func;
+ PropertyRNA *parm;
+
+ static EnumPropertyItem static_type_items[] = {
+ {NTREE_SHADER, "SHADER", ICON_MATERIAL, "Shader", "Shader nodes"},
+ {NTREE_TEXTURE, "TEXTURE", ICON_TEXTURE, "Texture", "Texture nodes"},
+ {NTREE_COMPOSIT, "COMPOSITING", ICON_RENDERLAYERS, "Compositing", "Compositing nodes"},
+ {0, NULL, 0, NULL, NULL}
+ };
srna = RNA_def_struct(brna, "NodeTree", "ID");
RNA_def_struct_ui_text(srna, "Node Tree",
@@ -4944,10 +6762,18 @@ static void rna_def_nodetree(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "bNodeTree");
RNA_def_struct_ui_icon(srna, ICON_NODETREE);
RNA_def_struct_refine_func(srna, "rna_NodeTree_refine");
+ RNA_def_struct_register_funcs(srna, "rna_NodeTree_register", "rna_NodeTree_unregister", NULL);
/* AnimData */
rna_def_animdata_common(srna);
-
+
+ /* Nodes Collection */
+ prop = RNA_def_property(srna, "nodes", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "nodes", NULL);
+ RNA_def_property_struct_type(prop, "Node");
+ RNA_def_property_ui_text(prop, "Nodes", "");
+ rna_def_nodetree_nodes_api(brna, prop);
+
/* NodeLinks Collection */
prop = RNA_def_property(srna, "links", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "links", NULL);
@@ -4965,21 +6791,100 @@ static void rna_def_nodetree(BlenderRNA *brna)
prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_enum_items(prop, nodetree_type_items);
- RNA_def_property_ui_text(prop, "Type", "Node Tree type");
+ RNA_def_property_enum_items(prop, static_type_items);
+ RNA_def_property_ui_text(prop, "Type", "Node Tree type (deprecated, bl_idname is the actual node tree type identifier)");
- /* group sockets */
prop = RNA_def_property(srna, "inputs", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "inputs", NULL);
- RNA_def_property_struct_type(prop, "NodeSocket");
- RNA_def_property_ui_text(prop, "Inputs", "");
- rna_def_group_sockets_api(brna, prop, SOCK_IN);
-
+ RNA_def_property_collection_funcs(prop, NULL, NULL, NULL, NULL, NULL, NULL,
+ "rna_NodeTree_inputs_lookupstring", NULL);
+ RNA_def_property_struct_type(prop, "NodeSocketInterface");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Inputs", "Node tree inputs");
+ rna_def_node_tree_sockets_api(brna, prop, SOCK_IN);
+
+ prop = RNA_def_property(srna, "active_input", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_funcs(prop, "rna_NodeTree_active_input_get", "rna_NodeTree_active_input_set", NULL);
+ RNA_def_property_ui_text(prop, "Active Input", "Index of the active input");
+ RNA_def_property_update(prop, NC_NODE, NULL);
+
prop = RNA_def_property(srna, "outputs", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "outputs", NULL);
- RNA_def_property_struct_type(prop, "NodeSocket");
- RNA_def_property_ui_text(prop, "Outputs", "");
- rna_def_group_sockets_api(brna, prop, SOCK_OUT);
+ RNA_def_property_collection_funcs(prop, NULL, NULL, NULL, NULL, NULL, NULL,
+ "rna_NodeTree_outputs_lookupstring", NULL);
+ RNA_def_property_struct_type(prop, "NodeSocketInterface");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Outputs", "Node tree outputs");
+ rna_def_node_tree_sockets_api(brna, prop, SOCK_OUT);
+
+ prop = RNA_def_property(srna, "active_output", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_funcs(prop, "rna_NodeTree_active_output_get", "rna_NodeTree_active_output_set", NULL);
+ RNA_def_property_ui_text(prop, "Active Output", "Index of the active output");
+ RNA_def_property_update(prop, NC_NODE, NULL);
+
+ /* exposed as a function for runtime interface type properties */
+ func = RNA_def_function(srna, "interface_update", "rna_NodeTree_interface_update");
+ RNA_def_function_ui_description(func, "Updated node group interface");
+ parm = RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+
+ /* registration */
+ prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "typeinfo->idname");
+ RNA_def_property_string_funcs(prop, "rna_NodeTree_bl_idname_get", "rna_NodeTree_bl_idname_length", NULL);
+ RNA_def_property_flag(prop, PROP_REGISTER|PROP_NEVER_CLAMP);
+ RNA_def_property_ui_text(prop, "ID Name", "");
+
+ prop = RNA_def_property(srna, "bl_label", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "typeinfo->ui_name");
+ RNA_def_property_string_funcs(prop, "rna_NodeTree_bl_label_get", "rna_NodeTree_bl_label_length", NULL);
+ RNA_def_property_flag(prop, PROP_REGISTER);
+ RNA_def_property_ui_text(prop, "Label", "The node tree label");
+
+ prop = RNA_def_property(srna, "bl_description", PROP_STRING, PROP_TRANSLATION);
+ RNA_def_property_string_sdna(prop, NULL, "typeinfo->ui_description");
+ RNA_def_property_string_funcs(prop, "rna_NodeTree_bl_description_get", "rna_NodeTree_bl_description_length", NULL);
+ RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
+
+ prop = RNA_def_property(srna, "bl_icon", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "typeinfo->ui_icon");
+ RNA_def_property_enum_funcs(prop, "rna_NodeTree_bl_icon_get", NULL, NULL);
+ RNA_def_property_enum_items(prop, node_icon_items);
+ RNA_def_property_enum_default(prop, ICON_NODETREE);
+ RNA_def_property_flag(prop, PROP_REGISTER);
+ RNA_def_property_ui_text(prop, "Icon", "The node tree icon");
+
+ /* poll */
+ func = RNA_def_function(srna, "poll", NULL);
+ RNA_def_function_ui_description(func, "Check visibility in the editor");
+ RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_REGISTER_OPTIONAL);
+ parm = RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+ RNA_def_function_return(func, RNA_def_boolean(func, "visible", FALSE, "", ""));
+
+ /* draw add menu */
+ func = RNA_def_function(srna, "draw_add_menu", NULL);
+ RNA_def_function_ui_description(func, "Draw the menu for adding nodes");
+ RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL);
+ parm = RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED|PROP_NEVER_NULL);
+ parm = RNA_def_property(func, "layout", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(parm, "UILayout");
+ RNA_def_property_ui_text(parm, "Layout", "Menu layout in the UI");
+ RNA_def_property_flag(parm, PROP_REQUIRED|PROP_NEVER_NULL);
+
+ /* get a node tree from context */
+ func = RNA_def_function(srna, "get_from_context", NULL);
+ RNA_def_function_ui_description(func, "Get a node tree from the context");
+ RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_REGISTER_OPTIONAL);
+ parm = RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+ parm = RNA_def_pointer(func, "result_1", "NodeTree", "Node Tree", "Active node tree from context");
+ RNA_def_function_output(func, parm);
+ parm = RNA_def_pointer(func, "result_2", "ID", "Owner ID", "ID data block that owns the node tree");
+ RNA_def_function_output(func, parm);
+ parm = RNA_def_pointer(func, "result_3", "ID", "From ID", "Original ID data block selected from the context");
+ RNA_def_function_output(func, parm);
}
static void rna_def_composite_nodetree(BlenderRNA *brna)
@@ -4990,15 +6895,7 @@ static void rna_def_composite_nodetree(BlenderRNA *brna)
srna = RNA_def_struct(brna, "CompositorNodeTree", "NodeTree");
RNA_def_struct_ui_text(srna, "Compositor Node Tree", "Node tree consisting of linked nodes used for compositing");
RNA_def_struct_sdna(srna, "bNodeTree");
- RNA_def_struct_ui_icon(srna, ICON_NODETREE);
-
- /* Nodes Collection */
- prop = RNA_def_property(srna, "nodes", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_collection_sdna(prop, NULL, "nodes", NULL);
- RNA_def_property_struct_type(prop, "Node");
- RNA_def_property_ui_text(prop, "Nodes", "");
-
- rna_def_composite_nodetree_api(brna, prop);
+ RNA_def_struct_ui_icon(srna, ICON_RENDERLAYERS);
prop = RNA_def_property(srna, "render_quality", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "render_quality");
@@ -5029,6 +6926,11 @@ static void rna_def_composite_nodetree(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Two Pass", "Use two pass execution during editing: first calculate fast nodes, "
"second pass calculate all nodes");
+ prop = RNA_def_property(srna, "is_local_tree", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_default(prop, FALSE);
+ RNA_def_property_flag(prop, PROP_IDPROPERTY);
+ RNA_def_property_ui_text(prop, "Local Scene Tree", "Local scene node tree, eligible for special node types");
+
prop = RNA_def_property(srna, "use_viewer_border", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", NTREE_VIEWER_BORDER);
RNA_def_property_ui_text(prop, "Viewer Border", "Use boundaries for viewer nodes and composite backdrop");
@@ -5044,15 +6946,12 @@ static void rna_def_shader_nodetree(BlenderRNA *brna)
RNA_def_struct_ui_text(srna, "Shader Node Tree",
"Node tree consisting of linked nodes used for materials (and other shading datablocks)");
RNA_def_struct_sdna(srna, "bNodeTree");
- RNA_def_struct_ui_icon(srna, ICON_NODETREE);
+ RNA_def_struct_ui_icon(srna, ICON_MATERIAL);
- /* Nodes Collection */
- prop = RNA_def_property(srna, "nodes", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_collection_sdna(prop, NULL, "nodes", NULL);
- RNA_def_property_struct_type(prop, "Node");
- RNA_def_property_ui_text(prop, "Nodes", "");
-
- rna_def_shader_nodetree_api(brna, prop);
+ prop = RNA_def_property(srna, "is_local_tree", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_default(prop, FALSE);
+ RNA_def_property_flag(prop, PROP_IDPROPERTY);
+ RNA_def_property_ui_text(prop, "Local Material Tree", "Local material node tree, eligible for special node types");
}
static void rna_def_texture_nodetree(BlenderRNA *brna)
@@ -5063,64 +6962,87 @@ static void rna_def_texture_nodetree(BlenderRNA *brna)
srna = RNA_def_struct(brna, "TextureNodeTree", "NodeTree");
RNA_def_struct_ui_text(srna, "Texture Node Tree", "Node tree consisting of linked nodes used for textures");
RNA_def_struct_sdna(srna, "bNodeTree");
- RNA_def_struct_ui_icon(srna, ICON_NODETREE);
-
- /* Nodes Collection */
- prop = RNA_def_property(srna, "nodes", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_collection_sdna(prop, NULL, "nodes", NULL);
- RNA_def_property_struct_type(prop, "Node");
- RNA_def_property_ui_text(prop, "Nodes", "");
+ RNA_def_struct_ui_icon(srna, ICON_TEXTURE);
- rna_def_texture_nodetree_api(brna, prop);
+ prop = RNA_def_property(srna, "is_local_tree", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_default(prop, FALSE);
+ RNA_def_property_flag(prop, PROP_IDPROPERTY);
+ RNA_def_property_ui_text(prop, "Local Texture Tree", "Local texture node tree, eligible for special node types");
}
-static void define_specific_node(BlenderRNA *brna, int id, void (*def_func)(StructRNA *))
+static void define_specific_node(BlenderRNA *brna, const char *struct_name, const char *base_name,
+ const char *ui_name, const char *ui_desc, void (*def_func)(StructRNA *))
{
- StructRNA *srna = def_node(brna, id);
+ StructRNA *srna;
+ FunctionRNA *func;
+ PropertyRNA *parm;
+ srna = RNA_def_struct(brna, struct_name, base_name);
+ RNA_def_struct_ui_text(srna, ui_name, ui_desc);
+ RNA_def_struct_sdna(srna, "bNode");
+
+ func = RNA_def_function(srna, "is_registered_node_type", "rna_Node_is_registered_node_type");
+ RNA_def_function_ui_description(func, "True if a registered node type");
+ RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_USE_SELF_TYPE);
+ parm = RNA_def_boolean(func, "result", FALSE, "Result", "");
+ RNA_def_function_return(func, parm);
+
if (def_func)
def_func(srna);
}
+static void rna_def_node_instance_hash(BlenderRNA *brna)
+{
+ StructRNA *srna;
+
+ srna = RNA_def_struct(brna, "NodeInstanceHash", NULL);
+ RNA_def_struct_ui_text(srna, "Node Instance Hash", "Hash table containing node instance data");
+
+ /* XXX This type is a stub for now, only used to store instance hash in the context.
+ * Eventually could use a StructRNA pointer to define a specific data type
+ * and expose lookup functions.
+ */
+}
+
void RNA_def_nodetree(BlenderRNA *brna)
{
- init();
- rna_def_nodetree(brna);
-
rna_def_node_socket(brna);
-
- /* Generate RNA definitions for all socket subtypes */
- #define SUBTYPE(socktype, stypename, id, idname) \
- rna_def_node_socket_subtype(brna, SOCK_##socktype, PROP_##id, "NodeSocket"#stypename#idname, \
- #idname" "#stypename" Node Socket");
- NODE_DEFINE_SUBTYPES
- #undef SUBTYPE
- rna_def_node_socket_subtype(brna, SOCK_BOOLEAN, 0, "NodeSocketBoolean", "Boolean Node Socket");
- rna_def_node_socket_subtype(brna, SOCK_RGBA, 0, "NodeSocketRGBA", "RGBA Node Socket");
- rna_def_node_socket_subtype(brna, SOCK_SHADER, 0, "NodeSocketShader", "Shader Closure Node Socket");
+ rna_def_node_socket_interface(brna);
rna_def_node(brna);
rna_def_node_link(brna);
rna_def_shader_node(brna);
rna_def_compositor_node(brna);
rna_def_texture_node(brna);
- rna_def_special_node(brna);
+
+ rna_def_nodetree(brna);
+
+ rna_def_node_socket_standard_types(brna);
rna_def_composite_nodetree(brna);
rna_def_shader_nodetree(brna);
rna_def_texture_nodetree(brna);
+
#define DefNode(Category, ID, DefFunc, EnumName, StructName, UIName, UIDesc) \
- define_specific_node(brna, ID, DefFunc);
-
- #include "rna_nodetree_types.h"
+ define_specific_node(brna, #Category #StructName, #Category, UIName, UIDesc, DefFunc);
- define_specific_node(brna, NODE_GROUP, def_group);
- define_specific_node(brna, NODE_FRAME, def_frame);
- define_specific_node(brna, NODE_REROUTE, 0);
+ /* hack, don't want to add include path to RNA just for this, since in the future RNA types
+ * for nodes should be defined locally at runtime anyway ...
+ */
+ #include "../../nodes/NOD_static_types.h"
+
+ /* Node group types need to be defined for shader, compositor, texture nodes individually.
+ * Cannot use the static types header for this, since they share the same int id.
+ */
+ define_specific_node(brna, "ShaderNodeGroup", "ShaderNode", "Group", "", def_group);
+ define_specific_node(brna, "CompositorNodeGroup", "CompositorNode", "Group", "", def_group);
+ define_specific_node(brna, "TextureNodeGroup", "TextureNode", "Group", "", def_group);
/* special socket types */
rna_def_cmp_output_file_slot_file(brna);
rna_def_cmp_output_file_slot_layer(brna);
+
+ rna_def_node_instance_hash(brna);
}
/* clean up macro definition */
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index d556cc0dcdc..e03e7d222c6 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -1173,13 +1173,12 @@ static void rna_SceneRenderLayer_pass_update(Main *bmain, Scene *activescene, Po
rna_Scene_glsl_update(bmain, activescene, ptr);
}
-static void rna_Scene_use_nodes_set(PointerRNA *ptr, int value)
+static void rna_Scene_use_nodes_update(bContext *C, PointerRNA *ptr)
{
Scene *scene = (Scene *)ptr->data;
- scene->use_nodes = value;
if (scene->use_nodes && scene->nodetree == NULL)
- ED_node_composit_default(scene);
+ ED_node_composit_default(C, scene);
}
static void rna_Physics_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
@@ -4533,9 +4532,9 @@ void RNA_def_scene(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_nodes", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "use_nodes", 1);
- RNA_def_property_boolean_funcs(prop, NULL, "rna_Scene_use_nodes_set");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_ui_text(prop, "Use Nodes", "Enable the compositing node tree");
- RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_use_nodes_update");
/* Sequencer */
prop = RNA_def_property(srna, "sequence_editor", PROP_POINTER, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index d88e8ed782a..f365352ca30 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -25,6 +25,7 @@
*/
#include <stdlib.h>
+#include <string.h>
#include "MEM_guardedalloc.h"
@@ -32,6 +33,7 @@
#include "BKE_key.h"
#include "BKE_movieclip.h"
+#include "BKE_node.h"
#include "DNA_action_types.h"
#include "DNA_key_types.h"
@@ -1014,20 +1016,91 @@ static void rna_BackgroundImage_clear(View3D *v3d)
/* Space Node Editor */
-static int rna_SpaceNodeEditor_node_tree_poll(PointerRNA *ptr, PointerRNA value)
+static void rna_SpaceNodeEditor_node_tree_set(PointerRNA *ptr, const PointerRNA value)
+{
+ SpaceNode *snode = (SpaceNode *)ptr->data;
+ ED_node_tree_start(snode, (bNodeTree *)value.data, NULL, NULL);
+}
+
+static int rna_SpaceNodeEditor_node_tree_poll(PointerRNA *ptr, const PointerRNA value)
{
SpaceNode *snode = (SpaceNode *)ptr->data;
bNodeTree *ntree = (bNodeTree *)value.data;
- /* exclude group trees, only trees of the active type */
- return (ntree->nodetype == 0 && ntree->type == snode->treetype);
+ /* node tree type must match the selected type in node editor */
+ return (strcmp(snode->tree_idname, ntree->idname) == 0);
}
-static void rna_SpaceNodeEditor_node_tree_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr)
+static void rna_SpaceNodeEditor_node_tree_update(const bContext *C, PointerRNA *UNUSED(ptr))
{
- SpaceNode *snode = (SpaceNode *)ptr->data;
+ ED_node_tree_update(C);
+}
+
+static int rna_SpaceNodeEditor_tree_type_get(PointerRNA *ptr)
+{
+ SpaceNode *snode= (SpaceNode*)ptr->data;
+ return rna_node_tree_idname_to_enum(snode->tree_idname);
+}
+static void rna_SpaceNodeEditor_tree_type_set(PointerRNA *ptr, int value)
+{
+ SpaceNode *snode= (SpaceNode*)ptr->data;
+ ED_node_set_tree_type(snode, rna_node_tree_type_from_enum(value));
+}
+static int rna_SpaceNodeEditor_tree_type_poll(void *Cv, bNodeTreeType *type)
+{
+ bContext *C = (bContext *)Cv;
+ if (type->poll)
+ return type->poll(C, type);
+ else
+ return TRUE;
+}
+static EnumPropertyItem *rna_SpaceNodeEditor_tree_type_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), int *free)
+{
+ return rna_node_tree_type_itemf(C, rna_SpaceNodeEditor_tree_type_poll, free);
+}
+
+static void rna_SpaceNodeEditor_path_get(PointerRNA *ptr, char *value)
+{
+ SpaceNode *snode = ptr->data;
+ ED_node_tree_path_get(snode, value);
+}
+
+static int rna_SpaceNodeEditor_path_length(PointerRNA *ptr)
+{
+ SpaceNode *snode = ptr->data;
+ return ED_node_tree_path_length(snode);
+}
+
+void rna_SpaceNodeEditor_path_clear(SpaceNode *snode, bContext *C)
+{
+ ED_node_tree_start(snode, NULL, NULL, NULL);
+ ED_node_tree_update(C);
+}
+
+void rna_SpaceNodeEditor_path_start(SpaceNode *snode, bContext *C, PointerRNA *node_tree)
+{
+ ED_node_tree_start(snode, (bNodeTree *)node_tree->data, NULL, NULL);
+ ED_node_tree_update(C);
+}
+
+void rna_SpaceNodeEditor_path_push(SpaceNode *snode, bContext *C, ReportList *reports, PointerRNA *node)
+{
+ PointerRNA tree_ptr;
+
+ tree_ptr = RNA_pointer_get(node, "node_tree");
+ if (!tree_ptr.data) {
+ BKE_reportf(reports, RPT_WARNING, "Missing node group tree in node %s", ((bNode *)node->data)->name);
+ return;
+ }
- ED_node_tree_update(snode, scene);
+ ED_node_tree_push(snode, (bNodeTree *)tree_ptr.data, (bNode *)node->data);
+ ED_node_tree_update(C);
+}
+
+void rna_SpaceNodeEditor_path_pop(SpaceNode *snode, bContext *C)
+{
+ ED_node_tree_pop(snode);
+ ED_node_tree_update(C);
}
static EnumPropertyItem *rna_SpaceProperties_texture_context_itemf(bContext *C, PointerRNA *UNUSED(ptr),
@@ -3077,6 +3150,58 @@ static void rna_def_space_userpref(BlenderRNA *brna)
}
+static void rna_def_node_tree_path(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "NodeTreePath", NULL);
+ RNA_def_struct_sdna(srna, "bNodeTreePath");
+ RNA_def_struct_ui_text(srna, "Node Tree Path", "Element of the node space tree path");
+
+ prop = RNA_def_property(srna, "node_tree", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "nodetree");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Node Tree", "Base node tree from context");
+}
+
+static void rna_def_space_node_path_api(BlenderRNA *brna, PropertyRNA *cprop)
+{
+ StructRNA *srna;
+ PropertyRNA *prop, *parm;
+ FunctionRNA *func;
+
+ RNA_def_property_srna(cprop, "SpaceNodeEditorPath");
+ srna = RNA_def_struct(brna, "SpaceNodeEditorPath", NULL);
+ RNA_def_struct_sdna(srna, "SpaceNode");
+ RNA_def_struct_ui_text(srna, "Space Node Editor Path", "History of node trees in the editor");
+
+ prop = RNA_def_property(srna, "to_string", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_funcs(prop, "rna_SpaceNodeEditor_path_get", "rna_SpaceNodeEditor_path_length", NULL);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_struct_ui_text(srna, "Path", "Get the node tree path as a string");
+
+ func = RNA_def_function(srna, "clear", "rna_SpaceNodeEditor_path_clear");
+ RNA_def_function_ui_description(func, "Reset the node tree path");
+ RNA_def_function_flag(func, FUNC_USE_CONTEXT);
+
+ func = RNA_def_function(srna, "start", "rna_SpaceNodeEditor_path_start");
+ RNA_def_function_ui_description(func, "Set the root node tree");
+ RNA_def_function_flag(func, FUNC_USE_CONTEXT);
+ parm = RNA_def_pointer(func, "node_tree", "NodeTree", "Node Tree", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR);
+
+ func = RNA_def_function(srna, "push", "rna_SpaceNodeEditor_path_push");
+ RNA_def_function_ui_description(func, "Append a node group tree to the path");
+ RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
+ parm = RNA_def_pointer(func, "node", "NodeGroup", "Node", "Group node");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR);
+
+ func = RNA_def_function(srna, "pop", "rna_SpaceNodeEditor_path_pop");
+ RNA_def_function_ui_description(func, "Remove the last node tree from the path");
+ RNA_def_function_flag(func, FUNC_USE_CONTEXT);
+}
+
static void rna_def_space_node(BlenderRNA *brna)
{
StructRNA *srna;
@@ -3106,13 +3231,17 @@ static void rna_def_space_node(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
+ static EnumPropertyItem dummy_items[] = {
+ {0, "DUMMY", 0, "", ""},
+ {0, NULL, 0, NULL, NULL}};
+
srna = RNA_def_struct(brna, "SpaceNodeEditor", "Space");
RNA_def_struct_sdna(srna, "SpaceNode");
RNA_def_struct_ui_text(srna, "Space Node Editor", "Node editor space data");
prop = RNA_def_property(srna, "tree_type", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "treetype");
- RNA_def_property_enum_items(prop, nodetree_type_items);
+ RNA_def_property_enum_items(prop, dummy_items);
+ RNA_def_property_enum_funcs(prop, "rna_SpaceNodeEditor_tree_type_get", "rna_SpaceNodeEditor_tree_type_set", "rna_SpaceNodeEditor_tree_type_itemf");
RNA_def_property_ui_text(prop, "Tree Type", "Node tree type to display and edit");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NODE, NULL);
@@ -3137,17 +3266,29 @@ static void rna_def_space_node(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "ID From", "Datablock from which the edited datablock is linked");
+ prop= RNA_def_property(srna, "path", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "treepath", NULL);
+ RNA_def_property_struct_type(prop, "NodeTreePath");
+ RNA_def_property_ui_text(prop, "Node Tree Path", "Path from the data block to the currently edited node tree");
+ rna_def_space_node_path_api(brna, prop);
+
prop = RNA_def_property(srna, "node_tree", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_funcs(prop, NULL, "rna_SpaceNodeEditor_node_tree_set", NULL, "rna_SpaceNodeEditor_node_tree_poll");
RNA_def_property_pointer_sdna(prop, NULL, "nodetree");
- RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_SpaceNodeEditor_node_tree_poll");
- RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Node Tree", "Node tree being displayed");
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_CONTEXT_UPDATE);
+ RNA_def_property_ui_text(prop, "Node Tree", "Base node tree from context");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NODE, "rna_SpaceNodeEditor_node_tree_update");
- prop = RNA_def_property(srna, "edit_tree", PROP_POINTER, PROP_NONE);
+ prop= RNA_def_property(srna, "edit_tree", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "edittree");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Edit Tree", "Edited node tree");
+ RNA_def_property_ui_text(prop, "Edit Tree", "Node tree being displayed and edited");
+
+ prop= RNA_def_property(srna, "pin", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", SNODE_PIN);
+ RNA_def_property_ui_text(prop, "Pinned", "Use the pinned node tree");
+ RNA_def_property_ui_icon(prop, ICON_UNPINNED, 1);
+ RNA_def_property_update(prop, NC_SPACE|ND_SPACE_NODE, NULL);
prop = RNA_def_property(srna, "show_backdrop", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SNODE_BACKDRAW);
@@ -3544,6 +3685,7 @@ void RNA_def_space(BlenderRNA *brna)
rna_def_console_line(brna);
rna_def_space_info(brna);
rna_def_space_userpref(brna);
+ rna_def_node_tree_path(brna);
rna_def_space_node(brna);
rna_def_space_logic(brna);
rna_def_space_clip(brna);
diff --git a/source/blender/makesrna/intern/rna_texture.c b/source/blender/makesrna/intern/rna_texture.c
index d86e5fd0d9c..009823555f0 100644
--- a/source/blender/makesrna/intern/rna_texture.c
+++ b/source/blender/makesrna/intern/rna_texture.c
@@ -107,6 +107,7 @@ EnumPropertyItem blend_type_items[] = {
#include "RNA_access.h"
+#include "BKE_context.h"
#include "BKE_depsgraph.h"
#include "BKE_image.h"
#include "BKE_texture.h"
@@ -167,7 +168,7 @@ static void rna_Texture_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *pt
}
else if (GS(id->name) == ID_NT) {
bNodeTree *ntree = ptr->id.data;
- ED_node_generic_update(bmain, ntree, NULL);
+ ED_node_tag_update_nodetree(bmain, ntree);
}
}
@@ -384,15 +385,18 @@ static void rna_Texture_use_color_ramp_set(PointerRNA *ptr, int value)
tex->coba = add_colorband(0);
}
-static void rna_Texture_use_nodes_set(PointerRNA *ptr, int v)
+static void rna_Texture_use_nodes_update(bContext *C, PointerRNA *ptr)
{
Tex *tex = (Tex *)ptr->data;
- tex->use_nodes = v;
- tex->type = 0;
+ if (tex->use_nodes) {
+ tex->type = 0;
+
+ if (tex->nodetree == NULL)
+ ED_node_texture_default(C, tex);
+ }
- if (v && tex->nodetree == NULL)
- ED_node_texture_default(tex);
+ rna_Texture_nodes_update(CTX_data_main(C), CTX_data_scene(C), ptr);
}
static void rna_ImageTexture_mipmap_set(PointerRNA *ptr, int value)
@@ -2021,9 +2025,9 @@ static void rna_def_texture(BlenderRNA *brna)
/* nodetree */
prop = RNA_def_property(srna, "use_nodes", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "use_nodes", 1);
- RNA_def_property_boolean_funcs(prop, NULL, "rna_Texture_use_nodes_set");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_ui_text(prop, "Use Nodes", "Make this a node-based texture");
- RNA_def_property_update(prop, 0, "rna_Texture_nodes_update");
+ RNA_def_property_update(prop, 0, "rna_Texture_use_nodes_update");
prop = RNA_def_property(srna, "node_tree", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "nodetree");
diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c
index 0204fa5367b..41d1411d35c 100644
--- a/source/blender/makesrna/intern/rna_ui_api.c
+++ b/source/blender/makesrna/intern/rna_ui_api.c
@@ -419,6 +419,8 @@ void RNA_api_ui_layout(StructRNA *srna)
{0, NULL, 0, NULL, NULL}
};
+ static float node_socket_color_default[] = { 0.0f, 0.0f, 0.0f, 1.0f };
+
/* simple layout specifiers */
func = RNA_def_function(srna, "row", "uiLayoutRow");
parm = RNA_def_pointer(func, "layout", "UILayout", "", "Sub-layout to put items in");
@@ -829,6 +831,14 @@ void RNA_api_ui_layout(StructRNA *srna)
parm = RNA_def_pointer(func, "item", "KeyMapItem", "", "");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR | PROP_NEVER_NULL);
+ func = RNA_def_function(srna, "template_component_menu", "uiTemplateComponentMenu");
+ RNA_def_function_ui_description(func, "Item. Display expanded property in a popup menu");
+ parm = RNA_def_pointer(func, "data", "AnyType", "", "Data from which to take property");
+ RNA_def_property_flag(parm, PROP_REQUIRED|PROP_RNAPTR);
+ parm = RNA_def_string(func, "property", "", 0, "", "Identifier of property in data");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ RNA_def_string(func, "name", "", 0, "", "");
+
func = RNA_def_function(srna, "introspect", "uiLayoutIntrospect");
parm = RNA_def_string(func, "string", "", 1024 * 1024, "Descr", "DESCR");
RNA_def_function_return(func, parm);
@@ -843,6 +853,12 @@ void RNA_api_ui_layout(StructRNA *srna)
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
api_ui_item_rna_common(func);
/* RNA_def_boolean(func, "show_global_settings", 0, "", "Show widgets to control global color management settings"); */
+
+ /* node socket icon */
+ func = RNA_def_function(srna, "template_node_socket", "uiTemplateNodeSocket");
+ RNA_def_function_ui_description(func, "Node Socket Icon");
+ RNA_def_function_flag(func, FUNC_USE_CONTEXT);
+ RNA_def_float_array(func, "color", 4, node_socket_color_default, 0.0f, 1.0f, "Color", "", 0.0f, 1.0f);
}
#endif
diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c
index 3824ee28956..12fac82fb75 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -1884,6 +1884,12 @@ static void rna_def_userdef_theme_space_node(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Group Node", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
+ prop= RNA_def_property(srna, "group_socket_node", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "console_output");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Group Socket Node", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
prop = RNA_def_property(srna, "frame_node", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_float_sdna(prop, NULL, "movie");
RNA_def_property_array(prop, 4);
diff --git a/source/blender/makesrna/intern/rna_world.c b/source/blender/makesrna/intern/rna_world.c
index 02a04d36c23..b689a82c231 100644
--- a/source/blender/makesrna/intern/rna_world.c
+++ b/source/blender/makesrna/intern/rna_world.c
@@ -42,6 +42,7 @@
#include "MEM_guardedalloc.h"
+#include "BKE_context.h"
#include "BKE_depsgraph.h"
#include "BKE_main.h"
#include "BKE_texture.h"
@@ -121,14 +122,14 @@ static void rna_World_stars_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Po
WM_main_add_notifier(NC_WORLD | ND_WORLD_STARS, wo);
}
-static void rna_World_use_nodes_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_World_use_nodes_update(bContext *C, PointerRNA *ptr)
{
World *wrld = (World *)ptr->data;
if (wrld->use_nodes && wrld->nodetree == NULL)
- ED_node_shader_default(scene, &wrld->id);
+ ED_node_shader_default(C, &wrld->id);
- rna_World_update(bmain, scene, ptr);
+ rna_World_update(CTX_data_main(C), CTX_data_scene(C), ptr);
}
#else
@@ -581,6 +582,7 @@ void RNA_def_world(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_nodes", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "use_nodes", 1);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_ui_text(prop, "Use Nodes", "Use shader nodes to render the world");
RNA_def_property_update(prop, 0, "rna_World_use_nodes_update");
diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt
index 12842085189..f3b3d6b1f53 100644
--- a/source/blender/nodes/CMakeLists.txt
+++ b/source/blender/nodes/CMakeLists.txt
@@ -123,7 +123,7 @@ set(SRC
composite/nodes/node_composite_pixelate.c
composite/node_composite_tree.c
- composite/node_composite_util.h
+ composite/node_composite_util.c
shader/nodes/node_shader_camera.c
shader/nodes/node_shader_common.c
@@ -224,13 +224,16 @@ set(SRC
intern/node_common.c
intern/node_socket.c
+ composite/node_composite_util.h
shader/node_shader_util.h
texture/node_texture_util.h
+ NOD_common.h
NOD_composite.h
NOD_shader.h
NOD_texture.h
NOD_socket.h
+ NOD_static_types.h
intern/node_util.h
intern/node_exec.h
intern/node_common.h
diff --git a/source/blender/nodes/NOD_common.h b/source/blender/nodes/NOD_common.h
new file mode 100644
index 00000000000..ac0ceab36d4
--- /dev/null
+++ b/source/blender/nodes/NOD_common.h
@@ -0,0 +1,54 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2005 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Lukas Toenne.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file NOD_common.h
+ * \ingroup nodes
+ */
+
+#ifndef NOD_COMMON_H
+#define NOD_COMMON_H
+
+#include "BKE_node.h"
+
+void register_node_type_frame(void);
+void register_node_type_reroute(void);
+
+void register_node_type_group_input(void);
+void register_node_type_group_output(void);
+
+
+/* internal functions for editor */
+struct bNodeSocket *node_group_find_input_socket(struct bNode *groupnode, const char *identifier);
+struct bNodeSocket *node_group_find_output_socket(struct bNode *groupnode, const char *identifier);
+void node_group_verify(struct bNodeTree *ntree, struct bNode *node, struct ID *id);
+
+struct bNodeSocket *node_group_input_find_socket(struct bNode *node, const char *identifier);
+struct bNodeSocket *node_group_output_find_socket(struct bNode *node, const char *identifier);
+void node_group_input_verify(struct bNodeTree *ntree, struct bNode *node, struct ID *id);
+void node_group_output_verify(struct bNodeTree *ntree, struct bNode *node, struct ID *id);
+
+#endif
diff --git a/source/blender/nodes/NOD_composite.h b/source/blender/nodes/NOD_composite.h
index 6d60ac0bb58..f272ec670e7 100644
--- a/source/blender/nodes/NOD_composite.h
+++ b/source/blender/nodes/NOD_composite.h
@@ -34,105 +34,109 @@
#include "BKE_node.h"
-extern bNodeTreeType ntreeType_Composite;
+extern struct bNodeTreeType *ntreeType_Composite;
/* ****************** types array for all composite nodes ****************** */
-void register_node_type_cmp_group(struct bNodeTreeType *ttype);
+void register_node_tree_type_cmp(void);
-void register_node_type_cmp_rlayers(struct bNodeTreeType *ttype);
-void register_node_type_cmp_image(struct bNodeTreeType *ttype);
-void register_node_type_cmp_texture(struct bNodeTreeType *ttype);
-void register_node_type_cmp_value(struct bNodeTreeType *ttype);
-void register_node_type_cmp_rgb(struct bNodeTreeType *ttype);
-void register_node_type_cmp_curve_time(struct bNodeTreeType *ttype);
-void register_node_type_cmp_movieclip(struct bNodeTreeType *ttype);
+void register_node_type_cmp_group(void);
+void register_node_type_cmp_forloop(void);
+void register_node_type_cmp_whileloop(void);
+
+void register_node_type_cmp_rlayers(void);
+void register_node_type_cmp_image(void);
+void register_node_type_cmp_texture(void);
+void register_node_type_cmp_value(void);
+void register_node_type_cmp_rgb(void);
+void register_node_type_cmp_curve_time(void);
+void register_node_type_cmp_movieclip(void);
void register_node_type_cmp_usermask(struct bNodeTreeType *ttype);
-void register_node_type_cmp_composite(struct bNodeTreeType *ttype);
-void register_node_type_cmp_viewer(struct bNodeTreeType *ttype);
-void register_node_type_cmp_splitviewer(struct bNodeTreeType *ttype);
-void register_node_type_cmp_output_file(struct bNodeTreeType *ttype);
-void register_node_type_cmp_view_levels(struct bNodeTreeType *ttype);
-
-void register_node_type_cmp_curve_rgb(struct bNodeTreeType *ttype);
-void register_node_type_cmp_mix_rgb(struct bNodeTreeType *ttype);
-void register_node_type_cmp_hue_sat(struct bNodeTreeType *ttype);
-void register_node_type_cmp_brightcontrast(struct bNodeTreeType *ttype);
-void register_node_type_cmp_gamma(struct bNodeTreeType *ttype);
-void register_node_type_cmp_invert(struct bNodeTreeType *ttype);
-void register_node_type_cmp_alphaover(struct bNodeTreeType *ttype);
-void register_node_type_cmp_zcombine(struct bNodeTreeType *ttype);
-void register_node_type_cmp_colorbalance(struct bNodeTreeType *ttype);
-void register_node_type_cmp_huecorrect(struct bNodeTreeType *ttype);
-
-void register_node_type_cmp_normal(struct bNodeTreeType *ttype);
-void register_node_type_cmp_curve_vec(struct bNodeTreeType *ttype);
-void register_node_type_cmp_map_value(struct bNodeTreeType *ttype);
-void register_node_type_cmp_map_range(struct bNodeTreeType *ttype);
-void register_node_type_cmp_normalize(struct bNodeTreeType *ttype);
-
-void register_node_type_cmp_filter(struct bNodeTreeType *ttype);
-void register_node_type_cmp_blur(struct bNodeTreeType *ttype);
-void register_node_type_cmp_dblur(struct bNodeTreeType *ttype);
-void register_node_type_cmp_bilateralblur(struct bNodeTreeType *ttype);
-void register_node_type_cmp_vecblur(struct bNodeTreeType *ttype);
-void register_node_type_cmp_dilateerode(struct bNodeTreeType *ttype);
-void register_node_type_cmp_inpaint(struct bNodeTreeType *ttype);
-void register_node_type_cmp_despeckle(struct bNodeTreeType *ttype);
-void register_node_type_cmp_defocus(struct bNodeTreeType *ttype);
-
-void register_node_type_cmp_valtorgb(struct bNodeTreeType *ttype);
-void register_node_type_cmp_rgbtobw(struct bNodeTreeType *ttype);
-void register_node_type_cmp_setalpha(struct bNodeTreeType *ttype);
-void register_node_type_cmp_idmask(struct bNodeTreeType *ttype);
-void register_node_type_cmp_math(struct bNodeTreeType *ttype);
-void register_node_type_cmp_seprgba(struct bNodeTreeType *ttype);
-void register_node_type_cmp_combrgba(struct bNodeTreeType *ttype);
-void register_node_type_cmp_sephsva(struct bNodeTreeType *ttype);
-void register_node_type_cmp_combhsva(struct bNodeTreeType *ttype);
-void register_node_type_cmp_sepyuva(struct bNodeTreeType *ttype);
-void register_node_type_cmp_combyuva(struct bNodeTreeType *ttype);
-void register_node_type_cmp_sepycca(struct bNodeTreeType *ttype);
-void register_node_type_cmp_combycca(struct bNodeTreeType *ttype);
-void register_node_type_cmp_premulkey(struct bNodeTreeType *ttype);
-
-void register_node_type_cmp_diff_matte(struct bNodeTreeType *ttype);
-void register_node_type_cmp_distance_matte(struct bNodeTreeType *ttype);
-void register_node_type_cmp_chroma_matte(struct bNodeTreeType *ttype);
-void register_node_type_cmp_color_matte(struct bNodeTreeType *ttype);
-void register_node_type_cmp_channel_matte(struct bNodeTreeType *ttype);
-void register_node_type_cmp_color_spill(struct bNodeTreeType *ttype);
-void register_node_type_cmp_luma_matte(struct bNodeTreeType *ttype);
-void register_node_type_cmp_doubleedgemask(struct bNodeTreeType *ttype);
-void register_node_type_cmp_keyingscreen(struct bNodeTreeType *ttype);
-void register_node_type_cmp_keying(struct bNodeTreeType *ttype);
-
-void register_node_type_cmp_translate(struct bNodeTreeType *ttype);
-void register_node_type_cmp_rotate(struct bNodeTreeType *ttype);
-void register_node_type_cmp_scale(struct bNodeTreeType *ttype);
-void register_node_type_cmp_flip(struct bNodeTreeType *ttype);
-void register_node_type_cmp_crop(struct bNodeTreeType *ttype);
-void register_node_type_cmp_displace(struct bNodeTreeType *ttype);
-void register_node_type_cmp_mapuv(struct bNodeTreeType *ttype);
-void register_node_type_cmp_transform(struct bNodeTreeType *ttype);
-void register_node_type_cmp_stabilize2d(struct bNodeTreeType *ttype);
-void register_node_type_cmp_moviedistortion(struct bNodeTreeType *ttype);
-void register_node_type_cmp_mask(struct bNodeTreeType *ttype);
-
-void register_node_type_cmp_glare(struct bNodeTreeType *ttype);
-void register_node_type_cmp_tonemap(struct bNodeTreeType *ttype);
-void register_node_type_cmp_lensdist(struct bNodeTreeType *ttype);
-
-
-void register_node_type_cmp_colorcorrection(struct bNodeTreeType *ttype);
-void register_node_type_cmp_boxmask(struct bNodeTreeType *ttype);
-void register_node_type_cmp_ellipsemask(struct bNodeTreeType *ttype);
-void register_node_type_cmp_bokehimage(struct bNodeTreeType *ttype);
-void register_node_type_cmp_bokehblur(struct bNodeTreeType *ttype);
-void register_node_type_cmp_switch(struct bNodeTreeType *ttype);
-void register_node_type_cmp_pixelate(struct bNodeTreeType *ttype);
-void register_node_type_cmp_trackpos(struct bNodeTreeType *ttype);
+void register_node_type_cmp_composite(void);
+void register_node_type_cmp_viewer(void);
+void register_node_type_cmp_splitviewer(void);
+void register_node_type_cmp_output_file(void);
+void register_node_type_cmp_view_levels(void);
+
+void register_node_type_cmp_curve_rgb(void);
+void register_node_type_cmp_mix_rgb(void);
+void register_node_type_cmp_hue_sat(void);
+void register_node_type_cmp_brightcontrast(void);
+void register_node_type_cmp_gamma(void);
+void register_node_type_cmp_invert(void);
+void register_node_type_cmp_alphaover(void);
+void register_node_type_cmp_zcombine(void);
+void register_node_type_cmp_colorbalance(void);
+void register_node_type_cmp_huecorrect(void);
+
+void register_node_type_cmp_normal(void);
+void register_node_type_cmp_curve_vec(void);
+void register_node_type_cmp_map_value(void);
+void register_node_type_cmp_map_range(void);
+void register_node_type_cmp_normalize(void);
+
+void register_node_type_cmp_filter(void);
+void register_node_type_cmp_blur(void);
+void register_node_type_cmp_dblur(void);
+void register_node_type_cmp_bilateralblur(void);
+void register_node_type_cmp_vecblur(void);
+void register_node_type_cmp_dilateerode(void);
+void register_node_type_cmp_inpaint(void);
+void register_node_type_cmp_despeckle(void);
+void register_node_type_cmp_defocus(void);
+
+void register_node_type_cmp_valtorgb(void);
+void register_node_type_cmp_rgbtobw(void);
+void register_node_type_cmp_setalpha(void);
+void register_node_type_cmp_idmask(void);
+void register_node_type_cmp_math(void);
+void register_node_type_cmp_seprgba(void);
+void register_node_type_cmp_combrgba(void);
+void register_node_type_cmp_sephsva(void);
+void register_node_type_cmp_combhsva(void);
+void register_node_type_cmp_sepyuva(void);
+void register_node_type_cmp_combyuva(void);
+void register_node_type_cmp_sepycca(void);
+void register_node_type_cmp_combycca(void);
+void register_node_type_cmp_premulkey(void);
+
+void register_node_type_cmp_diff_matte(void);
+void register_node_type_cmp_distance_matte(void);
+void register_node_type_cmp_chroma_matte(void);
+void register_node_type_cmp_color_matte(void);
+void register_node_type_cmp_channel_matte(void);
+void register_node_type_cmp_color_spill(void);
+void register_node_type_cmp_luma_matte(void);
+void register_node_type_cmp_doubleedgemask(void);
+void register_node_type_cmp_keyingscreen(void);
+void register_node_type_cmp_keying(void);
+
+void register_node_type_cmp_translate(void);
+void register_node_type_cmp_rotate(void);
+void register_node_type_cmp_scale(void);
+void register_node_type_cmp_flip(void);
+void register_node_type_cmp_crop(void);
+void register_node_type_cmp_displace(void);
+void register_node_type_cmp_mapuv(void);
+void register_node_type_cmp_transform(void);
+void register_node_type_cmp_stabilize2d(void);
+void register_node_type_cmp_moviedistortion(void);
+void register_node_type_cmp_mask(void);
+
+void register_node_type_cmp_glare(void);
+void register_node_type_cmp_tonemap(void);
+void register_node_type_cmp_lensdist(void);
+
+
+void register_node_type_cmp_colorcorrection(void);
+void register_node_type_cmp_boxmask(void);
+void register_node_type_cmp_ellipsemask(void);
+void register_node_type_cmp_bokehimage(void);
+void register_node_type_cmp_bokehblur(void);
+void register_node_type_cmp_switch(void);
+void register_node_type_cmp_pixelate(void);
+void register_node_type_cmp_trackpos(void);
#endif
diff --git a/source/blender/nodes/NOD_shader.h b/source/blender/nodes/NOD_shader.h
index 0a7a11e4506..9561fe00409 100644
--- a/source/blender/nodes/NOD_shader.h
+++ b/source/blender/nodes/NOD_shader.h
@@ -34,87 +34,91 @@
#include "BKE_node.h"
-extern struct bNodeTreeType ntreeType_Shader;
+extern struct bNodeTreeType *ntreeType_Shader;
/* the type definitions array */
/* ****************** types array for all shaders ****************** */
-void register_node_type_sh_group(struct bNodeTreeType *ttype);
-
-void register_node_type_sh_output(struct bNodeTreeType *ttype);
-void register_node_type_sh_material(struct bNodeTreeType *ttype);
-void register_node_type_sh_camera(struct bNodeTreeType *ttype);
-void register_node_type_sh_value(struct bNodeTreeType *ttype);
-void register_node_type_sh_rgb(struct bNodeTreeType *ttype);
-void register_node_type_sh_mix_rgb(struct bNodeTreeType *ttype);
-void register_node_type_sh_valtorgb(struct bNodeTreeType *ttype);
-void register_node_type_sh_rgbtobw(struct bNodeTreeType *ttype);
-void register_node_type_sh_texture(struct bNodeTreeType *ttype);
-void register_node_type_sh_normal(struct bNodeTreeType *ttype);
-void register_node_type_sh_gamma(struct bNodeTreeType *ttype);
-void register_node_type_sh_brightcontrast(struct bNodeTreeType *ttype);
-void register_node_type_sh_geom(struct bNodeTreeType *ttype);
-void register_node_type_sh_mapping(struct bNodeTreeType *ttype);
-void register_node_type_sh_curve_vec(struct bNodeTreeType *ttype);
-void register_node_type_sh_curve_rgb(struct bNodeTreeType *ttype);
-void register_node_type_sh_math(struct bNodeTreeType *ttype);
-void register_node_type_sh_vect_math(struct bNodeTreeType *ttype);
-void register_node_type_sh_squeeze(struct bNodeTreeType *ttype);
-void register_node_type_sh_dynamic(struct bNodeTreeType *ttype);
-void register_node_type_sh_material_ext(struct bNodeTreeType *ttype);
-void register_node_type_sh_invert(struct bNodeTreeType *ttype);
-void register_node_type_sh_seprgb(struct bNodeTreeType *ttype);
-void register_node_type_sh_combrgb(struct bNodeTreeType *ttype);
-void register_node_type_sh_hue_sat(struct bNodeTreeType *ttype);
-void register_node_type_sh_tex_brick(struct bNodeTreeType *ttype);
-
-void register_node_type_sh_attribute(struct bNodeTreeType *ttype);
-void register_node_type_sh_geometry(struct bNodeTreeType *ttype);
-void register_node_type_sh_light_path(struct bNodeTreeType *ttype);
-void register_node_type_sh_light_falloff(struct bNodeTreeType *ttype);
-void register_node_type_sh_object_info(struct bNodeTreeType *ttype);
-void register_node_type_sh_fresnel(struct bNodeTreeType *ttype);
-void register_node_type_sh_layer_weight(struct bNodeTreeType *ttype);
-void register_node_type_sh_tex_coord(struct bNodeTreeType *ttype);
-void register_node_type_sh_particle_info(struct bNodeTreeType *ttype);
-void register_node_type_sh_hair_info(struct bNodeTreeType *ttype);
-void register_node_type_sh_script(struct bNodeTreeType *ttype);
-void register_node_type_sh_normal_map(struct bNodeTreeType *ttype);
-void register_node_type_sh_tangent(struct bNodeTreeType *ttype);
-
-void register_node_type_sh_ambient_occlusion(struct bNodeTreeType *ttype);
-void register_node_type_sh_background(struct bNodeTreeType *ttype);
-void register_node_type_sh_bsdf_diffuse(struct bNodeTreeType *ttype);
-void register_node_type_sh_bsdf_glossy(struct bNodeTreeType *ttype);
-void register_node_type_sh_bsdf_glass(struct bNodeTreeType *ttype);
-void register_node_type_sh_bsdf_refraction(struct bNodeTreeType *ttype);
-void register_node_type_sh_bsdf_translucent(struct bNodeTreeType *ttype);
-void register_node_type_sh_bsdf_transparent(struct bNodeTreeType *ttype);
-void register_node_type_sh_bsdf_velvet(struct bNodeTreeType *ttype);
-void register_node_type_sh_bsdf_anisotropic(struct bNodeTreeType *ttype);
-void register_node_type_sh_emission(struct bNodeTreeType *ttype);
-void register_node_type_sh_holdout(struct bNodeTreeType *ttype);
-void register_node_type_sh_volume_transparent(struct bNodeTreeType *ttype);
-void register_node_type_sh_volume_isotropic(struct bNodeTreeType *ttype);
-void register_node_type_sh_mix_shader(struct bNodeTreeType *ttype);
-void register_node_type_sh_add_shader(struct bNodeTreeType *ttype);
-
-void register_node_type_sh_output_lamp(struct bNodeTreeType *ttype);
-void register_node_type_sh_output_material(struct bNodeTreeType *ttype);
-void register_node_type_sh_output_world(struct bNodeTreeType *ttype);
-
-void register_node_type_sh_tex_image(struct bNodeTreeType *ttype);
-void register_node_type_sh_tex_environment(struct bNodeTreeType *ttype);
-void register_node_type_sh_tex_sky(struct bNodeTreeType *ttype);
-void register_node_type_sh_tex_voronoi(struct bNodeTreeType *ttype);
-void register_node_type_sh_tex_gradient(struct bNodeTreeType *ttype);
-void register_node_type_sh_tex_magic(struct bNodeTreeType *ttype);
-void register_node_type_sh_tex_wave(struct bNodeTreeType *ttype);
-void register_node_type_sh_tex_musgrave(struct bNodeTreeType *ttype);
-void register_node_type_sh_tex_noise(struct bNodeTreeType *ttype);
-void register_node_type_sh_tex_checker(struct bNodeTreeType *ttype);
-void register_node_type_sh_bump(struct bNodeTreeType *ttype);
+void register_node_tree_type_sh(void);
+
+void register_node_type_sh_group(void);
+void register_node_type_sh_forloop(void);
+void register_node_type_sh_whileloop(void);
+
+void register_node_type_sh_output(void);
+void register_node_type_sh_material(void);
+void register_node_type_sh_camera(void);
+void register_node_type_sh_value(void);
+void register_node_type_sh_rgb(void);
+void register_node_type_sh_mix_rgb(void);
+void register_node_type_sh_valtorgb(void);
+void register_node_type_sh_rgbtobw(void);
+void register_node_type_sh_texture(void);
+void register_node_type_sh_normal(void);
+void register_node_type_sh_gamma(void);
+void register_node_type_sh_brightcontrast(void);
+void register_node_type_sh_geom(void);
+void register_node_type_sh_mapping(void);
+void register_node_type_sh_curve_vec(void);
+void register_node_type_sh_curve_rgb(void);
+void register_node_type_sh_math(void);
+void register_node_type_sh_vect_math(void);
+void register_node_type_sh_squeeze(void);
+void register_node_type_sh_dynamic(void);
+void register_node_type_sh_material_ext(void);
+void register_node_type_sh_invert(void);
+void register_node_type_sh_seprgb(void);
+void register_node_type_sh_combrgb(void);
+void register_node_type_sh_hue_sat(void);
+void register_node_type_sh_tex_brick(void);
+
+void register_node_type_sh_attribute(void);
+void register_node_type_sh_geometry(void);
+void register_node_type_sh_light_path(void);
+void register_node_type_sh_light_falloff(void);
+void register_node_type_sh_object_info(void);
+void register_node_type_sh_fresnel(void);
+void register_node_type_sh_layer_weight(void);
+void register_node_type_sh_tex_coord(void);
+void register_node_type_sh_particle_info(void);
+void register_node_type_sh_hair_info(void);
+void register_node_type_sh_script(void);
+void register_node_type_sh_normal_map(void);
+void register_node_type_sh_tangent(void);
+
+void register_node_type_sh_ambient_occlusion(void);
+void register_node_type_sh_background(void);
+void register_node_type_sh_bsdf_diffuse(void);
+void register_node_type_sh_bsdf_glossy(void);
+void register_node_type_sh_bsdf_glass(void);
+void register_node_type_sh_bsdf_refraction(void);
+void register_node_type_sh_bsdf_translucent(void);
+void register_node_type_sh_bsdf_transparent(void);
+void register_node_type_sh_bsdf_velvet(void);
+void register_node_type_sh_bsdf_anisotropic(void);
+void register_node_type_sh_emission(void);
+void register_node_type_sh_holdout(void);
+void register_node_type_sh_volume_transparent(void);
+void register_node_type_sh_volume_isotropic(void);
+void register_node_type_sh_mix_shader(void);
+void register_node_type_sh_add_shader(void);
+
+void register_node_type_sh_output_lamp(void);
+void register_node_type_sh_output_material(void);
+void register_node_type_sh_output_world(void);
+
+void register_node_type_sh_tex_image(void);
+void register_node_type_sh_tex_environment(void);
+void register_node_type_sh_tex_sky(void);
+void register_node_type_sh_tex_voronoi(void);
+void register_node_type_sh_tex_gradient(void);
+void register_node_type_sh_tex_magic(void);
+void register_node_type_sh_tex_wave(void);
+void register_node_type_sh_tex_musgrave(void);
+void register_node_type_sh_tex_noise(void);
+void register_node_type_sh_tex_checker(void);
+void register_node_type_sh_bump(void);
#endif
diff --git a/source/blender/nodes/NOD_socket.h b/source/blender/nodes/NOD_socket.h
index b14f7c4e884..5f7da1c3f4d 100644
--- a/source/blender/nodes/NOD_socket.h
+++ b/source/blender/nodes/NOD_socket.h
@@ -45,41 +45,11 @@ struct bNodeTree;
struct bNode;
struct bNodeStack;
-void node_socket_type_init(struct bNodeSocketType *types[]);
-
-void *node_socket_make_default_value(int type);
-void node_socket_free_default_value(int type, void *default_value);
-void node_socket_init_default_value(int type, void *default_value);
-void node_socket_copy_default_value(int type, void *to_default_value, void *from_default_value);
-void node_socket_convert_default_value(int to_type, void *to_default_value, int from_type, void *from_default_value);
-
-void node_socket_set_default_value_int(void *default_value, PropertySubType subtype, int value, int min, int max);
-void node_socket_set_default_value_float(void *default_value, PropertySubType subtype, float value, float min, float max);
-void node_socket_set_default_value_boolean(void *default_value, char value);
-void node_socket_set_default_value_vector(void *default_value, PropertySubType subtype, float x, float y, float z, float min, float max);
-void node_socket_set_default_value_rgba(void *default_value, float r, float g, float b, float a);
-void node_socket_set_default_value_shader(void *default_value);
-void node_socket_set_default_value_mesh(void *default_value);
-void node_socket_set_default_value_string(void *default_value, PropertySubType subtype, const char *value);
-
-struct bNodeSocket *node_add_input_from_template(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocketTemplate *stemp);
-struct bNodeSocket *node_add_output_from_template(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocketTemplate *stemp);
+struct bNodeSocket *node_add_socket_from_template(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocketTemplate *stemp, int in_out);
void node_verify_socket_templates(struct bNodeTree *ntree, struct bNode *node);
-
-/* Socket Converters */
-
-#define SOCK_VECTOR_X 1
-#define SOCK_VECTOR_Y 2
-#define SOCK_VECTOR_Z 3
-
-#define SOCK_RGBA_R 1
-#define SOCK_RGBA_G 2
-#define SOCK_RGBA_B 3
-#define SOCK_RGBA_A 4
-
-#define SOCK_MESH_VERT_CO 1
-#define SOCK_MESH_VERT_NO 2
+void node_socket_init_default_value(struct bNodeSocket *sock);
+void register_standard_node_socket_types(void);
#endif
diff --git a/source/blender/makesrna/intern/rna_nodetree_types.h b/source/blender/nodes/NOD_static_types.h
index b7ec9235483..9d044772274 100644
--- a/source/blender/makesrna/intern/rna_nodetree_types.h
+++ b/source/blender/nodes/NOD_static_types.h
@@ -20,8 +20,8 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file blender/makesrna/intern/rna_nodetree_types.h
- * \ingroup RNA
+/** \file blender/makesrna/intern/NOD_static_types.h
+ * \ingroup nodes
*/
/* intentionally no include guard */
@@ -34,6 +34,12 @@
/* WARNING! If you edit those strings, please do the same in relevant nodes files (under blender/nodes/...)! */
/* Tree type Node ID RNA def function Enum name Struct name UI Name UI Description */
+DefNode( Node, NODE_FRAME, def_frame, "FRAME", Frame, "Frame", "" )
+DefNode( Node, NODE_GROUP, def_group, "GROUP", Group, "Group", "" )
+DefNode( Node, NODE_GROUP_INPUT, def_group_input, "GROUP_INPUT", GroupInput, "Group Input", "" )
+DefNode( Node, NODE_GROUP_OUTPUT, def_group_output, "GROUP_OUTPUT", GroupOutput, "Group Output", "" )
+DefNode( Node, NODE_REROUTE, 0, "REROUTE", Reroute, "Reroute", "" )
+
DefNode( ShaderNode, SH_NODE_OUTPUT, 0, "OUTPUT", Output, "Output", "" )
DefNode( ShaderNode, SH_NODE_MATERIAL, def_sh_material, "MATERIAL", Material, "Material", "" )
DefNode( ShaderNode, SH_NODE_RGB, 0, "RGB", RGB, "RGB", "" )
@@ -186,7 +192,7 @@ DefNode( CompositorNode, CMP_NODE_KEYINGSCREEN, def_cmp_keyingscreen, "KEYIN
DefNode( CompositorNode, CMP_NODE_KEYING, def_cmp_keying, "KEYING", Keying, "Keying", "" )
DefNode( CompositorNode, CMP_NODE_TRACKPOS, def_cmp_trackpos, "TRACKPOS", TrackPos, "Track Position", "" )
DefNode( CompositorNode, CMP_NODE_PIXELATE, 0, "PIXELATE", Pixelate, "Pixelate", "" )
-
+
DefNode( TextureNode, TEX_NODE_OUTPUT, def_tex_output, "OUTPUT", Output, "Output", "" )
DefNode( TextureNode, TEX_NODE_CHECKER, 0, "CHECKER", Checker, "Checker", "" )
DefNode( TextureNode, TEX_NODE_TEXTURE, def_texture, "TEXTURE", Texture, "Texture", "" )
@@ -209,6 +215,18 @@ DefNode( TextureNode, TEX_NODE_COMPOSE, 0, "COMPO
DefNode( TextureNode, TEX_NODE_DECOMPOSE, 0, "DECOMPOSE", Decompose, "Separate RGBA", "" )
DefNode( TextureNode, TEX_NODE_VALTONOR, 0, "VALTONOR", ValToNor, "Value to Normal", "" )
DefNode( TextureNode, TEX_NODE_SCALE, 0, "SCALE", Scale, "Scale", "" )
+DefNode( TextureNode, TEX_NODE_AT, 0, "AT", At, "At", "" )
+/* procedural textures */
+DefNode( TextureNode, TEX_NODE_PROC+TEX_VORONOI, 0, "TEX_VORONOI", TexVoronoi, "Voronoi", "" )
+DefNode( TextureNode, TEX_NODE_PROC+TEX_BLEND, 0, "TEX_BLEND", TexBlend, "Blend", "" )
+DefNode( TextureNode, TEX_NODE_PROC+TEX_MAGIC, 0, "TEX_MAGIC", TexMagic, "Magic", "" )
+DefNode( TextureNode, TEX_NODE_PROC+TEX_MARBLE, 0, "TEX_MARBLE", TexMarble, "Marble", "" )
+DefNode( TextureNode, TEX_NODE_PROC+TEX_CLOUDS, 0, "TEX_CLOUDS", TexClouds, "Clouds", "" )
+DefNode( TextureNode, TEX_NODE_PROC+TEX_WOOD, 0, "TEX_WOOD", TexWood, "Wood", "" )
+DefNode( TextureNode, TEX_NODE_PROC+TEX_MUSGRAVE, 0, "TEX_MUSGRAVE", TexMusgrave, "Musgrave", "" )
+DefNode( TextureNode, TEX_NODE_PROC+TEX_NOISE, 0, "TEX_NOISE", TexNoise, "Noise", "" )
+DefNode( TextureNode, TEX_NODE_PROC+TEX_STUCCI, 0, "TEX_STUCCI", TexStucci, "Stucci", "" )
+DefNode( TextureNode, TEX_NODE_PROC+TEX_DISTNOISE, 0, "TEX_DISTNOISE", TexDistNoise, "Distorted Noise", "" )
/* undefine macros */
diff --git a/source/blender/nodes/NOD_texture.h b/source/blender/nodes/NOD_texture.h
index a1be9963b8a..ea003f23960 100644
--- a/source/blender/nodes/NOD_texture.h
+++ b/source/blender/nodes/NOD_texture.h
@@ -34,48 +34,52 @@
#include "BKE_node.h"
-extern bNodeTreeType ntreeType_Texture;
+extern struct bNodeTreeType *ntreeType_Texture;
/* ****************** types array for all texture nodes ****************** */
-void register_node_type_tex_group(struct bNodeTreeType *ttype);
+void register_node_tree_type_tex(void);
-void register_node_type_tex_math(struct bNodeTreeType *ttype);
-void register_node_type_tex_mix_rgb(struct bNodeTreeType *ttype);
-void register_node_type_tex_valtorgb(struct bNodeTreeType *ttype);
-void register_node_type_tex_valtonor(struct bNodeTreeType *ttype);
-void register_node_type_tex_rgbtobw(struct bNodeTreeType *ttype);
-void register_node_type_tex_output(struct bNodeTreeType *ttype);
-void register_node_type_tex_viewer(struct bNodeTreeType *ttype);
-void register_node_type_tex_checker(struct bNodeTreeType *ttype);
-void register_node_type_tex_texture(struct bNodeTreeType *ttype);
-void register_node_type_tex_bricks(struct bNodeTreeType *ttype);
-void register_node_type_tex_image(struct bNodeTreeType *ttype);
-void register_node_type_tex_curve_rgb(struct bNodeTreeType *ttype);
-void register_node_type_tex_curve_time(struct bNodeTreeType *ttype);
-void register_node_type_tex_invert(struct bNodeTreeType *ttype);
-void register_node_type_tex_hue_sat(struct bNodeTreeType *ttype);
-void register_node_type_tex_coord(struct bNodeTreeType *ttype);
-void register_node_type_tex_distance(struct bNodeTreeType *ttype);
+void register_node_type_tex_group(void);
+void register_node_type_tex_forloop(void);
+void register_node_type_tex_whileloop(void);
-void register_node_type_tex_rotate(struct bNodeTreeType *ttype);
-void register_node_type_tex_translate(struct bNodeTreeType *ttype);
-void register_node_type_tex_scale(struct bNodeTreeType *ttype);
-void register_node_type_tex_at(struct bNodeTreeType *ttype);
+void register_node_type_tex_math(void);
+void register_node_type_tex_mix_rgb(void);
+void register_node_type_tex_valtorgb(void);
+void register_node_type_tex_valtonor(void);
+void register_node_type_tex_rgbtobw(void);
+void register_node_type_tex_output(void);
+void register_node_type_tex_viewer(void);
+void register_node_type_tex_checker(void);
+void register_node_type_tex_texture(void);
+void register_node_type_tex_bricks(void);
+void register_node_type_tex_image(void);
+void register_node_type_tex_curve_rgb(void);
+void register_node_type_tex_curve_time(void);
+void register_node_type_tex_invert(void);
+void register_node_type_tex_hue_sat(void);
+void register_node_type_tex_coord(void);
+void register_node_type_tex_distance(void);
-void register_node_type_tex_compose(struct bNodeTreeType *ttype);
-void register_node_type_tex_decompose(struct bNodeTreeType *ttype);
+void register_node_type_tex_rotate(void);
+void register_node_type_tex_translate(void);
+void register_node_type_tex_scale(void);
+void register_node_type_tex_at(void);
-void register_node_type_tex_proc_voronoi(struct bNodeTreeType *ttype);
-void register_node_type_tex_proc_blend(struct bNodeTreeType *ttype);
-void register_node_type_tex_proc_magic(struct bNodeTreeType *ttype);
-void register_node_type_tex_proc_marble(struct bNodeTreeType *ttype);
-void register_node_type_tex_proc_clouds(struct bNodeTreeType *ttype);
-void register_node_type_tex_proc_wood(struct bNodeTreeType *ttype);
-void register_node_type_tex_proc_musgrave(struct bNodeTreeType *ttype);
-void register_node_type_tex_proc_noise(struct bNodeTreeType *ttype);
-void register_node_type_tex_proc_stucci(struct bNodeTreeType *ttype);
-void register_node_type_tex_proc_distnoise(struct bNodeTreeType *ttype);
+void register_node_type_tex_compose(void);
+void register_node_type_tex_decompose(void);
+
+void register_node_type_tex_proc_voronoi(void);
+void register_node_type_tex_proc_blend(void);
+void register_node_type_tex_proc_magic(void);
+void register_node_type_tex_proc_marble(void);
+void register_node_type_tex_proc_clouds(void);
+void register_node_type_tex_proc_wood(void);
+void register_node_type_tex_proc_musgrave(void);
+void register_node_type_tex_proc_noise(void);
+void register_node_type_tex_proc_stucci(void);
+void register_node_type_tex_proc_distnoise(void);
#endif
diff --git a/source/blender/nodes/composite/node_composite_tree.c b/source/blender/nodes/composite/node_composite_tree.c
index 999bcb9bba5..d10ab9d8d49 100644
--- a/source/blender/nodes/composite/node_composite_tree.c
+++ b/source/blender/nodes/composite/node_composite_tree.c
@@ -44,6 +44,7 @@
#include "BKE_animsys.h"
#include "BKE_colortools.h"
+#include "BKE_context.h"
#include "BKE_fcurve.h"
#include "BKE_global.h"
#include "BKE_main.h"
@@ -64,14 +65,17 @@
#include "COM_compositor.h"
#endif
-static void foreach_nodetree(Main *main, void *calldata, bNodeTreeCallback func)
+static void composite_get_from_context(const bContext *C, bNodeTreeType *UNUSED(treetype), bNodeTree **r_ntree, ID **r_id, ID **r_from)
{
- Scene *sce;
- for (sce= main->scene.first; sce; sce= sce->id.next) {
- if (sce->nodetree) {
- func(calldata, &sce->id, sce->nodetree);
- }
- }
+ Scene *scene = CTX_data_scene(C);
+
+ *r_from = NULL;
+ *r_id = &scene->id;
+ *r_ntree = scene->nodetree;
+
+ /* update output sockets based on available layers */
+ ntreeCompositForceHidden(scene->nodetree, scene);
+
}
static void foreach_nodeclass(Scene *UNUSED(scene), void *calldata, bNodeClassCallback func)
@@ -85,6 +89,7 @@ static void foreach_nodeclass(Scene *UNUSED(scene), void *calldata, bNodeClassCa
func(calldata, NODE_CLASS_MATTE, N_("Matte"));
func(calldata, NODE_CLASS_DISTORT, N_("Distort"));
func(calldata, NODE_CLASS_GROUP, N_("Group"));
+ func(calldata, NODE_CLASS_INTERFACE, N_("Interface"));
func(calldata, NODE_CLASS_LAYOUT, N_("Layout"));
}
@@ -106,22 +111,6 @@ static void free_cache(bNodeTree *ntree)
free_node_cache(ntree, node);
}
-static void update_node(bNodeTree *ntree, bNode *node)
-{
- bNodeSocket *sock;
-
- for (sock= node->outputs.first; sock; sock= sock->next) {
- if (sock->cache) {
- //free_compbuf(sock->cache);
- //sock->cache= NULL;
- }
- }
- node->need_exec= 1;
- /* individual node update call */
- if (node->typeinfo->updatefunc)
- node->typeinfo->updatefunc(ntree, node);
-}
-
/* local tree then owns all compbufs */
static void localize(bNodeTree *localtree, bNodeTree *ntree)
{
@@ -145,16 +134,6 @@ static void localize(bNodeTree *localtree, bNodeTree *ntree)
}
}
- /* copy over the preview buffers to update graduatly */
- if (node->preview) {
- bNodePreview *preview = MEM_callocN(sizeof(bNodePreview), "Preview");
- preview->pad = node->preview->pad;
- preview->xsize = node->preview->xsize;
- preview->ysize = node->preview->ysize;
- preview->rect = MEM_dupallocN(node->preview->rect);
- node->new_node->preview = preview;
- }
-
for (sock= node->outputs.first; sock; sock= sock->next) {
sock->new_sock->cache= sock->cache;
sock->cache= NULL;
@@ -183,24 +162,8 @@ static void localize(bNodeTree *localtree, bNodeTree *ntree)
}
}
-static void local_sync(bNodeTree *localtree, bNodeTree *ntree)
+static void local_sync(bNodeTree *UNUSED(localtree), bNodeTree *UNUSED(ntree))
{
- bNode *lnode;
-
- /* move over the compbufs and previews */
- for (lnode= localtree->nodes.first; lnode; lnode= lnode->next) {
- if ( (lnode->exec & NODE_READY) && !(lnode->exec & NODE_SKIPPED) ) {
- if (ntreeNodeExists(ntree, lnode->new_node)) {
-
- if (lnode->preview && lnode->preview->rect) {
- nodeFreePreview(lnode->new_node);
- lnode->new_node->preview= lnode->preview;
- lnode->preview= NULL;
- }
-
- }
- }
- }
}
static void local_merge(bNodeTree *localtree, bNodeTree *ntree)
@@ -245,27 +208,38 @@ static void update(bNodeTree *ntree)
ntreeSetOutput(ntree);
ntree_update_reroute_nodes(ntree);
+
+ if (ntree->update & NTREE_UPDATE_NODES) {
+ /* clean up preview cache, in case nodes have been removed */
+ BKE_node_preview_remove_unused(ntree);
+ }
}
-bNodeTreeType ntreeType_Composite = {
- /* type */ NTREE_COMPOSIT,
- /* idname */ "NTCompositing Nodetree",
+bNodeTreeType *ntreeType_Composite;
+
+void register_node_tree_type_cmp()
+{
+ bNodeTreeType *tt = ntreeType_Composite = MEM_callocN(sizeof(bNodeTreeType), "compositor node tree type");
- /* node_types */ { NULL, NULL },
+ tt->type = NTREE_COMPOSIT;
+ strcpy(tt->idname, "CompositorNodeTree");
+ strcpy(tt->ui_name, "Compositing");
+ tt->ui_icon = 0; /* defined in drawnode.c */
+ strcpy(tt->ui_description, "");
- /* free_cache */ free_cache,
- /* free_node_cache */ free_node_cache,
- /* foreach_nodetree */ foreach_nodetree,
- /* foreach_nodeclass */ foreach_nodeclass,
- /* localize */ localize,
- /* local_sync */ local_sync,
- /* local_merge */ local_merge,
- /* update */ update,
- /* update_node */ update_node,
- /* validate_link */ NULL,
- /* update_internal_links */ node_update_internal_links_default
-};
-
+ tt->free_cache = free_cache;
+ tt->free_node_cache = free_node_cache;
+ tt->foreach_nodeclass = foreach_nodeclass;
+ tt->localize = localize;
+ tt->local_sync = local_sync;
+ tt->local_merge = local_merge;
+ tt->update = update;
+ tt->get_from_context = composite_get_from_context;
+
+ tt->ext.srna = &RNA_CompositorNodeTree;
+
+ ntreeTypeAdd(tt);
+}
void *COM_linker_hack = NULL;
diff --git a/source/blender/nodes/composite/node_composite_util.c b/source/blender/nodes/composite/node_composite_util.c
new file mode 100644
index 00000000000..b125473d5fa
--- /dev/null
+++ b/source/blender/nodes/composite/node_composite_util.c
@@ -0,0 +1,59 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2006 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/nodes/composite/node_composite_util.c
+ * \ingroup nodes
+ */
+
+#include "node_composite_util.h"
+
+
+int cmp_node_poll_default(bNodeType *UNUSED(ntype), bNodeTree *ntree)
+{
+ return (strcmp(ntree->idname, "CompositorNodeTree")==0);
+}
+
+void cmp_node_update_default(bNodeTree *UNUSED(ntree), bNode *node)
+{
+ bNodeSocket *sock;
+ for(sock= node->outputs.first; sock; sock= sock->next) {
+ if(sock->cache) {
+ //free_compbuf(sock->cache);
+ //sock->cache= NULL;
+ }
+ }
+ node->need_exec= 1;
+}
+
+void cmp_node_type_base(bNodeType *ntype, int type, const char *name, short nclass, short flag)
+{
+ node_type_base(ntype, type, name, nclass, flag);
+
+ ntype->poll = cmp_node_poll_default;
+ ntype->updatefunc = cmp_node_update_default;
+ ntype->update_internal_links = node_update_internal_links_default;
+}
diff --git a/source/blender/nodes/composite/node_composite_util.h b/source/blender/nodes/composite/node_composite_util.h
index a3c4bffe018..3f9cfc03089 100644
--- a/source/blender/nodes/composite/node_composite_util.h
+++ b/source/blender/nodes/composite/node_composite_util.h
@@ -59,4 +59,9 @@
#define CMP_SCALE_MAX 12000
+int cmp_node_poll_default(struct bNodeType *ntype, struct bNodeTree *ntree);
+void cmp_node_update_default(struct bNodeTree *UNUSED(ntree), struct bNode *node);
+void cmp_node_type_base(struct bNodeType *ntype, int type, const char *name, short nclass, short flag);
+
#endif /* __NODE_COMPOSITE_UTIL_H__ */
+
diff --git a/source/blender/nodes/composite/nodes/node_composite_alphaOver.c b/source/blender/nodes/composite/nodes/node_composite_alphaOver.c
index 217670621a8..d7c452e406e 100644
--- a/source/blender/nodes/composite/nodes/node_composite_alphaOver.c
+++ b/source/blender/nodes/composite/nodes/node_composite_alphaOver.c
@@ -43,19 +43,19 @@ static bNodeSocketTemplate cmp_node_alphaover_out[] = {
{ -1, 0, "" }
};
-static void node_alphaover_init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_alphaover_init(bNodeTree *UNUSED(ntree), bNode *node)
{
node->storage= MEM_callocN(sizeof(NodeTwoFloats), "NodeTwoFloats");
}
-void register_node_type_cmp_alphaover(bNodeTreeType *ttype)
+void register_node_type_cmp_alphaover()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_ALPHAOVER, "Alpha Over", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_ALPHAOVER, "Alpha Over", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_alphaover_in, cmp_node_alphaover_out);
node_type_init(&ntype, node_alphaover_init);
node_type_storage(&ntype, "NodeTwoFloats", node_free_standard_storage, node_copy_standard_storage);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_bilateralblur.c b/source/blender/nodes/composite/nodes/node_composite_bilateralblur.c
index b8bf379b14b..bb2f9023866 100644
--- a/source/blender/nodes/composite/nodes/node_composite_bilateralblur.c
+++ b/source/blender/nodes/composite/nodes/node_composite_bilateralblur.c
@@ -43,7 +43,7 @@ static bNodeSocketTemplate cmp_node_bilateralblur_out[] = {
{ -1, 0, "" }
};
-static void node_composit_init_bilateralblur(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_bilateralblur(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeBilateralBlurData *nbbd = MEM_callocN(sizeof(NodeBilateralBlurData), "node bilateral blur data");
node->storage = nbbd;
@@ -51,14 +51,14 @@ static void node_composit_init_bilateralblur(bNodeTree *UNUSED(ntree), bNode *no
nbbd->sigma_space = 5.0;
}
-void register_node_type_cmp_bilateralblur(bNodeTreeType *ttype)
+void register_node_type_cmp_bilateralblur()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_BILATERALBLUR, "Bilateral Blur", NODE_CLASS_OP_FILTER, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_BILATERALBLUR, "Bilateral Blur", NODE_CLASS_OP_FILTER, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_bilateralblur_in, cmp_node_bilateralblur_out);
node_type_init(&ntype, node_composit_init_bilateralblur);
node_type_storage(&ntype, "NodeBilateralBlurData", node_free_standard_storage, node_copy_standard_storage);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_blur.c b/source/blender/nodes/composite/nodes/node_composite_blur.c
index 20fce05a40e..e531f1080cd 100644
--- a/source/blender/nodes/composite/nodes/node_composite_blur.c
+++ b/source/blender/nodes/composite/nodes/node_composite_blur.c
@@ -44,21 +44,21 @@ static bNodeSocketTemplate cmp_node_blur_out[] = {
{ -1, 0, "" }
};
-static void node_composit_init_blur(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_blur(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeBlurData *data = MEM_callocN(sizeof(NodeBlurData), "node blur data");
data->filtertype = R_FILTER_GAUSS;
node->storage = data;
}
-void register_node_type_cmp_blur(bNodeTreeType *ttype)
+void register_node_type_cmp_blur()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_BLUR, "Blur", NODE_CLASS_OP_FILTER, NODE_PREVIEW | NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_BLUR, "Blur", NODE_CLASS_OP_FILTER, NODE_PREVIEW | NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_blur_in, cmp_node_blur_out);
node_type_init(&ntype, node_composit_init_blur);
node_type_storage(&ntype, "NodeBlurData", node_free_standard_storage, node_copy_standard_storage);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_bokehblur.c b/source/blender/nodes/composite/nodes/node_composite_bokehblur.c
index ea3162a9e55..a2d9e6e1473 100644
--- a/source/blender/nodes/composite/nodes/node_composite_bokehblur.c
+++ b/source/blender/nodes/composite/nodes/node_composite_bokehblur.c
@@ -49,19 +49,19 @@ static bNodeSocketTemplate cmp_node_bokehblur_out[] = {
{ -1, 0, "" }
};
-static void node_composit_init_bokehblur(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_bokehblur(bNodeTree *UNUSED(ntree), bNode *node)
{
node->custom3 = 4.0f;
node->custom4 = 16.0f;
}
-void register_node_type_cmp_bokehblur(bNodeTreeType *ttype)
+void register_node_type_cmp_bokehblur(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_BOKEHBLUR, "Bokeh Blur", NODE_CLASS_OP_FILTER, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_BOKEHBLUR, "Bokeh Blur", NODE_CLASS_OP_FILTER, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_bokehblur_in, cmp_node_bokehblur_out);
node_type_init(&ntype, node_composit_init_bokehblur);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_bokehimage.c b/source/blender/nodes/composite/nodes/node_composite_bokehimage.c
index b006280ca8a..c04682c42a6 100644
--- a/source/blender/nodes/composite/nodes/node_composite_bokehimage.c
+++ b/source/blender/nodes/composite/nodes/node_composite_bokehimage.c
@@ -41,7 +41,8 @@ static bNodeSocketTemplate cmp_node_bokehimage_out[] = {
{ SOCK_RGBA, 0, N_("Image"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
{ -1, 0, "" }
};
-static void node_composit_init_bokehimage(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+
+static void node_composit_init_bokehimage(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeBokehImage * data = MEM_callocN(sizeof(NodeBokehImage), "NodeBokehImage");
data->angle = 0.0f;
@@ -52,14 +53,14 @@ static void node_composit_init_bokehimage(bNodeTree *UNUSED(ntree), bNode *node,
node->storage = data;
}
-void register_node_type_cmp_bokehimage(bNodeTreeType *ttype)
+void register_node_type_cmp_bokehimage(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_BOKEHIMAGE, "Bokeh Image", NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_BOKEHIMAGE, "Bokeh Image", NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS);
node_type_socket_templates(&ntype, NULL, cmp_node_bokehimage_out);
node_type_init(&ntype, node_composit_init_bokehimage);
node_type_storage(&ntype, "NodeBokehImage", node_free_standard_storage, node_copy_standard_storage);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_boxmask.c b/source/blender/nodes/composite/nodes/node_composite_boxmask.c
index eb2c58894f3..41820457b4b 100644
--- a/source/blender/nodes/composite/nodes/node_composite_boxmask.c
+++ b/source/blender/nodes/composite/nodes/node_composite_boxmask.c
@@ -44,7 +44,7 @@ static bNodeSocketTemplate cmp_node_boxmask_out[] = {
{ -1, 0, "" }
};
-static void node_composit_init_boxmask(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_boxmask(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeBoxMask *data = MEM_callocN(sizeof(NodeBoxMask), "NodeBoxMask");
data->x = 0.5;
@@ -55,16 +55,16 @@ static void node_composit_init_boxmask(bNodeTree *UNUSED(ntree), bNode *node, bN
node->storage = data;
}
-void register_node_type_cmp_boxmask(bNodeTreeType *ttype)
+void register_node_type_cmp_boxmask(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_MASK_BOX, "Box Mask", NODE_CLASS_MATTE, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_MASK_BOX, "Box Mask", NODE_CLASS_MATTE, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_boxmask_in, cmp_node_boxmask_out);
node_type_init(&ntype, node_composit_init_boxmask);
node_type_storage(&ntype, "NodeBoxMask", node_free_standard_storage, node_copy_standard_storage);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_brightness.c b/source/blender/nodes/composite/nodes/node_composite_brightness.c
index 025f5c03c7c..babb753a98b 100644
--- a/source/blender/nodes/composite/nodes/node_composite_brightness.c
+++ b/source/blender/nodes/composite/nodes/node_composite_brightness.c
@@ -48,12 +48,12 @@ static bNodeSocketTemplate cmp_node_brightcontrast_out[] = {
};
-void register_node_type_cmp_brightcontrast(bNodeTreeType *ttype)
+void register_node_type_cmp_brightcontrast()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_BRIGHTCONTRAST, "Bright/Contrast", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_BRIGHTCONTRAST, "Bright/Contrast", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_brightcontrast_in, cmp_node_brightcontrast_out);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_channelMatte.c b/source/blender/nodes/composite/nodes/node_composite_channelMatte.c
index acb0566be7c..b68bc066b12 100644
--- a/source/blender/nodes/composite/nodes/node_composite_channelMatte.c
+++ b/source/blender/nodes/composite/nodes/node_composite_channelMatte.c
@@ -45,7 +45,7 @@ static bNodeSocketTemplate cmp_node_channel_matte_out[] = {
{-1, 0, ""}
};
-static void node_composit_init_channel_matte(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_channel_matte(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeChroma *c= MEM_callocN(sizeof(NodeChroma), "node chroma");
node->storage=c;
@@ -60,14 +60,14 @@ static void node_composit_init_channel_matte(bNodeTree *UNUSED(ntree), bNode *no
node->custom2= 2; /* Green Channel */
}
-void register_node_type_cmp_channel_matte(bNodeTreeType *ttype)
+void register_node_type_cmp_channel_matte()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_CHANNEL_MATTE, "Channel Key", NODE_CLASS_MATTE, NODE_PREVIEW|NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_CHANNEL_MATTE, "Channel Key", NODE_CLASS_MATTE, NODE_PREVIEW|NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_channel_matte_in, cmp_node_channel_matte_out);
node_type_init(&ntype, node_composit_init_channel_matte);
node_type_storage(&ntype, "NodeChroma", node_free_standard_storage, node_copy_standard_storage);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_chromaMatte.c b/source/blender/nodes/composite/nodes/node_composite_chromaMatte.c
index 29782c3bc51..f119c5ae04f 100644
--- a/source/blender/nodes/composite/nodes/node_composite_chromaMatte.c
+++ b/source/blender/nodes/composite/nodes/node_composite_chromaMatte.c
@@ -45,7 +45,7 @@ static bNodeSocketTemplate cmp_node_chroma_out[] = {
{-1, 0, ""}
};
-static void node_composit_init_chroma_matte(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_chroma_matte(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeChroma *c= MEM_callocN(sizeof(NodeChroma), "node chroma");
node->storage= c;
@@ -56,14 +56,14 @@ static void node_composit_init_chroma_matte(bNodeTree *UNUSED(ntree), bNode *nod
c->fstrength= 1.0f;
}
-void register_node_type_cmp_chroma_matte(bNodeTreeType *ttype)
+void register_node_type_cmp_chroma_matte()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_CHROMA_MATTE, "Chroma Key", NODE_CLASS_MATTE, NODE_PREVIEW|NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_CHROMA_MATTE, "Chroma Key", NODE_CLASS_MATTE, NODE_PREVIEW|NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_chroma_in, cmp_node_chroma_out);
node_type_init(&ntype, node_composit_init_chroma_matte);
node_type_storage(&ntype, "NodeChroma", node_free_standard_storage, node_copy_standard_storage);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_colorMatte.c b/source/blender/nodes/composite/nodes/node_composite_colorMatte.c
index 9905a2446b8..c1ed315adcb 100644
--- a/source/blender/nodes/composite/nodes/node_composite_colorMatte.c
+++ b/source/blender/nodes/composite/nodes/node_composite_colorMatte.c
@@ -45,7 +45,7 @@ static bNodeSocketTemplate cmp_node_color_out[] = {
{-1, 0, ""}
};
-static void node_composit_init_color_matte(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_color_matte(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeChroma *c= MEM_callocN(sizeof(NodeChroma), "node color");
node->storage= c;
@@ -56,14 +56,14 @@ static void node_composit_init_color_matte(bNodeTree *UNUSED(ntree), bNode *node
c->fstrength= 1.0f;
}
-void register_node_type_cmp_color_matte(bNodeTreeType *ttype)
+void register_node_type_cmp_color_matte()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_COLOR_MATTE, "Color Key", NODE_CLASS_MATTE, NODE_PREVIEW|NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_COLOR_MATTE, "Color Key", NODE_CLASS_MATTE, NODE_PREVIEW|NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_color_in, cmp_node_color_out);
node_type_init(&ntype, node_composit_init_color_matte);
node_type_storage(&ntype, "NodeChroma", node_free_standard_storage, node_copy_standard_storage);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_colorSpill.c b/source/blender/nodes/composite/nodes/node_composite_colorSpill.c
index 32fa446790e..848a5280992 100644
--- a/source/blender/nodes/composite/nodes/node_composite_colorSpill.c
+++ b/source/blender/nodes/composite/nodes/node_composite_colorSpill.c
@@ -43,7 +43,7 @@ static bNodeSocketTemplate cmp_node_color_spill_out[] = {
{-1, 0, ""}
};
-static void node_composit_init_color_spill(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_color_spill(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeColorspill *ncs= MEM_callocN(sizeof(NodeColorspill), "node colorspill");
node->storage=ncs;
@@ -54,14 +54,14 @@ static void node_composit_init_color_spill(bNodeTree *UNUSED(ntree), bNode *node
ncs->unspill=0; /* do not use unspill */
}
-void register_node_type_cmp_color_spill(bNodeTreeType *ttype)
+void register_node_type_cmp_color_spill()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_COLOR_SPILL, "Color Spill", NODE_CLASS_MATTE, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_COLOR_SPILL, "Color Spill", NODE_CLASS_MATTE, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_color_spill_in, cmp_node_color_spill_out);
node_type_init(&ntype, node_composit_init_color_spill);
node_type_storage(&ntype, "NodeColorspill", node_free_standard_storage, node_copy_standard_storage);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_colorbalance.c b/source/blender/nodes/composite/nodes/node_composite_colorbalance.c
index da9ce64d994..ebd41441b31 100644
--- a/source/blender/nodes/composite/nodes/node_composite_colorbalance.c
+++ b/source/blender/nodes/composite/nodes/node_composite_colorbalance.c
@@ -46,7 +46,7 @@ static bNodeSocketTemplate cmp_node_colorbalance_out[] = {
{-1, 0, ""}
};
-static void node_composit_init_colorbalance(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_colorbalance(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeColorBalance *n= node->storage= MEM_callocN(sizeof(NodeColorBalance), "node colorbalance");
@@ -55,15 +55,15 @@ static void node_composit_init_colorbalance(bNodeTree *UNUSED(ntree), bNode *nod
n->gain[0] = n->gain[1] = n->gain[2] = 1.0f;
}
-void register_node_type_cmp_colorbalance(bNodeTreeType *ttype)
+void register_node_type_cmp_colorbalance()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_COLORBALANCE, "Color Balance", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_COLORBALANCE, "Color Balance", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_colorbalance_in, cmp_node_colorbalance_out);
node_type_size(&ntype, 400, 200, 400);
node_type_init(&ntype, node_composit_init_colorbalance);
node_type_storage(&ntype, "NodeColorBalance", node_free_standard_storage, node_copy_standard_storage);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_colorcorrection.c b/source/blender/nodes/composite/nodes/node_composite_colorcorrection.c
index 19f2fad2e42..9b09462ed0f 100644
--- a/source/blender/nodes/composite/nodes/node_composite_colorcorrection.c
+++ b/source/blender/nodes/composite/nodes/node_composite_colorcorrection.c
@@ -47,7 +47,7 @@ static bNodeSocketTemplate cmp_node_colorcorrection_out[] = {
{ -1,0,""}
};
-static void node_composit_init_colorcorrection(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_colorcorrection(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeColorCorrection *n= node->storage= MEM_callocN(sizeof(NodeColorCorrection), "node colorcorrection");
n->startmidtones = 0.2f;
@@ -75,15 +75,15 @@ static void node_composit_init_colorcorrection(bNodeTree *UNUSED(ntree), bNode *
node->custom1 = 7; // red + green + blue enabled
}
-void register_node_type_cmp_colorcorrection(bNodeTreeType *ttype)
+void register_node_type_cmp_colorcorrection(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_COLORCORRECTION, "Color Correction", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_COLORCORRECTION, "Color Correction", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_colorcorrection_in, cmp_node_colorcorrection_out);
node_type_size(&ntype, 400, 200, 600);
node_type_init(&ntype, node_composit_init_colorcorrection);
node_type_storage(&ntype, "NodeColorCorrection", node_free_standard_storage, node_copy_standard_storage);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_common.c b/source/blender/nodes/composite/nodes/node_composite_common.c
index 7198798a152..384653e7b41 100644
--- a/source/blender/nodes/composite/nodes/node_composite_common.c
+++ b/source/blender/nodes/composite/nodes/node_composite_common.c
@@ -33,25 +33,35 @@
#include "DNA_node_types.h"
#include "node_composite_util.h"
+#include "NOD_common.h"
#include "node_common.h"
#include "node_exec.h"
#include "BKE_node.h"
-void register_node_type_cmp_group(bNodeTreeType *ttype)
+#include "RNA_access.h"
+
+void register_node_type_cmp_group()
{
static bNodeType ntype;
-
- node_type_base(ttype, &ntype, NODE_GROUP, "Group", NODE_CLASS_GROUP, NODE_OPTIONS | NODE_CONST_OUTPUT);
+
+ /* NB: cannot use sh_node_type_base for node group, because it would map the node type
+ * to the shared NODE_GROUP integer type id.
+ */
+ node_type_base_custom(&ntype, "CompositorNodeGroup", "Group", NODE_CLASS_GROUP, NODE_OPTIONS | NODE_CONST_OUTPUT);
+ ntype.type = NODE_GROUP;
+ ntype.poll = cmp_node_poll_default;
+ ntype.update_internal_links = node_update_internal_links_default;
+ ntype.ext.srna = RNA_struct_find("CompositorNodeGroup");
+ BLI_assert(ntype.ext.srna != NULL);
+ RNA_struct_blender_type_set(ntype.ext.srna, &ntype);
+
node_type_socket_templates(&ntype, NULL, NULL);
node_type_size(&ntype, 120, 60, 200);
node_type_label(&ntype, node_group_label);
- node_type_init(&ntype, node_group_init);
- node_type_valid(&ntype, node_group_valid);
- node_type_template(&ntype, node_group_template);
node_type_update(&ntype, NULL, node_group_verify);
- node_type_group_edit(&ntype, node_group_edit_get, node_group_edit_set, node_group_edit_clear);
+ strcpy(ntype.group_tree_idname, "CompositorNodeTree");
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_composite.c b/source/blender/nodes/composite/nodes/node_composite_composite.c
index ea281a3f556..42e284e0c52 100644
--- a/source/blender/nodes/composite/nodes/node_composite_composite.c
+++ b/source/blender/nodes/composite/nodes/node_composite_composite.c
@@ -39,15 +39,15 @@ static bNodeSocketTemplate cmp_node_composite_in[] = {
{ -1, 0, "" }
};
-void register_node_type_cmp_composite(bNodeTreeType *ttype)
+void register_node_type_cmp_composite()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_COMPOSITE, "Composite", NODE_CLASS_OUTPUT, NODE_OPTIONS | NODE_PREVIEW);
+ cmp_node_type_base(&ntype, CMP_NODE_COMPOSITE, "Composite", NODE_CLASS_OUTPUT, NODE_OPTIONS | NODE_PREVIEW);
node_type_socket_templates(&ntype, cmp_node_composite_in, NULL);
/* Do not allow muting for this node. */
node_type_internal_links(&ntype, NULL);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_crop.c b/source/blender/nodes/composite/nodes/node_composite_crop.c
index 10af55480cd..bae36024b88 100644
--- a/source/blender/nodes/composite/nodes/node_composite_crop.c
+++ b/source/blender/nodes/composite/nodes/node_composite_crop.c
@@ -43,7 +43,7 @@ static bNodeSocketTemplate cmp_node_crop_out[] = {
{ -1, 0, "" }
};
-static void node_composit_init_crop(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_crop(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeTwoXYs *nxy= MEM_callocN(sizeof(NodeTwoXYs), "node xy data");
node->storage= nxy;
@@ -53,14 +53,14 @@ static void node_composit_init_crop(bNodeTree *UNUSED(ntree), bNode *node, bNode
nxy->y2= 0;
}
-void register_node_type_cmp_crop(bNodeTreeType *ttype)
+void register_node_type_cmp_crop()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_CROP, "Crop", NODE_CLASS_DISTORT, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_CROP, "Crop", NODE_CLASS_DISTORT, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_crop_in, cmp_node_crop_out);
node_type_init(&ntype, node_composit_init_crop);
node_type_storage(&ntype, "NodeTwoXYs", node_free_standard_storage, node_copy_standard_storage);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_curves.c b/source/blender/nodes/composite/nodes/node_composite_curves.c
index 9f40159baf3..18999cdc985 100644
--- a/source/blender/nodes/composite/nodes/node_composite_curves.c
+++ b/source/blender/nodes/composite/nodes/node_composite_curves.c
@@ -41,24 +41,24 @@ static bNodeSocketTemplate cmp_node_time_out[] = {
{ -1, 0, "" }
};
-static void node_composit_init_curves_time(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_curves_time(bNodeTree *UNUSED(ntree), bNode *node)
{
node->custom1= 1;
node->custom2= 250;
node->storage= curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
}
-void register_node_type_cmp_curve_time(bNodeTreeType *ttype)
+void register_node_type_cmp_curve_time()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_TIME, "Time", NODE_CLASS_INPUT, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_TIME, "Time", NODE_CLASS_INPUT, NODE_OPTIONS);
node_type_socket_templates(&ntype, NULL, cmp_node_time_out);
node_type_size(&ntype, 140, 100, 320);
node_type_init(&ntype, node_composit_init_curves_time);
node_type_storage(&ntype, "CurveMapping", node_free_curves, node_copy_curves);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
@@ -74,22 +74,22 @@ static bNodeSocketTemplate cmp_node_curve_vec_out[] = {
{ -1, 0, "" }
};
-static void node_composit_init_curve_vec(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_curve_vec(bNodeTree *UNUSED(ntree), bNode *node)
{
node->storage= curvemapping_add(3, -1.0f, -1.0f, 1.0f, 1.0f);
}
-void register_node_type_cmp_curve_vec(bNodeTreeType *ttype)
+void register_node_type_cmp_curve_vec()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_CURVE_VEC, "Vector Curves", NODE_CLASS_OP_VECTOR, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_CURVE_VEC, "Vector Curves", NODE_CLASS_OP_VECTOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_curve_vec_in, cmp_node_curve_vec_out);
node_type_size(&ntype, 200, 140, 320);
node_type_init(&ntype, node_composit_init_curve_vec);
node_type_storage(&ntype, "CurveMapping", node_free_curves, node_copy_curves);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
@@ -107,20 +107,20 @@ static bNodeSocketTemplate cmp_node_curve_rgb_out[] = {
{ -1, 0, "" }
};
-static void node_composit_init_curve_rgb(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_curve_rgb(bNodeTree *UNUSED(ntree), bNode *node)
{
node->storage= curvemapping_add(4, 0.0f, 0.0f, 1.0f, 1.0f);
}
-void register_node_type_cmp_curve_rgb(bNodeTreeType *ttype)
+void register_node_type_cmp_curve_rgb()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_CURVE_RGB, "RGB Curves", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_CURVE_RGB, "RGB Curves", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_curve_rgb_in, cmp_node_curve_rgb_out);
node_type_size(&ntype, 200, 140, 320);
node_type_init(&ntype, node_composit_init_curve_rgb);
node_type_storage(&ntype, "CurveMapping", node_free_curves, node_copy_curves);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_defocus.c b/source/blender/nodes/composite/nodes/node_composite_defocus.c
index c05f1d6fcff..95d9e611584 100644
--- a/source/blender/nodes/composite/nodes/node_composite_defocus.c
+++ b/source/blender/nodes/composite/nodes/node_composite_defocus.c
@@ -44,7 +44,7 @@ static bNodeSocketTemplate cmp_node_defocus_out[] = {
{ -1, 0, "" }
};
-static void node_composit_init_defocus(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_defocus(bNodeTree *UNUSED(ntree), bNode *node)
{
/* qdn: defocus node */
NodeDefocus *nbd = MEM_callocN(sizeof(NodeDefocus), "node defocus data");
@@ -61,14 +61,14 @@ static void node_composit_init_defocus(bNodeTree *UNUSED(ntree), bNode *node, bN
node->storage = nbd;
}
-void register_node_type_cmp_defocus(bNodeTreeType *ttype)
+void register_node_type_cmp_defocus()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_DEFOCUS, "Defocus", NODE_CLASS_OP_FILTER, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_DEFOCUS, "Defocus", NODE_CLASS_OP_FILTER, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_defocus_in, cmp_node_defocus_out);
node_type_init(&ntype, node_composit_init_defocus);
node_type_storage(&ntype, "NodeDefocus", node_free_standard_storage, node_copy_standard_storage);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_despeckle.c b/source/blender/nodes/composite/nodes/node_composite_despeckle.c
index 816a1803e47..9811e2762df 100644
--- a/source/blender/nodes/composite/nodes/node_composite_despeckle.c
+++ b/source/blender/nodes/composite/nodes/node_composite_despeckle.c
@@ -42,19 +42,19 @@ static bNodeSocketTemplate cmp_node_despeckle_out[] = {
{ -1, 0, "" }
};
-static void node_composit_init_despeckle(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_despeckle(bNodeTree *UNUSED(ntree), bNode *node)
{
node->custom3 = 0.5f;
node->custom4 = 0.5f;
}
-void register_node_type_cmp_despeckle(bNodeTreeType *ttype)
+void register_node_type_cmp_despeckle()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_DESPECKLE, "Despeckle", NODE_CLASS_OP_FILTER, NODE_PREVIEW|NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_DESPECKLE, "Despeckle", NODE_CLASS_OP_FILTER, NODE_PREVIEW|NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_despeckle_in, cmp_node_despeckle_out);
node_type_init(&ntype, node_composit_init_despeckle);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_diffMatte.c b/source/blender/nodes/composite/nodes/node_composite_diffMatte.c
index 29712d54e32..1faf1d1e82c 100644
--- a/source/blender/nodes/composite/nodes/node_composite_diffMatte.c
+++ b/source/blender/nodes/composite/nodes/node_composite_diffMatte.c
@@ -45,7 +45,7 @@ static bNodeSocketTemplate cmp_node_diff_matte_out[] = {
{-1, 0, ""}
};
-static void node_composit_init_diff_matte(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_diff_matte(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeChroma *c= MEM_callocN(sizeof(NodeChroma), "node chroma");
node->storage= c;
@@ -53,14 +53,14 @@ static void node_composit_init_diff_matte(bNodeTree *UNUSED(ntree), bNode *node,
c->t2= 0.1f;
}
-void register_node_type_cmp_diff_matte(bNodeTreeType *ttype)
+void register_node_type_cmp_diff_matte()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_DIFF_MATTE, "Difference Key", NODE_CLASS_MATTE, NODE_PREVIEW|NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_DIFF_MATTE, "Difference Key", NODE_CLASS_MATTE, NODE_PREVIEW|NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_diff_matte_in, cmp_node_diff_matte_out);
node_type_init(&ntype, node_composit_init_diff_matte);
node_type_storage(&ntype, "NodeChroma", node_free_standard_storage, node_copy_standard_storage);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_dilate.c b/source/blender/nodes/composite/nodes/node_composite_dilate.c
index fabc54f61b3..d68a8c340d7 100644
--- a/source/blender/nodes/composite/nodes/node_composite_dilate.c
+++ b/source/blender/nodes/composite/nodes/node_composite_dilate.c
@@ -44,22 +44,21 @@ static bNodeSocketTemplate cmp_node_dilateerode_out[] = {
{ -1, 0, "" }
};
-static void node_composit_init_dilateerode(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_dilateerode(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeDilateErode *data = MEM_callocN(sizeof(NodeDilateErode), "NodeDilateErode");
data->falloff = PROP_SMOOTH;
node->storage = data;
}
-void register_node_type_cmp_dilateerode(bNodeTreeType *ttype)
+void register_node_type_cmp_dilateerode()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_DILATEERODE, "Dilate/Erode", NODE_CLASS_OP_FILTER, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_DILATEERODE, "Dilate/Erode", NODE_CLASS_OP_FILTER, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_dilateerode_in, cmp_node_dilateerode_out);
node_type_init(&ntype, node_composit_init_dilateerode);
-
node_type_storage(&ntype, "NodeDilateErode", node_free_standard_storage, node_copy_standard_storage);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_directionalblur.c b/source/blender/nodes/composite/nodes/node_composite_directionalblur.c
index 6197d78563c..3a9c4928175 100644
--- a/source/blender/nodes/composite/nodes/node_composite_directionalblur.c
+++ b/source/blender/nodes/composite/nodes/node_composite_directionalblur.c
@@ -42,7 +42,7 @@ static bNodeSocketTemplate cmp_node_dblur_out[] = {
{ -1, 0, "" }
};
-static void node_composit_init_dblur(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_dblur(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeDBlurData *ndbd = MEM_callocN(sizeof(NodeDBlurData), "node dblur data");
node->storage = ndbd;
@@ -50,14 +50,14 @@ static void node_composit_init_dblur(bNodeTree *UNUSED(ntree), bNode *node, bNod
ndbd->center_y = 0.5;
}
-void register_node_type_cmp_dblur(bNodeTreeType *ttype)
+void register_node_type_cmp_dblur()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_DBLUR, "Directional Blur", NODE_CLASS_OP_FILTER, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_DBLUR, "Directional Blur", NODE_CLASS_OP_FILTER, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_dblur_in, cmp_node_dblur_out);
node_type_init(&ntype, node_composit_init_dblur);
node_type_storage(&ntype, "NodeDBlurData", node_free_standard_storage, node_copy_standard_storage);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_displace.c b/source/blender/nodes/composite/nodes/node_composite_displace.c
index 251345d8a28..2ae7423b31b 100644
--- a/source/blender/nodes/composite/nodes/node_composite_displace.c
+++ b/source/blender/nodes/composite/nodes/node_composite_displace.c
@@ -47,12 +47,12 @@ static bNodeSocketTemplate cmp_node_displace_out[] = {
{ -1, 0, "" }
};
-void register_node_type_cmp_displace(bNodeTreeType *ttype)
+void register_node_type_cmp_displace()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_DISPLACE, "Displace", NODE_CLASS_DISTORT, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_DISPLACE, "Displace", NODE_CLASS_DISTORT, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_displace_in, cmp_node_displace_out);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_distanceMatte.c b/source/blender/nodes/composite/nodes/node_composite_distanceMatte.c
index 26f8055e7f2..1bbe71810c3 100644
--- a/source/blender/nodes/composite/nodes/node_composite_distanceMatte.c
+++ b/source/blender/nodes/composite/nodes/node_composite_distanceMatte.c
@@ -45,7 +45,7 @@ static bNodeSocketTemplate cmp_node_distance_matte_out[] = {
{-1, 0, ""}
};
-static void node_composit_init_distance_matte(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_distance_matte(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeChroma *c= MEM_callocN(sizeof(NodeChroma), "node chroma");
node->storage= c;
@@ -54,14 +54,14 @@ static void node_composit_init_distance_matte(bNodeTree *UNUSED(ntree), bNode *n
c->t2= 0.1f;
}
-void register_node_type_cmp_distance_matte(bNodeTreeType *ttype)
+void register_node_type_cmp_distance_matte()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_DIST_MATTE, "Distance Key", NODE_CLASS_MATTE, NODE_PREVIEW|NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_DIST_MATTE, "Distance Key", NODE_CLASS_MATTE, NODE_PREVIEW|NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_distance_matte_in, cmp_node_distance_matte_out);
node_type_init(&ntype, node_composit_init_distance_matte);
node_type_storage(&ntype, "NodeChroma", node_free_standard_storage, node_copy_standard_storage);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_doubleEdgeMask.c b/source/blender/nodes/composite/nodes/node_composite_doubleEdgeMask.c
index d5dd63a4042..767dfce4d59 100644
--- a/source/blender/nodes/composite/nodes/node_composite_doubleEdgeMask.c
+++ b/source/blender/nodes/composite/nodes/node_composite_doubleEdgeMask.c
@@ -42,12 +42,13 @@ static bNodeSocketTemplate cmp_node_doubleedgemask_out[] = {
{ -1, 0, "" } // output socket array terminator
};
-void register_node_type_cmp_doubleedgemask(bNodeTreeType *ttype)
+void register_node_type_cmp_doubleedgemask()
{
static bNodeType ntype; // allocate a node type data structure
- node_type_base(ttype, &ntype, CMP_NODE_DOUBLEEDGEMASK, "Double Edge Mask", NODE_CLASS_MATTE, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_DOUBLEEDGEMASK, "Double Edge Mask", NODE_CLASS_MATTE, NODE_OPTIONS);
+ node_type_socket_templates(&ntype, cmp_node_doubleedgemask_in, cmp_node_doubleedgemask_out);
node_type_socket_templates(&ntype, cmp_node_doubleedgemask_in, cmp_node_doubleedgemask_out);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_ellipsemask.c b/source/blender/nodes/composite/nodes/node_composite_ellipsemask.c
index c2e34dc07a0..c4a01abc6d1 100644
--- a/source/blender/nodes/composite/nodes/node_composite_ellipsemask.c
+++ b/source/blender/nodes/composite/nodes/node_composite_ellipsemask.c
@@ -44,7 +44,7 @@ static bNodeSocketTemplate cmp_node_ellipsemask_out[] = {
{ -1, 0, "" }
};
-static void node_composit_init_ellipsemask(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_ellipsemask(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeEllipseMask *data = MEM_callocN(sizeof(NodeEllipseMask), "NodeEllipseMask");
data->x = 0.5;
@@ -55,17 +55,17 @@ static void node_composit_init_ellipsemask(bNodeTree *UNUSED(ntree), bNode *node
node->storage = data;
}
-void register_node_type_cmp_ellipsemask(bNodeTreeType *ttype)
+void register_node_type_cmp_ellipsemask(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_MASK_ELLIPSE, "Ellipse Mask", NODE_CLASS_MATTE, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_MASK_ELLIPSE, "Ellipse Mask", NODE_CLASS_MATTE, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_ellipsemask_in, cmp_node_ellipsemask_out);
node_type_size(&ntype, 260, 110, 320);
node_type_init(&ntype, node_composit_init_ellipsemask);
node_type_storage(&ntype, "NodeEllipseMask", node_free_standard_storage, node_copy_standard_storage);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_filter.c b/source/blender/nodes/composite/nodes/node_composite_filter.c
index 3ecc7282632..cdd3e136874 100644
--- a/source/blender/nodes/composite/nodes/node_composite_filter.c
+++ b/source/blender/nodes/composite/nodes/node_composite_filter.c
@@ -43,13 +43,13 @@ static bNodeSocketTemplate cmp_node_filter_out[] = {
{ -1, 0, "" }
};
-void register_node_type_cmp_filter(bNodeTreeType *ttype)
+void register_node_type_cmp_filter()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_FILTER, "Filter", NODE_CLASS_OP_FILTER, NODE_PREVIEW|NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_FILTER, "Filter", NODE_CLASS_OP_FILTER, NODE_PREVIEW|NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_filter_in, cmp_node_filter_out);
node_type_label(&ntype, node_filter_label);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_flip.c b/source/blender/nodes/composite/nodes/node_composite_flip.c
index f56805809c5..0041cdfd44e 100644
--- a/source/blender/nodes/composite/nodes/node_composite_flip.c
+++ b/source/blender/nodes/composite/nodes/node_composite_flip.c
@@ -43,12 +43,12 @@ static bNodeSocketTemplate cmp_node_flip_out[] = {
{ -1, 0, "" }
};
-void register_node_type_cmp_flip(bNodeTreeType *ttype)
+void register_node_type_cmp_flip()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_FLIP, "Flip", NODE_CLASS_DISTORT, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_FLIP, "Flip", NODE_CLASS_DISTORT, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_flip_in, cmp_node_flip_out);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_gamma.c b/source/blender/nodes/composite/nodes/node_composite_gamma.c
index 6da56165979..43eaa26c863 100644
--- a/source/blender/nodes/composite/nodes/node_composite_gamma.c
+++ b/source/blender/nodes/composite/nodes/node_composite_gamma.c
@@ -45,12 +45,12 @@ static bNodeSocketTemplate cmp_node_gamma_out[] = {
{ -1, 0, "" }
};
-void register_node_type_cmp_gamma(bNodeTreeType *ttype)
+void register_node_type_cmp_gamma()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_GAMMA, "Gamma", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_GAMMA, "Gamma", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_gamma_in, cmp_node_gamma_out);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_glare.c b/source/blender/nodes/composite/nodes/node_composite_glare.c
index dde056de807..c2f889a7bf5 100644
--- a/source/blender/nodes/composite/nodes/node_composite_glare.c
+++ b/source/blender/nodes/composite/nodes/node_composite_glare.c
@@ -41,7 +41,7 @@ static bNodeSocketTemplate cmp_node_glare_out[] = {
{ -1, 0, "" }
};
-static void node_composit_init_glare(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_glare(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeGlare *ndg = MEM_callocN(sizeof(NodeGlare), "node glare data");
ndg->quality = 1;
@@ -57,14 +57,14 @@ static void node_composit_init_glare(bNodeTree *UNUSED(ntree), bNode *node, bNod
node->storage = ndg;
}
-void register_node_type_cmp_glare(bNodeTreeType *ttype)
+void register_node_type_cmp_glare()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_GLARE, "Glare", NODE_CLASS_OP_FILTER, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_GLARE, "Glare", NODE_CLASS_OP_FILTER, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_glare_in, cmp_node_glare_out);
node_type_init(&ntype, node_composit_init_glare);
node_type_storage(&ntype, "NodeGlare", node_free_standard_storage, node_copy_standard_storage);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_hueSatVal.c b/source/blender/nodes/composite/nodes/node_composite_hueSatVal.c
index 64ba24e082d..06ba1ba4851 100644
--- a/source/blender/nodes/composite/nodes/node_composite_hueSatVal.c
+++ b/source/blender/nodes/composite/nodes/node_composite_hueSatVal.c
@@ -44,7 +44,7 @@ static bNodeSocketTemplate cmp_node_hue_sat_out[] = {
{ -1, 0, "" }
};
-static void node_composit_init_hue_sat(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_hue_sat(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeHueSat *nhs= MEM_callocN(sizeof(NodeHueSat), "node hue sat");
node->storage= nhs;
@@ -53,14 +53,14 @@ static void node_composit_init_hue_sat(bNodeTree *UNUSED(ntree), bNode *node, bN
nhs->val= 1.0f;
}
-void register_node_type_cmp_hue_sat(bNodeTreeType *ttype)
+void register_node_type_cmp_hue_sat()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_HUE_SAT, "Hue Saturation Value", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_HUE_SAT, "Hue Saturation Value", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_hue_sat_in, cmp_node_hue_sat_out);
node_type_init(&ntype, node_composit_init_hue_sat);
node_type_storage(&ntype, "NodeHueSat", node_free_standard_storage, node_copy_standard_storage);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_huecorrect.c b/source/blender/nodes/composite/nodes/node_composite_huecorrect.c
index 738f2f511f7..3ec4a9c9a4a 100644
--- a/source/blender/nodes/composite/nodes/node_composite_huecorrect.c
+++ b/source/blender/nodes/composite/nodes/node_composite_huecorrect.c
@@ -43,7 +43,7 @@ static bNodeSocketTemplate cmp_node_huecorrect_out[] = {
{ -1, 0, "" }
};
-static void node_composit_init_huecorrect(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_huecorrect(bNodeTree *UNUSED(ntree), bNode *node)
{
CurveMapping *cumapping = node->storage= curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
int c;
@@ -59,15 +59,15 @@ static void node_composit_init_huecorrect(bNodeTree *UNUSED(ntree), bNode *node,
cumapping->cur = 1;
}
-void register_node_type_cmp_huecorrect(bNodeTreeType *ttype)
+void register_node_type_cmp_huecorrect()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_HUECORRECT, "Hue Correct", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_HUECORRECT, "Hue Correct", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_huecorrect_in, cmp_node_huecorrect_out);
node_type_size(&ntype, 320, 140, 500);
node_type_init(&ntype, node_composit_init_huecorrect);
node_type_storage(&ntype, "CurveMapping", node_free_curves, node_copy_curves);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_idMask.c b/source/blender/nodes/composite/nodes/node_composite_idMask.c
index 89ef4ad3d01..2d4fcc76462 100644
--- a/source/blender/nodes/composite/nodes/node_composite_idMask.c
+++ b/source/blender/nodes/composite/nodes/node_composite_idMask.c
@@ -44,12 +44,12 @@ static bNodeSocketTemplate cmp_node_idmask_out[] = {
{ -1, 0, "" }
};
-void register_node_type_cmp_idmask(bNodeTreeType *ttype)
+void register_node_type_cmp_idmask()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_ID_MASK, "ID Mask", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_ID_MASK, "ID Mask", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_idmask_in, cmp_node_idmask_out);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_image.c b/source/blender/nodes/composite/nodes/node_composite_image.c
index 563ad2b74b2..f9f289297d7 100644
--- a/source/blender/nodes/composite/nodes/node_composite_image.c
+++ b/source/blender/nodes/composite/nodes/node_composite_image.c
@@ -70,7 +70,7 @@ static bNodeSocket *cmp_node_image_add_render_pass_output(bNodeTree *ntree, bNod
bNodeSocket *sock;
NodeImageLayer *sockdata;
- sock = node_add_output_from_template(ntree, node, &cmp_node_rlayers_out[rres_index]);
+ sock = node_add_socket_from_template(ntree, node, &cmp_node_rlayers_out[rres_index], SOCK_OUT);
/* extra socket info */
sockdata = MEM_callocN(sizeof(NodeImageLayer), "node image layer");
sock->storage = sockdata;
@@ -157,7 +157,7 @@ static void cmp_node_image_add_multilayer_outputs(bNodeTree *ntree, bNode *node,
else
type = SOCK_RGBA;
- sock = nodeAddSocket(ntree, node, SOCK_OUT, rpass->name, type);
+ sock = nodeAddStaticSocket(ntree, node, SOCK_OUT, type, PROP_NONE, rpass->name, rpass->name);
/* extra socket info */
sockdata = MEM_callocN(sizeof(NodeImageLayer), "node image layer");
sock->storage = sockdata;
@@ -240,9 +240,6 @@ static void cmp_node_image_verify_outputs(bNodeTree *ntree, bNode *node)
/* XXX make callback */
cmp_node_image_create_outputs(ntree, node);
- /* flag all new sockets as dynamic, to prevent removal by socket verification function */
- for (newsock=node->outputs.first; newsock; newsock=newsock->next)
- newsock->flag |= SOCK_DYNAMIC;
for (newsock=node->outputs.first; newsock; newsock=newsock->next) {
/* XXX make callback */
@@ -284,7 +281,7 @@ static void cmp_node_image_update(bNodeTree *ntree, bNode *node)
cmp_node_image_verify_outputs(ntree, node);
}
-static void node_composit_init_image(bNodeTree *ntree, bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_image(bNodeTree *ntree, bNode *node)
{
ImageUser *iuser= MEM_callocN(sizeof(ImageUser), "node image user");
node->storage= iuser;
@@ -308,38 +305,48 @@ static void node_composit_free_image(bNode *node)
MEM_freeN(node->storage);
}
-static void node_composit_copy_image(bNode *orig_node, bNode *new_node)
+static void node_composit_copy_image(bNodeTree *UNUSED(dest_ntree), bNode *dest_node, bNode *src_node)
{
bNodeSocket *sock;
- new_node->storage= MEM_dupallocN(orig_node->storage);
+ dest_node->storage= MEM_dupallocN(src_node->storage);
/* copy extra socket info */
- for (sock=orig_node->outputs.first; sock; sock=sock->next)
+ for (sock=src_node->outputs.first; sock; sock=sock->next)
sock->new_sock->storage = MEM_dupallocN(sock->storage);
}
-void register_node_type_cmp_image(bNodeTreeType *ttype)
+void register_node_type_cmp_image()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_IMAGE, "Image", NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_IMAGE, "Image", NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS);
node_type_init(&ntype, node_composit_init_image);
node_type_storage(&ntype, "ImageUser", node_composit_free_image, node_composit_copy_image);
node_type_update(&ntype, cmp_node_image_update, NULL);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
/* **************** RENDER RESULT ******************** */
-void register_node_type_cmp_rlayers(bNodeTreeType *ttype)
+static int node_composit_poll_rlayers(bNodeType *UNUSED(ntype), bNodeTree *ntree)
+{
+ PointerRNA ptr;
+
+ /* render layers node can only be used in local scene->nodetree, since it directly links to the scene */
+ RNA_id_pointer_create((ID *)ntree, &ptr);
+ return (strcmp(ntree->idname, "CompositorNodeTree")==0 && RNA_boolean_get(&ptr, "is_local_tree"));
+}
+
+void register_node_type_cmp_rlayers()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_R_LAYERS, "Render Layers", NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_R_LAYERS, "Render Layers", NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS);
node_type_socket_templates(&ntype, NULL, cmp_node_rlayers_out);
+ ntype.poll = node_composit_poll_rlayers;
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_inpaint.c b/source/blender/nodes/composite/nodes/node_composite_inpaint.c
index 4844b35fb62..83517d07b69 100644
--- a/source/blender/nodes/composite/nodes/node_composite_inpaint.c
+++ b/source/blender/nodes/composite/nodes/node_composite_inpaint.c
@@ -44,12 +44,12 @@ static bNodeSocketTemplate cmp_node_inpaint_out[] = {
{ -1, 0, "" }
};
-void register_node_type_cmp_inpaint(bNodeTreeType *ttype)
+void register_node_type_cmp_inpaint(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_INPAINT, "Inpaint", NODE_CLASS_OP_FILTER, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_INPAINT, "Inpaint", NODE_CLASS_OP_FILTER, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_inpaint_in, cmp_node_inpaint_out);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_invert.c b/source/blender/nodes/composite/nodes/node_composite_invert.c
index 0bfbe42868b..9765c3c8764 100644
--- a/source/blender/nodes/composite/nodes/node_composite_invert.c
+++ b/source/blender/nodes/composite/nodes/node_composite_invert.c
@@ -43,19 +43,19 @@ static bNodeSocketTemplate cmp_node_invert_out[] = {
{ -1, 0, "" }
};
-static void node_composit_init_invert(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_invert(bNodeTree *UNUSED(ntree), bNode *node)
{
node->custom1 |= CMP_CHAN_RGB;
}
/* custom1 = mix type */
-void register_node_type_cmp_invert(bNodeTreeType *ttype)
+void register_node_type_cmp_invert()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_INVERT, "Invert", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_INVERT, "Invert", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_invert_in, cmp_node_invert_out);
node_type_init(&ntype, node_composit_init_invert);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_keying.c b/source/blender/nodes/composite/nodes/node_composite_keying.c
index 51e0e9a8e39..464df4d72ab 100644
--- a/source/blender/nodes/composite/nodes/node_composite_keying.c
+++ b/source/blender/nodes/composite/nodes/node_composite_keying.c
@@ -60,7 +60,7 @@ static bNodeSocketTemplate cmp_node_keying_out[] = {
{ -1, 0, "" }
};
-static void node_composit_init_keying(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_keying(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeKeyingData *data;
@@ -78,14 +78,14 @@ static void node_composit_init_keying(bNodeTree *UNUSED(ntree), bNode *node, bNo
node->storage = data;
}
-void register_node_type_cmp_keying(bNodeTreeType *ttype)
+void register_node_type_cmp_keying(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_KEYING, "Keying", NODE_CLASS_MATTE, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_KEYING, "Keying", NODE_CLASS_MATTE, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_keying_in, cmp_node_keying_out);
node_type_init(&ntype, node_composit_init_keying);
node_type_storage(&ntype, "NodeKeyingData", node_free_standard_storage, node_copy_standard_storage);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_keyingscreen.c b/source/blender/nodes/composite/nodes/node_composite_keyingscreen.c
index 1974087e8e7..b593196d815 100644
--- a/source/blender/nodes/composite/nodes/node_composite_keyingscreen.c
+++ b/source/blender/nodes/composite/nodes/node_composite_keyingscreen.c
@@ -50,7 +50,7 @@ static bNodeSocketTemplate cmp_node_keyingscreen_out[] = {
{ -1, 0, "" }
};
-static void node_composit_init_keyingscreen(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_keyingscreen(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeKeyingScreenData *data;
@@ -59,14 +59,14 @@ static void node_composit_init_keyingscreen(bNodeTree *UNUSED(ntree), bNode *nod
node->storage = data;
}
-void register_node_type_cmp_keyingscreen(bNodeTreeType *ttype)
+void register_node_type_cmp_keyingscreen(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_KEYINGSCREEN, "Keying Screen", NODE_CLASS_MATTE, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_KEYINGSCREEN, "Keying Screen", NODE_CLASS_MATTE, NODE_OPTIONS);
node_type_socket_templates(&ntype, NULL, cmp_node_keyingscreen_out);
node_type_init(&ntype, node_composit_init_keyingscreen);
node_type_storage(&ntype, "NodeKeyingScreenData", node_free_standard_storage, node_copy_standard_storage);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_lensdist.c b/source/blender/nodes/composite/nodes/node_composite_lensdist.c
index 15d10e07946..78eeccbe4b1 100644
--- a/source/blender/nodes/composite/nodes/node_composite_lensdist.c
+++ b/source/blender/nodes/composite/nodes/node_composite_lensdist.c
@@ -43,7 +43,7 @@ static bNodeSocketTemplate cmp_node_lensdist_out[] = {
{ -1, 0, "" }
};
-static void node_composit_init_lensdist(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_lensdist(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeLensDist *nld = MEM_callocN(sizeof(NodeLensDist), "node lensdist data");
nld->jit = nld->proj = nld->fit = 0;
@@ -51,14 +51,14 @@ static void node_composit_init_lensdist(bNodeTree *UNUSED(ntree), bNode *node, b
}
-void register_node_type_cmp_lensdist(bNodeTreeType *ttype)
+void register_node_type_cmp_lensdist()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_LENSDIST, "Lens Distortion", NODE_CLASS_DISTORT, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_LENSDIST, "Lens Distortion", NODE_CLASS_DISTORT, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_lensdist_in, cmp_node_lensdist_out);
node_type_init(&ntype, node_composit_init_lensdist);
node_type_storage(&ntype, "NodeLensDist", node_free_standard_storage, node_copy_standard_storage);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_levels.c b/source/blender/nodes/composite/nodes/node_composite_levels.c
index f50a8838d74..2d24dfadbd3 100644
--- a/source/blender/nodes/composite/nodes/node_composite_levels.c
+++ b/source/blender/nodes/composite/nodes/node_composite_levels.c
@@ -45,19 +45,19 @@ static bNodeSocketTemplate cmp_node_view_levels_out[] = {
{-1, 0, ""}
};
-static void node_composit_init_view_levels(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_view_levels(bNodeTree *UNUSED(ntree), bNode *node)
{
node->custom1=1; /*All channels*/
}
-void register_node_type_cmp_view_levels(bNodeTreeType *ttype)
+void register_node_type_cmp_view_levels()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_VIEW_LEVELS, "Levels", NODE_CLASS_OUTPUT, NODE_OPTIONS|NODE_PREVIEW);
+ cmp_node_type_base(&ntype, CMP_NODE_VIEW_LEVELS, "Levels", NODE_CLASS_OUTPUT, NODE_OPTIONS|NODE_PREVIEW);
node_type_socket_templates(&ntype, cmp_node_view_levels_in, cmp_node_view_levels_out);
node_type_init(&ntype, node_composit_init_view_levels);
node_type_storage(&ntype, "ImageUser", NULL, NULL);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_lummaMatte.c b/source/blender/nodes/composite/nodes/node_composite_lummaMatte.c
index 60a7f3014de..2155db9ae20 100644
--- a/source/blender/nodes/composite/nodes/node_composite_lummaMatte.c
+++ b/source/blender/nodes/composite/nodes/node_composite_lummaMatte.c
@@ -45,7 +45,7 @@ static bNodeSocketTemplate cmp_node_luma_matte_out[] = {
{-1, 0, ""}
};
-static void node_composit_init_luma_matte(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_luma_matte(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeChroma *c= MEM_callocN(sizeof(NodeChroma), "node chroma");
node->storage=c;
@@ -53,14 +53,14 @@ static void node_composit_init_luma_matte(bNodeTree *UNUSED(ntree), bNode *node,
c->t2= 0.0f;
}
-void register_node_type_cmp_luma_matte(bNodeTreeType *ttype)
+void register_node_type_cmp_luma_matte()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_LUMA_MATTE, "Luminance Key", NODE_CLASS_MATTE, NODE_PREVIEW|NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_LUMA_MATTE, "Luminance Key", NODE_CLASS_MATTE, NODE_PREVIEW|NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_luma_matte_in, cmp_node_luma_matte_out);
node_type_init(&ntype, node_composit_init_luma_matte);
node_type_storage(&ntype, "NodeChroma", node_free_standard_storage, node_copy_standard_storage);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_mapRange.c b/source/blender/nodes/composite/nodes/node_composite_mapRange.c
index 07f34e79bd1..43d359db0a5 100644
--- a/source/blender/nodes/composite/nodes/node_composite_mapRange.c
+++ b/source/blender/nodes/composite/nodes/node_composite_mapRange.c
@@ -46,12 +46,12 @@ static bNodeSocketTemplate cmp_node_map_range_out[] = {
{ -1, 0, "" }
};
-void register_node_type_cmp_map_range(bNodeTreeType *ttype)
+void register_node_type_cmp_map_range()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_MAP_RANGE, "Map Range", NODE_CLASS_OP_VECTOR, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_MAP_RANGE, "Map Range", NODE_CLASS_OP_VECTOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_map_range_in, cmp_node_map_range_out);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_mapUV.c b/source/blender/nodes/composite/nodes/node_composite_mapUV.c
index fa4c8d7022c..eca8dea0470 100644
--- a/source/blender/nodes/composite/nodes/node_composite_mapUV.c
+++ b/source/blender/nodes/composite/nodes/node_composite_mapUV.c
@@ -44,12 +44,12 @@ static bNodeSocketTemplate cmp_node_mapuv_out[] = {
{ -1, 0, "" }
};
-void register_node_type_cmp_mapuv(bNodeTreeType *ttype)
+void register_node_type_cmp_mapuv()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_MAP_UV, "Map UV", NODE_CLASS_DISTORT, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_MAP_UV, "Map UV", NODE_CLASS_DISTORT, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_mapuv_in, cmp_node_mapuv_out);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_mapValue.c b/source/blender/nodes/composite/nodes/node_composite_mapValue.c
index 046eeaf4fc8..e12c7e2d2c7 100644
--- a/source/blender/nodes/composite/nodes/node_composite_mapValue.c
+++ b/source/blender/nodes/composite/nodes/node_composite_mapValue.c
@@ -42,19 +42,19 @@ static bNodeSocketTemplate cmp_node_map_value_out[] = {
{ -1, 0, "" }
};
-static void node_composit_init_map_value(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_map_value(bNodeTree *UNUSED(ntree), bNode *node)
{
node->storage= add_tex_mapping();
}
-void register_node_type_cmp_map_value(bNodeTreeType *ttype)
+void register_node_type_cmp_map_value()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_MAP_VALUE, "Map Value", NODE_CLASS_OP_VECTOR, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_MAP_VALUE, "Map Value", NODE_CLASS_OP_VECTOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_map_value_in, cmp_node_map_value_out);
node_type_init(&ntype, node_composit_init_map_value);
node_type_storage(&ntype, "TexMapping", node_free_standard_storage, node_copy_standard_storage);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_mask.c b/source/blender/nodes/composite/nodes/node_composite_mask.c
index 27534698422..f97e83f177a 100644
--- a/source/blender/nodes/composite/nodes/node_composite_mask.c
+++ b/source/blender/nodes/composite/nodes/node_composite_mask.c
@@ -45,7 +45,7 @@ static bNodeSocketTemplate cmp_node_mask_out[] = {
{ -1, 0, "" }
};
-static void node_composit_init_mask(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_mask(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeMask *data = MEM_callocN(sizeof(NodeMask), "NodeMask");
data->size_x = data->size_y = 256;
@@ -55,15 +55,15 @@ static void node_composit_init_mask(bNodeTree *UNUSED(ntree), bNode *node, bNode
node->custom3 = 0.5f; /* shutter */
}
-void register_node_type_cmp_mask(bNodeTreeType *ttype)
+void register_node_type_cmp_mask(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_MASK, "Mask", NODE_CLASS_INPUT, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_MASK, "Mask", NODE_CLASS_INPUT, NODE_OPTIONS);
node_type_socket_templates(&ntype, NULL, cmp_node_mask_out);
node_type_init(&ntype, node_composit_init_mask);
node_type_storage(&ntype, "NodeMask", node_free_standard_storage, node_copy_standard_storage);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_math.c b/source/blender/nodes/composite/nodes/node_composite_math.c
index 5f5369ce03a..90c0d6ce30a 100644
--- a/source/blender/nodes/composite/nodes/node_composite_math.c
+++ b/source/blender/nodes/composite/nodes/node_composite_math.c
@@ -45,13 +45,13 @@ static bNodeSocketTemplate cmp_node_math_out[] = {
};
-void register_node_type_cmp_math(bNodeTreeType *ttype)
+void register_node_type_cmp_math()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_MATH, "Math", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_MATH, "Math", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_math_in, cmp_node_math_out);
node_type_label(&ntype, node_math_label);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_mixrgb.c b/source/blender/nodes/composite/nodes/node_composite_mixrgb.c
index 23e4fc90457..0a6559d4f2f 100644
--- a/source/blender/nodes/composite/nodes/node_composite_mixrgb.c
+++ b/source/blender/nodes/composite/nodes/node_composite_mixrgb.c
@@ -44,13 +44,13 @@ static bNodeSocketTemplate cmp_node_mix_rgb_out[] = {
};
/* custom1 = mix type */
-void register_node_type_cmp_mix_rgb(bNodeTreeType *ttype)
+void register_node_type_cmp_mix_rgb()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_MIX_RGB, "Mix", NODE_CLASS_OP_COLOR, NODE_PREVIEW|NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_MIX_RGB, "Mix", NODE_CLASS_OP_COLOR, NODE_PREVIEW|NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_mix_rgb_in, cmp_node_mix_rgb_out);
node_type_label(&ntype, node_blend_label);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_movieclip.c b/source/blender/nodes/composite/nodes/node_composite_movieclip.c
index 39d46e053bf..ae6f02452b4 100644
--- a/source/blender/nodes/composite/nodes/node_composite_movieclip.c
+++ b/source/blender/nodes/composite/nodes/node_composite_movieclip.c
@@ -42,7 +42,7 @@ static bNodeSocketTemplate cmp_node_movieclip_out[] = {
{ -1, 0, "" }
};
-static void init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void init(bNodeTree *UNUSED(ntree), bNode *node)
{
MovieClipUser *user = MEM_callocN(sizeof(MovieClipUser), "node movie clip user");
@@ -50,14 +50,14 @@ static void init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(nt
user->framenr = 1;
}
-void register_node_type_cmp_movieclip(bNodeTreeType *ttype)
+void register_node_type_cmp_movieclip()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_MOVIECLIP, "Movie Clip", NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_MOVIECLIP, "Movie Clip", NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS);
node_type_socket_templates(&ntype, NULL, cmp_node_movieclip_out);
node_type_init(&ntype, init);
node_type_storage(&ntype, "MovieClipUser", node_free_standard_storage, node_copy_standard_storage);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_moviedistortion.c b/source/blender/nodes/composite/nodes/node_composite_moviedistortion.c
index 198ffbb2857..b8770d1670e 100644
--- a/source/blender/nodes/composite/nodes/node_composite_moviedistortion.c
+++ b/source/blender/nodes/composite/nodes/node_composite_moviedistortion.c
@@ -60,21 +60,21 @@ static void storage_free(bNode *node)
node->storage = NULL;
}
-static void storage_copy(bNode *orig_node, bNode *new_node)
+static void storage_copy(bNodeTree *UNUSED(dest_ntree), bNode *dest_node, bNode *src_node)
{
- if (orig_node->storage)
- new_node->storage = BKE_tracking_distortion_copy(orig_node->storage);
+ if (src_node->storage)
+ dest_node->storage = BKE_tracking_distortion_copy(src_node->storage);
}
-void register_node_type_cmp_moviedistortion(bNodeTreeType *ttype)
+void register_node_type_cmp_moviedistortion()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_MOVIEDISTORTION, "Movie Distortion", NODE_CLASS_DISTORT, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_MOVIEDISTORTION, "Movie Distortion", NODE_CLASS_DISTORT, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_moviedistortion_in, cmp_node_moviedistortion_out);
node_type_label(&ntype, label);
node_type_storage(&ntype, NULL, storage_free, storage_copy);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_normal.c b/source/blender/nodes/composite/nodes/node_composite_normal.c
index 88db5d36810..7a6d2fcd8e8 100644
--- a/source/blender/nodes/composite/nodes/node_composite_normal.c
+++ b/source/blender/nodes/composite/nodes/node_composite_normal.c
@@ -32,7 +32,6 @@
#include "node_composite_util.h"
-
/* **************** NORMAL ******************** */
static bNodeSocketTemplate cmp_node_normal_in[] = {
{ SOCK_VECTOR, 1, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_DIRECTION},
@@ -40,28 +39,17 @@ static bNodeSocketTemplate cmp_node_normal_in[] = {
};
static bNodeSocketTemplate cmp_node_normal_out[] = {
- { SOCK_VECTOR, 0, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_DIRECTION},
+ { SOCK_VECTOR, 0, N_("Normal"), 0.0f, 0.0f, 1.0f, 0.0f, -1.0f, 1.0f, PROP_DIRECTION},
{ SOCK_FLOAT, 0, N_("Dot")},
{ -1, 0, "" }
};
-static void init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
-{
- bNodeSocket *sock= node->outputs.first;
- float *nor= ((bNodeSocketValueVector*)sock->default_value)->value;
-
- nor[0] = 0.0f;
- nor[1] = 0.0f;
- nor[2] = 1.0f;
-}
-
-void register_node_type_cmp_normal(bNodeTreeType *ttype)
+void register_node_type_cmp_normal()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_NORMAL, "Normal", NODE_CLASS_OP_VECTOR, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_NORMAL, "Normal", NODE_CLASS_OP_VECTOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_normal_in, cmp_node_normal_out);
- node_type_init(&ntype, init);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_normalize.c b/source/blender/nodes/composite/nodes/node_composite_normalize.c
index db811666900..2f19c6bc523 100644
--- a/source/blender/nodes/composite/nodes/node_composite_normalize.c
+++ b/source/blender/nodes/composite/nodes/node_composite_normalize.c
@@ -43,12 +43,12 @@ static bNodeSocketTemplate cmp_node_normalize_out[] = {
{ -1, 0, "" }
};
-void register_node_type_cmp_normalize(bNodeTreeType *ttype)
+void register_node_type_cmp_normalize()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_NORMALIZE, "Normalize", NODE_CLASS_OP_VECTOR, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_NORMALIZE, "Normalize", NODE_CLASS_OP_VECTOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_normalize_in, cmp_node_normalize_out);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_outputFile.c b/source/blender/nodes/composite/nodes/node_composite_outputFile.c
index d9a146ddaad..e008e17cbb0 100644
--- a/source/blender/nodes/composite/nodes/node_composite_outputFile.c
+++ b/source/blender/nodes/composite/nodes/node_composite_outputFile.c
@@ -34,6 +34,10 @@
#include "BLI_utildefines.h"
#include "BLI_path_util.h"
+#include "BKE_context.h"
+
+#include "RNA_access.h"
+
#include "node_composite_util.h"
#include "IMB_imbuf.h"
@@ -105,7 +109,7 @@ void ntreeCompositOutputFileUniqueLayer(ListBase *list, bNodeSocket *sock, const
bNodeSocket *ntreeCompositOutputFileAddSocket(bNodeTree *ntree, bNode *node, const char *name, ImageFormatData *im_format)
{
NodeImageMultiFile *nimf = node->storage;
- bNodeSocket *sock = nodeAddSocket(ntree, node, SOCK_IN, "", SOCK_RGBA);
+ bNodeSocket *sock = nodeAddStaticSocket(ntree, node, SOCK_IN, SOCK_RGBA, PROP_NONE, NULL, name);
/* create format data for the input socket */
NodeImageMultiFileSocket *sockdata = MEM_callocN(sizeof(NodeImageMultiFileSocket), "socket image format");
@@ -165,14 +169,19 @@ void ntreeCompositOutputFileSetLayer(bNode *node, bNodeSocket *sock, const char
ntreeCompositOutputFileUniqueLayer(&node->inputs, sock, name, '_');
}
-static void init_output_file(bNodeTree *ntree, bNode *node, bNodeTemplate *ntemp)
+/* XXX uses initfunc_api callback, regular initfunc does not support context yet */
+static void init_output_file(const bContext *C, PointerRNA *ptr)
{
+ Scene *scene = CTX_data_scene(C);
+ bNodeTree *ntree = ptr->id.data;
+ bNode *node = ptr->data;
NodeImageMultiFile *nimf= MEM_callocN(sizeof(NodeImageMultiFile), "node image multi file");
ImageFormatData *format = NULL;
node->storage= nimf;
+
+ if (scene) {
+ RenderData *rd = &scene->r;
- if (ntemp->scene) {
- RenderData *rd = &ntemp->scene->r;
BLI_strncpy(nimf->base_path, rd->pic, sizeof(nimf->base_path));
nimf->format = rd->im_format;
if (BKE_imtype_is_movie(nimf->format.imtype)) {
@@ -200,41 +209,43 @@ static void free_output_file(bNode *node)
MEM_freeN(node->storage);
}
-static void copy_output_file(struct bNode *node, struct bNode *target)
+static void copy_output_file(bNodeTree *UNUSED(dest_ntree), bNode *dest_node, bNode *src_node)
{
- bNodeSocket *sock, *newsock;
+ bNodeSocket *src_sock, *dest_sock;
- target->storage = MEM_dupallocN(node->storage);
+ dest_node->storage = MEM_dupallocN(src_node->storage);
/* duplicate storage data in sockets */
- for (sock=node->inputs.first, newsock=target->inputs.first; sock && newsock; sock=sock->next, newsock=newsock->next) {
- newsock->storage = MEM_dupallocN(sock->storage);
+ for (src_sock=src_node->inputs.first, dest_sock=dest_node->inputs.first; src_sock && dest_sock; src_sock=src_sock->next, dest_sock=dest_sock->next) {
+ dest_sock->storage = MEM_dupallocN(src_sock->storage);
}
}
-static void update_output_file(bNodeTree *UNUSED(ntree), bNode *node)
+static void update_output_file(bNodeTree *ntree, bNode *node)
{
bNodeSocket *sock;
+ PointerRNA ptr;
+
+ cmp_node_update_default(ntree, node);
/* automatically update the socket type based on linked input */
for (sock=node->inputs.first; sock; sock=sock->next) {
if (sock->link) {
- int linktype = sock->link->fromsock->type;
- if (linktype != sock->type)
- nodeSocketSetType(sock, linktype);
+ RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr);
+ RNA_enum_set(&ptr, "type", sock->link->fromsock->type);
}
}
}
-void register_node_type_cmp_output_file(bNodeTreeType *ttype)
+void register_node_type_cmp_output_file()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_OUTPUT_FILE, "File Output", NODE_CLASS_OUTPUT, NODE_OPTIONS|NODE_PREVIEW);
+ cmp_node_type_base(&ntype, CMP_NODE_OUTPUT_FILE, "File Output", NODE_CLASS_OUTPUT, NODE_OPTIONS|NODE_PREVIEW);
node_type_socket_templates(&ntype, NULL, NULL);
- node_type_init(&ntype, init_output_file);
+ ntype.initfunc_api = init_output_file;
node_type_storage(&ntype, "NodeImageMultiFile", free_output_file, copy_output_file);
node_type_update(&ntype, update_output_file, NULL);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_pixelate.c b/source/blender/nodes/composite/nodes/node_composite_pixelate.c
index 3b65a2cdbd5..bb8df65ee23 100644
--- a/source/blender/nodes/composite/nodes/node_composite_pixelate.c
+++ b/source/blender/nodes/composite/nodes/node_composite_pixelate.c
@@ -45,12 +45,12 @@ static bNodeSocketTemplate cmp_node_pixelate_out[] = {
{ -1, 0, "" }
};
-void register_node_type_cmp_pixelate(bNodeTreeType *ttype)
+void register_node_type_cmp_pixelate()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_PIXELATE, "Pixelate", NODE_CLASS_OP_FILTER, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_PIXELATE, "Pixelate", NODE_CLASS_OP_FILTER, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_pixelate_in, cmp_node_pixelate_out);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_premulkey.c b/source/blender/nodes/composite/nodes/node_composite_premulkey.c
index 01eb3607760..75e34335c3a 100644
--- a/source/blender/nodes/composite/nodes/node_composite_premulkey.c
+++ b/source/blender/nodes/composite/nodes/node_composite_premulkey.c
@@ -44,12 +44,12 @@ static bNodeSocketTemplate cmp_node_premulkey_out[] = {
{ -1, 0, "" }
};
-void register_node_type_cmp_premulkey(bNodeTreeType *ttype)
+void register_node_type_cmp_premulkey()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_PREMULKEY, "Alpha Convert", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_PREMULKEY, "Alpha Convert", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_premulkey_in, cmp_node_premulkey_out);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_rgb.c b/source/blender/nodes/composite/nodes/node_composite_rgb.c
index 30b23a4c146..d2ebd84487d 100644
--- a/source/blender/nodes/composite/nodes/node_composite_rgb.c
+++ b/source/blender/nodes/composite/nodes/node_composite_rgb.c
@@ -32,32 +32,19 @@
#include "node_composite_util.h"
-
/* **************** RGB ******************** */
static bNodeSocketTemplate cmp_node_rgb_out[] = {
- { SOCK_RGBA, 0, N_("RGBA"), 0.5f, 0.5f, 0.5f, 1.0f},
+ { SOCK_RGBA, 0, N_("RGBA"), 0.5f, 0.5f, 0.5f, 1.0f},
{ -1, 0, "" }
};
-static void node_composit_init_rgb(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
-{
- bNodeSocket *sock= node->outputs.first;
- float *col= ((bNodeSocketValueRGBA*)sock->default_value)->value;
- /* uses the default value of the output socket, must be initialized here */
- col[0] = 0.5f;
- col[1] = 0.5f;
- col[2] = 0.5f;
- col[3] = 1.0f;
-}
-
-void register_node_type_cmp_rgb(bNodeTreeType *ttype)
+void register_node_type_cmp_rgb()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_RGB, "RGB", NODE_CLASS_INPUT, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_RGB, "RGB", NODE_CLASS_INPUT, NODE_OPTIONS);
node_type_socket_templates(&ntype, NULL, cmp_node_rgb_out);
- node_type_init(&ntype, node_composit_init_rgb);
node_type_size_preset(&ntype, NODE_SIZE_SMALL);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_rotate.c b/source/blender/nodes/composite/nodes/node_composite_rotate.c
index 6b5521ea4d2..f52d54b9c64 100644
--- a/source/blender/nodes/composite/nodes/node_composite_rotate.c
+++ b/source/blender/nodes/composite/nodes/node_composite_rotate.c
@@ -44,18 +44,18 @@ static bNodeSocketTemplate cmp_node_rotate_out[] = {
{ -1, 0, "" }
};
-static void node_composit_init_rotate(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_rotate(bNodeTree *UNUSED(ntree), bNode *node)
{
node->custom1= 1; /* Bilinear Filter*/
}
-void register_node_type_cmp_rotate(bNodeTreeType *ttype)
+void register_node_type_cmp_rotate()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_ROTATE, "Rotate", NODE_CLASS_DISTORT, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_ROTATE, "Rotate", NODE_CLASS_DISTORT, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_rotate_in, cmp_node_rotate_out);
node_type_init(&ntype, node_composit_init_rotate);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_scale.c b/source/blender/nodes/composite/nodes/node_composite_scale.c
index 6c2c6c37cb7..284b6dca72d 100644
--- a/source/blender/nodes/composite/nodes/node_composite_scale.c
+++ b/source/blender/nodes/composite/nodes/node_composite_scale.c
@@ -45,12 +45,12 @@ static bNodeSocketTemplate cmp_node_scale_out[] = {
{ -1, 0, "" }
};
-void register_node_type_cmp_scale(bNodeTreeType *ttype)
+void register_node_type_cmp_scale()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_SCALE, "Scale", NODE_CLASS_DISTORT, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_SCALE, "Scale", NODE_CLASS_DISTORT, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_scale_in, cmp_node_scale_out);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_sepcombHSVA.c b/source/blender/nodes/composite/nodes/node_composite_sepcombHSVA.c
index d463f35a07a..2043812c6eb 100644
--- a/source/blender/nodes/composite/nodes/node_composite_sepcombHSVA.c
+++ b/source/blender/nodes/composite/nodes/node_composite_sepcombHSVA.c
@@ -46,14 +46,14 @@ static bNodeSocketTemplate cmp_node_sephsva_out[] = {
{ -1, 0, "" }
};
-void register_node_type_cmp_sephsva(bNodeTreeType *ttype)
+void register_node_type_cmp_sephsva()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_SEPHSVA, "Separate HSVA", NODE_CLASS_CONVERTOR, 0);
+ cmp_node_type_base(&ntype, CMP_NODE_SEPHSVA, "Separate HSVA", NODE_CLASS_CONVERTOR, 0);
node_type_socket_templates(&ntype, cmp_node_sephsva_in, cmp_node_sephsva_out);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
@@ -70,12 +70,12 @@ static bNodeSocketTemplate cmp_node_combhsva_out[] = {
{ -1, 0, "" }
};
-void register_node_type_cmp_combhsva(bNodeTreeType *ttype)
+void register_node_type_cmp_combhsva()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_COMBHSVA, "Combine HSVA", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_COMBHSVA, "Combine HSVA", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_combhsva_in, cmp_node_combhsva_out);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_sepcombRGBA.c b/source/blender/nodes/composite/nodes/node_composite_sepcombRGBA.c
index 03b43f5073f..6b522184fe7 100644
--- a/source/blender/nodes/composite/nodes/node_composite_sepcombRGBA.c
+++ b/source/blender/nodes/composite/nodes/node_composite_sepcombRGBA.c
@@ -45,14 +45,14 @@ static bNodeSocketTemplate cmp_node_seprgba_out[] = {
{ -1, 0, "" }
};
-void register_node_type_cmp_seprgba(bNodeTreeType *ttype)
+void register_node_type_cmp_seprgba()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_SEPRGBA, "Separate RGBA", NODE_CLASS_CONVERTOR, 0);
+ cmp_node_type_base(&ntype, CMP_NODE_SEPRGBA, "Separate RGBA", NODE_CLASS_CONVERTOR, 0);
node_type_socket_templates(&ntype, cmp_node_seprgba_in, cmp_node_seprgba_out);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
@@ -70,12 +70,12 @@ static bNodeSocketTemplate cmp_node_combrgba_out[] = {
{ -1, 0, "" }
};
-void register_node_type_cmp_combrgba(bNodeTreeType *ttype)
+void register_node_type_cmp_combrgba()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_COMBRGBA, "Combine RGBA", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_COMBRGBA, "Combine RGBA", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_combrgba_in, cmp_node_combrgba_out);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_sepcombYCCA.c b/source/blender/nodes/composite/nodes/node_composite_sepcombYCCA.c
index 16aba1ba408..5940cf18c8a 100644
--- a/source/blender/nodes/composite/nodes/node_composite_sepcombYCCA.c
+++ b/source/blender/nodes/composite/nodes/node_composite_sepcombYCCA.c
@@ -47,14 +47,14 @@ static bNodeSocketTemplate cmp_node_sepycca_out[] = {
};
-void register_node_type_cmp_sepycca(bNodeTreeType *ttype)
+void register_node_type_cmp_sepycca()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_SEPYCCA, "Separate YCbCrA", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_SEPYCCA, "Separate YCbCrA", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_sepycca_in, cmp_node_sepycca_out);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
@@ -72,12 +72,12 @@ static bNodeSocketTemplate cmp_node_combycca_out[] = {
{ -1, 0, "" }
};
-void register_node_type_cmp_combycca(bNodeTreeType *ttype)
+void register_node_type_cmp_combycca()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_COMBYCCA, "Combine YCbCrA", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_COMBYCCA, "Combine YCbCrA", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_combycca_in, cmp_node_combycca_out);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_sepcombYUVA.c b/source/blender/nodes/composite/nodes/node_composite_sepcombYUVA.c
index 7d7ec166fd4..01dfd3b1abd 100644
--- a/source/blender/nodes/composite/nodes/node_composite_sepcombYUVA.c
+++ b/source/blender/nodes/composite/nodes/node_composite_sepcombYUVA.c
@@ -46,15 +46,14 @@ static bNodeSocketTemplate cmp_node_sepyuva_out[] = {
{ -1, 0, "" }
};
-
-void register_node_type_cmp_sepyuva(bNodeTreeType *ttype)
+void register_node_type_cmp_sepyuva()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_SEPYUVA, "Separate YUVA", NODE_CLASS_CONVERTOR, 0);
+ cmp_node_type_base(&ntype, CMP_NODE_SEPYUVA, "Separate YUVA", NODE_CLASS_CONVERTOR, 0);
node_type_socket_templates(&ntype, cmp_node_sepyuva_in, cmp_node_sepyuva_out);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
@@ -72,12 +71,12 @@ static bNodeSocketTemplate cmp_node_combyuva_out[] = {
{ -1, 0, "" }
};
-void register_node_type_cmp_combyuva(bNodeTreeType *ttype)
+void register_node_type_cmp_combyuva()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_COMBYUVA, "Combine YUVA", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_COMBYUVA, "Combine YUVA", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_combyuva_in, cmp_node_combyuva_out);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_setalpha.c b/source/blender/nodes/composite/nodes/node_composite_setalpha.c
index d36acc6c054..30e408dcccb 100644
--- a/source/blender/nodes/composite/nodes/node_composite_setalpha.c
+++ b/source/blender/nodes/composite/nodes/node_composite_setalpha.c
@@ -43,12 +43,12 @@ static bNodeSocketTemplate cmp_node_setalpha_out[] = {
{ -1, 0, "" }
};
-void register_node_type_cmp_setalpha(bNodeTreeType *ttype)
+void register_node_type_cmp_setalpha()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_SETALPHA, "Set Alpha", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_SETALPHA, "Set Alpha", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_setalpha_in, cmp_node_setalpha_out);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_splitViewer.c b/source/blender/nodes/composite/nodes/node_composite_splitViewer.c
index 38a6981613a..9fd61eca668 100644
--- a/source/blender/nodes/composite/nodes/node_composite_splitViewer.c
+++ b/source/blender/nodes/composite/nodes/node_composite_splitViewer.c
@@ -39,7 +39,7 @@ static bNodeSocketTemplate cmp_node_splitviewer_in[] = {
{ -1, 0, "" }
};
-static void node_composit_init_splitviewer(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_splitviewer(bNodeTree *UNUSED(ntree), bNode *node)
{
ImageUser *iuser= MEM_callocN(sizeof(ImageUser), "node image user");
node->storage= iuser;
@@ -49,11 +49,11 @@ static void node_composit_init_splitviewer(bNodeTree *UNUSED(ntree), bNode *node
node->custom1= 50; /* default 50% split */
}
-void register_node_type_cmp_splitviewer(bNodeTreeType *ttype)
+void register_node_type_cmp_splitviewer()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_SPLITVIEWER, "Split Viewer", NODE_CLASS_OUTPUT, NODE_PREVIEW|NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_SPLITVIEWER, "Split Viewer", NODE_CLASS_OUTPUT, NODE_PREVIEW|NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_splitviewer_in, NULL);
node_type_init(&ntype, node_composit_init_splitviewer);
node_type_storage(&ntype, "ImageUser", node_free_standard_storage, node_copy_standard_storage);
@@ -61,5 +61,5 @@ void register_node_type_cmp_splitviewer(bNodeTreeType *ttype)
/* Do not allow muting for this node. */
node_type_internal_links(&ntype, NULL);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_stabilize2d.c b/source/blender/nodes/composite/nodes/node_composite_stabilize2d.c
index 6b345b4c15c..2aa2906d67a 100644
--- a/source/blender/nodes/composite/nodes/node_composite_stabilize2d.c
+++ b/source/blender/nodes/composite/nodes/node_composite_stabilize2d.c
@@ -45,12 +45,12 @@ static bNodeSocketTemplate cmp_node_stabilize2d_out[] = {
{ -1, 0, "" }
};
-void register_node_type_cmp_stabilize2d(bNodeTreeType *ttype)
+void register_node_type_cmp_stabilize2d()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_STABILIZE2D, "Stabilize 2D", NODE_CLASS_DISTORT, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_STABILIZE2D, "Stabilize 2D", NODE_CLASS_DISTORT, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_stabilize2d_in, cmp_node_stabilize2d_out);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_switch.c b/source/blender/nodes/composite/nodes/node_composite_switch.c
index 49fa61a8397..a6254de62d5 100644
--- a/source/blender/nodes/composite/nodes/node_composite_switch.c
+++ b/source/blender/nodes/composite/nodes/node_composite_switch.c
@@ -46,13 +46,13 @@ static bNodeSocketTemplate cmp_node_switch_out[] = {
};
/* custom1 = mix type */
-void register_node_type_cmp_switch(bNodeTreeType *ttype)
+void register_node_type_cmp_switch(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_SWITCH, "Switch", NODE_CLASS_LAYOUT, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_SWITCH, "Switch", NODE_CLASS_LAYOUT, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_switch_in, cmp_node_switch_out);
node_type_size_preset(&ntype, NODE_SIZE_SMALL);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_texture.c b/source/blender/nodes/composite/nodes/node_composite_texture.c
index 515093fc3e1..3793dd4669a 100644
--- a/source/blender/nodes/composite/nodes/node_composite_texture.c
+++ b/source/blender/nodes/composite/nodes/node_composite_texture.c
@@ -44,12 +44,12 @@ static bNodeSocketTemplate cmp_node_texture_out[] = {
{ -1, 0, "" }
};
-void register_node_type_cmp_texture(bNodeTreeType *ttype)
+void register_node_type_cmp_texture()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_TEXTURE, "Texture", NODE_CLASS_INPUT, NODE_OPTIONS|NODE_PREVIEW);
+ cmp_node_type_base(&ntype, CMP_NODE_TEXTURE, "Texture", NODE_CLASS_INPUT, NODE_OPTIONS|NODE_PREVIEW);
node_type_socket_templates(&ntype, cmp_node_texture_in, cmp_node_texture_out);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_tonemap.c b/source/blender/nodes/composite/nodes/node_composite_tonemap.c
index fd3a217b150..4f43297a182 100644
--- a/source/blender/nodes/composite/nodes/node_composite_tonemap.c
+++ b/source/blender/nodes/composite/nodes/node_composite_tonemap.c
@@ -41,7 +41,7 @@ static bNodeSocketTemplate cmp_node_tonemap_out[] = {
{ -1, 0, "" }
};
-static void node_composit_init_tonemap(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_tonemap(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeTonemap *ntm = MEM_callocN(sizeof(NodeTonemap), "node tonemap data");
ntm->type = 1;
@@ -57,14 +57,14 @@ static void node_composit_init_tonemap(bNodeTree *UNUSED(ntree), bNode *node, bN
node->storage = ntm;
}
-void register_node_type_cmp_tonemap(bNodeTreeType *ttype)
+void register_node_type_cmp_tonemap()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_TONEMAP, "Tonemap", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_TONEMAP, "Tonemap", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_tonemap_in, cmp_node_tonemap_out);
node_type_init(&ntype, node_composit_init_tonemap);
node_type_storage(&ntype, "NodeTonemap", node_free_standard_storage, node_copy_standard_storage);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_trackpos.c b/source/blender/nodes/composite/nodes/node_composite_trackpos.c
index 1583680720a..bc3c54702ac 100644
--- a/source/blender/nodes/composite/nodes/node_composite_trackpos.c
+++ b/source/blender/nodes/composite/nodes/node_composite_trackpos.c
@@ -39,21 +39,21 @@ static bNodeSocketTemplate cmp_node_trackpos_out[] = {
{ -1, 0, "" }
};
-static void init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void init(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeTrackPosData *data = MEM_callocN(sizeof(NodeTrackPosData), "node track position data");
node->storage = data;
}
-void register_node_type_cmp_trackpos(bNodeTreeType *ttype)
+void register_node_type_cmp_trackpos(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_TRACKPOS, "Track Position", NODE_CLASS_INPUT, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_TRACKPOS, "Track Position", NODE_CLASS_INPUT, NODE_OPTIONS);
node_type_socket_templates(&ntype, NULL, cmp_node_trackpos_out);
node_type_init(&ntype, init);
node_type_storage(&ntype, "NodeTrackPosData", node_free_standard_storage, node_copy_standard_storage);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_transform.c b/source/blender/nodes/composite/nodes/node_composite_transform.c
index 3ed8bdb9995..9618cc85811 100644
--- a/source/blender/nodes/composite/nodes/node_composite_transform.c
+++ b/source/blender/nodes/composite/nodes/node_composite_transform.c
@@ -48,12 +48,12 @@ static bNodeSocketTemplate cmp_node_transform_out[] = {
{ -1, 0, "" }
};
-void register_node_type_cmp_transform(bNodeTreeType *ttype)
+void register_node_type_cmp_transform()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_TRANSFORM, "Transform", NODE_CLASS_DISTORT, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_TRANSFORM, "Transform", NODE_CLASS_DISTORT, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_transform_in, cmp_node_transform_out);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_translate.c b/source/blender/nodes/composite/nodes/node_composite_translate.c
index 5d555cdcda9..2449f614fe0 100644
--- a/source/blender/nodes/composite/nodes/node_composite_translate.c
+++ b/source/blender/nodes/composite/nodes/node_composite_translate.c
@@ -46,20 +46,20 @@ static bNodeSocketTemplate cmp_node_translate_out[] = {
{ -1, 0, "" }
};
-static void node_composit_init_translate(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_translate(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeTranslateData *data = MEM_callocN(sizeof(NodeTranslateData), "node translate data");
node->storage = data;
}
-void register_node_type_cmp_translate(bNodeTreeType *ttype)
+void register_node_type_cmp_translate()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_TRANSLATE, "Translate", NODE_CLASS_DISTORT, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_TRANSLATE, "Translate", NODE_CLASS_DISTORT, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_translate_in, cmp_node_translate_out);
node_type_init(&ntype, node_composit_init_translate);
node_type_storage(&ntype, "NodeTranslateData", node_free_standard_storage, node_copy_standard_storage);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_valToRgb.c b/source/blender/nodes/composite/nodes/node_composite_valToRgb.c
index 5a23507bcc7..db02c51c95f 100644
--- a/source/blender/nodes/composite/nodes/node_composite_valToRgb.c
+++ b/source/blender/nodes/composite/nodes/node_composite_valToRgb.c
@@ -44,22 +44,22 @@ static bNodeSocketTemplate cmp_node_valtorgb_out[] = {
{ -1, 0, "" }
};
-static void node_composit_init_valtorgb(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_valtorgb(bNodeTree *UNUSED(ntree), bNode *node)
{
node->storage= add_colorband(1);
}
-void register_node_type_cmp_valtorgb(bNodeTreeType *ttype)
+void register_node_type_cmp_valtorgb()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_VALTORGB, "ColorRamp", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_VALTORGB, "ColorRamp", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_valtorgb_in, cmp_node_valtorgb_out);
node_type_size(&ntype, 240, 200, 320);
node_type_init(&ntype, node_composit_init_valtorgb);
node_type_storage(&ntype, "ColorBand", node_free_standard_storage, node_copy_standard_storage);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
@@ -74,13 +74,13 @@ static bNodeSocketTemplate cmp_node_rgbtobw_out[] = {
{ -1, 0, "" }
};
-void register_node_type_cmp_rgbtobw(bNodeTreeType *ttype)
+void register_node_type_cmp_rgbtobw()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_RGBTOBW, "RGB to BW", NODE_CLASS_CONVERTOR, 0);
+ cmp_node_type_base(&ntype, CMP_NODE_RGBTOBW, "RGB to BW", NODE_CLASS_CONVERTOR, 0);
node_type_socket_templates(&ntype, cmp_node_rgbtobw_in, cmp_node_rgbtobw_out);
node_type_size_preset(&ntype, NODE_SIZE_SMALL);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_value.c b/source/blender/nodes/composite/nodes/node_composite_value.c
index 306170baf93..491c01c465a 100644
--- a/source/blender/nodes/composite/nodes/node_composite_value.c
+++ b/source/blender/nodes/composite/nodes/node_composite_value.c
@@ -34,29 +34,17 @@
/* **************** VALUE ******************** */
static bNodeSocketTemplate cmp_node_value_out[] = {
- /* XXX value nodes use the output sockets for buttons, so we need explicit limits here! */
- { SOCK_FLOAT, 0, N_("Value"), 0.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX},
+ { SOCK_FLOAT, 0, N_("Value"), 0.5f, 0, 0, 0, -FLT_MAX, FLT_MAX, PROP_NONE},
{ -1, 0, "" }
};
-static void node_composit_init_value(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
-{
- bNodeSocket *sock= node->outputs.first;
- bNodeSocketValueFloat *dval= (bNodeSocketValueFloat*)sock->default_value;
- /* uses the default value of the output socket, must be initialized here */
- dval->value = 0.5f;
- dval->min = -FLT_MAX;
- dval->max = FLT_MAX;
-}
-
-void register_node_type_cmp_value(bNodeTreeType *ttype)
+void register_node_type_cmp_value()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_VALUE, "Value", NODE_CLASS_INPUT, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_VALUE, "Value", NODE_CLASS_INPUT, NODE_OPTIONS);
node_type_socket_templates(&ntype, NULL, cmp_node_value_out);
- node_type_init(&ntype, node_composit_init_value);
node_type_size_preset(&ntype, NODE_SIZE_SMALL);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_vecBlur.c b/source/blender/nodes/composite/nodes/node_composite_vecBlur.c
index 35fb4a944db..02a5fdcc0e5 100644
--- a/source/blender/nodes/composite/nodes/node_composite_vecBlur.c
+++ b/source/blender/nodes/composite/nodes/node_composite_vecBlur.c
@@ -45,7 +45,7 @@ static bNodeSocketTemplate cmp_node_vecblur_out[] = {
{ -1, 0, "" }
};
-static void node_composit_init_vecblur(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_vecblur(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeBlurData *nbd = MEM_callocN(sizeof(NodeBlurData), "node blur data");
node->storage = nbd;
@@ -54,14 +54,14 @@ static void node_composit_init_vecblur(bNodeTree *UNUSED(ntree), bNode *node, bN
}
/* custom1: itterations, custom2: maxspeed (0 = nolimit) */
-void register_node_type_cmp_vecblur(bNodeTreeType *ttype)
+void register_node_type_cmp_vecblur()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_VECBLUR, "Vector Blur", NODE_CLASS_OP_FILTER, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_VECBLUR, "Vector Blur", NODE_CLASS_OP_FILTER, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_vecblur_in, cmp_node_vecblur_out);
node_type_init(&ntype, node_composit_init_vecblur);
node_type_storage(&ntype, "NodeBlurData", node_free_standard_storage, node_copy_standard_storage);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_viewer.c b/source/blender/nodes/composite/nodes/node_composite_viewer.c
index 211ebe54eb0..a1e6640dcb6 100644
--- a/source/blender/nodes/composite/nodes/node_composite_viewer.c
+++ b/source/blender/nodes/composite/nodes/node_composite_viewer.c
@@ -41,7 +41,7 @@ static bNodeSocketTemplate cmp_node_viewer_in[] = {
{ -1, 0, "" }
};
-static void node_composit_init_viewer(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_viewer(bNodeTree *UNUSED(ntree), bNode *node)
{
ImageUser *iuser = MEM_callocN(sizeof(ImageUser), "node image user");
node->storage = iuser;
@@ -52,16 +52,16 @@ static void node_composit_init_viewer(bNodeTree *UNUSED(ntree), bNode *node, bNo
node->custom4 = 0.5f;
}
-void register_node_type_cmp_viewer(bNodeTreeType *ttype)
+void register_node_type_cmp_viewer()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_VIEWER, "Viewer", NODE_CLASS_OUTPUT, NODE_OPTIONS | NODE_PREVIEW);
+ cmp_node_type_base(&ntype, CMP_NODE_VIEWER, "Viewer", NODE_CLASS_OUTPUT, NODE_OPTIONS | NODE_PREVIEW);
node_type_socket_templates(&ntype, cmp_node_viewer_in, NULL);
node_type_init(&ntype, node_composit_init_viewer);
node_type_storage(&ntype, "ImageUser", node_free_standard_storage, node_copy_standard_storage);
node_type_internal_links(&ntype, NULL);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_zcombine.c b/source/blender/nodes/composite/nodes/node_composite_zcombine.c
index ba81174e103..ca7258c5b97 100644
--- a/source/blender/nodes/composite/nodes/node_composite_zcombine.c
+++ b/source/blender/nodes/composite/nodes/node_composite_zcombine.c
@@ -48,12 +48,12 @@ static bNodeSocketTemplate cmp_node_zcombine_out[] = {
{ -1, 0, "" }
};
-void register_node_type_cmp_zcombine(bNodeTreeType *ttype)
+void register_node_type_cmp_zcombine()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_ZCOMBINE, "Z Combine", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_ZCOMBINE, "Z Combine", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_zcombine_in, cmp_node_zcombine_out);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/intern/node_common.c b/source/blender/nodes/intern/node_common.c
index d59061dfc0a..85e2f775ad9 100644
--- a/source/blender/nodes/intern/node_common.c
+++ b/source/blender/nodes/intern/node_common.c
@@ -31,19 +31,22 @@
#include <string.h>
+#include <stddef.h>
#include "DNA_node_types.h"
#include "BLI_listbase.h"
+#include "BLI_math.h"
+#include "BLI_path_util.h"
#include "BLI_string.h"
#include "BLI_utildefines.h"
#include "BLF_translation.h"
#include "BKE_global.h"
+#include "BKE_idprop.h"
#include "BKE_library.h"
#include "BKE_main.h"
-#include "BLI_math.h"
#include "BKE_node.h"
#include "RNA_access.h"
@@ -55,247 +58,110 @@
#include "node_util.h"
#include "node_exec.h"
#include "NOD_socket.h"
+#include "NOD_common.h"
+
/**** Group ****/
-bNodeSocket *node_group_find_input(bNode *gnode, bNodeSocket *gsock)
+bNodeSocket *node_group_find_input_socket(bNode *groupnode, const char *identifier)
{
bNodeSocket *sock;
- for (sock=gnode->inputs.first; sock; sock=sock->next)
- if (sock->groupsock == gsock)
+ for (sock=groupnode->inputs.first; sock; sock=sock->next)
+ if (strcmp(sock->identifier, identifier)==0)
return sock;
return NULL;
}
-bNodeSocket *node_group_find_output(bNode *gnode, bNodeSocket *gsock)
+bNodeSocket *node_group_find_output_socket(bNode *groupnode, const char *identifier)
{
bNodeSocket *sock;
- for (sock=gnode->outputs.first; sock; sock=sock->next)
- if (sock->groupsock == gsock)
+ for (sock=groupnode->outputs.first; sock; sock=sock->next)
+ if (strcmp(sock->identifier, identifier)==0)
return sock;
return NULL;
}
-bNodeSocket *node_group_add_extern_socket(bNodeTree *UNUSED(ntree), ListBase *lb, int in_out, bNodeSocket *gsock)
-{
- bNodeSocket *sock;
-
- if (gsock->flag & SOCK_INTERNAL)
- return NULL;
-
- sock= MEM_callocN(sizeof(bNodeSocket), "sock");
-
- /* make a copy of the group socket */
- *sock = *gsock;
- sock->link = NULL;
- sock->next = sock->prev = NULL;
- sock->new_sock = NULL;
-
- /* group sockets are dynamically added */
- sock->flag |= SOCK_DYNAMIC|SOCK_COLLAPSED;
-
- sock->own_index = gsock->own_index;
- sock->groupsock = gsock;
- sock->limit = (in_out==SOCK_IN ? 1 : 0xFFF);
-
- sock->default_value = node_socket_make_default_value(sock->type);
- node_socket_copy_default_value(sock->type, sock->default_value, gsock->default_value);
-
- if (lb)
- BLI_addtail(lb, sock);
-
- return sock;
-}
-
-bNodeSocket *node_group_add_socket(bNodeTree *ngroup, const char *name, int type, int in_out)
-{
- bNodeSocketType *stype = ntreeGetSocketType(type);
- bNodeSocket *gsock = MEM_callocN(sizeof(bNodeSocket), "bNodeSocket");
-
- BLI_strncpy(gsock->name, name, sizeof(gsock->name));
- gsock->type = type;
- /* group sockets are dynamically added */
- gsock->flag |= SOCK_DYNAMIC|SOCK_COLLAPSED;
-
- gsock->next = gsock->prev = NULL;
- gsock->new_sock = NULL;
- gsock->link = NULL;
- /* assign new unique index */
- gsock->own_index = ngroup->cur_index++;
- gsock->limit = (in_out==SOCK_IN ? 0xFFF : 1);
-
- if (stype->value_structsize > 0)
- gsock->default_value = MEM_callocN(stype->value_structsize, "default socket value");
-
- BLI_addtail(in_out==SOCK_IN ? &ngroup->inputs : &ngroup->outputs, gsock);
-
- ngroup->update |= (in_out==SOCK_IN ? NTREE_UPDATE_GROUP_IN : NTREE_UPDATE_GROUP_OUT);
-
- return gsock;
-}
-
-bNodeSocket *node_group_expose_socket(bNodeTree *ngroup, bNodeSocket *sock, int in_out)
-{
- bNodeSocket *gsock= node_group_add_socket(ngroup, sock->name, sock->type, in_out);
-
- /* initialize the default value. */
- node_socket_copy_default_value(gsock->type, gsock->default_value, sock->default_value);
-
- return gsock;
-}
-
-void node_group_expose_all_sockets(bNodeTree *ngroup)
-{
- bNode *node;
- bNodeSocket *sock, *gsock;
-
- for (node=ngroup->nodes.first; node; node=node->next) {
- for (sock=node->inputs.first; sock; sock=sock->next) {
- if (!sock->link && !nodeSocketIsHidden(sock)) {
- gsock = node_group_add_socket(ngroup, sock->name, sock->type, SOCK_IN);
-
- /* initialize the default value. */
- node_socket_copy_default_value(gsock->type, gsock->default_value, sock->default_value);
-
- sock->link = nodeAddLink(ngroup, NULL, gsock, node, sock);
- }
- }
- for (sock=node->outputs.first; sock; sock=sock->next) {
- if (nodeCountSocketLinks(ngroup, sock)==0 && !nodeSocketIsHidden(sock)) {
- gsock = node_group_add_socket(ngroup, sock->name, sock->type, SOCK_OUT);
-
- /* initialize the default value. */
- node_socket_copy_default_value(gsock->type, gsock->default_value, sock->default_value);
-
- gsock->link = nodeAddLink(ngroup, node, sock, NULL, gsock);
- }
- }
- }
-}
-
-void node_group_remove_socket(bNodeTree *ngroup, bNodeSocket *gsock, int in_out)
-{
- nodeRemSocketLinks(ngroup, gsock);
-
- switch (in_out) {
- case SOCK_IN:
- BLI_remlink(&ngroup->inputs, gsock);
- ngroup->update |= NTREE_UPDATE_GROUP_IN;
- break;
- case SOCK_OUT:
- BLI_remlink(&ngroup->outputs, gsock);
- ngroup->update |= NTREE_UPDATE_GROUP_OUT;
- break;
- }
-
- if (gsock->default_value)
- MEM_freeN(gsock->default_value);
-
- MEM_freeN(gsock);
-}
-
/* groups display their internal tree name as label */
const char *node_group_label(bNode *node)
{
return (node->id)? node->id->name + 2: IFACE_("Missing Datablock");
}
-int node_group_valid(bNodeTree *ntree, bNodeTemplate *ntemp)
+int node_group_poll_instance(bNode *node, bNodeTree *nodetree)
{
- bNodeTemplate childtemp;
- bNode *node;
-
- /* regular groups cannot be recursive */
- if (ntree == ntemp->ngroup)
- return 0;
-
- /* make sure all children are valid */
- for (node=ntemp->ngroup->nodes.first; node; node=node->next) {
- childtemp = nodeMakeTemplate(node);
- if (!nodeValid(ntree, &childtemp))
- return 0;
- }
-
- return 1;
-}
-
-bNodeTemplate node_group_template(bNode *node)
-{
- bNodeTemplate ntemp;
- ntemp.type = NODE_GROUP;
- ntemp.ngroup = (bNodeTree *)node->id;
- return ntemp;
+ bNodeTree *grouptree = (bNodeTree*)node->id;
+ if (grouptree)
+ return nodeGroupPoll(nodetree, grouptree);
+ else
+ return 1;
}
-void node_group_init(bNodeTree *ntree, bNode *node, bNodeTemplate *ntemp)
+int nodeGroupPoll(bNodeTree *nodetree, bNodeTree *grouptree)
{
- node->id = (ID *)ntemp->ngroup;
+ bNode *node;
+ int valid = 1;
- /* NB: group socket input/output roles are inverted internally!
- * Group "inputs" work as outputs in links and vice versa.
- */
- if (ntemp->ngroup) {
- bNodeSocket *gsock;
- for (gsock=ntemp->ngroup->inputs.first; gsock; gsock=gsock->next)
- node_group_add_extern_socket(ntree, &node->inputs, SOCK_IN, gsock);
- for (gsock=ntemp->ngroup->outputs.first; gsock; gsock=gsock->next)
- node_group_add_extern_socket(ntree, &node->outputs, SOCK_OUT, gsock);
+ if (nodetree == grouptree)
+ return 0;
+
+ for (node=grouptree->nodes.first; node; node=node->next) {
+ if (!node->typeinfo->poll_instance(node, nodetree)) {
+ valid = 0;
+ break;
+ }
}
+ return valid;
}
-static bNodeSocket *group_verify_socket(bNodeTree *ntree, ListBase *lb, int in_out, bNodeSocket *gsock)
+/* used for both group nodes and interface nodes */
+static bNodeSocket *group_verify_socket(bNodeTree *ntree, bNode *gnode, bNodeSocket *iosock, ListBase *verify_lb, int in_out)
{
bNodeSocket *sock;
- /* group sockets tagged as internal are not exposed ever */
- if (gsock->flag & SOCK_INTERNAL)
- return NULL;
-
- for (sock= lb->first; sock; sock= sock->next) {
- if (sock->own_index==gsock->own_index)
+ for (sock= verify_lb->first; sock; sock= sock->next) {
+ if (strcmp(sock->identifier, iosock->identifier)==0)
break;
}
if (sock) {
- sock->groupsock = gsock;
-
- BLI_strncpy(sock->name, gsock->name, sizeof(sock->name));
- if (gsock->type != sock->type)
- nodeSocketSetType(sock, gsock->type);
-
- /* XXX hack: group socket input/output roles are inverted internally,
- * need to change the limit value when making actual node sockets from them.
- */
- sock->limit = (in_out==SOCK_IN ? 1 : 0xFFF);
-
- BLI_remlink(lb, sock);
-
- return sock;
+ strcpy(sock->name, iosock->name);
}
else {
- return node_group_add_extern_socket(ntree, NULL, in_out, gsock);
+ sock = nodeAddSocket(ntree, gnode, in_out, iosock->idname, iosock->identifier, iosock->name);
+
+ if (iosock->typeinfo->interface_init_socket)
+ iosock->typeinfo->interface_init_socket(ntree, iosock, gnode, sock, "interface");
}
+
+ /* remove from list temporarily, to distinguish from orphaned sockets */
+ BLI_remlink(verify_lb, sock);
+
+ return sock;
}
-static void group_verify_socket_list(bNodeTree *ntree, bNode *node, ListBase *lb, int in_out, ListBase *glb)
+/* used for both group nodes and interface nodes */
+static void group_verify_socket_list(bNodeTree *ntree, bNode *gnode,
+ ListBase *iosock_lb, ListBase *verify_lb, int in_out)
{
- bNodeSocket *sock, *nextsock, *gsock;
+ bNodeSocket *iosock, *sock, *nextsock;
/* step by step compare */
- for (gsock= glb->first; gsock; gsock=gsock->next) {
+
+ iosock = iosock_lb->first;
+ for (; iosock; iosock = iosock->next) {
/* abusing new_sock pointer for verification here! only used inside this function */
- gsock->new_sock= group_verify_socket(ntree, lb, in_out, gsock);
+ iosock->new_sock = group_verify_socket(ntree, gnode, iosock, verify_lb, in_out);
}
/* leftovers are removed */
- for (sock=lb->first; sock; sock=nextsock) {
- nextsock=sock->next;
- if (sock->flag & SOCK_DYNAMIC)
- nodeRemoveSocket(ntree, node, sock);
+ for (sock = verify_lb->first; sock; sock = nextsock) {
+ nextsock = sock->next;
+ nodeRemoveSocket(ntree, gnode, sock);
}
/* and we put back the verified sockets */
- for (gsock= glb->first; gsock; gsock=gsock->next) {
- if (gsock->new_sock) {
- BLI_addtail(lb, gsock->new_sock);
- gsock->new_sock = NULL;
+ iosock = iosock_lb->first;
+ for (; iosock; iosock = iosock->next) {
+ if (iosock->new_sock) {
+ BLI_addtail(verify_lb, iosock->new_sock);
+ iosock->new_sock = NULL;
}
}
}
@@ -304,59 +170,16 @@ static void group_verify_socket_list(bNodeTree *ntree, bNode *node, ListBase *lb
void node_group_verify(struct bNodeTree *ntree, struct bNode *node, struct ID *id)
{
/* check inputs and outputs, and remove or insert them */
- if (node->id==id) {
+ if (id == node->id) {
bNodeTree *ngroup= (bNodeTree *)node->id;
- group_verify_socket_list(ntree, node, &node->inputs, SOCK_IN, &ngroup->inputs);
- group_verify_socket_list(ntree, node, &node->outputs, SOCK_OUT, &ngroup->outputs);
+ group_verify_socket_list(ntree, node, &ngroup->inputs, &node->inputs, SOCK_IN);
+ group_verify_socket_list(ntree, node, &ngroup->outputs, &node->outputs, SOCK_OUT);
}
}
-struct bNodeTree *node_group_edit_get(bNode *node)
-{
- if (node->flag & NODE_GROUP_EDIT)
- return (bNodeTree *)node->id;
- else
- return NULL;
-}
-
-struct bNodeTree *node_group_edit_set(bNode *node, int edit)
-{
- if (edit) {
- bNodeTree *ngroup= (bNodeTree *)node->id;
- if (ngroup) {
- if (ngroup->id.lib)
- ntreeMakeLocal(ngroup);
-
- node->flag |= NODE_GROUP_EDIT;
- }
- return ngroup;
- }
- else {
- node->flag &= ~NODE_GROUP_EDIT;
- return NULL;
- }
-}
-
-void node_group_edit_clear(bNode *node)
-{
- bNodeTree *ngroup= (bNodeTree *)node->id;
- bNode *inode;
-
- node->flag &= ~NODE_GROUP_EDIT;
-
- if (ngroup)
- for (inode=ngroup->nodes.first; inode; inode=inode->next)
- nodeGroupEditClear(inode);
-}
-
-static void UNUSED_FUNCTION(node_group_link)(bNodeTree *ntree, bNodeSocket *sock, int in_out)
-{
- node_group_expose_socket(ntree, sock, in_out);
-}
-
/**** FRAME ****/
-static void node_frame_init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_frame_init(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeFrame *data = (NodeFrame *)MEM_callocN(sizeof(NodeFrame), "frame node storage");
node->storage = data;
@@ -366,19 +189,19 @@ static void node_frame_init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate
data->label_size = 20;
}
-void register_node_type_frame(bNodeTreeType *ttype)
+void register_node_type_frame(void)
{
/* frame type is used for all tree types, needs dynamic allocation */
bNodeType *ntype= MEM_callocN(sizeof(bNodeType), "frame node type");
- node_type_base(ttype, ntype, NODE_FRAME, "Frame", NODE_CLASS_LAYOUT, NODE_BACKGROUND|NODE_OPTIONS);
+ node_type_base(ntype, NODE_FRAME, "Frame", NODE_CLASS_LAYOUT, NODE_BACKGROUND|NODE_OPTIONS);
node_type_init(ntype, node_frame_init);
node_type_storage(ntype, "NodeFrame", node_free_standard_storage, node_copy_standard_storage);
node_type_size(ntype, 150, 100, 0);
node_type_compatibility(ntype, NODE_OLD_SHADING|NODE_NEW_SHADING);
ntype->needs_free = 1;
- nodeRegisterType(ttype, ntype);
+ nodeRegisterType(ntype);
}
@@ -403,34 +226,34 @@ static void node_reroute_update_internal_links(bNodeTree *ntree, bNode *node)
BLI_addtail(&node->internal_links, link);
}
-static void node_reroute_init(bNodeTree *ntree, bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_reroute_init(bNodeTree *ntree, bNode *node)
{
/* Note: Cannot use socket templates for this, since it would reset the socket type
* on each file read via the template verification procedure.
*/
- nodeAddSocket(ntree, node, SOCK_IN, "Input", SOCK_RGBA);
- nodeAddSocket(ntree, node, SOCK_OUT, "Output", SOCK_RGBA);
+ nodeAddStaticSocket(ntree, node, SOCK_IN, SOCK_RGBA, PROP_NONE, "Input", "Input");
+ nodeAddStaticSocket(ntree, node, SOCK_OUT, SOCK_RGBA, PROP_NONE, "Output", "Output");
}
-void register_node_type_reroute(bNodeTreeType *ttype)
+void register_node_type_reroute(void)
{
/* frame type is used for all tree types, needs dynamic allocation */
bNodeType *ntype= MEM_callocN(sizeof(bNodeType), "frame node type");
- node_type_base(ttype, ntype, NODE_REROUTE, "Reroute", NODE_CLASS_LAYOUT, 0);
+ node_type_base(ntype, NODE_REROUTE, "Reroute", NODE_CLASS_LAYOUT, 0);
node_type_init(ntype, node_reroute_init);
node_type_internal_links(ntype, node_reroute_update_internal_links);
ntype->needs_free = 1;
- nodeRegisterType(ttype, ntype);
+ nodeRegisterType(ntype);
}
static void node_reroute_inherit_type_recursive(bNodeTree *ntree, bNode *node)
{
bNodeSocket *input = node->inputs.first;
bNodeSocket *output = node->outputs.first;
- int type = SOCK_FLOAT;
bNodeLink *link;
+ int type = SOCK_FLOAT;
/* XXX it would be a little bit more efficient to restrict actual updates
* to rerout nodes connected to an updated node, but there's no reliable flag
@@ -446,6 +269,8 @@ static void node_reroute_inherit_type_recursive(bNodeTree *ntree, bNode *node)
bNode *tonode = link->tonode;
if (!tonode || !fromnode)
continue;
+ if (nodeLinkIsHidden(link))
+ continue;
if (tonode == node && fromnode->type == NODE_REROUTE && !fromnode->done)
node_reroute_inherit_type_recursive(ntree, fromnode);
@@ -462,9 +287,13 @@ static void node_reroute_inherit_type_recursive(bNodeTree *ntree, bNode *node)
/* arbitrary, could also test output->type, both are the same */
if (input->type != type) {
+ PointerRNA input_ptr, output_ptr;
/* same type for input/output */
- nodeSocketSetType(input, type);
- nodeSocketSetType(output, type);
+ RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, input, &input_ptr);
+ RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, output, &output_ptr);
+
+ RNA_enum_set(&input_ptr, "type", type);
+ RNA_enum_set(&output_ptr, "type", type);
}
}
@@ -484,9 +313,8 @@ void ntree_update_reroute_nodes(bNodeTree *ntree)
node_reroute_inherit_type_recursive(ntree, node);
}
-void BKE_node_tree_unlink_id_cb(void *calldata, struct ID *UNUSED(owner_id), struct bNodeTree *ntree)
+void BKE_node_tree_unlink_id(ID *id, struct bNodeTree *ntree)
{
- ID *id = (ID *)calldata;
bNode *node;
for (node = ntree->nodes.first; node; node = node->next) {
@@ -495,3 +323,179 @@ void BKE_node_tree_unlink_id_cb(void *calldata, struct ID *UNUSED(owner_id), str
}
}
}
+
+/**** GROUP_INPUT / GROUP_OUTPUT ****/
+
+static void node_group_input_init(bNodeTree *ntree, bNode *node)
+{
+ node_group_input_verify(ntree, node, (ID *)ntree);
+}
+
+bNodeSocket *node_group_input_find_socket(bNode *node, const char *identifier)
+{
+ bNodeSocket *sock;
+ for (sock=node->outputs.first; sock; sock=sock->next)
+ if (strcmp(sock->identifier, identifier)==0)
+ return sock;
+ return NULL;
+}
+
+void node_group_input_verify(bNodeTree *ntree, bNode *node, ID *id)
+{
+ /* check inputs and outputs, and remove or insert them */
+ if (id == (ID *)ntree) {
+ /* value_in_out inverted for interface nodes to get correct socket value_property */
+ group_verify_socket_list(ntree, node, &ntree->inputs, &node->outputs, SOCK_OUT);
+
+ /* add virtual extension socket */
+ nodeAddSocket(ntree, node, SOCK_OUT, "NodeSocketVirtual", "__extend__", "");
+ }
+}
+
+static void node_group_input_update(bNodeTree *ntree, bNode *node)
+{
+ bNodeSocket *extsock = node->outputs.last;
+ bNodeLink *link;
+ /* Adding a tree socket and verifying will remove the extension socket!
+ * This list caches the existing links from the extension socket
+ * so they can be recreated after verification.
+ */
+ ListBase tmplinks;
+
+ /* find links from the extension socket and store them */
+ tmplinks.first = tmplinks.last = NULL;
+ for (link = ntree->links.first; link; link = link->next) {
+ if (nodeLinkIsHidden(link))
+ continue;
+ if (link->fromsock == extsock) {
+ bNodeLink *tlink = MEM_callocN(sizeof(bNodeLink), "temporary link");
+ *tlink = *link;
+ BLI_addtail(&tmplinks, tlink);
+ }
+ }
+
+ if (tmplinks.first) {
+ bNodeSocket *gsock, *newsock;
+ /* XXX Multiple sockets can be connected to the extension socket at once,
+ * in that case the arbitrary first link determines name and type.
+ * This could be improved by choosing the "best" type among all links,
+ * whatever that means.
+ */
+ bNodeLink *exposelink = tmplinks.first;
+
+ /* XXX what if connecting virtual to virtual socket?? */
+ gsock = ntreeAddSocketInterfaceFromSocket(ntree, exposelink->tonode, exposelink->tosock);
+
+ node_group_input_verify(ntree, node, (ID *)ntree);
+ newsock = node_group_input_find_socket(node, gsock->identifier);
+
+ /* redirect links from the extension socket */
+ for (link = tmplinks.first; link; link = link->next) {
+ nodeAddLink(ntree, node, newsock, link->tonode, link->tosock);
+ }
+
+ BLI_freelistN(&tmplinks);
+ }
+}
+
+void register_node_type_group_input(void)
+{
+ /* used for all tree types, needs dynamic allocation */
+ bNodeType *ntype= MEM_callocN(sizeof(bNodeType), "node type");
+
+ node_type_base(ntype, NODE_GROUP_INPUT, "Group Input", NODE_CLASS_INTERFACE, NODE_OPTIONS);
+ node_type_size(ntype, 140, 80, 200);
+ node_type_init(ntype, node_group_input_init);
+ node_type_update(ntype, node_group_input_update, node_group_input_verify);
+ node_type_compatibility(ntype, NODE_OLD_SHADING|NODE_NEW_SHADING);
+
+ ntype->needs_free = 1;
+ nodeRegisterType(ntype);
+}
+
+static void node_group_output_init(bNodeTree *ntree, bNode *node)
+{
+ node_group_output_verify(ntree, node, (ID *)ntree);
+}
+
+bNodeSocket *node_group_output_find_socket(bNode *node, const char *identifier)
+{
+ bNodeSocket *sock;
+ for (sock=node->inputs.first; sock; sock=sock->next)
+ if (strcmp(sock->identifier, identifier)==0)
+ return sock;
+ return NULL;
+}
+
+void node_group_output_verify(bNodeTree *ntree, bNode *node, ID *id)
+{
+ /* check inputs and outputs, and remove or insert them */
+ if (id == (ID *)ntree) {
+ /* value_in_out inverted for interface nodes to get correct socket value_property */
+ group_verify_socket_list(ntree, node, &ntree->outputs, &node->inputs, SOCK_IN);
+
+ /* add virtual extension socket */
+ nodeAddSocket(ntree, node, SOCK_IN, "NodeSocketVirtual", "__extend__", "");
+ }
+}
+
+static void node_group_output_update(bNodeTree *ntree, bNode *node)
+{
+ bNodeSocket *extsock = node->inputs.last;
+ bNodeLink *link;
+ /* Adding a tree socket and verifying will remove the extension socket!
+ * This list caches the existing links to the extension socket
+ * so they can be recreated after verification.
+ */
+ ListBase tmplinks;
+
+ /* find links to the extension socket and store them */
+ tmplinks.first = tmplinks.last = NULL;
+ for (link = ntree->links.first; link; link = link->next) {
+ if (nodeLinkIsHidden(link))
+ continue;
+ if (link->tosock == extsock) {
+ bNodeLink *tlink = MEM_callocN(sizeof(bNodeLink), "temporary link");
+ *tlink = *link;
+ BLI_addtail(&tmplinks, tlink);
+ }
+ }
+
+ if (tmplinks.first) {
+ bNodeSocket *gsock, *newsock;
+ /* XXX Multiple sockets can be connected to the extension socket at once,
+ * in that case the arbitrary first link determines name and type.
+ * This could be improved by choosing the "best" type among all links,
+ * whatever that means.
+ */
+ bNodeLink *exposelink = tmplinks.first;
+
+ /* XXX what if connecting virtual to virtual socket?? */
+ gsock = ntreeAddSocketInterfaceFromSocket(ntree, exposelink->fromnode, exposelink->fromsock);
+
+ node_group_output_verify(ntree, node, (ID *)ntree);
+ newsock = node_group_output_find_socket(node, gsock->identifier);
+
+ /* redirect links to the extension socket */
+ for (link = tmplinks.first; link; link = link->next) {
+ nodeAddLink(ntree, link->fromnode, link->fromsock, node, newsock);
+ }
+
+ BLI_freelistN(&tmplinks);
+ }
+}
+
+void register_node_type_group_output(void)
+{
+ /* used for all tree types, needs dynamic allocation */
+ bNodeType *ntype= MEM_callocN(sizeof(bNodeType), "node type");
+
+ node_type_base(ntype, NODE_GROUP_OUTPUT, "Group Output", NODE_CLASS_INTERFACE, NODE_OPTIONS);
+ node_type_size(ntype, 140, 80, 200);
+ node_type_init(ntype, node_group_output_init);
+ node_type_update(ntype, node_group_output_update, node_group_output_verify);
+ node_type_compatibility(ntype, NODE_OLD_SHADING|NODE_NEW_SHADING);
+
+ ntype->needs_free = 1;
+ nodeRegisterType(ntype);
+}
diff --git a/source/blender/nodes/intern/node_common.h b/source/blender/nodes/intern/node_common.h
index 9e04a9e05f8..498da607b91 100644
--- a/source/blender/nodes/intern/node_common.h
+++ b/source/blender/nodes/intern/node_common.h
@@ -37,15 +37,8 @@
struct bNodeTree;
-void node_group_init(struct bNodeTree *ntree, struct bNode *node, struct bNodeTemplate *ntemp);
const char *node_group_label(struct bNode *node);
-struct bNodeTemplate node_group_template(struct bNode *node);
-int node_group_valid(struct bNodeTree *ntree, struct bNodeTemplate *ntemp);
-void node_group_verify(struct bNodeTree *ntree, struct bNode *node, struct ID *id);
-
-struct bNodeTree *node_group_edit_get(struct bNode *node);
-struct bNodeTree *node_group_edit_set(struct bNode *node, int edit);
-void node_group_edit_clear(bNode *node);
+int node_group_poll_instance(struct bNode *node, struct bNodeTree *nodetree);
void ntree_update_reroute_nodes(struct bNodeTree *ntree);
diff --git a/source/blender/nodes/intern/node_exec.c b/source/blender/nodes/intern/node_exec.c
index 8cf7cc7a1ea..8fb23064bf0 100644
--- a/source/blender/nodes/intern/node_exec.c
+++ b/source/blender/nodes/intern/node_exec.c
@@ -41,12 +41,19 @@
#include "MEM_guardedalloc.h"
#include "node_exec.h"
+#include "node_util.h"
+/* supported socket types in old nodes */
+int node_exec_socket_use_stack(bNodeSocket *sock)
+{
+ return ELEM3(sock->type, SOCK_FLOAT, SOCK_VECTOR, SOCK_RGBA);
+}
+
/* for a given socket, find the actual stack entry */
bNodeStack *node_get_socket_stack(bNodeStack *stack, bNodeSocket *sock)
{
- if (stack && sock)
+ if (stack && sock && sock->stack_index >= 0)
return stack + sock->stack_index;
return NULL;
}
@@ -75,7 +82,10 @@ static void node_init_input_index(bNodeSocket *sock, int *index)
sock->stack_index = sock->link->fromsock->stack_index;
}
else {
- sock->stack_index = (*index)++;
+ if (node_exec_socket_use_stack(sock))
+ sock->stack_index = (*index)++;
+ else
+ sock->stack_index = -1;
}
}
@@ -91,19 +101,27 @@ static void node_init_output_index(bNodeSocket *sock, int *index, ListBase *inte
}
}
/* if not internally connected, assign a new stack index anyway to avoid bad stack access */
- if (!link)
- sock->stack_index = (*index)++;
+ if (!link) {
+ if (node_exec_socket_use_stack(sock))
+ sock->stack_index = (*index)++;
+ else
+ sock->stack_index = -1;
+ }
}
else {
- sock->stack_index = (*index)++;
+ if (node_exec_socket_use_stack(sock))
+ sock->stack_index = (*index)++;
+ else
+ sock->stack_index = -1;
}
}
/* basic preparation of socket stacks */
-static struct bNodeStack *setup_stack(bNodeStack *stack, bNodeSocket *sock)
+static struct bNodeStack *setup_stack(bNodeStack *stack, bNodeTree *ntree, bNode *node, bNodeSocket *sock)
{
bNodeStack *ns = node_get_socket_stack(stack, sock);
- float null_value[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ if (!ns)
+ return NULL;
/* don't mess with remote socket stacks, these are initialized by other nodes! */
if (sock->link)
@@ -111,49 +129,37 @@ static struct bNodeStack *setup_stack(bNodeStack *stack, bNodeSocket *sock)
ns->sockettype = sock->type;
- if (sock->default_value) {
- switch (sock->type) {
+ switch (sock->type) {
case SOCK_FLOAT:
- ns->vec[0] = ((bNodeSocketValueFloat *)sock->default_value)->value;
+ ns->vec[0] = node_socket_get_float(ntree, node, sock);
break;
case SOCK_VECTOR:
- copy_v3_v3(ns->vec, ((bNodeSocketValueVector *)sock->default_value)->value);
+ node_socket_get_vector(ntree, node, sock, ns->vec);
break;
case SOCK_RGBA:
- copy_v4_v4(ns->vec, ((bNodeSocketValueRGBA *)sock->default_value)->value);
+ node_socket_get_color(ntree, node, sock, ns->vec);
break;
- }
- }
- else {
- switch (sock->type) {
- case SOCK_FLOAT:
- ns->vec[0] = 0.0f;
- break;
- case SOCK_VECTOR:
- copy_v3_v3(ns->vec, null_value);
- break;
- case SOCK_RGBA:
- copy_v4_v4(ns->vec, null_value);
- break;
- }
}
return ns;
}
-bNodeTreeExec *ntree_exec_begin(bNodeTree *ntree)
+bNodeTreeExec *ntree_exec_begin(bNodeExecContext *context, bNodeTree *ntree, bNodeInstanceKey parent_key)
{
bNodeTreeExec *exec;
bNode *node;
bNodeExec *nodeexec;
- bNodeSocket *sock, *gsock;
+ bNodeInstanceKey nodekey;
+ bNodeSocket *sock;
bNodeStack *ns;
int index;
bNode **nodelist;
int totnodes, n;
- if ((ntree->init & NTREE_TYPE_INIT)==0)
- ntreeInitTypes(ntree);
+ BLI_assert(ntreeIsValid(ntree));
+
+ /* ensure all sock->link pointers and node levels are correct */
+ ntreeUpdateTree(ntree);
/* get a dependency-sorted list of nodes */
ntreeGetDependencyList(ntree, &nodelist, &totnodes);
@@ -165,9 +171,6 @@ bNodeTreeExec *ntree_exec_begin(bNodeTree *ntree)
/* set stack indices */
index = 0;
- /* group inputs essentially work as outputs */
- for (gsock=ntree->inputs.first; gsock; gsock = gsock->next)
- node_init_output_index(gsock, &index, NULL);
for (n=0; n < totnodes; ++n) {
node = nodelist[n];
@@ -186,9 +189,6 @@ bNodeTreeExec *ntree_exec_begin(bNodeTree *ntree)
node_init_output_index(sock, &index, NULL);
}
}
- /* group outputs essentially work as inputs */
- for (gsock=ntree->outputs.first; gsock; gsock = gsock->next)
- node_init_input_index(gsock, &index);
/* allocated exec data pointers for nodes */
exec->totnodes = totnodes;
@@ -201,11 +201,7 @@ bNodeTreeExec *ntree_exec_begin(bNodeTree *ntree)
for (n=0; n < exec->stacksize; ++n)
exec->stack[n].hasinput = 1;
- /* prepare group tree inputs */
- for (sock=ntree->inputs.first; sock; sock=sock->next) {
- /* ns = */ setup_stack(exec->stack, sock);
- }
- /* prepare all internal nodes for execution */
+ /* prepare all nodes for execution */
for (n=0, nodeexec= exec->nodeexec; n < totnodes; ++n, ++nodeexec) {
node = nodeexec->node = nodelist[n];
@@ -215,22 +211,20 @@ bNodeTreeExec *ntree_exec_begin(bNodeTree *ntree)
if (sock->link && !(sock->link->flag & NODE_LINK_VALID))
node->need_exec= 0;
- ns = setup_stack(exec->stack, sock);
- ns->hasoutput = 1;
+ ns = setup_stack(exec->stack, ntree, node, sock);
+ if (ns)
+ ns->hasoutput = 1;
}
/* tag all outputs */
for (sock=node->outputs.first; sock; sock=sock->next) {
- /* ns = */ setup_stack(exec->stack, sock);
+ /* ns = */ setup_stack(exec->stack, ntree, node, sock);
}
+ nodekey = BKE_node_instance_key(parent_key, ntree, node);
+ nodeexec->data.preview = context->previews ? BKE_node_instance_hash_lookup(context->previews, nodekey) : NULL;
if (node->typeinfo->initexecfunc)
- nodeexec->data = node->typeinfo->initexecfunc(node);
- }
- /* prepare group tree outputs */
- for (sock=ntree->outputs.first; sock; sock=sock->next) {
- ns = setup_stack(exec->stack, sock);
- ns->hasoutput = 1;
+ nodeexec->data.data = node->typeinfo->initexecfunc(context, node, nodekey);
}
if (nodelist)
@@ -250,7 +244,7 @@ void ntree_exec_end(bNodeTreeExec *exec)
for (n=0, nodeexec= exec->nodeexec; n < exec->totnodes; ++n, ++nodeexec) {
if (nodeexec->node->typeinfo)
if (nodeexec->node->typeinfo->freeexecfunc)
- nodeexec->node->typeinfo->freeexecfunc(nodeexec->node, nodeexec->data);
+ nodeexec->node->typeinfo->freeexecfunc(nodeexec->node, nodeexec->data.data);
}
if (exec->nodeexec)
@@ -309,9 +303,7 @@ bool ntreeExecThreadNodes(bNodeTreeExec *exec, bNodeThreadStack *nts, void *call
// if (node->typeinfo->compatibility == NODE_NEW_SHADING)
// return false;
if (node->typeinfo->execfunc)
- node->typeinfo->execfunc(callerdata, node, nsin, nsout);
- else if (node->typeinfo->newexecfunc)
- node->typeinfo->newexecfunc(callerdata, thread, node, nodeexec->data, nsin, nsout);
+ node->typeinfo->execfunc(callerdata, thread, node, &nodeexec->data, nsin, nsout);
}
}
diff --git a/source/blender/nodes/intern/node_exec.h b/source/blender/nodes/intern/node_exec.h
index 5febda036e0..7d76ef34934 100644
--- a/source/blender/nodes/intern/node_exec.h
+++ b/source/blender/nodes/intern/node_exec.h
@@ -39,6 +39,8 @@
#include "BKE_node.h"
+#include "node_util.h"
+
#include "RNA_types.h"
struct bNodeTree;
@@ -48,20 +50,20 @@ struct bNodeStack;
/* Node execution data */
typedef struct bNodeExec {
struct bNode *node; /* backpointer to node */
- void *data; /* custom data storage */
+ bNodeExecData data;
} bNodeExec;
/* Execution Data for each instance of node tree execution */
typedef struct bNodeTreeExec {
struct bNodeTree *nodetree; /* backpointer to node tree */
- int totnodes; /* total node count */
+ int totnodes; /* total node count */
struct bNodeExec *nodeexec; /* per-node execution data */
int stacksize;
struct bNodeStack *stack; /* socket data stack */
/* only used by material and texture trees to keep one stack for each thread */
- ListBase *threadstack; /* one instance of the stack for each thread */
+ ListBase *threadstack; /* one instance of the stack for each thread */
} bNodeTreeExec;
/* stores one stack copy for each thread (material and texture trees) */
@@ -71,14 +73,22 @@ typedef struct bNodeThreadStack {
int used;
} bNodeThreadStack;
+int node_exec_socket_use_stack(struct bNodeSocket *sock);
+
struct bNodeStack *node_get_socket_stack(struct bNodeStack *stack, struct bNodeSocket *sock);
void node_get_stack(struct bNode *node, struct bNodeStack *stack, struct bNodeStack **in, struct bNodeStack **out);
-struct bNodeTreeExec *ntree_exec_begin(struct bNodeTree *ntree);
+struct bNodeTreeExec *ntree_exec_begin(struct bNodeExecContext *context, struct bNodeTree *ntree, bNodeInstanceKey parent_key);
void ntree_exec_end(struct bNodeTreeExec *exec);
struct bNodeThreadStack *ntreeGetThreadStack(struct bNodeTreeExec *exec, int thread);
void ntreeReleaseThreadStack(struct bNodeThreadStack *nts);
bool ntreeExecThreadNodes(struct bNodeTreeExec *exec, struct bNodeThreadStack *nts, void *callerdata, int thread);
+struct bNodeTreeExec *ntreeShaderBeginExecTree_internal(struct bNodeExecContext *context, struct bNodeTree *ntree, bNodeInstanceKey parent_key);
+void ntreeShaderEndExecTree_internal(struct bNodeTreeExec *exec);
+
+struct bNodeTreeExec *ntreeTexBeginExecTree_internal(struct bNodeExecContext *context, struct bNodeTree *ntree, bNodeInstanceKey parent_key);
+void ntreeTexEndExecTree_internal(struct bNodeTreeExec *exec);
+
#endif
diff --git a/source/blender/nodes/intern/node_socket.c b/source/blender/nodes/intern/node_socket.c
index 69256fafc3d..68ae8fa87b3 100644
--- a/source/blender/nodes/intern/node_socket.c
+++ b/source/blender/nodes/intern/node_socket.c
@@ -33,547 +33,95 @@
#include "DNA_node_types.h"
-#include "DNA_mesh_types.h"
-#include "DNA_meshdata_types.h"
-#include "DNA_object_types.h"
-#include "DNA_scene_types.h"
-
#include "BLI_listbase.h"
#include "BLI_math.h"
+#include "BLI_string.h"
#include "BLI_utildefines.h"
#include "BLI_string.h"
-#include "BKE_DerivedMesh.h"
#include "BKE_node.h"
+#include "BKE_idprop.h"
#include "RNA_access.h"
+#include "RNA_define.h"
#include "RNA_types.h"
#include "MEM_guardedalloc.h"
#include "NOD_socket.h"
-/****************** FLOAT ******************/
-
-static bNodeSocketType node_socket_type_float = {
- /* type */ SOCK_FLOAT,
- /* ui_name */ "Float",
- /* ui_description */ "Floating Point",
- /* ui_icon */ 0,
- /* ui_color */ {160, 160, 160, 255},
-
- /* value_structname */ "bNodeSocketValueFloat",
- /* value_structsize */ sizeof(bNodeSocketValueFloat),
-
- /* buttonfunc */ NULL,
-};
-
-/****************** VECTOR ******************/
-
-static bNodeSocketType node_socket_type_vector = {
- /* type */ SOCK_VECTOR,
- /* ui_name */ "Vector",
- /* ui_description */ "3-dimensional floating point vector",
- /* ui_icon */ 0,
- /* ui_color */ {100, 100, 200, 255},
-
- /* value_structname */ "bNodeSocketValueVector",
- /* value_structsize */ sizeof(bNodeSocketValueVector),
-
- /* buttonfunc */ NULL,
-};
-
-/****************** RGBA ******************/
-
-static bNodeSocketType node_socket_type_rgba = {
- /* type */ SOCK_RGBA,
- /* ui_name */ "RGBA",
- /* ui_description */ "RGBA color",
- /* ui_icon */ 0,
- /* ui_color */ {200, 200, 40, 255},
-
- /* value_structname */ "bNodeSocketValueRGBA",
- /* value_structsize */ sizeof(bNodeSocketValueRGBA),
-
- /* buttonfunc */ NULL,
-};
-
-/****************** INT ******************/
-
-static bNodeSocketType node_socket_type_int = {
- /* type */ SOCK_INT,
- /* ui_name */ "Int",
- /* ui_description */ "Integer",
- /* ui_icon */ 0,
- /* ui_color */ {17, 133, 37, 255},
-
- /* value_structname */ "bNodeSocketValueInt",
- /* value_structsize */ sizeof(bNodeSocketValueInt),
-
- /* buttonfunc */ NULL,
-};
-
-/****************** BOOLEAN ******************/
-
-static bNodeSocketType node_socket_type_boolean = {
- /* type */ SOCK_BOOLEAN,
- /* ui_name */ "Boolean",
- /* ui_description */ "Boolean",
- /* ui_icon */ 0,
- /* ui_color */ {158, 139, 63, 255},
-
- /* value_structname */ "bNodeSocketValueBoolean",
- /* value_structsize */ sizeof(bNodeSocketValueBoolean),
-
- /* buttonfunc */ NULL,
-};
-
-/****************** SHADER ******************/
-
-static bNodeSocketType node_socket_type_shader = {
- /* type */ SOCK_SHADER,
- /* ui_name */ "Shader",
- /* ui_description */ "Shader",
- /* ui_icon */ 0,
- /* ui_color */ {100, 200, 100, 255},
-
- /* value_structname */ NULL,
- /* value_structsize */ 0,
-
- /* buttonfunc */ NULL,
-};
-
-/****************** MESH ******************/
-
-static bNodeSocketType node_socket_type_mesh = {
- /* type */ SOCK_MESH,
- /* ui_name */ "Mesh",
- /* ui_description */ "Mesh geometry data",
- /* ui_icon */ 0,
- /* ui_color */ {255, 133, 7, 255},
-
- /* value_structname */ NULL,
- /* value_structsize */ 0,
-
- /* buttonfunc */ NULL,
-};
+struct Main;
-/****************** STRING ******************/
-
-static bNodeSocketType node_socket_type_string = {
- /* type */ SOCK_STRING,
- /* ui_name */ "String",
- /* ui_description */ "String",
- /* ui_icon */ 0,
- /* ui_color */ {255, 255, 255, 255},
-
- /* value_structname */ "bNodeSocketValueString",
- /* value_structsize */ sizeof(bNodeSocketValueString),
-
- /* buttonfunc */ NULL,
-};
-
-void node_socket_type_init(bNodeSocketType *types[])
+struct bNodeSocket *node_add_socket_from_template(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocketTemplate *stemp, int in_out)
{
- #define INIT_TYPE(name) types[node_socket_type_##name.type] = &node_socket_type_##name
+ bNodeSocket *sock = nodeAddStaticSocket(ntree, node, in_out, stemp->type, stemp->subtype, stemp->identifier, stemp->name);
- INIT_TYPE(float);
- INIT_TYPE(vector);
- INIT_TYPE(rgba);
- INIT_TYPE(int);
- INIT_TYPE(boolean);
- INIT_TYPE(shader);
- INIT_TYPE(mesh);
- INIT_TYPE(string);
+ sock->flag |= stemp->flag;
- #undef INIT_TYPE
-}
-
-void *node_socket_make_default_value(int type)
-{
- /* XXX currently just allocates from stype->structsize.
- * it might become necessary to do more complex allocations for later types.
- */
- bNodeSocketType *stype = ntreeGetSocketType(type);
- if (stype->value_structsize > 0) {
- void *default_value = MEM_callocN(stype->value_structsize, "default socket value");
- return default_value;
- }
- else
- return NULL;
-}
-
-void node_socket_free_default_value(int UNUSED(type), void *default_value)
-{
- /* XXX can just free the pointee for all current socket types. */
- if (default_value)
- MEM_freeN(default_value);
-}
-
-void node_socket_init_default_value(int type, void *default_value)
-{
- switch (type) {
- case SOCK_FLOAT:
- node_socket_set_default_value_float(default_value, PROP_NONE, 0.0f, -FLT_MAX, FLT_MAX);
- break;
- case SOCK_INT:
- node_socket_set_default_value_int(default_value, PROP_NONE, 0, INT_MIN, INT_MAX);
- break;
- case SOCK_BOOLEAN:
- node_socket_set_default_value_boolean(default_value, FALSE);
- break;
- case SOCK_VECTOR:
- node_socket_set_default_value_vector(default_value, PROP_NONE, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX);
- break;
- case SOCK_RGBA:
- node_socket_set_default_value_rgba(default_value, 0.0f, 0.0f, 0.0f, 1.0f);
- break;
- case SOCK_SHADER:
- node_socket_set_default_value_shader(default_value);
- break;
- case SOCK_MESH:
- node_socket_set_default_value_mesh(default_value);
- break;
- case SOCK_STRING:
- node_socket_set_default_value_string(default_value, PROP_NONE, (char *)"");
- break;
- }
-}
-
-void node_socket_set_default_value_int(void *default_value, PropertySubType subtype, int value, int min, int max)
-{
- bNodeSocketValueInt *val = default_value;
- val->subtype = subtype;
- val->value = value;
- val->min = min;
- val->max = max;
-}
-
-void node_socket_set_default_value_float(void *default_value, PropertySubType subtype, float value, float min, float max)
-{
- bNodeSocketValueFloat *val = default_value;
- val->subtype = subtype;
- val->value = value;
- val->min = min;
- val->max = max;
-}
-
-void node_socket_set_default_value_boolean(void *default_value, char value)
-{
- bNodeSocketValueBoolean *val = default_value;
- val->value = value;
-}
-
-void node_socket_set_default_value_vector(void *default_value, PropertySubType subtype, float x, float y, float z, float min, float max)
-{
- bNodeSocketValueVector *val = default_value;
- val->subtype = subtype;
- val->value[0] = x;
- val->value[1] = y;
- val->value[2] = z;
- val->min = min;
- val->max = max;
-}
-
-void node_socket_set_default_value_rgba(void *default_value, float r, float g, float b, float a)
-{
- bNodeSocketValueRGBA *val = default_value;
- val->value[0] = r;
- val->value[1] = g;
- val->value[2] = b;
- val->value[3] = a;
-}
-
-void node_socket_set_default_value_string(void *default_value, PropertySubType subtype, const char *value)
-{
- bNodeSocketValueString *val = default_value;
- val->subtype = subtype;
- BLI_strncpy(val->value, value, 1024);//FILE_MAX
-}
-
-void node_socket_set_default_value_shader(void *UNUSED(default_value))
-{
-}
-
-void node_socket_set_default_value_mesh(void *UNUSED(default_value))
-{
-}
-
-
-void node_socket_copy_default_value(int type, void *to_default_value, void *from_default_value)
-{
- /* XXX only one of these pointers is valid! just putting them here for convenience */
- bNodeSocketValueFloat *fromfloat= (bNodeSocketValueFloat*)from_default_value;
- bNodeSocketValueInt *fromint= (bNodeSocketValueInt*)from_default_value;
- bNodeSocketValueBoolean *frombool= (bNodeSocketValueBoolean*)from_default_value;
- bNodeSocketValueVector *fromvector= (bNodeSocketValueVector*)from_default_value;
- bNodeSocketValueRGBA *fromrgba= (bNodeSocketValueRGBA*)from_default_value;
- bNodeSocketValueString *fromstring= (bNodeSocketValueString*)from_default_value;
-
- bNodeSocketValueFloat *tofloat= (bNodeSocketValueFloat*)to_default_value;
- bNodeSocketValueInt *toint= (bNodeSocketValueInt*)to_default_value;
- bNodeSocketValueBoolean *tobool= (bNodeSocketValueBoolean*)to_default_value;
- bNodeSocketValueVector *tovector= (bNodeSocketValueVector*)to_default_value;
- bNodeSocketValueRGBA *torgba= (bNodeSocketValueRGBA*)to_default_value;
- bNodeSocketValueString *tostring= (bNodeSocketValueString*)to_default_value;
-
- switch (type) {
- case SOCK_FLOAT:
- *tofloat = *fromfloat;
- break;
- case SOCK_INT:
- *toint = *fromint;
- break;
- case SOCK_BOOLEAN:
- *tobool = *frombool;
- break;
- case SOCK_VECTOR:
- *tovector = *fromvector;
- break;
- case SOCK_RGBA:
- *torgba = *fromrgba;
- break;
- case SOCK_STRING:
- *tostring = *fromstring;
- break;
- }
-}
-
-/* XXX This is a makeshift function to have useful initial group socket values.
- * In the end this should be implemented by a flexible socket data conversion system,
- * which is yet to be implemented. The idea is that beside default standard conversions,
- * such as int-to-float, it should be possible to quickly select a conversion method or
- * a chain of conversions for each input, whenever there is more than one option.
- * E.g. a vector-to-float conversion could use either of the x/y/z components or
- * the vector length.
- *
- * In the interface this could be implemented by a pseudo-script textbox on linked inputs,
- * with quick selection from a predefined list of conversion options. Some Examples:
- * - vector component 'z' (vector->float): "z"
- * - grayscale color (float->color): "gray"
- * - color luminance (color->float): "lum"
- * - matrix column 2 length (matrix->vector->float): "col[1].len"
- * - mesh vertex coordinate 'y' (mesh->vertex->vector->float): "vertex.co.y"
- *
- * The actual conversion is then done by a series of conversion functions,
- * which are defined in the socket type structs.
- */
-void node_socket_convert_default_value(int to_type, void *to_default_value, int from_type, void *from_default_value)
-{
- /* XXX only one of these pointers is valid! just putting them here for convenience */
- bNodeSocketValueFloat *fromfloat= (bNodeSocketValueFloat*)from_default_value;
- bNodeSocketValueInt *fromint= (bNodeSocketValueInt*)from_default_value;
- bNodeSocketValueBoolean *frombool= (bNodeSocketValueBoolean*)from_default_value;
- bNodeSocketValueVector *fromvector= (bNodeSocketValueVector*)from_default_value;
- bNodeSocketValueRGBA *fromrgba= (bNodeSocketValueRGBA*)from_default_value;
-
- bNodeSocketValueFloat *tofloat= (bNodeSocketValueFloat*)to_default_value;
- bNodeSocketValueInt *toint= (bNodeSocketValueInt*)to_default_value;
- bNodeSocketValueBoolean *tobool= (bNodeSocketValueBoolean*)to_default_value;
- bNodeSocketValueVector *tovector= (bNodeSocketValueVector*)to_default_value;
- bNodeSocketValueRGBA *torgba= (bNodeSocketValueRGBA*)to_default_value;
-
- switch (from_type) {
- case SOCK_FLOAT:
- switch (to_type) {
- case SOCK_FLOAT:
- tofloat->value = fromfloat->value;
- break;
- case SOCK_INT:
- toint->value = (int)fromfloat->value;
- break;
- case SOCK_BOOLEAN:
- tobool->value = (fromfloat->value > 0.0f);
- break;
- case SOCK_VECTOR:
- tovector->value[0] = tovector->value[1] = tovector->value[2] = fromfloat->value;
- break;
- case SOCK_RGBA:
- torgba->value[0] = torgba->value[1] = torgba->value[2] = torgba->value[3] = fromfloat->value;
- break;
- }
- break;
- case SOCK_INT:
- switch (to_type) {
- case SOCK_FLOAT:
- tofloat->value = (float)fromint->value;
- break;
- case SOCK_INT:
- toint->value = fromint->value;
- break;
- case SOCK_BOOLEAN:
- tobool->value = (fromint->value > 0);
- break;
- case SOCK_VECTOR:
- tovector->value[0] = tovector->value[1] = tovector->value[2] = (float)fromint->value;
- break;
- case SOCK_RGBA:
- torgba->value[0] = torgba->value[1] = torgba->value[2] = torgba->value[3] = (float)fromint->value;
- break;
- }
- break;
- case SOCK_BOOLEAN:
- switch (to_type) {
- case SOCK_FLOAT:
- tofloat->value = (float)frombool->value;
- break;
- case SOCK_INT:
- toint->value = (int)frombool->value;
- break;
- case SOCK_BOOLEAN:
- tobool->value = frombool->value;
- break;
- case SOCK_VECTOR:
- tovector->value[0] = tovector->value[1] = tovector->value[2] = (float)frombool->value;
- break;
- case SOCK_RGBA:
- torgba->value[0] = torgba->value[1] = torgba->value[2] = torgba->value[3] = (float)frombool->value;
- break;
- }
- break;
- case SOCK_VECTOR:
- switch (to_type) {
- case SOCK_FLOAT:
- tofloat->value = fromvector->value[0];
- break;
- case SOCK_INT:
- toint->value = (int)fromvector->value[0];
- break;
- case SOCK_BOOLEAN:
- tobool->value = (fromvector->value[0] > 0.0f);
- break;
- case SOCK_VECTOR:
- copy_v3_v3(tovector->value, fromvector->value);
- break;
- case SOCK_RGBA:
- copy_v3_v3(torgba->value, fromvector->value);
- torgba->value[3] = 1.0f;
+ /* initialize default_value */
+ switch (stemp->type) {
+ case SOCK_FLOAT: {
+ bNodeSocketValueFloat *dval = sock->default_value;
+ dval->value = stemp->val1;
+ dval->min = stemp->min;
+ dval->max = stemp->max;
break;
}
- break;
- case SOCK_RGBA:
- switch (to_type) {
- case SOCK_FLOAT:
- tofloat->value = fromrgba->value[0];
- break;
- case SOCK_INT:
- toint->value = (int)fromrgba->value[0];
- break;
- case SOCK_BOOLEAN:
- tobool->value = (fromrgba->value[0] > 0.0f);
- break;
- case SOCK_VECTOR:
- copy_v3_v3(tovector->value, fromrgba->value);
- break;
- case SOCK_RGBA:
- copy_v4_v4(torgba->value, fromrgba->value);
+ case SOCK_INT: {
+ bNodeSocketValueInt *dval = sock->default_value;
+ dval->value = (int)stemp->val1;
+ dval->min = (int)stemp->min;
+ dval->max = (int)stemp->max;
break;
}
- break;
- }
-}
-
-static void node_socket_set_minmax_subtype(bNodeSocket *sock, struct bNodeSocketTemplate *stemp)
-{
- switch (sock->type) {
- case SOCK_FLOAT:
- {
- bNodeSocketValueFloat *dval= sock->default_value;
- dval->min = stemp->min;
- dval->max = stemp->max;
- dval->subtype = stemp->subtype;
+ case SOCK_BOOLEAN: {
+ bNodeSocketValueBoolean *dval = sock->default_value;
+ dval->value = (int)stemp->val1;
break;
}
- case SOCK_INT:
- {
- bNodeSocketValueInt *dval= sock->default_value;
+ case SOCK_VECTOR: {
+ bNodeSocketValueVector *dval = sock->default_value;
+ dval->value[0] = stemp->val1;
+ dval->value[1] = stemp->val2;
+ dval->value[2] = stemp->val3;
dval->min = stemp->min;
dval->max = stemp->max;
- dval->subtype = stemp->subtype;
break;
}
- case SOCK_VECTOR:
- {
- bNodeSocketValueVector *dval= sock->default_value;
- dval->min = stemp->min;
- dval->max = stemp->max;
- dval->subtype = stemp->subtype;
+ case SOCK_RGBA: {
+ bNodeSocketValueRGBA *dval = sock->default_value;
+ dval->value[0] = stemp->val1;
+ dval->value[1] = stemp->val2;
+ dval->value[2] = stemp->val3;
+ dval->value[3] = stemp->val4;
break;
}
}
-}
-
-struct bNodeSocket *node_add_input_from_template(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocketTemplate *stemp)
-{
- bNodeSocket *sock = nodeAddSocket(ntree, node, SOCK_IN, stemp->name, stemp->type);
- sock->flag |= stemp->flag;
-
- switch (stemp->type) {
- case SOCK_INT:
- node_socket_set_default_value_int(sock->default_value, stemp->subtype, (int)stemp->val1, (int)stemp->min, (int)stemp->max);
- break;
- case SOCK_FLOAT:
- node_socket_set_default_value_float(sock->default_value, stemp->subtype, stemp->val1, stemp->min, stemp->max);
- break;
- case SOCK_BOOLEAN:
- node_socket_set_default_value_boolean(sock->default_value, (char)stemp->val1);
- break;
- case SOCK_VECTOR:
- node_socket_set_default_value_vector(sock->default_value, stemp->subtype, stemp->val1, stemp->val2, stemp->val3, stemp->min, stemp->max);
- break;
- case SOCK_RGBA:
- node_socket_set_default_value_rgba(sock->default_value, stemp->val1, stemp->val2, stemp->val3, stemp->val4);
- break;
- case SOCK_SHADER:
- node_socket_set_default_value_shader(sock->default_value);
- break;
- case SOCK_MESH:
- node_socket_set_default_value_mesh(sock->default_value);
- break;
- case SOCK_STRING:
- node_socket_set_default_value_string(sock->default_value, stemp->subtype, (char *)"");
- break;
- }
return sock;
}
-struct bNodeSocket *node_add_output_from_template(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocketTemplate *stemp)
-{
- bNodeSocket *sock = nodeAddSocket(ntree, node, SOCK_OUT, stemp->name, stemp->type);
- node_socket_set_minmax_subtype(sock, stemp);
- return sock;
-}
-
static bNodeSocket *verify_socket_template(bNodeTree *ntree, bNode *node, int in_out, ListBase *socklist, bNodeSocketTemplate *stemp)
{
bNodeSocket *sock;
for (sock= socklist->first; sock; sock= sock->next) {
- if (!(sock->flag & SOCK_DYNAMIC) && strncmp(sock->name, stemp->name, NODE_MAXSTR)==0)
+ if (strncmp(sock->name, stemp->name, NODE_MAXSTR)==0)
break;
}
if (sock) {
- sock->type = stemp->type; /* in future, read this from tydefs! */
+ sock->type = stemp->type;
if (stemp->limit == 0) sock->limit= 0xFFF;
else sock->limit = stemp->limit;
sock->flag |= stemp->flag;
- /* Copy the property range and subtype parameters in case the template changed.
- * NOT copying the actual value here, only button behavior changes!
- */
- node_socket_set_minmax_subtype(sock, stemp);
-
BLI_remlink(socklist, sock);
return sock;
}
else {
/* no socket for this template found, make a new one */
- if (in_out==SOCK_IN)
- sock = node_add_input_from_template(ntree, node, stemp);
- else
- sock = node_add_output_from_template(ntree, node, stemp);
+ sock = node_add_socket_from_template(ntree, node, stemp, in_out);
/* remove the new socket from the node socket list first,
* will be added back after verification.
*/
@@ -592,8 +140,7 @@ static void verify_socket_template_list(bNodeTree *ntree, bNode *node, int in_ou
if (stemp_first==NULL) {
for (sock = (bNodeSocket*)socklist->first; sock; sock=nextsock) {
nextsock = sock->next;
- if (!(sock->flag & SOCK_DYNAMIC))
- nodeRemoveSocket(ntree, node, sock);
+ nodeRemoveSocket(ntree, node, sock);
}
}
else {
@@ -606,8 +153,7 @@ static void verify_socket_template_list(bNodeTree *ntree, bNode *node, int in_ou
/* leftovers are removed */
for (sock = (bNodeSocket*)socklist->first; sock; sock=nextsock) {
nextsock = sock->next;
- if (!(sock->flag & SOCK_DYNAMIC))
- nodeRemoveSocket(ntree, node, sock);
+ nodeRemoveSocket(ntree, node, sock);
}
/* and we put back the verified sockets */
@@ -635,14 +181,182 @@ static void verify_socket_template_list(bNodeTree *ntree, bNode *node, int in_ou
void node_verify_socket_templates(bNodeTree *ntree, bNode *node)
{
bNodeType *ntype= node->typeinfo;
- /* XXX Small trick: don't try to match socket lists when there are no templates.
- * This also prevents group node sockets from being removed, without the need to explicitly
+ /* Don't try to match socket lists when there are no templates.
+ * This prevents group node sockets from being removed, without the need to explicitly
* check the node type here.
*/
- if (ntype && ((ntype->inputs && ntype->inputs[0].type >= 0) ||
- (ntype->outputs && ntype->outputs[0].type >= 0)))
- {
- verify_socket_template_list(ntree, node, SOCK_IN, &node->inputs, ntype->inputs);
- verify_socket_template_list(ntree, node, SOCK_OUT, &node->outputs, ntype->outputs);
+ if (ntype) {
+ if (ntype->inputs && ntype->inputs[0].type >= 0)
+ verify_socket_template_list(ntree, node, SOCK_IN, &node->inputs, ntype->inputs);
+ if (ntype->outputs && ntype->outputs[0].type >= 0)
+ verify_socket_template_list(ntree, node, SOCK_OUT, &node->outputs, ntype->outputs);
+ }
+}
+
+
+void node_socket_init_default_value(bNodeSocket *sock)
+{
+ int type = sock->typeinfo->type;
+ int subtype = sock->typeinfo->subtype;
+
+ if (sock->default_value)
+ return; /* already initialized */
+
+ switch (type) {
+ case SOCK_FLOAT: {
+ bNodeSocketValueFloat *dval = MEM_callocN(sizeof(bNodeSocketValueFloat), "node socket value float");
+ dval->subtype = subtype;
+ dval->value = 0.0f;
+ dval->min = -FLT_MAX;
+ dval->max = FLT_MAX;
+
+ sock->default_value = dval;
+ break;
+ }
+ case SOCK_INT: {
+ bNodeSocketValueInt *dval = MEM_callocN(sizeof(bNodeSocketValueInt), "node socket value int");
+ dval->subtype = subtype;
+ dval->value = 0;
+ dval->min = INT_MIN;
+ dval->max = INT_MAX;
+
+ sock->default_value = dval;
+ break;
+ }
+ case SOCK_BOOLEAN: {
+ bNodeSocketValueBoolean *dval = MEM_callocN(sizeof(bNodeSocketValueBoolean), "node socket value bool");
+ dval->value = false;
+
+ sock->default_value = dval;
+ break;
+ }
+ case SOCK_VECTOR: {
+ bNodeSocketValueVector *dval = MEM_callocN(sizeof(bNodeSocketValueVector), "node socket value vector");
+ dval->subtype = subtype;
+ copy_v3_v3(dval->value, (float[]){0.0f, 0.0f, 0.0f});
+ dval->min = -FLT_MAX;
+ dval->max = FLT_MAX;
+
+ sock->default_value = dval;
+ break;
}
+ case SOCK_RGBA: {
+ bNodeSocketValueRGBA *dval = MEM_callocN(sizeof(bNodeSocketValueRGBA), "node socket value color");
+ copy_v4_v4(dval->value, (float[]){0.0f, 0.0f, 0.0f, 1.0f});
+
+ sock->default_value = dval;
+ break;
+ }
+ case SOCK_STRING: {
+ bNodeSocketValueString *dval = MEM_callocN(sizeof(bNodeSocketValueString), "node socket value string");
+ dval->subtype = subtype;
+ dval->value[0] = '\0';
+
+ sock->default_value = dval;
+ break;
+ }
+ }
+}
+
+
+static void standard_node_socket_interface_init_socket(bNodeTree *UNUSED(ntree), bNodeSocket *UNUSED(stemp), bNode *UNUSED(node), bNodeSocket *sock, const char *UNUSED(data_path))
+{
+ /* initialize the type value */
+ sock->type = sock->typeinfo->type;
+}
+
+static bNodeSocketType *make_standard_socket_type(int type, int subtype)
+{
+ extern void ED_init_standard_node_socket_type(bNodeSocketType *);
+
+ const char *socket_idname = nodeStaticSocketType(type, subtype);
+ const char *interface_idname = nodeStaticSocketInterfaceType(type, subtype);
+ bNodeSocketType *stype;
+ StructRNA *srna;
+
+ stype = MEM_callocN(sizeof(bNodeSocketType), "node socket C type");
+ BLI_strncpy(stype->idname, socket_idname, sizeof(stype->idname));
+
+ /* set the RNA type
+ * uses the exact same identifier as the socket type idname */
+ srna = stype->ext_socket.srna = RNA_struct_find(socket_idname);
+ BLI_assert(srna != NULL);
+ /* associate the RNA type with the socket type */
+ RNA_struct_blender_type_set(srna, stype);
+
+ /* set the interface RNA type */
+ srna = stype->ext_interface.srna = RNA_struct_find(interface_idname);
+ BLI_assert(srna != NULL);
+ /* associate the RNA type with the socket type */
+ RNA_struct_blender_type_set(srna, stype);
+
+ /* extra type info for standard socket types */
+ stype->type = type;
+ stype->subtype = subtype;
+
+ /* XXX bad-level call! needed for setting draw callbacks */
+ ED_init_standard_node_socket_type(stype);
+
+ stype->interface_init_socket = standard_node_socket_interface_init_socket;
+
+ return stype;
+}
+
+static bNodeSocketType *make_socket_type_virtual(void)
+{
+ extern void ED_init_node_socket_type_virtual(bNodeSocketType *);
+
+ const char *socket_idname = "NodeSocketVirtual";
+ bNodeSocketType *stype;
+ StructRNA *srna;
+
+ stype = MEM_callocN(sizeof(bNodeSocketType), "node socket C type");
+ BLI_strncpy(stype->idname, socket_idname, sizeof(stype->idname));
+
+ /* set the RNA type
+ * uses the exact same identifier as the socket type idname */
+ srna = stype->ext_socket.srna = RNA_struct_find(socket_idname);
+ BLI_assert(srna != NULL);
+ /* associate the RNA type with the socket type */
+ RNA_struct_blender_type_set(srna, stype);
+
+ ED_init_node_socket_type_virtual(stype);
+
+ return stype;
+}
+
+
+void register_standard_node_socket_types()
+{
+ /* draw callbacks are set in drawnode.c to avoid bad-level calls */
+
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_FLOAT, PROP_NONE));
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_FLOAT, PROP_UNSIGNED));
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_FLOAT, PROP_PERCENTAGE));
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_FLOAT, PROP_FACTOR));
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_FLOAT, PROP_ANGLE));
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_FLOAT, PROP_TIME));
+
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_INT, PROP_NONE));
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_INT, PROP_UNSIGNED));
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_INT, PROP_PERCENTAGE));
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_INT, PROP_FACTOR));
+
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_BOOLEAN, PROP_NONE));
+
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_VECTOR, PROP_NONE));
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_VECTOR, PROP_TRANSLATION));
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_VECTOR, PROP_DIRECTION));
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_VECTOR, PROP_VELOCITY));
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_VECTOR, PROP_ACCELERATION));
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_VECTOR, PROP_EULER));
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_VECTOR, PROP_XYZ));
+
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_RGBA, PROP_NONE));
+
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_STRING, PROP_NONE));
+
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_SHADER, PROP_NONE));
+
+ nodeRegisterSocketType(make_socket_type_virtual());
}
diff --git a/source/blender/nodes/intern/node_util.c b/source/blender/nodes/intern/node_util.c
index 09e6ddd18a5..c622c1c5227 100644
--- a/source/blender/nodes/intern/node_util.c
+++ b/source/blender/nodes/intern/node_util.c
@@ -30,6 +30,7 @@
*/
#include <limits.h>
+#include <string.h>
#include "DNA_action_types.h"
#include "DNA_node_types.h"
@@ -63,17 +64,17 @@ void node_free_standard_storage(bNode *node)
}
}
-void node_copy_curves(bNode *orig_node, bNode *new_node)
+void node_copy_curves(bNodeTree *UNUSED(dest_ntree), bNode *dest_node, bNode *src_node)
{
- new_node->storage = curvemapping_copy(orig_node->storage);
+ dest_node->storage = curvemapping_copy(src_node->storage);
}
-void node_copy_standard_storage(bNode *orig_node, bNode *new_node)
+void node_copy_standard_storage(bNodeTree *UNUSED(dest_ntree), bNode *dest_node, bNode *src_node)
{
- new_node->storage = MEM_dupallocN(orig_node->storage);
+ dest_node->storage = MEM_dupallocN(src_node->storage);
}
-void *node_initexec_curves(bNode *node)
+void *node_initexec_curves(bNodeExecContext *UNUSED(context), bNode *node, bNodeInstanceKey UNUSED(key))
{
curvemapping_initialize(node->storage);
return NULL; /* unused return */
@@ -129,6 +130,8 @@ void node_update_internal_links_default(bNodeTree *ntree, bNode *node)
fromindex = INT_MAX;
fromsock = NULL;
for (link=ntree->links.first; link; link=link->next) {
+ if (nodeLinkIsHidden(link))
+ continue;
if (link->tonode == node && link->tosock->type == datatype) {
int index = BLI_findindex(&node->inputs, link->tosock);
if (index < fromindex) {
@@ -146,6 +149,8 @@ void node_update_internal_links_default(bNodeTree *ntree, bNode *node)
toindex = INT_MAX;
tosock = NULL;
for (link=ntree->links.first; link; link=link->next) {
+ if (nodeLinkIsHidden(link))
+ continue;
if (link->fromnode == node && link->fromsock->type == datatype) {
int index = BLI_findindex(&node->outputs, link->fromsock);
if (index < toindex) {
@@ -188,3 +193,45 @@ void node_update_internal_links_default(bNodeTree *ntree, bNode *node)
BLI_addtail(&node->internal_links, ilink);
}
}
+
+float node_socket_get_float(bNodeTree *ntree, bNode *UNUSED(node), bNodeSocket *sock)
+{
+ PointerRNA ptr;
+ RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr);
+ return RNA_float_get(&ptr, "default_value");
+}
+
+void node_socket_set_float(bNodeTree *ntree, bNode *UNUSED(node), bNodeSocket *sock, float value)
+{
+ PointerRNA ptr;
+ RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr);
+ RNA_float_set(&ptr, "default_value", value);
+}
+
+void node_socket_get_color(bNodeTree *ntree, bNode *UNUSED(node), bNodeSocket *sock, float *value)
+{
+ PointerRNA ptr;
+ RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr);
+ RNA_float_get_array(&ptr, "default_value", value);
+}
+
+void node_socket_set_color(bNodeTree *ntree, bNode *UNUSED(node), bNodeSocket *sock, const float *value)
+{
+ PointerRNA ptr;
+ RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr);
+ RNA_float_set_array(&ptr, "default_value", value);
+}
+
+void node_socket_get_vector(bNodeTree *ntree, bNode *UNUSED(node), bNodeSocket *sock, float *value)
+{
+ PointerRNA ptr;
+ RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr);
+ RNA_float_get_array(&ptr, "default_value", value);
+}
+
+void node_socket_set_vector(bNodeTree *ntree, bNode *UNUSED(node), bNodeSocket *sock, const float *value)
+{
+ PointerRNA ptr;
+ RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr);
+ RNA_float_set_array(&ptr, "default_value", value);
+}
diff --git a/source/blender/nodes/intern/node_util.h b/source/blender/nodes/intern/node_util.h
index 6b783915816..2b3f84420f9 100644
--- a/source/blender/nodes/intern/node_util.h
+++ b/source/blender/nodes/intern/node_util.h
@@ -35,6 +35,8 @@
#include "DNA_listBase.h"
+#include "BLI_utildefines.h"
+
#include "BKE_node.h"
#include "MEM_guardedalloc.h"
@@ -43,17 +45,29 @@
#include "GPU_material.h" /* For Shader muting GPU code... */
+#include "RNA_access.h"
+
struct bNodeTree;
struct bNode;
+/* data for initializing node execution */
+typedef struct bNodeExecContext {
+ struct bNodeInstanceHash *previews;
+} bNodeExecContext;
+
+typedef struct bNodeExecData {
+ void *data; /* custom data storage */
+ struct bNodePreview *preview; /* optional preview image */
+} bNodeExecData;
+
/**** Storage Data ****/
extern void node_free_curves(struct bNode *node);
extern void node_free_standard_storage(struct bNode *node);
-extern void node_copy_curves(struct bNode *orig_node, struct bNode *new_node);
-extern void node_copy_standard_storage(struct bNode *orig_node, struct bNode *new_node);
-extern void *node_initexec_curves(struct bNode *node);
+extern void node_copy_curves(struct bNodeTree *dest_ntree, struct bNode *dest_node, struct bNode *src_node);
+extern void node_copy_standard_storage(struct bNodeTree *dest_ntree, struct bNode *dest_node, struct bNode *src_node);
+extern void *node_initexec_curves(struct bNodeExecContext *context, struct bNode *node, bNodeInstanceKey key);
/**** Labels ****/
@@ -64,4 +78,11 @@ const char *node_filter_label(struct bNode *node);
void node_update_internal_links_default(struct bNodeTree *ntree, struct bNode *node);
+float node_socket_get_float(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *sock);
+void node_socket_set_float(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *sock, float value);
+void node_socket_get_color(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *sock, float *value);
+void node_socket_set_color(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *sock, const float *value);
+void node_socket_get_vector(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *sock, float *value);
+void node_socket_set_vector(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *sock, const float *value);
+
#endif
diff --git a/source/blender/nodes/shader/node_shader_tree.c b/source/blender/nodes/shader/node_shader_tree.c
index 8fde0b9c342..30da509c09d 100644
--- a/source/blender/nodes/shader/node_shader_tree.c
+++ b/source/blender/nodes/shader/node_shader_tree.c
@@ -36,6 +36,7 @@
#include "DNA_material_types.h"
#include "DNA_node_types.h"
#include "DNA_scene_types.h"
+#include "DNA_space_types.h"
#include "DNA_world_types.h"
#include "BLI_listbase.h"
@@ -45,11 +46,14 @@
#include "BLF_translation.h"
+#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_node.h"
#include "BKE_scene.h"
+#include "RNA_access.h"
+
#include "GPU_material.h"
#include "RE_shader_ext.h"
@@ -59,23 +63,45 @@
#include "node_util.h"
#include "node_shader_util.h"
-static void foreach_nodetree(Main *main, void *calldata, bNodeTreeCallback func)
+static int shader_tree_poll(const bContext *C, bNodeTreeType *UNUSED(treetype))
{
- Material *ma;
- Lamp *la;
- World *wo;
-
- for (ma = main->mat.first; ma; ma = ma->id.next)
- if (ma->nodetree)
- func(calldata, &ma->id, ma->nodetree);
-
- for (la = main->lamp.first; la; la = la->id.next)
- if (la->nodetree)
- func(calldata, &la->id, la->nodetree);
+ Scene *scene = CTX_data_scene(C);
+ /* allow empty engine string too, this is from older versions that didn't have registerable engines yet */
+ return (scene->r.engine[0] == '\0'
+ || strcmp(scene->r.engine, "BLENDER_RENDER")==0
+ || strcmp(scene->r.engine, "CYCLES")==0);
+}
- for (wo = main->world.first; wo; wo = wo->id.next)
- if (wo->nodetree)
- func(calldata, &wo->id, wo->nodetree);
+static void shader_get_from_context(const bContext *C, bNodeTreeType *UNUSED(treetype), bNodeTree **r_ntree, ID **r_id, ID **r_from)
+{
+ SpaceNode *snode = CTX_wm_space_node(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = OBACT;
+
+ if (snode->shaderfrom == SNODE_SHADER_OBJECT) {
+ if (ob) {
+ if (ob->type == OB_LAMP) {
+ *r_from = &ob->id;
+ *r_id = ob->data;
+ *r_ntree = ((Lamp *)ob->data)->nodetree;
+ }
+ else {
+ Material *ma = give_current_material(ob, ob->actcol);
+ if (ma) {
+ *r_from = &ob->id;
+ *r_id = &ma->id;
+ *r_ntree = ma->nodetree;
+ }
+ }
+ }
+ }
+ else { /* SNODE_SHADER_WORLD */
+ if (scene->world) {
+ *r_from = NULL;
+ *r_id = &scene->world->id;
+ *r_ntree = scene->world->nodetree;
+ }
+ }
}
static void foreach_nodeclass(Scene *scene, void *calldata, bNodeClassCallback func)
@@ -93,6 +119,7 @@ static void foreach_nodeclass(Scene *scene, void *calldata, bNodeClassCallback f
func(calldata, NODE_CLASS_CONVERTOR, N_("Convertor"));
func(calldata, NODE_CLASS_SCRIPT, N_("Script"));
func(calldata, NODE_CLASS_GROUP, N_("Group"));
+ func(calldata, NODE_CLASS_INTERFACE, N_("Interface"));
func(calldata, NODE_CLASS_LAYOUT, N_("Layout"));
}
@@ -111,24 +138,8 @@ static void localize(bNodeTree *localtree, bNodeTree *UNUSED(ntree))
}
}
-static void local_sync(bNodeTree *localtree, bNodeTree *ntree)
+static void local_sync(bNodeTree *UNUSED(localtree), bNodeTree *UNUSED(ntree))
{
- bNode *lnode;
-
- /* copy over contents of previews */
- for (lnode = localtree->nodes.first; lnode; lnode = lnode->next) {
- if (ntreeNodeExists(ntree, lnode->new_node)) {
- bNode *node = lnode->new_node;
-
- if (node->preview && node->preview->rect) {
- if (lnode->preview && lnode->preview->rect) {
- int xsize = node->preview->xsize;
- int ysize = node->preview->ysize;
- memcpy(node->preview->rect, lnode->preview->rect, 4 * xsize + xsize * ysize * sizeof(char) * 4);
- }
- }
- }
- }
}
static void update(bNodeTree *ntree)
@@ -136,26 +147,36 @@ static void update(bNodeTree *ntree)
ntreeSetOutput(ntree);
ntree_update_reroute_nodes(ntree);
+
+ if (ntree->update & NTREE_UPDATE_NODES) {
+ /* clean up preview cache, in case nodes have been removed */
+ BKE_node_preview_remove_unused(ntree);
+ }
}
-bNodeTreeType ntreeType_Shader = {
- /* type */ NTREE_SHADER,
- /* id_name */ "NTShader Nodetree",
+bNodeTreeType *ntreeType_Shader;
+
+void register_node_tree_type_sh()
+{
+ bNodeTreeType *tt = ntreeType_Shader = MEM_callocN(sizeof(bNodeTreeType), "shader node tree type");
+
+ tt->type = NTREE_SHADER;
+ strcpy(tt->idname, "ShaderNodeTree");
+ strcpy(tt->ui_name, "Shader");
+ tt->ui_icon = 0; /* defined in drawnode.c */
+ strcpy(tt->ui_description, "");
- /* node_types */ { NULL, NULL },
+ tt->foreach_nodeclass = foreach_nodeclass;
+ tt->localize = localize;
+ tt->local_sync = local_sync;
+ tt->update = update;
+ tt->poll = shader_tree_poll;
+ tt->get_from_context = shader_get_from_context;
- /* free_cache */ NULL,
- /* free_node_cache */ NULL,
- /* foreach_nodetree */ foreach_nodetree,
- /* foreach_nodeclass */ foreach_nodeclass,
- /* localize */ localize,
- /* local_sync */ local_sync,
- /* local_merge */ NULL,
- /* update */ update,
- /* update_node */ NULL,
- /* validate_link */ NULL,
- /* update_internal_links */ node_update_internal_links_default
-};
+ tt->ext.srna = &RNA_ShaderNodeTree;
+
+ ntreeTypeAdd(tt);
+}
/* GPU material from shader nodes */
@@ -163,11 +184,11 @@ void ntreeGPUMaterialNodes(bNodeTree *ntree, GPUMaterial *mat)
{
bNodeTreeExec *exec;
- exec = ntreeShaderBeginExecTree(ntree, 1);
+ exec = ntreeShaderBeginExecTree(ntree);
ntreeExecGPUNodes(exec, mat, 1);
- ntreeShaderEndExecTree(exec, 1);
+ ntreeShaderEndExecTree(exec);
}
/* **************** call to switch lamploop for material node ************ */
@@ -180,27 +201,16 @@ void set_node_shader_lamp_loop(void (*lamp_loop_func)(ShadeInput *, ShadeResult
}
-/* XXX Group nodes must set use_tree_data to false, since their trees can be shared by multiple nodes.
- * If use_tree_data is true, the ntree->execdata pointer is checked to avoid multiple execution of top-level trees.
- */
-bNodeTreeExec *ntreeShaderBeginExecTree(bNodeTree *ntree, int use_tree_data)
+bNodeTreeExec *ntreeShaderBeginExecTree_internal(bNodeExecContext *context, bNodeTree *ntree, bNodeInstanceKey parent_key)
{
bNodeTreeExec *exec;
bNode *node;
- if (use_tree_data) {
- /* XXX hack: prevent exec data from being generated twice.
- * this should be handled by the renderer!
- */
- if (ntree->execdata)
- return ntree->execdata;
- }
-
/* ensures only a single output node is enabled */
ntreeSetOutput(ntree);
/* common base initialization */
- exec = ntree_exec_begin(ntree);
+ exec = ntree_exec_begin(context, ntree, parent_key);
/* allocate the thread stack listbase array */
exec->threadstack = MEM_callocN(BLENDER_MAX_THREADS * sizeof(ListBase), "thread stack array");
@@ -208,43 +218,58 @@ bNodeTreeExec *ntreeShaderBeginExecTree(bNodeTree *ntree, int use_tree_data)
for (node = exec->nodetree->nodes.first; node; node = node->next)
node->need_exec = 1;
- if (use_tree_data) {
- /* XXX this should not be necessary, but is still used for cmp/sha/tex nodes,
- * which only store the ntree pointer. Should be fixed at some point!
- */
- ntree->execdata = exec;
- }
+ return exec;
+}
+
+bNodeTreeExec *ntreeShaderBeginExecTree(bNodeTree *ntree)
+{
+ bNodeExecContext context;
+ bNodeTreeExec *exec;
+
+ /* XXX hack: prevent exec data from being generated twice.
+ * this should be handled by the renderer!
+ */
+ if (ntree->execdata)
+ return ntree->execdata;
+
+ context.previews = ntree->previews;
+
+ exec = ntreeShaderBeginExecTree_internal(&context, ntree, NODE_INSTANCE_KEY_BASE);
+
+ /* XXX this should not be necessary, but is still used for cmp/sha/tex nodes,
+ * which only store the ntree pointer. Should be fixed at some point!
+ */
+ ntree->execdata = exec;
return exec;
}
-/* XXX Group nodes must set use_tree_data to false, since their trees can be shared by multiple nodes.
- * If use_tree_data is true, the ntree->execdata pointer is checked to avoid multiple execution of top-level trees.
- */
-void ntreeShaderEndExecTree(bNodeTreeExec *exec, int use_tree_data)
+void ntreeShaderEndExecTree_internal(bNodeTreeExec *exec)
{
- if (exec) {
- bNodeTree *ntree = exec->nodetree;
- bNodeThreadStack *nts;
- int a;
-
- if (exec->threadstack) {
- for (a = 0; a < BLENDER_MAX_THREADS; a++) {
- for (nts = exec->threadstack[a].first; nts; nts = nts->next)
- if (nts->stack) MEM_freeN(nts->stack);
- BLI_freelistN(&exec->threadstack[a]);
- }
-
- MEM_freeN(exec->threadstack);
- exec->threadstack = NULL;
+ bNodeThreadStack *nts;
+ int a;
+
+ if (exec->threadstack) {
+ for (a = 0; a < BLENDER_MAX_THREADS; a++) {
+ for (nts = exec->threadstack[a].first; nts; nts = nts->next)
+ if (nts->stack) MEM_freeN(nts->stack);
+ BLI_freelistN(&exec->threadstack[a]);
}
- ntree_exec_end(exec);
+ MEM_freeN(exec->threadstack);
+ exec->threadstack = NULL;
+ }
+
+ ntree_exec_end(exec);
+}
+
+void ntreeShaderEndExecTree(bNodeTreeExec *exec)
+{
+ if (exec) {
+ ntreeShaderEndExecTree_internal(exec);
- if (use_tree_data) {
- /* XXX clear nodetree backpointer to exec data, same problem as noted in ntreeBeginExecTree */
- ntree->execdata = NULL;
- }
+ /* XXX clear nodetree backpointer to exec data, same problem as noted in ntreeBeginExecTree */
+ exec->nodetree->execdata = NULL;
}
}
@@ -272,7 +297,7 @@ bool ntreeShaderExecTree(bNodeTree *ntree, ShadeInput *shi, ShadeResult *shr)
if (!exec) {
BLI_lock_thread(LOCK_NODES);
if (!ntree->execdata)
- ntree->execdata = ntreeShaderBeginExecTree(ntree, 1);
+ ntree->execdata = ntreeShaderBeginExecTree(ntree);
BLI_unlock_thread(LOCK_NODES);
exec = ntree->execdata;
diff --git a/source/blender/nodes/shader/node_shader_util.c b/source/blender/nodes/shader/node_shader_util.c
index 1123a0dc44a..040172d9998 100644
--- a/source/blender/nodes/shader/node_shader_util.c
+++ b/source/blender/nodes/shader/node_shader_util.c
@@ -36,6 +36,20 @@
#include "node_exec.h"
+
+int sh_node_poll_default(bNodeType *UNUSED(ntype), bNodeTree *ntree)
+{
+ return (strcmp(ntree->idname, "ShaderNodeTree")==0);
+}
+
+void sh_node_type_base(struct bNodeType *ntype, int type, const char *name, short nclass, short flag)
+{
+ node_type_base(ntype, type, name, nclass, flag);
+
+ ntype->poll = sh_node_poll_default;
+ ntype->update_internal_links = node_update_internal_links_default;
+}
+
/* ****** */
void nodestack_get_vec(float *in, short type_in, bNodeStack *ns)
@@ -123,74 +137,6 @@ void ntreeShaderGetTexcoMode(bNodeTree *ntree, int r_mode, short *texco, int *mo
}
}
-/* nodes that use ID data get synced with local data */
-void nodeShaderSynchronizeID(bNode *node, int copyto)
-{
- if (node->id==NULL) return;
-
- if (ELEM(node->type, SH_NODE_MATERIAL, SH_NODE_MATERIAL_EXT)) {
- bNodeSocket *sock;
- Material *ma= (Material *)node->id;
- int a;
-
- /* hrmf, case in loop isn't super fast, but we don't edit 100s of material at same time either! */
- for (a=0, sock= node->inputs.first; sock; sock= sock->next, a++) {
- if (!nodeSocketIsHidden(sock)) {
- if (copyto) {
- switch (a) {
- case MAT_IN_COLOR:
- copy_v3_v3(&ma->r, ((bNodeSocketValueRGBA *)sock->default_value)->value); break;
- case MAT_IN_SPEC:
- copy_v3_v3(&ma->specr, ((bNodeSocketValueRGBA *)sock->default_value)->value); break;
- case MAT_IN_REFL:
- ma->ref= ((bNodeSocketValueFloat *)sock->default_value)->value; break;
- case MAT_IN_MIR:
- copy_v3_v3(&ma->mirr, ((bNodeSocketValueRGBA *)sock->default_value)->value); break;
- case MAT_IN_AMB:
- ma->amb = ((bNodeSocketValueFloat *)sock->default_value)->value; break;
- case MAT_IN_EMIT:
- ma->emit = ((bNodeSocketValueFloat *)sock->default_value)->value; break;
- case MAT_IN_SPECTRA:
- ma->spectra = ((bNodeSocketValueFloat *)sock->default_value)->value; break;
- case MAT_IN_RAY_MIRROR:
- ma->ray_mirror = ((bNodeSocketValueFloat *)sock->default_value)->value; break;
- case MAT_IN_ALPHA:
- ma->alpha = ((bNodeSocketValueFloat *)sock->default_value)->value; break;
- case MAT_IN_TRANSLUCENCY:
- ma->translucency = ((bNodeSocketValueFloat *)sock->default_value)->value; break;
- }
- }
- else {
- switch (a) {
- case MAT_IN_COLOR:
- copy_v3_v3(((bNodeSocketValueRGBA *)sock->default_value)->value, &ma->r); break;
- case MAT_IN_SPEC:
- copy_v3_v3(((bNodeSocketValueRGBA *)sock->default_value)->value, &ma->specr); break;
- case MAT_IN_REFL:
- ((bNodeSocketValueFloat *)sock->default_value)->value= ma->ref; break;
- case MAT_IN_MIR:
- copy_v3_v3(((bNodeSocketValueRGBA *)sock->default_value)->value, &ma->mirr); break;
- case MAT_IN_AMB:
- ((bNodeSocketValueFloat *)sock->default_value)->value = ma->amb; break;
- case MAT_IN_EMIT:
- ((bNodeSocketValueFloat *)sock->default_value)->value = ma->emit; break;
- case MAT_IN_SPECTRA:
- ((bNodeSocketValueFloat *)sock->default_value)->value = ma->spectra; break;
- case MAT_IN_RAY_MIRROR:
- ((bNodeSocketValueFloat *)sock->default_value)->value = ma->ray_mirror; break;
- case MAT_IN_ALPHA:
- ((bNodeSocketValueFloat *)sock->default_value)->value = ma->alpha; break;
- case MAT_IN_TRANSLUCENCY:
- ((bNodeSocketValueFloat *)sock->default_value)->value = ma->translucency; break;
- }
- }
- }
- }
- }
-
-}
-
-
void node_gpu_stack_from_data(struct GPUNodeStack *gs, int type, bNodeStack *ns)
{
memset(gs, 0, sizeof(*gs));
@@ -249,23 +195,24 @@ static void data_from_gpu_stack_list(ListBase *sockets, bNodeStack **ns, GPUNode
bNode *nodeGetActiveTexture(bNodeTree *ntree)
{
/* this is the node we texture paint and draw in textured draw */
- bNode *node;
+ bNode *node, *tnode;
if (!ntree)
return NULL;
- /* check for group edit */
- for (node= ntree->nodes.first; node; node= node->next)
- if (node->flag & NODE_GROUP_EDIT)
- break;
-
- if (node)
- ntree = (bNodeTree *)node->id;
-
for (node= ntree->nodes.first; node; node= node->next)
if (node->flag & NODE_ACTIVE_TEXTURE)
return node;
+ /* node active texture node in this tree, look inside groups */
+ for(node= ntree->nodes.first; node; node= node->next) {
+ if (node->type==NODE_GROUP) {
+ tnode = nodeGetActiveTexture((bNodeTree*)node->id);
+ if (tnode)
+ return tnode;
+ }
+ }
+
return NULL;
}
@@ -299,14 +246,7 @@ void ntreeExecGPUNodes(bNodeTreeExec *exec, GPUMaterial *mat, int do_outputs)
node_get_stack(node, stack, nsin, nsout);
gpu_stack_from_data_list(gpuin, &node->inputs, nsin);
gpu_stack_from_data_list(gpuout, &node->outputs, nsout);
- if (node->typeinfo->gpufunc(mat, node, gpuin, gpuout))
- data_from_gpu_stack_list(&node->outputs, nsout, gpuout);
- }
- else if (node->typeinfo->gpuextfunc) {
- node_get_stack(node, stack, nsin, nsout);
- gpu_stack_from_data_list(gpuin, &node->inputs, nsin);
- gpu_stack_from_data_list(gpuout, &node->outputs, nsout);
- if (node->typeinfo->gpuextfunc(mat, node, nodeexec->data, gpuin, gpuout))
+ if (node->typeinfo->gpufunc(mat, node, &nodeexec->data, gpuin, gpuout))
data_from_gpu_stack_list(&node->outputs, nsout, gpuout);
}
}
diff --git a/source/blender/nodes/shader/node_shader_util.h b/source/blender/nodes/shader/node_shader_util.h
index 9c911501435..57b129335bb 100644
--- a/source/blender/nodes/shader/node_shader_util.h
+++ b/source/blender/nodes/shader/node_shader_util.h
@@ -79,6 +79,11 @@
#include "GPU_material.h"
+
+int sh_node_poll_default(struct bNodeType *ntype, struct bNodeTree *ntree);
+void sh_node_type_base(struct bNodeType *ntype, int type, const char *name, short nclass, short flag);
+
+
/* ********* exec data struct, remains internal *********** */
typedef struct ShaderCallData {
@@ -86,40 +91,6 @@ typedef struct ShaderCallData {
ShadeResult *shr; /* from render pipe */
} ShaderCallData;
-/* output socket defines */
-#define GEOM_OUT_GLOB 0
-#define GEOM_OUT_LOCAL 1
-#define GEOM_OUT_VIEW 2
-#define GEOM_OUT_ORCO 3
-#define GEOM_OUT_UV 4
-#define GEOM_OUT_NORMAL 5
-#define GEOM_OUT_VCOL 6
-#define GEOM_OUT_VCOL_ALPHA 7
-#define GEOM_OUT_FRONTBACK 8
-
-
-/* input socket defines */
-#define MAT_IN_COLOR 0
-#define MAT_IN_SPEC 1
-#define MAT_IN_REFL 2
-#define MAT_IN_NORMAL 3
-#define MAT_IN_MIR 4
-#define MAT_IN_AMB 5
-#define MAT_IN_EMIT 6
-#define MAT_IN_SPECTRA 7
-#define MAT_IN_RAY_MIRROR 8
-#define MAT_IN_ALPHA 9
-#define MAT_IN_TRANSLUCENCY 10
-#define NUM_MAT_IN 11 /* for array size */
-
-/* output socket defines */
-#define MAT_OUT_COLOR 0
-#define MAT_OUT_ALPHA 1
-#define MAT_OUT_NORMAL 2
-#define MAT_OUT_DIFFUSE 3
-#define MAT_OUT_SPEC 4
-#define MAT_OUT_AO 5
-
extern void node_ID_title_cb(void *node_v, void *unused_v);
void nodestack_get_vec(float *in, short type_in, bNodeStack *ns);
diff --git a/source/blender/nodes/shader/nodes/node_shader_add_shader.c b/source/blender/nodes/shader/nodes/node_shader_add_shader.c
index ec868b2cc38..75d4fb1a30a 100644
--- a/source/blender/nodes/shader/nodes/node_shader_add_shader.c
+++ b/source/blender/nodes/shader/nodes/node_shader_add_shader.c
@@ -40,24 +40,23 @@ static bNodeSocketTemplate sh_node_add_shader_out[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_add_shader(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_add_shader(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
return GPU_stack_link(mat, "node_add_shader", in, out);
}
/* node type definition */
-void register_node_type_sh_add_shader(bNodeTreeType *ttype)
+void register_node_type_sh_add_shader()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_ADD_SHADER, "Add Shader", NODE_CLASS_SHADER, 0);
+ sh_node_type_base(&ntype, SH_NODE_ADD_SHADER, "Add Shader", NODE_CLASS_SHADER, 0);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_add_shader_in, sh_node_add_shader_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_add_shader);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_ambient_occlusion.c b/source/blender/nodes/shader/nodes/node_shader_ambient_occlusion.c
index 7dfefc9ece0..85814c4a041 100644
--- a/source/blender/nodes/shader/nodes/node_shader_ambient_occlusion.c
+++ b/source/blender/nodes/shader/nodes/node_shader_ambient_occlusion.c
@@ -39,25 +39,24 @@ static bNodeSocketTemplate sh_node_ambient_occlusion_out[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_ambient_occlusion(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_ambient_occlusion(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
return GPU_stack_link(mat, "node_ambient_occlusion", in, out, GPU_builtin(GPU_VIEW_NORMAL));
}
/* node type definition */
-void register_node_type_sh_ambient_occlusion(bNodeTreeType *ttype)
+void register_node_type_sh_ambient_occlusion()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_AMBIENT_OCCLUSION, "Ambient Occlusion", NODE_CLASS_SHADER, 0);
+ sh_node_type_base(&ntype, SH_NODE_AMBIENT_OCCLUSION, "Ambient Occlusion", NODE_CLASS_SHADER, 0);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_ambient_occlusion_in, sh_node_ambient_occlusion_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_ambient_occlusion);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_attribute.c b/source/blender/nodes/shader/nodes/node_shader_attribute.c
index 9b2ed2f14f0..b6463655755 100644
--- a/source/blender/nodes/shader/nodes/node_shader_attribute.c
+++ b/source/blender/nodes/shader/nodes/node_shader_attribute.c
@@ -36,25 +36,23 @@ static bNodeSocketTemplate sh_node_attribute_out[] = {
{ -1, 0, "" }
};
-static void node_shader_init_attribute(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_shader_init_attribute(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeShaderAttribute *attr = MEM_callocN(sizeof(NodeShaderAttribute), "NodeShaderAttribute");
node->storage = attr;
}
/* node type definition */
-void register_node_type_sh_attribute(bNodeTreeType *ttype)
+void register_node_type_sh_attribute()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_ATTRIBUTE, "Attribute", NODE_CLASS_INPUT, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_ATTRIBUTE, "Attribute", NODE_CLASS_INPUT, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, NULL, sh_node_attribute_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, node_shader_init_attribute);
node_type_storage(&ntype, "NodeShaderAttribute", node_free_standard_storage, node_copy_standard_storage);
- node_type_exec(&ntype, NULL);
- node_type_gpu(&ntype, NULL);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_background.c b/source/blender/nodes/shader/nodes/node_shader_background.c
index d82c513540c..b109a2e4596 100644
--- a/source/blender/nodes/shader/nodes/node_shader_background.c
+++ b/source/blender/nodes/shader/nodes/node_shader_background.c
@@ -41,18 +41,16 @@ static bNodeSocketTemplate sh_node_background_out[] = {
};
/* node type definition */
-void register_node_type_sh_background(bNodeTreeType *ttype)
+void register_node_type_sh_background()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_BACKGROUND, "Background", NODE_CLASS_SHADER, 0);
+ sh_node_type_base(&ntype, SH_NODE_BACKGROUND, "Background", NODE_CLASS_SHADER, 0);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_background_in, sh_node_background_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
- node_type_exec(&ntype, NULL);
- node_type_gpu(&ntype, NULL);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_brightness.c b/source/blender/nodes/shader/nodes/node_shader_brightness.c
index fa77fce4c88..ccdbddadb14 100644
--- a/source/blender/nodes/shader/nodes/node_shader_brightness.c
+++ b/source/blender/nodes/shader/nodes/node_shader_brightness.c
@@ -43,23 +43,22 @@ static bNodeSocketTemplate sh_node_brightcontrast_out[] = {
{ -1, 0, "" }
};
-static int gpu_shader_brightcontrast(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
+static int gpu_shader_brightcontrast(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
return GPU_stack_link(mat, "brightness_contrast", in, out);
}
-void register_node_type_sh_brightcontrast(bNodeTreeType *ttype)
+void register_node_type_sh_brightcontrast()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_BRIGHTCONTRAST, "Bright/Contrast", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_BRIGHTCONTRAST, "Bright/Contrast", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_brightcontrast_in, sh_node_brightcontrast_out);
node_type_size(&ntype, 140, 100, 320);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, gpu_shader_brightcontrast);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.c
index 71780e9316e..e4b9c372607 100644
--- a/source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.c
+++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.c
@@ -44,7 +44,7 @@ static bNodeSocketTemplate sh_node_bsdf_anisotropic_out[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_bsdf_anisotropic(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_bsdf_anisotropic(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
if (!in[3].link)
in[3].link = GPU_builtin(GPU_VIEW_NORMAL);
@@ -53,18 +53,17 @@ static int node_shader_gpu_bsdf_anisotropic(GPUMaterial *mat, bNode *UNUSED(node
}
/* node type definition */
-void register_node_type_sh_bsdf_anisotropic(bNodeTreeType *ttype)
+void register_node_type_sh_bsdf_anisotropic()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_BSDF_ANISOTROPIC, "Anisotropic BSDF", NODE_CLASS_SHADER, 0);
+ sh_node_type_base(&ntype, SH_NODE_BSDF_ANISOTROPIC, "Anisotropic BSDF", NODE_CLASS_SHADER, 0);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_bsdf_anisotropic_in, sh_node_bsdf_anisotropic_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_bsdf_anisotropic);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_diffuse.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_diffuse.c
index ad9f197afb8..466c2db07d4 100644
--- a/source/blender/nodes/shader/nodes/node_shader_bsdf_diffuse.c
+++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_diffuse.c
@@ -41,7 +41,7 @@ static bNodeSocketTemplate sh_node_bsdf_diffuse_out[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_bsdf_diffuse(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_bsdf_diffuse(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
if (!in[2].link)
in[2].link = GPU_builtin(GPU_VIEW_NORMAL);
@@ -50,18 +50,17 @@ static int node_shader_gpu_bsdf_diffuse(GPUMaterial *mat, bNode *UNUSED(node), G
}
/* node type definition */
-void register_node_type_sh_bsdf_diffuse(bNodeTreeType *ttype)
+void register_node_type_sh_bsdf_diffuse()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_BSDF_DIFFUSE, "Diffuse BSDF", NODE_CLASS_SHADER, 0);
+ sh_node_type_base(&ntype, SH_NODE_BSDF_DIFFUSE, "Diffuse BSDF", NODE_CLASS_SHADER, 0);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_bsdf_diffuse_in, sh_node_bsdf_diffuse_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_bsdf_diffuse);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_glass.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_glass.c
index 9e188092570..b36a754e129 100644
--- a/source/blender/nodes/shader/nodes/node_shader_bsdf_glass.c
+++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_glass.c
@@ -42,7 +42,7 @@ static bNodeSocketTemplate sh_node_bsdf_glass_out[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_bsdf_glass(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_bsdf_glass(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
if (!in[3].link)
in[3].link = GPU_builtin(GPU_VIEW_NORMAL);
@@ -51,18 +51,17 @@ static int node_shader_gpu_bsdf_glass(GPUMaterial *mat, bNode *UNUSED(node), GPU
}
/* node type definition */
-void register_node_type_sh_bsdf_glass(bNodeTreeType *ttype)
+void register_node_type_sh_bsdf_glass()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_BSDF_GLASS, "Glass BSDF", NODE_CLASS_SHADER, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_BSDF_GLASS, "Glass BSDF", NODE_CLASS_SHADER, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_bsdf_glass_in, sh_node_bsdf_glass_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_bsdf_glass);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.c
index 5e32930b707..00d4f18fe65 100644
--- a/source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.c
+++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.c
@@ -41,7 +41,7 @@ static bNodeSocketTemplate sh_node_bsdf_glossy_out[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_bsdf_glossy(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_bsdf_glossy(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
if (!in[2].link)
in[2].link = GPU_builtin(GPU_VIEW_NORMAL);
@@ -50,18 +50,17 @@ static int node_shader_gpu_bsdf_glossy(GPUMaterial *mat, bNode *UNUSED(node), GP
}
/* node type definition */
-void register_node_type_sh_bsdf_glossy(bNodeTreeType *ttype)
+void register_node_type_sh_bsdf_glossy()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_BSDF_GLOSSY, "Glossy BSDF", NODE_CLASS_SHADER, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_BSDF_GLOSSY, "Glossy BSDF", NODE_CLASS_SHADER, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_bsdf_glossy_in, sh_node_bsdf_glossy_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_bsdf_glossy);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_refraction.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_refraction.c
index 99e66e39002..e8509c489ef 100644
--- a/source/blender/nodes/shader/nodes/node_shader_bsdf_refraction.c
+++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_refraction.c
@@ -42,7 +42,7 @@ static bNodeSocketTemplate sh_node_bsdf_refraction_out[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_bsdf_refraction(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_bsdf_refraction(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
if (!in[3].link)
in[3].link = GPU_builtin(GPU_VIEW_NORMAL);
@@ -51,18 +51,17 @@ static int node_shader_gpu_bsdf_refraction(GPUMaterial *mat, bNode *UNUSED(node)
}
/* node type definition */
-void register_node_type_sh_bsdf_refraction(bNodeTreeType *ttype)
+void register_node_type_sh_bsdf_refraction()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_BSDF_REFRACTION, "Refraction BSDF", NODE_CLASS_SHADER, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_BSDF_REFRACTION, "Refraction BSDF", NODE_CLASS_SHADER, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_bsdf_refraction_in, sh_node_bsdf_refraction_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_bsdf_refraction);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_translucent.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_translucent.c
index 3c7084886b7..ab4ced3f99e 100644
--- a/source/blender/nodes/shader/nodes/node_shader_bsdf_translucent.c
+++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_translucent.c
@@ -40,7 +40,7 @@ static bNodeSocketTemplate sh_node_bsdf_translucent_out[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_bsdf_translucent(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_bsdf_translucent(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
if (!in[1].link)
in[1].link = GPU_builtin(GPU_VIEW_NORMAL);
@@ -49,18 +49,17 @@ static int node_shader_gpu_bsdf_translucent(GPUMaterial *mat, bNode *UNUSED(node
}
/* node type definition */
-void register_node_type_sh_bsdf_translucent(bNodeTreeType *ttype)
+void register_node_type_sh_bsdf_translucent()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_BSDF_TRANSLUCENT, "Translucent BSDF", NODE_CLASS_SHADER, 0);
+ sh_node_type_base(&ntype, SH_NODE_BSDF_TRANSLUCENT, "Translucent BSDF", NODE_CLASS_SHADER, 0);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_bsdf_translucent_in, sh_node_bsdf_translucent_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_bsdf_translucent);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_transparent.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_transparent.c
index 7fb452ad78d..843454dbb3e 100644
--- a/source/blender/nodes/shader/nodes/node_shader_bsdf_transparent.c
+++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_transparent.c
@@ -39,24 +39,23 @@ static bNodeSocketTemplate sh_node_bsdf_transparent_out[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_bsdf_transparent(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_bsdf_transparent(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
return GPU_stack_link(mat, "node_bsdf_transparent", in, out);
}
/* node type definition */
-void register_node_type_sh_bsdf_transparent(bNodeTreeType *ttype)
+void register_node_type_sh_bsdf_transparent()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_BSDF_TRANSPARENT, "Transparent BSDF", NODE_CLASS_SHADER, 0);
+ sh_node_type_base(&ntype, SH_NODE_BSDF_TRANSPARENT, "Transparent BSDF", NODE_CLASS_SHADER, 0);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_bsdf_transparent_in, sh_node_bsdf_transparent_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_bsdf_transparent);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_velvet.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_velvet.c
index a4d25d42d4e..ff9fd3a07fe 100644
--- a/source/blender/nodes/shader/nodes/node_shader_bsdf_velvet.c
+++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_velvet.c
@@ -41,7 +41,7 @@ static bNodeSocketTemplate sh_node_bsdf_velvet_out[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_bsdf_velvet(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_bsdf_velvet(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
if (!in[2].link)
in[2].link = GPU_builtin(GPU_VIEW_NORMAL);
@@ -50,18 +50,17 @@ static int node_shader_gpu_bsdf_velvet(GPUMaterial *mat, bNode *UNUSED(node), GP
}
/* node type definition */
-void register_node_type_sh_bsdf_velvet(bNodeTreeType *ttype)
+void register_node_type_sh_bsdf_velvet()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_BSDF_VELVET, "Velvet BSDF", NODE_CLASS_SHADER, 0);
+ sh_node_type_base(&ntype, SH_NODE_BSDF_VELVET, "Velvet BSDF", NODE_CLASS_SHADER, 0);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_bsdf_velvet_in, sh_node_bsdf_velvet_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_bsdf_velvet);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_bump.c b/source/blender/nodes/shader/nodes/node_shader_bump.c
index b0605f9b248..00733ebaf5c 100644
--- a/source/blender/nodes/shader/nodes/node_shader_bump.c
+++ b/source/blender/nodes/shader/nodes/node_shader_bump.c
@@ -46,23 +46,22 @@ static bNodeSocketTemplate sh_node_bump_out[] = {
{ -1, 0, "" }
};
-static int gpu_shader_bump(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
+static int gpu_shader_bump(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
return GPU_stack_link(mat, "node_bump", in, out, GPU_builtin(GPU_VIEW_NORMAL));
}
/* node type definition */
-void register_node_type_sh_bump(bNodeTreeType *ttype)
+void register_node_type_sh_bump()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_BUMP, "Bump", NODE_CLASS_OP_VECTOR, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_BUMP, "Bump", NODE_CLASS_OP_VECTOR, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_bump_in, sh_node_bump_out);
node_type_size(&ntype, 150, 60, 200);
node_type_storage(&ntype, "BumpNode", node_free_standard_storage, node_copy_standard_storage);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, gpu_shader_bump);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_camera.c b/source/blender/nodes/shader/nodes/node_shader_camera.c
index fd36a94516e..8a406bc7f74 100644
--- a/source/blender/nodes/shader/nodes/node_shader_camera.c
+++ b/source/blender/nodes/shader/nodes/node_shader_camera.c
@@ -41,7 +41,7 @@ static bNodeSocketTemplate sh_node_camera_out[] = {
};
-static void node_shader_exec_camera(void *data, bNode *UNUSED(node), bNodeStack **UNUSED(in), bNodeStack **out)
+static void node_shader_exec_camera(void *data, int UNUSED(thread), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), bNodeStack **UNUSED(in), bNodeStack **out)
{
if (data) {
ShadeInput *shi= ((ShaderCallData *)data)->shi; /* Data we need for shading. */
@@ -52,22 +52,22 @@ static void node_shader_exec_camera(void *data, bNode *UNUSED(node), bNodeStack
}
}
-static int gpu_shader_camera(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
+static int gpu_shader_camera(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
return GPU_stack_link(mat, "camera", in, out, GPU_builtin(GPU_VIEW_POSITION));
}
-void register_node_type_sh_camera(bNodeTreeType *ttype)
+void register_node_type_sh_camera()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_CAMERA, "Camera Data", NODE_CLASS_INPUT, 0);
+ sh_node_type_base(&ntype, SH_NODE_CAMERA, "Camera Data", NODE_CLASS_INPUT, 0);
node_type_compatibility(&ntype, NODE_OLD_SHADING|NODE_NEW_SHADING);
node_type_socket_templates(&ntype, NULL, sh_node_camera_out);
node_type_size(&ntype, 95, 95, 120);
node_type_storage(&ntype, "node_camera", NULL, NULL);
- node_type_exec(&ntype, node_shader_exec_camera);
+ node_type_exec(&ntype, NULL, NULL, node_shader_exec_camera);
node_type_gpu(&ntype, gpu_shader_camera);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_common.c b/source/blender/nodes/shader/nodes/node_shader_common.c
index 9c784709de3..8c148b86610 100644
--- a/source/blender/nodes/shader/nodes/node_shader_common.c
+++ b/source/blender/nodes/shader/nodes/node_shader_common.c
@@ -38,9 +38,12 @@
#include "BKE_node.h"
#include "node_shader_util.h"
+#include "NOD_common.h"
#include "node_common.h"
#include "node_exec.h"
+#include "RNA_access.h"
+
static void copy_stack(bNodeStack *to, bNodeStack *from)
{
if (to != from) {
@@ -61,16 +64,14 @@ static void move_stack(bNodeStack *to, bNodeStack *from)
to->datatype = from->datatype;
to->is_copy = from->is_copy;
- zero_v4(from->vec);
from->data = NULL;
- from->datatype = 0;
from->is_copy = 0;
}
}
/**** GROUP ****/
-static void *group_initexec(bNode *node)
+static void *group_initexec(bNodeExecContext *context, bNode *node, bNodeInstanceKey key)
{
bNodeTree *ngroup = (bNodeTree *)node->id;
bNodeTreeExec *exec;
@@ -79,7 +80,7 @@ static void *group_initexec(bNode *node)
return NULL;
/* initialize the internal node tree execution */
- exec = ntreeShaderBeginExecTree(ngroup, 0);
+ exec = ntreeShaderBeginExecTree_internal(context, ngroup, key);
return exec;
}
@@ -88,42 +89,55 @@ static void group_freeexec(bNode *UNUSED(node), void *nodedata)
{
bNodeTreeExec*gexec = (bNodeTreeExec *)nodedata;
- ntreeShaderEndExecTree(gexec, 0);
+ ntreeShaderEndExecTree_internal(gexec);
}
/* Copy inputs to the internal stack.
*/
-static void group_copy_inputs(bNode *node, bNodeStack **in, bNodeStack *gstack)
+static void group_copy_inputs(bNode *gnode, bNodeStack **in, bNodeStack *gstack)
{
+ bNodeTree *ngroup = (bNodeTree*)gnode->id;
+ bNode *node;
bNodeSocket *sock;
bNodeStack *ns;
int a;
- for (sock=node->inputs.first, a=0; sock; sock=sock->next, ++a) {
- if (sock->groupsock) {
- ns = node_get_socket_stack(gstack, sock->groupsock);
- copy_stack(ns, in[a]);
+
+ for (node = ngroup->nodes.first; node; node = node->next) {
+ if (node->type == NODE_GROUP_INPUT) {
+ for (sock = node->outputs.first, a = 0; sock; sock = sock->next, ++a) {
+ ns = node_get_socket_stack(gstack, sock);
+ if (ns)
+ copy_stack(ns, in[a]);
+ }
}
}
}
/* Copy internal results to the external outputs.
*/
-static void group_move_outputs(bNode *node, bNodeStack **out, bNodeStack *gstack)
+static void group_move_outputs(bNode *gnode, bNodeStack **out, bNodeStack *gstack)
{
+ bNodeTree *ngroup = (bNodeTree*)gnode->id;
+ bNode *node;
bNodeSocket *sock;
bNodeStack *ns;
int a;
- for (sock=node->outputs.first, a=0; sock; sock=sock->next, ++a) {
- if (sock->groupsock) {
- ns = node_get_socket_stack(gstack, sock->groupsock);
- move_stack(out[a], ns);
+
+ for (node = ngroup->nodes.first; node; node = node->next) {
+ if (node->type == NODE_GROUP_OUTPUT && (node->flag & NODE_DO_OUTPUT)) {
+ for (sock = node->inputs.first, a = 0; sock; sock = sock->next, ++a) {
+ ns = node_get_socket_stack(gstack, sock);
+ if (ns)
+ move_stack(out[a], ns);
+ }
+ break; /* only one active output node */
}
}
}
-static void group_execute(void *data, int thread, struct bNode *node, void *nodedata, struct bNodeStack **in, struct bNodeStack **out)
+static void group_execute(void *data, int thread, struct bNode *node, bNodeExecData *execdata, struct bNodeStack **in, struct bNodeStack **out)
{
- bNodeTreeExec *exec = (bNodeTreeExec *)nodedata;
+ bNodeTreeExec *exec = execdata->data;
bNodeThreadStack *nts;
if (!exec)
@@ -147,62 +161,88 @@ static void group_execute(void *data, int thread, struct bNode *node, void *node
ntreeReleaseThreadStack(nts);
}
-static void group_gpu_copy_inputs(bNode *node, GPUNodeStack *in, bNodeStack *gstack)
+static void group_gpu_copy_inputs(bNode *gnode, GPUNodeStack *in, bNodeStack *gstack)
{
+ bNodeTree *ngroup = (bNodeTree*)gnode->id;
+ bNode *node;
bNodeSocket *sock;
bNodeStack *ns;
int a;
- for (sock=node->inputs.first, a=0; sock; sock=sock->next, ++a) {
- if (sock->groupsock) {
- ns = node_get_socket_stack(gstack, sock->groupsock);
- /* convert the external gpu stack back to internal node stack data */
- node_data_from_gpu_stack(ns, &in[a]);
+
+ for (node = ngroup->nodes.first; node; node = node->next) {
+ if (node->type == NODE_GROUP_INPUT) {
+ for (sock = node->outputs.first, a = 0; sock; sock = sock->next, ++a) {
+ ns = node_get_socket_stack(gstack, sock);
+ if (ns) {
+ /* convert the external gpu stack back to internal node stack data */
+ node_data_from_gpu_stack(ns, &in[a]);
+ }
+ }
}
}
}
/* Copy internal results to the external outputs.
*/
-static void group_gpu_move_outputs(bNode *node, GPUNodeStack *out, bNodeStack *gstack)
+static void group_gpu_move_outputs(bNode *gnode, GPUNodeStack *out, bNodeStack *gstack)
{
+ bNodeTree *ngroup = (bNodeTree*)gnode->id;
+ bNode *node;
bNodeSocket *sock;
bNodeStack *ns;
int a;
- for (sock=node->outputs.first, a=0; sock; sock=sock->next, ++a) {
- if (sock->groupsock) {
- ns = node_get_socket_stack(gstack, sock->groupsock);
- /* convert the node stack data result back to gpu stack */
- node_gpu_stack_from_data(&out[a], sock->type, ns);
+
+ for (node = ngroup->nodes.first; node; node = node->next) {
+ if (node->type == NODE_GROUP_OUTPUT && (node->flag & NODE_DO_OUTPUT)) {
+ for (sock = node->inputs.first, a = 0; sock; sock = sock->next, ++a) {
+ ns = node_get_socket_stack(gstack, sock);
+ if (ns) {
+ /* convert the node stack data result back to gpu stack */
+ node_gpu_stack_from_data(&out[a], sock->type, ns);
+ }
+ }
+ break; /* only one active output node */
}
}
}
-static int gpu_group_execute(GPUMaterial *mat, bNode *node, void *nodedata, GPUNodeStack *in, GPUNodeStack *out)
+static int gpu_group_execute(GPUMaterial *mat, bNode *node, bNodeExecData *execdata, GPUNodeStack *in, GPUNodeStack *out)
{
- bNodeTreeExec *exec = (bNodeTreeExec *)nodedata;
+ bNodeTreeExec *exec = execdata->data;
group_gpu_copy_inputs(node, in, exec->stack);
+ #if 0 /* XXX NODE_GROUP_EDIT is deprecated, depends on node space */
ntreeExecGPUNodes(exec, mat, (node->flag & NODE_GROUP_EDIT));
+ #else
+ ntreeExecGPUNodes(exec, mat, 0);
+ #endif
group_gpu_move_outputs(node, out, exec->stack);
return 1;
}
-void register_node_type_sh_group(bNodeTreeType *ttype)
+void register_node_type_sh_group()
{
static bNodeType ntype;
-
- node_type_base(ttype, &ntype, NODE_GROUP, "Group", NODE_CLASS_GROUP, NODE_OPTIONS|NODE_CONST_OUTPUT);
+
+ /* NB: cannot use sh_node_type_base for node group, because it would map the node type
+ * to the shared NODE_GROUP integer type id.
+ */
+ node_type_base_custom(&ntype, "ShaderNodeGroup", "Group", NODE_CLASS_GROUP, NODE_OPTIONS | NODE_CONST_OUTPUT);
+ ntype.type = NODE_GROUP;
+ ntype.poll = sh_node_poll_default;
+ ntype.update_internal_links = node_update_internal_links_default;
+ ntype.ext.srna = RNA_struct_find("ShaderNodeGroup");
+ BLI_assert(ntype.ext.srna != NULL);
+ RNA_struct_blender_type_set(ntype.ext.srna, &ntype);
+
node_type_socket_templates(&ntype, NULL, NULL);
node_type_size(&ntype, 120, 60, 200);
node_type_label(&ntype, node_group_label);
- node_type_init(&ntype, node_group_init);
- node_type_valid(&ntype, node_group_valid);
- node_type_template(&ntype, node_group_template);
node_type_update(&ntype, NULL, node_group_verify);
- node_type_group_edit(&ntype, node_group_edit_get, node_group_edit_set, node_group_edit_clear);
- node_type_exec_new(&ntype, group_initexec, group_freeexec, group_execute);
- node_type_gpu_ext(&ntype, gpu_group_execute);
+ strcpy(ntype.group_tree_idname, "ShaderNodeTree");
+ node_type_exec(&ntype, group_initexec, group_freeexec, group_execute);
+ node_type_gpu(&ntype, gpu_group_execute);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_curves.c b/source/blender/nodes/shader/nodes/node_shader_curves.c
index 216e10a7e9a..7a6d4a08db0 100644
--- a/source/blender/nodes/shader/nodes/node_shader_curves.c
+++ b/source/blender/nodes/shader/nodes/node_shader_curves.c
@@ -45,7 +45,7 @@ static bNodeSocketTemplate sh_node_curve_vec_out[] = {
{ -1, 0, "" }
};
-static void node_shader_exec_curve_vec(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
+static void node_shader_exec_curve_vec(void *UNUSED(data), int UNUSED(thread), bNode *node, bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out)
{
float vec[3];
@@ -55,12 +55,12 @@ static void node_shader_exec_curve_vec(void *UNUSED(data), bNode *node, bNodeSta
curvemapping_evaluate3F(node->storage, out[0]->vec, vec);
}
-static void node_shader_init_curve_vec(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_shader_init_curve_vec(bNodeTree *UNUSED(ntree), bNode *node)
{
node->storage= curvemapping_add(3, -1.0f, -1.0f, 1.0f, 1.0f);
}
-static int gpu_shader_curve_vec(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out)
+static int gpu_shader_curve_vec(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
float *array;
int size;
@@ -69,21 +69,20 @@ static int gpu_shader_curve_vec(GPUMaterial *mat, bNode *node, GPUNodeStack *in,
return GPU_stack_link(mat, "curves_vec", in, out, GPU_texture(size, array));
}
-void register_node_type_sh_curve_vec(bNodeTreeType *ttype)
+void register_node_type_sh_curve_vec()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_CURVE_VEC, "Vector Curves", NODE_CLASS_OP_VECTOR, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_CURVE_VEC, "Vector Curves", NODE_CLASS_OP_VECTOR, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_OLD_SHADING|NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_curve_vec_in, sh_node_curve_vec_out);
node_type_size(&ntype, 200, 140, 320);
node_type_init(&ntype, node_shader_init_curve_vec);
node_type_storage(&ntype, "CurveMapping", node_free_curves, node_copy_curves);
- node_type_exec(&ntype, node_shader_exec_curve_vec);
- node_type_exec_new(&ntype, node_initexec_curves, NULL, NULL); /* only for its initexec func */
+ node_type_exec(&ntype, node_initexec_curves, NULL, node_shader_exec_curve_vec);
node_type_gpu(&ntype, gpu_shader_curve_vec);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
@@ -99,7 +98,7 @@ static bNodeSocketTemplate sh_node_curve_rgb_out[] = {
{ -1, 0, "" }
};
-static void node_shader_exec_curve_rgb(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
+static void node_shader_exec_curve_rgb(void *UNUSED(data), int UNUSED(thread), bNode *node, bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out)
{
float vec[3];
@@ -112,12 +111,12 @@ static void node_shader_exec_curve_rgb(void *UNUSED(data), bNode *node, bNodeSta
}
}
-static void node_shader_init_curve_rgb(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_shader_init_curve_rgb(bNodeTree *UNUSED(ntree), bNode *node)
{
node->storage= curvemapping_add(4, 0.0f, 0.0f, 1.0f, 1.0f);
}
-static int gpu_shader_curve_rgb(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out)
+static int gpu_shader_curve_rgb(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
float *array;
int size;
@@ -127,19 +126,18 @@ static int gpu_shader_curve_rgb(GPUMaterial *mat, bNode *node, GPUNodeStack *in,
return GPU_stack_link(mat, "curves_rgb", in, out, GPU_texture(size, array));
}
-void register_node_type_sh_curve_rgb(bNodeTreeType *ttype)
+void register_node_type_sh_curve_rgb()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_CURVE_RGB, "RGB Curves", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_CURVE_RGB, "RGB Curves", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_OLD_SHADING|NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_curve_rgb_in, sh_node_curve_rgb_out);
node_type_size(&ntype, 200, 140, 320);
node_type_init(&ntype, node_shader_init_curve_rgb);
node_type_storage(&ntype, "CurveMapping", node_free_curves, node_copy_curves);
- node_type_exec(&ntype, node_shader_exec_curve_rgb);
- node_type_exec_new(&ntype, node_initexec_curves, NULL, NULL); /* only for its initexec func */
+ node_type_exec(&ntype, node_initexec_curves, NULL, node_shader_exec_curve_rgb);
node_type_gpu(&ntype, gpu_shader_curve_rgb);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_emission.c b/source/blender/nodes/shader/nodes/node_shader_emission.c
index 0c4cb7ed51c..d330afbdabe 100644
--- a/source/blender/nodes/shader/nodes/node_shader_emission.c
+++ b/source/blender/nodes/shader/nodes/node_shader_emission.c
@@ -40,24 +40,23 @@ static bNodeSocketTemplate sh_node_emission_out[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_emission(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_emission(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
return GPU_stack_link(mat, "node_emission", in, out, GPU_builtin(GPU_VIEW_NORMAL));
}
/* node type definition */
-void register_node_type_sh_emission(bNodeTreeType *ttype)
+void register_node_type_sh_emission()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_EMISSION, "Emission", NODE_CLASS_SHADER, 0);
+ sh_node_type_base(&ntype, SH_NODE_EMISSION, "Emission", NODE_CLASS_SHADER, 0);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_emission_in, sh_node_emission_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_emission);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_fresnel.c b/source/blender/nodes/shader/nodes/node_shader_fresnel.c
index 80913e6b07a..fe15cc9bc04 100644
--- a/source/blender/nodes/shader/nodes/node_shader_fresnel.c
+++ b/source/blender/nodes/shader/nodes/node_shader_fresnel.c
@@ -38,25 +38,24 @@ static bNodeSocketTemplate sh_node_fresnel_out[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_fresnel(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_fresnel(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
/* todo: is incoming vector normalized? */
return GPU_stack_link(mat, "node_fresnel", in, out, GPU_builtin(GPU_VIEW_NORMAL), GPU_builtin(GPU_VIEW_POSITION));
}
/* node type definition */
-void register_node_type_sh_fresnel(bNodeTreeType *ttype)
+void register_node_type_sh_fresnel()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_FRESNEL, "Fresnel", NODE_CLASS_INPUT, 0);
+ sh_node_type_base(&ntype, SH_NODE_FRESNEL, "Fresnel", NODE_CLASS_INPUT, 0);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_fresnel_in, sh_node_fresnel_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_fresnel);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_gamma.c b/source/blender/nodes/shader/nodes/node_shader_gamma.c
index 365bac77004..35b01cfb73e 100644
--- a/source/blender/nodes/shader/nodes/node_shader_gamma.c
+++ b/source/blender/nodes/shader/nodes/node_shader_gamma.c
@@ -41,18 +41,16 @@ static bNodeSocketTemplate sh_node_gamma_out[] = {
{ -1, 0, "" }
};
-void register_node_type_sh_gamma(bNodeTreeType *ttype)
+void register_node_type_sh_gamma()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_GAMMA, "Gamma", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_GAMMA, "Gamma", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_gamma_in, sh_node_gamma_out);
node_type_size(&ntype, 140, 100, 320);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
- node_type_exec(&ntype, NULL);
- node_type_gpu(&ntype, NULL);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_geom.c b/source/blender/nodes/shader/nodes/node_shader_geom.c
index eb3d462d616..166e9453f35 100644
--- a/source/blender/nodes/shader/nodes/node_shader_geom.c
+++ b/source/blender/nodes/shader/nodes/node_shader_geom.c
@@ -51,7 +51,7 @@ static bNodeSocketTemplate sh_node_geom_out[] = {
};
/* node execute callback */
-static void node_shader_exec_geom(void *data, bNode *node, bNodeStack **UNUSED(in), bNodeStack **out)
+static void node_shader_exec_geom(void *data, int UNUSED(thread), bNode *node, bNodeExecData *UNUSED(execdata), bNodeStack **UNUSED(in), bNodeStack **out)
{
if (data) {
ShadeInput *shi= ((ShaderCallData *)data)->shi;
@@ -120,12 +120,12 @@ static void node_shader_exec_geom(void *data, bNode *node, bNodeStack **UNUSED(i
}
}
-static void node_shader_init_geometry(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_shader_init_geometry(bNodeTree *UNUSED(ntree), bNode *node)
{
node->storage= MEM_callocN(sizeof(NodeGeometry), "NodeGeometry");
}
-static int gpu_shader_geom(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out)
+static int gpu_shader_geom(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
NodeGeometry *ngeo= (NodeGeometry*)node->storage;
GPUNodeLink *orco = GPU_attribute(CD_ORCO, "");
@@ -138,18 +138,18 @@ static int gpu_shader_geom(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUN
}
/* node type definition */
-void register_node_type_sh_geom(bNodeTreeType *ttype)
+void register_node_type_sh_geom()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_GEOMETRY, "Geometry", NODE_CLASS_INPUT, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_GEOMETRY, "Geometry", NODE_CLASS_INPUT, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_OLD_SHADING);
node_type_socket_templates(&ntype, NULL, sh_node_geom_out);
node_type_size(&ntype, 120, 80, 160);
node_type_init(&ntype, node_shader_init_geometry);
node_type_storage(&ntype, "NodeGeometry", node_free_standard_storage, node_copy_standard_storage);
- node_type_exec(&ntype, node_shader_exec_geom);
+ node_type_exec(&ntype, NULL, NULL, node_shader_exec_geom);
node_type_gpu(&ntype, gpu_shader_geom);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_geometry.c b/source/blender/nodes/shader/nodes/node_shader_geometry.c
index acef885d2d4..f57caa2f798 100644
--- a/source/blender/nodes/shader/nodes/node_shader_geometry.c
+++ b/source/blender/nodes/shader/nodes/node_shader_geometry.c
@@ -40,7 +40,7 @@ static bNodeSocketTemplate sh_node_geometry_out[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_geometry(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_geometry(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
return GPU_stack_link(mat, "node_geometry", in, out,
GPU_builtin(GPU_VIEW_POSITION), GPU_builtin(GPU_VIEW_NORMAL),
@@ -48,18 +48,17 @@ static int node_shader_gpu_geometry(GPUMaterial *mat, bNode *UNUSED(node), GPUNo
}
/* node type definition */
-void register_node_type_sh_geometry(bNodeTreeType *ttype)
+void register_node_type_sh_geometry()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_NEW_GEOMETRY, "Geometry", NODE_CLASS_INPUT, 0);
+ sh_node_type_base(&ntype, SH_NODE_NEW_GEOMETRY, "Geometry", NODE_CLASS_INPUT, 0);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, NULL, sh_node_geometry_out);
node_type_size(&ntype, 120, 60, 200);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_geometry);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_hair_info.c b/source/blender/nodes/shader/nodes/node_shader_hair_info.c
index 5cd4c8bd1d3..f03373ad066 100644
--- a/source/blender/nodes/shader/nodes/node_shader_hair_info.c
+++ b/source/blender/nodes/shader/nodes/node_shader_hair_info.c
@@ -36,18 +36,16 @@ static bNodeSocketTemplate outputs[] = {
};
/* node type definition */
-void register_node_type_sh_hair_info(bNodeTreeType *ttype)
+void register_node_type_sh_hair_info()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_HAIR_INFO, "Hair Info", NODE_CLASS_INPUT, 0);
+ sh_node_type_base(&ntype, SH_NODE_HAIR_INFO, "Hair Info", NODE_CLASS_INPUT, 0);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, NULL, outputs);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
- node_type_exec(&ntype, NULL);
- node_type_gpu(&ntype, NULL);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_holdout.c b/source/blender/nodes/shader/nodes/node_shader_holdout.c
index 18ad4994c9b..04769cad590 100644
--- a/source/blender/nodes/shader/nodes/node_shader_holdout.c
+++ b/source/blender/nodes/shader/nodes/node_shader_holdout.c
@@ -40,18 +40,16 @@ static bNodeSocketTemplate sh_node_holdout_out[] = {
/* node type definition */
-void register_node_type_sh_holdout(bNodeTreeType *ttype)
+void register_node_type_sh_holdout()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_HOLDOUT, "Holdout", NODE_CLASS_SHADER, 0);
+ sh_node_type_base(&ntype, SH_NODE_HOLDOUT, "Holdout", NODE_CLASS_SHADER, 0);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_holdout_in, sh_node_holdout_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
- node_type_exec(&ntype, NULL);
- node_type_gpu(&ntype, NULL);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_hueSatVal.c b/source/blender/nodes/shader/nodes/node_shader_hueSatVal.c
index b635ad1edd9..f4a5462b8cc 100644
--- a/source/blender/nodes/shader/nodes/node_shader_hueSatVal.c
+++ b/source/blender/nodes/shader/nodes/node_shader_hueSatVal.c
@@ -69,27 +69,27 @@ static void do_hue_sat_fac(bNode *UNUSED(node), float *out, float *hue, float *s
}
}
-static void node_shader_exec_hue_sat(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
+static void node_shader_exec_hue_sat(void *UNUSED(data), int UNUSED(thread), bNode *node, bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out)
{
do_hue_sat_fac(node, out[0]->vec, in[0]->vec, in[1]->vec, in[2]->vec, in[4]->vec, in[3]->vec);
}
-static int gpu_shader_hue_sat(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
+static int gpu_shader_hue_sat(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
return GPU_stack_link(mat, "hue_sat", in, out);
}
-void register_node_type_sh_hue_sat(bNodeTreeType *ttype)
+void register_node_type_sh_hue_sat()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_HUE_SAT, "Hue Saturation Value", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_HUE_SAT, "Hue Saturation Value", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_OLD_SHADING|NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_hue_sat_in, sh_node_hue_sat_out);
node_type_size(&ntype, 150, 80, 250);
- node_type_exec(&ntype, node_shader_exec_hue_sat);
+ node_type_exec(&ntype, NULL, NULL, node_shader_exec_hue_sat);
node_type_gpu(&ntype, gpu_shader_hue_sat);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_invert.c b/source/blender/nodes/shader/nodes/node_shader_invert.c
index 2ea858f4e34..f3d4efc82d7 100644
--- a/source/blender/nodes/shader/nodes/node_shader_invert.c
+++ b/source/blender/nodes/shader/nodes/node_shader_invert.c
@@ -46,7 +46,7 @@ static bNodeSocketTemplate sh_node_invert_out[] = {
{ -1, 0, "" }
};
-static void node_shader_exec_invert(void *UNUSED(data), bNode *UNUSED(node), bNodeStack **in,
+static void node_shader_exec_invert(void *UNUSED(data), int UNUSED(thread), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), bNodeStack **in,
bNodeStack **out)
{
float col[3], facm;
@@ -67,21 +67,21 @@ bNodeStack **out)
copy_v3_v3(out[0]->vec, col);
}
-static int gpu_shader_invert(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
+static int gpu_shader_invert(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
return GPU_stack_link(mat, "invert", in, out);
}
-void register_node_type_sh_invert(bNodeTreeType *ttype)
+void register_node_type_sh_invert()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_INVERT, "Invert", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_INVERT, "Invert", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_OLD_SHADING|NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_invert_in, sh_node_invert_out);
node_type_size(&ntype, 90, 80, 100);
- node_type_exec(&ntype, node_shader_exec_invert);
+ node_type_exec(&ntype, NULL, NULL, node_shader_exec_invert);
node_type_gpu(&ntype, gpu_shader_invert);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_layer_weight.c b/source/blender/nodes/shader/nodes/node_shader_layer_weight.c
index 3058483ebef..5b7cb4730ae 100644
--- a/source/blender/nodes/shader/nodes/node_shader_layer_weight.c
+++ b/source/blender/nodes/shader/nodes/node_shader_layer_weight.c
@@ -40,24 +40,23 @@ static bNodeSocketTemplate sh_node_layer_weight_out[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_layer_weight(GPUMaterial *UNUSED(mat), bNode *UNUSED(node), GPUNodeStack *UNUSED(in), GPUNodeStack *UNUSED(out))
+static int node_shader_gpu_layer_weight(GPUMaterial *UNUSED(mat), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *UNUSED(in), GPUNodeStack *UNUSED(out))
{
return 0;
}
/* node type definition */
-void register_node_type_sh_layer_weight(bNodeTreeType *ttype)
+void register_node_type_sh_layer_weight()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_LAYER_WEIGHT, "Layer Weight", NODE_CLASS_INPUT, 0);
+ sh_node_type_base(&ntype, SH_NODE_LAYER_WEIGHT, "Layer Weight", NODE_CLASS_INPUT, 0);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_layer_weight_in, sh_node_layer_weight_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_layer_weight);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_light_falloff.c b/source/blender/nodes/shader/nodes/node_shader_light_falloff.c
index 2dec244ae3a..e30c59f6920 100644
--- a/source/blender/nodes/shader/nodes/node_shader_light_falloff.c
+++ b/source/blender/nodes/shader/nodes/node_shader_light_falloff.c
@@ -44,25 +44,24 @@ static bNodeSocketTemplate sh_node_light_falloff_out[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_light_falloff(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_light_falloff(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
return GPU_stack_link(mat, "node_light_falloff", in, out);
}
/* node type definition */
-void register_node_type_sh_light_falloff(bNodeTreeType *ttype)
+void register_node_type_sh_light_falloff(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_LIGHT_FALLOFF, "Light Falloff", NODE_CLASS_OP_COLOR, 0);
+ sh_node_type_base(&ntype, SH_NODE_LIGHT_FALLOFF, "Light Falloff", NODE_CLASS_OP_COLOR, 0);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_light_falloff_in, sh_node_light_falloff_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_light_falloff);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_light_path.c b/source/blender/nodes/shader/nodes/node_shader_light_path.c
index b4a3d4e01e1..93efc5abfa4 100644
--- a/source/blender/nodes/shader/nodes/node_shader_light_path.c
+++ b/source/blender/nodes/shader/nodes/node_shader_light_path.c
@@ -41,24 +41,23 @@ static bNodeSocketTemplate sh_node_light_path_out[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_light_path(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_light_path(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
return GPU_stack_link(mat, "node_light_path", in, out);
}
/* node type definition */
-void register_node_type_sh_light_path(bNodeTreeType *ttype)
+void register_node_type_sh_light_path()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_LIGHT_PATH, "Light Path", NODE_CLASS_INPUT, 0);
+ sh_node_type_base(&ntype, SH_NODE_LIGHT_PATH, "Light Path", NODE_CLASS_INPUT, 0);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, NULL, sh_node_light_path_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_light_path);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_mapping.c b/source/blender/nodes/shader/nodes/node_shader_mapping.c
index 396c1ac60bf..fc3ef736737 100644
--- a/source/blender/nodes/shader/nodes/node_shader_mapping.c
+++ b/source/blender/nodes/shader/nodes/node_shader_mapping.c
@@ -44,7 +44,7 @@ static bNodeSocketTemplate sh_node_mapping_out[] = {
};
/* do the regular mapping options for blender textures */
-static void node_shader_exec_mapping(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
+static void node_shader_exec_mapping(void *UNUSED(data), int UNUSED(thread), bNode *node, bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out)
{
TexMapping *texmap= node->storage;
float *vec= out[0]->vec;
@@ -67,12 +67,12 @@ static void node_shader_exec_mapping(void *UNUSED(data), bNode *node, bNodeStack
}
-static void node_shader_init_mapping(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_shader_init_mapping(bNodeTree *UNUSED(ntree), bNode *node)
{
node->storage= add_tex_mapping();
}
-static int gpu_shader_mapping(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out)
+static int gpu_shader_mapping(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
TexMapping *texmap= node->storage;
float domin= (texmap->flag & TEXMAP_CLIP_MIN) != 0;
@@ -86,18 +86,18 @@ static int gpu_shader_mapping(GPUMaterial *mat, bNode *node, GPUNodeStack *in, G
return GPU_stack_link(mat, "mapping", in, out, tmat, tmin, tmax, tdomin, tdomax);
}
-void register_node_type_sh_mapping(bNodeTreeType *ttype)
+void register_node_type_sh_mapping()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_MAPPING, "Mapping", NODE_CLASS_OP_VECTOR, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_MAPPING, "Mapping", NODE_CLASS_OP_VECTOR, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_OLD_SHADING|NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_mapping_in, sh_node_mapping_out);
node_type_size(&ntype, 240, 160, 320);
node_type_init(&ntype, node_shader_init_mapping);
node_type_storage(&ntype, "TexMapping", node_free_standard_storage, node_copy_standard_storage);
- node_type_exec(&ntype, node_shader_exec_mapping);
+ node_type_exec(&ntype, NULL, NULL, node_shader_exec_mapping);
node_type_gpu(&ntype, gpu_shader_mapping);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_material.c b/source/blender/nodes/shader/nodes/node_shader_material.c
index a36f35c646d..29612ff74e2 100644
--- a/source/blender/nodes/shader/nodes/node_shader_material.c
+++ b/source/blender/nodes/shader/nodes/node_shader_material.c
@@ -29,7 +29,6 @@
* \ingroup shdnodes
*/
-
#include "node_shader_util.h"
/* **************** MATERIAL ******************** */
@@ -76,7 +75,7 @@ static bNodeSocketTemplate sh_node_material_ext_out[] = {
{ -1, 0, "" }
};
-static void node_shader_exec_material(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+static void node_shader_exec_material(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out)
{
if (data && node->id) {
ShadeResult shrnode;
@@ -170,7 +169,7 @@ static void node_shader_exec_material(void *data, bNode *node, bNodeStack **in,
col[3] = shrnode.alpha;
if (shi->do_preview)
- nodeAddToPreview(node, col, shi->xs, shi->ys, shi->do_manage);
+ BKE_node_preview_set_pixel(execdata->preview, col, shi->xs, shi->ys, shi->do_manage);
copy_v3_v3(out[MAT_OUT_COLOR]->vec, col);
out[MAT_OUT_ALPHA]->vec[0] = shrnode.alpha;
@@ -208,7 +207,7 @@ static void node_shader_exec_material(void *data, bNode *node, bNodeStack **in,
}
-static void node_shader_init_material(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_shader_init_material(bNodeTree *UNUSED(ntree), bNode *node)
{
node->custom1= SH_NODE_MAT_DIFF|SH_NODE_MAT_SPEC;
}
@@ -224,7 +223,7 @@ static GPUNodeLink *gpu_get_input_link(GPUNodeStack *in)
return GPU_uniform(in->vec);
}
-static int gpu_shader_material(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out)
+static int gpu_shader_material(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
if (node->id) {
GPUShadeInput shi;
@@ -308,33 +307,33 @@ static int gpu_shader_material(GPUMaterial *mat, bNode *node, GPUNodeStack *in,
return 0;
}
-void register_node_type_sh_material(bNodeTreeType *ttype)
+void register_node_type_sh_material()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_MATERIAL, "Material", NODE_CLASS_INPUT, NODE_OPTIONS|NODE_PREVIEW);
+ sh_node_type_base(&ntype, SH_NODE_MATERIAL, "Material", NODE_CLASS_INPUT, NODE_OPTIONS|NODE_PREVIEW);
node_type_compatibility(&ntype, NODE_OLD_SHADING);
node_type_socket_templates(&ntype, sh_node_material_in, sh_node_material_out);
node_type_size(&ntype, 120, 80, 240);
node_type_init(&ntype, node_shader_init_material);
- node_type_exec(&ntype, node_shader_exec_material);
+ node_type_exec(&ntype, NULL, NULL, node_shader_exec_material);
node_type_gpu(&ntype, gpu_shader_material);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
-void register_node_type_sh_material_ext(bNodeTreeType *ttype)
+void register_node_type_sh_material_ext()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_MATERIAL_EXT, "Extended Material", NODE_CLASS_INPUT, NODE_OPTIONS|NODE_PREVIEW);
+ sh_node_type_base(&ntype, SH_NODE_MATERIAL_EXT, "Extended Material", NODE_CLASS_INPUT, NODE_OPTIONS|NODE_PREVIEW);
node_type_compatibility(&ntype, NODE_OLD_SHADING);
node_type_socket_templates(&ntype, sh_node_material_ext_in, sh_node_material_ext_out);
node_type_size(&ntype, 120, 80, 240);
node_type_init(&ntype, node_shader_init_material);
- node_type_exec(&ntype, node_shader_exec_material);
+ node_type_exec(&ntype, NULL, NULL, node_shader_exec_material);
node_type_gpu(&ntype, gpu_shader_material);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_math.c b/source/blender/nodes/shader/nodes/node_shader_math.c
index 0b71a3f13b4..08ba48176bb 100644
--- a/source/blender/nodes/shader/nodes/node_shader_math.c
+++ b/source/blender/nodes/shader/nodes/node_shader_math.c
@@ -45,8 +45,7 @@ static bNodeSocketTemplate sh_node_math_out[] = {
{ -1, 0, "" }
};
-static void node_shader_exec_math(void *UNUSED(data), bNode *node, bNodeStack **in,
-bNodeStack **out)
+static void node_shader_exec_math(void *UNUSED(data), int UNUSED(thread), bNode *node, bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out)
{
switch (node->custom1) {
@@ -207,7 +206,7 @@ bNodeStack **out)
}
}
-static int gpu_shader_math(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out)
+static int gpu_shader_math(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
static const char *names[] = {"math_add", "math_subtract", "math_multiply",
"math_divide", "math_sine", "math_cosine", "math_tangent", "math_asin",
@@ -256,18 +255,18 @@ static int gpu_shader_math(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUN
return 1;
}
-void register_node_type_sh_math(bNodeTreeType *ttype)
+void register_node_type_sh_math()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_MATH, "Math", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_MATH, "Math", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_OLD_SHADING|NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_math_in, sh_node_math_out);
node_type_size(&ntype, 120, 110, 160);
node_type_label(&ntype, node_math_label);
node_type_storage(&ntype, "node_math", NULL, NULL);
- node_type_exec(&ntype, node_shader_exec_math);
+ node_type_exec(&ntype, NULL, NULL, node_shader_exec_math);
node_type_gpu(&ntype, gpu_shader_math);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_mixRgb.c b/source/blender/nodes/shader/nodes/node_shader_mixRgb.c
index 18dcc8f7fef..2bbdf91dc65 100644
--- a/source/blender/nodes/shader/nodes/node_shader_mixRgb.c
+++ b/source/blender/nodes/shader/nodes/node_shader_mixRgb.c
@@ -44,7 +44,7 @@ static bNodeSocketTemplate sh_node_mix_rgb_out[] = {
{ -1, 0, "" }
};
-static void node_shader_exec_mix_rgb(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
+static void node_shader_exec_mix_rgb(void *UNUSED(data), int UNUSED(thread), bNode *node, bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out)
{
/* stack order in: fac, col1, col2 */
/* stack order out: col */
@@ -62,7 +62,7 @@ static void node_shader_exec_mix_rgb(void *UNUSED(data), bNode *node, bNodeStack
copy_v3_v3(out[0]->vec, col);
}
-static int gpu_shader_mix_rgb(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out)
+static int gpu_shader_mix_rgb(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
static const char *names[] = {"mix_blend", "mix_add", "mix_mult", "mix_sub",
"mix_screen", "mix_div", "mix_diff", "mix_dark", "mix_light",
@@ -73,17 +73,17 @@ static int gpu_shader_mix_rgb(GPUMaterial *mat, bNode *node, GPUNodeStack *in, G
}
-void register_node_type_sh_mix_rgb(bNodeTreeType *ttype)
+void register_node_type_sh_mix_rgb()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_MIX_RGB, "Mix", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_MIX_RGB, "Mix", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_OLD_SHADING|NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_mix_rgb_in, sh_node_mix_rgb_out);
node_type_size(&ntype, 100, 60, 150);
node_type_label(&ntype, node_blend_label);
- node_type_exec(&ntype, node_shader_exec_mix_rgb);
+ node_type_exec(&ntype, NULL, NULL, node_shader_exec_mix_rgb);
node_type_gpu(&ntype, gpu_shader_mix_rgb);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_mix_shader.c b/source/blender/nodes/shader/nodes/node_shader_mix_shader.c
index 039e63a4dea..56178a8ddbe 100644
--- a/source/blender/nodes/shader/nodes/node_shader_mix_shader.c
+++ b/source/blender/nodes/shader/nodes/node_shader_mix_shader.c
@@ -41,24 +41,23 @@ static bNodeSocketTemplate sh_node_mix_shader_out[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_mix_shader(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_mix_shader(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
return GPU_stack_link(mat, "node_mix_shader", in, out);
}
/* node type definition */
-void register_node_type_sh_mix_shader(bNodeTreeType *ttype)
+void register_node_type_sh_mix_shader()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_MIX_SHADER, "Mix Shader", NODE_CLASS_SHADER, 0);
+ sh_node_type_base(&ntype, SH_NODE_MIX_SHADER, "Mix Shader", NODE_CLASS_SHADER, 0);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_mix_shader_in, sh_node_mix_shader_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_mix_shader);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_normal.c b/source/blender/nodes/shader/nodes/node_shader_normal.c
index 0ad58d6af76..a1f00ee0c33 100644
--- a/source/blender/nodes/shader/nodes/node_shader_normal.c
+++ b/source/blender/nodes/shader/nodes/node_shader_normal.c
@@ -39,26 +39,14 @@ static bNodeSocketTemplate sh_node_normal_in[] = {
};
static bNodeSocketTemplate sh_node_normal_out[] = {
- { SOCK_VECTOR, 0, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_DIRECTION},
+ { SOCK_VECTOR, 0, N_("Normal"), 0.0f, 0.0f, 1.0f, 0.0f, -1.0f, 1.0f, PROP_DIRECTION},
{ SOCK_FLOAT, 0, N_("Dot")},
{ -1, 0, "" }
};
-static void node_shader_init_normal(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
-{
- bNodeSocket *sock= node->outputs.first;
- bNodeSocketValueVector *dval= (bNodeSocketValueVector*)sock->default_value;
-
- /* output value is used for normal vector */
- dval->value[0] = 0.0f;
- dval->value[1] = 0.0f;
- dval->value[2] = 1.0f;
-}
-
/* generates normal, does dot product */
-static void node_shader_exec_normal(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
+static void node_shader_exec_normal(void *UNUSED(data), int UNUSED(thread), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out)
{
- bNodeSocket *sock= node->outputs.first;
float vec[3];
/* stack order input: normal */
@@ -66,29 +54,25 @@ static void node_shader_exec_normal(void *UNUSED(data), bNode *node, bNodeStack
nodestack_get_vec(vec, SOCK_VECTOR, in[0]);
- copy_v3_v3(out[0]->vec, ((bNodeSocketValueVector*)sock->default_value)->value);
/* render normals point inside... the widget points outside */
- out[1]->vec[0] = -dot_v3v3(out[0]->vec, vec);
+ out[1]->vec[0] = -dot_v3v3(vec, out[0]->vec);
}
-static int gpu_shader_normal(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out)
+static int gpu_shader_normal(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
- bNodeSocket *sock= node->outputs.first;
- GPUNodeLink *vec = GPU_uniform(((bNodeSocketValueVector*)sock->default_value)->value);
-
+ GPUNodeLink *vec = GPU_uniform(out[0].vec);
return GPU_stack_link(mat, "normal", in, out, vec);
}
-void register_node_type_sh_normal(bNodeTreeType *ttype)
+void register_node_type_sh_normal()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_NORMAL, "Normal", NODE_CLASS_OP_VECTOR, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_NORMAL, "Normal", NODE_CLASS_OP_VECTOR, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_OLD_SHADING|NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_normal_in, sh_node_normal_out);
- node_type_init(&ntype, node_shader_init_normal);
- node_type_exec(&ntype, node_shader_exec_normal);
+ node_type_exec(&ntype, NULL, NULL, node_shader_exec_normal);
node_type_gpu(&ntype, gpu_shader_normal);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_normal_map.c b/source/blender/nodes/shader/nodes/node_shader_normal_map.c
index 6a4eb9d81df..bca1b0e2798 100644
--- a/source/blender/nodes/shader/nodes/node_shader_normal_map.c
+++ b/source/blender/nodes/shader/nodes/node_shader_normal_map.c
@@ -40,31 +40,30 @@ static bNodeSocketTemplate sh_node_normal_map_out[] = {
{ -1, 0, "" }
};
-static void node_shader_init_normal_map(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_shader_init_normal_map(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeShaderNormalMap *attr = MEM_callocN(sizeof(NodeShaderNormalMap), "NodeShaderNormalMap");
node->storage = attr;
}
-static int gpu_shader_normal_map(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
+static int gpu_shader_normal_map(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
return GPU_stack_link(mat, "node_normal_map", in, out, GPU_builtin(GPU_VIEW_NORMAL));
}
/* node type definition */
-void register_node_type_sh_normal_map(bNodeTreeType *ttype)
+void register_node_type_sh_normal_map()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_NORMAL_MAP, "Normal Map", NODE_CLASS_OP_VECTOR, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_NORMAL_MAP, "Normal Map", NODE_CLASS_OP_VECTOR, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_normal_map_in, sh_node_normal_map_out);
node_type_size(&ntype, 250, 60, 250);
node_type_init(&ntype, node_shader_init_normal_map);
node_type_storage(&ntype, "NodeShaderNormalMap", node_free_standard_storage, node_copy_standard_storage);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, gpu_shader_normal_map);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_object_info.c b/source/blender/nodes/shader/nodes/node_shader_object_info.c
index ef283004d46..d00037546ea 100644
--- a/source/blender/nodes/shader/nodes/node_shader_object_info.c
+++ b/source/blender/nodes/shader/nodes/node_shader_object_info.c
@@ -37,25 +37,24 @@ static bNodeSocketTemplate sh_node_object_info_out[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_object_info(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_object_info(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
return GPU_stack_link(mat, "node_object_info", in, out);
}
/* node type definition */
-void register_node_type_sh_object_info(bNodeTreeType *ttype)
+void register_node_type_sh_object_info(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_OBJECT_INFO, "Object Info", NODE_CLASS_INPUT, 0);
+ sh_node_type_base(&ntype, SH_NODE_OBJECT_INFO, "Object Info", NODE_CLASS_INPUT, 0);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, NULL, sh_node_object_info_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_object_info);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_output.c b/source/blender/nodes/shader/nodes/node_shader_output.c
index 6f7f900aecd..4c2fdf146da 100644
--- a/source/blender/nodes/shader/nodes/node_shader_output.c
+++ b/source/blender/nodes/shader/nodes/node_shader_output.c
@@ -39,7 +39,7 @@ static bNodeSocketTemplate sh_node_output_in[] = {
{ -1, 0, "" }
};
-static void node_shader_exec_output(void *data, bNode *node, bNodeStack **in, bNodeStack **UNUSED(out))
+static void node_shader_exec_output(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **UNUSED(out))
{
if (data) {
ShadeInput *shi= ((ShaderCallData *)data)->shi;
@@ -50,7 +50,7 @@ static void node_shader_exec_output(void *data, bNode *node, bNodeStack **in, bN
nodestack_get_vec(col+3, SOCK_FLOAT, in[1]);
if (shi->do_preview) {
- nodeAddToPreview(node, col, shi->xs, shi->ys, shi->do_manage);
+ BKE_node_preview_set_pixel(execdata->preview, col, shi->xs, shi->ys, shi->do_manage);
node->lasty= shi->ys;
}
@@ -65,7 +65,7 @@ static void node_shader_exec_output(void *data, bNode *node, bNodeStack **in, bN
}
}
-static int gpu_shader_output(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
+static int gpu_shader_output(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
GPUNodeLink *outlink;
@@ -80,19 +80,19 @@ static int gpu_shader_output(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack
return 1;
}
-void register_node_type_sh_output(bNodeTreeType *ttype)
+void register_node_type_sh_output()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_OUTPUT, "Output", NODE_CLASS_OUTPUT, NODE_PREVIEW);
+ sh_node_type_base(&ntype, SH_NODE_OUTPUT, "Output", NODE_CLASS_OUTPUT, NODE_PREVIEW);
node_type_compatibility(&ntype, NODE_OLD_SHADING);
node_type_socket_templates(&ntype, sh_node_output_in, NULL);
node_type_size(&ntype, 80, 60, 200);
- node_type_exec(&ntype, node_shader_exec_output);
+ node_type_exec(&ntype, NULL, NULL, node_shader_exec_output);
node_type_gpu(&ntype, gpu_shader_output);
/* Do not allow muting output node. */
node_type_internal_links(&ntype, NULL);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_output_lamp.c b/source/blender/nodes/shader/nodes/node_shader_output_lamp.c
index ce406a8f5a1..e44326428b5 100644
--- a/source/blender/nodes/shader/nodes/node_shader_output_lamp.c
+++ b/source/blender/nodes/shader/nodes/node_shader_output_lamp.c
@@ -35,21 +35,19 @@ static bNodeSocketTemplate sh_node_output_lamp_in[] = {
};
/* node type definition */
-void register_node_type_sh_output_lamp(bNodeTreeType *ttype)
+void register_node_type_sh_output_lamp()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_OUTPUT_LAMP, "Lamp Output", NODE_CLASS_OUTPUT, 0);
+ sh_node_type_base(&ntype, SH_NODE_OUTPUT_LAMP, "Lamp Output", NODE_CLASS_OUTPUT, 0);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_output_lamp_in, NULL);
node_type_size(&ntype, 120, 60, 200);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
- node_type_exec(&ntype, NULL);
- node_type_gpu(&ntype, NULL);
/* Do not allow muting output node. */
node_type_internal_links(&ntype, NULL);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_output_material.c b/source/blender/nodes/shader/nodes/node_shader_output_material.c
index f185e13010b..90030d6699b 100644
--- a/source/blender/nodes/shader/nodes/node_shader_output_material.c
+++ b/source/blender/nodes/shader/nodes/node_shader_output_material.c
@@ -36,7 +36,7 @@ static bNodeSocketTemplate sh_node_output_material_in[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_output_material(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_output_material(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
GPUNodeLink *outlink;
@@ -48,21 +48,20 @@ static int node_shader_gpu_output_material(GPUMaterial *mat, bNode *UNUSED(node)
/* node type definition */
-void register_node_type_sh_output_material(bNodeTreeType *ttype)
+void register_node_type_sh_output_material()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_OUTPUT_MATERIAL, "Material Output", NODE_CLASS_OUTPUT, 0);
+ sh_node_type_base(&ntype, SH_NODE_OUTPUT_MATERIAL, "Material Output", NODE_CLASS_OUTPUT, 0);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_output_material_in, NULL);
node_type_size(&ntype, 120, 60, 200);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_output_material);
/* Do not allow muting output node. */
node_type_internal_links(&ntype, NULL);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_output_world.c b/source/blender/nodes/shader/nodes/node_shader_output_world.c
index 953197ab2cd..e9a60bd34e3 100644
--- a/source/blender/nodes/shader/nodes/node_shader_output_world.c
+++ b/source/blender/nodes/shader/nodes/node_shader_output_world.c
@@ -36,21 +36,19 @@ static bNodeSocketTemplate sh_node_output_world_in[] = {
};
/* node type definition */
-void register_node_type_sh_output_world(bNodeTreeType *ttype)
+void register_node_type_sh_output_world()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_OUTPUT_WORLD, "World Output", NODE_CLASS_OUTPUT, 0);
+ sh_node_type_base(&ntype, SH_NODE_OUTPUT_WORLD, "World Output", NODE_CLASS_OUTPUT, 0);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_output_world_in, NULL);
node_type_size(&ntype, 120, 60, 200);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
- node_type_exec(&ntype, NULL);
- node_type_gpu(&ntype, NULL);
/* Do not allow muting output node. */
node_type_internal_links(&ntype, NULL);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_particle_info.c b/source/blender/nodes/shader/nodes/node_shader_particle_info.c
index c7e31d117cc..e4d91d524d2 100644
--- a/source/blender/nodes/shader/nodes/node_shader_particle_info.c
+++ b/source/blender/nodes/shader/nodes/node_shader_particle_info.c
@@ -42,15 +42,15 @@ static bNodeSocketTemplate outputs[] = {
};
/* node type definition */
-void register_node_type_sh_particle_info(bNodeTreeType *ttype)
+void register_node_type_sh_particle_info(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_PARTICLE_INFO, "Particle Info", NODE_CLASS_INPUT, 0);
+ sh_node_type_base(&ntype, SH_NODE_PARTICLE_INFO, "Particle Info", NODE_CLASS_INPUT, 0);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, NULL, outputs);
node_type_size(&ntype, 150, 60, 200);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_rgb.c b/source/blender/nodes/shader/nodes/node_shader_rgb.c
index f37ff1d511b..b3215fc6803 100644
--- a/source/blender/nodes/shader/nodes/node_shader_rgb.c
+++ b/source/blender/nodes/shader/nodes/node_shader_rgb.c
@@ -34,49 +34,25 @@
/* **************** RGB ******************** */
static bNodeSocketTemplate sh_node_rgb_out[] = {
- { SOCK_RGBA, 0, N_("Color")},
+ { SOCK_RGBA, 0, N_("Color"), 0.5f, 0.5f, 0.5f, 1.0f},
{ -1, 0, "" }
};
-static void node_shader_init_rgb(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static int gpu_shader_rgb(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
- bNodeSocket *sock= node->outputs.first;
- bNodeSocketValueRGBA *dval= (bNodeSocketValueRGBA*)sock->default_value;
- /* uses the default value of the output socket, must be initialized here */
- dval->value[0] = 0.5f;
- dval->value[1] = 0.5f;
- dval->value[2] = 0.5f;
- dval->value[3] = 1.0f;
-}
-
-static void node_shader_exec_rgb(void *UNUSED(data), bNode *node, bNodeStack **UNUSED(in), bNodeStack **out)
-{
- bNodeSocket *sock= node->outputs.first;
- float *col= ((bNodeSocketValueRGBA*)sock->default_value)->value;
-
- copy_v3_v3(out[0]->vec, col);
-}
-
-static int gpu_shader_rgb(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out)
-{
- bNodeSocket *sock= node->outputs.first;
- float *col= ((bNodeSocketValueRGBA*)sock->default_value)->value;
- GPUNodeLink *vec = GPU_uniform(col);
-
+ GPUNodeLink *vec = GPU_uniform(out[0].vec);
return GPU_stack_link(mat, "set_rgba", in, out, vec);
}
-void register_node_type_sh_rgb(bNodeTreeType *ttype)
+void register_node_type_sh_rgb()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_RGB, "RGB", NODE_CLASS_INPUT, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_RGB, "RGB", NODE_CLASS_INPUT, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_OLD_SHADING|NODE_NEW_SHADING);
node_type_socket_templates(&ntype, NULL, sh_node_rgb_out);
- node_type_init(&ntype, node_shader_init_rgb);
node_type_size(&ntype, 140, 80, 140);
- node_type_exec(&ntype, node_shader_exec_rgb);
node_type_gpu(&ntype, gpu_shader_rgb);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_script.c b/source/blender/nodes/shader/nodes/node_shader_script.c
index b5563658a64..8b4c2702474 100644
--- a/source/blender/nodes/shader/nodes/node_shader_script.c
+++ b/source/blender/nodes/shader/nodes/node_shader_script.c
@@ -35,7 +35,7 @@
/* **************** Script ******************** */
-static void init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void init(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeShaderScript *nss = MEM_callocN(sizeof(NodeShaderScript), "shader script node");
node->storage = nss;
@@ -50,37 +50,29 @@ static void node_free_script(bNode *node)
MEM_freeN(nss->bytecode);
}
- if (nss->prop) {
- IDP_FreeProperty(nss->prop);
- MEM_freeN(nss->prop);
- }
-
MEM_freeN(nss);
}
}
-static void node_copy_script(bNode *orig_node, bNode *new_node)
+static void node_copy_script(bNodeTree *UNUSED(dest_ntree), bNode *dest_node, bNode *src_node)
{
- NodeShaderScript *orig_nss = orig_node->storage;
- NodeShaderScript *new_nss = MEM_dupallocN(orig_nss);
-
- if (orig_nss->bytecode)
- new_nss->bytecode = MEM_dupallocN(orig_nss->bytecode);
+ NodeShaderScript *src_nss = src_node->storage;
+ NodeShaderScript *dest_nss = MEM_dupallocN(src_nss);
- if (orig_nss->prop)
- new_nss->prop = IDP_CopyProperty(orig_nss->prop);
+ if (src_nss->bytecode)
+ dest_nss->bytecode = MEM_dupallocN(src_nss->bytecode);
- new_node->storage = new_nss;
+ dest_node->storage = dest_nss;
}
-void register_node_type_sh_script(bNodeTreeType *ttype)
+void register_node_type_sh_script()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_SCRIPT, "Script", NODE_CLASS_SCRIPT, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_SCRIPT, "Script", NODE_CLASS_SCRIPT, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_init(&ntype, init);
node_type_storage(&ntype, "NodeShaderScript", node_free_script, node_copy_script);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_sepcombRGB.c b/source/blender/nodes/shader/nodes/node_shader_sepcombRGB.c
index 70fba161de9..1f6cd3506e9 100644
--- a/source/blender/nodes/shader/nodes/node_shader_sepcombRGB.c
+++ b/source/blender/nodes/shader/nodes/node_shader_sepcombRGB.c
@@ -44,30 +44,30 @@ static bNodeSocketTemplate sh_node_seprgb_out[] = {
{ -1, 0, "" }
};
-static void node_shader_exec_seprgb(void *UNUSED(data), bNode *UNUSED(node), bNodeStack **in, bNodeStack **out)
+static void node_shader_exec_seprgb(void *UNUSED(data), int UNUSED(thread), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out)
{
out[0]->vec[0] = in[0]->vec[0];
out[1]->vec[0] = in[0]->vec[1];
out[2]->vec[0] = in[0]->vec[2];
}
-static int gpu_shader_seprgb(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
+static int gpu_shader_seprgb(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
return GPU_stack_link(mat, "separate_rgb", in, out);
}
-void register_node_type_sh_seprgb(bNodeTreeType *ttype)
+void register_node_type_sh_seprgb()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_SEPRGB, "Separate RGB", NODE_CLASS_CONVERTOR, 0);
+ sh_node_type_base(&ntype, SH_NODE_SEPRGB, "Separate RGB", NODE_CLASS_CONVERTOR, 0);
node_type_compatibility(&ntype, NODE_OLD_SHADING|NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_seprgb_in, sh_node_seprgb_out);
node_type_size(&ntype, 80, 40, 140);
- node_type_exec(&ntype, node_shader_exec_seprgb);
+ node_type_exec(&ntype, NULL, NULL, node_shader_exec_seprgb);
node_type_gpu(&ntype, gpu_shader_seprgb);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
@@ -84,28 +84,28 @@ static bNodeSocketTemplate sh_node_combrgb_out[] = {
{ -1, 0, "" }
};
-static void node_shader_exec_combrgb(void *UNUSED(data), bNode *UNUSED(node), bNodeStack **in, bNodeStack **out)
+static void node_shader_exec_combrgb(void *UNUSED(data), int UNUSED(thread), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out)
{
out[0]->vec[0] = in[0]->vec[0];
out[0]->vec[1] = in[1]->vec[0];
out[0]->vec[2] = in[2]->vec[0];
}
-static int gpu_shader_combrgb(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
+static int gpu_shader_combrgb(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
return GPU_stack_link(mat, "combine_rgb", in, out);
}
-void register_node_type_sh_combrgb(bNodeTreeType *ttype)
+void register_node_type_sh_combrgb()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_COMBRGB, "Combine RGB", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_COMBRGB, "Combine RGB", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_OLD_SHADING|NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_combrgb_in, sh_node_combrgb_out);
node_type_size(&ntype, 80, 40, 140);
- node_type_exec(&ntype, node_shader_exec_combrgb);
+ node_type_exec(&ntype, NULL, NULL, node_shader_exec_combrgb);
node_type_gpu(&ntype, gpu_shader_combrgb);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_squeeze.c b/source/blender/nodes/shader/nodes/node_shader_squeeze.c
index 8073f4b01d2..538efb15cb3 100644
--- a/source/blender/nodes/shader/nodes/node_shader_squeeze.c
+++ b/source/blender/nodes/shader/nodes/node_shader_squeeze.c
@@ -45,7 +45,7 @@ static bNodeSocketTemplate sh_node_squeeze_out[] = {
{ -1, 0, "" }
};
-static void node_shader_exec_squeeze(void *UNUSED(data), bNode *UNUSED(node), bNodeStack **in, bNodeStack **out)
+static void node_shader_exec_squeeze(void *UNUSED(data), int UNUSED(thread), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out)
{
float vec[3];
@@ -56,22 +56,22 @@ static void node_shader_exec_squeeze(void *UNUSED(data), bNode *UNUSED(node), bN
out[0]->vec[0] = 1.0f / (1.0f + powf(M_E, -((vec[0] - vec[2]) * vec[1])));
}
-static int gpu_shader_squeeze(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
+static int gpu_shader_squeeze(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
return GPU_stack_link(mat, "squeeze", in, out);
}
-void register_node_type_sh_squeeze(bNodeTreeType *ttype)
+void register_node_type_sh_squeeze()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_SQUEEZE, "Squeeze Value", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_SQUEEZE, "Squeeze Value", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_OLD_SHADING);
node_type_socket_templates(&ntype, sh_node_squeeze_in, sh_node_squeeze_out);
node_type_size(&ntype, 120, 110, 160);
node_type_storage(&ntype, "node_squeeze", NULL, NULL);
- node_type_exec(&ntype, node_shader_exec_squeeze);
+ node_type_exec(&ntype, NULL, NULL, node_shader_exec_squeeze);
node_type_gpu(&ntype, gpu_shader_squeeze);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_tangent.c b/source/blender/nodes/shader/nodes/node_shader_tangent.c
index 6c0d6d7cd9f..a51c943285b 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tangent.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tangent.c
@@ -34,7 +34,7 @@ static bNodeSocketTemplate sh_node_tangent_out[] = {
{ -1, 0, "" }
};
-static void node_shader_init_tangent(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_shader_init_tangent(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeShaderTangent *attr = MEM_callocN(sizeof(NodeShaderTangent), "NodeShaderTangent");
attr->axis = SHD_TANGENT_AXIS_Z;
@@ -42,19 +42,16 @@ static void node_shader_init_tangent(bNodeTree *UNUSED(ntree), bNode *node, bNod
}
/* node type definition */
-void register_node_type_sh_tangent(bNodeTreeType *ttype)
+void register_node_type_sh_tangent()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_TANGENT, "Tangent", NODE_CLASS_INPUT, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_TANGENT, "Tangent", NODE_CLASS_INPUT, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, NULL, sh_node_tangent_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, node_shader_init_tangent);
node_type_storage(&ntype, "NodeShaderTangent", node_free_standard_storage, node_copy_standard_storage);
- node_type_exec(&ntype, NULL);
- node_type_gpu(&ntype, NULL);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
-
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_brick.c b/source/blender/nodes/shader/nodes/node_shader_tex_brick.c
index 66bf0267586..dad74d324f8 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_brick.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_brick.c
@@ -48,7 +48,7 @@ static bNodeSocketTemplate sh_node_tex_brick_out[] = {
{ -1, 0, "" }
};
-static void node_shader_init_tex_brick(bNodeTree *UNUSED(ntree), bNode* node, bNodeTemplate *UNUSED(ntemp))
+static void node_shader_init_tex_brick(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeTexBrick *tex = MEM_callocN(sizeof(NodeTexBrick), "NodeTexBrick");
default_tex_mapping(&tex->base.tex_mapping);
@@ -62,7 +62,7 @@ static void node_shader_init_tex_brick(bNodeTree *UNUSED(ntree), bNode* node, bN
node->storage = tex;
}
-static int node_shader_gpu_tex_brick(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_tex_brick(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
if (!in[0].link)
in[0].link = GPU_attribute(CD_ORCO, "");
@@ -73,18 +73,17 @@ static int node_shader_gpu_tex_brick(GPUMaterial *mat, bNode *node, GPUNodeStack
}
/* node type definition */
-void register_node_type_sh_tex_brick(bNodeTreeType *ttype)
+void register_node_type_sh_tex_brick(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_TEX_BRICK, "Brick Texture", NODE_CLASS_TEXTURE, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_TEX_BRICK, "Brick Texture", NODE_CLASS_TEXTURE, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_tex_brick_in, sh_node_tex_brick_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, node_shader_init_tex_brick);
node_type_storage(&ntype, "NodeTexBrick", node_free_standard_storage, node_copy_standard_storage);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_tex_brick);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_checker.c b/source/blender/nodes/shader/nodes/node_shader_tex_checker.c
index 8a2ae2d40dc..aff92e58f90 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_checker.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_checker.c
@@ -43,7 +43,7 @@ static bNodeSocketTemplate sh_node_tex_checker_out[] = {
{ -1, 0, "" }
};
-static void node_shader_init_tex_checker(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_shader_init_tex_checker(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeTexChecker *tex = MEM_callocN(sizeof(NodeTexChecker), "NodeTexChecker");
default_tex_mapping(&tex->base.tex_mapping);
@@ -52,7 +52,7 @@ static void node_shader_init_tex_checker(bNodeTree *UNUSED(ntree), bNode *node,
node->storage = tex;
}
-static int node_shader_gpu_tex_checker(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_tex_checker(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
if (!in[0].link)
in[0].link = GPU_attribute(CD_ORCO, "");
@@ -63,18 +63,17 @@ static int node_shader_gpu_tex_checker(GPUMaterial *mat, bNode *node, GPUNodeSta
}
/* node type definition */
-void register_node_type_sh_tex_checker(bNodeTreeType *ttype)
+void register_node_type_sh_tex_checker()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_TEX_CHECKER, "Checker Texture", NODE_CLASS_TEXTURE, 0);
+ sh_node_type_base(&ntype, SH_NODE_TEX_CHECKER, "Checker Texture", NODE_CLASS_TEXTURE, 0);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_tex_checker_in, sh_node_tex_checker_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, node_shader_init_tex_checker);
node_type_storage(&ntype, "NodeTexChecker", node_free_standard_storage, node_copy_standard_storage);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_tex_checker);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_coord.c b/source/blender/nodes/shader/nodes/node_shader_tex_coord.c
index dd717874951..d2b69aebf96 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_coord.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_coord.c
@@ -42,7 +42,7 @@ static bNodeSocketTemplate sh_node_tex_coord_out[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_tex_coord(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_tex_coord(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
GPUNodeLink *orco = GPU_attribute(CD_ORCO, "");
GPUNodeLink *mtface = GPU_attribute(CD_MTFACE, "");
@@ -53,18 +53,17 @@ static int node_shader_gpu_tex_coord(GPUMaterial *mat, bNode *UNUSED(node), GPUN
}
/* node type definition */
-void register_node_type_sh_tex_coord(bNodeTreeType *ttype)
+void register_node_type_sh_tex_coord()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_TEX_COORD, "Texture Coordinate", NODE_CLASS_INPUT, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_TEX_COORD, "Texture Coordinate", NODE_CLASS_INPUT, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, NULL, sh_node_tex_coord_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_tex_coord);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c
index d2d0870e2ed..25cc892c944 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c
@@ -41,7 +41,7 @@ static bNodeSocketTemplate sh_node_tex_environment_out[] = {
{ -1, 0, "" }
};
-static void node_shader_init_tex_environment(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_shader_init_tex_environment(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeTexEnvironment *tex = MEM_callocN(sizeof(NodeTexEnvironment), "NodeTexEnvironment");
default_tex_mapping(&tex->base.tex_mapping);
@@ -56,7 +56,7 @@ static void node_shader_init_tex_environment(bNodeTree *UNUSED(ntree), bNode *no
node->storage = tex;
}
-static int node_shader_gpu_tex_environment(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_tex_environment(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
Image *ima= (Image*)node->id;
ImageUser *iuser= NULL;
@@ -88,18 +88,17 @@ static int node_shader_gpu_tex_environment(GPUMaterial *mat, bNode *node, GPUNod
}
/* node type definition */
-void register_node_type_sh_tex_environment(bNodeTreeType *ttype)
+void register_node_type_sh_tex_environment()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_TEX_ENVIRONMENT, "Environment Texture", NODE_CLASS_TEXTURE, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_TEX_ENVIRONMENT, "Environment Texture", NODE_CLASS_TEXTURE, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_tex_environment_in, sh_node_tex_environment_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, node_shader_init_tex_environment);
node_type_storage(&ntype, "NodeTexEnvironment", node_free_standard_storage, node_copy_standard_storage);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_tex_environment);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_gradient.c b/source/blender/nodes/shader/nodes/node_shader_tex_gradient.c
index 0802ecdea1d..ab962c946f2 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_gradient.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_gradient.c
@@ -40,7 +40,7 @@ static bNodeSocketTemplate sh_node_tex_gradient_out[] = {
{ -1, 0, "" }
};
-static void node_shader_init_tex_gradient(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_shader_init_tex_gradient(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeTexGradient *tex = MEM_callocN(sizeof(NodeTexGradient), "NodeTexGradient");
default_tex_mapping(&tex->base.tex_mapping);
@@ -50,7 +50,7 @@ static void node_shader_init_tex_gradient(bNodeTree *UNUSED(ntree), bNode *node,
node->storage = tex;
}
-static int node_shader_gpu_tex_gradient(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_tex_gradient(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
if (!in[0].link)
in[0].link = GPU_attribute(CD_ORCO, "");
@@ -61,18 +61,17 @@ static int node_shader_gpu_tex_gradient(GPUMaterial *mat, bNode *node, GPUNodeSt
}
/* node type definition */
-void register_node_type_sh_tex_gradient(bNodeTreeType *ttype)
+void register_node_type_sh_tex_gradient()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_TEX_GRADIENT, "Gradient Texture", NODE_CLASS_TEXTURE, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_TEX_GRADIENT, "Gradient Texture", NODE_CLASS_TEXTURE, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_tex_gradient_in, sh_node_tex_gradient_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, node_shader_init_tex_gradient);
node_type_storage(&ntype, "NodeTexGradient", node_free_standard_storage, node_copy_standard_storage);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_tex_gradient);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_image.c b/source/blender/nodes/shader/nodes/node_shader_tex_image.c
index 49b38434246..a30acd80712 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_image.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_image.c
@@ -42,7 +42,7 @@ static bNodeSocketTemplate sh_node_tex_image_out[] = {
{ -1, 0, "" }
};
-static void node_shader_init_tex_image(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_shader_init_tex_image(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeTexImage *tex = MEM_callocN(sizeof(NodeTexImage), "NodeTexImage");
default_tex_mapping(&tex->base.tex_mapping);
@@ -56,7 +56,7 @@ static void node_shader_init_tex_image(bNodeTree *UNUSED(ntree), bNode *node, bN
node->storage = tex;
}
-static int node_shader_gpu_tex_image(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_tex_image(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
Image *ima= (Image*)node->id;
ImageUser *iuser= NULL;
@@ -88,18 +88,17 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat, bNode *node, GPUNodeStack
}
/* node type definition */
-void register_node_type_sh_tex_image(bNodeTreeType *ttype)
+void register_node_type_sh_tex_image()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_TEX_IMAGE, "Image Texture", NODE_CLASS_TEXTURE, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_TEX_IMAGE, "Image Texture", NODE_CLASS_TEXTURE, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_tex_image_in, sh_node_tex_image_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, node_shader_init_tex_image);
node_type_storage(&ntype, "NodeTexImage", node_free_standard_storage, node_copy_standard_storage);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_tex_image);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_magic.c b/source/blender/nodes/shader/nodes/node_shader_tex_magic.c
index 86feabbcc2b..8d32cac9dab 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_magic.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_magic.c
@@ -42,7 +42,7 @@ static bNodeSocketTemplate sh_node_tex_magic_out[] = {
{ -1, 0, "" }
};
-static void node_shader_init_tex_magic(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_shader_init_tex_magic(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeTexMagic *tex = MEM_callocN(sizeof(NodeTexMagic), "NodeTexMagic");
default_tex_mapping(&tex->base.tex_mapping);
@@ -52,7 +52,7 @@ static void node_shader_init_tex_magic(bNodeTree *UNUSED(ntree), bNode *node, bN
node->storage = tex;
}
-static int node_shader_gpu_tex_magic(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_tex_magic(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
NodeTexMagic *tex = (NodeTexMagic*)node->storage;
float depth = tex->depth;
@@ -66,18 +66,17 @@ static int node_shader_gpu_tex_magic(GPUMaterial *mat, bNode *node, GPUNodeStack
}
/* node type definition */
-void register_node_type_sh_tex_magic(bNodeTreeType *ttype)
+void register_node_type_sh_tex_magic()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_TEX_MAGIC, "Magic Texture", NODE_CLASS_TEXTURE, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_TEX_MAGIC, "Magic Texture", NODE_CLASS_TEXTURE, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_tex_magic_in, sh_node_tex_magic_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, node_shader_init_tex_magic);
node_type_storage(&ntype, "NodeTexMagic", node_free_standard_storage, node_copy_standard_storage);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_tex_magic);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c b/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c
index cd4b5743e14..d4f7c9d0c1c 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c
@@ -46,7 +46,7 @@ static bNodeSocketTemplate sh_node_tex_musgrave_out[] = {
{ -1, 0, "" }
};
-static void node_shader_init_tex_musgrave(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_shader_init_tex_musgrave(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeTexMusgrave *tex = MEM_callocN(sizeof(NodeTexMusgrave), "NodeTexMusgrave");
default_tex_mapping(&tex->base.tex_mapping);
@@ -56,7 +56,7 @@ static void node_shader_init_tex_musgrave(bNodeTree *UNUSED(ntree), bNode *node,
node->storage = tex;
}
-static int node_shader_gpu_tex_musgrave(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_tex_musgrave(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
if (!in[0].link)
in[0].link = GPU_attribute(CD_ORCO, "");
@@ -67,18 +67,17 @@ static int node_shader_gpu_tex_musgrave(GPUMaterial *mat, bNode *node, GPUNodeSt
}
/* node type definition */
-void register_node_type_sh_tex_musgrave(bNodeTreeType *ttype)
+void register_node_type_sh_tex_musgrave()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_TEX_MUSGRAVE, "Musgrave Texture", NODE_CLASS_TEXTURE, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_TEX_MUSGRAVE, "Musgrave Texture", NODE_CLASS_TEXTURE, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_tex_musgrave_in, sh_node_tex_musgrave_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, node_shader_init_tex_musgrave);
node_type_storage(&ntype, "NodeTexMusgrave", node_free_standard_storage, node_copy_standard_storage);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_tex_musgrave);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_noise.c b/source/blender/nodes/shader/nodes/node_shader_tex_noise.c
index 18788f9e72c..0143645f448 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_noise.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_noise.c
@@ -43,7 +43,7 @@ static bNodeSocketTemplate sh_node_tex_noise_out[] = {
{ -1, 0, "" }
};
-static void node_shader_init_tex_noise(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_shader_init_tex_noise(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeTexNoise *tex = MEM_callocN(sizeof(NodeTexNoise), "NodeTexNoise");
default_tex_mapping(&tex->base.tex_mapping);
@@ -52,7 +52,7 @@ static void node_shader_init_tex_noise(bNodeTree *UNUSED(ntree), bNode *node, bN
node->storage = tex;
}
-static int node_shader_gpu_tex_noise(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_tex_noise(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
if (!in[0].link)
in[0].link = GPU_attribute(CD_ORCO, "");
@@ -63,18 +63,17 @@ static int node_shader_gpu_tex_noise(GPUMaterial *mat, bNode *node, GPUNodeStack
}
/* node type definition */
-void register_node_type_sh_tex_noise(bNodeTreeType *ttype)
+void register_node_type_sh_tex_noise()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_TEX_NOISE, "Noise Texture", NODE_CLASS_TEXTURE, 0);
+ sh_node_type_base(&ntype, SH_NODE_TEX_NOISE, "Noise Texture", NODE_CLASS_TEXTURE, 0);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_tex_noise_in, sh_node_tex_noise_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, node_shader_init_tex_noise);
node_type_storage(&ntype, "NodeTexNoise", node_free_standard_storage, node_copy_standard_storage);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_tex_noise);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_sky.c b/source/blender/nodes/shader/nodes/node_shader_tex_sky.c
index 7a1b853a7f4..2aa977bade6 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_sky.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_sky.c
@@ -39,7 +39,7 @@ static bNodeSocketTemplate sh_node_tex_sky_out[] = {
{ -1, 0, "" }
};
-static void node_shader_init_tex_sky(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_shader_init_tex_sky(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeTexSky *tex = MEM_callocN(sizeof(NodeTexSky), "NodeTexSky");
default_tex_mapping(&tex->base.tex_mapping);
@@ -52,7 +52,7 @@ static void node_shader_init_tex_sky(bNodeTree *UNUSED(ntree), bNode *node, bNod
node->storage = tex;
}
-static int node_shader_gpu_tex_sky(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_tex_sky(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
if (!in[0].link)
in[0].link = GPU_attribute(CD_ORCO, "");
@@ -63,18 +63,17 @@ static int node_shader_gpu_tex_sky(GPUMaterial *mat, bNode *node, GPUNodeStack *
}
/* node type definition */
-void register_node_type_sh_tex_sky(bNodeTreeType *ttype)
+void register_node_type_sh_tex_sky()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_TEX_SKY, "Sky Texture", NODE_CLASS_TEXTURE, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_TEX_SKY, "Sky Texture", NODE_CLASS_TEXTURE, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_tex_sky_in, sh_node_tex_sky_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, node_shader_init_tex_sky);
node_type_storage(&ntype, "NodeTexSky", node_free_standard_storage, node_copy_standard_storage);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_tex_sky);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.c b/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.c
index d4cc24687b3..cf7d775914e 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.c
@@ -41,7 +41,7 @@ static bNodeSocketTemplate sh_node_tex_voronoi_out[] = {
{ -1, 0, "" }
};
-static void node_shader_init_tex_voronoi(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_shader_init_tex_voronoi(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeTexVoronoi *tex = MEM_callocN(sizeof(NodeTexVoronoi), "NodeTexVoronoi");
default_tex_mapping(&tex->base.tex_mapping);
@@ -51,7 +51,7 @@ static void node_shader_init_tex_voronoi(bNodeTree *UNUSED(ntree), bNode *node,
node->storage = tex;
}
-static int node_shader_gpu_tex_voronoi(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_tex_voronoi(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
if (!in[0].link)
in[0].link = GPU_attribute(CD_ORCO, "");
@@ -62,18 +62,17 @@ static int node_shader_gpu_tex_voronoi(GPUMaterial *mat, bNode *node, GPUNodeSta
}
/* node type definition */
-void register_node_type_sh_tex_voronoi(bNodeTreeType *ttype)
+void register_node_type_sh_tex_voronoi()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_TEX_VORONOI, "Voronoi Texture", NODE_CLASS_TEXTURE, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_TEX_VORONOI, "Voronoi Texture", NODE_CLASS_TEXTURE, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_tex_voronoi_in, sh_node_tex_voronoi_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, node_shader_init_tex_voronoi);
node_type_storage(&ntype, "NodeTexVoronoi", node_free_standard_storage, node_copy_standard_storage);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_tex_voronoi);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_wave.c b/source/blender/nodes/shader/nodes/node_shader_tex_wave.c
index 8b23de0310c..2f085df8d07 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_wave.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_wave.c
@@ -44,7 +44,7 @@ static bNodeSocketTemplate sh_node_tex_wave_out[] = {
{ -1, 0, "" }
};
-static void node_shader_init_tex_wave(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_shader_init_tex_wave(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeTexWave *tex = MEM_callocN(sizeof(NodeTexWave), "NodeTexWave");
default_tex_mapping(&tex->base.tex_mapping);
@@ -54,7 +54,7 @@ static void node_shader_init_tex_wave(bNodeTree *UNUSED(ntree), bNode *node, bNo
node->storage = tex;
}
-static int node_shader_gpu_tex_wave(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_tex_wave(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
if (!in[0].link)
in[0].link = GPU_attribute(CD_ORCO, "");
@@ -65,18 +65,17 @@ static int node_shader_gpu_tex_wave(GPUMaterial *mat, bNode *node, GPUNodeStack
}
/* node type definition */
-void register_node_type_sh_tex_wave(bNodeTreeType *ttype)
+void register_node_type_sh_tex_wave()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_TEX_WAVE, "Wave Texture", NODE_CLASS_TEXTURE, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_TEX_WAVE, "Wave Texture", NODE_CLASS_TEXTURE, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_tex_wave_in, sh_node_tex_wave_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, node_shader_init_tex_wave);
node_type_storage(&ntype, "NodeTexWave", node_free_standard_storage, node_copy_standard_storage);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_tex_wave);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_texture.c b/source/blender/nodes/shader/nodes/node_shader_texture.c
index ec238b62408..4f6cc574be3 100644
--- a/source/blender/nodes/shader/nodes/node_shader_texture.c
+++ b/source/blender/nodes/shader/nodes/node_shader_texture.c
@@ -48,7 +48,7 @@ static bNodeSocketTemplate sh_node_texture_out[] = {
{ -1, 0, "" }
};
-static void node_shader_exec_texture(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+static void node_shader_exec_texture(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out)
{
if (data && node->id) {
ShadeInput *shi= ((ShaderCallData *)data)->shi;
@@ -113,13 +113,14 @@ static void node_shader_exec_texture(void *data, bNode *node, bNodeStack **in, b
copy_v3_v3(out[2]->vec, nor);
- if (shi->do_preview)
- nodeAddToPreview(node, out[1]->vec, shi->xs, shi->ys, shi->do_manage);
+ if (shi->do_preview) {
+ BKE_node_preview_set_pixel(execdata->preview, out[1]->vec, shi->xs, shi->ys, shi->do_manage);
+ }
}
}
-static int gpu_shader_texture(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out)
+static int gpu_shader_texture(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
Tex *tex = (Tex*)node->id;
@@ -143,16 +144,16 @@ static int gpu_shader_texture(GPUMaterial *mat, bNode *node, GPUNodeStack *in, G
return 0;
}
-void register_node_type_sh_texture(bNodeTreeType *ttype)
+void register_node_type_sh_texture()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_TEXTURE, "Texture", NODE_CLASS_INPUT, NODE_OPTIONS|NODE_PREVIEW);
+ sh_node_type_base(&ntype, SH_NODE_TEXTURE, "Texture", NODE_CLASS_INPUT, NODE_OPTIONS|NODE_PREVIEW);
node_type_compatibility(&ntype, NODE_OLD_SHADING);
node_type_socket_templates(&ntype, sh_node_texture_in, sh_node_texture_out);
node_type_size(&ntype, 120, 80, 240);
- node_type_exec(&ntype, node_shader_exec_texture);
+ node_type_exec(&ntype, NULL, NULL, node_shader_exec_texture);
node_type_gpu(&ntype, gpu_shader_texture);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_valToRgb.c b/source/blender/nodes/shader/nodes/node_shader_valToRgb.c
index 182487d343e..e70ac6b700e 100644
--- a/source/blender/nodes/shader/nodes/node_shader_valToRgb.c
+++ b/source/blender/nodes/shader/nodes/node_shader_valToRgb.c
@@ -43,7 +43,7 @@ static bNodeSocketTemplate sh_node_valtorgb_out[] = {
{ -1, 0, "" }
};
-static void node_shader_exec_valtorgb(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
+static void node_shader_exec_valtorgb(void *UNUSED(data), int UNUSED(thread), bNode *node, bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out)
{
/* stack order in: fac */
/* stack order out: col, alpha */
@@ -57,12 +57,12 @@ static void node_shader_exec_valtorgb(void *UNUSED(data), bNode *node, bNodeStac
}
}
-static void node_shader_init_valtorgb(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_shader_init_valtorgb(bNodeTree *UNUSED(ntree), bNode *node)
{
node->storage= add_colorband(1);
}
-static int gpu_shader_valtorgb(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out)
+static int gpu_shader_valtorgb(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
float *array;
int size;
@@ -71,20 +71,20 @@ static int gpu_shader_valtorgb(GPUMaterial *mat, bNode *node, GPUNodeStack *in,
return GPU_stack_link(mat, "valtorgb", in, out, GPU_texture(size, array));
}
-void register_node_type_sh_valtorgb(bNodeTreeType *ttype)
+void register_node_type_sh_valtorgb()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_VALTORGB, "ColorRamp", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_VALTORGB, "ColorRamp", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_OLD_SHADING|NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_valtorgb_in, sh_node_valtorgb_out);
node_type_size(&ntype, 240, 200, 300);
node_type_init(&ntype, node_shader_init_valtorgb);
node_type_storage(&ntype, "ColorBand", node_free_standard_storage, node_copy_standard_storage);
- node_type_exec(&ntype, node_shader_exec_valtorgb);
+ node_type_exec(&ntype, NULL, NULL, node_shader_exec_valtorgb);
node_type_gpu(&ntype, gpu_shader_valtorgb);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
@@ -99,7 +99,7 @@ static bNodeSocketTemplate sh_node_rgbtobw_out[] = {
};
-static void node_shader_exec_rgbtobw(void *UNUSED(data), bNode *UNUSED(node), bNodeStack **in, bNodeStack **out)
+static void node_shader_exec_rgbtobw(void *UNUSED(data), int UNUSED(thread), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out)
{
/* stack order out: bw */
/* stack order in: col */
@@ -107,21 +107,21 @@ static void node_shader_exec_rgbtobw(void *UNUSED(data), bNode *UNUSED(node), bN
out[0]->vec[0] = rgb_to_bw(in[0]->vec);
}
-static int gpu_shader_rgbtobw(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
+static int gpu_shader_rgbtobw(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
return GPU_stack_link(mat, "rgbtobw", in, out);
}
-void register_node_type_sh_rgbtobw(bNodeTreeType *ttype)
+void register_node_type_sh_rgbtobw()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_RGBTOBW, "RGB to BW", NODE_CLASS_CONVERTOR, 0);
+ sh_node_type_base(&ntype, SH_NODE_RGBTOBW, "RGB to BW", NODE_CLASS_CONVERTOR, 0);
node_type_compatibility(&ntype, NODE_OLD_SHADING|NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_rgbtobw_in, sh_node_rgbtobw_out);
node_type_size(&ntype, 80, 40, 120);
- node_type_exec(&ntype, node_shader_exec_rgbtobw);
+ node_type_exec(&ntype, NULL, NULL, node_shader_exec_rgbtobw);
node_type_gpu(&ntype, gpu_shader_rgbtobw);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_value.c b/source/blender/nodes/shader/nodes/node_shader_value.c
index a3d1e5afec2..00a23283a14 100644
--- a/source/blender/nodes/shader/nodes/node_shader_value.c
+++ b/source/blender/nodes/shader/nodes/node_shader_value.c
@@ -34,49 +34,25 @@
/* **************** VALUE ******************** */
static bNodeSocketTemplate sh_node_value_out[] = {
- /* XXX value nodes use the output sockets for buttons, so we need explicit limits here! */
- { SOCK_FLOAT, 0, N_("Value"), 0.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX},
+ { SOCK_FLOAT, 0, N_("Value"), 0.5f, 0, 0, 0, -FLT_MAX, FLT_MAX, PROP_NONE},
{ -1, 0, "" }
};
-static void node_shader_init_value(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static int gpu_shader_value(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
- bNodeSocket *sock= node->outputs.first;
- bNodeSocketValueFloat *dval= (bNodeSocketValueFloat*)sock->default_value;
- /* uses the default value of the output socket, must be initialized here */
- dval->value = 0.5f;
- dval->min = -FLT_MAX;
- dval->max = FLT_MAX;
-}
-
-static void node_shader_exec_value(void *UNUSED(data), bNode *node, bNodeStack **UNUSED(in), bNodeStack **out)
-{
- bNodeSocket *sock= node->outputs.first;
- float val= ((bNodeSocketValueFloat*)sock->default_value)->value;
-
- out[0]->vec[0] = val;
-}
-
-static int gpu_shader_value(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out)
-{
- bNodeSocket *sock= node->outputs.first;
- float *val= &((bNodeSocketValueFloat*)sock->default_value)->value;
- GPUNodeLink *vec = GPU_uniform(val);
-
+ GPUNodeLink *vec = GPU_uniform(out[0].vec);
return GPU_stack_link(mat, "set_value", in, out, vec);
}
-void register_node_type_sh_value(bNodeTreeType *ttype)
+void register_node_type_sh_value()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_VALUE, "Value", NODE_CLASS_INPUT, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_VALUE, "Value", NODE_CLASS_INPUT, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_OLD_SHADING|NODE_NEW_SHADING);
node_type_socket_templates(&ntype, NULL, sh_node_value_out);
- node_type_init(&ntype, node_shader_init_value);
node_type_size(&ntype, 80, 50, 120);
- node_type_exec(&ntype, node_shader_exec_value);
node_type_gpu(&ntype, gpu_shader_value);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_vectMath.c b/source/blender/nodes/shader/nodes/node_shader_vectMath.c
index 3e00421ddf0..7a76f408916 100644
--- a/source/blender/nodes/shader/nodes/node_shader_vectMath.c
+++ b/source/blender/nodes/shader/nodes/node_shader_vectMath.c
@@ -47,7 +47,7 @@ static bNodeSocketTemplate sh_node_vect_math_out[] = {
{ -1, 0, "" }
};
-static void node_shader_exec_vect_math(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
+static void node_shader_exec_vect_math(void *UNUSED(data), int UNUSED(thread), bNode *node, bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out)
{
float vec1[3], vec2[3];
@@ -102,7 +102,7 @@ static void node_shader_exec_vect_math(void *UNUSED(data), bNode *node, bNodeSta
}
-static int gpu_shader_vect_math(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out)
+static int gpu_shader_vect_math(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
static const char *names[] = {"vec_math_add", "vec_math_sub",
"vec_math_average", "vec_math_dot", "vec_math_cross",
@@ -139,18 +139,18 @@ static int gpu_shader_vect_math(GPUMaterial *mat, bNode *node, GPUNodeStack *in,
return 1;
}
-void register_node_type_sh_vect_math(bNodeTreeType *ttype)
+void register_node_type_sh_vect_math()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_VECT_MATH, "Vector Math", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_VECT_MATH, "Vector Math", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_OLD_SHADING|NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_vect_math_in, sh_node_vect_math_out);
node_type_size(&ntype, 80, 75, 140);
node_type_label(&ntype, node_vect_math_label);
node_type_storage(&ntype, "node_vect_math", NULL, NULL);
- node_type_exec(&ntype, node_shader_exec_vect_math);
+ node_type_exec(&ntype, NULL, NULL, node_shader_exec_vect_math);
node_type_gpu(&ntype, gpu_shader_vect_math);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_volume_isotropic.c b/source/blender/nodes/shader/nodes/node_shader_volume_isotropic.c
index 5451eb303cc..5ce62e2e15b 100644
--- a/source/blender/nodes/shader/nodes/node_shader_volume_isotropic.c
+++ b/source/blender/nodes/shader/nodes/node_shader_volume_isotropic.c
@@ -40,24 +40,23 @@ static bNodeSocketTemplate sh_node_volume_isotropic_out[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_volume_isotropic(GPUMaterial *UNUSED(mat), bNode *UNUSED(node), GPUNodeStack *UNUSED(in), GPUNodeStack *UNUSED(out))
+static int node_shader_gpu_volume_isotropic(GPUMaterial *UNUSED(mat), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *UNUSED(in), GPUNodeStack *UNUSED(out))
{
return 0;
}
/* node type definition */
-void register_node_type_sh_volume_isotropic(bNodeTreeType *ttype)
+void register_node_type_sh_volume_isotropic()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_VOLUME_ISOTROPIC, "Isotropic Volume", NODE_CLASS_SHADER, 0);
+ sh_node_type_base(&ntype, SH_NODE_VOLUME_ISOTROPIC, "Isotropic Volume", NODE_CLASS_SHADER, 0);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_volume_isotropic_in, sh_node_volume_isotropic_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_volume_isotropic);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_volume_transparent.c b/source/blender/nodes/shader/nodes/node_shader_volume_transparent.c
index ad7d7fceda3..cd4ad5d0080 100644
--- a/source/blender/nodes/shader/nodes/node_shader_volume_transparent.c
+++ b/source/blender/nodes/shader/nodes/node_shader_volume_transparent.c
@@ -40,24 +40,23 @@ static bNodeSocketTemplate sh_node_volume_transparent_out[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_volume_transparent(GPUMaterial *UNUSED(mat), bNode *UNUSED(node), GPUNodeStack *UNUSED(in), GPUNodeStack *UNUSED(out))
+static int node_shader_gpu_volume_transparent(GPUMaterial *UNUSED(mat), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *UNUSED(in), GPUNodeStack *UNUSED(out))
{
return 0;
}
/* node type definition */
-void register_node_type_sh_volume_transparent(bNodeTreeType *ttype)
+void register_node_type_sh_volume_transparent()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_VOLUME_TRANSPARENT, "Transparent Volume", NODE_CLASS_SHADER, 0);
+ sh_node_type_base(&ntype, SH_NODE_VOLUME_TRANSPARENT, "Transparent Volume", NODE_CLASS_SHADER, 0);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_volume_transparent_in, sh_node_volume_transparent_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_volume_transparent);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/texture/node_texture_tree.c b/source/blender/nodes/texture/node_texture_tree.c
index ba94531c259..0690ccdd19f 100644
--- a/source/blender/nodes/texture/node_texture_tree.c
+++ b/source/blender/nodes/texture/node_texture_tree.c
@@ -34,6 +34,7 @@
#include "DNA_texture_types.h"
#include "DNA_node_types.h"
+#include "DNA_space_types.h"
#include "BLI_listbase.h"
#include "BLI_threads.h"
@@ -41,9 +42,11 @@
#include "BLF_translation.h"
+#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_node.h"
+#include "BKE_paint.h"
#include "node_common.h"
#include "node_exec.h"
@@ -51,16 +54,57 @@
#include "NOD_texture.h"
#include "node_texture_util.h"
+#include "RNA_access.h"
+
#include "RE_pipeline.h"
#include "RE_shader_ext.h"
-static void foreach_nodetree(Main *main, void *calldata, bNodeTreeCallback func)
+static void texture_get_from_context(const bContext *C, bNodeTreeType *UNUSED(treetype), bNodeTree **r_ntree, ID **r_id, ID **r_from)
{
- Tex *tx;
- for (tx = main->tex.first; tx; tx = tx->id.next) {
- if (tx->nodetree) {
- func(calldata, &tx->id, tx->nodetree);
+ SpaceNode *snode = CTX_wm_space_node(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = OBACT;
+ Tex *tx = NULL;
+
+ if (snode->texfrom == SNODE_TEX_OBJECT) {
+ if (ob) {
+ tx = give_current_object_texture(ob);
+ if (tx) {
+ if (ob->type == OB_LAMP)
+ *r_from = (ID*)ob->data;
+ else
+ *r_from = (ID*)give_current_material(ob, ob->actcol);
+
+ /* from is not set fully for material nodes, should be ID + Node then */
+ *r_id = &tx->id;
+ *r_ntree = tx->nodetree;
+ }
+ }
+ }
+ else if (snode->texfrom == SNODE_TEX_WORLD) {
+ tx = give_current_world_texture(scene->world);
+ if (tx) {
+ *r_from = (ID *)scene->world;
+ *r_id = &tx->id;
+ *r_ntree = tx->nodetree;
+ }
+ }
+ else {
+ struct Brush *brush = NULL;
+
+ if (ob && (ob->mode & OB_MODE_SCULPT))
+ brush = paint_brush(&scene->toolsettings->sculpt->paint);
+ else
+ brush = paint_brush(&scene->toolsettings->imapaint.paint);
+
+ if (brush) {
+ *r_from = (ID *)brush;
+ tx = give_current_brush_texture(brush);
+ if (tx) {
+ *r_id = &tx->id;
+ *r_ntree = tx->nodetree;
+ }
}
}
}
@@ -75,6 +119,7 @@ static void foreach_nodeclass(Scene *UNUSED(scene), void *calldata, bNodeClassCa
func(calldata, NODE_CLASS_CONVERTOR, N_("Convertor"));
func(calldata, NODE_CLASS_DISTORT, N_("Distort"));
func(calldata, NODE_CLASS_GROUP, N_("Group"));
+ func(calldata, NODE_CLASS_INTERFACE, N_("Interface"));
func(calldata, NODE_CLASS_LAYOUT, N_("Layout"));
}
@@ -93,49 +138,42 @@ static void localize(bNodeTree *localtree, bNodeTree *UNUSED(ntree))
}
}
-static void local_sync(bNodeTree *localtree, bNodeTree *ntree)
+static void local_sync(bNodeTree *UNUSED(localtree), bNodeTree *UNUSED(ntree))
{
- bNode *lnode;
-
- /* copy over contents of previews */
- for (lnode = localtree->nodes.first; lnode; lnode = lnode->next) {
- if (ntreeNodeExists(ntree, lnode->new_node)) {
- bNode *node = lnode->new_node;
-
- if (node->preview && node->preview->rect) {
- if (lnode->preview && lnode->preview->rect) {
- int xsize = node->preview->xsize;
- int ysize = node->preview->ysize;
- memcpy(node->preview->rect, lnode->preview->rect, 4 * xsize + xsize * ysize * sizeof(char) * 4);
- }
- }
- }
- }
}
static void update(bNodeTree *ntree)
{
ntree_update_reroute_nodes(ntree);
+
+ if (ntree->update & NTREE_UPDATE_NODES) {
+ /* clean up preview cache, in case nodes have been removed */
+ BKE_node_preview_remove_unused(ntree);
+ }
}
-bNodeTreeType ntreeType_Texture = {
- /* type */ NTREE_TEXTURE,
- /* id_name */ "NTTexture Nodetree",
+bNodeTreeType *ntreeType_Texture;
+
+void register_node_tree_type_tex()
+{
+ bNodeTreeType *tt = ntreeType_Texture = MEM_callocN(sizeof(bNodeTreeType), "texture node tree type");
- /* node_types */ { NULL, NULL },
+ tt->type = NTREE_TEXTURE;
+ strcpy(tt->idname, "TextureNodeTree");
+ strcpy(tt->ui_name, "Texture");
+ tt->ui_icon = 0; /* defined in drawnode.c */
+ strcpy(tt->ui_description, "");
- /* free_cache */ NULL,
- /* free_node_cache */ NULL,
- /* foreach_nodetree */ foreach_nodetree,
- /* foreach_nodeclass */ foreach_nodeclass,
- /* localize */ localize,
- /* local_sync */ local_sync,
- /* local_merge */ NULL,
- /* update */ update,
- /* update_node */ NULL,
- /* validate_link */ NULL,
- /* update_internal_links */ node_update_internal_links_default
-};
+ tt->foreach_nodeclass = foreach_nodeclass;
+ tt->update = update;
+ tt->localize = localize;
+ tt->local_sync = local_sync;
+ tt->get_from_context = texture_get_from_context;
+
+ tt->ext.srna = &RNA_TextureNodeTree;
+
+ ntreeTypeAdd(tt);
+}
int ntreeTexTagAnimated(bNodeTree *ntree)
{
@@ -158,24 +196,13 @@ int ntreeTexTagAnimated(bNodeTree *ntree)
return 0;
}
-/* XXX Group nodes must set use_tree_data to false, since their trees can be shared by multiple nodes.
- * If use_tree_data is true, the ntree->execdata pointer is checked to avoid multiple execution of top-level trees.
- */
-bNodeTreeExec *ntreeTexBeginExecTree(bNodeTree *ntree, int use_tree_data)
+bNodeTreeExec *ntreeTexBeginExecTree_internal(bNodeExecContext *context, bNodeTree *ntree, bNodeInstanceKey parent_key)
{
bNodeTreeExec *exec;
bNode *node;
- if (use_tree_data) {
- /* XXX hack: prevent exec data from being generated twice.
- * this should be handled by the renderer!
- */
- if (ntree->execdata)
- return ntree->execdata;
- }
-
/* common base initialization */
- exec = ntree_exec_begin(ntree);
+ exec = ntree_exec_begin(context, ntree, parent_key);
/* allocate the thread stack listbase array */
exec->threadstack = MEM_callocN(BLENDER_MAX_THREADS * sizeof(ListBase), "thread stack array");
@@ -183,12 +210,28 @@ bNodeTreeExec *ntreeTexBeginExecTree(bNodeTree *ntree, int use_tree_data)
for (node = exec->nodetree->nodes.first; node; node = node->next)
node->need_exec = 1;
- if (use_tree_data) {
- /* XXX this should not be necessary, but is still used for cmp/sha/tex nodes,
- * which only store the ntree pointer. Should be fixed at some point!
- */
- ntree->execdata = exec;
- }
+ return exec;
+}
+
+bNodeTreeExec *ntreeTexBeginExecTree(bNodeTree *ntree)
+{
+ bNodeExecContext context;
+ bNodeTreeExec *exec;
+
+ /* XXX hack: prevent exec data from being generated twice.
+ * this should be handled by the renderer!
+ */
+ if (ntree->execdata)
+ return ntree->execdata;
+
+ context.previews = ntree->previews;
+
+ exec = ntreeTexBeginExecTree_internal(&context, ntree, NODE_INSTANCE_KEY_BASE);
+
+ /* XXX this should not be necessary, but is still used for cmp/sha/tex nodes,
+ * which only store the ntree pointer. Should be fixed at some point!
+ */
+ ntree->execdata = exec;
return exec;
}
@@ -207,35 +250,34 @@ static void tex_free_delegates(bNodeTreeExec *exec)
MEM_freeN(ns->data);
}
-/* XXX Group nodes must set use_tree_data to false, since their trees can be shared by multiple nodes.
- * If use_tree_data is true, the ntree->execdata pointer is checked to avoid multiple execution of top-level trees.
- */
-void ntreeTexEndExecTree(bNodeTreeExec *exec, int use_tree_data)
+void ntreeTexEndExecTree_internal(bNodeTreeExec *exec)
{
- if (exec) {
- bNodeTree *ntree = exec->nodetree;
- bNodeThreadStack *nts;
- int a;
+ bNodeThreadStack *nts;
+ int a;
+
+ if (exec->threadstack) {
+ tex_free_delegates(exec);
- if (exec->threadstack) {
- tex_free_delegates(exec);
-
- for (a = 0; a < BLENDER_MAX_THREADS; a++) {
- for (nts = exec->threadstack[a].first; nts; nts = nts->next)
- if (nts->stack) MEM_freeN(nts->stack);
- BLI_freelistN(&exec->threadstack[a]);
- }
-
- MEM_freeN(exec->threadstack);
- exec->threadstack = NULL;
+ for (a = 0; a < BLENDER_MAX_THREADS; a++) {
+ for (nts = exec->threadstack[a].first; nts; nts = nts->next)
+ if (nts->stack) MEM_freeN(nts->stack);
+ BLI_freelistN(&exec->threadstack[a]);
}
- ntree_exec_end(exec);
+ MEM_freeN(exec->threadstack);
+ exec->threadstack = NULL;
+ }
+
+ ntree_exec_end(exec);
+}
+
+void ntreeTexEndExecTree(bNodeTreeExec *exec)
+{
+ if (exec) {
+ ntreeTexEndExecTree_internal(exec);
- if (use_tree_data) {
- /* XXX clear nodetree backpointer to exec data, same problem as noted in ntreeBeginExecTree */
- ntree->execdata = NULL;
- }
+ /* XXX clear nodetree backpointer to exec data, same problem as noted in ntreeBeginExecTree */
+ exec->nodetree->execdata = NULL;
}
}
@@ -275,7 +317,7 @@ int ntreeTexExecTree(
if (!exec) {
BLI_lock_thread(LOCK_NODES);
if (!nodes->execdata)
- ntreeTexBeginExecTree(nodes, 1);
+ ntreeTexBeginExecTree(nodes);
BLI_unlock_thread(LOCK_NODES);
exec = nodes->execdata;
diff --git a/source/blender/nodes/texture/node_texture_util.c b/source/blender/nodes/texture/node_texture_util.c
index 06473d800d0..80644157b02 100644
--- a/source/blender/nodes/texture/node_texture_util.c
+++ b/source/blender/nodes/texture/node_texture_util.c
@@ -49,13 +49,28 @@
#include <assert.h>
#include "node_texture_util.h"
+
+int tex_node_poll_default(bNodeType *UNUSED(ntype), bNodeTree *ntree)
+{
+ return (strcmp(ntree->idname, "TextureNodeTree")==0);
+}
+
+void tex_node_type_base(struct bNodeType *ntype, int type, const char *name, short nclass, short flag)
+{
+ node_type_base(ntype, type, name, nclass, flag);
+
+ ntype->poll = tex_node_poll_default;
+ ntype->update_internal_links = node_update_internal_links_default;
+}
+
+
static void tex_call_delegate(TexDelegate *dg, float *out, TexParams *params, short thread)
{
if (dg->node->need_exec) {
dg->fn(out, params, dg->node, dg->in, thread);
if (dg->cdata->do_preview)
- tex_do_preview(dg->node, params->previewco, out);
+ tex_do_preview(dg->preview, params->previewco, out);
}
}
@@ -112,19 +127,17 @@ void params_from_cdata(TexParams *out, TexCallData *in)
out->mtex = in->mtex;
}
-void tex_do_preview(bNode *node, const float coord[2], const float col[4])
+void tex_do_preview(bNodePreview *preview, const float coord[2], const float col[4])
{
- bNodePreview *preview = node->preview;
-
if (preview) {
int xs = ((coord[0] + 1.0f) * 0.5f) * preview->xsize;
int ys = ((coord[1] + 1.0f) * 0.5f) * preview->ysize;
-
- nodeAddToPreview(node, col, xs, ys, 0); /* 0 = no color management */
+
+ BKE_node_preview_set_pixel(preview, col, xs, ys, 0); /* 0 = no color management */
}
}
-void tex_output(bNode *node, bNodeStack **in, bNodeStack *out, TexFn texfn, TexCallData *cdata)
+void tex_output(bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack *out, TexFn texfn, TexCallData *cdata)
{
TexDelegate *dg;
if (!out->data)
@@ -136,6 +149,7 @@ void tex_output(bNode *node, bNodeStack **in, bNodeStack *out, TexFn texfn, TexC
dg->cdata = cdata;
dg->fn = texfn;
dg->node = node;
+ dg->preview = execdata->preview;
memcpy(dg->in, in, MAX_SOCKET * sizeof(bNodeStack *));
dg->type = out->sockettype;
}
diff --git a/source/blender/nodes/texture/node_texture_util.h b/source/blender/nodes/texture/node_texture_util.h
index 3b2a7e14f69..b81ea51ddff 100644
--- a/source/blender/nodes/texture/node_texture_util.h
+++ b/source/blender/nodes/texture/node_texture_util.h
@@ -65,6 +65,7 @@
#include "BKE_library.h"
#include "node_util.h"
+#include "NOD_texture.h"
#include "NOD_texture.h"
@@ -111,16 +112,21 @@ typedef struct TexDelegate {
TexCallData *cdata;
TexFn fn;
bNode *node;
+ bNodePreview *preview;
bNodeStack *in[MAX_SOCKET];
int type;
} TexDelegate;
+
+int tex_node_poll_default(struct bNodeType *ntype, struct bNodeTree *ntree);
+void tex_node_type_base(struct bNodeType *ntype, int type, const char *name, short nclass, short flag);
+
void tex_input_rgba(float *out, bNodeStack *in, TexParams *params, short thread);
void tex_input_vec(float *out, bNodeStack *in, TexParams *params, short thread);
float tex_input_value(bNodeStack *in, TexParams *params, short thread);
-void tex_output(bNode *node, bNodeStack **in, bNodeStack *out, TexFn texfn, TexCallData *data);
-void tex_do_preview(bNode *node, const float coord[2], const float col[4]);
+void tex_output(bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack *out, TexFn texfn, TexCallData *data);
+void tex_do_preview(bNodePreview *preview, const float coord[2], const float col[4]);
void params_from_cdata(TexParams *out, TexCallData *in);
diff --git a/source/blender/nodes/texture/nodes/node_texture_at.c b/source/blender/nodes/texture/nodes/node_texture_at.c
index 4c2d276b902..ef930a39fe3 100644
--- a/source/blender/nodes/texture/nodes/node_texture_at.c
+++ b/source/blender/nodes/texture/nodes/node_texture_at.c
@@ -53,19 +53,19 @@ static void colorfn(float *out, TexParams *p, bNode *UNUSED(node), bNodeStack **
tex_input_rgba(out, in[0], &np, thread);
}
-static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+static void exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out)
{
- tex_output(node, in, out[0], &colorfn, data);
+ tex_output(node, execdata, in, out[0], &colorfn, data);
}
-void register_node_type_tex_at(bNodeTreeType *ttype)
+void register_node_type_tex_at()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, TEX_NODE_AT, "At", NODE_CLASS_DISTORT, 0);
+ tex_node_type_base(&ntype, TEX_NODE_AT, "At", NODE_CLASS_DISTORT, 0);
node_type_socket_templates(&ntype, inputs, outputs);
node_type_size(&ntype, 140, 100, 320);
- node_type_exec(&ntype, exec);
+ node_type_exec(&ntype, NULL, NULL, exec);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/texture/nodes/node_texture_bricks.c b/source/blender/nodes/texture/nodes/node_texture_bricks.c
index b4f81f08e43..afcbf4216c3 100644
--- a/source/blender/nodes/texture/nodes/node_texture_bricks.c
+++ b/source/blender/nodes/texture/nodes/node_texture_bricks.c
@@ -50,7 +50,7 @@ static bNodeSocketTemplate outputs[] = {
{ -1, 0, "" }
};
-static void init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void init(bNodeTree *UNUSED(ntree), bNode *node)
{
node->custom3 = 0.5; /* offset */
node->custom4 = 1.0; /* squash */
@@ -116,20 +116,20 @@ static void colorfn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
}
}
-static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+static void exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out)
{
- tex_output(node, in, out[0], &colorfn, data);
+ tex_output(node, execdata, in, out[0], &colorfn, data);
}
-void register_node_type_tex_bricks(bNodeTreeType *ttype)
+void register_node_type_tex_bricks()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, TEX_NODE_BRICKS, "Bricks", NODE_CLASS_PATTERN, NODE_PREVIEW|NODE_OPTIONS);
+ tex_node_type_base(&ntype, TEX_NODE_BRICKS, "Bricks", NODE_CLASS_PATTERN, NODE_PREVIEW|NODE_OPTIONS);
node_type_socket_templates(&ntype, inputs, outputs);
node_type_size(&ntype, 150, 60, 150);
node_type_init(&ntype, init);
- node_type_exec(&ntype, exec);
+ node_type_exec(&ntype, NULL, NULL, exec);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/texture/nodes/node_texture_checker.c b/source/blender/nodes/texture/nodes/node_texture_checker.c
index 1f653d1f7b9..53c91db0312 100644
--- a/source/blender/nodes/texture/nodes/node_texture_checker.c
+++ b/source/blender/nodes/texture/nodes/node_texture_checker.c
@@ -65,19 +65,19 @@ static void colorfn(float *out, TexParams *p, bNode *UNUSED(node), bNodeStack **
}
}
-static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+static void exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out)
{
- tex_output(node, in, out[0], &colorfn, data);
+ tex_output(node, execdata, in, out[0], &colorfn, data);
}
-void register_node_type_tex_checker(bNodeTreeType *ttype)
+void register_node_type_tex_checker()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, TEX_NODE_CHECKER, "Checker", NODE_CLASS_PATTERN, NODE_PREVIEW|NODE_OPTIONS);
+ tex_node_type_base(&ntype, TEX_NODE_CHECKER, "Checker", NODE_CLASS_PATTERN, NODE_PREVIEW|NODE_OPTIONS);
node_type_socket_templates(&ntype, inputs, outputs);
node_type_size(&ntype, 100, 60, 150);
- node_type_exec(&ntype, exec);
+ node_type_exec(&ntype, NULL, NULL, exec);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/texture/nodes/node_texture_common.c b/source/blender/nodes/texture/nodes/node_texture_common.c
index aa427ff3587..2af2a3a1999 100644
--- a/source/blender/nodes/texture/nodes/node_texture_common.c
+++ b/source/blender/nodes/texture/nodes/node_texture_common.c
@@ -38,9 +38,12 @@
#include "BKE_node.h"
#include "node_texture_util.h"
+#include "NOD_common.h"
#include "node_common.h"
#include "node_exec.h"
+#include "RNA_access.h"
+
static void copy_stack(bNodeStack *to, bNodeStack *from)
{
if (to != from) {
@@ -55,7 +58,7 @@ static void copy_stack(bNodeStack *to, bNodeStack *from)
/**** GROUP ****/
-static void *group_initexec(bNode *node)
+static void *group_initexec(bNodeExecContext *context, bNode *node, bNodeInstanceKey key)
{
bNodeTree *ngroup= (bNodeTree*)node->id;
void *exec;
@@ -64,7 +67,7 @@ static void *group_initexec(bNode *node)
return NULL;
/* initialize the internal node tree execution */
- exec = ntreeTexBeginExecTree(ngroup, 0);
+ exec = ntreeTexBeginExecTree_internal(context, ngroup, key);
return exec;
}
@@ -73,43 +76,56 @@ static void group_freeexec(bNode *UNUSED(node), void *nodedata)
{
bNodeTreeExec*gexec= (bNodeTreeExec*)nodedata;
- ntreeTexEndExecTree(gexec, 0);
+ ntreeTexEndExecTree_internal(gexec);
}
/* Copy inputs to the internal stack.
* This is a shallow copy, no buffers are duplicated here!
*/
-static void group_copy_inputs(bNode *node, bNodeStack **in, bNodeStack *gstack)
+static void group_copy_inputs(bNode *gnode, bNodeStack **in, bNodeStack *gstack)
{
+ bNodeTree *ngroup = (bNodeTree*)gnode->id;
+ bNode *node;
bNodeSocket *sock;
bNodeStack *ns;
int a;
- for (sock=node->inputs.first, a=0; sock; sock=sock->next, ++a) {
- if (sock->groupsock) {
- ns = node_get_socket_stack(gstack, sock->groupsock);
- copy_stack(ns, in[a]);
+
+ for (node = ngroup->nodes.first; node; node = node->next) {
+ if (node->type == NODE_GROUP_INPUT) {
+ for (sock = node->outputs.first, a = 0; sock; sock = sock->next, ++a) {
+ ns = node_get_socket_stack(gstack, sock);
+ if (ns)
+ copy_stack(ns, in[a]);
+ }
}
}
}
/* Copy internal results to the external outputs.
*/
-static void group_copy_outputs(bNode *node, bNodeStack **out, bNodeStack *gstack)
+static void group_copy_outputs(bNode *gnode, bNodeStack **out, bNodeStack *gstack)
{
+ bNodeTree *ngroup = (bNodeTree*)gnode->id;
+ bNode *node;
bNodeSocket *sock;
bNodeStack *ns;
int a;
- for (sock=node->outputs.first, a=0; sock; sock=sock->next, ++a) {
- if (sock->groupsock) {
- ns = node_get_socket_stack(gstack, sock->groupsock);
- copy_stack(out[a], ns);
+
+ for (node = ngroup->nodes.first; node; node = node->next) {
+ if (node->type == NODE_GROUP_OUTPUT && (node->flag & NODE_DO_OUTPUT)) {
+ for (sock = node->inputs.first, a = 0; sock; sock = sock->next, ++a) {
+ ns = node_get_socket_stack(gstack, sock);
+ if (ns)
+ copy_stack(out[a], ns);
+ }
+ break; /* only one active output node */
}
}
}
-static void group_execute(void *data, int thread, struct bNode *node, void *nodedata, struct bNodeStack **in, struct bNodeStack **out)
+static void group_execute(void *data, int thread, struct bNode *node, bNodeExecData *execdata, struct bNodeStack **in, struct bNodeStack **out)
{
- bNodeTreeExec *exec= (bNodeTreeExec*)nodedata;
+ bNodeTreeExec *exec= execdata->data;
bNodeThreadStack *nts;
if (!exec)
@@ -133,20 +149,27 @@ static void group_execute(void *data, int thread, struct bNode *node, void *node
ntreeReleaseThreadStack(nts);
}
-void register_node_type_tex_group(bNodeTreeType *ttype)
+void register_node_type_tex_group()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, NODE_GROUP, "Group", NODE_CLASS_GROUP, NODE_OPTIONS|NODE_CONST_OUTPUT);
+ /* NB: cannot use sh_node_type_base for node group, because it would map the node type
+ * to the shared NODE_GROUP integer type id.
+ */
+ node_type_base_custom(&ntype, "TextureNodeGroup", "Group", NODE_CLASS_GROUP, NODE_OPTIONS | NODE_CONST_OUTPUT);
+ ntype.type = NODE_GROUP;
+ ntype.poll = tex_node_poll_default;
+ ntype.update_internal_links = node_update_internal_links_default;
+ ntype.ext.srna = RNA_struct_find("TextureNodeGroup");
+ BLI_assert(ntype.ext.srna != NULL);
+ RNA_struct_blender_type_set(ntype.ext.srna, &ntype);
+
node_type_socket_templates(&ntype, NULL, NULL);
node_type_size(&ntype, 120, 60, 200);
node_type_label(&ntype, node_group_label);
- node_type_init(&ntype, node_group_init);
- node_type_valid(&ntype, node_group_valid);
- node_type_template(&ntype, node_group_template);
node_type_update(&ntype, NULL, node_group_verify);
- node_type_group_edit(&ntype, node_group_edit_get, node_group_edit_set, node_group_edit_clear);
- node_type_exec_new(&ntype, group_initexec, group_freeexec, group_execute);
+ strcpy(ntype.group_tree_idname, "TextureNodeTree");
+ node_type_exec(&ntype, group_initexec, group_freeexec, group_execute);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/texture/nodes/node_texture_compose.c b/source/blender/nodes/texture/nodes/node_texture_compose.c
index 43a8ba1babf..ddaae829da9 100644
--- a/source/blender/nodes/texture/nodes/node_texture_compose.c
+++ b/source/blender/nodes/texture/nodes/node_texture_compose.c
@@ -52,19 +52,19 @@ static void colorfn(float *out, TexParams *p, bNode *UNUSED(node), bNodeStack **
out[i] = tex_input_value(in[i], p, thread);
}
-static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+static void exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out)
{
- tex_output(node, in, out[0], &colorfn, data);
+ tex_output(node, execdata, in, out[0], &colorfn, data);
}
-void register_node_type_tex_compose(bNodeTreeType *ttype)
+void register_node_type_tex_compose()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, TEX_NODE_COMPOSE, "Combine RGBA", NODE_CLASS_OP_COLOR, 0);
+ tex_node_type_base(&ntype, TEX_NODE_COMPOSE, "Combine RGBA", NODE_CLASS_OP_COLOR, 0);
node_type_socket_templates(&ntype, inputs, outputs);
node_type_size(&ntype, 100, 60, 150);
- node_type_exec(&ntype, exec);
+ node_type_exec(&ntype, NULL, NULL, exec);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/texture/nodes/node_texture_coord.c b/source/blender/nodes/texture/nodes/node_texture_coord.c
index 971520ebc38..94793288ec3 100644
--- a/source/blender/nodes/texture/nodes/node_texture_coord.c
+++ b/source/blender/nodes/texture/nodes/node_texture_coord.c
@@ -43,20 +43,20 @@ static void vectorfn(float *out, TexParams *p, bNode *UNUSED(node), bNodeStack *
copy_v3_v3(out, p->co);
}
-static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+static void exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out)
{
- tex_output(node, in, out[0], &vectorfn, data);
+ tex_output(node, execdata, in, out[0], &vectorfn, data);
}
-void register_node_type_tex_coord(bNodeTreeType *ttype)
+void register_node_type_tex_coord()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, TEX_NODE_COORD, "Coordinates", NODE_CLASS_INPUT, NODE_OPTIONS);
+ tex_node_type_base(&ntype, TEX_NODE_COORD, "Coordinates", NODE_CLASS_INPUT, NODE_OPTIONS);
node_type_socket_templates(&ntype, NULL, outputs);
node_type_size(&ntype, 120, 110, 160);
node_type_storage(&ntype, "node_coord", NULL, NULL);
- node_type_exec(&ntype, exec);
+ node_type_exec(&ntype, NULL, NULL, exec);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/texture/nodes/node_texture_curves.c b/source/blender/nodes/texture/nodes/node_texture_curves.c
index 5980f938938..94235eae93c 100644
--- a/source/blender/nodes/texture/nodes/node_texture_curves.c
+++ b/source/blender/nodes/texture/nodes/node_texture_curves.c
@@ -54,32 +54,31 @@ static void time_colorfn(float *out, TexParams *p, bNode *node, bNodeStack **UNU
out[0] = CLAMPIS(fac, 0.0f, 1.0f);
}
-static void time_exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+static void time_exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out)
{
- tex_output(node, in, out[0], &time_colorfn, data);
+ tex_output(node, execdata, in, out[0], &time_colorfn, data);
}
-static void time_init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void time_init(bNodeTree *UNUSED(ntree), bNode *node)
{
node->custom1= 1;
node->custom2= 250;
node->storage= curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
}
-void register_node_type_tex_curve_time(bNodeTreeType *ttype)
+void register_node_type_tex_curve_time()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, TEX_NODE_CURVE_TIME, "Time", NODE_CLASS_INPUT, NODE_OPTIONS);
+ tex_node_type_base(&ntype, TEX_NODE_CURVE_TIME, "Time", NODE_CLASS_INPUT, NODE_OPTIONS);
node_type_socket_templates(&ntype, NULL, time_outputs);
node_type_size(&ntype, 140, 100, 320);
node_type_init(&ntype, time_init);
node_type_storage(&ntype, "CurveMapping", node_free_curves, node_copy_curves);
- node_type_exec(&ntype, time_exec);
- node_type_exec_new(&ntype, node_initexec_curves, NULL, NULL); /* only for its initexec func */
+ node_type_exec(&ntype, node_initexec_curves, NULL, time_exec);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
/* **************** CURVE RGB ******************** */
@@ -102,27 +101,26 @@ static void rgb_colorfn(float *out, TexParams *p, bNode *node, bNodeStack **in,
out[3] = cin[3];
}
-static void rgb_exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+static void rgb_exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out)
{
- tex_output(node, in, out[0], &rgb_colorfn, data);
+ tex_output(node, execdata, in, out[0], &rgb_colorfn, data);
}
-static void rgb_init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void rgb_init(bNodeTree *UNUSED(ntree), bNode *node)
{
node->storage= curvemapping_add(4, 0.0f, 0.0f, 1.0f, 1.0f);
}
-void register_node_type_tex_curve_rgb(bNodeTreeType *ttype)
+void register_node_type_tex_curve_rgb()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, TEX_NODE_CURVE_RGB, "RGB Curves", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
+ tex_node_type_base(&ntype, TEX_NODE_CURVE_RGB, "RGB Curves", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, rgb_inputs, rgb_outputs);
node_type_size(&ntype, 200, 140, 320);
node_type_init(&ntype, rgb_init);
node_type_storage(&ntype, "CurveMapping", node_free_curves, node_copy_curves);
- node_type_exec(&ntype, rgb_exec);
- node_type_exec_new(&ntype, node_initexec_curves, NULL, NULL); /* only for its initexec func */
+ node_type_exec(&ntype, node_initexec_curves, NULL, rgb_exec);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/texture/nodes/node_texture_decompose.c b/source/blender/nodes/texture/nodes/node_texture_decompose.c
index 0866428ca6c..fa2c1d6398f 100644
--- a/source/blender/nodes/texture/nodes/node_texture_decompose.c
+++ b/source/blender/nodes/texture/nodes/node_texture_decompose.c
@@ -70,22 +70,22 @@ static void valuefn_a(float *out, TexParams *p, bNode *UNUSED(node), bNodeStack
*out = out[3];
}
-static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+static void exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out)
{
- tex_output(node, in, out[0], &valuefn_r, data);
- tex_output(node, in, out[1], &valuefn_g, data);
- tex_output(node, in, out[2], &valuefn_b, data);
- tex_output(node, in, out[3], &valuefn_a, data);
+ tex_output(node, execdata, in, out[0], &valuefn_r, data);
+ tex_output(node, execdata, in, out[1], &valuefn_g, data);
+ tex_output(node, execdata, in, out[2], &valuefn_b, data);
+ tex_output(node, execdata, in, out[3], &valuefn_a, data);
}
-void register_node_type_tex_decompose(bNodeTreeType *ttype)
+void register_node_type_tex_decompose()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, TEX_NODE_DECOMPOSE, "Separate RGBA", NODE_CLASS_OP_COLOR, 0);
+ tex_node_type_base(&ntype, TEX_NODE_DECOMPOSE, "Separate RGBA", NODE_CLASS_OP_COLOR, 0);
node_type_socket_templates(&ntype, inputs, outputs);
node_type_size(&ntype, 100, 60, 150);
- node_type_exec(&ntype, exec);
+ node_type_exec(&ntype, NULL, NULL, exec);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/texture/nodes/node_texture_distance.c b/source/blender/nodes/texture/nodes/node_texture_distance.c
index 8c3b1555d5d..fefa093481d 100644
--- a/source/blender/nodes/texture/nodes/node_texture_distance.c
+++ b/source/blender/nodes/texture/nodes/node_texture_distance.c
@@ -56,20 +56,20 @@ static void valuefn(float *out, TexParams *p, bNode *UNUSED(node), bNodeStack **
*out = len_v3v3(co2, co1);
}
-static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+static void exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out)
{
- tex_output(node, in, out[0], &valuefn, data);
+ tex_output(node, execdata, in, out[0], &valuefn, data);
}
-void register_node_type_tex_distance(bNodeTreeType *ttype)
+void register_node_type_tex_distance()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, TEX_NODE_DISTANCE, "Distance", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
+ tex_node_type_base(&ntype, TEX_NODE_DISTANCE, "Distance", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, inputs, outputs);
node_type_size(&ntype, 120, 110, 160);
node_type_storage(&ntype, "node_distance", NULL, NULL);
- node_type_exec(&ntype, exec);
+ node_type_exec(&ntype, NULL, NULL, exec);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/texture/nodes/node_texture_hueSatVal.c b/source/blender/nodes/texture/nodes/node_texture_hueSatVal.c
index b5e9969a830..c5acf01801c 100644
--- a/source/blender/nodes/texture/nodes/node_texture_hueSatVal.c
+++ b/source/blender/nodes/texture/nodes/node_texture_hueSatVal.c
@@ -87,19 +87,19 @@ static void colorfn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
out[3] = col[3];
}
-static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+static void exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out)
{
- tex_output(node, in, out[0], &colorfn, data);
+ tex_output(node, execdata, in, out[0], &colorfn, data);
}
-void register_node_type_tex_hue_sat(bNodeTreeType *ttype)
+void register_node_type_tex_hue_sat()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, TEX_NODE_HUE_SAT, "Hue Saturation Value", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
+ tex_node_type_base(&ntype, TEX_NODE_HUE_SAT, "Hue Saturation Value", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, inputs, outputs);
node_type_size(&ntype, 150, 80, 250);
- node_type_exec(&ntype, exec);
+ node_type_exec(&ntype, NULL, NULL, exec);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/texture/nodes/node_texture_image.c b/source/blender/nodes/texture/nodes/node_texture_image.c
index 2ef1669a266..e897b0e4e96 100644
--- a/source/blender/nodes/texture/nodes/node_texture_image.c
+++ b/source/blender/nodes/texture/nodes/node_texture_image.c
@@ -83,12 +83,12 @@ static void colorfn(float *out, TexParams *p, bNode *node, bNodeStack **UNUSED(i
}
}
-static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+static void exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out)
{
- tex_output(node, in, out[0], &colorfn, data);
+ tex_output(node, execdata, in, out[0], &colorfn, data);
}
-static void init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void init(bNodeTree *UNUSED(ntree), bNode *node)
{
ImageUser *iuser= MEM_callocN(sizeof(ImageUser), "node image user");
node->storage= iuser;
@@ -97,16 +97,16 @@ static void init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(nt
iuser->ok= 1;
}
-void register_node_type_tex_image(bNodeTreeType *ttype)
+void register_node_type_tex_image()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, TEX_NODE_IMAGE, "Image", NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS);
+ tex_node_type_base(&ntype, TEX_NODE_IMAGE, "Image", NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS);
node_type_socket_templates(&ntype, NULL, outputs);
node_type_size(&ntype, 120, 80, 300);
node_type_init(&ntype, init);
node_type_storage(&ntype, "ImageUser", node_free_standard_storage, node_copy_standard_storage);
- node_type_exec(&ntype, exec);
+ node_type_exec(&ntype, NULL, NULL, exec);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/texture/nodes/node_texture_invert.c b/source/blender/nodes/texture/nodes/node_texture_invert.c
index 9c2963d2dc2..aa394bff8bc 100644
--- a/source/blender/nodes/texture/nodes/node_texture_invert.c
+++ b/source/blender/nodes/texture/nodes/node_texture_invert.c
@@ -58,19 +58,19 @@ static void colorfn(float *out, TexParams *p, bNode *UNUSED(node), bNodeStack **
out[3] = col[3];
}
-static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+static void exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out)
{
- tex_output(node, in, out[0], &colorfn, data);
+ tex_output(node, execdata, in, out[0], &colorfn, data);
}
-void register_node_type_tex_invert(bNodeTreeType *ttype)
+void register_node_type_tex_invert()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, TEX_NODE_INVERT, "Invert", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
+ tex_node_type_base(&ntype, TEX_NODE_INVERT, "Invert", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, inputs, outputs);
node_type_size(&ntype, 90, 80, 100);
- node_type_exec(&ntype, exec);
+ node_type_exec(&ntype, NULL, NULL, exec);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/texture/nodes/node_texture_math.c b/source/blender/nodes/texture/nodes/node_texture_math.c
index 95d70ccc7d6..e83579070a9 100644
--- a/source/blender/nodes/texture/nodes/node_texture_math.c
+++ b/source/blender/nodes/texture/nodes/node_texture_math.c
@@ -181,21 +181,21 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
}
}
-static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+static void exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out)
{
- tex_output(node, in, out[0], &valuefn, data);
+ tex_output(node, execdata, in, out[0], &valuefn, data);
}
-void register_node_type_tex_math(bNodeTreeType *ttype)
+void register_node_type_tex_math()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, TEX_NODE_MATH, "Math", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
+ tex_node_type_base(&ntype, TEX_NODE_MATH, "Math", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, inputs, outputs);
node_type_size(&ntype, 120, 110, 160);
node_type_label(&ntype, node_math_label);
node_type_storage(&ntype, "node_math", NULL, NULL);
- node_type_exec(&ntype, exec);
+ node_type_exec(&ntype, NULL, NULL, exec);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/texture/nodes/node_texture_mixRgb.c b/source/blender/nodes/texture/nodes/node_texture_mixRgb.c
index fe04854c734..7a68af4b1e2 100644
--- a/source/blender/nodes/texture/nodes/node_texture_mixRgb.c
+++ b/source/blender/nodes/texture/nodes/node_texture_mixRgb.c
@@ -59,20 +59,20 @@ static void colorfn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
ramp_blend(node->custom1, out, fac, col2);
}
-static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+static void exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out)
{
- tex_output(node, in, out[0], &colorfn, data);
+ tex_output(node, execdata, in, out[0], &colorfn, data);
}
-void register_node_type_tex_mix_rgb(bNodeTreeType *ttype)
+void register_node_type_tex_mix_rgb()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, TEX_NODE_MIX_RGB, "Mix", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
+ tex_node_type_base(&ntype, TEX_NODE_MIX_RGB, "Mix", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, inputs, outputs);
node_type_size(&ntype, 100, 60, 150);
node_type_label(&ntype, node_blend_label);
- node_type_exec(&ntype, exec);
+ node_type_exec(&ntype, NULL, NULL, exec);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/texture/nodes/node_texture_output.c b/source/blender/nodes/texture/nodes/node_texture_output.c
index 2f5efe8c45e..8c8f7622d29 100644
--- a/source/blender/nodes/texture/nodes/node_texture_output.c
+++ b/source/blender/nodes/texture/nodes/node_texture_output.c
@@ -41,7 +41,7 @@ static bNodeSocketTemplate inputs[] = {
};
/* applies to render pipeline */
-static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **UNUSED(out))
+static void exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **UNUSED(out))
{
TexCallData *cdata = (TexCallData *)data;
TexResult *target = cdata->target;
@@ -54,7 +54,7 @@ static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **UNUSED(o
tex_input_rgba(&target->tr, in[1], &params, cdata->thread);
else
tex_input_rgba(&target->tr, in[0], &params, cdata->thread);
- tex_do_preview(node, params.co, &target->tr);
+ tex_do_preview(execdata->preview, params.co, &target->tr);
}
else {
/* 0 means don't care, so just use first */
@@ -141,7 +141,7 @@ static void assign_index(struct bNode *node)
node->custom1 = index;
}
-static void init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void init(bNodeTree *UNUSED(ntree), bNode *node)
{
TexNodeOutput *tno = MEM_callocN(sizeof(TexNodeOutput), "TEX_output");
node->storage= tno;
@@ -151,26 +151,26 @@ static void init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(nt
assign_index(node);
}
-static void copy(bNode *orig, bNode *new)
+static void copy(bNodeTree *dest_ntree, bNode *dest_node, bNode *src_node)
{
- node_copy_standard_storage(orig, new);
- unique_name(new);
- assign_index(new);
+ node_copy_standard_storage(dest_ntree, dest_node, src_node);
+ unique_name(dest_node);
+ assign_index(dest_node);
}
-void register_node_type_tex_output(bNodeTreeType *ttype)
+void register_node_type_tex_output()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, TEX_NODE_OUTPUT, "Output", NODE_CLASS_OUTPUT, NODE_PREVIEW|NODE_OPTIONS);
+ tex_node_type_base(&ntype, TEX_NODE_OUTPUT, "Output", NODE_CLASS_OUTPUT, NODE_PREVIEW|NODE_OPTIONS);
node_type_socket_templates(&ntype, inputs, NULL);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, init);
node_type_storage(&ntype, "TexNodeOutput", node_free_standard_storage, copy);
- node_type_exec(&ntype, exec);
+ node_type_exec(&ntype, NULL, NULL, exec);
/* Do not allow muting output. */
node_type_internal_links(&ntype, NULL);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/texture/nodes/node_texture_proc.c b/source/blender/nodes/texture/nodes/node_texture_proc.c
index de2dac22d81..504e77ebb27 100644
--- a/source/blender/nodes/texture/nodes/node_texture_proc.c
+++ b/source/blender/nodes/texture/nodes/node_texture_proc.c
@@ -129,11 +129,11 @@ static int count_outputs(bNode *node)
{ \
texfn(result, p, node, in, 1, &name##_map_inputs, thread); \
} \
- static void name##_exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) \
+ static void name##_exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out) \
{ \
int outs = count_outputs(node); \
- if (outs >= 1) tex_output(node, in, out[0], &name##_colorfn, data); \
- if (outs >= 2) tex_output(node, in, out[1], &name##_normalfn, data); \
+ if (outs >= 1) tex_output(node, execdata, in, out[0], &name##_colorfn, data); \
+ if (outs >= 2) tex_output(node, execdata, in, out[1], &name##_normalfn, data); \
}
@@ -281,7 +281,7 @@ ProcDef(stucci)
/* --- */
-static void init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void init(bNodeTree *UNUSED(ntree), bNode *node)
{
Tex *tex = MEM_callocN(sizeof(Tex), "Tex");
node->storage= tex;
@@ -296,18 +296,18 @@ static void init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(nt
/* Node type definitions */
#define TexDef(TEXTYPE, outputs, name, Name) \
-void register_node_type_tex_proc_##name(bNodeTreeType *ttype) \
+void register_node_type_tex_proc_##name() \
{ \
static bNodeType ntype; \
\
- node_type_base(ttype, &ntype, TEX_NODE_PROC+TEXTYPE, Name, NODE_CLASS_TEXTURE, NODE_PREVIEW|NODE_OPTIONS); \
+ tex_node_type_base(&ntype, TEX_NODE_PROC+TEXTYPE, Name, NODE_CLASS_TEXTURE, NODE_PREVIEW|NODE_OPTIONS); \
node_type_socket_templates(&ntype, name##_inputs, outputs); \
node_type_size(&ntype, 140, 80, 140); \
node_type_init(&ntype, init); \
node_type_storage(&ntype, "Tex", node_free_standard_storage, node_copy_standard_storage); \
- node_type_exec(&ntype, name##_exec); \
+ node_type_exec(&ntype, NULL, NULL, name##_exec); \
\
- nodeRegisterType(ttype, &ntype); \
+ nodeRegisterType(&ntype); \
}
#define C outputs_color_only
diff --git a/source/blender/nodes/texture/nodes/node_texture_rotate.c b/source/blender/nodes/texture/nodes/node_texture_rotate.c
index 1b1d57044a3..8f3f66dbee4 100644
--- a/source/blender/nodes/texture/nodes/node_texture_rotate.c
+++ b/source/blender/nodes/texture/nodes/node_texture_rotate.c
@@ -90,19 +90,19 @@ static void colorfn(float *out, TexParams *p, bNode *UNUSED(node), bNodeStack **
tex_input_rgba(out, in[0], &np, thread);
}
}
-static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+static void exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out)
{
- tex_output(node, in, out[0], &colorfn, data);
+ tex_output(node, execdata, in, out[0], &colorfn, data);
}
-void register_node_type_tex_rotate(bNodeTreeType *ttype)
+void register_node_type_tex_rotate()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, TEX_NODE_ROTATE, "Rotate", NODE_CLASS_DISTORT, NODE_OPTIONS);
+ tex_node_type_base(&ntype, TEX_NODE_ROTATE, "Rotate", NODE_CLASS_DISTORT, NODE_OPTIONS);
node_type_socket_templates(&ntype, inputs, outputs);
node_type_size(&ntype, 140, 100, 320);
- node_type_exec(&ntype, exec);
+ node_type_exec(&ntype, NULL, NULL, exec);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/texture/nodes/node_texture_scale.c b/source/blender/nodes/texture/nodes/node_texture_scale.c
index 56562724fb9..67e0c064b7c 100644
--- a/source/blender/nodes/texture/nodes/node_texture_scale.c
+++ b/source/blender/nodes/texture/nodes/node_texture_scale.c
@@ -63,19 +63,19 @@ static void colorfn(float *out, TexParams *p, bNode *UNUSED(node), bNodeStack **
tex_input_rgba(out, in[0], &np, thread);
}
-static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+static void exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out)
{
- tex_output(node, in, out[0], &colorfn, data);
+ tex_output(node, execdata, in, out[0], &colorfn, data);
}
-void register_node_type_tex_scale(bNodeTreeType *ttype)
+void register_node_type_tex_scale()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, TEX_NODE_SCALE, "Scale", NODE_CLASS_DISTORT, NODE_OPTIONS);
+ tex_node_type_base(&ntype, TEX_NODE_SCALE, "Scale", NODE_CLASS_DISTORT, NODE_OPTIONS);
node_type_socket_templates(&ntype, inputs, outputs);
node_type_size(&ntype, 90, 80, 100);
- node_type_exec(&ntype, exec);
+ node_type_exec(&ntype, NULL, NULL, exec);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/texture/nodes/node_texture_texture.c b/source/blender/nodes/texture/nodes/node_texture_texture.c
index f839f485976..9970c3c2a26 100644
--- a/source/blender/nodes/texture/nodes/node_texture_texture.c
+++ b/source/blender/nodes/texture/nodes/node_texture_texture.c
@@ -90,19 +90,19 @@ static void colorfn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
}
}
-static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+static void exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out)
{
- tex_output(node, in, out[0], &colorfn, data);
+ tex_output(node, execdata, in, out[0], &colorfn, data);
}
-void register_node_type_tex_texture(bNodeTreeType *ttype)
+void register_node_type_tex_texture()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, TEX_NODE_TEXTURE, "Texture", NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS);
+ tex_node_type_base(&ntype, TEX_NODE_TEXTURE, "Texture", NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS);
node_type_socket_templates(&ntype, inputs, outputs);
node_type_size(&ntype, 120, 80, 240);
- node_type_exec(&ntype, exec);
+ node_type_exec(&ntype, NULL, NULL, exec);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/texture/nodes/node_texture_translate.c b/source/blender/nodes/texture/nodes/node_texture_translate.c
index a95cb00a47d..3d5db4f863a 100644
--- a/source/blender/nodes/texture/nodes/node_texture_translate.c
+++ b/source/blender/nodes/texture/nodes/node_texture_translate.c
@@ -59,19 +59,19 @@ static void colorfn(float *out, TexParams *p, bNode *UNUSED(node), bNodeStack **
tex_input_rgba(out, in[0], &np, thread);
}
-static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+static void exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out)
{
- tex_output(node, in, out[0], &colorfn, data);
+ tex_output(node, execdata, in, out[0], &colorfn, data);
}
-void register_node_type_tex_translate(bNodeTreeType *ttype)
+void register_node_type_tex_translate()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, TEX_NODE_TRANSLATE, "Translate", NODE_CLASS_DISTORT, NODE_OPTIONS);
+ tex_node_type_base(&ntype, TEX_NODE_TRANSLATE, "Translate", NODE_CLASS_DISTORT, NODE_OPTIONS);
node_type_socket_templates(&ntype, inputs, outputs);
node_type_size(&ntype, 90, 80, 100);
- node_type_exec(&ntype, exec);
+ node_type_exec(&ntype, NULL, NULL, exec);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/texture/nodes/node_texture_valToNor.c b/source/blender/nodes/texture/nodes/node_texture_valToNor.c
index bbfc1fa616b..d7495f9833d 100644
--- a/source/blender/nodes/texture/nodes/node_texture_valToNor.c
+++ b/source/blender/nodes/texture/nodes/node_texture_valToNor.c
@@ -75,19 +75,19 @@ static void normalfn(float *out, TexParams *p, bNode *UNUSED(node), bNodeStack *
out[1] = val-nor[1];
out[2] = val-nor[2];
}
-static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+static void exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out)
{
- tex_output(node, in, out[0], &normalfn, data);
+ tex_output(node, execdata, in, out[0], &normalfn, data);
}
-void register_node_type_tex_valtonor(bNodeTreeType *ttype)
+void register_node_type_tex_valtonor()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, TEX_NODE_VALTONOR, "Value to Normal", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
+ tex_node_type_base(&ntype, TEX_NODE_VALTONOR, "Value to Normal", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, inputs, outputs);
node_type_size(&ntype, 90, 80, 100);
- node_type_exec(&ntype, exec);
+ node_type_exec(&ntype, NULL, NULL, exec);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/texture/nodes/node_texture_valToRgb.c b/source/blender/nodes/texture/nodes/node_texture_valToRgb.c
index 78635453fc1..fec89aa03eb 100644
--- a/source/blender/nodes/texture/nodes/node_texture_valToRgb.c
+++ b/source/blender/nodes/texture/nodes/node_texture_valToRgb.c
@@ -52,28 +52,28 @@ static void valtorgb_colorfn(float *out, TexParams *p, bNode *node, bNodeStack *
}
}
-static void valtorgb_exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+static void valtorgb_exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out)
{
- tex_output(node, in, out[0], &valtorgb_colorfn, data);
+ tex_output(node, execdata, in, out[0], &valtorgb_colorfn, data);
}
-static void valtorgb_init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void valtorgb_init(bNodeTree *UNUSED(ntree), bNode *node)
{
node->storage = add_colorband(1);
}
-void register_node_type_tex_valtorgb(bNodeTreeType *ttype)
+void register_node_type_tex_valtorgb()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, TEX_NODE_VALTORGB, "ColorRamp", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
+ tex_node_type_base(&ntype, TEX_NODE_VALTORGB, "ColorRamp", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, valtorgb_in, valtorgb_out);
node_type_size(&ntype, 240, 200, 300);
node_type_init(&ntype, valtorgb_init);
node_type_storage(&ntype, "ColorBand", node_free_standard_storage, node_copy_standard_storage);
- node_type_exec(&ntype, valtorgb_exec);
+ node_type_exec(&ntype, NULL, NULL, valtorgb_exec);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
/* **************** RGBTOBW ******************** */
@@ -94,19 +94,19 @@ static void rgbtobw_valuefn(float *out, TexParams *p, bNode *UNUSED(node), bNode
*out = rgb_to_bw(cin);
}
-static void rgbtobw_exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+static void rgbtobw_exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out)
{
- tex_output(node, in, out[0], &rgbtobw_valuefn, data);
+ tex_output(node, execdata, in, out[0], &rgbtobw_valuefn, data);
}
-void register_node_type_tex_rgbtobw(bNodeTreeType *ttype)
+void register_node_type_tex_rgbtobw()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, TEX_NODE_RGBTOBW, "RGB to BW", NODE_CLASS_CONVERTOR, 0);
+ tex_node_type_base(&ntype, TEX_NODE_RGBTOBW, "RGB to BW", NODE_CLASS_CONVERTOR, 0);
node_type_socket_templates(&ntype, rgbtobw_in, rgbtobw_out);
node_type_size(&ntype, 80, 40, 120);
- node_type_exec(&ntype, rgbtobw_exec);
+ node_type_exec(&ntype, NULL, NULL, rgbtobw_exec);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/texture/nodes/node_texture_viewer.c b/source/blender/nodes/texture/nodes/node_texture_viewer.c
index 5cb8d8c438c..44724c9280f 100644
--- a/source/blender/nodes/texture/nodes/node_texture_viewer.c
+++ b/source/blender/nodes/texture/nodes/node_texture_viewer.c
@@ -42,7 +42,7 @@ static bNodeSocketTemplate outputs[] = {
{ -1, 0, "" }
};
-static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **UNUSED(out))
+static void exec(void *data, int UNUSED(thread), bNode *UNUSED(node), bNodeExecData *execdata, bNodeStack **in, bNodeStack **UNUSED(out))
{
TexCallData *cdata = (TexCallData *)data;
@@ -52,21 +52,21 @@ static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **UNUSED(o
params_from_cdata(&params, cdata);
tex_input_rgba(col, in[0], &params, cdata->thread);
- tex_do_preview(node, params.previewco, col);
+ tex_do_preview(execdata->preview, params.previewco, col);
}
}
-void register_node_type_tex_viewer(bNodeTreeType *ttype)
+void register_node_type_tex_viewer()
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, TEX_NODE_VIEWER, "Viewer", NODE_CLASS_OUTPUT, NODE_PREVIEW);
+ tex_node_type_base(&ntype, TEX_NODE_VIEWER, "Viewer", NODE_CLASS_OUTPUT, NODE_PREVIEW);
node_type_socket_templates(&ntype, inputs, outputs);
node_type_size(&ntype, 100, 60, 150);
- node_type_exec(&ntype, exec);
+ node_type_exec(&ntype, NULL, NULL, exec);
/* Do not allow muting viewer node. */
node_type_internal_links(&ntype, NULL);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c
index 8fe75032a46..ebd38e672da 100644
--- a/source/blender/python/intern/bpy_rna.c
+++ b/source/blender/python/intern/bpy_rna.c
@@ -3119,6 +3119,33 @@ static PyObject *pyrna_struct_is_property_set(BPy_StructRNA *self, PyObject *arg
return PyBool_FromLong(RNA_property_is_set(&self->ptr, prop));
}
+PyDoc_STRVAR(pyrna_struct_property_unset_doc,
+".. method:: property_unset(property)\n"
+"\n"
+" Unset a property, will use default value afterward.\n"
+);
+static PyObject *pyrna_struct_property_unset(BPy_StructRNA *self, PyObject *args)
+{
+ PropertyRNA *prop;
+ const char *name;
+
+ PYRNA_STRUCT_CHECK_OBJ(self);
+
+ if (!PyArg_ParseTuple(args, "s:property_unset", &name))
+ return NULL;
+
+ if ((prop = RNA_struct_find_property(&self->ptr, name)) == NULL) {
+ PyErr_Format(PyExc_TypeError,
+ "%.200s.property_unset(\"%.200s\") not found",
+ RNA_struct_identifier(self->ptr.type), name);
+ return NULL;
+ }
+
+ RNA_property_unset(&self->ptr, prop);
+
+ Py_RETURN_NONE;
+}
+
PyDoc_STRVAR(pyrna_struct_is_property_hidden_doc,
".. method:: is_property_hidden(property)\n"
"\n"
@@ -4633,6 +4660,7 @@ static struct PyMethodDef pyrna_struct_methods[] = {
{"driver_remove", (PyCFunction)pyrna_struct_driver_remove, METH_VARARGS, pyrna_struct_driver_remove_doc},
{"is_property_set", (PyCFunction)pyrna_struct_is_property_set, METH_VARARGS, pyrna_struct_is_property_set_doc},
+ {"property_unset", (PyCFunction)pyrna_struct_property_unset, METH_VARARGS, pyrna_struct_property_unset_doc},
{"is_property_hidden", (PyCFunction)pyrna_struct_is_property_hidden, METH_VARARGS, pyrna_struct_is_property_hidden_doc},
{"path_resolve", (PyCFunction)pyrna_struct_path_resolve, METH_VARARGS, pyrna_struct_path_resolve_doc},
{"path_from_id", (PyCFunction)pyrna_struct_path_from_id, METH_VARARGS, pyrna_struct_path_from_id_doc},
diff --git a/source/blender/render/intern/source/render_texture.c b/source/blender/render/intern/source/render_texture.c
index 15ca865643b..96eaa656c36 100644
--- a/source/blender/render/intern/source/render_texture.c
+++ b/source/blender/render/intern/source/render_texture.c
@@ -121,7 +121,7 @@ static void init_render_texture(Render *re, Tex *tex)
}
if (tex->nodetree && tex->use_nodes) {
- ntreeTexBeginExecTree(tex->nodetree, 1); /* has internal flag to detect it only does it once */
+ ntreeTexBeginExecTree(tex->nodetree); /* has internal flag to detect it only does it once */
}
}
@@ -141,7 +141,7 @@ void init_render_textures(Render *re)
static void end_render_texture(Tex *tex)
{
if (tex && tex->use_nodes && tex->nodetree && tex->nodetree->execdata)
- ntreeTexEndExecTree(tex->nodetree->execdata, 1);
+ ntreeTexEndExecTree(tex->nodetree->execdata);
}
void end_render_textures(Render *re)
diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c
index 28193b71bbd..f31983dcd62 100644
--- a/source/blenderplayer/bad_level_call_stubs/stubs.c
+++ b/source/blenderplayer/bad_level_call_stubs/stubs.c
@@ -106,8 +106,11 @@ struct bConstraintOb;
struct bConstraintTarget;
struct bContextDataResult;
struct bNode;
+struct bNodeType;
struct bNodeSocket;
+struct bNodeSocketType;
struct bNodeTree;
+struct bNodeTreeType;
struct bPoseChannel;
struct bPythonConstraint;
struct bTheme;
@@ -225,7 +228,7 @@ void ED_armature_edit_bone_remove(struct bArmature *arm, struct EditBone *exBone
void object_test_constraints(struct Object *owner) {}
void ED_object_parent(struct Object *ob, struct Object *par, int type, const char *substr) {}
void ED_object_constraint_set_active(struct Object *ob, struct bConstraint *con) {}
-void ED_node_composit_default(struct Scene *sce) {}
+void ED_node_composit_default(struct bContext *C, struct Scene *scene) {}
void *ED_region_draw_cb_activate(struct ARegionType *art, void(*draw)(const struct bContext *, struct ARegion *, void *), void *custumdata, int type) {return 0;} /* XXX this one looks weird */
void *ED_region_draw_cb_customdata(void *handle) {return 0;} /* XXX This one looks wrong also */
void ED_region_draw_cb_exit(struct ARegionType *art, void *handle) {}
@@ -302,10 +305,21 @@ void ED_area_newspace(struct bContext *C, struct ScrArea *sa, int type) {}
void ED_region_tag_redraw(struct ARegion *ar) {}
void WM_event_add_fileselect(struct bContext *C, struct wmOperator *op) {}
void WM_cursor_wait(int val) {}
-void ED_node_texture_default(struct Tex *tx) {}
-void ED_node_changed_update(struct bContext *C, struct bNode *node) {}
-void ED_node_generic_update(struct Main *bmain, struct bNodeTree *ntree, struct bNode *node) {}
-void ED_node_tree_update(struct SpaceNode *snode, struct Scene *scene) {}
+void ED_node_texture_default(struct bContext *C, struct Tex *tx) {}
+void ED_node_tag_update_id(struct ID *id) {}
+void ED_node_tag_update_nodetree(struct Main *bmain, struct bNodeTree *ntree) {}
+void ED_node_tree_update(const struct bContext *C) {}
+void ED_node_set_tree_type(struct SpaceNode *snode, struct bNodeTreeType *typeinfo){}
+void ED_init_custom_node_type(struct bNodeType *ntype){}
+void ED_init_custom_node_socket_type(struct bNodeSocketType *stype){}
+void ED_init_standard_node_socket_type(struct bNodeSocketType *) {}
+void ED_init_node_socket_type_virtual(struct bNodeSocketType *) {}
+int ED_node_tree_path_length(struct SpaceNode *snode){return 0;}
+void ED_node_tree_path_get(struct SpaceNode *snode, char *value){}
+void ED_node_tree_path_get_fixedbuf(struct SpaceNode *snode, char *value, int max_length){}
+void ED_node_tree_start(struct SpaceNode *snode, struct bNodeTree *ntree, struct ID *id, struct ID *from){}
+void ED_node_tree_push(struct SpaceNode *snode, struct bNodeTree *ntree, struct bNode *gnode){}
+void ED_node_tree_pop(struct SpaceNode *snode){}
void ED_view3d_scene_layers_update(struct Main *bmain, struct Scene *scene) {}
int ED_view3d_scene_layer_set(int lay, const int *values) {return 0;}
void ED_view3d_quadview_update(struct ScrArea *sa, struct ARegion *ar) {}
@@ -317,7 +331,7 @@ void ED_view3d_update_viewmat(struct Scene *scene, struct View3D *v3d, struct AR
float ED_view3d_grid_scale(struct Scene *scene, struct View3D *v3d, const char **grid_unit) {return 0.0f;}
void view3d_apply_mat4(float mat[4][4], float *ofs, float *quat, float *dist) {}
int text_file_modified(struct Text *text) {return 0;}
-void ED_node_shader_default(struct Material *ma) {}
+void ED_node_shader_default(struct bContext *C, struct ID *id) {}
void ED_screen_animation_timer_update(struct bContext *C, int redraws) {}
void ED_screen_animation_playing(struct wmWindowManager *wm) {}
void ED_base_object_select(struct Base *base, short mode) {}
@@ -456,6 +470,7 @@ void uiTemplateMarker(struct uiLayout *layout, struct PointerRNA *ptr, const cha
void uiTemplateImageSettings(struct uiLayout *layout, struct PointerRNA *imfptr) {}
void uiTemplateColorspaceSettings(struct uiLayout *layout, struct PointerRNA *ptr, const char *propname) {}
void uiTemplateColormanagedViewSettings(struct uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, const char *propname, int show_global_settings) {}
+void uiTemplateComponentMenu(struct uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *name){}
/* rna render */
struct RenderResult *RE_engine_begin_result(struct RenderEngine *engine, int x, int y, int w, int h) {return (struct RenderResult *) NULL;}